diff -u --recursive --new-file v2.3.99-pre3/linux/CREDITS linux/CREDITS --- v2.3.99-pre3/linux/CREDITS Mon Mar 27 08:08:20 2000 +++ linux/CREDITS Sun Apr 9 08:12:56 2000 @@ -1381,7 +1381,7 @@ S: Czech Republic N: Bas Laarhoven -E: bas@vimec.nl +E: sjml@xs4all.nl D: Loadable modules and ftape driver S: J. Obrechtstr 23 S: NL-5216 GP 's-Hertogenbosch @@ -1526,9 +1526,10 @@ D: Initial implementation of VC's, pty's and select() N: Pavel Machek -E: pavel@atrey.karlin.mff.cuni.cz -D: Softcursor for vga, hypertech cdrom support, vcsa bugfix -D: Network block device, sun4/330 port +E: pavel@ucw.cz +E: pavel@suse.cz +D: Softcursor for vga, hypertech cdrom support, vcsa bugfix, nbd +D: sun4/330 port, capabilities for elf, speedup for rm on ext2, USB S: Volkova 1131 S: 198 00 Praha 9 S: Czech Republic @@ -1569,6 +1570,15 @@ S: Santa Clara, CA 95052 S: USA +N: Petko Manolov +E: petkan@spct.net +D: USB ethernet (pegasus) driver +D: optimizing i[45]86 string routines +D: i386 task swithing hacks +S: 5, Vrah Mancho str. +S: 1324 Sofia +S: Bulgaria + N: Martin Mares E: mj@suse.cz E: mj@ucw.cz @@ -2113,6 +2123,15 @@ S: 301/222 City Walk S: Canberra ACT 2601 S: Australia + +N: Bill Ryder +E: bryder@sgi.com +D: FTDI_SIO usb/serial converter driver +W: http://reality.sgi.com/bryder_wellington/ftdi_sio +S: I/3 Walter St +S: Wellington +S: New Zealand + N: Sampo Saaristo E: sambo@cs.tut.fi diff -u --recursive --new-file v2.3.99-pre3/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.3.99-pre3/linux/Documentation/Configure.help Mon Mar 27 08:08:20 2000 +++ linux/Documentation/Configure.help Mon Apr 10 23:02:59 2000 @@ -59,7 +59,7 @@ # All this was shamelessly stolen from several different sources. Many # thanks to all the contributors. Feel free to use these help texts in # your own kernel configuration tools. The texts are copyrighted (c) -# 1995-1999 by Axel Boldt and many others and are governed by the GNU +# 1995-2000 by Axel Boldt and many others and are governed by the GNU # General Public License. Prompt for development and/or incomplete code/drivers @@ -112,18 +112,23 @@ Y to "Enhanced Real Time Clock Support", below. The "Advanced Power Management" code will be disabled if you say Y here. - See also: Documentation/SMP.txt, Documentation/smp.tex, - Documentation/smp.txt, and Documentation/IO-APIC.txt. Also see the + See also the files Documentation/smp.tex, Documentation/smp.txt, + Documentation/IO-APIC.txt, Documentation/nmi_watchdog.txt and the SMP-FAQ on the WWW at http://www.irisa.fr/prive/mentre/smp-faq/ . If you don't know what to do here, say N. APIC and IO-APIC Support on Uniprocessors CONFIG_X86_UP_IOAPIC - This option enables uniprocessor-kernels to switch into IO-APIC mode - if there is an IO-APIC in the system. Such a kernel will still boot - on IO-APIC-less systems with no slowdown at all. SMP kernels include - IO-APIC support unconditionally. + APIC (Advanced Programmable Interrupt Controller) is a scheme for + delivering hardware interrupt requests to the CPU. It is commonly + used on systems with several CPU's. If you have a single-CPU system + which uses APIC, you can say Y here to use it. If you say Y here + even though your machine doesn't have APIC, then the kernel will + still run with now slowdown at all. + + If you have system with several CPU's, you do not need to say Y + here: APIC will be used automatically. Kernel math emulation CONFIG_MATH_EMULATION @@ -140,10 +145,8 @@ command line option "no387", which comes handy if your coprocessor is broken. Try "man bootparam" or see the documentation of your boot loader (lilo or loadlin) about how to pass options to the kernel at - boot time. The lilo procedure is also explained in the SCSI-HOWTO, - available from http://www.linuxdoc.org/docs.html#howto .) This - means that it is a good idea to say Y here if you intend to use this - kernel on different machines. + boot time.) This means that it is a good idea to say Y here if you + intend to use this kernel on different machines. More information about the internals of the Linux math coprocessor emulation can be found in arch/i386/math-emu/README. @@ -187,9 +190,9 @@ If you are compiling a kernel which will never run on a machine with more than 1 Gigabyte total physical RAM, answer "off" here (default choice). This will result in the old "3GB/1GB" - virtual/physical memory split. 3BG are mapped so as each processus + virtual/physical memory split. 3GB are mapped so as each processus sees a 3GB virtual memory space. - The remaining part of the 4G virtual memory space is used by the + The remaining part of the 4GB virtual memory space is used by the kernel to 'permanently map' as much physical memory as possible. Certain types of applications perform better if there is more 'permanently mapped' kernel memory. @@ -277,7 +280,10 @@ This is useful if you want to check an ISO 9660 file system before burning the CD, or if you want to use floppy images without first - writing them to floppy. + writing them to floppy. Furthermore, some Linux distributions avoid + the need for a dedicated Linux partition by keeping their complete + root file system inside a DOS FAT file using this loop device + driver. The loop device driver can also be used to "hide" a file system in a disk partition, floppy, or regular file, either using encryption @@ -289,13 +295,13 @@ ftp://verden.pvv.org/pub/linux/kerneli/v2.1/ , and then you need to say Y to this option. - Note that alternative ways to use encrypted file systems are provided - by the cfs package, which can be gotten from + Note that alternative ways to use encrypted file systems are + provided by the cfs package, which can be gotten from ftp://ftp.replay.com/pub/crypto/disk/ , and the newer tcfs package, available at http://tcfs.dia.unisa.it/ . You do not need to say Y here if you want to use one of these. However, using cfs requires - saying Y to "NFS file system support" below while using tcfs requires - applying a kernel patch. + saying Y to "NFS file system support" below while using tcfs + requires applying a kernel patch. To use the loop device, you need the losetup utility and a recent version of the mount program, both contained in the util-linux @@ -341,35 +347,39 @@ ATA/IDE/MFM/RLL support CONFIG_IDE - If you say Y here, your kernel will be able to manage low cost mass storage - units such as ATA/(E)IDE and ATAPI units. + If you say Y here, your kernel will be able to manage low cost mass + storage units such as ATA/(E)IDE and ATAPI units. The most common + cases are IDE hard drives and ATAPI CDROM drives. - Integrated Disk Electronics (IDE aka ATA-1) is a connecting standard for - mass storage units such as hard disks. It was designed by Western Digital - and Compaq Computer in 1984. It was then named ST506. - Quite a number of disks use IDE interface. State of the art disks use SCSI - interface. + If your system is pure SCSI and doesn't use these interfaces, you + can say N here. + + Integrated Disk Electronics (IDE aka ATA-1) is a connecting standard + for mass storage units such as hard disks. It was designed by + Western Digital and Compaq Computer in 1984. It was then named + ST506. Quite a number of disks use the IDE interface. - AT Atachment (ATA) is a subset of the IDE specifications. + AT Attachment (ATA) is a subset of the IDE specifications. ST506 was also called ATA-1. - Fast-IDE is ATA-2 (also named Fast ATA), Enhanced IDE (EIDE) is ATA-3. It - provides support for larger disks (up to 8.4GB by means of the LBA standard), - more disks (4 instead of 2) and for other mass storage units such as tapes - and cdrom. - UDMA/33 (aka UltraDMA/33) is ATA-4 and provides faster (and more CPU friendly) - transfer modes than previous PIO (Programmed processor Input/Ouput) from - previous ATA/IDE standards by means of fast DMA controlers. - - ATA Packet Interface (ATAPI) is a protocol used by EIDE tape and CDROM - drives, similar in many respects to the SCSI protocol. - - SMART IDE (Self Monitoring, Analysis and Reporting Technology) was designed - in order to prevent data corruption and disk crash by detecting pre hardware - faillure conditions (heat, access time, and the like...). Disks builded since - june 1995 may follow this standard. The kernel itself don't manage this; - however there are quite a number of user programs such as smart that can - query the status of SMART parameters disk. + Fast-IDE is ATA-2 (also named Fast ATA), Enhanced IDE (EIDE) is + ATA-3. It provides support for larger disks (up to 8.4GB by means of + the LBA standard), more disks (4 instead of 2) and for other mass + storage units such as tapes and cdrom. UDMA/33 (aka UltraDMA/33) is + ATA-4 and provides faster (and more CPU friendly) transfer modes + than previous PIO (Programmed processor Input/Output) from previous + ATA/IDE standards by means of fast DMA controllers. + + ATA Packet Interface (ATAPI) is a protocol used by EIDE tape and + CDROM drives, similar in many respects to the SCSI protocol. + + SMART IDE (Self Monitoring, Analysis and Reporting Technology) was + designed in order to prevent data corruption and disk crash by + detecting pre hardware failure conditions (heat, access time, and + the like...). Disks built since June 1995 may follow this + standard. The kernel itself don't manage this; however there are + quite a number of user programs such as smart that can query the + status of SMART parameters disk. If you want to compile this driver as a module ( = code which can be inserted in and removed from the running kernel whenever you want), @@ -385,15 +395,15 @@ If you say Y here, you will use the full-featured IDE driver to control up to ten ATA/IDE interfaces, each being able to serve a "master" and a "slave" device, for a total of up to twenty ATA/IDE - disk/cdrom/tape/floppy drives. People with SCSI-only systems - can say N or M here. + disk/cdrom/tape/floppy drives. Useful information about large (>540 MB) IDE disks, multiple interfaces, what to do if ATA/IDE devices are not automatically - detected, sound card ATA/IDE ports, module support, and other topics, is - contained in Documentation/ide.txt. For detailed information about - hard drives, consult the Disk-HOWTO and the Multi-Disk-HOWTO, - available from http://www.linuxdoc.org/docs.html#howto . + detected, sound card ATA/IDE ports, module support, and other + topics, is contained in Documentation/ide.txt. For detailed + information about hard drives, consult the Disk-HOWTO and the + Multi-Disk-HOWTO, available from + http://www.linuxdoc.org/docs.html#howto . To fine-tune ATA/IDE drive/interface parameters for improved performance, look for the hdparm package at @@ -403,7 +413,7 @@ inserted in and removed from the running kernel whenever you want), say M here and read Documentation/modules.txt and Documentation/ide.txt. The module will be called ide-mod.o. Do not - compile this driver as a module if your root filesystem (the one + compile this driver as a module if your root file system (the one containing the directory /) is located on an IDE device. If you have one or more IDE drives, say Y or M here. If your system @@ -428,8 +438,6 @@ Disk-HOWTO, available from http://www.linuxdoc.org/docs.html#howto . - People with SCSI-only systems can say N here. - Use old disk-only driver on primary interface CONFIG_BLK_DEV_HD_IDE There are two drivers for MFM/RLL/IDE disks. Most people use just @@ -446,9 +454,6 @@ Normally, just say N here; you will then use the new driver for all 4 interfaces. - People with SCSI-only systems don't need this and can say N here as - well. - Include IDE/ATA-2 DISK support CONFIG_BLK_DEV_IDEDISK This will include enhanced support for MFM/RLL/IDE hard disks. If @@ -505,8 +510,8 @@ to the SCSI protocol. If you have an SCSI tape drive however, you can say N here. - This now includes the OnStream DI-30 tape drive support. - Will not work with SCSI protocol, until there is support for the + You should also say Y if you have an OnStream DI-30 tape drive; this + will not work with the SCSI protocol, until there is support for the SC-30 and SC-50 versions. If you say Y here, the tape drive will be identified at boot time @@ -547,14 +552,17 @@ and will allow you to use a SCSI device driver instead of a native ATAPI driver. - Must pass "hdx=scsi" per devices if you want the native EIDE sub-drivers - to skip over the native support. This is required for use of CD-RW's. - This is useful if you have an ATAPI device for which no native driver has been written (for example, an ATAPI PD-CD or CDR drive); you can then use this emulation together with an appropriate SCSI device driver. In order to do this, say Y here and to "SCSI support" - and "SCSI generic support", below. + and "SCSI generic support", below. You must then provide the kernel + command line "hdx=scsi" (try "man bootparam" or see the + documentation of your boot loader (lilo or loadlin) about how to + pass options to the kernel at boot time) for devices if you want the + native EIDE sub-drivers to skip over the native support, so that + this SCSI emulation can be used instead. This is required for use of + CD-RW's. Note that this option does NOT allow you to attach SCSI devices to a box that doesn't have a SCSI host adapter installed. @@ -562,12 +570,10 @@ If both this SCSI emulation and native ATAPI support are compiled into the kernel, the native support will be used. - People with SCSI-only systems can say N here. If unsure, say N. - ISA-PNP EIDE support CONFIG_BLK_DEV_ISAPNP - If you have an ISA EIDE card that is PnP and requires setup first - before scanning for devices, say Y here. + If you have an ISA EIDE card that is PnP (Plug and Play) and + requires setup first before scanning for devices, say Y here. If unsure, say N. @@ -587,16 +593,12 @@ (VLB) instead of PCI, you must also supply a kernel boot parameter to enable the CMD640 bugfix/support: "ide0=cmd640_vlb". (Try "man bootparam" or see the documentation of your boot loader about how to - pass options to the kernel. The lilo procedure is also explained in - the SCSI-HOWTO, available from - http://www.linuxdoc.org/docs.html#howto .) + pass options to the kernel.) The CMD640 chip is also used on add-in cards by Acculogic, and on the "CSA-6400E PCI to IDE controller" that some people have. For details, read Documentation/ide.txt. - People with SCSI-only systems should say N here. If unsure, say Y. - CMD640 enhanced support CONFIG_BLK_DEV_CMD640_ENHANCED This option includes support for setting/autotuning PIO modes and @@ -615,16 +617,12 @@ Linux. This may slow disk throughput by a few percent, but at least things will operate 100% reliably. - People with SCSI-only systems should say N here. If unsure, say Y. - Generic PCI IDE chipset support CONFIG_BLK_DEV_IDEPCI Say Y here for PCI systems which use IDE drive(s). This option helps the IDE driver to automatically detect and configure all PCI-based IDE interfaces in your system. - People with SCSI-only systems should say N here; if unsure say Y. - Support for sharing PCI IDE interrupts CONFIG_IDEPCI_SHARE_IRQ Some ATA/IDE chipsets have hardware support which allows for @@ -646,8 +644,8 @@ the latest version of the hdparm utility from ftp://metalab.unc.edu/pub/Linux/system/hardware/ . - Read the comments at the beginning of drivers/ide/ide-dma.c and the - file Documentation/ide.txt for more information. + Read the comments at the beginning of drivers/ide/ide-dma.c and + the file Documentation/ide.txt for more information. It is safe to say Y to this question. @@ -671,16 +669,14 @@ cards (off-board controllers) are relegated to ide2 and ide3. Answering Y here will allow you to reverse the situation, with off-board controllers on ide0/1 and on-board controllers on ide2/3. - This can improve the usability of some boot managers such as LILO + This can improve the usability of some boot managers such as lilo when booting from a drive on an off-board controller. If you say Y here, and you actually want to reverse the device scan order as explained above, you also need to issue the kernel command line option "ide=reverse". (Try "man bootparam" or see the documentation of your boot loader (lilo or loadlin) about how to - pass options to the kernel at boot time. The lilo procedure is also - explained in the SCSI-HOWTO, available from - http://www.linuxdoc.org/docs.html#howto .) + pass options to the kernel at boot time.) Note that, if you do this, the order of the hd* devices will be rearranged which may require modification of fstab and other files. @@ -693,7 +689,7 @@ DMA for IDE drives and chipsets which support it. Due to concerns about a couple of cases where buggy hardware may have caused damage, the default is now to NOT use DMA automatically. To revert to the - previous behavior, say Y to this question. + previous behaviour, say Y to this question. If you suspect your hardware is at all flakey, say N here. Do NOT email the IDE kernel people regarding this issue! @@ -703,8 +699,9 @@ Various ATA, Work(s) In Progress (EXPERIMENTAL) CONFIG_IDEDMA_PCI_WIP - If you enable this you will be capable of using and testing - highly developmental projects. + If you enable this you will be able to use and test highly + developmental projects. If you say N, this configure script will + simply skip those options. It is SAFEST to say N to this question. @@ -726,8 +723,9 @@ should say Y here, and preferably also to "Use DMA by default when available". - Please read the comments at the top of drivers/ide/aec6210.c - If you say Y here, then say Y to "Use DMA by default when available" as well. + Please read the comments at the top of drivers/ide/aec6210.c If + you say Y here, then say Y to "Use DMA by default when available" as + well. AEC6210 Tuning support (WIP) CONFIG_AEC6210_TUNING @@ -736,33 +734,37 @@ ALI M15x3 chipset support CONFIG_BLK_DEV_ALI15X3 - This driver ensures (U)DMA support for ALI 1543 and 1543C, - 1535, 1535D onboard chipsets. It also tests for Simplex mode and - enables normal dual channel support. + This driver ensures (U)DMA support for ALI 1533, 1543 and 1543C + onboard chipsets. It also tests for Simplex mode and enables + normal dual channel support. + If you say Y here, you also need to say Y to "Use DMA by default + when available", above. Please read the comments at the top of drivers/ide/alim15x3.c - If you say Y here, then say Y to "Use DMA by default when available" as well. If unsure, say N. ALI M15x3 WDC support (DANGEROUS) CONFIG_WDC_ALI15X3 - This allows for UltraDMA support for WDC drives that ignore CRC checking. - You are a fool for enabling this option, but there have been requests. - DO NOT COMPLAIN IF YOUR DRIVE HAS FS CORUPTION, IF YOU ENABLE THIS! - No one will listen, just laugh for ignoring this SERIOUS WARNING. + This allows for UltraDMA support for WDC drives that ignore CRC + checking. You are a fool for enabling this option, but there have + been requests. DO NOT COMPLAIN IF YOUR DRIVE HAS FS CORRUPTION, IF + YOU ENABLE THIS! No one will listen, just laugh for ignoring this + SERIOUS WARNING. - Using this option can allow WDC drives to run at ATA-4/5 transfer rates with - only an ATA-2 support structure. + Using this option can allow WDC drives to run at ATA-4/5 transfer + rates with only an ATA-2 support structure. SAY NO! AMD7409 chipset support (EXPERIMENTAL) CONFIG_BLK_DEV_AMD7409 - This driver ensures (U)DMA support for AMD756 Viper chipset. + This driver ensures (U)DMA support for the AMD756 Viper chipset. + If you say Y here, you also need to say Y to "Use DMA by default + when available", above. Please read the comments at the top of drivers/ide/amd7409.c - If you say Y here, then say Y to "Use DMA by default when available" as well. + If unsure, say N. AMD Viper ATA-66 Override support (WIP) @@ -773,8 +775,8 @@ CMD64X chipset support CONFIG_BLK_DEV_CMD64X - Say Y here if you have an IDE controller which uses any of these chipsets, - CMD643, CMD646, or CMD648. + Say Y here if you have an IDE controller which uses any of these + chipsets: CMD643, CMD646, or CMD648. CMD64X chipset RAID support (WIP) CONFIG_CMD64X_RAID @@ -786,7 +788,8 @@ This driver adds detection and support for the CY82C693 chipset used on Digital's PC-Alpha 164SX boards. - If you say Y here, then say Y to "Use DMA by default when available" as well. + If you say Y here, you need to say Y to "Use DMA by default + when available" as well. Cyrix CS5530 MediaGX chipset support CONFIG_BLK_DEV_CS5530 @@ -795,6 +798,8 @@ It is safe to say Y to this question. + People with SCSI-only systems should say N here. If unsure, say Y. + HPT34X chipset support CONFIG_BLK_DEV_HPT34X This driver adds up to 4 more EIDE devices sharing a single @@ -806,38 +811,39 @@ HPT34X AUTODMA support (WIP) CONFIG_HPT34X_AUTODMA - This is a dangerous thing to attempt currently! - Please read the comments at the top of drivers/ide/hpt34x.c - If you say Y here, then say Y to "Use DMA by default when available" as well. + This is a dangerous thing to attempt currently! Please read the + comments at the top of drivers/ide/hpt34x.c If you say Y here, + then say Y to "Use DMA by default when available" as well. If unsure, say N. HPT366 chipset support CONFIG_BLK_DEV_HPT366 - This is an Ultra DMA chipset for ATA-66. + HPT366 is an Ultra DMA chipset for ATA-66. This driver adds up to 4 more EIDE devices sharing a single - interrupt. The HPT366 chipset in its current form is a non-bootable, - without special LILO commands for redirecting the reference to device 0x80. - The other solution is to include "CONFIG_BLK_DEV_OFFBOARD" unless your - mainboard has the chipset native mounted. Regardless one should use the - fore mentioned option and call at LILO or include in your append-line: - "ide=reverse". This driver requires dynamic tuning of the chipset during - the ide-probe at boot. It is reported to support DVD II drives, by the - manufacturer. + interrupt. - Please read the comments at the top of drivers/ide/hpt366.c - If you say Y here, then say Y to "Use DMA by default when available" as well. + The HPT366 chipset in its current form is non-bootable. One solution + for this problem are special LILO commands for redirecting the + reference to device 0x80. The other solution is to say Y to "Boot + off-board chipsets first support" (CONFIG_BLK_DEV_OFFBOARD) unless + your mother board has the chipset natively mounted. Regardless one + should use the fore mentioned option and call at LILO or include + "ide=reverse" in LILO's append-line. + + This driver requires dynamic tuning of the chipset during the + ide-probe at boot. It is reported to support DVD II drives, by the + manufacturer. HPT366 Fast Interrupts (WIP) CONFIG_HPT366_FIP - If unsure, say N. -HPT366 mode three unsupported (WIP) +HPT366 mode three unsupported (EXPERIMENTAL) (WIP) CONFIG_HPT366_MODE3 - This is an undocumented mode that the HA366 can default to in many cases. - If unsure, say N. + This is an undocumented mode that the HA366 can default to in many + cases. If unsure, say N. NS87415 support (EXPERIMENTAL) CONFIG_BLK_DEV_NS87415 @@ -858,12 +864,14 @@ PIO 0-4 mode settings, this allows dynamic tuning of the chipset via the standard end-user tool 'hdparm'. - Please read the comments at the top of drivers/ide/piix.c + Please read the comments at the top of drivers/ide/piix.c. - Should also include "PIIXn Tuning support" CONFIG_PIIX_TUNING - If unsure, say Y. + If you say Y here, you should also say Y to "PIIXn Tuning support", + below. + + If unsure, say N. -PIIXn Tuning support +PIIXn Tuning support (EXPERIMENTAL) CONFIG_PIIX_TUNING This driver extension adds DMA mode setting and tuning for all PIIX IDE controllers by Intel. Since the BIOS can sometimes improperly @@ -873,7 +881,7 @@ Case 430HX/440FX PIIX3 need speed limits to reduce UDMA to DMA mode 2 if the BIOS can not perform this task at initialization. - If unsure, say Y. + If unsure, say N. PROMISE PDC20246/PDC20262 support CONFIG_BLK_DEV_PDC202XX @@ -883,10 +891,10 @@ interrupt. This add-on card is a bootable PCI UDMA controller. Since multiple cards can be installed and there are BIOS ROM problems that happen if the BIOS revisions of all installed cards (three-max) do - not match, the driver attempts to do dynamic tuning of the chipset at - boot-time for max-speed. Ultra33 BIOS 1.25 or newer is required for - more than one card. This card may require that you say Y to "Special - UDMA Feature (EXPERIMENTAL)". + not match, the driver attempts to do dynamic tuning of the chipset + at boot-time for max-speed. Ultra33 BIOS 1.25 or newer is required + for more than one card. This card may require that you say Y to + "Special UDMA Feature (EXPERIMENTAL)". Promise Ultra66 or PDC20262 @@ -896,12 +904,14 @@ boot-time for max-speed. Note tested limits are UDMA-2. Ultra66 BIOS 1.11 or newer required. - If you say Y here, then say Y to "Use DMA by default when available" as well. + If you say Y here, you need to say Y to "Use DMA by default when + available" as well. + Please read the comments at the top of drivers/ide/pdc202xx.c If unsure, say N. -Special UDMA Feature +Special UDMA Feature (EXPERIMENTAL) CONFIG_PDC202XX_BURST For PDC20246 and PDC20262 Ultra DMA chipsets. Designed originally for PDC20246/Ultra33 that has BIOS setup failures when using 3 or @@ -918,6 +928,17 @@ Say N. +SiS5513 chipset support +CONFIG_BLK_DEV_SIS5513 + This driver ensures (U)DMA support for SIS5513 chipset based + mainboards. SiS620/530 UDMA mode 4, SiS5600/5597 UDMA mode 2, all + other DMA mode 2 limited chipsets are unsupported to date. + + If you say Y here, you need to say Y to "Use DMA by default when + available" as well. + + Please read the comments at the top of drivers/ide/sis5513.c + Winbond SL82c105 support CONFIG_BLK_DEV_SL82C105 If you have a Winbond SL82c105 IDE controller, say Y here to enable @@ -933,16 +954,18 @@ VIA82CXXX chipset support (EXPERIMENTAL) CONFIG_BLK_DEV_VIA82CXXX - This allows you to to configure your chipset for a better use while - running (U)DMA: it will allow you to enable efficiently the second - channel dma usage, as it is may not be set by BIOS. It allows you to - run a kernel command line at boot time in order to set fifo config. - If no command line is provided, it will try to set fifo configuration - at its best. It will allow you to get a proc/ide/via display - (while running a "cat") provided you enabled "proc" support. + This allows you to to configure your chipset for a better use while + running (U)DMA: it will allow you to enable efficiently the second + channel dma usage, as it may not be set by BIOS. It allows you to + pass a kernel command line at boot time in order to set fifo + config. If no command line is provided, it will try to set fifo + configuration at its best. It will allow you to get information from + /proc/ide/via provided you enabled "proc" support. + Please read the comments at the top of drivers/ide/via82cxxx.c - If you say Y here, then say Y to "Use DMA by default when available" as well. + If you say Y here, then say Y to "Use DMA by default when available" + as well. If unsure, say N. @@ -1045,7 +1068,7 @@ Amiga IDE Doubler support (EXPERIMENTAL) CONFIG_BLK_DEV_IDEDOUBLER - This driver provides support for the so called `IDE doublers' (made + This driver provides support for the so-called `IDE doublers' (made by various manufacturers, e.g. Eyetech) that can be connected to the builtin IDE interface of some Amiga models. Using such an IDE doubler, you can connect up to four instead of two IDE devices on @@ -1087,11 +1110,6 @@ devices (hard disks, CD-ROM drives, etc.) that are connected to the builtin IDE interface. -IDE card support -CONFIG_BLK_DEV_IDE_CARDS - On Acorn systems, say Y here if you wish to use an IDE interface - expansion card. If you do not or are unsure, say N to this. - ICS IDE interface support CONFIG_BLK_DEV_IDE_ICSIDE On Acorn systems, say Y here if you wish to use the ICS IDE @@ -1100,7 +1118,8 @@ ICS DMA support CONFIG_BLK_DEV_IDEDMA_ICS - No help for CONFIG_BLK_DEV_IDEDMA_ICS + Say Y here if you want to add DMA (Direct Memory Access) support to + the ICS IDE driver. Use ICS DMA by default CONFIG_IDEDMA_ICS_AUTO @@ -1113,10 +1132,6 @@ If you suspect your hardware is at all flakey, say N here. Do NOT email the IDE kernel people regarding this issue! -RapIDE interface support -CONFIG_BLK_DEV_IDE_RAPIDE - No help for CONFIG_BLK_DEV_IDE_RAPIDE - XT hard disk support CONFIG_BLK_DEV_XD Very old 8 bit hard disk controllers used in the IBM XT computer @@ -1133,7 +1148,7 @@ CONFIG_BLK_DEV_PS2 Say Y here if you have a PS/2 machine with a MCA bus and an ESDI hard disk. - + If you want to compile the driver as a module ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read Documentation/modules.txt. The module will be @@ -1157,7 +1172,7 @@ your computer's parallel port. Most of them are actually IDE devices using a parallel port IDE adapter. This option enables the PARIDE subsystem which contains drivers for many of these external drives. - Read linux/Documentation/paride.txt for more information. + Read Documentation/paride.txt for more information. If you have said Y to the "Parallel-port support" configuration option, you may share a single port between your printer and other @@ -1199,8 +1214,8 @@ system. Among the devices supported by this driver are the MicroSolutions backpack CD-ROM drives and the Freecom Power CD. If you have such a CD-ROM drive, you should also say Y or M to "ISO - 9660 CDROM file system support" below, because that's the file system - used on CDROMs. + 9660 CDROM file system support" below, because that's the file + system used on CDROMs. Parallel port ATAPI disks CONFIG_PARIDE_PF @@ -1241,7 +1256,7 @@ your system. This driver implements an API loosely related to the generic SCSI - driver. See /usr/include/linux/pg.h for details. + driver. See include/linux/pg.h for details. You can obtain the most recent version of cdrecord from ftp://ftp.fokus.gmd.de/pub/unix/cdrecord/ . Versions 1.6.1a3 and @@ -1401,9 +1416,13 @@ to new capacity needs. Logical volumes are accessed as block devices named /dev/VolumeGroupName/LogicalVolumeName. - For details see /usr/src/linux/Documentaion/LVM-HOWTO. + For details see Documentation/LVM-HOWTO. You will need supporting + user space software from http://linux.msede.com/lvm . - To get the newest software see . + If you want to compile this support as a module ( = code which can + be inserted in and removed from the running kernel whenever you + want), say M here and read Documentation/modules.txt. The module + will be called lvm-mod.o. Logical Volume Manager /proc file system information CONFIG_LVM_PROC_FS @@ -1517,37 +1536,30 @@ answer Y here. For lilo and loadlin options see the file Documentation/md.txt. -Support for Deskstation RPC44 -CONFIG_DESKSTATION_RPC44 - This is a machine with a R4400 100 MHz CPU. To compile a Linux - kernel that runs on these, say Y here. For details about Linux - on the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at - http://oss.sgi.com/mips. - Support for Acer PICA 1 chipset CONFIG_ACER_PICA_61 This is a machine with a R4400 133/150 MHz CPU. To compile a Linux kernel that runs on these, say Y here. For details about Linux on the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at - http://oss.sgi.com/mips. + http://oss.sgi.com/mips . Support for Algorithmics P4032 (EXPERIMENTAL) CONFIG_ALGOR_P4032 This is an evaluation board of the British company Algorithmics. The board uses the R4300 and a R5230 CPUs. For more information about - this board see http://www.algor.co.uk. + this board see http://www.algor.co.uk . Support for BAGET MIPS series CONFIG_BAGET_MIPS This enables support for the Baget, a Russian embedded system. For more details about the Baget see the Linux/MIPS FAQ on - http://oss.sgi.com/mips. + http://oss.sgi.com/mips . Support for DECstations CONFIG_DECSTATION This enables support for DEC's MIPS based workstations. For details - see the Linux/MIPS FAQ on http://oss.sgi.com/mips. the - DECstation porting pages on http://decstation.unix-ag.org. + see the Linux/MIPS FAQ on http://oss.sgi.com/mips and the + DECstation porting pages on http://decstation.unix-ag.org . If you have one of the following DECstation Models you definitely want to choose R4xx0 for the CPU Type: @@ -1561,26 +1573,8 @@ Support for NEC DDB Vrc-5074 CONFIG_DDB5074 - This enables support for the VR5000-based NEC DDB Vrc-5074 evaluation - board. - -IDE card support -CONFIG_BLK_DEV_IDE_CARDS - On Acorn systems, say Y here if you wish to use an IDE interface - expansion card. If you do not or are unsure, say N to this. - -ICS IDE interface -CONFIG_BLK_DEV_IDE_ICS - On Acorn systems, say Y here if you wish to use the ICS IDE - interface card. This is not required for ICS partition support. - If you are unsure, say N to this. - -ADFS partition support -CONFIG_BLK_DEV_PART - This allows Linux on Acorn systems to determine its partitions in - the 'non-ADFS' partition area of the hard disk - usually located - after the ADFS partition. You are probably using this system, so - you should say Y it. + This enables support for the VR5000-based NEC DDB Vrc-5074 + evaluation board. Support for Mips Magnum 4000 CONFIG_MIPS_MAGNUM_4000 @@ -1598,9 +1592,9 @@ Support for SGI IP22 CONFIG_SGI_IP22 - This are the SGI Indy, Challenge S and Indigo2, as well as certain OEM - variants like the Tandem CMN B006S. To compile a Linux kernel that - runs on these, say Y here. + This are the SGI Indy, Challenge S and Indigo2, as well as certain + OEM variants like the Tandem CMN B006S. To compile a Linux kernel + that runs on these, say Y here. Support for SGI IP27 This are the SGI Origin 200, Origin 2000 and Onyx 2 Graphics @@ -1611,7 +1605,7 @@ CONFIG_SGI_SN0_N_MODE The nodes of Origin 200, Origin 2000 and Onyx 2 systems can be configured in either N-Modes which allows for more nodes or M-Mode - which allows for more more memory. Your system is most probly + which allows for more more memory. Your system is most probably running in M-Mode, so you should say N here. MIPS JAZZ onboard SONIC Ethernet support @@ -1621,26 +1615,26 @@ MIPS JAZZ FAS216 SCSI support CONFIG_JAZZ_ESP - This is the driver for the onboard SCSI hostadapter of MIPS Magnum 4000, - Acer PICA, Olivetti M700-10 and a few other identical OEM systems. + This is the driver for the onboard SCSI host adapter of MIPS Magnum + 4000, Acer PICA, Olivetti M700-10 and a few other identical OEM + systems. CPU type CONFIG_CPU_R3000 - Please make shure to pick the right CPU type. Linux/MIPS is not + Please make sure to pick the right CPU type. Linux/MIPS is not designed to be generic, i.e. Kernels compiled for R3000 CPUs will *not* work on R4000 Machines and vice versa. - However, since most the supported Machines have an R4000 (or similar) - CPU R4xx0 might be a safe bet. + However, since most the supported Machines have an R4000 (or + similar) CPU, R4xx0 might be a safe bet. If the resulting Kernel does not work try to recompile with R3000. Support for large 64-bit configurations CONFIG_MIPS_INSANE_LARGE MIPS R10000 does support a 44 bit / 16TB address space as opposed to - previous 64-bit processors which only did only support 40 bit / 1TB. If - you need processes of more than 1TB virtual address space activate this. - Activating CONFIG_MIPS_INSANE_LARGE results in additional memory usage, - so only activate this if you really need. Very few people will need - this. + previous 64-bit processors which only supported 40 bit / 1TB. If you + need processes of more than 1TB virtual address space, say Y here. + This will result in additional memory usage, so it is not + recommended for normal users. Generate little endian code CONFIG_CPU_LITTLE_ENDIAN @@ -1648,11 +1642,6 @@ byte order. These modes require different kernels. Say Y if your machine is little endian, N if it's a big endian machine. -Kernel support for IRIX binaries -CONFIG_BINFMT_IRIX - If you say Y here, the kernel will support running of IRIX binaries. - You will need IRIX libraries for this to work. - Networking support CONFIG_NET Unless you really know what you are doing, you should say Y here. @@ -1675,7 +1664,7 @@ socket and thereby tell the kernel that it should allow or disallow certain types of data to get through the socket. Linux Socket Filtering works on all socket types except TCP for now. See the text - file linux/Documentation/networking/filter.txt for more information. + file Documentation/networking/filter.txt for more information. If unsure, say N. Network packet filtering @@ -1710,7 +1699,7 @@ are completely invisible to the outside world, even though they can reach the outside and can receive replies. It is even possible to run globally visible servers from within a masqueraded local network - using a mechanism called port-forwarding. Masquerading is also often + using a mechanism called portforwarding. Masquerading is also often called NAT (Network Address Translation). Another use of Netfilter is in transparent proxying: if a machine on @@ -1720,7 +1709,7 @@ Various modules exist for netfilter which replace the previous masquerading (ipmasqadm), packet filtering (ipchains), transparent - proxying, and port-forwarding mechanisms. More information is + proxying, and portforwarding mechanisms. More information is available from http://netfilter.kernelnotes.org . Make sure to say N to "Fast switching" below if you intend to say Y @@ -1729,6 +1718,11 @@ Chances are that you should say Y here if you compile a kernel which will run as a router and N for regular hosts. If unsure, say N. +Network packet filtering debugging +CONFIG_NETFILTER_DEBUG + You can say Y here if you want to get additional messages useful in + debugging the netfilter code. + IP: connection tracking (required for masq/NAT) CONFIG_IP_NF_CONNTRACK Connection tracking keeps a record of what packets have passed @@ -1773,7 +1767,8 @@ limit match support CONFIG_IP_NF_MATCH_LIMIT limit matching allows you to control the rate at which a rule can be - matched: mainly useful in combination with the LOG target. + matched: mainly useful in combination with the LOG target ("LOG + target support", below). If you want to compile it as a module, say M here and read Documentation/modules.txt. If unsure, say `N'. @@ -1831,7 +1826,6 @@ Owner match support (EXPERIMENTAL) CONFIG_IP_NF_MATCH_OWNER - Packet owner matching allows you to match locally-generated packets based on who created them: the user, group, process or session. @@ -1889,7 +1883,7 @@ REDIRECT is a special case of NAT: all incoming connections are mapped onto the incoming interface's address, causing the packets to come to the local machine instead of passing through. This is - useful for tranparent proxies. + useful for transparent proxies. If you want to compile it as a module, say M here and read Documentation/modules.txt. If unsure, say `N'. @@ -1914,11 +1908,12 @@ MARK target support CONFIG_IP_NF_TARGET_MARK - This option adds a `MARK' target, which allows you to create rules in - the `mangle' table which alter the netfilter mark (nfmark) field - associated with the packet packet prior to routing. This can change - the routing method (see `IP: use netfilter MARK value as routing key') - and can also be used by other subsystems to change their behavior. + This option adds a `MARK' target, which allows you to create rules + in the `mangle' table which alter the netfilter mark (nfmark) field + associated with the packet packet prior to routing. This can change + the routing method (see `IP: use netfilter MARK value as routing + key') and can also be used by other subsystems to change their + behavior. If you want to compile it as a module, say M here and read Documentation/modules.txt. If unsure, say `N'. @@ -1989,11 +1984,6 @@ If unsure, say Y. -Sun floppy controller support -CONFIG_BLK_DEV_SUNFD - This is support for floppy drives on Sun SPARC workstations. Say Y - if you have a floppy drive, otherwise N. Easy. - Alpha system type CONFIG_ALPHA_GENERIC This is the system type of your hardware. A "generic" kernel will @@ -2060,12 +2050,6 @@ If unsure, say N. -Use SRM PCI setup -CONFIG_ALPHA_SRM_SETUP - This option controls whether or not the PCI configuration set up by - SRM is modified. If you say Y, the existing PCI configuration will - be left intact. - Non-standard serial port support CONFIG_SERIAL_NONSTANDARD Say Y here if you have any non-standard serial boards -- boards @@ -2128,7 +2112,7 @@ SGI PROM Console Support CONFIG_SGI_PROM_CONSOLE - Enable this if you want to use the PROMs for console I/O. + Say Y here if you want to use the PROMs for console I/O. SGI Zilog85C30 serial support CONFIG_SGI_SERIAL @@ -2144,7 +2128,7 @@ SGI Newport Console support CONFIG_SGI_NEWPORT_CONSOLE - Enable this if you want the console on the Newport aka XL graphics + Say Y here if you want the console on the Newport aka XL graphics card of your Indy. Most people say Y here. SGI DS1286 RTC support @@ -2152,51 +2136,131 @@ If you say Y here and create a character special file /dev/rtc with major number 10 and minor number 135 using mknod ("man mknod"), you will get access to the real time clock built into your computer. - Every SGI has such a clock built in. It reports status information - via the file /proc/rtc and its behaviour is set by various ioctls on + Every SGI has such a clock built in. It reports status information + via the file /proc/rtc and its behaviour is set by various ioctls on /dev/rtc. -SGI Vino Video For Linux (EXPERIMENTAL) -CONFIG_SGI_VIDEO_VINO - Support for the SGI Vino Video hardware which is part of the Newport - aka XL graphics card. Most people will say N here. - Support the Bell Technologies HUB6 card CONFIG_HUB6 Say Y here to enable support in the dumb serial driver to support the HUB6 card. -Support for hot-pluggable devices -CONFIG_HOTPLUG - Say Y here to enable support for hot plugin of certain hardware such as - PCMCIA cards and the like. - - At this moment, few drivers support it, but as they get converted to use the - new ressource allocator/manager, their number will increase. - PCMCIA serial device support CONFIG_PCMCIA_SERIAL_CS Say Y here to enable support for 16-bit PCMCIA serial devices, including serial port cards, modems, and the modem functions of - multifunction ethernet/modem cards. + multi-function ethernet/modem cards. (PCMCIA- or PC-cards are + credit-card size devices often used with laptops.) This driver 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 serial_cs.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. If unsure, + The module will be called serial_cs.o. If you want to compile it as + a module, say M here and read Documentation/modules.txt. If unsure, say N. CardBus serial device support CONFIG_PCMCIA_SERIAL_CB Say Y here to enable support for CardBus serial devices, including - the modem functions of multifunction ethernet/modem devices. + serial port cards, modems, and the modem functions of multi-function + ethernet/modem devices. (CardBus cards are the newer and better + version of PCMCIA- or PC-cards: credit card size devices often + used with laptops.) This driver 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 serial_cb.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. If unsure, + The module will be called serial_cb.o. If you want to compile it as + a module, say M here and read Documentation/modules.txt. If unsure, say N. +/dev/agpgart (AGP Support) (EXPERIMENTAL) +CONFIG_AGP + AGP (Accelerated Graphics Port) is a bus system mainly used to + connect graphics cards to the rest of the system. + + If you have an AGP system and you say Y here, it will be possible to + use the AGP features of your 3D rendering video card. This code acts + as a sort of "AGP driver" for the motherboard's chipset. The glx + module will then be able to program the GART (graphics aperture + relocation table) registers with appropriate values to transfer + commands to the card. + + If you need more texture memory than you can get with the AGP GART + (theoretically up to 256 MB, but in practice usually 64 or 128 MB + due to kernel allocation issues), you could use PCI accesses + and have up to a couple gigs of texture space. + + Note that this is the only means to have XFree4/GLX use + write-combining with MTRR support on the AGP bus. Without it, OpenGL + direct rendering will be a lot slower but still faster than PIO. + + 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 + http://utah-glx.sourceforge.net/ , or need to use the 810 Xserver in + XFree 3.3.6. + + This driver is available as a module. If you want to compile it as a + module, say M here and read Documentation/modules.txt. The module + will be called agpgart.o. + +Intel 440LX/BX/GX support +CONFIG_AGP_INTEL + This option gives you AGP support for the GLX component of the + "soon to be released" XFree86 4.x on Intel 440LX/BX/GX 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 + http://utah-glx.sourceforge.net/ . + +Intel I810/I810 DC100/I810e support +CONFIG_AGP_I810 + This option gives you AGP support for the Xserver for the Intel + 810 chipset boards. This is required to do any useful video + modes. + +VIA chipset support +CONFIG_AGP_VIA + This option gives you AGP support for the GLX component of the + "soon to be released" XFree86 4.x on VIA MPV3/Apollo Pro 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 + http://utah-glx.sourceforge.net/ . + +AMD Irongate support +CONFIG_AGP_AMD + This option gives you AGP support for the GLX component of the + "soon to be released" XFree86 4.x on Intel AMD Irongate chipset. + + 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 + http://utah-glx.sourceforge.net/ . + +Generic SiS support +CONFIG_AGP_SIS + This option gives you AGP support for the GLX component of the "soon + to be released" XFree86 4.x on Silicon Integrated Systems [SiS] + chipsets. + + Note that 5591/5592 AGP chipsets are NOT supported. + + 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 + http://utah-glx.sourceforge.net/ . + +ALI M1541 support +CONFIG_AGP_ALI + This option gives you AGP support for the GLX component of the + "soon to be released" XFree86 4.x on the ALi M1541 chipset. + + This chipset can do AGP 1x and 2x, but note that there is an + acknowledged incompatibility with Matrox G200 cards. Due to + timing issues, this chipset cannot do AGP 2x with the G200. + This is a hardware limitation. AGP 1x seems to be fine, though. + + 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 + http://utah-glx.sourceforge.net/ . + PCI support CONFIG_PCI Find out whether you have a PCI motherboard. PCI is the name of a @@ -2221,16 +2285,17 @@ devices. If you choose "BIOS", the BIOS will be used, if you choose "Direct", the BIOS won't be used, and if you choose "Any", the kernel will try the direct access method and falls back to the BIOS - if that doesn't work. If unsure, go with the default. + if that doesn't work. If unsure, go with the default, which is + "Any". PCI device name database CONFIG_PCI_NAMES By default, the kernel contains a database of all known PCI device - names to make the information in /proc/pci, /proc/ioports and similar - files comprehensible to the user. This database increases size of - the kernel image by about 80KB, but it gets freed after the system - boots up, so it doesn't take up kernel memory. Anyway, if you are - building an installation floppy or kernel for an embedded system + names to make the information in /proc/pci, /proc/ioports and + similar files comprehensible to the user. This database increases + size of the kernel image by about 80KB, but it gets freed after the + system boots up, so it doesn't take up kernel memory. Anyway, if you + are building an installation floppy or kernel for an embedded system where kernel image size really matters, you can disable this feature and you'll get device ID numbers instead of names. @@ -2343,8 +2408,9 @@ Say Y here if you would like Linux to configure your Plug and Play devices. You should then also say Y to "ISA Plug and Play support", - below. Alternatively, you can configure your PnP devices using the - user space utilities contained in the isapnptools package. + below. Alternatively, you can say N here and configure your PnP + devices using the user space utilities contained in the isapnptools + package. This support is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -2354,7 +2420,8 @@ ISA Plug and Play support CONFIG_ISAPNP Say Y here if you would like support for ISA Plug and Play devices. - + Some information is in Documentation/isapnp.txt. + This support is also available as a module called isapnp.o ( = code which can be inserted in and removed from the running kernel whenever you want). If you want to compile it as a module, say M @@ -2362,13 +2429,27 @@ If unsure, say Y. -PCMCIA/CardBus support +Support for hot-pluggable devices +CONFIG_HOTPLUG + Say Y here if you want to attach devices to your computer that can + be attached and detached while the system is running. The most + prominent example of this are PCMCIA- or PC-cards, credit-card size + devices such as network cards, modems or hard drives which are + plugged into slots found on all modern laptop computers. + +PCMCIA/Cardbus support CONFIG_PCMCIA - Include kernel support for PCMCIA and CardBus devices. Because - PCMCIA support requires additional components that are not part of - the kernel (i.e., the pcmcia-cs package), building PCMCIA into the - kernel is generally not recommended unless you have a specific - need. If unsure, say N. + Say Y here if you want to attach PCMCIA- or PC-cards to your Linux + computer. These are credit-card size devices such as network cards, + modems or hard drives often used with laptops computers. There are + actually two varieties of these cards: the older 16 bit PCMCIA cards + and the newer 32 bit CardBus cards. If you want to use CardBus + cards, you need to say Y here and also to "CardBus support" below. + + To use your PC-cards, you will need supporting software from David + Hinds' pcmcia-cs package (see the file Documentation/Changes for + location). Please also read the PCMCIA-HOWTO, available from + http://www.linuxdoc.org/docs.html#howto This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -2376,27 +2457,32 @@ and ds.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. - You will also need David Hinds' pcmcia-cs package (see the file - Documentation/Changes for location). For more information, see the - PCMCIA-HOWTO. - CardBus support CONFIG_CARDBUS - There are two types of PCMCIA devices: 16-bit PC Cards, and higher - performance 32-bit CardBus devices. Use this option to include - support for CardBus devices. If unsure, say Y. + CardBus is a bus mastering architecture for PC-cards, which allows + for 32 bit PC-cards (the original PCMCIA standard specifies only + a 16 bit wide bus). Many newer PC-cards are actually CardBus cards. + + To use your PC-cards, you will need supporting software from David + Hinds' pcmcia-cs package (see the file Documentation/Changes for + location). + + If unsure, say Y. i82365/Yenta compatible bridge support CONFIG_I82365 - Include support for PCMCIA and CardBus host bridges that are - register compatible with the Intel i82365 and/or the Yenta + Say Y here to include support for PCMCIA and CardBus host bridges + that are register compatible with the Intel i82365 and/or the Yenta specification: this includes virtually all modern PCMCIA bridges. - If unsure, say Y. + "Bridge" is the name used for the hardware inside your computer that + PCMCIA cards are plugged into. If unsure, say Y. Databook TCIC host bridge support CONFIG_TCIC - Include support for the Databook TCIC family of PCMCIA host bridges. - These are only found on a handful of old systems. If unsure, say N. + Say Y here to include support for the Databook TCIC family of PCMCIA + host bridges. These are only found on a handful of old systems. + "Bridge" is the name used for the hardware inside your computer that + PCMCIA cards are plugged into. If unsure, say N. System V IPC CONFIG_SYSVIPC @@ -2414,9 +2500,9 @@ http://www.linuxdoc.org/docs.html#guide . Shared memory is now implemented using a new (minimal) virtual file - system, which you need to mount before programs can use shared memory. - To do this automatically at system startup just add the following line - to your /etc/fstab: + system, which you need to mount before programs can use shared + memory. To do this automatically at system startup just add the + following line to your /etc/fstab: none /var/shm shm defaults 0 0 @@ -2451,21 +2537,24 @@ Kernel core (/proc/kcore) format CONFIG_KCORE_ELF - If you enabled support for /proc file system then the file /proc/kcore - will contain the kernel core image. This can be used in gdb: + If you enabled support for /proc file system then the file + /proc/kcore will contain the kernel core image. This can be used + in gdb: $ cd /usr/src/linux ; gdb vmlinux /proc/kcore - Selecting ELF will make /proc/kcore appear in ELF core format as defined - by the Executable and Linking Format specification. Selecting A.OUT will - choose the old "a.out" format which may be necessary for some old versions + You have two choices here: ELF and A.OUT. Selecting ELF will make + /proc/kcore appear in ELF core format as defined by the Executable + and Linking Format specification. Selecting A.OUT will choose the + old "a.out" format which may be necessary for some old versions of binutils or on some architectures. - This is especially useful if you have compiled the kernel with "-g" option - to preserve debugging information. It is mainly used for examining kernel - data structures on the live kernel so if you don't understand what this - means or are not a kernel hacker, just leave it at its default value ELF. - + This is especially useful if you have compiled the kernel with the + "-g" option to preserve debugging information. It is mainly used + for examining kernel data structures on the live kernel so if you + don't understand what this means or are not a kernel hacker, just + leave it at its default value ELF. + Kernel support for ELF binaries CONFIG_BINFMT_ELF ELF (Executable and Linkable Format) is a format for libraries and @@ -2569,10 +2658,10 @@ all x86 CPU types (albeit not optimally fast), you can specify "386" here. - If you specify one of "486" or "586" or "Pentium" or "PPro", then - the kernel will not necessarily run on earlier architectures (e.g. a - Pentium optimized kernel will run on a PPro, but not necessarily on - a i486). + If you specify one of "486" or "586" or "Pentium" or "PPro" or + "Athlon", then the kernel will not necessarily run on earlier + architectures (e.g. a Pentium optimized kernel will run on a PPro, + but not necessarily on a i486). Here are the settings recommended for greatest speed: - "386" for the AMD/Cyrix/Intel 386DX/DXL/SL/SLC/SX, Cyrix/TI @@ -2583,11 +2672,11 @@ UMC U5D or U5S. - "586" for generic Pentium CPUs, possibly lacking the TSC (time stamp counter) register. - - "Pentium" for the Intel Pentium/Pentium MMX, AMD K5. + - "Pentium" for the Intel Pentium/Pentium MMX, and AMD K5. - "PPro" for the Cyrix/IBM/National Semiconductor 6x86MX, MII and - Intel Pentium II/Pentium Pro. + Intel Pentium Pro/Celeron/Pentium II/Pentium III. - "K6/II/III" for the AMD K6, K6-II and K6-III (aka K6-3D). - - "Athlon" for the AMD Athlon (aka K7) + - "Athlon" for the AMD Athlon (K7). If you don't know what to do, choose "386". @@ -2612,9 +2701,7 @@ "vga=" option from your boot loader (lilo or loadlin) or set "vga=ask" which brings up a video mode menu on kernel startup. (Try "man bootparam" or see the documentation of your boot loader about - how to pass options to the kernel. The lilo procedure is also - explained in the SCSI-HOWTO, available from - http://www.linuxdoc.org/docs.html#howto .) + how to pass options to the kernel.) Read the file Documentation/svga.txt for more information about the Video mode selection support. If unsure, say N. @@ -2658,11 +2745,6 @@ hardware found in Acorn RISC PCs and other ARM-based machines. If unsure, say N. -Apollo frame buffer device -CONFIG_FB_APOLLO - This is the frame buffer device driver for the monochrome graphics - hardware found in some Apollo workstations. - Amiga native chipset support CONFIG_FB_AMIGA This is the frame buffer device driver for the builtin graphics @@ -2769,8 +2851,8 @@ 3Dfx Banshee/Voodoo3 display support (EXPERIMENTAL) CONFIG_FB_3DFX - This driver supports graphics boards with the 3Dfx Banshee/Voodoo3 chips. - Say Y if you have such a graphics board. + This driver supports graphics boards with the 3Dfx Banshee/Voodoo3 + chips. Say Y if you have such a graphics board. The driver is also available as a module ( = code which can be inserted and removed from the running kernel whenever you want). The @@ -2797,17 +2879,18 @@ inserted and removed from the running kernel whenever you want). The module will be called atyfb.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. - + ATI Rage128 display support (EXPERIMENTAL) CONFIG_FB_ATY128 This driver supports graphics boards with the ATI Rage128 chips. - Say Y if you have such a graphics board. + Say Y if you have such a graphics board and read + Documentation/fb/aty128fb.txt. The driver is also available as a module ( = code which can be inserted and removed from the running kernel whenever you want). The module will be called aty128fb.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. - + PowerMac "control" frame buffer device support CONFIG_FB_CONTROL This driver supports a frame buffer for the graphics adapter in the @@ -2828,16 +2911,6 @@ This is the frame buffer device driver for the Chips & Technologies 65550 graphics chip in PowerBooks. -Mac frame buffer device -CONFIG_FB_MAC - This is the frame buffer device driver for the graphics hardware in - m68k Macintoshes. - -HP300 frame buffer device -CONFIG_FB_HP300 - This is the frame buffer device driver for the Topcat graphics - hardware found in HP300 workstations. - TGA frame buffer support CONFIG_FB_TGA This is the frame buffer device driver for generic TGA graphic @@ -2853,10 +2926,11 @@ VGA 16-color planar support CONFIG_FBCON_VGA_PLANES This low level frame buffer console driver enable the kernel to use - the 16-color planar modes of the old VGA cards where the bits of each - pixel are separated into 4 plans. - Only answer Y here if you have an (very old) VGA card that isn't - VESA 2 compatible. + the 16-color planar modes of the old VGA cards where the bits of + each pixel are separated into 4 planes. + + Only answer Y here if you have a (very old) VGA card that isn't VESA + 2 compatible. VGA 16-color graphics console CONFIG_FB_VGA16 @@ -2870,12 +2944,12 @@ Select other compiled-in fonts CONFIG_FBCON_FONTS - Say Y here if you would like to use fonts other than the default your frame - buffer console usually use. + Say Y here if you would like to use fonts other than the default + your frame buffer console usually use. - Note that the answer to this question won't directly affect the kernel: - saying N will just cause this configure script to skip all the questions - about foreign fonts. + Note that the answer to this question won't directly affect the + kernel: saying N will just cause this configure script to skip all + the questions about foreign fonts. If unsure, say N (the default choices are safe). @@ -2895,22 +2969,21 @@ Sparc console 8x16 font CONFIG_FONT_SUN8x16 - This is the high resolution console font for Sun machines. - - Say Y. + This is the high resolution console font for Sun machines. Say Y. Sparc console 12x22 font (not supported by all drivers) CONFIG_FONT_SUN12x22 - This is the high resolution console font for Sun machines with very big - letters (like the letters used in the SPARC PROM). If the standard font - is unreadable for you, say Y, otherwise say N. + This is the high resolution console font for Sun machines with very + big letters (like the letters used in the SPARC PROM). If the + standard font is unreadable for you, say Y, otherwise say N. VGA 8x8 font CONFIG_FONT_8x8 This is the "high resolution" font for the VGA frame buffer (the one - provided by the text console 80x50 (and higher) modes. - Note this is a poor quality font. The VGA 8x16 font is quite a lot - more readable. + provided by the text console 80x50 (and higher) modes). + + Note that this is a poor quality font. The VGA 8x16 font is quite a + lot more readable. Given the resolution provided by the frame buffer device, answer N here is safe. @@ -2923,7 +2996,6 @@ (XF68_FBDev). HGA monochrome support (EXPERIMENTAL) -Hercules mono graphics console (EXPERIMENTAL) CONFIG_FBCON_HGA Say Y here if you have a Hercules mono graphics card. @@ -2932,11 +3004,12 @@ The module will be called hgafb.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. - As this card technology is 15 years old, most people will answer N here. + As this card technology is 15 years old, most people will answer N + here. Matrox unified accelerated driver (EXPERIMENTAL) CONFIG_FB_MATROX - Say Y here if you have Matrox Millennium, Matrox Millennium II, + Say Y here if you have a Matrox Millennium, Matrox Millennium II, Matrox Mystique, Matrox Mystique 220, Matrox Productiva G100, Matrox Mystique G200, Matrox Millennium G200, Matrox Marvel G200 video or Matrox G400 card in your box. At this time, support for the G100, @@ -2976,49 +3049,51 @@ you select "Advanced lowlevel driver options", you should check 8 bpp packed pixel, 16 bpp packed pixel, 24 bpp packed pixel and 32 bpp packed pixel. You can also use font widths different from 8. - - If you need support for G400 secondary head, you must first enable - I2C support and I2C bit-banging support in character devices section, - and then Matrox I2C support and G400 secondary head support here - in framebuffer section. + + If you need support for G400 secondary head, you must first say Y to + "I2C support" and "I2C bit-banging support" in the character devices + section, and then to "Matrox I2C support" and "G400 second head + support" here in the framebuffer section. Matrox I2C support CONFIG_FB_MATROX_I2C - This drivers creates I2C buses which are needed for accessing - DDC (I2C) bus present on all Matroxes, I2C bus which interconnects - Matrox optional devices, like MGA-TVO on G200 and G400, and - secondary head DDC bus, present on G400 only. + This drivers creates I2C buses which are needed for accessing the + DDC (I2C) bus present on all Matroxes, an I2C bus which + interconnects Matrox optional devices, like MGA-TVO on G200 and + G400, and the secondary head DDC bus, present on G400 only. You can say Y or M here if you want to experiment with monitor detection code. You must say Y or M here if you want to use either second head of G400 or MGA-TVO on G200 or G400. - If you compile it as module, it will create module named i2c-matroxfb.o. + If you compile it as module, it will create a module named + i2c-matroxfb.o. Matrox G400 second head support CONFIG_FB_MATROX_MAVEN - Say Y or M here if you want to use secondary head on G400 or MGA-TVO - add-on on G200. Secondary head is not compatible with accelerated - XFree 3.3.x SVGA servers - secondary head output is blanked while you - are in X. With XFree 3.9.17 preview you can use both heads if you use - SVGA over fbdev or fbdev driver on first head and fbdev driver on - second head. - - If you compile it as module, two modules are created, matroxfb_crtc2.o - and matroxfb_maven.o. Matroxfb_maven is needed for both G200 and G400, - matroxfb_crtc2 is needed only by G400. You must also load i2c-matroxfb - to get it to run. - - Driver starts in monitor mode and you must use matroxset tool (available - at ftp://platan.vc.cvut.cz/pub/linux/matrox-latest) to switch it to PAL - or NTSC or to swap primary and secondary head outputs. Secondary head - driver also always start in 640x480 resolution, you must use fbset to - change it. - - Also do not forget that second head supports only 16 and 32 bpp packed - pixels, so it is good idea to compile them into kernel too. You can - use only some font widths, as driver uses generic painting procedures - (secondary head does not use acceleration engine). + Say Y or M here if you want to use a secondary head (meaning two + monitors in parallel) on G400 or MGA-TVO add-on on G200. Secondary + head is not compatible with accelerated XFree 3.3.x SVGA servers - + secondary head output is blanked while you are in X. With XFree + 3.9.17 preview you can use both heads if you use SVGA over fbdev or + the fbdev driver on first head and the fbdev driver on second head. + + If you compile it as module, two modules are created, + matroxfb_crtc2.o and matroxfb_maven.o. Matroxfb_maven is needed for + both G200 and G400, matroxfb_crtc2 is needed only by G400. You must + also load i2c-matroxfb to get it to run. + + The driver starts in monitor mode and you must use the matroxset + tool (available at ftp://platan.vc.cvut.cz/pub/linux/matrox-latest) + to switch it to PAL or NTSC or to swap primary and secondary head + outputs. Secondary head driver also always start in 640x480 + resolution, you must use fbset to change it. + + Also do not forget that second head supports only 16 and 32 bpp + packed pixels, so it is a good idea to compile them into the kernel + too. You can use only some font widths, as the driver uses generic + painting procedures (the secondary head does not use acceleration + engine). There is no need for enabling 'Matrox multihead support' if you have only one Matrox card in the box. @@ -3026,16 +3101,17 @@ Matrox unified driver multihead support CONFIG_FB_MATROX_MULTIHEAD Say Y here if you have more than one (supported) Matrox device in - your computer and you want to use all of them. If you have only one - device, you should say N because the driver compiled with Y is - larger and a bit slower, especially on ia32 (ix86). + your computer and you want to use all of them for different monitors + ("multihead"). If you have only one device, you should say N because + the driver compiled with Y is larger and a bit slower, especially on + ia32 (ix86). If you said M to "Matrox unified accelerated driver" and N here, you - will still be able to use several Matrox devices simultaneously. - This is slightly faster but uses 40 KB of kernel memory per Matrox - card. You do this by inserting several instances of the module - matroxfb.o into the kernel with insmod, supplying the parameter - "dev=N" where N is 0, 1, etc. for the different Matrox devices. + will still be able to use several Matrox devices simultaneously: + insert several instances of the module matroxfb.o into the kernel + with insmod, supplying the parameter "dev=N" where N is 0, 1, etc. + for the different Matrox devices. This method is slightly faster but + uses 40 KB of kernel memory per Matrox card. MDA text console (dual-headed) CONFIG_MDA_CONSOLE @@ -3188,12 +3264,6 @@ bits per pixel packed pixels on Mac. It supports variable font widths for low resolution screens. -#VGA 16-color planar support -#CONFIG_FBCON_VGA_PLANES -### -###What is this? -### - VGA characters/attributes support CONFIG_FBCON_VGA This is the low level frame buffer console driver for VGA text mode; @@ -3266,17 +3336,11 @@ other non-standard types of parallel ports. This causes a performance loss, so most people say N. -Sun Ultra/AX-style hardware -CONFIG_PARPORT_AX - Say Y here if you need support for the parallel port hardware on Sun - Ultra/AX machines. This code is also available as a module (say M), - called parport_ax.o. If in doubt, saying N is the safe plan. - Support IEEE1284 status readback CONFIG_PRINTER_READBACK - If you have a device on your parallel port that support this protocol, - this option'll enable it to report its status. - It is safe to say Y. + If you have a device on your parallel port that support this + protocol, this option will allow the device to report its status. It + is safe to say Y. IEEE1284 transfer modes CONFIG_PARPORT_1284 @@ -3366,9 +3430,9 @@ Internet connected Unix computer; for more information, read http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html ). - If you say Y here and also to "/proc file system support" and "Sysctl - support" below, you can change various aspects of the behavior of - the TCP/IP code by writing to the (virtual) files in + If you say Y here and also to "/proc file system support" and + "Sysctl support" below, you can change various aspects of the + behavior of the TCP/IP code by writing to the (virtual) files in /proc/sys/net/ipv4/*; the options are explained in the file Documentation/Networking/ip-sysctl.txt. @@ -3377,7 +3441,7 @@ IP: multicasting CONFIG_IP_MULTICAST This is code for addressing several networked computers at once, - enlarging your kernel by about 2 kB. You need multicasting if you + enlarging your kernel by about 2 KB. You need multicasting if you intend to participate in the MBONE, a high bandwidth network on top of the Internet which carries audio and video broadcasts. More information about the MBONE is on the WWW at @@ -3502,8 +3566,8 @@ echo "1" > /proc/sys/net/ipv4/ip_forward - at boot time after the /proc file system has been mounted. You can do - that even if you say N here. + at boot time after the /proc file system has been mounted. You can + do that even if you say N here. If unsure, say N here. @@ -3511,7 +3575,7 @@ CONFIG_IP_PNP This enables automatic configuration of IP addresses of devices and of the routing table during kernel boot, based on either information - supplied at the kernel command line or by BOOTP or RARP protocols. + supplied on the kernel command line or by BOOTP or RARP protocols. You need to say Y only for diskless machines requiring network access to boot (in which case you want to say Y to "Root file system on NFS" as well), because all other machines configure the network @@ -3633,16 +3697,7 @@ saying Y here. Everyone else says N. People having problems with NCSA telnet should see the file - linux/Documentation/networking/ncsa-telnet. - -Assume subnets are local -CONFIG_INET_SNARL - Say Y if you are on a subnetted network with all machines connected - by Ethernet segments only, as this option optimizes network access - for this special case. If there are other connections, e.g. SLIP - links, between machines of your IP network, say N. If in doubt, - answer N. The PATH mtu discovery facility will cover most cases - anyway. + Documentation/networking/ncsa-telnet. Path MTU Discovery (normally enabled) CONFIG_PATH_MTU_DISCOVERY @@ -3751,6 +3806,20 @@ say Y to "Kernel/User network link driver" and to "Routing messages" instead. +Kernel httpd acceleration (EXPERIMENTAL) +CONFIG_KHTTPD + The kernel httpd acceleration daemon (kHTTPd) is a (limited) + web server built into the kernel. It is limited since it can only + serve files from the file system. Saying "M" here builds the + kHTTPd module; this is NOT enough to have a working kHTTPd. + For safety reasons, the module has to be activated by doing a + "echo 1 > /proc/sys/net/khttpd/start" after inserting the module. + + Before using this, read the README in net/khttpd ! + + The kHTTPd is experimental. Be careful when using it on a production + machine. Also note that kHTTPd doesn't support virtual servers yet. + IPX networking CONFIG_IPX This is support for the Novell networking protocol, IPX, commonly @@ -3760,7 +3829,7 @@ ftp://metalab.unc.edu/pub/Linux/system/filesystems/ ) or from within the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO, available from http://www.linuxdoc.org/docs.html#howto ). In order to do the - former, you'll also have to say Y to "NCP file systems support", + former, you'll also have to say Y to "NCP file system support", below. IPX is similar in scope to IP, while SPX, which runs on top of IPX, @@ -3819,7 +3888,7 @@ Note that Novell NetWare file sharing does not use SPX; it uses a protocol called NCP, for which separate Linux support is available - ("NCP file systems support" below for the client side, and the user + ("NCP file system support" below for the client side, and the user space programs lwared or mars_nwe for the server side). Say Y here if you have use for SPX; read the IPX-HOWTO at @@ -3844,7 +3913,7 @@ More detailed documentation is available in the Documentation/networking/decnet.txt file. - Be sure to say Y to "/proc file systems support" and "Sysctl support" + Be sure to say Y to "/proc file system support" and "Sysctl support" below when using DECnet, since you will need sysctl support to aid in configuration at run time. @@ -3865,22 +3934,28 @@ CONFIG_DECNET_ROUTER Add support for turning your DECnet Endnode into a level 1 or 2 router. This is an unfinished option for developers only. If you do - turn it on, then make sure that you also say Y to "Kernel/User - network link driver", "Routing messages" and "Network packet + say Y here, then make sure that you also say Y to "Kernel/User + network link driver", "Routing messages" and "Network packet filtering". The first two are required to allow configuration via rtnetlink (currently you need Alexey Kuznetsov's iproute2 package - from ftp.inr.ac.ru). The "Network packet filtering" option will - be required for the forthcoming routing daemon to work. + from ftp://ftp.inr.ac.ru). The "Network packet filtering" option + will be required for the forthcoming routing daemon to work. See Documentation/networking/decnet.txt for more information. +DECnet: use FWMARK value as routing key +CONFIG_DECNET_ROUTE_FWMARK + If you say Y here, you will be able to specify different routes for + packets with different FWMARK ("firewalling mark") values + (see ipchains(8), "-m" argument). + Appletalk interfaces support CONFIG_APPLETALK AppleTalk is the way Apple computers speak to each other on a network. If your Linux box is connected to such a network and you want to join the conversation, say Y. -AppleTalk DDP +AppleTalk protocol support CONFIG_ATALK AppleTalk is the way Apple computers speak to each other on a network. If your Linux box is connected to such a network and you @@ -3894,7 +3969,7 @@ supported by Linux. General information about how to connect Linux, Windows machines and - Macs is on the WWW at http://www.eats.com/linux_mac_win.html The + Macs is on the WWW at http://www.eats.com/linux_mac_win.html . The NET-3-HOWTO, available from http://www.linuxdoc.org/docs.html#howto , contains valuable information as well. @@ -4401,17 +4476,23 @@ Ethernet bridge, which means that the different Ethernet segments it is connected to will appear as one Ethernet to the participants. Several such bridges can work together to create even larger - networks of Ethernets using the IEEE 802.1d spanning tree protocol. - As this is a standard, Linux bridges will interwork properly with + networks of Ethernets using the IEEE 802.1 spanning tree algorithm. + As this is a standard, Linux bridges will cooperate properly with other third party bridge products. In order to use the ethernet bridge, you'll need the bridge - configuration tools available from ftp://openrock.net/bridge. Please - read the Bridge mini-HOWTO for more information. Note that if your - box acts as a bridge, it probably contains several Ethernet devices, - but the kernel is not able to recognize more than one at boot time - without help; for details read the Ethernet-HOWTO, available from in - http://www.linuxdoc.org/docs.html#howto . + configuration tools; see Documentation/networking/bridge.txt for + location. Please read the Bridge mini-HOWTO for more information. + + Note that if your box acts as a bridge, it probably contains several + Ethernet devices, but the kernel is not able to recognize more than + one at boot time without help; for details read the Ethernet-HOWTO, + available from in http://www.linuxdoc.org/docs.html#howto . + + If you want to compile this code as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called bridge.o. If unsure, say N. @@ -4491,16 +4572,17 @@ Classical IP over ATM CONFIG_ATM_CLIP Classical IP over ATM for PVCs and SVCs, supporting InARP and - ATMARP. Typically you will either use LAN Emulation (LANE) or - Classical IP to communicate with other IP hosts on your ATM network. + ATMARP. If you want to communication with other IP hosts on your ATM + network, you will typically either say Y here or to "LAN Emulation + (LANE)" below. -Do NOT send ICMP if no neighbor +Do NOT send ICMP if no neighbour CONFIG_ATM_CLIP_NO_ICMP - Normally, an "ICMP host unreachable" message is sent if a neighbor + Normally, an "ICMP host unreachable" message is sent if a neighbour cannot be reached because there is no VC to it in the kernel's ATMARP table. This may cause problems when ATMARP table entries are briefly removed during revalidation. If you say Y here, packets to - such neighbors are silently discarded instead. + such neighbours are silently discarded instead. LAN Emulation (LANE) support CONFIG_ATM_LANE @@ -4524,12 +4606,16 @@ Efficient Networks ENI155P CONFIG_ATM_ENI Driver for the Efficient Networks ENI155p series and SMC ATM - Power155 155 Mbps ATM adapters. Both, the versions with 512kB and + Power155 155 Mbps ATM adapters. Both, the versions with 512KB and 2MB on-board RAM (Efficient calls them "C" and "S", respectively), and the FPGA and the ASIC Tonga versions of the board are supported. The driver works with MMF (-MF or ...F) and UTP-5 (-U5 or ...D) adapters. + This driver is also available as a module. If you want to compile + it as a module, say M here and read Documentation/modules.txt. The + module will be called eni.o. + Enable extended debugging CONFIG_ATM_ENI_DEBUG Extended debugging records various events and displays that list @@ -4610,6 +4696,10 @@ Driver for the ZeitNet ZN1221 (MMF) and ZN1225 (UTP-5) 155 Mbps ATM adapters. + This driver is also available as a module. If you want to compile + it as a module, say M here and read Documentation/modules.txt. The + module will be called zatm.o. + Enable extended debugging CONFIG_ATM_ZATM_DEBUG Extended debugging records various events and displays that list @@ -4632,7 +4722,11 @@ CONFIG_ATM_NICSTAR The NICStAR chipset family is used in a large number of ATM NICs for 25 and for 155 Mbps, including IDT cards and the Fore ForeRunnerLE - series. + series. Say Y if you have one of those. + + This driver is also available as a module. If you want to compile + it as a module, say M here and read Documentation/modules.txt. The + module will be called nicstar.o. ForeRunner LE155 PHYsical layer CONFIG_ATM_NICSTAR_USE_SUNI @@ -4717,6 +4811,35 @@ speed of the driver, and the size of your syslog files! When inactive, they will have only a modest impact on performance. +Linux telephony support +CONFIG_PHONE + Say Y here if you have a telephony card, which for example allows + you to use a regular phone for voice-over-IP applications. + + Note: this has nothing to do with modems. You do not need to say Y + here in order to be able to use a modem under Linux. + + This support is also available as a module. If you want to compile + it as a module, say M here and read Documentation/modules.txt. The + module will be called phonedev.o. + +QuickNet Internet LineJack/PhoneJack support +CONFIG_PHONE_IXJ + Say M if you have a telephony card manufactured by Quicknet + Technologies, Inc. These include the Internet PhoneJACK and + Internet LineJACK Telephony Cards. You will get a module called + ixj.o. + + For the ISA versions of these products, you can configure the + cards using the isapnp tools (pnpdump/isapnp) or you can use the + isapnp support. Please read Documentation/telephony/ixj.txt. + + For more information on these cards, see Quicknet's web site at: + http://www.quicknet.net/ . + + If you do not have any Quicknet telephony cards, you can safely + say N here. + FORE Systems 200E-series CONFIG_ATM_FORE200E This is a driver for the FORE Systems 200E-series ATM adapter @@ -4729,14 +4852,14 @@ Enable PCA-200E card support on PCI-based hosts CONFIG_ATM_FORE200E_PCA - Enable this if you want your PCA-200E cards to be probed. + Say Y here if you want your PCA-200E cards to be probed. Use default PCA-200E firmware CONFIG_ATM_FORE200E_PCA_DEFAULT_FW Use the default PCA-200E firmware data shipped with the driver. Normal users do not have to deal with the firmware stuff, so - this feature is normally enabled. + they should say Y here. Pathname of user-supplied binary firmware CONFIG_ATM_FORE200E_PCA_FW @@ -4744,20 +4867,20 @@ firmware image supplied by the user. This pathname may be absolute or relative to the drivers/atm directory. - The driver comes with an adequate firmware image, so normal users - do not have to supply an alternative one. They just enable the use - of the default firmware instead. + The driver comes with an adequate firmware image, so normal users do + not have to supply an alternative one. They just say Y to "Use + default PCA-200E firmware" instead. Enable SBA-200E card support on SBUS-based hosts CONFIG_ATM_FORE200E_SBA - Enable this if you want your SBA-200E cards to be probed. + Say Y here if you want your SBA-200E cards to be probed. Use default SBA-200E firmware CONFIG_ATM_FORE200E_SBA_DEFAULT_FW Use the default SBA-200E firmware data shipped with the driver. Normal users do not have to deal with the firmware stuff, so - this feature is normally enabled. + they should say Y here. Pathname of user-supplied binary firmware CONFIG_ATM_FORE200E_SBA_FW @@ -4765,9 +4888,9 @@ firmware image supplied by the user. This pathname may be absolute or relative to the drivers/atm directory. - The driver comes with an adequate firmware image, so normal users - do not have to supply an alternative one. They just enable the use - of the default firmware instead. + The driver comes with an adequate firmware image, so normal users do + not have to supply an alternative one. They just say Y to "Use + default SBA-200E firmware", above. Maximum number of tx retries CONFIG_ATM_FORE200E_TX_RETRY @@ -4815,8 +4938,8 @@ The module will be called scsi_mod.o. If you want to compile it as a module, say M here and read Documentation/modules.txt and Documentation/scsi.txt. However, do not compile this as a module if - your root file systems (the one containing the directory /) is located - on a SCSI device. + your root file system (the one containing the directory /) is + located on a SCSI device. SCSI disk support CONFIG_BLK_DEV_SD @@ -4831,15 +4954,15 @@ The module will be called sd_mod.o. If you want to compile it as a module, say M here and read Documentation/modules.txt and Documentation/scsi.txt. Do not compile this driver as a module if - your root file systems (the one containing the directory /) is located - on a SCSI disk. In this case, do not compile the driver for your - SCSI host adapter (below) as a module either. + your root file system (the one containing the directory /) is + located on a SCSI disk. In this case, do not compile the driver for + your SCSI host adapter (below) as a module either. Extra SCSI Disks CONFIG_SD_EXTRA_DEVS This controls the amount of additional space allocated in tables for drivers that are loaded as modules after the kernel is booted. In - the event that the SCSI core itself was loaded as a module, this this + the event that the SCSI core itself was loaded as a module, this value is the number of additional disks that can be loaded after the first host driver is loaded. @@ -4847,6 +4970,8 @@ involved with resizing the internal arrays on the fly. Someday this flag will go away, and everything will work automatically. + If you don't understand what's going on, go with the default. + SCSI tape support CONFIG_CHR_DEV_ST If you want to use a SCSI tape drive under Linux, say Y and read the @@ -4866,7 +4991,7 @@ If you want to use a SCSI CDROM under Linux, say Y and read the SCSI-HOWTO and the CDROM-HOWTO at http://www.linuxdoc.org/docs.html#howto . Also make sure to say Y - or M to "ISO 9660 CDROM file systems support" later. + or M to "ISO 9660 CDROM file system support" later. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -4877,15 +5002,17 @@ Extra SCSI CDROMs CONFIG_SR_EXTRA_DEVS This controls the amount of additional space allocated in tables for - drivers that are loaded as modules after the kernel is booted. In the - event that the SCSI core itself was loaded as a module, this this value - is the number of additional CDROMs that can be loaded after the first - host driver is loaded. + drivers that are loaded as modules after the kernel is booted. In + the event that the SCSI core itself was loaded as a module, this + value is the number of additional CDROMs that can be loaded after + the first host driver is loaded. Admittedly this isn't pretty, but there are tons of race conditions involved with resizing the internal arrays on the fly. Someday this flag will go away, and everything will work automatically. + If you don't understand what's going on, go with the default. + Enable vendor-specific extensions (for SCSI CDROM) CONFIG_BLK_DEV_SR_VENDOR This enables the usage of vendor specific SCSI commands. This is @@ -4899,14 +5026,15 @@ about anything having "SCSI" in its name other than hard disks, CDROMs or tapes, say Y here. These won't be supported by the kernel directly, so you need some additional software which knows how to - talk to these devices using the SCSI protocol. For CD-writers, you - would need the program cdwrite, available from - ftp://metalab.unc.edu/pub/Linux/utils/disk-management ; for other - devices, it's possible that you'll have to write the driver software - yourself, so have a look at the SCSI-HOWTO and at the - SCSI-Programming-HOWTO, both available from - http://www.linuxdoc.org/docs.html#howto . Please read the file - Documentation/scsi-generic.txt for more information. + talk to these devices using the SCSI protocol. For scanners, look at + SANE (www.mostang.com/sane). For CD writer software look at cdrecord + (www.fokus.gmd.de/research/cc/glone/employees/joerg.schilling/private + /cdrecord.html) and for burning a "disk at once": cdrdao + (www.ping.de/sites/daneb/cdrdao.html). Cdparanoia is a high quality + digital reader of audio CDs (www.xiph.org/paranoia). + For other devices, it's possible that you'll have to write the driver + software yourself. Please read the file Documentation/scsi-generic.txt + for more information. If you want to compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), @@ -4916,13 +5044,14 @@ Debug new queueing code for SCSI CONFIG_SCSI_DEBUG_QUEUES - This option turns on a lot of additional consistency checking for the new - queueing code. This will adversely affect performance, but it is likely - that bugs will be caught sooner if this is turned on. This will typically - cause the kernel to panic if an error is detected, but it would have probably - crashed if the panic weren't there. Comments/questions/problems to - linux-scsi mailing list please. See http://www.andante.org/scsi_queue.html - for more uptodate information. + This option turns on a lot of additional consistency checking for + the new queueing code. This will adversely affect performance, but + it is likely that bugs will be caught sooner if this is turned on. + This will typically cause the kernel to panic if an error is + detected, but it would have probably crashed if the panic weren't + there. Comments/questions/problems to linux-scsi mailing list + please. See http://www.andante.org/scsi_queue.html for more + up-to-date information. Probe all LUNs on each SCSI device CONFIG_SCSI_MULTI_LUN @@ -4946,12 +5075,12 @@ of SCSI related problems. If you say Y here, no logging output will appear by default, but you - can enable logging by saying Y to "/proc file systems support" and + can enable logging by saying Y to "/proc file system support" and "Sysctl support" below and executing the command echo "scsi log token [level]" > /proc/scsi/scsi - at boot time after the /proc file systems has been mounted. + at boot time after the /proc file system has been mounted. There are a number of things that can be used for 'token' (you can find them in the source: drivers/scsi/scsi.c), and this allows you @@ -4982,7 +5111,7 @@ It is explained in section 3.3 of the SCSI-HOWTO, available from http://www.linuxdoc.org/docs.html#howto . You might also want to - read the comments at the top of drivers/scsi/aha152x.c. + read the file drivers/scsi/README.aha152x. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -5129,18 +5258,22 @@ after a bus reset to be ready for the next command, but most hard drives and CD-ROM devices are ready in only a few seconds. This option has a maximum upper limit of 20 seconds to avoid bad - interactions between the aic7xxx driver and the rest of the linux + interactions between the aic7xxx driver and the rest of the Linux kernel. The default value has been reduced to 5 seconds. If this doesn't work with your hardware, try increasing this value. IBM ServeRAID Support CONFIG_SCSI_IPS This is support for the IBM ServeRAID hardware RAID controllers. - Consult the SCSI-HOWTO, available via anonymous FTP from - ftp://metalab.unc.edu/pub/Linux/docs/HOWTO, and the file - README.ips in drivers/scsi for more information. If this driver - does not work correctly without modification please contact the - author by email at ipslinux@us.ibm.com. + + Please consult the SCSI-HOWTO, available from + http://www.linuxdoc.org/docs.html#howto . + + You can build this driver as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + but only a single instance may be loaded. If you want to compile it + as a module, say M here and read Documentation/modules.txt. The + module will be called ips.o. BusLogic SCSI support CONFIG_SCSI_BUSLOGIC @@ -5165,6 +5298,15 @@ substantial, so users of MultiMaster Host Adapters may wish to omit it. +DMX3191D SCSI support +CONFIG_SCSI_DMX3191D + This is support for Domex DMX3191D SCSI Host Adapters. + + This driver 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 dmx3191d.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. + DTC3180/3280 SCSI support CONFIG_SCSI_DTC3280 This is support for DTC 3180/3280 SCSI Host Adapters. Please read @@ -5528,9 +5670,7 @@ info like under OS/2, but more informative, by setting 'ibmmcascsi=display' as an additional kernel parameter. Try "man bootparam" or see the documentation of your boot loader about how to - pass options to the kernel. The lilo procedure is also explained in - the SCSI-HOWTO, available from - http://www.linuxdoc.org/docs.html#howto . + pass options to the kernel. If you want to compile this driver as a module ( = code which can be inserted in and removed from the running kernel whenever you want), @@ -5857,13 +5997,32 @@ read Documentation/modules.txt. The module will be called sym53c416.o. +Simple 53c710 SCSI support (Compaq, NCR machines) +CONFIG_SCSI_SIM710 + This is a simple driver for NCR53c710 based SCSI host adapters. + + More complex drivers for this chip are available ("NCR53c7,8xx SCSI + support", above), but they require that the scsi chip be able to do + DMA block moves between memory and on-chip registers, which can + cause problems under certain conditions. This driver is designed to + avoid these problems and is intended to work with any Intel machines + using 53c710 chips, including various Compaq and NCR machines. + + Please read the comments at the top of the file + drivers/scsi/sim710.c for more information. + + If you want to compile this driver as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called sim710.o. + Tekram DC390(T) and Am53/79C974 (PCscsi) SCSI support CONFIG_SCSI_DC390T This driver supports PCI SCSI host adapters based on the Am53C974A chip, e.g. Tekram DC390(T), DawiControl 2974 and some onboard PCscsi/PCnet (Am53/79C974) solutions. - Documentation can be found in linux/drivers/scsi/README.tmscsim. + Documentation can be found in drivers/scsi/README.tmscsim. Note that this driver does NOT support Tekram DC390W/U/F, which are based on NCR/Symbios chips. Use "NCR53C8XX SCSI support" for those. @@ -5881,7 +6040,7 @@ EEPROM to get initial values for its settings, such as speed, termination, etc. If it can't find this EEPROM, it will use defaults or the user supplied boot/module parameters. For details on driver - configuration see linux/drivers/scsi/README.tmscsim. + configuration see drivers/scsi/README.tmscsim. If you say Y here and if no EEPROM is found, the driver gives up and thus only supports Tekram DC390(T) adapters. This can be useful if @@ -6015,21 +6174,28 @@ important data. This is primarily of use to people trying to debug the middle and upper layers of the SCSI subsystem. If unsure, say N. -Fibre Channel support +Fibre Channel support and FC4 SCSI support CONFIG_FC4 - This is an experimental support for storage arrays connected to - the system using Fibre Optic and the "X3.269-199X Fibre Channel - Protocol for SCSI" specification. You'll also need the generic SCSI - support, as well as the drivers for the storage array itself and - for the interface adapter such as SOC or SOC+. This subsystem could even - serve for IP networking, with some code extensions. If unsure, say N. + Fibre Channel is a high speed serial protocol mainly used to + connect large storage devices to the computer; it is compatible with + and intended to replace SCSI. + + This is an experimental support for storage arrays connected to your + computer using optical fibre cables and the "X3.269-199X Fibre + Channel Protocol for SCSI" specification. If you want to use this, + you need to say Y here and to "SCSI support" as well as to the + drivers for the storage array itself and for the interface adapter + such as SOC or SOC+. This subsystem could even serve for IP + networking, with some code extensions. + + If unsure, say N. Sun SOC CONFIG_FC4_SOC Serial Optical Channel is an interface card with one or two Fibre - Optic ports, each of which can be connected to a disk array. Note that - if you have older firmware in the card, you'll need the microcode from - the Solaris driver to make it work. + Optic ports, each of which can be connected to a disk array. Note + that if you have older firmware in the card, you'll need the + microcode from the Solaris driver to make it work. This support is also available as a module called soc.o ( = code which can be inserted in and removed from the running kernel @@ -6038,11 +6204,11 @@ Sun SOC+ (aka SOCAL) CONFIG_FC4_SOCAL - Serial Optical Channel Plus is an interface card with up to two Fibre - Optic ports. This card supports FC Arbitrated Loop (usually A5000 or - internal FC disks in E[3-6]000 machines through the Interface Board). - You'll probably need the microcode from the Solaris driver to make it - work. + Serial Optical Channel Plus is an interface card with up to two + Fibre Optic ports. This card supports FC Arbitrated Loop (usually + A5000 or internal FC disks in E[3-6]000 machines through the + Interface Board). You'll probably need the microcode from the + Solaris driver to make it work. This support is also available as a module called socal.o ( = code which can be inserted in and removed from the running kernel @@ -6060,9 +6226,9 @@ Sun Enterprise Network Array (A5000 and EX500) CONFIG_SCSI_FCAL - This driver drives FC-AL disks connected through a Fibre Channel card - using the drivers/fc4 layer (currently only SOCAL). - The most common is either A5000 array or internal disks in E[3-6]000 + This driver drives FC-AL disks connected through a Fibre Channel + card using the drivers/fc4 layer (currently only SOCAL). The most + common is either A5000 array or internal disks in E[3-6]000 machines. This support is also available as a module called fcal.o ( = code @@ -6123,55 +6289,125 @@ This enables support for the Powertec SCSI card on Acorn systems. If you have one of these, say Y. If unsure, say N. -Network device support? -CONFIG_NETDEVICES - You can say N here if you don't intend to connect your Linux box to - any other computer at all or if all your connections will be over a - telephone line with a modem either via UUCP (UUCP is a protocol to - forward mail and news between unix hosts over telephone lines; read - the UUCP-HOWTO, available from - http://www.linuxdoc.org/docs.html#howto ) or dialing up a shell - account or a BBS, even using term (term is a program which gives you - almost full Internet connectivity if you have a regular dial up - shell account on some Internet connected Unix computer. Read - http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html ). +IEEE 1394 (aka FireWire) support +CONFIG_IEEE1394 + IEEE 1394 describes a high performance serial bus, which is also + known as FireWire(tm) or i.Link(tm) and is used for connecting all + sorts of devices (most notably digital video cameras) to your + computer. - You'll have to say Y if your computer contains a network card that - you want to use under Linux (make sure you know its name because you - will be asked for it and read the Ethernet-HOWTO (especially if you - plan to use more than one network card under Linux)) or if you want - to use SLIP (Serial Line Internet Protocol is the protocol used to - send Internet traffic over telephone lines or null modem cables) or - CSLIP (compressed SLIP) or PPP (Point to Point Protocol, a better - and newer replacement for SLIP) or PLIP (Parallel Line Internet - Protocol is mainly used to create a mini network by connecting the - parallel ports of two local machines) or AX.25/KISS (protocol for - sending Internet traffic over amateur radio links). + If you have FireWire hardware and want to use it, say Y here. This + is the core support only, you will also need to select a driver for + your IEEE 1394 adapter. - Make sure to read the NET-3-HOWTO. Eventually, you will have to read - Olaf Kirch's excellent and free book "Network Administrator's - Guide", to be found in ftp://metalab.unc.edu/pub/Linux/docs/LDP . If - unsure, say Y. + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called ieee1394.o. -Bonding driver support -CONFIG_BONDING - Say 'Y' or 'M' if you wish to be able to 'bond' multiple Ethernet - Channels together. This is called 'Etherchannel' by Cisco, 'Trunking' - by Sun, and 'Bonding' in Linux. +TI PCILynx IEEE 1394 support +CONFIG_IEEE1394_PCILYNX + Say Y here if you have a IEEE-1394 controller with the Texas + Instruments PCILynx chip. Note: this driver is written for revision + 2 of this chip and may not work with revision 0. - If you have two ethernet connections to some other computer, you can - make them behave like one double speed connection using this driver. - Naturally, this has to be supported at the other end as well, either - with a similar Bonding Linux driver, a Cisco 5500 switch or a - SunTrunking SunSoft driver. + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called pcilynx.o. + +Use local RAM on PCILynx board +CONFIG_IEEE1394_PCILYNX_LOCALRAM + This option makes the PCILynx driver use local RAM available on some + PCILynx setups for Packet Control Lists. Local RAM is random access + memory which resides on the PCILynx board as opposed to on your + computer's motherboard. Local RAM may speed up command processing + because no PCI transfers are necessary during use of the Packet + Control Lists. + + Note that there are no known PCILynx systems providing local RAM + except for the evaluation boards by Texas Instruments and that the + PCILynx does not reliably report missing RAM. This means that it is + dangerous to say Y here if you are not absolutely sure that your + board provides 64KB of local RAM. - This is similar to the EQL driver, but it merge ethernet segments instead - of serial lines. + If unsure, say N. + +Adaptec AIC-5800 IEEE 1394 support +CONFIG_IEEE1394_AIC5800 + Say Y here if you have a IEEE 1394 controller using the Adaptec + AIC-5800 chip. All Adaptec host adapters (89xx series) use this + chip, as well as miro's DV boards. If you want to compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read Documentation/modules.txt. The module will be - called bonding.o. + called aic5800.o. + +OHCI (Open Host Controller Interface) support +CONFIG_IEEE1394_OHCI1394 + Say Y here if you have a IEEE 1394 controller based on OHCI. + The current driver was only tested with OHCI chipsets made + by Texas Instruments. However, most third-party vendors use + TI chips. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called ohci1394.o. + +Raw IEEE 1394 I/O support +CONFIG_IEEE1394_RAWIO + Say Y here if you want support for the raw device. This is generally + a good idea, so you should say Y here. The raw device enables + direct communication of user programs with the IEEE 1394 bus and + thus with the attached peripherals. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called raw1394.o. + +Excessive debugging output +CONFIG_IEEE1394_VERBOSEDEBUG + If you say Y here, you will get very verbose debugging logs from the + subsystem which includes a dump of the header of every sent and + received packet. This can amount to a high amount of data collected + in a very short time which is usually also saved to disk by the + system logging daemons. + + Say Y if you really want or need the debugging output, everyone else + says N. + +Network device support? +CONFIG_NETDEVICES + You can say N here if you don't intend to connect your Linux box to + any other computer at all or if all your connections will be over a + telephone line with a modem either via UUCP (UUCP is a protocol to + forward mail and news between unix hosts over telephone lines; read + the UUCP-HOWTO, available from + http://www.linuxdoc.org/docs.html#howto ) or dialing up a shell + account or a BBS, even using term (term is a program which gives you + almost full Internet connectivity if you have a regular dial up + shell account on some Internet connected Unix computer. Read + http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html ). + + You'll have to say Y if your computer contains a network card that + you want to use under Linux (make sure you know its name because you + will be asked for it and read the Ethernet-HOWTO (especially if you + plan to use more than one network card under Linux)) or if you want + to use SLIP (Serial Line Internet Protocol is the protocol used to + send Internet traffic over telephone lines or null modem cables) or + CSLIP (compressed SLIP) or PPP (Point to Point Protocol, a better + and newer replacement for SLIP) or PLIP (Parallel Line Internet + Protocol is mainly used to create a mini network by connecting the + parallel ports of two local machines) or AX.25/KISS (protocol for + sending Internet traffic over amateur radio links). + + Make sure to read the NET-3-HOWTO. Eventually, you will have to read + Olaf Kirch's excellent and free book "Network Administrator's + Guide", to be found in http://www.linuxdoc.org/docs.html#guide . If + unsure, say Y. Dummy net driver support CONFIG_DUMMY @@ -6183,7 +6419,7 @@ thing often comes in handy, the default is Y. It won't enlarge your kernel either. What a deal. Read about it in the Network Administrator's Guide, available from - http://metalab.unc.edu/mdw/linux.html#guide . + http://www.linuxdoc.org/docs.html#guide . If you want to compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), @@ -6192,6 +6428,26 @@ time, you need to compile this driver as a module. Instead of 'dummy', the devices will then be called 'dummy0', 'dummy1' etc. +Bonding driver support +CONFIG_BONDING + Say 'Y' or 'M' if you wish to be able to 'bond' multiple Ethernet + Channels together. This is called 'Etherchannel' by Cisco, + 'Trunking' by Sun, and 'Bonding' in Linux. + + If you have two ethernet connections to some other computer, you can + make them behave like one double speed connection using this driver. + Naturally, this has to be supported at the other end as well, either + with a similar Bonding Linux driver, a Cisco 5500 switch or a + SunTrunking SunSoft driver. + + This is similar to the EQL driver, but it merges Ethernet segments + instead of serial lines. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called bonding.o. + SLIP (serial line) support CONFIG_SLIP Say Y if you intend to use SLIP or CSLIP (compressed SLIP) to @@ -6231,11 +6487,11 @@ on both ends. Ask your access provider if you are not sure and answer Y, just in case. You will still be able to use plain SLIP. If you plan to use SLiRP, the SLIP emulator (available from - ftp://metalab.unc.edu/pub/Linux/system/network/serial/ ) which allows - you to use SLIP over a regular dial up shell connection, you + ftp://metalab.unc.edu/pub/Linux/system/network/serial/ ) which + allows you to use SLIP over a regular dial up shell connection, you definitely want to say Y here. The NET-3-HOWTO, available from - http://www.linuxdoc.org/docs.html#howto , explains how to - configure CSLIP. This won't enlarge your kernel. + http://www.linuxdoc.org/docs.html#howto , explains how to configure + CSLIP. This won't enlarge your kernel. Keepalive and linefill CONFIG_SLIP_SMART @@ -6296,6 +6552,7 @@ into and removed from the running kernel). If you want to compile it as a module, say M here and read Documentation/modules.txt. +PPP support for sync tty ports CONFIG_PPP_SYNC_TTY Say Y (or M) here if you want to be able to use PPP over synchronous (HDLC) tty devices, such as the SyncLink adapter. These devices @@ -6338,10 +6595,20 @@ Wireless LAN (non-hamradio) CONFIG_NET_RADIO Support for wireless LANs and everything having to do with radio, - but not with amateur radio. Note that the answer to this question - won't directly affect the kernel: saying N will just cause this - configure script to skip all the questions about radio - interfaces. + but not with amateur radio or FM broadcasting. + + Saying Y here also enables the Wireless Extensions (creates + /proc/net/wireless and enables ifconfig access). The Wireless + Extension is a generic API allowing a driver to expose to the user + space configuration and statistics specific to common Wireless LANs. + The beauty of it is that a single set of tool can support all the + variations of Wireless LANs, regardless of their type (as long as + the driver supports Wireless Extension). Another advantage is that + these parameters may be changed on the fly without restarting the + driver (or Linux). If you wish to use Wireless Extensions with + wireless PCMCIA (PC-) cards, you need to say Y here; you can fetch + the tools from + http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html . Some user-level drivers for scarab devices which don't require special kernel support are available from @@ -6388,8 +6655,8 @@ in the source code drivers/net/wavelan.p.h. You will also need the wireless tools package available from - ftp://hyper.stanford.edu/pub/pcmcia/contrib/ . Please read the man - pages contained therein. + http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html . + Please read the man pages contained therein. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -6402,95 +6669,109 @@ Aironet makes Arlan, a class of wireless LAN adapters. These use the www.Telxon.com chip, which is also used on several similar cards. This driver is tested on the 655 and IC2200 series cards. Look at - http://www.ylenurme.ee/~elmer/655/ for latest information. + http://www.ylenurme.ee/~elmer/655/ for the latest information. The driver is built as two modules, arlan and arlan-proc. The latter is the /proc interface and is not needed most of time. - On some computers the card ends up in non-valid state after some time. - Use a ping-reset script to clear it. + On some computers the card ends up in non-valid state after some + time. Use a ping-reset script to clear it. Aironet 4500/4800 series adapters CONFIG_AIRONET4500 www.aironet.com (recently bought by Cisco) makes these 802.11 DS adapters. Driver by Elmer Joandi (elmer@ylenurme.ee). - Work sponsored by www.spectrumwireless.net and www.vendomar.ee - This configuration option enables common code for all devices (PCI, ISA, - PCMCIA) - module is aironet4500_core + + Say Y here if you have such an adapter, and then say Y below to + the option that applies to your particular type of card (PCI, ISA, + or PCMCIA). + + This driver 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 aironet4500_core.o. If you want to + compile it as a module, say M here and read + Documentation/modules.txt as well as + Documentation/networking/net-modules.txt. + quick config parameters: SSID=tsunami - "The Password" adhoc=1 there are no Access Points around - master=1 Adhoc master (the one who creates network sync) - slave=1 Adhoc slave(btw, it is still forming own net + master=1 Adhoc master (the one who creates network + sync) + slave=1 Adhoc slave (btw, it is still forming own net sometimes, and has problems with firmware... change IbssJoinNetTimeout from /proc...) channel=1..? meaningful in adhoc mode - all other parameters can be set via /proc interface - These parameters belong to .._card module, but alas, they are here - if you have problems with screwing up card, both_bap_lock=1 is conservative - value (performance hit 15%) - for any other configuration options look at ..._proc module + + If you have problems with screwing up card, both_bap_lock=1 is a + conservative value (performance hit 15%). + + All other parameters can be set via the proc interface. Aironet 4500/4800 ISA/PCI/PNP/365 support CONFIG_AIRONET4500_NONCS - This is module aironet4500_card, which includes _possibility_ to - support for following - PCI device - ISA device in ISA mode(does not work currently) - ISA device in PNP mode - PCMCIA device _without_ cardservices, direct 365 chip INIT, - does not work currently - PCMCIA _with_ CardServices(normal way) is at another module - radio parameters are currently configurable at ..._core module + If you have an ISA, PCI or PCMCIA Aironet 4500/4800 wireless LAN + card, say Y here, and then also to the options below that apply + to you. + + This driver 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 aironet4500_card.o. If you want to + compile it as a module, say M here and read + Documentation/modules.txt Aironet 4500/4800 PNP support CONFIG_AIRONET4500_PNP - This option should be enabled for ISA cards, remember to enable - PNP jumper on board. - module aironet4500_card + If you have an ISA Aironet 4500/4800 card which you want to use in + PNP (Plug and Play) mode, say Y here. This is the recommended mode + for ISA cards. Remember however to enable the PNP jumper on the + board if you say Y here. Aironet 4500/4800 PCI support CONFIG_AIRONET4500_PCI - This option should be enabled for PCI cards - module aironet4500_card + If you have an PCI Aironet 4500/4800 card, say Y here. Aironet 4500/4800 ISA broken support (EXPERIMENTAL) CONFIG_AIRONET4500_ISA - This option enables support for ISA cards in non-PNP mode. - Does not operate correctly by now. - module aironet4500_card + If you have an ISA Aironet 4500/4800 card which you want to run in + non-PNP mode, say Y here. This is not recommended and does not work + correctly at this point. Say N. Aironet 4500/4800 I365 broken support (EXPERIMENTAL) CONFIG_AIRONET4500_I365 - This option enables support for PCMCIA cards on i365 controller - _without_ cardservices. Doesn't have much sense and is not working - properly. Comes from times where there was no PCMCIA support in - kernel main source tree + If you have a PCMCIA Aironet 4500/4800 card which you want to use + without the standard PCMCIA cardservices provided by the pcmcia-cs + package, say Y here. This is not recommended, so say N. Aironet 4500/4800 PCMCIA support CONFIG_AIRONET4500_CS - This option enables support for PCMCIA cards to be used with - CardServices. - This is not for ISA and PCI adapters. - module aironet4500_cs.o - The same option is both on: - 1. PCMCIA netdevices configuring panel - 2. Wireless netdevices configuring panel - Possibility to change this option depends on options set in 2. + Say Y here if you have a PCMCIA Aironet 4500/4800 card which you + want to use with the standard PCMCIA cardservices provided by the + pcmcia-cs package. + + This driver 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 aironet4500_cs.o. If you want to + compile it as a module, say M here and read + Documentation/modules.txt. Aironet 4500/4800 PROC interface CONFIG_AIRONET4500_PROC - This option enables /proc/sys/aironet4500 interface for - configuring the device. - NOTE: it takes lot of memory. Compile it as module and remove - after configuration - module: aironet4500_proc - additional info: look into drivers/net/aironet4500_rids.c - this is quite human-readable(no need to know C) + If you say Y here (and to the "/proc file system" below), you will + be able to configure your Aironet card via the + /proc/sys/aironet4500 interface. + Additional info: look in drivers/net/aironet4500_rids.c. - + This driver 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 aironet4500_proc.o. If you want to + compile it as a module, say M here and read + Documentation/modules.txt. + + NOTE: the proc interface uses a lot of memory, so it is recommended + to compile it as a module and remove the module after + configuration. LAPB over Ethernet driver CONFIG_LAPBETHER @@ -6520,8 +6801,18 @@ PCMCIA network device support CONFIG_NET_PCMCIA - Say Y if you would like to include support for any PCMCIA network - adapters. If unsure, say N. + Say Y if you would like to include support for any PCMCIA or CardBus + network adapters, then say Y to the driver for your particular card + below. PCMCIA- or PC-cards are credit-card size devices often used + with laptops computers; CardBus is the newer and faster version of + PCMCIA. + + To use your PC-cards, you will need supporting software from David + Hinds' pcmcia-cs package (see the file Documentation/Changes for + location). You also want to check out the PCMCIA-HOWTO, available + from http://www.linuxdoc.org/docs.html#howto . + + If unsure, say N. 3Com 3c589 PCMCIA support CONFIG_PCMCIA_3C589 @@ -6552,8 +6843,8 @@ This driver 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 fmvj18x_cs.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. If unsure, + The module will be called fmvj18x_cs.o. If you want to compile it as + a module, say M here and read Documentation/modules.txt. If unsure, say N. NE2000 compatible PCMCIA support @@ -6574,8 +6865,8 @@ This driver 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 nmclan_cs.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. If unsure, + The module will be called nmclan_cs.o. If you want to compile it as + a module, say M here and read Documentation/modules.txt. If unsure, say N. SMC 91Cxx PCMCIA support @@ -6585,9 +6876,9 @@ This driver 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 smc91c92_cs.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. If unsure, - say N. + The module will be called smc91c92_cs.o. If you want to compile it + as a module, say M here and read Documentation/modules.txt. If + unsure, say N. Xircom 16-bit PCMCIA support CONFIG_PCMCIA_XIRC2PS @@ -6596,10 +6887,21 @@ This driver 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 xirc2ps_cs.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. If unsure, + The module will be called xirc2ps_cs.o. If you want to compile it as + a module, say M here and read Documentation/modules.txt. If unsure, say N. +COM20020 ARCnet PCMCIA support +CONFIG_ARCNET_COM20020_CS + Say Y here if you intend to attach this type of ARCnet PCMCIA card + to your computer. + + This driver 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 com20020_cs.o. If you want to compile it + as a module, say M here and read Documentation/modules.txt. If + unsure, say N. + 3Com 3c575 CardBus support CONFIG_PCMCIA_3C575 This driver supports the 3Com 3c575 series of CardBus Fast Ethernet @@ -6610,20 +6912,36 @@ The module will be called 3c575_cb.o. If you want to do that, say M here and read Documentation/modules.txt. If unsure, say N. -SMC EPIC CardBus support -CONFIG_PCMCIA_EPIC100 - This driver supports CardBus Fast Ethernet adapters based on the SMC - EPIC chipset. +Xircom Tulip-like CardBus support +CONFIG_PCMCIA_XIRTULIP + This driver is for the Digital "Tulip" Ethernet CardBus adapters. + It should work with most DEC 21*4*-based chips/ethercards, as well + as with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and + ASIX. - This driver can only be compiled as a module ( = code which can be + This driver 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 epic100_cb.o. If you want to do that, say - M here and read Documentation/modules.txt. If unsure, say N. + The module will be called xircom_tulip_cb.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. If + unsure, say N. + +Pcmcia Wireless LAN +CONFIG_NET_PCMCIA_RADIO + Say Y here if you would like to use a PCMCIA (PC-card) device to + connect to a wireless local area network. Then say Y to the driver + for your particular card below. + + To use your PC-cards, you will need supporting software from David + Hinds' pcmcia-cs package (see the file Documentation/Changes for + location). You also want to check out the PCMCIA-HOWTO, available + from http://www.linuxdoc.org/docs.html#howto . Aviator/Raytheon 2.4MHz wireless support CONFIG_PCMCIA_RAYCS Say Y here if you intend to attach an Aviator/Raytheon PCMCIA (PC-card) wireless Ethernet networking card to your computer. + Please read the file Documentation/networking/ray_cs.txt for + details. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -6633,13 +6951,13 @@ Xircom Netwave AirSurfer wireless support CONFIG_PCMCIA_NETWAVE - Say Y here if you intend to attach a Xircom Netwave AirSurfer PCMCIA - (PC-card) wireless Ethernet networking card to your computer. + Say Y here if you intend to attach this type of PCMCIA (PC-card) + wireless Ethernet networking card to your computer. This driver 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 netwave_cs.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. If unsure, + The module will be called netwave_cs.o. If you want to compile it as + a module, say M here and read Documentation/modules.txt. If unsure, say N. AT&T/Lucent Wavelan wireless support @@ -6650,8 +6968,8 @@ This driver 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 wavelan_cs.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. If unsure, + The module will be called wavelan_cs.o. If you want to compile it as + a module, say M here and read Documentation/modules.txt. If unsure, say N. PLIP (parallel port) support @@ -6814,17 +7132,6 @@ Say Y here if you have a native Econet network card installed in your computer. -Wan interfaces support -CONFIG_WAN - Wide Area Networks (WANs), such as X.25, frame relay and leased - lines, are used to interconnect Local Area Networks (LANs) over vast - distances with data transfer rates significantly higher than those - achievable with commonly used asynchronous modem connections. - - Say Y here if you want to use such interconnections. - - It is safe to say N. Most people won't need it. - WAN Router CONFIG_WAN_ROUTER Wide Area Networks (WANs), such as X.25, frame relay and leased @@ -6850,18 +7157,6 @@ If unsure, say N. -WAN router drivers -CONFIG_WAN_ROUTER_DRIVERS - Wide Area Networks (WANs), such as X.25, frame relay and leased - lines, are used to interconnect Local Area Networks (LANs) over vast - distances with data transfer rates significantly higher than those - achievable with commonly used asynchronous modem connections. - Usually, a quite expensive external device called a `WAN router' is - needed to connect to a WAN. - - Say Y here will enable the kernel to a??? as a WAN router betwenn LAN by - means of WAN adapters. - Fast switching (read help!) CONFIG_NET_FASTROUTE Saying Y here enables direct NIC-to-NIC (NIC = Network Interface @@ -6917,9 +7212,15 @@ That package also contains some documentation; for more, check out http://snafu.freedom.org/linux2.2/iproute-notes.html . - If you say Y here and to "/proc file system support" below, you will - be able to read status information about packet schedulers from the - file /proc/net/psched. + This Quality of Service (QoS) support will enable you to use + Differentiated Services (diffserv) and Resource Reservation Protocol + (RSVP) on your Linux router if you also say Y to "QoS support", + "Packet classifier API" and to some classifiers below. Documentation + and software is at http://icawwww1.ipfl.ch/linux/diffserv/ . + + If you say Y here and to "/proc file system" below, you will be able + to read status information about packet schedulers from the file + /proc/net/psched. The available schedulers are listed in the following questions; you can say Y to as many as you like. If unsure, say N now. @@ -7030,12 +7331,23 @@ whenever you want). If you want to compile it as a module, say M here and read Documentation/modules.txt. +### Add these +#+tristate ' GRED queue' CONFIG_NET_SCH_GRED +#+tristate ' Diffserv field marker' CONFIG_NET_SCH_DSMARK +#+tristate ' Ingress Qdisc' CONFIG_NET_SCH_INGRESS + QoS support CONFIG_NET_QOS Say Y here if you want to include Quality Of Service scheduling features, which means that you will be able to request certain rate-of-flow limits for your network devices. + This Quality of Service (QoS) support will enable you to use + Differentiated Services (diffserv) and Resource Reservation Protocol + (RSVP) on your Linux router if you also say Y to "Packet classifier + API" and to some classifiers below. Documentation and software is at + http://icawwww1.ipfl.ch/linux/diffserv/ . + Note that the answer to this question won't directly affect the kernel: saying N will just cause this configure script to skip all the questions about QoS support. @@ -7054,8 +7366,16 @@ choice of several different packet classifiers with the following questions. + This will enable you to use Differentiated Services (diffserv) and + Resource Reservation Protocol (RSVP) on your Linux router. + Documentation and software is at + http://icawwww1.ipfl.ch/linux/diffserv/ . + +### Add +#tristate ' TC index classifier' CONFIG_NET_CLS_TCINDEX + Routing tables based classifier -CONFIG_NET_CLS_ROUTE +CONFIG_NET_CLS_ROUTE4 If you say Y here, you will be able to classify outgoing packets according to the route table entry they matched. If unsure, say Y. @@ -7114,7 +7434,7 @@ here and read Documentation/modules.txt # -# Ingres traffic policing +# Traffic policing (needed for in/egress) # CONFIG_NET_CLS_POLICE ### ### Some expert please fill these in @@ -7127,6 +7447,22 @@ performance will be written to /proc/net/profile. If you don't know what it is about, you don't need it: say N. +Wan interfaces support +CONFIG_WAN + Wide Area Networks (WANs), such as X.25, frame relay and leased + lines, are used to interconnect Local Area Networks (LANs) over vast + distances with data transfer rates significantly higher than those + achievable with commonly used asynchronous modem connections. + Usually, a quite expensive external device called a `WAN router' is + needed to connect to a WAN. + + As an alternative, a relatively inexpensive WAN interface card can + allow your Linux box to directly connect to a WAN. If you have one + of those cards and wish to use it under Linux, say Y here and also + to the WAN driver for your card, below. + + If unsure, say N. + Comtrol Hostess SV-11 support CONFIG_HOSTESS_SV11 This is a network card for low speed synchronous serial links, at @@ -7158,16 +7494,24 @@ Fibre Channel driver support CONFIG_NET_FC - Say Y here provide support for storage arrays connected to - the system using Fibre Optic and the "X3.269-199X Fibre Channel - Protocol for SCSI" specification. You'll also need the generic SCSI - support, as well as the drivers for the storage array itself and - for the interface adapter such as SOC or SOC+. This subsystem could even - serve for IP networking, with some code extensions. If unsure, say N. - -# Interphase 5526 Tachyon chipset based adaptor support -# CONFIG_IPHASE5526 + Fibre Channel is a high speed serial protocol mainly used to connect + large storage devices to the computer; it is compatible with and + intended to replace SCSI. + + If you intend to use Fibre Channel, you need to have a Fibre channel + adaptor card in your computer; say Y here and to the driver for your + adaptor below. You also should have said Y to "SCSI support" and + "SCSI generic support". + +Interphase 5526 Tachyon chipset based adaptor support +CONFIG_IPHASE5526 + Say Y here if you have a Fibre Channel adaptor of this kind. + The driver 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 iph5526.o. For general information about + modules read Documentation/modules.txt. + Red Creek Hardware VPN (EXPERIMENTAL) CONFIG_RCPCI This is a driver for hardware which provides a Virtual Private @@ -7178,43 +7522,46 @@ whenever you want). If you want to compile it as a module, say M here and read Documentation/modules.txt. -SBNI Leased Line Adapters +SBNI12-xx support CONFIG_SBNI - This is a driver for ISA SBNI12-xx cards that is a low cost - alternative to leased line modems. Say Y if you want to insert - driver into kernel or say M to compile driver as a module. + This is a driver for ISA SBNI12-xx cards which are low cost + alternatives to leased line modems. Say Y if you want to insert + the driver into the kernel or say M to compile it as a module (the + module will be called sbni.o). You can find more information and last versions of drivers and - utilities at http://www.granch.ru. If you have any question you - can mail to sbni@granch.ru. + utilities at http://www.granch.ru . If you have any question you + can send email to sbni@granch.ru. Say N if unsure. - -WAN Drivers -CONFIG_WAN_DRIVERS - Say Y to this option if your Linux box contains a WAN card and you - are planning to use the box as a WAN ( = Wide Area Network) router - ( = device used to interconnect local area networks over wide area - communication links, such as leased lines or public data networks, - e.g. X.25 or frame relay) and you will be offered a list of drivers - for WAN cards currently available. For more information, read - Documentation/networking/wan-router.txt. + +WAN router drivers +CONFIG_WAN_ROUTER_DRIVERS + If you have a WAN interface card and you want your Linux box to act + as a WAN router, thereby connecting you Local Area Network to the + outside world over the WAN connection, say Y here and then to the + driver for your card below. In addition, you need to say Y to "Wan + Router". + + You will need the wan-tools package which is available from + ftp://ftp.sangoma.com . Read Documentation/networking/wan-router.txt + for more information. Note that the answer to this question won't directly affect the kernel: saying N will just cause this configure script to skip all - the questions about WAN card drivers. If unsure, say N. + the questions about WAN router drivers. If unsure, say N. Sangoma WANPIPE(tm) multiprotocol cards CONFIG_VENDOR_SANGOMA - WANPIPE from Sangoma Technologies Inc. (http://www.sangoma.com ) is a - family of intelligent multiprotocol WAN adapters with data transfer - rates up to T1 (1.544 Mbps). They are also known as Synchronous Data - Link Adapters (SDLA) and designated S502E(A), S503 or S508. These - cards support the X.25, Frame Relay, and PPP protocols. If you have - one or more of these cards, say Y to this option; you may then also - want to read the file Documentation/networking/wanpipe.txt. The next - questions will ask you about the protocols you want the driver to - support. + WANPIPE from Sangoma Technologies Inc. (http://www.sangoma.com ) is + a family of intelligent multiprotocol WAN adapters with data + transfer rates up to T1 (1.544 Mbps). They are also known as + Synchronous Data Link Adapters (SDLA) and designated S502E(A), S503 + or S508. These cards support the X.25, Frame Relay, and PPP + protocols. If you have one or more of these cards, say Y to this + option; you may then also want to read the file + Documentation/networking/wanpipe.txt. The next questions will ask + you about the protocols you want the driver to support. The driver will be compiled as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -7229,6 +7576,13 @@ re-compiling the driver, but remember that in this case you'll waste some kernel memory (about 1K per card). +WANPIPE Cisco HDLC support +CONFIG_WANPIPE_CHDLC + Say Y to this option if you are planning to connect a WANPIPE card + to a connection which uses the synchronous Cisco HDLC (High-level + Data Link Control) protocol. This protocol is often used on + high-speed leased lines like T1/E1. + WANPIPE X.25 support CONFIG_WANPIPE_X25 Say Y to this option if you are planning to connect a WANPIPE card @@ -7255,13 +7609,13 @@ MultiGate/COMX support CONFIG_COMX - Say Y if you want to use any board from the MultiGate (COMX) family. - These boards are synchronous serial adapters for the PC, manufactured - by ITConsult-Pro Co, Hungary. - - Read linux/Documentation/networking/comx.txt for help on configuring - and using COMX interfaces. Further info on these cards can be found at - http://www.itc.hu or . + Say Y if you want to use any board from the MultiGate (COMX) family. + These boards are synchronous serial adapters for the PC, + manufactured by ITConsult-Pro Co, Hungary. + + Read linux/Documentation/networking/comx.txt for help on configuring + and using COMX interfaces. Further info on these cards can be found + at http://www.itc.hu or . If you want to compile this as a module, say M and read Documentation/modules.txt. The module will be called comx.o. @@ -7279,30 +7633,34 @@ LoCOMX board support CONFIG_COMX_HW_LOCOMX - Hardware driver for the 'LoCOMX' board from the MultiGate family. Say Y - if you have a board like this. + Hardware driver for the 'LoCOMX' board from the MultiGate family. + Say Y if you have a board like this. If you want to compile this as a module, say M and read - Documentation/modules.txt. The module will be called comx-hw-locomx.o. + Documentation/modules.txt. The module will be called + comx-hw-locomx.o. MixCOM board support CONFIG_COMX_HW_MIXCOM - Hardware driver for the 'MixCOM' board from the MultiGate family. Say Y - if you have a board like this. + Hardware driver for the 'MixCOM' board from the MultiGate family. + Say Y if you have a board like this. If you want to use the watchdog device on this card, you should select it in the Watchdog Cards section of the Character Devices - configuration. The ISDN interface of this card is Teles 16.3 compatible, - you should enable it in the ISDN configuration menu. The driver for the - flash ROM of this card is available separately on ftp://ftp.itc.hu/. + configuration. The ISDN interface of this card is Teles 16.3 + compatible, you should enable it in the ISDN configuration menu. The + driver for the flash ROM of this card is available separately on + ftp://ftp.itc.hu/. If you want to compile this as a module, say M and read - Documentation/modules.txt. The module will be called comx-hw-mixcom.o. + Documentation/modules.txt. The module will be called + comx-hw-mixcom.o. MultiGate Cisco-HDLC and synchronous PPP protocol support CONFIG_COMX_PROTO_PPP - Cisco-HDLC and synchronous PPP protocol driver for all MultiGate boards. - Say Y if you want to use either protocol on your MultiGate boards. + Cisco-HDLC and synchronous PPP protocol driver for all MultiGate + boards. Say Y if you want to use either protocol on your MultiGate + boards. If you want to compile this as a module, say M and read Documentation/modules.txt. The module will be called @@ -7314,7 +7672,8 @@ want to use this protocol on your MultiGate boards. If you want to compile this as a module, say M and read - Documentation/modules.txt. The module will be called comx-proto-lapb.o. + Documentation/modules.txt. The module will be called + comx-proto-lapb.o. MultiGate Frame Relay protocol support CONFIG_COMX_PROTO_FR @@ -7322,7 +7681,8 @@ want to use this protocol on your MultiGate boards. If you want to compile this as a module, say M and read - Documentation/modules.txt. The module will be called comx-proto-fr.o. + Documentation/modules.txt. The module will be called + comx-proto-fr.o. Cyclom 2X(tm) multiprotocol cards (EXPERIMENTAL) CONFIG_CYCLADES_SYNC @@ -7343,7 +7703,7 @@ Feel free to contact me or the cycsyn-devel mailing list at acme@conectiva.com.br and cycsyn-devel@bazar.conectiva.com.br for additional details, I hope to have documentation available as soon - as possible (Cyclades Brazil is writing the Documentation). + as possible. (Cyclades Brazil is writing the Documentation). The driver will be compiled as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -7383,22 +7743,6 @@ kernel: saying N will just cause this configure script to skip all the questions about Ethernet network cards. If unsure, say N. -Sun LANCE Ethernet support -CONFIG_SUN_LANCE - This is support for lance Ethernet cards on Sun workstations such as - the SPARCstation IPC (any SPARC with a network interface 'le0' under - SunOS basically). - - This driver 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 lance.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. - -Sun Intel Ethernet support -CONFIG_SUN_INTEL - This is support for the Intel Ethernet cards on some Sun - workstations (all those with a network interface 'ie0' under SunOS). - Western Digital/SMC cards CONFIG_NET_VENDOR_SMC If you have a network (Ethernet) card belonging to this class, say Y @@ -7494,19 +7838,6 @@ module, say M here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. -PCI DM9102(A)/DM9132/DM9801 support -CONFIG_DM9102 - This driver is for DM9102 compatible PCI cards from Davicom - (http://www.davicom.com.tw) including models DM9132 & DM9801. - If you have a PCI DM9102, DM9132 or DM9801 network (Ethernet) - card, say Y. - - This driver 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 dmfe.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt as well as - Documentation/networking/net-modules.txt. - Racal-Interlan (Micom) NI cards CONFIG_NET_VENDOR_RACAL If you have a network (Ethernet) card belonging to this class, such @@ -7570,9 +7901,9 @@ RealTek RTL-8139 PCI Fast Ethernet Adapter support CONFIG_8139TOO This is a driver for the Fast Ethernet PCI network cards based on - the RTL8139 chip. If you have one of those, say Y and - read the Ethernet-HOWTO, available from - http://www.linuxdoc.org/docs.html#howto . + the RTL8139 chips. If you have one of those, say Y and read + Documentation/networking/8139too.txt as well as the Ethernet-HOWTO, + available from http://www.linuxdoc.org/docs.html#howto . If you want to compile this driver as a module ( = code which can be inserted in and removed from the running kernel whenever you want), @@ -7584,13 +7915,13 @@ This is a driver for the Fast Ethernet PCI network cards based on the SiS 900 and SiS 7016 chips. The SiS 900 core is also embedded in SiS 630 and SiS 540 chipsets. If you have one of those, say Y and - read the Ethernet-HOWTO, available via FTP (user: anonymous) in - ftp://metalab.unc.edu/pub/Linux/docs/HOWTO. Please read - Documentation/networking/sis900.txt and comments at the beginning - of drivers/net/sis900.c for more information. + read the Ethernet-HOWTO, available at + http://www.linuxdoc.org/docs.html#howto . Please read + Documentation/networking/sis900.txt and comments at the beginning of + drivers/net/sis900.c for more information. - This driver also supports AMD 79C901 HomePNA such that you can use - your phone line as network cable. + This driver also supports AMD 79C901 HomePNA so that you can use + your phone line as a network cable. If you want to compile this driver as a module ( = code which can be inserted in and removed from the running kernel whenever you want), @@ -7632,6 +7963,18 @@ If you don't have this card, of course say N. +Adaptec Starfire support (EXPERIMENTAL) +CONFIG_ADAPTEC_STARFIRE + Say Y here if you have an Adaptec Starfire (or DuraLAN) PCI network + adapter. The DuraLAN chip is used on the 64 bit PCI boards from + Adaptec e.g. the ANA-6922A. The older 32 bit boards use the tulip + driver. + + If you want to compile this driver as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. This is recommended. + The module will be called starfile.o. + Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support CONFIG_ACENIC Say Y here if you have an Alteon AceNIC, 3Com 3C985(B), NetGear @@ -7682,6 +8025,11 @@ CONFIG_MYRI_SBUS This driver supports MyriCOM Sbus gigabit ethernet cards. + If you want to compile this driver as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. This is recommended. + The module will be called myri_sbus.o. + AMD LANCE and PCnet (AT1500 and NE2100) support CONFIG_LANCE If you have a network (Ethernet) card of this type, say Y and read @@ -7694,6 +8042,12 @@ say M here and read Documentation/modules.txt. This is recommended. The module will be called lance.o. +SGI IOC3 Ethernet +CONFIG_SGI_IOC3_ETH + If you have a network (Ethernet) card of this type, say Y and read + the Ethernet-HOWTO, available from + http://www.linuxdoc.org/docs.html#howto . + 3COM cards CONFIG_NET_VENDOR_3COM If you have a network (Ethernet) card belonging to this class, say Y @@ -7797,6 +8151,18 @@ Documentation/networking/net-modules.txt. The module will be called 3c509.o. +3c515 ISA Fast EtherLink +CONFIG_3C515 + If you have a 3Com ISA EtherLink XL "Corkscrew" 3c515 Fast Ethernet + network card, say Y and read the Ethernet-HOWTO, available from + http://www.linuxdoc.org/docs.html#howto . + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt as well as + Documentation/networking/net-modules.txt. The module will be called + 3c515.o. + 3c590 series (592/595/597) "Vortex" support CONFIG_VORTEX If you have a 3Com "Vortex" (Fast EtherLink 3c590/3c592/3c595/3c597) @@ -7858,7 +8224,7 @@ ARCnet documentation in Documentation/networking/arcnet.txt for more information about using arc0e and arc0s. -Enable arc0s (ARCnet RFC1051 packet format) +Enable old ARCNet packet format (RFC 1051) CONFIG_ARCNET_1051 This allows you to use RFC1051 with your ARCnet card via the virtual arc0s device. You only need arc0s if you want to talk to ARCnet @@ -8178,7 +8544,7 @@ module, say M here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. -Novell/Eagle/Microdyne NE3210 EISA support (EXPERIMENTAL) +Novell/Eagle/Microdyne NE3210 EISA support CONFIG_NE3210 If you have a network (Ethernet) card of this type, say Y and read the Ethernet-HOWTO, available from @@ -8263,10 +8629,10 @@ module, say M here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. -EtherExpress PRO/100 support -CONFIG_EEPRO100_PM (EXPERIMENTAL) +Enable Power Management (EXPERIMENTAL) +CONFIG_EEPRO100_PM If you want to play around with power management code - that has reported to lock up some machines, say Y here. + that has been reported to lock up some machines, say Y here. ICL EtherTeam 16i/32 support (EXPERIMENTAL) CONFIG_ETH16I @@ -8297,7 +8663,7 @@ module, say M here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. - Please email feedback to torben.mathiasen@compaq.com. + Please email feedback to torben.mathiasen@compaq.com. VIA Rhine support CONFIG_VIA_RHINE @@ -8310,6 +8676,19 @@ a module, say M here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. +PCI DM9102(A)/DM9132/DM9801 support +CONFIG_DM9102 + This driver is for DM9102(A)/DM9132/DM9801 compatible PCI cards from + Davicom ( http://www.davicom.com.tw ). If you have such a network + (Ethernet) card, say Y. Some information is contained in the file + Documentation/networking/dmfe.txt. + + This driver 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 dmfe.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt as well as + Documentation/networking/net-modules.txt. + Racal-Interlan EISA ES3210 support (EXPERIMENTAL) CONFIG_ES3210 If you have a network (Ethernet) card of this type, say Y and read @@ -8347,18 +8726,6 @@ by this driver. Read the Ethernet-HOWTO, available from http://www.linuxdoc.org/docs.html#howto . -Adaptec Starfire support -CONFIG_ADAPTEC_STARFIRE - If you have an Ethernet network card like this, say Y and read the - Ethernet-HOWTO, available from - http://www.linuxdoc.org/docs.html#howto . - - This driver 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 starfire.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt as well as - Documentation/networking/net-modules.txt. - Pocket and portable adapters CONFIG_NET_POCKET Cute little network (Ethernet) devices which attach to the parallel @@ -8386,9 +8753,14 @@ port. Read drivers/net/atp.c as well as the Ethernet-HOWTO, available from http://www.linuxdoc.org/docs.html#howto , if you want to use this. If you intend to use this driver, you should have - said N to the Parallel Printer support, because the two drivers + said N to the "Parallel printer support", because the two drivers don't like each other. + If you want to compile this driver as a module however ( = code + which can be inserted in and removed from the running kernel + whenever you want), say M here and read Documentation/modules.txt. + The module will be called atp.o. + D-Link DE600 pocket adapter support CONFIG_DE600 This is a network (Ethernet) device which attaches to your parallel @@ -8459,22 +8831,22 @@ The module will will be called olympic.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. - Also read the file Documentation/networking/olympic.txt or check the + Also read the file Documentation/networking/olympic.txt or check the Linux Token Ring Project site for the latest information at - http://www.linuxtr.net + http://www.linuxtr.net . IBM Lanstreamer chipset PCI adapter support CONFIG_IBMLS This is support for IBM Lanstreamer PCI Token Ring Cards. - If you have such an adapter, say Y and read the Token-Ring mini-HOWTO - available via FTP (user:anonymous) from + If you have such an adapter, say Y and read the Token-Ring + mini-HOWTO available via FTP (user:anonymous) from ftp://metalab.unc/edu/pub/Linux/docs/HOWTO. This driver is also available as a modules ( = code which can be inserted in and removed from the running kernel whenever you want). - The modules will be called lanstreamer.o. If you want to compile it as - a module, say M here and read Documentation/modules.txt. + The modules will be called lanstreamer.o. If you want to compile it + as a module, say M here and read Documentation/modules.txt. Generic TMS380 Token Ring ISA/PCI/MCA/EISA adapter support CONFIG_TMS380TR @@ -8483,16 +8855,21 @@ includes the SysKonnect TR4/16(+) ISA (SK-4190), SysKonnect TR4/16(+) PCI (SK-4590), SysKonnect TR4/16 PCI (SK-4591), Compaq 4/16 PCI, Thomas-Conrad TC4048 4/16 PCI, and several - Madge adapters. If selected, you will be asked to select + Madge adapters. If you say Y here, you will be asked to select which cards to support below. If you're using modules, each class of card will be supported by a separate module. - If you have such an adapter and would like to use it, say Y or M and + If you have such an adapter and would like to use it, say Y and read the Token-Ring mini-HOWTO, available from http://www.linuxdoc.org/docs.html#howto . - Also read the file linux/Documentation/networking/tms380tr.txt or check - http://www.auk.cx/tms380tr/ + Also read the file Documentation/networking/tms380tr.txt or + check http://www.auk.cx/tms380tr/ . + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will will be called tms380tr.o. If you want to compile it + as a module, say M here and read Documentation/modules.txt. Generic TMS380 PCI support CONFIG_TMSPCI @@ -8504,30 +8881,53 @@ - Thomas-Conrad TC4048 PCI 4/16 - 3Com Token Link Velocity + This driver is available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will will be called tmspci.o. If you want to compile it + as a module, say M here and read Documentation/modules.txt. + Madge Smart 16/4 PCI Mk2 support CONFIG_ABYSS - This tms380 module supports the Madge Smart 16/4 PCI Mk2 cards (51-02). + This tms380 module supports the Madge Smart 16/4 PCI Mk2 + cards (51-02). + + This driver is available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will will be called abyss.o. If you want to compile it + as a module, say M here and read Documentation/modules.txt. Madge Smart 16/4 Ringode MicroChannel CONFIG_MADGEMC This tms380 module supports the Madge Smart 16/4 MC16 and MC32 - MicroChannel adapters + MicroChannel adapters. + + This driver is available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will will be called madgemc.o. If you want to compile it + as a module, say M here and read Documentation/modules.txt. SMC ISA TokenRing adapter support CONFIG_SMCTR - This is support for the ISA and MCA SMC Token Ring cards, specifically - SMC TokenCard Elite (8115T) and SMC TokenCard Elite/A (8115T/A) adapters. + This is support for the ISA and MCA SMC Token Ring cards, + specifically SMC TokenCard Elite (8115T) and SMC TokenCard Elite/A + (8115T/A) adapters. If you have such an adapter and would like to use it, say Y or M and read the Token-Ring mini-HOWTO, available from - http://www.linuxdoc.org/docs.html#howto . + http://www.linuxdoc.org/docs.html#howto and the file + Documentation/networking/smctr.txt. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will will be called smctr.o. If you want to compile it + as a module, say M here and read Documentation/modules.txt. Sun Happy Meal 10/100baseT support CONFIG_HAPPYMEAL - This driver supports the "hme" interface present on most Ultra systems - and as an option on older Sbus systems. This driver supports both PCI - and Sbus devices. This driver also supports the "qfe" quad 100baseT - device available in both PCI and Sbus configurations. + This driver supports the "hme" interface present on most Ultra + systems and as an option on older Sbus systems. This driver supports + both PCI and Sbus devices. This driver also supports the "qfe" quad + 100baseT device available in both PCI and Sbus configurations. This support is also available as a module called sunhme.o ( = code which can be inserted in and removed from the running kernel @@ -8539,8 +8939,8 @@ This driver supports the "le" interface present on all 32-bit Sparc systems, on some older Ultra systems and as an Sbus option. - This support is also available as a module called sunlance.o ( = code - which can be inserted in and removed from the running kernel + This support is also available as a module called sunlance.o ( = + code which can be inserted in and removed from the running kernel whenever you want). If you want to compile it as a module, say M here and read Documentation/modules.txt. @@ -8620,8 +9020,10 @@ - Netelligent 100 FDDI DAS UTP - Netelligent 100 FDDI SAS UTP - Netelligent 100 FDDI SAS Fibre MIC + Read Documentation/networking/skfp.txt for information about the driver. + WARNING: this driver does currently not support 64 bit systems! Questions concerning this driver can be addressed to: linux@syskonnect.de @@ -8631,14 +9033,6 @@ say M here and read Documentation/modules.txt. This is recommended. The module will be called skfp.o. -Linux telephony support -CONFIG_PHONE - This option enable the kernel to manage telephony cards. - - There are very few supported cards at this moment. - - If unsure, say N. - HIgh Performance Parallel Interface support (EXPERIMENTAL) CONFIG_HIPPI HIgh Performance Parallel Interface (HIPPI) is a 800Mbit/sec and @@ -8712,7 +9106,7 @@ read Documentation/modules.txt. If you want to use any of these CDROM drivers, you also have to - answer Y or M to "ISO 9660 CDROM file systems support" below (this + answer Y or M to "ISO 9660 CDROM file system support" below (this answer will get "defaulted" for you if you enable any of the Linux CDROM drivers). @@ -8725,11 +9119,10 @@ time as described in Documentation/cdrom/cdu31a or fill in your parameters into drivers/cdrom/cdu31a.c. Try "man bootparam" or see the documentation of your boot loader (lilo or loadlin) about - how to pass options to the kernel. The lilo procedure is also - explained in the SCSI-HOWTO. + how to pass options to the kernel. If you say Y here, you should also say Y or M to "ISO 9660 CDROM - file systems support" below, because that's the file systems used on + file system support" below, because that's the file system used on CDROMs. This driver is also available as a module ( = code which can be @@ -8751,7 +9144,7 @@ this. If you want that one, say N here. If you say Y here, you should also say Y or M to "ISO 9660 CDROM - file systems support" below, because that's the file systems used on + file system support" below, because that's the file system used on CDROMs. This driver is also available as a module ( = code which can be @@ -8784,7 +9177,7 @@ Documentation/cdrom/mcdx. If you say Y here, you should also say Y or M to "ISO 9660 CDROM - file systems support" below, because that's the file systems used on + file system support" below, because that's the file system used on CDROMs. This driver is also available as a module ( = code which can be @@ -8822,7 +9215,7 @@ usable. If you say Y here, you should also say Y or M to "ISO 9660 CDROM - file systems support" below, because that's the file systems used on + file system support" below, because that's the file system used on CDROMs. This driver is also available as a module ( = code which can be @@ -8835,7 +9228,7 @@ Say Y here only if you have two CDROM controller cards of this type (usually only if you have more than four drives). You should enter the parameters for the second, third and fourth interface card into - linux/include/linux/sbpcd.h before compiling the new kernel. Read + include/linux/sbpcd.h before compiling the new kernel. Read the file Documentation/cdrom/sbpcd. Aztech/Orchid/Okano/Wearnes/TXC/CyDROM CDROM support @@ -8847,7 +9240,7 @@ CDA269-031SE. Please read the file Documentation/cdrom/aztcd. If you say Y here, you should also say Y or M to "ISO 9660 CDROM - file systems support" below, because that's the file systems used on + file system support" below, because that's the file system used on CDROMs. This driver is also available as a module ( = code which can be @@ -8872,8 +9265,8 @@ Goldstar R420 CDROM support CONFIG_GSCD If this is your CDROM drive, say Y here. As described in the file - linux/Documentation/cdrom/gscd, you might have to change a setting - in the file linux/drivers/cdrom/gscd.h before compiling the + Documentation/cdrom/gscd, you might have to change a setting + in the file drivers/cdrom/gscd.h before compiling the kernel. Please read the file Documentation/cdrom/gscd. If you say Y here, you should also say Y or M to "ISO 9660 CDROM @@ -8929,17 +9322,6 @@ The module will be called sjcd.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. -Soft configurable cdrom interface card support -CONFIG_CDI_INIT - If you want to include boot-time initialization of any cdrom - interface card that is software configurable, say Y here. Currently - only the ISP16/MAD16/Mozart sound cards with built-in cdrom - interfaces are supported. - - Note that the answer to this question doesn't directly affect the - kernel: saying N will just cause this configure script to skip all - the questions about these CDROM drives. - ISP16/MAD16/Mozart soft configurable cdrom interface support CONFIG_ISP16_CDI These are sound cards with built-in cdrom interfaces using the OPTi @@ -8969,8 +9351,8 @@ traditional PC serial port. The bus supplies power to peripherals and allows for hot swapping. Up to 127 USB peripherals can be connected to a single USB port in a tree structure. The USB port is - the root of the tree, the peripherals are the leaves, and the inner - nodes are special USB devices called hubs. Many newer PCs have USB + the root of the tree, the peripherals are the leaves and the inner + nodes are special USB devices called hubs. Many newer PC's have USB ports and newer peripherals such as scanners, keyboards, mice, modems, and printers support the USB protocol and can be connected to the PC via those ports. @@ -8986,6 +9368,12 @@ The module will be called usbcore.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. +USB verbose debug messages +CONFIG_USB_DEBUG + Say Y here if you want the USB core drivers to produce a bunch of + debug messages to the system log. Select this if you are having a + problem with USB support and want to see more of what is going on. + UHCI (intel PIIX4, VIA, ...) support? CONFIG_USB_UHCI The Universal Host Controller Interface is a standard by Intel for @@ -9061,17 +9449,37 @@ USB keyboard and prefer to use the keyboard in its limited Boot Protocol mode. This driver is much smaller than the HID one. + 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 usbkbd.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. + + If unsure, say N. + USB HIDBP Mouse support CONFIG_USB_MOUSE Say Y here if you don't want to use the generic HID driver for your USB mouse and prefer to use the mouse in its limited Boot Protocol mode. This driver is much smaller than the HID one. + 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 usbmouse.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. + + If unsure, say N. + Wacom Intuos/Graphire tablet support CONFIG_USB_WACOM - Say Y here if you want to use the USB version of the Wacom - Intuos or Graphire tablet. Make sure you select Mouse and Event - support as well. + Say Y here if you want to use the USB version of the Wacom Intuos or + Graphire tablet. Make sure to say Y to "Mouse support" + (CONFIG_INPUT_MOUSEDEV) and "Event interface support" + (CONFIG_INPUT_EVDEV) as well. + + This driver 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 wacom.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. Logitech WingMan Force joystick support CONFIG_USB_WMFORCE @@ -9079,42 +9487,65 @@ on the USB port. No force-feedback support yet, but other than that, it should work like a normal joystick. + This driver 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 wmforce.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. + Keyboard support CONFIG_INPUT_KEYBDEV Say Y here if you want your USB HID keyboard to be able to serve as a system keyboard. + This driver 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 keybdev.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. + Mouse support CONFIG_INPUT_MOUSEDEV Say Y here if you want your USB HID mouse to be accessible as - misc devices 32+ under /dev/, as an emulated PS/2 mouse. + misc devices 32+ under /dev/, as an emulated PS/2 mouse. That way, + all user space programs will be able to use your mouse. + + If unsure, say Y. + + This driver 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 mousedev.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. Mix all mice into one device CONFIG_INPUT_MOUSEDEV_MIX Say Y here if you want input from all your USB HID mice to be mixed into one misc device. If you say N, you'll have a separate - device for each your USB mouse. + device for each USB mouse. Support for digitizers CONFIG_INPUT_MOUSEDEV_DIGITIZER - Use this if you have a digitizer that doesn't emulate a mouse + Say Y here if you have a digitizer that doesn't emulate a mouse itself, and want to use it as a mouse. Horizontal screen resolution CONFIG_INPUT_MOUSEDEV_SCREEN_X - For the mouse emulation to be correct, the mousedev driver needs - to know the screen resolution you are using (in X). + For the mouse emulation to be correct, the mousedev driver needs to + know the screen resolution you are using (in the X window system). Vertical screen resolution CONFIG_INPUT_MOUSEDEV_SCREEN_Y - For the mouse emulation to be correct, the mousedev driver needs - to know the screen resolution you are using (in X). + For the mouse emulation to be correct, the mousedev driver needs to + know the screen resolution you are using (in the X window system). Joystick support CONFIG_INPUT_JOYDEV Say Y here if you want your USB HID joystick or gamepad to be - accessible as /dev/js device. You can't use a normal joystick - if you select this. + accessible as a /dev/js device. You can't use a normal (non-USB) + joystick if you say Y here. + + This driver 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 joydev.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. Event interface support CONFIG_INPUT_EVDEV @@ -9124,18 +9555,18 @@ USB Scanner support CONFIG_USB_SCANNER - Say Y here if you want to connect a USB scanner to your - computer's USB port. Please read Documentation/usb/scanner.txt - and Documentation/usb/scanner-hp-sane.txt for more information. + Say Y here if you want to connect a USB scanner to your computer's + USB port. Please read Documentation/usb/scanner.txt and + Documentation/usb/scanner-hp-sane.txt for more information. 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 hp_scanner.o. If you want to compile it as + The module will be called scanner.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. USB Audio support CONFIG_USB_AUDIO - Say Y here if you want to connect USB audio equipment such as + Say Y here if you want to connect UAB audio equipment such as speakers to your computer's USB port. This code is also available as a module ( = code which can be @@ -9155,11 +9586,16 @@ USB Serial converter support CONFIG_USB_SERIAL - Say Y here if you want to connect a Connect Tech WhiteHEAT - multi-port USB to serial converter; a FTDI or Keyspan single port - USB to serial converter; or a Handspring Visor. Please read - Documentation/usb/usb-serial.txt for more information. + Say Y here if you have a USB device that provides normal serial + ports, and you want to connect it to your USB bus. Supported devices + are the Tech WhiteHEAT multi-port USB to serial converter, and the + FTDI or Keyspan single port USB to serial converter Handspring + Visor. In addition to saying Y here, you need to say Y to the driver + for your specific hardware below. Some other devices may also be + used if you say Y to "USB Generic Serial Driver", below. + Please read Documentation/usb/usb-serial.txt for more information. + 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 usb-serial.o. If you want to compile it @@ -9167,10 +9603,11 @@ USB Generic Serial Driver CONFIG_USB_SERIAL_GENERIC - Say Y here if you want to use the generic USB serial driver. - Please read Documentation/usb/usb-serial.txt for more information - on using this driver. It is recommended that the USB Serial - Driver be compiled as a module for this driver to be used properly. + Say Y here if you want to use the generic USB serial driver. Please + read Documentation/usb/usb-serial.txt for more information on using + this driver. It is recommended that the "USB Serial converter + support" be compiled as a module for this driver to be used + properly. USB ConnectTech WhiteHEAT Serial Driver CONFIG_USB_SERIAL_WHITEHEAT @@ -9186,7 +9623,10 @@ USB FTDI Single Port Serial Driver CONFIG_USB_SERIAL_FTDI_SIO Say Y here if you want to use a FTDI SIO single port USB to serial - converter device. + converter device. The implementation I have is called the USC-1000 + + See http://reality.sgi.com/bryder_wellington/ftdi_sio for more information + on this driver and the device USB FTDI Single Port Serial Driver CONFIG_USB_SERIAL_KEYSPAN_PDA @@ -9203,26 +9643,11 @@ The module will be called printer.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. -USB CPiA Camera support -CONFIG_USB_CPIA - Say Y here if you want to connect this type of camera to your - computer's USB port. - - This driver uses the Video For Linux API. You must enable - (Y or M in config) Video For Linux (under Character Devices) - to use this driver. Information on this API and pointers to - "v4l" programs may be found on the WWW at - http://roadrunner.swansea.uk.linux.org/v4l.shtml . - - 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 cpia.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. - USB IBM (Xirlink) C-It Camera support CONFIG_USB_IBMCAM - Say Y here if you want to connect this type of camera to your - computer's USB port. + Say Y here if you want to connect a IBM "C-It" camera, also known as + "Xirlink PC Camera" to your computer's USB port. For more + information, read Documentation/usb/ibmcam.txt. This driver uses the Video For Linux API. You must enable (Y or M in config) Video For Linux (under Character Devices) @@ -9243,11 +9668,10 @@ computer's USB port. See Documentation/usb/ov511.txt for more information and for a list of supported cameras. - This driver uses the Video For Linux API. You must enable - (Y or M in config) Video For Linux (under Character Devices) - to use this driver. Information on this API and pointers to - "v4l" programs may be found on the WWW at - http://roadrunner.swansea.uk.linux.org/v4l.shtml . + This driver uses the Video For Linux API. You must say Y or M to + "Video For Linux" (under Character Devices) to use this driver. + Information on this API and pointers to "v4l" programs may be found + on the WWW at http://roadrunner.swansea.uk.linux.org/v4l.shtml . This code is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -9256,11 +9680,18 @@ USB ADMtek Pegasus-based ethernet device support CONFIG_USB_PEGASUS - Say Y if you want to use your USB ethernet device. Note that - the code is still experimental. If you have devices with vendor - IDs other than ADMtek's, you should change/add them in the - driver code and send a message to me (petkan@spct.net) for - update. + Say Y if you want to use your USB ethernet device. Supported + cards until now are: + Accton 10/100 + Billington USB-100 + Corega FEter USB-TX + MELCO/BUFFALO LUA-TX + D-Link DSB-650TX, DSB-650TX-PNA + Linksys USB100TX + SNC 202 + If you have devices with vendor IDs other than noted above + you should add them in the driver code and send a message + to me (petkan@spct.net) for update. This code is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -9285,7 +9716,7 @@ Say Y here if you want to connect this type of still camera to your computer's USB port. This driver can be used with gphoto 0.4.3 and higher (look at www.gphoto.org). - To use it create a devicenode with mknod /dev/mustek c 10 171 and + To use it create a devicenode with mknod /dev/mustek c 180 32 and configure it in your software. This code is also available as a module ( = code which can be @@ -9293,7 +9724,6 @@ The module will be called mdc800.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. - USB Mass Storage support CONFIG_USB_STORAGE Say Y here if you want to connect USB mass storage devices to your @@ -9312,8 +9742,9 @@ USS720 parport driver CONFIG_USB_USS720 This driver is for USB parallel port adapters that use the Lucent - Technologies USS-720 chip. These adapters provide USB compatibility - to peripherals designed with parallel port interfaces. + Technologies USS-720 chip. These cables are plugged into your USB + port and provide USB compatibility to peripherals designed with + parallel port interfaces. The chip has two modes: automatic mode and manual mode. In automatic mode, it looks to the computer like a standard USB printer. Only @@ -9338,38 +9769,53 @@ USB device file system CONFIG_USB_DEVICEFS - This file system implements a "devices" file, that lists - the currently connected to your USB busses, a "drivers" file - that lists the USB kernel client drivers currently loaded, - and for every connected device a file named "xxx/yyy", where - xxx is the bus number and yyy the device number, that can be used - by userspace drivers to talk to the device. + If you say Y here (and to "/proc file system support" below), you + will get a file /proc/usb/devices which lists the devices currently + connected to your USB busses, a file /proc/usb/drivers file which + lists the USB kernel client drivers currently loaded, and for every + connected device a file named "/proc/usb/xxx/yyy", where xxx is the + bus number and yyy the device number; the latter files can be used + by userspace drivers to talk to the device. These files are + "virtual", meaning they are generated on the fly and not stored on + the hard drive. + + For the format of the /proc/usb/ files, please read + Documentation/usb/proc_usb_info.txt. + + Please note that this code is completely unrelated to devfs, the + "/dev file system support". Most users want to say Y here. DABUSB driver CONFIG_USB_DABUSB - A Digital Audio Broadcasting (DAB) Receiver for USB and Linux brought - to you by the DAB-Team (http://dab.in.tum.de). - This driver can be taken as an example for URB-based bulk, control, and - isochronous transactions. + A Digital Audio Broadcasting (DAB) Receiver for USB and Linux + brought to you by the DAB-Team (http://dab.in.tum.de). This driver + can be taken as an example for URB-based bulk, control, and + isochronous transactions. URB's are explained in + Documentation/usb/URB.txt. 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 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). + 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). + + 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 plusb.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. USB Diamond Rio500 support CONFIG_USB_RIO500 - Say Y here if you want to connect a USB rio500 to your + Say Y here if you want to connect a USB Rio500 mp3 player to your computer's USB port. Please read Documentation/usb/rio.txt for more information. @@ -9378,7 +9824,7 @@ The module will be called rio500.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. -D-Link DSB-R100 FM radio upport +D-Link DSB-R100 FM radio support CONFIG_USB_DSBR Say Y here if you want to connect this type of radio to your computer's USB port. Note that the audio is not digital, and @@ -9396,28 +9842,22 @@ The module will be called dsbr100.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. -ACPI support -CONFIG_ACPI - Advanced Configuration and Power Interface (ACPI) is an interface - specification to support power management of peripherals. If your - system supports it, say Y here. - Minix fs support CONFIG_MINIX_FS Minix is a simple operating system used in many classes about OS's. The minix file system (method to organize files on a hard disk partition or a floppy disk) was the original file system for Linux, but has been superseded by the second extended file system ext2fs. - You don't want to use the minix file system on your hard disk because - of certain built-in restrictions, but it is sometimes found on older - Linux floppy disks. This option will enlarge your kernel by about - 28 kB. If unsure, say N. + You don't want to use the minix file system on your hard disk + because of certain built-in restrictions, but it is sometimes found + on older Linux floppy disks. This option will enlarge your kernel by + about 28 KB. If unsure, say N. If you want to compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read Documentation/modules.txt. The module will be - called minix.o. Note that the file system of your root partition (the - one containing the directory /) cannot be compiled as a module. + called minix.o. Note that the file system of your root partition + (the one containing the directory /) cannot be compiled as a module. Second extended fs support CONFIG_EXT2_FS @@ -9425,11 +9865,11 @@ files on a storage device) for hard disks. You want to say Y here, unless you intend to use Linux exclusively - from inside a DOS partition using the umsdos file system. The + from inside a DOS partition using the UMSDOS file system. The advantage of the latter is that you can get away without repartitioning your hard drive (which often implies backing everything up and restoring afterwards); the disadvantage is that - Linux becomes susceptible to DOS viruses and that umsdos is somewhat + Linux becomes susceptible to DOS viruses and that UMSDOS is somewhat slower than ext2fs. Even if you want to run Linux in this fashion, it might be a good idea to have ext2fs around: it enables you to read more floppy disks and facilitates the transition to a *real* @@ -9437,7 +9877,7 @@ ext2fs is a diskless Linux box which mounts all files over the network using NFS (in this case it's sufficient to say Y to "NFS file system support" below). Saying Y here will enlarge your kernel - by about 44 kB. + by about 44 KB. The Ext2fs-Undeletion mini-HOWTO, available from http://www.linuxdoc.org/docs.html#howto , gives information about @@ -9451,9 +9891,10 @@ command line tool package (available via FTP (user: anonymous) from ftp://metalab.unc.edu/pub/Linux/system/filesystems/ext2 ) and from within Windows NT using the ext2nt command line tool package from - ftp://metalab.unc.edu/pub/Linux/utils/dos . Explore2fs is a graphical - explorer for ext2fs partitions which runs on Windows 95 and Windows - NT and includes experimental write support; it is available from + ftp://metalab.unc.edu/pub/Linux/utils/dos . Explore2fs is a + graphical explorer for ext2fs partitions which runs on Windows 95 + and Windows NT and includes experimental write support; it is + available from http://jnewbigin-pc.it.swin.edu.au/Linux/Explore2fs.htm . If you want to compile this file system as a module ( = code which @@ -9467,31 +9908,50 @@ BFS file system support (EXPERIMENTAL) CONFIG_BFS_FS Boot File System (BFS) is a file system used under SCO UnixWare to - allow bootloader access the kernel image and other important files - during the boot process. It is usually mounted under /stand and - corresponds to the slice marked as "STAND" in the UnixWare - partition. This is useful if you want to access files on your /stand - slice from Linux. More information on this file system can be found in - Documentation/filesystems/bfs.txt file. If you do not know what it is, - say N. + allow the bootloader access to the kernel image and other important + files during the boot process. It is usually mounted under /stand + and corresponds to the slice marked as "STAND" in the UnixWare + partition. You should say Y if you want to read or write + the files on your /stand slice from within Linux. You then also + need to say Y to "UnixWare slices support", below. More information + about the BFS file system is contained in the file + Documentation/filesystems/bfs.txt. + + If you don't know what this is about, say N. If you want to compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read Documentation/modules.txt. The module will be called bfs.o. Note that the file system of your root partition (the one containing the directory /) cannot be compiled as a module. - + +Compressed ROM file system support +CONFIG_CRAMFS + Saying Y here includes support for CramFs (Compressed ROM File + System). Cramfs is designed to be a simple, small, and compressed + file system for ROM based embedded systems. CramFs is read-only, + limited to 256MB file systems (with 16MB files), and doesn't support + 16/32 bits uid/gid, hard links and timestamps. + + See Documentation/filesystems/cramfs.txt and fs/cramfs/README + for further information. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called cramfs.o. + ISO 9660 CDROM file system support CONFIG_ISO9660_FS This is the standard file system used on CDROMs. It was previously - known as "High Sierra File System" and is called "hsfs" on other Unix - systems. The so-called Rock-Ridge extensions which allow for long - Unix filenames and symbolic links are also supported by this driver. - If you have a CDROM drive and want to do more with it than just - listen to audio CDs and watch its LEDs, say Y (and read + known as "High Sierra File System" and is called "hsfs" on other + Unix systems. The so-called Rock-Ridge extensions which allow for + long Unix filenames and symbolic links are also supported by this + driver. If you have a CDROM drive and want to do more with it than + just listen to audio CDs and watch its LEDs, say Y (and read Documentation/filesystems/isofs.txt and the CDROM-HOWTO, available - from http://www.linuxdoc.org/docs.html#howto ), thereby - enlarging your kernel by about 27 KB; otherwise say N. + from http://www.linuxdoc.org/docs.html#howto ), thereby enlarging + your kernel by about 27 KB; otherwise say N. If you want to compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), @@ -9507,17 +9967,21 @@ http://www.unicode.org for more information). Say Y here if you want to be able to read Joliet CDROMs under Linux. -UDF file system support (read only) +UDF File System support (read only) CONFIG_UDF_FS - This is the new file system used by some CDROMS and DVD drivers. Say - Y if you intend to mount DVD discs or CDRW's written in packet mode, - or if written to by other UDF utilities, such as DirectCD. Please - read Documentation/filesystems/udf.txt. + This is the new file system used on some CDROMs and DVDs. Say Y if + you intend to mount DVD discs or CDRW's written in packet mode, or + if written to by other UDF utilities, such as DirectCD. This UDF + file system support is read-only. If you want to write to UDF + file systems on some media, you need to say Y to "UDF read-write + support" below in addition. Please read + Documentation/filesystems/udf.txt. - This file system support is also available as a module ( = code which - can be inserted in and removed from the running kernel whenever you - want). The module is called udf.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. + This file system support is also available as a module ( = code + which can be inserted in and removed from the running kernel + whenever you want). The module is called udf.o. If you want to + compile it as a module, say M here and read + Documentation/modules.txt. If unsure, say N. @@ -9525,7 +9989,7 @@ CONFIG_UDF_RW Say Y if you want to test write support for UDF file systems. Due to lack of support for writing to CDR/CDRW's, this option - is only supported for Hard Discs, DVD-RAM, and loopback files. + is only supported for hard discs, DVD-RAM, and loopback files. DOS FAT fs support CONFIG_FAT_FS @@ -9537,18 +10001,24 @@ files on them, i.e. MSDOS files will look and behave just like all other Unix files. - This FAT support is not a file system in itself, it only provides the - foundation for the other file systems. You will have to say Y or M to - at least one of "msdos fs support" or "vfat fs support" in order to - make use of it. + This FAT support is not a file system in itself, it only provides + the foundation for the other file systems. You will have to say Y or + M to at least one of "MSDOS fs support" or "VFAT fs support" in + order to make use of it. Another way to read and write MSDOS floppies and hard drive partitions from within Linux (but not transparently) is with the - mtools ("man mtools") program suite. This doesn't require the FAT - file system support. + mtools ("man mtools") program suite. You don't need to say Y here in + order to do that. + If you need to move large files on floppies between a DOS and a + Linux box, say Y here, mount the floppy under Linux with an MSDOS + file system and use GNU tar's M option. GNU tar is a program + available for Unix and DOS ("man tar" or "info tar"). + It is now also becoming possible to read and write compressed FAT - file systems; read Documentation/filesystems/fat_cvf.txt for details. + file systems; read Documentation/filesystems/fat_cvf.txt for + details. The FAT support will enlarge your kernel by about 37 KB. If unsure, say Y. @@ -9557,11 +10027,11 @@ be inserted in and removed from the running kernel whenever you want), say M here and read Documentation/modules.txt. The module will be called fat.o. Note that if you compile the FAT support as a - module, you cannot compile any of the FAT-based file systems into the - kernel -- they will have to be modules as well. The file system of - your root partition (the one containing the directory /) cannot be a - module, so don't say M here if you intend to use UMSDOS as your root - file system. + module, you cannot compile any of the FAT-based file systems into + the kernel -- they will have to be modules as well. The file system + of your root partition (the one containing the directory /) cannot + be a module, so don't say M here if you intend to use UMSDOS as your + root file system. MSDOS fs support CONFIG_MSDOS_FS @@ -9576,36 +10046,37 @@ transparent, i.e. the MSDOS files look and behave just like all other Unix files. - If you want to use umsdos, the Unix-like file system on top of DOS, - which allows you to run Linux from within a DOS partition without - repartitioning, you'll have to say Y or M here. + If you want to use UMSDOS, the Unix-like file system on top of a + DOS file system, which allows you to run Linux from within a DOS + partition without repartitioning, you'll have to say Y or M here. If you have Windows 95 or Windows NT installed on your MSDOS - partitions, you should use the VFAT file system (say Y to "vfat fs + partitions, you should use the VFAT file system (say Y to "VFAT fs support" below), or you will not be able to see the long filenames generated by Windows 95 / Windows NT. This option will enlarge your kernel by about 7 KB. If unsure, - answer Y. This will only work if you said Y to "fat fs support" as - well. If you want to compile this as a module however ( = code which - can be inserted in and removed from the running kernel whenever you - want), say M here and read Documentation/modules.txt. The module - will be called msdos.o. + answer Y. This will only work if you said Y to "DOS FAT fs support" + as well. If you want to compile this as a module however ( = code + which can be inserted in and removed from the running kernel + whenever you want), say M here and read Documentation/modules.txt. + The module will be called msdos.o. VFAT (Windows-95) fs support CONFIG_VFAT_FS This option provides support for normal Windows file systems with long filenames. That includes non-compressed FAT-based file systems - used by Windows 95, Windows 98, Windows NT 4.0, and mtools. + used by Windows 95, Windows 98, Windows NT 4.0, and the Unix + programs from the mtools package. You cannot use the VFAT file system for your Linux root partition (the one containing the directory /); use UMSDOS instead if you want to run Linux from within a DOS partition (i.e. say Y to - "umsdos: Unix like fs on top of std MSDOS fs", below). + "UMSDOS: Unix like fs on top of std MSDOS fs", below). The VFAT support enlarges your kernel by about 10 KB and it only - works if you said Y to the "fat fs support" above. Please read the - file Documentation/filesystems/vfat.txt for details. If unsure, + works if you said Y to the "DOS FAT fs support" above. Please read + the file Documentation/filesystems/vfat.txt for details. If unsure, say Y. If you want to compile this as a module ( = code which can be @@ -9613,23 +10084,6 @@ say M here and read Documentation/modules.txt. The module will be called vfat.o. -Compressed ROM file system support -CONFIG_CRAMFS - This option provides support for CramFs (Compressed ROM File System). - Cramfs is designed to be a simple, small, and compressed file system for ROM - based embedded systems. - CramFs is read-only, limited to 256MB file systems (with 16MB files), don't - support neither 16/32 bits uid/gid nor hard links. Neither are timestamps. - It isn't endian aware. - - See Documentation/filesystems/cramfs.txt and fs/cramfs/README - for further information. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read Documentation/modules.txt. The module will be - called cramfs.o. - UMSDOS: Unix-like file system on top of standard MSDOS fs CONFIG_UMSDOS_FS Say Y here if you want to run Linux from within an existing DOS @@ -9642,20 +10096,20 @@ is to write files with long unix filenames to MSDOS floppies; it also allows Unix-style soft-links and owner/permissions of files on MSDOS floppies. You will need a program called umssync in order to - make use of umsdos; read Documentation/filesystems/umsdos.txt. + make use of UMSDOS; read Documentation/filesystems/umsdos.txt. To get utilities for initializing/checking UMSDOS file system, or - latest patches and/or information, visit UMSDOS homepage at + latest patches and/or information, visit the UMSDOS home page at http://www.voyager.hr/~mnalis/umsdos/ . This option enlarges your kernel by about 28 KB and it only works if - you said Y to both "fat fs support" and "msdos fs support" above. If - you want to compile this as a module ( = code which can be inserted - in and removed from the running kernel whenever you want), say M - here and read Documentation/modules.txt. The module will be called - umsdos.o. Note that the file system of your root partition (the one - containing the directory /) cannot be a module, so saying M could be - dangerous. If unsure, say N. + you said Y to both "DOS FAT fs support" and "MSDOS fs support" + above. If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called umsdos.o. Note that the file system of your root partition + (the one containing the directory /) cannot be a module, so saying M + could be dangerous. If unsure, say N. /proc file system support CONFIG_PROC_FS @@ -9674,30 +10128,35 @@ The /proc file system is explained in the file Documentation/filesystems/proc.txt and on the proc(5) manpage ("man - 5 proc"). + 5 proc"). You can also use the program procinfo to display some + information about your system gathered from the /proc file system. This option will enlarge your kernel by about 67 KB. Several programs depend on this, so everyone should say Y here. /dev file system support (EXPERIMENTAL) CONFIG_DEVFS_FS - This is another virtual file system (like /proc) which provides the - file system interface to device drivers, normally found in /dev. - Devfs does not depend on major and minor number allocations. Device - drivers register entries in /dev which appear automagically. Without - devfs you need to populate /dev with hundreds, even thousands of - inodes. + This is support for devfs, a virtual file system (like /proc) which + provides the file system interface to device drivers, normally found + in /dev. Devfs does not depend on major and minor number + allocations. Device drivers register entries in /dev which then + appear automatically, which means that the system administrator does + not have to create character and block special device files in the + /dev directory using the mknod command anymore. + This is work in progress. If you want to use this you *must* read - Documentation/filesystems/devfs/README - In particular, make sure you install devfsd. If you don't, expect to - spend time patching broken code and updating configuration files. + the material in Documentation/filesystems/devfs/, especially the + file README there. + + If unsure, say N. Debug devfs CONFIG_DEVFS_DEBUG - This option appears if you have CONFIG_DEVFS_FS enabled. Setting - this to 'Y' enables devfs debugging output. See the file + If you say Y here, then the /dev file system code will generate + debugging messages. See the file Documentation/filesystems/devfs/boot-options for more details. - The default is 'N'. + + If unsure, say N. NFS file system support CONFIG_NFS_FS @@ -9710,7 +10169,7 @@ programs nfsd and mountd (but does not need to have NFS file system support enabled in its kernel). NFS is explained in the Network Administrator's Guide, available from - http://metalab.unc.edu/mdw/linux.html#guide , on its man page: "man + http://www.linuxdoc.org/docs.html#guide , on its man page: "man nfs", and in the NFS-HOWTO. A superior but less widely used alternative to NFS is provided by @@ -9761,35 +10220,34 @@ section. Please read the NFS-HOWTO, available from - http://www.linuxdoc.org/HOWTO/NFS-HOWTO.html . - + http://www.linuxdoc.org/docs.html#howto . The NFS server is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). The module is called nfsd.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. If unsure, say N. -Provide NFSv3 server support (EXPERIMENTAL) +Provide NFSv3 server support CONFIG_NFSD_V3 - If you would like to include the NFSv3 server was well as the NFSv2 - server, say Y here. File locking, via the NLMv4 protocol, is also - supported. If unsure, say N. + If you would like to include the NFSv3 server as well as the NFSv2 + server, say Y here. In unsure, say Y. OS/2 HPFS file system support CONFIG_HPFS_FS OS/2 is IBM's operating system for PC's, the same as Warp, and HPFS is the file system used for organizing files on OS/2 hard disk - partitions. Say Y if you want to be able to read files from an OS/2 - HPFS partition of your hard drive. OS/2 floppies however are in - regular MSDOS format, so you don't need this option in order to be - able to read them. Read Documentation/filesystems/hpfs.txt. + partitions. Say Y if you want to be able to read files from and + write files to an OS/2 HPFS partition on your hard drive. OS/2 + floppies however are in regular MSDOS format, so you don't need this + option in order to be able to read them. Read + Documentation/filesystems/hpfs.txt. This file system is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). The module is called hpfs.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. If unsure, say N. -NTFS file system support (read only) +NTFS support (read only) CONFIG_NTFS_FS NTFS is the file system of Microsoft Windows NT. Say Y if you want to get read access to files on NTFS partitions of your hard drive. @@ -9804,11 +10262,13 @@ NTFS write support (DANGEROUS) CONFIG_NTFS_RW - If you say Y here, you will (hopefully) be able to write to NTFS - file systems as well as read from them. The read-write support - in NTFS is far from being complete and is not well tested. If you + If you say Y here, you will (maybe) be able to write to NTFS file + systems as well as read from them. The read-write support in + NTFS is far from being complete and is not well tested. If you enable this, back up your NTFS volume first since it may get - damaged. + damaged. Also, make sure to run chkdsk from within Microsoft + Windows NT after having performed any writes to a NTFS partition + from Linux to detect any problems as early as possible. If unsure, say N. @@ -9816,7 +10276,8 @@ CONFIG_SYSV_FS SCO, Xenix and Coherent are commercial Unix systems for Intel machines. Saying Y here would allow you to read from their floppies - and hard disk partitions. + and hard disk partitions. If you also want to write to these media, + say Y to "SYSV file system write support" below. If you have floppies or hard disk partitions like that, it is likely that they contain binaries from those other Unix systems; in order @@ -9837,7 +10298,7 @@ tar" or preferably "info tar"). Note also that this option has nothing whatsoever to do with the option "System V IPC". Read about the System V file system in Documentation/filesystems/sysv-fs.txt. - Saying Y here will enlarge your kernel by about 27 kB. + Saying Y here will enlarge your kernel by about 27 KB. If you want to compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), @@ -9848,12 +10309,12 @@ SYSV file system write support (DANGEROUS) CONFIG_SYSV_FS_WRITE - If you say Y here, you will (hopefully) be able to write to System V - and Coherent file systems as well as read from them. The read-write - support in SYSV is not well tested yet. If you enable this, back up - your SYSV/Coherent volumes first since they may get damaged. + If you say Y here, you will be able to write to hard drive + partitions and floppy disks which carry a SYSV file system used the + commercial Unixes SCO, Xenix and Coherent. - If unsure, say N. + This support is experimental and you may destroy your data. If + unsure, say N. Amiga FFS file system support CONFIG_AFFS_FS @@ -9883,10 +10344,11 @@ Please read fs/hfs/HFS.txt to learn about the available mount options. - This file system support is also available as a module ( = code which - can be inserted in and removed from the running kernel whenever you - want). The module is called hfs.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. + This file system support is also available as a module ( = code + which can be inserted in and removed from the running kernel + whenever you want). The module is called hfs.o. If you want to + compile it as a module, say M here and read + Documentation/modules.txt. ROM file system support CONFIG_ROMFS_FS @@ -9895,10 +10357,11 @@ other read-only media as well. Read Documentation/filesystems/romfs.txt for details. - This file system support is also available as a module ( = code which - can be inserted in and removed from the running kernel whenever you - want). The module is called romfs.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. + This file system support is also available as a module ( = code + which can be inserted in and removed from the running kernel + whenever you want). The module is called romfs.o. If you want to + compile it as a module, say M here and read + Documentation/modules.txt. If you don't know whether you need it, then you don't need it: answer N. @@ -9907,13 +10370,14 @@ CONFIG_QNX4FS_FS This is the file system used by the operating system QNX 4. Say Y if you intend to mount QNX hard disks or floppies. Unless you say Y to - "QNX4FS write support" below, you will only be able to read + "QNX4FS read-write support" below, you will only be able to read these file systems. - This file system support is also available as a module ( = code which - can be inserted in and removed from the running kernel whenever you - want). The module is called qnx4.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. + This file system support is also available as a module ( = code + which can be inserted in and removed from the running kernel + whenever you want). The module is called qnx4.o. If you want to + compile it as a module, say M here and read + Documentation/modules.txt. If you don't know whether you need it, then you don't need it: answer N. @@ -9933,6 +10397,10 @@ ftp://ftp.kernel.org/pub/linux/daemons/autofs ; you also want to answer Y to "NFS file system support", below. + If you want to use the newer version of the automounter with more + features, say N here and say Y to "Kernel automounter v4 support", + below. + If you want to compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read Documentation/modules.txt. The module will be @@ -9941,10 +10409,7 @@ If you are not a part of a fairly large, distributed network, you probably do not need an automounter, and can say N here. - If you want to use the newer version of autofs with more features, - say N here and select automounter v4. - -Kernel automounter version 4 support (also supports v3) +Kernel automounter v4 support CONFIG_AUTOFS4_FS The automounter is a tool to automatically mount remote file systems on demand. This implementation is partially kernel-based to reduce @@ -9961,15 +10426,16 @@ called autofs4.o. You will need to add "alias autofs autofs4" to your modules configuration file. - If you are not a part of a fairly large, distributed network or don't - have a laptop which needs to dynamically reconfigure to the local - network, you probably do not need an automounter, and can say N here. + If you are not a part of a fairly large, distributed network or + don't have a laptop which needs to dynamically reconfigure to the + local network, you probably do not need an automounter, and can say + N here. -EFS file system support (read only) (EXPERIMENTAL) +EFS file system support (read-only) (EXPERIMENTAL) CONFIG_EFS_FS - EFS is an older file system used for non-ISO9660 CDROMs and hard disk - partitions by SGI's IRIX operating system (IRIX 6.0 and newer uses - the XFS file system for hard disk partitions however). + EFS is an older file system used for non-ISO9660 CDROMs and hard + disk partitions by SGI's IRIX operating system (IRIX 6.0 and newer + uses the XFS file system for hard disk partitions however). This implementation only offers read-only access. If you don't know what all this is about, it's safe to say N. For more information @@ -9980,12 +10446,7 @@ whenever you want), say M here and read Documentation/modules.txt. The module will be called efs.o. -SGI disklabel support -CONFIG_SGI_DISKLABEL - Say Y to this only if you plan on mounting disks with SGI - disklabels. This is not required to mount EFS-format CDROMs. - -UFS file system support (read only) +UFS file system support (read-only) CONFIG_UFS_FS BSD and derivate versions of Unix (such as SunOS, FreeBSD, NetBSD, OpenBSD and NeXTstep) use a file system called UFS. Some System V @@ -10028,7 +10489,7 @@ Note that the answer to this question won't directly affect the kernel: saying N will just cause this configure script to skip all - the questions about foreign partitioning schemes. + the questions about foreign partitioning schemes. If unsure, say N. @@ -10084,13 +10545,14 @@ Say Y here if you would like to be able to read the hard disk partition table format used by SGI machines. -ADFS file system support (read only) (EXPERIMENTAL) +ADFS file system support (EXPERIMENTAL) CONFIG_ADFS_FS The Acorn Disc Filing System is the standard file system of the RiscOS operating system which runs on Acorn's ARM-based Risc PC systems and the Acorn Archimedes range of machines. If you say Y here, Linux will be able to read from ADFS partitions on hard drives - and from ADFS-formatted floppy discs. + and from ADFS-formatted floppy discs. If you also want to be able to + write to those devices, say Y to "ADFS write support" below. The ADFS partition should be the first partition (i.e., /dev/[hs]d?1) on each of your drives. Please read the file @@ -10103,6 +10565,12 @@ If unsure, say N. +ADFS write support (DANGEROUS) +CONFIG_ADFS_FS_RW + If you say Y here, you will be able to write to ADFS partitions on + hard drives and ADFS-formatted floppy disks. This is experimental + codes, so if you're unsure, say N. + /dev/pts file system for Unix98 PTYs CONFIG_DEVPTS_FS You should say Y here if you said Y to "Unix98 PTY support" above. @@ -10119,7 +10587,8 @@ mode of operation; you also need client programs that use the Unix98 API. - Note that CONFIG_DEVFS_FS is a more general facility. + Note that the experimental "/dev file system support" + (CONFIG_DEVFS_FS) is a more general facility. UnixWare slices support (EXPERIMENTAL) CONFIG_UNIXWARE_DISKLABEL @@ -10127,9 +10596,8 @@ partition (VTOC - Virtual Table of Contents). Its format is incompatible with all other OSes. Saying Y here allows you to read VTOC and further mount UnixWare partitions read-only from within - Linux if you have also said Y to "UFS file system support", "System - V and Coherent file system support" or "BFS file system support", - above. + Linux if you have also said Y to "UFS file system support" or + "System V and Coherent file system support", above. This is mainly used to carry data from a UnixWare box to your Linux box via a removable medium like magneto-optical, ZIP or @@ -10178,9 +10646,9 @@ If you say Y here, your Linux box will be able to act as a Coda *client*. You will need user level code as well, both for the client - and server. Servers are currently user level, i.e. need no kernel - support. Please read Documentation/filesystems/coda.txt and check - out the Coda home page http://www.coda.cs.cmu.edu . + and server. Servers are currently user level, i.e. they need no + kernel support. Please read Documentation/filesystems/coda.txt and + check out the Coda home page http://www.coda.cs.cmu.edu . If you want to compile the coda client support as a module ( = code which can be inserted in and removed from the running kernel @@ -10266,7 +10734,7 @@ To utilize this feature you must use ncpfs-2.0.12 or newer. -NDS interserver authentication domains +NDS authentication support CONFIG_NCPFS_NDS_DOMAINS This allows storing NDS private keys in kernel space where they can be used to authenticate another server as interserver NDS @@ -10295,7 +10763,7 @@ nls codepage 437 CONFIG_NLS_CODEPAGE_437 - The Microsoft fat file system family can deal with filenames in + The Microsoft FAT file system family can deal with filenames in native language character sets. These character sets are stored in so-called DOS codepages. You need to include the appropriate codepage if you want to be able to read/write these filenames on @@ -10306,7 +10774,7 @@ nls codepage 737 CONFIG_NLS_CODEPAGE_737 - The Microsoft fat file system family can deal with filenames in + The Microsoft FAT file system family can deal with filenames in native language character sets. These character sets are stored in so-called DOS codepages. You need to include the appropriate codepage if you want to be able to read/write these filenames on @@ -10317,7 +10785,7 @@ nls codepage 775 CONFIG_NLS_CODEPAGE_775 - The Microsoft fat file system family can deal with filenames in + The Microsoft FAT file system family can deal with filenames in native language character sets. These character sets are stored in so-called DOS codepages. You need to include the appropriate codepage if you want to be able to read/write these filenames on @@ -10328,7 +10796,7 @@ nls codepage 850 CONFIG_NLS_CODEPAGE_850 - The Microsoft fat file system family can deal with filenames in + The Microsoft FAT file system family can deal with filenames in native language character sets. These character sets are stored in so-called DOS codepages. You need to include the appropriate codepage if you want to be able to read/write these filenames on @@ -10343,7 +10811,7 @@ nls codepage 852 CONFIG_NLS_CODEPAGE_852 - The Microsoft fat file system family can deal with filenames in + The Microsoft FAT file system family can deal with filenames in native language character sets. These character sets are stored in so-called DOS codepages. You need to include the appropriate codepage if you want to be able to read/write these filenames on @@ -10357,7 +10825,7 @@ nls codepage 855 CONFIG_NLS_CODEPAGE_855 - The Microsoft fat file system family can deal with filenames in + The Microsoft FAT file system family can deal with filenames in native language character sets. These character sets are stored in so-called DOS codepages. You need to include the appropriate codepage if you want to be able to read/write these filenames on @@ -10367,7 +10835,7 @@ nls codepage 857 CONFIG_NLS_CODEPAGE_857 - The Microsoft fat file system family can deal with filenames in + The Microsoft FAT file system family can deal with filenames in native language character sets. These character sets are stored in so-called DOS codepages. You need to include the appropriate codepage if you want to be able to read/write these filenames on @@ -10377,7 +10845,7 @@ nls codepage 860 CONFIG_NLS_CODEPAGE_860 - The Microsoft fat file system family can deal with filenames in + The Microsoft FAT file system family can deal with filenames in native language character sets. These character sets are stored in so-called DOS codepages. You need to include the appropriate codepage if you want to be able to read/write these filenames on @@ -10387,7 +10855,7 @@ nls codepage 861 CONFIG_NLS_CODEPAGE_861 - The Microsoft fat file system family can deal with filenames in + The Microsoft FAT file system family can deal with filenames in native language character sets. These character sets are stored in so-called DOS codepages. You need to include the appropriate codepage if you want to be able to read/write these filenames on @@ -10397,7 +10865,7 @@ nls codepage 862 CONFIG_NLS_CODEPAGE_862 - The Microsoft fat file system family can deal with filenames in + The Microsoft FAT file system family can deal with filenames in native language character sets. These character sets are stored in so-called DOS codepages. You need to include the appropriate codepage if you want to be able to read/write these filenames on @@ -10407,7 +10875,7 @@ nls codepage 863 CONFIG_NLS_CODEPAGE_863 - The Microsoft fat file system family can deal with filenames in + The Microsoft FAT file system family can deal with filenames in native language character sets. These character sets are stored in so-called DOS codepages. You need to include the appropriate codepage if you want to be able to read/write these filenames on @@ -10418,7 +10886,7 @@ nls codepage 864 CONFIG_NLS_CODEPAGE_864 - The Microsoft fat file system family can deal with filenames in + The Microsoft FAT file system family can deal with filenames in native language character sets. These character sets are stored in so-called DOS codepages. You need to include the appropriate codepage if you want to be able to read/write these filenames on @@ -10428,7 +10896,7 @@ nls codepage 865 CONFIG_NLS_CODEPAGE_865 - The Microsoft fat file system family can deal with filenames in + The Microsoft FAT file system family can deal with filenames in native language character sets. These character sets are stored in so-called DOS codepages. You need to include the appropriate codepage if you want to be able to read/write these filenames on @@ -10439,7 +10907,7 @@ nls codepage 866 CONFIG_NLS_CODEPAGE_866 - The Microsoft fat file system family can deal with filenames in + The Microsoft FAT file system family can deal with filenames in native language character sets. These character sets are stored in so-called DOS codepages. You need to include the appropriate codepage if you want to be able to read/write these filenames on @@ -10450,20 +10918,17 @@ nls codepage 869 CONFIG_NLS_CODEPAGE_869 - The Microsoft fat file system family can deal with filenames in + The Microsoft FAT file system family can deal with filenames in native language character sets. These character sets are stored in so-called DOS codepages. You need to include the appropriate codepage if you want to be able to read/write these filenames on DOS/Windows partitions correctly. This does apply to the filenames only, not to the file contents. You can include several codepages; say Y here if you want to include the DOS codepage for Greek. -### -### Why do we have two codepages for Greek and Cyrillic? -### nls codepage 874 CONFIG_NLS_CODEPAGE_874 - The Microsoft fat file system family can deal with filenames in + The Microsoft FAT file system family can deal with filenames in native language character sets. These character sets are stored in so-called DOS codepages. You need to include the appropriate codepage if you want to be able to read/write these filenames on @@ -10474,7 +10939,7 @@ nls iso8859-1 CONFIG_NLS_ISO8859_1 If you want to display filenames with native language characters - from the Microsoft fat file system family or from JOLIET CDROMs + from the Microsoft FAT file system family or from JOLIET CDROMs correctly on the screen, you need to include the appropriate input/output character sets. Say Y here for the Latin 1 character set, which covers most West European languages such as Albanian, @@ -10485,7 +10950,7 @@ nls iso8859-2 CONFIG_NLS_ISO8859_2 If you want to display filenames with native language characters - from the Microsoft fat file system family or from JOLIET CDROMs + from the Microsoft FAT file system family or from JOLIET CDROMs correctly on the screen, you need to include the appropriate input/output character sets. Say Y here for the Latin 2 character set, which works for most Latin-written Slavic and Central European @@ -10495,7 +10960,7 @@ nls iso8859-3 CONFIG_NLS_ISO8859_3 If you want to display filenames with native language characters - from the Microsoft fat file system family or from JOLIET CDROMs + from the Microsoft FAT file system family or from JOLIET CDROMs correctly on the screen, you need to include the appropriate input/output character sets. Say Y here for the Latin 3 character set, which is popular with authors of Esperanto, Galician, Maltese, @@ -10504,7 +10969,7 @@ nls iso8859-4 CONFIG_NLS_ISO8859_4 If you want to display filenames with native language characters - from the Microsoft fat file system family or from JOLIET CDROMs + from the Microsoft FAT file system family or from JOLIET CDROMs correctly on the screen, you need to include the appropriate input/output character sets. Say Y here for the Latin 4 character set which introduces letters for Estonian, Latvian, and @@ -10513,7 +10978,7 @@ nls iso8859-5 CONFIG_NLS_ISO8859_5 If you want to display filenames with native language characters - from the Microsoft fat file system family or from JOLIET CDROMs + from the Microsoft FAT file system family or from JOLIET CDROMs correctly on the screen, you need to include the appropriate input/output character sets. Say Y here for ISO8859-5, a Cyrillic character set with which you can type Bulgarian, Byelorussian, @@ -10523,7 +10988,7 @@ nls iso8859-6 CONFIG_NLS_ISO8859_6 If you want to display filenames with native language characters - from the Microsoft fat file system family or from JOLIET CDROMs + from the Microsoft FAT file system family or from JOLIET CDROMs correctly on the screen, you need to include the appropriate input/output character sets. Say Y here for ISO8859-6, the Arabic character set. @@ -10531,7 +10996,7 @@ nls iso8859-7 CONFIG_NLS_ISO8859_7 If you want to display filenames with native language characters - from the Microsoft fat file system family or from JOLIET CDROMs + from the Microsoft FAT file system family or from JOLIET CDROMs correctly on the screen, you need to include the appropriate input/output character sets. Say Y here for ISO8859-7, the Modern Greek character set. @@ -10539,7 +11004,7 @@ nls iso8859-8 CONFIG_NLS_ISO8859_8 If you want to display filenames with native language characters - from the Microsoft fat file system family or from JOLIET CDROMs + from the Microsoft FAT file system family or from JOLIET CDROMs correctly on the screen, you need to include the appropriate input/output character sets. Say Y here for ISO8859-8, the Hebrew character set. @@ -10547,7 +11012,7 @@ nls iso8859-9 CONFIG_NLS_ISO8859_9 If you want to display filenames with native language characters - from the Microsoft fat file system family or from JOLIET CDROMs + from the Microsoft FAT file system family or from JOLIET CDROMs correctly on the screen, you need to include the appropriate input/output character sets. Say Y here for the Latin 5 character set, and it replaces the rarely needed Icelandic letters in Latin 1 @@ -10556,7 +11021,7 @@ nls iso8859-10 CONFIG_NLS_ISO8859_10 If you want to display filenames with native language characters - from the Microsoft fat file system family or from JOLIET CDROMs + from the Microsoft FAT file system family or from JOLIET CDROMs correctly on the screen, you need to include the appropriate input/output character sets. Say Y here for the Latin 6 character set, which adds the last Inuit (Greenlandic) and Sami (Lappish) @@ -10566,7 +11031,7 @@ NLS ISO 8859-14 (Latin 8; Celtic) CONFIG_NLS_ISO8859_14 If you want to display filenames with native language characters - from the Microsoft fat file system family or from JOLIET CDROMs + from the Microsoft FAT file system family or from JOLIET CDROMs correctly on the screen, you need to include the appropriate input/output character sets. Say Y here for the Latin 8 character set, which adds the last accented vowels for Welsh (aka Cymraeg) @@ -10576,7 +11041,7 @@ nls iso8859-15 CONFIG_NLS_ISO8859_15 If you want to display filenames with native language characters - from the Microsoft fat file system family or from JOLIET CDROMs + from the Microsoft FAT file system family or from JOLIET CDROMs correctly on the screen, you need to include the appropriate input/output character sets. Say Y here for the Latin 9 character set, which covers most West European languages such as Albanian, @@ -10591,7 +11056,7 @@ nls koi8-r CONFIG_NLS_KOI8_R If you want to display filenames with native language characters - from the Microsoft fat file system family or from JOLIET CDROMs + from the Microsoft FAT file system family or from JOLIET CDROMs correctly on the screen, you need to include the appropriate input/output character sets. Say Y here for the preferred Russian character set. @@ -10608,7 +11073,12 @@ is done with certain key combinations, usually Alt-. The setterm command ("man setterm") can be used to change the - properties (such as colors) of a virtual terminal. + properties (such as colors or beeping) of a virtual terminal. The + man page console_codes(4) ("man console_codes") contains the special + character sequences that can be used to change those properties + directly. The fonts used on virtual terminals can be changed with + the setfont ("man setfont") command and the key bindings are defined + with the loadkeys ("man loadkeys") command. You need at least one virtual terminal device in order to make use of your keyboard and monitor. Therefore, only people configuring an @@ -10634,20 +11104,10 @@ that with a kernel command line option such as "console=tty3" which would use the third virtual terminal as system console. (Try "man bootparam" or see the documentation of your boot loader (lilo or - loadlin) about how to pass options to the kernel at boot time. The - lilo procedure is also explained in the SCSI-HOWTO, available from - http://www.linuxdoc.org/docs.html#howto .) + loadlin) about how to pass options to the kernel at boot time.) If unsure, say Y. -Software generated cursor -CONFIG_SOFTCURSOR - If you say Y here, you'll be able to do lots of nice things with the - cursors of your virtual consoles -- for example turn them into - non-blinking block cursors which are more visible on laptop screens, - or change their colors depending on the virtual console they're on. - See Documentation/VGA-softcursor.txt for more information. - Support for PowerMac keyboard CONFIG_MAC_KEYBOARD This option allows you to use an ADB keyboard attached to your @@ -10698,9 +11158,7 @@ you can alter that using a kernel command line option such as "console=ttyS1". (Try "man bootparam" or see the documentation of your boot loader (lilo or loadlin) about how to pass options to the - kernel at boot time. The lilo procedure is also explained in the - SCSI-HOWTO, available from - http://www.linuxdoc.org/docs.html#howto .) + kernel at boot time.) If you don't have a VGA card installed and you say Y here, the kernel will automatically use the first serial line, /dev/ttyS0, as @@ -10766,11 +11224,11 @@ Computone IntelliPort Plus serial support CONFIG_COMPUTONE This driver supports the entire family of Intelliport II/Plus - controllers with the exception of the MicroChannel controllers. It - does not support products previous to the Intelliport II. These are - multiport cards, which give you many serial ports. You would need - something like this to connect more than two modems to your Linux - box, for instance in order to become a dial-in server. If you have a + controllers with the exception of the MicroChannel controllers and + products previous to the Intelliport II. These are multiport cards, + which give you many serial ports. You would need something like + this to connect more than two modems to your Linux box, for + instance in order to become a dial-in server. If you have a card like that, say Y here and read Documentation/computone.txt. If you want to compile this as a module ( = code which can be @@ -10818,13 +11276,13 @@ Cyclades-Z interrupt mode operation (EXPERIMENTAL) CONFIG_CYZ_INTR - The Cyclades-Z family of multiport cards allows 2 (two) driver - op modes: polling and interrupt. In polling mode, the driver will - check the status of the Cyclades-Z ports every certain amount of - time (which is called polling cycle and is configurable). In - interrupt mode, it will use an interrupt line (IRQ) in order to check - the status of the Cyclades-Z ports. The default op mode is polling. - If unsure, say N. + The Cyclades-Z family of multiport cards allows 2 (two) driver op + modes: polling and interrupt. In polling mode, the driver will check + the status of the Cyclades-Z ports every certain amount of time + (which is called polling cycle and is configurable). In interrupt + mode, it will use an interrupt line (IRQ) in order to check the + status of the Cyclades-Z ports. The default op mode is polling. If + unsure, say N. Stallion multiport serial support CONFIG_STALDRV @@ -10899,6 +11357,24 @@ and read Documentation/modules.txt. The module will be called esp.o. If unsure, say N. +Moxa Intellio support +CONFIG_MOXA_INTELLIO + Say Y here if you have a Moxa Intellio multiport serial card. + + This driver can also be built as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called moxa.o. If you want to do that, say M + here. + +Moxa SmartIO support +CONFIG_MOXA_SMARTIO + Say Y here if you have a Moxa SmartIO multiport serial card. + + This driver can also be built as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called mxser.o. If you want to do that, say M + here. + Multi-Tech multiport card support (EXPERIMENTAL) CONFIG_ISI This is a driver for the Multi-Tech cards which provide several @@ -10964,10 +11440,8 @@ If you have several parallel ports, you can specify which ports to use with the "lp" kernel command line option. (Try "man bootparam" or see the documentation of your boot loader (lilo or loadlin) about - how to pass options to the kernel at boot time. The lilo procedure - is also explained in the SCSI-HOWTO, available from - http://www.linuxdoc.org/docs.html#howto .) The syntax of the "lp" - command line option can be found in drivers/char/lp.c. + how to pass options to the kernel at boot time.) The syntax of the + "lp" command line option can be found in drivers/char/lp.c. If you have more than 3 printers, you need to increase the LP_NO variable in lp.c. @@ -10980,11 +11454,118 @@ option "console=lp" to the kernel at boot time. Note that kernel messages can get lost if the printer is out of - paper (or off, or unplugged, or too busy..), but this behavior + paper (or off, or unplugged, or too busy..), but this behaviour can be changed. See drivers/char/lp.c (do this at your own risk). If unsure, say N. +Support for user-space parallel port device drivers +CONFIG_PPDEV + Saying Y to this adds support for /dev/parport device nodes. This + is needed for programs that want portable access to the parallel + port, for instance deviceid (which displays Plug-and-Play device + IDs). + + This is the parallel port equivalent of SCSI generic support (sg). + It is safe to say N to this -- it is not needed for normal printing + or parallel port CD-ROM/disk support. + + This support is also available as a module. If you want to compile + it as a module, say M here and read Documentation/modules.txt. The + module will be called ppdev.o. + + If unsure, say N. + +I2C support +CONFIG_I2C + I2C (pronounce: I-square-C) is a slow serial bus protocol used in + many micro controller applications and developed by Philips. SMBus, + or System Management Bus is a subset of the I2C protocol. More + information is contained in the directory Documentation/i2c/, + especially in the file called "summary" there. + + Both I2C and SMBus are supported here. You will need this for + hardware sensors support, and also for Video for Linux support. + Specifically, if you want to use a BT848 based frame grabber/overlay + boards under Linux, say Y here and also to "I2C bit-banging + interfaces", below. + + If you want I2C support, you should say Y here and also to the + specific driver for your bus adapter(s) below. If you say Y to + "/proc file system" below, you will then get a /proc interface which + is documented in Documentation/i2c/proc-interface. + + This I2C support is also available as a module. If you want to + compile it as a module, say M here and read + Documentation/modules.txt. The module will be called i2c-core.o. + +I2C bit-banging interfaces +CONFIG_I2C_ALGOBIT + This allows you to use a range of I2C adapters called bit-banging + adapters. Say Y if you own an I2C adapter belonging to this class + and then say Y to the specific driver for you adapter below. + + This support is also available as a module. If you want to compile + it as a module, say M here and read Documentation/modules.txt. The + module will be called i2c-algo-bit.o. + +Philips style parallel port adapter +CONFIG_I2C_PHILIPSPAR + This supports parallel-port I2C adapters made by Philips. Say Y if + you own such an adapter. + + This driver is also available as a module. If you want to compile + it as a module, say M here and read Documentation/modules.txt. The + module will be called i2c-philips-par.o. + +ELV adapter +CONFIG_I2C_ELV + This supports parallel-port I2C adapters called ELV. Say Y if you + own such an adapter. + + This driver is also available as a module. If you want to compile + it as a module, say M here and read Documentation/modules.txt. The + module will be called i2c-elv.o. + +Velleman K9000 adapter +CONFIG_I2C_VELLEMAN + This supports the Velleman K9000 parallel-port I2C adapter. Say Y if + you own such an adapter. + + This driver is also available as a module. If you want to compile + it as a module, say M here and read Documentation/modules.txt. The + module will be called i2c-velleman.o. + +I2C PCF 8584 interfaces +CONFIG_I2C_ALGOPCF + This allows you to use a range of I2C adapters called PCF adapters. + Say Y if you own an I2C adapter belonging to this class and then say + Y to the specific driver for you adapter below. + + This support is also available as a module. If you want to compile + it as a module, say M here and read Documentation/modules.txt. The + module will be called i2c-algo-pcf.o. + +Elektor ISA card +CONFIG_I2C_ELEKTOR + This supports the PCF8584 ISA bus I2C adapter. Say Y if you own such + an adapter. + + This driver is also available as a module. If you want to compile + it as a module, say M here and read Documentation/modules.txt. The + module will be called i2c-elektor.o. + +I2C device interface +CONFIG_I2C_CHARDEV + Say Y here to use i2c-* device files, usually found in the /dev + directory on your system. They make it possible to have user-space + programs use the I2C bus. Information on how to do this is contained + in the file Documentation/i2c/dev-interface. + + This code is also available as a module. If you want to compile + it as a module, say M here and read Documentation/modules.txt. The + module will be called i2c-dev.o. + Bus Mouse Support CONFIG_BUSMOUSE Say Y here if your machine has a bus mouse as opposed to a serial @@ -11069,7 +11650,7 @@ PC110 digitizer pad support CONFIG_PC110_PAD - This drives the digitizer pad on the IBM PC110 palmtop. It can turn + This drives the digitizer pad on the IBM PC110 palmtop. It can turn the digitizer pad into a PS/2 mouse emulation with tap gestures or into an absolute pad. @@ -11258,11 +11839,10 @@ kernel driver. Saying Y will enlarge the size of the ftape driver by approximately 2 KB. - WARNING: When compiling ftape as a module (i.e. saying M to - "Floppy tape drive") it is dangerous to use ftape's /proc file - system interface. Accessing `/proc/ftape' while the module is - unloaded will result in a kernel Oops. This cannot be fixed from - inside ftape. + WARNING: When compiling ftape as a module (i.e. saying M to "Floppy + tape drive") it is dangerous to use ftape's /proc file system + interface. Accessing `/proc/ftape' while the module is unloaded will + result in a kernel Oops. This cannot be fixed from inside ftape. Controlling the amount of debugging output of ftape CONFIG_FT_NORMAL_DEBUG @@ -11434,50 +12014,52 @@ Direct Rendering Manager (XFree86 DRI support) CONFIG_DRM Kernel-level support for the Direct Rendering Infrastructure (DRI) - introduced in XFree86 4.x. These modules provide support for - synchronization, security, and DMA transfers. Select the module that - provides support for your graphics card. + introduced in XFree86 4.x. If you say Y here, you need to select + the module that's right for your graphics card from the list below. + These modules provide support for synchronization, security, and + DMA transfers. Please read drivers/char/drm/README.drm for more + details. -tdfx Direct Rendering Manager (XFree86 DRI support) +3dfx Banshee/Voodoo3 CONFIG_DRM_TDFX Choose M here if you have a 3dfx Banshee/Voodoo3 graphics card. + The module will be called tdfx.o. 3dlabs GMX 2000 Direct Rendering Driver (XFree86 DRI support) CONFIG_DRM_GAMMA Choose M here if you have a 3dlabs GMX 2000 graphics card. + The module will be called gamma.o. MTRR control and configuration CONFIG_MTRR On Intel P6 family processors (Pentium Pro, Pentium II and later) the Memory Type Range Registers (MTRRs) may be used to control - processor access to memory ranges. This is most useful when you have + processor access to memory ranges. This is most useful if you have a video (VGA) card on a PCI or AGP bus. Enabling write-combining allows bus write transfers to be combined into a larger transfer before bursting over the PCI/AGP bus. This can increase performance - of image write operations 2.5 times or more. This option creates a - /proc/mtrr file which may be used to manipulate your - MTRRs. Typically the X server should use this. This should have a - reasonably generic interface so that similar control registers on - other processors can be easily supported. + of image write operations 2.5 times or more. Saying Y here creates a + /proc/mtrr file which may be used to manipulate your processor's + MTRRs. Typically the X server should use this. + + This code has a reasonably generic interface so that similar + control registers on other processors can be easily supported + as well: The Cyrix 6x86, 6x86MX and M II processors have Address Range Registers (ARRs) which provide a similar functionality to MTRRs. For - these, the ARRs are used to emulate the MTRRs, which means that it - makes sense to say Y here for these processors as well. - + these, the ARRs are used to emulate the MTRRs. The AMD K6-2 (stepping 8 and above) and K6-3 processors have two MTRRs. The Centaur C6 (WinChip) has 8 MCRs, allowing - write-combining. All of these processors are supported by this code. - - The Centaur C6 (WinChip) has 8 MCRs, allowing write-combining. These - are supported. + write-combining. All of these processors are supported by this code + and it makes sense to say Y here if you have one of them. Saying Y here also fixes a problem with buggy SMP BIOSes which only - set the MTRRs for the boot CPU and not the secondary CPUs. This can - lead to all sorts of problems. + set the MTRRs for the boot CPU and not for the secondary CPUs. This + can lead to all sorts of problems, so it's good to say Y here. You can safely say Y even if your machine doesn't have MTRRs, you'll - just add about 9K to your kernel. + just add about 9 KB to your kernel. See Documentation/mtrr.txt for more information. @@ -11487,11 +12069,6 @@ determined automatically, so you need to specify it here ONLY if running a DEC Alpha, otherwise this setting has no effect. -Zilog serial support -CONFIG_SUN_ZS - This driver does not exist at this point, so you might as well - say N. - Double Talk PC internal speech card support CONFIG_DTLK This driver is for the DoubleTalk PC, a speech synthesizer @@ -11531,26 +12108,54 @@ Power Management support CONFIG_PM - This enable the kernel to lower the requested computer power by making some - devices enter in lower power levels (standy, sleep, ... modes). - Basically, this let you save power. - - Two majors interfaces exist between the hardware and the OS, the older - Advanced Power Management (APM) and the newer Advanced Configuration and - Power Interface (ACPI). - - Both are supported by the Linux Kernel. - - Note that on some architectures (such as ia32), the idle task perform hlt - instructions which makes the CPU enter a low power mode. This can be seen as - the first kernel PM level. + "Power Management" means that parts of your computer are shut + off or put into a power conserving "sleep" mode if they are not + being used. There are two competing standards for doing this: APM + and ACPI. If you want to use either one, say Y here and then also to + the requisite support below. + + Power Management is most important for battery powered laptop + computers; if you have a laptop, check out the Linux Laptop home + page on the WWW at + http://www.cs.utexas.edu/users/kharker/linux-laptop/ and the Battery + Powered Linux mini-HOWTO, available from + http://www.linuxdoc.org/docs.html#howto . + + Note that, even if you say N here, Linux on the x86 architecture + will issue the hlt instruction if nothing is to be done, thereby + sending the processor to sleep and saving power. + +ACPI support +CONFIG_ACPI + The Advanced Configuration and Power Interface is a standard + designed to allow the operating system more control over power + management issues, such as suspending a computer in a low power + consumption state after a certain time of inaction. It aims to be + an improved version of APM (see below). ACPI has to be + supported by the motherboard. You can read more about the standard + at http://www.teleport.com/~acpi/ . + + If your computer supports ACPI and you want to use it, say Y here. + You will then need supporting software; for location and more + information, please read Documentation/pm.txt and the Battery + Powered Linux mini-HOWTO, available from + http://www.linuxdoc.org/docs.html#howto . + + If you say Y here and also to "Advanced Power Management" (APM) + below, then ACPI has precedence in the sense that, if your hardware + supports ACPI, it will be used and APM won't. + + To compile this driver as a module ( = code which can be inserted in + and removed from the running kernel whenever you want), say M here + and read Documentation/modules.txt. The module will be called + acpi.o. Enter S1 for sleep (EXPERIMENTAL) CONFIG_ACPI_S1_SLEEP - This enable ACPI compliant devices to enter level 1 of ACPI saving - power levels. Basically, this will let them entering in sleep mode. + If you say Y here, ACPI compliant devices can enter level 1 of ACPI + saving power levels. Basically, this will let them enter sleep mode. -Advanced Power Management +Advanced Power Management BIOS support CONFIG_APM APM is a BIOS specification for saving power using several different techniques. This is mostly useful for battery powered laptops with @@ -11565,8 +12170,9 @@ Note that the APM support is almost completely disabled for machines with more than one CPU. - Supporting software is available; for more information, read the - Battery Powered Linux mini-HOWTO, available from + In order to use APM, you will need supporting software. For location + and more information, read Documentation/pm.txt and the Battery + Powered Linux mini-HOWTO, available from http://www.linuxdoc.org/docs.html#howto . This driver does not spin down disk drives (see the hdparm(8) @@ -11578,10 +12184,6 @@ desktop machines also don't have compliant BIOSes, and this driver may cause those machines to panic during the boot phase. - If you are running Linux on a laptop, you may also want to read the - Linux Laptop home page on the WWW at - http://www.cs.utexas.edu/users/kharker/linux-laptop/ . - Generally, if you don't have a battery in your machine, there isn't much point in using this driver and you should say N. If you get random kernel OOPSes or reboots that don't seem to be related to @@ -11689,7 +12291,7 @@ Normally we disable external interrupts while we are making calls to the APM BIOS as a measure to lessen the effects of a badly behaving BIOS implementation. The BIOS should reenable interrupts if it - needs to. Unfortunately, some BIOSes do not - especially those in + needs to. Unfortunately, some BIOSes do not -- especially those in many of the newer IBM Thinkpads. If you experience hangs when you suspend, try setting this to Y. Otherwise, say N. @@ -11724,7 +12326,7 @@ Disable watchdog shutdown on close CONFIG_WATCHDOG_NOWAYOUT - The default watchdog behavior (which you get if you say N here) is + The default watchdog behaviour (which you get if you say N here) is to stop the timer if the process managing it closes the file /dev/watchdog. It's always remotely possible that this process might get killed. If you say Y here, the watchdog cannot be stopped once @@ -11797,34 +12399,47 @@ module, say M here and read Documentation/modules.txt. Most people will say N. -Intel P6 CPU Microcode Update Support +Mixcom Watchdog +CONFIG_MIXCOMWD + This is a driver for the Mixcom hardware watchdog cards. This + watchdog simply watches your kernel to make sure it doesn't freeze, + and if it does, it reboots your computer after a certain amount of + time. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module is called mixcomwd.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. Most people + will say N. + +/dev/cpu/microcode - Intel P6 CPU microcode support CONFIG_MICROCODE - If you say Y here you will be able to update microcode on - Intel processors in P6 family, e.g. Pentium Pro, Pentium II, + If you say Y here and also to "/dev file system support" in the + 'File systems' section, you will be able to update the microcode on + Intel processors in the P6 family, e.g. Pentium Pro, Pentium II, Pentium III, Xeon etc. You will obviously need the actual microcode - binary data itself which is not shipped with the Linux kernel. - You also need to say Y to "/dev file system support" in 'File systems' - section of the kernel configuration menu. + binary data itself which is not shipped with the Linux kernel. - You need to be superuser to do that. For latest news and information - on obtaining all the required ingredients for this driver, check: - - http://www.ocston.org/~tigran/patches/microcode + For latest news and information on obtaining all the required + ingredients for this driver, check: + http://www.ocston.org/~tigran/patches/microcode . This driver 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 microcode.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. + The module will be called microcode.o. If you want to compile it as + a module, say M here and read Documentation/modules.txt. Enhanced Real Time Clock Support CONFIG_RTC If you say Y here and create a character special file /dev/rtc with major number 10 and minor number 135 using mknod ("man mknod"), you - will get access to the real time clock built into your computer. + will get access to the real time clock (or hardware clock) built + into your computer. + Every PC has such a clock built in. It can be used to generate signals from as low as 1Hz up to 8192Hz, and can also be used as a 24 hour alarm. It reports status information via the file - /proc/driver/rtc and its behavior is set by various ioctls on + /proc/driver/rtc and its behaviour is set by various ioctls on /dev/rtc. If you run Linux on a multiprocessor machine and said Y to @@ -11835,6 +12450,15 @@ sampling), then say Y here, and read Documentation/rtc.txt for details. + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module is called rtc.o. If you want to compile it as a module, + say M here and read Documentation/modules.txt. + +### Add +#EFI Real Time Clock Services +#CONFIG_EFI_RTC + Tadpole ANA H8 Support CONFIG_H8 The Hitachi H8/337 is a microcontroller used to deal with the power @@ -11878,6 +12502,11 @@ the file Documentation/joystick.txt which contains more information and the location of the joystick package that you'll need. + This driver 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 joystick.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. + Classic PC analog CONFIG_JOY_ANALOG Say Y here if you have a controller that connects to the PC @@ -11887,30 +12516,55 @@ ThrustMaster FCS or 6 and 8 button gamepads. For more information on how to use the driver please read Documentation/joystick.txt + This driver 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 joy-analog.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + FPGaming and MadCatz A3D CONFIG_JOY_ASSASSIN Say Y here if you have an FPGaming or MadCatz controller using the A3D protocol over the PC gameport. For more information on how to use the driver please read Documentation/joystick.txt + This driver 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 joy-assasin.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + Gravis GrIP CONFIG_JOY_GRAVIS Say Y here if you have a Gravis controller using the GrIP protocol over the PC gameport. For more information on how to use the driver please read Documentation/joystick.txt + This driver 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 joy-gravis.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + Logitech ADI CONFIG_JOY_LOGITECH Say Y here if you have a Logitech controller using the ADI protocol over the PC gameport. For more information on how to use the driver please read Documentation/joystick.txt + This driver 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 joy-logitech.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + Microsoft SideWinder CONFIG_JOY_SIDEWINDER Say Y here if you have a Microsoft controller using the Digital Overdrive protocol over PC gameport. For more information on how to use the driver please read Documentation/joystick.txt + This driver 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 joy-sidewinder.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + ThrustMaster DirectConnect CONFIG_JOY_THRUSTMASTER Say Y here if you have a ThrustMaster controller using the @@ -11918,18 +12572,44 @@ information on how to use the driver please read Documentation/joystick.txt + This driver 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 joy-thrustmaster.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + Creative Labs Blaster CONFIG_JOY_CREATIVE Say Y here if you have a Creative Labs controller using the Blaster protocol over the PC gameport. For more information on how to use the driver please read Documentation/joystick.txt -PDPI Lightning 4 card + This driver 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 joy-creative.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + +PDPI Lightning 4 cards CONFIG_JOY_LIGHTNING Say Y here if you have a PDPI Lightning 4 gamecard and an analog joystick or gamepad connected to it. For more information on how to use the driver please read Documentation/joystick.txt + This driver 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 joy-lightning.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + +Logitech WingMan Warrior +CONFIG_JOY_WARRIOR + Say Y here if you have a Logitech WingMan Warrior controller + connected to your computer's serial port. For more information on + how to use the driver please read Documentation/joystick.txt + + This driver 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 joy-warrior.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + Trident 4DWave and Aureal Vortex gameport CONFIG_JOY_PCI Say Y here if you have a Trident 4DWave DX/NX or Aureal Vortex 1/2 @@ -11937,12 +12617,22 @@ with and ordinary analog joystick. For more information on how to use the driver please read Documentation/joystick.txt + This driver 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 joy-pci.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + Magellan and Space Mouse CONFIG_JOY_MAGELLAN Say Y here if you have a Magellan or Space Mouse 6DOF controller connected to your computer's serial port. For more information on how to use the driver please read Documentation/joystick.txt + This driver 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 joy-magellan.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + SpaceTec SpaceOrb 360 and SpaceBall Avenger CONFIG_JOY_SPACEORB Say Y here if you have a SpaceOrb 360 or SpaceBall Avenger 6DOF @@ -11950,6 +12640,11 @@ information on how to use the driver please read Documentation/joystick.txt + This driver 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 joy-spaceorb.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + SpaceTec SpaceBall 4000 FLX CONFIG_JOY_SPACEBALL Say Y here if you have a SpaceTec SpaceBall 4000 FLX @@ -11957,12 +12652,11 @@ information on how to use the driver please read Documentation/joystick.txt -Logitech WingMan Warrior -CONFIG_JOY_WARRIOR - Say Y here if you have a Logitech WingMan Warrior controller - connected to your computer's serial port. For more information on - how to use the driver please read Documentation/joystick.txt - + This driver 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 joy-spaceball.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + NES, SNES, N64, PSX, Multi CONFIG_JOY_CONSOLE Say Y here if you have a Nintendo Entertainment System gamepad, @@ -11972,15 +12666,25 @@ For more information on how to use the driver please read Documentation/joystick.txt and Documentation/joystick-parport.txt + This driver 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 joy-console.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + Sega, Multi CONFIG_JOY_DB9 Say Y here if you have a Sega Master System gamepad, Sega Genesis gamepad, Sega Saturn gamepad, or a Multisystem -- Atari, Amiga, - Commodore, Amstrad CPC joystick connected to your parallel port. For - more information on how to use the driver please read - Documentation/joystick.txt and Documentation/joystick-parport.txt + Commodore, Amstrad CPC joystick connected to your parallel port. + For more information on how to use the driver please read + Documentation/joystick.txt and Documentation/joystick-parport.txt. + + This driver 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 joy-db9.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. -TurboGraFX interface +TurboGraFX Multisystem interface CONFIG_JOY_TURBOGRAFX Say Y here if you have the TurboGraFX interface by Steffen Schwenke, and want to use it with Multiststem -- Atari, Amiga, Commodore, @@ -11988,12 +12692,22 @@ please read Documentation/joystick.txt and Documentation/joystick-parport.txt + This driver 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 joy-turbografx.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + Amiga joysticks CONFIG_JOY_AMIGA Say Y here if you have an Amiga with a digital joystick connected to it. For more information on how to use the driver please read Documentation/joystick.txt + This driver 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 joy-amiga.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + Atomwide Serial Support CONFIG_ATOMWIDE_SERIAL If you have an Atomwide Serial card for an Acorn system, say Y to @@ -12017,7 +12731,7 @@ row. Do not hold the button down for too long, as the driver does not - alter the behavior of the hardware reset circuitry attached to the + alter the behaviour of the hardware reset circuitry attached to the button; it will still execute a hard reset if the button is held down for longer than approximately five seconds. @@ -12066,7 +12780,7 @@ I'm told that even without a sound card, you can make your computer say more than an occasional beep, by programming the PC speaker. Kernel patches and supporting utilities to do that are in the pcsp - package, available at ftp://ftp.infradead.org/pub/pcsp/. + package, available at ftp://ftp.infradead.org/pub/pcsp/ . OSS sound modules CONFIG_SOUND_OSS @@ -12096,24 +12810,25 @@ This module initializes the older non Plug and Play sound galaxy cards from Aztech. It supports the Waverider Pro 32 - 3D and the Galaxy Washington 16. + If you compile the driver into the kernel, you have to add - "sgalaxy=,,,," to the kernel command line. + "sgalaxy=,,,," to the kernel command + line. Support for AD1816(A) based cards (EXPERIMENTAL) CONFIG_SOUND_AD1816 Say M here if you have a sound card based on the Analog Devices AD1816(A) chip. + If you compile the driver into the kernel, you have to add "ad1816=,,," to the kernel command line. - NOTE: This driver is still EXPERIMENTAL. - See Documentation/sound/AD1816 for further information. - Yamaha OPL3-SA1 audio controller CONFIG_SOUND_OPL3SA1 Say Y or M if you have a Yamaha OPL3-SA1 sound chip, which is usually built into motherboards. Read Documentation/sound/OPL3-SA for details. + If you compile the driver into the kernel, you have to add "opl3sa=,,,,," to the kernel command line. @@ -12124,6 +12839,7 @@ 16 or Logitech SoundMan 16 sound card. Don't answer Y if you have some other card made by Media Vision or Logitech since they are not PAS16 compatible. + If you compile the driver into the kernel, you have to add "pas2=,,,,,,, to the kernel command line. @@ -12138,14 +12854,16 @@ Please read the file Documentation/sound/Soundblaster. You should also say Y here for cards based on the Avance Logic - ALS-007 chip (read Documentation/sound/ALS007) and for cards based + ALS-007 chip (read Documentation/sound/ALS) and for cards based on ESS chips (read Documentation/sound/ESS1868 and Documentation/sound/ESS). If you have an SB AWE 32 or SB AWE 64, say Y here and also to "Additional lowlevel drivers" and to "SB32/AWE support" below and read Documentation/sound/INSTALL.awe. If you have an IBM Mwave card, say Y here and read Documentation/sound/mwave. - If you compile the driver into the kernel and don't want to use isapnp, - you have to add "sb=,,," to the kernel command line. + + If you compile the driver into the kernel and don't want to use + isapnp, you have to add "sb=,,," to the kernel + command line. You can say M here to compile this driver as a module; the module is called sb.o. @@ -12161,6 +12879,7 @@ Say Y here for any type of Gravis Ultrasound card, including the GUS or GUS MAX. See also Documentation/sound/ultrasound for more information on configuring this card with modules. + If you compile the driver into the kernel, you have to add "gus=,,," to the kernel command line. @@ -12174,6 +12893,7 @@ was in the list of supported cards, look at the card specific instructions in the drivers/sound/Readme.cards file. It's safe to answer Y if you have a true MPU401 MIDI interface card. + If you compile the driver into the kernel, you have to add "mpu401=," to the kernel command line. @@ -12182,14 +12902,10 @@ This option enables support for MIDI interfaces based on the 6850 UART chip. This interface is rarely found on sound cards. It's safe to answer N to this question. + If you compile the driver into the kernel, you have to add "uart6850=," to the kernel command line. -VIDC Sound -CONFIG_VIDC_SOUND - Say Y here for ARM systems with the VIDC video controller and 16-bit - Linear sound DACs. If unsure, say N. - PSS (AD1848, ADSP-2115, ESC614) support CONFIG_SOUND_PSS Answer Y or M if you have an Orchid SW32, Cardinal DSP16, Beethoven @@ -12197,6 +12913,7 @@ ADSP-2115 DSP chip + Echo ESC614 ASIC CHIP). For more information on how to compile it into the kernel or as a module see the file Documentation/sound/PSS. + If you compile the driver into the kernel, you have to add "pss=,,,,," to the kernel command line. @@ -12223,16 +12940,6 @@ Enter the full pathname of your DSPxxx.LD file or SYNTH.LD file, starting from /. -16 bit sampling option of GUS (_NOT_ GUS MAX) -CONFIG_SOUND_GUS16 - Answer Y if you have installed the 16 bit sampling daughtercard on - your GUS. Answer N if you have a GUS MAX, since saying Y here - disables GUS MAX support. - -GUS MAX support -CONFIG_SOUND_GUSMAX - Answer Y only if you have a Gravis Ultrasound MAX. - Microsoft Sound System support CONFIG_SOUND_MSS Again think carefully before answering Y to this question. It's safe @@ -12258,8 +12965,10 @@ specific instructions in drivers/sound/Readme.cards. Some drivers have their own MSS support and saying Y to this option will cause a conflict. + If you compile the driver into the kernel, you have to add - "ad1848=,,,[,]" to the kernel command line. + "ad1848=,,,[,]" to the kernel command + line. SGI Visual Workstation on-board audio CONFIG_SOUND_VWSND @@ -12272,16 +12981,15 @@ Answer Y if you have a sound card based on the Ensoniq SoundScape chipset. Such cards are being manufactured at least by Ensoniq, Spea and Reveal (Reveal makes also other cards). + If you compile the driver into the kernel, you have to add - "sscape=,,,," to the kernel command line. + "sscape=,,,," to the kernel command + line. MediaTriX AudioTriX Pro support CONFIG_SOUND_TRIX Answer Y if you have the AudioTriX Pro sound card manufactured by MediaTrix. - If you compile the driver into the kernel, you have to add - "trix=,,,,,,,," - to the kernel command line. Have TRXPRO.HEX firmware file CONFIG_TRIX_HAVE_BOOT @@ -12306,6 +13014,7 @@ and Diamond (latest ones). Note however that the Tropez sound cards have their own driver; if you have one of those, say N here and Y or M to "Full support for Turtle Beach WaveFront", below. + If you compile the driver into the kernel, you have to add "mad16=,,,,," to the kernel command line. @@ -12329,6 +13038,7 @@ CONFIG_SOUND_CS4232 Say Y here if you have a card based on the Crystal CS4232 chip set, which uses its own Plug and Play protocol. + If you compile the driver into the kernel, you have to add "cs4232=,,,,," to the kernel command line. @@ -12341,6 +13051,7 @@ Say Y or M if you have a card based on one of these Yamaha sound chipsets. Read Documentation/sound/OPL3-SA2 for more information on configuring these cards. + If you compile the driver into the kernel, you have to add "opl3sa2=,,,,," to the kernel command line. @@ -12349,6 +13060,7 @@ CONFIG_SOUND_MAUI Say Y here if you have a Turtle Beach Wave Front, Maui, or Tropez sound card. + If you compile the driver into the kernel, you have to add "maui=," to the kernel command line. @@ -12447,15 +13159,11 @@ cards, however). Please read the file Documentation/sound/OPL3 if your card has an OPL3 chip. + If you compile the driver into the kernel, you have to add "opl3=" to the kernel command line. If unsure, say Y. - -Sun Audio support -CONFIG_SUN_AUDIO - This is support for the sound cards on Sun workstations. The code - does not exist yet, so you might as well say N here. ACI mixer (miroPCM12/PCM20) CONFIG_SOUND_ACI_MIXER @@ -12502,6 +13210,7 @@ You should then say Y to "100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support" and N to "Audio Excel DSP 16 (MSS emulation)". + If you compile the driver into the kernel, you have to add "aedsp16=,,,,," to the kernel command line. @@ -12590,7 +13299,7 @@ for Trident 4Dwave. PCI ID 1039:7018 stands for SiS7018. This driver differs slightly from OSS/Free, so PLEASE READ the - comments at of driver/sound/trident.c + comments at the top of driver/sound/trident.c Rockwell WaveArtist CONFIG_SOUND_WAVEARTIST @@ -12599,18 +13308,18 @@ VIA 82Cxxx Audio Codec CONFIG_SOUND_VIA82CXXX - Say Y here to include support for the audio codec found on - VIA 82Cxxx-based chips. Typically these are built into a motherboard. - DO NOT select SoundBlaster or Adlib with this driver, unless you have - a SoundBlaster or Adlib card in addition to your VIA audio chip. + Say Y here to include support for the audio codec found on VIA + 82Cxxx-based chips. Typically these are built into a motherboard. DO + NOT select Sound Blaster or Adlib with this driver, unless you have + a Sound Blaster or Adlib card in addition to your VIA audio chip. NeoMagic 256AV/256ZX sound chipsets CONFIG_SOUND_NM256 Say M here to include audio support for the NeoMagic 256AV/256ZX - chipsets. These are the audio chipsets found in the Sony Z505S/SX/DX, - some Sony F-series, and the Dell Latitude CPi and CPt laptops. It includes - support for an AC97-compatible mixer and an apparently proprietary sound - engine. + chipsets. These are the audio chipsets found in the Sony + Z505S/SX/DX, some Sony F-series, and the Dell Latitude CPi and CPt + laptops. It includes support for an AC97-compatible mixer and an + apparently proprietary sound engine. See Documentation/sound/NM256 for further information. @@ -12627,9 +13336,9 @@ Kernel support for Linux/MIPS 32-bit binary compatibility CONFIG_MIPS32_COMPAT - Select this option this option if you want Linux/MIPS 32-bit binary - compatibility. Since all software available available for Linux/MIPS - is currently 32-bit you should say Y here. + Select this option if you want Linux/MIPS 32-bit binary + compatibility. Since all software available for Linux/MIPS is + currently 32-bit you should say Y here. Build fp exception handler module CONFIG_MIPS_FPE_MODULE @@ -12717,7 +13426,7 @@ X.25 PLP on top of ISDN CONFIG_ISDN_X25 - This feature provides the X.25 protocol over ISDN connections. + This feature provides the X.25 protocol over ISDN connections. See Documentation/isdn/README.x25 for more information if you are thinking about using this. @@ -12782,11 +13491,21 @@ HiSax Support for EURO/DSS1 CONFIG_HISAX_EURO - Enable this if you have a EURO ISDN line. + Say Y or N according to the D-channel protocol which your local + telephone service company provides. -Support for german chargeinfo + NOTE: If you say Y here and you have only one ISDN card installed, + you cannot say Y to "HiSax Support for German 1TR6", below. And vice + versa. + +Support for german charge info CONFIG_DE_AOC - If you have german AOC, you can enable this to get the charginfo. + If you want that the HiSax hardware driver sends messages to the + upper level of the isdn code on each AOCD (Advice Of Charge, During + the call -- transmission of the fee information during a call) and + on each AOCE (Advice Of Charge, at the End of the call -- + transmission of fee information at the end of the call), say Y here. + This works only in Germany. Disable sending complete CONFIG_HISAX_NO_SENDCOMPLETE @@ -12800,12 +13519,17 @@ Disable keypad protocol option CONFIG_HISAX_NO_KEYPAD - If you like to send special dialstrings including * or # without + If you like to send special dial strings including * or # without using the keypad protocol, select this option. -HiSax Support for german 1TR6 +HiSax Support for German 1TR6 CONFIG_HISAX_1TR6 - Enable this if you have a old german 1TR6 line. + Say Y or N according to the D-channel protocol which your local + telephone service company provides. + + NOTE: If you say Y here and you have only one ISDN card installed, + you cannot say Y to "HiSax Support for EURO/DSS1", above. And vice + versa. Teles 16.0/8.0 CONFIG_HISAX_16_0 @@ -12829,7 +13553,7 @@ CONFIG_HISAX_TELESPCI This enables HiSax support for the Teles PCI. See Documentation/isdn/README.HiSax on how to configure it. - + Teles S0Box CONFIG_HISAX_S0BOX This enables HiSax support for the Teles/Creatix parallel port @@ -12992,8 +13716,8 @@ HFC-S+, HFC-SP, HFC-PCMCIA cards (EXPERIMENTAL) CONFIG_HISAX_HFC_SX - This enables HiSax support for the HFC-S+, HFC-SP and HFC-PCMCIA cards. - This code is not finished yet. + This enables HiSax support for the HFC-S+, HFC-SP and HFC-PCMCIA + cards. This code is not finished yet. Am7930 (EXPERIMENTAL) CONFIG_HISAX_AMD7930 @@ -13049,10 +13773,16 @@ CAPI2.0 support CONFIG_ISDN_CAPI - This provides the CAPI (Common ISDN Application Programming Interface, a - standard making it easy for programs to access ISDN hardware, see - http://www.capi.org/. This is needed for AVM's set of active ISDN - controllers like B1, T1, M1. + This provides the CAPI (Common ISDN Application Programming + Interface, a standard making it easy for programs to access ISDN + hardware, see http://www.capi.org/ . This is needed for AVM's set of + active ISDN controllers like B1, T1, M1. + + This code is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The modules will be called capi.o and kernelcapi.o. If you want to + compile it as a module, say M here and read + Documentation/modules.txt. AVM B1 ISA support CONFIG_ISDN_DRV_AVMB1_B1ISA @@ -13091,7 +13821,6 @@ disconnecting. This will increase the size of the kernel by 7 KB. If unsure, say Y. - IBM Active 2000 support (EXPERIMENTAL) CONFIG_ISDN_DRV_ACT2000 Say Y here if you have an IBM Active 2000 ISDN card. In order to use @@ -13100,12 +13829,12 @@ isdn4k-utils package. Please read the file Documentation/isdn/README.act2000 for more information. -Support for AP1000 multicomputer -CONFIG_AP1000 - This enables support for a SPARC based parallel multi-computer - called AP1000+. For details on our efforts to port Linux to this - machine see http://cap.anu.edu.au/cap/projects/linux or mail to - hackers@cafe.anu.edu.au +Hypercope HYSDN cards (Champ, Ergo, Metro) support (module) +CONFIG_HYSDN + Say Y here if you have one of Hypercope's active PCI ISDN cards + Champ, Ergo and Metro. You will then get a module called hysdn.o. + Please read the file Documentation/isdn/README.hysdn for more + information. Support for Sun4 architecture CONFIG_SUN4 @@ -13127,11 +13856,11 @@ CONFIG_SCSI_QLOGICPTI This driver supports SBUS SCSI controllers from PTI or QLogic. These controllers are known under Solaris as qpti and in the openprom as - PTI,ptisp or QLGC,isp. Note that PCI QLogic SCSI controllers are driven - by a different driver. + PTI,ptisp or QLGC,isp. Note that PCI QLogic SCSI controllers are + driven by a different driver. - This support is also available as a module called qlogicpti.o ( = code - which can be inserted in and removed from the running kernel + This support is also available as a module called qlogicpti.o ( = + code which can be inserted in and removed from the running kernel whenever you want). If you want to compile it as a module, say M here and read Documentation/modules.txt. @@ -13147,14 +13876,14 @@ Openprom tree appears in /proc/openprom CONFIG_SUN_OPENPROMFS - If you say Y, the OpenPROM device tree will be available as a virtual - file system, which you can mount to /proc/openprom by - "mount -t openpromfs none /proc/openprom". - - If you want to compile the /proc/openprom support as a module ( = code - which can be inserted in and removed from the running kernel whenever - you want), say M here and read Documentation/modules.txt. The module - will be called openpromfs.o. If unsure, say M. + If you say Y, the OpenPROM device tree will be available as a + virtual file system, which you can mount to /proc/openprom by "mount + -t openpromfs none /proc/openprom". + + If you want to compile the /proc/openprom support as a module ( = + code which can be inserted in and removed from the running kernel + whenever you want), say M here and read Documentation/modules.txt. + The module will be called openpromfs.o. If unsure, say M. Kernel support for Linux/Sparc 32bit binary compatibility CONFIG_SPARC32_COMPAT @@ -13195,8 +13924,8 @@ JavaStation OS Flash SIMM (EXPERIMENTAL) CONFIG_SUN_JSFLASH - This option enables a driver for JavaStation OS Flash driver. - Say N unless you want to boot from your Flash SIMM. + If you say Y here, you will be able to boot from your JavaStation's + Flash memory. Siemens SAB82532 serial support CONFIG_SAB82532 @@ -13212,8 +13941,9 @@ CONFIG_SPARCAUDIO This driver provides support for the build-in sound devices on most Sun machines. If you want to be able to use this, select this option - and one or more of the lowlevel drivers below. See - http://www.dementia.org/~shadow/sparcaudio.html for more information. + and one or more of the lowlevel drivers below. See + http://www.dementia.org/~shadow/sparcaudio.html for more + information. AMD7930 Lowlevel Driver CONFIG_SPARCAUDIO_AMD7930 @@ -13227,108 +13957,20 @@ DBRI Lowlevel Driver CONFIG_SPARCAUDIO_DBRI - This driver supports the DBRI audio interface found on the SS10, SS20, - Sparcbook 3, and Voyager systems. + This driver supports the DBRI audio interface found on the SS10, + SS20, Sparcbook 3, and Voyager systems. Dummy lowlevel Driver CONFIG_SPARCAUDIO_DUMMY - This is a pseudo-driver used for debugging and testing the sparcaudio - subsystem. Say N unless you want to work on this subsystem. + This is a pseudo-driver used for debugging and testing the + sparcaudio subsystem. Say N unless you want to work on this + subsystem. Sparc hardware (EXPERIMENTAL) CONFIG_PARPORT_SUNBPP - This driver provides support for the bidirectional parallel port found - on many Sun machines. Note that many of the newer Ultras actually have - pc style hardware instead. - -IEEE 1394 (aka FireWire) support -CONFIG_IEEE1394 - IEEE 1394 describes a high performance serial bus, which is also - known as FireWire(tm) or i.Link(tm) and is used for connecting all - sorts of devices (most notably digital video cameras). - - If you have FireWire hardware and want to use it, say Y here. This - is the core support only, you will also need to select a driver for - your IEEE 1394 adapter. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read Documentation/modules.txt. The module will be - called ieee1394.o. - - FireWire is a trademark by Apple Inc. and i.Link is a trademark by - Sony. - -TI PCILynx IEEE 1394 support -CONFIG_IEEE1394_PCILYNX - Say Y here if you have a IEEE-1394 controller with the Texas - Instruments PCILynx chip. Note: this driver is written for revision - 2 of this chip and may not work with revision 0. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read Documentation/modules.txt. The module will be - called pcilynx.o. - -Use local RAM on PCILynx board -CONFIG_IEEE1394_PCILYNX_LOCALRAM - This option makes the PCILynx driver use local RAM available on some - PCILynx setups for Packet Control Lists. Local RAM may speed up - command processing because no PCI transfers are necessary during - use of the Packet Control Lists. - - Note that there are no known PCILynx systems providing local RAM - except for the evaluation boards by Texas Instruments and that the - PCILynx does not reliably report missing RAM. - - Unless you are absolutely sure that you have 64kB of local RAM and - that you want to use it or if you don't know what this is all about, - say N here. - -Adaptec AIC-5800 IEEE 1394 support -CONFIG_IEEE1394_AIC5800 - Say Y here if you have a IEEE 1394 controller using the Adaptec - AIC-5800 chip. All Adaptec host adapters (89xx series) use this - chip, as well as miro's DV boards. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read Documentation/modules.txt. The module will be - called aic5800.o. - -OHCI (Open Host Controller Interface) support -CONFIG_IEEE1394_OHCI1394 - Say Y here if you have a IEEE 1394 controller based on OHCI. - The current driver was only tested with OHCI chipsets made - by Texas Instruments. However, most third-party vendors use - TI chips. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read Documentation/modules.txt. The module will be - called ohci1394.o. - -Raw IEEE 1394 I/O support -CONFIG_IEEE1394_RAWIO - Say Y here if you want support for the raw device. This is generally - a good idea, so you should say Y here. The raw device enables - direct communication of user programs to the IEEE 1394 bus. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read Documentation/modules.txt. The module will be - called raw1394.o. - -Excessive debugging output -CONFIG_IEEE1394_VERBOSEDEBUG - If you say Y here, you will get very verbose debugging logs from the - subsystem which includes a dump of the header of every sent and - received packet. This can amount to a high amount of data collected - in a very short time which is usually also saved to disk by the - system logging daemons. - - Say Y if you really want or need the debugging output, everyone else - says N. + This driver provides support for the bidirectional parallel port + found on many Sun machines. Note that many of the newer Ultras + actually have pc style hardware instead. # # m68k-specific kernel options @@ -13370,23 +14012,12 @@ Sun 3X support CONFIG_SUN3X - This option enables support for the Sun 3x series of workstations. Be - warned that this support is very experimental. You will also want to - say Y to 68020 support and N to the other processors below. + This option enables support for the Sun 3x series of workstations. + Be warned that this support is very experimental. You will also want + to say Y to 68020 support and N to the other processors below. If you don't want to compile a kernel for a Sun 3x, say N. -Sun 3 support -CONFIG_SUN3 - This option enables support for the Sun 3 series of workstations. Be - warned that this support is very experimental. You will also want to - say Y to 68020 support and N to the other processors below. - Currently, it is not possible to build a kernel with support for the - Sun 3 and something else, so make sure you have said N to all the - other machines. This option does not support the sun3x series of - machines (the Sun 3/80 and 3/460). If you don't want to compile a - kernel for a Sun 3, say N. - 68020 support CONFIG_M68020 If you anticipate running this kernel on a computer with a MC68020 @@ -13444,7 +14075,13 @@ This gives you access to some advanced options for the CPU. The defaults should be fine for most users, but these options may make it possible for you to improve performance somewhat if you know what - you are doing. Most users should say N to this question. + you are doing. + + Note that the answer to this question won't directly affect the + kernel: saying N will just cause this configure script to skip all + the questions about these options. + + Most users should say N to this question. Use read-modify-write instructions CONFIG_RMW_INSNS @@ -13465,8 +14102,9 @@ cards that obey the AutoConfig(tm) specification. Say Y if you want your expansion cards to be identified on bootup; it will enlarge your kernel by about 10 KB. The identification - information is also available through /proc/zorro (say Y to - "/proc file system support"!). + information is then also available through /proc/zorro (say Y to + "/proc file system support"!). Read Documentation/zorro.txt for more + information. Note that even if you say N here, you can still use your expansion cards. If in doubt, say Y. @@ -13476,23 +14114,6 @@ Include support in the kernel for pcmcia on Amiga 1200 and Amiga 600. If you intend to use pcmcia cards say Y; otherwise say N. -Amiga GSP (TMS340x0) support -CONFIG_AMIGA_GSP - Include support for Amiga graphics cards that use the Texas - Instruments TMS340x0 GSP (Graphics Signal Processor) chips. Say Y - if you want to use a DMI Resolver or Commodore A2410 (Lowell) - graphics card on an Amiga; otherwise, say N. - -DMI Resolver support -CONFIG_GSP_RESOLVER - Include support in the kernel for the DMI Resolver graphics card. If - you have one, say Y; otherwise, say N. - -A2410 support -CONFIG_GSP_A2410 - Include support in the kernel for the Commodore/University of Lowell - A2410 graphics card. If you have one, say Y; otherwise, say N. - Amiga Zorro II ramdisk support CONFIG_AMIGA_Z2RAM This enables support for using Chip RAM and Zorro II RAM as a @@ -13591,7 +14212,7 @@ and the optional Cyberstorm SCSI controller, say Y. Otherwise, answer N. -Blizzard 2060 SCSI support +Blizzard 2060 SCSI support (EXPERIMENTAL) CONFIG_BLZ2060_SCSI If you have an Amiga with a Phase5 Blizzard 2060 accelerator board and want to use the onboard SCSI controller, say Y. Otherwise, @@ -13603,7 +14224,7 @@ 1260 accelerator, and the optional SCSI module, say Y. Otherwise, say N. -Blizzard PowerUP 603e+ SCSI support (EXPERIMENTAL) +Blizzard PowerUP 603e+ SCSI support CONFIG_BLZ603EPLUS_SCSI If you have an Amiga 1200 with a Phase5 Blizzard PowerUP 603e+ accelerator, say Y. Otherwise, say N. @@ -13706,16 +14327,6 @@ ACSI port ("ACSI node"). The driver works (has to work...) with a polled I/O scheme, so it's rather slow :-( -Multiface Card III parallel support -CONFIG_MULTIFACE_III_LP - If you have a Multiface III card for your Amiga, and want to use its - parallel port in Linux, say Y. Otherwise, say N. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module is called lp_m68k.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. - Amiga mouse support CONFIG_AMIGAMOUSE If you want to be able to use an Amiga mouse in Linux, say Y. @@ -13725,13 +14336,6 @@ The module is called amigamouse.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. -Amiga Copper Console -CONFIG_COPCON - This configures the console to use the Amiga's graphics coprocessor - for scrolling, instead of using the CPU. This option markedly - improves response times in the high color modes (5 bitplanes and - up). If you would like to use this, say Y; otherwise, say N. - Atari mouse support CONFIG_ATARIMOUSE If you want to be able to use an Atari mouse in Linux, say Y. @@ -13821,12 +14425,44 @@ If you want to compile it as a module, say M here and read Documentation/modules.txt. -Amiga or Atari DMA sound support -CONFIG_DMASOUND - If you want to use the internal audio of your Atari or Amiga in - Linux, answer Y to this question. This will provide a Sun-like - /dev/audio, compatible with the Linux/i386 sound system. Otherwise, - say N. +Atari DMA sound support +CONFIG_DMASOUND_ATARI + If you want to use the internal audio of your Atari in Linux, answer + Y to this question. This will provide a Sun-like /dev/audio, + compatible with the Linux/i386 sound system. Otherwise, say N. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you + want). If you want to compile it as a module, say M here and read + Documentation/modules.txt. + +PowerMac DMA sound support +CONFIG_DMASOUND_AWACS + If you want to use the internal audio of your PowerMac in Linux, + answer Y to this question. This will provide a Sun-like /dev/audio, + compatible with the Linux/i386 sound system. Otherwise, say N. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you + want). If you want to compile it as a module, say M here and read + Documentation/modules.txt. + +Amiga DMA sound support +CONFIG_DMASOUND_PAULA + If you want to use the internal audio of your Amiga in Linux, answer + Y to this question. This will provide a Sun-like /dev/audio, + compatible with the Linux/i386 sound system. Otherwise, say N. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you + want). If you want to compile it as a module, say M here and read + Documentation/modules.txt. + +Q40 sound support +CONFIG_DMASOUND_Q40 + If you want to use the internal audio of your Q40 in Linux, answer + Y to this question. This will provide a Sun-like /dev/audio, + compatible with the Linux/i386 sound system. Otherwise, say N. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you @@ -13843,11 +14479,6 @@ If you want to use the builtin "LANCE" Ethernet controller on an HP300 machine, say Y here. -Sun 3 onboard LANCE support -CONFIG_SUN3LANCE - If you want to use the onboard AMD "LANCE" (le) Ethernet hardware - on a Sun 3, you will need to say Y here. - DIO bus support CONFIG_DIO Say Y here to enable support for the "DIO" expansion bus used in @@ -13857,10 +14488,10 @@ Processor Type CONFIG_6xx There are three types of PowerPC chips supported. The more common - types (601, 603, 604, 740, 750), the Motorola embedded versions (821, - 823, 850, 855, 860), and the IBM embedded versions (403 and 405). - Unless you are building a kernel for one of the embedded processor - systems, choose 6xx. + types (601, 603, 604, 740, 750), the Motorola embedded versions + (821, 823, 850, 855, 860), and the IBM embedded versions (403 and + 405). Unless you are building a kernel for one of the embedded + processor systems, choose 6xx. Machine Type CONFIG_PMAC @@ -13932,6 +14563,35 @@ whenever you want). If you want to compile it as a module, say M here and read Documentation/modules.txt. +GMAC (G4/iBook ethernet) support +CONFIG_GMAC + Say Y for support of GMAC Ethernet interfaces. These are used on G4 + and iBook computers. + + This driver is also available as a module called gmac.o ( = code + which can be inserted in and removed from the running kernel + whenever you want). If you want to compile it as a module, say M + here and read Documentation/modules.txt. + +Symbios 53c885 (Synergy ethernet) support +CONFIG_NCR885E + This is and Ethernet driver for the dual-function NCR 53C885 + SCSI/Ethernet controller. + + This driver is also available as a module called ncr885e.o ( = code + which can be inserted in and removed from the running kernel + whenever you want). If you want to compile it as a module, say M + here and read Documentation/modules.txt. + +National DP83902AV (Oak ethernet) support +CONFIG_OAKNET + Say Y if your machine has this type of Ethernet network card. + + This driver is also available as a module called oaknet.o ( = code + which can be inserted in and removed from the running kernel + whenever you want). If you want to compile it as a module, say M + here and read Documentation/modules.txt. + Video For Linux CONFIG_VIDEO_DEV Support for audio/video capture and overlay devices and FM radio @@ -14037,10 +14697,6 @@ say M here and read Documentation/modules.txt. The module will be called radio-cadet.o. -ADS Cadet AM/FM Radio Tuner Card I/O Port -CONFIG_RADIO_CADET_PORT - Enter the I/O address of the card here (most commonly 330). - SF16FMI Radio CONFIG_RADIO_SF16FMI Choose Y here if you have one of these FM radio cards, and then fill @@ -14160,7 +14816,9 @@ GemTek i/o port CONFIG_RADIO_GEMTEK_PORT Enter either 0x20c, 0x30c, 0x24c or 0x34c here. The card default is - 0x34c, if you haven't changed the jumper setting on the card. + 0x34c, if you haven't changed the jumper setting on the card. On + Sound Vision 16 Gold PnP with FM Radio (ESS1869+FM Gemtek), the i/o + port is 0x28c. PlanB Video-In for PowerMacs CONFIG_VIDEO_PLANB @@ -14179,34 +14837,56 @@ Note: This driver is in its early stages. Right now volume and frequency control and muting works at least for me, but unfortunately i have not found anybody who wants to use this card - with linux. So if it is this what YOU are trying to do right now, + with Linux. So if it is this what YOU are trying to do right now, PLEASE DROP ME A NOTE!! Rolf Offermanns (rolf@offermanns.de) In order to control your radio card, you will need to use programs that are compatible with the Video for Linux API. Information on this API and pointers to "v4l" programs may be found on the WWW at - http://roadrunner.swansea.uk.linux.org/v4l.shtml; to browse the WWW, - you need to have access to a machine on the Internet that has a - program like lynx or netscape. + http://roadrunner.swansea.uk.linux.org/v4l.shtml . If you want to compile this driver as a module ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read Documentation/modules.txt. The module will be called radio-terratec.o. +Terratec i/o port (normally 0x590) +CONFIG_RADIO_TERRATEC_PORT + Fill in the i/o port of your TerraTec FM radio card. If unsure, go + with the default. + +### Add these # Zoran ZR36057/36060 support # CONFIG_VIDEO_ZORAN # Include support for Iomega Buz # CONFIG_VIDEO_BUZ +Trust FM radio card +CONFIG_RADIO_TRUST + This is a driver for the Trust FM radio cards. Say Y if you have + such a card and want to use it under Linux. + + This driver is also available as a module called radio-trust.o ( = + code which can be inserted in and removed from the running kernel + whenever you want). If you want to compile it as a module, say M + here and read Documentation/modules.txt. + +Trust i/o port (usually 0x350 or 0x358) +CONFIG_RADIO_TRUST_PORT + Enter the i/o port of your Trust FM radio card. If unsure, try the + values "0x350" or "0x358". + BT848 Video For Linux CONFIG_VIDEO_BT848 Support for BT848 based frame grabber/overlay boards. This includes the Miro, Hauppauge and STB boards. Please read the material in Documentation/video4linux/bttv for more information. - This driver is also available as a module called bttv.o ( = code + If you say Y or M here, you need to say Y or M to "I2C support" and + "I2C bit-banging interfaces" in the character device section. + + This driver is available as a module called bttv.o ( = code which can be inserted in and removed from the running kernel whenever you want). If you want to compile it as a module, say M here and read Documentation/modules.txt. @@ -14245,11 +14925,12 @@ Colour QuickCam Video For Linux CONFIG_VIDEO_CQCAM - This is the video4linux driver for the color version of the + This is the video4linux driver for the colour version of the Connectix Quickcam. If you have one of these cameras, say Y here, otherwise say N. This driver does not work with the original monochrome Quickcam, Quickcam VC or QuickClip. It is also available - as a module (c-qcam.o). + as a module (c-qcam.o). Read Documentation/video4linux/CQcam.txt for + more information. Mediavision Pro Movie Studio Video For Linux CONFIG_VIDEO_PMS @@ -14266,114 +14947,9 @@ boards supported by this driver, and for further information on the use of this driver. -QuickNet Internet LineJack/PhoneJack support -CONFIG_PHONE_IXJ - Say M if you have a telephony card manufactured by Quicknet - Technologies, Inc. These include the Internet PhoneJACK and - Internet LineJACK Telephony Cards. - - For the ISA versions of these products, you can configure the - cards using the isapnp tools (pnpdump/isapnp) or you can use the - isapnp support. Please read: - - /usr/src/linux/Documentation/telephony/ixj.txt. - - For more information on these cards, see Quicknet's website at: - http://www.quicknet.net/ - - If you do not have any Quicknet telephony cards, you can safely - ignore this option. - -/dev/agpgart (AGP Support) (EXPERIMENTAL) -CONFIG_AGP - The agpgart kernel module is necessary to use the AGP features - of your 3D rendering video card. It acts as a sort of "AGP - driver" for the motherboard's chipset. - Loading this module into the kernel will allow the glx module to - program the GART (graphics aperture relocation table) registers - with appropriate values to transfer commands to the card. - - If you need more texture memory than you can get with the AGP GART - (theoretically up to 256 megs, but in practice usually 64 or 128 - megs due to kernel allocation issues), you could use PCI accesses - and have up to a couple gigs of texture space. - - Note that this is the only mean to have get XFree4/GLX use - write-combining with MTRR support on AGP bus. Without, OpenGL - direct rendering will be a lot slower but still faster than PIO. - - For the moment, most people should say no, unless you want to - test the GLX component which can be downloaded from - http://glx.on.openprojects.net/ - - or need to use the 810 Xserver in XFree 3.3.6 - -Intel 440LX/BX/GX support -CONFIG_AGP_INTEL - This option give you AGP support for the GLX component of the - "soon to be released" XFree86-4 on Intel 440LX/BX/GX chipsets. - - For the moment, most people should say no, unless you want to - test the GLX component which can be downloaded from - http://glx.on.openprojects.net/ - -Intel I810/I810 DC100/I810e support -CONFIG_AGP_I810 - This option give you AGP support for the Xserver for the intel - 810 chipset boards. This is required to do any useful video - modes. - -VIA VP3/MVP3/Apollo Pro support -CONFIG_AGP_VIA - This option give you AGP support for the GLX component of the - "soon to be released" XFree86-4 on VIA MPV3/Apollo Pro chipsets. - - For the moment, most people should say no, unless you want to - test the GLX component which can be downloaded from - http://glx.on.openprojects.net/ - -AMD Irongate support -CONFIG_AGP_AMD - This option give you AGP support for the GLX component of the - "soon to be released" XFree86-4 on Intel AMD Irongate chipset. - - For the moment, most people should say no, unless you want to - test the GLX component which can be downloaded from - http://glx.on.openprojects.net/ - -Generic SiS support -CONFIG_AGP_SIS - This option give you AGP support for the GLX component of the - "soon to be released" XFree86-4 on Silicon Integrated Systems [SiS] - chipsets. - - Note than 5591/5592 AGP chipsets are NOT supported. - - For the moment, most people should say no, unless you want to - test the GLX component which can be downloaded from - http://glx.on.openprojects.net/ - -ALI M1541 support -CONFIG_AGP_ALI - This option give you AGP support for the GLX component of the - "soon to be released" XFree86-4 on ALI M1541 chipset. - - For the moment, most people should say no, unless you want to - test the GLX component which can be downloaded from - http://glx.on.openprojects.net/ - # # ARM options # -CPU Optimization -CONFIG_CPU_ARM2 - This selects the processor type of your CPU. This is only used to - determine C compiler optimization options, and can affect the - compatibility of the kernel on other processors. If you specify - ARM6, the kernel should work on all 32-bit processors. If you - specify ARM2, ARM250 or ARM3, it should work on all 26-bit - processors. If you're not sure, set it to "None". - ARM System type CONFIG_ARCH_ARC This selects what ARM system you wish to build the kernel for. It @@ -14381,14 +14957,6 @@ to set this option to, please consult any information supplied with your system. -Include support for Chalice CATS boards -CONFIG_CATS - Say Y here if you intend to run this kernel on a CATS system. - -Include support for Intel EBSA285 -CONFIG_ARCH_EBSA285 - board. - Include support for the NetWinder CONFIG_ARCH_NETWINDER Say Y here if you intend to run this kernel on the NetWinder. @@ -14412,7 +14980,7 @@ Say Y to include the NWFPE floating point emulator in the kernel. This is necessary to run most binaries. Linux does not currently support floating point hardware so you need to say Y here even if - your machine has an FPA or floating point co-processor module. + your machine has an FPA or floating point co-processor podule. It is also possible to say M to build the emulator as a module (nwfpe.o) or indeed to leave it out altogether. However, unless you @@ -14441,12 +15009,6 @@ you are concerned with the code size or don't want to see these messages. -Build Tools Selection -CONFIG_BINUTILS_NEW - Say Y here if and only if you're using GCC 2.8.1/EGCS with a - binutils version >= 2.8.1 to compile the kernel (check with "gcc - --version" and "ld -v"). - Compile kernel with frame pointer CONFIG_FRAME_POINTER If you say Y here, the resulting kernel will be slightly larger and @@ -14469,12 +15031,12 @@ time and disk space needed for compilation of the kernel. If in doubt say N. -Split initialization functions into discardable section +Split initialisation functions into discardable section CONFIG_TEXT_SECTIONS If you say Y here, kernel code that is only used during - initialization is collected into a special area of the kernel so + initialisation is collected into a special area of the kernel so that it can be discarded and the memory reclaimed when - initialization is complete. In addition, if the kernel you wish to + initialisation is complete. In addition, if the kernel you wish to build is able to run on multiple architectures, it allows the unused code to be discarded. Some versions of binutils, however, have a bug that causes the kernel to crash during startup when this option is @@ -14535,7 +15097,7 @@ MFM hard disk support CONFIG_BLK_DEV_MFM Support the MFM hard drives on the Acorn Archimedes both - on-board the A4x0 motherboards and via the Acorn MFM modules. + on-board the A4x0 motherboards and via the Acorn MFM podules. Drives up to 64MB are supported. If you haven't got one of these machines or drives just say N. @@ -14553,7 +15115,7 @@ sometimes doesn't work and it also does some dodgy stuff which potentially might damage your drive. -IrDA Protocols +IrDA subsystem support CONFIG_IRDA Say Y here if you want to build support for the IrDA (TM) protocols. The Infrared Data Associations (tm) specifies standards for wireless @@ -14565,8 +15127,9 @@ Documentation/networking/irda.txt. You also want to read the IR-HOWTO, available at http://www.linuxdoc.org/docs.html#howto . - This support is also available as a module. If you want to compile - it as a module, say M here and read Documentation/modules.txt. + This support is also available as a module called irda.o. If you + want to compile it as a module, say M here and read + Documentation/modules.txt. IrDA Cache last LSAP CONFIG_IRDA_CACHE_LAST_LSAP @@ -14623,7 +15186,7 @@ IrLAN Protocol CONFIG_IRLAN Say Y here if you want to build support for the IrLAN protocol. If - you want to compile it as a module, say M here and read + you want to compile it as a module (irlan.o), say M here and read Documentation/modules.txt. IrLAN emulates an Ethernet and makes it possible to put up a wireless LAN using infrared beams. @@ -14635,19 +15198,20 @@ IrCOMM Protocol CONFIG_IRCOMM Say Y here if you want to build support for the IrCOMM protocol. If - you want to compile it as a module, say M here and read - Documentation/modules.txt. IrCOMM implements serial port emulation, - and makes it possible to use all existing applications that - understands TTY's with an infrared link. Thus you should be able to - use application like PPP, minicom and others. Enabling this option - will create two modules called ircomm and ircomm-tty. + you want to compile it as a module (you will get ircomm.o and + ircomm-tty.o), say M here and read Documentation/modules.txt. IrCOMM + implements serial port emulation, and makes it possible to use all + existing applications that understands TTY's with an infrared link. + Thus you should be able to use application like PPP, minicom and + others. Enabling this option will create two modules called ircomm + and ircomm_tty. IrTTY IrDA Device Driver CONFIG_IRTTY_SIR Say Y here if you want to build support for the IrTTY line - discipline. If you want to compile it as a module, say M here and - read Documentation/modules.txt. IrTTY makes it possible to use - Linux's own serial driver for all IrDA ports that are 16550 + discipline. If you want to compile it as a module (irtty.o), say M + here and read Documentation/modules.txt. IrTTY makes it possible to + use Linux's own serial driver for all IrDA ports that are 16550 compatible. Most IrDA chips are 16550 compatible so you should probably say Y to this option. Using IrTTY will however limit the speed of the connection to 115200 bps (IrDA SIR mode) @@ -14657,50 +15221,62 @@ IrPORT IrDA Device Driver CONFIG_IRPORT_SIR Say Y here if you want to build support for the IrPORT IrDA device - driver. If you want to compile it as a module, say M here and - read Documentation/modules.txt. IrPORT can be used instead of - IrTTY and sometimes this can be better. One example is if your - IrDA port does not have echo-canceling, which will work OK with - IrPORT since this driver is working in half-duplex mode only. You - don't need to use irattach with IrPORT, but you just insert it - the same way as FIR drivers (insmod irport io=0x3e8 irq=11). - Notice that IrPORT is a SIR device driver which means that speed - is limited to 115200 bps. + driver. If you want to compile it as a module (irport.o), say M here + and read Documentation/modules.txt. IrPORT can be used instead of + IrTTY and sometimes this can be better. One example is if your IrDA + port does not have echo-canceling, which will work OK with IrPORT + since this driver is working in half-duplex mode only. You don't + need to use irattach with IrPORT, but you just insert it the same + way as FIR drivers (insmod irport io=0x3e8 irq=11). Notice that + IrPORT is a SIR device driver which means that speed is limited to + 115200 bps. If unsure, say Y. -SiS5513 chipset support -CONFIG_BLK_DEV_SIS5513 - This driver ensures (U)DMA support for SIS5513 chipset based - mainboards. SiS620/530 UDMA mode 4, SiS5600/5597 UDMA mode 2, all - other DMA mode 2 limited chipsets are unsupported to date. - - If you say Y here, you need to say Y to "Use DMA by default when - available" as well. - - Please read the comments at the top of drivers/block/sis5513.c - Winbond W83977AF IrDA Device Driver CONFIG_WINBOND_FIR Say Y here if you want to build IrDA support for the Winbond - W83977AF super-io chipset. If you want to compile it as a module, - say M here and read Documentation/modules.txt. This driver should be - used for the IrDA chipset in the Corel NetWinder. The driver - supports SIR, MIR and FIR (4Mbps) speeds. + W83977AF super-io chipset. This driver should be used for the IrDA + chipset in the Corel NetWinder. The driver supports SIR, MIR and FIR + (4Mbps) speeds. + + If you want to compile it as a module, say M here and read + Documentation/modules.txt. The module will be called w83977af_ir.o. NSC PC87108 IrDA Device Driver CONFIG_NSC_FIR Say Y here if you want to build support for the NSC PC87108 and - PC87338 IrDA chipsets. If you want to compile it as a module, say M - here and read Documentation/modules.txt. This driver supports SIR, - MIR and FIR (4Mbps) speeds. + PC87338 IrDA chipsets. This driver supports SIR, + MIR and FIR (4Mbps) speeds. + + If you want to compile it as a module, say M here and read + Documentation/modules.txt. The module will be called nsc-ircc.o. Toshiba Type-O IR Port Device Driver CONFIG_TOSHIBA_FIR Say Y here if you want to build support for the Toshiba Type-O IR - chipset. If you want to compile it as a module, say M here and - read Documentation/modules.txt. This chipset is used by the Toshiba - Libretto 100CT, and many more laptops. + chipset. This chipset is used by the Toshiba Libretto 100CT, and + many more laptops. If you want to compile it as a module, say M here + and read Documentation/modules.txt. The module will be called + toshoboe.o. + +SMC IrCC (Experimental) +CONFIG_SMC_IRCC_FIR + Say Y here if you want to build support for the SMC Infrared + Communications Controller. It is used in the Fujitsu Lifebook 635t + and Sony PCG-505TX. If you want to compile it as a module, say M + here and read Documentation/modules.txt. The module will be called + smc-ircc.o. + +Serial dongle support +CONFIG_DONGLE + Say Y here if you have an infrared device that connects to your + computer's serial port. These devices are called dongles. Then say Y + or M to the driver for your particular dongle below. + + Note that the answer to this question won't directly affect the + kernel: saying N will just cause this configure script to skip all + the questions about serial dongles. ESI JetEye PC Dongle CONFIG_ESI_DONGLE @@ -14748,6 +15324,14 @@ by IrTTY. To activate support for Parallax dongles you will have to start irattach like this "irattach -d litelink". +Old Belkin dongle +CONFIG_OLD_BELKIN_DONGLE + Say Y here if you want to build support for the Adaptec Airport 1000 + and 2000 dongles. If you want to compile it as a module, say M here + and read Documentation/modules.txt. The module will be called + old_belkin.o. Some information is contained in the comments at the + top of drivers/net/irda/old_belkin.c. + VME (Motorola and BVM) support CONFIG_VME Say Y here if you want to build a kernel for a 680x0 based VME @@ -14795,13 +15379,6 @@ SCSI controller chip. Almost everyone using one of these boards will want to say Y to this question. -Simple 53c710 SCSI support (Compaq, NCR machines) -CONFIG_SCSI_SIM710 - This is a driver for the NCR53C710 chip commonly found in Compaq and - NCR machines. If you are looking for 53C710 support for an Amiga or - some 680x0 based VME card then you probably want the other NCR53C710 - driver. - MVME16x Ethernet support CONFIG_MVME16x_NET This is the driver for the Ethernet interface on the Motorola @@ -14916,6 +15493,31 @@ files, usually found in the /dev directory on your system. They make it possible to have user-space programs use the I2C bus. +CPiA Video For Linux +CONFIG_VIDEO_CPIA + This is the video4linux driver for cameras based on Vision's CPiA + (Colour Processor Interface ASIC), such as the Creative Labs Video + Blaster Webcam II. If you have one of these cameras, say Y here + and select parallel port and/or USB lowlevel support below, + otherwise say N. This will not work with the Creative Webcam III. + It is also available as a module (cpia.o). + +CPiA Parallel Port Lowlevel Support +CONFIG_VIDEO_CPIA_PP + This is the lowlevel parallel port support for cameras based on + Vision's CPiA (Colour Processor Interface ASIC), such as the + Creative Webcam II. If you have the parallel port version of one + of these cameras, say Y here, otherwise say N. It is also available + as a module (cpia_pp.o). + +CPiA USB Lowlevel Support +CONFIG_VIDEO_CPIA_USB + This is the lowlevel USB support for cameras based on Vision's CPiA + (Colour Processor Interface ASIC), such as the Creative Webcam II. + If you have the USB version of one of these cameras, say Y here, + otherwise say N. This will not work with the Creative Webcam III. + It is also available as a module (cpia_usb.o). + # # A couple of things I keep forgetting: # capitalize: AppleTalk, Ethernet, DOS, DMA, FAT, FTP, Internet, @@ -14930,7 +15532,7 @@ # LocalWords: CONFIG coprocessor DX Pentium SX lilo loadlin HOWTO ftp metalab # LocalWords: unc edu docs emu README kB BLK DEV FD Thinkpad fd MFM RLL IDE gz # LocalWords: cdrom diskless netboot nfs xzvf ATAPI MB ide pavia rubini pl pd -# LocalWords: HD CDROMs IDECD NEC MITSUMI XT XD PCI BIOS cezar ATEN +# LocalWords: HD CDROMs IDECD NEC MITSUMI filesystem XT XD PCI BIOS cezar ATEN # LocalWords: ISA EISA Microchannel VESA BIOSes IPC SYSVIPC ipc Ctrl dmesg hlt # LocalWords: BINFMT Linkable http ac uk jo html GCC SPARC AVANTI CABRIOLET EB # LocalWords: netscape gcc LD CC toplevel MODVERSIONS insmod rmmod modprobe IP @@ -14960,11 +15562,11 @@ # LocalWords: readprofile diskdrives org com masq EtherTalk tcp netrom sunacm # LocalWords: misc AIC aic pio scc Portmaster eql GIS PhotoCDs MCDX Perell PG # LocalWords: mcdx gscd optcd sjcd ISP hdparm Workgroups Lan samba PARIDE PCD -# LocalWords: smbfs ATA ppp PCTech RZ www powerquest txt CMD ESDI +# LocalWords: filesystems smbfs ATA ppp PCTech RZ www powerquest txt CMD ESDI # LocalWords: chipset FB multicast MROUTE appletalk ifconfig IBMTR multiport # LocalWords: Multisession STALDRV EasyIO EC EasyConnection ISTALLION ONboard # LocalWords: Brumby pci TNC cis ohio faq usenet NETLINK dev hydra ca Tyne mem -# LocalWords: carleton Deskstation DECstation SUNFD JENSEN Noname XXXM SLiRP +# LocalWords: carleton DECstation SUNFD JENSEN Noname XXXM SLiRP LILO's amifb # LocalWords: pppd Zilog ZS SRM bootloader ez mainmenu rarp ipfwadm paride pcd # LocalWords: RTNETLINK mknod xos MTU lwared Macs mac netatalk macs cs Wolff # LocalWords: dartmouth flowerpt MultiMaster FlashPoint tudelft etherexpress @@ -14977,12 +15579,13 @@ # LocalWords: PMAX MILO Alphas Multia Tseng linuxelf endian mipsel mips drv HT # LocalWords: kerneld callouts AdvanSys advansys Admin WDT DataStor EP verden # LocalWords: wdt hdb hdc bugfix SiS vlb Acculogic CSA DTC dtc Holtek ht QDI -# LocalWords: QD qd UMC umc ALI ali oss sgi com azstarnet cdr fb MDA ps esdi +# LocalWords: QD qd UMC umc ALI ali lena fnet fr azstarnet cdr fb MDA ps esdi # LocalWords: Avanti XL AlphaStations Jensen DECpc AXPpci UDB Cabriolet MCA RC # LocalWords: AlphaPC mca AOUT OUTput PPro sipx gwdg lo nwe FourPort Boca unm # LocalWords: Keepalive linefill RELCOM keepalive analogue CDR conf CDI INIT # LocalWords: OPTi isp irq noisp VFAT vfat NTFS losetup dmsdosfs dosfs ISDN MP -# LocalWords: NOWAYOUT behavior dialin isdn callback BTX Teles ICN EDSS Cisco +# LocalWords: NOWAYOUT behaviour dialin isdn callback BTX Teles XXXX LVM lvm +ICN EDSS Cisco # LocalWords: ipppd syncppp RFC MPP VJ downloaded icn NICCY Creatix shmem ufr # LocalWords: ibp md ARCnet ether encap NDIS arcether ODI Amigas AmiTCP NetBSD # LocalWords: initrd tue util DES funet des OnNet BIOSP smc Travan Iomega CMS @@ -15052,12 +15655,12 @@ # LocalWords: caldera Preload Preloading slowdowns schoebel uni NBD nbd prog # LocalWords: stuttgart rdist TRANS hostnames mango jukeboxes ESS userland PD # LocalWords: hardlinked NAMETRANS env mtab fstab umount nologin runlevel gid -# LocalWords: transname filespace adm Nodename hostname uname Kernelname bootp +# LocalWords: filespace adm Nodename hostname uname Kernelname bootp nmi DI OV # LocalWords: KERNNAME kname ktype kernelname Kerneltype KERNTYPE Alt RX mdafb # LocalWords: dataless kerneltype SYSNAME Comtrol Rocketport palmtop fbset EGS # LocalWords: nvram SYSRQ SysRq PrintScreen sysrq NVRAMs NvRAM Shortwave RTTY -# LocalWords: Sitor Amtor Pactor GTOR hayes TX TMOUT JFdocs HIGHMEM DAC IRQ's -# LocalWords: IDEPCI IDEDMA idedma PDC pdc TRM trm raidtools luthien nuclecu +# LocalWords: Sitor Amtor Pactor GTOR hayes TX TMOUT JFdocs BIGMEM DAC IRQ's +# LocalWords: IDEPCI IDEDMA PDC pdc TRM trm raidtools luthien nuclecu BAGET VR # LocalWords: unam mx miguel koobera uic EMUL solaris pp ieee lpsg co DMAs TOS # LocalWords: BLDCONFIG preloading jumperless BOOTINIT modutils multipath GRE # LocalWords: misconfigured autoconfiguration IPGRE ICMP tracert ipautofw PIM @@ -15073,7 +15676,7 @@ # LocalWords: Braam braam Schmidt's freiburg nls codepages codepage Romanian # LocalWords: Slovak Slovenian Sorbian Nordic iso Catalan Faeroese Galician SZ # LocalWords: Valencian Slovene Esperanto Estonian Latvian Byelorussian KOI mt -# LocalWords: charset Inuit Greenlandic Sami Lappish koi SOFTCURSOR softcursor +# LocalWords: charset Inuit Greenlandic Sami Lappish koi Alexey Kuznetsov's sa # LocalWords: Specialix specialix DTR RTS RTSCTS cycladesZ Exabyte ftape's inr # LocalWords: Iomega's LBFM claus ZFTAPE VFS zftape zft William's lzrw DFLT kb # LocalWords: MTSETBLK MTIOCTOP qft setblk zftape's tar's afio's setdrvbuffer @@ -15087,7 +15690,7 @@ # LocalWords: struct APIC realtime OSs LynxOS CNC tmp cvf HFS hfs ADFS Risc os # LocalWords: adfs ncpmount namespace SUBDIR reexport NDS kcore FT SPX spx DAT # LocalWords: interserver BLKSZ NUMBUFFERS apmd Tadpole ANA roestock QuickCam -# LocalWords: isapnptools Colour CQCAM color Connectix QuickClip prive mentre +# LocalWords: isapnptools Colour CQCAM colour Connectix QuickClip prive mentre # LocalWords: KMOD kmod conformant utexas kharker UnixWare Mwave cgi cl ts ibm # LocalWords: eXchange threepio oakland simtel pre ULTRAMCA EtherLink isa luik # LocalWords: EtherLink OpenBSD pts DEVPTS devpts ptmx ttyp glibc readback SA @@ -15103,8 +15706,8 @@ # LocalWords: Yellowfin gsfc nasa gov yellowfin pcnet Mylex LNE lne EtherH hs # LocalWords: EBSA chattr RiscOS Winmodem AGP Atomwide DUALSP pcsp robinson CT # LocalWords: SGALAXY Waverider DSPxxx TRXPRO AudioTrix OSWF MOT CFB DSY kbps -# LocalWords: tuwien kkudielk LVD mega lun MAXTAGS Gbps arcnet Olicom SKTR SNA -# LocalWords: SysKonnect tms380tr sna etherboot ufs NetBEUI MultiSound MSNDCLAS GX +# LocalWords: tuwien kkudielk LVD mega lun MAXTAGS Gbps arcnet Olicom SNA PAE +# LocalWords: SysKonnect tms sna etherboot ufs NetBEUI MultiSound MSNDCLAS GX # LocalWords: MSNDINIT MSNDPERM MSNDPIN PNDSPINI PNDSPERM Ensoniq's RetinaZ SS # LocalWords: AudioPCI lspci SonicVibes sonicvibes SPARCs roadrunner CLgen UPA # LocalWords: swansea shtml Zoltrix zoltrix BINUTILS EGCS binutils VIDC DACs @@ -15141,7 +15744,7 @@ # LocalWords: ACTiSYS Dongle dongle dongles esi actisys IrMate tekram BVM MVME # LocalWords: BVME BVME WRITETHROUGH copyback writethrough fwmark syncookie tu # LocalWords: alphalinux GOBIOS csn chemnitz nat ACARD AMI MegaRAID megaraid -# LocalWords: QNX4FS ISI isicom xterms Apollos VPN RCPCI rcpci sgi visws pcmcia +# LocalWords: QNXFS ISI isicom xterms Apollos VPN RCPCI rcpci sgi visws pcmcia # LocalWords: IrLPT UIRCC Tecra Strebel jstrebel suse Eichwalder ke INI INIA # LocalWords: FCP qlogicfc sym isapnp DTLK DoubleTalk rcsys dtlk DMAP SGIVW ar # LocalWords: dmabuf EcoRadio MUTEFREQ GIrBIL girbil tepkom vol mha diplom PQS @@ -15151,7 +15754,7 @@ # LocalWords: VROOTHUB KBD ARRs MCRs NWBUTTON nwbutton NUM WaveArtist APNE cpu # LocalWords: apne blackhawke PlanB lu mlan planb NWFPE FPA nwfpe unbootable # LocalWords: FPEmulator ds vmlinux initialisation discardable pgtable PGT mdw -# LocalWords: quicklist pagetable arthur StrongARM module modules Autodetect +# LocalWords: quicklist pagetable arthur StrongARM podule podules Autodetect # LocalWords: dodgy IrPORT irport Litelink litelink SuSE rtfm internet hda CY # LocalWords: multmode DriveReady SeekComplete DriveStatusError miscompile AEC # LocalWords: mainboard's Digital's alim FastTrak aec PIIXn piix Gayle Eyetech @@ -15173,9 +15776,56 @@ # LocalWords: ServeRAID IPS ips ipslinux gzip BSDCOMP LZW RAYCS Interphase app # LocalWords: Tachyon IPHASE Surfboard NextLevel SURFboard jacksonville Tigon # LocalWords: fventuri adelphia siglercm linuxpower AceNICs Starfire starfire -# LocalWords: ISOC CPiA cpia uss ACPI UDF DirectCD udf CDRW's OSF Manx acpi +# LocalWords: ISOC CPiA cpia uss ACPI UDF DirectCD udf CDRW's OSF Manx acpi DM # LocalWords: Unixware cymru Computone IntelliPort Intelliport computone SI sx # LocalWords: adbmouse DRI DRM dlabs GMX PLCs Applicom fieldbus applicom int # LocalWords: VWSND eg ESSSOLO CFU CFNR scribed eiconctrl eicon hylafax KFPU -# LocalWords: EXTRAPREC fpu mainboards KHTTPD kHTTPd khttpd Xcelerator -# LocalWords: LOGIBUSMOUSE OV511 ov511 Integraphics +# LocalWords: EXTRAPREC fpu mainboards KHTTPD kHTTPd khttpd Xcelerator SBNI tw +# LocalWords: LOGIBUSMOUSE Granch granch sbni Raylink NOHIGHMEM Athlon SIM sim +# LocalWords: hpl Tourrilhes DuraLAN starfile Davicom davicom dmfe auk tms tr +# LocalWords: TokenExpress Belkin Peracom eTek DVDs infradead Cxxx Adlib AV ZX +# LocalWords: NeoMagic CPi CPt Celeron decapsulation Undeletion BFS bfs nVidia +# LocalWords: OnStream Irongate Riva phonedev QuickNet LineJack PhoneJack IXJ +# LocalWords: Quicknet PhoneJACK LineJACK ixj pnpdump Quicknet's Joandi SSID +# LocalWords: aironet quickconfig adhoc btw bap NONCS cardservices Xircom lin +# LocalWords: Netwave AirSurfer netwave HomePNA failover MVP iMacs ALi aktual +# LocalWords: Aladin HIDBP usbkbd KEYBDEV MOUSEDEV JOYDEV EVDEV UAB WhiteHEAT +# LocalWords: Handspring ov DABUSB URB URB's dabusb CRAMFS NFSv ELV IOAPIC WIP +# LocalWords: NLMv SMBus ALGOBIT algo PHILIPSPAR philips elv Velleman velleman +# LocalWords: ALGOPCF Elektor elektor CHARDEV dfx TDFX tdfx Extensa dof gravis +# LocalWords: assasin logitech Overdrive thrustmaster DWave Aureal magellan db +# LocalWords: SpaceTec SpaceOrb SpaceBall spaceorb FLX spaceball turbografx zr +# LocalWords: amiga ESS's WaveWatcher Maxi belkin RW's ata glx GART MPV Baget +# LocalWords: OpenGL Xserver agpgart HOTPLUG CyberPro Integraphics Netwinder +# LocalWords: aty FONTWIDTH eni zatm nicstar ForeRunner OC DECstations DEC's +# LocalWords: PHYsical SUNI reinsertion ChipSAR KVC PHY ClassID iphase iadbg +# LocalWords: DEVS FireWire PCILynx pcilynx LOCALRAM miro's DV RAWIO GRED Mk +# LocalWords: Diffserv DSMARK Ingress Qdisc TCINDEX TMSPCI tmspci Ringode JE +# LocalWords: MADGEMC madgemc TokenRing SMCTR TokenCard smctr Wacom Graphire +# LocalWords: WMFORCE mousedev ConnectTech HandSpring Xirlink IBMCAM ibmcam SN +# LocalWords: DEVICEFS yyy userspace Cymraeg Dwave SIMM JSFLASH JavaStation's +# LocalWords: nsc ircc DDB Vrc CMN TB PROMs Vino rivafb DDC Matroxes MGA TVO +# LocalWords: MAVEN fbdev crtc maven matroxset NTSC PCA SBA AAL SKFP DAS SAS +# LocalWords: skfp Intuos ADMtek's pegasus PLUSB plusb pointopoint mp rio Xeon +# LocalWords: DEVFS devfs dd bs EDSS german TELESPCI FRITZPCI HFC HFCS BDS HST +# LocalWords: ISURF ISAR Saphir HSTSAPHIR Telekom BKM Scitel Quadro SCT Gazel +# LocalWords: SP PRI Hypercope HYSDN Hypercope's hysdn IbssJoinNetTimeout FTDI +# LocalWords: ARCNet Keyspan PDA ADMtek sgalaxy sgbase opl mpuio mpuirq sbio +# LocalWords: sbirq sbdma gus uart mssio mssirq mssdma sscape maui mouirq iph +# LocalWords: CHDLC UPS's usbmouse wacom wmforce keybdev joydev fibre Trunking +# LocalWords: Etherchannel IOC Moxa Intellio moxa SmartIO mxser Mixcom EFI ir +# LocalWords: MIXCOMWD mixcomwd SENDCOMPLETE GMAC iBook gmac OAKNET oaknet PCG +# LocalWords: diffserv irlan irtty toshoboe IrCC Lifebook idex AUTODMA FIP Cxx +# LocalWords: Yenta Databook TCIC FMVJ fmvj NMCLAN LiveWire nmclan XIRC xirc +# LocalWords: loadkeys setfont shm SuperIO soc SOCAL socal FCAL fc fcal COMX +# LocalWords: MultiGate ITConsult comx CMX HiCOMX downloadable hw LoCOMX PROTO +# LocalWords: locomx MixCOM mixcom proto MyriCOM MYRI Sbus myri sbus IBMLS hme +# LocalWords: lanstreamer baseT HAPPYMEAL qfe sunhme SUNLANCE sunlance BigMAC +# LocalWords: SUNBMAC sunbmac QuadEthernet SUNQE qe FastEthernet sunqe DSB PTI +# LocalWords: DSBR dsbr procinfo QLOGICPTI qpti ptisp QLGC qlogicpti se LBA NF +# LocalWords: OPENPROMFS OpenPROM openpromfs OBP OpenBoot flashable Multiboard +# LocalWords: SPARCAUDIO SparcClassic Ultras DBRI Sparcbook sparcaudio SUNBPP +# LocalWords: UltraDMA WDC CRC CONNTRACK IPTABLES iptables nfmark interface's +# LocalWords: tdfxfb TNTx HGA hgafb VERBOSEDEBUG SunTrunking SunSoft XIRTULIP +# LocalWords: ethercards PNIC Macronix MXIC ASIX xircom Mustek MDC gphoto mdc +# LocalWords: CramFs Cramfs uid cramfs AVM's kernelcapi PCIV diff -u --recursive --new-file v2.3.99-pre3/linux/Documentation/DocBook/Makefile linux/Documentation/DocBook/Makefile --- v2.3.99-pre3/linux/Documentation/DocBook/Makefile Mon Mar 27 08:08:20 2000 +++ linux/Documentation/DocBook/Makefile Mon Apr 3 13:24:05 2000 @@ -1,7 +1,14 @@ -BOOKS := wanbook.sgml z8530book.sgml mcabook.sgml videobook.sgml kernel-api.sgml - +BOOKS := wanbook.sgml z8530book.sgml mcabook.sgml videobook.sgml kernel-api.sgml parportbook.sgml + +PS := $(patsubst %.sgml, %.ps, $(BOOKS)) +PDF := $(patsubst %.sgml, %.pdf, $(BOOKS)) + books: docproc $(BOOKS) +ps: $(PS) + +pdf: $(PDF) + docproc: $(MAKE) -C $(TOPDIR)/scripts docproc @@ -36,11 +43,32 @@ $(TOPDIR)/drivers/net/wan/syncppp.c \ $(TOPDIR)/drivers/net/wan/z85230.c \ $(TOPDIR)/kernel/pm.c \ + $(TOPDIR)/kernel/ksyms.c \ + $(TOPDIR)/net/netsyms.c \ kernel-api.sgml +parportbook.sgml: parportbook.tmpl + $(TOPDIR)/scripts/docgen $(TOPDIR)/drivers/parport/init.c \ + parportbook.sgml + +DVI := $(patsubst %.sgml, %.dvi, $(BOOKS)) +AUX := $(patsubst %.sgml, %.aux, $(BOOKS)) +TEX := $(patsubst %.sgml, %.tex, $(BOOKS)) +LOG := $(patsubst %.sgml, %.log, $(BOOKS)) + clean: - rm -f core *~ - rm -f $(BOOKS) + $(RM) core *~ + $(RM) $(BOOKS) + $(RM) $(DVI) $(AUX) $(TEX) $(LOG) + +mrproper: clean + $(RM) $(PS) $(PDF) + +%.ps : %.sgml + db2ps $< + +%.pdf : %.sgml + db2pdf $< include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.3.99-pre3/linux/Documentation/DocBook/kernel-api.tmpl linux/Documentation/DocBook/kernel-api.tmpl --- v2.3.99-pre3/linux/Documentation/DocBook/kernel-api.tmpl Mon Mar 27 08:08:20 2000 +++ linux/Documentation/DocBook/kernel-api.tmpl Sun Apr 2 15:38:53 2000 @@ -34,13 +34,71 @@ - - Interrupt Handling -!Iarch/i386/kernel/irq.c + + The Linux VFS + The Directory Cache +!Efs/dcache.c +!Iinclude/linux/dcache.h + + Inode Handling +!Efs/inode.c +!Efs/bad_inode.c + + Registration and Superblocks +!Efs/super.c + + + + + Linux Networking + Socket Buffer Functions +!Iinclude/linux/skbuff.h +!Enet/core/skbuff.c + + Socket Filter +!Enet/core/filter.c + - - MTRR Handling + + + Network device support + Driver Support +!Edrivers/net/net_init.c +!Enet/core/dev.c + + 8390 Based Network Cards +!Edrivers/net/8390.c + + Synchronous PPP +!Edrivers/net/wan/syncppp.c + + + + + Module Loading +!Ekernel/kmod.c + + + + Hardware Interfaces + Interrupt Handling +!Iarch/i386/kernel/irq.c + + + MTRR Handling !Earch/i386/kernel/mtrr.c + + PCI Support Library +!Edrivers/pci/pci.c + + MCA Architecture + MCA Device Functions +!Earch/i386/kernel/mca.c + + MCA Bus DMA +!Iinclude/asm-i386/mca_dma.h + + @@ -58,34 +116,14 @@ !Edrivers/char/videodev.c - - Network devices -!Idrivers/net/net_init.c -!Edrivers/net/8390.c - - Sound Devices !Edrivers/sound/sound_core.c !Idrivers/sound/sound_firmware.c - - MCA Architecture - MCA Device Functions -!Earch/i386/kernel/mca.c - - MCA Bus DMA -!Iinclude/asm-i386/mca_dma.h - - - - - Synchronous PPP -!Edrivers/net/wan/syncppp.c - - + 16x50 UART Driver !Edrivers/char/serial.c @@ -95,9 +133,5 @@ !Edrivers/net/wan/z85230.c - - PCI Support Library -!Edrivers/pci/pci.c - diff -u --recursive --new-file v2.3.99-pre3/linux/Documentation/DocBook/parportbook.sgml linux/Documentation/DocBook/parportbook.sgml --- v2.3.99-pre3/linux/Documentation/DocBook/parportbook.sgml Tue Mar 14 19:10:38 2000 +++ linux/Documentation/DocBook/parportbook.sgml Wed Dec 31 16:00:00 1969 @@ -1,1747 +0,0 @@ - - - - - The Parallel Port Subsystem - - - - Tim - Waugh - -
- twaugh@redhat.com -
-
-
-
- - - 1999-2000 - Tim Waugh - - - - - This documentation 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 - - - - For more details see the file COPYING in the source - distribution of Linux. - - -
- - - - -Design goals - - -The problems - - - - - - -The first parallel port support for Linux came with the line -printer driver, lp. The printer driver is a -character special device, and (in Linux 2.0) had support for writing, -via write, and configuration and statistics -reporting via ioctl. - -The printer driver could be used on any computer that had an IBM -PC-compatible parallel port. Because some architectures have parallel -ports that aren't really the same as PC-style ports, other variants of -the printer driver were written in order to support Amiga and Atari -parallel ports. - -When the Iomega Zip drive was released, and a driver written for -it, a problem became apparent. The Zip drive is a parallel port -device that provides a parallel port of its own---it is designed to -sit between a computer and an attached printer, with the printer -plugged into the Zip drive, and the Zip drive plugged into the -computer. - -The problem was that, although printers and Zip drives were both -supported, for any given port only one could be used at a time. Only -one of the two drivers could be present in the kernel at once. This -was because of the fact that both drivers wanted to drive the same -hardware---the parallel port. When the printer driver initialised, it -would call the check_region function to make sure -that the IO region associated with the parallel port was free, and -then it would call request_region to allocate it. -The Zip drive used the same mechanism. Whichever driver initialised -first would gain exclusive control of the parallel port. - -The only way around this problem at the time was to make sure -that both drivers were available as loadable kernel modules. To use -the printer, load the printer driver module; then for the Zip drive, -unload the printer driver module and load the Zip driver -module. - -The net effect was that printing a document that was stored on a Zip -drive was a bit of an ordeal, at least if the Zip drive and printer -shared a parallel port. A better solution was needed. - -Zip drives are not the only devices that presented problems for -Linux. There are other devices with pass-through ports, for example -parallel port CD-ROM drives. There are also printers that report -their status textually rather than using simple error pins: sending a -command to the printer can cause it to report the number of pages that -it has ever printed, or how much free memory it has, or whether it is -running out of toner, and so on. The printer driver didn't originally -offer any facility for reading back this information (although Carsten -Gross added nibble mode readback support for kernel 2.2). - - - -The IEEE has issued a standards document called IEEE 1284, which -documents existing practice for parallel port communications in a -variety of modes. Those modes are: compatibility, -reverse nibble, reverse byte, ECP and EPP. Newer devices often use -the more advanced modes of transfer (ECP and EPP). In Linux 2.0, the -printer driver only supported compatibility mode -(i.e. normal printer protocol) and reverse nibble mode. - - - - -The solutions - - - -The parport code in Linux 2.2 was designed -to meet these problems of architectural differences in parallel ports, -of port-sharing between devices with pass-through ports, and of lack -of support for IEEE 1284 transfer modes. - - - -There are two layers to the -parport subsystem, only one of which deals -directly with the hardware. The other layer deals with sharing and -IEEE 1284 transfer modes. In this way, parallel support for a -particular architecture comes in the form of a module which registers -itself with the generic sharing layer. - - - -The sharing model provided by the parport -subsystem is one of exclusive access. A device driver, such as the -printer driver, must ask the parport layer for -access to the port, and can only use the port once access has been -granted. When it has finished a transaction, it can -tell the parport layer that it may release the -port for other device drivers to use. - - - -Devices with pass-through ports all manage to share a parallel -port with other devices in generally the same way. The device has a -latch for each of the pins on its pass-through port. The normal state -of affairs is pass-through mode, with the device copying the signal -lines between its host port and its pass-through port. When the -device sees a special signal from the host port, it latches the -pass-through port so that devices further downstream don't get -confused by the pass-through device's conversation with the host -parallel port: the device connected to the pass-through port (and any -devices connected in turn to it) are effectively cut off from the -computer. When the pass-through device has completed its transaction -with the computer, it enables the pass-through port again. - - - - - - - -This technique relies on certain special signals -being invisible to devices that aren't watching for them. This tends -to mean only changing the data signals and leaving the control signals -alone. IEEE 1284.3 documents a standard protocol for daisy-chaining -devices together with parallel ports. - - - -Support for standard transfer modes are provided as operations -that can be performed on a port, along with operations for setting the -data lines, or the control lines, or reading the status lines. These -operations appear to the device driver as function pointers; more -later. - - - - - - -Standard transfer modes - - - - -The standard transfer modes in use over the -parallel port are defined by a document called IEEE -1284. It really just codifies existing practice and documents -protocols (and variations on protocols) that have been in common use -for quite some time. - -The original definitions of which pin did what were set out by -Centronics Data Computer Corporation, but only the printer-side -interface signals were specified. - -By the early 1980s, IBM's host-side implementation had become -the most widely used. New printers emerged that claimed Centronics -compatibility, but although compatible with Centronics they differed -from one another in a number of ways. - -As a result of this, when IEEE 1284 was published in 1994, all -that it could really do was document the various protocols that are -used for printers (there are about six variations on a theme). - -In addition to the protocol used to talk to -Centronics-compatible printers, IEEE 1284 defined other protocols that -are used for unidirectional peripheral-to-host transfers (reverse -nibble and reverse byte) and for fast bidirectional transfers (ECP and -EPP). - - - - -Structure - - - - - - - - - - - - -Sharing core - - - -At the core of the parport subsystem is the -sharing mechanism (see drivers/parport/share.c). -This module, parport, is responsible for -keeping track of which ports there are in the system, which device -drivers might be interested in new ports, and whether or not each port -is available for use (or if not, which driver is currently using -it). - - - - -Parports and their overrides - - -The generic parport sharing code doesn't -directly handle the parallel port hardware. That is done instead by -low-level parport drivers. The -function of a low-level parport driver is to -detect parallel ports, register them with the sharing code, and -provide a list of access functions for each port. - -The most basic access functions that must be provided are ones -for examining the status lines, for setting the control lines, and for -setting the data lines. There are also access functions for setting -the direction of the data lines; normally they are in the -forward direction (that is, the computer drives them), -but some ports allow switching to reverse mode (driven -by the peripheral). There is an access function for examining the -data lines once in reverse mode. - - - - -IEEE 1284 transfer modes - - -Stacked on top of the sharing mechanism, but still in the -parport module, are functions for transferring -data. They are provided for the device drivers to use, and are very -much like library routines. Since these transfer functions are -provided by the generic parport core they must -use the lowest common denominator set of access -functions: they can set the control lines, examine the status lines, -and use the data lines. With some parallel ports the data lines can -only be set and not examined, and with other ports accessing the data -register causes control line activity; with these types of situations, -the IEEE 1284 transfer functions make a best effort attempt to do the -right thing. In some cases, it is not physically possible to use -particular IEEE 1284 transfer modes. - -The low-level parport drivers also provide -IEEE 1284 transfer functions, as names in the access function list. -The low-level driver can just name the generic IEEE 1284 transfer -functions for this. Some parallel ports can do IEEE 1284 transfers in -hardware; for those ports, the low-level driver can provide functions -to utilise that feature. - - - - - - - - -Pardevices and parport_drivers - -When a parallel port device driver (such as -lp) initialises it tells the sharing layer about -itself using parport_register_driver. The -information is put into a struct -parport_driver, which is put into a linked list. The -information in a struct parport_driver really -just amounts to some function pointers to callbacks in the parallel -port device driver. - -During its initialisation, a low-level port driver tells the -sharing layer about all the ports that it has found (using -parport_register_port), and the sharing layer -creates a struct parport for each of them. -Each struct parport contains (among other -things) a pointer to a struct -parport_operations, which is a list of function pointers -for the various operations that can be performed on a port. You can -think of a struct parport as a parallel port -object, if object-orientated programming -is your thing. The parport structures are -chained in a linked list, whose head is portlist -(in drivers/parport/share.c). - -Once the port has been registered, the low-level port driver -announces it. The parport_announce_port function -walks down the list of parallel port device drivers -(struct parport_drivers) calling the -attach function of each. - -Similarly, a low-level port driver can undo the effect of -registering a port with the -parport_unregister_port function, and device -drivers are notified using the detach -callback. - -Device drivers can undo the effect of registering themselves -with the parport_unregister_driver -function. - - - - - - -The IEEE 1284.3 API - -The ability to daisy-chain devices is very useful, but if every -device does it in a different way it could lead to lots of -complications for device driver writers. Fortunately, the IEEE are -standardising it in IEEE 1284.3, which covers daisy-chain devices and -port multiplexors. - -At the time of writing, IEEE 1284.3 has not been published, but -the draft specifies the on-the-wire protocol for daisy-chaining and -multiplexing, and also suggests a programming interface for using it. -That interface (or most of it) has been implemented in the -parport code in Linux. - -At initialisation of the parallel port bus, daisy-chained -devices are assigned addresses starting from zero. There can only be -four devices with daisy-chain addresses, plus one device on the end -that doesn't know about daisy-chaining and thinks it's connected -directly to a computer. - -Another way of connecting more parallel port devices is to use a -multiplexor. The idea is to have a device that is connected directly -to a parallel port on a computer, but has a number of parallel ports -on the other side for other peripherals to connect to (two or four -ports are allowed). The multiplexor switches control to different -ports under software control---it is, in effect, a programmable -printer switch. - -Combining the ability of daisy-chaining five devices together -with the ability to multiplex one parallel port between four gives the -potential to have twenty peripherals connected to the same parallel -port! - -In addition, of course, a single computer can have multiple -parallel ports. So, each parallel port peripheral in the system can -be identified with three numbers, or co-ordinates: the parallel port, -the multiplexed port, and the daisy-chain address. - - - - - - - - - - - - - - - -Each device in the system is numbered at initialisation (by -parport_daisy_init). You can convert between -this device number and its co-ordinates with -parport_device_num and -parport_device_coords. - - - int parport_device_num - int parport - int mux - int daisy - - - - int parport_device_coords - int devnum - int *parport - int *mux - int *daisy - - -Any parallel port peripheral will be connected directly or -indirectly to a parallel port on the system, but it won't have a -daisy-chain address if it does not know about daisy-chaining, and it -won't be connected through a multiplexor port if there is no -multiplexor. The special co-ordinate value -1 is -used to indicate these cases. - -Two functions are provided for finding devices based on their -IEEE 1284 Device ID: parport_find_device and -parport_find_class. - - - int parport_find_device - const char *mfg - const char *mdl - int from - - - - int parport_find_class - parport_device_class cls - int from - - -These functions take a device number (in addition to some other -things), and return another device number. They walk through the list -of detected devices until they find one that matches the requirements, -and then return that device number (or -1 if -there are no more such devices). They start their search at the -device after the one in the list with the number given (at -from+1, in other words). - - - - - - -Device driver's view - - - - - - - - - -This section is written from the point of view of the device -driver programmer, who might be writing a driver for a printer or a -scanner or else anything that plugs into the parallel port. It -explains how to use the parport interface to find -parallel ports, use them, and share them with other device -drivers. - -We'll start out with a description of the various functions that -can be called, and then look at a reasonably simple example of their -use: the printer driver. - -The interactions between the device driver and the -parport layer are as follows. First, the device -driver registers its existence with parport, in -order to get told about any parallel ports that have been (or will be) -detected. When it gets told about a parallel port, it then tells -parport that it wants to drive a device on that -port. Thereafter it can claim exclusive access to the port in order -to talk to its device. - -So, the first thing for the device driver to do is tell -parport that it wants to know what parallel ports -are on the system. To do this, it uses the -parport_register_device function: - - - - - - int parport_register_driver - struct parport_driver *driver - - -In other words, the device driver passes pointers to a couple of -functions to parport, and -parport calls attach for -each port that's detected (and detach for each -port that disappears -- yes, this can happen). - -The next thing that happens is that the device driver tells -parport that it thinks there's a device on the -port that it can drive. This typically will happen in the driver's -attach function, and is done with -parport_register_device: - - - struct pardevice *parport_register_device - struct parport *port - const char *name - int (*pf) - void * - void (*kf) - void * - void (*irq_func) - int, void *, struct pt_regs * - int flags - void *handle - - -The port comes from the parameter supplied -to the attach function when it is called, or -alternatively can be found from the list of detected parallel ports -directly with the (now deprecated) -parport_enumerate function. - -The next three parameters, pf, -kf, and irq_func, are -more function pointers. These callback functions get called under -various circumstances, and are always given the -handle as one of their parameters. - -The preemption callback, pf, is called -when the driver has claimed access to the port but another device -driver wants access. If the driver is willing to let the port go, it -should return zero and the port will be released on its behalf. There -is no need to call parport_release. If -pf gets called at a bad time for letting the -port go, it should return non-zero and no action will be taken. It is -good manners for the driver to try to release the port at the earliest -opportunity after its preemption callback is called. - -The kick callback, kf, is -called when the port can be claimed for exclusive access; that is, -parport_claim is guaranteed to succeed inside the -kick callback. If the driver wants to claim the port -it should do so; otherwise, it need not take any action. - -The irq_func callback is called, -predictably, when a parallel port interrupt is generated. But it is -not the only code that hooks on the interrupt. The sequence is this: -the lowlevel driver is the one that has done -request_irq; it then does whatever -hardware-specific things it needs to do to the parallel port hardware -(for PC-style ports, there is nothing special to do); it then tells -the IEEE 1284 code about the interrupt, which may involve reacting to -an IEEE 1284 event, depending on the current IEEE 1284 phase; and -finally the irq_func function is called. - -None of the callback functions are allowed to block. - -The flags are for telling -parport any requirements or hints that are -useful. The only useful value here (other than -0, which is the usual value) is -PARPORT_DEV_EXCL. The point of that flag is to -request exclusive access at all times---once a driver has successfully -called parport_register_device with that flag, no -other device drivers will be able to register devices on that port -(until the successful driver deregisters its device, of -course). - -The PARPORT_DEV_EXCL flag is for preventing -port sharing, and so should only be used when sharing the port with -other device drivers is impossible and would lead to incorrect -behaviour. Use it sparingly! - -Devices can also be registered by device drivers based on their -device numbers (the same device numbers as in the previous -section). - -The parport_open function is similar to -parport_register_device, and -parport_close is the equivalent of -parport_unregister_device. The difference is -that parport_open takes a device number rather -than a pointer to a struct parport. - - - struct pardevice *parport_open - int devnum - int (*pf) - void * - int (*kf) - void * - int (*irqf) - int, void *, struct pt_regs * - int flags - void *handle - - - - void parport_close - struct pardevice *dev - - - - struct pardevice *parport_register_device - struct parport *port - const char *name - int (*pf) - void * - int (*kf) - void * - int (*irqf) - int, void *, struct pt_regs * - int flags - void *handle - - - - void parport_unregister_device - struct pardevice *dev - - -The intended use of these functions is during driver -initialisation while the driver looks for devices that it supports, as -demonstrated by the following code fragment: - - - - -Once your device driver has registered its device and been -handed a pointer to a struct pardevice, the -next thing you are likely to want to do is communicate with the device -you think is there. To do that you'll need to claim access to the -port. - - - int parport_claim - struct pardevice *dev - - - - int parport_claim_or_block - struct pardevice *dev - - - - void parport_release - struct pardevice *dev - - -To claim access to the port, use -parport_claim or -parport_claim_or_block. The first of these will -not block, and so can be used from interrupt context. If -parport_claim succeeds it will return zero and -the port is available to use. It may fail (returning non-zero) if the -port is in use by another driver and that driver is not willing to -relinquish control of the port. - -The other function, parport_claim_or_block, -will block if necessary to wait for the port to be free. If it slept, -it returns 1; if it succeeded without needing to -sleep it returns 0. If it fails it will return a -negative error code. - -When you have finished communicating with the device, you can -give up access to the port so that other drivers can communicate with -their devices. The parport_release function -cannot fail, but it should not be called without the port claimed. -Similarly, you should not try to claim the port if you already have it -claimed. - -You may find that although there are convenient points for your -driver to relinquish the parallel port and allow other drivers to talk -to their devices, it would be preferable to keep hold of the port. -The printer driver only needs the port when there is data to print, -for example, but a network driver (such as PLIP) could be sent a -remote packet at any time. With PLIP, it is no huge catastrophe if a -network packet is dropped, since it will likely be sent again, so it -is possible for that kind of driver to share the port with other -(pass-through) devices. - -The parport_yield and -parport_yield_blocking functions are for marking -points in the driver at which other drivers may claim the port and use -their devices. Yielding the port is similar to releasing it and -reclaiming it, but it more efficient because nothing is done if there -are no other devices needing the port. In fact, nothing is done even -if there are other devices waiting but the current device is still -within its timeslice. The default timeslice is half a -second, but it can be adjusted via a /proc -entry. - - - int parport_yield - struct pardevice *dev - - - - int parport_yield_blocking - struct pardevice *dev - - -The first of these, parport_yield, will not -block but as a result may fail. The return value for -parport_yield is the same as for -parport_claim. The blocking version, -parport_yield_blocking, has the same return code -as parport_claim_or_block. - -Once the port has been claimed, the device driver can use the -functions in the struct parport_operations -pointer in the struct parport it has a -pointer to. For example: - - -ops->write_data (port, d); -]]> - -Some of these operations have shortcuts. For -instance, parport_write_data is equivalent to the -above, but may be a little bit faster (it's a macro that in some cases -can avoid needing to indirect through port and -ops). - - - - -Port drivers - - - -To recap, then: - - - - - -The device driver registers itself with parport. - - - - - -A low-level driver finds a parallel port and registers it with -parport (these first two things can happen in -either order). This registration creates a struct -parport which is linked onto a list of known ports. - - - - - -parport calls the attach -function of each registered device driver, passing it the pointer to -the new struct parport. - - - - - -The device driver gets a handle from parport, for -use with -parport_claim/release. This -handle takes the form of a pointer to a struct -pardevice, representing a particular device on the -parallel port, and is acquired using -parport_register_device. - - - - - -The device driver claims the port using -parport_claim (or -function_claim_or_block). - - - - - -Then it goes ahead and uses the port. When finished it releases the -port. - - - - - -The purpose of the low-level drivers, then, is to detect -parallel ports and provide methods of accessing them -(i.e. implementing the operations in struct -parport_operations). - - - - - - -A more complete description of which operation is supposed to do -what is available in -Documentation/parport-lowlevel.txt. - - - - -The printer driver - - - - -The printer driver, lp is a character -special device driver and a parport client. As a -character special device driver it registers a struct -file_operations using -register_chrdev, with pointers filled in for -write, ioctl, -open and -release. As a client of -parport, it registers a struct -parport_driver using -parport_register_driver, so that -parport knows to call -lp_attach when a new parallel port is discovered -(and lp_detach when it goes away). - -The parallel port console functionality is also implemented in -lp.c, but that won't be covered here (it's quite -simple though). - -The initialisation of the driver is quite easy to understand -(see lp_init). The lp_table -is an array of structures that contain information about a specific -device (the struct pardevice associated with -it, for example). That array is initialised to sensible values first -of all. - -Next, the printer driver calls -register_chrdev passing it a pointer to -lp_fops, which contains function pointers for the -printer driver's implementation of open, -write, and so on. This part is the same as for -any character special device driver. - -After successfully registering itself as a character special -device driver, the printer driver registers itself as a -parport client using -parport_register_driver. It passes a pointer to -this structure: - - - - -The lp_detach function is not very -interesting (it does nothing); the interesting bit is -lp_attach. What goes on here depends on whether -the user supplied any parameters. The possibilities are: no -parameters supplied, in which case the printer driver uses every port -that is detected; the user supplied the parameter auto, -in which case only ports on which the device ID string indicates a -printer is present are used; or the user supplied a list of parallel -port numbers to try, in which case only those are used. - -For each port that the printer driver wants to use (see -lp_register), it calls -parport_register_device and stores the resulting -struct pardevice pointer in the -lp_table. If the user told it to do so, it then -resets the printer. - -The other interesting piece of the printer driver, from the -point of view of parport, is -lp_write. In this function, the user space -process has data that it wants printed, and the printer driver hands -it off to the parport code to deal with. - -The parport functions it uses that we have -not seen yet are parport_negotiate, -parport_set_timeout, and -parport_write. These functions are part of the -IEEE 1284 implementation. - -The way the IEEE 1284 protocol works is that the host tells the -peripheral what transfer mode it would like to use, and the peripheral -either accepts that mode or rejects it; if the mode is rejected, the -host can try again with a different mode. This is the negotation -phase. Once the peripheral has accepted a particular transfer mode, -data transfer can begin that mode. - -The particular transfer mode that the printer driver wants to -use is named in IEEE 1284 as compatibility mode, and -the function to request a particular mode is called -parport_negotiate. - - - int parport_negotiate - struct parport *port - int mode - - -The modes parameter is a symbolic -constant representing an IEEE 1284 mode; in this instance, it is -IEEE1284_MODE_COMPAT. (Compatibility mode is -slightly different to the other modes---rather than being specifically -requested, it is the default until another mode is selected.) - -Back to lp_write then. First, access to -the parallel port is secured with -parport_claim_or_block. At this point the driver -might sleep, waiting for another driver (perhaps a Zip drive driver, -for instance) to let the port go. Next, it goes to compatibility mode -using parport_negotiate. - -The main work is done in the write-loop. In particular, the -line that hands the data over to parport -reads: - - - - -The parport_write function writes data to -the peripheral using the currently selected transfer mode -(compatibility mode, in this case). It returns the number of bytes -successfully written: - - - ssize_t parport_write - struct parport *port - const void *buf - size_t len - - - - ssize_t parport_read - struct parport *port - void *buf - size_t len - - -(parport_read does what it sounds like, but -only works for modes in which reverse transfer is possible. Of -course, parport_write only works in modes in -which forward transfer is possible, too.) - -The buf pointer should be to kernel space -memory, and obviously the len parameter -specifies the amount of data to transfer. - -In fact what parport_write does is call the -appropriate block transfer function from the struct -parport_operations: - - - - -The transfer code in parport will tolerate -a data transfer stall only for so long, and this timeout can be -specified with parport_set_timeout, which returns -the previous timeout: - - - long parport_set_timeout - struct pardevice *dev - long inactivity - - -This timeout is specific to the device, and is restored on -parport_claim. - - - - -User-level device drivers - - - -Introduction to ppdev - -The printer is accessible through /dev/lp0; -in the same way, the parallel port itself is accessible through -/dev/parport0. The difference is in the level of -control that you have over the wires in the parallel port -cable. - -With the printer driver, a user-space program (such as the -printer spooler) can send bytes in printer protocol. -Briefly, this means that for each byte, the eight data lines are set -up, then a strobe line tells the printer to look at the -data lines, and the printer sets an acknowledgement -line to say that it got the byte. The printer driver also allows the -user-space program to read bytes in nibble mode, which -is a way of transferring data from the peripheral to the computer half -a byte at a time (and so it's quite slow). - -In contrast, the ppdev driver (accessed via -/dev/parport0) allows you to: - - - - - -examine status lines, - - - - - -set control lines, - - - - - -set/examine data lines (and control the direction of the data lines), - - - - - -wait for an interrupt (triggered by one of the status lines), - - - - - -find out how many new interrupts have occurred, - - - - - -set up a response to an interrupt, - - - - - -use IEEE 1284 negotiation (for telling peripheral which transfer mode, -to use) - - - - - -transfer data using a specified IEEE 1284 mode. - - - - - - - - -User-level or kernel-level driver? - -The decision of whether to choose to write a kernel-level device -driver or a user-level device driver depends on several factors. One -of the main ones from a practical point of view is speed: kernel-level -device drivers get to run faster because they are not preemptable, -unlike user-level applications. - -Another factor is ease of development. It is in general easier -to write a user-level driver because (a) one wrong move does not -result in a crashed machine, (b) you have access to user libraries -(such as the C library), and (c) debugging is easier. - - - - -Programming interface - -The ppdev interface is largely the same as -that of other character special devices, in that it supports -open, close, -read, write, and -ioctl. - - -Starting and stopping: <function>open</function> and -<function>close</function> - -The device node /dev/parport0 represents -any device that is connected to parport0, the -first parallel port in the system. Each time the device node is -opened, it represents (to the process doing the opening) a different -device. It can be opened more than once, but only one instance can -actually be in control of the parallel port at any time. A process -that has opened /dev/parport0 shares the parallel -port in the same way as any other device driver. A user-land driver -may be sharing the parallel port with in-kernel device drivers as well -as other user-land drivers. - - - -Control: <function>ioctl</function> - -Most of the control is done, naturally enough, via the -ioctl call. Using ioctl, -the user-land driver can control both the ppdev -driver in the kernel and the physical parallel port itself. The -ioctl call takes as parameters a file descriptor -(the one returned from opening the device node), a command, and -optionally (a pointer to) some data. - - -PPCLAIM - - -Claims access to the port. As a user-land device driver writer, -you will need to do this before you are able to actually change the -state of the parallel port in any way. Note that some operations only -affect the ppdev driver and not the port, such as -PPSETMODE; they can be performed while access to -the port is not claimed. - - - -PPEXCL - - -Instructs the kernel driver to forbid any sharing of the port -with other drivers, i.e. it requests exclusivity. The -PPEXCL command is only valid when the port is not -already claimed for use, and it may mean that the next -PPCLAIM ioctl will fail: -some other driver may already have registered itself on that -port. - -Most device drivers don't need exclusive access to the port. -It's only provided in case it is really needed, for example for -devices where access to the port is required for extensive periods of -time (many seconds). - -Note that the PPEXCL -ioctl doesn't actually claim the port there and -then---action is deferred until the PPCLAIM -ioctl is performed. - - - -PPRELEASE - - -Releases the port. Releasing the port undoes the effect of -claiming the port. It allows other device drivers to talk to their -devices (assuming that there are any). - - - -PPYIELD - - -Yields the port to another driver. This -ioctl is a kind of short-hand for releasing the -port and immediately reclaiming it. It gives other drivers a chance -to talk to their devices, but afterwards claims the port back. An -example of using this would be in a user-land printer driver: once a -few characters have been written we could give the port to another -device driver for a while, but if we still have characters to send to -the printer we would want the port back as soon as possible. - -It is important not to claim the parallel port for too long, as -other device drivers will have no time to service their devices. If -your device does not allow for parallel port sharing at all, it is -better to claim the parallel port exclusively (see -PPEXCL). - - - -PPNEGOT - - -Performs IEEE 1284 negotiation into a particular mode. Briefly, -negotiation is the method by which the host and the peripheral decide -on a protocol to use when transferring data. - -An IEEE 1284 compliant device will start out in compatibility -mode, and then the host can negotiate to another mode (such as -ECP). - -The ioctl parameter should be a pointer to -an int; values for this are in -parport.h and include: - - -IEEE1284_MODE_COMPAT -IEEE1284_MODE_NIBBLE -IEEE1284_MODE_BYTE -IEEE1284_MODE_EPP -IEEE1284_MODE_ECP - - -The PPNEGOT ioctl -actually does two things: it performs the on-the-wire negotiation, and -it sets the behaviour of subsequent -read/write calls so that -they use that mode (but see PPSETMODE). - - - -PPSETMODE - - -Sets which IEEE 1284 protocol to use for the -read and write calls. - -The ioctl parameter should be a pointer to -an int. - - - -PPGETTIME - - -Retrieves the time-out value. The read and -write calls will time out if the peripheral -doesn't respond quickly enough. The PPGETTIME -ioctl retrieves the length of time that the -peripheral is allowed to have before giving up. - -The ioctl parameter should be a pointer to -a struct timeval. - - - -PPSETTIME - - -Sets the time-out. The ioctl parameter -should be a pointer to a struct -timeval. - - - -PPWCONTROL - - -Sets the control lines. The ioctl -parameter is a pointer to an unsigned char, the bitwise -OR of the control line values in -parport.h. - - - -PPRCONTROL - - -Returns the last value written to the control register, in the -form of an unsigned char: each bit corresponds to a -control line (although some are unused). The -ioctl parameter should be a pointer to an -unsigned char. - -This doesn't actually touch the hardware; the last value written -is remembered in software. This is because some parallel port -hardware does not offer read access to the control register. - -The control lines bits are defined in -parport.h: - - -PARPORT_CONTROL_STROBE -PARPORT_CONTROL_AUTOFD -PARPORT_CONTROL_SELECT -PARPORT_CONTROL_INIT - - - - -PPFCONTROL - - -Frobs the control lines. Since a common operation is to change -one of the control signals while leaving the others alone, it would be -quite inefficient for the user-land driver to have to use -PPRCONTROL, make the change, and then use -PPWCONTROL. Of course, each driver could -remember what state the control lines are supposed to be in (they are -never changed by anything else), but in order to provide -PPRCONTROL, ppdev must -remember the state of the control lines anyway. - -The PPFCONTROL ioctl -is for frobbing control lines, and is like -PPWCONTROL but acts on a restricted set of -control lines. The ioctl parameter is a pointer -to a struct ppdev_frob_struct: - - - - - -The mask and -val fields are bitwise ORs of control line -names (such as in PPWCONTROL). The operation -performed by PPFCONTROL is: - - - - - -In other words, the signals named in -mask are set to the values in -val. - - - -PPRSTATUS - - -Returns an unsigned char containing bits set for -each status line that is set (for instance, -PARPORT_STATUS_BUSY). The -ioctl parameter should be a pointer to an -unsigned char. - - - -PPDATADIR - - -Controls the data line drivers. Normally the computer's -parallel port will drive the data lines, but for byte-wide transfers -from the peripheral to the host it is useful to turn off those drivers -and let the peripheral drive the signals. (If the drivers on the -computer's parallel port are left on when this happens, the port might -be damaged.) - -This is only needed in conjunction with -PPWDATA or PPRDATA. - -The ioctl parameter is a pointer to an -int. If the int is zero, the drivers are -turned on (forward direction); if non-zero, the drivers are turned off -(reverse direction). - - - -PPWDATA - - -Sets the data lines (if in forward mode). The -ioctl parameter is a pointer to an unsigned -char. - - - -PPRDATA - - -Reads the data lines (if in reverse mode). The -ioctl parameter is a pointer to an unsigned -char. - - - -PPCLRIRQ - - -Clears the interrupt count. The ppdev -driver keeps a count of interrupts as they are triggered. -PPCLRIRQ stores this count in an -int, a pointer to which is passed in as the -ioctl parameter. - -In addition, the interrupt count is reset to zero. - - - -PPWCTLONIRQ - - -Set a trigger response. Afterwards when an interrupt is -triggered, the interrupt handler will set the control lines as -requested. The ioctl parameter is a pointer to -an unsigned char, which is interpreted in the same way as -for PPWCONTROL. - -The reason for this ioctl is simply speed. -Without this ioctl, responding to an interrupt -would start in the interrupt handler, switch context to the user-land -driver via poll or select, -and then switch context back to the kernel in order to handle -PPWCONTROL. Doing the whole lot in the interrupt -handler is a lot faster. - - - - - - - - - - -Transferring data: <function>read</function> and -<function>write</function> - -Transferring data using read and -write is straightforward. The data is -transferring using the current IEEE 1284 mode (see the -PPSETMODE ioctl). For modes -which can only transfer data in one direction, only the appropriate -function will work, of course. - - - -Waiting for events: <function>poll</function> and -<function>select</function> - -The ppdev driver provides user-land device -drivers with the ability to wait for interrupts, and this is done -using poll (and select, -which is implemented in terms of poll). - -When a user-land device driver wants to wait for an interrupt, -it sleeps with poll. When the interrupt arrives, -ppdev wakes it up (with a read -event, although strictly speaking there is nothing to actually -read). - - - - - - -Examples - -Presented here are two demonstrations of how to write a simple -printer driver for ppdev. Firstly we will use -the write function, and after that we will drive -the control and data lines directly. - -The first thing to do is to actually open the device. - - - -Here name should be something along the lines -of "/dev/parport0". (If you don't have any -/dev/parport files, you can make them with -mknod; they are character special device nodes with -major 99.) - -In order to do anything with the port we need to claim access to -it. - - - -Our printer driver will copy its input (from -stdin) to the printer, and it can do that it one of -two ways. The first way is to hand it all off to the kernel driver, -with the knowledge that the protocol that the printer speaks is IEEE -1284's compatibility mode. - - 0) { - int written = write_printer (fd, ptr, got); - - if (written < 0) { - perror ("write"); - close (fd); - return 1; - } - - ptr += written; - got -= written; - } - } -]]> - -The write_printer function is not pictured -above. This is because the main loop that is shown can be used for -both methods of driving the printer. Here is one implementation of -write_printer: - - - -We hand the data to the kernel-level driver (using -write) and it handles the printer -protocol. - -Now let's do it the hard way! In this particular example there -is no practical reason to do anything other than just call -write, because we know that the printer talks an -IEEE 1284 protocol. On the other hand, this particular example does -not even need a user-land driver since there is already a kernel-level -one; for the purpose of this discussion, try to imagine that the -printer speaks a protocol that is not already implemented under -Linux. - -So, here is the alternative implementation of -write_printer (for brevity, error checking has -been omitted): - - - -To show a bit more of the ppdev interface, -here is a small piece of code that is intended to mimic the printer's -side of printer protocol. - - 1) - fprintf (stderr, "Arghh! Missed %d interrupt%s!\n", - irqc - 1, irqc == 2 ? "s" : ""); - - /* Ack it. */ - ioctl (fd, PPWCONTROL, &acking); - usleep (2); - ioctl (fd, PPWCONTROL, &busy); - - putchar (ch); - } -]]> - - - - -
\ No newline at end of file diff -u --recursive --new-file v2.3.99-pre3/linux/Documentation/DocBook/parportbook.tmpl linux/Documentation/DocBook/parportbook.tmpl --- v2.3.99-pre3/linux/Documentation/DocBook/parportbook.tmpl Wed Dec 31 16:00:00 1969 +++ linux/Documentation/DocBook/parportbook.tmpl Tue Mar 21 14:43:39 2000 @@ -0,0 +1,1747 @@ + + + + + The Parallel Port Subsystem + + + + Tim + Waugh + +
+ twaugh@redhat.com +
+
+
+
+ + + 1999-2000 + Tim Waugh + + + + + This documentation 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 + + + + For more details see the file COPYING in the source + distribution of Linux. + + +
+ + + + +Design goals + + +The problems + + + + + + +The first parallel port support for Linux came with the line +printer driver, lp. The printer driver is a +character special device, and (in Linux 2.0) had support for writing, +via write, and configuration and statistics +reporting via ioctl. + +The printer driver could be used on any computer that had an IBM +PC-compatible parallel port. Because some architectures have parallel +ports that aren't really the same as PC-style ports, other variants of +the printer driver were written in order to support Amiga and Atari +parallel ports. + +When the Iomega Zip drive was released, and a driver written for +it, a problem became apparent. The Zip drive is a parallel port +device that provides a parallel port of its own---it is designed to +sit between a computer and an attached printer, with the printer +plugged into the Zip drive, and the Zip drive plugged into the +computer. + +The problem was that, although printers and Zip drives were both +supported, for any given port only one could be used at a time. Only +one of the two drivers could be present in the kernel at once. This +was because of the fact that both drivers wanted to drive the same +hardware---the parallel port. When the printer driver initialised, it +would call the check_region function to make sure +that the IO region associated with the parallel port was free, and +then it would call request_region to allocate it. +The Zip drive used the same mechanism. Whichever driver initialised +first would gain exclusive control of the parallel port. + +The only way around this problem at the time was to make sure +that both drivers were available as loadable kernel modules. To use +the printer, load the printer driver module; then for the Zip drive, +unload the printer driver module and load the Zip driver +module. + +The net effect was that printing a document that was stored on a Zip +drive was a bit of an ordeal, at least if the Zip drive and printer +shared a parallel port. A better solution was needed. + +Zip drives are not the only devices that presented problems for +Linux. There are other devices with pass-through ports, for example +parallel port CD-ROM drives. There are also printers that report +their status textually rather than using simple error pins: sending a +command to the printer can cause it to report the number of pages that +it has ever printed, or how much free memory it has, or whether it is +running out of toner, and so on. The printer driver didn't originally +offer any facility for reading back this information (although Carsten +Gross added nibble mode readback support for kernel 2.2). + + + +The IEEE has issued a standards document called IEEE 1284, which +documents existing practice for parallel port communications in a +variety of modes. Those modes are: compatibility, +reverse nibble, reverse byte, ECP and EPP. Newer devices often use +the more advanced modes of transfer (ECP and EPP). In Linux 2.0, the +printer driver only supported compatibility mode +(i.e. normal printer protocol) and reverse nibble mode. + + + + +The solutions + + + +The parport code in Linux 2.2 was designed +to meet these problems of architectural differences in parallel ports, +of port-sharing between devices with pass-through ports, and of lack +of support for IEEE 1284 transfer modes. + + + +There are two layers to the +parport subsystem, only one of which deals +directly with the hardware. The other layer deals with sharing and +IEEE 1284 transfer modes. In this way, parallel support for a +particular architecture comes in the form of a module which registers +itself with the generic sharing layer. + + + +The sharing model provided by the parport +subsystem is one of exclusive access. A device driver, such as the +printer driver, must ask the parport layer for +access to the port, and can only use the port once access has been +granted. When it has finished a transaction, it can +tell the parport layer that it may release the +port for other device drivers to use. + + + +Devices with pass-through ports all manage to share a parallel +port with other devices in generally the same way. The device has a +latch for each of the pins on its pass-through port. The normal state +of affairs is pass-through mode, with the device copying the signal +lines between its host port and its pass-through port. When the +device sees a special signal from the host port, it latches the +pass-through port so that devices further downstream don't get +confused by the pass-through device's conversation with the host +parallel port: the device connected to the pass-through port (and any +devices connected in turn to it) are effectively cut off from the +computer. When the pass-through device has completed its transaction +with the computer, it enables the pass-through port again. + + + + + + + +This technique relies on certain special signals +being invisible to devices that aren't watching for them. This tends +to mean only changing the data signals and leaving the control signals +alone. IEEE 1284.3 documents a standard protocol for daisy-chaining +devices together with parallel ports. + + + +Support for standard transfer modes are provided as operations +that can be performed on a port, along with operations for setting the +data lines, or the control lines, or reading the status lines. These +operations appear to the device driver as function pointers; more +later. + + + + + + +Standard transfer modes + + + + +The standard transfer modes in use over the +parallel port are defined by a document called IEEE +1284. It really just codifies existing practice and documents +protocols (and variations on protocols) that have been in common use +for quite some time. + +The original definitions of which pin did what were set out by +Centronics Data Computer Corporation, but only the printer-side +interface signals were specified. + +By the early 1980s, IBM's host-side implementation had become +the most widely used. New printers emerged that claimed Centronics +compatibility, but although compatible with Centronics they differed +from one another in a number of ways. + +As a result of this, when IEEE 1284 was published in 1994, all +that it could really do was document the various protocols that are +used for printers (there are about six variations on a theme). + +In addition to the protocol used to talk to +Centronics-compatible printers, IEEE 1284 defined other protocols that +are used for unidirectional peripheral-to-host transfers (reverse +nibble and reverse byte) and for fast bidirectional transfers (ECP and +EPP). + + + + +Structure + + + + + + + + + + + + +Sharing core + + + +At the core of the parport subsystem is the +sharing mechanism (see drivers/parport/share.c). +This module, parport, is responsible for +keeping track of which ports there are in the system, which device +drivers might be interested in new ports, and whether or not each port +is available for use (or if not, which driver is currently using +it). + + + + +Parports and their overrides + + +The generic parport sharing code doesn't +directly handle the parallel port hardware. That is done instead by +low-level parport drivers. The +function of a low-level parport driver is to +detect parallel ports, register them with the sharing code, and +provide a list of access functions for each port. + +The most basic access functions that must be provided are ones +for examining the status lines, for setting the control lines, and for +setting the data lines. There are also access functions for setting +the direction of the data lines; normally they are in the +forward direction (that is, the computer drives them), +but some ports allow switching to reverse mode (driven +by the peripheral). There is an access function for examining the +data lines once in reverse mode. + + + + +IEEE 1284 transfer modes + + +Stacked on top of the sharing mechanism, but still in the +parport module, are functions for transferring +data. They are provided for the device drivers to use, and are very +much like library routines. Since these transfer functions are +provided by the generic parport core they must +use the lowest common denominator set of access +functions: they can set the control lines, examine the status lines, +and use the data lines. With some parallel ports the data lines can +only be set and not examined, and with other ports accessing the data +register causes control line activity; with these types of situations, +the IEEE 1284 transfer functions make a best effort attempt to do the +right thing. In some cases, it is not physically possible to use +particular IEEE 1284 transfer modes. + +The low-level parport drivers also provide +IEEE 1284 transfer functions, as names in the access function list. +The low-level driver can just name the generic IEEE 1284 transfer +functions for this. Some parallel ports can do IEEE 1284 transfers in +hardware; for those ports, the low-level driver can provide functions +to utilise that feature. + + + + + + + + +Pardevices and parport_drivers + +When a parallel port device driver (such as +lp) initialises it tells the sharing layer about +itself using parport_register_driver. The +information is put into a struct +parport_driver, which is put into a linked list. The +information in a struct parport_driver really +just amounts to some function pointers to callbacks in the parallel +port device driver. + +During its initialisation, a low-level port driver tells the +sharing layer about all the ports that it has found (using +parport_register_port), and the sharing layer +creates a struct parport for each of them. +Each struct parport contains (among other +things) a pointer to a struct +parport_operations, which is a list of function pointers +for the various operations that can be performed on a port. You can +think of a struct parport as a parallel port +object, if object-orientated programming +is your thing. The parport structures are +chained in a linked list, whose head is portlist +(in drivers/parport/share.c). + +Once the port has been registered, the low-level port driver +announces it. The parport_announce_port function +walks down the list of parallel port device drivers +(struct parport_drivers) calling the +attach function of each. + +Similarly, a low-level port driver can undo the effect of +registering a port with the +parport_unregister_port function, and device +drivers are notified using the detach +callback. + +Device drivers can undo the effect of registering themselves +with the parport_unregister_driver +function. + + + + + + +The IEEE 1284.3 API + +The ability to daisy-chain devices is very useful, but if every +device does it in a different way it could lead to lots of +complications for device driver writers. Fortunately, the IEEE are +standardising it in IEEE 1284.3, which covers daisy-chain devices and +port multiplexors. + +At the time of writing, IEEE 1284.3 has not been published, but +the draft specifies the on-the-wire protocol for daisy-chaining and +multiplexing, and also suggests a programming interface for using it. +That interface (or most of it) has been implemented in the +parport code in Linux. + +At initialisation of the parallel port bus, daisy-chained +devices are assigned addresses starting from zero. There can only be +four devices with daisy-chain addresses, plus one device on the end +that doesn't know about daisy-chaining and thinks it's connected +directly to a computer. + +Another way of connecting more parallel port devices is to use a +multiplexor. The idea is to have a device that is connected directly +to a parallel port on a computer, but has a number of parallel ports +on the other side for other peripherals to connect to (two or four +ports are allowed). The multiplexor switches control to different +ports under software control---it is, in effect, a programmable +printer switch. + +Combining the ability of daisy-chaining five devices together +with the ability to multiplex one parallel port between four gives the +potential to have twenty peripherals connected to the same parallel +port! + +In addition, of course, a single computer can have multiple +parallel ports. So, each parallel port peripheral in the system can +be identified with three numbers, or co-ordinates: the parallel port, +the multiplexed port, and the daisy-chain address. + + + + + + + + + + + + + + + +Each device in the system is numbered at initialisation (by +parport_daisy_init). You can convert between +this device number and its co-ordinates with +parport_device_num and +parport_device_coords. + + + int parport_device_num + int parport + int mux + int daisy + + + + int parport_device_coords + int devnum + int *parport + int *mux + int *daisy + + +Any parallel port peripheral will be connected directly or +indirectly to a parallel port on the system, but it won't have a +daisy-chain address if it does not know about daisy-chaining, and it +won't be connected through a multiplexor port if there is no +multiplexor. The special co-ordinate value -1 is +used to indicate these cases. + +Two functions are provided for finding devices based on their +IEEE 1284 Device ID: parport_find_device and +parport_find_class. + + + int parport_find_device + const char *mfg + const char *mdl + int from + + + + int parport_find_class + parport_device_class cls + int from + + +These functions take a device number (in addition to some other +things), and return another device number. They walk through the list +of detected devices until they find one that matches the requirements, +and then return that device number (or -1 if +there are no more such devices). They start their search at the +device after the one in the list with the number given (at +from+1, in other words). + + + + + + +Device driver's view + + + + + + + + + +This section is written from the point of view of the device +driver programmer, who might be writing a driver for a printer or a +scanner or else anything that plugs into the parallel port. It +explains how to use the parport interface to find +parallel ports, use them, and share them with other device +drivers. + +We'll start out with a description of the various functions that +can be called, and then look at a reasonably simple example of their +use: the printer driver. + +The interactions between the device driver and the +parport layer are as follows. First, the device +driver registers its existence with parport, in +order to get told about any parallel ports that have been (or will be) +detected. When it gets told about a parallel port, it then tells +parport that it wants to drive a device on that +port. Thereafter it can claim exclusive access to the port in order +to talk to its device. + +So, the first thing for the device driver to do is tell +parport that it wants to know what parallel ports +are on the system. To do this, it uses the +parport_register_device function: + + + + + + int parport_register_driver + struct parport_driver *driver + + +In other words, the device driver passes pointers to a couple of +functions to parport, and +parport calls attach for +each port that's detected (and detach for each +port that disappears -- yes, this can happen). + +The next thing that happens is that the device driver tells +parport that it thinks there's a device on the +port that it can drive. This typically will happen in the driver's +attach function, and is done with +parport_register_device: + + + struct pardevice *parport_register_device + struct parport *port + const char *name + int (*pf) + void * + void (*kf) + void * + void (*irq_func) + int, void *, struct pt_regs * + int flags + void *handle + + +The port comes from the parameter supplied +to the attach function when it is called, or +alternatively can be found from the list of detected parallel ports +directly with the (now deprecated) +parport_enumerate function. + +The next three parameters, pf, +kf, and irq_func, are +more function pointers. These callback functions get called under +various circumstances, and are always given the +handle as one of their parameters. + +The preemption callback, pf, is called +when the driver has claimed access to the port but another device +driver wants access. If the driver is willing to let the port go, it +should return zero and the port will be released on its behalf. There +is no need to call parport_release. If +pf gets called at a bad time for letting the +port go, it should return non-zero and no action will be taken. It is +good manners for the driver to try to release the port at the earliest +opportunity after its preemption callback is called. + +The kick callback, kf, is +called when the port can be claimed for exclusive access; that is, +parport_claim is guaranteed to succeed inside the +kick callback. If the driver wants to claim the port +it should do so; otherwise, it need not take any action. + +The irq_func callback is called, +predictably, when a parallel port interrupt is generated. But it is +not the only code that hooks on the interrupt. The sequence is this: +the lowlevel driver is the one that has done +request_irq; it then does whatever +hardware-specific things it needs to do to the parallel port hardware +(for PC-style ports, there is nothing special to do); it then tells +the IEEE 1284 code about the interrupt, which may involve reacting to +an IEEE 1284 event, depending on the current IEEE 1284 phase; and +finally the irq_func function is called. + +None of the callback functions are allowed to block. + +The flags are for telling +parport any requirements or hints that are +useful. The only useful value here (other than +0, which is the usual value) is +PARPORT_DEV_EXCL. The point of that flag is to +request exclusive access at all times---once a driver has successfully +called parport_register_device with that flag, no +other device drivers will be able to register devices on that port +(until the successful driver deregisters its device, of +course). + +The PARPORT_DEV_EXCL flag is for preventing +port sharing, and so should only be used when sharing the port with +other device drivers is impossible and would lead to incorrect +behaviour. Use it sparingly! + +Devices can also be registered by device drivers based on their +device numbers (the same device numbers as in the previous +section). + +The parport_open function is similar to +parport_register_device, and +parport_close is the equivalent of +parport_unregister_device. The difference is +that parport_open takes a device number rather +than a pointer to a struct parport. + + + struct pardevice *parport_open + int devnum + int (*pf) + void * + int (*kf) + void * + int (*irqf) + int, void *, struct pt_regs * + int flags + void *handle + + + + void parport_close + struct pardevice *dev + + + + struct pardevice *parport_register_device + struct parport *port + const char *name + int (*pf) + void * + int (*kf) + void * + int (*irqf) + int, void *, struct pt_regs * + int flags + void *handle + + + + void parport_unregister_device + struct pardevice *dev + + +The intended use of these functions is during driver +initialisation while the driver looks for devices that it supports, as +demonstrated by the following code fragment: + + + + +Once your device driver has registered its device and been +handed a pointer to a struct pardevice, the +next thing you are likely to want to do is communicate with the device +you think is there. To do that you'll need to claim access to the +port. + + + int parport_claim + struct pardevice *dev + + + + int parport_claim_or_block + struct pardevice *dev + + + + void parport_release + struct pardevice *dev + + +To claim access to the port, use +parport_claim or +parport_claim_or_block. The first of these will +not block, and so can be used from interrupt context. If +parport_claim succeeds it will return zero and +the port is available to use. It may fail (returning non-zero) if the +port is in use by another driver and that driver is not willing to +relinquish control of the port. + +The other function, parport_claim_or_block, +will block if necessary to wait for the port to be free. If it slept, +it returns 1; if it succeeded without needing to +sleep it returns 0. If it fails it will return a +negative error code. + +When you have finished communicating with the device, you can +give up access to the port so that other drivers can communicate with +their devices. The parport_release function +cannot fail, but it should not be called without the port claimed. +Similarly, you should not try to claim the port if you already have it +claimed. + +You may find that although there are convenient points for your +driver to relinquish the parallel port and allow other drivers to talk +to their devices, it would be preferable to keep hold of the port. +The printer driver only needs the port when there is data to print, +for example, but a network driver (such as PLIP) could be sent a +remote packet at any time. With PLIP, it is no huge catastrophe if a +network packet is dropped, since it will likely be sent again, so it +is possible for that kind of driver to share the port with other +(pass-through) devices. + +The parport_yield and +parport_yield_blocking functions are for marking +points in the driver at which other drivers may claim the port and use +their devices. Yielding the port is similar to releasing it and +reclaiming it, but it more efficient because nothing is done if there +are no other devices needing the port. In fact, nothing is done even +if there are other devices waiting but the current device is still +within its timeslice. The default timeslice is half a +second, but it can be adjusted via a /proc +entry. + + + int parport_yield + struct pardevice *dev + + + + int parport_yield_blocking + struct pardevice *dev + + +The first of these, parport_yield, will not +block but as a result may fail. The return value for +parport_yield is the same as for +parport_claim. The blocking version, +parport_yield_blocking, has the same return code +as parport_claim_or_block. + +Once the port has been claimed, the device driver can use the +functions in the struct parport_operations +pointer in the struct parport it has a +pointer to. For example: + + +ops->write_data (port, d); +]]> + +Some of these operations have shortcuts. For +instance, parport_write_data is equivalent to the +above, but may be a little bit faster (it's a macro that in some cases +can avoid needing to indirect through port and +ops). + + + + +Port drivers + + + +To recap, then: + + + + + +The device driver registers itself with parport. + + + + + +A low-level driver finds a parallel port and registers it with +parport (these first two things can happen in +either order). This registration creates a struct +parport which is linked onto a list of known ports. + + + + + +parport calls the attach +function of each registered device driver, passing it the pointer to +the new struct parport. + + + + + +The device driver gets a handle from parport, for +use with +parport_claim/release. This +handle takes the form of a pointer to a struct +pardevice, representing a particular device on the +parallel port, and is acquired using +parport_register_device. + + + + + +The device driver claims the port using +parport_claim (or +function_claim_or_block). + + + + + +Then it goes ahead and uses the port. When finished it releases the +port. + + + + + +The purpose of the low-level drivers, then, is to detect +parallel ports and provide methods of accessing them +(i.e. implementing the operations in struct +parport_operations). + + + + + + +A more complete description of which operation is supposed to do +what is available in +Documentation/parport-lowlevel.txt. + + + + +The printer driver + + + + +The printer driver, lp is a character +special device driver and a parport client. As a +character special device driver it registers a struct +file_operations using +register_chrdev, with pointers filled in for +write, ioctl, +open and +release. As a client of +parport, it registers a struct +parport_driver using +parport_register_driver, so that +parport knows to call +lp_attach when a new parallel port is discovered +(and lp_detach when it goes away). + +The parallel port console functionality is also implemented in +lp.c, but that won't be covered here (it's quite +simple though). + +The initialisation of the driver is quite easy to understand +(see lp_init). The lp_table +is an array of structures that contain information about a specific +device (the struct pardevice associated with +it, for example). That array is initialised to sensible values first +of all. + +Next, the printer driver calls +register_chrdev passing it a pointer to +lp_fops, which contains function pointers for the +printer driver's implementation of open, +write, and so on. This part is the same as for +any character special device driver. + +After successfully registering itself as a character special +device driver, the printer driver registers itself as a +parport client using +parport_register_driver. It passes a pointer to +this structure: + + + + +The lp_detach function is not very +interesting (it does nothing); the interesting bit is +lp_attach. What goes on here depends on whether +the user supplied any parameters. The possibilities are: no +parameters supplied, in which case the printer driver uses every port +that is detected; the user supplied the parameter auto, +in which case only ports on which the device ID string indicates a +printer is present are used; or the user supplied a list of parallel +port numbers to try, in which case only those are used. + +For each port that the printer driver wants to use (see +lp_register), it calls +parport_register_device and stores the resulting +struct pardevice pointer in the +lp_table. If the user told it to do so, it then +resets the printer. + +The other interesting piece of the printer driver, from the +point of view of parport, is +lp_write. In this function, the user space +process has data that it wants printed, and the printer driver hands +it off to the parport code to deal with. + +The parport functions it uses that we have +not seen yet are parport_negotiate, +parport_set_timeout, and +parport_write. These functions are part of the +IEEE 1284 implementation. + +The way the IEEE 1284 protocol works is that the host tells the +peripheral what transfer mode it would like to use, and the peripheral +either accepts that mode or rejects it; if the mode is rejected, the +host can try again with a different mode. This is the negotation +phase. Once the peripheral has accepted a particular transfer mode, +data transfer can begin that mode. + +The particular transfer mode that the printer driver wants to +use is named in IEEE 1284 as compatibility mode, and +the function to request a particular mode is called +parport_negotiate. + + + int parport_negotiate + struct parport *port + int mode + + +The modes parameter is a symbolic +constant representing an IEEE 1284 mode; in this instance, it is +IEEE1284_MODE_COMPAT. (Compatibility mode is +slightly different to the other modes---rather than being specifically +requested, it is the default until another mode is selected.) + +Back to lp_write then. First, access to +the parallel port is secured with +parport_claim_or_block. At this point the driver +might sleep, waiting for another driver (perhaps a Zip drive driver, +for instance) to let the port go. Next, it goes to compatibility mode +using parport_negotiate. + +The main work is done in the write-loop. In particular, the +line that hands the data over to parport +reads: + + + + +The parport_write function writes data to +the peripheral using the currently selected transfer mode +(compatibility mode, in this case). It returns the number of bytes +successfully written: + + + ssize_t parport_write + struct parport *port + const void *buf + size_t len + + + + ssize_t parport_read + struct parport *port + void *buf + size_t len + + +(parport_read does what it sounds like, but +only works for modes in which reverse transfer is possible. Of +course, parport_write only works in modes in +which forward transfer is possible, too.) + +The buf pointer should be to kernel space +memory, and obviously the len parameter +specifies the amount of data to transfer. + +In fact what parport_write does is call the +appropriate block transfer function from the struct +parport_operations: + + + + +The transfer code in parport will tolerate +a data transfer stall only for so long, and this timeout can be +specified with parport_set_timeout, which returns +the previous timeout: + + + long parport_set_timeout + struct pardevice *dev + long inactivity + + +This timeout is specific to the device, and is restored on +parport_claim. + + + + +User-level device drivers + + + +Introduction to ppdev + +The printer is accessible through /dev/lp0; +in the same way, the parallel port itself is accessible through +/dev/parport0. The difference is in the level of +control that you have over the wires in the parallel port +cable. + +With the printer driver, a user-space program (such as the +printer spooler) can send bytes in printer protocol. +Briefly, this means that for each byte, the eight data lines are set +up, then a strobe line tells the printer to look at the +data lines, and the printer sets an acknowledgement +line to say that it got the byte. The printer driver also allows the +user-space program to read bytes in nibble mode, which +is a way of transferring data from the peripheral to the computer half +a byte at a time (and so it's quite slow). + +In contrast, the ppdev driver (accessed via +/dev/parport0) allows you to: + + + + + +examine status lines, + + + + + +set control lines, + + + + + +set/examine data lines (and control the direction of the data lines), + + + + + +wait for an interrupt (triggered by one of the status lines), + + + + + +find out how many new interrupts have occurred, + + + + + +set up a response to an interrupt, + + + + + +use IEEE 1284 negotiation (for telling peripheral which transfer mode, +to use) + + + + + +transfer data using a specified IEEE 1284 mode. + + + + + + + + +User-level or kernel-level driver? + +The decision of whether to choose to write a kernel-level device +driver or a user-level device driver depends on several factors. One +of the main ones from a practical point of view is speed: kernel-level +device drivers get to run faster because they are not preemptable, +unlike user-level applications. + +Another factor is ease of development. It is in general easier +to write a user-level driver because (a) one wrong move does not +result in a crashed machine, (b) you have access to user libraries +(such as the C library), and (c) debugging is easier. + + + + +Programming interface + +The ppdev interface is largely the same as +that of other character special devices, in that it supports +open, close, +read, write, and +ioctl. + + +Starting and stopping: <function>open</function> and +<function>close</function> + +The device node /dev/parport0 represents +any device that is connected to parport0, the +first parallel port in the system. Each time the device node is +opened, it represents (to the process doing the opening) a different +device. It can be opened more than once, but only one instance can +actually be in control of the parallel port at any time. A process +that has opened /dev/parport0 shares the parallel +port in the same way as any other device driver. A user-land driver +may be sharing the parallel port with in-kernel device drivers as well +as other user-land drivers. + + + +Control: <function>ioctl</function> + +Most of the control is done, naturally enough, via the +ioctl call. Using ioctl, +the user-land driver can control both the ppdev +driver in the kernel and the physical parallel port itself. The +ioctl call takes as parameters a file descriptor +(the one returned from opening the device node), a command, and +optionally (a pointer to) some data. + + +PPCLAIM + + +Claims access to the port. As a user-land device driver writer, +you will need to do this before you are able to actually change the +state of the parallel port in any way. Note that some operations only +affect the ppdev driver and not the port, such as +PPSETMODE; they can be performed while access to +the port is not claimed. + + + +PPEXCL + + +Instructs the kernel driver to forbid any sharing of the port +with other drivers, i.e. it requests exclusivity. The +PPEXCL command is only valid when the port is not +already claimed for use, and it may mean that the next +PPCLAIM ioctl will fail: +some other driver may already have registered itself on that +port. + +Most device drivers don't need exclusive access to the port. +It's only provided in case it is really needed, for example for +devices where access to the port is required for extensive periods of +time (many seconds). + +Note that the PPEXCL +ioctl doesn't actually claim the port there and +then---action is deferred until the PPCLAIM +ioctl is performed. + + + +PPRELEASE + + +Releases the port. Releasing the port undoes the effect of +claiming the port. It allows other device drivers to talk to their +devices (assuming that there are any). + + + +PPYIELD + + +Yields the port to another driver. This +ioctl is a kind of short-hand for releasing the +port and immediately reclaiming it. It gives other drivers a chance +to talk to their devices, but afterwards claims the port back. An +example of using this would be in a user-land printer driver: once a +few characters have been written we could give the port to another +device driver for a while, but if we still have characters to send to +the printer we would want the port back as soon as possible. + +It is important not to claim the parallel port for too long, as +other device drivers will have no time to service their devices. If +your device does not allow for parallel port sharing at all, it is +better to claim the parallel port exclusively (see +PPEXCL). + + + +PPNEGOT + + +Performs IEEE 1284 negotiation into a particular mode. Briefly, +negotiation is the method by which the host and the peripheral decide +on a protocol to use when transferring data. + +An IEEE 1284 compliant device will start out in compatibility +mode, and then the host can negotiate to another mode (such as +ECP). + +The ioctl parameter should be a pointer to +an int; values for this are in +parport.h and include: + + +IEEE1284_MODE_COMPAT +IEEE1284_MODE_NIBBLE +IEEE1284_MODE_BYTE +IEEE1284_MODE_EPP +IEEE1284_MODE_ECP + + +The PPNEGOT ioctl +actually does two things: it performs the on-the-wire negotiation, and +it sets the behaviour of subsequent +read/write calls so that +they use that mode (but see PPSETMODE). + + + +PPSETMODE + + +Sets which IEEE 1284 protocol to use for the +read and write calls. + +The ioctl parameter should be a pointer to +an int. + + + +PPGETTIME + + +Retrieves the time-out value. The read and +write calls will time out if the peripheral +doesn't respond quickly enough. The PPGETTIME +ioctl retrieves the length of time that the +peripheral is allowed to have before giving up. + +The ioctl parameter should be a pointer to +a struct timeval. + + + +PPSETTIME + + +Sets the time-out. The ioctl parameter +should be a pointer to a struct +timeval. + + + +PPWCONTROL + + +Sets the control lines. The ioctl +parameter is a pointer to an unsigned char, the bitwise +OR of the control line values in +parport.h. + + + +PPRCONTROL + + +Returns the last value written to the control register, in the +form of an unsigned char: each bit corresponds to a +control line (although some are unused). The +ioctl parameter should be a pointer to an +unsigned char. + +This doesn't actually touch the hardware; the last value written +is remembered in software. This is because some parallel port +hardware does not offer read access to the control register. + +The control lines bits are defined in +parport.h: + + +PARPORT_CONTROL_STROBE +PARPORT_CONTROL_AUTOFD +PARPORT_CONTROL_SELECT +PARPORT_CONTROL_INIT + + + + +PPFCONTROL + + +Frobs the control lines. Since a common operation is to change +one of the control signals while leaving the others alone, it would be +quite inefficient for the user-land driver to have to use +PPRCONTROL, make the change, and then use +PPWCONTROL. Of course, each driver could +remember what state the control lines are supposed to be in (they are +never changed by anything else), but in order to provide +PPRCONTROL, ppdev must +remember the state of the control lines anyway. + +The PPFCONTROL ioctl +is for frobbing control lines, and is like +PPWCONTROL but acts on a restricted set of +control lines. The ioctl parameter is a pointer +to a struct ppdev_frob_struct: + + + + + +The mask and +val fields are bitwise ORs of control line +names (such as in PPWCONTROL). The operation +performed by PPFCONTROL is: + + + + + +In other words, the signals named in +mask are set to the values in +val. + + + +PPRSTATUS + + +Returns an unsigned char containing bits set for +each status line that is set (for instance, +PARPORT_STATUS_BUSY). The +ioctl parameter should be a pointer to an +unsigned char. + + + +PPDATADIR + + +Controls the data line drivers. Normally the computer's +parallel port will drive the data lines, but for byte-wide transfers +from the peripheral to the host it is useful to turn off those drivers +and let the peripheral drive the signals. (If the drivers on the +computer's parallel port are left on when this happens, the port might +be damaged.) + +This is only needed in conjunction with +PPWDATA or PPRDATA. + +The ioctl parameter is a pointer to an +int. If the int is zero, the drivers are +turned on (forward direction); if non-zero, the drivers are turned off +(reverse direction). + + + +PPWDATA + + +Sets the data lines (if in forward mode). The +ioctl parameter is a pointer to an unsigned +char. + + + +PPRDATA + + +Reads the data lines (if in reverse mode). The +ioctl parameter is a pointer to an unsigned +char. + + + +PPCLRIRQ + + +Clears the interrupt count. The ppdev +driver keeps a count of interrupts as they are triggered. +PPCLRIRQ stores this count in an +int, a pointer to which is passed in as the +ioctl parameter. + +In addition, the interrupt count is reset to zero. + + + +PPWCTLONIRQ + + +Set a trigger response. Afterwards when an interrupt is +triggered, the interrupt handler will set the control lines as +requested. The ioctl parameter is a pointer to +an unsigned char, which is interpreted in the same way as +for PPWCONTROL. + +The reason for this ioctl is simply speed. +Without this ioctl, responding to an interrupt +would start in the interrupt handler, switch context to the user-land +driver via poll or select, +and then switch context back to the kernel in order to handle +PPWCONTROL. Doing the whole lot in the interrupt +handler is a lot faster. + + + + + + + + + + +Transferring data: <function>read</function> and +<function>write</function> + +Transferring data using read and +write is straightforward. The data is +transferring using the current IEEE 1284 mode (see the +PPSETMODE ioctl). For modes +which can only transfer data in one direction, only the appropriate +function will work, of course. + + + +Waiting for events: <function>poll</function> and +<function>select</function> + +The ppdev driver provides user-land device +drivers with the ability to wait for interrupts, and this is done +using poll (and select, +which is implemented in terms of poll). + +When a user-land device driver wants to wait for an interrupt, +it sleeps with poll. When the interrupt arrives, +ppdev wakes it up (with a read +event, although strictly speaking there is nothing to actually +read). + + + + + + +Examples + +Presented here are two demonstrations of how to write a simple +printer driver for ppdev. Firstly we will use +the write function, and after that we will drive +the control and data lines directly. + +The first thing to do is to actually open the device. + + + +Here name should be something along the lines +of "/dev/parport0". (If you don't have any +/dev/parport files, you can make them with +mknod; they are character special device nodes with +major 99.) + +In order to do anything with the port we need to claim access to +it. + + + +Our printer driver will copy its input (from +stdin) to the printer, and it can do that it one of +two ways. The first way is to hand it all off to the kernel driver, +with the knowledge that the protocol that the printer speaks is IEEE +1284's compatibility mode. + + 0) { + int written = write_printer (fd, ptr, got); + + if (written < 0) { + perror ("write"); + close (fd); + return 1; + } + + ptr += written; + got -= written; + } + } +]]> + +The write_printer function is not pictured +above. This is because the main loop that is shown can be used for +both methods of driving the printer. Here is one implementation of +write_printer: + + + +We hand the data to the kernel-level driver (using +write) and it handles the printer +protocol. + +Now let's do it the hard way! In this particular example there +is no practical reason to do anything other than just call +write, because we know that the printer talks an +IEEE 1284 protocol. On the other hand, this particular example does +not even need a user-land driver since there is already a kernel-level +one; for the purpose of this discussion, try to imagine that the +printer speaks a protocol that is not already implemented under +Linux. + +So, here is the alternative implementation of +write_printer (for brevity, error checking has +been omitted): + + + +To show a bit more of the ppdev interface, +here is a small piece of code that is intended to mimic the printer's +side of printer protocol. + + 1) + fprintf (stderr, "Arghh! Missed %d interrupt%s!\n", + irqc - 1, irqc == 2 ? "s" : ""); + + /* Ack it. */ + ioctl (fd, PPWCONTROL, &acking); + usleep (2); + ioctl (fd, PPWCONTROL, &busy); + + putchar (ch); + } +]]> + + + + +
\ No newline at end of file diff -u --recursive --new-file v2.3.99-pre3/linux/Documentation/arm/SA1100/Brutus linux/Documentation/arm/SA1100/Brutus --- v2.3.99-pre3/linux/Documentation/arm/SA1100/Brutus Thu Feb 10 17:11:01 2000 +++ linux/Documentation/arm/SA1100/Brutus Mon Mar 27 10:46:29 2000 @@ -23,7 +23,7 @@ - RS232 serial ports - audio output - LCD screen - - keyboard (needs to be cleaned up badly... any volunteer?) + - keyboard The actual Brutus support may not be complete without extra patches. If such patches exist, they should be found from diff -u --recursive --new-file v2.3.99-pre3/linux/Documentation/arm/SA1100/ThinClient linux/Documentation/arm/SA1100/ThinClient --- v2.3.99-pre3/linux/Documentation/arm/SA1100/ThinClient Wed Dec 31 16:00:00 1969 +++ linux/Documentation/arm/SA1100/ThinClient Mon Mar 27 10:46:29 2000 @@ -0,0 +1,33 @@ +Thin Client / Single Board Computer + +The Thin Client, a low cost high power single board computer, has been +designed to provide intuitive graphical displays in embedded systems. + +For more details, contact Applied Data Systems or see +http://www.flatpanels.com/products.html + +Current Linux support for this product has been provided by Nicolas Pitre +. + +It's currently possible to mount a root filesystem via NFS providing a +complete Linux environment. Otherwyse a ramdisk image may be used. Use +'make thinclient_config' before any 'make config'. This will set up +defaults for ThinClient support. + +Supported peripherals: +- SA1100 LCD frame buffer (only 8bpp yet) +- on-board SMC 92C94 ethernet NIC +- SA1100 serial port +- possibly UCB1200 audio (not tested yet) + +To do: +- touchscreen driver +- flash memory access +- 16bpp frame buffer support +- extra (external) serial port driver +- pcmcia +- some console keyboard support (maybe IR?) +- everything else! :-) + +Any contribution can be sent to nico@cam.org and will be greatly welcome! + diff -u --recursive --new-file v2.3.99-pre3/linux/Documentation/filesystems/ntfs.txt linux/Documentation/filesystems/ntfs.txt --- v2.3.99-pre3/linux/Documentation/filesystems/ntfs.txt Tue Apr 28 14:22:04 1998 +++ linux/Documentation/filesystems/ntfs.txt Mon Apr 10 23:02:59 2000 @@ -4,10 +4,13 @@ To mount an NTFS volume, use the filesystem type 'ntfs'. The driver currently works only in read-only mode, with no fault-tolerance supported. If you enable the experimental write support, make sure -you can recover from a complete loss of data. For ftdisk support, -limited success was reported with volume sets on top of the md driver, -although mirror and stripe sets should work as well - if the md -driver can be talked into using the same layout as Windows NT. +you can recover from a complete loss of data and also always run +chkdsk from within Microsoft Windows NT after performing a write to +a NTFS partition from Linux to detect any problems as early as +possible. For ftdisk support, limited success was reported with +volume sets on top of the md driver, although mirror and stripe +sets should work as well - if the md driver can be talked into +using the same layout as Windows NT. The ntfs driver supports the following mount options: iocharset=name Character set to use when returning file names. diff -u --recursive --new-file v2.3.99-pre3/linux/Documentation/sound/CMI8330 linux/Documentation/sound/CMI8330 --- v2.3.99-pre3/linux/Documentation/sound/CMI8330 Thu Feb 10 17:11:02 2000 +++ linux/Documentation/sound/CMI8330 Mon Mar 27 11:02:54 2000 @@ -2,6 +2,9 @@ ------------------------------------- Alessandro Zummo +( Be sure to read Documentation/sound/SoundPro too ) + + This adapter is now directly supported by the sb driver. The only thing you have to do is to compile the kernel sound @@ -24,17 +27,6 @@ for MPU401 support. -CONFIG_SOUND_YM3812=m - - for OPL3 support. Please note that there are better ways to play midi files, like - timidity or the softoss2 module. - - -CONFIG_JOYSTICK=y - - to activate the joystick port. - - (I suggest you to use "make menuconfig" or "make xconfig" for a more comfortable configuration editing) @@ -51,25 +43,8 @@ sb: CMI8330 detected. sb: CMI8330 sb base located at 0x220 sb: CMI8330 mpu base located at 0x330 -sb: CMI8330 gameport base located at 0x200 -sb: CMI8330 opl3 base located at 0x388 sb: CMI8330 mail reports to Alessandro Zummo sb: ISAPnP reports CMI 8330 SoundPRO at i/o 0x220, irq 7, dma 1,5 - - - - -To activate the OPL3 support, you need these lines in /etc/modules.conf -or in a file in /etc/modutils - -alias synth0 opl3 -options opl3 io=0x388 - -and then you can do: - - modprobe opl3 - - diff -u --recursive --new-file v2.3.99-pre3/linux/Documentation/sound/PAS16 linux/Documentation/sound/PAS16 --- v2.3.99-pre3/linux/Documentation/sound/PAS16 Wed Dec 31 16:00:00 1969 +++ linux/Documentation/sound/PAS16 Sun Apr 2 15:38:53 2000 @@ -0,0 +1,185 @@ +Pro Audio Spectrum 16 for 2.3.99 and later +========================================= +by Thomas Molina (tmolina@home.com) +last modified 26 Mar 2000 +Acknowledgement to Axel Boldt (boldt@math.ucsb.edu) for stuff taken +from Configure.help, Riccardo Facchetti for stuff from README.OSS, +and others whose names I could not find. + +This documentation is relevant for the PAS16 driver (pas2_card.c and +friends) under kernel version 2.3.99 and later. If you are +unfamiliar with configuring sound under Linux, please read the +Sound-HOWTO, linux/Documentation/sound/Introduction and other +relevant docs first. + +The following information is relevant information from README.OSS +and legacy docs for the Pro Audio Spectrum 16 (PAS16): +================================================================== + +The pas2_card.c driver supports the following cards -- +Pro Audio Spectrum 16 (PAS16) and compatibles: + Pro Audio Spectrum 16 + Pro Audio Studio 16 + Logitech Sound Man 16 + NOTE! The original Pro Audio Spectrum as well as the PAS+ are not + and will not be supported by the driver. + +The sound driver configuration dialog +------------------------------------- + +Sound configuration starts by making some yes/no questions. Be careful +when answering to these questions since answering y to a question may +prevent some later ones from being asked. For example don't answer y to +the question about (PAS16) if you don't really have a PAS16. Sound +configuration may also be made modular by answering m to configuration +options presented. + +Note also that all questions may not be asked. The configuration program +may disable some questions depending on the earlier choices. It may also +select some options automatically as well. + + "ProAudioSpectrum 16 support", + - Answer 'y'_ONLY_ if you have a Pro Audio Spectrum _16_, + Pro Audio Studio 16 or Logitech SoundMan 16 (be sure that + you read the above list correctly). Don't answer 'y' if you + have some other card made by Media Vision or Logitech since they + are not PAS16 compatible. + NOTE! Since 3.5-beta10 you need to enable SB support (next question) + if you want to use the SB emulation of PAS16. It's also possible to + the emulation if you want to use a true SB card together with PAS16 + (there is another question about this that is asked later). + "Sound Blaster support", + - Answer 'y' if you have an original SB card made by Creative Labs + or a full 100% hardware compatible clone (like Thunderboard or + SM Games). If your card was in the list of supported cards (above), + please look at the card specific instructions later in this file + before answering this question. For an unknown card you may answer + 'y' if the card claims to be SB compatible. + Enable this option also with PAS16. + + "Generic OPL2/OPL3 FM synthesizer support", + - Answer 'y' if your card has a FM chip made by Yamaha (OPL2/OPL3/OPL4). + The PAS16 has an OPL3-compatible FM chip. + +With PAS16 you can use two audio device files at the same time. /dev/dsp (and +/dev/audio) is connected to the 8/16 bit native codec and the /dev/dsp1 (and +/dev/audio1) is connected to the SB emulation (8 bit mono only). + + +The new stuff for 2.3.99 and later +============================================================================ +The following configuration options from linux/Documentation/Configure.help +are relevant to configuring the PAS16: + +Sound card support +CONFIG_SOUND + If you have a sound card in your computer, i.e. if it can say more + than an occasional beep, say Y. Be sure to have all the information + about your sound card and its configuration down (I/O port, + interrupt and DMA channel), because you will be asked for it. + + You want to read the Sound-HOWTO, available from + http://www.linuxdoc.org/docs.html#howto . General information + about the modular sound system is contained in the files + Documentation/sound/Introduction. The file + Documentation/sound/README.OSS contains some slightly outdated but + still useful information as well. + +OSS sound modules +CONFIG_SOUND_OSS + OSS is the Open Sound System suite of sound card drivers. They make + sound programming easier since they provide a common API. Say Y or M + here (the module will be called sound.o) if you haven't found a + driver for your sound card above, then pick your driver from the + list below. + +Persistent DMA buffers +CONFIG_SOUND_DMAP + Linux can often have problems allocating DMA buffers for ISA sound + cards on machines with more than 16MB of RAM. This is because ISA + DMA buffers must exist below the 16MB boundary and it is quite + possible that a large enough free block in this region cannot be + found after the machine has been running for a while. If you say Y + here the DMA buffers (64Kb) will be allocated at boot time and kept + until the shutdown. This option is only useful if you said Y to + "OSS sound modules", above. If you said M to "OSS sound modules" + then you can get the persistent DMA buffer functionality by passing + the command-line argument "dmabuf=1" to the sound.o module. + + Say y here for PAS16. + +ProAudioSpectrum 16 support +CONFIG_SOUND_PAS + Answer Y only if you have a Pro Audio Spectrum 16, ProAudio Studio + 16 or Logitech SoundMan 16 sound card. Don't answer Y if you have + some other card made by Media Vision or Logitech since they are not + PAS16 compatible. + If you compile the driver into the kernel, you have to add + "pas2=,,,,,,, + to the kernel command line. + +100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support +CONFIG_SOUND_SB + Answer Y if you have an original Sound Blaster card made by Creative + Labs or a 100% hardware compatible clone (like the Thunderboard or + SM Games). For an unknown card you may answer Y if the card claims + to be Sound Blaster-compatible. The PAS16 has 8-bit Soundblaster + support, so you can answer Y here for it. + + Please read the file Documentation/sound/Soundblaster. + + If you compile the driver into the kernel and don't want to use isapnp, + you have to add "sb=,,," to the kernel command line. + + You can say M here to compile this driver as a module; the module is + called sb.o. + +FM Synthesizer (YM3812/OPL-3) support +CONFIG_SOUND_YM3812 + Answer Y if your card has a FM chip made by Yamaha (OPL2/OPL3/OPL4). + Answering Y is usually a safe and recommended choice, however some + cards may have software (TSR) FM emulation. Enabling FM support with + these cards may cause trouble (I don't currently know of any such + cards, however). + Please read the file Documentation/sound/OPL3 if your card has an + OPL3 chip. + If you compile the driver into the kernel, you have to add + "opl3=" to the kernel command line. + + If you compile your drivers into the kernel, you MUST configure + OPL3 support as a module for PAS16 support to work properly. + You can then get OPL3 functionality by issuing the command: + insmod opl3 + In addition, you must either add the following line to + /etc/modules.conf: + options opl3 io=0x388 + or else add the following line to /etc/lilo.conf: + opl3=0x388 + + +EXAMPLES +=================================================================== +To use the PAS16 in my computer I have enabled the following sound +configuration options: + +CONFIG_SOUND=y +CONFIG_SOUND_OSS=y +CONFIG_SOUND_TRACEINIT=y +CONFIG_SOUND_DMAP=y +CONFIG_SOUND_PAS=y +CONFIG_SOUND_SB=y +CONFIG_SOUND_YM3812=m + +I have also included the following append line in /etc/lilo.conf: +append="pas2=0x388,10,3,-1,0x220,5,1,-1 sb=0x220,5,1,-1 opl3=0x388" + +The io address of 0x388 is default configuration on the PAS16. The +irq of 10 and dma of 3 may not match your installation. The above +configuration enables PAS16, 8-bit Soundblaster and OPL3 +functionality. If Soundblaster functionality is not desired, the +following line would be appropriate: +append="pas2=0x388,10,3,-1,0,-1,-1,-1 opl3=0x388" + +If sound is built totally modular, the above options may be +specified in /etc/modules.conf for pas2.o, sb.o and opl3.o +respectively. diff -u --recursive --new-file v2.3.99-pre3/linux/Documentation/sound/SoundPro linux/Documentation/sound/SoundPro --- v2.3.99-pre3/linux/Documentation/sound/SoundPro Fri Jan 21 18:19:15 2000 +++ linux/Documentation/sound/SoundPro Mon Mar 27 11:02:54 2000 @@ -1,6 +1,8 @@ Documentation for the SoundPro CMI8330 extensions in the WSS driver (ad1848.o) ------------------------------------------------------------------------------ +( Be sure to read Documentation/sound/CMI8330 too ) + Ion Badulescu, ionut@cs.columbia.edu February 24, 1999 diff -u --recursive --new-file v2.3.99-pre3/linux/Documentation/sysrq.txt linux/Documentation/sysrq.txt --- v2.3.99-pre3/linux/Documentation/sysrq.txt Sun Mar 19 18:35:30 2000 +++ linux/Documentation/sysrq.txt Mon Apr 10 23:09:01 2000 @@ -1,7 +1,7 @@ - MAGIC SYSRQ KEY DOCUMENTATION v1.31 + MAGIC SYSRQ KEY DOCUMENTATION v1.32 ------------------------------------ - [Mon Mar 13 21:45:48 EST 2000] + [Sat Apr 8 22:15:03 CEST 2000] * What is the magic SysRQ key? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -113,13 +113,13 @@ * I hit SysRQ, but nothing seems to happen, what's wrong? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -There are some keyboards which do not support 'SysRQ', you can try running -'showkey -s' and pressing SysRQ or alt-SysRQ to see if it generates any -0x54 codes. If it doesn't, you may define the magic sysrq sequence to a -different key. Find the keycode with showkey, and change the define of -'#define SYSRQ_KEY 0x54' in [/usr/src/linux/]include/asm/keyboard.h to -the keycode of the key you wish to use, then recompile. Oh, and by the way, -you exit 'showkey' by not typing anything for ten seconds. +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 +for ten seconds. * I have more questions, who can I ask? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff -u --recursive --new-file v2.3.99-pre3/linux/Documentation/usb/CREDITS linux/Documentation/usb/CREDITS --- v2.3.99-pre3/linux/Documentation/usb/CREDITS Fri Jan 28 15:09:06 2000 +++ linux/Documentation/usb/CREDITS Sun Apr 2 15:20:16 2000 @@ -16,6 +16,7 @@ Paul Mackerras David E. Nelson Vojtech Pavlik + Bill Ryder Thomas Sailer Gregory P. Smith Linus Torvalds diff -u --recursive --new-file v2.3.99-pre3/linux/Documentation/usb/acm.txt linux/Documentation/usb/acm.txt --- v2.3.99-pre3/linux/Documentation/usb/acm.txt Thu Jan 6 12:57:47 2000 +++ linux/Documentation/usb/acm.txt Wed Apr 5 16:58:38 2000 @@ -1,94 +1,138 @@ -The ACM driver works with modems and ISDN TAs that use the USB Abstract -Control Model standard. - -**************************** -Test it: -Watch out, the driver is not stable and tested. Sync often, make backups, -most importand: don't blame me... - -Create device files: -mknod /dev/ttyACM0 c 166 0 -mknod /dev/ttyACM1 c 166 1 -mknod /dev/ttyACM2 c 166 2 -mknod /dev/ttyACM3 c 166 3 -Compile a kernel with support for your host controller (uhci only for now!) -and support for ACM. Boot this kernel. If you connect your device to the -USB bus you should see messages like the following: - -Jul 19 20:14:29 office kernel: USB new device connect, assigned device number 1 -Jul 19 20:14:29 office kernel: Found 02:09 -Jul 19 20:14:29 office kernel: Found 04:09 -Jul 19 20:14:29 office kernel: Found 05:07 -Jul 19 20:14:29 office last message repeated 2 times -Jul 19 20:14:29 office kernel: parsed = 39 len = 67 -Jul 19 20:14:29 office kernel: Expected descriptor 04/09, got 02/09 - skipping -Jul 19 20:14:29 office kernel: 0 09 -Jul 19 20:14:29 office kernel: 1 02 -Jul 19 20:14:29 office kernel: 2 43 -Jul 19 20:14:29 office kernel: 3 00 -Jul 19 20:14:29 office kernel: 4 02 -Jul 19 20:14:29 office kernel: 5 02 -Jul 19 20:14:29 office kernel: 6 04 -Jul 19 20:14:29 office kernel: 7 60 -Jul 19 20:14:29 office kernel: 8 00 -Jul 19 20:14:29 office kernel: Found 04:09 -Jul 19 20:14:29 office kernel: Found 02:09 -Jul 19 20:14:29 office kernel: Found 04:09 -Jul 19 20:14:29 office kernel: Found 05:07 -Jul 19 20:14:29 office kernel: Found 04:09 -Jul 19 20:14:29 office kernel: Found 05:07 -Jul 19 20:14:29 office kernel: Found 05:07 -Jul 19 20:14:29 office kernel: parsed = 67 len = 0 -Jul 19 20:14:29 office kernel: getstringtable -Jul 19 20:14:29 office kernel: acm_probe -Jul 19 20:14:29 office kernel: USB ACM found - -Watch out for the line: -Jul 19 20:14:29 office kernel: USB new device connect, assigned device number 1 -and the line: -Jul 19 20:14:29 office kernel: USB ACM found -These two lines show that the device was seen by the usb host controller and -then recognized by the acm driver as a valid device. - -If you use a terminal emulation software like minicom with /dev/ttyACM0 you -should be able to send AT commands to your device and get responses. I've -been able to do zmodem downloads to another pc. However downloads from one -ISDN TA to another ISDN TA connected to the same PC didn't work. Don't -know why. Flow control is not finised after all and i'd guess there might -be problems on heavily loades PCs. I also did some tests with ppp but i'm -not finised with this. There might be a chance to get it working. However -i'd like to know if your device is recognized as an ACM device. I'm also -interested if the thing is stable or if it crashes. -(should i say how it crases?) - -You should be able to add and remove devices from the bus. The driver will -always try to fill up unused ttys. This means if you hotplug devices their -order may have changed after reboot. This is not the behaviour Linus liked -to see but it's ok for now. (I hope ;-) - -Please report your experiences to me: -fuerst@in.tum.de - -*************************** -I've tested it with: -3Com ISDN Pro TA. - -It should work with (That means i know these devices conform to ACM): -3Com Office Connect Modem -3Com Sportster USB (I think that's what it's called) - -*************************** -Many thanks to 3Com which did not only support me with hardware but also -with technical support in USB questions. They also allowed me to do tests in -their lab. Great! - -*************************** -Known bugs: -Flow control not tested (likely not to work) -Some tty function calls not implemented (putchar, etc...) -Huge amounts of debug output (compile in [*] Magic SysRq key and press ALT+PRTSCR+0 ) -Not all mem is freed at close (need terminate irq in hcd) - -*************************** -Have fun, - Armin Fuerst + Linux ACM driver v0.16 + (c) 1999 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. Usage +~~~~~~~~ + The drivers/usb/acm.c drivers works with USB modems and USB ISDN terminal +adapters that conform to the Universal Serial Bus Communication Device Class +Abstract Control Model (USB CDC ACM) specification. + + Many modems do, here is a list of those I know of: + + 3Com OfficeConnect 56k + 3Com Voice FaxModem Pro + 3Com Sportster + MultiTech MultiModem 56k + Zoom 2986L FaxModem + Compaq 56k FaxModem + ELSA Microlink 56k + + I know of one ISDN TA that does work with the acm driver: + + 3Com USR ISDN Pro TA + + Unfortunately many modems and most ISDN TAs use proprietary interfaces and +thus won't work with this drivers. Check for ACM compliance before buying. + + The driver (with devfs) creates these devices in /dev/usb/acm: + + crw-r--r-- 1 root root 166, 0 Apr 1 10:49 0 + crw-r--r-- 1 root root 166, 1 Apr 1 10:49 1 + crw-r--r-- 1 root root 166, 2 Apr 1 10:49 2 + + And so on, up to 31, with the limit being possible to change in acm.c to up +to 256, so you can use up to 256 USB modems with one computer (you'll need +three USB cards for that, though). + + If you don't use devfs, then you can create device nodes with the same +minor/major numbers anywhere you want, but either the above location or +/dev/usb/ttyACM0 is preferred. + + To use the modems you need these modules loaded: + + usbcore.o + usb-[uo]hci.o or uhci.o + acm.o + + After that, the modem[s] should be accessible. You should be able to use +minicom, ppp and mgetty with them. + +2. Verifying that it works +~~~~~~~~~~~~~~~~~~~~~~~~~~ + The first step would be to check /proc/bus/usb/devices, it should look +like this: + +T: Bus=01 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 +B: Alloc= 0/900 us ( 0%), #Int= 0, #Iso= 0 +D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 +P: Vendor=0000 ProdID=0000 Rev= 0.00 +S: Product=USB UHCI Root Hub +S: SerialNumber=6800 +C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA +I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub +E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms +T: Bus=01 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 2 Spd=12 MxCh= 0 +D: Ver= 1.00 Cls=02(comm.) Sub=00 Prot=00 MxPS= 8 #Cfgs= 2 +P: Vendor=04c1 ProdID=008f Rev= 2.07 +S: Manufacturer=3Com Inc. +S: Product=3Com U.S. Robotics Pro ISDN TA +S: SerialNumber=UFT53A49BVT7 +C: #Ifs= 1 Cfg#= 1 Atr=60 MxPwr= 0mA +I: If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=acm +E: Ad=85(I) Atr=02(Bulk) MxPS= 64 Ivl= 0ms +E: Ad=04(O) Atr=02(Bulk) MxPS= 64 Ivl= 0ms +E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=128ms +C:* #Ifs= 2 Cfg#= 2 Atr=60 MxPwr= 0mA +I: If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=02 Prot=01 Driver=acm +E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=128ms +I: If#= 1 Alt= 0 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=acm +E: Ad=85(I) Atr=02(Bulk) MxPS= 64 Ivl= 0ms +E: Ad=04(O) Atr=02(Bulk) MxPS= 64 Ivl= 0ms + +The presence of these three lines (and the Cls= 'comm' and 'data' classes) +is important, it means it's an ACM device. The Driver=acm means the acm +driver is used for the device. If you see only Cls=ff(vend.) then you're out +of luck, you have a device with vendor specific-interface. + +D: Ver= 1.00 Cls=02(comm.) Sub=00 Prot=00 MxPS= 8 #Cfgs= 2 +I: If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=02 Prot=01 Driver=acm +I: If#= 1 Alt= 0 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=acm + +In the system log you should see: + +usb.c: USB new device connect, assigned device number 2 +usb.c: kmalloc IF c7691fa0, numif 1 +usb.c: kmalloc IF c7b5f3e0, numif 2 +usb.c: skipped 4 class/vendor specific interface descriptors +usb.c: new device strings: Mfr=1, Product=2, SerialNumber=3 +usb.c: USB device number 2 default language ID 0x409 +Manufacturer: 3Com Inc. +Product: 3Com U.S. Robotics Pro ISDN TA +SerialNumber: UFT53A49BVT7 +acm.c: probing config 1 +acm.c: probing config 2 +ttyACM0: USB ACM device +acm.c: acm_control_msg: rq: 0x22 val: 0x0 len: 0x0 result: 0 +acm.c: acm_control_msg: rq: 0x20 val: 0x0 len: 0x7 result: 7 +usb.c: acm driver claimed interface c7b5f3e0 +usb.c: acm driver claimed interface c7b5f3f8 +usb.c: acm driver claimed interface c7691fa0 + +If all this seems to be OK, fire up minicom and set it to talk to the ttyACM +device and try typing 'at'. If it responds with 'OK', then everything is +working. diff -u --recursive --new-file v2.3.99-pre3/linux/Documentation/usb/hid.txt linux/Documentation/usb/hid.txt --- v2.3.99-pre3/linux/Documentation/usb/hid.txt Thu Jan 6 12:57:47 2000 +++ linux/Documentation/usb/hid.txt Wed Dec 31 16:00:00 1969 @@ -1,162 +0,0 @@ - Linux HID driver v0.8 - (c) 1999 Vojtech Pavlik - (c) 1999 Andreas Gal - 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. Introduction -~~~~~~~~~~~~~~~ - This is a driver for USB devices conforming to the USB HID (Human Input -Device) standard. These devices include namely keyboards, mice and -joysticks. - - However many other devices (monitors, speakers, UPSs ...) also communicate -through the same protocol, which makes its specification somewhat bloated. -This isn't a problem, though, because the driver doesn't need to know about -all the possible devices it can control, and can just parse the protocol and -leave the rest of the job (for example understanding what the UPS wants to -say) to the userland. - - Because of this, the USB HID driver has two interfaces. One is via the -proc filesystem, allowing userland applications send and read arbitrary -reports to and from a connected USB device. The other is via a very simple -yet generic input device driver, which dispatches input events (keystrokes, -mouse or joystick movements) to specific, backward compatible userland -interfaces. This way a PS/2 mouse, an AT keyboard or a Linux joystick driver -interface are emulated, and allow applications to immediately work with USB -mice, USB keyboards and USB joysticks without any changes. - - The input driver is aimed for a little more than USB device handling in -the future, though. It's generic enough so that it can be used for any -mouse, keyboard or joystick (and more, of course). A PS/2 mouse driver, a -serial mouse, Sun mouse, and most of the busmouse drivers were rewritten to -use this as well as the AT keyboard and Sun keyboard drivers. This will -hopefully allow conversion of all Linux keyboard and mouse and joystick -drivers to this scheme. - - 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. -There is also a mailing list for this: - - listproc@atrey.karlin.mff.cuni.cz - -Send "subscribe linux-joystick Your Name" to subscribe to it. - -2. Usage -~~~~~~~~ - Since the driver comes with recent 2.3 kernels, all that's needed to use -it is to enable it either as a module or compiled-in into the kernel. - - After that, after reboot (and possibly also inserting the USB and HID -modules) the following will happen: - -* If you selected keyboard support, all USB keystrokes will be also routed - to the Linux keyboard driver as if being input through the ordinary system - keyboard. - -* If you selected mouse support, there will be (one or more) simulated PS/2 - mouse devices on major 10, minor 32, 33 and more. These simulated mice can - in addition to a standard 3-button PS/2 mouse behave like MS Intellimice, - with a wheel. If you want to use the wheel, just specify '-t imps2' to gpm - and 'Protocol "ImPS/2"' to X, and it will work. A single emulated mouse - device can be open by any number of processes (unlike the /dev/psaux), and - for each of them the emulation is separate, each can use a different mode. - The mousedev driver, which emulates the mice, can also emulate a Genius - NewScroll 5 buttons-and-a-wheel mouse, if you set it to a Genius PS/2 - mode ('-t netmouse' 'Protocol "NetMousePS/2"'). However, not gpm, nor X - can decode the 5 buttons yet, so this isn't very useful right now. - -* If you selected joystick support, the driver will take over major 15, the - joystick major number, and will emulate joysticks on it. This means the - normal joystick driver can't be used together with it (now, after the - normal joystick drivers are converted to the input scheme, all will work - nicely together). Also, you'll probably need to calibrate your joystick - manually ('man jscal') to be able to use it, because the USB - autocalibration is far from perfect yet. - -* If you selected event device support, there will be devices on major 10, - minors 64, 65 and more for each input device connected through this - driver. These devices output raw events the input driver dispatches. Each - has a timestamp. This hopefully will be THE way X will talk to keyboard - and mice, because it's hardware independent, and not limited by existing - de-facto standards. - -3. 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/hidmouse (c, 10, 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). - -4. FAQ -~~~~~~ -Q: Why aren't any questions here yet? -A: Because none were frequent enough yet. - -5. Event interface -~~~~~~~~~~~~~~~~~~ - Should you want to add event device support into any application (X, gpm, -svgalib ...) I (vojtech@suse.cz) 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/inputX 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. - -6. Proc interface -~~~~~~~~~~~~~~~~~ - For HID-specific devices there is also the /proc interface. It isn't -present in this release yet, though, so it's description will appear here -together with the code in the driver. diff -u --recursive --new-file v2.3.99-pre3/linux/Documentation/usb/ibmcam.txt linux/Documentation/usb/ibmcam.txt --- v2.3.99-pre3/linux/Documentation/usb/ibmcam.txt Thu Mar 2 14:36:22 2000 +++ linux/Documentation/usb/ibmcam.txt Sun Apr 2 15:19:56 2000 @@ -7,8 +7,7 @@ This driver was developed using logs of observed USB traffic which was produced by standard Windows driver (c-it98.sys). -I did not have any input from Xirlink. Some people asked about -data sheets, but nothing came out of that. I didn't try. +I did not have data sheets from Xirlink. Video formats: 128x96 [model 1] @@ -29,14 +28,16 @@ IBM "C-It" camera, also known as "Xirlink PC Camera" The device uses proprietary ASIC (and compression method); it is manufactured by Xirlink. See http://www.xirlink.com/ -or http://www.c-itnow.com/ for details and pictures. +http://www.ibmpccamera.com or http://www.c-itnow.com/ for +details and pictures. The Linux driver was developed with camera with following model number (or FCC ID): KSX-XVP510. This camera has three interfaces, each with one endpoint (control, iso, iso). This -type of cameras is referred to as "model 1". +type of cameras is referred to as "model 1". These cameras are +no longer manufactured. -It appears that Xirlink made some changes in their cameras recently. +Xirlink now manufactures new cameras which are somewhat different. In particular, following models [FCC ID] belong to that category: XVP300 [KSX-X9903] @@ -46,29 +47,20 @@ (see http://www.xirlink.com/ibmpccamera/ for updates, they refer to these new cameras by Windows driver dated 12-27-99, v3005 BETA) These cameras have two interfaces, one endpoint in each (iso, bulk). -Such type of cameras is referred to as "model 2". They are supported. +Such type of cameras is referred to as "model 2". They are supported +(with exception of 352x288 native mode). Quirks of Model 2 cameras: ------------------------- -These cameras apparently produce only 176x144 native video stream; -the 352x288 formats are produced from 176x144 RGB stream. In fact, -Xirlink broke perfectly good Model 1 (which used I420 on all sizes) -and instead switched to color-separated RGB which is a terrible waste -of bandwidth and resolution. However it probably allowed to simplify -the camera and use less RAM. Model 2 camera works visibly worse than -model 1 even using Xirlink's own driver on Windows. The image quality -is better on Linux than on Windows, partly thanks to _absence_ of -annoying automatic color corrections which Windows driver feeds into -the camera several times per second. - Model 2 does not have hardware contrast control. Corresponding V4L control is not used at the moment. It may be possible to implement contrast control in software, at cost of extra processor cycles. -The bandwidth demand imposed by RGB quasi-352x288 mode (800 Kbits per -frame) essentially limits this mode to 10 frames per second or less, in -ideal conditions on the bus (USB is shared, after all). The frame rate +This driver provides 352x288 mode by switching the camera into +quasi-352x288 RGB mode (800 Kbits per frame) essentially limiting +this mode to 10 frames per second or less, in ideal conditions on +the bus (USB is shared, after all). The frame rate has to be programmed very conservatively. Additional concern is that frame rate depends on brightness setting; therefore the picture can be good at one brightness and broken at another! I did not want to fix @@ -81,24 +73,21 @@ to send all data. However if you regularly use Model 2 cameras you may prefer videosize=1 which makes perfectly good I420, with no scaling and lesser demands on USB (300 Kbits per second, or 26 frames per second). -Remember that model 2 cameras never produce images with resolution -better than "true" 176x144 - or so it seems. The camera that I had also has a hardware quirk: if disconnected, it needs few minutes to "relax" before it can be plugged in again (poorly designed USB processor reset circuit?) -Finally, to say something good about Model 2: it is much simpler to program -than Model 1. Commands are few, and they all are straightforward. This camera -can be programmed for very high sensitivity (starlight may be enough), this -makes it convenient for tinkering with. The driver code has enough comments -to help a programmer to tweak the camera as s/he feels necessary. +Model 2 camera can be programmed for very high sensitivity (even starlight +may be enough), this makes it convenient for tinkering with. The driver +code has enough comments to help a programmer to tweak the camera +as s/he feels necessary. WHAT YOU NEED: - A supported IBM PC (C-it) camera (model 1 or 2) -- A Linux box with USB support (2.3/2.4 or 2.2 w/backport) +- A Linux box with USB support (2.3/2.4; 2.2 w/backport may work) - A Video4Linux compatible frame grabber program such as xawtv. @@ -179,6 +168,19 @@ FLAGS_OVERLAY_STATS 8 Shows tiny numbers on screen, useful only for debugging. FLAGS_FORCE_TESTPATTERN 16 Shows blue screen with numbers. + FLAGS_SEPARATE_FRAMES 32 Shows each frame separately, as + it was received from the camera. + Default (not set) is to mix the + preceding frame in to compensate + for occasional loss of Isoc data + on high frame rates. + FLAGS_CLEAN_FRAMES 64 Forces "cleanup" of each frame + prior to use; relevant only if + FLAGS_SEPARATE_FRAMES is set. + Default is not to clean frames, + this is a little faster but may + produce flicker if frame rate is + too high and Isoc data gets lost. framerate This setting controls frame rate of the camera. This is an approximate setting (in terms of "worst" ... "best") diff -u --recursive --new-file v2.3.99-pre3/linux/Documentation/usb/input.txt linux/Documentation/usb/input.txt --- v2.3.99-pre3/linux/Documentation/usb/input.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/usb/input.txt Wed Apr 5 16:58:38 2000 @@ -0,0 +1,294 @@ + Linux Input drivers v0.9 + (c) 1999 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. 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 32: + + crw-r--r-- 1 root root 13, 32 Mar 28 22:45 mouse0 + + 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/mouse0 c 13 32 + + 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/mouse0 + + And in X: + + Section "Pointer" + Protocol "ImPS/2" + Device "/dev/input/mouse0" + 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 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 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 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 + +and so on, up to mouse31. Each is assigned to a single mouse or digitizer, +unless CONFIG_INPUT_MOUSEDEV_MIX is set. In that case all mice and +digitizers share a single character device, mouse0, and even when none are +connected, mouse0 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. + + Mousedev.c will generate either PS/2, ImPS/2 (microsoft intellimouse) or +GenPS/2 (genius netmouse/netscroll) protocols, depending on what the program +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 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. +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/inputX 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.3.99-pre3/linux/Documentation/usb/ov511.txt linux/Documentation/usb/ov511.txt --- v2.3.99-pre3/linux/Documentation/usb/ov511.txt Tue Mar 14 19:10:38 2000 +++ linux/Documentation/usb/ov511.txt Wed Apr 5 17:01:56 2000 @@ -5,42 +5,17 @@ Author: Mark McClelland Homepage: http://alpha.dyndns.org/ov511 +NEW IN THIS VERSION: + o Support for OV511+ + o Support for OV7620 + INTRODUCTION: This is a preliminary version of my OV511 Linux device driver. Currently, it can grab a frame in color (YUV420) at 640x480 or 320x240 using either vidcat or xawtv. Other utilities may work but have not yet been tested. -NEW IN THIS VERSION: - o Preliminary snapshot support - o Experimental red-blue misalignment fixes - o Better YUV420 color conversion - o Module options - o Finer-grained debug message control - o Support for new cameras (4, 36) - o Uses initcalls - -SUPPORTED CAMERAS: -_________________________________________________________ -Manufacturer | Model | Custom ID | Status ------------------+-----------------+-----------+--------- -MediaForte | MV300 | 0 | Working -Aiptek | HyperVCam ? | 0 | Working -NetView | NV300M | 0 | Working -D-Link | DSB-C300 | 3 | Working -Hawking Tech. | ??? | 3 | Working -??? | Generic | 4 | Untested -Puretek | PT-6007 | 5 | Working -Creative Labs | WebCam 3 | 21 | Working -??? | Koala-Cam | 36 | Untested -Lifeview | RoboCam | 100 | Untested -AverMedia | InterCam Elite | 102 | Working -MediaForte | MV300 | 112 | Working -Omnivision | OV7110 EV board | 112 | Working* ---------------------------------------------------------- -(*) uses OV7110 (monochrome) - -Any camera using the OV511 and the OV7610 CCD should work with this driver. The +Any camera using the OV511/OV511+ and the OV7610/20/20AE CCD should work. The driver only detects known cameras though, based on their custom id number. If you have a currently unsupported camera, the ID number should be reported to you in the kernel logs. Please send me the model, manufacturer and ID number and I @@ -140,7 +115,7 @@ DESC: The camera normally adjusts exposure, gain, and hue automatically. This can be set to 0 to disable this automatic adjustment. Note that there is currently no way to set these parameters manually once autoadjust is - disabled. (This feature is not working yet) + disabled. NAME: debug TYPE: integer (0-6) @@ -174,7 +149,8 @@ o Color streaming/capture at 640x480 and 320x240 o YUV420 color o Monochrome - o Setting/getting of saturation, contrast and brightness (no color yet) + o Setting/getting of saturation, contrast and brightness (no hue yet; only + works with OV7610, not the OV7620 or OV7620AE) EXPERIMENTAL FEATURES: o fix_rgb_offset: Sometimes works, but other times causes errors with xawtv and @@ -197,13 +173,13 @@ o Get hue (red/blue channel balance) adjustment working (in ov511_get_picture() and ov511_set_picture()) o Get autoadjust disable working - o Devise some clean way to support different types of CCDs (based on Custom ID) - o OV511A support o V4L2 support (Probably not until it goes into the kernel) o Fix I2C initialization. Some people are reporting problems with reading the 7610 registers. This could be due to timing differences, an excessive I2C clock rate, or a problem with ov511_i2c_read(). o Get rid of the memory management functions (put them in videodev.c??) + o Setting of contrast and brightness not working with 7620 + o Driver/camera state save/restore for when USB supports suspend/resume HOW TO CONTACT ME: diff -u --recursive --new-file v2.3.99-pre3/linux/Documentation/usb/proc_usb_info.txt linux/Documentation/usb/proc_usb_info.txt --- v2.3.99-pre3/linux/Documentation/usb/proc_usb_info.txt Thu Jan 6 12:57:47 2000 +++ linux/Documentation/usb/proc_usb_info.txt Mon Mar 27 10:09:20 2000 @@ -1,16 +1,17 @@ /proc/bus/usb filesystem output =============================== -(version 19991218) +(version 2000.03.24) The /proc filesystem for USB devices generates /proc/bus/usb/drivers and /proc/bus/usb/devices. -/proc/bus/usb/drivers just lists the registered drivers, -one per line. Not very interesting or pretty. +/proc/bus/usb/drivers lists the registered drivers, +one per line, with each driver's USB minor dev node +number range if applicable. In /proc/bus/usb/devices, each device's output has multiple -lines (except for a root hub) of ASCII output. +lines of ASCII output. I made it ASCII instead of binary on purpose, so that someone can obtain some useful data from it without the use of an auxiliary program. However, with an auxiliary program, the numbers @@ -22,11 +23,12 @@ Each line is tagged with a one-character ID for that line: T = Topology (etc.) -B = Bandwidth +B = Bandwidth (applies only to USB host controllers, which are + virtualized as root hubs) D = Device descriptor info. P = Product ID info. (from Device descriptor, but they won't fit together on one line) -S = String info +S = String descriptors. C = Configuration descriptor info. (* = active configuration) I = Interface descriptor info. E = Endpoint descriptor info. @@ -93,7 +95,17 @@ |__String info tag S: Product=ssss -| |__Product description of this device as read from the device. +| |__Product description of this device as read from the device, +| except that it is a generated string for USB host controllers +| (virtual root hubs), in the form "USB *HCI Root Hub". +|__String info tag + +S: SerialNumber=ssss +| |__Serial Number of this device as read from the device, +| except that it is a generated string for USB host controllers +| (virtual root hubs), and represent's the host controller's +| unique identification in the system (currently I/O or +| memory-mapped base address). |__String info tag @@ -142,7 +154,7 @@ script, it can display any selected lines (for example, only T, D, and P lines) and change their output format. (The "procusb" Perl script is the beginning of this idea. It will list only -selected lines [selected from TDPCIE] or "All" lines from +selected lines [selected from TBDPSCIE] or "All" lines from /proc/bus/usb/devices.) The Topology lines can be used to generate a graphic/pictorial @@ -163,6 +175,13 @@ T: Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 B: Alloc= 28/900 us ( 3%), #Int= 2, #Iso= 0 +D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 +P: Vendor=0000 ProdID=0000 Rev= 0.00 +S: Product=USB UHCI Root Hub +S: SerialNumber=dce0 +C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA +I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub +E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms T: Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 4 D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 P: Vendor=0451 ProdID=1446 Rev= 1.00 diff -u --recursive --new-file v2.3.99-pre3/linux/Documentation/usb/scanner-hp-sane.txt linux/Documentation/usb/scanner-hp-sane.txt --- v2.3.99-pre3/linux/Documentation/usb/scanner-hp-sane.txt Fri Jan 28 15:09:06 2000 +++ linux/Documentation/usb/scanner-hp-sane.txt Mon Mar 27 09:44:58 2000 @@ -1,10 +1,11 @@ Copyright (C) 1999, 2000 David E. Nelson -Jan. 22, 2000 +Mar. 23, 2000 CHANGES - Amended for Linux-2.3.40 +- Updated for multiple scanner support INTRODUCTION @@ -30,13 +31,13 @@ version SANE-1.0.1. For instructions on building and installing SANE, refer to the various README files within the SANE distribution. -The latest SANE HP backend available from http://www.kirchgessner.net. +The latest SANE HP backend is available from http://www.kirchgessner.net. At the time of this writing, version 0.83 was available. OK, I'VE INSTALLED SANE. SO WHAT DO I DO NOW? -NOTE: $INSTALL_DIR is the location where SANE was installed. It may +NOTE: $INSTALL_DIR is the location where SANE is installed. It may be /usr/local, /usr, /opt or somewhere else. If you don't know, ask your system administrator. @@ -53,6 +54,9 @@ /dev/usbscanner option connect-device + +NOTE: If you are using multiple scanners, make sure to have the correct +devince, ie /dev/usbscanner0. See scanner.txt for more info. 3) You should now be able to use SANE (xscanimage or scanimage). diff -u --recursive --new-file v2.3.99-pre3/linux/Documentation/usb/scanner.txt linux/Documentation/usb/scanner.txt --- v2.3.99-pre3/linux/Documentation/usb/scanner.txt Fri Jan 28 15:09:06 2000 +++ linux/Documentation/usb/scanner.txt Mon Mar 27 09:44:58 2000 @@ -1,12 +1,15 @@ Copyright (C) 1999, 2000 David E. Nelson -Jan. 22, 2000 +Mar. 23, 2000 CHANGES - Amended for linux-2.3.40 - Appended hp_scan.c to end of this README - Removed most references to HP +- Updated uhci/ohci host controller info +- Updated support for multiple scanner support +- Updated supported scanners list OVERVIEW @@ -28,10 +31,8 @@ REQUIREMENTS A host with a USB port. Ideally, either a UHCI (Intel) or OHCI -(Compaq and others) hardware port should work. However, I've only -been able to really use an OHCI controller. At the time of this -writing, both uhci and ohci work with scanner.c *except* for the HP -4100C which only works with ohci. This problem is being investigated. +(Compaq and others) hardware port should work. At the time of this +writing, there are two UHCI drivers and one OHCI. A Linux development kernel (2.3.x) with USB support enabled or a backported version to linux-2.2.x. See http://www.linux-usb.org for @@ -69,12 +70,26 @@ (you may need to execute `depmod -a` to update the module dependencies). Testing was performed only as modules, YMMV. -Add a device for the USB scanner: - `mknod /dev/usbscanner c 180 48` - -Set appropriate permissions for /dev/usbscanner (don't forget about -group and world permissions). Both read and write permissions are -required for proper operation. +Beginning with version 0.4 of the driver, up to 16 scanners can be +connected/used simultaneously. If you intend to use more than +one scanner at a time: + + Add a device for the USB scanner: + `mknod /dev/usbscanner0 c 180 48` + `mknod /dev/usbscanner1 c 180 49` + . + . + `mknod /dev/usb/scanner15 180 63` + + +If you forsee using only one scanner: + `mknod /dev/usbscanner0 c 180 48` + `ln -s /dev/usbscanner0 /dev/usbscanner` + + +Set appropriate permissions for /dev/usbscanner[0-15] (don't forget +about group and world permissions). Both read and write permissions +are required for proper operation. Load the appropriate modules (if compiled as modules): @@ -110,25 +125,49 @@ At the time of this writing, the following scanners were supported by scanner.c: + Acer + + Prisa AcerScan 620U + + Agfa + + SnapScan 1212U, SnapScan Touch + + Genius + + ColorPage Vivid Pro + Hewlett Packard 3300, 4100, 4200, 5200, 6200, 6300, PhotoSmart S20 - AGFA + Microtek - SnapScan 1212U + ScanMaker X6-X6U, Phantom 336CX - C3, Phantom C6, ScanMaker V6USL, + ScanMaker V6UL - SpicyU - Umax + Mustek - Astra 2000U + 1200 CU + + Primax/Colorado + + G2-300, G2-600, G2E-300, G2E-600, ReadyScan 636i, Colorado USB + 19200, Colorado 600u, Colorado 1200u Seiko/Epson - Perfection 636, Perfection 1200U + Perfection Perfection 610, Perfection 636U/636Photo, Perfection + 1200U/1200Photo - Mustek + Umax + + Astra 1220U, 1236U, 2000U + + Visioneer + + OneTouch 5300, OneTouch 7600, 6100, - 1200 CU User Specified. See MODULE PARAMETERS for details. @@ -142,11 +181,11 @@ product=0x****' to the conf.modules/modules.conf file replacing the #'s and the *'s with the correct ID's. The ID's can be retrieved from the messages file or using `cat /proc/bus/usb/devices` if USB /proc -support was selected during kernel configuration. In later kernels -(2.3.38+), a new filesystem was introduced, usbdevfs. To mount the -filesystem, issue the command `mount -t usbdevfs /proc/bus/usb -/proc/bus/usb`. You can then issue ` cat /proc/bus/usb/devices` to -extract USB device information. +support was selected during kernel configuration. **NOTE**:In later +kernels (2.3.38+), a new filesystem was introduced, usbdevfs. To +mount the filesystem, issue the command `mount -t usbdevfs +/proc/bus/usb /proc/bus/usb`. You can then issue ` cat +/proc/bus/usb/devices` to extract USB device information. BUGS diff -u --recursive --new-file v2.3.99-pre3/linux/Documentation/usb/usb-help.txt linux/Documentation/usb/usb-help.txt --- v2.3.99-pre3/linux/Documentation/usb/usb-help.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/usb/usb-help.txt Mon Mar 27 09:44:58 2000 @@ -0,0 +1,16 @@ +usb-help.txt +2000-March-24 + +For USB help other than the readme files that are located in +linux/Documentation/usb/*, see the following: + +Linux-USB project: http://www.linux-usb.org + mirrors at http://www.suse.cz/development/linux-usb/ + and http://usb.in.tum.de/linux-usb/ +Linux USB Guide: http://linuxusbguide.sourceforge.net +Linux-USB device overview (working devices and drivers): + http://www.qbik.ch/usb/devices/ + +The Linux-USB mailing list is linux-usb@suse.com . + +### diff -u --recursive --new-file v2.3.99-pre3/linux/Documentation/video4linux/README.cpia linux/Documentation/video4linux/README.cpia --- v2.3.99-pre3/linux/Documentation/video4linux/README.cpia Wed Dec 31 16:00:00 1969 +++ linux/Documentation/video4linux/README.cpia Mon Mar 27 10:22:30 2000 @@ -0,0 +1,191 @@ +This is a driver for the CPiA PPC2 driven parallel connected +Camera. For example the Creative WebcamII is CPiA driven. + + ) [1]Peter Pregler, Linz 2000, published under the [2]GNU GPL + +--------------------------------------------------------------------------- + +USAGE: + +General: +======== + +1) Make sure you have created the video devices (/dev/video*): + +- if you have a recent MAKEDEV do a 'cd /dev;./MAKEDEV video' +- otherwise do a: + +cd /dev +mknod video0 c 81 0 +ln -s video0 video + +2) Compile the kernel (see below for the list of options to use), + configure your parport and reboot. + +3) If all worked well you should get messages similar + to the following (your versions may be different) on the console: + +V4L-Driver for Vision CPiA based cameras v0.7.4 +parport0: read2 timeout. +parport0: Multimedia device, VLSI Vision Ltd PPC2 +Parallel port driver for Vision CPiA based camera + CPIA Version: 1.20 (2.0) + CPIA PnP-ID: 0553:0002:0100 + VP-Version: 1.0 0100 + 1 camera(s) found + + +As modules: +=========== + +Make sure you have selected the following kernel options (you can +select all stuff as modules): + +The cpia-stuff is in the section 'Character devices -> Video For Linux'. + +CONFIG_PARPORT=m +CONFIG_PARPORT_PC=m +CONFIG_PARPORT_PC_FIFO=y +CONFIG_PARPORT_1284=y +CONFIG_VIDEO_DEV=m +CONFIG_VIDEO_CPIA=m +CONFIG_VIDEO_CPIA_PP=m + +For autoloading of all those modules you need to tell kerneld some +stuff. Add the following line to your kerneld config-file +(e.g. /etc/modules.conf or wherever your distribution does store that +stuff): + +options parport_pc dma=3 irq=7 +alias char-major-81 cpia_pp + +The first line tells the dma/irq channels to use. Those _must_ match +the settings of your BIOS. Do NOT simply use the values above. See +Documentation/parport.txt for more information about this. The second +line associates the video-device file with the driver. Of cause you +can also load the modules once upon boot (usually done in /etc/modules). + +Linked into the kernel: +======================= + +Make sure you have selected the following kernel options. Note that +you cannot compile the parport-stuff as modules and the cpia-driver +statically (the other way round is okay though). + +The cpia-stuff is in the section 'Character devices -> Video For Linux'. + +CONFIG_PARPORT=y +CONFIG_PARPORT_PC=y +CONFIG_PARPORT_PC_FIFO=y +CONFIG_PARPORT_1284=y +CONFIG_VIDEO_DEV=y +CONFIG_VIDEO_CPIA=y +CONFIG_VIDEO_CPIA_PP=y + +To use DMA/irq you will need to tell the kernel upon boot time the +hardware configuration of the parport. You can give the boot-parameter +at the LILO-prompt or specify it in lilo.conf. I use the following +append-line in lilo.conf: + + append="parport=0x378,7,3" + +See Documentation/parport.txt for more information about the +configuration of the parport and the values given above. Do not simply +use the values given above. + +--------------------------------------------------------------------------- +FEATURES: + +- mmap/read v4l-interface (but no overlay) +- image formats: CIF/QCIF, SIF/QSIF, various others used by isabel; + note: all sizes except CIF/QCIF are implemented by clipping, i.e. + pixels are not uploaded from the camera +- palettes: VIDEO_PALETTE_GRAY, VIDEO_PALETTE_RGB565, VIDEO_PALETTE_RGB555, + VIDEO_PALETTE_RGB24, VIDEO_PALETTE_RGB32, VIDEO_PALETTE_YUYV, + VIDEO_PALETTE_UYVY, VIDEO_PALETTE_YUV422 +- state information (color balance, exposure, ...) is preserved between + device opens +- complete control over camera via proc-interface (_all_ camera settings are + supported), there is also a python-gtk application available for this [3] +- works under SMP (but the driver is completly serialized and synchronous) + so you get no benefit from SMP, but at least it does not crash your box +- might work for non-Intel architecture, let us know about this + +--------------------------------------------------------------------------- +TESTED APPLICATIONS: + +- a simple test application based on Xt is available at [3] +- another test-application based on gqcam-0.4 (uses GTK) +- gqcam-0.6 should work +- xawtv-3.x (also the webcam software) +- xawtv-2.46 +- w3cam (cgi-interface and vidcat, e.g. you may try out 'vidcat |xv + -maxpect -root -quit +noresetroot -rmode 5 -') +- vic, the MBONE video conferencing tool (version 2.8ucl4-1) +- isabel 3R4beta (barely working, but AFAICT all the problems are on + their side) +- camserv-0.40 + +See [3] for pointers to v4l-applications. + +--------------------------------------------------------------------------- +KNOWN PROBLEMS: + +- some applications do not handle the image format correctly, you will + see strange horizontal stripes instead of a nice picture -> make sure + your application does use a supported image size or queries the driver + for the actually used size (reason behind this: the camera cannot + provide any image format, so if size NxM is requested the driver will + use a format to the closest fitting N1xM1, the application should now + query for this granted size, most applications do not). +- all the todo ;) +- if there is not enough light and the picture is too dark try to + adjust the SetSensorFPS setting, automatic frame rate adjustment + has its price +- do not try out isabel 3R4beta (built 135), you will be disappointed + +--------------------------------------------------------------------------- +TODO: + +- multiple camera support (struct camera or something) - This should work, + but hasn't been tested yet. +- architecture independence? +- SMP-safe asynchronous mmap interface +- nibble mode for old parport interfaces +- streaming capture, this should give a performance gain + +--------------------------------------------------------------------------- +IMPLEMENTATION NOTES: + +The camera can act in two modes, streaming or grabbing. Right now a +polling grab-scheme is used. Maybe interrupt driven streaming will be +used for a ansychronous mmap interface in the next major release of the +driver. This might give a better frame rate. + +--------------------------------------------------------------------------- +THANKS (in no particular order): + +- Scott J. Bertin for cleanups, the proc-filesystem + and much more +- Henry Bruce for providing developers information about + the CPiA chip, I wish all companies would treat Linux as seriously +- Karoly Erdei and RISC-Linz for being + my boss ;) resp. my employer and for providing me the hardware and + allow me to devote some working time to this project +- Manuel J. Petit de Gabriel for providing help + with Isabel (http://isabel.dit.upm.es/) +- Bas Huisman for writing the initial parport code +- Jarl Totland for setting up the mailing list + and maintaining the web-server[3] +- Chris Whiteford for fixes related to the + 1.02 firmware +- special kudos to all the tester whose machines crashed and/or + will crash. :) + +--------------------------------------------------------------------------- +REFERENCES + + 1. http://www.risc.uni-linz.ac.at/people/ppregler + mailto:Peter_Pregler@email.com + 2. see the file COPYING in the top directory of the kernel tree + 3. http://webcam.sourceforge.net/ diff -u --recursive --new-file v2.3.99-pre3/linux/Documentation/video4linux/bttv/CARDLIST linux/Documentation/video4linux/bttv/CARDLIST --- v2.3.99-pre3/linux/Documentation/video4linux/bttv/CARDLIST Tue Mar 7 14:32:25 2000 +++ linux/Documentation/video4linux/bttv/CARDLIST Sun Apr 2 15:32:49 2000 @@ -37,6 +37,7 @@ card=35 - Chronos Video Shuttle II card=36 - Typhoon TView TV/FM Tuner card=37 - PixelView PlayTV pro + card=38 - TView99 CPH063 tuner.o type=0 - Temic PAL @@ -53,3 +54,4 @@ type=11 - Alps TSBB5 type=12 - Alps TSBE5 type=13 - Alps TSBC5 + type=14 - Temic 4006FH5 diff -u --recursive --new-file v2.3.99-pre3/linux/MAINTAINERS linux/MAINTAINERS --- v2.3.99-pre3/linux/MAINTAINERS Mon Mar 27 08:08:20 2000 +++ linux/MAINTAINERS Mon Apr 10 23:02:59 2000 @@ -740,6 +740,12 @@ L: linux-kernel@vger.rutgers.edu S: Maintained +NTFS FILESYSTEM +P: Anton Altaparmakov +M: aia21@cus.cam.ac.uk +L: linux-kernel@vger.rutgers.edu +S: Odd Fixes + NVIDIA (RIVA) FRAMEBUFFER DRIVER P: Jeff Garzik M: jgarzik@mandrakesoft.com @@ -822,8 +828,8 @@ S: Maintained PPP PROTOCOL DRIVERS AND COMPRESSORS -P: Al Longyear -M: longyear@pobox.com +P: Paul Mackerras +M: paulus@linuxcare.com L: linux-ppp@vger.rutgers.edu S: Maintained diff -u --recursive --new-file v2.3.99-pre3/linux/Makefile linux/Makefile --- v2.3.99-pre3/linux/Makefile Mon Mar 27 08:08:20 2000 +++ linux/Makefile Sun Apr 2 17:28:22 2000 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 3 SUBLEVEL = 99 -EXTRAVERSION = -pre3 +EXTRAVERSION = -pre4 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) @@ -88,7 +88,7 @@ endif CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -AFLAGS := $(CPPFLAGS) +AFLAGS := -D__ASSEMBLY__ $(CPPFLAGS) # use '-fno-strict-aliasing', but only if the compiler can take it CFLAGS += $(shell if $(CC) -fno-strict-aliasing -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-fno-strict-aliasing"; fi) @@ -185,9 +185,9 @@ export NETWORKS DRIVERS LIBS HEAD LDFLAGS LINKFLAGS MAKEBOOT ASFLAGS .S.s: - $(CPP) -D__ASSEMBLY__ $(AFLAGS) -traditional -o $*.s $< + $(CPP) $(AFLAGS) -traditional -o $*.s $< .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c -o $*.o $< + $(CC) $(AFLAGS) -traditional -c -o $*.o $< Version: dummy @rm -f include/linux/compile.h @@ -374,6 +374,7 @@ rm -f net/khttpd/times.h rm -f submenu* rm -rf modules + $(MAKE) -C Documentation/DocBook clean mrproper: clean archmrproper rm -f include/linux/autoconf.h include/linux/version.h @@ -398,8 +399,7 @@ rm -f .hdepend scripts/mkdep scripts/split-include scripts/docproc rm -f $(TOPDIR)/include/linux/modversions.h rm -rf $(TOPDIR)/include/linux/modules - make clean TOPDIR=$(TOPDIR) -C Documentation/DocBook - + $(MAKE) -C Documentation/DocBook mrproper distclean: mrproper rm -f core `find . \( -name '*.orig' -o -name '*.rej' -o -name '*~' \ -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \ @@ -412,6 +412,14 @@ sgmldocs: $(MAKE) -C $(TOPDIR)/Documentation/DocBook books +psdocs: sgmldocs + $(MAKE) -C scripts docproc + $(MAKE) -C Documentation/DocBook ps + +pdfdocs: sgmldocs + $(MAKE) -C scripts docproc + $(MAKE) -C Documentation/DocBook pdf + sums: find . -type f -print | sort | xargs sum > .SUMS @@ -434,7 +442,10 @@ find * -name '*.[hcS]' -type f -print | grep -v scripts/ | sort | xargs $(PERL) -w scripts/checkconfig.pl checkhelp: - $(PERL) -w scripts/checkhelp.pl `find * -name [cC]onfig.in -print` + find * -name [cC]onfig.in -print | sort | xargs $(PERL) -w scripts/checkhelp.pl + +checkincludes: + find * -name '*.[hcS]' -type f -print | sort | xargs $(PERL) -w scripts/checkincludes.pl ifdef CONFIGURATION ..$(CONFIGURATION): diff -u --recursive --new-file v2.3.99-pre3/linux/Rules.make linux/Rules.make --- v2.3.99-pre3/linux/Rules.make Mon Mar 27 08:08:21 2000 +++ linux/Rules.make Thu Mar 30 16:56:04 2000 @@ -48,7 +48,7 @@ $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -S $< -o $@ %.i: %.c - $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -E $< > $@ + $(CPP) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) $< > $@ %.o: %.c $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -c -o $@ $< diff -u --recursive --new-file v2.3.99-pre3/linux/arch/alpha/boot/Makefile linux/arch/alpha/boot/Makefile --- v2.3.99-pre3/linux/arch/alpha/boot/Makefile Mon Dec 20 18:48:21 1999 +++ linux/arch/alpha/boot/Makefile Thu Mar 30 16:56:04 2000 @@ -11,9 +11,9 @@ LINKFLAGS = -static -T bootloader.lds #-N -relax .S.s: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -E -o $*.o $< + $(CPP) $(AFLAGS) -traditional -o $*.o $< .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c -o $*.o $< + $(CC) $(AFLAGS) -traditional -c -o $*.o $< OBJECTS = head.o main.o BPOBJECTS = head.o bootp.o diff -u --recursive --new-file v2.3.99-pre3/linux/arch/alpha/config.in linux/arch/alpha/config.in --- v2.3.99-pre3/linux/arch/alpha/config.in Mon Mar 27 08:08:21 2000 +++ linux/arch/alpha/config.in Mon Mar 27 14:18:32 2000 @@ -65,6 +65,7 @@ # Most of these machines have ISA slots; not exactly sure which don't, # and this doesn't activate hordes of code, so do it always. define_bool CONFIG_ISA y +define_bool CONFIG_SBUS n if [ "$CONFIG_ALPHA_JENSEN" = "y" ] then @@ -189,6 +190,8 @@ if [ "$CONFIG_HOTPLUG" = "y" ] ; then source drivers/pcmcia/Config.in +else + define_bool CONFIG_PCMCIA n fi bool 'Networking support' CONFIG_NET @@ -274,7 +277,6 @@ source drivers/char/Config.in -source drivers/usb/Config.in #source drivers/misc/Config.in @@ -299,6 +301,8 @@ source drivers/sound/Config.in fi endmenu + +source drivers/usb/Config.in mainmenu_option next_comment comment 'Kernel hacking' diff -u --recursive --new-file v2.3.99-pre3/linux/arch/alpha/defconfig linux/arch/alpha/defconfig --- v2.3.99-pre3/linux/arch/alpha/defconfig Mon Mar 27 08:08:21 2000 +++ linux/arch/alpha/defconfig Mon Mar 27 09:38:47 2000 @@ -46,11 +46,13 @@ # CONFIG_ALPHA_SABLE is not set # CONFIG_ALPHA_TAKARA is not set CONFIG_ISA=y +# CONFIG_SBUS is not set CONFIG_PCI=y CONFIG_ALPHA_BROKEN_IRQ_MASK=y # CONFIG_SMP is not set CONFIG_PCI_NAMES=y # CONFIG_HOTPLUG is not set +# CONFIG_PCMCIA is not set CONFIG_NET=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set diff -u --recursive --new-file v2.3.99-pre3/linux/arch/alpha/kernel/Makefile linux/arch/alpha/kernel/Makefile --- v2.3.99-pre3/linux/arch/alpha/kernel/Makefile Sun Mar 19 18:35:30 2000 +++ linux/arch/alpha/kernel/Makefile Thu Mar 30 16:56:04 2000 @@ -8,9 +8,9 @@ # Note 2! The CFLAGS definitions are now in the main makefile... .S.s: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -E -o $*.s $< + $(CPP) $(AFLAGS) -o $*.s $< .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -c -o $*.o $< + $(CC) $(AFLAGS) -c -o $*.o $< O_TARGET := kernel.o O_OBJS := entry.o traps.o process.o osf_sys.o irq.o irq_alpha.o \ diff -u --recursive --new-file v2.3.99-pre3/linux/arch/alpha/kernel/irq_i8259.c linux/arch/alpha/kernel/irq_i8259.c --- v2.3.99-pre3/linux/arch/alpha/kernel/irq_i8259.c Thu Mar 2 14:36:22 2000 +++ linux/arch/alpha/kernel/irq_i8259.c Mon Mar 27 10:55:05 2000 @@ -146,12 +146,6 @@ */ int j = *(vuip) IACK_SC; j &= 0xff; - if (j == 7) { - if (!(inb(0x20) & 0x80)) { - /* It's only a passive release... */ - return; - } - } handle_irq(j, regs); } #endif diff -u --recursive --new-file v2.3.99-pre3/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c --- v2.3.99-pre3/linux/arch/alpha/kernel/osf_sys.c Mon Mar 27 08:08:21 2000 +++ linux/arch/alpha/kernel/osf_sys.c Sun Apr 2 15:53:28 2000 @@ -42,7 +42,7 @@ #include #include -extern int do_mount(struct block_device *, const char *, const char *, char *, int, void *); +extern long do_sys_mount(char *, char *, char *, int, void *); extern int do_pipe(int *); extern asmlinkage int sys_swapon(const char *specialfile, int swap_flags); @@ -319,20 +319,16 @@ asmlinkage int osf_fstatfs(unsigned long fd, struct osf_statfs *buffer, unsigned long bufsiz) { struct file *file; - struct dentry *dentry; int retval; - lock_kernel(); retval = -EBADF; file = fget(fd); - if (!file) - goto out; - dentry = file->f_dentry; - if (dentry) - retval = do_osf_statfs(dentry, buffer, bufsiz); - fput(file); -out: - unlock_kernel(); + if (file) { + lock_kernel(); + retval = do_osf_statfs(file->f_dentry, buffer, bufsiz); + unlock_kernel(); + fput(file); + } return retval; } @@ -363,32 +359,6 @@ uid_t exroot; }; -static struct dentry *getdev(const char *name, int rdonly) -{ - struct dentry *dentry; - struct inode *inode; - int retval; - - dentry = namei(name); - retval = PTR_ERR(dentry); - if (IS_ERR(dentry)) - return dentry; - - retval = -ENOTBLK; - inode = dentry->d_inode; - if (!S_ISBLK(inode->i_mode)) - goto out_dput; - - retval = -EACCES; - if (IS_NODEV(inode)) - goto out_dput; - return dentry; - -out_dput: - dput(dentry); - return ERR_PTR(retval); -} - /* * We can't actually handle ufs yet, so we translate UFS mounts to * ext2fs mounts. I wouldn't mind a UFS filesystem, but the UFS @@ -400,20 +370,18 @@ static int osf_ufs_mount(char *dirname, struct ufs_args *args, int flags) { int retval; - struct dentry *dentry; struct cdfs_args tmp; + char *devname; retval = -EFAULT; if (copy_from_user(&tmp, args, sizeof(tmp))) goto out; - - dentry = getdev(tmp.devname, 0); - retval = PTR_ERR(dentry); - if (IS_ERR(dentry)) + devname = getname(tmp.devname); + retval = PTR_ERR(devname); + if (IS_ERR(devname)) goto out; - retval = do_mount(dentry->d_inode->i_bdev, tmp.devname, dirname, - "ext2", flags, NULL); - dput(dentry); + retval = do_sys_mount(devname, dirname, "ext2", flags, NULL); + putname(devname); out: return retval; } @@ -421,20 +389,18 @@ static int osf_cdfs_mount(char *dirname, struct cdfs_args *args, int flags) { int retval; - struct dentry * dentry; struct cdfs_args tmp; + char *devname; retval = -EFAULT; if (copy_from_user(&tmp, args, sizeof(tmp))) goto out; - - dentry = getdev(tmp.devname, 1); - retval = PTR_ERR(dentry); - if (IS_ERR(dentry)) + devname = getname(tmp.devname); + retval = PTR_ERR(devname); + if (IS_ERR(devname)) goto out; - retval = do_mount(dentry->d_inode->i_bdev, tmp.devname, dirname, - "iso9660", flags, NULL); - dput(dentry); + retval = do_sys_mount(devname, dirname, "iso9660", flags, NULL); + putname(devname); out: return retval; } @@ -445,27 +411,36 @@ if (copy_from_user(&tmp, args, sizeof(tmp))) return -EFAULT; - return do_mount(NULL, "", dirname, "proc", flags, NULL); + + return do_sys_mount("", dirname, "proc", flags, NULL); } asmlinkage int osf_mount(unsigned long typenr, char *path, int flag, void *data) { int retval = -EINVAL; + char *name; lock_kernel(); + + name = getname(path); + retval = PTR_ERR(name); + if (IS_ERR(name)) + goto out; switch (typenr) { case 1: - retval = osf_ufs_mount(path, (struct ufs_args *) data, flag); + retval = osf_ufs_mount(name, (struct ufs_args *) data, flag); break; case 6: - retval = osf_cdfs_mount(path, (struct cdfs_args *) data, flag); + retval = osf_cdfs_mount(name, (struct cdfs_args *) data, flag); break; case 9: - retval = osf_procfs_mount(path, (struct procfs_args *) data, flag); + retval = osf_procfs_mount(name, (struct procfs_args *) data, flag); break; default: printk("osf_mount(%ld, %x)\n", typenr, flag); } + putname(name); +out: unlock_kernel(); return retval; } diff -u --recursive --new-file v2.3.99-pre3/linux/arch/arm/Makefile linux/arch/arm/Makefile --- v2.3.99-pre3/linux/arch/arm/Makefile Sun Mar 19 18:35:30 2000 +++ linux/arch/arm/Makefile Mon Mar 27 10:46:29 2000 @@ -100,7 +100,7 @@ LIBGCC := $(shell $(CC) $(CFLAGS) --print-libgcc-file-name) -export LIBGCC +export LIBGCC MACHINE PROCESSOR TEXTADDR ifeq ($(CONFIG_ARCH_A5K),y) MACHINE = a5k @@ -216,7 +216,7 @@ @$(MAKEBOOT) clean $(RM) arch/arm/lib/constants.h arch/arm/vmlinux.lds -archdep: +archdep: symlinks @$(MAKEBOOT) dep # My testing targets (that short circuit a few dependencies) @@ -256,3 +256,8 @@ empeg_config: $(RM) arch/arm/defconfig cp arch/arm/def-configs/empeg arch/arm/defconfig + +thinclient_config: + $(RM) arch/arm/defconfig + cp arch/arm/def-configs/thinclient arch/arm/defconfig + diff -u --recursive --new-file v2.3.99-pre3/linux/arch/arm/boot/compressed/head-sa1100.S linux/arch/arm/boot/compressed/head-sa1100.S --- v2.3.99-pre3/linux/arch/arm/boot/compressed/head-sa1100.S Thu Mar 2 14:36:22 2000 +++ linux/arch/arm/boot/compressed/head-sa1100.S Mon Mar 27 10:46:29 2000 @@ -17,8 +17,9 @@ #error What am I doing here... #endif -#ifdef CONFIG_SA1100_BRUTUS -@ need to enter SVC mode +#if defined( CONFIG_SA1100_BRUTUS ) || \ + defined( CONFIG_SA1100_THINCLIENT ) +@ Booting from Angel -- need to enter SVC mode #define angel_SWIreason_EnterSVC 0x17 /* from arm.h, in angel source */ #define angel_SWI_ARM (0xEF123456 & 0xffffff) mov r0, #angel_SWIreason_EnterSVC diff -u --recursive --new-file v2.3.99-pre3/linux/arch/arm/config.in linux/arch/arm/config.in --- v2.3.99-pre3/linux/arch/arm/config.in Mon Mar 27 08:08:21 2000 +++ linux/arch/arm/config.in Mon Mar 27 14:18:32 2000 @@ -53,6 +53,7 @@ Itsy CONFIG_SA1100_ITSY \ LART CONFIG_SA1100_LART \ PLEB CONFIG_SA1100_PLEB \ + ThinClient CONFIG_SA1100_THINCLIENT \ Victor CONFIG_SA1100_VICTOR \ Tifon CONFIG_SA1100_TIFON" Brutus fi @@ -136,6 +137,9 @@ define_bool CONFIG_ISA_DMA n fi +define_bool CONFIG_SBUS n +define_bool CONFIG_PCMCIA n + if [ "$CONFIG_CPU_32" = "y" -a "$CONFIG_ARCH_EBSA110" != "y" ]; then bool 'Kernel-mode alignment trap handler' CONFIG_ALIGNMENT_TRAP fi @@ -218,7 +222,6 @@ fi fi -source drivers/usb/Config.in #source drivers/misc/Config.in @@ -297,6 +300,8 @@ fi source fs/Config.in + +source drivers/usb/Config.in mainmenu_option next_comment comment 'Kernel hacking' diff -u --recursive --new-file v2.3.99-pre3/linux/arch/arm/def-configs/brutus linux/arch/arm/def-configs/brutus --- v2.3.99-pre3/linux/arch/arm/def-configs/brutus Tue Dec 14 01:27:23 1999 +++ linux/arch/arm/def-configs/brutus Mon Mar 27 10:46:29 2000 @@ -2,6 +2,12 @@ # Automatically generated make config: don't edit # CONFIG_ARM=y +CONFIG_UID16=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y # # System and processor type @@ -12,25 +18,21 @@ # CONFIG_ARCH_EBSA110 is not set # CONFIG_FOOTBRIDGE is not set CONFIG_ARCH_SA1100=y -CONFIG_CPU_SA1100=y CONFIG_SA1100_BRUTUS=y # CONFIG_SA1100_EMPEG is not set # CONFIG_SA1100_ITSY is not set # CONFIG_SA1100_LART is not set # CONFIG_SA1100_PLEB is not set +# CONFIG_SA1100_THINCLIENT is not set # CONFIG_SA1100_VICTOR is not set # CONFIG_SA1100_TIFON is not set +CONFIG_DISCONTIGMEM=y # CONFIG_ARCH_ACORN is not set CONFIG_CPU_32=y # CONFIG_CPU_26 is not set CONFIG_CPU_32v4=y -CONFIG_CPU_SA110=y +CONFIG_CPU_SA1100=y # CONFIG_ISA_DMA is not set - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y # CONFIG_ALIGNMENT_TRAP is not set # @@ -48,10 +50,16 @@ # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_SYSCTL is not set CONFIG_NWFPE=y +CONFIG_KCORE_ELF=y +# CONFIG_KCORE_AOUT is not set CONFIG_BINFMT_AOUT=y CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set # CONFIG_ARTHUR is not set + +# +# Parallel port support +# # CONFIG_PARPORT is not set CONFIG_CMDLINE="" @@ -61,7 +69,6 @@ # 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 @@ -81,7 +88,6 @@ # Please see Documentation/ide.txt for help/info on IDE drives # # CONFIG_BLK_DEV_HD_ONLY is not set -# CONFIG_BLK_CPQ_DA is not set # # Additional Block Devices @@ -91,7 +97,6 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_INITRD=y # CONFIG_BLK_DEV_XD is not set -CONFIG_PARIDE_PARPORT=y # CONFIG_PARIDE is not set # CONFIG_BLK_DEV_IDE_MODES is not set # CONFIG_BLK_DEV_HD is not set @@ -100,9 +105,9 @@ # Character devices # CONFIG_VT=y -CONFIG_VT_CONSOLE=y +# CONFIG_VT_CONSOLE is not set CONFIG_SERIAL_SA1100=y -# CONFIG_SERIAL_SA1100_CONSOLE is not set +CONFIG_SERIAL_SA1100_CONSOLE=y # CONFIG_SERIAL is not set # CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set @@ -110,11 +115,25 @@ CONFIG_UNIX98_PTY_COUNT=32 # +# I2C support +# +# CONFIG_I2C is not set + +# # Mice # # CONFIG_BUSMOUSE is not set # CONFIG_MOUSE is not set + +# +# Joysticks +# +# CONFIG_JOYSTICK is not set # CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# # CONFIG_WATCHDOG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set @@ -123,11 +142,6 @@ # Video For Linux # # CONFIG_VIDEO_DEV is not set - -# -# Joystick support -# -# CONFIG_JOYSTICK is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set @@ -137,9 +151,11 @@ # # CONFIG_FTAPE is not set # CONFIG_DRM is not set +# CONFIG_DRM_TDFX is not set +# CONFIG_AGP is not set # -# USB drivers - not for the faint of heart +# USB support # # CONFIG_USB is not set @@ -148,16 +164,22 @@ # # CONFIG_VGA_CONSOLE is not set CONFIG_FB=y + +# +# Frame-buffer support +# +CONFIG_FB=y CONFIG_DUMMY_CONSOLE=y CONFIG_FB_SA1100=y # CONFIG_FB_MATROX is not set # CONFIG_FB_ATY is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_3DFX is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_FBCON_ADVANCED is not set CONFIG_FBCON_CFB2=y CONFIG_FBCON_CFB4=y CONFIG_FBCON_CFB8=y -CONFIG_FBCON_CFB16=y CONFIG_FBCON_FONTWIDTH8_ONLY=y CONFIG_FBCON_FONTS=y CONFIG_FONT_8x8=y @@ -172,30 +194,35 @@ # CONFIG_SCSI is not set # -# Filesystems +# File systems # # CONFIG_QUOTA is not set # CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set # CONFIG_ADFS_FS 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_CRAMFS is not set # CONFIG_ISO9660_FS is not set # CONFIG_JOLIET is not set -# CONFIG_UDF_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_NTFS_FS is not set # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_DEBUG is not set CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS 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_UFS_FS is not set # @@ -203,8 +230,6 @@ # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y -# CONFIG_SGI_PARTITION is not set -# CONFIG_SUN_PARTITION is not set # CONFIG_NLS is not set # diff -u --recursive --new-file v2.3.99-pre3/linux/arch/arm/def-configs/footbridge linux/arch/arm/def-configs/footbridge --- v2.3.99-pre3/linux/arch/arm/def-configs/footbridge Thu Feb 10 17:11:02 2000 +++ linux/arch/arm/def-configs/footbridge Mon Mar 27 10:46:29 2000 @@ -2,6 +2,7 @@ # Automatically generated make config: don't edit # CONFIG_ARM=y +CONFIG_UID16=y # # Code maturity level options @@ -19,16 +20,18 @@ CONFIG_HOST_FOOTBRIDGE=y # CONFIG_ADDIN_FOOTBRIDGE is not set CONFIG_ARCH_EBSA285=y -# CONFIG_CATS is not set +# CONFIG_ARCH_CATS is not set CONFIG_ARCH_NETWINDER=y +# CONFIG_ARCH_PERSONAL_SERVER is not set # CONFIG_ARCH_ACORN is not set CONFIG_CPU_32=y # CONFIG_CPU_26 is not set CONFIG_CPU_32v4=y CONFIG_CPU_SA110=y CONFIG_PCI=y +CONFIG_PCI_NAMES=y CONFIG_ISA_DMA=y -# CONFIG_ALIGNMENT_TRAP is not set +CONFIG_ALIGNMENT_TRAP=y # # Loadable module support @@ -42,7 +45,7 @@ # CONFIG_NET=y CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_BSD_PROCESS_ACCT=y CONFIG_SYSCTL=y CONFIG_NWFPE=y CONFIG_KCORE_ELF=y @@ -51,10 +54,14 @@ CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set # CONFIG_ARTHUR is not set + +# +# Parallel port support +# CONFIG_PARPORT=y CONFIG_PARPORT_PC=y CONFIG_PARPORT_PC_FIFO=y -# CONFIG_PARPORT_PC_PCMCIA is not set +# CONFIG_PARPORT_PC_SUPERIO is not set # CONFIG_PARPORT_ARC is not set # CONFIG_PARPORT_AMIGA is not set # CONFIG_PARPORT_MFC3 is not set @@ -68,6 +75,11 @@ # CONFIG_LEDS_CPU is not set # +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# # I2O device support # # CONFIG_I2O is not set @@ -87,64 +99,9 @@ # Block devices # # CONFIG_BLK_DEV_FD is not set -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD_IDE is not set -CONFIG_BLK_DEV_IDEDISK=y -CONFIG_IDEDISK_MULTI_MODE=y -# CONFIG_BLK_DEV_IDECD is not set -# CONFIG_BLK_DEV_IDETAPE is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_BLK_DEV_IDESCSI is not set - -# -# IDE chipset support/bugfixes -# -# CONFIG_BLK_DEV_CMD640 is not set -# CONFIG_BLK_DEV_RZ1000 is not set -CONFIG_BLK_DEV_IDEPCI=y -CONFIG_BLK_DEV_IDEDMA_PCI=y -CONFIG_IDEDMA_PCI_AUTO=y -CONFIG_IDEDMA_NEW_DRIVE_LISTINGS=y -CONFIG_IDEDMA_PCI_EXPERIMENTAL=y -CONFIG_BLK_DEV_OFFBOARD=y -# CONFIG_BLK_DEV_AEC6210 is not set -# CONFIG_BLK_DEV_ALI15X3 is not set -# CONFIG_BLK_DEV_CMD646 is not set -CONFIG_BLK_DEV_CY82C693=y -# CONFIG_BLK_DEV_HPT34X is not set -# CONFIG_BLK_DEV_HPT366 is not set -# CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_OPTI621 is not set -CONFIG_BLK_DEV_PDC202XX=y -# CONFIG_PDC202XX_FORCE_BURST_BIT is not set -# CONFIG_PDC202XX_FORCE_MASTER_MODE is not set -# CONFIG_BLK_DEV_TRM290 is not set -CONFIG_BLK_DEV_SL82C105=y -CONFIG_BLK_DEV_IDEDMA=y -CONFIG_IDEDMA_AUTO=y -# CONFIG_IDE_CHIPSETS is not set -# CONFIG_BLK_CPQ_DA is not set - -# -# Additional Block Devices -# -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_MD=y -CONFIG_MD_LINEAR=m -CONFIG_MD_STRIPED=m -CONFIG_MD_MIRRORING=m -CONFIG_MD_RAID5=m -CONFIG_BLK_DEV_RAM=y -# CONFIG_BLK_DEV_INITRD is not set # CONFIG_BLK_DEV_XD is not set -# CONFIG_BLK_DEV_DAC960 is not set -CONFIG_PARIDE_PARPORT=y CONFIG_PARIDE=m +CONFIG_PARIDE_PARPORT=y # # Parallel IDE high-level drivers @@ -172,8 +129,17 @@ CONFIG_PARIDE_KTTI=m CONFIG_PARIDE_ON20=m CONFIG_PARIDE_ON26=m -CONFIG_BLK_DEV_IDE_MODES=y -# CONFIG_BLK_DEV_HD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set + +# +# Additional Block Devices +# +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_NBD=m +# CONFIG_BLK_DEV_MD is not set +CONFIG_BLK_DEV_RAM=y +# CONFIG_BLK_DEV_INITRD is not set # # Character devices @@ -183,7 +149,24 @@ CONFIG_SERIAL=y CONFIG_SERIAL_CONSOLE=y # CONFIG_SERIAL_EXTENDED is not set -# CONFIG_SERIAL_NONSTANDARD is not set +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +# CONFIG_CYCLADES is not set +CONFIG_SERIAL_21285=y +CONFIG_SERIAL_21285_CONSOLE=y +# 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_STALDRV is not set CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTY_COUNT=256 CONFIG_PRINTER=m @@ -191,6 +174,14 @@ # CONFIG_PPDEV is not set # +# I2C support +# +CONFIG_I2C=m +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_CHARDEV is not set + +# # Mice # # CONFIG_BUSMOUSE is not set @@ -214,13 +205,14 @@ CONFIG_SOFT_WATCHDOG=y # CONFIG_PCWATCHDOG is not set # CONFIG_ACQUIRE_WDT is not set -# CONFIG_21285_WATCHDOG is not set +# CONFIG_MIXCOMWD is not set +CONFIG_21285_WATCHDOG=m CONFIG_977_WATCHDOG=m CONFIG_DS1620=y CONFIG_NWBUTTON=y CONFIG_NWBUTTON_REBOOT=y CONFIG_NWFLASH=m -# CONFIG_NVRAM is not set +CONFIG_NVRAM=m CONFIG_RTC=y # @@ -230,25 +222,29 @@ # CONFIG_I2C_PARPORT is not set # -# Radio/Video Adapters +# Radio Adapters # # CONFIG_RADIO_CADET is not set # CONFIG_RADIO_RTRACK is not set # CONFIG_RADIO_RTRACK2 is not set # CONFIG_RADIO_AZTECH is not set -# CONFIG_VIDEO_BT848 is not set # CONFIG_RADIO_GEMTEK is not set -# CONFIG_VIDEO_PMS is not set # CONFIG_RADIO_MIROPCM20 is not set -# CONFIG_VIDEO_BWQCAM is not set -# CONFIG_VIDEO_CQCAM is not set -# CONFIG_VIDEO_SAA5249 is not set # CONFIG_RADIO_SF16FMI is not set -# CONFIG_VIDEO_STRADIS is not set # CONFIG_RADIO_TERRATEC is not set # CONFIG_RADIO_TRUST is not set # CONFIG_RADIO_TYPHOON is not set # CONFIG_RADIO_ZOLTRIX is not set + +# +# Video Adapters +# +# CONFIG_VIDEO_PMS is not set +# CONFIG_VIDEO_BWQCAM is not set +# CONFIG_VIDEO_CQCAM is not set +# CONFIG_VIDEO_SAA5249 is not set +# CONFIG_TUNER_3036 is not set +# CONFIG_VIDEO_STRADIS is not set # CONFIG_VIDEO_ZORAN is not set # CONFIG_VIDEO_BUZ is not set # CONFIG_VIDEO_ZR36120 is not set @@ -263,15 +259,10 @@ # CONFIG_FTAPE is not set # CONFIG_DRM is not set # CONFIG_DRM_TDFX is not set - -# -# PCMCIA character device support -# -# CONFIG_PCMCIA_SERIAL_CS is not set # CONFIG_AGP is not set # -# Support for USB +# USB support # CONFIG_USB=m @@ -279,32 +270,46 @@ # USB Controllers # # CONFIG_USB_UHCI is not set +# CONFIG_USB_UHCI_ALT is not set CONFIG_USB_OHCI=m -CONFIG_USB_OHCI_DEBUG=y -CONFIG_USB_OHCI_HCD=m -CONFIG_USB_OHCI_VROOTHUB=y # # Miscellaneous USB options # -# CONFIG_USB_DEBUG_ISOC is not set -CONFIG_USB_PROC=y -# CONFIG_USB_EZUSB is not set +# CONFIG_USB_DEVICEFS is not set # # USB Devices # -CONFIG_USB_MOUSE=m -# CONFIG_USB_HP_SCANNER is not set -CONFIG_USB_KBD=m -CONFIG_USB_AUDIO=m -CONFIG_USB_ACM=m CONFIG_USB_PRINTER=m +CONFIG_USB_SCANNER=m +CONFIG_USB_AUDIO=m +# CONFIG_USB_ACM is not set # CONFIG_USB_SERIAL is not set # CONFIG_USB_CPIA is not set +# CONFIG_USB_IBMCAM is not set +# CONFIG_USB_OV511 is not set # CONFIG_USB_DC2XX is not set -# CONFIG_USB_SCSI is not set +# CONFIG_USB_STORAGE is not set # CONFIG_USB_USS720 is not set +# CONFIG_USB_DABUSB is not set +# CONFIG_USB_PLUSB is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_DSBR is not set + +# +# USB HID +# +# CONFIG_USB_HID is not set +CONFIG_USB_KBD=m +CONFIG_USB_MOUSE=m +# CONFIG_USB_WACOM is not set +# CONFIG_USB_WMFORCE 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 # # Console drivers @@ -342,10 +347,11 @@ # CONFIG_FBCON_MAC is not set # CONFIG_FBCON_VGA_PLANES is not set CONFIG_FBCON_VGA=y +# CONFIG_FBCON_HGA is not set # CONFIG_FBCON_FONTWIDTH8_ONLY is not set CONFIG_FBCON_FONTS=y -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y +# CONFIG_FONT_8x8 is not set +# CONFIG_FONT_8x16 is not set # CONFIG_FONT_SUN8x16 is not set # CONFIG_FONT_SUN12x22 is not set # CONFIG_FONT_6x11 is not set @@ -356,7 +362,7 @@ # Networking options # CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set +CONFIG_PACKET_MMAP=y # CONFIG_NETLINK is not set # CONFIG_NETFILTER is not set # CONFIG_FILTER is not set @@ -371,12 +377,12 @@ # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set CONFIG_IP_ALIAS=y -# CONFIG_SYN_COOKIES is not set +CONFIG_SYN_COOKIES=y # # (it is safe to leave these untouched) # -CONFIG_SKB_LARGE=y +# CONFIG_SKB_LARGE is not set # CONFIG_IPV6 is not set # CONFIG_KHTTPD is not set # CONFIG_ATM is not set @@ -409,7 +415,46 @@ # # IrDA (infrared) support # -# CONFIG_IRDA is not set +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRCOMM=m +CONFIG_IRDA_ULTRA=y +CONFIG_IRDA_OPTIONS=y + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +# CONFIG_IRDA_DEBUG is not set +# CONFIG_IRDA_COMPRESSION is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +# CONFIG_IRTTY_SIR is not set +# CONFIG_IRPORT_SIR is not set + +# +# FIR device drivers +# +# CONFIG_NSC_FIR is not set +CONFIG_WINBOND_FIR=m +# CONFIG_TOSHIBA_FIR is not set +# CONFIG_SMC_IRCC_FIR is not set + +# +# Dongle support +# +# CONFIG_DONGLE is not set # # Network device support @@ -421,6 +466,7 @@ # # CONFIG_ARCNET is not set # CONFIG_DUMMY is not set +# CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_NET_SB1000 is not set @@ -440,30 +486,30 @@ # CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_RTL8139 is not set -# CONFIG_DM9102 is not set # CONFIG_AT1700 is not set # CONFIG_DEPCA is not set # CONFIG_NET_ISA is not set -CONFIG_NET_EISA=y +CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set # CONFIG_ADAPTEC_STARFIRE is not set # CONFIG_AC3200 is not set # CONFIG_APRICOT is not set # CONFIG_CS89x0 is not set # CONFIG_DE4X5 is not set -CONFIG_DEC_ELCP=m +CONFIG_TULIP=m # CONFIG_DGRS is not set -# CONFIG_EEXPRESS_PRO100 is not set +# CONFIG_DM9102 is not set +# CONFIG_EEPRO100 is not set # CONFIG_LNE390 is not set # CONFIG_NE3210 is not set CONFIG_NE2K_PCI=y +# CONFIG_RTL8129 is not set +# CONFIG_8139TOO is not set # CONFIG_SIS900 is not set # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set # CONFIG_ES3210 is not set # CONFIG_EPIC100 is not set -# CONFIG_ZNET is not set # CONFIG_NET_POCKET is not set # @@ -491,7 +537,7 @@ # CONFIG_NET_RADIO is not set # -# Token Ring driver support +# Token Ring devices # # CONFIG_TR is not set # CONFIG_NET_FC is not set @@ -504,9 +550,70 @@ # CONFIG_WAN is not set # -# PCMCIA network device support +# ATA/IDE/MFM/RLL support +# +CONFIG_IDE=y + +# +# IDE, ATA and ATAPI Block devices +# +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD_IDE is not set +# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +# CONFIG_BLK_DEV_IDECS is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set + +# +# IDE chipset support/bugfixes # -# CONFIG_NET_PCMCIA is not set +# CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_BLK_DEV_CMD640_ENHANCED is not set +# CONFIG_BLK_DEV_ISAPNP is not set +# CONFIG_BLK_DEV_RZ1000 is not set +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +CONFIG_BLK_DEV_IDEDMA_PCI=y +CONFIG_BLK_DEV_OFFBOARD=y +CONFIG_IDEDMA_PCI_AUTO=y +CONFIG_BLK_DEV_IDEDMA=y +CONFIG_IDEDMA_PCI_EXPERIMENTAL=y +# CONFIG_IDEDMA_PCI_WIP is not set +# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set +# CONFIG_BLK_DEV_AEC6210 is not set +# CONFIG_AEC6210_TUNING is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD7409 is not set +# CONFIG_AMD7409_OVERRIDE is not set +# CONFIG_BLK_DEV_CMD64X is not set +# CONFIG_CMD64X_RAID is not set +CONFIG_BLK_DEV_CY82C693=y +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_HPT34X_AUTODMA is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_HPT366_FIP is not set +# CONFIG_HPT366_MODE3 is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_PDC202XX=y +# CONFIG_PDC202XX_BURST is not set +# CONFIG_PDC202XX_MASTER is not set +# CONFIG_BLK_DEV_SIS5513 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +CONFIG_BLK_DEV_SL82C105=y +# CONFIG_IDE_CHIPSETS is not set +CONFIG_IDEDMA_AUTO=y +CONFIG_BLK_DEV_IDE_MODES=y # # SCSI support @@ -527,8 +634,12 @@ # CONFIG_SOUND_MSNDCLAS is not set # CONFIG_SOUND_MSNDPIN is not set CONFIG_SOUND_OSS=m +# CONFIG_SOUND_TRACEINIT is not set +# CONFIG_SOUND_DMAP is not set # CONFIG_SOUND_AD1816 is not set # CONFIG_SOUND_SGALAXY is not set +CONFIG_SOUND_ADLIB=m +# CONFIG_SOUND_ACI_MIXER is not set # CONFIG_SOUND_CS4232 is not set # CONFIG_SOUND_SSCAPE is not set # CONFIG_SOUND_GUS is not set @@ -539,9 +650,11 @@ # CONFIG_SOUND_NM256 is not set # CONFIG_SOUND_MAD16 is not set # CONFIG_SOUND_PAS is not set +# CONFIG_PAS_JOYSTICK is not set # CONFIG_SOUND_PSS is not set # CONFIG_SOUND_SOFTOSS is not set CONFIG_SOUND_SB=m +# CONFIG_SOUND_AWE32_SYNTH is not set # CONFIG_SOUND_WAVEFRONT is not set # CONFIG_SOUND_MAUI is not set # CONFIG_SOUND_VIA82CXXX is not set @@ -549,24 +662,18 @@ # CONFIG_SOUND_OPL3SA1 is not set # CONFIG_SOUND_OPL3SA2 is not set # CONFIG_SOUND_UART6850 is not set +# CONFIG_SOUND_AEDSP16 is not set # CONFIG_SOUND_VIDC is not set CONFIG_SOUND_WAVEARTIST=m -CONFIG_WAVEARTIST_BASE=250 -CONFIG_WAVEARTIST_IRQ=12 -CONFIG_WAVEARTIST_DMA=3 -CONFIG_WAVEARTIST_DMA2=7 # -# Additional low level sound drivers -# -# CONFIG_LOWLEVEL_SOUND is not set - -# -# Filesystems +# File systems # # CONFIG_QUOTA is not set CONFIG_AUTOFS_FS=y -CONFIG_ADFS_FS=y +# CONFIG_AUTOFS4_FS is not set +CONFIG_ADFS_FS=m +# 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 @@ -575,12 +682,15 @@ # CONFIG_UMSDOS_FS is not set CONFIG_VFAT_FS=m # CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set CONFIG_ISO9660_FS=m CONFIG_JOLIET=y # CONFIG_MINIX_FS is not set # CONFIG_NTFS_FS is not set # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_DEBUG is not set CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set # CONFIG_ROMFS_FS is not set @@ -606,7 +716,14 @@ # Partition Types # CONFIG_PARTITION_ADVANCED=y +CONFIG_ACORN_PARTITION=y +# CONFIG_ACORN_PARTITION_ICS is not set +CONFIG_ACORN_PARTITION_ADFS=y +# CONFIG_ACORN_PARTITION_POWERTEC is not set +# CONFIG_ACORN_PARTITION_RISCIX 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 @@ -614,13 +731,6 @@ # CONFIG_UNIXWARE_DISKLABEL is not set # CONFIG_SGI_PARTITION is not set # CONFIG_SUN_PARTITION is not set -# CONFIG_AMIGA_PARTITION is not set -# CONFIG_ATARI_PARTITION is not set -CONFIG_ACORN_PARTITION=y -CONFIG_ACORN_PARTITION_ADFS=y -# CONFIG_ACORN_PARTITION_ICS is not set -# CONFIG_ACORN_PARTITION_POWERTEC is not set -# CONFIG_ACORN_PARTITION_RISCIX is not set CONFIG_NLS=y # diff -u --recursive --new-file v2.3.99-pre3/linux/arch/arm/def-configs/thinclient linux/arch/arm/def-configs/thinclient --- v2.3.99-pre3/linux/arch/arm/def-configs/thinclient Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/def-configs/thinclient Mon Mar 27 10:46:29 2000 @@ -0,0 +1,379 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_ARM=y +CONFIG_UID16=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# System and processor type +# +# CONFIG_ARCH_ARC is not set +# CONFIG_ARCH_A5K is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_FOOTBRIDGE is not set +CONFIG_ARCH_SA1100=y +# CONFIG_SA1100_BRUTUS is not set +# CONFIG_SA1100_EMPEG is not set +# CONFIG_SA1100_ITSY is not set +# CONFIG_SA1100_LART is not set +# CONFIG_SA1100_PLEB is not set +CONFIG_SA1100_THINCLIENT=y +# CONFIG_SA1100_VICTOR is not set +# CONFIG_SA1100_TIFON is not set +CONFIG_DISCONTIGMEM=y +# CONFIG_ARCH_ACORN is not set +CONFIG_CPU_32=y +# CONFIG_CPU_26 is not set +CONFIG_CPU_32v4=y +CONFIG_CPU_SA1100=y +# CONFIG_ISA_DMA is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +# CONFIG_KMOD is not set + +# +# General setup +# +CONFIG_NET=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_NWFPE=y +CONFIG_KCORE_ELF=y +# CONFIG_KCORE_AOUT is not set +CONFIG_BINFMT_AOUT=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set +# CONFIG_PARPORT is not set +CONFIG_CMDLINE="root=nfs" + +# +# 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 + +# +# Plug and Play configuration +# +# CONFIG_PNP is not set +# CONFIG_ISAPNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_IDE is not set + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD_ONLY is not set + +# +# Additional Block Devices +# +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_MD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_INITRD=y +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_HD is not set + +# +# Character devices +# +CONFIG_VT=y +# CONFIG_VT_CONSOLE is not set +CONFIG_SERIAL_SA1100=y +CONFIG_SERIAL_SA1100_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=32 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set + +# +# Joysticks +# +# CONFIG_JOYSTICK is not set +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_EFI_RTC is not set + +# +# Video For Linux +# +# CONFIG_VIDEO_DEV 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_DRM is not set +# CONFIG_DRM_TDFX is not set +# CONFIG_AGP is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# Misc devices +# + +# +# Console drivers +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_FB=y + +# +# Frame-buffer support +# +CONFIG_FB=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_FB_SA1100=y +# CONFIG_FB_MATROX is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FBCON_ADVANCED is not set +CONFIG_FBCON_CFB2=y +CONFIG_FBCON_CFB4=y +CONFIG_FBCON_CFB8=y +CONFIG_FBCON_FONTWIDTH8_ONLY=y +CONFIG_FBCON_FONTS=y +# CONFIG_FONT_8x8 is not set +CONFIG_FONT_8x16=y +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 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_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_IP_ROUTER is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_ALIAS is not set +# CONFIG_SYN_COOKIES is not set + +# +# (it is safe to leave these untouched) +# +CONFIG_SKB_LARGE=y +# 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_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_BRIDGE is not set +# CONFIG_LLC 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 + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA 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_NET_SB1000 is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_ARM_AM79C961A is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +CONFIG_NET_VENDOR_SMC=y +# CONFIG_WD80x3 is not set +# CONFIG_ULTRA is not set +# CONFIG_ULTRA32 is not set +CONFIG_SMC9194=y +# 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 + +# +# Ethernet (1000 Mbit) +# +# CONFIG_YELLOWFIN is not set +# CONFIG_ACENIC 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 driver support +# +# 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 + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_ADFS_FS 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_CRAMFS is not set +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_MINIX_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_DEBUG is not set +CONFIG_DEVPTS_FS=y +# CONFIG_QNX4FS_FS 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_UFS_FS is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_INFO=y +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_LL is not set diff -u --recursive --new-file v2.3.99-pre3/linux/arch/arm/defconfig linux/arch/arm/defconfig --- v2.3.99-pre3/linux/arch/arm/defconfig Mon Mar 27 08:08:21 2000 +++ linux/arch/arm/defconfig Mon Mar 27 09:38:47 2000 @@ -32,6 +32,8 @@ CONFIG_PCI_NAMES=y CONFIG_ISA=y CONFIG_ISA_DMA=y +# CONFIG_SBUS is not set +# CONFIG_PCMCIA is not set # CONFIG_ALIGNMENT_TRAP is not set # @@ -537,6 +539,7 @@ # CONFIG_BLK_DEV_AEC6210 is not set # CONFIG_AEC6210_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_CMD64X is not set diff -u --recursive --new-file v2.3.99-pre3/linux/arch/arm/kernel/Makefile linux/arch/arm/kernel/Makefile --- v2.3.99-pre3/linux/arch/arm/kernel/Makefile Tue Mar 14 19:10:38 2000 +++ linux/arch/arm/kernel/Makefile Thu Mar 30 16:56:04 2000 @@ -59,12 +59,12 @@ all: kernel.o $(HEAD_OBJ) init_task.o $(HEAD_OBJ): $(HEAD_OBJ:.o=.S) - $(CC) -D__ASSEMBLY__ $(AFLAGS) -DTEXTADDR=$(TEXTADDR) -traditional -c $(HEAD_OBJ:.o=.S) -o $@ + $(CC) $(AFLAGS) -DTEXTADDR=$(TEXTADDR) -traditional -c $(HEAD_OBJ:.o=.S) -o $@ include $(TOPDIR)/Rules.make .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) $(AFLAGS_$@) -c -o $*.o $< + $(CC) $(AFLAGS) $(AFLAGS_$@) -c -o $*.o $< # Spell out some dependencies that `make dep' doesn't spot entry-armv.o: calls.S ../lib/constants.h diff -u --recursive --new-file v2.3.99-pre3/linux/arch/arm/kernel/arch.c linux/arch/arm/kernel/arch.c --- v2.3.99-pre3/linux/arch/arm/kernel/arch.c Sun Mar 19 18:35:30 2000 +++ linux/arch/arm/kernel/arch.c Mon Mar 27 10:46:29 2000 @@ -23,6 +23,9 @@ unsigned int number_mfm_drives; #endif +extern void setup_initrd(unsigned int start, unsigned int size); +extern void setup_ramdisk(int doload, int prompt, int start, unsigned int rd_sz); + /* * Architecture specific fixups. This is where any * parameters in the params struct are fixed up, or @@ -157,11 +160,15 @@ #if defined(CONFIG_SA1100_BRUTUS) ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); setup_ramdisk( 1, 0, 0, 8192 ); - setup_initrd( __phys_to_virt(0xd8000000), 0x00400000 ); + setup_initrd( __phys_to_virt(0xd8000000), 3*1024*1024 ); #elif defined(CONFIG_SA1100_EMPEG) ROOT_DEV = MKDEV( 3, 1 ); /* /dev/hda1 */ setup_ramdisk( 1, 0, 0, 4096 ); setup_initrd( 0xd0000000+((1024-320)*1024), (320*1024) ); +#elif defined(CONFIG_SA1100_THINCLIENT) + ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); + setup_ramdisk( 1, 0, 0, 8192 ); + setup_initrd( __phys_to_virt(0xc0800000), 4*1024*1024 ); #elif defined(CONFIG_SA1100_TIFON) ROOT_DEV = MKDEV(UNNAMED_MAJOR, 0); setup_ramdisk(1, 0, 0, 4096); @@ -198,7 +205,7 @@ "EBSA110", /* RMK */ 0x00000400, NO_VIDEO, - 1, 0, 1, 1, 1, + 1, 0, 1, 0, 1, NULL }, #endif diff -u --recursive --new-file v2.3.99-pre3/linux/arch/arm/kernel/armksyms.c linux/arch/arm/kernel/armksyms.c --- v2.3.99-pre3/linux/arch/arm/kernel/armksyms.c Tue Mar 14 19:10:38 2000 +++ linux/arch/arm/kernel/armksyms.c Mon Mar 27 10:46:29 2000 @@ -190,6 +190,8 @@ EXPORT_SYMBOL(uaccess_user); #endif + /* consistent area handling */ +EXPORT_SYMBOL(pci_alloc_consistent); EXPORT_SYMBOL(consistent_alloc); EXPORT_SYMBOL(consistent_free); EXPORT_SYMBOL(consistent_sync); diff -u --recursive --new-file v2.3.99-pre3/linux/arch/arm/kernel/bios32.c linux/arch/arm/kernel/bios32.c --- v2.3.99-pre3/linux/arch/arm/kernel/bios32.c Sun Mar 19 18:35:30 2000 +++ linux/arch/arm/kernel/bios32.c Mon Mar 27 10:46:29 2000 @@ -504,6 +504,10 @@ { } +void pcibios_set_master(struct pci_dev *dev) +{ +} + int pcibios_enable_device(struct pci_dev *dev) { u16 cmd, old_cmd; diff -u --recursive --new-file v2.3.99-pre3/linux/arch/arm/kernel/entry-armv.S linux/arch/arm/kernel/entry-armv.S --- v2.3.99-pre3/linux/arch/arm/kernel/entry-armv.S Thu Mar 2 14:36:22 2000 +++ linux/arch/arm/kernel/entry-armv.S Mon Mar 27 10:46:29 2000 @@ -201,6 +201,38 @@ .byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2 .endm +#elif defined(CONFIG_ARCH_SHARK) + + .macro disable_fiq + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base + mov r4, #0xe0000000 + orr r4, r4, #0x20 + + mov \irqstat, #0x0C + strb \irqstat, [r4] @outb(0x0C, 0x20) /* Poll command */ + ldrb \irqnr, [r4] @irq = inb(0x20) & 7 + and \irqstat, \irqnr, #0x80 + teq \irqstat, #0 + beq 43f + and \irqnr, \irqnr, #7 + teq \irqnr, #2 + bne 44f +43: mov \irqstat, #0x0C + strb \irqstat, [r4, #0x80] @outb(0x0C, 0xA0) /* Poll command */ + ldrb \irqnr, [r4, #0x80] @irq = (inb(0xA0) & 7) + 8 + and \irqstat, \irqnr, #0x80 + teq \irqstat, #0 + beq 44f + and \irqnr, \irqnr, #7 + add \irqnr, \irqnr, #8 +44: teq \irqstat, #0 + .endm + + .macro irq_prio_table + .endm + #elif defined(CONFIG_HOST_FOOTBRIDGE) || defined(CONFIG_ADDIN_FOOTBRIDGE) #include @@ -295,9 +327,40 @@ .endm .macro get_irqnr_and_base, irqnr, irqstat, base - ldr r4, =0xffe00000 - ldr \irqstat, [r4, #0x180] @ get interrupts + ldr \irqstat, =INTCONT_BASE + ldr \base, =soft_irq_mask + ldr \irqstat, [\irqstat] @ get interrupts + ldr \base, [\base] + mov \irqnr, #0 + and \irqstat, \irqstat, \base @ mask out disabled ones +1001: tst \irqstat, #1 + addeq \irqnr, \irqnr, #1 + moveq \irqstat, \irqstat, lsr #1 + tsteq \irqnr, #32 + beq 1001b + teq \irqnr, #32 + .endm + + .macro irq_prio_table + .ltorg + .bss +ENTRY(soft_irq_mask) + .word 0 + .text + .endm + +#elif defined(CONFIG_ARCH_TBOX) + + .macro disable_fiq + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base + ldr \irqstat, =0xffff7000 + ldr \irqstat, [\irqstat] @ get interrupts + ldr \base, =soft_irq_mask + ldr \base, [\base] mov \irqnr, #0 + and \irqstat, \irqstat, \base @ mask out disabled ones 1001: tst \irqstat, #1 addeq \irqnr, \irqnr, #1 moveq \irqstat, \irqstat, lsr #1 @@ -307,6 +370,11 @@ .endm .macro irq_prio_table + .ltorg + .bss +ENTRY(soft_irq_mask) + .word 0 + .text .endm #elif defined(CONFIG_ARCH_SA1100) diff -u --recursive --new-file v2.3.99-pre3/linux/arch/arm/kernel/process.c linux/arch/arm/kernel/process.c --- v2.3.99-pre3/linux/arch/arm/kernel/process.c Sun Mar 19 18:35:30 2000 +++ linux/arch/arm/kernel/process.c Mon Mar 27 10:46:29 2000 @@ -28,15 +28,24 @@ #include #include -#include #include +/* + * Values for cpu_do_idle() + */ +#define IDLE_WAIT_SLOW 0 +#define IDLE_WAIT_FAST 1 +#define IDLE_CLOCK_SLOW 2 +#define IDLE_CLOCK_FAST 3 + extern char *processor_modes[]; extern void setup_mm_for_reboot(char mode); asmlinkage void ret_from_sys_call(void) __asm__("ret_from_sys_call"); -static int hlt_counter; +static volatile int hlt_counter; + +#include void disable_hlt(void) { @@ -64,7 +73,9 @@ __setup("hlt", hlt_setup); /* - * The idle loop on an ARM... + * The idle thread. We try to conserve power, while trying to keep + * overall latency low. The architecture specific idle is passed + * a value to indicate the level of "idleness" of the system. */ void cpu_idle(void) { @@ -72,15 +83,13 @@ init_idle(); current->priority = 0; current->counter = -100; + while (1) { - if (!hlt_counter) - arch_do_idle(); - if (current->need_resched) { - schedule(); + arch_idle(); + schedule(); #ifndef CONFIG_NO_PGT_CACHE - check_pgt_cache(); + check_pgt_cache(); #endif - } } } @@ -89,7 +98,7 @@ int __init reboot_setup(char *str) { reboot_mode = str[0]; - return 0; + return 1; } __setup("reboot=", reboot_setup); diff -u --recursive --new-file v2.3.99-pre3/linux/arch/arm/kernel/setup.c linux/arch/arm/kernel/setup.c --- v2.3.99-pre3/linux/arch/arm/kernel/setup.c Tue Mar 14 19:10:39 2000 +++ linux/arch/arm/kernel/setup.c Mon Mar 27 10:46:29 2000 @@ -228,7 +228,7 @@ *cmdline_p = command_line; } -static void __init +void __init setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz) { #ifdef CONFIG_BLK_DEV_RAM @@ -246,7 +246,7 @@ /* * initial ram disk */ -static void __init setup_initrd(unsigned int start, unsigned int size) +void __init setup_initrd(unsigned int start, unsigned int size) { #ifdef CONFIG_BLK_DEV_INITRD if (start == 0) diff -u --recursive --new-file v2.3.99-pre3/linux/arch/arm/lib/Makefile linux/arch/arm/lib/Makefile --- v2.3.99-pre3/linux/arch/arm/lib/Makefile Tue Mar 14 19:10:39 2000 +++ linux/arch/arm/lib/Makefile Thu Mar 30 16:56:04 2000 @@ -37,7 +37,7 @@ include $(TOPDIR)/Rules.make .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c -o $*.o $< + $(CC) $(AFLAGS) -traditional -c -o $*.o $< constants.h: getconsdata.o extractconstants.pl $(PERL) extractconstants.pl $(OBJDUMP) > $@ diff -u --recursive --new-file v2.3.99-pre3/linux/arch/arm/mm/Makefile linux/arch/arm/mm/Makefile --- v2.3.99-pre3/linux/arch/arm/mm/Makefile Sun Feb 13 19:29:03 2000 +++ linux/arch/arm/mm/Makefile Thu Mar 30 16:56:04 2000 @@ -34,7 +34,7 @@ include $(TOPDIR)/Rules.make .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) $(AFLAGS_$@) -traditional -c -o $*.o $< + $(CC) $(AFLAGS) $(AFLAGS_$@) -traditional -c -o $*.o $< # Special dependencies fault-armv.o: fault-common.c diff -u --recursive --new-file v2.3.99-pre3/linux/arch/arm/mm/mm-armv.c linux/arch/arm/mm/mm-armv.c --- v2.3.99-pre3/linux/arch/arm/mm/mm-armv.c Sun Mar 19 18:35:30 2000 +++ linux/arch/arm/mm/mm-armv.c Mon Mar 27 10:46:29 2000 @@ -293,9 +293,14 @@ */ void setup_mm_for_reboot(char mode) { - pgd_t *pgd = current->mm->pgd; + pgd_t *pgd; pmd_t pmd; int i; + + if (current->mm && current->mm->pgd) + pgd = current->mm->pgd; + else + pgd = init_mm.pgd; for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++) { pmd_val(pmd) = (i << PGDIR_SHIFT) | diff -u --recursive --new-file v2.3.99-pre3/linux/arch/arm/mm/mm-sa1100.c linux/arch/arm/mm/mm-sa1100.c --- v2.3.99-pre3/linux/arch/arm/mm/mm-sa1100.c Fri Jan 21 18:19:16 2000 +++ linux/arch/arm/mm/mm-sa1100.c Mon Mar 27 10:46:29 2000 @@ -36,10 +36,8 @@ #if defined(CONFIG_SA1100_BRUTUS) { 0xc0000000, 0x00400000 }, /* 4MB */ { 0xc8000000, 0x00400000 }, /* 4MB */ -#if 0 /* only two banks until the bootmem stuff is fixed... */ { 0xd0000000, 0x00400000 }, /* 4MB */ { 0xd8000000, 0x00400000 } /* 4MB */ -#endif #elif defined(CONFIG_SA1100_EMPEG) { 0xc0000000, 0x00400000 }, /* 4MB */ { 0xc8000000, 0x00400000 } /* 4MB */ @@ -50,6 +48,8 @@ { 0xc9000000, 0x00800000 } /* 8MB */ #elif defined(CONFIG_SA1100_VICTOR) { 0xc0000000, 0x00400000 } /* 4MB */ +#elif defined(CONFIG_SA1100_THINCLIENT) + { 0xc0000000, 0x01000000 } /* 16MB */ #elif defined(CONFIG_SA1100_TIFON) { 0xc0000000, 0x01000000 }, /* 16MB */ { 0xc8000000, 0x01000000 } /* 16MB */ @@ -67,12 +67,24 @@ { 0xd0000000, 0x00000000, 0x00200000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash */ #elif defined(CONFIG_SA1100_EMPEG) { EMPEG_FLASHBASE, 0x00000000, 0x00200000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash */ +#elif defined(CONFIG_SA1100_THINCLIENT) +#if 1 + /* ThinClient: only one of those... */ +// { 0xd0000000, 0x00000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 when JP1 2-4 */ + { 0xd0000000, 0x08000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 when JP1 3-4 */ +#else + /* GraphicsClient: */ + { 0xd0000000, 0x08000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 */ + { 0xd0800000, 0x18000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 3 */ +#endif #elif defined(CONFIG_SA1100_TIFON) { 0xd0000000, 0x00000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 */ { 0xd0800000, 0x08000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 2 */ #endif -#ifdef CONFIG_SA1101 +#if defined( CONFIG_SA1101 ) { 0xdc000000, SA1101_BASE, 0x00400000, DOMAIN_IO, 1, 1, 0, 0 }, /* SA1101 */ +#elif defined( CONFIG_SA1100_THINCLIENT ) + { 0xdc000000, 0x10000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* CPLD */ #endif { 0xe0000000, 0x20000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA0 IO */ { 0xe4000000, 0x30000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA1 IO */ diff -u --recursive --new-file v2.3.99-pre3/linux/arch/arm/mm/mm-shark.c linux/arch/arm/mm/mm-shark.c --- v2.3.99-pre3/linux/arch/arm/mm/mm-shark.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/mm/mm-shark.c Mon Mar 27 10:46:29 2000 @@ -0,0 +1,25 @@ +/* + * arch/arm/mm/mm-shark.c + * + * by Alexander.Schulz@stud.uni-karlsruhe.de + */ +#include +#include +#include + +#include +#include +#include + +#include "map.h" + +struct map_desc io_desc[] __initdata = { + { IO_BASE , IO_START , IO_SIZE , DOMAIN_IO, 0, 1, 0, 0 }, + { FB_BASE , FB_START , FB_SIZE , DOMAIN_IO, 0, 1, 0, 0 }, + { FBREG_BASE , FBREG_START , FBREG_SIZE , DOMAIN_IO, 0, 1, 0, 0 } +}; + + +#define SIZEOFMAP (sizeof(io_desc) / sizeof(io_desc[0])) + +unsigned int __initdata io_desc_size = SIZEOFMAP; diff -u --recursive --new-file v2.3.99-pre3/linux/arch/arm/mm/proc-sa110.S linux/arch/arm/mm/proc-sa110.S --- v2.3.99-pre3/linux/arch/arm/mm/proc-sa110.S Sun Mar 19 18:35:30 2000 +++ linux/arch/arm/mm/proc-sa110.S Mon Mar 27 10:46:29 2000 @@ -435,17 +435,35 @@ ldmfd sp!, {r1, pc} .align 5 +idle: mcr p15, 0, r0, c15, c8, 2 @ Wait for interrupt + mov r0, r0 @ safety + mov pc, lr +/* + * Function: *_do_idle + * Params : r0 = call type: + * 0 = slow idle + * 1 = fast idle + * 2 = switch to slow processor clock + * 3 = switch to fast processor clock + */ ENTRY(cpu_sa110_do_idle) ENTRY(cpu_sa1100_do_idle) - mov r0, #0 - mcr p15, 0, r0, c15, c2, 2 @ Disable clock switching - ldr r1, =FLUSH_BASE+FLUSH_OFFSET*2 @ load from uncacheable loc - ldr r1, [r1, #0] - b 1f + mov ip, #0 + cmp r0, #4 + addcc pc, pc, r0, lsl #2 + mov pc, lr - .align 5 -1: mcr p15, 0, r0, c15, c8, 2 @ Wait for interrupt - mcr p15, 0, r0, c15, c1, 2 @ Enable clock switching + b idle + b idle + b slow_clock + b fast_clock + +fast_clock: mcr p15, 0, ip, c15, c1, 2 @ enable clock switching + mov pc, lr + +slow_clock: mcr p15, 0, ip, c15, c2, 2 @ disable clock switching + ldr r1, =UNCACHEABLE_ADDR @ load from uncacheable loc + ldr r1, [r1, #0] @ force switch to MCLK mov pc, lr /* diff -u --recursive --new-file v2.3.99-pre3/linux/arch/i386/boot/compressed/head.S linux/arch/i386/boot/compressed/head.S --- v2.3.99-pre3/linux/arch/i386/boot/compressed/head.S Sun Mar 19 18:35:30 2000 +++ linux/arch/i386/boot/compressed/head.S Tue Mar 28 15:33:49 2000 @@ -23,7 +23,6 @@ */ .text -#define __ASSEMBLY__ #include #include diff -u --recursive --new-file v2.3.99-pre3/linux/arch/i386/config.in linux/arch/i386/config.in --- v2.3.99-pre3/linux/arch/i386/config.in Mon Mar 27 08:08:21 2000 +++ linux/arch/i386/config.in Tue Apr 4 22:42:30 2000 @@ -6,6 +6,7 @@ define_bool CONFIG_X86 y define_bool CONFIG_ISA y +define_bool CONFIG_SBUS n define_bool CONFIG_UID16 y @@ -43,11 +44,17 @@ define_bool CONFIG_X86_USE_STRING_486 y define_bool CONFIG_X86_ALIGNMENT_16 y fi -if [ "$CONFIG_M586TSC" = "y" -o "$CONFIG_MK6" = "y" ]; then +if [ "$CONFIG_M586TSC" = "y" ]; then define_bool CONFIG_X86_USE_STRING_486 y define_bool CONFIG_X86_ALIGNMENT_16 y define_bool CONFIG_X86_TSC y fi +if [ "$CONFIG_MK6" = "y" ]; then + define_bool CONFIG_X86_ALIGNMENT_16 y + define_bool CONFIG_X86_TSC y + define_bool CONFIG_X86_USE_3DNOW y + define_bool CONFIG_X86_USE_PPRO_CHECKSUM y +fi if [ "$CONFIG_M686" = "y" ]; then define_bool CONFIG_X86_TSC y define_bool CONFIG_X86_GOOD_APIC y @@ -136,6 +143,8 @@ if [ "$CONFIG_HOTPLUG" = "y" ] ; then source drivers/pcmcia/Config.in +else + define_bool CONFIG_PCMCIA n fi bool 'System V IPC' CONFIG_SYSVIPC @@ -252,7 +261,6 @@ source drivers/char/Config.in -source drivers/usb/Config.in #source drivers/misc/Config.in @@ -278,6 +286,8 @@ source drivers/sound/Config.in fi endmenu + +source drivers/usb/Config.in mainmenu_option next_comment comment 'Kernel hacking' diff -u --recursive --new-file v2.3.99-pre3/linux/arch/i386/defconfig linux/arch/i386/defconfig --- v2.3.99-pre3/linux/arch/i386/defconfig Mon Mar 27 08:08:21 2000 +++ linux/arch/i386/defconfig Tue Apr 11 11:04:35 2000 @@ -3,6 +3,7 @@ # CONFIG_X86=y CONFIG_ISA=y +# CONFIG_SBUS is not set CONFIG_UID16=y # @@ -22,11 +23,14 @@ # CONFIG_MK7 is not set CONFIG_X86_WP_WORKS_OK=y CONFIG_X86_INVLPG=y +CONFIG_X86_CMPXCHG=y CONFIG_X86_BSWAP=y CONFIG_X86_POPAD_OK=y +CONFIG_X86_L1_CACHE_BYTES=32 CONFIG_X86_TSC=y CONFIG_X86_GOOD_APIC=y CONFIG_X86_PGE=y +CONFIG_X86_USE_PPRO_CHECKSUM=y # CONFIG_MICROCODE is not set CONFIG_NOHIGHMEM=y # CONFIG_HIGHMEM4G is not set @@ -104,7 +108,10 @@ # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_STRIPED is not set # CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set # # Networking options @@ -185,6 +192,7 @@ # CONFIG_BLK_DEV_AEC6210 is not set # CONFIG_AEC6210_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_CMD64X is not set @@ -248,6 +256,7 @@ # CONFIG_SCSI_AM53C974 is not set # CONFIG_SCSI_MEGARAID is not set # CONFIG_SCSI_BUSLOGIC 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 @@ -375,6 +384,7 @@ # CONFIG_PCMCIA_SMC91C92 is not set # CONFIG_PCMCIA_XIRC2PS is not set # CONFIG_ARCNET_COM20020_CS is not set +# CONFIG_PCMCIA_IBMTR is not set # CONFIG_PCMCIA_3C575 is not set # CONFIG_PCMCIA_XIRTULIP is not set CONFIG_NET_PCMCIA_RADIO=y @@ -467,17 +477,13 @@ # CONFIG_PCMCIA_SERIAL_CB is not set # -# USB support -# -# CONFIG_USB is not set - -# # File systems # # CONFIG_QUOTA is not set # CONFIG_AUTOFS_FS is not set CONFIG_AUTOFS4_FS=y # 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 @@ -487,27 +493,34 @@ # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set # CONFIG_CRAMFS is not set +# CONFIG_RAMFS is not set CONFIG_ISO9660_FS=y # 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_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 is not set # CONFIG_ROOT_NFS is not set CONFIG_NFSD=y # CONFIG_NFSD_V3 is not set @@ -515,6 +528,16 @@ 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_MOUNT_SUBDIR is not set +# CONFIG_NCPFS_NDS_DOMAINS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set # # Partition Types @@ -533,6 +556,11 @@ # Sound # # CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set # # Kernel hacking diff -u --recursive --new-file v2.3.99-pre3/linux/arch/i386/kernel/Makefile linux/arch/i386/kernel/Makefile --- v2.3.99-pre3/linux/arch/i386/kernel/Makefile Tue Mar 14 19:10:39 2000 +++ linux/arch/i386/kernel/Makefile Thu Mar 30 16:56:04 2000 @@ -8,7 +8,7 @@ # Note 2! The CFLAGS definitions are now in the main makefile... .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o + $(CC) $(AFLAGS) -traditional -c $< -o $*.o all: kernel.o head.o init_task.o diff -u --recursive --new-file v2.3.99-pre3/linux/arch/i386/kernel/acpi.c linux/arch/i386/kernel/acpi.c --- v2.3.99-pre3/linux/arch/i386/kernel/acpi.c Sun Mar 19 18:35:30 2000 +++ linux/arch/i386/kernel/acpi.c Wed Apr 5 17:04:37 2000 @@ -103,13 +103,57 @@ enum { - ACPI_ENABLED, - ACPI_TABLES_ONLY, - ACPI_CHIPSET_ONLY, - ACPI_DISABLED, + ACPI_ENABLED = 0x00000000, // use ACPI if present + ACPI_DISABLED = 0x00000001, // never use ACPI + ACPI_TABLES_ONLY = 0x00000002, // never use chipset-specific driver + ACPI_CHIPSET_ONLY = 0x00000004, // always use chipset-specific driver + ACPI_IGNORE_ERRATA = 0x00000008, // ignore any listed platform errata + ACPI_COPY_TABLES = 0x00000010, // copy ACPI tables before use + ACPI_TRUST_TABLES = 0x00000020, // use tables even after ioremap fails + ACPI_SCI_DISABLED = 0x00000040, // never enable ACPI (info. only) + ACPI_C2_DISABLED = 0x00000080, // never enter C2 + ACPI_C3_DISABLED = 0x00000100, // never enter C3 + ACPI_S1_DISABLED = 0x00000200, // never enter S1 + ACPI_S5_DISABLED = 0x00000400, // never enter S5 }; -static int acpi_enabled = ACPI_ENABLED; +struct acpi_option_info +{ + const char *name; + unsigned long value; +}; + +static struct acpi_option_info acpi_options[] = +{ + {"on", ACPI_ENABLED}, + {"off", ACPI_DISABLED}, + {"tables", ACPI_TABLES_ONLY}, + {"chipset", ACPI_CHIPSET_ONLY}, + {"no-errata", ACPI_IGNORE_ERRATA}, + {"copy-tables", ACPI_COPY_TABLES}, + {"trust-tables", ACPI_TRUST_TABLES}, + {"no-sci", ACPI_SCI_DISABLED}, + {"no-c2", ACPI_C2_DISABLED}, + {"no-c3", ACPI_C3_DISABLED}, + {"no-s1", ACPI_S1_DISABLED}, + {"no-s5", ACPI_S5_DISABLED}, + {NULL, 0}, +}; + +static unsigned long acpi_opts = ACPI_ENABLED; + +struct acpi_errata_info +{ + const char *oem; + const char *oem_table; + u32 oem_rev; + unsigned long options; +}; + +struct acpi_errata_info acpi_errata[] = +{ + {NULL, NULL, 0, 0}, +}; // bits 8-15 are SLP_TYPa, bits 0-7 are SLP_TYPb static unsigned long acpi_slp_typ[] = @@ -171,7 +215,7 @@ &acpi_p_lvl3_lat, sizeof(acpi_p_lvl3_lat), 0644, NULL, &acpi_do_ulong}, - {ACPI_P_LVL2_LAT, "enter_lvl2_lat", + {ACPI_ENTER_LVL2_LAT, "enter_lvl2_lat", &acpi_enter_lvl2_lat, sizeof(acpi_enter_lvl2_lat), 0644, NULL, &acpi_do_ulong}, @@ -405,6 +449,16 @@ printk(KERN_ERR "ACPI: unreserved table memory @ 0x%p!\n", (void*) addr); + + if (acpi_opts & ACPI_TRUST_TABLES) { + /* OK, trust that the table is there + * if it isn't you'll get an OOPS here + */ + static u32 sig; + table = (struct acpi_table *) + phys_to_virt(addr); + sig = table->signature; + } } } return table; @@ -423,14 +477,33 @@ /* * Initialize an ACPI table */ -static void acpi_init_table(struct acpi_table_info *info, - void *data, - int mapped) +static int acpi_init_table(struct acpi_table_info *info, + void *data, + int mapped) { struct acpi_table *table = (struct acpi_table*) data; + + info->table = NULL; + info->size = 0; + info->mapped = 0; + + if (!table || table->signature != info->expected_signature) + return -EINVAL; + + if (mapped && (acpi_opts & ACPI_COPY_TABLES)) { + struct acpi_table *copy + = kmalloc(table->length, GFP_KERNEL); + if (!copy) + return -ENOMEM; + memcpy(copy, table, table->length); + table = copy; + mapped = 0; + } + info->table = table; - info->size = (size_t)(table ? table->length:0); + info->size = (size_t) table->length; info->mapped = mapped; + return 0; } /* @@ -502,22 +575,13 @@ rsdt_entry_count = (int) ((rsdt->length - sizeof(*rsdt)) >> 2); while (rsdt_entry_count) { struct acpi_table *dt = acpi_map_table(*rsdt_entry); - if (dt && dt->signature == ACPI_FACP_SIG) { - struct acpi_facp *facp = (struct acpi_facp*) dt; - acpi_init_table(&acpi_facp, dt, 1); + if (!acpi_init_table(&acpi_facp, dt, 1)) { + struct acpi_facp *facp + = (struct acpi_facp*) acpi_facp.table; // map DSDT if it exists dt = acpi_map_table(facp->dsdt); - if (dt && dt->signature == ACPI_DSDT_SIG) - acpi_init_table(&acpi_dsdt, dt, 1); - else - acpi_unmap_table(dt); - - // map FACS if it exists - dt = acpi_map_table(facp->facs); - if (dt && dt->signature == ACPI_FACS_SIG) - acpi_init_table(&acpi_facs, dt, 1); - else + if (acpi_init_table(&acpi_dsdt, dt, 1)) acpi_unmap_table(dt); } else { @@ -769,6 +833,15 @@ } /* + * Is SCI to be enabled? + */ +static inline int +acpi_sci_enabled(void) +{ + return !(acpi_opts & ACPI_SCI_DISABLED); +} + +/* * Is ACPI enabled or not? */ static inline int acpi_is_enabled(struct acpi_facp *facp) @@ -781,7 +854,7 @@ */ static int acpi_enable(struct acpi_facp *facp) { - if (facp->smi_cmd) + if (facp->smi_cmd && acpi_sci_enabled()) outb(facp->acpi_enable, facp->smi_cmd); return (acpi_is_enabled(facp) ? 0:-1); } @@ -791,16 +864,20 @@ */ static int acpi_disable(struct acpi_facp *facp) { - // disable and clear any pending events - acpi_write_gpe_enable(facp, 0); - while (acpi_read_gpe_status(facp)) - acpi_write_gpe_status(facp, acpi_read_gpe_status(facp)); - acpi_write_pm1_enable(facp, 0); - acpi_write_pm1_status(facp, acpi_read_pm1_status(facp)); - - /* writing acpi_disable to smi_cmd would be appropriate - * here but this causes a nasty crash on many systems - */ + if (facp->smi_cmd && acpi_sci_enabled()) { + // disable and clear any pending events + acpi_write_gpe_enable(facp, 0); + while (acpi_read_gpe_status(facp)) { + acpi_write_gpe_status(facp, + acpi_read_gpe_status(facp)); + } + acpi_write_pm1_enable(facp, 0); + acpi_write_pm1_status(facp, acpi_read_pm1_status(facp)); + + /* writing acpi_disable to smi_cmd would be appropriate + * here but this causes a nasty crash on many systems + */ + } return 0; } @@ -860,7 +937,7 @@ sleep3: sleep_level = 3; if (!acpi_p_lvl3_tested) { - printk("ACPI C3 works\n"); + printk(KERN_INFO "ACPI C3 works\n"); acpi_p_lvl3_tested = 1; } wake_on_busmaster(facp); @@ -916,7 +993,7 @@ sleep2: sleep_level = 2; if (!acpi_p_lvl2_tested) { - printk("ACPI C2 works\n"); + printk(KERN_INFO "ACPI C2 works\n"); acpi_p_lvl2_tested = 1; } wake_on_busmaster(facp); /* Required to track BM activity.. */ @@ -1006,47 +1083,52 @@ } } - /* * Enter system sleep state */ -static void acpi_enter_sx(acpi_sstate_t state) +static int acpi_enter_sx(acpi_sstate_t state) { - unsigned long slp_typ = acpi_slp_typ[(int) state]; - if (slp_typ != ACPI_SLP_TYP_DISABLED) { - struct acpi_facp *facp = (struct acpi_facp*) acpi_facp.table; - u16 typa, typb, value; - - // bits 8-15 are SLP_TYPa, bits 0-7 are SLP_TYPb - typa = (slp_typ >> 8) & 0xff; - typb = slp_typ & 0xff; - - typa = ((typa << ACPI_SLP_TYP_SHIFT) & ACPI_SLP_TYP_MASK); - typb = ((typb << ACPI_SLP_TYP_SHIFT) & ACPI_SLP_TYP_MASK); - - acpi_sleep_start = get_cmos_time(); - acpi_enter_dx(ACPI_D3); - acpi_sleep_state = state; - - // clear wake status - acpi_write_pm1_status(facp, ACPI_WAK); - - // set SLP_TYPa/b and SLP_EN - if (facp->pm1a_cnt) { - value = inw(facp->pm1a_cnt) & ~ACPI_SLP_TYP_MASK; - outw(value | typa | ACPI_SLP_EN, facp->pm1a_cnt); - } - if (facp->pm1b_cnt) { - value = inw(facp->pm1b_cnt) & ~ACPI_SLP_TYP_MASK; - outw(value | typb | ACPI_SLP_EN, facp->pm1b_cnt); - } - - // wait until S1 is entered - while (!(acpi_read_pm1_status(facp) & ACPI_WAK)) ; - // finished sleeping, update system time - acpi_update_clock(); - acpi_enter_dx(ACPI_D0); + unsigned long slp_typ; + u16 typa, typb, value; + struct acpi_facp *facp; + + slp_typ = acpi_slp_typ[(int) state]; + if (slp_typ == ACPI_SLP_TYP_DISABLED) + return -EPERM; + + // bits 8-15 are SLP_TYPa, bits 0-7 are SLP_TYPb + typa = (slp_typ >> 8) & 0xff; + typb = slp_typ & 0xff; + + typa = ((typa << ACPI_SLP_TYP_SHIFT) & ACPI_SLP_TYP_MASK); + typb = ((typb << ACPI_SLP_TYP_SHIFT) & ACPI_SLP_TYP_MASK); + + acpi_sleep_start = get_cmos_time(); + acpi_enter_dx(ACPI_D3); + acpi_sleep_state = state; + + facp = (struct acpi_facp*) acpi_facp.table; + + // clear wake status + acpi_write_pm1_status(facp, ACPI_WAK); + + // set SLP_TYPa/b and SLP_EN + if (facp->pm1a_cnt) { + value = inw(facp->pm1a_cnt) & ~ACPI_SLP_TYP_MASK; + outw(value | typa | ACPI_SLP_EN, facp->pm1a_cnt); + } + if (facp->pm1b_cnt) { + value = inw(facp->pm1b_cnt) & ~ACPI_SLP_TYP_MASK; + outw(value | typb | ACPI_SLP_EN, facp->pm1b_cnt); } + + // wait until S1 is entered + while (!(acpi_read_pm1_status(facp) & ACPI_WAK)) ; + // finished sleeping, update system time + acpi_update_clock(); + acpi_enter_dx(ACPI_D0); + + return 0; } /* @@ -1113,6 +1195,42 @@ } /* + * Determine if modification of value is permitted + */ +static int +acpi_verify_mod(int ctl_name) +{ + switch (ctl_name) { + case ACPI_PM1_ENABLE: + case ACPI_GPE_ENABLE: + case ACPI_GPE_LEVEL: + if (!acpi_sci_enabled()) + return -EPERM; + break; + case ACPI_P_LVL2_LAT: + case ACPI_ENTER_LVL2_LAT: + if (acpi_opts & ACPI_C2_DISABLED) + return -EPERM; + break; + case ACPI_P_LVL3_LAT: + case ACPI_ENTER_LVL3_LAT: + if (acpi_opts & ACPI_C3_DISABLED) + return -EPERM; + break; + case ACPI_S1_SLP_TYP: + case ACPI_SLEEP: + if (acpi_opts & ACPI_S1_DISABLED) + return -EPERM; + break; + case ACPI_S5_SLP_TYP: + if (acpi_opts & ACPI_S5_DISABLED) + return -EPERM; + break; + } + return 0; +} + +/* * Examine/modify value */ static int acpi_do_ulong(ctl_table *ctl, @@ -1141,6 +1259,9 @@ *len = 0; } else { + if (acpi_verify_mod(ctl->ctl_name)) + return -EPERM; + size = sizeof(str) - 1; if (size > *len) size = *len; @@ -1313,6 +1434,9 @@ } else { + if (acpi_verify_mod(ctl->ctl_name)) + return -EPERM; + // fetch user value size = sizeof(str) - 1; if (size > *len) @@ -1443,24 +1567,71 @@ } else { -#ifdef CONFIG_ACPI_S1_SLEEP - acpi_enter_sx(ACPI_S1); -#endif + if (acpi_verify_mod(ctl->ctl_name) || acpi_enter_sx(ACPI_S1)) + return -EPERM; } file->f_pos += *len; return 0; } +/* + * Parse command line options + */ +static int __init acpi_setup(char *str) +{ + while (str && *str) { + struct acpi_option_info *opt = acpi_options; + while (opt->name) { + if (!strncmp(str, opt->name, strlen(opt->name))) { + acpi_opts |= opt->value; + break; + } + opt++; + } + str = strpbrk(str, ","); + if (str) + str += strspn(str, ","); + } + + if (acpi_opts) + printk(KERN_INFO "ACPI: options 0x%08lx\n", acpi_opts); + + return 1; +} + +/* + * kernel/module command line interfaces are both "acpi=OPTION,OPTION,..." + */ +__setup("acpi=", acpi_setup); + +static char * __initdata acpi = NULL; + +MODULE_DESCRIPTION("ACPI driver"); +MODULE_PARM(acpi, "s"); +MODULE_PARM_DESC(acpi, "ACPI driver command line"); /* * Initialize and enable ACPI */ -static int __init acpi_init(void) +int __init acpi_init(void) { struct acpi_facp *facp = NULL; - switch (acpi_enabled) { - case ACPI_ENABLED: + if (acpi) + acpi_setup(acpi); + + if (acpi_opts & ACPI_DISABLED) { + return -ENODEV; + } + else if (acpi_opts & ACPI_TABLES_ONLY) { + if (acpi_find_tables()) + return -ENODEV; + } + else if (acpi_opts & ACPI_CHIPSET_ONLY) { + if (acpi_find_chipset()) + return -ENODEV; + } + else { switch (acpi_find_tables()) { case 0: // found valid ACPI tables @@ -1474,17 +1645,6 @@ // found broken ACPI tables return -ENODEV; } - break; - case ACPI_TABLES_ONLY: - if (acpi_find_tables()) - return -ENODEV; - break; - case ACPI_CHIPSET_ONLY: - if (acpi_find_chipset()) - return -ENODEV; - break; - case ACPI_DISABLED: - return -ENODEV; } facp = (struct acpi_facp*) acpi_facp.table; @@ -1502,12 +1662,14 @@ * control in the /proc interfaces. */ if (facp->p_lvl2_lat - && facp->p_lvl2_lat <= ACPI_MAX_P_LVL2_LAT) { + && facp->p_lvl2_lat <= ACPI_MAX_P_LVL2_LAT + && !acpi_verify_mod(ACPI_P_LVL2_LAT)) { acpi_p_lvl2_lat = ACPI_uS_TO_TMR_TICKS(facp->p_lvl2_lat); acpi_enter_lvl2_lat = ACPI_uS_TO_TMR_TICKS(ACPI_TMR_HZ / 1000); } if (facp->p_lvl3_lat - && facp->p_lvl3_lat <= ACPI_MAX_P_LVL3_LAT) { + && facp->p_lvl3_lat <= ACPI_MAX_P_LVL3_LAT + && !acpi_verify_mod(ACPI_P_LVL3_LAT)) { acpi_p_lvl3_lat = ACPI_uS_TO_TMR_TICKS(facp->p_lvl3_lat); acpi_enter_lvl3_lat = ACPI_uS_TO_TMR_TICKS(facp->p_lvl3_lat * 5); @@ -1519,6 +1681,7 @@ } if (facp->sci_int + && acpi_sci_enabled() && request_irq(facp->sci_int, acpi_irq, SA_INTERRUPT | SA_SHIRQ, @@ -1529,6 +1692,10 @@ goto err_out; } +#ifndef CONFIG_ACPI_S1_SLEEP + acpi_opts |= ACPI_S1_DISABLED; +#endif + acpi_sysctl = register_sysctl_table(acpi_dir_table, 1); pm_power_off = acpi_power_off; @@ -1559,7 +1726,7 @@ /* * Disable and deinitialize ACPI */ -static void __exit acpi_exit(void) +void __exit acpi_exit(void) { struct acpi_facp *facp = (struct acpi_facp*) acpi_facp.table; @@ -1570,7 +1737,7 @@ acpi_disable(facp); acpi_release_ioports(facp); - if (facp->sci_int) + if (facp->sci_int && acpi_sci_enabled()) free_irq(facp->sci_int, &acpi_facp); acpi_destroy_tables(); @@ -1581,29 +1748,5 @@ pm_active = 0; } -/* - * Parse kernel command line options - */ -static int __init acpi_setup(char *str) -{ - while (str && *str) { - if (strncmp(str, "on", 2) == 0) - acpi_enabled = ACPI_ENABLED; - else if (strncmp(str, "tables", 6) == 0) - acpi_enabled = ACPI_TABLES_ONLY; - else if (strncmp(str, "chipset", 7) == 0) - acpi_enabled = ACPI_CHIPSET_ONLY; - else if (strncmp(str, "off", 3) == 0) - acpi_enabled = ACPI_DISABLED; - str = strpbrk(str, ","); - if (str) - str += strspn(str, ","); - } - return 1; -} - -__setup("acpi=", acpi_setup); - module_init(acpi_init); module_exit(acpi_exit); - diff -u --recursive --new-file v2.3.99-pre3/linux/arch/i386/kernel/head.S linux/arch/i386/kernel/head.S --- v2.3.99-pre3/linux/arch/i386/kernel/head.S Sun Mar 19 18:35:30 2000 +++ linux/arch/i386/kernel/head.S Tue Apr 11 12:20:12 2000 @@ -70,22 +70,28 @@ */ #define cr4_bits mmu_cr4_features-__PAGE_OFFSET cmpl $0,cr4_bits - je 1f - movl %cr4,%eax # Turn on 4Mb pages + je 3f + movl %cr4,%eax # Turn on paging options (PSE,PAE,..) orl cr4_bits,%eax movl %eax,%cr4 + jmp 3f +1: #endif /* - * Setup paging (intialize tables, then switch them on) + * Initialize page tables */ -1: movl $pg0-__PAGE_OFFSET,%edi /* initialize page tables */ movl $007,%eax /* "007" doesn't mean with right to kill, but PRESENT+RW+USER */ -1: stosl +2: stosl add $0x1000,%eax cmp $empty_zero_page-__PAGE_OFFSET,%edi - jne 1b + jne 2b + +/* + * Enable paging + */ +3: movl $swapper_pg_dir-__PAGE_OFFSET,%eax movl %eax,%cr3 /* set the page table pointer.. */ movl %cr0,%eax diff -u --recursive --new-file v2.3.99-pre3/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c --- v2.3.99-pre3/linux/arch/i386/kernel/irq.c Tue Mar 14 19:10:39 2000 +++ linux/arch/i386/kernel/irq.c Mon Mar 27 14:17:05 2000 @@ -862,7 +862,7 @@ */ /** - * probe_irq_mask + * probe_irq_mask - scan a bitmap of interrupt lines * @val: mask of interrupts to consider * * Scan the ISA bus interrupt lines and return a bitmap of diff -u --recursive --new-file v2.3.99-pre3/linux/arch/i386/kernel/mtrr.c linux/arch/i386/kernel/mtrr.c --- v2.3.99-pre3/linux/arch/i386/kernel/mtrr.c Tue Mar 14 19:10:39 2000 +++ linux/arch/i386/kernel/mtrr.c Mon Mar 27 14:17:05 2000 @@ -1281,7 +1281,7 @@ } /* End Function mtrr_add */ /** - * mtrr_del + * mtrr_del - delete a memory type region * @reg: Register returned by mtrr_add * @base: Physical base address * @size: Size of region diff -u --recursive --new-file v2.3.99-pre3/linux/arch/i386/kernel/pci-i386.c linux/arch/i386/kernel/pci-i386.c --- v2.3.99-pre3/linux/arch/i386/kernel/pci-i386.c Sun Mar 19 18:35:30 2000 +++ linux/arch/i386/kernel/pci-i386.c Mon Mar 27 14:29:13 2000 @@ -228,7 +228,7 @@ if (!pr || request_resource(pr, r) < 0) { printk(KERN_ERR "PCI: Cannot allocate resource region %d of device %s\n", idx, dev->slot_name); /* We'll assign a new address later */ - r->start -= r->end; + r->end -= r->start; r->start = 0; } } @@ -317,6 +317,8 @@ 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("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd); pci_write_config_word(dev, PCI_COMMAND, cmd); diff -u --recursive --new-file v2.3.99-pre3/linux/arch/i386/kernel/pci-pc.c linux/arch/i386/kernel/pci-pc.c --- v2.3.99-pre3/linux/arch/i386/kernel/pci-pc.c Sun Mar 19 18:35:30 2000 +++ linux/arch/i386/kernel/pci-pc.c Mon Mar 27 10:33:03 2000 @@ -1188,7 +1188,7 @@ } else if (newirq) { DBG(" -> [VIA] set to %02x\n", newirq); x = (pirq & 1) ? ((x & 0x0f) | (newirq << 4)) : ((x & 0xf0) | newirq); - pci_write_config_byte(router, reg, y); + pci_write_config_byte(router, reg, x); msg = "VIA-NEW"; } else DBG(" -> [VIA] sink\n"); break; diff -u --recursive --new-file v2.3.99-pre3/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c --- v2.3.99-pre3/linux/arch/i386/kernel/setup.c Sun Mar 19 18:35:30 2000 +++ linux/arch/i386/kernel/setup.c Sun Apr 9 08:12:56 2000 @@ -727,7 +727,7 @@ #ifdef CONFIG_BLK_DEV_INITRD if (LOADER_TYPE && INITRD_START) { - if (INITRD_START + INITRD_SIZE < (max_low_pfn << PAGE_SHIFT)) { + if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) { reserve_bootmem(INITRD_START, INITRD_SIZE); initrd_start = INITRD_START ? INITRD_START + PAGE_OFFSET : 0; @@ -863,7 +863,7 @@ rdmsr(0xC0000082, l, h); if((l&0x0000FFFF)==0) { - l=(1<<0)|(mbytes/4); + l=(1<<0)|((mbytes/4)<<1); save_flags(flags); __cli(); __asm__ __volatile__ ("wbinvd": : :"memory"); diff -u --recursive --new-file v2.3.99-pre3/linux/arch/i386/lib/Makefile linux/arch/i386/lib/Makefile --- v2.3.99-pre3/linux/arch/i386/lib/Makefile Fri Oct 22 13:21:45 1999 +++ linux/arch/i386/lib/Makefile Thu Mar 30 16:56:04 2000 @@ -3,7 +3,7 @@ # .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o + $(CC) $(AFLAGS) -traditional -c $< -o $*.o L_TARGET = lib.a L_OBJS = checksum.o old-checksum.o delay.o \ diff -u --recursive --new-file v2.3.99-pre3/linux/arch/i386/math-emu/Makefile linux/arch/i386/math-emu/Makefile --- v2.3.99-pre3/linux/arch/i386/math-emu/Makefile Mon Dec 20 18:48:21 1999 +++ linux/arch/i386/math-emu/Makefile Thu Mar 30 16:56:04 2000 @@ -10,7 +10,7 @@ CFLAGS := $(CFLAGS) $(PARANOID) $(DEBUG) -fno-builtin $(MATH_EMULATION) .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) $(PARANOID) -c $< + $(CC) $(AFLAGS) $(PARANOID) -c $< # From 'C' language sources: C_OBJS =fpu_entry.o errors.o \ diff -u --recursive --new-file v2.3.99-pre3/linux/arch/ia64/boot/Makefile linux/arch/ia64/boot/Makefile --- v2.3.99-pre3/linux/arch/ia64/boot/Makefile Thu Feb 10 17:11:03 2000 +++ linux/arch/ia64/boot/Makefile Thu Mar 30 16:56:04 2000 @@ -11,9 +11,9 @@ LINKFLAGS = -static -T bootloader.lds .S.s: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -E -o $*.o $< + $(CPP) $(AFLAGS) -traditional -o $*.o $< .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c -o $*.o $< + $(CC) $(AFLAGS) -traditional -c -o $*.o $< OBJECTS = bootloader.o TARGETS = diff -u --recursive --new-file v2.3.99-pre3/linux/arch/ia64/config.in linux/arch/ia64/config.in --- v2.3.99-pre3/linux/arch/ia64/config.in Mon Mar 27 08:08:21 2000 +++ linux/arch/ia64/config.in Mon Mar 27 14:18:32 2000 @@ -4,6 +4,8 @@ comment 'General setup' define_bool CONFIG_IA64 y +define_bool CONFIG_ISA n +define_bool CONFIG_SBUS n choice 'IA-64 system type' \ "Generic CONFIG_IA64_GENERIC \ @@ -50,7 +52,12 @@ bool 'PCI support' CONFIG_PCI source drivers/pci/Config.in -source drivers/pcmcia/Config.in +bool 'Support for hot-pluggable devices' CONFIG_HOTPLUG +if [ "$CONFIG_HOTPLUG" = "y" ]; then + source drivers/pcmcia/Config.in +else + define_bool CONFIG_PCMCIA n +fi mainmenu_option next_comment comment 'Code maturity level options' @@ -134,7 +141,6 @@ endmenu source drivers/char/Config.in -source drivers/usb/Config.in #source drivers/misc/Config.in source fs/Config.in @@ -160,6 +166,8 @@ source drivers/sound/Config.in fi endmenu + +source drivers/usb/Config.in mainmenu_option next_comment comment 'Kernel hacking' diff -u --recursive --new-file v2.3.99-pre3/linux/arch/ia64/defconfig linux/arch/ia64/defconfig --- v2.3.99-pre3/linux/arch/ia64/defconfig Mon Mar 27 08:08:21 2000 +++ linux/arch/ia64/defconfig Mon Mar 27 09:38:47 2000 @@ -6,6 +6,8 @@ # General setup # CONFIG_IA64=y +# CONFIG_ISA is not set +# CONFIG_SBUS is not set # CONFIG_IA64_GENERIC is not set CONFIG_IA64_HP_SIM=y # CONFIG_IA64_SGI_SN1_SIM is not set @@ -25,10 +27,7 @@ # CONFIG_BINFMT_MISC is not set CONFIG_PCI=y CONFIG_PCI_NAMES=y - -# -# PCMCIA/CardBus support -# +# CONFIG_HOTPLUG is not set # CONFIG_PCMCIA is not set # @@ -119,6 +118,7 @@ # CONFIG_BLK_DEV_AEC6210 is not set # CONFIG_AEC6210_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_CMD64X is not set diff -u --recursive --new-file v2.3.99-pre3/linux/arch/ia64/dig/Makefile linux/arch/ia64/dig/Makefile --- v2.3.99-pre3/linux/arch/ia64/dig/Makefile Thu Feb 10 17:11:03 2000 +++ linux/arch/ia64/dig/Makefile Thu Mar 30 16:56:04 2000 @@ -6,9 +6,9 @@ # .S.s: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -E -o $*.s $< + $(CPP) $(AFLAGS) -o $*.s $< .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -c -o $*.o $< + $(CC) $(AFLAGS) -c -o $*.o $< all: dig.a diff -u --recursive --new-file v2.3.99-pre3/linux/arch/ia64/ia32/Makefile linux/arch/ia64/ia32/Makefile --- v2.3.99-pre3/linux/arch/ia64/ia32/Makefile Thu Feb 10 17:11:03 2000 +++ linux/arch/ia64/ia32/Makefile Thu Mar 30 16:56:04 2000 @@ -3,9 +3,9 @@ # .S.s: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -E -o $*.s $< + $(CPP) $(AFLAGS) -o $*.s $< .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -c -o $*.o $< + $(CC) $(AFLAGS) -c -o $*.o $< all: ia32.o diff -u --recursive --new-file v2.3.99-pre3/linux/arch/ia64/ia32/sys_ia32.c linux/arch/ia64/ia32/sys_ia32.c --- v2.3.99-pre3/linux/arch/ia64/ia32/sys_ia32.c Sat Feb 26 22:31:39 2000 +++ linux/arch/ia64/ia32/sys_ia32.c Sun Apr 2 15:49:08 2000 @@ -2298,7 +2298,9 @@ return 0; } -extern asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type, +extern asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type, + unsigned long new_flags, void *data); +extern long do_sys_mount(char * dev_name, char * dir_name, char * type, unsigned long new_flags, void *data); #define SMBFS_NAME "smbfs" @@ -2328,7 +2330,6 @@ (void *)AA(data)); } else { unsigned long dev_page, dir_page, data_page; - mm_segment_t old_fs; err = copy_mount_stuff_to_kernel((const void *)dev_name, &dev_page); @@ -2348,13 +2349,9 @@ do_smb_super_data_conv((void *)data_page); else panic("The problem is here..."); - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_mount((char *)dev_page, (char *)dir_page, + err = do_sys_mount((char *)dev_page, (char *)dir_page, (char *)type_page, new_flags, (void *)data_page); - set_fs(old_fs); - if(data_page) free_page(data_page); dir_out: diff -u --recursive --new-file v2.3.99-pre3/linux/arch/ia64/kdb/Makefile linux/arch/ia64/kdb/Makefile --- v2.3.99-pre3/linux/arch/ia64/kdb/Makefile Thu Feb 10 17:11:03 2000 +++ linux/arch/ia64/kdb/Makefile Thu Mar 30 16:56:04 2000 @@ -13,7 +13,7 @@ ALL_SUB_DIRS := $(SUB_DIRS) .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o + $(CC) $(AFLAGS) -traditional -c $< -o $*.o L_TARGET = kdb.a L_OBJS = kdbsupport.o kdb_io.o kdb_bt.o kdb_traps.o diff -u --recursive --new-file v2.3.99-pre3/linux/arch/ia64/kernel/Makefile linux/arch/ia64/kernel/Makefile --- v2.3.99-pre3/linux/arch/ia64/kernel/Makefile Fri Mar 10 16:40:39 2000 +++ linux/arch/ia64/kernel/Makefile Thu Mar 30 16:56:04 2000 @@ -8,9 +8,9 @@ # Note 2! The CFLAGS definitions are now in the main makefile... .S.s: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -E -o $*.s $< + $(CPP) $(AFLAGS) -o $*.s $< .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -c -o $*.o $< + $(CC) $(AFLAGS) -c -o $*.o $< all: kernel.o head.o init_task.o diff -u --recursive --new-file v2.3.99-pre3/linux/arch/ia64/lib/Makefile linux/arch/ia64/lib/Makefile --- v2.3.99-pre3/linux/arch/ia64/lib/Makefile Sun Feb 13 19:29:03 2000 +++ linux/arch/ia64/lib/Makefile Thu Mar 30 16:56:04 2000 @@ -3,7 +3,7 @@ # .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -c $< -o $@ + $(CC) $(AFLAGS) -c $< -o $@ OBJS = __divdi3.o __divsi3.o __udivdi3.o __udivsi3.o \ __moddi3.o __modsi3.o __umoddi3.o __umodsi3.o \ diff -u --recursive --new-file v2.3.99-pre3/linux/arch/ia64/sn/Makefile linux/arch/ia64/sn/Makefile --- v2.3.99-pre3/linux/arch/ia64/sn/Makefile Thu Feb 10 17:11:03 2000 +++ linux/arch/ia64/sn/Makefile Thu Mar 30 16:56:04 2000 @@ -10,9 +10,9 @@ AFLAGS := $(AFLAGS) -DCONFIG_SGI_SN1 -DSN1 -DSOFTSDV .S.s: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -E -o $*.s $< + $(CPP) $(AFLAGS) -o $*.s $< .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -c -o $*.o $< + $(CC) $(AFLAGS) -c -o $*.o $< all: sn.a diff -u --recursive --new-file v2.3.99-pre3/linux/arch/ia64/sn/sn1/Makefile linux/arch/ia64/sn/sn1/Makefile --- v2.3.99-pre3/linux/arch/ia64/sn/sn1/Makefile Thu Feb 10 17:11:03 2000 +++ linux/arch/ia64/sn/sn1/Makefile Thu Mar 30 16:56:04 2000 @@ -10,9 +10,9 @@ AFLAGS := $(AFLAGS) -DCONFIG_SGI_SN1 -DSN1 -DSOFTSDV .S.s: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -E -o $*.s $< + $(CPP) $(AFLAGS) -o $*.s $< .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -c -o $*.o $< + $(CC) $(AFLAGS) -c -o $*.o $< all: sn1.a diff -u --recursive --new-file v2.3.99-pre3/linux/arch/m68k/config.in linux/arch/m68k/config.in --- v2.3.99-pre3/linux/arch/m68k/config.in Mon Mar 27 08:08:22 2000 +++ linux/arch/m68k/config.in Mon Apr 10 22:58:59 2000 @@ -16,16 +16,15 @@ comment 'Platform dependent setup' define_bool CONFIG_ISA n +define_bool CONFIG_PCMCIA n + bool 'Amiga support' CONFIG_AMIGA bool 'Atari support' CONFIG_ATARI -if [ "$CONFIG_ATARI" = "y" ]; then - bool ' Hades support' CONFIG_HADES - if [ "$CONFIG_HADES" = "y" ]; then - define_bool CONFIG_PCI y - fi -fi -if [ "$CONFIG_HADES" != "y" ]; then - define_bool CONFIG_PCI n +dep_bool ' Hades support' CONFIG_HADES $CONFIG_ATARI +if [ "$CONFIG_HADES" = "y" ]; then + define_bool CONFIG_PCI y +else + define_bool CONFIG_PCI n fi bool 'Macintosh support' CONFIG_MAC if [ "$CONFIG_MAC" = "y" ]; then @@ -421,19 +420,21 @@ if [ "$CONFIG_HP300" = "y" -a "$CONFIG_DIO" = "y" ]; then tristate 'HP DCA serial support' CONFIG_HPDCA fi -if [ "$CONFIG_SUN3X" = "y" ]; then - bool 'Sun3x builtin serial support' CONFIG_SUN3X_ZS - if [ "$CONFIG_SUN3X_ZS" = "y" ]; then - bool ' Sun keyboard support' CONFIG_SUN_KEYBOARD - bool ' Sun mouse support' CONFIG_SUN_MOUSE - if [ "$CONFIG_SUN_MOUSE" != "n" ]; then - define_bool CONFIG_BUSMOUSE y - fi - define_bool CONFIG_SBUS y - define_bool CONFIG_SBUSCHAR y - define_bool CONFIG_SUN_SERIAL y - fi + +dep_bool 'Sun3x builtin serial support' CONFIG_SUN3X_ZS $CONFIG_SUN3X +dep_bool ' Sun keyboard support' CONFIG_SUN_KEYBOARD $CONFIG_SUN3X_ZS +dep_bool ' Sun mouse support' CONFIG_SUN_MOUSE $CONFIG_SUN3X_ZS +if [ "$CONFIG_SUN_MOUSE" = "y" ]; then + define_bool CONFIG_BUSMOUSE y +fi +if [ "$CONFIG_SUN3X_ZS" = "y" ]; then + define_bool CONFIG_SBUS y + define_bool CONFIG_SBUSCHAR y + define_bool CONFIG_SUN_SERIAL y +else + define_bool CONFIG_SBUS n fi + if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_ATARI" = "y" -o \ "$CONFIG_MAC" = "y" -o "$CONFIG_HP300" = "y" -o \ "$CONFIG_SUN3X" = "y" ]; then @@ -483,7 +484,7 @@ tristate 'Sound support' CONFIG_SOUND if [ "$CONFIG_SOUND" != "n" ]; then - dep_tristate ' Amiga or Atari DMA sound support' CONFIG_DMASOUND $CONFIG_SOUND + source drivers/sound/dmasound/Config.in fi endmenu diff -u --recursive --new-file v2.3.99-pre3/linux/arch/m68k/defconfig linux/arch/m68k/defconfig --- v2.3.99-pre3/linux/arch/m68k/defconfig Mon Mar 27 08:08:22 2000 +++ linux/arch/m68k/defconfig Mon Mar 27 09:38:47 2000 @@ -12,8 +12,10 @@ # Platform dependent setup # # CONFIG_ISA is not set +# CONFIG_PCMCIA is not set CONFIG_AMIGA=y # CONFIG_ATARI is not set +# CONFIG_HADES is not set # CONFIG_PCI is not set # CONFIG_MAC is not set # CONFIG_APOLLO is not set @@ -195,6 +197,10 @@ # CONFIG_GVPIOEXT_LP is not set # CONFIG_GVPIOEXT_PLIP is not set # CONFIG_MULTIFACE_III_TTY is not set +# CONFIG_SUN3X_ZS is not set +# CONFIG_SUN_KEYBOARD is not set +# CONFIG_SUN_MOUSE is not set +# CONFIG_SBUS is not set # CONFIG_SERIAL_CONSOLE is not set # CONFIG_USERIAL is not set # CONFIG_WATCHDOG is not set diff -u --recursive --new-file v2.3.99-pre3/linux/arch/m68k/fpsp040/Makefile linux/arch/m68k/fpsp040/Makefile --- v2.3.99-pre3/linux/arch/m68k/fpsp040/Makefile Mon Dec 20 18:48:21 1999 +++ linux/arch/m68k/fpsp040/Makefile Thu Mar 30 16:56:04 2000 @@ -8,7 +8,7 @@ # Note 2! The CFLAGS definitions are now in the main makefile... .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c -o $*.o $< + $(CC) $(AFLAGS) -traditional -c -o $*.o $< OS_TARGET := fpsp.o diff -u --recursive --new-file v2.3.99-pre3/linux/arch/m68k/ifpsp060/Makefile linux/arch/m68k/ifpsp060/Makefile --- v2.3.99-pre3/linux/arch/m68k/ifpsp060/Makefile Mon Dec 20 18:48:21 1999 +++ linux/arch/m68k/ifpsp060/Makefile Thu Mar 30 16:56:04 2000 @@ -5,7 +5,7 @@ # for more details. .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c -o $*.o $< + $(CC) $(AFLAGS) -traditional -c -o $*.o $< OS_TARGET := ifpsp.o diff -u --recursive --new-file v2.3.99-pre3/linux/arch/m68k/kernel/Makefile linux/arch/m68k/kernel/Makefile --- v2.3.99-pre3/linux/arch/m68k/kernel/Makefile Sun Feb 13 19:29:03 2000 +++ linux/arch/m68k/kernel/Makefile Thu Mar 30 16:56:04 2000 @@ -8,7 +8,7 @@ # Note 2! The CFLAGS definitions are now in the main makefile... .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o + $(CC) $(AFLAGS) -traditional -c $< -o $*.o ifndef CONFIG_SUN3 all: head.o kernel.o diff -u --recursive --new-file v2.3.99-pre3/linux/arch/m68k/lib/Makefile linux/arch/m68k/lib/Makefile --- v2.3.99-pre3/linux/arch/m68k/lib/Makefile Fri Jan 28 15:09:07 2000 +++ linux/arch/m68k/lib/Makefile Thu Mar 30 16:56:04 2000 @@ -3,7 +3,7 @@ # .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $@ + $(CC) $(AFLAGS) -traditional -c $< -o $@ L_TARGET = lib.a L_OBJS = ashrdi3.o lshrdi3.o checksum.o memcpy.o memcmp.o memset.o semaphore.o diff -u --recursive --new-file v2.3.99-pre3/linux/arch/m68k/math-emu/Makefile linux/arch/m68k/math-emu/Makefile --- v2.3.99-pre3/linux/arch/m68k/math-emu/Makefile Mon Dec 20 18:48:21 1999 +++ linux/arch/m68k/math-emu/Makefile Thu Mar 30 16:56:04 2000 @@ -8,7 +8,7 @@ # Note 2! The CFLAGS definitions are now in the main makefile... .S.o: - $(CC) $(EXTRA_CFLAGS) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o + $(CC) $(EXTRA_CFLAGS) $(AFLAGS) -traditional -c $< -o $*.o #EXTRA_CFLAGS=-DFPU_EMU_DEBUG diff -u --recursive --new-file v2.3.99-pre3/linux/arch/m68k/sun3/Makefile linux/arch/m68k/sun3/Makefile --- v2.3.99-pre3/linux/arch/m68k/sun3/Makefile Fri Jan 28 15:09:07 2000 +++ linux/arch/m68k/sun3/Makefile Thu Mar 30 16:56:04 2000 @@ -8,7 +8,7 @@ # Note 2! The CFLAGS definitions are now in the main makefile... .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -Wa,-m68020 -c $< -o $*.o + $(CC) $(AFLAGS) -traditional -Wa,-m68020 -c $< -o $*.o O_TARGET := sun3.o O_OBJS := config.o idprom.o mmu_emu.o sun3ints.o leds.o dvma.o sbus.o intersil.o diff -u --recursive --new-file v2.3.99-pre3/linux/arch/mips/config.in linux/arch/mips/config.in --- v2.3.99-pre3/linux/arch/mips/config.in Mon Mar 27 08:08:22 2000 +++ linux/arch/mips/config.in Mon Mar 27 14:18:32 2000 @@ -29,6 +29,8 @@ unset CONFIG_MIPS_JAZZ unset CONFIG_VIDEO_G364 +define_bool CONFIG_SBUS n + if [ "$CONFIG_ALGOR_P4032" = "y" -o "$CONFIG_SNI_RM200_PCI" = "y" -o \ "$CONFIG_DDB5074" = "y" ]; then define_bool CONFIG_PCI y @@ -127,7 +129,13 @@ bool 'Networking support' CONFIG_NET source drivers/pci/Config.in -source drivers/pcmcia/Config.in + +bool 'Support for hot-pluggable devices' CONFIG_HOTPLUG +if [ "$CONFIG_HOTPLUG" = "y" ]; then + source drivers/pcmcia/Config.in +else + define_bool CONFIG_PCMCIA n +fi bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT @@ -252,8 +260,11 @@ fi if [ "$CONFIG_SGI" != "y" -a "$CONFIG_DECSTATION" != "y" -a "$CONFIG_BAGET_MIPS" != "y" ]; then - source drivers/net/hamradio/Config.in + mainmenu_option next_comment + # comment 'AX.25 network device drivers' + source drivers/net/hamradio/Config.in + endmenu mainmenu_option next_comment comment 'ISDN subsystem' @@ -307,7 +318,6 @@ endmenu fi -source drivers/usb/Config.in #source drivers/misc/Config.in @@ -347,6 +357,8 @@ if [ "$CONFIG_SGI_IP22" = "y" ]; then source drivers/sgi/Config.in fi + +source drivers/usb/Config.in mainmenu_option next_comment comment 'Kernel hacking' diff -u --recursive --new-file v2.3.99-pre3/linux/arch/mips/defconfig linux/arch/mips/defconfig --- v2.3.99-pre3/linux/arch/mips/defconfig Mon Mar 27 08:08:22 2000 +++ linux/arch/mips/defconfig Mon Mar 27 09:38:47 2000 @@ -19,6 +19,7 @@ # CONFIG_OLIVETTI_M700 is not set CONFIG_SGI_IP22=y # CONFIG_SNI_RM200_PCI is not set +# CONFIG_SBUS is not set # CONFIG_PCI is not set # CONFIG_ISA is not set @@ -49,10 +50,7 @@ CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set CONFIG_NET=y - -# -# PCMCIA/CardBus support -# +# CONFIG_HOTPLUG is not set # CONFIG_PCMCIA is not set CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set diff -u --recursive --new-file v2.3.99-pre3/linux/arch/mips/kernel/sysirix.c linux/arch/mips/kernel/sysirix.c --- v2.3.99-pre3/linux/arch/mips/kernel/sysirix.c Fri Mar 10 16:40:40 2000 +++ linux/arch/mips/kernel/sysirix.c Sun Apr 2 15:49:08 2000 @@ -696,7 +696,7 @@ return -EINTR; } -extern asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type, +extern asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type, unsigned long new_flags, void * data); /* XXX need more than this... */ diff -u --recursive --new-file v2.3.99-pre3/linux/arch/mips64/config.in linux/arch/mips64/config.in --- v2.3.99-pre3/linux/arch/mips64/config.in Mon Mar 27 08:08:22 2000 +++ linux/arch/mips64/config.in Mon Mar 27 14:18:32 2000 @@ -19,11 +19,10 @@ bool ' Discontiguous Memory Support' CONFIG_DISCONTIGMEM #bool ' IP27 XXL' CONFIG_SGI_SN0_XXL fi -endmenu - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then bool 'Symmetric Multi-Processing support' CONFIG_SMP fi +endmenu # # Select some configuration options automatically based on user selections @@ -37,6 +36,7 @@ unset CONFIG_BINFMT_ELF32 define_bool CONFIG_ISA n +define_bool CONFIG_SBUS n if [ "$CONFIG_SGI_IP22" = "y" ]; then define_bool CONFIG_BOOT_ELF32 y @@ -78,7 +78,14 @@ bool 'Networking support' CONFIG_NET source drivers/pci/Config.in -source drivers/pcmcia/Config.in + +bool 'Support for hot-pluggable devices' CONFIG_HOTPLUG + +if [ "$CONFIG_HOTPLUG" = "y" ] ; then + source drivers/pcmcia/Config.in +else + define_bool CONFIG_PCMCIA n +fi bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT @@ -191,7 +198,6 @@ source drivers/char/Config.in -source drivers/usb/Config.in #source drivers/misc/Config.in @@ -225,6 +231,8 @@ if [ "$CONFIG_SGI_IP22" = "y" ]; then source drivers/sgi/Config.in fi + +source drivers/usb/Config.in mainmenu_option next_comment comment 'Kernel hacking' diff -u --recursive --new-file v2.3.99-pre3/linux/arch/mips64/defconfig linux/arch/mips64/defconfig --- v2.3.99-pre3/linux/arch/mips64/defconfig Mon Mar 27 08:08:22 2000 +++ linux/arch/mips64/defconfig Mon Mar 27 09:38:47 2000 @@ -15,6 +15,7 @@ # CONFIG_SGI_SN0_N_MODE is not set # CONFIG_DISCONTIGMEM is not set # CONFIG_ISA is not set +# CONFIG_SBUS is not set CONFIG_BOOT_ELF64=y CONFIG_ARC64=y CONFIG_COHERENT_IO=y @@ -38,10 +39,7 @@ # CONFIG_CPU_LITTLE_ENDIAN is not set CONFIG_NET=y CONFIG_PCI_NAMES=y - -# -# PCMCIA/CardBus support -# +# CONFIG_HOTPLUG is not set # CONFIG_PCMCIA is not set CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set diff -u --recursive --new-file v2.3.99-pre3/linux/arch/mips64/sgi-ip27/ip27-memory.c linux/arch/mips64/sgi-ip27/ip27-memory.c --- v2.3.99-pre3/linux/arch/mips64/sgi-ip27/ip27-memory.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/sgi-ip27/ip27-memory.c Mon Mar 27 10:24:56 2000 @@ -284,7 +284,7 @@ PLAT_NODE_DATA(node)->physstart = (start_pfn << PAGE_SHIFT); PLAT_NODE_DATA(node)->size = (zones_size[ZONE_DMA] << PAGE_SHIFT); free_area_init_node(node, NODE_DATA(node), zones_size, - start_pfn << PAGE_SHIFT); + start_pfn << PAGE_SHIFT, 0); PLAT_NODE_DATA(node)->start_mapnr = (NODE_DATA(node)->node_mem_map - mem_map); if ((PLAT_NODE_DATA(node)->start_mapnr + diff -u --recursive --new-file v2.3.99-pre3/linux/arch/ppc/8xx_io/enet.c linux/arch/ppc/8xx_io/enet.c --- v2.3.99-pre3/linux/arch/ppc/8xx_io/enet.c Thu Nov 18 20:25:37 1999 +++ linux/arch/ppc/8xx_io/enet.c Mon Mar 27 22:30:29 2000 @@ -63,13 +63,13 @@ * Like the LANCE driver: * The driver runs as two independent, single-threaded flows of control. One * is the send-packet routine, which enforces single-threaded use by the - * dev->tbusy flag. The other thread is the interrupt handler, which is single - * threaded by the hardware and other software. + * cep->tx_busy flag. The other thread is the interrupt handler, which is + * single threaded by the hardware and other software. * - * The send packet thread has partial control over the Tx ring and 'dev->tbusy' - * flag. It sets the tbusy flag whenever it's queuing a Tx packet. If the next - * queue slot is empty, it clears the tbusy flag when finished otherwise it sets - * the 'lp->tx_full' flag. + * The send packet thread has partial control over the Tx ring and the + * 'cep->tx_busy' flag. It sets the tx_busy flag whenever it's queuing a Tx + * packet. If the next queue slot is empty, it clears the tx_busy flag when + * finished otherwise it sets the 'lp->tx_full' flag. * * The MBX has a control register external to the MPC8xx that has some * control of the Ethernet interface. Control Register 1 has the @@ -149,8 +149,10 @@ cbd_t *dirty_tx; /* The ring entries to be free()ed. */ scc_t *sccp; struct net_device_stats stats; - char tx_full; + uint tx_full; + uint tx_busy; unsigned long lock; + int interrupt; }; static int cpm_enet_open(struct net_device *dev); @@ -190,10 +192,7 @@ * a simple way to do that. */ - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; - + netif_start_queue(dev); return 0; /* Always succeed */ } @@ -205,7 +204,7 @@ unsigned long flags; /* Transmitter timeout, serious problems. */ - if (dev->tbusy) { + if (cep->tx_busy) { int tickssofar = jiffies - dev->trans_start; if (tickssofar < 200) return 1; @@ -233,22 +232,23 @@ } #endif - dev->tbusy=0; + cep->tx_busy=0; dev->trans_start = jiffies; return 0; } /* Block a timer-based transmit from overlapping. This could better be - done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { + * done with atomic_swap(1, cep->tx_busy), but set_bit() works as well. + */ + if (test_and_set_bit(0, (void*)&cep->tx_busy) != 0) { printk("%s: Transmitter access conflict.\n", dev->name); return 1; } if (test_and_set_bit(0, (void*)&cep->lock) != 0) { printk("%s: tx queue lock!.\n", dev->name); - /* don't clear dev->tbusy flag. */ + /* don't clear cep->tx_busy flag. */ return 1; } @@ -258,7 +258,7 @@ #ifndef final_version if (bdp->cbd_sc & BD_ENET_TX_READY) { /* Ooops. All transmit buffers are full. Bail out. - * This should not happen, since dev->tbusy should be set. + * This should not happen, since cep->tx_busy should be set. */ printk("%s: tx queue full!.\n", dev->name); cep->lock = 0; @@ -314,7 +314,7 @@ if (bdp->cbd_sc & BD_ENET_TX_READY) cep->tx_full = 1; else - dev->tbusy=0; + cep->tx_busy=0; restore_flags(flags); cep->cur_tx = (cbd_t *)bdp; @@ -335,10 +335,10 @@ int must_restart; cep = (struct cpm_enet_private *)dev->priv; - if (dev->interrupt) + if (cep->interrupt) printk("%s: Re-entering the interrupt handler.\n", dev->name); - dev->interrupt = 1; + cep->interrupt = 1; /* Get the interrupt events that caused us to be here. */ @@ -399,7 +399,7 @@ /* Free the sk buffer associated with this last transmit. */ - dev_kfree_skb(cep->tx_skbuff[cep->skb_dirty]/*, FREE_WRITE*/); + dev_kfree_skb_irq(cep->tx_skbuff[cep->skb_dirty]); cep->skb_dirty = (cep->skb_dirty + 1) & TX_RING_MOD_MASK; /* Update pointer to next buffer descriptor to be transmitted. @@ -421,10 +421,10 @@ /* Since we have freed up a buffer, the ring is no longer * full. */ - if (cep->tx_full && dev->tbusy) { + if (cep->tx_full && cep->tx_busy) { cep->tx_full = 0; - dev->tbusy = 0; - mark_bh(NET_BH); + cep->tx_busy = 0; + netif_wake_queue(dev); } cep->dirty_tx = (cbd_t *)bdp; @@ -455,7 +455,7 @@ printk("CPM ENET: BSY can't happen.\n"); } - dev->interrupt = 0; + cep->interrupt = 0; return; } @@ -564,6 +564,7 @@ { /* Don't know what to do yet. */ + netif_stop_queue(dev); return 0; } diff -u --recursive --new-file v2.3.99-pre3/linux/arch/ppc/8xx_io/uart.c linux/arch/ppc/8xx_io/uart.c --- v2.3.99-pre3/linux/arch/ppc/8xx_io/uart.c Sat Oct 9 11:47:50 1999 +++ linux/arch/ppc/8xx_io/uart.c Sun Apr 2 15:38:53 2000 @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -1937,6 +1938,7 @@ printk("rs_open returning after block_til_ready with %d\n", retval); #endif + MOD_DEC_USE_COUNT; return retval; } diff -u --recursive --new-file v2.3.99-pre3/linux/arch/ppc/Makefile linux/arch/ppc/Makefile --- v2.3.99-pre3/linux/arch/ppc/Makefile Thu Feb 10 17:11:04 2000 +++ linux/arch/ppc/Makefile Mon Mar 27 22:30:29 2000 @@ -72,7 +72,7 @@ ifdef CONFIG_8xx SUBDIRS += arch/ppc/8xx_io -DRIVERS += arch/ppc/8xx_io/8xx_io.a drivers/net/net.a +DRIVERS += arch/ppc/8xx_io/8xx_io.a endif ifdef CONFIG_APUS diff -u --recursive --new-file v2.3.99-pre3/linux/arch/ppc/boot/Makefile linux/arch/ppc/boot/Makefile --- v2.3.99-pre3/linux/arch/ppc/boot/Makefile Fri Mar 10 16:40:40 2000 +++ linux/arch/ppc/boot/Makefile Thu Mar 30 16:56:04 2000 @@ -16,9 +16,9 @@ .c.o: $(CC) $(CFLAGS) -DINITRD_OFFSET=$(IOFF) -DINITRD_SIZE=$(ISZ) -DZIMAGE_OFFSET=$(ZOFF) -DZIMAGE_SIZE=$(ZSZ) -D__BOOTER__ -c -o $*.o $< .S.s: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -E -o $*.o $< + $(CPP) $(AFLAGS) -traditional -o $*.o $< .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c -o $*.o $< + $(CC) $(AFLAGS) -traditional -c -o $*.o $< ZOFF = 0 ZSZ = 0 diff -u --recursive --new-file v2.3.99-pre3/linux/arch/ppc/chrpboot/Makefile linux/arch/ppc/chrpboot/Makefile --- v2.3.99-pre3/linux/arch/ppc/chrpboot/Makefile Fri Mar 10 16:40:40 2000 +++ linux/arch/ppc/chrpboot/Makefile Thu Mar 30 16:56:04 2000 @@ -12,9 +12,9 @@ .c.o: $(CC) $(CFLAGS) -DKERNELBASE=$(KERNELBASE) -c -o $*.o $< .S.s: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -E -o $*.o $< + $(CPP) $(AFLAGS) -traditional -o $*.o $< .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c -o $*.o $< + $(CC) $(AFLAGS) -traditional -c -o $*.o $< CFLAGS = $(CPPFLAGS) -O -fno-builtin -DSTDC_HEADERS LD_ARGS = -Ttext 0x00400000 diff -u --recursive --new-file v2.3.99-pre3/linux/arch/ppc/config.in linux/arch/ppc/config.in --- v2.3.99-pre3/linux/arch/ppc/config.in Mon Mar 27 08:08:22 2000 +++ linux/arch/ppc/config.in Mon Apr 10 22:58:59 2000 @@ -83,12 +83,13 @@ comment 'General setup' define_bool CONFIG_ISA n +define_bool CONFIG_SBUS n if [ "$CONFIG_APUS" = "y" -o "$CONFIG_4xx" = "y" -o \ "$CONFIG_82xx" = "y" ]; then define_bool CONFIG_PCI n else - if [ "$CONFIG_6xx" = "y" -o CONFIG_PPC64 ]; then + if [ "$CONFIG_6xx" = "y" -o "$CONFIG_PPC64" = "y" ]; then define_bool CONFIG_PCI y else # CONFIG_8xx @@ -115,6 +116,8 @@ if [ "$CONFIG_HOTPLUG" = "y" ]; then source drivers/pcmcia/Config.in +else + define_bool CONFIG_PCMCIA n fi source drivers/parport/Config.in @@ -247,14 +250,13 @@ endmenu source drivers/char/Config.in -source drivers/usb/Config.in source fs/Config.in mainmenu_option next_comment comment 'Sound' tristate 'Sound card support' CONFIG_SOUND if [ "$CONFIG_SOUND" != "n" ]; then - dep_tristate 'Amiga or PowerMac DMA sound support' CONFIG_DMASOUND $CONFIG_SOUND + source drivers/sound/dmasound/Config.in source drivers/sound/Config.in fi @@ -263,6 +265,8 @@ if [ "$CONFIG_8xx" = "y" ]; then source arch/ppc/8xx_io/Config.in fi + +source drivers/usb/Config.in mainmenu_option next_comment comment 'Kernel hacking' diff -u --recursive --new-file v2.3.99-pre3/linux/arch/ppc/defconfig linux/arch/ppc/defconfig --- v2.3.99-pre3/linux/arch/ppc/defconfig Mon Mar 27 08:08:22 2000 +++ linux/arch/ppc/defconfig Mon Mar 27 09:38:47 2000 @@ -34,6 +34,7 @@ # General setup # # CONFIG_ISA is not set +# CONFIG_SBUS is not set CONFIG_PCI=y CONFIG_NET=y CONFIG_SYSCTL=y @@ -45,6 +46,7 @@ # CONFIG_BINFMT_MISC is not set # CONFIG_PCI_NAMES is not set # CONFIG_HOTPLUG is not set +# CONFIG_PCMCIA is not set # # Parallel port support @@ -185,6 +187,7 @@ # CONFIG_BLK_DEV_AEC6210 is not set # CONFIG_AEC6210_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_CMD64X is not set diff -u --recursive --new-file v2.3.99-pre3/linux/arch/ppc/kernel/feature.c linux/arch/ppc/kernel/feature.c --- v2.3.99-pre3/linux/arch/ppc/kernel/feature.c Tue Mar 7 14:32:25 2000 +++ linux/arch/ppc/kernel/feature.c Mon Apr 10 22:58:59 2000 @@ -184,14 +184,14 @@ if (controller_count) printk(KERN_INFO "Registered %d feature controller(s)\n", controller_count); -#ifdef CONFIG_PMAC_PBOOK -#ifdef CONFIG_DMASOUND_MODULE - /* On PowerBooks, we disable the sound chip when dmasound is a module */ +#if defined(CONFIG_PMAC_PBOOK) && !defined(CONFIG_DMASOUND_AWACS) + /* On PowerBooks, we disable the sound chip when dmasound is a module + * or not used at all + */ if (controller_count && find_devices("via-pmu") != NULL) { feature_clear(controllers[0].device, FEATURE_Sound_power); feature_clear(controllers[0].device, FEATURE_Sound_CLK_enable); } -#endif #endif } diff -u --recursive --new-file v2.3.99-pre3/linux/arch/ppc/kernel/m8xx_setup.c linux/arch/ppc/kernel/m8xx_setup.c --- v2.3.99-pre3/linux/arch/ppc/kernel/m8xx_setup.c Wed Dec 29 13:13:12 1999 +++ linux/arch/ppc/kernel/m8xx_setup.c Mon Mar 27 22:30:25 2000 @@ -276,7 +276,6 @@ int i; void cpm_interrupt_init(void); - ppc8xx_pic.irq_offset = 0; for ( i = 0 ; i < NR_SIU_INTS ; i++ ) irq_desc[i].handler = &ppc8xx_pic; diff -u --recursive --new-file v2.3.99-pre3/linux/arch/ppc/lib/Makefile linux/arch/ppc/lib/Makefile --- v2.3.99-pre3/linux/arch/ppc/lib/Makefile Mon Dec 20 18:48:21 1999 +++ linux/arch/ppc/lib/Makefile Thu Mar 30 16:56:04 2000 @@ -3,7 +3,7 @@ # .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -c $< -o $*.o + $(CC) $(AFLAGS) -c $< -o $*.o O_TARGET = lib.o O_OBJS = checksum.o string.o strcase.o diff -u --recursive --new-file v2.3.99-pre3/linux/arch/ppc/math-emu/math.c linux/arch/ppc/math-emu/math.c --- v2.3.99-pre3/linux/arch/ppc/math-emu/math.c Tue Aug 31 17:29:13 1999 +++ linux/arch/ppc/math-emu/math.c Mon Mar 27 22:30:30 2000 @@ -233,14 +233,14 @@ case LFD: idx = (insn >> 16) & 0x1f; sdisp = (insn & 0xffff); - op0 = (void *)¤t->tss.fpr[(insn >> 21) & 0x1f]; + op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; op1 = (void *)((idx ? regs->gpr[idx] : 0) + sdisp); lfd(op0, op1, op2, op3); break; case LFDU: idx = (insn >> 16) & 0x1f; sdisp = (insn & 0xffff); - op0 = (void *)¤t->tss.fpr[(insn >> 21) & 0x1f]; + op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; op1 = (void *)((idx ? regs->gpr[idx] : 0) + sdisp); lfd(op0, op1, op2, op3); regs->gpr[idx] = (unsigned long)op1; @@ -248,21 +248,21 @@ case STFD: idx = (insn >> 16) & 0x1f; sdisp = (insn & 0xffff); - op0 = (void *)¤t->tss.fpr[(insn >> 21) & 0x1f]; + op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; op1 = (void *)((idx ? regs->gpr[idx] : 0) + sdisp); stfd(op0, op1, op2, op3); break; case STFDU: idx = (insn >> 16) & 0x1f; sdisp = (insn & 0xffff); - op0 = (void *)¤t->tss.fpr[(insn >> 21) & 0x1f]; + op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; op1 = (void *)((idx ? regs->gpr[idx] : 0) + sdisp); stfd(op0, op1, op2, op3); regs->gpr[idx] = (unsigned long)op1; break; case OP63: - op0 = (void *)¤t->tss.fpr[(insn >> 21) & 0x1f]; - op1 = (void *)¤t->tss.fpr[(insn >> 11) & 0x1f]; + op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; + op1 = (void *)¤t->thread.fpr[(insn >> 11) & 0x1f]; fmr(op0, op1, op2, op3); break; default: @@ -359,28 +359,28 @@ switch (type) { case AB: - op0 = (void *)¤t->tss.fpr[(insn >> 21) & 0x1f]; - op1 = (void *)¤t->tss.fpr[(insn >> 16) & 0x1f]; - op2 = (void *)¤t->tss.fpr[(insn >> 11) & 0x1f]; + op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; + op1 = (void *)¤t->thread.fpr[(insn >> 16) & 0x1f]; + op2 = (void *)¤t->thread.fpr[(insn >> 11) & 0x1f]; break; case AC: - op0 = (void *)¤t->tss.fpr[(insn >> 21) & 0x1f]; - op1 = (void *)¤t->tss.fpr[(insn >> 16) & 0x1f]; - op2 = (void *)¤t->tss.fpr[(insn >> 6) & 0x1f]; + op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; + op1 = (void *)¤t->thread.fpr[(insn >> 16) & 0x1f]; + op2 = (void *)¤t->thread.fpr[(insn >> 6) & 0x1f]; break; case ABC: - op0 = (void *)¤t->tss.fpr[(insn >> 21) & 0x1f]; - op1 = (void *)¤t->tss.fpr[(insn >> 16) & 0x1f]; - op2 = (void *)¤t->tss.fpr[(insn >> 11) & 0x1f]; - op3 = (void *)¤t->tss.fpr[(insn >> 6) & 0x1f]; + op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; + op1 = (void *)¤t->thread.fpr[(insn >> 16) & 0x1f]; + op2 = (void *)¤t->thread.fpr[(insn >> 11) & 0x1f]; + op3 = (void *)¤t->thread.fpr[(insn >> 6) & 0x1f]; break; case D: idx = (insn >> 16) & 0x1f; sdisp = (insn & 0xffff); - op0 = (void *)¤t->tss.fpr[(insn >> 21) & 0x1f]; + op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; op1 = (void *)((idx ? regs->gpr[idx] : 0) + sdisp); break; @@ -390,22 +390,22 @@ goto illegal; sdisp = (insn & 0xffff); - op0 = (void *)¤t->tss.fpr[(insn >> 21) & 0x1f]; + op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; op1 = (void *)(regs->gpr[idx] + sdisp); break; case X: - op0 = (void *)¤t->tss.fpr[(insn >> 21) & 0x1f]; + op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; break; case XA: - op0 = (void *)¤t->tss.fpr[(insn >> 21) & 0x1f]; - op1 = (void *)¤t->tss.fpr[(insn >> 16) & 0x1f]; + op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; + op1 = (void *)¤t->thread.fpr[(insn >> 16) & 0x1f]; break; case XB: - op0 = (void *)¤t->tss.fpr[(insn >> 21) & 0x1f]; - op1 = (void *)¤t->tss.fpr[(insn >> 11) & 0x1f]; + op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; + op1 = (void *)¤t->thread.fpr[(insn >> 11) & 0x1f]; break; case XE: @@ -413,13 +413,13 @@ if (!idx) goto illegal; - op0 = (void *)¤t->tss.fpr[(insn >> 21) & 0x1f]; + op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; op1 = (void *)(regs->gpr[idx] + regs->gpr[(insn >> 11) & 0x1f]); break; case XEU: idx = (insn >> 16) & 0x1f; - op0 = (void *)¤t->tss.fpr[(insn >> 21) & 0x1f]; + op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; op1 = (void *)((idx ? regs->gpr[idx] : 0) + regs->gpr[(insn >> 11) & 0x1f]); break; @@ -427,8 +427,8 @@ case XCR: op0 = (void *)®s->ccr; op1 = (void *)((insn >> 23) & 0x7); - op2 = (void *)¤t->tss.fpr[(insn >> 16) & 0x1f]; - op3 = (void *)¤t->tss.fpr[(insn >> 11) & 0x1f]; + op2 = (void *)¤t->thread.fpr[(insn >> 16) & 0x1f]; + op3 = (void *)¤t->thread.fpr[(insn >> 11) & 0x1f]; break; case XCRL: @@ -448,7 +448,7 @@ case XFLB: op0 = (void *)((insn >> 17) & 0xff); - op1 = (void *)¤t->tss.fpr[(insn >> 11) & 0x1f]; + op1 = (void *)¤t->thread.fpr[(insn >> 11) & 0x1f]; break; default: diff -u --recursive --new-file v2.3.99-pre3/linux/arch/ppc/math-emu/sfp-machine.h linux/arch/ppc/math-emu/sfp-machine.h --- v2.3.99-pre3/linux/arch/ppc/math-emu/sfp-machine.h Tue Aug 31 17:29:13 1999 +++ linux/arch/ppc/math-emu/sfp-machine.h Mon Mar 27 22:30:29 2000 @@ -166,7 +166,7 @@ #include #include -#define __FPU_FPSCR (current->tss.fpscr) +#define __FPU_FPSCR (current->thread.fpscr) /* We only actually write to the destination register * if exceptions signalled (if any) will not trap. diff -u --recursive --new-file v2.3.99-pre3/linux/arch/ppc/mbxboot/Makefile linux/arch/ppc/mbxboot/Makefile --- v2.3.99-pre3/linux/arch/ppc/mbxboot/Makefile Fri Mar 10 16:40:40 2000 +++ linux/arch/ppc/mbxboot/Makefile Thu Mar 30 16:56:04 2000 @@ -16,9 +16,9 @@ .c.o: $(CC) $(CFLAGS) -DINITRD_OFFSET=$(IOFF) -DINITRD_SIZE=$(ISZ) -DZIMAGE_OFFSET=$(ZOFF) -DZIMAGE_SIZE=$(ZSZ) -c -o $*.o $< .S.s: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -E -o $*.o $< + $(CPP) $(AFLAGS) -traditional -o $*.o $< .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c -o $*.o $< + $(CC) $(AFLAGS) -traditional -c -o $*.o $< ZOFF = 0 ZSZ = 0 @@ -26,7 +26,7 @@ ISZ = 0 TFTPIMAGE=/tftpboot/zImage.mbx -ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00100000 +ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00180000 OBJECTS := head.o misc.o ../coffboot/zlib.o m8xx_tty.o CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS -fno-builtin -DCONFIG_8xx diff -u --recursive --new-file v2.3.99-pre3/linux/arch/ppc/mm/fault.c linux/arch/ppc/mm/fault.c --- v2.3.99-pre3/linux/arch/ppc/mm/fault.c Tue Dec 7 09:32:42 1999 +++ linux/arch/ppc/mm/fault.c Mon Mar 27 22:30:30 2000 @@ -182,34 +182,44 @@ #ifdef CONFIG_8xx -unsigned long va_to_phys(unsigned long address) +/* The pgtable.h claims some functions generically exist, but I + * can't find them...... + */ +pte_t *find_pte(struct mm_struct *mm, unsigned long address) { pgd_t *dir; pmd_t *pmd; pte_t *pte; - - dir = pgd_offset(current->mm, address & PAGE_MASK); - if (dir) - { + + dir = pgd_offset(mm, address & PAGE_MASK); + if (dir) { pmd = pmd_offset(dir, address & PAGE_MASK); - if (pmd && pmd_present(*pmd)) - { + if (pmd && pmd_present(*pmd)) { pte = pte_offset(pmd, address & PAGE_MASK); - if (pte && pte_present(*pte)) - { - return(pte_page(*pte) | (address & ~(PAGE_MASK-1))); + if (pte && pte_present(*pte)) { + return(pte); } - } else - { + } + else { return (0); } - } else - { + } + else { return (0); } return (0); } +unsigned long va_to_phys(unsigned long address) +{ + pte_t *pte; + + pte = find_pte(current->mm, address); + if (pte) + return((unsigned long)(pte_page(*pte)) | (address & ~(PAGE_MASK-1))); + return (0); +} + void print_8xx_pte(struct mm_struct *mm, unsigned long addr) { @@ -227,8 +237,8 @@ printk(" (0x%08lx)->(0x%08lx)->0x%08lx\n", (long)pgd, (long)pte, (long)pte_val(*pte)); #define pp ((long)pte_val(*pte)) - printk(" RPN: %05x PP: %x SPS: %x SH: %x " - "CI: %x v: %x\n", + printk(" RPN: %05x PP: %x SPS: %x SH: %lx " + "CI: %lx v: %lx\n", pp>>12, /* rpn */ (pp>>10)&3, /* pp */ (pp>>3)&1, /* small */ diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sh/Makefile linux/arch/sh/Makefile --- v2.3.99-pre3/linux/arch/sh/Makefile Tue Mar 7 14:32:25 2000 +++ linux/arch/sh/Makefile Mon Mar 27 10:26:15 2000 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.2 1999/12/23 12:13:53 gniibe Exp gniibe $ +# $Id: Makefile,v 1.4 2000/03/08 15:14:14 gniibe 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 diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sh/config.in linux/arch/sh/config.in --- v2.3.99-pre3/linux/arch/sh/config.in Mon Mar 27 08:08:22 2000 +++ linux/arch/sh/config.in Mon Mar 27 10:26:15 2000 @@ -48,6 +48,7 @@ comment 'General setup' define_bool CONFIG_ISA n +define_bool CONFIG_SBUS n bool 'Networking support' CONFIG_NET @@ -73,6 +74,8 @@ if [ "$CONFIG_HOTPLUG" = "y" ] ; then source drivers/pcmcia/Config.in +else + define_bool CONFIG_PCMCIA n fi bool 'System V IPC' CONFIG_SYSVIPC @@ -169,8 +172,6 @@ if [ "$CONFIG_HOTPLUG" = "y" -a "$CONFIG_PCMCIA" != "n" ]; then source drivers/char/pcmcia/Config.in fi - -#source drivers/misc/Config.in source fs/Config.in diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sh/defconfig linux/arch/sh/defconfig --- v2.3.99-pre3/linux/arch/sh/defconfig Mon Mar 27 08:08:22 2000 +++ linux/arch/sh/defconfig Mon Mar 27 09:38:47 2000 @@ -29,10 +29,12 @@ # General setup # # CONFIG_ISA is not set +# CONFIG_SBUS is not set # CONFIG_NET is not set CONFIG_CF_ENABLER=y # CONFIG_PCI 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 is not set diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sh/kernel/Makefile linux/arch/sh/kernel/Makefile --- v2.3.99-pre3/linux/arch/sh/kernel/Makefile Tue Mar 7 14:32:25 2000 +++ linux/arch/sh/kernel/Makefile Thu Mar 30 16:56:04 2000 @@ -7,7 +7,7 @@ # .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o + $(CC) $(AFLAGS) -traditional -c $< -o $*.o O_TARGET := kernel.o O_OBJS := process.o signal.o entry.o traps.o irq.o irq_onchip.o \ @@ -29,7 +29,7 @@ entry.o: entry.S head.o: head.S - $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $*.S -o $*.o + $(CC) $(AFLAGS) -traditional -c $*.S -o $*.o clean: diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sh/kernel/entry.S linux/arch/sh/kernel/entry.S --- v2.3.99-pre3/linux/arch/sh/kernel/entry.S Tue Mar 7 14:32:25 2000 +++ linux/arch/sh/kernel/entry.S Mon Mar 27 10:26:15 2000 @@ -1,4 +1,4 @@ -/* $Id: entry.S,v 1.55 2000/03/05 01:48:58 gniibe Exp $ +/* $Id: entry.S,v 1.71 2000/03/22 13:29:33 gniibe Exp $ * * linux/arch/sh/entry.S * @@ -33,10 +33,9 @@ * * syscall # * ssr - * r15 = stack pointer * r0 * ... - * r14 + * r15 = stack pointer * gbr * mach * macl @@ -46,7 +45,7 @@ */ /* - * these are offsets into the task-struct. + * These are offsets into the task-struct. */ state = 0 flags = 4 @@ -78,8 +77,8 @@ /* Offsets to the stack */ SYSCALL_NR = 0 SR = 4 -SP = 8 -R0 = 12 +R0 = 8 +SP = (8+15*4) #define k0 r0 #define k1 r1 @@ -96,7 +95,7 @@ k2 scratch (Exception code) k3 scratch (Return address) k4 Stack base = current+8192 - k5 reserved + k5 Global Interrupt Mask (0--15) k6 reserved k7 reserved */ @@ -115,109 +114,113 @@ ! this first version depends *much* on C implementation. ! -#define DO_FAULT(write) \ - mov.l 4f,r0; \ - mov.l @r0,r6; \ - /* STI */ \ - mov.l 3f,r1; \ - stc sr,r0; \ - and r1,r0; \ - ldc r0,sr; \ - /* */ \ - mov r15,r4; \ - mov.l 2f,r0; \ - jmp @r0; \ - mov #write,r5; +#define RESTORE_FLAGS() \ + mov.l @(SR,$r15), $r0; \ + and #0xf0, $r0; \ + shlr8 $r0; \ + cmp/eq #0x0f, $r0; \ + bt 9f; \ + mov.l __INV_IMASK, $r1; \ + stc $sr, $r0; \ + and $r1, $r0; \ + stc $r5_bank, $r1; \ + or $r1, $r0; \ + ldc $r0, $sr .balign 4 tlb_protection_violation_load: tlb_miss_load: - mov #-1,r0 - mov.l r0,@r15 ! syscall nr = -1 - DO_FAULT(0) + mov #-1, $r0 + mov.l $r0, @$r15 ! syscall nr = -1 + mov.l 2f, $r0 + mov.l @$r0, $r6 + RESTORE_FLAGS() +9: mov $r15, $r4 + mov.l 1f, $r0 + jmp @$r0 + mov #0, $r5 .balign 4 tlb_protection_violation_store: tlb_miss_store: initial_page_write: - mov #-1,r0 - mov.l r0,@r15 ! syscall nr = -1 - DO_FAULT(1) + mov #-1, $r0 + mov.l $r0, @$r15 ! syscall nr = -1 + mov.l 2f, $r0 + mov.l @$r0, $r6 + RESTORE_FLAGS() +9: mov $r15, $r4 + mov.l 1f, $r0 + jmp @$r0 + mov #1, $r5 .balign 4 -2: .long SYMBOL_NAME(do_page_fault) -3: .long 0xefffffff ! BL=0 -4: .long MMU_TEA +1: .long SYMBOL_NAME(do_page_fault) +2: .long MMU_TEA #ifdef CONFIG_DEBUG_KERNEL_WITH_GDB_STUB .balign 4 /* Unwind the stack and jmp to the debug entry */ debug: - add #4,r15 ! skip syscall number - mov.l @r15+,r11 ! SSR - mov.l @r15+,r10 ! original stack - mov.l @r15+,r0 - mov.l @r15+,r1 - mov.l @r15+,r2 - mov.l @r15+,r3 - mov.l @r15+,r4 - mov.l @r15+,r5 - mov.l @r15+,r6 - mov.l @r15+,r7 - stc sr,r14 - mov.l 8f,r9 ! BL =1, RB=1 - or r9,r14 - ldc r14,sr ! here, change the register bank - mov r10,k0 - mov r11,k1 - mov.l @r15+,r8 - mov.l @r15+,r9 - mov.l @r15+,r10 - mov.l @r15+,r11 - mov.l @r15+,r12 - mov.l @r15+,r13 - mov.l @r15+,r14 - ldc.l @r15+,gbr - lds.l @r15+,mach - lds.l @r15+,macl - lds.l @r15+,pr - ldc.l @r15+,spc - mov k0,r15 - ! - mov.l 9f,k0 - jmp @k0 - ldc k1,ssr + add #4, $r15 ! skip syscall number + mov.l @$r15+, $r11 ! SSR + mov.l @$r15+, $r0 + mov.l @$r15+, $r1 + mov.l @$r15+, $r2 + mov.l @$r15+, $r3 + mov.l @$r15+, $r4 + mov.l @$r15+, $r5 + mov.l @$r15+, $r6 + mov.l @$r15+, $r7 + stc $sr, $r14 + mov.l 1f, $r9 ! BL =1, RB=1 + or $r9, $r14 + ldc $r14, $sr ! here, change the register bank + mov $r11, $k1 + mov.l @$r15+, $r8 + mov.l @$r15+, $r9 + mov.l @$r15+, $r10 + mov.l @$r15+, $r11 + mov.l @$r15+, $r12 + mov.l @$r15+, $r13 + mov.l @$r15+, $r14 + mov.l @$r15+, $k0 + ldc.l @$r15+, $gbr + lds.l @$r15+, $mach + lds.l @$r15+, $macl + lds.l @$r15+, $pr + ldc.l @$r15+, $spc + mov $k0, $r15 + ! + mov.l 2f, $k0 + jmp @$k0 + ldc $k1, $ssr .balign 4 -8: .long 0x300000f0 -9: .long 0xa0000100 +1: .long 0x300000f0 +2: .long 0xa0000100 #endif .balign 4 error: - ! STI - mov.l 2f,r1 - stc sr,r0 - and r1,r0 - ldc r0,sr - ! - mov.l 1f,r1 - mov #-1,r0 - jmp @r1 - mov.l r0,@r15 ! syscall nr = -1 + ! + RESTORE_FLAGS() +9: mov.l 1f, $r1 + mov #-1, $r0 + jmp @$r1 + mov.l $r0, @$r15 ! syscall nr = -1 .balign 4 1: .long SYMBOL_NAME(do_exception_error) -2: .long 0xefffffff ! BL=0 -badsys: mov #-ENOSYS,r0 +badsys: mov #-ENOSYS, $r0 rts ! go to ret_from_syscall.. - mov.l r0,@(R0,r15) + mov.l $r0, @(R0,$r15) ! ! ! ENTRY(ret_from_fork) bra SYMBOL_NAME(ret_from_syscall) - add #4,r15 ! pop down bogus r0 (see switch_to MACRO) + add #4, $r15 ! pop down bogus r0 (see switch_to MACRO) ! ! The immediate value of "trapa" indicates the number of arguments @@ -226,83 +229,77 @@ ! Note that TRA register contains the value = Imm x 4. ! system_call: - mov.l 1f,r2 - mov.l @r2,r8 + mov.l 1f, $r2 + mov.l @$r2, $r8 ! ! DEBUG DEBUG - ! mov.l led,r1 - ! mov r0,r2 - ! mov.b r2,@r1 + ! mov.l led, $r1 + ! mov $r0, $r2 + ! mov.b $r2, @$r1 ! #ifdef CONFIG_DEBUG_KERNEL_WITH_GDB_STUB - mov #0x20,r1 - extu.b r1,r1 - shll2 r1 - cmp/hs r1,r8 + mov #0x20, $r1 + extu.b $r1, $r1 + shll2 $r1 + cmp/hs $r1, $r8 bt debug #endif - ! STI - mov.l 2f,r1 - stc sr,r2 - and r1,r2 - ldc r2,sr - ! - mov.l __n_sys,r1 - cmp/hs r1,r0 - bt/s badsys - mov r0,r2 - ! - stc ksp,r1 ! - mov.l __tsk_flags,r0 ! - add r0,r1 ! - mov.l @r1,r0 ! Is it trace? - tst #PF_TRACESYS,r0 + ! + mov $r0, $r2 + RESTORE_FLAGS() +9: mov.l __n_sys, $r1 + cmp/hs $r1, $r2 + bt badsys + ! + stc $ksp, $r1 + mov.l __tsk_flags, $r0 + add $r0, $r1 ! + mov.l @$r1, $r0 ! Is it trace? + tst #PF_TRACESYS, $r0 bt 5f ! Trace system call - mov #-ENOSYS,r1 - mov.l r1,@(R0,r15) - mov.l 3f,r1 - jsr @r1 + mov #-ENOSYS, $r1 + mov.l $r1, @(R0,$r15) + mov.l 3f, $r1 + jsr @$r1 nop - mova 4f,r0 + mova 3f, $r0 bra 6f - lds r0,pr + lds $r0, $pr ! -5: mova ret,r0 ! normal case - lds r0,pr - ! Build the stack frame if TRA > 0 - ! -6: mov r2,r3 - mov r8,r2 - cmp/pl r8 - bf 9f - mov.l @(SP,r15),r0 ! get original stack -7: add #-4,r8 -8: mov.l @(r0,r8),r1 ! May cause address error exception.. - mov.l r1,@-r15 - cmp/pl r8 +5: mova syscall_ret, $r0 + lds $r0, $pr + ! Build the stack frame if TRA > 0 +6: mov $r2, $r3 + mov $r8, $r2 + cmp/pl $r8 + bf 0f + mov #SP, $r0 + mov.l @($r0,$r15), $r0 ! get original stack +7: add #-4, $r8 +4: mov.l @($r0,$r8), $r1 ! May cause address error exception.. + mov.l $r1, @-$r15 + cmp/pl $r8 bt 7b ! -9: mov r3,r0 - shll2 r0 ! x4 - mov.l __sct,r1 - add r1,r0 - mov.l @r0,r1 - jmp @r1 - mov r2,r8 - +0: mov $r3, $r0 + shll2 $r0 ! x4 + mov.l __sct, $r1 + add $r1, $r0 + mov.l @$r0, $r1 + jmp @$r1 + mov $r2, $r8 ! In case of trace .balign 4 -4: add r8,r15 ! pop off the arguments - mov.l r0,@(R0,r15) ! save the return value - mov.l 3f,r1 - mova SYMBOL_NAME(ret_from_syscall),r0 - jmp @r1 - lds r0,pr +3: add $r8, $r15 ! pop off the arguments + mov.l $r0, @(R0,$r15) ! save the return value + mov.l 2f, $r1 + mova SYMBOL_NAME(ret_from_syscall), $r0 + jmp @$r1 + lds $r0, $pr .balign 4 -3: .long SYMBOL_NAME(syscall_trace) -2: .long 0xefffffff ! BL=0 1: .long TRA +2: .long SYMBOL_NAME(syscall_trace) __n_sys: .long NR_syscalls __sct: .long SYMBOL_NAME(sys_call_table) __tsk_flags: .long flags-8192 ! offset from stackbase to tsk->flags @@ -311,85 +308,80 @@ .section .fixup,"ax" fixup_syscall_argerr: rts - mov.l 1f,r0 + mov.l 1f, $r0 1: .long -22 ! -EINVAL .previous .section __ex_table, "a" .balign 4 - .long 8b,fixup_syscall_argerr + .long 4b,fixup_syscall_argerr .previous + .balign 4 reschedule: - mova SYMBOL_NAME(ret_from_syscall),r0 - mov.l 1f,r1 - jmp @r1 - lds r0,pr + mova SYMBOL_NAME(ret_from_syscall), $r0 + mov.l 1f, $r1 + jmp @$r1 + lds $r0, $pr .balign 4 1: .long SYMBOL_NAME(schedule) ENTRY(ret_from_irq) - mov.l @(SR,r15),r0 ! get status register - shll r0 - shll r0 ! kernel space? + mov.l @(SR,$r15), $r0 ! get status register + shll $r0 + shll $r0 ! kernel space? bt restore_all ! Yes, it's from kernel, go back soon - ! STI - mov.l 1f, $r1 - stc $sr, $r2 - and $r1, $r2 - ldc $r2, $sr ! - bra ret_with_reschedule + RESTORE_FLAGS() +9: bra ret_with_reschedule nop ENTRY(ret_from_exception) - mov.l @(SR,r15),r0 ! get status register - shll r0 - shll r0 ! kernel space? + mov.l @(SR,$r15), $r0 ! get status register + shll $r0 + shll $r0 ! kernel space? bt restore_all ! Yes, it's from kernel, go back soon - ! STI - mov.l 1f, $r1 - stc $sr, $r2 - and $r1, $r2 - ldc $r2, $sr ! - bra ret_from_syscall + RESTORE_FLAGS() +9: bra ret_from_syscall nop .balign 4 -1: .long 0xefffffff ! BL=0 +__INV_IMASK: + .long 0xffffff0f ! ~(IMASK) .balign 4 -ret: add r8,r15 ! pop off the arguments - mov.l r0,@(R0,r15) ! save the return value +syscall_ret: + add $r8, $r15 ! pop off the arguments + mov.l $r0, @(R0,$r15) ! save the return value /* fall through */ ENTRY(ret_from_syscall) - mov.l __softirq_state,r0 - mov.l @r0,r1 - mov.l @(4,r0),r2 - tst r2,r1 + mov.l __softirq_state, $r0 + mov.l @$r0, $r1 + mov.l @(4,$r0), $r2 + tst $r2, $r1 bt ret_with_reschedule handle_softirq: - mov.l __do_softirq,r0 - jsr @r0 + mov.l __do_softirq, $r0 + jsr @$r0 nop ret_with_reschedule: - stc ksp,r1 - mov.l __minus8192,r0 - add r0,r1 - mov.l @(need_resched,r1),r0 - tst #0xff,r0 + stc $ksp, $r1 + mov.l __minus8192, $r0 + add $r0, $r1 + mov.l @(need_resched,$r1), $r0 + tst #0xff, $r0 bf reschedule - mov.l @(sigpending,r1),r0 - tst #0xff,r0 + mov.l @(sigpending,$r1), $r0 + tst #0xff, $r0 bt restore_all signal_return: - mov r15,r4 - mov #0,r5 - mov.l __do_signal,r1 - mova restore_all,r0 - jmp @r1 - lds r0,pr + mov $r15, $r4 + mov #0, $r5 + mov.l __do_signal, $r1 + mova restore_all, $r0 + jmp @$r1 + lds $r0, $pr .balign 4 __do_signal: .long SYMBOL_NAME(do_signal) @@ -407,56 +399,57 @@ jsr @$r1 stc $sr, $r4 #endif - add #4,r15 ! Skip syscall number - mov.l @r15+,r11 ! Got SSR into R11 + add #4, $r15 ! Skip syscall number + mov.l @$r15+, $r11 ! Got SSR into R11 #if defined(__SH4__) mov $r11, $r12 #endif ! - mov.l 1f,r1 - stc sr,r0 - and r1,r0 ! Get IMASK+FD - mov.l 2f,r1 - and r1,r11 - or r0,r11 ! Inherit the IMASK+FD value of SR - ! - mov.l @r15+,r10 ! original stack - mov.l @r15+,r0 - mov.l @r15+,r1 - mov.l @r15+,r2 - mov.l @r15+,r3 - mov.l @r15+,r4 - mov.l @r15+,r5 - mov.l @r15+,r6 - mov.l @r15+,r7 - stc sr,r14 - mov.l __blrb_flags,r9 ! BL =1, RB=1 - or r9,r14 - ldc r14,sr ! here, change the register bank - mov r10,k0 - mov r11,k1 + mov.l 1f, $r1 + stc $sr, $r0 + and $r1, $r0 ! Get FD + mov.l 2f, $r1 + and $r1, $r11 + or $r0, $r11 ! Inherit the FD value of SR + stc $r5_bank, $r0 + or $r0, $r11 ! Inherit the IMASK value + ! + mov.l @$r15+, $r0 + mov.l @$r15+, $r1 + mov.l @$r15+, $r2 + mov.l @$r15+, $r3 + mov.l @$r15+, $r4 + mov.l @$r15+, $r5 + mov.l @$r15+, $r6 + mov.l @$r15+, $r7 + stc $sr, $r14 + mov.l __blrb_flags, $r9 ! BL =1, RB=1 + or $r9, $r14 + ldc $r14, $sr ! here, change the register bank + mov $r11, $k1 #if defined(__SH4__) mov $r12, $k2 #endif - mov.l @r15+,r8 - mov.l @r15+,r9 - mov.l @r15+,r10 - mov.l @r15+,r11 - mov.l @r15+,r12 - mov.l @r15+,r13 - mov.l @r15+,r14 - ldc.l @r15+,gbr - lds.l @r15+,mach - lds.l @r15+,macl - lds.l @r15+,pr - ldc.l @r15+,spc - ldc k1,ssr + mov.l @$r15+, $r8 + mov.l @$r15+, $r9 + mov.l @$r15+, $r10 + mov.l @$r15+, $r11 + mov.l @$r15+, $r12 + mov.l @$r15+, $r13 + mov.l @$r15+, $r14 + mov.l @$r15+, $k0 ! original stack + ldc.l @$r15+, $gbr + lds.l @$r15+, $mach + lds.l @$r15+, $macl + lds.l @$r15+, $pr + ldc.l @$r15+, $spc + ldc $k1, $ssr #if defined(__SH4__) shll $k1 shll $k1 bf 9f ! user mode /* Kernel to kernel transition */ - mov.l 3f, $k1 + mov.l 1f, $k1 tst $k1, $k2 bf 9f ! it hadn't FPU ! Kernel to kernel and FPU was used @@ -496,7 +489,7 @@ lds.l @$r15+, $fpul 9: #endif - mov k0,r15 + mov $k0, $r15 rte nop @@ -510,9 +503,8 @@ __PF_USEDFPU: .long PF_USEDFPU #endif -1: .long 0x000080f0 ! IMASK+FD +1: .long 0x00008000 ! FD 2: .long 0xffff7f0f ! ~(IMASK+FD) -3: .long 0x00008000 ! FD=1 ! Exception Vector Base ! @@ -524,10 +516,10 @@ ! .balign 256,0,256 general_exception: - mov.l 1f,k2 - mov.l 2f,k3 + mov.l 1f, $k2 + mov.l 2f, $k3 bra handle_exception - mov.l @k2,k2 + mov.l @$k2, $k2 .balign 4 2: .long SYMBOL_NAME(ret_from_exception) 1: .long EXPEVT @@ -535,17 +527,17 @@ ! .balign 1024,0,1024 tlb_miss: - mov.l 1f,k2 - mov.l 4f,k3 + mov.l 1f, $k2 + mov.l 4f, $k3 bra handle_exception - mov.l @k2,k2 + mov.l @$k2, $k2 ! .balign 512,0,512 interrupt: - mov.l 2f,k2 - mov.l 3f,k3 + mov.l 2f, $k2 + mov.l 3f, $k3 bra handle_exception - mov.l @k2,k2 + mov.l @$k2, $k2 .balign 4 1: .long EXPEVT @@ -559,9 +551,9 @@ ! Using k0, k1 for scratch registers (r0_bank1, r1_bank), ! save all registers onto stack. ! - stc ssr,k0 ! from kernel space? - shll k0 ! Check MD bit (bit30) - shll k0 + stc $ssr, $k0 ! from kernel space? + shll $k0 ! Check MD bit (bit30) + shll $k0 #if defined(__SH4__) bf/s 8f ! it's from user to kernel transition mov $r15, $k0 ! save original stack to k0 @@ -569,6 +561,7 @@ mov.l 2f, $k1 stc $ssr, $k0 tst $k1, $k0 + mov.l 4f, $k1 bf/s 9f ! FPU is not used mov $r15, $k0 ! save original stack to k0 ! FPU is used, save FPU @@ -593,64 +586,63 @@ fmov.s $fr1, @-$r15 fmov.s $fr0, @-$r15 bra 9f - mov #0, $k1 + mov.l 3f, $k1 #else + mov.l 3f, $k1 bt/s 9f ! it's from kernel to kernel transition - mov r15,k0 ! save original stack to k0 anyway + mov $r15, $k0 ! save original stack to k0 anyway #endif 8: /* User space to kernel */ - mov kernel_sp, $r15 ! change to kernel stack -#if defined(__SH4__) - mov.l 2f, $k1 ! let kernel release FPU -#endif -9: stc.l spc,@-r15 - sts.l pr,@-r15 - ! - lds k3,pr ! Set the return address to pr - ! - sts.l macl,@-r15 - sts.l mach,@-r15 - stc.l gbr,@-r15 - mov.l r14,@-r15 - ! - stc sr,r14 ! Back to normal register bank, and -#if defined(__SH4__) - or $k1, $r14 ! may release FPU -#endif - mov.l 3f,k1 - and k1,r14 ! ... - ldc r14,sr ! ...changed here. - ! - mov.l r13,@-r15 - mov.l r12,@-r15 - mov.l r11,@-r15 - mov.l r10,@-r15 - mov.l r9,@-r15 - mov.l r8,@-r15 - mov.l r7,@-r15 - mov.l r6,@-r15 - mov.l r5,@-r15 - mov.l r4,@-r15 - mov.l r3,@-r15 - mov.l r2,@-r15 - mov.l r1,@-r15 - mov.l r0,@-r15 - stc.l r0_bank,@-r15 ! save orignal stack - stc.l ssr,@-r15 - mov.l r0,@-r15 ! push r0 again (for syscall number) + mov $kernel_sp, $r15 ! change to kernel stack + mov.l 4f, $k1 ! let kernel release FPU +9: stc.l $spc, @-$r15 + sts.l $pr, @-$r15 + ! + lds $k3, $pr ! Set the return address to pr + ! + sts.l $macl, @-$r15 + sts.l $mach, @-$r15 + stc.l $gbr, @-$r15 + mov.l $k0, @-$r15 ! save orignal stack + mov.l $r14, @-$r15 + ! + stc $sr, $r14 ! Back to normal register bank, and + or $k1, $r14 ! Block all interrupts, may release FPU + mov.l 5f, $k1 + and $k1, $r14 ! ... + ldc $r14, $sr ! ...changed here. + ! + mov.l $r13, @-$r15 + mov.l $r12, @-$r15 + mov.l $r11, @-$r15 + mov.l $r10, @-$r15 + mov.l $r9, @-$r15 + mov.l $r8, @-$r15 + mov.l $r7, @-$r15 + mov.l $r6, @-$r15 + mov.l $r5, @-$r15 + mov.l $r4, @-$r15 + mov.l $r3, @-$r15 + mov.l $r2, @-$r15 + mov.l $r1, @-$r15 + mov.l $r0, @-$r15 + stc.l $ssr, @-$r15 + mov.l $r0, @-$r15 ! push $r0 again (for syscall number) ! Then, dispatch to the handler, according to the excepiton code. - stc k_ex_code,r1 - shlr2 r1 - shlr r1 - mov.l 1f,r0 - add r1,r0 - mov.l @r0,r0 - jmp @r0 - mov.l @r15,r0 ! recovering r0.. + stc $k_ex_code, $r1 + shlr2 $r1 + shlr $r1 + mov.l 1f, $r0 + add $r1, $r0 + mov.l @$r0, $r0 + jmp @$r0 + mov.l @$r15, $r0 ! recovering $r0.. .balign 4 1: .long SYMBOL_NAME(exception_handling_table) 2: .long 0x00008000 ! FD=1 -3: .long 0xdfffffff ! RB=0, leave BL=1 +3: .long 0x000000f0 ! FD=0, IMASK=15 +4: .long 0x000080f0 ! FD=1, IMASK=15 +5: .long 0xcfffffff ! RB=0, BL=0 none: rts @@ -679,7 +671,7 @@ ENTRY(nmi_slot) .long none ! Not implemented yet ENTRY(user_break_point_trap) - .long error ! Not implemented yet + .long break_point_trap ENTRY(interrupt_table) ! external hardware .long SYMBOL_NAME(do_IRQ) ! 0000 @@ -985,6 +977,8 @@ .long SYMBOL_NAME(sys_setfsuid) /* 215 */ .long SYMBOL_NAME(sys_setfsgid) .long SYMBOL_NAME(sys_pivot_root) + .long SYMBOL_NAME(sys_mincore) + .long SYMBOL_NAME(sys_madvise) /* * NOTE!! This doesn't have to be exact - we just have @@ -992,7 +986,7 @@ * entries. Don't panic if you notice that this hasn't * been shrunk every time we add a new system call. */ - .rept NR_syscalls-217 + .rept NR_syscalls-219 .long SYMBOL_NAME(sys_ni_syscall) .endr diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sh/kernel/fpu.c linux/arch/sh/kernel/fpu.c --- v2.3.99-pre3/linux/arch/sh/kernel/fpu.c Tue Mar 7 14:32:25 2000 +++ linux/arch/sh/kernel/fpu.c Mon Mar 27 10:26:15 2000 @@ -1,4 +1,4 @@ -/* $Id: fpu.c,v 1.27 2000/03/05 01:48:34 gniibe Exp $ +/* $Id: fpu.c,v 1.29 2000/03/22 13:42:10 gniibe Exp $ * * linux/arch/sh/kernel/fpu.c * @@ -114,8 +114,6 @@ * has the property that no matter wether considered as single or as * double precission represents signaling NANS. */ -/* Double presision, NANS as NANS, rounding to nearest, no exceptions */ -#define FPU_DEFAULT 0x00080000 void fpu_init(void) { @@ -156,7 +154,7 @@ "fsts $fpul, $fr15\n\t" "frchg" : /* no output */ - : "r" (0), "r" (FPU_DEFAULT)); + : "r" (0), "r" (FPSCR_INIT)); } asmlinkage void diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sh/kernel/head.S linux/arch/sh/kernel/head.S --- v2.3.99-pre3/linux/arch/sh/kernel/head.S Tue Mar 7 14:32:25 2000 +++ linux/arch/sh/kernel/head.S Mon Mar 27 10:26:15 2000 @@ -1,4 +1,4 @@ -/* $Id: head.S,v 1.16 2000/03/02 00:01:15 gniibe Exp $ +/* $Id: head.S,v 1.17 2000/03/06 12:44:24 gniibe Exp $ * * arch/sh/kernel/head.S * @@ -37,8 +37,11 @@ */ ENTRY(_stext) ! Initialize Status Register - mov.l 1f, $r0 ! MD=1, RB=0, BL=1 + mov.l 1f, $r0 ! MD=1, RB=0, BL=0, IMASK=0xF ldc $r0, $sr + ! Initialize global interrupt mask + mov #0, $r0 + ldc $r0, $r5_bank ! mov.l 2f, $r0 mov $r0, $r15 ! Set initial r15 (stack pointer) @@ -62,7 +65,7 @@ nop .balign 4 -1: .long 0x50000000 ! MD=1, RB=0, BL=1, FD=0 +1: .long 0x400000F0 ! MD=1, RB=0, BL=0, FD=0, IMASK=0xF 2: .long SYMBOL_NAME(stack) 3: .long SYMBOL_NAME(__bss_start) 4: .long SYMBOL_NAME(_end) diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sh/kernel/irq.c linux/arch/sh/kernel/irq.c --- v2.3.99-pre3/linux/arch/sh/kernel/irq.c Tue Mar 7 14:32:25 2000 +++ linux/arch/sh/kernel/irq.c Mon Mar 27 10:26:15 2000 @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.11 2000/02/29 11:03:40 gniibe Exp $ +/* $Id: irq.c,v 1.12 2000/03/06 14:07:50 gniibe Exp $ * * linux/arch/sh/kernel/irq.c * @@ -238,11 +238,11 @@ regs.syscall_nr = -1; /* It's not system call */ /* Get IRQ number */ - asm volatile("stc r2_bank,%0\n\t" + asm volatile("stc $r2_bank, %0\n\t" "shlr2 %0\n\t" "shlr2 %0\n\t" "shlr %0\n\t" - "add #-16,%0\n\t" + "add #-16, %0\n\t" :"=z" (irq)); kstat.irqs[cpu][irq]++; diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sh/kernel/irq_imask.c linux/arch/sh/kernel/irq_imask.c --- v2.3.99-pre3/linux/arch/sh/kernel/irq_imask.c Tue Mar 7 14:32:25 2000 +++ linux/arch/sh/kernel/irq_imask.c Mon Mar 27 10:26:15 2000 @@ -1,8 +1,8 @@ -/* $Id: irq_imask.c,v 1.2 2000/02/11 04:57:40 gniibe Exp $ +/* $Id: irq_imask.c,v 1.6 2000/03/06 14:11:32 gniibe Exp $ * * linux/arch/sh/kernel/irq_imask.c * - * Copyright (C) 1999 Niibe Yutaka + * Copyright (C) 1999, 2000 Niibe Yutaka * * Simple interrupt handling using IMASK of SR register. * @@ -52,35 +52,40 @@ end_imask_irq }; -void disable_imask_irq(unsigned int irq) +void static inline set_interrupt_registers(int ip) { unsigned long __dummy; + asm volatile("ldc %2, $r5_bank\n\t" + "stc $sr, %0\n\t" + "and #0xf0, %0\n\t" + "shlr8 %0\n\t" + "cmp/eq #0x0f, %0\n\t" + "bt 1f ! CLI-ed\n\t" + "stc $sr, %0\n\t" + "and %1, %0\n\t" + "or %2, %0\n\t" + "ldc %0, $sr\n" + "1:" + : "=&z" (__dummy) + : "r" (~0xf0), "r" (ip << 4)); +} + +void disable_imask_irq(unsigned int irq) +{ clear_bit(irq, &imask_mask); if (interrupt_priority < IMASK_PRIORITY - irq) interrupt_priority = IMASK_PRIORITY - irq; - asm volatile("stc sr,%0\n\t" - "and %1,%0\n\t" - "or %2,%0\n\t" - "ldc %0,sr" - : "=&r" (__dummy) - : "r" (0xffffff0f), "r" (interrupt_priority << 4)); + set_interrupt_registers(interrupt_priority); } static void enable_imask_irq(unsigned int irq) { - unsigned long __dummy; - set_bit(irq, &imask_mask); interrupt_priority = IMASK_PRIORITY - ffz(imask_mask); - asm volatile("stc sr,%0\n\t" - "and %1,%0\n\t" - "or %2,%0\n\t" - "ldc %0,sr" - : "=&r" (__dummy) - : "r" (0xffffff0f), "r" (interrupt_priority << 4)); + set_interrupt_registers(interrupt_priority); } static void mask_and_ack_imask(unsigned int irq) diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sh/kernel/process.c linux/arch/sh/kernel/process.c --- v2.3.99-pre3/linux/arch/sh/kernel/process.c Tue Mar 7 14:32:25 2000 +++ linux/arch/sh/kernel/process.c Mon Mar 27 10:26:15 2000 @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.28 2000/03/05 02:16:15 gniibe Exp $ +/* $Id: process.c,v 1.33 2000/03/25 00:06:15 gniibe Exp $ * * linux/arch/sh/kernel/process.c * @@ -94,7 +94,7 @@ { printk("\n"); printk("PC : %08lx SP : %08lx SR : %08lx TEA : %08lx\n", - regs->pc, regs->sp, regs->sr, ctrl_inl(MMU_TEA)); + regs->pc, regs->regs[15], regs->sr, ctrl_inl(MMU_TEA)); printk("R0 : %08lx R1 : %08lx R2 : %08lx R3 : %08lx\n", regs->regs[0],regs->regs[1], regs->regs[2],regs->regs[3]); @@ -210,22 +210,22 @@ struct task_struct *p, struct pt_regs *regs) { struct pt_regs *childregs; +#if defined(__SH4__) struct task_struct *tsk = current; - childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long) p)) - 1; - struct_cpy(childregs, regs); - -#if defined(__SH4__) if (tsk != &init_task) { unlazy_fpu(tsk); - struct_cpy(&p->thread.fpu, ¤t->thread.fpu); + p->thread.fpu = current->thread.fpu; p->used_math = tsk->used_math; } #endif + childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long) p)) - 1; + *childregs = *regs; + if (user_mode(regs)) { - childregs->sp = usp; + childregs->regs[15] = usp; } else { - childregs->sp = (unsigned long)p+2*PAGE_SIZE; + childregs->regs[15] = (unsigned long)p+2*PAGE_SIZE; } childregs->regs[0] = 0; /* Set return value for child */ childregs->sr |= SR_FD; /* Invalidate FPU flag */ @@ -244,7 +244,7 @@ dump->magic = CMAGIC; dump->start_code = current->mm->start_code; dump->start_data = current->mm->start_data; - dump->start_stack = regs->sp & ~(PAGE_SIZE - 1); + dump->start_stack = regs->regs[15] & ~(PAGE_SIZE - 1); dump->u_tsize = (current->mm->end_code - dump->start_code) >> PAGE_SHIFT; dump->u_dsize = (current->mm->brk + (PAGE_SIZE-1) - dump->start_data) >> PAGE_SHIFT; dump->u_ssize = (current->mm->start_stack - dump->start_stack + @@ -279,7 +279,7 @@ unsigned long r6, unsigned long r7, struct pt_regs regs) { - return do_fork(SIGCHLD, regs.sp, ®s); + return do_fork(SIGCHLD, regs.regs[15], ®s); } asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, @@ -287,7 +287,7 @@ struct pt_regs regs) { if (!newsp) - newsp = regs.sp; + newsp = regs.regs[15]; return do_fork(clone_flags, newsp, ®s); } @@ -305,7 +305,7 @@ unsigned long r6, unsigned long r7, struct pt_regs regs) { - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.sp, ®s); + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.regs[15], ®s); } /* @@ -369,4 +369,13 @@ (current->flags&PF_USEDFPU)?'C':' ', (init_task.flags&PF_USEDFPU)?'K':' ', (sr&SR_FD)?' ':'F'); restore_flags(flags); +} + +asmlinkage void break_point_trap(void) +{ + /* Clear traicng. */ + ctrl_outw(0, UBC_BBRA); + ctrl_outw(0, UBC_BBRB); + + force_sig(SIGTRAP, current); } diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sh/kernel/ptrace.c linux/arch/sh/kernel/ptrace.c --- v2.3.99-pre3/linux/arch/sh/kernel/ptrace.c Tue Sep 7 12:14:06 1999 +++ linux/arch/sh/kernel/ptrace.c Mon Mar 27 10:26:15 2000 @@ -1,6 +1,13 @@ -/* - * Surely this doesn't work... (we need to design ptrace for SupreH) +/* $Id: ptrace.c,v 1.4 2000/03/22 13:59:01 gniibe Exp $ + * * linux/arch/sh/kernel/ptrace.c + * + * Original x86 implementation: + * By Ross Biro 1/23/92 + * edited by Linus Torvalds + * + * SuperH version: Copyright (C) 1999, 2000 Kaz Kojima & Niibe Yutaka + * */ #include @@ -12,135 +19,126 @@ #include #include +#include #include #include #include #include +#include /* * does not yet catch signals sent when the child dies. * in exit.c or in signal.c. */ -/* determines which flags the user has access to. */ -/* 1 = access 0 = no access */ -#define FLAG_MASK 0x00044dd5 - -/* set's the trap flag. */ -#define TRAP_FLAG 0x100 - /* - * Offset of eflags on child stack.. + * This routine will get a word off of the process kernel stack. */ -#define EFL_OFFSET ((EFL-2)*4-sizeof(struct pt_regs)) - -/* - * this routine will get a word off of the processes privileged stack. - * the offset is how far from the base addr as stored in the TSS. - * this routine assumes that all the privileged stacks are in our - * data space. - */ static inline int get_stack_long(struct task_struct *task, int offset) { unsigned char *stack; - stack = (unsigned char *)task->thread.sp; + stack = (unsigned char *)task + THREAD_SIZE - sizeof(struct pt_regs); stack += offset; return (*((int *)stack)); } /* - * this routine will put a word on the processes privileged stack. - * the offset is how far from the base addr as stored in the TSS. - * this routine assumes that all the privileged stacks are in our - * data space. + * This routine will put a word on the process kernel stack. */ static inline int put_stack_long(struct task_struct *task, int offset, - unsigned long data) + unsigned long data) { - unsigned char * stack; + unsigned char *stack; - stack = (unsigned char *) task->thread.sp; + stack = (unsigned char *)task + THREAD_SIZE - sizeof(struct pt_regs); stack += offset; *(unsigned long *) stack = data; return 0; } -static int putreg(struct task_struct *child, - unsigned long regno, unsigned long value) +static void +compute_next_pc(struct pt_regs *regs, unsigned short inst, + unsigned long *pc1, unsigned long *pc2) { -#if 0 - switch (regno >> 2) { - case ORIG_EAX: - return -EIO; - case FS: - if (value && (value & 3) != 3) - return -EIO; - child->thread.fs = value; - return 0; - case GS: - if (value && (value & 3) != 3) - return -EIO; - child->thread.gs = value; - return 0; - case DS: - case ES: - if (value && (value & 3) != 3) - return -EIO; - value &= 0xffff; - break; - case SS: - case CS: - if ((value & 3) != 3) - return -EIO; - value &= 0xffff; - break; - case EFL: - value &= FLAG_MASK; - value |= get_stack_long(child, EFL_OFFSET) & ~FLAG_MASK; - } - if (regno > GS*4) - regno -= 2*4; - put_stack_long(child, regno - sizeof(struct pt_regs), value); -#endif - return 0; + int nib[4] + = { (inst >> 12) & 0xf, + (inst >> 8) & 0xf, + (inst >> 4) & 0xf, + inst & 0xf}; + + /* bra & bsr */ + if (nib[0] == 0xa || nib[0] == 0xb) { + *pc1 = regs->pc + 4 + ((short) ((inst & 0xfff) << 4) >> 3); + *pc2 = (unsigned long) -1; + return; + } + + /* bt & bf */ + if (nib[0] == 0x8 && (nib[1] == 0x9 || nib[1] == 0xb)) { + *pc1 = regs->pc + 4 + ((char) (inst & 0xff) << 1); + *pc2 = regs->pc + 2; + return; + } + + /* bt/s & bf/s */ + if (nib[0] == 0x8 && (nib[1] == 0xd || nib[1] == 0xf)) { + *pc1 = regs->pc + 4 + ((char) (inst & 0xff) << 1); + *pc2 = regs->pc + 4; + return; + } + + /* jmp & jsr */ + if (nib[0] == 0x4 && nib[3] == 0xb + && (nib[2] == 0x0 || nib[2] == 0x2)) { + *pc1 = regs->regs[nib[1]]; + *pc2 = (unsigned long) -1; + return; + } + + /* braf & bsrf */ + if (nib[0] == 0x0 && nib[3] == 0x3 + && (nib[2] == 0x0 || nib[2] == 0x2)) { + *pc1 = regs->pc + 4 + regs->regs[nib[1]]; + *pc2 = (unsigned long) -1; + return; + } + + if (inst == 0x000b) { + *pc1 = regs->pr; + *pc2 = (unsigned long) -1; + return; + } + + *pc1 = regs->pc + 2; + *pc2 = (unsigned long) -1; + return; } -static unsigned long getreg(struct task_struct *child, - unsigned long regno) +/* Tracing by user break controller. */ +static void +ubc_set_tracing(int asid, unsigned long nextpc1, unsigned nextpc2) { - unsigned long retval = ~0UL; - -#if 0 - switch (regno >> 2) { - case FS: - retval = child->thread.fs; - break; - case GS: - retval = child->thread.gs; - break; - case DS: - case ES: - case SS: - case CS: - retval = 0xffff; - /* fall through */ - default: - if (regno > GS*4) - regno -= 2*4; - regno = regno - sizeof(struct pt_regs); - retval &= get_stack_long(child, regno); + ctrl_outl(nextpc1, UBC_BARA); + ctrl_outb(asid, UBC_BASRA); + 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); + ctrl_outb(BAMR_12, UBC_BAMRB); + ctrl_outw(BBR_INST | BBR_READ, UBC_BBRB); } -#endif - return retval; + ctrl_outw(BRCR_PCBA | BRCR_PCBB, UBC_BRCR); } asmlinkage int sys_ptrace(long request, long pid, long addr, long data) { - struct task_struct *child; + struct task_struct *child, *tsk = current; struct user * dummy = NULL; unsigned long flags; - int i, ret; + int ret; lock_kernel(); ret = -EPERM; @@ -163,16 +161,16 @@ if (pid == 1) /* you may not mess with init */ goto out; if (request == PTRACE_ATTACH) { - if (child == current) + if (child == tsk) goto out; if ((!child->dumpable || - (current->uid != child->euid) || - (current->uid != child->suid) || - (current->uid != child->uid) || - (current->gid != child->egid) || - (current->gid != child->sgid) || - (!cap_issubset(child->cap_permitted, current->cap_permitted)) || - (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) + (tsk->uid != child->euid) || + (tsk->uid != child->suid) || + (tsk->uid != child->uid) || + (tsk->gid != child->egid) || + (tsk->gid != child->sgid) || + (!cap_issubset(child->cap_permitted, tsk->cap_permitted)) || + (tsk->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) goto out; /* the same process cannot be attached many times */ if (child->flags & PF_PTRACED) @@ -180,9 +178,9 @@ child->flags |= PF_PTRACED; write_lock_irqsave(&tasklist_lock, flags); - if (child->p_pptr != current) { + if (child->p_pptr != tsk) { REMOVE_LINKS(child); - child->p_pptr = current; + child->p_pptr = tsk; SET_LINKS(child); } write_unlock_irqrestore(&tasklist_lock, flags); @@ -198,257 +196,180 @@ if (request != PTRACE_KILL) goto out; } - if (child->p_pptr != current) + if (child->p_pptr != tsk) goto out; switch (request) { /* when I and D space are separate, these will need to be fixed. */ - case PTRACE_PEEKTEXT: /* read word at location addr. */ - case PTRACE_PEEKDATA: { - unsigned long tmp; - int copied; - - copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); - ret = -EIO; - if (copied != sizeof(tmp)) - goto out; - ret = put_user(tmp,(unsigned long *) data); - goto out; - } + case PTRACE_PEEKTEXT: /* read word at location addr. */ + case PTRACE_PEEKDATA: { + unsigned long tmp; + int copied; + + copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); + ret = -EIO; + if (copied != sizeof(tmp)) + break; + ret = put_user(tmp,(unsigned long *) data); + break; + } /* read the word at location addr in the USER area. */ - case PTRACE_PEEKUSR: { - unsigned long tmp; + case PTRACE_PEEKUSR: { + unsigned long tmp; - ret = -EIO; - if ((addr & 3) || addr < 0 || - addr > sizeof(struct user) - 3) - goto out; - - tmp = 0; /* Default return condition */ - if(addr < 17*sizeof(long)) - tmp = getreg(child, addr); -#if 0 - if(addr >= (long) &dummy->u_debugreg[0] && - addr <= (long) &dummy->u_debugreg[7]){ - addr -= (long) &dummy->u_debugreg[0]; - addr = addr >> 2; - tmp = child->thread.debugreg[addr]; - }; -#endif - ret = put_user(tmp,(unsigned long *) data); - goto out; - } + ret = -EIO; + if ((addr & 3) || addr < 0 || + addr > sizeof(struct user) - 3) + break; - /* when I and D space are separate, this will have to be fixed. */ - case PTRACE_POKETEXT: /* write the word at location addr. */ - case PTRACE_POKEDATA: - ret = 0; - if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) - goto out; - ret = -EIO; - goto out; + if (addr < sizeof(struct pt_regs)) + tmp = get_stack_long(child, addr); + else if (addr >= (long) &dummy->fpu && + addr < (long) &dummy->u_fpvalid) { + if (!child->used_math) { + if (addr == (long)&dummy->fpu.fpscr) + tmp = FPSCR_INIT; + else + tmp = 0; + } else + tmp = ((long *)&child->thread.fpu) + [(addr - (long)&dummy->fpu) >> 2]; + } else if (addr == (long) &dummy->u_fpvalid) + tmp = child->used_math; + else + tmp = 0; + ret = put_user(tmp, (unsigned long *)data); + break; + } - case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ - ret = -EIO; - if ((addr & 3) || addr < 0 || - addr > sizeof(struct user) - 3) - goto out; - - if (addr < 17*sizeof(long)) { - ret = putreg(child, addr, data); - goto out; - } - - /* We need to be very careful here. We implicitly - want to modify a portion of the task_struct, and we - have to be selective about what portions we allow someone - to modify. */ -#if 0 - if(addr >= (long) &dummy->u_debugreg[0] && - addr <= (long) &dummy->u_debugreg[7]){ - - if(addr == (long) &dummy->u_debugreg[4]) return -EIO; - if(addr == (long) &dummy->u_debugreg[5]) return -EIO; - if(addr < (long) &dummy->u_debugreg[4] && - ((unsigned long) data) >= TASK_SIZE-3) return -EIO; - - ret = -EIO; - if(addr == (long) &dummy->u_debugreg[7]) { - data &= ~DR_CONTROL_RESERVED; - for(i=0; i<4; i++) - if ((0x5f54 >> ((data >> (16 + 4*i)) & 0xf)) & 1) - goto out; - }; - - addr -= (long) &dummy->u_debugreg; - addr = addr >> 2; - child->thread.debugreg[addr] = data; - ret = 0; - goto out; - }; -#endif - ret = -EIO; - goto out; + /* when I and D space are separate, this will have to be fixed. */ + case PTRACE_POKETEXT: /* write the word at location addr. */ + case PTRACE_POKEDATA: + ret = 0; + if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) + break; + ret = -EIO; + break; - case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ - case PTRACE_CONT: { /* restart after signal. */ - long tmp; - - ret = -EIO; - if ((unsigned long) data > _NSIG) - goto out; - if (request == PTRACE_SYSCALL) - child->flags |= PF_TRACESYS; - else - child->flags &= ~PF_TRACESYS; - child->exit_code = data; - /* make sure the single step bit is not set. */ -#if 0 - tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG; - put_stack_long(child, EFL_OFFSET,tmp); -#endif - wake_up_process(child); + case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ + ret = -EIO; + if ((addr & 3) || addr < 0 || + addr > sizeof(struct user) - 3) + break; + + if (addr < sizeof(struct pt_regs)) + ret = put_stack_long(child, addr, data); + else if (addr >= (long) &dummy->fpu && + addr < (long) &dummy->u_fpvalid) { + child->used_math = 1; + ((long *)&child->thread.fpu) + [(addr - (long)&dummy->fpu) >> 2] = data; + ret = 0; + } else if (addr == (long) &dummy->u_fpvalid) { + child->used_math = data?1:0; ret = 0; - goto out; } + break; + + case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ + case PTRACE_CONT: { /* restart after signal. */ + ret = -EIO; + if ((unsigned long) data > _NSIG) + break; + if (request == PTRACE_SYSCALL) + child->flags |= PF_TRACESYS; + else + child->flags &= ~PF_TRACESYS; + child->exit_code = data; + wake_up_process(child); + ret = 0; + break; + } /* * make the child exit. Best I can do is send it a sigkill. * perhaps it should be put in the status that it wants to * exit. */ - case PTRACE_KILL: { - long tmp; + case PTRACE_KILL: { + ret = 0; + if (child->state == TASK_ZOMBIE) /* already dead */ + break; + child->exit_code = SIGKILL; + wake_up_process(child); + break; + } - ret = 0; - if (child->state == TASK_ZOMBIE) /* already dead */ - goto out; - child->exit_code = SIGKILL; - /* make sure the single step bit is not set. */ -#if 0 - tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG; - put_stack_long(child, EFL_OFFSET, tmp); -#endif - wake_up_process(child); - goto out; - } + case PTRACE_SINGLESTEP: { /* set the trap flag. */ + long tmp, pc; + struct pt_regs *dummy = NULL; + struct pt_regs *regs; + unsigned long nextpc1, nextpc2; + unsigned short insn; - case PTRACE_SINGLESTEP: { /* set the trap flag. */ - long tmp; + ret = -EIO; + if ((unsigned long) data > _NSIG) + break; + child->flags &= ~PF_TRACESYS; + if ((child->flags & PF_DTRACE) == 0) { + /* Spurious delayed TF traps may occur */ + child->flags |= PF_DTRACE; + } - ret = -EIO; - if ((unsigned long) data > _NSIG) - goto out; - child->flags &= ~PF_TRACESYS; - if ((child->flags & PF_DTRACE) == 0) { - /* Spurious delayed TF traps may occur */ - child->flags |= PF_DTRACE; - } -#if 0 - tmp = get_stack_long(child, EFL_OFFSET) | TRAP_FLAG; - put_stack_long(child, EFL_OFFSET, tmp); + /* Compute next pc. */ + pc = get_stack_long(child, (long)&dummy->pc); + regs = (struct pt_regs *)((unsigned long)child + THREAD_SIZE - sizeof(struct pt_regs)); + if (access_process_vm(child, pc&~3, &tmp, sizeof(tmp), 1) != sizeof(data)) + break; + +#ifdef __LITTLE_ENDIAN__ + if (pc & 3) + insn = tmp >> 16; + else + insn = tmp & 0xffff; +#else + if (pc & 3) + insn = tmp & 0xffff; + else + insn = tmp >> 16; #endif - child->exit_code = data; - /* give it a chance to run. */ - wake_up_process(child); - ret = 0; - goto out; - } + compute_next_pc (regs, insn, &nextpc1, &nextpc2); - case PTRACE_DETACH: { /* detach a process that was attached. */ - long tmp; + if (nextpc1 & 0x80000000) + break; + if (nextpc2 != (unsigned long) -1 && (nextpc2 & 0x80000000)) + break; - ret = -EIO; - if ((unsigned long) data > _NSIG) - goto out; - child->flags &= ~(PF_PTRACED|PF_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. */ -#if 0 - tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG; - put_stack_long(child, EFL_OFFSET, tmp); -#endif - wake_up_process(child); - ret = 0; - goto out; - } -#if 0 - case PTRACE_GETREGS: { /* Get all gp regs from the child. */ - if (!access_ok(VERIFY_WRITE, (unsigned *)data, - 17*sizeof(long))) - { - ret = -EIO; - goto out; - } - for ( i = 0; i < 17*sizeof(long); i += sizeof(long) ) - { - __put_user(getreg(child, i),(unsigned long *) data); - data += sizeof(long); - } - ret = 0; - goto out; - }; + ubc_set_tracing(child->mm->context & MMU_CONTEXT_ASID_MASK, + nextpc1, nextpc2); - case PTRACE_SETREGS: { /* Set all gp regs in the child. */ - unsigned long tmp; - if (!access_ok(VERIFY_READ, (unsigned *)data, - 17*sizeof(long))) - { - ret = -EIO; - goto out; - } - for ( i = 0; i < 17*sizeof(long); i += sizeof(long) ) - { - __get_user(tmp, (unsigned long *) data); - putreg(child, i, tmp); - data += sizeof(long); - } - ret = 0; - goto out; - }; + child->exit_code = data; + /* give it a chance to run. */ + wake_up_process(child); + ret = 0; + break; + } - case PTRACE_GETFPREGS: { /* Get the child FPU state. */ - if (!access_ok(VERIFY_WRITE, (unsigned *)data, - sizeof(struct user_i387_struct))) - { - ret = -EIO; - goto out; - } - ret = 0; - if ( !child->used_math ) { - /* Simulate an empty FPU. */ - child->thread.i387.hard.cwd = 0xffff037f; - child->thread.i387.hard.swd = 0xffff0000; - child->thread.i387.hard.twd = 0xffffffff; - } - __copy_to_user((void *)data, &child->thread.i387.hard, - sizeof(struct user_i387_struct)); - goto out; - }; + case PTRACE_DETACH: { /* detach a process that was attached. */ + ret = -EIO; + if ((unsigned long) data > _NSIG) + break; + child->flags &= ~(PF_PTRACED|PF_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); + ret = 0; + break; + } - case PTRACE_SETFPREGS: { /* Set the child FPU state. */ - if (!access_ok(VERIFY_READ, (unsigned *)data, - sizeof(struct user_i387_struct))) - { - ret = -EIO; - goto out; - } - child->used_math = 1; - __copy_from_user(&child->thread.i387.hard, (void *)data, - sizeof(struct user_i387_struct)); - ret = 0; - goto out; - }; -#endif - default: - ret = -EIO; - goto out; + default: + ret = -EIO; + break; } out: unlock_kernel(); @@ -457,20 +378,22 @@ asmlinkage void syscall_trace(void) { - if ((current->flags & (PF_PTRACED|PF_TRACESYS)) - != (PF_PTRACED|PF_TRACESYS)) + struct task_struct *tsk = current; + + if ((tsk->flags & (PF_PTRACED|PF_TRACESYS)) + != (PF_PTRACED|PF_TRACESYS)) return; - current->exit_code = SIGTRAP; - current->state = TASK_STOPPED; - notify_parent(current, SIGCHLD); + tsk->exit_code = SIGTRAP; + tsk->state = TASK_STOPPED; + notify_parent(tsk, SIGCHLD); schedule(); /* * this isn't the same as continuing with a signal, but it will do * for normal use. strace only continues with a signal if the * stopping signal is not SIGTRAP. -brl */ - if (current->exit_code) { - send_sig(current->exit_code, current, 1); - current->exit_code = 0; + if (tsk->exit_code) { + send_sig(tsk->exit_code, tsk, 1); + tsk->exit_code = 0; } } diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sh/kernel/signal.c linux/arch/sh/kernel/signal.c --- v2.3.99-pre3/linux/arch/sh/kernel/signal.c Tue Mar 7 14:32:25 2000 +++ linux/arch/sh/kernel/signal.c Mon Mar 27 10:26:15 2000 @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.16 2000/01/29 11:31:31 gniibe Exp gniibe $ +/* $Id: signal.c,v 1.21 2000/03/11 14:06:21 gniibe Exp $ * * linux/arch/sh/kernel/signal.c * @@ -6,7 +6,7 @@ * * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson * - * SuperH version: Copyright (C) 1999 Niibe Yutaka + * SuperH version: Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima * */ @@ -125,7 +125,7 @@ unsigned long r6, unsigned long r7, struct pt_regs regs) { - return do_sigaltstack(uss, uoss, regs.sp); + return do_sigaltstack(uss, uoss, regs.regs[15]); } @@ -136,7 +136,6 @@ struct sigframe { struct sigcontext sc; - /* FPU data should come here: SH-3 has no FPU */ unsigned long extramask[_NSIG_WORDS-1]; char retcode[4]; }; @@ -147,10 +146,38 @@ void *puc; struct siginfo info; struct ucontext uc; - /* FPU should come here: SH-3 has no FPU */ char retcode[4]; }; +#if defined(__SH4__) +static inline int restore_sigcontext_fpu(struct sigcontext *sc) +{ + current->used_math = 1; + return __copy_from_user(&tsk->thread.fpu.hard, &sc->sc_fpregs[0], + sizeof(long)*(NUM_FPU_REGS*2+2)); +} + +static inline int save_sigcontext_fpu(struct sigcontext *sc) +{ + struct task_struct *tsk = current; + + if (!tsk->used_math) { + sc->owend_fp = 0; + return 0; + } + + sc->owend_fp = 1; + + /* This will cause a "finit" to be triggered by the next + attempted FPU operation by the 'current' process. + */ + tsk->used_math = 0; + + unlazy_fpu(tsk); + return __copy_to_user(&sc->sc_fpregs[0], &tsk->thread.fpu.hard, + sizeof(long)*(NUM_FPU_REGS*2+2)); +} +#endif static int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *r0_p) @@ -165,15 +192,28 @@ COPY(regs[8]); COPY(regs[9]); COPY(regs[10]); COPY(regs[11]); COPY(regs[12]); COPY(regs[13]); - COPY(regs[14]); COPY(sp); + COPY(regs[14]); COPY(regs[15]); COPY(gbr); COPY(mach); COPY(macl); COPY(pr); COPY(sr); COPY(pc); #undef COPY +#if defined(__SH4__) + { + int owned_fp; + struct task_struct *tsk = current; + + regs->sr |= SR_FD; /* Release FPU */ + clear_fpu(tsk); + current->used_math = 0; + __get_user (owned_fp, &context->sc_ownedfp); + if (owned_fp) + err |= restore_sigcontext_fpu(sc); + } +#endif + regs->syscall_nr = -1; /* disable syscall checks */ err |= __get_user(*r0_p, &sc->sc_regs[0]); - return err; } @@ -181,7 +221,7 @@ unsigned long r6, unsigned long r7, struct pt_regs regs) { - struct sigframe *frame = (struct sigframe *)regs.sp; + struct sigframe *frame = (struct sigframe *)regs.regs[15]; sigset_t set; int r0; @@ -214,7 +254,7 @@ unsigned long r6, unsigned long r7, struct pt_regs regs) { - struct rt_sigframe *frame = (struct rt_sigframe *)regs.sp; + struct rt_sigframe *frame = (struct rt_sigframe *)regs.regs[15]; sigset_t set; stack_t st; int r0; @@ -238,7 +278,7 @@ goto badframe; /* It is more difficult to avoid calling this function than to call it and ignore errors. */ - do_sigaltstack(&st, NULL, regs.sp); + do_sigaltstack(&st, NULL, regs.regs[15]); return r0; @@ -265,12 +305,16 @@ COPY(regs[8]); COPY(regs[9]); COPY(regs[10]); COPY(regs[11]); COPY(regs[12]); COPY(regs[13]); - COPY(regs[14]); COPY(sp); + COPY(regs[14]); COPY(regs[15]); COPY(gbr); COPY(mach); COPY(macl); COPY(pr); COPY(sr); COPY(pc); #undef COPY +#if defined(__SH4__) + err |= save_sigcontext_fpu(sc); +#endif + /* non-iBCS2 extensions.. */ err |= __put_user(mask, &sc->oldmask); @@ -296,7 +340,7 @@ int err = 0; int signal; - frame = get_sigframe(ka, regs->sp, sizeof(*frame)); + frame = get_sigframe(ka, regs->regs[15], sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; @@ -334,7 +378,7 @@ goto give_sigsegv; /* Set up registers for signal handler */ - regs->sp = (unsigned long) frame; + regs->regs[15] = (unsigned long) frame; regs->regs[4] = signal; /* Arg for signal handler */ regs->pc = (unsigned long) ka->sa.sa_handler; @@ -361,7 +405,7 @@ int err = 0; int signal; - frame = get_sigframe(ka, regs->sp, sizeof(*frame)); + frame = get_sigframe(ka, regs->regs[15], sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; @@ -381,7 +425,8 @@ err |= __put_user(0, &frame->uc.uc_link); err |= __put_user((void *)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); - err |= __put_user(sas_ss_flags(regs->sp), &frame->uc.uc_stack.ss_flags); + err |= __put_user(sas_ss_flags(regs->regs[15]), + &frame->uc.uc_stack.ss_flags); err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]); @@ -407,7 +452,7 @@ goto give_sigsegv; /* Set up registers for signal handler */ - regs->sp = (unsigned long) frame; + regs->regs[15] = (unsigned long) frame; regs->regs[4] = signal; /* Arg for signal handler */ regs->pc = (unsigned long) ka->sa.sa_handler; diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sh/lib/Makefile linux/arch/sh/lib/Makefile --- v2.3.99-pre3/linux/arch/sh/lib/Makefile Wed Oct 27 16:34:12 1999 +++ linux/arch/sh/lib/Makefile Thu Mar 30 16:56:04 2000 @@ -3,7 +3,7 @@ # .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o + $(CC) $(AFLAGS) -traditional -c $< -o $*.o L_TARGET = lib.a L_OBJS = delay.o memcpy.o memset.o memmove.o memchr.o old-checksum.o \ diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sh/mm/cache.c linux/arch/sh/mm/cache.c --- v2.3.99-pre3/linux/arch/sh/mm/cache.c Tue Mar 7 14:32:25 2000 +++ linux/arch/sh/mm/cache.c Mon Mar 27 10:26:15 2000 @@ -1,4 +1,4 @@ -/* $Id: cache.c,v 1.9 2000/02/14 12:45:26 gniibe Exp $ +/* $Id: cache.c,v 1.10 2000/03/07 11:58:34 gniibe Exp $ * * linux/arch/sh/mm/cache.c * @@ -67,36 +67,15 @@ #define CACHE_IC_NUM_WAYS 1 #endif -#define jump_to_p2(__dummy) \ - asm volatile("mova 1f,%0\n\t" \ - "add %1,%0\n\t" \ - "jmp @r0 ! Jump to P2 area\n\t" \ - " nop\n\t" \ - ".balign 4\n" \ - "1:" \ - : "=&z" (__dummy) \ - : "r" (0x20000000)) - -#define back_to_p1(__dummy) \ - asm volatile("nop;nop;nop;nop;nop;nop\n\t" \ - "mova 9f,%0\n\t" \ - "sub %1,%0\n\t" \ - "jmp @r0 ! Back to P1 area\n\t" \ - " nop\n\t" \ - ".balign 4\n" \ - "9:" \ - : "=&z" (__dummy) \ - : "r" (0x20000000), "0" (__dummy)) - /* Write back caches to memory (if needed) and invalidates the caches */ void cache_flush_area(unsigned long start, unsigned long end) { - unsigned long flags, __dummy; + unsigned long flags; unsigned long addr, data, v, p; start &= ~(L1_CACHE_BYTES-1); save_and_cli(flags); - jump_to_p2(__dummy); + jump_to_P2(); for (v = start; v < end; v+=L1_CACHE_BYTES) { p = __pa(v); @@ -110,7 +89,7 @@ : "m" (__m(v))); #endif } - back_to_p1(__dummy); + back_to_P1(); restore_flags(flags); } @@ -124,12 +103,12 @@ the cache line. */ void cache_purge_area(unsigned long start, unsigned long end) { - unsigned long flags, __dummy; + unsigned long flags; unsigned long addr, data, v, p, j; start &= ~(L1_CACHE_BYTES-1); save_and_cli(flags); - jump_to_p2(__dummy); + jump_to_P2(); for (v = start; v < end; v+=L1_CACHE_BYTES) { p = __pa(v); @@ -150,19 +129,19 @@ : "m" (__m(v))); #endif } - back_to_p1(__dummy); + back_to_P1(); restore_flags(flags); } /* write back the dirty cache, but not invalidate the cache */ void cache_wback_area(unsigned long start, unsigned long end) { - unsigned long flags, __dummy; + unsigned long flags; unsigned long v; start &= ~(L1_CACHE_BYTES-1); save_and_cli(flags); - jump_to_p2(__dummy); + jump_to_P2(); for (v = start; v < end; v+=L1_CACHE_BYTES) { #if CACHE_IC_ADDRESS_ARRAY == CACHE_OC_ADDRESS_ARRAY @@ -187,7 +166,7 @@ : "m" (__m(v))); #endif } - back_to_p1(__dummy); + back_to_P1(); restore_flags(flags); } @@ -199,11 +178,11 @@ */ static void cache_wback_all(void) { - unsigned long flags, __dummy; + unsigned long flags; unsigned long addr, data, i, j; save_and_cli(flags); - jump_to_p2(__dummy); + jump_to_P2(); for (i=0; icontext == NO_CONTEXT) return; @@ -305,19 +302,25 @@ data = (page & 0xfffe0000) | asid; /* VALID bit is off */ ctrl_outl(data, addr); #elif defined(__SH4__) + jump_to_P2(); addr = MMU_UTLB_ADDRESS_ARRAY | MMU_PAGE_ASSOC_BIT; data = page | asid; /* VALID bit is off */ ctrl_outl(data, addr); - - for (i=0; i<4; i++) { - addr = MMU_ITLB_ADDRESS_ARRAY | (i<<8); - data = ctrl_inl(addr); - data &= ~0x300; - if (data == (page | asid)) { - ctrl_outl(data, addr); - break; +#if 0 /* Not need when using ASSOC. ??? */ + { + int i; + for (i=0; i<4; i++) { + addr = MMU_ITLB_ADDRESS_ARRAY | (i<<8); + data = ctrl_inl(addr); + data &= ~0x300; + if (data == (page | asid)) { + ctrl_outl(data, addr); + break; + } } } +#endif + back_to_P1(); #endif if (saved_asid != MMU_NO_ASID) set_asid(saved_asid); diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sh/mm/init.c linux/arch/sh/mm/init.c --- v2.3.99-pre3/linux/arch/sh/mm/init.c Tue Mar 7 14:32:25 2000 +++ linux/arch/sh/mm/init.c Mon Mar 27 10:24:56 2000 @@ -224,7 +224,7 @@ zones_size[ZONE_DMA] = max_dma - start_pfn; zones_size[ZONE_NORMAL] = low - max_dma; } - free_area_init_node(0, 0, zones_size, __MEMORY_START); + free_area_init_node(0, 0, zones_size, __MEMORY_START, 0); } } diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc/config.in linux/arch/sparc/config.in --- v2.3.99-pre3/linux/arch/sparc/config.in Mon Mar 27 08:08:22 2000 +++ linux/arch/sparc/config.in Thu Mar 30 16:54:53 2000 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.90 2000/03/17 05:18:02 anton Exp $ +# $Id: config.in,v 1.92 2000/03/29 11:56:48 davem Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -20,6 +20,8 @@ bool 'Symmetric multi-processing support (does not work on sun4/sun4c)' CONFIG_SMP # Global things across all Sun machines. +define_bool CONFIG_ISA n +define_bool CONFIG_PCMCIA n define_bool CONFIG_SBUS y define_bool CONFIG_SBUSCHAR y define_bool CONFIG_BUSMOUSE y diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc/defconfig linux/arch/sparc/defconfig --- v2.3.99-pre3/linux/arch/sparc/defconfig Sun Mar 19 18:35:30 2000 +++ linux/arch/sparc/defconfig Mon Mar 27 09:38:47 2000 @@ -14,6 +14,8 @@ CONFIG_VT=y CONFIG_VT_CONSOLE=y # CONFIG_SMP is not set +# CONFIG_ISA is not set +# CONFIG_PCMCIA is not set CONFIG_SBUS=y CONFIG_SBUSCHAR=y CONFIG_BUSMOUSE=y diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc/kernel/Makefile linux/arch/sparc/kernel/Makefile --- v2.3.99-pre3/linux/arch/sparc/kernel/Makefile Wed Dec 29 13:13:13 1999 +++ linux/arch/sparc/kernel/Makefile Thu Mar 30 16:56:04 2000 @@ -8,10 +8,10 @@ # Note 2! The CFLAGS definitions are now in the main makefile... .S.s: - $(CPP) -D__ASSEMBLY__ $(AFLAGS) -ansi $< -o $*.s + $(CPP) $(AFLAGS) -ansi $< -o $*.s .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c $< -o $*.o + $(CC) $(AFLAGS) -ansi -c $< -o $*.o all: kernel.o head.o init_task.o @@ -47,7 +47,7 @@ endif head.o: head.S - $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c $*.S -o $*.o + $(CC) $(AFLAGS) -ansi -c $*.S -o $*.o check_asm: dummy @echo "/* Automatically generated. Do not edit. */" > asm_offsets.h @@ -62,7 +62,7 @@ @echo "#undef __SMP__" >> tmp.c @echo "#undef CONFIG_SMP" >> tmp.c @echo "#include " >> tmp.c - $(CC) $(CPPFLAGS) -E tmp.c -o tmp.i + $(CPP) $(CPPFLAGS) tmp.c -o tmp.i @echo "/* Automatically generated. Do not edit. */" > check_asm.c @echo "#include " >> check_asm.c @echo "#undef __SMP__" >> check_asm.c @@ -87,7 +87,7 @@ @echo "#undef CONFIG_SMP" >> tmp.c @echo "#define CONFIG_SMP 1" >> tmp.c @echo "#include " >> tmp.c - $(CC) $(CPPFLAGS) -D__SMP__ -E tmp.c -o tmp.i + $(CPP) $(CPPFLAGS) -D__SMP__ tmp.c -o tmp.i @echo "/* Automatically generated. Do not edit. */" > check_asm.c @echo "#include " >> check_asm.c @echo "#undef CONFIG_SMP" >> check_asm.c diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc/kernel/ioport.c linux/arch/sparc/kernel/ioport.c --- v2.3.99-pre3/linux/arch/sparc/kernel/ioport.c Sun Mar 19 18:35:30 2000 +++ linux/arch/sparc/kernel/ioport.c Thu Mar 30 16:54:53 2000 @@ -1,4 +1,4 @@ -/* $Id: ioport.c,v 1.36 2000/03/16 08:22:53 anton Exp $ +/* $Id: ioport.c,v 1.37 2000/03/28 06:38:19 davem Exp $ * ioport.c: Simple io mapping allocator. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -581,6 +581,7 @@ { if (direction == PCI_DMA_NONE) BUG(); + /* IIep is write-through, not flushing. */ return virt_to_bus(ptr); } @@ -591,11 +592,15 @@ * 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) +void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t ba, size_t size, + int direction) { if (direction == PCI_DMA_NONE) BUG(); - /* Nothing to do... */ + if (direction != PCI_DMA_TODEVICE) { + mmu_inval_dma_area((unsigned long)bus_to_virt(ba), + (size + PAGE_SIZE-1) & PAGE_MASK); + } } /* Map a set of buffers described by scatterlist in streaming @@ -613,13 +618,14 @@ * 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 pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, + int direction) { int n; if (direction == PCI_DMA_NONE) BUG(); - + /* IIep is write-through, not flushing. */ for (n = 0; n < nents; n++) { sg->dvma_address = virt_to_bus(sg->address); sg->dvma_length = sg->length; @@ -632,15 +638,24 @@ * 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 nhwents, int direction) +void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, + int direction) { + int n; + if (direction == PCI_DMA_NONE) BUG(); - /* Nothing to do... */ + if (direction != PCI_DMA_TODEVICE) { + for (n = 0; n < nents; n++) { + mmu_inval_dma_area((unsigned long)sg->address, + (sg->length + PAGE_SIZE-1) & PAGE_MASK); + sg++; + } + } } /* Make physical memory consistent for a single - * streaming mode DMA translation after a transfer. + * streaming mode DMA translation before or 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 @@ -652,8 +667,10 @@ { if (direction == PCI_DMA_NONE) BUG(); - mmu_inval_dma_area((unsigned long)bus_to_virt(ba), - (size + PAGE_SIZE-1) & PAGE_MASK); + if (direction != PCI_DMA_TODEVICE) { + mmu_inval_dma_area((unsigned long)bus_to_virt(ba), + (size + PAGE_SIZE-1) & PAGE_MASK); + } } /* Make physical memory consistent for a set of streaming @@ -664,13 +681,16 @@ */ void pci_dma_sync_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, int direction) { + int n; + if (direction == PCI_DMA_NONE) BUG(); - while (nents) { - --nents; - mmu_inval_dma_area((unsigned long)sg->address, - (sg->dvma_length + PAGE_SIZE-1) & PAGE_MASK); - sg++; + if (direction != PCI_DMA_TODEVICE) { + for (n = 0; n < nents; n++) { + mmu_inval_dma_area((unsigned long)sg->address, + (sg->length + PAGE_SIZE-1) & PAGE_MASK); + sg++; + } } } #endif CONFIG_PCI diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc/kernel/setup.c linux/arch/sparc/kernel/setup.c --- v2.3.99-pre3/linux/arch/sparc/kernel/setup.c Sun Mar 19 18:35:30 2000 +++ linux/arch/sparc/kernel/setup.c Thu Mar 30 16:54:53 2000 @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.116 2000/03/15 23:26:22 anton Exp $ +/* $Id: setup.c,v 1.117 2000/03/27 12:14:54 davem Exp $ * linux/arch/sparc/kernel/setup.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -45,6 +45,8 @@ #include #include +#undef PROM_DEBUG_CONSOLE + struct screen_info screen_info = { 0, 0, /* orig-x, orig-y */ 0, /* unused */ @@ -282,6 +284,7 @@ struct pt_regs fake_swapper_regs = { 0, 0, 0, 0, { 0, } }; +#ifdef PROM_DEBUG_CONSOLE static void prom_cons_write(struct console *con, const char *str, unsigned count) { while (count--) @@ -291,6 +294,7 @@ static struct console prom_console = { "PROM", prom_cons_write, 0, 0, 0, 0, 0, CON_PRINTBUFFER, 0, 0, 0 }; +#endif extern void paging_init(void); @@ -345,6 +349,9 @@ printk("UNKNOWN!\n"); break; }; +#ifdef PROM_DEBUG_CONSOLE + register_console(&prom_console); +#endif #ifdef CONFIG_DUMMY_CONSOLE conswitchp = &dummy_con; diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc/kernel/signal.c linux/arch/sparc/kernel/signal.c --- v2.3.99-pre3/linux/arch/sparc/kernel/signal.c Fri Jan 28 15:09:07 2000 +++ linux/arch/sparc/kernel/signal.c Sun Apr 2 15:53:27 2000 @@ -1096,7 +1096,9 @@ if (map->vm_file != NULL) { dev = map->vm_file->f_dentry->d_inode->i_dev; ino = map->vm_file->f_dentry->d_inode->i_ino; - line = d_path(map->vm_file->f_dentry, buffer, PAGE_SIZE); + line = d_path(map->vm_file->f_dentry, + map->vm_file->f_vfsmnt, + buffer, PAGE_SIZE); } printk(MAPS_LINE_FORMAT, map->vm_start, map->vm_end, str, map->vm_pgoff << PAGE_SHIFT, kdevname(dev), ino); diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc/kernel/sys_sunos.c linux/arch/sparc/kernel/sys_sunos.c --- v2.3.99-pre3/linux/arch/sparc/kernel/sys_sunos.c Sun Mar 19 18:35:30 2000 +++ linux/arch/sparc/kernel/sys_sunos.c Sun Apr 2 15:53:28 2000 @@ -1,4 +1,4 @@ -/* $Id: sys_sunos.c,v 1.117 2000/03/15 02:43:32 davem Exp $ +/* $Id: sys_sunos.c,v 1.118 2000/03/26 11:28:56 davem Exp $ * sys_sunos.c: SunOS specific syscall compatibility support. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -91,7 +91,7 @@ * of /dev/zero, transform it into an anonymous mapping. * SunOS is so stupid some times... hmph! */ - if(file->f_dentry && file->f_dentry->d_inode) { + if (file) { if(MAJOR(file->f_dentry->d_inode->i_rdev) == MEM_MAJOR && MINOR(file->f_dentry->d_inode->i_rdev) == 5) { flags |= MAP_ANONYMOUS; @@ -633,10 +633,9 @@ }; -extern int do_mount(struct block_device *, const char *, const char *, char *, int, void *); extern dev_t get_unnamed_dev(void); extern void put_unnamed_dev(dev_t); -extern asmlinkage int sys_mount(char *, char *, char *, unsigned long, void *); +extern asmlinkage long do_sys_mount(char *, char *, char *, int, void *); extern asmlinkage int sys_connect(int fd, struct sockaddr *uservaddr, int addrlen); extern asmlinkage int sys_socket(int family, int type, int protocol); extern asmlinkage int sys_bind(int fd, struct sockaddr *umyaddr, int addrlen); @@ -660,8 +659,6 @@ file = fget(fd); if (!file) goto out; - if (!file->f_dentry || !(inode = file->f_dentry->d_inode)) - goto out_putf; socket = &inode->u.socket_i; local.sin_family = AF_INET; @@ -702,12 +699,12 @@ return def_value; } -asmlinkage int sunos_nfs_mount(char *dir_name, int linux_flags, void *data) +static int sunos_nfs_mount(char *dir_name, int linux_flags, void *data) { int server_fd; char *the_name; struct nfs_mount_data linux_nfs_mount; - struct sunos_nfs_mount_args *sunos_mount = data; + struct sunos_nfs_mount_args sunos_mount; /* Ok, here comes the fun part: Linux's nfs mount needs a * socket connection to the server, but SunOS mount does not @@ -715,33 +712,42 @@ * address to create a socket and bind it to a reserved * port on this system */ + if (copy_from_user(&sunos_mount, data, sizeof(sunos_mount)) + return -EFAULT; + server_fd = sys_socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (server_fd < 0) return -ENXIO; - if (!sunos_nfs_get_server_fd (server_fd, sunos_mount->addr)){ + if (copy_from_user(&linux_nfs_mount.addr,sunos_mount.addr, + sizeof(*sunos_mount.addr)) || + copy_from_user(&linux_nfs_mount.root,sunos_mount.fh, + sizeof(*sunos_mount.fh))) { + sys_close (server_fd); + return -EFAULT; + } + + if (!sunos_nfs_get_server_fd (server_fd, &linux_nfs_mount.addr)){ sys_close (server_fd); return -ENXIO; } /* Now, bind it to a locally reserved port */ linux_nfs_mount.version = NFS_MOUNT_VERSION; - linux_nfs_mount.flags = sunos_mount->flags; - linux_nfs_mount.addr = *sunos_mount->addr; - linux_nfs_mount.root = *sunos_mount->fh; + linux_nfs_mount.flags = sunos_mount.flags; linux_nfs_mount.fd = server_fd; - linux_nfs_mount.rsize = get_default (sunos_mount->rsize, 8192); - linux_nfs_mount.wsize = get_default (sunos_mount->wsize, 8192); - linux_nfs_mount.timeo = get_default (sunos_mount->timeo, 10); - linux_nfs_mount.retrans = sunos_mount->retrans; + linux_nfs_mount.rsize = get_default (sunos_mount.rsize, 8192); + linux_nfs_mount.wsize = get_default (sunos_mount.wsize, 8192); + linux_nfs_mount.timeo = get_default (sunos_mount.timeo, 10); + linux_nfs_mount.retrans = sunos_mount.retrans; - linux_nfs_mount.acregmin = sunos_mount->acregmin; - linux_nfs_mount.acregmax = sunos_mount->acregmax; - linux_nfs_mount.acdirmin = sunos_mount->acdirmin; - linux_nfs_mount.acdirmax = sunos_mount->acdirmax; + linux_nfs_mount.acregmin = sunos_mount.acregmin; + linux_nfs_mount.acregmax = sunos_mount.acregmax; + linux_nfs_mount.acdirmin = sunos_mount.acdirmin; + linux_nfs_mount.acdirmax = sunos_mount.acdirmax; - the_name = getname(sunos_mount->hostname); + the_name = getname(sunos_mount.hostname); if(IS_ERR(the_name)) return PTR_ERR(the_name); @@ -749,7 +755,7 @@ linux_nfs_mount.hostname [255] = 0; putname (the_name); - return do_mount (NULL, "", dir_name, "nfs", linux_flags, &linux_nfs_mount); + return do_sys_mount ("", dir_name, "nfs", linux_flags, &linux_nfs_mount); } asmlinkage int @@ -758,6 +764,7 @@ int linux_flags = MS_MGC_MSK; /* new semantics */ int ret = -EINVAL; char *dev_fname = 0; + char *dir_page, *type_page; if (!capable (CAP_SYS_ADMIN)) return -EPERM; @@ -777,24 +784,44 @@ linux_flags |= MS_RDONLY; if(flags & SMNT_NOSUID) linux_flags |= MS_NOSUID; - if(strcmp(type, "ext2") == 0) { - dev_fname = (char *) data; - } else if(strcmp(type, "iso9660") == 0) { - dev_fname = (char *) data; - } else if(strcmp(type, "minix") == 0) { - dev_fname = (char *) data; - } else if(strcmp(type, "nfs") == 0) { - ret = sunos_nfs_mount (dir, flags, data); - goto out; - } else if(strcmp(type, "ufs") == 0) { + + dir_page = getname(dir); + ret = PTR_ERR(dir_page); + if (IS_ERR(dir_page)) + goto out; + + type_page = getname(type); + ret = PTR_ERR(type_page); + if (IS_ERR(type_page)) + goto out1; + + if(strcmp(type_page, "ext2") == 0) { + dev_fname = getname(data); + } else if(strcmp(type_page, "iso9660") == 0) { + dev_fname = getname(data); + } else if(strcmp(type_page, "minix") == 0) { + dev_fname = getname(data); + } else if(strcmp(type_page, "nfs") == 0) { + ret = sunos_nfs_mount (dir_page, flags, data); + goto out2 + } else if(strcmp(type_page, "ufs") == 0) { printk("Warning: UFS filesystem mounts unsupported.\n"); ret = -ENODEV; - goto out; - } else if(strcmp(type, "proc")) { + goto out2 + } else if(strcmp(type_page, "proc")) { ret = -ENODEV; - goto out; + goto out2 } - ret = sys_mount(dev_fname, dir, type, linux_flags, NULL); + ret = PTR_ERR(dev_fname); + if (IS_ERR(dev_fname)) + goto out2; + ret = do_sys_mount(dev_fname, dir_page, type_page, linux_flags, NULL); + if (dev_fname) + putname(dev_fname); +out2: + putname(type_page); +out1: + putname(dir_page); out: unlock_kernel(); return ret; diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc/lib/Makefile linux/arch/sparc/lib/Makefile --- v2.3.99-pre3/linux/arch/sparc/lib/Makefile Sun Mar 19 18:35:30 2000 +++ linux/arch/sparc/lib/Makefile Thu Mar 30 16:56:04 2000 @@ -13,10 +13,10 @@ sync .S.s: - $(CPP) -D__ASSEMBLY__ $(AFLAGS) -ansi -DST_DIV0=0x2 $< -o $*.s + $(CPP) $(AFLAGS) -ansi -DST_DIV0=0x2 $< -o $*.s .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -DST_DIV0=0x2 -c $< -o $*.o + $(CC) $(AFLAGS) -ansi -DST_DIV0=0x2 -c $< -o $*.o dep: diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc/math-emu/Makefile linux/arch/sparc/math-emu/Makefile --- v2.3.99-pre3/linux/arch/sparc/math-emu/Makefile Mon Dec 20 18:48:21 1999 +++ linux/arch/sparc/math-emu/Makefile Thu Mar 30 16:56:04 2000 @@ -11,10 +11,10 @@ O_OBJS := math.o ashldi3.o .S.s: - $(CPP) -D__ASSEMBLY__ $(AFLAGS) -ansi $< -o $*.s + $(CPP) $(AFLAGS) -ansi $< -o $*.s .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c $< -o $*.o + $(CC) $(AFLAGS) -ansi -c $< -o $*.o CFLAGS += -I. -I$(TOPDIR)/include/math-emu -w diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc/mm/Makefile linux/arch/sparc/mm/Makefile --- v2.3.99-pre3/linux/arch/sparc/mm/Makefile Tue Feb 1 01:35:43 2000 +++ linux/arch/sparc/mm/Makefile Thu Mar 30 16:56:04 2000 @@ -7,6 +7,9 @@ # # Note 2! The CFLAGS definition is now in the main makefile... +.S.o: + $(CC) $(AFLAGS) -ansi -c -o $*.o $< + O_TARGET := mm.o O_OBJS := fault.o init.o loadmmu.o generic.o extable.o btfixup.o ifeq ($(CONFIG_SUN4),y) @@ -21,15 +24,3 @@ endif include $(TOPDIR)/Rules.make - -hypersparc.o: hypersparc.S - $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o hypersparc.o hypersparc.S - -viking.o: viking.S - $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o viking.o viking.S - -tsunami.o: tsunami.S - $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o tsunami.o tsunami.S - -swift.o: swift.S - $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o swift.o swift.S diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc/mm/sun4c.c linux/arch/sparc/mm/sun4c.c --- v2.3.99-pre3/linux/arch/sparc/mm/sun4c.c Sun Feb 20 21:12:38 2000 +++ linux/arch/sparc/mm/sun4c.c Sun Apr 2 15:53:28 2000 @@ -2408,20 +2408,16 @@ */ static void sun4c_vac_alias_fixup(struct vm_area_struct *vma, unsigned long address, pte_t pte) { - struct dentry *dentry = NULL; - struct inode *inode = NULL; pgd_t *pgdp; pte_t *ptep; - if (vma->vm_file) - dentry = vma->vm_file->f_dentry; - if(dentry) - inode = dentry->d_inode; - if(inode) { - struct address_space *mapping = inode->i_mapping; + if (vma->vm_file) { + struct address_space *mapping; unsigned long offset = (address & PAGE_MASK) - vma->vm_start; struct vm_area_struct *vmaring; int alias_found = 0; + + mapping = vma->vm_file->f_dentry->d_inode->i_mapping; spin_lock(&mapping->i_shared_lock); vmaring = mapping->i_mmap; do { diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/config.in linux/arch/sparc64/config.in --- v2.3.99-pre3/linux/arch/sparc64/config.in Mon Mar 27 08:08:22 2000 +++ linux/arch/sparc64/config.in Thu Mar 30 16:54:53 2000 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.105 2000/03/24 00:34:11 davem Exp $ +# $Id: config.in,v 1.107 2000/03/29 11:56:51 davem Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -18,6 +18,8 @@ bool 'Symmetric multi-processing support' CONFIG_SMP # Global things across all Sun machines. +define_bool CONFIG_ISA n +define_bool CONFIG_PCMCIA n define_bool CONFIG_SBUS y define_bool CONFIG_SBUSCHAR y define_bool CONFIG_BUSMOUSE y @@ -29,7 +31,6 @@ define_bool CONFIG_SUN_CONSOLE y define_bool CONFIG_SUN_AUXIO y define_bool CONFIG_SUN_IO y -define_bool CONFIG_ISA n bool 'PCI support' CONFIG_PCI source drivers/pci/Config.in diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig --- v2.3.99-pre3/linux/arch/sparc64/defconfig Mon Mar 27 08:08:22 2000 +++ linux/arch/sparc64/defconfig Mon Mar 27 10:35:56 2000 @@ -13,6 +13,8 @@ CONFIG_VT=y CONFIG_VT_CONSOLE=y # CONFIG_SMP is not set +# CONFIG_ISA is not set +# CONFIG_PCMCIA is not set CONFIG_SBUS=y CONFIG_SBUSCHAR=y CONFIG_BUSMOUSE=y @@ -24,7 +26,6 @@ CONFIG_SUN_CONSOLE=y CONFIG_SUN_AUXIO=y CONFIG_SUN_IO=y -# CONFIG_ISA is not set CONFIG_PCI=y CONFIG_PCI_NAMES=y CONFIG_SUN_OPENPROMFS=m @@ -225,6 +226,7 @@ # CONFIG_BLK_DEV_AEC6210 is not set # CONFIG_AEC6210_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_CMD64X=y diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/kernel/Makefile linux/arch/sparc64/kernel/Makefile --- v2.3.99-pre3/linux/arch/sparc64/kernel/Makefile Mon Mar 27 08:08:22 2000 +++ linux/arch/sparc64/kernel/Makefile Thu Mar 30 16:56:04 2000 @@ -8,10 +8,10 @@ # Note 2! The CFLAGS definitions are now in the main makefile... .S.s: - $(CPP) -D__ASSEMBLY__ $(AFLAGS) -ansi $< -o $*.s + $(CPP) $(AFLAGS) -ansi $< -o $*.s .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c $< -o $*.o + $(CC) $(AFLAGS) -ansi -c $< -o $*.o all: kernel.o head.o init_task.o @@ -54,7 +54,7 @@ head.o: head.S ttable.S itlb_base.S dtlb_base.S dtlb_backend.S dtlb_prot.S \ etrap.S rtrap.S winfixup.S entry.S - $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c $*.S -o $*.o + $(CC) $(AFLAGS) -ansi -c $*.S -o $*.o # # This is just to get the dependencies... @@ -84,7 +84,7 @@ @echo "#undef __SMP__" >> tmp.c @echo "#undef CONFIG_SMP" >> tmp.c @echo "#include " >> tmp.c - $(CC) $(CPPFLAGS) -E tmp.c -o tmp.i + $(CPP) $(CPPFLAGS) tmp.c -o tmp.i @echo "/* Automatically generated. Do not edit. */" > check_asm.c @echo "#include " >> check_asm.c @echo "#undef __SMP__" >> check_asm.c @@ -113,7 +113,7 @@ @echo "#undef CONFIG_SMP" >> tmp.c @echo "#define CONFIG_SMP 1" >> tmp.c @echo "#include " >> tmp.c - $(CC) $(CPPFLAGS) -D__SMP__ -E tmp.c -o tmp.i + $(CPP) $(CPPFLAGS) -D__SMP__ tmp.c -o tmp.i @echo "/* Automatically generated. Do not edit. */" > check_asm.c @echo "#include " >> check_asm.c @echo "#undef CONFIG_SMP" >> check_asm.c @@ -138,7 +138,7 @@ @rm -f check_asm check_asm.c @echo -e "\n#else /* SPIN_LOCK_DEBUG */\n" >> asm_offsets.h @echo "#include " > tmp.c - $(CC) $(CPPFLAGS) -D__SMP__ -DSPIN_LOCK_DEBUG -E tmp.c -o tmp.i + $(CPP) $(CPPFLAGS) -D__SMP__ -DSPIN_LOCK_DEBUG tmp.c -o tmp.i @echo "/* Automatically generated. Do not edit. */" > check_asm.c @echo "#include " >> check_asm.c @echo "#undef CONFIG_SMP" >> check_asm.c diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/kernel/dtlb_base.S linux/arch/sparc64/kernel/dtlb_base.S --- v2.3.99-pre3/linux/arch/sparc64/kernel/dtlb_base.S Tue Feb 1 01:35:43 2000 +++ linux/arch/sparc64/kernel/dtlb_base.S Mon Mar 27 10:35:56 2000 @@ -1,4 +1,4 @@ -/* $Id: dtlb_base.S,v 1.5 2000/01/31 04:59:12 davem Exp $ +/* $Id: dtlb_base.S,v 1.7 2000/03/26 09:13:48 davem Exp $ * dtlb_base.S: Front end to DTLB miss replacement strategy. * This is included directly into the trap table. * @@ -56,19 +56,19 @@ be,pn %xcc, 3f ! Yep, special processing srax %g4, VPTE_SHIFT, %g6 ! Create VPTE offset ldxa [%g3 + %g6] ASI_S, %g5 ! Load VPTE -1: brlz,pt %g5, 2f ! Valid, load into TLB +1: brlz,pt %g5, 9f ! Valid, load into TLB and %g5, (_PAGE_PRESENT|_PAGE_READ), %g4 ! Mask readable bits ba,a,pt %xcc, 4f ! Invalid, branch out /* DTLB ** ICACHE line 2: Quick kernel TLB misses */ -3: brgez,a,pn %g4, 1b ! Kernel virtual map? - ldxa [%g3 + %g6] ASI_N, %g5 ! Yep, load k-vpte - srlx %g4, 40, %g5 ! Else compute phys-kpte - andcc %g5, 1, %g0 ! I/O area? - be,pt %xcc, 2f ! Nope, go and load TLB +3: brlz,pt %g4, 9f ! Kernel virtual map? xor %g2, %g4, %g5 ! Finish bit twiddles - ba,pt %xcc, 2f ! Yes, I/O space, back back - xor %g5, (KERN_IOBITS), %g5 ! After set E, clear CP/CV + ldxa [%g3 + %g6] ASI_N, %g5 ! Yep, load k-vpte + ba,pt %xcc, 1b ! Continue tlb reload + nop +9: stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Reload TLB + retry ! Trap return + nop /* DTLB ** ICACHE line 3: winfixups+real_faults */ 4: cmp %g4, (_PAGE_PRESENT|_PAGE_READ) ! Readable page? @@ -81,14 +81,14 @@ mov TLB_TAG_ACCESS, %g4 ! Prepare for fault processing /* DTLB ** ICACHE line 4: padding */ + ldxa [%g4] ASI_DMMU, %g5 ! Load faulting VA page be,pt %xcc, sparc64_realfault_common ! Jump to normal fault handling - ldxa [%g4] ASI_DMMU, %g5 ! And load faulting VA page + mov FAULT_CODE_DTLB, %g4 ! It was read from DTLB ba,a,pt %xcc, winfix_trampoline ! Call window fixup code 5: or %g5, _PAGE_ACCESSED, %g5 ! Indicate reference or %g5, %g4, %g5 ! Set valid stxa %g5, [%g3 + %g6] ASI_S ! Update PTE table (cant trap) -2: stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Reload TLB - retry ! Trap return + ba,a,pt %xcc, 9b ! Complete tlb miss #undef TAG_CONTEXT_BITS #undef VPTE_SHIFT diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/kernel/dtlb_prot.S linux/arch/sparc64/kernel/dtlb_prot.S --- v2.3.99-pre3/linux/arch/sparc64/kernel/dtlb_prot.S Tue Feb 1 01:35:43 2000 +++ linux/arch/sparc64/kernel/dtlb_prot.S Mon Mar 27 10:35:56 2000 @@ -1,4 +1,4 @@ -/* $Id: dtlb_prot.S,v 1.19 2000/01/31 04:59:12 davem Exp $ +/* $Id: dtlb_prot.S,v 1.20 2000/03/26 09:13:48 davem Exp $ * dtlb_prot.S: DTLB protection trap strategy. * This is included directly into the trap table. * @@ -40,15 +40,15 @@ /* PROT ** ICACHE line 3: Real user faults */ 1: rdpr %pstate, %g5 ! Move into alternate globals wrpr %g5, PSTATE_AG|PSTATE_MG, %pstate - rdpr %tl, %g4 ! Need to do a winfixup? - cmp %g4, 1 ! Trap level >1? + rdpr %tl, %g1 ! Need to do a winfixup? + cmp %g1, 1 ! Trap level >1? mov TLB_TAG_ACCESS, %g4 ! Prepare reload of vaddr bgu,pn %xcc, winfix_trampoline ! Yes, perform winfixup ldxa [%g4] ASI_DMMU, %g5 ! Put tagaccess in %g5 ba,pt %xcc, sparc64_realfault_common ! Nope, normal fault /* PROT ** ICACHE line 4: More real fault processing */ - mov 1, %g4 ! Indicate this was a write + mov FAULT_CODE_DTLB | FAULT_CODE_WRITE, %g4 nop nop nop diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/kernel/ebus.c linux/arch/sparc64/kernel/ebus.c --- v2.3.99-pre3/linux/arch/sparc64/kernel/ebus.c Wed Dec 29 13:13:14 1999 +++ linux/arch/sparc64/kernel/ebus.c Mon Mar 27 10:35:56 2000 @@ -1,4 +1,4 @@ -/* $Id: ebus.c,v 1.46 1999/11/19 05:52:48 davem Exp $ +/* $Id: ebus.c,v 1.47 2000/03/25 05:18:10 davem Exp $ * ebus.c: PCI to EBus bridge device. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -278,7 +278,6 @@ struct linux_ebus *ebus; struct pci_dev *pdev; struct pcidev_cookie *cookie; - unsigned short pci_command; int nd, ebusnd; int num_ebus = 0; @@ -327,17 +326,6 @@ ebus->prom_node = ebusnd; ebus->self = pdev; ebus->parent = pbm = cookie->pbm; - - /* Enable BUS Master. */ - pci_read_config_word(pdev, PCI_COMMAND, &pci_command); - pci_command |= PCI_COMMAND_MASTER; - pci_write_config_word(pdev, PCI_COMMAND, pci_command); - - /* Set reasonable cache line size and latency timer values. */ - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64); - - /* NOTE: Cache line size is in 32-bit word units. */ - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 64/sizeof(u32)); ebus_ranges_init(ebus); ebus_intmap_init(ebus); diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/kernel/entry.S linux/arch/sparc64/kernel/entry.S --- v2.3.99-pre3/linux/arch/sparc64/kernel/entry.S Tue Mar 7 14:32:25 2000 +++ linux/arch/sparc64/kernel/entry.S Thu Mar 30 16:54:53 2000 @@ -1,4 +1,4 @@ -/* $Id: entry.S,v 1.113 2000/03/06 22:33:42 davem Exp $ +/* $Id: entry.S,v 1.115 2000/03/29 09:55:30 davem Exp $ * arch/sparc64/kernel/entry.S: Sparc64 trap low-level entry points. * * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) @@ -998,12 +998,12 @@ mov %i5, %o5 ! IEU1 srl %i2, 0, %o2 ! IEU0 Group - mov %i0, %l5 ! IEU1 - andcc %l0, 0x20, %g0 ! IEU1 Group + andcc %l0, 0x20, %g0 ! IEU0 Group bne,pn %icc, linux_syscall_trace32 ! CTI - srl %i3, 0, %o3 ! IEU0 + mov %i0, %l5 ! IEU1 call %l7 ! CTI Group brk forced - add %o7, 3f-.-4, %o7 ! IEU0 + srl %i3, 0, %o3 ! IEU0 + ba,a,pt %xcc, 3f /* Linux native and SunOS system calls enter here... */ .align 32 @@ -1032,30 +1032,31 @@ mov %i0, %l5 ! IEU0 2: call %l7 ! CTI Group brk forced mov %i5, %o5 ! IEU0 + nop + 3: stx %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0] ret_sys_call: #ifdef SYSCALL_TRACING call syscall_trace_exit add %sp, STACK_BIAS + REGWIN_SZ, %o1 #endif - ldx [%curptr + AOFF_task_flags], %l6 + ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE], %g3 + ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %l1 ! pc = npc sra %o0, 0, %o0 mov %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2 - ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE], %g3 cmp %o0, -ENOIOCTLCMD sllx %g2, 32, %g2 bgeu,pn %xcc, 1f - andcc %l6, 0x20, %l6 - /* System call success, clear Carry condition code. */ - andn %g3, %g2, %g3 + andcc %l0, 0x20, %l6 + andn %g3, %g2, %g3 /* System call success, clear Carry condition code. */ stx %g3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE] bne,pn %icc, linux_syscall_trace2 - ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %l1 ! pc = npc - add %l1, 0x4, %l2 !npc = npc+4 + add %l1, 0x4, %l2 ! npc = npc+4 stx %l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC] - b,pt %xcc, rtrap_clr_l6 + ba,pt %xcc, rtrap_clr_l6 stx %l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC] + 1: /* System call failure, set Carry condition code. * Also, get abs(errno) to return to the process. @@ -1066,15 +1067,14 @@ mov 1, %l6 stx %g3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE] bne,pn %icc, linux_syscall_trace2 - ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %l1 ! pc = npc - add %l1, 0x4, %l2 !npc = npc+4 - + add %l1, 0x4, %l2 !npc = npc+4 stx %l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC] + b,pt %xcc, rtrap stx %l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC] linux_syscall_trace2: call syscall_trace - add %l1, 0x4, %l2 /* npc = npc+4 */ + nop stx %l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC] ba,pt %xcc, rtrap stx %l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC] @@ -1082,6 +1082,9 @@ .align 32 .globl __flushw_user __flushw_user: + rdpr %otherwin, %g1 + brz,pn %g1, 2f + clr %g2 1: save %sp, -128, %sp rdpr %otherwin, %g1 brnz,pt %g1, 1b @@ -1090,4 +1093,4 @@ brnz,pt %g2, 1b restore %g0, %g0, %g0 2: retl - mov %g3, %o7 + nop diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/kernel/etrap.S linux/arch/sparc64/kernel/etrap.S --- v2.3.99-pre3/linux/arch/sparc64/kernel/etrap.S Mon Aug 2 22:07:16 1999 +++ linux/arch/sparc64/kernel/etrap.S Thu Mar 30 16:54:53 2000 @@ -1,4 +1,4 @@ -/* $Id: etrap.S,v 1.42 1999/07/30 09:35:18 davem Exp $ +/* $Id: etrap.S,v 1.43 2000/03/29 09:55:30 davem Exp $ * etrap.S: Preparing for entry into the kernel on Sparc V9. * * Copyright (C) 1996, 1997 David S. Miller (davem@caip.rutgers.edu) @@ -13,6 +13,8 @@ #include #define TASK_REGOFF ((PAGE_SIZE<<1)-TRACEREG_SZ-REGWIN_SZ) +#define ETRAP_PSTATE1 (PSTATE_RMO | PSTATE_PRIV) +#define ETRAP_PSTATE2 (PSTATE_RMO | PSTATE_PEF | PSTATE_PRIV | PSTATE_IE) /* * On entry, %g7 is return address - 0x4. @@ -20,148 +22,167 @@ */ .text - .align 32 - .globl etrap, etrap_irq, etraptl1 - .globl scetrap - -etrap: rdpr %pil, %g2 ! Single Group -etrap_irq: rdpr %tstate, %g1 ! Single Group - sllx %g2, 20, %g3 ! IEU0 Group - andcc %g1, TSTATE_PRIV, %g0 ! IEU1 - or %g1, %g3, %g1 ! IEU0 Group - bne,a,pn %xcc, 1f ! CTI - sub %sp, REGWIN_SZ + TRACEREG_SZ - STACK_BIAS, %g2 ! IEU1 - sethi %hi(TASK_REGOFF), %g2 ! IEU0 Group - sethi %hi(TSTATE_PEF), %g3 ! IEU1 - or %g2, %lo(TASK_REGOFF), %g2 ! IEU0 Group - and %g1, %g3, %g3 ! IEU1 - brnz,pn %g3, 1f ! CTI+IEU1 Group - add %g6, %g2, %g2 ! IEU0 - wr %g0, 0, %fprs ! Single Group+4bubbles -1: rdpr %tpc, %g3 ! Single Group - stx %g1, [%g2 + REGWIN_SZ + PT_V9_TSTATE] ! Store Group - rdpr %tnpc, %g1 ! Single Group - stx %g3, [%g2 + REGWIN_SZ + PT_V9_TPC] ! Store Group - rd %y, %g3 ! Single Group+4bubbles - stx %g1, [%g2 + REGWIN_SZ + PT_V9_TNPC] ! Store Group - st %g3, [%g2 + REGWIN_SZ + PT_V9_Y] ! Store Group - save %g2, -STACK_BIAS, %sp ! The ordering here is ! Single Group - rdpr %pstate, %g1 ! critical, see winfixup ! Single Group+9bubbles - andn %g6, 0x1f, %l6 ! IEU0 Group - bne,pn %xcc, 3f ! CTI - mov PRIMARY_CONTEXT, %l4 ! IEU1 - rdpr %canrestore, %g3 ! Single Group+4bubbles - rdpr %wstate, %g2 ! Single Group+4bubbles - wrpr %g0, 7, %cleanwin ! Single Group+4bubbles - wrpr %g0, 0, %canrestore ! Single Group+4bubbles - sll %g2, 3, %g2 ! IEU0 Group - mov 1, %l5 ! IEU1 - stb %l5, [%l6 + AOFF_task_thread + AOFF_thread_fpdepth] ! Store - wrpr %g3, 0, %otherwin ! Single Group+4bubbles - wrpr %g2, 0, %wstate ! Single Group+4bubbles - stxa %g0, [%l4] ASI_DMMU ! Store Group - flush %l6 ! Single Group+9bubbles - wr %g0, ASI_AIUS, %asi ! Single Group+4bubbles -2: wrpr %g0, 0x0, %tl ! Single Group+4bubbles - andn %g1, PSTATE_MM, %l1 ! IEU0 Group - mov %g4, %l4 ! IEU1 - mov %g5, %l5 ! IEU0 Group - mov %g7, %l2 ! IEU1 - wrpr %l1, (PSTATE_AG|PSTATE_RMO), %pstate ! Single Group+4bubbles - stx %g1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G1] ! Store Group - stx %g2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G2] ! Store Group - stx %g3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G3] ! Store Group - stx %g4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G4] ! Store Group - stx %g5, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G5] ! Store Group - stx %g6, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G6] ! Store Group - stx %g7, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G7] ! Store Group - stx %i0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0] ! Store Group - stx %i1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1] ! Store Group - stx %i2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I2] ! Store Group - stx %i3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I3] ! Store Group - stx %i4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I4] ! Store Group - sethi %uhi(PAGE_OFFSET), %g4 ! IEU0 - stx %i5, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I5] ! Store Group - stx %i6, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I6] ! Store Group - sllx %g4, 32, %g4 ! IEU0 - stx %i7, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I7] ! Store Group - wrpr %l1, (PSTATE_IE|PSTATE_AG|PSTATE_RMO), %pstate ! Single Group+4bubbles - jmpl %l2 + 0x4, %g0 ! CTI Group - mov %l6, %g6 ! IEU0 - -3: ldub [%l6 + AOFF_task_thread + AOFF_thread_fpdepth], %l5 ! Load Group - add %l6, AOFF_task_thread + AOFF_thread_fpsaved + 1, %l4 ! IEU0 - srl %l5, 1, %l3 ! IEU0 Group - add %l5, 2, %l5 ! IEU1 - stb %l5, [%l6 + AOFF_task_thread + AOFF_thread_fpdepth] ! Store - ba,pt %xcc, 2b ! CTI - stb %g0, [%l4 + %l3] ! Store Group - -etraptl1: rdpr %tstate, %g1 ! Single Group+4bubbles - sub %sp, REGWIN_SZ + TRACEREG_SZ - STACK_BIAS, %g2 ! IEU1 - ba,pt %xcc, 1b ! CTI Group - andcc %g1, TSTATE_PRIV, %g0 ! IEU0 - -scetrap: rdpr %pil, %g2 ! Single Group - rdpr %tstate, %g1 ! Single Group - sllx %g2, 20, %g3 ! IEU0 Group - andcc %g1, TSTATE_PRIV, %g0 ! IEU1 - or %g1, %g3, %g1 ! IEU0 Group - bne,a,pn %xcc, 1f ! CTI - sub %sp, REGWIN_SZ + TRACEREG_SZ - STACK_BIAS, %g2 ! IEU1 - sethi %hi(TASK_REGOFF), %g2 ! IEU0 Group - sethi %hi(TSTATE_PEF), %g3 ! IEU1 - or %g2, %lo(TASK_REGOFF), %g2 ! IEU0 Group - and %g1, %g3, %g3 ! IEU1 - brnz,pn %g3, 1f ! CTI+IEU1 Group - add %g6, %g2, %g2 ! IEU0 - wr %g0, 0, %fprs ! Single Group+4bubbles -1: rdpr %tpc, %g3 ! Single Group - stx %g1, [%g2 + REGWIN_SZ + PT_V9_TSTATE] ! Store Group - rdpr %tnpc, %g1 ! Single Group - stx %g3, [%g2 + REGWIN_SZ + PT_V9_TPC] ! Store Group - stx %g1, [%g2 + REGWIN_SZ + PT_V9_TNPC] ! Store Group - st %g0, [%g2 + REGWIN_SZ + PT_V9_Y] ! Store Group - save %g2, -STACK_BIAS, %sp ! The ordering here is ! Single Group - rdpr %pstate, %g1 ! critical, see winfixup ! Single Group+9bubbles - andn %g6, 0x1f, %l6 ! IEU0 Group - bne,pn %xcc, 2f ! CTI - mov PRIMARY_CONTEXT, %l4 ! IEU1 - rdpr %canrestore, %g3 ! Single Group+4bubbles - rdpr %wstate, %g2 ! Single Group+4bubbles - wrpr %g0, 7, %cleanwin ! Single Group+4bubbles - wrpr %g0, 0, %canrestore ! Single Group+4bubbles - sll %g2, 3, %g2 ! IEU0 Group - wrpr %g3, 0, %otherwin ! Single Group+4bubbles - wrpr %g2, 0, %wstate ! Single Group+4bubbles - stxa %g0, [%l4] ASI_DMMU ! Store Group - flush %l6 ! Single Group+9bubbles - wr %g0, ASI_AIUS, %asi ! Single Group+4bubbles -2: wrpr %g0, 0x0, %tl ! Single Group+4bubbles - andn %g1, PSTATE_MM, %l1 ! IEU0 Group - mov %g4, %l4 ! IEU1 - mov %g5, %l5 ! IEU0 Group - mov %g7, %l2 ! IEU1 - wrpr %l1, (PSTATE_AG|PSTATE_RMO), %pstate ! Single Group+4bubbles - stx %g1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G1] ! Store Group - stx %g2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G2] ! Store Group - stx %g3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G3] ! Store Group - stx %g4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G4] ! Store Group - stx %g5, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G5] ! Store Group - stx %g6, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G6] ! Store Group - stx %g7, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G7] ! Store Group - stx %i0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0] ! Store Group - stx %i1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1] ! Store Group - stx %i2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I2] ! Store Group - stx %i3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I3] ! Store Group - stx %i4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I4] ! Store Group - sethi %uhi(PAGE_OFFSET), %g4 ! IEU0 - stx %i5, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I5] ! Store Group - stx %i6, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I6] ! Store Group - sllx %g4, 32, %g4 ! IEU0 - stx %i7, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I7] ! Store Group - wrpr %l1, (PSTATE_IE|PSTATE_AG|PSTATE_RMO), %pstate ! Single Group+4bubbles - jmpl %l2 + 0x4, %g0 ! CTI Group - mov %l6, %g6 ! IEU0 + .align 64 + .globl etrap, etrap_irq, etraptl1 + +etrap: rdpr %pil, %g2 ! Single Group +etrap_irq: rdpr %tstate, %g1 ! Single Group + sllx %g2, 20, %g3 ! IEU0 Group + andcc %g1, TSTATE_PRIV, %g0 ! IEU1 + or %g1, %g3, %g1 ! IEU0 Group + bne,pn %xcc, 1f ! CTI + sub %sp, REGWIN_SZ+TRACEREG_SZ-STACK_BIAS, %g2 ! IEU1 + wrpr %g0, 7, %cleanwin ! Single Group+4bubbles + + sethi %hi(TASK_REGOFF), %g2 ! IEU0 Group + sethi %hi(TSTATE_PEF), %g3 ! IEU1 + or %g2, %lo(TASK_REGOFF), %g2 ! IEU0 Group + and %g1, %g3, %g3 ! IEU1 + brnz,pn %g3, 1f ! CTI+IEU1 Group + add %g6, %g2, %g2 ! IEU0 + wr %g0, 0, %fprs ! Single Group+4bubbles +1: rdpr %tpc, %g3 ! Single Group + + stx %g1, [%g2 + REGWIN_SZ + PT_V9_TSTATE] ! Store Group + rdpr %tnpc, %g1 ! Single Group + stx %g3, [%g2 + REGWIN_SZ + PT_V9_TPC] ! Store Group + rd %y, %g3 ! Single Group+4bubbles + stx %g1, [%g2 + REGWIN_SZ + PT_V9_TNPC] ! Store Group + st %g3, [%g2 + REGWIN_SZ + PT_V9_Y] ! Store Group + save %g2, -STACK_BIAS, %sp ! Ordering here is critical ! Single Group + mov %g6, %l6 ! IEU0 Group + + bne,pn %xcc, 3f ! CTI + mov PRIMARY_CONTEXT, %l4 ! IEU1 + rdpr %canrestore, %g3 ! Single Group+4bubbles + rdpr %wstate, %g2 ! Single Group+4bubbles + wrpr %g0, 0, %canrestore ! Single Group+4bubbles + sll %g2, 3, %g2 ! IEU0 Group + mov 1, %l5 ! IEU1 + stb %l5, [%l6 + AOFF_task_thread + AOFF_thread_fpdepth] ! Store + + wrpr %g3, 0, %otherwin ! Single Group+4bubbles + wrpr %g2, 0, %wstate ! Single Group+4bubbles + stxa %g0, [%l4] ASI_DMMU ! Store Group + flush %l6 ! Single Group+9bubbles + wr %g0, ASI_AIUS, %asi ! Single Group+4bubbles +2: wrpr %g0, 0x0, %tl ! Single Group+4bubbles + mov %g4, %l4 ! IEU1 + mov %g5, %l5 ! IEU0 Group + + mov %g7, %l2 ! IEU1 + wrpr %g0, ETRAP_PSTATE1, %pstate ! Single Group+4bubbles + stx %g1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G1] ! Store Group + stx %g2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G2] ! Store Group + stx %g3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G3] ! Store Group + stx %g4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G4] ! Store Group + stx %g5, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G5] ! Store Group + stx %g6, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G6] ! Store Group + + stx %g7, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G7] ! Store Group + stx %i0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0] ! Store Group + stx %i1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1] ! Store Group + stx %i2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I2] ! Store Group + stx %i3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I3] ! Store Group + stx %i4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I4] ! Store Group + sethi %uhi(PAGE_OFFSET), %g4 ! IEU0 + stx %i5, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I5] ! Store Group + + stx %i6, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I6] ! Store Group + sllx %g4, 32, %g4 ! IEU0 + stx %i7, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I7] ! Store Group + wrpr %g0, ETRAP_PSTATE2, %pstate ! Single Group+4bubbles + jmpl %l2 + 0x4, %g0 ! CTI Group + mov %l6, %g6 ! IEU0 + nop + nop + +3: ldub [%l6 + AOFF_task_thread + AOFF_thread_fpdepth], %l5 ! Load Group + add %l6, AOFF_task_thread + AOFF_thread_fpsaved + 1, %l4 ! IEU0 + srl %l5, 1, %l3 ! IEU0 Group + add %l5, 2, %l5 ! IEU1 + stb %l5, [%l6 + AOFF_task_thread + AOFF_thread_fpdepth] ! Store + ba,pt %xcc, 2b ! CTI + stb %g0, [%l4 + %l3] ! Store Group + nop + +etraptl1: rdpr %tstate, %g1 ! Single Group+4bubbles + sub %sp, REGWIN_SZ + TRACEREG_SZ - STACK_BIAS, %g2 ! IEU1 + ba,pt %xcc, 1b ! CTI Group + andcc %g1, TSTATE_PRIV, %g0 ! IEU0 + + .align 64 + .globl scetrap +scetrap: rdpr %pil, %g2 ! Single Group + rdpr %tstate, %g1 ! Single Group + sllx %g2, 20, %g3 ! IEU0 Group + andcc %g1, TSTATE_PRIV, %g0 ! IEU1 + or %g1, %g3, %g1 ! IEU0 Group + bne,pn %xcc, 1f ! CTI + sub %sp, (REGWIN_SZ+TRACEREG_SZ-STACK_BIAS), %g2 ! IEU1 + wrpr %g0, 7, %cleanwin ! Single Group+4bubbles + + sllx %g1, 51, %g3 ! IEU0 Group + sethi %hi(TASK_REGOFF), %g2 ! IEU1 + or %g2, %lo(TASK_REGOFF), %g2 ! IEU0 Group + brlz,pn %g3, 1f ! CTI+IEU1 + add %g6, %g2, %g2 ! IEU0 Group + wr %g0, 0, %fprs ! Single Group+4bubbles +1: rdpr %tpc, %g3 ! Single Group + stx %g1, [%g2 + REGWIN_SZ + PT_V9_TSTATE] ! Store Group + + rdpr %tnpc, %g1 ! Single Group + stx %g3, [%g2 + REGWIN_SZ + PT_V9_TPC] ! Store Group + stx %g1, [%g2 + REGWIN_SZ + PT_V9_TNPC] ! Store Group + save %g2, -STACK_BIAS, %sp ! Ordering here is critical ! Single Group + mov %g6, %l6 ! IEU0 Group + bne,pn %xcc, 2f ! CTI + mov ASI_P, %l7 ! IEU1 + rdpr %canrestore, %g3 ! Single Group+4bubbles + + rdpr %wstate, %g2 ! Single Group+4bubbles + wrpr %g0, 0, %canrestore ! Single Group+4bubbles + sll %g2, 3, %g2 ! IEU0 Group + mov PRIMARY_CONTEXT, %l4 ! IEU1 + wrpr %g3, 0, %otherwin ! Single Group+4bubbles + wrpr %g2, 0, %wstate ! Single Group+4bubbles + stxa %g0, [%l4] ASI_DMMU ! Store + flush %l6 ! Single Group+9bubbles + + mov ASI_AIUS, %l7 ! IEU0 Group +2: mov %g4, %l4 ! IEU1 + mov %g5, %l5 ! IEU0 Group + add %g7, 0x4, %l2 ! IEU1 + wrpr %g0, ETRAP_PSTATE1, %pstate ! Single Group+4bubbles + stx %g1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G1] ! Store Group + stx %g2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G2] ! Store Group + sllx %l7, 24, %l7 ! IEU0 + + stx %g3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G3] ! Store Group + rdpr %cwp, %l0 ! Single Group + stx %g4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G4] ! Store Group + stx %g5, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G5] ! Store Group + stx %g6, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G6] ! Store Group + stx %g7, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G7] ! Store Group + or %l7, %l0, %l7 ! IEU0 + sethi %hi(TSTATE_RMO | TSTATE_PEF), %l0 ! IEU1 + + or %l7, %l0, %l7 ! IEU0 Group + wrpr %l2, %tnpc ! Single Group+4bubbles + wrpr %l7, (TSTATE_PRIV | TSTATE_IE), %tstate ! Single Group+4bubbles + stx %i0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0] ! Store Group + stx %i1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1] ! Store Group + stx %i2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I2] ! Store Group + stx %i3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I3] ! Store Group + stx %i4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I4] ! Store Group + + sethi %uhi(PAGE_OFFSET), %g4 ! IEU0 + stx %i5, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I5] ! Store Group + stx %i6, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I6] ! Store Group + sllx %g4, 32, %g4 ! IEU0 + mov %l6, %g6 ! IEU1 + stx %i7, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I7] ! Store Group + done + nop #undef TASK_REGOFF diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c --- v2.3.99-pre3/linux/arch/sparc64/kernel/ioctl32.c Mon Mar 27 08:08:22 2000 +++ linux/arch/sparc64/kernel/ioctl32.c Thu Mar 30 16:54:53 2000 @@ -1,4 +1,4 @@ -/* $Id: ioctl32.c,v 1.85 2000/03/23 05:25:41 davem Exp $ +/* $Id: ioctl32.c,v 1.87 2000/03/30 02:09:07 davem Exp $ * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) @@ -2716,6 +2716,25 @@ COMPATIBLE_IOCTL(SG_EMULATED_HOST) COMPATIBLE_IOCTL(SG_SET_TRANSFORM) COMPATIBLE_IOCTL(SG_GET_TRANSFORM) +COMPATIBLE_IOCTL(SG_SET_RESERVED_SIZE) +COMPATIBLE_IOCTL(SG_GET_RESERVED_SIZE) +COMPATIBLE_IOCTL(SG_GET_SCSI_ID) +COMPATIBLE_IOCTL(SG_SET_FORCE_LOW_DMA) +COMPATIBLE_IOCTL(SG_GET_LOW_DMA) +COMPATIBLE_IOCTL(SG_SET_FORCE_PACK_ID) +COMPATIBLE_IOCTL(SG_GET_PACK_ID) +COMPATIBLE_IOCTL(SG_GET_NUM_WAITING) +COMPATIBLE_IOCTL(SG_SET_DEBUG) +COMPATIBLE_IOCTL(SG_GET_SG_TABLESIZE) +COMPATIBLE_IOCTL(SG_GET_COMMAND_Q) +COMPATIBLE_IOCTL(SG_SET_COMMAND_Q) +COMPATIBLE_IOCTL(SG_GET_VERSION_NUM) +COMPATIBLE_IOCTL(SG_NEXT_CMD_LEN) +COMPATIBLE_IOCTL(SG_SCSI_RESET) +COMPATIBLE_IOCTL(SG_IO) +COMPATIBLE_IOCTL(SG_GET_REQUEST_TABLE) +COMPATIBLE_IOCTL(SG_SET_KEEP_ORPHAN) +COMPATIBLE_IOCTL(SG_GET_KEEP_ORPHAN) /* PPP stuff */ COMPATIBLE_IOCTL(PPPIOCGFLAGS) COMPATIBLE_IOCTL(PPPIOCSFLAGS) diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/kernel/itlb_base.S linux/arch/sparc64/kernel/itlb_base.S --- v2.3.99-pre3/linux/arch/sparc64/kernel/itlb_base.S Tue Feb 1 01:35:43 2000 +++ linux/arch/sparc64/kernel/itlb_base.S Mon Mar 27 10:35:56 2000 @@ -1,4 +1,4 @@ -/* $Id: itlb_base.S,v 1.8 2000/01/31 04:59:12 davem Exp $ +/* $Id: itlb_base.S,v 1.9 2000/03/26 09:13:48 davem Exp $ * itlb_base.S: Front end to ITLB miss replacement strategy. * This is included directly into the trap table. * @@ -40,25 +40,25 @@ /* ITLB ** ICACHE line 3: Real faults */ rdpr %tpc, %g5 ! And load faulting VA - clr %g4 ! It was read + mov FAULT_CODE_ITLB, %g4 ! It was read from ITLB sparc64_realfault_common: ! Called by TL0 dtlb_miss too - sethi %hi(1f), %g7 ! Save state - ba,pt %xcc, etrap ! ... -1: or %g7, %lo(1b), %g7 ! ... - mov %l4, %o2 ! Read/Write/No idea - srlx %l5, PAGE_SHIFT, %o1 ! Page align faulting VA - add %sp, STACK_BIAS + REGWIN_SZ, %o0! Compute pt_regs arg - -/* ITLB ** ICACHE line 4: Call fault processing code */ + stb %g4, [%g6 + AOFF_task_thread + AOFF_thread_fault_code] + stx %g5, [%g6 + AOFF_task_thread + AOFF_thread_fault_address] + ba,pt %xcc, etrap ! Save state +1: rd %pc, %g7 ! ... call do_sparc64_fault ! Call fault handler - sllx %o1, PAGE_SHIFT, %o1 ! Finish page alignment - ba,a,pt %xcc, rtrap_clr_l6 ! Restore cpu state - nop + add %sp, STACK_BIAS + REGWIN_SZ, %o0! Compute pt_regs arg + +/* ITLB ** ICACHE line 4: Finish faults + window fixups */ + ba,pt %xcc, rtrap_clr_l6 ! Restore cpu state + nop winfix_trampoline: rdpr %tpc, %g3 ! Prepare winfixup TNPC or %g3, 0x7c, %g3 ! Compute offset to branch wrpr %g3, %tnpc ! Write it into TNPC done ! Do it to it + nop + nop #undef TAG_CONTEXT_BITS #undef VPTE_SHIFT diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/kernel/pci_common.c linux/arch/sparc64/kernel/pci_common.c --- v2.3.99-pre3/linux/arch/sparc64/kernel/pci_common.c Fri Jan 7 19:13:21 2000 +++ linux/arch/sparc64/kernel/pci_common.c Mon Mar 27 10:35:56 2000 @@ -1,4 +1,4 @@ -/* $Id: pci_common.c,v 1.6 2000/01/06 23:51:49 davem Exp $ +/* $Id: pci_common.c,v 1.7 2000/03/25 05:18:11 davem Exp $ * pci_common.c: PCI controller common support. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -563,6 +563,165 @@ walk = &pbus->children; for (walk = walk->next; walk != &pbus->children; walk = walk->next) pci_fixup_irq(pbm, pci_bus_b(walk)); +} + +#undef DEBUG_BUSMASTERING + +static void pdev_setup_busmastering(struct pci_dev *pdev, int is_66mhz) +{ + u16 cmd; + u8 hdr_type, min_gnt, ltimer; + +#ifdef DEBUG_BUSMASTERING + printk("PCI: Checking DEV(%s), ", pdev->name); +#endif + + pci_read_config_word(pdev, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_MASTER; + pci_write_config_word(pdev, PCI_COMMAND, cmd); + + /* Read it back, if the mastering bit did not + * get set, the device does not support bus + * mastering so we have nothing to do here. + */ + pci_read_config_word(pdev, PCI_COMMAND, &cmd); + if ((cmd & PCI_COMMAND_MASTER) == 0) { +#ifdef DEBUG_BUSMASTERING + printk("no bus mastering...\n"); +#endif + return; + } + + /* Set correct cache line size, 64-byte on all + * Sparc64 PCI systems. Note that the value is + * measured in 32-bit words. + */ +#ifdef DEBUG_BUSMASTERING + printk("set cachelinesize, "); +#endif + pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, + 64 / sizeof(u32)); + + pci_read_config_byte(pdev, PCI_HEADER_TYPE, &hdr_type); + hdr_type &= ~0x80; + if (hdr_type != PCI_HEADER_TYPE_NORMAL) { +#ifdef DEBUG_BUSMASTERING + printk("hdr_type=%x, exit\n", hdr_type); +#endif + return; + } + + /* If the latency timer is already programmed with a non-zero + * value, assume whoever set it (OBP or whoever) knows what + * they are doing. + */ + pci_read_config_byte(pdev, PCI_LATENCY_TIMER, <imer); + if (ltimer != 0) { +#ifdef DEBUG_BUSMASTERING + printk("ltimer was %x, exit\n", ltimer); +#endif + return; + } + + /* XXX Since I'm tipping off the min grant value to + * XXX choose a suitable latency timer value, I also + * XXX considered making use of the max latency value + * XXX as well. Unfortunately I've seen too many bogusly + * XXX low settings for it to the point where it lacks + * XXX any usefulness. In one case, an ethernet card + * XXX claimed a min grant of 10 and a max latency of 5. + * XXX Now, if I had two such cards on the same bus I + * XXX could not set the desired burst period (calculated + * XXX from min grant) without violating the max latency + * XXX bound. Duh... + * XXX + * XXX I blame dumb PC bios implementors for stuff like + * XXX this, most of them don't even try to do something + * XXX sensible with latency timer values and just set some + * XXX default value (usually 32) into every device. + */ + + pci_read_config_byte(pdev, PCI_MIN_GNT, &min_gnt); + + if (min_gnt == 0) { + /* If no min_gnt setting then use a default + * value. + */ + if (is_66mhz) + ltimer = 16; + else + ltimer = 32; + } else { + int shift_factor; + + if (is_66mhz) + shift_factor = 2; + else + shift_factor = 3; + + /* Use a default value when the min_gnt value + * is erroneously high. + */ + if (((unsigned int) min_gnt << shift_factor) > 512 || + ((min_gnt << shift_factor) & 0xff) == 0) { + ltimer = 8 << shift_factor; + } else { + ltimer = min_gnt << shift_factor; + } + } + + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, ltimer); +#ifdef DEBUG_BUSMASTERING + printk("set ltimer to %x\n", ltimer); +#endif +} + +void pci_determine_66mhz_disposition(struct pci_pbm_info *pbm, + struct pci_bus *pbus) +{ + struct list_head *walk; + int all_are_66mhz; + u16 status; + + if (pbm->is_66mhz_capable == 0) { + all_are_66mhz = 0; + goto out; + } + + walk = &pbus->devices; + all_are_66mhz = 1; + for (walk = walk->next; walk != &pbus->devices; walk = walk->next) { + struct pci_dev *pdev = pci_dev_b(walk); + + pci_read_config_word(pdev, PCI_STATUS, &status); + if (!(status & PCI_STATUS_66MHZ)) { + all_are_66mhz = 0; + break; + } + } +out: + pbm->all_devs_66mhz = all_are_66mhz; + + printk("PCI%d(PBM%c): Bus running at %dMHz\n", + pbm->parent->index, + (pbm == &pbm->parent->pbm_A) ? 'A' : 'B', + (all_are_66mhz ? 66 : 33)); +} + +void pci_setup_busmastering(struct pci_pbm_info *pbm, + struct pci_bus *pbus) +{ + struct list_head *walk = &pbus->devices; + int is_66mhz; + + is_66mhz = pbm->is_66mhz_capable && pbm->all_devs_66mhz; + + for (walk = walk->next; walk != &pbus->devices; walk = walk->next) + pdev_setup_busmastering(pci_dev_b(walk), is_66mhz); + + walk = &pbus->children; + for (walk = walk->next; walk != &pbus->children; walk = walk->next) + pci_setup_busmastering(pbm, pci_bus_b(walk)); } /* Generic helper routines for PCI error reporting. */ diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/kernel/pci_impl.h linux/arch/sparc64/kernel/pci_impl.h --- v2.3.99-pre3/linux/arch/sparc64/kernel/pci_impl.h Thu Feb 10 17:11:06 2000 +++ linux/arch/sparc64/kernel/pci_impl.h Mon Mar 27 10:35:56 2000 @@ -1,4 +1,4 @@ -/* $Id: pci_impl.h,v 1.5 2000/02/08 05:11:32 jj Exp $ +/* $Id: pci_impl.h,v 1.6 2000/03/25 05:18:11 davem Exp $ * pci_impl.h: Helper definitions for PCI controller support. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -28,6 +28,10 @@ struct pci_bus *pbus); extern void pci_fixup_irq(struct pci_pbm_info *pbm, struct pci_bus *pbus); +extern void pci_determine_66mhz_disposition(struct pci_pbm_info *pbm, + struct pci_bus *pbus); +extern void pci_setup_busmastering(struct pci_pbm_info *pbm, + struct pci_bus *pbus); /* Error reporting support. */ extern void pci_scan_for_target_abort(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *); diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/kernel/pci_psycho.c linux/arch/sparc64/kernel/pci_psycho.c --- v2.3.99-pre3/linux/arch/sparc64/kernel/pci_psycho.c Fri Mar 10 16:40:41 2000 +++ linux/arch/sparc64/kernel/pci_psycho.c Mon Mar 27 10:35:56 2000 @@ -1,4 +1,4 @@ -/* $Id: pci_psycho.c,v 1.14 2000/03/10 02:42:15 davem Exp $ +/* $Id: pci_psycho.c,v 1.15 2000/03/25 05:18:11 davem Exp $ * pci_psycho.c: PSYCHO/U2P specific PCI controller support. * * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu) @@ -1193,6 +1193,23 @@ pbm_renumber(&p->pbm_A, 0xff); } +static void __init pbm_config_busmastering(struct pci_pbm_info *pbm) +{ + u8 *addr; + + /* Set cache-line size to 64 bytes, this is actually + * a nop but I do it for completeness. + */ + addr = psycho_pci_config_mkaddr(pbm, pbm->pci_first_busno, + 0, PCI_CACHE_LINE_SIZE); + pci_config_write8(addr, 64 / sizeof(u32)); + + /* Set PBM latency timer to 64 PCI clocks. */ + addr = psycho_pci_config_mkaddr(pbm, pbm->pci_first_busno, + 0, PCI_LATENCY_TIMER); + pci_config_write8(addr, 64); +} + static void __init pbm_scan_bus(struct pci_controller_info *p, struct pci_pbm_info *pbm) { @@ -1203,11 +1220,17 @@ pci_record_assignments(pbm, pbm->pci_bus); pci_assign_unassigned(pbm, pbm->pci_bus); pci_fixup_irq(pbm, pbm->pci_bus); + pci_determine_66mhz_disposition(pbm, pbm->pci_bus); + pci_setup_busmastering(pbm, pbm->pci_bus); } static void __init psycho_scan_bus(struct pci_controller_info *p) { pbm_bridge_reconfigure(p); + pbm_config_busmastering(&p->pbm_B); + p->pbm_B.is_66mhz_capable = 0; + pbm_config_busmastering(&p->pbm_A); + p->pbm_A.is_66mhz_capable = 1; pbm_scan_bus(p, &p->pbm_B); pbm_scan_bus(p, &p->pbm_A); diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/kernel/pci_sabre.c linux/arch/sparc64/kernel/pci_sabre.c --- v2.3.99-pre3/linux/arch/sparc64/kernel/pci_sabre.c Fri Mar 10 16:40:41 2000 +++ linux/arch/sparc64/kernel/pci_sabre.c Mon Mar 27 10:35:56 2000 @@ -1,4 +1,4 @@ -/* $Id: pci_sabre.c,v 1.15 2000/03/10 02:42:16 davem Exp $ +/* $Id: pci_sabre.c,v 1.16 2000/03/25 05:18:12 davem Exp $ * pci_sabre.c: Sabre specific PCI controller support. * * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu) @@ -1060,6 +1060,13 @@ struct pci_bus *sabre_bus; struct list_head *walk; + /* The APB bridge speaks to the Sabre host PCI bridge + * at 66Mhz, but the front side of APB runs at 33Mhz + * for both segments. + */ + p->pbm_A.is_66mhz_capable = 0; + p->pbm_B.is_66mhz_capable = 0; + /* Unlike for PSYCHO, we can only have one SABRE * in a system. Having multiple SABREs is thus * and error, and as a consequence we do not need @@ -1079,6 +1086,17 @@ sabre_bus = pci_scan_bus(p->pci_first_busno, p->pci_ops, &p->pbm_A); + + { + unsigned int devfn; + u8 *addr; + + devfn = PCI_DEVFN(0, 0); + addr = sabre_pci_config_mkaddr(&p->pbm_A, 0, + devfn, PCI_LATENCY_TIMER); + pci_config_write8(addr, 32); + } + apb_init(p, sabre_bus); walk = &sabre_bus->children; @@ -1099,6 +1117,8 @@ pci_record_assignments(pbm, pbus); pci_assign_unassigned(pbm, pbus); pci_fixup_irq(pbm, pbus); + pci_determine_66mhz_disposition(pbm, pbus); + pci_setup_busmastering(pbm, pbus); } sabre_register_error_handlers(p); diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c --- v2.3.99-pre3/linux/arch/sparc64/kernel/process.c Thu Mar 2 14:36:22 2000 +++ linux/arch/sparc64/kernel/process.c Mon Mar 27 10:35:56 2000 @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.104 2000/03/01 02:53:32 davem Exp $ +/* $Id: process.c,v 1.105 2000/03/26 09:13:48 davem Exp $ * arch/sparc64/kernel/process.c * * Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu) @@ -451,7 +451,7 @@ { unsigned long fp, distance, rval; - if(!(current->thread.flags & SPARC_FLAG_32BIT)) { + if (!(current->thread.flags & SPARC_FLAG_32BIT)) { csp += STACK_BIAS; psp += STACK_BIAS; __get_user(fp, &(((struct reg_window *)psp)->ins[6])); @@ -466,14 +466,14 @@ distance = fp - psp; rval = (csp - distance); - if(copy_in_user(rval, psp, distance)) + if (copy_in_user(rval, psp, distance)) rval = 0; - else if(current->thread.flags & SPARC_FLAG_32BIT) { - if(put_user(((u32)csp), &(((struct reg_window32 *)rval)->ins[6]))) + else if (current->thread.flags & SPARC_FLAG_32BIT) { + if (put_user(((u32)csp), &(((struct reg_window32 *)rval)->ins[6]))) rval = 0; } else { - if(put_user(((u64)csp - STACK_BIAS), - &(((struct reg_window *)rval)->ins[6]))) + if (put_user(((u64)csp - STACK_BIAS), + &(((struct reg_window *)rval)->ins[6]))) rval = 0; else rval = rval - STACK_BIAS; @@ -488,7 +488,7 @@ { int i; - for(i = first_win; i < last_win; i++) { + for (i = first_win; i < last_win; i++) { t->rwbuf_stkptrs[i] = t->rwbuf_stkptrs[i+1]; memcpy(&t->reg_window[i], &t->reg_window[i+1], sizeof(struct reg_window)); @@ -501,11 +501,11 @@ unsigned long window; flush_user_windows(); - if((window = t->w_saved) != 0) { + if ((window = t->w_saved) != 0) { int winsize = REGWIN_SZ; int bias = 0; - if(t->flags & SPARC_FLAG_32BIT) + if (t->flags & SPARC_FLAG_32BIT) winsize = REGWIN32_SZ; else bias = STACK_BIAS; @@ -515,11 +515,11 @@ unsigned long sp = (t->rwbuf_stkptrs[window] + bias); struct reg_window *rwin = &t->reg_window[window]; - if(!copy_to_user((char *)sp, rwin, winsize)) { + if (!copy_to_user((char *)sp, rwin, winsize)) { shift_window_buffer(window, t->w_saved - 1, t); t->w_saved--; } - } while(window--); + } while (window--); } } @@ -530,25 +530,29 @@ int winsize = REGWIN_SZ; int bias = 0; - if(t->flags & SPARC_FLAG_32BIT) + if (t->flags & SPARC_FLAG_32BIT) winsize = REGWIN32_SZ; else bias = STACK_BIAS; + flush_user_windows(); window = t->w_saved; - if(window != 0) { + + if (window != 0) { window -= 1; do { unsigned long sp = (t->rwbuf_stkptrs[window] + bias); struct reg_window *rwin = &t->reg_window[window]; - if(copy_to_user((char *)sp, rwin, winsize)) + if (copy_to_user((char *)sp, rwin, winsize)) goto barf; - } while(window--); + } while (window--); } t->w_saved = 0; return; + barf: + t->w_saved = window + 1; do_exit(SIGILL); } @@ -578,7 +582,8 @@ t->kregs = (struct pt_regs *)(child_trap_frame+sizeof(struct reg_window)); t->cwp = (regs->tstate + 1) & TSTATE_CWP; t->fpsaved[0] = 0; - if(regs->tstate & TSTATE_PRIV) { + + if (regs->tstate & TSTATE_PRIV) { /* Special case, if we are spawning a kernel thread from * a userspace task (via KMOD, NFS, or similar) we must * disable performance counters in the child because the @@ -597,7 +602,7 @@ sizeof(struct reg_window)); t->kregs->u_regs[UREG_G6] = (unsigned long) p; } else { - if(t->flags & SPARC_FLAG_32BIT) { + if (t->flags & SPARC_FLAG_32BIT) { sp &= 0x00000000ffffffffUL; regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL; } @@ -607,7 +612,7 @@ unsigned long csp; csp = clone_stackframe(sp, regs->u_regs[UREG_FP]); - if(!csp) + if (!csp) return -EFAULT; t->kregs->u_regs[UREG_FP] = csp; } @@ -621,19 +626,7 @@ /* Set the second return value for the parent. */ regs->u_regs[UREG_I1] = 0; -#if 0 - printk("\ncopy_thread: c(%p[mm(%p:%p)]) p(%p[mm(%p:%p)])\n", - current, current->mm, current->active_mm, - p, p->mm, p->active_mm); - printk("copy_thread: c MM_ctx(%016lx) MM_pgd(%016lx)\n", - (current->mm ? current->mm->context : 0), - (current->mm ? pgd_val(current->mm->pgd[0]) : 0)); - printk("copy_thread: p MM_ctx(%016lx) MM_pgd(%08x)\n", - (p->mm ? p->mm->context : 0), - (p->mm ? pgd_val(p->mm->pgd[0]) : 0)); - printk("copy_thread: c->flags(%x) p->flags(%x) ", - current->thread.flags, p->thread.flags); -#endif + return 0; } diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/kernel/rtrap.S linux/arch/sparc64/kernel/rtrap.S --- v2.3.99-pre3/linux/arch/sparc64/kernel/rtrap.S Thu Feb 10 17:11:06 2000 +++ linux/arch/sparc64/kernel/rtrap.S Thu Mar 30 16:54:53 2000 @@ -1,4 +1,4 @@ -/* $Id: rtrap.S,v 1.48 2000/02/09 11:15:07 davem Exp $ +/* $Id: rtrap.S,v 1.49 2000/03/29 09:55:31 davem Exp $ * rtrap.S: Preparing for return from trap on Sparc V9. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -14,194 +14,207 @@ #include #define PTREGS_OFF (STACK_BIAS + REGWIN_SZ) +#define RTRAP_PSTATE (PSTATE_RMO|PSTATE_PEF|PSTATE_PRIV|PSTATE_IE) +#define RTRAP_PSTATE_IRQOFF (PSTATE_RMO|PSTATE_PEF|PSTATE_PRIV) +#define RTRAP_PSTATE_AG_IRQOFF (PSTATE_RMO|PSTATE_PEF|PSTATE_PRIV|PSTATE_AG) + +#if 0 +#define RTRAP_CHECK call rtrap_check; add %sp, (STACK_BIAS+REGWIN_SZ), %o0; +#else +#define RTRAP_CHECK +#endif .text + .align 32 +__handle_softirq: + call do_softirq + nop + ba,a,pt %xcc, __handle_softirq_continue + nop +__handle_preemption: + call schedule + nop + ba,pt %xcc, __handle_preemption_continue + nop +__handle_user_windows: + wrpr %g0, RTRAP_PSTATE, %pstate + call fault_in_user_windows + add %sp, STACK_BIAS + REGWIN_SZ, %g0 + ba,a,pt %xcc, __handle_user_windows_continue +__handle_perfctrs: + /* Don't forget to preserve user window invariants. */ + wrpr %g0, RTRAP_PSTATE, %pstate + call update_perfctrs + nop + wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate + ldub [%g6 + AOFF_task_thread + AOFF_thread_w_saved], %o2 + brz,pt %o2, __handle_perfctrs_continue + sethi %hi(TSTATE_PEF), %l6 + wrpr %g0, RTRAP_PSTATE, %pstate + + call fault_in_user_windows + add %sp, STACK_BIAS + REGWIN_SZ, %o0 + ba,pt %xcc, __handle_perfctrs_continue + nop +__handle_userfpu: + rd %fprs, %l5 + andcc %l5, FPRS_FEF, %g0 + be,a,pn %icc, __handle_userfpu_continue + andn %l1, %l6, %l1 + ba,a,pt %xcc, __handle_userfpu_continue +__handle_signal: + clr %o0 + mov %l5, %o2 + mov %l6, %o3 + call do_signal + add %sp, STACK_BIAS + REGWIN_SZ, %o1 + ba,pt %xcc, __handle_signal_continue + clr %l6 + nop + + .align 64 .globl rtrap_clr_l6, rtrap rtrap_clr_l6: clr %l6 - /* Fall through */ rtrap: lduw [%g6 + AOFF_task_processor], %l0 sethi %hi(softirq_state), %l2 or %l2, %lo(softirq_state), %l2 sllx %l0, 6, %l0 ldx [%l2 + %l0], %l1 srlx %l1, 32, %l2 - andcc %l1, %l2, %g0 - be,pt %icc, 2f - nop - call do_softirq - nop -2: ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1 + + bne,pn %icc, __handle_softirq + ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1 +__handle_softirq_continue: sethi %hi(0xf << 20), %l4 andcc %l1, TSTATE_PRIV, %l3 - and %l1, %l4, %l4 - rdpr %pstate, %l7 - andn %l1, %l4, %l1 - be,pt %icc, to_user - andn %l7, PSTATE_IE, %l7 + bne,pn %icc, to_kernel + andn %l1, %l4, %l1 +to_user: ldx [%g6 + AOFF_task_need_resched], %l0 + + brnz,pn %l0, __handle_preemption +__handle_preemption_continue: + lduw [%g6 + AOFF_task_sigpending], %l0 + brnz,pn %l0, __handle_signal + nop +__handle_signal_continue: +check_user_wins: + wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate + ldub [%g6 + AOFF_task_thread + AOFF_thread_w_saved], %o2 + brnz,pn %o2, __handle_user_windows + sethi %hi(TSTATE_PEF), %l6 + +__handle_user_windows_continue: + RTRAP_CHECK + ldub [%g6 + AOFF_task_thread + AOFF_thread_flags], %l5 + andcc %l5, SPARC_FLAG_PERFCTR, %g0 + bne,pn %xcc, __handle_perfctrs +__handle_perfctrs_continue: + andcc %l1, %l6, %g0 + bne,pn %xcc, __handle_userfpu + stb %g0, [%g6 + AOFF_task_thread + AOFF_thread_fpdepth] ! This is neccessary for non-syscall rtraps only +__handle_userfpu_continue: - ldub [%g6 + AOFF_task_thread + AOFF_thread_fpdepth], %l5 - brz,pt %l5, rt_continue - srl %l5, 1, %o0 - add %g6, AOFF_task_thread + AOFF_thread_fpsaved, %l6 - ldub [%l6 + %o0], %l2 - sub %l5, 2, %l5 - add %g6, AOFF_task_thread + AOFF_thread_gsr, %o1 - andcc %l2, (FPRS_FEF|FPRS_DU), %g0 - be,pt %icc, 2f - and %l2, FPRS_DL, %l6 - andcc %l2, FPRS_FEF, %g0 - be,pn %icc, 5f - sll %o0, 3, %o5 - rd %fprs, %g5 - wr %g5, FPRS_FEF, %fprs - ldub [%o1 + %o0], %g5 - add %g6, AOFF_task_thread + AOFF_thread_xfsr, %o1 - membar #StoreLoad | #LoadLoad - sll %o0, 8, %o2 - add %g6, AOFF_task_fpregs, %o3 - brz,pn %l6, 1f - add %g6, AOFF_task_fpregs+0x40, %o4 - ldda [%o3 + %o2] ASI_BLK_P, %f0 - ldda [%o4 + %o2] ASI_BLK_P, %f16 -1: andcc %l2, FPRS_DU, %g0 - be,pn %icc, 1f - wr %g5, 0, %gsr - add %o2, 0x80, %o2 - ldda [%o3 + %o2] ASI_BLK_P, %f32 - ldda [%o4 + %o2] ASI_BLK_P, %f48 -1: membar #Sync - ldx [%o1 + %o5], %fsr -2: stb %l5, [%g6 + AOFF_task_thread + AOFF_thread_fpdepth] rt_continue: ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1 ldx [%sp + PTREGS_OFF + PT_V9_G2], %g2 + ldx [%sp + PTREGS_OFF + PT_V9_G3], %g3 - mov %g6, %o5 ldx [%sp + PTREGS_OFF + PT_V9_G4], %g4 ldx [%sp + PTREGS_OFF + PT_V9_G5], %g5 ldx [%sp + PTREGS_OFF + PT_V9_G6], %g6 ldx [%sp + PTREGS_OFF + PT_V9_G7], %g7 - - wrpr %l7, PSTATE_AG, %pstate + wrpr %g0, RTRAP_PSTATE_AG_IRQOFF, %pstate ldx [%sp + PTREGS_OFF + PT_V9_I0], %i0 ldx [%sp + PTREGS_OFF + PT_V9_I1], %i1 + ldx [%sp + PTREGS_OFF + PT_V9_I2], %i2 ldx [%sp + PTREGS_OFF + PT_V9_I3], %i3 ldx [%sp + PTREGS_OFF + PT_V9_I4], %i4 ldx [%sp + PTREGS_OFF + PT_V9_I5], %i5 ldx [%sp + PTREGS_OFF + PT_V9_I6], %i6 - ldx [%sp + PTREGS_OFF + PT_V9_I7], %i7 - ld [%sp + PTREGS_OFF + PT_V9_Y], %o3 ldx [%sp + PTREGS_OFF + PT_V9_TPC], %l2 ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %o2 + + ld [%sp + PTREGS_OFF + PT_V9_Y], %o3 wr %o3, %g0, %y srl %l4, 20, %l4 wrpr %l4, 0x0, %pil wrpr %g0, 0x1, %tl - wrpr %l1, %g0, %tstate wrpr %l2, %g0, %tpc wrpr %o2, %g0, %tnpc + brnz,pn %l3, kern_rtt mov PRIMARY_CONTEXT, %l7 ldxa [%l7 + %l7] ASI_DMMU, %l0 stxa %l0, [%l7] ASI_DMMU - flush %o5 - + flush %g6 rdpr %wstate, %l1 rdpr %otherwin, %l2 srl %l1, 3, %l1 + wrpr %l2, %g0, %canrestore wrpr %l1, %g0, %wstate wrpr %g0, %g0, %otherwin restore rdpr %canrestore, %g1 - wrpr %g1, 0x0, %cleanwin retry + nop + kern_rtt: restore retry -to_user: ldx [%g6 + AOFF_task_need_resched], %l0 - wrpr %l7, PSTATE_IE, %pstate - orcc %g0, %l0, %g0 - be,a,pt %xcc, check_signal - - lduw [%g6 + AOFF_task_sigpending], %l0 - call schedule - nop - lduw [%g6 + AOFF_task_sigpending], %l0 -check_signal: brz,a,pt %l0, check_user_wins - nop - clr %o0 - mov %l5, %o2 - mov %l6, %o3 - call do_signal - add %sp, STACK_BIAS + REGWIN_SZ, %o1 - clr %l6 - - /* We must not take any traps between here and the actual - * return to user-space. If we do we risk having windows - * saved to the thread struct between the test and the - * actual return from trap. --DaveM - */ -check_user_wins: - wrpr %l7, 0x0, %pstate - ldub [%g6 + AOFF_task_thread + AOFF_thread_w_saved], %o2 - brz,pt %o2, 1f - sethi %hi(TSTATE_PEF), %l6 +to_kernel: ldub [%g6 + AOFF_task_thread + AOFF_thread_fpdepth], %l5 + brz,pt %l5, rt_continue + srl %l5, 1, %o0 + add %g6, AOFF_task_thread + AOFF_thread_fpsaved, %l6 + ldub [%l6 + %o0], %l2 + sub %l5, 2, %l5 - wrpr %l7, PSTATE_IE, %pstate - call fault_in_user_windows - add %sp, STACK_BIAS + REGWIN_SZ, %o0 - /* It is OK to leave interrupts on now because if - * fault_in_user_windows has returned it has left us - * with a clean user stack state. - */ -1: -#if 0 - call rtrap_check - add %sp, STACK_BIAS + REGWIN_SZ, %o0 -#endif - ldub [%g6 + AOFF_task_thread + AOFF_thread_flags], %l5 - andcc %l5, SPARC_FLAG_PERFCTR, %g0 - be,pt %xcc, 1f - nop + add %g6, AOFF_task_thread + AOFF_thread_gsr, %o1 + andcc %l2, (FPRS_FEF|FPRS_DU), %g0 + be,pt %icc, 2f + and %l2, FPRS_DL, %l6 + andcc %l2, FPRS_FEF, %g0 + be,pn %icc, 5f + sll %o0, 3, %o5 + rd %fprs, %g5 - /* Don't forget to preserve user window invariants. */ - wrpr %l7, PSTATE_IE, %pstate - call update_perfctrs - nop - wrpr %l7, 0x0, %pstate - ldub [%g6 + AOFF_task_thread + AOFF_thread_w_saved], %o2 - brz,pt %o2, 1f - sethi %hi(TSTATE_PEF), %l6 - wrpr %l7, PSTATE_IE, %pstate - call fault_in_user_windows - add %sp, STACK_BIAS + REGWIN_SZ, %o0 + wr %g5, FPRS_FEF, %fprs + ldub [%o1 + %o0], %g5 + add %g6, AOFF_task_thread + AOFF_thread_xfsr, %o1 + membar #StoreLoad | #LoadLoad + sll %o0, 8, %o2 + add %g6, AOFF_task_fpregs, %o3 + brz,pn %l6, 1f + add %g6, AOFF_task_fpregs+0x40, %o4 -1: - andcc %l1, %l6, %g0 - be,pt %xcc, rt_continue - stb %g0, [%g6 + AOFF_task_thread + AOFF_thread_fpdepth] ! This is neccessary for non-syscall rtraps only + ldda [%o3 + %o2] ASI_BLK_P, %f0 + ldda [%o4 + %o2] ASI_BLK_P, %f16 +1: andcc %l2, FPRS_DU, %g0 + be,pn %icc, 1f + wr %g5, 0, %gsr + add %o2, 0x80, %o2 + ldda [%o3 + %o2] ASI_BLK_P, %f32 + ldda [%o4 + %o2] ASI_BLK_P, %f48 - rd %fprs, %l5 - andcc %l5, FPRS_FEF, %g0 - be,a,pn %icc, rt_continue - andn %l1, %l6, %l1 +1: membar #Sync + ldx [%o1 + %o5], %fsr +2: stb %l5, [%g6 + AOFF_task_thread + AOFF_thread_fpdepth] ba,pt %xcc, rt_continue nop - 5: wr %g0, FPRS_FEF, %fprs membar #StoreLoad | #LoadLoad sll %o0, 8, %o2 + add %g6, AOFF_task_fpregs+0x80, %o3 add %g6, AOFF_task_fpregs+0xc0, %o4 ldda [%o3 + %o2] ASI_BLK_P, %f32 ldda [%o4 + %o2] ASI_BLK_P, %f48 -1: membar #Sync + membar #Sync wr %g0, FPRS_DU, %fprs ba,pt %xcc, rt_continue stb %l5, [%g6 + AOFF_task_thread + AOFF_thread_fpdepth] diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/kernel/semaphore.c linux/arch/sparc64/kernel/semaphore.c --- v2.3.99-pre3/linux/arch/sparc64/kernel/semaphore.c Tue Jan 4 13:57:16 2000 +++ linux/arch/sparc64/kernel/semaphore.c Thu Mar 30 16:54:53 2000 @@ -1,4 +1,4 @@ -/* $Id: semaphore.c,v 1.2 1999/12/23 17:12:03 jj Exp $ +/* $Id: semaphore.c,v 1.3 2000/03/27 10:38:46 davem Exp $ * Generic semaphore code. Buyer beware. Do your own * specific changes in */ @@ -203,7 +203,7 @@ add_wait_queue(&sem->wait, &wait); /* put ourselves at the head of the list */ for (;;) { - if (clear_le_bit(0, &sem->granted)) + if (test_and_clear_le_bit(0, &sem->granted)) break; set_task_state(tsk, TASK_UNINTERRUPTIBLE); if (!test_le_bit(0, &sem->granted)) @@ -221,7 +221,7 @@ add_wait_queue_exclusive(&sem->write_bias_wait, &wait); /* put ourselves at the end of the list */ for (;;) { - if (clear_le_bit(1, &sem->granted)) + if (test_and_clear_le_bit(1, &sem->granted)) break; set_task_state(tsk, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE); if (!test_le_bit(1, &sem->granted)) @@ -286,11 +286,11 @@ void __rwsem_wake(struct rw_semaphore *sem, unsigned long readers) { if (readers) { - if (set_le_bit(0, &sem->granted)) + if (test_and_set_le_bit(0, &sem->granted)) BUG(); wake_up(&sem->wait); } else { - if (set_le_bit(1, &sem->granted)) + if (test_and_set_le_bit(1, &sem->granted)) BUG(); wake_up(&sem->write_bias_wait); } diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/kernel/signal.c linux/arch/sparc64/kernel/signal.c --- v2.3.99-pre3/linux/arch/sparc64/kernel/signal.c Wed Dec 29 13:13:14 1999 +++ linux/arch/sparc64/kernel/signal.c Sun Apr 2 15:53:27 2000 @@ -616,7 +616,9 @@ if (map->vm_file != NULL) { dev = map->vm_file->f_dentry->d_inode->i_dev; ino = map->vm_file->f_dentry->d_inode->i_ino; - line = d_path(map->vm_file->f_dentry, buffer, PAGE_SIZE); + line = d_path(map->vm_file->f_dentry, + map->vm_file->f_vfsmnt, + buffer, PAGE_SIZE); } printk(MAPS_LINE_FORMAT, map->vm_start, map->vm_end, str, map->vm_pgoff << PAGE_SHIFT, kdevname(dev), ino); diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/kernel/signal32.c linux/arch/sparc64/kernel/signal32.c --- v2.3.99-pre3/linux/arch/sparc64/kernel/signal32.c Sat Feb 26 22:31:42 2000 +++ linux/arch/sparc64/kernel/signal32.c Sun Apr 2 15:53:28 2000 @@ -1279,7 +1279,9 @@ if (map->vm_file != NULL) { dev = map->vm_file->f_dentry->d_inode->i_dev; ino = map->vm_file->f_dentry->d_inode->i_ino; - line = d_path(map->vm_file->f_dentry, buffer, PAGE_SIZE); + line = d_path(map->vm_file->f_dentry, + map->vm_file->f_vfsmnt, + buffer, PAGE_SIZE); } printk(MAPS_LINE_FORMAT, map->vm_start, map->vm_end, str, map->vm_pgoff << PAGE_SHIFT, kdevname(dev), ino); diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/kernel/smp.c linux/arch/sparc64/kernel/smp.c --- v2.3.99-pre3/linux/arch/sparc64/kernel/smp.c Sun Mar 19 18:35:30 2000 +++ linux/arch/sparc64/kernel/smp.c Thu Mar 30 16:54:53 2000 @@ -469,52 +469,83 @@ */ void smp_flush_tlb_mm(struct mm_struct *mm) { - u32 ctx = CTX_HWBITS(mm->context); - - if (mm == current->active_mm && - atomic_read(&mm->mm_users) == 1 && - (mm->cpu_vm_mask == (1UL << smp_processor_id()))) - goto local_flush_and_out; + if (CTX_VALID(mm->context)) { + u32 ctx = CTX_HWBITS(mm->context); + int cpu = smp_processor_id(); + + if (mm == current->active_mm && atomic_read(&mm->mm_users) == 1) { + /* See smp_flush_tlb_page for info about this. */ + mm->cpu_vm_mask = (1UL << cpu); + goto local_flush_and_out; + } - smp_cross_call(&xcall_flush_tlb_mm, ctx, 0, 0); + smp_cross_call(&xcall_flush_tlb_mm, ctx, 0, 0); -local_flush_and_out: - __flush_tlb_mm(ctx, SECONDARY_CONTEXT); + local_flush_and_out: + __flush_tlb_mm(ctx, SECONDARY_CONTEXT); + } } void smp_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) { - u32 ctx = CTX_HWBITS(mm->context); - - start &= PAGE_MASK; - end &= PAGE_MASK; - if(mm == current->active_mm && - atomic_read(&mm->mm_users) == 1 && - (mm->cpu_vm_mask == (1UL << smp_processor_id()))) - goto local_flush_and_out; + if (CTX_VALID(mm->context)) { + u32 ctx = CTX_HWBITS(mm->context); + int cpu = smp_processor_id(); + + start &= PAGE_MASK; + end &= PAGE_MASK; + + if (mm == current->active_mm && atomic_read(&mm->mm_users) == 1) { + mm->cpu_vm_mask = (1UL << cpu); + goto local_flush_and_out; + } - smp_cross_call(&xcall_flush_tlb_range, ctx, start, end); + smp_cross_call(&xcall_flush_tlb_range, ctx, start, end); -local_flush_and_out: - __flush_tlb_range(ctx, start, SECONDARY_CONTEXT, end, PAGE_SIZE, (end-start)); + local_flush_and_out: + __flush_tlb_range(ctx, start, SECONDARY_CONTEXT, end, PAGE_SIZE, (end-start)); + } } void smp_flush_tlb_page(struct mm_struct *mm, unsigned long page) { - u32 ctx = CTX_HWBITS(mm->context); - - page &= PAGE_MASK; - if(mm == current->active_mm && - atomic_read(&mm->mm_users) == 1 && - (mm->cpu_vm_mask == (1UL << smp_processor_id()))) { - goto local_flush_and_out; - } + if (CTX_VALID(mm->context)) { + u32 ctx = CTX_HWBITS(mm->context); + int cpu = smp_processor_id(); + + page &= PAGE_MASK; + if (mm == current->active_mm && atomic_read(&mm->mm_users) == 1) { + /* By virtue of being the current address space, and + * having the only reference to it, the following operation + * is safe. + * + * It would not be a win to perform the xcall tlb flush in + * this case, because even if we switch back to one of the + * other processors in cpu_vm_mask it is almost certain that + * all TLB entries for this context will be replaced by the + * time that happens. + */ + mm->cpu_vm_mask = (1UL << cpu); + goto local_flush_and_out; + } else { + /* By virtue of running under the mm->page_table_lock, + * and mmu_context.h:switch_mm doing the same, the following + * operation is safe. + */ + if (mm->cpu_vm_mask == (1UL << cpu)) + goto local_flush_and_out; + } - smp_cross_call(&xcall_flush_tlb_page, ctx, page, 0); + /* OK, we have to actually perform the cross call. Most likely + * this is a cloned mm or kswapd is kicking out pages for a task + * which has run recently on another cpu. + */ + smp_cross_call(&xcall_flush_tlb_page, ctx, page, 0); -local_flush_and_out: - __flush_tlb_page(ctx, page, SECONDARY_CONTEXT); + local_flush_and_out: + __flush_tlb_page(ctx, page, SECONDARY_CONTEXT); + } } /* CPU capture. */ @@ -603,13 +634,16 @@ extern int rwlock_impl_begin, rwlock_impl_end; extern int atomic_impl_begin, atomic_impl_end; extern int __memcpy_begin, __memcpy_end; + extern int __bitops_begin, __bitops_end; if ((pc >= (unsigned long) &atomic_impl_begin && pc < (unsigned long) &atomic_impl_end) || (pc >= (unsigned long) &rwlock_impl_begin && pc < (unsigned long) &rwlock_impl_end) || (pc >= (unsigned long) &__memcpy_begin && - pc < (unsigned long) &__memcpy_end)) + pc < (unsigned long) &__memcpy_end) || + (pc >= (unsigned long) &__bitops_begin && + pc < (unsigned long) &__bitops_end)) pc = o7; pc -= (unsigned long) &_stext; diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c --- v2.3.99-pre3/linux/arch/sparc64/kernel/sparc64_ksyms.c Sun Mar 19 18:35:30 2000 +++ linux/arch/sparc64/kernel/sparc64_ksyms.c Thu Mar 30 16:54:53 2000 @@ -1,4 +1,4 @@ -/* $Id: sparc64_ksyms.c,v 1.79 2000/03/17 14:41:18 davem Exp $ +/* $Id: sparc64_ksyms.c,v 1.80 2000/03/27 10:38:47 davem Exp $ * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -169,6 +169,13 @@ /* Atomic counter implementation. */ EXPORT_SYMBOL_PRIVATE(atomic_add); EXPORT_SYMBOL_PRIVATE(atomic_sub); + +/* Atomic bit operations. */ +EXPORT_SYMBOL_PRIVATE(test_and_set_bit); +EXPORT_SYMBOL_PRIVATE(test_and_clear_bit); +EXPORT_SYMBOL_PRIVATE(test_and_change_bit); +EXPORT_SYMBOL_PRIVATE(test_and_set_le_bit); +EXPORT_SYMBOL_PRIVATE(test_and_clear_le_bit); EXPORT_SYMBOL(ivector_table); EXPORT_SYMBOL(enable_irq); diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/kernel/sys32.S linux/arch/sparc64/kernel/sys32.S --- v2.3.99-pre3/linux/arch/sparc64/kernel/sys32.S Fri Jan 21 18:19:16 2000 +++ linux/arch/sparc64/kernel/sys32.S Mon Mar 27 10:35:56 2000 @@ -1,4 +1,4 @@ -/* $Id: sys32.S,v 1.11 2000/01/11 17:33:29 jj Exp $ +/* $Id: sys32.S,v 1.12 2000/03/24 04:17:37 davem Exp $ * sys32.S: I-cache tricks for 32-bit compatability layer simple * conversions. * @@ -6,6 +6,8 @@ * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) */ +#include + /* NOTE: call as jump breaks return stack, we have to avoid that */ .text @@ -69,3 +71,187 @@ srl %o5, 0, %o5 jmpl %g1 + %lo(sys_mmap), %g0 sllx %o5, 12, %o5 + + .align 32 + .globl sys32_socketcall +sys32_socketcall: /* %o0=call, %o1=args */ + cmp %o0, 1 + bl,pn %xcc, do_einval + cmp %o0, 17 + bg,pn %xcc, do_einval + sub %o0, 1, %o0 + sllx %o0, 5, %o0 + sethi %hi(__socketcall_table_begin), %g2 + or %g2, %lo(__socketcall_table_begin), %g2 + jmpl %g2 + %o0, %g0 + nop + + /* Each entry is exactly 32 bytes. */ + .align 32 +__socketcall_table_begin: +do_sys_socket: /* sys_socket(int, int, int) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys_socket), %g1 + ldswa [%o1 + 0x8] %asi, %o2 + jmpl %g1 + %lo(sys_socket), %g0 + ldswa [%o1 + 0x4] %asi, %o1 + nop + nop + nop +do_sys_bind: /* sys_bind(int fd, struct sockaddr *, int) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys_bind), %g1 + ldswa [%o1 + 0x8] %asi, %o2 + jmpl %g1 + %lo(sys_bind), %g0 + lduwa [%o1 + 0x4] %asi, %o1 + nop + nop + nop +do_sys_connect: /* sys_connect(int, struct sockaddr *, int) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys_connect), %g1 + ldswa [%o1 + 0x8] %asi, %o2 + jmpl %g1 + %lo(sys_connect), %g0 + lduwa [%o1 + 0x4] %asi, %o1 + nop + nop + nop +do_sys_listen: /* sys_listen(int, int) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys_listen), %g1 + jmpl %g1 + %lo(sys_listen), %g0 + ldswa [%o1 + 0x4] %asi, %o1 + nop + nop + nop + nop +do_sys_accept: /* sys_accept(int, struct sockaddr *, int *) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys_accept), %g1 + lduwa [%o1 + 0x8] %asi, %o2 + jmpl %g1 + %lo(sys_accept), %g0 + lduwa [%o1 + 0x4] %asi, %o1 + nop + nop + nop +do_sys_getsockname: /* sys_getsockname(int, struct sockaddr *, int *) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys_getsockname), %g1 + lduwa [%o1 + 0x8] %asi, %o2 + jmpl %g1 + %lo(sys_getsockname), %g0 + lduwa [%o1 + 0x4] %asi, %o1 + nop + nop + nop +do_sys_getpeername: /* sys_getpeername(int, struct sockaddr *, int *) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys_getpeername), %g1 + lduwa [%o1 + 0x8] %asi, %o2 + jmpl %g1 + %lo(sys_getpeername), %g0 + lduwa [%o1 + 0x4] %asi, %o1 + nop + nop + nop +do_sys_socketpair: /* sys_socketpair(int, int, int, int *) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys_socketpair), %g1 + ldswa [%o1 + 0x8] %asi, %o2 + lduwa [%o1 + 0xc] %asi, %o3 + jmpl %g1 + %lo(sys_socketpair), %g0 + ldswa [%o1 + 0x4] %asi, %o1 + nop + nop +do_sys_send: /* sys_send(int, void *, size_t, unsigned int) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys_send), %g1 + lduwa [%o1 + 0x8] %asi, %o2 + lduwa [%o1 + 0xc] %asi, %o3 + jmpl %g1 + %lo(sys_send), %g0 + lduwa [%o1 + 0x4] %asi, %o1 + nop + nop +do_sys_recv: /* sys_recv(int, void *, size_t, unsigned int) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys_recv), %g1 + lduwa [%o1 + 0x8] %asi, %o2 + lduwa [%o1 + 0xc] %asi, %o3 + jmpl %g1 + %lo(sys_recv), %g0 + lduwa [%o1 + 0x4] %asi, %o1 + nop + nop +do_sys_sendto: /* sys32_sendto(int, u32, __kernel_size_t32, unsigned int, u32, int) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys32_sendto), %g1 + lduwa [%o1 + 0x8] %asi, %o2 + lduwa [%o1 + 0xc] %asi, %o3 + lduwa [%o1 + 0x10] %asi, %o4 + ldswa [%o1 + 0x14] %asi, %o5 + jmpl %g1 + %lo(sys32_sendto), %g0 + lduwa [%o1 + 0x4] %asi, %o1 +do_sys_recvfrom: /* sys32_recvfrom(int, u32, __kernel_size_t32, unsigned int, u32, u32) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys32_recvfrom), %g1 + lduwa [%o1 + 0x8] %asi, %o2 + lduwa [%o1 + 0xc] %asi, %o3 + lduwa [%o1 + 0x10] %asi, %o4 + lduwa [%o1 + 0x14] %asi, %o5 + jmpl %g1 + %lo(sys32_recvfrom), %g0 + lduwa [%o1 + 0x4] %asi, %o1 +do_sys_shutdown: /* sys_shutdown(int, int) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys_shutdown), %g1 + jmpl %g1 + %lo(sys_shutdown), %g0 + ldswa [%o1 + 0x4] %asi, %o1 + nop + nop + nop + nop +do_sys_setsockopt: /* sys32_setsockopt(int, int, int, char *, int) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys32_setsockopt), %g1 + ldswa [%o1 + 0x8] %asi, %o2 + lduwa [%o1 + 0xc] %asi, %o3 + ldswa [%o1 + 0x10] %asi, %o4 + jmpl %g1 + %lo(sys32_setsockopt), %g0 + ldswa [%o1 + 0x4] %asi, %o1 + nop +do_sys_getsockopt: /* sys32_getsockopt(int, int, int, u32, u32) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys32_getsockopt), %g1 + ldswa [%o1 + 0x8] %asi, %o2 + lduwa [%o1 + 0xc] %asi, %o3 + lduwa [%o1 + 0x10] %asi, %o4 + jmpl %g1 + %lo(sys32_getsockopt), %g0 + ldswa [%o1 + 0x4] %asi, %o1 + nop +do_sys_sendmsg: /* sys32_sendmsg(int, struct msghdr32 *, unsigned int) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys32_sendmsg), %g1 + lduwa [%o1 + 0x8] %asi, %o2 + jmpl %g1 + %lo(sys32_sendmsg), %g0 + lduwa [%o1 + 0x4] %asi, %o1 + nop + nop + nop +do_sys_recvmsg: /* sys32_recvmsg(int, struct msghdr32 *, unsigned int) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys32_recvmsg), %g1 + lduwa [%o1 + 0x8] %asi, %o2 + jmpl %g1 + %lo(sys32_recvmsg), %g0 + lduwa [%o1 + 0x4] %asi, %o1 + nop + nop + nop +__socketcall_table_end: + +do_einval: + retl + mov -EINVAL, %o0 +do_efault: + retl + mov -EFAULT, %o0 + + .section __ex_table + .align 4 + .word __socketcall_table_begin, 0, __socketcall_table_end, do_efault + .previous diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c --- v2.3.99-pre3/linux/arch/sparc64/kernel/sys_sparc32.c Mon Mar 27 08:08:22 2000 +++ linux/arch/sparc64/kernel/sys_sparc32.c Sun Apr 2 15:49:08 2000 @@ -1,4 +1,4 @@ -/* $Id: sys_sparc32.c,v 1.141 2000/03/24 01:31:30 davem Exp $ +/* $Id: sys_sparc32.c,v 1.142 2000/03/24 04:17:38 davem Exp $ * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -1746,8 +1746,8 @@ return 0; } -extern long do_sys_mount(char * dev_name, char * dir_name, unsigned long type_page, - unsigned long new_flags, unsigned long data_page); +extern long do_sys_mount(char * dev_page, char * dir_page, char * type_page, + unsigned long new_flags, char * data_page); #define SMBFS_NAME "smbfs" #define NCPFS_NAME "ncpfs" @@ -1756,6 +1756,8 @@ { unsigned long type_page = 0; unsigned long data_page = 0; + unsigned long dev_page = 0; + unsigned long dir_page = 0; int err, is_smb, is_ncp; is_smb = is_ncp = 0; @@ -1777,19 +1779,32 @@ if (err) goto type_out; + err = copy_mount_stuff_to_kernel(dev_name, &dev_page); + if (err) + goto data_out; + + err = copy_mount_stuff_to_kernel(dir_name, &dir_page); + if (err) + goto dev_out; + if (!is_smb && !is_ncp) { - err = do_sys_mount(dev_name, dir_name, type_page, new_flags, - data_page); + err = do_sys_mount((char*)dev_page, (char*)dir_page, + (char*)type_page, new_flags, (char*)data_page); } else { if (is_ncp) do_ncp_super_data_conv((void *)data_page); else do_smb_super_data_conv((void *)data_page); - err = do_sys_mount(dev_name, dir_name, type_page, new_flags, - data_page); + err = do_sys_mount((char*)dev_page, (char*)dir_page, + (char*)type_page, new_flags, (char*)data_page); } + free_page(dir_page); + +dev_out: + free_page(dev_page); +data_out: free_page(data_page); type_out: @@ -2790,85 +2805,6 @@ return sys_setsockopt(fd, level, optname, optval, optlen); } -/* Argument list sizes for sys_socketcall */ -#define AL(x) ((x) * sizeof(u32)) -static unsigned char nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), - AL(3),AL(3),AL(4),AL(4),AL(4),AL(6), - AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)}; -#undef AL - -extern asmlinkage int sys_bind(int fd, struct sockaddr *umyaddr, int addrlen); -extern asmlinkage int sys_connect(int fd, struct sockaddr *uservaddr, int addrlen); -extern asmlinkage int sys_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen); -extern asmlinkage int sys_getsockname(int fd, struct sockaddr *usockaddr, int *usockaddr_len); -extern asmlinkage int sys_getpeername(int fd, struct sockaddr *usockaddr, int *usockaddr_len); -extern asmlinkage int sys_send(int fd, void *buff, size_t len, unsigned flags); -extern asmlinkage int sys32_sendto(int fd, u32 buff, __kernel_size_t32 len, - unsigned flags, u32 addr, int addr_len); -extern asmlinkage int sys_recv(int fd, void *ubuf, size_t size, unsigned flags); -extern asmlinkage int sys32_recvfrom(int fd, u32 ubuf, __kernel_size_t32 size, - unsigned flags, u32 addr, u32 addr_len); -extern asmlinkage int sys32_getsockopt(int fd, int level, int optname, - u32 optval, u32 optlen); - -extern asmlinkage int sys_socket(int family, int type, int protocol); -extern asmlinkage int sys_socketpair(int family, int type, int protocol, - int usockvec[2]); -extern asmlinkage int sys_shutdown(int fd, int how); -extern asmlinkage int sys_listen(int fd, int backlog); - -asmlinkage int sys32_socketcall(int call, u32 *args) -{ - u32 a[6]; - u32 a0,a1; - - if (callSYS_RECVMSG) - return -EINVAL; - if (copy_from_user(a, args, nargs[call])) - return -EFAULT; - a0=a[0]; - a1=a[1]; - - switch(call) - { - case SYS_SOCKET: - return sys_socket(a0, a1, a[2]); - case SYS_BIND: - return sys_bind(a0, (struct sockaddr *)A(a1), a[2]); - case SYS_CONNECT: - return sys_connect(a0, (struct sockaddr *)A(a1), a[2]); - case SYS_LISTEN: - return sys_listen(a0, a1); - case SYS_ACCEPT: - return sys_accept(a0, (struct sockaddr *)A(a1), (int *)A(a[2])); - case SYS_GETSOCKNAME: - return sys_getsockname(a0, (struct sockaddr *)A(a1), (int *)A(a[2])); - case SYS_GETPEERNAME: - return sys_getpeername(a0, (struct sockaddr *)A(a1), (int *)A(a[2])); - case SYS_SOCKETPAIR: - return sys_socketpair(a0, a1, a[2], (int *)A(a[3])); - case SYS_SEND: - return sys_send(a0, (void *)A(a1), a[2], a[3]); - case SYS_SENDTO: - return sys32_sendto(a0, a1, a[2], a[3], a[4], a[5]); - case SYS_RECV: - return sys_recv(a0, (void *)A(a1), a[2], a[3]); - case SYS_RECVFROM: - return sys32_recvfrom(a0, a1, a[2], a[3], a[4], a[5]); - case SYS_SHUTDOWN: - return sys_shutdown(a0,a1); - case SYS_SETSOCKOPT: - return sys32_setsockopt(a0, a1, a[2], (char *)A(a[3]), a[4]); - case SYS_GETSOCKOPT: - return sys32_getsockopt(a0, a1, a[2], a[3], a[4]); - case SYS_SENDMSG: - return sys32_sendmsg(a0, (struct msghdr32 *)A(a1), a[2]); - case SYS_RECVMSG: - return sys32_recvmsg(a0, (struct msghdr32 *)A(a1), a[2]); - } - return -EINVAL; -} - extern void check_pending(int signum); asmlinkage int sys32_sigaction (int sig, struct old_sigaction32 *act, struct old_sigaction32 *oact) @@ -4144,7 +4080,7 @@ if (fd >= 0) { struct file * f; lock_kernel(); - f = filp_open(tmp, flags, mode, NULL); + f = filp_open(tmp, flags, mode); unlock_kernel(); error = PTR_ERR(f); if (IS_ERR(f)) diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/kernel/sys_sunos32.c linux/arch/sparc64/kernel/sys_sunos32.c --- v2.3.99-pre3/linux/arch/sparc64/kernel/sys_sunos32.c Sun Mar 19 18:35:30 2000 +++ linux/arch/sparc64/kernel/sys_sunos32.c Sun Apr 2 15:53:28 2000 @@ -1,4 +1,4 @@ -/* $Id: sys_sunos32.c,v 1.42 2000/03/15 02:43:35 davem Exp $ +/* $Id: sys_sunos32.c,v 1.43 2000/03/26 11:28:53 davem Exp $ * sys_sunos32.c: SunOS binary compatability layer on sparc64. * * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu) @@ -79,19 +79,17 @@ } retval = -EBADF; if(!(flags & MAP_ANONYMOUS)) { + struct inode * inode; if(fd >= SUNOS_NR_OPEN) goto out; file = fget(fd); if (!file) goto out; - if (file->f_dentry && file->f_dentry->d_inode) { - struct inode * inode = file->f_dentry->d_inode; - if(MAJOR(inode->i_rdev) == MEM_MAJOR && - MINOR(inode->i_rdev) == 5) { - flags |= MAP_ANONYMOUS; - fput(file); - file = NULL; - } + inode = file->f_dentry->d_inode; + if(MAJOR(inode->i_rdev)==MEM_MAJOR && MINOR(inode->i_rdev)==5) { + flags |= MAP_ANONYMOUS; + fput(file); + file = NULL; } } @@ -601,7 +599,7 @@ char *netname; /* server's netname */ }; -extern int do_mount(struct block_device *, const char *, const char *, char *, int, void *); +extern long do_sys_mount(const char *, const char *, char *, int, void *); extern dev_t get_unnamed_dev(void); extern void put_unnamed_dev(dev_t); extern asmlinkage int sys_mount(char *, char *, char *, unsigned long, void *); @@ -627,17 +625,12 @@ struct inode *inode; struct file *file; - file = fcheck(fd); + file = fget(fd); if(!file) return 0; dentry = file->f_dentry; - if(!dentry) - return 0; - inode = dentry->d_inode; - if(!inode) - return 0; socket = &inode->u.socket_i; local.sin_family = AF_INET; @@ -651,8 +644,10 @@ sizeof(local)); } while (ret && try_port > (1024 / 2)); - if (ret) + if (ret) { + fput(file); return 0; + } server.sin_family = AF_INET; server.sin_addr = addr->sin_addr; @@ -661,6 +656,7 @@ /* Call sys_connect */ ret = socket->ops->connect (socket, (struct sockaddr *) &server, sizeof (server), file->f_flags); + fput(file); if (ret < 0) return 0; return 1; @@ -676,12 +672,12 @@ } /* XXXXXXXXXXXXXXXXXXXX */ -asmlinkage int sunos_nfs_mount(char *dir_name, int linux_flags, void *data) +static int sunos_nfs_mount(char *dir_name, int linux_flags, void *data) { int server_fd; char *the_name; struct nfs_mount_data linux_nfs_mount; - struct sunos_nfs_mount_args *sunos_mount = data; + struct sunos_nfs_mount_args sunos_mount; /* Ok, here comes the fun part: Linux's nfs mount needs a * socket connection to the server, but SunOS mount does not @@ -689,41 +685,50 @@ * address to create a socket and bind it to a reserved * port on this system */ + if (copy_from_user(&sunos_mount, data, sizeof(sunos_mount)) + return -EFAULT; + server_fd = sys_socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (server_fd < 0) return -ENXIO; - if (!sunos_nfs_get_server_fd (server_fd, sunos_mount->addr)){ + if (copy_from_user(&linux_nfs_mount.addr,sunos_mount.addr, + sizeof(*sunos_mount.addr)) || + copy_from_user(&linux_nfs_mount.root,sunos_mount.fh, + sizeof(*sunos_mount.fh))) { + sys_close (server_fd); + return -EFAULT; + } + + if (!sunos_nfs_get_server_fd (server_fd, &linux_nfs_mount.addr)){ sys_close (server_fd); return -ENXIO; } /* Now, bind it to a locally reserved port */ linux_nfs_mount.version = NFS_MOUNT_VERSION; - linux_nfs_mount.flags = sunos_mount->flags; - linux_nfs_mount.addr = *sunos_mount->addr; - linux_nfs_mount.root = *sunos_mount->fh; + linux_nfs_mount.flags = sunos_mount.flags; linux_nfs_mount.fd = server_fd; - linux_nfs_mount.rsize = get_default (sunos_mount->rsize, 8192); - linux_nfs_mount.wsize = get_default (sunos_mount->wsize, 8192); - linux_nfs_mount.timeo = get_default (sunos_mount->timeo, 10); - linux_nfs_mount.retrans = sunos_mount->retrans; + linux_nfs_mount.rsize = get_default (sunos_mount.rsize, 8192); + linux_nfs_mount.wsize = get_default (sunos_mount.wsize, 8192); + linux_nfs_mount.timeo = get_default (sunos_mount.timeo, 10); + linux_nfs_mount.retrans = sunos_mount.retrans; - linux_nfs_mount.acregmin = sunos_mount->acregmin; - linux_nfs_mount.acregmax = sunos_mount->acregmax; - linux_nfs_mount.acdirmin = sunos_mount->acdirmin; - linux_nfs_mount.acdirmax = sunos_mount->acdirmax; + linux_nfs_mount.acregmin = sunos_mount.acregmin; + linux_nfs_mount.acregmax = sunos_mount.acregmax; + linux_nfs_mount.acdirmin = sunos_mount.acdirmin; + linux_nfs_mount.acdirmax = sunos_mount.acdirmax; - the_name = getname(sunos_mount->hostname); + the_name = getname(sunos_mount.hostname); if(IS_ERR(the_name)) - return -EFAULT; + return PTR_ERR(the_name); strncpy (linux_nfs_mount.hostname, the_name, 254); linux_nfs_mount.hostname [255] = 0; putname (the_name); - - return do_mount (NULL, "", dir_name, "nfs", linux_flags, &linux_nfs_mount); + + return do_sys_mount ("", dir_name, "nfs", linux_flags, &linux_nfs_mount); } /* XXXXXXXXXXXXXXXXXXXX */ @@ -733,6 +738,7 @@ int linux_flags = MS_MGC_MSK; /* new semantics */ int ret = -EINVAL; char *dev_fname = 0; + char *dir_page, *type_page; if (!capable (CAP_SYS_ADMIN)) return -EPERM; @@ -751,24 +757,44 @@ linux_flags |= MS_RDONLY; if(flags & SMNT_NOSUID) linux_flags |= MS_NOSUID; - if(strcmp(type, "ext2") == 0) { - dev_fname = (char *) data; - } else if(strcmp(type, "iso9660") == 0) { - dev_fname = (char *) data; - } else if(strcmp(type, "minix") == 0) { - dev_fname = (char *) data; - } else if(strcmp(type, "nfs") == 0) { - ret = sunos_nfs_mount (dir, flags, data); - goto out; - } else if(strcmp(type, "ufs") == 0) { + + dir_page = getname(dir); + ret = PTR_ERR(dir_page); + if (IS_ERR(dir_page)) + goto out; + + type_page = getname(type); + ret = PTR_ERR(type_page); + if (IS_ERR(type_page)) + goto out1; + + if(strcmp(type_page, "ext2") == 0) { + dev_fname = getname(data); + } else if(strcmp(type_page, "iso9660") == 0) { + dev_fname = getname(data); + } else if(strcmp(type_page, "minix") == 0) { + dev_fname = getname(data); + } else if(strcmp(type_page, "nfs") == 0) { + ret = sunos_nfs_mount (dir_page, flags, data); + goto out2 + } else if(strcmp(type_page, "ufs") == 0) { printk("Warning: UFS filesystem mounts unsupported.\n"); ret = -ENODEV; - goto out; - } else if(strcmp(type, "proc")) { + goto out2 + } else if(strcmp(type_page, "proc")) { ret = -ENODEV; - goto out; + goto out2 } - ret = sys_mount(dev_fname, dir, type, linux_flags, NULL); + ret = PTR_ERR(dev_fname); + if (IS_ERR(dev_fname)) + goto out2; + ret = do_sys_mount(dev_fname, dir_page, type_page, linux_flags, NULL); + if (dev_fname) + putname(dev_fname); +out2: + putname(type_page); +out1: + putname(dir_page); out: unlock_kernel(); return ret; diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/kernel/winfixup.S linux/arch/sparc64/kernel/winfixup.S --- v2.3.99-pre3/linux/arch/sparc64/kernel/winfixup.S Mon Aug 2 22:07:16 1999 +++ linux/arch/sparc64/kernel/winfixup.S Mon Mar 27 10:35:56 2000 @@ -1,4 +1,4 @@ -/* $Id: winfixup.S,v 1.28 1999/07/30 09:35:34 davem Exp $ +/* $Id: winfixup.S,v 1.29 2000/03/26 09:13:48 davem Exp $ * * winfixup.S: Handle cases where user stack pointer is found to be bogus. * @@ -31,7 +31,7 @@ fill_fixup: rdpr %tstate, %g1 andcc %g1, TSTATE_PRIV, %g0 - clr %g4 + or %g4, FAULT_CODE_WINFIXUP, %g4 be,pt %xcc, window_scheisse_from_user_common and %g1, TSTATE_CWP, %g1 @@ -69,21 +69,20 @@ mov %g6, %o7 ! Get current. andn %l1, PSTATE_MM, %l1 ! We want to be in RMO - srlx %g5, PAGE_SHIFT, %o1 ! Fault address + stb %g4, [%g6 + AOFF_task_thread + AOFF_thread_fault_code] + stx %g5, [%g6 + AOFF_task_thread + AOFF_thread_fault_address] wrpr %g0, 0x0, %tl ! Out of trap levels. wrpr %l1, (PSTATE_IE | PSTATE_AG | PSTATE_RMO), %pstate sethi %uhi(PAGE_OFFSET), %g4 ! Prepare page_offset global reg mov %o7, %g6 sllx %g4, 32, %g4 ! and finish it... - clr %o2 /* This is the same as below, except we handle this a bit special * since we must preserve %l5 and %l6, see comment above. */ - sllx %o1, PAGE_SHIFT, %o1 call do_sparc64_fault add %sp, STACK_BIAS + REGWIN_SZ, %o0 - b,pt %xcc, rtrap + ba,pt %xcc, rtrap nop ! yes, nop is correct /* Be very careful about usage of the alternate globals here. @@ -149,22 +148,19 @@ andcc %g1, TSTATE_PRIV, %g0 saved and %g1, TSTATE_CWP, %g1 - be,a,pn %xcc, window_scheisse_from_user_common - or %g4, 0x4, %g4 ! we know it was a write + be,pn %xcc, window_scheisse_from_user_common + mov FAULT_CODE_WRITE | FAULT_CODE_DTLB | FAULT_CODE_WINFIXUP, %g4 retry + window_scheisse_from_user_common: + stb %g4, [%g6 + AOFF_task_thread + AOFF_thread_fault_code] + stx %g5, [%g6 + AOFF_task_thread + AOFF_thread_fault_address] wrpr %g1, %cwp - sethi %hi(109f), %g7 ba,pt %xcc, etrap -109: or %g7, %lo(109b), %g7 - srlx %l5, PAGE_SHIFT, %o1 - - and %l4, 0x4, %o2 - sllx %o1, PAGE_SHIFT, %o1 + rd %pc, %g7 call do_sparc64_fault add %sp, STACK_BIAS + REGWIN_SZ, %o0 - ba,pt %xcc, rtrap - clr %l6 + ba,a,pt %xcc, rtrap_clr_l6 .globl winfix_mna, fill_fixup_mna, spill_fixup_mna winfix_mna: diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/lib/Makefile linux/arch/sparc64/lib/Makefile --- v2.3.99-pre3/linux/arch/sparc64/lib/Makefile Fri Jan 28 15:09:07 2000 +++ linux/arch/sparc64/lib/Makefile Thu Mar 30 16:56:04 2000 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.20 2000/01/19 04:06:03 davem Exp $ +# $Id: Makefile,v 1.21 2000/03/27 10:38:41 davem Exp $ # Makefile for Sparc library files.. # @@ -7,7 +7,7 @@ OBJS = PeeCeeI.o blockops.o debuglocks.o strlen.o strncmp.o \ memscan.o strncpy_from_user.o strlen_user.o memcmp.o checksum.o \ VIScopy.o VISbzero.o VISmemset.o VIScsum.o VIScsumcopy.o \ - VIScsumcopyusr.o VISsave.o atomic.o rwlock.o + VIScsumcopyusr.o VISsave.o atomic.o rwlock.o bitops.o lib.a: $(OBJS) $(AR) rcs lib.a $(OBJS) @@ -17,10 +17,10 @@ VISbzero.o: VISbzero.S VIS.h .S.s: - $(CPP) -D__ASSEMBLY__ $(AFLAGS) -ansi $< -o $*.s + $(CPP) $(AFLAGS) -ansi $< -o $*.s .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c $< -o $*.o + $(CC) $(AFLAGS) -ansi -c $< -o $*.o dep: diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/lib/VIScopy.S linux/arch/sparc64/lib/VIScopy.S --- v2.3.99-pre3/linux/arch/sparc64/lib/VIScopy.S Sun Mar 19 18:35:30 2000 +++ linux/arch/sparc64/lib/VIScopy.S Mon Mar 27 10:35:56 2000 @@ -1,4 +1,4 @@ -/* $Id: VIScopy.S,v 1.22 2000/03/16 16:44:38 davem Exp $ +/* $Id: VIScopy.S,v 1.23 2000/03/26 09:13:49 davem Exp $ * VIScopy.S: High speed copy operations utilizing the UltraSparc * Visual Instruction Set. * @@ -135,11 +135,11 @@ #define MAIN_LOOP_CHUNK(src, dest, fdest, fsrc, len, jmptgt) \ EXVIS(LDBLK [%src] ASIBLK, %fdest); \ ASI_SETDST_BLK \ + EXVIS2(STBLK %fsrc, [%dest] ASIBLK); \ add %src, 0x40, %src; \ - add %dest, 0x40, %dest; \ subcc %len, 0x40, %len; \ be,pn %xcc, jmptgt; \ - EXVIS2(STBLK %fsrc, [%dest - 0x40] ASIBLK); \ + add %dest, 0x40, %dest; \ ASI_SETSRC_BLK #define LOOP_CHUNK1(src, dest, len, branch_dest) \ diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/lib/bitops.S linux/arch/sparc64/lib/bitops.S --- v2.3.99-pre3/linux/arch/sparc64/lib/bitops.S Wed Dec 31 16:00:00 1969 +++ linux/arch/sparc64/lib/bitops.S Thu Mar 30 16:54:53 2000 @@ -0,0 +1,110 @@ +/* $Id: bitops.S,v 1.1 2000/03/27 10:38:41 davem Exp $ + * bitops.S: Sparc64 atomic bit operations. + * + * Copyright (C) 2000 David S. Miller (davem@redhat.com) + */ + +#include + + .text + .align 64 + .globl __bitops_begin +__bitops_begin: + + .globl __test_and_set_bit +__test_and_set_bit: /* %o0=nr, %o1=addr */ + srlx %o0, 6, %g1 + mov 1, %g5 + sllx %g1, 3, %g3 + and %o0, 63, %g2 + sllx %g5, %g2, %g5 + add %o1, %g3, %o1 + ldx [%o1], %g7 +1: andcc %g7, %g5, %o0 + bne,pn %xcc, 2f + xor %g7, %g5, %g1 + casx [%o1], %g7, %g1 + cmp %g7, %g1 + bne,a,pn %xcc, 1b + ldx [%o1], %g7 +2: retl + nop + + .globl __test_and_clear_bit +__test_and_clear_bit: /* %o0=nr, %o1=addr */ + srlx %o0, 6, %g1 + mov 1, %g5 + sllx %g1, 3, %g3 + and %o0, 63, %g2 + sllx %g5, %g2, %g5 + add %o1, %g3, %o1 + ldx [%o1], %g7 +1: andcc %g7, %g5, %o0 + be,pn %xcc, 2f + xor %g7, %g5, %g1 + casx [%o1], %g7, %g1 + cmp %g7, %g1 + bne,a,pn %xcc, 1b + ldx [%o1], %g7 +2: retl + nop + + .globl __test_and_change_bit +__test_and_change_bit: /* %o0=nr, %o1=addr */ + srlx %o0, 6, %g1 + mov 1, %g5 + sllx %g1, 3, %g3 + and %o0, 63, %g2 + sllx %g5, %g2, %g5 + add %o1, %g3, %o1 + ldx [%o1], %g7 +1: and %g7, %g5, %o0 + xor %g7, %g5, %g1 + casx [%o1], %g7, %g1 + cmp %g7, %g1 + bne,a,pn %xcc, 1b + ldx [%o1], %g7 +2: retl + nop + nop + + .globl __test_and_set_le_bit +__test_and_set_le_bit: /* %o0=nr, %o1=addr */ + srlx %o0, 5, %g1 + mov 1, %g5 + sllx %g1, 2, %g3 + and %o0, 31, %g2 + sllx %g5, %g2, %g5 + add %o1, %g3, %o1 + lduwa [%o1] ASI_PL, %g7 +1: andcc %g7, %g5, %o0 + bne,pn %icc, 2f + xor %g7, %g5, %g1 + casa [%o1] ASI_PL, %g7, %g1 + cmp %g7, %g1 + bne,a,pn %icc, 1b + lduwa [%o1] ASI_PL, %g7 +2: retl + nop + + .globl __test_and_clear_le_bit +__test_and_clear_le_bit: /* %o0=nr, %o1=addr */ + srlx %o0, 5, %g1 + mov 1, %g5 + sllx %g1, 2, %g3 + and %o0, 31, %g2 + sllx %g5, %g2, %g5 + add %o1, %g3, %o1 + lduwa [%o1] ASI_PL, %g7 +1: andcc %g7, %g5, %o0 + be,pn %icc, 2f + xor %g7, %g5, %g1 + casa [%o1] ASI_PL, %g7, %g1 + cmp %g7, %g1 + bne,a,pn %icc, 1b + lduwa [%o1] ASI_PL, %g7 +2: retl + nop + + .globl __bitops_end +__bitops_end: diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/lib/blockops.S linux/arch/sparc64/lib/blockops.S --- v2.3.99-pre3/linux/arch/sparc64/lib/blockops.S Sun Mar 19 18:35:30 2000 +++ linux/arch/sparc64/lib/blockops.S Thu Mar 30 16:54:53 2000 @@ -1,4 +1,4 @@ -/* $Id: blockops.S,v 1.22 2000/03/15 07:18:55 davem Exp $ +/* $Id: blockops.S,v 1.24 2000/03/27 10:38:41 davem Exp $ * blockops.S: UltraSparc block zero optimized routines. * * Copyright (C) 1996, 1998, 1999, 2000 David S. Miller (davem@redhat.com) @@ -38,21 +38,21 @@ sethi %hi(8192), %o2 1: TOUCH(f0, f2, f4, f6, f8, f10, f12, f14) ldda [%o1] ASI_BLK_P, %f32 + stda %f48, [%o0] ASI_BLK_P add %o1, 0x40, %o1 sub %o2, 0x40, %o2 - stda %f48, [%o0] ASI_BLK_P add %o0, 0x40, %o0 TOUCH(f16, f18, f20, f22, f24, f26, f28, f30) ldda [%o1] ASI_BLK_P, %f0 + stda %f48, [%o0] ASI_BLK_P add %o1, 0x40, %o1 sub %o2, 0x40, %o2 - stda %f48, [%o0] ASI_BLK_P add %o0, 0x40, %o0 TOUCH(f32, f34, f36, f38, f40, f42, f44, f46) ldda [%o1] ASI_BLK_P, %f16 - add %o1, 0x40, %o1 - sub %o2, 0x40, %o2 stda %f48, [%o0] ASI_BLK_P + sub %o2, 0x40, %o2 + add %o1, 0x40, %o1 cmp %o2, 0x80 bne,pt %xcc, 1b add %o0, 0x40, %o0 @@ -122,7 +122,11 @@ stxa %g2, [%o3] ASI_DTLB_DATA_ACCESS membar #Sync - membar #LoadStore | #StoreStore | #StoreLoad + ldub [%g6 + AOFF_task_thread + AOFF_thread_use_blkcommit], %g2 + cmp %g2, 0 + bne,pn %xcc, copy_page_using_blkcommit + nop + ldda [%o1] ASI_BLK_P, %f0 add %o1, 0x40, %o1 ldda [%o1] ASI_BLK_P, %f16 @@ -130,21 +134,21 @@ sethi %hi(8192), %o2 1: TOUCH(f0, f2, f4, f6, f8, f10, f12, f14) ldda [%o1] ASI_BLK_P, %f32 + stda %f48, [%o0] ASI_BLK_P add %o1, 0x40, %o1 sub %o2, 0x40, %o2 - stda %f48, [%o0] ASI_BLK_P add %o0, 0x40, %o0 TOUCH(f16, f18, f20, f22, f24, f26, f28, f30) ldda [%o1] ASI_BLK_P, %f0 + stda %f48, [%o0] ASI_BLK_P add %o1, 0x40, %o1 sub %o2, 0x40, %o2 - stda %f48, [%o0] ASI_BLK_P add %o0, 0x40, %o0 TOUCH(f32, f34, f36, f38, f40, f42, f44, f46) ldda [%o1] ASI_BLK_P, %f16 - add %o1, 0x40, %o1 - sub %o2, 0x40, %o2 stda %f48, [%o0] ASI_BLK_P + sub %o2, 0x40, %o2 + add %o1, 0x40, %o1 cmp %o2, 0x80 bne,pt %xcc, 1b add %o0, 0x40, %o0 @@ -152,6 +156,7 @@ stda %f0, [%o0] ASI_BLK_P add %o0, 0x40, %o0 stda %f16, [%o0] ASI_BLK_P +copy_user_page_continue: membar #Sync VISExit @@ -166,6 +171,39 @@ jmpl %o7 + 0x8, %g0 wrpr %g3, 0x0, %pstate +copy_page_using_blkcommit: + membar #LoadStore | #StoreStore | #StoreLoad + ldda [%o1] ASI_BLK_P, %f0 + add %o1, 0x40, %o1 + ldda [%o1] ASI_BLK_P, %f16 + add %o1, 0x40, %o1 + sethi %hi(8192), %o2 +1: TOUCH(f0, f2, f4, f6, f8, f10, f12, f14) + ldda [%o1] ASI_BLK_P, %f32 + stda %f48, [%o0] ASI_BLK_COMMIT_P + add %o1, 0x40, %o1 + sub %o2, 0x40, %o2 + add %o0, 0x40, %o0 + TOUCH(f16, f18, f20, f22, f24, f26, f28, f30) + ldda [%o1] ASI_BLK_P, %f0 + stda %f48, [%o0] ASI_BLK_COMMIT_P + add %o1, 0x40, %o1 + sub %o2, 0x40, %o2 + add %o0, 0x40, %o0 + TOUCH(f32, f34, f36, f38, f40, f42, f44, f46) + ldda [%o1] ASI_BLK_P, %f16 + stda %f48, [%o0] ASI_BLK_COMMIT_P + sub %o2, 0x40, %o2 + add %o1, 0x40, %o1 + cmp %o2, 0x80 + bne,pt %xcc, 1b + add %o0, 0x40, %o0 + membar #Sync + stda %f0, [%o0] ASI_BLK_COMMIT_P + add %o0, 0x40, %o0 + ba,pt %xcc, copy_user_page_continue + stda %f16, [%o0] ASI_BLK_COMMIT_P + .align 32 .globl clear_page .type clear_page,@function @@ -213,6 +251,7 @@ mov 1, %o4 clear_page_common: + membar #StoreLoad | #StoreStore | #LoadStore ! LSU Group fzero %f0 ! FPA Group mov 32, %o1 ! IEU0 fzero %f2 ! FPA Group @@ -223,7 +262,6 @@ faddd %f0, %f2, %f12 ! FPA Group fmuld %f0, %f2, %f14 ! FPM - membar #StoreLoad | #StoreStore | #LoadStore ! LSU Group 1: stda %f0, [%o0 + %g0] ASI_BLK_P ! Store Group add %o0, 0x40, %o0 ! IEU0 stda %f0, [%o0 + %g0] ASI_BLK_P ! Store Group diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/mm/Makefile linux/arch/sparc64/mm/Makefile --- v2.3.99-pre3/linux/arch/sparc64/mm/Makefile Tue Feb 1 01:35:43 2000 +++ linux/arch/sparc64/mm/Makefile Thu Mar 30 16:56:04 2000 @@ -8,10 +8,10 @@ # Note 2! The CFLAGS definition is now in the main makefile... .S.s: - $(CPP) -D__ASSEMBLY__ $(AFLAGS) -ansi $< -o $*.s + $(CPP) $(AFLAGS) -ansi $< -o $*.s .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c $< -o $*.o + $(CC) $(AFLAGS) -ansi -c $< -o $*.o O_TARGET := mm.o O_OBJS := ultra.o fault.o init.o generic.o extable.o modutil.o diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/mm/fault.c linux/arch/sparc64/mm/fault.c --- v2.3.99-pre3/linux/arch/sparc64/mm/fault.c Sun Mar 19 18:35:30 2000 +++ linux/arch/sparc64/mm/fault.c Thu Mar 30 16:54:53 2000 @@ -1,4 +1,4 @@ -/* $Id: fault.c,v 1.43 2000/03/14 03:59:46 davem Exp $ +/* $Id: fault.c,v 1.45 2000/03/27 10:38:51 davem Exp $ * arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -92,162 +92,211 @@ die_if_kernel("Oops", regs); } -/* #define DEBUG_EXCEPTIONS */ -/* #define DEBUG_LOCKUPS */ - -/* #define INSN_VPTE_LOOKUP */ - -static inline u32 get_user_insn(unsigned long tpc) +static unsigned int get_user_insn(unsigned long tpc) { - u32 insn; -#ifndef INSN_VPTE_LOOKUP pgd_t *pgdp = pgd_offset(current->mm, tpc); pmd_t *pmdp; - pte_t *ptep; + pte_t *ptep, pte; + unsigned long pa; + u32 insn = 0; if(pgd_none(*pgdp)) - return 0; + goto out; pmdp = pmd_offset(pgdp, tpc); if(pmd_none(*pmdp)) - return 0; + goto out; ptep = pte_offset(pmdp, tpc); - if(!pte_present(*ptep)) - return 0; - insn = *(unsigned int *) - ((unsigned long)__va(pte_pagenr(*ptep) << PAGE_SHIFT) + - (tpc & ~PAGE_MASK)); -#else - register unsigned long pte asm("l1"); - - /* So that we don't pollute TLB, we read the instruction - * using PHYS bypass. For that, we of course need - * to know its page table entry. Do this by simulating - * dtlb_miss handler. -jj */ - pte = ((((long)tpc) >> (PAGE_SHIFT-3)) & ~7); - asm volatile (" - rdpr %%pstate, %%l0 - wrpr %%l0, %2, %%pstate - wrpr %%g0, 1, %%tl - mov %%l1, %%g6 - ldxa [%%g3 + %%l1] %3, %%g5 - mov %%g5, %%l1 - wrpr %%g0, 0, %%tl - wrpr %%l0, 0, %%pstate - " : "=r" (pte) : "0" (pte), "i" (PSTATE_MG|PSTATE_IE), "i" (ASI_S) : "l0"); - - if ((long)pte >= 0) return 0; - - pte = (pte & _PAGE_PADDR) + (tpc & ~PAGE_MASK); - asm ("lduwa [%1] %2, %0" : "=r" (insn) : "r" (pte), "i" (ASI_PHYS_USE_EC)); -#endif + pte = *ptep; + if(!pte_present(pte)) + goto out; + + pa = (pte_pagenr(pte) << PAGE_SHIFT) + (tpc & ~PAGE_MASK); + + /* Use phys bypass so we don't pollute dtlb/dcache. */ + __asm__ __volatile__("lduwa [%1] %2, %0" + : "=r" (insn) + : "r" (pa), "i" (ASI_PHYS_USE_EC)); +out: return insn; } -asmlinkage void do_sparc64_fault(struct pt_regs *regs, unsigned long address, int write) +static void do_fault_siginfo(int code, int sig, unsigned long address) +{ + siginfo_t info; + + info.si_code = code; + info.si_signo = sig; + info.si_errno = 0; + info.si_addr = (void *) address; + info.si_trapno = 0; + force_sig_info(sig, &info, current); +} + +extern int handle_ldf_stq(u32, struct pt_regs *); +extern int handle_ld_nf(u32, struct pt_regs *); + +static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code, + unsigned int insn, unsigned long address) +{ + unsigned long g2; + unsigned char asi = ASI_P; + + if (!insn) { + if (regs->tstate & TSTATE_PRIV) { + if (regs->tpc & 0x3) + goto cannot_handle; + insn = *(unsigned int *)regs->tpc; + } else { + insn = get_user_insn(regs->tpc); + } + } + + /* If user insn could be read (thus insn is zero), that + * is fine. We will just gun down the process with a signal + * in that case. + */ + + if (!(fault_code & FAULT_CODE_WRITE) && + (insn & 0xc0800000) == 0xc0800000) { + if (insn & 0x2000) + asi = (regs->tstate >> 24); + else + asi = (insn >> 5); + if ((asi & 0xf2) == 0x82) { + if (insn & 0x1000000) { + handle_ldf_stq(insn, regs); + } else { + /* This was a non-faulting load. Just clear the + * destination register(s) and continue with the next + * instruction. -jj + */ + handle_ld_nf(insn, regs); + } + return; + } + } + + g2 = regs->u_regs[UREG_G2]; + + /* Is this in ex_table? */ + if (regs->tstate & TSTATE_PRIV) { + unsigned long fixup; + + if (asi == ASI_P && (insn & 0xc0800000) == 0xc0800000) { + if (insn & 0x2000) + asi = (regs->tstate >> 24); + else + asi = (insn >> 5); + } + + /* Look in asi.h: All _S asis have LS bit set */ + if ((asi & 0x1) && + (fixup = search_exception_table (regs->tpc, &g2))) { + regs->tpc = fixup; + regs->tnpc = regs->tpc + 4; + regs->u_regs[UREG_G2] = g2; + return; + } + } else { + /* The si_code was set to make clear whether + * this was a SEGV_MAPERR or SEGV_ACCERR fault. + */ + do_fault_siginfo(si_code, SIGSEGV, address); + return; + } + +cannot_handle: + unhandled_fault (address, current, regs); +} + +asmlinkage void do_sparc64_fault(struct pt_regs *regs) { struct mm_struct *mm = current->mm; struct vm_area_struct *vma; unsigned int insn = 0; - siginfo_t info; -#ifdef DEBUG_LOCKUPS - static unsigned long lastaddr, lastpc; - static int lastwrite, lockcnt; -#endif + int si_code, fault_code; + unsigned long address; + + si_code = SEGV_MAPERR; + fault_code = current->thread.fault_code; + address = current->thread.fault_address; + + if ((fault_code & FAULT_CODE_ITLB) && + (fault_code & FAULT_CODE_DTLB)) + BUG(); - info.si_code = SEGV_MAPERR; /* * If we're in an interrupt or have no user * context, we must not take the fault.. */ if (in_interrupt() || !mm) - goto do_kernel_fault; + goto handle_kernel_fault; down(&mm->mmap_sem); -#ifdef DEBUG_LOCKUPS - if (regs->tpc == lastpc && - address == lastaddr && - write == lastwrite) { - lockcnt++; - if (lockcnt == 100000) { - unsigned char tmp; - register unsigned long tmp1 asm("o5"); - register unsigned long tmp2 asm("o4"); - - printk("do_sparc64_fault[%s:%d]: possible fault loop for %016lx %s\n", - current->comm, current->pid, - address, write ? "write" : "read"); - printk("do_sparc64_fault: CHECK[papgd[%016lx],pcac[%016lx]]\n", - __pa(mm->pgd), pgd_val(mm->pgd[0])<<11UL); - __asm__ __volatile__( - "wrpr %%g0, 0x494, %%pstate\n\t" - "mov %3, %%g4\n\t" - "mov %%g7, %0\n\t" - "ldxa [%%g4] %2, %1\n\t" - "wrpr %%g0, 0x096, %%pstate" - : "=r" (tmp1), "=r" (tmp2) - : "i" (ASI_DMMU), "i" (TSB_REG)); - printk("do_sparc64_fault: IS[papgd[%016lx],pcac[%016lx]]\n", - tmp1, tmp2); - printk("do_sparc64_fault: CHECK[ctx(%016lx)] IS[ctx(%016lx)]\n", - mm->context, spitfire_get_secondary_context()); - __asm__ __volatile__("rd %%asi, %0" - : "=r" (tmp)); - printk("do_sparc64_fault: CHECK[seg(%02x)] IS[seg(%02x)]\n", - current->thread.current_ds.seg, tmp); - show_regs(regs); - __sti(); - while(1) - barrier(); - } - } else { - lastpc = regs->tpc; - lastaddr = address; - lastwrite = write; - lockcnt = 0; - } -#endif vma = find_vma(mm, address); - if(!vma) + if (!vma) goto bad_area; -#ifndef INSN_VPTE_LOOKUP - write &= 0xf; -#else - if (write & 0x10) { - write = 0; - if((vma->vm_flags & VM_WRITE)) { - if (regs->tstate & TSTATE_PRIV) - insn = *(unsigned int *)regs->tpc; - else - insn = get_user_insn(regs->tpc); - if ((insn & 0xc0200000) == 0xc0200000 && (insn & 0x1780000) != 0x1680000) - write = 1; + + /* Pure DTLB misses do not tell us whether the fault causing + * load/store/atomic was a write or not, it only says that there + * was no match. So in such a case we (carefully) read the + * instruction to try and figure this out. It's an optimization + * so it's ok if we can't do this. + * + * Special hack, window spill/fill knows the exact fault type. + */ + if (((fault_code & + (FAULT_CODE_DTLB | FAULT_CODE_WRITE | FAULT_CODE_WINFIXUP)) == FAULT_CODE_DTLB) && + (vma->vm_flags & VM_WRITE) != 0) { + unsigned long tpc = regs->tpc; + + if (tpc & 0x3) + goto continue_fault; + + if (regs->tstate & TSTATE_PRIV) + insn = *(unsigned int *)tpc; + else + insn = get_user_insn(tpc); + + if ((insn & 0xc0200000) == 0xc0200000 && + (insn & 0x1780000) != 0x1680000) { + /* Don't bother updating thread struct value, + * because update_mmu_cache only cares which tlb + * the access came from. + */ + fault_code |= FAULT_CODE_WRITE; } } -#endif - if(vma->vm_start <= address) +continue_fault: + + if (vma->vm_start <= address) goto good_area; - if(!(vma->vm_flags & VM_GROWSDOWN)) + if (!(vma->vm_flags & VM_GROWSDOWN)) goto bad_area; - if(expand_stack(vma, address)) + if (expand_stack(vma, address)) goto bad_area; /* * Ok, we have a good vm_area for this memory access, so * we can handle it.. */ good_area: - info.si_code = SEGV_ACCERR; - if(write) { - if(!(vma->vm_flags & VM_WRITE)) + si_code = SEGV_ACCERR; + if (fault_code & FAULT_CODE_WRITE) { + if (!(vma->vm_flags & VM_WRITE)) goto bad_area; + if ((vma->vm_flags & VM_EXEC) != 0 && + vma->vm_file != NULL) + current->thread.use_blkcommit = 1; } else { /* Allow reads even for write-only mappings */ - if(!(vma->vm_flags & (VM_READ | VM_EXEC))) + if (!(vma->vm_flags & (VM_READ | VM_EXEC))) goto bad_area; } { - int fault = handle_mm_fault(current, vma, address, write); + int fault = handle_mm_fault(current, vma, + address, (fault_code & FAULT_CODE_WRITE)); if (fault < 0) goto out_of_memory; @@ -255,7 +304,8 @@ goto do_sigbus; } up(&mm->mmap_sem); - return; + goto fault_done; + /* * Something tried to access memory that isn't in our memory map.. * Fix it, but check if it's kernel or user first.. @@ -263,89 +313,10 @@ bad_area: up(&mm->mmap_sem); -do_kernel_fault: - { - unsigned long g2; - unsigned char asi = ASI_P; - - if (!insn) { - if (regs->tstate & TSTATE_PRIV) - insn = *(unsigned int *)regs->tpc; - else - insn = get_user_insn(regs->tpc); - } - if (write != 1 && (insn & 0xc0800000) == 0xc0800000) { - if (insn & 0x2000) - asi = (regs->tstate >> 24); - else - asi = (insn >> 5); - if ((asi & 0xf2) == 0x82) { - /* This was a non-faulting load. Just clear the - destination register(s) and continue with the next - instruction. -jj */ - if (insn & 0x1000000) { - extern int handle_ldf_stq(u32, struct pt_regs *); - - handle_ldf_stq(insn, regs); - } else { - extern int handle_ld_nf(u32, struct pt_regs *); - - handle_ld_nf(insn, regs); - } - return; - } - } - - g2 = regs->u_regs[UREG_G2]; - - /* Is this in ex_table? */ - if (regs->tstate & TSTATE_PRIV) { - unsigned long fixup; +handle_kernel_fault: + do_kernel_fault(regs, si_code, fault_code, insn, address); - if (asi == ASI_P && (insn & 0xc0800000) == 0xc0800000) { - if (insn & 0x2000) - asi = (regs->tstate >> 24); - else - asi = (insn >> 5); - } - - /* Look in asi.h: All _S asis have LS bit set */ - if ((asi & 0x1) && - (fixup = search_exception_table (regs->tpc, &g2))) { -#ifdef DEBUG_EXCEPTIONS - printk("Exception: PC<%016lx> faddr<%016lx>\n", - regs->tpc, address); - printk("EX_TABLE: insn<%016lx> fixup<%016lx> " - "g2<%016lx>\n", regs->tpc, fixup, g2); -#endif - regs->tpc = fixup; - regs->tnpc = regs->tpc + 4; - regs->u_regs[UREG_G2] = g2; - return; - } - } else { -#if 0 - extern void __show_regs(struct pt_regs *); - printk("SHIT(%s:%d:cpu(%d)): PC[%016lx] ADDR[%016lx]\n", - current->comm, current->pid, smp_processor_id(), - regs->tpc, address); - __show_regs(regs); - __sti(); - while(1) - barrier(); -#endif - info.si_signo = SIGSEGV; - info.si_errno = 0; - /* info.si_code set above to make clear whether - this was a SEGV_MAPERR or SEGV_ACCERR fault. */ - info.si_addr = (void *)address; - info.si_trapno = 0; - force_sig_info (SIGSEGV, &info, current); - return; - } - unhandled_fault (address, current, regs); - } - return; + goto fault_done; /* * We ran out of memory, or some other thing happened to us that made @@ -356,7 +327,7 @@ printk("VM: killing process %s\n", current->comm); if (!(regs->tstate & TSTATE_PRIV)) do_exit(SIGKILL); - goto do_kernel_fault; + goto handle_kernel_fault; do_sigbus: up(&mm->mmap_sem); @@ -365,14 +336,15 @@ * Send a sigbus, regardless of whether we were in kernel * or user mode. */ - info.si_signo = SIGBUS; - info.si_errno = 0; - info.si_code = BUS_ADRERR; - info.si_addr = (void *)address; - info.si_trapno = 0; - force_sig_info (SIGBUS, &info, current); + do_fault_siginfo(BUS_ADRERR, SIGBUS, address); /* Kernel mode? Handle exceptions or die */ if (regs->tstate & TSTATE_PRIV) - goto do_kernel_fault; + goto handle_kernel_fault; + +fault_done: + /* These values are no longer needed, clear them. */ + current->thread.fault_code = 0; + current->thread.use_blkcommit = 0; + current->thread.fault_address = 0; } diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/mm/ultra.S linux/arch/sparc64/mm/ultra.S --- v2.3.99-pre3/linux/arch/sparc64/mm/ultra.S Tue Mar 7 14:32:25 2000 +++ linux/arch/sparc64/mm/ultra.S Thu Mar 30 16:54:53 2000 @@ -1,11 +1,12 @@ -/* $Id: ultra.S,v 1.38 2000/03/03 23:48:44 davem Exp $ +/* $Id: ultra.S,v 1.41 2000/03/27 10:38:51 davem Exp $ * ultra.S: Don't expand these all over the place... * - * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1997, 2000 David S. Miller (davem@redhat.com) */ #include #include +#include #include /* This file is meant to be read efficiently by the CPU, not humans. @@ -160,34 +161,86 @@ srlx %o0, 5, %o0 clr %o1 ! IC_addr sllx %g1, 36, %g1 + ldda [%o1] ASI_IC_TAG, %o4 sub %g1, 1, %g2 or %o0, %g1, %o0 ! VALID+phys-addr comparitor - sllx %g2, 1, %g2 + sllx %g2, 1, %g2 andn %g2, 0xfe, %g2 ! IC_tag mask -1: ldda [%o1] ASI_IC_TAG, %o4 - and %o5, %g2, %o5 - cmp %o5, %o0 + nop + nop + nop + nop + nop + nop + +1: addx %g0, %g0, %g0 + ldda [%o1 + %o2] ASI_IC_TAG, %g4 + addx %g0, %g0, %g0 + and %o5, %g2, %g3 + cmp %g3, %o0 + add %o1, 0x20, %o1 + ldda [%o1] ASI_IC_TAG, %o4 be,pn %xcc, iflush1 - add %o1, 0x20, %g3 -2: ldda [%o1 + %o2] ASI_IC_TAG, %o4 - and %o5, %g2, %o5 - cmp %o5, %o0 +2: nop + and %g5, %g2, %g5 + cmp %g5, %o0 be,pn %xcc, iflush2 - nop -3: cmp %g3, %o2 +3: cmp %o1, %o2 bne,pt %xcc, 1b - mov %g3, %o1 + addx %g0, %g0, %g0 + nop + + sethi %uhi(PAGE_OFFSET), %g4 retl - nop + sllx %g4, 32, %g4 -iflush1:stxa %g0, [%o1] ASI_IC_TAG +iflush1:sub %o1, 0x20, %g3 + stxa %g0, [%g3] ASI_IC_TAG flush %g6 ba,a,pt %xcc, 2b -iflush2:stxa %g0, [%o1 + %o2] ASI_IC_TAG +iflush2:sub %o1, 0x20, %g3 + stxa %g0, [%o1 + %o2] ASI_IC_TAG flush %g6 ba,a,pt %xcc, 3b + + .align 32 +__prefill_dtlb: + rdpr %pstate, %g7 + wrpr %g7, PSTATE_IE, %pstate + mov TLB_TAG_ACCESS, %g1 + stxa %o0, [%g1] ASI_DMMU + stxa %o1, [%g0] ASI_DTLB_DATA_IN + flush %g6 + retl + wrpr %g7, %pstate +__prefill_itlb: + rdpr %pstate, %g7 + wrpr %g7, PSTATE_IE, %pstate + mov TLB_TAG_ACCESS, %g1 + stxa %o0, [%g1] ASI_IMMU + stxa %o1, [%g0] ASI_ITLB_DATA_IN + flush %g6 + retl + wrpr %g7, %pstate + + .globl update_mmu_cache +update_mmu_cache: /* %o0=vma, %o1=address, %o2=pte */ + ldub [%g6 + AOFF_task_thread + AOFF_thread_fault_code], %o3 + srlx %o1, 13, %o1 + ldx [%o0 + 0x0], %o4 /* XXX vma->vm_mm */ + brz,pn %o3, 1f + sllx %o1, 13, %o0 + ldx [%o4 + AOFF_mm_context], %o5 + andcc %o3, FAULT_CODE_DTLB, %g0 + mov %o2, %o1 + and %o5, 0x3ff, %o5 + bne,pt %xcc, __prefill_dtlb + or %o0, %o5, %o0 + ba,a,pt %xcc, __prefill_itlb +1: retl + nop #ifdef __SMP__ /* These are all called by the slaves of a cross call, at diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/prom/Makefile linux/arch/sparc64/prom/Makefile --- v2.3.99-pre3/linux/arch/sparc64/prom/Makefile Wed Dec 29 13:13:15 1999 +++ linux/arch/sparc64/prom/Makefile Thu Mar 30 16:56:04 2000 @@ -18,10 +18,10 @@ sync .S.s: - $(CPP) -D__ASSEMBLY__ $(AFLAGS) -ansi $< -o $*.s + $(CPP) $(AFLAGS) -ansi $< -o $*.s .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c $< -o $*.o + $(CC) $(AFLAGS) -ansi -c $< -o $*.o dep: $(CPP) $(CPPFLAGS) -M *.c > .depend diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/solaris/Makefile linux/arch/sparc64/solaris/Makefile --- v2.3.99-pre3/linux/arch/sparc64/solaris/Makefile Mon Nov 16 10:37:28 1998 +++ linux/arch/sparc64/solaris/Makefile Thu Mar 30 16:56:04 2000 @@ -15,10 +15,10 @@ endif .S.s: - $(CPP) -D__ASSEMBLY__ $(AFLAGS) $(CPPFLAGS) -ansi $< -o $*.s + $(CPP) $(AFLAGS) $(CPPFLAGS) -ansi $< -o $*.s .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) $(CPPFLAGS) -ansi -c $< -o $*.o + $(CC) $(AFLAGS) $(CPPFLAGS) -ansi -c $< -o $*.o ifneq ($(CONFIG_SOLARIS_EMUL),y) do_it_all: diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/solaris/fs.c linux/arch/sparc64/solaris/fs.c --- v2.3.99-pre3/linux/arch/sparc64/solaris/fs.c Fri Mar 10 16:40:41 2000 +++ linux/arch/sparc64/solaris/fs.c Sun Apr 2 15:53:28 2000 @@ -495,26 +495,18 @@ asmlinkage int solaris_fstatvfs(unsigned int fd, u32 buf) { - struct inode * inode; - struct dentry * dentry; struct file * file; int error; - lock_kernel(); error = -EBADF; file = fget(fd); - if (!file) - goto out; - - if (!(dentry = file->f_dentry)) - error = -ENOENT; - else if (!(inode = dentry->d_inode)) - error = -ENOENT; - else - error = report_statvfs(inode, buf); - fput(file); + if (file) { + lock_kernel(); + error = report_statvfs(file->f_dentry->d_inode, buf); + unlock_kernel(); + fput(file); + } out: - unlock_kernel(); return error; } @@ -538,26 +530,17 @@ asmlinkage int solaris_fstatvfs64(unsigned int fd, u32 buf) { - struct inode * inode; - struct dentry * dentry; struct file * file; int error; - lock_kernel(); error = -EBADF; file = fget(fd); - if (!file) - goto out; - - if (!(dentry = file->f_dentry)) - error = -ENOENT; - else if (!(inode = dentry->d_inode)) - error = -ENOENT; - else - error = report_statvfs64(inode, buf); - fput(file); -out: - unlock_kernel(); + if (file) { + lock_kernel(); + error = report_statvfs64(file->f_dentry->d_inode, buf); + unlock_kernel(); + fput(file); + } return error; } diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/solaris/misc.c linux/arch/sparc64/solaris/misc.c --- v2.3.99-pre3/linux/arch/sparc64/solaris/misc.c Tue Mar 14 19:10:39 2000 +++ linux/arch/sparc64/solaris/misc.c Sun Apr 2 15:53:28 2000 @@ -72,7 +72,7 @@ file = fget(fd); if (!file) goto out; - if (file->f_dentry && file->f_dentry->d_inode) { + else { struct inode * inode = file->f_dentry->d_inode; if(MAJOR(inode->i_rdev) == MEM_MAJOR && MINOR(inode->i_rdev) == 5) { diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/solaris/socksys.c linux/arch/sparc64/solaris/socksys.c --- v2.3.99-pre3/linux/arch/sparc64/solaris/socksys.c Sun Feb 20 21:12:38 2000 +++ linux/arch/sparc64/solaris/socksys.c Thu Mar 30 16:54:53 2000 @@ -1,4 +1,4 @@ -/* $Id: socksys.c,v 1.12 2000/02/17 05:50:11 davem Exp $ +/* $Id: socksys.c,v 1.13 2000/03/29 11:56:54 davem Exp $ * socksys.c: /dev/inet/ stuff for Solaris emulation. * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -17,6 +17,7 @@ #include #include #include +#include #include #include diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sparc64/solaris/timod.c linux/arch/sparc64/solaris/timod.c --- v2.3.99-pre3/linux/arch/sparc64/solaris/timod.c Wed Dec 29 13:13:15 1999 +++ linux/arch/sparc64/solaris/timod.c Mon Mar 27 10:35:56 2000 @@ -1,4 +1,4 @@ -/* $Id: timod.c,v 1.5 1999/11/23 08:55:24 davem Exp $ +/* $Id: timod.c,v 1.6 2000/03/25 03:23:21 davem Exp $ * timod.c: timod emulation. * * Copyright (C) 1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz) @@ -151,7 +151,7 @@ SOLD("wakeing socket"); sock = ¤t->files->fd[fd]->f_dentry->d_inode->u.socket_i; wake_up_interruptible(&sock->wait); - if (sock->fasync_list && !(sock->flags & SO_WAITDATA)) + if (sock->fasync_list && !test_bit(SOCK_ASYNC_WAITDATA, &sock->flags)) kill_fasync(sock->fasync_list, SIGIO, POLL_IN); SOLD("done"); } diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/acorn/char/keyb_ps2.c linux/drivers/acorn/char/keyb_ps2.c --- v2.3.99-pre3/linux/drivers/acorn/char/keyb_ps2.c Sun Feb 13 19:29:03 2000 +++ linux/drivers/acorn/char/keyb_ps2.c Mon Mar 27 10:45:48 2000 @@ -32,8 +32,6 @@ extern void kbd_reset_kdown(void); int kbd_read_mask; -#define IRQ_KEYBOARDRX 15 - #define VERSION 100 #define KBD_REPORT_ERR @@ -330,6 +328,10 @@ { unsigned long flags; + /* Reset the keyboard state machine. */ + outb(0, IOMD_KCTRL); + outb(8, IOMD_KCTRL); + save_flags_cli (flags); if (request_irq (IRQ_KEYBOARDRX, ps2kbd_rx, 0, "keyboard", NULL) != 0) panic("Could not allocate keyboard receive IRQ!"); @@ -342,4 +344,3 @@ printk (KERN_INFO "PS/2 keyboard driver v%d.%02d\n", VERSION/100, VERSION%100); return 0; } - diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/acorn/scsi/acornscsi.h linux/drivers/acorn/scsi/acornscsi.h --- v2.3.99-pre3/linux/drivers/acorn/scsi/acornscsi.h Thu Nov 11 20:11:32 1999 +++ linux/drivers/acorn/scsi/acornscsi.h Sun Apr 2 17:28:21 2000 @@ -1,3 +1,8 @@ +/* + * Acorn SCSI driver + * + * Copyright (C) 1997 Russell King + */ #ifndef ACORNSCSI_H #define ACORNSCSI_H diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/acorn/scsi/arxescsi.c linux/drivers/acorn/scsi/arxescsi.c --- v2.3.99-pre3/linux/drivers/acorn/scsi/arxescsi.c Thu Mar 2 14:36:22 2000 +++ linux/drivers/acorn/scsi/arxescsi.c Sun Apr 2 17:28:21 2000 @@ -1,7 +1,7 @@ /* - * linux/arch/arm/drivers/scsi/cumana_2.c + * linux/arch/arm/drivers/scsi/arxescsi.c * - * Copyright (C) 1997,1998 Russell King + * Copyright (C) 1997-2000 Russell King * * This driver is based on experimentation. Hence, it may have made * assumptions about the particular card that I have available, and @@ -13,6 +13,7 @@ * 15-04-1998 RMK 0.0.1 Only do PIO if FAS216 will allow it. * 11-06-1998 0.0.2 Changed to support ARXE 16-bit SCSI card, enabled writing * by Stefan Hanske + * 02-04-2000 RMK 0.0.3 Updated for new error handling code. */ #include @@ -54,7 +55,7 @@ */ #define VER_MAJOR 0 #define VER_MINOR 0 -#define VER_PATCH 2 +#define VER_PATCH 3 static struct expansion_card *ecs[MAX_ECARDS]; @@ -308,10 +309,9 @@ static char string[100], *p; p = string; - p += sprintf(string, "%s at port %lX irq %d v%d.%d.%d scsi %s", - host->hostt->name, host->io_port, host->irq, - VER_MAJOR, VER_MINOR, VER_PATCH, - info->info.scsi.type); + p += sprintf(p, "%s ", host->hostt->name); + p += fas216_info(&info->info, p); + p += sprintf(p, "v%d.%d.%d", VER_MAJOR, VER_MINOR, VER_PATCH); return string; } @@ -354,12 +354,7 @@ pos = sprintf(buffer, "ARXE 16-bit SCSI driver version %d.%d.%d\n", VER_MAJOR, VER_MINOR, VER_PATCH); - pos += sprintf(buffer + pos, - "Address: %08lX IRQ : %d\n" - "FAS : %s\n\n" - "Statistics:\n", - host->io_port, host->irq, info->info.scsi.type); - + pos += fas216_print_host(&info->info, buffer + pos); pos += fas216_print_stats(&info->info, buffer + pos); pos += sprintf (buffer+pos, "\nAttached devices:\n"); diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/acorn/scsi/arxescsi.h linux/drivers/acorn/scsi/arxescsi.h --- v2.3.99-pre3/linux/drivers/acorn/scsi/arxescsi.h Thu Jun 17 01:11:35 1999 +++ linux/drivers/acorn/scsi/arxescsi.h Sun Apr 2 17:28:21 2000 @@ -1,7 +1,8 @@ /* * ARXE SCSI card driver * - * Copyright (C) 1997 Russell King + * Copyright (C) 1997-2000 Russell King + * * Changes to support ARXE 16-bit SCSI card by Stefan Hanske */ #ifndef ARXE_SCSI_H @@ -44,22 +45,25 @@ #include "fas216.h" #endif -#define ARXEScsi { \ -proc_info: arxescsi_proc_info, \ -name: "ARXE SCSI card", \ -detect: arxescsi_detect, /* detect */ \ -release: arxescsi_release, /* release */ \ -info: arxescsi_info, /* info */ \ -command: fas216_command, /* command */ \ -queuecommand: fas216_queue_command, /* queuecommand */ \ -abort: fas216_abort, /* abort */ \ -reset: fas216_reset, /* reset */ \ -bios_param: scsicam_bios_param, /* biosparam */ \ -can_queue: CAN_QUEUE, /* can queue */ \ -this_id: SCSI_ID, /* scsi host id */ \ -sg_tablesize: SG_ALL, /* sg_tablesize */ \ -cmd_per_lun: CMD_PER_LUN, /* cmd per lun */ \ -use_clustering: DISABLE_CLUSTERING \ +#define ARXEScsi { \ +proc_info: arxescsi_proc_info, \ +name: "ARXE SCSI card", \ +detect: arxescsi_detect, \ +release: arxescsi_release, \ +info: arxescsi_info, \ +bios_param: scsicam_bios_param, \ +can_queue: CAN_QUEUE, \ +this_id: SCSI_ID, \ +sg_tablesize: SG_ALL, \ +cmd_per_lun: CMD_PER_LUN, \ +use_clustering: DISABLE_CLUSTERING, \ +command: fas216_command, \ +queuecommand: fas216_queue_command, \ +eh_host_reset_handler: fas216_eh_host_reset, \ +eh_bus_reset_handler: fas216_eh_bus_reset, \ +eh_device_reset_handler: fas216_eh_device_reset, \ +eh_abort_handler: fas216_eh_abort, \ +use_new_eh_code: 1 \ } #ifndef HOSTS_C diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/acorn/scsi/cumana_2.c linux/drivers/acorn/scsi/cumana_2.c --- v2.3.99-pre3/linux/drivers/acorn/scsi/cumana_2.c Thu Nov 11 20:11:32 1999 +++ linux/drivers/acorn/scsi/cumana_2.c Sun Apr 2 17:28:22 2000 @@ -1,7 +1,7 @@ /* * linux/arch/arm/drivers/scsi/cumana_2.c * - * Copyright (C) 1997-1998 Russell King + * Copyright (C) 1997-2000 Russell King * * Changelog: * 30-08-1997 RMK 0.0.0 Created, READONLY version. @@ -10,6 +10,7 @@ * 02-05-1998 RMK 0.0.2 Updated & added DMA support. * 27-06-1998 RMK Changed asm/delay.h to linux/delay.h * 18-08-1998 RMK 0.0.3 Fixed synchronous transfer depth. + * 02-04-2000 RMK 0.0.4 Updated for new error handling code. */ #include @@ -70,7 +71,7 @@ */ #define VER_MAJOR 0 #define VER_MINOR 0 -#define VER_PATCH 3 +#define VER_PATCH 4 static struct expansion_card *ecs[MAX_ECARDS]; @@ -433,25 +434,11 @@ static char string[100], *p; p = string; - p += sprintf(string, "%s at port %lX ", - host->hostt->name, host->io_port); - - if (host->irq != NO_IRQ) - p += sprintf(p, "irq %d ", host->irq); - else - p += sprintf(p, "NO IRQ "); - - if (host->dma_channel != NO_DMA) - p += sprintf(p, "dma %d ", host->dma_channel); - else - p += sprintf(p, "NO DMA "); - - p += sprintf(p, "v%d.%d.%d scsi %s", + p += sprintf(p, "%s ", host->hostt->name); + p += fas216_info(&info->info, p); + p += sprintf(p, "v%d.%d.%d terminators o%s", VER_MAJOR, VER_MINOR, VER_PATCH, - info->info.scsi.type); - - p += sprintf(p, " terminators %s", - info->terms ? "on" : "off"); + info->terms ? "n" : "ff"); return string; } @@ -525,26 +512,14 @@ pos = sprintf(buffer, "Cumana SCSI II driver version %d.%d.%d\n", VER_MAJOR, VER_MINOR, VER_PATCH); - pos += sprintf(buffer + pos, - "Address: %08lX IRQ : %d DMA : %d\n" - "FAS : %-10s TERM: %-3s\n\n" - "Statistics:\n", - host->io_port, host->irq, host->dma_channel, - info->info.scsi.type, info->terms ? "on" : "off"); - - pos += sprintf(buffer+pos, - "Queued commands: %-10u Issued commands: %-10u\n" - "Done commands : %-10u Reads : %-10u\n" - "Writes : %-10u Others : %-10u\n" - "Disconnects : %-10u Aborts : %-10u\n" - "Resets : %-10u\n", - info->info.stats.queues, info->info.stats.removes, - info->info.stats.fins, info->info.stats.reads, - info->info.stats.writes, info->info.stats.miscs, - info->info.stats.disconnects, info->info.stats.aborts, - info->info.stats.resets); - pos += sprintf(buffer+pos, "\nAttached devices:%s\n", host->host_queue ? "" : " none"); + pos += fas216_print_host(&info->info, buffer + pos); + pos += sprintf(buffer + pos, "Term : o%s\n", + info->terms ? "n" : "ff"); + + pos += fas216_print_stats(&info->info, buffer + pos); + + pos += sprintf(buffer+pos, "\nAttached devices:\n"); for (scd = host->host_queue; scd; scd = scd->next) { int len; diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/acorn/scsi/cumana_2.h linux/drivers/acorn/scsi/cumana_2.h --- v2.3.99-pre3/linux/drivers/acorn/scsi/cumana_2.h Fri May 8 00:42:39 1998 +++ linux/drivers/acorn/scsi/cumana_2.h Sun Apr 2 17:28:22 2000 @@ -1,7 +1,7 @@ /* * Cumana SCSI II driver * - * Copyright (C) 1997-1998 Russell King + * Copyright (C) 1997-2000 Russell King */ #ifndef CUMANA_2_H #define CUMANA_2_H @@ -23,6 +23,13 @@ #define CAN_QUEUE 1 #endif +#ifndef CMD_PER_LUN +/* + * Default queue size + */ +#define CMD_PER_LUN 1 +#endif + #ifndef SCSI_ID /* * Default SCSI host ID @@ -36,23 +43,25 @@ #include "fas216.h" #endif -#define CUMANASCSI_2 { \ -proc_info: cumanascsi_2_proc_info, \ -name: "Cumana SCSI II", \ -detect: cumanascsi_2_detect, /* detect */ \ -release: cumanascsi_2_release, /* release */ \ -info: cumanascsi_2_info, /* info */ \ -command: fas216_command, /* command */ \ -queuecommand: fas216_queue_command, /* queuecommand */ \ -abort: fas216_abort, /* abort */ \ -reset: fas216_reset, /* reset */ \ -bios_param: scsicam_bios_param, /* biosparam */ \ -can_queue: CAN_QUEUE, /* can queue */ \ -this_id: SCSI_ID, /* scsi host id */ \ -sg_tablesize: SG_ALL, /* sg_tablesize */ \ -cmd_per_lun: CAN_QUEUE, /* cmd per lun */ \ -unchecked_isa_dma: 0, /* unchecked isa dma */ \ -use_clustering: DISABLE_CLUSTERING \ +#define CUMANASCSI_2 { \ +proc_info: cumanascsi_2_proc_info, \ +name: "Cumana SCSI II", \ +detect: cumanascsi_2_detect, \ +release: cumanascsi_2_release, \ +info: cumanascsi_2_info, \ +bios_param: scsicam_bios_param, \ +can_queue: CAN_QUEUE, \ +this_id: SCSI_ID, \ +sg_tablesize: SG_ALL, \ +cmd_per_lun: CMD_PER_LUN, \ +use_clustering: DISABLE_CLUSTERING, \ +command: fas216_command, \ +queuecommand: fas216_queue_command, \ +eh_host_reset_handler: fas216_eh_host_reset, \ +eh_bus_reset_handler: fas216_eh_bus_reset, \ +eh_device_reset_handler: fas216_eh_device_reset, \ +eh_abort_handler: fas216_eh_abort, \ +use_new_eh_code: 1 \ } #ifndef HOSTS_C diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/acorn/scsi/eesox.c linux/drivers/acorn/scsi/eesox.c --- v2.3.99-pre3/linux/drivers/acorn/scsi/eesox.c Thu Nov 11 20:11:32 1999 +++ linux/drivers/acorn/scsi/eesox.c Sun Apr 2 17:28:22 2000 @@ -1,20 +1,22 @@ /* * linux/arch/arm/drivers/scsi/eesox.c * - * Copyright (C) 1997-1998 Russell King + * Copyright (C) 1997-2000 Russell King * * This driver is based on experimentation. Hence, it may have made * assumptions about the particular card that I have available, and * may not be reliable! * * Changelog: - * 01-10-1997 RMK Created, READONLY version - * 15-02-1998 RMK READ/WRITE version - * added DMA support and hardware definitions - * 14-03-1998 RMK Updated DMA support - * Added terminator control - * 15-04-1998 RMK Only do PIO if FAS216 will allow it. - * 27-06-1998 RMK Changed asm/delay.h to linux/delay.h + * 01-10-1997 RMK Created, READONLY version + * 15-02-1998 RMK READ/WRITE version + * added DMA support and hardware definitions + * 14-03-1998 RMK Updated DMA support + * Added terminator control + * 15-04-1998 RMK Only do PIO if FAS216 will allow it. + * 27-06-1998 RMK Changed asm/delay.h to linux/delay.h + * 02-04-2000 RMK 0.0.3 Fixed NO_IRQ/NO_DMA problem, updated for new + * error handling code. */ #include @@ -67,7 +69,7 @@ */ #define VER_MAJOR 0 #define VER_MINOR 0 -#define VER_PATCH 2 +#define VER_PATCH 3 static struct expansion_card *ecs[MAX_ECARDS]; @@ -382,14 +384,16 @@ request_region(host->io_port + EESOX_FAS216_OFFSET, 16 << EESOX_FAS216_SHIFT, "eesox2-fas"); - if (request_irq(host->irq, eesoxscsi_intr, + if (host->irq != NO_IRQ && + request_irq(host->irq, eesoxscsi_intr, SA_INTERRUPT, "eesox", host)) { printk("scsi%d: IRQ%d not free, interrupts disabled\n", host->host_no, host->irq); host->irq = NO_IRQ; } - if (request_dma(host->dma_channel, "eesox")) { + if (host->dma_channel != NO_DMA && + request_dma(host->dma_channel, "eesox")) { printk("scsi%d: DMA%d not free, DMA disabled\n", host->host_no, host->dma_channel); host->dma_channel = NO_DMA; @@ -435,24 +439,11 @@ static char string[100], *p; p = string; - p += sprintf(string, "%s at port %lX ", - host->hostt->name, host->io_port); - - if (host->irq != NO_IRQ) - p += sprintf(p, "irq %d ", host->irq); - else - p += sprintf(p, "NO IRQ "); - - if (host->dma_channel != NO_DMA) - p += sprintf(p, "dma %d ", host->dma_channel); - else - p += sprintf(p, "NO DMA "); - - p += sprintf(p, "v%d.%d.%d scsi %s", VER_MAJOR, VER_MINOR, VER_PATCH, - info->info.scsi.type); - - p += sprintf(p, " terminators %s", - info->control.control & EESOX_TERM_ENABLE ? "on" : "off"); + p += sprintf(p, "%s ", host->hostt->name); + p += fas216_info(&info->info, p); + p += sprintf(p, "v%d.%d.%d terminators o%s", + VER_MAJOR, VER_MINOR, VER_PATCH, + info->control.control & EESOX_TERM_ENABLE ? "n" : "ff"); return string; } @@ -526,26 +517,13 @@ pos = sprintf(buffer, "EESOX SCSI driver version %d.%d.%d\n", VER_MAJOR, VER_MINOR, VER_PATCH); - pos += sprintf(buffer + pos, - "Address: %08lX IRQ : %d DMA : %d\n" - "FAS : %-10s TERM: %-3s\n\n" - "Statistics:\n", - host->io_port, host->irq, host->dma_channel, - info->info.scsi.type, info->control.control & EESOX_TERM_ENABLE ? "on" : "off"); - - pos += sprintf(buffer+pos, - "Queued commands: %-10u Issued commands: %-10u\n" - "Done commands : %-10u Reads : %-10u\n" - "Writes : %-10u Others : %-10u\n" - "Disconnects : %-10u Aborts : %-10u\n" - "Resets : %-10u\n", - info->info.stats.queues, info->info.stats.removes, - info->info.stats.fins, info->info.stats.reads, - info->info.stats.writes, info->info.stats.miscs, - info->info.stats.disconnects, info->info.stats.aborts, - info->info.stats.resets); + pos += fas216_print_host(&info->info, buffer + pos); + pos += sprintf(buffer + pos, "Term : o%s\n", + info->control.control & EESOX_TERM_ENABLE ? "n" : "ff"); + + pos += fas216_print_stats(&info->info, buffer + pos); - pos += sprintf (buffer+pos, "\nAttached devices:%s\n", host->host_queue ? "" : " none"); + pos += sprintf (buffer+pos, "\nAttached devices:\n"); for (scd = host->host_queue; scd; scd = scd->next) { int len; diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/acorn/scsi/eesox.h linux/drivers/acorn/scsi/eesox.h --- v2.3.99-pre3/linux/drivers/acorn/scsi/eesox.h Fri May 8 00:42:39 1998 +++ linux/drivers/acorn/scsi/eesox.h Sun Apr 2 17:28:22 2000 @@ -1,7 +1,7 @@ /* * EESOX SCSI driver * - * Copyright (C) 1997-1998 Russell King + * Copyright (C) 1997-2000 Russell King */ #ifndef EESOXSCSI_H #define EESOXSCSI_H @@ -38,22 +38,25 @@ #include "fas216.h" -#define EESOXSCSI { \ -proc_info: eesoxscsi_proc_info, \ -name: "EESOX SCSI", \ -detect: eesoxscsi_detect, /* detect */ \ -release: eesoxscsi_release, /* release */ \ -info: eesoxscsi_info, /* info */ \ -command: fas216_command, /* command */ \ -queuecommand: fas216_queue_command, /* queuecommand */ \ -abort: fas216_abort, /* abort */ \ -reset: fas216_reset, /* reset */ \ -bios_param: scsicam_bios_param, /* biosparam */ \ -can_queue: CAN_QUEUE, /* can queue */ \ -this_id: SCSI_ID, /* scsi host id */ \ -sg_tablesize: SG_ALL, /* sg_tablesize */ \ -cmd_per_lun: CAN_QUEUE, /* cmd per lun */ \ -use_clustering: DISABLE_CLUSTERING \ +#define EESOXSCSI { \ +proc_info: eesoxscsi_proc_info, \ +name: "EESOX SCSI", \ +detect: eesoxscsi_detect, \ +release: eesoxscsi_release, \ +info: eesoxscsi_info, \ +bios_param: scsicam_bios_param, \ +can_queue: CAN_QUEUE, \ +this_id: SCSI_ID, \ +sg_tablesize: SG_ALL, \ +cmd_per_lun: CAN_QUEUE, \ +use_clustering: DISABLE_CLUSTERING, \ +command: fas216_command, \ +queuecommand: fas216_queue_command, \ +eh_host_reset_handler: fas216_eh_host_reset, \ +eh_bus_reset_handler: fas216_eh_bus_reset, \ +eh_device_reset_handler: fas216_eh_device_reset, \ +eh_abort_handler: fas216_eh_abort, \ +use_new_eh_code: 1 \ } #ifndef HOSTS_C diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/acorn/scsi/fas216.c linux/drivers/acorn/scsi/fas216.c --- v2.3.99-pre3/linux/drivers/acorn/scsi/fas216.c Tue Dec 14 01:27:23 1999 +++ linux/drivers/acorn/scsi/fas216.c Sun Apr 2 17:28:22 2000 @@ -1,11 +1,12 @@ /* * linux/arch/arm/drivers/scsi/fas216.c * - * Copyright (C) 1997 Russell King + * Copyright (C) 1997-2000 Russell King * * Based on information in qlogicfas.c by Tom Zerucha, Michael Griffith, and * other sources, including: * the AMD Am53CF94 data sheet + * the AMD Am53C94 data sheet * * This is a generic driver. To use it, have a look at cumana_2.c. You * should define your own structure that overlays FAS216_Info, eg: @@ -25,6 +26,9 @@ * 24-05-1998 RMK Fixed synchronous transfers with period >= 200ns * 27-06-1998 RMK Changed asm/delay.h to linux/delay.h * 26-08-1998 RMK Improved message support wrt MESSAGE_REJECT + * 02-04-2000 RMK Converted to use the new error handling, and + * automatically request sense data upon check + * condition status from targets. * * Todo: * - allow individual devices to enable sync xfers. @@ -59,8 +63,6 @@ #define VER_MINOR 0 #define VER_PATCH 5 -#define SCSI2_TAG - /* NOTE: SCSI2 Synchronous transfers *require* DMA according to * the data sheet. This restriction is crazy, especially when * you only want to send 16 bytes! What were the guys who @@ -85,8 +87,8 @@ * I was thinking that this was a good chip until I found this restriction ;( */ #define SCSI2_SYNC - -#define SCSI2_WIDE +#undef SCSI2_WIDE +#undef SCSI2_TAG #undef DEBUG_CONNECT #undef DEBUG_BUSSERVICE @@ -143,10 +145,11 @@ info->scsi.async_stp, info->scsi.disconnectable, info->scsi.aborting); printk(" stats={ queues=%X removes=%X fins=%X reads=%X writes=%X miscs=%X\n" - " disconnects=%X aborts=%X resets=%X }\n", + " disconnects=%X aborts=%X bus_resets=%X host_resets=%X}\n", info->stats.queues, info->stats.removes, info->stats.fins, info->stats.reads, info->stats.writes, info->stats.miscs, - info->stats.disconnects, info->stats.aborts, info->stats.resets); + info->stats.disconnects, info->stats.aborts, info->stats.bus_resets, + info->stats.host_resets); printk(" ifcfg={ clockrate=%X select_timeout=%X asyncperiod=%X sync_max_depth=%X }\n", info->ifcfg.clockrate, info->ifcfg.select_timeout, info->ifcfg.asyncperiod, info->ifcfg.sync_max_depth); @@ -164,7 +167,7 @@ } #ifdef CHECK_STRUCTURE -static void fas216_checkmagic(FAS216_Info *info, const char *func) +static void __fas216_checkmagic(FAS216_Info *info, const char *func) { int corruption = 0; if (info->magic_start != MAGIC) { @@ -180,8 +183,9 @@ panic("scsi memory space corrupted in %s", func); } } +#define fas216_checkmagic(info) __fas216_checkmagic((info), __FUNCTION__) #else -#define fas216_checkmagic(info,func) +#define fas216_checkmagic(info) #endif static const char *fas216_bus_phase(int stat) @@ -312,7 +316,7 @@ { int value = (info->ifcfg.clockrate * ns) / 1000; - fas216_checkmagic(info, "fas216_syncperiod"); + fas216_checkmagic(info); if (value < 4) value = 4; @@ -586,7 +590,7 @@ unsigned char *ptr; unsigned int residual; - fas216_checkmagic(info, "fas216_updateptrs"); + fas216_checkmagic(info); ptr = info->scsi.SCp.ptr; residual = info->scsi.SCp.this_residual; @@ -629,7 +633,7 @@ unsigned int residual; char *ptr; - fas216_checkmagic(info, "fas216_pio"); + fas216_checkmagic(info); residual = info->scsi.SCp.this_residual; ptr = info->scsi.SCp.ptr; @@ -668,7 +672,7 @@ { fasdmatype_t dmatype; - fas216_checkmagic(info, "fas216_starttransfer"); + fas216_checkmagic(info); info->scsi.phase = (direction == DMA_OUT) ? PHASE_DATAOUT : PHASE_DATAIN; @@ -763,7 +767,7 @@ static void fas216_stoptransfer(FAS216_Info *info) { - fas216_checkmagic(info, "fas216_stoptransfer"); + fas216_checkmagic(info); if (info->dma.transfer_type != fasdma_none && info->dma.transfer_type != fasdma_pio) { @@ -797,7 +801,7 @@ static void fas216_disconnect_intr(FAS216_Info *info) { - fas216_checkmagic(info, "fas216_disconnected_intr"); + fas216_checkmagic(info); #ifdef DEBUG_CONNECT printk("scsi%d.%c: disconnect phase=%02X\n", info->host->host_no, @@ -849,7 +853,7 @@ { unsigned char target, identify_msg, ok; - fas216_checkmagic(info, "fas216_reselected_intr"); + fas216_checkmagic(info); if ((info->scsi.phase == PHASE_SELECTION || info->scsi.phase == PHASE_SELSTEPS) && info->SCpnt) { @@ -949,6 +953,7 @@ msgqueue_addmsg(&info->scsi.msgs, 1, ABORT); info->scsi.phase = PHASE_MSGOUT_EXPECT; } + outb(CMD_MSGACCEPTED, REG_CMD(info)); } @@ -959,7 +964,7 @@ static void fas216_finish_reconnect(FAS216_Info *info) { - fas216_checkmagic(info, "fas216_reconnect"); + fas216_checkmagic(info); #ifdef DEBUG_CONNECT printk("Connected: %1X %1X %02X, reconnected: %1X %1X %02X\n", @@ -1087,7 +1092,7 @@ unsigned int msglen = 1, i; int msgbyte = 0; - fas216_checkmagic(info, "fas216_message"); + fas216_checkmagic(info); message[0] = inb(REG_FF(info)); @@ -1270,7 +1275,7 @@ { int i; - fas216_checkmagic(info, "fas216_send_command"); + fas216_checkmagic(info); outb(CMD_NOP|CMD_WITHDMA, REG_CMD(info)); outb(CMD_FLUSHFIFO, REG_CMD(info)); @@ -1293,7 +1298,7 @@ { unsigned int tot_msglen = msgqueue_msglength(&info->scsi.msgs); - fas216_checkmagic(info, "fas216_send_messageout"); + fas216_checkmagic(info); outb(CMD_FLUSHFIFO, REG_CMD(info)); @@ -1326,7 +1331,7 @@ */ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigned int ssr) { - fas216_checkmagic(info, "fas216_busservice_intr"); + fas216_checkmagic(info); #ifdef DEBUG_BUSSERVICE printk("scsi%d.%c: bus service: stat=%02X ssr=%02X phase=%02X\n", @@ -1520,7 +1525,7 @@ { int status, message; - fas216_checkmagic(info, "fas216_funcdone_intr"); + fas216_checkmagic(info); #ifdef DEBUG_FUNCTIONDONE printk("scsi%d.%c: function done: stat=%X ssr=%X phase=%02X\n", @@ -1562,7 +1567,7 @@ FAS216_Info *info = (FAS216_Info *)instance->hostdata; unsigned char isr, ssr, stat; - fas216_checkmagic(info, "fas216_intr"); + fas216_checkmagic(info); stat = inb(REG_STAT(info)); ssr = inb(REG_IS(info)); @@ -1571,9 +1576,10 @@ add_debug_list(stat, ssr, isr, info->scsi.phase); if (stat & STAT_INT) { - if (isr & INST_BUSRESET) + if (isr & INST_BUSRESET) { printk(KERN_DEBUG "scsi%d.H: bus reset detected\n", instance->host_no); - else if (isr & INST_ILLEGALCMD) { + scsi_report_bus_reset(instance, 0); + } else if (isr & INST_ILLEGALCMD) { printk(KERN_CRIT "scsi%d.H: illegal command given\n", instance->host_no); fas216_dumpstate(info); } else if (isr & INST_DISCONNECT) @@ -1599,22 +1605,35 @@ */ static void fas216_kick(FAS216_Info *info) { - Scsi_Cmnd *SCpnt; - int tot_msglen, from_queue = 0; + Scsi_Cmnd *SCpnt = NULL; + int tot_msglen, from_queue = 0, disconnect_ok; - fas216_checkmagic(info, "fas216_kick"); + fas216_checkmagic(info); - if (info->origSCpnt) { - SCpnt = info->origSCpnt; - info->origSCpnt = NULL; - } else - SCpnt = NULL; + /* + * Obtain the next command to process. + */ + do { + if (info->reqSCpnt) { + SCpnt = info->reqSCpnt; + info->reqSCpnt = NULL; + break; + } - /* retrieve next command */ - if (!SCpnt) { - SCpnt = queue_remove_exclude(&info->queues.issue, info->busyluns); - from_queue = 1; - } + if (info->origSCpnt) { + SCpnt = info->origSCpnt; + info->origSCpnt = NULL; + break; + } + + /* retrieve next command */ + if (!SCpnt) { + SCpnt = queue_remove_exclude(&info->queues.issue, + info->busyluns); + from_queue = 1; + break; + } + } while (0); if (!SCpnt) /* no command pending - just exit */ return; @@ -1628,16 +1647,6 @@ } /* - * tagged queuing - allocate a new tag to this command - */ - if (SCpnt->device->tagged_queue && SCpnt->cmnd[0] != REQUEST_SENSE) { - SCpnt->device->current_tag += 1; - if (SCpnt->device->current_tag == 0) - SCpnt->device->current_tag = 1; - SCpnt->tag = SCpnt->device->current_tag; - } - - /* * claim host busy */ info->scsi.phase = PHASE_SELECTION; @@ -1653,6 +1662,9 @@ if (from_queue) { #ifdef SCSI2_TAG + /* + * tagged queuing - allocate a new tag to this command + */ if (SCpnt->device->tagged_queue && SCpnt->cmnd[0] != REQUEST_SENSE && SCpnt->cmnd[0] != INQUIRY) { SCpnt->device->current_tag += 1; @@ -1681,41 +1693,48 @@ } } - /* build outgoing message bytes */ - msgqueue_flush(&info->scsi.msgs); + /* + * Don't allow request sense commands to disconnect. + */ + disconnect_ok = SCpnt->cmnd[0] != REQUEST_SENSE && + info->device[SCpnt->target].disconnect_ok; - if (info->device[SCpnt->target].disconnect_ok) - msgqueue_addmsg(&info->scsi.msgs, 1, IDENTIFY(1, SCpnt->lun)); - else - msgqueue_addmsg(&info->scsi.msgs, 1, IDENTIFY(0, SCpnt->lun)); + /* + * build outgoing message bytes + */ + msgqueue_flush(&info->scsi.msgs); + msgqueue_addmsg(&info->scsi.msgs, 1, IDENTIFY(disconnect_ok, SCpnt->lun)); - /* add tag message if required */ + /* + * add tag message if required + */ if (SCpnt->tag) msgqueue_addmsg(&info->scsi.msgs, 2, SIMPLE_QUEUE_TAG, SCpnt->tag); + do { #ifdef SCSI2_WIDE - if (info->device[SCpnt->target].wide_state == neg_wait) { - info->device[SCpnt->target].wide_state = neg_inprogress; - msgqueue_addmsg(&info->scsi.msgs, 4, - EXTENDED_MESSAGE, 2, EXTENDED_WDTR, - info->ifcfg.wide_max_size); - } -#ifdef SCSI2_SYNC - else -#endif + if (info->device[SCpnt->target].wide_state == neg_wait) { + info->device[SCpnt->target].wide_state = neg_inprogress; + msgqueue_addmsg(&info->scsi.msgs, 4, + EXTENDED_MESSAGE, 2, EXTENDED_WDTR, + info->ifcfg.wide_max_size); + break; + } #endif #ifdef SCSI2_SYNC - if ((info->device[SCpnt->target].sync_state == neg_wait || - info->device[SCpnt->target].sync_state == neg_complete) && - (SCpnt->cmnd[0] == REQUEST_SENSE || - SCpnt->cmnd[0] == INQUIRY)) { - info->device[SCpnt->target].sync_state = neg_inprogress; - msgqueue_addmsg(&info->scsi.msgs, 5, - EXTENDED_MESSAGE, 3, EXTENDED_SDTR, - 1000 / info->ifcfg.clockrate, - info->ifcfg.sync_max_depth); - } + if ((info->device[SCpnt->target].sync_state == neg_wait || + info->device[SCpnt->target].sync_state == neg_complete) && + (SCpnt->cmnd[0] == REQUEST_SENSE || + SCpnt->cmnd[0] == INQUIRY)) { + info->device[SCpnt->target].sync_state = neg_inprogress; + msgqueue_addmsg(&info->scsi.msgs, 5, + EXTENDED_MESSAGE, 3, EXTENDED_SDTR, + 1000 / info->ifcfg.clockrate, + info->ifcfg.sync_max_depth); + break; + } #endif + } while (0); /* following what the ESP driver says */ outb(0, REG_STCL(info)); @@ -1780,18 +1799,156 @@ /* should now get either DISCONNECT or (FUNCTION DONE with BUS SERVICE) intr */ } +/* Function: void fas216_rq_sns_done(info, SCpnt, result) + * Purpose : Finish processing automatic request sense command + * Params : info - interface that completed + * SCpnt - command that completed + * result - driver byte of result + */ +static void +fas216_rq_sns_done(FAS216_Info *info, Scsi_Cmnd *SCpnt, unsigned int result) +{ +#ifdef DEBUG_CONNECT + printk("scsi%d.%c: request sense complete, result=%04X%02X%02X\n", + info->host->host_no, '0' + SCpnt->target, result, + SCpnt->SCp.Message, SCpnt->SCp.Status); +#endif + + if (result != DID_OK || SCpnt->SCp.Status != GOOD) + /* + * Something went wrong. Make sure that we don't + * have valid data in the sense buffer that could + * confuse the higher levels. + */ + memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer)); + + /* + * Note that we don't set SCpnt->result, since that should + * reflect the status of the command that we were asked by + * the upper layers to process. This would have been set + * correctly by fas216_std_done. + */ + SCpnt->scsi_done(SCpnt); +} + +/* Function: void fas216_std_done(info, SCpnt, result) + * Purpose : Finish processing of standard command + * Params : info - interface that completed + * SCpnt - command that completed + * result - driver byte of result + */ +static void +fas216_std_done(FAS216_Info *info, Scsi_Cmnd *SCpnt, unsigned int result) +{ + info->stats.fins += 1; + + SCpnt->result = result << 16 | info->scsi.SCp.Message << 8 | + info->scsi.SCp.Status; + +#ifdef DEBUG_CONNECT + printk("scsi%d.%c: command complete, result=%08X, command=", + info->host->host_no, '0' + SCpnt->target, SCpnt->result); + print_command(SCpnt->cmnd); +#endif + + /* + * If the driver detected an error, or the command + * was request sense, then we're all done. + */ + if (result != DID_OK || SCpnt->cmnd[0] == REQUEST_SENSE) + goto done; + + /* + * If the command returned CHECK_CONDITION status, + * request the sense information. + */ + if (info->scsi.SCp.Status == CHECK_CONDITION) + goto request_sense; + + /* + * If the command did not complete with GOOD status, + * we are all done here. + */ + if (info->scsi.SCp.Status != GOOD) + goto done; + + /* + * We have successfully completed a command. Make sure that + * we do not have any buffers left to transfer. The world + * is not perfect, and we seem to occasionally hit this. + * It can be indicative of a buggy driver, target or the upper + * levels of the SCSI code. + */ + if (info->scsi.SCp.ptr) { + switch (SCpnt->cmnd[0]) { + case INQUIRY: + case START_STOP: +// case READ_CAPACITY: + case MODE_SENSE: + break; + + default: + printk(KERN_ERR "scsi%d.%c: incomplete data transfer " + "detected: res=%08X ptr=%p len=%X command=", + info->host->host_no, '0' + SCpnt->target, + SCpnt->result, info->scsi.SCp.ptr, + info->scsi.SCp.this_residual); + print_command(SCpnt->cmnd); + } + } + +done: SCpnt->scsi_done(SCpnt); + return; + +request_sense: + memset(SCpnt->cmnd, 0, sizeof (SCpnt->cmnd)); + SCpnt->cmnd[0] = REQUEST_SENSE; + SCpnt->cmnd[1] = SCpnt->lun << 5; + SCpnt->cmnd[4] = sizeof(SCpnt->sense_buffer); + SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]); + SCpnt->SCp.buffer = NULL; + SCpnt->SCp.buffers_residual = 0; + SCpnt->SCp.ptr = (char *)SCpnt->sense_buffer; + SCpnt->SCp.this_residual = sizeof(SCpnt->sense_buffer); + SCpnt->SCp.Message = 0; + SCpnt->SCp.Status = 0; + SCpnt->sc_data_direction = SCSI_DATA_READ; + SCpnt->use_sg = 0; + SCpnt->tag = 0; + SCpnt->host_scribble = (void *)fas216_rq_sns_done; + + /* + * Place this command into the high priority "request + * sense" slot. This will be the very next command + * executed, unless a target connects to us. + */ + if (info->reqSCpnt) + printk(KERN_WARNING "scsi%d.%c: loosing request command\n", + info->host->host_no, '0' + SCpnt->target); + info->reqSCpnt = SCpnt; +} + /* Function: void fas216_done(FAS216_Info *info, unsigned int result) - * Purpose : complete processing for command + * Purpose : complete processing for current command * Params : info - interface that completed * result - driver byte of result */ static void fas216_done(FAS216_Info *info, unsigned int result) { + void (*fn)(FAS216_Info *, Scsi_Cmnd *, unsigned int); Scsi_Cmnd *SCpnt; - fas216_checkmagic(info, "fas216_done"); + fas216_checkmagic(info); + + if (!info->SCpnt) + goto no_command; SCpnt = info->SCpnt; + info->SCpnt = NULL; + info->scsi.phase = PHASE_IDLE; + + if (!SCpnt->scsi_done) + goto no_done; if (info->scsi.aborting) { printk("scsi%d.%c: uncaught abort - returning DID_ABORT\n", @@ -1800,66 +1957,39 @@ info->scsi.aborting = 0; } - info->stats.fins += 1; - - if (SCpnt) { - info->scsi.phase = PHASE_IDLE; - info->SCpnt = NULL; - - SCpnt->result = result << 16 | info->scsi.SCp.Message << 8 | - info->scsi.SCp.Status; - - /* - * In theory, this should not happen, but just in case it does. - */ - if (info->scsi.SCp.ptr && - info->scsi.SCp.this_residual && - result == DID_OK) { - switch (SCpnt->cmnd[0]) { - case INQUIRY: - case START_STOP: - case READ_CAPACITY: - case TEST_UNIT_READY: - case MODE_SENSE: - case REQUEST_SENSE: - break; - - default: - switch (status_byte(SCpnt->result)) { - case CHECK_CONDITION: - case COMMAND_TERMINATED: - case BUSY: - case QUEUE_FULL: - case RESERVATION_CONFLICT: - break; - - default: - printk(KERN_ERR "scsi%d.H: incomplete data transfer " - "detected: res=%08X ptr=%p len=%X command=", - info->host->host_no, SCpnt->result, - info->scsi.SCp.ptr, info->scsi.SCp.this_residual); - print_command(SCpnt->cmnd); - } - } - } -#ifdef DEBUG_CONNECT - printk("scsi%d.%c: scsi command (%p) complete, result=%08X\n", - info->host->host_no, fas216_target(info), - SCpnt, SCpnt->result); -#endif + /* + * Sanity check the completion - if we have zero bytes left + * to transfer, we should not have a valid pointer. + */ + if (info->scsi.SCp.ptr && info->scsi.SCp.this_residual == 0) { + printk("scsi%d.%c: zero bytes left to transfer, but " + "buffer pointer still valid: ptr=%p len=%08x command=", + info->host->host_no, '0' + SCpnt->target, + info->scsi.SCp.ptr, info->scsi.SCp.this_residual); + info->scsi.SCp.ptr = NULL; + print_command(SCpnt->cmnd); + } - if (!SCpnt->scsi_done) - panic("scsi%d.H: null scsi_done function in " - "fas216_done", info->host->host_no); + /* + * Clear down this command as completed. If we need to request + * the sense information, fas216_kick will re-assert the busy + * status. + */ + clear_bit(SCpnt->target * 8 + SCpnt->lun, info->busyluns); - clear_bit(SCpnt->target * 8 + SCpnt->lun, info->busyluns); - - SCpnt->scsi_done(SCpnt); - } else - panic("scsi%d.H: null command in fas216_done", info->host->host_no); + fn = (void (*)(FAS216_Info *, Scsi_Cmnd *, unsigned int))SCpnt->host_scribble; + fn(info, SCpnt, result); if (info->scsi.irq != NO_IRQ) fas216_kick(info); + return; + +no_command: + panic("scsi%d.H: null command in fas216_done", + info->host->host_no); +no_done: + panic("scsi%d.H: null scsi_done function in fas216_done", + info->host->host_no); } /* Function: int fas216_queue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) @@ -1867,13 +1997,14 @@ * Params : SCpnt - Command to queue * done - done function to call once command is complete * Returns : 0 - success, else error + * Notes : io_request_lock is held, interrupts are disabled. */ int fas216_queue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata; - unsigned long flags; + int result; - fas216_checkmagic(info, "fas216_queue_command"); + fas216_checkmagic(info); #ifdef DEBUG_CONNECT printk("scsi%d.%c: received queuable command (%p) %02X\n", @@ -1882,7 +2013,7 @@ #endif SCpnt->scsi_done = done; - SCpnt->host_scribble = NULL; + SCpnt->host_scribble = (void *)fas216_std_done; SCpnt->result = 0; SCpnt->SCp.Message = 0; SCpnt->SCp.Status = 0; @@ -1896,10 +2027,16 @@ SCpnt->SCp.ptr = (char *) SCpnt->SCp.buffer->address; SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length; /* - * Calculate correct buffer length + * Calculate correct buffer length. Some commands + * come in with the wrong request_bufflen. */ for (buf = 0; buf <= SCpnt->SCp.buffers_residual; buf++) len += SCpnt->SCp.buffer[buf].length; + + if (SCpnt->request_bufflen != len) + printk(KERN_WARNING "scsi%d.%c: bad request buffer " + "length %d, should be %ld\n", info->host->host_no, + '0' + SCpnt->target, SCpnt->request_bufflen, len); SCpnt->request_bufflen = len; } else { SCpnt->SCp.buffer = NULL; @@ -1908,22 +2045,36 @@ SCpnt->SCp.this_residual = SCpnt->request_bufflen; } + /* + * If the upper SCSI layers pass a buffer, but zero length, + * we aren't interested in the buffer pointer. + */ + if (SCpnt->SCp.this_residual == 0 && SCpnt->SCp.ptr) { +#if 0 + printk(KERN_WARNING "scsi%d.%c: zero length buffer passed for " + "command ", info->host->host_no, '0' + SCpnt->target); + print_command(SCpnt->cmnd); +#endif + SCpnt->SCp.ptr = NULL; + } + info->stats.queues += 1; SCpnt->tag = 0; - /* add command into execute queue and let it complete under + /* + * Add command into execute queue and let it complete under * whatever scheme we're using. */ - if (!queue_add_cmd_ordered(&info->queues.issue, SCpnt)) { - SCpnt->result = DID_ERROR << 16; - done(SCpnt); - } - save_flags_cli(flags); - if (!info->SCpnt || info->scsi.disconnectable) + result = !queue_add_cmd_ordered(&info->queues.issue, SCpnt); + + /* + * If we successfully added the command, + * kick the interface to get it moving. + */ + if (result == 0 && (!info->SCpnt || info->scsi.disconnectable)) fas216_kick(info); - restore_flags(flags); - return 0; + return result; } /* Function: void fas216_internal_done(Scsi_Cmnd *SCpnt) @@ -1934,7 +2085,7 @@ { FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata; - fas216_checkmagic(info, "fas216_internal_done"); + fas216_checkmagic(info); info->internal_done = 1; } @@ -1943,13 +2094,20 @@ * Purpose : queue a command for adapter to process. * Params : SCpnt - Command to queue * Returns : scsi result code + * Notes : io_request_lock is held, interrupts are disabled. */ int fas216_command(Scsi_Cmnd *SCpnt) { FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata; - unsigned long flags; - fas216_checkmagic(info, "fas216_command"); + fas216_checkmagic(info); + + /* + * We should only be using this if we don't have an interrupt. + * Provide some "incentive" to use the queueing code. + */ + if (info->scsi.irq != NO_IRQ) + BUG(); info->internal_done = 0; fas216_queue_command(SCpnt, fas216_internal_done); @@ -1960,114 +2118,52 @@ * However, we must re-enable interrupts, or else we'll be * waiting forever. */ - save_flags(flags); - sti(); + spin_unlock_irq(&io_request_lock); while (!info->internal_done) { /* - * If we don't have an IRQ, then we must - * poll the card for it's interrupt, and - * use that to call this driver's interrupt - * routine. That way, we keep the command - * progressing. - */ - if (info->scsi.irq == NO_IRQ) { - sti(); - while (!(inb(REG_STAT(info)) & STAT_INT)); - cli(); + * If we don't have an IRQ, then we must poll the card for + * it's interrupt, and use that to call this driver's + * interrupt routine. That way, we keep the command + * progressing. Maybe we can add some inteligence here + * and go to sleep if we know that the device is going + * to be some time (eg, disconnected). + */ + if (inb(REG_STAT(info)) & STAT_INT) { + spin_lock_irq(&io_request_lock); fas216_intr(info->host); + spin_unlock_irq(&io_request_lock); } } - restore_flags(flags); + spin_lock_irq(&io_request_lock); return SCpnt->result; } -/* Prototype: void fas216_reportstatus(Scsi_Cmnd **SCpntp1, - * Scsi_Cmnd **SCpntp2, int result, int no_report) - * Purpose : pass a result to *SCpntp1, and check if *SCpntp1 = *SCpntp2 - * Params : SCpntp1 - pointer to command to return - * SCpntp2 - pointer to command to check - * result - result to pass back to mid-level done function - * Returns : *SCpntp2 = NULL if *SCpntp1 is the same command - * structure as *SCpntp2. - */ -static void fas216_reportstatus(Scsi_Cmnd **SCpntp1, Scsi_Cmnd **SCpntp2, - int result, int no_report) -{ - Scsi_Cmnd *SCpnt = *SCpntp1; - - if (SCpnt) { - *SCpntp1 = NULL; - - SCpnt->result = result; - if (!no_report || SCpnt != *SCpntp2) - SCpnt->scsi_done(SCpnt); - } - - if (SCpnt == *SCpntp2) - *SCpntp2 = NULL; -} - -/* Function: int fas216_eh_abort(Scsi_Cmnd *SCpnt) - * Purpose : abort this command - * Params : SCpnt - command to abort - * Returns : FAILED if unable to abort - */ -int fas216_eh_abort(Scsi_Cmnd *SCpnt) -{ - return FAILED; -} - -/* Function: int fas216_eh_device_reset(Scsi_Cmnd *SCpnt) - * Purpose : Reset the device associated with this command - * Params : SCpnt - command specifing device to reset - * Returns : FAILED if unable to reset - */ -int fas216_eh_device_reset(Scsi_Cmnd *SCpnt) -{ - return FAILED; -} - -/* Function: int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt) - * Purpose : Reset the complete bus associated with this command - * Params : SCpnt - command specifing bus to reset - * Returns : FAILED if unable to reset - */ -int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt) -{ - return FAILED; -} - -/* Function: int fas216_eh_host_reset(Scsi_Cmnd *SCpnt) - * Purpose : Reset the host associated with this command - * Params : SCpnt - command specifing host to reset - * Returns : FAILED if unable to reset - */ -int fas216_eh_host_reset(Scsi_Cmnd *SCpnt) -{ - return FAILED; -} - -enum res_abort { res_not_running, res_success, res_success_clear, res_snooze }; +enum res_abort { + res_failed, /* unable to abort */ + res_success, /* command on issue queue */ + res_success_clear, /* command marked tgt/lun busy */ + res_hw_abort /* command on disconnected dev */ +}; /* * Prototype: enum res_abort fas216_do_abort(FAS216_Info *info, Scsi_Cmnd *SCpnt) - * Purpose : abort a command on this host + * Purpose : decide how to abort a command * Params : SCpnt - command to abort * Returns : abort status */ static enum res_abort fas216_do_abort(FAS216_Info *info, Scsi_Cmnd *SCpnt) { - enum res_abort res = res_not_running; + enum res_abort res = res_failed; if (queue_removecmd(&info->queues.issue, SCpnt)) { /* * The command was on the issue queue, and has not been * issued yet. We can remove the command from the queue, - * and acknowledge the abort. Neither the devices nor the + * and acknowledge the abort. Neither the device nor the * interface know about the command. */ printk("on issue queue "); @@ -2075,54 +2171,32 @@ res = res_success; } else if (queue_removecmd(&info->queues.disconnected, SCpnt)) { /* - * The command was on the disconnected queue. Simply - * acknowledge the abort condition, and when the target - * reconnects, we will give it an ABORT message. The - * target should then disconnect, and we will clear - * the busylun bit. + * The command was on the disconnected queue. We must + * reconnect with the device if possible, and send it + * an abort message. */ printk("on disconnected queue "); - res = res_success; + res = res_hw_abort; } else if (info->SCpnt == SCpnt) { - unsigned long flags; - printk("executing "); - save_flags(flags); - cli(); switch (info->scsi.phase) { /* * If the interface is idle, and the command is 'disconnectable', - * then it is the same as on the disconnected queue. We simply - * remove all traces of the command. When the target reconnects, - * we will give it an ABORT message since the command could not - * be found. When the target finally disconnects, we will clear - * the busylun bit. + * then it is the same as on the disconnected queue. */ case PHASE_IDLE: if (info->scsi.disconnectable) { info->scsi.disconnectable = 0; info->SCpnt = NULL; - res = res_success; + res = res_hw_abort; } break; - /* - * If the command has connected and done nothing futher, - * simply force a disconnect. We also need to clear the - * busylun bit. - */ - case PHASE_SELECTION: -// info->SCpnt = NULL; -// res = res_success_clear; -// break; - default: - res = res_snooze; break; } - restore_flags(flags); } else if (info->origSCpnt == SCpnt) { /* * The command will be executed next, but a command @@ -2139,17 +2213,18 @@ return res; } -/* Function: int fas216_abort(Scsi_Cmnd *SCpnt) - * Purpose : abort a command if something horrible happens. - * Params : SCpnt - Command that is believed to be causing a problem. - * Returns : one of SCSI_ABORT_ macros. +/* Function: int fas216_eh_abort(Scsi_Cmnd *SCpnt) + * Purpose : abort this command + * Params : SCpnt - command to abort + * Returns : FAILED if unable to abort + * Notes : io_request_lock is taken, and irqs are disabled */ -int fas216_abort(Scsi_Cmnd *SCpnt) +int fas216_eh_abort(Scsi_Cmnd *SCpnt) { FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata; - int result = SCSI_ABORT_SNOOZE; + int result = FAILED; - fas216_checkmagic(info, "fas216_abort"); + fas216_checkmagic(info); info->stats.aborts += 1; @@ -2176,29 +2251,23 @@ */ case res_success: printk("success\n"); - SCpnt->result = DID_ABORT << 16; - SCpnt->scsi_done(SCpnt); - result = SCSI_ABORT_SUCCESS; + result = SUCCESS; break; /* - * We did find the command, but unfortunately we couldn't - * unhook it from ourselves. Wait some more, and if it - * still doesn't complete, reset the interface. + * We need to reconnect to the target and send it an + * ABORT or ABORT_TAG message. We can only do this + * if the bus is free. */ - case res_snooze: - printk("snooze\n"); - result = SCSI_ABORT_SNOOZE; - break; + case res_hw_abort: + /* - * The command could not be found (either because it completed, - * or it got dropped. + * We are unable to abort the command for some reason. */ default: - case res_not_running: - result = SCSI_ABORT_SNOOZE; - printk("not running\n"); + case res_failed: + printk("failed\n"); break; } @@ -2214,7 +2283,7 @@ neg_t sync_state, wide_state; int i; - fas216_checkmagic(info, "fas216_reset_state"); + fas216_checkmagic(info); /* * Clear out all stale info in our state structure @@ -2257,6 +2326,80 @@ info->device[i].sof = 0; info->device[i].wide_xfer = 0; } + + /* + * Drain all commands on disconnected queue + */ + while (queue_remove(&info->queues.disconnected) != NULL); + + /* + * Remove executing commands. + */ + info->SCpnt = NULL; + info->reqSCpnt = NULL; + info->origSCpnt = NULL; +} + +/* Function: int fas216_eh_device_reset(Scsi_Cmnd *SCpnt) + * Purpose : Reset the device associated with this command + * Params : SCpnt - command specifing device to reset + * Returns : FAILED if unable to reset + */ +int fas216_eh_device_reset(Scsi_Cmnd *SCpnt) +{ + FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata; + + printk("scsi%d.%c: "__FUNCTION__": called\n", + info->host->host_no, '0' + SCpnt->target); + return FAILED; +} + +/* Function: int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt) + * Purpose : Reset the bus associated with the command + * Params : SCpnt - command specifing bus to reset + * Returns : FAILED if unable to reset + * Notes : io_request_lock is taken, and irqs are disabled + */ +int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt) +{ + FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata; + int result = FAILED; + + fas216_checkmagic(info); + + info->stats.bus_resets += 1; + + printk("scsi%d.%c: "__FUNCTION__": resetting bus\n", + info->host->host_no, '0' + SCpnt->target); + + /* + * Attempt to stop all activity on this interface. + */ + outb(info->scsi.cfg[2], REG_CNTL3(info)); + fas216_stoptransfer(info); + + /* + * Clear any pending interrupts + */ + while (inb(REG_STAT(info)) & STAT_INT) + inb(REG_INST(info)); + + /* + * Reset the SCSI bus + */ + outb(CMD_RESETSCSI, REG_CMD(info)); + udelay(5); + + /* + * Clear reset interrupt + */ + if (inb(REG_STAT(info)) & STAT_INT && + inb(REG_INST(info)) & INST_BUSRESET) + result = SUCCESS; + + fas216_reset_state(info); + + return result; } /* Function: void fas216_init_chip(FAS216_Info *info) @@ -2265,8 +2408,6 @@ */ static void fas216_init_chip(FAS216_Info *info) { - fas216_checkmagic(info, "fas216_init_chip"); - outb(fas216_clockrate(info->ifcfg.clockrate), REG_CLKF(info)); outb(info->scsi.cfg[0], REG_CNTL1(info)); outb(info->scsi.cfg[1], REG_CNTL2(info)); @@ -2277,100 +2418,144 @@ outb(info->scsi.cfg[0], REG_CNTL1(info)); } -/* Function: int fas216_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags) - * Purpose : resets the adapter if something horrible happens. - * Params : SCpnt - Command that is believed to be causing a problem. - * reset_flags - flags indicating reset type that is believed - * to be required. - * Returns : one of SCSI_RESET_ macros, or'd with the SCSI_RESET_*_RESET - * macros. +/* Function: int fas216_eh_host_reset(Scsi_Cmnd *SCpnt) + * Purpose : Reset the host associated with this command + * Params : SCpnt - command specifing host to reset + * Returns : FAILED if unable to reset + * Notes : io_request_lock is taken, and irqs are disabled */ -int fas216_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags) +int fas216_eh_host_reset(Scsi_Cmnd *SCpnt) { FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata; - Scsi_Cmnd *SCptr; - int result = 0; - int synchronous = reset_flags & SCSI_RESET_SYNCHRONOUS; - fas216_checkmagic(info, "fas216_reset"); + fas216_checkmagic(info); + + printk("scsi%d.%c: "__FUNCTION__": resetting host\n", + info->host->host_no, '0' + SCpnt->target); /* - * Validate that command is actually on one of our queues if we're doing - * an asynchronous reset + * Reset the SCSI chip. */ - if (reset_flags & SCSI_RESET_ASYNCHRONOUS && - SCpnt && - info->SCpnt != SCpnt && - info->origSCpnt != SCpnt && - !queue_cmdonqueue(&info->queues.disconnected, SCpnt) && - !queue_cmdonqueue(&info->queues.issue, SCpnt)) { - printk("scsi%d: fas216_reset: asynchronous reset for unknown command\n", - info->host->host_no); - return SCSI_RESET_NOT_RUNNING; - } + outb(CMD_RESETCHIP, REG_CMD(info)); - info->stats.resets += 1; + /* + * Ugly ugly ugly! + * We need to release the io_request_lock and enable + * IRQs if we sleep, but we must relock and disable + * IRQs after the sleep. + */ + spin_unlock_irq(&io_request_lock); + scsi_sleep(5); + spin_lock_irq(&io_request_lock); - print_debug_list(); - printk(KERN_WARNING "scsi%d: reset ", info->host->host_no); - if (SCpnt) - printk("for target %d ", SCpnt->target); + /* + * Release the SCSI reset. + */ + outb(CMD_NOP, REG_CMD(info)); - printk("\n"); + fas216_init_chip(info); - outb(info->scsi.cfg[3], REG_CNTL3(info)); + return SUCCESS; +} - fas216_stoptransfer(info); +#define TYPE_UNKNOWN 0 +#define TYPE_NCR53C90 1 +#define TYPE_NCR53C90A 2 +#define TYPE_NCR53C9x 3 +#define TYPE_Am53CF94 4 +#define TYPE_EmFAS216 5 +#define TYPE_QLFAS216 6 + +static char *chip_types[] = { + "unknown", + "NS NCR53C90", + "NS NCR53C90A", + "NS NCR53C9x", + "AMD Am53CF94", + "Emulex FAS216", + "QLogic FAS216" +}; - switch (reset_flags & (SCSI_RESET_SUGGEST_BUS_RESET | SCSI_RESET_SUGGEST_HOST_RESET)) { - case SCSI_RESET_SUGGEST_BUS_RESET: - outb(CMD_RESETSCSI, REG_CMD(info)); - outb(CMD_NOP, REG_CMD(info)); - result |= SCSI_RESET_BUS_RESET; - break; +static int fas216_detect_type(FAS216_Info *info) +{ + int family, rev; - case SCSI_RESET_SUGGEST_HOST_RESET: - outb(CMD_RESETCHIP, REG_CMD(info)); - outb(CMD_NOP, REG_CMD(info)); - result |= SCSI_RESET_HOST_RESET; - break; + /* + * Reset the chip. + */ + outb(CMD_RESETCHIP, REG_CMD(info)); + udelay(50); + outb(CMD_NOP, REG_CMD(info)); - default: - outb(CMD_RESETCHIP, REG_CMD(info)); - outb(CMD_NOP, REG_CMD(info)); - outb(CMD_RESETSCSI, REG_CMD(info)); - result |= SCSI_RESET_HOST_RESET | SCSI_RESET_BUS_RESET; - break; - } + /* + * Check to see if control reg 2 is present. + */ + outb(0, REG_CNTL3(info)); + outb(CNTL2_S2FE, REG_CNTL2(info)); - udelay(300); - fas216_reset_state(info); - fas216_init_chip(info); + /* + * If we are unable to read back control reg 2 + * correctly, it is not present, and we have a + * NCR53C90. + */ + if ((inb(REG_CNTL2(info)) & (~0xe0)) != CNTL2_S2FE) + return TYPE_NCR53C90; /* - * Signal all commands in progress have been reset + * Now, check control register 3 */ - fas216_reportstatus(&info->SCpnt, &SCpnt, DID_RESET << 16, synchronous); + outb(0, REG_CNTL2(info)); + outb(0, REG_CNTL3(info)); + outb(5, REG_CNTL3(info)); - while ((SCptr = queue_remove(&info->queues.disconnected)) != NULL) - fas216_reportstatus(&SCptr, &SCpnt, DID_RESET << 16, synchronous); + /* + * If we are unable to read the register back + * correctly, we have a NCR53C90A + */ + if (inb(REG_CNTL3(info)) != 5) + return TYPE_NCR53C90A; - if (SCpnt) { - /* - * Command not found on disconnected queue, nor currently - * executing command - check pending commands - */ - if (info->origSCpnt == SCpnt) - info->origSCpnt = NULL; + /* + * Now read the ID from the chip. + */ + outb(0, REG_CNTL3(info)); - queue_removecmd(&info->queues.issue, SCpnt); + outb(CNTL3_ADIDCHK, REG_CNTL3(info)); + outb(0, REG_CNTL3(info)); - SCpnt->result = DID_RESET << 16; - if (!synchronous) - SCpnt->scsi_done(SCpnt); - } + outb(CMD_RESETCHIP, REG_CMD(info)); + udelay(5); + outb(CMD_WITHDMA | CMD_NOP, REG_CMD(info)); + + outb(CNTL2_ENF, REG_CNTL2(info)); + outb(CMD_RESETCHIP, REG_CMD(info)); + udelay(5); + outb(CMD_NOP, REG_CMD(info)); + + rev = inb(REG1_ID(info)); + family = rev >> 3; + rev &= 7; + + switch (family) { + case 0x01: + if (rev == 4) + return TYPE_Am53CF94; + break; + + case 0x02: + switch (rev) { + case 2: + return TYPE_EmFAS216; + case 3: + return TYPE_QLFAS216; + } + break; - return result | SCSI_RESET_SUCCESS; + default: + break; + } + printk("family %x rev %x\n", family, rev); + return TYPE_NCR53C9x; } /* Function: int fas216_init(struct Scsi_Host *instance) @@ -2381,19 +2566,14 @@ int fas216_init(struct Scsi_Host *instance) { FAS216_Info *info = (FAS216_Info *)instance->hostdata; - unsigned long flags; - int target_jiffies; + int type; info->magic_start = MAGIC; - info->magic_end = MAGIC; - - info->host = instance; + info->magic_end = MAGIC; + info->host = instance; info->scsi.cfg[0] = instance->this_id; info->scsi.cfg[1] = CNTL2_ENF | CNTL2_S2FE; info->scsi.cfg[2] = info->ifcfg.cntl3 | CNTL3_ADIDCHK | CNTL3_G2CB; - info->scsi.type = "unknown"; - info->SCpnt = NULL; - fas216_reset_state(info); memset(&info->stats, 0, sizeof(info->stats)); @@ -2407,64 +2587,36 @@ return 1; } - outb(CMD_RESETCHIP, REG_CMD(info)); - - outb(0, REG_CNTL3(info)); - outb(CNTL2_S2FE, REG_CNTL2(info)); - - if ((inb(REG_CNTL2(info)) & (~0xe0)) != CNTL2_S2FE) { - info->scsi.type = "NCR53C90"; - } else { - outb(0, REG_CNTL2(info)); - outb(0, REG_CNTL3(info)); - outb(5, REG_CNTL3(info)); - if (inb(REG_CNTL3(info)) != 5) { - info->scsi.type = "NCR53C90A"; - } else { - outb(0, REG_CNTL3(info)); - info->scsi.type = "NCR53C9x"; - } - } - - - outb(CNTL3_ADIDCHK, REG_CNTL3(info)); - outb(0, REG_CNTL3(info)); - - outb(CMD_RESETCHIP, REG_CMD(info)); - outb(CMD_WITHDMA | CMD_NOP, REG_CMD(info)); - outb(CNTL2_ENF, REG_CNTL2(info)); - outb(CMD_RESETCHIP, REG_CMD(info)); - switch (inb(REG1_ID(info))) { - case 12: - info->scsi.type = "Am53CF94"; - break; - default: - break; - } + fas216_reset_state(info); + type = fas216_detect_type(info); + info->scsi.type = chip_types[type]; udelay(300); - /* now for the real initialisation */ + + /* + * Initialise the chip correctly. + */ fas216_init_chip(info); + /* + * Reset the SCSI bus. We don't want to see + * the resulting reset interrupt, so mask it + * out. + */ outb(info->scsi.cfg[0] | CNTL1_DISR, REG_CNTL1(info)); outb(CMD_RESETSCSI, REG_CMD(info)); - /* scsi standard says 250ms */ - target_jiffies = jiffies + (25 * HZ) / 100; - save_flags(flags); - sti(); - - while (time_before(jiffies, target_jiffies)) barrier(); - - restore_flags(flags); + /* + * scsi standard says wait 250ms + */ + spin_unlock_irq(&io_request_lock); + scsi_sleep(5); + spin_lock_irq(&io_request_lock); outb(info->scsi.cfg[0], REG_CNTL1(info)); inb(REG_INST(info)); - /* now for the real initialisation */ - fas216_init_chip(info); - - fas216_checkmagic(info, "fas216_init"); + fas216_checkmagic(info); return 0; } @@ -2479,7 +2631,7 @@ { FAS216_Info *info = (FAS216_Info *)instance->hostdata; - fas216_checkmagic(info, "fas216_release"); + fas216_checkmagic(info); outb(CMD_RESETCHIP, REG_CMD(info)); queue_free(&info->queues.disconnected); @@ -2488,19 +2640,67 @@ return 0; } +/* + * Function: int fas216_info(FAS216_Info *info, char *buffer) + * Purpose : generate a string containing information about this + * host. + * Params : info - FAS216 host information + * buffer - string buffer to build string + * Returns : size of built string + */ +int fas216_info(FAS216_Info *info, char *buffer) +{ + char *p = buffer; + + p += sprintf(p, "(%s) at port 0x%08lX ", + info->scsi.type, info->host->io_port); + + if (info->host->irq != NO_IRQ) + p += sprintf(p, "irq %d ", info->host->irq); + else + p += sprintf(p, "no irq "); + + if (info->host->dma_channel != NO_DMA) + p += sprintf(p, "dma %d ", info->host->dma_channel); + else + p += sprintf(p, "no dma "); + + return p - buffer; +} + +int fas216_print_host(FAS216_Info *info, char *buffer) +{ + + return sprintf(buffer, + "\n" + "Chip : %s\n" + " Address: 0x%08lX\n" + " IRQ : %d\n" + " DMA : %d\n", + info->scsi.type, info->host->io_port, + info->host->irq, info->host->dma_channel); +} + int fas216_print_stats(FAS216_Info *info, char *buffer) { return sprintf(buffer, - "Queued commands: %-10u Issued commands: %-10u\n" - "Done commands : %-10u Reads : %-10u\n" - "Writes : %-10u Others : %-10u\n" - "Disconnects : %-10u Aborts : %-10u\n" - "Resets : %-10u\n", + "\n" + "Command Statistics:\n" + " Queued : %u\n" + " Issued : %u\n" + " Completed : %u\n" + " Reads : %u\n" + " Writes : %u\n" + " Others : %u\n" + " Disconnects: %u\n" + " Aborts : %u\n" + " Bus resets : %u\n" + " Host resets: %u\n", info->stats.queues, info->stats.removes, info->stats.fins, info->stats.reads, info->stats.writes, info->stats.miscs, info->stats.disconnects, info->stats.aborts, - info->stats.resets); + info->stats.bus_resets, info->stats.host_resets); } int fas216_print_device(FAS216_Info *info, Scsi_Device *scd, char *buffer) @@ -2531,9 +2731,8 @@ return p - buffer; } +EXPORT_SYMBOL(fas216_info); EXPORT_SYMBOL(fas216_init); -EXPORT_SYMBOL(fas216_abort); -EXPORT_SYMBOL(fas216_reset); EXPORT_SYMBOL(fas216_queue_command); EXPORT_SYMBOL(fas216_command); EXPORT_SYMBOL(fas216_intr); @@ -2542,6 +2741,7 @@ EXPORT_SYMBOL(fas216_eh_device_reset); EXPORT_SYMBOL(fas216_eh_bus_reset); EXPORT_SYMBOL(fas216_eh_host_reset); +EXPORT_SYMBOL(fas216_print_host); EXPORT_SYMBOL(fas216_print_stats); EXPORT_SYMBOL(fas216_print_device); diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/acorn/scsi/fas216.h linux/drivers/acorn/scsi/fas216.h --- v2.3.99-pre3/linux/drivers/acorn/scsi/fas216.h Mon Aug 2 10:19:52 1999 +++ linux/drivers/acorn/scsi/fas216.h Sun Apr 2 17:28:22 2000 @@ -1,11 +1,7 @@ /* * FAS216 generic driver * - * Copyright (C) 1997-1998 Russell King - * - * NOTE! This file should be viewed using a console with - * >100 character width (since it uses 8-space tabs) - * (it used to fit in 80-columns with 4 space) + * Copyright (C) 1997-2000 Russell King */ #ifndef FAS216_H #define FAS216_H @@ -215,6 +211,7 @@ struct Scsi_Host *host; /* host */ Scsi_Cmnd *SCpnt; /* currently processing command */ Scsi_Cmnd *origSCpnt; /* original connecting command */ + Scsi_Cmnd *reqSCpnt; /* request sense command */ /* driver information */ struct { @@ -254,7 +251,8 @@ unsigned int miscs; unsigned int disconnects; unsigned int aborts; - unsigned int resets; + unsigned int bus_resets; + unsigned int host_resets; } stats; /* configuration information */ @@ -350,6 +348,8 @@ */ extern int fas216_release (struct Scsi_Host *instance); +extern int fas216_info(FAS216_Info *info, char *buffer); +extern int fas216_print_host(FAS216_Info *info, char *buffer); extern int fas216_print_stats(FAS216_Info *info, char *buffer); extern int fas216_print_device(FAS216_Info *info, Scsi_Device *scd, char *buffer); diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/acorn/scsi/msgqueue.h linux/drivers/acorn/scsi/msgqueue.h --- v2.3.99-pre3/linux/drivers/acorn/scsi/msgqueue.h Thu Jun 17 01:11:35 1999 +++ linux/drivers/acorn/scsi/msgqueue.h Sun Apr 2 17:28:22 2000 @@ -1,7 +1,7 @@ /* * msgqueue.h: message queue handling * - * (c) 1997 Russell King + * Copyright (C) 1997 Russell King */ #ifndef MSGQUEUE_H #define MSGQUEUE_H diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/acorn/scsi/powertec.c linux/drivers/acorn/scsi/powertec.c --- v2.3.99-pre3/linux/drivers/acorn/scsi/powertec.c Tue Dec 14 01:27:23 1999 +++ linux/drivers/acorn/scsi/powertec.c Sun Apr 2 17:28:22 2000 @@ -1,7 +1,7 @@ /* * linux/arch/arm/drivers/scsi/powertec.c * - * Copyright (C) 1997-1998 Russell King + * Copyright (C) 1997-2000 Russell King * * This driver is based on experimentation. Hence, it may have made * assumptions about the particular card that I have available, and @@ -13,6 +13,7 @@ * 15-04-1998 RMK Only do PIO if FAS216 will allow it. * 02-05-1998 RMK Moved DMA sg list into per-interface structure. * 27-06-1998 RMK Changed asm/delay.h to linux/delay.h + * 02-04-2000 RMK Updated for new error handling code. */ #include @@ -67,7 +68,7 @@ */ #define VER_MAJOR 0 #define VER_MINOR 0 -#define VER_PATCH 2 +#define VER_PATCH 5 MODULE_AUTHOR("Russell King"); MODULE_DESCRIPTION("Powertec SCSI driver"); @@ -345,25 +346,11 @@ static char string[100], *p; p = string; - p += sprintf(string, "%s at port %lX ", - host->hostt->name, host->io_port); - - if (host->irq != NO_IRQ) - p += sprintf(p, "irq %d ", host->irq); - else - p += sprintf(p, "NO IRQ "); - - if (host->dma_channel != NO_DMA) - p += sprintf(p, "dma %d ", host->dma_channel); - else - p += sprintf(p, "NO DMA "); - - p += sprintf(p, "v%d.%d.%d scsi %s", + p += sprintf(p, "%s ", host->hostt->name); + p += fas216_info(&info->info, p); + p += sprintf(p, "v%d.%d.%d terminators o%s", VER_MAJOR, VER_MINOR, VER_PATCH, - info->info.scsi.type); - - p += sprintf(p, " terminators %s", - info->control.terms ? "on" : "off"); + info->control.terms ? "n" : "ff"); return string; } @@ -403,13 +390,13 @@ * int length, int host_no, int inout) * Purpose : Return information about the driver to a user process accessing * the /proc filesystem. - * Params : buffer - a buffer to write information to - * start - a pointer into this buffer set by this routine to the start - * of the required information. - * offset - offset into information that we have read upto. - * length - length of buffer + * Params : buffer - a buffer to write information to + * start - a pointer into this buffer set by this routine to the start + * of the required information. + * offset - offset into information that we have read upto. + * length - length of buffer * host_no - host number to return information for - * inout - 0 for reading, 1 for writing. + * inout - 0 for reading, 1 for writing. * Returns : length of data written to buffer. */ int powertecscsi_proc_info(char *buffer, char **start, off_t offset, @@ -437,16 +424,14 @@ pos = sprintf(buffer, "PowerTec SCSI driver version %d.%d.%d\n", VER_MAJOR, VER_MINOR, VER_PATCH); - pos += sprintf(buffer + pos, - "Address: %08lX IRQ : %d DMA : %d\n" - "FAS : %-10s TERM: %-3s\n\n" - "Statistics:\n", - host->io_port, host->irq, host->dma_channel, - info->info.scsi.type, info->control.terms ? "on" : "off"); + + pos += fas216_print_host(&info->info, buffer + pos); + pos += sprintf(buffer + pos, "Term : o%s\n", + info->control.terms ? "n" : "ff"); pos += fas216_print_stats(&info->info, buffer + pos); - pos += sprintf (buffer+pos, "\nAttached devices:\n"); + pos += sprintf(buffer+pos, "\nAttached devices:\n"); for (scd = host->host_queue; scd; scd = scd->next) { pos += fas216_print_device(&info->info, scd, buffer + pos); diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/acorn/scsi/powertec.h linux/drivers/acorn/scsi/powertec.h --- v2.3.99-pre3/linux/drivers/acorn/scsi/powertec.h Fri May 8 00:42:39 1998 +++ linux/drivers/acorn/scsi/powertec.h Sun Apr 2 17:28:22 2000 @@ -1,7 +1,7 @@ /* * PowerTec SCSI driver * - * Copyright (C) 1997-1998 Russell King + * Copyright (C) 1997-2000 Russell King */ #ifndef POWERTECSCSI_H #define POWERTECSCSI_H @@ -38,28 +38,25 @@ #include "fas216.h" -#define POWERTECSCSI { \ -proc_info: powertecscsi_proc_info, \ -name: "PowerTec SCSI", \ -detect: powertecscsi_detect, /* detect */ \ -release: powertecscsi_release, /* release */ \ -info: powertecscsi_info, /* info */ \ -command: fas216_command, /* command */ \ -queuecommand: fas216_queue_command, /* queuecommand */ \ -abort: fas216_abort, /* abort */ \ -reset: fas216_reset, /* reset */ \ -bios_param: scsicam_bios_param, /* biosparam */ \ -can_queue: CAN_QUEUE, /* can queue */ \ -this_id: SCSI_ID, /* scsi host id */ \ -sg_tablesize: SG_ALL, /* sg_tablesize */ \ -cmd_per_lun: CMD_PER_LUN, /* cmd per lun */ \ -use_clustering: ENABLE_CLUSTERING, \ -eh_strategy_handler: NULL, \ -eh_host_reset_handler: fas216_eh_host_reset, \ -eh_bus_reset_handler: fas216_eh_bus_reset, \ -eh_device_reset_handler: fas216_eh_device_reset, \ -eh_abort_handler: fas216_eh_abort, \ -use_new_eh_code: 0 \ +#define POWERTECSCSI { \ +proc_info: powertecscsi_proc_info, \ +name: "PowerTec SCSI", \ +detect: powertecscsi_detect, \ +release: powertecscsi_release, \ +info: powertecscsi_info, \ +bios_param: scsicam_bios_param, \ +can_queue: CAN_QUEUE, \ +this_id: SCSI_ID, \ +sg_tablesize: SG_ALL, \ +cmd_per_lun: CMD_PER_LUN, \ +use_clustering: ENABLE_CLUSTERING, \ +command: fas216_command, \ +queuecommand: fas216_queue_command, \ +eh_host_reset_handler: fas216_eh_host_reset, \ +eh_bus_reset_handler: fas216_eh_bus_reset, \ +eh_device_reset_handler: fas216_eh_device_reset, \ +eh_abort_handler: fas216_eh_abort, \ +use_new_eh_code: 1 \ } #ifndef HOSTS_C diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/acorn/scsi/queue.h linux/drivers/acorn/scsi/queue.h --- v2.3.99-pre3/linux/drivers/acorn/scsi/queue.h Thu Sep 25 14:35:09 1997 +++ linux/drivers/acorn/scsi/queue.h Sun Apr 2 17:28:22 2000 @@ -1,7 +1,7 @@ /* * queue.h: queue handling * - * (c) 1997 Russell King + * Copyright (C) 1997 Russell King */ #ifndef QUEUE_H #define QUEUE_H diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/atm/fore200e.c linux/drivers/atm/fore200e.c --- v2.3.99-pre3/linux/drivers/atm/fore200e.c Mon Mar 27 08:08:23 2000 +++ linux/drivers/atm/fore200e.c Mon Mar 27 09:44:58 2000 @@ -45,10 +45,7 @@ #include #include #include - -#ifdef CONFIG_ATM_FORE200E_PCA #include -#endif #ifdef CONFIG_ATM_FORE200E_SBA #include diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/block/Config.in linux/drivers/block/Config.in --- v2.3.99-pre3/linux/drivers/block/Config.in Sun Mar 19 18:35:30 2000 +++ linux/drivers/block/Config.in Mon Apr 10 23:04:49 2000 @@ -12,9 +12,7 @@ tristate 'Atari floppy support' CONFIG_ATARI_FLOPPY fi if [ "$CONFIG_MAC" = "y" ]; then - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - bool 'Macintosh IIfx/Quadra 900/Quadra 950 floppy support (EXPERIMENTAL)' CONFIG_BLK_DEV_SWIM_IOP - fi + dep_bool 'Macintosh IIfx/Quadra 900/Quadra 950 floppy support (EXPERIMENTAL)' CONFIG_BLK_DEV_SWIM_IOP $CONFIG_EXPERIMENTAL fi if [ "$CONFIG_MCA" = "y" ]; then tristate 'PS/2 ESDI hard disk support' CONFIG_BLK_DEV_PS2 @@ -30,36 +28,28 @@ tristate ' Atari SLM laser printer support' CONFIG_ATARI_SLM fi fi -tristate 'XT hard disk support' CONFIG_BLK_DEV_XD +dep_tristate 'XT hard disk support' CONFIG_BLK_DEV_XD $CONFIG_ISA dep_tristate 'Parallel port IDE device support' CONFIG_PARIDE $CONFIG_PARPORT if [ "$CONFIG_PARIDE" = "y" -o "$CONFIG_PARIDE" = "m" ]; then source drivers/block/paride/Config.in fi - -if [ "$CONFIG_PCI" = "y" ]; then - tristate 'Compaq SMART2 support' CONFIG_BLK_CPQ_DA - tristate 'Mylex DAC960/DAC1100 PCI RAID Controller support' CONFIG_BLK_DEV_DAC960 -fi +dep_tristate 'Compaq SMART2 support' CONFIG_BLK_CPQ_DA $CONFIG_PCI +dep_tristate 'Mylex DAC960/DAC1100 PCI RAID Controller support' CONFIG_BLK_DEV_DAC960 $CONFIG_PCI comment 'Additional Block Devices' tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP -if [ "$CONFIG_NET" = "y" ]; then - tristate 'Network block device support' CONFIG_BLK_DEV_NBD -fi +dep_tristate 'Network block device support' CONFIG_BLK_DEV_NBD $CONFIG_NET + bool 'Multiple devices driver support' CONFIG_BLK_DEV_MD -if [ "$CONFIG_BLK_DEV_MD" = "y" ]; then - tristate ' Linear (append) mode' CONFIG_MD_LINEAR - tristate ' RAID-0 (striping) mode' CONFIG_MD_STRIPED -# tristate ' RAID-1 (mirroring) mode' CONFIG_MD_MIRRORING -# tristate ' RAID-4/RAID-5 mode' CONFIG_MD_RAID5 -fi -#if [ "$CONFIG_MD_LINEAR" = "y" -o "$CONFIG_MD_STRIPED" = "y" ]; then -# bool ' Boot support (linear, striped)' CONFIG_MD_BOOT -#fi -tristate 'RAM disk support' CONFIG_BLK_DEV_RAM -if [ "$CONFIG_BLK_DEV_RAM" = "y" ]; then - bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD +dep_tristate ' Linear (append) mode' CONFIG_MD_LINEAR $CONFIG_BLK_DEV_MD +dep_tristate ' RAID-0 (striping) mode' CONFIG_MD_STRIPED $CONFIG_BLK_DEV_MD +#dep_tristate ' RAID-1 (mirroring) mode' CONFIG_MD_MIRRORING $CONFIG_BLK_DEV_MD +#dep_tristate ' RAID-4/RAID-5 mode' CONFIG_MD_RAID5 $CONFIG_BLK_DEV_MD +if [ "$CONFIG_MD_LINEAR" = "y" -o "$CONFIG_MD_STRIPED" = "y" ]; then + bool ' Boot support (linear, striped)' CONFIG_MD_BOOT fi +tristate 'RAM disk support' CONFIG_BLK_DEV_RAM +dep_bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD $CONFIG_BLK_DEV_RAM endmenu diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c --- v2.3.99-pre3/linux/drivers/block/ll_rw_blk.c Sun Mar 19 18:35:30 2000 +++ linux/drivers/block/ll_rw_blk.c Tue Apr 4 19:25:14 2000 @@ -481,7 +481,7 @@ elevator_merge_requests(&q->elevator, req, next); req->bhtail->b_reqnext = next->bh; req->bhtail = next->bhtail; - req->nr_sectors += next->nr_sectors; + req->nr_sectors = req->hard_nr_sectors += next->hard_nr_sectors; next->rq_status = RQ_INACTIVE; list_del(&next->queue); wake_up (&wait_for_request); @@ -685,7 +685,7 @@ break; req->bhtail->b_reqnext = bh; req->bhtail = bh; - req->nr_sectors += count; + req->nr_sectors = req->hard_nr_sectors += count; drive_stat_acct(req, count, 0); elevator_merge_after(elevator, req, latency); @@ -714,8 +714,8 @@ req->bh = bh; req->buffer = bh->b_data; req->current_nr_sectors = count; - req->sector = sector; - req->nr_sectors += count; + req->sector = req->hard_sector = sector; + req->nr_sectors = req->hard_nr_sectors += count; drive_stat_acct(req, count, 0); elevator_merge_before(elevator, req, latency); @@ -754,8 +754,8 @@ /* fill up the request-info, and add it to the queue */ req->cmd = rw; req->errors = 0; - req->sector = sector; - req->nr_sectors = count; + req->hard_sector = req->sector = sector; + req->hard_nr_sectors = req->nr_sectors = count; req->current_nr_sectors = count; req->nr_segments = 1; /* Always 1 for a new request. */ req->nr_hw_segments = 1; /* Always 1 for a new request. */ @@ -920,23 +920,21 @@ int nsect; req->errors = 0; - if (!uptodate) { + if (!uptodate) printk("end_request: I/O error, dev %s (%s), sector %lu\n", kdevname(req->rq_dev), name, req->sector); - if ((bh = req->bh) != NULL) { - nsect = bh->b_size >> 9; - req->nr_sectors--; - req->nr_sectors &= ~(nsect - 1); - req->sector += nsect; - req->sector &= ~(nsect - 1); - } - } if ((bh = req->bh) != NULL) { + nsect = bh->b_size >> 9; req->bh = bh->b_reqnext; bh->b_reqnext = NULL; bh->b_end_io(bh, uptodate); if ((bh = req->bh) != NULL) { + req->hard_sector += nsect; + req->hard_nr_sectors -= nsect; + req->sector = req->hard_sector; + req->nr_sectors = req->hard_nr_sectors; + req->current_nr_sectors = bh->b_size >> 9; if (req->nr_sectors < req->current_nr_sectors) { req->nr_sectors = req->current_nr_sectors; @@ -1072,6 +1070,12 @@ #endif #ifdef CONFIG_BLK_DEV_NBD nbd_init(); +#endif +#ifdef CONFIG_MDISK + mdisk_init(); +#endif +#ifdef CONFIG_DASD + dasd_init(); #endif return 0; }; diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/block/lvm.c linux/drivers/block/lvm.c --- v2.3.99-pre3/linux/drivers/block/lvm.c Mon Mar 27 08:08:23 2000 +++ linux/drivers/block/lvm.c Mon Mar 27 09:44:58 2000 @@ -931,7 +931,7 @@ printk(KERN_DEBUG "%s -- lvm_blk_ioctl -- BLKRAGET\n", lvm_name); #endif - if (put_user(lv->lv_read_ahead, (long *)arg)) + if (put_user(lv_ptr->lv_read_ahead, (long *)arg)) return -EFAULT; break; diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/block/md.c linux/drivers/block/md.c --- v2.3.99-pre3/linux/drivers/block/md.c Mon Mar 27 08:08:23 2000 +++ linux/drivers/block/md.c Mon Apr 10 23:04:49 2000 @@ -1805,6 +1805,136 @@ #undef OUT +/* support old ioctls/init - cold add only */ +int do_md_add(mddev_t *mddev, kdev_t dev) +{ + int err; + mdk_rdev_t *rdev; + + if (mddev->sb || mddev->pers) + return -EBUSY; + err = md_import_device(dev, 0); + if (err) return err; + rdev = find_rdev_all(dev); + if (!rdev) { + MD_BUG(); + return -EINVAL; + } + rdev->old_dev = dev; + rdev->desc_nr = mddev->nb_dev; + bind_rdev_to_array(rdev, mddev); + return 0; +} + +#define SET_SB(x,v) mddev->sb->x = v +#define SET_RSB(x,y) mddev->sb->disks[nr].x = y +static void autorun_array (mddev_t *mddev); +int do_md_start(mddev_t *mddev, int info) +{ + int pers = (info & 0xFF0000UL)>>16; +// int fault= (info & 0x00FF00UL)>>8; + int factor=(info & 0x0000FFUL); + + struct md_list_head *tmp; + mdk_rdev_t *rdev, *rdev0=NULL; + int err = 0; + + if (mddev->sb) { + printk("array md%d already has superbloc!!\n", + mdidx(mddev)); + return -EBUSY; + } + if (pers==1 || pers==2) { + /* non-persistant super block */ + int devs = mddev->nb_dev; + if (alloc_array_sb(mddev)) + return -ENOMEM; + mddev->sb->major_version = MD_MAJOR_VERSION; + mddev->sb->minor_version = MD_MINOR_VERSION; + mddev->sb->patch_version = MD_PATCHLEVEL_VERSION; + mddev->sb->ctime = CURRENT_TIME; + + SET_SB(level,pers_to_level(pers)); + SET_SB(size,0); + SET_SB(nr_disks, devs); + SET_SB(raid_disks, devs); + SET_SB(md_minor,mdidx(mddev)); + SET_SB(not_persistent, 1); + + + SET_SB(state, 1<sb->md_magic = MD_SB_MAGIC; + + /* + * Generate a 128 bit UUID + */ + get_random_bytes(&mddev->sb->set_uuid0, 4); + get_random_bytes(&mddev->sb->set_uuid1, 4); + get_random_bytes(&mddev->sb->set_uuid2, 4); + get_random_bytes(&mddev->sb->set_uuid3, 4); + + /* add each disc */ + ITERATE_RDEV(mddev,rdev,tmp) { + int nr, size; + nr = rdev->desc_nr; + SET_RSB(number,nr); + SET_RSB(major,MAJOR(rdev->dev)); + SET_RSB(minor,MINOR(rdev->dev)); + SET_RSB(raid_disk,nr); + SET_RSB(state,6); /* ACTIVE|SYNC */ + size = calc_dev_size(rdev->dev, mddev, 0); + rdev->sb_offset = calc_dev_sboffset(rdev->dev, mddev, 0); + + if (!mddev->sb->size || (mddev->sb->size > size)) + mddev->sb->size = size; + } + sync_sbs(mddev); + err = do_md_run(mddev); + if (err) + do_md_stop(mddev, 0); + } else { + /* persistant super block - ignore the info and read the superblocks */ + ITERATE_RDEV(mddev,rdev,tmp) { + if ((err = read_disk_sb(rdev))) { + printk("md: could not read %s's sb, not importing!\n", + partition_name(rdev->dev)); + break; + } + if ((err = check_disk_sb(rdev))) { + printk("md: %s has invalid sb, not importing!\n", + partition_name(rdev->dev)); + break; + } + rdev->desc_nr = rdev->sb->this_disk.number; + if (!rdev0) rdev0=rdev; + if (!uuid_equal(rdev0, rdev)) { + printk("%s has different UUID to %s .. dropping\n", + partition_name(rdev->dev), + partition_name(rdev0->dev)); + err = -EINVAL; + break; + } + if (!sb_equal(rdev0->sb, rdev->sb)) { + printk("%s has same UUID as %s, but superblocks differ ...\n", partition_name(rdev->dev), partition_name(rdev0->dev)); + err = -EINVAL; + break; + } + } + if (!err) + autorun_array(mddev); + } + return err; +} +#undef SET_SB +#undef SET_RSB /* * We have to safely support old arrays too. */ @@ -2573,6 +2703,58 @@ } default: } + /* handle "old style" ioctls */ + switch (cmd) + { + case START_MD: + if (!mddev) + return -ENODEV; + err = lock_mddev(mddev); + if (err) { + printk("ioctl lock interrupted, reason %d, cmd %d\n",err, cmd); + goto abort; + } + err = do_md_start(mddev, (int) arg); + if (err) { + printk("couldn't mdstart\n"); + goto abort_unlock; + } + goto done_unlock; + case STOP_MD: + if (!mddev) + return -ENODEV; + err = lock_mddev(mddev); + if (err) { + printk("ioctl lock interrupted, reason %d, cmd %d\n",err, cmd); + goto abort_unlock; + } + err = do_md_stop(mddev, 0); + if (err) { + printk("couldn't mdstop\n"); + goto abort_unlock; + } + goto done_unlock; + case REGISTER_DEV: + /* add this device to an unstarted array, + * create the array if needed */ + if (!mddev) + mddev = alloc_mddev(dev); + if (!mddev) { + err = -ENOMEM; + goto abort; + } + err = lock_mddev(mddev); + if (err) { + printk("ioctl, reason %d, cmd %d\n", err, cmd); + goto abort; + } + err = do_md_add(mddev, to_kdev_t((dev_t) arg)); + if (err) { + printk("do_md_add failed %d\n", err); + goto abort_unlock; + } + goto done_unlock; + } switch (cmd) { @@ -2593,7 +2775,7 @@ err = set_array_info(mddev, (void *)arg); if (err) { printk("couldnt set array info. %d\n", err); - goto abort; + goto abort_unlock; } goto done_unlock; @@ -3188,10 +3370,11 @@ } #ifdef CONFIG_MD_BOOT +#define MAX_MD_BOOT_DEVS 16 struct { unsigned long set; - int pers[MAX_MD_DEVS]; - kdev_t devices[MAX_MD_DEVS][MAX_REAL]; + int pers[MAX_MD_BOOT_DEVS]; + kdev_t devices[MAX_MD_BOOT_DEVS][MAX_REAL]; } md_setup_args md__initdata = { 0,{0},{{0}} }; @@ -3219,7 +3402,7 @@ get_option(&str, &fault) != 2) { printk("md: Too few arguments supplied to md=.\n"); return 0; - } else if (minor >= MAX_MD_DEVS) { + } else if (minor >= MAX_MD_BOOT_DEVS) { printk ("md: Minor device number too high.\n"); return 0; } else if (md_setup_args.set & (1 << minor)) { @@ -3229,13 +3412,13 @@ switch(level) { #ifdef CONFIG_MD_LINEAR case -1: - level = LINEAR; + level = LINEAR<<16; pername = "linear"; break; #endif #ifdef CONFIG_MD_STRIPED case 0: - level = STRIPED; + level = STRIPED<<16; pername = "striped"; break; #endif @@ -3263,9 +3446,9 @@ printk ("md: Will configure md%d (%s) from %s, below.\n", minor, pername, devnames); md_setup_args.devices[minor][i] = (kdev_t) 0; - md_setup_args.pers[minor] = level | factor | (fault << FAULT_SHIFT); + md_setup_args.pers[minor] = level | factor | (fault << 8); md_setup_args.set |= (1 << minor); - return 0; + return 1; } #endif @@ -3273,7 +3456,7 @@ { int i; - for(i = 0; i < MAX_MD_DEVS; i++) { + for(i = 0; i < MAX_MD_BOOT_DEVS; i++) { md_blocksizes[i] = 1024; md_size[i] = 0; md_maxreadahead[i] = MD_READAHEAD; @@ -3344,20 +3527,20 @@ } #ifdef CONFIG_MD_BOOT -static void __init md_setup_drive(void) +void __init md_setup_drive(void) { - if(md_setup_args.set) - do_md_setup(md_setup_args.str, md_setup_args.ints); int minor, i; kdev_t dev; + mddev_t*mddev; - for (minor = 0; minor < MAX_MD_DEVS; minor++) { + for (minor = 0; minor < MAX_MD_BOOT_DEVS; minor++) { if ((md_setup_args.set & (1 << minor)) == 0) continue; printk("md: Loading md%d.\n", minor); + mddev = alloc_mddev(MKDEV(MD_MAJOR,minor)); for (i = 0; (dev = md_setup_args.devices[minor][i]); i++) - do_md_add (minor, dev); - do_md_run (minor, md_setup_args.pers[minor]); + do_md_add (mddev, dev); + do_md_start (mddev, md_setup_args.pers[minor]); } } diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/block/nbd.c linux/drivers/block/nbd.c --- v2.3.99-pre3/linux/drivers/block/nbd.c Sun Mar 19 18:35:30 2000 +++ linux/drivers/block/nbd.c Tue Apr 11 06:59:13 2000 @@ -350,6 +350,7 @@ { struct nbd_device *lo; int dev, error, temp; + struct request sreq ; /* Anyone capable of this syscall can do *real bad* things */ @@ -363,6 +364,13 @@ lo = &nbd_dev[dev]; switch (cmd) { + case NBD_DISCONNECT: + printk("NBD_DISCONNECT\n") ; + sreq.cmd=2 ; /* shutdown command */ + if (!lo->sock) return -EINVAL ; + nbd_send_req(lo->sock,&sreq) ; + return 0 ; + case NBD_CLEAR_SOCK: down(&lo->queue_lock); nbd_clear_que(lo); diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/block/paride/pcd.c linux/drivers/block/paride/pcd.c --- v2.3.99-pre3/linux/drivers/block/paride/pcd.c Wed Feb 16 17:03:51 2000 +++ linux/drivers/block/paride/pcd.c Tue Apr 4 19:25:14 2000 @@ -765,7 +765,7 @@ pcd_unit = unit; } pcd_sector = CURRENT->sector; - pcd_count = CURRENT->nr_sectors; + pcd_count = CURRENT->current_nr_sectors; pcd_buf = CURRENT->buffer; pcd_busy = 1; ps_set_intr(do_pcd_read,0,0,nice); diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/block/paride/pd.c linux/drivers/block/paride/pd.c --- v2.3.99-pre3/linux/drivers/block/paride/pd.c Wed Feb 16 17:03:51 2000 +++ linux/drivers/block/paride/pd.c Tue Apr 4 19:25:14 2000 @@ -385,9 +385,62 @@ } } +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++; + q->elevator.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; + + q->elevator.nr_segments -= same_segment; + req->nr_segments = total_segments; + return 1; +} + int pd_init (void) { int i; + request_queue_t * q; if (disable) return -1; if (devfs_register_blkdev(MAJOR_NR,name,&pd_fops)) { @@ -395,7 +448,11 @@ name,major); return -1; } - blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST); + 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; @@ -865,7 +922,6 @@ static void do_pd_request (request_queue_t * q) { struct buffer_head * bh; - struct request * req; int unit; if (pd_busy) return; @@ -876,12 +932,10 @@ pd_dev = MINOR(CURRENT->rq_dev); pd_unit = unit = DEVICE_NR(CURRENT->rq_dev); pd_block = CURRENT->sector; - pd_count = CURRENT->nr_sectors; + pd_run = CURRENT->nr_sectors; + pd_count = CURRENT->current_nr_sectors; bh = CURRENT->bh; - req = CURRENT; - if (bh->b_reqnext) - printk("%s: OUCH: b_reqnext != NULL\n",PD.name); if ((pd_dev >= PD_DEVS) || ((pd_block+pd_count) > pd_hd[pd_dev].nr_sects)) { @@ -890,14 +944,6 @@ } pd_cmd = CURRENT->cmd; - pd_run = pd_count; - while ((pd_run <= cluster) && - (req = blkdev_next_request(req)) && - (pd_block+pd_run == req->sector) && - (pd_cmd == req->cmd) && - (pd_dev == MINOR(req->rq_dev))) - pd_run += req->nr_sectors; - pd_poffs = pd_hd[pd_dev].start_sect; pd_block += pd_poffs; pd_buf = CURRENT->buffer; @@ -932,7 +978,7 @@ printk("%s: OUCH: request list changed unexpectedly\n", PD.name); - pd_count = CURRENT->nr_sectors; + pd_count = CURRENT->current_nr_sectors; pd_buf = CURRENT->buffer; spin_unlock_irqrestore(&io_request_lock,saved_flags); } diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/block/paride/pf.c linux/drivers/block/paride/pf.c --- v2.3.99-pre3/linux/drivers/block/paride/pf.c Wed Feb 16 17:03:51 2000 +++ linux/drivers/block/paride/pf.c Tue Apr 4 19:25:14 2000 @@ -339,9 +339,62 @@ } } +static inline int pf_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++; + q->elevator.nr_segments++; + return 1; + } + return 0; +} + +static int pf_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 pf_new_segment(q, req, max_segments); +} + +static int pf_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 pf_new_segment(q, req, max_segments); +} + +static int pf_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; + + q->elevator.nr_segments -= same_segment; + req->nr_segments = total_segments; + return 1; +} + int pf_init (void) /* preliminary initialisation */ { int i; + request_queue_t * q; if (disable) return -1; @@ -355,7 +408,11 @@ major); return -1; } - blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST); + q = BLK_DEFAULT_QUEUE(MAJOR_NR); + blk_init_queue(q, DEVICE_REQUEST); + q->back_merge_fn = pf_back_merge_fn; + q->front_merge_fn = pf_front_merge_fn; + q->merge_requests_fn = pf_merge_requests_fn; read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read ahead */ for (i=0;irq_dev); pf_block = CURRENT->sector; - pf_count = CURRENT->nr_sectors; + pf_run = CURRENT->nr_sectors; + pf_count = CURRENT->current_nr_sectors; bh = CURRENT->bh; - req = CURRENT; - if (bh->b_reqnext) - printk("%s: OUCH: b_reqnext != NULL\n",PF.name); if ((pf_unit >= PF_UNITS) || (pf_block+pf_count > PF.capacity)) { end_request(0); @@ -872,14 +926,6 @@ } pf_cmd = CURRENT->cmd; - pf_run = pf_count; - while ((pf_run <= cluster) && - (req = blkdev_next_request(req)) && - (pf_block+pf_run == req->sector) && - (pf_cmd == req->cmd) && - (pf_unit == DEVICE_NR(req->rq_dev))) - pf_run += req->nr_sectors; - pf_buf = CURRENT->buffer; pf_retries = 0; @@ -912,7 +958,7 @@ printk("%s: OUCH: request list changed unexpectedly\n", PF.name); - pf_count = CURRENT->nr_sectors; + pf_count = CURRENT->current_nr_sectors; pf_buf = CURRENT->buffer; spin_unlock_irqrestore(&io_request_lock,saved_flags); } diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/block/rd.c linux/drivers/block/rd.c --- v2.3.99-pre3/linux/drivers/block/rd.c Fri Mar 10 16:40:42 2000 +++ linux/drivers/block/rd.c Sun Apr 9 08:12:56 2000 @@ -333,7 +333,8 @@ * Immunize device against invalidate_buffers() and prune_icache(). */ if (rd_inode[DEVICE_NR(inode->i_rdev)] == NULL) { - if((rd_inode[DEVICE_NR(inode->i_rdev)] = igrab(inode)) != 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); } diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/block/xd.c linux/drivers/block/xd.c --- v2.3.99-pre3/linux/drivers/block/xd.c Wed Feb 16 17:03:51 2000 +++ linux/drivers/block/xd.c Sun Apr 2 15:38:53 2000 @@ -1059,7 +1059,7 @@ } /* xd_setup: initialise controler from command line parameters */ -void __init xd_setup (char *command,int *integers) +void __init do_xd_setup (int *integers) { switch (integers[0]) { case 4: if (integers[4] < 0) @@ -1079,21 +1079,6 @@ xd_maxsectors = 0x01; } -#ifndef MODULE -/* xd_manual_geo_init: initialise drive geometry from command line parameters - (used only for WD drives) */ -void __init xd_manual_geo_init (char *command,int *integers) -{ - int i; - if (integers[0]%3 != 0) { - printk("xd: incorrect number of parameters for xd_geo\n"); - return; - } - for (i = 0; (i < integers[0]) && (i < 3*XD_MAXDRIVES); i++) - xd_geo[i] = integers[i+1]; -} -#endif /* MODULE */ - /* xd_setparam: set the drive characteristics */ static void __init xd_setparam (u_char command,u_char drive,u_char heads,u_short cylinders,u_short rwrite,u_short wprecomp,u_char ecc) { @@ -1149,7 +1134,7 @@ if(((xd[i] = xd[i-1]) >= 0) && !count) count = i; if((xd[0] = count)) - xd_setup(NULL, xd); + do_xd_setup(xd); if (error = xd_init()) return error; @@ -1190,6 +1175,30 @@ } } #else + +static int __init xd_setup (char *str) +{ + int ints[5]; + get_options (str, ARRAY_SIZE (ints), ints); + do_xd_setup (ints); + return 1; +} + +/* xd_manual_geo_init: initialise drive geometry from command line parameters + (used only for WD drives) */ +static int __init xd_manual_geo_init (char *str) +{ + int i, integers[1 + 3*XD_MAXDRIVES]; + + get_options (str, ARRAY_SIZE (ints), ints); + if (integers[0]%3 != 0) { + printk("xd: incorrect number of parameters for xd_geo\n"); + return 1; + } + for (i = 0; (i < integers[0]) && (i < 3*XD_MAXDRIVES); i++) + xd_geo[i] = integers[i+1]; + return 1; +} __setup ("xd=", xd_setup); __setup ("xd_geo=", xd_manual_geo_init); diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/char/Config.in linux/drivers/char/Config.in --- v2.3.99-pre3/linux/drivers/char/Config.in Tue Mar 14 19:10:39 2000 +++ linux/drivers/char/Config.in Sun Apr 2 15:38:53 2000 @@ -110,6 +110,7 @@ if [ "$CONFIG_WATCHDOG" != "n" ]; then bool ' Disable watchdog shutdown on close' CONFIG_WATCHDOG_NOWAYOUT tristate ' WDT Watchdog timer' CONFIG_WDT + tristate ' WDT PCI Watchdog timer' CONFIG_WDTPCI if [ "$CONFIG_WDT" != "n" ]; then bool ' WDT501 features' CONFIG_WDT_501 if [ "$CONFIG_WDT_501" = "y" ]; then @@ -152,7 +153,7 @@ tristate 'Video For Linux' CONFIG_VIDEO_DEV if [ "$CONFIG_VIDEO_DEV" != "n" ]; then - dep_tristate ' I2C on parallel port' CONFIG_I2C_PARPORT $CONFIG_PARPORT + dep_tristate ' I2C on parallel port' CONFIG_I2C_PARPORT $CONFIG_PARPORT $CONFIG_I2C comment 'Radio Adapters' dep_tristate ' ADS Cadet AM/FM Tuner' CONFIG_RADIO_CADET $CONFIG_VIDEO_DEV dep_tristate ' AIMSlab RadioTrack (aka RadioReveal) support' CONFIG_RADIO_RTRACK $CONFIG_VIDEO_DEV @@ -208,6 +209,15 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then dep_tristate ' QuickCam Colour Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_CQCAM $CONFIG_VIDEO_DEV $CONFIG_PARPORT fi + fi + dep_tristate 'CPiA Video For Linux' CONFIG_VIDEO_CPIA $CONFIG_VIDEO_DEV + if [ "$CONFIG_VIDEO_CPIA" != "n" ]; then + if [ "CONFIG_PARPORT_1284" != "n" ]; then + dep_tristate 'CPiA Parallel Port Lowlevel Support' CONFIG_VIDEO_CPIA_PP $CONFIG_VIDEO_CPIA $CONFIG_PARPORT + fi + if [ "$CONFIG_USB" != "n" ]; then + dep_tristate 'CPiA USB Lowlevel Support' CONFIG_VIDEO_CPIA_USB $CONFIG_VIDEO_CPIA $CONFIG_USB + fi fi dep_tristate ' SAA5249 Teletext processor' CONFIG_VIDEO_SAA5249 $CONFIG_VIDEO_DEV $CONFIG_I2C dep_tristate ' SAB3036 tuner' CONFIG_TUNER_3036 $CONFIG_VIDEO_DEV $CONFIG_I2C diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/char/Makefile linux/drivers/char/Makefile --- v2.3.99-pre3/linux/drivers/char/Makefile Tue Mar 7 14:32:25 2000 +++ linux/drivers/char/Makefile Sun Apr 2 15:38:53 2000 @@ -38,7 +38,7 @@ export-objs := busmouse.o console.o i2c-old.o keyboard.o sysrq.o \ misc.o pty.o random.o selection.o serial.o videodev.o \ - tty_io.o bttv.o + tty_io.o bttv.o cpia.o KEYMAP =defkeymap.o KEYBD =pc_keyb.o @@ -171,6 +171,7 @@ obj-$(CONFIG_ADBMOUSE) += adbmouse.o busmouse.o obj-$(CONFIG_PC110_PAD) += pc110pad.o obj-$(CONFIG_WDT) += wdt.o +obj-$(CONFIG_WDTPCI) += wdt_pci.o obj-$(CONFIG_RTC) += rtc.o obj-$(CONFIG_EFI_RTC) += efirtc.o ifeq ($(CONFIG_PPC),) @@ -179,7 +180,7 @@ obj-$(CONFIG_VIDEO_DEV) += videodev.o -obj-$(CONFIG_21825_WATCHDOG) += wdt285.o +obj-$(CONFIG_21285_WATCHDOG) += wdt285.o obj-$(CONFIG_977_WATCHDOG) += wdt977.o obj-$(CONFIG_DS1620) += ds1620.o @@ -252,6 +253,9 @@ obj-$(CONFIG_VIDEO_PLANB) += planb.o obj-$(CONFIG_VIDEO_VINO) += vino.o obj-$(CONFIG_VIDEO_STRADIS) += stradis.o +obj-$(CONFIG_VIDEO_CPIA) += cpia.o +obj-$(CONFIG_VIDEO_CPIA_PP) += cpia_pp.o +obj-$(CONFIG_VIDEO_CPIA_USB) += cpia_usb.o obj-$(CONFIG_RADIO_AZTECH) += radio-aztech.o obj-$(CONFIG_RADIO_RTRACK2) += radio-rtrack2.o obj-$(CONFIG_RADIO_SF16FMI) += radio-sf16fmi.o diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/char/agp/agpgart_be.c linux/drivers/char/agp/agpgart_be.c --- v2.3.99-pre3/linux/drivers/char/agp/agpgart_be.c Tue Mar 7 14:32:25 2000 +++ linux/drivers/char/agp/agpgart_be.c Mon Apr 10 22:41:19 2000 @@ -1764,6 +1764,30 @@ #endif /* CONFIG_AGP_INTEL */ #ifdef CONFIG_AGP_SIS + { PCI_DEVICE_ID_SI_630, + 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", + sis_generic_setup }, { 0, PCI_VENDOR_ID_SI, SIS_GENERIC, diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/char/applicom.c linux/drivers/char/applicom.c --- v2.3.99-pre3/linux/drivers/char/applicom.c Mon Mar 27 08:08:23 2000 +++ linux/drivers/char/applicom.c Mon Mar 27 09:44:58 2000 @@ -1,7 +1,7 @@ /* Derived from Applicom driver ac.c for SCO Unix */ /* Ported by David Woodhouse, Axiom (Cambridge) Ltd. */ /* Dave@mvhi.com 30/8/98 */ -/* $Id: ac.c,v 1.16 1999/08/28 15:11:50 dwmw2 Exp $ */ +/* $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. */ /*****************************************************************************/ /* J PAGET 18/02/94 passage V2.4.2 ioctl avec code 2 reset to les interrupt */ @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -29,15 +30,29 @@ #include #include #include +#include + #include "applicom.h" -#ifndef LINUX_VERSION_CODE -#include + +#if LINUX_VERSION_CODE < 0x20300 +/* These probably want adding to */ +#define init_waitqueue_head(x) do { *(x) = NULL; } while (0); +#define PCI_BASE_ADDRESS(dev) (dev->base_address[0]) +#define DECLARE_WAIT_QUEUE_HEAD(x) struct wait_queue *x +#define __setup(x,y) /* */ +#else +#define PCI_BASE_ADDRESS(dev) (dev->resource[0].start) #endif +/* NOTE: We use for loops with {write,read}b() instead of + memcpy_{from,to}io throughout this driver. This is because + the board doesn't correctly handle word accesses - only + bytes. +*/ + + #undef DEBUG -#define DEVPRIO PZERO+8 -#define FALSE 0 -#define TRUE ~FALSE + #define MAX_BOARD 8 /* maximum of pc board possible */ #define MAX_ISA_BOARD 4 #define LEN_RAM_IO 0x800 @@ -52,7 +67,9 @@ #endif static char *applicom_pci_devnames[] = { - "PCI board", "PCI2000IBS / PCI2000CAN", "PCI2000PFB" + "PCI board", + "PCI2000IBS / PCI2000CAN", + "PCI2000PFB" }; MODULE_AUTHOR("David Woodhouse & Applicom International"); @@ -68,12 +85,9 @@ struct applicom_board { unsigned long PhysIO; unsigned long RamIO; -#if LINUX_VERSION_CODE > 0x20300 wait_queue_head_t FlagSleepSend; -#else - struct wait_queue *FlagSleepSend; -#endif long irq; + spinlock_t mutex; } apbs[MAX_BOARD]; static unsigned int irq = 0; /* interrupt number IRQ */ @@ -81,22 +95,19 @@ static unsigned int numboards; /* number of installed boards */ static volatile unsigned char Dummy; -#if LINUX_VERSION_CODE > 0x20300 static DECLARE_WAIT_QUEUE_HEAD(FlagSleepRec); -#else -static struct wait_queue *FlagSleepRec; -#endif static unsigned int WriteErrorCount; /* number of write error */ static unsigned int ReadErrorCount; /* number of read error */ static unsigned int DeviceErrorCount; /* number of device error */ -static loff_t ac_llseek(struct file *file, loff_t offset, int origin); -static int ac_open(struct inode *inode, struct file *filp); -static ssize_t ac_read(struct file *filp, char *buf, size_t count, loff_t * ptr); -static ssize_t ac_write(struct file *file, const char *buf, size_t count, loff_t * ppos); -static int ac_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); -static int ac_release(struct inode *inode, struct file *file); -static void ac_interrupt(int irq, void *dev_instance, struct pt_regs *regs); +static loff_t ac_llseek(struct file *, loff_t, int); +static int ac_open(struct inode *, struct file *); +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 int ac_release(struct inode *, struct file *); +static void ac_interrupt(int, void *, struct pt_regs *); struct file_operations ac_fops = { llseek:ac_llseek, @@ -113,24 +124,29 @@ &ac_fops }; -int ac_register_board(unsigned long physloc, unsigned long loc, unsigned char boardno) +int ac_register_board(unsigned long physloc, unsigned long loc, + unsigned char boardno) { volatile unsigned char byte_reset_it; - if ((readb(loc + CONF_END_TEST) != 0x00) || (readb(loc + CONF_END_TEST + 1) != 0x55) || (readb(loc + CONF_END_TEST + 2) != 0xAA) || (readb(loc + CONF_END_TEST + 3) != 0xFF)) + if((readb(loc + CONF_END_TEST) != 0x00) || + (readb(loc + CONF_END_TEST + 1) != 0x55) || + (readb(loc + CONF_END_TEST + 2) != 0xAA) || + (readb(loc + CONF_END_TEST + 3) != 0xFF)) return 0; - if (!boardno) boardno = readb(loc + NUMCARD_OWNER_TO_PC); if (!boardno && boardno > MAX_BOARD) { - printk(KERN_WARNING "Board #%d (at 0x%lx) is out of range (1 <= x <= %d).\n", boardno, physloc, MAX_BOARD); + printk(KERN_WARNING "Board #%d (at 0x%lx) is out of range (1 <= x <= %d).\n", + boardno, physloc, MAX_BOARD); return 0; } if (apbs[boardno - 1].RamIO) { - printk(KERN_WARNING "Board #%d (at 0x%lx) conflicts with previous board #%d (at 0x%lx)\n", boardno, physloc, boardno, apbs[boardno - 1].PhysIO); + printk(KERN_WARNING "Board #%d (at 0x%lx) conflicts with previous board #%d (at 0x%lx)\n", + boardno, physloc, boardno, apbs[boardno-1].PhysIO); return 0; } @@ -138,11 +154,8 @@ apbs[boardno].PhysIO = physloc; apbs[boardno].RamIO = loc; -#if LINUX_VERSION_CODE > 0x20300 init_waitqueue_head(&apbs[boardno].FlagSleepSend); -#else - apbs[boardno].FlagSleepSend = NULL; -#endif + spin_lock_init(&apbs[boardno].mutex); byte_reset_it = readb(loc + RAM_IT_TO_PC); numboards++; @@ -158,14 +171,17 @@ int i; misc_deregister(&ac_miscdev); + for (i = 0; i < MAX_BOARD; i++) { + if (!apbs[i].RamIO) continue; + iounmap((void *) apbs[i].RamIO); + if (apbs[i].irq) free_irq(apbs[i].irq, &ac_open); } - // printk("Removing Applicom module\n"); } #endif /* MODULE */ @@ -176,20 +192,19 @@ struct pci_dev *dev = NULL; void *RamIO; int boardno; -#if LINUX_VERSION_CODE > 0x20300 -#define PCI_BASE_ADDRESS(dev) (dev->resource[0].start) -#else -#define PCI_BASE_ADDRESS(dev) (dev->base_address[0]) -#endif - printk(KERN_INFO "Applicom driver: $Id: ac.c,v 1.16 1999/08/28 15:11:50 dwmw2 Exp $\n"); + printk(KERN_INFO "Applicom driver: $Id: ac.c,v 1.30 2000/03/22 16:03:57 dwmw2 Exp $\n"); /* No mem and irq given - check for a PCI card */ - while ((dev = pci_find_device(PCI_VENDOR_ID_APPLICOM, 1, dev))) { - // mem = dev->base_address[0]; - // irq = dev->irq; + while ( (dev = pci_find_class(PCI_CLASS_OTHERS << 16, dev))) { + if (dev->vendor != PCI_VENDOR_ID_APPLICOM) + continue; + + if (dev->device > MAX_PCI_DEVICE_NUM || dev->device == 0) + continue; + RamIO = ioremap(PCI_BASE_ADDRESS(dev), LEN_RAM_IO); if (!RamIO) { @@ -197,9 +212,12 @@ return -EIO; } - printk(KERN_INFO "Applicom %s found at mem 0x%lx, irq %d\n", applicom_pci_devnames[dev->device - 1], PCI_BASE_ADDRESS(dev), dev->irq); + printk(KERN_INFO "Applicom %s found at mem 0x%lx, irq %d\n", + applicom_pci_devnames[dev->device-1], PCI_BASE_ADDRESS(dev), + dev->irq); - if (!(boardno = ac_register_board(PCI_BASE_ADDRESS(dev), (unsigned long) RamIO, 0))) { + if (!(boardno = ac_register_board(PCI_BASE_ADDRESS(dev), + (unsigned long)RamIO,0))) { printk(KERN_INFO "ac.o: PCI Applicom device doesn't have correct signature.\n"); iounmap(RamIO); continue; @@ -236,9 +254,8 @@ RamIO = ioremap(mem, LEN_RAM_IO * MAX_ISA_BOARD); - if (!RamIO) { + if (!RamIO) printk(KERN_INFO "ac.o: Failed to ioremap ISA memory space at 0x%lx\n", mem); - } for (i = 0; i < MAX_ISA_BOARD; i++) { RamIO = ioremap(mem + (LEN_RAM_IO * i), LEN_RAM_IO); @@ -248,39 +265,38 @@ continue; } - if (!(boardno = ac_register_board((unsigned long) mem + (LEN_RAM_IO * i), (unsigned long) RamIO, i + 1))) { + if (!(boardno = ac_register_board((unsigned long)mem+ (LEN_RAM_IO*i), + (unsigned long)RamIO,i+1))) { iounmap(RamIO); continue; } - printk("Applicom ISA card found at mem 0x%lx, irq %d\n", mem + (LEN_RAM_IO * i), irq); + printk(KERN_NOTICE "Applicom ISA card found at mem 0x%lx, irq %d\n", mem + (LEN_RAM_IO*i), irq); if (!numisa) { if (request_irq(irq, &ac_interrupt, SA_SHIRQ, "Applicom ISA", &ac_open)) { - printk("Could not allocate IRQ %d for ISA Applicom device.\n", irq); + printk(KERN_WARNING "Could not allocate IRQ %d for ISA Applicom device.\n", irq); iounmap((void *) RamIO); apbs[boardno - 1].RamIO = 0; } apbs[boardno - 1].irq = irq; - } else + } + else apbs[boardno - 1].irq = 0; numisa++; } if (!numisa) - printk("ac.o: No valid ISA Applicom boards found at mem 0x%lx\n", mem); + printk(KERN_WARNING"ac.o: No valid ISA Applicom boards found at mem 0x%lx\n",mem); -#if LINUX_VERSION_CODE > 0x20300 + fin: init_waitqueue_head(&FlagSleepRec); -#else - FlagSleepRec = NULL; -#endif + WriteErrorCount = 0; ReadErrorCount = 0; DeviceErrorCount = 0; - fin: if (numboards) { misc_register(&ac_miscdev); for (i = 0; i < MAX_BOARD; i++) { @@ -292,12 +308,18 @@ for (serial = 0; serial < SERIAL_NUMBER - TYPE_CARD; serial++) boardname[serial] = readb(apbs[i].RamIO + TYPE_CARD + serial); - boardname[serial] = 0; + boardname[serial] = 0; - printk(KERN_INFO "Applicom board %d: %s, PROM V%d.%d", i + 1, boardname, (int) (readb(apbs[i].RamIO + VERS) >> 4), (int) (readb(apbs[i].RamIO + VERS) & 0xF)); - serial = (readb(apbs[i].RamIO + SERIAL_NUMBER) << 16) + (readb(apbs[i].RamIO + SERIAL_NUMBER + 1) << 8) + (readb(apbs[i].RamIO + SERIAL_NUMBER + 2)); + printk(KERN_INFO "Applicom board %d: %s, PROM V%d.%d", + i+1, boardname, + (int)(readb(apbs[i].RamIO + VERS) >> 4), + (int)(readb(apbs[i].RamIO + VERS) & 0xF)); + + serial = (readb(apbs[i].RamIO + SERIAL_NUMBER) << 16) + + (readb(apbs[i].RamIO + SERIAL_NUMBER + 1) << 8) + + (readb(apbs[i].RamIO + SERIAL_NUMBER + 2) ); if (serial != 0) printk(" S/N %d\n", serial); @@ -342,35 +364,41 @@ unsigned long flags; /* Current priority */ struct st_ram_io st_loc; struct mailbox tmpmailbox; +#ifdef DEBUG + int c; +#endif + DECLARE_WAITQUEUE(wait, current); if (count != sizeof(struct st_ram_io) + sizeof(struct mailbox)) { - printk("Hmmm. write() of Applicom card, length %d != expected %d\n", count, sizeof(struct st_ram_io) + sizeof(struct mailbox)); + static int warncount = 5; + if (warncount) { + printk(KERN_INFO "Hmmm. write() of Applicom card, length %d != expected %d\n", + count, sizeof(struct st_ram_io) + sizeof(struct mailbox)); + warncount--; + } return -EINVAL; } - if (copy_from_user(&st_loc, buf, sizeof(struct st_ram_io))) { + if(copy_from_user(&st_loc, buf, sizeof(struct st_ram_io))) return -EFAULT; - } - if (copy_from_user(&tmpmailbox, &buf[sizeof(struct st_ram_io)], sizeof(struct mailbox))) { + + if(copy_from_user(&tmpmailbox, &buf[sizeof(struct st_ram_io)], + sizeof(struct mailbox))) return -EFAULT; - } NumCard = st_loc.num_card; /* board number to send */ TicCard = st_loc.tic_des_from_pc; /* tic number to send */ IndexCard = NumCard - 1; - if ((NumCard < 1) || (NumCard > MAX_BOARD) || !apbs[IndexCard].RamIO) { /* User board number not OK */ - // printk("Write to invalid Applicom board %d\n", NumCard); - return -EINVAL; /* Return error code user buffer */ - } -#ifdef DEBUG - { - int c; - - printk("Write to applicom card #%d. struct st_ram_io follows:", NumCard); + if((NumCard < 1) || (NumCard > MAX_BOARD) || !apbs[IndexCard].RamIO) + return -EINVAL; +#ifdef DEBUG + printk("Write to applicom card #%d. struct st_ram_io follows:", + IndexCard+1); for (c = 0; c < sizeof(struct st_ram_io);) { + printk("\n%5.5X: %2.2X", c, ((unsigned char *) &st_loc)[c]); for (c++; c % 8 && c < sizeof(struct st_ram_io); c++) { @@ -389,36 +417,48 @@ } printk("\n"); - } - #endif - save_flags(flags); - cli(); /* disable interrupt */ + spin_lock_irqsave(&apbs[IndexCard].mutex, flags); - if (readb(apbs[IndexCard].RamIO + DATA_FROM_PC_READY) > 2) { /* Test octet ready correct */ + /* Test octet ready correct */ + if(readb(apbs[IndexCard].RamIO + DATA_FROM_PC_READY) > 2) { Dummy = readb(apbs[IndexCard].RamIO + VERS); - restore_flags(flags); - printk("APPLICOM driver write error board %d, DataFromPcReady = %d\n", IndexCard, (int) readb(apbs[IndexCard].RamIO + DATA_FROM_PC_READY)); + spin_unlock_irqrestore(&apbs[IndexCard].mutex, flags); + printk(KERN_WARNING "APPLICOM driver write error board %d, DataFromPcReady = %d\n", + IndexCard,(int)readb(apbs[IndexCard].RamIO + DATA_FROM_PC_READY)); DeviceErrorCount++; return -EIO; } + + /* Place ourselves on the wait queue */ + current->state = TASK_INTERRUPTIBLE; + add_wait_queue(&apbs[IndexCard].FlagSleepSend, &wait); + + /* Check whether the card is ready for us */ while (readb(apbs[IndexCard].RamIO + DATA_FROM_PC_READY) != 0) { Dummy = readb(apbs[IndexCard].RamIO + VERS); - restore_flags(flags); - /* - * FIXME: Race on wakeup. Race on re-entering write - * in another thread. - */ - interruptible_sleep_on(&apbs[IndexCard].FlagSleepSend); - if (signal_pending(current)) + /* It's busy. Sleep. */ + + spin_unlock_irqrestore(&apbs[IndexCard].mutex, flags); + schedule(); + if (signal_pending(current)) { + remove_wait_queue(&apbs[IndexCard].FlagSleepSend, + &wait); return -EINTR; - save_flags(flags); - cli(); } + spin_lock_irqsave(&apbs[IndexCard].mutex, flags); + } + + /* We may not have actually slept */ + current->state = TASK_RUNNING; + remove_wait_queue(&apbs[IndexCard].FlagSleepSend, &wait); + writeb(1, apbs[IndexCard].RamIO + DATA_FROM_PC_READY); - // memcpy_toio ((void *)apbs[IndexCard].PtrRamFromPc, (void *)&tmpmailbox, sizeof(struct mailbox)); + /* Which is best - lock down the pages with rawio and then + copy directly, or use bounce buffers? For now we do the latter + because it works with 2.2 still */ { unsigned char *from = (unsigned char *) &tmpmailbox; unsigned long to = (unsigned long) apbs[IndexCard].RamIO + RAM_FROM_PC; @@ -427,6 +467,7 @@ for (c = 0; c < sizeof(struct mailbox); c++) writeb(*(from++), to++); } + writeb(0x20, apbs[IndexCard].RamIO + TIC_OWNER_FROM_PC); writeb(0xff, apbs[IndexCard].RamIO + NUMCARD_OWNER_FROM_PC); writeb(TicCard, apbs[IndexCard].RamIO + TIC_DES_FROM_PC); @@ -434,75 +475,25 @@ writeb(2, apbs[IndexCard].RamIO + DATA_FROM_PC_READY); writeb(1, apbs[IndexCard].RamIO + RAM_IT_FROM_PC); Dummy = readb(apbs[IndexCard].RamIO + VERS); - restore_flags(flags); + spin_unlock_irqrestore(&apbs[IndexCard].mutex, flags); return 0; } -static ssize_t ac_read(struct file *filp, char *buf, size_t count, loff_t * ptr) +static int do_ac_read(int IndexCard, char *buf) { - unsigned int NumCard; /* board number 1 -> 8 */ - unsigned int IndexCard; /* index board number 0 -> 7 */ - unsigned long flags; - unsigned int i; - unsigned char tmp = 0; struct st_ram_io st_loc; struct mailbox tmpmailbox; /* bounce buffer - can't copy to user space with cli() */ + unsigned long from = (unsigned long)apbs[IndexCard].RamIO + RAM_TO_PC; + unsigned char *to = (unsigned char *)&tmpmailbox; +#ifdef DEBUG + int c; +#endif - - if (count != sizeof(struct st_ram_io) + sizeof(struct mailbox)) { - printk("Hmmm. read() of Applicom card, length %d != expected %d\n", count, sizeof(struct st_ram_io) + sizeof(struct mailbox)); - return -EINVAL; - } - - save_flags(flags); - cli(); - - i = 0; - - while (tmp != 2) { - for (i = 0; i < MAX_BOARD; i++) { - if (!apbs[i].RamIO) - continue; - - tmp = readb(apbs[i].RamIO + DATA_TO_PC_READY); - - if (tmp == 2) - break; - - if (tmp > 2) { /* Test octet ready correct */ - Dummy = readb(apbs[i].RamIO + VERS); - restore_flags(flags); - printk(KERN_WARNING "APPLICOM driver read error board %d, DataToPcReady = %d\n", i, (int) readb(apbs[i].RamIO + DATA_TO_PC_READY)); - DeviceErrorCount++; - return -EIO; - } - Dummy = readb(apbs[i].RamIO + VERS); - - } - if (tmp != 2) { - /* - * FIXME: race on wakeup. O_NDELAY not implemented - * Parallel read threads race. - */ - restore_flags(flags); - interruptible_sleep_on(&FlagSleepRec); - if (signal_pending(current)) - return -EINTR; - save_flags(flags); - cli(); - } - } - - IndexCard = i; - NumCard = i + 1; st_loc.tic_owner_to_pc = readb(apbs[IndexCard].RamIO + TIC_OWNER_TO_PC); st_loc.numcard_owner_to_pc = readb(apbs[IndexCard].RamIO + NUMCARD_OWNER_TO_PC); - // memcpy_fromio(&tmpmailbox, apbs[IndexCard].PtrRamToPc, sizeof(struct mailbox)); { - unsigned long from = (unsigned long) apbs[IndexCard].RamIO + RAM_TO_PC; - unsigned char *to = (unsigned char *) &tmpmailbox; int c; for (c = 0; c < sizeof(struct mailbox); c++) @@ -510,18 +501,15 @@ } writeb(1, apbs[IndexCard].RamIO + ACK_FROM_PC_READY); writeb(1, apbs[IndexCard].RamIO + TYP_ACK_FROM_PC); - writeb(NumCard, apbs[IndexCard].RamIO + NUMCARD_ACK_FROM_PC); - writeb(readb(apbs[IndexCard].RamIO + TIC_OWNER_TO_PC), apbs[IndexCard].RamIO + TIC_ACK_FROM_PC); + writeb(IndexCard+1, apbs[IndexCard].RamIO + NUMCARD_ACK_FROM_PC); + writeb(readb(apbs[IndexCard].RamIO + TIC_OWNER_TO_PC), + apbs[IndexCard].RamIO + TIC_ACK_FROM_PC); writeb(2, apbs[IndexCard].RamIO + ACK_FROM_PC_READY); writeb(0, apbs[IndexCard].RamIO + DATA_TO_PC_READY); writeb(2, apbs[IndexCard].RamIO + RAM_IT_FROM_PC); Dummy = readb(apbs[IndexCard].RamIO + VERS); - restore_flags(flags); #ifdef DEBUG - { - int c; - printk("Read from applicom card #%d. struct st_ram_io follows:", NumCard); for (c = 0; c < sizeof(struct st_ram_io);) { @@ -542,11 +530,8 @@ } } printk("\n"); - - } #endif - /* Je suis stupide. DW. */ if (copy_to_user(buf, &st_loc, sizeof(struct st_ram_io))) @@ -554,7 +539,82 @@ if (copy_to_user(&buf[sizeof(struct st_ram_io)], &tmpmailbox, sizeof(struct mailbox))) return -EFAULT; - return 0; + return (sizeof(struct st_ram_io) + sizeof(struct mailbox)); +} + +static ssize_t ac_read (struct file *filp, char *buf, size_t count, loff_t *ptr) +{ + unsigned long flags; + unsigned int i; + unsigned char tmp; + int ret = 0; + DECLARE_WAITQUEUE(wait, current); +#ifdef DEBUG + int loopcount=0; +#endif + /* No need to ratelimit this. Only root can trigger it anyway */ + if (count != sizeof(struct st_ram_io) + sizeof(struct mailbox)) { + printk( KERN_WARNING "Hmmm. read() of Applicom card, length %d != expected %d\n", + count,sizeof(struct st_ram_io) + sizeof(struct mailbox)); + return -EINVAL; + } + + while(1) { + /* Stick ourself on the wait queue */ + current->state = TASK_INTERRUPTIBLE; + add_wait_queue(&FlagSleepRec, &wait); + + /* Scan each board, looking for one which has a packet for us */ + for (i=0; i < MAX_BOARD; i++) { + if (!apbs[i].RamIO) + continue; + spin_lock_irqsave(&apbs[i].mutex, flags); + + tmp = readb(apbs[i].RamIO + DATA_TO_PC_READY); + + if (tmp == 2) { + /* Got a packet for us */ + ret = do_ac_read(i, buf); + spin_unlock_irqrestore(&apbs[i].mutex, flags); + current->state = TASK_RUNNING; + remove_wait_queue(&FlagSleepRec, &wait); + return tmp; + } + + if (tmp > 2) { + /* Got an error */ + Dummy = readb(apbs[i].RamIO + VERS); + + spin_unlock_irqrestore(&apbs[i].mutex, flags); + current->state = TASK_RUNNING; + remove_wait_queue(&FlagSleepRec, &wait); + + printk(KERN_WARNING "APPLICOM driver read error board %d, DataToPcReady = %d\n", + i,(int)readb(apbs[i].RamIO + DATA_TO_PC_READY)); + DeviceErrorCount++; + return -EIO; + } + + /* Nothing for us. Try the next board */ + Dummy = readb(apbs[i].RamIO + VERS); + spin_unlock_irqrestore(&apbs[i].mutex, flags); + + } /* per board */ + + /* OK - No boards had data for us. Sleep now */ + + schedule(); + remove_wait_queue(&FlagSleepRec, &wait); + + if (signal_pending(current)) + return -EINTR; + +#ifdef DEBUG + if (loopcount++ > 2) { + printk("Looping in ac_read. loopcount %d\n", loopcount); + } +#endif + } } static void ac_interrupt(int vec, void *dev_instance, struct pt_regs *regs) @@ -562,36 +622,50 @@ unsigned int i; unsigned int FlagInt; unsigned int LoopCount; - // volatile unsigned char ResetIntBoard; // printk("Applicom interrupt on IRQ %d occurred\n", vec); LoopCount = 0; - // for(i=boardno;i 2) { - printk(KERN_WARNING "APPLICOM driver interrupt err board %d, DataToPcReady = %d\n", i + 1, (int) readb(apbs[i].RamIO + DATA_TO_PC_READY)); + printk(KERN_WARNING "APPLICOM driver interrupt err board %d, DataToPcReady = %d\n", + i+1,(int)readb(apbs[i].RamIO + DATA_TO_PC_READY)); DeviceErrorCount++; } - if ((readb(apbs[i].RamIO + DATA_FROM_PC_READY) > 2) && (readb(apbs[i].RamIO + DATA_FROM_PC_READY) != 6)) { - printk("APPLICOM driver interrupt err board %d, DataFromPcReady = %d\n", i + 1, (int) readb(apbs[i].RamIO + DATA_FROM_PC_READY)); + + if((readb(apbs[i].RamIO + DATA_FROM_PC_READY) > 2) && + (readb(apbs[i].RamIO + DATA_FROM_PC_READY) != 6)) { + + printk(KERN_WARNING "APPLICOM driver interrupt err board %d, DataFromPcReady = %d\n", + i+1,(int)readb(apbs[i].RamIO + DATA_FROM_PC_READY)); DeviceErrorCount++; } + if (readb(apbs[i].RamIO + DATA_TO_PC_READY) == 2) { /* mailbox sent by the card ? */ + if (waitqueue_active(&FlagSleepRec)) { wake_up_interruptible(&FlagSleepRec); } + } + if (readb(apbs[i].RamIO + DATA_FROM_PC_READY) == 0) { /* ram i/o free for write by pc ? */ if (waitqueue_active(&apbs[i].FlagSleepSend)) { /* process sleep during read ? */ wake_up_interruptible(&apbs[i].FlagSleepSend); @@ -599,120 +673,123 @@ } Dummy = readb(apbs[i].RamIO + VERS); - if (readb(apbs[i].RamIO + RAM_IT_TO_PC)) - i--; /* There's another int waiting on this card */ + if(readb(apbs[i].RamIO + RAM_IT_TO_PC)) { + /* There's another int waiting on this card */ + spin_unlock(&apbs[i].mutex); + i--; + } else { + spin_unlock(&apbs[i].mutex); + } } if (FlagInt) LoopCount = 0; else LoopCount++; - } - while (LoopCount < 2); + } while(LoopCount < 2); } + static int ac_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) + { /* @ ADG ou ATO selon le cas */ int i; unsigned char IndexCard; unsigned long pmem; + int ret = 0; volatile unsigned char byte_reset_it; - struct st_ram_io adgl; - unsigned char TmpRamIo[sizeof(struct st_ram_io)]; + struct st_ram_io *adgl; + /* In general, the device is only openable by root anyway, so we're not + particularly concerned that bogus ioctls can flood the console. */ - if (copy_from_user(&adgl, (void *) arg, sizeof(struct st_ram_io))) - return -EFAULT; + adgl = kmalloc(sizeof(struct st_ram_io), GFP_KERNEL); + if (!adgl) + return -ENOMEM; - IndexCard = adgl.num_card - 1; + if (copy_from_user(adgl, (void *)arg,sizeof(struct st_ram_io))) { + kfree(adgl); + return -EFAULT; + } - /* - * FIXME: user can flood the console using bogus ioctls - */ + IndexCard = adgl->num_card-1; - if (cmd != 0 && cmd != 6 && ((IndexCard >= MAX_BOARD) || !apbs[IndexCard].RamIO)) { - printk("APPLICOM driver IOCTL, bad board number %d\n", (int) IndexCard + 1); - printk("apbs[%d].RamIO = %lx\n", IndexCard, apbs[IndexCard].RamIO); + if(cmd != 0 && cmd != 6 && + ((IndexCard >= MAX_BOARD) || !apbs[IndexCard].RamIO)) { + static int warncount = 10; + if (warncount) { + printk( KERN_WARNING "APPLICOM driver IOCTL, bad board number %d\n",(int)IndexCard+1); + warncount--; + } + kfree(adgl); return -EINVAL; } - /* - * FIXME races between ioctls with multiple clients - */ - switch (cmd) { + case 0: pmem = apbs[IndexCard].RamIO; for (i = 0; i < sizeof(struct st_ram_io); i++) - TmpRamIo[i] = readb(pmem++); - if (copy_to_user((void *) arg, TmpRamIo, sizeof(struct st_ram_io))) - return -EFAULT; + ((unsigned char *)adgl)[i]=readb(pmem++); + if (copy_to_user((void *)arg, adgl, sizeof(struct st_ram_io))) + ret = -EFAULT; break; case 1: pmem = apbs[IndexCard].RamIO + CONF_END_TEST; for (i = 0; i < 4; i++) - adgl.conf_end_test[i] = readb(pmem++); + adgl->conf_end_test[i] = readb(pmem++); for (i = 0; i < 2; i++) - adgl.error_code[i] = readb(pmem++); + adgl->error_code[i] = readb(pmem++); for (i = 0; i < 4; i++) - adgl.parameter_error[i] = readb(pmem++); + adgl->parameter_error[i] = readb(pmem++); pmem = apbs[IndexCard].RamIO + VERS; - adgl.vers = readb(pmem); + adgl->vers = readb(pmem); pmem = apbs[IndexCard].RamIO + TYPE_CARD; for (i = 0; i < 20; i++) - adgl.reserv1[i] = readb(pmem++); - *(int *) &adgl.reserv1[20] = (readb(apbs[IndexCard].RamIO + SERIAL_NUMBER) << 16) + (readb(apbs[IndexCard].RamIO + SERIAL_NUMBER + 1) << 8) + (readb(apbs[IndexCard].RamIO + SERIAL_NUMBER + 2)); + adgl->reserv1[i] = readb(pmem++); + *(int *)&adgl->reserv1[20] = + (readb(apbs[IndexCard].RamIO + SERIAL_NUMBER) << 16) + + (readb(apbs[IndexCard].RamIO + SERIAL_NUMBER + 1) << 8) + + (readb(apbs[IndexCard].RamIO + SERIAL_NUMBER + 2) ); - if (copy_to_user((void *) arg, &adgl, sizeof(struct st_ram_io))) - return -EFAULT; + if (copy_to_user((void *)arg, adgl, sizeof(struct st_ram_io))) + ret = -EFAULT; break; case 2: pmem = apbs[IndexCard].RamIO + CONF_END_TEST; for (i = 0; i < 10; i++) writeb(0xff, pmem++); - writeb(adgl.data_from_pc_ready, apbs[IndexCard].RamIO + DATA_FROM_PC_READY); + writeb(adgl->data_from_pc_ready, + apbs[IndexCard].RamIO + DATA_FROM_PC_READY); writeb(1, apbs[IndexCard].RamIO + RAM_IT_FROM_PC); - /* - * FIXME: can trash waitqueue that is active. - */ -#if LINUX_VERSION_CODE > 0x20300 - init_waitqueue_head(&FlagSleepRec); -#else - FlagSleepRec = NULL; -#endif for (i = 0; i < MAX_BOARD; i++) { if (apbs[i].RamIO) { -#if LINUX_VERSION_CODE > 0x20300 - init_waitqueue_head(&apbs[i].FlagSleepSend); -#else - apbs[i].FlagSleepSend = NULL; -#endif byte_reset_it = readb(apbs[i].RamIO + RAM_IT_TO_PC); } } break; case 3: pmem = apbs[IndexCard].RamIO + TIC_DES_FROM_PC; - writeb(adgl.tic_des_from_pc, pmem); + writeb(adgl->tic_des_from_pc, pmem); break; case 4: pmem = apbs[IndexCard].RamIO + TIC_OWNER_TO_PC; - adgl.tic_owner_to_pc = readb(pmem++); - adgl.numcard_owner_to_pc = readb(pmem); - if (copy_to_user((void *) arg, &adgl, sizeof(struct st_ram_io))) - return -EFAULT; + adgl->tic_owner_to_pc = readb(pmem++); + adgl->numcard_owner_to_pc = readb(pmem); + if (copy_to_user((void *)arg, adgl,sizeof(struct st_ram_io))) + ret = -EFAULT; break; case 5: - writeb(adgl.num_card, apbs[IndexCard].RamIO + NUMCARD_OWNER_TO_PC); - writeb(adgl.num_card, apbs[IndexCard].RamIO + NUMCARD_DES_FROM_PC); - writeb(adgl.num_card, apbs[IndexCard].RamIO + NUMCARD_ACK_FROM_PC); + writeb(adgl->num_card, apbs[IndexCard].RamIO + NUMCARD_OWNER_TO_PC); + writeb(adgl->num_card, apbs[IndexCard].RamIO + NUMCARD_DES_FROM_PC); + writeb(adgl->num_card, apbs[IndexCard].RamIO + NUMCARD_ACK_FROM_PC); writeb(4, apbs[IndexCard].RamIO + DATA_FROM_PC_READY); writeb(1, apbs[IndexCard].RamIO + RAM_IT_FROM_PC); break; case 6: - printk(KERN_INFO "APPLICOM driver release .... V2.8.0\n"); + printk(KERN_INFO "APPLICOM driver release .... V2.8.0 ($Revision: 1.30 $)\n"); printk(KERN_INFO "Number of installed boards . %d\n", (int) numboards); printk(KERN_INFO "Segment of board ........... %X\n", (int) mem); printk(KERN_INFO "Interrupt IRQ number ....... %d\n", (int) irq); @@ -723,16 +800,20 @@ if (!apbs[i].RamIO) continue; - for (serial = 0; serial < SERIAL_NUMBER - TYPE_CARD; serial++) boardname[serial] = readb(apbs[i].RamIO + TYPE_CARD + serial); boardname[serial] = 0; - - printk(KERN_INFO "Prom version board %d ....... V%d.%d %s", i + 1, (int) (readb(apbs[IndexCard].RamIO + VERS) >> 4), (int) (readb(apbs[IndexCard].RamIO + VERS) & 0xF), boardname); + printk(KERN_INFO "Prom version board %d ....... V%d.%d %s", + i+1, + (int)(readb(apbs[IndexCard].RamIO + VERS) >> 4), + (int)(readb(apbs[IndexCard].RamIO + VERS) & 0xF), + boardname); - serial = (readb(apbs[i].RamIO + SERIAL_NUMBER) << 16) + (readb(apbs[i].RamIO + SERIAL_NUMBER + 1) << 8) + (readb(apbs[i].RamIO + SERIAL_NUMBER + 2)); + serial = (readb(apbs[i].RamIO + SERIAL_NUMBER) << 16) + + (readb(apbs[i].RamIO + SERIAL_NUMBER + 1) << 8) + + (readb(apbs[i].RamIO + SERIAL_NUMBER + 2) ); if (serial != 0) printk(" S/N %d\n", serial); @@ -746,18 +827,19 @@ if (WriteErrorCount != 0) printk(KERN_INFO "WriteErrorCount ............ %d\n", WriteErrorCount); if (waitqueue_active(&FlagSleepRec)) - printk("Process in read pending\n"); + printk(KERN_INFO "Process in read pending\n"); for (i = 0; i < MAX_BOARD; i++) { if (apbs[i].RamIO && waitqueue_active(&apbs[i].FlagSleepSend)) - printk("Process in write pending board %d\n", i + 1); + printk(KERN_INFO "Process in write pending board %d\n",i+1); } break; default: - printk("APPLICOM driver ioctl, unknown function code %d\n", cmd); - return -EINVAL; + printk(KERN_INFO "APPLICOM driver ioctl, unknown function code %d\n",cmd) ; + ret = -EINVAL; break; } Dummy = readb(apbs[IndexCard].RamIO + VERS); + kfree(adgl); return 0; } @@ -773,7 +855,7 @@ } if (ints[0] < 2) { - printk("applicom numargs: %d\n", ints[0]); + printk(KERN_INFO"applicom numargs: %d\n", ints[0]); return 0; } @@ -782,7 +864,7 @@ return 1; } -#if LINUX_VERSION_CODE > 0x20300 __setup("applicom=", applicom_setup); -#endif + #endif /* MODULE */ + diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/char/bttv.c linux/drivers/char/bttv.c --- v2.3.99-pre3/linux/drivers/char/bttv.c Mon Mar 27 08:08:23 2000 +++ linux/drivers/char/bttv.c Sun Apr 2 15:32:49 2000 @@ -490,7 +490,8 @@ bttv_bit_setscl(btv,1); bttv_bit_setsda(btv,1); - return i2c_bit_add_bus(&btv->i2c_adap); + btv->i2c_ok = i2c_bit_add_bus(&btv->i2c_adap); + return btv->i2c_ok; } /* read I2C */ @@ -498,6 +499,8 @@ { unsigned char buffer = 0; + if (0 != btv->i2c_ok) + return -1; if (verbose && NULL != probe_for) printk(KERN_INFO "bttv%d: i2c: checking for %s @ 0x%02x... ", btv->nr,probe_for,addr); @@ -523,11 +526,13 @@ unsigned char buffer[2]; int bytes = both ? 2 : 1; + if (0 != btv->i2c_ok) + return -1; btv->i2c_client.addr = addr >> 1; buffer[0] = b1; buffer[1] = b2; if (bytes != i2c_master_send(&btv->i2c_client, buffer, bytes)) - return -1; + return -1; return 0; } @@ -702,42 +707,25 @@ /* ----------------------------------------------------------------------- */ -/* for some vendors it is just the PCI ID */ -static struct VENDOR { - int id; - char *name; -} vendors[] = { - { 0x0001, "ATI Technologies Inc" }, - { 0x10b4, "STB Systems Inc" }, - { 0x1118, "Terratec" }, - { 0x13eb, "Hauppauge Computer Works Inc" }, - { 0x1461, "Avermedia" }, - { 0x1850, "Chronos" }, - { 0x1852, "Typhoon" }, - { 0x3000, "Askey" }, - { 0x3002, "Askey" }, - { 0x6606, "Leadtek" }, - { -1, NULL } -}; - static struct CARD { - int vid; - int id; + unsigned id; int cardnr; char *name; } cards[] = { - { 0x0001, 0x1002, BTTV_HAUPPAUGE878, "TV Wonder" }, - { 0x10b4, 0x2636, BTTV_HAUPPAUGE878, "???" }, - { 0x1118, 0x153b, BTTV_TERRATVALUE, "TV Value" }, - { 0x13eb, 0x0070, BTTV_HAUPPAUGE878, "WinTV" }, - { 0x1461, 0x0002, BTTV_AVERMEDIA98, "TVCapture 98" }, - { 0x1850, 0x1851, BTTV_CHRONOS_VS2, "Video Shuttle II" }, - { 0x1852, 0x1852, BTTV_TYPHOON_TVIEW, "TView TV/FM Tuner" }, - { 0x3000, 0x14ff, BTTV_MAGICTVIEW061, "TView 99" }, - { 0x3002, 0x144f, BTTV_MAGICTVIEW061, "Magic TView" }, - { 0x3002, 0x14ff, BTTV_PHOEBE_TVMAS, "TV Master" }, - { 0x6606, 0x217d, BTTV_WINFAST2000, "WinFast TV 2000" }, - { -1, -1, -1, NULL } + { 0x00011002, BTTV_HAUPPAUGE878, "ATI TV Wonder" }, + { 0x00031461, BTTV_AVERMEDIA98, "AVerMedia TVPhone98" }, + { 0x10b42636, BTTV_HAUPPAUGE878, "STB ???" }, + { 0x1118153b, BTTV_TERRATVALUE, "Terratec TV Value" }, + { 0x13eb0070, BTTV_HAUPPAUGE878, "Hauppauge WinTV" }, + { 0x14610002, BTTV_AVERMEDIA98, "Avermedia TVCapture 98" }, + { 0x18501851, BTTV_CHRONOS_VS2, "Chronos Video Shuttle II" }, + { 0x18521852, BTTV_TYPHOON_TVIEW, "Typhoon TView TV/FM Tuner" }, + { 0x3000144f, BTTV_MAGICTVIEW063, "TView 99 (CPH063)" }, + { 0x300014ff, BTTV_MAGICTVIEW061, "TView 99 (CPH061)" }, + { 0x3002144f, BTTV_MAGICTVIEW061, "Askey Magic TView" }, + { 0x300214ff, BTTV_PHOEBE_TVMAS, "Phoebe TV Master" }, + { 0x6606217d, BTTV_WINFAST2000, "Leadtek WinFast TV 2000" }, + { 0, -1, NULL } }; struct tvcard @@ -869,7 +857,7 @@ 1,1,1,1,0 }, { "FlyVideo 98", 3, 1, 0, 2, 0x8dff00, {2, 3, 1, 1}, - { 0, 0x8dff00, 0x800, 0x400, 0x8dff00, 0 },0, + { 0, 0x8dff00, 0x8df700, 0x8de700, 0x8dff00, 0 },0, 1,1,1,1,0 }, { "iProTV", 3, 1, 0, 2, 1, { 2, 3, 1, 1}, { 1, 0, 0, 0, 0 },0, @@ -893,9 +881,12 @@ { "Typhoon TView TV/FM Tuner", 3, 3, 0, 2, 0x1800, { 2, 3, 1, 1}, { 0, 0x800, 0, 0, 0x1800, 0 },0, 1,1,1,1,0 }, - { "PixelView PlayTV pro", - 3, 1, 0, 2, 0xff, { 2, 3, 1, 1 }, - { 0x21, 0x20, 0x24, 0x2c, 0x29, 0x29 }, 0 } + { "PixelView PlayTV pro", + 3, 1, 0, 2, 0xff, { 2, 3, 1, 1 }, + { 0x21, 0x20, 0x24, 0x2c, 0x29, 0x29 }, 0 }, + { "TView99 CPH063", + 3, 1, 0, 2, 0x551e00, { 2, 0, 1, 1}, + { 0x551400, 0x551200, 0, 0, 0x551200 }, 0,1,1,1,1,0 }, }; #define TVCARDS (sizeof(tvcards)/sizeof(struct tvcard)) @@ -920,39 +911,35 @@ static int idcard_eeprom(struct bttv *btv) { - int i,id1,id2,n1,n2; + unsigned id; + int i,n; - id1 = (eeprom_data[254] << 8) | (eeprom_data[255]); - id2 = (eeprom_data[252] << 8) | (eeprom_data[253]); - if (id1 == 0 || id1 == 0xffff || - id2 == 0 || id2 == 0xffff) - return -1; + id = (eeprom_data[252] << 24) | + (eeprom_data[253] << 16) | + (eeprom_data[254] << 8) | + (eeprom_data[255]); + if (id == 0 || id == 0xffffffff) + return -1; /* look for the card */ - n1 = -1; n2 = -1; - for (i = 0; vendors[i].id != -1; i++) - if (vendors[i].id == id2) - n2 = i; - for (i = 0; cards[i].id != -1; i++) - if (cards[i].id == id1 && - cards[i].vid == id2) - n1 = i; + for (n = -1, i = 0; cards[i].id != 0; i++) + if (cards[i].id == id) + n = i; - if (n1 != -1 && n2 != -1) { + if (n != -1) { /* found it */ - printk(KERN_INFO "bttv%d: id: %s (0x%04x), vendor: %s (0x%04x)\n", - btv->nr,cards[n1].name,id1,vendors[n2].name,id2); + printk(KERN_INFO "bttv%d: id: %s (0x%08x)\n", + btv->nr,cards[n].name,id); if (verbose) printk(KERN_INFO "bttv%d: => card=%d (%s)\n", - btv->nr,cards[n1].cardnr, - tvcards[cards[n1].cardnr].name); - return cards[n1].cardnr; + btv->nr,cards[n].cardnr, + tvcards[cards[n].cardnr].name); + return cards[n].cardnr; } else { /* 404 */ - printk(KERN_INFO "bttv%d: id: %s (0x%04x), vendor: %s (0x%04x)\n", - btv->nr, "unknown", id1, - (n2 != -1) ? vendors[n2].name : "unknown", id2); - printk(KERN_INFO "please mail id + vendor, board name and " + printk(KERN_INFO "bttv%d: id: unknown (0x%08x)\n", + btv->nr, id); + printk(KERN_INFO "please mail id, board name and " "the correct card= insmod option to " "kraxel@goldbach.in-berlin.de\n"); return -1; @@ -1670,30 +1657,48 @@ * www.brooktree.com - nicely done those folks. */ -/* set geometry for even/odd frames - just if you are wondering: - handling of even and odd frames will be separated, e.g. for grabbing - the even ones as RGB into videomem and the others as YUV in main memory for - compressing and sending to the video conferencing partner. - -*/ -static inline void bt848_set_eogeo(struct bttv *btv, int odd, u8 vtc, - u16 hscale, u16 vscale, - u16 hactive, u16 vactive, - u16 hdelay, u16 vdelay, - u8 crop) +static inline void bt848_set_eogeo(struct bttv *btv, struct tvnorm *tvn, + int odd, int width, int height) { + u16 vscale, hscale; + u32 xsf, sr; + u16 hdelay; + u8 crop, vtc; + int inter = (height>tvn->sheight/2) ? 0 : 1; int off = odd ? 0x80 : 0x00; - + + xsf = (width*tvn->scaledtwidth)/tvn->swidth; + hscale = ((tvn->totalwidth*4096UL)/xsf-4096); + hdelay = tvn->hdelayx1; + hdelay = (hdelay*width)/tvn->swidth; + hdelay &= 0x3fe; + sr=((tvn->sheight>>inter)*512)/height-512; + vscale=(0x10000UL-sr)&0x1fff; + crop=((width>>8)&0x03)|((hdelay>>6)&0x0c)| + ((tvn->sheight>>4)&0x30)|((tvn->vdelay>>2)&0xc0); + vscale |= inter ? (BT848_VSCALE_INT<<8) : 0; + +#if 0 + /* Some people say interpolation looks bad ... */ + vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0); + if (width < 767) + btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off); + else + btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off); +#else + vtc = 0; + btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off); +#endif + btwrite(vtc, BT848_E_VTC+off); btwrite(hscale>>8, BT848_E_HSCALE_HI+off); btwrite(hscale&0xff, BT848_E_HSCALE_LO+off); btaor((vscale>>8), 0xe0, BT848_E_VSCALE_HI+off); btwrite(vscale&0xff, BT848_E_VSCALE_LO+off); - btwrite(hactive&0xff, BT848_E_HACTIVE_LO+off); + btwrite(width&0xff, BT848_E_HACTIVE_LO+off); btwrite(hdelay&0xff, BT848_E_HDELAY_LO+off); - btwrite(vactive&0xff, BT848_E_VACTIVE_LO+off); - btwrite(vdelay&0xff, BT848_E_VDELAY_LO+off); + btwrite(tvn->sheight&0xff, BT848_E_VACTIVE_LO+off); + btwrite(tvn->vdelay&0xff, BT848_E_VDELAY_LO+off); btwrite(crop, BT848_E_CROP+off); } @@ -1701,14 +1706,8 @@ static void bt848_set_geo(struct bttv *btv, int no_irq_context) { - u16 vscale, hscale; - u32 xsf, sr; u16 ewidth, eheight, owidth, oheight; u16 format, bswap; - u16 hdelay; - u16 hactive; - u16 inter; - u8 crop, vtc; struct tvnorm *tvn; unsigned long flags; @@ -1727,10 +1726,6 @@ if (no_irq_context) set_pll(btv); - vtc=0; - /* Some people say interpolation looks bad ... */ - /* vtc = (hactive < 193) ? 2 : ((hactive < 385) ? 1 : 0); */ - btv->win.interlace = (btv->win.height>tvn->sheight/2) ? 1 : 0; if (0 == btv->risc_cap_odd && @@ -1762,40 +1757,11 @@ eheight = btv->gbuf[btv->gq_grab].height; format = btv->gbuf[btv->gq_grab].fmt; bswap = 0; - inter = (btv->win.height>tvn->sheight/2) ? 0 : 1; } - inter = (oheight>tvn->sheight/2) ? 0 : 1; - - /* odd field */ - hactive=owidth; - xsf = (hactive*tvn->scaledtwidth)/tvn->swidth; - hscale = ((tvn->totalwidth*4096UL)/xsf-4096); - hdelay = tvn->hdelayx1; - hdelay = (hdelay*hactive)/tvn->swidth; - hdelay &= 0x3fe; - sr=((tvn->sheight>>inter)*512)/oheight-512; - vscale=(0x10000UL-sr)&0x1fff; - crop=((hactive>>8)&0x03)|((hdelay>>6)&0x0c)| - ((tvn->sheight>>4)&0x30)|((tvn->vdelay>>2)&0xc0); - vscale |= btv->win.interlace ? (BT848_VSCALE_INT<<8) : 0; - bt848_set_eogeo(btv, 1, vtc, hscale, vscale, hactive, tvn->sheight, - hdelay, tvn->vdelay, crop); - - /* even field */ - hactive=ewidth; - xsf = (hactive*tvn->scaledtwidth)/tvn->swidth; - hscale = ((tvn->totalwidth*4096UL)/xsf-4096); - hdelay = tvn->hdelayx1; - hdelay = (hdelay*hactive)/tvn->swidth; - hdelay &= 0x3fe; - sr=((tvn->sheight>>inter)*512)/eheight-512; - vscale=(0x10000UL-sr)&0x1fff; - crop=((hactive>>8)&0x03)|((hdelay>>6)&0x0c)| - ((tvn->sheight>>4)&0x30)|((tvn->vdelay>>2)&0xc0); - vscale |= btv->win.interlace ? (BT848_VSCALE_INT<<8) : 0; - bt848_set_eogeo(btv, 0, vtc, hscale, vscale, hactive, tvn->sheight, - hdelay, tvn->vdelay, crop); + /* program odd + even fields */ + bt848_set_eogeo(btv, tvn, 1, owidth, oheight); + bt848_set_eogeo(btv, tvn, 0, ewidth, eheight); btwrite(format, BT848_COLOR_FMT); btwrite(bswap | BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL); @@ -1897,8 +1863,8 @@ make_vrisctab(btv, ro, re, vbuf, mp->width, mp->height, mp->format); if (debug) - printk("bttv%d: cap vgrab: queue %d (%dx%d)\n", - btv->nr,mp->frame,mp->width,mp->height); + printk("bttv%d: cap vgrab: queue %d (%d:%dx%d)\n", + btv->nr,mp->frame,mp->format,mp->width,mp->height); cli(); btv->gbuf[mp->frame].stat = GBUFFER_GRABBING; btv->gbuf[mp->frame].fmt = palette2fmt[mp->format]; @@ -1914,10 +1880,6 @@ #endif if (btv->gq_in == btv->gq_out) { - if(mp->format>=VIDEO_PALETTE_COMPONENT) { - btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI); - btor(BT848_VSCALE_COMB, BT848_O_VSCALE_HI); - } btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ); } btv->gqueue[btv->gq_in++] = mp->frame; @@ -2317,7 +2279,7 @@ btv->win.height=vw.height; bt848_set_risc_jmps(btv,0); - + bt848_set_winsize(btv); up(&btv->lock); @@ -2573,10 +2535,8 @@ if (debug) printk("bttv%d: cap sync: sleep on %d\n",btv->nr,i); interruptible_sleep_on(&btv->capq); - if(signal_pending(current)) { - ret = -EINTR; - break; - } + if(signal_pending(current)) + return -EINTR; } /* fall throuth */ case GBUFFER_DONE: @@ -2649,9 +2609,6 @@ else vu.radio=VIDEO_NO_UNIT; vu.audio=VIDEO_NO_UNIT; -#if 0 - AUDIO(AUDC_GET_UNIT, &vu.audio); -#endif vu.teletext=VIDEO_NO_UNIT; if(copy_to_user((void *)arg, (void *)&vu, sizeof(vu))) return -EFAULT; @@ -3054,17 +3011,6 @@ } } -#if 0 -#warning please use tda8425.c instead -static void init_tda8425(struct bttv *btv) -{ - I2CWrite(btv, I2C_TDA8425, TDA8425_VL, 0xFC, 1); /* volume left 0dB */ - I2CWrite(btv, I2C_TDA8425, TDA8425_VR, 0xFC, 1); /* volume right 0dB */ - I2CWrite(btv, I2C_TDA8425, TDA8425_BA, 0xF6, 1); /* bass 0dB */ - I2CWrite(btv, I2C_TDA8425, TDA8425_TR, 0xF6, 1); /* treble 0dB */ - I2CWrite(btv, I2C_TDA8425, TDA8425_S1, 0xCE, 1); /* mute off */ -} -#endif /* can tda9855.c handle this too maybe? */ static void init_tda9840(struct bttv *btv) @@ -3164,6 +3110,7 @@ btv->type == BTTV_PIXVIEWPLAYTV || btv->type == BTTV_AVERMEDIA98 || btv->type == BTTV_MAGICTVIEW061 || + btv->type == BTTV_MAGICTVIEW063 || btv->type == BTTV_CHRONOS_VS2 || btv->type == BTTV_TYPHOON_TVIEW || btv->type == BTTV_PXELVWPLTVPRO || @@ -3600,8 +3547,6 @@ btv->risc_cap_odd = 0; btv->risc_cap_even = 0; bt848_set_risc_jmps(btv,-1); - btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI); - btand(~BT848_VSCALE_COMB, BT848_O_VSCALE_HI); bt848_set_geo(btv,0); btwrite(btv->fb_color_ctl | BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL); diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/char/bttv.h linux/drivers/char/bttv.h --- v2.3.99-pre3/linux/drivers/char/bttv.h Mon Mar 27 08:08:23 2000 +++ linux/drivers/char/bttv.h Sun Apr 2 15:32:49 2000 @@ -21,7 +21,7 @@ #ifndef _BTTV_H_ #define _BTTV_H_ -#define BTTV_VERSION_CODE KERNEL_VERSION(0,7,24) +#define BTTV_VERSION_CODE KERNEL_VERSION(0,7,25) #include #include @@ -138,7 +138,7 @@ struct i2c_adapter i2c_adap; struct i2c_algo_bit_data i2c_algo; struct i2c_client i2c_client; - int i2c_state; + int i2c_state, i2c_ok; struct i2c_client *i2c_clients[I2C_CLIENTS_MAX]; int tuner_type; @@ -270,6 +270,7 @@ #define BTTV_CHRONOS_VS2 0x23 #define BTTV_TYPHOON_TVIEW 0x24 #define BTTV_PXELVWPLTVPRO 0x25 +#define BTTV_MAGICTVIEW063 0x26 #define AUDIO_TUNER 0x00 diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/char/console.c linux/drivers/char/console.c --- v2.3.99-pre3/linux/drivers/char/console.c Tue Mar 14 19:10:39 2000 +++ linux/drivers/char/console.c Sun Apr 2 15:20:27 2000 @@ -121,8 +121,6 @@ #define DEFAULT_BELL_PITCH 750 #define DEFAULT_BELL_DURATION (HZ/8) -extern int tty_register_devfs (struct tty_driver *driver, unsigned int flags, - unsigned int minor); extern void vcs_make_devfs (unsigned int index, int unregister); #ifndef MIN diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/char/cpia.c linux/drivers/char/cpia.c --- v2.3.99-pre3/linux/drivers/char/cpia.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/cpia.c Mon Mar 27 10:22:31 2000 @@ -0,0 +1,3319 @@ +/* + * cpia CPiA driver + * + * Supports CPiA based Video Camera's. + * + * (C) Copyright 1999-2000 Peter Pregler, + * (C) Copyright 1999-2000 Scott J. Bertin, + * (C) Copyright 1999-2000 Johannes Erdfelt, jerdfelt@valinux.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. + */ + +/* #define _CPIA_DEBUG_ define for verbose debug output */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_KMOD +#include +#endif + +#include "cpia.h" + +#ifdef CONFIG_VIDEO_CPIA_PP +extern int cpia_pp_init(void); +#endif +#ifdef CONFIG_VIDEO_CPIA_USB +extern int cpia_usb_init(void); +#endif + +#ifdef MODULE +MODULE_AUTHOR("Scott J. Bertin & Peter Pregler & Johannes Erdfelt "); +MODULE_DESCRIPTION("V4L-driver for Vision CPiA based cameras"); +MODULE_SUPPORTED_DEVICE("video"); +#endif + +#define ABOUT "V4L-Driver for Vision CPiA based cameras" + +#ifndef VID_HARDWARE_CPIA +#define VID_HARDWARE_CPIA 24 /* FIXME -> from linux/videodev.h */ +#endif + +#define CPIA_MODULE_CPIA (0<<5) +#define CPIA_MODULE_SYSTEM (1<<5) +#define CPIA_MODULE_VP_CTRL (5<<5) +#define CPIA_MODULE_CAPTURE (6<<5) +#define CPIA_MODULE_DEBUG (7<<5) + +#define INPUT (DATA_IN << 8) +#define OUTPUT (DATA_OUT << 8) + +#define CPIA_COMMAND_GetCPIAVersion (INPUT | CPIA_MODULE_CPIA | 1) +#define CPIA_COMMAND_GetPnPID (INPUT | CPIA_MODULE_CPIA | 2) +#define CPIA_COMMAND_GetCameraStatus (INPUT | CPIA_MODULE_CPIA | 3) +#define CPIA_COMMAND_GotoHiPower (OUTPUT | CPIA_MODULE_CPIA | 4) +#define CPIA_COMMAND_GotoLoPower (OUTPUT | CPIA_MODULE_CPIA | 5) +#define CPIA_COMMAND_GotoSuspend (OUTPUT | CPIA_MODULE_CPIA | 7) +#define CPIA_COMMAND_GotoPassThrough (OUTPUT | CPIA_MODULE_CPIA | 8) +#define CPIA_COMMAND_ModifyCameraStatus (OUTPUT | CPIA_MODULE_CPIA | 10) + +#define CPIA_COMMAND_ReadVCRegs (INPUT | CPIA_MODULE_SYSTEM | 1) +#define CPIA_COMMAND_WriteVCReg (OUTPUT | CPIA_MODULE_SYSTEM | 2) +#define CPIA_COMMAND_ReadMCPorts (INPUT | CPIA_MODULE_SYSTEM | 3) +#define CPIA_COMMAND_WriteMCPort (OUTPUT | CPIA_MODULE_SYSTEM | 4) +#define CPIA_COMMAND_SetBaudRate (OUTPUT | CPIA_MODULE_SYSTEM | 5) +#define CPIA_COMMAND_SetECPTiming (OUTPUT | CPIA_MODULE_SYSTEM | 6) +#define CPIA_COMMAND_ReadIDATA (INPUT | CPIA_MODULE_SYSTEM | 7) +#define CPIA_COMMAND_WriteIDATA (OUTPUT | CPIA_MODULE_SYSTEM | 8) +#define CPIA_COMMAND_GenericCall (OUTPUT | CPIA_MODULE_SYSTEM | 9) +#define CPIA_COMMAND_I2CStart (OUTPUT | CPIA_MODULE_SYSTEM | 10) +#define CPIA_COMMAND_I2CStop (OUTPUT | CPIA_MODULE_SYSTEM | 11) +#define CPIA_COMMAND_I2CWrite (OUTPUT | CPIA_MODULE_SYSTEM | 12) +#define CPIA_COMMAND_I2CRead (INPUT | CPIA_MODULE_SYSTEM | 13) + +#define CPIA_COMMAND_GetVPVersion (INPUT | CPIA_MODULE_VP_CTRL | 1) +#define CPIA_COMMAND_SetColourParams (OUTPUT | CPIA_MODULE_VP_CTRL | 3) +#define CPIA_COMMAND_SetExposure (OUTPUT | CPIA_MODULE_VP_CTRL | 4) +#define CPIA_COMMAND_SetColourBalance (OUTPUT | CPIA_MODULE_VP_CTRL | 6) +#define CPIA_COMMAND_SetSensorFPS (OUTPUT | CPIA_MODULE_VP_CTRL | 7) +#define CPIA_COMMAND_SetVPDefaults (OUTPUT | CPIA_MODULE_VP_CTRL | 8) +#define CPIA_COMMAND_SetApcor (OUTPUT | CPIA_MODULE_VP_CTRL | 9) +#define CPIA_COMMAND_SetFlickerCtrl (OUTPUT | CPIA_MODULE_VP_CTRL | 10) +#define CPIA_COMMAND_SetVLOffset (OUTPUT | CPIA_MODULE_VP_CTRL | 11) +#define CPIA_COMMAND_GetColourParams (INPUT | CPIA_MODULE_VP_CTRL | 16) +#define CPIA_COMMAND_GetColourBalance (INPUT | CPIA_MODULE_VP_CTRL | 17) +#define CPIA_COMMAND_GetExposure (INPUT | CPIA_MODULE_VP_CTRL | 18) +#define CPIA_COMMAND_SetSensorMatrix (OUTPUT | CPIA_MODULE_VP_CTRL | 19) +#define CPIA_COMMAND_ColourBars (OUTPUT | CPIA_MODULE_VP_CTRL | 25) +#define CPIA_COMMAND_ReadVPRegs (INPUT | CPIA_MODULE_VP_CTRL | 30) +#define CPIA_COMMAND_WriteVPReg (OUTPUT | CPIA_MODULE_VP_CTRL | 31) + +#define CPIA_COMMAND_GrabFrame (OUTPUT | CPIA_MODULE_CAPTURE | 1) +#define CPIA_COMMAND_UploadFrame (OUTPUT | CPIA_MODULE_CAPTURE | 2) +#define CPIA_COMMAND_SetGrabMode (OUTPUT | CPIA_MODULE_CAPTURE | 3) +#define CPIA_COMMAND_InitStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 4) +#define CPIA_COMMAND_FiniStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 5) +#define CPIA_COMMAND_StartStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 6) +#define CPIA_COMMAND_EndStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 7) +#define CPIA_COMMAND_SetFormat (OUTPUT | CPIA_MODULE_CAPTURE | 8) +#define CPIA_COMMAND_SetROI (OUTPUT | CPIA_MODULE_CAPTURE | 9) +#define CPIA_COMMAND_SetCompression (OUTPUT | CPIA_MODULE_CAPTURE | 10) +#define CPIA_COMMAND_SetCompressionTarget (OUTPUT | CPIA_MODULE_CAPTURE | 11) +#define CPIA_COMMAND_SetYUVThresh (OUTPUT | CPIA_MODULE_CAPTURE | 12) +#define CPIA_COMMAND_SetCompressionParams (OUTPUT | CPIA_MODULE_CAPTURE | 13) +#define CPIA_COMMAND_DiscardFrame (OUTPUT | CPIA_MODULE_CAPTURE | 14) + +#define CPIA_COMMAND_OutputRS232 (OUTPUT | CPIA_MODULE_DEBUG | 1) +#define CPIA_COMMAND_AbortProcess (OUTPUT | CPIA_MODULE_DEBUG | 4) +#define CPIA_COMMAND_SetDramPage (OUTPUT | CPIA_MODULE_DEBUG | 5) +#define CPIA_COMMAND_StartDramUpload (OUTPUT | CPIA_MODULE_DEBUG | 6) +#define CPIA_COMMAND_StartDummyDtream (OUTPUT | CPIA_MODULE_DEBUG | 8) +#define CPIA_COMMAND_AbortStream (OUTPUT | CPIA_MODULE_DEBUG | 9) +#define CPIA_COMMAND_DownloadDRAM (OUTPUT | CPIA_MODULE_DEBUG | 10) + +enum { + FRAME_READY, /* Ready to grab into */ + FRAME_GRABBING, /* In the process of being grabbed into */ + FRAME_DONE, /* Finished grabbing, but not been synced yet */ + FRAME_UNUSED, /* Unused (no MCAPTURE) */ +}; + +#define COMMAND_NONE 0x0000 +#define COMMAND_SETCOMPRESSION 0x0001 +#define COMMAND_SETCOMPRESSIONTARGET 0x0002 +#define COMMAND_SETCOLOURPARAMS 0x0004 +#define COMMAND_SETFORMAT 0x0008 +#define COMMAND_PAUSE 0x0010 +#define COMMAND_RESUME 0x0020 +#define COMMAND_SETYUVTHRESH 0x0040 +#define COMMAND_SETECPTIMING 0x0080 +#define COMMAND_SETCOMPRESSIONPARAMS 0x0100 +#define COMMAND_SETEXPOSURE 0x0200 +#define COMMAND_SETCOLOURBALANCE 0x0400 +#define COMMAND_SETSENSORFPS 0x0800 +#define COMMAND_SETAPCOR 0x1000 +#define COMMAND_SETFLICKERCTRL 0x2000 +#define COMMAND_SETVLOFFSET 0x4000 + +/* Developer's Guide Table 5 p 3-34 + * indexed by [mains][sensorFps.baserate][sensorFps.divisor]*/ +static u8 flicker_jumps[2][2][4] = +{ { { 76, 38, 19, 9 }, { 92, 46, 23, 11 } }, + { { 64, 32, 16, 8 }, { 76, 38, 19, 9} } +}; + +/* forward declaration of local function */ +static void reset_camera_struct(struct cam_data *cam); + +/********************************************************************** + * + * Memory management + * + * This is a shameless copy from the USB-cpia driver (linux kernel + * version 2.3.29 or so, I have no idea what this code actually does ;). + * Actually it seems to be a copy of a shameless copy of the bttv-driver. + * Or that is a copy of a shameless copy of ... (To the powers: is there + * no generic kernel-function to do this sort of stuff?) + * + * Yes, it was a shameless copy from the bttv-driver. IIRC, Alan says + * there will be one, but apparentely not yet - jerdfelt + * + **********************************************************************/ + +/* Given PGD from the address space's page table, return the kernel + * virtual mapping of the physical memory mapped at ADR. + */ +static inline unsigned long 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 = page_address(pte_page(pte)) | + (adr & (PAGE_SIZE-1)); + } + } + 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) +{ + unsigned long va, kva, ret; + + va = VMALLOC_VMADDR(adr); + kva = uvirt_to_kva(pgd_offset_k(va), va); + ret = __pa(kva); + return ret; +} + +static void *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(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; + } + + return mem; +} + +static void 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 = kvirt_to_pa(adr); + mem_map_unreserve(MAP_NR(__va(page))); + adr += PAGE_SIZE; + if (size > PAGE_SIZE) + size -= PAGE_SIZE; + else + size = 0; + } + vfree(mem); +} + +/********************************************************************** + * + * /proc interface + * + **********************************************************************/ +#ifdef CONFIG_PROC_FS +static struct proc_dir_entry *cpia_proc_root=NULL; + +static int cpia_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + char *out = page; + int len, tmp; + struct cam_data *cam = data; + char tmpstr[20]; + + /* IMPORTANT: This output MUST be kept under PAGE_SIZE + * or we need to get more sophisticated. */ + + out += sprintf(out, "read-only\n-----------------------\n"); + out += sprintf(out, "V4L Driver version: %d.%d.%d\n", + CPIA_MAJ_VER, CPIA_MIN_VER, CPIA_PATCH_VER); + out += sprintf(out, "CPIA Version: %d.%02d (%d.%d)\n", + cam->params.version.firmwareVersion, + cam->params.version.firmwareRevision, + cam->params.version.vcVersion, + cam->params.version.vcRevision); + out += sprintf(out, "CPIA PnP-ID: %04x:%04x:%04x\n", + cam->params.pnpID.vendor, cam->params.pnpID.product, + cam->params.pnpID.deviceRevision); + out += sprintf(out, "VP-Version: %d.%d %04x\n", + cam->params.vpVersion.vpVersion, + cam->params.vpVersion.vpRevision, + cam->params.vpVersion.cameraHeadID); + + out += sprintf(out, "system_state: %#04x\n", + cam->params.status.systemState); + out += sprintf(out, "grab_state: %#04x\n", + cam->params.status.grabState); + out += sprintf(out, "stream_state: %#04x\n", + cam->params.status.streamState); + out += sprintf(out, "fatal_error: %#04x\n", + cam->params.status.fatalError); + out += sprintf(out, "cmd_error: %#04x\n", + cam->params.status.cmdError); + out += sprintf(out, "debug_flags: %#04x\n", + cam->params.status.debugFlags); + out += sprintf(out, "vp_status: %#04x\n", + cam->params.status.vpStatus); + out += sprintf(out, "error_code: %#04x\n", + cam->params.status.errorCode); + out += sprintf(out, "video_size: %s\n", + cam->params.format.videoSize == VIDEOSIZE_CIF ? + "CIF " : "QCIF"); + out += sprintf(out, "sub_sample: %s\n", + cam->params.format.subSample == SUBSAMPLE_420 ? + "420" : "422"); + out += sprintf(out, "yuv_order: %s\n", + cam->params.format.yuvOrder == YUVORDER_YUYV ? + "YUYV" : "UYVY"); + out += sprintf(out, "roi: (%3d, %3d) to (%3d, %3d)\n", + cam->params.roi.colStart*8, + cam->params.roi.rowStart*4, + cam->params.roi.colEnd*8, + cam->params.roi.rowEnd*4); + out += sprintf(out, "actual_fps: %3d\n", cam->fps); + out += sprintf(out, "transfer_rate: %4dkB/s\n", + cam->transfer_rate); + + out += sprintf(out, "\nread-write\n"); + out += sprintf(out, "----------------------- current min" + " max default comment\n"); + out += sprintf(out, "brightness: %8d %8d %8d %8d\n", + cam->params.colourParams.brightness, 0, 100, 50); + if (cam->params.version.firmwareVersion == 1 && + cam->params.version.firmwareRevision == 2) + /* 1-02 firmware limits contrast to 80 */ + tmp = 80; + else + tmp = 96; + + out += sprintf(out, "contrast: %8d %8d %8d %8d" + " steps of 8\n", + cam->params.colourParams.contrast, 0, tmp, 48); + out += sprintf(out, "saturation: %8d %8d %8d %8d\n", + cam->params.colourParams.saturation, 0, 100, 50); + tmp = (25000+5000*cam->params.sensorFps.baserate)/ + (1<params.sensorFps.divisor); + out += sprintf(out, "sensor_fps: %4d.%03d %8d %8d %8d\n", + tmp/1000, tmp%1000, 3, 30, 15); + out += sprintf(out, "stream_start_line: %8d %8d %8d %8d\n", + 2*cam->params.streamStartLine, 0, + cam->params.format.videoSize == VIDEOSIZE_CIF ? 288:144, + cam->params.format.videoSize == VIDEOSIZE_CIF ? 240:120); + out += sprintf(out, "ecp_timing: %8s %8s %8s %8s\n", + cam->params.ecpTiming ? "slow" : "normal", "slow", + "normal", "normal"); + + if (cam->params.colourBalance.balanceModeIsAuto) { + sprintf(tmpstr, "auto"); + } else { + sprintf(tmpstr, "manual"); + } + out += sprintf(out, "color_balance_mode: %8s %8s %8s" + " %8s\n", tmpstr, "manual", "auto", "auto"); + out += sprintf(out, "red_gain: %8d %8d %8d %8d\n", + cam->params.colourBalance.redGain, 0, 212, 32); + out += sprintf(out, "green_gain: %8d %8d %8d %8d\n", + cam->params.colourBalance.greenGain, 0, 212, 6); + out += sprintf(out, "blue_gain: %8d %8d %8d %8d\n", + cam->params.colourBalance.blueGain, 0, 212, 92); + + if (cam->params.version.firmwareVersion == 1 && + cam->params.version.firmwareRevision == 2) + /* 1-02 firmware limits gain to 2 */ + sprintf(tmpstr, "%8d %8d", 1, 2); + else + sprintf(tmpstr, "1,2,4,8"); + + if (cam->params.exposure.gainMode == 0) + out += sprintf(out, "max_gain: unknown %18s" + " %8d\n", tmpstr, 2); + else + out += sprintf(out, "max_gain: %8d %18s %8d\n", + 1<<(cam->params.exposure.gainMode-1), tmpstr, 2); + + switch(cam->params.exposure.expMode) { + case 1: + case 3: + sprintf(tmpstr, "manual"); + break; + case 2: + sprintf(tmpstr, "auto"); + break; + default: + sprintf(tmpstr, "unknown"); + break; + } + out += sprintf(out, "exposure_mode: %8s %8s %8s" + " %8s\n", tmpstr, "manual", "auto", "auto"); + out += sprintf(out, "centre_weight: %8s %8s %8s %8s\n", + (2-cam->params.exposure.centreWeight) ? "on" : "off", + "off", "on", "on"); + out += sprintf(out, "gain: %8d %8d max_gain %8d 1,2,4,8 possible\n", + 1<params.exposure.gain, 1, 1); + if (cam->params.version.firmwareVersion == 1 && + cam->params.version.firmwareRevision == 2) + /* 1-02 firmware limits fineExp to 127 */ + tmp = 255; + else + tmp = 511; + + out += sprintf(out, "fine_exp: %8d %8d %8d %8d\n", + cam->params.exposure.fineExp*2, 0, tmp, 0); + if (cam->params.version.firmwareVersion == 1 && + cam->params.version.firmwareRevision == 2) + /* 1-02 firmware limits coarseExpHi to 0 */ + tmp = 255; + else + tmp = 65535; + + out += sprintf(out, "coarse_exp: %8d %8d %8d" + " %8d\n", cam->params.exposure.coarseExpLo+ + 256*cam->params.exposure.coarseExpHi, 0, tmp, 185); + out += sprintf(out, "red_comp: %8d %8d %8d %8d\n", + cam->params.exposure.redComp, 220, 255, 220); + out += sprintf(out, "green1_comp: %8d %8d %8d %8d\n", + cam->params.exposure.green1Comp, 214, 255, 214); + out += sprintf(out, "green2_comp: %8d %8d %8d %8d\n", + cam->params.exposure.green2Comp, 214, 255, 214); + out += sprintf(out, "blue_comp: %8d %8d %8d %8d\n", + cam->params.exposure.blueComp, 230, 255, 230); + + out += sprintf(out, "apcor_gain1: %#8x %#8x %#8x %#8x\n", + cam->params.apcor.gain1, 0, 0xff, 0x1c); + out += sprintf(out, "apcor_gain2: %#8x %#8x %#8x %#8x\n", + cam->params.apcor.gain2, 0, 0xff, 0x1a); + out += sprintf(out, "apcor_gain4: %#8x %#8x %#8x %#8x\n", + cam->params.apcor.gain4, 0, 0xff, 0x2d); + out += sprintf(out, "apcor_gain8: %#8x %#8x %#8x %#8x\n", + cam->params.apcor.gain8, 0, 0xff, 0x2a); + out += sprintf(out, "vl_offset_gain1: %8d %8d %8d %8d\n", + cam->params.vlOffset.gain1, 0, 255, 24); + out += sprintf(out, "vl_offset_gain2: %8d %8d %8d %8d\n", + cam->params.vlOffset.gain2, 0, 255, 28); + out += sprintf(out, "vl_offset_gain4: %8d %8d %8d %8d\n", + cam->params.vlOffset.gain4, 0, 255, 30); + out += sprintf(out, "vl_offset_gain8: %8d %8d %8d %8d\n", + cam->params.vlOffset.gain8, 0, 255, 30); + out += sprintf(out, "flicker_control: %8s %8s %8s %8s\n", + cam->params.flickerControl.flickerMode ? "on" : "off", + "off", "on", "off"); + out += sprintf(out, "mains_frequency: %8d %8d %8d %8d" + " only 50/60\n", + cam->mainsFreq ? 60 : 50, 50, 60, 50); + out += sprintf(out, "allowable_overexposure: %8d %8d %8d %8d\n", + cam->params.flickerControl.allowableOverExposure, 0, + 255, 0); + out += sprintf(out, "compression_mode: "); + switch(cam->params.compression.mode) { + case CPIA_COMPRESSION_NONE: + out += sprintf(out, "%8s", "none"); + break; + case CPIA_COMPRESSION_AUTO: + out += sprintf(out, "%8s", "auto"); + break; + case CPIA_COMPRESSION_MANUAL: + out += sprintf(out, "%8s", "manual"); + break; + default: + out += sprintf(out, "%8s", "unknown"); + break; + } + out += sprintf(out, " none,auto,manual auto\n"); + out += sprintf(out, "decimation_enable: %8s %8s %8s %8s\n", + cam->params.compression.decimation == + DECIMATION_ENAB ? "on":"off", "off", "off", + "off"); + out += sprintf(out, "compression_target: %9s %9s %9s %9s\n", + cam->params.compressionTarget.frTargeting == + CPIA_COMPRESSION_TARGET_FRAMERATE ? + "framerate":"quality", + "framerate", "quality", "quality"); + out += sprintf(out, "target_framerate: %8d %8d %8d %8d\n", + cam->params.compressionTarget.targetFR, 0, 30, 7); + out += sprintf(out, "target_quality: %8d %8d %8d %8d\n", + cam->params.compressionTarget.targetQ, 0, 255, 10); + out += sprintf(out, "y_threshold: %8d %8d %8d %8d\n", + cam->params.yuvThreshold.yThreshold, 0, 31, 15); + out += sprintf(out, "uv_threshold: %8d %8d %8d %8d\n", + cam->params.yuvThreshold.uvThreshold, 0, 31, 15); + out += sprintf(out, "hysteresis: %8d %8d %8d %8d\n", + cam->params.compressionParams.hysteresis, 0, 255, 3); + out += sprintf(out, "threshold_max: %8d %8d %8d %8d\n", + cam->params.compressionParams.threshMax, 0, 255, 11); + out += sprintf(out, "small_step: %8d %8d %8d %8d\n", + cam->params.compressionParams.smallStep, 0, 255, 1); + out += sprintf(out, "large_step: %8d %8d %8d %8d\n", + cam->params.compressionParams.largeStep, 0, 255, 3); + out += sprintf(out, "decimation_hysteresis: %8d %8d %8d %8d\n", + cam->params.compressionParams.decimationHysteresis, + 0, 255, 2); + out += sprintf(out, "fr_diff_step_thresh: %8d %8d %8d %8d\n", + cam->params.compressionParams.frDiffStepThresh, + 0, 255, 5); + out += sprintf(out, "q_diff_step_thresh: %8d %8d %8d %8d\n", + cam->params.compressionParams.qDiffStepThresh, + 0, 255, 3); + out += sprintf(out, "decimation_thresh_mod: %8d %8d %8d %8d\n", + cam->params.compressionParams.decimationThreshMod, + 0, 255, 2); + + 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 cpia_write_proc(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + struct cam_data *cam = data; + struct cam_params new_params; + int retval, find_colon; + int size = count; + unsigned long val; + u32 command_flags = 0; + u8 new_mains; + + if (down_interruptible(&cam->param_lock)) + return -ERESTARTSYS; + + /* + * Skip over leading whitespace + */ + while (count && isspace(*buffer)) { + --count; + ++buffer; + } + + memcpy(&new_params, &cam->params, sizeof(struct cam_params)); + new_mains = cam->mainsFreq; + +#define MATCH(x) \ + ({ \ + int _len = strlen(x), _ret, _colon_found; \ + _ret = (_len <= count && strncmp(buffer, x, _len) == 0); \ + if (_ret) { \ + buffer += _len; \ + count -= _len; \ + if (find_colon) { \ + _colon_found = 0; \ + while (count && (*buffer == ' ' || *buffer == '\t' || \ + (!_colon_found && *buffer == ':'))) { \ + if (*buffer == ':') \ + _colon_found = 1; \ + --count; \ + ++buffer; \ + } \ + if (!count || !_colon_found) \ + retval = -EINVAL; \ + find_colon = 0; \ + } \ + } \ + _ret; \ + }) +#define FIRMWARE_VERSION(x,y) (new_params.version.firmwareVersion == (x) && \ + new_params.version.firmwareRevision == (y)) +#define VALUE \ + ({ \ + char *_p; \ + unsigned long int _ret; \ + _ret = simple_strtoul(buffer, &_p, 0); \ + if (_p == buffer) \ + retval = -EINVAL; \ + else { \ + count -= _p - buffer; \ + buffer = _p; \ + } \ + _ret; \ + }) + + retval = 0; + while (count && !retval) { + find_colon = 1; + if (MATCH("brightness")) { + if (!retval) + val = VALUE; + + if (!retval) { + if (val <= 100) + new_params.colourParams.brightness = val; + else + retval = -EINVAL; + } + command_flags |= COMMAND_SETCOLOURPARAMS; + } else if (MATCH("contrast")) { + if (!retval) + val = VALUE; + + if (!retval) { + if (val <= 100) { + /* contrast is in steps of 8, so round*/ + val = ((val + 3) / 8) * 8; + /* 1-02 firmware limits contrast to 80*/ + if (FIRMWARE_VERSION(1,2) && val > 80) + val = 80; + + new_params.colourParams.contrast = val; + } else + retval = -EINVAL; + } + command_flags |= COMMAND_SETCOLOURPARAMS; + } else if (MATCH("saturation")) { + if (!retval) + val = VALUE; + + if (!retval) { + if (val <= 100) + new_params.colourParams.saturation = val; + else + retval = -EINVAL; + } + command_flags |= COMMAND_SETCOLOURPARAMS; + } else if (MATCH("sensor_fps")) { + if (!retval) + val = VALUE; + + if (!retval) { + /* find values so that sensorFPS is minimized, + * but >= val */ + if (val > 30) + retval = -EINVAL; + else if (val > 25) { + new_params.sensorFps.divisor = 0; + new_params.sensorFps.baserate = 1; + } else if (val > 15) { + new_params.sensorFps.divisor = 0; + new_params.sensorFps.baserate = 0; + } else if (val > 12) { + new_params.sensorFps.divisor = 1; + new_params.sensorFps.baserate = 1; + } else if (val > 7) { + new_params.sensorFps.divisor = 1; + new_params.sensorFps.baserate = 0; + } else if (val > 6) { + new_params.sensorFps.divisor = 2; + new_params.sensorFps.baserate = 1; + } else if (val > 3) { + new_params.sensorFps.divisor = 2; + new_params.sensorFps.baserate = 0; + } else { + new_params.sensorFps.divisor = 3; + /* Either base rate would work here */ + new_params.sensorFps.baserate = 1; + } + new_params.flickerControl.coarseJump = + flicker_jumps[new_mains] + [new_params.sensorFps.baserate] + [new_params.sensorFps.divisor]; + if (new_params.flickerControl.flickerMode) + command_flags |= COMMAND_SETFLICKERCTRL; + } + command_flags |= COMMAND_SETSENSORFPS; + } else if (MATCH("stream_start_line")) { + if (!retval) + val = VALUE; + + if (!retval) { + int max_line = 288; + + if (new_params.format.videoSize == VIDEOSIZE_QCIF) + max_line = 144; + if (val <= max_line) + new_params.streamStartLine = val/2; + else + retval = -EINVAL; + } + } else if (MATCH("ecp_timing")) { + if (!retval && MATCH("normal")) + new_params.ecpTiming = 0; + else if (!retval && MATCH("slow")) + new_params.ecpTiming = 1; + else + retval = -EINVAL; + + command_flags |= COMMAND_SETECPTIMING; + } else if (MATCH("color_balance_mode")) { + if (!retval && MATCH("manual")) + new_params.colourBalance.balanceModeIsAuto = 0; + else if (!retval && MATCH("auto")) + new_params.colourBalance.balanceModeIsAuto = 1; + else + retval = -EINVAL; + + command_flags |= COMMAND_SETCOLOURBALANCE; + } else if (MATCH("red_gain")) { + if (!retval) + val = VALUE; + + if (!retval) { + if (val <= 212) + new_params.colourBalance.redGain = val; + else + retval = -EINVAL; + } + command_flags |= COMMAND_SETCOLOURBALANCE; + } else if (MATCH("green_gain")) { + if (!retval) + val = VALUE; + + if (!retval) { + if (val <= 212) + new_params.colourBalance.greenGain = val; + else + retval = -EINVAL; + } + command_flags |= COMMAND_SETCOLOURBALANCE; + } else if (MATCH("blue_gain")) { + if (!retval) + val = VALUE; + + if (!retval) { + if (val <= 212) + new_params.colourBalance.blueGain = val; + else + retval = -EINVAL; + } + command_flags |= COMMAND_SETCOLOURBALANCE; + } else if (MATCH("max_gain")) { + if (!retval) + val = VALUE; + + if (!retval) { + /* 1-02 firmware limits gain to 2 */ + if (FIRMWARE_VERSION(1,2) && val > 2) + val = 2; + switch(val) { + case 1: + new_params.exposure.gainMode = 1; + break; + case 2: + new_params.exposure.gainMode = 2; + break; + case 4: + new_params.exposure.gainMode = 3; + break; + case 8: + new_params.exposure.gainMode = 4; + break; + default: + retval = -EINVAL; + break; + } + } + command_flags |= COMMAND_SETEXPOSURE; + } else if (MATCH("exposure_mode")) { + if (!retval && MATCH("auto")) + new_params.exposure.expMode = 2; + else if (!retval && MATCH("manual")) { + if (new_params.exposure.expMode == 2) + new_params.exposure.expMode = 3; + new_params.flickerControl.flickerMode = 0; + command_flags |= COMMAND_SETFLICKERCTRL; + } else + retval = -EINVAL; + + command_flags |= COMMAND_SETEXPOSURE; + } else if (MATCH("centre_weight")) { + if (!retval && MATCH("on")) + new_params.exposure.centreWeight = 1; + else if (!retval && MATCH("off")) + new_params.exposure.centreWeight = 2; + else + retval = -EINVAL; + + command_flags |= COMMAND_SETEXPOSURE; + } else if (MATCH("gain")) { + if (!retval) + val = VALUE; + + if (!retval) { + switch(val) { + case 1: + new_params.exposure.gain = 0; + new_params.exposure.expMode = 1; + new_params.flickerControl.flickerMode = 0; + command_flags |= COMMAND_SETFLICKERCTRL; + break; + case 2: + new_params.exposure.gain = 1; + new_params.exposure.expMode = 1; + new_params.flickerControl.flickerMode = 0; + command_flags |= COMMAND_SETFLICKERCTRL; + break; + case 4: + new_params.exposure.gain = 2; + new_params.exposure.expMode = 1; + new_params.flickerControl.flickerMode = 0; + command_flags |= COMMAND_SETFLICKERCTRL; + break; + case 8: + new_params.exposure.gain = 3; + new_params.exposure.expMode = 1; + new_params.flickerControl.flickerMode = 0; + command_flags |= COMMAND_SETFLICKERCTRL; + break; + default: + retval = -EINVAL; + break; + } + command_flags |= COMMAND_SETEXPOSURE; + if (new_params.exposure.gain > + new_params.exposure.gainMode-1) + retval = -EINVAL; + } + } else if (MATCH("fine_exp")) { + if (!retval) + val = VALUE; + + if (!retval) { + if (val < 256) { + /* 1-02 firmware limits fineExp to 127*/ + if (FIRMWARE_VERSION(1,2) && val > 127) + val = 127; + new_params.exposure.fineExp = val; + new_params.exposure.expMode = 1; + command_flags |= COMMAND_SETEXPOSURE; + new_params.flickerControl.flickerMode = 0; + command_flags |= COMMAND_SETFLICKERCTRL; + } else + retval = -EINVAL; + } + } else if (MATCH("coarse_exp")) { + if (!retval) + val = VALUE; + + if (!retval) { + if (val < 65536) { + /* 1-02 firmware limits + * coarseExp to 255 */ + if (FIRMWARE_VERSION(1,2) && val > 255) + val = 255; + new_params.exposure.coarseExpLo = + val & 0xff; + new_params.exposure.coarseExpHi = + val >> 8; + new_params.exposure.expMode = 1; + command_flags |= COMMAND_SETEXPOSURE; + new_params.flickerControl.flickerMode = 0; + command_flags |= COMMAND_SETFLICKERCTRL; + } else + retval = -EINVAL; + } + } else if (MATCH("red_comp")) { + if (!retval) + val = VALUE; + + if (!retval) { + if (val >= 220 && val <= 255) { + new_params.exposure.redComp = val; + command_flags |= COMMAND_SETEXPOSURE; + } else + retval = -EINVAL; + } + } else if (MATCH("green1_comp")) { + if (!retval) + val = VALUE; + + if (!retval) { + if (val >= 214 && val <= 255) { + new_params.exposure.green1Comp = val; + command_flags |= COMMAND_SETEXPOSURE; + } else + retval = -EINVAL; + } + } else if (MATCH("green2_comp")) { + if (!retval) + val = VALUE; + + if (!retval) { + if (val >= 214 && val <= 255) { + new_params.exposure.green2Comp = val; + command_flags |= COMMAND_SETEXPOSURE; + } else + retval = -EINVAL; + } + } else if (MATCH("blue_comp")) { + if (!retval) + val = VALUE; + + if (!retval) { + if (val >= 230 && val <= 255) { + new_params.exposure.blueComp = val; + command_flags |= COMMAND_SETEXPOSURE; + } else + retval = -EINVAL; + } + } else if (MATCH("apcor_gain1")) { + if (!retval) + val = VALUE; + + if (!retval) { + command_flags |= COMMAND_SETAPCOR; + if (val <= 0xff) + new_params.apcor.gain1 = val; + else + retval = -EINVAL; + } + } else if (MATCH("apcor_gain2")) { + if (!retval) + val = VALUE; + + if (!retval) { + command_flags |= COMMAND_SETAPCOR; + if (val <= 0xff) + new_params.apcor.gain2 = val; + else + retval = -EINVAL; + } + } else if (MATCH("apcor_gain4")) { + if (!retval) + val = VALUE; + + if (!retval) { + command_flags |= COMMAND_SETAPCOR; + if (val <= 0xff) + new_params.apcor.gain4 = val; + else + retval = -EINVAL; + } + } else if (MATCH("apcor_gain8")) { + if (!retval) + val = VALUE; + + if (!retval) { + command_flags |= COMMAND_SETAPCOR; + if (val <= 0xff) + new_params.apcor.gain8 = val; + else + retval = -EINVAL; + } + } else if (MATCH("vl_offset_gain1")) { + if (!retval) + val = VALUE; + + if (!retval) { + if (val <= 0xff) + new_params.vlOffset.gain1 = val; + else + retval = -EINVAL; + } + command_flags |= COMMAND_SETVLOFFSET; + } else if (MATCH("vl_offset_gain2")) { + if (!retval) + val = VALUE; + + if (!retval) { + if (val <= 0xff) + new_params.vlOffset.gain2 = val; + else + retval = -EINVAL; + } + command_flags |= COMMAND_SETVLOFFSET; + } else if (MATCH("vl_offset_gain4")) { + if (!retval) + val = VALUE; + + if (!retval) { + if (val <= 0xff) + new_params.vlOffset.gain4 = val; + else + retval = -EINVAL; + } + command_flags |= COMMAND_SETVLOFFSET; + } else if (MATCH("vl_offset_gain8")) { + if (!retval) + val = VALUE; + + if (!retval) { + if (val <= 0xff) + new_params.vlOffset.gain8 = val; + else + retval = -EINVAL; + } + command_flags |= COMMAND_SETVLOFFSET; + } else if (MATCH("flicker_control")) { + if (!retval && MATCH("on")) { + new_params.flickerControl.flickerMode = 1; + new_params.exposure.expMode = 2; + command_flags |= COMMAND_SETEXPOSURE; + } else if (!retval && MATCH("off")) + new_params.flickerControl.flickerMode = 0; + else + retval = -EINVAL; + + command_flags |= COMMAND_SETFLICKERCTRL; + } else if (MATCH("mains_frequency")) { + if (!retval && MATCH("50")) { + new_mains = 0; + new_params.flickerControl.coarseJump = + flicker_jumps[new_mains] + [new_params.sensorFps.baserate] + [new_params.sensorFps.divisor]; + if (new_params.flickerControl.flickerMode) + command_flags |= COMMAND_SETFLICKERCTRL; + } else if (!retval && MATCH("60")) { + new_mains = 1; + new_params.flickerControl.coarseJump = + flicker_jumps[new_mains] + [new_params.sensorFps.baserate] + [new_params.sensorFps.divisor]; + if (new_params.flickerControl.flickerMode) + command_flags |= COMMAND_SETFLICKERCTRL; + } else + retval = -EINVAL; + } else if (MATCH("allowable_overexposure")) { + if (!retval) + val = VALUE; + + if (!retval) { + if (val <= 0xff) { + new_params.flickerControl. + allowableOverExposure = val; + command_flags |= COMMAND_SETFLICKERCTRL; + } else + retval = -EINVAL; + } + } else if (MATCH("compression_mode")) { + if (!retval && MATCH("none")) + new_params.compression.mode = + CPIA_COMPRESSION_NONE; + else if (!retval && MATCH("auto")) + new_params.compression.mode = + CPIA_COMPRESSION_AUTO; + else if (!retval && MATCH("manual")) + new_params.compression.mode = + CPIA_COMPRESSION_MANUAL; + else + retval = -EINVAL; + + command_flags |= COMMAND_SETCOMPRESSION; + } else if (MATCH("decimation_enable")) { + if (!retval && MATCH("off")) + new_params.compression.decimation = 0; + else + retval = -EINVAL; + + command_flags |= COMMAND_SETCOMPRESSION; + } else if (MATCH("compression_target")) { + if (!retval && MATCH("quality")) + new_params.compressionTarget.frTargeting = + CPIA_COMPRESSION_TARGET_QUALITY; + else if (!retval && MATCH("framerate")) + new_params.compressionTarget.frTargeting = + CPIA_COMPRESSION_TARGET_FRAMERATE; + else + retval = -EINVAL; + + command_flags |= COMMAND_SETCOMPRESSIONTARGET; + } else if (MATCH("target_framerate")) { + if (!retval) + val = VALUE; + + if (!retval) + new_params.compressionTarget.targetFR = val; + command_flags |= COMMAND_SETCOMPRESSIONTARGET; + } else if (MATCH("target_quality")) { + if (!retval) + val = VALUE; + + if (!retval) + new_params.compressionTarget.targetQ = val; + + command_flags |= COMMAND_SETCOMPRESSIONTARGET; + } else if (MATCH("y_threshold")) { + if (!retval) + val = VALUE; + + if (!retval) { + if (val < 32) + new_params.yuvThreshold.yThreshold = val; + else + retval = -EINVAL; + } + command_flags |= COMMAND_SETYUVTHRESH; + } else if (MATCH("uv_threshold")) { + if (!retval) + val = VALUE; + + if (!retval) { + if (val < 32) + new_params.yuvThreshold.uvThreshold = val; + else + retval = -EINVAL; + } + command_flags |= COMMAND_SETYUVTHRESH; + } else if (MATCH("hysteresis")) { + if (!retval) + val = VALUE; + + if (!retval) { + if (val <= 0xff) + new_params.compressionParams.hysteresis = val; + else + retval = -EINVAL; + } + command_flags |= COMMAND_SETCOMPRESSIONPARAMS; + } else if (MATCH("threshold_max")) { + if (!retval) + val = VALUE; + + if (!retval) { + if (val <= 0xff) + new_params.compressionParams.threshMax = val; + else + retval = -EINVAL; + } + command_flags |= COMMAND_SETCOMPRESSIONPARAMS; + } else if (MATCH("small_step")) { + if (!retval) + val = VALUE; + + if (!retval) { + if (val <= 0xff) + new_params.compressionParams.smallStep = val; + else + retval = -EINVAL; + } + command_flags |= COMMAND_SETCOMPRESSIONPARAMS; + } else if (MATCH("large_step")) { + if (!retval) + val = VALUE; + + if (!retval) { + if (val <= 0xff) + new_params.compressionParams.largeStep = val; + else + retval = -EINVAL; + } + command_flags |= COMMAND_SETCOMPRESSIONPARAMS; + } else if (MATCH("decimation_hysteresis")) { + if (!retval) + val = VALUE; + + if (!retval) { + if (val <= 0xff) + new_params.compressionParams.decimationHysteresis = val; + else + retval = -EINVAL; + } + command_flags |= COMMAND_SETCOMPRESSIONPARAMS; + } else if (MATCH("fr_diff_step_thresh")) { + if (!retval) + val = VALUE; + + if (!retval) { + if (val <= 0xff) + new_params.compressionParams.frDiffStepThresh = val; + else + retval = -EINVAL; + } + command_flags |= COMMAND_SETCOMPRESSIONPARAMS; + } else if (MATCH("q_diff_step_thresh")) { + if (!retval) + val = VALUE; + + if (!retval) { + if (val <= 0xff) + new_params.compressionParams.qDiffStepThresh = val; + else + retval = -EINVAL; + } + command_flags |= COMMAND_SETCOMPRESSIONPARAMS; + } else if (MATCH("decimation_thresh_mod")) { + if (!retval) + val = VALUE; + + if (!retval) { + if (val <= 0xff) + new_params.compressionParams.decimationThreshMod = val; + else + retval = -EINVAL; + } + command_flags |= COMMAND_SETCOMPRESSIONPARAMS; + } else { + DBG("No match found\n"); + retval = -EINVAL; + } + + if (!retval) { + while (count && isspace(*buffer) && *buffer != '\n') { + --count; + ++buffer; + } + if (count) { + if (*buffer != '\n' && *buffer != ';') + retval = -EINVAL; + else { + --count; + ++buffer; + } + } + } + } +#undef MATCH +#undef FIRMWARE_VERSION +#undef VALUE +#undef FIND_VALUE +#undef FIND_END + if (!retval) { + if (command_flags & COMMAND_SETCOLOURPARAMS) { + /* Adjust cam->vp to reflect these changes */ + cam->vp.brightness = + new_params.colourParams.brightness*65535/100; + cam->vp.contrast = + new_params.colourParams.contrast*65535/100; + cam->vp.colour = + new_params.colourParams.saturation*65535/100; + } + + memcpy(&cam->params, &new_params, sizeof(struct cam_params)); + cam->mainsFreq = new_mains; + cam->cmd_queue |= command_flags; + retval = size; + } else + DBG("error: %d\n", retval); + + up(&cam->param_lock); + + return retval; +} + +static void create_proc_cpia_cam(struct cam_data *cam) +{ + char name[7]; + struct proc_dir_entry *ent; + + if (!cpia_proc_root || !cam) + return; + + sprintf(name, "video%d", cam->vdev.minor); + + ent = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, cpia_proc_root); + if (!ent) + return; + + ent->data = cam; + ent->read_proc = cpia_read_proc; + ent->write_proc = cpia_write_proc; + ent->size = 3626; + cam->proc_entry = ent; +} + +static void destroy_proc_cpia_cam(struct cam_data *cam) +{ + char name[7]; + + if (!cam || !cam->proc_entry) + return; + + sprintf(name, "video%d", cam->vdev.minor); + remove_proc_entry(name, cpia_proc_root); + cam->proc_entry = NULL; +} + +static void proc_cpia_create(void) +{ + cpia_proc_root = create_proc_entry("cpia", S_IFDIR, 0); + + if (cpia_proc_root) + cpia_proc_root->owner = THIS_MODULE; + else + LOG("Unable to initialise /proc/cpia\n"); +} + +static void proc_cpia_destroy(void) +{ + remove_proc_entry("cpia", 0); +} +#endif /* CONFIG_PROC_FS */ + +/* ----------------------- debug functions ---------------------- */ + +#define printstatus(cam) \ + DBG("%02x %02x %02x %02x %02x %02x %02x %02x\n",\ + cam->params.status.systemState, cam->params.status.grabState, \ + cam->params.status.streamState, cam->params.status.fatalError, \ + cam->params.status.cmdError, cam->params.status.debugFlags, \ + cam->params.status.vpStatus, cam->params.status.errorCode); + +/* ----------------------- v4l helpers -------------------------- */ + +/* supported frame palettes and depths */ +static inline int valid_mode(u16 palette, u16 depth) +{ + return (palette == VIDEO_PALETTE_GREY && depth == 8) || + (palette == VIDEO_PALETTE_RGB555 && depth == 16) || + (palette == VIDEO_PALETTE_RGB565 && depth == 16) || + (palette == VIDEO_PALETTE_RGB24 && depth == 24) || + (palette == VIDEO_PALETTE_RGB32 && depth == 32) || + (palette == VIDEO_PALETTE_YUV422 && depth == 16) || + (palette == VIDEO_PALETTE_YUYV && depth == 16) || + (palette == VIDEO_PALETTE_UYVY && depth == 16); +} + +static int match_videosize( int width, int height ) +{ + /* return the best match, where 'best' is as always + * the largest that is not bigger than what is requested. */ + if (width>=352 && height>=288) + return VIDEOSIZE_352_288; /* CIF */ + + if (width>=320 && height>=240) + return VIDEOSIZE_320_240; /* SIF */ + + if (width>=288 && height>=216) + return VIDEOSIZE_288_216; + + if (width>=256 && height>=192) + return VIDEOSIZE_256_192; + + if (width>=224 && height>=168) + return VIDEOSIZE_224_168; + + if (width>=192 && height>=144) + return VIDEOSIZE_192_144; + + if (width>=176 && height>=144) + return VIDEOSIZE_176_144; /* QCIF */ + + if (width>=160 && height>=120) + return VIDEOSIZE_160_120; /* QSIF */ + + if (width>=128 && height>=96) + return VIDEOSIZE_128_96; + + if (width>=88 && height>=72) + return VIDEOSIZE_88_72; + + if (width>=64 && height>=48) + return VIDEOSIZE_64_48; + + if (width>=48 && height>=48) + return VIDEOSIZE_48_48; + + return -1; +} + +/* these are the capture sizes we support */ +static void set_vw_size(struct cam_data *cam) +{ + /* the col/row/start/end values are the result of simple math */ + /* study the SetROI-command in cpia developers guide p 2-22 */ + /* streamStartLine is set to the recommended value in the cpia */ + /* developers guide p 3-37 */ + switch(cam->video_size) { + case VIDEOSIZE_CIF: + cam->vw.width = 352; + cam->vw.height = 288; + cam->params.format.videoSize=VIDEOSIZE_CIF; + cam->params.roi.colStart=0; + cam->params.roi.colEnd=44; + cam->params.roi.rowStart=0; + cam->params.roi.rowEnd=72; + cam->params.streamStartLine = 120; + break; + case VIDEOSIZE_SIF: + cam->vw.width = 320; + cam->vw.height = 240; + cam->params.format.videoSize=VIDEOSIZE_CIF; + cam->params.roi.colStart=2; + cam->params.roi.colEnd=42; + cam->params.roi.rowStart=6; + cam->params.roi.rowEnd=66; + cam->params.streamStartLine = 120; + break; + case VIDEOSIZE_288_216: + cam->vw.width = 288; + cam->vw.height = 216; + cam->params.format.videoSize=VIDEOSIZE_CIF; + cam->params.roi.colStart=4; + cam->params.roi.colEnd=40; + cam->params.roi.rowStart=9; + cam->params.roi.rowEnd=63; + cam->params.streamStartLine = 120; + break; + case VIDEOSIZE_256_192: + cam->vw.width = 256; + cam->vw.height = 192; + cam->params.format.videoSize=VIDEOSIZE_CIF; + cam->params.roi.colStart=6; + cam->params.roi.colEnd=38; + cam->params.roi.rowStart=12; + cam->params.roi.rowEnd=60; + cam->params.streamStartLine = 120; + break; + case VIDEOSIZE_224_168: + cam->vw.width = 224; + cam->vw.height = 168; + cam->params.format.videoSize=VIDEOSIZE_CIF; + cam->params.roi.colStart=8; + cam->params.roi.colEnd=36; + cam->params.roi.rowStart=15; + cam->params.roi.rowEnd=57; + cam->params.streamStartLine = 120; + break; + case VIDEOSIZE_192_144: + cam->vw.width = 192; + cam->vw.height = 144; + cam->params.format.videoSize=VIDEOSIZE_CIF; + cam->params.roi.colStart=10; + cam->params.roi.colEnd=34; + cam->params.roi.rowStart=18; + cam->params.roi.rowEnd=54; + cam->params.streamStartLine = 120; + break; + case VIDEOSIZE_QCIF: + cam->vw.width = 176; + cam->vw.height = 144; + cam->params.format.videoSize=VIDEOSIZE_QCIF; + cam->params.roi.colStart=0; + cam->params.roi.colEnd=22; + cam->params.roi.rowStart=0; + cam->params.roi.rowEnd=36; + cam->params.streamStartLine = 60; + break; + case VIDEOSIZE_QSIF: + cam->vw.width = 160; + cam->vw.height = 120; + cam->params.format.videoSize=VIDEOSIZE_QCIF; + cam->params.roi.colStart=1; + cam->params.roi.colEnd=21; + cam->params.roi.rowStart=3; + cam->params.roi.rowEnd=33; + cam->params.streamStartLine = 60; + break; + case VIDEOSIZE_128_96: + cam->vw.width = 128; + cam->vw.height = 96; + cam->params.format.videoSize=VIDEOSIZE_QCIF; + cam->params.roi.colStart=3; + cam->params.roi.colEnd=19; + cam->params.roi.rowStart=6; + cam->params.roi.rowEnd=30; + cam->params.streamStartLine = 60; + break; + case VIDEOSIZE_88_72: + cam->vw.width = 88; + cam->vw.height = 72; + cam->params.format.videoSize=VIDEOSIZE_QCIF; + cam->params.roi.colStart=5; + cam->params.roi.colEnd=16; + cam->params.roi.rowStart=9; + cam->params.roi.rowEnd=27; + cam->params.streamStartLine = 60; + break; + case VIDEOSIZE_64_48: + cam->vw.width = 64; + cam->vw.height = 48; + cam->params.format.videoSize=VIDEOSIZE_QCIF; + cam->params.roi.colStart=7; + cam->params.roi.colEnd=15; + cam->params.roi.rowStart=12; + cam->params.roi.rowEnd=24; + cam->params.streamStartLine = 60; + break; + case VIDEOSIZE_48_48: + cam->vw.width = 48; + cam->vw.height = 48; + cam->params.format.videoSize=VIDEOSIZE_QCIF; + cam->params.roi.colStart=8; + cam->params.roi.colEnd=14; + cam->params.roi.rowStart=6; + cam->params.roi.rowEnd=30; + cam->params.streamStartLine = 60; + break; + default: + LOG("bad videosize value: %d\n", cam->video_size); + } + + return; +} + +static int allocate_frame_buf(struct cam_data *cam) +{ + int i; + + cam->frame_buf = rvmalloc(FRAME_NUM * CPIA_MAX_FRAME_SIZE); + if (!cam->frame_buf) + return -ENOBUFS; + + for (i = 0; i < FRAME_NUM; i++) + cam->frame[i].data = cam->frame_buf + i * CPIA_MAX_FRAME_SIZE; + + return 0; +} + +static int free_frame_buf(struct cam_data *cam) +{ + int i; + + rvfree(cam->frame_buf, FRAME_NUM*CPIA_MAX_FRAME_SIZE); + cam->frame_buf = 0; + for (i=0; i < FRAME_NUM; i++) + cam->frame[i].data = NULL; + + return 0; +} + + +static void inline free_frames(struct cpia_frame frame[FRAME_NUM]) +{ + int i; + + for (i=0; i < FRAME_NUM; i++) + frame[i].state = FRAME_UNUSED; + return; +} + +/********************************************************************** + * + * General functions + * + **********************************************************************/ +/* send an arbitrary command to the camera */ +static int do_command(struct cam_data *cam, u16 command, u8 a, u8 b, u8 c, u8 d) +{ + int retval, datasize; + u8 cmd[8], data[8]; + + switch(command) { + case CPIA_COMMAND_GetCPIAVersion: + case CPIA_COMMAND_GetPnPID: + case CPIA_COMMAND_GetCameraStatus: + case CPIA_COMMAND_GetVPVersion: + datasize=8; + break; + case CPIA_COMMAND_GetColourParams: + case CPIA_COMMAND_GetColourBalance: + case CPIA_COMMAND_GetExposure: + down(&cam->param_lock); + datasize=8; + break; + default: + datasize=0; + break; + } + + cmd[0] = command>>8; + cmd[1] = command&0xff; + cmd[2] = a; + cmd[3] = b; + cmd[4] = c; + cmd[5] = d; + cmd[6] = datasize; + cmd[7] = 0; + + retval = cam->ops->transferCmd(cam->lowlevel_data, cmd, data); + if (retval) + DBG("%x - failed, retval=%d\n", command, retval); + else { + switch(command) { + case CPIA_COMMAND_GetCPIAVersion: + cam->params.version.firmwareVersion = data[0]; + cam->params.version.firmwareRevision = data[1]; + cam->params.version.vcVersion = data[2]; + cam->params.version.vcRevision = data[3]; + break; + case CPIA_COMMAND_GetPnPID: + cam->params.pnpID.vendor = data[0]+(((u16)data[1])<<8); + cam->params.pnpID.product = data[2]+(((u16)data[3])<<8); + cam->params.pnpID.deviceRevision = + data[4]+(((u16)data[5])<<8); + break; + case CPIA_COMMAND_GetCameraStatus: + cam->params.status.systemState = data[0]; + cam->params.status.grabState = data[1]; + cam->params.status.streamState = data[2]; + cam->params.status.fatalError = data[3]; + cam->params.status.cmdError = data[4]; + cam->params.status.debugFlags = data[5]; + cam->params.status.vpStatus = data[6]; + cam->params.status.errorCode = data[7]; + break; + case CPIA_COMMAND_GetVPVersion: + cam->params.vpVersion.vpVersion = data[0]; + cam->params.vpVersion.vpRevision = data[1]; + cam->params.vpVersion.cameraHeadID = + data[2]+(((u16)data[3])<<8); + break; + case CPIA_COMMAND_GetColourParams: + cam->params.colourParams.brightness = data[0]; + cam->params.colourParams.contrast = data[1]; + cam->params.colourParams.saturation = data[2]; + up(&cam->param_lock); + break; + case CPIA_COMMAND_GetColourBalance: + cam->params.colourBalance.redGain = data[0]; + cam->params.colourBalance.greenGain = data[1]; + cam->params.colourBalance.blueGain = data[2]; + up(&cam->param_lock); + break; + case CPIA_COMMAND_GetExposure: + cam->params.exposure.gain = data[0]; + cam->params.exposure.fineExp = data[1]; + cam->params.exposure.coarseExpLo = data[2]; + cam->params.exposure.coarseExpHi = data[3]; + cam->params.exposure.redComp = data[4]; + cam->params.exposure.green1Comp = data[5]; + cam->params.exposure.green2Comp = data[6]; + cam->params.exposure.blueComp = data[7]; + /* If the *Comp parameters are wacko, generate + * a warning, and reset them back to default + * values. - rich@annexia.org + */ + if (cam->params.exposure.redComp < 220 || + cam->params.exposure.redComp > 255 || + cam->params.exposure.green1Comp < 214 || + cam->params.exposure.green1Comp > 255 || + cam->params.exposure.green2Comp < 214 || + cam->params.exposure.green2Comp > 255 || + cam->params.exposure.blueComp < 230 || + cam->params.exposure.blueComp > 255) + { + printk (KERN_WARNING "*_comp parameters have gone AWOL (%d/%d/%d/%d) - reseting them\n", + cam->params.exposure.redComp, + cam->params.exposure.green1Comp, + cam->params.exposure.green2Comp, + cam->params.exposure.blueComp); + cam->params.exposure.redComp = 220; + cam->params.exposure.green1Comp = 214; + cam->params.exposure.green2Comp = 214; + cam->params.exposure.blueComp = 230; + } + up(&cam->param_lock); + break; + default: + break; + } + } + return retval; +} + +/* send a command to the camera with an additional data transaction */ +static int do_command_extended(struct cam_data *cam, u16 command, + u8 a, u8 b, u8 c, u8 d, + u8 e, u8 f, u8 g, u8 h, + u8 i, u8 j, u8 k, u8 l) +{ + int retval; + u8 cmd[8], data[8]; + + cmd[0] = command>>8; + cmd[1] = command&0xff; + cmd[2] = a; + cmd[3] = b; + cmd[4] = c; + cmd[5] = d; + cmd[6] = 8; + cmd[7] = 0; + data[0] = e; + data[1] = f; + data[2] = g; + data[3] = h; + data[4] = i; + data[5] = j; + data[6] = k; + data[7] = l; + + retval = cam->ops->transferCmd(cam->lowlevel_data, cmd, data); + if (retval) + LOG("%x - failed\n", command); + + return retval; +} + +/********************************************************************** + * + * Colorspace conversion + * + **********************************************************************/ +#define LIMIT(x) ((((x)>0xffffff)?0xff0000:(((x)<=0xffff)?0:(x)&0xff0000))>>16) + +static int yuvconvert(unsigned char *yuv, unsigned char *rgb, int out_fmt, + int in_uyvy, int mmap_kludge) +{ + int y, u, v, r, g, b, y1; + + switch(out_fmt) { + case VIDEO_PALETTE_RGB555: + case VIDEO_PALETTE_RGB565: + case VIDEO_PALETTE_RGB24: + case VIDEO_PALETTE_RGB32: + if (in_uyvy) { + u = *yuv++ - 128; + y = (*yuv++ - 16) * 76310; + v = *yuv++ - 128; + y1 = (*yuv - 16) * 76310; + } else { + y = (*yuv++ - 16) * 76310; + u = *yuv++ - 128; + y1 = (*yuv++ - 16) * 76310; + v = *yuv - 128; + } + r = 104635 * v; + g = -25690 * u + -53294 * v; + b = 132278 * u; + break; + default: + y = *yuv++; + u = *yuv++; + y1 = *yuv++; + v = *yuv; + /* Just to avoid compiler warnings */ + r = 0; + g = 0; + b = 0; + break; + } + switch(out_fmt) { + case VIDEO_PALETTE_RGB555: + *rgb++ = ((LIMIT(g+y) & 0xf8) << 2) | (LIMIT(b+y) >> 3); + *rgb++ = ((LIMIT(r+y) & 0xf8) >> 1) | (LIMIT(g+y) >> 6); + *rgb++ = ((LIMIT(g+y1) & 0xf8) << 2) | (LIMIT(b+y1) >> 3); + *rgb = ((LIMIT(r+y1) & 0xf8) >> 1) | (LIMIT(g+y1) >> 6); + return 4; + case VIDEO_PALETTE_RGB565: + *rgb++ = ((LIMIT(g+y) & 0xfc) << 3) | (LIMIT(b+y) >> 3); + *rgb++ = (LIMIT(r+y) & 0xf8) | (LIMIT(g+y) >> 5); + *rgb++ = ((LIMIT(g+y1) & 0xfc) << 3) | (LIMIT(b+y1) >> 3); + *rgb = (LIMIT(r+y1) & 0xf8) | (LIMIT(g+y1) >> 5); + return 4; + case VIDEO_PALETTE_RGB24: + if (mmap_kludge) { + *rgb++ = LIMIT(b+y); + *rgb++ = LIMIT(g+y); + *rgb++ = LIMIT(r+y); + *rgb++ = LIMIT(b+y1); + *rgb++ = LIMIT(g+y1); + *rgb = LIMIT(r+y1); + } else { + *rgb++ = LIMIT(r+y); + *rgb++ = LIMIT(g+y); + *rgb++ = LIMIT(b+y); + *rgb++ = LIMIT(r+y1); + *rgb++ = LIMIT(g+y1); + *rgb = LIMIT(b+y1); + } + return 6; + case VIDEO_PALETTE_RGB32: + if (mmap_kludge) { + *rgb++ = LIMIT(b+y); + *rgb++ = LIMIT(g+y); + *rgb++ = LIMIT(r+y); + rgb++; + *rgb++ = LIMIT(b+y1); + *rgb++ = LIMIT(g+y1); + *rgb = LIMIT(r+y1); + } else { + *rgb++ = LIMIT(r+y); + *rgb++ = LIMIT(g+y); + *rgb++ = LIMIT(b+y); + rgb++; + *rgb++ = LIMIT(r+y1); + *rgb++ = LIMIT(g+y1); + *rgb = LIMIT(b+y1); + } + return 8; + case VIDEO_PALETTE_GREY: + *rgb++ = y; + *rgb = y1; + return 2; + case VIDEO_PALETTE_YUV422: + case VIDEO_PALETTE_YUYV: + *rgb++ = y; + *rgb++ = u; + *rgb++ = y1; + *rgb = v; + return 4; + case VIDEO_PALETTE_UYVY: + *rgb++ = u; + *rgb++ = y; + *rgb++ = v; + *rgb = y1; + return 4; + default: + DBG("Empty: %d\n", out_fmt); + return 0; + } +} + +static int skipcount(int count, int fmt) +{ + switch(fmt) { + case VIDEO_PALETTE_GREY: + case VIDEO_PALETTE_RGB555: + case VIDEO_PALETTE_RGB565: + case VIDEO_PALETTE_YUV422: + case VIDEO_PALETTE_YUYV: + case VIDEO_PALETTE_UYVY: + return 2*count; + case VIDEO_PALETTE_RGB24: + return 3*count; + case VIDEO_PALETTE_RGB32: + return 4*count; + default: + return 0; + } +} + +static int parse_picture(struct cam_data *cam, int size) +{ + u8 *obuf, *ibuf, *end_obuf; + int ll, in_uyvy, compressed, origsize, out_fmt; + + /* make sure params don't change while we are decoding */ + down(&cam->param_lock); + + obuf = cam->decompressed_frame.data; + end_obuf = obuf+CPIA_MAX_FRAME_SIZE; + ibuf = cam->raw_image; + origsize = size; + out_fmt = cam->vp.palette; + + if ((ibuf[0] != MAGIC_0) || (ibuf[1] != MAGIC_1)) { + LOG("header not found\n"); + up(&cam->param_lock); + return -1; + } + + if ((ibuf[16] != VIDEOSIZE_QCIF) && (ibuf[16] != VIDEOSIZE_CIF)) { + LOG("wrong video size\n"); + up(&cam->param_lock); + return -1; + } + + if (ibuf[17] != SUBSAMPLE_422) { + LOG("illegal subtype %d\n",ibuf[17]); + up(&cam->param_lock); + return -1; + } + + if (ibuf[18] != YUVORDER_YUYV && ibuf[18] != YUVORDER_UYVY) { + LOG("illegal yuvorder %d\n",ibuf[18]); + up(&cam->param_lock); + return -1; + } + in_uyvy = ibuf[18] == YUVORDER_UYVY; + +#if 0 + /* FIXME: ROI mismatch occurs when switching capture sizes */ + if ((ibuf[24] != cam->params.roi.colStart) || + (ibuf[25] != cam->params.roi.colEnd) || + (ibuf[26] != cam->params.roi.rowStart) || + (ibuf[27] != cam->params.roi.rowEnd)) { + LOG("ROI mismatch\n"); + up(&cam->param_lock); + return -1; + } +#endif + + if ((ibuf[28] != NOT_COMPRESSED) && (ibuf[28] != COMPRESSED)) { + LOG("illegal compression %d\n",ibuf[28]); + up(&cam->param_lock); + return -1; + } + compressed = (ibuf[28] == COMPRESSED); + + if (ibuf[29] != NO_DECIMATION) { + LOG("decimation not supported\n"); + up(&cam->param_lock); + return -1; + } + + cam->params.yuvThreshold.yThreshold = ibuf[30]; + cam->params.yuvThreshold.uvThreshold = ibuf[31]; + cam->params.status.systemState = ibuf[32]; + cam->params.status.grabState = ibuf[33]; + cam->params.status.streamState = ibuf[34]; + cam->params.status.fatalError = ibuf[35]; + cam->params.status.cmdError = ibuf[36]; + cam->params.status.debugFlags = ibuf[37]; + cam->params.status.vpStatus = ibuf[38]; + cam->params.status.errorCode = ibuf[39]; + cam->fps = ibuf[41]; + up(&cam->param_lock); + + ibuf += FRAME_HEADER_SIZE; + size -= FRAME_HEADER_SIZE; + ll = ibuf[0] | (ibuf[1] << 8); + ibuf += 2; + + while (size > 0) { + size -= (ll+2); + if (size < 0) { + LOG("Insufficient data in buffer\n"); + return -1; + } + + while (ll > 1) { + if (!compressed || (compressed && !(*ibuf & 1))) { + obuf += yuvconvert(ibuf, obuf, out_fmt, + in_uyvy, cam->mmap_kludge); + ibuf += 4; + ll -= 4; + } else { + /*skip compressed interval from previous frame*/ + int skipsize = skipcount(*ibuf >> 1, out_fmt); + obuf += skipsize; + if (obuf > end_obuf) { + LOG("Insufficient data in buffer\n"); + return -1; + } + ++ibuf; + ll--; + } + } + if (ll == 1) { + if (*ibuf != EOL) { + LOG("EOL not found giving up after %d/%d" + " bytes\n", origsize-size, origsize); + return -1; + } + + ibuf++; /* skip over EOL */ + + if ((size > 3) && (ibuf[0] == EOI) && (ibuf[1] == EOI) && + (ibuf[2] == EOI) && (ibuf[3] == EOI)) { + size -= 4; + break; + } + + if (size > 1) { + ll = ibuf[0] | (ibuf[1] << 8); + ibuf += 2; /* skip over line length */ + } + } else { + LOG("line length was not 1 but %d after %d/%d bytes\n", + ll, origsize-size, origsize); + return -1; + } + } + + cam->decompressed_frame.count = obuf-cam->decompressed_frame.data; + + return cam->decompressed_frame.count; +} + +/* InitStreamCap wrapper to select correct start line */ +static inline int init_stream_cap(struct cam_data *cam) +{ + return do_command(cam, CPIA_COMMAND_InitStreamCap, + 0, cam->params.streamStartLine, 0, 0); +} + +/* update various camera modes and settings */ +static void dispatch_commands(struct cam_data *cam) +{ + down(&cam->param_lock); + if (cam->cmd_queue==COMMAND_NONE) { + up(&cam->param_lock); + return; + } + DEB_BYTE(cam->cmd_queue); + DEB_BYTE(cam->cmd_queue>>8); + if (cam->cmd_queue & COMMAND_SETCOLOURPARAMS) + do_command(cam, CPIA_COMMAND_SetColourParams, + cam->params.colourParams.brightness, + cam->params.colourParams.contrast, + cam->params.colourParams.saturation, 0); + + if (cam->cmd_queue & COMMAND_SETCOMPRESSION) + do_command(cam, CPIA_COMMAND_SetCompression, + cam->params.compression.mode, + cam->params.compression.decimation, 0, 0); + + if (cam->cmd_queue & COMMAND_SETFORMAT) { + do_command(cam, CPIA_COMMAND_SetFormat, + cam->params.format.videoSize, + cam->params.format.subSample, + cam->params.format.yuvOrder, 0); + do_command(cam, CPIA_COMMAND_SetROI, + cam->params.roi.colStart, cam->params.roi.colEnd, + cam->params.roi.rowStart, cam->params.roi.rowEnd); + cam->first_frame = 1; + } + + if (cam->cmd_queue & COMMAND_SETCOMPRESSIONTARGET) + do_command(cam, CPIA_COMMAND_SetCompressionTarget, + cam->params.compressionTarget.frTargeting, + cam->params.compressionTarget.targetFR, + cam->params.compressionTarget.targetQ, 0); + + if (cam->cmd_queue & COMMAND_SETYUVTHRESH) + do_command(cam, CPIA_COMMAND_SetYUVThresh, + cam->params.yuvThreshold.yThreshold, + cam->params.yuvThreshold.uvThreshold, 0, 0); + + if (cam->cmd_queue & COMMAND_SETECPTIMING) + do_command(cam, CPIA_COMMAND_SetECPTiming, + cam->params.ecpTiming, 0, 0, 0); + + if (cam->cmd_queue & COMMAND_SETCOMPRESSIONPARAMS) + do_command_extended(cam, CPIA_COMMAND_SetCompressionParams, + 0, 0, 0, 0, + cam->params.compressionParams.hysteresis, + cam->params.compressionParams.threshMax, + cam->params.compressionParams.smallStep, + cam->params.compressionParams.largeStep, + cam->params.compressionParams.decimationHysteresis, + cam->params.compressionParams.frDiffStepThresh, + cam->params.compressionParams.qDiffStepThresh, + cam->params.compressionParams.decimationThreshMod); + + if (cam->cmd_queue & COMMAND_SETEXPOSURE) + do_command_extended(cam, CPIA_COMMAND_SetExposure, + cam->params.exposure.gainMode, + cam->params.exposure.expMode, + cam->params.exposure.compMode, + cam->params.exposure.centreWeight, + cam->params.exposure.gain, + cam->params.exposure.fineExp, + cam->params.exposure.coarseExpLo, + cam->params.exposure.coarseExpHi, + cam->params.exposure.redComp, + cam->params.exposure.green1Comp, + cam->params.exposure.green2Comp, + cam->params.exposure.blueComp); + + if (cam->cmd_queue & COMMAND_SETCOLOURBALANCE) { + if (cam->params.colourBalance.balanceModeIsAuto) { + do_command(cam, CPIA_COMMAND_SetColourBalance, + 2, 0, 0, 0); + } else { + do_command(cam, CPIA_COMMAND_SetColourBalance, + 1, + cam->params.colourBalance.redGain, + cam->params.colourBalance.greenGain, + cam->params.colourBalance.blueGain); + do_command(cam, CPIA_COMMAND_SetColourBalance, + 3, 0, 0, 0); + } + } + + if (cam->cmd_queue & COMMAND_SETSENSORFPS) + do_command(cam, CPIA_COMMAND_SetSensorFPS, + cam->params.sensorFps.divisor, + cam->params.sensorFps.baserate, 0, 0); + + if (cam->cmd_queue & COMMAND_SETAPCOR) + do_command(cam, CPIA_COMMAND_SetApcor, + cam->params.apcor.gain1, + cam->params.apcor.gain2, + cam->params.apcor.gain4, + cam->params.apcor.gain8); + + if (cam->cmd_queue & COMMAND_SETFLICKERCTRL) + do_command(cam, CPIA_COMMAND_SetFlickerCtrl, + cam->params.flickerControl.flickerMode, + cam->params.flickerControl.coarseJump, + cam->params.flickerControl.allowableOverExposure, 0); + + if (cam->cmd_queue & COMMAND_SETVLOFFSET) + do_command(cam, CPIA_COMMAND_SetVLOffset, + cam->params.vlOffset.gain1, + cam->params.vlOffset.gain2, + cam->params.vlOffset.gain4, + cam->params.vlOffset.gain8); + + if (cam->cmd_queue & COMMAND_PAUSE) + do_command(cam, CPIA_COMMAND_EndStreamCap, 0, 0, 0, 0); + + if (cam->cmd_queue & COMMAND_RESUME) + init_stream_cap(cam); + + up(&cam->param_lock); + cam->cmd_queue = COMMAND_NONE; + return; +} + +/* kernel thread function to read image from camera */ +static void fetch_frame(void *data) +{ + int image_size, retry; + struct cam_data *cam = (struct cam_data *)data; + unsigned long oldjif, rate, diff; + + /* Allow up to two bad images in a row to be read and + * ignored before an error is reported */ + for (retry = 0; retry < 3; ++retry) { + if (retry) + DBG("retry=%d\n", retry); + + if (!cam->ops) + continue; + + /* load first frame always uncompressed */ + if (cam->first_frame && + cam->params.compression.mode != CPIA_COMPRESSION_NONE) + do_command(cam, CPIA_COMMAND_SetCompression, + CPIA_COMPRESSION_NONE, + NO_DECIMATION, 0, 0); + + /* init camera upload */ + if (do_command(cam, CPIA_COMMAND_SetGrabMode, + CPIA_GRAB_CONTINUOUS, 0, 0, 0)) + continue; + + if (do_command(cam, CPIA_COMMAND_GrabFrame, 0, + cam->params.streamStartLine, 0, 0)) + continue; + + if (cam->ops->wait_for_stream_ready) { + /* loop until image ready */ + do_command(cam, CPIA_COMMAND_GetCameraStatus,0,0,0,0); + while (cam->params.status.streamState != STREAM_READY) { + if (current->need_resched) + schedule(); + + current->state = TASK_INTERRUPTIBLE; + + /* sleep for 10 ms, hopefully ;) */ + schedule_timeout(10*HZ/1000); + if (signal_pending(current)) + return; + + do_command(cam, CPIA_COMMAND_GetCameraStatus, + 0, 0, 0, 0); + } + } + + /* grab image from camera */ + if (current->need_resched) + schedule(); + + oldjif = jiffies; + image_size = cam->ops->streamRead(cam->lowlevel_data, + cam->raw_image, 0); + if (image_size <= 0) { + DBG("streamRead failed: %d\n", image_size); + continue; + } + + rate = image_size * HZ / 1024; + diff = jiffies-oldjif; + cam->transfer_rate = diff==0 ? rate : rate/diff; + /* diff==0 ? unlikely but possible */ + + /* camera idle now so dispatch queued commands */ + dispatch_commands(cam); + + /* Update our knowledge of the camera state - FIXME: necessary? */ + do_command(cam, CPIA_COMMAND_GetColourBalance, 0, 0, 0, 0); + do_command(cam, CPIA_COMMAND_GetExposure, 0, 0, 0, 0); + + /* decompress and convert image to by copying it from + * raw_image to decompressed_frame + */ + if (current->need_resched) + schedule(); + + cam->image_size = parse_picture(cam, image_size); + if (cam->image_size <= 0) + DBG("parse_picture failed %d\n", cam->image_size); + else + break; + } + + if (retry < 3) { + /* FIXME: this only works for double buffering */ + if (cam->frame[cam->curframe].state == FRAME_READY) { + memcpy(cam->frame[cam->curframe].data, + cam->decompressed_frame.data, + cam->decompressed_frame.count); + cam->frame[cam->curframe].state = FRAME_DONE; + } else + cam->decompressed_frame.state = FRAME_DONE; + +#if 0 + if (cam->first_frame && + cam->params.compression.mode != CPIA_COMPRESSION_NONE) { + cam->first_frame = 0; + cam->cmd_queue |= COMMAND_SETCOMPRESSION; + } +#else + if (cam->first_frame) { + cam->first_frame = 0; + cam->cmd_queue |= COMMAND_SETCOMPRESSION; + cam->cmd_queue |= COMMAND_SETEXPOSURE; + } +#endif + } +} + +static int capture_frame(struct cam_data *cam, struct video_mmap *vm) +{ + int retval = 0; + + if (!cam->frame_buf) { + /* we do lazy allocation */ + if ((retval = allocate_frame_buf(cam))) + return retval; + } + + /* FIXME: the first frame seems to be captured by the camera + without regards to any initial settings, so we throw away + that one, the next one is generated with our settings + (exposure, color balance, ...) + */ + if (cam->first_frame) { + cam->curframe = vm->frame; + cam->frame[cam->curframe].state = FRAME_READY; + fetch_frame(cam); + if (cam->frame[cam->curframe].state != FRAME_DONE) + retval = -EIO; + } + cam->curframe = vm->frame; + cam->frame[cam->curframe].state = FRAME_READY; + fetch_frame(cam); + if (cam->frame[cam->curframe].state != FRAME_DONE) + retval=-EIO; + + return retval; +} + +static int goto_high_power(struct cam_data *cam) +{ + if (do_command(cam, CPIA_COMMAND_GotoHiPower, 0, 0, 0, 0)) + return -1; + mdelay(100); /* windows driver does it too */ + if (do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0)) + return -1; + if (cam->params.status.systemState == HI_POWER_STATE) { + DBG("camera now in HIGH power state\n"); + return 0; + } + printstatus(cam); + return -1; +} + +static int goto_low_power(struct cam_data *cam) +{ + if (do_command(cam, CPIA_COMMAND_GotoLoPower, 0, 0, 0, 0)) + return -1; + if (do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0)) + return -1; + if (cam->params.status.systemState == LO_POWER_STATE) { + DBG("camera now in LOW power state\n"); + return 0; + } + printstatus(cam); + return -1; +} + +static void save_camera_state(struct cam_data *cam) +{ + do_command(cam, CPIA_COMMAND_GetColourBalance, 0, 0, 0, 0); + do_command(cam, CPIA_COMMAND_GetExposure, 0, 0, 0, 0); + + DBG("%d/%d/%d/%d/%d/%d/%d/%d\n", + cam->params.exposure.gain, + cam->params.exposure.fineExp, + cam->params.exposure.coarseExpLo, + cam->params.exposure.coarseExpHi, + cam->params.exposure.redComp, + cam->params.exposure.green1Comp, + cam->params.exposure.green2Comp, + cam->params.exposure.blueComp); + DBG("%d/%d/%d\n", + cam->params.colourBalance.redGain, + cam->params.colourBalance.greenGain, + cam->params.colourBalance.blueGain); +} + +static void set_camera_state(struct cam_data *cam) +{ + if(cam->params.colourBalance.balanceModeIsAuto) { + do_command(cam, CPIA_COMMAND_SetColourBalance, + 2, 0, 0, 0); + } else { + do_command(cam, CPIA_COMMAND_SetColourBalance, + 1, + cam->params.colourBalance.redGain, + cam->params.colourBalance.greenGain, + cam->params.colourBalance.blueGain); + do_command(cam, CPIA_COMMAND_SetColourBalance, + 3, 0, 0, 0); + } + + + do_command_extended(cam, CPIA_COMMAND_SetExposure, + cam->params.exposure.gainMode, 1, 1, + cam->params.exposure.centreWeight, + cam->params.exposure.gain, + cam->params.exposure.fineExp, + cam->params.exposure.coarseExpLo, + cam->params.exposure.coarseExpHi, + cam->params.exposure.redComp, + cam->params.exposure.green1Comp, + cam->params.exposure.green2Comp, + cam->params.exposure.blueComp); + do_command_extended(cam, CPIA_COMMAND_SetExposure, + 0, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0); + + if (!cam->params.exposure.gainMode) + cam->params.exposure.gainMode = 2; + if (!cam->params.exposure.expMode) + cam->params.exposure.expMode = 2; + if (!cam->params.exposure.centreWeight) + cam->params.exposure.centreWeight = 1; + + cam->cmd_queue = COMMAND_SETCOMPRESSION | + COMMAND_SETCOMPRESSIONTARGET | + COMMAND_SETCOLOURPARAMS | + COMMAND_SETFORMAT | + COMMAND_SETYUVTHRESH | + COMMAND_SETECPTIMING | + COMMAND_SETCOMPRESSIONPARAMS | +#if 0 + COMMAND_SETEXPOSURE | +#endif + COMMAND_SETCOLOURBALANCE | + COMMAND_SETSENSORFPS | + COMMAND_SETAPCOR | + COMMAND_SETFLICKERCTRL | + COMMAND_SETVLOFFSET; + dispatch_commands(cam); + save_camera_state(cam); + + return; +} + +static void get_version_information(struct cam_data *cam) +{ + /* GetCPIAVersion */ + do_command(cam, CPIA_COMMAND_GetCPIAVersion, 0, 0, 0, 0); + + /* GetPnPID */ + do_command(cam, CPIA_COMMAND_GetPnPID, 0, 0, 0, 0); +} + +/* initialize camera */ +static int reset_camera(struct cam_data *cam) +{ + /* Start the camera in low power mode */ + if (goto_low_power(cam)) { + if (cam->params.status.systemState != WARM_BOOT_STATE) + return -ENODEV; + + /* FIXME: this is just dirty trial and error */ + reset_camera_struct(cam); + goto_high_power(cam); + do_command(cam, CPIA_COMMAND_DiscardFrame, 0, 0, 0, 0); + if (goto_low_power(cam)) + return -NODEV; + } + + /* procedure described in developer's guide p3-28 */ + + /* Check the firmware version FIXME: should we check PNPID? */ + cam->params.version.firmwareVersion = 0; + get_version_information(cam); + if (cam->params.version.firmwareVersion != 1) + return -ENODEV; + + /* The fatal error checking should be done after + * the camera powers up (developer's guide p 3-38) */ + + /* Set streamState before transition to high power to avoid bug + * in firmware 1-02 */ + do_command(cam, CPIA_COMMAND_ModifyCameraStatus, STREAMSTATE, 0, + STREAM_NOT_READY, 0); + + /* GotoHiPower */ + if (goto_high_power(cam)) + return -ENODEV; + + /* Check the camera status */ + if (do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0)) + return -EIO; + + if (cam->params.status.fatalError) { + DBG("fatal_error: %#04x\n", + cam->params.status.fatalError); + DBG("vp_status: %#04x\n", + cam->params.status.vpStatus); + if (cam->params.status.fatalError & ~(COM_FLAG|CPIA_FLAG)) { + /* Fatal error in camera */ + return -EIO; + } else if (cam->params.status.fatalError & (COM_FLAG|CPIA_FLAG)) { + /* Firmware 1-02 may do this for parallel port cameras, + * just clear the flags (developer's guide p 3-38) */ + do_command(cam, CPIA_COMMAND_ModifyCameraStatus, + FATALERROR, ~(COM_FLAG|CPIA_FLAG), 0, 0); + } + } + + /* Check the camera status again */ + if (cam->params.status.fatalError) { + if (cam->params.status.fatalError) + return -EIO; + } + + /* VPVersion can't be retrieved before the camera is in HiPower, + * so get it here instead of in get_version_information. */ + do_command(cam, CPIA_COMMAND_GetVPVersion, 0, 0, 0, 0); + + /* set camera to a known state */ + set_camera_state(cam); + + return 0; +} + +/* ------------------------- V4L interface --------------------- */ +static int cpia_open(struct video_device *dev, int flags) +{ + int i; + struct cam_data *cam = dev->priv; + + if (!cam) { + DBG("Internal error, cam_data not found!\n"); + return -EBUSY; + } + + if (cam->open_count > 0) { + DBG("Camera already open\n"); + return -EBUSY; + } + + if (!cam->raw_image) { + cam->raw_image = rvmalloc(CPIA_MAX_IMAGE_SIZE); + if (!cam->raw_image) + return -ENOMEM; + } + + if (!cam->decompressed_frame.data) { + cam->decompressed_frame.data = rvmalloc(CPIA_MAX_FRAME_SIZE); + if (!cam->decompressed_frame.data) { + rvfree(cam->raw_image, CPIA_MAX_IMAGE_SIZE); + cam->raw_image = NULL; + return -ENOMEM; + } + } + + /* open cpia */ + if (cam->ops->open(cam->lowlevel_data)) { + rvfree(cam->decompressed_frame.data, CPIA_MAX_FRAME_SIZE); + cam->decompressed_frame.data = NULL; + rvfree(cam->raw_image, CPIA_MAX_IMAGE_SIZE); + cam->raw_image = NULL; + return -ENODEV; + } + + /* reset the camera */ + if ((i = reset_camera(cam)) != 0) { + cam->ops->close(cam->lowlevel_data); + rvfree(cam->decompressed_frame.data, CPIA_MAX_FRAME_SIZE); + cam->decompressed_frame.data = NULL; + rvfree(cam->raw_image, CPIA_MAX_IMAGE_SIZE); + cam->raw_image = NULL; + return i; + } + + /* Set ownership of /proc/cpia/videoX to current user */ + if(cam->proc_entry) + cam->proc_entry->uid = current->uid; + + /* set mark for loading first frame uncompressed */ + cam->first_frame = 1; + + /* init it to something */ + cam->mmap_kludge = 0; + + ++cam->open_count; +#ifdef MODULE + MOD_INC_USE_COUNT; +#endif + return 0; +} + +static void cpia_close(struct video_device *dev) +{ + struct cam_data *cam; + + cam = dev->priv; + + if (cam->ops) { + /* Return ownership of /proc/cpia/videoX to root */ + if(cam->proc_entry) + cam->proc_entry->uid = 0; + + /* save camera state for later open (developers guide ch 3.5.3) */ + save_camera_state(cam); + + /* GotoLoPower */ + goto_low_power(cam); + + /* Update the camera ststus */ + do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0); + + /* cleanup internal state stuff */ + free_frames(cam->frame); + + /* close cpia */ + cam->ops->close(cam->lowlevel_data); + } + + if (--cam->open_count == 0) { + /* clean up capture-buffers */ + if (cam->raw_image) { + rvfree(cam->raw_image, CPIA_MAX_IMAGE_SIZE); + cam->raw_image = NULL; + } + + if (cam->decompressed_frame.data) { + rvfree(cam->decompressed_frame.data, CPIA_MAX_FRAME_SIZE); + cam->decompressed_frame.data = NULL; + } + + if (cam->frame_buf) + free_frame_buf(cam); + + if (!cam->ops) { + video_unregister_device(dev); + kfree(cam); + } + } + + +#ifdef MODULE + MOD_DEC_USE_COUNT; +#endif + return; +} + +static long cpia_read(struct video_device *dev, char *buf, + unsigned long count, int noblock) +{ + struct cam_data *cam = dev->priv; + + /* make this _really_ smp and multithredi-safe */ + if (down_interruptible(&cam->busy_lock)) + return -EINTR; + + if (!buf) { + DBG("buf NULL\n"); + up(&cam->busy_lock); + return -EINVAL; + } + + if (!count) { + DBG("count 0\n"); + up(&cam->busy_lock); + return 0; + } + + if (!cam->ops) { + DBG("ops NULL\n"); + up(&cam->busy_lock); + return -ENODEV; + } + + /* upload frame */ + cam->decompressed_frame.state = FRAME_READY; + cam->mmap_kludge=0; + fetch_frame(cam); + if (cam->decompressed_frame.state != FRAME_DONE) { + DBG("upload failed %d/%d\n", cam->decompressed_frame.count, + cam->decompressed_frame.state); + up(&cam->busy_lock); + return -EIO; + } + cam->decompressed_frame.state = FRAME_UNUSED; + + /* copy data to user space */ + if (cam->decompressed_frame.count > count) { + DBG("count wrong: %d, %lu\n", cam->decompressed_frame.count, + count); + up(&cam->busy_lock); + return -EFAULT; + } + if (copy_to_user(buf, cam->decompressed_frame.data, + cam->decompressed_frame.count)) { + DBG("copy_to_user failed\n"); + up(&cam->busy_lock); + return -EFAULT; + } + + up(&cam->busy_lock); + return cam->decompressed_frame.count; +} + +static int cpia_ioctl(struct video_device *dev, unsigned int ioctlnr, void *arg) +{ + struct cam_data *cam = dev->priv; + int retval = 0; + + if (!cam || !cam->ops) + return -ENODEV; + + /* make this _really_ smp-safe */ + if (down_interruptible(&cam->busy_lock)) + return -EINTR; + + //DBG("cpia_ioctl: %u\n", ioctlnr); + + switch (ioctlnr) { + /* query capabilites */ + case VIDIOCGCAP: + { + struct video_capability b; + + DBG("VIDIOCGCAP\n"); + strcpy(b.name, "CPiA Camera"); + b.type = VID_TYPE_CAPTURE; + b.channels = 1; + b.audios = 0; + b.maxwidth = 352; /* VIDEOSIZE_CIF */ + b.maxheight = 288; + b.minwidth = 48; /* VIDEOSIZE_48_48 */ + b.minheight = 48; + + if (copy_to_user(arg, &b, sizeof(b))) + retval = -EFAULT; + + break; + } + + /* get/set video source - we are a camera and nothing else */ + case VIDIOCGCHAN: + { + struct video_channel v; + + DBG("VIDIOCGCHAN\n"); + if (copy_from_user(&v, arg, sizeof(v))) { + retval = -EFAULT; + break; + } + if (v.channel != 0) { + retval = -EINVAL; + break; + } + + v.channel = 0; + strcpy(v.name, "Camera"); + v.tuners = 0; + v.flags = 0; + v.type = VIDEO_TYPE_CAMERA; + v.norm = 0; + + if (copy_to_user(arg, &v, sizeof(v))) + retval = -EFAULT; + break; + } + + case VIDIOCSCHAN: + { + int v; + + DBG("VIDIOCSCHAN\n"); + if (copy_from_user(&v, arg, sizeof(v))) + retval = -EFAULT; + + if (retval == 0 && v != 0) + retval = -EINVAL; + + break; + } + + /* image properties */ + case VIDIOCGPICT: + DBG("VIDIOCGPICT\n"); + if (copy_to_user(arg, &cam->vp, sizeof(struct video_picture))) + retval = -EFAULT; + break; + + case VIDIOCSPICT: + { + struct video_picture vp; + + DBG("VIDIOCSPICT\n"); + + /* copy_from_user */ + if (copy_from_user(&vp, arg, sizeof(vp))) { + retval = -EFAULT; + break; + } + + /* check validity */ + DBG("palette: %d\n", vp.palette); + DBG("depth: %d\n", vp.depth); + if (!valid_mode(vp.palette, vp.depth)) { + retval = -EINVAL; + break; + } + + down(&cam->param_lock); + /* brightness, colour, contrast need no check 0-65535 */ + memcpy( &cam->vp, &vp, sizeof(vp) ); + /* update cam->params.colourParams */ + cam->params.colourParams.brightness = vp.brightness*100/65535; + cam->params.colourParams.contrast = vp.contrast*100/65535; + cam->params.colourParams.saturation = vp.colour*100/65535; + /* contrast is in steps of 8, so round */ + cam->params.colourParams.contrast = + ((cam->params.colourParams.contrast + 3) / 8) * 8; + if (cam->params.version.firmwareVersion == 1 && + cam->params.version.firmwareRevision == 2 && + cam->params.colourParams.contrast > 80) { + /* 1-02 firmware limits contrast to 80 */ + cam->params.colourParams.contrast = 80; + } + + /* queue command to update camera */ + cam->cmd_queue |= COMMAND_SETCOLOURPARAMS; + up(&cam->param_lock); + DBG("VIDIOCSPICT: %d / %d // %d / %d / %d / %d\n", + vp.depth, vp.palette, vp.brightness, vp.hue, vp.colour, + vp.contrast); + break; + } + + /* get/set capture window */ + case VIDIOCGWIN: + DBG("VIDIOCGWIN\n"); + + if (copy_to_user(arg, &cam->vw, sizeof(struct video_window))) + retval = -EFAULT; + break; + + case VIDIOCSWIN: + { + /* copy_from_user, check validity, copy to internal structure */ + struct video_window vw; + DBG("VIDIOCSWIN\n"); + if (copy_from_user(&vw, arg, sizeof(vw))) { + retval = -EFAULT; + break; + } + + if (vw.clipcount != 0) { /* clipping not supported */ + retval = -EINVAL; + break; + } + if (vw.clips != NULL) { /* clipping not supported */ + retval = -EINVAL; + break; + } + + /* we set the video window to something smaller or equal to what + * is requested by the user??? + */ + down(&cam->param_lock); + if (vw.width != cam->vw.width || vw.height != cam->vw.height) { + int video_size = match_videosize(vw.width, vw.height); + + if (video_size < 0) { + retval = -EINVAL; + up(&cam->param_lock); + break; + } + cam->video_size = video_size; + set_vw_size(cam); + DBG("%d / %d\n", cam->vw.width, cam->vw.height); + cam->cmd_queue |= COMMAND_SETFORMAT; + } + + // FIXME needed??? memcpy(&cam->vw, &vw, sizeof(vw)); + up(&cam->param_lock); + + /* setformat ignored by camera during streaming, + * so stop/dispatch/start */ + if (cam->cmd_queue & COMMAND_SETFORMAT) { + DBG("\n"); + dispatch_commands(cam); + } + DBG("%d/%d:%d\n", cam->video_size, + cam->vw.width, cam->vw.height); + break; + } + + /* mmap interface */ + case VIDIOCGMBUF: + { + struct video_mbuf vm; + int i; + + DBG("VIDIOCGMBUF\n"); + memset(&vm, 0, sizeof(vm)); + vm.size = CPIA_MAX_FRAME_SIZE*FRAME_NUM; + vm.frames = FRAME_NUM; + for (i = 0; i < FRAME_NUM; i++) + vm.offsets[i] = CPIA_MAX_FRAME_SIZE * i; + + if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm))) + retval = -EFAULT; + + break; + } + + case VIDIOCMCAPTURE: + { + struct video_mmap vm; + int video_size; + + if (copy_from_user((void *)&vm, (void *)arg, sizeof(vm))) { + retval = -EFAULT; + break; + } +#if 1 + DBG("VIDIOCMCAPTURE: %d / %d / %dx%d\n", vm.format, vm.frame, + vm.width, vm.height); +#endif + if (vm.frame<0||vm.frame>FRAME_NUM) { + retval = -EINVAL; + break; + } + + /* set video format */ + cam->vp.palette = vm.format; + switch(vm.format) { + case VIDEO_PALETTE_GREY: + case VIDEO_PALETTE_RGB555: + case VIDEO_PALETTE_RGB565: + case VIDEO_PALETTE_YUV422: + case VIDEO_PALETTE_YUYV: + case VIDEO_PALETTE_UYVY: + cam->vp.depth = 16; + break; + case VIDEO_PALETTE_RGB24: + cam->vp.depth = 24; + break; + case VIDEO_PALETTE_RGB32: + cam->vp.depth = 32; + break; + default: + retval = -EINVAL; + break; + } + if (retval) + break; + + /* set video size */ + video_size = match_videosize(vm.width, vm.height); + if (cam->video_size < 0) { + retval = -EINVAL; + break; + } + if (video_size != cam->video_size) { + cam->video_size = video_size; + set_vw_size(cam); + cam->cmd_queue |= COMMAND_SETFORMAT; + dispatch_commands(cam); + } +#if 0 + DBG("VIDIOCMCAPTURE: %d / %d/%d\n", cam->video_size, + cam->vw.width, cam->vw.height); +#endif + /* according to v4l-spec we must start streaming here */ + cam->mmap_kludge = 1; + retval = capture_frame(cam, &vm); + + break; + } + + case VIDIOCSYNC: + { + int frame; + + if (copy_from_user((void *)&frame, arg, sizeof(int))) { + retval = -EFAULT; + break; + } + //DBG("VIDIOCSYNC: %d\n", frame); + + if (frame<0 || frame >= FRAME_NUM) { + retval = -EINVAL; + break; + } + + switch (cam->frame[frame].state) { + case FRAME_UNUSED: + case FRAME_READY: + case FRAME_GRABBING: + DBG("sync to unused frame %d\n", frame); + retval = -EINVAL; + break; + + case FRAME_DONE: + cam->frame[frame].state = FRAME_UNUSED; + //DBG("VIDIOCSYNC: %d synced\n", frame); + break; + } + if (retval == -EINTR) { + /* FIXME - xawtv does not handle this nice */ + retval = 0; + } + break; + } + + /* pointless to implement overlay with this camera */ + case VIDIOCCAPTURE: + retval = -EINVAL; + break; + case VIDIOCGFBUF: + retval = -EINVAL; + break; + case VIDIOCSFBUF: + retval = -EINVAL; + break; + case VIDIOCKEY: + retval = -EINVAL; + break; + + /* tuner interface - we have none */ + case VIDIOCGTUNER: + retval = -EINVAL; + break; + case VIDIOCSTUNER: + retval = -EINVAL; + break; + case VIDIOCGFREQ: + retval = -EINVAL; + break; + case VIDIOCSFREQ: + retval = -EINVAL; + break; + + /* audio interface - we have none */ + case VIDIOCGAUDIO: + retval = -EINVAL; + break; + case VIDIOCSAUDIO: + retval = -EINVAL; + break; + default: + retval = -ENOIOCTLCMD; + break; + } + + up(&cam->param_lock); + up(&cam->busy_lock); + return retval; +} + +/* FIXME */ +static int cpia_mmap(struct video_device *dev, const char *adr, + unsigned long size) +{ + unsigned long start = (unsigned long)adr; + unsigned long page, pos; + struct cam_data *cam = dev->priv; + int retval; + + if (!cam || !cam->ops) + return -ENODEV; + + DBG("cpia_mmap: %ld\n", size); + + if (size > FRAME_NUM*CPIA_MAX_FRAME_SIZE) + return -EINVAL; + + if (!cam || !cam->ops) + return -ENODEV; + + /* make this _really_ smp-safe */ + if (down_interruptible(&cam->busy_lock)) + return -EINTR; + + if (!cam->frame_buf) { /* we do lazy allocation */ + if ((retval = allocate_frame_buf(cam))) { + up(&cam->busy_lock); + return retval; + } + } + + pos = (unsigned long)(cam->frame_buf); + while (size > 0) { + page = kvirt_to_pa(pos); + if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) { + up(&cam->busy_lock); + return -EAGAIN; + } + start += PAGE_SIZE; + pos += PAGE_SIZE; + if (size > PAGE_SIZE) + size -= PAGE_SIZE; + else + size = 0; + } + + DBG("cpia_mmap: %ld\n", size); + up(&cam->busy_lock); + + return 0; +} + +int cpia_video_init(struct video_device *vdev) +{ +#ifdef CONFIG_PROC_FS + create_proc_cpia_cam(vdev->priv); +#endif + return 0; +} + +static struct video_device cpia_template = { + "CPiA Camera", + VID_TYPE_CAPTURE, + VID_HARDWARE_CPIA, /* FIXME */ + cpia_open, /* open */ + cpia_close, /* close */ + cpia_read, /* read */ + NULL, /* no write */ + NULL, /* no poll */ + cpia_ioctl, /* ioctl */ + cpia_mmap, /* mmap */ + cpia_video_init, /* initialize */ + NULL, /* priv */ + 0, /* busy */ + -1 /* minor - unset */ +}; + +/* initialise cam_data structure */ +static void reset_camera_struct(struct cam_data *cam) +{ + /* The following parameter values are the defaults from + * "Software Developer's Guide for CPiA Cameras". Any changes + * to the defaults are noted in comments. */ + cam->params.colourParams.brightness = 50; + cam->params.colourParams.contrast = 48; + cam->params.colourParams.saturation = 50; + cam->params.exposure.gainMode = 2; + cam->params.exposure.expMode = 2; /* AEC */ + cam->params.exposure.compMode = 1; + cam->params.exposure.centreWeight = 1; + cam->params.exposure.gain = 0; + cam->params.exposure.fineExp = 0; + cam->params.exposure.coarseExpLo = 185; + cam->params.exposure.coarseExpHi = 0; + cam->params.exposure.redComp = 220; + cam->params.exposure.green1Comp = 214; + cam->params.exposure.green2Comp = 214; + cam->params.exposure.blueComp = 230; + cam->params.colourBalance.balanceModeIsAuto = 1; + cam->params.colourBalance.redGain = 32; + cam->params.colourBalance.greenGain = 6; + cam->params.colourBalance.blueGain = 92; + cam->params.apcor.gain1 = 0x1c; + cam->params.apcor.gain2 = 0x1a; + cam->params.apcor.gain4 = 0x2d; + cam->params.apcor.gain8 = 0x2a; + cam->params.flickerControl.flickerMode = 0; + cam->params.flickerControl.coarseJump = + flicker_jumps[cam->mainsFreq] + [cam->params.sensorFps.baserate] + [cam->params.sensorFps.divisor]; + cam->params.vlOffset.gain1 = 24; + cam->params.vlOffset.gain2 = 28; + cam->params.vlOffset.gain4 = 30; + cam->params.vlOffset.gain8 = 30; + cam->params.compressionParams.hysteresis = 3; + cam->params.compressionParams.threshMax = 11; + cam->params.compressionParams.smallStep = 1; + cam->params.compressionParams.largeStep = 3; + cam->params.compressionParams.decimationHysteresis = 2; + cam->params.compressionParams.frDiffStepThresh = 5; + cam->params.compressionParams.qDiffStepThresh = 3; + cam->params.compressionParams.decimationThreshMod = 2; + /* End of default values from Software Developer's Guide */ + + cam->transfer_rate = 0; + + /* Set Sensor FPS to 15fps. This seems better than 30fps + * for indoor lighting. */ + cam->params.sensorFps.divisor = 1; + cam->params.sensorFps.baserate = 1; + + cam->params.yuvThreshold.yThreshold = 15; /* FIXME? */ + cam->params.yuvThreshold.uvThreshold = 15; /* FIXME? */ + + cam->params.format.subSample = SUBSAMPLE_422; + cam->params.format.yuvOrder = YUVORDER_YUYV; + + cam->params.compression.mode = CPIA_COMPRESSION_AUTO; + cam->params.compressionTarget.frTargeting = + CPIA_COMPRESSION_TARGET_QUALITY; + cam->params.compressionTarget.targetFR = 7; /* FIXME? */ + cam->params.compressionTarget.targetQ = 10; /* FIXME? */ + + cam->video_size = VIDEOSIZE_CIF; + + cam->vp.colour = 32768; /* 50% */ + cam->vp.hue = 32768; /* 50% */ + cam->vp.brightness = 32768; /* 50% */ + cam->vp.contrast = 32768; /* 50% */ + cam->vp.whiteness = 0; /* not used -> grayscale only */ + cam->vp.depth = 0; /* FIXME: to be set by user? */ + cam->vp.palette = VIDEO_PALETTE_RGB24; /* FIXME: to be set by user? */ + + cam->vw.x = 0; + cam->vw.y = 0; + set_vw_size(cam); + cam->vw.chromakey = 0; + /* PP NOTE: my extension to use vw.flags for this, bear it! */ + cam->vw.flags = 0; + cam->vw.clipcount = 0; + cam->vw.clips = NULL; + + cam->cmd_queue = COMMAND_NONE; + cam->first_frame = 0; + + return; +} + +/* initialize cam_data structure */ +static void init_camera_struct(struct cam_data *cam, + struct cpia_camera_ops *ops ) +{ + int i; + + /* Default everything to 0 */ + memset(cam, 0, sizeof(struct cam_data)); + + cam->ops = ops; + init_MUTEX(&cam->param_lock); + init_MUTEX(&cam->busy_lock); + + reset_camera_struct(cam); + + cam->proc_entry = NULL; + + memcpy(&cam->vdev, &cpia_template, sizeof(cpia_template)); + cam->vdev.priv = cam; + + cam->curframe = 0; + for (i = 0; i < FRAME_NUM; i++) { + cam->frame[i].width = 0; + cam->frame[i].height = 0; + cam->frame[i].state = FRAME_UNUSED; + cam->frame[i].data = NULL; + } + cam->decompressed_frame.width = 0; + cam->decompressed_frame.height = 0; + cam->decompressed_frame.state = FRAME_UNUSED; + cam->decompressed_frame.data = NULL; +} + +struct cam_data *cpia_register_camera(struct cpia_camera_ops *ops, void *lowlevel) +{ + struct cam_data *camera; + + /* Need a lock when adding/removing cameras. This doesn't happen + * often and doesn't take very long, so grabbing the kernel lock + * should be OK. */ + + if ((camera = kmalloc(sizeof(struct cam_data), GFP_KERNEL)) == NULL) { + unlock_kernel(); + return NULL; + } + + init_camera_struct( camera, ops ); + camera->lowlevel_data = lowlevel; + + /* register v4l device */ + if (video_register_device(&camera->vdev, VFL_TYPE_GRABBER) == -1) { + kfree(camera); + unlock_kernel(); + printk(KERN_DEBUG "video_register_device failed\n"); + return NULL; + } + + /* get version information from camera: open/reset/close */ + + /* open cpia */ + if (camera->ops->open(camera->lowlevel_data)) + return camera; + + /* reset the camera */ + if (reset_camera(camera) != 0) { + camera->ops->close(camera->lowlevel_data); + return camera; + } + + /* close cpia */ + camera->ops->close(camera->lowlevel_data); + +/* Eh? Feeling happy? - jerdfelt */ +/* + camera->ops->open(camera->lowlevel_data); + camera->ops->close(camera->lowlevel_data); +*/ + + printk(KERN_INFO " CPiA Version: %d.%02d (%d.%d)\n", + camera->params.version.firmwareVersion, + camera->params.version.firmwareRevision, + camera->params.version.vcVersion, + camera->params.version.vcRevision); + printk(KERN_INFO " CPiA PnP-ID: %04x:%04x:%04x\n", + camera->params.pnpID.vendor, + camera->params.pnpID.product, + camera->params.pnpID.deviceRevision); + printk(KERN_INFO " VP-Version: %d.%d %04x\n", + camera->params.vpVersion.vpVersion, + camera->params.vpVersion.vpRevision, + camera->params.vpVersion.cameraHeadID); + + return camera; +} + +void cpia_unregister_camera(struct cam_data *cam) +{ + if (!cam->open_count) { + DBG("unregistering video\n"); + video_unregister_device(&cam->vdev); + } else { + LOG("/dev/video%d removed while open, " + "deferring video_unregister_device\n", cam->vdev.minor); + DBG("camera open -- setting ops to NULL\n"); + cam->ops = NULL; + } + +#ifdef CONFIG_PROC_FS + DBG("destroying /proc/cpia/video%d\n", cam->vdev.minor); + destroy_proc_cpia_cam(cam); +#endif + if (!cam->open_count) { + DBG("freeing camera\n"); + kfree(cam); + } +} + +/**************************************************************************** + * + * Module routines + * + ***************************************************************************/ + +#ifdef MODULE +int init_module(void) +{ + printk(KERN_INFO "%s v%d.%d.%d\n", ABOUT, + CPIA_MAJ_VER, CPIA_MIN_VER, CPIA_PATCH_VER); +#ifdef CONFIG_PROC_FS + proc_cpia_create(); +#endif +#ifdef CONFIG_KMOD +#ifdef CONFIG_VIDEO_CPIA_PP_MODULE + request_module("cpia_pp"); +#endif +#ifdef CONFIG_VIDEO_CPIA_USB_MODULE + request_module("cpia_usb"); +#endif +#endif +return 0; +} + +void cleanup_module(void) +{ +#ifdef CONFIG_PROC_FS + proc_cpia_destroy(); +#endif +} + +#else + +int cpia_init(struct video_init *unused) +{ + printk(KERN_INFO "%s v%d.%d.%d\n", ABOUT, + CPIA_MAJ_VER, CPIA_MIN_VER, CPIA_PATCH_VER); +#ifdef CONFIG_PROC_FS + proc_cpia_create(); +#endif + +#ifdef CONFIG_VIDEO_CPIA_PP + cpia_pp_init(); +#endif +#ifdef CONFIG_KMOD +#ifdef CONFIG_VIDEO_CPIA_PP_MODULE + request_module("cpia_pp"); +#endif + +#ifdef CONFIG_VIDEO_CPIA_USB_MODULE + request_module("cpia_usb"); +#endif +#endif /* CONFIG_KMOD */ +#ifdef CONFIG_VIDEO_CPIA_USB + cpia_usb_init(); +#endif + return 0; +} + +/* Exported symbols for modules. */ + +EXPORT_SYMBOL(cpia_register_camera); +EXPORT_SYMBOL(cpia_unregister_camera); + +#endif diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/char/cpia.h linux/drivers/char/cpia.h --- v2.3.99-pre3/linux/drivers/char/cpia.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/cpia.h Mon Mar 27 10:22:31 2000 @@ -0,0 +1,421 @@ +#ifndef cpia_h +#define cpia_h + +/* + * CPiA Parallel Port Video4Linux driver + * + * Supports CPiA based parallel port Video Camera's. + * + * (C) Copyright 1999 Bas Huisman, + * Peter Pregler, + * Scott J. Bertin, + * VLSI Vision Ltd. + * + * 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. + */ + +#define CPIA_MAJ_VER 0 +#define CPIA_MIN_VER 7 +#define CPIA_PATCH_VER 4 + +#define CPIA_PP_MAJ_VER 0 +#define CPIA_PP_MIN_VER 7 +#define CPIA_PP_PATCH_VER 4 + +#define CPIA_MAX_FRAME_SIZE_UNALIGNED (352 * 288 * 4) /* CIF at RGB32 */ +#define CPIA_MAX_FRAME_SIZE ((CPIA_MAX_FRAME_SIZE_UNALIGNED + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)) /* align above to PAGE_SIZE */ + +#ifdef __KERNEL__ + +#include +#include +#include + +struct cpia_camera_ops +{ + /* open sets privdata to point to structure for this camera. + * Returns negative value on error, otherwise 0. + */ + int (*open)(void *privdata); + + /* Registers callback function cb to be called with cbdata + * when an image is ready. If cb is NULL, only single image grabs + * should be used. cb should immediately call streamRead to read + * the data or data may be lost. Returns negative value on error, + * otherwise 0. + */ + int (*registerCallback)(void *privdata, void (*cb)(void *cbdata), + void *cbdata); + + /* transferCmd sends commands to the camera. command MUST point to + * an 8 byte buffer in kernel space. data can be NULL if no extra + * data is needed. The size of the data is given by the last 2 + * bytes of comand. data must also point to memory in kernel space. + * Returns negative value on error, otherwise 0. + */ + int (*transferCmd)(void *privdata, u8 *command, u8 *data); + + /* streamStart initiates stream capture mode. + * Returns negative value on error, otherwise 0. + */ + int (*streamStart)(void *privdata); + + /* streamStop terminates stream capture mode. + * Returns negative value on error, otherwise 0. + */ + int (*streamStop)(void *privdata); + + /* streamRead reads a frame from the camera. buffer points to a + * buffer large enough to hold a complete frame in kernel space. + * noblock indicates if this should be a non blocking read. + * Returns the number of bytes read, or negative value on error. + */ + int (*streamRead)(void *privdata, u8 *buffer, int noblock); + + /* close disables the device until open() is called again. + * Returns negative value on error, otherwise 0. + */ + int (*close)(void *privdata); + + /* If wait_for_stream_ready is non-zero, wait until the streamState + * is STREAM_READY before calling streamRead. + */ + int wait_for_stream_ready; +}; + +struct cpia_frame { + u8 *data; + int count; + int width; + int height; + volatile int state; +}; + +struct cam_params { + struct { + u8 firmwareVersion; + u8 firmwareRevision; + u8 vcVersion; + u8 vcRevision; + } version; + struct { + u16 vendor; + u16 product; + u16 deviceRevision; + } pnpID; + struct { + u8 vpVersion; + u8 vpRevision; + u16 cameraHeadID; + } vpVersion; + struct { + u8 systemState; + u8 grabState; + u8 streamState; + u8 fatalError; + u8 cmdError; + u8 debugFlags; + u8 vpStatus; + u8 errorCode; + } status; + struct { + u8 brightness; + u8 contrast; + u8 saturation; + } colourParams; + struct { + u8 gainMode; + u8 expMode; + u8 compMode; + u8 centreWeight; + u8 gain; + u8 fineExp; + u8 coarseExpLo; + u8 coarseExpHi; + u8 redComp; + u8 green1Comp; + u8 green2Comp; + u8 blueComp; + } exposure; + struct { + u8 balanceModeIsAuto; + u8 redGain; + u8 greenGain; + u8 blueGain; + } colourBalance; + struct { + u8 divisor; + u8 baserate; + } sensorFps; + struct { + u8 gain1; + u8 gain2; + u8 gain4; + u8 gain8; + } apcor; + struct { + u8 flickerMode; + u8 coarseJump; + u8 allowableOverExposure; + } flickerControl; + struct { + u8 gain1; + u8 gain2; + u8 gain4; + u8 gain8; + } vlOffset; + struct { + u8 mode; + u8 decimation; + } compression; + struct { + u8 frTargeting; + u8 targetFR; + u8 targetQ; + } compressionTarget; + struct { + u8 yThreshold; + u8 uvThreshold; + } yuvThreshold; + struct { + u8 hysteresis; + u8 threshMax; + u8 smallStep; + u8 largeStep; + u8 decimationHysteresis; + u8 frDiffStepThresh; + u8 qDiffStepThresh; + u8 decimationThreshMod; + } compressionParams; + struct { + u8 videoSize; /* CIF/QCIF */ + u8 subSample; + u8 yuvOrder; + } format; + struct { + u8 colStart; /* skip first 8*colStart pixels */ + u8 colEnd; /* finish at 8*colEnd pixels */ + u8 rowStart; /* skip first 4*rowStart lines */ + u8 rowEnd; /* finish at 4*rowEnd lines */ + } roi; + u8 ecpTiming; + u8 streamStartLine; +}; + +enum v4l_camstates { + CPIA_V4L_IDLE = 0, + CPIA_V4L_ERROR, + CPIA_V4L_COMMAND, + CPIA_V4L_GRABBING, + CPIA_V4L_STREAMING, + CPIA_V4L_STREAMING_PAUSED, +}; + +#define FRAME_NUM 2 /* double buffering for now */ + +struct cam_data { + struct cam_data **previous; + struct cam_data *next; + + struct semaphore busy_lock; /* guard against SMP multithreading */ + struct cpia_camera_ops *ops; /* lowlevel driver operations */ + void *lowlevel_data; /* private data for lowlevel driver */ + u8 *raw_image; /* buffer for raw image data */ + struct cpia_frame decompressed_frame; + /* buffer to hold decompressed frame */ + int image_size; /* sizeof last decompressed image */ + int open_count; /* # of process that have camera open */ + + /* camera status */ + int fps; /* actual fps reported by the camera */ + int transfer_rate; /* transfer rate from camera in kB/s */ + u8 mainsFreq; /* for flicker control */ + + /* proc interface */ + struct semaphore param_lock; /* params lock for this camera */ + struct cam_params params; /* camera settings */ + struct proc_dir_entry *proc_entry; /* /proc/cpia/videoX */ + + /* v4l */ + int video_size; /* VIDEO_SIZE_ */ + volatile enum v4l_camstates camstate; /* v4l layer status */ + struct video_device vdev; /* v4l videodev */ + struct video_picture vp; /* v4l camera settings */ + struct video_window vw; /* v4l capture area */ + + /* mmap interface */ + int curframe; /* the current frame to grab into */ + u8 *frame_buf; /* frame buffer data */ + struct cpia_frame frame[FRAME_NUM]; + /* FRAME_NUM-buffering, so we need a array */ + + int first_frame; + int mmap_kludge; /* 'wrong' byte order for mmap */ + volatile u32 cmd_queue; /* queued commands */ +}; + +/* cpia_register_camera is called by low level driver for each camera. + * A unique camera number is returned, or a negative value on error */ +struct cam_data *cpia_register_camera(struct cpia_camera_ops *ops, void *lowlevel); + +/* cpia_unregister_camera is called by low level driver when a camera + * is removed. This must not fail. */ +void cpia_unregister_camera(struct cam_data *cam); + +/* raw CIF + 64 byte header + (2 bytes line_length + EOL) per line + 4*EOI + + * one byte 16bit DMA alignment + */ +#define CPIA_MAX_IMAGE_SIZE ((352*288*2)+64+(288*3)+5) + +/* constant value's */ +#define MAGIC_0 0x19 +#define MAGIC_1 0x68 +#define DATA_IN 0xC0 +#define DATA_OUT 0x40 +#define VIDEOSIZE_QCIF 0 /* 176x144 */ +#define VIDEOSIZE_CIF 1 /* 352x288 */ +#define VIDEOSIZE_SIF 2 /* 320x240 */ +#define VIDEOSIZE_QSIF 3 /* 160x120 */ +#define VIDEOSIZE_48_48 4 /* where no one has gone before, iconsize! */ +#define VIDEOSIZE_64_48 5 +#define VIDEOSIZE_128_96 6 +#define VIDEOSIZE_160_120 VIDEOSIZE_QSIF +#define VIDEOSIZE_176_144 VIDEOSIZE_QCIF +#define VIDEOSIZE_192_144 7 +#define VIDEOSIZE_224_168 8 +#define VIDEOSIZE_256_192 9 +#define VIDEOSIZE_288_216 10 +#define VIDEOSIZE_320_240 VIDEOSIZE_SIF +#define VIDEOSIZE_352_288 VIDEOSIZE_CIF +#define VIDEOSIZE_88_72 11 /* quarter CIF */ +#define SUBSAMPLE_420 0 +#define SUBSAMPLE_422 1 +#define YUVORDER_YUYV 0 +#define YUVORDER_UYVY 1 +#define NOT_COMPRESSED 0 +#define COMPRESSED 1 +#define NO_DECIMATION 0 +#define DECIMATION_ENAB 1 +#define EOI 0xff /* End Of Image */ +#define EOL 0xfd /* End Of Line */ +#define FRAME_HEADER_SIZE 64 + +/* Image grab modes */ +#define CPIA_GRAB_SINGLE 0 +#define CPIA_GRAB_CONTINUOUS 1 + +/* Compression parameters */ +#define CPIA_COMPRESSION_NONE 0 +#define CPIA_COMPRESSION_AUTO 1 +#define CPIA_COMPRESSION_MANUAL 2 +#define CPIA_COMPRESSION_TARGET_QUALITY 0 +#define CPIA_COMPRESSION_TARGET_FRAMERATE 1 + +/* Return offsets for GetCameraState */ +#define SYSTEMSTATE 0 +#define GRABSTATE 1 +#define STREAMSTATE 2 +#define FATALERROR 3 +#define CMDERROR 4 +#define DEBUGFLAGS 5 +#define VPSTATUS 6 +#define ERRORCODE 7 + +/* SystemState */ +#define UNINITIALISED_STATE 0 +#define PASS_THROUGH_STATE 1 +#define LO_POWER_STATE 2 +#define HI_POWER_STATE 3 +#define WARM_BOOT_STATE 4 + +/* GrabState */ +#define GRAB_IDLE 0 +#define GRAB_ACTIVE 1 +#define GRAB_DONE 2 + +/* StreamState */ +#define STREAM_NOT_READY 0 +#define STREAM_READY 1 +#define STREAM_OPEN 2 +#define STREAM_PAUSED 3 +#define STREAM_FINISHED 4 + +/* Fatal Error, CmdError, and DebugFlags */ +#define CPIA_FLAG 1 +#define SYSTEM_FLAG 2 +#define INT_CTRL_FLAG 4 +#define PROCESS_FLAG 8 +#define COM_FLAG 16 +#define VP_CTRL_FLAG 32 +#define CAPTURE_FLAG 64 +#define DEBUG_FLAG 128 + +/* VPStatus */ +#define VP_STATE_OK 0x00 + +#define VP_STATE_FAILED_VIDEOINIT 0x01 +#define VP_STATE_FAILED_AECACBINIT 0x02 +#define VP_STATE_AEC_MAX 0x04 +#define VP_STATE_ACB_BMAX 0x08 + +#define VP_STATE_ACB_RMIN 0x10 +#define VP_STATE_ACB_GMIN 0x20 +#define VP_STATE_ACB_RMAX 0x40 +#define VP_STATE_ACB_GMAX 0x80 + +/* ErrorCode */ +#define ERROR_FLICKER_BELOW_MIN_EXP 0x01 /*flicker exposure got below minimum exposure */ + +#define ALOG(lineno,fmt,args...) printk(fmt,lineno,##args) +#define LOG(fmt,args...) ALOG((__LINE__),KERN_INFO __FILE__":"__FUNCTION__"(%d):"fmt,##args) + +#ifdef _CPIA_DEBUG_ +#define ADBG(lineno,fmt,args...) printk(fmt, jiffies, lineno, ##args) +#define DBG(fmt,args...) ADBG((__LINE__),KERN_DEBUG __FILE__"(%ld):"__FUNCTION__"(%d):"fmt,##args) +#else +#define DBG(fmn,args...) do {} while(0) +#endif + +#define DEB_BYTE(p)\ + DBG("%1d %1d %1d %1d %1d %1d %1d %1d \n",\ + (p)&0x80?1:0, (p)&0x40?1:0, (p)&0x20?1:0, (p)&0x10?1:0,\ + (p)&0x08?1:0, (p)&0x04?1:0, (p)&0x02?1:0, (p)&0x01?1:0); + +#define ADD_TO_LIST(l, drv) \ + {\ + lock_kernel();\ + (drv)->next = l;\ + (drv)->previous = &(l);\ + (l) = drv;\ + unlock_kernel();\ + } while(0) + +#define REMOVE_FROM_LIST(drv) \ + {\ + if ((drv)->previous != NULL) {\ + lock_kernel();\ + if ((drv)->next != NULL)\ + (drv)->next->previous = (drv)->previous;\ + *((drv)->previous) = (drv)->next;\ + (drv)->previous = NULL;\ + (drv)->next = NULL;\ + unlock_kernel();\ + }\ + } while (0) + + +#endif /* __KERNEL__ */ + +#endif /* cpia_h */ diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/char/cpia_pp.c linux/drivers/char/cpia_pp.c --- v2.3.99-pre3/linux/drivers/char/cpia_pp.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/cpia_pp.c Mon Mar 27 10:22:31 2000 @@ -0,0 +1,745 @@ +/* + * cpia_pp CPiA Parallel Port driver + * + * Supports CPiA based parallel port Video Camera's. + * + * (C) Copyright 1999 Bas Huisman + * (C) Copyright 1999-2000 Scott J. Bertin , + * (C) Copyright 1999-2000 Peter Pregler + * + * 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. + */ + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#ifdef CONFIG_KMOD +#include +#endif + +/* #define _CPIA_DEBUG_ define for verbose debug output */ +#include "cpia.h" + +static int cpia_pp_open(void *privdata); +static int cpia_pp_registerCallback(void *privdata, void (*cb) (void *cbdata), + void *cbdata); +static int cpia_pp_transferCmd(void *privdata, u8 *command, u8 *data); +static int cpia_pp_streamStart(void *privdata); +static int cpia_pp_streamStop(void *privdata); +static int cpia_pp_streamRead(void *privdata, u8 *buffer, int noblock); +static int cpia_pp_close(void *privdata); + +#define ABOUT "Parallel port driver for Vision CPiA based cameras" + +/* IEEE 1284 Compatiblity Mode signal names */ +#define nStrobe PARPORT_CONTROL_STROBE /* inverted */ +#define nAutoFd PARPORT_CONTROL_AUTOFD /* inverted */ +#define nInit PARPORT_CONTROL_INIT +#define nSelectIn PARPORT_CONTROL_SELECT +#define IntrEnable PARPORT_CONTROL_INTEN /* normally zero for no IRQ */ +#define DirBit PARPORT_CONTROL_DIRECTION /* 0 = Forward, 1 = Reverse */ + +#define nFault PARPORT_STATUS_ERROR +#define Select PARPORT_STATUS_SELECT +#define PError PARPORT_STATUS_PAPEROUT +#define nAck PARPORT_STATUS_ACK +#define Busy PARPORT_STATUS_BUSY /* inverted */ + +/* some more */ +#define HostClk nStrobe +#define HostAck nAutoFd +#define nReverseRequest nInit +#define Active_1284 nSelectIn +#define nPeriphRequest nFault +#define XFlag Select +#define nAckReverse PError +#define PeriphClk nAck +#define PeriphAck Busy + +/* these can be used to correct for the inversion on some bits */ +#define STATUS_INVERSION_MASK (Busy) +#define CONTROL_INVERSION_MASK (nStrobe|nAutoFd|nSelectIn) + +#define ECR_empty 0x01 +#define ECR_full 0x02 +#define ECR_serviceIntr 0x04 +#define ECR_dmaEn 0x08 +#define ECR_nErrIntrEn 0x10 + +#define ECR_mode_mask 0xE0 +#define ECR_SPP_mode 0x00 +#define ECR_PS2_mode 0x20 +#define ECR_FIFO_mode 0x40 +#define ECR_ECP_mode 0x60 + +#define ECP_FIFO_SIZE 16 +#define DMA_BUFFER_SIZE PAGE_SIZE + /* for 16bit DMA make sure DMA_BUFFER_SIZE is 16 bit aligned */ +#define PARPORT_CHUNK_SIZE PAGE_SIZE/* >=2.3.x */ + /* we read this many bytes at once */ + +#define GetECRMasked(port,mask) (parport_read_econtrol(port) & (mask)) +#define GetStatus(port) ((parport_read_status(port)^STATUS_INVERSION_MASK)&(0xf8)) +#define SetStatus(port,val) parport_write_status(port,(val)^STATUS_INVERSION_MASK) +#define GetControl(port) ((parport_read_control(port)^CONTROL_INVERSION_MASK)&(0x3f)) +#define SetControl(port,val) parport_write_control(port,(val)^CONTROL_INVERSION_MASK) + +#define GetStatusMasked(port,mask) (GetStatus(port) & (mask)) +#define GetControlMasked(port,mask) (GetControl(port) & (mask)) +#define SetControlMasked(port,mask) SetControl(port,GetControl(port) | (mask)); +#define ClearControlMasked(port,mask) SetControl(port,GetControl(port)&~(mask)); +#define FrobControlBit(port,mask,value) SetControl(port,(GetControl(port)&~(mask))|((value)&(mask))); + +#define PACKET_LENGTH 8 + +/* Magic numbers for defining port-device mappings */ +#define PPCPIA_PARPORT_UNSPEC -4 +#define PPCPIA_PARPORT_AUTO -3 +#define PPCPIA_PARPORT_OFF -2 +#define PPCPIA_PARPORT_NONE -1 + +#ifdef MODULE +static int parport_nr[PARPORT_MAX] = {[0 ... PARPORT_MAX - 1] = PPCPIA_PARPORT_UNSPEC}; +static char *parport[PARPORT_MAX] = {NULL,}; + +MODULE_AUTHOR("B. Huisman & Peter Pregler "); +MODULE_DESCRIPTION("Parallel port driver for Vision CPiA based cameras"); +MODULE_PARM(parport, "1-" __MODULE_STRING(PARPORT_MAX) "s"); +MODULE_PARM_DESC(parport, "'auto' or a list of parallel port numbers. Just like lp."); +#else +static int parport_nr[PARPORT_MAX] __initdata = + {[0 ... PARPORT_MAX - 1] = PPCPIA_PARPORT_UNSPEC}; +static int parport_ptr = 0; +#endif + +struct pp_cam_entry { + struct pardevice *pdev; + struct parport *port; + struct tq_struct cb_task; + int open_count; + wait_queue_head_t wq_stream; + /* image state flags */ + int image_ready; /* we got an interrupt */ + int image_complete; /* we have seen 4 EOI */ + + int streaming; /* we are in streaming mode */ + int stream_irq; +}; + +static struct cpia_camera_ops cpia_pp_ops = +{ + cpia_pp_open, + cpia_pp_registerCallback, + cpia_pp_transferCmd, + cpia_pp_streamStart, + cpia_pp_streamStop, + cpia_pp_streamRead, + cpia_pp_close, + 1 +}; + +static struct cam_data *cam_list; + +#ifdef _CPIA_DEBUG_ +#define DEB_PORT(port) { \ +u8 controll = GetControl(port); \ +u8 statusss = GetStatus(port); \ +DBG("nsel %c per %c naut %c nstrob %c nak %c busy %c nfaul %c sel %c init %c dir %c\n",\ +((controll & nSelectIn) ? 'U' : 'D'), \ +((statusss & PError) ? 'U' : 'D'), \ +((controll & nAutoFd) ? 'U' : 'D'), \ +((controll & nStrobe) ? 'U' : 'D'), \ +((statusss & nAck) ? 'U' : 'D'), \ +((statusss & Busy) ? 'U' : 'D'), \ +((statusss & nFault) ? 'U' : 'D'), \ +((statusss & Select) ? 'U' : 'D'), \ +((controll & nInit) ? 'U' : 'D'), \ +((controll & DirBit) ? 'R' : 'F') \ +); } +#else +#define DEB_PORT(port) {} +#endif + +#define WHILE_OUT_TIMEOUT (HZ/10) +#define DMA_TIMEOUT 10*HZ + +/* FIXME */ +static void cpia_parport_enable_irq( struct parport *port ) { + parport_enable_irq(port); + mdelay(10); + return; +} + +static void cpia_parport_disable_irq( struct parport *port ) { + parport_disable_irq(port); + mdelay(10); + return; +} + +/**************************************************************************** + * + * EndTransferMode + * + ***************************************************************************/ +static void EndTransferMode(struct pp_cam_entry *cam) +{ + parport_negotiate(cam->port, IEEE1284_MODE_COMPAT); +} + +/**************************************************************************** + * + * ForwardSetup + * + ***************************************************************************/ +static int ForwardSetup(struct pp_cam_entry *cam) +{ + int retry; + + /* After some commands the camera needs extra time before + * it will respond again, so we try up to 3 times */ + for(retry=0; retry<3; ++retry) { + if(!parport_negotiate(cam->port, IEEE1284_MODE_ECP)) { + break; + } + } + if(retry == 3) { + DBG("Unable to negotiate ECP mode\n"); + return -1; + } + return 0; +} + +/**************************************************************************** + * + * ReverseSetup + * + ***************************************************************************/ +static int ReverseSetup(struct pp_cam_entry *cam, int extensibility) +{ + int retry; + int mode = IEEE1284_MODE_ECP; + if(extensibility) mode = 8|3|IEEE1284_EXT_LINK; + + /* After some commands the camera needs extra time before + * it will respond again, so we try up to 3 times */ + for(retry=0; retry<3; ++retry) { + if(!parport_negotiate(cam->port, mode)) { + break; + } + } + if(retry == 3) { + if(extensibility) + DBG("Unable to negotiate extensibility mode\n"); + else + DBG("Unable to negotiate ECP mode\n"); + return -1; + } + if(extensibility) cam->port->ieee1284.mode = IEEE1284_MODE_ECP; + return 0; +} + +/**************************************************************************** + * + * WritePacket + * + ***************************************************************************/ +static int WritePacket(struct pp_cam_entry *cam, const u8 *packet, size_t size) +{ + int retval=0; + int size_written; + + if (packet == NULL) { + return -EINVAL; + } + if (ForwardSetup(cam)) { + DBG("Write failed in setup\n"); + return -EIO; + } + size_written = parport_write(cam->port, packet, size); + if(size_written != size) { + DBG("Write failed, wrote %d/%d\n", size_written, size); + retval = -EIO; + } + EndTransferMode(cam); + return retval; +} + +/**************************************************************************** + * + * ReadPacket + * + ***************************************************************************/ +static int ReadPacket(struct pp_cam_entry *cam, u8 *packet, size_t size) +{ + int retval=0; + if (packet == NULL) { + return -EINVAL; + } + if (ReverseSetup(cam, 0)) { + return -EIO; + } + if(parport_read(cam->port, packet, size) != size) { + retval = -EIO; + } + EndTransferMode(cam); + return retval; +} + +/**************************************************************************** + * + * cpia_pp_streamStart + * + ***************************************************************************/ +static int cpia_pp_streamStart(void *privdata) +{ + struct pp_cam_entry *cam = privdata; + DBG("\n"); + cam->streaming=1; + cam->image_ready=0; + //if (ReverseSetup(cam,1)) return -EIO; + if(cam->stream_irq) cpia_parport_enable_irq(cam->port); + return 0; +} + +/**************************************************************************** + * + * cpia_pp_streamStop + * + ***************************************************************************/ +static int cpia_pp_streamStop(void *privdata) +{ + struct pp_cam_entry *cam = privdata; + + DBG("\n"); + cam->streaming=0; + cpia_parport_disable_irq(cam->port); + //EndTransferMode(cam); + + return 0; +} + +static int cpia_pp_read(struct parport *port, u8 *buffer, int len) +{ + int bytes_read, new_bytes; + for(bytes_read=0; bytes_readstreaming) DBG("%d / %d\n", cam->image_ready, noblock); + if( cam->stream_irq ) { + DBG("%d\n", cam->image_ready); + cam->image_ready--; + } + cam->image_complete=0; + if (0/*cam->streaming*/) { + if(!cam->image_ready) { + if(noblock) return -EWOULDBLOCK; + interruptible_sleep_on(&cam->wq_stream); + if( signal_pending(current) ) return -EINTR; + DBG("%d\n", cam->image_ready); + } + } else { + if (ReverseSetup(cam, 1)) { + DBG("unable to ReverseSetup\n"); + return -EIO; + } + } + endseen = 0; + block_size = PARPORT_CHUNK_SIZE; + while( !cam->image_complete ) { + if(current->need_resched) schedule(); + + new_bytes = cpia_pp_read(cam->port, buffer, block_size ); + if( new_bytes <= 0 ) { + break; + } + i=-1; + while(++iimage_complete=1; + break; + } + if( CPIA_MAX_IMAGE_SIZE-read_bytes <= PARPORT_CHUNK_SIZE ) { + block_size=CPIA_MAX_IMAGE_SIZE-read_bytes; + } + } + EndTransferMode(cam); + return cam->image_complete ? read_bytes : -EIO; +} + +/**************************************************************************** + * + * cpia_pp_transferCmd + * + ***************************************************************************/ +static int cpia_pp_transferCmd(void *privdata, u8 *command, u8 *data) +{ + int err; + int retval=0; + int databytes; + struct pp_cam_entry *cam = privdata; + + if(cam == NULL) { + DBG("Internal driver error: cam is NULL\n"); + return -EINVAL; + } + if(command == NULL) { + DBG("Internal driver error: command is NULL\n"); + return -EINVAL; + } + databytes = (((int)command[7])<<8) | command[6]; + if ((err = WritePacket(cam, command, PACKET_LENGTH)) < 0) { + DBG("Error writing command\n"); + return err; + } + if(command[0] == DATA_IN) { + u8 buffer[8]; + if(data == NULL) { + DBG("Internal driver error: data is NULL\n"); + return -EINVAL; + } + if((err = ReadPacket(cam, buffer, 8)) < 0) { + return err; + DBG("Error reading command result\n"); + } + memcpy(data, buffer, databytes); + } else if(command[0] == DATA_OUT) { + if(databytes > 0) { + if(data == NULL) { + DBG("Internal driver error: data is NULL\n"); + retval = -EINVAL; + } else { + if((err=WritePacket(cam, data, databytes)) < 0){ + DBG("Error writing command data\n"); + return err; + } + } + } + } else { + DBG("Unexpected first byte of command: %x\n", command[0]); + retval = -EINVAL; + } + return retval; +} + +/**************************************************************************** + * + * cpia_pp_open + * + ***************************************************************************/ +static int cpia_pp_open(void *privdata) +{ + struct pp_cam_entry *cam = (struct pp_cam_entry *)privdata; + + if (cam == NULL) + return -EINVAL; + + if(cam->open_count == 0) { + if (parport_claim(cam->pdev)) { + DBG("failed to claim the port\n"); + return -EBUSY; + } + parport_negotiate(cam->port, IEEE1284_MODE_COMPAT); + parport_data_forward(cam->port); + parport_write_control(cam->port, PARPORT_CONTROL_SELECT); + udelay(50); + parport_write_control(cam->port, + PARPORT_CONTROL_SELECT + | PARPORT_CONTROL_INIT); + } + + ++cam->open_count; + +#ifdef MODULE + MOD_INC_USE_COUNT; +#endif + return 0; +} + +/**************************************************************************** + * + * cpia_pp_registerCallback + * + ***************************************************************************/ +static int cpia_pp_registerCallback(void *privdata, void (*cb)(void *cbdata), void *cbdata) +{ + struct pp_cam_entry *cam = privdata; + int retval = 0; + + if(cam->port->irq != PARPORT_IRQ_NONE) { + cam->cb_task.routine = cb; + cam->cb_task.data = cbdata; + } else { + retval = -1; + } + return retval; +} + +/**************************************************************************** + * + * cpia_pp_close + * + ***************************************************************************/ +static int cpia_pp_close(void *privdata) +{ + struct pp_cam_entry *cam = privdata; +#ifdef MODULE + MOD_DEC_USE_COUNT; +#endif + if (--cam->open_count == 0) { + parport_release(cam->pdev); + } + return 0; +} + +/**************************************************************************** + * + * cpia_pp_register + * + ***************************************************************************/ +static int cpia_pp_register(struct parport *port) +{ + struct pardevice *pdev = NULL; + struct pp_cam_entry *cam; + struct cam_data *cpia; + + if (!(port->modes & PARPORT_MODE_ECP) && + !(port->modes & PARPORT_MODE_TRISTATE)) { + LOG("port is not ECP capable\n"); + return -ENXIO; + } + + cam = kmalloc(sizeof(struct pp_cam_entry), GFP_KERNEL); + if (cam == NULL) { + LOG("failed to allocate camera structure\n"); + return -ENOMEM; + } + memset(cam,0,sizeof(struct pp_cam_entry)); + + pdev = parport_register_device(port, "cpia_pp", NULL, NULL, + NULL, 0, cam); + + if (!pdev) { + LOG("failed to parport_register_device\n"); + kfree(cam); + return -ENXIO; + } + + cam->pdev = pdev; + cam->port = port; + init_waitqueue_head(&cam->wq_stream); + + cam->streaming = 0; + cam->stream_irq = 0; + + if((cpia = cpia_register_camera(&cpia_pp_ops, cam)) == NULL) { + LOG("failed to cpia_register_camera\n"); + parport_unregister_device(pdev); + kfree(cam); + return -ENXIO; + } + ADD_TO_LIST(cam_list, cpia); + + return 0; +} + +static void cpia_pp_detach (struct parport *port) +{ + struct cam_data *cpia; + + for(cpia = cam_list; cpia != NULL; cpia = cpia->next) { + struct pp_cam_entry *cam = cpia->lowlevel_data; + if (cam && cam->port->number == port->number) { + REMOVE_FROM_LIST(cpia); + + cpia_unregister_camera(cpia); + + if(cam->open_count > 0) { + cpia_pp_close(cam); + } + + parport_unregister_device(cam->pdev); + + kfree(cam); + cpia->lowlevel_data = NULL; + break; + } + } +} + +static void cpia_pp_attach (struct parport *port) +{ + unsigned int i; + + switch (parport_nr[0]) + { + case PPCPIA_PARPORT_UNSPEC: + case PPCPIA_PARPORT_AUTO: + if (port->probe_info[0].class != PARPORT_CLASS_MEDIA || + port->probe_info[0].cmdset == NULL || + strncmp(port->probe_info[0].cmdset, "CPIA_1", 6) != 0) + return; + + cpia_pp_register(port); + + break; + + default: + for (i = 0; i < PARPORT_MAX; ++i) { + if (port->number == parport_nr[i]) { + cpia_pp_register(port); + break; + } + } + break; + } +} + +static struct parport_driver cpia_pp_driver = { + "cpia_pp", + cpia_pp_attach, + cpia_pp_detach, + NULL +}; + +int cpia_pp_init(void) +{ + printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT, + CPIA_PP_MAJ_VER,CPIA_PP_MIN_VER,CPIA_PP_PATCH_VER); + + if(parport_nr[0] == PPCPIA_PARPORT_OFF) { + printk(" disabled\n"); + return 0; + } + + if (parport_register_driver (&cpia_pp_driver)) { + LOG ("unable to register with parport\n"); + return -EIO; + } + + return 0; +} + +#ifdef MODULE +int init_module(void) +{ + if (parport[0]) { + /* The user gave some parameters. Let's see what they were. */ + if (!strncmp(parport[0], "auto", 4)) { + parport_nr[0] = PPCPIA_PARPORT_AUTO; + } else { + int n; + for (n = 0; n < PARPORT_MAX && parport[n]; n++) { + if (!strncmp(parport[n], "none", 4)) { + parport_nr[n] = PPCPIA_PARPORT_NONE; + } else { + char *ep; + unsigned long r = simple_strtoul(parport[n], &ep, 0); + if (ep != parport[n]) { + parport_nr[n] = r; + } else { + LOG("bad port specifier `%s'\n", parport[n]); + return -ENODEV; + } + } + } + } + } +#if defined(CONFIG_KMOD) && defined(CONFIG_PNP_PARPORT_MODULE) + if(parport_enumerate() && !parport_enumerate()->probe_info.model) { + request_module("parport_probe"); + } +#endif + return cpia_pp_init(); +} + +void cleanup_module(void) +{ + parport_unregister_driver (&cpia_pp_driver); + return; +} + +#else /* !MODULE */ + +static int __init cpia_pp_setup(char *str) +{ +#if 0 + /* Is this only a 2.2ism? -jerdfelt */ + if (!str) { + if (ints[0] == 0 || ints[1] == 0) { + /* disable driver on "cpia_pp=" or "cpia_pp=0" */ + parport_nr[0] = PPCPIA_PARPORT_OFF; + } + } else +#endif + if (!strncmp(str, "parport", 7)) { + int n = simple_strtoul(str + 7, NULL, 10); + if (parport_ptr < PARPORT_MAX) { + parport_nr[parport_ptr++] = n; + } else { + LOG("too many ports, %s ignored.\n", str); + } + } else if (!strcmp(str, "auto")) { + parport_nr[0] = PPCPIA_PARPORT_AUTO; + } else if (!strcmp(str, "none")) { + parport_nr[parport_ptr++] = PPCPIA_PARPORT_NONE; + } + + return 0; +} + +__setup("cpia_pp=", cpia_pp_setup); + +#endif /* !MODULE */ diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/char/cpia_usb.c linux/drivers/char/cpia_usb.c --- v2.3.99-pre3/linux/drivers/char/cpia_usb.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/cpia_usb.c Thu Mar 30 18:00:01 2000 @@ -0,0 +1,626 @@ +/* + * cpia_usb CPiA USB driver + * + * Supports CPiA based parallel port Video Camera's. + * + * Copyright (C) 1999 Jochen Scharrlach + * Copyright (C) 1999, 2000 Johannes Erdfelt + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cpia.h" + +#define USB_REQ_CPIA_GRAB_FRAME 0xC1 +#define USB_REQ_CPIA_UPLOAD_FRAME 0xC2 +#define WAIT_FOR_NEXT_FRAME 0 +#define FORCE_FRAME_UPLOAD 1 + +#define FRAMES_PER_DESC 10 +#define FRAME_SIZE_PER_DESC 960 /* Shouldn't be hardcoded */ +#define CPIA_NUMSBUF 2 +#define STREAM_BUF_SIZE (PAGE_SIZE * 4) +#define SCRATCH_BUF_SIZE (STREAM_BUF_SIZE * 2) + +struct cpia_sbuf { + char *data; + urb_t *urb; +}; + +#define FRAMEBUF_LEN (CPIA_MAX_FRAME_SIZE+100) +enum framebuf_status { + FRAME_EMPTY, + FRAME_READING, + FRAME_READY, + FRAME_ERROR, +}; + +struct framebuf { + int length; + enum framebuf_status status; + u8 data[FRAMEBUF_LEN]; + struct framebuf *next; +}; + +struct usb_cpia { + /* Device structure */ + struct usb_device *dev; + + unsigned char iface; + wait_queue_head_t wq_stream; + + int cursbuf; /* Current receiving sbuf */ + struct cpia_sbuf sbuf[CPIA_NUMSBUF]; /* Double buffering */ + + int streaming; + int open; + int present; + struct framebuf *buffers[3]; + struct framebuf *curbuff, *workbuff; +}; + +static int cpia_usb_open(void *privdata); +static int cpia_usb_registerCallback(void *privdata, void (*cb) (void *cbdata), + void *cbdata); +static int cpia_usb_transferCmd(void *privdata, u8 *command, u8 *data); +static int cpia_usb_streamStart(void *privdata); +static int cpia_usb_streamStop(void *privdata); +static int cpia_usb_streamRead(void *privdata, u8 *frame, int noblock); +static int cpia_usb_close(void *privdata); + +#define ABOUT "USB driver for Vision CPiA based cameras" + +static struct cpia_camera_ops cpia_usb_ops = { + cpia_usb_open, + cpia_usb_registerCallback, + cpia_usb_transferCmd, + cpia_usb_streamStart, + cpia_usb_streamStop, + cpia_usb_streamRead, + cpia_usb_close, + 0 +}; + +static struct cam_data *cam_list; + +static void cpia_usb_complete(struct urb *urb) +{ + int i; + char *cdata; + struct usb_cpia *ucpia; + + if (!urb || !urb->context) + return; + + ucpia = (struct usb_cpia *) urb->context; + + if (!ucpia->dev || !ucpia->streaming || !ucpia->present || !ucpia->open) + return; + + if (ucpia->workbuff->status == FRAME_EMPTY) { + ucpia->workbuff->status = FRAME_READING; + ucpia->workbuff->length = 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; + + if (st) + printk(KERN_DEBUG "cpia data error: [%d] len=%d, status=%X\n", i, n, st); + + if (FRAMEBUF_LEN < ucpia->workbuff->length + n) { + printk(KERN_DEBUG "cpia: scratch buf overflow!scr_len: %d, n: %d\n", ucpia->workbuff->length, n); + return; + } + + if (n) { + if ((ucpia->workbuff->length > 0) || + (0x19 == cdata[0] && 0x68 == cdata[1])) { + memcpy(ucpia->workbuff->data + ucpia->workbuff->length, cdata, n); + ucpia->workbuff->length += n; + } else + DBG("Ignoring packet!\n"); + } else { + if (ucpia->workbuff->length > 4 && + 0xff == ucpia->workbuff->data[ucpia->workbuff->length-1] && + 0xff == ucpia->workbuff->data[ucpia->workbuff->length-2] && + 0xff == ucpia->workbuff->data[ucpia->workbuff->length-3] && + 0xff == ucpia->workbuff->data[ucpia->workbuff->length-4]) { + ucpia->workbuff->status = FRAME_READY; + ucpia->curbuff = ucpia->workbuff; + ucpia->workbuff = ucpia->workbuff->next; + ucpia->workbuff->status = FRAME_EMPTY; + ucpia->workbuff->length = 0; + + if (waitqueue_active(&ucpia->wq_stream)) + wake_up_interruptible(&ucpia->wq_stream); + } + } + } +} + +static int cpia_usb_open(void *privdata) +{ + struct usb_cpia *ucpia = (struct usb_cpia *) privdata; + urb_t *urb; + int ret, retval = 0, fx, err; + + if (!ucpia) + return -EINVAL; + + ucpia->sbuf[0].data = kmalloc(FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL); + if (!ucpia->sbuf[0].data) + return -EINVAL; + + ucpia->sbuf[1].data = kmalloc(FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL); + if (!ucpia->sbuf[1].data) { + retval = -EINVAL; + goto error_0; + } + + ret = usb_set_interface(ucpia->dev, ucpia->iface, 3); + if (ret < 0) { + printk(KERN_ERR "cpia_usb_open: usb_set_interface error (ret = %d)\n", ret); + retval = -EBUSY; + goto error_all; + } + + ucpia->buffers[0]->status = FRAME_EMPTY; + ucpia->buffers[0]->length = 0; + ucpia->buffers[1]->status = FRAME_EMPTY; + ucpia->buffers[1]->length = 0; + ucpia->buffers[2]->status = FRAME_EMPTY; + ucpia->buffers[2]->length = 0; + ucpia->curbuff = ucpia->buffers[0]; + ucpia->workbuff = ucpia->buffers[1]; + + /* We double buffer the Iso lists */ + urb = usb_alloc_urb(FRAMES_PER_DESC); + if (!urb) { + printk(KERN_ERR "cpia_init_isoc: usb_alloc_urb 0\n"); + retval = -ENOMEM; + goto error_all; + } + + ucpia->sbuf[0].urb = urb; + urb->dev = ucpia->dev; + urb->context = ucpia; + urb->pipe = usb_rcvisocpipe(ucpia->dev, 1); + urb->transfer_flags = USB_ISO_ASAP; + urb->transfer_buffer = ucpia->sbuf[0].data; + urb->complete = cpia_usb_complete; + urb->number_of_packets = FRAMES_PER_DESC; + urb->transfer_buffer_length = FRAME_SIZE_PER_DESC * FRAMES_PER_DESC; + for (fx = 0; fx < FRAMES_PER_DESC; fx++) { + urb->iso_frame_desc[fx].offset = FRAME_SIZE_PER_DESC * fx; + urb->iso_frame_desc[fx].length = FRAME_SIZE_PER_DESC; + } + + urb = usb_alloc_urb(FRAMES_PER_DESC); + if (!urb) { + printk(KERN_ERR "cpia_init_isoc: usb_alloc_urb 0\n"); + retval = -ENOMEM; + goto error_all; + } + + ucpia->sbuf[1].urb = urb; + urb->dev = ucpia->dev; + urb->context = ucpia; + urb->pipe = usb_rcvisocpipe(ucpia->dev, 1); + urb->transfer_flags = USB_ISO_ASAP; + urb->transfer_buffer = ucpia->sbuf[1].data; + urb->complete = cpia_usb_complete; + urb->number_of_packets = FRAMES_PER_DESC; + urb->transfer_buffer_length = FRAME_SIZE_PER_DESC * FRAMES_PER_DESC; + for (fx = 0; fx < FRAMES_PER_DESC; fx++) { + urb->iso_frame_desc[fx].offset = FRAME_SIZE_PER_DESC * fx; + urb->iso_frame_desc[fx].length = FRAME_SIZE_PER_DESC; + } + + ucpia->sbuf[1].urb->next = ucpia->sbuf[0].urb; + ucpia->sbuf[0].urb->next = ucpia->sbuf[1].urb; + + err = usb_submit_urb(ucpia->sbuf[0].urb); + if (err) + printk(KERN_ERR "cpia_init_isoc: usb_submit_urb 0 ret %d\n", + err); + err = usb_submit_urb(ucpia->sbuf[1].urb); + if (err) + printk(KERN_ERR "cpia_init_isoc: usb_submit_urb 1 ret %d\n", + err); + + ucpia->streaming = 1; + ucpia->open = 1; + + return 0; + +error_all: + kfree (ucpia->sbuf[1].data); +error_0: + kfree (ucpia->sbuf[0].data); + + return retval; +} + +// +// convenience functions +// + +/**************************************************************************** + * + * WritePacket + * + ***************************************************************************/ +static int WritePacket(struct usb_device *udev, const u8 *packet, u8 *buf, size_t size) +{ + if (!packet) + return -EINVAL; + + return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + packet[1] + (packet[0] << 8), + USB_TYPE_VENDOR | USB_RECIP_DEVICE, + packet[2] + (packet[3] << 8), + packet[4] + (packet[5] << 8), buf, size, HZ); +} + +/**************************************************************************** + * + * ReadPacket + * + ***************************************************************************/ +static int ReadPacket(struct usb_device *udev, u8 *packet, u8 *buf, size_t size) +{ + if (!packet || size <= 0) + return -EINVAL; + + return usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + packet[1] + (packet[0] << 8), + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + packet[2] + (packet[3] << 8), + packet[4] + (packet[5] << 8), buf, size, HZ); +} + +static int cpia_usb_transferCmd(void *privdata, u8 *command, u8 *data) +{ + int err = 0; + int databytes; + struct usb_cpia *ucpia = (struct usb_cpia *)privdata; + struct usb_device *udev = ucpia->dev; + + if (!udev) { + DBG("Internal driver error: udev is NULL\n"); + return -EINVAL; + } + + if (!command) { + DBG("Internal driver error: command is NULL\n"); + return -EINVAL; + } + + databytes = (((int)command[7])<<8) | command[6]; + + if (command[0] == DATA_IN) { + u8 buffer[8]; + + if (!data) { + DBG("Internal driver error: data is NULL\n"); + return -EINVAL; + } + + err = ReadPacket(udev, command, buffer, 8); + if (err < 0) + return err; + + memcpy(data, buffer, databytes); + } else if(command[0] == DATA_OUT) + WritePacket(udev, command, data, databytes); + else { + DBG("Unexpected first byte of command: %x\n", command[0]); + err = -EINVAL; + } + + return 0; +} + +static int cpia_usb_registerCallback(void *privdata, void (*cb) (void *cbdata), + void *cbdata) +{ + return -ENODEV; +} + +static int cpia_usb_streamStart(void *privdata) +{ + return -ENODEV; +} + +static int cpia_usb_streamStop(void *privdata) +{ + return -ENODEV; +} + +static int cpia_usb_streamRead(void *privdata, u8 *frame, int noblock) +{ + struct usb_cpia *ucpia = (struct usb_cpia *) privdata; + struct framebuf *mybuff; + + if (!ucpia || !ucpia->present) + return -1; + + if (ucpia->curbuff->status != FRAME_READY) + interruptible_sleep_on(&ucpia->wq_stream); + else + DBG("Frame already waiting!\n"); + + mybuff = ucpia->curbuff; + + if (!mybuff) + return -1; + + if (mybuff->status != FRAME_READY || mybuff->length < 4) { + DBG("Something went wrong!\n"); + return -1; + } + + memcpy(frame, mybuff->data, mybuff->length); + mybuff->status = FRAME_EMPTY; + +/* DBG("read done, %d bytes, Header: %x/%x, Footer: %x%x%x%x\n", */ +/* mybuff->length, frame[0], frame[1], */ +/* frame[mybuff->length-4], frame[mybuff->length-3], */ +/* frame[mybuff->length-2], frame[mybuff->length-1]); */ + + return mybuff->length; +} + +static void cpia_usb_free_resources(struct usb_cpia *ucpia, int try) +{ + if (!ucpia->streaming) + return; + + ucpia->streaming = 0; + + /* Set packet size to 0 */ + if (try) { + int ret; + + ret = usb_set_interface(ucpia->dev, ucpia->iface, 0); + if (ret < 0) { + printk(KERN_ERR "usb_set_interface error (ret = %d)\n", ret); + return; + } + } + + /* Unschedule all of the iso td's */ + if (ucpia->sbuf[1].urb) { + usb_unlink_urb(ucpia->sbuf[1].urb); + usb_free_urb(ucpia->sbuf[1].urb); + ucpia->sbuf[1].urb = NULL; + } + + if (ucpia->sbuf[0].urb) { + usb_unlink_urb(ucpia->sbuf[0].urb); + usb_free_urb(ucpia->sbuf[0].urb); + ucpia->sbuf[0].urb = NULL; + } +} + +static int cpia_usb_close(void *privdata) +{ + struct usb_cpia *ucpia = (struct usb_cpia *) privdata; + + ucpia->open = 0; + + cpia_usb_free_resources(ucpia, 1); + + if (!ucpia->present) + kfree(ucpia); + + return 0; +} + +int cpia_usb_init(void) +{ + /* return -ENODEV; */ + return 0; +} + +/* Probing and initializing */ + +static void *cpia_probe(struct usb_device *udev, unsigned int ifnum) +{ + struct usb_interface_descriptor *interface; + struct usb_cpia *ucpia; + struct cam_data *cam; + int ret; + + /* A multi-config CPiA camera? */ + if (udev->descriptor.bNumConfigurations != 1) + return NULL; + + interface = &udev->actconfig->interface[ifnum].altsetting[0]; + + /* Is it a CPiA? */ + if (udev->descriptor.idVendor != 0x0553) + return NULL; + if (udev->descriptor.idProduct != 0x0002) + return NULL; + + /* We found a CPiA */ + printk(KERN_INFO "USB CPiA camera found\n"); + + ucpia = kmalloc(sizeof(*ucpia), GFP_KERNEL); + if (!ucpia) { + printk(KERN_ERR "couldn't kmalloc cpia struct\n"); + return NULL; + } + + memset(ucpia, 0, sizeof(*ucpia)); + + ucpia->dev = udev; + ucpia->iface = interface->bInterfaceNumber; + init_waitqueue_head(&ucpia->wq_stream); + + ucpia->buffers[0] = vmalloc(sizeof(*ucpia->buffers[0])); + if (!ucpia->buffers[0]) { + printk(KERN_ERR "couldn't vmalloc frame buffer 0\n"); + goto fail_alloc_0; + } + + ucpia->buffers[1] = vmalloc(sizeof(*ucpia->buffers[1])); + if (!ucpia->buffers[1]) { + printk(KERN_ERR "couldn't vmalloc frame buffer 1\n"); + goto fail_alloc_1; + } + + ucpia->buffers[2] = vmalloc(sizeof(*ucpia->buffers[2])); + if (!ucpia->buffers[2]) { + printk(KERN_ERR "couldn't vmalloc frame buffer 2\n"); + goto fail_alloc_2; + } + + ucpia->buffers[0]->next = ucpia->buffers[1]; + ucpia->buffers[1]->next = ucpia->buffers[2]; + ucpia->buffers[2]->next = ucpia->buffers[0]; + + ret = usb_set_interface(udev, ucpia->iface, 0); + if (ret < 0) { + printk(KERN_ERR "cpia_probe: usb_set_interface error (ret = %d)\n", ret); + /* goto fail_all; */ + } + + /* Before register_camera, important */ + ucpia->present = 1; + + cam = cpia_register_camera(&cpia_usb_ops, ucpia); + if (!cam) { + LOG("failed to cpia_register_camera\n"); + goto fail_all; + } + + ADD_TO_LIST(cam_list, cam); + + return cam; + +fail_all: + vfree(ucpia->buffers[2]); + ucpia->buffers[2] = NULL; +fail_alloc_2: + vfree(ucpia->buffers[1]); + ucpia->buffers[1] = NULL; +fail_alloc_1: + vfree(ucpia->buffers[0]); + ucpia->buffers[0] = NULL; +fail_alloc_0: + + return NULL; +} + +static void cpia_disconnect(struct usb_device *dev, void *ptr); + +static struct usb_driver cpia_driver = { + "cpia", + cpia_probe, + cpia_disconnect, + { NULL, NULL } +}; + +/* don't use dev, it may be NULL! (see usb_cpia_cleanup) */ +/* _disconnect from usb_cpia_cleanup is not necessary since usb_deregister */ +/* will do it for us as well as passing a udev structure - jerdfelt */ +static void cpia_disconnect(struct usb_device *udev, void *ptr) +{ + struct cam_data *cam = (struct cam_data *) ptr; + struct usb_cpia *ucpia = (struct usb_cpia *) cam->lowlevel_data; + + REMOVE_FROM_LIST(cam); + + /* Don't even try to reset the altsetting if we're disconnected */ + cpia_usb_free_resources(ucpia, 0); + + ucpia->present = 0; + + cpia_unregister_camera(cam); + + ucpia->curbuff->status = FRAME_ERROR; + + if (waitqueue_active(&ucpia->wq_stream)) + wake_up_interruptible(&ucpia->wq_stream); + + usb_driver_release_interface(&cpia_driver, + &udev->actconfig->interface[0]); + + ucpia->curbuff = ucpia->workbuff = NULL; + + if (ucpia->buffers[2]) { + vfree(ucpia->buffers[2]); + ucpia->buffers[2] = NULL; + } + + if (ucpia->buffers[1]) { + vfree(ucpia->buffers[1]); + ucpia->buffers[1] = NULL; + } + + if (ucpia->buffers[0]) { + vfree(ucpia->buffers[0]); + ucpia->buffers[0] = NULL; + } + + if (!ucpia->open) + kfree(ucpia); +} + +int usb_cpia_init(void) +{ + cam_list = NULL; + + return usb_register(&cpia_driver); +} + +void usb_cpia_cleanup(void) +{ +/* + struct cam_data *cam; + + while ((cam = cam_list) != NULL) + cpia_disconnect(NULL, cam); +*/ + + usb_deregister(&cpia_driver); +} + +#ifdef MODULE +int init_module(void) +{ + return usb_cpia_init(); +} + +void cleanup_module(void) +{ + usb_cpia_cleanup(); +} +#endif /* !MODULE */ diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/char/joystick/joy-spaceball.c linux/drivers/char/joystick/joy-spaceball.c --- v2.3.99-pre3/linux/drivers/char/joystick/joy-spaceball.c Wed Dec 8 14:11:26 1999 +++ linux/drivers/char/joystick/joy-spaceball.c Sun Apr 2 15:33:34 2000 @@ -207,6 +207,8 @@ struct js_sball_info iniinfo; struct js_sball_info *info = &iniinfo; + MOD_INC_USE_COUNT; + info->tty = tty; info->idx = 0; info->used = 1; @@ -221,8 +223,6 @@ js_sball_init_corr(js_sball_port->corr); - MOD_INC_USE_COUNT; - return 0; } @@ -312,9 +312,7 @@ static struct tty_ldisc js_sball_ldisc = { magic: TTY_LDISC_MAGIC, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) name: "spaceball", -#endif open: js_sball_ldisc_open, close: js_sball_ldisc_close, receive_buf: js_sball_ldisc_receive, diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/char/joystick/joy-spaceorb.c linux/drivers/char/joystick/joy-spaceorb.c --- v2.3.99-pre3/linux/drivers/char/joystick/joy-spaceorb.c Wed Dec 8 14:11:26 1999 +++ linux/drivers/char/joystick/joy-spaceorb.c Sun Apr 2 15:33:34 2000 @@ -199,6 +199,8 @@ struct js_orb_info iniinfo; struct js_orb_info *info = &iniinfo; + MOD_INC_USE_COUNT; + info->tty = tty; info->idx = 0; info->used = 1; @@ -213,8 +215,6 @@ js_orb_init_corr(js_orb_port->corr); - MOD_INC_USE_COUNT; - return 0; } @@ -270,9 +270,7 @@ static struct tty_ldisc js_orb_ldisc = { magic: TTY_LDISC_MAGIC, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) name: "spaceorb", -#endif open: js_orb_ldisc_open, close: js_orb_ldisc_close, receive_buf: js_orb_ldisc_receive, diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/char/joystick/joy-warrior.c linux/drivers/char/joystick/joy-warrior.c --- v2.3.99-pre3/linux/drivers/char/joystick/joy-warrior.c Wed Dec 8 14:11:26 1999 +++ linux/drivers/char/joystick/joy-warrior.c Sun Apr 2 15:33:34 2000 @@ -90,28 +90,12 @@ if (!info->port->devs[0]) return; buttons[0][0] = ((data[3] & 0xa) >> 1) | ((data[3] & 0x5) << 1); return; - case 2: /* Static status (Send !S to get one) */ -#if 0 - printk("joy-warrior: Static status:"); - for (i = 0; i < 12; i++) - printk(" %02x", info->data[i]); - printk("\n"); -#endif - return; case 3: /* XY-axis info->data */ if (!info->port->devs[0]) return; axes[0][0] = ((data[0] & 8) << 5) - (data[2] | ((data[0] & 4) << 5)); axes[0][1] = (data[1] | ((data[0] & 1) << 7)) - ((data[0] & 2) << 7); return; break; - case 4: /* Dynamic status */ -#if 0 - printk("joy-warrior: Dynamic status:"); - for (i = 0; i < 4; i++) - printk(" %02x", info->data[i]); - printk("\n"); -#endif - return; case 5: /* Throttle, spinner, hat info->data */ if (!info->port->devs[0]) return; axes[0][2] = (data[1] | ((data[0] & 1) << 7)) - ((data[0] & 2) << 7); @@ -119,6 +103,9 @@ axes[0][4] = (data[3] & 8 ? 1 : 0) - (info->data[3] & 4 ? 1 : 0); axes[0][5] = (data[2] | ((data[0] & 4) << 5)) - ((data[0] & 8) << 5); return; + case 2: /* Static status (Send !S to get one) */ + case 4: /* Dynamic status */ + return; default: printk("joy-warrior: Unknown packet %d length %d:", (data[0] >> 4) & 7, info->idx); for (i = 0; i < info->idx; i++) @@ -199,6 +186,8 @@ struct js_war_info iniinfo; struct js_war_info *info = &iniinfo; + MOD_INC_USE_COUNT; + info->tty = tty; info->idx = 0; info->len = 0; @@ -216,8 +205,6 @@ js_war_init_corr(js_war_port->corr); - MOD_INC_USE_COUNT; - return 0; } @@ -283,9 +270,7 @@ static struct tty_ldisc js_war_ldisc = { magic: TTY_LDISC_MAGIC, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) name: "warrior", -#endif open: js_war_ldisc_open, close: js_war_ldisc_close, receive_buf: js_war_ldisc_receive, diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/char/joystick/joystick.c linux/drivers/char/joystick/joystick.c --- v2.3.99-pre3/linux/drivers/char/joystick/joystick.c Sun Feb 20 21:12:39 2000 +++ linux/drivers/char/joystick/joystick.c Sun Apr 2 15:33:34 2000 @@ -499,6 +499,7 @@ if (MAJOR(inode->i_rdev) != JOYSTICK_MAJOR) return -EINVAL; + spin_lock_irqsave(&js_lock, flags); while (i > 0 && jd) { @@ -510,32 +511,32 @@ if (!jd) return -ENODEV; - if ((result = jd->open(jd))) return result; - - if ((new = kmalloc(sizeof(struct js_list), GFP_KERNEL))) { + if ((result = jd->open(jd))) + return result; - MOD_INC_USE_COUNT; + MOD_INC_USE_COUNT; - spin_lock_irqsave(&js_lock, flags); + if ((new = kmalloc(sizeof(struct js_list), GFP_KERNEL))) { + MOD_DEC_USE_COUNT; + return -ENOMEM; + } - curl = jd->list; + spin_lock_irqsave(&js_lock, flags); - jd->list = new; - jd->list->next = curl; - jd->list->dev = jd; - jd->list->startup = 0; - jd->list->tail = GOB(jd->bhead); - file->private_data = jd->list; + curl = jd->list; - spin_unlock_irqrestore(&js_lock, flags); + jd->list = new; + jd->list->next = curl; + jd->list->dev = jd; + jd->list->startup = 0; + jd->list->tail = GOB(jd->bhead); + file->private_data = jd->list; - if (!js_use_count++) js_do_timer(0); + spin_unlock_irqrestore(&js_lock, flags); - } else { - result = -ENOMEM; - } + if (!js_use_count++) js_do_timer(0); - return result; + return 0; } /* @@ -573,10 +574,11 @@ kfree(file->private_data); if (!--js_use_count) del_timer(&js_timer); - MOD_DEC_USE_COUNT; jd->close(jd); + MOD_DEC_USE_COUNT; + return 0; } @@ -584,50 +586,6 @@ * js_dump_mem() dumps all data structures in memory. * It's used for debugging only. */ - -#if 0 -static void js_dump_mem(void) -{ - - struct js_port *curp = js_port; - struct js_dev *curd = js_dev; - int i; - - printk(",--- Dumping Devices:\n"); - printk("| js_dev = %x\n", (int) js_dev); - - while (curd) { - printk("| %s-device %x, next %x axes %d, buttons %d, port %x - %#x\n", - curd->next ? "|":"`", - (int) curd, (int) curd->next, curd->num_axes, curd->num_buttons, (int) curd->port, curd->port->io); - curd = curd->next; - } - - printk(">--- Dumping ports:\n"); - printk("| js_port = %x\n", (int) js_port); - - while (curp) { - printk("| %s-port %x, next %x, io %#x, devices %d\n", - curp->next ? "|":"`", - (int) curp, (int) curp->next, curp->io, curp->ndevs); - for (i = 0; i < curp->ndevs; i++) { - curd = curp->devs[i]; - if (curd) - printk("| %s %s-device %x, next %x axes %d, buttons %d, port %x\n", - curp->next ? "|":" ", (i < curp->ndevs-1) ? "|":"`", - (int) curd, (int) curd->next, curd->num_axes, curd->num_buttons, (int) curd->port); - else - printk("| %s %s-device %x, not there\n", - curp->next ? "|":" ", (i < curp->ndevs-1) ? "|":"`", (int) curd); - - } - curp = curp->next; - } - - printk("`--- Done\n"); -} -#endif - struct js_port *js_register_port(struct js_port *port, void *info, int devs, int infos, js_read_func read) diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/char/mem.c linux/drivers/char/mem.c --- v2.3.99-pre3/linux/drivers/char/mem.c Tue Mar 14 19:10:39 2000 +++ linux/drivers/char/mem.c Mon Apr 10 22:58:59 2000 @@ -34,9 +34,6 @@ #ifdef CONFIG_SOUND_OSS void soundcard_init(void); #endif -#ifdef CONFIG_DMASOUND -void dmasound_init(void); -#endif #endif #ifdef CONFIG_SPARCAUDIO extern int sparcaudio_init(void); @@ -633,9 +630,6 @@ soundcore_init(); #ifdef CONFIG_SOUND_OSS soundcard_init(); -#endif -#ifdef CONFIG_DMASOUND - dmasound_init(); #endif #endif #ifdef CONFIG_SPARCAUDIO diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/char/n_r3964.c linux/drivers/char/n_r3964.c --- v2.3.99-pre3/linux/drivers/char/n_r3964.c Tue Sep 7 12:14:06 1999 +++ linux/drivers/char/n_r3964.c Sun Apr 2 15:38:53 2000 @@ -12,7 +12,10 @@ * Author: * L. Haag * - * $Log: r3964.c,v $ + * $Log: n_r3964.c,v $ + * Revision 1.8 2000/03/23 14:14:54 dwmw2 + * Fix race in sleeping in r3964_read() + * * Revision 1.7 1999/28/08 11:41:50 dwmw2 * Port to 2.3 kernel * @@ -38,7 +41,6 @@ * * */ -#define R3964_VERSION "1.7" #include #include @@ -224,7 +226,7 @@ { int status; - printk ("r3964: Philips r3964 Driver V%s\n", R3964_VERSION); + printk ("r3964: Philips r3964 Driver $Revision: 1.8 $\n"); /* * Register the tty line discipline @@ -1280,8 +1282,8 @@ /* block until there is a message: */ add_wait_queue(&pInfo->read_wait, &wait); repeat: - pMsg = remove_msg(pInfo, pClient); current->state = TASK_INTERRUPTIBLE; + pMsg = remove_msg(pInfo, pClient); if (!pMsg && !signal_pending(current)) { schedule(); diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/char/pcwd.c linux/drivers/char/pcwd.c --- v2.3.99-pre3/linux/drivers/char/pcwd.c Thu Feb 10 17:11:08 2000 +++ linux/drivers/char/pcwd.c Tue Apr 4 19:25:14 2000 @@ -39,6 +39,7 @@ * 990605 Made changes to code to support Firmware 1.22a, added * fairly useless proc entry. * 990610 removed said useless proc code for the merge + * 000403 Removed last traces of proc code. */ #include @@ -539,38 +540,6 @@ { outb_p(0x00, current_readport + 2); mode_debug = 0; -} - -static int pcwd_proc_get_info(char *buffer, char **start, off_t offset, - int length, int inout) -{ - int len; - off_t begin = 0; - - revision = get_revision(); - len = sprintf(buffer, "Version = " WD_VER "\n"); - - if (revision == PCWD_REVISION_A) - len += sprintf(buffer + len, "Revision = A\n"); - else - len += sprintf(buffer + len, "Revision = C\n"); - - if (supports_temp) { - unsigned short c = inb(current_readport); - - len += sprintf(buffer + len, "Temp = Yes\n" - "Current temp = %d (Celsius)\n", - c); - } else - len += sprintf(buffer + len, "Temp = No\n"); - - *start = buffer + (offset); - len -= offset; - - if (len > length) - len = length; - - return len; } static struct file_operations pcwd_fops = { diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/char/ppdev.c linux/drivers/char/ppdev.c --- v2.3.99-pre3/linux/drivers/char/ppdev.c Tue Mar 14 19:10:39 2000 +++ linux/drivers/char/ppdev.c Mon Apr 3 13:24:05 2000 @@ -537,7 +537,7 @@ unsigned int minor = MINOR (inode->i_rdev); struct pp_struct *pp = file->private_data; - if (pp->pdev->port->ieee1284.mode != IEEE1284_MODE_COMPAT) { + if (pp->pdev && pp->pdev->port->ieee1284.mode != IEEE1284_MODE_COMPAT) { if (!(pp->flags & PP_CLAIMED)) { parport_claim_or_block (pp->pdev); pp->flags |= PP_CLAIMED; diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/char/pty.c linux/drivers/char/pty.c --- v2.3.99-pre3/linux/drivers/char/pty.c Tue Mar 14 19:10:39 2000 +++ linux/drivers/char/pty.c Sun Apr 2 15:20:27 2000 @@ -29,10 +29,6 @@ #define BUILDING_PTY_C 1 #include -extern void tty_register_devfs (struct tty_driver *driver, unsigned int flags, - unsigned int minor); -extern void tty_unregister_devfs (struct tty_driver *driver, unsigned minor); - struct pty_struct { int magic; wait_queue_head_t open_wait; diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/char/serial.c linux/drivers/char/serial.c --- v2.3.99-pre3/linux/drivers/char/serial.c Mon Mar 27 08:08:24 2000 +++ linux/drivers/char/serial.c Sun Apr 2 15:20:27 2000 @@ -220,10 +220,6 @@ #define _INLINE_ #endif -extern void tty_register_devfs (struct tty_driver *driver, unsigned int flags, - unsigned int minor); -extern void tty_unregister_devfs (struct tty_driver *driver, unsigned minor); - static char *serial_name = "Serial driver"; static DECLARE_TASK_QUEUE(tq_serial); @@ -4359,6 +4355,9 @@ SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT, 1, 115200 }, /* U.S. Robotics 56K FAX INT */ { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x3031), 0, 0, + SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT, 1, 115200 }, + /* Viking 56K FAX INT */ + { ISAPNP_VENDOR('R', 'S', 'S'), ISAPNP_DEVICE(0x0262), 0, 0, SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT, 1, 115200 }, /* These ID's are taken from M$ documentation */ diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/char/sh-sci.c linux/drivers/char/sh-sci.c --- v2.3.99-pre3/linux/drivers/char/sh-sci.c Tue Mar 7 14:32:25 2000 +++ linux/drivers/char/sh-sci.c Mon Mar 27 10:26:15 2000 @@ -1,9 +1,10 @@ -/* $Id: sh-sci.c,v 1.32 2000-03-05 13:56:18+09 gniibe Exp $ +/* $Id: sh-sci.c,v 1.36 2000/03/22 13:32:10 gniibe Exp $ * * linux/drivers/char/sh-sci.c * * SuperH on-chip serial module support. (SCI with no FIFO / with FIFO) * Copyright (C) 1999, 2000 Niibe Yutaka + * Copyright (C) 2000 Sugioka Toshinobu * * TTY code is based on sx.c (Specialix SX driver) by: * @@ -38,7 +39,7 @@ #include #include -#include "generic_serial.h" +#include #include "sh-sci.h" #ifdef CONFIG_DEBUG_KERNEL_WITH_GDB_STUB @@ -54,7 +55,7 @@ static void sci_enable_rx_interrupts(void *ptr); static int sci_get_CD(void *ptr); static void sci_shutdown_port(void *ptr); -static void sci_set_real_termios(void *ptr); +static int sci_set_real_termios(void *ptr); static void sci_hungup(void *ptr); static void sci_close(void *ptr); static int sci_chars_in_buffer(void *ptr); @@ -142,7 +143,11 @@ } if (t > 0) { - sci_setsignals (port, 1, -1); + sci_setsignals (port, 1, -1); + if(t >= 256) { + ctrl_out((ctrl_in(SCSMR) & ~3) | 1, SCSMR); + t >>= 2; + } ctrl_outb(t, SCBRR); ctrl_outw(0xa400, RFCR); /* Refresh counter clear */ while (ctrl_inw(RFCR) < WAIT_RFCR_COUNTER) @@ -155,7 +160,7 @@ static void sci_set_termios_cflag(struct sci_port *port) { unsigned short status; - unsigned short smr_val=0; + unsigned short smr_val; #if defined(CONFIG_SH_SCIF_SERIAL) unsigned short fcr_val=6; /* TFRST=1, RFRST=1 */ #endif @@ -172,6 +177,7 @@ fcr_val = 0; #endif + smr_val = ctrl_in(SCSMR) & 3; if ((port->gs.tty->termios->c_cflag & CSIZE) == CS7) smr_val |= 0x40; if (C_PARENB(port->gs.tty)) @@ -196,7 +202,7 @@ sci_enable_rx_interrupts(port); } -static void sci_set_real_termios(void *ptr) +static int sci_set_real_termios(void *ptr) { struct sci_port *port = ptr; @@ -218,6 +224,8 @@ set_bit(TTY_HW_COOK_OUT, &port->gs.tty->flags); else clear_bit(TTY_HW_COOK_OUT, &port->gs.tty->flags); + + return 0; } /* ********************************************************************** * @@ -352,10 +360,16 @@ static void sci_rx_interrupt(int irq, void *ptr, struct pt_regs *regs) { struct sci_port *port = ptr; + unsigned long flags; if (port->gs.flags & GS_ACTIVE) - if (!(port->gs.flags & SCI_RX_THROTTLE)) + if (!(port->gs.flags & SCI_RX_THROTTLE)) { sci_receive_chars(port); + return; + } + save_and_cli(flags); + ctrl_out(ctrl_in(SCSCR) & ~SCI_CTRL_FLAGS_RIE, SCSCR); + restore_flags(flags); } static void sci_tx_interrupt(int irq, void *ptr, struct pt_regs *regs) @@ -363,9 +377,14 @@ struct sci_port *port = ptr; if (port->gs.flags & GS_ACTIVE) - if (port->gs.xmit_cnt) { - sci_transmit_chars(port); - } + sci_transmit_chars(port); + else { + unsigned long flags; + + save_and_cli(flags); + ctrl_out(ctrl_in(SCSCR) & ~SCI_CTRL_FLAGS_TIE, SCSCR); + restore_flags(flags); + } } static void sci_er_interrupt(int irq, void *ptr, struct pt_regs *regs) diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/char/sh-sci.h linux/drivers/char/sh-sci.h --- v2.3.99-pre3/linux/drivers/char/sh-sci.h Tue Mar 7 14:32:25 2000 +++ linux/drivers/char/sh-sci.h Mon Mar 27 10:26:15 2000 @@ -1,4 +1,4 @@ -/* $Id: sh-sci.h,v 1.5 2000-03-05 13:54:32+09 gniibe Exp $ +/* $Id: sh-sci.h,v 1.8 2000/03/08 15:19:39 gniibe Exp $ * * linux/drivers/char/sh-sci.h * @@ -18,13 +18,18 @@ #define SC_SR (volatile unsigned char *)0xfffffe88 #define SC_RDR 0xfffffe8a #define SCSPTR 0xffffff7c - -#define SCSCR_INIT 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ - #elif defined(__SH4__) -Not yet. +#define SCSMR (volatile unsigned char *)0xffe00000 +#define SCBRR 0xffe00004 +#define SCSCR (volatile unsigned char *)0xffe00008 +#define SC_TDR 0xffe0000c +#define SC_SR (volatile unsigned char *)0xffe00010 +#define SC_RDR 0xffe00014 +#define SCSPTR 0xffe0001c #endif +#define SCSCR_INIT 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ + #define SCI_TD_E 0x80 #define SCI_RD_F 0x40 #define SCI_ORER 0x20 @@ -45,8 +50,6 @@ #define SCI_CTRL_FLAGS_CKE1 0x02 #define SCI_CTRL_FLAGS_CKE0 0x01 -#define RFCR 0xffffff74 - #define SCI_ERI_IRQ 23 #define SCI_RXI_IRQ 24 #define SCI_TXI_IRQ 25 @@ -69,8 +72,6 @@ #undef SCSPTR /* Is there any register for RTS?? */ #undef SCLSR -#define RFCR 0xffffff74 - #define SCSCR_INIT 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ /* 0x33 when external clock is used */ #define SCI_IPR_OFFSET (64+4) @@ -87,8 +88,6 @@ #define SCSPTR 0xFFE80020 #define SCLSR 0xFFE80024 -#define RFCR 0xFF800028 - #define SCSCR_INIT 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ #define SCI_IPR_OFFSET (32+4) @@ -131,6 +130,12 @@ #endif #endif +#if defined(__sh3__) +#define RFCR 0xffffff74 +#elif defined(__SH4__) +#define RFCR 0xFF800028 +#endif + #define SCI_PRIORITY 3 #define SCI_MINOR_START 64 @@ -183,14 +188,15 @@ */ #if defined(__sh3__) -#define BPS_2400 191 -#define BPS_4800 95 -#define BPS_9600 47 -#define BPS_19200 23 -#define BPS_38400 11 -#define BPS_115200 3 +#define PCLK 14745600 #elif defined(__SH4__) -/* Values for SH-4 please! */ - -#define BPS_115200 8 +#define PCLK 33333333 #endif + +#define SCBRR_VALUE(bps) (PCLK/(32*bps)-1) +#define BPS_2400 SCBRR_VALUE(2400) +#define BPS_4800 SCBRR_VALUE(4800) +#define BPS_9600 SCBRR_VALUE(9600) +#define BPS_19200 SCBRR_VALUE(19200) +#define BPS_38400 SCBRR_VALUE(38400) +#define BPS_115200 SCBRR_VALUE(115200) diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c --- v2.3.99-pre3/linux/drivers/char/tty_io.c Mon Mar 27 08:08:24 2000 +++ linux/drivers/char/tty_io.c Sun Apr 2 15:20:27 2000 @@ -99,9 +99,6 @@ #ifdef CONFIG_VT extern void con_init_devfs (void); #endif -void tty_register_devfs (struct tty_driver *driver, unsigned int flags, - unsigned minor); -void tty_unregister_devfs (struct tty_driver *driver, unsigned minor); #define CONSOLE_DEV MKDEV(TTY_MAJOR,0) #define TTY_DEV MKDEV(TTYAUX_MAJOR,0) @@ -153,6 +150,12 @@ extern console_8xx_init(void); extern int rs_8xx_init(void); #endif /* CONFIG_8xx */ +#ifdef CONFIG_HWC +extern void hwc_console_init(void); +#endif +#ifdef CONFIG_3215 +extern void con3215_init(void); +#endif /* CONFIG_3215 */ #ifndef MIN @@ -2191,6 +2194,12 @@ #if defined(CONFIG_SERIAL167) serial167_console_init(); #endif +#endif +#ifdef CONFIG_3215 + con3215_init(); +#endif +#ifdef CONFIG_HWC + hwc_console_init(); #endif } diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/char/tuner.c linux/drivers/char/tuner.c --- v2.3.99-pre3/linux/drivers/char/tuner.c Tue Mar 7 14:32:25 2000 +++ linux/drivers/char/tuner.c Sun Apr 2 15:32:49 2000 @@ -97,7 +97,6 @@ { "Temic NTSC", TEMIC, NTSC, 16*157.25,16*463.25,0x02,0x04,0x01,0x8e,732}, { "Temic PAL_I", TEMIC, PAL_I, - // 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, 16*170.00,16*450.00,0x02,0x04,0x01,0x8e,623}, { "Temic 4036 FY5 NTSC", TEMIC, NTSC, 16*157.25,16*463.25,0xa0,0x90,0x30,0x8e,732}, @@ -111,6 +110,8 @@ 16*133.25,16*351.25,0x01,0x02,0x08,0x8e,622}, { "Alps TSBC5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */ 16*133.25,16*351.25,0x01,0x02,0x08,0x8e,608}, + { "Temic 4006FH5", TEMIC, PAL_I, + 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, }; #define TUNERS (sizeof(tuners)/sizeof(struct tunertype)) diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/char/videodev.c linux/drivers/char/videodev.c --- v2.3.99-pre3/linux/drivers/char/videodev.c Tue Mar 14 19:10:39 2000 +++ linux/drivers/char/videodev.c Mon Mar 27 10:29:41 2000 @@ -47,6 +47,9 @@ #ifdef CONFIG_VIDEO_BWQCAM extern int init_bw_qcams(struct video_init *); #endif +#ifdef CONFIG_VIDEO_CPIA +extern int cpia_init(struct video_init *); +#endif #ifdef CONFIG_VIDEO_PLANB extern int init_planbs(struct video_init *); #endif @@ -62,6 +65,9 @@ #ifdef CONFIG_VIDEO_BWQCAM {"bw-qcam", init_bw_qcams}, #endif +#ifdef CONFIG_VIDEO_CPIA + {"cpia", cpia_init}, +#endif #ifdef CONFIG_VIDEO_PLANB {"planb", init_planbs}, #endif @@ -133,9 +139,11 @@ if(vfl==NULL) { char modname[20]; + MOD_INC_USE_COUNT; sprintf (modname, "char-major-%d-%d", VIDEO_MAJOR, minor); request_module(modname); vfl=video_device[minor]; + MOD_DEC_USE_COUNT; if (vfl==NULL) return -ENODEV; } diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/char/wd501p.h linux/drivers/char/wd501p.h --- v2.3.99-pre3/linux/drivers/char/wd501p.h Mon Jan 12 15:12:42 1998 +++ linux/drivers/char/wd501p.h Sun Apr 2 15:38:53 2000 @@ -25,11 +25,21 @@ #define WDT_COUNT1 (io+1) #define WDT_COUNT2 (io+2) #define WDT_CR (io+3) -#define WDT_SR (io+4) -#define WDT_RT (io+5) -#define WDT_UNUSED (io+6) +#define WDT_SR (io+4) /* Start buzzer on PCI write */ +#define WDT_RT (io+5) /* Stop buzzer on PCI write */ +#define WDT_BUZZER (io+6) /* PCI only: rd=disable, wr=enable */ #define WDT_DC (io+7) +/* The following are only on the PCI card, they're outside of I/O space on + * the ISA card: */ +#define WDT_CLOCK (io+12) /* COUNT2: rd=16.67MHz, wr=2.0833MHz */ +/* inverted opto isolated reset output: */ +#define WDT_OPTONOTRST (io+13) /* wr=enable, rd=disable */ +/* opto isolated reset output: */ +#define WDT_OPTORST (io+14) /* wr=enable, rd=disable */ +/* programmable outputs: */ +#define WDT_PROGOUT (io+15) /* wr=enable, rd=disable */ + #define WDC_SR_WCCR 1 /* Active low */ #define WDC_SR_TGOOD 2 #define WDC_SR_ISOI0 4 @@ -39,6 +49,8 @@ #define WDC_SR_PSUUNDR 64 /* Active low */ #define WDC_SR_IRQ 128 /* Active low */ +#ifndef WDT_IS_PCI + /* * Feature Map 1 is the active high inputs not supported on your card. * Feature Map 2 is the active low inputs not supported on your card. @@ -62,6 +74,13 @@ #endif #ifdef CONFIG_WDT_500 /* Minimal board */ +#define FEATUREMAP1 (WDC_SR_TGOOD|WDC_SR_FANGOOD) +#define FEATUREMAP2 (WDC_SR_PSUOVER|WDC_SR_PSUUNDR) +#define WDT_OPTION_MASK (WDIOF_OVERHEAT) +#endif + +#else + #define FEATUREMAP1 (WDC_SR_TGOOD|WDC_SR_FANGOOD) #define FEATUREMAP2 (WDC_SR_PSUOVER|WDC_SR_PSUUNDR) #define WDT_OPTION_MASK (WDIOF_OVERHEAT) diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/char/wdt_pci.c linux/drivers/char/wdt_pci.c --- v2.3.99-pre3/linux/drivers/char/wdt_pci.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/wdt_pci.c Sun Apr 2 15:38:53 2000 @@ -0,0 +1,558 @@ +/* + * Industrial Computer Source WDT500/501 driver for Linux 2.1.x + * + * (c) Copyright 1996-1997 Alan Cox , All Rights Reserved. + * http://www.redhat.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. + * + * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. + * + * (c) Copyright 1995 Alan Cox + * + * Release 0.08. + * + * Fixes + * Dave Gregorich : Modularisation and minor bugs + * Alan Cox : Added the watchdog ioctl() stuff + * Alan Cox : Fixed the reboot problem (as noted by + * Matt Crocker). + * Alan Cox : Added wdt= boot option + * Alan Cox : Cleaned up copy/user stuff + * Tim Hockin : Added insmod parameters, comment cleanup + * Parameterized timeout + * JP Nollmann : Added support for PCI wdt501p + * Alan Cox : Split ISA and PCI cards into two drivers + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define WDT_IS_PCI +#include "wd501p.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * Until Access I/O gets their application for a PCI vendor ID approved, + * I don't think that it's appropriate to move these constants into the + * regular pci_ids.h file. -- JPN 2000/01/18 + */ + +#ifndef PCI_VENDOR_ID_ACCESSIO +#define PCI_VENDOR_ID_ACCESSIO 0x494f +#endif +#ifndef PCI_DEVICE_ID_WDG_CSM +#define PCI_DEVICE_ID_WDG_CSM 0x22c0 +#endif + +static int wdt_is_open=0; + +/* + * You must set these - there is no sane way to probe for this board. + * You can use wdt=x,y to set these now. + */ + +static int io=0x240; +static int irq=11; + +#define WD_TIMO (100*60) /* 1 minute */ + +#ifndef MODULE + +/** + * wdtpci_setup: + * @str: command line string + * + * Setup options. The board isn't really probe-able so we have to + * get the user to tell us the configuration. Sane people build it + * modular but the others come here. + */ + +static int __init wdtpci_setup(char *str) +{ + int ints[4]; + + str = get_options (str, ARRAY_SIZE(ints), ints); + + if (ints[0] > 0) + { + io = ints[1]; + if(ints[0] > 1) + irq = ints[2]; + } + + return 1; +} + +__setup("wdt=", wdtpci_setup); + +#endif /* !MODULE */ + +/* + * Programming support + */ + +static void wdtpci_ctr_mode(int ctr, int mode) +{ + ctr<<=6; + ctr|=0x30; + ctr|=(mode<<1); + outb_p(ctr, WDT_CR); +} + +static void wdtpci_ctr_load(int ctr, int val) +{ + outb_p(val&0xFF, WDT_COUNT0+ctr); + outb_p(val>>8, WDT_COUNT0+ctr); +} + +/* + * Kernel methods. + */ + + +/** + * wdtpci_status: + * + * Extract the status information from a WDT watchdog device. There are + * several board variants so we have to know which bits are valid. Some + * bits default to one and some to zero in order to be maximally painful. + * + * we then map the bits onto the status ioctl flags. + */ + +static int wdtpci_status(void) +{ + /* + * Status register to bit flags + */ + + int flag=0; + unsigned char status=inb_p(WDT_SR); + status|=FEATUREMAP1; + status&=~FEATUREMAP2; + + if(!(status&WDC_SR_TGOOD)) + flag|=WDIOF_OVERHEAT; + if(!(status&WDC_SR_PSUOVER)) + flag|=WDIOF_POWEROVER; + if(!(status&WDC_SR_PSUUNDR)) + flag|=WDIOF_POWERUNDER; + if(!(status&WDC_SR_FANGOOD)) + flag|=WDIOF_FANFAULT; + if(status&WDC_SR_ISOI0) + flag|=WDIOF_EXTERN1; + if(status&WDC_SR_ISII1) + flag|=WDIOF_EXTERN2; + return flag; +} + +/** + * wdtpci_interrupt: + * @irq: Interrupt number + * @dev_id: Unused as we don't allow multiple devices. + * @regs: Unused. + * + * Handle an interrupt from the board. These are raised when the status + * map changes in what the board considers an interesting way. That means + * a failure condition occuring. + */ + +static void wdtpci_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + /* + * Read the status register see what is up and + * then printk it. + */ + + unsigned char status=inb_p(WDT_SR); + + status|=FEATUREMAP1; + status&=~FEATUREMAP2; + + printk(KERN_CRIT "WDT status %d\n", status); + + if(!(status&WDC_SR_TGOOD)) + printk(KERN_CRIT "Overheat alarm.(%d)\n",inb_p(WDT_RT)); + if(!(status&WDC_SR_PSUOVER)) + printk(KERN_CRIT "PSU over voltage.\n"); + if(!(status&WDC_SR_PSUUNDR)) + printk(KERN_CRIT "PSU under voltage.\n"); + if(!(status&WDC_SR_FANGOOD)) + printk(KERN_CRIT "Possible fan fault.\n"); + if(!(status&WDC_SR_WCCR)) +#ifdef SOFTWARE_REBOOT +#ifdef ONLY_TESTING + printk(KERN_CRIT "Would Reboot.\n"); +#else + printk(KERN_CRIT "Initiating system reboot.\n"); + machine_restart(NULL); +#endif +#else + printk(KERN_CRIT "Reset in 5ms.\n"); +#endif +} + + +static long long wdtpci_llseek(struct file *file, long long offset, int origin) +{ + return -ESPIPE; +} + +/** + * wdtpci_ping: + * + * Reload counter one with the watchdog timeout. We don't bother reloading + * the cascade counter. + */ + +static void wdtpci_ping(void) +{ + /* Write a watchdog value */ + inb_p(WDT_DC); + wdtpci_ctr_mode(1,2); + wdtpci_ctr_load(1,WD_TIMO); /* Timeout */ + outb_p(0, WDT_DC); +} + +/** + * wdtpci_write: + * @file: file handle to the watchdog + * @buf: buffer to write (unused as data does not matter here + * @count: count of bytes + * @ppos: pointer to the position to write. No seeks allowed + * + * A write to a watchdog device is defined as a keepalive signal. Any + * write of data will do, as we we don't define content meaning. + */ + +static ssize_t wdtpci_write(struct file *file, const char *buf, size_t count, loff_t *ppos) +{ + /* Can't seek (pwrite) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + + if(count) + { + wdtpci_ping(); + return 1; + } + return 0; +} + +/** + * wdtpci_read: + * @file: file handle to the watchdog board + * @buf: buffer to write 1 byte into + * @count: length of buffer + * @ptr: offset (no seek allowed) + * + * Read reports the temperature in degrees Fahrenheit. The API is in + * farenheit. It was designed by an imperial measurement luddite. + */ + +static ssize_t wdtpci_read(struct file *file, char *buf, size_t count, loff_t *ptr) +{ + unsigned short c=inb_p(WDT_RT); + unsigned char cp; + + /* Can't seek (pread) on this device */ + if (ptr != &file->f_pos) + return -ESPIPE; + + switch(MINOR(file->f_dentry->d_inode->i_rdev)) + { + case TEMP_MINOR: + c*=11; + c/=15; + cp=c+7; + if(copy_to_user(buf,&cp,1)) + return -EFAULT; + return 1; + default: + return -EINVAL; + } +} + +/** + * wdtpci_ioctl: + * @inode: inode of the device + * @file: file handle to the device + * @cmd: watchdog command + * @arg: argument pointer + * + * The watchdog API defines a common set of functions for all watchdogs + * according to their available features. We only actually usefully support + * querying capabilities and current status. + */ + +static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + static struct watchdog_info ident= + { + WDIOF_OVERHEAT|WDIOF_POWERUNDER|WDIOF_POWEROVER + |WDIOF_EXTERN1|WDIOF_EXTERN2|WDIOF_FANFAULT, + 1, + "WDT500/501PCI" + }; + + ident.options&=WDT_OPTION_MASK; /* Mask down to the card we have */ + switch(cmd) + { + default: + return -ENOIOCTLCMD; + case WDIOC_GETSUPPORT: + return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0; + + case WDIOC_GETSTATUS: + return put_user(wdtpci_status(),(int *)arg); + case WDIOC_GETBOOTSTATUS: + return put_user(0, (int *)arg); + case WDIOC_KEEPALIVE: + wdtpci_ping(); + return 0; + } +} + +/** + * wdtpci_open: + * @inode: inode of device + * @file: file handle to device + * + * One of our two misc devices has been opened. The watchdog device is + * single open and on opening we load the counters. Counter zero is a + * 100Hz cascade, into counter 1 which downcounts to reboot. When the + * counter triggers counter 2 downcounts the length of the reset pulse + * which set set to be as long as possible. + */ + +static int wdtpci_open(struct inode *inode, struct file *file) +{ + switch(MINOR(inode->i_rdev)) + { + case WATCHDOG_MINOR: + if(wdt_is_open) + return -EBUSY; + MOD_INC_USE_COUNT; + /* + * Activate + */ + + wdt_is_open=1; + + inb_p(WDT_DC); /* Disable */ + + /* + * "pet" the watchdog, as Access says. + * This resets the clock outputs. + */ + + wdtpci_ctr_mode(2,0); + outb_p(0, WDT_DC); + + inb_p(WDT_DC); + + outb_p(0, WDT_CLOCK); /* 2.0833MHz clock */ + inb_p(WDT_BUZZER); /* disable */ + inb_p(WDT_OPTONOTRST); /* disable */ + inb_p(WDT_OPTORST); /* disable */ + inb_p(WDT_PROGOUT); /* disable */ + wdtpci_ctr_mode(0,3); + wdtpci_ctr_mode(1,2); + wdtpci_ctr_mode(2,1); + wdtpci_ctr_load(0,20833); /* count at 100Hz */ + wdtpci_ctr_load(1,WD_TIMO);/* Timeout 60 seconds */ + /* DO NOT LOAD CTR2 on PCI card! -- JPN */ + outb_p(0, WDT_DC); /* Enable */ + return 0; + case TEMP_MINOR: + MOD_INC_USE_COUNT; + return 0; + default: + return -ENODEV; + } +} + +/** + * wdtpci_close: + * @inode: inode to board + * @file: file handle to board + * + * The watchdog has a configurable API. There is a religious dispute + * between people who want their watchdog to be able to shut down and + * those who want to be sure if the watchdog manager dies the machine + * reboots. In the former case we disable the counters, in the latter + * case you have to open it again very soon. + */ + +static int wdtpci_release(struct inode *inode, struct file *file) +{ + if(MINOR(inode->i_rdev)==WATCHDOG_MINOR) + { +#ifndef CONFIG_WATCHDOG_NOWAYOUT + inb_p(WDT_DC); /* Disable counters */ + wdtpci_ctr_load(2,0); /* 0 length reset pulses now */ +#endif + wdt_is_open=0; + } + MOD_DEC_USE_COUNT; + return 0; +} + +/** + * notify_sys: + * @this: our notifier block + * @code: the event being reported + * @unused: unused + * + * Our notifier is called on system shutdowns. We want to turn the card + * off at reboot otherwise the machine will reboot again during memory + * test or worse yet during the following fsck. This would suck, in fact + * trust me - if it happens it does suck. + */ + +static int wdtpci_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if(code==SYS_DOWN || code==SYS_HALT) + { + /* Turn the card off */ + inb_p(WDT_DC); + wdtpci_ctr_load(2,0); + } + return NOTIFY_DONE; +} + +/* + * Kernel Interfaces + */ + + +static struct file_operations wdtpci_fops = { + llseek: wdtpci_llseek, + read: wdtpci_read, + write: wdtpci_write, + ioctl: wdtpci_ioctl, + open: wdtpci_open, + release: wdtpci_release, +}; + +static struct miscdevice wdtpci_miscdev= +{ + WATCHDOG_MINOR, + "watchdog", + &wdtpci_fops +}; + +#ifdef CONFIG_WDT_501 +static struct miscdevice temp_miscdev= +{ + TEMP_MINOR, + "temperature", + &wdtpci_fops +}; +#endif + +/* + * The WDT card needs to learn about soft shutdowns in order to + * turn the timebomb registers off. + */ + +static struct notifier_block wdtpci_notifier= +{ + wdtpci_notify_sys, + NULL, + 0 +}; + +#ifdef MODULE + +#define wdtpci_init init_module + +/** + * cleanup_module: + * + * Unload the watchdog. You cannot do this with any file handles open. + * If your watchdog is set to continue ticking on close and you unload + * it, well it keeps ticking. We won't get the interrupt but the board + * will not touch PC memory so all is fine. You just have to load a new + * module in 60 seconds or reboot. + */ + +void cleanup_module(void) +{ + misc_deregister(&wdtpci_miscdev); +#ifdef CONFIG_WDT_501_PCI + misc_deregister(&temp_miscdev); +#endif + unregister_reboot_notifier(&wdtpci_notifier); + release_region(io,16); + free_irq(irq, &wdtpci_miscdev); +} + +#endif + +/** + * wdtpci_init: + * + * Set up the WDT watchdog board. All we have to do is grab the + * resources we require and bitch if anyone beat us to them. + * The open() function will actually kick the board off. + */ + +int __init wdtpci_init(void) +{ + struct pci_dev *dev = NULL; + + if (pci_present()) + { + while ((dev = pci_find_device(PCI_VENDOR_ID_ACCESSIO, + PCI_DEVICE_ID_WDG_CSM, dev))) { + /* See if we can do this device */ + irq = dev->irq; + io = dev->resource[2].start; + printk("WDT501-P(PCI-WDG-CSM) driver 0.07 at %X " + "(Interrupt %d)\n", io, irq); + } + } + if(request_region(io, 16, "wdt-pci")==NULL) + { + printk(KERN_ERR "I/O %d is not free.\n", io); + return -EIO; + } + if(request_irq(irq, wdtpci_interrupt, SA_INTERRUPT|SA_SHIRQ, "wdt-pci", &wdtpci_miscdev)) + { + printk(KERN_ERR "IRQ %d is not free.\n", irq); + release_region(io, 16); + return -EIO; + } + misc_register(&wdtpci_miscdev); +#ifdef CONFIG_WDT_501 + misc_register(&temp_miscdev); +#endif + register_reboot_notifier(&wdtpci_notifier); + return 0; +} + diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/i2c/i2c-elektor.c linux/drivers/i2c/i2c-elektor.c --- v2.3.99-pre3/linux/drivers/i2c/i2c-elektor.c Sun Mar 19 18:35:30 2000 +++ linux/drivers/i2c/i2c-elektor.c Mon Mar 27 10:28:55 2000 @@ -231,7 +231,7 @@ pcf_isa_unreg, }; -static int __init i2c_pcfisa_init(void) +int __init i2c_pcfisa_init(void) { struct i2c_pcf_isa *pisa = &gpi; diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/ide/ide-disk.c linux/drivers/ide/ide-disk.c --- v2.3.99-pre3/linux/drivers/ide/ide-disk.c Mon Mar 27 08:08:24 2000 +++ linux/drivers/ide/ide-disk.c Mon Apr 3 13:30:00 2000 @@ -813,14 +813,18 @@ (!drive->forced_geom) && drive->bios_sect && drive->bios_head) drive->bios_cyl = (capacity / drive->bios_sect) / drive->bios_head; -#if 0 /* done instead for entire identify block in arch/ide.h stuff */ - /* fix byte-ordering of buffer size field */ - id->buf_size = le16_to_cpu(id->buf_size); -#endif - printk (KERN_INFO "%s: %.40s, %ldMB w/%dkB Cache, CHS=%d/%d/%d", - drive->name, id->model, - capacity/2048L, id->buf_size/2, - drive->bios_cyl, drive->bios_head, drive->bios_sect); + printk (KERN_INFO "%s: %ld sectors", drive->name, capacity); + + /* Give size in megabytes (MB), not mebibytes (MiB). */ + /* We compute the exact rounded value, avoiding overflow. */ + printk (" (%ld MB)", (capacity - capacity/625 + 974)/1950); + + /* Only print cache size when it was specified */ + if (id->buf_size) + printk (" w/%dKiB Cache", id->buf_size/2); + + printk(", CHS=%d/%d/%d", + drive->bios_cyl, drive->bios_head, drive->bios_sect); #ifdef CONFIG_BLK_DEV_IDEDMA if (drive->using_dma) (void) HWIF(drive)->dmaproc(ide_dma_verbose, drive); diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/ide/ide-pci.c linux/drivers/ide/ide-pci.c --- v2.3.99-pre3/linux/drivers/ide/ide-pci.c Mon Mar 27 08:08:24 2000 +++ linux/drivers/ide/ide-pci.c Mon Mar 27 11:01:13 2000 @@ -603,6 +603,8 @@ IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) || IDE_PCI_DEVID_EQ(d->devid, DEVID_CS5530) || IDE_PCI_DEVID_EQ(d->devid, DEVID_CY82C693) || + IDE_PCI_DEVID_EQ(d->devid, DEVID_CMD646) || + IDE_PCI_DEVID_EQ(d->devid, DEVID_CMD648) || ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))) { unsigned long dma_base = ide_get_or_set_dma_base(hwif, (!mate && d->extra) ? d->extra : 0, d->name); if (dma_base && !(pcicmd & PCI_COMMAND_MASTER)) { diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/ide/ide.c linux/drivers/ide/ide.c --- v2.3.99-pre3/linux/drivers/ide/ide.c Mon Mar 27 08:08:24 2000 +++ linux/drivers/ide/ide.c Tue Apr 4 19:25:14 2000 @@ -1662,6 +1662,7 @@ rq->cmd = IDE_DRIVE_CMD; rq->sector = 0; rq->nr_sectors = 0; + rq->nr_segments = 0; rq->current_nr_sectors = 0; rq->sem = NULL; rq->bh = NULL; diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/net/8390.c linux/drivers/net/8390.c --- v2.3.99-pre3/linux/drivers/net/8390.c Mon Mar 27 08:08:26 2000 +++ linux/drivers/net/8390.c Sun Apr 2 15:38:53 2000 @@ -114,8 +114,8 @@ static void set_multicast_list(struct net_device *dev); static void do_set_multicast_list(struct net_device *dev); -/** - * DOC: SMP and the 8390 setup. +/* + * SMP and the 8390 setup. * * The 8390 isnt exactly designed to be multithreaded on RX/TX. There is * a page register that controls bank and packet buffer access. We guard @@ -407,13 +407,16 @@ } /** - * ei_interrupt - - * @irq: - * @dev_id: - * @regs: + * ei_interrupt - handle the interrupts from an 8390 + * @irq: interrupt number + * @dev_id: a pointer to the net_device + * @regs: unused * - * The typical workload of the driver: - * Handle the ether interface interrupts. + * Handle the ether interface interrupts. We pull packets from + * the 8390 via the card specific functions and fire them at the networking + * stack. We also handle transmit completions and wake the transmit path if + * neccessary. We also update the counters and do other housekeeping as + * needed */ void ei_interrupt(int irq, void *dev_id, struct pt_regs * regs) diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/net/Config.in linux/drivers/net/Config.in --- v2.3.99-pre3/linux/drivers/net/Config.in Mon Mar 27 08:08:26 2000 +++ linux/drivers/net/Config.in Sun Apr 2 15:38:53 2000 @@ -108,9 +108,7 @@ tristate ' HP PCLAN+ (27247B and 27252A) support' CONFIG_HPLAN_PLUS tristate ' HP PCLAN (27245 and other 27xxx series) support' CONFIG_HPLAN tristate ' HP 10/100VG PCLAN (ISA, EISA, PCI) support' CONFIG_HP100 - if [ "$CONFIG_OBSOLETE" = "y" ]; then - tristate ' ICL EtherTeam 16i/32 support' CONFIG_ETH16I - fi + tristate ' ICL EtherTeam 16i/32 support' CONFIG_ETH16I tristate ' NE2000/NE1000 support' CONFIG_NE2000 if [ "$CONFIG_OBSOLETE" = "y" ]; then tristate ' SEEQ8005 support (EXPERIMENTAL)' CONFIG_SEEQ8005 @@ -194,7 +192,7 @@ bool 'FDDI driver support' CONFIG_FDDI if [ "$CONFIG_FDDI" = "y" ]; then - bool ' Digital DEFEA and DEFPA adapter support' CONFIG_DEFXX + dep_tristate ' Digital DEFEA and DEFPA adapter support' CONFIG_DEFXX $CONFIG_FDDI tristate ' SysKonnect FDDI PCI support' CONFIG_SKFP fi @@ -216,6 +214,7 @@ tristate 'PPP (point-to-point protocol) support' CONFIG_PPP if [ ! "$CONFIG_PPP" = "n" ]; then + dep_bool ' PPP multilink support (EXPERIMENTAL)' CONFIG_PPP_MULTILINK $CONFIG_EXPERIMENTAL dep_tristate ' PPP support for async serial ports' CONFIG_PPP_ASYNC $CONFIG_PPP dep_tristate ' PPP support for sync tty ports' CONFIG_PPP_SYNC_TTY $CONFIG_PPP dep_tristate ' PPP Deflate compression' CONFIG_PPP_DEFLATE $CONFIG_PPP diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/net/Makefile linux/drivers/net/Makefile --- v2.3.99-pre3/linux/drivers/net/Makefile Sun Mar 19 18:35:30 2000 +++ linux/drivers/net/Makefile Mon Mar 27 09:44:58 2000 @@ -324,7 +324,9 @@ M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m))) MX_OBJS := $(sort $(filter $(export-objs), $(obj-m))) +ifneq ($(ARCH),s390) O_OBJS += auto_irq.o +endif include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/net/Space.c linux/drivers/net/Space.c --- v2.3.99-pre3/linux/drivers/net/Space.c Thu Mar 2 14:36:22 2000 +++ linux/drivers/net/Space.c Sun Apr 2 15:38:53 2000 @@ -119,7 +119,7 @@ extern int de620_probe(struct net_device *); /* FDDI adapters */ -extern int dfx_probe(struct net_device *dev); +extern int dfx_probe(void); extern int apfddi_init(struct net_device *dev); extern int skfp_probe(struct net_device *dev); @@ -185,6 +185,9 @@ #ifdef CONFIG_NE3210 {ne3210_probe, 0}, #endif +#ifdef CONFIG_DEFXX + {dfx_probe, 0}. +#endif {NULL, 0}, }; @@ -469,9 +472,6 @@ return 1; /* ENXIO */ if (1 -#ifdef CONFIG_DEFXX - && dfx_probe(dev) -#endif #ifdef CONFIG_APFDDI && apfddi_init(dev) #endif diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/net/defxx.c linux/drivers/net/defxx.c --- v2.3.99-pre3/linux/drivers/net/defxx.c Mon Mar 27 08:08:26 2000 +++ linux/drivers/net/defxx.c Mon Apr 10 23:09:01 2000 @@ -194,11 +194,12 @@ * 12-Sep-96 LVS Reset current address to factory address during * device open. Updated transmit path to post a * single fragment which includes PRH->end of data. + * Mar 2000 AC Did various cleanups for 2.3.x */ /* Version information string - should be updated prior to each new release!!! */ -static const char *version = "defxx.c:v1.04 09/16/96 Lawrence V. Stefani (stefani@lkg.dec.com)\n"; +static const char *version = "defxx.c:v1.05 2000/03/26 Lawrence V. Stefani (stefani@lkg.dec.com) and others\n"; /* Include files */ @@ -236,11 +237,11 @@ /* Define global routines */ -int dfx_probe(struct net_device *dev); +int dfx_probe(void); /* Define module-wide (static) routines */ -static struct net_device *dfx_alloc_device(struct net_device *dev, u16 iobase); +static struct net_device *dfx_alloc_device(u16 iobase); static void dfx_bus_init(struct net_device *dev); static void dfx_bus_config_check(DFX_board_t *bp); @@ -402,29 +403,9 @@ * dev - pointer to device information * * Functional Description: - * This routine is called by the OS for each FDDI device name (fddi0, - * fddi1,...,fddi6, fddi7) specified in drivers/net/Space.c. Since - * the DEFXX.C driver currently does not support being loaded as a - * module, dfx_probe() will initialize all devices the first time - * it is called. - * - * Let's say that dfx_probe() is getting called to initialize fddi0. - * Furthermore, let's say there are three supported controllers in the - * system. Before dfx_probe() leaves, devices fddi0, fddi1, and fddi2 - * will be initialized and a global flag will be set to indicate that - * dfx_probe() has already been called. - * - * However...the OS doesn't know that we've already initialized - * devices fddi1 and fddi2 so dfx_probe() gets called again and again - * until it reaches the end of the device list for FDDI (presently, - * fddi7). It's important that the driver "pretend" to probe for - * devices fddi1 and fddi2 and return success. Devices fddi3 - * through fddi7 will return failure since they weren't initialized. - * - * This algorithm seems to work for the time being. As other FDDI - * drivers are written for Linux, a more generic approach (perhaps - * similar to the Ethernet card approach) may need to be implemented. - * + * This routine is called by the OS once at startup to scan for + * DEFXX cards. + * * Return Codes: * 0 - This device (fddi0, fddi1, etc) configured successfully * -ENODEV - No devices present, or no Digital FDDI EISA or PCI device @@ -446,7 +427,9 @@ * the device structure. */ -int __init dfx_probe(struct net_device *dev) +static struct net_device *bp_root; + +int __init dfx_probe(void) { int i; /* used in for loops */ int version_disp; /* was version info string already displayed? */ @@ -456,44 +439,26 @@ u16 command; /* PCI Configuration space Command register val */ u32 slot_id; /* EISA hardware (slot) ID read from adapter */ DFX_board_t *bp; /* board pointer */ + struct net_device *dev; DBG_printk("In dfx_probe...\n"); - /* - * Verify whether we're going through dfx_probe() again - * - * If so, see if we're going through for a subsequent fddi device that - * we've already initialized. If we are, return success (0). If not, - * return failure (-ENODEV). - */ - version_disp = 0; /* default to version string not displayed */ - if (already_probed) - { - DBG_printk("Already entered dfx_probe\n"); - if (dev != NULL) - if ((strncmp(dev->name, "fddi", 4) == 0) && (dev->base_addr != 0)) - { - DBG_printk("In dfx_probe for fddi adapter (%s) we've already initialized it, so return success\n", dev->name); - return(0); - } - return(-ENODEV); - } - already_probed = 1; /* set global flag */ + already_probed = 1; /* set global flag */ /* Scan for FDDI EISA controllers */ for (i=0; i < DFX_MAX_EISA_SLOTS; i++) /* only scan for up to 16 EISA slots */ - { + { port = (i << 12) + PI_ESIC_K_SLOT_ID; /* port = I/O address for reading slot ID */ slot_id = inl(port); /* read EISA HW (slot) ID */ if ((slot_id & 0xF0FFFFFF) == DEFEA_PRODUCT_ID) - { + { if (!version_disp) /* display version info if adapter is found */ - { + { version_disp = 1; /* set display flag to TRUE so that */ printk(version); /* we only display this string ONCE */ - } + } port = (i << 12); /* recalc base addr */ @@ -501,46 +466,47 @@ port_len = PI_ESIC_K_CSR_IO_LEN; if (check_region(port, port_len) == 0) - { + { /* Allocate a new device structure for this adapter */ - dev = dfx_alloc_device(dev, port); + dev = dfx_alloc_device(port); if (dev != NULL) - { + { /* Initialize board structure with bus-specific info */ - bp = (DFX_board_t *) dev->priv; + bp->next = bp_root; + bp_root = dev; bp->dev = dev; bp->bus_type = DFX_BUS_TYPE_EISA; if (dfx_driver_init(dev) == DFX_K_SUCCESS) num_boards++; /* only increment global board count on success */ else dev->base_addr = 0; /* clear port address field in device structure on failure */ - } } + } else printk("I/O range allocated to adapter (0x%X-0x%X) is already being used!\n", port, (port + port_len-1)); - } } + } /* Scan for FDDI PCI controllers */ if (pci_present()) /* is PCI even present? */ while ((pdev = pci_find_device(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_FDDI, pdev))) - { + { if (!version_disp) /* display version info if adapter is found */ - { + { version_disp = 1; /* set display flag to TRUE so that */ printk(version); /* we only display this string ONCE */ - } + } /* Verify that I/O enable bit is set (PCI slot is enabled) */ pci_read_config_word(pdev, PCI_COMMAND, &command); if ((command & PCI_COMMAND_IO) == 0) - printk("I/O enable bit not set! Verify that slot is enabled\n"); + printk(KERN_ERR "defxx: I/O enable bit not set! Verify that slot is enabled\n"); else - { + { /* Turn off memory mapped space and enable mastering */ command |= PCI_COMMAND_MASTER; @@ -556,28 +522,30 @@ port_len = PFI_K_CSR_IO_LEN; if (check_region(port, port_len) == 0) - { + { /* Allocate a new device structure for this adapter */ - dev = dfx_alloc_device(dev, port); + dev = dfx_alloc_device(port); if (dev != NULL) - { + { /* Initialize board structure with bus-specific info */ bp = (DFX_board_t *) dev->priv; bp->dev = dev; + bp->next = bp_root; + bp_root = dev; bp->bus_type = DFX_BUS_TYPE_PCI; bp->pci_dev = pdev; if (dfx_driver_init(dev) == DFX_K_SUCCESS) num_boards++; /* only increment global board count on success */ else dev->base_addr = 0; /* clear port address field in device structure on failure */ - } } - else - printk("I/O range allocated to adapter (0x%X-0x%X) is already being used!\n", port, (port + port_len-1)); } + else + printk(KERN_ERR "defxx: I/O range allocated to adapter (0x%X-0x%X) is already being used!\n", port, (port + port_len-1)); } + } /* * If we're at this point we're going through dfx_probe() for the first @@ -589,7 +557,7 @@ return(0); else return(-ENODEV); - } +} /* @@ -639,32 +607,32 @@ * None */ -struct net_device __init *dfx_alloc_device( struct net_device *dev, u16 iobase) +struct net_device __init *dfx_alloc_device(u16 iobase) { struct net_device *tmp_dev; /* pointer to a device structure */ + int err; DBG_printk("In dfx_alloc_device...\n"); /* Find next free fddi entry */ - for (tmp_dev = dev; tmp_dev != NULL; tmp_dev = tmp_dev->next) - if ((strncmp(tmp_dev->name, "fddi", 4) == 0) && (tmp_dev->base_addr == 0)) - break; + tmp_dev = dev_alloc("fddi%d", &err); if (tmp_dev == NULL) - { - printk("Could not find free FDDI device structure for this adapter!\n"); + { + printk(KERN_ERR "Could not find free FDDI device structure for this adapter!\n"); return(NULL); - } + } DBG_printk("Device entry free, device name = %s\n", tmp_dev->name); /* Allocate space for private board structure */ tmp_dev->priv = (void *) kmalloc(sizeof(DFX_board_t), GFP_KERNEL); if (tmp_dev->priv == NULL) - { - printk("Could not allocate memory for private board structure!\n"); + { + printk(KERN_ERR "defxx: Could not allocate memory for private board structure!\n"); + kfree(tmp_dev); return(NULL); - } + } memset(tmp_dev->priv, 0, sizeof(DFX_board_t)); /* clear structure */ /* Initialize new device structure */ @@ -696,7 +664,7 @@ fddi_setup(tmp_dev); return(tmp_dev); - } +} /* @@ -1370,22 +1338,22 @@ * if the open is successful. */ -int dfx_open( - struct net_device *dev - ) - - { +int dfx_open(struct net_device *dev) +{ DFX_board_t *bp = (DFX_board_t *)dev->priv; DBG_printk("In dfx_open...\n"); + + MOD_INC_USE_COUNT; /* Register IRQ - support shared interrupts by passing device ptr */ if (request_irq(dev->irq, (void *)dfx_interrupt, SA_SHIRQ, dev->name, dev)) - { - printk("%s: Requested IRQ %d is busy\n", dev->name, dev->irq); - return(-EAGAIN); - } + { + printk(KERN_ERR "%s: Requested IRQ %d is busy\n", dev->name, dev->irq); + MOD_DEC_USE_COUNT; + return -EAGAIN; + } /* * Set current address to factory MAC address @@ -1416,16 +1384,17 @@ bp->reset_type = PI_PDATA_A_RESET_M_SKIP_ST; /* skip self-test */ if (dfx_adap_init(bp) != DFX_K_SUCCESS) - { - printk("%s: Adapter open failed!\n", dev->name); - return(-EAGAIN); - } + { + printk(KERN_ERR "%s: Adapter open failed!\n", dev->name); + free_irq(dev->irq, dev); + MOD_DEC_USE_COUNT; + return -EAGAIN; + } /* Set device structure info */ - netif_start_queue(dev); return(0); - } +} /* @@ -1460,11 +1429,8 @@ * routine. */ -int dfx_close( - struct net_device *dev - ) - - { +int dfx_close(struct net_device *dev) +{ DFX_board_t *bp = (DFX_board_t *)dev->priv; DBG_printk("In dfx_close...\n"); @@ -1514,8 +1480,10 @@ /* Deregister (free) IRQ */ free_irq(dev->irq, dev); + + MOD_DEC_USE_COUNT; return(0); - } +} /* @@ -3491,6 +3459,30 @@ bp->cons_block_virt->xmt_rcv_data = prod_cons; return; } + + +#ifdef MODULE + +int init_module(void) +{ + if(dfx_probe()<0) + return -ENODEV; + return 0; +} + +void cleanup_module(void) +{ + while(bp_root!=NULL) + { + struct net_device *tmp=bp_root; + DFX_board_t *priv=tmp->priv; + bp_root=priv->next; + kfree(tmp->priv); + kfree(tmp); + } +} + +#endif /* diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/net/defxx.h linux/drivers/net/defxx.h --- v2.3.99-pre3/linux/drivers/net/defxx.h Wed Aug 18 11:36:45 1999 +++ linux/drivers/net/defxx.h Sun Apr 2 15:38:53 2000 @@ -1756,6 +1756,7 @@ /* Store device, bus-specific, and parameter information for this adapter */ struct net_device *dev; /* pointer to device structure */ + struct net_device *next; u32 bus_type; /* bus type (0 == PCI, 1 == EISA) */ u16 base_addr; /* base I/O address (same as dev->base_addr) */ struct pci_dev * pci_dev; diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/net/eepro100.c linux/drivers/net/eepro100.c --- v2.3.99-pre3/linux/drivers/net/eepro100.c Sat Feb 26 22:31:46 2000 +++ linux/drivers/net/eepro100.c Thu Mar 30 18:00:01 2000 @@ -1,9 +1,8 @@ +/* drivers/net/eepro100.c: An Intel i82557-559 Ethernet driver for Linux. */ /* - - drivers/net/eepro100.c: An Intel i82557-559 Ethernet driver for Linux - + NOTICE: For use with late 2.3 kernels only. + May not compile for kernels 2.3.43-47. Written 1996-1999 by Donald Becker. - Modified 2000 by Linux Kernel Team This software may be used and distributed according to the terms of the GNU Public License, incorporated herein by reference. @@ -11,8 +10,6 @@ This driver is for the Intel EtherExpress Pro100 (Speedo3) design. It should work with all i82557/558/559 boards. - To use as a module, use the compile-command at the end of the file. - The author may be reached as becker@CESDIS.usra.edu, or C/O Center of Excellence in Space Data and Information Sciences Code 930.5, NASA Goddard Space Flight Center, Greenbelt MD 20771 @@ -23,14 +20,211 @@ There is a Majordomo mailing list based at linux-eepro100@cesdis.gsfc.nasa.gov + The driver also contains updates by different kernel developers + (see incomplete list below). + This driver clone is maintained by Andrey V. Savochkin . + Please use this email address and linux-kernel mailing list for bug reports. + + Version history: + 1998 Apr - 2000 Feb Andrey V. Savochkin + Serious fixes for multicast filter list setting, TX timeout routine; + RX ring refilling logic; other stuff + 2000 Feb Jeff Garzik + Convert to new PCI driver interface + 2000 Mar 24 Dragan Stancevic + Disabled FC and ER, to avoid lockups when when we get FCP interrupts. + Dragan Stancevic March 24th, 2000. +*/ +static const char *version = +"eepro100.c:v1.09j-t 9/29/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html\n" +"eepro100.c: $Revision: 1.29 $ 2000/03/30 Modified by Andrey V. Savochkin and others\n"; - Version history: - v1.09j+LK1.0 - Jeff Garzik - Convert to new PCI driver interface +/* A few user-configurable values that apply to all boards. + First set is undocumented and spelled per Intel recommendations. */ + +static int congenb = 0; /* Enable congestion control in the DP83840. */ +static int txfifo = 8; /* Tx FIFO threshold in 4 byte units, 0-15 */ +static int rxfifo = 8; /* Rx FIFO threshold, default 32 bytes. */ +/* Tx/Rx DMA burst length, 0-127, 0 == no preemption, tx==128 -> disabled. */ +static int txdmacount = 128; +static int rxdmacount = 0; + +/* Set the copy breakpoint for the copy-only-tiny-buffer Rx method. + Lower values use more memory, but are faster. */ +static int rx_copybreak = 200; + +/* Maximum events (Rx packets, etc.) to handle at each interrupt. */ +static int max_interrupt_work = 20; + +/* Maximum number of multicast addresses to filter (vs. rx-all-multicast) */ +static int multicast_filter_limit = 64; + +/* 'options' is used to pass a transceiver override or full-duplex flag + e.g. "options=16" for FD, "options=32" for 100mbps-only. */ +static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1}; +static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1}; +static int debug = -1; /* The debug level */ +/* A few values that may be tweaked. */ +/* The ring sizes should be a power of two for efficiency. */ +#define TX_RING_SIZE 32 +#define RX_RING_SIZE 32 +/* How much slots multicast filter setup may take. + Do not descrease without changing set_rx_mode() implementaion. */ +#define TX_MULTICAST_SIZE 2 +#define TX_MULTICAST_RESERV (TX_MULTICAST_SIZE*2) +/* Actual number of TX packets queued, must be + <= TX_RING_SIZE-TX_MULTICAST_RESERV. */ +#define TX_QUEUE_LIMIT (TX_RING_SIZE-TX_MULTICAST_RESERV) +/* Hysteresis marking queue as no longer full. */ +#define TX_QUEUE_UNFULL (TX_QUEUE_LIMIT-4) +/* Operational parameters that usually are not changed. */ +/* Time in jiffies before concluding the transmitter is hung. */ +#define TX_TIMEOUT (2*HZ) +/* Size of an pre-allocated Rx buffer: + slack.*/ +#define PKT_BUF_SZ 1536 + +#if !defined(__OPTIMIZE__) || !defined(__KERNEL__) +#warning You must compile this file with the correct options! +#warning See the last lines of the source file. +#error You must compile this driver with "-O". +#endif + +#include +#include +#include +#if defined(MODVERSIONS) +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +MODULE_AUTHOR("Maintainer: Andrey V. Savochkin "); +MODULE_DESCRIPTION("Intel i82557/i82558/i82559 PCI EtherExpressPro driver"); +MODULE_PARM(debug, "i"); +MODULE_PARM(options, "1-" __MODULE_STRING(8) "i"); +MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i"); +MODULE_PARM(congenb, "i"); +MODULE_PARM(txfifo, "i"); +MODULE_PARM(rxfifo, "i"); +MODULE_PARM(txdmacount, "i"); +MODULE_PARM(rxdmacount, "i"); +MODULE_PARM(rx_copybreak, "i"); +MODULE_PARM(max_interrupt_work, "i"); +MODULE_PARM(multicast_filter_limit, "i"); + +#define RUN_AT(x) (jiffies + (x)) + +/* ACPI power states don't universally work (yet) */ +#ifndef CONFIG_EEPRO100_PM +#undef pci_set_power_state +#define pci_set_power_state null_set_power_state +static inline int null_set_power_state(struct pci_dev *dev, int state) +{ + return 0; +} +#endif /* CONFIG_EEPRO100_PM */ + +#ifndef pci_resource_start +#define pci_resource_start(p, n) (p)->resource[n].start +#define pci_resource_len(p, n) ((p)->resource[n].end - (p)->resource[n].start) +#endif + +/* Because of changes in this area the driver may not compile for kernels + 2.3.43 - 2.3.47. --SAW */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43) +#define netif_wake_queue(dev) do { \ + clear_bit(0, (void*)&dev->tbusy); \ + mark_bh(NET_BH); \ + } while(0) +#define netif_start_queue(dev) clear_bit(0, (void*)&dev->tbusy) +#define netif_stop_queue(dev) set_bit(0, (void*)&dev->tbusy) +#define netif_running(dev) dev->start +#define netdevice_start(dev) dev->start = 1 +#define netdevice_stop(dev) dev->start = 0 +#define netif_set_tx_timeout(dev, tf, tm) +#define dev_kfree_skb_irq(x) dev_kfree_skb(x) +#else +#define netdevice_start(dev) +#define netdevice_stop(dev) +#define netif_set_tx_timeout(dev, tf, tm) \ + do { \ + (dev)->tx_timeout = (tf); \ + (dev)->watchdog_timeo = (tm); \ + } while(0) +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,47) +#define netif_device_attach(dev) netif_start_queue(dev) +#define netif_device_detach(dev) netif_stop_queue(dev) +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43) +typedef u32 dma_addr_t; +static void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, + dma_addr_t *dma_handle) +{ + void *ret; + ret = kmalloc(size, GFP_ATOMIC); + if (ret != NULL) { + *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) +{ + kfree(vaddr); +} + +#define PCI_DMA_FROMDEVICE 0 +#define PCI_DMA_TODEVICE 0 + +extern inline dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, + size_t size, int direction) +{ + return virt_to_bus(ptr); +} + +extern inline void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, + size_t size, int direction) +{ +} + +extern inline void pci_dma_sync_single(struct pci_dev *hwdev, + dma_addr_t dma_handle, + size_t size, int direction) +{ +} +#endif + +/* The total I/O port extent of the board. + The registers beyond 0x18 only exist on the i82558. */ +#define SPEEDO3_TOTAL_SIZE 0x20 + +int speedo_debug = 1; + +/* Theory of Operation I. Board Compatibility @@ -136,24 +330,6 @@ is non-trivial, and the larger copy might flush the cache of useful data, so we pass up the skbuff the packet was received into. -IIID. Synchronization -The driver runs as two independent, single-threaded flows of control. One -is the send-packet routine, which enforces single-threaded use by the -dev->tbusy flag. The other thread is the interrupt handler, which is single -threaded by the hardware and other software. - -The send packet thread has partial control over the Tx ring and 'dev->tbusy' -flag. It sets the tbusy flag whenever it's queuing a Tx packet. If the next -queue slot is empty, it clears the tbusy flag when finished otherwise it sets -the 'sp->tx_full' flag. - -The interrupt handler has exclusive control over the Rx ring and records stats -from the Tx ring. (The Tx-done interrupt can't be selectively turned off, so -we can't avoid the interrupt overhead by having the Tx routine reap the Tx -stats.) After reaping the stats, it marks the queue entry as empty by setting -the 'base' to zero. Iff the 'sp->tx_full' flag is set, it clears both the -tx_full and tbusy flags. - IV. Notes Thanks to Steve Williams of Intel for arranging the non-disclosure agreement @@ -162,120 +338,30 @@ */ +static int speedo_found1(struct pci_dev *pdev, long ioaddr, int irq, int chip_idx, int fnd_cnt, int acpi_idle_state); -static const char *version = -"eepro100.c:v1.09j+LK1.0 Feb 13, 2000 Linux Kernel Team http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html\n"; - -/* A few user-configurable values that apply to all boards. - First set is undocumented and spelled per Intel recommendations. */ - -static int congenb = 0; /* Enable congestion control in the DP83840. */ -static int txfifo = 8; /* Tx FIFO threshold in 4 byte units, 0-15 */ -static int rxfifo = 8; /* Rx FIFO threshold, default 32 bytes. */ -/* Tx/Rx DMA burst length, 0-127, 0 == no preemption, tx==128 -> disabled. */ -static int txdmacount = 128; -static int rxdmacount = 0; - -/* Set the copy breakpoint for the copy-only-tiny-buffer Rx method. - Lower values use more memory, but are faster. */ -static int rx_copybreak = 200; - -/* Maximum events (Rx packets, etc.) to handle at each interrupt. */ -static int max_interrupt_work = 20; - -/* Maximum number of multicast addresses to filter (vs. rx-all-multicast) */ -static int multicast_filter_limit = 64; - -/* 'options' is used to pass a transceiver override or full-duplex flag - e.g. "options=16" for FD, "options=32" for 100mbps-only. */ -static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int debug = -1; /* The debug level */ - -/* A few values that may be tweaked. */ -/* The ring sizes should be a power of two for efficiency. */ -#define TX_RING_SIZE 32 /* Effectively 2 entries fewer. */ -#define RX_RING_SIZE 32 -/* Actual number of TX packets queued, must be <= TX_RING_SIZE-2. */ -#define TX_QUEUE_LIMIT 12 - -/* Operational parameters that usually are not changed. */ - -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (2*HZ) -/* Size of an pre-allocated Rx buffer: + slack.*/ -#define PKT_BUF_SZ 1536 - -#if !defined(__OPTIMIZE__) || !defined(__KERNEL__) -#warning You must compile this file with the correct options! -#warning See the last lines of the source file. -#error You must compile this driver with "-O". +#ifdef USE_IO +#define SPEEDO_IOTYPE PCI_USES_MASTER|PCI_USES_IO|PCI_ADDR1 +#define SPEEDO_SIZE 32 +#else +#define SPEEDO_IOTYPE PCI_USES_MASTER|PCI_USES_MEM|PCI_ADDR0 +#define SPEEDO_SIZE 0x1000 #endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -MODULE_AUTHOR("Donald Becker "); -MODULE_DESCRIPTION("Intel i82557/i82558 PCI EtherExpressPro driver"); -MODULE_PARM(debug, "i"); -MODULE_PARM(options, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM(congenb, "i"); -MODULE_PARM(txfifo, "i"); -MODULE_PARM(rxfifo, "i"); -MODULE_PARM(txdmacount, "i"); -MODULE_PARM(rxdmacount, "i"); -MODULE_PARM(rx_copybreak, "i"); -MODULE_PARM(max_interrupt_work, "i"); -MODULE_PARM(multicast_filter_limit, "i"); - -#define EEPRO100_MODULE_NAME "eepro100" -#define PFX EEPRO100_MODULE_NAME ": " - -#define RUN_AT(x) (jiffies + (x)) - -/* ACPI power states don't universally work (yet) */ -#ifndef CONFIG_EEPRO100_PM -#undef pci_set_power_state -#define pci_set_power_state null_set_power_state -static inline int null_set_power_state(struct pci_dev *dev, int state) -{ - return 0; -} -#endif /* CONFIG_EEPRO100_PM */ - - -/* compile-time switch to en/disable slow PIO */ -#undef USE_IO - - -int speedo_debug = 1; - - enum pci_flags_bit { PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4, PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3, }; #ifndef USE_IO +/* Currently alpha headers define in/out macros. + Undefine them. 2000/03/30 SAW */ +#undef inb +#undef inw +#undef inl +#undef outb +#undef outw +#undef outl #define inb readb #define inw readw #define inl readl @@ -284,127 +370,106 @@ #define outl writel #endif - /* How to wait for the command unit to accept a command. Typically this takes 0 ticks. */ -static inline void wait_for_cmd_done (long cmd_ioaddr) +static inline void wait_for_cmd_done(long cmd_ioaddr) { - int wait = 100; - do; - while (inb (cmd_ioaddr) && --wait >= 0); + int wait = 1000; + do ; + while(inb(cmd_ioaddr) && --wait >= 0); } - /* Offsets to the various registers. All accesses need not be longword aligned. */ enum speedo_offsets { SCBStatus = 0, SCBCmd = 2, /* Rx/Command Unit command and status. */ - SCBPointer = 4, /* General purpose pointer. */ - SCBPort = 8, /* Misc. commands and operands. */ - SCBflash = 12, SCBeeprom = 14, /* EEPROM and flash memory control. */ - SCBCtrlMDI = 16, /* MDI interface control. */ - SCBEarlyRx = 20, /* Early receive byte count. */ + SCBPointer = 4, /* General purpose pointer. */ + SCBPort = 8, /* Misc. commands and operands. */ + SCBflash = 12, SCBeeprom = 14, /* EEPROM and flash memory control. */ + SCBCtrlMDI = 16, /* MDI interface control. */ + SCBEarlyRx = 20, /* Early receive byte count. */ }; - - /* Commands that can be put in a command list entry. */ enum commands { - CmdNOp = 0, - CmdIASetup = 0x10000, - CmdConfigure = 0x20000, - CmdMulticastList = 0x30000, - CmdTx = 0x40000, - CmdTDR = 0x50000, - CmdDump = 0x60000, - CmdDiagnose = 0x70000, + CmdNOp = 0, CmdIASetup = 0x10000, CmdConfigure = 0x20000, + CmdMulticastList = 0x30000, CmdTx = 0x40000, CmdTDR = 0x50000, + CmdDump = 0x60000, CmdDiagnose = 0x70000, CmdSuspend = 0x40000000, /* Suspend after completion. */ CmdIntr = 0x20000000, /* Interrupt after completion. */ CmdTxFlex = 0x00080000, /* Use "Flexible mode" for CmdTx command. */ }; - - -/* Do atomically if possible. */ -#if defined(__i386__) || defined(__alpha__) || defined(__ia64__) -#define clear_suspend(cmd) clear_bit(30, &(cmd)->cmd_status) -#elif defined(__powerpc__) -#define clear_suspend(cmd) clear_bit(6, &(cmd)->cmd_status) +/* 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 #else -#if 0 -# error You are probably in trouble: clear_suspend() MUST be atomic. -#endif -# define clear_suspend(cmd) (cmd)->cmd_status &= cpu_to_le32(~CmdSuspend) +#error Unsupported byteorder #endif enum SCBCmdBits { - SCBMaskCmdDone = 0x8000, - SCBMaskRxDone = 0x4000, - SCBMaskCmdIdle = 0x2000, - SCBMaskRxSuspend = 0x1000, - SCBMaskEarlyRx = 0x0800, - SCBMaskFlowCtl = 0x0400, - SCBTriggerIntr = 0x0200, - SCBMaskAll = 0x0100, - /* The rest are Rx and Tx commands. */ - CUStart = 0x0010, - CUResume = 0x0020, - CUStatsAddr = 0x0040, - CUShowStats = 0x0050, - CUCmdBase = 0x0060, /* CU Base address (set to zero) . */ - CUDumpStats = 0x0070, /* Dump then reset stats counters. */ - RxStart = 0x0001, - RxResume = 0x0002, - RxAbort = 0x0004, - RxAddrLoad = 0x0006, - RxResumeNoResources = 0x0007, + SCBMaskCmdDone=0x8000, SCBMaskRxDone=0x4000, SCBMaskCmdIdle=0x2000, + SCBMaskRxSuspend=0x1000, SCBMaskEarlyRx=0x0800, SCBMaskFlowCtl=0x0400, + SCBTriggerIntr=0x0200, SCBMaskAll=0x0100, + /* The rest are Rx and Tx commands. */ + CUStart=0x0010, CUResume=0x0020, CUStatsAddr=0x0040, CUShowStats=0x0050, + CUCmdBase=0x0060, /* CU Base address (set to zero) . */ + CUDumpStats=0x0070, /* Dump then reset stats counters. */ + RxStart=0x0001, RxResume=0x0002, RxAbort=0x0004, RxAddrLoad=0x0006, + RxResumeNoResources=0x0007, }; enum SCBPort_cmds { - PortReset = 0, - PortSelfTest = 1, - PortPartialReset = 2, - PortDump = 3, + PortReset=0, PortSelfTest=1, PortPartialReset=2, PortDump=3, }; /* The Speedo3 Rx and Tx frame/buffer descriptors. */ -struct descriptor { /* A generic descriptor. */ - s32 cmd_status; /* All command and status fields. */ - u32 link; /* struct descriptor * */ +struct descriptor { /* A generic descriptor. */ + s32 cmd_status; /* All command and status fields. */ + u32 link; /* struct descriptor * */ unsigned char params[0]; }; /* The Speedo3 Rx and Tx buffer descriptors. */ -struct RxFD { /* Receive frame descriptor. */ +struct RxFD { /* Receive frame descriptor. */ s32 status; - u32 link; /* struct RxFD * */ - u32 rx_buf_addr; /* void * */ + u32 link; /* struct RxFD * */ + u32 rx_buf_addr; /* void * */ u32 count; }; /* Selected elements of the Tx/RxFD.status word. */ enum RxFD_bits { - RxComplete = 0x8000, - RxOK = 0x2000, - RxErrCRC = 0x0800, - RxErrAlign = 0x0400, - RxErrTooBig = 0x0200, - RxErrSymbol = 0x0010, - RxEth2Type = 0x0020, - RxNoMatch = 0x0004, - RxNoIAMatch = 0x0002, - TxUnderrun = 0x1000, - StatusComplete = 0x8000, + RxComplete=0x8000, RxOK=0x2000, + RxErrCRC=0x0800, RxErrAlign=0x0400, RxErrTooBig=0x0200, RxErrSymbol=0x0010, + RxEth2Type=0x0020, RxNoMatch=0x0004, RxNoIAMatch=0x0002, + TxUnderrun=0x1000, StatusComplete=0x8000, }; -struct TxFD { /* Transmit frame descriptor set. */ +struct TxFD { /* Transmit frame descriptor set. */ s32 status; - u32 link; /* void * */ - u32 tx_desc_addr; /* Always points to the tx_buf_addr element. */ - s32 count; /* # of TBD (=1), Tx start thresh., etc. */ + u32 link; /* void * */ + u32 tx_desc_addr; /* Always points to the tx_buf_addr element. */ + s32 count; /* # of TBD (=1), Tx start thresh., etc. */ /* This constitutes two "TBD" entries -- we only use one. */ - u32 tx_buf_addr0; /* void *, frame to be transmitted. */ - s32 tx_buf_size0; /* Length of Tx frame. */ - u32 tx_buf_addr1; /* void *, frame to be transmitted. */ - s32 tx_buf_size1; /* Length of Tx frame. */ +#define TX_DESCR_BUF_OFFSET 16 + u32 tx_buf_addr0; /* void *, frame to be transmitted. */ + s32 tx_buf_size0; /* Length of Tx frame. */ + u32 tx_buf_addr1; /* void *, frame to be transmitted. */ + s32 tx_buf_size1; /* Length of Tx frame. */ +}; + +/* Multicast filter setting block. --SAW */ +struct speedo_mc_block { + struct speedo_mc_block *next; + unsigned int tx; + dma_addr_t frame_dma; + unsigned int len; + struct descriptor frame __attribute__ ((__aligned__(16))); }; /* Elements of the dump_statistics block. This block must be lword aligned. */ @@ -428,46 +493,55 @@ u32 done_marker; }; +enum Rx_ring_state_bits { + RrNoMem=1, RrPostponed=2, RrNoResources=4, RrOOMReported=8, +}; + /* Do not change the position (alignment) of the first few elements! - The later elements are grouped for cache locality. */ + The later elements are grouped for cache locality. + + Unfortunately, all the positions have been shifted since there. + A new re-alignment is required. 2000/03/06 SAW */ struct speedo_private { - struct TxFD *tx_ring; /* Commands (usually CmdTxPacket). */ + struct TxFD *tx_ring; /* Commands (usually CmdTxPacket). */ struct RxFD *rx_ringp[RX_RING_SIZE];/* Rx descriptor, used as ring. */ /* The addresses of a Tx/Rx-in-place packets/buffers. */ struct sk_buff *tx_skbuff[TX_RING_SIZE]; struct sk_buff *rx_skbuff[RX_RING_SIZE]; - dma_addr_t rx_ring_dma[RX_RING_SIZE]; + /* Mapped addresses of the rings. */ dma_addr_t tx_ring_dma; - struct descriptor *last_cmd; /* Last command sent. */ - unsigned int cur_tx, dirty_tx; /* The ring entries to be free()ed. */ - spinlock_t lock; /* Group with Tx control cache line. */ - u32 tx_threshold; /* The value for txdesc.count. */ - struct RxFD *last_rxf; /* Last command sent. */ - unsigned int cur_rx, dirty_rx; /* The next free ring entry */ - long last_rx_time; /* Last Rx, in jiffies, to handle Rx hang. */ +#define TX_RING_ELEM_DMA(sp, n) ((sp)->tx_ring_dma + (n)*sizeof(struct TxFD)) + dma_addr_t rx_ring_dma[RX_RING_SIZE]; + struct descriptor *last_cmd; /* Last command sent. */ + unsigned int cur_tx, dirty_tx; /* The ring entries to be free()ed. */ + spinlock_t lock; /* Group with Tx control cache line. */ + u32 tx_threshold; /* The value for txdesc.count. */ + struct RxFD *last_rxf; /* Last filled RX buffer. */ + unsigned int cur_rx, dirty_rx; /* The next free ring entry */ + long last_rx_time; /* Last Rx, in jiffies, to handle Rx hang. */ const char *product_name; struct enet_statistics stats; struct speedo_stats *lstats; + dma_addr_t lstats_dma; int chip_id; - unsigned char acpi_pwr; struct pci_dev *pdev; - struct timer_list timer; /* Media selection timer. */ - int mc_setup_frm_len; /* The length of an allocated.. */ - struct descriptor *mc_setup_frm;/* ..multicast setup frame. */ - int mc_setup_busy; /* Avoid double-use of setup frame. */ - dma_addr_t mc_setup_dma; - char rx_mode; /* Current PROMISC/ALLMULTI setting. */ - unsigned int tx_full:1; /* The Tx queue is full. */ - unsigned int full_duplex:1; /* Full-duplex operation requested. */ - unsigned int flow_ctrl:1; /* Use 802.3x flow control. */ - unsigned int rx_bug:1; /* Work around receiver hang errata. */ - unsigned int rx_bug10:1; /* Receiver might hang at 10mbps. */ - unsigned int rx_bug100:1; /* Receiver might hang at 100mbps. */ - unsigned char default_port:8; /* Last dev->if_port value. */ - unsigned short phy[2]; /* PHY media interfaces available. */ - unsigned short advertising; /* Current PHY advertised caps. */ - unsigned short partner; /* Link partner caps. */ + struct timer_list timer; /* Media selection timer. */ + struct speedo_mc_block *mc_setup_head;/* Multicast setup frame list head. */ + struct speedo_mc_block *mc_setup_tail;/* Multicast setup frame list tail. */ + int in_interrupt; /* Word-aligned dev->interrupt */ + unsigned char acpi_pwr; + char rx_mode; /* Current PROMISC/ALLMULTI setting. */ + unsigned int tx_full:1; /* The Tx queue is full. */ + unsigned int full_duplex:1; /* Full-duplex operation requested. */ + unsigned int flow_ctrl:1; /* Use 802.3x flow control. */ + unsigned int rx_bug:1; /* Work around receiver hang errata. */ + unsigned char default_port:8; /* Last dev->if_port value. */ + unsigned char rx_ring_state; /* RX ring status flags. */ + unsigned short phy[2]; /* PHY media interfaces available. */ + unsigned short advertising; /* Current PHY advertised caps. */ + unsigned short partner; /* Link partner caps. */ }; + /* The parameters for a CmdConfigure operation. There are so many options that it would be difficult to document each bit. We mostly use the default or recommended settings. */ @@ -479,7 +553,7 @@ const char i82558_config_cmd[22] = { 22, 0x08, 0, 1, 0, 0, 0x22, 0x03, 1, /* 1=Use MII 0=Use AUI */ 0, 0x2E, 0, 0x60, 0x08, 0x88, - 0x68, 0, 0x40, 0xf2, 0xBD, /* 0xBD->0xFD=Force full-duplex */ + 0x68, 0, 0x40, 0xf2, 0x84, /* Disable FC */ 0x31, 0x05, }; /* PHY media interface chips. */ @@ -493,6 +567,12 @@ static const char is_mii[] = { 0, 1, 1, 0, 1, 1, 0, 1 }; #define EE_READ_CMD (6) +static int eepro100_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent); +static void eepro100_remove_one (struct pci_dev *pdev); +static void eepro100_suspend (struct pci_dev *pdev); +static void eepro100_resume (struct pci_dev *pdev); + static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len); static int mdio_read(long ioaddr, int phy_id, int location); static int mdio_write(long ioaddr, int phy_id, int location, int value); @@ -502,12 +582,15 @@ static void speedo_init_rx_ring(struct net_device *dev); static void speedo_tx_timeout(struct net_device *dev); static int speedo_start_xmit(struct sk_buff *skb, struct net_device *dev); +static void speedo_refill_rx_buffers(struct net_device *dev, int force); static int speedo_rx(struct net_device *dev); +static void speedo_tx_buffer_gc(struct net_device *dev); static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs); static int speedo_close(struct net_device *dev); static struct enet_statistics *speedo_get_stats(struct net_device *dev); static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static void set_rx_mode(struct net_device *dev); +static void speedo_show_state(struct net_device *dev); @@ -518,75 +601,104 @@ 0x2000, 0x2100, 0x0400, 0x3100}; #endif +static int __devinit eepro100_init_one (struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + unsigned long ioaddr; + int irq; + int acpi_idle_state = 0, pm; + static int cards_found = 0; + + static int did_version = 0; /* Already printed version info. */ + if (speedo_debug > 0 && did_version++ == 0) + printk(version); + + if (!request_region(pci_resource_start(pdev, 1), + pci_resource_len(pdev, 1), "eepro100")) { + printk (KERN_ERR "eepro100: cannot reserve I/O ports\n"); + goto err_out_none; + } + if (!request_mem_region(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0), "eepro100")) { + printk (KERN_ERR "eepro100: cannot reserve MMIO region\n"); + goto err_out_free_pio_region; + } + + irq = pdev->irq; +#ifdef USE_IO + ioaddr = pci_resource_start(pdev, 1); + if (speedo_debug > 2) + printk("Found Intel i82557 PCI Speedo at I/O %#lx, IRQ %d.\n", + ioaddr, irq); +#else + ioaddr = (unsigned long)ioremap(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); + if (!ioaddr) { + printk (KERN_ERR "eepro100: cannot remap MMIO region %lx @ %lx\n", + pci_resource_len(pdev, 0), pci_resource_start(pdev, 0)); + goto err_out_free_mmio_region; + } + if (speedo_debug > 2) + printk("Found Intel i82557 PCI Speedo, MMIO at %#lx, IRQ %d.\n", + pci_resource_start(pdev, 0), irq); +#endif + + /* save power state b4 pci_enable_device overwrites it */ + pm = pci_find_capability(pdev, PCI_CAP_ID_PM); + if (pm) { + u16 pwr_command; + pci_read_config_word(pdev, pm + PCI_PM_CTRL, &pwr_command); + acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK; + } + if (pci_enable_device(pdev)) { + printk(KERN_ERR "eepro100: Could not enable PCI device\n"); + goto err_out_free_mmio_region; + } + + pci_set_master(pdev); + + if (speedo_found1(pdev, ioaddr, irq, 0, cards_found, acpi_idle_state) == 0) + cards_found++; + else + goto err_out_iounmap; + + return 0; + +err_out_iounmap: ; +#ifndef USE_IO + iounmap ((void *)ioaddr); +#endif +err_out_free_mmio_region: + release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); +err_out_free_pio_region: + release_region(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1)); +err_out_none: + return -ENODEV; +} -static int __devinit eepro100_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) +static int speedo_found1(struct pci_dev *pdev, + long ioaddr, int irq, int chip_idx, int card_idx, int acpi_idle_state) { struct net_device *dev; struct speedo_private *sp; - unsigned char *tx_ring; - dma_addr_t tx_ring_dma; const char *product; int i, option; u16 eeprom[0x100]; - int acpi_idle_state = 0, pm, irq; - unsigned long ioaddr; - static int card_idx = -1; - - static int did_version = 0; /* Already printed version info. */ - - if (speedo_debug > 0 && did_version++ == 0) - printk(version); - -#ifdef USE_IO - ioaddr = pci_resource_start (pdev, 0); -#else - ioaddr = pci_resource_start (pdev, 1); -#endif - irq = pdev->irq; - - card_idx++; - - if (!request_region (pci_resource_start (pdev, 1), - pci_resource_len (pdev, 1), - EEPRO100_MODULE_NAME)) { - printk (KERN_ERR PFX "cannot reserve I/O ports\n"); - goto err_out_none; - } - if (!request_mem_region (pci_resource_start (pdev, 0), - pci_resource_len (pdev, 0), - EEPRO100_MODULE_NAME)) { - printk (KERN_ERR PFX "cannot reserve MMIO region\n"); - goto err_out_free_pio_region; - } - -#ifndef USE_IO - ioaddr = (unsigned long) ioremap (pci_resource_start (pdev, 0), - pci_resource_len (pdev, 0)); - if (!ioaddr) { - printk (KERN_ERR PFX "cannot remap MMIO region %lx @ %lx\n", - pci_resource_len (pdev, 0), - pci_resource_start (pdev, 0)); - goto err_out_free_mmio_region; - } -#endif + int size; + void *tx_ring_space; + dma_addr_t tx_ring_dma; - tx_ring = pci_alloc_consistent(pdev, TX_RING_SIZE * sizeof(struct TxFD) - + sizeof(struct speedo_stats), &tx_ring_dma); - if (!tx_ring) { - printk(KERN_ERR PFX "Could not allocate DMA memory.\n"); - goto err_out_iounmap; - } + size = TX_RING_SIZE * sizeof(struct TxFD) + sizeof(struct speedo_stats); + tx_ring_space = pci_alloc_consistent(pdev, size, &tx_ring_dma); + if (tx_ring_space == NULL) + return -1; dev = init_etherdev(NULL, sizeof(struct speedo_private)); if (dev == NULL) { - printk(KERN_ERR PFX "Could not allocate ethernet device.\n"); - goto err_out_free_tx_ring; - } - if (dev->priv == NULL) { - printk(KERN_ERR PFX "Could not allocate ethernet device private info.\n"); - goto err_out_free_netdev; + printk(KERN_ERR "eepro100: Could not allocate ethernet device.\n"); + pci_free_consistent(pdev, size, tx_ring_space, tx_ring_dma); + return -1; } if (dev->mem_start > 0) @@ -596,21 +708,6 @@ else option = 0; - /* save power state b4 pci_enable_device overwrites it */ - pm = pci_find_capability(pdev, PCI_CAP_ID_PM); - if (pm) { - u16 pwr_command; - pci_read_config_word(pdev, pm + PCI_PM_CTRL, &pwr_command); - acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK; - } - - if (pci_enable_device (pdev)) { - printk(KERN_ERR PFX "Could not enable PCI device\n"); - goto err_out_free_netdev; - } - - pci_set_master (pdev); - /* Read the station address EEPROM before doing the reset. Nominally his should even be done before accepting the device, but then we wouldn't have a device name with which to report the error. @@ -655,22 +752,26 @@ if (eeprom[3] & 0x0100) product = "OEM i82557/i82558 10/100 Ethernet"; else - product = "Intel PCI EtherExpress Pro100"; + product = pdev->name; - printk(KERN_INFO "%s: %s at %#3lx, ", dev->name, product, ioaddr); + printk(KERN_INFO "%s: %s, ", dev->name, product); for (i = 0; i < 5; i++) printk("%2.2X:", dev->dev_addr[i]); - printk("%2.2X, IRQ %d.\n", dev->dev_addr[i], irq); + printk("%2.2X, ", dev->dev_addr[i]); +#ifdef USE_IO + printk("I/O at %#3lx, ", ioaddr); +#endif + printk("IRQ %d.\n", irq); -#if 1 +#if 1 || defined(kernel_bloat) /* OK, this is pure kernel bloat. I don't like it when other drivers waste non-pageable kernel space to emit similar messages, but I need them for bug reports. */ { const char *connectors[] = {" RJ45", " BNC", " AUI", " MII"}; /* The self-test results must be paragraph aligned. */ - volatile s32 *self_test_results = (volatile s32 *)tx_ring; + volatile s32 *self_test_results; int boguscnt = 16000; /* Timeout for set-test. */ if (eeprom[3] & 0x03) printk(KERN_INFO " Receiver lock-up bug exists -- enabling" @@ -704,7 +805,8 @@ ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ } - /* Perform a system self-test. Use the tx_ring consistent DMA mapping for it. */ + /* Perform a system self-test. */ + self_test_results = (s32*) ((((long) tx_ring_space) + 15) & ~0xf); self_test_results[0] = 0; self_test_results[1] = -1; outl(tx_ring_dma | PortSelfTest, ioaddr + SCBPort); @@ -734,7 +836,7 @@ outl(PortReset, ioaddr + SCBPort); /* Return the chip to its original power state. */ - pci_set_power_state (pdev, acpi_idle_state); + pci_set_power_state(pdev, acpi_idle_state); pdev->driver_data = dev; @@ -742,20 +844,18 @@ dev->irq = irq; sp = dev->priv; - sp->pdev = pdev; sp->acpi_pwr = acpi_idle_state; - sp->tx_ring = (struct TxFD *)tx_ring; + sp->tx_ring = tx_ring_space; sp->tx_ring_dma = tx_ring_dma; sp->lstats = (struct speedo_stats *)(sp->tx_ring + TX_RING_SIZE); - - sp->full_duplex = option >= 0 && (option & 0x10) ? 1 : 0; + sp->lstats_dma = TX_RING_ELEM_DMA(sp, TX_RING_SIZE); + sp->full_duplex = option >= 0 && (option & 0x10) ? 1 : 0; if (card_idx >= 0) { if (full_duplex[card_idx] >= 0) sp->full_duplex = full_duplex[card_idx]; } - sp->default_port = option >= 0 ? (option & 0x0f) : 0; sp->phy[0] = eeprom[6]; @@ -768,37 +868,15 @@ /* The Speedo-specific entries in the device structure. */ dev->open = &speedo_open; dev->hard_start_xmit = &speedo_start_xmit; - dev->tx_timeout = &speedo_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; + netif_set_tx_timeout(dev, &speedo_tx_timeout, TX_TIMEOUT); dev->stop = &speedo_close; dev->get_stats = &speedo_get_stats; dev->set_multicast_list = &set_rx_mode; dev->do_ioctl = &speedo_ioctl; return 0; - -err_out_free_netdev: - unregister_netdevice (dev); - kfree (dev); -err_out_free_tx_ring: - pci_free_consistent(pdev, TX_RING_SIZE * sizeof(struct TxFD) - + sizeof(struct speedo_stats), - tx_ring, tx_ring_dma); -err_out_iounmap: -#ifndef USE_IO - iounmap ((void *)ioaddr); -err_out_free_mmio_region: -#endif - release_mem_region (pci_resource_start (pdev, 0), - pci_resource_len (pdev, 0)); -err_out_free_pio_region: - release_region (pci_resource_start (pdev, 1), - pci_resource_len (pdev, 1)); -err_out_none: - return -ENODEV; } - - + /* Serial EEPROM section. A "bit" grungy, but we work our way through bit-by-bit :->. */ /* EEPROM_Ctrl bits. */ @@ -887,6 +965,7 @@ sp->last_cmd = 0; sp->tx_full = 0; spin_lock_init(&sp->lock); + sp->in_interrupt = 0; /* .. we can safely take handler calls during init. */ if (request_irq(dev->irq, &speedo_interrupt, SA_SHIRQ, dev->name, dev)) { @@ -896,9 +975,8 @@ dev->if_port = sp->default_port; -#if 0 - /* With some transceivers we must retrigger negotiation to reset - power-up errors. */ +#ifdef oh_no_you_dont_unless_you_honour_the_options_passed_in_to_us + /* Retrigger negotiation to reset previous errors. */ if ((sp->phy[0] & 0x8000) == 0) { int phy_addr = sp->phy[0] & 0x1f ; /* Use 0x3300 for restarting NWay, other values to force xcvr: @@ -918,16 +996,17 @@ speedo_init_rx_ring(dev); /* Fire up the hardware. */ + outw(SCBMaskAll, ioaddr + SCBCmd); speedo_resume(dev); + netdevice_start(dev); netif_start_queue(dev); /* Setup the chip and configure the multicast list. */ - sp->mc_setup_frm = NULL; - sp->mc_setup_frm_len = 0; - sp->mc_setup_busy = 0; - sp->rx_mode = -1; /* Invalid -> always reset the mode. */ + sp->mc_setup_head = NULL; + sp->mc_setup_tail = NULL; sp->flow_ctrl = sp->partner = 0; + sp->rx_mode = -1; /* Invalid -> always reset the mode. */ set_rx_mode(dev); if ((sp->phy[0] & 0x8000) == 0) sp->advertising = mdio_read(ioaddr, sp->phy[0] & 0x1f, 4); @@ -951,6 +1030,7 @@ /* No need to wait for the command unit to accept here. */ if ((sp->phy[0] & 0x8000) == 0) mdio_read(ioaddr, sp->phy[0] & 0x1f, 0); + return 0; } @@ -960,8 +1040,6 @@ struct speedo_private *sp = (struct speedo_private *)dev->priv; long ioaddr = dev->base_addr; - outw(SCBMaskAll, ioaddr + SCBCmd); - /* Start with a Tx threshold of 256 (0x..20.... 8 byte units). */ sp->tx_threshold = 0x01208000; @@ -974,42 +1052,45 @@ wait_for_cmd_done(ioaddr + SCBCmd); /* Load the statistics block and rx ring addresses. */ - outl(sp->tx_ring_dma + sizeof(struct TxFD) * TX_RING_SIZE, ioaddr + SCBPointer); + outl(sp->lstats_dma, ioaddr + SCBPointer); outb(CUStatsAddr, ioaddr + SCBCmd); sp->lstats->done_marker = 0; wait_for_cmd_done(ioaddr + SCBCmd); - outl(sp->rx_ring_dma[sp->cur_rx % RX_RING_SIZE], - ioaddr + SCBPointer); - outb(RxStart, ioaddr + SCBCmd); - wait_for_cmd_done(ioaddr + SCBCmd); + if (sp->rx_ringp[sp->cur_rx % RX_RING_SIZE] == NULL) { + if (speedo_debug > 2) + printk(KERN_DEBUG "%s: NULL cur_rx in speedo_resume().\n", + dev->name); + } else { + outl(sp->rx_ring_dma[sp->cur_rx % RX_RING_SIZE], + ioaddr + SCBPointer); + outb(RxStart, ioaddr + SCBCmd); + wait_for_cmd_done(ioaddr + SCBCmd); + } outb(CUDumpStats, ioaddr + SCBCmd); /* Fill the first command with our physical address. */ { - int entry = sp->cur_tx++ % TX_RING_SIZE; - struct descriptor *cur_cmd = (struct descriptor *)&sp->tx_ring[entry]; + struct descriptor *ias_cmd; + ias_cmd = + (struct descriptor *)&sp->tx_ring[sp->cur_tx++ % TX_RING_SIZE]; /* Avoid a bug(?!) here by marking the command already completed. */ - cur_cmd->cmd_status = cpu_to_le32((CmdSuspend | CmdIASetup) | 0xa000); - cur_cmd->link = - cpu_to_le32(sp->tx_ring_dma + (sp->cur_tx % TX_RING_SIZE) - * sizeof(struct TxFD)); - memcpy(cur_cmd->params, dev->dev_addr, 6); - if (sp->last_cmd) - clear_suspend(sp->last_cmd); - sp->last_cmd = cur_cmd; + ias_cmd->cmd_status = cpu_to_le32((CmdSuspend | CmdIASetup) | 0xa000); + ias_cmd->link = + cpu_to_le32(TX_RING_ELEM_DMA(sp, sp->cur_tx % TX_RING_SIZE)); + memcpy(ias_cmd->params, dev->dev_addr, 6); + sp->last_cmd = ias_cmd; } /* Start the chip's Tx process and unmask interrupts. */ wait_for_cmd_done(ioaddr + SCBCmd); - outl(sp->tx_ring_dma - + (sp->dirty_tx % TX_RING_SIZE) * sizeof(struct TxFD), + outl(cpu_to_le32(TX_RING_ELEM_DMA(sp, sp->dirty_tx % TX_RING_SIZE)), ioaddr + SCBPointer); - outw(CUStart, ioaddr + SCBCmd); - - netif_start_queue (dev); + /* We are not ACK-ing FCP and ER in the interrupt handler yet so they should + remain masked --Dragan */ + outw(CUStart | SCBMaskEarlyRx | SCBMaskFlowCtl, ioaddr + SCBCmd); } /* Media monitoring and control. */ @@ -1025,6 +1106,8 @@ int partner = mdio_read(ioaddr, phy_num, 5); if (partner != sp->partner) { int flow_ctrl = sp->advertising & partner & 0x0400 ? 1 : 0; + if (speedo_debug > 2) + printk(KERN_DEBUG "%s: Link status change.\n", dev->name); sp->partner = partner; if (flow_ctrl != sp->flow_ctrl) { sp->flow_ctrl = flow_ctrl; @@ -1034,12 +1117,11 @@ mdio_read(ioaddr, phy_num, 1); /* If link beat has returned... */ if (mdio_read(ioaddr, phy_num, 1) & 0x0004) - dev->flags |= IFF_RUNNING; + dev->flags |= IFF_RUNNING; else dev->flags &= ~IFF_RUNNING; } } - if (speedo_debug > 3) { printk(KERN_DEBUG "%s: Media control tick, status %4.4x.\n", dev->name, inw(ioaddr + SCBStatus)); @@ -1049,6 +1131,9 @@ /* We haven't received a packet in a Long Time. We might have been bitten by the receiver hang bug. This can be cleared by sending a set multicast list command. */ + if (speedo_debug > 2) + printk(KERN_DEBUG "%s: Sending a multicast list set command" + " from a timer routine.\n", dev->name); set_rx_mode(dev); } /* We must continue to monitor the media. */ @@ -1066,25 +1151,31 @@ /* Print a few items for debugging. */ if (speedo_debug > 0) { int i; - printk(KERN_DEBUG "%s: Tx ring dump, Tx queue %d / %d:\n", dev->name, + printk(KERN_DEBUG "%s: Tx ring dump, Tx queue %u / %u:\n", dev->name, sp->cur_tx, sp->dirty_tx); for (i = 0; i < TX_RING_SIZE; i++) - printk(KERN_DEBUG "%s: %c%c%d %8.8x.\n", dev->name, + printk(KERN_DEBUG "%s: %c%c%2d %8.8x.\n", dev->name, i == sp->dirty_tx % TX_RING_SIZE ? '*' : ' ', i == sp->cur_tx % TX_RING_SIZE ? '=' : ' ', i, sp->tx_ring[i].status); } - printk(KERN_DEBUG "%s:Printing Rx ring (next to receive into %d).\n", - dev->name, sp->cur_rx); + printk(KERN_DEBUG "%s: Printing Rx ring" + " (next to receive into %u, dirty index %u).\n", + dev->name, sp->cur_rx, sp->dirty_rx); for (i = 0; i < RX_RING_SIZE; i++) - printk(KERN_DEBUG " Rx ring entry %d %8.8x.\n", - i, (int)sp->rx_ringp[i]->status); + printk(KERN_DEBUG "%s: %c%c%c%2d %8.8x.\n", dev->name, + sp->rx_ringp[i] == sp->last_rxf ? 'l' : ' ', + i == sp->dirty_rx % RX_RING_SIZE ? '*' : ' ', + i == sp->cur_rx % RX_RING_SIZE ? '=' : ' ', + i, (sp->rx_ringp[i] != NULL) ? + (unsigned)sp->rx_ringp[i]->status : 0); for (i = 0; i < 16; i++) { + /* FIXME: what does it mean? --SAW */ if (i == 6) i = 21; - printk(KERN_DEBUG " PHY index %d register %d is %4.4x.\n", - phy_num, i, mdio_read(ioaddr, phy_num, i)); + printk(KERN_DEBUG "%s: PHY index %d register %d is %4.4x.\n", + dev->name, phy_num, i, mdio_read(ioaddr, phy_num, i)); } } @@ -1126,55 +1217,124 @@ sp->last_rxf = last_rxf; } +static void speedo_purge_tx(struct net_device *dev) +{ + struct speedo_private *sp = (struct speedo_private *)dev->priv; + int entry; + + while ((int)(sp->cur_tx - sp->dirty_tx) > 0) { + entry = sp->dirty_tx % TX_RING_SIZE; + if (sp->tx_skbuff[entry]) { + sp->stats.tx_errors++; + pci_unmap_single(sp->pdev, + le32_to_cpu(sp->tx_ring[entry].tx_buf_addr0), + sp->tx_skbuff[entry]->len, PCI_DMA_TODEVICE); + dev_kfree_skb_irq(sp->tx_skbuff[entry]); + sp->tx_skbuff[entry] = 0; + } + sp->dirty_tx++; + } + while (sp->mc_setup_head != NULL) { + struct speedo_mc_block *t; + if (speedo_debug > 1) + printk(KERN_DEBUG "%s: freeing mc frame.\n", dev->name); + pci_unmap_single(sp->pdev, sp->mc_setup_head->frame_dma, + sp->mc_setup_head->len, PCI_DMA_TODEVICE); + t = sp->mc_setup_head->next; + kfree(sp->mc_setup_head); + sp->mc_setup_head = t; + } + sp->mc_setup_tail = NULL; + sp->tx_full = 0; + netif_wake_queue(dev); +} + static void speedo_tx_timeout(struct net_device *dev) { struct speedo_private *sp = (struct speedo_private *)dev->priv; long ioaddr = dev->base_addr; int status = inw(ioaddr + SCBStatus); - - /* Trigger a stats dump to give time before the reset. */ - speedo_get_stats(dev); + unsigned long flags; printk(KERN_WARNING "%s: Transmit timed out: status %4.4x " " %4.4x at %d/%d command %8.8x.\n", dev->name, status, inw(ioaddr + SCBCmd), sp->dirty_tx, sp->cur_tx, sp->tx_ring[sp->dirty_tx % TX_RING_SIZE].status); + + /* Trigger a stats dump to give time before the reset. */ + speedo_get_stats(dev); + speedo_show_state(dev); +#if 0 if ((status & 0x00C0) != 0x0080 && (status & 0x003C) == 0x0010) { /* Only the command unit has stopped. */ printk(KERN_WARNING "%s: Trying to restart the transmitter...\n", dev->name); - outl(sp->tx_ring_dma - + (sp->dirty_tx % TX_RING_SIZE) * sizeof(struct TxFD), + outl(cpu_to_le32(TX_RING_ELEM_DMA(sp, dirty_tx % TX_RING_SIZE])), ioaddr + SCBPointer); outw(CUStart, ioaddr + SCBCmd); } else { +#else + { +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43) + start_bh_atomic(); + /* Ensure that timer routine doesn't run! */ + del_timer(&sp->timer); + end_bh_atomic(); +#else /* LINUX_VERSION_CODE */ +#ifdef __SMP__ + del_timer_sync(&sp->timer); +#else /* SMP */ + del_timer(&sp->timer); +#endif /* SMP */ +#endif /* LINUX_VERSION_CODE */ /* Reset the Tx and Rx units. */ outl(PortReset, ioaddr + SCBPort); - if (speedo_debug > 0) - speedo_show_state(dev); + /* We may get spurious interrupts here. But I don't think that they + may do much harm. 1999/12/09 SAW */ udelay(10); + /* Disable interrupts. */ + outw(SCBMaskAll, ioaddr + SCBCmd); + synchronize_irq(); + speedo_tx_buffer_gc(dev); + /* Free as much as possible. + It helps to recover from a hang because of out-of-memory. + It also simplifies speedo_resume() in case TX ring is full or + close-to-be full. */ + speedo_purge_tx(dev); + speedo_refill_rx_buffers(dev, 1); + spin_lock_irqsave(&sp->lock, flags); speedo_resume(dev); + sp->rx_mode = -1; + dev->trans_start = jiffies; + spin_unlock_irqrestore(&sp->lock, flags); + set_rx_mode(dev); /* it takes the spinlock itself --SAW */ + sp->timer.expires = RUN_AT(2*HZ); + add_timer(&sp->timer); } /* Reset the MII transceiver, suggested by Fred Young @ scalable.com. */ if ((sp->phy[0] & 0x8000) == 0) { int phy_addr = sp->phy[0] & 0x1f; + int advertising = mdio_read(ioaddr, phy_addr, 4); + int mii_bmcr = mdio_read(ioaddr, phy_addr, 0); mdio_write(ioaddr, phy_addr, 0, 0x0400); mdio_write(ioaddr, phy_addr, 1, 0x0000); mdio_write(ioaddr, phy_addr, 4, 0x0000); mdio_write(ioaddr, phy_addr, 0, 0x8000); #ifdef honor_default_port mdio_write(ioaddr, phy_addr, 0, mii_ctrl[dev->default_port & 7]); +#else + mdio_read(ioaddr, phy_addr, 0); + mdio_write(ioaddr, phy_addr, 0, mii_bmcr); + mdio_write(ioaddr, phy_addr, 4, advertising); #endif } - sp->stats.tx_errors++; - dev->trans_start = jiffies; - netif_start_queue (dev); + return; } - static int speedo_start_xmit(struct sk_buff *skb, struct net_device *dev) { @@ -1182,58 +1342,141 @@ long ioaddr = dev->base_addr; int entry; - /* Caution: the write order is important here, set the base address - with the "ownership" bits last. */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43) + if (test_bit(0, (void*)&dev->tbusy) != 0) { + int tickssofar = jiffies - dev->trans_start; + if (tickssofar < TX_TIMEOUT - 2) + return 1; + if (tickssofar < TX_TIMEOUT) { + /* Reap sent packets from the full Tx queue. */ + unsigned long flags; + spin_lock_irqsave(&sp->lock, flags); + wait_for_cmd_done(ioaddr + SCBCmd); + outw(SCBTriggerIntr, ioaddr + SCBCmd); + spin_unlock_irqrestore(&sp->lock, flags); + return 1; + } + speedo_tx_timeout(dev); + return 1; + } +#endif { /* Prevent interrupts from changing the Tx ring from underneath us. */ unsigned long flags; spin_lock_irqsave(&sp->lock, flags); + + /* Check if there are enough space. */ + if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) { + printk(KERN_ERR "%s: incorrect tbusy state, fixed.\n", dev->name); + netif_stop_queue(dev); + sp->tx_full = 1; + spin_unlock_irqrestore(&sp->lock, flags); + return 1; + } + /* Calculate the Tx descriptor entry. */ entry = sp->cur_tx++ % TX_RING_SIZE; sp->tx_skbuff[entry] = skb; - /* Todo: be a little more clever about setting the interrupt bit. */ sp->tx_ring[entry].status = cpu_to_le32(CmdSuspend | CmdTx | CmdTxFlex); + if (!(entry & ((TX_RING_SIZE>>2)-1))) + sp->tx_ring[entry].status |= cpu_to_le32(CmdIntr); sp->tx_ring[entry].link = - cpu_to_le32(sp->tx_ring_dma - + (sp->cur_tx % TX_RING_SIZE) - * sizeof(struct TxFD)); + cpu_to_le32(TX_RING_ELEM_DMA(sp, sp->cur_tx % TX_RING_SIZE)); sp->tx_ring[entry].tx_desc_addr = - cpu_to_le32(sp->tx_ring_dma - + ((long)&sp->tx_ring[entry].tx_buf_addr0 - - (long)sp->tx_ring)); + cpu_to_le32(TX_RING_ELEM_DMA(sp, sp->cur_tx % TX_RING_SIZE) + + TX_DESCR_BUF_OFFSET); /* The data region is always in one buffer descriptor. */ sp->tx_ring[entry].count = cpu_to_le32(sp->tx_threshold); sp->tx_ring[entry].tx_buf_addr0 = cpu_to_le32(pci_map_single(sp->pdev, skb->data, skb->len, PCI_DMA_TODEVICE)); sp->tx_ring[entry].tx_buf_size0 = cpu_to_le32(skb->len); - /* Todo: perhaps leave the interrupt bit set if the Tx queue is more - than half full. Argument against: we should be receiving packets - and scavenging the queue. Argument for: if so, it shouldn't - matter. */ /* Trigger the command unit resume. */ - { - struct descriptor *last_cmd = sp->last_cmd; - sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry]; - last_cmd->cmd_status &= cpu_to_le32(~(CmdSuspend | CmdIntr)); - } - if (sp->cur_tx - sp->dirty_tx >= TX_QUEUE_LIMIT) { + wait_for_cmd_done(ioaddr + SCBCmd); + clear_suspend(sp->last_cmd); + /* We want the time window between clearing suspend flag on the previous + command and resuming CU to be as small as possible. + Interrupts in between are very undesired. --SAW */ + outb(CUResume, ioaddr + SCBCmd); + sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry]; + + /* Leave room for set_rx_mode(). If there is no more space than reserved + for multicast filter mark the ring as full. */ + if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) { + netif_stop_queue(dev); sp->tx_full = 1; - netif_stop_queue (dev); } + spin_unlock_irqrestore(&sp->lock, flags); } - wait_for_cmd_done(ioaddr + SCBCmd); - outw(CUResume, ioaddr + SCBCmd); dev->trans_start = jiffies; - + return 0; } +static void speedo_tx_buffer_gc(struct net_device *dev) +{ + unsigned int dirty_tx; + struct speedo_private *sp = (struct speedo_private *)dev->priv; + + dirty_tx = sp->dirty_tx; + while ((int)(sp->cur_tx - dirty_tx) > 0) { + int entry = dirty_tx % TX_RING_SIZE; + int status = le32_to_cpu(sp->tx_ring[entry].status); + + if (speedo_debug > 5) + printk(KERN_DEBUG " scavenge candidate %d status %4.4x.\n", + entry, status); + if ((status & StatusComplete) == 0) + break; /* It still hasn't been processed. */ + if (status & TxUnderrun) + if (sp->tx_threshold < 0x01e08000) { + if (speedo_debug > 2) + printk(KERN_DEBUG "%s: TX underrun, threshold adjusted.\n", + dev->name); + sp->tx_threshold += 0x00040000; + } + /* Free the original skb. */ + if (sp->tx_skbuff[entry]) { + sp->stats.tx_packets++; /* Count only user packets. */ + sp->stats.tx_bytes += sp->tx_skbuff[entry]->len; + pci_unmap_single(sp->pdev, + le32_to_cpu(sp->tx_ring[entry].tx_buf_addr0), + sp->tx_skbuff[entry]->len, PCI_DMA_TODEVICE); + dev_kfree_skb_irq(sp->tx_skbuff[entry]); + sp->tx_skbuff[entry] = 0; + } + dirty_tx++; + } + + if (speedo_debug && (int)(sp->cur_tx - dirty_tx) > TX_RING_SIZE) { + printk(KERN_ERR "out-of-sync dirty pointer, %d vs. %d," + " full=%d.\n", + dirty_tx, sp->cur_tx, sp->tx_full); + dirty_tx += TX_RING_SIZE; + } + + while (sp->mc_setup_head != NULL + && (int)(dirty_tx - sp->mc_setup_head->tx - 1) > 0) { + struct speedo_mc_block *t; + if (speedo_debug > 1) + printk(KERN_DEBUG "%s: freeing mc frame.\n", dev->name); + pci_unmap_single(sp->pdev, sp->mc_setup_head->frame_dma, + sp->mc_setup_head->len, PCI_DMA_TODEVICE); + t = sp->mc_setup_head->next; + kfree(sp->mc_setup_head); + sp->mc_setup_head = t; + } + if (sp->mc_setup_head == NULL) + sp->mc_setup_tail = NULL; + + sp->dirty_tx = dirty_tx; +} + /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs) @@ -1253,11 +1496,21 @@ ioaddr = dev->base_addr; sp = (struct speedo_private *)dev->priv; - spin_lock (&sp->lock); +#ifndef final_version + /* A lock to prevent simultaneous entry on SMP machines. */ + if (test_and_set_bit(0, (void*)&sp->in_interrupt)) { + printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n", + dev->name); + sp->in_interrupt = 0; /* Avoid halting machine. */ + return; + } +#endif do { status = inw(ioaddr + SCBStatus); /* Acknowledge all of the current interrupt sources ASAP. */ + /* Will change from 0xfc00 to 0xff00 when we start handling + FCP and ER interrupts --Dragan */ outw(status & 0xfc00, ioaddr + SCBStatus); if (speedo_debug > 4) @@ -1267,90 +1520,194 @@ if ((status & 0xfc00) == 0) break; - if (status & 0x4000) /* Packet received. */ + /* Always check if all rx buffers are allocated. --SAW */ + speedo_refill_rx_buffers(dev, 0); + + if ((status & 0x5000) || /* Packet received, or Rx error. */ + (sp->rx_ring_state&(RrNoMem|RrPostponed)) == RrPostponed) + /* Need to gather the postponed packet. */ speedo_rx(dev); if (status & 0x1000) { - if ((status & 0x003c) == 0x0028) /* No more Rx buffers. */ - outw(RxResumeNoResources, ioaddr + SCBCmd); - else if ((status & 0x003c) == 0x0008) { /* No resources (why?!) */ - /* No idea of what went wrong. Restart the receiver. */ - outl(sp->rx_ring_dma[sp->cur_rx % RX_RING_SIZE], - ioaddr + SCBPointer); - outw(RxStart, ioaddr + SCBCmd); + spin_lock(&sp->lock); + if ((status & 0x003c) == 0x0028) { /* No more Rx buffers. */ + struct RxFD *rxf; + printk(KERN_WARNING "%s: card reports no RX buffers.\n", + dev->name); + rxf = sp->rx_ringp[sp->cur_rx % RX_RING_SIZE]; + if (rxf == NULL) { + if (speedo_debug > 2) + printk(KERN_DEBUG + "%s: NULL cur_rx in speedo_interrupt().\n", + dev->name); + sp->rx_ring_state |= RrNoMem|RrNoResources; + } else if (rxf == sp->last_rxf) { + if (speedo_debug > 2) + printk(KERN_DEBUG + "%s: cur_rx is last in speedo_interrupt().\n", + dev->name); + sp->rx_ring_state |= RrNoMem|RrNoResources; + } else + outb(RxResumeNoResources, ioaddr + SCBCmd); + } else if ((status & 0x003c) == 0x0008) { /* No resources. */ + struct RxFD *rxf; + printk(KERN_WARNING "%s: card reports no resources.\n", + dev->name); + rxf = sp->rx_ringp[sp->cur_rx % RX_RING_SIZE]; + if (rxf == NULL) { + if (speedo_debug > 2) + printk(KERN_DEBUG + "%s: NULL cur_rx in speedo_interrupt().\n", + dev->name); + sp->rx_ring_state |= RrNoMem|RrNoResources; + } else if (rxf == sp->last_rxf) { + if (speedo_debug > 2) + printk(KERN_DEBUG + "%s: cur_rx is last in speedo_interrupt().\n", + dev->name); + sp->rx_ring_state |= RrNoMem|RrNoResources; + } else { + /* Restart the receiver. */ + outl(sp->rx_ring_dma[sp->cur_rx % RX_RING_SIZE], + ioaddr + SCBPointer); + outb(RxStart, ioaddr + SCBCmd); + } } sp->stats.rx_errors++; + spin_unlock(&sp->lock); + } + + if ((sp->rx_ring_state&(RrNoMem|RrNoResources)) == RrNoResources) { + printk(KERN_WARNING + "%s: restart the receiver after a possible hang.\n", + dev->name); + spin_lock(&sp->lock); + /* Restart the receiver. + I'm not sure if it's always right to restart the receiver + here but I don't know another way to prevent receiver hangs. + 1999/12/25 SAW */ + outl(sp->rx_ring_dma[sp->cur_rx % RX_RING_SIZE], + ioaddr + SCBPointer); + outb(RxStart, ioaddr + SCBCmd); + sp->rx_ring_state &= ~RrNoResources; + spin_unlock(&sp->lock); } /* User interrupt, Command/Tx unit interrupt or CU not active. */ if (status & 0xA400) { - unsigned int dirty_tx; - - dirty_tx = sp->dirty_tx; - while (sp->cur_tx - dirty_tx > 0) { - int entry = dirty_tx % TX_RING_SIZE; - int status = le32_to_cpu(sp->tx_ring[entry].status); - - if (speedo_debug > 5) - printk(KERN_DEBUG " scavenge candidate %d status %4.4x.\n", - entry, status); - if ((status & StatusComplete) == 0) - break; /* It still hasn't been processed. */ - if (status & TxUnderrun) - if (sp->tx_threshold < 0x01e08000) - sp->tx_threshold += 0x00040000; - /* Free the original skb. */ - if (sp->tx_skbuff[entry]) { - sp->stats.tx_packets++; /* Count only user packets. */ - sp->stats.tx_bytes += sp->tx_skbuff[entry]->len; - pci_unmap_single(sp->pdev, - le32_to_cpu(sp->tx_ring[entry].tx_buf_addr0), - sp->tx_skbuff[entry]->len, PCI_DMA_TODEVICE); - dev_kfree_skb_irq(sp->tx_skbuff[entry]); - sp->tx_skbuff[entry] = 0; - } else if ((status & 0x70000) == CmdNOp) { - if (sp->mc_setup_busy) - pci_unmap_single(sp->pdev, - sp->mc_setup_dma, - sp->mc_setup_frm_len, - PCI_DMA_TODEVICE); - sp->mc_setup_busy = 0; - } - dirty_tx++; - } - -#ifndef final_version - if (sp->cur_tx - dirty_tx > TX_RING_SIZE) { - printk(KERN_ERR "out-of-sync dirty pointer, %d vs. %d," - " full=%d.\n", - dirty_tx, sp->cur_tx, sp->tx_full); - dirty_tx += TX_RING_SIZE; - } -#endif - - sp->dirty_tx = dirty_tx; + spin_lock(&sp->lock); + speedo_tx_buffer_gc(dev); if (sp->tx_full - && sp->cur_tx - dirty_tx < TX_QUEUE_LIMIT - 1) { - /* The ring is no longer full, clear tbusy. */ + && (int)(sp->cur_tx - sp->dirty_tx) < TX_QUEUE_UNFULL) { + /* The ring is no longer full. */ sp->tx_full = 0; - netif_wake_queue (dev); + netif_wake_queue(dev); /* Attention: under a spinlock. --SAW */ } + spin_unlock(&sp->lock); } - } while (--boguscnt > 0); - - if (boguscnt <= 0) { - printk(KERN_ERR "%s: Too much work at interrupt, status=0x%4.4x.\n", - dev->name, status); - /* Clear all interrupt sources. */ - outl(0xfc00, ioaddr + SCBStatus); - } + if (--boguscnt < 0) { + printk(KERN_ERR "%s: Too much work at interrupt, status=0x%4.4x.\n", + dev->name, status); + /* Clear all interrupt sources. */ + /* Will change from 0xfc00 to 0xff00 when we start handling + FCP and ER interrupts --Dragan */ + outl(0xfc00, ioaddr + SCBStatus); + break; + } + } while (1); if (speedo_debug > 3) printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n", dev->name, inw(ioaddr + SCBStatus)); - spin_unlock (&sp->lock); + clear_bit(0, (void*)&sp->in_interrupt); + return; +} + +static inline struct RxFD *speedo_rx_alloc(struct net_device *dev, int entry) +{ + struct speedo_private *sp = (struct speedo_private *)dev->priv; + struct RxFD *rxf; + struct sk_buff *skb; + /* Get a fresh skbuff to replace the consumed one. */ + skb = dev_alloc_skb(PKT_BUF_SZ + sizeof(struct RxFD)); + sp->rx_skbuff[entry] = skb; + if (skb == NULL) { + sp->rx_ringp[entry] = NULL; + return NULL; + } + rxf = sp->rx_ringp[entry] = (struct RxFD *)skb->tail; + sp->rx_ring_dma[entry] = + pci_map_single(sp->pdev, rxf, + PKT_BUF_SZ + sizeof(struct RxFD), PCI_DMA_FROMDEVICE); + skb->dev = dev; + skb_reserve(skb, sizeof(struct RxFD)); + rxf->rx_buf_addr = 0xffffffff; + return rxf; +} + +static inline void speedo_rx_link(struct net_device *dev, int entry, + struct RxFD *rxf, dma_addr_t rxf_dma) +{ + struct speedo_private *sp = (struct speedo_private *)dev->priv; + rxf->status = cpu_to_le32(0xC0000001); /* '1' for driver use only. */ + rxf->link = 0; /* None yet. */ + rxf->count = cpu_to_le32(PKT_BUF_SZ << 16); + sp->last_rxf->link = cpu_to_le32(rxf_dma); + sp->last_rxf->status &= cpu_to_le32(~0xC0000000); + sp->last_rxf = rxf; +} + +static int speedo_refill_rx_buf(struct net_device *dev, int force) +{ + struct speedo_private *sp = (struct speedo_private *)dev->priv; + int entry; + struct RxFD *rxf; + + entry = sp->dirty_rx % RX_RING_SIZE; + if (sp->rx_skbuff[entry] == NULL) { + rxf = speedo_rx_alloc(dev, entry); + if (rxf == NULL) { + unsigned int forw; + int forw_entry; + if (speedo_debug > 2 || !(sp->rx_ring_state & RrOOMReported)) { + printk(KERN_WARNING "%s: can't fill rx buffer (force %d)!\n", + dev->name, force); + speedo_show_state(dev); + sp->rx_ring_state |= RrOOMReported; + } + if (!force) + return -1; /* Better luck next time! */ + /* Borrow an skb from one of next entries. */ + for (forw = sp->dirty_rx + 1; forw != sp->cur_rx; forw++) + if (sp->rx_skbuff[forw % RX_RING_SIZE] != NULL) + break; + if (forw == sp->cur_rx) + return -1; + forw_entry = forw % RX_RING_SIZE; + sp->rx_skbuff[entry] = sp->rx_skbuff[forw_entry]; + sp->rx_skbuff[forw_entry] = NULL; + rxf = sp->rx_ringp[forw_entry]; + sp->rx_ringp[forw_entry] = NULL; + sp->rx_ringp[entry] = rxf; + } + } else { + rxf = sp->rx_ringp[entry]; + } + speedo_rx_link(dev, entry, rxf, sp->rx_ring_dma[entry]); + sp->dirty_rx++; + sp->rx_ring_state &= ~(RrNoMem|RrOOMReported); /* Mark the progress. */ + return 0; +} + +static void speedo_refill_rx_buffers(struct net_device *dev, int force) +{ + struct speedo_private *sp = (struct speedo_private *)dev->priv; + + /* Refill the RX ring. */ + while ((int)(sp->cur_rx - sp->dirty_rx) > 0 && + speedo_refill_rx_buf(dev, force) != -1); } static int @@ -1360,6 +1717,7 @@ int entry = sp->cur_rx % RX_RING_SIZE; int status; int rx_work_limit = sp->dirty_rx + RX_RING_SIZE - sp->cur_rx; + int alloc_ok = 1; if (speedo_debug > 4) printk(KERN_DEBUG " In speedo_rx().\n"); @@ -1370,6 +1728,19 @@ if (--rx_work_limit < 0) break; + + /* Check for a rare out-of-memory case: the current buffer is + the last buffer allocated in the RX ring. --SAW */ + if (sp->last_rxf == sp->rx_ringp[entry]) { + /* Postpone the packet. It'll be reaped at an interrupt when this + packet is no longer the last packet in the ring. */ + if (speedo_debug > 2) + printk(KERN_DEBUG "%s: RX packet postponed!\n", + dev->name); + sp->rx_ring_state |= RrPostponed; + break; + } + if (speedo_debug > 4) printk(KERN_DEBUG " speedo_rx() status %8.8x len %d.\n", status, pkt_len); @@ -1377,11 +1748,12 @@ if (status & RxErrTooBig) printk(KERN_ERR "%s: Ethernet frame overran the Rx buffer, " "status %8.8x!\n", dev->name, status); - else if ( ! (status & RxOK)) { + else if (! (status & RxOK)) { /* There was a fatal error. This *should* be impossible. */ sp->stats.rx_errors++; printk(KERN_ERR "%s: Anomalous event in speedo_rx(), " - "status %8.8x.\n", dev->name, status); + "status %8.8x.\n", + dev->name, status); } } else { struct sk_buff *skb; @@ -1394,7 +1766,7 @@ skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ /* 'skb_put()' points to the start of sk_buff data area. */ pci_dma_sync_single(sp->pdev, sp->rx_ring_dma[entry], - PKT_BUF_SZ + sizeof(struct RxFD), PCI_DMA_FROMDEVICE); + PKT_BUF_SZ + sizeof(struct RxFD), PCI_DMA_FROMDEVICE); #if 1 || USE_IP_CSUM /* Packet is in one chunk -- we can copy + cksum. */ eth_copy_and_sum(skb, sp->rx_skbuff[entry]->tail, pkt_len, 0); @@ -1416,7 +1788,7 @@ temp = skb_put(skb, pkt_len); sp->rx_ringp[entry] = NULL; pci_unmap_single(sp->pdev, sp->rx_ring_dma[entry], - PKT_BUF_SZ + sizeof(struct RxFD), PCI_DMA_FROMDEVICE); + PKT_BUF_SZ + sizeof(struct RxFD), PCI_DMA_FROMDEVICE); } skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); @@ -1424,40 +1796,18 @@ sp->stats.rx_bytes += pkt_len; } entry = (++sp->cur_rx) % RX_RING_SIZE; + sp->rx_ring_state &= ~RrPostponed; + /* Refill the recently taken buffers. + Do it one-by-one to handle traffic bursts better. */ + if (alloc_ok && speedo_refill_rx_buf(dev, 0) == -1) + alloc_ok = 0; } - /* Refill the Rx ring buffers. */ - for (; sp->cur_rx - sp->dirty_rx > 0; sp->dirty_rx++) { - struct RxFD *rxf; - entry = sp->dirty_rx % RX_RING_SIZE; - if (sp->rx_skbuff[entry] == NULL) { - struct sk_buff *skb; - /* Get a fresh skbuff to replace the consumed one. */ - skb = dev_alloc_skb(PKT_BUF_SZ + sizeof(struct RxFD)); - sp->rx_skbuff[entry] = skb; - if (skb == NULL) { - sp->rx_ringp[entry] = NULL; - break; /* Better luck next time! */ - } - rxf = sp->rx_ringp[entry] = (struct RxFD *)skb->tail; - sp->rx_ring_dma[entry] = - pci_map_single(sp->pdev, rxf, PKT_BUF_SZ - + sizeof(struct RxFD), PCI_DMA_FROMDEVICE); - skb->dev = dev; - skb_reserve(skb, sizeof(struct RxFD)); - rxf->rx_buf_addr = 0xffffffff; - } else { - rxf = sp->rx_ringp[entry]; - } - rxf->status = cpu_to_le32(0xC0000001); /* '1' for driver use only. */ - rxf->link = 0; /* None yet. */ - rxf->count = cpu_to_le32(PKT_BUF_SZ << 16); - sp->last_rxf->link = cpu_to_le32(sp->rx_ring_dma[entry]); - sp->last_rxf->status &= cpu_to_le32(~0xC0000000); - sp->last_rxf = rxf; - } + /* Try hard to refill the recently taken buffers. */ + speedo_refill_rx_buffers(dev, 1); sp->last_rx_time = jiffies; + return 0; } @@ -1468,6 +1818,7 @@ struct speedo_private *sp = (struct speedo_private *)dev->priv; int i; + netdevice_stop(dev); netif_stop_queue(dev); if (speedo_debug > 1) @@ -1477,13 +1828,16 @@ /* Shut off the media monitoring timer. */ del_timer(&sp->timer); - /* Disable interrupts, and stop the chip's Rx process. */ - outw(SCBMaskAll, ioaddr + SCBCmd); - outw(SCBMaskAll | RxAbort, ioaddr + SCBCmd); + /* Shutting down the chip nicely fails to disable flow control. So.. */ + outl(PortPartialReset, ioaddr + SCBPort); free_irq(dev->irq, dev); - /* Free all the skbuffs in the Rx and Tx queues. */ + /* Print a few items for debugging. */ + if (speedo_debug > 3) + speedo_show_state(dev); + + /* Free all the skbuffs in the Rx and Tx queues. */ for (i = 0; i < RX_RING_SIZE; i++) { struct sk_buff *skb = sp->rx_skbuff[i]; sp->rx_skbuff[i] = 0; @@ -1499,7 +1853,6 @@ for (i = 0; i < TX_RING_SIZE; i++) { struct sk_buff *skb = sp->tx_skbuff[i]; sp->tx_skbuff[i] = 0; - /* Clear the Tx descriptors. */ if (skb) { pci_unmap_single(sp->pdev, @@ -1508,17 +1861,19 @@ dev_kfree_skb(skb); } } - if (sp->mc_setup_frm) { - kfree(sp->mc_setup_frm); - sp->mc_setup_frm_len = 0; - } - /* Print a few items for debugging. */ - if (speedo_debug > 3) - speedo_show_state(dev); + /* Free multicast setting blocks. */ + for (i = 0; sp->mc_setup_head != NULL; i++) { + struct speedo_mc_block *t; + t = sp->mc_setup_head->next; + kfree(sp->mc_setup_head); + sp->mc_setup_head = t; + } + sp->mc_setup_tail = NULL; + if (speedo_debug > 0) + printk(KERN_DEBUG "%s: %d multicast blocks dropped.\n", dev->name, i); - /* Alt: acpi_set_pwr_state(pci_bus, pci_devfn, sp->acpi_pwr); */ - pci_set_power_state (sp->pdev, 2); + pci_set_power_state(sp->pdev, 2); MOD_DEC_USE_COUNT; @@ -1558,8 +1913,13 @@ sp->stats.rx_length_errors += le32_to_cpu(sp->lstats->rx_runt_errs); sp->lstats->done_marker = 0x0000; if (netif_running(dev)) { + unsigned long flags; + /* Take a spinlock to make wait_for_cmd_done and sending the + * command atomic. --SAW */ + spin_lock_irqsave(&sp->lock, flags); wait_for_cmd_done(ioaddr + SCBCmd); - outw(CUDumpStats, ioaddr + SCBCmd); + outb(CUDumpStats, ioaddr + SCBCmd); + spin_unlock_irqrestore(&sp->lock, flags); } } return &sp->stats; @@ -1577,9 +1937,11 @@ case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */ data[0] = phy; case SIOCDEVPRIVATE+1: /* Read the specified MII register. */ - saved_acpi = pci_set_power_state (sp->pdev, 0); - data[3] = mdio_read (ioaddr, data[0], data[1]); - pci_set_power_state (sp->pdev, saved_acpi); + /* FIXME: these operations probably need to be serialized with MDIO + access from the timer routine and timeout handler. 2000/03/08 SAW */ + saved_acpi = pci_set_power_state(sp->pdev, 0); + data[3] = mdio_read(ioaddr, data[0], data[1]); + pci_set_power_state(sp->pdev, saved_acpi); return 0; case SIOCDEVPRIVATE+2: /* Write the specified MII register */ if (!capable(CAP_NET_ADMIN)) @@ -1619,9 +1981,13 @@ } else new_rx_mode = 0; - if (sp->cur_tx - sp->dirty_tx >= TX_RING_SIZE - 1) { - /* The Tx ring is full -- don't add anything! Presumably the new mode - is in config_cmd_data and will be added anyway. */ + if (speedo_debug > 3) + printk(KERN_DEBUG "%s: set_rx_mode %d -> %d\n", dev->name, + sp->rx_mode, new_rx_mode); + + if ((int)(sp->cur_tx - sp->dirty_tx) > TX_RING_SIZE - TX_MULTICAST_SIZE) { + /* The Tx ring is full -- don't add anything! Hope the mode will be + * set again later. */ sp->rx_mode = -1; return; } @@ -1637,8 +2003,7 @@ sp->tx_skbuff[entry] = 0; /* Redundant. */ sp->tx_ring[entry].status = cpu_to_le32(CmdSuspend | CmdConfigure); sp->tx_ring[entry].link = - cpu_to_le32(sp->tx_ring_dma + ((entry + 1) % TX_RING_SIZE) - * sizeof(struct TxFD)); + cpu_to_le32(TX_RING_ELEM_DMA(sp, (entry + 1) % TX_RING_SIZE)); config_cmd_data = (void *)&sp->tx_ring[entry].tx_desc_addr; /* Construct a full CmdConfig frame. */ memcpy(config_cmd_data, i82558_config_cmd, sizeof(i82558_config_cmd)); @@ -1646,7 +2011,10 @@ config_cmd_data[4] = rxdmacount; config_cmd_data[5] = txdmacount + 0x80; config_cmd_data[15] |= (new_rx_mode & 2) ? 1 : 0; - config_cmd_data[19] = sp->flow_ctrl ? 0xBD : 0x80; + /* 0x80 doesn't disable FC 0x84 does. + Disable Flow control since we are not ACK-ing any FC interrupts + for now. --Dragan */ + config_cmd_data[19] = 0x84; config_cmd_data[19] |= sp->full_duplex ? 0x40 : 0; config_cmd_data[21] = (new_rx_mode & 1) ? 0x0D : 0x05; if (sp->phy[0] & 0x8000) { /* Use the AUI port instead. */ @@ -1656,7 +2024,11 @@ /* Trigger the command unit resume. */ wait_for_cmd_done(ioaddr + SCBCmd); clear_suspend(last_cmd); - outw(CUResume, ioaddr + SCBCmd); + outb(CUResume, ioaddr + SCBCmd); + if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) { + netif_stop_queue(dev); + sp->tx_full = 1; + } spin_unlock_irqrestore(&sp->lock, flags); } @@ -1674,8 +2046,7 @@ sp->tx_skbuff[entry] = 0; sp->tx_ring[entry].status = cpu_to_le32(CmdSuspend | CmdMulticastList); sp->tx_ring[entry].link = - cpu_to_le32(sp->tx_ring_dma + ((entry + 1) % TX_RING_SIZE) - * sizeof(struct TxFD)); + cpu_to_le32(TX_RING_ELEM_DMA(sp, (entry + 1) % TX_RING_SIZE)); sp->tx_ring[entry].tx_desc_addr = 0; /* Really MC list count. */ setup_params = (u16 *)&sp->tx_ring[entry].tx_desc_addr; *setup_params++ = cpu_to_le16(dev->mc_count*6); @@ -1691,40 +2062,39 @@ wait_for_cmd_done(ioaddr + SCBCmd); clear_suspend(last_cmd); /* Immediately trigger the command unit resume. */ - outw(CUResume, ioaddr + SCBCmd); + outb(CUResume, ioaddr + SCBCmd); + + if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) { + netif_stop_queue(dev); + sp->tx_full = 1; + } spin_unlock_irqrestore(&sp->lock, flags); } else if (new_rx_mode == 0) { struct dev_mc_list *mclist; u16 *setup_params, *eaddrs; - struct descriptor *mc_setup_frm = sp->mc_setup_frm; + struct speedo_mc_block *mc_blk; + struct descriptor *mc_setup_frm; int i; - /* If we are busy, someone might be quickly adding to the MC list. - Try again later when the list updates stop. */ - if (sp->mc_setup_busy) { - sp->rx_mode = -1; + mc_blk = kmalloc(sizeof(*mc_blk) + 2 + multicast_filter_limit*6, + GFP_ATOMIC); + if (mc_blk == NULL) { + printk(KERN_ERR "%s: Failed to allocate a setup frame.\n", + dev->name); + sp->rx_mode = -1; /* We failed, try again. */ return; } - if (sp->mc_setup_frm_len < 10 + dev->mc_count*6 - || sp->mc_setup_frm == NULL) { - /* Allocate a full setup frame, 10bytes + . */ - if (sp->mc_setup_frm) - kfree(sp->mc_setup_frm); - sp->mc_setup_frm_len = 10 + multicast_filter_limit*6; - sp->mc_setup_frm = kmalloc(sp->mc_setup_frm_len, GFP_ATOMIC); - if (sp->mc_setup_frm == NULL) { - printk(KERN_ERR "%s: Failed to allocate a setup frame.\n", - dev->name); - sp->rx_mode = -1; /* We failed, try again. */ - return; - } - } - mc_setup_frm = sp->mc_setup_frm; + mc_blk->next = NULL; + mc_blk->len = 2 + multicast_filter_limit*6; + mc_blk->frame_dma = + pci_map_single(sp->pdev, &mc_blk->frame, mc_blk->len, + PCI_DMA_TODEVICE); + mc_setup_frm = &mc_blk->frame; + /* Fill the setup frame. */ if (speedo_debug > 1) - printk(KERN_DEBUG "%s: Constructing a setup frame at %p, " - "%d bytes.\n", - dev->name, sp->mc_setup_frm, sp->mc_setup_frm_len); + printk(KERN_DEBUG "%s: Constructing a setup frame at %p.\n", + dev->name, mc_setup_frm); mc_setup_frm->cmd_status = cpu_to_le32(CmdSuspend | CmdIntr | CmdMulticastList); /* Link set below. */ @@ -1741,27 +2111,38 @@ /* Disable interrupts while playing with the Tx Cmd list. */ spin_lock_irqsave(&sp->lock, flags); + + if (sp->mc_setup_tail) + sp->mc_setup_tail->next = mc_blk; + else + sp->mc_setup_head = mc_blk; + sp->mc_setup_tail = mc_blk; + mc_blk->tx = sp->cur_tx; + entry = sp->cur_tx++ % TX_RING_SIZE; last_cmd = sp->last_cmd; sp->last_cmd = mc_setup_frm; - sp->mc_setup_busy = 1; /* Change the command to a NoOp, pointing to the CmdMulti command. */ sp->tx_skbuff[entry] = 0; sp->tx_ring[entry].status = cpu_to_le32(CmdNOp); - sp->mc_setup_dma = pci_map_single(sp->pdev, mc_setup_frm, sp->mc_setup_frm_len, PCI_DMA_TODEVICE); - sp->tx_ring[entry].link = cpu_to_le32(sp->mc_setup_dma); + sp->tx_ring[entry].link = cpu_to_le32(mc_blk->frame_dma); /* Set the link in the setup frame. */ mc_setup_frm->link = - cpu_to_le32(sp->tx_ring_dma + ((entry + 1) % TX_RING_SIZE) - * sizeof(struct TxFD)); + cpu_to_le32(TX_RING_ELEM_DMA(sp, (entry + 1) % TX_RING_SIZE)); wait_for_cmd_done(ioaddr + SCBCmd); clear_suspend(last_cmd); /* Immediately trigger the command unit resume. */ - outw(CUResume, ioaddr + SCBCmd); + outb(CUResume, ioaddr + SCBCmd); + + if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) { + netif_stop_queue(dev); + sp->tx_full = 1; + } spin_unlock_irqrestore(&sp->lock, flags); + if (speedo_debug > 5) printk(" CmdMCSetup frame length %d in entry %d.\n", dev->mc_count, entry); @@ -1769,9 +2150,8 @@ sp->rx_mode = new_rx_mode; } - - -static void eepro100_suspend (struct pci_dev *pdev) + +static void eepro100_suspend(struct pci_dev *pdev) { struct net_device *dev = pdev->driver_data; long ioaddr = dev->base_addr; @@ -1782,54 +2162,58 @@ /* XXX call pci_set_power_state ()? */ } - -static void eepro100_resume (struct pci_dev *pdev) +static void eepro100_resume(struct pci_dev *pdev) { struct net_device *dev = pdev->driver_data; - struct speedo_private *np = (struct speedo_private *)dev->priv; + struct speedo_private *sp = (struct speedo_private *)dev->priv; + long ioaddr = dev->base_addr; - netif_device_attach(dev); + /* I'm absolutely uncertain if this part of code may work. + The problems are: + - correct hardware reinitialization; + - correct driver behavior between different steps of the + reinitialization; + - serialization with other driver calls. + 2000/03/08 SAW */ + outw(SCBMaskAll, ioaddr + SCBCmd); speedo_resume(dev); - np->rx_mode = -1; - np->flow_ctrl = np->partner = 0; + netif_device_attach(dev); + sp->rx_mode = -1; + sp->flow_ctrl = sp->partner = 0; set_rx_mode(dev); } - static void __devexit eepro100_remove_one (struct pci_dev *pdev) { struct net_device *dev = pdev->driver_data; struct speedo_private *sp = (struct speedo_private *)dev->priv; - unregister_netdev (dev); + unregister_netdev(dev); - release_region (pci_resource_start (pdev, 1), - pci_resource_len (pdev, 1)); - release_mem_region (pci_resource_start (pdev, 0), - pci_resource_len (pdev, 0)); + release_region(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1)); + release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); #ifndef USE_IO - iounmap ((char *) dev->base_addr); + iounmap((char *)dev->base_addr); #endif pci_free_consistent(pdev, TX_RING_SIZE * sizeof(struct TxFD) - + sizeof(struct speedo_stats), - sp->tx_ring, sp->tx_ring_dma); - - kfree (dev); + + sizeof(struct speedo_stats), + sp->tx_ring, sp->tx_ring_dma); + kfree(dev); } - - + static struct pci_device_id eepro100_pci_tbl[] __devinitdata = { { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82557, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82559ER, + PCI_ANY_ID, PCI_ANY_ID, }, { 0,}, }; -MODULE_DEVICE_TABLE (pci, eepro100_pci_tbl); - +MODULE_DEVICE_TABLE(pci, eepro100_pci_tbl); static struct pci_driver eepro100_driver = { - name: EEPRO100_MODULE_NAME, + name: "eepro100", id_table: eepro100_pci_tbl, probe: eepro100_init_one, remove: eepro100_remove_one, @@ -1837,30 +2221,44 @@ resume: eepro100_resume, }; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,48) +static int pci_module_init(struct pci_driver *pdev) +{ + int rc; + + rc = pci_register_driver(pdev); + if (rc <= 0) { + printk(KERN_INFO "%s: No cards found, driver not installed.\n", + pdev->name); + pci_unregister_driver(pdev); + return -ENODEV; + } + return 0; +} +#endif static int __init eepro100_init_module(void) { + if (debug >= 0 && speedo_debug != debug) + printk(KERN_INFO "eepro100.c: Debug level is %d.\n", debug); if (debug >= 0) speedo_debug = debug; - return pci_module_init (&eepro100_driver); + return pci_module_init(&eepro100_driver); } - static void __exit eepro100_cleanup_module(void) { - pci_unregister_driver (&eepro100_driver); + pci_unregister_driver(&eepro100_driver); } - module_init(eepro100_init_module); module_exit(eepro100_cleanup_module); - + /* * Local variables: - * compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c eepro100.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS` `[ -f ./pci-netif.h ] && echo -DHAS_PCI_NETIF`" - * SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c eepro100.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`" - * simple-compile-command: "gcc -DMODULE -D__KERNEL__ -O6 -c eepro100.c" + * compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c eepro100.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`" + * SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c eepro100.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`" * c-indent-level: 4 * c-basic-offset: 4 * tab-width: 4 diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/net/loopback.c linux/drivers/net/loopback.c --- v2.3.99-pre3/linux/drivers/net/loopback.c Thu Feb 10 17:11:10 2000 +++ linux/drivers/net/loopback.c Mon Mar 27 10:35:56 2000 @@ -52,7 +52,7 @@ #include /* For the statistics structure. */ #include /* For ARPHRD_ETHER */ -#define LOOPBACK_MTU (PAGE_SIZE - 172) +#define LOOPBACK_OVERHEAD (128 + MAX_HEADER + 16 + 16) /* * The higher levels take care of making this non-reentrant (it's @@ -63,13 +63,6 @@ struct net_device_stats *stats = (struct net_device_stats *)dev->priv; /* - * Take this out if the debug says its ok - */ - - if (skb == NULL || dev == NULL) - printk(KERN_DEBUG "loopback fed NULL data - splat\n"); - - /* * Optimise so buffers with skb->free=1 are not copied but * instead are lobbed from tx queue to rx queue */ @@ -110,7 +103,7 @@ /* Initialize the rest of the LOOPBACK device. */ int __init loopback_init(struct net_device *dev) { - dev->mtu = LOOPBACK_MTU; + dev->mtu = PAGE_SIZE - LOOPBACK_OVERHEAD; dev->hard_start_xmit = loopback_xmit; dev->hard_header = eth_header; dev->hard_header_cache = eth_header_cache; @@ -126,6 +119,9 @@ return -ENOMEM; memset(dev->priv, 0, sizeof(struct net_device_stats)); dev->get_stats = get_stats; + + if (num_physpages >= ((128*1024*1024)>>PAGE_SHIFT)) + dev->mtu = 4096*4 - LOOPBACK_OVERHEAD; /* * Fill in the generic fields of the device structure. diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/net/pcmcia/Config.in linux/drivers/net/pcmcia/Config.in --- v2.3.99-pre3/linux/drivers/net/pcmcia/Config.in Mon Mar 27 08:08:26 2000 +++ linux/drivers/net/pcmcia/Config.in Sun Apr 2 15:38:53 2000 @@ -15,6 +15,7 @@ dep_tristate ' SMC 91Cxx PCMCIA support' CONFIG_PCMCIA_SMC91C92 $CONFIG_PCMCIA dep_tristate ' Xircom 16-bit PCMCIA support' CONFIG_PCMCIA_XIRC2PS $CONFIG_PCMCIA dep_tristate ' COM20020 ARCnet PCMCIA support' CONFIG_ARCNET_COM20020_CS $CONFIG_ARCNET_COM20020 $CONFIG_ARCNET $CONFIG_PCMCIA + dep_tristate ' IBM PCMCIA tokenring adapter support' CONFIG_PCMCIA_IBMTR $CONFIG_PCMCIA_IBMTR $CONFIG_TR $CONFIG_PCMCIA if [ "$CONFIG_CARDBUS" = "y" ]; then dep_tristate ' 3Com 3c575 CardBus support' CONFIG_PCMCIA_3C575 m diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/net/pcmcia/Makefile linux/drivers/net/pcmcia/Makefile --- v2.3.99-pre3/linux/drivers/net/pcmcia/Makefile Mon Mar 27 08:08:26 2000 +++ linux/drivers/net/pcmcia/Makefile Sun Apr 2 15:38:53 2000 @@ -39,9 +39,18 @@ obj-$(CONFIG_PCMCIA_3C575) += 3c575_cb.o obj-$(CONFIG_PCMCIA_XIRTULIP) += xircom_tulip_cb.o +obj-$(CONFIG_PCMCIA_IBMTR) += ibmtr_cs.o + O_OBJS := $(filter-out $(export-objs), $(obj-y)) OX_OBJS := $(filter $(export-objs), $(obj-y)) M_OBJS := $(filter-out $(export-objs), $(obj-m)) MX_OBJS := $(filter $(export-objs), $(obj-m)) include $(TOPDIR)/Rules.make + +.ibmtr.o: ../tokenring/ibmtr.c + $(CC) $(CFLAGS) -D__NO_VERSION__ -DPCMCIA -c -o $@ ../tokenring/ibmtr.c + +ibmtr_cs.o: .ibmtr.o ibmtr_cs.c + $(CC) $(CFLAGS) -DPCMCIA -c -o .$@ ibmtr_cs.c + $(LD) -r -o $@ .$@ .ibmtr.o diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/net/pcmcia/ibmtr_cs.c linux/drivers/net/pcmcia/ibmtr_cs.c --- v2.3.99-pre3/linux/drivers/net/pcmcia/ibmtr_cs.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/pcmcia/ibmtr_cs.c Sun Apr 2 15:38:53 2000 @@ -0,0 +1,635 @@ +/*====================================================================== + + A PCMCIA token-ring driver for IBM-based cards + + This driver supports the IBM PCMCIA Token-Ring Card. + Written by Steve Kipisz, kipisz@vnet.ibm.com or + bungy@ibm.net + + Written 1995,1996. + + This code is based on pcnet_cs.c from David Hinds. + + V2.2.0 February 1999 - Mike Phillips phillim@amtrak.com + + Linux V2.2.x presented significant changes to the underlying + ibmtr.c code. Mainly the code became a lot more organized and + modular. + + This caused the old PCMCIA Token Ring driver to give up and go + home early. Instead of just patching the old code to make it + work, the PCMCIA code has been streamlined, updated and possibly + improved. + + This code now only contains code required for the Card Services. + All we do here is set the card up enough so that the real ibmtr.c + driver can find it and work with it properly. + + i.e. We set up the io port, irq, mmio memory and shared ram memory. + This enables ibmtr_probe in ibmtr.c to find the card and configure it + as though it was a normal ISA and/or PnP card. + + There is some confusion with the difference between available shared + ram and the amount actually reserved from memory. ibmtr.c sets up + several offsets depending upon the actual on-board memory, not the + reserved memory. We need to get around this to allow the cards to + work with other cards in restricted memory space. Therefore the + pcmcia_reality_check function. + + TODO + - Write the suspend / resume functions. + - Fix Kernel Oops when removing card before ifconfig down + + CHANGES + + v2.2.5 April 1999 Mike Phillips (phillim@amtrak.com) + Obscure bug fix, required changed to ibmtr.c not ibmtr_cs.c + + v2.2.7 May 1999 Mike Phillips (phillim@amtrak.com) + Updated to version 2.2.7 to match the first version of the kernel + that the modification to ibmtr.c were incorporated into. + + +======================================================================*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#define PCMCIA_DEBUG 10 +#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 = +"ibmtr_cs.c 1.10 1996/01/06 05:19:00 (Steve Kipisz)\n" +" 2.2.7 1999/05/03 12:00:00 (Mike Phillips)\n" ; +#else +#define DEBUG(n, args...) +#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 }; + +/* MMIO base address */ +static u_long mmiobase = 0; + +/* SRAM base address */ +static u_long srambase = 0; + +/* SRAM size 8,16,32,64 */ +static u_long sramsize = 16; + +/* Ringspeed 4,16 */ +static int ringspeed = 16; + +MODULE_PARM(irq_mask, "i"); +MODULE_PARM(irq_list, "1-4i"); +MODULE_PARM(mmiobase, "i"); +MODULE_PARM(srambase, "i"); +MODULE_PARM(sramsize, "i"); +MODULE_PARM(ringspeed, "i"); + +/*====================================================================*/ + +static void ibmtr_config(dev_link_t *link); +static void ibmtr_hw_setup(struct net_device *dev); +static void ibmtr_release(u_long arg); +static int ibmtr_event(event_t event, int priority, + event_callback_args_t *args); + +static dev_info_t dev_info = "ibmtr_cs"; + +static dev_link_t *ibmtr_attach(void); +static void ibmtr_detach(dev_link_t *); + +static dev_link_t *dev_list = NULL; + +extern int ibmtr_probe(struct net_device *dev); +unsigned char pcmcia_reality_check(unsigned char gss); + +extern int trdev_init(struct net_device *dev); +extern void tok_interrupt(int irq, struct pt_regs *regs); +extern int tok_init_card(struct net_device *dev); +extern unsigned char get_sram_size(struct tok_info *ti); + +/*====================================================================*/ + +typedef struct ibmtr_dev_t { + dev_link_t link; + struct net_device *dev; /* Changed for 2.2.0 */ + dev_node_t node; + window_handle_t sram_win_handle; + struct tok_info ti; +} ibmtr_dev_t; + +/*====================================================================== + + This bit of code is used to avoid unregistering network devices + at inappropriate times. 2.2 and later kernels are fairly picky + about when this can happen. + +======================================================================*/ + +static void flush_stale_links(void) +{ + dev_link_t *link, *next; + for (link = dev_list; link; link = next) { + next = link->next; + if (link->state & DEV_STALE_LINK) + ibmtr_detach(link); + } +} + +/*====================================================================*/ + +static void cs_error(client_handle_t handle, int func, int ret) +{ + error_info_t err = { func, ret }; + CardServices(ReportError, handle, &err); +} + +/*====================================================================== + + ibmtr_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 *ibmtr_attach(void) +{ + ibmtr_dev_t *info; + dev_link_t *link; + struct net_device *dev; + client_reg_t client_reg; + int i, ret; + + DEBUG(0, "ibmtr_attach()\n"); + flush_stale_links(); + + /* Create new token-ring 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 = &ibmtr_release; + link->release.data = (u_long)link; + link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + link->io.NumPorts1 = 4; + link->io.IOAddrLines = 16; + link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; + 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->irq.Handler = &tok_interrupt; + link->conf.Attributes = CONF_ENABLE_IRQ; + link->conf.Vcc = 50; + link->conf.IntType = INT_MEMORY_AND_IO; + link->conf.Present = PRESENT_OPTION; + + dev = init_trdev(NULL,0); + dev->priv = &info->ti; + link->irq.Instance = info->dev = dev; + + if (dev == NULL) { + ibmtr_detach(link); + return NULL; + } + + dev->init = &ibmtr_probe; + +#if 0 + dev->tbusy = 1; +#endif + + /* 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 = &ibmtr_event; + client_reg.Version = 0x0210; + client_reg.event_callback_args.client_data = link; + ret = CardServices(RegisterClient, &link->handle, &client_reg); + if (ret != 0) { + cs_error(link->handle, RegisterClient, ret); + ibmtr_detach(link); + return NULL; + } + + return link; +} /* ibmtr_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 ibmtr_detach(dev_link_t *link) +{ + struct ibmtr_dev_t *info = link->priv; + dev_link_t **linkp; + struct net_device *dev; + long flags; + + + DEBUG(0, "ibmtr_detach(0x%p)\n", link); + + /* Locate device structure */ + for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) + if (*linkp == link) break; + if (*linkp == NULL) + return; + + dev = info->dev; + + save_flags(flags); + cli(); + { + struct tok_info *ti = (struct tok_info *)dev->priv; + if (ti->tr_timer.next) del_timer(&(ti->tr_timer)); + } + if (link->state & DEV_RELEASE_PENDING) { + del_timer(&link->release); + link->state &= ~DEV_RELEASE_PENDING; + } + restore_flags(flags); + + if (link->state & DEV_CONFIG) { + ibmtr_release((u_long)link); + if (link->state & DEV_STALE_CONFIG) { + link->state |= DEV_STALE_LINK; + return; + } + } + + if (link->handle) + CardServices(DeregisterClient, link->handle); + + /* Unlink device structure, free bits */ + *linkp = link->next; + if (link->dev) + unregister_trdev(info->dev); + kfree(info); + +} /* ibmtr_detach */ + +/*====================================================================== + + ibmtr_config() is scheduled to run after a CARD_INSERTION event + is received, to configure the PCMCIA socket, and to make the + token-ring device available to the system. + +======================================================================*/ + +#define CS_CHECK(fn, args...) \ +while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed + +static void ibmtr_config(dev_link_t *link) +{ + client_handle_t handle = link->handle; + ibmtr_dev_t *info = link->priv; + struct net_device *dev = info->dev; + struct tok_info *ti = dev->priv; + tuple_t tuple; + cisparse_t parse; + win_req_t req; + memreq_t mem; + int i, last_ret, last_fn; + u_char buf[64]; + unsigned char Shared_Ram_Base; + + DEBUG(0, "ibmtr_config(0x%p)\n", link); + + tuple.Attributes = 0; + tuple.TupleData = buf; + tuple.TupleDataMax = 64; + tuple.TupleOffset = 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; + + /* Configure card */ + link->state |= DEV_CONFIG; + + link->conf.ConfigIndex = 0x61; + + /* Determine if this is PRIMARY or ALTERNATE. */ + + /* Try PRIMARY card at 0xA20-0xA23 */ + link->io.BasePort1 = 0xA20; + i = CardServices(RequestIO, link->handle, &link->io); + if (i == CS_SUCCESS) { + memcpy(info->node.dev_name, "tr0\0", 4); + } else { + /* Couldn't get 0xA20-0xA23. Try ALTERNATE at 0xA24-0xA27. */ + link->io.BasePort1 = 0xA24; + CS_CHECK(RequestIO, link->handle, &link->io); + memcpy(info->node.dev_name, "tr1\0", 4); + } + dev->base_addr = link->io.BasePort1; + + CS_CHECK(RequestIRQ, link->handle, &link->irq); + dev->irq = link->irq.AssignedIRQ; + ti->irq = link->irq.AssignedIRQ; + ti->global_int_enable=GLOBAL_INT_ENABLE+((dev->irq==9) ? 2 : dev->irq); + + /* Allocate the MMIO memory window */ + req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE; + req.Attributes |= WIN_USE_WAIT|WIN_STRICT_ALIGN; + req.Base = mmiobase; + req.Size = 0x2000; + req.AccessSpeed = 250; + link->win = (window_handle_t) link->handle; + CS_CHECK(RequestWindow, &link->win, &req); + mem.CardOffset = req.Base; + mem.Page = 0; + CS_CHECK(MapMemPage, link->win, &mem); + ti->mmio = (u_long)ioremap(req.Base, req.Size); + + /* Allocate the SRAM memory window */ + req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE; + req.Attributes |= WIN_USE_WAIT|WIN_MAP_BELOW_1MB; + req.Base = srambase; + req.Size = sramsize * 1024; + req.AccessSpeed = 250; + info->sram_win_handle = (window_handle_t)link->handle; + CS_CHECK(RequestWindow, &info->sram_win_handle, &req); + + mem.CardOffset = req.Base; + mem.Page = 0; + CS_CHECK(MapMemPage, info->sram_win_handle, &mem); + Shared_Ram_Base = req.Base >> 12; + + ti->sram = 0; + ti->sram_base = Shared_Ram_Base; + + CS_CHECK(RequestConfiguration, link->handle, &link->conf); + + /* Set up the Token-Ring Controller Configuration Register and + turn on the card. Check the "Local Area Network Credit Card + Adapters Technical Reference" SC30-3585 for this info. */ + ibmtr_hw_setup(dev); + +#if 0 + dev->tbusy = 0; +#endif + + i = register_trdev(dev); + + if (i != 0) { + printk(KERN_NOTICE "ibmtr_cs: register_trdev() failed\n"); + goto failed; + } + + link->dev = &info->node; + link->state &= ~DEV_CONFIG_PENDING; + + printk(KERN_INFO "%s: port %#3lx, irq %d,", + dev->name, dev->base_addr, dev->irq); + printk (" mmio %#5lx,", (u_long)ti->mmio); + printk (" sram %#5lx,", (u_long)ti->sram_base << 12); + printk ("\n" KERN_INFO " hwaddr="); + for (i = 0; i < TR_ALEN; i++) + printk("%02X", dev->dev_addr[i]); + printk("\n"); + return; + +cs_failed: + cs_error(link->handle, last_fn, last_ret); +failed: + ibmtr_release((u_long)link); +} /* ibmtr_config */ + +/*====================================================================== + + After a card is removed, ibmtr_release() will unregister the net + device, and release the PCMCIA configuration. If the device is + still open, this will be postponed until it is closed. + +======================================================================*/ + +static void ibmtr_release(u_long arg) +{ + dev_link_t *link = (dev_link_t *)arg; + ibmtr_dev_t *info = link->priv; + struct net_device *dev = info->dev; + struct tok_info *ti=(struct tok_info *) dev->priv; + + DEBUG(0, "ibmtr_release(0x%p)\n", link); + + if (link->open) { + DEBUG(1, "ibmtr_cs: release postponed, '%s' " + "still open\n", info->node.dev_name); + link->state |= DEV_STALE_CONFIG; + return; + } + + ti->open_status=CLOSED; + + CardServices(ReleaseConfiguration, link->handle); + CardServices(ReleaseIO, link->handle, &link->io); + CardServices(ReleaseIRQ, link->handle, &link->irq); + if (link->win) { + struct tok_info *ti = dev->priv; + iounmap((void *)ti->mmio); + CardServices(ReleaseWindow, link->win); + CardServices(ReleaseWindow, info->sram_win_handle); + } + + link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING); + +} /* ibmtr_release */ + +/*====================================================================== + + The card status event handler. Mostly, this schedules other + stuff to run after an event is received. A CARD_REMOVAL event + also sets some flags to discourage the net drivers from trying + to talk to the card any more. + +======================================================================*/ + +static int ibmtr_event(event_t event, int priority, + event_callback_args_t *args) +{ + dev_link_t *link = args->client_data; + ibmtr_dev_t *info = link->priv; + struct net_device *dev = info->dev; + + DEBUG(1, "ibmtr_event(0x%06x)\n", event); + + switch (event) { + case CS_EVENT_CARD_REMOVAL: + link->state &= ~DEV_PRESENT; + if (link->state & DEV_CONFIG) { +#if 0 + dev->tbusy = 1; dev->start = 0; +#endif + 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; + ibmtr_config(link); + break; + case CS_EVENT_PM_SUSPEND: + link->state |= DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_RESET_PHYSICAL: + if (link->state & DEV_CONFIG) { +#if 0 + if (link->open) { + dev->tbusy = 1; dev->start = 0; + } +#endif + CardServices(ReleaseConfiguration, link->handle); + } + break; + case CS_EVENT_PM_RESUME: + link->state &= ~DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_CARD_RESET: + if (link->state & DEV_CONFIG) { + CardServices(RequestConfiguration, link->handle, &link->conf); + if (link->open) { + (dev->init)(dev); +#if 0 + dev->tbusy = 0; dev->start = 1; +#endif + } + } + break; + } + return 0; +} /* ibmtr_event */ + +/*====================================================================*/ + +static void ibmtr_hw_setup(struct net_device *dev) +{ + struct tok_info *ti = dev->priv; + int i; + + /* Bizarre IBM behavior, there are 16 bits of information we + need to set, but the card only allows us to send 4 bits at a + time. For each byte sent to base_addr, bits 7-4 tell the + card which part of the 16 bits we are setting, bits 3-0 contain + the actual information */ + + /* First nibble provides 4 bits of mmio */ + i = ((int)ti->mmio >> 16) & 0x0F; + outb(i, dev->base_addr); + + /* Second nibble provides 3 bits of mmio */ + i = 0x10 | (((int)ti->mmio >> 12) & 0x0E); + outb(i, dev->base_addr); + + /* Third nibble, hard-coded values */ + i = 0x26; + outb(i, dev->base_addr); + + /* Fourth nibble sets shared ram page size */ + + /* 8 = 00, 16 = 01, 32 = 10, 64 = 11 */ + + i = (sramsize >> 4) & 0x07; + i = ((i == 4) ? 3 : i) << 2; + i |= 0x30; + + if (ringspeed == 16) + i |= 2; + if (dev->base_addr == 0xA24) + i |= 1; + outb(i, dev->base_addr); + + /* X40 will release the card for use */ + + outb(0x40, dev->base_addr); + + return; +} + +/*====================================================================== + + A sweet little function that circumvents the problem with + ibmtr.c trying to use more memory than we can allocate for + the PCMCIA card. ibmtr.c just assumes that if a card has + 64K of shared ram, the entire 64K must be mapped into memory, + whereas resources are sometimes a little tight in card services + so we fool ibmtr.c into thinking the card has less memory on + it than it has. + +======================================================================*/ + +unsigned char pcmcia_reality_check(unsigned char gss) +{ + return (gss < sramsize) ? sramsize : gss; +} + +/*====================================================================*/ + +static int __init init_ibmtr_cs(void) +{ + servinfo_t serv; + DEBUG(0, "%s\n", version); + CardServices(GetCardServicesInfo, &serv); + if (serv.Revision != CS_RELEASE_CODE) { + printk(KERN_NOTICE "ibmtr_cs: Card Services release " + "does not match!\n"); + return -1; + } + register_pccard_driver(&dev_info, &ibmtr_attach, &ibmtr_detach); + return 0; +} + +static void __exit exit_ibmtr_cs(void) +{ + DEBUG(0, "ibmtr_cs: unloading\n"); + unregister_pccard_driver(&dev_info); + while (dev_list != NULL) + ibmtr_detach(dev_list); +} + +module_init(init_ibmtr_cs); +module_exit(exit_ibmtr_cs); diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/net/ppp_async.c linux/drivers/net/ppp_async.c --- v2.3.99-pre3/linux/drivers/net/ppp_async.c Sun Mar 19 18:35:30 2000 +++ linux/drivers/net/ppp_async.c Mon Apr 10 23:05:35 2000 @@ -119,9 +119,11 @@ struct asyncppp *ap; int err; + MOD_INC_USE_COUNT; + err = -ENOMEM; ap = kmalloc(sizeof(*ap), GFP_KERNEL); if (ap == 0) - return -ENOMEM; + goto out; /* initialize the asyncppp structure */ memset(ap, 0, sizeof(*ap)); @@ -140,15 +142,18 @@ ap->chan.ops = &async_ops; ap->chan.mtu = PPP_MRU; err = ppp_register_channel(&ap->chan); - if (err) { - kfree(ap); - return err; - } + if (err) + goto out_free; tty->disc_data = ap; - MOD_INC_USE_COUNT; return 0; + + out_free: + kfree(ap); + out: + MOD_DEC_USE_COUNT; + return err; } /* @@ -215,6 +220,16 @@ err = -EFAULT; switch (cmd) { + case PPPIOCGCHAN: + err = -ENXIO; + if (ap == 0) + break; + err = -EFAULT; + if (put_user(ppp_channel_index(&ap->chan), (int *) arg)) + break; + err = 0; + break; + case PPPIOCGUNIT: err = -ENXIO; if (ap == 0) @@ -257,10 +272,14 @@ case PPPIOCSXASYNCMAP: case PPPIOCGMRU: case PPPIOCSMRU: + err = -EPERM; + if (!capable(CAP_NET_ADMIN)) + break; err = ppp_async_ioctl(&ap->chan, cmd, arg); break; case PPPIOCATTACH: + case PPPIOCDETACH: err = ppp_channel_ioctl(&ap->chan, cmd, arg); break; diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/net/ppp_generic.c linux/drivers/net/ppp_generic.c --- v2.3.99-pre3/linux/drivers/net/ppp_generic.c Sun Mar 19 18:35:30 2000 +++ linux/drivers/net/ppp_generic.c Mon Apr 10 23:05:35 2000 @@ -19,7 +19,7 @@ * PPP driver, written by Michael Callahan and Al Longyear, and * subsequently hacked by Paul Mackerras. * - * ==FILEVERSION 20000313== + * ==FILEVERSION 20000406== */ #include @@ -55,8 +55,8 @@ #define NP_AT 3 /* Appletalk protocol */ #define NUM_NP 4 /* Number of NPs. */ -#define MPHDRLEN 4 /* multilink protocol header length */ -#define MPHDRLEN_SSN 2 /* ditto with short sequence numbers */ +#define MPHDRLEN 6 /* multilink protocol header length */ +#define MPHDRLEN_SSN 4 /* ditto with short sequence numbers */ #define MIN_FRAG_SIZE 64 /* @@ -125,12 +125,13 @@ /* * Bits in flags: SC_NO_TCP_CCID, SC_CCP_OPEN, SC_CCP_UP, SC_LOOP_TRAFFIC, - * SC_MULTILINK, SC_MP_SHORTSEQ, SC_MP_XSHORTSEQ. + * SC_MULTILINK, SC_MP_SHORTSEQ, SC_MP_XSHORTSEQ, SC_COMP_TCP, SC_REJ_COMP_TCP. * Bits in rstate: SC_DECOMP_RUN, SC_DC_ERROR, SC_DC_FERROR. * Bits in xstate: SC_COMP_RUN */ #define SC_FLAG_BITS (SC_NO_TCP_CCID|SC_CCP_OPEN|SC_CCP_UP|SC_LOOP_TRAFFIC \ - |SC_MULTILINK|SC_MP_SHORTSEQ|SC_MP_XSHORTSEQ) + |SC_MULTILINK|SC_MP_SHORTSEQ|SC_MP_XSHORTSEQ \ + |SC_COMP_TCP|SC_REJ_COMP_TCP) /* * Private data structure for each channel. @@ -182,6 +183,14 @@ /* We limit the length of ppp->file.rq to this (arbitrary) value */ #define PPP_MAX_RQLEN 32 +/* + * Maximum number of multilink fragments queued up. + * This has to be large enough to cope with the maximum latency of + * the slowest channel relative to the others. Strictly it should + * depend on the number of channels and their characteristics. + */ +#define PPP_MP_MAX_QLEN 128 + /* Multilink header bits. */ #define B 0x80 /* this fragment begins a packet */ #define E 0x40 /* this fragment ends a packet */ @@ -351,10 +360,13 @@ add_wait_queue(&pf->rwait, &wait); current->state = TASK_INTERRUPTIBLE; for (;;) { - ret = -EAGAIN; skb = skb_dequeue(&pf->rq); if (skb) break; + ret = 0; + if (pf->kind == CHANNEL && PF_TO_CHANNEL(pf)->chan == 0) + break; + ret = -EAGAIN; if (file->f_flags & O_NONBLOCK) break; ret = -ERESTARTSYS; @@ -487,7 +499,7 @@ spin_lock_bh(&pch->downl); chan = pch->chan; err = -ENOTTY; - if (chan->ops->ioctl) + if (chan && chan->ops->ioctl) err = chan->ops->ioctl(chan, cmd, arg); spin_unlock_bh(&pch->downl); } @@ -767,6 +779,7 @@ outf: kfree_skb(skb); + ++ppp->stats.tx_dropped; return 0; } @@ -1003,8 +1016,15 @@ pch = list_entry(list, struct channel, clist); spin_lock_bh(&pch->downl); - if (skb_queue_len(&pch->file.xq) == 0 - && pch->chan->ops->start_xmit(pch->chan, skb)) + if (pch->chan) { + if (pch->chan->ops->start_xmit(pch->chan, skb)) + skb = 0; + } else { + /* channel got unregistered */ + kfree_skb(skb); + skb = 0; + } + if (skb_queue_len(&pch->file.xq) == 0 && skb == 0) ppp->xmit_pending = 0; spin_unlock_bh(&pch->downl); return; @@ -1029,7 +1049,8 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) { int nch, len, fragsize; - int i, bits, hdrlen; + int i, bits, hdrlen, mtu; + int flen, fnb; unsigned char *p, *q; struct list_head *list; struct channel *pch; @@ -1037,6 +1058,7 @@ struct ppp_channel *chan; nch = 0; + hdrlen = (ppp->flags & SC_MP_XSHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN; list = &ppp->channels; while ((list = list->next) != &ppp->channels) { pch = list_entry(list, struct channel, clist); @@ -1087,8 +1109,6 @@ /* create a fragment for each channel */ bits = B; - hdrlen = (ppp->flags & SC_MP_XSHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN; - /* XXX gotta do A/C and prot compression here */ do { list = list->next; if (list == &ppp->channels) { @@ -1099,47 +1119,73 @@ ++i; if (!pch->avail) continue; - if (fragsize >= len) { - fragsize = len; - bits |= E; + + /* check the channel's mtu and whether it is still attached. */ + spin_lock_bh(&pch->downl); + if (pch->chan == 0 || (mtu = pch->chan->mtu) < hdrlen) { + /* can't use this channel */ + spin_unlock_bh(&pch->downl); + pch->avail = 0; + if (--nch == 0) + break; + continue; } - frag = alloc_skb(fragsize + hdrlen, GFP_ATOMIC); - if (frag != 0) { - q = skb_put(frag, fragsize + hdrlen); + + /* + * We have to create multiple fragments for this channel + * if fragsize is greater than the channel's mtu. + */ + if (fragsize > len) + fragsize = len; + for (flen = fragsize; flen > 0; flen -= fnb) { + fnb = flen; + if (fnb > mtu + 2 - hdrlen) + fnb = mtu + 2 - hdrlen; + if (fnb >= len) + bits |= E; + frag = alloc_skb(fnb + hdrlen, GFP_ATOMIC); + if (frag == 0) + goto noskb; + q = skb_put(frag, fnb + hdrlen); /* make the MP header */ + q[0] = PPP_MP >> 8; + q[1] = PPP_MP; if (ppp->flags & SC_MP_XSHORTSEQ) { - q[0] = bits + ((ppp->nxseq >> 8) & 0xf); - q[1] = ppp->nxseq; - } else { - q[0] = bits; - q[1] = ppp->nxseq >> 16; - q[2] = ppp->nxseq >> 8; + q[2] = bits + ((ppp->nxseq >> 8) & 0xf); q[3] = ppp->nxseq; + } else { + q[2] = bits; + q[3] = ppp->nxseq >> 16; + q[4] = ppp->nxseq >> 8; + q[5] = ppp->nxseq; } /* copy the data in */ - memcpy(q + hdrlen, p, fragsize); + memcpy(q + hdrlen, p, fnb); /* try to send it down the channel */ - spin_lock_bh(&pch->downl); chan = pch->chan; - if (chan != 0) { - if (!chan->ops->start_xmit(chan, frag)) - skb_queue_tail(&pch->file.xq, frag); - } else { - /* channel got unregistered, too bad */ - kfree_skb(skb); - } - spin_unlock_bh(&pch->downl); + if (!chan->ops->start_xmit(chan, frag)) + skb_queue_tail(&pch->file.xq, frag); + pch->had_frag = 1; + p += fnb; + len -= fnb; + ++ppp->nxseq; + bits = 0; } - p += fragsize; - len -= fragsize; - ++ppp->nxseq; - bits = 0; + spin_unlock_bh(&pch->downl); } while (len > 0); ppp->nxchan = i; return 1; + + noskb: + spin_unlock_bh(&pch->downl); + if (ppp->debug & 1) + printk(KERN_ERR "PPP: no memory (fragment)\n"); + ++ppp->stats.tx_errors; + ++ppp->nxseq; + return 1; /* abandon the frame */ } #endif /* CONFIG_PPP_MULTILINK */ @@ -1201,7 +1247,7 @@ proto = PPP_PROTO(skb); read_lock_bh(&pch->upl); - if (pch->ppp == 0 || proto == PPP_LCP || proto == 0x80fb) { + if (pch->ppp == 0 || proto >= 0xc000 || proto == PPP_CCPFRAG) { /* put it on the channel queue */ skb_queue_tail(&pch->file.rq, skb); /* drop old frames if queue too long */ @@ -1306,12 +1352,7 @@ } len = slhc_uncompress(ppp->vj, skb->data + 2, skb->len - 2); if (len <= 0) { - int i; printk(KERN_DEBUG "PPP: VJ decompression error\n"); - printk(KERN_DEBUG "PPP: len = %d data =", skb->len); - for (i = 0; i < 16 && i < skb->len; ++i) - printk(" %.2x", skb->data[i]); - printk("\n"); goto err; } len += 2; @@ -1426,11 +1467,11 @@ static void ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) { - u32 mask, seq, minseq; + u32 mask, seq; struct list_head *l; - int mphdrlen = (ppp->flags & SC_MP_SHORTSEQ)? 2: 4; + int mphdrlen = (ppp->flags & SC_MP_SHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN; - if (skb->len < mphdrlen + 3) + if (skb->len < mphdrlen + 1 || ppp->mrru == 0) goto err; /* no good, throw it away */ /* Decode sequence number and begin/end bits */ @@ -1442,22 +1483,38 @@ mask = 0xffffff; } skb->BEbits = skb->data[2]; - skb_pull(skb, mphdrlen + 2); /* pull off PPP and MP headers*/ + skb_pull(skb, mphdrlen); /* pull off PPP and MP headers */ - /* Expand sequence number to 32 bits */ - seq |= pch->lastseq & ~mask; - if (seq_before(seq, pch->lastseq)) { - if (seq_after(seq, pch->lastseq - 100)) { - printk(KERN_DEBUG "PPP: MP fragments out of order" - " (%u, %u)\n", pch->lastseq, seq); - goto err; - } + /* + * Do protocol ID decompression on the first fragment of each packet. + */ + if ((skb->BEbits & B) && (skb->data[0] & 1)) + *skb_push(skb, 1) = 0; + + /* + * Expand sequence number to 32 bits, making it as close + * as possible to ppp->minseq. + */ + seq |= ppp->minseq & ~mask; + if ((int)(ppp->minseq - seq) > (int)(mask >> 1)) seq += mask + 1; - } + else if ((int)(seq - ppp->minseq) > (int)(mask >> 1)) + seq -= mask + 1; /* should never happen */ skb->sequence = seq; pch->lastseq = seq; /* + * If this packet comes before the next one we were expecting, + * drop it. + */ + if (seq_before(seq, ppp->nextseq)) { + kfree_skb(skb); + ++ppp->stats.rx_dropped; + ppp_receive_error(ppp); + return; + } + + /* * Reevaluate minseq, the minimum over all channels of the * last sequence number received on each channel. Because of * the increasing sequence number rule, we know that any fragment @@ -1465,17 +1522,23 @@ * The list of channels can't change because we have the receive * side of the ppp unit locked. */ - minseq = seq; for (l = ppp->channels.next; l != &ppp->channels; l = l->next) { struct channel *ch = list_entry(l, struct channel, clist); if (seq_before(ch->lastseq, seq)) seq = ch->lastseq; } - ppp->minseq = minseq; + if (seq_before(ppp->minseq, seq)) + ppp->minseq = seq; /* Put the fragment on the reconstruction queue */ ppp_mp_insert(ppp, skb); + /* If the queue is getting long, don't wait any longer for packets + before the start of the queue. */ + if (skb_queue_len(&ppp->mrq) >= PPP_MP_MAX_QLEN + && seq_before(ppp->minseq, ppp->mrq.next->sequence)) + ppp->minseq = ppp->mrq.next->sequence; + /* Pull completed packets off the queue and receive them. */ while ((skb = ppp_mp_reconstruct(ppp)) != 0) ppp_receive_nonmp_frame(ppp, skb); @@ -1523,16 +1586,17 @@ struct sk_buff *skb = NULL; int lost = 0, len = 0; + if (ppp->mrru == 0) /* do nothing until mrru is set */ + return NULL; head = list->next; tail = NULL; for (p = head; p != (struct sk_buff *) list; p = next) { next = p->next; if (seq_before(p->sequence, seq)) { - /* this can't happen, anyway toss the skb */ - printk(KERN_ERR "ppp_mp_reconstruct bad seq %x < %x\n", + /* this can't happen, anyway ignore the skb */ + printk(KERN_ERR "ppp_mp_reconstruct bad seq %u < %u\n", p->sequence, seq); - __skb_unlink(p, list); - kfree_skb(p); + head = next; continue; } if (p->sequence != seq) { @@ -1542,8 +1606,8 @@ break; /* Fragment `seq' is lost, keep going. */ lost = 1; - seq = seq_before(p->sequence, minseq)? - p->sequence: minseq; + seq = seq_before(minseq, p->sequence)? + minseq + 1: p->sequence; next = p; continue; } @@ -1560,22 +1624,31 @@ if (p->BEbits & B) { head = p; lost = 0; - /* reset len, allow for protocol ID compression */ - len = p->data[0] & 1; + len = 0; } len += p->len; /* Got a complete packet yet? */ if (lost == 0 && (p->BEbits & E) && (head->BEbits & B)) { - if (len > ppp->mrru) { + if (len > ppp->mrru + 2) { ++ppp->stats.rx_length_errors; + printk(KERN_DEBUG "PPP: reconstructed packet" + " is too long (%d)\n", len); + } else if (p == head) { + /* fragment is complete packet - reuse skb */ + tail = p; + skb = skb_get(p); + break; } else if ((skb = dev_alloc_skb(len)) == NULL) { ++ppp->stats.rx_missed_errors; + printk(KERN_DEBUG "PPP: no memory for " + "reconstructed packet"); } else { tail = p; break; } + ppp->nextseq = seq + 1; } /* @@ -1593,19 +1666,18 @@ if (tail != NULL) { /* If we have discarded any fragments, signal a receive error. */ - if (head->sequence != ppp->nextseq) + if (head->sequence != ppp->nextseq) { + if (ppp->debug & 1) + printk(KERN_DEBUG " missed pkts %u..%u\n", + ppp->nextseq, head->sequence-1); + ++ppp->stats.rx_dropped; ppp_receive_error(ppp); - - /* uncompress protocol ID */ - if (head->data[0] & 1) - *skb_put(skb, 1) = 0; - p = head; - for (;;) { - memcpy(skb_put(skb, p->len), p->data, p->len); - if (p == tail) - break; - p = p->next; } + + if (head != tail) + /* copy to a single skb */ + for (p = head; p != tail->next; p = p->next) + memcpy(skb_put(skb, p->len), p->data, p->len); ppp->nextseq = tail->sequence + 1; head = tail->next; } @@ -1642,6 +1714,9 @@ chan->ppp = pch; init_ppp_file(&pch->file, CHANNEL); pch->file.hdrlen = chan->hdrlen; +#ifdef CONFIG_PPP_MULTILINK + pch->lastseq = -1; +#endif /* CONFIG_PPP_MULTILINK */ spin_lock_init(&pch->downl); pch->upl = RW_LOCK_UNLOCKED; spin_lock_bh(&all_channels_lock); @@ -1653,13 +1728,30 @@ } /* - * Return the unit number associated with a channel. + * Return the index of a channel. + */ +int ppp_channel_index(struct ppp_channel *chan) +{ + struct channel *pch = chan->ppp; + + return pch->file.index; +} + +/* + * Return the PPP unit number to which a channel is connected. */ int ppp_unit_number(struct ppp_channel *chan) { struct channel *pch = chan->ppp; + int unit = -1; - return pch->ppp->file.index; + if (pch != 0) { + read_lock_bh(&pch->upl); + if (pch->ppp != 0) + unit = pch->ppp->file.index; + read_unlock_bh(&pch->upl); + } + return unit; } /* @@ -1760,6 +1852,8 @@ int err = -ENOTTY; int unit; + if (!capable(CAP_NET_ADMIN)) + return -EPERM; if (pch == 0) return -EINVAL; switch (cmd) { @@ -2104,6 +2198,10 @@ INIT_LIST_HEAD(&ppp->channels); spin_lock_init(&ppp->rlock); spin_lock_init(&ppp->wlock); +#ifdef CONFIG_PPP_MULTILINK + ppp->minseq = -1; + skb_queue_head_init(&ppp->mrq); +#endif /* CONFIG_PPP_MULTILINK */ ppp->dev = dev; dev->init = ppp_net_init; @@ -2163,6 +2261,9 @@ } skb_queue_purge(&ppp->file.xq); skb_queue_purge(&ppp->file.rq); +#ifdef CONFIG_PPP_MULTILINK + skb_queue_purge(&ppp->mrq); +#endif /* CONFIG_PPP_MULTILINK */ dev = ppp->dev; ppp->dev = 0; ppp_unlock(ppp); @@ -2247,10 +2348,12 @@ if (pch->chan == 0) /* need to check this?? */ goto outr; - hdrlen = pch->chan->hdrlen + PPP_HDRLEN; + if (pch->file.hdrlen > ppp->file.hdrlen) + ppp->file.hdrlen = pch->file.hdrlen; + hdrlen = pch->file.hdrlen + 2; /* for protocol bytes */ if (ppp->dev && hdrlen > ppp->dev->hard_header_len) ppp->dev->hard_header_len = hdrlen; - list_add(&pch->clist, &ppp->channels); + list_add_tail(&pch->clist, &ppp->channels); ++ppp->n_channels; pch->ppp = ppp; ret = 0; @@ -2319,6 +2422,7 @@ EXPORT_SYMBOL(ppp_register_channel); EXPORT_SYMBOL(ppp_unregister_channel); +EXPORT_SYMBOL(ppp_channel_index); EXPORT_SYMBOL(ppp_unit_number); EXPORT_SYMBOL(ppp_input); EXPORT_SYMBOL(ppp_input_error); diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/net/ppp_synctty.c linux/drivers/net/ppp_synctty.c --- v2.3.99-pre3/linux/drivers/net/ppp_synctty.c Tue Mar 14 19:10:39 2000 +++ linux/drivers/net/ppp_synctty.c Mon Apr 10 23:05:35 2000 @@ -29,11 +29,9 @@ * PPP driver, written by Michael Callahan and Al Longyear, and * subsequently hacked by Paul Mackerras. * - * ==FILEVERSION 991018== + * ==FILEVERSION 20000322== */ -/* $Id: ppp_synctty.c,v 1.3 1999/09/02 05:30:10 paulus Exp $ */ - #include #include #include @@ -43,9 +41,17 @@ #include #include #include +#include #include -#define PPP_VERSION "2.4.0" +#ifndef spin_trylock_bh +#define spin_trylock_bh(lock) ({ int __r; local_bh_disable(); \ + __r = spin_trylock(lock); \ + if (!__r) local_bh_enable(); \ + __r; }) +#endif + +#define PPP_VERSION "2.4.1" /* Structure for storing local state. */ struct syncppp { @@ -53,29 +59,25 @@ unsigned int flags; unsigned int rbits; int mru; - unsigned long busy; + spinlock_t xmit_lock; + spinlock_t recv_lock; + unsigned long xmit_flags; u32 xaccm[8]; u32 raccm; unsigned int bytes_sent; unsigned int bytes_rcvd; struct sk_buff *tpkt; - struct sk_buff_head xq; unsigned long last_xmit; struct sk_buff *rpkt; - struct sk_buff_head rq; - wait_queue_head_t rwait; struct ppp_channel chan; /* interface to generic ppp layer */ - int connected; }; -/* Bit numbers in busy */ -#define XMIT_BUSY 0 -#define RECV_BUSY 1 -#define XMIT_WAKEUP 2 -#define XMIT_FULL 3 +/* Bit numbers in xmit_flags */ +#define XMIT_WAKEUP 0 +#define XMIT_FULL 1 /* Bits in rbits */ #define SC_RCV_BITS (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP) @@ -85,15 +87,18 @@ /* * Prototypes. */ -static struct sk_buff* ppp_sync_txdequeue(struct syncppp *ap); +static struct sk_buff* ppp_sync_txmunge(struct syncppp *ap, struct sk_buff *); static int ppp_sync_send(struct ppp_channel *chan, struct sk_buff *skb); +static int ppp_sync_ioctl(struct ppp_channel *chan, unsigned int cmd, + unsigned long arg); static int ppp_sync_push(struct syncppp *ap); static void ppp_sync_flush_output(struct syncppp *ap); static void ppp_sync_input(struct syncppp *ap, const unsigned char *buf, - char *flags, int count); + char *flags, int count); struct ppp_channel_ops sync_ops = { - ppp_sync_send + ppp_sync_send, + ppp_sync_ioctl }; /* @@ -157,50 +162,6 @@ } } -/* - * Routines for locking and unlocking the transmit and receive paths. - */ -static inline void -lock_path(struct syncppp *ap, int bit) -{ - do { - while (test_bit(bit, &ap->busy)) - mb(); - } while (test_and_set_bit(bit, &ap->busy)); - mb(); -} - -static inline int -trylock_path(struct syncppp *ap, int bit) -{ - if (test_and_set_bit(bit, &ap->busy)) - return 0; - mb(); - return 1; -} - -static inline void -unlock_path(struct syncppp *ap, int bit) -{ - mb(); - clear_bit(bit, &ap->busy); -} - -#define lock_xmit_path(ap) lock_path(ap, XMIT_BUSY) -#define trylock_xmit_path(ap) trylock_path(ap, XMIT_BUSY) -#define unlock_xmit_path(ap) unlock_path(ap, XMIT_BUSY) -#define lock_recv_path(ap) lock_path(ap, RECV_BUSY) -#define trylock_recv_path(ap) trylock_path(ap, RECV_BUSY) -#define unlock_recv_path(ap) unlock_path(ap, RECV_BUSY) - -static inline void -flush_skb_queue(struct sk_buff_head *q) -{ - struct sk_buff *skb; - - while ((skb = skb_dequeue(q)) != 0) - kfree_skb(skb); -} /* * Routines implementing the synchronous PPP line discipline. @@ -213,27 +174,41 @@ ppp_sync_open(struct tty_struct *tty) { struct syncppp *ap; + int err; + MOD_INC_USE_COUNT; ap = kmalloc(sizeof(*ap), GFP_KERNEL); + err = -ENOMEM; if (ap == 0) - return -ENOMEM; - - MOD_INC_USE_COUNT; + goto out; /* initialize the syncppp structure */ memset(ap, 0, sizeof(*ap)); ap->tty = tty; ap->mru = PPP_MRU; + spin_lock_init(&ap->xmit_lock); + spin_lock_init(&ap->recv_lock); ap->xaccm[0] = ~0U; ap->xaccm[3] = 0x60000000U; ap->raccm = ~0U; - skb_queue_head_init(&ap->xq); - skb_queue_head_init(&ap->rq); - init_waitqueue_head(&ap->rwait); + + ap->chan.private = ap; + ap->chan.ops = &sync_ops; + ap->chan.mtu = PPP_MRU; + ap->chan.hdrlen = 2; /* for A/C bytes */ + err = ppp_register_channel(&ap->chan); + if (err) + goto out_free; tty->disc_data = ap; return 0; + + out_free: + kfree(ap); + out: + MOD_DEC_USE_COUNT; + return err; } /* @@ -248,208 +223,59 @@ if (ap == 0) return; tty->disc_data = 0; - lock_xmit_path(ap); - lock_recv_path(ap); + ppp_unregister_channel(&ap->chan); if (ap->rpkt != 0) kfree_skb(ap->rpkt); - flush_skb_queue(&ap->rq); if (ap->tpkt != 0) kfree_skb(ap->tpkt); - flush_skb_queue(&ap->xq); - if (ap->connected) - ppp_unregister_channel(&ap->chan); kfree(ap); MOD_DEC_USE_COUNT; } /* - * Read a PPP frame. pppd can use this to negotiate over the - * channel before it joins it to a bundle. + * Read a PPP frame, for compatibility until pppd is updated. */ static ssize_t ppp_sync_read(struct tty_struct *tty, struct file *file, unsigned char *buf, size_t count) { struct syncppp *ap = tty->disc_data; - DECLARE_WAITQUEUE(wait, current); - ssize_t ret; - struct sk_buff *skb = 0; - ret = -ENXIO; if (ap == 0) - goto out; /* should never happen */ - - add_wait_queue(&ap->rwait, &wait); - current->state = TASK_INTERRUPTIBLE; - for (;;) { - ret = -EAGAIN; - skb = skb_dequeue(&ap->rq); - if (skb) - break; - if (file->f_flags & O_NONBLOCK) - break; - ret = -ERESTARTSYS; - if (signal_pending(current)) - break; - schedule(); - } - current->state = TASK_RUNNING; - remove_wait_queue(&ap->rwait, &wait); - - if (skb == 0) - goto out; - - ret = -EOVERFLOW; - if (skb->len > count) - goto outf; - ret = -EFAULT; - if (copy_to_user(buf, skb->data, skb->len)) - goto outf; - ret = skb->len; - - outf: - kfree_skb(skb); - out: - return ret; + return -ENXIO; + return ppp_channel_read(&ap->chan, file, buf, count); } /* - * Write a ppp frame. pppd can use this to send frames over - * this particular channel. + * Write a ppp frame, for compatibility until pppd is updated. */ static ssize_t ppp_sync_write(struct tty_struct *tty, struct file *file, const unsigned char *buf, size_t count) { struct syncppp *ap = tty->disc_data; - struct sk_buff *skb; - ssize_t ret; - ret = -ENXIO; if (ap == 0) - goto out; /* should never happen */ - - ret = -ENOMEM; - skb = alloc_skb(count + 2, GFP_KERNEL); - if (skb == 0) - goto out; - skb_reserve(skb, 2); - ret = -EFAULT; - if (copy_from_user(skb_put(skb, count), buf, count)) { - kfree_skb(skb); - goto out; - } - - skb_queue_tail(&ap->xq, skb); - ppp_sync_push(ap); - - ret = count; - - out: - return ret; + return -ENXIO; + return ppp_channel_write(&ap->chan, buf, count); } static int -ppp_sync_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) +ppp_synctty_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) { struct syncppp *ap = tty->disc_data; int err, val; - u32 accm[8]; - struct sk_buff *skb; - - err = -ENXIO; - if (ap == 0) - goto out; /* should never happen */ - err = -EPERM; - if (!capable(CAP_NET_ADMIN)) - goto out; err = -EFAULT; switch (cmd) { - case PPPIOCGFLAGS: - val = ap->flags | ap->rbits; - if (put_user(val, (int *) arg)) - break; - err = 0; - break; - case PPPIOCSFLAGS: - if (get_user(val, (int *) arg)) - break; - ap->flags = val & ~SC_RCV_BITS; - ap->rbits = val & SC_RCV_BITS; - err = 0; - break; - - case PPPIOCGASYNCMAP: - if (put_user(ap->xaccm[0], (u32 *) arg)) - break; - err = 0; - break; - case PPPIOCSASYNCMAP: - if (get_user(ap->xaccm[0], (u32 *) arg)) - break; - err = 0; - break; - - case PPPIOCGRASYNCMAP: - if (put_user(ap->raccm, (u32 *) arg)) - break; - err = 0; - break; - case PPPIOCSRASYNCMAP: - if (get_user(ap->raccm, (u32 *) arg)) - break; - err = 0; - break; - - case PPPIOCGXASYNCMAP: - if (copy_to_user((void *) arg, ap->xaccm, sizeof(ap->xaccm))) - break; - err = 0; - break; - case PPPIOCSXASYNCMAP: - if (copy_from_user(accm, (void *) arg, sizeof(accm))) - break; - accm[2] &= ~0x40000000U; /* can't escape 0x5e */ - accm[3] |= 0x60000000U; /* must escape 0x7d, 0x7e */ - memcpy(ap->xaccm, accm, sizeof(ap->xaccm)); - err = 0; - break; - - case PPPIOCGMRU: - if (put_user(ap->mru, (int *) arg)) - break; - err = 0; - break; - case PPPIOCSMRU: - if (get_user(val, (int *) arg)) - break; - if (val < PPP_MRU) - val = PPP_MRU; - ap->mru = val; - err = 0; - break; - - case PPPIOCATTACH: - if (get_user(val, (int *) arg)) - break; - err = -EALREADY; - if (ap->connected) - break; - ap->chan.private = ap; - ap->chan.ops = &sync_ops; - err = ppp_register_channel(&ap->chan); - if (err != 0) - break; - ap->connected = 1; - break; - case PPPIOCDETACH: + case PPPIOCGUNIT: err = -ENXIO; - if (!ap->connected) + if (ap == 0) + break; + err = -EFAULT; + if (put_user(ppp_channel_index(&ap->chan), (int *) arg)) break; - ppp_unregister_channel(&ap->chan); - ap->connected = 0; err = 0; break; @@ -460,8 +286,6 @@ case TCFLSH: /* flush our buffers and the serial port's buffer */ - if (arg == TCIFLUSH || arg == TCIOFLUSH) - flush_skb_queue(&ap->rq); if (arg == TCIOFLUSH || arg == TCOFLUSH) ppp_sync_flush_output(ap); err = n_tty_ioctl(tty, file, cmd, arg); @@ -469,17 +293,39 @@ case FIONREAD: val = 0; - if ((skb = skb_peek(&ap->rq)) != 0) - val = skb->len; if (put_user(val, (int *) arg)) break; err = 0; break; + /* + * Compatibility calls until pppd is updated. + */ + case PPPIOCGFLAGS: + case PPPIOCSFLAGS: + case PPPIOCGASYNCMAP: + case PPPIOCSASYNCMAP: + case PPPIOCGRASYNCMAP: + case PPPIOCSRASYNCMAP: + case PPPIOCGXASYNCMAP: + case PPPIOCSXASYNCMAP: + case PPPIOCGMRU: + case PPPIOCSMRU: + err = -EPERM; + if (!capable(CAP_NET_ADMIN)) + break; + err = ppp_sync_ioctl(&ap->chan, cmd, arg); + break; + + case PPPIOCATTACH: + case PPPIOCDETACH: + err = ppp_channel_ioctl(&ap->chan, cmd, arg); + break; + default: err = -ENOIOCTLCMD; } - out: + return err; } @@ -489,12 +335,10 @@ struct syncppp *ap = tty->disc_data; unsigned int mask; - if (ap == 0) - return 0; /* should never happen */ - poll_wait(file, &ap->rwait, wait); mask = POLLOUT | POLLWRNORM; - if (skb_peek(&ap->rq)) - mask |= POLLIN | POLLRDNORM; + /* compatibility for old pppd */ + if (ap != 0) + mask |= ppp_channel_poll(&ap->chan, file, wait); if (test_bit(TTY_OTHER_CLOSED, &tty->flags) || tty_hung_up_p(file)) mask |= POLLHUP; return mask; @@ -514,9 +358,9 @@ if (ap == 0) return; - trylock_recv_path(ap); + spin_lock_bh(&ap->recv_lock); ppp_sync_input(ap, buf, flags, count); - unlock_recv_path(ap); + spin_unlock_bh(&ap->recv_lock); if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) && tty->driver.unthrottle) tty->driver.unthrottle(tty); @@ -530,7 +374,7 @@ clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); if (ap == 0) return; - if (ppp_sync_push(ap) && ap->connected) + if (ppp_sync_push(ap)) ppp_output_wakeup(&ap->chan); } @@ -542,7 +386,7 @@ close: ppp_sync_close, read: ppp_sync_read, write: ppp_sync_write, - ioctl: ppp_sync_ioctl, + ioctl: ppp_synctty_ioctl, poll: ppp_sync_poll, receive_room: ppp_sync_room, receive_buf: ppp_sync_receive, @@ -562,54 +406,133 @@ } /* + * The following routines provide the PPP channel interface. + */ +static int +ppp_sync_ioctl(struct ppp_channel *chan, unsigned int cmd, unsigned long arg) +{ + struct syncppp *ap = chan->private; + int err, val; + u32 accm[8]; + + err = -EFAULT; + switch (cmd) { + case PPPIOCGFLAGS: + val = ap->flags | ap->rbits; + if (put_user(val, (int *) arg)) + break; + err = 0; + break; + case PPPIOCSFLAGS: + if (get_user(val, (int *) arg)) + break; + ap->flags = val & ~SC_RCV_BITS; + spin_lock_bh(&ap->recv_lock); + ap->rbits = val & SC_RCV_BITS; + spin_unlock_bh(&ap->recv_lock); + err = 0; + break; + + case PPPIOCGASYNCMAP: + if (put_user(ap->xaccm[0], (u32 *) arg)) + break; + err = 0; + break; + case PPPIOCSASYNCMAP: + if (get_user(ap->xaccm[0], (u32 *) arg)) + break; + err = 0; + break; + + case PPPIOCGRASYNCMAP: + if (put_user(ap->raccm, (u32 *) arg)) + break; + err = 0; + break; + case PPPIOCSRASYNCMAP: + if (get_user(ap->raccm, (u32 *) arg)) + break; + err = 0; + break; + + case PPPIOCGXASYNCMAP: + if (copy_to_user((void *) arg, ap->xaccm, sizeof(ap->xaccm))) + break; + err = 0; + break; + case PPPIOCSXASYNCMAP: + if (copy_from_user(accm, (void *) arg, sizeof(accm))) + break; + accm[2] &= ~0x40000000U; /* can't escape 0x5e */ + accm[3] |= 0x60000000U; /* must escape 0x7d, 0x7e */ + memcpy(ap->xaccm, accm, sizeof(ap->xaccm)); + err = 0; + break; + + case PPPIOCGMRU: + if (put_user(ap->mru, (int *) arg)) + break; + err = 0; + break; + case PPPIOCSMRU: + if (get_user(val, (int *) arg)) + break; + if (val < PPP_MRU) + val = PPP_MRU; + ap->mru = val; + err = 0; + break; + + default: + err = -ENOTTY; + } + return err; +} + +/* * Procedures for encapsulation and framing. */ struct sk_buff* -ppp_sync_txdequeue(struct syncppp *ap) +ppp_sync_txmunge(struct syncppp *ap, struct sk_buff *skb) { int proto; unsigned char *data; int islcp; - struct sk_buff *skb; - - while ((skb = skb_dequeue(&ap->xq)) != NULL) { - data = skb->data; - proto = (data[0] << 8) + data[1]; + data = skb->data; + proto = (data[0] << 8) + data[1]; - /* LCP packets with codes between 1 (configure-request) - * and 7 (code-reject) must be sent as though no options - * have been negotiated. - */ - islcp = proto == PPP_LCP && 1 <= data[2] && data[2] <= 7; - - /* compress protocol field if option enabled */ - if (data[0] == 0 && (ap->flags & SC_COMP_PROT) && !islcp) - skb_pull(skb,1); - - /* prepend address/control fields if necessary */ - if ((ap->flags & SC_COMP_AC) == 0 || islcp) { - if (skb_headroom(skb) < 2) { - struct sk_buff *npkt = dev_alloc_skb(skb->len + 2); - if (npkt == NULL) { - kfree_skb(skb); - continue; - } - skb_reserve(npkt,2); - memcpy(skb_put(npkt,skb->len), skb->data, skb->len); + /* LCP packets with codes between 1 (configure-request) + * and 7 (code-reject) must be sent as though no options + * have been negotiated. + */ + islcp = proto == PPP_LCP && 1 <= data[2] && data[2] <= 7; + + /* compress protocol field if option enabled */ + if (data[0] == 0 && (ap->flags & SC_COMP_PROT) && !islcp) + skb_pull(skb,1); + + /* prepend address/control fields if necessary */ + if ((ap->flags & SC_COMP_AC) == 0 || islcp) { + if (skb_headroom(skb) < 2) { + struct sk_buff *npkt = dev_alloc_skb(skb->len + 2); + if (npkt == NULL) { kfree_skb(skb); - skb = npkt; + return NULL; } - skb_push(skb,2); - skb->data[0] = PPP_ALLSTATIONS; - skb->data[1] = PPP_UI; + skb_reserve(npkt,2); + memcpy(skb_put(npkt,skb->len), skb->data, skb->len); + kfree_skb(skb); + skb = npkt; } - - ap->last_xmit = jiffies; - break; + skb_push(skb,2); + skb->data[0] = PPP_ALLSTATIONS; + skb->data[1] = PPP_UI; } + ap->last_xmit = jiffies; + if (skb && ap->flags & SC_LOG_OUTPKT) ppp_print_buffer ("send buffer", skb->data, skb->len); @@ -633,9 +556,13 @@ ppp_sync_push(ap); - if (test_and_set_bit(XMIT_FULL, &ap->busy)) + if (test_and_set_bit(XMIT_FULL, &ap->xmit_flags)) return 0; /* already full */ - skb_queue_head(&ap->xq,skb); + skb = ppp_sync_txmunge(ap, skb); + if (skb != NULL) + ap->tpkt = skb; + else + clear_bit(XMIT_FULL, &ap->xmit_flags); ppp_sync_push(ap); return 1; @@ -651,20 +578,13 @@ struct tty_struct *tty = ap->tty; int tty_stuffed = 0; - if (!trylock_xmit_path(ap)) { - set_bit(XMIT_WAKEUP, &ap->busy); + set_bit(XMIT_WAKEUP, &ap->xmit_flags); + if (!spin_trylock_bh(&ap->xmit_lock)) return 0; - } for (;;) { - if (test_and_clear_bit(XMIT_WAKEUP, &ap->busy)) + if (test_and_clear_bit(XMIT_WAKEUP, &ap->xmit_flags)) tty_stuffed = 0; - if (ap->tpkt == 0) { - if ((ap->tpkt = ppp_sync_txdequeue(ap)) == 0) { - clear_bit(XMIT_FULL, &ap->busy); - done = 1; - } - } - if (!tty_stuffed && ap->tpkt != NULL) { + if (!tty_stuffed && ap->tpkt != 0) { set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); sent = tty->driver.write(tty, 0, ap->tpkt->data, ap->tpkt->len); if (sent < 0) @@ -674,15 +594,17 @@ } else { kfree_skb(ap->tpkt); ap->tpkt = 0; + clear_bit(XMIT_FULL, &ap->xmit_flags); + done = 1; } continue; } /* haven't made any progress */ - unlock_xmit_path(ap); - if (!(test_bit(XMIT_WAKEUP, &ap->busy) + spin_unlock_bh(&ap->xmit_lock); + if (!(test_bit(XMIT_WAKEUP, &ap->xmit_flags) || (!tty_stuffed && ap->tpkt != 0))) break; - if (!trylock_xmit_path(ap)) + if (!spin_trylock_bh(&ap->xmit_lock)) break; } return done; @@ -691,10 +613,10 @@ if (ap->tpkt != 0) { kfree_skb(ap->tpkt); ap->tpkt = 0; - clear_bit(XMIT_FULL, &ap->busy); + clear_bit(XMIT_FULL, &ap->xmit_flags); done = 1; } - unlock_xmit_path(ap); + spin_unlock_bh(&ap->xmit_lock); return done; } @@ -707,16 +629,15 @@ { int done = 0; - flush_skb_queue(&ap->xq); - lock_xmit_path(ap); + spin_lock_bh(&ap->xmit_lock); if (ap->tpkt != NULL) { kfree_skb(ap->tpkt); ap->tpkt = 0; - clear_bit(XMIT_FULL, &ap->busy); + clear_bit(XMIT_FULL, &ap->xmit_flags); done = 1; } - unlock_xmit_path(ap); - if (done && ap->connected) + spin_unlock_bh(&ap->xmit_lock); + if (done) ppp_output_wakeup(&ap->chan); } @@ -750,30 +671,13 @@ } else if (skb->len < 2) goto err; - /* pass to generic layer or queue it */ - if (ap->connected) { - ppp_input(&ap->chan, skb); - } else { - skb_queue_tail(&ap->rq, skb); - /* drop old frames if queue too long */ - while (ap->rq.qlen > PPPSYNC_MAX_RQLEN - && (skb = skb_dequeue(&ap->rq)) != 0) - kfree(skb); - wake_up_interruptible(&ap->rwait); - } + /* pass to generic layer */ + ppp_input(&ap->chan, skb); return; err: kfree_skb(skb); - if (ap->connected) - ppp_input_error(&ap->chan, code); -} - -static inline void -input_error(struct syncppp *ap, int code) -{ - if (ap->connected) - ppp_input_error(&ap->chan, code); + ppp_input_error(&ap->chan, code); } /* called when the tty driver has data for us. @@ -794,7 +698,7 @@ /* if flag set, then error, ignore frame */ if (flags != 0 && *flags) { - input_error(ap, *flags); + ppp_input_error(&ap->chan, *flags); return; } @@ -805,7 +709,7 @@ if ((skb = ap->rpkt) == 0) { if ((skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2)) == 0) { printk(KERN_ERR "PPPsync: no memory (input pkt)\n"); - input_error(ap, 0); + ppp_input_error(&ap->chan, 0); return; } /* Try to get the payload 4-byte aligned */ @@ -815,7 +719,7 @@ } if (count > skb_tailroom(skb)) { /* packet overflowed MRU */ - input_error(ap, 1); + ppp_input_error(&ap->chan, 1); } else { sp = skb_put(skb, count); memcpy(sp, buf, count); @@ -823,17 +727,12 @@ } } -#ifdef MODULE -int -init_module(void) -{ - return ppp_sync_init(); -} - -void -cleanup_module(void) +void __exit +ppp_sync_cleanup(void) { if (tty_register_ldisc(N_SYNC_PPP, NULL) != 0) printk(KERN_ERR "failed to unregister Sync PPP line discipline\n"); } -#endif /* MODULE */ + +module_init(ppp_sync_init); +module_exit(ppp_sync_cleanup); diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/net/sk98lin/skge.c linux/drivers/net/sk98lin/skge.c --- v2.3.99-pre3/linux/drivers/net/sk98lin/skge.c Sun Feb 20 21:12:39 2000 +++ linux/drivers/net/sk98lin/skge.c Mon Mar 27 10:35:56 2000 @@ -412,21 +412,6 @@ pci_set_master(pdev); -#ifdef __sparc__ - /* Set the proper cache line size value, plus enable - * write-invalidate and fast back-to-back on Sparc. - */ - { - SK_U16 pci_command; - - SkPciWriteCfgByte(pAC, PCI_CACHE_LINE_SIZE, 0x10); - - SkPciReadCfgWord(pAC, PCI_COMMAND, &pci_command); - pci_command |= (PCI_COMMAND_INVALIDATE | PCI_COMMAND_FAST_BACK); - SkPciWriteCfgWord(pAC, PCI_COMMAND, pci_command); - } -#endif - base_address = pdev->resource[0].start; #ifdef SK_BIG_ENDIAN diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/net/sunhme.c linux/drivers/net/sunhme.c --- v2.3.99-pre3/linux/drivers/net/sunhme.c Sun Mar 19 18:35:30 2000 +++ linux/drivers/net/sunhme.c Mon Mar 27 10:35:56 2000 @@ -1,4 +1,4 @@ -/* $Id: sunhme.c,v 1.94 2000/03/15 06:47:04 davem Exp $ +/* $Id: sunhme.c,v 1.95 2000/03/25 05:18:15 davem Exp $ * sunhme.c: Sparc HME/BigMac 10/100baseT half/full duplex auto switching, * auto carrier detecting ethernet driver. Also known as the * "Happy Meal Ethernet" found on SunSwift SBUS cards. @@ -2688,7 +2688,6 @@ struct pcidev_cookie *pcp; struct happy_meal *hp; unsigned long hpreg_base; - unsigned short pci_command; int i, node, qfe_slot = -1; char prom_name[64]; @@ -2844,20 +2843,6 @@ happy_meal_set_initial_advertisement(hp); ether_setup(dev); - - /* If we don't do this, nothing works. */ - pci_read_config_word(pdev, PCI_COMMAND, &pci_command); - pci_command |= PCI_COMMAND_MASTER; - pci_write_config_word(pdev, PCI_COMMAND, pci_command); - - /* Set the latency timer and cache line size as well, - * PROM leaves it at zero. - */ - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64); -#ifdef __sparc_v9__ - /* NOTE: Cache line size is in 32-bit word units. */ - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x10); -#endif #ifdef MODULE /* We are home free at this point, link us in to the happy diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/net/tokenring/Config.in linux/drivers/net/tokenring/Config.in --- v2.3.99-pre3/linux/drivers/net/tokenring/Config.in Tue Mar 14 19:10:39 2000 +++ linux/drivers/net/tokenring/Config.in Thu Mar 30 16:54:53 2000 @@ -14,7 +14,9 @@ if [ "$CONFIG_TMS380TR" != "n" ]; then dep_tristate ' Generic TMS380 PCI support' CONFIG_TMSPCI $CONFIG_TMS380TR dep_tristate ' Madge Smart 16/4 PCI Mk2 support' CONFIG_ABYSS $CONFIG_TMS380TR - dep_tristate ' Madge Smart 16/4 Ringnode MicroChannel' CONFIG_MADGEMC $CONFIG_TMS380TR + if [ "$CONFIG_MCA" = "y" ]; then + dep_tristate ' Madge Smart 16/4 Ringnode MicroChannel' CONFIG_MADGEMC $CONFIG_TMS380TR + fi fi dep_tristate ' SMC ISA/MCA adapter support' CONFIG_SMCTR $CONFIG_TR fi diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/net/tokenring/ibmtr.c linux/drivers/net/tokenring/ibmtr.c --- v2.3.99-pre3/linux/drivers/net/tokenring/ibmtr.c Thu Mar 2 14:36:22 2000 +++ linux/drivers/net/tokenring/ibmtr.c Sun Apr 2 15:38:54 2000 @@ -88,6 +88,9 @@ * to support windowing into on adapter shared ram. * i.e. Use LANAID to setup a PnP configuration with 16K RAM. Paging * will shift this 16K window over the entire available shared RAM. + * + * Changes by Peter De Schrijver (p2@mind.be) : + * + fixed a problem with PCMCIA card removal */ /* change the define of IBMTR_DEBUG_MESSAGES to a nonzero value @@ -95,16 +98,8 @@ #define IBMTR_DEBUG_MESSAGES 0 -#ifdef PCMCIA -#define MODULE -#endif - #include -#ifdef PCMCIA -#undef MODULE -#endif - #define NO_AUTODETECT 1 #undef NO_AUTODETECT /* #undef ENABLE_PAGING */ @@ -161,13 +156,13 @@ #include #include #include +#include #include #include #include #include -#include "ibmtr.h" #define DPRINTK(format, args...) printk("%s: " format, dev->name , ## args) @@ -814,6 +809,9 @@ int i; + if(ti->open_status==CLOSED) + return; + address[0] = address[1] = address[2] = address[3] = 0; mclist = dev->mc_list; @@ -870,26 +868,28 @@ struct tok_info *ti=(struct tok_info *) dev->priv; - netif_stop_queue(dev); - SET_PAGE(ti->srb_page); - isa_writeb(DIR_CLOSE_ADAPTER, - ti->srb + offsetof(struct srb_close_adapter, command)); - isa_writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); - - ti->open_status=CLOSED; - - sleep_on(&ti->wait_for_tok_int); - - SET_PAGE(ti->srb_page); - if (isa_readb(ti->srb + offsetof(struct srb_close_adapter, ret_code))) - DPRINTK("close adapter failed: %02X\n", - (int)isa_readb(ti->srb + offsetof(struct srb_close_adapter, ret_code))); + if(ti->open_status!=CLOSED) { + netif_stop_queue(dev); + SET_PAGE(ti->srb_page); + isa_writeb(DIR_CLOSE_ADAPTER, + ti->srb + offsetof(struct srb_close_adapter, command)); + isa_writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); + + ti->open_status=CLOSED; + + sleep_on(&ti->wait_for_tok_int); + + SET_PAGE(ti->srb_page); + if (isa_readb(ti->srb + offsetof(struct srb_close_adapter, ret_code))) + DPRINTK("close adapter failed: %02X\n", + (int)isa_readb(ti->srb + offsetof(struct srb_close_adapter, ret_code))); #ifdef PCMCIA - ti->sram = 0 ; + ti->sram = 0 ; #endif - DPRINTK("Adapter closed.\n"); - MOD_DEC_USE_COUNT; + DPRINTK("Adapter closed.\n"); + MOD_DEC_USE_COUNT; + } return 0; } @@ -937,6 +937,7 @@ if (status == 0xFF) { DPRINTK("PCMCIA card removed.\n"); + ti->open_status=CLOSED; goto return_point ; } @@ -944,6 +945,7 @@ if ( isa_readb (ti->mmio + ACA_OFFSET + ACA_RW + ISRP_EVEN) == 0xFF) { DPRINTK("PCMCIA card removed.\n"); + ti->open_status=CLOSED; goto return_point ; } #endif @@ -1851,6 +1853,7 @@ return 0; } +#ifndef PCMCIA #ifdef MODULE /* 3COM 3C619C supports 8 interrupts, 32 I/O ports */ @@ -1908,3 +1911,4 @@ } } #endif /* MODULE */ +#endif diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/net/wan/cycx_drv.c linux/drivers/net/wan/cycx_drv.c --- v2.3.99-pre3/linux/drivers/net/wan/cycx_drv.c Tue Jan 11 22:31:40 2000 +++ linux/drivers/net/wan/cycx_drv.c Mon Apr 3 19:32:57 2000 @@ -48,14 +48,8 @@ * Aug 8, 1998 acme Initial version. */ -#ifdef MODULE -#ifdef MODVERSIONS -#include -#endif +#include /* __init */ #include -#else -#define EXPORT_SYMBOL(function) -#endif #include /* printk(), and other useful stuff */ #include /* offsetof(), etc. */ #include /* return codes */ @@ -66,12 +60,10 @@ #include /* read[wl], write[wl], ioremap, iounmap */ #define MOD_VERSION 0 -#define MOD_RELEASE 5 +#define MOD_RELEASE 6 -#ifdef MODULE MODULE_AUTHOR("Arnaldo Carvalho de Melo"); MODULE_DESCRIPTION("Cyclom 2x Sync Card Driver"); -#endif /* Function Prototypes */ /* Module entry points. These are called by the OS and must be public. */ @@ -129,20 +121,21 @@ * Return: 0 Ok * < 0 error. * Context: process */ -#ifdef MODULE -int init_module(void) + +int __init cycx_drv_init(void) { printk(KERN_INFO "%s v%u.%u %s\n", fullname, MOD_VERSION, MOD_RELEASE, copyright); return 0; } + /* Module 'remove' entry point. * o release all remaining system resources */ -void cleanup_module(void) +void cycx_drv_cleanup(void) { } -#endif + /* Kernel APIs */ /* Set up adapter. * o detect adapter type @@ -599,4 +592,8 @@ return crc; } + +module_init(cycx_drv_init); +module_exit(cycx_drv_cleanup); + /* End */ diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/net/wan/cycx_main.c linux/drivers/net/wan/cycx_main.c --- v2.3.99-pre3/linux/drivers/net/wan/cycx_main.c Fri Jan 28 15:09:07 2000 +++ linux/drivers/net/wan/cycx_main.c Mon Apr 3 19:32:57 2000 @@ -13,6 +13,8 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * ============================================================================ +* 2000/04/02 acme dprintk and cycx_debug +* module_init/module_exit * 2000/01/21 acme rename cyclomx_open to cyclomx_mod_inc_use_count * and cyclomx_close to cyclomx_mod_dec_use_count * 2000/01/08 acme cleanup @@ -43,15 +45,21 @@ #include /* kernel <-> user copy */ #include /* __init (when not using as a module) */ +/* Debug */ + +unsigned int cycx_debug = 0; + #ifdef MODULE MODULE_AUTHOR("Arnaldo Carvalho de Melo"); MODULE_DESCRIPTION("Cyclom 2X Sync Card Driver."); +MODULE_PARM(debug, "i"); +MODULE_PARM_DESC(debug, "cyclomx debug level"); #endif /* Defines & Macros */ #define DRV_VERSION 0 /* version number */ -#define DRV_RELEASE 6 /* release (minor version) number */ +#define DRV_RELEASE 7 /* release (minor version) number */ #define MAX_CARDS 1 /* max number of adapters */ #ifndef CONFIG_CYCLOMX_CARDS /* configurable option */ @@ -60,10 +68,6 @@ /* Function Prototypes */ -/* Module entry points */ -int init_module (void); -void cleanup_module (void); - /* WAN link driver entry points */ static int setup (wan_device_t *wandev, wandev_conf_t *conf); static int shutdown (wan_device_t *wandev); @@ -98,11 +102,7 @@ * < 0 error. * Context: process */ -#ifdef MODULE -int init_module (void) -#else int __init cyclomx_init (void) -#endif { int cnt, err = 0; @@ -156,8 +156,7 @@ * o unregister all adapters from the WAN router * o release all remaining system resources */ -#ifdef MODULE -void cleanup_module (void) +void cyclomx_cleanup (void) { int i = 0; @@ -168,7 +167,7 @@ kfree(card_array); } -#endif + /* WAN Device Driver Entry Points */ /* * Setup/configure WAN link driver. @@ -384,5 +383,8 @@ card->state_tick = jiffies; spin_unlock_irqrestore(&card->lock, host_cpu_flags); } + +module_init(cyclomx_init); +module_exit(cyclomx_cleanup); /* End */ diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/net/wan/cycx_x25.c linux/drivers/net/wan/cycx_x25.c --- v2.3.99-pre3/linux/drivers/net/wan/cycx_x25.c Sun Feb 20 21:12:39 2000 +++ linux/drivers/net/wan/cycx_x25.c Mon Apr 3 19:32:57 2000 @@ -12,6 +12,10 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * ============================================================================ +* 2000/04/02 acme dprintk, cycx_debug +* fixed the bug introduced in get_dev_by_lcn and +* get_dev_by_dte_addr by the anonymous hacker +* that converted this driver to softnet * 2000/01/08 acme cleanup * 1999/10/27 acme use ARPHRD_HWX25 so that the X.25 stack know * that we have a X.25 stack implemented in @@ -110,7 +114,7 @@ u32 idle_tmout; /* sec, before disconnecting */ struct sk_buff *rx_skb; /* receive socket buffer */ cycx_t *card; /* -> owner */ - struct enet_statistics ifstats; /* interface statistics */ + struct net_device_stats ifstats;/* interface statistics */ } x25_channel_t; /* Function Prototypes */ @@ -178,13 +182,11 @@ static void x25_dump_config(TX25Config *conf); static void x25_dump_stats(TX25Stats *stats); static void x25_dump_devs(wan_device_t *wandev); -#define dprintk(format, a...) printk(format, ##a) #else #define hex_dump(msg, p, len) #define x25_dump_config(conf) #define x25_dump_stats(stats) #define x25_dump_devs(wandev) -#define dprintk(format, a...) #endif /* Public Functions */ @@ -846,7 +848,7 @@ if (sizerem) nibble_to_byte(d + (sizeloc >> 1), rem, sizerem, sizeloc & 1); - dprintk(KERN_INFO "connect_intr:lcn=%d, local=%s, remote=%s\n", + dprintk(1, KERN_INFO "connect_intr:lcn=%d, local=%s, remote=%s\n", lcn, loc, rem); if ((dev = get_dev_by_dte_addr(wandev, rem)) == NULL) { @@ -872,7 +874,7 @@ cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn)); cycx_peek(&card->hw, cmd->buf + 1, &key, sizeof(key)); - dprintk(KERN_INFO "%s: connect_confirm_intr:lcn=%d, key=%d\n", + dprintk(1, KERN_INFO "%s: connect_confirm_intr:lcn=%d, key=%d\n", card->devname, lcn, key); if ((dev = get_dev_by_lcn(wandev, -key)) == NULL) { @@ -897,7 +899,7 @@ u8 lcn; cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn)); - dprintk(KERN_INFO "%s: disconnect_confirm_intr:lcn=%d\n", + dprintk(1, KERN_INFO "%s: disconnect_confirm_intr:lcn=%d\n", card->devname, lcn); if ((dev = get_dev_by_lcn(wandev, lcn)) == NULL) { /* Invalid channel, discard packet */ @@ -917,7 +919,7 @@ u8 lcn; cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn)); - dprintk(KERN_INFO "disconnect_intr:lcn=%d\n", lcn); + dprintk(1, KERN_INFO "disconnect_intr:lcn=%d\n", lcn); if ((dev = get_dev_by_lcn(wandev, lcn)) != NULL) { x25_channel_t *chan = dev->priv; @@ -1172,7 +1174,7 @@ key = ffz(card->u.x.connection_keys); set_bit(key, (void*)&card->u.x.connection_keys); ++key; - dprintk(KERN_INFO "%s:x25_place_call:key=%d\n", card->devname, key); + dprintk(1, KERN_INFO "%s:x25_place_call:key=%d\n", card->devname, key); memset(d, 0, sizeof(d)); d[1] = key; /* user key */ d[2] = 0x10; @@ -1259,6 +1261,8 @@ x25_channel_t *chan; while (dev) { + chan = (x25_channel_t*)dev->priv; + if (chan->lcn == lcn) break; dev = chan->slave; @@ -1273,6 +1277,8 @@ x25_channel_t *chan; while (dev) { + chan = (x25_channel_t*)dev->priv; + if (!strcmp(chan->addr, dte)) break; dev = chan->slave; @@ -1296,7 +1302,7 @@ if (!chan->addr[0]) return -EINVAL; /* no destination address */ - dprintk(KERN_INFO "%s: placing X.25 call to %s...\n", + dprintk(1, KERN_INFO "%s: placing X.25 call to %s...\n", card->devname, chan->addr); if (x25_place_call(card, chan)) diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/net/wan/z85230.c linux/drivers/net/wan/z85230.c --- v2.3.99-pre3/linux/drivers/net/wan/z85230.c Tue Mar 14 19:10:40 2000 +++ linux/drivers/net/wan/z85230.c Sun Apr 2 15:38:53 2000 @@ -1316,7 +1316,7 @@ * @rtable: Table of register, value pairs * FIXME: ioctl to allow user uploaded tables * - * Load a Z8530 channel up from the system data> We use +16 to + * Load a Z8530 channel up from the system data. We use +16 to * indicate the 'prime' registers. The value 255 terminates the * table */ diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/parport/ChangeLog linux/drivers/parport/ChangeLog --- v2.3.99-pre3/linux/drivers/parport/ChangeLog Mon Mar 27 08:08:27 2000 +++ linux/drivers/parport/ChangeLog Mon Mar 27 11:27:07 2000 @@ -1,3 +1,8 @@ +2000-03-27 Tim Waugh + + * parport_pc.c (parport_pc_ecp_read_block_pio): Correct operation + when peripheral is trying to send data when we stop listening. + 2000-03-22 Tim Waugh * init.c (parport_setup): Fix return value. diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/parport/parport_pc.c linux/drivers/parport/parport_pc.c --- v2.3.99-pre3/linux/drivers/parport/parport_pc.c Mon Mar 27 08:08:27 2000 +++ linux/drivers/parport/parport_pc.c Mon Mar 27 11:27:07 2000 @@ -178,9 +178,6 @@ int cnfga; const struct parport_pc_private *priv = p->physport->private_data; - /* Prevent further data transfer. */ - frob_econtrol (p, 0xe0, ECR_TST << 5); - /* Adjust for the contents of the FIFO. */ for (residue = priv->fifo_depth; ; residue--) { if (inb (ECONTROL (p)) & 0x2) @@ -862,7 +859,8 @@ length, flags); /* Switch to reverse mode if necessary. */ - if (port->ieee1284.phase != IEEE1284_PH_REV_IDLE) { + if ((port->ieee1284.phase != IEEE1284_PH_REV_IDLE) && + (port->ieee1284.phase != IEEE1284_PH_REV_DATA)) { /* Event 38: Set nAutoFd low */ parport_frob_control (port, PARPORT_CONTROL_AUTOFD, @@ -879,7 +877,7 @@ parport_wait_peripheral (port, PARPORT_STATUS_PAPEROUT, 0); } - /* Set up ECP parallel port mode.*/ + /* Set up ECP FIFO mode.*/ parport_pc_data_reverse (port); /* Must be in PS2 mode */ parport_pc_frob_control (port, PARPORT_CONTROL_STROBE | @@ -951,14 +949,23 @@ left--; } + port->ieee1284.phase = IEEE1284_PH_REV_IDLE; + + /* Go to forward idle mode to shut the peripheral up. */ + parport_frob_control (port, PARPORT_CONTROL_INIT, 0); + parport_wait_peripheral (port, + PARPORT_STATUS_PAPEROUT, + PARPORT_STATUS_PAPEROUT); + port->ieee1284.phase = IEEE1284_PH_FWD_IDLE; + /* Finish up. */ - if (change_mode (port, ECR_PS2) == -EBUSY) { + { int lost = get_fifo_residue (port); - printk (KERN_DEBUG "%s: DATA LOSS (%d bytes)!\n", port->name, - lost); + if (lost) + /* Shouldn't happen with compliant peripherals. */ + printk (KERN_DEBUG "%s: DATA LOSS (%d bytes)!\n", + port->name, lost); } - - port->ieee1284.phase = IEEE1284_PH_REV_IDLE; return length - left; } diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/parport/parport_sunbpp.c linux/drivers/parport/parport_sunbpp.c --- v2.3.99-pre3/linux/drivers/parport/parport_sunbpp.c Wed Dec 29 13:13:16 1999 +++ linux/drivers/parport/parport_sunbpp.c Thu Mar 30 16:54:53 2000 @@ -1,4 +1,4 @@ -/* $Id: parport_sunbpp.c,v 1.9 1999/10/14 05:59:43 ecd Exp $ +/* $Id: parport_sunbpp.c,v 1.10 2000/03/27 01:47:56 anton Exp $ * Parallel-port routines for Sun architecture * * Author: Derrick J. Brashear @@ -334,6 +334,8 @@ sbus_iounmap(base, size); return 0; } + + p->size = size; dprintk(("init_one_port: request_irq(%08x:%p:%x:%s:%p) ", p->irq, parport_sunbpp_interrupt, SA_SHIRQ, p->name, p)); diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/parport/share.c linux/drivers/parport/share.c --- v2.3.99-pre3/linux/drivers/parport/share.c Sat Feb 26 22:31:47 2000 +++ linux/drivers/parport/share.c Mon Apr 3 13:24:05 2000 @@ -103,6 +103,19 @@ request_module ("parport_lowlevel"); } +/** + * parport_register_driver - register a parallel port device driver + * @drv: structure describing the driver + * + * This can be called by a parallel port device driver in order to + * receive notifications about ports being found in the system, as + * well as ports no longer available. + * + * The @drv structure is allocated by the caller and must not be + * deallocated until after calling parport_unregister_driver(). + * + * Returns 0 on success. Currently it always succeeds. + **/ int parport_register_driver (struct parport_driver *drv) { struct parport *port; @@ -121,6 +134,23 @@ return 0; } +/** + * parport_unregister_driver - deregister a parallel port device driver + * @arg: structure describing the driver that was given to + * parport_register_driver() + * + * This should be called by a parallel port device driver that has + * registered itself using parport_register_driver() when it is about + * to be unloaded. + * + * When it returns, the driver's attach() routine will no longer be + * called, and for each port that attach() was called for, the + * detach() routine will hae been called. + * + * If the caller's attach() function can block, it is their + * responsibility to make sure to wait for it to exit before + * unloading. + **/ void parport_unregister_driver (struct parport_driver *arg) { struct parport_driver *drv = driver_chain, *olddrv = NULL; @@ -149,8 +179,17 @@ } } -/* Return a list of all the ports we know about. This function shouldn't - * really be used -- use parport_register_driver instead. */ +/** + * parport_enumerate - return a list of the system's parallel ports + * + * This returns the head of the list of parallel ports in the system. + * The structure that is returned describes the first port in the + * list, and its 'next' member points to the next port, or %NULL if + * it's the last port. + * + * If there are no parallel ports in the system, parport_enumerate() + * will return %NULL. + **/ struct parport *parport_enumerate(void) { if (!portlist) @@ -159,6 +198,33 @@ return portlist; } +/** + * parport_register_port - register a parallel port + * @base: base I/O address + * @irq: IRQ line + * @dma: DMA channel + * @ops: pointer to the port driver's port operations structure + * + * When a parallel port (lowlevel) driver finds a port that should be + * made available to parallel port device drivers, it should call + * parport_register_port(). The @base, @irq, and @dma parameters are + * for the convenience of port drivers, and for ports where they + * aren't meaningful needn't be set to anything special. They can be + * altered afterwards by adjusting the relevant members of the parport + * structure that is returned and represents the port. They should + * not be tampered with after calling parport_announce_port, however. + * + * If there are parallel port device drivers in the system that have + * registered themselves using parport_register_driver(), they are not + * told about the port at this time; that is done by + * parport_announce_port(). + * + * The @ops structure is allocated by the caller, and must not be + * deallocated before calling parport_unregister_port(). + * + * If there is no memory to allocate a new parport structure, this + * function will return %NULL. + **/ struct parport *parport_register_port(unsigned long base, int irq, int dma, struct parport_operations *ops) { @@ -243,6 +309,17 @@ return tmp; } +/** + * parport_announce_port - tell device drivers about a parallel port + * @port: parallel port to announce + * + * After a port driver has registered a parallel port with + * parport_register_port, and performed any necessary initialisation + * or adjustments, it should call parport_announce_port() in order to + * notify all device drivers that have called + * parport_register_driver(). Their attach() functions will be + * called, with @port as the parameter. + **/ void parport_announce_port (struct parport *port) { #ifdef CONFIG_PARPORT_1284 @@ -286,6 +363,23 @@ kfree(port); } +/** + * parport_unregister_port - deregister a parallel port + * @port: parallel port to deregister + * + * When a parallel port driver is forcibly unloaded, or a parallel + * port becomes inaccessible, the port driver must call this function + * in order to deal with device drivers that still want to use it. + * + * The parport structure associated with the port has its operations + * structure replaced with one containing 'null' operations that + * return errors or just don't do anything. + * + * Any drivers that have registered themselves using + * parport_register_driver() are notified that the port is no longer + * accessible by having their detach() routines called with @port as + * the parameter. + **/ void parport_unregister_port(struct parport *port) { struct parport *p; @@ -320,10 +414,76 @@ free_port (port); } -struct pardevice *parport_register_device(struct parport *port, const char *name, - int (*pf)(void *), void (*kf)(void *), - void (*irq_func)(int, void *, struct pt_regs *), - int flags, void *handle) +/** + * parport_register_device - register a device on a parallel port + * @port: port to which the device is attached + * @name: a name to refer to the device + * @pf: preemption callback + * @kf: kick callback (wake-up) + * @irq_func: interrupt handler + * @flags: registration flags + * @handle: data for callback functions + * + * This function, called by parallel port device drivers, declares + * that a device is connected to a port, and tells the system all it + * needs to know. + * + * The @name is allocated by the caller and must not be deallocated + * until the caller calls @parport_unregister_device for that device. + * + * The preemption callback function, @pf, is called when this device + * driver has claimed access to the port but another device driver + * wants to use it. It is given @handle as its parameter, and should + * return zero if it is willing for the system to release the port to + * another driver on its behalf. If it wants to keep control of the + * port it should return non-zero, and no action will be taken. It is + * good manners for the driver to try to release the port at the + * earliest opportunity after its preemption callback rejects a + * preemption attempt. Note that if a preemption callback is happy + * for preemption to go ahead, there is no need to release the port; + * it is done automatically. This function may not block, as it may + * be called from interrupt context. If the device driver does not + * support preemption, @pf can be %NULL. + * + * The wake-up ("kick") callback function, @kf, is called when the + * port is available to be claimed for exclusive access; that is, + * parport_claim() is guaranteed to succeed when called from inside + * the wake-up callback function. If the driver wants to claim the + * port it should do so; otherwise, it need not take any action. This + * function may not block, as it may be called from interrupt context. + * If the device driver does not want to be explicitly invited to + * claim the port in this way, @kf can be %NULL. + * + * The interrupt handler, @irq_func, is called when an interrupt + * arrives from the parallel port. Note that if a device driver wants + * to use interrupts it should use parport_enable_irq(), and can also + * check the irq member of the parport structure representing the + * port. + * + * The parallel port (lowlevel) driver is the one that has called + * request_irq() and whose interrupt handler is called first. This + * handler does whatever needs to be done to the hardware to + * acknowledge the interrupt (for PC-style ports there is nothing + * special to be done). It then tells the IEEE 1284 code about the + * interrupt, which may involve reacting to an IEEE 1284 event + * depending on the current IEEE 1284 phase. After this, it calls + * @irq_func. Needless to say, @irq_func will be called from + * interrupt context, and may not block. + * + * The %PARPORT_DEV_EXCL flag is for preventing port sharing, and so + * should only be used when sharing the port with other device drivers + * is impossible and would lead to incorrect behaviour. Use it + * sparingly! Normally, @flags will be zero. + * + * This function returns a pointer to a structure that represents the + * device on the port, or %NULL if there is not enough memory to + * allocate space for that structure. + **/ +struct pardevice * +parport_register_device(struct parport *port, const char *name, + int (*pf)(void *), void (*kf)(void *), + void (*irq_func)(int, void *, struct pt_regs *), + int flags, void *handle) { struct pardevice *tmp; @@ -341,17 +501,25 @@ } } + /* We up our own module reference count, and that of the port + on which a device is to be registered, to ensure that + neither of us gets unloaded while we sleep in (e.g.) + kmalloc. To be absolutely safe, we have to require that + our caller doesn't sleep in between parport_enumerate and + parport_register_device.. */ + inc_parport_count(); + port->ops->inc_use_count(); + tmp = kmalloc(sizeof(struct pardevice), GFP_KERNEL); if (tmp == NULL) { printk(KERN_WARNING "%s: memory squeeze, couldn't register %s.\n", port->name, name); - return NULL; + goto out; } tmp->state = kmalloc(sizeof(struct parport_state), GFP_KERNEL); if (tmp->state == NULL) { printk(KERN_WARNING "%s: memory squeeze, couldn't register %s.\n", port->name, name); - kfree(tmp); - return NULL; + goto out_free_pardevice; } tmp->name = name; @@ -376,12 +544,10 @@ if (flags & PARPORT_DEV_EXCL) { if (port->physport->devices) { spin_unlock (&port->physport->pardevice_lock); - kfree (tmp->state); - kfree (tmp); printk (KERN_DEBUG "%s: cannot grant exclusive access for " "device %s\n", port->name, name); - return NULL; + goto out_free_all; } port->flags |= PARPORT_FLAG_EXCL; } @@ -392,9 +558,6 @@ port->physport->devices = tmp; spin_unlock(&port->physport->pardevice_lock); - inc_parport_count(); - port->ops->inc_use_count(); - init_waitqueue_head(&tmp->wait_q); tmp->timeslice = parport_default_timeslice; tmp->waitnext = tmp->waitprev = NULL; @@ -406,8 +569,23 @@ port->ops->init_state(tmp, tmp->state); parport_device_proc_register(tmp); return tmp; + + out_free_all: + kfree (tmp->state); + out_free_pardevice: + kfree (tmp); + out: + dec_parport_count(); + port->ops->dec_use_count(); + return NULL; } +/** + * parport_unregister_device - deregister a device on a parallel port + * @dev: pointer to structure representing device + * + * This undoes the effect of parport_register_device(). + **/ void parport_unregister_device(struct pardevice *dev) { struct parport *port; @@ -454,6 +632,16 @@ free_port (port); } +/** + * parport_claim - claim access to a parallel port device + * @dev: pointer to structure representing a device on the port + * + * This function will not block and so can be used from interrupt + * context. If parport_claim() succeeds in claiming access to the + * port it returns zero and the port is available to use. It may fail + * (returning non-zero) if the port is in use by another driver and + * that driver is not willing to relinquish control of the port. + **/ int parport_claim(struct pardevice *dev) { struct pardevice *oldcad; @@ -555,6 +743,15 @@ return -EAGAIN; } +/** + * parport_claim_or_block - claim access to a parallel port device + * @dev: pointer to structure representing a device on the port + * + * This behaves like parport_claim(), but will block if necessary to + * wait for the port to be free. A return value of 1 indicates that + * it slept; 0 means that it succeeded without needing to sleep. A + * negative error code indicates failure. + **/ int parport_claim_or_block(struct pardevice *dev) { int r; @@ -597,6 +794,14 @@ return r; } +/** + * parport_release - give up access to a parallel port device + * @dev: pointer to structure representing parallel port device + * + * This function cannot fail, but it should not be called without the + * port claimed. Similarly, if the port is already claimed you should + * not try claiming it again. + **/ void parport_release(struct pardevice *dev) { struct parport *port = dev->port->physport; diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/pci/gen-devlist.c linux/drivers/pci/gen-devlist.c --- v2.3.99-pre3/linux/drivers/pci/gen-devlist.c Fri Jan 28 15:09:08 2000 +++ linux/drivers/pci/gen-devlist.c Mon Mar 27 14:29:13 2000 @@ -1,12 +1,14 @@ /* * Generate devlist.h and classlist.h from the PCI ID file. * - * (c) 1999 Martin Mares + * (c) 1999--2000 Martin Mares */ #include #include +#define MAX_NAME_SIZE 79 + static void pq(FILE *f, const char *c) { @@ -22,9 +24,11 @@ int main(void) { - char line[1024], *c, vend[8]; + char line[1024], *c, *bra, vend[8]; int vendors = 0; int mode = 0; + int lino = 0; + int vendor_len = 0; FILE *devf, *clsf; devf = fopen("devlist.h", "w"); @@ -35,6 +39,7 @@ } while (fgets(line, sizeof(line)-1, stdin)) { + lino++; if ((c = strchr(line, '\n'))) *c = 0; if (!line[0] || line[0] == '#') @@ -56,6 +61,16 @@ c = line + 5; while (*c == ' ') *c++ = 0; + if (vendor_len + strlen(c) + 1 > MAX_NAME_SIZE) { + /* Too long, try cutting off long description */ + bra = strchr(c, '['); + if (bra && bra > c && bra[-1] == ' ') + bra[-1] = 0; + if (vendor_len + strlen(c) + 1 > MAX_NAME_SIZE) { + fprintf(stderr, "Line %d: Device name too long\n", lino); + return 1; + } + } fprintf(devf, "\tDEVICE(%s,%s,\"", vend, line+1); pq(devf, c); fputs("\")\n", devf); @@ -80,13 +95,18 @@ fputs("ENDVENDOR()\n\n", devf); vendors++; strcpy(vend, line); + vendor_len = strlen(c); + if (vendor_len + 24 > MAX_NAME_SIZE) { + fprintf(stderr, "Line %d: Vendor name too long\n", lino); + return 1; + } fprintf(devf, "VENDOR(%s,\"", vend); pq(devf, c); fputs("\")\n", devf); mode = 1; } else { err: - fprintf(stderr, "Syntax error in mode %d: %s\n", mode, line); + fprintf(stderr, "Line %d: Syntax error in mode %d: %s\n", lino, mode, line); return 1; } } diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/pci/pci.ids linux/drivers/pci/pci.ids --- v2.3.99-pre3/linux/drivers/pci/pci.ids Sun Mar 19 18:35:30 2000 +++ linux/drivers/pci/pci.ids Mon Mar 27 14:29:13 2000 @@ -1245,7 +1245,7 @@ 10db Rohm LSI Systems, Inc. 10dc CERN/ECP/EDU 0001 STAR/RD24 SCI-PCI (PMC) - 0002 TAR/RD24 SCI-PCI (PMC) [ATT 2C15-3 (FPGA) SCI bridge on PCI 5 Volt card] + 0002 TAR/RD24 SCI-PCI (PMC) 0021 HIPPI destination 0022 HIPPI source 10dc ATT2C15-3 FPGA @@ -1328,7 +1328,7 @@ 8089 Kingsberg Spacetec Serial Output Board 809c S5933_HEPC3 811a PCI-IEEE1355-DS-DE Interface - 8170 S5933 "Matchmaker" PCI Chipset Development Tool + 8170 S5933 "Matchmaker" [PCI Chipset Development Tool] 10e9 Alps Electric Co., Ltd. 10ea Intergraphics Systems 1680 IGA-1680 diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/pci/setup-res.c linux/drivers/pci/setup-res.c --- v2.3.99-pre3/linux/drivers/pci/setup-res.c Fri Jan 21 18:19:16 2000 +++ linux/drivers/pci/setup-res.c Mon Mar 27 14:29:13 2000 @@ -89,7 +89,7 @@ return 0; } -static void +void pdev_assign_unassigned_resources(struct pci_dev *dev) { u32 reg; diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/scsi/ChangeLog.ncr53c8xx linux/drivers/scsi/ChangeLog.ncr53c8xx --- v2.3.99-pre3/linux/drivers/scsi/ChangeLog.ncr53c8xx Tue Mar 14 19:10:40 2000 +++ linux/drivers/scsi/ChangeLog.ncr53c8xx Sat Apr 1 07:45:31 2000 @@ -1,3 +1,13 @@ +Sat Apr 1 12:00 2000 Gerard Roudier (groudier@club-internet.fr) + * revision 3.2h + - Fix a compilation problem on Alpha introduced in version 3.2g. + (`port' changed to `base_io'). + - Move from `sym' to this driver a tiny change for __sparc__ that + applies to cache line size (? Probably from David S Miller). + - Make sure no data transfer will happen for Scsi_Cmnd requests + that supply SCSI_DATA_NONE direction (this avoids some BUG() + statement in the PCI code when a data buffer is also supplied). + Mon March 6 23:15 2000 Gerard Roudier (groudier@club-internet.fr) * revision 3.2g - Add the file sym53c8xx_comm.h that collects code that should diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/scsi/ChangeLog.sym53c8xx linux/drivers/scsi/ChangeLog.sym53c8xx --- v2.3.99-pre3/linux/drivers/scsi/ChangeLog.sym53c8xx Tue Mar 14 19:10:40 2000 +++ linux/drivers/scsi/ChangeLog.sym53c8xx Sat Apr 1 07:45:31 2000 @@ -1,3 +1,11 @@ +Sat Apr 1 12:00 2000 Gerard Roudier (groudier@club-internet.fr) + * revision 1.5l + - Tiny change for __sparc__ appeared in 2.3.99-pre4.1 that + applies to cache line size (? Probably from David S Miller). + - Make sure no data transfer will happen for Scsi_Cmnd requests + that supply SCSI_DATA_NONE direction (this avoids some BUG() + statement in the PCI code when a data buffer is also supplied). + Mon Mar 6 23:30 2000 Gerard Roudier (groudier@club-internet.fr) * version sym53c8xx-1.5k - Test against expected data transfer direction from SCRIPTS. diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/scsi/Config.in linux/drivers/scsi/Config.in --- v2.3.99-pre3/linux/drivers/scsi/Config.in Tue Mar 14 19:10:40 2000 +++ linux/drivers/scsi/Config.in Mon Mar 27 09:45:33 2000 @@ -55,7 +55,9 @@ bool ' Collect statistics to report in /proc' CONFIG_AIC7XXX_PROC_STATS int ' Delay in seconds after SCSI bus reset' CONFIG_AIC7XXX_RESET_DELAY 5 fi -dep_tristate 'IBM ServeRAID support' CONFIG_SCSI_IPS $CONFIG_SCSI +if [ "$CONFIG_X86" = "y" ]; then + dep_tristate 'IBM ServeRAID support' CONFIG_SCSI_IPS $CONFIG_SCSI +fi 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 @@ -65,6 +67,7 @@ if [ "$CONFIG_SCSI_BUSLOGIC" != "n" ]; then bool ' Omit FlashPoint support' CONFIG_SCSI_OMIT_FLASHPOINT fi +dep_tristate 'DMX3191D SCSI support' CONFIG_SCSI_DMX3191D $CONFIG_SCSI $CONFIG_PCI dep_tristate 'DTC3180/3280 SCSI support' CONFIG_SCSI_DTC3280 $CONFIG_SCSI dep_tristate 'EATA ISA/EISA/PCI (DPT and generic EATA/DMA-compliant boards) support' CONFIG_SCSI_EATA $CONFIG_SCSI if [ "$CONFIG_SCSI_EATA" != "n" ]; then @@ -86,10 +89,8 @@ "Port CONFIG_SCSI_G_NCR5380_PORT \ Memory CONFIG_SCSI_G_NCR5380_MEM" Port fi -if [ "$CONFIG_PCI" = "y" ]; then - dep_tristate 'Initio 9100U(W) support' CONFIG_SCSI_INITIO $CONFIG_SCSI - dep_tristate 'Initio INI-A100U2W support' CONFIG_SCSI_INIA100 $CONFIG_SCSI -fi +dep_tristate 'Initio 9100U(W) support' CONFIG_SCSI_INITIO $CONFIG_SCSI $CONFIG_PCI +dep_tristate 'Initio INI-A100U2W support' CONFIG_SCSI_INIA100 $CONFIG_SCSI $CONFIG_PCI if [ "$CONFIG_PARPORT" != "n" ]; then dep_tristate 'IOMEGA parallel port (ppa - older drives)' CONFIG_SCSI_PPA $CONFIG_SCSI $CONFIG_PARPORT dep_tristate 'IOMEGA parallel port (imm - newer drives)' CONFIG_SCSI_IMM $CONFIG_SCSI $CONFIG_PARPORT @@ -101,13 +102,11 @@ dep_tristate 'NCR53c406a SCSI support' CONFIG_SCSI_NCR53C406A $CONFIG_SCSI dep_tristate 'symbios 53c416 SCSI support' CONFIG_SCSI_SYM53C416 $CONFIG_SCSI dep_tristate 'Simple 53c710 SCSI support (Compaq, NCR machines)' CONFIG_SCSI_SIM710 $CONFIG_SCSI -if [ "$CONFIG_PCI" = "y" ]; then - dep_tristate 'NCR53c7,8xx SCSI support' CONFIG_SCSI_NCR53C7xx $CONFIG_SCSI - if [ "$CONFIG_SCSI_NCR53C7xx" != "n" ]; then - bool ' always negotiate synchronous transfers' CONFIG_SCSI_NCR53C7xx_sync - bool ' allow FAST-SCSI [10MHz]' CONFIG_SCSI_NCR53C7xx_FAST - bool ' allow DISCONNECT' CONFIG_SCSI_NCR53C7xx_DISCONNECT - 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 + bool ' allow FAST-SCSI [10MHz]' CONFIG_SCSI_NCR53C7xx_FAST + bool ' allow DISCONNECT' CONFIG_SCSI_NCR53C7xx_DISCONNECT fi if [ "$CONFIG_PCI" = "y" -a "$CONFIG_SCSI_NCR53C7xx" != "y" ]; then dep_tristate 'NCR53C8XX SCSI support' CONFIG_SCSI_NCR53C8XX $CONFIG_SCSI @@ -149,7 +148,9 @@ dep_tristate 'Qlogic ISP FC SCSI support' CONFIG_SCSI_QLOGIC_FC $CONFIG_SCSI dep_tristate 'Qlogic QLA 1280 SCSI support' CONFIG_SCSI_QLOGIC_1280 $CONFIG_SCSI fi -dep_tristate 'Seagate ST-02 and Future Domain TMC-8xx SCSI support' CONFIG_SCSI_SEAGATE $CONFIG_SCSI +if [ "$CONFIG_X86" = "y" ]; then + dep_tristate 'Seagate ST-02 and Future Domain TMC-8xx SCSI support' CONFIG_SCSI_SEAGATE $CONFIG_SCSI +fi if [ "$CONFIG_PCI" = "y" ]; then dep_tristate 'Tekram DC390(T) and Am53/79C974 SCSI support' CONFIG_SCSI_DC390T $CONFIG_SCSI if [ "$CONFIG_SCSI_DC390T" != "n" ]; then @@ -162,7 +163,9 @@ bool ' enable elevator sorting' CONFIG_SCSI_U14_34F_LINKED_COMMANDS int ' maximum number of queued commands' CONFIG_SCSI_U14_34F_MAX_TAGS 8 fi -dep_tristate 'UltraStor SCSI support' CONFIG_SCSI_ULTRASTOR $CONFIG_SCSI +if [ "$CONFIG_X86" = "y" ]; then + dep_tristate 'UltraStor SCSI support' CONFIG_SCSI_ULTRASTOR $CONFIG_SCSI +fi # # Note - this is a very special 'host' adapter that simulates the presence of some disks. # It can come in very handy for troubleshooting. Anyone else is welcome to use it - all diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile --- v2.3.99-pre3/linux/drivers/scsi/Makefile Mon Mar 27 08:08:27 2000 +++ linux/drivers/scsi/Makefile Mon Mar 27 09:44:58 2000 @@ -613,6 +613,14 @@ endif endif +ifeq ($(CONFIG_SCSI_DMX3191D),y) +L_OBJS += dmx3191d.o +else + ifeq ($(CONFIG_SCSI_DMX3191D),m) + M_OBJS += dmx3191d.o + endif +endif + ifeq ($(CONFIG_SCSI_DTC3280),y) L_OBJS += dtc.o else diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/scsi/dmx3191d.c linux/drivers/scsi/dmx3191d.c --- v2.3.99-pre3/linux/drivers/scsi/dmx3191d.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/dmx3191d.c Mon Mar 27 09:48:11 2000 @@ -0,0 +1,125 @@ + +/* + dmx3191d.c - midlevel driver for the Domex DMX3191D SCSI card. + Copyright (C) 2000 by Massimo Piccioni + + Based on the generic NCR5380 driver by Drew Eckhardt et al. + + 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. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "scsi.h" +#include "hosts.h" +#include "constants.h" +#include "sd.h" + +#include "dmx3191d.h" + +/* play with these values to tune up your system performances */ +/* default setting from g_NCR5380.c */ +/* +#define USLEEP +#define USLEEP_POLL 1 +#define USLEEP_SLEEP 20 +#define USLEEP_WAITLONG 500 +*/ + +#define AUTOSENSE +#include "NCR5380.h" +#include "NCR5380.c" + + +int __init dmx3191d_detect(Scsi_Host_Template *tmpl) { + int boards = 0; + struct Scsi_Host *instance = NULL; + struct pci_dev *pdev = NULL; + + if (!pci_present()) { + dmx3191d_printk("PCI support not enabled\n"); + return 0; + } + + tmpl->proc_name = DMX3191D_DRIVER_NAME; + + while ((pdev = pci_find_device(PCI_VENDOR_ID_DOMEX, + PCI_DEVICE_ID_DOMEX_DMX3191D, pdev))) { + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13) + unsigned long port = pdev->base_address[0] & PCI_IOADDRESS_MASK; +#else + unsigned long port = pdev->resource[0].start; +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13) */ + + if (check_region(port, DMX3191D_REGION)) { + dmx3191d_printk("region 0x%lx-0x%lx already reserved\n", + port, port + DMX3191D_REGION); + continue; + } + + request_region(port, DMX3191D_REGION, DMX3191D_DRIVER_NAME); + + instance = scsi_register(tmpl, sizeof(struct NCR5380_hostdata)); + instance->io_port = port; + instance->irq = pdev->irq; + NCR5380_init(instance, FLAG_NO_PSEUDO_DMA | FLAG_DTC3181E); + + if (request_irq(pdev->irq, dmx3191d_do_intr, SA_SHIRQ, + DMX3191D_DRIVER_NAME, instance)) { + dmx3191d_printk("irq %d not available\n", pdev->irq); + /* Steam powered scsi controllers run without an IRQ + anyway */ + instance->irq = IRQ_NONE; + } + + boards++; + } + return boards; +} + +const char * dmx3191d_info(struct Scsi_Host *host) { + static const char *info ="Domex DMX3191D"; + + return info; +} + +int dmx3191d_release_resources(struct Scsi_Host *instance) +{ + release_region(instance->io_port, DMX3191D_REGION); + if(instance->irq!=IRQ_NONE) + free_irq(instance->irq, instance); + + return 0; +} + + +#ifdef MODULE +Scsi_Host_Template driver_template = DMX3191D; + +#include "scsi_module.c" + +#endif /* MODULE */ + diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/scsi/dmx3191d.h linux/drivers/scsi/dmx3191d.h --- v2.3.99-pre3/linux/drivers/scsi/dmx3191d.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/dmx3191d.h Mon Mar 27 09:48:11 2000 @@ -0,0 +1,74 @@ + +/* + dmx3191d.h - defines for the Domex DMX3191D SCSI card. + Copyright (C) 2000 by Massimo Piccioni + + 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 __DMX3191D_H +#define __DMX3191D_H + +#define DMX3191D_DRIVER_NAME "dmx3191d" +#define DMX3191D_REGION 8 + +#ifndef PCI_VENDOR_ID_DOMEX +#define PCI_VENDOR_ID_DOMEX 0x134a +#define PCI_DEVICE_ID_DOMEX_DMX3191D 0x0001 +#endif + +#define dmx3191d_printk( args... ) printk(__FILE__": " ##args) + +#ifndef ASM +int dmx3191d_abort(Scsi_Cmnd *); +int dmx3191d_detect(Scsi_Host_Template *); +const char* dmx3191d_info(struct Scsi_Host *); +int dmx3191d_proc_info(char *, char **, off_t, int, int, int); +int dmx3191d_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +int dmx3191d_release_resources(struct Scsi_Host *); +int dmx3191d_reset(Scsi_Cmnd *, unsigned int); + + +#if defined(HOSTS_C) || defined(MODULE) +#define DMX3191D { \ + proc_info: dmx3191d_proc_info, \ + name: "Domex DMX3191D", \ + detect: dmx3191d_detect, \ + release: dmx3191d_release_resources, \ + info: dmx3191d_info, \ + queuecommand: dmx3191d_queue_command, \ + abort: dmx3191d_abort, \ + reset: dmx3191d_reset, \ + bios_param: NULL, \ + can_queue: 32, \ + this_id: 7, \ + sg_tablesize: SG_ALL, \ + cmd_per_lun: 2, \ + use_clustering: DISABLE_CLUSTERING \ +} +#endif /* HOSTS_C || MODULE */ + + +#ifndef HOSTS_C +#define NCR5380_read(reg) inb(port + reg) +#define NCR5380_write(reg, value) outb(value, port + reg) + +#define NCR5380_implementation_fields unsigned int port +#define NCR5380_local_declare() NCR5380_implementation_fields +#define NCR5380_setup(instance) port = instance->io_port + +#define NCR5380_abort dmx3191d_abort +#define do_NCR5380_intr dmx3191d_do_intr +#define NCR5380_intr dmx3191d_intr +#define NCR5380_proc_info dmx3191d_proc_info +#define NCR5380_queue_command dmx3191d_queue_command +#define NCR5380_reset dmx3191d_reset + +#endif /* HOSTS_C */ +#endif /* ASM */ + +#endif /* __DMX3191D_H */ + diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/scsi/esp.c linux/drivers/scsi/esp.c --- v2.3.99-pre3/linux/drivers/scsi/esp.c Sun Feb 20 21:12:39 2000 +++ linux/drivers/scsi/esp.c Thu Mar 30 16:54:54 2000 @@ -1,4 +1,4 @@ -/* $Id: esp.c,v 1.92 2000/02/18 13:49:58 davem Exp $ +/* $Id: esp.c,v 1.94 2000/03/30 02:09:10 davem Exp $ * esp.c: EnhancedScsiProcessor Sun SCSI driver code. * * Copyright (C) 1995, 1998 David S. Miller (davem@caip.rutgers.edu) @@ -4346,6 +4346,13 @@ ESP_INTSON(esp->dregs); } spin_unlock_irqrestore(&esp->lock, flags); +} + +int esp_revoke(Scsi_Device* SDptr) +{ + struct esp *esp = (struct esp *) SDptr->host->hostdata; + esp->targets_present &= ~(1 << SDptr->id); + return 0; } #ifdef MODULE diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/scsi/esp.h linux/drivers/scsi/esp.h --- v2.3.99-pre3/linux/drivers/scsi/esp.h Wed Dec 29 13:13:18 1999 +++ linux/drivers/scsi/esp.h Mon Apr 10 23:25:00 2000 @@ -1,4 +1,4 @@ -/* $Id: esp.h,v 1.27 1999/12/15 14:12:52 davem Exp $ +/* $Id: esp.h,v 1.28 2000/03/30 01:33:17 davem Exp $ * esp.h: Defines and structures for the Sparc ESP (Enhanced SCSI * Processor) driver under Linux. * @@ -398,12 +398,14 @@ extern int esp_reset(Scsi_Cmnd *, unsigned int); extern int esp_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout); +extern int esp_revoke(Scsi_Device* SDptr); #define SCSI_SPARC_ESP { \ proc_name: "esp", \ proc_info: &esp_proc_info, \ name: "Sun ESP 100/100a/200", \ detect: esp_detect, \ + revoke: esp_revoke, \ info: esp_info, \ command: esp_command, \ queuecommand: esp_queue, \ diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/scsi/hosts.c linux/drivers/scsi/hosts.c --- v2.3.99-pre3/linux/drivers/scsi/hosts.c Sat Feb 26 22:31:48 2000 +++ linux/drivers/scsi/hosts.c Mon Mar 27 09:48:11 2000 @@ -205,6 +205,10 @@ #include "t128.h" #endif +#ifdef CONFIG_SCSI_DMX3191D +#include "dmx3191d.h" +#endif + #ifdef CONFIG_SCSI_DTC3280 #include "dtc.h" #endif @@ -549,6 +553,9 @@ #endif #ifdef CONFIG_SCSI_T128 TRANTOR_T128, +#endif +#ifdef CONFIG_SCSI_DMX3191D + DMX3191D, #endif #ifdef CONFIG_SCSI_DTC3280 DTC3x80, diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/scsi/hosts.h linux/drivers/scsi/hosts.h --- v2.3.99-pre3/linux/drivers/scsi/hosts.h Tue Mar 14 19:10:40 2000 +++ linux/drivers/scsi/hosts.h Mon Apr 10 23:24:58 2000 @@ -96,6 +96,8 @@ */ int (* detect)(struct SHT *); + int (*revoke)(Scsi_Device *); + /* Used with loadable modules to unload the host structures. Note: * there is a default action built into the modules code which may * be sufficient for most host adapters. Thus you may not have to supply diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/scsi/ncr53c8xx.c linux/drivers/scsi/ncr53c8xx.c --- v2.3.99-pre3/linux/drivers/scsi/ncr53c8xx.c Tue Mar 14 19:10:40 2000 +++ linux/drivers/scsi/ncr53c8xx.c Sat Apr 1 07:45:31 2000 @@ -104,7 +104,7 @@ /* ** Name and version of the driver */ -#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - version 3.2g" +#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - version 3.2h" #define SCSI_NCR_DEBUG_FLAGS (0) @@ -1120,7 +1120,7 @@ u_char revision_id; /* PCI device revision id */ u_char bus; /* PCI BUS number */ u_char device_fn; /* PCI BUS device and function */ - u_long port; /* IO space base address */ + u_long base_io; /* IO space base address */ u_int irq; /* IRQ level */ u_int features; /* Chip features map */ u_char myaddr; /* SCSI id of the adapter */ @@ -3734,7 +3734,7 @@ */ request_region(device->slot.io_port, 128, "ncr53c8xx"); - np->port = device->slot.io_port; + np->base_io = device->slot.io_port; #ifdef SCSI_NCR_NVRAM_SUPPORT if (nvram) { @@ -3951,11 +3951,11 @@ unmap_pci_mem((vm_offset_t) np->vaddr, (u_long) 128); } #endif /* !NCR_IOMAPPED */ - if (np->port) { + if (np->base_io) { #ifdef DEBUG_NCR53C8XX - printk(KERN_DEBUG "%s: releasing IO region %x[%d]\n", ncr_name(np), np->port, 128); + printk(KERN_DEBUG "%s: releasing IO region %x[%d]\n", ncr_name(np), np->base_io, 128); #endif - release_region(np->port, 128); + release_region(np->base_io, 128); } if (np->irq) { #ifdef DEBUG_NCR53C8XX @@ -4260,11 +4260,17 @@ **---------------------------------------------------- */ - segments = ncr_scatter (np, cp, cp->cmd); - - if (segments < 0) { - ncr_free_ccb(np, cp); - return(DID_ERROR); + direction = scsi_data_direction(cmd); + if (direction != SCSI_DATA_NONE) { + segments = ncr_scatter (np, cp, cp->cmd); + if (segments < 0) { + ncr_free_ccb(np, cp); + return(DID_ERROR); + } + } + else { + cp->data_len = 0; + segments = 0; } /*---------------------------------------------------- @@ -4275,8 +4281,6 @@ */ if (!cp->data_len) direction = SCSI_DATA_NONE; - else - direction = scsi_data_direction(cmd); /* ** If data direction is UNKNOWN, speculate DATA_READ @@ -4796,9 +4800,9 @@ #endif /* !NCR_IOMAPPED */ #ifdef DEBUG_NCR53C8XX - printk("%s: releasing IO region %x[%d]\n", ncr_name(np), np->port, 128); + printk("%s: releasing IO region %x[%d]\n", ncr_name(np), np->base_io, 128); #endif - release_region(np->port, 128); + release_region(np->base_io, 128); /* ** Free allocated ccb(s) diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/scsi/qlogicisp.c linux/drivers/scsi/qlogicisp.c --- v2.3.99-pre3/linux/drivers/scsi/qlogicisp.c Mon Mar 27 08:08:27 2000 +++ linux/drivers/scsi/qlogicisp.c Mon Mar 27 10:35:56 2000 @@ -1389,14 +1389,6 @@ return 1; } -#ifdef __sparc__ - command |= (PCI_COMMAND_MASTER|PCI_COMMAND_IO|PCI_COMMAND_MEMORY| - PCI_COMMAND_INVALIDATE|PCI_COMMAND_SERR); - pci_write_config_word(pdev, PCI_COMMAND, command); - pci_read_config_word(pdev, PCI_COMMAND, &command); - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 16); - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64); -#endif #ifdef __alpha__ /* Force ALPHA to use bus I/O and not bus MEM. This is to avoid having to use HAE_MEM registers, diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c --- v2.3.99-pre3/linux/drivers/scsi/scsi.c Mon Mar 27 08:08:27 2000 +++ linux/drivers/scsi/scsi.c Thu Mar 30 16:54:54 2000 @@ -1866,6 +1866,8 @@ * Nobody is using this device any more. * Free all of the command structures. */ + if (HBA_ptr->hostt->revoke) + HBA_ptr->hostt->revoke(scd); devfs_unregister (scd->de); scsi_release_commandblocks(scd); diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c --- v2.3.99-pre3/linux/drivers/scsi/sd.c Tue Mar 14 19:10:40 2000 +++ linux/drivers/scsi/sd.c Mon Mar 27 11:01:58 2000 @@ -120,7 +120,6 @@ struct Scsi_Host * host; Scsi_Device * SDev; int diskinfo[4]; - struct hd_geometry *loc = (struct hd_geometry *) arg; SDev = rscsi_disks[DEVICE_NR(dev)].device; /* @@ -138,6 +137,8 @@ switch (cmd) { case HDIO_GETGEO: /* Return BIOS disk parameters */ + { + struct hd_geometry *loc = (struct hd_geometry *) arg; if(!loc) return -EINVAL; @@ -164,6 +165,7 @@ put_user(sd[SD_PARTITION(inode->i_rdev)].start_sect, &loc->start)) return -EFAULT; return 0; + } case BLKGETSIZE: /* Return device size */ if (!arg) return -EINVAL; diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/scsi/sg.c linux/drivers/scsi/sg.c --- v2.3.99-pre3/linux/drivers/scsi/sg.c Tue Mar 7 14:32:26 2000 +++ linux/drivers/scsi/sg.c Mon Mar 27 10:48:23 2000 @@ -17,8 +17,8 @@ * any later version. * */ - static char * sg_version_str = "Version: 3.1.12 (20000222)"; - static int sg_version_num = 30112; /* 2 digits for each component */ + static char * sg_version_str = "Version: 3.1.13 (20000323)"; + static int sg_version_num = 30113; /* 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 @@ -66,8 +66,10 @@ #ifdef CONFIG_PROC_FS #include static int sg_proc_init(void); +#ifdef MODULE static void sg_proc_cleanup(void); #endif +#endif #ifndef LINUX_VERSION_CODE #include @@ -548,12 +550,16 @@ hp->cmd_len = (unsigned char)cmd_size; hp->iovec_count = 0; hp->mx_sb_len = 0; +#if 1 + hp->dxfer_direction = SG_DXFER_UNKNOWN; +#else if (input_size > 0) hp->dxfer_direction = ((old_hdr.reply_len - size_sg_header) > 0) ? SG_DXFER_TO_FROM_DEV : SG_DXFER_TO_DEV; else hp->dxfer_direction = (mxsize > 0) ? SG_DXFER_FROM_DEV : SG_DXFER_NONE; +#endif hp->dxfer_len = mxsize; hp->dxferp = (unsigned char *)buf + cmd_size; hp->sbp = NULL; @@ -671,6 +677,8 @@ SCpnt->sc_data_direction = SCSI_DATA_READ; break; case SG_DXFER_TO_DEV: SCpnt->sc_data_direction = SCSI_DATA_WRITE; break; + case SG_DXFER_UNKNOWN: + SCpnt->sc_data_direction = SCSI_DATA_UNKNOWN; break; default: SCpnt->sc_data_direction = SCSI_DATA_NONE; break; } @@ -1166,9 +1174,10 @@ for(k = 0; k < sg_template.dev_max; k++) if(! sg_dev_arr[k]) break; - if(k >= sg_template.dev_max) panic ("sg_dev_arr corrupt"); - - sdp = (Sg_device *)kmalloc(sizeof(Sg_device), GFP_ATOMIC); + if(k < sg_template.dev_max) + sdp = (Sg_device *)kmalloc(sizeof(Sg_device), GFP_ATOMIC); + else + sdp = NULL; if (NULL == sdp) { scsidp->attached--; write_unlock_irqrestore(&sg_dev_arr_lock, flags); @@ -1318,12 +1327,16 @@ Sg_fd * sfp = srp->parentfp; sg_io_hdr_t * hp = &srp->header; int dxfer_len = (int)hp->dxfer_len; + int dxfer_dir = hp->dxfer_direction; Sg_scatter_hold * req_schp = &srp->data; Sg_scatter_hold * rsv_schp = &sfp->reserve; SCSI_LOG_TIMEOUT(4, printk("sg_start_req: dxfer_len=%d\n", dxfer_len)); - if ((hp->flags & SG_FLAG_DIRECT_IO) && (dxfer_len > 0) && - (hp->dxfer_direction != SG_DXFER_NONE) && (0 == hp->iovec_count) && + if ((dxfer_len <= 0) || (dxfer_dir == SG_DXFER_NONE)) + return 0; + if ((hp->flags & SG_FLAG_DIRECT_IO) && + (dxfer_dir != SG_DXFER_UNKNOWN) && + (0 == hp->iovec_count) && (! sfp->parentdp->device->host->unchecked_isa_dma)) { res = sg_build_dir(srp, sfp, dxfer_len); if (res <= 0) /* -ve -> error, 0 -> done, 1 -> try indirect */ @@ -1563,12 +1576,13 @@ int num_xfer = 0; int j, k, onum, usglen, ksglen, res, ok; int iovec_count = (int)hp->iovec_count; + int dxfer_dir = hp->dxfer_direction; unsigned char * p; unsigned char * up; int new_interface = ('\0' == hp->interface_id) ? 0 : 1; - if ((SG_DXFER_TO_DEV == hp->dxfer_direction) || - (SG_DXFER_TO_FROM_DEV == hp->dxfer_direction)) { + if ((SG_DXFER_UNKNOWN == dxfer_dir) || (SG_DXFER_TO_DEV == dxfer_dir) || + (SG_DXFER_TO_FROM_DEV == dxfer_dir)) { num_xfer = (int)(new_interface ? hp->dxfer_len : hp->flags); if (schp->bufflen < num_xfer) num_xfer = schp->bufflen; @@ -1711,12 +1725,13 @@ int num_xfer = 0; int j, k, onum, usglen, ksglen, res, ok; int iovec_count = (int)hp->iovec_count; + int dxfer_dir = hp->dxfer_direction; unsigned char * p; unsigned char * up; int new_interface = ('\0' == hp->interface_id) ? 0 : 1; - if ((SG_DXFER_FROM_DEV == hp->dxfer_direction) || - (SG_DXFER_TO_FROM_DEV == hp->dxfer_direction)) { + if ((SG_DXFER_UNKNOWN == dxfer_dir) || (SG_DXFER_FROM_DEV == dxfer_dir) || + (SG_DXFER_TO_FROM_DEV == dxfer_dir)) { num_xfer = hp->dxfer_len; if (schp->bufflen < num_xfer) num_xfer = schp->bufflen; @@ -2445,6 +2460,7 @@ return 0; } +#ifdef MODULE static void sg_proc_cleanup() { int k; @@ -2456,6 +2472,7 @@ remove_proc_entry(sg_proc_leaf_names[k], sg_proc_sgp); remove_proc_entry(sg_proc_sg_dirname, proc_scsi); } +#endif static int sg_proc_dressz_read(char * buffer, char ** start, off_t offset, int size, int * eof, void * data) @@ -2505,7 +2522,7 @@ } read_lock(&sg_dev_arr_lock); max_dev = sg_last_dev(); - PRINT_PROC("dev_max=%d max_active_device=%d (origin 1)\n", + PRINT_PROC("dev_max(currently)=%d max_active_device=%d (origin 1)\n", sg_template.dev_max, max_dev); PRINT_PROC(" scsi_dma_free_sectors=%u sg_pool_secs_aval=%d " "def_reserved_size=%d\n", @@ -2523,12 +2540,13 @@ } dev = MINOR(sdp->i_rdev); - PRINT_PROC(" >>> device=%d(sg%d) ", dev, dev); - PRINT_PROC("scsi%d chan=%d id=%d lun=%d em=%d sg_tablesize=%d" + if ((fp = sdp->headfp)) { + PRINT_PROC(" >>> device=%d(sg%d) ", dev, dev); + PRINT_PROC("scsi%d chan=%d id=%d lun=%d em=%d sg_tablesize=%d" " excl=%d\n", scsidp->host->host_no, scsidp->channel, scsidp->id, scsidp->lun, scsidp->host->hostt->emulated, sdp->sg_tablesize, sdp->exclude); - fp = sdp->headfp; + } for (k = 1; fp; fp = fp->nextfp, ++k) { PRINT_PROC(" FD(%d): timeout=%d bufflen=%d " "(res)sgat=%d low_dma=%d\n", @@ -2543,13 +2561,13 @@ while (srp) { hp = &srp->header; /* stop indenting so far ... */ - PRINT_PROC(srp->res_used ? " reserved_buff>> " : + PRINT_PROC(srp->res_used ? " rb>> " : ((SG_INFO_DIRECT_IO_MASK & hp->info) ? " dio>> " : " ")); blen = srp->my_cmdp ? srp->my_cmdp->bufflen : srp->data.bufflen; usg = srp->my_cmdp ? srp->my_cmdp->use_sg : srp->data.k_use_sg; PRINT_PROC(srp->done ? "rcv: id=%d" : (srp->my_cmdp ? "act: id=%d" : "prior: id=%d"), srp->header.pack_id); - if (! srp->res_used) PRINT_PROC(" blen=%d", blen); + PRINT_PROC(" blen=%d", blen); if (srp->done) PRINT_PROC(" dur=%d", sg_jif_to_ms(hp->duration)); else diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/scsi/sym53c8xx.c linux/drivers/scsi/sym53c8xx.c --- v2.3.99-pre3/linux/drivers/scsi/sym53c8xx.c Tue Mar 14 19:10:40 2000 +++ linux/drivers/scsi/sym53c8xx.c Sat Apr 1 07:45:31 2000 @@ -84,7 +84,7 @@ /* ** Name and version of the driver */ -#define SCSI_NCR_DRIVER_NAME "sym53c8xx - version 1.5k" +#define SCSI_NCR_DRIVER_NAME "sym53c8xx - version 1.5l" /* #define DEBUG_896R1 */ #define SCSI_NCR_OPTIMIZE_896 @@ -6303,7 +6303,6 @@ lcb_p lp = ncr_lp(np, tp, cmd->lun); ccb_p cp; - int segments; u_char idmsg, *msgptr; u_int msglen; int direction; @@ -6452,11 +6451,17 @@ **---------------------------------------------------- */ - cp->segments = segments = np->scatter (np, cp, cp->cmd); - - if (segments < 0) { - ncr_free_ccb(np, cp); - return(DID_ERROR); + direction = scsi_data_direction(cmd); + if (direction != SCSI_DATA_NONE) { + cp->segments = np->scatter (np, cp, cp->cmd); + if (cp->segments < 0) { + ncr_free_ccb(np, cp); + return(DID_ERROR); + } + } + else { + cp->data_len = 0; + cp->segments = 0; } /*---------------------------------------------------- @@ -6467,8 +6472,6 @@ */ if (!cp->data_len) direction = SCSI_DATA_NONE; - else - direction = scsi_data_direction(cmd); /* ** If data direction is UNKNOWN, speculate DATA_READ @@ -6480,7 +6483,7 @@ case SCSI_DATA_UNKNOWN: case SCSI_DATA_WRITE: goalp = NCB_SCRIPT_PHYS (np, data_out2) + 8; - lastp = goalp - 8 - (segments * (SCR_SG_SIZE*4)); + lastp = goalp - 8 - (cp->segments * (SCR_SG_SIZE*4)); if (direction != SCSI_DATA_UNKNOWN) break; cp->phys.header.wgoalp = cpu_to_scr(goalp); @@ -6489,7 +6492,7 @@ case SCSI_DATA_READ: cp->host_flags |= HF_DATA_IN; goalp = NCB_SCRIPT_PHYS (np, data_in2) + 8; - lastp = goalp - 8 - (segments * (SCR_SG_SIZE*4)); + lastp = goalp - 8 - (cp->segments * (SCR_SG_SIZE*4)); break; default: case SCSI_DATA_NONE: @@ -12316,16 +12319,6 @@ } #endif #endif /* __powerpc__ */ - -#ifdef __sparc__ - /* - ** Fix-ups for sparc. - */ - if (!cache_line_size) - suggested_cache_line_size = 16; - - driver_setup.pci_fix_up |= 0x7; -#endif /* __sparc__ */ #if defined(__i386__) && !defined(MODULE) if (!cache_line_size) { diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/scsi/sym53c8xx_comm.h linux/drivers/scsi/sym53c8xx_comm.h --- v2.3.99-pre3/linux/drivers/scsi/sym53c8xx_comm.h Tue Mar 14 19:10:40 2000 +++ linux/drivers/scsi/sym53c8xx_comm.h Sat Apr 1 07:45:31 2000 @@ -2497,16 +2497,6 @@ #endif #endif /* __powerpc__ */ -#ifdef __sparc__ - /* - ** Fix-ups for sparc. - */ - if (!cache_line_size) - suggested_cache_line_size = 16; - - driver_setup.pci_fix_up |= 0x7; -#endif /* __sparc__ */ - #if defined(__i386__) && !defined(MODULE) if (!cache_line_size) { #if LINUX_VERSION_CODE < LinuxVersionCode(2,1,75) diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/scsi/wd33c93.c linux/drivers/scsi/wd33c93.c --- v2.3.99-pre3/linux/drivers/scsi/wd33c93.c Tue Nov 23 22:42:21 1999 +++ linux/drivers/scsi/wd33c93.c Mon Mar 27 09:48:11 2000 @@ -1638,7 +1638,7 @@ setup_used[i] = 0; done_setup = 1; - return 0; + return 1; } __setup("wd33c93", wd33c93_setup); diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/sound/Makefile linux/drivers/sound/Makefile --- v2.3.99-pre3/linux/drivers/sound/Makefile Sun Mar 19 18:35:30 2000 +++ linux/drivers/sound/Makefile Mon Apr 10 22:58:59 2000 @@ -35,7 +35,6 @@ # Each configuration option enables a list of files. obj-$(CONFIG_SOUND) += soundcore.o -obj-$(CONFIG_DMASOUND) += dmasound.o obj-$(CONFIG_SOUND_OSS) += sound.o obj-$(CONFIG_SOUND_CS4232) += cs4232.o ad1848.o @@ -81,6 +80,17 @@ obj-$(CONFIG_SOUND_MAESTRO) += maestro.o obj-$(CONFIG_SOUND_TRIDENT) += trident.o ac97_codec.o +ifeq ($(CONFIG_DMASOUND),y) + SUB_DIRS += dmasound + MOD_SUB_DIRS += dmasound + obj-y += dmasound/dmasound.o +else + ifeq ($(CONFIG_DMASOUND),m) + MOD_SUB_DIRS += dmasound + endif +endif + + # Declare multi-part drivers. list-multi := sound.o gus.o pas2.o sb.o sb_lib.o softoss2.o vidc_mod.o \ @@ -137,10 +147,6 @@ MX_OBJS := $(sort $(filter $(export-objs), $(obj-m))) MI_OBJS := $(sort $(filter-out $(export-objs), $(int-m))) MIX_OBJS := $(sort $(filter $(export-objs), $(int-m))) - -ifeq ($(CONFIG_LOWLEVEL_SOUND),y) - O_OBJS += lowlevel/lowlevel.o -endif include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/sound/ad1816.c linux/drivers/sound/ad1816.c --- v2.3.99-pre3/linux/drivers/sound/ad1816.c Sun Mar 19 18:35:30 2000 +++ linux/drivers/sound/ad1816.c Mon Mar 27 10:41:51 2000 @@ -1266,8 +1266,7 @@ static int __initdata dma2 = -1; #if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE -struct pci_dev *ad1816_dev = NULL, - *mpu_dev = NULL; +struct pci_dev *ad1816_dev = NULL; static int activated = 1; diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/sound/aedsp16.c linux/drivers/sound/aedsp16.c --- v2.3.99-pre3/linux/drivers/sound/aedsp16.c Fri Mar 10 16:40:44 2000 +++ linux/drivers/sound/aedsp16.c Mon Mar 27 09:48:11 2000 @@ -1383,6 +1383,7 @@ mss_base = ints[4]; mpu_base = ints[5]; mpu_irq = ints[6]; + return 1; } __setup("aedsp16=", setup_aedsp16); diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/sound/dev_table.c linux/drivers/sound/dev_table.c --- v2.3.99-pre3/linux/drivers/sound/dev_table.c Sun Mar 19 18:35:30 2000 +++ linux/drivers/sound/dev_table.c Sun Apr 2 15:45:06 2000 @@ -26,15 +26,13 @@ struct audio_operations *op; int l, num; - if (vers != AUDIO_DRIVER_VERSION || driver_size > sizeof(struct audio_driver)) - { + if (vers != AUDIO_DRIVER_VERSION || driver_size > sizeof(struct audio_driver)) { printk(KERN_ERR "Sound: Incompatible audio driver for %s\n", name); return -(EINVAL); } num = sound_alloc_audiodev(); - if (num == -1) - { + if (num == -1) { printk(KERN_ERR "sound: Too many audio drivers\n"); return -(EBUSY); } @@ -47,8 +45,7 @@ if (sound_nblocks < 1024) sound_nblocks++; - if (d == NULL || op == NULL) - { + if (d == NULL || op == NULL) { printk(KERN_ERR "Sound: Can't allocate driver for (%s)\n", name); sound_unload_audiodev(num); return -(ENOMEM); @@ -91,14 +88,12 @@ int n = sound_alloc_mixerdev(); - if (n == -1) - { + if (n == -1) { printk(KERN_ERR "Sound: Too many mixer drivers\n"); return -EBUSY; } if (vers != MIXER_DRIVER_VERSION || - driver_size > sizeof(struct mixer_operations)) - { + driver_size > sizeof(struct mixer_operations)) { printk(KERN_ERR "Sound: Incompatible mixer driver for %s\n", name); return -EINVAL; } @@ -110,8 +105,7 @@ if (sound_nblocks < 1024) sound_nblocks++; - if (op == NULL) - { + if (op == NULL) { printk(KERN_ERR "Sound: Can't allocate mixer driver for (%s)\n", name); return -ENOMEM; } @@ -131,8 +125,7 @@ void sound_unload_audiodev(int dev) { - if (dev != -1) - { + if (dev != -1) { DMAbuf_deinit(dev); audio_devs[dev] = NULL; unregister_sound_dsp((dev<<4)+3); @@ -165,10 +158,8 @@ { int i; - for (i = 0; i < MAX_SYNTH_DEV; i++) - { - if (synth_devs[i] == NULL) - { + for (i = 0; i < MAX_SYNTH_DEV; i++) { + if (synth_devs[i] == NULL) { if (i >= num_synths) num_synths++; return i; @@ -192,10 +183,8 @@ { int i; - for (i = 0; i < MAX_TIMER_DEV; i++) - { - if (sound_timer_devs[i] == NULL) - { + for (i = 0; i < MAX_TIMER_DEV; i++) { + if (sound_timer_devs[i] == NULL) { if (i >= num_sound_timers) num_sound_timers++; return i; @@ -206,8 +195,7 @@ void sound_unload_mixerdev(int dev) { - if (dev != -1) - { + if (dev != -1) { mixer_devs[dev] = NULL; unregister_sound_mixer(dev<<4); num_mixers--; @@ -216,8 +204,7 @@ void sound_unload_mididev(int dev) { - if (dev != -1) - { + if (dev != -1) { midi_devs[dev] = NULL; unregister_sound_midi((dev<<4)+2); } diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/sound/dev_table.h linux/drivers/sound/dev_table.h --- v2.3.99-pre3/linux/drivers/sound/dev_table.h Tue Mar 14 19:10:40 2000 +++ linux/drivers/sound/dev_table.h Sun Apr 2 15:45:06 2000 @@ -133,9 +133,6 @@ char neutral_byte; int dma; /* DMA channel */ -#ifdef OS_DMA_PARMS - OS_DMA_PARMS -#endif int applic_profile; /* Application profile (APF_*) */ /* Interrupt callback stuff */ void (*audio_callback) (int dev, int parm); @@ -347,7 +344,6 @@ }; #ifdef _DEV_TABLE_C_ - struct audio_operations *audio_devs[MAX_AUDIO_DEV] = {NULL}; int num_audiodevs = 0; struct mixer_operations *mixer_devs[MAX_MIXER_DEV] = {NULL}; @@ -356,21 +352,13 @@ int num_synths = 0; struct midi_operations *midi_devs[MAX_MIDI_DEV] = {NULL}; int num_midis = 0; -#ifndef EXCLUDE_TIMERS + extern struct sound_timer_operations default_sound_timer; struct sound_timer_operations *sound_timer_devs[MAX_TIMER_DEV] = { &default_sound_timer, NULL }; int num_sound_timers = 1; #else -struct sound_timer_operations *sound_timer_devs[MAX_TIMER_DEV] = { - NULL -}; -int num_sound_timers = 0; -#endif - - -#else extern struct audio_operations *audio_devs[MAX_AUDIO_DEV]; extern int num_audiodevs; extern struct mixer_operations *mixer_devs[MAX_MIXER_DEV]; @@ -384,8 +372,6 @@ #endif /* _DEV_TABLE_C_ */ extern int sound_map_buffer (int dev, struct dma_buffparms *dmap, buffmem_desc *info); -int sndtable_probe (int unit, struct address_info *hw_config); -int sndtable_start_card (int unit, struct address_info *hw_config); void sound_timer_init (struct sound_lowlev_timer *t, char *name); void sound_dma_intr (int dev, struct dma_buffparms *dmap, int chan); diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/sound/dmasound/Config.in linux/drivers/sound/dmasound/Config.in --- v2.3.99-pre3/linux/drivers/sound/dmasound/Config.in Wed Dec 31 16:00:00 1969 +++ linux/drivers/sound/dmasound/Config.in Mon Apr 10 22:58:59 2000 @@ -0,0 +1,27 @@ +# drivers/sound/dmasound/Config.in + +if [ "$CONFIG_ATARI" = "y" ]; then + dep_tristate ' Atari DMA sound support' CONFIG_DMASOUND_ATARI $CONFIG_SOUND +fi +if [ "$CONFIG_ALL_PPC" = "y" ]; then + dep_tristate ' PowerMac DMA sound support' CONFIG_DMASOUND_AWACS $CONFIG_SOUND +fi +if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_APUS" = "y" ]; then + dep_tristate ' Amiga DMA sound support' CONFIG_DMASOUND_PAULA $CONFIG_SOUND +fi +if [ "$CONFIG_Q40" = "y" ]; then + dep_tristate ' Q40 sound support' CONFIG_DMASOUND_Q40 $CONFIG_SOUND +fi +if [ "$CONFIG_DMASOUND_ATARI" = "y" -o \ + "$CONFIG_DMASOUND_AWACS" = "y" -o \ + "$CONFIG_DMASOUND_PAULA" = "y" -o \ + "$CONFIG_DMASOUND_Q40" = "y" ]; then + define_tristate CONFIG_DMASOUND y +else + if [ "$CONFIG_DMASOUND_ATARI" = "m" -o \ + "$CONFIG_DMASOUND_AWACS" = "m" -o \ + "$CONFIG_DMASOUND_PAULA" = "m" -o \ + "$CONFIG_DMASOUND_Q40" = "m" ]; then + define_tristate CONFIG_DMASOUND m + fi +fi diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/sound/dmasound/Makefile linux/drivers/sound/dmasound/Makefile --- v2.3.99-pre3/linux/drivers/sound/dmasound/Makefile Wed Dec 31 16:00:00 1969 +++ linux/drivers/sound/dmasound/Makefile Mon Apr 10 22:58:59 2000 @@ -0,0 +1,38 @@ +# +# Makefile for the DMA sound driver +# +# 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... + +O_TARGET := +O_OBJS := +OX_OBJS := +M_OBJS := +MX_OBJS := + +export-objs := dmasound_core.o + +obj-$(CONFIG_DMASOUND_ATARI) += dmasound_core.o dmasound_atari.o +obj-$(CONFIG_DMASOUND_AWACS) += dmasound_core.o dmasound_awacs.o +obj-$(CONFIG_DMASOUND_PAULA) += dmasound_core.o dmasound_paula.o +obj-$(CONFIG_DMASOUND_Q40) += dmasound_core.o dmasound_q40.o + +# Files that are both resident and modular: remove from modular. + +obj-m := $(filter-out $(obj-y), $(obj-m)) + +# Translate to Rules.make lists. + +O_OBJS := $(filter-out $(export-objs), $(obj-y)) +OX_OBJS := $(filter $(export-objs), $(obj-y)) +M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m))) +MX_OBJS := $(sort $(filter $(export-objs), $(obj-m))) + +ifeq ($(CONFIG_DMASOUND),y) + O_TARGET = dmasound.o +endif + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/sound/dmasound/dmasound.h linux/drivers/sound/dmasound/dmasound.h --- v2.3.99-pre3/linux/drivers/sound/dmasound/dmasound.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/sound/dmasound/dmasound.h Mon Apr 10 22:58:59 2000 @@ -0,0 +1,246 @@ + +/* + * linux/drivers/sound/dmasound.h + * + * + * Minor numbers for the sound driver. + * + * Unfortunately Creative called the codec chip of SB as a DSP. For this + * reason the /dev/dsp is reserved for digitized audio use. There is a + * device for true DSP processors but it will be called something else. + * In v3.0 it's /dev/sndproc but this could be a temporary solution. + */ + + +#include + + +#define SND_NDEVS 256 /* Number of supported devices */ +#define SND_DEV_CTL 0 /* Control port /dev/mixer */ +#define SND_DEV_SEQ 1 /* Sequencer output /dev/sequencer (FM + synthesizer and MIDI output) */ +#define SND_DEV_MIDIN 2 /* Raw midi access */ +#define SND_DEV_DSP 3 /* Digitized voice /dev/dsp */ +#define SND_DEV_AUDIO 4 /* Sparc compatible /dev/audio */ +#define SND_DEV_DSP16 5 /* Like /dev/dsp but 16 bits/sample */ +#define SND_DEV_STATUS 6 /* /dev/sndstat */ +/* #7 not in use now. Was in 2.4. Free for use after v3.0. */ +#define SND_DEV_SEQ2 8 /* /dev/sequencer, level 2 interface */ +#define SND_DEV_SNDPROC 9 /* /dev/sndproc for programmable devices */ +#define SND_DEV_PSS SND_DEV_SNDPROC + +#define DSP_DEFAULT_SPEED 8000 + +#define ON 1 +#define OFF 0 + +#define MAX_AUDIO_DEV 5 +#define MAX_MIXER_DEV 2 +#define MAX_SYNTH_DEV 3 +#define MAX_MIDI_DEV 6 +#define MAX_TIMER_DEV 3 + + +#define MAX_CATCH_RADIUS 10 +#define MIN_BUFFERS 4 +#define MIN_BUFSIZE 4 /* in KB */ +#define MAX_BUFSIZE 128 /* Limit for Amiga in KB */ + + +#define arraysize(x) (sizeof(x)/sizeof(*(x))) +#define min(x, y) ((x) < (y) ? (x) : (y)) +#define le2be16(x) (((x)<<8 & 0xff00) | ((x)>>8 & 0x00ff)) +#define le2be16dbl(x) (((x)<<8 & 0xff00ff00) | ((x)>>8 & 0x00ff00ff)) + +#define IOCTL_IN(arg, ret) \ + do { int error = get_user(ret, (int *)(arg)); \ + if (error) return error; \ + } while (0) +#define IOCTL_OUT(arg, ret) ioctl_return((int *)(arg), ret) + +static inline int ioctl_return(int *addr, int value) +{ + return value < 0 ? value : put_user(value, addr); +} + + + /* + * Configuration + */ + +#undef HAS_8BIT_TABLES +#undef HAS_14BIT_TABLES +#undef HAS_16BIT_TABLES +#undef HAS_RECORD + +#if defined(CONFIG_DMASOUND_ATARI) || defined(CONFIG_DMASOUND_ATARI_MODULE) ||\ + defined(CONFIG_DMASOUND_PAULA) || defined(CONFIG_DMASOUND_PAULA_MODULE) ||\ + defined(CONFIG_DMASOUND_Q40) || defined(CONFIG_DMASOUND_Q40_MODULE) +#define HAS_8BIT_TABLES +#endif +#if defined(CONFIG_DMASOUND_AWACS) || defined(CONFIG_DMASOUND_AWACS_MODULE) +#define HAS_16BIT_TABLES +#define HAS_RECORD +#endif + + + /* + * Initialization + */ + +extern int dmasound_init(void); +extern void dmasound_deinit(void); + + + /* + * Machine definitions + */ + +typedef struct { + const char *name; + const char *name2; + void (*open)(void); + void (*release)(void); + void *(*dma_alloc)(unsigned int, int); + void (*dma_free)(void *, unsigned int); + int (*irqinit)(void); +#ifdef MODULE + void (*irqcleanup)(void); +#endif /* MODULE */ + void (*init)(void); + void (*silence)(void); + int (*setFormat)(int); + int (*setVolume)(int); + int (*setBass)(int); + int (*setTreble)(int); + int (*setGain)(int); + void (*play)(void); + void (*record)(void); /* optional */ + void (*mixer_init)(void); /* optional */ + int (*mixer_ioctl)(u_int, u_long); /* optional */ + void (*write_sq_setup)(void); /* optional */ + void (*read_sq_setup)(void); /* optional */ + void (*sq_open)(void); /* optional */ + int (*state_info)(char *); /* optional */ + void (*abort_read)(void); /* optional */ + int min_dsp_speed; +} MACHINE; + + + /* + * Low level stuff + */ + +typedef struct { + int format; /* AFMT_* */ + int stereo; /* 0 = mono, 1 = stereo */ + int size; /* 8/16 bit*/ + int speed; /* speed */ +} SETTINGS; + +typedef struct { + ssize_t (*ct_ulaw)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); + ssize_t (*ct_alaw)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); + ssize_t (*ct_s8)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); + ssize_t (*ct_u8)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); + ssize_t (*ct_s16be)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); + ssize_t (*ct_u16be)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); + ssize_t (*ct_s16le)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); + ssize_t (*ct_u16le)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); +} TRANS; + +struct sound_settings { + MACHINE mach; /* machine dependent things */ + SETTINGS hard; /* hardware settings */ + SETTINGS soft; /* software settings */ + SETTINGS dsp; /* /dev/dsp default settings */ + TRANS *trans_write; /* supported translations */ +#ifdef HAS_RECORD + TRANS *trans_read; /* supported translations */ +#endif + int volume_left; /* volume (range is machine dependent) */ + int volume_right; + int bass; /* tone (range is machine dependent) */ + int treble; + int gain; + int minDev; /* minor device number currently open */ +}; + +extern struct sound_settings dmasound; + +extern char dmasound_ulaw2dma8[]; +extern char dmasound_alaw2dma8[]; +extern short dmasound_ulaw2dma16[]; +extern short dmasound_alaw2dma16[]; + + + /* + * Mid level stuff + */ + +static inline int dmasound_set_volume(int volume) +{ + return dmasound.mach.setVolume(volume); +} + +static inline int dmasound_set_bass(int bass) +{ + return dmasound.mach.setBass ? dmasound.mach.setBass(bass) : 50; +} + +static inline int dmasound_set_treble(int treble) +{ + return dmasound.mach.setTreble ? dmasound.mach.setTreble(treble) : 50; +} + +static inline int dmasound_set_gain(int gain) +{ + return dmasound.mach.setGain ? dmasound.mach.setGain(gain) : 100; +} + + + /* + * Sound queue stuff, the heart of the driver + */ + +struct sound_queue { + /* buffers allocated for this queue */ + int numBufs; + int bufSize; /* in bytes */ + char **buffers; + + /* current parameters */ + int max_count; + int block_size; /* in bytes */ + int max_active; + + /* it shouldn't be necessary to declare any of these volatile */ + int front, rear, count; + int rear_size; + /* + * The use of the playing field depends on the hardware + * + * Atari, PMac: The number of frames that are loaded/playing + * + * Amiga: Bit 0 is set: a frame is loaded + * Bit 1 is set: a frame is playing + */ + int active; + wait_queue_head_t action_queue, open_queue, sync_queue; + int open_mode; + int busy, syncing; +}; + +#define SLEEP(queue) interruptible_sleep_on_timeout(&queue, HZ) +#define WAKE_UP(queue) (wake_up_interruptible(&queue)) + +extern struct sound_queue dmasound_write_sq; +extern struct sound_queue dmasound_read_sq; + +#define write_sq dmasound_write_sq +#define read_sq dmasound_read_sq + +extern int dmasound_catchRadius; + +#define catchRadius dmasound_catchRadius + diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/sound/dmasound/dmasound_atari.c linux/drivers/sound/dmasound/dmasound_atari.c --- v2.3.99-pre3/linux/drivers/sound/dmasound/dmasound_atari.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/sound/dmasound/dmasound_atari.c Mon Apr 10 22:58:59 2000 @@ -0,0 +1,1560 @@ + +/* + * linux/drivers/sound/dmasound_atari.c + * + * Atari DMA Sound Driver + * + * See linux/drivers/sound/dmasound_core.c for copyright and credits + */ + + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "dmasound.h" + + +extern void atari_microwire_cmd(int cmd); + + +static int is_falcon; +static int write_sq_ignore_int = 0; /* ++TeSche: used for Falcon */ + +static int expand_bal; /* Balance factor for expanding (not volume!) */ +static int expand_data; /* Data for expanding */ + + +/*** Translations ************************************************************/ + + +/* ++TeSche: radically changed for new expanding purposes... + * + * These two routines now deal with copying/expanding/translating the samples + * from user space into our buffer at the right frequency. They take care about + * how much data there's actually to read, how much buffer space there is and + * to convert samples into the right frequency/encoding. They will only work on + * complete samples so it may happen they leave some bytes in the input stream + * if the user didn't write a multiple of the current sample size. They both + * return the number of bytes they've used from both streams so you may detect + * such a situation. Luckily all programs should be able to cope with that. + * + * I think I've optimized anything as far as one can do in plain C, all + * variables should fit in registers and the loops are really short. There's + * one loop for every possible situation. Writing a more generalized and thus + * parameterized loop would only produce slower code. Feel free to optimize + * this in assembler if you like. :) + * + * I think these routines belong here because they're not yet really hardware + * independent, especially the fact that the Falcon can play 16bit samples + * only in stereo is hardcoded in both of them! + * + * ++geert: split in even more functions (one per format) + */ + +static ssize_t ata_ct_law(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t ata_ct_s8(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t ata_ct_u8(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t ata_ct_s16be(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t ata_ct_u16be(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t ata_ct_s16le(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t ata_ct_u16le(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t ata_ctx_law(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t ata_ctx_s8(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t ata_ctx_u8(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t ata_ctx_s16be(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t ata_ctx_u16be(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t ata_ctx_s16le(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t ata_ctx_u16le(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); + + +/*** Low level stuff *********************************************************/ + + +static void AtaOpen(void); +static void AtaRelease(void); +static void *AtaAlloc(unsigned int size, int flags); +static void AtaFree(void *, unsigned int size); +static int AtaIrqInit(void); +#ifdef MODULE +static void AtaIrqCleanUp(void); +#endif /* MODULE */ +static int AtaSetBass(int bass); +static int AtaSetTreble(int treble); +static void TTSilence(void); +static void TTInit(void); +static int TTSetFormat(int format); +static int TTSetVolume(int volume); +static int TTSetGain(int gain); +static void FalconSilence(void); +static void FalconInit(void); +static int FalconSetFormat(int format); +static int FalconSetVolume(int volume); +static void AtaPlayNextFrame(int index); +static void AtaPlay(void); +static void AtaInterrupt(int irq, void *dummy, struct pt_regs *fp); + +/*** Mid level stuff *********************************************************/ + +static void TTMixerInit(void); +static void FalconMixerInit(void); +static int AtaMixerIoctl(u_int cmd, u_long arg); +static int TTMixerIoctl(u_int cmd, u_long arg); +static int FalconMixerIoctl(u_int cmd, u_long arg); +static void AtaWriteSqSetup(void); +static void AtaSqOpen(void); +static int TTStateInfo(char *buffer); +static int FalconStateInfo(char *buffer); + + +/*** Translations ************************************************************/ + + +static ssize_t ata_ct_law(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + char *table = dmasound.soft.format == AFMT_MU_LAW ? dmasound_ulaw2dma8 + : dmasound_alaw2dma8; + ssize_t count, used; + u_char *p = &frame[*frameUsed]; + + count = min(userCount, frameLeft); + if (dmasound.soft.stereo) + count &= ~1; + used = count; + while (count > 0) { + u_char data; + if (get_user(data, userPtr++)) + return -EFAULT; + *p++ = table[data]; + count--; + } + *frameUsed += used; + return used; +} + + +static ssize_t ata_ct_s8(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + ssize_t count, used; + void *p = &frame[*frameUsed]; + + count = min(userCount, frameLeft); + if (dmasound.soft.stereo) + count &= ~1; + used = count; + if (copy_from_user(p, userPtr, count)) + return -EFAULT; + *frameUsed += used; + return used; +} + + +static ssize_t ata_ct_u8(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + ssize_t count, used; + + if (!dmasound.soft.stereo) { + u_char *p = &frame[*frameUsed]; + count = min(userCount, frameLeft); + used = count; + while (count > 0) { + u_char data; + if (get_user(data, userPtr++)) + return -EFAULT; + *p++ = data ^ 0x80; + count--; + } + } else { + u_short *p = (u_short *)&frame[*frameUsed]; + count = min(userCount, frameLeft)>>1; + used = count*2; + while (count > 0) { + u_short data; + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + *p++ = data ^ 0x8080; + count--; + } + } + *frameUsed += used; + return used; +} + + +static ssize_t ata_ct_s16be(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + ssize_t count, used; + + if (!dmasound.soft.stereo) { + u_short *p = (u_short *)&frame[*frameUsed]; + count = min(userCount, frameLeft)>>1; + used = count*2; + while (count > 0) { + u_short data; + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + *p++ = data; + *p++ = data; + count--; + } + *frameUsed += used*2; + } else { + void *p = (u_short *)&frame[*frameUsed]; + count = min(userCount, frameLeft) & ~3; + used = count; + if (copy_from_user(p, userPtr, count)) + return -EFAULT; + *frameUsed += used; + } + return used; +} + + +static ssize_t ata_ct_u16be(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + ssize_t count, used; + + if (!dmasound.soft.stereo) { + u_short *p = (u_short *)&frame[*frameUsed]; + count = min(userCount, frameLeft)>>1; + used = count*2; + while (count > 0) { + u_short data; + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + data ^= 0x8000; + *p++ = data; + *p++ = data; + count--; + } + *frameUsed += used*2; + } else { + u_long *p = (u_long *)&frame[*frameUsed]; + count = min(userCount, frameLeft)>>2; + used = count*4; + while (count > 0) { + u_long data; + if (get_user(data, ((u_int *)userPtr)++)) + return -EFAULT; + *p++ = data ^ 0x80008000; + count--; + } + *frameUsed += used; + } + return used; +} + + +static ssize_t ata_ct_s16le(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + ssize_t count, used; + + count = frameLeft; + if (!dmasound.soft.stereo) { + u_short *p = (u_short *)&frame[*frameUsed]; + count = min(userCount, frameLeft)>>1; + used = count*2; + while (count > 0) { + u_short data; + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + data = le2be16(data); + *p++ = data; + *p++ = data; + count--; + } + *frameUsed += used*2; + } else { + u_long *p = (u_long *)&frame[*frameUsed]; + count = min(userCount, frameLeft)>>2; + used = count*4; + while (count > 0) { + u_long data; + if (get_user(data, ((u_int *)userPtr)++)) + return -EFAULT; + data = le2be16dbl(data); + *p++ = data; + count--; + } + *frameUsed += used; + } + return used; +} + + +static ssize_t ata_ct_u16le(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + ssize_t count, used; + + count = frameLeft; + if (!dmasound.soft.stereo) { + u_short *p = (u_short *)&frame[*frameUsed]; + count = min(userCount, frameLeft)>>1; + used = count*2; + while (count > 0) { + u_short data; + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + data = le2be16(data) ^ 0x8000; + *p++ = data; + *p++ = data; + } + *frameUsed += used*2; + } else { + u_long *p = (u_long *)&frame[*frameUsed]; + count = min(userCount, frameLeft)>>2; + used = count; + while (count > 0) { + u_long data; + if (get_user(data, ((u_int *)userPtr)++)) + return -EFAULT; + data = le2be16dbl(data) ^ 0x80008000; + *p++ = data; + count--; + } + *frameUsed += used; + } + return used; +} + + +static ssize_t ata_ctx_law(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + char *table = dmasound.soft.format == AFMT_MU_LAW ? dmasound_ulaw2dma8 + : dmasound_alaw2dma8; + /* this should help gcc to stuff everything into registers */ + long bal = expand_bal; + long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; + ssize_t used, usedf; + + used = userCount; + usedf = frameLeft; + if (!dmasound.soft.stereo) { + u_char *p = &frame[*frameUsed]; + u_char data = expand_data; + while (frameLeft) { + u_char c; + if (bal < 0) { + if (!userCount) + break; + if (get_user(c, userPtr++)) + return -EFAULT; + data = table[c]; + userCount--; + bal += hSpeed; + } + *p++ = data; + frameLeft--; + bal -= sSpeed; + } + expand_data = data; + } else { + u_short *p = (u_short *)&frame[*frameUsed]; + u_short data = expand_data; + while (frameLeft >= 2) { + u_char c; + if (bal < 0) { + if (userCount < 2) + break; + if (get_user(c, userPtr++)) + return -EFAULT; + data = table[c] << 8; + if (get_user(c, userPtr++)) + return -EFAULT; + data |= table[c]; + userCount -= 2; + bal += hSpeed; + } + *p++ = data; + frameLeft -= 2; + bal -= sSpeed; + } + expand_data = data; + } + expand_bal = bal; + used -= userCount; + *frameUsed += usedf-frameLeft; + return used; +} + + +static ssize_t ata_ctx_s8(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + /* this should help gcc to stuff everything into registers */ + long bal = expand_bal; + long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; + ssize_t used, usedf; + + used = userCount; + usedf = frameLeft; + if (!dmasound.soft.stereo) { + u_char *p = &frame[*frameUsed]; + u_char data = expand_data; + while (frameLeft) { + if (bal < 0) { + if (!userCount) + break; + if (get_user(data, userPtr++)) + return -EFAULT; + userCount--; + bal += hSpeed; + } + *p++ = data; + frameLeft--; + bal -= sSpeed; + } + expand_data = data; + } else { + u_short *p = (u_short *)&frame[*frameUsed]; + u_short data = expand_data; + while (frameLeft >= 2) { + if (bal < 0) { + if (userCount < 2) + break; + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + userCount -= 2; + bal += hSpeed; + } + *p++ = data; + frameLeft -= 2; + bal -= sSpeed; + } + expand_data = data; + } + expand_bal = bal; + used -= userCount; + *frameUsed += usedf-frameLeft; + return used; +} + + +static ssize_t ata_ctx_u8(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + /* this should help gcc to stuff everything into registers */ + long bal = expand_bal; + long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; + ssize_t used, usedf; + + used = userCount; + usedf = frameLeft; + if (!dmasound.soft.stereo) { + u_char *p = &frame[*frameUsed]; + u_char data = expand_data; + while (frameLeft) { + if (bal < 0) { + if (!userCount) + break; + if (get_user(data, userPtr++)) + return -EFAULT; + data ^= 0x80; + userCount--; + bal += hSpeed; + } + *p++ = data; + frameLeft--; + bal -= sSpeed; + } + expand_data = data; + } else { + u_short *p = (u_short *)&frame[*frameUsed]; + u_short data = expand_data; + while (frameLeft >= 2) { + if (bal < 0) { + if (userCount < 2) + break; + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + data ^= 0x8080; + userCount -= 2; + bal += hSpeed; + } + *p++ = data; + frameLeft -= 2; + bal -= sSpeed; + } + expand_data = data; + } + expand_bal = bal; + used -= userCount; + *frameUsed += usedf-frameLeft; + return used; +} + + +static ssize_t ata_ctx_s16be(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + /* this should help gcc to stuff everything into registers */ + long bal = expand_bal; + long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; + ssize_t used, usedf; + + used = userCount; + usedf = frameLeft; + if (!dmasound.soft.stereo) { + u_short *p = (u_short *)&frame[*frameUsed]; + u_short data = expand_data; + while (frameLeft >= 4) { + if (bal < 0) { + if (userCount < 2) + break; + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + userCount -= 2; + bal += hSpeed; + } + *p++ = data; + *p++ = data; + frameLeft -= 4; + bal -= sSpeed; + } + expand_data = data; + } else { + u_long *p = (u_long *)&frame[*frameUsed]; + u_long data = expand_data; + while (frameLeft >= 4) { + if (bal < 0) { + if (userCount < 4) + break; + if (get_user(data, ((u_int *)userPtr)++)) + return -EFAULT; + userCount -= 4; + bal += hSpeed; + } + *p++ = data; + frameLeft -= 4; + bal -= sSpeed; + } + expand_data = data; + } + expand_bal = bal; + used -= userCount; + *frameUsed += usedf-frameLeft; + return used; +} + + +static ssize_t ata_ctx_u16be(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + /* this should help gcc to stuff everything into registers */ + long bal = expand_bal; + long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; + ssize_t used, usedf; + + used = userCount; + usedf = frameLeft; + if (!dmasound.soft.stereo) { + u_short *p = (u_short *)&frame[*frameUsed]; + u_short data = expand_data; + while (frameLeft >= 4) { + if (bal < 0) { + if (userCount < 2) + break; + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + data ^= 0x8000; + userCount -= 2; + bal += hSpeed; + } + *p++ = data; + *p++ = data; + frameLeft -= 4; + bal -= sSpeed; + } + expand_data = data; + } else { + u_long *p = (u_long *)&frame[*frameUsed]; + u_long data = expand_data; + while (frameLeft >= 4) { + if (bal < 0) { + if (userCount < 4) + break; + if (get_user(data, ((u_int *)userPtr)++)) + return -EFAULT; + data ^= 0x80008000; + userCount -= 4; + bal += hSpeed; + } + *p++ = data; + frameLeft -= 4; + bal -= sSpeed; + } + expand_data = data; + } + expand_bal = bal; + used -= userCount; + *frameUsed += usedf-frameLeft; + return used; +} + + +static ssize_t ata_ctx_s16le(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + /* this should help gcc to stuff everything into registers */ + long bal = expand_bal; + long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; + ssize_t used, usedf; + + used = userCount; + usedf = frameLeft; + if (!dmasound.soft.stereo) { + u_short *p = (u_short *)&frame[*frameUsed]; + u_short data = expand_data; + while (frameLeft >= 4) { + if (bal < 0) { + if (userCount < 2) + break; + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + data = le2be16(data); + userCount -= 2; + bal += hSpeed; + } + *p++ = data; + *p++ = data; + frameLeft -= 4; + bal -= sSpeed; + } + expand_data = data; + } else { + u_long *p = (u_long *)&frame[*frameUsed]; + u_long data = expand_data; + while (frameLeft >= 4) { + if (bal < 0) { + if (userCount < 4) + break; + if (get_user(data, ((u_int *)userPtr)++)) + return -EFAULT; + data = le2be16dbl(data); + userCount -= 4; + bal += hSpeed; + } + *p++ = data; + frameLeft -= 4; + bal -= sSpeed; + } + expand_data = data; + } + expand_bal = bal; + used -= userCount; + *frameUsed += usedf-frameLeft; + return used; +} + + +static ssize_t ata_ctx_u16le(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + /* this should help gcc to stuff everything into registers */ + long bal = expand_bal; + long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; + ssize_t used, usedf; + + used = userCount; + usedf = frameLeft; + if (!dmasound.soft.stereo) { + u_short *p = (u_short *)&frame[*frameUsed]; + u_short data = expand_data; + while (frameLeft >= 4) { + if (bal < 0) { + if (userCount < 2) + break; + if (get_user(data, ((u_short *)userPtr)++)) + return -EFAULT; + data = le2be16(data) ^ 0x8000; + userCount -= 2; + bal += hSpeed; + } + *p++ = data; + *p++ = data; + frameLeft -= 4; + bal -= sSpeed; + } + expand_data = data; + } else { + u_long *p = (u_long *)&frame[*frameUsed]; + u_long data = expand_data; + while (frameLeft >= 4) { + if (bal < 0) { + if (userCount < 4) + break; + if (get_user(data, ((u_int *)userPtr)++)) + return -EFAULT; + data = le2be16dbl(data) ^ 0x80008000; + userCount -= 4; + bal += hSpeed; + } + *p++ = data; + frameLeft -= 4; + bal -= sSpeed; + } + expand_data = data; + } + expand_bal = bal; + used -= userCount; + *frameUsed += usedf-frameLeft; + return used; +} + + +static TRANS transTTNormal = { + ct_ulaw: ata_ct_law, + ct_alaw: ata_ct_law, + ct_s8: ata_ct_s8, + ct_u8: ata_ct_u8, +}; + +static TRANS transTTExpanding = { + ct_ulaw: ata_ctx_law, + ct_alaw: ata_ctx_law, + ct_s8: ata_ctx_s8, + ct_u8: ata_ctx_u8, +}; + +static TRANS transFalconNormal = { + ct_ulaw: ata_ct_law, + ct_alaw: ata_ct_law, + ct_s8: ata_ct_s8, + ct_u8: ata_ct_u8, + ct_s16be: ata_ct_s16be, + ct_u16be: ata_ct_u16be, + ct_s16le: ata_ct_s16le, + ct_u16le: ata_ct_u16le +}; + +static TRANS transFalconExpanding = { + ct_ulaw: ata_ctx_law, + ct_alaw: ata_ctx_law, + ct_s8: ata_ctx_s8, + ct_u8: ata_ctx_u8, + ct_s16be: ata_ctx_s16be, + ct_u16be: ata_ctx_u16be, + ct_s16le: ata_ctx_s16le, + ct_u16le: ata_ctx_u16le, +}; + + +/*** Low level stuff *********************************************************/ + + + +/* + * Atari (TT/Falcon) + */ + +static void AtaOpen(void) +{ + MOD_INC_USE_COUNT; +} + +static void AtaRelease(void) +{ + MOD_DEC_USE_COUNT; +} + +static void *AtaAlloc(unsigned int size, int flags) +{ + return atari_stram_alloc( size, NULL, "dmasound" ); +} + +static void AtaFree(void *obj, unsigned int size) +{ + atari_stram_free( obj ); +} + +static int __init AtaIrqInit(void) +{ + /* Set up timer A. Timer A + will receive a signal upon end of playing from the sound + hardware. Furthermore Timer A is able to count events + and will cause an interrupt after a programmed number + of events. So all we need to keep the music playing is + to provide the sound hardware with new data upon + an interrupt from timer A. */ + mfp.tim_ct_a = 0; /* ++roman: Stop timer before programming! */ + mfp.tim_dt_a = 1; /* Cause interrupt after first event. */ + mfp.tim_ct_a = 8; /* Turn on event counting. */ + /* Register interrupt handler. */ + request_irq(IRQ_MFP_TIMA, AtaInterrupt, IRQ_TYPE_SLOW, "DMA sound", + AtaInterrupt); + mfp.int_en_a |= 0x20; /* Turn interrupt on. */ + mfp.int_mk_a |= 0x20; + return 1; +} + +#ifdef MODULE +static void AtaIrqCleanUp(void) +{ + mfp.tim_ct_a = 0; /* stop timer */ + mfp.int_en_a &= ~0x20; /* turn interrupt off */ + free_irq(IRQ_MFP_TIMA, AtaInterrupt); +} +#endif /* MODULE */ + + +#define TONE_VOXWARE_TO_DB(v) \ + (((v) < 0) ? -12 : ((v) > 100) ? 12 : ((v) - 50) * 6 / 25) +#define TONE_DB_TO_VOXWARE(v) (((v) * 25 + ((v) > 0 ? 5 : -5)) / 6 + 50) + + +static int AtaSetBass(int bass) +{ + dmasound.bass = TONE_VOXWARE_TO_DB(bass); + atari_microwire_cmd(MW_LM1992_BASS(dmasound.bass)); + return TONE_DB_TO_VOXWARE(dmasound.bass); +} + + +static int AtaSetTreble(int treble) +{ + dmasound.treble = TONE_VOXWARE_TO_DB(treble); + atari_microwire_cmd(MW_LM1992_TREBLE(dmasound.treble)); + return TONE_DB_TO_VOXWARE(dmasound.treble); +} + + + +/* + * TT + */ + + +static void TTSilence(void) +{ + tt_dmasnd.ctrl = DMASND_CTRL_OFF; + atari_microwire_cmd(MW_LM1992_PSG_HIGH); /* mix in PSG signal 1:1 */ +} + + +static void TTInit(void) +{ + int mode, i, idx; + const int freq[4] = {50066, 25033, 12517, 6258}; + + /* search a frequency that fits into the allowed error range */ + + idx = -1; + for (i = 0; i < arraysize(freq); i++) + /* this isn't as much useful for a TT than for a Falcon, but + * then it doesn't hurt very much to implement it for a TT too. + */ + if ((100 * abs(dmasound.soft.speed - freq[i]) / freq[i]) < catchRadius) + idx = i; + if (idx > -1) { + dmasound.soft.speed = freq[idx]; + dmasound.trans_write = &transTTNormal; + } else + dmasound.trans_write = &transTTExpanding; + + TTSilence(); + dmasound.hard = dmasound.soft; + + if (dmasound.hard.speed > 50066) { + /* we would need to squeeze the sound, but we won't do that */ + dmasound.hard.speed = 50066; + mode = DMASND_MODE_50KHZ; + dmasound.trans_write = &transTTNormal; + } else if (dmasound.hard.speed > 25033) { + dmasound.hard.speed = 50066; + mode = DMASND_MODE_50KHZ; + } else if (dmasound.hard.speed > 12517) { + dmasound.hard.speed = 25033; + mode = DMASND_MODE_25KHZ; + } else if (dmasound.hard.speed > 6258) { + dmasound.hard.speed = 12517; + mode = DMASND_MODE_12KHZ; + } else { + dmasound.hard.speed = 6258; + mode = DMASND_MODE_6KHZ; + } + + tt_dmasnd.mode = (dmasound.hard.stereo ? + DMASND_MODE_STEREO : DMASND_MODE_MONO) | + DMASND_MODE_8BIT | mode; + + expand_bal = -dmasound.soft.speed; +} + + +static int TTSetFormat(int format) +{ + /* TT sound DMA supports only 8bit modes */ + + switch (format) { + case AFMT_QUERY: + return dmasound.soft.format; + case AFMT_MU_LAW: + case AFMT_A_LAW: + case AFMT_S8: + case AFMT_U8: + break; + default: + format = AFMT_S8; + } + + dmasound.soft.format = format; + dmasound.soft.size = 8; + if (dmasound.minDev == SND_DEV_DSP) { + dmasound.dsp.format = format; + dmasound.dsp.size = 8; + } + TTInit(); + + return format; +} + + +#define VOLUME_VOXWARE_TO_DB(v) \ + (((v) < 0) ? -40 : ((v) > 100) ? 0 : ((v) * 2) / 5 - 40) +#define VOLUME_DB_TO_VOXWARE(v) ((((v) + 40) * 5 + 1) / 2) + + +static int TTSetVolume(int volume) +{ + dmasound.volume_left = VOLUME_VOXWARE_TO_DB(volume & 0xff); + atari_microwire_cmd(MW_LM1992_BALLEFT(dmasound.volume_left)); + dmasound.volume_right = VOLUME_VOXWARE_TO_DB((volume & 0xff00) >> 8); + atari_microwire_cmd(MW_LM1992_BALRIGHT(dmasound.volume_right)); + return VOLUME_DB_TO_VOXWARE(dmasound.volume_left) | + (VOLUME_DB_TO_VOXWARE(dmasound.volume_right) << 8); +} + + +#define GAIN_VOXWARE_TO_DB(v) \ + (((v) < 0) ? -80 : ((v) > 100) ? 0 : ((v) * 4) / 5 - 80) +#define GAIN_DB_TO_VOXWARE(v) ((((v) + 80) * 5 + 1) / 4) + +static int TTSetGain(int gain) +{ + dmasound.gain = GAIN_VOXWARE_TO_DB(gain); + atari_microwire_cmd(MW_LM1992_VOLUME(dmasound.gain)); + return GAIN_DB_TO_VOXWARE(dmasound.gain); +} + + + +/* + * Falcon + */ + + +static void FalconSilence(void) +{ + /* stop playback, set sample rate 50kHz for PSG sound */ + tt_dmasnd.ctrl = DMASND_CTRL_OFF; + tt_dmasnd.mode = DMASND_MODE_50KHZ | DMASND_MODE_STEREO | DMASND_MODE_8BIT; + tt_dmasnd.int_div = 0; /* STE compatible divider */ + tt_dmasnd.int_ctrl = 0x0; + tt_dmasnd.cbar_src = 0x0000; /* no matrix inputs */ + tt_dmasnd.cbar_dst = 0x0000; /* no matrix outputs */ + tt_dmasnd.dac_src = 1; /* connect ADC to DAC, disconnect matrix */ + tt_dmasnd.adc_src = 3; /* ADC Input = PSG */ +} + + +static void FalconInit(void) +{ + int divider, i, idx; + const int freq[8] = {49170, 32780, 24585, 19668, 16390, 12292, 9834, 8195}; + + /* search a frequency that fits into the allowed error range */ + + idx = -1; + for (i = 0; i < arraysize(freq); i++) + /* if we will tolerate 3% error 8000Hz->8195Hz (2.38%) would + * be playable without expanding, but that now a kernel runtime + * option + */ + if ((100 * abs(dmasound.soft.speed - freq[i]) / freq[i]) < catchRadius) + idx = i; + if (idx > -1) { + dmasound.soft.speed = freq[idx]; + dmasound.trans_write = &transFalconNormal; + } else + dmasound.trans_write = &transFalconExpanding; + + FalconSilence(); + dmasound.hard = dmasound.soft; + + if (dmasound.hard.size == 16) { + /* the Falcon can play 16bit samples only in stereo */ + dmasound.hard.stereo = 1; + } + + if (dmasound.hard.speed > 49170) { + /* we would need to squeeze the sound, but we won't do that */ + dmasound.hard.speed = 49170; + divider = 1; + dmasound.trans_write = &transFalconNormal; + } else if (dmasound.hard.speed > 32780) { + dmasound.hard.speed = 49170; + divider = 1; + } else if (dmasound.hard.speed > 24585) { + dmasound.hard.speed = 32780; + divider = 2; + } else if (dmasound.hard.speed > 19668) { + dmasound.hard.speed = 24585; + divider = 3; + } else if (dmasound.hard.speed > 16390) { + dmasound.hard.speed = 19668; + divider = 4; + } else if (dmasound.hard.speed > 12292) { + dmasound.hard.speed = 16390; + divider = 5; + } else if (dmasound.hard.speed > 9834) { + dmasound.hard.speed = 12292; + divider = 7; + } else if (dmasound.hard.speed > 8195) { + dmasound.hard.speed = 9834; + divider = 9; + } else { + dmasound.hard.speed = 8195; + divider = 11; + } + tt_dmasnd.int_div = divider; + + /* Setup Falcon sound DMA for playback */ + tt_dmasnd.int_ctrl = 0x4; /* Timer A int at play end */ + tt_dmasnd.track_select = 0x0; /* play 1 track, track 1 */ + tt_dmasnd.cbar_src = 0x0001; /* DMA(25MHz) --> DAC */ + tt_dmasnd.cbar_dst = 0x0000; + tt_dmasnd.rec_track_select = 0; + tt_dmasnd.dac_src = 2; /* connect matrix to DAC */ + tt_dmasnd.adc_src = 0; /* ADC Input = Mic */ + + tt_dmasnd.mode = (dmasound.hard.stereo ? + DMASND_MODE_STEREO : DMASND_MODE_MONO) | + ((dmasound.hard.size == 8) ? + DMASND_MODE_8BIT : DMASND_MODE_16BIT) | + DMASND_MODE_6KHZ; + + expand_bal = -dmasound.soft.speed; +} + + +static int FalconSetFormat(int format) +{ + int size; + /* Falcon sound DMA supports 8bit and 16bit modes */ + + switch (format) { + case AFMT_QUERY: + return dmasound.soft.format; + case AFMT_MU_LAW: + case AFMT_A_LAW: + case AFMT_U8: + case AFMT_S8: + size = 8; + break; + case AFMT_S16_BE: + case AFMT_U16_BE: + case AFMT_S16_LE: + case AFMT_U16_LE: + size = 16; + break; + default: /* :-) */ + size = 8; + format = AFMT_S8; + } + + dmasound.soft.format = format; + dmasound.soft.size = size; + if (dmasound.minDev == SND_DEV_DSP) { + dmasound.dsp.format = format; + dmasound.dsp.size = dmasound.soft.size; + } + + FalconInit(); + + return format; +} + + +/* This is for the Falcon output *attenuation* in 1.5dB steps, + * i.e. output level from 0 to -22.5dB in -1.5dB steps. + */ +#define VOLUME_VOXWARE_TO_ATT(v) \ + ((v) < 0 ? 15 : (v) > 100 ? 0 : 15 - (v) * 3 / 20) +#define VOLUME_ATT_TO_VOXWARE(v) (100 - (v) * 20 / 3) + + +static int FalconSetVolume(int volume) +{ + dmasound.volume_left = VOLUME_VOXWARE_TO_ATT(volume & 0xff); + dmasound.volume_right = VOLUME_VOXWARE_TO_ATT((volume & 0xff00) >> 8); + tt_dmasnd.output_atten = dmasound.volume_left << 8 | dmasound.volume_right << 4; + return VOLUME_ATT_TO_VOXWARE(dmasound.volume_left) | + VOLUME_ATT_TO_VOXWARE(dmasound.volume_right) << 8; +} + + +static void AtaPlayNextFrame(int index) +{ + char *start, *end; + + /* used by AtaPlay() if all doubts whether there really is something + * to be played are already wiped out. + */ + start = write_sq.buffers[write_sq.front]; + end = start+((write_sq.count == index) ? write_sq.rear_size + : write_sq.block_size); + /* end might not be a legal virtual address. */ + DMASNDSetEnd(virt_to_phys(end - 1) + 1); + DMASNDSetBase(virt_to_phys(start)); + /* Since only an even number of samples per frame can + be played, we might lose one byte here. (TO DO) */ + write_sq.front = (write_sq.front+1) % write_sq.max_count; + write_sq.active++; + tt_dmasnd.ctrl = DMASND_CTRL_ON | DMASND_CTRL_REPEAT; +} + + +static void AtaPlay(void) +{ + /* ++TeSche: Note that write_sq.active is no longer just a flag but + * holds the number of frames the DMA is currently programmed for + * instead, may be 0, 1 (currently being played) or 2 (pre-programmed). + * + * Changes done to write_sq.count and write_sq.active are a bit more + * subtle again so now I must admit I also prefer disabling the irq + * here rather than considering all possible situations. But the point + * is that disabling the irq doesn't have any bad influence on this + * version of the driver as we benefit from having pre-programmed the + * DMA wherever possible: There's no need to reload the DMA at the + * exact time of an interrupt but only at some time while the + * pre-programmed frame is playing! + */ + atari_disable_irq(IRQ_MFP_TIMA); + + if (write_sq.active == 2 || /* DMA is 'full' */ + write_sq.count <= 0) { /* nothing to do */ + atari_enable_irq(IRQ_MFP_TIMA); + return; + } + + if (write_sq.active == 0) { + /* looks like there's nothing 'in' the DMA yet, so try + * to put two frames into it (at least one is available). + */ + if (write_sq.count == 1 && + write_sq.rear_size < write_sq.block_size && + !write_sq.syncing) { + /* hmmm, the only existing frame is not + * yet filled and we're not syncing? + */ + atari_enable_irq(IRQ_MFP_TIMA); + return; + } + AtaPlayNextFrame(1); + if (write_sq.count == 1) { + /* no more frames */ + atari_enable_irq(IRQ_MFP_TIMA); + return; + } + if (write_sq.count == 2 && + write_sq.rear_size < write_sq.block_size && + !write_sq.syncing) { + /* hmmm, there were two frames, but the second + * one is not yet filled and we're not syncing? + */ + atari_enable_irq(IRQ_MFP_TIMA); + return; + } + AtaPlayNextFrame(2); + } else { + /* there's already a frame being played so we may only stuff + * one new into the DMA, but even if this may be the last + * frame existing the previous one is still on write_sq.count. + */ + if (write_sq.count == 2 && + write_sq.rear_size < write_sq.block_size && + !write_sq.syncing) { + /* hmmm, the only existing frame is not + * yet filled and we're not syncing? + */ + atari_enable_irq(IRQ_MFP_TIMA); + return; + } + AtaPlayNextFrame(2); + } + atari_enable_irq(IRQ_MFP_TIMA); +} + + +static void AtaInterrupt(int irq, void *dummy, struct pt_regs *fp) +{ +#if 0 + /* ++TeSche: if you should want to test this... */ + static int cnt = 0; + if (write_sq.active == 2) + if (++cnt == 10) { + /* simulate losing an interrupt */ + cnt = 0; + return; + } +#endif + + if (write_sq_ignore_int && is_falcon) { + /* ++TeSche: Falcon only: ignore first irq because it comes + * immediately after starting a frame. after that, irqs come + * (almost) like on the TT. + */ + write_sq_ignore_int = 0; + return; + } + + if (!write_sq.active) { + /* playing was interrupted and sq_reset() has already cleared + * the sq variables, so better don't do anything here. + */ + WAKE_UP(write_sq.sync_queue); + return; + } + + /* Probably ;) one frame is finished. Well, in fact it may be that a + * pre-programmed one is also finished because there has been a long + * delay in interrupt delivery and we've completely lost one, but + * there's no way to detect such a situation. In such a case the last + * frame will be played more than once and the situation will recover + * as soon as the irq gets through. + */ + write_sq.count--; + write_sq.active--; + + if (!write_sq.active) { + tt_dmasnd.ctrl = DMASND_CTRL_OFF; + write_sq_ignore_int = 1; + } + + WAKE_UP(write_sq.action_queue); + /* At least one block of the queue is free now + so wake up a writing process blocked because + of a full queue. */ + + if ((write_sq.active != 1) || (write_sq.count != 1)) + /* We must be a bit carefully here: write_sq.count indicates the + * number of buffers used and not the number of frames to be + * played. If write_sq.count==1 and write_sq.active==1 that + * means the only remaining frame was already programmed + * earlier (and is currently running) so we mustn't call + * AtaPlay() here, otherwise we'll play one frame too much. + */ + AtaPlay(); + + if (!write_sq.active) WAKE_UP(write_sq.sync_queue); + /* We are not playing after AtaPlay(), so there + is nothing to play any more. Wake up a process + waiting for audio output to drain. */ +} + + +/*** Mid level stuff *********************************************************/ + + +/* + * /dev/mixer abstraction + */ + +#define RECLEVEL_VOXWARE_TO_GAIN(v) \ + ((v) < 0 ? 0 : (v) > 100 ? 15 : (v) * 3 / 20) +#define RECLEVEL_GAIN_TO_VOXWARE(v) (((v) * 20 + 2) / 3) + + +static void __init TTMixerInit(void) +{ + atari_microwire_cmd(MW_LM1992_VOLUME(0)); + dmasound.volume_left = 0; + atari_microwire_cmd(MW_LM1992_BALLEFT(0)); + dmasound.volume_right = 0; + atari_microwire_cmd(MW_LM1992_BALRIGHT(0)); + atari_microwire_cmd(MW_LM1992_TREBLE(0)); + atari_microwire_cmd(MW_LM1992_BASS(0)); +} + +static void __init FalconMixerInit(void) +{ + dmasound.volume_left = (tt_dmasnd.output_atten & 0xf00) >> 8; + dmasound.volume_right = (tt_dmasnd.output_atten & 0xf0) >> 4; +} + +static int AtaMixerIoctl(u_int cmd, u_long arg) +{ + int data; + switch (cmd) { + case SOUND_MIXER_READ_SPEAKER: + if (is_falcon || MACH_IS_TT) { + int porta; + cli(); + sound_ym.rd_data_reg_sel = 14; + porta = sound_ym.rd_data_reg_sel; + sti(); + return IOCTL_OUT(arg, porta & 0x40 ? 0 : 100); + } + break; + case SOUND_MIXER_WRITE_VOLUME: + IOCTL_IN(arg, data); + return IOCTL_OUT(arg, dmasound_set_volume(data)); + case SOUND_MIXER_WRITE_SPEAKER: + if (is_falcon || MACH_IS_TT) { + int porta; + IOCTL_IN(arg, data); + cli(); + sound_ym.rd_data_reg_sel = 14; + porta = (sound_ym.rd_data_reg_sel & ~0x40) | + (data < 50 ? 0x40 : 0); + sound_ym.wd_data = porta; + sti(); + return IOCTL_OUT(arg, porta & 0x40 ? 0 : 100); + } + } + return -EINVAL; +} + + +static int TTMixerIoctl(u_int cmd, u_long arg) +{ + int data; + switch (cmd) { + case SOUND_MIXER_READ_RECMASK: + return IOCTL_OUT(arg, 0); + case SOUND_MIXER_READ_DEVMASK: + return IOCTL_OUT(arg, + SOUND_MASK_VOLUME | SOUND_MASK_TREBLE | SOUND_MASK_BASS | + (MACH_IS_TT ? SOUND_MASK_SPEAKER : 0)); + case SOUND_MIXER_READ_STEREODEVS: + return IOCTL_OUT(arg, SOUND_MASK_VOLUME); + case SOUND_MIXER_READ_VOLUME: + return IOCTL_OUT(arg, + VOLUME_DB_TO_VOXWARE(dmasound.volume_left) | + (VOLUME_DB_TO_VOXWARE(dmasound.volume_right) << 8)); + case SOUND_MIXER_READ_BASS: + return IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(dmasound.bass)); + case SOUND_MIXER_READ_TREBLE: + return IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(dmasound.treble)); + case SOUND_MIXER_READ_OGAIN: + return IOCTL_OUT(arg, GAIN_DB_TO_VOXWARE(dmasound.gain)); + case SOUND_MIXER_WRITE_BASS: + IOCTL_IN(arg, data); + return IOCTL_OUT(arg, dmasound_set_bass(data)); + case SOUND_MIXER_WRITE_TREBLE: + IOCTL_IN(arg, data); + return IOCTL_OUT(arg, dmasound_set_treble(data)); + case SOUND_MIXER_WRITE_OGAIN: + IOCTL_IN(arg, data); + return IOCTL_OUT(arg, dmasound_set_gain(data)); + } + return AtaMixerIoctl(cmd, arg); +} + +static int FalconMixerIoctl(u_int cmd, u_long arg) +{ + int data; + switch (cmd) { + case SOUND_MIXER_READ_RECMASK: + return IOCTL_OUT(arg, SOUND_MASK_MIC); + case SOUND_MIXER_READ_DEVMASK: + return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC | SOUND_MASK_SPEAKER); + case SOUND_MIXER_READ_STEREODEVS: + return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC); + case SOUND_MIXER_READ_VOLUME: + return IOCTL_OUT(arg, + VOLUME_ATT_TO_VOXWARE(dmasound.volume_left) | + VOLUME_ATT_TO_VOXWARE(dmasound.volume_right) << 8); + case SOUND_MIXER_READ_CAPS: + return IOCTL_OUT(arg, SOUND_CAP_EXCL_INPUT); + case SOUND_MIXER_WRITE_MIC: + IOCTL_IN(arg, data); + tt_dmasnd.input_gain = + RECLEVEL_VOXWARE_TO_GAIN(data & 0xff) << 4 | + RECLEVEL_VOXWARE_TO_GAIN(data >> 8 & 0xff); + /* fall thru, return set value */ + case SOUND_MIXER_READ_MIC: + return IOCTL_OUT(arg, + RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain >> 4 & 0xf) | + RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain & 0xf) << 8); + } + return AtaMixerIoctl(cmd, arg); +} + +static void AtaWriteSqSetup(void) +{ + write_sq_ignore_int = 0; +} + +static void AtaSqOpen(void) +{ + write_sq_ignore_int = 1; +} + +static int TTStateInfo(char *buffer) +{ + int len = 0; + len += sprintf(buffer+len, "\tsound.volume_left = %ddB [-40...0]\n", + dmasound.volume_left); + len += sprintf(buffer+len, "\tsound.volume_right = %ddB [-40...0]\n", + dmasound.volume_right); + len += sprintf(buffer+len, "\tsound.bass = %ddB [-12...+12]\n", + dmasound.bass); + len += sprintf(buffer+len, "\tsound.treble = %ddB [-12...+12]\n", + dmasound.treble); + return len; +} + +static int FalconStateInfo(char *buffer) +{ + int len = 0; + len += sprintf(buffer+len, "\tsound.volume_left = %ddB [-22.5...0]\n", + dmasound.volume_left); + len += sprintf(buffer+len, "\tsound.volume_right = %ddB [-22.5...0]\n", + dmasound.volume_right); + return len; +} + + +/*** Machine definitions *****************************************************/ + + +static MACHINE machTT = { + name: "Atari", + name2: "TT", + open: AtaOpen, + release: AtaRelease, + dma_alloc: AtaAlloc, + dma_free: AtaFree, + irqinit: AtaIrqInit, +#ifdef MODULE + irqcleanup: AtaIrqCleanUp, +#endif /* MODULE */ + init: TTInit, + silence: TTSilence, + setFormat: TTSetFormat, + setVolume: TTSetVolume, + setBass: AtaSetBass, + setTreble: AtaSetTreble, + setGain: TTSetGain, + play: AtaPlay, + mixer_init: TTMixerInit, + mixer_ioctl: TTMixerIoctl, + write_sq_setup: AtaWriteSqSetup, + sq_open: AtaSqOpen, + state_info: TTStateInfo, + min_dsp_speed: 6258, +}; + +static MACHINE machFalcon = { + name: "Atari", + name2: "FALCON", + dma_alloc: AtaAlloc, + dma_free: AtaFree, + irqinit: AtaIrqInit, +#ifdef MODULE + irqcleanup: AtaIrqCleanUp, +#endif /* MODULE */ + init: FalconInit, + silence: FalconSilence, + setFormat: FalconSetFormat, + setVolume: FalconSetVolume, + setBass: AtaSetBass, + setTreble: AtaSetTreble, + play: AtaPlay, + mixer_init: FalconMixerInit, + mixer_ioctl: FalconMixerIoctl, + write_sq_setup: AtaWriteSqSetup, + sq_open: AtaSqOpen, + state_info: FalconStateInfo, + min_dsp_speed: 8195, +}; + + +/*** Config & Setup **********************************************************/ + + +static int __init dmasound_atari_init(void) +{ + if (MACH_IS_ATARI && ATARIHW_PRESENT(PCM_8BIT)) { + if (ATARIHW_PRESENT(CODEC)) { + dmasound.mach = machFalcon; + is_falcon = 1; + } else if (ATARIHW_PRESENT(MICROWIRE)) { + dmasound.mach = machTT; + is_falcon = 0; + } else + return -ENODEV; + if ((mfp.int_en_a & mfp.int_mk_a & 0x20) == 0) + return dmasound_init(); + else { + printk("DMA sound driver: Timer A interrupt already in use\n"); + return -EBUSY; + } + } + return -ENODEV; +} + +static void __exit dmasound_atari_cleanup(void) +{ + dmasound_deinit(); +} + +module_init(dmasound_atari_init); +module_exit(dmasound_atari_cleanup); diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/sound/dmasound/dmasound_awacs.c linux/drivers/sound/dmasound/dmasound_awacs.c --- v2.3.99-pre3/linux/drivers/sound/dmasound/dmasound_awacs.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/sound/dmasound/dmasound_awacs.c Mon Apr 10 22:58:59 2000 @@ -0,0 +1,2113 @@ + +/* + * linux/drivers/sound/dmasound_awacs.c + * + * PowerMac DMA Sound Driver + * + * See linux/drivers/sound/dmasound_core.c for copyright and credits + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "awacs_defs.h" +#include "dmasound.h" + + +/* + * Interrupt numbers and addresses, obtained from the device tree. + */ +static int awacs_irq, awacs_tx_irq, awacs_rx_irq; +static volatile struct awacs_regs *awacs; +static volatile struct dbdma_regs *awacs_txdma, *awacs_rxdma; +static int awacs_rate_index; +static int awacs_subframe; +static int awacs_spkr_vol; +static struct device_node* awacs_node; + +static char awacs_name[64]; +static int awacs_revision; +#define AWACS_BURGUNDY 100 /* fake revision # for burgundy */ + +/* + * Space for the DBDMA command blocks. + */ +static void *awacs_tx_cmd_space; +static volatile struct dbdma_cmd *awacs_tx_cmds; + +static void *awacs_rx_cmd_space; +static volatile struct dbdma_cmd *awacs_rx_cmds; + +/* + * Cached values of AWACS registers (we can't read them). + * Except on the burgundy. XXX + */ +int awacs_reg[5]; + +#define HAS_16BIT_TABLES +#undef HAS_8BIT_TABLES + +/* + * Stuff for outputting a beep. The values range from -327 to +327 + * so we can multiply by an amplitude in the range 0..100 to get a + * signed short value to put in the output buffer. + */ +static short beep_wform[256] = { + 0, 40, 79, 117, 153, 187, 218, 245, + 269, 288, 304, 316, 323, 327, 327, 324, + 318, 310, 299, 288, 275, 262, 249, 236, + 224, 213, 204, 196, 190, 186, 183, 182, + 182, 183, 186, 189, 192, 196, 200, 203, + 206, 208, 209, 209, 209, 207, 204, 201, + 197, 193, 188, 183, 179, 174, 170, 166, + 163, 161, 160, 159, 159, 160, 161, 162, + 164, 166, 168, 169, 171, 171, 171, 170, + 169, 167, 163, 159, 155, 150, 144, 139, + 133, 128, 122, 117, 113, 110, 107, 105, + 103, 103, 103, 103, 104, 104, 105, 105, + 105, 103, 101, 97, 92, 86, 78, 68, + 58, 45, 32, 18, 3, -11, -26, -41, + -55, -68, -79, -88, -95, -100, -102, -102, + -99, -93, -85, -75, -62, -48, -33, -16, + 0, 16, 33, 48, 62, 75, 85, 93, + 99, 102, 102, 100, 95, 88, 79, 68, + 55, 41, 26, 11, -3, -18, -32, -45, + -58, -68, -78, -86, -92, -97, -101, -103, + -105, -105, -105, -104, -104, -103, -103, -103, + -103, -105, -107, -110, -113, -117, -122, -128, + -133, -139, -144, -150, -155, -159, -163, -167, + -169, -170, -171, -171, -171, -169, -168, -166, + -164, -162, -161, -160, -159, -159, -160, -161, + -163, -166, -170, -174, -179, -183, -188, -193, + -197, -201, -204, -207, -209, -209, -209, -208, + -206, -203, -200, -196, -192, -189, -186, -183, + -182, -182, -183, -186, -190, -196, -204, -213, + -224, -236, -249, -262, -275, -288, -299, -310, + -318, -324, -327, -327, -323, -316, -304, -288, + -269, -245, -218, -187, -153, -117, -79, -40, +}; + +#define BEEP_SRATE 22050 /* 22050 Hz sample rate */ +#define BEEP_BUFLEN 512 +#define BEEP_VOLUME 15 /* 0 - 100 */ + +static int beep_volume = BEEP_VOLUME; +static int beep_playing = 0; +static int awacs_beep_state = 0; +static short *beep_buf; +static volatile struct dbdma_cmd *beep_dbdma_cmd; +static void (*orig_mksound)(unsigned int, unsigned int); +static int is_pbook_3400; +static unsigned char *latch_base; +static int is_pbook_G3; +static unsigned char *macio_base; + +/* Burgundy functions */ +static void awacs_burgundy_wcw(unsigned addr,unsigned newval); +static unsigned awacs_burgundy_rcw(unsigned addr); +static void awacs_burgundy_write_volume(unsigned address, int volume); +static int awacs_burgundy_read_volume(unsigned address); +static void awacs_burgundy_write_mvolume(unsigned address, int volume); +static int awacs_burgundy_read_mvolume(unsigned address); + +#ifdef CONFIG_PMAC_PBOOK +/* + * Stuff for restoring after a sleep. + */ +static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when); +struct pmu_sleep_notifier awacs_sleep_notifier = { + awacs_sleep_notify, SLEEP_LEVEL_SOUND, +}; +#endif /* CONFIG_PMAC_PBOOK */ + +static int expand_bal; /* Balance factor for expanding (not volume!) */ +static int expand_data; /* Data for expanding */ + + +/*** Translations ************************************************************/ + + +/* ++TeSche: radically changed for new expanding purposes... + * + * These two routines now deal with copying/expanding/translating the samples + * from user space into our buffer at the right frequency. They take care about + * how much data there's actually to read, how much buffer space there is and + * to convert samples into the right frequency/encoding. They will only work on + * complete samples so it may happen they leave some bytes in the input stream + * if the user didn't write a multiple of the current sample size. They both + * return the number of bytes they've used from both streams so you may detect + * such a situation. Luckily all programs should be able to cope with that. + * + * I think I've optimized anything as far as one can do in plain C, all + * variables should fit in registers and the loops are really short. There's + * one loop for every possible situation. Writing a more generalized and thus + * parameterized loop would only produce slower code. Feel free to optimize + * this in assembler if you like. :) + * + * I think these routines belong here because they're not yet really hardware + * independent, especially the fact that the Falcon can play 16bit samples + * only in stereo is hardcoded in both of them! + * + * ++geert: split in even more functions (one per format) + */ + +static ssize_t pmac_ct_law(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t pmac_ct_s8(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t pmac_ct_u8(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t pmac_ct_s16(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t pmac_ct_u16(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t pmac_ctx_law(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t pmac_ctx_s8(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t pmac_ctx_u8(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t pmac_ctx_s16(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t pmac_ctx_u16(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t pmac_ct_s16_read(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t pmac_ct_u16_read(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); + + +/*** Low level stuff *********************************************************/ + + +static void PMacOpen(void); +static void PMacRelease(void); +static void *PMacAlloc(unsigned int size, int flags); +static void PMacFree(void *ptr, unsigned int size); +static int PMacIrqInit(void); +#ifdef MODULE +static void PMacIrqCleanup(void); +#endif +static void PMacSilence(void); +static void PMacInit(void); +static int PMacSetFormat(int format); +static int PMacSetVolume(int volume); +static void PMacPlay(void); +static void PMacRecord(void); +static void pmac_awacs_tx_intr(int irq, void *devid, struct pt_regs *regs); +static void pmac_awacs_rx_intr(int irq, void *devid, struct pt_regs *regs); +static void pmac_awacs_intr(int irq, void *devid, struct pt_regs *regs); +static void awacs_write(int val); +static int awacs_get_volume(int reg, int lshift); +static int awacs_volume_setter(int volume, int n, int mute, int lshift); +static void awacs_mksound(unsigned int hz, unsigned int ticks); +static void awacs_nosound(unsigned long xx); + + +/*** Mid level stuff **********************************************************/ + + +static int PMacMixerIoctl(u_int cmd, u_long arg); +static void PMacWriteSqSetup(void); +static void PMacReadSqSetup(void); +static void PMacAbortRead(void); + + +/*** Translations ************************************************************/ + + +static ssize_t pmac_ct_law(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + short *table = dmasound.soft.format == AFMT_MU_LAW + ? dmasound_ulaw2dma16 : dmasound_alaw2dma16; + ssize_t count, used; + short *p = (short *) &frame[*frameUsed]; + int val, stereo = dmasound.soft.stereo; + + frameLeft >>= 2; + if (stereo) + userCount >>= 1; + used = count = min(userCount, frameLeft); + while (count > 0) { + u_char data; + if (get_user(data, userPtr++)) + return -EFAULT; + val = table[data]; + *p++ = val; + if (stereo) { + if (get_user(data, userPtr++)) + return -EFAULT; + val = table[data]; + } + *p++ = val; + count--; + } + *frameUsed += used * 4; + return stereo? used * 2: used; +} + + +static ssize_t pmac_ct_s8(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + ssize_t count, used; + short *p = (short *) &frame[*frameUsed]; + int val, stereo = dmasound.soft.stereo; + + frameLeft >>= 2; + if (stereo) + userCount >>= 1; + used = count = min(userCount, frameLeft); + while (count > 0) { + u_char data; + if (get_user(data, userPtr++)) + return -EFAULT; + val = data << 8; + *p++ = val; + if (stereo) { + if (get_user(data, userPtr++)) + return -EFAULT; + val = data << 8; + } + *p++ = val; + count--; + } + *frameUsed += used * 4; + return stereo? used * 2: used; +} + + +static ssize_t pmac_ct_u8(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + ssize_t count, used; + short *p = (short *) &frame[*frameUsed]; + int val, stereo = dmasound.soft.stereo; + + frameLeft >>= 2; + if (stereo) + userCount >>= 1; + used = count = min(userCount, frameLeft); + while (count > 0) { + u_char data; + if (get_user(data, userPtr++)) + return -EFAULT; + val = (data ^ 0x80) << 8; + *p++ = val; + if (stereo) { + if (get_user(data, userPtr++)) + return -EFAULT; + val = (data ^ 0x80) << 8; + } + *p++ = val; + count--; + } + *frameUsed += used * 4; + return stereo? used * 2: used; +} + + +static ssize_t pmac_ct_s16(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + ssize_t count, used; + int stereo = dmasound.soft.stereo; + short *fp = (short *) &frame[*frameUsed]; + + frameLeft >>= 2; + userCount >>= (stereo? 2: 1); + used = count = min(userCount, frameLeft); + if (!stereo) { + short *up = (short *) userPtr; + while (count > 0) { + short data; + if (get_user(data, up++)) + return -EFAULT; + *fp++ = data; + *fp++ = data; + count--; + } + } else { + if (copy_from_user(fp, userPtr, count * 4)) + return -EFAULT; + } + *frameUsed += used * 4; + return stereo? used * 4: used * 2; +} + +static ssize_t pmac_ct_u16(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + ssize_t count, used; + int mask = (dmasound.soft.format == AFMT_U16_LE? 0x0080: 0x8000); + int stereo = dmasound.soft.stereo; + short *fp = (short *) &frame[*frameUsed]; + short *up = (short *) userPtr; + + frameLeft >>= 2; + userCount >>= (stereo? 2: 1); + used = count = min(userCount, frameLeft); + while (count > 0) { + int data; + if (get_user(data, up++)) + return -EFAULT; + data ^= mask; + *fp++ = data; + if (stereo) { + if (get_user(data, up++)) + return -EFAULT; + data ^= mask; + } + *fp++ = data; + count--; + } + *frameUsed += used * 4; + return stereo? used * 4: used * 2; +} + + +static ssize_t pmac_ctx_law(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + unsigned short *table = (unsigned short *) + (dmasound.soft.format == AFMT_MU_LAW + ? dmasound_ulaw2dma16 : dmasound_alaw2dma16); + unsigned int data = expand_data; + unsigned int *p = (unsigned int *) &frame[*frameUsed]; + int bal = expand_bal; + int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; + int utotal, ftotal; + int stereo = dmasound.soft.stereo; + + frameLeft >>= 2; + if (stereo) + userCount >>= 1; + ftotal = frameLeft; + utotal = userCount; + while (frameLeft) { + u_char c; + if (bal < 0) { + if (userCount == 0) + break; + if (get_user(c, userPtr++)) + return -EFAULT; + data = table[c]; + if (stereo) { + if (get_user(c, userPtr++)) + return -EFAULT; + data = (data << 16) + table[c]; + } else + data = (data << 16) + data; + userCount--; + bal += hSpeed; + } + *p++ = data; + frameLeft--; + bal -= sSpeed; + } + expand_bal = bal; + expand_data = data; + *frameUsed += (ftotal - frameLeft) * 4; + utotal -= userCount; + return stereo? utotal * 2: utotal; +} + + +static ssize_t pmac_ctx_s8(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + unsigned int *p = (unsigned int *) &frame[*frameUsed]; + unsigned int data = expand_data; + int bal = expand_bal; + int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; + int stereo = dmasound.soft.stereo; + int utotal, ftotal; + + frameLeft >>= 2; + if (stereo) + userCount >>= 1; + ftotal = frameLeft; + utotal = userCount; + while (frameLeft) { + u_char c; + if (bal < 0) { + if (userCount == 0) + break; + if (get_user(c, userPtr++)) + return -EFAULT; + data = c << 8; + if (stereo) { + if (get_user(c, userPtr++)) + return -EFAULT; + data = (data << 16) + (c << 8); + } else + data = (data << 16) + data; + userCount--; + bal += hSpeed; + } + *p++ = data; + frameLeft--; + bal -= sSpeed; + } + expand_bal = bal; + expand_data = data; + *frameUsed += (ftotal - frameLeft) * 4; + utotal -= userCount; + return stereo? utotal * 2: utotal; +} + + +static ssize_t pmac_ctx_u8(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + unsigned int *p = (unsigned int *) &frame[*frameUsed]; + unsigned int data = expand_data; + int bal = expand_bal; + int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; + int stereo = dmasound.soft.stereo; + int utotal, ftotal; + + frameLeft >>= 2; + if (stereo) + userCount >>= 1; + ftotal = frameLeft; + utotal = userCount; + while (frameLeft) { + u_char c; + if (bal < 0) { + if (userCount == 0) + break; + if (get_user(c, userPtr++)) + return -EFAULT; + data = (c ^ 0x80) << 8; + if (stereo) { + if (get_user(c, userPtr++)) + return -EFAULT; + data = (data << 16) + ((c ^ 0x80) << 8); + } else + data = (data << 16) + data; + userCount--; + bal += hSpeed; + } + *p++ = data; + frameLeft--; + bal -= sSpeed; + } + expand_bal = bal; + expand_data = data; + *frameUsed += (ftotal - frameLeft) * 4; + utotal -= userCount; + return stereo? utotal * 2: utotal; +} + + +static ssize_t pmac_ctx_s16(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + unsigned int *p = (unsigned int *) &frame[*frameUsed]; + unsigned int data = expand_data; + unsigned short *up = (unsigned short *) userPtr; + int bal = expand_bal; + int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; + int stereo = dmasound.soft.stereo; + int utotal, ftotal; + + frameLeft >>= 2; + userCount >>= (stereo? 2: 1); + ftotal = frameLeft; + utotal = userCount; + while (frameLeft) { + unsigned short c; + if (bal < 0) { + if (userCount == 0) + break; + if (get_user(data, up++)) + return -EFAULT; + if (stereo) { + if (get_user(c, up++)) + return -EFAULT; + data = (data << 16) + c; + } else + data = (data << 16) + data; + userCount--; + bal += hSpeed; + } + *p++ = data; + frameLeft--; + bal -= sSpeed; + } + expand_bal = bal; + expand_data = data; + *frameUsed += (ftotal - frameLeft) * 4; + utotal -= userCount; + return stereo? utotal * 4: utotal * 2; +} + + +static ssize_t pmac_ctx_u16(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + int mask = (dmasound.soft.format == AFMT_U16_LE? 0x0080: 0x8000); + unsigned int *p = (unsigned int *) &frame[*frameUsed]; + unsigned int data = expand_data; + unsigned short *up = (unsigned short *) userPtr; + int bal = expand_bal; + int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; + int stereo = dmasound.soft.stereo; + int utotal, ftotal; + + frameLeft >>= 2; + userCount >>= (stereo? 2: 1); + ftotal = frameLeft; + utotal = userCount; + while (frameLeft) { + unsigned short c; + if (bal < 0) { + if (userCount == 0) + break; + if (get_user(data, up++)) + return -EFAULT; + data ^= mask; + if (stereo) { + if (get_user(c, up++)) + return -EFAULT; + data = (data << 16) + (c ^ mask); + } else + data = (data << 16) + data; + userCount--; + bal += hSpeed; + } + *p++ = data; + frameLeft--; + bal -= sSpeed; + } + expand_bal = bal; + expand_data = data; + *frameUsed += (ftotal - frameLeft) * 4; + utotal -= userCount; + return stereo? utotal * 4: utotal * 2; +} + +static ssize_t pmac_ct_s8_read(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + ssize_t count, used; + short *p = (short *) &frame[*frameUsed]; + int val, stereo = dmasound.soft.stereo; + + frameLeft >>= 2; + if (stereo) + userCount >>= 1; + used = count = min(userCount, frameLeft); + while (count > 0) { + u_char data; + + val = *p++; + data = val >> 8; + if (put_user(data, (u_char *)userPtr++)) + return -EFAULT; + if (stereo) { + val = *p; + data = val >> 8; + if (put_user(data, (u_char *)userPtr++)) + return -EFAULT; + } + p++; + count--; + } + *frameUsed += used * 4; + return stereo? used * 2: used; +} + + +static ssize_t pmac_ct_u8_read(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + ssize_t count, used; + short *p = (short *) &frame[*frameUsed]; + int val, stereo = dmasound.soft.stereo; + + frameLeft >>= 2; + if (stereo) + userCount >>= 1; + used = count = min(userCount, frameLeft); + while (count > 0) { + u_char data; + + val = *p++; + data = (val >> 8) ^ 0x80; + if (put_user(data, (u_char *)userPtr++)) + return -EFAULT; + if (stereo) { + val = *p; + data = (val >> 8) ^ 0x80; + if (put_user(data, (u_char *)userPtr++)) + return -EFAULT; + } + p++; + count--; + } + *frameUsed += used * 4; + return stereo? used * 2: used; +} + + +static ssize_t pmac_ct_s16_read(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + ssize_t count, used; + int stereo = dmasound.soft.stereo; + short *fp = (short *) &frame[*frameUsed]; + + frameLeft >>= 2; + userCount >>= (stereo? 2: 1); + used = count = min(userCount, frameLeft); + if (!stereo) { + short *up = (short *) userPtr; + while (count > 0) { + short data; + data = *fp; + if (put_user(data, up++)) + return -EFAULT; + fp+=2; + count--; + } + } else { + if (copy_to_user((u_char *)userPtr, fp, count * 4)) + return -EFAULT; + } + *frameUsed += used * 4; + return stereo? used * 4: used * 2; +} + +static ssize_t pmac_ct_u16_read(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + ssize_t count, used; + int mask = (dmasound.soft.format == AFMT_U16_LE? 0x0080: 0x8000); + int stereo = dmasound.soft.stereo; + short *fp = (short *) &frame[*frameUsed]; + short *up = (short *) userPtr; + + frameLeft >>= 2; + userCount >>= (stereo? 2: 1); + used = count = min(userCount, frameLeft); + while (count > 0) { + int data; + + data = *fp++; + data ^= mask; + if (put_user(data, up++)) + return -EFAULT; + if (stereo) { + data = *fp; + data ^= mask; + if (put_user(data, up++)) + return -EFAULT; + } + fp++; + count--; + } + *frameUsed += used * 4; + return stereo? used * 4: used * 2; +} + + +static TRANS transAwacsNormal = { + ct_ulaw: pmac_ct_law, + ct_alaw: pmac_ct_law, + ct_s8: pmac_ct_s8, + ct_u8: pmac_ct_u8, + ct_s16be: pmac_ct_s16, + ct_u16be: pmac_ct_u16, + ct_s16le: pmac_ct_s16, + ct_u16le: pmac_ct_u16, +}; + +static TRANS transAwacsExpand = { + ct_ulaw: pmac_ctx_law, + ct_alaw: pmac_ctx_law, + ct_s8: pmac_ctx_s8, + ct_u8: pmac_ctx_u8, + ct_s16be: pmac_ctx_s16, + ct_u16be: pmac_ctx_u16, + ct_s16le: pmac_ctx_s16, + ct_u16le: pmac_ctx_u16, +}; + +static TRANS transAwacsNormalRead = { + ct_s8: pmac_ct_s8_read, + ct_u8: pmac_ct_u8_read, + ct_s16be: pmac_ct_s16_read, + ct_u16be: pmac_ct_u16_read, + ct_s16le: pmac_ct_s16_read, + ct_u16le: pmac_ct_u16_read, +}; + +/*** Low level stuff *********************************************************/ + + + +/* + * PCI PowerMac, with AWACS and DBDMA. + */ + +static void PMacOpen(void) +{ + MOD_INC_USE_COUNT; +} + +static void PMacRelease(void) +{ + MOD_DEC_USE_COUNT; +} + +static void *PMacAlloc(unsigned int size, int flags) +{ + return kmalloc(size, flags); +} + +static void PMacFree(void *ptr, unsigned int size) +{ + kfree(ptr); +} + +static int __init PMacIrqInit(void) +{ + if (request_irq(awacs_irq, pmac_awacs_intr, 0, "AWACS", 0) + || request_irq(awacs_tx_irq, pmac_awacs_tx_intr, 0, "AWACS out", 0) + || request_irq(awacs_rx_irq, pmac_awacs_rx_intr, 0, "AWACS in", 0)) + return 0; + return 1; +} + +#ifdef MODULE +static void PMacIrqCleanup(void) +{ + /* turn off output dma */ + out_le32(&awacs_txdma->control, RUN<<16); + /* disable interrupts from awacs interface */ + out_le32(&awacs->control, in_le32(&awacs->control) & 0xfff); +#ifdef CONFIG_PMAC_PBOOK + if (is_pbook_G3) { + feature_clear(awacs_node, FEATURE_Sound_power); + feature_clear(awacs_node, FEATURE_Sound_CLK_enable); + } +#endif + free_irq(awacs_irq, 0); + free_irq(awacs_tx_irq, 0); + free_irq(awacs_rx_irq, 0); + kfree(awacs_tx_cmd_space); + if (awacs_rx_cmd_space) + kfree(awacs_rx_cmd_space); + if (beep_buf) + kfree(beep_buf); + kd_mksound = orig_mksound; +#ifdef CONFIG_PMAC_PBOOK + pmu_unregister_sleep_notifier(&awacs_sleep_notifier); +#endif +} +#endif /* MODULE */ + +static void PMacSilence(void) +{ + /* turn off output dma */ + out_le32(&awacs_txdma->control, RUN<<16); +} + +static int awacs_freqs[8] = { + 44100, 29400, 22050, 17640, 14700, 11025, 8820, 7350 +}; +static int awacs_freqs_ok[8] = { 1, 1, 1, 1, 1, 1, 1, 1 }; + +static void PMacInit(void) +{ + int i, tolerance; + + switch (dmasound.soft.format) { + case AFMT_S16_LE: + case AFMT_U16_LE: + dmasound.hard.format = AFMT_S16_LE; + break; + default: + dmasound.hard.format = AFMT_S16_BE; + break; + } + dmasound.hard.stereo = 1; + dmasound.hard.size = 16; + + /* + * If we have a sample rate which is within catchRadius percent + * of the requested value, we don't have to expand the samples. + * Otherwise choose the next higher rate. + * N.B.: burgundy awacs (iMac and later) only works at 44100 Hz. + */ + i = 8; + do { + tolerance = catchRadius * awacs_freqs[--i] / 100; + if (awacs_freqs_ok[i] + && dmasound.soft.speed <= awacs_freqs[i] + tolerance) + break; + } while (i > 0); + if (dmasound.soft.speed >= awacs_freqs[i] - tolerance) + dmasound.trans_write = &transAwacsNormal; + else + dmasound.trans_write = &transAwacsExpand; + dmasound.trans_read = &transAwacsNormalRead; + dmasound.hard.speed = awacs_freqs[i]; + awacs_rate_index = i; + + /* XXX disable error interrupt on burgundy for now */ + out_le32(&awacs->control, MASK_IEPC | (i << 8) | 0x11 + | (awacs_revision < AWACS_BURGUNDY? MASK_IEE: 0)); + awacs_reg[1] = (awacs_reg[1] & ~MASK_SAMPLERATE) | (i << 3); + awacs_write(awacs_reg[1] | MASK_ADDR1); + out_le32(&awacs->byteswap, dmasound.hard.format != AFMT_S16_BE); + + /* We really want to execute a DMA stop command, after the AWACS + * is initialized. + * For reasons I don't understand, it stops the hissing noise + * common to many PowerBook G3 systems (like mine :-). + */ + out_le32(&awacs_txdma->control, (RUN|WAKE|FLUSH|PAUSE) << 16); + st_le16(&beep_dbdma_cmd->command, DBDMA_STOP); + out_le32(&awacs_txdma->cmdptr, virt_to_bus(beep_dbdma_cmd)); + out_le32(&awacs_txdma->control, RUN | (RUN << 16)); + + expand_bal = -dmasound.soft.speed; +} + +static int PMacSetFormat(int format) +{ + int size; + + switch (format) { + case AFMT_QUERY: + return dmasound.soft.format; + case AFMT_MU_LAW: + case AFMT_A_LAW: + case AFMT_U8: + case AFMT_S8: + size = 8; + break; + case AFMT_S16_BE: + case AFMT_U16_BE: + case AFMT_S16_LE: + case AFMT_U16_LE: + size = 16; + break; + default: /* :-) */ + printk(KERN_ERR "dmasound: unknown format 0x%x, using AFMT_U8\n", + format); + size = 8; + format = AFMT_U8; + } + + dmasound.soft.format = format; + dmasound.soft.size = size; + if (dmasound.minDev == SND_DEV_DSP) { + dmasound.dsp.format = format; + dmasound.dsp.size = size; + } + + PMacInit(); + + return format; +} + +#define AWACS_VOLUME_TO_MASK(x) (15 - ((((x) - 1) * 15) / 99)) +#define AWACS_MASK_TO_VOLUME(y) (100 - ((y) * 99 / 15)) + +static int awacs_get_volume(int reg, int lshift) +{ + int volume; + + volume = AWACS_MASK_TO_VOLUME((reg >> lshift) & 0xf); + volume |= AWACS_MASK_TO_VOLUME(reg & 0xf) << 8; + return volume; +} + +static int awacs_volume_setter(int volume, int n, int mute, int lshift) +{ + int r1, rn; + + if (mute && volume == 0) { + r1 = awacs_reg[1] | mute; + } else { + r1 = awacs_reg[1] & ~mute; + rn = awacs_reg[n] & ~(0xf | (0xf << lshift)); + rn |= ((AWACS_VOLUME_TO_MASK(volume & 0xff) & 0xf) << lshift); + rn |= AWACS_VOLUME_TO_MASK((volume >> 8) & 0xff) & 0xf; + awacs_reg[n] = rn; + awacs_write((n << 12) | rn); + volume = awacs_get_volume(rn, lshift); + } + if (r1 != awacs_reg[1]) { + awacs_reg[1] = r1; + awacs_write(r1 | MASK_ADDR1); + } + return volume; +} + +static int PMacSetVolume(int volume) +{ + return awacs_volume_setter(volume, 2, MASK_AMUTE, 6); +} + +static void PMacPlay(void) +{ + volatile struct dbdma_cmd *cp; + int i, count; + unsigned long flags; + + save_flags(flags); cli(); + if (awacs_beep_state) { + /* sound takes precedence over beeps */ + out_le32(&awacs_txdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16); + out_le32(&awacs->control, + (in_le32(&awacs->control) & ~0x1f00) + | (awacs_rate_index << 8)); + out_le32(&awacs->byteswap, dmasound.hard.format != AFMT_S16_BE); + out_le32(&awacs_txdma->cmdptr, virt_to_bus(&(awacs_tx_cmds[(write_sq.front+write_sq.active) % write_sq.max_count]))); + + beep_playing = 0; + awacs_beep_state = 0; + } + i = write_sq.front + write_sq.active; + if (i >= write_sq.max_count) + i -= write_sq.max_count; + while (write_sq.active < 2 && write_sq.active < write_sq.count) { + count = (write_sq.count == write_sq.active + 1)?write_sq.rear_size:write_sq.block_size; + if (count < write_sq.block_size && !write_sq.syncing) + /* last block not yet filled, and we're not syncing. */ + break; + cp = &awacs_tx_cmds[i]; + st_le16(&cp->req_count, count); + st_le16(&cp->xfer_status, 0); + if (++i >= write_sq.max_count) + i = 0; + out_le16(&awacs_tx_cmds[i].command, DBDMA_STOP); + out_le16(&cp->command, OUTPUT_MORE + INTR_ALWAYS); + if (write_sq.active == 0) + out_le32(&awacs_txdma->cmdptr, virt_to_bus(cp)); + out_le32(&awacs_txdma->control, ((RUN|WAKE) << 16) + (RUN|WAKE)); + ++write_sq.active; + } + restore_flags(flags); +} + + +static void PMacRecord(void) +{ + unsigned long flags; + + if (read_sq.active) + return; + + save_flags(flags); cli(); + + /* This is all we have to do......Just start it up. + */ + out_le32(&awacs_rxdma->control, ((RUN|WAKE) << 16) + (RUN|WAKE)); + read_sq.active = 1; + + restore_flags(flags); +} + + +static void +pmac_awacs_tx_intr(int irq, void *devid, struct pt_regs *regs) +{ + int i = write_sq.front; + int stat; + volatile struct dbdma_cmd *cp; + + while (write_sq.active > 0) { + cp = &awacs_tx_cmds[i]; + stat = ld_le16(&cp->xfer_status); + if ((stat & ACTIVE) == 0) + break; /* this frame is still going */ + --write_sq.count; + --write_sq.active; + if (++i >= write_sq.max_count) + i = 0; + } + if (i != write_sq.front) + WAKE_UP(write_sq.action_queue); + write_sq.front = i; + + PMacPlay(); + + if (!write_sq.active) + WAKE_UP(write_sq.sync_queue); +} + + +static void +pmac_awacs_rx_intr(int irq, void *devid, struct pt_regs *regs) +{ + + /* For some reason on my PowerBook G3, I get one interrupt + * when the interrupt vector is installed (like something is + * pending). This happens before the dbdma is initialize by + * us, so I just check the command pointer and if it is zero, + * just blow it off. + */ + if (in_le32(&awacs_rxdma->cmdptr) == 0) + return; + + /* We also want to blow 'em off when shutting down. + */ + if (read_sq.active == 0) + return; + + /* Check multiple buffers in case we were held off from + * interrupt processing for a long time. Geeze, I really hope + * this doesn't happen. + */ + while (awacs_rx_cmds[read_sq.rear].xfer_status) { + + /* Clear status and move on to next buffer. + */ + awacs_rx_cmds[read_sq.rear].xfer_status = 0; + read_sq.rear++; + + /* Wrap the buffer ring. + */ + if (read_sq.rear >= read_sq.max_active) + read_sq.rear = 0; + + /* If we have caught up to the front buffer, bump it. + * This will cause weird (but not fatal) results if the + * read loop is currently using this buffer. The user is + * behind in this case anyway, so weird things are going + * to happen. + */ + if (read_sq.rear == read_sq.front) { + read_sq.front++; + if (read_sq.front >= read_sq.max_active) + read_sq.front = 0; + } + } + + WAKE_UP(read_sq.action_queue); +} + + +static void +pmac_awacs_intr(int irq, void *devid, struct pt_regs *regs) +{ + int ctrl = in_le32(&awacs->control); + + if (ctrl & MASK_PORTCHG) { + /* do something when headphone is plugged/unplugged? */ + } + if (ctrl & MASK_CNTLERR) { + int err = (in_le32(&awacs->codec_stat) & MASK_ERRCODE) >> 16; + if (err != 0 && awacs_revision < AWACS_BURGUNDY) + printk(KERN_ERR "AWACS: error %x\n", err); + } + /* Writing 1s to the CNTLERR and PORTCHG bits clears them... */ + out_le32(&awacs->control, ctrl); +} + +static void +awacs_write(int val) +{ + if (awacs_revision >= AWACS_BURGUNDY) + return; + while (in_le32(&awacs->codec_ctrl) & MASK_NEWECMD) + ; /* XXX should have timeout */ + out_le32(&awacs->codec_ctrl, val | (awacs_subframe << 22)); +} + +static void awacs_nosound(unsigned long xx) +{ + unsigned long flags; + + save_flags(flags); cli(); + if (beep_playing) { + st_le16(&beep_dbdma_cmd->command, DBDMA_STOP); + out_le32(&awacs_txdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16); + out_le32(&awacs->control, + (in_le32(&awacs->control) & ~0x1f00) + | (awacs_rate_index << 8)); + out_le32(&awacs->byteswap, dmasound.hard.format != AFMT_S16_BE); + beep_playing = 0; + } + restore_flags(flags); +} + +static struct timer_list beep_timer = { + NULL, NULL, 0, 0, awacs_nosound +}; + +static void awacs_mksound(unsigned int hz, unsigned int ticks) +{ + unsigned long flags; + int beep_speed = 0; + int srate; + int period, ncycles, nsamples; + int i, j, f; + short *p; + static int beep_hz_cache; + static int beep_nsamples_cache; + static int beep_volume_cache; + + for (i = 0; i < 8 && awacs_freqs[i] >= BEEP_SRATE; ++i) + if (awacs_freqs_ok[i]) + beep_speed = i; + srate = awacs_freqs[beep_speed]; + + if (hz <= srate / BEEP_BUFLEN || hz > srate / 2) { +#if 1 + /* this is a hack for broken X server code */ + hz = 750; + ticks = 12; +#else + /* cancel beep currently playing */ + awacs_nosound(0); + return; +#endif + } + save_flags(flags); cli(); + del_timer(&beep_timer); + if (ticks) { + beep_timer.expires = jiffies + ticks; + add_timer(&beep_timer); + } + if (beep_playing || write_sq.active || beep_buf == NULL) { + restore_flags(flags); + return; /* too hard, sorry :-( */ + } + beep_playing = 1; + st_le16(&beep_dbdma_cmd->command, OUTPUT_MORE + BR_ALWAYS); + restore_flags(flags); + + if (hz == beep_hz_cache && beep_volume == beep_volume_cache) { + nsamples = beep_nsamples_cache; + } else { + period = srate * 256 / hz; /* fixed point */ + ncycles = BEEP_BUFLEN * 256 / period; + nsamples = (period * ncycles) >> 8; + f = ncycles * 65536 / nsamples; + j = 0; + p = beep_buf; + for (i = 0; i < nsamples; ++i, p += 2) { + p[0] = p[1] = beep_wform[j >> 8] * beep_volume; + j = (j + f) & 0xffff; + } + beep_hz_cache = hz; + beep_volume_cache = beep_volume; + beep_nsamples_cache = nsamples; + } + + st_le16(&beep_dbdma_cmd->req_count, nsamples*4); + st_le16(&beep_dbdma_cmd->xfer_status, 0); + st_le32(&beep_dbdma_cmd->cmd_dep, virt_to_bus(beep_dbdma_cmd)); + st_le32(&beep_dbdma_cmd->phy_addr, virt_to_bus(beep_buf)); + awacs_beep_state = 1; + + save_flags(flags); cli(); + if (beep_playing) { /* i.e. haven't been terminated already */ + out_le32(&awacs_txdma->control, (RUN|WAKE|FLUSH|PAUSE) << 16); + out_le32(&awacs->control, + (in_le32(&awacs->control) & ~0x1f00) + | (beep_speed << 8)); + out_le32(&awacs->byteswap, 0); + out_le32(&awacs_txdma->cmdptr, virt_to_bus(beep_dbdma_cmd)); + out_le32(&awacs_txdma->control, RUN | (RUN << 16)); + } + restore_flags(flags); +} + +#ifdef CONFIG_PMAC_PBOOK +/* + * Save state when going to sleep, restore it afterwards. + */ +static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when) +{ + switch (when) { + case PBOOK_SLEEP_NOW: + /* XXX we should stop any dma in progress when going to sleep + and restart it when we wake. */ + PMacSilence(); + disable_irq(awacs_irq); + disable_irq(awacs_tx_irq); + if (is_pbook_G3) { + feature_clear(awacs_node, FEATURE_Sound_CLK_enable); + feature_clear(awacs_node, FEATURE_Sound_power); + } + break; + case PBOOK_WAKE: + /* There is still a problem on wake. Sound seems to work fine + if I launch mpg123 and resumes fine if mpg123 was playing, + but the console beep is dead until I do something with the + mixer. Probably yet another timing issue */ + if (!feature_test(awacs_node, FEATURE_Sound_CLK_enable) + || !feature_test(awacs_node, FEATURE_Sound_power)) { + /* these aren't present on the 3400 AFAIK -- paulus */ + feature_set(awacs_node, FEATURE_Sound_CLK_enable); + feature_set(awacs_node, FEATURE_Sound_power); + mdelay(1000); + } + out_le32(&awacs->control, MASK_IEPC + | (awacs_rate_index << 8) | 0x11 + | (awacs_revision < AWACS_BURGUNDY? MASK_IEE: 0)); + awacs_write(awacs_reg[0] | MASK_ADDR0); + awacs_write(awacs_reg[1] | MASK_ADDR1); + awacs_write(awacs_reg[2] | MASK_ADDR2); + awacs_write(awacs_reg[4] | MASK_ADDR4); + out_le32(&awacs->byteswap, dmasound.hard.format != AFMT_S16_BE); + enable_irq(awacs_irq); + enable_irq(awacs_tx_irq); + if (awacs_revision == 3) { + mdelay(100); + awacs_write(0x6000); + mdelay(2); + awacs_write(awacs_reg[1] | MASK_ADDR1); + } + /* enable CD sound input */ + if (macio_base && is_pbook_G3) { + out_8(macio_base + 0x37, 3); + } else if (is_pbook_3400) { + feature_set(awacs_node, FEATURE_IOBUS_enable); + udelay(10); + in_8(latch_base + 0x190); + } + /* Resume pending sounds. */ + PMacPlay(); + } + return PBOOK_SLEEP_OK; +} +#endif /* CONFIG_PMAC_PBOOK */ + + +/* All the burgundy functions: */ + +/* Waits for busy flag to clear */ +inline static void +awacs_burgundy_busy_wait(void) +{ + while (in_le32(&awacs->codec_ctrl) & MASK_NEWECMD) + ; +} + +inline static void +awacs_burgundy_extend_wait(void) +{ + while (!(in_le32(&awacs->codec_stat) & MASK_EXTEND)) + ; + while (in_le32(&awacs->codec_stat) & MASK_EXTEND) + ; +} + +static void +awacs_burgundy_wcw(unsigned addr, unsigned val) +{ + out_le32(&awacs->codec_ctrl, addr + 0x200c00 + (val & 0xff)); + awacs_burgundy_busy_wait(); + out_le32(&awacs->codec_ctrl, addr + 0x200d00 +((val>>8) & 0xff)); + awacs_burgundy_busy_wait(); + out_le32(&awacs->codec_ctrl, addr + 0x200e00 +((val>>16) & 0xff)); + awacs_burgundy_busy_wait(); + out_le32(&awacs->codec_ctrl, addr + 0x200f00 +((val>>24) & 0xff)); + awacs_burgundy_busy_wait(); +} + +static unsigned +awacs_burgundy_rcw(unsigned addr) +{ + unsigned val = 0; + unsigned long flags; + + /* should have timeouts here */ + save_flags(flags); cli(); + + out_le32(&awacs->codec_ctrl, addr + 0x100000); + awacs_burgundy_busy_wait(); + awacs_burgundy_extend_wait(); + val += (in_le32(&awacs->codec_stat) >> 4) & 0xff; + + out_le32(&awacs->codec_ctrl, addr + 0x100100); + awacs_burgundy_busy_wait(); + awacs_burgundy_extend_wait(); + val += ((in_le32(&awacs->codec_stat)>>4) & 0xff) <<8; + + out_le32(&awacs->codec_ctrl, addr + 0x100200); + awacs_burgundy_busy_wait(); + awacs_burgundy_extend_wait(); + val += ((in_le32(&awacs->codec_stat)>>4) & 0xff) <<16; + + out_le32(&awacs->codec_ctrl, addr + 0x100300); + awacs_burgundy_busy_wait(); + awacs_burgundy_extend_wait(); + val += ((in_le32(&awacs->codec_stat)>>4) & 0xff) <<24; + + restore_flags(flags); + + return val; +} + + +static void +awacs_burgundy_wcb(unsigned addr, unsigned val) +{ + out_le32(&awacs->codec_ctrl, addr + 0x300000 + (val & 0xff)); + awacs_burgundy_busy_wait(); +} + +static unsigned +awacs_burgundy_rcb(unsigned addr) +{ + unsigned val = 0; + unsigned long flags; + + /* should have timeouts here */ + save_flags(flags); cli(); + + out_le32(&awacs->codec_ctrl, addr + 0x100000); + awacs_burgundy_busy_wait(); + awacs_burgundy_extend_wait(); + val += (in_le32(&awacs->codec_stat) >> 4) & 0xff; + + restore_flags(flags); + + return val; +} + +static int +awacs_burgundy_check(void) +{ + /* Checks to see the chip is alive and kicking */ + int error = in_le32(&awacs->codec_ctrl) & MASK_ERRCODE; + + return error == 0xf0000; +} + +static int +awacs_burgundy_init(void) +{ + if (awacs_burgundy_check()) { + printk(KERN_WARNING "AWACS: disabled by MacOS :-(\n"); + return 1; + } + + awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_OUTPUTENABLES, + DEF_BURGUNDY_OUTPUTENABLES); + awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, + DEF_BURGUNDY_MORE_OUTPUTENABLES); + awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_OUTPUTSELECTS, + DEF_BURGUNDY_OUTPUTSELECTS); + + awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_INPSEL21, + DEF_BURGUNDY_INPSEL21); + awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_INPSEL3, + DEF_BURGUNDY_INPSEL3); + awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_GAINCD, + DEF_BURGUNDY_GAINCD); + awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_GAINLINE, + DEF_BURGUNDY_GAINLINE); + awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_GAINMIC, + DEF_BURGUNDY_GAINMIC); + awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_GAINMODEM, + DEF_BURGUNDY_GAINMODEM); + + awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_ATTENSPEAKER, + DEF_BURGUNDY_ATTENSPEAKER); + awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_ATTENLINEOUT, + DEF_BURGUNDY_ATTENLINEOUT); + awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_ATTENHP, + DEF_BURGUNDY_ATTENHP); + + awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_MASTER_VOLUME, + DEF_BURGUNDY_MASTER_VOLUME); + awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_VOLCD, + DEF_BURGUNDY_VOLCD); + awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_VOLLINE, + DEF_BURGUNDY_VOLLINE); + awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_VOLMIC, + DEF_BURGUNDY_VOLMIC); + return 0; +} + +static void +awacs_burgundy_write_volume(unsigned address, int volume) +{ + int hardvolume,lvolume,rvolume; + + lvolume = (volume & 0xff) ? (volume & 0xff) + 155 : 0; + rvolume = ((volume >>8)&0xff) ? ((volume >> 8)&0xff ) + 155 : 0; + + hardvolume = lvolume + (rvolume << 16); + + awacs_burgundy_wcw(address, hardvolume); +} + +static int +awacs_burgundy_read_volume(unsigned address) +{ + int softvolume,wvolume; + + wvolume = awacs_burgundy_rcw(address); + + softvolume = (wvolume & 0xff) - 155; + softvolume += (((wvolume >> 16) & 0xff) - 155)<<8; + + return softvolume > 0 ? softvolume : 0; +} + + + + +static int +awacs_burgundy_read_mvolume(unsigned address) +{ + int lvolume,rvolume,wvolume; + + wvolume = awacs_burgundy_rcw(address); + + wvolume &= 0xffff; + + rvolume = (wvolume & 0xff) - 155; + lvolume = ((wvolume & 0xff00)>>8) - 155; + + return lvolume + (rvolume << 8); +} + + +static void +awacs_burgundy_write_mvolume(unsigned address, int volume) +{ + int lvolume,rvolume,hardvolume; + + lvolume = (volume &0xff) ? (volume & 0xff) + 155 :0; + rvolume = ((volume >>8) & 0xff) ? (volume >> 8) + 155 :0; + + hardvolume = lvolume + (rvolume << 8); + hardvolume += (hardvolume << 16); + + awacs_burgundy_wcw(address, hardvolume); +} + +/* End burgundy functions */ + + + + + +/* Turn on sound output, needed on G3 desktop powermacs */ +static void +awacs_enable_amp(int spkr_vol) +{ + struct adb_request req; + + awacs_spkr_vol = spkr_vol; + if (sys_ctrler != SYS_CTRLER_CUDA) + return; + + /* turn on headphones */ + cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, + 0x8a, 4, 0); + while (!req.complete) cuda_poll(); + cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, + 0x8a, 6, 0); + while (!req.complete) cuda_poll(); + + /* turn on speaker */ + cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, + 0x8a, 3, (100 - (spkr_vol & 0xff)) * 32 / 100); + while (!req.complete) cuda_poll(); + cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, + 0x8a, 5, (100 - ((spkr_vol >> 8) & 0xff)) * 32 / 100); + while (!req.complete) cuda_poll(); + + cuda_request(&req, NULL, 5, CUDA_PACKET, + CUDA_GET_SET_IIC, 0x8a, 1, 0x29); + while (!req.complete) cuda_poll(); +} + + +/*** Mid level stuff *********************************************************/ + + +/* + * /dev/mixer abstraction + */ + +static int PMacMixerIoctl(u_int cmd, u_long arg) +{ + int data; + /* Different IOCTLS for burgundy*/ + if (awacs_revision < AWACS_BURGUNDY) { + switch (cmd) { + case SOUND_MIXER_READ_DEVMASK: + data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER + | SOUND_MASK_LINE | SOUND_MASK_MIC + | SOUND_MASK_CD | SOUND_MASK_RECLEV + | SOUND_MASK_ALTPCM + | SOUND_MASK_MONITOR; + return IOCTL_OUT(arg, data); + case SOUND_MIXER_READ_RECMASK: + data = SOUND_MASK_LINE | SOUND_MASK_MIC + | SOUND_MASK_CD; + return IOCTL_OUT(arg, data); + case SOUND_MIXER_READ_RECSRC: + data = 0; + if (awacs_reg[0] & MASK_MUX_AUDIN) + data |= SOUND_MASK_LINE; + if (awacs_reg[0] & MASK_MUX_MIC) + data |= SOUND_MASK_MIC; + if (awacs_reg[0] & MASK_MUX_CD) + data |= SOUND_MASK_CD; + if (awacs_reg[1] & MASK_LOOPTHRU) + data |= SOUND_MASK_MONITOR; + return IOCTL_OUT(arg, data); + case SOUND_MIXER_WRITE_RECSRC: + IOCTL_IN(arg, data); + data &= (SOUND_MASK_LINE + | SOUND_MASK_MIC | SOUND_MASK_CD + | SOUND_MASK_MONITOR); + awacs_reg[0] &= ~(MASK_MUX_CD | MASK_MUX_MIC + | MASK_MUX_AUDIN); + awacs_reg[1] &= ~MASK_LOOPTHRU; + if (data & SOUND_MASK_LINE) + awacs_reg[0] |= MASK_MUX_AUDIN; + if (data & SOUND_MASK_MIC) + awacs_reg[0] |= MASK_MUX_MIC; + if (data & SOUND_MASK_CD) + awacs_reg[0] |= MASK_MUX_CD; + if (data & SOUND_MASK_MONITOR) + awacs_reg[1] |= MASK_LOOPTHRU; + awacs_write(awacs_reg[0] | MASK_ADDR0); + awacs_write(awacs_reg[1] | MASK_ADDR1); + return IOCTL_OUT(arg, data); + case SOUND_MIXER_READ_STEREODEVS: + data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER + | SOUND_MASK_RECLEV; + return IOCTL_OUT(arg, data); + case SOUND_MIXER_READ_CAPS: + return IOCTL_OUT(arg, 0); + case SOUND_MIXER_READ_VOLUME: + data = (awacs_reg[1] & MASK_AMUTE)? 0: + awacs_get_volume(awacs_reg[2], 6); + return IOCTL_OUT(arg, data); + case SOUND_MIXER_WRITE_VOLUME: + IOCTL_IN(arg, data); + return IOCTL_OUT(arg, dmasound_set_volume(data)); + case SOUND_MIXER_READ_SPEAKER: + if (awacs_revision == 3 + && sys_ctrler == SYS_CTRLER_CUDA) + data = awacs_spkr_vol; + else + data = (awacs_reg[1] & MASK_CMUTE)? 0: + awacs_get_volume(awacs_reg[4], 6); + return IOCTL_OUT(arg, data); + case SOUND_MIXER_WRITE_SPEAKER: + IOCTL_IN(arg, data); + if (awacs_revision == 3 + && sys_ctrler == SYS_CTRLER_CUDA) + awacs_enable_amp(data); + else + data = awacs_volume_setter(data, 4, MASK_CMUTE, 6); + return IOCTL_OUT(arg, data); + case SOUND_MIXER_WRITE_ALTPCM: /* really bell volume */ + IOCTL_IN(arg, data); + beep_volume = data & 0xff; + /* fall through */ + case SOUND_MIXER_READ_ALTPCM: + return IOCTL_OUT(arg, beep_volume); + case SOUND_MIXER_WRITE_LINE: + IOCTL_IN(arg, data); + awacs_reg[0] &= ~MASK_MUX_AUDIN; + if ((data & 0xff) >= 50) + awacs_reg[0] |= MASK_MUX_AUDIN; + awacs_write(MASK_ADDR0 | awacs_reg[0]); + /* fall through */ + case SOUND_MIXER_READ_LINE: + data = (awacs_reg[0] & MASK_MUX_AUDIN)? 100: 0; + return IOCTL_OUT(arg, data); + case SOUND_MIXER_WRITE_MIC: + IOCTL_IN(arg, data); + data &= 0xff; + awacs_reg[0] &= ~(MASK_MUX_MIC | MASK_GAINLINE); + if (data >= 25) { + awacs_reg[0] |= MASK_MUX_MIC; + if (data >= 75) + awacs_reg[0] |= MASK_GAINLINE; + } + awacs_write(MASK_ADDR0 | awacs_reg[0]); + /* fall through */ + case SOUND_MIXER_READ_MIC: + data = (awacs_reg[0] & MASK_MUX_MIC)? + (awacs_reg[0] & MASK_GAINLINE? 100: 50): 0; + return IOCTL_OUT(arg, data); + case SOUND_MIXER_WRITE_CD: + IOCTL_IN(arg, data); + awacs_reg[0] &= ~MASK_MUX_CD; + if ((data & 0xff) >= 50) + awacs_reg[0] |= MASK_MUX_CD; + awacs_write(MASK_ADDR0 | awacs_reg[0]); + /* fall through */ + case SOUND_MIXER_READ_CD: + data = (awacs_reg[0] & MASK_MUX_CD)? 100: 0; + return IOCTL_OUT(arg, data); + case SOUND_MIXER_WRITE_RECLEV: + IOCTL_IN(arg, data); + data = awacs_volume_setter(data, 0, 0, 4); + return IOCTL_OUT(arg, data); + case SOUND_MIXER_READ_RECLEV: + data = awacs_get_volume(awacs_reg[0], 4); + return IOCTL_OUT(arg, data); + } + } else { + /* We are, we are, we are... Burgundy or better */ + switch(cmd) { + case SOUND_MIXER_READ_DEVMASK: + data = SOUND_MASK_VOLUME | SOUND_MASK_CD | + SOUND_MASK_LINE | SOUND_MASK_MIC | + SOUND_MASK_SPEAKER | SOUND_MASK_ALTPCM; + return IOCTL_OUT(arg, data); + case SOUND_MIXER_READ_RECMASK: + data = SOUND_MASK_LINE | SOUND_MASK_MIC + | SOUND_MASK_CD; + return IOCTL_OUT(arg, data); + case SOUND_MIXER_READ_RECSRC: + data = 0; + if (awacs_reg[0] & MASK_MUX_AUDIN) + data |= SOUND_MASK_LINE; + if (awacs_reg[0] & MASK_MUX_MIC) + data |= SOUND_MASK_MIC; + if (awacs_reg[0] & MASK_MUX_CD) + data |= SOUND_MASK_CD; + return IOCTL_OUT(arg, data); + case SOUND_MIXER_WRITE_RECSRC: + IOCTL_IN(arg, data); + data &= (SOUND_MASK_LINE + | SOUND_MASK_MIC | SOUND_MASK_CD); + awacs_reg[0] &= ~(MASK_MUX_CD | MASK_MUX_MIC + | MASK_MUX_AUDIN); + if (data & SOUND_MASK_LINE) + awacs_reg[0] |= MASK_MUX_AUDIN; + if (data & SOUND_MASK_MIC) + awacs_reg[0] |= MASK_MUX_MIC; + if (data & SOUND_MASK_CD) + awacs_reg[0] |= MASK_MUX_CD; + awacs_write(awacs_reg[0] | MASK_ADDR0); + return IOCTL_OUT(arg, data); + case SOUND_MIXER_READ_STEREODEVS: + data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER + | SOUND_MASK_RECLEV | SOUND_MASK_CD + | SOUND_MASK_LINE; + return IOCTL_OUT(arg, data); + case SOUND_MIXER_READ_CAPS: + return IOCTL_OUT(arg, 0); + case SOUND_MIXER_WRITE_VOLUME: + IOCTL_IN(arg, data); + awacs_burgundy_write_mvolume(MASK_ADDR_BURGUNDY_MASTER_VOLUME, data); + /* Fall through */ + case SOUND_MIXER_READ_VOLUME: + return IOCTL_OUT(arg, awacs_burgundy_read_mvolume(MASK_ADDR_BURGUNDY_MASTER_VOLUME)); + case SOUND_MIXER_WRITE_SPEAKER: + IOCTL_IN(arg, data); + + if (!(data & 0xff)) { + /* Mute the left speaker */ + awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, + awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) & ~0x2); + } else { + /* Unmute the left speaker */ + awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, + awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) | 0x2); + } + if (!(data & 0xff00)) { + /* Mute the right speaker */ + awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, + awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) & ~0x4); + } else { + /* Unmute the right speaker */ + awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, + awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) | 0x4); + } + + data = (((data&0xff)*16)/100 > 0xf ? 0xf : + (((data&0xff)*16)/100)) + + ((((data>>8)*16)/100 > 0xf ? 0xf : + ((((data>>8)*16)/100)))<<4); + + awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_ATTENSPEAKER, ~data); + /* Fall through */ + case SOUND_MIXER_READ_SPEAKER: + data = awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_ATTENSPEAKER); + data = (((data & 0xf)*100)/16) + ((((data>>4)*100)/16)<<8); + return IOCTL_OUT(arg, ~data); + case SOUND_MIXER_WRITE_ALTPCM: /* really bell volume */ + IOCTL_IN(arg, data); + beep_volume = data & 0xff; + /* fall through */ + case SOUND_MIXER_READ_ALTPCM: + return IOCTL_OUT(arg, beep_volume); + case SOUND_MIXER_WRITE_LINE: + IOCTL_IN(arg, data); + awacs_burgundy_write_volume(MASK_ADDR_BURGUNDY_VOLLINE, data); + + /* fall through */ + case SOUND_MIXER_READ_LINE: + data = awacs_burgundy_read_volume(MASK_ADDR_BURGUNDY_VOLLINE); + return IOCTL_OUT(arg, data); + case SOUND_MIXER_WRITE_MIC: + IOCTL_IN(arg, data); + /* Mic is mono device */ + data = (data << 8) + (data << 24); + awacs_burgundy_write_volume(MASK_ADDR_BURGUNDY_VOLMIC, data); + /* fall through */ + case SOUND_MIXER_READ_MIC: + data = awacs_burgundy_read_volume(MASK_ADDR_BURGUNDY_VOLMIC); + data <<= 24; + return IOCTL_OUT(arg, data); + case SOUND_MIXER_WRITE_CD: + IOCTL_IN(arg, data); + awacs_burgundy_write_volume(MASK_ADDR_BURGUNDY_VOLCD, data); + /* fall through */ + case SOUND_MIXER_READ_CD: + data = awacs_burgundy_read_volume(MASK_ADDR_BURGUNDY_VOLCD); + return IOCTL_OUT(arg, data); + case SOUND_MIXER_WRITE_RECLEV: + IOCTL_IN(arg, data); + data = awacs_volume_setter(data, 0, 0, 4); + return IOCTL_OUT(arg, data); + case SOUND_MIXER_READ_RECLEV: + data = awacs_get_volume(awacs_reg[0], 4); + return IOCTL_OUT(arg, data); + case SOUND_MIXER_OUTMASK: + break; + case SOUND_MIXER_OUTSRC: + break; + } + } + return -EINVAL; +} + + +static void PMacWriteSqSetup(void) +{ + int i; + volatile struct dbdma_cmd *cp; + + cp = awacs_tx_cmds; + memset((void *)cp, 0, (write_sq.numBufs+1) * sizeof(struct dbdma_cmd)); + for (i = 0; i < write_sq.numBufs; ++i, ++cp) { + st_le32(&cp->phy_addr, virt_to_bus(write_sq.buffers[i])); + } + st_le16(&cp->command, DBDMA_NOP + BR_ALWAYS); + st_le32(&cp->cmd_dep, virt_to_bus(awacs_tx_cmds)); + out_le32(&awacs_txdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16); + out_le32(&awacs_txdma->cmdptr, virt_to_bus(awacs_tx_cmds)); +} + +static void PMacReadSqSetup(void) +{ + int i; + volatile struct dbdma_cmd *cp; + + cp = awacs_rx_cmds; + memset((void *)cp, 0, (read_sq.numBufs+1) * sizeof(struct dbdma_cmd)); + + /* Set dma buffers up in a loop */ + for (i = 0; i < read_sq.numBufs; i++,cp++) { + st_le32(&cp->phy_addr, virt_to_bus(read_sq.buffers[i])); + st_le16(&cp->command, INPUT_MORE + INTR_ALWAYS); + st_le16(&cp->req_count, read_sq.block_size); + st_le16(&cp->xfer_status, 0); + } + + /* The next two lines make the thing loop around. + */ + st_le16(&cp->command, DBDMA_NOP + BR_ALWAYS); + st_le32(&cp->cmd_dep, virt_to_bus(awacs_rx_cmds)); + + /* Don't start until the first read is done. + * This will also abort any operations in progress if the DMA + * happens to be running (and it shouldn't). + */ + out_le32(&awacs_rxdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16); + out_le32(&awacs_rxdma->cmdptr, virt_to_bus(awacs_rx_cmds)); + +} + +static void PMacAbortRead(void) +{ + int i; + volatile struct dbdma_cmd *cp; + + cp = awacs_rx_cmds; + for (i = 0; i < read_sq.numBufs; i++,cp++) + st_le16(&cp->command, DBDMA_STOP); + /* + * We should probably wait for the thing to stop before we + * release the memory + */ +} + + +/*** Machine definitions *****************************************************/ + + +static MACHINE machPMac = { + name: awacs_name, + name2: "AWACS", + open: PMacOpen, + release: PMacRelease, + dma_alloc: PMacAlloc, + dma_free: PMacFree, + irqinit: PMacIrqInit, +#ifdef MODULE + irqcleanup: PMacIrqCleanup, +#endif /* MODULE */ + init: PMacInit, + silence: PMacSilence, + setFormat: PMacSetFormat, + setVolume: PMacSetVolume, + play: PMacPlay, + record: PMacRecord, + mixer_ioctl: PMacMixerIoctl, + write_sq_setup: PMacWriteSqSetup, + read_sq_setup: PMacReadSqSetup, + abort_read: PMacAbortRead, + min_dsp_speed: 8000 +}; + + +/*** Config & Setup **********************************************************/ + + +int __init dmasound_awacs_init(void) +{ + struct device_node *np; + + if (_machine != _MACH_Pmac) + return -ENODEV; + + awacs_subframe = 0; + awacs_revision = 0; + np = find_devices("awacs"); + if (np == 0) { + /* + * powermac G3 models have a node called "davbus" + * with a child called "sound". + */ + struct device_node *sound; + np = find_devices("davbus"); + sound = find_devices("sound"); + if (sound != 0 && sound->parent == np) { + unsigned int *prop, l, i; + prop = (unsigned int *) + get_property(sound, "sub-frame", 0); + if (prop != 0 && *prop >= 0 && *prop < 16) + awacs_subframe = *prop; + if (device_is_compatible(sound, "burgundy")) + awacs_revision = AWACS_BURGUNDY; + + /* look for a property saying what sample rates + are available */ + for (i = 0; i < 8; ++i) + awacs_freqs_ok[i] = 0; + prop = (unsigned int *) get_property + (sound, "sample-rates", &l); + if (prop == 0) + prop = (unsigned int *) get_property + (sound, "output-frame-rates", &l); + if (prop != 0) { + for (l /= sizeof(int); l > 0; --l) { + /* sometimes the rate is in the + high-order 16 bits (?) */ + unsigned int r = *prop++; + if (r >= 0x10000) + r >>= 16; + for (i = 0; i < 8; ++i) { + if (r == awacs_freqs[i]) { + awacs_freqs_ok[i] = 1; + break; + } + } + } + } else { + /* assume just 44.1k is OK */ + awacs_freqs_ok[0] = 1; + } + } + } + if (np != NULL && np->n_addrs >= 3 && np->n_intrs >= 3) { + int vol; + dmasound.mach = machPMac; + + awacs = (volatile struct awacs_regs *) + ioremap(np->addrs[0].address, 0x80); + awacs_txdma = (volatile struct dbdma_regs *) + ioremap(np->addrs[1].address, 0x100); + awacs_rxdma = (volatile struct dbdma_regs *) + ioremap(np->addrs[2].address, 0x100); + + awacs_irq = np->intrs[0].line; + awacs_tx_irq = np->intrs[1].line; + awacs_rx_irq = np->intrs[2].line; + + awacs_tx_cmd_space = kmalloc((write_sq.numBufs + 4) * sizeof(struct dbdma_cmd), + GFP_KERNEL); + if (awacs_tx_cmd_space == NULL) { + printk(KERN_ERR "DMA sound driver: Not enough buffer memory, driver disabled!\n"); + return -ENOMEM; + } + awacs_node = np; +#ifdef CONFIG_PMAC_PBOOK + if (machine_is_compatible("PowerBook1,1") + || machine_is_compatible("AAPL,PowerBook1998")) { + feature_set(np, FEATURE_Sound_CLK_enable); + feature_set(np, FEATURE_Sound_power); + /* Shorter delay will not work */ + mdelay(1000); + } +#endif + awacs_tx_cmds = (volatile struct dbdma_cmd *) + DBDMA_ALIGN(awacs_tx_cmd_space); + + + awacs_rx_cmd_space = kmalloc((read_sq.numBufs + 4) * sizeof(struct dbdma_cmd), + GFP_KERNEL); + if (awacs_rx_cmd_space == NULL) { + printk("DMA sound driver: No memory for input"); + } + awacs_rx_cmds = (volatile struct dbdma_cmd *) + DBDMA_ALIGN(awacs_rx_cmd_space); + + + + awacs_reg[0] = MASK_MUX_CD; + awacs_reg[1] = MASK_LOOPTHRU | MASK_PAROUT; + /* get default volume from nvram */ + vol = (~nvram_read_byte(0x1308) & 7) << 1; + awacs_reg[2] = vol + (vol << 6); + awacs_reg[4] = vol + (vol << 6); + out_le32(&awacs->control, 0x11); + awacs_write(awacs_reg[0] + MASK_ADDR0); + awacs_write(awacs_reg[1] + MASK_ADDR1); + awacs_write(awacs_reg[2] + MASK_ADDR2); + awacs_write(awacs_reg[4] + MASK_ADDR4); + + /* Initialize recent versions of the awacs */ + if (awacs_revision == 0) { + awacs_revision = + (in_le32(&awacs->codec_stat) >> 12) & 0xf; + if (awacs_revision == 3) { + mdelay(100); + awacs_write(0x6000); + mdelay(2); + awacs_write(awacs_reg[1] + MASK_ADDR1); + awacs_enable_amp(100 * 0x101); + } + } + if (awacs_revision >= AWACS_BURGUNDY) + awacs_burgundy_init(); + + /* Initialize beep stuff */ + beep_dbdma_cmd = awacs_tx_cmds + (write_sq.numBufs + 1); + orig_mksound = kd_mksound; + kd_mksound = awacs_mksound; + beep_buf = (short *) kmalloc(BEEP_BUFLEN * 4, GFP_KERNEL); + if (beep_buf == NULL) + printk(KERN_WARNING "dmasound: no memory for " + "beep buffer\n"); +#ifdef CONFIG_PMAC_PBOOK + pmu_register_sleep_notifier(&awacs_sleep_notifier); +#endif /* CONFIG_PMAC_PBOOK */ + + /* Powerbooks have odd ways of enabling inputs such as + an expansion-bay CD or sound from an internal modem + or a PC-card modem. */ + if (machine_is_compatible("AAPL,3400/2400") + || machine_is_compatible("AAPL,3500")) { + is_pbook_3400 = 1; + /* + * Enable CD and PC-card sound inputs. + * This is done by reading from address + * f301a000, + 0x10 to enable the expansion-bay + * CD sound input, + 0x80 to enable the PC-card + * sound input. The 0x100 enables the SCSI bus + * terminator power. + */ + latch_base = (unsigned char *) ioremap + (0xf301a000, 0x1000); + in_8(latch_base + 0x190); + } else if (machine_is_compatible("PowerBook1,1") + || machine_is_compatible("AAPL,PowerBook1998")) { + struct device_node* mio; + macio_base = 0; + is_pbook_G3 = 1; + for (mio = np->parent; mio; mio = mio->parent) { + if (strcmp(mio->name, "mac-io") == 0 + && mio->n_addrs > 0) { + macio_base = (unsigned char *) ioremap + (mio->addrs[0].address, 0x40); + break; + } + } + /* enable CD sound input */ + if (macio_base) + out_8(macio_base + 0x37, 3); + } + sprintf(awacs_name, "PowerMac (AWACS rev %d) ", + awacs_revision); + return dmasound_init(); + } + return -ENODEV; +} + +static void __exit dmasound_awacs_cleanup(void) +{ + dmasound_deinit(); +} + +module_init(dmasound_awacs_init); +module_exit(dmasound_awacs_cleanup); diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/sound/dmasound/dmasound_core.c linux/drivers/sound/dmasound/dmasound_core.c --- v2.3.99-pre3/linux/drivers/sound/dmasound/dmasound_core.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/sound/dmasound/dmasound_core.c Mon Apr 10 22:58:59 2000 @@ -0,0 +1,1313 @@ + +/* + * linux/drivers/sound/dmasound.c + * + * + * OSS/Free compatible Atari TT/Falcon and Amiga DMA sound driver for + * Linux/m68k + * Extended to support Power Macintosh for Linux/ppc by Paul Mackerras + * + * (c) 1995 by Michael Schlueter & Michael Marte + * + * Michael Schlueter (michael@duck.syd.de) did the basic structure of the VFS + * interface and the u-law to signed byte conversion. + * + * Michael Marte (marte@informatik.uni-muenchen.de) did the sound queue, + * /dev/mixer, /dev/sndstat and complemented the VFS interface. He would like + * to thank: + * - Michael Schlueter for initial ideas and documentation on the MFP and + * the DMA sound hardware. + * - Therapy? for their CD 'Troublegum' which really made me rock. + * + * /dev/sndstat is based on code by Hannu Savolainen, the author of the + * VoxWare family of drivers. + * + * 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. + * + * History: + * + * 1995/8/25 First release + * + * 1995/9/02 Roman Hodek: + * - Fixed atari_stram_alloc() call, the timer + * programming and several race conditions + * 1995/9/14 Roman Hodek: + * - After some discussion with Michael Schlueter, + * revised the interrupt disabling + * - Slightly speeded up U8->S8 translation by using + * long operations where possible + * - Added 4:3 interpolation for /dev/audio + * + * 1995/9/20 Torsten Scherer: + * - Fixed a bug in sq_write and changed /dev/audio + * converting to play at 12517Hz instead of 6258Hz. + * + * 1995/9/23 Torsten Scherer: + * - Changed sq_interrupt() and sq_play() to pre-program + * the DMA for another frame while there's still one + * running. This allows the IRQ response to be + * arbitrarily delayed and playing will still continue. + * + * 1995/10/14 Guenther Kelleter, Torsten Scherer: + * - Better support for Falcon audio (the Falcon doesn't + * raise an IRQ at the end of a frame, but at the + * beginning instead!). uses 'if (codec_dma)' in lots + * of places to simply switch between Falcon and TT + * code. + * + * 1995/11/06 Torsten Scherer: + * - Started introducing a hardware abstraction scheme + * (may perhaps also serve for Amigas?) + * - Can now play samples at almost all frequencies by + * means of a more generalized expand routine + * - Takes a good deal of care to cut data only at + * sample sizes + * - Buffer size is now a kernel runtime option + * - Implemented fsync() & several minor improvements + * Guenther Kelleter: + * - Useful hints and bug fixes + * - Cross-checked it for Falcons + * + * 1996/3/9 Geert Uytterhoeven: + * - Support added for Amiga, A-law, 16-bit little + * endian. + * - Unification to drivers/sound/dmasound.c. + * + * 1996/4/6 Martin Mitchell: + * - Updated to 1.3 kernel. + * + * 1996/6/13 Topi Kanerva: + * - Fixed things that were broken (mainly the amiga + * 14-bit routines) + * - /dev/sndstat shows now the real hardware frequency + * - The lowpass filter is disabled by default now + * + * 1996/9/25 Geert Uytterhoeven: + * - Modularization + * + * 1998/6/10 Andreas Schwab: + * - Converted to use sound_core + * + * 1999/12/28 Richard Zidlicky: + * - Added support for Q40 + * + * 2000/2/27 Geert Uytterhoeven: + * - Clean up and split the code into 4 parts: + * o dmasound_core: machine-independent code + * o dmasound_atari: Atari TT and Falcon support + * o dmasound_awacs: Apple PowerMac support + * o dmasound_paula: Amiga support + * + * 2000/3/25 Geert Uytterhoeven: + * - Integration of dmasound_q40 + * - Small clean ups + */ + + +#include +#include +#include +#include +#include + +#include + +#include "dmasound.h" + + + /* + * Declarations + */ + +int dmasound_catchRadius = 0; +static unsigned int numWriteBufs = 4; +static unsigned int writeBufSize = 32; /* in KB! */ +#ifdef HAS_RECORD +static unsigned int numReadBufs = 4; +static unsigned int readBufSize = 32; /* in KB! */ +#endif + +MODULE_PARM(dmasound_catchRadius, "i"); +MODULE_PARM(numWriteBufs, "i"); +MODULE_PARM(writeBufSize, "i"); +MODULE_PARM(numReadBufs, "i"); +MODULE_PARM(readBufSize, "i"); + +#ifdef MODULE +static int sq_unit = -1; +static int mixer_unit = -1; +static int state_unit = -1; +static int irq_installed = 0; +#endif /* MODULE */ + + + /* + * Conversion tables + */ + +#ifdef HAS_8BIT_TABLES +/* 8 bit mu-law */ + +char dmasound_ulaw2dma8[] = { + -126, -122, -118, -114, -110, -106, -102, -98, + -94, -90, -86, -82, -78, -74, -70, -66, + -63, -61, -59, -57, -55, -53, -51, -49, + -47, -45, -43, -41, -39, -37, -35, -33, + -31, -30, -29, -28, -27, -26, -25, -24, + -23, -22, -21, -20, -19, -18, -17, -16, + -16, -15, -15, -14, -14, -13, -13, -12, + -12, -11, -11, -10, -10, -9, -9, -8, + -8, -8, -7, -7, -7, -7, -6, -6, + -6, -6, -5, -5, -5, -5, -4, -4, + -4, -4, -4, -4, -3, -3, -3, -3, + -3, -3, -3, -3, -2, -2, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -2, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 0, + 125, 121, 117, 113, 109, 105, 101, 97, + 93, 89, 85, 81, 77, 73, 69, 65, + 62, 60, 58, 56, 54, 52, 50, 48, + 46, 44, 42, 40, 38, 36, 34, 32, + 30, 29, 28, 27, 26, 25, 24, 23, + 22, 21, 20, 19, 18, 17, 16, 15, + 15, 14, 14, 13, 13, 12, 12, 11, + 11, 10, 10, 9, 9, 8, 8, 7, + 7, 7, 6, 6, 6, 6, 5, 5, + 5, 5, 4, 4, 4, 4, 3, 3, + 3, 3, 3, 3, 2, 2, 2, 2, + 2, 2, 2, 2, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* 8 bit A-law */ + +char dmasound_alaw2dma8[] = { + -22, -21, -24, -23, -18, -17, -20, -19, + -30, -29, -32, -31, -26, -25, -28, -27, + -11, -11, -12, -12, -9, -9, -10, -10, + -15, -15, -16, -16, -13, -13, -14, -14, + -86, -82, -94, -90, -70, -66, -78, -74, + -118, -114, -126, -122, -102, -98, -110, -106, + -43, -41, -47, -45, -35, -33, -39, -37, + -59, -57, -63, -61, -51, -49, -55, -53, + -2, -2, -2, -2, -2, -2, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -2, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -6, -6, -6, -6, -5, -5, -5, -5, + -8, -8, -8, -8, -7, -7, -7, -7, + -3, -3, -3, -3, -3, -3, -3, -3, + -4, -4, -4, -4, -4, -4, -4, -4, + 21, 20, 23, 22, 17, 16, 19, 18, + 29, 28, 31, 30, 25, 24, 27, 26, + 10, 10, 11, 11, 8, 8, 9, 9, + 14, 14, 15, 15, 12, 12, 13, 13, + 86, 82, 94, 90, 70, 66, 78, 74, + 118, 114, 126, 122, 102, 98, 110, 106, + 43, 41, 47, 45, 35, 33, 39, 37, + 59, 57, 63, 61, 51, 49, 55, 53, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 4, 4, 4, 4, + 7, 7, 7, 7, 6, 6, 6, 6, + 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3 +}; +#endif /* HAS_8BIT_TABLES */ + +#ifdef HAS_16BIT_TABLES + +/* 16 bit mu-law */ + +short dmasound_ulaw2dma16[] = { + -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956, + -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764, + -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412, + -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316, + -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140, + -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092, + -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004, + -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980, + -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436, + -1372, -1308, -1244, -1180, -1116, -1052, -988, -924, + -876, -844, -812, -780, -748, -716, -684, -652, + -620, -588, -556, -524, -492, -460, -428, -396, + -372, -356, -340, -324, -308, -292, -276, -260, + -244, -228, -212, -196, -180, -164, -148, -132, + -120, -112, -104, -96, -88, -80, -72, -64, + -56, -48, -40, -32, -24, -16, -8, 0, + 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956, + 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764, + 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412, + 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316, + 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140, + 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092, + 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004, + 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980, + 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436, + 1372, 1308, 1244, 1180, 1116, 1052, 988, 924, + 876, 844, 812, 780, 748, 716, 684, 652, + 620, 588, 556, 524, 492, 460, 428, 396, + 372, 356, 340, 324, 308, 292, 276, 260, + 244, 228, 212, 196, 180, 164, 148, 132, + 120, 112, 104, 96, 88, 80, 72, 64, + 56, 48, 40, 32, 24, 16, 8, 0, +}; + +/* 16 bit A-law */ + +short dmasound_alaw2dma16[] = { + -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736, + -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, + -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368, + -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392, + -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944, + -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136, + -11008, -10496, -12032, -11520, -8960, -8448, -9984, -9472, + -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568, + -344, -328, -376, -360, -280, -264, -312, -296, + -472, -456, -504, -488, -408, -392, -440, -424, + -88, -72, -120, -104, -24, -8, -56, -40, + -216, -200, -248, -232, -152, -136, -184, -168, + -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184, + -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, + -688, -656, -752, -720, -560, -528, -624, -592, + -944, -912, -1008, -976, -816, -784, -880, -848, + 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736, + 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, + 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368, + 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, + 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944, + 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, + 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472, + 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, + 344, 328, 376, 360, 280, 264, 312, 296, + 472, 456, 504, 488, 408, 392, 440, 424, + 88, 72, 120, 104, 24, 8, 56, 40, + 216, 200, 248, 232, 152, 136, 184, 168, + 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184, + 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, + 688, 656, 752, 720, 560, 528, 624, 592, + 944, 912, 1008, 976, 816, 784, 880, 848, +}; +#endif /* HAS_16BIT_TABLES */ + + +#ifdef HAS_14BIT_TABLES + + /* + * Unused for now. Where are the MSB parts anyway?? + */ + +/* 14 bit mu-law (LSB) */ + +char dmasound_ulaw2dma14l[] = { + 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 49, 17, 49, 17, 49, 17, 49, 17, + 49, 17, 49, 17, 49, 17, 49, 17, + 41, 57, 9, 25, 41, 57, 9, 25, + 41, 57, 9, 25, 41, 57, 9, 25, + 37, 45, 53, 61, 5, 13, 21, 29, + 37, 45, 53, 61, 5, 13, 21, 29, + 35, 39, 43, 47, 51, 55, 59, 63, + 3, 7, 11, 15, 19, 23, 27, 31, + 34, 36, 38, 40, 42, 44, 46, 48, + 50, 52, 54, 56, 58, 60, 62, 0, + 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, + 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, + 15, 47, 15, 47, 15, 47, 15, 47, + 15, 47, 15, 47, 15, 47, 15, 47, + 23, 7, 55, 39, 23, 7, 55, 39, + 23, 7, 55, 39, 23, 7, 55, 39, + 27, 19, 11, 3, 59, 51, 43, 35, + 27, 19, 11, 3, 59, 51, 43, 35, + 29, 25, 21, 17, 13, 9, 5, 1, + 61, 57, 53, 49, 45, 41, 37, 33, + 30, 28, 26, 24, 22, 20, 18, 16, + 14, 12, 10, 8, 6, 4, 2, 0 +}; + +/* 14 bit A-law (LSB) */ + +char dmasound_alaw2dma14l[] = { + 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, + 16, 48, 16, 48, 16, 48, 16, 48, + 16, 48, 16, 48, 16, 48, 16, 48, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 42, 46, 34, 38, 58, 62, 50, 54, + 10, 14, 2, 6, 26, 30, 18, 22, + 42, 46, 34, 38, 58, 62, 50, 54, + 10, 14, 2, 6, 26, 30, 18, 22, + 40, 56, 8, 24, 40, 56, 8, 24, + 40, 56, 8, 24, 40, 56, 8, 24, + 20, 28, 4, 12, 52, 60, 36, 44, + 20, 28, 4, 12, 52, 60, 36, 44, + 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, + 48, 16, 48, 16, 48, 16, 48, 16, + 48, 16, 48, 16, 48, 16, 48, 16, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 22, 18, 30, 26, 6, 2, 14, 10, + 54, 50, 62, 58, 38, 34, 46, 42, + 22, 18, 30, 26, 6, 2, 14, 10, + 54, 50, 62, 58, 38, 34, 46, 42, + 24, 8, 56, 40, 24, 8, 56, 40, + 24, 8, 56, 40, 24, 8, 56, 40, + 44, 36, 60, 52, 12, 4, 28, 20, + 44, 36, 60, 52, 12, 4, 28, 20 +}; +#endif /* HAS_14BIT_TABLES */ + + + /* + * Common stuff + */ + +static long long sound_lseek(struct file *file, long long offset, int orig) +{ + return -ESPIPE; +} + + + /* + * Mid level stuff + */ + +struct sound_settings dmasound; + +static inline void sound_silence(void) +{ + /* update hardware settings one more */ + dmasound.mach.init(); + + dmasound.mach.silence(); +} + +static inline void sound_init(void) +{ + dmasound.mach.init(); +} + +static inline int sound_set_format(int format) +{ + return dmasound.mach.setFormat(format); +} + +static int sound_set_speed(int speed) +{ + if (speed < 0) + return dmasound.soft.speed; + + dmasound.soft.speed = speed; + dmasound.mach.init(); + if (dmasound.minDev == SND_DEV_DSP) + dmasound.dsp.speed = dmasound.soft.speed; + + return dmasound.soft.speed; +} + +static int sound_set_stereo(int stereo) +{ + if (stereo < 0) + return dmasound.soft.stereo; + + stereo = !!stereo; /* should be 0 or 1 now */ + + dmasound.soft.stereo = stereo; + if (dmasound.minDev == SND_DEV_DSP) + dmasound.dsp.stereo = stereo; + dmasound.mach.init(); + + return stereo; +} + +static ssize_t sound_copy_translate(TRANS *trans, const u_char *userPtr, + size_t userCount, u_char frame[], + ssize_t *frameUsed, ssize_t frameLeft) +{ + ssize_t (*ct_func)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); + + switch (dmasound.soft.format) { + case AFMT_MU_LAW: + ct_func = trans->ct_ulaw; + break; + case AFMT_A_LAW: + ct_func = trans->ct_alaw; + break; + case AFMT_S8: + ct_func = trans->ct_s8; + break; + case AFMT_U8: + ct_func = trans->ct_u8; + break; + case AFMT_S16_BE: + ct_func = trans->ct_s16be; + break; + case AFMT_U16_BE: + ct_func = trans->ct_u16be; + break; + case AFMT_S16_LE: + ct_func = trans->ct_s16le; + break; + case AFMT_U16_LE: + ct_func = trans->ct_u16le; + break; + default: + return 0; + } + return ct_func(userPtr, userCount, frame, frameUsed, frameLeft); +} + + + /* + * /dev/mixer abstraction + */ + +static struct { + int busy; + int modify_counter; +} mixer; + +static int mixer_open(struct inode *inode, struct file *file) +{ + MOD_INC_USE_COUNT; + dmasound.mach.open(); + mixer.busy = 1; + return 0; +} + +static int mixer_release(struct inode *inode, struct file *file) +{ + mixer.busy = 0; + dmasound.mach.release(); + MOD_DEC_USE_COUNT; + return 0; +} +static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg) +{ + if (_SIOC_DIR(cmd) & _SIOC_WRITE) + mixer.modify_counter++; + switch (cmd) { + case OSS_GETVERSION: + return IOCTL_OUT(arg, SOUND_VERSION); + case SOUND_MIXER_INFO: + { + mixer_info info; + strncpy(info.id, dmasound.mach.name2, sizeof(info.id)); + strncpy(info.name, dmasound.mach.name2, sizeof(info.name)); + info.name[sizeof(info.name)-1] = 0; + info.modify_counter = mixer.modify_counter; + copy_to_user_ret((int *)arg, &info, sizeof(info), -EFAULT); + return 0; + } + } + if (dmasound.mach.mixer_ioctl) + return dmasound.mach.mixer_ioctl(cmd, arg); + return -EINVAL; +} + +static struct file_operations mixer_fops = +{ + llseek: sound_lseek, + ioctl: mixer_ioctl, + open: mixer_open, + release: mixer_release, +}; + +static void __init mixer_init(void) +{ +#ifndef MODULE + int mixer_unit; +#endif + mixer_unit = register_sound_mixer(&mixer_fops, -1); + if (mixer_unit < 0) + return; + + mixer.busy = 0; + dmasound.treble = 0; + dmasound.bass = 0; + if (dmasound.mach.mixer_init) + dmasound.mach.mixer_init(); +} + + + /* + * Sound queue stuff, the heart of the driver + */ + +struct sound_queue dmasound_write_sq; +#ifdef HAS_RECORD +struct sound_queue dmasound_read_sq; +#endif + +static int sq_allocate_buffers(struct sound_queue *sq, int num, int size) +{ + int i; + + if (sq->buffers) + return 0; + sq->numBufs = num; + sq->bufSize = size; + sq->buffers = kmalloc (num * sizeof(char *), GFP_KERNEL); + if (!sq->buffers) + return -ENOMEM; + for (i = 0; i < num; i++) { + sq->buffers[i] = dmasound.mach.dma_alloc(size, GFP_KERNEL); + if (!sq->buffers[i]) { + while (i--) + dmasound.mach.dma_free(sq->buffers[i], size); + kfree(sq->buffers); + sq->buffers = 0; + return -ENOMEM; + } + } + return 0; +} + +static void sq_release_buffers(struct sound_queue *sq) +{ + int i; + + if (sq->buffers) { + if (sq != &write_sq && dmasound.mach.abort_read) + dmasound.mach.abort_read(); + for (i = 0; i < sq->numBufs; i++) + dmasound.mach.dma_free(sq->buffers[i], sq->bufSize); + kfree(sq->buffers); + sq->buffers = NULL; + } +} + +static void sq_setup(struct sound_queue *sq, int max_count, int max_active, + int block_size) +{ + void (*setup_func)(void); + + sq->max_count = max_count; + sq->max_active = max_active; + sq->block_size = block_size; + + sq->front = sq->count = sq->rear_size = 0; + sq->syncing = 0; + sq->active = 0; + + if (sq == &write_sq) { + sq->rear = -1; + setup_func = dmasound.mach.write_sq_setup; + } else { + sq->rear = 0; + setup_func = dmasound.mach.read_sq_setup; + } + if (setup_func) + setup_func(); +} + +static inline void sq_play(void) +{ + dmasound.mach.play(); +} + +static ssize_t sq_write(struct file *file, const char *src, size_t uLeft, + loff_t *ppos) +{ + ssize_t uWritten = 0; + u_char *dest; + ssize_t uUsed, bUsed, bLeft; + + /* ++TeSche: Is something like this necessary? + * Hey, that's an honest question! Or does any other part of the + * filesystem already checks this situation? I really don't know. + */ + if (uLeft == 0) + return 0; + + /* The interrupt doesn't start to play the last, incomplete frame. + * Thus we can append to it without disabling the interrupts! (Note + * also that write_sq.rear isn't affected by the interrupt.) + */ + + if (write_sq.count > 0 && + (bLeft = write_sq.block_size-write_sq.rear_size) > 0) { + dest = write_sq.buffers[write_sq.rear]; + bUsed = write_sq.rear_size; + uUsed = sound_copy_translate(dmasound.trans_write, src, uLeft, + dest, &bUsed, bLeft); + if (uUsed <= 0) + return uUsed; + src += uUsed; + uWritten += uUsed; + uLeft -= uUsed; + write_sq.rear_size = bUsed; + } + + do { + while (write_sq.count == write_sq.max_active) { + sq_play(); + if (write_sq.open_mode & O_NONBLOCK) + return uWritten > 0 ? uWritten : -EAGAIN; + SLEEP(write_sq.action_queue); + if (signal_pending(current)) + return uWritten > 0 ? uWritten : -EINTR; + } + + /* Here, we can avoid disabling the interrupt by first + * copying and translating the data, and then updating + * the write_sq variables. Until this is done, the interrupt + * won't see the new frame and we can work on it + * undisturbed. + */ + + dest = write_sq.buffers[(write_sq.rear+1) % write_sq.max_count]; + bUsed = 0; + bLeft = write_sq.block_size; + uUsed = sound_copy_translate(dmasound.trans_write, src, uLeft, + dest, &bUsed, bLeft); + if (uUsed <= 0) + break; + src += uUsed; + uWritten += uUsed; + uLeft -= uUsed; + if (bUsed) { + write_sq.rear = (write_sq.rear+1) % write_sq.max_count; + write_sq.rear_size = bUsed; + write_sq.count++; + } + } while (bUsed); /* uUsed may have been 0 */ + + sq_play(); + + return uUsed < 0? uUsed: uWritten; +} + +#ifdef HAS_RECORD + /* + * Here is how the values are used for reading. + * The value 'active' simply indicates the DMA is running. This is done + * so the driver semantics are DMA starts when the first read is posted. + * The value 'front' indicates the buffer we should next send to the user. + * The value 'rear' indicates the buffer the DMA is currently filling. + * When 'front' == 'rear' the buffer "ring" is empty (we always have an + * empty available). The 'rear_size' is used to track partial offsets + * into the current buffer. Right now, I just keep the DMA running. If + * the reader can't keep up, the interrupt tosses the oldest buffer. We + * could also shut down the DMA in this case. + */ + +static ssize_t sq_read(struct file *file, char *dst, size_t uLeft, + loff_t *ppos) +{ + + ssize_t uRead, bLeft, bUsed, uUsed; + + if (uLeft == 0) + return 0; + + if (!read_sq.active && dmasound.mach.record) + dmasound.mach.record(); /* Kick off the record process. */ + + uRead = 0; + + /* Move what the user requests, depending upon other options. + */ + while (uLeft > 0) { + + /* When front == rear, the DMA is not done yet. + */ + while (read_sq.front == read_sq.rear) { + if (read_sq.open_mode & O_NONBLOCK) { + return uRead > 0 ? uRead : -EAGAIN; + } + SLEEP(read_sq.action_queue); + if (signal_pending(current)) + return uRead > 0 ? uRead : -EINTR; + } + + /* The amount we move is either what is left in the + * current buffer or what the user wants. + */ + bLeft = read_sq.block_size - read_sq.rear_size; + bUsed = read_sq.rear_size; + uUsed = sound_copy_translate(dmasound.trans_read, dst, uLeft, + read_sq.buffers[read_sq.front], + &bUsed, bLeft); + if (uUsed <= 0) + return uUsed; + dst += uUsed; + uRead += uUsed; + uLeft -= uUsed; + read_sq.rear_size += bUsed; + if (read_sq.rear_size >= read_sq.block_size) { + read_sq.rear_size = 0; + read_sq.front++; + if (read_sq.front >= read_sq.max_active) + read_sq.front = 0; + } + } + return uRead; +} +#endif /* HAS_RECORD */ + +static inline void sq_init_waitqueue(struct sound_queue *sq) +{ + init_waitqueue_head(&sq->action_queue); + init_waitqueue_head(&sq->open_queue); + init_waitqueue_head(&sq->sync_queue); + sq->busy = 0; +} + +static inline void sq_wake_up(struct sound_queue *sq, struct file *file, + mode_t mode) +{ + if (file->f_mode & mode) { + sq->busy = 0; + WAKE_UP(sq->open_queue); + } +} + +static int sq_open2(struct sound_queue *sq, struct file *file, mode_t mode, + int numbufs, int bufsize) +{ + int rc = 0; + + if (file->f_mode & mode) { + if (sq->busy) { + rc = -EBUSY; + if (file->f_flags & O_NONBLOCK) + return rc; + rc = -EINTR; + while (sq->busy) { + SLEEP(sq->open_queue); + if (signal_pending(current)) + return rc; + } + rc = 0; + } + sq->busy = 1; /* Let's play spot-the-race-condition */ + + if (sq_allocate_buffers(sq, numbufs, bufsize)) { + sq_wake_up(sq, file, mode); + return rc; + } + + sq_setup(sq, numbufs, numbufs, bufsize); + sq->open_mode = file->f_mode; + } + return rc; +} + +#define write_sq_init_waitqueue() sq_init_waitqueue(&write_sq) +#define write_sq_wake_up(file) sq_wake_up(&write_sq, file, FMODE_WRITE) +#define write_sq_release_buffers() sq_release_buffers(&write_sq) +#define write_sq_open(file) \ + sq_open2(&write_sq, file, FMODE_WRITE, numWriteBufs, writeBufSize << 10) + +#ifdef HAS_RECORD +#define read_sq_init_waitqueue() sq_init_waitqueue(&read_sq) +#define read_sq_wake_up(file) sq_wake_up(&read_sq, file, FMODE_READ) +#define read_sq_release_buffers() sq_release_buffers(&read_sq) +#define read_sq_open(file) \ + sq_open2(&read_sq, file, FMODE_READ, numReadBufs, readBufSize << 10) +#else /* !HAS_RECORD */ +#define read_sq_init_waitqueue() do {} while (0) +#define read_sq_wake_up(file) do {} while (0) +#define read_sq_release_buffers() do {} while (0) +#define read_sq_open(file) (0) +#endif /* !HAS_RECORD */ + +static int sq_open(struct inode *inode, struct file *file) +{ + int rc; + + MOD_INC_USE_COUNT; + dmasound.mach.open(); + if ((rc = write_sq_open(file)) || (rc = read_sq_open(file))) { + dmasound.mach.release(); + MOD_DEC_USE_COUNT; + return rc; + } + + if (dmasound.mach.sq_open) + dmasound.mach.sq_open(); + dmasound.minDev = MINOR(inode->i_rdev) & 0x0f; + dmasound.soft = dmasound.dsp; + dmasound.hard = dmasound.dsp; + sound_init(); + if ((MINOR(inode->i_rdev) & 0x0f) == SND_DEV_AUDIO) { + sound_set_speed(8000); + sound_set_stereo(0); + sound_set_format(AFMT_MU_LAW); + } + +#if 0 + if (file->f_mode == FMODE_READ && dmasound.mach.record) { + /* Start dma'ing straight away */ + dmasound.mach.record(); + } +#endif + + return 0; +} + +static void sq_reset(void) +{ + sound_silence(); + write_sq.active = 0; + write_sq.count = 0; + write_sq.front = (write_sq.rear+1) % write_sq.max_count; +} + +static int sq_fsync(struct file *filp, struct dentry *dentry) +{ + int rc = 0; + + write_sq.syncing = 1; + sq_play(); /* there may be an incomplete frame waiting */ + + while (write_sq.active) { + SLEEP(write_sq.sync_queue); + if (signal_pending(current)) { + /* While waiting for audio output to drain, an + * interrupt occurred. Stop audio output immediately + * and clear the queue. */ + sq_reset(); + rc = -EINTR; + break; + } + } + + write_sq.syncing = 0; + return rc; +} + +static int sq_release(struct inode *inode, struct file *file) +{ + int rc = 0; + + if (write_sq.busy) + rc = sq_fsync(file, file->f_dentry); + dmasound.soft = dmasound.dsp; + dmasound.hard = dmasound.dsp; + sound_silence(); + + write_sq_release_buffers(); + read_sq_release_buffers(); + dmasound.mach.release(); + MOD_DEC_USE_COUNT; + + /* There is probably a DOS atack here. They change the mode flag. */ + /* XXX add check here */ + read_sq_wake_up(file); + write_sq_wake_up(file); + + /* Wake up a process waiting for the queue being released. + * Note: There may be several processes waiting for a call + * to open() returning. */ + + return rc; +} + +static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg) +{ + u_long fmt; + int data; + int size, nbufs; + audio_buf_info info; + + switch (cmd) { + case SNDCTL_DSP_RESET: + sq_reset(); + return 0; + case SNDCTL_DSP_POST: + case SNDCTL_DSP_SYNC: + return sq_fsync(file, file->f_dentry); + + /* ++TeSche: before changing any of these it's + * probably wise to wait until sound playing has + * settled down. */ + case SNDCTL_DSP_SPEED: + sq_fsync(file, file->f_dentry); + IOCTL_IN(arg, data); + return IOCTL_OUT(arg, sound_set_speed(data)); + case SNDCTL_DSP_STEREO: + sq_fsync(file, file->f_dentry); + IOCTL_IN(arg, data); + return IOCTL_OUT(arg, sound_set_stereo(data)); + case SOUND_PCM_WRITE_CHANNELS: + sq_fsync(file, file->f_dentry); + IOCTL_IN(arg, data); + return IOCTL_OUT(arg, sound_set_stereo(data-1)+1); + case SNDCTL_DSP_SETFMT: + sq_fsync(file, file->f_dentry); + IOCTL_IN(arg, data); + return IOCTL_OUT(arg, sound_set_format(data)); + case SNDCTL_DSP_GETFMTS: + fmt = 0; + if (dmasound.trans_write) { + if (dmasound.trans_write->ct_ulaw) + fmt |= AFMT_MU_LAW; + if (dmasound.trans_write->ct_alaw) + fmt |= AFMT_A_LAW; + if (dmasound.trans_write->ct_s8) + fmt |= AFMT_S8; + if (dmasound.trans_write->ct_u8) + fmt |= AFMT_U8; + if (dmasound.trans_write->ct_s16be) + fmt |= AFMT_S16_BE; + if (dmasound.trans_write->ct_u16be) + fmt |= AFMT_U16_BE; + if (dmasound.trans_write->ct_s16le) + fmt |= AFMT_S16_LE; + if (dmasound.trans_write->ct_u16le) + fmt |= AFMT_U16_LE; + } + return IOCTL_OUT(arg, fmt); + case SNDCTL_DSP_GETBLKSIZE: + size = write_sq.block_size + * dmasound.soft.size * (dmasound.soft.stereo + 1) + / (dmasound.hard.size * (dmasound.hard.stereo + 1)); + return IOCTL_OUT(arg, size); + case SNDCTL_DSP_SUBDIVIDE: + break; + case SNDCTL_DSP_SETFRAGMENT: + if (write_sq.count || write_sq.active || write_sq.syncing) + return -EINVAL; + IOCTL_IN(arg, size); + nbufs = size >> 16; + if (nbufs < 2 || nbufs > write_sq.numBufs) + nbufs = write_sq.numBufs; + size &= 0xffff; + if (size >= 8 && size <= 29) { + size = 1 << size; + size *= dmasound.hard.size * (dmasound.hard.stereo + 1); + size /= dmasound.soft.size * (dmasound.soft.stereo + 1); + if (size > write_sq.bufSize) + size = write_sq.bufSize; + } else + size = write_sq.bufSize; + sq_setup(&write_sq, write_sq.numBufs, nbufs, size); + return 0; + case SNDCTL_DSP_GETOSPACE: + info.fragments = write_sq.max_active - write_sq.count; + info.fragstotal = write_sq.max_active; + info.fragsize = write_sq.block_size; + info.bytes = info.fragments * info.fragsize; + if (copy_to_user((void *)arg, &info, sizeof(info))) + return -EFAULT; + return 0; + + default: + return mixer_ioctl(inode, file, cmd, arg); + } + return -EINVAL; +} + +static struct file_operations sq_fops = +{ + llseek: sound_lseek, + write: sq_write, + ioctl: sq_ioctl, + open: sq_open, + release: sq_release, +#ifdef HAS_RECORD + read: sq_read, +#endif +}; + +static void __init sq_init(void) +{ +#ifndef MODULE + int sq_unit; +#endif + sq_unit = register_sound_dsp(&sq_fops, -1); + if (sq_unit < 0) + return; + + write_sq_init_waitqueue(); + read_sq_init_waitqueue(); + + /* whatever you like as startup mode for /dev/dsp, + * (/dev/audio hasn't got a startup mode). note that + * once changed a new open() will *not* restore these! + */ + dmasound.dsp.format = AFMT_U8; + dmasound.dsp.stereo = 0; + dmasound.dsp.size = 8; + + /* set minimum rate possible without expanding */ + dmasound.dsp.speed = dmasound.mach.min_dsp_speed; + + /* before the first open to /dev/dsp this wouldn't be set */ + dmasound.soft = dmasound.dsp; + dmasound.hard = dmasound.dsp; + + sound_silence(); +} + + + /* + * /dev/sndstat + */ + +static struct { + int busy; + char buf[512]; /* state.buf should not overflow! */ + int len, ptr; +} state; + +static int state_open(struct inode *inode, struct file *file) +{ + char *buffer = state.buf; + int len = 0; + + if (state.busy) + return -EBUSY; + + MOD_INC_USE_COUNT; + dmasound.mach.open(); + state.ptr = 0; + state.busy = 1; + + len += sprintf(buffer+len, "%sDMA sound driver:\n", dmasound.mach.name); + + len += sprintf(buffer+len, "\tsound.format = 0x%x", + dmasound.soft.format); + switch (dmasound.soft.format) { + case AFMT_MU_LAW: + len += sprintf(buffer+len, " (mu-law)"); + break; + case AFMT_A_LAW: + len += sprintf(buffer+len, " (A-law)"); + break; + case AFMT_U8: + len += sprintf(buffer+len, " (unsigned 8 bit)"); + break; + case AFMT_S8: + len += sprintf(buffer+len, " (signed 8 bit)"); + break; + case AFMT_S16_BE: + len += sprintf(buffer+len, " (signed 16 bit big)"); + break; + case AFMT_U16_BE: + len += sprintf(buffer+len, " (unsigned 16 bit big)"); + break; + case AFMT_S16_LE: + len += sprintf(buffer+len, " (signed 16 bit little)"); + break; + case AFMT_U16_LE: + len += sprintf(buffer+len, " (unsigned 16 bit little)"); + break; + } + len += sprintf(buffer+len, "\n"); + len += sprintf(buffer+len, "\tsound.speed = %dHz (phys. %dHz)\n", + dmasound.soft.speed, dmasound.hard.speed); + len += sprintf(buffer+len, "\tsound.stereo = 0x%x (%s)\n", + dmasound.soft.stereo, + dmasound.soft.stereo ? "stereo" : "mono"); + if (dmasound.mach.state_info) + len += dmasound.mach.state_info(buffer); + len += sprintf(buffer+len, "\tsq.block_size = %d sq.max_count = %d" + " sq.max_active = %d\n", + write_sq.block_size, write_sq.max_count, + write_sq.max_active); + len += sprintf(buffer+len, "\tsq.count = %d sq.rear_size = %d\n", + write_sq.count, write_sq.rear_size); + len += sprintf(buffer+len, "\tsq.active = %d sq.syncing = %d\n", + write_sq.active, write_sq.syncing); + state.len = len; + return 0; +} + +static int state_release(struct inode *inode, struct file *file) +{ + state.busy = 0; + dmasound.mach.release(); + MOD_DEC_USE_COUNT; + return 0; +} + +static ssize_t state_read(struct file *file, char *buf, size_t count, + loff_t *ppos) +{ + int n = state.len - state.ptr; + if (n > count) + n = count; + if (n <= 0) + return 0; + if (copy_to_user(buf, &state.buf[state.ptr], n)) + return -EFAULT; + state.ptr += n; + return n; +} + +static struct file_operations state_fops = +{ + llseek: sound_lseek, + read: state_read, + open: state_open, + release: state_release, +}; + +static void __init state_init(void) +{ +#ifndef MODULE + int state_unit; +#endif + state_unit = register_sound_special(&state_fops, SND_DEV_STATUS); + if (state_unit < 0) + return; + state.busy = 0; +} + + + /* + * Config & Setup + * + * This function is called by _one_ chipset-specific driver + */ + +int __init dmasound_init(void) +{ + if (irq_installed) + return -EBUSY; + + /* Set up sound queue, /dev/audio and /dev/dsp. */ + + /* Set default settings. */ + sq_init(); + + /* Set up /dev/sndstat. */ + state_init(); + + /* Set up /dev/mixer. */ + mixer_init(); + + if (!dmasound.mach.irqinit()) { + printk(KERN_ERR "DMA sound driver: Interrupt initialization failed\n"); + return -ENODEV; + } +#ifdef MODULE + irq_installed = 1; +#endif + + printk(KERN_INFO "DMA sound driver installed, using %d buffers of %dk.\n", + numWriteBufs, writeBufSize); + + return 0; +} + +#ifdef MODULE + +void dmasound_deinit(void) +{ + if (irq_installed) { + sound_silence(); + dmasound.mach.irqcleanup(); + } + + write_sq_release_buffers(); + read_sq_release_buffers(); + + if (mixer_unit >= 0) + unregister_sound_mixer(mixer_unit); + if (state_unit >= 0) + unregister_sound_special(state_unit); + if (sq_unit >= 0) + unregister_sound_dsp(sq_unit); +} + +#else /* !MODULE */ + +static int __init dmasound_setup(char *str) +{ + int ints[6]; + + str = get_options(str, ARRAY_SIZE(ints), ints); + + /* check the bootstrap parameter for "dmasound=" */ + + switch (ints[0]) { + case 3: + if ((ints[3] < 0) || (ints[3] > MAX_CATCH_RADIUS)) + printk("dmasound_setup: illegal catch radius, using default = %d\n", catchRadius); + else + catchRadius = ints[3]; + /* fall through */ + case 2: + if (ints[1] < MIN_BUFFERS) + printk("dmasound_setup: illegal number of buffers, using default = %d\n", numWriteBufs); + else + numWriteBufs = ints[1]; + if (ints[2] < MIN_BUFSIZE || ints[2] > MAX_BUFSIZE) + printk("dmasound_setup: illegal buffer size, using default = %dK\n", writeBufSize); + else + writeBufSize = ints[2]; + break; + case 0: + break; + default: + printk("dmasound_setup: illegal number of arguments\n"); + return 0; + } + return 1; +} + +__setup("dmasound=", dmasound_setup); + +#endif /* !MODULE */ + + + /* + * Visible symbols for modules + */ + +EXPORT_SYMBOL(dmasound); +EXPORT_SYMBOL(dmasound_init); +#ifdef MODULE +EXPORT_SYMBOL(dmasound_deinit); +#endif +EXPORT_SYMBOL(dmasound_write_sq); +#ifdef HAS_RECORD +EXPORT_SYMBOL(dmasound_read_sq); +#endif +EXPORT_SYMBOL(dmasound_catchRadius); +#ifdef HAS_8BIT_TABLES +EXPORT_SYMBOL(dmasound_ulaw2dma8); +EXPORT_SYMBOL(dmasound_alaw2dma8); +#endif +#ifdef HAS_16BIT_TABLES +EXPORT_SYMBOL(dmasound_ulaw2dma16); +EXPORT_SYMBOL(dmasound_alaw2dma16); +#endif +#ifdef HAS_14BIT_TABLES +EXPORT_SYMBOL(dmasound_ulaw2dma14l); +EXPORT_SYMBOL(dmasound_ulaw2dma14h); +EXPORT_SYMBOL(dmasound_alaw2dma14l); +EXPORT_SYMBOL(dmasound_alaw2dma14h); +#endif + diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/sound/dmasound/dmasound_paula.c linux/drivers/sound/dmasound/dmasound_paula.c --- v2.3.99-pre3/linux/drivers/sound/dmasound/dmasound_paula.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/sound/dmasound/dmasound_paula.c Mon Apr 10 22:58:59 2000 @@ -0,0 +1,690 @@ + +/* + * linux/drivers/sound/dmasound_paula.c + * + * Amiga DMA Sound Driver + * + * See linux/drivers/sound/dmasound_core.c for copyright and credits + */ + + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "dmasound.h" + + + /* + * The minimum period for audio depends on htotal (for OCS/ECS/AGA) + * (Imported from arch/m68k/amiga/amisound.c) + * + * FIXME: if amifb is not used, there should be a method to change htotal + */ + +extern volatile u_short amiga_audio_min_period; + + + /* + * amiga_mksound() should be able to restore the period after beeping + * (Imported from arch/m68k/amiga/amisound.c) + */ + +extern u_short amiga_audio_period; + + + /* + * Audio DMA masks + */ + +#define AMI_AUDIO_OFF (DMAF_AUD0 | DMAF_AUD1 | DMAF_AUD2 | DMAF_AUD3) +#define AMI_AUDIO_8 (DMAF_SETCLR | DMAF_MASTER | DMAF_AUD0 | DMAF_AUD1) +#define AMI_AUDIO_14 (AMI_AUDIO_8 | DMAF_AUD2 | DMAF_AUD3) + + + /* + * Helper pointers for 16(14)-bit sound + */ + +static int write_sq_block_size_half, write_sq_block_size_quarter; + + +/*** Low level stuff *********************************************************/ + + +static void AmiOpen(void); +static void AmiRelease(void); +static void *AmiAlloc(unsigned int size, int flags); +static void AmiFree(void *obj, unsigned int size); +static int AmiIrqInit(void); +#ifdef MODULE +static void AmiIrqCleanUp(void); +#endif +static void AmiSilence(void); +static void AmiInit(void); +static int AmiSetFormat(int format); +static int AmiSetVolume(int volume); +static int AmiSetTreble(int treble); +static void AmiPlayNextFrame(int index); +static void AmiPlay(void); +static void AmiInterrupt(int irq, void *dummy, struct pt_regs *fp); + + +/*** Mid level stuff *********************************************************/ + +static void AmiMixerInit(void); +static int AmiMixerIoctl(u_int cmd, u_long arg); +static void AmiWriteSqSetup(void); +static int AmiStateInfo(char *buffer); + + +/*** Translations ************************************************************/ + +/* ++TeSche: radically changed for new expanding purposes... + * + * These two routines now deal with copying/expanding/translating the samples + * from user space into our buffer at the right frequency. They take care about + * how much data there's actually to read, how much buffer space there is and + * to convert samples into the right frequency/encoding. They will only work on + * complete samples so it may happen they leave some bytes in the input stream + * if the user didn't write a multiple of the current sample size. They both + * return the number of bytes they've used from both streams so you may detect + * such a situation. Luckily all programs should be able to cope with that. + * + * I think I've optimized anything as far as one can do in plain C, all + * variables should fit in registers and the loops are really short. There's + * one loop for every possible situation. Writing a more generalized and thus + * parameterized loop would only produce slower code. Feel free to optimize + * this in assembler if you like. :) + * + * I think these routines belong here because they're not yet really hardware + * independent, especially the fact that the Falcon can play 16bit samples + * only in stereo is hardcoded in both of them! + * + * ++geert: split in even more functions (one per format) + */ + + + /* + * Native format + */ + +static ssize_t ami_ct_s8(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, ssize_t frameLeft) +{ + ssize_t count, used; + + if (!dmasound.soft.stereo) { + void *p = &frame[*frameUsed]; + count = min(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(userCount, frameLeft)>>1 & ~1; + used = count*2; + while (count > 0) { + if (get_user(*left++, userPtr++) + || get_user(*right++, userPtr++)) + return -EFAULT; + count--; + } + } + *frameUsed += used; + return used; +} + + + /* + * Copy and convert 8 bit data + */ + +#define GENERATE_AMI_CT8(funcname, convsample) \ +static ssize_t funcname(const u_char *userPtr, size_t userCount, \ + u_char frame[], ssize_t *frameUsed, \ + ssize_t frameLeft) \ +{ \ + ssize_t count, used; \ + \ + if (!dmasound.soft.stereo) { \ + u_char *p = &frame[*frameUsed]; \ + count = min(userCount, frameLeft) & ~1; \ + used = count; \ + while (count > 0) { \ + u_char data; \ + if (get_user(data, userPtr++)) \ + return -EFAULT; \ + *p++ = convsample(data); \ + count--; \ + } \ + } else { \ + u_char *left = &frame[*frameUsed>>1]; \ + u_char *right = left+write_sq_block_size_half; \ + count = min(userCount, frameLeft)>>1 & ~1; \ + used = count*2; \ + while (count > 0) { \ + u_char data; \ + if (get_user(data, userPtr++)) \ + return -EFAULT; \ + *left++ = convsample(data); \ + if (get_user(data, userPtr++)) \ + return -EFAULT; \ + *right++ = convsample(data); \ + count--; \ + } \ + } \ + *frameUsed += used; \ + return used; \ +} + +#define AMI_CT_ULAW(x) (dmasound_ulaw2dma8[(x)]) +#define AMI_CT_ALAW(x) (dmasound_alaw2dma8[(x)]) +#define AMI_CT_U8(x) ((x) ^ 0x80) + +GENERATE_AMI_CT8(ami_ct_ulaw, AMI_CT_ULAW) +GENERATE_AMI_CT8(ami_ct_alaw, AMI_CT_ALAW) +GENERATE_AMI_CT8(ami_ct_u8, AMI_CT_U8) + + + /* + * Copy and convert 16 bit data + */ + +#define GENERATE_AMI_CT_16(funcname, convsample) \ +static ssize_t funcname(const u_char *userPtr, size_t userCount, \ + u_char frame[], ssize_t *frameUsed, \ + ssize_t frameLeft) \ +{ \ + ssize_t count, used; \ + u_short data; \ + \ + if (!dmasound.soft.stereo) { \ + u_char *high = &frame[*frameUsed>>1]; \ + u_char *low = high+write_sq_block_size_half; \ + count = min(userCount, frameLeft)>>1 & ~1; \ + used = count*2; \ + while (count > 0) { \ + if (get_user(data, ((u_short *)userPtr)++)) \ + return -EFAULT; \ + data = convsample(data); \ + *high++ = data>>8; \ + *low++ = (data>>2) & 0x3f; \ + count--; \ + } \ + } else { \ + u_char *lefth = &frame[*frameUsed>>2]; \ + 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(userCount, frameLeft)>>2 & ~1; \ + used = count*4; \ + while (count > 0) { \ + if (get_user(data, ((u_short *)userPtr)++)) \ + return -EFAULT; \ + data = convsample(data); \ + *lefth++ = data>>8; \ + *leftl++ = (data>>2) & 0x3f; \ + if (get_user(data, ((u_short *)userPtr)++)) \ + return -EFAULT; \ + data = convsample(data); \ + *righth++ = data>>8; \ + *rightl++ = (data>>2) & 0x3f; \ + count--; \ + } \ + } \ + *frameUsed += used; \ + return used; \ +} + +#define AMI_CT_S16BE(x) (x) +#define AMI_CT_U16BE(x) ((x) ^ 0x8000) +#define AMI_CT_S16LE(x) (le2be16((x))) +#define AMI_CT_U16LE(x) (le2be16((x)) ^ 0x8000) + +GENERATE_AMI_CT_16(ami_ct_s16be, AMI_CT_S16BE) +GENERATE_AMI_CT_16(ami_ct_u16be, AMI_CT_U16BE) +GENERATE_AMI_CT_16(ami_ct_s16le, AMI_CT_S16LE) +GENERATE_AMI_CT_16(ami_ct_u16le, AMI_CT_U16LE) + + +static TRANS transAmiga = { + ct_ulaw: ami_ct_ulaw, + ct_alaw: ami_ct_alaw, + ct_s8: ami_ct_s8, + ct_u8: ami_ct_u8, + ct_s16be: ami_ct_s16be, + ct_u16be: ami_ct_u16be, + ct_s16le: ami_ct_s16le, + ct_u16le: ami_ct_u16le, +}; + +/*** Low level stuff *********************************************************/ + + +static void AmiOpen(void) +{ + MOD_INC_USE_COUNT; +} + +static void AmiRelease(void) +{ + MOD_DEC_USE_COUNT; +} + +static inline void StopDMA(void) +{ + custom.aud[0].audvol = custom.aud[1].audvol = 0; + custom.aud[2].audvol = custom.aud[3].audvol = 0; + custom.dmacon = AMI_AUDIO_OFF; +} + +static void *AmiAlloc(unsigned int size, int flags) +{ + return amiga_chip_alloc((long)size, "dmasound [Paula]"); +} + +static void AmiFree(void *obj, unsigned int size) +{ + amiga_chip_free (obj); +} + +static int __init AmiIrqInit(void) +{ + /* turn off DMA for audio channels */ + StopDMA(); + + /* Register interrupt handler. */ + if (request_irq(IRQ_AMIGA_AUD0, AmiInterrupt, 0, "DMA sound", + AmiInterrupt)) + return 0; + return 1; +} + +#ifdef MODULE +static void AmiIrqCleanUp(void) +{ + /* turn off DMA for audio channels */ + StopDMA(); + /* release the interrupt */ + free_irq(IRQ_AMIGA_AUD0, AmiInterrupt); +} +#endif /* MODULE */ + +static void AmiSilence(void) +{ + /* turn off DMA for audio channels */ + StopDMA(); +} + + +static void AmiInit(void) +{ + int period, i; + + AmiSilence(); + + if (dmasound.soft.speed) + period = amiga_colorclock/dmasound.soft.speed-1; + else + period = amiga_audio_min_period; + dmasound.hard = dmasound.soft; + dmasound.trans_write = &transAmiga; + + if (period < amiga_audio_min_period) { + /* we would need to squeeze the sound, but we won't do that */ + period = amiga_audio_min_period; + } else if (period > 65535) { + period = 65535; + } + dmasound.hard.speed = amiga_colorclock/(period+1); + + for (i = 0; i < 4; i++) + custom.aud[i].audper = period; + amiga_audio_period = period; + + AmiSetTreble(50); /* recommended for newer amiga models */ +} + + +static int AmiSetFormat(int format) +{ + int size; + + /* Amiga sound DMA supports 8bit and 16bit (pseudo 14 bit) modes */ + + switch (format) { + case AFMT_QUERY: + return dmasound.soft.format; + case AFMT_MU_LAW: + case AFMT_A_LAW: + case AFMT_U8: + case AFMT_S8: + size = 8; + break; + case AFMT_S16_BE: + case AFMT_U16_BE: + case AFMT_S16_LE: + case AFMT_U16_LE: + size = 16; + break; + default: /* :-) */ + size = 8; + format = AFMT_S8; + } + + dmasound.soft.format = format; + dmasound.soft.size = size; + if (dmasound.minDev == SND_DEV_DSP) { + dmasound.dsp.format = format; + dmasound.dsp.size = dmasound.soft.size; + } + AmiInit(); + + return format; +} + + +#define VOLUME_VOXWARE_TO_AMI(v) \ + (((v) < 0) ? 0 : ((v) > 100) ? 64 : ((v) * 64)/100) +#define VOLUME_AMI_TO_VOXWARE(v) ((v)*100/64) + +static int AmiSetVolume(int volume) +{ + dmasound.volume_left = VOLUME_VOXWARE_TO_AMI(volume & 0xff); + custom.aud[0].audvol = dmasound.volume_left; + dmasound.volume_right = VOLUME_VOXWARE_TO_AMI((volume & 0xff00) >> 8); + custom.aud[1].audvol = dmasound.volume_right; + if (dmasound.hard.size == 16) { + if (dmasound.volume_left == 64 && dmasound.volume_right == 64) { + custom.aud[2].audvol = 1; + custom.aud[3].audvol = 1; + } else { + custom.aud[2].audvol = 0; + custom.aud[3].audvol = 0; + } + } + return VOLUME_AMI_TO_VOXWARE(dmasound.volume_left) | + (VOLUME_AMI_TO_VOXWARE(dmasound.volume_right) << 8); +} + +static int AmiSetTreble(int treble) +{ + dmasound.treble = treble; + if (treble < 50) + ciaa.pra &= ~0x02; + else + ciaa.pra |= 0x02; + return treble; +} + + +#define AMI_PLAY_LOADED 1 +#define AMI_PLAY_PLAYING 2 +#define AMI_PLAY_MASK 3 + + +static void AmiPlayNextFrame(int index) +{ + u_char *start, *ch0, *ch1, *ch2, *ch3; + u_long size; + + /* used by AmiPlay() if all doubts whether there really is something + * to be played are already wiped out. + */ + start = write_sq.buffers[write_sq.front]; + size = (write_sq.count == index ? write_sq.rear_size + : write_sq.block_size)>>1; + + if (dmasound.hard.stereo) { + ch0 = start; + ch1 = start+write_sq_block_size_half; + size >>= 1; + } else { + ch0 = start; + ch1 = start; + } + + custom.aud[0].audvol = dmasound.volume_left; + custom.aud[1].audvol = dmasound.volume_right; + if (dmasound.hard.size == 8) { + custom.aud[0].audlc = (u_short *)ZTWO_PADDR(ch0); + custom.aud[0].audlen = size; + custom.aud[1].audlc = (u_short *)ZTWO_PADDR(ch1); + custom.aud[1].audlen = size; + custom.dmacon = AMI_AUDIO_8; + } else { + size >>= 1; + custom.aud[0].audlc = (u_short *)ZTWO_PADDR(ch0); + custom.aud[0].audlen = size; + custom.aud[1].audlc = (u_short *)ZTWO_PADDR(ch1); + custom.aud[1].audlen = size; + if (dmasound.volume_left == 64 && dmasound.volume_right == 64) { + /* We can play pseudo 14-bit only with the maximum volume */ + ch3 = ch0+write_sq_block_size_quarter; + ch2 = ch1+write_sq_block_size_quarter; + custom.aud[2].audvol = 1; /* we are being affected by the beeps */ + custom.aud[3].audvol = 1; /* restoring volume here helps a bit */ + custom.aud[2].audlc = (u_short *)ZTWO_PADDR(ch2); + custom.aud[2].audlen = size; + custom.aud[3].audlc = (u_short *)ZTWO_PADDR(ch3); + custom.aud[3].audlen = size; + custom.dmacon = AMI_AUDIO_14; + } else { + custom.aud[2].audvol = 0; + custom.aud[3].audvol = 0; + custom.dmacon = AMI_AUDIO_8; + } + } + write_sq.front = (write_sq.front+1) % write_sq.max_count; + write_sq.active |= AMI_PLAY_LOADED; +} + + +static void AmiPlay(void) +{ + int minframes = 1; + + custom.intena = IF_AUD0; + + if (write_sq.active & AMI_PLAY_LOADED) { + /* There's already a frame loaded */ + custom.intena = IF_SETCLR | IF_AUD0; + return; + } + + if (write_sq.active & AMI_PLAY_PLAYING) + /* Increase threshold: frame 1 is already being played */ + minframes = 2; + + if (write_sq.count < minframes) { + /* Nothing to do */ + custom.intena = IF_SETCLR | IF_AUD0; + return; + } + + if (write_sq.count <= minframes && + write_sq.rear_size < write_sq.block_size && !write_sq.syncing) { + /* hmmm, the only existing frame is not + * yet filled and we're not syncing? + */ + custom.intena = IF_SETCLR | IF_AUD0; + return; + } + + AmiPlayNextFrame(minframes); + + custom.intena = IF_SETCLR | IF_AUD0; +} + + +static void AmiInterrupt(int irq, void *dummy, struct pt_regs *fp) +{ + int minframes = 1; + + custom.intena = IF_AUD0; + + if (!write_sq.active) { + /* Playing was interrupted and sq_reset() has already cleared + * the sq variables, so better don't do anything here. + */ + WAKE_UP(write_sq.sync_queue); + return; + } + + if (write_sq.active & AMI_PLAY_PLAYING) { + /* We've just finished a frame */ + write_sq.count--; + WAKE_UP(write_sq.action_queue); + } + + if (write_sq.active & AMI_PLAY_LOADED) + /* Increase threshold: frame 1 is already being played */ + minframes = 2; + + /* Shift the flags */ + write_sq.active = (write_sq.active<<1) & AMI_PLAY_MASK; + + if (!write_sq.active) + /* No frame is playing, disable audio DMA */ + StopDMA(); + + custom.intena = IF_SETCLR | IF_AUD0; + + if (write_sq.count >= minframes) + /* Try to play the next frame */ + AmiPlay(); + + if (!write_sq.active) + /* Nothing to play anymore. + Wake up a process waiting for audio output to drain. */ + WAKE_UP(write_sq.sync_queue); +} + +/*** Mid level stuff *********************************************************/ + + +/* + * /dev/mixer abstraction + */ + +static void __init AmiMixerInit(void) +{ + dmasound.volume_left = 64; + dmasound.volume_right = 64; + custom.aud[0].audvol = dmasound.volume_left; + custom.aud[3].audvol = 1; /* For pseudo 14bit */ + custom.aud[1].audvol = dmasound.volume_right; + custom.aud[2].audvol = 1; /* For pseudo 14bit */ + dmasound.treble = 50; +} + +static int AmiMixerIoctl(u_int cmd, u_long arg) +{ + int data; + switch (cmd) { + case SOUND_MIXER_READ_DEVMASK: + return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_TREBLE); + case SOUND_MIXER_READ_RECMASK: + return IOCTL_OUT(arg, 0); + case SOUND_MIXER_READ_STEREODEVS: + return IOCTL_OUT(arg, SOUND_MASK_VOLUME); + case SOUND_MIXER_READ_VOLUME: + return IOCTL_OUT(arg, + VOLUME_AMI_TO_VOXWARE(dmasound.volume_left) | + VOLUME_AMI_TO_VOXWARE(dmasound.volume_right) << 8); + case SOUND_MIXER_WRITE_VOLUME: + IOCTL_IN(arg, data); + return IOCTL_OUT(arg, dmasound_set_volume(data)); + case SOUND_MIXER_READ_TREBLE: + return IOCTL_OUT(arg, dmasound.treble); + case SOUND_MIXER_WRITE_TREBLE: + IOCTL_IN(arg, data); + return IOCTL_OUT(arg, dmasound_set_treble(data)); + } + return -EINVAL; +} + + +static void AmiWriteSqSetup(void) +{ + write_sq_block_size_half = write_sq.block_size>>1; + write_sq_block_size_quarter = write_sq_block_size_half>>1; +} + + +static int AmiStateInfo(char *buffer) +{ + int len = 0; + len += sprintf(buffer+len, "\tsound.volume_left = %d [0...64]\n", + dmasound.volume_left); + len += sprintf(buffer+len, "\tsound.volume_right = %d [0...64]\n", + dmasound.volume_right); + return len; +} + + +/*** Machine definitions *****************************************************/ + + +static MACHINE machAmiga = { + name: "Amiga", + name2: "AMIGA", + open: AmiOpen, + release: AmiRelease, + dma_alloc: AmiAlloc, + dma_free: AmiFree, + irqinit: AmiIrqInit, +#ifdef MODULE + irqcleanup: AmiIrqCleanUp, +#endif /* MODULE */ + init: AmiInit, + silence: AmiSilence, + setFormat: AmiSetFormat, + setVolume: AmiSetVolume, + setTreble: AmiSetTreble, + play: AmiPlay, + mixer_init: AmiMixerInit, + mixer_ioctl: AmiMixerIoctl, + write_sq_setup: AmiWriteSqSetup, + state_info: AmiStateInfo, + min_dsp_speed: 8000 +}; + + +/*** Config & Setup **********************************************************/ + + +int __init dmasound_paula_init(void) +{ + int err; + + if (MACH_IS_AMIGA && AMIGAHW_PRESENT(AMI_AUDIO)) { + if (!request_mem_region(CUSTOM_PHYSADDR+0xa0, 0x40, + "dmasound [Paula]")) + return -EBUSY; + dmasound.mach = machAmiga; + err = dmasound_init(); + if (err) + release_mem_region(CUSTOM_PHYSADDR+0xa0, 0x40); + return err; + } else + return -ENODEV; +} + +static void __exit dmasound_paula_cleanup(void) +{ + dmasound_deinit(); + release_mem_region(CUSTOM_PHYSADDR+0xa0, 0x40); +} + +module_init(dmasound_paula_init); +module_exit(dmasound_paula_cleanup); diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/sound/dmasound/dmasound_q40.c linux/drivers/sound/dmasound/dmasound_q40.c --- v2.3.99-pre3/linux/drivers/sound/dmasound/dmasound_q40.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/sound/dmasound/dmasound_q40.c Mon Apr 10 22:58:59 2000 @@ -0,0 +1,587 @@ + +/* + * linux/drivers/sound/dmasound_q40.c + * + * Q40 DMA Sound Driver + * + * See linux/drivers/sound/dmasound_core.c for copyright and credits + */ + + +#include +#include +#include +#include + +#include +#include + +#include "dmasound.h" + + +static int expand_bal; /* Balance factor for expanding (not volume!) */ +static int expand_data; /* Data for expanding */ + + +/*** Low level stuff *********************************************************/ + + +static void Q40Open(void); +static void Q40Release(void); +static void *Q40Alloc(unsigned int size, int flags); +static void Q40Free(void *, unsigned int); +static int Q40IrqInit(void); +#ifdef MODULE +static void Q40IrqCleanUp(void); +#endif +static void Q40Silence(void); +static void Q40Init(void); +static int Q40SetFormat(int format); +static int Q40SetVolume(int volume); +static void Q40PlayNextFrame(int index); +static void Q40Play(void); +static void Q40StereoInterrupt(int irq, void *dummy, struct pt_regs *fp); +static void Q40MonoInterrupt(int irq, void *dummy, struct pt_regs *fp); +static void Q40Interrupt(void); + + +/*** Mid level stuff *********************************************************/ + + +#if 1 +/* userCount, frameUsed, frameLeft == byte counts */ +static ssize_t q40_ct_law(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + char *table = dmasound.soft.format == AFMT_MU_LAW ? dmasound_ulaw2dma8: dmasound_alaw2dma8; + ssize_t count, used; + u_char *p = (u_char *) &frame[*frameUsed]; + + used = count = min(userCount, frameLeft); + if (copy_from_user(p,userPtr,count)) + return -EFAULT; + while (count > 0) { + *p = table[*p]+128; + p++; + count--; + } + *frameUsed += used ; + return used; +} +#else +static ssize_t q40_ct_law(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + char *table = dmasound.soft.format == AFMT_MU_LAW ? dmasound_ulaw2dma8: dmasound_alaw2dma8; + ssize_t count, used; + u_char *p = (u_char *) &frame[*frameUsed]; + u_char val; + int stereo = sound.soft.stereo; + + + frameLeft >>= 1; + if (stereo) + userCount >>= 1; + used = count = min(userCount, frameLeft); + while (count > 0) { + u_char data; + if (get_user(data, userPtr++)) + return -EFAULT; + val = table[data]+128; + *p++ = val; + if (stereo) { + if (get_user(data, userPtr++)) + return -EFAULT; + val = table[data]+128; + } + *p++ = val; + count--; + } + *frameUsed += used * 2; + return stereo? used * 2: used; +} +#endif + +#if 1 +static ssize_t q40_ct_s8(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + ssize_t count, used; + u_char *p = (u_char *) &frame[*frameUsed]; + + used = count = min(userCount, frameLeft); + if (copy_from_user(p,userPtr,count)) + return -EFAULT; + while (count > 0) { + *p = *p + 128; + p++; + count--; + } + *frameUsed += used; + return used; +} +#else +static ssize_t q40_ct_s8(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + ssize_t count, used; + u_char *p = (u_char *) &frame[*frameUsed]; + u_char val; + int stereo = dmasound.soft.stereo; + + frameLeft >>= 1; + if (stereo) + userCount >>= 1; + used = count = min(userCount, frameLeft); + while (count > 0) { + u_char data; + if (get_user(data, userPtr++)) + return -EFAULT; + val = data + 128; + *p++ = val; + if (stereo) { + if (get_user(data, userPtr++)) + return -EFAULT; + val = data + 128; + } + *p++ = val; + count--; + } + *frameUsed += used * 2; + return stereo? used * 2: used; +} +#endif + +#if 1 +static ssize_t q40_ct_u8(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + ssize_t count, used; + u_char *p = (u_char *) &frame[*frameUsed]; + + used = count = min(userCount, frameLeft); + if (copy_from_user(p,userPtr,count)) + return -EFAULT; + *frameUsed += used; + return used; +} +#else +static ssize_t q40_ct_u8(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + ssize_t count, used; + u_char *p = (u_char *) &frame[*frameUsed]; + u_char val; + int stereo = dmasound.soft.stereo; + + + frameLeft >>= 1; + if (stereo) + userCount >>= 1; + used = count = min(userCount, frameLeft); + while (count > 0) { + u_char data; + if (get_user(data, userPtr++)) + return -EFAULT; + val = data; + *p++ = val; + if (stereo) { + if (get_user(data, userPtr++)) + return -EFAULT; + val = data; + } + *p++ = val; + count--; + } + *frameUsed += used * 2; + return stereo? used * 2: used; +} +#endif + +/* a bit too complicated to optimise right now ..*/ +static ssize_t q40_ctx_law(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + unsigned char *table = (unsigned char *) + (dmasound.soft.format == AFMT_MU_LAW ? dmasound_ulaw2dma8: dmasound_alaw2dma8); + unsigned int data = expand_data; + u_char *p = (u_char *) &frame[*frameUsed]; + int bal = expand_bal; + int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; + int utotal, ftotal; + + ftotal = frameLeft; + utotal = userCount; + while (frameLeft) { + u_char c; + if (bal < 0) { + if (userCount == 0) + break; + if (get_user(c, userPtr++)) + return -EFAULT; + data = table[c]; + data += 0x80; + userCount--; + bal += hSpeed; + } + *p++ = data; + frameLeft--; + bal -= sSpeed; + } + expand_bal = bal; + expand_data = data; + *frameUsed += (ftotal - frameLeft); + utotal -= userCount; + return utotal; +} + + +static ssize_t q40_ctx_s8(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + u_char *p = (u_char *) &frame[*frameUsed]; + unsigned int data = expand_data; + int bal = expand_bal; + int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; + int utotal, ftotal; + + + ftotal = frameLeft; + utotal = userCount; + while (frameLeft) { + u_char c; + if (bal < 0) { + if (userCount == 0) + break; + if (get_user(c, userPtr++)) + return -EFAULT; + data = c ; + data += 0x80; + userCount--; + bal += hSpeed; + } + *p++ = data; + frameLeft--; + bal -= sSpeed; + } + expand_bal = bal; + expand_data = data; + *frameUsed += (ftotal - frameLeft); + utotal -= userCount; + return utotal; +} + + +static ssize_t q40_ctx_u8(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + u_char *p = (u_char *) &frame[*frameUsed]; + unsigned int data = expand_data; + int bal = expand_bal; + int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; + int utotal, ftotal; + + ftotal = frameLeft; + utotal = userCount; + while (frameLeft) { + u_char c; + if (bal < 0) { + if (userCount == 0) + break; + if (get_user(c, userPtr++)) + return -EFAULT; + data = c ; + userCount--; + bal += hSpeed; + } + *p++ = data; + frameLeft--; + bal -= sSpeed; + } + expand_bal = bal; + expand_data = data; + *frameUsed += (ftotal - frameLeft) ; + utotal -= userCount; + return utotal; +} + + +static TRANS transQ40Normal = { + q40_ct_law, q40_ct_law, q40_ct_s8, q40_ct_u8, NULL, NULL, NULL, NULL +}; + +static TRANS transQ40Expanding = { + q40_ctx_law, q40_ctx_law, q40_ctx_s8, q40_ctx_u8, NULL, NULL, NULL, NULL +}; + + +/*** Low level stuff *********************************************************/ + + +static void Q40Open(void) +{ + MOD_INC_USE_COUNT; +} + +static void Q40Release(void) +{ + MOD_DEC_USE_COUNT; +} + + +static void *Q40Alloc(unsigned int size, int flags) +{ + return kmalloc(size, flags); /* change to vmalloc */ +} + +static void Q40Free(void *ptr, unsigned int size) +{ + kfree(ptr); +} + +static int __init Q40IrqInit(void) +{ + /* Register interrupt handler. */ + request_irq(Q40_IRQ_SAMPLE, Q40StereoInterrupt, 0, + "DMA sound", Q40Interrupt); + + return(1); +} + + +#ifdef MODULE +static void Q40IrqCleanUp(void) +{ + master_outb(0,SAMPLE_ENABLE_REG); + free_irq(Q40_IRQ_SAMPLE, Q40Interrupt); +} +#endif /* MODULE */ + + +static void Q40Silence(void) +{ + master_outb(0,SAMPLE_ENABLE_REG); + *DAC_LEFT=*DAC_RIGHT=0; +} + +static char *q40_pp=NULL; +static unsigned int q40_sc=0; + +static void Q40PlayNextFrame(int index) +{ + u_char *start; + u_long size; + u_char speed; + + /* used by Q40Play() if all doubts whether there really is something + * to be played are already wiped out. + */ + start = write_sq.buffers[write_sq.front]; + size = (write_sq.count == index ? write_sq.rear_size : write_sq.block_size); + + q40_pp=start; + q40_sc=size; + + write_sq.front = (write_sq.front+1) % write_sq.max_count; + write_sq.active++; + + speed=(dmasound.hard.speed==10000 ? 0 : 1); + + master_outb( 0,SAMPLE_ENABLE_REG); + free_irq(Q40_IRQ_SAMPLE, Q40Interrupt); + if (dmasound.soft.stereo) + request_irq(Q40_IRQ_SAMPLE, Q40StereoInterrupt, 0, + "Q40 sound", Q40Interrupt); + else + request_irq(Q40_IRQ_SAMPLE, Q40MonoInterrupt, 0, + "Q40 sound", Q40Interrupt); + + master_outb( speed, SAMPLE_RATE_REG); + master_outb( 1,SAMPLE_CLEAR_REG); + master_outb( 1,SAMPLE_ENABLE_REG); +} + +static void Q40Play(void) +{ + unsigned long flags; + + if (write_sq.active || write_sq.count<=0 ) { + /* There's already a frame loaded */ + return; + } + + /* nothing in the queue */ + if (write_sq.count <= 1 && write_sq.rear_size < write_sq.block_size && !write_sq.syncing) { + /* hmmm, the only existing frame is not + * yet filled and we're not syncing? + */ + return; + } + save_flags(flags); cli(); + Q40PlayNextFrame(1); + restore_flags(flags); +} + +static void Q40StereoInterrupt(int irq, void *dummy, struct pt_regs *fp) +{ + if (q40_sc>1){ + *DAC_LEFT=*q40_pp++; + *DAC_RIGHT=*q40_pp++; + q40_sc -=2; + master_outb(1,SAMPLE_CLEAR_REG); + }else Q40Interrupt(); +} +static void Q40MonoInterrupt(int irq, void *dummy, struct pt_regs *fp) +{ + if (q40_sc>0){ + *DAC_LEFT=*q40_pp; + *DAC_RIGHT=*q40_pp++; + q40_sc --; + master_outb(1,SAMPLE_CLEAR_REG); + }else Q40Interrupt(); +} +static void Q40Interrupt(void) +{ + if (!write_sq.active) { + /* playing was interrupted and sq_reset() has already cleared + * the sq variables, so better don't do anything here. + */ + WAKE_UP(write_sq.sync_queue); + master_outb(0,SAMPLE_ENABLE_REG); /* better safe */ + goto exit; + } else write_sq.active=0; + write_sq.count--; + Q40Play(); + + if (q40_sc<2) + { /* there was nothing to play, disable irq */ + master_outb(0,SAMPLE_ENABLE_REG); + *DAC_LEFT=*DAC_RIGHT=0; + } + WAKE_UP(write_sq.action_queue); + + exit: + master_outb(1,SAMPLE_CLEAR_REG); +} + + +static void Q40Init(void) +{ + int i, idx; + const int freq[] = {10000, 20000}; + + /* search a frequency that fits into the allowed error range */ + + idx = -1; + for (i = 0; i < 2; i++) + if ((100 * abs(dmasound.soft.speed - freq[i]) / freq[i]) <= catchRadius) + idx = i; + + dmasound.hard = dmasound.soft; + /*sound.hard.stereo=1;*/ /* no longer true */ + dmasound.hard.size=8; + + if (idx > -1) { + dmasound.soft.speed = freq[idx]; + dmasound.trans_write = &transQ40Normal; + } else + dmasound.trans_write = &transQ40Expanding; + + Q40Silence(); + + if (dmasound.hard.speed > 20000) { + /* we would need to squeeze the sound, but we won't do that */ + dmasound.hard.speed = 20000; + dmasound.trans_write = &transQ40Normal; + } else if (dmasound.hard.speed > 10000) { + dmasound.hard.speed = 20000; + } else { + dmasound.hard.speed = 10000; + } + expand_bal = -dmasound.soft.speed; +} + + +static int Q40SetFormat(int format) +{ + /* Q40 sound supports only 8bit modes */ + + switch (format) { + case AFMT_QUERY: + return(dmasound.soft.format); + case AFMT_MU_LAW: + case AFMT_A_LAW: + case AFMT_S8: + case AFMT_U8: + break; + default: + format = AFMT_S8; + } + + dmasound.soft.format = format; + dmasound.soft.size = 8; + if (dmasound.minDev == SND_DEV_DSP) { + dmasound.dsp.format = format; + dmasound.dsp.size = 8; + } + Q40Init(); + + return(format); +} + +static int Q40SetVolume(int volume) +{ + return 0; +} + + +/*** Machine definitions *****************************************************/ + + +static MACHINE machQ40 = { + name: "Q40", + name2: "Q40", + open: Q40Open, + release: Q40Release, + dma_alloc: Q40Alloc, + dma_free: Q40Free, + irqinit: Q40IrqInit, +#ifdef MODULE + irqcleanup: Q40IrqCleanUp, +#endif /* MODULE */ + init: Q40Init, + silence: Q40Silence, + setFormat: Q40SetFormat, + setVolume: Q40SetVolume, + play: Q40Play +}; + + +/*** Config & Setup **********************************************************/ + + +int __init dmasound_q40_init(void) +{ + if (MACH_IS_Q40) { + dmasound.mach = machQ40; + return dmasound_init(); + } else + return -ENODEV; +} + +static void __exit dmasound_q40_cleanup(void) +{ + dmasound_deinit(); +} + +module_init(dmasound_q40_init); +module_exit(dmasound_q40_cleanup); diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/sound/dmasound.c linux/drivers/sound/dmasound.c --- v2.3.99-pre3/linux/drivers/sound/dmasound.c Wed Feb 16 17:03:52 2000 +++ linux/drivers/sound/dmasound.c Wed Dec 31 16:00:00 1969 @@ -1,5821 +0,0 @@ - -/* linux/drivers/sound/dmasound.c */ - -/* - -OSS/Free compatible Atari TT/Falcon and Amiga DMA sound driver for Linux/m68k -Extended to support Power Macintosh for Linux/ppc by Paul Mackerras - -(c) 1995 by Michael Schlueter & Michael Marte - -Michael Schlueter (michael@duck.syd.de) did the basic structure of the VFS -interface and the u-law to signed byte conversion. - -Michael Marte (marte@informatik.uni-muenchen.de) did the sound queue, -/dev/mixer, /dev/sndstat and complemented the VFS interface. He would like -to thank: -Michael Schlueter for initial ideas and documentation on the MFP and -the DMA sound hardware. -Therapy? for their CD 'Troublegum' which really made me rock. - -/dev/sndstat is based on code by Hannu Savolainen, the author of the -VoxWare family of drivers. - -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. - -History: -1995/8/25 first release - -1995/9/02 ++roman: fixed atari_stram_alloc() call, the timer programming - and several race conditions - -1995/9/14 ++roman: After some discussion with Michael Schlueter, revised - the interrupt disabling - Slightly speeded up U8->S8 translation by using long - operations where possible - Added 4:3 interpolation for /dev/audio - -1995/9/20 ++TeSche: Fixed a bug in sq_write and changed /dev/audio - converting to play at 12517Hz instead of 6258Hz. - -1995/9/23 ++TeSche: Changed sq_interrupt() and sq_play() to pre-program - the DMA for another frame while there's still one - running. This allows the IRQ response to be - arbitrarily delayed and playing will still continue. - -1995/10/14 ++Guenther_Kelleter@ac3.maus.de, ++TeSche: better support for - Falcon audio (the Falcon doesn't raise an IRQ at the - end of a frame, but at the beginning instead!). uses - 'if (codec_dma)' in lots of places to simply switch - between Falcon and TT code. - -1995/11/06 ++TeSche: started introducing a hardware abstraction scheme - (may perhaps also serve for Amigas?), can now play - samples at almost all frequencies by means of a more - generalized expand routine, takes a good deal of care - to cut data only at sample sizes, buffer size is now - a kernel runtime option, implemented fsync() & several - minor improvements - ++Guenther: useful hints and bug fixes, cross-checked it for - Falcons - -1996/3/9 ++geert: support added for Amiga, A-law, 16-bit little endian. - Unification to drivers/sound/dmasound.c. - -1996/4/6 ++Martin Mitchell: updated to 1.3 kernel. - -1996/6/13 ++topi: fixed things that were broken (mainly the amiga - 14-bit routines), /dev/sndstat shows now the real - hardware frequency, the lowpass filter is disabled - by default now. - -1996/9/25 ++geert: modularization - -1998-06-10 ++andreas: converted to use sound_core - -*/ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(__mc68000__) || defined(CONFIG_APUS) -#include -#endif -#include -#include -#include -#include - -#ifdef CONFIG_ATARI -#include -#include -#include -#endif /* CONFIG_ATARI */ -#ifdef CONFIG_AMIGA -#include -#include -#endif /* CONFIG_AMIGA */ -#ifdef CONFIG_PPC -#include -#include -#include -#include -#include -#include -#include -#include -#include "awacs_defs.h" -#include -#include -#endif /* CONFIG_PPC */ - -#include "dmasound.h" -#include - -#define HAS_8BIT_TABLES - -#ifdef MODULE -static int sq_unit = -1; -static int mixer_unit = -1; -static int state_unit = -1; -static int irq_installed = 0; -#endif /* MODULE */ -static char **sound_buffers = NULL; -#ifdef CONFIG_PPC -static char **sound_read_buffers = NULL; -#endif - -#ifdef CONFIG_ATARI -extern void atari_microwire_cmd(int cmd); -#endif /* CONFIG_ATARI */ - -#ifdef CONFIG_AMIGA - /* - * The minimum period for audio depends on htotal (for OCS/ECS/AGA) - * (Imported from arch/m68k/amiga/amisound.c) - */ - -extern volatile u_short amiga_audio_min_period; - - - /* - * amiga_mksound() should be able to restore the period after beeping - * (Imported from arch/m68k/amiga/amisound.c) - */ - -extern u_short amiga_audio_period; - - - /* - * Audio DMA masks - */ - -#define AMI_AUDIO_OFF (DMAF_AUD0 | DMAF_AUD1 | DMAF_AUD2 | DMAF_AUD3) -#define AMI_AUDIO_8 (DMAF_SETCLR | DMAF_MASTER | DMAF_AUD0 | DMAF_AUD1) -#define AMI_AUDIO_14 (AMI_AUDIO_8 | DMAF_AUD2 | DMAF_AUD3) - -#endif /* CONFIG_AMIGA */ - -#ifdef CONFIG_PPC -/* - * Interrupt numbers and addresses, obtained from the device tree. - */ -static int awacs_irq, awacs_tx_irq, awacs_rx_irq; -static volatile struct awacs_regs *awacs; -static volatile struct dbdma_regs *awacs_txdma, *awacs_rxdma; -static int awacs_rate_index; -static int awacs_subframe; -static int awacs_spkr_vol; -static struct device_node* awacs_node; - -static int awacs_revision; -#define AWACS_BURGUNDY 100 /* fake revision # for burgundy */ - -/* - * Space for the DBDMA command blocks. - */ -static void *awacs_tx_cmd_space; -static volatile struct dbdma_cmd *awacs_tx_cmds; - -static void *awacs_rx_cmd_space; -static volatile struct dbdma_cmd *awacs_rx_cmds; - -/* - * Cached values of AWACS registers (we can't read them). - * Except on the burgundy. XXX - */ -int awacs_reg[5]; - -#define HAS_16BIT_TABLES -#undef HAS_8BIT_TABLES - -/* - * Stuff for outputting a beep. The values range from -327 to +327 - * so we can multiply by an amplitude in the range 0..100 to get a - * signed short value to put in the output buffer. - */ -static short beep_wform[256] = { - 0, 40, 79, 117, 153, 187, 218, 245, - 269, 288, 304, 316, 323, 327, 327, 324, - 318, 310, 299, 288, 275, 262, 249, 236, - 224, 213, 204, 196, 190, 186, 183, 182, - 182, 183, 186, 189, 192, 196, 200, 203, - 206, 208, 209, 209, 209, 207, 204, 201, - 197, 193, 188, 183, 179, 174, 170, 166, - 163, 161, 160, 159, 159, 160, 161, 162, - 164, 166, 168, 169, 171, 171, 171, 170, - 169, 167, 163, 159, 155, 150, 144, 139, - 133, 128, 122, 117, 113, 110, 107, 105, - 103, 103, 103, 103, 104, 104, 105, 105, - 105, 103, 101, 97, 92, 86, 78, 68, - 58, 45, 32, 18, 3, -11, -26, -41, - -55, -68, -79, -88, -95, -100, -102, -102, - -99, -93, -85, -75, -62, -48, -33, -16, - 0, 16, 33, 48, 62, 75, 85, 93, - 99, 102, 102, 100, 95, 88, 79, 68, - 55, 41, 26, 11, -3, -18, -32, -45, - -58, -68, -78, -86, -92, -97, -101, -103, - -105, -105, -105, -104, -104, -103, -103, -103, - -103, -105, -107, -110, -113, -117, -122, -128, - -133, -139, -144, -150, -155, -159, -163, -167, - -169, -170, -171, -171, -171, -169, -168, -166, - -164, -162, -161, -160, -159, -159, -160, -161, - -163, -166, -170, -174, -179, -183, -188, -193, - -197, -201, -204, -207, -209, -209, -209, -208, - -206, -203, -200, -196, -192, -189, -186, -183, - -182, -182, -183, -186, -190, -196, -204, -213, - -224, -236, -249, -262, -275, -288, -299, -310, - -318, -324, -327, -327, -323, -316, -304, -288, - -269, -245, -218, -187, -153, -117, -79, -40, -}; - -#define BEEP_SRATE 22050 /* 22050 Hz sample rate */ -#define BEEP_BUFLEN 512 -#define BEEP_VOLUME 15 /* 0 - 100 */ - -static int beep_volume = BEEP_VOLUME; -static int beep_playing = 0; -static int awacs_beep_state = 0; -static short *beep_buf; -static volatile struct dbdma_cmd *beep_dbdma_cmd; -static void (*orig_mksound)(unsigned int, unsigned int); -static int is_pbook_3400; -static unsigned char *latch_base; -static int is_pbook_G3; -static unsigned char *macio_base; - -/* Burgundy functions */ -static void awacs_burgundy_wcw(unsigned addr,unsigned newval); -static unsigned awacs_burgundy_rcw(unsigned addr); -static void awacs_burgundy_write_volume(unsigned address, int volume); -static int awacs_burgundy_read_volume(unsigned address); -static void awacs_burgundy_write_mvolume(unsigned address, int volume); -static int awacs_burgundy_read_mvolume(unsigned address); - -#ifdef CONFIG_PMAC_PBOOK -/* - * Stuff for restoring after a sleep. - */ -static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when); -struct pmu_sleep_notifier awacs_sleep_notifier = { - awacs_sleep_notify, SLEEP_LEVEL_SOUND, -}; -#endif /* CONFIG_PMAC_PBOOK */ - -#endif /* CONFIG_PPC */ - -/*** Some declarations *******************************************************/ - - -#define DMASND_TT 1 -#define DMASND_FALCON 2 -#define DMASND_AMIGA 3 -#define DMASND_AWACS 4 - -#define MAX_CATCH_RADIUS 10 -#define MIN_BUFFERS 4 -#define MIN_BUFSIZE 4 -#define MAX_BUFSIZE 128 /* Limit for Amiga */ - -static int catchRadius = 0; -static int numBufs = 4, bufSize = 32; -#ifdef CONFIG_PPC -static int numReadBufs = 4, readbufSize = 32; -#endif - -MODULE_PARM(catchRadius, "i"); -MODULE_PARM(numBufs, "i"); -MODULE_PARM(bufSize, "i"); -MODULE_PARM(numReadBufs, "i"); -MODULE_PARM(readbufSize, "i"); - -#define arraysize(x) (sizeof(x)/sizeof(*(x))) -#define min(x, y) ((x) < (y) ? (x) : (y)) -#define le2be16(x) (((x)<<8 & 0xff00) | ((x)>>8 & 0x00ff)) -#define le2be16dbl(x) (((x)<<8 & 0xff00ff00) | ((x)>>8 & 0x00ff00ff)) - -#define IOCTL_IN(arg, ret) \ - do { int error = get_user(ret, (int *)(arg)); \ - if (error) return error; \ - } while (0) -#define IOCTL_OUT(arg, ret) ioctl_return((int *)(arg), ret) - - -/*** Some low level helpers **************************************************/ - -#ifdef HAS_8BIT_TABLES -/* 8 bit mu-law */ - -static char ulaw2dma8[] = { - -126, -122, -118, -114, -110, -106, -102, -98, - -94, -90, -86, -82, -78, -74, -70, -66, - -63, -61, -59, -57, -55, -53, -51, -49, - -47, -45, -43, -41, -39, -37, -35, -33, - -31, -30, -29, -28, -27, -26, -25, -24, - -23, -22, -21, -20, -19, -18, -17, -16, - -16, -15, -15, -14, -14, -13, -13, -12, - -12, -11, -11, -10, -10, -9, -9, -8, - -8, -8, -7, -7, -7, -7, -6, -6, - -6, -6, -5, -5, -5, -5, -4, -4, - -4, -4, -4, -4, -3, -3, -3, -3, - -3, -3, -3, -3, -2, -2, -2, -2, - -2, -2, -2, -2, -2, -2, -2, -2, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 0, - 125, 121, 117, 113, 109, 105, 101, 97, - 93, 89, 85, 81, 77, 73, 69, 65, - 62, 60, 58, 56, 54, 52, 50, 48, - 46, 44, 42, 40, 38, 36, 34, 32, - 30, 29, 28, 27, 26, 25, 24, 23, - 22, 21, 20, 19, 18, 17, 16, 15, - 15, 14, 14, 13, 13, 12, 12, 11, - 11, 10, 10, 9, 9, 8, 8, 7, - 7, 7, 6, 6, 6, 6, 5, 5, - 5, 5, 4, 4, 4, 4, 3, 3, - 3, 3, 3, 3, 2, 2, 2, 2, - 2, 2, 2, 2, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* 8 bit A-law */ - -static char alaw2dma8[] = { - -22, -21, -24, -23, -18, -17, -20, -19, - -30, -29, -32, -31, -26, -25, -28, -27, - -11, -11, -12, -12, -9, -9, -10, -10, - -15, -15, -16, -16, -13, -13, -14, -14, - -86, -82, -94, -90, -70, -66, -78, -74, - -118, -114, -126, -122, -102, -98, -110, -106, - -43, -41, -47, -45, -35, -33, -39, -37, - -59, -57, -63, -61, -51, -49, -55, -53, - -2, -2, -2, -2, -2, -2, -2, -2, - -2, -2, -2, -2, -2, -2, -2, -2, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -6, -6, -6, -6, -5, -5, -5, -5, - -8, -8, -8, -8, -7, -7, -7, -7, - -3, -3, -3, -3, -3, -3, -3, -3, - -4, -4, -4, -4, -4, -4, -4, -4, - 21, 20, 23, 22, 17, 16, 19, 18, - 29, 28, 31, 30, 25, 24, 27, 26, - 10, 10, 11, 11, 8, 8, 9, 9, - 14, 14, 15, 15, 12, 12, 13, 13, - 86, 82, 94, 90, 70, 66, 78, 74, - 118, 114, 126, 122, 102, 98, 110, 106, - 43, 41, 47, 45, 35, 33, 39, 37, - 59, 57, 63, 61, 51, 49, 55, 53, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 5, 5, 5, 5, 4, 4, 4, 4, - 7, 7, 7, 7, 6, 6, 6, 6, - 2, 2, 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 3 -}; -#endif /* HAS_8BIT_TABLES */ - -#ifdef HAS_16BIT_TABLES - -/* 16 bit mu-law */ - -static short ulaw2dma16[] = { - -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956, - -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764, - -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412, - -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316, - -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140, - -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092, - -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004, - -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980, - -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436, - -1372, -1308, -1244, -1180, -1116, -1052, -988, -924, - -876, -844, -812, -780, -748, -716, -684, -652, - -620, -588, -556, -524, -492, -460, -428, -396, - -372, -356, -340, -324, -308, -292, -276, -260, - -244, -228, -212, -196, -180, -164, -148, -132, - -120, -112, -104, -96, -88, -80, -72, -64, - -56, -48, -40, -32, -24, -16, -8, 0, - 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956, - 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764, - 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412, - 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316, - 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140, - 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092, - 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004, - 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980, - 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436, - 1372, 1308, 1244, 1180, 1116, 1052, 988, 924, - 876, 844, 812, 780, 748, 716, 684, 652, - 620, 588, 556, 524, 492, 460, 428, 396, - 372, 356, 340, 324, 308, 292, 276, 260, - 244, 228, 212, 196, 180, 164, 148, 132, - 120, 112, 104, 96, 88, 80, 72, 64, - 56, 48, 40, 32, 24, 16, 8, 0, -}; - -/* 16 bit A-law */ - -static short alaw2dma16[] = { - -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736, - -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, - -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368, - -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392, - -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944, - -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136, - -11008, -10496, -12032, -11520, -8960, -8448, -9984, -9472, - -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568, - -344, -328, -376, -360, -280, -264, -312, -296, - -472, -456, -504, -488, -408, -392, -440, -424, - -88, -72, -120, -104, -24, -8, -56, -40, - -216, -200, -248, -232, -152, -136, -184, -168, - -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184, - -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, - -688, -656, -752, -720, -560, -528, -624, -592, - -944, -912, -1008, -976, -816, -784, -880, -848, - 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736, - 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, - 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368, - 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, - 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944, - 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, - 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472, - 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, - 344, 328, 376, 360, 280, 264, 312, 296, - 472, 456, 504, 488, 408, 392, 440, 424, - 88, 72, 120, 104, 24, 8, 56, 40, - 216, 200, 248, 232, 152, 136, 184, 168, - 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184, - 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, - 688, 656, 752, 720, 560, 528, 624, 592, - 944, 912, 1008, 976, 816, 784, 880, 848, -}; -#endif /* HAS_16BIT_TABLES */ - - -#ifdef HAS_14BIT_TABLES - -/* 14 bit mu-law (LSB) */ - -static char alaw2dma14l[] = { - 33, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 33, 33, 33, 33, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 49, 17, 49, 17, 49, 17, 49, 17, - 49, 17, 49, 17, 49, 17, 49, 17, - 41, 57, 9, 25, 41, 57, 9, 25, - 41, 57, 9, 25, 41, 57, 9, 25, - 37, 45, 53, 61, 5, 13, 21, 29, - 37, 45, 53, 61, 5, 13, 21, 29, - 35, 39, 43, 47, 51, 55, 59, 63, - 3, 7, 11, 15, 19, 23, 27, 31, - 34, 36, 38, 40, 42, 44, 46, 48, - 50, 52, 54, 56, 58, 60, 62, 0, - 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31, - 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, - 15, 47, 15, 47, 15, 47, 15, 47, - 15, 47, 15, 47, 15, 47, 15, 47, - 23, 7, 55, 39, 23, 7, 55, 39, - 23, 7, 55, 39, 23, 7, 55, 39, - 27, 19, 11, 3, 59, 51, 43, 35, - 27, 19, 11, 3, 59, 51, 43, 35, - 29, 25, 21, 17, 13, 9, 5, 1, - 61, 57, 53, 49, 45, 41, 37, 33, - 30, 28, 26, 24, 22, 20, 18, 16, - 14, 12, 10, 8, 6, 4, 2, 0 -}; - -/* 14 bit A-law (LSB) */ - -static char alaw2dma14l[] = { - 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, - 16, 48, 16, 48, 16, 48, 16, 48, - 16, 48, 16, 48, 16, 48, 16, 48, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 42, 46, 34, 38, 58, 62, 50, 54, - 10, 14, 2, 6, 26, 30, 18, 22, - 42, 46, 34, 38, 58, 62, 50, 54, - 10, 14, 2, 6, 26, 30, 18, 22, - 40, 56, 8, 24, 40, 56, 8, 24, - 40, 56, 8, 24, 40, 56, 8, 24, - 20, 28, 4, 12, 52, 60, 36, 44, - 20, 28, 4, 12, 52, 60, 36, 44, - 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, - 48, 16, 48, 16, 48, 16, 48, 16, - 48, 16, 48, 16, 48, 16, 48, 16, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 22, 18, 30, 26, 6, 2, 14, 10, - 54, 50, 62, 58, 38, 34, 46, 42, - 22, 18, 30, 26, 6, 2, 14, 10, - 54, 50, 62, 58, 38, 34, 46, 42, - 24, 8, 56, 40, 24, 8, 56, 40, - 24, 8, 56, 40, 24, 8, 56, 40, - 44, 36, 60, 52, 12, 4, 28, 20, - 44, 36, 60, 52, 12, 4, 28, 20 -}; -#endif /* HAS_14BIT_TABLES */ - - -/*** Translations ************************************************************/ - - -#ifdef CONFIG_ATARI -static ssize_t ata_ct_law(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t ata_ct_s8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t ata_ct_u8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t ata_ct_s16be(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t ata_ct_u16be(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t ata_ct_s16le(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t ata_ct_u16le(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t ata_ctx_law(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t ata_ctx_s8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t ata_ctx_u8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t ata_ctx_s16be(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t ata_ctx_u16be(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t ata_ctx_s16le(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t ata_ctx_u16le(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -#endif /* CONFIG_ATARI */ - -#ifdef CONFIG_AMIGA -static ssize_t ami_ct_law(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t ami_ct_s8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t ami_ct_u8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t ami_ct_s16be(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t ami_ct_u16be(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t ami_ct_s16le(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t ami_ct_u16le(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -#endif /* CONFIG_AMIGA */ - -#ifdef CONFIG_PPC -static ssize_t pmac_ct_law(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t pmac_ct_s8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t pmac_ct_u8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t pmac_ct_s16(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t pmac_ct_u16(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t pmac_ctx_law(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t pmac_ctx_s8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t pmac_ctx_u8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t pmac_ctx_s16(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t pmac_ctx_u16(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t pmac_ct_s16_read(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t pmac_ct_u16_read(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -#endif /* CONFIG_PPC */ - -/*** Machine definitions *****************************************************/ - - -typedef struct { - int type; - void *(*dma_alloc)(unsigned int, int); - void (*dma_free)(void *, unsigned int); - int (*irqinit)(void); -#ifdef MODULE - void (*irqcleanup)(void); -#endif /* MODULE */ - void (*init)(void); - void (*silence)(void); - int (*setFormat)(int); - int (*setVolume)(int); - int (*setBass)(int); - int (*setTreble)(int); - int (*setGain)(int); - void (*play)(void); -} MACHINE; - - -/*** Low level stuff *********************************************************/ - - -typedef struct { - int format; /* AFMT_* */ - int stereo; /* 0 = mono, 1 = stereo */ - int size; /* 8/16 bit*/ - int speed; /* speed */ -} SETTINGS; - -typedef struct { - ssize_t (*ct_ulaw)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_alaw)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_s8)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_u8)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_s16be)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_u16be)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_s16le)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_u16le)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); -} TRANS; - -struct sound_settings { - MACHINE mach; /* machine dependent things */ - SETTINGS hard; /* hardware settings */ - SETTINGS soft; /* software settings */ - SETTINGS dsp; /* /dev/dsp default settings */ - TRANS *trans; /* supported translations */ -#if defined(CONFIG_PPC) - TRANS *read_trans; /* supported translations */ -#endif - int volume_left; /* volume (range is machine dependent) */ - int volume_right; - int bass; /* tone (range is machine dependent) */ - int treble; - int gain; - int minDev; /* minor device number currently open */ -#if defined(CONFIG_ATARI) || defined(CONFIG_PPC) - int bal; /* balance factor for expanding (not volume!) */ - u_long data; /* data for expanding */ -#endif /* CONFIG_ATARI */ -}; - -static struct sound_settings sound; - - -#ifdef CONFIG_ATARI -static void *AtaAlloc(unsigned int size, int flags); -static void AtaFree(void *, unsigned int size); -static int AtaIrqInit(void); -#ifdef MODULE -static void AtaIrqCleanUp(void); -#endif /* MODULE */ -static int AtaSetBass(int bass); -static int AtaSetTreble(int treble); -static void TTSilence(void); -static void TTInit(void); -static int TTSetFormat(int format); -static int TTSetVolume(int volume); -static int TTSetGain(int gain); -static void FalconSilence(void); -static void FalconInit(void); -static int FalconSetFormat(int format); -static int FalconSetVolume(int volume); -static void ata_sq_play_next_frame(int index); -static void AtaPlay(void); -static void ata_sq_interrupt(int irq, void *dummy, struct pt_regs *fp); -#endif /* CONFIG_ATARI */ - -#ifdef CONFIG_AMIGA -static void *AmiAlloc(unsigned int size, int flags); -static void AmiFree(void *, unsigned int); -static int AmiIrqInit(void); -#ifdef MODULE -static void AmiIrqCleanUp(void); -#endif /* MODULE */ -static void AmiSilence(void); -static void AmiInit(void); -static int AmiSetFormat(int format); -static int AmiSetVolume(int volume); -static int AmiSetTreble(int treble); -static void ami_sq_play_next_frame(int index); -static void AmiPlay(void); -static void ami_sq_interrupt(int irq, void *dummy, struct pt_regs *fp); -#endif /* CONFIG_AMIGA */ - -#ifdef CONFIG_PPC -static void *PMacAlloc(unsigned int size, int flags); -static void PMacFree(void *ptr, unsigned int size); -static int PMacIrqInit(void); -#ifdef MODULE -static void PMacIrqCleanup(void); -#endif /* MODULE */ -static void PMacSilence(void); -static void PMacInit(void); -static void PMacPlay(void); -static void PMacRecord(void); -static int PMacSetFormat(int format); -static int PMacSetVolume(int volume); -static void pmac_awacs_tx_intr(int irq, void *devid, struct pt_regs *regs); -static void pmac_awacs_rx_intr(int irq, void *devid, struct pt_regs *regs); -static void pmac_awacs_intr(int irq, void *devid, struct pt_regs *regs); -static void awacs_write(int val); -static int awacs_get_volume(int reg, int lshift); -static int awacs_volume_setter(int volume, int n, int mute, int lshift); -static void awacs_mksound(unsigned int hz, unsigned int ticks); -static void awacs_nosound(unsigned long xx); -#endif /* CONFIG_PPC */ - -/*** Mid level stuff *********************************************************/ - - -static void sound_silence(void); -static void sound_init(void); -static int sound_set_format(int format); -static int sound_set_speed(int speed); -static int sound_set_stereo(int stereo); -static int sound_set_volume(int volume); -#ifdef CONFIG_ATARI -static int sound_set_bass(int bass); -#endif /* CONFIG_ATARI */ -#if defined(CONFIG_ATARI) || defined(CONFIG_AMIGA) -static int sound_set_treble(int treble); -#endif /* CONFIG_ATARI || CONFIG_AMIGA */ -static ssize_t sound_copy_translate(const u_char *userPtr, - size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -#ifdef CONFIG_PPC -static ssize_t sound_copy_translate_read(const u_char *userPtr, - size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -#endif - - -/* - * /dev/mixer abstraction - */ - -struct sound_mixer { - int busy; - int modify_counter; -}; - -static struct sound_mixer mixer; - -/* - * Sound queue stuff, the heart of the driver - */ - -struct sound_queue { - int max_count, block_size; - char **buffers; - int max_active; - - /* it shouldn't be necessary to declare any of these volatile */ - int front, rear, count; - int rear_size; - /* - * The use of the playing field depends on the hardware - * - * Atari, PMac: The number of frames that are loaded/playing - * - * Amiga: Bit 0 is set: a frame is loaded - * Bit 1 is set: a frame is playing - */ - int active; - wait_queue_head_t action_queue, open_queue, sync_queue; - int open_mode; - int busy, syncing; -#ifdef CONFIG_ATARI - int ignore_int; /* ++TeSche: used for Falcon */ -#endif /* CONFIG_ATARI */ -#ifdef CONFIG_AMIGA - int block_size_half, block_size_quarter; -#endif /* CONFIG_AMIGA */ -}; - -static struct sound_queue sq; -#ifdef CONFIG_PPC -static struct sound_queue read_sq; -#endif - -#define sq_block_address(i) (sq.buffers[i]) -#define SIGNAL_RECEIVED (signal_pending(current)) -#define NON_BLOCKING(open_mode) (open_mode & O_NONBLOCK) -#define ONE_SECOND HZ /* in jiffies (100ths of a second) */ -#define NO_TIME_LIMIT 0xffffffff -#define SLEEP(queue, time_limit) \ - interruptible_sleep_on_timeout(&queue, (time_limit)); -#define WAKE_UP(queue) (wake_up_interruptible(&queue)) - -/* - * /dev/sndstat - */ - -struct sound_state { - int busy; - char buf[512]; - int len, ptr; -}; - -static struct sound_state state; - -/*** Common stuff ********************************************************/ - -static long long sound_lseek(struct file *file, long long offset, int orig); -static inline int ioctl_return(int *addr, int value) -{ - if (value < 0) - return(value); - - return put_user(value, addr); -} - - -/*** Config & Setup **********************************************************/ - - -void dmasound_init(void); -static int dmasound_setup(char *str); - - -/*** Translations ************************************************************/ - - -/* ++TeSche: radically changed for new expanding purposes... - * - * These two routines now deal with copying/expanding/translating the samples - * from user space into our buffer at the right frequency. They take care about - * how much data there's actually to read, how much buffer space there is and - * to convert samples into the right frequency/encoding. They will only work on - * complete samples so it may happen they leave some bytes in the input stream - * if the user didn't write a multiple of the current sample size. They both - * return the number of bytes they've used from both streams so you may detect - * such a situation. Luckily all programs should be able to cope with that. - * - * I think I've optimized anything as far as one can do in plain C, all - * variables should fit in registers and the loops are really short. There's - * one loop for every possible situation. Writing a more generalized and thus - * parameterized loop would only produce slower code. Feel free to optimize - * this in assembler if you like. :) - * - * I think these routines belong here because they're not yet really hardware - * independent, especially the fact that the Falcon can play 16bit samples - * only in stereo is hardcoded in both of them! - * - * ++geert: split in even more functions (one per format) - */ - -#ifdef CONFIG_ATARI -static ssize_t ata_ct_law(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8; - ssize_t count, used; - u_char *p = &frame[*frameUsed]; - - count = min(userCount, frameLeft); - if (sound.soft.stereo) - count &= ~1; - used = count; - while (count > 0) { - u_char data; - if (get_user(data, userPtr++)) - return -EFAULT; - *p++ = table[data]; - count--; - } - *frameUsed += used; - return used; -} - - -static ssize_t ata_ct_s8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - void *p = &frame[*frameUsed]; - - count = min(userCount, frameLeft); - if (sound.soft.stereo) - count &= ~1; - used = count; - if (copy_from_user(p, userPtr, count)) - return -EFAULT; - *frameUsed += used; - return(used); -} - - -static ssize_t ata_ct_u8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - - if (!sound.soft.stereo) { - u_char *p = &frame[*frameUsed]; - count = min(userCount, frameLeft); - used = count; - while (count > 0) { - u_char data; - if (get_user(data, userPtr++)) - return -EFAULT; - *p++ = data ^ 0x80; - count--; - } - } else { - u_short *p = (u_short *)&frame[*frameUsed]; - count = min(userCount, frameLeft)>>1; - used = count*2; - while (count > 0) { - u_short data; - if (get_user(data, ((u_short *)userPtr)++)) - return -EFAULT; - *p++ = data ^ 0x8080; - count--; - } - } - *frameUsed += used; - return(used); -} - - -static ssize_t ata_ct_s16be(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - - if (!sound.soft.stereo) { - u_short *p = (u_short *)&frame[*frameUsed]; - count = min(userCount, frameLeft)>>1; - used = count*2; - while (count > 0) { - u_short data; - if (get_user(data, ((u_short *)userPtr)++)) - return -EFAULT; - *p++ = data; - *p++ = data; - count--; - } - *frameUsed += used*2; - } else { - void *p = (u_short *)&frame[*frameUsed]; - count = min(userCount, frameLeft) & ~3; - used = count; - if (copy_from_user(p, userPtr, count)) - return -EFAULT; - *frameUsed += used; - } - return(used); -} - - -static ssize_t ata_ct_u16be(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - - if (!sound.soft.stereo) { - u_short *p = (u_short *)&frame[*frameUsed]; - count = min(userCount, frameLeft)>>1; - used = count*2; - while (count > 0) { - u_short data; - if (get_user(data, ((u_short *)userPtr)++)) - return -EFAULT; - data ^= 0x8000; - *p++ = data; - *p++ = data; - count--; - } - *frameUsed += used*2; - } else { - u_long *p = (u_long *)&frame[*frameUsed]; - count = min(userCount, frameLeft)>>2; - used = count*4; - while (count > 0) { - u_long data; - if (get_user(data, ((u_int *)userPtr)++)) - return -EFAULT; - *p++ = data ^ 0x80008000; - count--; - } - *frameUsed += used; - } - return(used); -} - - -static ssize_t ata_ct_s16le(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - - count = frameLeft; - if (!sound.soft.stereo) { - u_short *p = (u_short *)&frame[*frameUsed]; - count = min(userCount, frameLeft)>>1; - used = count*2; - while (count > 0) { - u_short data; - if (get_user(data, ((u_short *)userPtr)++)) - return -EFAULT; - data = le2be16(data); - *p++ = data; - *p++ = data; - count--; - } - *frameUsed += used*2; - } else { - u_long *p = (u_long *)&frame[*frameUsed]; - count = min(userCount, frameLeft)>>2; - used = count*4; - while (count > 0) { - u_long data; - if (get_user(data, ((u_int *)userPtr)++)) - return -EFAULT; - data = le2be16dbl(data); - *p++ = data; - count--; - } - *frameUsed += used; - } - return(used); -} - - -static ssize_t ata_ct_u16le(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - - count = frameLeft; - if (!sound.soft.stereo) { - u_short *p = (u_short *)&frame[*frameUsed]; - count = min(userCount, frameLeft)>>1; - used = count*2; - while (count > 0) { - u_short data; - if (get_user(data, ((u_short *)userPtr)++)) - return -EFAULT; - data = le2be16(data) ^ 0x8000; - *p++ = data; - *p++ = data; - } - *frameUsed += used*2; - } else { - u_long *p = (u_long *)&frame[*frameUsed]; - count = min(userCount, frameLeft)>>2; - used = count; - while (count > 0) { - u_long data; - if (get_user(data, ((u_int *)userPtr)++)) - return -EFAULT; - data = le2be16dbl(data) ^ 0x80008000; - *p++ = data; - count--; - } - *frameUsed += used; - } - return(used); -} - - -static ssize_t ata_ctx_law(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8; - /* this should help gcc to stuff everything into registers */ - long bal = sound.bal; - long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - ssize_t used, usedf; - - used = userCount; - usedf = frameLeft; - if (!sound.soft.stereo) { - u_char *p = &frame[*frameUsed]; - u_char data = sound.data; - while (frameLeft) { - u_char c; - if (bal < 0) { - if (!userCount) - break; - if (get_user(c, userPtr++)) - return -EFAULT; - data = table[c]; - userCount--; - bal += hSpeed; - } - *p++ = data; - frameLeft--; - bal -= sSpeed; - } - sound.data = data; - } else { - u_short *p = (u_short *)&frame[*frameUsed]; - u_short data = sound.data; - while (frameLeft >= 2) { - u_char c; - if (bal < 0) { - if (userCount < 2) - break; - if (get_user(c, userPtr++)) - return -EFAULT; - data = table[c] << 8; - if (get_user(c, userPtr++)) - return -EFAULT; - data |= table[c]; - userCount -= 2; - bal += hSpeed; - } - *p++ = data; - frameLeft -= 2; - bal -= sSpeed; - } - sound.data = data; - } - sound.bal = bal; - used -= userCount; - *frameUsed += usedf-frameLeft; - return(used); -} - - -static ssize_t ata_ctx_s8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - /* this should help gcc to stuff everything into registers */ - long bal = sound.bal; - long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - ssize_t used, usedf; - - used = userCount; - usedf = frameLeft; - if (!sound.soft.stereo) { - u_char *p = &frame[*frameUsed]; - u_char data = sound.data; - while (frameLeft) { - if (bal < 0) { - if (!userCount) - break; - if (get_user(data, userPtr++)) - return -EFAULT; - userCount--; - bal += hSpeed; - } - *p++ = data; - frameLeft--; - bal -= sSpeed; - } - sound.data = data; - } else { - u_short *p = (u_short *)&frame[*frameUsed]; - u_short data = sound.data; - while (frameLeft >= 2) { - if (bal < 0) { - if (userCount < 2) - break; - if (get_user(data, ((u_short *)userPtr)++)) - return -EFAULT; - userCount -= 2; - bal += hSpeed; - } - *p++ = data; - frameLeft -= 2; - bal -= sSpeed; - } - sound.data = data; - } - sound.bal = bal; - used -= userCount; - *frameUsed += usedf-frameLeft; - return(used); -} - - -static ssize_t ata_ctx_u8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - /* this should help gcc to stuff everything into registers */ - long bal = sound.bal; - long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - ssize_t used, usedf; - - used = userCount; - usedf = frameLeft; - if (!sound.soft.stereo) { - u_char *p = &frame[*frameUsed]; - u_char data = sound.data; - while (frameLeft) { - if (bal < 0) { - if (!userCount) - break; - if (get_user(data, userPtr++)) - return -EFAULT; - data ^= 0x80; - userCount--; - bal += hSpeed; - } - *p++ = data; - frameLeft--; - bal -= sSpeed; - } - sound.data = data; - } else { - u_short *p = (u_short *)&frame[*frameUsed]; - u_short data = sound.data; - while (frameLeft >= 2) { - if (bal < 0) { - if (userCount < 2) - break; - if (get_user(data, ((u_short *)userPtr)++)) - return -EFAULT; - data ^= 0x8080; - userCount -= 2; - bal += hSpeed; - } - *p++ = data; - frameLeft -= 2; - bal -= sSpeed; - } - sound.data = data; - } - sound.bal = bal; - used -= userCount; - *frameUsed += usedf-frameLeft; - return(used); -} - - -static ssize_t ata_ctx_s16be(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - /* this should help gcc to stuff everything into registers */ - long bal = sound.bal; - long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - ssize_t used, usedf; - - used = userCount; - usedf = frameLeft; - if (!sound.soft.stereo) { - u_short *p = (u_short *)&frame[*frameUsed]; - u_short data = sound.data; - while (frameLeft >= 4) { - if (bal < 0) { - if (userCount < 2) - break; - if (get_user(data, ((u_short *)userPtr)++)) - return -EFAULT; - userCount -= 2; - bal += hSpeed; - } - *p++ = data; - *p++ = data; - frameLeft -= 4; - bal -= sSpeed; - } - sound.data = data; - } else { - u_long *p = (u_long *)&frame[*frameUsed]; - u_long data = sound.data; - while (frameLeft >= 4) { - if (bal < 0) { - if (userCount < 4) - break; - if (get_user(data, ((u_int *)userPtr)++)) - return -EFAULT; - userCount -= 4; - bal += hSpeed; - } - *p++ = data; - frameLeft -= 4; - bal -= sSpeed; - } - sound.data = data; - } - sound.bal = bal; - used -= userCount; - *frameUsed += usedf-frameLeft; - return(used); -} - - -static ssize_t ata_ctx_u16be(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - /* this should help gcc to stuff everything into registers */ - long bal = sound.bal; - long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - ssize_t used, usedf; - - used = userCount; - usedf = frameLeft; - if (!sound.soft.stereo) { - u_short *p = (u_short *)&frame[*frameUsed]; - u_short data = sound.data; - while (frameLeft >= 4) { - if (bal < 0) { - if (userCount < 2) - break; - if (get_user(data, ((u_short *)userPtr)++)) - return -EFAULT; - data ^= 0x8000; - userCount -= 2; - bal += hSpeed; - } - *p++ = data; - *p++ = data; - frameLeft -= 4; - bal -= sSpeed; - } - sound.data = data; - } else { - u_long *p = (u_long *)&frame[*frameUsed]; - u_long data = sound.data; - while (frameLeft >= 4) { - if (bal < 0) { - if (userCount < 4) - break; - if (get_user(data, ((u_int *)userPtr)++)) - return -EFAULT; - data ^= 0x80008000; - userCount -= 4; - bal += hSpeed; - } - *p++ = data; - frameLeft -= 4; - bal -= sSpeed; - } - sound.data = data; - } - sound.bal = bal; - used -= userCount; - *frameUsed += usedf-frameLeft; - return(used); -} - - -static ssize_t ata_ctx_s16le(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - /* this should help gcc to stuff everything into registers */ - long bal = sound.bal; - long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - ssize_t used, usedf; - - used = userCount; - usedf = frameLeft; - if (!sound.soft.stereo) { - u_short *p = (u_short *)&frame[*frameUsed]; - u_short data = sound.data; - while (frameLeft >= 4) { - if (bal < 0) { - if (userCount < 2) - break; - if (get_user(data, ((u_short *)userPtr)++)) - return -EFAULT; - data = le2be16(data); - userCount -= 2; - bal += hSpeed; - } - *p++ = data; - *p++ = data; - frameLeft -= 4; - bal -= sSpeed; - } - sound.data = data; - } else { - u_long *p = (u_long *)&frame[*frameUsed]; - u_long data = sound.data; - while (frameLeft >= 4) { - if (bal < 0) { - if (userCount < 4) - break; - if (get_user(data, ((u_int *)userPtr)++)) - return -EFAULT; - data = le2be16dbl(data); - userCount -= 4; - bal += hSpeed; - } - *p++ = data; - frameLeft -= 4; - bal -= sSpeed; - } - sound.data = data; - } - sound.bal = bal; - used -= userCount; - *frameUsed += usedf-frameLeft; - return(used); -} - - -static ssize_t ata_ctx_u16le(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - /* this should help gcc to stuff everything into registers */ - long bal = sound.bal; - long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - ssize_t used, usedf; - - used = userCount; - usedf = frameLeft; - if (!sound.soft.stereo) { - u_short *p = (u_short *)&frame[*frameUsed]; - u_short data = sound.data; - while (frameLeft >= 4) { - if (bal < 0) { - if (userCount < 2) - break; - if (get_user(data, ((u_short *)userPtr)++)) - return -EFAULT; - data = le2be16(data) ^ 0x8000; - userCount -= 2; - bal += hSpeed; - } - *p++ = data; - *p++ = data; - frameLeft -= 4; - bal -= sSpeed; - } - sound.data = data; - } else { - u_long *p = (u_long *)&frame[*frameUsed]; - u_long data = sound.data; - while (frameLeft >= 4) { - if (bal < 0) { - if (userCount < 4) - break; - if (get_user(data, ((u_int *)userPtr)++)) - return -EFAULT; - data = le2be16dbl(data) ^ 0x80008000; - userCount -= 4; - bal += hSpeed; - } - *p++ = data; - frameLeft -= 4; - bal -= sSpeed; - } - sound.data = data; - } - sound.bal = bal; - used -= userCount; - *frameUsed += usedf-frameLeft; - return(used); -} -#endif /* CONFIG_ATARI */ - - -#ifdef CONFIG_AMIGA -static ssize_t ami_ct_law(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8; - ssize_t count, used; - - if (!sound.soft.stereo) { - u_char *p = &frame[*frameUsed]; - count = min(userCount, frameLeft) & ~1; - used = count; - while (count > 0) { - u_char data; - if (get_user(data, userPtr++)) - return -EFAULT; - *p++ = table[data]; - count--; - } - } else { - u_char *left = &frame[*frameUsed>>1]; - u_char *right = left+sq.block_size_half; - count = min(userCount, frameLeft)>>1 & ~1; - used = count*2; - while (count > 0) { - u_char data; - if (get_user(data, userPtr++)) - return -EFAULT; - *left++ = table[data]; - if (get_user(data, userPtr++)) - return -EFAULT; - *right++ = table[data]; - count--; - } - } - *frameUsed += used; - return(used); -} - - -static ssize_t ami_ct_s8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, ssize_t frameLeft) -{ - ssize_t count, used; - - if (!sound.soft.stereo) { - void *p = &frame[*frameUsed]; - count = min(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+sq.block_size_half; - count = min(userCount, frameLeft)>>1 & ~1; - used = count*2; - while (count > 0) { - if (get_user(*left++, userPtr++) - || get_user(*right++, userPtr++)) - return -EFAULT; - count--; - } - } - *frameUsed += used; - return(used); -} - - -static ssize_t ami_ct_u8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, ssize_t frameLeft) -{ - ssize_t count, used; - - if (!sound.soft.stereo) { - char *p = &frame[*frameUsed]; - count = min(userCount, frameLeft) & ~1; - used = count; - while (count > 0) { - u_char data; - if (get_user(data, userPtr++)) - return -EFAULT; - *p++ = data ^ 0x80; - count--; - } - } else { - u_char *left = &frame[*frameUsed>>1]; - u_char *right = left+sq.block_size_half; - count = min(userCount, frameLeft)>>1 & ~1; - used = count*2; - while (count > 0) { - u_char data; - if (get_user(data, userPtr++)) - return -EFAULT; - *left++ = data ^ 0x80; - if (get_user(data, userPtr++)) - return -EFAULT; - *right++ = data ^ 0x80; - count--; - } - } - *frameUsed += used; - return(used); -} - - -static ssize_t ami_ct_s16be(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - u_short data; - - if (!sound.soft.stereo) { - u_char *high = &frame[*frameUsed>>1]; - u_char *low = high+sq.block_size_half; - count = min(userCount, frameLeft)>>1 & ~1; - used = count*2; - while (count > 0) { - if (get_user(data, ((u_short *)userPtr)++)) - return -EFAULT; - *high++ = data>>8; - *low++ = (data>>2) & 0x3f; - count--; - } - } else { - u_char *lefth = &frame[*frameUsed>>2]; - u_char *leftl = lefth+sq.block_size_quarter; - u_char *righth = lefth+sq.block_size_half; - u_char *rightl = righth+sq.block_size_quarter; - count = min(userCount, frameLeft)>>2 & ~1; - used = count*4; - while (count > 0) { - if (get_user(data, ((u_short *)userPtr)++)) - return -EFAULT; - *lefth++ = data>>8; - *leftl++ = (data>>2) & 0x3f; - if (get_user(data, ((u_short *)userPtr)++)) - return -EFAULT; - *righth++ = data>>8; - *rightl++ = (data>>2) & 0x3f; - count--; - } - } - *frameUsed += used; - return(used); -} - - -static ssize_t ami_ct_u16be(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - u_short data; - - if (!sound.soft.stereo) { - u_char *high = &frame[*frameUsed>>1]; - u_char *low = high+sq.block_size_half; - count = min(userCount, frameLeft)>>1 & ~1; - used = count*2; - while (count > 0) { - if (get_user(data, ((u_short *)userPtr)++)) - return -EFAULT; - data ^= 0x8000; - *high++ = data>>8; - *low++ = (data>>2) & 0x3f; - count--; - } - } else { - u_char *lefth = &frame[*frameUsed>>2]; - u_char *leftl = lefth+sq.block_size_quarter; - u_char *righth = lefth+sq.block_size_half; - u_char *rightl = righth+sq.block_size_quarter; - count = min(userCount, frameLeft)>>2 & ~1; - used = count*4; - while (count > 0) { - if (get_user(data, ((u_short *)userPtr)++)) - return -EFAULT; - data ^= 0x8000; - *lefth++ = data>>8; - *leftl++ = (data>>2) & 0x3f; - if (get_user(data, ((u_short *)userPtr)++)) - return -EFAULT; - data ^= 0x8000; - *righth++ = data>>8; - *rightl++ = (data>>2) & 0x3f; - count--; - } - } - *frameUsed += used; - return(used); -} - - -static ssize_t ami_ct_s16le(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - u_short data; - - if (!sound.soft.stereo) { - u_char *high = &frame[*frameUsed>>1]; - u_char *low = high+sq.block_size_half; - count = min(userCount, frameLeft)>>1 & ~1; - used = count*2; - while (count > 0) { - if (get_user(data, ((u_short *)userPtr)++)) - return -EFAULT; - data = le2be16(data); - *high++ = data>>8; - *low++ = (data>>2) & 0x3f; - count--; - } - } else { - u_char *lefth = &frame[*frameUsed>>2]; - u_char *leftl = lefth+sq.block_size_quarter; - u_char *righth = lefth+sq.block_size_half; - u_char *rightl = righth+sq.block_size_quarter; - count = min(userCount, frameLeft)>>2 & ~1; - used = count*4; - while (count > 0) { - if (get_user(data, ((u_short *)userPtr)++)) - return -EFAULT; - data = le2be16(data); - *lefth++ = data>>8; - *leftl++ = (data>>2) & 0x3f; - if (get_user(data, ((u_short *)userPtr)++)) - return -EFAULT; - data = le2be16(data); - *righth++ = data>>8; - *rightl++ = (data>>2) & 0x3f; - count--; - } - } - *frameUsed += used; - return(used); -} - - -static ssize_t ami_ct_u16le(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - u_short data; - - if (!sound.soft.stereo) { - u_char *high = &frame[*frameUsed>>1]; - u_char *low = high+sq.block_size_half; - count = min(userCount, frameLeft)>>1 & ~1; - used = count*2; - while (count > 0) { - if (get_user(data, ((u_short *)userPtr)++)) - return -EFAULT; - data = le2be16(data) ^ 0x8000; - *high++ = data>>8; - *low++ = (data>>2) & 0x3f; - count--; - } - } else { - u_char *lefth = &frame[*frameUsed>>2]; - u_char *leftl = lefth+sq.block_size_quarter; - u_char *righth = lefth+sq.block_size_half; - u_char *rightl = righth+sq.block_size_quarter; - count = min(userCount, frameLeft)>>2 & ~1; - used = count*4; - while (count > 0) { - if (get_user(data, ((u_short *)userPtr)++)) - return -EFAULT; - data = le2be16(data) ^ 0x8000; - *lefth++ = data>>8; - *leftl++ = (data>>2) & 0x3f; - if (get_user(data, ((u_short *)userPtr)++)) - return -EFAULT; - data = le2be16(data) ^ 0x8000; - *righth++ = data>>8; - *rightl++ = (data>>2) & 0x3f; - count--; - } - } - *frameUsed += used; - return(used); -} -#endif /* CONFIG_AMIGA */ - -#ifdef CONFIG_PPC -static ssize_t pmac_ct_law(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - short *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma16: alaw2dma16; - ssize_t count, used; - short *p = (short *) &frame[*frameUsed]; - int val, stereo = sound.soft.stereo; - - frameLeft >>= 2; - if (stereo) - userCount >>= 1; - used = count = min(userCount, frameLeft); - while (count > 0) { - u_char data; - if (get_user(data, userPtr++)) - return -EFAULT; - val = table[data]; - *p++ = val; - if (stereo) { - if (get_user(data, userPtr++)) - return -EFAULT; - val = table[data]; - } - *p++ = val; - count--; - } - *frameUsed += used * 4; - return stereo? used * 2: used; -} - - -static ssize_t pmac_ct_s8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - short *p = (short *) &frame[*frameUsed]; - int val, stereo = sound.soft.stereo; - - frameLeft >>= 2; - if (stereo) - userCount >>= 1; - used = count = min(userCount, frameLeft); - while (count > 0) { - u_char data; - if (get_user(data, userPtr++)) - return -EFAULT; - val = data << 8; - *p++ = val; - if (stereo) { - if (get_user(data, userPtr++)) - return -EFAULT; - val = data << 8; - } - *p++ = val; - count--; - } - *frameUsed += used * 4; - return stereo? used * 2: used; -} - - -static ssize_t pmac_ct_u8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - short *p = (short *) &frame[*frameUsed]; - int val, stereo = sound.soft.stereo; - - frameLeft >>= 2; - if (stereo) - userCount >>= 1; - used = count = min(userCount, frameLeft); - while (count > 0) { - u_char data; - if (get_user(data, userPtr++)) - return -EFAULT; - val = (data ^ 0x80) << 8; - *p++ = val; - if (stereo) { - if (get_user(data, userPtr++)) - return -EFAULT; - val = (data ^ 0x80) << 8; - } - *p++ = val; - count--; - } - *frameUsed += used * 4; - return stereo? used * 2: used; -} - - -static ssize_t pmac_ct_s16(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - int stereo = sound.soft.stereo; - short *fp = (short *) &frame[*frameUsed]; - - frameLeft >>= 2; - userCount >>= (stereo? 2: 1); - used = count = min(userCount, frameLeft); - if (!stereo) { - short *up = (short *) userPtr; - while (count > 0) { - short data; - if (get_user(data, up++)) - return -EFAULT; - *fp++ = data; - *fp++ = data; - count--; - } - } else { - if (copy_from_user(fp, userPtr, count * 4)) - return -EFAULT; - } - *frameUsed += used * 4; - return stereo? used * 4: used * 2; -} - -static ssize_t pmac_ct_u16(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - int mask = (sound.soft.format == AFMT_U16_LE? 0x0080: 0x8000); - int stereo = sound.soft.stereo; - short *fp = (short *) &frame[*frameUsed]; - short *up = (short *) userPtr; - - frameLeft >>= 2; - userCount >>= (stereo? 2: 1); - used = count = min(userCount, frameLeft); - while (count > 0) { - int data; - if (get_user(data, up++)) - return -EFAULT; - data ^= mask; - *fp++ = data; - if (stereo) { - if (get_user(data, up++)) - return -EFAULT; - data ^= mask; - } - *fp++ = data; - count--; - } - *frameUsed += used * 4; - return stereo? used * 4: used * 2; -} - - -static ssize_t pmac_ctx_law(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - unsigned short *table = (unsigned short *) - (sound.soft.format == AFMT_MU_LAW ? ulaw2dma16: alaw2dma16); - unsigned int data = sound.data; - unsigned int *p = (unsigned int *) &frame[*frameUsed]; - int bal = sound.bal; - int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - int utotal, ftotal; - int stereo = sound.soft.stereo; - - frameLeft >>= 2; - if (stereo) - userCount >>= 1; - ftotal = frameLeft; - utotal = userCount; - while (frameLeft) { - u_char c; - if (bal < 0) { - if (userCount == 0) - break; - if (get_user(c, userPtr++)) - return -EFAULT; - data = table[c]; - if (stereo) { - if (get_user(c, userPtr++)) - return -EFAULT; - data = (data << 16) + table[c]; - } else - data = (data << 16) + data; - userCount--; - bal += hSpeed; - } - *p++ = data; - frameLeft--; - bal -= sSpeed; - } - sound.bal = bal; - sound.data = data; - *frameUsed += (ftotal - frameLeft) * 4; - utotal -= userCount; - return stereo? utotal * 2: utotal; -} - - -static ssize_t pmac_ctx_s8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - unsigned int *p = (unsigned int *) &frame[*frameUsed]; - unsigned int data = sound.data; - int bal = sound.bal; - int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - int stereo = sound.soft.stereo; - int utotal, ftotal; - - frameLeft >>= 2; - if (stereo) - userCount >>= 1; - ftotal = frameLeft; - utotal = userCount; - while (frameLeft) { - u_char c; - if (bal < 0) { - if (userCount == 0) - break; - if (get_user(c, userPtr++)) - return -EFAULT; - data = c << 8; - if (stereo) { - if (get_user(c, userPtr++)) - return -EFAULT; - data = (data << 16) + (c << 8); - } else - data = (data << 16) + data; - userCount--; - bal += hSpeed; - } - *p++ = data; - frameLeft--; - bal -= sSpeed; - } - sound.bal = bal; - sound.data = data; - *frameUsed += (ftotal - frameLeft) * 4; - utotal -= userCount; - return stereo? utotal * 2: utotal; -} - - -static ssize_t pmac_ctx_u8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - unsigned int *p = (unsigned int *) &frame[*frameUsed]; - unsigned int data = sound.data; - int bal = sound.bal; - int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - int stereo = sound.soft.stereo; - int utotal, ftotal; - - frameLeft >>= 2; - if (stereo) - userCount >>= 1; - ftotal = frameLeft; - utotal = userCount; - while (frameLeft) { - u_char c; - if (bal < 0) { - if (userCount == 0) - break; - if (get_user(c, userPtr++)) - return -EFAULT; - data = (c ^ 0x80) << 8; - if (stereo) { - if (get_user(c, userPtr++)) - return -EFAULT; - data = (data << 16) + ((c ^ 0x80) << 8); - } else - data = (data << 16) + data; - userCount--; - bal += hSpeed; - } - *p++ = data; - frameLeft--; - bal -= sSpeed; - } - sound.bal = bal; - sound.data = data; - *frameUsed += (ftotal - frameLeft) * 4; - utotal -= userCount; - return stereo? utotal * 2: utotal; -} - - -static ssize_t pmac_ctx_s16(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - unsigned int *p = (unsigned int *) &frame[*frameUsed]; - unsigned int data = sound.data; - unsigned short *up = (unsigned short *) userPtr; - int bal = sound.bal; - int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - int stereo = sound.soft.stereo; - int utotal, ftotal; - - frameLeft >>= 2; - userCount >>= (stereo? 2: 1); - ftotal = frameLeft; - utotal = userCount; - while (frameLeft) { - unsigned short c; - if (bal < 0) { - if (userCount == 0) - break; - if (get_user(data, up++)) - return -EFAULT; - if (stereo) { - if (get_user(c, up++)) - return -EFAULT; - data = (data << 16) + c; - } else - data = (data << 16) + data; - userCount--; - bal += hSpeed; - } - *p++ = data; - frameLeft--; - bal -= sSpeed; - } - sound.bal = bal; - sound.data = data; - *frameUsed += (ftotal - frameLeft) * 4; - utotal -= userCount; - return stereo? utotal * 4: utotal * 2; -} - - -static ssize_t pmac_ctx_u16(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - int mask = (sound.soft.format == AFMT_U16_LE? 0x0080: 0x8000); - unsigned int *p = (unsigned int *) &frame[*frameUsed]; - unsigned int data = sound.data; - unsigned short *up = (unsigned short *) userPtr; - int bal = sound.bal; - int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - int stereo = sound.soft.stereo; - int utotal, ftotal; - - frameLeft >>= 2; - userCount >>= (stereo? 2: 1); - ftotal = frameLeft; - utotal = userCount; - while (frameLeft) { - unsigned short c; - if (bal < 0) { - if (userCount == 0) - break; - if (get_user(data, up++)) - return -EFAULT; - data ^= mask; - if (stereo) { - if (get_user(c, up++)) - return -EFAULT; - data = (data << 16) + (c ^ mask); - } else - data = (data << 16) + data; - userCount--; - bal += hSpeed; - } - *p++ = data; - frameLeft--; - bal -= sSpeed; - } - sound.bal = bal; - sound.data = data; - *frameUsed += (ftotal - frameLeft) * 4; - utotal -= userCount; - return stereo? utotal * 4: utotal * 2; -} - -static ssize_t pmac_ct_s8_read(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - short *p = (short *) &frame[*frameUsed]; - int val, stereo = sound.soft.stereo; - - frameLeft >>= 2; - if (stereo) - userCount >>= 1; - used = count = min(userCount, frameLeft); - while (count > 0) { - u_char data; - - val = *p++; - data = val >> 8; - if (put_user(data, (u_char *)userPtr++)) - return -EFAULT; - if (stereo) { - val = *p; - data = val >> 8; - if (put_user(data, (u_char *)userPtr++)) - return -EFAULT; - } - p++; - count--; - } - *frameUsed += used * 4; - return stereo? used * 2: used; -} - - -static ssize_t pmac_ct_u8_read(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - short *p = (short *) &frame[*frameUsed]; - int val, stereo = sound.soft.stereo; - - frameLeft >>= 2; - if (stereo) - userCount >>= 1; - used = count = min(userCount, frameLeft); - while (count > 0) { - u_char data; - - val = *p++; - data = (val >> 8) ^ 0x80; - if (put_user(data, (u_char *)userPtr++)) - return -EFAULT; - if (stereo) { - val = *p; - data = (val >> 8) ^ 0x80; - if (put_user(data, (u_char *)userPtr++)) - return -EFAULT; - } - p++; - count--; - } - *frameUsed += used * 4; - return stereo? used * 2: used; -} - - -static ssize_t pmac_ct_s16_read(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - int stereo = sound.soft.stereo; - short *fp = (short *) &frame[*frameUsed]; - - frameLeft >>= 2; - userCount >>= (stereo? 2: 1); - used = count = min(userCount, frameLeft); - if (!stereo) { - short *up = (short *) userPtr; - while (count > 0) { - short data; - data = *fp; - if (put_user(data, up++)) - return -EFAULT; - fp+=2; - count--; - } - } else { - if (copy_to_user((u_char *)userPtr, fp, count * 4)) - return -EFAULT; - } - *frameUsed += used * 4; - return stereo? used * 4: used * 2; -} - -static ssize_t pmac_ct_u16_read(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - int mask = (sound.soft.format == AFMT_U16_LE? 0x0080: 0x8000); - int stereo = sound.soft.stereo; - short *fp = (short *) &frame[*frameUsed]; - short *up = (short *) userPtr; - - frameLeft >>= 2; - userCount >>= (stereo? 2: 1); - used = count = min(userCount, frameLeft); - while (count > 0) { - int data; - - data = *fp++; - data ^= mask; - if (put_user(data, up++)) - return -EFAULT; - if (stereo) { - data = *fp; - data ^= mask; - if (put_user(data, up++)) - return -EFAULT; - } - fp++; - count--; - } - *frameUsed += used * 4; - return stereo? used * 4: used * 2; -} - - -#endif /* CONFIG_PPC */ - - -#ifdef CONFIG_ATARI -static TRANS transTTNormal = { - ata_ct_law, ata_ct_law, ata_ct_s8, ata_ct_u8, NULL, NULL, NULL, NULL -}; - -static TRANS transTTExpanding = { - ata_ctx_law, ata_ctx_law, ata_ctx_s8, ata_ctx_u8, NULL, NULL, NULL, NULL -}; - -static TRANS transFalconNormal = { - ata_ct_law, ata_ct_law, ata_ct_s8, ata_ct_u8, - ata_ct_s16be, ata_ct_u16be, ata_ct_s16le, ata_ct_u16le -}; - -static TRANS transFalconExpanding = { - ata_ctx_law, ata_ctx_law, ata_ctx_s8, ata_ctx_u8, - ata_ctx_s16be, ata_ctx_u16be, ata_ctx_s16le, ata_ctx_u16le -}; -#endif /* CONFIG_ATARI */ - -#ifdef CONFIG_AMIGA -static TRANS transAmiga = { - ami_ct_law, ami_ct_law, ami_ct_s8, ami_ct_u8, - ami_ct_s16be, ami_ct_u16be, ami_ct_s16le, ami_ct_u16le -}; -#endif /* CONFIG_AMIGA */ - -#ifdef CONFIG_PPC -static TRANS transAwacsNormal = { - pmac_ct_law, pmac_ct_law, pmac_ct_s8, pmac_ct_u8, - pmac_ct_s16, pmac_ct_u16, pmac_ct_s16, pmac_ct_u16 -}; - -static TRANS transAwacsExpand = { - pmac_ctx_law, pmac_ctx_law, pmac_ctx_s8, pmac_ctx_u8, - pmac_ctx_s16, pmac_ctx_u16, pmac_ctx_s16, pmac_ctx_u16 -}; - -static TRANS transAwacsNormalRead = { - NULL, NULL, pmac_ct_s8_read, pmac_ct_u8_read, - pmac_ct_s16_read, pmac_ct_u16_read, pmac_ct_s16_read, pmac_ct_u16_read -}; -#endif /* CONFIG_PPC */ - -/*** Low level stuff *********************************************************/ - - -#ifdef CONFIG_ATARI - -/* - * Atari (TT/Falcon) - */ - -static void *AtaAlloc(unsigned int size, int flags) -{ - return( atari_stram_alloc( size, NULL, "dmasound" )); -} - -static void AtaFree(void *obj, unsigned int size) -{ - atari_stram_free( obj ); -} - -static int __init AtaIrqInit(void) -{ - /* Set up timer A. Timer A - will receive a signal upon end of playing from the sound - hardware. Furthermore Timer A is able to count events - and will cause an interrupt after a programmed number - of events. So all we need to keep the music playing is - to provide the sound hardware with new data upon - an interrupt from timer A. */ - mfp.tim_ct_a = 0; /* ++roman: Stop timer before programming! */ - mfp.tim_dt_a = 1; /* Cause interrupt after first event. */ - mfp.tim_ct_a = 8; /* Turn on event counting. */ - /* Register interrupt handler. */ - request_irq(IRQ_MFP_TIMA, ata_sq_interrupt, IRQ_TYPE_SLOW, - "DMA sound", ata_sq_interrupt); - mfp.int_en_a |= 0x20; /* Turn interrupt on. */ - mfp.int_mk_a |= 0x20; - return(1); -} - -#ifdef MODULE -static void AtaIrqCleanUp(void) -{ - mfp.tim_ct_a = 0; /* stop timer */ - mfp.int_en_a &= ~0x20; /* turn interrupt off */ - free_irq(IRQ_MFP_TIMA, ata_sq_interrupt); -} -#endif /* MODULE */ - - -#define TONE_VOXWARE_TO_DB(v) \ - (((v) < 0) ? -12 : ((v) > 100) ? 12 : ((v) - 50) * 6 / 25) -#define TONE_DB_TO_VOXWARE(v) (((v) * 25 + ((v) > 0 ? 5 : -5)) / 6 + 50) - - -static int AtaSetBass(int bass) -{ - sound.bass = TONE_VOXWARE_TO_DB(bass); - atari_microwire_cmd(MW_LM1992_BASS(sound.bass)); - return(TONE_DB_TO_VOXWARE(sound.bass)); -} - - -static int AtaSetTreble(int treble) -{ - sound.treble = TONE_VOXWARE_TO_DB(treble); - atari_microwire_cmd(MW_LM1992_TREBLE(sound.treble)); - return(TONE_DB_TO_VOXWARE(sound.treble)); -} - - - -/* - * TT - */ - - -static void TTSilence(void) -{ - tt_dmasnd.ctrl = DMASND_CTRL_OFF; - atari_microwire_cmd(MW_LM1992_PSG_HIGH); /* mix in PSG signal 1:1 */ -} - - -static void TTInit(void) -{ - int mode, i, idx; - const int freq[4] = {50066, 25033, 12517, 6258}; - - /* search a frequency that fits into the allowed error range */ - - idx = -1; - for (i = 0; i < arraysize(freq); i++) - /* this isn't as much useful for a TT than for a Falcon, but - * then it doesn't hurt very much to implement it for a TT too. - */ - if ((100 * abs(sound.soft.speed - freq[i]) / freq[i]) < catchRadius) - idx = i; - if (idx > -1) { - sound.soft.speed = freq[idx]; - sound.trans = &transTTNormal; - } else - sound.trans = &transTTExpanding; - - TTSilence(); - sound.hard = sound.soft; - - if (sound.hard.speed > 50066) { - /* we would need to squeeze the sound, but we won't do that */ - sound.hard.speed = 50066; - mode = DMASND_MODE_50KHZ; - sound.trans = &transTTNormal; - } else if (sound.hard.speed > 25033) { - sound.hard.speed = 50066; - mode = DMASND_MODE_50KHZ; - } else if (sound.hard.speed > 12517) { - sound.hard.speed = 25033; - mode = DMASND_MODE_25KHZ; - } else if (sound.hard.speed > 6258) { - sound.hard.speed = 12517; - mode = DMASND_MODE_12KHZ; - } else { - sound.hard.speed = 6258; - mode = DMASND_MODE_6KHZ; - } - - tt_dmasnd.mode = (sound.hard.stereo ? - DMASND_MODE_STEREO : DMASND_MODE_MONO) | - DMASND_MODE_8BIT | mode; - - sound.bal = -sound.soft.speed; -} - - -static int TTSetFormat(int format) -{ - /* TT sound DMA supports only 8bit modes */ - - switch (format) { - case AFMT_QUERY: - return(sound.soft.format); - case AFMT_MU_LAW: - case AFMT_A_LAW: - case AFMT_S8: - case AFMT_U8: - break; - default: - format = AFMT_S8; - } - - sound.soft.format = format; - sound.soft.size = 8; - if (sound.minDev == SND_DEV_DSP) { - sound.dsp.format = format; - sound.dsp.size = 8; - } - TTInit(); - - return(format); -} - - -#define VOLUME_VOXWARE_TO_DB(v) \ - (((v) < 0) ? -40 : ((v) > 100) ? 0 : ((v) * 2) / 5 - 40) -#define VOLUME_DB_TO_VOXWARE(v) ((((v) + 40) * 5 + 1) / 2) - - -static int TTSetVolume(int volume) -{ - sound.volume_left = VOLUME_VOXWARE_TO_DB(volume & 0xff); - atari_microwire_cmd(MW_LM1992_BALLEFT(sound.volume_left)); - sound.volume_right = VOLUME_VOXWARE_TO_DB((volume & 0xff00) >> 8); - atari_microwire_cmd(MW_LM1992_BALRIGHT(sound.volume_right)); - return(VOLUME_DB_TO_VOXWARE(sound.volume_left) | - (VOLUME_DB_TO_VOXWARE(sound.volume_right) << 8)); -} - - -#define GAIN_VOXWARE_TO_DB(v) \ - (((v) < 0) ? -80 : ((v) > 100) ? 0 : ((v) * 4) / 5 - 80) -#define GAIN_DB_TO_VOXWARE(v) ((((v) + 80) * 5 + 1) / 4) - -static int TTSetGain(int gain) -{ - sound.gain = GAIN_VOXWARE_TO_DB(gain); - atari_microwire_cmd(MW_LM1992_VOLUME(sound.gain)); - return GAIN_DB_TO_VOXWARE(sound.gain); -} - - - -/* - * Falcon - */ - - -static void FalconSilence(void) -{ - /* stop playback, set sample rate 50kHz for PSG sound */ - tt_dmasnd.ctrl = DMASND_CTRL_OFF; - tt_dmasnd.mode = DMASND_MODE_50KHZ | DMASND_MODE_STEREO | DMASND_MODE_8BIT; - tt_dmasnd.int_div = 0; /* STE compatible divider */ - tt_dmasnd.int_ctrl = 0x0; - tt_dmasnd.cbar_src = 0x0000; /* no matrix inputs */ - tt_dmasnd.cbar_dst = 0x0000; /* no matrix outputs */ - tt_dmasnd.dac_src = 1; /* connect ADC to DAC, disconnect matrix */ - tt_dmasnd.adc_src = 3; /* ADC Input = PSG */ -} - - -static void FalconInit(void) -{ - int divider, i, idx; - const int freq[8] = {49170, 32780, 24585, 19668, 16390, 12292, 9834, 8195}; - - /* search a frequency that fits into the allowed error range */ - - idx = -1; - for (i = 0; i < arraysize(freq); i++) - /* if we will tolerate 3% error 8000Hz->8195Hz (2.38%) would - * be playable without expanding, but that now a kernel runtime - * option - */ - if ((100 * abs(sound.soft.speed - freq[i]) / freq[i]) < catchRadius) - idx = i; - if (idx > -1) { - sound.soft.speed = freq[idx]; - sound.trans = &transFalconNormal; - } else - sound.trans = &transFalconExpanding; - - FalconSilence(); - sound.hard = sound.soft; - - if (sound.hard.size == 16) { - /* the Falcon can play 16bit samples only in stereo */ - sound.hard.stereo = 1; - } - - if (sound.hard.speed > 49170) { - /* we would need to squeeze the sound, but we won't do that */ - sound.hard.speed = 49170; - divider = 1; - sound.trans = &transFalconNormal; - } else if (sound.hard.speed > 32780) { - sound.hard.speed = 49170; - divider = 1; - } else if (sound.hard.speed > 24585) { - sound.hard.speed = 32780; - divider = 2; - } else if (sound.hard.speed > 19668) { - sound.hard.speed = 24585; - divider = 3; - } else if (sound.hard.speed > 16390) { - sound.hard.speed = 19668; - divider = 4; - } else if (sound.hard.speed > 12292) { - sound.hard.speed = 16390; - divider = 5; - } else if (sound.hard.speed > 9834) { - sound.hard.speed = 12292; - divider = 7; - } else if (sound.hard.speed > 8195) { - sound.hard.speed = 9834; - divider = 9; - } else { - sound.hard.speed = 8195; - divider = 11; - } - tt_dmasnd.int_div = divider; - - /* Setup Falcon sound DMA for playback */ - tt_dmasnd.int_ctrl = 0x4; /* Timer A int at play end */ - tt_dmasnd.track_select = 0x0; /* play 1 track, track 1 */ - tt_dmasnd.cbar_src = 0x0001; /* DMA(25MHz) --> DAC */ - tt_dmasnd.cbar_dst = 0x0000; - tt_dmasnd.rec_track_select = 0; - tt_dmasnd.dac_src = 2; /* connect matrix to DAC */ - tt_dmasnd.adc_src = 0; /* ADC Input = Mic */ - - tt_dmasnd.mode = (sound.hard.stereo ? - DMASND_MODE_STEREO : DMASND_MODE_MONO) | - ((sound.hard.size == 8) ? - DMASND_MODE_8BIT : DMASND_MODE_16BIT) | - DMASND_MODE_6KHZ; - - sound.bal = -sound.soft.speed; -} - - -static int FalconSetFormat(int format) -{ - int size; - /* Falcon sound DMA supports 8bit and 16bit modes */ - - switch (format) { - case AFMT_QUERY: - return(sound.soft.format); - case AFMT_MU_LAW: - case AFMT_A_LAW: - case AFMT_U8: - case AFMT_S8: - size = 8; - break; - case AFMT_S16_BE: - case AFMT_U16_BE: - case AFMT_S16_LE: - case AFMT_U16_LE: - size = 16; - break; - default: /* :-) */ - size = 8; - format = AFMT_S8; - } - - sound.soft.format = format; - sound.soft.size = size; - if (sound.minDev == SND_DEV_DSP) { - sound.dsp.format = format; - sound.dsp.size = sound.soft.size; - } - - FalconInit(); - - return(format); -} - - -/* This is for the Falcon output *attenuation* in 1.5dB steps, - * i.e. output level from 0 to -22.5dB in -1.5dB steps. - */ -#define VOLUME_VOXWARE_TO_ATT(v) \ - ((v) < 0 ? 15 : (v) > 100 ? 0 : 15 - (v) * 3 / 20) -#define VOLUME_ATT_TO_VOXWARE(v) (100 - (v) * 20 / 3) - - -static int FalconSetVolume(int volume) -{ - sound.volume_left = VOLUME_VOXWARE_TO_ATT(volume & 0xff); - sound.volume_right = VOLUME_VOXWARE_TO_ATT((volume & 0xff00) >> 8); - tt_dmasnd.output_atten = sound.volume_left << 8 | sound.volume_right << 4; - return(VOLUME_ATT_TO_VOXWARE(sound.volume_left) | - VOLUME_ATT_TO_VOXWARE(sound.volume_right) << 8); -} - - -static void ata_sq_play_next_frame(int index) -{ - char *start, *end; - - /* used by AtaPlay() if all doubts whether there really is something - * to be played are already wiped out. - */ - start = sq_block_address(sq.front); - end = start+((sq.count == index) ? sq.rear_size : sq.block_size); - /* end might not be a legal virtual address. */ - DMASNDSetEnd(virt_to_phys(end - 1) + 1); - DMASNDSetBase(virt_to_phys(start)); - /* Since only an even number of samples per frame can - be played, we might lose one byte here. (TO DO) */ - sq.front = (sq.front+1) % sq.max_count; - sq.active++; - tt_dmasnd.ctrl = DMASND_CTRL_ON | DMASND_CTRL_REPEAT; -} - - -static void AtaPlay(void) -{ - /* ++TeSche: Note that sq.active is no longer just a flag but holds - * the number of frames the DMA is currently programmed for instead, - * may be 0, 1 (currently being played) or 2 (pre-programmed). - * - * Changes done to sq.count and sq.active are a bit more subtle again - * so now I must admit I also prefer disabling the irq here rather - * than considering all possible situations. But the point is that - * disabling the irq doesn't have any bad influence on this version of - * the driver as we benefit from having pre-programmed the DMA - * wherever possible: There's no need to reload the DMA at the exact - * time of an interrupt but only at some time while the pre-programmed - * frame is playing! - */ - atari_disable_irq(IRQ_MFP_TIMA); - - if (sq.active == 2 || /* DMA is 'full' */ - sq.count <= 0) { /* nothing to do */ - atari_enable_irq(IRQ_MFP_TIMA); - return; - } - - if (sq.active == 0) { - /* looks like there's nothing 'in' the DMA yet, so try - * to put two frames into it (at least one is available). - */ - if (sq.count == 1 && sq.rear_size < sq.block_size && !sq.syncing) { - /* hmmm, the only existing frame is not - * yet filled and we're not syncing? - */ - atari_enable_irq(IRQ_MFP_TIMA); - return; - } - ata_sq_play_next_frame(1); - if (sq.count == 1) { - /* no more frames */ - atari_enable_irq(IRQ_MFP_TIMA); - return; - } - if (sq.count == 2 && sq.rear_size < sq.block_size && !sq.syncing) { - /* hmmm, there were two frames, but the second - * one is not yet filled and we're not syncing? - */ - atari_enable_irq(IRQ_MFP_TIMA); - return; - } - ata_sq_play_next_frame(2); - } else { - /* there's already a frame being played so we may only stuff - * one new into the DMA, but even if this may be the last - * frame existing the previous one is still on sq.count. - */ - if (sq.count == 2 && sq.rear_size < sq.block_size && !sq.syncing) { - /* hmmm, the only existing frame is not - * yet filled and we're not syncing? - */ - atari_enable_irq(IRQ_MFP_TIMA); - return; - } - ata_sq_play_next_frame(2); - } - atari_enable_irq(IRQ_MFP_TIMA); -} - - -static void ata_sq_interrupt(int irq, void *dummy, struct pt_regs *fp) -{ -#if 0 - /* ++TeSche: if you should want to test this... */ - static int cnt = 0; - if (sq.active == 2) - if (++cnt == 10) { - /* simulate losing an interrupt */ - cnt = 0; - return; - } -#endif - - if (sq.ignore_int && (sound.mach.type == DMASND_FALCON)) { - /* ++TeSche: Falcon only: ignore first irq because it comes - * immediately after starting a frame. after that, irqs come - * (almost) like on the TT. - */ - sq.ignore_int = 0; - return; - } - - if (!sq.active) { - /* playing was interrupted and sq_reset() has already cleared - * the sq variables, so better don't do anything here. - */ - WAKE_UP(sq.sync_queue); - return; - } - - /* Probably ;) one frame is finished. Well, in fact it may be that a - * pre-programmed one is also finished because there has been a long - * delay in interrupt delivery and we've completely lost one, but - * there's no way to detect such a situation. In such a case the last - * frame will be played more than once and the situation will recover - * as soon as the irq gets through. - */ - sq.count--; - sq.active--; - - if (!sq.active) { - tt_dmasnd.ctrl = DMASND_CTRL_OFF; - sq.ignore_int = 1; - } - - WAKE_UP(sq.action_queue); - /* At least one block of the queue is free now - so wake up a writing process blocked because - of a full queue. */ - - if ((sq.active != 1) || (sq.count != 1)) - /* We must be a bit carefully here: sq.count indicates the - * number of buffers used and not the number of frames to - * be played. If sq.count==1 and sq.active==1 that means - * the only remaining frame was already programmed earlier - * (and is currently running) so we mustn't call AtaPlay() - * here, otherwise we'll play one frame too much. - */ - AtaPlay(); - - if (!sq.active) WAKE_UP(sq.sync_queue); - /* We are not playing after AtaPlay(), so there - is nothing to play any more. Wake up a process - waiting for audio output to drain. */ -} -#endif /* CONFIG_ATARI */ - - -#ifdef CONFIG_AMIGA - -/* - * Amiga - */ - -#define StopDMA() custom.aud[0].audvol = custom.aud[1].audvol = 0; \ - custom.aud[2].audvol = custom.aud[3].audvol = 0; \ - custom.dmacon = AMI_AUDIO_OFF; - -static void *AmiAlloc(unsigned int size, int flags) -{ - return amiga_chip_alloc((long)size, "dmasound"); -} - -static void AmiFree(void *obj, unsigned int size) -{ - amiga_chip_free (obj); -} - -static int __init AmiIrqInit(void) -{ - /* turn off DMA for audio channels */ - StopDMA(); - - /* Register interrupt handler. */ - if (request_irq(IRQ_AMIGA_AUD0, ami_sq_interrupt, 0, - "DMA sound", ami_sq_interrupt)) - return(0); - return(1); -} - -#ifdef MODULE -static void AmiIrqCleanUp(void) -{ - /* turn off DMA for audio channels */ - StopDMA(); - /* release the interrupt */ - free_irq(IRQ_AMIGA_AUD0, ami_sq_interrupt); -} -#endif /* MODULE */ - -static void AmiSilence(void) -{ - /* turn off DMA for audio channels */ - StopDMA(); -} - - -static void AmiInit(void) -{ - int period, i; - - AmiSilence(); - - if (sound.soft.speed) - period = amiga_colorclock/sound.soft.speed-1; - else - period = amiga_audio_min_period; - sound.hard = sound.soft; - sound.trans = &transAmiga; - - if (period < amiga_audio_min_period) { - /* we would need to squeeze the sound, but we won't do that */ - period = amiga_audio_min_period; - } else if (period > 65535) { - period = 65535; - } - sound.hard.speed = amiga_colorclock/(period+1); - - for (i = 0; i < 4; i++) - custom.aud[i].audper = period; - amiga_audio_period = period; - - AmiSetTreble(50); /* recommended for newer amiga models */ -} - - -static int AmiSetFormat(int format) -{ - int size; - - /* Amiga sound DMA supports 8bit and 16bit (pseudo 14 bit) modes */ - - switch (format) { - case AFMT_QUERY: - return(sound.soft.format); - case AFMT_MU_LAW: - case AFMT_A_LAW: - case AFMT_U8: - case AFMT_S8: - size = 8; - break; - case AFMT_S16_BE: - case AFMT_U16_BE: - case AFMT_S16_LE: - case AFMT_U16_LE: - size = 16; - break; - default: /* :-) */ - size = 8; - format = AFMT_S8; - } - - sound.soft.format = format; - sound.soft.size = size; - if (sound.minDev == SND_DEV_DSP) { - sound.dsp.format = format; - sound.dsp.size = sound.soft.size; - } - AmiInit(); - - return(format); -} - - -#define VOLUME_VOXWARE_TO_AMI(v) \ - (((v) < 0) ? 0 : ((v) > 100) ? 64 : ((v) * 64)/100) -#define VOLUME_AMI_TO_VOXWARE(v) ((v)*100/64) - -static int AmiSetVolume(int volume) -{ - sound.volume_left = VOLUME_VOXWARE_TO_AMI(volume & 0xff); - custom.aud[0].audvol = sound.volume_left; - sound.volume_right = VOLUME_VOXWARE_TO_AMI((volume & 0xff00) >> 8); - custom.aud[1].audvol = sound.volume_right; - if (sound.hard.size == 16) { - if (sound.volume_left == 64 && sound.volume_right == 64) { - custom.aud[2].audvol = 1; - custom.aud[3].audvol = 1; - } else { - custom.aud[2].audvol = 0; - custom.aud[3].audvol = 0; - } - } - return(VOLUME_AMI_TO_VOXWARE(sound.volume_left) | - (VOLUME_AMI_TO_VOXWARE(sound.volume_right) << 8)); -} - -static int AmiSetTreble(int treble) -{ - sound.treble = treble; - if (treble < 50) - ciaa.pra &= ~0x02; - else - ciaa.pra |= 0x02; - return(treble); -} - - -#define AMI_PLAY_LOADED 1 -#define AMI_PLAY_PLAYING 2 -#define AMI_PLAY_MASK 3 - - -static void ami_sq_play_next_frame(int index) -{ - u_char *start, *ch0, *ch1, *ch2, *ch3; - u_long size; - - /* used by AmiPlay() if all doubts whether there really is something - * to be played are already wiped out. - */ - start = sq_block_address(sq.front); - size = (sq.count == index ? sq.rear_size : sq.block_size)>>1; - - if (sound.hard.stereo) { - ch0 = start; - ch1 = start+sq.block_size_half; - size >>= 1; - } else { - ch0 = start; - ch1 = start; - } - - custom.aud[0].audvol = sound.volume_left; - custom.aud[1].audvol = sound.volume_right; - if (sound.hard.size == 8) { - custom.aud[0].audlc = (u_short *)ZTWO_PADDR(ch0); - custom.aud[0].audlen = size; - custom.aud[1].audlc = (u_short *)ZTWO_PADDR(ch1); - custom.aud[1].audlen = size; - custom.dmacon = AMI_AUDIO_8; - } else { - size >>= 1; - custom.aud[0].audlc = (u_short *)ZTWO_PADDR(ch0); - custom.aud[0].audlen = size; - custom.aud[1].audlc = (u_short *)ZTWO_PADDR(ch1); - custom.aud[1].audlen = size; - if (sound.volume_left == 64 && sound.volume_right == 64) { - /* We can play pseudo 14-bit only with the maximum volume */ - ch3 = ch0+sq.block_size_quarter; - ch2 = ch1+sq.block_size_quarter; - custom.aud[2].audvol = 1; /* we are being affected by the beeps */ - custom.aud[3].audvol = 1; /* restoring volume here helps a bit */ - custom.aud[2].audlc = (u_short *)ZTWO_PADDR(ch2); - custom.aud[2].audlen = size; - custom.aud[3].audlc = (u_short *)ZTWO_PADDR(ch3); - custom.aud[3].audlen = size; - custom.dmacon = AMI_AUDIO_14; - } else { - custom.aud[2].audvol = 0; - custom.aud[3].audvol = 0; - custom.dmacon = AMI_AUDIO_8; - } - } - sq.front = (sq.front+1) % sq.max_count; - sq.active |= AMI_PLAY_LOADED; -} - - -static void AmiPlay(void) -{ - int minframes = 1; - - custom.intena = IF_AUD0; - - if (sq.active & AMI_PLAY_LOADED) { - /* There's already a frame loaded */ - custom.intena = IF_SETCLR | IF_AUD0; - return; - } - - if (sq.active & AMI_PLAY_PLAYING) - /* Increase threshold: frame 1 is already being played */ - minframes = 2; - - if (sq.count < minframes) { - /* Nothing to do */ - custom.intena = IF_SETCLR | IF_AUD0; - return; - } - - if (sq.count <= minframes && sq.rear_size < sq.block_size && !sq.syncing) { - /* hmmm, the only existing frame is not - * yet filled and we're not syncing? - */ - custom.intena = IF_SETCLR | IF_AUD0; - return; - } - - ami_sq_play_next_frame(minframes); - - custom.intena = IF_SETCLR | IF_AUD0; -} - - -static void ami_sq_interrupt(int irq, void *dummy, struct pt_regs *fp) -{ - int minframes = 1; - - custom.intena = IF_AUD0; - - if (!sq.active) { - /* Playing was interrupted and sq_reset() has already cleared - * the sq variables, so better don't do anything here. - */ - WAKE_UP(sq.sync_queue); - return; - } - - if (sq.active & AMI_PLAY_PLAYING) { - /* We've just finished a frame */ - sq.count--; - WAKE_UP(sq.action_queue); - } - - if (sq.active & AMI_PLAY_LOADED) - /* Increase threshold: frame 1 is already being played */ - minframes = 2; - - /* Shift the flags */ - sq.active = (sq.active<<1) & AMI_PLAY_MASK; - - if (!sq.active) - /* No frame is playing, disable audio DMA */ - StopDMA(); - - custom.intena = IF_SETCLR | IF_AUD0; - - if (sq.count >= minframes) - /* Try to play the next frame */ - AmiPlay(); - - if (!sq.active) - /* Nothing to play anymore. - Wake up a process waiting for audio output to drain. */ - WAKE_UP(sq.sync_queue); -} -#endif /* CONFIG_AMIGA */ - -#ifdef CONFIG_PPC - -/* - * PCI PowerMac, with AWACS and DBDMA. - */ - -static void *PMacAlloc(unsigned int size, int flags) -{ - return kmalloc(size, flags); -} - -static void PMacFree(void *ptr, unsigned int size) -{ - kfree(ptr); -} - -static int __init PMacIrqInit(void) -{ - if (request_irq(awacs_irq, pmac_awacs_intr, 0, "AWACS", 0) - || request_irq(awacs_tx_irq, pmac_awacs_tx_intr, 0, "AWACS out", 0) - || request_irq(awacs_rx_irq, pmac_awacs_rx_intr, 0, "AWACS in", 0)) - return 0; - return 1; -} - -#ifdef MODULE -static void PMacIrqCleanup(void) -{ - /* turn off output dma */ - out_le32(&awacs_txdma->control, RUN<<16); - /* disable interrupts from awacs interface */ - out_le32(&awacs->control, in_le32(&awacs->control) & 0xfff); -#ifdef CONFIG_PMAC_PBOOK - if (is_pbook_G3) { - feature_clear(awacs_node, FEATURE_Sound_power); - feature_clear(awacs_node, FEATURE_Sound_CLK_enable); - } -#endif - free_irq(awacs_irq, 0); - free_irq(awacs_tx_irq, 0); - free_irq(awacs_rx_irq, 0); - kfree(awacs_tx_cmd_space); - if (awacs_rx_cmd_space) - kfree(awacs_rx_cmd_space); - if (beep_buf) - kfree(beep_buf); - kd_mksound = orig_mksound; -#ifdef CONFIG_PMAC_PBOOK - pmu_unregister_sleep_notifier(&awacs_sleep_notifier); -#endif -} -#endif /* MODULE */ - -static void PMacSilence(void) -{ - /* turn off output dma */ - out_le32(&awacs_txdma->control, RUN<<16); -} - -static int awacs_freqs[8] = { - 44100, 29400, 22050, 17640, 14700, 11025, 8820, 7350 -}; -static int awacs_freqs_ok[8] = { 1, 1, 1, 1, 1, 1, 1, 1 }; - -static void PMacInit(void) -{ - int i, tolerance; - - switch (sound.soft.format) { - case AFMT_S16_LE: - case AFMT_U16_LE: - sound.hard.format = AFMT_S16_LE; - break; - default: - sound.hard.format = AFMT_S16_BE; - break; - } - sound.hard.stereo = 1; - sound.hard.size = 16; - - /* - * If we have a sample rate which is within catchRadius percent - * of the requested value, we don't have to expand the samples. - * Otherwise choose the next higher rate. - * N.B.: burgundy awacs (iMac and later) only works at 44100 Hz. - */ - i = 8; - do { - tolerance = catchRadius * awacs_freqs[--i] / 100; - if (awacs_freqs_ok[i] - && sound.soft.speed <= awacs_freqs[i] + tolerance) - break; - } while (i > 0); - if (sound.soft.speed >= awacs_freqs[i] - tolerance) - sound.trans = &transAwacsNormal; - else - sound.trans = &transAwacsExpand; - sound.read_trans = &transAwacsNormalRead; - sound.hard.speed = awacs_freqs[i]; - awacs_rate_index = i; - - /* XXX disable error interrupt on burgundy for now */ - out_le32(&awacs->control, MASK_IEPC | (i << 8) | 0x11 - | (awacs_revision < AWACS_BURGUNDY? MASK_IEE: 0)); - awacs_reg[1] = (awacs_reg[1] & ~MASK_SAMPLERATE) | (i << 3); - awacs_write(awacs_reg[1] | MASK_ADDR1); - out_le32(&awacs->byteswap, sound.hard.format != AFMT_S16_BE); - - /* We really want to execute a DMA stop command, after the AWACS - * is initialized. - * For reasons I don't understand, it stops the hissing noise - * common to many PowerBook G3 systems (like mine :-). - */ - out_le32(&awacs_txdma->control, (RUN|WAKE|FLUSH|PAUSE) << 16); - st_le16(&beep_dbdma_cmd->command, DBDMA_STOP); - out_le32(&awacs_txdma->cmdptr, virt_to_bus(beep_dbdma_cmd)); - out_le32(&awacs_txdma->control, RUN | (RUN << 16)); - - sound.bal = -sound.soft.speed; -} - -static int PMacSetFormat(int format) -{ - int size; - - switch (format) { - case AFMT_QUERY: - return sound.soft.format; - case AFMT_MU_LAW: - case AFMT_A_LAW: - case AFMT_U8: - case AFMT_S8: - size = 8; - break; - case AFMT_S16_BE: - case AFMT_U16_BE: - case AFMT_S16_LE: - case AFMT_U16_LE: - size = 16; - break; - default: /* :-) */ - printk(KERN_ERR "dmasound: unknown format 0x%x, using AFMT_U8\n", - format); - size = 8; - format = AFMT_U8; - } - - sound.soft.format = format; - sound.soft.size = size; - if (sound.minDev == SND_DEV_DSP) { - sound.dsp.format = format; - sound.dsp.size = size; - } - - PMacInit(); - - return format; -} - -#define AWACS_VOLUME_TO_MASK(x) (15 - ((((x) - 1) * 15) / 99)) -#define AWACS_MASK_TO_VOLUME(y) (100 - ((y) * 99 / 15)) - -static int awacs_get_volume(int reg, int lshift) -{ - int volume; - - volume = AWACS_MASK_TO_VOLUME((reg >> lshift) & 0xf); - volume |= AWACS_MASK_TO_VOLUME(reg & 0xf) << 8; - return volume; -} - -static int awacs_volume_setter(int volume, int n, int mute, int lshift) -{ - int r1, rn; - - if (mute && volume == 0) { - r1 = awacs_reg[1] | mute; - } else { - r1 = awacs_reg[1] & ~mute; - rn = awacs_reg[n] & ~(0xf | (0xf << lshift)); - rn |= ((AWACS_VOLUME_TO_MASK(volume & 0xff) & 0xf) << lshift); - rn |= AWACS_VOLUME_TO_MASK((volume >> 8) & 0xff) & 0xf; - awacs_reg[n] = rn; - awacs_write((n << 12) | rn); - volume = awacs_get_volume(rn, lshift); - } - if (r1 != awacs_reg[1]) { - awacs_reg[1] = r1; - awacs_write(r1 | MASK_ADDR1); - } - return volume; -} - -static int PMacSetVolume(int volume) -{ - return awacs_volume_setter(volume, 2, MASK_AMUTE, 6); -} - -static void PMacPlay(void) -{ - volatile struct dbdma_cmd *cp; - int i, count; - unsigned long flags; - - save_flags(flags); cli(); - if (awacs_beep_state) { - /* sound takes precedence over beeps */ - out_le32(&awacs_txdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16); - out_le32(&awacs->control, - (in_le32(&awacs->control) & ~0x1f00) - | (awacs_rate_index << 8)); - out_le32(&awacs->byteswap, sound.hard.format != AFMT_S16_BE); - out_le32(&awacs_txdma->cmdptr, virt_to_bus(&(awacs_tx_cmds[(sq.front+sq.active) % sq.max_count]))); - - beep_playing = 0; - awacs_beep_state = 0; - } - i = sq.front + sq.active; - if (i >= sq.max_count) - i -= sq.max_count; - while (sq.active < 2 && sq.active < sq.count) { - count = (sq.count == sq.active + 1)?sq.rear_size:sq.block_size; - if (count < sq.block_size && !sq.syncing) - /* last block not yet filled, and we're not syncing. */ - break; - cp = &awacs_tx_cmds[i]; - st_le16(&cp->req_count, count); - st_le16(&cp->xfer_status, 0); - if (++i >= sq.max_count) - i = 0; - out_le16(&awacs_tx_cmds[i].command, DBDMA_STOP); - out_le16(&cp->command, OUTPUT_MORE + INTR_ALWAYS); - if (sq.active == 0) - out_le32(&awacs_txdma->cmdptr, virt_to_bus(cp)); - out_le32(&awacs_txdma->control, ((RUN|WAKE) << 16) + (RUN|WAKE)); - ++sq.active; - } - restore_flags(flags); -} - - -static void PMacRecord(void) -{ - unsigned long flags; - - if (read_sq.active) - return; - - save_flags(flags); cli(); - - /* This is all we have to do......Just start it up. - */ - out_le32(&awacs_rxdma->control, ((RUN|WAKE) << 16) + (RUN|WAKE)); - read_sq.active = 1; - - restore_flags(flags); -} - - -static void -pmac_awacs_tx_intr(int irq, void *devid, struct pt_regs *regs) -{ - int i = sq.front; - int stat; - volatile struct dbdma_cmd *cp; - - while (sq.active > 0) { - cp = &awacs_tx_cmds[i]; - stat = ld_le16(&cp->xfer_status); - if ((stat & ACTIVE) == 0) - break; /* this frame is still going */ - --sq.count; - --sq.active; - if (++i >= sq.max_count) - i = 0; - } - if (i != sq.front) - WAKE_UP(sq.action_queue); - sq.front = i; - - PMacPlay(); - - if (!sq.active) - WAKE_UP(sq.sync_queue); -} - - -static void -pmac_awacs_rx_intr(int irq, void *devid, struct pt_regs *regs) -{ - - /* For some reason on my PowerBook G3, I get one interrupt - * when the interrupt vector is installed (like something is - * pending). This happens before the dbdma is initialize by - * us, so I just check the command pointer and if it is zero, - * just blow it off. - */ - if (in_le32(&awacs_rxdma->cmdptr) == 0) - return; - - /* We also want to blow 'em off when shutting down. - */ - if (read_sq.active == 0) - return; - - /* Check multiple buffers in case we were held off from - * interrupt processing for a long time. Geeze, I really hope - * this doesn't happen. - */ - while (awacs_rx_cmds[read_sq.rear].xfer_status) { - - /* Clear status and move on to next buffer. - */ - awacs_rx_cmds[read_sq.rear].xfer_status = 0; - read_sq.rear++; - - /* Wrap the buffer ring. - */ - if (read_sq.rear >= read_sq.max_active) - read_sq.rear = 0; - - /* If we have caught up to the front buffer, bump it. - * This will cause weird (but not fatal) results if the - * read loop is currently using this buffer. The user is - * behind in this case anyway, so weird things are going - * to happen. - */ - if (read_sq.rear == read_sq.front) { - read_sq.front++; - if (read_sq.front >= read_sq.max_active) - read_sq.front = 0; - } - } - - WAKE_UP(read_sq.action_queue); -} - - -static void -pmac_awacs_intr(int irq, void *devid, struct pt_regs *regs) -{ - int ctrl = in_le32(&awacs->control); - - if (ctrl & MASK_PORTCHG) { - /* do something when headphone is plugged/unplugged? */ - } - if (ctrl & MASK_CNTLERR) { - int err = (in_le32(&awacs->codec_stat) & MASK_ERRCODE) >> 16; - if (err != 0 && awacs_revision < AWACS_BURGUNDY) - printk(KERN_ERR "AWACS: error %x\n", err); - } - /* Writing 1s to the CNTLERR and PORTCHG bits clears them... */ - out_le32(&awacs->control, ctrl); -} - -static void -awacs_write(int val) -{ - if (awacs_revision >= AWACS_BURGUNDY) - return; - while (in_le32(&awacs->codec_ctrl) & MASK_NEWECMD) - ; /* XXX should have timeout */ - out_le32(&awacs->codec_ctrl, val | (awacs_subframe << 22)); -} - -static void awacs_nosound(unsigned long xx) -{ - unsigned long flags; - - save_flags(flags); cli(); - if (beep_playing) { - st_le16(&beep_dbdma_cmd->command, DBDMA_STOP); - out_le32(&awacs_txdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16); - out_le32(&awacs->control, - (in_le32(&awacs->control) & ~0x1f00) - | (awacs_rate_index << 8)); - out_le32(&awacs->byteswap, sound.hard.format != AFMT_S16_BE); - beep_playing = 0; - } - restore_flags(flags); -} - -static struct timer_list beep_timer = { - NULL, NULL, 0, 0, awacs_nosound -}; - -static void awacs_mksound(unsigned int hz, unsigned int ticks) -{ - unsigned long flags; - int beep_speed = 0; - int srate; - int period, ncycles, nsamples; - int i, j, f; - short *p; - static int beep_hz_cache; - static int beep_nsamples_cache; - static int beep_volume_cache; - - for (i = 0; i < 8 && awacs_freqs[i] >= BEEP_SRATE; ++i) - if (awacs_freqs_ok[i]) - beep_speed = i; - srate = awacs_freqs[beep_speed]; - - if (hz <= srate / BEEP_BUFLEN || hz > srate / 2) { -#if 1 - /* this is a hack for broken X server code */ - hz = 750; - ticks = 12; -#else - /* cancel beep currently playing */ - awacs_nosound(0); - return; -#endif - } - save_flags(flags); cli(); - del_timer(&beep_timer); - if (ticks) { - beep_timer.expires = jiffies + ticks; - add_timer(&beep_timer); - } - if (beep_playing || sq.active || beep_buf == NULL) { - restore_flags(flags); - return; /* too hard, sorry :-( */ - } - beep_playing = 1; - st_le16(&beep_dbdma_cmd->command, OUTPUT_MORE + BR_ALWAYS); - restore_flags(flags); - - if (hz == beep_hz_cache && beep_volume == beep_volume_cache) { - nsamples = beep_nsamples_cache; - } else { - period = srate * 256 / hz; /* fixed point */ - ncycles = BEEP_BUFLEN * 256 / period; - nsamples = (period * ncycles) >> 8; - f = ncycles * 65536 / nsamples; - j = 0; - p = beep_buf; - for (i = 0; i < nsamples; ++i, p += 2) { - p[0] = p[1] = beep_wform[j >> 8] * beep_volume; - j = (j + f) & 0xffff; - } - beep_hz_cache = hz; - beep_volume_cache = beep_volume; - beep_nsamples_cache = nsamples; - } - - st_le16(&beep_dbdma_cmd->req_count, nsamples*4); - st_le16(&beep_dbdma_cmd->xfer_status, 0); - st_le32(&beep_dbdma_cmd->cmd_dep, virt_to_bus(beep_dbdma_cmd)); - st_le32(&beep_dbdma_cmd->phy_addr, virt_to_bus(beep_buf)); - awacs_beep_state = 1; - - save_flags(flags); cli(); - if (beep_playing) { /* i.e. haven't been terminated already */ - out_le32(&awacs_txdma->control, (RUN|WAKE|FLUSH|PAUSE) << 16); - out_le32(&awacs->control, - (in_le32(&awacs->control) & ~0x1f00) - | (beep_speed << 8)); - out_le32(&awacs->byteswap, 0); - out_le32(&awacs_txdma->cmdptr, virt_to_bus(beep_dbdma_cmd)); - out_le32(&awacs_txdma->control, RUN | (RUN << 16)); - } - restore_flags(flags); -} - -#ifdef CONFIG_PMAC_PBOOK -/* - * Save state when going to sleep, restore it afterwards. - */ -static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when) -{ - switch (when) { - case PBOOK_SLEEP_NOW: - /* XXX we should stop any dma in progress when going to sleep - and restart it when we wake. */ - PMacSilence(); - disable_irq(awacs_irq); - disable_irq(awacs_tx_irq); - if (is_pbook_G3) { - feature_clear(awacs_node, FEATURE_Sound_CLK_enable); - feature_clear(awacs_node, FEATURE_Sound_power); - } - break; - case PBOOK_WAKE: - /* There is still a problem on wake. Sound seems to work fine - if I launch mpg123 and resumes fine if mpg123 was playing, - but the console beep is dead until I do something with the - mixer. Probably yet another timing issue */ - if (!feature_test(awacs_node, FEATURE_Sound_CLK_enable) - || !feature_test(awacs_node, FEATURE_Sound_power)) { - /* these aren't present on the 3400 AFAIK -- paulus */ - feature_set(awacs_node, FEATURE_Sound_CLK_enable); - feature_set(awacs_node, FEATURE_Sound_power); - mdelay(1000); - } - out_le32(&awacs->control, MASK_IEPC - | (awacs_rate_index << 8) | 0x11 - | (awacs_revision < AWACS_BURGUNDY? MASK_IEE: 0)); - awacs_write(awacs_reg[0] | MASK_ADDR0); - awacs_write(awacs_reg[1] | MASK_ADDR1); - awacs_write(awacs_reg[2] | MASK_ADDR2); - awacs_write(awacs_reg[4] | MASK_ADDR4); - out_le32(&awacs->byteswap, sound.hard.format != AFMT_S16_BE); - enable_irq(awacs_irq); - enable_irq(awacs_tx_irq); - if (awacs_revision == 3) { - mdelay(100); - awacs_write(0x6000); - mdelay(2); - awacs_write(awacs_reg[1] | MASK_ADDR1); - } - /* enable CD sound input */ - if (macio_base && is_pbook_G3) { - out_8(macio_base + 0x37, 3); - } else if (is_pbook_3400) { - feature_set(awacs_node, FEATURE_IOBUS_enable); - udelay(10); - in_8(latch_base + 0x190); - } - /* Resume pending sounds. */ - PMacPlay(); - } - return PBOOK_SLEEP_OK; -} -#endif /* CONFIG_PMAC_PBOOK */ - - -/* All the burgundy functions: */ - -/* Waits for busy flag to clear */ -inline static void -awacs_burgundy_busy_wait(void) -{ - while (in_le32(&awacs->codec_ctrl) & MASK_NEWECMD) - ; -} - -inline static void -awacs_burgundy_extend_wait(void) -{ - while (!(in_le32(&awacs->codec_stat) & MASK_EXTEND)) - ; - while (in_le32(&awacs->codec_stat) & MASK_EXTEND) - ; -} - -static void -awacs_burgundy_wcw(unsigned addr, unsigned val) -{ - out_le32(&awacs->codec_ctrl, addr + 0x200c00 + (val & 0xff)); - awacs_burgundy_busy_wait(); - out_le32(&awacs->codec_ctrl, addr + 0x200d00 +((val>>8) & 0xff)); - awacs_burgundy_busy_wait(); - out_le32(&awacs->codec_ctrl, addr + 0x200e00 +((val>>16) & 0xff)); - awacs_burgundy_busy_wait(); - out_le32(&awacs->codec_ctrl, addr + 0x200f00 +((val>>24) & 0xff)); - awacs_burgundy_busy_wait(); -} - -static unsigned -awacs_burgundy_rcw(unsigned addr) -{ - unsigned val = 0; - unsigned long flags; - - /* should have timeouts here */ - save_flags(flags); cli(); - - out_le32(&awacs->codec_ctrl, addr + 0x100000); - awacs_burgundy_busy_wait(); - awacs_burgundy_extend_wait(); - val += (in_le32(&awacs->codec_stat) >> 4) & 0xff; - - out_le32(&awacs->codec_ctrl, addr + 0x100100); - awacs_burgundy_busy_wait(); - awacs_burgundy_extend_wait(); - val += ((in_le32(&awacs->codec_stat)>>4) & 0xff) <<8; - - out_le32(&awacs->codec_ctrl, addr + 0x100200); - awacs_burgundy_busy_wait(); - awacs_burgundy_extend_wait(); - val += ((in_le32(&awacs->codec_stat)>>4) & 0xff) <<16; - - out_le32(&awacs->codec_ctrl, addr + 0x100300); - awacs_burgundy_busy_wait(); - awacs_burgundy_extend_wait(); - val += ((in_le32(&awacs->codec_stat)>>4) & 0xff) <<24; - - restore_flags(flags); - - return val; -} - - -static void -awacs_burgundy_wcb(unsigned addr, unsigned val) -{ - out_le32(&awacs->codec_ctrl, addr + 0x300000 + (val & 0xff)); - awacs_burgundy_busy_wait(); -} - -static unsigned -awacs_burgundy_rcb(unsigned addr) -{ - unsigned val = 0; - unsigned long flags; - - /* should have timeouts here */ - save_flags(flags); cli(); - - out_le32(&awacs->codec_ctrl, addr + 0x100000); - awacs_burgundy_busy_wait(); - awacs_burgundy_extend_wait(); - val += (in_le32(&awacs->codec_stat) >> 4) & 0xff; - - restore_flags(flags); - - return val; -} - -static int -awacs_burgundy_check(void) -{ - /* Checks to see the chip is alive and kicking */ - int error = in_le32(&awacs->codec_ctrl) & MASK_ERRCODE; - - return error == 0xf0000; -} - -static int -awacs_burgundy_init(void) -{ - if (awacs_burgundy_check()) { - printk(KERN_WARNING "AWACS: disabled by MacOS :-(\n"); - return 1; - } - - awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_OUTPUTENABLES, - DEF_BURGUNDY_OUTPUTENABLES); - awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, - DEF_BURGUNDY_MORE_OUTPUTENABLES); - awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_OUTPUTSELECTS, - DEF_BURGUNDY_OUTPUTSELECTS); - - awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_INPSEL21, - DEF_BURGUNDY_INPSEL21); - awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_INPSEL3, - DEF_BURGUNDY_INPSEL3); - awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_GAINCD, - DEF_BURGUNDY_GAINCD); - awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_GAINLINE, - DEF_BURGUNDY_GAINLINE); - awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_GAINMIC, - DEF_BURGUNDY_GAINMIC); - awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_GAINMODEM, - DEF_BURGUNDY_GAINMODEM); - - awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_ATTENSPEAKER, - DEF_BURGUNDY_ATTENSPEAKER); - awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_ATTENLINEOUT, - DEF_BURGUNDY_ATTENLINEOUT); - awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_ATTENHP, - DEF_BURGUNDY_ATTENHP); - - awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_MASTER_VOLUME, - DEF_BURGUNDY_MASTER_VOLUME); - awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_VOLCD, - DEF_BURGUNDY_VOLCD); - awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_VOLLINE, - DEF_BURGUNDY_VOLLINE); - awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_VOLMIC, - DEF_BURGUNDY_VOLMIC); - return 0; -} - -static void -awacs_burgundy_write_volume(unsigned address, int volume) -{ - int hardvolume,lvolume,rvolume; - - lvolume = (volume & 0xff) ? (volume & 0xff) + 155 : 0; - rvolume = ((volume >>8)&0xff) ? ((volume >> 8)&0xff ) + 155 : 0; - - hardvolume = lvolume + (rvolume << 16); - - awacs_burgundy_wcw(address, hardvolume); -} - -static int -awacs_burgundy_read_volume(unsigned address) -{ - int softvolume,wvolume; - - wvolume = awacs_burgundy_rcw(address); - - softvolume = (wvolume & 0xff) - 155; - softvolume += (((wvolume >> 16) & 0xff) - 155)<<8; - - return softvolume > 0 ? softvolume : 0; -} - - - - -static int -awacs_burgundy_read_mvolume(unsigned address) -{ - int lvolume,rvolume,wvolume; - - wvolume = awacs_burgundy_rcw(address); - - wvolume &= 0xffff; - - rvolume = (wvolume & 0xff) - 155; - lvolume = ((wvolume & 0xff00)>>8) - 155; - - return lvolume + (rvolume << 8); -} - - -static void -awacs_burgundy_write_mvolume(unsigned address, int volume) -{ - int lvolume,rvolume,hardvolume; - - lvolume = (volume &0xff) ? (volume & 0xff) + 155 :0; - rvolume = ((volume >>8) & 0xff) ? (volume >> 8) + 155 :0; - - hardvolume = lvolume + (rvolume << 8); - hardvolume += (hardvolume << 16); - - awacs_burgundy_wcw(address, hardvolume); -} - -/* End burgundy functions */ - - - - - -/* Turn on sound output, needed on G3 desktop powermacs */ -static void -awacs_enable_amp(int spkr_vol) -{ - struct adb_request req; - - awacs_spkr_vol = spkr_vol; - if (sys_ctrler != SYS_CTRLER_CUDA) - return; - - /* turn on headphones */ - cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, - 0x8a, 4, 0); - while (!req.complete) cuda_poll(); - cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, - 0x8a, 6, 0); - while (!req.complete) cuda_poll(); - - /* turn on speaker */ - cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, - 0x8a, 3, (100 - (spkr_vol & 0xff)) * 32 / 100); - while (!req.complete) cuda_poll(); - cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, - 0x8a, 5, (100 - ((spkr_vol >> 8) & 0xff)) * 32 / 100); - while (!req.complete) cuda_poll(); - - cuda_request(&req, NULL, 5, CUDA_PACKET, - CUDA_GET_SET_IIC, 0x8a, 1, 0x29); - while (!req.complete) cuda_poll(); -} - -#endif /* CONFIG_PPC */ - -/*** Machine definitions *****************************************************/ - - -#ifdef CONFIG_ATARI -static MACHINE machTT = { - DMASND_TT, AtaAlloc, AtaFree, AtaIrqInit, -#ifdef MODULE - AtaIrqCleanUp, -#endif /* MODULE */ - TTInit, TTSilence, TTSetFormat, TTSetVolume, - AtaSetBass, AtaSetTreble, TTSetGain, - AtaPlay -}; - -static MACHINE machFalcon = { - DMASND_FALCON, AtaAlloc, AtaFree, AtaIrqInit, -#ifdef MODULE - AtaIrqCleanUp, -#endif /* MODULE */ - FalconInit, FalconSilence, FalconSetFormat, FalconSetVolume, - AtaSetBass, AtaSetTreble, NULL, - AtaPlay -}; -#endif /* CONFIG_ATARI */ - -#ifdef CONFIG_AMIGA -static MACHINE machAmiga = { - DMASND_AMIGA, AmiAlloc, AmiFree, AmiIrqInit, -#ifdef MODULE - AmiIrqCleanUp, -#endif /* MODULE */ - AmiInit, AmiSilence, AmiSetFormat, AmiSetVolume, - NULL, AmiSetTreble, NULL, - AmiPlay -}; -#endif /* CONFIG_AMIGA */ - -#ifdef CONFIG_PPC -static MACHINE machPMac = { - DMASND_AWACS, PMacAlloc, PMacFree, PMacIrqInit, -#ifdef MODULE - PMacIrqCleanup, -#endif /* MODULE */ - PMacInit, PMacSilence, PMacSetFormat, PMacSetVolume, - NULL, NULL, NULL, /* bass, treble, gain */ - PMacPlay -}; -#endif /* CONFIG_AMIGA */ - - -/*** Mid level stuff *********************************************************/ - - -static void sound_silence(void) -{ - /* update hardware settings one more */ - (*sound.mach.init)(); - - (*sound.mach.silence)(); -} - - -static void sound_init(void) -{ - (*sound.mach.init)(); -} - - -static int sound_set_format(int format) -{ - return(*sound.mach.setFormat)(format); -} - - -static int sound_set_speed(int speed) -{ - if (speed < 0) - return(sound.soft.speed); - - sound.soft.speed = speed; - (*sound.mach.init)(); - if (sound.minDev == SND_DEV_DSP) - sound.dsp.speed = sound.soft.speed; - - return(sound.soft.speed); -} - - -static int sound_set_stereo(int stereo) -{ - if (stereo < 0) - return(sound.soft.stereo); - - stereo = !!stereo; /* should be 0 or 1 now */ - - sound.soft.stereo = stereo; - if (sound.minDev == SND_DEV_DSP) - sound.dsp.stereo = stereo; - (*sound.mach.init)(); - - return(stereo); -} - - -static int sound_set_volume(int volume) -{ - return(*sound.mach.setVolume)(volume); -} - - -#ifdef CONFIG_ATARI -static int sound_set_bass(int bass) -{ - return(sound.mach.setBass ? (*sound.mach.setBass)(bass) : 50); -} - -static int sound_set_gain(int gain) -{ - return sound.mach.setGain ? sound.mach.setGain(gain) : 100; -} -#endif /* CONFIG_ATARI */ - -#if defined(CONFIG_ATARI) || defined(CONFIG_AMIGA) -static int sound_set_treble(int treble) -{ - return(sound.mach.setTreble ? (*sound.mach.setTreble)(treble) : 50); -} -#endif /* CONFIG_ATARI || CONFIG_AMIGA */ - - -static ssize_t sound_copy_translate(const u_char *userPtr, - size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t (*ct_func)(const u_char *, size_t, u_char *, ssize_t *, ssize_t) = NULL; - - switch (sound.soft.format) { - case AFMT_MU_LAW: - ct_func = sound.trans->ct_ulaw; - break; - case AFMT_A_LAW: - ct_func = sound.trans->ct_alaw; - break; - case AFMT_S8: - ct_func = sound.trans->ct_s8; - break; - case AFMT_U8: - ct_func = sound.trans->ct_u8; - break; - case AFMT_S16_BE: - ct_func = sound.trans->ct_s16be; - break; - case AFMT_U16_BE: - ct_func = sound.trans->ct_u16be; - break; - case AFMT_S16_LE: - ct_func = sound.trans->ct_s16le; - break; - case AFMT_U16_LE: - ct_func = sound.trans->ct_u16le; - break; - } - if (ct_func) - return ct_func(userPtr, userCount, frame, frameUsed, frameLeft); - else - return 0; -} - -#ifdef CONFIG_PPC -static ssize_t sound_copy_translate_read(const u_char *userPtr, - size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t (*ct_func)(const u_char *, size_t, u_char *, ssize_t *, ssize_t) = NULL; - - switch (sound.soft.format) { - case AFMT_MU_LAW: - ct_func = sound.read_trans->ct_ulaw; - break; - case AFMT_A_LAW: - ct_func = sound.read_trans->ct_alaw; - break; - case AFMT_S8: - ct_func = sound.read_trans->ct_s8; - break; - case AFMT_U8: - ct_func = sound.read_trans->ct_u8; - break; - case AFMT_S16_BE: - ct_func = sound.read_trans->ct_s16be; - break; - case AFMT_U16_BE: - ct_func = sound.read_trans->ct_u16be; - break; - case AFMT_S16_LE: - ct_func = sound.read_trans->ct_s16le; - break; - case AFMT_U16_LE: - ct_func = sound.read_trans->ct_u16le; - break; - } - if (ct_func) - return ct_func(userPtr, userCount, frame, frameUsed, frameLeft); - else - return 0; -} -#endif - - -/* - * /dev/mixer abstraction - */ - - -#define RECLEVEL_VOXWARE_TO_GAIN(v) \ - ((v) < 0 ? 0 : (v) > 100 ? 15 : (v) * 3 / 20) -#define RECLEVEL_GAIN_TO_VOXWARE(v) (((v) * 20 + 2) / 3) - - -static int mixer_open(struct inode *inode, struct file *file) -{ - MOD_INC_USE_COUNT; - mixer.busy = 1; - return 0; -} - - -static int mixer_release(struct inode *inode, struct file *file) -{ - mixer.busy = 0; - MOD_DEC_USE_COUNT; - return 0; -} - - -static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd, - u_long arg) -{ - int data; - if (_SIOC_DIR(cmd) & _SIOC_WRITE) - mixer.modify_counter++; - if (cmd == OSS_GETVERSION) - return IOCTL_OUT(arg, SOUND_VERSION); - switch (sound.mach.type) { -#ifdef CONFIG_ATARI - case DMASND_FALCON: - switch (cmd) { - case SOUND_MIXER_INFO: { - mixer_info info; - strncpy(info.id, "FALCON", sizeof(info.id)); - strncpy(info.name, "FALCON", sizeof(info.name)); - info.name[sizeof(info.name)-1] = 0; - info.modify_counter = mixer.modify_counter; - copy_to_user_ret((int *)arg, &info, sizeof(info), -EFAULT); - return 0; - } - case SOUND_MIXER_READ_DEVMASK: - return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC | SOUND_MASK_SPEAKER); - case SOUND_MIXER_READ_RECMASK: - return IOCTL_OUT(arg, SOUND_MASK_MIC); - case SOUND_MIXER_READ_STEREODEVS: - return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC); - case SOUND_MIXER_READ_CAPS: - return IOCTL_OUT(arg, SOUND_CAP_EXCL_INPUT); - case SOUND_MIXER_READ_VOLUME: - return IOCTL_OUT(arg, - VOLUME_ATT_TO_VOXWARE(sound.volume_left) | - VOLUME_ATT_TO_VOXWARE(sound.volume_right) << 8); - case SOUND_MIXER_WRITE_MIC: - IOCTL_IN(arg, data); - tt_dmasnd.input_gain = - RECLEVEL_VOXWARE_TO_GAIN(data & 0xff) << 4 | - RECLEVEL_VOXWARE_TO_GAIN(data >> 8 & 0xff); - /* fall thru, return set value */ - case SOUND_MIXER_READ_MIC: - return IOCTL_OUT(arg, - RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain >> 4 & 0xf) | - RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain & 0xf) << 8); - case SOUND_MIXER_READ_SPEAKER: - { - int porta; - cli(); - sound_ym.rd_data_reg_sel = 14; - porta = sound_ym.rd_data_reg_sel; - sti(); - return IOCTL_OUT(arg, porta & 0x40 ? 0 : 100); - } - case SOUND_MIXER_WRITE_VOLUME: - IOCTL_IN(arg, data); - return IOCTL_OUT(arg, sound_set_volume(data)); - case SOUND_MIXER_WRITE_SPEAKER: - { - int porta; - IOCTL_IN(arg, data); - cli(); - sound_ym.rd_data_reg_sel = 14; - porta = (sound_ym.rd_data_reg_sel & ~0x40) | - (data < 50 ? 0x40 : 0); - sound_ym.wd_data = porta; - sti(); - return IOCTL_OUT(arg, porta & 0x40 ? 0 : 100); - } - } - break; - - case DMASND_TT: - switch (cmd) { - case SOUND_MIXER_INFO: { - mixer_info info; - strncpy(info.id, "TT", sizeof(info.id)); - strncpy(info.name, "TT", sizeof(info.name)); - info.name[sizeof(info.name)-1] = 0; - info.modify_counter = mixer.modify_counter; - copy_to_user_ret((int *)arg, &info, sizeof(info), -EFAULT); - return 0; - } - case SOUND_MIXER_READ_DEVMASK: - return IOCTL_OUT(arg, - SOUND_MASK_VOLUME | SOUND_MASK_TREBLE | SOUND_MASK_BASS | - (MACH_IS_TT ? SOUND_MASK_SPEAKER : 0)); - case SOUND_MIXER_READ_RECMASK: - return IOCTL_OUT(arg, 0); - case SOUND_MIXER_READ_STEREODEVS: - return IOCTL_OUT(arg, SOUND_MASK_VOLUME); - case SOUND_MIXER_READ_VOLUME: - return IOCTL_OUT(arg, - VOLUME_DB_TO_VOXWARE(sound.volume_left) | - (VOLUME_DB_TO_VOXWARE(sound.volume_right) << 8)); - case SOUND_MIXER_READ_BASS: - return IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(sound.bass)); - case SOUND_MIXER_READ_TREBLE: - return IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(sound.treble)); - case SOUND_MIXER_READ_OGAIN: - return IOCTL_OUT(arg, GAIN_DB_TO_VOXWARE(sound.gain)); - case SOUND_MIXER_READ_SPEAKER: - { - int porta; - if (MACH_IS_TT) { - cli(); - sound_ym.rd_data_reg_sel = 14; - porta = sound_ym.rd_data_reg_sel; - sti(); - return IOCTL_OUT(arg, porta & 0x40 ? 0 : 100); - } - } - break; - case SOUND_MIXER_WRITE_VOLUME: - IOCTL_IN(arg, data); - return IOCTL_OUT(arg, sound_set_volume(data)); - case SOUND_MIXER_WRITE_BASS: - IOCTL_IN(arg, data); - return IOCTL_OUT(arg, sound_set_bass(data)); - case SOUND_MIXER_WRITE_TREBLE: - IOCTL_IN(arg, data); - return IOCTL_OUT(arg, sound_set_treble(data)); - case SOUND_MIXER_WRITE_OGAIN: - IOCTL_IN(arg, data); - return IOCTL_OUT(arg, sound_set_gain(data)); - case SOUND_MIXER_WRITE_SPEAKER: - if (MACH_IS_TT) { - int porta; - IOCTL_IN(arg, data); - cli(); - sound_ym.rd_data_reg_sel = 14; - porta = (sound_ym.rd_data_reg_sel & ~0x40) | - (data < 50 ? 0x40 : 0); - sound_ym.wd_data = porta; - sti(); - return IOCTL_OUT(arg, porta & 0x40 ? 0 : 100); - } - } - break; -#endif /* CONFIG_ATARI */ - -#ifdef CONFIG_AMIGA - case DMASND_AMIGA: - switch (cmd) { - case SOUND_MIXER_INFO: { - mixer_info info; - strncpy(info.id, "AMIGA", sizeof(info.id)); - strncpy(info.name, "AMIGA", sizeof(info.name)); - info.name[sizeof(info.name)-1] = 0; - info.modify_counter = mixer.modify_counter; - copy_to_user_ret((int *)arg, &info, sizeof(info), -EFAULT); - return 0; - } - case SOUND_MIXER_READ_DEVMASK: - return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_TREBLE); - case SOUND_MIXER_READ_RECMASK: - return IOCTL_OUT(arg, 0); - case SOUND_MIXER_READ_STEREODEVS: - return IOCTL_OUT(arg, SOUND_MASK_VOLUME); - case SOUND_MIXER_READ_VOLUME: - return IOCTL_OUT(arg, - VOLUME_AMI_TO_VOXWARE(sound.volume_left) | - VOLUME_AMI_TO_VOXWARE(sound.volume_right) << 8); - case SOUND_MIXER_WRITE_VOLUME: - IOCTL_IN(arg, data); - return IOCTL_OUT(arg, sound_set_volume(data)); - case SOUND_MIXER_READ_TREBLE: - return IOCTL_OUT(arg, sound.treble); - case SOUND_MIXER_WRITE_TREBLE: - IOCTL_IN(arg, data); - return IOCTL_OUT(arg, sound_set_treble(data)); - } - break; -#endif /* CONFIG_AMIGA */ - -#ifdef CONFIG_PPC - case DMASND_AWACS: - /* Different IOCTLS for burgundy*/ - if (awacs_revision < AWACS_BURGUNDY) { - switch (cmd) { - case SOUND_MIXER_INFO: { - mixer_info info; - strncpy(info.id, "AWACS", sizeof(info.id)); - strncpy(info.name, "AWACS", sizeof(info.name)); - info.name[sizeof(info.name)-1] = 0; - info.modify_counter = mixer.modify_counter; - copy_to_user_ret((int *)arg, &info, - sizeof(info), -EFAULT); - return 0; - } - case SOUND_MIXER_READ_DEVMASK: - data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER - | SOUND_MASK_LINE | SOUND_MASK_MIC - | SOUND_MASK_CD | SOUND_MASK_RECLEV - | SOUND_MASK_ALTPCM - | SOUND_MASK_MONITOR; - return IOCTL_OUT(arg, data); - case SOUND_MIXER_READ_RECMASK: - data = SOUND_MASK_LINE | SOUND_MASK_MIC - | SOUND_MASK_CD; - return IOCTL_OUT(arg, data); - case SOUND_MIXER_READ_RECSRC: - data = 0; - if (awacs_reg[0] & MASK_MUX_AUDIN) - data |= SOUND_MASK_LINE; - if (awacs_reg[0] & MASK_MUX_MIC) - data |= SOUND_MASK_MIC; - if (awacs_reg[0] & MASK_MUX_CD) - data |= SOUND_MASK_CD; - if (awacs_reg[1] & MASK_LOOPTHRU) - data |= SOUND_MASK_MONITOR; - return IOCTL_OUT(arg, data); - case SOUND_MIXER_WRITE_RECSRC: - IOCTL_IN(arg, data); - data &= (SOUND_MASK_LINE - | SOUND_MASK_MIC | SOUND_MASK_CD - | SOUND_MASK_MONITOR); - awacs_reg[0] &= ~(MASK_MUX_CD | MASK_MUX_MIC - | MASK_MUX_AUDIN); - awacs_reg[1] &= ~MASK_LOOPTHRU; - if (data & SOUND_MASK_LINE) - awacs_reg[0] |= MASK_MUX_AUDIN; - if (data & SOUND_MASK_MIC) - awacs_reg[0] |= MASK_MUX_MIC; - if (data & SOUND_MASK_CD) - awacs_reg[0] |= MASK_MUX_CD; - if (data & SOUND_MASK_MONITOR) - awacs_reg[1] |= MASK_LOOPTHRU; - awacs_write(awacs_reg[0] | MASK_ADDR0); - awacs_write(awacs_reg[1] | MASK_ADDR1); - return IOCTL_OUT(arg, data); - case SOUND_MIXER_READ_STEREODEVS: - data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER - | SOUND_MASK_RECLEV; - return IOCTL_OUT(arg, data); - case SOUND_MIXER_READ_CAPS: - return IOCTL_OUT(arg, 0); - case SOUND_MIXER_READ_VOLUME: - data = (awacs_reg[1] & MASK_AMUTE)? 0: - awacs_get_volume(awacs_reg[2], 6); - return IOCTL_OUT(arg, data); - case SOUND_MIXER_WRITE_VOLUME: - IOCTL_IN(arg, data); - return IOCTL_OUT(arg, sound_set_volume(data)); - case SOUND_MIXER_READ_SPEAKER: - if (awacs_revision == 3 - && sys_ctrler == SYS_CTRLER_CUDA) - data = awacs_spkr_vol; - else - data = (awacs_reg[1] & MASK_CMUTE)? 0: - awacs_get_volume(awacs_reg[4], 6); - return IOCTL_OUT(arg, data); - case SOUND_MIXER_WRITE_SPEAKER: - IOCTL_IN(arg, data); - if (awacs_revision == 3 - && sys_ctrler == SYS_CTRLER_CUDA) - awacs_enable_amp(data); - else - data = awacs_volume_setter(data, 4, MASK_CMUTE, 6); - return IOCTL_OUT(arg, data); - case SOUND_MIXER_WRITE_ALTPCM: /* really bell volume */ - IOCTL_IN(arg, data); - beep_volume = data & 0xff; - /* fall through */ - case SOUND_MIXER_READ_ALTPCM: - return IOCTL_OUT(arg, beep_volume); - case SOUND_MIXER_WRITE_LINE: - IOCTL_IN(arg, data); - awacs_reg[0] &= ~MASK_MUX_AUDIN; - if ((data & 0xff) >= 50) - awacs_reg[0] |= MASK_MUX_AUDIN; - awacs_write(MASK_ADDR0 | awacs_reg[0]); - /* fall through */ - case SOUND_MIXER_READ_LINE: - data = (awacs_reg[0] & MASK_MUX_AUDIN)? 100: 0; - return IOCTL_OUT(arg, data); - case SOUND_MIXER_WRITE_MIC: - IOCTL_IN(arg, data); - data &= 0xff; - awacs_reg[0] &= ~(MASK_MUX_MIC | MASK_GAINLINE); - if (data >= 25) { - awacs_reg[0] |= MASK_MUX_MIC; - if (data >= 75) - awacs_reg[0] |= MASK_GAINLINE; - } - awacs_write(MASK_ADDR0 | awacs_reg[0]); - /* fall through */ - case SOUND_MIXER_READ_MIC: - data = (awacs_reg[0] & MASK_MUX_MIC)? - (awacs_reg[0] & MASK_GAINLINE? 100: 50): 0; - return IOCTL_OUT(arg, data); - case SOUND_MIXER_WRITE_CD: - IOCTL_IN(arg, data); - awacs_reg[0] &= ~MASK_MUX_CD; - if ((data & 0xff) >= 50) - awacs_reg[0] |= MASK_MUX_CD; - awacs_write(MASK_ADDR0 | awacs_reg[0]); - /* fall through */ - case SOUND_MIXER_READ_CD: - data = (awacs_reg[0] & MASK_MUX_CD)? 100: 0; - return IOCTL_OUT(arg, data); - case SOUND_MIXER_WRITE_RECLEV: - IOCTL_IN(arg, data); - data = awacs_volume_setter(data, 0, 0, 4); - return IOCTL_OUT(arg, data); - case SOUND_MIXER_READ_RECLEV: - data = awacs_get_volume(awacs_reg[0], 4); - return IOCTL_OUT(arg, data); - } - break; - } else { - /* We are, we are, we are... Burgundy or better */ - switch(cmd) { - case SOUND_MIXER_INFO: { - mixer_info info; - strncpy(info.id, "AWACS", sizeof(info.id)); - strncpy(info.name, "AWACS", sizeof(info.name)); - info.name[sizeof(info.name)-1] = 0; - info.modify_counter = mixer.modify_counter; - copy_to_user_ret((int *)arg, &info, - sizeof(info), -EFAULT); - return 0; - } - case SOUND_MIXER_READ_DEVMASK: - data = SOUND_MASK_VOLUME | SOUND_MASK_CD | - SOUND_MASK_LINE | SOUND_MASK_MIC | - SOUND_MASK_SPEAKER | SOUND_MASK_ALTPCM; - return IOCTL_OUT(arg, data); - case SOUND_MIXER_READ_RECMASK: - data = SOUND_MASK_LINE | SOUND_MASK_MIC - | SOUND_MASK_CD; - return IOCTL_OUT(arg, data); - case SOUND_MIXER_READ_RECSRC: - data = 0; - if (awacs_reg[0] & MASK_MUX_AUDIN) - data |= SOUND_MASK_LINE; - if (awacs_reg[0] & MASK_MUX_MIC) - data |= SOUND_MASK_MIC; - if (awacs_reg[0] & MASK_MUX_CD) - data |= SOUND_MASK_CD; - return IOCTL_OUT(arg, data); - case SOUND_MIXER_WRITE_RECSRC: - IOCTL_IN(arg, data); - data &= (SOUND_MASK_LINE - | SOUND_MASK_MIC | SOUND_MASK_CD); - awacs_reg[0] &= ~(MASK_MUX_CD | MASK_MUX_MIC - | MASK_MUX_AUDIN); - if (data & SOUND_MASK_LINE) - awacs_reg[0] |= MASK_MUX_AUDIN; - if (data & SOUND_MASK_MIC) - awacs_reg[0] |= MASK_MUX_MIC; - if (data & SOUND_MASK_CD) - awacs_reg[0] |= MASK_MUX_CD; - awacs_write(awacs_reg[0] | MASK_ADDR0); - return IOCTL_OUT(arg, data); - case SOUND_MIXER_READ_STEREODEVS: - data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER - | SOUND_MASK_RECLEV | SOUND_MASK_CD - | SOUND_MASK_LINE; - return IOCTL_OUT(arg, data); - case SOUND_MIXER_READ_CAPS: - return IOCTL_OUT(arg, 0); - case SOUND_MIXER_WRITE_VOLUME: - IOCTL_IN(arg, data); - awacs_burgundy_write_mvolume(MASK_ADDR_BURGUNDY_MASTER_VOLUME, data); - /* Fall through */ - case SOUND_MIXER_READ_VOLUME: - return IOCTL_OUT(arg, awacs_burgundy_read_mvolume(MASK_ADDR_BURGUNDY_MASTER_VOLUME)); - case SOUND_MIXER_WRITE_SPEAKER: - IOCTL_IN(arg, data); - - if (!(data & 0xff)) { - /* Mute the left speaker */ - awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, - awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) & ~0x2); - } else { - /* Unmute the left speaker */ - awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, - awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) | 0x2); - } - if (!(data & 0xff00)) { - /* Mute the right speaker */ - awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, - awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) & ~0x4); - } else { - /* Unmute the right speaker */ - awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, - awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) | 0x4); - } - - data = (((data&0xff)*16)/100 > 0xf ? 0xf : - (((data&0xff)*16)/100)) + - ((((data>>8)*16)/100 > 0xf ? 0xf : - ((((data>>8)*16)/100)))<<4); - - awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_ATTENSPEAKER, ~data); - /* Fall through */ - case SOUND_MIXER_READ_SPEAKER: - data = awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_ATTENSPEAKER); - data = (((data & 0xf)*100)/16) + ((((data>>4)*100)/16)<<8); - return IOCTL_OUT(arg, ~data); - case SOUND_MIXER_WRITE_ALTPCM: /* really bell volume */ - IOCTL_IN(arg, data); - beep_volume = data & 0xff; - /* fall through */ - case SOUND_MIXER_READ_ALTPCM: - return IOCTL_OUT(arg, beep_volume); - case SOUND_MIXER_WRITE_LINE: - IOCTL_IN(arg, data); - awacs_burgundy_write_volume(MASK_ADDR_BURGUNDY_VOLLINE, data); - - /* fall through */ - case SOUND_MIXER_READ_LINE: - data = awacs_burgundy_read_volume(MASK_ADDR_BURGUNDY_VOLLINE); - return IOCTL_OUT(arg, data); - case SOUND_MIXER_WRITE_MIC: - IOCTL_IN(arg, data); - /* Mic is mono device */ - data = (data << 8) + (data << 24); - awacs_burgundy_write_volume(MASK_ADDR_BURGUNDY_VOLMIC, data); - /* fall through */ - case SOUND_MIXER_READ_MIC: - data = awacs_burgundy_read_volume(MASK_ADDR_BURGUNDY_VOLMIC); - data <<= 24; - return IOCTL_OUT(arg, data); - case SOUND_MIXER_WRITE_CD: - IOCTL_IN(arg, data); - awacs_burgundy_write_volume(MASK_ADDR_BURGUNDY_VOLCD, data); - /* fall through */ - case SOUND_MIXER_READ_CD: - data = awacs_burgundy_read_volume(MASK_ADDR_BURGUNDY_VOLCD); - return IOCTL_OUT(arg, data); - case SOUND_MIXER_WRITE_RECLEV: - IOCTL_IN(arg, data); - data = awacs_volume_setter(data, 0, 0, 4); - return IOCTL_OUT(arg, data); - case SOUND_MIXER_READ_RECLEV: - data = awacs_get_volume(awacs_reg[0], 4); - return IOCTL_OUT(arg, data); - case SOUND_MIXER_OUTMASK: - break; - case SOUND_MIXER_OUTSRC: - break; - } - break; - } -#endif - } - - return -EINVAL; -} - - -static struct file_operations mixer_fops = -{ - llseek: sound_lseek, - ioctl: mixer_ioctl, - open: mixer_open, - release: mixer_release, -}; - - -static void __init mixer_init(void) -{ -#ifndef MODULE - int mixer_unit; -#endif - mixer_unit = register_sound_mixer(&mixer_fops, -1); - if (mixer_unit < 0) - return; - - mixer.busy = 0; - sound.treble = 0; - sound.bass = 0; - switch (sound.mach.type) { -#ifdef CONFIG_ATARI - case DMASND_TT: - atari_microwire_cmd(MW_LM1992_VOLUME(0)); - sound.volume_left = 0; - atari_microwire_cmd(MW_LM1992_BALLEFT(0)); - sound.volume_right = 0; - atari_microwire_cmd(MW_LM1992_BALRIGHT(0)); - atari_microwire_cmd(MW_LM1992_TREBLE(0)); - atari_microwire_cmd(MW_LM1992_BASS(0)); - break; - case DMASND_FALCON: - sound.volume_left = (tt_dmasnd.output_atten & 0xf00) >> 8; - sound.volume_right = (tt_dmasnd.output_atten & 0xf0) >> 4; - break; -#endif /* CONFIG_ATARI */ -#ifdef CONFIG_AMIGA - case DMASND_AMIGA: - sound.volume_left = 64; - sound.volume_right = 64; - custom.aud[0].audvol = sound.volume_left; - custom.aud[3].audvol = 1; /* For pseudo 14bit */ - custom.aud[1].audvol = sound.volume_right; - custom.aud[2].audvol = 1; /* For pseudo 14bit */ - sound.treble = 50; - break; -#endif /* CONFIG_AMIGA */ - } -} - - -/* - * Sound queue stuff, the heart of the driver - */ - - -static int sq_allocate_buffers(void) -{ - int i; - - if (sound_buffers) - return 0; - sound_buffers = kmalloc (numBufs * sizeof(char *), GFP_KERNEL); - if (!sound_buffers) - return -ENOMEM; - for (i = 0; i < numBufs; i++) { - sound_buffers[i] = sound.mach.dma_alloc (bufSize << 10, GFP_KERNEL); - if (!sound_buffers[i]) { - while (i--) - sound.mach.dma_free (sound_buffers[i], bufSize << 10); - kfree (sound_buffers); - sound_buffers = 0; - return -ENOMEM; - } - } - return 0; -} - - -static void sq_release_buffers(void) -{ - int i; - - if (sound_buffers) { - for (i = 0; i < numBufs; i++) - sound.mach.dma_free (sound_buffers[i], bufSize << 10); - kfree (sound_buffers); - sound_buffers = 0; - } -} - - -#ifdef CONFIG_PPC -static int sq_allocate_read_buffers(void) -{ - int i; - int j; - - if (sound_read_buffers) - return 0; - sound_read_buffers = kmalloc(numReadBufs * sizeof(char *), GFP_KERNEL); - if (!sound_read_buffers) - return -ENOMEM; - for (i = 0; i < numBufs; i++) { - sound_read_buffers[i] = sound.mach.dma_alloc (readbufSize<<10, - GFP_KERNEL); - if (!sound_read_buffers[i]) { - while (i--) - sound.mach.dma_free (sound_read_buffers[i], - readbufSize << 10); - kfree (sound_read_buffers); - sound_read_buffers = 0; - return -ENOMEM; - } - /* XXXX debugging code */ - for (j=0; jcommand, DBDMA_STOP); - } - /* We should probably wait for the thing to stop before we - release the memory */ - for (i = 0; i < numBufs; i++) - sound.mach.dma_free (sound_read_buffers[i], - bufSize << 10); - kfree (sound_read_buffers); - sound_read_buffers = 0; - } -} -#endif - - -static void sq_setup(int numBufs, int bufSize, char **write_buffers) -{ -#ifdef CONFIG_PPC - int i; - volatile struct dbdma_cmd *cp; -#endif /* CONFIG_PPC */ - - sq.max_count = numBufs; - sq.max_active = numBufs; - sq.block_size = bufSize; - sq.buffers = write_buffers; - - sq.front = sq.count = 0; - sq.rear = -1; - sq.syncing = 0; - sq.active = 0; - -#ifdef CONFIG_ATARI - sq.ignore_int = 0; -#endif /* CONFIG_ATARI */ -#ifdef CONFIG_AMIGA - sq.block_size_half = sq.block_size>>1; - sq.block_size_quarter = sq.block_size_half>>1; -#endif /* CONFIG_AMIGA */ -#ifdef CONFIG_PPC - cp = awacs_tx_cmds; - memset((void *) cp, 0, (numBufs + 1) * sizeof(struct dbdma_cmd)); - for (i = 0; i < numBufs; ++i, ++cp) { - st_le32(&cp->phy_addr, virt_to_bus(write_buffers[i])); - } - st_le16(&cp->command, DBDMA_NOP + BR_ALWAYS); - st_le32(&cp->cmd_dep, virt_to_bus(awacs_tx_cmds)); - out_le32(&awacs_txdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16); - out_le32(&awacs_txdma->cmdptr, virt_to_bus(awacs_tx_cmds)); -#endif /* CONFIG_PPC */ -} - -#ifdef CONFIG_PPC -static void read_sq_setup(int numBufs, int bufSize, char **read_buffers) -{ - int i; - volatile struct dbdma_cmd *cp; - - read_sq.max_count = numBufs; - read_sq.max_active = numBufs; - read_sq.block_size = bufSize; - read_sq.buffers = read_buffers; - - read_sq.front = read_sq.count = 0; - read_sq.rear = 0; - read_sq.rear_size = 0; - read_sq.syncing = 0; - read_sq.active = 0; - - cp = awacs_rx_cmds; - memset((void *) cp, 0, (numBufs + 1) * sizeof(struct dbdma_cmd)); - - /* Set dma buffers up in a loop */ - for (i = 0; i < numBufs; i++,cp++) { - st_le32(&cp->phy_addr, virt_to_bus(read_buffers[i])); - st_le16(&cp->command, INPUT_MORE + INTR_ALWAYS); - st_le16(&cp->req_count, read_sq.block_size); - st_le16(&cp->xfer_status, 0); - } - - /* The next two lines make the thing loop around. - */ - st_le16(&cp->command, DBDMA_NOP + BR_ALWAYS); - st_le32(&cp->cmd_dep, virt_to_bus(awacs_rx_cmds)); - - /* Don't start until the first read is done. - * This will also abort any operations in progress if the DMA - * happens to be running (and it shouldn't). - */ - out_le32(&awacs_rxdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16); - out_le32(&awacs_rxdma->cmdptr, virt_to_bus(awacs_rx_cmds)); - -} -#endif /* CONFIG_PPC */ - - -static void sq_play(void) -{ - (*sound.mach.play)(); -} - - -/* ++TeSche: radically changed this one too */ - -static ssize_t sq_write(struct file *file, const char *src, size_t uLeft, - loff_t *ppos) -{ - ssize_t uWritten = 0; - u_char *dest; - ssize_t uUsed, bUsed, bLeft; - - /* ++TeSche: Is something like this necessary? - * Hey, that's an honest question! Or does any other part of the - * filesystem already checks this situation? I really don't know. - */ - if (uLeft == 0) - return 0; - - /* The interrupt doesn't start to play the last, incomplete frame. - * Thus we can append to it without disabling the interrupts! (Note - * also that sq.rear isn't affected by the interrupt.) - */ - - if (sq.count > 0 && (bLeft = sq.block_size-sq.rear_size) > 0) { - dest = sq_block_address(sq.rear); - bUsed = sq.rear_size; - uUsed = sound_copy_translate(src, uLeft, dest, &bUsed, bLeft); - if (uUsed <= 0) - return uUsed; - src += uUsed; - uWritten += uUsed; - uLeft -= uUsed; - sq.rear_size = bUsed; - } - - do { - while (sq.count == sq.max_active) { - sq_play(); - if (NON_BLOCKING(sq.open_mode)) - return uWritten > 0 ? uWritten : -EAGAIN; - SLEEP(sq.action_queue, ONE_SECOND); - if (SIGNAL_RECEIVED) - return uWritten > 0 ? uWritten : -EINTR; - } - - /* Here, we can avoid disabling the interrupt by first - * copying and translating the data, and then updating - * the sq variables. Until this is done, the interrupt - * won't see the new frame and we can work on it - * undisturbed. - */ - - dest = sq_block_address((sq.rear+1) % sq.max_count); - bUsed = 0; - bLeft = sq.block_size; - uUsed = sound_copy_translate(src, uLeft, dest, &bUsed, bLeft); - if (uUsed <= 0) - break; - src += uUsed; - uWritten += uUsed; - uLeft -= uUsed; - if (bUsed) { - sq.rear = (sq.rear+1) % sq.max_count; - sq.rear_size = bUsed; - sq.count++; - } - } while (bUsed); /* uUsed may have been 0 */ - - sq_play(); - - return uUsed < 0? uUsed: uWritten; -} - - -/***********/ - -#ifdef CONFIG_PPC - -/* Here is how the values are used for reading. - * The value 'active' simply indicates the DMA is running. This is - * done so the driver semantics are DMA starts when the first read is - * posted. The value 'front' indicates the buffer we should next - * send to the user. The value 'rear' indicates the buffer the DMA is - * currently filling. When 'front' == 'rear' the buffer "ring" is - * empty (we always have an empty available). The 'rear_size' is used - * to track partial offsets into the current buffer. Right now, I just keep - * the DMA running. If the reader can't keep up, the interrupt tosses - * the oldest buffer. We could also shut down the DMA in this case. - */ -static ssize_t sq_read(struct file *file, char *dst, size_t uLeft, - loff_t *ppos) -{ - - ssize_t uRead, bLeft, bUsed, uUsed; - - if (uLeft == 0) - return 0; - - if (!read_sq.active) - PMacRecord(); /* Kick off the record process. */ - - uRead = 0; - - /* Move what the user requests, depending upon other options. - */ - while (uLeft > 0) { - - /* When front == rear, the DMA is not done yet. - */ - while (read_sq.front == read_sq.rear) { - if (NON_BLOCKING(read_sq.open_mode)) { - return uRead > 0 ? uRead : -EAGAIN; - } - SLEEP(read_sq.action_queue, ONE_SECOND); - if (SIGNAL_RECEIVED) - return uRead > 0 ? uRead : -EINTR; - } - - /* The amount we move is either what is left in the - * current buffer or what the user wants. - */ - bLeft = read_sq.block_size - read_sq.rear_size; - bUsed = read_sq.rear_size; - uUsed = sound_copy_translate_read(dst, uLeft, - read_sq.buffers[read_sq.front], &bUsed, bLeft); - if (uUsed <= 0) - return uUsed; - dst += uUsed; - uRead += uUsed; - uLeft -= uUsed; - read_sq.rear_size += bUsed; - if (read_sq.rear_size >= read_sq.block_size) { - read_sq.rear_size = 0; - read_sq.front++; - if (read_sq.front >= read_sq.max_active) - read_sq.front = 0; - } - } - return uRead; -} -#endif - -static int sq_open(struct inode *inode, struct file *file) -{ - int rc = 0; - - MOD_INC_USE_COUNT; - if (file->f_mode & FMODE_WRITE) { - if (sq.busy) { - rc = -EBUSY; - if (NON_BLOCKING(file->f_flags)) - goto err_out; - rc = -EINTR; - while (sq.busy) { - SLEEP(sq.open_queue, ONE_SECOND); - if (SIGNAL_RECEIVED) - goto err_out; - } - } - sq.busy = 1; /* Let's play spot-the-race-condition */ - - if (sq_allocate_buffers()) goto err_out_nobusy; - - sq_setup(numBufs, bufSize<<10,sound_buffers); - sq.open_mode = file->f_mode; - } - - -#ifdef CONFIG_PPC - if (file->f_mode & FMODE_READ) { - if (read_sq.busy) { - rc = -EBUSY; - if (NON_BLOCKING(file->f_flags)) - goto err_out; - rc = -EINTR; - while (read_sq.busy) { - SLEEP(read_sq.open_queue, ONE_SECOND); - if (SIGNAL_RECEIVED) - goto err_out; - } - rc = 0; - } - read_sq.busy = 1; - if (sq_allocate_read_buffers()) goto err_out_nobusy; - - read_sq_setup(numReadBufs,readbufSize<<10, sound_read_buffers); - read_sq.open_mode = file->f_mode; - } -#endif - -#ifdef CONFIG_ATARI - sq.ignore_int = 1; -#endif /* CONFIG_ATARI */ - sound.minDev = MINOR(inode->i_rdev) & 0x0f; - sound.soft = sound.dsp; - sound.hard = sound.dsp; - sound_init(); - if ((MINOR(inode->i_rdev) & 0x0f) == SND_DEV_AUDIO) { - sound_set_speed(8000); - sound_set_stereo(0); - sound_set_format(AFMT_MU_LAW); - } - -#if 0 - if (file->f_mode == FMODE_READ) { - /* Start dma'ing straight away */ - PMacRecord(); - } -#endif - - return 0; - -err_out_nobusy: - if (file->f_mode & FMODE_WRITE) { - sq.busy = 0; - WAKE_UP(sq.open_queue); - } -#ifdef CONFIG_PPC - if (file->f_mode & FMODE_READ) { - read_sq.busy = 0; - WAKE_UP(read_sq.open_queue); - } -#endif -err_out: - MOD_DEC_USE_COUNT; - return rc; -} - - -static void sq_reset(void) -{ - sound_silence(); - sq.active = 0; - sq.count = 0; - sq.front = (sq.rear+1) % sq.max_count; -} - - -static int sq_fsync(struct file *filp, struct dentry *dentry) -{ - int rc = 0; - - sq.syncing = 1; - sq_play(); /* there may be an incomplete frame waiting */ - - while (sq.active) { - SLEEP(sq.sync_queue, ONE_SECOND); - if (SIGNAL_RECEIVED) { - /* While waiting for audio output to drain, an - * interrupt occurred. Stop audio output immediately - * and clear the queue. */ - sq_reset(); - rc = -EINTR; - break; - } - } - - sq.syncing = 0; - return rc; -} - -static int sq_release(struct inode *inode, struct file *file) -{ - int rc = 0; - - if (sq.busy) - rc = sq_fsync(file, file->f_dentry); - sound.soft = sound.dsp; - sound.hard = sound.dsp; - sound_silence(); - -#ifdef CONFIG_PPC - sq_release_read_buffers(); -#endif - sq_release_buffers(); - MOD_DEC_USE_COUNT; - - /* There is probably a DOS atack here. They change the mode flag. */ - /* XXX add check here */ -#ifdef CONFIG_PPC - if (file->f_mode & FMODE_READ) { - read_sq.busy = 0; - WAKE_UP(read_sq.open_queue); - } -#endif - - if (file->f_mode & FMODE_WRITE) { - sq.busy = 0; - WAKE_UP(sq.open_queue); - } - - /* Wake up a process waiting for the queue being released. - * Note: There may be several processes waiting for a call - * to open() returning. */ - - return rc; -} - - -static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd, - u_long arg) -{ - u_long fmt; - int data; - int size, nbufs; - audio_buf_info info; - - switch (cmd) { - case SNDCTL_DSP_RESET: - sq_reset(); - return 0; - case SNDCTL_DSP_POST: - case SNDCTL_DSP_SYNC: - return sq_fsync(file, file->f_dentry); - - /* ++TeSche: before changing any of these it's - * probably wise to wait until sound playing has - * settled down. */ - case SNDCTL_DSP_SPEED: - sq_fsync(file, file->f_dentry); - IOCTL_IN(arg, data); - return IOCTL_OUT(arg, sound_set_speed(data)); - case SNDCTL_DSP_STEREO: - sq_fsync(file, file->f_dentry); - IOCTL_IN(arg, data); - return IOCTL_OUT(arg, sound_set_stereo(data)); - case SOUND_PCM_WRITE_CHANNELS: - sq_fsync(file, file->f_dentry); - IOCTL_IN(arg, data); - return IOCTL_OUT(arg, sound_set_stereo(data-1)+1); - case SNDCTL_DSP_SETFMT: - sq_fsync(file, file->f_dentry); - IOCTL_IN(arg, data); - return IOCTL_OUT(arg, sound_set_format(data)); - case SNDCTL_DSP_GETFMTS: - fmt = 0; - if (sound.trans) { - if (sound.trans->ct_ulaw) - fmt |= AFMT_MU_LAW; - if (sound.trans->ct_alaw) - fmt |= AFMT_A_LAW; - if (sound.trans->ct_s8) - fmt |= AFMT_S8; - if (sound.trans->ct_u8) - fmt |= AFMT_U8; - if (sound.trans->ct_s16be) - fmt |= AFMT_S16_BE; - if (sound.trans->ct_u16be) - fmt |= AFMT_U16_BE; - if (sound.trans->ct_s16le) - fmt |= AFMT_S16_LE; - if (sound.trans->ct_u16le) - fmt |= AFMT_U16_LE; - } - return IOCTL_OUT(arg, fmt); - case SNDCTL_DSP_GETBLKSIZE: - size = sq.block_size - * sound.soft.size * (sound.soft.stereo + 1) - / (sound.hard.size * (sound.hard.stereo + 1)); - return IOCTL_OUT(arg, size); - case SNDCTL_DSP_SUBDIVIDE: - break; - case SNDCTL_DSP_SETFRAGMENT: - if (sq.count || sq.active || sq.syncing) - return -EINVAL; - IOCTL_IN(arg, size); - nbufs = size >> 16; - if (nbufs < 2 || nbufs > numBufs) - nbufs = numBufs; - size &= 0xffff; - if (size >= 8 && size <= 29) { - size = 1 << size; - size *= sound.hard.size * (sound.hard.stereo + 1); - size /= sound.soft.size * (sound.soft.stereo + 1); - if (size > (bufSize << 10)) - size = bufSize << 10; - } else - size = bufSize << 10; - sq_setup(numBufs, size, sound_buffers); - sq.max_active = nbufs; - return 0; - case SNDCTL_DSP_GETOSPACE: - info.fragments = sq.max_active - sq.count; - info.fragstotal = sq.max_active; - info.fragsize = sq.block_size; - info.bytes = info.fragments * info.fragsize; - if (copy_to_user((void *)arg, &info, sizeof(info))) - return -EFAULT; - return 0; - - default: - return mixer_ioctl(inode, file, cmd, arg); - } - return -EINVAL; -} - - - -static struct file_operations sq_fops = -{ - llseek: sound_lseek, - write: sq_write, - ioctl: sq_ioctl, - open: sq_open, - release: sq_release, -#ifdef CONFIG_PPC - read: sq_read, /* sq_read */ -#endif -}; - - -static void __init sq_init(void) -{ -#ifndef MODULE - int sq_unit; -#endif - sq_unit = register_sound_dsp(&sq_fops, -1); - if (sq_unit < 0) - return; - - init_waitqueue_head(&sq.action_queue); - init_waitqueue_head(&sq.open_queue); - init_waitqueue_head(&sq.sync_queue); - -#ifdef CONFIG_PPC - init_waitqueue_head(&read_sq.action_queue); - init_waitqueue_head(&read_sq.open_queue); - init_waitqueue_head(&read_sq.sync_queue); -#endif - - sq.busy = 0; -#ifdef CONFIG_PPC - read_sq.busy = 0; -#endif - - /* whatever you like as startup mode for /dev/dsp, - * (/dev/audio hasn't got a startup mode). note that - * once changed a new open() will *not* restore these! - */ - sound.dsp.format = AFMT_U8; - sound.dsp.stereo = 0; - sound.dsp.size = 8; - - /* set minimum rate possible without expanding */ - switch (sound.mach.type) { -#ifdef CONFIG_ATARI - case DMASND_TT: - sound.dsp.speed = 6258; - break; - case DMASND_FALCON: - sound.dsp.speed = 8195; - break; -#endif /* CONFIG_ATARI */ -#ifdef CONFIG_AMIGA - case DMASND_AMIGA: - sound.dsp.speed = 8000; - break; -#endif /* CONFIG_AMIGA */ -#ifdef CONFIG_PPC - case DMASND_AWACS: - sound.dsp.speed = 8000; - break; -#endif /* CONFIG_PPC */ - } - - /* before the first open to /dev/dsp this wouldn't be set */ - sound.soft = sound.dsp; - sound.hard = sound.dsp; - - sound_silence(); -} - -/* - * /dev/sndstat - */ - - -/* state.buf should not overflow! */ - -static int state_open(struct inode *inode, struct file *file) -{ - char *buffer = state.buf, *mach = ""; -#ifdef CONFIG_PPC - char awacs_buf[64]; -#endif - int len = 0; - - if (state.busy) - return -EBUSY; - - MOD_INC_USE_COUNT; - state.ptr = 0; - state.busy = 1; - - switch (sound.mach.type) { -#ifdef CONFIG_ATARI - case DMASND_TT: - case DMASND_FALCON: - mach = "Atari "; - break; -#endif /* CONFIG_ATARI */ -#ifdef CONFIG_AMIGA - case DMASND_AMIGA: - mach = "Amiga "; - break; -#endif /* CONFIG_AMIGA */ -#ifdef CONFIG_PPC - case DMASND_AWACS: - sprintf(awacs_buf, "PowerMac (AWACS rev %d) ", awacs_revision); - mach = awacs_buf; - break; -#endif /* CONFIG_PPC */ - } - len += sprintf(buffer+len, "%sDMA sound driver:\n", mach); - - len += sprintf(buffer+len, "\tsound.format = 0x%x", sound.soft.format); - switch (sound.soft.format) { - case AFMT_MU_LAW: - len += sprintf(buffer+len, " (mu-law)"); - break; - case AFMT_A_LAW: - len += sprintf(buffer+len, " (A-law)"); - break; - case AFMT_U8: - len += sprintf(buffer+len, " (unsigned 8 bit)"); - break; - case AFMT_S8: - len += sprintf(buffer+len, " (signed 8 bit)"); - break; - case AFMT_S16_BE: - len += sprintf(buffer+len, " (signed 16 bit big)"); - break; - case AFMT_U16_BE: - len += sprintf(buffer+len, " (unsigned 16 bit big)"); - break; - case AFMT_S16_LE: - len += sprintf(buffer+len, " (signed 16 bit little)"); - break; - case AFMT_U16_LE: - len += sprintf(buffer+len, " (unsigned 16 bit little)"); - break; - } - len += sprintf(buffer+len, "\n"); - len += sprintf(buffer+len, "\tsound.speed = %dHz (phys. %dHz)\n", - sound.soft.speed, sound.hard.speed); - len += sprintf(buffer+len, "\tsound.stereo = 0x%x (%s)\n", - sound.soft.stereo, sound.soft.stereo ? "stereo" : "mono"); - switch (sound.mach.type) { -#ifdef CONFIG_ATARI - case DMASND_TT: - len += sprintf(buffer+len, "\tsound.volume_left = %ddB [-40...0]\n", - sound.volume_left); - len += sprintf(buffer+len, "\tsound.volume_right = %ddB [-40...0]\n", - sound.volume_right); - len += sprintf(buffer+len, "\tsound.bass = %ddB [-12...+12]\n", - sound.bass); - len += sprintf(buffer+len, "\tsound.treble = %ddB [-12...+12]\n", - sound.treble); - break; - case DMASND_FALCON: - len += sprintf(buffer+len, "\tsound.volume_left = %ddB [-22.5...0]\n", - sound.volume_left); - len += sprintf(buffer+len, "\tsound.volume_right = %ddB [-22.5...0]\n", - sound.volume_right); - break; -#endif /* CONFIG_ATARI */ -#ifdef CONFIG_AMIGA - case DMASND_AMIGA: - len += sprintf(buffer+len, "\tsound.volume_left = %d [0...64]\n", - sound.volume_left); - len += sprintf(buffer+len, "\tsound.volume_right = %d [0...64]\n", - sound.volume_right); - break; -#endif /* CONFIG_AMIGA */ - } - len += sprintf(buffer+len, "\tsq.block_size = %d sq.max_count = %d" - " sq.max_active = %d\n", - sq.block_size, sq.max_count, sq.max_active); - len += sprintf(buffer+len, "\tsq.count = %d sq.rear_size = %d\n", sq.count, - sq.rear_size); - len += sprintf(buffer+len, "\tsq.active = %d sq.syncing = %d\n", - sq.active, sq.syncing); - state.len = len; - return 0; -} - - -static int state_release(struct inode *inode, struct file *file) -{ - state.busy = 0; - MOD_DEC_USE_COUNT; - return 0; -} - - -static ssize_t state_read(struct file *file, char *buf, size_t count, - loff_t *ppos) -{ - int n = state.len - state.ptr; - if (n > count) - n = count; - if (n <= 0) - return 0; - if (copy_to_user(buf, &state.buf[state.ptr], n)) - return -EFAULT; - state.ptr += n; - return n; -} - - -static struct file_operations state_fops = -{ - llseek: sound_lseek, - read: state_read, - open: state_open, - release: state_release, -}; - - -static void __init state_init(void) -{ -#ifndef MODULE - int state_unit; -#endif - state_unit = register_sound_special(&state_fops, SND_DEV_STATUS); - if (state_unit < 0) - return; - state.busy = 0; -} - - -/*** Common stuff ********************************************************/ - -static long long sound_lseek(struct file *file, long long offset, int orig) -{ - return -ESPIPE; -} - - -/*** Config & Setup **********************************************************/ - - -void __init dmasound_init(void) -{ - int has_sound = 0; -#ifdef CONFIG_PPC - struct device_node *np; -#endif - -#if defined(__mc68000__) || defined(CONFIG_APUS) - switch (m68k_machtype) { -#ifdef CONFIG_ATARI - case MACH_ATARI: - if (ATARIHW_PRESENT(PCM_8BIT)) { - if (ATARIHW_PRESENT(CODEC)) - sound.mach = machFalcon; - else if (ATARIHW_PRESENT(MICROWIRE)) - sound.mach = machTT; - else - break; - if ((mfp.int_en_a & mfp.int_mk_a & 0x20) == 0) - has_sound = 1; - else - printk("DMA sound driver: Timer A interrupt already in use\n"); - } - break; - -#endif /* CONFIG_ATARI */ -#ifdef CONFIG_AMIGA - case MACH_AMIGA: - if (AMIGAHW_PRESENT(AMI_AUDIO)) { - sound.mach = machAmiga; - has_sound = 1; - } - break; -#endif /* CONFIG_AMIGA */ - } -#endif /* __mc68000__||CONFIG_APUS */ - -#ifdef CONFIG_PPC - awacs_subframe = 0; - awacs_revision = 0; - np = find_devices("awacs"); - if (np == 0) { - /* - * powermac G3 models have a node called "davbus" - * with a child called "sound". - */ - struct device_node *sound; - np = find_devices("davbus"); - sound = find_devices("sound"); - if (sound != 0 && sound->parent == np) { - unsigned int *prop, l, i; - prop = (unsigned int *) - get_property(sound, "sub-frame", 0); - if (prop != 0 && *prop >= 0 && *prop < 16) - awacs_subframe = *prop; - if (device_is_compatible(sound, "burgundy")) - awacs_revision = AWACS_BURGUNDY; - - /* look for a property saying what sample rates - are available */ - for (i = 0; i < 8; ++i) - awacs_freqs_ok[i] = 0; - prop = (unsigned int *) get_property - (sound, "sample-rates", &l); - if (prop == 0) - prop = (unsigned int *) get_property - (sound, "output-frame-rates", &l); - if (prop != 0) { - for (l /= sizeof(int); l > 0; --l) { - /* sometimes the rate is in the - high-order 16 bits (?) */ - unsigned int r = *prop++; - if (r >= 0x10000) - r >>= 16; - for (i = 0; i < 8; ++i) { - if (r == awacs_freqs[i]) { - awacs_freqs_ok[i] = 1; - break; - } - } - } - } else { - /* assume just 44.1k is OK */ - awacs_freqs_ok[0] = 1; - } - } - } - if (np != NULL && np->n_addrs >= 3 && np->n_intrs >= 3) { - int vol; - sound.mach = machPMac; - has_sound = 1; - - awacs = (volatile struct awacs_regs *) - ioremap(np->addrs[0].address, 0x80); - awacs_txdma = (volatile struct dbdma_regs *) - ioremap(np->addrs[1].address, 0x100); - awacs_rxdma = (volatile struct dbdma_regs *) - ioremap(np->addrs[2].address, 0x100); - - awacs_irq = np->intrs[0].line; - awacs_tx_irq = np->intrs[1].line; - awacs_rx_irq = np->intrs[2].line; - - awacs_tx_cmd_space = kmalloc((numBufs + 4) * sizeof(struct dbdma_cmd), - GFP_KERNEL); - if (awacs_tx_cmd_space == NULL) { - printk(KERN_ERR "DMA sound driver: Not enough buffer memory, driver disabled!\n"); - return; - } - awacs_node = np; -#ifdef CONFIG_PMAC_PBOOK - if (machine_is_compatible("PowerBook1,1") - || machine_is_compatible("AAPL,PowerBook1998")) { - feature_set(np, FEATURE_Sound_CLK_enable); - feature_set(np, FEATURE_Sound_power); - /* Shorter delay will not work */ - mdelay(1000); - } -#endif - awacs_tx_cmds = (volatile struct dbdma_cmd *) - DBDMA_ALIGN(awacs_tx_cmd_space); - - - awacs_rx_cmd_space = kmalloc((numReadBufs + 4) * sizeof(struct dbdma_cmd), - GFP_KERNEL); - if (awacs_rx_cmd_space == NULL) { - printk("DMA sound driver: No memory for input"); - } - awacs_rx_cmds = (volatile struct dbdma_cmd *) - DBDMA_ALIGN(awacs_rx_cmd_space); - - - - awacs_reg[0] = MASK_MUX_CD; - awacs_reg[1] = MASK_LOOPTHRU | MASK_PAROUT; - /* get default volume from nvram */ - vol = (~nvram_read_byte(0x1308) & 7) << 1; - awacs_reg[2] = vol + (vol << 6); - awacs_reg[4] = vol + (vol << 6); - out_le32(&awacs->control, 0x11); - awacs_write(awacs_reg[0] + MASK_ADDR0); - awacs_write(awacs_reg[1] + MASK_ADDR1); - awacs_write(awacs_reg[2] + MASK_ADDR2); - awacs_write(awacs_reg[4] + MASK_ADDR4); - - /* Initialize recent versions of the awacs */ - if (awacs_revision == 0) { - awacs_revision = - (in_le32(&awacs->codec_stat) >> 12) & 0xf; - if (awacs_revision == 3) { - mdelay(100); - awacs_write(0x6000); - mdelay(2); - awacs_write(awacs_reg[1] + MASK_ADDR1); - awacs_enable_amp(100 * 0x101); - } - } - if (awacs_revision >= AWACS_BURGUNDY) - awacs_burgundy_init(); - - /* Initialize beep stuff */ - beep_dbdma_cmd = awacs_tx_cmds + (numBufs + 1); - orig_mksound = kd_mksound; - kd_mksound = awacs_mksound; - beep_buf = (short *) kmalloc(BEEP_BUFLEN * 4, GFP_KERNEL); - if (beep_buf == NULL) - printk(KERN_WARNING "dmasound: no memory for " - "beep buffer\n"); -#ifdef CONFIG_PMAC_PBOOK - pmu_register_sleep_notifier(&awacs_sleep_notifier); -#endif /* CONFIG_PMAC_PBOOK */ - - /* Powerbooks have odd ways of enabling inputs such as - an expansion-bay CD or sound from an internal modem - or a PC-card modem. */ - if (machine_is_compatible("AAPL,3400/2400") - || machine_is_compatible("AAPL,3500")) { - is_pbook_3400 = 1; - /* - * Enable CD and PC-card sound inputs. - * This is done by reading from address - * f301a000, + 0x10 to enable the expansion-bay - * CD sound input, + 0x80 to enable the PC-card - * sound input. The 0x100 enables the SCSI bus - * terminator power. - */ - latch_base = (unsigned char *) ioremap - (0xf301a000, 0x1000); - in_8(latch_base + 0x190); - } else if (machine_is_compatible("PowerBook1,1") - || machine_is_compatible("AAPL,PowerBook1998")) { - struct device_node* mio; - macio_base = 0; - is_pbook_G3 = 1; - for (mio = np->parent; mio; mio = mio->parent) { - if (strcmp(mio->name, "mac-io") == 0 - && mio->n_addrs > 0) { - macio_base = (unsigned char *) ioremap - (mio->addrs[0].address, 0x40); - break; - } - } - /* enable CD sound input */ - if (macio_base) - out_8(macio_base + 0x37, 3); - } - } -#endif /* CONFIG_PPC */ - - if (!has_sound) - return; - - /* Set up sound queue, /dev/audio and /dev/dsp. */ - - /* Set default settings. */ - sq_init(); - - /* Set up /dev/sndstat. */ - state_init(); - - /* Set up /dev/mixer. */ - mixer_init(); - - if (!sound.mach.irqinit()) { - printk(KERN_ERR "DMA sound driver: Interrupt initialization failed\n"); - return; - } -#ifdef MODULE - irq_installed = 1; -#endif - - printk(KERN_INFO "DMA sound driver installed, using %d buffers of %dk.\n", - numBufs, bufSize); - - return; -} - - -static int __init dmasound_setup(char *str) -{ - int ints[6]; - - str = get_options(str, ARRAY_SIZE(ints), ints); - - /* check the bootstrap parameter for "dmasound=" */ - - switch (ints[0]) { - case 3: - if ((ints[3] < 0) || (ints[3] > MAX_CATCH_RADIUS)) - printk("dmasound_setup: illegal catch radius, using default = %d\n", catchRadius); - else - catchRadius = ints[3]; - /* fall through */ - case 2: - if (ints[1] < MIN_BUFFERS) - printk("dmasound_setup: illegal number of buffers, using default = %d\n", numBufs); - else - numBufs = ints[1]; - if (ints[2] < MIN_BUFSIZE || ints[2] > MAX_BUFSIZE) - printk("dmasound_setup: illegal buffer size, using default = %d\n", bufSize); - else - bufSize = ints[2]; - break; - case 0: - break; - default: - printk("dmasound_setup: illegal number of arguments\n"); - return 0; - } - - return 1; -} - -__setup("dmasound=", dmasound_setup); - - -#ifdef MODULE - -int init_module(void) -{ - dmasound_init(); - return 0; -} - - -void cleanup_module(void) -{ - if (irq_installed) { - sound_silence(); - sound.mach.irqcleanup(); - } - -#ifdef CONFIG_PPC - sq_release_read_buffers(); -#endif - sq_release_buffers(); - - if (mixer_unit >= 0) - unregister_sound_mixer(mixer_unit); - if (state_unit >= 0) - unregister_sound_special(state_unit); - if (sq_unit >= 0) - unregister_sound_dsp(sq_unit); -} - -#endif /* MODULE */ diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/sound/dmasound.h linux/drivers/sound/dmasound.h --- v2.3.99-pre3/linux/drivers/sound/dmasound.h Tue Sep 30 08:46:59 1997 +++ linux/drivers/sound/dmasound.h Wed Dec 31 16:00:00 1969 @@ -1,36 +0,0 @@ - -/* linux/drivers/sound/dmasound.h */ - -/* - * Minor numbers for the sound driver. - * - * Unfortunately Creative called the codec chip of SB as a DSP. For this - * reason the /dev/dsp is reserved for digitized audio use. There is a - * device for true DSP processors but it will be called something else. - * In v3.0 it's /dev/sndproc but this could be a temporary solution. - */ - -#define SND_NDEVS 256 /* Number of supported devices */ -#define SND_DEV_CTL 0 /* Control port /dev/mixer */ -#define SND_DEV_SEQ 1 /* Sequencer output /dev/sequencer (FM - synthesizer and MIDI output) */ -#define SND_DEV_MIDIN 2 /* Raw midi access */ -#define SND_DEV_DSP 3 /* Digitized voice /dev/dsp */ -#define SND_DEV_AUDIO 4 /* Sparc compatible /dev/audio */ -#define SND_DEV_DSP16 5 /* Like /dev/dsp but 16 bits/sample */ -#define SND_DEV_STATUS 6 /* /dev/sndstat */ -/* #7 not in use now. Was in 2.4. Free for use after v3.0. */ -#define SND_DEV_SEQ2 8 /* /dev/sequencer, level 2 interface */ -#define SND_DEV_SNDPROC 9 /* /dev/sndproc for programmable devices */ -#define SND_DEV_PSS SND_DEV_SNDPROC - -#define DSP_DEFAULT_SPEED 8000 - -#define ON 1 -#define OFF 0 - -#define MAX_AUDIO_DEV 5 -#define MAX_MIXER_DEV 2 -#define MAX_SYNTH_DEV 3 -#define MAX_MIDI_DEV 6 -#define MAX_TIMER_DEV 3 diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/sound/mad16.c linux/drivers/sound/mad16.c --- v2.3.99-pre3/linux/drivers/sound/mad16.c Fri Mar 10 16:40:44 2000 +++ linux/drivers/sound/mad16.c Mon Mar 27 11:02:54 2000 @@ -791,7 +791,7 @@ mad_write(MC3_PORT, tmp | 0x04); hw_config->driver_use_1 = SB_MIDI_ONLY; - return sb_dsp_detect(hw_config, 0, 0); + return sb_dsp_detect(hw_config, 0, 0, NULL); #else /* assuming all later Mozart cards are identified as * either 82C928 or Mozart. If so, following code attempts diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/sound/sb.h linux/drivers/sound/sb.h --- v2.3.99-pre3/linux/drivers/sound/sb.h Mon Mar 27 08:08:28 2000 +++ linux/drivers/sound/sb.h Mon Mar 27 11:02:54 2000 @@ -70,6 +70,13 @@ typedef struct mixer_def mixer_tab[32][2]; typedef struct mixer_def mixer_ent; +struct sb_module_options +{ + int esstype; /* ESS chip type */ + int acer; /* Do acer notebook init? */ + int sm_games; /* Logitech soundman games? */ +}; + typedef struct sb_devc { int dev; @@ -128,7 +135,10 @@ int input_opened; int midi_broken; void (*midi_input_intr) (int dev, unsigned char data); - void *midi_irq_cookie; /* IRQ cookie for the midi */ + void *midi_irq_cookie; /* IRQ cookie for the midi */ + + struct sb_module_options sbmo; /* Module options */ + } sb_devc; /* @@ -147,7 +157,7 @@ int sb_dsp_reset (sb_devc *devc); void sb_setmixer (sb_devc *devc, unsigned int port, unsigned int value); unsigned int sb_getmixer (sb_devc *devc, unsigned int port); -int sb_dsp_detect (struct address_info *hw_config, int pci, int pciio); +int sb_dsp_detect (struct address_info *hw_config, int pci, int pciio, struct sb_module_options *sbmo); int sb_dsp_init (struct address_info *hw_config); void sb_dsp_unload(struct address_info *hw_config, int sbmpu); int sb_mixer_init(sb_devc *devc); @@ -163,7 +173,6 @@ int sb_audio_open(int dev, int mode); void sb_audio_close(int dev); -extern int acer; extern sb_devc *last_sb; /* From sb_common.c */ diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/sound/sb_card.c linux/drivers/sound/sb_card.c --- v2.3.99-pre3/linux/drivers/sound/sb_card.c Mon Mar 27 08:08:28 2000 +++ linux/drivers/sound/sb_card.c Mon Mar 27 11:02:55 2000 @@ -32,6 +32,10 @@ * 13-03-2000 Added some more cards, thanks to Torsten Werner. * Removed joystick and wavetable code, there are better places for them. * Code cleanup plus some fixes. + * Alessandro Zummo + * + * 26-03-2000 Fixed acer, esstype and sm_games module options. + * Alessandro Zummo * */ @@ -51,6 +55,22 @@ extern void *smw_free; +/* + * Note DMA2 of -1 has the right meaning in the SB16 driver as well + * as here. It will cause either an error if it is needed or a fallback + * to the 8bit channel. + */ + +static int __initdata mpu_io = 0; +static int __initdata io = -1; +static int __initdata irq = -1; +static int __initdata dma = -1; +static int __initdata dma16 = -1; /* Set this for modules that need it */ +static int __initdata type = 0; /* Can set this to a specific card type */ +static int __initdata esstype = 0; /* ESS chip type */ +static int __initdata acer = 0; /* Do acer notebook init? */ +static int __initdata sm_games = 0; /* Logitech soundman games? */ + static void __init attach_sb_card(struct address_info *hw_config) { if(!sb_dsp_init(hw_config)) @@ -60,6 +80,8 @@ static int __init probe_sb(struct address_info *hw_config) { + struct sb_module_options sbmo; + if (hw_config->io_base == -1 || hw_config->dma == -1 || hw_config->irq == -1) { printk(KERN_ERR "sb_card: I/O, IRQ, and DMA are mandatory\n"); @@ -127,14 +149,21 @@ } #endif - /* This is useless since is done by sb_dsp_detect - azummo */ + /* This is useless since it is done by sb_dsp_detect - azummo */ if (check_region(hw_config->io_base, 16)) { printk(KERN_ERR "sb_card: I/O port 0x%x is already in use\n\n", hw_config->io_base); return 0; } - return sb_dsp_detect(hw_config, 0, 0); + + /* Setup extra module options */ + + sbmo.acer = acer; + sbmo.sm_games = sm_games; + sbmo.esstype = esstype; + + return sb_dsp_detect(hw_config, 0, 0, &sbmo); } static void __exit unload_sb(struct address_info *hw_config) @@ -143,25 +172,11 @@ sb_dsp_unload(hw_config, sbmpu); } -extern int esstype; /* ESS chip type */ - static struct address_info cfg; static struct address_info cfg_mpu; struct pci_dev *sb_dev = NULL, *mpu_dev = NULL; -/* - * Note DMA2 of -1 has the right meaning in the SB16 driver as well - * as here. It will cause either an error if it is needed or a fallback - * to the 8bit channel. - */ - -static int __initdata mpu_io = 0; -static int __initdata io = -1; -static int __initdata irq = -1; -static int __initdata dma = -1; -static int __initdata dma16 = -1; /* Set this for modules that need it */ -static int __initdata type = 0; /* Can set this to a specific card type */ #if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/sound/sb_common.c linux/drivers/sound/sb_common.c --- v2.3.99-pre3/linux/drivers/sound/sb_common.c Mon Mar 27 08:08:28 2000 +++ linux/drivers/sound/sb_common.c Mon Mar 27 11:02:55 2000 @@ -53,14 +53,6 @@ 0, 1, 0, 2, 0, 3, 0, 4 }; -/* Do acer notebook init? */ -int acer = 0; - -/* soundman games? */ -int sm_games = 0; - -extern int esstype; - void *smw_free = NULL; /* @@ -503,12 +495,16 @@ #endif } -int sb_dsp_detect(struct address_info *hw_config, int pci, int pciio) +int sb_dsp_detect(struct address_info *hw_config, int pci, int pciio, struct sb_module_options *sbmo) { sb_devc sb_info; sb_devc *devc = &sb_info; memset((char *) &sb_info, 0, sizeof(sb_info)); /* Zero everything */ + + /* Copy module options in place */ + if(sbmo) memcpy(&devc->sbmo, sbmo, sizeof(struct sb_module_options)); + sb_info.my_mididev = -1; sb_info.my_mixerdev = -1; sb_info.dev = -1; @@ -553,7 +549,7 @@ printk("Yamaha PCI mode.\n"); } - if (acer) + if (devc->sbmo.acer) { cli(); inb(devc->base + 0x09); @@ -1294,10 +1290,6 @@ #endif unload_uart401(hw_config); } - -MODULE_PARM(acer, "i"); -MODULE_PARM(sm_games, "i"); -MODULE_PARM(esstype, "i"); EXPORT_SYMBOL(sb_dsp_init); EXPORT_SYMBOL(sb_dsp_detect); diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/sound/sb_ess.c linux/drivers/sound/sb_ess.c --- v2.3.99-pre3/linux/drivers/sound/sb_ess.c Tue Dec 14 01:27:24 1999 +++ linux/drivers/sound/sb_ess.c Mon Mar 27 11:02:55 2000 @@ -196,8 +196,6 @@ #define ESSTYPE_LIKE20 -1 /* Mimic 2.0 behaviour */ #define ESSTYPE_DETECT 0 /* Mimic 2.0 behaviour */ -int esstype = ESSTYPE_DETECT; /* module parameter in sb_card.c */ - #define SUBMDL_ES1788 0x10 /* Subtype ES1788 for specific handling */ #define SUBMDL_ES1868 0x11 /* Subtype ES1868 for specific handling */ #define SUBMDL_ES1869 0x12 /* Subtype ES1869 for specific handling */ @@ -1066,7 +1064,7 @@ char *chip = NULL; int submodel = -1; - switch (esstype) { + switch (devc->sbmo.esstype) { case ESSTYPE_DETECT: case ESSTYPE_LIKE20: break; @@ -1098,12 +1096,12 @@ submodel = SUBMDL_ES1888; break; default: - printk (KERN_ERR "Invalid esstype=%d specified\n", esstype); + printk (KERN_ERR "Invalid esstype=%d specified\n", devc->sbmo.esstype); return 0; }; if (submodel != -1) { devc->submodel = submodel; - sprintf (modelname, "ES%d", esstype); + sprintf (modelname, "ES%d", devc->sbmo.esstype); chip = modelname; }; if (chip == NULL && (ess_minor & 0x0f) < 8) { @@ -1116,7 +1114,7 @@ * If Nothing detected yet, and we want 2.0 behaviour... * Then let's assume it's ES1688. */ - if (chip == NULL && esstype == ESSTYPE_LIKE20) { + if (chip == NULL && devc->sbmo.esstype == ESSTYPE_LIKE20) { chip = "ES1688"; }; @@ -1185,11 +1183,11 @@ printk ( KERN_INFO "ESS chip %s %s%s\n" , chip - , ( esstype == ESSTYPE_DETECT || esstype == ESSTYPE_LIKE20 + , ( devc->sbmo.esstype == ESSTYPE_DETECT || devc->sbmo.esstype == ESSTYPE_LIKE20 ? "detected" : "specified" ) - , ( esstype == ESSTYPE_LIKE20 + , ( devc->sbmo.esstype == ESSTYPE_LIKE20 ? " (kernel 2.0 compatible)" : "" ) diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/sound/sb_mixer.c linux/drivers/sound/sb_mixer.c --- v2.3.99-pre3/linux/drivers/sound/sb_mixer.c Mon Mar 27 08:08:28 2000 +++ linux/drivers/sound/sb_mixer.c Mon Mar 27 11:02:55 2000 @@ -642,11 +642,10 @@ { char name[32]; int i; - extern int sm_games; sprintf(name, "SB_%d", devc->sbmixnum); - if (sm_games) + if (devc->sbmo.sm_games) devc->levels = load_mixer_volumes(name, smg_default_levels, 1); else devc->levels = load_mixer_volumes(name, sb_default_levels, 1); diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/sound/sound_calls.h linux/drivers/sound/sound_calls.h --- v2.3.99-pre3/linux/drivers/sound/sound_calls.h Tue Mar 7 14:32:26 2000 +++ linux/drivers/sound/sound_calls.h Sun Apr 2 15:45:06 2000 @@ -89,10 +89,3 @@ /* From midi_synth.c */ void do_midi_msg (int synthno, unsigned char *msg, int mlen); - -#ifdef FIXED_LOWLEVEL_SOUND -/* From aedsp16.c */ -int InitAEDSP16_SBPRO(struct address_info *hw_config); -int InitAEDSP16_MSS(struct address_info *hw_config); -int InitAEDSP16_MPU401(struct address_info *hw_config); -#endif diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/sound/sound_core.c linux/drivers/sound/sound_core.c --- v2.3.99-pre3/linux/drivers/sound/sound_core.c Tue Mar 14 19:10:40 2000 +++ linux/drivers/sound/sound_core.c Sun Apr 2 15:38:54 2000 @@ -218,7 +218,7 @@ static struct sound_unit *chains[16]; /** - * register_sound_special + * register_sound_special - register a special sound node * @fops: File operations for the driver * @unit: Unit number to allocate * @@ -288,7 +288,7 @@ EXPORT_SYMBOL(register_sound_special); /** - * register_sound_mixer + * register_sound_mixer - register a mixer device * @fops: File operations for the driver * @dev: Unit number to allocate * @@ -306,7 +306,7 @@ EXPORT_SYMBOL(register_sound_mixer); /** - * register_sound_midi + * register_sound_midi - register a midi device * @fops: File operations for the driver * @dev: Unit number to allocate * @@ -329,7 +329,7 @@ */ /** - * register_sound_dsp + * register_sound_dsp - register a DSP device * @fops: File operations for the driver * @dev: Unit number to allocate * @@ -350,7 +350,7 @@ EXPORT_SYMBOL(register_sound_dsp); /** - * register_sound_synth + * register_sound_synth - register a synth device * @fops: File operations for the driver * @dev: Unit number to allocate * @@ -369,7 +369,7 @@ EXPORT_SYMBOL(register_sound_synth); /** - * unregister_sound_special + * unregister_sound_special - unregister a special sound device * @unit: Unit number to allocate * * Release a sound device that was allocated with register_sound_special. @@ -385,7 +385,7 @@ EXPORT_SYMBOL(unregister_sound_special); /** - * unregister_sound_mixer + * unregister_sound_mixer - unregister a mixer * @unit: Unit number to allocate * * Release a sound device that was allocated with register_sound_mixer. @@ -400,7 +400,7 @@ EXPORT_SYMBOL(unregister_sound_mixer); /** - * unregister_sound_midi + * unregister_sound_midi - unregister a midi device * @unit: Unit number to allocate * * Release a sound device that was allocated with register_sound_midi. @@ -415,7 +415,7 @@ EXPORT_SYMBOL(unregister_sound_midi); /** - * unregister_sound_dsp + * unregister_sound_dsp - unregister a DSP device * @unit: Unit number to allocate * * Release a sound device that was allocated with register_sound_dsp. @@ -433,7 +433,7 @@ EXPORT_SYMBOL(unregister_sound_dsp); /** - * unregister_sound_synth + * unregister_sound_synth - unregister a synth device * @unit: Unit number to allocate * * Release a sound device that was allocated with register_sound_synth. diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/sound/soundcard.c linux/drivers/sound/soundcard.c --- v2.3.99-pre3/linux/drivers/sound/soundcard.c Tue Mar 14 19:10:40 2000 +++ linux/drivers/sound/soundcard.c Sun Apr 2 15:46:00 2000 @@ -46,14 +46,6 @@ #include "soundmodule.h" -#if defined(CONFIG_LOWLEVEL_SOUND) && !defined MODULE -extern void sound_preinit_lowlevel_drivers(void); -extern void sound_init_lowlevel_drivers(void); -#endif - -/* From obsolete legacy.h */ -#define SELECTED_SOUND_OPTIONS 0x0 - struct notifier_block *sound_locker=(struct notifier_block *)0; static int lock_depth = 0; @@ -65,7 +57,6 @@ #endif static int chrdev_registered = 0; -static int is_unloading = 0; /* * Table for permanently allocated memory (used when unloading the module) @@ -80,7 +71,6 @@ int sound_dmap_flag = 0; #endif -static int soundcard_configured = 0; static char dma_alloc_map[MAX_DMA_CHANNELS] = {0}; #define DMA_MAP_UNAVAIL 0 @@ -101,17 +91,14 @@ { int i, n; - for (i = 0; i < num_mixer_volumes; i++) - { - if (strcmp(name, mixer_vols[i].name) == 0) - { + for (i = 0; i < num_mixer_volumes; i++) { + if (strcmp(name, mixer_vols[i].name) == 0) { if (present) mixer_vols[i].num = i; return mixer_vols[i].levels; } } - if (num_mixer_volumes >= MAX_MIXER_DEV) - { + if (num_mixer_volumes >= MAX_MIXER_DEV) { printk(KERN_ERR "Sound: Too many mixers (%s)\n", name); return levels; } @@ -229,26 +216,15 @@ static int sound_open(struct inode *inode, struct file *file) { - int dev, retval; + int dev = MINOR(inode->i_rdev); + int retval; - if (is_unloading) { - /* printk(KERN_ERR "Sound: Driver partially removed. Can't open device\n");*/ - return -EBUSY; - } - dev = MINOR(inode->i_rdev); - if (!soundcard_configured && dev != SND_DEV_CTL && dev != SND_DEV_STATUS) { - /* printk("SoundCard Error: The sound system has not been configured\n");*/ - return -ENXIO; - } DEB(printk("sound_open(dev=%d)\n", dev)); if ((dev >= SND_NDEVS) || (dev < 0)) { /* printk(KERN_ERR "Invalid minor device %d\n", dev);*/ return -ENXIO; } switch (dev & 0x0f) { - case SND_DEV_STATUS: - break; - case SND_DEV_CTL: dev >>= 4; if (dev >= 0 && dev < MAX_MIXER_DEV && mixer_devs[dev] == NULL) { @@ -296,7 +272,6 @@ DEB(printk("sound_release(dev=%d)\n", dev)); switch (dev & 0x0f) { - case SND_DEV_STATUS: case SND_DEV_CTL: break; @@ -470,45 +445,38 @@ dev_class = dev & 0x0f; dev >>= 4; - if (dev_class != SND_DEV_DSP && dev_class != SND_DEV_DSP16 && dev_class != SND_DEV_AUDIO) - { -/* printk("Sound: mmap() not supported for other than audio devices\n");*/ + if (dev_class != SND_DEV_DSP && dev_class != SND_DEV_DSP16 && dev_class != SND_DEV_AUDIO) { + printk(KERN_ERR "Sound: mmap() not supported for other than audio devices\n"); return -EINVAL; } if (vma->vm_flags & VM_WRITE) /* Map write and read/write to the output buf */ dmap = audio_devs[dev]->dmap_out; else if (vma->vm_flags & VM_READ) dmap = audio_devs[dev]->dmap_in; - else - { -/* printk("Sound: Undefined mmap() access\n");*/ + else { + printk(KERN_ERR "Sound: Undefined mmap() access\n"); return -EINVAL; } - if (dmap == NULL) - { -/* printk("Sound: mmap() error. dmap == NULL\n");*/ + if (dmap == NULL) { + printk(KERN_ERR "Sound: mmap() error. dmap == NULL\n"); return -EIO; } - if (dmap->raw_buf == NULL) - { -/* printk("Sound: mmap() called when raw_buf == NULL\n");*/ + if (dmap->raw_buf == NULL) { + printk(KERN_ERR "Sound: mmap() called when raw_buf == NULL\n"); return -EIO; } - if (dmap->mapping_flags) - { -/* printk("Sound: mmap() called twice for the same DMA buffer\n");*/ + if (dmap->mapping_flags) { + printk(KERN_ERR "Sound: mmap() called twice for the same DMA buffer\n"); return -EIO; } - if (vma->vm_pgoff != 0) - { -/* printk("Sound: mmap() offset must be 0.\n");*/ + if (vma->vm_pgoff != 0) { + printk(KERN_ERR "Sound: mmap() offset must be 0.\n"); return -EINVAL; } size = vma->vm_end - vma->vm_start; - if (size != dmap->bytes_in_use) - { + if (size != dmap->bytes_in_use) { printk(KERN_WARNING "Sound: mmap() size = %ld. Should be %d\n", size, dmap->bytes_in_use); } if (remap_page_range(vma->vm_start, virt_to_phys(dmap->raw_buf), @@ -546,19 +514,14 @@ static int create_special_devices(void) { int seq1,seq2; - int sndstat=register_sound_special(&oss_sound_fops, 6); - if(sndstat==-1) - goto bad1; seq1=register_sound_special(&oss_sound_fops, 1); if(seq1==-1) - goto bad2; + goto bad; seq2=register_sound_special(&oss_sound_fops, 8); if(seq2!=-1) return 0; unregister_sound_special(1); -bad2: - unregister_sound_special(6); -bad1: +bad: return -1; } @@ -594,30 +557,27 @@ /* Register/unregister audio entries */ static void soundcard_register_devfs (int do_register) { - char name_buf[32]; - int i, j, num; - - for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) - { - num = (dev_list[i].num == NULL) ? 0 : *dev_list[i].num; - for (j = 0; j < num || j == 0; j++) - { - soundcard_make_name (name_buf, dev_list[i].name, j); - if (do_register) - devfs_register (NULL, name_buf, 0, DEVFS_FL_NONE, - SOUND_MAJOR, dev_list[i].minor+ (j* 0x10), - S_IFCHR | dev_list[i].mode, 0, 0, - &oss_sound_fops, NULL); - else - { - devfs_handle_t de; + char name_buf[32]; + int i, j, num; - de = devfs_find_handle (NULL, name_buf, 0, 0, 0, + for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) { + num = (dev_list[i].num == NULL) ? 0 : *dev_list[i].num; + for (j = 0; j < num || j == 0; j++) { + soundcard_make_name (name_buf, dev_list[i].name, j); + if (do_register) + devfs_register (NULL, name_buf, 0, DEVFS_FL_NONE, + SOUND_MAJOR, dev_list[i].minor+ (j* 0x10), + S_IFCHR | dev_list[i].mode, 0, 0, + &oss_sound_fops, NULL); + else { + devfs_handle_t de; + + de = devfs_find_handle (NULL, name_buf, 0, 0, 0, DEVFS_SPECIAL_CHR, 0); - devfs_unregister (de); - } + devfs_unregister (de); + } + } } - } } #ifdef MODULE @@ -638,10 +598,6 @@ chrdev_registered = 1; #endif - soundcard_configured = 1; - - audio_init_devices(); - soundcard_register_devfs(1); /* register after we know # of devices */ } @@ -650,14 +606,9 @@ static void destroy_special_devices(void) { unregister_sound_special(6); - unregister_sound_special(1); unregister_sound_special(8); } -static int sound[20] = { - 0 -}; - static int dmabuf = 0; static int dmabug = 0; @@ -668,12 +619,12 @@ { int err; +#ifdef CONFIG_PCI if(dmabug) isa_dma_bridge_buggy = dmabug; - +#endif err = create_special_devices(); - if (err) - { + if (err) { printk(KERN_ERR "sound: driver already loaded/included in kernel\n"); return err; } @@ -695,10 +646,8 @@ int i; if (MOD_IN_USE) - { return; - } - remove_proc_entry("sound", NULL); + soundcard_register_devfs (0); if (chrdev_registered) destroy_special_devices(); @@ -708,17 +657,13 @@ sequencer_unload(); for (i = 0; i < MAX_DMA_CHANNELS; i++) - { - if (dma_alloc_map[i] != DMA_MAP_UNAVAIL) - { + if (dma_alloc_map[i] != DMA_MAP_UNAVAIL) { printk(KERN_ERR "Sound: Hmm, DMA%d was left allocated - fixed\n", i); sound_free_dma(i); } - } + for (i = 0; i < sound_nblocks; i++) - { vfree(sound_mem_blocks[i]); - } } #endif @@ -739,16 +684,14 @@ { unsigned long flags; - if (!valid_dma(chn)) - { + if (!valid_dma(chn)) { printk(KERN_ERR "sound_open_dma: Invalid DMA channel %d\n", chn); return 1; } save_flags(flags); cli(); - if (dma_alloc_map[chn] != DMA_MAP_FREE) - { + if (dma_alloc_map[chn] != DMA_MAP_FREE) { printk("sound_open_dma: DMA channel %d busy or not allocated (%d)\n", chn, dma_alloc_map[chn]); restore_flags(flags); return 1; @@ -760,8 +703,7 @@ void sound_free_dma(int chn) { - if (dma_alloc_map[chn] == DMA_MAP_UNAVAIL) - { + if (dma_alloc_map[chn] == DMA_MAP_UNAVAIL) { /* printk( "sound_free_dma: Bad access to DMA channel %d\n", chn); */ return; } @@ -776,8 +718,7 @@ save_flags(flags); cli(); - if (dma_alloc_map[chn] != DMA_MAP_BUSY) - { + if (dma_alloc_map[chn] != DMA_MAP_BUSY) { printk(KERN_ERR "sound_close_dma: Bad access to DMA channel %d\n", chn); restore_flags(flags); return; @@ -799,8 +740,7 @@ { extern unsigned long seq_time; - if (count < 0) - { + if (count < 0) { seq_timer.expires = (-count) + jiffies; add_timer(&seq_timer); return; @@ -879,8 +819,7 @@ * Normalise the lock count by calling the entry directly. We * have to call the module as it owns its own use counter */ - while(ctnotifier_call(bl, 1, 0); ct++; } diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/sound/trix.c linux/drivers/sound/trix.c --- v2.3.99-pre3/linux/drivers/sound/trix.c Tue Mar 7 14:32:26 2000 +++ linux/drivers/sound/trix.c Mon Mar 27 11:02:55 2000 @@ -318,7 +318,7 @@ sb_initialized = 1; hw_config->name = "AudioTrix SB"; - return sb_dsp_detect(hw_config, 0, 0); + return sb_dsp_detect(hw_config, 0, 0, NULL); } static void __init attach_trix_sb(struct address_info *hw_config) diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/sound/via82cxxx_audio.c linux/drivers/sound/via82cxxx_audio.c --- v2.3.99-pre3/linux/drivers/sound/via82cxxx_audio.c Tue Mar 7 14:32:26 2000 +++ linux/drivers/sound/via82cxxx_audio.c Mon Mar 27 11:02:55 2000 @@ -486,7 +486,7 @@ return 0; } DPRINTK("EXIT after sb_dsp_detect\n"); - return sb_dsp_detect(hw_config, 0, 0); + return sb_dsp_detect(hw_config, 0, 0, NULL); } diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/telephony/phonedev.c linux/drivers/telephony/phonedev.c --- v2.3.99-pre3/linux/drivers/telephony/phonedev.c Tue Mar 14 19:10:40 2000 +++ linux/drivers/telephony/phonedev.c Sun Apr 2 15:38:54 2000 @@ -28,6 +28,7 @@ #include #include +#include #define PHONE_NUM_DEVICES 256 @@ -37,6 +38,7 @@ */ static struct phone_device *phone_device[PHONE_NUM_DEVICES]; +static DECLARE_MUTEX(phone_lock); /* * Open a phone device. @@ -45,29 +47,37 @@ static int phone_open(struct inode *inode, struct file *file) { unsigned int minor = MINOR(inode->i_rdev); - int err; + int err = 0; struct phone_device *p; if (minor >= PHONE_NUM_DEVICES) return -ENODEV; + down(&phone_lock); p = phone_device[minor]; if (p == NULL) { char modname[32]; + up(&phone_lock); sprintf(modname, "char-major-%d-%d", PHONE_MAJOR, minor); request_module(modname); + down(&phone_lock); p = phone_device[minor]; if (p == NULL) - return -ENODEV; + { + err=-ENODEV; + goto end; + } } if (p->open) { err = p->open(p, file); /* Tell the device it is open */ if (err) - return err; + goto end; } file->f_op = p->f_op; - return 0; +end: + up(&phone_lock); + return err; } /* @@ -87,14 +97,18 @@ base = unit; end = unit + 1; /* enter the loop at least one time */ } + + down(&phone_lock); for (i = base; i < end; i++) { if (phone_device[i] == NULL) { phone_device[i] = p; p->minor = i; MOD_INC_USE_COUNT; + up(&phone_lock); return 0; } } + up(&phone_lock); return -ENFILE; } @@ -104,9 +118,11 @@ void phone_unregister_device(struct phone_device *pfd) { + down(&phone_lock); if (phone_device[pfd->minor] != pfd) panic("phone: bad unregister"); phone_device[pfd->minor] = NULL; + up(&phone_lock); MOD_DEC_USE_COUNT; } diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/Config.in linux/drivers/usb/Config.in --- v2.3.99-pre3/linux/drivers/usb/Config.in Mon Mar 27 08:08:28 2000 +++ linux/drivers/usb/Config.in Mon Apr 10 22:53:15 2000 @@ -6,6 +6,10 @@ tristate 'Support for USB' CONFIG_USB if [ ! "$CONFIG_USB" = "n" ]; then + bool ' USB verbose debug messages' CONFIG_USB_DEBUG + +comment 'Miscellaneous USB options' + bool ' Preliminary USB device filesystem' CONFIG_USB_DEVICEFS comment 'USB Controllers' if [ "$CONFIG_USB_UHCI_ALT" != "y" ]; then @@ -13,19 +17,13 @@ fi if [ "$CONFIG_USB_UHCI" != "y" ]; then dep_tristate ' UHCI Alternate Driver (JE) support' CONFIG_USB_UHCI_ALT $CONFIG_USB - if [ "$CONFIG_USB_UHCI_ALT" != "n" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then - bool ' UHCI unlink optimizations (EXPERIMENTAL)' CONFIG_USB_UHCI_ALT_UNLINK_OPTIMIZE - fi fi dep_tristate ' OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support' CONFIG_USB_OHCI $CONFIG_USB -comment 'Miscellaneous USB options' - bool ' Preliminary USB device filesystem' CONFIG_USB_DEVICEFS - comment 'USB Devices' dep_tristate ' USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB dep_tristate ' USB Scanner support' CONFIG_USB_SCANNER $CONFIG_USB - dep_tristate ' USB Audio support' CONFIG_USB_AUDIO $CONFIG_USB + dep_tristate ' USB Audio support' CONFIG_USB_AUDIO $CONFIG_USB $CONFIG_SOUND dep_tristate ' USB Modem (CDC ACM) support' CONFIG_USB_ACM $CONFIG_USB dep_tristate ' USB Serial Converter support' CONFIG_USB_SERIAL $CONFIG_USB if [ "$CONFIG_USB_SERIAL" != "n" ]; then @@ -38,9 +36,8 @@ fi bool ' USB Serial Converter verbose debug' CONFIG_USB_SERIAL_DEBUG fi - dep_tristate ' USB CPiA Camera support' CONFIG_USB_CPIA $CONFIG_USB - dep_tristate ' USB IBM (Xirlink) C-it Camera support' CONFIG_USB_IBMCAM $CONFIG_USB - dep_tristate ' USB OV511 Camera support' CONFIG_USB_OV511 $CONFIG_USB + dep_tristate ' USB IBM (Xirlink) C-it Camera support' CONFIG_USB_IBMCAM $CONFIG_USB $CONFIG_VIDEO_DEV + dep_tristate ' USB OV511 Camera support' CONFIG_USB_OV511 $CONFIG_USB $CONFIG_VIDEO_DEV dep_tristate ' USB Kodak DC-2xx Camera support' CONFIG_USB_DC2XX $CONFIG_USB if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then dep_tristate ' USB Mustek MDC800 Digital Camera support (EXPERIMENTAL)' CONFIG_USB_MDC800 $CONFIG_USB @@ -52,12 +49,12 @@ dep_tristate ' USS720 parport driver' CONFIG_USB_USS720 $CONFIG_USB $CONFIG_PARPORT dep_tristate ' DABUSB driver' CONFIG_USB_DABUSB $CONFIG_USB if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - dep_tristate ' PLUSB Prolific USB-Network driver (EXPERIMENTAL)' CONFIG_USB_PLUSB $CONFIG_USB - dep_tristate ' USB ADMtek Pegasus-based device support (EXPERIMENTAL)' CONFIG_USB_PEGASUS $CONFIG_USB + dep_tristate ' PLUSB Prolific USB-Network driver (EXPERIMENTAL)' CONFIG_USB_PLUSB $CONFIG_USB $CONFIG_NET + dep_tristate ' USB ADMtek Pegasus-based device support (EXPERIMENTAL)' CONFIG_USB_PEGASUS $CONFIG_USB $CONFIG_NET dep_tristate ' USB Diamond Rio500 support (EXPERIMENTAL)' CONFIG_USB_RIO500 $CONFIG_USB - dep_tristate ' D-Link USB FM radio support (EXPERIMENTAL)' CONFIG_USB_DSBR $CONFIG_USB + dep_tristate ' D-Link USB FM radio support (EXPERIMENTAL)' CONFIG_USB_DSBR $CONFIG_USB $CONFIG_VIDEO_DEV fi - + comment 'USB HID' dep_tristate ' USB Human Interface Device (HID) support' CONFIG_USB_HID $CONFIG_USB if [ "$CONFIG_USB_HID" != "y" ]; then @@ -69,12 +66,8 @@ dep_tristate ' Keyboard support' CONFIG_INPUT_KEYBDEV $CONFIG_USB dep_tristate ' Mouse support' CONFIG_INPUT_MOUSEDEV $CONFIG_USB if [ "$CONFIG_INPUT_MOUSEDEV" != "n" ]; then - bool ' Mix all mice into one device' CONFIG_INPUT_MOUSEDEV_MIX - bool ' Support for digitizers' CONFIG_INPUT_MOUSEDEV_DIGITIZER - if [ "$CONFIG_INPUT_MOUSEDEV_DIGITIZER" != "n" ]; then - int ' Horizontal screen resolution' CONFIG_INPUT_MOUSEDEV_SCREEN_X 1024 - int ' Vertical screen resolution' CONFIG_INPUT_MOUSEDEV_SCREEN_Y 768 - fi + 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_USB dep_tristate ' Event interface support' CONFIG_INPUT_EVDEV $CONFIG_USB diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/Makefile linux/drivers/usb/Makefile --- v2.3.99-pre3/linux/drivers/usb/Makefile Mon Mar 27 08:08:28 2000 +++ linux/drivers/usb/Makefile Mon Mar 27 14:25:28 2000 @@ -42,7 +42,7 @@ ifeq ($(CONFIG_USB_SERIAL),y) SUB_DIRS += serial - obj-y += serial/serial.o + obj-y += serial/usb-serial.o else ifeq ($(CONFIG_USB_SERIAL),m) MOD_IN_SUB_DIRS += serial @@ -71,7 +71,6 @@ obj-$(CONFIG_USB_ACM) += acm.o obj-$(CONFIG_USB_PRINTER) += printer.o obj-$(CONFIG_USB_AUDIO) += audio.o -obj-$(CONFIG_USB_CPIA) += cpia.o obj-$(CONFIG_USB_IBMCAM) += ibmcam.o obj-$(CONFIG_USB_DC2XX) += dc2xx.o obj-$(CONFIG_USB_MDC800) += mdc800.o diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/acm.c linux/drivers/usb/acm.c --- v2.3.99-pre3/linux/drivers/usb/acm.c Fri Mar 10 16:40:44 2000 +++ linux/drivers/usb/acm.c Wed Apr 5 16:58:38 2000 @@ -52,6 +52,10 @@ #define DEBUG #include +void tty_register_devfs (struct tty_driver *driver, unsigned int flags, + unsigned minor); +void tty_unregister_devfs (struct tty_driver *driver, unsigned minor); + /* * CMSPAR, some architectures can't have space and mark parity. */ @@ -143,6 +147,7 @@ }; static struct usb_driver acm_driver; +static struct tty_driver acm_tty_driver; static struct acm *acm_table[ACM_TTY_MINORS] = { NULL, /* .... */ }; #define ACM_READY(acm) (acm && acm->dev && acm->used) @@ -306,20 +311,19 @@ if (!acm || !acm->used) return; - MOD_DEC_USE_COUNT; - - if (--acm->used) return; - - if (acm->dev) { - acm_set_control(acm, acm->ctrlout = 0); - usb_unlink_urb(&acm->ctrlurb); - usb_unlink_urb(&acm->writeurb); - usb_unlink_urb(&acm->readurb); - return; + if (!--acm->used) { + if (acm->dev) { + acm_set_control(acm, acm->ctrlout = 0); + usb_unlink_urb(&acm->ctrlurb); + usb_unlink_urb(&acm->writeurb); + usb_unlink_urb(&acm->readurb); + } else { + tty_unregister_devfs(&acm_tty_driver, acm->minor); + acm_table[acm->minor] = NULL; + kfree(acm); + } } - - acm_table[acm->minor] = NULL; - kfree(acm); + MOD_DEC_USE_COUNT; } static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count) @@ -572,6 +576,7 @@ usb_driver_claim_interface(&acm_driver, acm->iface + 0, acm); usb_driver_claim_interface(&acm_driver, acm->iface + 1, acm); + tty_register_devfs(&acm_tty_driver, 0, minor); return acm_table[minor] = acm; } @@ -599,6 +604,7 @@ usb_driver_release_interface(&acm_driver, acm->iface + 1); if (!acm->used) { + tty_unregister_devfs(&acm_tty_driver, acm->minor); acm_table[acm->minor] = NULL; kfree(acm); return; @@ -630,14 +636,14 @@ static struct tty_driver acm_tty_driver = { magic: TTY_DRIVER_MAGIC, - driver_name: "usb", - name: "ttyACM", + driver_name: "acm", + name: "usb/acm/%d", major: ACM_TTY_MAJOR, minor_start: 0, num: ACM_TTY_MINORS, type: TTY_DRIVER_TYPE_SERIAL, subtype: SERIAL_TYPE_NORMAL, - flags: TTY_DRIVER_REAL_RAW, + flags: TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS, refcount: &acm_tty_refcount, diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/audio.c linux/drivers/usb/audio.c --- v2.3.99-pre3/linux/drivers/usb/audio.c Fri Mar 10 16:40:44 2000 +++ linux/drivers/usb/audio.c Mon Mar 27 10:23:21 2000 @@ -1395,25 +1395,30 @@ /* --------------------------------------------------------------------- */ -static unsigned int find_format(struct audioformat *afp, unsigned int nr, unsigned int fmt) +static unsigned int find_format(struct audioformat *afp, unsigned int nr, unsigned int fmt, unsigned int rate) { unsigned int i; - /* first find an exact match */ - for (i = 0; i < nr; i++) - if (afp[i].format == fmt) + /* first find an exact match, taking both format and sample rate into account, + but ignore stereo bit */ + for (i = 0; i < nr; i++) { + if (afp[i].format == (fmt & ~AFMT_STEREO) && rate >= afp[i].sratelo && rate <= afp[i].sratehi) return i; + } + /* second find a match with the same stereo/mono and 8bit/16bit property */ for (i = 0; i < nr; i++) if (!AFMT_ISSTEREO(afp[i].format) == !AFMT_ISSTEREO(fmt) && - !AFMT_IS16BIT(afp[i].format) == !AFMT_IS16BIT(fmt)) + !AFMT_IS16BIT(afp[i].format) == !AFMT_IS16BIT(fmt) && + rate >= afp[i].sratelo && rate <= afp[i].sratehi) return i; /* third find a match with the same number of channels */ for (i = 0; i < nr; i++) - if (!AFMT_ISSTEREO(afp[i].format) == !AFMT_ISSTEREO(fmt)) + if (!AFMT_ISSTEREO(afp[i].format) == !AFMT_ISSTEREO(fmt) && + rate >= afp[i].sratelo && rate <= afp[i].sratehi) return i; - /* return anything */ - return 0; + /* return failure */ + return -1; } static int set_format_in(struct usb_audiodev *as) @@ -1432,7 +1437,13 @@ if (u->interface < 0 || u->interface >= config->bNumInterfaces) return 0; iface = &config->interface[u->interface]; - fmtnr = find_format(as->fmtin, as->numfmtin, d->format); + + fmtnr = find_format(as->fmtin, as->numfmtin, d->format, d->srate); + if (fmtnr < 0) { + printk(KERN_ERR "usbaudio: set_format_in(): failed to find desired format/speed combination.\n"); + return -1; + } + fmt = as->fmtin + fmtnr; alts = &iface->altsetting[fmt->altsetting]; u->format = fmt->format; @@ -1513,7 +1524,13 @@ if (u->interface < 0 || u->interface >= config->bNumInterfaces) return 0; iface = &config->interface[u->interface]; - fmtnr = find_format(as->fmtout, as->numfmtout, d->format); + + fmtnr = find_format(as->fmtout, as->numfmtout, d->format, d->srate); + if (fmtnr < 0) { + printk(KERN_ERR "usbaudio: set_format_out(): failed to find desired format/speed combination.\n"); + return -1; + } + fmt = as->fmtout + fmtnr; u->format = fmt->format; alts = &iface->altsetting[fmt->altsetting]; @@ -3330,7 +3347,7 @@ struct usb_interface *iface; unsigned char ifin[USB_MAXINTERFACES], ifout[USB_MAXINTERFACES]; unsigned char *p1; - unsigned int i, j, numifin = 0, numifout = 0; + unsigned int i, j, k, numifin = 0, numifout = 0; if (!(s = kmalloc(sizeof(struct usb_audio_state), GFP_KERNEL))) return NULL; @@ -3377,12 +3394,25 @@ dev->devnum, ctrlif, j); continue; } - if (iface->num_altsetting < 2 || - iface->altsetting[0].bNumEndpoints > 0) { - printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u altsetting 0 not zero bandwidth\n", - dev->devnum, ctrlif); + if (iface->num_altsetting == 0) { + printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u has no working interface.\n", dev->devnum, ctrlif); + continue; + } + if (iface->num_altsetting == 1) { + printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u has only 1 altsetting.\n", dev->devnum, ctrlif); continue; } + if (iface->altsetting[0].bNumEndpoints > 0) { + /* Check all endpoints; should they all have a bandwidth of 0 ? */ + for (k = 0; k < iface->altsetting[0].bNumEndpoints; k++) { + if (iface->altsetting[0].endpoint[k].wMaxPacketSize > 0) { + printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u endpoint %d does not have 0 bandwidth at alt[0]\n", dev->devnum, ctrlif, k); + break; + } + } + if (k < iface->altsetting[0].bNumEndpoints) + continue; + } if (iface->altsetting[1].bNumEndpoints < 1) { printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u has no endpoint\n", dev->devnum, ctrlif, j); @@ -3418,7 +3448,7 @@ p1 = find_csinterface_descriptor(buffer, buflen, p1, OUTPUT_TERMINAL, ctrlif, -1); } - ret: +ret: if (list_empty(&s->audiolist) && list_empty(&s->mixerlist)) { kfree(s); return NULL; diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/audio.h linux/drivers/usb/audio.h --- v2.3.99-pre3/linux/drivers/usb/audio.h Sat Oct 9 11:47:50 1999 +++ linux/drivers/usb/audio.h Mon Mar 27 10:23:21 2000 @@ -30,7 +30,7 @@ #define MAX_FREQ 16 #define MAX_IFACE 8 #define MAX_FORMAT 8 -#define MAX_ALT 8 +#define MAX_ALT 32 /* Sorry, we need quite a few for the Philips webcams */ struct usb_audio_terminal { diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/cpia.c linux/drivers/usb/cpia.c --- v2.3.99-pre3/linux/drivers/usb/cpia.c Fri Mar 10 16:40:44 2000 +++ linux/drivers/usb/cpia.c Wed Dec 31 16:00:00 1969 @@ -1,1425 +0,0 @@ -/* - * USB CPiA Video Camera driver - * - * Supports CPiA based Video Cameras. Many manufacturers use this chipset. - * - * (C) Copyright 1999-2000 Johannes Erdfelt, jerdfelt@valinux.com - * (C) Copyright 1999 Randy Dunlap - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "cpia.h" - -static int debug = 0; -MODULE_PARM(debug, "i"); - -/* Video Size 384 x 288 x 3 bytes for RGB */ -/* 384 because xawtv tries to grab 384 even though we tell it 352 is our max */ -#define MAX_FRAME_SIZE (384 * 288 * 3) - -/*******************************/ -/* Memory management functions */ -/*******************************/ - -#define MDEBUG(x) do { } while(0) /* Debug memory management */ - -static struct usb_driver cpia_driver; - -/* Given PGD from the address space's page table, return the kernel - * virtual mapping of the physical memory mapped at ADR. - */ -static inline unsigned long 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 = page_address(pte_page(pte)) | (adr & (PAGE_SIZE-1)); - } - } - MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret)); - 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); - MDEBUG(printk("uv2b(%lx-->%lx)", adr, ret)); - 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); - 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. - */ -static inline unsigned long kvirt_to_pa(unsigned long adr) -{ - unsigned long va, kva, ret; - - va = VMALLOC_VMADDR(adr); - kva = uvirt_to_kva(pgd_offset_k(va), va); - ret = __pa(kva); - MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret)); - return ret; -} - -static void *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(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; - } - - return mem; -} - -static void 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 = kvirt_to_pa(adr); - mem_map_unreserve(MAP_NR(__va(page))); - adr += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; - } - vfree(mem); -} - -static int usb_cpia_get_version(struct usb_device *dev, void *buf) -{ - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_CPIA_GET_VERSION, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, 0, buf, 4, HZ); -} - -#ifdef NOTUSED -static int usb_cpia_get_pnp_id(struct usb_device *dev, void *buf) -{ - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_CPIA_GET_PNP_ID, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, 0, buf, 6, HZ); -} -#endif - -#ifdef NOTUSED -static int usb_cpia_get_camera_status(struct usb_device *dev, void *buf) -{ - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_CPIA_GET_CAMERA_STATUS, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, 0, buf, 8, HZ); -} -#endif - -static int usb_cpia_goto_hi_power(struct usb_device *dev) -{ - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_CPIA_GOTO_HI_POWER, USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, 0, NULL, 0, HZ); -} - -static int usb_cpia_get_vp_version(struct usb_device *dev, void *buf) -{ - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_CPIA_GET_VP_VERSION, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, 0, buf, 4, HZ); -} - -static int usb_cpia_set_sensor_fps(struct usb_device *dev, int sensorbaserate, int sensorclkdivisor) -{ - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_CPIA_SET_SENSOR_FPS, - USB_TYPE_VENDOR | USB_RECIP_DEVICE, - (sensorbaserate << 8) + sensorclkdivisor, 0, NULL, 0, HZ); -} - -#ifdef NOTUSED -static int usb_cpia_grab_frame(struct usb_device *dev, int streamstartline) -{ - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_CPIA_GRAB_FRAME, USB_TYPE_VENDOR | USB_RECIP_DEVICE, - streamstartline << 8, 0, NULL, 0, HZ); -} -#endif - -static int usb_cpia_upload_frame(struct usb_device *dev, int forceupload) -{ - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_CPIA_UPLOAD_FRAME, USB_TYPE_VENDOR | USB_RECIP_DEVICE, - forceupload, 0, NULL, 0, HZ); -} - -static int usb_cpia_set_grab_mode(struct usb_device *dev, int continuousgrab) -{ - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_CPIA_SET_GRAB_MODE, - USB_TYPE_VENDOR | USB_RECIP_DEVICE, continuousgrab, - 0, NULL, 0, HZ); -} - -static int usb_cpia_set_format(struct usb_device *dev, int size, int subsample, int order) -{ - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_CPIA_SET_FORMAT, - USB_TYPE_VENDOR | USB_RECIP_DEVICE, - (subsample << 8) + size, order, NULL, 0, HZ); -} - -static int usb_cpia_set_roi(struct usb_device *dev, int colstart, int colend, int rowstart, int rowend) -{ - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_CPIA_SET_ROI, - USB_TYPE_VENDOR | USB_RECIP_DEVICE, - (colend << 8) + colstart, (rowend << 8) + rowstart, - NULL, 0, HZ); -} - -static int usb_cpia_set_compression(struct usb_device *dev, int compmode, int decimation) -{ - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_CPIA_SET_COMPRESSION, - USB_TYPE_VENDOR | USB_RECIP_DEVICE, - (decimation << 8) + compmode, 0, NULL, 0, HZ); -} - -#ifdef NOTUSED -static int usb_cpia_set_compression_target(struct usb_device *dev, int target, int targetfr, int targetq) -{ - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_CPIA_SET_COMPRESSION_TARGET, - USB_TYPE_VENDOR | USB_RECIP_DEVICE, - (targetfr << 8) + target, targetq, NULL, 0, HZ); -} -#endif - -#ifdef NOTUSED -static int usb_cpia_initstreamcap(struct usb_device *dev, int skipframes, int streamstartline) -{ - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_CPIA_INIT_STREAM_CAP, - USB_TYPE_VENDOR | USB_RECIP_DEVICE, - (streamstartline << 8) + skipframes, 0, NULL, 0, HZ); -} - -static int usb_cpia_finistreamcap(struct usb_device *dev) -{ - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_CPIA_FINI_STREAM_CAP, - USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, 0, NULL, 0, HZ); -} - -static int usb_cpia_startstreamcap(struct usb_device *dev) -{ - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_CPIA_START_STREAM_CAP, - USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, 0, NULL, 0, HZ); -} - -static int usb_cpia_endstreamcap(struct usb_device *dev) -{ - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_CPIA_END_STREAM_CAP, - USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, 0, NULL, 0, HZ); -} -#endif - -/* How much data is left in the scratch buf? */ -#define scratch_left(x) (cpia->scratchlen - (int)((char *)x - (char *)cpia->scratch)) - -static void cpia_parse_data(struct usb_cpia *cpia) -{ - struct cpia_frame *frame, *pframe; - unsigned char *data = cpia->scratch; - unsigned long left; - long copylen = 0; - - /* Grab the current frame and the previous frame */ - frame = &cpia->frame[cpia->curframe]; - pframe = &cpia->frame[(cpia->curframe - 1 + CPIA_NUMFRAMES) % CPIA_NUMFRAMES]; - - while (1) { - if (!scratch_left(data)) - goto out; - - switch (frame->scanstate) { - case STATE_SCANNING: - { - struct cpia_frame_header *header; - - /* We need at least 2 bytes for the magic value */ - if (scratch_left(data) < 2) - goto out; - - header = (struct cpia_frame_header *)data; - - if (be16_to_cpup(&header->magic) == CPIA_MAGIC) { - frame->scanstate = STATE_HEADER; - break; - } - - /* Woops, lost the header, find the end of the frame */ - if (scratch_left(data) < 4) - goto out; - - /* See if we found the end of the frame */ - while (scratch_left(data) >= 4) { - if (*((__u32 *)data) == 0xFFFFFFFF) { - data += 4; - if (debug >= 1) - printk(KERN_INFO "cpia: EOF while scanning for magic\n"); - goto error; - } - data++; - } - break; - } - case STATE_HEADER: - /* We need at least 64 bytes for the header */ - if (scratch_left(data) < - sizeof(struct cpia_frame_header)) - goto out; - - memcpy(&frame->header, data, - sizeof(struct cpia_frame_header)); - - /* Skip over the header */ - data += sizeof(struct cpia_frame_header); - - frame->hdrwidth = (frame->header.col_end - - frame->header.col_start) * 8; - frame->hdrheight = (frame->header.row_end - - frame->header.row_start) * 4; - if (debug >= 2) { - printk(KERN_DEBUG "cpia: frame size %dx%d\n", - frame->hdrwidth, frame->hdrheight); - printk(KERN_DEBUG "cpia: frame %scompressed\n", - frame->header.comp_enable ? "" : "not "); - } - - frame->scanstate = STATE_LINES; - frame->curline = 0; - break; - - case STATE_LINES: - { - unsigned char *f, *end; - unsigned int len; - int i; - int y, u, y1, v, r, g, b; - - /* We want at least 2 bytes for the length */ - if (scratch_left(data) < 2) - goto out; - - /* Grab the length */ - len = data[0] + (data[1] << 8); - - /* Check to make sure it's nothing outrageous */ - if (len > (frame->hdrwidth * 2) + 1) { - if (debug >= 1) - printk(KERN_DEBUG "cpia: bad length, resynching (expected %d, got %d)\n", (frame->hdrwidth * 2) + 1, len); - goto error; - } - - /* Make sure there's enough data for the entire line */ - if (scratch_left(data + 2) < len) - goto out; - - /* Skip over the length */ - data += 2; - - /* Is the end of the line there */ - if (data[len - 1] != 0xFD) { - if (debug >= 1) - printk(KERN_DEBUG "cpia: lost synch\n"); - goto error; - } - - /* Start at the beginning */ - end = data + len - 1; - - f = frame->data + (frame->width * 3 * frame->curline); - - if (frame->header.comp_enable) { - unsigned char *fp; - - /* We use the previous frame as a reference */ - fp = pframe->data + - (frame->width * 3 * frame->curline); - - while (data < end) { - if (*data & 1) { - /* Compress RLE data */ - i = *data >> 1; - memcpy(f, fp, i * 3); - copylen += (i * 3); - f += (i * 3); - fp += (i * 3); - data++; - } else { - /* Raw data */ - -#define LIMIT(x) ((((x)>0xffffff)?0xff0000:(((x)<=0xffff)?0:(x)&0xff0000))>>16) - -y = *data++ - 16; -u = *data++ - 128; -y1 = *data++ - 16; -v = *data++ - 128; -r = 104635 * v; -g = -25690 * u + -53294 * v; -b = 132278 * u; -y *= 76310; -y1 *= 76310; -*f++ = LIMIT(b + y); *f++ = LIMIT(g + y); *f++ = LIMIT(r + y); -*f++ = LIMIT(b + y1); *f++ = LIMIT(g + y1); *f++ = LIMIT(r + y1); - fp += 6; - copylen += 6; - } - } - } else { - /* Raw data */ - while (data < end) { -y = *data++ - 16; -u = *data++ - 128; -y1 = *data++ - 16; -v = *data++ - 128; -r = 104635 * v; -g = -25690 * u + -53294 * v; -b = 132278 * u; -y *= 76310; -y1 *= 76310; -*f++ = LIMIT(b + y); *f++ = LIMIT(g + y); *f++ = LIMIT(r + y); -*f++ = LIMIT(b + y1); *f++ = LIMIT(g + y1); *f++ = LIMIT(r + y1); -copylen += 6; - } - } - - /* Skip the last byte */ - data++; - - if (++frame->curline >= frame->hdrheight) - goto nextframe; - - break; - } /* end case STATE_LINES */ - } /* end switch (scanstate) */ - } /* end while (1) */ - -nextframe: - if (debug >= 1) - printk(KERN_DEBUG "cpia: marking as success\n"); - - if (scratch_left(data) >= 4 && *((__u32 *)data) == 0xFFFFFFFF) - data += 4; - - frame->grabstate = FRAME_DONE; - - goto wakeup; - -error: - if (debug >= 1) - printk(KERN_DEBUG "cpia: marking as error\n"); - - frame->grabstate = FRAME_ERROR; - - /* Get a fresh frame since this frame may have been important */ - cpia->compress = 0; - - copylen = 0; - -wakeup: - cpia->curframe = -1; - - /* This will cause the process to request another frame. */ - if (waitqueue_active(&frame->wq)) - wake_up_interruptible(&frame->wq); - -out: - /* Grab the remaining */ - left = scratch_left(data); - memmove(cpia->scratch, data, left); - cpia->scratchlen = left; - - /* Update the frame's uncompressed length. */ - frame->scanlength += copylen; -} - -/* - * Make all of the blocks of data contiguous - */ -static int cpia_compress_isochronous(struct usb_cpia *cpia, urb_t *urb) -{ - unsigned char *cdata, *data; - int i, totlen = 0; - - data = cpia->scratch + cpia->scratchlen; - 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; - - if (st && debug >= 1) - printk(KERN_DEBUG "cpia data error: [%d] len=%d, status=%X\n", - i, n, st); - - if ((cpia->scratchlen + n) > SCRATCH_BUF_SIZE) { - printk(KERN_DEBUG "cpia: scratch buf overflow!scr_len: %d, n: %d\n",cpia->scratchlen, n ); - return totlen; - } - - if (n) { - memmove(data, cdata, n); - data += n; - totlen += n; - cpia->scratchlen += n; - } - } - - return totlen; -} - -static void cpia_isoc_irq(struct urb *urb) -{ - int len; - struct usb_cpia *cpia = urb->context; - struct cpia_sbuf *sbuf; - int i; - - if (!cpia->dev) - return; - - if (!cpia->streaming) { - if (debug >= 1) - printk(KERN_DEBUG "cpia: oops, not streaming, but interrupt\n"); - return; - } - - sbuf = &cpia->sbuf[cpia->cursbuf]; - - /* Copy the data received into our scratch buffer */ - len = cpia_compress_isochronous(cpia, urb); - - /* If we don't have a frame we're current working on, complain */ - if (cpia->scratchlen) { - if (cpia->curframe < 0) { - if (debug >= 1) - printk(KERN_DEBUG "cpia: received data, but no frame available\n"); - } else - cpia_parse_data(cpia); - } - - for (i = 0; i < FRAMES_PER_DESC; i++) { - sbuf->urb->iso_frame_desc[i].status = 0; - sbuf->urb->iso_frame_desc[i].actual_length = 0; - } - - /* Move to the next sbuf */ - cpia->cursbuf = (cpia->cursbuf + 1) % CPIA_NUMSBUF; - - return; -} - -static int cpia_init_isoc(struct usb_cpia *cpia) -{ - urb_t *urb; - int fx, err; - - cpia->compress = 0; - cpia->curframe = -1; - cpia->cursbuf = 0; - cpia->scratchlen = 0; - - /* Alternate interface 3 is is the biggest frame size */ - if (usb_set_interface(cpia->dev, cpia->iface, 3) < 0) { - printk(KERN_ERR "usb_set_interface error\n"); - return -EBUSY; - } - - /* We double buffer the Iso lists */ - urb = usb_alloc_urb(FRAMES_PER_DESC); - - if (!urb) { - printk(KERN_ERR "cpia_init_isoc: usb_init_isoc ret %d\n", - 0); - return -ENOMEM; - } - cpia->sbuf[0].urb = urb; - urb->dev = cpia->dev; - urb->context = cpia; - urb->pipe = usb_rcvisocpipe(cpia->dev, 1); - urb->transfer_flags = USB_ISO_ASAP; - urb->transfer_buffer = cpia->sbuf[0].data; - urb->complete = cpia_isoc_irq; - urb->number_of_packets = FRAMES_PER_DESC; - urb->transfer_buffer_length = FRAME_SIZE_PER_DESC * FRAMES_PER_DESC; - for (fx = 0; fx < FRAMES_PER_DESC; fx++) { - urb->iso_frame_desc[fx].offset = FRAME_SIZE_PER_DESC * fx; - urb->iso_frame_desc[fx].length = FRAME_SIZE_PER_DESC; - } - urb = usb_alloc_urb(FRAMES_PER_DESC); - if (!urb) { - printk(KERN_ERR "cpia_init_isoc: usb_init_isoc ret %d\n", - 0); - return -ENOMEM; - } - cpia->sbuf[1].urb = urb; - urb->dev = cpia->dev; - urb->context = cpia; - urb->pipe = usb_rcvisocpipe(cpia->dev, 1); - urb->transfer_flags = USB_ISO_ASAP; - urb->transfer_buffer = cpia->sbuf[1].data; - urb->complete = cpia_isoc_irq; - urb->number_of_packets = FRAMES_PER_DESC; - urb->transfer_buffer_length = FRAME_SIZE_PER_DESC * FRAMES_PER_DESC; - for (fx = 0; fx < FRAMES_PER_DESC; fx++) { - urb->iso_frame_desc[fx].offset = FRAME_SIZE_PER_DESC * fx; - urb->iso_frame_desc[fx].length = FRAME_SIZE_PER_DESC; - } - - cpia->sbuf[1].urb->next = cpia->sbuf[0].urb; - cpia->sbuf[0].urb->next = cpia->sbuf[1].urb; - - err = usb_submit_urb(cpia->sbuf[0].urb); - if (err) - printk(KERN_ERR "cpia_init_isoc: usb_submit_urb(0) ret %d\n", - err); - err = usb_submit_urb(cpia->sbuf[1].urb); - if (err) - printk(KERN_ERR "cpia_init_isoc: usb_submit_urb(1) ret %d\n", - err); - - cpia->streaming = 1; - - return 0; -} - -static void cpia_stop_isoc(struct usb_cpia *cpia) -{ - if (!cpia->streaming || !cpia->dev) - return; - - /* Turn off continuous grab */ - if (usb_cpia_set_grab_mode(cpia->dev, 0) < 0) { - printk(KERN_ERR "cpia_set_grab_mode error\n"); - return /* -EBUSY */; - } - - /* Set packet size to 0 */ - if (usb_set_interface(cpia->dev, cpia->iface, 0) < 0) { - printk(KERN_ERR "usb_set_interface error\n"); - return /* -EINVAL */; - } - - cpia->streaming = 0; - - /* Unschedule all of the iso td's */ - if (cpia->sbuf[1].urb) { - cpia->sbuf[1].urb->next = NULL; - usb_unlink_urb(cpia->sbuf[1].urb); - usb_free_urb(cpia->sbuf[1].urb); - cpia->sbuf[1].urb = NULL; - } - if (cpia->sbuf[0].urb) { - cpia->sbuf[0].urb->next = NULL; - usb_unlink_urb(cpia->sbuf[0].urb); - usb_free_urb(cpia->sbuf[0].urb); - cpia->sbuf[0].urb = NULL; - } -} - -static int cpia_new_frame(struct usb_cpia *cpia, int framenum) -{ - struct cpia_frame *frame; - int width, height; - - if (!cpia->dev) - return -1; - - /* If we're not grabbing a frame right now and the other frame is */ - /* ready to be grabbed into, then use it instead */ - if (cpia->curframe == -1) { - if (cpia->frame[(framenum - 1 + CPIA_NUMFRAMES) % CPIA_NUMFRAMES].grabstate == FRAME_READY) - framenum = (framenum - 1 + CPIA_NUMFRAMES) % CPIA_NUMFRAMES; - } else - return 0; - - frame = &cpia->frame[framenum]; - width = frame->width; - height = frame->height; - - frame->grabstate = FRAME_GRABBING; - frame->scanstate = STATE_SCANNING; - frame->scanlength = 0; /* accumulated in cpia_parse_data() */ - - cpia->curframe = framenum; - - /* Make sure it's not too big */ - if (width > 352) - width = 352; - width = (width / 8) * 8; /* Multiple of 8 */ - - if (height > 288) - height = 288; - height = (height / 4) * 4; /* Multiple of 4 */ - - /* Set the ROI they want */ - if (usb_cpia_set_roi(cpia->dev, 0, width / 8, 0, height / 4) < 0) - return -EBUSY; - - if (usb_cpia_set_compression(cpia->dev, cpia->compress ? - COMP_AUTO : COMP_DISABLED, DONT_DECIMATE) < 0) { - printk(KERN_ERR "cpia_set_compression error\n"); - return -EBUSY; - } - - /* We want a fresh frame every 30 we get */ - cpia->compress = (cpia->compress + 1) % 30; - - /* Grab the frame */ - if (usb_cpia_upload_frame(cpia->dev, WAIT_FOR_NEXT_FRAME) < 0) { - printk(KERN_ERR "cpia_upload_frame error\n"); - return -EBUSY; - } - - return 0; -} - -/* Video 4 Linux API */ -static int cpia_open(struct video_device *dev, int flags) -{ - int err = -EBUSY; - struct usb_cpia *cpia = (struct usb_cpia *)dev; - - down(&cpia->lock); - if (cpia->user) - goto out_unlock; - - cpia->frame[0].grabstate = FRAME_UNUSED; - cpia->frame[1].grabstate = FRAME_UNUSED; - - err = -ENOMEM; - - /* Allocate memory for the frame buffers */ - cpia->fbuf = rvmalloc(2 * MAX_FRAME_SIZE); - if (!cpia->fbuf) - goto open_err_ret; - - cpia->frame[0].data = cpia->fbuf; - cpia->frame[1].data = cpia->fbuf + MAX_FRAME_SIZE; - - cpia->sbuf[0].data = kmalloc (FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL); - if (!cpia->sbuf[0].data) - goto open_err_on0; - - cpia->sbuf[1].data = kmalloc (FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL); - if (!cpia->sbuf[1].data) - goto open_err_on1; - - /* Set default sizes in case IOCTL (VIDIOCMCAPTURE) is not used - * (using read() instead). */ - cpia->frame[0].width = 352; - cpia->frame[0].height = 288; - cpia->frame[0].bytes_read = 0; - cpia->frame[1].width = 352; - cpia->frame[1].height = 288; - cpia->frame[1].bytes_read = 0; - - err = cpia_init_isoc(cpia); - if (err) - goto open_err_on2; - - cpia->user++; - up(&cpia->lock); - - MOD_INC_USE_COUNT; - - return 0; - -open_err_on2: - kfree (cpia->sbuf[1].data); -open_err_on1: - kfree (cpia->sbuf[0].data); -open_err_on0: - rvfree(cpia->fbuf, 2 * MAX_FRAME_SIZE); -open_err_ret: - return err; - -out_unlock: - up(&cpia->lock); - return err; -} - -static void cpia_close(struct video_device *dev) -{ - struct usb_cpia *cpia = (struct usb_cpia *)dev; - - down(&cpia->lock); - cpia->user--; - - MOD_DEC_USE_COUNT; - - cpia_stop_isoc(cpia); - - rvfree(cpia->fbuf, 2 * MAX_FRAME_SIZE); - - kfree(cpia->sbuf[1].data); - kfree(cpia->sbuf[0].data); - - up(&cpia->lock); - - if (!cpia->dev) { - video_unregister_device(&cpia->vdev); - kfree(cpia); - } -} - -static int cpia_init_done(struct video_device *dev) -{ - return 0; -} - -static long cpia_write(struct video_device *dev, const char *buf, unsigned long count, int noblock) -{ - return -EINVAL; -} - -static int cpia_ioctl(struct video_device *dev, unsigned int cmd, void *arg) -{ - struct usb_cpia *cpia = (struct usb_cpia *)dev; - - if (!cpia->dev) - return -EIO; - - switch (cmd) { - case VIDIOCGCAP: - { - struct video_capability b; - - strcpy(b.name, "CPiA USB Camera"); - b.type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE; - b.channels = 1; - b.audios = 0; - b.maxwidth = 352; /* CIF */ - b.maxheight = 288; /* " */ - b.minwidth = 8; - b.minheight = 4; - - if (copy_to_user(arg, &b, sizeof(b))) - return -EFAULT; - - return 0; - } - case VIDIOCGCHAN: - { - struct video_channel v; - - if (copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - if (v.channel != 0) - return -EINVAL; - - v.flags = 0; - v.tuners = 0; - v.type = VIDEO_TYPE_CAMERA; - strcpy(v.name, "Camera"); - - if (copy_to_user(arg, &v, sizeof(v))) - return -EFAULT; - - return 0; - } - case VIDIOCSCHAN: - { - int v; - - if (copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - - if (v != 0) - return -EINVAL; - - return 0; - } - case VIDIOCGPICT: - { - struct video_picture p; - - p.colour = 0x8000; /* Damn British people :) */ - p.hue = 0x8000; - p.brightness = 180 << 8; /* XXX */ - p.contrast = 192 << 8; /* XXX */ - p.whiteness = 105 << 8; /* XXX */ - p.depth = 24; - p.palette = VIDEO_PALETTE_RGB24; - - if (copy_to_user(arg, &p, sizeof(p))) - return -EFAULT; - - return 0; - } - case VIDIOCSPICT: - { - struct video_picture p; - - if (copy_from_user(&p, arg, sizeof(p))) - return -EFAULT; - - 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.height != 288) - return -EINVAL; - if (vw.width != 352) - return -EINVAL; - - cpia->compress = 0; - - return 0; - } - case VIDIOCGWIN: - { - struct video_window vw; - - vw.x = 0; - vw.y = 0; - vw.width = 352; - vw.height = 288; - vw.chromakey = 0; - vw.flags = 30; /* 30 fps */ - - 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 = MAX_FRAME_SIZE * 2; - vm.frames = 2; - vm.offsets[0] = 0; - vm.offsets[1] = 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))) - return -EFAULT; - - if (debug >= 1) - printk(KERN_DEBUG "frame: %d, size: %dx%d, format: %d\n", - vm.frame, vm.width, vm.height, vm.format); - - if (vm.format != VIDEO_PALETTE_RGB24) - return -EINVAL; - - if ((vm.frame != 0) && (vm.frame != 1)) - return -EINVAL; - - if (cpia->frame[vm.frame].grabstate == FRAME_GRABBING) - return -EBUSY; - - /* Don't compress if the size changed */ - if ((cpia->frame[vm.frame].width != vm.width) || - (cpia->frame[vm.frame].height != vm.height)) - cpia->compress = 0; - - cpia->frame[vm.frame].width = vm.width; - cpia->frame[vm.frame].height = vm.height; - - /* Mark it as ready */ - cpia->frame[vm.frame].grabstate = FRAME_READY; - - return cpia_new_frame(cpia, vm.frame); - } - case VIDIOCSYNC: - { - int frame; - - if (copy_from_user((void *)&frame, arg, sizeof(int))) - return -EFAULT; - - if (debug >= 1) - printk(KERN_DEBUG "cpia: syncing to frame %d\n", frame); - - switch (cpia->frame[frame].grabstate) { - case FRAME_UNUSED: - return -EINVAL; - case FRAME_READY: - case FRAME_GRABBING: - case FRAME_ERROR: -redo: - if (!cpia->dev) - return -EIO; - - do { - interruptible_sleep_on(&cpia->frame[frame].wq); - if (signal_pending(current)) - return -EINTR; - } while (cpia->frame[frame].grabstate == FRAME_GRABBING); - - if (cpia->frame[frame].grabstate == FRAME_ERROR) { - int ret; - - if ((ret = cpia_new_frame(cpia, frame)) < 0) - return ret; - goto redo; - } - case FRAME_DONE: - cpia->frame[frame].grabstate = FRAME_UNUSED; - break; - } - - cpia->frame[frame].grabstate = FRAME_UNUSED; - - return 0; - } - 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: - return -EINVAL; - case VIDIOCGTUNER: - case VIDIOCSTUNER: - return -EINVAL; - case VIDIOCGFREQ: - case VIDIOCSFREQ: - return -EINVAL; - case VIDIOCGAUDIO: - case VIDIOCSAUDIO: - return -EINVAL; - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static long cpia_read(struct video_device *dev, char *buf, unsigned long count, int noblock) -{ - struct usb_cpia *cpia = (struct usb_cpia *)dev; - int frmx = -1; - volatile struct cpia_frame *frame; - - if (debug >= 1) - printk(KERN_DEBUG "cpia_read: %ld bytes, noblock=%d\n", count, noblock); - - if (!dev || !buf) - return -EFAULT; - - if (!cpia->dev) - return -EIO; - - /* See if a frame is completed, then use it. */ - if (cpia->frame[0].grabstate >= FRAME_DONE) /* _DONE or _ERROR */ - frmx = 0; - else if (cpia->frame[1].grabstate >= FRAME_DONE)/* _DONE or _ERROR */ - frmx = 1; - - if (noblock && (frmx == -1)) - return -EAGAIN; - - /* If no FRAME_DONE, look for a FRAME_GRABBING state. */ - /* See if a frame is in process (grabbing), then use it. */ - if (frmx == -1) { - if (cpia->frame[0].grabstate == FRAME_GRABBING) - frmx = 0; - else if (cpia->frame[1].grabstate == FRAME_GRABBING) - frmx = 1; - } - - /* If no frame is active, start one. */ - if (frmx == -1) - cpia_new_frame(cpia, frmx = 0); - - frame = &cpia->frame[frmx]; - -restart: - if (!cpia->dev) - return -EIO; - - while (frame->grabstate == FRAME_GRABBING) { - interruptible_sleep_on(&frame->wq); - if (signal_pending(current)) - return -EINTR; - } - - if (frame->grabstate == FRAME_ERROR) { - frame->bytes_read = 0; -printk("cpia_read: errored frame %d\n", cpia->curframe); - if (cpia_new_frame(cpia, frmx)) - printk(KERN_ERR "cpia_read: cpia_new_frame error\n"); - goto restart; - } - - if (debug >= 1) - printk(KERN_DEBUG "cpia_read: frmx=%d, bytes_read=%ld, scanlength=%ld\n", - frmx, frame->bytes_read, frame->scanlength); - - /* copy bytes to user space; we allow for partials reads */ - if ((count + frame->bytes_read) > frame->scanlength) - count = frame->scanlength - frame->bytes_read; - - if (copy_to_user(buf, frame->data + frame->bytes_read, count)) - return -EFAULT; - - frame->bytes_read += count; - if (debug >= 1) - printk(KERN_DEBUG "cpia_read: {copy} count used=%ld, new bytes_read=%ld\n", - count, frame->bytes_read); - - if (frame->bytes_read >= frame->scanlength) { /* All data has been read */ - frame->bytes_read = 0; - - /* Mark it as available to be used again. */ - cpia->frame[frmx].grabstate = FRAME_UNUSED; - if (cpia_new_frame(cpia, frmx ? 0 : 1)) - printk(KERN_ERR "cpia_read: cpia_new_frame returned error\n"); - } - - return count; -} - -static int cpia_mmap(struct video_device *dev, const char *adr, unsigned long size) -{ - struct usb_cpia *cpia = (struct usb_cpia *)dev; - unsigned long start = (unsigned long)adr; - unsigned long page, pos; - - if (!cpia->dev) - return -EIO; - - if (size > (((2 * MAX_FRAME_SIZE) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) - return -EINVAL; - - pos = (unsigned long)cpia->fbuf; - while (size > 0) { - page = 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; -} - -static struct video_device cpia_template = { - "CPiA USB Camera", - VID_TYPE_CAPTURE, - VID_HARDWARE_CPIA, - cpia_open, - cpia_close, - cpia_read, - cpia_write, - NULL, - cpia_ioctl, - cpia_mmap, - cpia_init_done, - NULL, - 0, - 0 -}; - -static int usb_cpia_configure(struct usb_cpia *cpia) -{ - struct usb_device *dev = cpia->dev; - unsigned char version[4]; - - /* Set altsetting 0 */ - if (usb_set_interface(dev, cpia->iface, 0) < 0) { - printk(KERN_ERR "usb_set_interface error\n"); - return -EBUSY; - } - - if (usb_cpia_get_version(dev, version) < 0) { - printk(KERN_ERR "cpia_get_version error\n"); - return -EBUSY; - } - - if (debug >= 1) - printk(KERN_DEBUG "cpia: Firmware v%d.%d, VC Hardware v%d.%d\n", - version[0], version[1], version[2], version[3]); - - memcpy(&cpia->vdev, &cpia_template, sizeof(cpia_template)); - - init_waitqueue_head(&cpia->frame[0].wq); - init_waitqueue_head(&cpia->frame[1].wq); - - if (video_register_device(&cpia->vdev, VFL_TYPE_GRABBER) == -1) { - printk(KERN_ERR "video_register_device failed\n"); - return -EBUSY; - } - - if (usb_cpia_goto_hi_power(dev) < 0) { - printk(KERN_ERR "cpia_goto_hi_power error\n"); - goto error; - } - - if (usb_cpia_get_vp_version(dev, version) < 0) { - printk(KERN_ERR "cpia_get_vp_version error\n"); - goto error; - } - - if (debug >= 1) { - printk(KERN_DEBUG "cpia: VP v%d rev %d\n", version[0], version[1]); - printk(KERN_DEBUG "cpia: Camera Head ID %04X\n", (version[3] << 8) + version[2]); - } - - /* Turn on continuous grab */ - if (usb_cpia_set_grab_mode(dev, 1) < 0) { - printk(KERN_ERR "cpia_set_grab_mode error\n"); - goto error; - } - - /* Set up the sensor to be 30fps */ - if (usb_cpia_set_sensor_fps(dev, 1, 0) < 0) { - printk(KERN_ERR "cpia_set_sensor_fps error\n"); - goto error; - } - - /* Set video into CIF mode, and order into YUYV mode */ - if (usb_cpia_set_format(dev, FORMAT_CIF, FORMAT_422, - FORMAT_YUYV) < 0) { - printk(KERN_ERR "cpia_set_format error\n"); - goto error; - } - - /* Turn off compression */ - if (usb_cpia_set_compression(dev, COMP_DISABLED, DONT_DECIMATE) < 0) { - printk(KERN_ERR "cpia_set_compression error\n"); - goto error; - } - - cpia->compress = 0; - - return 0; - -error: - video_unregister_device(&cpia->vdev); - usb_driver_release_interface(&cpia_driver, - &dev->actconfig->interface[0]); - - kfree(cpia); - - return -EBUSY; -} - -static void * cpia_probe(struct usb_device *dev, unsigned int ifnum) -{ - struct usb_interface_descriptor *interface; - struct usb_cpia *cpia; - - /* We don't handle multi-config cameras */ - if (dev->descriptor.bNumConfigurations != 1) - return NULL; - - interface = &dev->actconfig->interface[ifnum].altsetting[0]; - - /* Is it a CPiA? */ - if (dev->descriptor.idVendor != 0x0553) - return NULL; - if (dev->descriptor.idProduct != 0x0002) - return NULL; - - /* Checking vendor/product should be enough, but what the hell */ - if (interface->bInterfaceClass != 0xFF) - return NULL; - if (interface->bInterfaceSubClass != 0x00) - return NULL; - - /* We found a CPiA */ - printk(KERN_INFO "USB CPiA camera found\n"); - - if ((cpia = kmalloc(sizeof(*cpia), GFP_KERNEL)) == NULL) { - printk(KERN_ERR "couldn't kmalloc cpia struct\n"); - return NULL; - } - - memset(cpia, 0, sizeof(*cpia)); - - cpia->dev = dev; - cpia->iface = interface->bInterfaceNumber; - - if (!usb_cpia_configure(cpia)) { - cpia->user=0; - init_MUTEX(&cpia->lock); /* to 1 == available */ - - return cpia; - } else - return NULL; -} - -static void cpia_disconnect(struct usb_device *dev, void *ptr) -{ - struct usb_cpia *cpia = (struct usb_cpia *) ptr; - - /* We don't want people trying to open up the device */ - if (!cpia->user) - video_unregister_device(&cpia->vdev); - - usb_driver_release_interface(&cpia_driver, - &cpia->dev->actconfig->interface[0]); - - cpia->dev = NULL; - cpia->frame[0].grabstate = FRAME_ERROR; - cpia->frame[1].grabstate = FRAME_ERROR; - cpia->curframe = -1; - - /* This will cause the process to request another frame. */ - if (waitqueue_active(&cpia->frame[0].wq)) - wake_up_interruptible(&cpia->frame[0].wq); - - if (waitqueue_active(&cpia->frame[1].wq)) - wake_up_interruptible(&cpia->frame[1].wq); - - cpia->streaming = 0; - - /* Unschedule all of the iso td's */ - if (cpia->sbuf[1].urb) { - cpia->sbuf[1].urb->next = NULL; - usb_unlink_urb(cpia->sbuf[1].urb); - usb_free_urb(cpia->sbuf[1].urb); - cpia->sbuf[1].urb = NULL; - } - if (cpia->sbuf[0].urb) { - cpia->sbuf[0].urb->next = NULL; - usb_unlink_urb(cpia->sbuf[0].urb); - usb_free_urb(cpia->sbuf[0].urb); - cpia->sbuf[0].urb = NULL; - } - - /* Free the memory */ - if (!cpia->user) - kfree(cpia); -} - -static struct usb_driver cpia_driver = { - "cpia", - cpia_probe, - cpia_disconnect, - { NULL, NULL } -}; - -int usb_cpia_init(void) -{ - return usb_register(&cpia_driver); -} - -void usb_cpia_cleanup(void) -{ - usb_deregister(&cpia_driver); -} - -#ifdef MODULE -int init_module(void) -{ - return usb_cpia_init(); -} - -void cleanup_module(void) -{ - usb_cpia_cleanup(); -} -#endif diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/cpia.h linux/drivers/usb/cpia.h --- v2.3.99-pre3/linux/drivers/usb/cpia.h Mon Dec 20 18:48:22 1999 +++ linux/drivers/usb/cpia.h Wed Dec 31 16:00:00 1969 @@ -1,205 +0,0 @@ -#ifndef __LINUX_CPIA_H -#define __LINUX_CPIA_H - -#include - -#define USB_REQ_CPIA_GET_VERSION 0x01 -#define USB_REQ_CPIA_GET_PNP_ID 0x02 -#define USB_REQ_CPIA_GET_CAMERA_STATUS 0x03 -#define USB_REQ_CPIA_GOTO_HI_POWER 0x04 -#define USB_REQ_CPIA_GOTO_LO_POWER 0x05 -/* No 0x06 */ -#define USB_REQ_CPIA_GOTO_SUSPEND 0x07 -#define USB_REQ_CPIA_GOTO_PASS_THROUGH 0x08 -/* No 0x09 */ -#define USB_REQ_CPIA_MODIFY_CAMERA_STATUS 0x0A - -#define USB_REQ_CPIA_READ_VC_REGS 0x21 -#define USB_REQ_CPIA_WRITE_BC_REG 0x22 -#define USB_REQ_CPIA_READ_MC_PORTS 0x23 -#define USB_REQ_CPIA_WRITE_MC_PORT 0x24 -#define USB_REQ_CPIA_SET_BAUD_RATE 0x25 -#define USB_REQ_CPIA_SET_ECP_TIMING 0x26 -#define USB_REQ_CPIA_READ_IDATA 0x27 -#define USB_REQ_CPIA_WRITE_IDATA 0x28 -#define USB_REQ_CPIA_GENERIC_CALL 0x29 -#define USB_REQ_CPIA_I2CSTART 0x2A -#define USB_REQ_CPIA_I2CSTOP 0x2B -#define USB_REQ_CPIA_I2CWRITE 0x2C -#define USB_REQ_CPIA_I2CREAD 0x2D - -#define USB_REQ_CPIA_GET_VP_VERSION 0xA1 -#define USB_REQ_CPIA_SET_COLOUR_PARAMS 0xA3 -#define USB_REQ_CPIA_SET_EXPOSURE 0xA4 -/* No 0xA5 */ -#define USB_REQ_CPIA_SET_COLOUR_BALANCE 0xA6 -#define USB_REQ_CPIA_SET_SENSOR_FPS 0xA7 -#define USB_REQ_CPIA_SET_VP_DEFAULTS 0xA8 -#define USB_REQ_CPIA_SET_APCOR 0xA9 -#define USB_REQ_CPIA_SET_FLICKER_CTRL 0xAA -#define USB_REQ_CPIA_SET_VL_OFFSET 0xAB - -#define USB_REQ_CPIA_GET_COLOUR_PARAMETERS 0xB0 -#define USB_REQ_CPIA_GET_COLOUR_BALANCE 0xB1 -#define USB_REQ_CPIA_GET_EXPOSURE 0xB2 -#define USB_REQ_CPIA_SET_SENSOR_MATRIX 0xB3 - -#define USB_REQ_CPIA_COLOUR_BARS 0xBD -#define USB_REQ_CPIA_READ_VP_REGS 0xBE -#define USB_REQ_CPIA_WRITE_VP_REGS 0xBF - -#define USB_REQ_CPIA_GRAB_FRAME 0xC1 -#define USB_REQ_CPIA_UPLOAD_FRAME 0xC2 -#define WAIT_FOR_NEXT_FRAME 0 -#define FORCE_FRAME_UPLOAD 1 -#define USB_REQ_CPIA_SET_GRAB_MODE 0xC3 -#define USB_REQ_CPIA_INIT_STREAM_CAP 0xC4 -#define USB_REQ_CPIA_FINI_STREAM_CAP 0xC5 -#define USB_REQ_CPIA_START_STREAM_CAP 0xC6 -#define USB_REQ_CPIA_END_STREAM_CAP 0xC7 -#define USB_REQ_CPIA_SET_FORMAT 0xC8 -#define FORMAT_QCIF 0 -#define FORMAT_CIF 1 -#define FORMAT_YUYV 0 -#define FORMAT_UYVY 1 -#define FORMAT_420 0 -#define FORMAT_422 1 -#define USB_REQ_CPIA_SET_ROI 0xC9 -#define USB_REQ_CPIA_SET_COMPRESSION 0xCA -#define COMP_DISABLED 0 -#define COMP_AUTO 1 -#define COMP_MANUAL 2 -#define DONT_DECIMATE 0 -#define DECIMATE 1 -#define USB_REQ_CPIA_SET_COMPRESSION_TARGET 0xCB -#define TARGET_QUALITY 0 -#define TARGET_FRAMERATE 1 -#define USB_REQ_CPIA_SET_YUV_THRESH 0xCC -#define USB_REQ_CPIA_SET_COMPRESSION_PARAMS 0xCD -#define USB_REQ_CPIA_DISCARD_FRAME 0xCE - -#define USB_REQ_CPIA_OUTPUT_RS232 0xE1 -#define USB_REQ_CPIA_ABORT_PROCESS 0xE4 -#define USB_REQ_CPIA_SET_DRAM_PAGE 0xE5 -#define USB_REQ_CPIA_START_DRAM_UPLOAD 0xE6 -#define USB_REQ_CPIA_START_DUMMY_STREAM 0xE8 -#define USB_REQ_CPIA_ABORT_STREAM 0xE9 -#define USB_REQ_CPIA_DOWNLOAD_DRAM 0xEA -/* #define USB_REQ_CPIA_NULL_CMD 0x?? */ - -#define STREAM_BUF_SIZE (PAGE_SIZE * 4) -/* #define STREAM_BUF_SIZE (FRAMES_PER_DESC * FRAME_SIZE_PER_DESC) */ - -#define SCRATCH_BUF_SIZE (STREAM_BUF_SIZE * 2) - -#define FRAMES_PER_DESC 10 -#define FRAME_SIZE_PER_DESC 960 /* Shouldn't be hardcoded */ - -enum { - STATE_SCANNING, /* Scanning for start */ - STATE_HEADER, /* Parsing header */ - STATE_LINES, /* Parsing lines */ -}; - -#define CPIA_MAGIC 0x1968 -struct cpia_frame_header { - __u16 magic; /* 0 - 1 */ - __u16 timestamp; /* 2 - 3 */ - __u16 unused; /* 4 - 5 */ - __u16 timestamp1; /* 6 - 7 */ - __u8 unused1[8]; /* 8 - 15 */ - __u8 video_size; /* 16 0 = QCIF, 1 = CIF */ - __u8 sub_sample; /* 17 0 = 4:2:0, 1 = 4:2:2 */ - __u8 yuv_order; /* 18 0 = YUYV, 1 = UYVY */ - __u8 unused2[5]; /* 19 - 23 */ - __u8 col_start; /* 24 */ - __u8 col_end; /* 25 */ - __u8 row_start; /* 26 */ - __u8 row_end; /* 27 */ - __u8 comp_enable; /* 28 0 = non compressed, 1 = compressed */ - __u8 decimation; /* 29 0 = no decimation, 1 = decimation */ - __u8 y_thresh; /* 30 */ - __u8 uv_thresh; /* 31 */ - __u8 system_state; /* 32 */ - __u8 grab_state; /* 33 */ - __u8 stream_state; /* 34 */ - __u8 fatal_error; /* 35 */ - __u8 cmd_error; /* 36 */ - __u8 debug_flags; /* 37 */ - __u8 camera_state_7; /* 38 */ - __u8 camera_state_8; /* 39 */ - __u8 cr_achieved; /* 40 */ - __u8 fr_achieved; /* 41 */ - __u8 unused3[22]; /* 42 - 63 */ -}; - -struct usb_device; - -struct cpia_sbuf { - char *data; - urb_t *urb; -}; - -enum { - FRAME_UNUSED, /* Unused (no MCAPTURE) */ - FRAME_READY, /* Ready to start grabbing */ - FRAME_GRABBING, /* In the process of being grabbed into */ - FRAME_DONE, /* Finished grabbing, but not been synced yet */ - FRAME_ERROR, /* Something bad happened while processing */ -}; - -struct cpia_frame { - char *data; /* Frame buffer */ - - struct cpia_frame_header header; /* Header from stream */ - - int width; /* Width application is expecting */ - int height; /* Height */ - - int hdrwidth; /* Width the frame actually is */ - int hdrheight; /* Height */ - - volatile int grabstate; /* State of grabbing */ - int scanstate; /* State of scanning */ - - int curline; /* Line of frame we're working on */ - - long scanlength; /* uncompressed, raw data length of frame */ - long bytes_read; /* amount of scanlength that has been read from *data */ - - wait_queue_head_t wq; /* Processes waiting */ -}; - -#define CPIA_NUMFRAMES 2 -#define CPIA_NUMSBUF 2 - -struct usb_cpia { - struct video_device vdev; - - /* Device structure */ - struct usb_device *dev; - - unsigned char iface; - - struct semaphore lock; - int user; /* user count for exclusive use */ - - int streaming; /* Are we streaming Isochronous? */ - int grabbing; /* Are we grabbing? */ - - int compress; /* Should the next frame be compressed? */ - - char *fbuf; /* Videodev buffer area */ - - int curframe; - struct cpia_frame frame[CPIA_NUMFRAMES]; /* Double buffering */ - - int cursbuf; /* Current receiving sbuf */ - struct cpia_sbuf sbuf[CPIA_NUMSBUF]; /* Double buffering */ - - /* Scratch space from the Isochronous pipe */ - unsigned char scratch[SCRATCH_BUF_SIZE]; - int scratchlen; -}; - -#endif diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/devices.c linux/drivers/usb/devices.c --- v2.3.99-pre3/linux/drivers/usb/devices.c Fri Mar 10 16:40:44 2000 +++ linux/drivers/usb/devices.c Mon Apr 10 22:55:08 2000 @@ -54,9 +54,8 @@ #include #include #include +#include #include - -#include "usbdevice_fs.h" #define MAX_TOPO_LEVEL 6 diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/devio.c linux/drivers/usb/devio.c --- v2.3.99-pre3/linux/drivers/usb/devio.c Fri Mar 10 16:40:44 2000 +++ linux/drivers/usb/devio.c Mon Apr 10 22:55:08 2000 @@ -41,9 +41,9 @@ #include #include #include +#include #include -#include "usbdevice_fs.h" struct async { struct list_head asynclist; diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/drivers.c linux/drivers/usb/drivers.c --- v2.3.99-pre3/linux/drivers/usb/drivers.c Sun Mar 19 18:35:30 2000 +++ linux/drivers/usb/drivers.c Mon Apr 10 22:55:08 2000 @@ -37,10 +37,8 @@ #include #include #include +#include #include - -#include "usbdevice_fs.h" - /*****************************************************************/ diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/evdev.c linux/drivers/usb/evdev.c --- v2.3.99-pre3/linux/drivers/usb/evdev.c Sat Feb 26 22:31:50 2000 +++ linux/drivers/usb/evdev.c Mon Apr 10 22:53:15 2000 @@ -29,9 +29,9 @@ */ #define EVDEV_MINOR_BASE 64 +#define EVDEV_MINORS 32 #define EVDEV_BUFFER_SIZE 64 -#include #include #include #include @@ -39,11 +39,12 @@ #include struct evdev { - char name[32]; int used; + int open; + int minor; struct input_handle handle; - struct miscdevice misc; wait_queue_head_t wait; + devfs_handle_t devfs; struct evdev_list *list; }; @@ -56,8 +57,7 @@ struct evdev_list *next; }; -static unsigned long evdev_miscbits = 0; -static struct evdev *evdev_base[BITS_PER_LONG]; +static struct evdev *evdev_table[EVDEV_MINORS] = { NULL, /* ... */ }; static void evdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) { @@ -99,10 +99,13 @@ while (*listptr && (*listptr != list)) listptr = &((*listptr)->next); *listptr = (*listptr)->next; + + if (!--list->evdev->open) + input_close_device(&list->evdev->handle); if (!--list->evdev->used) { - clear_bit(list->evdev->misc.minor - EVDEV_MINOR_BASE, &evdev_miscbits); - misc_deregister(&list->evdev->misc); + input_unregister_minor(list->evdev->devfs); + evdev_table[list->evdev->minor] = NULL; kfree(list->evdev); } @@ -117,23 +120,28 @@ struct evdev_list *list; int i = MINOR(inode->i_rdev) - EVDEV_MINOR_BASE; - if (i > BITS_PER_LONG || !test_bit(i, &evdev_miscbits)) + if (i > EVDEV_MINORS || !evdev_table[i]) return -ENODEV; - if (!(list = kmalloc(sizeof(struct evdev_list), GFP_KERNEL))) - return -ENOMEM; + MOD_INC_USE_COUNT; + if (!(list = kmalloc(sizeof(struct evdev_list), GFP_KERNEL))) { + MOD_DEC_USE_COUNT; + return -ENOMEM; + } memset(list, 0, sizeof(struct evdev_list)); - list->evdev = evdev_base[i]; - list->next = evdev_base[i]->list; - evdev_base[i]->list = list; + list->evdev = evdev_table[i]; + list->next = evdev_table[i]->list; + evdev_table[i]->list = list; file->private_data = list; list->evdev->used++; - MOD_INC_USE_COUNT; + if (!list->evdev->open++) + input_open_device(&list->evdev->handle); + return 0; } @@ -193,34 +201,81 @@ return 0; } +static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + struct evdev_list *list = file->private_data; + struct evdev *evdev = list->evdev; + struct input_dev *dev = evdev->handle.dev; + + switch (cmd) { + + case EVIOCGVERSION: + return put_user(EV_VERSION, (__u32 *) arg); + case EVIOCGID: + return copy_to_user(&dev->id, (void *) arg, + sizeof(struct input_id)) ? -EFAULT : 0; + default: + + if (_IOC_TYPE(cmd) != 'E' || _IOC_DIR(cmd) != _IOC_READ) + return -EINVAL; + + if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) { + + long *bits = NULL; + int len = 0; + + switch (_IOC_NR(cmd) & EV_MAX) { + case 0: bits = dev->evbit; len = EV_MAX; break; + case EV_KEY: bits = dev->keybit; len = KEY_MAX; break; + case EV_REL: bits = dev->relbit; len = REL_MAX; break; + 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; + default: return -EINVAL; + } + len = NBITS(len) * sizeof(long); + if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); + return copy_to_user((void *) arg, bits, len) ? -EFAULT : len; + } + + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) { + int len = strlen(dev->name) + 1; + if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); + return copy_to_user((char *) arg, dev->name, len) ? -EFAULT : len; + } + } + return -EINVAL; +} + static struct file_operations evdev_fops = { read: evdev_read, write: evdev_write, poll: evdev_poll, open: evdev_open, release: evdev_release, + ioctl: evdev_ioctl, fasync: evdev_fasync, }; -static int evdev_connect(struct input_handler *handler, struct input_dev *dev) +static struct input_handle *evdev_connect(struct input_handler *handler, struct input_dev *dev) { struct evdev *evdev; + int minor; - if (!(evdev = kmalloc(sizeof(struct evdev), GFP_KERNEL))) - return -1; + for (minor = 0; minor < EVDEV_MINORS && evdev_table[minor]; minor++); + if (evdev_table[minor]) { + printk(KERN_ERR "evdev: no more free evdev devices\n"); + return NULL; + } + if (!(evdev = kmalloc(sizeof(struct evdev), GFP_KERNEL))) + return NULL; memset(evdev, 0, sizeof(struct evdev)); init_waitqueue_head(&evdev->wait); - evdev->misc.minor = ffz(evdev_miscbits); - set_bit(evdev->misc.minor, &evdev_miscbits); - evdev_base[evdev->misc.minor] = evdev; - - sprintf(evdev->name, "evdev%d", evdev->misc.minor); - evdev->misc.name = evdev->name; - evdev->misc.minor += EVDEV_MINOR_BASE; - evdev->misc.fops = &evdev_fops; + evdev->minor = minor; + evdev_table[minor] = evdev; evdev->handle.dev = dev; evdev->handle.handler = handler; @@ -228,24 +283,23 @@ evdev->used = 1; - misc_register(&evdev->misc); - input_open_device(&evdev->handle); + evdev->devfs = input_register_minor("event%d", minor, EVDEV_MINOR_BASE); - printk("%s: Event device for input%d on misc%d - /dev/input%d\n", - evdev->name, dev->number, evdev->misc.minor, evdev->misc.minor - EVDEV_MINOR_BASE); + printk("event%d: Event device for input%d\n", minor, dev->number); - return 0; + return &evdev->handle; } static void evdev_disconnect(struct input_handle *handle) { struct evdev *evdev = handle->private; - input_close_device(handle); + if (evdev->open) + input_close_device(handle); if (!--evdev->used) { - clear_bit(evdev->misc.minor - EVDEV_MINOR_BASE, &evdev_miscbits); - misc_deregister(&evdev->misc); + input_unregister_minor(evdev->devfs); + evdev_table[evdev->minor] = NULL; kfree(evdev); } } @@ -254,6 +308,8 @@ event: evdev_event, connect: evdev_connect, disconnect: evdev_disconnect, + fops: &evdev_fops, + minor: EVDEV_MINOR_BASE, }; static int __init evdev_init(void) diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/hid.c linux/drivers/usb/hid.c --- v2.3.99-pre3/linux/drivers/usb/hid.c Mon Mar 27 08:08:28 2000 +++ linux/drivers/usb/hid.c Wed Apr 5 17:02:15 2000 @@ -1288,7 +1288,7 @@ hid_configure_usage(hid, report->field[i], report->field[i]->usage + j); if (k == HID_INPUT_REPORT) { - usb_set_idle(hid->dev, hid->ifnum, report->id, 0); + usb_set_idle(hid->dev, hid->ifnum, 0, report->id); hid_read_report(hid, report); } } diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/hub.c linux/drivers/usb/hub.c --- v2.3.99-pre3/linux/drivers/usb/hub.c Sun Mar 19 18:35:30 2000 +++ linux/drivers/usb/hub.c Tue Apr 11 09:57:43 2000 @@ -6,12 +6,17 @@ * (C) Copyright 1999 Gregory P. Smith */ +#include #include #include #include #include #include -#define DEBUG +#ifdef CONFIG_USB_DEBUG + #define DEBUG +#else + #undef DEBUG +#endif #include #include @@ -609,5 +614,28 @@ usb_deregister(&hub_driver); } /* usb_hub_cleanup() */ +int usb_reset_device(struct usb_device *dev) +{ + struct usb_device *parent = dev->parent; + int i; + + if (!parent) { + err("attempting to reset root hub!"); + return -EINVAL; + } + + for (i = 0; i < parent->maxchild; i++) { + if (parent->children[i] == dev) { + usb_set_port_feature(parent, i + 1, + USB_PORT_FEAT_RESET); + usb_disconnect(&dev); + usb_hub_port_connect_change(parent, i); + + return 0; + } + } + + return -ENOENT; +} diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/ibmcam.c linux/drivers/usb/ibmcam.c --- v2.3.99-pre3/linux/drivers/usb/ibmcam.c Fri Mar 10 16:40:44 2000 +++ linux/drivers/usb/ibmcam.c Sun Apr 2 15:19:56 2000 @@ -58,6 +58,8 @@ #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) static int flags = 0; /* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */ @@ -2238,6 +2240,12 @@ } } +/* + * ibmcam_new_frame() + * + * History: + * 29-Mar-00 Added copying of previous frame into the current one. + */ static int ibmcam_new_frame(struct usb_ibmcam *ibmcam, int framenum) { struct ibmcam_frame *frame; @@ -2258,10 +2266,33 @@ frame->scanstate = STATE_SCANNING; frame->scanlength = 0; /* Accumulated in ibmcam_parse_data() */ ibmcam->curframe = framenum; -#if 0 - /* This provides a "clean" frame but slows things down */ - memset(frame->data, 0, MAX_FRAME_SIZE); -#endif + + /* + * 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 (!(flags & FLAGS_SEPARATE_FRAMES)) { + /* This copies previous frame into this one to mask losses */ + memmove(frame->data, ibmcam->frame[1-framenum].data, MAX_FRAME_SIZE); + } else { + if (flags & FLAGS_CLEAN_FRAMES) { + /* This provides a "clean" frame but slows things down */ + memset(frame->data, 0, MAX_FRAME_SIZE); + } + } switch (videosize) { case VIDEOSIZE_128x96: frame->frmwidth = 128; diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/inode.c linux/drivers/usb/inode.c --- v2.3.99-pre3/linux/drivers/usb/inode.c Tue Mar 14 19:10:40 2000 +++ linux/drivers/usb/inode.c Mon Apr 10 22:55:08 2000 @@ -38,9 +38,8 @@ #include #include #include +#include #include - -#include "usbdevice_fs.h" /* --------------------------------------------------------------------- */ diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/input.c linux/drivers/usb/input.c --- v2.3.99-pre3/linux/drivers/usb/input.c Sat Feb 26 22:31:50 2000 +++ linux/drivers/usb/input.c Mon Apr 10 22:53:15 2000 @@ -35,20 +35,25 @@ MODULE_AUTHOR("Vojtech Pavlik "); -#ifndef MODULE EXPORT_SYMBOL(input_register_device); EXPORT_SYMBOL(input_unregister_device); EXPORT_SYMBOL(input_register_handler); EXPORT_SYMBOL(input_unregister_handler); +EXPORT_SYMBOL(input_register_minor); +EXPORT_SYMBOL(input_unregister_minor); EXPORT_SYMBOL(input_open_device); EXPORT_SYMBOL(input_close_device); EXPORT_SYMBOL(input_event); -#endif + +#define INPUT_MAJOR 13 +#define INPUT_DEVICES 256 static struct input_dev *input_dev = NULL; static struct input_handler *input_handler = NULL; - +static struct input_handler *input_table[8] = { NULL, /* ... */ }; +static devfs_handle_t input_devfs_handle = NULL; static int input_number = 0; +static long input_devices[NBITS(INPUT_DEVICES)] = { 0, /* ... */ }; void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { @@ -142,7 +147,8 @@ */ while (handle) { - handle->handler->event(handle, type, code, value); + if (handle->open) + handle->handler->event(handle, type, code, value); handle = handle->dnext; } } @@ -154,9 +160,48 @@ mod_timer(&dev->timer, jiffies + dev->rep[REP_PERIOD]); } +int input_open_device(struct input_handle *handle) +{ + handle->open++; + if (handle->dev->open) + return handle->dev->open(handle->dev); + return 0; +} + +void input_close_device(struct input_handle *handle) +{ + if (handle->dev->close) + handle->dev->close(handle->dev); + handle->open--; +} + +static void input_link_handle(struct input_handle *handle) +{ + handle->dnext = handle->dev->handle; + handle->hnext = handle->handler->handle; + handle->dev->handle = handle; + handle->handler->handle = handle; +} + +static void input_unlink_handle(struct input_handle *handle) +{ + struct input_handle **handleptr; + + handleptr = &handle->dev->handle; + while (*handleptr && (*handleptr != handle)) + handleptr = &((*handleptr)->dnext); + *handleptr = (*handleptr)->dnext; + + handleptr = &handle->handler->handle; + while (*handleptr && (*handleptr != handle)) + handleptr = &((*handleptr)->hnext); + *handleptr = (*handleptr)->hnext; +} + void input_register_device(struct input_dev *dev) { struct input_handler *handler = input_handler; + struct input_handle *handle; /* * Initialize repeat timer to default values. @@ -172,17 +217,25 @@ * Add the device. */ - MOD_INC_USE_COUNT; - dev->number = input_number++; + if (input_number >= INPUT_DEVICES) { + printk(KERN_WARNING "input: ran out of input device numbers!\n"); + dev->number = input_number; + } else { + dev->number = find_first_zero_bit(input_devices, INPUT_DEVICES); + set_bit(dev->number, input_devices); + } + dev->next = input_dev; input_dev = dev; + input_number++; /* * Notify handlers. */ while (handler) { - handler->connect(handler, dev); + if ((handle = handler->connect(handler, dev))) + input_link_handle(handle); handler = handler->next; } } @@ -203,6 +256,7 @@ */ while (handle) { + input_unlink_handle(handle); handle->handler->disconnect(handle); handle = handle->dnext; } @@ -216,12 +270,22 @@ *devptr = (*devptr)->next; input_number--; - MOD_DEC_USE_COUNT; + + if (dev->number < INPUT_DEVICES) + clear_bit(dev->number, input_devices); } void input_register_handler(struct input_handler *handler) { struct input_dev *dev = input_dev; + struct input_handle *handle; + +/* + * Add minors if needed. + */ + + if (handler->fops != NULL) + input_table[handler->minor >> 5] = handler; /* * Add the handler. @@ -235,7 +299,8 @@ */ while (dev) { - handler->connect(handler, dev); + if ((handle = handler->connect(handler, dev))) + input_link_handle(handle); dev = dev->next; } } @@ -250,6 +315,7 @@ */ while (handle) { + input_unlink_handle(handle); handler->disconnect(handle); handle = handle->hnext; } @@ -263,42 +329,59 @@ *handlerptr = (*handlerptr)->next; +/* + * Remove minors. + */ + + if (handler->fops != NULL) + input_table[handler->minor >> 5] = NULL; } -void input_open_device(struct input_handle *handle) +static int input_open_file(struct inode *inode, struct file *file) { - handle->dnext = handle->dev->handle; - handle->hnext = handle->handler->handle; - handle->dev->handle = handle; - handle->handler->handle = handle; + struct input_handler *handler = input_table[MINOR(inode->i_rdev) >> 5]; - if (handle->dev->open) - handle->dev->open(handle->dev); -} + if (!handler || !handler->fops || !handler->fops->open) + return -ENODEV; -void input_close_device(struct input_handle *handle) -{ - struct input_handle **handleptr; + file->f_op = handler->fops; - if (handle->dev->close) - handle->dev->close(handle->dev); -/* - * Remove from device list of handles. - */ + return handler->fops->open(inode, file); +} - handleptr = &handle->dev->handle; +static struct file_operations input_fops = { + open: input_open_file, +}; - while (*handleptr && (*handleptr != handle)) - handleptr = &((*handleptr)->dnext); - *handleptr = (*handleptr)->dnext; +devfs_handle_t input_register_minor(char *name, int minor, int minor_base) +{ + char devfs_name[16]; + sprintf(devfs_name, name, minor); + return devfs_register(input_devfs_handle, devfs_name, 0, DEVFS_FL_DEFAULT, INPUT_MAJOR, minor + minor_base, + S_IFCHR | S_IRUGO | S_IWUSR, 0, 0, &input_fops, NULL); +} -/* - * Remove from handler list of handles. - */ +void input_unregister_minor(devfs_handle_t handle) +{ + devfs_unregister(handle); +} - handleptr = &handle->handler->handle; +static int __init input_init(void) +{ + if (devfs_register_chrdev(INPUT_MAJOR, "input", &input_fops)) { + printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR); + return -EBUSY; + } + input_devfs_handle = devfs_mk_dir(NULL, "input", 5, NULL); + return 0; +} - while (*handleptr && (*handleptr != handle)) - handleptr = &((*handleptr)->hnext); - *handleptr = (*handleptr)->hnext; +static void __exit input_exit(void) +{ + devfs_unregister(input_devfs_handle); + if (devfs_unregister_chrdev(INPUT_MAJOR, "input")) + printk(KERN_ERR "input: can't unregister char major %d", INPUT_MAJOR); } + +module_init(input_init); +module_exit(input_exit); diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/joydev.c linux/drivers/usb/joydev.c --- v2.3.99-pre3/linux/drivers/usb/joydev.c Sun Mar 19 18:35:30 2000 +++ linux/drivers/usb/joydev.c Mon Apr 10 22:53:15 2000 @@ -45,15 +45,18 @@ #include #include -#define JOYDEV_MAJOR 15 +#define JOYDEV_MINOR_BASE 0 +#define JOYDEV_MINORS 32 #define JOYDEV_BUFFER_SIZE 64 struct joydev { - char name[32]; int used; - struct input_handle handle; + int open; int minor; + char name[32]; + struct input_handle handle; wait_queue_head_t wait; + devfs_handle_t devfs; struct joydev *next; struct joydev_list *list; struct js_corr corr[ABS_MAX]; @@ -76,11 +79,10 @@ struct joydev_list *next; }; -static unsigned long joydev_minors = 0; -static struct joydev *joydev_base[BITS_PER_LONG]; +static struct joydev *joydev_table[JOYDEV_MINORS]; MODULE_AUTHOR("Vojtech Pavlik "); -MODULE_SUPPORTED_DEVICE("js"); +MODULE_SUPPORTED_DEVICE("input/js"); static int joydev_correct(int value, struct js_corr *corr) { @@ -164,9 +166,13 @@ while (*listptr && (*listptr != list)) listptr = &((*listptr)->next); *listptr = (*listptr)->next; + + if (!--list->joydev->open) + input_close_device(&list->joydev->handle); if (!--list->joydev->used) { - clear_bit(list->joydev->minor, &joydev_minors); + input_unregister_minor(list->joydev->devfs); + joydev_table[list->joydev->minor] = NULL; kfree(list->joydev); } @@ -179,28 +185,30 @@ static int joydev_open(struct inode *inode, struct file *file) { struct joydev_list *list; - int i = MINOR(inode->i_rdev); + int i = MINOR(inode->i_rdev) - JOYDEV_MINOR_BASE; - if (MAJOR(inode->i_rdev) != JOYSTICK_MAJOR) - return -EINVAL; - - if (i > BITS_PER_LONG || !test_bit(i, &joydev_minors)) + if (i > JOYDEV_MINORS || !joydev_table[i]) return -ENODEV; - if (!(list = kmalloc(sizeof(struct joydev_list), GFP_KERNEL))) - return -ENOMEM; + MOD_INC_USE_COUNT; + if (!(list = kmalloc(sizeof(struct joydev_list), GFP_KERNEL))) { + MOD_DEC_USE_COUNT; + return -ENOMEM; + } memset(list, 0, sizeof(struct joydev_list)); - list->joydev = joydev_base[i]; - list->next = joydev_base[i]->list; - joydev_base[i]->list = list; + list->joydev = joydev_table[i]; + list->next = joydev_table[i]->list; + joydev_table[i]->list = list; file->private_data = list; list->joydev->used++; - MOD_INC_USE_COUNT; + if (!list->joydev->open++) + input_open_device(&list->joydev->handle); + return 0; } @@ -370,30 +378,33 @@ fasync: joydev_fasync, }; -static int joydev_connect(struct input_handler *handler, struct input_dev *dev) +static struct input_handle *joydev_connect(struct input_handler *handler, struct input_dev *dev) { struct joydev *joydev; - int i, j; + int i, j, minor; if (!(test_bit(EV_KEY, dev->evbit) && test_bit(EV_ABS, dev->evbit) && test_bit(ABS_X, dev->absbit) && test_bit(ABS_Y, dev->absbit) && (test_bit(BTN_TRIGGER, dev->keybit) || test_bit(BTN_A, dev->keybit) - || test_bit(BTN_1, dev->keybit)))) return -1; + || test_bit(BTN_1, dev->keybit)))) return NULL; - if (!(joydev = kmalloc(sizeof(struct joydev), GFP_KERNEL))) - return -1; + for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++); + if (joydev_table[minor]) { + printk(KERN_ERR "joydev: no more free joydev devices\n"); + return NULL; + } + if (!(joydev = kmalloc(sizeof(struct joydev), GFP_KERNEL))) + return NULL; memset(joydev, 0, sizeof(struct joydev)); init_waitqueue_head(&joydev->wait); - if (joydev_minors == -1) { - printk("Can't register new joystick - 32 devices already taken.\n"); - return -1; - } - sprintf(joydev->name, "joydev%d", joydev->minor); + joydev->minor = minor; + joydev_table[minor] = joydev; + joydev->handle.dev = dev; joydev->handle.handler = handler; joydev->handle.private = joydev; @@ -421,10 +432,6 @@ joydev->nkey++; } - joydev->minor = ffz(joydev_minors); - set_bit(joydev->minor, &joydev_minors); - joydev_base[joydev->minor] = joydev; - for (i = 0; i < joydev->nabs; i++) { j = joydev->abspam[i]; if (dev->absmax[j] == dev->absmin[j]) { @@ -439,21 +446,23 @@ joydev->corr[i].coef[3] = (1 << 29) / ((dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j]); } - input_open_device(&joydev->handle); + joydev->devfs = input_register_minor("js%d", minor, JOYDEV_MINOR_BASE); - printk("%s: Joystick device for input%d on /dev/js%d\n", joydev->name, dev->number, joydev->minor); + printk("js%d: Joystick device for input%d\n", minor, dev->number); - return 0; + return &joydev->handle; } static void joydev_disconnect(struct input_handle *handle) { struct joydev *joydev = handle->private; - input_close_device(handle); + if (joydev->open) + input_close_device(handle); if (!--joydev->used) { - clear_bit(joydev->minor, &joydev_minors); + input_unregister_minor(joydev->devfs); + joydev_table[joydev->minor] = NULL; kfree(joydev); } } @@ -462,14 +471,12 @@ event: joydev_event, connect: joydev_connect, disconnect: joydev_disconnect, + fops: &joydev_fops, + minor: JOYDEV_MINOR_BASE, }; static int __init joydev_init(void) { - if (register_chrdev(JOYDEV_MAJOR, "js", &joydev_fops)) { - printk(KERN_ERR "joydev: unable to get major %d for joystick\n", JOYDEV_MAJOR); - return -EBUSY; - } input_register_handler(&joydev_handler); return 0; } @@ -477,8 +484,6 @@ static void __exit joydev_exit(void) { input_unregister_handler(&joydev_handler); - if (unregister_chrdev(JOYSTICK_MAJOR, "js")) - printk(KERN_ERR "js: can't unregister device\n"); } module_init(joydev_init); diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/keybdev.c linux/drivers/usb/keybdev.c --- v2.3.99-pre3/linux/drivers/usb/keybdev.c Mon Mar 27 08:08:28 2000 +++ linux/drivers/usb/keybdev.c Mon Apr 10 22:53:15 2000 @@ -36,17 +36,63 @@ #include #include -#if defined(CONFIG_X86) || defined(CONFIG_IA64) +#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) || defined(CONFIG_MIPS) -static unsigned char keybdev_x86_e0s[] = - { 0x1c, 0x1d, 0x35, 0x2a, 0x38, 0x39, 0x47, 0x48, - 0x49, 0x4b, 0x4d, 0x4f, 0x50, 0x51, 0x52, 0x53, - 0x26, 0x25, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x00, - 0x23, 0x24, 0x25, 0x26, 0x27 }; +static int x86_sysrq_alt = 0; -#elif CONFIG_ADB_KEYBOARD +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, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 89, 85, 86, 87, 88,115,119,120,121,375,123, 90, + 284,285,309,298,312, 91,327,328,329,331,333,335,336,337,338,339, + 367,294,293,286,350, 92,334,512,116,377,109,111,373,347,348,349, + 360, 93, 94, 95, 98,376,100,101,357,316,354,304,289,102,351,355, + 103,104,105,275,281,272,306,106,274,107,288,364,358,363,362,361, + 291,108,381,290,287,292,279,305,280, 99,112,257,258,113,270,114, + 118,117,125,374,379,259,260,261,262,263,264,265,266,267,268,269, + 271,273,276,277,278,282,283,295,296,297,299,300,301,302,303,307, + 308,310,313,314,315,317,318,319,320,321,322,323,324,325,326,330, + 332,340,341,342,343,344,345,346,356,359,365,368,369,370,371,372 }; -static unsigned char keybdev_mac_codes[256] = +static int emulate_raw(unsigned int keycode, int down) +{ + if (keycode > 255 || !x86_keycodes[keycode]) + return -1; + + if (keycode == KEY_PAUSE) { + handle_scancode(0xe1, 1); + handle_scancode(0x1d, down); + handle_scancode(0x45, down); + return 0; + } + + if (keycode == KEY_SYSRQ && x86_sysrq_alt) { + handle_scancode(0x54, down); + return 0; + } + + if (x86_keycodes[keycode] & 0x100) + handle_scancode(0xe0, 1); + + handle_scancode(x86_keycodes[keycode] & 0x7f, down); + + if (keycode == KEY_SYSRQ) { + handle_scancode(0xe0, 1); + handle_scancode(0x37, down); + } + + if (keycode == KEY_LEFTALT || keycode == KEY_RIGHTALT) + x86_sysrq_alt = down; + + return 0; +} + +#elif defined(CONFIG_ADB_KEYBOARD) + +static unsigned char mac_keycodes[128] = { 0, 53, 18, 19, 20, 21, 23, 22, 26, 28, 25, 29, 27, 24, 51, 48, 12, 13, 14, 15, 17, 16, 32, 34, 31, 35, 33, 30, 36, 54,128, 1, 2, 3, 5, 4, 38, 40, 37, 41, 39, 50, 56, 42, 6, 7, 8, 9, @@ -56,10 +102,19 @@ 76,125, 75,105,124, 0,115, 62,116, 59, 60,119, 61,121,114,117, 0, 0, 0, 0,127, 81, 0,113, 0, 0, 0, 0, 0, 55, 55 }; +static int emulate_raw(unsigned int code, unsigned char upflag) +{ + if (keycode > 127 || !mac_keycodes[keycode]) + return -1; + + handle_scancode(mac_keycodes[keycode] & 0x7f, down); + + return 0; +} + #endif static struct input_handler keybdev_handler; -static int keybdev_alt = 0; void keybdev_ledfunc(unsigned int led) { @@ -76,70 +131,30 @@ void keybdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int down) { - if (type != EV_KEY || code > 255) return; + if (type != EV_KEY) return; -#if defined(CONFIG_X86) || defined(CONFIG_IA64) - - if (code >= 189) { - printk(KERN_WARNING "keybdev.c: can't emulate keycode %d\n", code); - return; - } else if (code >= 162) { - handle_scancode(0xe0, 1); - handle_scancode(code - 161, down); - } else if (code >= 125) { - handle_scancode(0xe0, 1); - handle_scancode(code - 34, down); - } else if (code == 119) { - handle_scancode(0xe1, 1); - handle_scancode(0x1d, down); - handle_scancode(0x45, down); - } else if (code >= 96) { - if (code == 99 && keybdev_alt) { - handle_scancode(84, down); - } else { - handle_scancode(0xe0, 1); - handle_scancode(keybdev_x86_e0s[code - 96], down); - if (code == 99) { - handle_scancode(0xe0, 1); - handle_scancode(0x37, down); - } - } - } else if (code == 84) { - handle_scancode(43, down); - } else handle_scancode(code, down); - - if (code == 56 || code == 100) keybdev_alt = down; - -#elif CONFIG_ADB_KEYBOARD - - if (code < 128 && keybdev_mac_codes[code]) - handle_scancode(keybdev_mac_codes[code] & 0x7f, down); - else - printk(KERN_WARNING "keybdev.c: can't emulate keycode %d\n", code); - -#else -#error "Cannot generate rawmode keyboard for your architecture yet." -#endif + if (emulate_raw(code, down)) + printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", code); tasklet_schedule(&keyboard_tasklet); } -static int keybdev_connect(struct input_handler *handler, struct input_dev *dev) +static struct input_handle *keybdev_connect(struct input_handler *handler, struct input_dev *dev) { struct input_handle *handle; int i; if (!test_bit(EV_KEY, dev->evbit)) - return -1; + return NULL; for (i = KEY_RESERVED; i < BTN_MISC; i++) if (test_bit(i, dev->keybit)) break; if (i == BTN_MISC) - return -1; + return NULL; if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL))) - return -1; + return NULL; memset(handle, 0, sizeof(struct input_handle)); handle->dev = dev; @@ -149,15 +164,13 @@ printk("keybdev.c: Adding keyboard: input%d\n", dev->number); - return 0; + return handle; } static void keybdev_disconnect(struct input_handle *handle) { printk("keybdev.c: Removing keyboard: input%d\n", handle->dev->number); - input_close_device(handle); - kfree(handle); } diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/mdc800.c linux/drivers/usb/mdc800.c --- v2.3.99-pre3/linux/drivers/usb/mdc800.c Mon Mar 27 08:08:28 2000 +++ linux/drivers/usb/mdc800.c Wed Apr 5 16:58:48 2000 @@ -26,11 +26,19 @@ * To use the Camera you must support the USB Protocoll of the camera * to the Kernel Node. * The Driver uses a misc device Node. Create it with : - * mknod /dev/mustek c 10 171 + * mknod /dev/mustek c 180 32 * * The driver supports only one camera. * * version 0.7.1 + * MOD_INC and MOD_DEC are changed in usb_probe to prevent load/unload + * problems when compiled as Module. + * (04/04/2000) + * + * The mdc800 driver gets assigned the USB Minor 32-47. The Registration + * was updated to use these values. + * (26/03/2000) + * * The Init und Exit Module Function are updated. * (01/03/2000) * @@ -57,7 +65,6 @@ #include #include #include -#include #include #include #include @@ -67,22 +74,22 @@ #include #define VERSION "0.7.1" -#define RELEASE_DATE "(01/03/2000)" +#define RELEASE_DATE "(26/03/2000)" /* Vendor and Product Information */ #define MDC800_VENDOR_ID 0x055f #define MDC800_PRODUCT_ID 0xa800 /* Timeouts (msec) */ -#define TO_READ_FROM_IRQ 4000 +#define TO_READ_FROM_IRQ 4000 #define TO_GET_READY 2000 -#define TO_DOWNLOAD_GET_READY 1500 -#define TO_DOWNLOAD_GET_BUSY 1500 -#define TO_WRITE_GET_READY 3000 -#define TO_DEFAULT_COMMAND 5000 +#define TO_DOWNLOAD_GET_READY 1500 +#define TO_DOWNLOAD_GET_BUSY 1500 +#define TO_WRITE_GET_READY 3000 +#define TO_DEFAULT_COMMAND 5000 -/* Minor Number of the device (create with mknod /dev/mustek c 10 171) */ -#define MDC800_DEVICE_MINOR 171 +/* Minor Number of the device (create with mknod /dev/mustek c 180 32) */ +#define MDC800_DEVICE_MINOR_BASE 32 /************************************************************************** @@ -514,11 +521,20 @@ static int mdc800_device_open (struct inode* inode, struct file *file) { int retval=0; + + MOD_INC_USE_COUNT; + if (mdc800->state == NOT_CONNECTED) + { + MOD_DEC_USE_COUNT; return -EBUSY; + } if (mdc800->open) + { + MOD_DEC_USE_COUNT; return -EBUSY; + } mdc800->rw_lock=0; mdc800->in_count=0; @@ -535,10 +551,10 @@ if (usb_submit_urb (mdc800->irq_urb)) { err ("request USB irq fails (submit_retval=%i urb_status=%i).",retval, mdc800->irq_urb->status); + MOD_DEC_USE_COUNT; return -EIO; } - MOD_INC_USE_COUNT; mdc800->open=1; dbg ("Mustek MDC800 device opened."); @@ -792,21 +808,6 @@ Init and Cleanup this driver (Structs and types) ****************************************************************************/ - -/* - * USB Driver Struct for this device - */ -static struct usb_driver mdc800_usb_driver = -{ - "mdc800", - mdc800_usb_probe, - mdc800_usb_disconnect, - { 0,0 }, - 0, - 0 -}; - - /* File Operations of this drivers */ static struct file_operations mdc800_device_ops = { @@ -828,17 +829,22 @@ }; + /* - * The Misc Device Configuration Struct + * USB Driver Struct for this device */ -static struct miscdevice mdc800_device = +static struct usb_driver mdc800_usb_driver = { - MDC800_DEVICE_MINOR, - "USB Mustek MDC800 Camera", - &mdc800_device_ops + "mdc800", + mdc800_usb_probe, + mdc800_usb_disconnect, + { 0,0 }, + &mdc800_device_ops, + MDC800_DEVICE_MINOR_BASE }; + /************************************************************************ Init and Cleanup this driver (Main Functions) *************************************************************************/ @@ -872,8 +878,6 @@ /* Register the driver */ if (usb_register (&mdc800_usb_driver) < 0) goto cleanup_on_fail; - if (misc_register (&mdc800_device) < 0) - goto cleanup_on_misc_register_fail; info ("Mustek Digital Camera Driver " VERSION " (MDC800)"); info (RELEASE_DATE " Henning Zabel "); @@ -882,9 +886,6 @@ /* Clean driver up, when something fails */ -cleanup_on_misc_register_fail: - usb_deregister (&mdc800_usb_driver); - cleanup_on_fail: if (mdc800 != 0) @@ -909,7 +910,6 @@ void __exit usb_mdc800_cleanup (void) { usb_deregister (&mdc800_usb_driver); - misc_deregister (&mdc800_device); usb_free_urb (mdc800->irq_urb); usb_free_urb (mdc800->download_urb); diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/mousedev.c linux/drivers/usb/mousedev.c --- v2.3.99-pre3/linux/drivers/usb/mousedev.c Mon Mar 27 08:08:28 2000 +++ linux/drivers/usb/mousedev.c Mon Apr 10 22:53:15 2000 @@ -29,8 +29,9 @@ */ #define MOUSEDEV_MINOR_BASE 32 +#define MOUSEDEV_MINORS 32 +#define MOUSEDEV_MIX 31 -#include #include #include #include @@ -46,12 +47,13 @@ #endif struct mousedev { - char name[32]; int used; - struct input_handle handle; - struct miscdevice misc; + int open; + int minor; wait_queue_head_t wait; struct mousedev_list *list; + struct input_handle handle; + devfs_handle_t devfs; }; struct mousedev_list { @@ -71,77 +73,80 @@ static unsigned char mousedev_genius_seq[] = { 0xe8, 3, 0xe6, 0xe6, 0xe6 }; static unsigned char mousedev_imps_seq[] = { 0xf3, 200, 0xf3, 100, 0xf3, 80 }; -#ifdef CONFIG_INPUT_MOUSEDEV_MIX -static struct mousedev mousedev_single; -#else -static unsigned long mousedev_miscbits = 0; -static struct mousedev *mousedev_base[BITS_PER_LONG]; -#endif +static struct input_handler mousedev_handler; + +static struct mousedev *mousedev_table[MOUSEDEV_MINORS]; +static struct mousedev mousedev_mix; static void mousedev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) { - struct mousedev *mousedev = handle->private; - struct mousedev_list *list = mousedev->list; + struct mousedev *mousedevs[3] = { handle->private, &mousedev_mix, NULL }; + struct mousedev **mousedev = mousedevs; + struct mousedev_list *list; int index, size; - while (list) { - switch (type) { - case EV_ABS: - switch (code) { - case ABS_X: - size = handle->dev->absmax[ABS_X] - handle->dev->absmin[ABS_X]; - list->dx += (value * CONFIG_MOUSEDEV_SCREEN_X - 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_MOUSEDEV_SCREEN_Y - list->oldy) / size; - list->oldy -= list->dy * size; - break; - } - break; - case EV_REL: - switch (code) { - case REL_X: list->dx += value; break; - case REL_Y: list->dy -= value; break; - case REL_WHEEL: if (list->mode) list->dz -= value; break; - } - break; + while (*mousedev) { + list = (*mousedev)->list; + while (list) { + switch (type) { + case EV_ABS: + switch (code) { + case ABS_X: + size = handle->dev->absmax[ABS_X] - handle->dev->absmin[ABS_X]; + list->dx += (value * CONFIG_MOUSEDEV_SCREEN_X - 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_MOUSEDEV_SCREEN_Y - list->oldy) / size; + list->oldy -= list->dy * size; + break; + } + break; + case EV_REL: + switch (code) { + case REL_X: list->dx += value; break; + case REL_Y: list->dy -= value; break; + case REL_WHEEL: if (list->mode) list->dz -= value; break; + } + break; + + case EV_KEY: + switch (code) { + case BTN_0: + case BTN_TOUCH: + case BTN_LEFT: index = 0; break; + case BTN_4: + case BTN_EXTRA: if (list->mode > 1) { 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_2: + case BTN_STYLUS2: + case BTN_MIDDLE: index = 2; break; + default: return; + } + switch (value) { + case 0: clear_bit(index, &list->buttons); break; + case 1: set_bit(index, &list->buttons); break; + case 2: return; + } + break; + } + + list->ready = 1; - case EV_KEY: - switch (code) { - case BTN_0: - case BTN_TOUCH: - case BTN_LEFT: index = 0; break; - case BTN_4: - case BTN_EXTRA: if (list->mode > 1) { 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_2: - case BTN_STYLUS2: - case BTN_MIDDLE: index = 2; break; - default: return; - } - switch (value) { - case 0: clear_bit(index, &list->buttons); break; - case 1: set_bit(index, &list->buttons); break; - case 2: return; - } - break; - } - - list->ready = 1; + if (list->fasync) + kill_fasync(list->fasync, SIGIO, POLL_IN); - if (list->fasync) - kill_fasync(list->fasync, SIGIO, POLL_IN); + list = list->next; + } - list = list->next; + wake_up_interruptible(&((*mousedev)->wait)); + mousedev++; } - - wake_up_interruptible(&mousedev->wait); } static int mousedev_fasync(int fd, struct file *file, int on) @@ -162,14 +167,27 @@ while (*listptr && (*listptr != list)) listptr = &((*listptr)->next); *listptr = (*listptr)->next; + + if (!--list->mousedev->open) { + if (list->mousedev->minor == MOUSEDEV_MIX) { + struct input_handle *handle = mousedev_handler.handle; + while (handle) { + struct mousedev *mousedev = handle->private; + if (!mousedev->open) + input_close_device(handle); + handle = handle->hnext; + } + } else { + if (!mousedev_mix.open) + input_close_device(&list->mousedev->handle); + } + } -#ifndef CONFIG_INPUT_MOUSEDEV_MIX if (!--list->mousedev->used) { - clear_bit(list->mousedev->misc.minor - MOUSEDEV_MINOR_BASE, &mousedev_miscbits); - misc_deregister(&list->mousedev->misc); + input_unregister_minor(list->mousedev->devfs); + mousedev_table[list->mousedev->minor] = NULL; kfree(list->mousedev); } -#endif kfree(list); @@ -180,33 +198,41 @@ static int mousedev_open(struct inode * inode, struct file * file) { struct mousedev_list *list; - -#ifndef CONFIG_INPUT_MOUSEDEV_MIX int i = MINOR(inode->i_rdev) - MOUSEDEV_MINOR_BASE; - if (i > BITS_PER_LONG || !test_bit(i, &mousedev_miscbits)) + + if (i > MOUSEDEV_MINORS || !mousedev_table[i]) return -ENODEV; -#endif - if (!(list = kmalloc(sizeof(struct mousedev_list), GFP_KERNEL))) - return -ENOMEM; + MOD_INC_USE_COUNT; + if (!(list = kmalloc(sizeof(struct mousedev_list), GFP_KERNEL))) { + MOD_DEC_USE_COUNT; + return -ENOMEM; + } memset(list, 0, sizeof(struct mousedev_list)); + list->mousedev = mousedev_table[i]; + list->next = mousedev_table[i]->list; + mousedev_table[i]->list = list; + file->private_data = list; -#ifdef CONFIG_INPUT_MOUSEDEV_MIX - list->mousedev = &mousedev_single; - list->next = mousedev_single.list; - mousedev_single.list = list; -#else - list->mousedev = mousedev_base[i]; - list->next = mousedev_base[i]->list; - mousedev_base[i]->list = list; list->mousedev->used++; -#endif - file->private_data = list; + if (!list->mousedev->open++) { + if (list->mousedev->minor == MOUSEDEV_MIX) { + struct input_handle *handle = mousedev_handler.handle; + while (handle) { + struct mousedev *mousedev = handle->private; + if (!mousedev->open) + input_open_device(handle); + handle = handle->hnext; + } + } else { + if (!mousedev_mix.open) + input_open_device(&list->mousedev->handle); + } + } - MOD_INC_USE_COUNT; return 0; } @@ -357,119 +383,93 @@ fasync: mousedev_fasync, }; -static int mousedev_connect(struct input_handler *handler, struct input_dev *dev) +static struct input_handle *mousedev_connect(struct input_handler *handler, struct input_dev *dev) { + struct mousedev *mousedev; + int minor = 0; if (!test_bit(EV_KEY, dev->evbit) || (!test_bit(BTN_LEFT, dev->keybit) && !test_bit(BTN_TOUCH, dev->keybit))) - return -1; + return NULL; if ((!test_bit(EV_REL, dev->evbit) || !test_bit(REL_X, dev->relbit)) && (!test_bit(EV_ABS, dev->evbit) || !test_bit(ABS_X, dev->absbit))) - return -1; - -#ifdef CONFIG_INPUT_MOUSEDEV_MIX - { - struct input_handle *handle; + return NULL; - if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL))) - return -1; - - memset(handle, 0, sizeof(struct input_handle)); - - handle->dev = dev; - handle->handler = handler; - handle->private = &mousedev_single; - - input_open_device(handle); - - printk("mousedev.c: Adding mouse: input%d\n", dev->number); + for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++); + if (mousedev_table[minor]) { + printk(KERN_ERR "mousedev: no more free mousedev devices\n"); + return NULL; } -#else - { - struct mousedev *mousedev; - - if (!(mousedev = kmalloc(sizeof(struct mousedev), GFP_KERNEL))) - return -1; - - memset(mousedev, 0, sizeof(struct mousedev)); - - mousedev->misc.minor = ffz(mousedev_miscbits); - set_bit(mousedev->misc.minor, &mousedev_miscbits); - mousedev_base[mousedev->misc.minor] = mousedev; - sprintf(mousedev->name, "mousedev%d", mousedev->misc.minor); - mousedev->misc.name = mousedev->name; - mousedev->misc.minor += MOUSEDEV_MINOR_BASE; - mousedev->misc.fops = &mousedev_fops; + if (!(mousedev = kmalloc(sizeof(struct mousedev), GFP_KERNEL))) + return NULL; + memset(mousedev, 0, sizeof(struct mousedev)); + init_waitqueue_head(&mousedev->wait); + + mousedev->used = 1; + mousedev->minor = minor; + mousedev_table[minor] = mousedev; + + mousedev->handle.dev = dev; + mousedev->handle.handler = handler; + mousedev->handle.private = mousedev; - mousedev->handle.dev = dev; - mousedev->handle.handler = handler; - mousedev->handle.private = mousedev; + mousedev->devfs = input_register_minor("mouse%d", minor, MOUSEDEV_MINOR_BASE); - init_waitqueue_head(&mousedev->wait); - - mousedev->used = 1; - - misc_register(&mousedev->misc); + if (mousedev_mix.open) { input_open_device(&mousedev->handle); - - printk("%s: PS/2 mouse device for input%d on misc%d\n", - mousedev->name, dev->number, mousedev->misc.minor); + mousedev_mix.open++; } -#endif - return 0; + printk("mouse%d: PS/2 mouse device for input%d\n", minor, dev->number); + + return &mousedev->handle; } static void mousedev_disconnect(struct input_handle *handle) { -#ifdef CONFIG_INPUT_MOUSEDEV_MIX - printk("mousedev.c: Removing mouse: input%d\n", handle->dev->number); - input_close_device(handle); - kfree(handle); -#else struct mousedev *mousedev = handle->private; - input_close_device(handle); + + if (mousedev->open || mousedev_mix.open) { + input_close_device(handle); + mousedev_mix.open--; + } + if (!--mousedev->used) { - clear_bit(mousedev->misc.minor - MOUSEDEV_MINOR_BASE, &mousedev_miscbits); - misc_deregister(&mousedev->misc); + input_unregister_minor(mousedev->devfs); + mousedev_table[mousedev->minor] = NULL; kfree(mousedev); } -#endif } static struct input_handler mousedev_handler = { event: mousedev_event, connect: mousedev_connect, disconnect: mousedev_disconnect, + fops: &mousedev_fops, + minor: MOUSEDEV_MINOR_BASE, }; static int __init mousedev_init(void) { input_register_handler(&mousedev_handler); -#ifdef CONFIG_INPUT_MOUSEDEV_MIX - memset(&mousedev_single, 0, sizeof(struct mousedev)); - - init_waitqueue_head(&mousedev_single.wait); - mousedev_single.misc.minor = MOUSEDEV_MINOR_BASE; - mousedev_single.misc.name = "mousedev"; - mousedev_single.misc.fops = &mousedev_fops; + memset(&mousedev_mix, 0, sizeof(struct mousedev)); + init_waitqueue_head(&mousedev_mix.wait); + mousedev_table[MOUSEDEV_MIX] = &mousedev_mix; + mousedev_mix.used = 1; + mousedev_mix.minor = MOUSEDEV_MIX; + mousedev_mix.devfs = input_register_minor("mice", MOUSEDEV_MIX, MOUSEDEV_MINOR_BASE); - misc_register(&mousedev_single.misc); - - printk("mousedev: PS/2 mouse device on misc%d\n", mousedev_single.misc.minor); -#endif + printk("mice: PS/2 mouse device common for all mice\n"); return 0; } static void __exit mousedev_exit(void) { -#ifdef CONFIG_INPUT_MOUSEDEV_MIX - misc_deregister(&mousedev_single.misc); -#endif + input_unregister_minor(mousedev_mix.devfs); input_unregister_handler(&mousedev_handler); } diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/ov511.c linux/drivers/usb/ov511.c --- v2.3.99-pre3/linux/drivers/usb/ov511.c Tue Mar 14 19:10:40 2000 +++ linux/drivers/usb/ov511.c Wed Apr 5 17:01:56 2000 @@ -4,12 +4,13 @@ * Many improvements by Bret Wallach * Color fixes by by Orion Sky Lawlor, olawlor@acm.org, 2/26/2000 * Snapshot code by Kevin Moore + * OV7620 fixes by Charl P. Botha * * Based on the Linux CPiA driver. * * Released under GPL v.2 license. * - * Version: 1.09 + * Version: 1.11 * * Please see the file: linux/Documentation/usb/ov511.txt * and the website at: http://alpha.dyndns.org/ov511 @@ -34,8 +35,6 @@ #define __NO_VERSION__ -/* Handle mangled (versioned) external symbols */ - #include #include #include @@ -83,10 +82,14 @@ /* Snapshot mode enabled flag */ static int snapshot = 0; +/* Sensor detection override (global for all attached cameras) */ +static int sensor = 0; + MODULE_PARM(autoadjust, "i"); MODULE_PARM(debug, "i"); MODULE_PARM(fix_rgb_offset, "i"); MODULE_PARM(snapshot, "i"); +MODULE_PARM(sensor, "i"); MODULE_AUTHOR("Mark McClelland (and others)"); MODULE_DESCRIPTION("OV511 USB Camera Driver"); @@ -210,7 +213,9 @@ vfree(mem); } -int ov511_reg_write(struct usb_device *dev, unsigned char reg, unsigned char value) +static int ov511_reg_write(struct usb_device *dev, + unsigned char reg, + unsigned char value) { int rc; @@ -219,14 +224,17 @@ 2 /* REG_IO */, USB_TYPE_CLASS | USB_RECIP_DEVICE, 0, (__u16)reg, &value, 1, HZ); - + PDEBUG(5, "reg write: 0x%02X:0x%02X, 0x%x", reg, value, rc); - + + if (rc < 0) + err("ov511_reg_write: error %d", rc); + return rc; } /* returns: negative is error, pos or zero is data */ -int ov511_reg_read(struct usb_device *dev, unsigned char reg) +static int ov511_reg_read(struct usb_device *dev, unsigned char reg) { int rc; unsigned char buffer[1]; @@ -239,13 +247,17 @@ PDEBUG(5, "reg read: 0x%02X:0x%02X", reg, buffer[0]); - if(rc < 0) + if(rc < 0) { + err("ov511_reg_read: error %d", rc); return rc; + } else return buffer[0]; } -int ov511_i2c_write(struct usb_device *dev, unsigned char reg, unsigned char value) +static int ov511_i2c_write(struct usb_device *dev, + unsigned char reg, + unsigned char value) { int rc, retries; @@ -255,19 +267,19 @@ for(retries = OV511_I2C_RETRIES;;) { /* Select camera register */ rc = ov511_reg_write(dev, OV511_REG_I2C_SUB_ADDRESS_3_BYTE, reg); - if (rc < 0) return rc; + if (rc < 0) goto error; /* Write "value" to I2C data port of OV511 */ rc = ov511_reg_write(dev, OV511_REG_I2C_DATA_PORT, value); - if (rc < 0) return rc; + if (rc < 0) goto error; /* Initiate 3-byte write cycle */ rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x01); - if (rc < 0) return rc; + if (rc < 0) goto error; do rc = ov511_reg_read(dev, OV511_REG_I2C_CONTROL); while(rc > 0 && ((rc&1) == 0)); /* Retry until idle */ - if (rc < 0) return rc; + if (rc < 0) goto error; if((rc&2) == 0) /* Ack? */ break; @@ -275,14 +287,22 @@ /* I2C abort */ ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x10); #endif - if (--retries < 0) return -1; + if (--retries < 0) { + err("i2c write retries exhausted"); + rc = -1; + goto error; + } } return 0; + +error: + err("ov511_i2c_write: error %d", rc); + return rc; } /* returns: negative is error, pos or zero is data */ -int ov511_i2c_read(struct usb_device *dev, unsigned char reg) +static int ov511_i2c_read(struct usb_device *dev, unsigned char reg) { int rc, value, retries; @@ -290,15 +310,15 @@ for(retries = OV511_I2C_RETRIES;;) { /* Select camera register */ rc = ov511_reg_write(dev, OV511_REG_I2C_SUB_ADDRESS_2_BYTE, reg); - if (rc < 0) return rc; + if (rc < 0) goto error; /* Initiate 2-byte write cycle */ rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x03); - if (rc < 0) return rc; + if (rc < 0) goto error; do rc = ov511_reg_read(dev, OV511_REG_I2C_CONTROL); while(rc > 0 && ((rc&1) == 0)); /* Retry until idle */ - if (rc < 0) return rc; + if (rc < 0) goto error; if((rc&2) == 0) /* Ack? */ break; @@ -306,27 +326,35 @@ /* I2C abort */ ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x10); - if (--retries < 0) return -1; + if (--retries < 0) { + err("i2c write retries exhausted"); + rc = -1; + goto error; + } } /* Two byte read cycle */ for(retries = OV511_I2C_RETRIES;;) { /* Initiate 2-byte read cycle */ rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x05); - if (rc < 0) return rc; + if (rc < 0) goto error; do rc = ov511_reg_read(dev, OV511_REG_I2C_CONTROL); while(rc > 0 && ((rc&1) == 0)); /* Retry until idle */ - if (rc < 0) return rc; + if (rc < 0) goto error; if((rc&2) == 0) /* Ack? */ break; /* I2C abort */ rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x10); - if (rc < 0) return rc; + if (rc < 0) goto error; - if (--retries < 0) return -1; + if (--retries < 0) { + err("i2c read retries exhausted"); + rc = -1; + goto error; + } } value = ov511_reg_read(dev, OV511_REG_I2C_DATA_PORT); @@ -335,60 +363,41 @@ /* This is needed to make ov511_i2c_write() work */ rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x05); - if (rc < 0) return rc; + if (rc < 0) goto error; - return (value); -} - - -// This version doesn't always work -#if 0 - /* returns: negative is error, pos or zero is data */ - int ov511_i2c_read(struct usb_device *dev, unsigned char reg) - { - int rc, value; - - /* Select camera register */ - rc = ov511_reg_write(dev, OV511_REG_I2C_SUB_ADDRESS_2_BYTE, reg); - if (rc < 0) return rc; - - - /* Initiate 2-byte write cycle */ - rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x03); - if (rc < 0) return rc; - - - /* Initiate 2-byte read cycle */ - rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x05); - if (rc < 0) return rc; - - value = ov511_reg_read(dev, OV511_REG_I2C_DATA_PORT); + return value; - PDEBUG(5, "i2c read: 0x%02X:0x%02X", reg, value); - - return (value); - } -#endif +error: + err("ov511_i2c_read: error %d", rc); + return rc; +} static int ov511_write_regvals(struct usb_device *dev, struct ov511_regvals * pRegvals) { - int ret; + int rc; + while(pRegvals->bus != OV511_DONE_BUS) { if (pRegvals->bus == OV511_REG_BUS) { - if ((ret = ov511_reg_write(dev, pRegvals->reg, + if ((rc = ov511_reg_write(dev, pRegvals->reg, pRegvals->val)) < 0) - return ret; + goto error; } else if (pRegvals->bus == OV511_I2C_BUS) { - if ((ret = ov511_i2c_write(dev, pRegvals->reg, + if ((rc = ov511_i2c_write(dev, pRegvals->reg, pRegvals->val)) < 0) - return ret; + goto error; } else { - err("Bad regval array"); + err("Bad regval array"); + rc = -1; + goto error; } pRegvals++; } return 0; + +error: + err("ov511_write_regvals: error %d", rc); + return rc; } #if 0 @@ -396,10 +405,9 @@ { int i; int rc; - for(i=reg1; i<=regn; i++) { - rc = ov511_i2c_read(dev, i); - - PDEBUG(1, "OV7610[0x%X] = 0x%X", i, rc); + for(i = reg1; i <= regn; i++) { + rc = ov511_i2c_read(dev, i); + PDEBUG(1, "OV7610[0x%X] = 0x%X", i, rc); } } @@ -413,7 +421,7 @@ { int i; int rc; - for(i=reg1; i<=regn; i++) { + for(i = reg1; i <= regn; i++) { rc = ov511_reg_read(dev, i); PDEBUG(1, "OV511[0x%X] = 0x%X", i, rc); } @@ -443,72 +451,82 @@ } #endif -int ov511_reset(struct usb_device *dev, unsigned char reset_type) +static int ov511_reset(struct usb_device *dev, unsigned char reset_type) { int rc; PDEBUG(3, "Reset: type=0x%X", reset_type); rc = ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, reset_type); - if (rc < 0) - err("reset: command failed"); - rc = ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0); + if (rc < 0) err("reset: command failed"); return rc; } -int ov511_set_packet_size(struct usb_ov511 *ov511, int size) +/* Temporarily stops OV511 from functioning. Must do this before changing + * registers while the camera is streaming */ +static inline int ov511_stop(struct usb_device *dev) { - int alt, multiplier, rc; - - PDEBUG(3, "set packet size: %d", size); - - switch (size) { - case 992: - alt = 0; - multiplier = 31; - break; - case 993: - alt = 1; - multiplier = 31; - break; - case 768: - alt = 2; - multiplier = 24; - break; - case 769: - alt = 3; - multiplier = 24; - break; - case 512: - alt = 4; - multiplier = 16; - break; - case 513: - alt = 5; - multiplier = 16; - break; - case 257: - alt = 6; - multiplier = 8; - break; - case 0: - alt = 7; - multiplier = 1; // FIXME - is this correct? - break; - default: + PDEBUG(4, "ov511_stop()"); + return (ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0x3d)); +} + +/* Restarts OV511 after ov511_stop() is called */ +static inline int ov511_restart(struct usb_device *dev) +{ + PDEBUG(4, "ov511_restart()"); + return (ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0x00)); +} + +static int ov511_set_packet_size(struct usb_ov511 *ov511, int size) +{ + int alt, mult; + + if (ov511_stop(ov511->dev) < 0) + return -EIO; + + mult = size / 32; + + if (ov511->bridge == BRG_OV511) { + if (size == 0) alt = OV511_ALT_SIZE_0; + else if (size == 257) alt = OV511_ALT_SIZE_257; +// else if (size == 512) alt = OV511_ALT_SIZE_512; + else if (size == 513) alt = OV511_ALT_SIZE_513; +// else if (size == 768) alt = OV511_ALT_SIZE_768; + else if (size == 769) alt = OV511_ALT_SIZE_769; +// else if (size == 992) alt = OV511_ALT_SIZE_992; + else if (size == 993) alt = OV511_ALT_SIZE_993; + else { + err("Set packet size: invalid size (%d)", size); + return -EINVAL; + } + } + else if (ov511->bridge == BRG_OV511PLUS) { + if (size == 0) alt = OV511PLUS_ALT_SIZE_0; + else if (size == 33) alt = OV511PLUS_ALT_SIZE_33; + else if (size == 129) alt = OV511PLUS_ALT_SIZE_129; + else if (size == 257) alt = OV511PLUS_ALT_SIZE_257; + else if (size == 385) alt = OV511PLUS_ALT_SIZE_385; + else if (size == 513) alt = OV511PLUS_ALT_SIZE_513; + else if (size == 769) alt = OV511PLUS_ALT_SIZE_769; + else if (size == 961) alt = OV511PLUS_ALT_SIZE_961; + else { err("Set packet size: invalid size (%d)", size); return -EINVAL; + } + } + else { + err("Set packet size: Invalid bridge type"); + return -EINVAL; } - rc = ov511_reg_write(ov511->dev, OV511_REG_FIFO_PACKET_SIZE, - multiplier); - if (rc < 0) { - err("Set packet size: Set FIFO size ret %d", rc); + PDEBUG(3, "set packet size: %d, mult=%d, alt=%d", size, mult, alt); + + if (ov511_reg_write(ov511->dev, OV511_REG_FIFO_PACKET_SIZE, + mult) < 0) return -ENOMEM; - } if (usb_set_interface(ov511->dev, ov511->iface, alt) < 0) { err("Set packet size: set interface error"); @@ -519,6 +537,11 @@ if (ov511_reset(ov511->dev, OV511_RESET_NOREGS) < 0) return -ENOMEM; + ov511->packet_size = size; + + if (ov511_restart(ov511->dev) < 0) + return -EIO; + return 0; } @@ -526,34 +549,44 @@ struct video_picture *p) { int ret; + struct usb_device *dev = ov511->dev; - /* Stop the camera */ - if (ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_RESET, 0x3d) < 0) { - err("reset: command failed"); + PDEBUG(4, "ov511_set_picture"); + + if (ov511_stop(dev) < 0) return -EIO; - } - if((ret = ov511_i2c_read(ov511->dev, OV7610_REG_COM_B)) < 0) + if((ret = ov511_i2c_read(dev, OV7610_REG_COM_B)) < 0) return -EIO; #if 0 - if(ov511_i2c_write(ov511->dev, OV7610_REG_COM_B, ret & 0xfe) < 0) + if(ov511_i2c_write(dev, OV7610_REG_COM_B, ret & 0xfe) < 0) return -EIO; #endif + if (ov511->sensor == SEN_OV7610 || ov511->sensor == SEN_OV7620AE) + if(ov511_i2c_write(dev, OV7610_REG_SAT, p->colour >> 8) < 0) + return -EIO; + + if (ov511->sensor == SEN_OV7610) { + if(ov511_i2c_write(dev, OV7610_REG_CNT, p->contrast >> 8) < 0) + return -EIO; + + if(ov511_i2c_write(dev, OV7610_REG_BRT, p->brightness >> 8) < 0) + return -EIO; + } + else if ((ov511->sensor == SEN_OV7620) + || (ov511->sensor == SEN_OV7620AE)) { +// cur_con = ov511_i2c_read(dev, OV7610_REG_CNT); +// cur_brt = ov511_i2c_read(dev, OV7610_REG_BRT); +// // DEBUG_CODE +// PDEBUG(1, "con=%d brt=%d", ov511_i2c_read(dev, OV7610_REG_CNT), +// ov511_i2c_read(dev, OV7610_REG_BRT)); +// +// if(ov511_i2c_write(dev, OV7610_REG_CNT, p->contrast >> 8) < 0) +// return -EIO; + } - if(ov511_i2c_write(ov511->dev, OV7610_REG_SAT, p->colour >> 8) < 0) - return -EIO; - - if(ov511_i2c_write(ov511->dev, OV7610_REG_CNT, p->contrast >> 8) < 0) - return -EIO; - - if(ov511_i2c_write(ov511->dev, OV7610_REG_BRT, p->brightness >> 8) < 0) - return -EIO; - - /* Restart the camera */ - if (ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_RESET, 0x0) < 0) { - err("reset: command failed"); + if (ov511_restart(dev) < 0) return -EIO; - } return 0; } @@ -562,20 +595,20 @@ struct video_picture *p) { int ret; + struct usb_device *dev = ov511->dev; - /* Stop the camera */ - if (ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_RESET, 0x3d) < 0) { - err("reset: command failed"); + PDEBUG(4, "ov511_get_picture"); + + if (ov511_stop(dev) < 0) return -EIO; - } - if((ret = ov511_i2c_read(ov511->dev, OV7610_REG_SAT)) < 0) return -EIO; + if((ret = ov511_i2c_read(dev, OV7610_REG_SAT)) < 0) return -EIO; p->colour = ret << 8; - if((ret = ov511_i2c_read(ov511->dev, OV7610_REG_CNT)) < 0) return -EIO; + if((ret = ov511_i2c_read(dev, OV7610_REG_CNT)) < 0) return -EIO; p->contrast = ret << 8; - if((ret = ov511_i2c_read(ov511->dev, OV7610_REG_BRT)) < 0) return -EIO; + if((ret = ov511_i2c_read(dev, OV7610_REG_BRT)) < 0) return -EIO; p->brightness = ret << 8; p->hue = 0x8000; @@ -583,11 +616,8 @@ p->depth = 3; /* Don't know if this is right */ p->palette = VIDEO_PALETTE_RGB24; - /* Restart the camera */ - if (ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_RESET, 0x0) < 0) { - err("reset: command failed"); + if (ov511_restart(dev) < 0) return -EIO; - } return 0; } @@ -597,67 +627,93 @@ { int rc = 0; struct usb_device *dev = ov511->dev; + int hwsbase = 0; + int hwebase = 0; PDEBUG(3, "ov511_mode_init_regs(ov511, w:%d, h:%d, mode:%d, sub:%d)", width, height, mode, sub_flag); -// ov511_set_packet_size(ov511, 0); - if (ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0x3d) < 0) { - err("reset: command failed"); + if (ov511_stop(ov511->dev) < 0) return -EIO; - } if (mode == VIDEO_PALETTE_GREY) { ov511_reg_write(dev, 0x16, 0x00); - ov511_i2c_write(dev, 0x0e, 0x44); - ov511_i2c_write(dev, 0x13, 0x21); + if (ov511->sensor == SEN_OV7610 + || ov511->sensor == SEN_OV7620AE) { + /* these aren't valid on the OV7620 */ + ov511_i2c_write(dev, 0x0e, 0x44); + } + ov511_i2c_write(dev, 0x13, autoadjust ? 0x21 : 0x20); /* For snapshot */ ov511_reg_write(dev, 0x1e, 0x00); ov511_reg_write(dev, 0x1f, 0x01); } else { ov511_reg_write(dev, 0x16, 0x01); - ov511_i2c_write(dev, 0x0e, 0x04); - ov511_i2c_write(dev, 0x13, 0x01); + if (ov511->sensor == SEN_OV7610 + || ov511->sensor == SEN_OV7620AE) { + /* not valid on the OV7620 */ + ov511_i2c_write(dev, 0x0e, 0x04); + } + ov511_i2c_write(dev, 0x13, autoadjust ? 0x01 : 0x00); /* For snapshot */ ov511_reg_write(dev, 0x1e, 0x01); ov511_reg_write(dev, 0x1f, 0x03); } + /* The different sensor ICs handle setting up of window differently */ + switch (ov511->sensor) { + case SEN_OV7610: + case SEN_OV7620AE: + hwsbase = 0x38; + hwebase = 0x3a; break; + case SEN_OV7620: + hwsbase = 0x2c; + hwebase = 0x2d; break; + default: + hwsbase = 0; + hwebase = 0; break; + } + if (width == 640 && height == 480) { if (sub_flag) { - ov511_i2c_write(ov511->dev, 0x17, 0x38+(ov511->subx>>2)); - ov511_i2c_write(ov511->dev, 0x18, - 0x3a+((ov511->subx+ov511->subw)>>2)); - ov511_i2c_write(ov511->dev, 0x19, 0x5+(ov511->suby>>1)); - ov511_i2c_write(ov511->dev, 0x1a, + /* horizontal window start */ + ov511_i2c_write(dev, 0x17, hwsbase+(ov511->subx>>2)); + /* horizontal window end */ + ov511_i2c_write(dev, 0x18, + hwebase+((ov511->subx+ov511->subw)>>2)); + /* vertical window start */ + ov511_i2c_write(dev, 0x19, 0x5+(ov511->suby>>1)); + /* vertical window end */ + ov511_i2c_write(dev, 0x1a, 0x5+((ov511->suby+ov511->subh)>>1)); - ov511_reg_write(ov511->dev, 0x12, (ov511->subw>>3)-1); - ov511_reg_write(ov511->dev, 0x13, (ov511->subh>>3)-1); + ov511_reg_write(dev, 0x12, (ov511->subw>>3)-1); + ov511_reg_write(dev, 0x13, (ov511->subh>>3)-1); + /* clock rate control */ ov511_i2c_write(dev, 0x11, 0x01); /* Snapshot additions */ - ov511_reg_write(ov511->dev, 0x1a, (ov511->subw>>3)-1); - ov511_reg_write(ov511->dev, 0x1b, (ov511->subh>>3)-1); - ov511_reg_write(ov511->dev, 0x1c, 0x00); - ov511_reg_write(ov511->dev, 0x1d, 0x00); + ov511_reg_write(dev, 0x1a, (ov511->subw>>3)-1); + ov511_reg_write(dev, 0x1b, (ov511->subh>>3)-1); + ov511_reg_write(dev, 0x1c, 0x00); + ov511_reg_write(dev, 0x1d, 0x00); } else { - ov511_i2c_write(ov511->dev, 0x17, 0x38); - ov511_i2c_write(ov511->dev, 0x18, 0x3a + (640>>2)); - ov511_i2c_write(ov511->dev, 0x19, 0x5); - ov511_i2c_write(ov511->dev, 0x1a, 5 + (480>>1)); + ov511_i2c_write(dev, 0x17, hwsbase); + ov511_i2c_write(dev, 0x18, hwebase + (640>>2)); + ov511_i2c_write(dev, 0x19, 0x5); + ov511_i2c_write(dev, 0x1a, 5 + (480>>1)); ov511_reg_write(dev, 0x12, 0x4f); ov511_reg_write(dev, 0x13, 0x3d); /* Snapshot additions */ - ov511_reg_write(ov511->dev, 0x1a, 0x4f); - ov511_reg_write(ov511->dev, 0x1b, 0x3d); - ov511_reg_write(ov511->dev, 0x1c, 0x00); - ov511_reg_write(ov511->dev, 0x1d, 0x00); + ov511_reg_write(dev, 0x1a, 0x4f); + ov511_reg_write(dev, 0x1b, 0x3d); + ov511_reg_write(dev, 0x1c, 0x00); + ov511_reg_write(dev, 0x1d, 0x00); if (mode == VIDEO_PALETTE_GREY) { - ov511_i2c_write(dev, 0x11, 4); /* check */ + ov511_i2c_write(dev, 0x11, 4); /* check */ } else { - ov511_i2c_write(dev, 0x11, 6); /* check */ + ov511_i2c_write(dev, 0x11, 6); /* check */ } } @@ -669,7 +725,10 @@ ov511_i2c_write(dev, 0x12, 0x24); ov511_i2c_write(dev, 0x14, 0x04); - ov511_i2c_write(dev, 0x35, 0x9e); + + /* 7620 doesn't have register 0x35, so play it safe */ + if (ov511->sensor != SEN_OV7620) + ov511_i2c_write(dev, 0x35, 0x9e); } else if (width == 320 && height == 240) { ov511_reg_write(dev, 0x12, 0x27); ov511_reg_write(dev, 0x13, 0x1f); @@ -697,12 +756,8 @@ rc = -EINVAL; } -// ov511_set_packet_size(ov511, 993); - - if (ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0x00) < 0) { - err("reset: command failed"); + if (ov511_restart(ov511->dev) < 0) return -EIO; - } return rc; } @@ -928,29 +983,30 @@ *************************************************************/ static void fixFrameRGBoffset(struct ov511_frame *frame) { - int x,y; - int rowBytes=frame->width*3,w=frame->width; - unsigned char *rgb=frame->data; - const int shift=1;//Distance to shift pixels by, vertically + int x, y; + int rowBytes = frame->width*3, w = frame->width; + unsigned char *rgb = frame->data; + const int shift = 1; //Distance to shift pixels by, vertically - if (frame->width<400) - return;//Don't bother with little images + if (frame->width < 400) + return; //Don't bother with little images //Shift red channel up - for (y=shift;yheight;y++) + for (y = shift; y < frame->height; y++) { - int lp=(y-shift)*rowBytes;//Previous line offset - int lc=y*rowBytes;//Current line offset - for (x=0;xheight-shift-1;y>=0;y--) + for (y=frame->height-shift-1; y >= 0; y--) { - int ln=(y+shift)*rowBytes;//Next line offset - int lc=y*rowBytes;//Current line offset - for (x=0;xnumber_of_packets; i++) { int n = urb->iso_frame_desc[i].actual_length; int st = urb->iso_frame_desc[i].status; @@ -969,7 +1027,7 @@ urb->iso_frame_desc[i].status = 0; cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset; - aPackNum[i] = n ? cdata[992] : -1; + aPackNum[i] = n ? cdata[ov511->packet_size - 1] : -1; if (!n || ov511->curframe == -1) continue; @@ -988,7 +1046,7 @@ do_gettimeofday(ts); PDEBUG(4, "Frame End, curframe = %d, packnum=%d, hw=%d, vw=%d", - ov511->curframe, (int)(cdata[992]), + ov511->curframe, (int)(cdata[ov511->packet_size - 1]), (int)(cdata[9]), (int)(cdata[10])); if (frame->scanstate == STATE_LINES) { @@ -1051,7 +1109,7 @@ } /* Parse the segments */ - while(iPix <= 992 - frame->segsize && + while(iPix <= (ov511->packet_size - 1) - frame->segsize && frame->segment < frame->width * frame->height / 256) { int iSegY; int iSegUV; @@ -1099,7 +1157,7 @@ /* Save extra data for next time */ if (frame->segment < frame->width * frame->height / 256) { - ov511->scratchlen = 992 - iPix; + ov511->scratchlen = (ov511->packet_size - 1) - iPix; if (ov511->scratchlen < frame->segsize) { memmove(ov511->scratch, pData, ov511->scratchlen); } else { @@ -1149,13 +1207,20 @@ { urb_t *urb; int fx, err; - + + PDEBUG(4, "ov511_init_isoc"); + ov511->compress = 0; ov511->curframe = -1; ov511->cursbuf = 0; ov511->scratchlen = 0; - ov511_set_packet_size(ov511, 993); + if (ov511->bridge == BRG_OV511) + ov511_set_packet_size(ov511, 993); + else if (ov511->bridge == BRG_OV511PLUS) + ov511_set_packet_size(ov511, 961); + else + err("invalid bridge type"); /* We double buffer the Iso lists */ urb = usb_alloc_urb(FRAMES_PER_DESC); @@ -1172,10 +1237,10 @@ urb->transfer_buffer = ov511->sbuf[0].data; urb->complete = ov511_isoc_irq; urb->number_of_packets = FRAMES_PER_DESC; - urb->transfer_buffer_length = FRAME_SIZE_PER_DESC * FRAMES_PER_DESC; + urb->transfer_buffer_length = ov511->packet_size * FRAMES_PER_DESC; for (fx = 0; fx < FRAMES_PER_DESC; fx++) { - urb->iso_frame_desc[fx].offset = FRAME_SIZE_PER_DESC * fx; - urb->iso_frame_desc[fx].length = FRAME_SIZE_PER_DESC; + urb->iso_frame_desc[fx].offset = ov511->packet_size * fx; + urb->iso_frame_desc[fx].length = ov511->packet_size; } urb = usb_alloc_urb(FRAMES_PER_DESC); @@ -1191,10 +1256,10 @@ urb->transfer_buffer = ov511->sbuf[1].data; urb->complete = ov511_isoc_irq; urb->number_of_packets = FRAMES_PER_DESC; - urb->transfer_buffer_length = FRAME_SIZE_PER_DESC * FRAMES_PER_DESC; + urb->transfer_buffer_length = ov511->packet_size * FRAMES_PER_DESC; for (fx = 0; fx < FRAMES_PER_DESC; fx++) { - urb->iso_frame_desc[fx].offset = FRAME_SIZE_PER_DESC * fx; - urb->iso_frame_desc[fx].length = FRAME_SIZE_PER_DESC; + urb->iso_frame_desc[fx].offset = ov511->packet_size * fx; + urb->iso_frame_desc[fx].length = ov511->packet_size; } ov511->sbuf[1].urb->next = ov511->sbuf[0].urb; @@ -1215,6 +1280,7 @@ static void ov511_stop_isoc(struct usb_ov511 *ov511) { + PDEBUG(4, "ov511_stop_isoc"); if (!ov511->streaming || !ov511->dev) return; @@ -1239,10 +1305,11 @@ static int ov511_new_frame(struct usb_ov511 *ov511, int framenum) { -#if 1 struct ov511_frame *frame; int width, height; + PDEBUG(4, "ov511_new_frame"); + if (!ov511->dev) return -1; @@ -1277,7 +1344,6 @@ // /* We want a fresh frame every 30 we get */ // ov511->compress = (ov511->compress + 1) % 30; -#endif return 0; } @@ -1311,10 +1377,10 @@ PDEBUG(4, "frame [0] @ %p", ov511->frame[0].data); PDEBUG(4, "frame [1] @ %p", ov511->frame[1].data); - ov511->sbuf[0].data = kmalloc(FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL); + ov511->sbuf[0].data = kmalloc(FRAMES_PER_DESC * MAX_FRAME_SIZE_PER_DESC, GFP_KERNEL); if (!ov511->sbuf[0].data) goto open_err_on0; - ov511->sbuf[1].data = kmalloc(FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL); + ov511->sbuf[1].data = kmalloc(FRAMES_PER_DESC * MAX_FRAME_SIZE_PER_DESC, GFP_KERNEL); if (!ov511->sbuf[1].data) goto open_err_on1; @@ -1835,9 +1901,11 @@ initialize: ov511_init_done, }; -static int ov7610_configure(struct usb_device *dev) +static int ov7610_configure(struct usb_ov511 *ov511) { + struct usb_device *dev = ov511->dev; int tries; + int rc; if(ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE, OV7610_I2C_WRITE_ID) < 0) @@ -1865,13 +1933,42 @@ --tries; } - if (tries == 0) { - err("Failed to read OV7610 ID. You might not have an OV7610,"); + if (tries == 1) { + err("Failed to read sensor ID. You might not have an OV7610/20,"); err("or it may be not responding. Report this to"); err("mmcclelland@delphi.com"); return -1; } + if (sensor == 0) { + rc = ov511_i2c_read(dev, OV7610_REG_COM_I); + + if (rc < 0) { + err("Error detecting sensor type"); + return -1; + } + else if((rc & 3) == 3) { + printk("ov511: Sensor is an OV7610\n"); + ov511->sensor = SEN_OV7610; + } + else if((rc & 3) == 1) { + printk("ov511: Sensor is an OV7620AE\n"); + ov511->sensor = SEN_OV7620AE; + } + else if((rc & 3) == 0) { + printk("ov511: Sensor is an OV7620\n"); + ov511->sensor = SEN_OV7620; + } + else { + err("Unknown image sensor version: %d", rc & 3); + return -1; + } + } + else { /* sensor != 0; user overrode detection */ + ov511->sensor = sensor; + printk("ov511: Sensor set to type %d\n", ov511->sensor); + } + return 0; } @@ -1890,9 +1987,9 @@ {OV511_REG_BUS, OV511_REG_SYSTEM_RESET, 0x3d}, {OV511_DONE_BUS, 0x0, 0x00}, }; - static struct ov511_regvals aRegvalsNorm[] = - {{OV511_REG_BUS, 0x20, 1}, -#if 1 + + static struct ov511_regvals aRegvalsNorm7610[] = + {{OV511_REG_BUS, 0x20, 0x01}, {OV511_REG_BUS, 0x52, 0x02}, {OV511_REG_BUS, 0x52, 0x00}, {OV511_REG_BUS, 0x31, 0x1f}, /* 0f */ @@ -1907,16 +2004,14 @@ {OV511_REG_BUS, 0x78, 0x06}, {OV511_REG_BUS, 0x79, 0x03}, - {OV511_I2C_BUS, 0x10, 0xff}, {OV511_I2C_BUS, 0x16, 0x06}, - {OV511_I2C_BUS, 0x28, 0x24}, /* 24 */ + {OV511_I2C_BUS, 0x28, 0x24}, {OV511_I2C_BUS, 0x2b, 0xac}, {OV511_I2C_BUS, 0x05, 0x00}, {OV511_I2C_BUS, 0x06, 0x00}, {OV511_I2C_BUS, 0x12, 0x00}, -// {OV511_I2C_BUS, 0x13, 0x00}, {OV511_I2C_BUS, 0x38, 0x81}, {OV511_I2C_BUS, 0x28, 0x24}, /* 0c */ {OV511_I2C_BUS, 0x05, 0x00}, @@ -1931,26 +2026,64 @@ {OV511_I2C_BUS, 0x29, 0x03}, /* 91 */ {OV511_I2C_BUS, 0x2a, 0x04}, {OV511_I2C_BUS, 0x2c, 0xfe}, - {OV511_I2C_BUS, 0x2d, 0x93}, /* d7 */ {OV511_I2C_BUS, 0x30, 0x71}, {OV511_I2C_BUS, 0x31, 0x60}, {OV511_I2C_BUS, 0x32, 0x26}, {OV511_I2C_BUS, 0x33, 0x20}, {OV511_I2C_BUS, 0x34, 0x48}, {OV511_I2C_BUS, 0x12, 0x24}, -// {OV511_I2C_BUS, 0x13, 0x01}, {OV511_I2C_BUS, 0x11, 0x01}, {OV511_I2C_BUS, 0x0c, 0x24}, {OV511_I2C_BUS, 0x0d, 0x24}, -#endif {OV511_DONE_BUS, 0x0, 0x00}, }; - /* Set altsetting 0 */ - if (usb_set_interface(dev, ov511->iface, 0) < 0) { - err("usb_set_interface error"); - return -EBUSY; - } + static struct ov511_regvals aRegvalsNorm7620[] = + {{OV511_REG_BUS, 0x20, 0x01}, + {OV511_REG_BUS, 0x52, 0x02}, + {OV511_REG_BUS, 0x52, 0x00}, + {OV511_REG_BUS, 0x31, 0x1f}, + {OV511_REG_BUS, 0x70, 0x3f}, + {OV511_REG_BUS, 0x71, 0x3f}, + {OV511_REG_BUS, 0x72, 0x01}, + {OV511_REG_BUS, 0x73, 0x01}, + {OV511_REG_BUS, 0x74, 0x01}, + {OV511_REG_BUS, 0x75, 0x01}, + {OV511_REG_BUS, 0x76, 0x01}, + {OV511_REG_BUS, 0x77, 0x01}, + {OV511_REG_BUS, 0x78, 0x06}, + {OV511_REG_BUS, 0x79, 0x03}, + + {OV511_I2C_BUS, 0x10, 0xff}, + {OV511_I2C_BUS, 0x16, 0x06}, + {OV511_I2C_BUS, 0x28, 0x24}, + {OV511_I2C_BUS, 0x2b, 0xac}, + + {OV511_I2C_BUS, 0x12, 0x00}, + + {OV511_I2C_BUS, 0x28, 0x24}, + {OV511_I2C_BUS, 0x05, 0x00}, + {OV511_I2C_BUS, 0x0f, 0x05}, + {OV511_I2C_BUS, 0x15, 0x01}, + {OV511_I2C_BUS, 0x23, 0x00}, + {OV511_I2C_BUS, 0x24, 0x10}, + {OV511_I2C_BUS, 0x25, 0x8a}, + {OV511_I2C_BUS, 0x26, 0xa2}, + {OV511_I2C_BUS, 0x27, 0xe2}, + {OV511_I2C_BUS, 0x29, 0x03}, + {OV511_I2C_BUS, 0x2a, 0x00}, + {OV511_I2C_BUS, 0x2c, 0xfe}, + {OV511_I2C_BUS, 0x30, 0x71}, + {OV511_I2C_BUS, 0x31, 0x60}, + {OV511_I2C_BUS, 0x32, 0x26}, + {OV511_I2C_BUS, 0x33, 0x20}, + {OV511_I2C_BUS, 0x34, 0x48}, + {OV511_I2C_BUS, 0x12, 0x24}, + {OV511_I2C_BUS, 0x11, 0x01}, + {OV511_I2C_BUS, 0x0c, 0x24}, + {OV511_I2C_BUS, 0x0d, 0x24}, + {OV511_DONE_BUS, 0x0, 0x00}, + }; memcpy(&ov511->vdev, &ov511_template, sizeof(ov511_template)); @@ -1966,18 +2099,17 @@ if ((rc = ov511_write_regvals(dev, aRegvalsInit))) return rc; - if(ov7610_configure(dev) < 0) { + if(ov7610_configure(ov511) < 0) { err("failed to configure OV7610"); goto error; } + ov511_set_packet_size(ov511, 0); + /* Disable compression */ - if (ov511_reg_write(dev, OV511_OMNICE_ENABLE, 0x00) < 0) { - err("disable compression: command failed"); + if (ov511_reg_write(dev, OV511_OMNICE_ENABLE, 0x00) < 0) goto error; - } - ov511->compress = 0; ov511->snap_enabled = snapshot; /* Set default sizes in case IOCTL (VIDIOCMCAPTURE) is not used @@ -1990,15 +2122,27 @@ ov511->frame[1].bytes_read = 0; /* Initialize to DEFAULT_WIDTH, DEFAULT_HEIGHT, YUV4:2:0 */ - if ((rc = ov511_write_regvals(dev, aRegvalsNorm))) goto error; - if ((rc = ov511_mode_init_regs(ov511, DEFAULT_WIDTH, DEFAULT_HEIGHT, - VIDEO_PALETTE_RGB24, 0)) < 0) goto error; + + if (ov511->sensor == SEN_OV7620) { + if (ov511_write_regvals(dev, aRegvalsNorm7620)) goto error; + } + else { + if (ov511_write_regvals(dev, aRegvalsNorm7610)) goto error; + } + + if (ov511_mode_init_regs(ov511, DEFAULT_WIDTH, DEFAULT_HEIGHT, + VIDEO_PALETTE_RGB24, 0) < 0) goto error; if (autoadjust) { if (ov511_i2c_write(dev, 0x13, 0x01) < 0) goto error; + if (ov511_i2c_write(dev, 0x2d, + ov511->sensor==SEN_OV7620?0x91:0x93) < 0) goto error; } else { - if (ov511_i2c_write(dev, 0x13, 0x00) < 0 ) goto error; + if (ov511_i2c_write(dev, 0x13, 0x00) < 0) goto error; + if (ov511_i2c_write(dev, 0x2d, + ov511->sensor==SEN_OV7620?0x81:0x83) < 0) goto error; + ov511_i2c_write(dev, 0x28, ov511_i2c_read(dev, 0x28) | 8); } return 0; @@ -2009,6 +2153,7 @@ &dev->actconfig->interface[ov511->iface]); kfree(ov511); + ov511 = NULL; return -EBUSY; } @@ -2027,10 +2172,11 @@ interface = &dev->actconfig->interface[ifnum].altsetting[0]; - /* Is it an OV511? */ + /* Is it an OV511/OV511+? */ if (dev->descriptor.idVendor != 0x05a9) return NULL; - if (dev->descriptor.idProduct != 0x0511) + if (dev->descriptor.idProduct != 0x0511 + && dev->descriptor.idProduct != 0xA511) return NULL; /* Checking vendor/product should be enough, but what the hell */ @@ -2039,9 +2185,6 @@ if (interface->bInterfaceSubClass != 0x00) return NULL; - /* We found one */ - printk(KERN_INFO "ov511: USB OV511-based camera found\n"); - if ((ov511 = kmalloc(sizeof(*ov511), GFP_KERNEL)) == NULL) { err("couldn't kmalloc ov511 struct"); return NULL; @@ -2052,15 +2195,24 @@ ov511->dev = dev; ov511->iface = interface->bInterfaceNumber; + if (dev->descriptor.idProduct == 0x0511) { + info("USB OV511 camera found"); + ov511->bridge = BRG_OV511; + } + else if (dev->descriptor.idProduct == 0xA511) { + info("USB OV511+ camera found"); + ov511->bridge = BRG_OV511PLUS; + } + rc = ov511_reg_read(dev, OV511_REG_SYSTEM_CUSTOM_ID); if (rc < 0) { err("Unable to read camera bridge registers"); - return NULL; + goto error; } switch(ov511->customid = rc) { case 0: /* This also means that no custom ID was set */ - printk("ov511: Camera is probably a MediaForte MV300\n"); + printk("ov511: Camera is a generic model (no ID)\n"); break; case 3: printk("ov511: Camera is a D-Link DSB-C300\n"); @@ -2077,6 +2229,11 @@ case 36: printk("ov511: Camera is a Koala-Cam\n"); break; + case 38: + printk("ov511: Camera is a Lifeview USB Life TV\n"); + printk("ov511: This device is not supported, exiting...\n"); + goto error; + break; case 100: printk("ov511: Camera is a Lifeview RoboCam\n"); break; @@ -2090,9 +2247,13 @@ err("Specific camera type (%d) not recognized", rc); err("Please contact mmcclelland@delphi.com to request"); err("support for your camera."); - return NULL; } +// if (ov511->bridge == BRG_OV511PLUS) { +// err("Sorry, the OV511+ chip is not supported yet"); +// goto error; +// } + if (!ov511_configure(ov511)) { ov511->user=0; init_MUTEX(&ov511->lock); /* to 1 == available */ @@ -2100,10 +2261,18 @@ } else { err("Failed to configure camera"); - return NULL; + goto error; } return ov511; + +error: + if (ov511) { + kfree(ov511); + ov511 = NULL; + } + + return NULL; } static void ov511_disconnect(struct usb_device *dev, void *ptr) @@ -2147,7 +2316,7 @@ usb_unlink_urb(ov511->sbuf[0].urb); usb_free_urb(ov511->sbuf[0].urb); ov511->sbuf[0].urb = NULL; - } + } /* Free the memory */ if (!ov511->user) { diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/ov511.h linux/drivers/usb/ov511.h --- v2.3.99-pre3/linux/drivers/usb/ov511.h Tue Mar 14 19:10:40 2000 +++ linux/drivers/usb/ov511.h Mon Mar 27 09:44:58 2000 @@ -1,8 +1,6 @@ #ifndef __LINUX_OV511_H #define __LINUX_OV511_H -//#include - #define OV511_DEBUG /* Turn on debug messages */ #ifdef OV511_DEBUG @@ -75,14 +73,16 @@ #define OV511_REG_SYSTEM_CLOCK_DIVISOR 0x51 #define OV511_REG_SYSTEM_SNAPSHOT 0x52 #define OV511_REG_SYSTEM_INIT 0x53 +#define OV511_REG_SYSTEM_PWR_CLK 0x54 /* OV511+ only */ +#define OV511_REG_SYSTEM_LED_CTL 0x55 /* OV511+ only */ #define OV511_REG_SYSTEM_USER_DEFINED 0x5E #define OV511_REG_SYSTEM_CUSTOM_ID 0x5F /* OmniCE register numbers */ -#define OV511_OMNICE_PREDICATION_HORIZ_Y 0x70 -#define OV511_OMNICE_PREDICATION_HORIZ_UV 0x71 -#define OV511_OMNICE_PREDICATION_VERT_Y 0x72 -#define OV511_OMNICE_PREDICATION_VERT_UV 0x73 +#define OV511_OMNICE_PREDICTION_HORIZ_Y 0x70 +#define OV511_OMNICE_PREDICTION_HORIZ_UV 0x71 +#define OV511_OMNICE_PREDICTION_VERT_Y 0x72 +#define OV511_OMNICE_PREDICTION_VERT_UV 0x73 #define OV511_OMNICE_QUANTIZATION_HORIZ_Y 0x74 #define OV511_OMNICE_QUANTIZATION_HORIZ_UV 0x75 #define OV511_OMNICE_QUANTIZATION_VERT_Y 0x76 @@ -94,15 +94,25 @@ #define OV511_OMNICE_UV_LUT_BEGIN 0xA0 #define OV511_OMNICE_UV_LUT_END 0xBF -/* Alternate numbers for various max packet sizes */ -#define OV511_ALTERNATE_SIZE_992 0 -#define OV511_ALTERNATE_SIZE_993 1 -#define OV511_ALTERNATE_SIZE_768 2 -#define OV511_ALTERNATE_SIZE_769 3 -#define OV511_ALTERNATE_SIZE_512 4 -#define OV511_ALTERNATE_SIZE_513 5 -#define OV511_ALTERNATE_SIZE_257 6 -#define OV511_ALTERNATE_SIZE_0 7 +/* Alternate numbers for various max packet sizes (OV511 only) */ +#define OV511_ALT_SIZE_992 0 +#define OV511_ALT_SIZE_993 1 +#define OV511_ALT_SIZE_768 2 +#define OV511_ALT_SIZE_769 3 +#define OV511_ALT_SIZE_512 4 +#define OV511_ALT_SIZE_513 5 +#define OV511_ALT_SIZE_257 6 +#define OV511_ALT_SIZE_0 7 + +/* Alternate numbers for various max packet sizes (OV511+ only) */ +#define OV511PLUS_ALT_SIZE_0 0 +#define OV511PLUS_ALT_SIZE_33 1 +#define OV511PLUS_ALT_SIZE_129 2 +#define OV511PLUS_ALT_SIZE_257 3 +#define OV511PLUS_ALT_SIZE_385 4 +#define OV511PLUS_ALT_SIZE_513 5 +#define OV511PLUS_ALT_SIZE_769 6 +#define OV511PLUS_ALT_SIZE_961 7 /* ov7610 registers */ #define OV7610_REG_GAIN 0x00 @@ -154,7 +164,8 @@ #define SCRATCH_BUF_SIZE 384 #define FRAMES_PER_DESC 10 /* FIXME - What should this be? */ -#define FRAME_SIZE_PER_DESC 993 /* FIXME - Shouldn't be hardcoded */ +#define FRAME_SIZE_PER_DESC 993 /* FIXME - Deprecated */ +#define MAX_FRAME_SIZE_PER_DESC 993 /* For statically allocated stuff */ // FIXME - should this be 0x81 (endpoint address) or 0x01 (endpoint number)? #define OV511_ENDPOINT_ADDRESS 0x81 /* Address of isoc endpoint */ @@ -171,6 +182,19 @@ unsigned char reg, unsigned char value); +/* Bridge types */ +enum { + BRG_OV511, + BRG_OV511PLUS, +}; + +/* Sensor types */ +enum { + SEN_UNKNOWN, + SEN_OV7610, + SEN_OV7620, + SEN_OV7620AE, +}; enum { STATE_SCANNING, /* Scanning for start */ @@ -214,7 +238,7 @@ int hdrheight; /* Height */ int sub_flag; /* Sub-capture mode for this frame? */ - int format; /* Format for this frame */ + int format; /* Format for this frame */ int segsize; /* How big is each segment from the camera? */ volatile int grabstate; /* State of grabbing */ @@ -274,6 +298,11 @@ wait_queue_head_t wq; /* Processes waiting */ int snap_enabled; /* Snapshot mode enabled */ + + int bridge; /* Type of bridge (OV511 or OV511+) */ + int sensor; /* Type of image sensor chip */ + + int packet_size; /* Frame size per isoc desc */ }; #endif diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/pegasus.c linux/drivers/usb/pegasus.c --- v2.3.99-pre3/linux/drivers/usb/pegasus.c Mon Mar 27 08:08:28 2000 +++ linux/drivers/usb/pegasus.c Tue Apr 11 09:57:43 2000 @@ -16,11 +16,13 @@ #include -static const char *version = __FILE__ ": v0.3.5 2000/03/21 Written by Petko Manolov (petkan@spct.net)\n"; +static const char *version = __FILE__ ": v0.3.9 2000/04/11 Written by Petko Manolov (petkan@spct.net)\n"; #define PEGASUS_MTU 1500 -#define PEGASUS_MAX_MTU 1536 +#define PEGASUS_MAX_MTU 1536 +#define SROM_WRITE 0x01 +#define SROM_READ 0x02 #define PEGASUS_TX_TIMEOUT (HZ*5) #define ALIGN(x) x __attribute__((aligned(16))) @@ -51,12 +53,18 @@ static struct usb_eth_dev usb_dev_id[] = { - { "D-Link DSB-650TX", 0x2001, 0x4001, NULL }, - { "Linksys USB100TX", 0x066b, 0x2203, NULL }, - { "SMC 202 USB Ethernet", 0x0707, 0x0200, NULL }, - { "ADMtek AN986 (Pegasus) USB Ethernet", 0x07a6, 0x0986, NULL }, - { "Accton USB 10/100 Ethernet Adapter", 0x083a, 0x1046, NULL }, - { NULL, 0, 0, NULL } + {"Billionton USB-100", 0x08dd, 0x0986, NULL}, + {"Corega FEter USB-TX", 0x7aa, 0x0004, NULL}, + {"MELCO/BUFFALO LUA-TX", 0x0411, 0x0001, NULL}, + {"D-Link DSB-650TX", 0x2001, 0x4001, NULL}, + {"D-Link DSB-650TX", 0x2001, 0x4002, NULL}, + {"D-Link DSB-650TX(PNA)", 0x2001, 0x4003, NULL}, + {"Linksys USB100TX", 0x066b, 0x2203, NULL}, + {"Linksys USB100TX", 0x066b, 0x2204, NULL}, + {"SMC 202 USB Ethernet", 0x0707, 0x0200, NULL}, + {"ADMtek AN986 \"Pegasus\" USB Ethernet (eval board)", 0x07a6, 0x0986, NULL}, + {"Accton USB 10/100 Ethernet Adapter", 0x083a, 0x1046, NULL}, + {NULL, 0, 0, NULL} }; @@ -105,10 +113,10 @@ return 1; } -static int pegasus_read_srom_word(struct usb_device *dev, __u8 index, __u16 *retdata) +static int pegasus_rw_srom_word(struct usb_device *dev, __u8 index, __u16 *retdata, __u8 direction) { int i; - __u8 data[4] = { index, 0, 0, 0x02 }; + __u8 data[4] = { index, 0, 0, direction }; pegasus_set_registers(dev, 0x20, 4, data); for (i = 0; i < 100; i++) { @@ -120,7 +128,7 @@ } } - warn("read_srom_word() failed"); + warn("pegasus_rw_srom_word() failed"); return 1; } @@ -128,7 +136,7 @@ { int i; for (i = 0; i < 3; i++) - if (pegasus_read_srom_word(dev, i, (__u16 *)&id[i * 2])) + if (pegasus_rw_srom_word(dev,i,(__u16 *)&id[i * 2],SROM_READ)) return 1; return 0; } @@ -170,8 +178,9 @@ return 2; if ((~temp & 4) && !loopback) { - err("link NOT established - %x", temp); - return 3; + warn("%s: link NOT established (0x%x), check the cable.", + dev->name, temp); + /* return 3; FIXME */ } if (pegasus_read_phy_word(usb, 5, &partmedia)) @@ -376,13 +385,14 @@ if (net->flags & IFF_PROMISC) { info("%s: Promiscuous mode enabled", net->name); - pegasus_set_register(pegasus->usb, 2, 0x04); +/* pegasus_set_register(pegasus->usb, 2, 0x04); FIXME */ } else if ((net->mc_count > multicast_filter_limit) || (net->flags & IFF_ALLMULTI)) { pegasus_set_register(pegasus->usb, 0, 0xfa); pegasus_set_register(pegasus->usb, 2, 0); + info("%s set allmulti", net->name); } else { - dbg("%s: set Rx mode", net->name); + info("%s: set Rx mode", net->name); } netif_wake_queue(net); @@ -395,18 +405,19 @@ while ( usb_dev_id[i].name ) { if ( (usb_dev_id[i].vendor == vendor) && (usb_dev_id[i].device == product) ) - return 0; + return i; i++; } - return 1; + return -1; } static void * pegasus_probe(struct usb_device *dev, unsigned int ifnum) { struct net_device *net; struct pegasus *pegasus; + int dev_indx; - if ( check_device_ids(dev->descriptor.idVendor, dev->descriptor.idProduct) ) { + if ( (dev_indx = check_device_ids(dev->descriptor.idVendor, dev->descriptor.idProduct)) == -1 ) { return NULL; } @@ -449,11 +460,11 @@ FILL_BULK_URB(&pegasus->tx_urb, dev, usb_sndbulkpipe(dev, 2), pegasus->tx_buff, PEGASUS_MAX_MTU, pegasus_write_bulk, pegasus); - FILL_INT_URB(&pegasus->intr_urb, dev, usb_rcvintpipe(dev, 0), + FILL_INT_URB(&pegasus->intr_urb, dev, usb_rcvintpipe(dev, 3), pegasus->intr_buff, 8, pegasus_irq, pegasus, 250); - printk(KERN_INFO "%s: ADMtek AN986 Pegasus usb device\n", net->name); + printk(KERN_INFO "%s: %s\n", net->name, usb_dev_id[dev_indx].name); return pegasus; } diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/printer.c linux/drivers/usb/printer.c --- v2.3.99-pre3/linux/drivers/usb/printer.c Fri Mar 10 16:40:45 2000 +++ linux/drivers/usb/printer.c Wed Apr 5 16:58:38 2000 @@ -160,10 +160,13 @@ if (usblp->used) return -EBUSY; - if ((retval = usblp_check_status(usblp))) + MOD_INC_USE_COUNT; + + if ((retval = usblp_check_status(usblp))) { + MOD_DEC_USE_COUNT; return retval; + } - MOD_INC_USE_COUNT; usblp->used = 1; file->private_data = usblp; @@ -179,17 +182,18 @@ { struct usblp *usblp = file->private_data; - MOD_DEC_USE_COUNT; usblp->used = 0; if (usblp->dev) { usb_unlink_urb(&usblp->readurb); usb_unlink_urb(&usblp->writeurb); + MOD_DEC_USE_COUNT; return 0; } usblp_table[usblp->minor] = NULL; kfree(usblp); + MOD_DEC_USE_COUNT; return 0; } diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/scanner.c linux/drivers/usb/scanner.c --- v2.3.99-pre3/linux/drivers/usb/scanner.c Thu Mar 2 14:36:23 2000 +++ linux/drivers/usb/scanner.c Mon Mar 27 09:44:58 2000 @@ -1,7 +1,7 @@ /* -*- linux-c -*- */ /* - * Driver for USB Scanners (linux-2.3.42) + * Driver for USB Scanners (linux-2.3.99-pre3-7) * * Copyright (C) 1999, 2000 David E. Nelson * @@ -148,8 +148,29 @@ * - Increased the timeout parameter in read_scanner() to 120 Secs. * * + * 0.4.2 3/23/2000 + * + * - Added Umax 1236U ID. Thanks to Philipp Baer . + * - Added Primax, ReadyScan, Visioneer, Colorado, and Genius ID's. + * Thanks to Adrian Perez Jorge . + * - Fixed error number reported for non-existant devices. Thanks to + * Spyridon Papadimitriou . + * - Added Acer Prisascan 620U ID's. Thanks to Joao . + * - Replaced __initcall() with module_init()/module_exit(). Updates + * from patch-2.3.48. + * - Replaced file_operations structure with new syntax. Updates + * from patch-2.3.49. + * - Changed #include "usb.h" to #include + * - Added #define SCN_IOCTL to exclude development areas + * since 2.4.x is about to be released. This mainly affects the + * ioctl() stuff. See scanner.h for more details. + * - Changed the return value for signal_pending() from -ERESTARTSYS to + * -EINTR. + * + * * TODO * + * - Performance * - Select/poll methods * - More testing * - Proper registry/assignment for LM9830 ioctl's @@ -214,7 +235,7 @@ if (!p_scn_table[scn_minor]) { err("open_scanner(%d): invalid scn_minor", scn_minor); - return -ENOIOCTLCMD; + return -ENODEV; } scn = p_scn_table[scn_minor]; @@ -255,7 +276,7 @@ if (!p_scn_table[scn_minor]) { err("close_scanner(%d): invalid scn_minor", scn_minor); - return -ENOIOCTLCMD; + return -ENODEV; } scn = p_scn_table[scn_minor]; @@ -279,6 +300,8 @@ ssize_t bytes_written = 0; /* Overall count of bytes written */ ssize_t ret = 0; + kdev_t scn_minor; + int this_write; /* Number of bytes to write */ int partial; /* Number of bytes successfully written */ int result = 0; @@ -287,6 +310,8 @@ scn = file->private_data; + scn_minor = scn->scn_minor; + obuf = scn->obuf; dev = scn->scn_dev; @@ -294,7 +319,7 @@ while (count > 0) { if (signal_pending(current)) { - ret = -ERESTARTSYS; + ret = -EINTR; break; } @@ -306,14 +331,14 @@ } result = usb_bulk_msg(dev,usb_sndbulkpipe(dev, scn->bulk_out_ep), obuf, this_write, &partial, 60*HZ); - dbg("write stats(%d): result:%d this_write:%d partial:%d", scn->scn_minor, result, this_write, partial); + dbg("write stats(%d): result:%d this_write:%d partial:%d", scn_minor, result, this_write, partial); if (result == USB_ST_TIMEOUT) { /* NAK -- shouldn't happen */ warn("write_scanner: NAK recieved."); ret = -ETIME; break; } else if (result < 0) { /* We should not get any I/O errors */ - warn("write_scanner(%d): funky result: %d. Please notify the maintainer.", scn->scn_minor, result); + warn("write_scanner(%d): funky result: %d. Please notify the maintainer.", scn_minor, result); ret = -EIO; break; } @@ -322,7 +347,7 @@ if (partial) { unsigned char cnt, cnt_max; cnt_max = (partial > 24) ? 24 : partial; - printk(KERN_DEBUG "dump(%d): ", scn->scn_minor); + printk(KERN_DEBUG "dump(%d): ", scn_minor); for (cnt=0; cnt < cnt_max; cnt++) { printk("%X ", obuf[cnt]); } @@ -355,8 +380,10 @@ struct scn_usb_data *scn; struct usb_device *dev; - ssize_t bytes_read = 0; /* Overall count of bytes_read */ - ssize_t ret = 0; + ssize_t bytes_read; /* Overall count of bytes_read */ + ssize_t ret; + + kdev_t scn_minor; int partial; /* Number of bytes successfully read */ int this_read; /* Max number of bytes to read */ @@ -366,29 +393,32 @@ scn = file->private_data; + scn_minor = scn->scn_minor; + ibuf = scn->ibuf; dev = scn->scn_dev; bytes_read = 0; + ret = 0; while (count) { if (signal_pending(current)) { - ret = -ERESTARTSYS; + ret = -EINTR; break; } this_read = (count >= IBUF_SIZE) ? IBUF_SIZE : count; result = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, scn->bulk_in_ep), ibuf, this_read, &partial, 120*HZ); - dbg("read stats(%d): result:%d this_read:%d partial:%d", scn->scn_minor, result, this_read, partial); + dbg("read stats(%d): result:%d this_read:%d partial:%d", scn_minor, result, this_read, partial); if (result == USB_ST_TIMEOUT) { /* NAK -- shouldn't happen */ - warn("read_scanner(%d): NAK received", scn->scn_minor); + warn("read_scanner(%d): NAK received", scn_minor); ret = -ETIME; break; } else if ((result < 0) && (result != USB_ST_DATAUNDERRUN)) { - warn("read_scanner(%d): funky result:%d. Please notify the maintainer.", scn->scn_minor, (int)result); + warn("read_scanner(%d): funky result:%d. Please notify the maintainer.", scn_minor, (int)result); ret = -EIO; break; } @@ -397,7 +427,7 @@ if (partial) { unsigned char cnt, cnt_max; cnt_max = (partial > 24) ? 24 : partial; - printk(KERN_DEBUG "dump(%d): ", scn->scn_minor); + printk(KERN_DEBUG "dump(%d): ", scn_minor); for (cnt=0; cnt < cnt_max; cnt++) { printk("%X ", ibuf[cnt]); } @@ -492,15 +522,17 @@ if (dev->descriptor.idVendor == 0x1606) { /* Umax */ if (dev->descriptor.idProduct == 0x0010 || /* Astra 1220U */ - dev->descriptor.idProduct == 0x0030) { /* Astra 2000U */ + dev->descriptor.idProduct == 0x0030 || /* Astra 2000U */ + dev->descriptor.idProduct == 0x0002) { /* Astra 1236U */ valid_device = 1; break; } } if (dev->descriptor.idVendor == 0x04b8) { /* Seiko/Epson Corp. */ - if (dev->descriptor.idProduct == 0x0101 || /* Perfection 636 */ - dev->descriptor.idProduct == 0x0104) { /* Perfection 1200U */ + if (dev->descriptor.idProduct == 0x0101 || /* Perfection 636U and 636Photo */ + dev->descriptor.idProduct == 0x0103 || /* Perfection 610 */ + dev->descriptor.idProduct == 0x0104) { /* Perfection 1200U and 1200Photo */ valid_device = 1; break; } @@ -526,15 +558,56 @@ } } + if (dev->descriptor.idVendor == 0x0461) { /* Primax/Colorado */ + if (dev->descriptor.idProduct == 0x0300 || /* G2-300 #1 */ + dev->descriptor.idProduct == 0x0380 || /* G2-600 #1 */ + dev->descriptor.idProduct == 0x0301 || /* G2E-300 */ + dev->descriptor.idProduct == 0x0381 || /* ReadyScan 636i */ + dev->descriptor.idProduct == 0x0302 || /* G2-300 #2 */ + dev->descriptor.idProduct == 0x0382 || /* G2-600 #2 */ + dev->descriptor.idProduct == 0x0303 || /* G2E-300 */ + dev->descriptor.idProduct == 0x0383 || /* G2E-600 */ + dev->descriptor.idProduct == 0x0340 || /* Colorado USB 9600 */ + dev->descriptor.idProduct == 0x0360 || /* Colorado USB 19200 */ + dev->descriptor.idProduct == 0x0341 || /* Colorado 600u */ + dev->descriptor.idProduct == 0x0361) { /* Colorado 1200u */ + valid_device = 1; + break; + } + } + + if (dev->descriptor.idVendor == 0x04a7) { /* Visioneer */ + if (dev->descriptor.idProduct == 0x0221 || /* OneTouch 5300 */ + dev->descriptor.idProduct == 0x0221 || /* OneTouch 7600 */ + dev->descriptor.idProduct == 0x0231) { /* 6100 */ + valid_device = 1; + break; + } + } + + if (dev->descriptor.idVendor == 0x0458) { /* Genius */ + if(dev->descriptor.idProduct == 0x2001) { /* ColorPage-Vivid Pro */ + valid_device = 1; + break; + } + } + + if (dev->descriptor.idVendor == 0x04a5) { /* Acer */ + if(dev->descriptor.idProduct == 0x2060) { /* Prisa Acerscan 620U */ + valid_device = 1; + break; + } + } + if (dev->descriptor.idVendor == vendor && /* User specified */ dev->descriptor.idProduct == product) { /* User specified */ valid_device = 1; break; } - - + + } while (0); - + if (!valid_device) return NULL; /* We didn't find anything pleasing */ @@ -714,6 +787,7 @@ kfree (scn); } +#ifdef SCN_IOCTL static int ioctl_scanner(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) @@ -728,7 +802,7 @@ if (!p_scn_table[scn_minor]) { err("ioctl_scanner(%d): invalid scn_minor", scn_minor); - return -ENOIOCTLCMD; + return -ENODEV; } dev = p_scn_table[scn_minor]->scn_dev; @@ -790,12 +864,15 @@ } 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, }; @@ -810,12 +887,14 @@ SCN_BASE_MNR }; -void __exit usb_scanner_exit(void) +void __exit +usb_scanner_exit(void) { usb_deregister(&scanner_driver); } -int __init usb_scanner_init(void) +int __init +usb_scanner_init (void) { if (usb_register(&scanner_driver) < 0) return -1; diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/scanner.h linux/drivers/usb/scanner.h --- v2.3.99-pre3/linux/drivers/usb/scanner.h Fri Mar 10 16:40:45 2000 +++ linux/drivers/usb/scanner.h Mon Mar 27 09:44:58 2000 @@ -6,8 +6,15 @@ #include #include #include + // #define DEBUG + +/* Enable to activate the ioctl interface. This is mainly meant for */ +/* development purposes until an ioctl number is officially registered */ +// #define SCN_IOCTL + #include +// #include "usb.h" /* WARNING: These DATA_DUMP's can produce a lot of data. Caveat Emptor. */ // #define RD_DATA_DUMP /* Enable to dump data - limited to 24 bytes */ diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/serial/Makefile linux/drivers/usb/serial/Makefile --- v2.3.99-pre3/linux/drivers/usb/serial/Makefile Sun Mar 19 18:35:31 2000 +++ linux/drivers/usb/serial/Makefile Mon Mar 27 14:25:28 2000 @@ -1,67 +1,11 @@ # -# Makefile for the kernel USB device drivers. +# Makefile for the USB serial device drivers. # -# Subdirs. - -SUB_DIRS := -MOD_SUB_DIRS := $(SUB_DIRS) -MOD_IN_SUB_DIRS := $(SUB_DIRS) -ALL_SUB_DIRS := $(SUB_DIRS) - -# The target object and module list name. - -O_TARGET := serial.o +O_TARGET := usb-serial.o M_OBJS := usb-serial.o -O_OBJS := usb-serial.o +O_OBJS := usbserial.o visor.o whiteheat.o ftdi_sio.o keyspan_pda.o MOD_LIST_NAME := USB_SERIAL_MODULES -# Objects that export symbols. - -# Multipart objects. - -# Optional parts of multipart objects. - -# Object file lists. - -obj-y := -obj-m := -obj-n := -obj- := - -# Each configuration option enables a list of files. - -obj-$(CONFIG_USB_SERIAL) += usb-serial.o - -# Extract lists of the multi-part drivers. -# The 'int-*' lists are the intermediate files used to build the multi's. - -multi-y := $(filter $(list-multi), $(obj-y)) -multi-m := $(filter $(list-multi), $(obj-m)) -int-y := $(sort $(foreach m, $(multi-y), $($(basename $(m))-objs))) -int-m := $(sort $(foreach m, $(multi-m), $($(basename $(m))-objs))) - -# Files that are both resident and modular: remove from modular. - -obj-m := $(filter-out $(obj-y), $(obj-m)) -int-m := $(filter-out $(int-y), $(int-m)) - -# Take multi-part drivers out of obj-y and put components in. - -obj-y := $(filter-out $(list-multi), $(obj-y)) $(int-y) - -# Translate to Rules.make lists. - -O_OBJS := $(sort $(filter-out $(export-objs), $(obj-y))) -OX_OBJS := $(sort $(filter $(export-objs), $(obj-y))) -M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m))) -MX_OBJS := $(sort $(filter $(export-objs), $(obj-m))) -MI_OBJS := $(sort $(filter-out $(export-objs), $(int-m))) -MIX_OBJS := $(sort $(filter $(export-objs), $(int-m))) - -# The global Rules.make. - include $(TOPDIR)/Rules.make - -# Link rules for multi-part drivers. diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/serial/ezusb_convert.pl linux/drivers/usb/serial/ezusb_convert.pl --- v2.3.99-pre3/linux/drivers/usb/serial/ezusb_convert.pl Fri Mar 10 16:40:45 2000 +++ linux/drivers/usb/serial/ezusb_convert.pl Mon Apr 10 22:54:09 2000 @@ -27,6 +27,8 @@ push(@records, [$addr, \@bytes]); } +@sorted_records = sort { $a->[0] <=> $b->[0] } @records; + print <<"EOF"; /* * ${basename}_fw.h @@ -39,7 +41,7 @@ EOF print "static const struct ezusb_hex_record ${basename}_firmware[] = {\n"; -foreach $r (@records) { +foreach $r (@sorted_records) { printf("{ 0x%04x,\t%d,\t{", $r->[0], scalar(@{$r->[1]})); print join(", ", map {sprintf('0x%02x', $_);} @{$r->[1]}); print "} },\n"; diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/serial/ftdi_sio.c linux/drivers/usb/serial/ftdi_sio.c --- v2.3.99-pre3/linux/drivers/usb/serial/ftdi_sio.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/serial/ftdi_sio.c Wed Apr 5 16:58:38 2000 @@ -0,0 +1,728 @@ +/* + * USB FTDI SIO driver + * + * (C) Copyright (C) 1999, 2000 + * Greg Kroah-Hartman (greg@kroah.com) + * Bill Ryder (bryder@sgi.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. + * + * See Documentation/usb/usb-serial.txt for more information on using this driver + * + * (04/04/2000) Bill Ryder + * Fixed bugs in TCGET/TCSET ioctls (by removing them - they are + * handled elsewhere in the serial driver chain). + * + * (03/30/2000) Bill Ryder + * Implemented lots of ioctls + * Fixed a race condition in write + * Changed some dbg's to errs + * + * (03/26/2000) gkh + * Split driver up into device specific pieces. + * + */ + +/* Bill Ryder - bryder@sgi.com - wrote the FTDI_SIO implementation */ +/* Thanx to FTDI for so kindly providing details of the protocol required */ +/* to talk to the device */ + + +#include + +#ifdef CONFIG_USB_SERIAL_FTDI_SIO + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_USB_SERIAL_DEBUG + #define DEBUG +#else + #undef DEBUG +#endif +#include + +#include "usb-serial.h" + +#include "ftdi_sio.h" + +#define FTDI_VENDOR_ID 0x0403 +#define FTDI_SIO_SERIAL_CONVERTER_ID 0x8372 + +/* function prototypes for a FTDI serial converter */ +static int ftdi_sio_startup (struct usb_serial *serial); +static int ftdi_sio_open (struct usb_serial_port *port, struct file *filp); +static void ftdi_sio_close (struct usb_serial_port *port, struct file *filp); +static int ftdi_sio_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); +static void ftdi_sio_write_bulk_callback (struct urb *urb); +static void ftdi_sio_read_bulk_callback (struct urb *urb); +static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios * old); +static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); + +/* All of the device info needed for the FTDI SIO serial converter */ +static __u16 ftdi_vendor_id = FTDI_VENDOR_ID; +static __u16 ftdi_sio_product_id = FTDI_SIO_SERIAL_CONVERTER_ID; +struct usb_serial_device_type ftdi_sio_device = { + name: "FTDI SIO", + idVendor: &ftdi_vendor_id, /* the FTDI vendor ID */ + idProduct: &ftdi_sio_product_id, /* the FTDI SIO product id */ + 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: ftdi_sio_open, + close: ftdi_sio_close, + write: ftdi_sio_write, + read_bulk_callback: ftdi_sio_read_bulk_callback, + write_bulk_callback: ftdi_sio_write_bulk_callback, + ioctl: ftdi_sio_ioctl, + set_termios: ftdi_sio_set_termios, + startup: ftdi_sio_startup, +}; + + +/* + * *************************************************************************** + * FTDI SIO Serial Converter specific driver functions + * *************************************************************************** + * + * Bill Ryder bryder@sgi.com of Silicon Graphics, Inc. did the FTDI_SIO code + * Thanx to FTDI for so kindly providing details of the protocol required + * to talk to the device - http://www.ftdi.co.uk + * + * Tested as at this version - other stuff might work + * 23 March 2000 + * Works: + * Baudrates - 9600, 38400,19200, 57600, 115200 + * TIOCMBIC - TIOCM_DTR / TIOCM_RTS + * TIOCMBIS - TIOCM_DTR / TIOCM_RTS + * TIOCMSET - DTR on/RTSon / DTR off, RTS off + * no parity:CS8 even parity:CS7 odd parity:CS7 + * CRTSCTS flow control + * + * Pilot-xfer zillions of times + * + * cu works with dir option + * + * Not Tested (ie might not work): + * xon/xoff flow control + * ppp (modem handling in general) + * + * KNOWN BUGS: + * Multiple Opens + * ============== + * Seems to have problem when opening an already open port, + * Get I/O error on first attempt, then it lets you in. + * Need to do proper usage counting - keep registered callbacks for first opener. + * + * Reproduce with: + * cu -l /dev/ttyUSB0 dir + * whilst cu is running do: + * stty -a < /dev/ttyUSB0 + * + * from stty get: 'bash: /dev/ttyUSB0: Invalid argument ' + * from cu get + * write: Invalid argument + * + * Initialisation Problem + * ====================== + * Pilot transfer required me to run the serial_loopback program before it would work. + * Still working on this. See the webpage http://reality.sgi.com/bryder_wellington/ftdi_sio + * + */ + +#define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */ + +/* do some startup allocations not currently performed by usb_serial_probe() */ +static int ftdi_sio_startup (struct usb_serial *serial) +{ + init_waitqueue_head(&serial->write_wait); + + return (0); +} + +static int ftdi_sio_open (struct usb_serial_port *port, struct file *filp) +{ /* ftdi_sio_open */ + struct termios tmp_termios; + struct usb_serial *serial = port->serial; + char buf[1]; /* Needed for the usb_control_msg I think */ + + dbg("ftdi_sio_open port %d", port->number); + + /* FIXME - multiple concurrent opens cause trouble */ + if (port->active) { + err ("port already open"); + return -EINVAL; + } + port->active = 1; /* FIXME - For multiple open this should increment */ + + /* See ftdi_sio.h for description of what is reset */ + usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, + FTDI_SIO_RESET_SIO, + 0, buf, 0, WDR_TIMEOUT); + + /* Setup termios */ + port->tty->termios->c_cflag = + B9600 | CS8 | CREAD | HUPCL | CLOCAL; + + + ftdi_sio_set_termios(port, &tmp_termios); + + /* Disable flow control */ + if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_FLOW_CTRL_REQUEST, + FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, + 0, 0, + buf, 0, WDR_TIMEOUT) < 0) { + err("error from flowcontrol urb"); + return(-EINVAL); + } + + /* Turn on RTS and DTR since we are not flow controlling*/ + if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_MODEM_CTRL_REQUEST, + FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, + (unsigned)FTDI_SIO_SET_DTR_HIGH, 0, + buf, 0, WDR_TIMEOUT) < 0) { + err("Error from DTR HIGH urb"); + } + if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_MODEM_CTRL_REQUEST, + FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, + (unsigned)FTDI_SIO_SET_RTS_HIGH, 0, + buf, 0, WDR_TIMEOUT) < 0) { + err("Error from RTS HIGH urb"); + } + + /*Start reading from the device*/ + if (usb_submit_urb(port->read_urb)) + err("usb_submit_urb(read bulk) failed"); + + return (0); +} /* ftdi_sio_open */ + + +static void ftdi_sio_close (struct usb_serial_port *port, struct file *filp) +{ /* ftdi_sio_close */ + struct usb_serial *serial = port->serial; + unsigned int c_cflag = port->tty->termios->c_cflag; + char buf[1]; + + dbg("ftdi_sio_close port %d", port->number); + + if (c_cflag & HUPCL){ + /* Disable flow control */ + if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_FLOW_CTRL_REQUEST, + FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, + 0, 0, + buf, 0, WDR_TIMEOUT) < 0) { + err("error from flowcontrol urb"); + } + + /* drop DTR */ + if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_MODEM_CTRL_REQUEST, + FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, + (unsigned)FTDI_SIO_SET_DTR_LOW, 0, + buf, 0, WDR_TIMEOUT) < 0) { + err("Error from DTR LOW urb"); + } + /* drop RTS */ + if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_MODEM_CTRL_REQUEST, + FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, + (unsigned)FTDI_SIO_SET_RTS_LOW, 0, + buf, 0, WDR_TIMEOUT) < 0) { + err("Error from RTS LOW urb"); + } + } + + /* shutdown our bulk reads and writes */ + usb_unlink_urb (port->write_urb); + usb_unlink_urb (port->read_urb); + port->active = 0; +} /* ftdi_sio_close */ + + + +/* The ftdi_sio requires the first byte to have: + * B0 1 + * B1 0 + * B2..7 length of message excluding byte 0 + */ +static int ftdi_sio_write (struct usb_serial_port *port, int from_user, + const unsigned char *buf, int count) +{ /* ftdi_sio_write */ + struct usb_serial *serial = port->serial; + const int data_offset = 1; + int rc; + DECLARE_WAITQUEUE(wait, current); + + dbg("ftdi_sio_serial_write port %d, %d bytes", port->number, count); + + if (count == 0) { + err("write request of 0 bytes"); + return 0; + } + + /* only do something if we have a bulk out endpoint */ + if (serial->num_bulk_out) { + unsigned char *first_byte = port->write_urb->transfer_buffer; + + /* Was seeing a race here, got a read callback, then write callback before + hitting interuptible_sleep_on - so wrapping in add_wait_queue stuff */ + + add_wait_queue(&serial->write_wait, &wait); + set_current_state (TASK_INTERRUPTIBLE); + while (port->write_urb->status == -EINPROGRESS) { + dbg("ftdi_sio - write in progress - retrying"); + if (0 /* file->f_flags & O_NONBLOCK */) { + rc = -EAGAIN; + goto err; + } + if (signal_pending(current)) { + current->state = TASK_RUNNING; + remove_wait_queue(&serial->write_wait, &wait); + rc = -ERESTARTSYS; + goto err; + } + schedule(); + } + remove_wait_queue(&serial->write_wait, &wait); + set_current_state(TASK_RUNNING); + + count += data_offset; + count = (count > port->bulk_out_size) ? port->bulk_out_size : count; + if (count == 0) { + return 0; + } + + /* Copy in the data to send */ + if (from_user) { + copy_from_user(port->write_urb->transfer_buffer + data_offset , + buf, count - data_offset ); + } + else { + memcpy(port->write_urb->transfer_buffer + data_offset, + buf, count - data_offset ); + } + + /* Write the control byte at the front of the packet*/ + first_byte = port->write_urb->transfer_buffer; + *first_byte = 1 | ((count-data_offset) << 2) ; + +#ifdef CONFIG_USB_SERIAL_DEBUG + dbg("Bytes: %d, Control Byte: 0o%03o",count, first_byte[0]); + + if (count) { + int i; + printk (KERN_DEBUG __FILE__ ": data written - length = %d, data = ", count); + for (i = 0; i < count; ++i) { + printk ( "0x%02x ", first_byte[i]); + if (first_byte[i] > ' ' && first_byte[i] < '~') { + printk( "%c ", first_byte[i]); + } else { + printk( " "); + } + } + + + printk ( "\n"); + } + +#endif + /* send the data out the bulk port */ + port->write_urb->transfer_buffer_length = count; + + if (usb_submit_urb(port->write_urb)) + err("usb_submit_urb(write bulk) failed"); + + dbg("write returning: %d", count - data_offset); + return (count - data_offset); + } + + /* no bulk out, so return 0 bytes written */ + return 0; + err: /* error exit */ + return(rc); +} /* ftdi_sio_write */ + +static void ftdi_sio_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("ftdi_sio_write_bulk_callback"); + + if (port_paranoia_check (port, "ftdi_sio_write_bulk_callback")) { + return; + } + + serial = port->serial; + if (serial_paranoia_check (serial, "ftdi_sio_write_bulk_callback")) { + return; + } + + if (urb->status) { + dbg("nonzero write bulk status received: %d", urb->status); + return; + } + + wake_up_interruptible(&serial->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); + + return; +} /* ftdi_sio_write_bulk_callback */ + +static void ftdi_sio_read_bulk_callback (struct urb *urb) +{ /* ftdi_sio_serial_buld_callback */ + struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + struct usb_serial *serial; + struct tty_struct *tty = port->tty ; + unsigned char *data = urb->transfer_buffer; + + const int data_offset = 2; + int i; + + dbg("ftdi_sio read callback"); + + if (port_paranoia_check (port, "ftdi_sio_read_bulk_callback")) { + return; + } + + serial = port->serial; + if (serial_paranoia_check (serial, "ftdi_sio_read_bulk_callback")) { + return; + } + + /* TO DO -- check for hung up line and handle appropriately: */ + /* send hangup (need to find out how to do this) */ + + + if (urb->status) { + /* This will happen at close every time so it is a dbg not an err */ + dbg("nonzero read bulk status received: %d", urb->status); + return; + } + +#ifdef CONFIG_USB_SERIAL_DEBUG + if (urb->actual_length > 2) { + printk (KERN_DEBUG __FILE__ ": data read - length = %d, data = ", urb->actual_length); + for (i = 0; i < urb->actual_length; ++i) { + printk ( "0x%.2x ", data[i]); + if (data[i] > ' ' && data[i] < '~') { + printk( "%c ", data[i]); + } else { + printk( " "); + } + } + printk ( "\n"); + } else { + dbg("Just status"); + } +#endif + + + if (urb->actual_length > data_offset) { + for (i = data_offset ; i < urb->actual_length ; ++i) { + tty_insert_flip_char(tty, data[i], 0); + } + tty_flip_buffer_push(tty); + } + + /* Continue trying to always read */ + if (usb_submit_urb(urb)) + err("failed resubmitting read urb"); + + return; +} /* ftdi_sio_serial_read_bulk_callback */ + +/* As I understand this - old_termios contains the original termios settings */ +/* and tty->termios contains the new setting to be used */ +/* */ +/* WARNING: set_termios calls this with old_termios in kernel space */ + +static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios *old_termios) +{ /* ftdi_sio_set_termios */ + struct usb_serial *serial = port->serial; + unsigned int cflag = port->tty->termios->c_cflag; + __u16 urb_value; /* Will hold the new flags */ + char buf[1]; /* Perhaps I should dynamically alloc this? */ + + dbg("ftdi_sio_set_termios port %d", port->number); + + + /* FIXME -For this cut I don't care if the line is really changing or + not - so just do the change regardless - should be able to + compare old_termios and tty->termios */ + /* NOTE These routines can get interrupted by + ftdi_sio_read_bulk_callback - need to examine what this + means - don't see any problems yet */ + + /* Set number of data bits, parity, stop bits */ + + urb_value = 0; + urb_value |= (cflag & CSTOPB ? FTDI_SIO_SET_DATA_STOP_BITS_2 : + FTDI_SIO_SET_DATA_STOP_BITS_1); + urb_value |= (cflag & PARENB ? + (cflag & PARODD ? FTDI_SIO_SET_DATA_PARITY_ODD : + FTDI_SIO_SET_DATA_PARITY_EVEN) : + FTDI_SIO_SET_DATA_PARITY_NONE); + if (cflag & CSIZE) { + switch (cflag & CSIZE) { + case CS5: urb_value |= 5; dbg("Setting CS5"); break; + case CS6: urb_value |= 6; dbg("Setting CS6"); break; + case CS7: urb_value |= 7; dbg("Setting CS7"); break; + case CS8: urb_value |= 8; dbg("Setting CS8"); break; + default: + err("CSIZE was set but not CS5-CS8"); + } + } + if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_DATA_REQUEST, + FTDI_SIO_SET_DATA_REQUEST_TYPE, + urb_value , 0, + buf, 0, 100) < 0) { + err("FAILED to set databits/stopbits/parity"); + } + + /* Now do the baudrate */ + + switch(cflag & CBAUD){ + case B0: break; /* Handled below */ + case B300: urb_value = ftdi_sio_b300; dbg("Set to 300"); break; + case B600: urb_value = ftdi_sio_b600; dbg("Set to 600") ; break; + case B1200: urb_value = ftdi_sio_b1200; dbg("Set to 1200") ; break; + case B2400: urb_value = ftdi_sio_b2400; dbg("Set to 2400") ; break; + case B4800: urb_value = ftdi_sio_b4800; dbg("Set to 4800") ; break; + case B9600: urb_value = ftdi_sio_b9600; dbg("Set to 9600") ; break; + case B19200: urb_value = ftdi_sio_b19200; dbg("Set to 19200") ; break; + case B38400: urb_value = ftdi_sio_b38400; dbg("Set to 38400") ; break; + case B57600: urb_value = ftdi_sio_b57600; dbg("Set to 57600") ; break; + case B115200: urb_value = ftdi_sio_b115200; dbg("Set to 115200") ; break; + default: dbg("FTDI_SIO does not support the baudrate requested"); + /* FIXME - how to return an error for this? */ break; + } + if ((cflag & CBAUD) == B0 ) { + /* Disable flow control */ + if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_FLOW_CTRL_REQUEST, + FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, + 0, 0, + buf, 0, WDR_TIMEOUT) < 0) { + err("error from disable flowcontrol urb"); + } + /* Drop RTS and DTR */ + if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_MODEM_CTRL_REQUEST, + FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, + (unsigned)FTDI_SIO_SET_DTR_LOW, 0, + buf, 0, WDR_TIMEOUT) < 0) { + err("Error from DTR LOW urb"); + } + if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_MODEM_CTRL_REQUEST, + FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, + (unsigned)FTDI_SIO_SET_RTS_LOW, 0, + buf, 0, WDR_TIMEOUT) < 0) { + err("Error from RTS LOW urb"); + } + + } else { + if (usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_BAUDRATE_REQUEST, + FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE, + urb_value, 0, + buf, 0, 100) < 0) { + err("urb failed to set baurdrate"); + } + } + /* Set flow control */ + /* Note device also supports DTR/CD (ugh) and Xon/Xoff in hardware */ + if (cflag & CRTSCTS) { + dbg("Setting to CRTSCTS flow control"); + if (usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_FLOW_CTRL_REQUEST, + FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, + 0 , FTDI_SIO_RTS_CTS_HS, + buf, 0, WDR_TIMEOUT) < 0) { + err("urb failed to set to rts/cts flow control"); + } + + } else { + /* CHECK Assuming XON/XOFF handled by stack - not by device */ + /* Disable flow control */ + dbg("Turning off hardware flow control"); + if (usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_FLOW_CTRL_REQUEST, + FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, + 0, 0, + buf, 0, WDR_TIMEOUT) < 0) { + err("urb failed to clear flow control"); + } + + } + return; +} /* ftdi_sio_set_termios */ + +static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg) +{ + struct usb_serial *serial = port->serial; + __u16 urb_value=0; /* Will hold the new flags */ + char buf[1]; + int ret, mask; + + dbg("ftdi_sio_ioctl - cmd 0x%04x", cmd); + + /* Based on code from acm.c and others */ + switch (cmd) { + + case TIOCMGET: + dbg("TIOCMGET"); + /* Request the status from the device */ + if ((ret = usb_control_msg(serial->dev, + usb_rcvctrlpipe(serial->dev, 0), + FTDI_SIO_GET_MODEM_STATUS_REQUEST, + FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, + 0, 0, + buf, 1, HZ * 5)) < 0 ) { + dbg("Get not get modem status of device"); + return(ret); + } + + return put_user((buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) | + (buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) | + (buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) | + (buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0), + (unsigned long *) arg); + break; + + case TIOCMSET: /* Turns on and off the lines as specified by the mask */ + dbg("TIOCMSET"); + if ((ret = get_user(mask, (unsigned long *) arg))) return ret; + urb_value = ((mask & TIOCM_DTR) ? FTDI_SIO_SET_DTR_HIGH : FTDI_SIO_SET_DTR_LOW); + if ((ret = usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_MODEM_CTRL_REQUEST, + FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, + urb_value , 0, + buf, 0, WDR_TIMEOUT)) < 0){ + err("Urb to set DTR failed"); + return(ret); + } + urb_value = ((mask & TIOCM_RTS) ? FTDI_SIO_SET_RTS_HIGH : FTDI_SIO_SET_RTS_LOW); + if ((ret = usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_MODEM_CTRL_REQUEST, + FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, + urb_value , 0, + buf, 0, WDR_TIMEOUT)) < 0){ + err("Urb to set RTS failed"); + return(ret); + } + break; + + case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */ + dbg("TIOCMBIS"); + if ((ret = get_user(mask, (unsigned long *) arg))) return ret; + if (mask & TIOCM_DTR){ + if ((ret = usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_MODEM_CTRL_REQUEST, + FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, + FTDI_SIO_SET_DTR_HIGH , 0, + buf, 0, WDR_TIMEOUT)) < 0){ + err("Urb to set DTR failed"); + return(ret); + } + } + if (mask & TIOCM_RTS) { + if ((ret = usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_MODEM_CTRL_REQUEST, + FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, + FTDI_SIO_SET_RTS_HIGH , 0, + buf, 0, WDR_TIMEOUT)) < 0){ + err("Urb to set RTS failed"); + return(ret); + } + } + break; + + case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */ + dbg("TIOCMBIC"); + if ((ret = get_user(mask, (unsigned long *) arg))) return ret; + if (mask & TIOCM_DTR){ + if ((ret = usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_MODEM_CTRL_REQUEST, + FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, + FTDI_SIO_SET_DTR_LOW , 0, + buf, 0, WDR_TIMEOUT)) < 0){ + err("Urb to unset DTR failed"); + return(ret); + } + } + if (mask & TIOCM_RTS) { + if ((ret = usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_MODEM_CTRL_REQUEST, + FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, + FTDI_SIO_SET_RTS_LOW , 0, + buf, 0, WDR_TIMEOUT)) < 0){ + err("Urb to unset RTS failed"); + return(ret); + } + } + break; + + /* + * I had originally implemented TCSET{A,S}{,F,W} and + * TCGET{A,S} here separately, however when testing I + * found that the higher layers actually do the termios + * conversions themselves and pass the call onto + * ftdi_sio_set_termios. + * + */ + + default: + /* This is not an error - turns out the higher layers will do + * some ioctls itself (see comment above) + */ + dbg("ftdi_sio ioctl arg not supported - it was 0x%04x",cmd); + return(-ENOIOCTLCMD); + break; + } + dbg("ftdi_sio_ioctl returning 0"); + return 0; +} /* ftdi_sio_ioctl */ + +#endif /* CONFIG_USB_SERIAL_FTDI_SIO */ + + diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/serial/ftdi_sio.h linux/drivers/usb/serial/ftdi_sio.h --- v2.3.99-pre3/linux/drivers/usb/serial/ftdi_sio.h Fri Mar 10 16:40:45 2000 +++ linux/drivers/usb/serial/ftdi_sio.h Sun Apr 2 15:20:16 2000 @@ -1,15 +1,23 @@ -/* Bill Ryder - bryder@sgi.com - wrote the FTDI_SIO implementation */ -/* The device is based on the FTDI FT8U100AX chip, DB25 on one side, USB on the other */ -/* Thanx to FTDI for so kindly providing details of the protocol required */ -/* http://www.ftdi.co.uk */ - -/* The implementation of the device I have is called a USC-1000 */ -/* which is available from http://www.dse.co.nz - cat no XH4214 */ -/* It looks similar to this: http://www.dansdata.com/usbser.htm but I can't be sure */ -/* There are other USC-1000s which don't look like my device though so beware */ - -/* Definitions for the FTDI USB Single Port Serial Converter */ -/* known as FTDI_SIO (Serial Input/Output application of the chipset) */ +/* + * Definitions for the FTDI USB Single Port Serial Converter - + * known as FTDI_SIO (Serial Input/Output application of the chipset) + * + * The example I have is known as the USC-1000 which is available from + * http://www.dse.co.nz - cat no XH4214 It looks similar to this: + * http://www.dansdata.com/usbser.htm but I can't be sure There are other + * USC-1000s which don't look like my device though so beware! + * + * The device is based on the FTDI FT8U100AX chip. It has a DB25 on one side, + * USB on the other. + * + * Thanx to FTDI (http://www.ftdi.co.uk) for so kindly providing details + * of the protocol required to talk to the device and ongoing assistence + * during development. + * + * Bill Ryder - bryder@sgi.com of Silicon Graphics, Inc.- wrote the + * FTDI_SIO implementation. + * + */ #define FTDI_VID 0x0403 /* Vendor Id */ #define FTDI_SIO_PID 0x8372 /* Product Id */ @@ -27,7 +35,7 @@ /* Port Identifier Table */ #define PIT_DEFAULT 0 /* SIOA */ #define PIT_SIOA 1 /* SIOA */ -/* The device this is tested with one has one port */ +/* The device this driver is tested with one has only one port */ #define PIT_SIOB 2 /* SIOB */ #define PIT_PARALLEL 3 /* Parallel */ @@ -37,17 +45,31 @@ #define FTDI_SIO_RESET_SIO 0 #define FTDI_SIO_RESET_PURGE_RX 1 #define FTDI_SIO_RESET_PURGE_TX 2 -/* - BmRequestType: 0100 0000B - bRequest: FTDI_SIO_RESET - wValue: Control Value - 0 = Reset SIO - 1 = Purge RX buffer - 2 = Purge TX buffer - wIndex: Port - wLength: 0 - Data: None +/* + * BmRequestType: 0100 0000B + * bRequest: FTDI_SIO_RESET + * wValue: Control Value + * 0 = Reset SIO + * 1 = Purge RX buffer + * 2 = Purge TX buffer + * wIndex: Port + * wLength: 0 + * Data: None + * + * The Reset SIO command has this effect: + * + * Sets flow control set to 'none' + * Event char = $0D + * Event trigger = disabled + * Purge RX buffer + * Purge TX buffer + * Clear DTR + * Clear RTS + * baud and data format not reset + * + * The Purge RX and TX buffer commands affect nothing except the buffers + * */ /* FTDI_SIO_SET_BAUDRATE */ @@ -55,13 +77,13 @@ #define FTDI_SIO_SET_BAUDRATE_REQUEST 3 /* - BmRequestType: 0100 0000B - bRequest: FTDI_SIO_SET_BAUDRATE - wValue: BaudRate value - see below - wIndex: Port - wLength: 0 - Data: None -*/ + * BmRequestType: 0100 0000B + * bRequest: FTDI_SIO_SET_BAUDRATE + * wValue: BaudRate value - see below + * wIndex: Port + * wLength: 0 + * Data: None + */ typedef enum { ftdi_sio_b300 = 0, @@ -89,28 +111,30 @@ /* FTDI_SIO_SET_DATA */ -/* BmRequestType: 0100 0000B */ -/* bRequest: FTDI_SIO_SET_DATA */ -/* wValue: Data characteristics (see below) */ -/* wIndex: Port */ -/* wLength: 0 */ -/* Data: None */ -/* - Data characteristics - -B0..7 Number of data bits -B8..10 Parity - 0 = None - 1 = Odd - 2 = Even - 3 = Mark - 4 = Space - B11..13 Stop Bits - 0 = 1 - 1 = 1.5 - 2 = 2 - B14..15 Reserved -*/ +/* + * BmRequestType: 0100 0000B + * bRequest: FTDI_SIO_SET_DATA + * wValue: Data characteristics (see below) + * wIndex: Port + * wLength: 0 + * Data: No + * + * Data characteristics + * + * B0..7 Number of data bits + * B8..10 Parity + * 0 = None + * 1 = Odd + * 2 = Even + * 3 = Mark + * 4 = Space + * B11..13 Stop Bits + * 0 = 1 + * 1 = 1.5 + * 2 = 2 + * B14..15 Reserved + * + */ @@ -119,16 +143,17 @@ #define FTDI_SIO_SET_MODEM_CTRL_REQUEST FTDI_SIO_MODEM_CTRL /* - BmRequestType: 0100 0000B - bRequest: FTDI_SIO_MODEM_CTRL - wValue: ControlValue (see below) - wIndex: Port - wLength: 0 - Data: None - - NOTE: If the device is in RTS/CTS flow control, the RTS set by this - command will be IGNORED without an error being returned -*/ + * BmRequestType: 0100 0000B + * bRequest: FTDI_SIO_MODEM_CTRL + * wValue: ControlValue (see below) + * wIndex: Port + * wLength: 0 + * Data: None + * + * NOTE: If the device is in RTS/CTS flow control, the RTS set by this + * command will be IGNORED without an error being returned + * Also - you can not set DTR and RTS with one control message + */ #define FTDI_SIO_SET_DTR_MASK 0x1 #define FTDI_SIO_SET_DTR_HIGH ( 1 | ( FTDI_SIO_SET_DTR_MASK << 8)) @@ -137,100 +162,107 @@ #define FTDI_SIO_SET_RTS_HIGH ( 2 | ( FTDI_SIO_SET_RTS_MASK << 8 )) #define FTDI_SIO_SET_RTS_LOW ( 0 | ( FTDI_SIO_SET_RTS_MASK << 8 )) -/* ControlValue - B0 DTR state - 0 = reset - 1 = set - B1 RTS state - 0 = reset - 1 = set - B2..7 Reserved - B8 DTR state enable - 0 = ignore - 1 = use DTR state - B9 RTS state enable - 0 = ignore - 1 = use RTS state - B10..15 Reserved -*/ +/* + * ControlValue + * B0 DTR state + * 0 = reset + * 1 = set + * B1 RTS state + * 0 = reset + * 1 = set + * B2..7 Reserved + * B8 DTR state enable + * 0 = ignore + * 1 = use DTR state + * B9 RTS state enable + * 0 = ignore + * 1 = use RTS state + * B10..15 Reserved + */ /* FTDI_SIO_SET_FLOW_CTRL */ #define FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE 0x40 #define FTDI_SIO_SET_FLOW_CTRL_REQUEST FTDI_SIO_SET_FLOW_CTRL #define FTDI_SIO_DISABLE_FLOW_CTRL 0x0 -#define FTDI_SIO_RTS_CTS_HS 0x1 -#define FTDI_SIO_DTR_DSR_HS 0x2 -#define FTDI_SIO_XON_XOFF_HS 0x4 -/* - BmRequestType: 0100 0000b - bRequest: FTDI_SIO_SET_FLOW_CTRL - wValue: Xoff/Xon - wIndex: Protocol/Port - hIndex is protocl / lIndex is port - wLength: 0 - Data: None - -hIndex - protocol has - B0 Output handshaking using RTS/CTS - 0 = disabled - 1 = enabled - B1 Output handshaking using DTR/DSR - 0 = disabled - 1 = enabled - B2 Xon/Xoff handshaking - 0 = disabled - 1 = enabled - -A value of zero in the hIndex field selects no handshaking +#define FTDI_SIO_RTS_CTS_HS (0x1 << 8) +#define FTDI_SIO_DTR_DSR_HS (0x2 << 8) +#define FTDI_SIO_XON_XOFF_HS (0x4 << 8) +/* + * BmRequestType: 0100 0000b + * bRequest: FTDI_SIO_SET_FLOW_CTRL + * wValue: Xoff/Xon + * wIndex: Protocol/Port - hIndex is protocl / lIndex is port + * wLength: 0 + * Data: None + * + * hIndex protocol is: + * B0 Output handshaking using RTS/CTS + * 0 = disabled + * 1 = enabled + * B1 Output handshaking using DTR/DSR + * 0 = disabled + * 1 = enabled + * B2 Xon/Xoff handshaking + * 0 = disabled + * 1 = enabled + * + * A value of zero in the hIndex field disables handshaking + * + * If Xon/Xoff handshaking is specified, the hValue field should contain the XOFF character + * and the lValue field contains the XON character. + */ + +/* + * FTDI_SIO_SET_EVENT_CHAR + * + * Set the special event character for the specified communications port. + * If the device sees this character it will immediately return the + * data read so far - rather than wait 40ms or until 62 bytes are read + * which is what normally happens. + */ -If Xon/Xoff handshaking is specified, the hValue field contains the Xoff character -and the lValue field contains the Xon character. -*/ - -/* FTDI_SIO_SET_EVENT_CHAR */ -/* Set the special event character for the specified communications port */ -/* If the device sees this character it will immediately return the */ -/* data read so far - rather than wait 40ms or until 62 bytes is read */ #define FTDI_SIO_SET_EVENT_CHAR_REQUEST FTDI_SIO_SET_EVENT_CHAR #define FTDI_SIO_SET_EVENT_CHAR_REQUEST_TYPE 0x40 /* - BmRequestType: 0100 0000b - bRequest: FTDI_SIO_SET_EVENT_CHAR - wValue: EventChar - wIndex: Port - wLength: 0 - Data: None - -wValue: - B0..7 Event Character - B8 Event Character Processing - 0 = disabled - 1 = enabled - B9..15 Reserved - -*/ + * BmRequestType: 0100 0000b + * bRequest: FTDI_SIO_SET_EVENT_CHAR + * wValue: EventChar + * wIndex: Port + * wLength: 0 + * Data: None + * + * wValue: + * B0..7 Event Character + * B8 Event Character Processing + * 0 = disabled + * 1 = enabled + * B9..15 Reserved + * + */ /* FTDI_SIO_SET_ERROR_CHAR */ + /* Set the parity error replacement character for the specified communications port */ /* - BmRequestType: 0100 0000b - bRequest: FTDI_SIO_SET_EVENT_CHAR - wValue: Error Char - wIndex: Port - wLength: 0 - Data: None - -Error Char - B0..7 Error Character - B8 Error Character Processing - 0 = disabled - 1 = enabled - B9..15 Reserved - -*/ + * BmRequestType: 0100 0000b + * bRequest: FTDI_SIO_SET_EVENT_CHAR + * wValue: Error Char + * wIndex: Port + * wLength: 0 + * Data: None + * + *Error Char + * B0..7 Error Character + * B8 Error Character Processing + * 0 = disabled + * 1 = enabled + * B9..15 Reserved + * + */ /* FTDI_SIO_GET_MODEM_STATUS */ /* Retreive the current value of the modem status register */ @@ -242,139 +274,140 @@ #define FTDI_SIO_RI_MASK 0x40 #define FTDI_SIO_RLSD_MASK 0x80 /* - BmRequestType: 1100 0000b - bRequest: FTDI_SIO_GET_MODEM_STATUS - wValue: zero - wIndex: Port - wLength: 1 - Data: Status - -One byte of data is returned -B0..3 0 -B4 CTS - 0 = inactive - 1 = active -B5 DSR - 0 = inactive - 1 = active -B6 Ring Indicator (RI) - 0 = inactive - 1 = active -B7 Receive Line Signal Detect (RLSD) - 0 = inactive - 1 = active -*/ + * BmRequestType: 1100 0000b + * bRequest: FTDI_SIO_GET_MODEM_STATUS + * wValue: zero + * wIndex: Port + * wLength: 1 + * Data: Status + * + * One byte of data is returned + * B0..3 0 + * B4 CTS + * 0 = inactive + * 1 = active + * B5 DSR + * 0 = inactive + * 1 = active + * B6 Ring Indicator (RI) + * 0 = inactive + * 1 = active + * B7 Receive Line Signal Detect (RLSD) + * 0 = inactive + * 1 = active + */ /* Descriptors returned by the device + * + * Device Descriptor + * + * Offset Field Size Value Description + * 0 bLength 1 0x12 Size of descriptor in bytes + * 1 bDescriptorType 1 0x01 DEVICE Descriptor Type + * 2 bcdUSB 2 0x0110 USB Spec Release Number + * 4 bDeviceClass 1 0x00 Class Code + * 5 bDeviceSubClass 1 0x00 SubClass Code + * 6 bDeviceProtocol 1 0x00 Protocol Code + * 7 bMaxPacketSize0 1 0x08 Maximum packet size for endpoint 0 + * 8 idVendor 2 0x0403 Vendor ID + * 10 idProduct 2 0x8372 Product ID (FTDI_SIO_PID) + * 12 bcdDevice 2 0x0001 Device release number + * 14 iManufacturer 1 0x01 Index of man. string desc + * 15 iProduct 1 0x02 Index of prod string desc + * 16 iSerialNumber 1 0x02 Index of serial nmr string desc + * 17 bNumConfigurations 1 0x01 Number of possible configurations + * + * Configuration Descriptor + * + * Offset Field Size Value + * 0 bLength 1 0x09 Size of descriptor in bytes + * 1 bDescriptorType 1 0x02 CONFIGURATION Descriptor Type + * 2 wTotalLength 2 0x0020 Total length of data + * 4 bNumInterfaces 1 0x01 Number of interfaces supported + * 5 bConfigurationValue 1 0x01 Argument for SetCOnfiguration() req + * 6 iConfiguration 1 0x02 Index of config string descriptor + * 7 bmAttributes 1 0x20 Config characteristics Remote Wakeup + * 8 MaxPower 1 0x1E Max power consumption + * + * Interface Descriptor + * + * Offset Field Size Value + * 0 bLength 1 0x09 Size of descriptor in bytes + * 1 bDescriptorType 1 0x04 INTERFACE Descriptor Type + * 2 bInterfaceNumber 1 0x00 Number of interface + * 3 bAlternateSetting 1 0x00 Value used to select alternate + * 4 bNumEndpoints 1 0x02 Number of endpoints + * 5 bInterfaceClass 1 0xFF Class Code + * 6 bInterfaceSubClass 1 0xFF Subclass Code + * 7 bInterfaceProtocol 1 0xFF Protocol Code + * 8 iInterface 1 0x02 Index of interface string description + * + * IN Endpoint Descriptor + * + * Offset Field Size Value + * 0 bLength 1 0x07 Size of descriptor in bytes + * 1 bDescriptorType 1 0x05 ENDPOINT descriptor type + * 2 bEndpointAddress 1 0x82 Address of endpoint + * 3 bmAttributes 1 0x02 Endpoint attributes - Bulk + * 4 bNumEndpoints 2 0x0040 maximum packet size + * 5 bInterval 1 0x00 Interval for polling endpoint + * + * OUT Endpoint Descriptor + * + * Offset Field Size Value + * 0 bLength 1 0x07 Size of descriptor in bytes + * 1 bDescriptorType 1 0x05 ENDPOINT descriptor type + * 2 bEndpointAddress 1 0x02 Address of endpoint + * 3 bmAttributes 1 0x02 Endpoint attributes - Bulk + * 4 bNumEndpoints 2 0x0040 maximum packet size + * 5 bInterval 1 0x00 Interval for polling endpoint + * + * DATA FORMAT + * + * IN Endpoint + * + * The device reserves the first two bytes of data on this endpoint to contain the current + * values of the modem and line status registers. In the absence of data, the device + * generates a message consisting of these two status bytes every 40 ms + * + * Byte 0: Modem Status + * + * Offset Description + * B0 Reserved - must be 1 + * B1 Reserved - must be 0 + * B2 Reserved - must be 0 + * B3 Reserved - must be 0 + * B4 Clear to Send (CTS) + * B5 Data Set Ready (DSR) + * B6 Ring Indicator (RI) + * B7 Receive Line Signal Detect (RLSD) + * + * Byte 1: Line Status + * + * Offset Description + * B0 Data Ready (DR) + * B1 Overrun Error (OE) + * B2 Parity Error (PE) + * B3 Framing Error (FE) + * B4 Break Interrupt (BI) + * B5 Transmitter Holding Register (THRE) + * B6 Transmitter Empty (TEMT) + * B7 Error in RCVR FIFO + * + * OUT Endpoint + * + * This device reserves the first bytes of data on this endpoint contain the length + * and port identifier of the message. For the FTDI USB Serial converter the port + * identifier is always 1. + * + * Byte 0: Line Status + * + * Offset Description + * B0 Reserved - must be 1 + * B1 Reserved - must be 0 + * B2..7 Length of message - (not including Byte 0) + * + */ - Device Descriptor - -Offset Field Size Value Description -0 bLength 1 0x12 Size of descriptor in bytes -1 bDescriptorType 1 0x01 DEVICE Descriptor Type -2 bcdUSB 2 0x0110 USB Spec Release Number -4 bDeviceClass 1 0x00 Class Code -5 bDeviceSubClass 1 0x00 SubClass Code -6 bDeviceProtocol 1 0x00 Protocol Code -7 bMaxPacketSize0 1 0x08 Maximum packet size for endpoint 0 -8 idVendor 2 0x0403 Vendor ID -10 idProduct 2 0x8372 Product ID (FTDI_SIO_PID) -12 bcdDevice 2 0x0001 Device release number -14 iManufacturer 1 0x01 Index of man. string desc -15 iProduct 1 0x02 Index of prod string desc -16 iSerialNumber 1 0x02 Index of serial nmr string desc -17 bNumConfigurations 1 0x01 Number of possible configurations - -Configuration Descriptor - -Offset Field Size Value -0 bLength 1 0x09 Size of descriptor in bytes -1 bDescriptorType 1 0x02 CONFIGURATION Descriptor Type -2 wTotalLength 2 0x0020 Total length of data -4 bNumInterfaces 1 0x01 Number of interfaces supported -5 bConfigurationValue 1 0x01 Argument for SetCOnfiguration() req -6 iConfiguration 1 0x02 Index of config string descriptor -7 bmAttributes 1 0x20 Config characteristics Remote Wakeup -8 MaxPower 1 0x1E Max power consumption - -Interface Descriptor - -Offset Field Size Value -0 bLength 1 0x09 Size of descriptor in bytes -1 bDescriptorType 1 0x04 INTERFACE Descriptor Type -2 bInterfaceNumber 1 0x00 Number of interface -3 bAlternateSetting 1 0x00 Value used to select alternate -4 bNumEndpoints 1 0x02 Number of endpoints -5 bInterfaceClass 1 0xFF Class Code -6 bInterfaceSubClass 1 0xFF Subclass Code -7 bInterfaceProtocol 1 0xFF Protocol Code -8 iInterface 1 0x02 Index of interface string description - -IN Endpoint Descriptor - -Offset Field Size Value -0 bLength 1 0x07 Size of descriptor in bytes -1 bDescriptorType 1 0x05 ENDPOINT descriptor type -2 bEndpointAddress 1 0x82 Address of endpoint -3 bmAttributes 1 0x02 Endpoint attributes - Bulk -4 bNumEndpoints 2 0x0040 maximum packet size -5 bInterval 1 0x00 Interval for polling endpoint - -OUT Endpoint Descriptor - -Offset Field Size Value -0 bLength 1 0x07 Size of descriptor in bytes -1 bDescriptorType 1 0x05 ENDPOINT descriptor type -2 bEndpointAddress 1 0x02 Address of endpoint -3 bmAttributes 1 0x02 Endpoint attributes - Bulk -4 bNumEndpoints 2 0x0040 maximum packet size -5 bInterval 1 0x00 Interval for polling endpoint - -DATA FORMAT - -IN Endpoint - -The device reserves the first two bytes of data on this endpoint to contain the current -values of the modem and line status registers. In the absence of data, the device -generates a message consisting of these two status bytes every 40 ms - -Byte 0: Modem Status - -Offset Description -B0 Reserved - must be 1 -B1 Reserved - must be 0 -B2 Reserved - must be 0 -B3 Reserved - must be 0 -B4 Clear to Send (CTS) -B5 Data Set Ready (DSR) -B6 Ring Indicator (RI) -B7 Receive Line Signal Detect (RLSD) - -Byte 1: Line Status - -Offset Description -B0 Data Ready (DR) -B1 Overrun Error (OE) -B2 Parity Error (PE) -B3 Framing Error (FE) -B4 Break Interrupt (BI) -B5 Transmitter Holding Register (THRE) -B6 Transmitter Empty (TEMT) -B7 Error in RCVR FIFO - -OUT Endpoint - -This device reserves the first bytes of data on this endpoint contain the length -and port identifier of the message. For the FTDI USB Serial converter the port -identifier is always 1. - -Byte 0: Line Status - -Offset Description -B0 Reserved - must be 1 -B1 Reserved - must be 0 -B2..7 Length of message - (not including Byte 0) - -*/ diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/serial/keyspan_pda.c linux/drivers/usb/serial/keyspan_pda.c --- v2.3.99-pre3/linux/drivers/usb/serial/keyspan_pda.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/serial/keyspan_pda.c Mon Mar 27 14:25:28 2000 @@ -0,0 +1,717 @@ +/* + * USB Keyspan PDA Converter driver + * + * (C) Copyright (C) 1999, 2000 + * Greg Kroah-Hartman (greg@kroah.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. + * + * See Documentation/usb/usb-serial.txt for more information on using this driver + * + * (03/26/2000) gkh + * Split driver up into device specific pieces. + * + */ + + +#include + +#ifdef CONFIG_USB_SERIAL_KEYSPAN_PDA + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_USB_SERIAL_DEBUG + #define DEBUG +#else + #undef DEBUG +#endif +#include + +struct ezusb_hex_record { + __u16 address; + __u8 data_size; + __u8 data[16]; +}; + +#include "keyspan_pda_fw.h" + +#include "usb-serial.h" + +#define KEYSPAN_VENDOR_ID 0x06cd +#define KEYSPAN_PDA_FAKE_ID 0x0103 +#define KEYSPAN_PDA_ID 0x0104 /* no clue */ + +/* function prototypes for a Keyspan PDA serial converter */ +static int keyspan_pda_open (struct usb_serial_port *port, + struct file *filp); +static void keyspan_pda_close (struct usb_serial_port *port, + struct file *filp); +static int keyspan_pda_startup (struct usb_serial *serial); +static void keyspan_pda_rx_throttle (struct usb_serial_port *port); +static void keyspan_pda_rx_unthrottle (struct usb_serial_port *port); +static int keyspan_pda_setbaud (struct usb_serial *serial, int baud); +static int keyspan_pda_write_room (struct usb_serial_port *port); +static int keyspan_pda_write (struct usb_serial_port *port, + int from_user, + const unsigned char *buf, + int count); +static void keyspan_pda_write_bulk_callback (struct urb *urb); +static int keyspan_pda_chars_in_buffer (struct usb_serial_port *port); +static int keyspan_pda_ioctl (struct usb_serial_port *port, + struct file *file, + unsigned int cmd, + unsigned long arg); +static void keyspan_pda_set_termios (struct usb_serial_port *port, + struct termios *old); +static void keyspan_pda_break_ctl (struct usb_serial_port *port, + int break_state); +static int keyspan_pda_fake_startup (struct usb_serial *serial); + + +/* All of the device info needed for the Keyspan PDA serial converter */ +static __u16 keyspan_vendor_id = KEYSPAN_VENDOR_ID; +static __u16 keyspan_pda_fake_product_id = KEYSPAN_PDA_FAKE_ID; +static __u16 keyspan_pda_product_id = KEYSPAN_PDA_ID; +struct usb_serial_device_type keyspan_pda_fake_device = { + name: "Keyspan PDA - (prerenumeration)", + idVendor: &keyspan_vendor_id, /* the Keyspan PDA vendor ID */ + idProduct: &keyspan_pda_fake_product_id, /* the Keyspan PDA initial product id */ + needs_interrupt_in: DONT_CARE, /* don't have to have an interrupt in endpoint */ + needs_bulk_in: DONT_CARE, /* don't have to have a bulk in endpoint */ + needs_bulk_out: DONT_CARE, /* don't have to have a bulk out endpoint */ + 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 = { + name: "Keyspan PDA", + idVendor: &keyspan_vendor_id, /* the Keyspan PDA vendor ID */ + idProduct: &keyspan_pda_product_id, /* the Keyspan PDA product id */ + needs_interrupt_in: MUST_HAVE, + needs_bulk_in: DONT_CARE, + needs_bulk_out: MUST_HAVE, + num_interrupt_in: 1, + num_bulk_in: 0, + num_bulk_out: 1, + num_ports: 1, + open: keyspan_pda_open, + close: keyspan_pda_close, + write: keyspan_pda_write, + write_room: keyspan_pda_write_room, + write_bulk_callback: keyspan_pda_write_bulk_callback, + chars_in_buffer: keyspan_pda_chars_in_buffer, + throttle: keyspan_pda_rx_throttle, + unthrottle: keyspan_pda_rx_unthrottle, + startup: keyspan_pda_startup, + ioctl: keyspan_pda_ioctl, + set_termios: keyspan_pda_set_termios, + break_ctl: keyspan_pda_break_ctl, +}; + + +static void keyspan_pda_rx_interrupt (struct urb *urb) +{ + struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + struct usb_serial *serial; + struct tty_struct *tty; + unsigned char *data = urb->transfer_buffer; + int i; + + /* the urb might have been killed. */ + if (urb->status) + return; + + if (port_paranoia_check (port, "keyspan_pda_rx_interrupt")) { + return; + } + + serial = port->serial; + if (serial_paranoia_check (serial, "keyspan_pda_rx_interrupt")) { + return; + } + + /* see if the message is data or a status interrupt */ + switch (data[0]) { + case 0: + /* rest of message is rx data */ + if (urb->actual_length) { + tty = serial->port[0].tty; + for (i = 1; i < urb->actual_length ; ++i) { + tty_insert_flip_char(tty, data[i], 0); + } + tty_flip_buffer_push(tty); + } + break; + case 1: + /* status interrupt */ + dbg(" rx int, d1=%d, d2=%d", data[1], data[2]); + switch (data[1]) { + case 1: /* modemline change */ + break; + case 2: /* tx unthrottle interrupt */ + tty = serial->port[0].tty; + serial->tx_throttled = 0; + wake_up(&serial->write_wait); /* wake up writer */ + wake_up(&tty->write_wait); /* them too */ + break; + default: + break; + } + break; + default: + break; + } + + /* INT urbs are automatically re-submitted */ +} + + +static void keyspan_pda_rx_throttle (struct usb_serial_port *port) +{ + /* stop receiving characters. We just turn off the URB request, and + let chars pile up in the device. If we're doing hardware + flowcontrol, the device will signal the other end when its buffer + fills up. If we're doing XON/XOFF, this would be a good time to + send an XOFF, although it might make sense to foist that off + upon the device too. */ + + dbg("keyspan_pda_rx_throttle port %d", port->number); + usb_unlink_urb(port->read_urb); +} + + +static void keyspan_pda_rx_unthrottle (struct usb_serial_port *port) +{ + /* just restart the receive interrupt URB */ + dbg("keyspan_pda_rx_unthrottle port %d", port->number); + if (usb_submit_urb(port->read_urb)) + dbg(" usb_submit_urb(read urb) failed"); + return; +} + + +static int keyspan_pda_setbaud (struct usb_serial *serial, int baud) +{ + int rc; + int bindex; + + switch(baud) { + case 110: bindex = 0; break; + case 300: bindex = 1; break; + case 1200: bindex = 2; break; + case 2400: bindex = 3; break; + case 4800: bindex = 4; break; + case 9600: bindex = 5; break; + case 19200: bindex = 6; break; + case 38400: bindex = 7; break; + case 57600: bindex = 8; break; + case 115200: bindex = 9; break; + default: return -EINVAL; + } + + /* rather than figure out how to sleep while waiting for this + to complete, I just use the "legacy" API. */ + rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + 0, /* set baud */ + USB_TYPE_VENDOR + | USB_RECIP_INTERFACE + | USB_DIR_OUT, /* type */ + bindex, /* value */ + 0, /* index */ + NULL, /* &data */ + 0, /* size */ + 2*HZ); /* timeout */ + return(rc); +} + + +static void keyspan_pda_break_ctl (struct usb_serial_port *port, int break_state) +{ + struct usb_serial *serial = port->serial; + int value; + if (break_state == -1) + value = 1; /* start break */ + else + value = 0; /* clear break */ + usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + 4, /* set break */ + USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, + value, 0, NULL, 0, 2*HZ); + /* there is something funky about this.. the TCSBRK that 'cu' performs + ought to translate into a break_ctl(-1),break_ctl(0) pair HZ/4 + seconds apart, but it feels like the break sent isn't as long as it + is on /dev/ttyS0 */ +} + + +static void keyspan_pda_set_termios (struct usb_serial_port *port, + struct termios *old_termios) +{ + struct usb_serial *serial = port->serial; + unsigned int cflag = port->tty->termios->c_cflag; + + /* cflag specifies lots of stuff: number of stop bits, parity, number + of data bits, baud. What can the device actually handle?: + CSTOPB (1 stop bit or 2) + PARENB (parity) + CSIZE (5bit .. 8bit) + There is minimal hw support for parity (a PSW bit seems to hold the + parity of whatever is in the accumulator). The UART either deals + with 10 bits (start, 8 data, stop) or 11 bits (start, 8 data, + 1 special, stop). So, with firmware changes, we could do: + 8N1: 10 bit + 8N2: 11 bit, extra bit always (mark?) + 8[EOMS]1: 11 bit, extra bit is parity + 7[EOMS]1: 10 bit, b0/b7 is parity + 7[EOMS]2: 11 bit, b0/b7 is parity, extra bit always (mark?) + + HW flow control is dictated by the tty->termios->c_cflags & CRTSCTS + bit. + + For now, just do baud. */ + + switch (cflag & CBAUD) { + /* we could support more values here, just need to calculate + the necessary divisors in the firmware. + has the Bnnn constants. */ + case B110: keyspan_pda_setbaud(serial, 110); break; + case B300: keyspan_pda_setbaud(serial, 300); break; + case B1200: keyspan_pda_setbaud(serial, 1200); break; + case B2400: keyspan_pda_setbaud(serial, 2400); break; + case B4800: keyspan_pda_setbaud(serial, 4800); break; + case B9600: keyspan_pda_setbaud(serial, 9600); break; + case B19200: keyspan_pda_setbaud(serial, 19200); break; + case B38400: keyspan_pda_setbaud(serial, 38400); break; + case B57600: keyspan_pda_setbaud(serial, 57600); break; + case B115200: keyspan_pda_setbaud(serial, 115200); break; + default: dbg("can't handle requested baud rate"); break; + } +} + + +/* modem control pins: DTR and RTS are outputs and can be controlled. + DCD, RI, DSR, CTS are inputs and can be read. All outputs can also be + read. The byte passed is: DTR(b7) DCD RI DSR CTS RTS(b2) unused unused */ + +static int keyspan_pda_get_modem_info(struct usb_serial *serial, + unsigned char *value) +{ + int rc; + unsigned char data; + rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), + 3, /* get pins */ + USB_TYPE_VENDOR|USB_RECIP_INTERFACE|USB_DIR_IN, + 0, 0, &data, 1, 2*HZ); + if (rc > 0) + *value = data; + return rc; +} + + +static int keyspan_pda_set_modem_info(struct usb_serial *serial, + unsigned char value) +{ + int rc; + rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + 3, /* set pins */ + USB_TYPE_VENDOR|USB_RECIP_INTERFACE|USB_DIR_OUT, + value, 0, NULL, 0, 2*HZ); + return rc; +} + + +static int keyspan_pda_ioctl(struct usb_serial_port *port, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct usb_serial *serial = port->serial; + int rc; + unsigned int value; + unsigned char status, mask; + + switch (cmd) { + case TIOCMGET: /* get modem pins state */ + rc = keyspan_pda_get_modem_info(serial, &status); + if (rc < 0) + return rc; + value = + ((status & (1<<7)) ? TIOCM_DTR : 0) | + ((status & (1<<6)) ? TIOCM_CAR : 0) | + ((status & (1<<5)) ? TIOCM_RNG : 0) | + ((status & (1<<4)) ? TIOCM_DSR : 0) | + ((status & (1<<3)) ? TIOCM_CTS : 0) | + ((status & (1<<2)) ? TIOCM_RTS : 0); + if (copy_to_user((unsigned int *)arg, &value, sizeof(int))) + return -EFAULT; + return 0; + case TIOCMSET: /* set a state as returned by MGET */ + if (copy_from_user(&value, (unsigned int *)arg, sizeof(int))) + return -EFAULT; + status = + ((value & TIOCM_DTR) ? (1<<7) : 0) | + ((value & TIOCM_CAR) ? (1<<6) : 0) | + ((value & TIOCM_RNG) ? (1<<5) : 0) | + ((value & TIOCM_DSR) ? (1<<4) : 0) | + ((value & TIOCM_CTS) ? (1<<3) : 0) | + ((value & TIOCM_RTS) ? (1<<2) : 0); + rc = keyspan_pda_set_modem_info(serial, status); + if (rc < 0) + return rc; + return 0; + case TIOCMBIS: /* set bits in bitmask */ + case TIOCMBIC: /* clear bits from bitmask */ + if (copy_from_user(&value, (unsigned int *)arg, sizeof(int))) + return -EFAULT; + rc = keyspan_pda_get_modem_info(serial, &status); + if (rc < 0) + return rc; + mask = + ((value & TIOCM_RTS) ? (1<<2) : 0) | + ((value & TIOCM_DTR) ? (1<<7) : 0); + if (cmd == TIOCMBIS) + status |= mask; + else + status &= ~mask; + rc = keyspan_pda_set_modem_info(serial, status); + if (rc < 0) + return rc; + return 0; + case TIOCMIWAIT: + /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/ + /* TODO */ + case TIOCGICOUNT: + /* return count of modemline transitions */ + return 0; /* TODO */ + } + + return -ENOIOCTLCMD; +} + +static int keyspan_pda_write(struct usb_serial_port *port, int from_user, + const unsigned char *buf, int count) +{ + struct usb_serial *serial = port->serial; + int request_unthrottle = 0; + int rc = 0; + DECLARE_WAITQUEUE(wait, current); + + /* guess how much room is left in the device's ring buffer, and if we + want to send more than that, check first, updating our notion of + what is left. If our write will result in no room left, ask the + device to give us an interrupt when the room available rises above + a threshold, and hold off all writers (eventually, those using + select() or poll() too) until we receive that unthrottle interrupt. + Block if we can't write anything at all, otherwise write as much as + we can. */ + + if (count == 0) { + dbg(" write request of 0 bytes"); + return (0); + } + + /* we might block because of: + the TX urb is in-flight (wait until it completes) + the device is full (wait until it says there is room) + */ + while (port->write_urb->status == -EINPROGRESS) { + if (0 /* file->f_flags & O_NONBLOCK */) { + rc = -EAGAIN; + goto err; + } + interruptible_sleep_on(&serial->write_wait); + if (signal_pending(current)) { + rc = -ERESTARTSYS; + goto err; + } + } + + /* at this point the URB is in our control, nobody else can submit it + again (the only sudden transition was the one from EINPROGRESS to + finished) */ + + /* the next potential block is that our TX process might be throttled. + The transition from throttled->not happens because of an Rx + interrupt, and the wake_up occurs during the same interrupt, so we + have to be careful to avoid a race that would cause us to sleep + forever. */ + + add_wait_queue(&serial->write_wait, &wait); + set_current_state(TASK_INTERRUPTIBLE); + while (serial->tx_throttled) { + /* device can't accomodate any more characters. Sleep until it + can. Woken up by an Rx interrupt message, which clears + tx_throttled first. */ + dbg(" tx_throttled, going to sleep"); + if (signal_pending(current)) { + current->state = TASK_RUNNING; + remove_wait_queue(&serial->write_wait, &wait); + dbg(" woke up because of signal"); + rc = -ERESTARTSYS; + goto err; + } + schedule(); + dbg(" woke up"); + } + remove_wait_queue(&serial->write_wait, &wait); + set_current_state(TASK_RUNNING); + + count = (count > port->bulk_out_size) ? port->bulk_out_size : count; + if (count > serial->tx_room) { + unsigned char room; + /* Looks like we might overrun the Tx buffer. Ask the device + how much room it really has */ + rc = usb_control_msg(serial->dev, + usb_rcvctrlpipe(serial->dev, 0), + 6, /* write_room */ + USB_TYPE_VENDOR | USB_RECIP_INTERFACE + | USB_DIR_IN, + 0, /* value: 0 means "remaining room" */ + 0, /* index */ + &room, + 1, + 2*HZ); + if (rc < 0) { + dbg(" roomquery failed"); + return rc; /* failed */ + } + if (rc == 0) { + dbg(" roomquery returned 0 bytes"); + return -EIO; /* device didn't return any data */ + } + dbg(" roomquery says %d", room); + serial->tx_room = room; + if (count > serial->tx_room) { + /* we're about to completely fill the Tx buffer, so + we'll be throttled afterwards. */ + count = serial->tx_room; + request_unthrottle = 1; + } + } + serial->tx_room -= count; + + if (count) { + /* now transfer data */ + if (from_user) { + copy_from_user(port->write_urb->transfer_buffer, buf, count); + } + else { + memcpy (port->write_urb->transfer_buffer, buf, count); + } + /* send the data out the bulk port */ + port->write_urb->transfer_buffer_length = count; + + if (usb_submit_urb(port->write_urb)) + dbg(" usb_submit_urb(write bulk) failed"); + } + else { + /* There wasn't any room left, so we are throttled until + the buffer empties a bit */ + request_unthrottle = 1; + } + + if (request_unthrottle) { + dbg(" request_unthrottle"); + /* ask the device to tell us when the tx buffer becomes + sufficiently empty */ + serial->tx_throttled = 1; /* block writers */ + rc = usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + 7, /* request_unthrottle */ + USB_TYPE_VENDOR | USB_RECIP_INTERFACE + | USB_DIR_OUT, + 16, /* value: threshold */ + 0, /* index */ + NULL, + 0, + 2*HZ); + } + + return (count); + err: + return (rc); +} + + +static void keyspan_pda_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; + + if (port_paranoia_check (port, "keyspan_pda_rx_interrupt")) { + return; + } + + serial = port->serial; + if (serial_paranoia_check (serial, "keyspan_pda_rx_interrupt")) { + return; + } + + wake_up_interruptible(&serial->write_wait); + + tty = port->tty; + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); + + wake_up_interruptible(&tty->write_wait); +} + + +static int keyspan_pda_write_room (struct usb_serial_port *port) +{ + struct usb_serial *serial = port->serial; + + /* used by n_tty.c for processing of tabs and such. Giving it our + conservative guess is probably good enough, but needs testing by + running a console through the device. */ + + return (serial->tx_room); +} + + +static int keyspan_pda_chars_in_buffer (struct usb_serial_port *port) +{ + struct usb_serial *serial = port->serial; + + /* when throttled, return at least WAKEUP_CHARS to tell select() (via + n_tty.c:normal_poll() ) that we're not writeable. */ + if (serial->tx_throttled) + return 256; + return 0; +} + + +static int keyspan_pda_open (struct usb_serial_port *port, struct file *filp) +{ + struct usb_serial *serial = port->serial; + unsigned char room; + int rc; + + if (port->active) { + return -EINVAL; + } + port->active = 1; + + /* find out how much room is in the Tx ring */ + rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), + 6, /* write_room */ + USB_TYPE_VENDOR | USB_RECIP_INTERFACE + | USB_DIR_IN, + 0, /* value */ + 0, /* index */ + &room, + 1, + 2*HZ); + if (rc < 0) { + dbg(" roomquery failed"); + return rc; /* failed */ + } + if (rc == 0) { + dbg(" roomquery returned 0 bytes"); + return -EIO; /* device didn't return any data */ + } + serial->tx_room = room; + serial->tx_throttled = room ? 0 : 1; + + /* the normal serial device seems to always turn on DTR and RTS here, + so do the same */ + if (port->tty->termios->c_cflag & CBAUD) + keyspan_pda_set_modem_info(serial, (1<<7) | (1<<2) ); + else + keyspan_pda_set_modem_info(serial, 0); + + /*Start reading from the device*/ + if (usb_submit_urb(port->read_urb)) + dbg(" usb_submit_urb(read int) failed"); + + return (0); +} + + +static void keyspan_pda_close(struct usb_serial_port *port, struct file *filp) +{ + struct usb_serial *serial = port->serial; + + /* the normal serial device seems to always shut off DTR and RTS now */ + if (port->tty->termios->c_cflag & HUPCL) + keyspan_pda_set_modem_info(serial, 0); + + /* shutdown our bulk reads and writes */ + usb_unlink_urb (port->write_urb); + usb_unlink_urb (port->read_urb); + port->active = 0; +} + + +/* download the firmware to a "fake" device (pre-renumeration) */ +static int keyspan_pda_fake_startup (struct usb_serial *serial) +{ + int response; + const struct ezusb_hex_record *record; + + /* download the firmware here ... */ + response = ezusb_set_reset(serial, 1); + + record = &keyspan_pda_firmware[0]; + while(record->address != 0xffff) { + response = ezusb_writememory(serial, record->address, + (unsigned char *)record->data, + record->data_size, 0xa0); + if (response < 0) { + err("ezusb_writememory failed for Keyspan PDA " + "firmware (%d %04X %p %d)", + response, + record->address, record->data, record->data_size); + break; + } + record++; + } + /* bring device out of reset. Renumeration will occur in a moment + and the new device will bind to the real driver */ + response = ezusb_set_reset(serial, 0); + + /* we want this device to fail to have a driver assigned to it. */ + return (1); +} + + +/* do some startup allocations not currently performed by usb_serial_probe() */ +static int keyspan_pda_startup (struct usb_serial *serial) +{ + struct usb_endpoint_descriptor *intin; + intin = serial->port[0].interrupt_in_endpoint; + + /* set up the receive interrupt urb */ + FILL_INT_URB(serial->port[0].read_urb, serial->dev, + usb_rcvintpipe(serial->dev, intin->bEndpointAddress), + serial->port[0].interrupt_in_buffer, + intin->wMaxPacketSize, + keyspan_pda_rx_interrupt, + serial, + intin->bInterval); + + init_waitqueue_head(&serial->write_wait); + + return (0); +} + +#endif /* CONFIG_USB_SERIAL_KEYSPAN_PDA */ + + diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/serial/usb-serial.c linux/drivers/usb/serial/usb-serial.c --- v2.3.99-pre3/linux/drivers/usb/serial/usb-serial.c Mon Mar 27 08:08:28 2000 +++ linux/drivers/usb/serial/usb-serial.c Wed Dec 31 16:00:00 1969 @@ -1,2593 +0,0 @@ -/* - * USB Serial Converter driver - * - * (C) Copyright (C) 1999, 2000 - * Greg Kroah-Hartman (greg@kroah.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 driver was originally based on the ACM driver by Armin Fuerst (which was - * based on a driver by Brad Keryan) - * - * See Documentation/usb/usb-serial.txt for more information on using this driver - * - * (03/19/2000) gkh - * Fixed oops that could happen when device was removed while a program - * was talking to the device. - * Removed the static urbs and now all urbs are created and destroyed - * dynamically. - * Reworked the internal interface. Now everything is based on the - * usb_serial_port structure instead of the larger usb_serial structure. - * This fixes the bug that a multiport device could not have more than - * one port open at one time. - * - * (03/17/2000) gkh - * Added config option for debugging messages. - * Added patch for keyspan pda from Brian Warner. - * - * (03/06/2000) gkh - * Added the keyspan pda code from Brian Warner - * Moved a bunch of the port specific stuff into its own structure. This - * is in anticipation of the true multiport devices (there's a bug if you - * try to access more than one port of any multiport device right now) - * - * (02/21/2000) gkh - * Made it so that any serial devices only have to specify which functions - * they want to overload from the generic function calls (great, - * inheritance in C, in a driver, just what I wanted...) - * Added support for set_termios and ioctl function calls. No drivers take - * advantage of this yet. - * Removed the #ifdef MODULE, now there is no module specific code. - * Cleaned up a few comments in usb-serial.h that were wrong (thanks again - * to Miles Lott). - * Small fix to get_free_serial. - * - * (02/14/2000) gkh - * Removed the Belkin and Peracom functionality from the driver due to - * the lack of support from the vendor, and me not wanting people to - * accidenatly buy the device, expecting it to work with Linux. - * Added read_bulk_callback and write_bulk_callback to the type structure - * for the needs of the FTDI and WhiteHEAT driver. - * Changed all reverences to FTDI to FTDI_SIO at the request of Bill - * Ryder. - * Changed the output urb size back to the max endpoint size to make - * the ftdi_sio driver have it easier, and due to the fact that it didn't - * really increase the speed any. - * - * (02/11/2000) gkh - * Added VISOR_FUNCTION_CONSOLE to the visor startup function. This was a - * patch from Miles Lott (milos@insync.net). - * Fixed bug with not restoring the minor range that a device grabs, if - * the startup function fails (thanks Miles for finding this). - * - * (02/05/2000) gkh - * Added initial framework for the Keyspan PDA serial converter so that - * Brian Warner has a place to put his code. - * Made the ezusb specific functions generic enough that different - * devices can use them (whiteheat and keyspan_pda both need them). - * Split out a whole bunch of structure and other stuff to a seperate - * usb-serial.h file. - * Made the Visor connection messages a little more understandable, now - * that Miles Lott (milos@insync.net) has gotten the Generic channel to - * work. Also made them always show up in the log file. - * - * (01/25/2000) gkh - * Added initial framework for FTDI serial converter so that Bill Ryder - * has a place to put his code. - * Added the vendor specific info from Handspring. Now we can print out - * informational debug messages as well as understand what is happening. - * - * (01/23/2000) gkh - * Fixed problem of crash when trying to open a port that didn't have a - * device assigned to it. Made the minor node finding a little smarter, - * now it looks to find a continous space for the new device. - * - * (01/21/2000) gkh - * Fixed bug in visor_startup with patch from Miles Lott (milos@insync.net) - * Fixed get_serial_by_minor which was all messed up for multi port - * devices. Fixed multi port problem for generic devices. Now the number - * of ports is determined by the number of bulk out endpoints for the - * generic device. - * - * (01/19/2000) gkh - * Removed lots of cruft that was around from the old (pre urb) driver - * interface. - * Made the serial_table dynamic. This should save lots of memory when - * the number of minor nodes goes up to 256. - * Added initial support for devices that have more than one port. - * Added more debugging comments for the Visor, and added a needed - * set_configuration call. - * - * (01/17/2000) gkh - * Fixed the WhiteHEAT firmware (my processing tool had a bug) - * and added new debug loader firmware for it. - * Removed the put_char function as it isn't really needed. - * Added visor startup commands as found by the Win98 dump. - * - * (01/13/2000) gkh - * Fixed the vendor id for the generic driver to the one I meant it to be. - * - * (01/12/2000) gkh - * Forget the version numbering...that's pretty useless... - * Made the driver able to be compiled so that the user can select which - * converter they want to use. This allows people who only want the Visor - * support to not pay the memory size price of the WhiteHEAT. - * Fixed bug where the generic driver (idVendor=0000 and idProduct=0000) - * grabbed the root hub. Not good. - * - * version 0.4.0 (01/10/2000) gkh - * Added whiteheat.h containing the firmware for the ConnectTech WhiteHEAT - * device. Added startup function to allow firmware to be downloaded to - * a device if it needs to be. - * Added firmware download logic to the WhiteHEAT device. - * Started to add #defines to split up the different drivers for potential - * configuration option. - * - * version 0.3.1 (12/30/99) gkh - * Fixed problems with urb for bulk out. - * Added initial support for multiple sets of endpoints. This enables - * the Handspring Visor to be attached successfully. Only the first - * bulk in / bulk out endpoint pair is being used right now. - * - * version 0.3.0 (12/27/99) gkh - * Added initial support for the Handspring Visor based on a patch from - * Miles Lott (milos@sneety.insync.net) - * Cleaned up the code a bunch and converted over to using urbs only. - * - * version 0.2.3 (12/21/99) gkh - * Added initial support for the Connect Tech WhiteHEAT converter. - * Incremented the number of ports in expectation of getting the - * WhiteHEAT to work properly (4 ports per connection). - * Added notification on insertion and removal of what port the - * device is/was connected to (and what kind of device it was). - * - * version 0.2.2 (12/16/99) gkh - * Changed major number to the new allocated number. We're legal now! - * - * version 0.2.1 (12/14/99) gkh - * Fixed bug that happens when device node is opened when there isn't a - * device attached to it. Thanks to marek@webdesign.no for noticing this. - * - * version 0.2.0 (11/10/99) gkh - * Split up internals to make it easier to add different types of serial - * converters to the code. - * Added a "generic" driver that gets it's vendor and product id - * from when the module is loaded. Thanks to David E. Nelson (dnelson@jump.net) - * for the idea and sample code (from the usb scanner driver.) - * Cleared up any licensing questions by releasing it under the GNU GPL. - * - * version 0.1.2 (10/25/99) gkh - * Fixed bug in detecting device. - * - * version 0.1.1 (10/05/99) gkh - * Changed the major number to not conflict with anything else. - * - * version 0.1 (09/28/99) gkh - * Can recognize the two different devices and start up a read from - * device when asked to. Writes also work. No control signals yet, this - * all is vendor specific data (i.e. no spec), also no control for - * different baud rates or other bit settings. - * Currently we are using the same devid as the acm driver. This needs - * to change. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_USB_SERIAL_DEBUG - #define DEBUG -#else - #undef DEBUG -#endif -#include - -#ifdef CONFIG_USB_SERIAL_WHITEHEAT -#include "whiteheat.h" /* firmware for the ConnectTech WhiteHEAT device */ -#endif - -#ifdef CONFIG_USB_SERIAL_KEYSPAN_PDA -struct ezusb_hex_record { - __u16 address; - __u8 data_size; - __u8 data[16]; -}; -#include "keyspan_pda_fw.h" -#endif - -#include "usb-serial.h" - -/* parity check flag */ -#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) - -/* local function prototypes */ -static int serial_open (struct tty_struct *tty, struct file * filp); -static void serial_close (struct tty_struct *tty, struct file * filp); -static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count); -static int serial_write_room (struct tty_struct *tty); -static int serial_chars_in_buffer (struct tty_struct *tty); -static void serial_throttle (struct tty_struct * tty); -static void serial_unthrottle (struct tty_struct * tty); -static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg); -static void serial_set_termios (struct tty_struct *tty, struct termios * old); - -static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum); -static void usb_serial_disconnect(struct usb_device *dev, void *ptr); - -static struct usb_driver usb_serial_driver = { - name: "serial", - probe: usb_serial_probe, - disconnect: usb_serial_disconnect, -}; - -static int serial_refcount; -static struct tty_struct * serial_tty[SERIAL_TTY_MINORS]; -static struct termios * serial_termios[SERIAL_TTY_MINORS]; -static struct termios * serial_termios_locked[SERIAL_TTY_MINORS]; -static struct usb_serial *serial_table[SERIAL_TTY_MINORS] = {NULL, }; - - -static inline int serial_paranoia_check (struct usb_serial *serial, const char *function) -{ - if (!serial) { - dbg("%s - serial == NULL", function); - return -1; - } - if (serial->magic != USB_SERIAL_MAGIC) { - dbg("%s - bad magic number for serial", function); - return -1; - } - if (!serial->type) { - dbg("%s - serial->type == NULL!", function); - return -1; - } - - return 0; -} - - -static inline int port_paranoia_check (struct usb_serial_port *port, const char *function) -{ - if (!port) { - dbg("%s - port == NULL", function); - return -1; - } - if (port->magic != USB_SERIAL_PORT_MAGIC) { - dbg("%s - bad magic number for port", function); - return -1; - } - if (!port->serial) { - dbg("%s - port->serial == NULL", function); - return -1; - } - if (!port->tty) { - dbg("%s - port->tty == NULL", function); - return -1; - } - - return 0; -} - - -static struct usb_serial *get_serial_by_minor (int minor) -{ - return serial_table[minor]; -} - - -static struct usb_serial *get_free_serial (int num_ports, int *minor) -{ - struct usb_serial *serial = NULL; - int i, j; - int good_spot; - - dbg("get_free_serial %d", num_ports); - - *minor = 0; - for (i = 0; i < SERIAL_TTY_MINORS; ++i) { - if (serial_table[i]) - continue; - - good_spot = 1; - for (j = 1; j <= num_ports-1; ++j) - if (serial_table[i+j]) - good_spot = 0; - if (good_spot == 0) - continue; - - if (!(serial = kmalloc(sizeof(struct usb_serial), GFP_KERNEL))) { - err("Out of memory"); - return NULL; - } - memset(serial, 0, sizeof(struct usb_serial)); - serial->magic = USB_SERIAL_MAGIC; - serial_table[i] = serial; - *minor = i; - dbg("minor base = %d", *minor); - for (i = *minor+1; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) - serial_table[i] = serial; - return serial; - } - return NULL; -} - - -static void return_serial (struct usb_serial *serial) -{ - int i; - - dbg("return_serial"); - - if (serial == NULL) - return; - - for (i = 0; i < serial->num_ports; ++i) { - serial_table[serial->minor + i] = NULL; - } - - return; -} - - -#ifdef USES_EZUSB_FUNCTIONS -/* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */ -#define CPUCS_REG 0x7F92 - -static int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *data, int length, __u8 bRequest) -{ - int result; - unsigned char *transfer_buffer = kmalloc (length, GFP_KERNEL); - -// dbg("ezusb_writememory %x, %d", address, length); - - if (!transfer_buffer) { - err("ezusb_writememory: kmalloc(%d) failed.", length); - return -ENOMEM; - } - memcpy (transfer_buffer, data, length); - result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), bRequest, 0x40, address, 0, transfer_buffer, length, 300); - kfree (transfer_buffer); - return result; -} - - -static int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit) -{ - int response; - dbg("ezusb_set_reset: %d", reset_bit); - response = ezusb_writememory (serial, CPUCS_REG, &reset_bit, 1, 0xa0); - if (response < 0) { - err("ezusb_set_reset %d failed", reset_bit); - } - return response; -} - -#endif /* USES_EZUSB_FUNCTIONS */ - - -/***************************************************************************** - * Driver tty interface functions - *****************************************************************************/ -static int serial_open (struct tty_struct *tty, struct file * filp) -{ - struct usb_serial *serial; - struct usb_serial_port *port; - int portNumber; - - dbg("serial_open"); - - /* initialize the pointer incase something fails */ - tty->driver_data = NULL; - - /* get the serial object associated with this tty pointer */ - serial = get_serial_by_minor (MINOR(tty->device)); - - if (serial_paranoia_check (serial, "serial_open")) { - return -ENODEV; - } - - /* set up our port structure */ - portNumber = MINOR(tty->device) - serial->minor; - port = &serial->port[portNumber]; - port->number = portNumber; - port->serial = serial; - port->magic = USB_SERIAL_PORT_MAGIC; - - /* make the tty driver remember our port object, and us it */ - tty->driver_data = port; - port->tty = tty; - - /* pass on to the driver specific version of this function if it is available */ - if (serial->type->open) { - return (serial->type->open(port, filp)); - } else { - return (generic_open(port, filp)); - } -} - - -static void serial_close(struct tty_struct *tty, struct file * filp) -{ - struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; - struct usb_serial *serial; - - dbg("serial_close"); - - if (port_paranoia_check (port, "serial_close")) { - return; - } - - serial = port->serial; - if (serial_paranoia_check (serial, "serial_close")) { - return; - } - - dbg("serial_close port %d", port->number); - - if (!port->active) { - dbg ("port not opened"); - return; - } - - /* pass on to the driver specific version of this function if it is available */ - if (serial->type->close) { - serial->type->close(port, filp); - } else { - generic_close(port, filp); - } -} - - -static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count) -{ - struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; - struct usb_serial *serial; - - dbg("serial_write"); - - if (port_paranoia_check (port, "serial_write")) { - return -ENODEV; - } - - serial = port->serial; - if (serial_paranoia_check (serial, "serial_write")) { - return -ENODEV; - } - - dbg("serial_write port %d, %d byte(s)", port->number, count); - - if (!port->active) { - dbg ("port not opened"); - return -EINVAL; - } - - /* pass on to the driver specific version of this function if it is available */ - if (serial->type->write) { - return (serial->type->write(port, from_user, buf, count)); - } else { - return (generic_write(port, from_user, buf, count)); - } -} - - -static int serial_write_room (struct tty_struct *tty) -{ - struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; - struct usb_serial *serial; - - dbg("serial_write_room"); - - if (port_paranoia_check (port, "serial_write")) { - return -ENODEV; - } - - serial = port->serial; - if (serial_paranoia_check (serial, "serial_write")) { - return -ENODEV; - } - - dbg("serial_write_room port %d", port->number); - - if (!port->active) { - dbg ("port not open"); - return -EINVAL; - } - - /* pass on to the driver specific version of this function if it is available */ - if (serial->type->write_room) { - return (serial->type->write_room(port)); - } else { - return (generic_write_room(port)); - } -} - - -static int serial_chars_in_buffer (struct tty_struct *tty) -{ - struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; - struct usb_serial *serial; - - dbg("serial_chars_in_buffer"); - - if (port_paranoia_check (port, "serial_chars_in_buffer")) { - return -ENODEV; - } - - serial = port->serial; - if (serial_paranoia_check (serial, "serial_chars_in_buffer")) { - return -ENODEV; - } - - if (!port->active) { - dbg ("port not open"); - return -EINVAL; - } - - /* pass on to the driver specific version of this function if it is available */ - if (serial->type->chars_in_buffer) { - return (serial->type->chars_in_buffer(port)); - } else { - return (generic_chars_in_buffer(port)); - } -} - - -static void serial_throttle (struct tty_struct * tty) -{ - struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; - struct usb_serial *serial; - - dbg("serial_throttle"); - - if (port_paranoia_check (port, "serial_throttle")) { - return; - } - - serial = port->serial; - if (serial_paranoia_check (serial, "serial_throttle")) { - return; - } - - dbg("serial_throttle port %d", port->number); - - if (!port->active) { - dbg ("port not open"); - return; - } - - /* pass on to the driver specific version of this function */ - if (serial->type->throttle) { - serial->type->throttle(port); - } - - return; -} - - -static void serial_unthrottle (struct tty_struct * tty) -{ - struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; - struct usb_serial *serial; - - dbg("serial_unthrottle"); - - if (port_paranoia_check (port, "serial_unthrottle")) { - return; - } - - serial = port->serial; - if (serial_paranoia_check (serial, "serial_unthrottle")) { - return; - } - - dbg("serial_unthrottle port %d", port->number); - - if (!port->active) { - dbg ("port not open"); - return; - } - - /* pass on to the driver specific version of this function */ - if (serial->type->unthrottle) { - serial->type->unthrottle(port); - } - - return; -} - - -static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) -{ - struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; - struct usb_serial *serial; - - dbg("serial_ioctl"); - - if (port_paranoia_check (port, "serial_ioctl")) { - return -ENODEV; - } - - serial = port->serial; - if (serial_paranoia_check (serial, "serial_ioctl")) { - return -ENODEV; - } - - dbg("serial_ioctl port %d", port->number); - - if (!port->active) { - dbg ("port not open"); - return -ENODEV; - } - - /* pass on to the driver specific version of this function if it is available */ - if (serial->type->ioctl) { - return (serial->type->ioctl(port, file, cmd, arg)); - } else { - return -ENOIOCTLCMD; - } -} - - -static void serial_set_termios (struct tty_struct *tty, struct termios * old) -{ - struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; - struct usb_serial *serial; - - dbg("serial_set_termios"); - - if (port_paranoia_check (port, "serial_set_termios")) { - return; - } - - serial = port->serial; - if (serial_paranoia_check (serial, "serial_set_termios")) { - return; - } - - dbg("serial_set_termios port %d", port->number); - - if (!port->active) { - dbg ("port not open"); - return; - } - - /* pass on to the driver specific version of this function if it is available */ - if (serial->type->set_termios) { - serial->type->set_termios(port, old); - } - - return; -} - - -static void serial_break (struct tty_struct *tty, int break_state) -{ - struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; - struct usb_serial *serial; - - dbg("serial_break"); - - if (port_paranoia_check (port, "serial_break")) { - return; - } - - serial = port->serial; - if (serial_paranoia_check (serial, "serial_break")) { - return; - } - - dbg("serial_break port %d", port->number); - - if (!port->active) { - dbg ("port not open"); - return; - } - - /* pass on to the driver specific version of this function if it is - available */ - if (serial->type->break_ctl) { - serial->type->break_ctl(port, break_state); - } -} - - -#ifdef CONFIG_USB_SERIAL_WHITEHEAT -/***************************************************************************** - * Connect Tech's White Heat specific driver functions - *****************************************************************************/ -static int whiteheat_open (struct usb_serial_port *port, struct file *filp) -{ - dbg("whiteheat_open port %d", port->number); - - if (port->active) { - dbg ("device already open"); - return -EINVAL; - } - port->active = 1; - - /*Start reading from the device*/ - if (usb_submit_urb(port->read_urb)) - dbg("usb_submit_urb(read bulk) failed"); - - /* Need to do device specific setup here (control lines, baud rate, etc.) */ - /* FIXME!!! */ - - return (0); -} - - -static void whiteheat_close(struct usb_serial_port *port, struct file * filp) -{ - dbg("whiteheat_close port %d", port->number); - - /* Need to change the control lines here */ - /* FIXME */ - - /* shutdown our bulk reads and writes */ - usb_unlink_urb (port->write_urb); - usb_unlink_urb (port->read_urb); - port->active = 0; -} - - -static void whiteheat_set_termios (struct usb_serial_port *port, struct termios *old_termios) -{ - unsigned int cflag = port->tty->termios->c_cflag; - - dbg("whiteheat_set_termios port %d", port->number); - - /* check that they really want us to change something */ - if (old_termios) { - if ((cflag == old_termios->c_cflag) && - (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) { - dbg("nothing to change..."); - return; - } - } - - /* do the parsing of the cflag to see what to set the line to */ - /* FIXME!! */ - - return; -} - -static void whiteheat_throttle (struct usb_serial_port *port) -{ - dbg("whiteheat_throttle port %d", port->number); - - /* Change the control signals */ - /* FIXME!!! */ - - return; -} - - -static void whiteheat_unthrottle (struct usb_serial_port *port) -{ - dbg("whiteheat_unthrottle port %d", port->number); - - /* Change the control signals */ - /* FIXME!!! */ - - return; -} - - -/* steps to download the firmware to the WhiteHEAT device: - - hold the reset (by writing to the reset bit of the CPUCS register) - - download the VEND_AX.HEX file to the chip using VENDOR_REQUEST-ANCHOR_LOAD - - release the reset (by writing to the CPUCS register) - - download the WH.HEX file for all addresses greater than 0x1b3f using - VENDOR_REQUEST-ANCHOR_EXTERNAL_RAM_LOAD - - hold the reset - - download the WH.HEX file for all addresses less than 0x1b40 using - VENDOR_REQUEST_ANCHOR_LOAD - - release the reset - - device renumerated itself and comes up as new device id with all - firmware download completed. -*/ -static int whiteheat_startup (struct usb_serial *serial) -{ - int response; - const struct whiteheat_hex_record *record; - - dbg("whiteheat_startup"); - - response = ezusb_set_reset (serial, 1); - - record = &whiteheat_loader[0]; - while (record->address != 0xffff) { - response = ezusb_writememory (serial, record->address, - (unsigned char *)record->data, record->data_size, 0xa0); - if (response < 0) { - err("ezusb_writememory failed for loader (%d %04X %p %d)", - response, record->address, record->data, record->data_size); - break; - } - ++record; - } - - response = ezusb_set_reset (serial, 0); - - record = &whiteheat_firmware[0]; - while (record->address < 0x1b40) { - ++record; - } - while (record->address != 0xffff) { - response = ezusb_writememory (serial, record->address, - (unsigned char *)record->data, record->data_size, 0xa0); - if (response < 0) { - err("ezusb_writememory failed for first firmware step (%d %04X %p %d)", - response, record->address, record->data, record->data_size); - break; - } - ++record; - } - - response = ezusb_set_reset (serial, 1); - - record = &whiteheat_firmware[0]; - while (record->address < 0x1b40) { - response = ezusb_writememory (serial, record->address, - (unsigned char *)record->data, record->data_size, 0xa0); - if (response < 0) { - err("ezusb_writememory failed for second firmware step (%d %04X %p %d)", - response, record->address, record->data, record->data_size); - break; - } - ++record; - } - - response = ezusb_set_reset (serial, 0); - - /* we want this device to fail to have a driver assigned to it. */ - return (1); -} -#endif /* CONFIG_USB_SERIAL_WHITEHEAT */ - - -#ifdef CONFIG_USB_SERIAL_VISOR -/****************************************************************************** - * Handspring Visor specific driver functions - ******************************************************************************/ -static int visor_open (struct usb_serial_port *port, struct file *filp) -{ - dbg("visor_open port %d", port->number); - - if (port->active) { - dbg ("device already open"); - return -EINVAL; - } - - port->active = 1; - - /*Start reading from the device*/ - if (usb_submit_urb(port->read_urb)) - dbg("usb_submit_urb(read bulk) failed"); - - return (0); -} - - -static void visor_close (struct usb_serial_port *port, struct file * filp) -{ - struct usb_serial *serial = port->serial; - unsigned char *transfer_buffer = kmalloc (0x12, GFP_KERNEL); - - dbg("visor_close port %d", port->number); - - if (!transfer_buffer) { - err("visor_close: kmalloc(%d) failed.", 0x12); - } else { - /* send a shutdown message to the device */ - usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_CLOSE_NOTIFICATION, - 0xc2, 0x0000, 0x0000, transfer_buffer, 0x12, 300); - } - - /* shutdown our bulk reads and writes */ - usb_unlink_urb (port->write_urb); - usb_unlink_urb (port->read_urb); - port->active = 0; -} - - -static void visor_throttle (struct usb_serial_port *port) -{ - dbg("visor_throttle port %d", port->number); - - usb_unlink_urb (port->read_urb); - - return; -} - - -static void visor_unthrottle (struct usb_serial_port *port) -{ - dbg("visor_unthrottle port %d", port->number); - - if (usb_unlink_urb (port->read_urb)) - dbg("usb_submit_urb(read bulk) failed"); - - return; -} - - -static int visor_startup (struct usb_serial *serial) -{ - int response; - int i; - unsigned char *transfer_buffer = kmalloc (256, GFP_KERNEL); - - if (!transfer_buffer) { - err("visor_startup: kmalloc(%d) failed.", 256); - return -ENOMEM; - } - - dbg("visor_startup"); - - dbg("visor_setup: Set config to 1"); - usb_set_configuration (serial->dev, 1); - - /* send a get connection info request */ - response = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_GET_CONNECTION_INFORMATION, - 0xc2, 0x0000, 0x0000, transfer_buffer, 0x12, 300); - if (response < 0) { - err("visor_startup: error getting connection information"); - } else { - struct visor_connection_info *connection_info = (struct visor_connection_info *)transfer_buffer; - char *string; - info("%s: Number of ports: %d", serial->type->name, connection_info->num_ports); - for (i = 0; i < connection_info->num_ports; ++i) { - switch (connection_info->connections[i].port_function_id) { - case VISOR_FUNCTION_GENERIC: - string = "Generic"; - break; - case VISOR_FUNCTION_DEBUGGER: - string = "Debugger"; - break; - case VISOR_FUNCTION_HOTSYNC: - string = "HotSync"; - break; - case VISOR_FUNCTION_CONSOLE: - string = "Console"; - break; - case VISOR_FUNCTION_REMOTE_FILE_SYS: - string = "Remote File System"; - break; - default: - string = "unknown"; - break; - } - info("%s: port %d, is for %s use and is bound to ttyUSB%d", serial->type->name, connection_info->connections[i].port, string, serial->minor + i); - } - } - - /* ask for the number of bytes available, but ignore the response as it is broken */ - response = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_REQUEST_BYTES_AVAILABLE, - 0xc2, 0x0000, 0x0005, transfer_buffer, 0x02, 300); - if (response < 0) { - err("visor_startup: error getting bytes available request"); - } - - kfree (transfer_buffer); - - /* continue on with initialization */ - return (0); -} - - -#endif /* CONFIG_USB_SERIAL_VISOR*/ - - -#ifdef CONFIG_USB_SERIAL_FTDI_SIO -/****************************************************************************** - * FTDI SIO Serial Converter specific driver functions - ******************************************************************************/ - -/* Bill Ryder - bryder@sgi.com - wrote the FTDI_SIO implementation */ -/* Thanx to FTDI for so kindly providing details of the protocol required */ -/* to talk to the device */ - -#include "ftdi_sio.h" - -static int ftdi_sio_open (struct usb_serial_port *port, struct file *filp) -{ - struct usb_serial *serial = port->serial; - char buf[1]; /* Needed for the usb_control_msg I think */ - - dbg("ftdi_sio_open port %d", port->number); - - if (port->active) { - dbg ("port already open"); - return -EINVAL; - } - port->active = 1; - - usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, - FTDI_SIO_RESET_SIO, - 0, buf, 0, HZ * 5); - - /* FIXME - Should I really purge the buffers? */ - usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, - FTDI_SIO_RESET_PURGE_RX, - 0, buf, 0, HZ * 5); - - usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, - FTDI_SIO_RESET_PURGE_TX, - 0, buf, 0, HZ * 5); - - - /* As per usb_serial_init s/be CS8, B9600, 1 STOP BIT */ - if ( usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - FTDI_SIO_SET_BAUDRATE_REQUEST, - FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE, - ftdi_sio_b9600, 0, - buf, 0, HZ * 5) < 0){ - dbg("Error from baudrate urb"); - return(-EINVAL); - } - - if ( usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - FTDI_SIO_SET_DATA_REQUEST, - FTDI_SIO_SET_DATA_REQUEST_TYPE, - 8 | FTDI_SIO_SET_DATA_PARITY_NONE | - FTDI_SIO_SET_DATA_STOP_BITS_1, 0, - buf, 0, HZ * 5) < 0){ - dbg("Error from cs8/noparity/1 stopbit urb"); - return(-EINVAL); - } - - /* Disable flow control */ - if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - FTDI_SIO_SET_FLOW_CTRL_REQUEST, - FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, - 0, 0, - buf, 0, HZ * 5) < 0) { - dbg("error from flowcontrol urb"); - return(-EINVAL); - } - - /* Turn on RTS and DTR since we are not flow controlling*/ - /* FIXME - check for correct behaviour clocal vs non clocal */ - /* FIXME - might be able to do both simultaneously */ - if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - FTDI_SIO_SET_MODEM_CTRL_REQUEST, - FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, - (unsigned)FTDI_SIO_SET_DTR_HIGH, 0, - buf, 0, HZ * 5) < 0) { - dbg("Error from DTR HIGH urb"); - } - if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - FTDI_SIO_SET_MODEM_CTRL_REQUEST, - FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, - (unsigned)FTDI_SIO_SET_RTS_HIGH, 0, - buf, 0, HZ * 5) < 0) { - dbg("Error from RTS HIGH urb"); - } - - /*Start reading from the device*/ - if (usb_submit_urb(port->read_urb)) - dbg("usb_submit_urb(read bulk) failed"); - - return (0); -} - - -static void ftdi_sio_close (struct usb_serial_port *port, struct file *filp) -{ - struct usb_serial *serial = port->serial; - char buf[1]; - - dbg("ftdi_sio_close port %d", port->number); - - /* FIXME - might be able to do both simultaneously */ - if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - FTDI_SIO_SET_MODEM_CTRL_REQUEST, - FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, - (unsigned)FTDI_SIO_SET_DTR_LOW, 0, - buf, 0, HZ * 5) < 0) { - dbg("Error from DTR LOW urb"); - } - if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - FTDI_SIO_SET_MODEM_CTRL_REQUEST, - FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, - (unsigned)FTDI_SIO_SET_RTS_LOW, 0, - buf, 0, HZ * 5) < 0) { - dbg("Error from RTS LOW urb"); - } - - /* FIXME Should I flush the device here? - not doing it for now */ - - /* shutdown our bulk reads and writes */ - usb_unlink_urb (port->write_urb); - usb_unlink_urb (port->read_urb); - port->active = 0; -} - - - -/* The ftdi_sio requires the first byte to have: - B0 1 - B1 0 - B2..7 length of message excluding byte 0 -*/ -static int ftdi_sio_write (struct usb_serial_port *port, int from_user, - const unsigned char *buf, int count) -{ - struct usb_serial *serial = port->serial; - const int data_offset = 1; - - dbg("ftdi_sio_serial_write port %d, %d bytes", port->number, count); - - if (count == 0) { - dbg("write request of 0 bytes"); - return 0; - } - - /* only do something if we have a bulk out endpoint */ - if (serial->num_bulk_out) { - unsigned char *first_byte = port->write_urb->transfer_buffer; - - if (port->write_urb->status == -EINPROGRESS) { - dbg ("already writing"); - return 0; - } - - count += data_offset; - count = (count > port->bulk_out_size) ? port->bulk_out_size : count; - if (count == 0) { - return 0; - } - - /* Copy in the data to send */ - if (from_user) { - copy_from_user(port->write_urb->transfer_buffer + data_offset , - buf, count - data_offset ); - } - else { - memcpy(port->write_urb->transfer_buffer + data_offset, - buf, count - data_offset ); - } - - /* Write the control byte at the front of the packet*/ - first_byte = port->write_urb->transfer_buffer; - *first_byte = 1 | ((count-data_offset) << 2) ; - -#ifdef DEBUG - dbg("Bytes: %d, Control Byte: 0o%03o",count, first_byte[0]); - - if (count) { - int i; - printk (KERN_DEBUG __FILE__ ": data written - length = %d, data = ", count); - for (i = 0; i < count; ++i) { - printk ("0x%02x ", first_byte[i]); - if (first_byte[i] > ' ' && first_byte[i] < '~') { - printk("%c ", first_byte[i]); - } else { - printk(" "); - } - } - - - printk ("\n"); - } - -#endif - /* send the data out the bulk port */ - port->write_urb->transfer_buffer_length = count; - - if (usb_submit_urb(port->write_urb)) - dbg("usb_submit_urb(write bulk) failed"); - - dbg("write returning: %d", count - data_offset); - return (count - data_offset); - } - - /* no bulk out, so return 0 bytes written */ - return 0; -} - - -static void ftdi_sio_read_bulk_callback (struct urb *urb) -{ /* ftdi_sio_serial_buld_callback */ - struct usb_serial_port *port = (struct usb_serial_port *)urb->context; - struct usb_serial *serial; - struct tty_struct *tty; - unsigned char *data = urb->transfer_buffer; - const int data_offset = 2; - int i; - - dbg("ftdi_sio_read_bulk_callback"); - - if (port_paranoia_check (port, "ftdi_sio_read_bulk_callback")) { - return; - } - - serial = port->serial; - if (serial_paranoia_check (serial, "ftdi_sio_read_bulk_callback")) { - return; - } - - if (urb->status) { - dbg("nonzero read bulk status received: %d", urb->status); - return; - } - -#ifdef DEBUG - if (urb->actual_length > 2) { - printk (KERN_DEBUG __FILE__ ": data read - length = %d, data = ", urb->actual_length); - for (i = 0; i < urb->actual_length; ++i) { - printk ("0x%.2x ", data[i]); - if (data[i] > ' ' && data[i] < '~') { - printk("%c ", data[i]); - } else { - printk(" "); - } - } - printk ("\n"); - } -#endif - - - if (urb->actual_length > data_offset) { - tty = port->tty; - for (i = data_offset ; i < urb->actual_length ; ++i) { - tty_insert_flip_char(tty, data[i], 0); - } - tty_flip_buffer_push(tty); - } - - /* Continue trying to always read */ - if (usb_submit_urb(urb)) - dbg("failed resubmitting read urb"); - - return; -} /* ftdi_sio_serial_read_bulk_callback */ - - -static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios *old_termios) -{ - struct usb_serial *serial = port->serial; - unsigned int cflag = port->tty->termios->c_cflag; - __u16 urb_value; /* Will hold the new flags */ - char buf[1]; /* Perhaps I should dynamically alloc this? */ - - dbg("ftdi_sio_set_termios port %d", port->number); - - /* FIXME - we should keep the old termios really */ - /* FIXME -For this cut I don't care if the line is really changing or - not - so just do the change regardless */ - - /* Set number of data bits, parity, stop bits */ - - urb_value = 0; - urb_value |= (cflag & CSTOPB ? FTDI_SIO_SET_DATA_STOP_BITS_2 : - FTDI_SIO_SET_DATA_STOP_BITS_1); - urb_value |= (cflag & PARENB ? - (cflag & PARODD ? FTDI_SIO_SET_DATA_PARITY_ODD : - FTDI_SIO_SET_DATA_PARITY_EVEN) : - FTDI_SIO_SET_DATA_PARITY_NONE); - if (cflag & CSIZE) { - switch (cflag & CSIZE) { - case CS5: urb_value |= 5; dbg("Setting CS5"); break; - case CS6: urb_value |= 6; dbg("Setting CS6"); break; - case CS7: urb_value |= 7; dbg("Setting CS7"); break; - case CS8: urb_value |= 8; dbg("Setting CS8"); break; - default: - dbg("CSIZE was set but not CS5-CS8"); - } - } - if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - FTDI_SIO_SET_DATA_REQUEST, - FTDI_SIO_SET_DATA_REQUEST_TYPE, - urb_value , 0, - buf, 0, 100) < 0) { - dbg("FAILED to set databits/stopbits/parity"); - } - - /* Now do the baudrate */ - /* FIXME - should drop lines on B0 */ - /* FIXME Should also handle CLOCAL here */ - - switch(cflag & CBAUD){ - case B300: urb_value = ftdi_sio_b300; dbg("Set to 300"); break; - case B600: urb_value = ftdi_sio_b600; dbg("Set to 600") ; break; - case B1200: urb_value = ftdi_sio_b1200; dbg("Set to 1200") ; break; - case B2400: urb_value = ftdi_sio_b2400; dbg("Set to 2400") ; break; - case B4800: urb_value = ftdi_sio_b4800; dbg("Set to 4800") ; break; - case B9600: urb_value = ftdi_sio_b9600; dbg("Set to 9600") ; break; - case B19200: urb_value = ftdi_sio_b19200; dbg("Set to 19200") ; break; - case B38400: urb_value = ftdi_sio_b38400; dbg("Set to 38400") ; break; - case B57600: urb_value = ftdi_sio_b57600; dbg("Set to 57600") ; break; - case B115200: urb_value = ftdi_sio_b115200; dbg("Set to 115200") ; break; - default: dbg("FTDI_SIO does not support the baudrate requested"); - /* FIXME - how to return an error for this? */ break; - } - /* Send the URB */ - if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - FTDI_SIO_SET_BAUDRATE_REQUEST, - FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE, - urb_value, 0, - buf, 0, 100) < 0) { - dbg("urb failed to set baurdrate"); - } - return; -} - - -/*FIXME - the beginnings of this implementation - not even hooked into the driver yet */ -static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg) -{ - struct usb_serial *serial = port->serial; - __u16 urb_value=0; /* Will hold the new flags */ - char buf[1]; - int ret, mask; - - dbg("ftdi_sio_ioctl port %d", port->number); - - /* Based on code from acm.c */ - switch (cmd) { - - case TIOCMGET: - /* Request the status from the device */ - if ((ret = usb_control_msg(serial->dev, - usb_sndctrlpipe(serial->dev, 0), - FTDI_SIO_GET_MODEM_STATUS_REQUEST, - FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, - 0, 0, - buf, 1, HZ * 5)) < 0 ) { - dbg("Get not get modem status of device"); - return(ret); - } - - return put_user((buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) | - (buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) | - (buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) | - (buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0), - (unsigned long *) arg); - break; - - case TIOCMSET: - case TIOCMBIS: - case TIOCMBIC: - if ((ret = get_user(mask, (unsigned long *) arg))) return ret; - - /* FIXME Need to remember if we have set DTR or RTS since we - can't ask the device */ - /* FIXME - also need to find the meaning of TIOCMBIS/BIC/SET */ - if (mask & TIOCM_DTR) { - switch(cmd) { - case TIOCMSET: - urb_value = FTDI_SIO_SET_DTR_HIGH | FTDI_SIO_SET_RTS_LOW; - break; - - case TIOCMBIS: - /* Will leave RTS alone and set DTR */ - urb_value = FTDI_SIO_SET_DTR_HIGH; - break; - - case TIOCMBIC: - urb_value = FTDI_SIO_SET_DTR_LOW; - break; - } - } - - if (mask & TIOCM_RTS) { - switch(cmd) { - case TIOCMSET: - urb_value = FTDI_SIO_SET_DTR_LOW | FTDI_SIO_SET_RTS_HIGH; - break; - - case TIOCMBIS: - /* Will leave DTR and set RTS */ - urb_value = FTDI_SIO_SET_RTS_HIGH; - break; - - case TIOCMBIC: - /* Will unset RTS */ - urb_value = FTDI_SIO_SET_RTS_LOW; - break; - } - } - - - return(usb_control_msg(serial->dev, - usb_sndctrlpipe(serial->dev, 0), - FTDI_SIO_SET_MODEM_CTRL_REQUEST, - FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, - urb_value , 0, - buf, 0, HZ * 5)); - } - - return -ENOIOCTLCMD; -} - -#endif /* CONFIG_USB_SERIAL_FTDI_SIO */ - - -#ifdef CONFIG_USB_SERIAL_KEYSPAN_PDA -/***************************************************************************** - * Keyspan PDA specific driver functions - *****************************************************************************/ - -static void keyspan_pda_rx_interrupt (struct urb *urb) -{ - struct usb_serial_port *port = (struct usb_serial_port *)urb->context; - struct usb_serial *serial; - struct tty_struct *tty; - unsigned char *data = urb->transfer_buffer; - int i; - - /* the urb might have been killed. */ - if (urb->status) - return; - - if (port_paranoia_check (port, "keyspan_pda_rx_interrupt")) { - return; - } - - serial = port->serial; - if (serial_paranoia_check (serial, "keyspan_pda_rx_interrupt")) { - return; - } - - /* see if the message is data or a status interrupt */ - switch (data[0]) { - case 0: - /* rest of message is rx data */ - if (urb->actual_length) { - tty = serial->port[0].tty; - for (i = 1; i < urb->actual_length ; ++i) { - tty_insert_flip_char(tty, data[i], 0); - } - tty_flip_buffer_push(tty); - } - break; - case 1: - /* status interrupt */ - dbg(" rx int, d1=%d, d2=%d", data[1], data[2]); - switch (data[1]) { - case 1: /* modemline change */ - break; - case 2: /* tx unthrottle interrupt */ - tty = serial->port[0].tty; - serial->tx_throttled = 0; - wake_up(&serial->write_wait); /* wake up writer */ - wake_up(&tty->write_wait); /* them too */ - break; - default: - break; - } - break; - default: - break; - } - - /* INT urbs are automatically re-submitted */ -} - - -static void keyspan_pda_rx_throttle (struct usb_serial_port *port) -{ - /* stop receiving characters. We just turn off the URB request, and - let chars pile up in the device. If we're doing hardware - flowcontrol, the device will signal the other end when its buffer - fills up. If we're doing XON/XOFF, this would be a good time to - send an XOFF, although it might make sense to foist that off - upon the device too. */ - - dbg("keyspan_pda_rx_throttle port %d", port->number); - usb_unlink_urb(port->read_urb); -} - - -static void keyspan_pda_rx_unthrottle (struct usb_serial_port *port) -{ - /* just restart the receive interrupt URB */ - dbg("keyspan_pda_rx_unthrottle port %d", port->number); - if (usb_submit_urb(port->read_urb)) - dbg(" usb_submit_urb(read urb) failed"); - return; -} - - -static int keyspan_pda_setbaud (struct usb_serial *serial, int baud) -{ - int rc; - int bindex; - - switch(baud) { - case 110: bindex = 0; break; - case 300: bindex = 1; break; - case 1200: bindex = 2; break; - case 2400: bindex = 3; break; - case 4800: bindex = 4; break; - case 9600: bindex = 5; break; - case 19200: bindex = 6; break; - case 38400: bindex = 7; break; - case 57600: bindex = 8; break; - case 115200: bindex = 9; break; - default: return -EINVAL; - } - - /* rather than figure out how to sleep while waiting for this - to complete, I just use the "legacy" API. */ - rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - 0, /* set baud */ - USB_TYPE_VENDOR - | USB_RECIP_INTERFACE - | USB_DIR_OUT, /* type */ - bindex, /* value */ - 0, /* index */ - NULL, /* &data */ - 0, /* size */ - 2*HZ); /* timeout */ - return(rc); -} - - -static void keyspan_pda_break_ctl (struct usb_serial_port *port, int break_state) -{ - struct usb_serial *serial = port->serial; - int value; - if (break_state == -1) - value = 1; /* start break */ - else - value = 0; /* clear break */ - usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - 4, /* set break */ - USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, - value, 0, NULL, 0, 2*HZ); - /* there is something funky about this.. the TCSBRK that 'cu' performs - ought to translate into a break_ctl(-1),break_ctl(0) pair HZ/4 - seconds apart, but it feels like the break sent isn't as long as it - is on /dev/ttyS0 */ -} - - -static void keyspan_pda_set_termios (struct usb_serial_port *port, - struct termios *old_termios) -{ - struct usb_serial *serial = port->serial; - unsigned int cflag = port->tty->termios->c_cflag; - - /* cflag specifies lots of stuff: number of stop bits, parity, number - of data bits, baud. What can the device actually handle?: - CSTOPB (1 stop bit or 2) - PARENB (parity) - CSIZE (5bit .. 8bit) - There is minimal hw support for parity (a PSW bit seems to hold the - parity of whatever is in the accumulator). The UART either deals - with 10 bits (start, 8 data, stop) or 11 bits (start, 8 data, - 1 special, stop). So, with firmware changes, we could do: - 8N1: 10 bit - 8N2: 11 bit, extra bit always (mark?) - 8[EOMS]1: 11 bit, extra bit is parity - 7[EOMS]1: 10 bit, b0/b7 is parity - 7[EOMS]2: 11 bit, b0/b7 is parity, extra bit always (mark?) - - HW flow control is dictated by the tty->termios->c_cflags & CRTSCTS - bit. - - For now, just do baud. */ - - switch (cflag & CBAUD) { - /* we could support more values here, just need to calculate - the necessary divisors in the firmware. - has the Bnnn constants. */ - case B110: keyspan_pda_setbaud(serial, 110); break; - case B300: keyspan_pda_setbaud(serial, 300); break; - case B1200: keyspan_pda_setbaud(serial, 1200); break; - case B2400: keyspan_pda_setbaud(serial, 2400); break; - case B4800: keyspan_pda_setbaud(serial, 4800); break; - case B9600: keyspan_pda_setbaud(serial, 9600); break; - case B19200: keyspan_pda_setbaud(serial, 19200); break; - case B38400: keyspan_pda_setbaud(serial, 38400); break; - case B57600: keyspan_pda_setbaud(serial, 57600); break; - case B115200: keyspan_pda_setbaud(serial, 115200); break; - default: dbg("can't handle requested baud rate"); break; - } -} - - -/* modem control pins: DTR and RTS are outputs and can be controlled. - DCD, RI, DSR, CTS are inputs and can be read. All outputs can also be - read. The byte passed is: DTR(b7) DCD RI DSR CTS RTS(b2) unused unused */ - -static int keyspan_pda_get_modem_info(struct usb_serial *serial, - unsigned char *value) -{ - int rc; - unsigned char data; - rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), - 3, /* get pins */ - USB_TYPE_VENDOR|USB_RECIP_INTERFACE|USB_DIR_IN, - 0, 0, &data, 1, 2*HZ); - if (rc > 0) - *value = data; - return rc; -} - - -static int keyspan_pda_set_modem_info(struct usb_serial *serial, - unsigned char value) -{ - int rc; - rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - 3, /* set pins */ - USB_TYPE_VENDOR|USB_RECIP_INTERFACE|USB_DIR_OUT, - value, 0, NULL, 0, 2*HZ); - return rc; -} - - -static int keyspan_pda_ioctl(struct usb_serial_port *port, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct usb_serial *serial = port->serial; - int rc; - unsigned int value; - unsigned char status, mask; - - switch (cmd) { - case TIOCMGET: /* get modem pins state */ - rc = keyspan_pda_get_modem_info(serial, &status); - if (rc < 0) - return rc; - value = - ((status & (1<<7)) ? TIOCM_DTR : 0) | - ((status & (1<<6)) ? TIOCM_CAR : 0) | - ((status & (1<<5)) ? TIOCM_RNG : 0) | - ((status & (1<<4)) ? TIOCM_DSR : 0) | - ((status & (1<<3)) ? TIOCM_CTS : 0) | - ((status & (1<<2)) ? TIOCM_RTS : 0); - if (copy_to_user((unsigned int *)arg, &value, sizeof(int))) - return -EFAULT; - return 0; - case TIOCMSET: /* set a state as returned by MGET */ - if (copy_from_user(&value, (unsigned int *)arg, sizeof(int))) - return -EFAULT; - status = - ((value & TIOCM_DTR) ? (1<<7) : 0) | - ((value & TIOCM_CAR) ? (1<<6) : 0) | - ((value & TIOCM_RNG) ? (1<<5) : 0) | - ((value & TIOCM_DSR) ? (1<<4) : 0) | - ((value & TIOCM_CTS) ? (1<<3) : 0) | - ((value & TIOCM_RTS) ? (1<<2) : 0); - rc = keyspan_pda_set_modem_info(serial, status); - if (rc < 0) - return rc; - return 0; - case TIOCMBIS: /* set bits in bitmask */ - case TIOCMBIC: /* clear bits from bitmask */ - if (copy_from_user(&value, (unsigned int *)arg, sizeof(int))) - return -EFAULT; - rc = keyspan_pda_get_modem_info(serial, &status); - if (rc < 0) - return rc; - mask = - ((value & TIOCM_RTS) ? (1<<2) : 0) | - ((value & TIOCM_DTR) ? (1<<7) : 0); - if (cmd == TIOCMBIS) - status |= mask; - else - status &= ~mask; - rc = keyspan_pda_set_modem_info(serial, status); - if (rc < 0) - return rc; - return 0; - case TIOCMIWAIT: - /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/ - /* TODO */ - case TIOCGICOUNT: - /* return count of modemline transitions */ - return 0; /* TODO */ - } - - return -ENOIOCTLCMD; -} - -static int keyspan_pda_write(struct usb_serial_port *port, int from_user, - const unsigned char *buf, int count) -{ - struct usb_serial *serial = port->serial; - int request_unthrottle = 0; - int rc = 0; - DECLARE_WAITQUEUE(wait, current); - - /* guess how much room is left in the device's ring buffer, and if we - want to send more than that, check first, updating our notion of - what is left. If our write will result in no room left, ask the - device to give us an interrupt when the room available rises above - a threshold, and hold off all writers (eventually, those using - select() or poll() too) until we receive that unthrottle interrupt. - Block if we can't write anything at all, otherwise write as much as - we can. */ - - if (count == 0) { - dbg(" write request of 0 bytes"); - return (0); - } - - /* we might block because of: - the TX urb is in-flight (wait until it completes) - the device is full (wait until it says there is room) - */ - while (port->write_urb->status == -EINPROGRESS) { - if (0 /* file->f_flags & O_NONBLOCK */) { - rc = -EAGAIN; - goto err; - } - interruptible_sleep_on(&serial->write_wait); - if (signal_pending(current)) { - rc = -ERESTARTSYS; - goto err; - } - } - - /* at this point the URB is in our control, nobody else can submit it - again (the only sudden transition was the one from EINPROGRESS to - finished) */ - - /* the next potential block is that our TX process might be throttled. - The transition from throttled->not happens because of an Rx - interrupt, and the wake_up occurs during the same interrupt, so we - have to be careful to avoid a race that would cause us to sleep - forever. */ - - add_wait_queue(&serial->write_wait, &wait); - set_current_state(TASK_INTERRUPTIBLE); - while (serial->tx_throttled) { - /* device can't accomodate any more characters. Sleep until it - can. Woken up by an Rx interrupt message, which clears - tx_throttled first. */ - dbg(" tx_throttled, going to sleep"); - if (signal_pending(current)) { - current->state = TASK_RUNNING; - remove_wait_queue(&serial->write_wait, &wait); - dbg(" woke up because of signal"); - rc = -ERESTARTSYS; - goto err; - } - schedule(); - dbg(" woke up"); - } - remove_wait_queue(&serial->write_wait, &wait); - set_current_state(TASK_RUNNING); - - count = (count > port->bulk_out_size) ? port->bulk_out_size : count; - if (count > serial->tx_room) { - unsigned char room; - /* Looks like we might overrun the Tx buffer. Ask the device - how much room it really has */ - rc = usb_control_msg(serial->dev, - usb_rcvctrlpipe(serial->dev, 0), - 6, /* write_room */ - USB_TYPE_VENDOR | USB_RECIP_INTERFACE - | USB_DIR_IN, - 0, /* value: 0 means "remaining room" */ - 0, /* index */ - &room, - 1, - 2*HZ); - if (rc < 0) { - dbg(" roomquery failed"); - return rc; /* failed */ - } - if (rc == 0) { - dbg(" roomquery returned 0 bytes"); - return -EIO; /* device didn't return any data */ - } - dbg(" roomquery says %d", room); - serial->tx_room = room; - if (count > serial->tx_room) { - /* we're about to completely fill the Tx buffer, so - we'll be throttled afterwards. */ - count = serial->tx_room; - request_unthrottle = 1; - } - } - serial->tx_room -= count; - - if (count) { - /* now transfer data */ - if (from_user) { - copy_from_user(port->write_urb->transfer_buffer, buf, count); - } - else { - memcpy (port->write_urb->transfer_buffer, buf, count); - } - /* send the data out the bulk port */ - port->write_urb->transfer_buffer_length = count; - - if (usb_submit_urb(port->write_urb)) - dbg(" usb_submit_urb(write bulk) failed"); - } - else { - /* There wasn't any room left, so we are throttled until - the buffer empties a bit */ - request_unthrottle = 1; - } - - if (request_unthrottle) { - dbg(" request_unthrottle"); - /* ask the device to tell us when the tx buffer becomes - sufficiently empty */ - serial->tx_throttled = 1; /* block writers */ - rc = usb_control_msg(serial->dev, - usb_sndctrlpipe(serial->dev, 0), - 7, /* request_unthrottle */ - USB_TYPE_VENDOR | USB_RECIP_INTERFACE - | USB_DIR_OUT, - 16, /* value: threshold */ - 0, /* index */ - NULL, - 0, - 2*HZ); - } - - return (count); - err: - return (rc); -} - - -static void keyspan_pda_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; - - if (port_paranoia_check (port, "keyspan_pda_rx_interrupt")) { - return; - } - - serial = port->serial; - if (serial_paranoia_check (serial, "keyspan_pda_rx_interrupt")) { - return; - } - - wake_up_interruptible(&serial->write_wait); - - tty = port->tty; - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); - - wake_up_interruptible(&tty->write_wait); -} - - -static int keyspan_pda_write_room (struct usb_serial_port *port) -{ - struct usb_serial *serial = port->serial; - - /* used by n_tty.c for processing of tabs and such. Giving it our - conservative guess is probably good enough, but needs testing by - running a console through the device. */ - - return (serial->tx_room); -} - - -static int keyspan_pda_chars_in_buffer (struct usb_serial_port *port) -{ - struct usb_serial *serial = port->serial; - - /* when throttled, return at least WAKEUP_CHARS to tell select() (via - n_tty.c:normal_poll() ) that we're not writeable. */ - if (serial->tx_throttled) - return 256; - return 0; -} - - -static int keyspan_pda_open (struct usb_serial_port *port, struct file *filp) -{ - struct usb_serial *serial = port->serial; - unsigned char room; - int rc; - - if (port->active) { - return -EINVAL; - } - port->active = 1; - - /* find out how much room is in the Tx ring */ - rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), - 6, /* write_room */ - USB_TYPE_VENDOR | USB_RECIP_INTERFACE - | USB_DIR_IN, - 0, /* value */ - 0, /* index */ - &room, - 1, - 2*HZ); - if (rc < 0) { - dbg(" roomquery failed"); - return rc; /* failed */ - } - if (rc == 0) { - dbg(" roomquery returned 0 bytes"); - return -EIO; /* device didn't return any data */ - } - serial->tx_room = room; - serial->tx_throttled = room ? 0 : 1; - - /* the normal serial device seems to always turn on DTR and RTS here, - so do the same */ - if (port->tty->termios->c_cflag & CBAUD) - keyspan_pda_set_modem_info(serial, (1<<7) | (1<<2) ); - else - keyspan_pda_set_modem_info(serial, 0); - - /*Start reading from the device*/ - if (usb_submit_urb(port->read_urb)) - dbg(" usb_submit_urb(read int) failed"); - - return (0); -} - - -static void keyspan_pda_close(struct usb_serial_port *port, struct file *filp) -{ - struct usb_serial *serial = port->serial; - - /* the normal serial device seems to always shut off DTR and RTS now */ - if (port->tty->termios->c_cflag & HUPCL) - keyspan_pda_set_modem_info(serial, 0); - - /* shutdown our bulk reads and writes */ - usb_unlink_urb (port->write_urb); - usb_unlink_urb (port->read_urb); - port->active = 0; -} - - -/* download the firmware to a "fake" device (pre-renumeration) */ -static int keyspan_pda_fake_startup (struct usb_serial *serial) -{ - int response; - const struct ezusb_hex_record *record; - - /* download the firmware here ... */ - response = ezusb_set_reset(serial, 1); - - record = &keyspan_pda_firmware[0]; - while(record->address != 0xffff) { - response = ezusb_writememory(serial, record->address, - (unsigned char *)record->data, - record->data_size, 0xa0); - if (response < 0) { - err("ezusb_writememory failed for Keyspan PDA " - "firmware (%d %04X %p %d)", - response, - record->address, record->data, record->data_size); - break; - } - record++; - } - /* bring device out of reset. Renumeration will occur in a moment - and the new device will bind to the real driver */ - response = ezusb_set_reset(serial, 0); - - /* we want this device to fail to have a driver assigned to it. */ - return (1); -} - - -/* do some startup allocations not currently performed by usb_serial_probe() */ -static int keyspan_pda_startup (struct usb_serial *serial) -{ - struct usb_endpoint_descriptor *intin; - intin = serial->port[0].interrupt_in_endpoint; - - /* set up the receive interrupt urb */ - FILL_INT_URB(serial->port[0].read_urb, serial->dev, - usb_rcvintpipe(serial->dev, intin->bEndpointAddress), - serial->port[0].interrupt_in_buffer, - intin->wMaxPacketSize, - keyspan_pda_rx_interrupt, - serial, - intin->bInterval); - - init_waitqueue_head(&serial->write_wait); - - return (0); -} - -#endif /* CONFIG_USB_SERIAL_KEYSPAN_PDA */ - - -/***************************************************************************** - * generic devices specific driver functions - *****************************************************************************/ -static int generic_open (struct usb_serial_port *port, struct file *filp) -{ - struct usb_serial *serial = port->serial; - - dbg("generic_open port %d", port->number); - - if (port->active) { - dbg ("device already open"); - return -EINVAL; - } - port->active = 1; - - /* if we have a bulk interrupt, start reading from it */ - if (serial->num_bulk_in) { - /*Start reading from the device*/ - if (usb_submit_urb(port->read_urb)) - dbg("usb_submit_urb(read bulk) failed"); - } - - return (0); -} - - -static void generic_close (struct usb_serial_port *port, struct file * filp) -{ - struct usb_serial *serial = port->serial; - - dbg("generic_close port %d", port->number); - - /* shutdown any bulk reads that might be going on */ - if (serial->num_bulk_out) { - usb_unlink_urb (port->write_urb); - } - if (serial->num_bulk_in) { - usb_unlink_urb (port->read_urb); - } - - port->active = 0; -} - - -static int generic_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) -{ - struct usb_serial *serial = port->serial; - - dbg("generic_serial_write port %d", port->number); - - if (count == 0) { - dbg("write request of 0 bytes"); - return (0); - } - - /* only do something if we have a bulk out endpoint */ - if (serial->num_bulk_out) { - if (port->write_urb->status == -EINPROGRESS) { - dbg ("already writing"); - return (0); - } - - count = (count > port->bulk_out_size) ? port->bulk_out_size : count; - - if (from_user) { - copy_from_user(port->write_urb->transfer_buffer, buf, count); - } - else { - memcpy (port->write_urb->transfer_buffer, buf, count); - } - - /* send the data out the bulk port */ - port->write_urb->transfer_buffer_length = count; - - if (usb_submit_urb(port->write_urb)) - dbg("usb_submit_urb(write bulk) failed"); - - return (count); - } - - /* no bulk out, so return 0 bytes written */ - return (0); -} - - -static int generic_write_room (struct usb_serial_port *port) -{ - struct usb_serial *serial = port->serial; - int room; - - dbg("generic_write_room port %d", port->number); - - if (serial->num_bulk_out) { - if (port->write_urb->status == -EINPROGRESS) - room = 0; - else - room = port->bulk_out_size; - dbg("generic_write_room returns %d", room); - return (room); - } - - return (0); -} - - -static int generic_chars_in_buffer (struct usb_serial_port *port) -{ - struct usb_serial *serial = port->serial; - - dbg("generic_chars_in_buffer port %d", port->number); - - if (serial->num_bulk_out) { - if (port->write_urb->status == -EINPROGRESS) { - return (port->bulk_out_size); - } - } - - return (0); -} - - -static void generic_read_bulk_callback (struct urb *urb) -{ - struct usb_serial_port *port = (struct usb_serial_port *)urb->context; - struct usb_serial *serial; - struct tty_struct *tty; - unsigned char *data = urb->transfer_buffer; - int i; - - dbg("generic_read_bulk_callback"); - - if (port_paranoia_check (port, "generic_read_bulk_callback")) { - return; - } - - serial = port->serial; - if (serial_paranoia_check (serial, "generic_read_bulk_callback")) { - return; - } - - if (urb->status) { - dbg("nonzero read bulk status received: %d", urb->status); - return; - } - -#ifdef DEBUG - if (urb->actual_length) { - printk (KERN_DEBUG __FILE__ ": data read - length = %d, data = ", urb->actual_length); - for (i = 0; i < urb->actual_length; ++i) { - printk ("%.2x ", data[i]); - } - printk ("\n"); - } -#endif - - tty = port->tty; - if (urb->actual_length) { - for (i = 0; i < urb->actual_length ; ++i) { - tty_insert_flip_char(tty, data[i], 0); - } - tty_flip_buffer_push(tty); - } - - /* Continue trying to always read */ - if (usb_submit_urb(urb)) - dbg("failed resubmitting read urb"); - - return; -} - - -static void generic_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; - - dbg("generic_write_bulk_callback"); - - if (port_paranoia_check (port, "generic_write_bulk_callback")) { - return; - } - - serial = port->serial; - if (serial_paranoia_check (serial, "generic_write_bulk_callback")) { - return; - } - - if (urb->status) { - dbg("nonzero write bulk status received: %d", urb->status); - return; - } - - tty = port->tty; - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); - - wake_up_interruptible(&tty->write_wait); - - return; -} - - -static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum) -{ - struct usb_serial *serial = NULL; - struct usb_serial_port *port; - struct usb_interface_descriptor *interface; - struct usb_endpoint_descriptor *endpoint; - struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS]; - struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS]; - struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS]; - struct usb_serial_device_type *type; - int device_num; - int minor; - int buffer_size; - int i; - char interrupt_pipe; - char bulk_in_pipe; - char bulk_out_pipe; - int num_interrupt_in = 0; - int num_bulk_in = 0; - int num_bulk_out = 0; - int num_ports; - - /* loop through our list of known serial converters, and see if this device matches */ - device_num = 0; - while (usb_serial_devices[device_num] != NULL) { - type = usb_serial_devices[device_num]; - dbg ("Looking at %s Vendor id=%.4x Product id=%.4x", type->name, *(type->idVendor), *(type->idProduct)); - - /* look at the device descriptor */ - if ((dev->descriptor.idVendor == *(type->idVendor)) && - (dev->descriptor.idProduct == *(type->idProduct))) { - - dbg("descriptor matches...looking at the endpoints"); - - /* descriptor matches, let's try to find the endpoints needed */ - interrupt_pipe = bulk_in_pipe = bulk_out_pipe = HAS_NOT; - - /* check out the endpoints */ - interface = &dev->actconfig->interface[ifnum].altsetting[0]; - for (i = 0; i < interface->bNumEndpoints; ++i) { - endpoint = &interface->endpoint[i]; - - if ((endpoint->bEndpointAddress & 0x80) && - ((endpoint->bmAttributes & 3) == 0x02)) { - /* we found a bulk in endpoint */ - dbg("found bulk in"); - bulk_in_pipe = HAS; - bulk_in_endpoint[num_bulk_in] = endpoint; - ++num_bulk_in; - } - - if (((endpoint->bEndpointAddress & 0x80) == 0x00) && - ((endpoint->bmAttributes & 3) == 0x02)) { - /* we found a bulk out endpoint */ - dbg("found bulk out"); - bulk_out_pipe = HAS; - bulk_out_endpoint[num_bulk_out] = endpoint; - ++num_bulk_out; - } - - if ((endpoint->bEndpointAddress & 0x80) && - ((endpoint->bmAttributes & 3) == 0x03)) { - /* we found a interrupt in endpoint */ - dbg("found interrupt in"); - interrupt_pipe = HAS; - interrupt_in_endpoint[num_interrupt_in] = endpoint; - ++num_interrupt_in; - } - - } - - /* verify that we found all of the endpoints that we need */ - if ((interrupt_pipe & type->needs_interrupt_in) && - (bulk_in_pipe & type->needs_bulk_in) && - (bulk_out_pipe & type->needs_bulk_out)) { - /* found all that we need */ - info("%s converter detected", type->name); - -#ifdef CONFIG_USB_SERIAL_GENERIC - if (type == &generic_device) - num_ports = num_bulk_out; - else -#endif - num_ports = type->num_ports; - - serial = get_free_serial (num_ports, &minor); - if (serial == NULL) { - err("No more free serial devices"); - return NULL; - } - - serial->dev = dev; - serial->type = type; - serial->minor = minor; - serial->num_ports = num_ports; - serial->num_bulk_in = num_bulk_in; - serial->num_bulk_out = num_bulk_out; - serial->num_interrupt_in = num_interrupt_in; - - /* collect interrupt_in endpoints now, because - the keyspan_pda startup function needs - to know about them */ - for (i = 0; i < num_interrupt_in; ++i) { - port = &serial->port[i]; - buffer_size = interrupt_in_endpoint[i]->wMaxPacketSize; - port->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL); - if (!port->interrupt_in_buffer) { - err("Couldn't allocate interrupt_in_buffer"); - goto probe_error; - } - port->interrupt_in_endpoint = interrupt_in_endpoint[i]; - } - - /* if this device type has a startup function, call it */ - if (type->startup) { - if (type->startup (serial)) { - return_serial (serial); - return NULL; - } - } - - /* set up the endpoint information */ - for (i = 0; i < num_bulk_in; ++i) { - port = &serial->port[i]; - port->read_urb = usb_alloc_urb (0); - if (!port->read_urb) { - err("No free urbs available"); - goto probe_error; - } - buffer_size = bulk_in_endpoint[i]->wMaxPacketSize; - port->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL); - if (!port->bulk_in_buffer) { - err("Couldn't allocate bulk_in_buffer"); - goto probe_error; - } - if (serial->type->read_bulk_callback) { - FILL_BULK_URB(port->read_urb, dev, usb_rcvbulkpipe (dev, bulk_in_endpoint[i]->bEndpointAddress), - port->bulk_in_buffer, buffer_size, serial->type->read_bulk_callback, port); - } else { - FILL_BULK_URB(port->read_urb, dev, usb_rcvbulkpipe (dev, bulk_in_endpoint[i]->bEndpointAddress), - port->bulk_in_buffer, buffer_size, generic_read_bulk_callback, port); - } - } - - for (i = 0; i < num_bulk_out; ++i) { - port = &serial->port[i]; - port->write_urb = usb_alloc_urb(0); - if (!port->write_urb) { - err("No free urbs available"); - goto probe_error; - } - port->bulk_out_size = bulk_out_endpoint[i]->wMaxPacketSize; - port->bulk_out_buffer = kmalloc (port->bulk_out_size, GFP_KERNEL); - if (!port->bulk_out_buffer) { - err("Couldn't allocate bulk_out_buffer"); - goto probe_error; - } - if (serial->type->write_bulk_callback) { - FILL_BULK_URB(port->write_urb, dev, usb_sndbulkpipe (dev, bulk_out_endpoint[i]->bEndpointAddress), - port->bulk_out_buffer, port->bulk_out_size, serial->type->write_bulk_callback, port); - } else { - FILL_BULK_URB(port->write_urb, dev, usb_sndbulkpipe (dev, bulk_out_endpoint[i]->bEndpointAddress), - port->bulk_out_buffer, port->bulk_out_size, generic_write_bulk_callback, port); - } - } - -#if 0 /* use this code when WhiteHEAT is up and running */ - for (i = 0; i < num_interrupt_in; ++i) { - port = &serial->port[i]; - port->control_urb = usb_alloc_urb(0); - if (!port->control_urb) { - err("No free urbs available"); - goto probe_error; - } - buffer_size = interrupt_in_endpoint[i]->wMaxPacketSize; - port->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL); - if (!port->interrupt_in_buffer) { - err("Couldn't allocate interrupt_in_buffer"); - goto probe_error; - } - FILL_INT_URB(port->control_urb, dev, usb_rcvintpipe (dev, interrupt_in_endpoint[i]->bEndpointAddress), - port->interrupt_in_buffer, buffer_size, serial_control_irq, - port, interrupt_in_endpoint[i]->bInterval); - } -#endif - - for (i = 0; i < serial->num_ports; ++i) { - info("%s converter now attached to ttyUSB%d", type->name, serial->minor + i); - } - - MOD_INC_USE_COUNT; - - return serial; - } else { - info("descriptors matched, but endpoints did not"); - } - } - - /* look at the next type in our list */ - ++device_num; - } - -probe_error: - if (serial) { - for (i = 0; i < num_bulk_in; ++i) { - port = &serial->port[i]; - if (port->read_urb) - usb_free_urb (port->read_urb); - if (serial->port[i].bulk_in_buffer[i]) - kfree (serial->port[i].bulk_in_buffer); - } - for (i = 0; i < num_bulk_out; ++i) { - port = &serial->port[i]; - if (port->write_urb) - usb_free_urb (port->write_urb); - if (serial->port[i].bulk_out_buffer) - kfree (serial->port[i].bulk_out_buffer); - } - for (i = 0; i < num_interrupt_in; ++i) { - port = &serial->port[i]; - if (port->control_urb) - usb_free_urb (port->control_urb); - if (serial->port[i].interrupt_in_buffer) - kfree (serial->port[i].interrupt_in_buffer); - } - - /* return the minor range that this device had */ - return_serial (serial); - - /* free up any memory that we allocated */ - kfree (serial); - } - return NULL; -} - - -static void usb_serial_disconnect(struct usb_device *dev, void *ptr) -{ - struct usb_serial *serial = (struct usb_serial *) ptr; - struct usb_serial_port *port; - int i; - - if (serial) { - for (i = 0; i < serial->num_ports; ++i) - serial->port[i].active = 0; - - for (i = 0; i < serial->num_bulk_in; ++i) { - port = &serial->port[i]; - if (port->read_urb) { - usb_unlink_urb (port->read_urb); - usb_free_urb (port->read_urb); - } - if (port->bulk_in_buffer) - kfree (port->bulk_in_buffer); - } - for (i = 0; i < serial->num_bulk_out; ++i) { - port = &serial->port[i]; - if (port->write_urb) { - usb_unlink_urb (port->write_urb); - usb_free_urb (port->write_urb); - } - if (port->bulk_out_buffer) - kfree (port->bulk_out_buffer); - } - for (i = 0; i < serial->num_interrupt_in; ++i) { - port = &serial->port[i]; - if (port->control_urb) { - usb_unlink_urb (port->control_urb); - usb_free_urb (port->control_urb); - } - if (port->interrupt_in_buffer) - kfree (port->interrupt_in_buffer); - } - - for (i = 0; i < serial->num_ports; ++i) { - info("%s converter now disconnected from ttyUSB%d", serial->type->name, serial->minor + i); - } - - /* return the minor range that this device had */ - return_serial (serial); - - /* free up any memory that we allocated */ - kfree (serial); - - } else { - info("device disconnected"); - } - - MOD_DEC_USE_COUNT; -} - - -static struct tty_driver serial_tty_driver = { - magic: TTY_DRIVER_MAGIC, - driver_name: "usb", - name: "ttyUSB%d", - major: SERIAL_TTY_MAJOR, - minor_start: 0, - num: SERIAL_TTY_MINORS, - type: TTY_DRIVER_TYPE_SERIAL, - subtype: SERIAL_TYPE_NORMAL, - flags: TTY_DRIVER_REAL_RAW, - refcount: &serial_refcount, - table: serial_tty, - proc_entry: NULL, - other: NULL, - termios: serial_termios, - termios_locked: serial_termios_locked, - - open: serial_open, - close: serial_close, - write: serial_write, - put_char: NULL, - flush_chars: NULL, - write_room: serial_write_room, - ioctl: serial_ioctl, - set_termios: serial_set_termios, - set_ldisc: NULL, - throttle: serial_throttle, - unthrottle: serial_unthrottle, - stop: NULL, - start: NULL, - hangup: NULL, - break_ctl: serial_break, - wait_until_sent: NULL, - send_xchar: NULL, - read_proc: NULL, - chars_in_buffer: serial_chars_in_buffer, - flush_buffer: NULL -}; - - -int usb_serial_init(void) -{ - int i; - - /* Initalize our global data */ - for (i = 0; i < SERIAL_TTY_MINORS; ++i) { - serial_table[i] = NULL; - } - - /* register the tty driver */ - serial_tty_driver.init_termios = tty_std_termios; - serial_tty_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; - if (tty_register_driver (&serial_tty_driver)) { - err("failed to register tty driver"); - return -EPERM; - } - - /* register the USB driver */ - if (usb_register(&usb_serial_driver) < 0) { - tty_unregister_driver(&serial_tty_driver); - return -1; - } - - info("support registered"); - return 0; -} - - -void usb_serial_exit(void) -{ - tty_unregister_driver(&serial_tty_driver); - usb_deregister(&usb_serial_driver); -} - - -module_init(usb_serial_init); -module_exit(usb_serial_exit); - - diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/serial/usb-serial.h linux/drivers/usb/serial/usb-serial.h --- v2.3.99-pre3/linux/drivers/usb/serial/usb-serial.h Mon Mar 27 08:08:28 2000 +++ linux/drivers/usb/serial/usb-serial.h Wed Apr 5 16:58:38 2000 @@ -19,47 +19,22 @@ #include -/* Module information */ -MODULE_AUTHOR("Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux-usb/"); -MODULE_DESCRIPTION("USB Serial Driver"); - -#ifdef CONFIG_USB_SERIAL_GENERIC -static __u16 vendor = 0x05f9; -static __u16 product = 0xffff; -MODULE_PARM(vendor, "i"); -MODULE_PARM_DESC(vendor, "User specified USB idVendor"); - -MODULE_PARM(product, "i"); -MODULE_PARM_DESC(product, "User specified USB idProduct"); -#endif - - -/* USB Serial devices vendor ids and device ids that this driver supports */ -#define CONNECT_TECH_VENDOR_ID 0x0710 -#define CONNECT_TECH_FAKE_WHITE_HEAT_ID 0x0001 -#define CONNECT_TECH_WHITE_HEAT_ID 0x8001 -#define HANDSPRING_VENDOR_ID 0x082d -#define HANDSPRING_VISOR_ID 0x0100 -#define FTDI_VENDOR_ID 0x0403 -#define FTDI_SIO_SERIAL_CONVERTER_ID 0x8372 -#define KEYSPAN_VENDOR_ID 0x06cd -#define KEYSPAN_PDA_FAKE_ID 0x0103 -#define KEYSPAN_PDA_ID 0x0104 /* no clue */ - #define SERIAL_TTY_MAJOR 188 /* Nice legal number now */ #define SERIAL_TTY_MINORS 16 /* Actually we are allowed 255, but this is good for now */ - -#define MAX_NUM_PORTS 8 /* The maximum number of ports one device can grab at once */ +#define MAX_NUM_PORTS 8 /* The maximum number of ports one device can grab at once */ #define USB_SERIAL_MAGIC 0x6702 /* magic number for usb_serial struct */ #define USB_SERIAL_PORT_MAGIC 0x7301 /* magic number for usb_serial_port struct */ +/* parity check flag */ +#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) + struct usb_serial_port { int magic; struct usb_serial *serial; /* pointer back to the owner of this port */ - struct tty_struct * tty; /* the coresponding tty for this device */ + struct tty_struct * tty; /* the coresponding tty for this port */ unsigned char minor; unsigned char number; char active; /* someone has this device open */ @@ -81,8 +56,9 @@ struct usb_serial { int magic; struct usb_device * dev; - struct usb_serial_device_type * type; - unsigned char minor; + struct usb_serial_device_type * type; /* the type of usb serial device this is */ + struct tty_driver * tty_driver; /* the tty_driver for this device */ + unsigned char minor; /* the starting minor number for this device */ unsigned char num_ports; /* the number of ports this device has */ char num_interrupt_in; /* number of interrupt in endpoints we have */ char num_bulk_in; /* number of bulk in endpoints we have */ @@ -141,299 +117,67 @@ }; -/* 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. */ -static int generic_open (struct usb_serial_port *port, struct file *filp); -static void generic_close (struct usb_serial_port *port, struct file *filp); -static int generic_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); -static int generic_write_room (struct usb_serial_port *port); -static int generic_chars_in_buffer (struct usb_serial_port *port); -static void generic_read_bulk_callback (struct urb *urb); -static void generic_write_bulk_callback (struct urb *urb); - - -#ifdef CONFIG_USB_SERIAL_GENERIC -/* All of the device info needed for the Generic Serial Converter */ -static struct usb_serial_device_type generic_device = { - name: "Generic", - idVendor: &vendor, /* use the user specified vendor id */ - idProduct: &product, /* use the user specified product id */ - needs_interrupt_in: DONT_CARE, /* don't have to have an interrupt in endpoint */ - needs_bulk_in: DONT_CARE, /* don't have to have a bulk in endpoint */ - needs_bulk_out: DONT_CARE, /* don't have to have a bulk out endpoint */ - num_interrupt_in: NUM_DONT_CARE, - num_bulk_in: NUM_DONT_CARE, - num_bulk_out: NUM_DONT_CARE, - num_ports: 1, -}; -#endif - - -#ifdef CONFIG_USB_SERIAL_WHITEHEAT -/* function prototypes for the Connect Tech WhiteHEAT serial converter */ -static int whiteheat_open (struct usb_serial_port *port, struct file *filp); -static void whiteheat_close (struct usb_serial_port *port, struct file *filp); -static void whiteheat_set_termios (struct usb_serial_port *port, struct termios * old); -static void whiteheat_throttle (struct usb_serial_port *port); -static void whiteheat_unthrottle (struct usb_serial_port *port); -static int whiteheat_startup (struct usb_serial *serial); - -/* All of the device info needed for the Connect Tech WhiteHEAT */ -static __u16 connecttech_vendor_id = CONNECT_TECH_VENDOR_ID; -static __u16 connecttech_whiteheat_fake_product_id = CONNECT_TECH_FAKE_WHITE_HEAT_ID; -static __u16 connecttech_whiteheat_product_id = CONNECT_TECH_WHITE_HEAT_ID; -static struct usb_serial_device_type whiteheat_fake_device = { - name: "Connect Tech - WhiteHEAT - (prerenumeration)", - idVendor: &connecttech_vendor_id, /* the Connect Tech vendor id */ - idProduct: &connecttech_whiteheat_fake_product_id, /* the White Heat initial product id */ - needs_interrupt_in: DONT_CARE, /* don't have to have an interrupt in endpoint */ - needs_bulk_in: DONT_CARE, /* don't have to have a bulk in endpoint */ - needs_bulk_out: DONT_CARE, /* don't have to have a bulk out endpoint */ - num_interrupt_in: NUM_DONT_CARE, - num_bulk_in: NUM_DONT_CARE, - num_bulk_out: NUM_DONT_CARE, - num_ports: 1, - startup: whiteheat_startup -}; -static struct usb_serial_device_type whiteheat_device = { - name: "Connect Tech - WhiteHEAT", - idVendor: &connecttech_vendor_id, /* the Connect Tech vendor id */ - idProduct: &connecttech_whiteheat_product_id, /* the White Heat real product id */ - needs_interrupt_in: DONT_CARE, /* don't have to have an interrupt in endpoint */ - needs_bulk_in: DONT_CARE, /* don't have to have a bulk in endpoint */ - needs_bulk_out: DONT_CARE, /* don't have to have a bulk out endpoint */ - num_interrupt_in: NUM_DONT_CARE, - num_bulk_in: NUM_DONT_CARE, - num_bulk_out: NUM_DONT_CARE, - num_ports: 4, - open: whiteheat_open, - close: whiteheat_close, - throttle: whiteheat_throttle, - unthrottle: whiteheat_unthrottle, - set_termios: whiteheat_set_termios, -}; -#endif - - -#ifdef CONFIG_USB_SERIAL_VISOR - -/**************************************************************************** - * Handspring Visor Vendor specific request codes (bRequest values) - * A big thank you to Handspring for providing the following information. - * If anyone wants the original file where these values and structures came - * from, send email to . - ****************************************************************************/ - -/**************************************************************************** - * VISOR_REQUEST_BYTES_AVAILABLE asks the visor for the number of bytes that - * are available to be transfered to the host for the specified endpoint. - * Currently this is not used, and always returns 0x0001 - ****************************************************************************/ -#define VISOR_REQUEST_BYTES_AVAILABLE 0x01 - -/**************************************************************************** - * VISOR_CLOSE_NOTIFICATION is set to the device to notify it that the host - * is now closing the pipe. An empty packet is sent in response. - ****************************************************************************/ -#define VISOR_CLOSE_NOTIFICATION 0x02 - -/**************************************************************************** - * VISOR_GET_CONNECTION_INFORMATION is sent by the host during enumeration to - * get the endpoints used by the connection. - ****************************************************************************/ -#define VISOR_GET_CONNECTION_INFORMATION 0x03 - - -/**************************************************************************** - * VISOR_GET_CONNECTION_INFORMATION returns data in the following format - ****************************************************************************/ -struct visor_connection_info { - __u16 num_ports; - struct { - __u8 port_function_id; - __u8 port; - } connections[2]; -}; - - -/* struct visor_connection_info.connection[x].port defines: */ -#define VISOR_ENDPOINT_1 0x01 -#define VISOR_ENDPOINT_2 0x02 - -/* struct visor_connection_info.connection[x].port_function_id defines: */ -#define VISOR_FUNCTION_GENERIC 0x00 -#define VISOR_FUNCTION_DEBUGGER 0x01 -#define VISOR_FUNCTION_HOTSYNC 0x02 -#define VISOR_FUNCTION_CONSOLE 0x03 -#define VISOR_FUNCTION_REMOTE_FILE_SYS 0x04 - - -/* function prototypes for a handspring visor */ -static int visor_open (struct usb_serial_port *port, struct file *filp); -static void visor_close (struct usb_serial_port *port, struct file *filp); -static void visor_throttle (struct usb_serial_port *port); -static void visor_unthrottle (struct usb_serial_port *port); -static int visor_startup (struct usb_serial *serial); - -/* All of the device info needed for the Handspring Visor */ -static __u16 handspring_vendor_id = HANDSPRING_VENDOR_ID; -static __u16 handspring_product_id = HANDSPRING_VISOR_ID; -static struct usb_serial_device_type handspring_device = { - name: "Handspring Visor", - idVendor: &handspring_vendor_id, /* the Handspring vendor ID */ - idProduct: &handspring_product_id, /* the Handspring Visor product id */ - 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, -}; -#endif - - -#ifdef CONFIG_USB_SERIAL_FTDI_SIO -/* function prototypes for a FTDI serial converter */ -static int ftdi_sio_open (struct usb_serial_port *port, struct file *filp); -static void ftdi_sio_close (struct usb_serial_port *port, struct file *filp); -static int ftdi_sio_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); -static void ftdi_sio_read_bulk_callback (struct urb *urb); -static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios * old); -static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); - -/* All of the device info needed for the FTDI SIO serial converter */ -static __u16 ftdi_vendor_id = FTDI_VENDOR_ID; -static __u16 ftdi_sio_product_id = FTDI_SIO_SERIAL_CONVERTER_ID; -static struct usb_serial_device_type ftdi_sio_device = { - name: "FTDI SIO", - idVendor: &ftdi_vendor_id, /* the FTDI vendor ID */ - idProduct: &ftdi_sio_product_id, /* the FTDI SIO product id */ - 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: ftdi_sio_open, - close: ftdi_sio_close, - write: ftdi_sio_write, - ioctl: ftdi_sio_ioctl, - read_bulk_callback: ftdi_sio_read_bulk_callback, - set_termios: ftdi_sio_set_termios -}; -#endif - -#ifdef CONFIG_USB_SERIAL_KEYSPAN_PDA -/* function prototypes for a Keyspan PDA serial converter */ -static int keyspan_pda_open (struct usb_serial_port *port, - struct file *filp); -static void keyspan_pda_close (struct usb_serial_port *port, - struct file *filp); -static int keyspan_pda_startup (struct usb_serial *serial); -static void keyspan_pda_rx_throttle (struct usb_serial_port *port); -static void keyspan_pda_rx_unthrottle (struct usb_serial_port *port); -static int keyspan_pda_setbaud (struct usb_serial *serial, int baud); -static int keyspan_pda_write_room (struct usb_serial_port *port); -static int keyspan_pda_write (struct usb_serial_port *port, - int from_user, - const unsigned char *buf, - int count); -static void keyspan_pda_write_bulk_callback (struct urb *urb); -static int keyspan_pda_chars_in_buffer (struct usb_serial_port *port); -static int keyspan_pda_ioctl (struct usb_serial_port *port, - struct file *file, - unsigned int cmd, - unsigned long arg); -static void keyspan_pda_set_termios (struct usb_serial_port *port, - struct termios *old); -static void keyspan_pda_break_ctl (struct usb_serial_port *port, - int break_state); -static int keyspan_pda_fake_startup (struct usb_serial *serial); - -/* All of the device info needed for the Keyspan PDA serial converter */ -static __u16 keyspan_vendor_id = KEYSPAN_VENDOR_ID; -static __u16 keyspan_pda_fake_product_id = KEYSPAN_PDA_FAKE_ID; -static __u16 keyspan_pda_product_id = KEYSPAN_PDA_ID; -static struct usb_serial_device_type keyspan_pda_fake_device = { - name: "Keyspan PDA - (prerenumeration)", - idVendor: &keyspan_vendor_id, /* the Keyspan PDA vendor ID */ - idProduct: &keyspan_pda_fake_product_id, /* the Keyspan PDA initial product id */ - needs_interrupt_in: DONT_CARE, /* don't have to have an interrupt in endpoint */ - needs_bulk_in: DONT_CARE, /* don't have to have a bulk in endpoint */ - needs_bulk_out: DONT_CARE, /* don't have to have a bulk out endpoint */ - 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 -}; -static struct usb_serial_device_type keyspan_pda_device = { - name: "Keyspan PDA", - idVendor: &keyspan_vendor_id, /* the Keyspan PDA vendor ID */ - idProduct: &keyspan_pda_product_id, /* the Keyspan PDA product id */ - needs_interrupt_in: MUST_HAVE, - needs_bulk_in: DONT_CARE, - needs_bulk_out: MUST_HAVE, - num_interrupt_in: 1, - num_bulk_in: 0, - num_bulk_out: 1, - num_ports: 1, - open: keyspan_pda_open, - close: keyspan_pda_close, - write: keyspan_pda_write, - write_room: keyspan_pda_write_room, - write_bulk_callback: keyspan_pda_write_bulk_callback, - chars_in_buffer: keyspan_pda_chars_in_buffer, - throttle: keyspan_pda_rx_throttle, - unthrottle: keyspan_pda_rx_unthrottle, - startup: keyspan_pda_startup, - ioctl: keyspan_pda_ioctl, - set_termios: keyspan_pda_set_termios, - break_ctl: keyspan_pda_break_ctl, -}; -#endif - - -/* To add support for another serial converter, create a usb_serial_device_type - structure for that device, and add it to this list, making sure that the - last entry is NULL. */ -static struct usb_serial_device_type *usb_serial_devices[] = { -#ifdef CONFIG_USB_SERIAL_GENERIC - &generic_device, -#endif -#ifdef CONFIG_USB_SERIAL_WHITEHEAT - &whiteheat_fake_device, - &whiteheat_device, -#endif -#ifdef CONFIG_USB_SERIAL_VISOR - &handspring_device, -#endif -#ifdef CONFIG_USB_SERIAL_FTDI_SIO - &ftdi_sio_device, -#endif -#ifdef CONFIG_USB_SERIAL_KEYSPAN_PDA - &keyspan_pda_fake_device, - &keyspan_pda_device, -#endif - NULL -}; +extern struct usb_serial_device_type handspring_device; +extern struct usb_serial_device_type whiteheat_fake_device; +extern struct usb_serial_device_type whiteheat_device; +extern struct usb_serial_device_type ftdi_sio_device; +extern struct usb_serial_device_type keyspan_pda_fake_device; +extern struct usb_serial_device_type keyspan_pda_device; /* determine if we should include the EzUSB loader functions */ #if defined(CONFIG_USB_SERIAL_KEYSPAN_PDA) || defined(CONFIG_USB_SERIAL_WHITEHEAT) #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 #endif + + +/* Inline functions to check the sanity of a pointer that is passed to us */ +static inline int serial_paranoia_check (struct usb_serial *serial, const char *function) +{ + if (!serial) { + dbg("%s - serial == NULL", function); + return -1; + } + if (serial->magic != USB_SERIAL_MAGIC) { + dbg("%s - bad magic number for serial", function); + return -1; + } + if (!serial->type) { + dbg("%s - serial->type == NULL!", function); + return -1; + } + + return 0; +} + + +static inline int port_paranoia_check (struct usb_serial_port *port, const char *function) +{ + if (!port) { + dbg("%s - port == NULL", function); + return -1; + } + if (port->magic != USB_SERIAL_PORT_MAGIC) { + dbg("%s - bad magic number for port", function); + return -1; + } + if (!port->serial) { + dbg("%s - port->serial == NULL", function); + return -1; + } + if (!port->tty) { + dbg("%s - port->tty == NULL", function); + return -1; + } + + return 0; +} + #endif /* ifdef __LINUX_USB_SERIAL_H */ diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/serial/usbserial.c linux/drivers/usb/serial/usbserial.c --- v2.3.99-pre3/linux/drivers/usb/serial/usbserial.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/serial/usbserial.c Wed Apr 5 16:58:38 2000 @@ -0,0 +1,1323 @@ +/* + * USB Serial Converter driver + * + * (C) Copyright (C) 1999, 2000 + * Greg Kroah-Hartman (greg@kroah.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 driver was originally based on the ACM driver by Armin Fuerst (which was + * based on a driver by Brad Keryan) + * + * See Documentation/usb/usb-serial.txt for more information on using this driver + * + * (04/03/2000) gkh + * Changed the probe process to remove the module unload races. + * Changed where the tty layer gets initialized to have devfs work nicer. + * Added initial devfs support. + * + * (03/26/2000) gkh + * Split driver up into device specific pieces. + * + * (03/19/2000) gkh + * Fixed oops that could happen when device was removed while a program + * was talking to the device. + * Removed the static urbs and now all urbs are created and destroyed + * dynamically. + * Reworked the internal interface. Now everything is based on the + * usb_serial_port structure instead of the larger usb_serial structure. + * This fixes the bug that a multiport device could not have more than + * one port open at one time. + * + * (03/17/2000) gkh + * Added config option for debugging messages. + * Added patch for keyspan pda from Brian Warner. + * + * (03/06/2000) gkh + * Added the keyspan pda code from Brian Warner + * Moved a bunch of the port specific stuff into its own structure. This + * is in anticipation of the true multiport devices (there's a bug if you + * try to access more than one port of any multiport device right now) + * + * (02/21/2000) gkh + * Made it so that any serial devices only have to specify which functions + * they want to overload from the generic function calls (great, + * inheritance in C, in a driver, just what I wanted...) + * Added support for set_termios and ioctl function calls. No drivers take + * advantage of this yet. + * Removed the #ifdef MODULE, now there is no module specific code. + * Cleaned up a few comments in usb-serial.h that were wrong (thanks again + * to Miles Lott). + * Small fix to get_free_serial. + * + * (02/14/2000) gkh + * Removed the Belkin and Peracom functionality from the driver due to + * the lack of support from the vendor, and me not wanting people to + * accidenatly buy the device, expecting it to work with Linux. + * Added read_bulk_callback and write_bulk_callback to the type structure + * for the needs of the FTDI and WhiteHEAT driver. + * Changed all reverences to FTDI to FTDI_SIO at the request of Bill + * Ryder. + * Changed the output urb size back to the max endpoint size to make + * the ftdi_sio driver have it easier, and due to the fact that it didn't + * really increase the speed any. + * + * (02/11/2000) gkh + * Added VISOR_FUNCTION_CONSOLE to the visor startup function. This was a + * patch from Miles Lott (milos@insync.net). + * Fixed bug with not restoring the minor range that a device grabs, if + * the startup function fails (thanks Miles for finding this). + * + * (02/05/2000) gkh + * Added initial framework for the Keyspan PDA serial converter so that + * Brian Warner has a place to put his code. + * Made the ezusb specific functions generic enough that different + * devices can use them (whiteheat and keyspan_pda both need them). + * Split out a whole bunch of structure and other stuff to a seperate + * usb-serial.h file. + * Made the Visor connection messages a little more understandable, now + * that Miles Lott (milos@insync.net) has gotten the Generic channel to + * work. Also made them always show up in the log file. + * + * (01/25/2000) gkh + * Added initial framework for FTDI serial converter so that Bill Ryder + * has a place to put his code. + * Added the vendor specific info from Handspring. Now we can print out + * informational debug messages as well as understand what is happening. + * + * (01/23/2000) gkh + * Fixed problem of crash when trying to open a port that didn't have a + * device assigned to it. Made the minor node finding a little smarter, + * now it looks to find a continous space for the new device. + * + * (01/21/2000) gkh + * Fixed bug in visor_startup with patch from Miles Lott (milos@insync.net) + * Fixed get_serial_by_minor which was all messed up for multi port + * devices. Fixed multi port problem for generic devices. Now the number + * of ports is determined by the number of bulk out endpoints for the + * generic device. + * + * (01/19/2000) gkh + * Removed lots of cruft that was around from the old (pre urb) driver + * interface. + * Made the serial_table dynamic. This should save lots of memory when + * the number of minor nodes goes up to 256. + * Added initial support for devices that have more than one port. + * Added more debugging comments for the Visor, and added a needed + * set_configuration call. + * + * (01/17/2000) gkh + * Fixed the WhiteHEAT firmware (my processing tool had a bug) + * and added new debug loader firmware for it. + * Removed the put_char function as it isn't really needed. + * Added visor startup commands as found by the Win98 dump. + * + * (01/13/2000) gkh + * Fixed the vendor id for the generic driver to the one I meant it to be. + * + * (01/12/2000) gkh + * Forget the version numbering...that's pretty useless... + * Made the driver able to be compiled so that the user can select which + * converter they want to use. This allows people who only want the Visor + * support to not pay the memory size price of the WhiteHEAT. + * Fixed bug where the generic driver (idVendor=0000 and idProduct=0000) + * grabbed the root hub. Not good. + * + * version 0.4.0 (01/10/2000) gkh + * Added whiteheat.h containing the firmware for the ConnectTech WhiteHEAT + * device. Added startup function to allow firmware to be downloaded to + * a device if it needs to be. + * Added firmware download logic to the WhiteHEAT device. + * Started to add #defines to split up the different drivers for potential + * configuration option. + * + * version 0.3.1 (12/30/99) gkh + * Fixed problems with urb for bulk out. + * Added initial support for multiple sets of endpoints. This enables + * the Handspring Visor to be attached successfully. Only the first + * bulk in / bulk out endpoint pair is being used right now. + * + * version 0.3.0 (12/27/99) gkh + * Added initial support for the Handspring Visor based on a patch from + * Miles Lott (milos@sneety.insync.net) + * Cleaned up the code a bunch and converted over to using urbs only. + * + * version 0.2.3 (12/21/99) gkh + * Added initial support for the Connect Tech WhiteHEAT converter. + * Incremented the number of ports in expectation of getting the + * WhiteHEAT to work properly (4 ports per connection). + * Added notification on insertion and removal of what port the + * device is/was connected to (and what kind of device it was). + * + * version 0.2.2 (12/16/99) gkh + * Changed major number to the new allocated number. We're legal now! + * + * version 0.2.1 (12/14/99) gkh + * Fixed bug that happens when device node is opened when there isn't a + * device attached to it. Thanks to marek@webdesign.no for noticing this. + * + * version 0.2.0 (11/10/99) gkh + * Split up internals to make it easier to add different types of serial + * converters to the code. + * Added a "generic" driver that gets it's vendor and product id + * from when the module is loaded. Thanks to David E. Nelson (dnelson@jump.net) + * for the idea and sample code (from the usb scanner driver.) + * Cleared up any licensing questions by releasing it under the GNU GPL. + * + * version 0.1.2 (10/25/99) gkh + * Fixed bug in detecting device. + * + * version 0.1.1 (10/05/99) gkh + * Changed the major number to not conflict with anything else. + * + * version 0.1 (09/28/99) gkh + * Can recognize the two different devices and start up a read from + * device when asked to. Writes also work. No control signals yet, this + * all is vendor specific data (i.e. no spec), also no control for + * different baud rates or other bit settings. + * Currently we are using the same devid as the acm driver. This needs + * to change. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_USB_SERIAL_DEBUG + #define DEBUG +#else + #undef DEBUG +#endif +#include + +/* Module information */ +MODULE_AUTHOR("Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux-usb/"); +MODULE_DESCRIPTION("USB Serial Driver"); + +#include "usb-serial.h" + + +/* 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. */ +static int generic_open (struct usb_serial_port *port, struct file *filp); +static void generic_close (struct usb_serial_port *port, struct file *filp); +static int generic_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); +static int generic_write_room (struct usb_serial_port *port); +static int generic_chars_in_buffer (struct usb_serial_port *port); +static void generic_read_bulk_callback (struct urb *urb); +static void generic_write_bulk_callback (struct urb *urb); + + +#ifdef CONFIG_USB_SERIAL_GENERIC +static __u16 vendor = 0x05f9; +static __u16 product = 0xffff; +MODULE_PARM(vendor, "i"); +MODULE_PARM_DESC(vendor, "User specified USB idVendor"); + +MODULE_PARM(product, "i"); +MODULE_PARM_DESC(product, "User specified USB idProduct"); + +/* All of the device info needed for the Generic Serial Converter */ +static struct usb_serial_device_type generic_device = { + name: "Generic", + idVendor: &vendor, /* use the user specified vendor id */ + idProduct: &product, /* use the user specified product id */ + needs_interrupt_in: DONT_CARE, /* don't have to have an interrupt in endpoint */ + needs_bulk_in: DONT_CARE, /* don't have to have a bulk in endpoint */ + needs_bulk_out: DONT_CARE, /* don't have to have a bulk out endpoint */ + num_interrupt_in: NUM_DONT_CARE, + num_bulk_in: NUM_DONT_CARE, + num_bulk_out: NUM_DONT_CARE, + num_ports: 1, +}; +#endif + + +/* To add support for another serial converter, create a usb_serial_device_type + structure for that device, and add it to this list, making sure that the + last entry is NULL. */ +static struct usb_serial_device_type *usb_serial_devices[] = { +#ifdef CONFIG_USB_SERIAL_GENERIC + &generic_device, +#endif +#ifdef CONFIG_USB_SERIAL_WHITEHEAT + &whiteheat_fake_device, + &whiteheat_device, +#endif +#ifdef CONFIG_USB_SERIAL_VISOR + &handspring_device, +#endif +#ifdef CONFIG_USB_SERIAL_FTDI_SIO + &ftdi_sio_device, +#endif +#ifdef CONFIG_USB_SERIAL_KEYSPAN_PDA + &keyspan_pda_fake_device, + &keyspan_pda_device, +#endif + NULL +}; + + +/* variables needed for the tty_driver structure */ +static char *driver_name = "usb"; +static char *tty_driver_name = "usb/tty/%d"; + + +/* local function prototypes */ +static int serial_open (struct tty_struct *tty, struct file * filp); +static void serial_close (struct tty_struct *tty, struct file * filp); +static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count); +static int serial_write_room (struct tty_struct *tty); +static int serial_chars_in_buffer (struct tty_struct *tty); +static void serial_throttle (struct tty_struct * tty); +static void serial_unthrottle (struct tty_struct * tty); +static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg); +static void serial_set_termios (struct tty_struct *tty, struct termios * old); + +static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum); +static void usb_serial_disconnect(struct usb_device *dev, void *ptr); + +static struct usb_driver usb_serial_driver = { + name: "serial", + probe: usb_serial_probe, + disconnect: usb_serial_disconnect, +}; + +static int serial_refcount; +static struct tty_struct * serial_tty[SERIAL_TTY_MINORS]; +static struct termios * serial_termios[SERIAL_TTY_MINORS]; +static struct termios * serial_termios_locked[SERIAL_TTY_MINORS]; +static struct usb_serial *serial_table[SERIAL_TTY_MINORS] = {NULL, }; + + + +static struct usb_serial *get_serial_by_minor (int minor) +{ + return serial_table[minor]; +} + + +static struct usb_serial *get_free_serial (int num_ports, int *minor) +{ + struct usb_serial *serial = NULL; + int i, j; + int good_spot; + + dbg("get_free_serial %d", num_ports); + + *minor = 0; + for (i = 0; i < SERIAL_TTY_MINORS; ++i) { + if (serial_table[i]) + continue; + + good_spot = 1; + for (j = 1; j <= num_ports-1; ++j) + if (serial_table[i+j]) + good_spot = 0; + if (good_spot == 0) + continue; + + if (!(serial = kmalloc(sizeof(struct usb_serial), GFP_KERNEL))) { + err("Out of memory"); + return NULL; + } + memset(serial, 0, sizeof(struct usb_serial)); + serial->magic = USB_SERIAL_MAGIC; + serial_table[i] = serial; + *minor = i; + dbg("minor base = %d", *minor); + for (i = *minor+1; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) + serial_table[i] = serial; + return serial; + } + return NULL; +} + + +static void return_serial (struct usb_serial *serial) +{ + int i; + + dbg("return_serial"); + + if (serial == NULL) + return; + + for (i = 0; i < serial->num_ports; ++i) { + serial_table[serial->minor + i] = NULL; + } + + return; +} + + +#ifdef USES_EZUSB_FUNCTIONS +/* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */ +#define CPUCS_REG 0x7F92 + +int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *data, int length, __u8 bRequest) +{ + int result; + unsigned char *transfer_buffer = kmalloc (length, GFP_KERNEL); + +// dbg("ezusb_writememory %x, %d", address, length); + + if (!transfer_buffer) { + err("ezusb_writememory: kmalloc(%d) failed.", length); + return -ENOMEM; + } + memcpy (transfer_buffer, data, length); + result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), bRequest, 0x40, address, 0, transfer_buffer, length, 300); + kfree (transfer_buffer); + return result; +} + + +int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit) +{ + int response; + dbg("ezusb_set_reset: %d", reset_bit); + response = ezusb_writememory (serial, CPUCS_REG, &reset_bit, 1, 0xa0); + if (response < 0) { + err("ezusb_set_reset %d failed", reset_bit); + } + return response; +} + +#endif /* USES_EZUSB_FUNCTIONS */ + + +/***************************************************************************** + * Driver tty interface functions + *****************************************************************************/ +static int serial_open (struct tty_struct *tty, struct file * filp) +{ + struct usb_serial *serial; + struct usb_serial_port *port; + int portNumber; + + dbg("serial_open"); + + /* initialize the pointer incase something fails */ + tty->driver_data = NULL; + + /* get the serial object associated with this tty pointer */ + serial = get_serial_by_minor (MINOR(tty->device)); + + if (serial_paranoia_check (serial, "serial_open")) { + return -ENODEV; + } + + /* set up our port structure */ + portNumber = MINOR(tty->device) - serial->minor; + port = &serial->port[portNumber]; + port->number = portNumber; + port->serial = serial; + port->magic = USB_SERIAL_PORT_MAGIC; + + /* make the tty driver remember our port object, and us it */ + tty->driver_data = port; + port->tty = tty; + + /* pass on to the driver specific version of this function if it is available */ + if (serial->type->open) { + return (serial->type->open(port, filp)); + } else { + return (generic_open(port, filp)); + } +} + + +static void serial_close(struct tty_struct *tty, struct file * filp) +{ + struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; + struct usb_serial *serial; + + dbg("serial_close"); + + if (port_paranoia_check (port, "serial_close")) { + return; + } + + serial = port->serial; + if (serial_paranoia_check (serial, "serial_close")) { + return; + } + + dbg("serial_close port %d", port->number); + + if (!port->active) { + dbg ("port not opened"); + return; + } + + /* pass on to the driver specific version of this function if it is available */ + if (serial->type->close) { + serial->type->close(port, filp); + } else { + generic_close(port, filp); + } +} + + +static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count) +{ + struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; + struct usb_serial *serial; + + dbg("serial_write"); + + if (port_paranoia_check (port, "serial_write")) { + return -ENODEV; + } + + serial = port->serial; + if (serial_paranoia_check (serial, "serial_write")) { + return -ENODEV; + } + + dbg("serial_write port %d, %d byte(s)", port->number, count); + + if (!port->active) { + dbg ("port not opened"); + return -EINVAL; + } + + /* pass on to the driver specific version of this function if it is available */ + if (serial->type->write) { + return (serial->type->write(port, from_user, buf, count)); + } else { + return (generic_write(port, from_user, buf, count)); + } +} + + +static int serial_write_room (struct tty_struct *tty) +{ + struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; + struct usb_serial *serial; + + dbg("serial_write_room"); + + if (port_paranoia_check (port, "serial_write")) { + return -ENODEV; + } + + serial = port->serial; + if (serial_paranoia_check (serial, "serial_write")) { + return -ENODEV; + } + + dbg("serial_write_room port %d", port->number); + + if (!port->active) { + dbg ("port not open"); + return -EINVAL; + } + + /* pass on to the driver specific version of this function if it is available */ + if (serial->type->write_room) { + return (serial->type->write_room(port)); + } else { + return (generic_write_room(port)); + } +} + + +static int serial_chars_in_buffer (struct tty_struct *tty) +{ + struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; + struct usb_serial *serial; + + dbg("serial_chars_in_buffer"); + + if (port_paranoia_check (port, "serial_chars_in_buffer")) { + return -ENODEV; + } + + serial = port->serial; + if (serial_paranoia_check (serial, "serial_chars_in_buffer")) { + return -ENODEV; + } + + if (!port->active) { + dbg ("port not open"); + return -EINVAL; + } + + /* pass on to the driver specific version of this function if it is available */ + if (serial->type->chars_in_buffer) { + return (serial->type->chars_in_buffer(port)); + } else { + return (generic_chars_in_buffer(port)); + } +} + + +static void serial_throttle (struct tty_struct * tty) +{ + struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; + struct usb_serial *serial; + + dbg("serial_throttle"); + + if (port_paranoia_check (port, "serial_throttle")) { + return; + } + + serial = port->serial; + if (serial_paranoia_check (serial, "serial_throttle")) { + return; + } + + dbg("serial_throttle port %d", port->number); + + if (!port->active) { + dbg ("port not open"); + return; + } + + /* pass on to the driver specific version of this function */ + if (serial->type->throttle) { + serial->type->throttle(port); + } + + return; +} + + +static void serial_unthrottle (struct tty_struct * tty) +{ + struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; + struct usb_serial *serial; + + dbg("serial_unthrottle"); + + if (port_paranoia_check (port, "serial_unthrottle")) { + return; + } + + serial = port->serial; + if (serial_paranoia_check (serial, "serial_unthrottle")) { + return; + } + + dbg("serial_unthrottle port %d", port->number); + + if (!port->active) { + dbg ("port not open"); + return; + } + + /* pass on to the driver specific version of this function */ + if (serial->type->unthrottle) { + serial->type->unthrottle(port); + } + + return; +} + + +static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) +{ + struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; + struct usb_serial *serial; + + dbg("serial_ioctl"); + + if (port_paranoia_check (port, "serial_ioctl")) { + return -ENODEV; + } + + serial = port->serial; + if (serial_paranoia_check (serial, "serial_ioctl")) { + return -ENODEV; + } + + dbg("serial_ioctl port %d", port->number); + + if (!port->active) { + dbg ("port not open"); + return -ENODEV; + } + + /* pass on to the driver specific version of this function if it is available */ + if (serial->type->ioctl) { + return (serial->type->ioctl(port, file, cmd, arg)); + } else { + return -ENOIOCTLCMD; + } +} + + +static void serial_set_termios (struct tty_struct *tty, struct termios * old) +{ + struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; + struct usb_serial *serial; + + dbg("serial_set_termios"); + + if (port_paranoia_check (port, "serial_set_termios")) { + return; + } + + serial = port->serial; + if (serial_paranoia_check (serial, "serial_set_termios")) { + return; + } + + dbg("serial_set_termios port %d", port->number); + + if (!port->active) { + dbg ("port not open"); + return; + } + + /* pass on to the driver specific version of this function if it is available */ + if (serial->type->set_termios) { + serial->type->set_termios(port, old); + } + + return; +} + + +static void serial_break (struct tty_struct *tty, int break_state) +{ + struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; + struct usb_serial *serial; + + dbg("serial_break"); + + if (port_paranoia_check (port, "serial_break")) { + return; + } + + serial = port->serial; + if (serial_paranoia_check (serial, "serial_break")) { + return; + } + + dbg("serial_break port %d", port->number); + + if (!port->active) { + dbg ("port not open"); + return; + } + + /* pass on to the driver specific version of this function if it is + available */ + if (serial->type->break_ctl) { + serial->type->break_ctl(port, break_state); + } +} + + + +/***************************************************************************** + * generic devices specific driver functions + *****************************************************************************/ +static int generic_open (struct usb_serial_port *port, struct file *filp) +{ + struct usb_serial *serial = port->serial; + + dbg("generic_open port %d", port->number); + + if (port->active) { + dbg ("device already open"); + return -EINVAL; + } + port->active = 1; + + /* if we have a bulk interrupt, start reading from it */ + if (serial->num_bulk_in) { + /*Start reading from the device*/ + if (usb_submit_urb(port->read_urb)) + dbg("usb_submit_urb(read bulk) failed"); + } + + return (0); +} + + +static void generic_close (struct usb_serial_port *port, struct file * filp) +{ + struct usb_serial *serial = port->serial; + + dbg("generic_close port %d", port->number); + + /* shutdown any bulk reads that might be going on */ + if (serial->num_bulk_out) { + usb_unlink_urb (port->write_urb); + } + if (serial->num_bulk_in) { + usb_unlink_urb (port->read_urb); + } + + port->active = 0; +} + + +static int generic_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) +{ + struct usb_serial *serial = port->serial; + + dbg("generic_serial_write port %d", port->number); + + if (count == 0) { + dbg("write request of 0 bytes"); + return (0); + } + + /* only do something if we have a bulk out endpoint */ + if (serial->num_bulk_out) { + if (port->write_urb->status == -EINPROGRESS) { + dbg ("already writing"); + return (0); + } + + count = (count > port->bulk_out_size) ? port->bulk_out_size : count; + + if (from_user) { + copy_from_user(port->write_urb->transfer_buffer, buf, count); + } + else { + memcpy (port->write_urb->transfer_buffer, buf, count); + } + + /* send the data out the bulk port */ + port->write_urb->transfer_buffer_length = count; + + if (usb_submit_urb(port->write_urb)) + dbg("usb_submit_urb(write bulk) failed"); + + return (count); + } + + /* no bulk out, so return 0 bytes written */ + return (0); +} + + +static int generic_write_room (struct usb_serial_port *port) +{ + struct usb_serial *serial = port->serial; + int room; + + dbg("generic_write_room port %d", port->number); + + if (serial->num_bulk_out) { + if (port->write_urb->status == -EINPROGRESS) + room = 0; + else + room = port->bulk_out_size; + dbg("generic_write_room returns %d", room); + return (room); + } + + return (0); +} + + +static int generic_chars_in_buffer (struct usb_serial_port *port) +{ + struct usb_serial *serial = port->serial; + + dbg("generic_chars_in_buffer port %d", port->number); + + if (serial->num_bulk_out) { + if (port->write_urb->status == -EINPROGRESS) { + return (port->bulk_out_size); + } + } + + return (0); +} + + +static void generic_read_bulk_callback (struct urb *urb) +{ + struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + struct usb_serial *serial; + struct tty_struct *tty; + unsigned char *data = urb->transfer_buffer; + int i; + + dbg("generic_read_bulk_callback"); + + if (port_paranoia_check (port, "generic_read_bulk_callback")) { + return; + } + + serial = port->serial; + if (serial_paranoia_check (serial, "generic_read_bulk_callback")) { + return; + } + + if (urb->status) { + dbg("nonzero read bulk status received: %d", urb->status); + return; + } + +#ifdef DEBUG + if (urb->actual_length) { + printk (KERN_DEBUG __FILE__ ": data read - length = %d, data = ", urb->actual_length); + for (i = 0; i < urb->actual_length; ++i) { + printk ("%.2x ", data[i]); + } + printk ("\n"); + } +#endif + + tty = port->tty; + if (urb->actual_length) { + for (i = 0; i < urb->actual_length ; ++i) { + tty_insert_flip_char(tty, data[i], 0); + } + tty_flip_buffer_push(tty); + } + + /* Continue trying to always read */ + if (usb_submit_urb(urb)) + dbg("failed resubmitting read urb"); + + return; +} + + +static void generic_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; + + dbg("generic_write_bulk_callback"); + + if (port_paranoia_check (port, "generic_write_bulk_callback")) { + return; + } + + serial = port->serial; + if (serial_paranoia_check (serial, "generic_write_bulk_callback")) { + return; + } + + if (urb->status) { + dbg("nonzero write bulk status received: %d", urb->status); + return; + } + + tty = port->tty; + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); + + wake_up_interruptible(&tty->write_wait); + + return; +} + + +static struct tty_driver * usb_serial_tty_driver_init (struct usb_serial *serial) +{ + struct tty_driver *serial_tty_driver; + + if (!(serial_tty_driver = kmalloc(sizeof(struct tty_driver), GFP_KERNEL))) { + err("Out of memory"); + return NULL; + } + + memset (serial_tty_driver, 0x00, sizeof(struct tty_driver)); + + /* initialize the entries that we don't want to be NULL */ + serial_tty_driver->magic = TTY_DRIVER_MAGIC; + serial_tty_driver->driver_name = driver_name; + serial_tty_driver->name = tty_driver_name; + serial_tty_driver->major = SERIAL_TTY_MAJOR; + serial_tty_driver->minor_start = serial->minor; + serial_tty_driver->num = serial->num_ports; + serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; + serial_tty_driver->subtype = SERIAL_TYPE_NORMAL; + serial_tty_driver->flags = TTY_DRIVER_REAL_RAW; + serial_tty_driver->refcount = &serial_refcount; + serial_tty_driver->table = serial_tty; + serial_tty_driver->termios = serial_termios; + serial_tty_driver->termios_locked = serial_termios_locked; + serial_tty_driver->open = serial_open; + serial_tty_driver->close = serial_close; + serial_tty_driver->write = serial_write; + serial_tty_driver->write_room = serial_write_room; + serial_tty_driver->ioctl = serial_ioctl; + serial_tty_driver->set_termios = serial_set_termios; + serial_tty_driver->throttle = serial_throttle; + serial_tty_driver->unthrottle = serial_unthrottle; + serial_tty_driver->break_ctl = serial_break; + serial_tty_driver->chars_in_buffer = serial_chars_in_buffer; + serial_tty_driver->init_termios = tty_std_termios; + serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + + return serial_tty_driver; +} + + +static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum) +{ + struct usb_serial *serial = NULL; + struct usb_serial_port *port; + struct usb_interface_descriptor *interface; + struct usb_endpoint_descriptor *endpoint; + struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS]; + struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS]; + struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS]; + struct usb_serial_device_type *type; + int device_num; + int minor; + int buffer_size; + int i; + char interrupt_pipe; + char bulk_in_pipe; + char bulk_out_pipe; + int num_interrupt_in = 0; + int num_bulk_in = 0; + int num_bulk_out = 0; + int num_ports; + + /* loop through our list of known serial converters, and see if this device matches */ + device_num = 0; + while (usb_serial_devices[device_num] != NULL) { + type = usb_serial_devices[device_num]; + dbg ("Looking at %s Vendor id=%.4x Product id=%.4x", type->name, *(type->idVendor), *(type->idProduct)); + + /* look at the device descriptor */ + if ((dev->descriptor.idVendor == *(type->idVendor)) && + (dev->descriptor.idProduct == *(type->idProduct))) { + + dbg("descriptor matches...looking at the endpoints"); + + /* descriptor matches, let's try to find the endpoints needed */ + interrupt_pipe = bulk_in_pipe = bulk_out_pipe = HAS_NOT; + + /* check out the endpoints */ + interface = &dev->actconfig->interface[ifnum].altsetting[0]; + for (i = 0; i < interface->bNumEndpoints; ++i) { + endpoint = &interface->endpoint[i]; + + if ((endpoint->bEndpointAddress & 0x80) && + ((endpoint->bmAttributes & 3) == 0x02)) { + /* we found a bulk in endpoint */ + dbg("found bulk in"); + bulk_in_pipe = HAS; + bulk_in_endpoint[num_bulk_in] = endpoint; + ++num_bulk_in; + } + + if (((endpoint->bEndpointAddress & 0x80) == 0x00) && + ((endpoint->bmAttributes & 3) == 0x02)) { + /* we found a bulk out endpoint */ + dbg("found bulk out"); + bulk_out_pipe = HAS; + bulk_out_endpoint[num_bulk_out] = endpoint; + ++num_bulk_out; + } + + if ((endpoint->bEndpointAddress & 0x80) && + ((endpoint->bmAttributes & 3) == 0x03)) { + /* we found a interrupt in endpoint */ + dbg("found interrupt in"); + interrupt_pipe = HAS; + interrupt_in_endpoint[num_interrupt_in] = endpoint; + ++num_interrupt_in; + } + + } + + /* verify that we found all of the endpoints that we need */ + if ((interrupt_pipe & type->needs_interrupt_in) && + (bulk_in_pipe & type->needs_bulk_in) && + (bulk_out_pipe & type->needs_bulk_out)) { + /* found all that we need */ + MOD_INC_USE_COUNT; + info("%s converter detected", type->name); + +#ifdef CONFIG_USB_SERIAL_GENERIC + if (type == &generic_device) + num_ports = num_bulk_out; + else +#endif + num_ports = type->num_ports; + + serial = get_free_serial (num_ports, &minor); + if (serial == NULL) { + err("No more free serial devices"); + MOD_DEC_USE_COUNT; + return NULL; + } + + serial->dev = dev; + serial->type = type; + serial->minor = minor; + serial->num_ports = num_ports; + serial->num_bulk_in = num_bulk_in; + serial->num_bulk_out = num_bulk_out; + serial->num_interrupt_in = num_interrupt_in; + + /* initialize a tty_driver for this device */ + serial->tty_driver = usb_serial_tty_driver_init (serial); + if (serial->tty_driver == NULL) { + err("Can't create a tty_serial_driver"); + goto probe_error; + } + + if (tty_register_driver (serial->tty_driver)) { + err("failed to register tty driver"); + goto probe_error; + } + + /* collect interrupt_in endpoints now, because + the keyspan_pda startup function needs + to know about them */ + for (i = 0; i < num_interrupt_in; ++i) { + port = &serial->port[i]; + buffer_size = interrupt_in_endpoint[i]->wMaxPacketSize; + port->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL); + if (!port->interrupt_in_buffer) { + err("Couldn't allocate interrupt_in_buffer"); + goto probe_error; + } + port->interrupt_in_endpoint = interrupt_in_endpoint[i]; + } + + /* if this device type has a startup function, call it */ + if (type->startup) { + if (type->startup (serial)) { + goto probe_error; + } + } + + /* set up the endpoint information */ + for (i = 0; i < num_bulk_in; ++i) { + port = &serial->port[i]; + port->read_urb = usb_alloc_urb (0); + if (!port->read_urb) { + err("No free urbs available"); + goto probe_error; + } + buffer_size = bulk_in_endpoint[i]->wMaxPacketSize; + port->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL); + if (!port->bulk_in_buffer) { + err("Couldn't allocate bulk_in_buffer"); + goto probe_error; + } + if (serial->type->read_bulk_callback) { + FILL_BULK_URB(port->read_urb, dev, usb_rcvbulkpipe (dev, bulk_in_endpoint[i]->bEndpointAddress), + port->bulk_in_buffer, buffer_size, serial->type->read_bulk_callback, port); + } else { + FILL_BULK_URB(port->read_urb, dev, usb_rcvbulkpipe (dev, bulk_in_endpoint[i]->bEndpointAddress), + port->bulk_in_buffer, buffer_size, generic_read_bulk_callback, port); + } + } + + for (i = 0; i < num_bulk_out; ++i) { + port = &serial->port[i]; + port->write_urb = usb_alloc_urb(0); + if (!port->write_urb) { + err("No free urbs available"); + goto probe_error; + } + port->bulk_out_size = bulk_out_endpoint[i]->wMaxPacketSize; + port->bulk_out_buffer = kmalloc (port->bulk_out_size, GFP_KERNEL); + if (!port->bulk_out_buffer) { + err("Couldn't allocate bulk_out_buffer"); + goto probe_error; + } + if (serial->type->write_bulk_callback) { + FILL_BULK_URB(port->write_urb, dev, usb_sndbulkpipe (dev, bulk_out_endpoint[i]->bEndpointAddress), + port->bulk_out_buffer, port->bulk_out_size, serial->type->write_bulk_callback, port); + } else { + FILL_BULK_URB(port->write_urb, dev, usb_sndbulkpipe (dev, bulk_out_endpoint[i]->bEndpointAddress), + port->bulk_out_buffer, port->bulk_out_size, generic_write_bulk_callback, port); + } + } + +#if 0 /* use this code when WhiteHEAT is up and running */ + for (i = 0; i < num_interrupt_in; ++i) { + port = &serial->port[i]; + port->control_urb = usb_alloc_urb(0); + if (!port->control_urb) { + err("No free urbs available"); + goto probe_error; + } + buffer_size = interrupt_in_endpoint[i]->wMaxPacketSize; + port->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL); + if (!port->interrupt_in_buffer) { + err("Couldn't allocate interrupt_in_buffer"); + goto probe_error; + } + FILL_INT_URB(port->control_urb, dev, usb_rcvintpipe (dev, interrupt_in_endpoint[i]->bEndpointAddress), + port->interrupt_in_buffer, buffer_size, serial_control_irq, + port, interrupt_in_endpoint[i]->bInterval); + } +#endif + + for (i = 0; i < serial->num_ports; ++i) { + info("%s converter now attached to ttyUSB%d", type->name, serial->minor + i); + } + + return serial; + } else { + info("descriptors matched, but endpoints did not"); + } + } + + /* look at the next type in our list */ + ++device_num; + } + +probe_error: + if (serial) { + for (i = 0; i < num_bulk_in; ++i) { + port = &serial->port[i]; + if (port->read_urb) + usb_free_urb (port->read_urb); + if (serial->port[i].bulk_in_buffer[i]) + kfree (serial->port[i].bulk_in_buffer); + } + for (i = 0; i < num_bulk_out; ++i) { + port = &serial->port[i]; + if (port->write_urb) + usb_free_urb (port->write_urb); + if (serial->port[i].bulk_out_buffer) + kfree (serial->port[i].bulk_out_buffer); + } + for (i = 0; i < num_interrupt_in; ++i) { + port = &serial->port[i]; + if (port->control_urb) + usb_free_urb (port->control_urb); + if (serial->port[i].interrupt_in_buffer) + kfree (serial->port[i].interrupt_in_buffer); + } + + /* return the minor range that this device had */ + return_serial (serial); + + /* if this device has a tty_driver, then unregister it and free it */ + if (serial->tty_driver) { + tty_unregister_driver (serial->tty_driver); + kfree (serial->tty_driver); + serial->tty_driver = NULL; + } + + /* free up any memory that we allocated */ + kfree (serial); + MOD_DEC_USE_COUNT; + } + return NULL; +} + + +static void usb_serial_disconnect(struct usb_device *dev, void *ptr) +{ + struct usb_serial *serial = (struct usb_serial *) ptr; + struct usb_serial_port *port; + int i; + + if (serial) { + for (i = 0; i < serial->num_ports; ++i) + serial->port[i].active = 0; + + for (i = 0; i < serial->num_bulk_in; ++i) { + port = &serial->port[i]; + if (port->read_urb) { + usb_unlink_urb (port->read_urb); + usb_free_urb (port->read_urb); + } + if (port->bulk_in_buffer) + kfree (port->bulk_in_buffer); + } + for (i = 0; i < serial->num_bulk_out; ++i) { + port = &serial->port[i]; + if (port->write_urb) { + usb_unlink_urb (port->write_urb); + usb_free_urb (port->write_urb); + } + if (port->bulk_out_buffer) + kfree (port->bulk_out_buffer); + } + for (i = 0; i < serial->num_interrupt_in; ++i) { + port = &serial->port[i]; + if (port->control_urb) { + usb_unlink_urb (port->control_urb); + usb_free_urb (port->control_urb); + } + if (port->interrupt_in_buffer) + kfree (port->interrupt_in_buffer); + } + + for (i = 0; i < serial->num_ports; ++i) { + info("%s converter now disconnected from ttyUSB%d", serial->type->name, serial->minor + i); + } + + /* return the minor range that this device had */ + return_serial (serial); + + /* if this device has a tty_driver, then unregister it and free it */ + if (serial->tty_driver) { + tty_unregister_driver (serial->tty_driver); + kfree (serial->tty_driver); + serial->tty_driver = NULL; + } + /* free up any memory that we allocated */ + kfree (serial); + + } else { + info("device disconnected"); + } + + MOD_DEC_USE_COUNT; +} + + +int usb_serial_init(void) +{ + int i; + + /* Initalize our global data */ + for (i = 0; i < SERIAL_TTY_MINORS; ++i) { + serial_table[i] = NULL; + } + + /* register the USB driver */ + if (usb_register(&usb_serial_driver) < 0) { + return -1; + } + + info("support registered"); + return 0; +} + + +void usb_serial_exit(void) +{ + usb_deregister(&usb_serial_driver); +} + + +module_init(usb_serial_init); +module_exit(usb_serial_exit); + + diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/serial/visor.c linux/drivers/usb/serial/visor.c --- v2.3.99-pre3/linux/drivers/usb/serial/visor.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/serial/visor.c Mon Mar 27 14:25:28 2000 @@ -0,0 +1,209 @@ +/* + * USB HandSpring Visor driver + * + * (C) Copyright (C) 1999, 2000 + * Greg Kroah-Hartman (greg@kroah.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. + * + * See Documentation/usb/usb-serial.txt for more information on using this driver + * + * (03/26/2000) gkh + * Split driver up into device specific pieces. + * + */ + +#include + +#ifdef CONFIG_USB_SERIAL_VISOR + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_USB_SERIAL_DEBUG + #define DEBUG +#else + #undef DEBUG +#endif +#include + +#include "usb-serial.h" + +#include "visor.h" + + +/* function prototypes for a handspring visor */ +static int visor_open (struct usb_serial_port *port, struct file *filp); +static void visor_close (struct usb_serial_port *port, struct file *filp); +static void visor_throttle (struct usb_serial_port *port); +static void visor_unthrottle (struct usb_serial_port *port); +static int visor_startup (struct usb_serial *serial); + +/* All of the device info needed for the Handspring Visor */ +static __u16 handspring_vendor_id = HANDSPRING_VENDOR_ID; +static __u16 handspring_product_id = HANDSPRING_VISOR_ID; +struct usb_serial_device_type handspring_device = { + name: "Handspring Visor", + idVendor: &handspring_vendor_id, /* the Handspring vendor ID */ + idProduct: &handspring_product_id, /* the Handspring Visor product id */ + 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, +}; + + +/****************************************************************************** + * Handspring Visor specific driver functions + ******************************************************************************/ +static int visor_open (struct usb_serial_port *port, struct file *filp) +{ + dbg("visor_open port %d", port->number); + + if (port->active) { + dbg ("device already open"); + return -EINVAL; + } + + port->active = 1; + + /*Start reading from the device*/ + if (usb_submit_urb(port->read_urb)) + dbg("usb_submit_urb(read bulk) failed"); + + return (0); +} + + +static void visor_close (struct usb_serial_port *port, struct file * filp) +{ + struct usb_serial *serial = port->serial; + unsigned char *transfer_buffer = kmalloc (0x12, GFP_KERNEL); + + dbg("visor_close port %d", port->number); + + if (!transfer_buffer) { + err("visor_close: kmalloc(%d) failed.", 0x12); + } else { + /* send a shutdown message to the device */ + usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_CLOSE_NOTIFICATION, + 0xc2, 0x0000, 0x0000, transfer_buffer, 0x12, 300); + } + + /* shutdown our bulk reads and writes */ + usb_unlink_urb (port->write_urb); + usb_unlink_urb (port->read_urb); + port->active = 0; +} + + +static void visor_throttle (struct usb_serial_port *port) +{ + dbg("visor_throttle port %d", port->number); + + usb_unlink_urb (port->read_urb); + + return; +} + + +static void visor_unthrottle (struct usb_serial_port *port) +{ + dbg("visor_unthrottle port %d", port->number); + + if (usb_unlink_urb (port->read_urb)) + dbg("usb_submit_urb(read bulk) failed"); + + return; +} + + +static int visor_startup (struct usb_serial *serial) +{ + int response; + int i; + unsigned char *transfer_buffer = kmalloc (256, GFP_KERNEL); + + if (!transfer_buffer) { + err("visor_startup: kmalloc(%d) failed.", 256); + return -ENOMEM; + } + + dbg("visor_startup"); + + dbg("visor_setup: Set config to 1"); + usb_set_configuration (serial->dev, 1); + + /* send a get connection info request */ + response = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_GET_CONNECTION_INFORMATION, + 0xc2, 0x0000, 0x0000, transfer_buffer, 0x12, 300); + if (response < 0) { + err("visor_startup: error getting connection information"); + } else { + struct visor_connection_info *connection_info = (struct visor_connection_info *)transfer_buffer; + char *string; + info("%s: Number of ports: %d", serial->type->name, connection_info->num_ports); + for (i = 0; i < connection_info->num_ports; ++i) { + switch (connection_info->connections[i].port_function_id) { + case VISOR_FUNCTION_GENERIC: + string = "Generic"; + break; + case VISOR_FUNCTION_DEBUGGER: + string = "Debugger"; + break; + case VISOR_FUNCTION_HOTSYNC: + string = "HotSync"; + break; + case VISOR_FUNCTION_CONSOLE: + string = "Console"; + break; + case VISOR_FUNCTION_REMOTE_FILE_SYS: + string = "Remote File System"; + break; + default: + string = "unknown"; + break; + } + info("%s: port %d, is for %s use and is bound to ttyUSB%d", serial->type->name, connection_info->connections[i].port, string, serial->minor + i); + } + } + + /* ask for the number of bytes available, but ignore the response as it is broken */ + response = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_REQUEST_BYTES_AVAILABLE, + 0xc2, 0x0000, 0x0005, transfer_buffer, 0x02, 300); + if (response < 0) { + err("visor_startup: error getting bytes available request"); + } + + kfree (transfer_buffer); + + /* continue on with initialization */ + return (0); +} + + +#endif /* CONFIG_USB_SERIAL_VISOR*/ + + diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/serial/visor.h linux/drivers/usb/serial/visor.h --- v2.3.99-pre3/linux/drivers/usb/serial/visor.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/serial/visor.h Mon Mar 27 14:25:28 2000 @@ -0,0 +1,74 @@ +/* + * USB HandSpring Visor driver + * + * (C) Copyright (C) 1999, 2000 + * Greg Kroah-Hartman (greg@kroah.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. + * + * See Documentation/usb/usb-serial.txt for more information on using this driver + * + */ + +#ifndef __LINUX_USB_SERIAL_VISOR_H +#define __LINUX_USB_SERIAL_VISOR_H + + +#define HANDSPRING_VENDOR_ID 0x082d +#define HANDSPRING_VISOR_ID 0x0100 + +/**************************************************************************** + * Handspring Visor Vendor specific request codes (bRequest values) + * A big thank you to Handspring for providing the following information. + * If anyone wants the original file where these values and structures came + * from, send email to . + ****************************************************************************/ + +/**************************************************************************** + * VISOR_REQUEST_BYTES_AVAILABLE asks the visor for the number of bytes that + * are available to be transfered to the host for the specified endpoint. + * Currently this is not used, and always returns 0x0001 + ****************************************************************************/ +#define VISOR_REQUEST_BYTES_AVAILABLE 0x01 + +/**************************************************************************** + * VISOR_CLOSE_NOTIFICATION is set to the device to notify it that the host + * is now closing the pipe. An empty packet is sent in response. + ****************************************************************************/ +#define VISOR_CLOSE_NOTIFICATION 0x02 + +/**************************************************************************** + * VISOR_GET_CONNECTION_INFORMATION is sent by the host during enumeration to + * get the endpoints used by the connection. + ****************************************************************************/ +#define VISOR_GET_CONNECTION_INFORMATION 0x03 + + +/**************************************************************************** + * VISOR_GET_CONNECTION_INFORMATION returns data in the following format + ****************************************************************************/ +struct visor_connection_info { + __u16 num_ports; + struct { + __u8 port_function_id; + __u8 port; + } connections[2]; +}; + + +/* struct visor_connection_info.connection[x].port defines: */ +#define VISOR_ENDPOINT_1 0x01 +#define VISOR_ENDPOINT_2 0x02 + +/* struct visor_connection_info.connection[x].port_function_id defines: */ +#define VISOR_FUNCTION_GENERIC 0x00 +#define VISOR_FUNCTION_DEBUGGER 0x01 +#define VISOR_FUNCTION_HOTSYNC 0x02 +#define VISOR_FUNCTION_CONSOLE 0x03 +#define VISOR_FUNCTION_REMOTE_FILE_SYS 0x04 + +#endif + diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/serial/whiteheat.c linux/drivers/usb/serial/whiteheat.c --- v2.3.99-pre3/linux/drivers/usb/serial/whiteheat.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/serial/whiteheat.c Mon Apr 10 22:54:09 2000 @@ -0,0 +1,251 @@ +/* + * USB ConnectTech WhiteHEAT driver + * + * (C) Copyright (C) 1999, 2000 + * Greg Kroah-Hartman (greg@kroah.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. + * + * See Documentation/usb/usb-serial.txt for more information on using this driver + * + * (03/26/2000) gkh + * Split driver up into device specific pieces. + * + */ + +#include + +#ifdef CONFIG_USB_SERIAL_WHITEHEAT + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_USB_SERIAL_DEBUG + #define DEBUG +#else + #undef DEBUG +#endif +#include + +#include "usb-serial.h" + +#include "whiteheat_fw.h" /* firmware for the ConnectTech WhiteHEAT device */ + + +#define CONNECT_TECH_VENDOR_ID 0x0710 +#define CONNECT_TECH_FAKE_WHITE_HEAT_ID 0x0001 +#define CONNECT_TECH_WHITE_HEAT_ID 0x8001 + +/* function prototypes for the Connect Tech WhiteHEAT serial converter */ +static int whiteheat_open (struct usb_serial_port *port, struct file *filp); +static void whiteheat_close (struct usb_serial_port *port, struct file *filp); +static void whiteheat_set_termios (struct usb_serial_port *port, struct termios * old); +static void whiteheat_throttle (struct usb_serial_port *port); +static void whiteheat_unthrottle (struct usb_serial_port *port); +static int whiteheat_startup (struct usb_serial *serial); + +/* All of the device info needed for the Connect Tech WhiteHEAT */ +static __u16 connecttech_vendor_id = CONNECT_TECH_VENDOR_ID; +static __u16 connecttech_whiteheat_fake_product_id = CONNECT_TECH_FAKE_WHITE_HEAT_ID; +static __u16 connecttech_whiteheat_product_id = CONNECT_TECH_WHITE_HEAT_ID; +struct usb_serial_device_type whiteheat_fake_device = { + name: "Connect Tech - WhiteHEAT - (prerenumeration)", + idVendor: &connecttech_vendor_id, /* the Connect Tech vendor id */ + idProduct: &connecttech_whiteheat_fake_product_id, /* the White Heat initial product id */ + needs_interrupt_in: DONT_CARE, /* don't have to have an interrupt in endpoint */ + needs_bulk_in: DONT_CARE, /* don't have to have a bulk in endpoint */ + needs_bulk_out: DONT_CARE, /* don't have to have a bulk out endpoint */ + num_interrupt_in: NUM_DONT_CARE, + num_bulk_in: NUM_DONT_CARE, + num_bulk_out: NUM_DONT_CARE, + num_ports: 1, + startup: whiteheat_startup +}; +struct usb_serial_device_type whiteheat_device = { + name: "Connect Tech - WhiteHEAT", + idVendor: &connecttech_vendor_id, /* the Connect Tech vendor id */ + idProduct: &connecttech_whiteheat_product_id, /* the White Heat real product id */ + needs_interrupt_in: DONT_CARE, /* don't have to have an interrupt in endpoint */ + needs_bulk_in: DONT_CARE, /* don't have to have a bulk in endpoint */ + needs_bulk_out: DONT_CARE, /* don't have to have a bulk out endpoint */ + num_interrupt_in: NUM_DONT_CARE, + num_bulk_in: NUM_DONT_CARE, + num_bulk_out: NUM_DONT_CARE, + num_ports: 4, + open: whiteheat_open, + close: whiteheat_close, + throttle: whiteheat_throttle, + unthrottle: whiteheat_unthrottle, + set_termios: whiteheat_set_termios, +}; + + +/***************************************************************************** + * Connect Tech's White Heat specific driver functions + *****************************************************************************/ +static int whiteheat_open (struct usb_serial_port *port, struct file *filp) +{ + dbg("whiteheat_open port %d", port->number); + + if (port->active) { + dbg ("device already open"); + return -EINVAL; + } + port->active = 1; + + /*Start reading from the device*/ + if (usb_submit_urb(port->read_urb)) + dbg("usb_submit_urb(read bulk) failed"); + + /* Need to do device specific setup here (control lines, baud rate, etc.) */ + /* FIXME!!! */ + + return (0); +} + + +static void whiteheat_close(struct usb_serial_port *port, struct file * filp) +{ + dbg("whiteheat_close port %d", port->number); + + /* Need to change the control lines here */ + /* FIXME */ + + /* shutdown our bulk reads and writes */ + usb_unlink_urb (port->write_urb); + usb_unlink_urb (port->read_urb); + port->active = 0; +} + + +static void whiteheat_set_termios (struct usb_serial_port *port, struct termios *old_termios) +{ + unsigned int cflag = port->tty->termios->c_cflag; + + dbg("whiteheat_set_termios port %d", port->number); + + /* check that they really want us to change something */ + if (old_termios) { + if ((cflag == old_termios->c_cflag) && + (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) { + dbg("nothing to change..."); + return; + } + } + + /* do the parsing of the cflag to see what to set the line to */ + /* FIXME!! */ + + return; +} + +static void whiteheat_throttle (struct usb_serial_port *port) +{ + dbg("whiteheat_throttle port %d", port->number); + + /* Change the control signals */ + /* FIXME!!! */ + + return; +} + + +static void whiteheat_unthrottle (struct usb_serial_port *port) +{ + dbg("whiteheat_unthrottle port %d", port->number); + + /* Change the control signals */ + /* FIXME!!! */ + + return; +} + + +/* steps to download the firmware to the WhiteHEAT device: + - hold the reset (by writing to the reset bit of the CPUCS register) + - download the VEND_AX.HEX file to the chip using VENDOR_REQUEST-ANCHOR_LOAD + - release the reset (by writing to the CPUCS register) + - download the WH.HEX file for all addresses greater than 0x1b3f using + VENDOR_REQUEST-ANCHOR_EXTERNAL_RAM_LOAD + - hold the reset + - download the WH.HEX file for all addresses less than 0x1b40 using + VENDOR_REQUEST_ANCHOR_LOAD + - release the reset + - device renumerated itself and comes up as new device id with all + firmware download completed. +*/ +static int whiteheat_startup (struct usb_serial *serial) +{ + int response; + const struct whiteheat_hex_record *record; + + dbg("whiteheat_startup"); + + response = ezusb_set_reset (serial, 1); + + record = &whiteheat_loader[0]; + while (record->address != 0xffff) { + response = ezusb_writememory (serial, record->address, + (unsigned char *)record->data, record->data_size, 0xa0); + if (response < 0) { + err("ezusb_writememory failed for loader (%d %04X %p %d)", + response, record->address, record->data, record->data_size); + break; + } + ++record; + } + + response = ezusb_set_reset (serial, 0); + + record = &whiteheat_firmware[0]; + while (record->address < 0x1b40) { + ++record; + } + while (record->address != 0xffff) { + response = ezusb_writememory (serial, record->address, + (unsigned char *)record->data, record->data_size, 0xa3); + if (response < 0) { + err("ezusb_writememory failed for first firmware step (%d %04X %p %d)", + response, record->address, record->data, record->data_size); + break; + } + ++record; + } + + response = ezusb_set_reset (serial, 1); + + record = &whiteheat_firmware[0]; + while (record->address < 0x1b40) { + response = ezusb_writememory (serial, record->address, + (unsigned char *)record->data, record->data_size, 0xa0); + if (response < 0) { + err("ezusb_writememory failed for second firmware step (%d %04X %p %d)", + response, record->address, record->data, record->data_size); + break; + } + ++record; + } + + response = ezusb_set_reset (serial, 0); + + /* we want this device to fail to have a driver assigned to it. */ + return (1); +} + +#endif /* CONFIG_USB_SERIAL_WHITEHEAT */ + + diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/serial/whiteheat.h linux/drivers/usb/serial/whiteheat.h --- v2.3.99-pre3/linux/drivers/usb/serial/whiteheat.h Fri Mar 10 16:40:45 2000 +++ linux/drivers/usb/serial/whiteheat.h Wed Dec 31 16:00:00 1969 @@ -1,1542 +0,0 @@ -/***************************************************************************** - * - * whiteheat.h -- ConnectTech WhiteHEAT Firmware. - * - * Copyright (C) 2000 ConnectTech Inc (http://www.connecttech.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. - * - * (01/16/2000) gkh - * Fixed my intel hex processing tool, so now the firmware actually - * matches the original file (this was causing a few problems...) - * - * (01/15/2000) gkh - * Added debug loader firmware if DEBUG is #defined: - * Port 1 LED flashes when the vend_ax program is running - * Port 2 LED flashes when any SETUP command arrives - * Port 3 LED flashes when any valid VENDOR request occurs - * Port 4 LED flashes when the EXTERNAL RAM DOWNLOAD request occurs - * - * version 1.0 (01/09/2000) gkh - * Original firmware from ConnectTech massaged a little to be program - * readable. - * - *****************************************************************************/ - -#define whiteheat_DATE "20000106" - -struct whiteheat_hex_record { - __u16 address; - __u8 data_size; - __u8 data[16]; -}; - -static const struct whiteheat_hex_record whiteheat_firmware[] = { -{ 0x0000, 3, {0x02, 0x91, 0xc9} }, -{ 0x0003, 3, {0x02, 0x13, 0x12} }, -{ 0x000b, 3, {0x02, 0x0a, 0x8d} }, -{ 0x0033, 3, {0x02, 0x07, 0x84} }, -{ 0x0043, 3, {0x02, 0x09, 0x00} }, -{ 0x0053, 3, {0x02, 0x0f, 0x6e} }, -{ 0x005b, 3, {0x02, 0x11, 0xb9} }, -{ 0x0300, 16, {0x90, 0x7f, 0xe9, 0xe0, 0x70, 0x03, 0x02, 0x04, 0x03, 0x14, 0x70, 0x03, 0x02, 0x04, 0x77, 0x24} }, -{ 0x0310, 16, {0xfe, 0x70, 0x03, 0x02, 0x04, 0xca, 0x24, 0xfb, 0x70, 0x03, 0x02, 0x03, 0xf4, 0x14, 0x70, 0x03} }, -{ 0x0320, 16, {0x02, 0x03, 0xe2, 0x14, 0x70, 0x03, 0x02, 0x03, 0xca, 0x14, 0x70, 0x03, 0x02, 0x03, 0xd9, 0x24} }, -{ 0x0330, 16, {0x05, 0x60, 0x03, 0x02, 0x05, 0x19, 0x90, 0x7f, 0xeb, 0xe0, 0x24, 0xfe, 0x60, 0x16, 0x14, 0x60} }, -{ 0x0340, 16, {0x36, 0x24, 0x02, 0x70, 0x7b, 0x74, 0x12, 0x90, 0x7f, 0xd4, 0xf0, 0x74, 0x00, 0x90, 0x7f, 0xd5} }, -{ 0x0350, 16, {0xf0, 0x02, 0x05, 0x20, 0x90, 0x7f, 0xea, 0xe0, 0xff, 0x12, 0x09, 0x58, 0xea, 0x49, 0x60, 0x0d} }, -{ 0x0360, 16, {0xea, 0x90, 0x7f, 0xd4, 0xf0, 0xe9, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x05, 0x20, 0x90, 0x7f, 0xb4} }, -{ 0x0370, 16, {0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0x20, 0x90, 0x7f, 0xea, 0xe0, 0xff, 0x12, 0x08, 0xa9, 0xea} }, -{ 0x0380, 16, {0x49, 0x60, 0x33, 0x12, 0x9a, 0x48, 0xf5, 0x5e, 0x90, 0x7f, 0xee, 0xe0, 0xff, 0xe5, 0x5e, 0xd3} }, -{ 0x0390, 16, {0x9f, 0x40, 0x03, 0xe0, 0xf5, 0x5e, 0xe5, 0x5e, 0xd3, 0x94, 0x40, 0x40, 0x03, 0x75, 0x5e, 0x40} }, -{ 0x03a0, 16, {0xae, 0x02, 0xaf, 0x01, 0x7c, 0x7f, 0x7d, 0x00, 0xab, 0x5e, 0x12, 0x1b, 0x0c, 0x90, 0x7f, 0xb5} }, -{ 0x03b0, 16, {0xe5, 0x5e, 0xf0, 0x02, 0x05, 0x20, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0x20} }, -{ 0x03c0, 16, {0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0x20, 0x90, 0x7f, 0x00, 0xe5, 0x21, 0xf0} }, -{ 0x03d0, 16, {0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x02, 0x05, 0x20, 0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x21, 0x02} }, -{ 0x03e0, 16, {0x05, 0x20, 0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x31, 0xd2, 0x02, 0x43, 0x88, 0x10, 0xd2, 0xeb, 0xd2} }, -{ 0x03f0, 16, {0xa8, 0x02, 0x05, 0x20, 0x90, 0x7f, 0x00, 0xe5, 0x31, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0} }, -{ 0x0400, 16, {0x02, 0x05, 0x20, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0x7f, 0x60, 0x24, 0x14, 0x60, 0x31, 0x24, 0x02} }, -{ 0x0410, 16, {0x70, 0x5b, 0xa2, 0x00, 0xe4, 0x33, 0xff, 0x25, 0xe0, 0xff, 0xa2, 0x05, 0xe4, 0x33, 0x4f, 0x90} }, -{ 0x0420, 16, {0x7f, 0x00, 0xf0, 0xe4, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0x20, 0xe4} }, -{ 0x0430, 16, {0x90, 0x7f, 0x00, 0xf0, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0x20, 0x90} }, -{ 0x0440, 16, {0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25} }, -{ 0x0450, 16, {0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe0, 0x54, 0x01, 0x90, 0x7f, 0x00} }, -{ 0x0460, 16, {0xf0, 0xe4, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0x20, 0x90, 0x7f, 0xb4} }, -{ 0x0470, 16, {0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0x20, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0xfe, 0x60, 0x1d, 0x24} }, -{ 0x0480, 16, {0x02, 0x60, 0x03, 0x02, 0x05, 0x20, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x05, 0xc2, 0x00, 0x02} }, -{ 0x0490, 16, {0x05, 0x20, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0x20, 0x90, 0x7f, 0xea, 0xe0} }, -{ 0x04a0, 16, {0x70, 0x1f, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54} }, -{ 0x04b0, 16, {0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe4, 0xf0, 0x80} }, -{ 0x04c0, 16, {0x5f, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x56, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0xfe} }, -{ 0x04d0, 16, {0x60, 0x18, 0x24, 0x02, 0x70, 0x4a, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x04, 0xd2, 0x00, 0x80} }, -{ 0x04e0, 16, {0x3f, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x36, 0x90, 0x7f, 0xea, 0xe0, 0x70, 0x20} }, -{ 0x04f0, 16, {0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f} }, -{ 0x0500, 16, {0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0x74, 0x01, 0xf0, 0x80, 0x10} }, -{ 0x0510, 16, {0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x07, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0} }, -{ 0x0520, 7, {0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0} }, -{ 0x0527, 1, {0x22} }, -{ 0x0528, 16, {0x75, 0x5a, 0xff, 0x75, 0x59, 0xff, 0x75, 0x58, 0x0f, 0x75, 0x57, 0x00, 0xd2, 0x03, 0xc2, 0x06} }, -{ 0x0538, 16, {0xc2, 0x02, 0xc2, 0x00, 0xc2, 0x05, 0xc2, 0x01, 0x90, 0x02, 0x9e, 0x74, 0x19, 0xf0, 0xe4, 0x90} }, -{ 0x0548, 16, {0x01, 0x5b, 0xf0, 0xc2, 0x04, 0x90, 0x01, 0x5e, 0xf0, 0xa3, 0xf0, 0xc2, 0xaf, 0xc2, 0xa8, 0x12} }, -{ 0x0558, 16, {0x0a, 0xfa, 0xe4, 0x90, 0x02, 0x4d, 0xf0, 0x90, 0x01, 0x00, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3} }, -{ 0x0568, 16, {0xf0, 0xa3, 0xf0, 0xa3, 0x74, 0x10, 0xf0, 0xa3, 0x74, 0x01, 0xf0, 0xa3, 0x74, 0x08, 0xf0, 0x7e} }, -{ 0x0578, 16, {0x01, 0x7f, 0x00, 0x12, 0x19, 0xc1, 0x75, 0x5c, 0x12, 0x75, 0x5d, 0x0a, 0x90, 0x01, 0x0b, 0xe0} }, -{ 0x0588, 16, {0xff, 0x05, 0x5d, 0xe5, 0x5d, 0xac, 0x5c, 0x70, 0x02, 0x05, 0x5c, 0x14, 0xf5, 0x82, 0x8c, 0x83} }, -{ 0x0598, 16, {0xef, 0xf0, 0x90, 0x01, 0x0c, 0xe0, 0x44, 0x80, 0xff, 0x05, 0x5d, 0xe5, 0x5d, 0xac, 0x5c, 0x70} }, -{ 0x05a8, 16, {0x02, 0x05, 0x5c, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x90, 0x01, 0x0d, 0xe0, 0xff, 0x05} }, -{ 0x05b8, 16, {0x5d, 0xe5, 0x5d, 0xac, 0x5c, 0x70, 0x02, 0x05, 0x5c, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0} }, -{ 0x05c8, 16, {0x90, 0x01, 0x0e, 0xe0, 0xff, 0x05, 0x5d, 0xe5, 0x5d, 0xac, 0x5c, 0x70, 0x02, 0x05, 0x5c, 0x14} }, -{ 0x05d8, 16, {0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x90, 0x12, 0x0a, 0xe4, 0x93, 0xff, 0x74, 0x01, 0x93, 0x90} }, -{ 0x05e8, 16, {0x01, 0x1c, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0x01, 0x1c, 0xe0, 0xff, 0xa3, 0xe0, 0xfe, 0xef} }, -{ 0x05f8, 16, {0x6e, 0xff, 0x90, 0x01, 0x1c, 0xf0, 0xa3, 0xe0, 0x6f, 0xff, 0xf0, 0x90, 0x01, 0x1c, 0xe0, 0x6f} }, -{ 0x0608, 16, {0xf0, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xe4, 0xfc, 0xfd, 0x75, 0x62, 0x10, 0x75, 0x63, 0x02, 0x75} }, -{ 0x0618, 16, {0x64, 0x12, 0x75, 0x65, 0xac, 0x12, 0x8e, 0x35, 0x75, 0x5c, 0x12, 0x75, 0x5d, 0xb2, 0x90, 0x01} }, -{ 0x0628, 16, {0x0d, 0xe0, 0xff, 0x05, 0x5d, 0xe5, 0x5d, 0xac, 0x5c, 0x70, 0x02, 0x05, 0x5c, 0x14, 0xf5, 0x82} }, -{ 0x0638, 16, {0x8c, 0x83, 0xef, 0xf0, 0x90, 0x01, 0x0e, 0xe0, 0xff, 0x05, 0x5d, 0xe5, 0x5d, 0xac, 0x5c, 0x70} }, -{ 0x0648, 16, {0x02, 0x05, 0x5c, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x90, 0x7f, 0x92, 0xe0, 0xff, 0xc4} }, -{ 0x0658, 16, {0x54, 0x0f, 0x24, 0x41, 0xff, 0x05, 0x5d, 0xe5, 0x5d, 0xac, 0x5c, 0x70, 0x02, 0x05, 0x5c, 0x14} }, -{ 0x0668, 16, {0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x05, 0x5d, 0xe5, 0x5d, 0xae, 0x5c, 0x70, 0x02, 0x05, 0x5c} }, -{ 0x0678, 16, {0x14, 0xf5, 0x82, 0x8e, 0x83, 0xe4, 0xf0, 0x75, 0x82, 0x10, 0x75, 0x83, 0x01, 0xe0, 0xfc, 0xa3} }, -{ 0x0688, 16, {0xe0, 0xfd, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x90, 0x01, 0x18, 0x12, 0x9b, 0xfb, 0x7e, 0x01} }, -{ 0x0698, 16, {0x7f, 0x18, 0x12, 0x84, 0x61, 0x90, 0x01, 0x18, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe} }, -{ 0x06a8, 16, {0xa3, 0xe0, 0xff, 0x75, 0x62, 0x0a, 0x75, 0x63, 0x06, 0x75, 0x64, 0x12, 0x75, 0x65, 0xb8, 0x12} }, -{ 0x06b8, 16, {0x8e, 0x35, 0xd2, 0xe8, 0x43, 0xd8, 0x20, 0x90, 0x7f, 0xab, 0x74, 0xff, 0xf0, 0x53, 0x91, 0xef} }, -{ 0x06c8, 16, {0x90, 0x7f, 0xaf, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xae, 0xe0, 0x44, 0x1f, 0xf0, 0xd2, 0xaf} }, -{ 0x06d8, 16, {0x20, 0x01, 0x2e, 0x20, 0x01, 0x2b, 0xa2, 0x03, 0x92, 0x07, 0x12, 0x09, 0xa7, 0x75, 0x56, 0x50} }, -{ 0x06e8, 16, {0x75, 0x55, 0x6d, 0x75, 0x54, 0x33, 0x75, 0x53, 0x00, 0x20, 0x01, 0xe4, 0x7f, 0xff, 0x7e, 0xff} }, -{ 0x06f8, 16, {0x7d, 0xff, 0x7c, 0xff, 0x78, 0x53, 0x12, 0x9b, 0xe4, 0xec, 0x4d, 0x4e, 0x4f, 0x60, 0xd1, 0x80} }, -{ 0x0708, 16, {0xe8, 0x30, 0x01, 0x05, 0x12, 0x03, 0x00, 0xc2, 0x01, 0x30, 0x06, 0x0d, 0x12, 0x08, 0xfb, 0x50} }, -{ 0x0718, 16, {0x06, 0x12, 0x0a, 0x00, 0x12, 0x09, 0xf4, 0xc2, 0x06, 0x12, 0x90, 0x58, 0x12, 0x98, 0x7d, 0xe4} }, -{ 0x0728, 16, {0xff, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xfe, 0x90, 0x01, 0x5b} }, -{ 0x0738, 16, {0xe0, 0x5e, 0x60, 0x14, 0x74, 0x27, 0x2f, 0xf8, 0xe6, 0xd3, 0x94, 0x0a, 0x40, 0x04, 0x7e, 0x01} }, -{ 0x0748, 16, {0x80, 0x02, 0x7e, 0x00, 0x8e, 0x5b, 0x80, 0x03, 0x75, 0x5b, 0x01, 0x74, 0x68, 0x2f, 0xf5, 0x82} }, -{ 0x0758, 16, {0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe5, 0x5b, 0xf0, 0x0f, 0xbf, 0x04, 0xc5, 0xe5, 0x2b, 0xd3, 0x94} }, -{ 0x0768, 16, {0x0a, 0x40, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0x90, 0x20, 0x6c, 0xef, 0xf0, 0x90, 0x02} }, -{ 0x0778, 11, {0x4d, 0xe0, 0x64, 0x0f, 0x70, 0x8b, 0x12, 0x93, 0x50, 0x80, 0x86} }, -{ 0x0783, 1, {0x22} }, -{ 0x0784, 4, {0x53, 0xd8, 0xef, 0x32} }, -{ 0x0788, 16, {0xe4, 0x90, 0x7f, 0x9c, 0xf0, 0x7f, 0x0a, 0xfe, 0x12, 0x08, 0x92, 0x90, 0x7f, 0x96, 0x74, 0x89} }, -{ 0x0798, 16, {0xf0, 0x90, 0x7f, 0x9c, 0x74, 0xcf, 0xf0, 0x7f, 0xf4, 0x7e, 0x01, 0x12, 0x08, 0x92, 0x90, 0x7f} }, -{ 0x07a8, 16, {0x96, 0xe0, 0x54, 0xfe, 0xf0, 0x7f, 0x0a, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x7f, 0x02, 0x7d, 0xff} }, -{ 0x07b8, 16, {0x12, 0x11, 0x4b, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x02} }, -{ 0x07c8, 16, {0xf0, 0xe0, 0x54, 0x7f, 0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x90, 0x7f, 0x96, 0xe0} }, -{ 0x07d8, 16, {0x44, 0x40, 0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x90, 0x7f, 0x96, 0xe0, 0x54, 0xbf} }, -{ 0x07e8, 16, {0xf0, 0x7f, 0x32, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x40, 0xf0, 0x7f} }, -{ 0x07f8, 7, {0x32, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x22} }, -{ 0x07ff, 16, {0x90, 0x7f, 0x96, 0xe0, 0x54, 0xfd, 0xf0, 0xe0, 0x44, 0x80, 0xf0, 0x7f, 0x0a, 0x7e, 0x00, 0x12} }, -{ 0x080f, 16, {0x08, 0x92, 0x7f, 0x02, 0xe4, 0xfd, 0x12, 0x11, 0x4b, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x08, 0x92} }, -{ 0x081f, 16, {0x90, 0x7f, 0x96, 0xe0, 0x54, 0xbf, 0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x90, 0x7f} }, -{ 0x082f, 16, {0x96, 0xe0, 0x44, 0x04, 0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x90, 0x7f, 0x96, 0xe0} }, -{ 0x083f, 16, {0x54, 0xf7, 0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x01} }, -{ 0x084f, 12, {0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x12, 0x0a, 0x00, 0x22} }, -{ 0x085b, 16, {0x90, 0x11, 0xef, 0xe4, 0x93, 0x70, 0x2f, 0x90, 0x7f, 0x93, 0x74, 0x30, 0xf0, 0x90, 0x7f, 0x94} }, -{ 0x086b, 16, {0x74, 0x3c, 0xf0, 0x90, 0x7f, 0x95, 0x74, 0xc6, 0xf0, 0xe4, 0x90, 0x7f, 0x97, 0xf0, 0x90, 0x7f} }, -{ 0x087b, 16, {0x9d, 0x74, 0x02, 0xf0, 0x90, 0x7f, 0xe2, 0x74, 0x12, 0xf0, 0x12, 0x07, 0x88, 0x75, 0x82, 0xef} }, -{ 0x088b, 7, {0x75, 0x83, 0x11, 0x74, 0xff, 0xf0, 0x22} }, -{ 0x0892, 16, {0x8e, 0x6d, 0x8f, 0x6e, 0xe5, 0x6e, 0x15, 0x6e, 0xae, 0x6d, 0x70, 0x02, 0x15, 0x6d, 0x4e, 0x60} }, -{ 0x08a2, 7, {0x05, 0x12, 0x08, 0xea, 0x80, 0xee, 0x22} }, -{ 0x08a9, 2, {0x8f, 0x5f} }, -{ 0x08ab, 16, {0xe4, 0xf5, 0x60, 0x75, 0x61, 0xff, 0x75, 0x62, 0x12, 0x75, 0x63, 0x6a, 0xab, 0x61, 0xaa, 0x62} }, -{ 0x08bb, 16, {0xa9, 0x63, 0x90, 0x00, 0x01, 0x12, 0x9a, 0x61, 0xb4, 0x03, 0x1d, 0xaf, 0x60, 0x05, 0x60, 0xef} }, -{ 0x08cb, 16, {0xb5, 0x5f, 0x01, 0x22, 0x12, 0x9a, 0x48, 0x7e, 0x00, 0x29, 0xff, 0xee, 0x3a, 0xa9, 0x07, 0x75} }, -{ 0x08db, 14, {0x61, 0xff, 0xf5, 0x62, 0x89, 0x63, 0x80, 0xd4, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} }, -{ 0x08e9, 1, {0x22} }, -{ 0x08ea, 16, {0x74, 0x00, 0xf5, 0x86, 0x90, 0xfd, 0xa5, 0x7c, 0x05, 0xa3, 0xe5, 0x82, 0x45, 0x83, 0x70, 0xf9} }, -{ 0x08fa, 1, {0x22} }, -{ 0x08fb, 5, {0x12, 0x07, 0xff, 0xd3, 0x22} }, -{ 0x0900, 16, {0x02, 0x0b, 0x17, 0x00, 0x02, 0x0b, 0x4a, 0x00, 0x02, 0x0b, 0x2f, 0x00, 0x02, 0x0b, 0x89, 0x00} }, -{ 0x0910, 16, {0x02, 0x0b, 0x73, 0x00, 0x02, 0x09, 0xf9, 0x00, 0x02, 0x09, 0xfa, 0x00, 0x02, 0x09, 0xfb, 0x00} }, -{ 0x0920, 16, {0x02, 0x0b, 0xa4, 0x00, 0x02, 0x0c, 0x78, 0x00, 0x02, 0x0b, 0xd9, 0x00, 0x02, 0x0c, 0xc5, 0x00} }, -{ 0x0930, 16, {0x02, 0x0c, 0x0e, 0x00, 0x02, 0x0d, 0x12, 0x00, 0x02, 0x0c, 0x43, 0x00, 0x02, 0x0d, 0x5f, 0x00} }, -{ 0x0940, 16, {0x02, 0x09, 0xfc, 0x00, 0x02, 0x09, 0xfe, 0x00, 0x02, 0x09, 0xfd, 0x00, 0x02, 0x09, 0xff, 0x00} }, -{ 0x0950, 8, {0x02, 0x0d, 0xac, 0x00, 0x02, 0x0d, 0xc2, 0x00} }, -{ 0x0958, 16, {0xe4, 0xfe, 0x75, 0x61, 0xff, 0x75, 0x62, 0x12, 0x75, 0x63, 0x12, 0xab, 0x61, 0xaa, 0x62, 0xa9} }, -{ 0x0968, 16, {0x63, 0x90, 0x00, 0x01, 0x12, 0x9a, 0x61, 0x64, 0x02, 0x70, 0x2d, 0xad, 0x06, 0x0e, 0xed, 0xb5} }, -{ 0x0978, 16, {0x07, 0x01, 0x22, 0x90, 0x00, 0x02, 0x12, 0x9a, 0xba, 0x85, 0xf0, 0x5f, 0xf5, 0x60, 0x62, 0x5f} }, -{ 0x0988, 16, {0xe5, 0x5f, 0x62, 0x60, 0xe5, 0x60, 0x62, 0x5f, 0x29, 0xfd, 0xe5, 0x5f, 0x3a, 0xa9, 0x05, 0x75} }, -{ 0x0998, 14, {0x61, 0xff, 0xf5, 0x62, 0x89, 0x63, 0x80, 0xc3, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} }, -{ 0x09a6, 1, {0x22} }, -{ 0x09a7, 16, {0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x30, 0x07, 0x04, 0xe0, 0x44} }, -{ 0x09b7, 16, {0x02, 0xf0, 0x7f, 0xd0, 0x7e, 0x07, 0x12, 0x08, 0x92, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xf7, 0xf0} }, -{ 0x09c7, 5, {0xe0, 0x44, 0x04, 0xf0, 0x22} }, -{ 0x09cc, 16, {0x53, 0x8e, 0xf7, 0xe5, 0x89, 0x54, 0xf1, 0x44, 0x01, 0xf5, 0x89, 0x75, 0x8c, 0xb1, 0xd2, 0xa9} }, -{ 0x09dc, 16, {0x75, 0x98, 0x40, 0x75, 0xcb, 0xff, 0x75, 0xca, 0xf3, 0x75, 0xc8, 0x34, 0xe4, 0xff, 0x7f, 0x05} }, -{ 0x09ec, 7, {0x78, 0x27, 0xe4, 0xf6, 0x08, 0xdf, 0xfc} }, -{ 0x09f3, 1, {0x22} }, -{ 0x09f4, 5, {0x12, 0x07, 0x88, 0xd3, 0x22} }, -{ 0x09f9, 1, {0x32} }, -{ 0x09fa, 1, {0x32} }, -{ 0x09fb, 1, {0x32} }, -{ 0x09fc, 1, {0x32} }, -{ 0x09fd, 1, {0x32} }, -{ 0x09fe, 1, {0x32} }, -{ 0x09ff, 1, {0x32} }, -{ 0x0a00, 9, {0x90, 0x7f, 0xd6, 0xe0, 0x44, 0x80, 0xf0, 0x80, 0x74} }, -{ 0x0a7d, 16, {0x43, 0x87, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22} }, -{ 0x0a8d, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x00, 0xc0, 0x00, 0xc0, 0x06, 0xc0} }, -{ 0x0a9d, 1, {0x07} }, -{ 0x0a9e, 16, {0x30, 0x04, 0x16, 0x75, 0x8c, 0xf8, 0x75, 0x8a, 0x30, 0x7f, 0x2f, 0xae, 0x07, 0x1f, 0xee, 0x60} }, -{ 0x0aae, 16, {0x3c, 0x90, 0x20, 0x00, 0x74, 0x55, 0xf0, 0x80, 0xf2, 0x75, 0x8c, 0xb1, 0x7f, 0x27, 0xef, 0xd3} }, -{ 0x0abe, 16, {0x94, 0x2b, 0x50, 0x09, 0xa8, 0x07, 0xe6, 0x60, 0x01, 0x16, 0x0f, 0x80, 0xf1, 0x90, 0x02, 0x9e} }, -{ 0x0ace, 16, {0xe0, 0x60, 0x02, 0x14, 0xf0, 0x90, 0x01, 0x5e, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x0e, 0x90} }, -{ 0x0ade, 13, {0x01, 0x5f, 0xe0, 0x24, 0xff, 0xf0, 0x90, 0x01, 0x5e, 0xe0, 0x34, 0xff, 0xf0} }, -{ 0x0aeb, 15, {0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x00, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, -{ 0x0afa, 16, {0xd2, 0x00, 0x75, 0x8e, 0x10, 0xe4, 0x90, 0x7f, 0x92, 0xf0, 0x12, 0x0f, 0x72, 0x12, 0x08, 0x5b} }, -{ 0x0b0a, 13, {0x12, 0x0e, 0x0f, 0x12, 0x8f, 0x06, 0x12, 0x11, 0x9c, 0x12, 0x09, 0xcc, 0x22} }, -{ 0x0b17, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xd2, 0x01, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x01} }, -{ 0x0b27, 8, {0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, -{ 0x0b2f, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x90, 0x7f, 0xc4, 0xe4, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f} }, -{ 0x0b3f, 11, {0xab, 0x74, 0x04, 0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, -{ 0x0b4a, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x02, 0xf0, 0x90} }, -{ 0x0b5a, 16, {0x7f, 0xd8, 0xe0, 0x70, 0x0d, 0x90, 0x7f, 0xd9, 0xe0, 0x70, 0x07, 0xe5, 0x2b, 0x70, 0x03, 0x75} }, -{ 0x0b6a, 9, {0x2b, 0x14, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, -{ 0x0b73, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x10, 0xf0, 0xd0} }, -{ 0x0b83, 6, {0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, -{ 0x0b89, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x30, 0x02, 0x02, 0xd2, 0x06, 0x53, 0x91, 0xef, 0x90, 0x7f} }, -{ 0x0b99, 11, {0xab, 0x74, 0x08, 0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, -{ 0x0ba4, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xa9, 0x74, 0x02, 0xf0, 0xe5} }, -{ 0x0bb4, 16, {0x30, 0x30, 0xe0, 0x13, 0xe5, 0x3b, 0x30, 0xe0, 0x07, 0x90, 0x20, 0x04, 0xe0, 0x44, 0x01, 0xf0} }, -{ 0x0bc4, 16, {0x90, 0x20, 0x01, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x2b, 0x70, 0x03, 0x75, 0x2b, 0x14, 0xd0, 0x82} }, -{ 0x0bd4, 5, {0xd0, 0x83, 0xd0, 0xe0, 0x32} }, -{ 0x0bd9, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xa9, 0x74, 0x04, 0xf0, 0xe5} }, -{ 0x0be9, 16, {0x30, 0x30, 0xe1, 0x13, 0xe5, 0x3b, 0x30, 0xe1, 0x07, 0x90, 0x20, 0x0c, 0xe0, 0x44, 0x01, 0xf0} }, -{ 0x0bf9, 16, {0x90, 0x20, 0x09, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x2b, 0x70, 0x03, 0x75, 0x2b, 0x14, 0xd0, 0x82} }, -{ 0x0c09, 5, {0xd0, 0x83, 0xd0, 0xe0, 0x32} }, -{ 0x0c0e, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xa9, 0x74, 0x08, 0xf0, 0xe5} }, -{ 0x0c1e, 16, {0x30, 0x30, 0xe2, 0x13, 0xe5, 0x3b, 0x30, 0xe2, 0x07, 0x90, 0x20, 0x14, 0xe0, 0x44, 0x01, 0xf0} }, -{ 0x0c2e, 16, {0x90, 0x20, 0x11, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x2b, 0x70, 0x03, 0x75, 0x2b, 0x14, 0xd0, 0x82} }, -{ 0x0c3e, 5, {0xd0, 0x83, 0xd0, 0xe0, 0x32} }, -{ 0x0c43, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xa9, 0x74, 0x10, 0xf0, 0xe5} }, -{ 0x0c53, 16, {0x30, 0x30, 0xe3, 0x13, 0xe5, 0x3b, 0x30, 0xe3, 0x07, 0x90, 0x20, 0x1c, 0xe0, 0x44, 0x01, 0xf0} }, -{ 0x0c63, 16, {0x90, 0x20, 0x19, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x2b, 0x70, 0x03, 0x75, 0x2b, 0x14, 0xd0, 0x82} }, -{ 0x0c73, 5, {0xd0, 0x83, 0xd0, 0xe0, 0x32} }, -{ 0x0c78, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x53} }, -{ 0x0c88, 16, {0x91, 0xef, 0x90, 0x7f, 0xaa, 0x74, 0x02, 0xf0, 0xe5, 0x30, 0x20, 0xe0, 0x06, 0x90, 0x7f, 0xc7} }, -{ 0x0c98, 16, {0xf0, 0x80, 0x16, 0xe5, 0x3b, 0x30, 0xe0, 0x0a, 0x90, 0x7f, 0xc7, 0xe0, 0x90, 0x02, 0x96, 0xf0} }, -{ 0x0ca8, 16, {0x80, 0x07, 0x90, 0x20, 0x01, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x2b, 0x70, 0x03, 0x75, 0x2b, 0x14} }, -{ 0x0cb8, 13, {0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, -{ 0x0cc5, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x53} }, -{ 0x0cd5, 16, {0x91, 0xef, 0x90, 0x7f, 0xaa, 0x74, 0x04, 0xf0, 0xe5, 0x30, 0x20, 0xe1, 0x06, 0x90, 0x7f, 0xc9} }, -{ 0x0ce5, 16, {0xf0, 0x80, 0x16, 0xe5, 0x3b, 0x30, 0xe1, 0x0a, 0x90, 0x7f, 0xc9, 0xe0, 0x90, 0x02, 0x97, 0xf0} }, -{ 0x0cf5, 16, {0x80, 0x07, 0x90, 0x20, 0x09, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x2b, 0x70, 0x03, 0x75, 0x2b, 0x14} }, -{ 0x0d05, 13, {0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, -{ 0x0d12, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x53} }, -{ 0x0d22, 16, {0x91, 0xef, 0x90, 0x7f, 0xaa, 0x74, 0x08, 0xf0, 0xe5, 0x30, 0x20, 0xe2, 0x06, 0x90, 0x7f, 0xcb} }, -{ 0x0d32, 16, {0xf0, 0x80, 0x16, 0xe5, 0x3b, 0x30, 0xe2, 0x0a, 0x90, 0x7f, 0xcb, 0xe0, 0x90, 0x02, 0x98, 0xf0} }, -{ 0x0d42, 16, {0x80, 0x07, 0x90, 0x20, 0x11, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x2b, 0x70, 0x03, 0x75, 0x2b, 0x14} }, -{ 0x0d52, 13, {0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, -{ 0x0d5f, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x53} }, -{ 0x0d6f, 16, {0x91, 0xef, 0x90, 0x7f, 0xaa, 0x74, 0x10, 0xf0, 0xe5, 0x30, 0x20, 0xe3, 0x06, 0x90, 0x7f, 0xcd} }, -{ 0x0d7f, 16, {0xf0, 0x80, 0x16, 0xe5, 0x3b, 0x30, 0xe3, 0x0a, 0x90, 0x7f, 0xcd, 0xe0, 0x90, 0x02, 0x99, 0xf0} }, -{ 0x0d8f, 16, {0x80, 0x07, 0x90, 0x20, 0x19, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x2b, 0x70, 0x03, 0x75, 0x2b, 0x14} }, -{ 0x0d9f, 13, {0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, -{ 0x0dac, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xa9, 0x74, 0x80, 0xf0, 0xd0} }, -{ 0x0dbc, 6, {0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, -{ 0x0dc2, 16, {0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x00, 0xc0, 0x00, 0xc0} }, -{ 0x0dd2, 16, {0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0x53, 0x91, 0xef} }, -{ 0x0de2, 16, {0x90, 0x7f, 0xaa, 0x74, 0x80, 0xf0, 0x7e, 0x7b, 0x7f, 0x40, 0x12, 0x8c, 0xfb, 0x90, 0x7f, 0xd3} }, -{ 0x0df2, 16, {0xe4, 0xf0, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01} }, -{ 0x0e02, 13, {0xd0, 0x00, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32} }, -{ 0x0e0f, 16, {0x90, 0x01, 0x20, 0x12, 0x9c, 0x07, 0x00, 0x00, 0x25, 0x80, 0x90, 0x01, 0x24, 0x74, 0x08, 0xf0} }, -{ 0x0e1f, 16, {0xa3, 0x74, 0x01, 0xf0, 0xa3, 0x74, 0x6e, 0xf0, 0xa3, 0xf0, 0xe4, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3} }, -{ 0x0e2f, 16, {0xf0, 0xa3, 0xf0, 0x90, 0x01, 0x1e, 0xf0, 0x90, 0x01, 0x1e, 0xe0, 0xff, 0xc3, 0x94, 0x04, 0x50} }, -{ 0x0e3f, 16, {0x13, 0xef, 0x04, 0xa3, 0xf0, 0x7e, 0x01, 0x7f, 0x1f, 0x12, 0x84, 0xf4, 0x90, 0x01, 0x1e, 0xe0} }, -{ 0x0e4f, 16, {0x04, 0xf0, 0x80, 0xe3, 0xe4, 0xf5, 0x26, 0x90, 0x01, 0x1e, 0xf0, 0x90, 0x01, 0x1e, 0xe0, 0xff} }, -{ 0x0e5f, 16, {0xc3, 0x94, 0x04, 0x50, 0x1a, 0x74, 0x96, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe4} }, -{ 0x0e6f, 16, {0xf0, 0x74, 0x22, 0x2f, 0xf8, 0xe4, 0xf6, 0x90, 0x01, 0x1e, 0xe0, 0x04, 0xf0, 0x80, 0xdc, 0xe4} }, -{ 0x0e7f, 16, {0xf5, 0x30, 0xe5, 0xc0, 0x60, 0x2f, 0x90, 0x01, 0x1e, 0x74, 0x01, 0xf0, 0x90, 0x01, 0x1e, 0xe0} }, -{ 0x0e8f, 16, {0xff, 0xd3, 0x94, 0x04, 0x50, 0x1f, 0xef, 0x14, 0xff, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02} }, -{ 0x0e9f, 16, {0xc3, 0x33, 0xd8, 0xfc, 0x42, 0x30, 0x7e, 0x01, 0x7f, 0x1e, 0x12, 0x82, 0xea, 0x90, 0x01, 0x1e} }, -{ 0x0eaf, 16, {0xe0, 0x04, 0xf0, 0x80, 0xd7, 0xe4, 0xf5, 0x3a, 0x90, 0x01, 0x1e, 0xf0, 0x90, 0x01, 0x1e, 0xe0} }, -{ 0x0ebf, 16, {0xff, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0, 0x54} }, -{ 0x0ecf, 16, {0xf0, 0xfe, 0x74, 0x63, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x01, 0xf5, 0x83, 0xee, 0xf0, 0x74, 0x36} }, -{ 0x0edf, 16, {0x2f, 0xf8, 0xa6, 0x06, 0x74, 0x32, 0x2f, 0xf8, 0xe4, 0xf6, 0x74, 0x2c, 0x2f, 0xf8, 0xe4, 0xf6} }, -{ 0x0eef, 16, {0x74, 0x9a, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe4, 0xf0, 0x90, 0x01, 0x1e, 0xe0} }, -{ 0x0eff, 16, {0x04, 0xf0, 0xe0, 0xb4, 0x04, 0xb6, 0x90, 0x20, 0x60, 0xe0, 0x54, 0x0f, 0xf5, 0x5e, 0x60, 0x5e} }, -{ 0x0f0f, 16, {0xe4, 0x90, 0x01, 0x1e, 0xf0, 0x90, 0x01, 0x1e, 0xe0, 0xff, 0xc3, 0x94, 0x04, 0x50, 0xe7, 0x74} }, -{ 0x0f1f, 16, {0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x55, 0x5e, 0x60, 0x38, 0x90, 0x01} }, -{ 0x0f2f, 1, {0x1e} }, -{ 0x0f30, 16, {0xe0, 0xff, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x02, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0} }, -{ 0x0f40, 16, {0xfe, 0xef, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0} }, -{ 0x0f50, 16, {0xef, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0, 0xfe} }, -{ 0x0f60, 14, {0x7d, 0x06, 0x12, 0x82, 0x60, 0x90, 0x01, 0x1e, 0xe0, 0x04, 0xf0, 0x80, 0xa7, 0x22} }, -{ 0x0f6e, 4, {0x53, 0x91, 0xbf, 0x32} }, -{ 0x0f72, 16, {0x7b, 0xff, 0x7a, 0x12, 0x79, 0x1b, 0x90, 0x00, 0x04, 0x12, 0x9a, 0x61, 0xfd, 0x8b, 0x60, 0x75} }, -{ 0x0f82, 16, {0x61, 0x12, 0x75, 0x62, 0x24, 0xe4, 0x90, 0x7f, 0xe1, 0xf0, 0x90, 0x7f, 0xe0, 0xf0, 0xf5, 0x5e} }, -{ 0x0f92, 16, {0xf5, 0x5f, 0x90, 0x02, 0x4c, 0xf0, 0x90, 0x7f, 0xdf, 0xf0, 0x90, 0x7f, 0xde, 0xf0, 0x90, 0x7f} }, -{ 0x0fa2, 16, {0xa9, 0x74, 0xff, 0xf0, 0x90, 0x7f, 0xaa, 0xf0, 0xe4, 0xfc, 0xec, 0x25, 0xe0, 0x24, 0xb4, 0xf5} }, -{ 0x0fb2, 16, {0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe4, 0xf0, 0x0c, 0xbc, 0x10, 0xee, 0xe4, 0x90, 0x7f, 0xdd} }, -{ 0x0fc2, 16, {0xf0, 0xaf, 0x05, 0x1d, 0xef, 0x70, 0x03, 0x02, 0x11, 0x38, 0xab, 0x60, 0xaa, 0x61, 0xa9, 0x62} }, -{ 0x0fd2, 16, {0x90, 0x00, 0x01, 0x12, 0x9a, 0x61, 0x64, 0x05, 0x60, 0x03, 0x02, 0x11, 0x27, 0x90, 0x00, 0x03} }, -{ 0x0fe2, 16, {0x12, 0x9a, 0x61, 0x64, 0x01, 0x60, 0x03, 0x02, 0x10, 0xae, 0x90, 0x00, 0x02, 0x12, 0x9a, 0x61} }, -{ 0x0ff2, 16, {0xff, 0x54, 0x7f, 0xfc, 0xd3, 0x94, 0x07, 0x50, 0x03, 0x02, 0x10, 0x88, 0xec, 0xc3, 0x94, 0x10} }, -{ 0x1002, 16, {0x40, 0x03, 0x02, 0x10, 0x88, 0xef, 0x30, 0xe7, 0x42, 0xe5, 0x5f, 0xae, 0x5e, 0x78, 0x02, 0xce} }, -{ 0x1012, 16, {0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff, 0x74, 0xf0, 0x2c, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5} }, -{ 0x1022, 16, {0x83, 0xef, 0xf0, 0x90, 0x7f, 0xe0, 0xe0, 0xff, 0xec, 0x24, 0xf8, 0xfe, 0x74, 0x01, 0xa8, 0x06} }, -{ 0x1032, 16, {0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x4f, 0x90, 0x7f, 0xe0, 0xf0, 0x90, 0x02, 0x4c, 0xe0} }, -{ 0x1042, 16, {0x04, 0xf0, 0x90, 0x7f, 0xdd, 0xe0, 0x44, 0x80, 0xf0, 0x80, 0x3e, 0xe5, 0x5f, 0xae, 0x5e, 0x78} }, -{ 0x1052, 16, {0x02, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff, 0x74, 0xe8, 0x2c, 0xf5, 0x82, 0xe4, 0x34} }, -{ 0x1062, 16, {0x7f, 0xf5, 0x83, 0xef, 0xf0, 0x90, 0x7f, 0xe1, 0xe0, 0xff, 0xec, 0x24, 0xf8, 0xfe, 0x74, 0x01} }, -{ 0x1072, 16, {0xa8, 0x06, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x4f, 0x90, 0x7f, 0xe1, 0xf0, 0x90, 0x02} }, -{ 0x1082, 16, {0x4c, 0xe0, 0x04, 0xf0, 0x80, 0x03, 0x7f, 0xff, 0x22, 0x90, 0x00, 0x04, 0x12, 0x9a, 0x61, 0x25} }, -{ 0x1092, 16, {0x5f, 0xf5, 0x5f, 0xe4, 0x35, 0x5e, 0xf5, 0x5e, 0x90, 0x00, 0x05, 0x12, 0x9a, 0x61, 0xfe, 0xe4} }, -{ 0x10a2, 16, {0x25, 0x5f, 0xf5, 0x5f, 0xee, 0x35, 0x5e, 0xf5, 0x5e, 0x02, 0x11, 0x2a, 0xab, 0x60, 0xaa, 0x61} }, -{ 0x10b2, 16, {0xa9, 0x62, 0x90, 0x00, 0x03, 0x12, 0x9a, 0x61, 0xff, 0x64, 0x02, 0x60, 0x05, 0xef, 0x64, 0x03} }, -{ 0x10c2, 16, {0x70, 0x60, 0x90, 0x00, 0x02, 0x12, 0x9a, 0x61, 0xff, 0x54, 0x7f, 0xfc, 0xd3, 0x94, 0x07, 0x50} }, -{ 0x10d2, 16, {0x4e, 0xef, 0x30, 0xe7, 0x1e, 0x90, 0x7f, 0xde, 0xe0, 0xff, 0x74, 0x01, 0xa8, 0x04, 0x08, 0x80} }, -{ 0x10e2, 16, {0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xfe, 0x4f, 0x90, 0x7f, 0xde, 0xf0, 0x90, 0x7f, 0xac, 0xe0, 0x4e} }, -{ 0x10f2, 16, {0xf0, 0x80, 0x35, 0x90, 0x7f, 0xdf, 0xe0, 0xff, 0x74, 0x01, 0xa8, 0x04, 0x08, 0x80, 0x02, 0xc3} }, -{ 0x1102, 16, {0x33, 0xd8, 0xfc, 0xfe, 0x4f, 0x90, 0x7f, 0xdf, 0xf0, 0x90, 0x7f, 0xad, 0xe0, 0x4e, 0xf0, 0xec} }, -{ 0x1112, 16, {0x25, 0xe0, 0x24, 0xc5, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xec, 0xf0, 0x80, 0x09, 0x7f} }, -{ 0x1122, 16, {0xff, 0x22, 0x7f, 0xff, 0x22, 0x7f, 0xff, 0x22, 0x74, 0x07, 0x25, 0x62, 0xf5, 0x62, 0xe4, 0x35} }, -{ 0x1132, 16, {0x61, 0xf5, 0x61, 0x02, 0x0f, 0xc3, 0x20, 0x03, 0x0d, 0x90, 0x02, 0x4c, 0xe0, 0x60, 0x07, 0x90} }, -{ 0x1142, 8, {0x7f, 0xae, 0xe0, 0x44, 0x02, 0xf0, 0x7f, 0x00} }, -{ 0x114a, 1, {0x22} }, -{ 0x114b, 2, {0xae, 0x07} }, -{ 0x114d, 16, {0x7c, 0x02, 0xec, 0x14, 0x60, 0x15, 0x14, 0x70, 0x1e, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0} }, -{ 0x115d, 16, {0xee, 0x25, 0xe0, 0x44, 0x40, 0x90, 0x7f, 0xa6, 0xf0, 0x80, 0x0c, 0x90, 0x7f, 0xa6, 0xed, 0xf0} }, -{ 0x116d, 16, {0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x90, 0x7f, 0xa5, 0xe0, 0xfb, 0x30, 0xe0, 0xf8, 0xbc} }, -{ 0x117d, 16, {0x02, 0x0a, 0x20, 0xe1, 0x07, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x07, 0x22, 0xeb, 0x30, 0xe2, 0x0a} }, -{ 0x118d, 14, {0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x06, 0x22, 0xdc, 0xb6, 0x7f, 0x08} }, -{ 0x119b, 1, {0x22} }, -{ 0x119c, 16, {0x7f, 0x05, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x7f, 0x02, 0x7d, 0xff, 0x12, 0x11, 0x4b, 0x7f, 0x05} }, -{ 0x11ac, 13, {0x7e, 0x00, 0x12, 0x08, 0x92, 0x7f, 0x03, 0x7d, 0xff, 0x12, 0x11, 0x4b, 0x22} }, -{ 0x11b9, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc2, 0xa9, 0x90, 0x02, 0x9e, 0x74, 0x19, 0xf0, 0xd2, 0xa9} }, -{ 0x11c9, 15, {0x53, 0x91, 0x7f, 0x90, 0x01, 0x62, 0xe4, 0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, -{ 0x11d8, 16, {0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xff, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33} }, -{ 0x11e8, 7, {0xd8, 0xfc, 0x42, 0x3a, 0x7f, 0x00, 0x22} }, -{ 0x11ef, 3, {0x00, 0x02, 0x28} }, -{ 0x1200, 16, {0x12, 0x01, 0x00, 0x01, 0xff, 0xff, 0xff, 0x40, 0x10, 0x07, 0x01, 0x80, 0x42, 0x00, 0x01, 0x02} }, -{ 0x1210, 16, {0x03, 0x01, 0x09, 0x02, 0x58, 0x00, 0x01, 0x01, 0x04, 0x80, 0x3c, 0x09, 0x04, 0x00, 0x00, 0x0a} }, -{ 0x1220, 16, {0xff, 0xff, 0xff, 0x05, 0x07, 0x05, 0x81, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x01, 0x02, 0x40} }, -{ 0x1230, 16, {0x00, 0x00, 0x07, 0x05, 0x82, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x02, 0x02, 0x40, 0x00, 0x00} }, -{ 0x1240, 16, {0x07, 0x05, 0x83, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x03, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05} }, -{ 0x1250, 16, {0x84, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x04, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x87, 0x02} }, -{ 0x1260, 16, {0x40, 0x00, 0x00, 0x07, 0x05, 0x07, 0x02, 0x40, 0x00, 0x00, 0x04, 0x03, 0x09, 0x04, 0x24, 0x03} }, -{ 0x1270, 16, {0x43, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x20, 0x00} }, -{ 0x1280, 16, {0x54, 0x00, 0x65, 0x00, 0x63, 0x00, 0x68, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00} }, -{ 0x1290, 16, {0x2e, 0x00, 0x18, 0x03, 0x57, 0x00, 0x68, 0x00, 0x69, 0x00, 0x74, 0x00, 0x65, 0x00, 0x48, 0x00} }, -{ 0x12a0, 16, {0x45, 0x00, 0x41, 0x00, 0x54, 0x00, 0x2d, 0x00, 0x34, 0x00, 0x1a, 0x03, 0x58, 0x00, 0x58, 0x00} }, -{ 0x12b0, 16, {0x2d, 0x00, 0x58, 0x00, 0x58, 0x00, 0x2d, 0x00, 0x58, 0x00, 0x58, 0x00, 0x58, 0x00, 0x58, 0x00} }, -{ 0x12c0, 16, {0x58, 0x00, 0x58, 0x00, 0x2a, 0x03, 0x43, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x69, 0x00} }, -{ 0x12d0, 16, {0x67, 0x00, 0x75, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00} }, -{ 0x12e0, 16, {0x20, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x22, 0x03} }, -{ 0x12f0, 16, {0x49, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x66, 0x00, 0x61, 0x00, 0x63, 0x00} }, -{ 0x1300, 16, {0x65, 0x00, 0x20, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00} }, -{ 0x1310, 2, {0x00, 0x00} }, -{ 0x1312, 16, {0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0xc0, 0xd0} }, -{ 0x1322, 16, {0x75, 0x86, 0x00, 0x75, 0xd0, 0x18, 0x90, 0x20, 0x60, 0xe0, 0x54, 0x0f, 0xf5, 0xf0, 0x70, 0x11} }, -{ 0x1332, 16, {0xd0, 0xd0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0} }, -{ 0x1342, 16, {0x32, 0x75, 0x86, 0x00, 0x10, 0xf0, 0x0b, 0x10, 0xf1, 0x12, 0x10, 0xf2, 0x19, 0x10, 0xf3, 0x20} }, -{ 0x1352, 16, {0x80, 0xd4, 0xe5, 0x27, 0x70, 0x03, 0x75, 0x27, 0x14, 0x02, 0x13, 0x7c, 0xe5, 0x28, 0x70, 0x03} }, -{ 0x1362, 16, {0x75, 0x28, 0x14, 0x02, 0x15, 0x0d, 0xe5, 0x29, 0x70, 0x03, 0x75, 0x29, 0x14, 0x02, 0x16, 0x9e} }, -{ 0x1372, 16, {0xe5, 0x2a, 0x70, 0x03, 0x75, 0x2a, 0x14, 0x02, 0x18, 0x2f, 0x90, 0x20, 0x02, 0xe0, 0x54, 0x3f} }, -{ 0x1382, 16, {0x20, 0xe2, 0x3a, 0x20, 0xe1, 0x0b, 0x20, 0xe4, 0x0b, 0x20, 0xe5, 0x14, 0x60, 0x09, 0x02, 0x13} }, -{ 0x1392, 16, {0x43, 0x02, 0x14, 0x65, 0x02, 0x13, 0x43, 0x43, 0x82, 0x04, 0xe0, 0xf5, 0x36, 0x02, 0x13, 0x43} }, -{ 0x13a2, 16, {0x43, 0x82, 0x04, 0xe0, 0x43, 0x2c, 0x01, 0x02, 0x13, 0x43, 0x53, 0x82, 0xf8, 0x43, 0x82, 0x05} }, -{ 0x13b2, 16, {0xe0, 0x42, 0x32, 0x53, 0x82, 0xfb, 0xe0, 0x54, 0xfb, 0xf0, 0x02, 0x13, 0x43, 0x30, 0xe1, 0x02} }, -{ 0x13c2, 16, {0x80, 0xe8, 0xf5, 0x85, 0xe5, 0x3b, 0x30, 0xe0, 0x0a, 0x53, 0x82, 0xf8, 0x43, 0x82, 0x04, 0xe0} }, -{ 0x13d2, 16, {0x54, 0xfe, 0xf0, 0xe5, 0x85, 0x20, 0xe3, 0x56, 0x90, 0x20, 0x50, 0x74, 0x00, 0xf0, 0x90, 0x20} }, -{ 0x13e2, 16, {0x58, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xe2, 0xe0, 0x44, 0x40, 0xf0, 0x90, 0x7f, 0xe3, 0x05, 0x86} }, -{ 0x13f2, 16, {0x90, 0x7e, 0x80, 0x05, 0x86, 0xe5, 0x85, 0xf0, 0xa3, 0xe5, 0x84, 0xf0, 0x05, 0x86, 0x90, 0x7f} }, -{ 0x1402, 16, {0xe5, 0xe5, 0x3c, 0xfd, 0x03, 0x03, 0x03, 0xfe, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0} }, -{ 0x1412, 16, {0xde, 0xf6, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00, 0xf0, 0x90} }, -{ 0x1422, 16, {0x7f, 0xb7, 0xed, 0xf0, 0x90, 0x20, 0x01, 0xe0, 0x54, 0xfe, 0xf0, 0x02, 0x13, 0x43, 0x7f, 0x40} }, -{ 0x1432, 16, {0x90, 0x7e, 0x80, 0x05, 0x86, 0x90, 0x20, 0x00, 0xe5, 0x84, 0xfe, 0x24, 0x05, 0xfd, 0x8d, 0x84} }, -{ 0x1442, 16, {0xe0, 0x8e, 0x84, 0x30, 0xe0, 0x09, 0xe0, 0x05, 0x86, 0xf0, 0xa3, 0x05, 0x86, 0xdf, 0xef, 0x05} }, -{ 0x1452, 16, {0x86, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0x7f, 0xb7, 0xf0, 0x05, 0x86, 0xa3, 0xe0, 0x54, 0xfe, 0xf0} }, -{ 0x1462, 16, {0x02, 0x13, 0x43, 0x53, 0x2c, 0xfa, 0xe5, 0x22, 0x60, 0x08, 0x75, 0x22, 0x00, 0xd2, 0xe7, 0xfe} }, -{ 0x1472, 16, {0x80, 0x0a, 0x90, 0x7f, 0xc7, 0xe0, 0xfe, 0x70, 0x03, 0x02, 0x14, 0xff, 0x90, 0x20, 0x50, 0x74} }, -{ 0x1482, 16, {0x00, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xe2, 0xe0, 0x44, 0x40, 0xf0, 0x90} }, -{ 0x1492, 16, {0x7f, 0xe3, 0x05, 0x86, 0x90, 0x7e, 0x40, 0x05, 0x86, 0xe5, 0x85, 0xf0, 0xa3, 0xe5, 0x84, 0xf0} }, -{ 0x14a2, 16, {0x05, 0x86, 0x90, 0x7f, 0xe5, 0xee, 0x30, 0xe7, 0x08, 0x05, 0x86, 0xe0, 0x24, 0x38, 0xf0, 0x05} }, -{ 0x14b2, 16, {0x86, 0xee, 0x54, 0x7f, 0xfe, 0x54, 0x07, 0xfb, 0xee, 0x54, 0x78, 0x60, 0x30, 0x03, 0x03, 0x03} }, -{ 0x14c2, 16, {0x30, 0xe3, 0x04, 0x74, 0x07, 0x7b, 0x08, 0xfd, 0xfc, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0} }, -{ 0x14d2, 16, {0xe0, 0xdd, 0xf6, 0xeb, 0xfe, 0x60, 0x19, 0xec, 0x64, 0x07, 0x70, 0x11, 0x8b, 0x22, 0x90, 0x7f} }, -{ 0x14e2, 16, {0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00, 0xf0, 0x80, 0x1b, 0xe0, 0xde, 0xfd} }, -{ 0x14f2, 16, {0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00, 0xf0, 0x90, 0x20, 0x01} }, -{ 0x1502, 16, {0xe0, 0x54, 0xfd, 0xf0, 0x90, 0x7f, 0xc7, 0xf0, 0x02, 0x13, 0x43, 0x90, 0x20, 0x0a, 0xe0, 0x54} }, -{ 0x1512, 16, {0x3f, 0x20, 0xe2, 0x3a, 0x20, 0xe1, 0x0b, 0x20, 0xe4, 0x0b, 0x20, 0xe5, 0x14, 0x60, 0x09, 0x02} }, -{ 0x1522, 16, {0x13, 0x43, 0x02, 0x15, 0xf6, 0x02, 0x13, 0x43, 0x43, 0x82, 0x04, 0xe0, 0xf5, 0x37, 0x02, 0x13} }, -{ 0x1532, 16, {0x43, 0x43, 0x82, 0x04, 0xe0, 0x43, 0x2d, 0x01, 0x02, 0x13, 0x43, 0x53, 0x82, 0xf8, 0x43, 0x82} }, -{ 0x1542, 16, {0x05, 0xe0, 0x42, 0x33, 0x53, 0x82, 0xfb, 0xe0, 0x54, 0xfb, 0xf0, 0x02, 0x13, 0x43, 0x30, 0xe1} }, -{ 0x1552, 16, {0x02, 0x80, 0xe8, 0xf5, 0x85, 0xe5, 0x3b, 0x30, 0xe1, 0x0a, 0x53, 0x82, 0xf8, 0x43, 0x82, 0x04} }, -{ 0x1562, 16, {0xe0, 0x54, 0xfe, 0xf0, 0xe5, 0x85, 0x20, 0xe3, 0x56, 0x90, 0x20, 0x50, 0x74, 0x01, 0xf0, 0x90} }, -{ 0x1572, 16, {0x20, 0x58, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xe2, 0xe0, 0x44, 0x40, 0xf0, 0x90, 0x7f, 0xe3, 0x05} }, -{ 0x1582, 16, {0x86, 0x90, 0x7e, 0x00, 0x05, 0x86, 0xe5, 0x85, 0xf0, 0xa3, 0xe5, 0x84, 0xf0, 0x05, 0x86, 0x90} }, -{ 0x1592, 16, {0x7f, 0xe5, 0xe5, 0x3d, 0xfd, 0x03, 0x03, 0x03, 0xfe, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0} }, -{ 0x15a2, 16, {0xf0, 0xde, 0xf6, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00, 0xf0} }, -{ 0x15b2, 16, {0x90, 0x7f, 0xb9, 0xed, 0xf0, 0x90, 0x20, 0x09, 0xe0, 0x54, 0xfe, 0xf0, 0x02, 0x13, 0x43, 0x7f} }, -{ 0x15c2, 16, {0x40, 0x90, 0x7e, 0x00, 0x05, 0x86, 0x90, 0x20, 0x08, 0xe5, 0x84, 0xfe, 0x24, 0x05, 0xfd, 0x8d} }, -{ 0x15d2, 16, {0x84, 0xe0, 0x8e, 0x84, 0x30, 0xe0, 0x09, 0xe0, 0x05, 0x86, 0xf0, 0xa3, 0x05, 0x86, 0xdf, 0xef} }, -{ 0x15e2, 16, {0x05, 0x86, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0x7f, 0xb9, 0xf0, 0x05, 0x86, 0xa3, 0xe0, 0x54, 0xfe} }, -{ 0x15f2, 16, {0xf0, 0x02, 0x13, 0x43, 0x53, 0x2d, 0xfa, 0xe5, 0x23, 0x60, 0x08, 0x75, 0x23, 0x00, 0xd2, 0xe7} }, -{ 0x1602, 16, {0xfe, 0x80, 0x0a, 0x90, 0x7f, 0xc9, 0xe0, 0xfe, 0x70, 0x03, 0x02, 0x16, 0x90, 0x90, 0x20, 0x50} }, -{ 0x1612, 16, {0x74, 0x01, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xe2, 0xe0, 0x44, 0x40, 0xf0} }, -{ 0x1622, 16, {0x90, 0x7f, 0xe3, 0x05, 0x86, 0x90, 0x7d, 0xc0, 0x05, 0x86, 0xe5, 0x85, 0xf0, 0xa3, 0xe5, 0x84} }, -{ 0x1632, 16, {0xf0, 0x05, 0x86, 0x90, 0x7f, 0xe5, 0xee, 0x30, 0xe7, 0x08, 0x05, 0x86, 0xe0, 0x24, 0x38, 0xf0} }, -{ 0x1642, 16, {0x05, 0x86, 0xee, 0x54, 0x7f, 0xfe, 0x54, 0x07, 0xfb, 0xee, 0x54, 0x78, 0x60, 0x30, 0x03, 0x03} }, -{ 0x1652, 16, {0x03, 0x30, 0xe3, 0x04, 0x74, 0x07, 0x7b, 0x08, 0xfd, 0xfc, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0} }, -{ 0x1662, 16, {0xe0, 0xe0, 0xdd, 0xf6, 0xeb, 0xfe, 0x60, 0x19, 0xec, 0x64, 0x07, 0x70, 0x11, 0x8b, 0x23, 0x90} }, -{ 0x1672, 16, {0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00, 0xf0, 0x80, 0x1b, 0xe0, 0xde} }, -{ 0x1682, 14, {0xfd, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00, 0xf0} }, -{ 0x1690, 16, {0x90, 0x20, 0x09, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0x7f, 0xc9, 0xf0, 0x02, 0x13, 0x43, 0x90, 0x20} }, -{ 0x16a0, 16, {0x12, 0xe0, 0x54, 0x3f, 0x20, 0xe2, 0x3a, 0x20, 0xe1, 0x0b, 0x20, 0xe4, 0x0b, 0x20, 0xe5, 0x14} }, -{ 0x16b0, 16, {0x60, 0x09, 0x02, 0x13, 0x43, 0x02, 0x17, 0x87, 0x02, 0x13, 0x43, 0x43, 0x82, 0x04, 0xe0, 0xf5} }, -{ 0x16c0, 16, {0x38, 0x02, 0x13, 0x43, 0x43, 0x82, 0x04, 0xe0, 0x43, 0x2e, 0x01, 0x02, 0x13, 0x43, 0x53, 0x82} }, -{ 0x16d0, 16, {0xf8, 0x43, 0x82, 0x05, 0xe0, 0x42, 0x34, 0x53, 0x82, 0xfb, 0xe0, 0x54, 0xfb, 0xf0, 0x02, 0x13} }, -{ 0x16e0, 16, {0x43, 0x30, 0xe1, 0x02, 0x80, 0xe8, 0xf5, 0x85, 0xe5, 0x3b, 0x30, 0xe2, 0x0a, 0x53, 0x82, 0xf8} }, -{ 0x16f0, 16, {0x43, 0x82, 0x04, 0xe0, 0x54, 0xfe, 0xf0, 0xe5, 0x85, 0x20, 0xe3, 0x56, 0x90, 0x20, 0x50, 0x74} }, -{ 0x1700, 16, {0x02, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xe2, 0xe0, 0x44, 0x40, 0xf0, 0x90} }, -{ 0x1710, 16, {0x7f, 0xe3, 0x05, 0x86, 0x90, 0x7d, 0x80, 0x05, 0x86, 0xe5, 0x85, 0xf0, 0xa3, 0xe5, 0x84, 0xf0} }, -{ 0x1720, 16, {0x05, 0x86, 0x90, 0x7f, 0xe5, 0xe5, 0x3e, 0xfd, 0x03, 0x03, 0x03, 0xfe, 0xf0, 0xf0, 0xf0, 0xf0} }, -{ 0x1730, 16, {0xf0, 0xf0, 0xf0, 0xf0, 0xde, 0xf6, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58} }, -{ 0x1740, 16, {0x74, 0x00, 0xf0, 0x90, 0x7f, 0xbb, 0xed, 0xf0, 0x90, 0x20, 0x11, 0xe0, 0x54, 0xfe, 0xf0, 0x02} }, -{ 0x1750, 16, {0x13, 0x43, 0x7f, 0x40, 0x90, 0x7d, 0x80, 0x05, 0x86, 0x90, 0x20, 0x10, 0xe5, 0x84, 0xfe, 0x24} }, -{ 0x1760, 16, {0x05, 0xfd, 0x8d, 0x84, 0xe0, 0x8e, 0x84, 0x30, 0xe0, 0x09, 0xe0, 0x05, 0x86, 0xf0, 0xa3, 0x05} }, -{ 0x1770, 16, {0x86, 0xdf, 0xef, 0x05, 0x86, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0x7f, 0xbb, 0xf0, 0x05, 0x86, 0xa3} }, -{ 0x1780, 16, {0xe0, 0x54, 0xfe, 0xf0, 0x02, 0x13, 0x43, 0x53, 0x2e, 0xfa, 0xe5, 0x24, 0x60, 0x08, 0x75, 0x24} }, -{ 0x1790, 16, {0x00, 0xd2, 0xe7, 0xfe, 0x80, 0x0a, 0x90, 0x7f, 0xcb, 0xe0, 0xfe, 0x70, 0x03, 0x02, 0x18, 0x21} }, -{ 0x17a0, 16, {0x90, 0x20, 0x50, 0x74, 0x02, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xe2, 0xe0} }, -{ 0x17b0, 16, {0x44, 0x40, 0xf0, 0x90, 0x7f, 0xe3, 0x05, 0x86, 0x90, 0x7d, 0x40, 0x05, 0x86, 0xe5, 0x85, 0xf0} }, -{ 0x17c0, 16, {0xa3, 0xe5, 0x84, 0xf0, 0x05, 0x86, 0x90, 0x7f, 0xe5, 0xee, 0x30, 0xe7, 0x08, 0x05, 0x86, 0xe0} }, -{ 0x17d0, 16, {0x24, 0x38, 0xf0, 0x05, 0x86, 0xee, 0x54, 0x7f, 0xfe, 0x54, 0x07, 0xfb, 0xee, 0x54, 0x78, 0x60} }, -{ 0x17e0, 16, {0x30, 0x03, 0x03, 0x03, 0x30, 0xe3, 0x04, 0x74, 0x07, 0x7b, 0x08, 0xfd, 0xfc, 0xe0, 0xe0, 0xe0} }, -{ 0x17f0, 16, {0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xdd, 0xf6, 0xeb, 0xfe, 0x60, 0x19, 0xec, 0x64, 0x07, 0x70, 0x11} }, -{ 0x1800, 16, {0x8b, 0x24, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00, 0xf0, 0x80} }, -{ 0x1810, 16, {0x1b, 0xe0, 0xde, 0xfd, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00} }, -{ 0x1820, 16, {0xf0, 0x90, 0x20, 0x11, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0x7f, 0xcb, 0xf0, 0x02, 0x13, 0x43, 0x90} }, -{ 0x1830, 16, {0x20, 0x1a, 0xe0, 0x54, 0x3f, 0x20, 0xe2, 0x3a, 0x20, 0xe1, 0x0b, 0x20, 0xe4, 0x0b, 0x20, 0xe5} }, -{ 0x1840, 16, {0x14, 0x60, 0x09, 0x02, 0x13, 0x43, 0x02, 0x19, 0x18, 0x02, 0x13, 0x43, 0x43, 0x82, 0x04, 0xe0} }, -{ 0x1850, 16, {0xf5, 0x39, 0x02, 0x13, 0x43, 0x43, 0x82, 0x04, 0xe0, 0x43, 0x2f, 0x01, 0x02, 0x13, 0x43, 0x53} }, -{ 0x1860, 16, {0x82, 0xf8, 0x43, 0x82, 0x05, 0xe0, 0x42, 0x35, 0x53, 0x82, 0xfb, 0xe0, 0x54, 0xfb, 0xf0, 0x02} }, -{ 0x1870, 16, {0x13, 0x43, 0x30, 0xe1, 0x02, 0x80, 0xe8, 0xf5, 0x85, 0xe5, 0x3b, 0x30, 0xe3, 0x0a, 0x53, 0x82} }, -{ 0x1880, 16, {0xf8, 0x43, 0x82, 0x04, 0xe0, 0x54, 0xfe, 0xf0, 0xe5, 0x85, 0x20, 0xe3, 0x56, 0x90, 0x20, 0x50} }, -{ 0x1890, 16, {0x74, 0x03, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xe2, 0xe0, 0x44, 0x40, 0xf0} }, -{ 0x18a0, 16, {0x90, 0x7f, 0xe3, 0x05, 0x86, 0x90, 0x7d, 0x00, 0x05, 0x86, 0xe5, 0x85, 0xf0, 0xa3, 0xe5, 0x84} }, -{ 0x18b0, 16, {0xf0, 0x05, 0x86, 0x90, 0x7f, 0xe5, 0xe5, 0x3f, 0xfd, 0x03, 0x03, 0x03, 0xfe, 0xf0, 0xf0, 0xf0} }, -{ 0x18c0, 16, {0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xde, 0xf6, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20} }, -{ 0x18d0, 16, {0x58, 0x74, 0x00, 0xf0, 0x90, 0x7f, 0xbd, 0xed, 0xf0, 0x90, 0x20, 0x19, 0xe0, 0x54, 0xfe, 0xf0} }, -{ 0x18e0, 16, {0x02, 0x13, 0x43, 0x7f, 0x40, 0x90, 0x7d, 0x00, 0x05, 0x86, 0x90, 0x20, 0x18, 0xe5, 0x84, 0xfe} }, -{ 0x18f0, 16, {0x24, 0x05, 0xfd, 0x8d, 0x84, 0xe0, 0x8e, 0x84, 0x30, 0xe0, 0x09, 0xe0, 0x05, 0x86, 0xf0, 0xa3} }, -{ 0x1900, 16, {0x05, 0x86, 0xdf, 0xef, 0x05, 0x86, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0x7f, 0xbd, 0xf0, 0x05, 0x86} }, -{ 0x1910, 16, {0xa3, 0xe0, 0x54, 0xfe, 0xf0, 0x02, 0x13, 0x43, 0x53, 0x2f, 0xfa, 0xe5, 0x25, 0x60, 0x08, 0x75} }, -{ 0x1920, 16, {0x25, 0x00, 0xd2, 0xe7, 0xfe, 0x80, 0x0a, 0x90, 0x7f, 0xcd, 0xe0, 0xfe, 0x70, 0x03, 0x02, 0x19} }, -{ 0x1930, 16, {0xb2, 0x90, 0x20, 0x50, 0x74, 0x03, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xe2} }, -{ 0x1940, 16, {0xe0, 0x44, 0x40, 0xf0, 0x90, 0x7f, 0xe3, 0x05, 0x86, 0x90, 0x7c, 0xc0, 0x05, 0x86, 0xe5, 0x85} }, -{ 0x1950, 16, {0xf0, 0xa3, 0xe5, 0x84, 0xf0, 0x05, 0x86, 0x90, 0x7f, 0xe5, 0xee, 0x30, 0xe7, 0x08, 0x05, 0x86} }, -{ 0x1960, 16, {0xe0, 0x24, 0x38, 0xf0, 0x05, 0x86, 0xee, 0x54, 0x7f, 0xfe, 0x54, 0x07, 0xfb, 0xee, 0x54, 0x78} }, -{ 0x1970, 16, {0x60, 0x30, 0x03, 0x03, 0x03, 0x30, 0xe3, 0x04, 0x74, 0x07, 0x7b, 0x08, 0xfd, 0xfc, 0xe0, 0xe0} }, -{ 0x1980, 16, {0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xdd, 0xf6, 0xeb, 0xfe, 0x60, 0x19, 0xec, 0x64, 0x07, 0x70} }, -{ 0x1990, 16, {0x11, 0x8b, 0x25, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00, 0xf0} }, -{ 0x19a0, 16, {0x80, 0x1b, 0xe0, 0xde, 0xfd, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74} }, -{ 0x19b0, 16, {0x00, 0xf0, 0x90, 0x20, 0x19, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0x7f, 0xcd, 0xf0, 0x02, 0x13, 0x43} }, -{ 0x19c0, 1, {0x32} }, -{ 0x19c1, 4, {0xad, 0x07, 0xac, 0x06} }, -{ 0x19c5, 16, {0x79, 0x06, 0xed, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x3c, 0xf5, 0x83, 0xe0, 0xfa, 0xa3, 0xe0, 0xfb} }, -{ 0x19d5, 16, {0x4a, 0x70, 0x03, 0x02, 0x1b, 0x09, 0xe9, 0xb4, 0x07, 0x00, 0x40, 0x03, 0x02, 0x1a, 0xdb, 0x90} }, -{ 0x19e5, 16, {0x19, 0xeb, 0xf8, 0x28, 0x28, 0x73, 0x02, 0x1a, 0xb9, 0x02, 0x1a, 0x71, 0x02, 0x1a, 0x5a, 0x02} }, -{ 0x19f5, 16, {0x1a, 0x40, 0x02, 0x1a, 0x2f, 0x02, 0x1a, 0x1a, 0x02, 0x1a, 0x00, 0x90, 0x7f, 0xa5, 0xe0, 0x44} }, -{ 0x1a05, 16, {0x80, 0xf0, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xe0, 0xff, 0x25, 0xe0, 0x44, 0xa0, 0x90, 0x7f, 0xa6} }, -{ 0x1a15, 16, {0xf0, 0x19, 0x02, 0x1a, 0xdb, 0x19, 0x8d, 0x82, 0x8c, 0x83, 0xe0, 0xc3, 0x94, 0x20, 0x40, 0x0a} }, -{ 0x1a25, 16, {0xa3, 0xa3, 0xe0, 0x90, 0x7f, 0xa6, 0xf0, 0x02, 0x1a, 0xdb, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3} }, -{ 0x1a35, 16, {0xe0, 0xa3, 0xe0, 0x90, 0x7f, 0xa6, 0xf0, 0x19, 0x02, 0x1a, 0xdb, 0x90, 0x7f, 0xa5, 0xe0, 0x44} }, -{ 0x1a45, 16, {0x80, 0xf0, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xe0, 0xff, 0x25, 0xe0, 0x44, 0xa1, 0x90, 0x7f, 0xa6} }, -{ 0x1a55, 16, {0xf0, 0x19, 0x02, 0x1a, 0xdb, 0xeb, 0x64, 0x01, 0x4a, 0x70, 0x08, 0x90, 0x7f, 0xa5, 0xe0, 0x44} }, -{ 0x1a65, 16, {0x20, 0xf0, 0x19, 0x90, 0x7f, 0xa6, 0xe0, 0xf5, 0x69, 0x19, 0x80, 0x6a, 0xed, 0x24, 0x04, 0xf5} }, -{ 0x1a75, 16, {0x82, 0xe4, 0x3c, 0xf5, 0x83, 0xe0, 0xfe, 0xa3, 0xe0, 0x64, 0x02, 0x4e, 0x70, 0x08, 0x90, 0x7f} }, -{ 0x1a85, 16, {0xa5, 0xe0, 0x44, 0x20, 0xf0, 0x19, 0x90, 0x7f, 0xa6, 0xe0, 0xff, 0xed, 0x24, 0x06, 0xf5, 0x82} }, -{ 0x1a95, 16, {0xe4, 0x3c, 0xf5, 0x83, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9a, 0xa4, 0x85, 0xf0, 0x82, 0xf5, 0x83} }, -{ 0x1aa5, 16, {0xef, 0xf0, 0xed, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x3c, 0xf5, 0x83, 0x74, 0xff, 0xf5, 0xf0, 0x12} }, -{ 0x1ab5, 16, {0x9a, 0x8e, 0x80, 0x22, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x90, 0x7f, 0xa6, 0xe0, 0xff} }, -{ 0x1ac5, 16, {0xed, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x3c, 0xf5, 0x83, 0xe0, 0xfa, 0xa3, 0xe0, 0xf5, 0x82, 0x8a} }, -{ 0x1ad5, 16, {0x83, 0xef, 0xf0, 0x7f, 0x08, 0x22, 0x90, 0x7f, 0xa5, 0xe0, 0xf5, 0x69, 0x30, 0xe0, 0xf7, 0x30} }, -{ 0x1ae5, 16, {0xe2, 0x07, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x06, 0x22, 0xe9, 0xd3, 0x94, 0x02, 0x50, 0x03, 0x02} }, -{ 0x1af5, 16, {0x19, 0xc7, 0xe5, 0x69, 0x30, 0xe1, 0x03, 0x02, 0x19, 0xc7, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40} }, -{ 0x1b05, 6, {0xf0, 0x7f, 0x07, 0x22, 0x7f, 0x08} }, -{ 0x1b0b, 1, {0x22} }, -{ 0x1b0c, 16, {0x8e, 0x5f, 0x8f, 0x60, 0x8c, 0x61, 0x8d, 0x62, 0xaf, 0x03, 0x1b, 0xef, 0x60, 0x24, 0x05, 0x60} }, -{ 0x1b1c, 16, {0xe5, 0x60, 0xae, 0x5f, 0x70, 0x02, 0x05, 0x5f, 0x14, 0xf5, 0x82, 0x8e, 0x83, 0xe0, 0xff, 0x05} }, -{ 0x1b2c, 16, {0x62, 0xe5, 0x62, 0xac, 0x61, 0x70, 0x02, 0x05, 0x61, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0} }, -{ 0x1b3c, 3, {0x80, 0xd6, 0x22} }, -{ 0x8000, 4, {0x8e, 0x69, 0x8f, 0x6a} }, -{ 0x8004, 16, {0x75, 0x6b, 0x03, 0xe5, 0x6a, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x69, 0xf5, 0x83, 0xe0, 0xfe} }, -{ 0x8014, 16, {0xa3, 0xe0, 0x4e, 0x70, 0x03, 0x02, 0x81, 0x0e, 0xe5, 0x6b, 0x60, 0x4e, 0x14, 0x60, 0x38, 0x14} }, -{ 0x8024, 16, {0x60, 0x20, 0x14, 0x60, 0x03, 0x02, 0x80, 0xb2, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0, 0x85} }, -{ 0x8034, 16, {0x6a, 0x82, 0x85, 0x69, 0x83, 0xa3, 0xe0, 0xff, 0x25, 0xe0, 0x44, 0xa0, 0x90, 0x7f, 0xa6, 0xf0} }, -{ 0x8044, 16, {0x80, 0x6c, 0x85, 0x6a, 0x82, 0x85, 0x69, 0x83, 0xe0, 0xc3, 0x94, 0x20, 0x40, 0x09, 0xa3, 0xa3} }, -{ 0x8054, 16, {0xe0, 0x90, 0x7f, 0xa6, 0xf0, 0x80, 0x57, 0x15, 0x6b, 0x85, 0x6a, 0x82, 0x85, 0x69, 0x83, 0xa3} }, -{ 0x8064, 16, {0xa3, 0xe0, 0xa3, 0xe0, 0x90, 0x7f, 0xa6, 0xf0, 0x80, 0x44, 0xe5, 0x6a, 0x24, 0x06, 0xf5, 0x82} }, -{ 0x8074, 16, {0xe4, 0x35, 0x69, 0xf5, 0x83, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9a, 0xa4, 0x85, 0xf0, 0x82, 0xf5} }, -{ 0x8084, 16, {0x83, 0xe0, 0x90, 0x7f, 0xa6, 0xf0, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0xe5, 0x6a, 0x24} }, -{ 0x8094, 16, {0x04, 0xf5, 0x82, 0xe4, 0x35, 0x69, 0xf5, 0x83, 0x74, 0xff, 0xf5, 0xf0, 0x12, 0x9a, 0x8e, 0x85} }, -{ 0x80a4, 16, {0x6a, 0x82, 0x85, 0x69, 0x83, 0xa3, 0xa3, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9a, 0x8e, 0x90, 0x7f} }, -{ 0x80b4, 16, {0xa5, 0xe0, 0xf5, 0x6c, 0x30, 0xe0, 0xf7, 0x30, 0xe2, 0x07, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x06} }, -{ 0x80c4, 16, {0x22, 0xe5, 0x6c, 0x20, 0xe1, 0x0a, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x07, 0x22} }, -{ 0x80d4, 16, {0xe5, 0x6b, 0x70, 0x31, 0x7f, 0x01, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x90, 0x7f, 0xa5, 0xe0, 0x44} }, -{ 0x80e4, 16, {0x80, 0xf0, 0x85, 0x6a, 0x82, 0x85, 0x69, 0x83, 0xa3, 0xe0, 0xff, 0x25, 0xe0, 0x44, 0xa0, 0x90} }, -{ 0x80f4, 16, {0x7f, 0xa6, 0xf0, 0x90, 0x7f, 0xa5, 0xe0, 0xf5, 0x6c, 0x30, 0xe0, 0xf7, 0x30, 0xe1, 0xd5, 0x75} }, -{ 0x8104, 12, {0x6b, 0x03, 0x02, 0x80, 0x07, 0x15, 0x6b, 0x02, 0x80, 0x07, 0x7f, 0x08} }, -{ 0x8110, 1, {0x22} }, -{ 0x8111, 2, {0xac, 0x07} }, -{ 0x8113, 16, {0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0, 0xec, 0x25, 0xe0, 0x44, 0x41, 0x90, 0x7f, 0xa6, 0xf0} }, -{ 0x8123, 16, {0x7b, 0x3c, 0xaf, 0x03, 0x1b, 0xef, 0x70, 0x16, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x90} }, -{ 0x8133, 16, {0x7f, 0xa6, 0xe0, 0xfd, 0x7d, 0x32, 0xaf, 0x05, 0x1d, 0xef, 0x60, 0xd4, 0x80, 0xf8, 0x90, 0x7f} }, -{ 0x8143, 16, {0xa5, 0xe0, 0xfd, 0x30, 0xe0, 0xdc, 0x20, 0xe1, 0x09, 0xe0, 0x44, 0x40, 0xf0, 0x7e, 0xff, 0x7f} }, -{ 0x8153, 16, {0xf9, 0x22, 0xed, 0x30, 0xe2, 0x0c, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x7e, 0xff, 0x7f} }, -{ 0x8163, 16, {0xfa, 0x22, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0x7f, 0xa6, 0xe0, 0xfd, 0x7b, 0x1e} }, -{ 0x8173, 16, {0xaf, 0x03, 0x1b, 0xef, 0x70, 0x16, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x90, 0x7f, 0xa6} }, -{ 0x8183, 16, {0xe0, 0xfd, 0x7d, 0x32, 0xaf, 0x05, 0x1d, 0xef, 0x60, 0x86, 0x80, 0xf8, 0x90, 0x7f, 0xa5, 0xe0} }, -{ 0x8193, 16, {0xfd, 0x20, 0xe0, 0xdc, 0x7b, 0x3c, 0xaf, 0x03, 0x1b, 0xef, 0x70, 0x19, 0x90, 0x7f, 0xa5, 0xe0} }, -{ 0x81a3, 16, {0x44, 0x40, 0xf0, 0x90, 0x7f, 0xa6, 0xe0, 0xfd, 0x7d, 0x32, 0xaf, 0x05, 0x1d, 0xef, 0x70, 0x03} }, -{ 0x81b3, 16, {0x02, 0x81, 0x13, 0x80, 0xf5, 0x90, 0x7f, 0xa5, 0xe0, 0xfd, 0x30, 0xe0, 0xd9, 0x30, 0xe2, 0x09} }, -{ 0x81c3, 16, {0xe0, 0x44, 0x40, 0xf0, 0x7e, 0xff, 0x7f, 0xfa, 0x22, 0xc2, 0xaf, 0x90, 0x7f, 0xa5, 0xe0, 0x44} }, -{ 0x81d3, 12, {0x40, 0xf0, 0x90, 0x7f, 0xa6, 0xe0, 0xfd, 0xd2, 0xaf, 0xff, 0x7e, 0x00} }, -{ 0x81df, 1, {0x22} }, -{ 0x81e0, 16, {0xef, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xab, 0x82, 0xfa, 0xf5} }, -{ 0x81f0, 16, {0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xf9, 0x74, 0xbf, 0xf0, 0x8b, 0x82, 0x8a, 0x83, 0xa3, 0xa3, 0xe0} }, -{ 0x8200, 16, {0x44, 0x10, 0xf0, 0x8b, 0x82, 0x8a, 0x83, 0xa3, 0xa3, 0xa3, 0xe4, 0xf0, 0x8b, 0x82, 0x8a, 0x83} }, -{ 0x8210, 16, {0xa3, 0xf0, 0xed, 0x60, 0x29, 0x74, 0x01, 0x7e, 0x00, 0xa8, 0x07, 0x08, 0x80, 0x05, 0xc3, 0x33} }, -{ 0x8220, 16, {0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff, 0xe4, 0xef, 0x55, 0x3b, 0x60, 0x0a, 0x8b, 0x82, 0x8a, 0x83} }, -{ 0x8230, 16, {0xa3, 0x74, 0x01, 0xf0, 0x80, 0x08, 0x8b, 0x82, 0x8a, 0x83, 0xa3, 0x74, 0xad, 0xf0, 0x8b, 0x82} }, -{ 0x8240, 16, {0x8a, 0x83, 0xa3, 0xa3, 0xa3, 0x74, 0xbf, 0xf0, 0x8b, 0x82, 0x8a, 0x83, 0xa3, 0xa3, 0xe0, 0x54} }, -{ 0x8250, 15, {0xef, 0xf0, 0xae, 0x02, 0xaf, 0x03, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xa3, 0xe9, 0xf0} }, -{ 0x825f, 1, {0x22} }, -{ 0x8260, 4, {0x8f, 0x68, 0x8d, 0x69} }, -{ 0x8264, 16, {0xe4, 0xf5, 0x6a, 0x74, 0x3c, 0x2f, 0xf8, 0x76, 0x08, 0xe5, 0x68, 0x75, 0xf0, 0x0d, 0xa4, 0x24} }, -{ 0x8274, 16, {0xa0, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe} }, -{ 0x8284, 16, {0xa3, 0xe0, 0xff, 0x7b, 0x80, 0x7a, 0x25, 0x79, 0x00, 0x78, 0x00, 0xc3, 0x12, 0x9b, 0xc0, 0x50} }, -{ 0x8294, 16, {0x3c, 0xe5, 0x68, 0x75, 0xf0, 0x0d, 0xa4, 0x24, 0xa0, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83} }, -{ 0x82a4, 16, {0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x7b, 0x00, 0x7a, 0x96, 0x78} }, -{ 0x82b4, 16, {0x00, 0xc3, 0x12, 0x9b, 0xc0, 0x40, 0x0c, 0x75, 0x6a, 0x40, 0x74, 0x3c, 0x25, 0x68, 0xf8, 0x76} }, -{ 0x82c4, 16, {0x10, 0x80, 0x0a, 0x75, 0x6a, 0x80, 0x74, 0x3c, 0x25, 0x68, 0xf8, 0x76, 0x38, 0xe5, 0x6a, 0x45} }, -{ 0x82d4, 16, {0x69, 0x44, 0x01, 0xff, 0xe5, 0x68, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x02, 0xf5, 0x82, 0xe4, 0x34} }, -{ 0x82e4, 5, {0x20, 0xf5, 0x83, 0xef, 0xf0} }, -{ 0x82e9, 1, {0x22} }, -{ 0x82ea, 16, {0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xf5, 0x5f, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82} }, -{ 0x82fa, 16, {0xe4, 0x34, 0x20, 0xaf, 0x82, 0xf5, 0x61, 0x8f, 0x62, 0xf5, 0x83, 0xe5, 0x82, 0x24, 0x04, 0xf5} }, -{ 0x830a, 16, {0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0xe0, 0x44, 0x03, 0xf0, 0xaf, 0x5f, 0x7d, 0x06, 0x12, 0x82} }, -{ 0x831a, 16, {0x60, 0xaf, 0x5f, 0x7d, 0x01, 0x12, 0x81, 0xe0, 0x85, 0x62, 0x82, 0x85, 0x61, 0x83, 0xa3, 0xa3} }, -{ 0x832a, 16, {0xe0, 0x20, 0xe0, 0x28, 0xe0, 0xf5, 0x60, 0xe5, 0x62, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x61} }, -{ 0x833a, 16, {0xf5, 0x83, 0xe0, 0xf5, 0x60, 0xe5, 0x62, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x35, 0x61, 0xf5, 0x83} }, -{ 0x834a, 16, {0xe0, 0xf5, 0x60, 0xaf, 0x5f, 0x7d, 0x06, 0x12, 0x82, 0x60, 0x80, 0xcc, 0x74, 0x96, 0x25, 0x5f} }, -{ 0x835a, 16, {0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x5f, 0x25, 0xe0, 0xff, 0xc3, 0x74} }, -{ 0x836a, 16, {0x0c, 0x9f, 0x75, 0xf0, 0x40, 0xa4, 0x24, 0x40, 0xf5, 0x82, 0xe5, 0xf0, 0x34, 0x7b, 0xaf, 0x82} }, -{ 0x837a, 16, {0xfe, 0xe5, 0x5f, 0x25, 0xe0, 0x24, 0x8d, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xee, 0xf0} }, -{ 0x838a, 16, {0xa3, 0xef, 0xf0, 0xaf, 0x5f, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc} }, -{ 0x839a, 4, {0x42, 0x30, 0x7f, 0x00} }, -{ 0x839e, 1, {0x22} }, -{ 0x839f, 16, {0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xf5, 0x47, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82} }, -{ 0x83af, 16, {0xe4, 0x34, 0x20, 0xaf, 0x82, 0xf5, 0x49, 0x8f, 0x4a, 0x74, 0x96, 0x25, 0x47, 0xf5, 0x82, 0xe4} }, -{ 0x83bf, 16, {0x34, 0x02, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x4a, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x49, 0xf5} }, -{ 0x83cf, 16, {0x83, 0xe0, 0x54, 0xfc, 0xf0, 0xaf, 0x47, 0xe4, 0xfd, 0x12, 0x81, 0xe0, 0xaf, 0x47, 0x7d, 0x06} }, -{ 0x83df, 16, {0x12, 0x82, 0x60, 0xe5, 0x4a, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x49, 0xf5, 0x83, 0xe0, 0x30} }, -{ 0x83ef, 16, {0xe0, 0x0b, 0x85, 0x4a, 0x82, 0x85, 0x49, 0x83, 0xe0, 0xf5, 0x48, 0x80, 0xe6, 0xaf, 0x47, 0x74} }, -{ 0x83ff, 16, {0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xf4, 0x52, 0x30, 0xe5, 0x47, 0x25} }, -{ 0x840f, 13, {0xe0, 0x24, 0xc7, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe4, 0xf0, 0xff} }, -{ 0x841c, 1, {0x22} }, -{ 0x841d, 4, {0x8e, 0x47, 0x8f, 0x48} }, -{ 0x8421, 16, {0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xf5, 0x49, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x01, 0xf5, 0x82} }, -{ 0x8431, 16, {0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0, 0x54, 0x03, 0x70, 0x23, 0x85, 0x48, 0x82, 0x8e, 0x83, 0xa3} }, -{ 0x8441, 16, {0xe0, 0x30, 0xe0, 0x07, 0xaf, 0x49, 0x7d, 0x02, 0x12, 0x82, 0x60, 0x85, 0x48, 0x82, 0x85, 0x47} }, -{ 0x8451, 15, {0x83, 0xa3, 0xe0, 0x30, 0xe1, 0x07, 0xaf, 0x49, 0x7d, 0x04, 0x12, 0x82, 0x60, 0x7f, 0x00} }, -{ 0x8460, 1, {0x22} }, -{ 0x8461, 16, {0x8f, 0x82, 0x8e, 0x83, 0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfd, 0xa3, 0xa3, 0xa3, 0xe0, 0xfc, 0xed} }, -{ 0x8471, 16, {0x6c, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xa3, 0xc0, 0x83, 0xc0} }, -{ 0x8481, 16, {0x82, 0xe0, 0xfd, 0x8f, 0x82, 0x8e, 0x83, 0xe0, 0xfc, 0xed, 0x6c, 0xd0, 0x82, 0xd0, 0x83, 0xf0} }, -{ 0x8491, 16, {0x8f, 0x82, 0x8e, 0x83, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0xe0, 0xfd, 0xec, 0x6d, 0xd0} }, -{ 0x84a1, 16, {0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfd, 0x8f} }, -{ 0x84b1, 16, {0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xe0, 0xfc, 0xed, 0x6c, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82} }, -{ 0x84c1, 16, {0x8e, 0x83, 0xa3, 0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfd, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xe0} }, -{ 0x84d1, 16, {0xfc, 0xed, 0x6c, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xc0, 0x83, 0xc0} }, -{ 0x84e1, 16, {0x82, 0xe0, 0xfd, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xe0, 0xff, 0xed, 0x6f, 0xd0, 0x82, 0xd0} }, -{ 0x84f1, 3, {0x83, 0xf0, 0x22} }, -{ 0x84f4, 4, {0x8e, 0x5f, 0x8f, 0x60} }, -{ 0x84f8, 16, {0x8f, 0x82, 0x8e, 0x83, 0xe0, 0xff, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0xf8, 0xf5, 0x82, 0xe4, 0x34} }, -{ 0x8508, 16, {0x1f, 0xad, 0x82, 0xf5, 0x66, 0x8d, 0x67, 0xaa, 0x5f, 0xa9, 0x60, 0x7b, 0x01, 0xc0, 0x03, 0xc0} }, -{ 0x8518, 16, {0x01, 0xef, 0x75, 0xf0, 0x0d, 0xa4, 0x24, 0x92, 0xf9, 0x74, 0x02, 0x35, 0xf0, 0xa8, 0x01, 0xfc} }, -{ 0x8528, 16, {0xad, 0x03, 0xd0, 0x01, 0xd0, 0x03, 0x7e, 0x00, 0x7f, 0x0d, 0x12, 0x9a, 0x1f, 0x85, 0x60, 0x82} }, -{ 0x8538, 16, {0x85, 0x5f, 0x83, 0xa3, 0xe0, 0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, 0xfa, 0xa3, 0xe0, 0xfb, 0x7f} }, -{ 0x8548, 16, {0x00, 0x7e, 0x08, 0x7d, 0x07, 0x7c, 0x00, 0x12, 0x9b, 0x2e, 0x8f, 0x64, 0x8e, 0x63, 0x8d, 0x62} }, -{ 0x8558, 16, {0x8c, 0x61, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00, 0x78, 0x00, 0xc3, 0x12, 0x9b, 0xc0, 0x70, 0x09} }, -{ 0x8568, 16, {0x75, 0x64, 0x01, 0xf5, 0x63, 0xf5, 0x62, 0xf5, 0x61, 0x7f, 0xff, 0x7e, 0xff, 0x7d, 0x00, 0x7c} }, -{ 0x8578, 16, {0x00, 0xab, 0x64, 0xaa, 0x63, 0xa9, 0x62, 0xa8, 0x61, 0xd3, 0x12, 0x9b, 0xc0, 0x40, 0x0c, 0x75} }, -{ 0x8588, 16, {0x64, 0xff, 0x75, 0x63, 0xff, 0x75, 0x62, 0x00, 0x75, 0x61, 0x00, 0x85, 0x67, 0x82, 0x85, 0x66} }, -{ 0x8598, 16, {0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0x44, 0x80, 0xf0, 0x85, 0x67, 0x82, 0x85, 0x66, 0x83, 0xe5, 0x64} }, -{ 0x85a8, 16, {0xf0, 0xaf, 0x64, 0xae, 0x63, 0xad, 0x62, 0xac, 0x61, 0x78, 0x08, 0x12, 0x9b, 0xd1, 0x85, 0x67} }, -{ 0x85b8, 16, {0x82, 0x85, 0x66, 0x83, 0xa3, 0xef, 0xf0, 0x85, 0x67, 0x82, 0x85, 0x66, 0x83, 0xa3, 0xa3, 0xa3} }, -{ 0x85c8, 16, {0xe0, 0x54, 0x7f, 0xf0, 0xe4, 0xf5, 0x65, 0xe5, 0x60, 0x24, 0x08, 0xf5, 0x82, 0xe4, 0x35, 0x5f} }, -{ 0x85d8, 16, {0xf5, 0x83, 0xe0, 0xff, 0xb4, 0x62, 0x05, 0x43, 0x65, 0x0a, 0x80, 0x10, 0xef, 0xb4, 0x72, 0x05} }, -{ 0x85e8, 16, {0x43, 0x65, 0x08, 0x80, 0x07, 0xef, 0xb4, 0x74, 0x03, 0x43, 0x65, 0x02, 0xe5, 0x60, 0x24, 0x0b} }, -{ 0x85f8, 16, {0xf5, 0x82, 0xe4, 0x35, 0x5f, 0xf5, 0x83, 0xe0, 0xff, 0x30, 0xe3, 0x03, 0x43, 0x65, 0x80, 0xef} }, -{ 0x8608, 16, {0x30, 0xe7, 0x12, 0x43, 0x65, 0x40, 0xe5, 0x67, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x66, 0xf5} }, -{ 0x8618, 16, {0x83, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x60, 0x24, 0x0b, 0xf5, 0x82, 0xe4, 0x35, 0x5f, 0xf5, 0x83} }, -{ 0x8628, 16, {0xe0, 0xff, 0x20, 0xe1, 0x03, 0x30, 0xe4, 0x27, 0x85, 0x60, 0x82, 0x85, 0x5f, 0x83, 0xe0, 0x14} }, -{ 0x8638, 16, {0xff, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x42, 0x3b, 0xe5, 0x67} }, -{ 0x8648, 16, {0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x66, 0xf5, 0x83, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x17, 0x85} }, -{ 0x8658, 16, {0x60, 0x82, 0x85, 0x5f, 0x83, 0xe0, 0x14, 0xff, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3} }, -{ 0x8668, 16, {0x33, 0xd8, 0xfc, 0xf4, 0x52, 0x3b, 0x85, 0x67, 0x82, 0x85, 0x66, 0x83, 0xa3, 0xa3, 0xa3, 0x74} }, -{ 0x8678, 16, {0xbf, 0xf0, 0x85, 0x67, 0x82, 0x85, 0x66, 0x83, 0xa3, 0xa3, 0xe4, 0xf0, 0xe5, 0x65, 0xf0, 0xe5} }, -{ 0x8688, 16, {0x60, 0x24, 0x0a, 0xf5, 0x82, 0xe4, 0x35, 0x5f, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x67, 0x24, 0x04} }, -{ 0x8698, 16, {0xf5, 0x82, 0xe4, 0x35, 0x66, 0xf5, 0x83, 0xef, 0xf0, 0xe5, 0x60, 0x24, 0x0a, 0xf5, 0x82, 0xe4} }, -{ 0x86a8, 16, {0x35, 0x5f, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x67, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x66, 0xf5} }, -{ 0x86b8, 16, {0x83, 0xef, 0xf0, 0xe5, 0x60, 0x24, 0x09, 0xf5, 0x82, 0xe4, 0x35, 0x5f, 0xf5, 0x83, 0xe0, 0xff} }, -{ 0x86c8, 16, {0xe5, 0x67, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x35, 0x66, 0xf5, 0x83, 0xef, 0xf0, 0xe5, 0x60, 0x24} }, -{ 0x86d8, 16, {0x09, 0xf5, 0x82, 0xe4, 0x35, 0x5f, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x67, 0x24, 0x07, 0xf5, 0x82} }, -{ 0x86e8, 16, {0xe4, 0x35, 0x66, 0xf5, 0x83, 0xef, 0xf0, 0x85, 0x67, 0x82, 0x85, 0x66, 0x83, 0xa3, 0xa3, 0xa3} }, -{ 0x86f8, 16, {0xe4, 0xf0, 0x85, 0x67, 0x82, 0x85, 0x66, 0x83, 0xa3, 0xa3, 0xf0, 0x85, 0x60, 0x82, 0x85, 0x5f} }, -{ 0x8708, 16, {0x83, 0xe0, 0x14, 0xff, 0x7d, 0x06, 0x12, 0x82, 0x60, 0x75, 0x65, 0x08, 0xe5, 0x60, 0x24, 0x0c} }, -{ 0x8718, 16, {0xf5, 0x82, 0xe4, 0x35, 0x5f, 0xf5, 0x83, 0xe0, 0x60, 0x03, 0x43, 0x65, 0x10, 0xe5, 0x67, 0x24} }, -{ 0x8728, 16, {0x04, 0xf5, 0x82, 0xe4, 0x35, 0x66, 0xf5, 0x83, 0xe0, 0x54, 0x03, 0x45, 0x65, 0xf0, 0xe5, 0x60} }, -{ 0x8738, 16, {0x24, 0x06, 0xf5, 0x82, 0xe4, 0x35, 0x5f, 0xf5, 0x83, 0xe0, 0x14, 0xff, 0x25, 0xe0, 0x25, 0xe0} }, -{ 0x8748, 16, {0xff, 0xe5, 0x60, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x5f, 0xf5, 0x83, 0xe0, 0x24, 0xfb, 0x4f} }, -{ 0x8758, 16, {0xf5, 0x65, 0xe5, 0x60, 0x24, 0x07, 0xf5, 0x82, 0xe4, 0x35, 0x5f, 0xf5, 0x83, 0xe0, 0x24, 0xd0} }, -{ 0x8768, 16, {0x60, 0x15, 0x14, 0x60, 0x17, 0x24, 0xc2, 0x60, 0x09, 0x24, 0x0a, 0x70, 0x12, 0x43, 0x65, 0x18} }, -{ 0x8778, 16, {0x80, 0x0d, 0x43, 0x65, 0x08, 0x80, 0x08, 0x43, 0x65, 0x38, 0x80, 0x03, 0x43, 0x65, 0x28, 0x85} }, -{ 0x8788, 13, {0x67, 0x82, 0x85, 0x66, 0x83, 0xa3, 0xa3, 0xa3, 0xe5, 0x65, 0xf0, 0x7f, 0x00} }, -{ 0x8795, 1, {0x22} }, -{ 0x8796, 4, {0x8e, 0x47, 0x8f, 0x48} }, -{ 0x879a, 16, {0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xf5, 0x4a, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82} }, -{ 0x87aa, 16, {0xe4, 0x34, 0x20, 0xaf, 0x82, 0xf5, 0x4d, 0x8f, 0x4e, 0x7e, 0x7b, 0x7f, 0x80, 0xef, 0x24, 0x01} }, -{ 0x87ba, 16, {0xf5, 0x4c, 0xe4, 0x3e, 0xf5, 0x4b, 0x8f, 0x82, 0x8e, 0x83, 0x74, 0x08, 0xf0, 0xe5, 0x4a, 0x04} }, -{ 0x87ca, 16, {0x85, 0x4c, 0x82, 0x85, 0x4b, 0x83, 0xf0, 0xa3, 0xe4, 0xf0, 0xe5, 0x4e, 0x24, 0x06, 0xf5, 0x82} }, -{ 0x87da, 16, {0xe4, 0x35, 0x4d, 0xf5, 0x83, 0xe0, 0x85, 0x4c, 0x82, 0x85, 0x4b, 0x83, 0xa3, 0xa3, 0xf0, 0xe5} }, -{ 0x87ea, 16, {0x4e, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x4d, 0xf5, 0x83, 0xe0, 0x54, 0x1e, 0x85, 0x4c, 0x82} }, -{ 0x87fa, 16, {0x85, 0x4b, 0x83, 0xa3, 0xa3, 0xa3, 0xf0, 0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xe0, 0x24, 0x2b} }, -{ 0x880a, 16, {0xf8, 0xe6, 0xff, 0xe5, 0x4c, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x4b, 0xf5, 0x83, 0xef, 0xf0} }, -{ 0x881a, 16, {0xaf, 0x4a, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xf5, 0x49, 0x7f} }, -{ 0x882a, 16, {0x02, 0x12, 0x81, 0x11, 0xc3, 0xee, 0x64, 0x80, 0x94, 0x80, 0x40, 0xf3, 0xe5, 0x49, 0x5f, 0xff} }, -{ 0x883a, 16, {0xe5, 0x4c, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x4b, 0xf5, 0x83, 0xef, 0xf0, 0x90, 0x7f, 0xc3} }, -{ 0x884a, 5, {0x74, 0x07, 0xf0, 0x7f, 0x00} }, -{ 0x884f, 1, {0x22} }, -{ 0x8850, 16, {0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0xf8, 0xf5, 0x82, 0xe4, 0x34, 0x1f} }, -{ 0x8860, 16, {0xaf, 0x82, 0xf5, 0x47, 0x8f, 0x48, 0x7e, 0x7b, 0x7f, 0x80, 0xef, 0x24, 0x01, 0xfd, 0xe4, 0x3e} }, -{ 0x8870, 16, {0xfc, 0x8f, 0x82, 0x8e, 0x83, 0x74, 0x0a, 0xf0, 0xe5, 0x48, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35} }, -{ 0x8880, 16, {0x47, 0xf5, 0x83, 0xe0, 0x8d, 0x82, 0x8c, 0x83, 0xf0, 0x90, 0x7f, 0xc3, 0x74, 0x02, 0xf0, 0x7f} }, -{ 0x8890, 1, {0x00} }, -{ 0x8891, 1, {0x22} }, -{ 0x8892, 16, {0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0xf8, 0xf5, 0x82, 0xe4, 0x34, 0x1f} }, -{ 0x88a2, 16, {0xad, 0x82, 0xfc, 0x8f, 0x82, 0xa3, 0xe0, 0x60, 0x0f, 0xed, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x3c} }, -{ 0x88b2, 16, {0xf5, 0x83, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x11, 0xae, 0x04, 0xaf, 0x05, 0xef, 0x24, 0x04, 0xf5} }, -{ 0x88c2, 11, {0x82, 0xe4, 0x3e, 0xf5, 0x83, 0xe0, 0x54, 0xfd, 0xf0, 0x7f, 0x00} }, -{ 0x88cd, 1, {0x22} }, -{ 0x88ce, 16, {0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0xf8, 0xf5, 0x82, 0xe4, 0x34, 0x1f} }, -{ 0x88de, 16, {0xad, 0x82, 0xfc, 0x8f, 0x82, 0xa3, 0xe0, 0x60, 0x0f, 0xed, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x3c} }, -{ 0x88ee, 16, {0xf5, 0x83, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x11, 0xae, 0x04, 0xaf, 0x05, 0xef, 0x24, 0x04, 0xf5} }, -{ 0x88fe, 11, {0x82, 0xe4, 0x3e, 0xf5, 0x83, 0xe0, 0x54, 0xfe, 0xf0, 0x7f, 0x00} }, -{ 0x8909, 1, {0x22} }, -{ 0x890a, 16, {0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0xf8, 0xf5, 0x82, 0xe4, 0x34, 0x1f} }, -{ 0x891a, 16, {0xad, 0x82, 0xfc, 0x8f, 0x82, 0xa3, 0xe0, 0x60, 0x0d, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xa3} }, -{ 0x892a, 16, {0xe0, 0x44, 0x40, 0xf0, 0x80, 0x0f, 0xae, 0x04, 0xaf, 0x05, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3} }, -{ 0x893a, 7, {0xa3, 0xe0, 0x54, 0xbf, 0xf0, 0x7f, 0x00} }, -{ 0x8941, 1, {0x22} }, -{ 0x8942, 4, {0x8e, 0x47, 0x8f, 0x48} }, -{ 0x8946, 16, {0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xe0, 0xf5, 0x4b, 0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x24, 0xfe, 0x60} }, -{ 0x8956, 16, {0x16, 0x14, 0x60, 0x1f, 0x14, 0x60, 0x28, 0x24, 0x03, 0x70, 0x2e, 0x7e, 0x7e, 0x7f, 0x80, 0x75} }, -{ 0x8966, 16, {0x49, 0x7e, 0x75, 0x4a, 0x80, 0x80, 0x22, 0x7e, 0x7e, 0x7f, 0x00, 0x75, 0x49, 0x7e, 0x75, 0x4a} }, -{ 0x8976, 16, {0x00, 0x80, 0x16, 0x7e, 0x7d, 0x7f, 0x80, 0x75, 0x49, 0x7d, 0x75, 0x4a, 0x80, 0x80, 0x0a, 0x7e} }, -{ 0x8986, 16, {0x7d, 0x7f, 0x00, 0x75, 0x49, 0x7d, 0x75, 0x4a, 0x00, 0xe5, 0x4b, 0x70, 0x20, 0x85, 0x4a, 0x82} }, -{ 0x8996, 16, {0x85, 0x49, 0x83, 0x74, 0xff, 0xf0, 0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xe0, 0x25, 0xe0, 0x24} }, -{ 0x89a6, 16, {0xb5, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0x74, 0x01, 0xf0, 0x80, 0x3a, 0xe5, 0x48, 0x24} }, -{ 0x89b6, 16, {0x02, 0xff, 0xe4, 0x35, 0x47, 0xfe, 0xe5, 0x4b, 0x60, 0x10, 0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x85} }, -{ 0x89c6, 16, {0x4a, 0x82, 0x85, 0x49, 0x83, 0xf0, 0x15, 0x4b, 0x80, 0xec, 0x85, 0x48, 0x82, 0x85, 0x47, 0x83} }, -{ 0x89d6, 16, {0xa3, 0xe0, 0xff, 0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xe0, 0x25, 0xe0, 0x24, 0xb5, 0xf5, 0x82} }, -{ 0x89e6, 9, {0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xef, 0xf0, 0x7f, 0x00} }, -{ 0x89ef, 1, {0x22} }, -{ 0x89f0, 16, {0xef, 0x24, 0x01, 0xf5, 0x48, 0xe4, 0x3e, 0xf5, 0x47, 0x7c, 0x7b, 0x7d, 0x80, 0x7e, 0x7b, 0x7f} }, -{ 0x8a00, 16, {0x80, 0x8f, 0x82, 0x8e, 0x83, 0x74, 0x07, 0xf0, 0xef, 0x24, 0x01, 0xff, 0xe4, 0x3e, 0x90, 0x01} }, -{ 0x8a10, 16, {0x31, 0xf0, 0xa3, 0xef, 0xf0, 0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xfe} }, -{ 0x8a20, 16, {0xa3, 0xe0, 0x8e, 0x49, 0xf5, 0x4a, 0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xe0, 0x24, 0x9e, 0x60} }, -{ 0x8a30, 16, {0x61, 0x24, 0xf9, 0x60, 0x0e, 0x24, 0xf1, 0x70, 0x03, 0x02, 0x8a, 0xdd, 0x24, 0x14, 0x60, 0x03} }, -{ 0x8a40, 16, {0x02, 0x8b, 0x30, 0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xc3} }, -{ 0x8a50, 16, {0xe4, 0x9f, 0xf5, 0x4c, 0x74, 0x01, 0x9e, 0xf5, 0x4b, 0xd3, 0xe5, 0x4c, 0x94, 0x40, 0xe5, 0x4b} }, -{ 0x8a60, 16, {0x94, 0x00, 0x40, 0x06, 0x75, 0x4b, 0x00, 0x75, 0x4c, 0x40, 0xd3, 0xe5, 0x4a, 0x95, 0x4c, 0xe5} }, -{ 0x8a70, 16, {0x49, 0x95, 0x4b, 0x50, 0x03, 0x02, 0x8b, 0x30, 0xae, 0x4b, 0xaf, 0x4c, 0x85, 0x48, 0x82, 0x85} }, -{ 0x8a80, 16, {0x47, 0x83, 0xa3, 0xa3, 0xa3, 0xee, 0xf0, 0xfe, 0xa3, 0xef, 0xf0, 0x8e, 0x49, 0xf5, 0x4a, 0x02} }, -{ 0x8a90, 16, {0x8b, 0x30, 0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xc3, 0x74} }, -{ 0x8aa0, 16, {0x30, 0x9f, 0xf5, 0x4c, 0xe4, 0x9e, 0xf5, 0x4b, 0xd3, 0xe5, 0x4c, 0x94, 0x40, 0xe5, 0x4b, 0x94} }, -{ 0x8ab0, 16, {0x00, 0x40, 0x06, 0x75, 0x4b, 0x00, 0x75, 0x4c, 0x40, 0xd3, 0xe5, 0x4a, 0x95, 0x4c, 0xe5, 0x49} }, -{ 0x8ac0, 16, {0x95, 0x4b, 0x40, 0x6c, 0xae, 0x4b, 0xaf, 0x4c, 0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xa3, 0xa3} }, -{ 0x8ad0, 16, {0xa3, 0xee, 0xf0, 0xfe, 0xa3, 0xef, 0xf0, 0x8e, 0x49, 0xf5, 0x4a, 0x80, 0x53, 0x85, 0x48, 0x82} }, -{ 0x8ae0, 16, {0x85, 0x47, 0x83, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xc3, 0xe4, 0x9f, 0xf5, 0x4c, 0xe4, 0x9e} }, -{ 0x8af0, 16, {0xf5, 0x4b, 0x45, 0x4c, 0x70, 0x07, 0xf5, 0x4b, 0x75, 0x4c, 0x40, 0x80, 0x11, 0xd3, 0xe5, 0x4c} }, -{ 0x8b00, 16, {0x94, 0x40, 0xe5, 0x4b, 0x94, 0x00, 0x40, 0x06, 0x75, 0x4b, 0x00, 0x75, 0x4c, 0x40, 0xd3, 0xe5} }, -{ 0x8b10, 16, {0x4a, 0x95, 0x4c, 0xe5, 0x49, 0x95, 0x4b, 0x40, 0x17, 0xae, 0x4b, 0xaf, 0x4c, 0x85, 0x48, 0x82} }, -{ 0x8b20, 16, {0x85, 0x47, 0x83, 0xa3, 0xa3, 0xa3, 0xee, 0xf0, 0xfe, 0xa3, 0xef, 0xf0, 0x8e, 0x49, 0xf5, 0x4a} }, -{ 0x8b30, 16, {0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xe0, 0x24, 0x9e, 0x70, 0x03, 0x02, 0x8b, 0xf0, 0x24, 0xf9} }, -{ 0x8b40, 16, {0x60, 0x58, 0x24, 0xf1, 0x70, 0x03, 0x02, 0x8c, 0x40, 0x24, 0x14, 0x60, 0x03, 0x02, 0x8c, 0x84} }, -{ 0x8b50, 16, {0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xd3, 0x94, 0xff, 0xee} }, -{ 0x8b60, 16, {0x94, 0x00, 0x40, 0x03, 0x02, 0x8c, 0x84, 0x90, 0x01, 0x2c, 0xef, 0xf0, 0xe5, 0x4a, 0x15, 0x4a} }, -{ 0x8b70, 16, {0xae, 0x49, 0x70, 0x02, 0x15, 0x49, 0x4e, 0x70, 0x03, 0x02, 0x8c, 0x84, 0x90, 0x01, 0x2c, 0xe0} }, -{ 0x8b80, 16, {0xff, 0x04, 0xf0, 0xa8, 0x07, 0xe6, 0xff, 0x90, 0x01, 0x31, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9a} }, -{ 0x8b90, 16, {0xa4, 0x85, 0xf0, 0x82, 0xf5, 0x83, 0xef, 0xf0, 0x80, 0xd2, 0x85, 0x48, 0x82, 0x85, 0x47, 0x83} }, -{ 0x8ba0, 16, {0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xc3, 0x94, 0x80, 0xee, 0x94, 0x00, 0x50, 0x03, 0x02, 0x8c} }, -{ 0x8bb0, 16, {0x84, 0xd3, 0xef, 0x94, 0xff, 0xee, 0x94, 0x00, 0x40, 0x03, 0x02, 0x8c, 0x84, 0x90, 0x01, 0x2d} }, -{ 0x8bc0, 16, {0xef, 0xf0, 0xe5, 0x4a, 0x15, 0x4a, 0xae, 0x49, 0x70, 0x02, 0x15, 0x49, 0x4e, 0x70, 0x03, 0x02} }, -{ 0x8bd0, 16, {0x8c, 0x84, 0x90, 0x01, 0x2d, 0xe0, 0xff, 0x04, 0xf0, 0xa8, 0x07, 0xe6, 0xff, 0x90, 0x01, 0x31} }, -{ 0x8be0, 16, {0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9a, 0xa4, 0x85, 0xf0, 0x82, 0xf5, 0x83, 0xef, 0xf0, 0x80, 0xd2} }, -{ 0x8bf0, 16, {0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xc3, 0x94, 0x20, 0xee} }, -{ 0x8c00, 16, {0x94, 0x00, 0x50, 0x03, 0x02, 0x8c, 0x84, 0xd3, 0xef, 0x94, 0x2f, 0xee, 0x94, 0x00, 0x50, 0x74} }, -{ 0x8c10, 16, {0x90, 0x01, 0x2e, 0xef, 0xf0, 0xe5, 0x4a, 0x15, 0x4a, 0xae, 0x49, 0x70, 0x02, 0x15, 0x49, 0x4e} }, -{ 0x8c20, 16, {0x60, 0x62, 0x90, 0x01, 0x2e, 0xe0, 0xff, 0x04, 0xf0, 0xa8, 0x07, 0xe6, 0xff, 0x90, 0x01, 0x31} }, -{ 0x8c30, 16, {0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9a, 0xa4, 0x85, 0xf0, 0x82, 0xf5, 0x83, 0xef, 0xf0, 0x80, 0xd5} }, -{ 0x8c40, 16, {0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xa3, 0xe0, 0xff, 0xa3, 0xe0, 0x90, 0x01, 0x2f, 0xcf, 0xf0} }, -{ 0x8c50, 16, {0xa3, 0xef, 0xf0, 0xe5, 0x4a, 0x15, 0x4a, 0xae, 0x49, 0x70, 0x02, 0x15, 0x49, 0x4e, 0x60, 0x24} }, -{ 0x8c60, 16, {0x90, 0x01, 0x2f, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9a, 0xa4, 0x85, 0xf0, 0x82, 0xf5, 0x83, 0xe0} }, -{ 0x8c70, 16, {0xff, 0x90, 0x01, 0x31, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9a, 0xa4, 0x85, 0xf0, 0x82, 0xf5, 0x83} }, -{ 0x8c80, 16, {0xef, 0xf0, 0x80, 0xcf, 0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xa3, 0xe0} }, -{ 0x8c90, 6, {0x90, 0x7f, 0xc3, 0xf0, 0x7f, 0x00} }, -{ 0x8c96, 1, {0x22} }, -{ 0x8c97, 16, {0x7e, 0x7b, 0x7f, 0x80, 0xef, 0x24, 0x01, 0xfd, 0xe4, 0x3e, 0xfc, 0x8f, 0x82, 0x8e, 0x83, 0x74} }, -{ 0x8ca7, 16, {0x0b, 0xf0, 0x90, 0x20, 0x70, 0xe0, 0x54, 0xf0, 0xff, 0xc4, 0x54, 0x0f, 0x8d, 0x82, 0x8c, 0x83} }, -{ 0x8cb7, 16, {0xf0, 0x90, 0x11, 0xf0, 0xe4, 0x93, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xf0, 0x90, 0x11, 0xf1, 0xe4} }, -{ 0x8cc7, 16, {0x93, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xf0, 0xe4, 0x90, 0x01, 0x33, 0xf0, 0xa3, 0xf0, 0xa3} }, -{ 0x8cd7, 16, {0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0x74, 0x10, 0xf0, 0xed, 0x24, 0x03, 0xfe, 0xe4, 0x3c, 0xa3} }, -{ 0x8ce7, 16, {0xf0, 0xa3, 0xce, 0xf0, 0x7e, 0x01, 0x7f, 0x33, 0x12, 0x19, 0xc1, 0x90, 0x7f, 0xc3, 0x74, 0x14} }, -{ 0x8cf7, 3, {0xf0, 0x7f, 0x00} }, -{ 0x8cfa, 1, {0x22} }, -{ 0x8cfb, 4, {0x8e, 0x40, 0x8f, 0x41} }, -{ 0x8cff, 16, {0x85, 0x40, 0x43, 0x85, 0x41, 0x44, 0x85, 0x44, 0x82, 0x85, 0x43, 0x83, 0xe0, 0x14, 0xb4, 0x0f} }, -{ 0x8d0f, 16, {0x00, 0x40, 0x03, 0x02, 0x8e, 0x32, 0x90, 0x8d, 0x1c, 0xf8, 0x28, 0x28, 0x73, 0x02, 0x8d, 0x49} }, -{ 0x8d1f, 16, {0x02, 0x8d, 0x5a, 0x02, 0x8d, 0x6b, 0x02, 0x8d, 0x8e, 0x02, 0x8d, 0x9f, 0x02, 0x8d, 0xb0, 0x02} }, -{ 0x8d2f, 16, {0x8d, 0xc0, 0x02, 0x8d, 0xcb, 0x02, 0x8d, 0xdb, 0x02, 0x8d, 0xeb, 0x02, 0x8d, 0xfb, 0x02, 0x8e} }, -{ 0x8d3f, 16, {0x02, 0x02, 0x8e, 0x32, 0x02, 0x8e, 0x12, 0x02, 0x8e, 0x22, 0xe5, 0x44, 0x24, 0x01, 0xff, 0xe4} }, -{ 0x8d4f, 16, {0x35, 0x43, 0xfe, 0x12, 0x82, 0xea, 0x8f, 0x42, 0x02, 0x8e, 0x32, 0xe5, 0x44, 0x24, 0x01, 0xff} }, -{ 0x8d5f, 16, {0xe4, 0x35, 0x43, 0xfe, 0x12, 0x83, 0x9f, 0x8f, 0x42, 0x02, 0x8e, 0x32, 0xe5, 0x44, 0x24, 0x01} }, -{ 0x8d6f, 16, {0xf5, 0x46, 0xe4, 0x35, 0x43, 0xf5, 0x45, 0xe5, 0x46, 0x24, 0x01, 0xff, 0xe4, 0x35, 0x45, 0xfe} }, -{ 0x8d7f, 16, {0x12, 0x84, 0x61, 0xaf, 0x46, 0xae, 0x45, 0x12, 0x84, 0xf4, 0x8f, 0x42, 0x02, 0x8e, 0x32, 0xe5} }, -{ 0x8d8f, 16, {0x44, 0x24, 0x01, 0xff, 0xe4, 0x35, 0x43, 0xfe, 0x12, 0x88, 0x92, 0x8f, 0x42, 0x02, 0x8e, 0x32} }, -{ 0x8d9f, 16, {0xe5, 0x44, 0x24, 0x01, 0xff, 0xe4, 0x35, 0x43, 0xfe, 0x12, 0x88, 0xce, 0x8f, 0x42, 0x02, 0x8e} }, -{ 0x8daf, 16, {0x32, 0xe5, 0x44, 0x24, 0x01, 0xff, 0xe4, 0x35, 0x43, 0xfe, 0x12, 0x89, 0x0a, 0x8f, 0x42, 0x80} }, -{ 0x8dbf, 16, {0x72, 0xaf, 0x41, 0xae, 0x40, 0x12, 0x89, 0xf0, 0x8f, 0x42, 0x80, 0x67, 0xe5, 0x44, 0x24, 0x01} }, -{ 0x8dcf, 16, {0xff, 0xe4, 0x35, 0x43, 0xfe, 0x12, 0x87, 0x96, 0x8f, 0x42, 0x80, 0x57, 0xe5, 0x44, 0x24, 0x01} }, -{ 0x8ddf, 16, {0xff, 0xe4, 0x35, 0x43, 0xfe, 0x12, 0x84, 0x1d, 0x8f, 0x42, 0x80, 0x47, 0xe5, 0x44, 0x24, 0x01} }, -{ 0x8def, 16, {0xff, 0xe4, 0x35, 0x43, 0xfe, 0x12, 0x88, 0x50, 0x8f, 0x42, 0x80, 0x37, 0x12, 0x8c, 0x97, 0x8f} }, -{ 0x8dff, 16, {0x42, 0x80, 0x30, 0xe5, 0x44, 0x24, 0x01, 0xff, 0xe4, 0x35, 0x43, 0xfe, 0x12, 0x11, 0xd8, 0x8f} }, -{ 0x8e0f, 16, {0x42, 0x80, 0x20, 0xe5, 0x44, 0x24, 0x01, 0xff, 0xe4, 0x35, 0x43, 0xfe, 0x12, 0x89, 0x42, 0x8f} }, -{ 0x8e1f, 16, {0x42, 0x80, 0x10, 0xaf, 0x41, 0xae, 0x40, 0x7c, 0x02, 0x7d, 0x4d, 0x7b, 0x40, 0x12, 0x1b, 0x0c} }, -{ 0x8e2f, 5, {0xe4, 0xf5, 0x42, 0xaf, 0x42} }, -{ 0x8e34, 1, {0x22} }, -{ 0x8e35, 8, {0x8f, 0x61, 0x8e, 0x60, 0x8d, 0x5f, 0x8c, 0x5e} }, -{ 0x8e3d, 16, {0x75, 0x68, 0x01, 0x75, 0x69, 0x3b, 0xe4, 0xf5, 0x67, 0xaf, 0x63, 0x15, 0x63, 0xef, 0x70, 0x03} }, -{ 0x8e4d, 16, {0x02, 0x8e, 0xd3, 0xaf, 0x62, 0xe4, 0xfc, 0xfd, 0xfe, 0xf8, 0xf9, 0xfa, 0xab, 0x07, 0xaf, 0x61} }, -{ 0x8e5d, 16, {0xae, 0x60, 0xad, 0x5f, 0xac, 0x5e, 0x12, 0x9b, 0x2e, 0xaf, 0x03, 0x8f, 0x66, 0xaf, 0x61, 0xae} }, -{ 0x8e6d, 16, {0x60, 0xad, 0x5f, 0xac, 0x5e, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0xaf, 0x62, 0xe4} }, -{ 0x8e7d, 16, {0xfc, 0xfd, 0xfe, 0xf8, 0xf9, 0xfa, 0xab, 0x07, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04} }, -{ 0x8e8d, 16, {0x12, 0x9b, 0x2e, 0x8f, 0x61, 0x8e, 0x60, 0x8d, 0x5f, 0x8c, 0x5e, 0xe5, 0x66, 0x24, 0x30, 0xf5} }, -{ 0x8e9d, 16, {0x66, 0xd3, 0x94, 0x39, 0x40, 0x06, 0x74, 0x07, 0x25, 0x66, 0xf5, 0x66, 0x05, 0x69, 0xe5, 0x69} }, -{ 0x8ead, 16, {0xae, 0x68, 0x70, 0x02, 0x05, 0x68, 0x14, 0xf5, 0x82, 0x8e, 0x83, 0xe4, 0xf0, 0x05, 0x69, 0xe5} }, -{ 0x8ebd, 16, {0x69, 0xae, 0x68, 0x70, 0x02, 0x05, 0x68, 0x14, 0xf5, 0x82, 0x8e, 0x83, 0xe5, 0x66, 0xf0, 0x05} }, -{ 0x8ecd, 16, {0x67, 0x05, 0x67, 0x02, 0x8e, 0x46, 0xe5, 0x69, 0x15, 0x69, 0x70, 0x02, 0x15, 0x68, 0xaf, 0x67} }, -{ 0x8edd, 16, {0x15, 0x67, 0xef, 0x60, 0x23, 0xe5, 0x69, 0x15, 0x69, 0xae, 0x68, 0x70, 0x02, 0x15, 0x68, 0xf5} }, -{ 0x8eed, 16, {0x82, 0x8e, 0x83, 0xe0, 0xff, 0x05, 0x65, 0xe5, 0x65, 0xac, 0x64, 0x70, 0x02, 0x05, 0x64, 0x14} }, -{ 0x8efd, 8, {0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x80, 0xd6} }, -{ 0x8f05, 1, {0x22} }, -{ 0x8f06, 16, {0xe4, 0x90, 0x01, 0x67, 0xf0, 0x7e, 0x01, 0x7f, 0x68, 0x90, 0x01, 0x5c, 0xee, 0xf0, 0xa3, 0xef} }, -{ 0x8f16, 10, {0xf0, 0x90, 0x01, 0x60, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x22} }, -{ 0x8f20, 16, {0xaa, 0x07, 0xa9, 0x05, 0x90, 0x01, 0x67, 0xe0, 0xc3, 0x94, 0x40, 0x50, 0x61, 0xac, 0x02, 0x74} }, -{ 0x8f30, 16, {0x01, 0x7e, 0x00, 0xa8, 0x04, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff} }, -{ 0x8f40, 16, {0xe4, 0xef, 0x55, 0x30, 0x60, 0x45, 0xea, 0x04, 0xff, 0x90, 0x01, 0x60, 0xe0, 0xfc, 0xa3, 0xe0} }, -{ 0x8f50, 16, {0xfd, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0xa3, 0xe9, 0xf0, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3} }, -{ 0x8f60, 16, {0xeb, 0xf0, 0x90, 0x01, 0x60, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x9a, 0x8e, 0xfc, 0xd3, 0xe5, 0xf0} }, -{ 0x8f70, 16, {0x94, 0x25, 0xec, 0x94, 0x02, 0x40, 0x0a, 0x90, 0x01, 0x60, 0x74, 0x01, 0xf0, 0xa3, 0x74, 0x68} }, -{ 0x8f80, 16, {0xf0, 0xc2, 0xaf, 0x90, 0x01, 0x67, 0xe0, 0x04, 0xf0, 0xd2, 0xaf, 0x7f, 0x01, 0x22, 0x7f, 0x00} }, -{ 0x8f90, 1, {0x22} }, -{ 0x8f91, 16, {0x90, 0x01, 0x67, 0xe0, 0xd3, 0x94, 0x00, 0x40, 0x55, 0x90, 0x01, 0x5c, 0xe0, 0xfc, 0xa3, 0xe0} }, -{ 0x8fa1, 16, {0xaa, 0x04, 0xf9, 0x7b, 0x01, 0xc0, 0x03, 0xc0, 0x02, 0xc0, 0x01, 0xaa, 0x06, 0xa9, 0x07, 0xa8} }, -{ 0x8fb1, 16, {0x01, 0xac, 0x02, 0xad, 0x03, 0xd0, 0x01, 0xd0, 0x02, 0xd0, 0x03, 0x7e, 0x00, 0x7f, 0x03, 0x12} }, -{ 0x8fc1, 16, {0x9a, 0x1f, 0x90, 0x01, 0x5c, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x9a, 0x8e, 0xfc, 0xd3, 0xe5, 0xf0} }, -{ 0x8fd1, 16, {0x94, 0x25, 0xec, 0x94, 0x02, 0x40, 0x0a, 0x90, 0x01, 0x5c, 0x74, 0x01, 0xf0, 0xa3, 0x74, 0x68} }, -{ 0x8fe1, 16, {0xf0, 0xc2, 0xaf, 0x90, 0x01, 0x67, 0xe0, 0x14, 0xf0, 0xd2, 0xaf, 0x7f, 0x01, 0x22, 0x7f, 0x00} }, -{ 0x8ff1, 1, {0x22} }, -{ 0x8ff2, 16, {0x90, 0x7f, 0xc2, 0xe0, 0x20, 0xe1, 0x5e, 0x7e, 0x7b, 0x7f, 0x80, 0x75, 0x63, 0x7b, 0x75, 0x64} }, -{ 0x9002, 16, {0x80, 0xe5, 0x64, 0x24, 0x01, 0xff, 0xe4, 0x35, 0x63, 0xa9, 0x07, 0x7b, 0x01, 0x8b, 0x65, 0xf5} }, -{ 0x9012, 16, {0x66, 0x89, 0x67, 0xfe, 0x12, 0x8f, 0x91, 0xef, 0x60, 0x3b, 0xab, 0x65, 0xaa, 0x66, 0xa9, 0x67} }, -{ 0x9022, 16, {0x12, 0x9a, 0x48, 0x14, 0xff, 0x90, 0x00, 0x01, 0x12, 0x9a, 0x61, 0xb4, 0x02, 0x16, 0xc2, 0xaf} }, -{ 0x9032, 16, {0xef, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x01, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0, 0x44} }, -{ 0x9042, 16, {0x04, 0xf0, 0xd2, 0xaf, 0x85, 0x64, 0x82, 0x85, 0x63, 0x83, 0x74, 0x0d, 0xf0, 0x90, 0x7f, 0xc3} }, -{ 0x9052, 5, {0x74, 0x04, 0xf0, 0xd2, 0xaf} }, -{ 0x9057, 1, {0x22} }, -{ 0x9058, 16, {0x12, 0x8f, 0xf2, 0xe4, 0xf5, 0x5e, 0x74, 0x36, 0x25, 0x5e, 0xf8, 0xe6, 0x54, 0xf0, 0xf5, 0x5f} }, -{ 0x9068, 16, {0x74, 0x63, 0x25, 0x5e, 0xf5, 0x82, 0xe4, 0x34, 0x01, 0xf5, 0x83, 0xe0, 0x65, 0x5f, 0xff, 0xc4} }, -{ 0x9078, 16, {0x54, 0x0f, 0xf5, 0x60, 0x60, 0x22, 0x74, 0x63, 0x25, 0x5e, 0xf5, 0x82, 0xe4, 0x34, 0x01, 0xf5} }, -{ 0x9088, 16, {0x83, 0xe5, 0x5f, 0xf0, 0xaf, 0x5e, 0x7d, 0x01, 0xe5, 0x5f, 0x45, 0x60, 0xfb, 0x12, 0x8f, 0x20} }, -{ 0x9098, 16, {0xef, 0x70, 0x05, 0x12, 0x8f, 0xf2, 0x80, 0xec, 0x05, 0x5e, 0xe5, 0x5e, 0xc3, 0x94, 0x04, 0x40} }, -{ 0x90a8, 16, {0xb5, 0x12, 0x8f, 0xf2, 0xe5, 0x3a, 0x60, 0x48, 0xe4, 0xf5, 0x5e, 0xaf, 0x5e, 0x74, 0x01, 0xa8} }, -{ 0x90b8, 16, {0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xf5, 0x5f, 0x55, 0x3a, 0x60, 0x29, 0xe5, 0x5e} }, -{ 0x90c8, 16, {0x75, 0xf0, 0x08, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0, 0x30, 0xe6} }, -{ 0x90d8, 16, {0x16, 0xaf, 0x5e, 0x7d, 0x04, 0x7b, 0x80, 0x12, 0x8f, 0x20, 0xef, 0x70, 0x05, 0x12, 0x8f, 0xf2} }, -{ 0x90e8, 16, {0x80, 0xef, 0xe5, 0x5f, 0xf4, 0x52, 0x3a, 0x05, 0x5e, 0xe5, 0x5e, 0xc3, 0x94, 0x04, 0x40, 0xbb} }, -{ 0x90f8, 16, {0x90, 0x02, 0x9e, 0xe0, 0x60, 0x03, 0x02, 0x91, 0xc5, 0x74, 0x19, 0xf0, 0x7f, 0x02, 0x12, 0x81} }, -{ 0x9108, 16, {0x11, 0x8e, 0x61, 0x8f, 0x62, 0xc3, 0xe5, 0x61, 0x64, 0x80, 0x94, 0x80, 0x40, 0xee, 0x90, 0x01} }, -{ 0x9118, 16, {0x5b, 0xe0, 0x65, 0x62, 0xf0, 0x60, 0x37, 0xe4, 0xf5, 0x5e, 0xaf, 0x5e, 0x74, 0x01, 0xa8, 0x07} }, -{ 0x9128, 16, {0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xf5, 0x5f, 0x90, 0x01, 0x5b, 0xe0, 0x55, 0x5f, 0x60} }, -{ 0x9138, 16, {0x14, 0xaf, 0x5e, 0x7d, 0x08, 0xe5, 0x5f, 0x55, 0x62, 0xfb, 0x12, 0x8f, 0x20, 0xef, 0x70, 0x05} }, -{ 0x9148, 16, {0x12, 0x8f, 0xf2, 0x80, 0xec, 0x05, 0x5e, 0xe5, 0x5e, 0xc3, 0x94, 0x04, 0x40, 0xcc, 0x90, 0x01} }, -{ 0x9158, 16, {0x5b, 0xe5, 0x62, 0xf0, 0xe4, 0xf5, 0x5e, 0xc2, 0xaf, 0x74, 0x32, 0x25, 0x5e, 0xf8, 0xe6, 0xf5} }, -{ 0x9168, 16, {0x5f, 0xe4, 0xf6, 0xd2, 0xaf, 0x53, 0x5f, 0x1e, 0xe5, 0x5f, 0x60, 0x11, 0xaf, 0x5e, 0x7d, 0x02} }, -{ 0x9178, 16, {0xab, 0x5f, 0x12, 0x8f, 0x20, 0xef, 0x70, 0x05, 0x12, 0x8f, 0xf2, 0x80, 0xef, 0x74, 0x2c, 0x25} }, -{ 0x9188, 16, {0x5e, 0xf8, 0xe6, 0xf5, 0x5f, 0x74, 0x9a, 0x25, 0x5e, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83} }, -{ 0x9198, 16, {0xe0, 0x65, 0x5f, 0x60, 0x11, 0xaf, 0x5e, 0x7d, 0x04, 0xab, 0x5f, 0x12, 0x8f, 0x20, 0xef, 0x70} }, -{ 0x91a8, 16, {0x05, 0x12, 0x8f, 0xf2, 0x80, 0xef, 0x74, 0x9a, 0x25, 0x5e, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5} }, -{ 0x91b8, 16, {0x83, 0xe5, 0x5f, 0xf0, 0x05, 0x5e, 0xe5, 0x5e, 0xc3, 0x94, 0x04, 0x40, 0x9a, 0x12, 0x8f, 0xf2} }, -{ 0x91c8, 1, {0x22} }, -{ 0x91c9, 12, {0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x6e, 0x02, 0x92, 0x10} }, -{ 0x91d5, 16, {0x02, 0x05, 0x28, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2} }, -{ 0x91e5, 16, {0x08, 0xdf, 0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33} }, -{ 0x91f5, 16, {0xc4, 0x54, 0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf} }, -{ 0x9205, 16, {0xe4, 0x80, 0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x92, 0x55, 0xe4, 0x7e} }, -{ 0x9215, 16, {0x01, 0x93, 0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93} }, -{ 0x9225, 16, {0xa3, 0x60, 0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3} }, -{ 0x9235, 16, {0xfa, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca} }, -{ 0x9245, 16, {0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe} }, -{ 0x9255, 16, {0x60, 0x24, 0x02, 0x28, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x81, 0x82, 0x84, 0x88} }, -{ 0x9265, 16, {0x90, 0xa0, 0xc0, 0xc1, 0xc2, 0xc4, 0xc8, 0xd0, 0xe0, 0xe1, 0xe2, 0xe4, 0xe8, 0xf0, 0xf1, 0xf2} }, -{ 0x9275, 8, {0xf4, 0xf8, 0xf9, 0xfa, 0xfc, 0xfd, 0xfe, 0xff} }, -{ 0x927d, 1, {0x00} }, -{ 0x927e, 11, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x18} }, -{ 0x9289, 16, {0x90, 0x20, 0x60, 0xe0, 0x54, 0x0f, 0xfe, 0x30, 0xe0, 0x05, 0x90, 0x20, 0x02, 0xe0, 0xff, 0xee} }, -{ 0x9299, 16, {0x30, 0xe1, 0x05, 0x90, 0x20, 0x0a, 0xe0, 0xff, 0xee, 0x30, 0xe2, 0x05, 0x90, 0x20, 0x12, 0xe0} }, -{ 0x92a9, 16, {0xff, 0xee, 0x30, 0xe3, 0x05, 0x90, 0x20, 0x1a, 0xe0, 0xff, 0x90, 0x01, 0x62, 0xe0, 0xb5, 0x1e} }, -{ 0x92b9, 10, {0x04, 0xe4, 0xf0, 0x80, 0x05, 0x90, 0x01, 0x62, 0xee, 0xf0} }, -{ 0x92c3, 9, {0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, -{ 0x92cc, 2, {0xa9, 0x03} }, -{ 0x92ce, 16, {0xef, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xab, 0x82, 0xfa, 0xe5} }, -{ 0x92de, 16, {0x6c, 0x45, 0x6d, 0xf5, 0x6e, 0xe9, 0x60, 0x14, 0x8a, 0x83, 0xe5, 0x82, 0x24, 0x04, 0xf5, 0x82} }, -{ 0x92ee, 16, {0xe4, 0x35, 0x83, 0xf5, 0x83, 0xe0, 0x4d, 0xf0, 0xe4, 0xfe, 0x80, 0x13, 0xeb, 0x24, 0x04, 0xf5} }, -{ 0x92fe, 16, {0x82, 0xe4, 0x3a, 0xf5, 0x83, 0xe0, 0xff, 0xed, 0xf4, 0xfc, 0xef, 0x5c, 0xf0, 0xae, 0x6e, 0xeb} }, -{ 0x930e, 16, {0x24, 0x06, 0xf5, 0x82, 0xe4, 0x3a, 0xf5, 0x83, 0xe0, 0x55, 0x6e, 0xfc, 0xb5, 0x06, 0x03, 0xaf} }, -{ 0x931e, 16, {0x05, 0x22, 0xe5, 0x6c, 0x5c, 0xfe, 0xe5, 0x6d, 0x5c, 0xfd, 0xe9, 0x60, 0x16, 0xee, 0x70, 0x04} }, -{ 0x932e, 16, {0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0xae, 0x07, 0xed, 0x70, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f} }, -{ 0x933e, 16, {0x00, 0xad, 0x07, 0xee, 0x60, 0x03, 0xaf, 0x6c, 0x22, 0xed, 0x60, 0x03, 0xaf, 0x6d, 0x22, 0x7f} }, -{ 0x934e, 1, {0x00} }, -{ 0x934f, 1, {0x22} }, -{ 0x9350, 16, {0x7e, 0x7b, 0x7f, 0x80, 0xef, 0x24, 0x01, 0xf5, 0x66, 0xe4, 0x3e, 0xf5, 0x65, 0x75, 0x63, 0x02} }, -{ 0x9360, 16, {0x75, 0x64, 0x4e, 0x8f, 0x82, 0x8e, 0x83, 0x74, 0x0f, 0xf0, 0x85, 0x64, 0x82, 0x85, 0x63, 0x83} }, -{ 0x9370, 16, {0xe0, 0x85, 0x66, 0x82, 0x85, 0x65, 0x83, 0xf0, 0x85, 0x64, 0x82, 0x85, 0x63, 0x83, 0xa3, 0xe0} }, -{ 0x9380, 16, {0x85, 0x66, 0x82, 0x85, 0x65, 0x83, 0xa3, 0xf0, 0x85, 0x66, 0x82, 0x85, 0x65, 0x83, 0xa3, 0xa3} }, -{ 0x9390, 16, {0x74, 0xff, 0xf0, 0xe5, 0x66, 0x24, 0x03, 0xf5, 0x68, 0xe4, 0x35, 0x65, 0xf5, 0x67, 0x85, 0x64} }, -{ 0x93a0, 16, {0x82, 0x85, 0x63, 0x83, 0xe0, 0x14, 0xb4, 0x0b, 0x00, 0x40, 0x03, 0x02, 0x98, 0x43, 0x90, 0x93} }, -{ 0x93b0, 16, {0xb5, 0xf8, 0x28, 0x28, 0x73, 0x02, 0x93, 0xd6, 0x02, 0x94, 0x7c, 0x02, 0x95, 0xba, 0x02, 0x95} }, -{ 0x93c0, 16, {0xda, 0x02, 0x95, 0xda, 0x02, 0x96, 0x7f, 0x02, 0x96, 0xbd, 0x02, 0x96, 0xe4, 0x02, 0x97, 0xa6} }, -{ 0x93d0, 16, {0x02, 0x97, 0xda, 0x02, 0x98, 0x0b, 0xe4, 0xf5, 0x5e, 0xe5, 0x5e, 0x75, 0xf0, 0x08, 0xa4, 0x24} }, -{ 0x93e0, 16, {0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xaf, 0x82, 0xf5, 0x61, 0x8f, 0x62, 0xe4, 0xff, 0xe4, 0xfe} }, -{ 0x93f0, 16, {0xef, 0x60, 0x10, 0x74, 0x28, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe0, 0xf4, 0xf5} }, -{ 0x9400, 16, {0x5f, 0x80, 0x0d, 0x74, 0x28, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe0, 0xf5, 0x5f} }, -{ 0x9410, 16, {0xe5, 0x62, 0x24, 0x07, 0xf5, 0x82, 0xe4, 0x35, 0x61, 0xf5, 0x83, 0xe5, 0x5f, 0xf0, 0xe0, 0xf5} }, -{ 0x9420, 16, {0x60, 0x65, 0x5f, 0x60, 0x3d, 0x85, 0x66, 0x82, 0x85, 0x65, 0x83, 0xa3, 0xa3, 0xe4, 0xf0, 0xe5} }, -{ 0x9430, 16, {0x5e, 0x04, 0xfd, 0x05, 0x68, 0xe5, 0x68, 0xaa, 0x67, 0x70, 0x02, 0x05, 0x67, 0x14, 0xf5, 0x82} }, -{ 0x9440, 16, {0x8a, 0x83, 0xed, 0xf0, 0x05, 0x68, 0xe5, 0x68, 0xac, 0x67, 0x70, 0x02, 0x05, 0x67, 0x14, 0xf5} }, -{ 0x9450, 16, {0x82, 0x8c, 0x83, 0xe5, 0x5f, 0xf0, 0x85, 0x68, 0x82, 0x85, 0x67, 0x83, 0xe5, 0x60, 0xf0, 0x02} }, -{ 0x9460, 16, {0x98, 0x4e, 0x0e, 0xee, 0x64, 0x24, 0x70, 0x88, 0x0f, 0xef, 0x64, 0x02, 0x70, 0x80, 0x05, 0x5e} }, -{ 0x9470, 16, {0xe5, 0x5e, 0x64, 0x04, 0x60, 0x03, 0x02, 0x93, 0xd9, 0x02, 0x98, 0x4e, 0x7e, 0x20, 0x7f, 0x00} }, -{ 0x9480, 16, {0x75, 0x61, 0x20, 0x75, 0x62, 0x00, 0xe4, 0xf5, 0x5e, 0xaf, 0x62, 0xae, 0x61, 0xe4, 0xfd, 0x12} }, -{ 0x9490, 16, {0x81, 0xe0, 0x74, 0x08, 0x25, 0x62, 0xf5, 0x62, 0xe4, 0x35, 0x61, 0xf5, 0x61, 0x05, 0x5e, 0xe5} }, -{ 0x94a0, 16, {0x5e, 0xd3, 0x94, 0x03, 0x40, 0xe3, 0x90, 0x00, 0x04, 0x74, 0x92, 0xf0, 0xa3, 0x74, 0x7e, 0xf0} }, -{ 0x94b0, 16, {0xe4, 0xf5, 0x60, 0x7e, 0x20, 0x7f, 0x00, 0x75, 0x61, 0x20, 0x75, 0x62, 0x00, 0xf5, 0x5e, 0xaf} }, -{ 0x94c0, 16, {0x5e, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xf5, 0x5f, 0x90, 0x01} }, -{ 0x94d0, 16, {0x62, 0xf0, 0x90, 0x01, 0x5e, 0xe4, 0xf0, 0xa3, 0x74, 0x0a, 0xf0, 0x85, 0x62, 0x82, 0x85, 0x61} }, -{ 0x94e0, 16, {0x83, 0xa3, 0x74, 0x02, 0xf0, 0x90, 0x01, 0x62, 0xe0, 0x65, 0x5f, 0x70, 0x39, 0x90, 0x01, 0x5e} }, -{ 0x94f0, 16, {0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x70, 0xee, 0x85, 0x66, 0x82, 0x85, 0x65, 0x83, 0xa3, 0xa3, 0xf0} }, -{ 0x9500, 16, {0xe5, 0x5e, 0x04, 0xff, 0x05, 0x68, 0xe5, 0x68, 0xac, 0x67, 0x70, 0x02, 0x05, 0x67, 0x14, 0xf5} }, -{ 0x9510, 16, {0x82, 0x8c, 0x83, 0xef, 0xf0, 0x85, 0x68, 0x82, 0x85, 0x67, 0x83, 0x74, 0xff, 0xf0, 0xe4, 0x90} }, -{ 0x9520, 16, {0x01, 0x62, 0xf0, 0x75, 0x60, 0xff, 0x90, 0x01, 0x62, 0xe0, 0xff, 0x60, 0x3c, 0x85, 0x66, 0x82} }, -{ 0x9530, 16, {0x85, 0x65, 0x83, 0xa3, 0xa3, 0xe4, 0xf0, 0xe5, 0x5e, 0x04, 0xfe, 0x05, 0x68, 0xe5, 0x68, 0xac} }, -{ 0x9540, 16, {0x67, 0x70, 0x02, 0x05, 0x67, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xee, 0xf0, 0x05, 0x68, 0xe5, 0x68} }, -{ 0x9550, 16, {0xac, 0x67, 0x70, 0x02, 0x05, 0x67, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x85, 0x68, 0x82} }, -{ 0x9560, 16, {0x85, 0x67, 0x83, 0xe5, 0x5f, 0xf0, 0x75, 0x60, 0xff, 0xe5, 0x60, 0x70, 0x16, 0x74, 0x08, 0x25} }, -{ 0x9570, 16, {0x62, 0xf5, 0x62, 0xe4, 0x35, 0x61, 0xf5, 0x61, 0x05, 0x5e, 0xe5, 0x5e, 0x64, 0x04, 0x60, 0x03} }, -{ 0x9580, 16, {0x02, 0x94, 0xbf, 0x7e, 0x20, 0x7f, 0x00, 0x75, 0x61, 0x20, 0x75, 0x62, 0x00, 0xe4, 0xf5, 0x5e} }, -{ 0x9590, 16, {0xaf, 0x62, 0xae, 0x61, 0x7d, 0x01, 0x12, 0x81, 0xe0, 0x74, 0x08, 0x25, 0x62, 0xf5, 0x62, 0xe4} }, -{ 0x95a0, 16, {0x35, 0x61, 0xf5, 0x61, 0x05, 0x5e, 0xe5, 0x5e, 0xd3, 0x94, 0x03, 0x40, 0xe3, 0x90, 0x00, 0x04} }, -{ 0x95b0, 16, {0x74, 0x13, 0xf0, 0xa3, 0x74, 0x12, 0xf0, 0x02, 0x98, 0x4e, 0x85, 0x64, 0x82, 0x85, 0x63, 0x83} }, -{ 0x95c0, 16, {0xa3, 0xe0, 0x14, 0xff, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x90} }, -{ 0x95d0, 16, {0x02, 0x95, 0xf0, 0x90, 0x01, 0x62, 0xf0, 0x02, 0x98, 0x4e, 0x90, 0x01, 0x5e, 0x74, 0x03, 0xf0} }, -{ 0x95e0, 16, {0xa3, 0x74, 0xe8, 0xf0, 0xe4, 0xf5, 0x60, 0x90, 0x02, 0x95, 0xe0, 0xff, 0x90, 0x01, 0x62, 0xe0} }, -{ 0x95f0, 16, {0xb5, 0x07, 0x1e, 0x90, 0x01, 0x5e, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x70, 0xea, 0x85, 0x66, 0x82} }, -{ 0x9600, 16, {0x85, 0x65, 0x83, 0xa3, 0xa3, 0xf0, 0x85, 0x68, 0x82, 0x85, 0x67, 0x83, 0x74, 0xff, 0xf0, 0xf5} }, -{ 0x9610, 16, {0x60, 0xe5, 0x60, 0x60, 0x03, 0x02, 0x98, 0x4e, 0x90, 0x01, 0x5e, 0xf0, 0xa3, 0x74, 0x96, 0xf0} }, -{ 0x9620, 16, {0x90, 0x01, 0x5e, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x70, 0xf6, 0x7f, 0x02, 0x12, 0x81, 0x11, 0xc3} }, -{ 0x9630, 16, {0xee, 0x64, 0x80, 0x94, 0x80, 0x40, 0xf3, 0xef, 0x54, 0x0f, 0xf5, 0x60, 0x90, 0x02, 0x95, 0xe0} }, -{ 0x9640, 16, {0x55, 0x60, 0x70, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0x8f, 0x5f, 0x85, 0x64, 0x82, 0x85} }, -{ 0x9650, 16, {0x63, 0x83, 0xe0, 0xb4, 0x05, 0x0c, 0xe5, 0x5f, 0x70, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00} }, -{ 0x9660, 16, {0x8f, 0x5f, 0xe5, 0x5f, 0x70, 0x03, 0x02, 0x98, 0x4e, 0x85, 0x66, 0x82, 0x85, 0x65, 0x83, 0xa3} }, -{ 0x9670, 16, {0xa3, 0xe4, 0xf0, 0x85, 0x68, 0x82, 0x85, 0x67, 0x83, 0xe5, 0x60, 0xf0, 0x02, 0x98, 0x4e, 0x7e} }, -{ 0x9680, 16, {0x20, 0x7f, 0x00, 0x75, 0x61, 0x20, 0x75, 0x62, 0x00, 0xaf, 0x62, 0xae, 0x61, 0xe4, 0xfd, 0x12} }, -{ 0x9690, 16, {0x81, 0xe0, 0x85, 0x62, 0x82, 0x85, 0x61, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0x44, 0x80, 0xf0, 0x85} }, -{ 0x96a0, 16, {0x62, 0x82, 0x85, 0x61, 0x83, 0x74, 0x01, 0xf0, 0xa3, 0xe4, 0xf0, 0x85, 0x62, 0x82, 0x85, 0x61} }, -{ 0x96b0, 16, {0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0x54, 0x7f, 0xf0, 0xd2, 0x04, 0x02, 0x98, 0x4e, 0xc2, 0x04, 0x7e} }, -{ 0x96c0, 16, {0x20, 0x7f, 0x00, 0x75, 0x61, 0x20, 0x75, 0x62, 0x00, 0xe5, 0x62, 0x24, 0x05, 0xf5, 0x82, 0xe4} }, -{ 0x96d0, 16, {0x35, 0x61, 0xf5, 0x83, 0xe0, 0x30, 0xe6, 0xf1, 0xaf, 0x62, 0xae, 0x61, 0x7d, 0x01, 0x12, 0x81} }, -{ 0x96e0, 16, {0xe0, 0x02, 0x98, 0x4e, 0xe4, 0xf5, 0x60, 0xf5, 0x5e, 0xe5, 0x5e, 0x75, 0xf0, 0x08, 0xa4, 0x24} }, -{ 0x96f0, 16, {0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xaf, 0x82, 0xf5, 0x61, 0x8f, 0x62, 0xfe, 0xe4, 0xfd, 0x12} }, -{ 0x9700, 16, {0x81, 0xe0, 0xe5, 0x62, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x61, 0xf5, 0x83, 0xe0, 0x54, 0xfc} }, -{ 0x9710, 16, {0xf0, 0xaf, 0x5e, 0x7d, 0x01, 0x7b, 0x01, 0x75, 0x6c, 0x80, 0x75, 0x6d, 0x40, 0x12, 0x92, 0xcc} }, -{ 0x9720, 16, {0x8f, 0x60, 0xe5, 0x60, 0x70, 0x11, 0xaf, 0x5e, 0x7d, 0x02, 0x7b, 0x01, 0x75, 0x6c, 0x10, 0x75} }, -{ 0x9730, 16, {0x6d, 0x20, 0x12, 0x92, 0xcc, 0x8f, 0x60, 0xe5, 0x60, 0x70, 0x10, 0xaf, 0x5e, 0x7d, 0x01, 0xfb} }, -{ 0x9740, 16, {0x75, 0x6c, 0x80, 0x75, 0x6d, 0x40, 0x12, 0x92, 0xcc, 0x8f, 0x60, 0xe5, 0x60, 0x70, 0x10, 0xaf} }, -{ 0x9750, 16, {0x5e, 0x7d, 0x02, 0xfb, 0x75, 0x6c, 0x10, 0x75, 0x6d, 0x20, 0x12, 0x92, 0xcc, 0x8f, 0x60, 0xaf} }, -{ 0x9760, 16, {0x62, 0xae, 0x61, 0x7d, 0x01, 0x12, 0x81, 0xe0, 0xe5, 0x60, 0x60, 0x2b, 0x85, 0x66, 0x82, 0x85} }, -{ 0x9770, 16, {0x65, 0x83, 0xa3, 0xa3, 0xe4, 0xf0, 0xe5, 0x5e, 0x04, 0xff, 0x05, 0x68, 0xe5, 0x68, 0xac, 0x67} }, -{ 0x9780, 16, {0x70, 0x02, 0x05, 0x67, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x85, 0x68, 0x82, 0x85, 0x67} }, -{ 0x9790, 16, {0x83, 0xe5, 0x60, 0xf0, 0x02, 0x98, 0x4e, 0x05, 0x5e, 0xe5, 0x5e, 0xd3, 0x94, 0x03, 0x50, 0x03} }, -{ 0x97a0, 16, {0x02, 0x96, 0xe9, 0x02, 0x98, 0x4e, 0xe4, 0x90, 0x02, 0xd3, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3} }, -{ 0x97b0, 16, {0xf0, 0xa3, 0xf0, 0xa3, 0x74, 0x10, 0xf0, 0xa3, 0x74, 0x98, 0xf0, 0xa3, 0x74, 0x6d, 0xf0, 0x7e} }, -{ 0x97c0, 16, {0x02, 0x7f, 0xd3, 0x12, 0x80, 0x00, 0xef, 0x64, 0x08, 0x70, 0x03, 0x02, 0x98, 0x4e, 0x85, 0x66} }, -{ 0x97d0, 16, {0x82, 0x85, 0x65, 0x83, 0xa3, 0xa3, 0xe4, 0xf0, 0x80, 0x74, 0xe4, 0x90, 0x02, 0xd3, 0xf0, 0xa3} }, -{ 0x97e0, 16, {0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0x74, 0x10, 0xf0, 0xa3, 0xe5, 0x67, 0xf0, 0xa3} }, -{ 0x97f0, 16, {0xe5, 0x68, 0xf0, 0x7e, 0x02, 0x7f, 0xd3, 0x12, 0x19, 0xc1, 0xef, 0x64, 0x08, 0x60, 0x4f, 0x85} }, -{ 0x9800, 16, {0x66, 0x82, 0x85, 0x65, 0x83, 0xa3, 0xa3, 0xe4, 0xf0, 0x80, 0x43, 0xe4, 0x90, 0x02, 0xd3, 0xf0} }, -{ 0x9810, 16, {0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0x74, 0x10, 0xf0, 0xe5, 0x64, 0x24, 0x02} }, -{ 0x9820, 16, {0x90, 0x02, 0xda, 0xf0, 0xe4, 0x35, 0x63, 0x90, 0x02, 0xd9, 0xf0, 0x7e, 0x02, 0x7f, 0xd3, 0x12} }, -{ 0x9830, 16, {0x80, 0x00, 0xef, 0x64, 0x08, 0x60, 0x17, 0x85, 0x66, 0x82, 0x85, 0x65, 0x83, 0xa3, 0xa3, 0xe4} }, -{ 0x9840, 16, {0xf0, 0x80, 0x0b, 0x85, 0x66, 0x82, 0x85, 0x65, 0x83, 0xa3, 0xa3, 0x74, 0x01, 0xf0, 0x90, 0x01} }, -{ 0x9850, 16, {0x5e, 0xe4, 0xf0, 0xa3, 0x74, 0x0a, 0xf0, 0x90, 0x01, 0x5e, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x70} }, -{ 0x9860, 12, {0xf6, 0x90, 0x7f, 0xc3, 0x74, 0x24, 0xf0, 0xe4, 0x90, 0x02, 0x4d, 0xf0} }, -{ 0x986c, 1, {0x22} }, -{ 0x986d, 16, {0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0} }, -{ 0x987d, 16, {0xe4, 0xfd, 0x74, 0x01, 0x7e, 0x00, 0xa8, 0x05, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce, 0x33, 0xce} }, -{ 0x988d, 16, {0xd8, 0xf9, 0xff, 0xe5, 0x3b, 0xfb, 0xe4, 0xef, 0x5b, 0x70, 0x03, 0x02, 0x99, 0x45, 0xed, 0x75} }, -{ 0x989d, 16, {0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xaf, 0x82, 0xfe, 0xf5, 0x83, 0xe5} }, -{ 0x98ad, 16, {0x82, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0xe0, 0x54, 0x60, 0x64, 0x60, 0x60} }, -{ 0x98bd, 16, {0x03, 0x02, 0x99, 0x45, 0xef, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x3e, 0xf5, 0x83, 0xe0, 0xfc, 0x74} }, -{ 0x98cd, 16, {0x36, 0x2d, 0xf8, 0xec, 0xf6, 0x30, 0xe5, 0x70, 0x74, 0x96, 0x2d, 0xf5, 0x82, 0xe4, 0x34, 0x02} }, -{ 0x98dd, 16, {0xf5, 0x83, 0xe0, 0x60, 0x63, 0xed, 0x25, 0xe0, 0x24, 0x8d, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5} }, -{ 0x98ed, 16, {0x83, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9a, 0xa4, 0x85, 0xf0, 0x82, 0xf5, 0x83, 0xe0, 0x8f, 0x82} }, -{ 0x98fd, 16, {0x8e, 0x83, 0xf0, 0x74, 0x96, 0x2d, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe0, 0x14, 0xf0} }, -{ 0x990d, 16, {0x70, 0x36, 0xed, 0x25, 0xe0, 0x24, 0xc7, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe4, 0xf0} }, -{ 0x991d, 16, {0xed, 0x25, 0xe0, 0xff, 0xc3, 0x74, 0x0c, 0x9f, 0x75, 0xf0, 0x40, 0xa4, 0x24, 0x40, 0xf5, 0x82} }, -{ 0x992d, 16, {0xe5, 0xf0, 0x34, 0x7b, 0xaf, 0x82, 0xfe, 0xed, 0x25, 0xe0, 0x24, 0x8d, 0xf5, 0x82, 0xe4, 0x34} }, -{ 0x993d, 16, {0x02, 0xf5, 0x83, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x0d, 0xed, 0x64, 0x04, 0x60, 0x03, 0x02, 0x98} }, -{ 0x994d, 1, {0x7f} }, -{ 0x994e, 1, {0x22} }, -{ 0x994f, 16, {0xe7, 0x09, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x46, 0xe7, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x3e} }, -{ 0x995f, 16, {0x88, 0x82, 0x8c, 0x83, 0xe7, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x32, 0xe3, 0x09, 0xf6, 0x08} }, -{ 0x996f, 16, {0xdf, 0xfa, 0x80, 0x78, 0xe3, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x70, 0x88, 0x82, 0x8c, 0x83} }, -{ 0x997f, 16, {0xe3, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x64, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf6, 0x08} }, -{ 0x998f, 16, {0xdf, 0xfa, 0x80, 0x58, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x4c} }, -{ 0x999f, 16, {0x80, 0xd2, 0x80, 0xfa, 0x80, 0xc6, 0x80, 0xd4, 0x80, 0x69, 0x80, 0xf2, 0x80, 0x33, 0x80, 0x10} }, -{ 0x99af, 16, {0x80, 0xa6, 0x80, 0xea, 0x80, 0x9a, 0x80, 0xa8, 0x80, 0xda, 0x80, 0xe2, 0x80, 0xca, 0x80, 0x33} }, -{ 0x99bf, 16, {0x89, 0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83} }, -{ 0x99cf, 16, {0xcc, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xe9, 0xde, 0xe7, 0x80} }, -{ 0x99df, 16, {0x0d, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf6, 0x08, 0xdf, 0xf9, 0xec, 0xfa, 0xa9, 0xf0} }, -{ 0x99ef, 16, {0xed, 0xfb, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc} }, -{ 0x99ff, 16, {0xc5, 0x83, 0xcc, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xea, 0xde} }, -{ 0x9a0f, 16, {0xe8, 0x80, 0xdb, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf2, 0x08, 0xdf, 0xf9, 0x80, 0xcc} }, -{ 0x9a1f, 16, {0x88, 0xf0, 0xed, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xc2, 0xf5, 0x82, 0xeb, 0x24, 0x02, 0xb4} }, -{ 0x9a2f, 16, {0x04, 0x00, 0x50, 0xb8, 0x23, 0x23, 0x45, 0x82, 0xf5, 0x82, 0xef, 0x4e, 0x60, 0xae, 0xef, 0x60} }, -{ 0x9a3f, 9, {0x01, 0x0e, 0xe5, 0x82, 0x23, 0x90, 0x99, 0x9f, 0x73} }, -{ 0x9a48, 16, {0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, 0xfe, 0x02} }, -{ 0x9a58, 9, {0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22} }, -{ 0x9a61, 16, {0xbb, 0x01, 0x0c, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50} }, -{ 0x9a71, 16, {0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22} }, -{ 0x9a81, 13, {0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22} }, -{ 0x9a8e, 16, {0xc5, 0xf0, 0xf8, 0xa3, 0xe0, 0x28, 0xf0, 0xc5, 0xf0, 0xf8, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x02} }, -{ 0x9a9e, 6, {0x15, 0x83, 0xe0, 0x38, 0xf0, 0x22} }, -{ 0x9aa4, 16, {0xa3, 0xf8, 0xe0, 0xc5, 0xf0, 0x25, 0xf0, 0xf0, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x02, 0x15, 0x83} }, -{ 0x9ab4, 6, {0xe0, 0xc8, 0x38, 0xf0, 0xe8, 0x22} }, -{ 0x9aba, 16, {0xbb, 0x01, 0x10, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0xf5, 0xf0} }, -{ 0x9aca, 16, {0xa3, 0xe0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 0xf8, 0x86, 0xf0, 0x08, 0xe6, 0x22, 0xbb, 0xfe} }, -{ 0x9ada, 16, {0x0a, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0xf5, 0xf0, 0x08, 0xe2, 0x22, 0xe5, 0x83, 0x2a, 0xf5, 0x83} }, -{ 0x9aea, 8, {0xe9, 0x93, 0xf5, 0xf0, 0xa3, 0xe9, 0x93, 0x22} }, -{ 0x9af2, 16, {0x75, 0xf0, 0x08, 0x75, 0x82, 0x00, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xcd, 0x33, 0xcd, 0xcc} }, -{ 0x9b02, 16, {0x33, 0xcc, 0xc5, 0x82, 0x33, 0xc5, 0x82, 0x9b, 0xed, 0x9a, 0xec, 0x99, 0xe5, 0x82, 0x98, 0x40} }, -{ 0x9b12, 16, {0x0c, 0xf5, 0x82, 0xee, 0x9b, 0xfe, 0xed, 0x9a, 0xfd, 0xec, 0x99, 0xfc, 0x0f, 0xd5, 0xf0, 0xd6} }, -{ 0x9b22, 16, {0xe4, 0xce, 0xfb, 0xe4, 0xcd, 0xfa, 0xe4, 0xcc, 0xf9, 0xa8, 0x82, 0x22, 0xb8, 0x00, 0xc1, 0xb9} }, -{ 0x9b32, 16, {0x00, 0x59, 0xba, 0x00, 0x2d, 0xec, 0x8b, 0xf0, 0x84, 0xcf, 0xce, 0xcd, 0xfc, 0xe5, 0xf0, 0xcb} }, -{ 0x9b42, 16, {0xf9, 0x78, 0x18, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xec, 0x33, 0xfc, 0xeb} }, -{ 0x9b52, 16, {0x33, 0xfb, 0x10, 0xd7, 0x03, 0x99, 0x40, 0x04, 0xeb, 0x99, 0xfb, 0x0f, 0xd8, 0xe5, 0xe4, 0xf9} }, -{ 0x9b62, 16, {0xfa, 0x22, 0x78, 0x18, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xec, 0x33, 0xfc} }, -{ 0x9b72, 16, {0xc9, 0x33, 0xc9, 0x10, 0xd7, 0x05, 0x9b, 0xe9, 0x9a, 0x40, 0x07, 0xec, 0x9b, 0xfc, 0xe9, 0x9a} }, -{ 0x9b82, 16, {0xf9, 0x0f, 0xd8, 0xe0, 0xe4, 0xc9, 0xfa, 0xe4, 0xcc, 0xfb, 0x22, 0x75, 0xf0, 0x10, 0xef, 0x2f} }, -{ 0x9b92, 16, {0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xcc, 0x33, 0xcc, 0xc8, 0x33, 0xc8, 0x10, 0xd7, 0x07} }, -{ 0x9ba2, 16, {0x9b, 0xec, 0x9a, 0xe8, 0x99, 0x40, 0x0a, 0xed, 0x9b, 0xfd, 0xec, 0x9a, 0xfc, 0xe8, 0x99, 0xf8} }, -{ 0x9bb2, 14, {0x0f, 0xd5, 0xf0, 0xda, 0xe4, 0xcd, 0xfb, 0xe4, 0xcc, 0xfa, 0xe4, 0xc8, 0xf9, 0x22} }, -{ 0x9bc0, 16, {0xeb, 0x9f, 0xf5, 0xf0, 0xea, 0x9e, 0x42, 0xf0, 0xe9, 0x9d, 0x42, 0xf0, 0xe8, 0x9c, 0x45, 0xf0} }, -{ 0x9bd0, 1, {0x22} }, -{ 0x9bd1, 16, {0xe8, 0x60, 0x0f, 0xec, 0xc3, 0x13, 0xfc, 0xed, 0x13, 0xfd, 0xee, 0x13, 0xfe, 0xef, 0x13, 0xff} }, -{ 0x9be1, 3, {0xd8, 0xf1, 0x22} }, -{ 0x9be4, 16, {0x08, 0x08, 0x08, 0xe6, 0xcf, 0x2f, 0xf6, 0x18, 0xe6, 0xce, 0x3e, 0xf6, 0x18, 0xe6, 0xcd, 0x3d} }, -{ 0x9bf4, 7, {0xf6, 0x18, 0xe6, 0xcc, 0x3c, 0xf6, 0x22} }, -{ 0x9bfb, 12, {0xec, 0xf0, 0xa3, 0xed, 0xf0, 0xa3, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x22} }, -{ 0x9c07, 16, {0xa8, 0x82, 0x85, 0x83, 0xf0, 0xd0, 0x83, 0xd0, 0x82, 0x12, 0x9c, 0x1e, 0x12, 0x9c, 0x1e, 0x12} }, -{ 0x9c17, 16, {0x9c, 0x1e, 0x12, 0x9c, 0x1e, 0xe4, 0x73, 0xe4, 0x93, 0xa3, 0xc5, 0x83, 0xc5, 0xf0, 0xc5, 0x83} }, -{ 0x9c27, 16, {0xc8, 0xc5, 0x82, 0xc8, 0xf0, 0xa3, 0xc5, 0x83, 0xc5, 0xf0, 0xc5, 0x83, 0xc8, 0xc5, 0x82, 0xc8} }, -{ 0x9c37, 1, {0x22} }, -{ 0xffff, 0, {0x00} } -}; - -#ifdef DEBUG -static const struct whiteheat_hex_record whiteheat_loader[] = { -{ 0x0000, 3, {0x02, 0x09, 0x8d} }, -{ 0x0033, 3, {0x02, 0x0e, 0x70} }, -{ 0x0043, 3, {0x02, 0x0b, 0x00} }, -{ 0x004b, 3, {0x02, 0x05, 0xb3} }, -{ 0x0100, 16, {0x90, 0x7f, 0xa5, 0xe0, 0x54, 0x10, 0xff, 0xc4, 0x54, 0x0f, 0x44, 0x50, 0xf5, 0x0f, 0x13, 0xe4} }, -{ 0x0110, 16, {0x33, 0xf5, 0x11, 0x90, 0x7f, 0xe9, 0xe0, 0x24, 0x5e, 0xb4, 0x07, 0x00, 0x40, 0x03, 0x02, 0x03} }, -{ 0x0120, 16, {0x7c, 0x90, 0x01, 0x28, 0xf8, 0x28, 0x28, 0x73, 0x02, 0x01, 0xbc, 0x02, 0x01, 0xbc, 0x02, 0x01} }, -{ 0x0130, 16, {0x91, 0x02, 0x01, 0x3d, 0x02, 0x01, 0x53, 0x02, 0x01, 0x6f, 0x02, 0x01, 0x9a, 0x90, 0x7f, 0x00} }, -{ 0x0140, 16, {0xe5, 0x11, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0} }, -{ 0x0150, 16, {0x02, 0x03, 0x7c, 0x90, 0x7f, 0x92, 0xe0, 0xff, 0xc4, 0x54, 0x0f, 0x90, 0x7f, 0x00, 0xf0, 0x90} }, -{ 0x0160, 16, {0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x02, 0x03, 0x7c, 0x12} }, -{ 0x0170, 16, {0x0a, 0x89, 0x50, 0x07, 0xe4, 0x90, 0x7f, 0x00, 0xf0, 0x80, 0x06, 0x90, 0x7f, 0x00, 0x74, 0x0f} }, -{ 0x0180, 16, {0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x02, 0x03} }, -{ 0x0190, 16, {0x7c, 0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x0f, 0x02, 0x03, 0x7c, 0x90, 0x7f, 0x00, 0x74, 0x07, 0xf0} }, -{ 0x01a0, 16, {0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x7f, 0xe8, 0x7e} }, -{ 0x01b0, 16, {0x03, 0x12, 0x0d, 0xd5, 0xd2, 0x06, 0x12, 0x0d, 0x0d, 0x02, 0x03, 0x7c, 0x90, 0x7f, 0xea, 0xe0} }, -{ 0x01c0, 16, {0x75, 0x29, 0x00, 0xf5, 0x2a, 0xa3, 0xe0, 0xfe, 0xe4, 0xee, 0x42, 0x29, 0x90, 0x7f, 0xee, 0xe0} }, -{ 0x01d0, 16, {0x75, 0x2b, 0x00, 0xf5, 0x2c, 0xa3, 0xe0, 0xfe, 0xe4, 0xee, 0x42, 0x2b, 0x90, 0x7f, 0xe8, 0xe0} }, -{ 0x01e0, 16, {0x64, 0xc0, 0x60, 0x03, 0x02, 0x02, 0xc9, 0xe5, 0x2c, 0x45, 0x2b, 0x70, 0x03, 0x02, 0x03, 0x7c} }, -{ 0x01f0, 16, {0xc3, 0xe5, 0x2c, 0x94, 0x40, 0xe5, 0x2b, 0x94, 0x00, 0x50, 0x08, 0x85, 0x2b, 0x2d, 0x85, 0x2c} }, -{ 0x0200, 16, {0x2e, 0x80, 0x06, 0x75, 0x2d, 0x00, 0x75, 0x2e, 0x40, 0x90, 0x7f, 0xe9, 0xe0, 0x64, 0xa3, 0x70} }, -{ 0x0210, 16, {0x34, 0xf5, 0x31, 0xf5, 0x32, 0xc3, 0xe5, 0x32, 0x95, 0x2e, 0xe5, 0x31, 0x95, 0x2d, 0x50, 0x5c} }, -{ 0x0220, 16, {0xe5, 0x2a, 0x25, 0x32, 0xf5, 0x82, 0xe5, 0x31, 0x35, 0x29, 0xf5, 0x83, 0xe0, 0xff, 0x74, 0x00} }, -{ 0x0230, 16, {0x25, 0x32, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xef, 0xf0, 0x05, 0x32, 0xe5, 0x32, 0x70} }, -{ 0x0240, 16, {0x02, 0x05, 0x31, 0x80, 0xd0, 0xe4, 0xf5, 0x31, 0xf5, 0x32, 0xc3, 0xe5, 0x32, 0x95, 0x2e, 0xe5} }, -{ 0x0250, 16, {0x31, 0x95, 0x2d, 0x50, 0x18, 0x74, 0x00, 0x25, 0x32, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83} }, -{ 0x0260, 16, {0x74, 0xcd, 0xf0, 0x05, 0x32, 0xe5, 0x32, 0x70, 0x02, 0x05, 0x31, 0x80, 0xdd, 0xaf, 0x2a, 0xae} }, -{ 0x0270, 16, {0x29, 0xad, 0x2e, 0x7a, 0x7f, 0x79, 0x00, 0x7b, 0x00, 0x12, 0x0b, 0xf4, 0x90, 0x7f, 0xb5, 0xe5} }, -{ 0x0280, 16, {0x2e, 0xf0, 0xe5, 0x2e, 0x25, 0x2a, 0xf5, 0x2a, 0xe5, 0x2d, 0x35, 0x29, 0xf5, 0x29, 0xc3, 0xe5} }, -{ 0x0290, 16, {0x2c, 0x95, 0x2e, 0xf5, 0x2c, 0xe5, 0x2b, 0x95, 0x2d, 0xf5, 0x2b, 0x90, 0x7f, 0x92, 0xe0, 0xff} }, -{ 0x02a0, 16, {0xc4, 0x54, 0x0f, 0x75, 0x2f, 0x00, 0xf5, 0x30, 0xd3, 0x94, 0x00, 0xe5, 0x2f, 0x94, 0x00, 0x50} }, -{ 0x02b0, 16, {0x0c, 0x90, 0x7f, 0xb4, 0xe0, 0x20, 0xe1, 0x03, 0x02, 0x01, 0xe7, 0x80, 0xf4, 0x90, 0x7f, 0xb4} }, -{ 0x02c0, 16, {0xe0, 0x20, 0xe2, 0x03, 0x02, 0x01, 0xe7, 0x80, 0xf4, 0x90, 0x7f, 0xe8, 0xe0, 0x64, 0x40, 0x60} }, -{ 0x02d0, 16, {0x03, 0x02, 0x03, 0x7c, 0xe5, 0x2c, 0x45, 0x2b, 0x70, 0x03, 0x02, 0x03, 0x7c, 0xe4, 0x90, 0x7f} }, -{ 0x02e0, 16, {0xc5, 0xf0, 0x90, 0x7f, 0x92, 0xe0, 0xff, 0xc4, 0x54, 0x0f, 0x75, 0x2f, 0x00, 0xf5, 0x30, 0xd3} }, -{ 0x02f0, 16, {0x94, 0x00, 0xe5, 0x2f, 0x94, 0x00, 0x50, 0x09, 0x90, 0x7f, 0xc4, 0xe0, 0x30, 0xe1, 0x09, 0x80} }, -{ 0x0300, 16, {0xf7, 0x90, 0x7f, 0xb4, 0xe0, 0x20, 0xe3, 0xf9, 0x90, 0x7f, 0xc5, 0xe0, 0x75, 0x2d, 0x00, 0xf5} }, -{ 0x0310, 16, {0x2e, 0x90, 0x7f, 0xe9, 0xe0, 0x64, 0xa3, 0x70, 0x38, 0x90, 0x20, 0x6b, 0xf0, 0xf5, 0x31, 0xf5} }, -{ 0x0320, 16, {0x32, 0xc3, 0xe5, 0x32, 0x95, 0x2e, 0xe5, 0x31, 0x95, 0x2d, 0x50, 0x34, 0x74, 0xc0, 0x25, 0x32} }, -{ 0x0330, 16, {0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x2a, 0x25, 0x32, 0xf5, 0x82, 0xe5} }, -{ 0x0340, 16, {0x31, 0x35, 0x29, 0xf5, 0x83, 0xef, 0xf0, 0x05, 0x32, 0xe5, 0x32, 0x70, 0x02, 0x05, 0x31, 0x80} }, -{ 0x0350, 16, {0xd0, 0xaf, 0x2a, 0xae, 0x29, 0xad, 0x2e, 0x7a, 0x7e, 0x79, 0xc0, 0x7b, 0xc0, 0x12, 0x0c, 0x80} }, -{ 0x0360, 16, {0xe5, 0x2e, 0x25, 0x2a, 0xf5, 0x2a, 0xe5, 0x2d, 0x35, 0x29, 0xf5, 0x29, 0xc3, 0xe5, 0x2c, 0x95} }, -{ 0x0370, 13, {0x2e, 0xf5, 0x2c, 0xe5, 0x2b, 0x95, 0x2d, 0xf5, 0x2b, 0x02, 0x02, 0xd4, 0xc3} }, -{ 0x037d, 1, {0x22} }, -{ 0x037e, 16, {0x90, 0x7f, 0xe9, 0xe0, 0x70, 0x03, 0x02, 0x04, 0x56, 0x14, 0x70, 0x03, 0x02, 0x04, 0xd2, 0x24} }, -{ 0x038e, 16, {0xfe, 0x70, 0x03, 0x02, 0x05, 0x46, 0x24, 0xfb, 0x70, 0x03, 0x02, 0x04, 0x50, 0x14, 0x70, 0x03} }, -{ 0x039e, 16, {0x02, 0x04, 0x4a, 0x14, 0x70, 0x03, 0x02, 0x04, 0x3e, 0x14, 0x70, 0x03, 0x02, 0x04, 0x44, 0x24} }, -{ 0x03ae, 16, {0x05, 0x60, 0x03, 0x02, 0x05, 0x9a, 0x12, 0x0e, 0x7b, 0x40, 0x03, 0x02, 0x05, 0xab, 0x90, 0x7f} }, -{ 0x03be, 16, {0xeb, 0xe0, 0x24, 0xfe, 0x60, 0x16, 0x14, 0x60, 0x40, 0x24, 0x02, 0x70, 0x69, 0x74, 0x11, 0x90} }, -{ 0x03ce, 16, {0x7f, 0xd4, 0xf0, 0x74, 0x00, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xea, 0xe0} }, -{ 0x03de, 16, {0xff, 0x12, 0x0b, 0x58, 0x8b, 0x26, 0x8a, 0x27, 0x89, 0x28, 0xea, 0x49, 0x60, 0x11, 0xae, 0x02} }, -{ 0x03ee, 16, {0xee, 0x90, 0x7f, 0xd4, 0xf0, 0xaf, 0x01, 0xef, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x05, 0xab, 0x90} }, -{ 0x03fe, 16, {0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xea, 0xe0, 0xff, 0x12, 0x0c} }, -{ 0x040e, 16, {0x3f, 0x8b, 0x26, 0x8a, 0x27, 0x89, 0x28, 0xea, 0x49, 0x60, 0x11, 0xae, 0x02, 0xee, 0x90, 0x7f} }, -{ 0x041e, 16, {0xd4, 0xf0, 0xaf, 0x01, 0xef, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xb4, 0xe0} }, -{ 0x042e, 16, {0x44, 0x01, 0xf0, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0xab} }, -{ 0x043e, 16, {0x12, 0x0e, 0x52, 0x02, 0x05, 0xab, 0x12, 0x0e, 0x60, 0x02, 0x05, 0xab, 0x12, 0x0a, 0xf7, 0x02} }, -{ 0x044e, 16, {0x05, 0xab, 0x12, 0x08, 0xf1, 0x02, 0x05, 0xab, 0x12, 0x0e, 0x7d, 0x40, 0x03, 0x02, 0x05, 0xab} }, -{ 0x045e, 16, {0x90, 0x7f, 0xe8, 0xe0, 0x24, 0x7f, 0x60, 0x24, 0x14, 0x60, 0x31, 0x24, 0x02, 0x70, 0x5b, 0xa2} }, -{ 0x046e, 16, {0x00, 0xe4, 0x33, 0xff, 0x25, 0xe0, 0xff, 0xa2, 0x02, 0xe4, 0x33, 0x4f, 0x90, 0x7f, 0x00, 0xf0} }, -{ 0x047e, 16, {0xe4, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0xab, 0xe4, 0x90, 0x7f, 0x00} }, -{ 0x048e, 16, {0xf0, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xec, 0xe0} }, -{ 0x049e, 16, {0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4} }, -{ 0x04ae, 16, {0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe0, 0x54, 0xfd, 0x90, 0x7f, 0x00, 0xf0, 0xe4, 0xa3} }, -{ 0x04be, 16, {0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01} }, -{ 0x04ce, 16, {0xf0, 0x02, 0x05, 0xab, 0x12, 0x0e, 0x7f, 0x40, 0x03, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xe8, 0xe0} }, -{ 0x04de, 16, {0x24, 0xfe, 0x60, 0x1d, 0x24, 0x02, 0x60, 0x03, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xea, 0xe0, 0xb4} }, -{ 0x04ee, 16, {0x01, 0x05, 0xc2, 0x00, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05} }, -{ 0x04fe, 16, {0xab, 0x90, 0x7f, 0xea, 0xe0, 0x70, 0x38, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4} }, -{ 0x050e, 16, {0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f} }, -{ 0x051e, 16, {0xf5, 0x83, 0xe4, 0xf0, 0x90, 0x7f, 0xec, 0xe0, 0x54, 0x80, 0xff, 0x13, 0x13, 0x13, 0x54, 0x1f} }, -{ 0x052e, 16, {0xff, 0xe0, 0x54, 0x07, 0x2f, 0x90, 0x7f, 0xd7, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x6e, 0x90} }, -{ 0x053e, 16, {0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x65, 0x12, 0x0e, 0x81, 0x50, 0x60, 0x90, 0x7f, 0xe8} }, -{ 0x054e, 16, {0xe0, 0x24, 0xfe, 0x60, 0x18, 0x24, 0x02, 0x70, 0x54, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x04} }, -{ 0x055e, 16, {0xd2, 0x00, 0x80, 0x49, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x40, 0x90, 0x7f, 0xea} }, -{ 0x056e, 16, {0xe0, 0x70, 0x20, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0} }, -{ 0x057e, 16, {0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0x74, 0x01} }, -{ 0x058e, 16, {0xf0, 0x80, 0x1a, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x11, 0xe4, 0x90, 0x20, 0x6a} }, -{ 0x059e, 16, {0xf0, 0x12, 0x01, 0x00, 0x50, 0x07, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xb4} }, -{ 0x05ae, 4, {0xe0, 0x44, 0x02, 0xf0} }, -{ 0x05b2, 1, {0x22} }, -{ 0x05b3, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xc0} }, -{ 0x05c3, 16, {0xd0, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x06, 0xc0, 0x07, 0x90, 0x7f, 0xa5} }, -{ 0x05d3, 16, {0xe0, 0x30, 0xe2, 0x06, 0x75, 0x0d, 0x06, 0x02, 0x06, 0x7f, 0x90, 0x7f, 0xa5, 0xe0, 0x20, 0xe1} }, -{ 0x05e3, 16, {0x0c, 0xe5, 0x0d, 0x64, 0x02, 0x60, 0x06, 0x75, 0x0d, 0x07, 0x02, 0x06, 0x7f, 0xaf, 0x0d, 0xef} }, -{ 0x05f3, 16, {0x24, 0xfe, 0x60, 0x48, 0x14, 0x60, 0x2c, 0x24, 0xfe, 0x60, 0x77, 0x24, 0x04, 0x60, 0x03, 0x02} }, -{ 0x0603, 16, {0x06, 0x7f, 0xab, 0x09, 0xaa, 0x0a, 0xa9, 0x0b, 0xaf, 0x0c, 0x05, 0x0c, 0x8f, 0x82, 0x75, 0x83} }, -{ 0x0613, 16, {0x00, 0x12, 0x07, 0x85, 0x90, 0x7f, 0xa6, 0xf0, 0xe5, 0x0c, 0x65, 0x08, 0x70, 0x5e, 0x75, 0x0d} }, -{ 0x0623, 16, {0x05, 0x80, 0x59, 0x90, 0x7f, 0xa6, 0xe0, 0xab, 0x09, 0xaa, 0x0a, 0xa9, 0x0b, 0xae, 0x0c, 0x8e} }, -{ 0x0633, 16, {0x82, 0x75, 0x83, 0x00, 0x12, 0x07, 0xb2, 0x75, 0x0d, 0x02, 0x80, 0x40, 0xe5, 0x08, 0x24, 0xfe} }, -{ 0x0643, 16, {0xb5, 0x0c, 0x07, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x20, 0xf0, 0xe5, 0x08, 0x14, 0xb5, 0x0c, 0x0a} }, -{ 0x0653, 16, {0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0xe4, 0xf5, 0x0d, 0x90, 0x7f, 0xa6, 0xe0, 0xab, 0x09} }, -{ 0x0663, 16, {0xaa, 0x0a, 0xa9, 0x0b, 0xae, 0x0c, 0x8e, 0x82, 0x75, 0x83, 0x00, 0x12, 0x07, 0xb2, 0x05, 0x0c} }, -{ 0x0673, 16, {0x80, 0x0a, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0xe4, 0xf5, 0x0d, 0x53, 0x91, 0xdf, 0xd0} }, -{ 0x0683, 16, {0x07, 0xd0, 0x06, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0xd0, 0xd0, 0x86, 0xd0} }, -{ 0x0693, 10, {0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, -{ 0x069d, 16, {0xc2, 0x04, 0xd2, 0x05, 0xe4, 0xf5, 0x25, 0xc2, 0x03, 0xc2, 0x00, 0xc2, 0x02, 0xc2, 0x01, 0x12} }, -{ 0x06ad, 16, {0x0e, 0x74, 0xd2, 0xe8, 0x43, 0xd8, 0x20, 0x90, 0x7f, 0xab, 0x74, 0xff, 0xf0, 0x90, 0x7f, 0xa9} }, -{ 0x06bd, 16, {0xf0, 0x90, 0x7f, 0xaa, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f, 0x95, 0xe0, 0x44, 0xc0, 0xf0, 0x90} }, -{ 0x06cd, 16, {0x7f, 0x93, 0x74, 0x30, 0xf0, 0x12, 0x0a, 0x19, 0x75, 0x24, 0x48, 0x75, 0x23, 0x92, 0x75, 0x22} }, -{ 0x06dd, 16, {0x00, 0x75, 0x21, 0x00, 0xe4, 0xff, 0xfe, 0x7e, 0x05, 0x90, 0x20, 0x68, 0x74, 0x01, 0xf0, 0xa3} }, -{ 0x06ed, 16, {0xde, 0xfc, 0x7e, 0x00, 0x7f, 0x05, 0x90, 0x7f, 0xaf, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xae} }, -{ 0x06fd, 16, {0xe0, 0x44, 0x0d, 0xf0, 0xd2, 0xaf, 0x12, 0x0e, 0x68, 0x30, 0x01, 0x0a, 0xe4, 0x90, 0x20, 0x69} }, -{ 0x070d, 16, {0xf0, 0x12, 0x03, 0x7e, 0xc2, 0x01, 0x30, 0x04, 0x1a, 0x12, 0x0e, 0x77, 0x50, 0x13, 0x12, 0x09} }, -{ 0x071d, 16, {0x00, 0x30, 0x00, 0x07, 0x90, 0x7f, 0xd6, 0xe0, 0x30, 0xe7, 0xf3, 0x12, 0x0d, 0x8b, 0x12, 0x0e} }, -{ 0x072d, 16, {0x79, 0xc2, 0x03, 0x7f, 0xff, 0x7e, 0xff, 0x7d, 0xff, 0x7c, 0xff, 0x78, 0x21, 0x12, 0x08, 0x1d} }, -{ 0x073d, 16, {0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00, 0x78, 0x00, 0xc3, 0x12, 0x08, 0x0c, 0x70, 0x1b, 0x75, 0x24} }, -{ 0x074d, 16, {0x48, 0x75, 0x23, 0x92, 0xf5, 0x22, 0xf5, 0x21, 0x63, 0x25, 0xff, 0x90, 0x20, 0x68, 0xe5, 0x25} }, -{ 0x075d, 14, {0xf0, 0xa3, 0x74, 0x01, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0x12, 0x08, 0xff, 0x80, 0x9b} }, -{ 0x076b, 1, {0x22} }, -{ 0x076c, 16, {0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, 0xfe, 0x02} }, -{ 0x077c, 9, {0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22} }, -{ 0x0785, 16, {0xbb, 0x01, 0x0c, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50} }, -{ 0x0795, 16, {0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22} }, -{ 0x07a5, 13, {0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22} }, -{ 0x07b2, 16, {0xf8, 0xbb, 0x01, 0x0d, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe8, 0xf0} }, -{ 0x07c2, 16, {0x22, 0x50, 0x06, 0xe9, 0x25, 0x82, 0xc8, 0xf6, 0x22, 0xbb, 0xfe, 0x05, 0xe9, 0x25, 0x82, 0xc8} }, -{ 0x07d2, 2, {0xf2, 0x22} }, -{ 0x07d4, 16, {0xbb, 0x01, 0x10, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0xf5, 0xf0} }, -{ 0x07e4, 16, {0xa3, 0xe0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 0xf8, 0x86, 0xf0, 0x08, 0xe6, 0x22, 0xbb, 0xfe} }, -{ 0x07f4, 16, {0x0a, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0xf5, 0xf0, 0x08, 0xe2, 0x22, 0xe5, 0x83, 0x2a, 0xf5, 0x83} }, -{ 0x0804, 8, {0xe9, 0x93, 0xf5, 0xf0, 0xa3, 0xe9, 0x93, 0x22} }, -{ 0x080c, 16, {0xeb, 0x9f, 0xf5, 0xf0, 0xea, 0x9e, 0x42, 0xf0, 0xe9, 0x9d, 0x42, 0xf0, 0xe8, 0x9c, 0x45, 0xf0} }, -{ 0x081c, 1, {0x22} }, -{ 0x081d, 16, {0x08, 0x08, 0x08, 0xe6, 0x2f, 0xff, 0xf6, 0x18, 0xe6, 0x3e, 0xfe, 0xf6, 0x18, 0xe6, 0x3d, 0xfd} }, -{ 0x082d, 7, {0xf6, 0x18, 0xe6, 0x3c, 0xfc, 0xf6, 0x22} }, -{ 0x0834, 4, {0x8c, 0x34, 0x8d, 0x35} }, -{ 0x0838, 16, {0x90, 0x7f, 0x95, 0xe0, 0x44, 0xc0, 0xf0, 0xe4, 0xf5, 0x36, 0xf5, 0x37, 0xc3, 0xe5, 0x37, 0x95} }, -{ 0x0848, 16, {0x35, 0xe5, 0x36, 0x95, 0x34, 0x50, 0x69, 0xef, 0x25, 0x37, 0xf5, 0x82, 0xe5, 0x36, 0x3e, 0xf5} }, -{ 0x0858, 16, {0x83, 0x74, 0xff, 0xf0, 0xf4, 0x60, 0x02, 0xc3, 0x22, 0xef, 0x25, 0x37, 0xf5, 0x82, 0xe5, 0x36} }, -{ 0x0868, 16, {0x3e, 0xf5, 0x83, 0xe4, 0xf0, 0x60, 0x02, 0xc3, 0x22, 0xef, 0x25, 0x37, 0xf5, 0x82, 0xe5, 0x36} }, -{ 0x0878, 16, {0x3e, 0xf5, 0x83, 0x74, 0xaa, 0xf0, 0x64, 0xaa, 0x60, 0x02, 0xc3, 0x22, 0xef, 0x25, 0x37, 0xf5} }, -{ 0x0888, 16, {0x82, 0xe5, 0x36, 0x3e, 0xf5, 0x83, 0x74, 0x55, 0xf0, 0x64, 0x55, 0x60, 0x02, 0xc3, 0x22, 0xad} }, -{ 0x0898, 16, {0x37, 0xe5, 0x37, 0x2f, 0xf5, 0x82, 0xe5, 0x36, 0x3e, 0xf5, 0x83, 0xed, 0xf0, 0xfc, 0xac, 0x05} }, -{ 0x08a8, 16, {0xed, 0x6c, 0x60, 0x02, 0xc3, 0x22, 0x05, 0x37, 0xe5, 0x37, 0x70, 0x02, 0x05, 0x36, 0x80, 0x8c} }, -{ 0x08b8, 16, {0xe4, 0xf5, 0x36, 0xf5, 0x37, 0xc3, 0xe5, 0x37, 0x95, 0x35, 0xe5, 0x36, 0x95, 0x34, 0x50, 0x27} }, -{ 0x08c8, 16, {0xef, 0x25, 0x37, 0xf5, 0x82, 0xe5, 0x36, 0x3e, 0xf5, 0x83, 0xe0, 0x65, 0x37, 0x60, 0x02, 0xc3} }, -{ 0x08d8, 16, {0x22, 0xef, 0x25, 0x37, 0xf5, 0x82, 0xe5, 0x36, 0x3e, 0xf5, 0x83, 0xe4, 0xf0, 0x05, 0x37, 0xe5} }, -{ 0x08e8, 8, {0x37, 0x70, 0x02, 0x05, 0x36, 0x80, 0xce, 0xd3} }, -{ 0x08f0, 1, {0x22} }, -{ 0x08f1, 14, {0x90, 0x7f, 0x00, 0xe5, 0x10, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0xd3, 0x22} }, -{ 0x08ff, 1, {0x22} }, -{ 0x0900, 9, {0x90, 0x7f, 0xd6, 0xe0, 0x44, 0x80, 0xf0, 0x80, 0x74} }, -{ 0x097d, 16, {0x43, 0x87, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22} }, -{ 0x098d, 12, {0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x3a, 0x02, 0x09, 0xd4} }, -{ 0x0999, 16, {0x02, 0x06, 0x9d, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2} }, -{ 0x09a9, 16, {0x08, 0xdf, 0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33} }, -{ 0x09b9, 16, {0xc4, 0x54, 0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf} }, -{ 0x09c9, 16, {0xe4, 0x80, 0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x0e, 0x2d, 0xe4, 0x7e} }, -{ 0x09d9, 16, {0x01, 0x93, 0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93} }, -{ 0x09e9, 16, {0xa3, 0x60, 0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3} }, -{ 0x09f9, 16, {0xfa, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca} }, -{ 0x0a09, 16, {0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe} }, -{ 0x0a19, 16, {0xe4, 0x90, 0x7f, 0x9c, 0xf0, 0x7f, 0x0a, 0xfe, 0x12, 0x0d, 0xd5, 0x90, 0x7f, 0x96, 0x74, 0x89} }, -{ 0x0a29, 16, {0xf0, 0x90, 0x7f, 0x9c, 0x74, 0xcf, 0xf0, 0x7f, 0xf4, 0x7e, 0x01, 0x12, 0x0d, 0xd5, 0x90, 0x7f} }, -{ 0x0a39, 16, {0x96, 0xe0, 0x54, 0xfe, 0xf0, 0x7f, 0x0a, 0x7e, 0x00, 0x12, 0x0d, 0xd5, 0x7f, 0x05, 0x7e, 0x00} }, -{ 0x0a49, 16, {0x12, 0x0d, 0xd5, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x02, 0xf0, 0xe0, 0x54, 0x7f, 0xf0, 0x7f, 0x05} }, -{ 0x0a59, 16, {0x7e, 0x00, 0x12, 0x0d, 0xd5, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x05, 0x7e, 0x00} }, -{ 0x0a69, 16, {0x12, 0x0d, 0xd5, 0x90, 0x7f, 0x96, 0xe0, 0x54, 0xbf, 0xf0, 0x7f, 0x32, 0x7e, 0x00, 0x12, 0x0d} }, -{ 0x0a79, 16, {0xd5, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x32, 0x7e, 0x00, 0x12, 0x0d, 0xd5, 0x22} }, -{ 0x0a89, 16, {0x75, 0x33, 0x01, 0xe5, 0x33, 0x60, 0x1b, 0x7f, 0x01, 0x12, 0x0e, 0x18, 0x7f, 0x00, 0x7e, 0x0e} }, -{ 0x0a99, 16, {0x7d, 0x00, 0x7c, 0x01, 0x12, 0x08, 0x34, 0xe4, 0x33, 0xf5, 0x33, 0x70, 0x05, 0x7f, 0x0f, 0x12} }, -{ 0x0aa9, 16, {0x0e, 0x18, 0xe5, 0x33, 0x60, 0x1b, 0x7f, 0x02, 0x12, 0x0e, 0x18, 0x7f, 0x00, 0x7e, 0x80, 0x7d} }, -{ 0x0ab9, 16, {0x00, 0x7c, 0x80, 0x12, 0x08, 0x34, 0xe4, 0x33, 0xf5, 0x33, 0x70, 0x05, 0x7f, 0x0f, 0x12, 0x0e} }, -{ 0x0ac9, 16, {0x18, 0xe5, 0x33, 0x60, 0x1b, 0x7f, 0x03, 0x12, 0x0e, 0x18, 0x7f, 0x00, 0x7e, 0x20, 0x7d, 0x40} }, -{ 0x0ad9, 16, {0x7c, 0x5b, 0x12, 0x08, 0x34, 0xe4, 0x33, 0xf5, 0x33, 0x70, 0x05, 0x7f, 0x0f, 0x12, 0x0e, 0x18} }, -{ 0x0ae9, 13, {0xe5, 0x33, 0x60, 0x05, 0xe4, 0xff, 0x12, 0x0e, 0x18, 0xe5, 0x33, 0x24, 0xff} }, -{ 0x0af6, 1, {0x22} }, -{ 0x0af7, 8, {0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x10, 0xd3, 0x22} }, -{ 0x0aff, 1, {0x32} }, -{ 0x0b00, 16, {0x02, 0x0d, 0xa5, 0x00, 0x02, 0x0d, 0xec, 0x00, 0x02, 0x0d, 0x70, 0x00, 0x02, 0x0d, 0xbd, 0x00} }, -{ 0x0b10, 16, {0x02, 0x0e, 0x02, 0x00, 0x02, 0x0a, 0xff, 0x00, 0x02, 0x0e, 0x83, 0x00, 0x02, 0x0e, 0x84, 0x00} }, -{ 0x0b20, 16, {0x02, 0x0e, 0x85, 0x00, 0x02, 0x0e, 0x86, 0x00, 0x02, 0x0e, 0x87, 0x00, 0x02, 0x0e, 0x88, 0x00} }, -{ 0x0b30, 16, {0x02, 0x0e, 0x89, 0x00, 0x02, 0x0e, 0x8a, 0x00, 0x02, 0x0e, 0x8b, 0x00, 0x02, 0x0e, 0x8c, 0x00} }, -{ 0x0b40, 16, {0x02, 0x0e, 0x8d, 0x00, 0x02, 0x0e, 0x8e, 0x00, 0x02, 0x0e, 0x8f, 0x00, 0x02, 0x0e, 0x90, 0x00} }, -{ 0x0b50, 8, {0x02, 0x0e, 0x91, 0x00, 0x02, 0x0e, 0x92, 0x00} }, -{ 0x0b58, 16, {0xe4, 0xfe, 0x75, 0x2b, 0xff, 0x75, 0x2c, 0x11, 0x75, 0x2d, 0x12, 0xab, 0x2b, 0xaa, 0x2c, 0xa9} }, -{ 0x0b68, 16, {0x2d, 0x90, 0x00, 0x01, 0x12, 0x07, 0x85, 0x64, 0x02, 0x70, 0x2d, 0xad, 0x06, 0x0e, 0xed, 0xb5} }, -{ 0x0b78, 16, {0x07, 0x01, 0x22, 0x90, 0x00, 0x02, 0x12, 0x07, 0xd4, 0x85, 0xf0, 0x29, 0xf5, 0x2a, 0x62, 0x29} }, -{ 0x0b88, 16, {0xe5, 0x29, 0x62, 0x2a, 0xe5, 0x2a, 0x62, 0x29, 0x29, 0xfd, 0xe5, 0x29, 0x3a, 0xa9, 0x05, 0x75} }, -{ 0x0b98, 14, {0x2b, 0xff, 0xf5, 0x2c, 0x89, 0x2d, 0x80, 0xc3, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} }, -{ 0x0ba6, 1, {0x22} }, -{ 0x0ba7, 6, {0xab, 0x07, 0xaa, 0x06, 0xac, 0x05} }, -{ 0x0bad, 16, {0xe4, 0xfd, 0xe5, 0x11, 0x60, 0x11, 0xea, 0xff, 0xae, 0x05, 0x0d, 0xee, 0x24, 0x10, 0xf5, 0x82} }, -{ 0x0bbd, 16, {0xe4, 0x34, 0x0f, 0xf5, 0x83, 0xef, 0xf0, 0xeb, 0xae, 0x05, 0x0d, 0x74, 0x10, 0x2e, 0xf5, 0x82} }, -{ 0x0bcd, 16, {0xe4, 0x34, 0x0f, 0xf5, 0x83, 0xeb, 0xf0, 0xaf, 0x05, 0x0d, 0x74, 0x10, 0x2f, 0xf5, 0x82, 0xe4} }, -{ 0x0bdd, 16, {0x34, 0x0f, 0xf5, 0x83, 0xec, 0xf0, 0xaf, 0x0f, 0x7a, 0x0f, 0x7b, 0x10, 0x12, 0x0d, 0x51, 0x7f} }, -{ 0x0bed, 6, {0x0a, 0x7e, 0x00, 0x12, 0x0d, 0xd5} }, -{ 0x0bf3, 1, {0x22} }, -{ 0x0bf4, 10, {0x8e, 0x33, 0x8f, 0x34, 0x8d, 0x35, 0x8a, 0x36, 0x8b, 0x37} }, -{ 0x0bfe, 16, {0xe4, 0xfd, 0xf5, 0x38, 0xe5, 0x11, 0x60, 0x12, 0xe5, 0x33, 0xff, 0xae, 0x05, 0x0d, 0xee, 0x24} }, -{ 0x0c0e, 16, {0x13, 0xf5, 0x82, 0xe4, 0x34, 0x0f, 0xf5, 0x83, 0xef, 0xf0, 0xe5, 0x34, 0xae, 0x05, 0x0d, 0x74} }, -{ 0x0c1e, 16, {0x13, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x0f, 0xf5, 0x83, 0xe5, 0x34, 0xf0, 0xaf, 0x0f, 0x7a, 0x0f} }, -{ 0x0c2e, 16, {0x7b, 0x13, 0x12, 0x0d, 0x51, 0xaf, 0x0f, 0xad, 0x35, 0xab, 0x37, 0xaa, 0x36, 0x12, 0x0d, 0x32} }, -{ 0x0c3e, 1, {0x22} }, -{ 0x0c3f, 2, {0x8f, 0x29} }, -{ 0x0c41, 16, {0xe4, 0xf5, 0x2a, 0x75, 0x2b, 0xff, 0x75, 0x2c, 0x11, 0x75, 0x2d, 0x32, 0xab, 0x2b, 0xaa, 0x2c} }, -{ 0x0c51, 16, {0xa9, 0x2d, 0x90, 0x00, 0x01, 0x12, 0x07, 0x85, 0xb4, 0x03, 0x1d, 0xaf, 0x2a, 0x05, 0x2a, 0xef} }, -{ 0x0c61, 16, {0xb5, 0x29, 0x01, 0x22, 0x12, 0x07, 0x6c, 0x7e, 0x00, 0x29, 0xff, 0xee, 0x3a, 0xa9, 0x07, 0x75} }, -{ 0x0c71, 14, {0x2b, 0xff, 0xf5, 0x2c, 0x89, 0x2d, 0x80, 0xd4, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} }, -{ 0x0c7f, 1, {0x22} }, -{ 0x0c80, 10, {0x8e, 0x33, 0x8f, 0x34, 0x8d, 0x35, 0x8a, 0x36, 0x8b, 0x37} }, -{ 0x0c8a, 16, {0xe4, 0xf5, 0x38, 0xe5, 0x38, 0xc3, 0x95, 0x35, 0x50, 0x20, 0x05, 0x34, 0xe5, 0x34, 0xae, 0x33} }, -{ 0x0c9a, 16, {0x70, 0x02, 0x05, 0x33, 0x14, 0xff, 0xe5, 0x37, 0x25, 0x38, 0xf5, 0x82, 0xe4, 0x35, 0x36, 0xf5} }, -{ 0x0caa, 10, {0x83, 0xe0, 0xfd, 0x12, 0x0b, 0xa7, 0x05, 0x38, 0x80, 0xd9} }, -{ 0x0cb4, 1, {0x22} }, -{ 0x0cb5, 16, {0xa9, 0x07, 0xe5, 0x0d, 0x70, 0x25, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0, 0xe9, 0x25, 0xe0} }, -{ 0x0cc5, 16, {0x44, 0x01, 0x90, 0x7f, 0xa6, 0xf0, 0x8d, 0x08, 0xaf, 0x03, 0xa9, 0x07, 0x75, 0x09, 0x01, 0x8a} }, -{ 0x0cd5, 13, {0x0a, 0x89, 0x0b, 0xe4, 0xf5, 0x0c, 0x75, 0x0d, 0x03, 0xd3, 0x22, 0xc3, 0x22} }, -{ 0x0ce2, 16, {0xa9, 0x07, 0xe5, 0x0d, 0x70, 0x23, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0, 0xe9, 0x25, 0xe0} }, -{ 0x0cf2, 16, {0x90, 0x7f, 0xa6, 0xf0, 0x8d, 0x08, 0xaf, 0x03, 0xa9, 0x07, 0x75, 0x09, 0x01, 0x8a, 0x0a, 0x89} }, -{ 0x0d02, 11, {0x0b, 0xe4, 0xf5, 0x0c, 0x75, 0x0d, 0x01, 0xd3, 0x22, 0xc3, 0x22} }, -{ 0x0d0d, 16, {0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x30, 0x06, 0x04, 0xe0, 0x44} }, -{ 0x0d1d, 16, {0x02, 0xf0, 0x7f, 0xd0, 0x7e, 0x07, 0x12, 0x0d, 0xd5, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xf7, 0xf0} }, -{ 0x0d2d, 5, {0xe0, 0x44, 0x04, 0xf0, 0x22} }, -{ 0x0d32, 16, {0x12, 0x0c, 0xb5, 0xe5, 0x0d, 0x24, 0xfa, 0x60, 0x10, 0x14, 0x60, 0x07, 0x24, 0x07, 0x70, 0xf3} }, -{ 0x0d42, 15, {0x7f, 0x08, 0x22, 0xe4, 0xf5, 0x0d, 0x7f, 0x07, 0x22, 0xe4, 0xf5, 0x0d, 0x7f, 0x06, 0x22} }, -{ 0x0d51, 16, {0x12, 0x0c, 0xe2, 0xe5, 0x0d, 0x24, 0xfa, 0x60, 0x10, 0x14, 0x60, 0x07, 0x24, 0x07, 0x70, 0xf3} }, -{ 0x0d61, 15, {0x7f, 0x08, 0x22, 0xe4, 0xf5, 0x0d, 0x7f, 0x07, 0x22, 0xe4, 0xf5, 0x0d, 0x7f, 0x06, 0x22} }, -{ 0x0d70, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x90, 0x7f, 0xc4, 0xe4, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f} }, -{ 0x0d80, 11, {0xab, 0x74, 0x04, 0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, -{ 0x0d8b, 16, {0x90, 0x7f, 0xd6, 0xe0, 0x30, 0xe7, 0x12, 0xe0, 0x44, 0x01, 0xf0, 0x7f, 0x14, 0x7e, 0x00, 0x12} }, -{ 0x0d9b, 10, {0x0d, 0xd5, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xfe, 0xf0, 0x22} }, -{ 0x0da5, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xd2, 0x01, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x01} }, -{ 0x0db5, 8, {0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, -{ 0x0dbd, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xd2, 0x03, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x08} }, -{ 0x0dcd, 8, {0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, -{ 0x0dd5, 16, {0x8e, 0x39, 0x8f, 0x3a, 0xe5, 0x3a, 0x15, 0x3a, 0xae, 0x39, 0x70, 0x02, 0x15, 0x39, 0x4e, 0x60} }, -{ 0x0de5, 7, {0x05, 0x12, 0x0e, 0x41, 0x80, 0xee, 0x22} }, -{ 0x0dec, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x02, 0xf0, 0xd0} }, -{ 0x0dfc, 6, {0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, -{ 0x0e02, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x10, 0xf0, 0xd0} }, -{ 0x0e12, 6, {0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, -{ 0x0e18, 16, {0xae, 0x07, 0x7f, 0x21, 0x7d, 0x01, 0x74, 0x00, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x0f, 0xab, 0x82} }, -{ 0x0e28, 5, {0xfa, 0x12, 0x0d, 0x51, 0x22} }, -{ 0x0e2d, 16, {0x50, 0x0f, 0x00, 0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x98, 0x88, 0x83, 0xc6} }, -{ 0x0e3d, 3, {0xa1, 0x86, 0x8e} }, -{ 0x0e40, 1, {0x00} }, -{ 0x0e41, 16, {0x74, 0x00, 0xf5, 0x86, 0x90, 0xfd, 0xa5, 0x7c, 0x05, 0xa3, 0xe5, 0x82, 0x45, 0x83, 0x70, 0xf9} }, -{ 0x0e51, 1, {0x22} }, -{ 0x0e52, 14, {0x90, 0x7f, 0x00, 0xe5, 0x0e, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0xd3, 0x22} }, -{ 0x0e60, 8, {0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x0e, 0xd3, 0x22} }, -{ 0x0e68, 8, {0xe4, 0xf5, 0x0d, 0xd2, 0xe9, 0xd2, 0xaf, 0x22} }, -{ 0x0e70, 4, {0x53, 0xd8, 0xef, 0x32} }, -{ 0x0e74, 3, {0xd2, 0x00, 0x22} }, -{ 0x0e77, 2, {0xd3, 0x22} }, -{ 0x0e79, 2, {0xd3, 0x22} }, -{ 0x0e7b, 2, {0xd3, 0x22} }, -{ 0x0e7d, 2, {0xd3, 0x22} }, -{ 0x0e7f, 2, {0xd3, 0x22} }, -{ 0x0e81, 2, {0xd3, 0x22} }, -{ 0x0e83, 1, {0x32} }, -{ 0x0e84, 1, {0x32} }, -{ 0x0e85, 1, {0x32} }, -{ 0x0e86, 1, {0x32} }, -{ 0x0e87, 1, {0x32} }, -{ 0x0e88, 1, {0x32} }, -{ 0x0e89, 1, {0x32} }, -{ 0x0e8a, 1, {0x32} }, -{ 0x0e8b, 1, {0x32} }, -{ 0x0e8c, 1, {0x32} }, -{ 0x0e8d, 1, {0x32} }, -{ 0x0e8e, 1, {0x32} }, -{ 0x0e8f, 1, {0x32} }, -{ 0x0e90, 1, {0x32} }, -{ 0x0e91, 1, {0x32} }, -{ 0x0e92, 1, {0x32} }, -{ 0x1100, 16, {0x12, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x47, 0x05, 0x10, 0x27, 0x01, 0x00, 0x01, 0x02} }, -{ 0x1110, 16, {0x00, 0x01, 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x03, 0xa0, 0x00, 0x09, 0x04, 0x00, 0x00, 0x02} }, -{ 0x1120, 16, {0xff, 0x00, 0x00, 0x04, 0x07, 0x05, 0x82, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x02, 0x02, 0x40} }, -{ 0x1130, 16, {0x00, 0x00, 0x04, 0x03, 0x09, 0x04, 0x26, 0x03, 0x41, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x68, 0x00} }, -{ 0x1140, 16, {0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x43, 0x00, 0x68, 0x00, 0x69, 0x00, 0x70, 0x00, 0x73, 0x00} }, -{ 0x1150, 16, {0x2c, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x2e, 0x00, 0x28, 0x03, 0x46, 0x00} }, -{ 0x1160, 16, {0x69, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x77, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00} }, -{ 0x1170, 16, {0x46, 0x00, 0x72, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x57, 0x00, 0x6f, 0x00, 0x72, 0x00} }, -{ 0x1180, 16, {0x6b, 0x00, 0x73, 0x00, 0x2a, 0x03, 0x43, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x69, 0x00} }, -{ 0x1190, 16, {0x67, 0x00, 0x75, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00} }, -{ 0x11a0, 16, {0x20, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x22, 0x03} }, -{ 0x11b0, 16, {0x49, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x66, 0x00, 0x61, 0x00, 0x63, 0x00} }, -{ 0x11c0, 16, {0x65, 0x00, 0x20, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00} }, -{ 0x11d0, 2, {0x00, 0x00} }, -{ 0xffff, 0, {0x00} } -}; - -#else - -static const struct whiteheat_hex_record whiteheat_loader[] = { -{ 0x0000, 3, {0x02, 0x09, 0x8d} }, -{ 0x0033, 3, {0x02, 0x08, 0xfb} }, -{ 0x0043, 3, {0x02, 0x0b, 0x00} }, -{ 0x004b, 3, {0x02, 0x05, 0xaa} }, -{ 0x0100, 16, {0x90, 0x7f, 0xa5, 0xe0, 0x54, 0x10, 0xff, 0xc4, 0x54, 0x0f, 0x44, 0x50, 0xf5, 0x0f, 0x13, 0xe4} }, -{ 0x0110, 16, {0x33, 0xf5, 0x11, 0x90, 0x7f, 0xe9, 0xe0, 0x24, 0x5e, 0xb4, 0x07, 0x00, 0x40, 0x03, 0x02, 0x03} }, -{ 0x0120, 16, {0x78, 0x90, 0x01, 0x28, 0xf8, 0x28, 0x28, 0x73, 0x02, 0x01, 0xbc, 0x02, 0x01, 0xbc, 0x02, 0x01} }, -{ 0x0130, 16, {0x91, 0x02, 0x01, 0x3d, 0x02, 0x01, 0x53, 0x02, 0x01, 0x6f, 0x02, 0x01, 0x9a, 0x90, 0x7f, 0x00} }, -{ 0x0140, 16, {0xe5, 0x11, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0} }, -{ 0x0150, 16, {0x02, 0x03, 0x78, 0x90, 0x7f, 0x92, 0xe0, 0xff, 0xc4, 0x54, 0x0f, 0x90, 0x7f, 0x00, 0xf0, 0x90} }, -{ 0x0160, 16, {0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x02, 0x03, 0x78, 0x12} }, -{ 0x0170, 16, {0x0a, 0x89, 0x50, 0x07, 0xe4, 0x90, 0x7f, 0x00, 0xf0, 0x80, 0x06, 0x90, 0x7f, 0x00, 0x74, 0x0f} }, -{ 0x0180, 16, {0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x02, 0x03} }, -{ 0x0190, 16, {0x78, 0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x0f, 0x02, 0x03, 0x78, 0x90, 0x7f, 0x00, 0x74, 0x07, 0xf0} }, -{ 0x01a0, 16, {0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x7f, 0xe8, 0x7e} }, -{ 0x01b0, 16, {0x03, 0x12, 0x0d, 0x94, 0xd2, 0x06, 0x12, 0x0c, 0xcc, 0x02, 0x03, 0x78, 0x90, 0x7f, 0xea, 0xe0} }, -{ 0x01c0, 16, {0x75, 0x28, 0x00, 0xf5, 0x29, 0xa3, 0xe0, 0xfe, 0xe4, 0xee, 0x42, 0x28, 0x90, 0x7f, 0xee, 0xe0} }, -{ 0x01d0, 16, {0x75, 0x2a, 0x00, 0xf5, 0x2b, 0xa3, 0xe0, 0xfe, 0xe4, 0xee, 0x42, 0x2a, 0x90, 0x7f, 0xe8, 0xe0} }, -{ 0x01e0, 16, {0x64, 0xc0, 0x60, 0x03, 0x02, 0x02, 0xc9, 0xe5, 0x2b, 0x45, 0x2a, 0x70, 0x03, 0x02, 0x03, 0x78} }, -{ 0x01f0, 16, {0xc3, 0xe5, 0x2b, 0x94, 0x40, 0xe5, 0x2a, 0x94, 0x00, 0x50, 0x08, 0x85, 0x2a, 0x2c, 0x85, 0x2b} }, -{ 0x0200, 16, {0x2d, 0x80, 0x06, 0x75, 0x2c, 0x00, 0x75, 0x2d, 0x40, 0x90, 0x7f, 0xe9, 0xe0, 0x64, 0xa3, 0x70} }, -{ 0x0210, 16, {0x34, 0xf5, 0x30, 0xf5, 0x31, 0xc3, 0xe5, 0x31, 0x95, 0x2d, 0xe5, 0x30, 0x95, 0x2c, 0x50, 0x5c} }, -{ 0x0220, 16, {0xe5, 0x29, 0x25, 0x31, 0xf5, 0x82, 0xe5, 0x30, 0x35, 0x28, 0xf5, 0x83, 0xe0, 0xff, 0x74, 0x00} }, -{ 0x0230, 16, {0x25, 0x31, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xef, 0xf0, 0x05, 0x31, 0xe5, 0x31, 0x70} }, -{ 0x0240, 16, {0x02, 0x05, 0x30, 0x80, 0xd0, 0xe4, 0xf5, 0x30, 0xf5, 0x31, 0xc3, 0xe5, 0x31, 0x95, 0x2d, 0xe5} }, -{ 0x0250, 16, {0x30, 0x95, 0x2c, 0x50, 0x18, 0x74, 0x00, 0x25, 0x31, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83} }, -{ 0x0260, 16, {0x74, 0xcd, 0xf0, 0x05, 0x31, 0xe5, 0x31, 0x70, 0x02, 0x05, 0x30, 0x80, 0xdd, 0xaf, 0x29, 0xae} }, -{ 0x0270, 16, {0x28, 0xad, 0x2d, 0x7a, 0x7f, 0x79, 0x00, 0x7b, 0x00, 0x12, 0x0b, 0xf4, 0x90, 0x7f, 0xb5, 0xe5} }, -{ 0x0280, 16, {0x2d, 0xf0, 0xe5, 0x2d, 0x25, 0x29, 0xf5, 0x29, 0xe5, 0x2c, 0x35, 0x28, 0xf5, 0x28, 0xc3, 0xe5} }, -{ 0x0290, 16, {0x2b, 0x95, 0x2d, 0xf5, 0x2b, 0xe5, 0x2a, 0x95, 0x2c, 0xf5, 0x2a, 0x90, 0x7f, 0x92, 0xe0, 0xff} }, -{ 0x02a0, 16, {0xc4, 0x54, 0x0f, 0x75, 0x2e, 0x00, 0xf5, 0x2f, 0xd3, 0x94, 0x00, 0xe5, 0x2e, 0x94, 0x00, 0x50} }, -{ 0x02b0, 16, {0x0c, 0x90, 0x7f, 0xb4, 0xe0, 0x20, 0xe1, 0x03, 0x02, 0x01, 0xe7, 0x80, 0xf4, 0x90, 0x7f, 0xb4} }, -{ 0x02c0, 16, {0xe0, 0x20, 0xe2, 0x03, 0x02, 0x01, 0xe7, 0x80, 0xf4, 0x90, 0x7f, 0xe8, 0xe0, 0x64, 0x40, 0x60} }, -{ 0x02d0, 16, {0x03, 0x02, 0x03, 0x78, 0xe5, 0x2b, 0x45, 0x2a, 0x70, 0x03, 0x02, 0x03, 0x78, 0xe4, 0x90, 0x7f} }, -{ 0x02e0, 16, {0xc5, 0xf0, 0x90, 0x7f, 0x92, 0xe0, 0xff, 0xc4, 0x54, 0x0f, 0x75, 0x2e, 0x00, 0xf5, 0x2f, 0xd3} }, -{ 0x02f0, 16, {0x94, 0x00, 0xe5, 0x2e, 0x94, 0x00, 0x50, 0x09, 0x90, 0x7f, 0xc4, 0xe0, 0x30, 0xe1, 0x09, 0x80} }, -{ 0x0300, 16, {0xf7, 0x90, 0x7f, 0xb4, 0xe0, 0x20, 0xe3, 0xf9, 0x90, 0x7f, 0xc5, 0xe0, 0x75, 0x2c, 0x00, 0xf5} }, -{ 0x0310, 16, {0x2d, 0x90, 0x7f, 0xe9, 0xe0, 0x64, 0xa3, 0x70, 0x34, 0xf5, 0x30, 0xf5, 0x31, 0xc3, 0xe5, 0x31} }, -{ 0x0320, 16, {0x95, 0x2d, 0xe5, 0x30, 0x95, 0x2c, 0x50, 0x34, 0x74, 0xc0, 0x25, 0x31, 0xf5, 0x82, 0xe4, 0x34} }, -{ 0x0330, 1, {0x7e} }, -{ 0x0331, 16, {0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x29, 0x25, 0x31, 0xf5, 0x82, 0xe5, 0x30, 0x35, 0x28, 0xf5, 0x83} }, -{ 0x0341, 16, {0xef, 0xf0, 0x05, 0x31, 0xe5, 0x31, 0x70, 0x02, 0x05, 0x30, 0x80, 0xd0, 0xaf, 0x29, 0xae, 0x28} }, -{ 0x0351, 16, {0xad, 0x2d, 0x7a, 0x7e, 0x79, 0xc0, 0x7b, 0xc0, 0x12, 0x0c, 0x3f, 0xe5, 0x2d, 0x25, 0x29, 0xf5} }, -{ 0x0361, 16, {0x29, 0xe5, 0x2c, 0x35, 0x28, 0xf5, 0x28, 0xc3, 0xe5, 0x2b, 0x95, 0x2d, 0xf5, 0x2b, 0xe5, 0x2a} }, -{ 0x0371, 9, {0x95, 0x2c, 0xf5, 0x2a, 0x02, 0x02, 0xd4, 0xc3, 0x22} }, -{ 0x037a, 16, {0x90, 0x7f, 0xe9, 0xe0, 0x70, 0x03, 0x02, 0x04, 0x52, 0x14, 0x70, 0x03, 0x02, 0x04, 0xce, 0x24} }, -{ 0x038a, 16, {0xfe, 0x70, 0x03, 0x02, 0x05, 0x42, 0x24, 0xfb, 0x70, 0x03, 0x02, 0x04, 0x4c, 0x14, 0x70, 0x03} }, -{ 0x039a, 16, {0x02, 0x04, 0x46, 0x14, 0x70, 0x03, 0x02, 0x04, 0x3a, 0x14, 0x70, 0x03, 0x02, 0x04, 0x40, 0x24} }, -{ 0x03aa, 16, {0x05, 0x60, 0x03, 0x02, 0x05, 0x96, 0x12, 0x0e, 0x44, 0x40, 0x03, 0x02, 0x05, 0xa2, 0x90, 0x7f} }, -{ 0x03ba, 16, {0xeb, 0xe0, 0x24, 0xfe, 0x60, 0x16, 0x14, 0x60, 0x40, 0x24, 0x02, 0x70, 0x69, 0x74, 0x11, 0x90} }, -{ 0x03ca, 16, {0x7f, 0xd4, 0xf0, 0x74, 0x00, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xea, 0xe0} }, -{ 0x03da, 16, {0xff, 0x12, 0x0b, 0x58, 0x8b, 0x25, 0x8a, 0x26, 0x89, 0x27, 0xea, 0x49, 0x60, 0x11, 0xae, 0x02} }, -{ 0x03ea, 16, {0xee, 0x90, 0x7f, 0xd4, 0xf0, 0xaf, 0x01, 0xef, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x05, 0xa2, 0x90} }, -{ 0x03fa, 16, {0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xea, 0xe0, 0xff, 0x12, 0x08} }, -{ 0x040a, 16, {0xba, 0x8b, 0x25, 0x8a, 0x26, 0x89, 0x27, 0xea, 0x49, 0x60, 0x11, 0xae, 0x02, 0xee, 0x90, 0x7f} }, -{ 0x041a, 16, {0xd4, 0xf0, 0xaf, 0x01, 0xef, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xb4, 0xe0} }, -{ 0x042a, 16, {0x44, 0x01, 0xf0, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0xa2} }, -{ 0x043a, 16, {0x12, 0x0e, 0x1f, 0x02, 0x05, 0xa2, 0x12, 0x0e, 0x2d, 0x02, 0x05, 0xa2, 0x12, 0x0a, 0xf7, 0x02} }, -{ 0x044a, 16, {0x05, 0xa2, 0x12, 0x0e, 0x11, 0x02, 0x05, 0xa2, 0x12, 0x0e, 0x46, 0x40, 0x03, 0x02, 0x05, 0xa2} }, -{ 0x045a, 16, {0x90, 0x7f, 0xe8, 0xe0, 0x24, 0x7f, 0x60, 0x24, 0x14, 0x60, 0x31, 0x24, 0x02, 0x70, 0x5b, 0xa2} }, -{ 0x046a, 16, {0x00, 0xe4, 0x33, 0xff, 0x25, 0xe0, 0xff, 0xa2, 0x02, 0xe4, 0x33, 0x4f, 0x90, 0x7f, 0x00, 0xf0} }, -{ 0x047a, 16, {0xe4, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0xa2, 0xe4, 0x90, 0x7f, 0x00} }, -{ 0x048a, 16, {0xf0, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xec, 0xe0} }, -{ 0x049a, 16, {0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4} }, -{ 0x04aa, 16, {0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe0, 0x54, 0xfd, 0x90, 0x7f, 0x00, 0xf0, 0xe4, 0xa3} }, -{ 0x04ba, 16, {0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01} }, -{ 0x04ca, 16, {0xf0, 0x02, 0x05, 0xa2, 0x12, 0x0e, 0x48, 0x40, 0x03, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xe8, 0xe0} }, -{ 0x04da, 16, {0x24, 0xfe, 0x60, 0x1d, 0x24, 0x02, 0x60, 0x03, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xea, 0xe0, 0xb4} }, -{ 0x04ea, 16, {0x01, 0x05, 0xc2, 0x00, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05} }, -{ 0x04fa, 16, {0xa2, 0x90, 0x7f, 0xea, 0xe0, 0x70, 0x38, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4} }, -{ 0x050a, 16, {0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f} }, -{ 0x051a, 16, {0xf5, 0x83, 0xe4, 0xf0, 0x90, 0x7f, 0xec, 0xe0, 0x54, 0x80, 0xff, 0x13, 0x13, 0x13, 0x54, 0x1f} }, -{ 0x052a, 16, {0xff, 0xe0, 0x54, 0x07, 0x2f, 0x90, 0x7f, 0xd7, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x69, 0x90} }, -{ 0x053a, 16, {0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x60, 0x12, 0x0e, 0x4a, 0x50, 0x5b, 0x90, 0x7f, 0xe8} }, -{ 0x054a, 16, {0xe0, 0x24, 0xfe, 0x60, 0x18, 0x24, 0x02, 0x70, 0x4f, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x04} }, -{ 0x055a, 16, {0xd2, 0x00, 0x80, 0x44, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x3b, 0x90, 0x7f, 0xea} }, -{ 0x056a, 16, {0xe0, 0x70, 0x20, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0} }, -{ 0x057a, 16, {0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0x74, 0x01} }, -{ 0x058a, 16, {0xf0, 0x80, 0x15, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x0c, 0x12, 0x01, 0x00, 0x50} }, -{ 0x059a, 16, {0x07, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x22} }, -{ 0x05aa, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xc0} }, -{ 0x05ba, 16, {0xd0, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x06, 0xc0, 0x07, 0x90, 0x7f, 0xa5} }, -{ 0x05ca, 16, {0xe0, 0x30, 0xe2, 0x06, 0x75, 0x0d, 0x06, 0x02, 0x06, 0x76, 0x90, 0x7f, 0xa5, 0xe0, 0x20, 0xe1} }, -{ 0x05da, 16, {0x0c, 0xe5, 0x0d, 0x64, 0x02, 0x60, 0x06, 0x75, 0x0d, 0x07, 0x02, 0x06, 0x76, 0xaf, 0x0d, 0xef} }, -{ 0x05ea, 16, {0x24, 0xfe, 0x60, 0x48, 0x14, 0x60, 0x2c, 0x24, 0xfe, 0x60, 0x77, 0x24, 0x04, 0x60, 0x03, 0x02} }, -{ 0x05fa, 16, {0x06, 0x76, 0xab, 0x09, 0xaa, 0x0a, 0xa9, 0x0b, 0xaf, 0x0c, 0x05, 0x0c, 0x8f, 0x82, 0x75, 0x83} }, -{ 0x060a, 16, {0x00, 0x12, 0x08, 0x22, 0x90, 0x7f, 0xa6, 0xf0, 0xe5, 0x0c, 0x65, 0x08, 0x70, 0x5e, 0x75, 0x0d} }, -{ 0x061a, 16, {0x05, 0x80, 0x59, 0x90, 0x7f, 0xa6, 0xe0, 0xab, 0x09, 0xaa, 0x0a, 0xa9, 0x0b, 0xae, 0x0c, 0x8e} }, -{ 0x062a, 16, {0x82, 0x75, 0x83, 0x00, 0x12, 0x08, 0x4f, 0x75, 0x0d, 0x02, 0x80, 0x40, 0xe5, 0x08, 0x24, 0xfe} }, -{ 0x063a, 16, {0xb5, 0x0c, 0x07, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x20, 0xf0, 0xe5, 0x08, 0x14, 0xb5, 0x0c, 0x0a} }, -{ 0x064a, 16, {0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0xe4, 0xf5, 0x0d, 0x90, 0x7f, 0xa6, 0xe0, 0xab, 0x09} }, -{ 0x065a, 16, {0xaa, 0x0a, 0xa9, 0x0b, 0xae, 0x0c, 0x8e, 0x82, 0x75, 0x83, 0x00, 0x12, 0x08, 0x4f, 0x05, 0x0c} }, -{ 0x066a, 16, {0x80, 0x0a, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0xe4, 0xf5, 0x0d, 0x53, 0x91, 0xdf, 0xd0} }, -{ 0x067a, 16, {0x07, 0xd0, 0x06, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0xd0, 0xd0, 0x86, 0xd0} }, -{ 0x068a, 10, {0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, -{ 0x0694, 16, {0x8c, 0x33, 0x8d, 0x34, 0x90, 0x7f, 0x95, 0xe0, 0x44, 0xc0, 0xf0, 0xe4, 0xf5, 0x35, 0xf5, 0x36} }, -{ 0x06a4, 16, {0xc3, 0xe5, 0x36, 0x95, 0x34, 0xe5, 0x35, 0x95, 0x33, 0x50, 0x69, 0xef, 0x25, 0x36, 0xf5, 0x82} }, -{ 0x06b4, 16, {0xe5, 0x35, 0x3e, 0xf5, 0x83, 0x74, 0xff, 0xf0, 0xf4, 0x60, 0x02, 0xc3, 0x22, 0xef, 0x25, 0x36} }, -{ 0x06c4, 16, {0xf5, 0x82, 0xe5, 0x35, 0x3e, 0xf5, 0x83, 0xe4, 0xf0, 0x60, 0x02, 0xc3, 0x22, 0xef, 0x25, 0x36} }, -{ 0x06d4, 16, {0xf5, 0x82, 0xe5, 0x35, 0x3e, 0xf5, 0x83, 0x74, 0xaa, 0xf0, 0x64, 0xaa, 0x60, 0x02, 0xc3, 0x22} }, -{ 0x06e4, 16, {0xef, 0x25, 0x36, 0xf5, 0x82, 0xe5, 0x35, 0x3e, 0xf5, 0x83, 0x74, 0x55, 0xf0, 0x64, 0x55, 0x60} }, -{ 0x06f4, 16, {0x02, 0xc3, 0x22, 0xad, 0x36, 0xe5, 0x36, 0x2f, 0xf5, 0x82, 0xe5, 0x35, 0x3e, 0xf5, 0x83, 0xed} }, -{ 0x0704, 16, {0xf0, 0xfc, 0xac, 0x05, 0xed, 0x6c, 0x60, 0x02, 0xc3, 0x22, 0x05, 0x36, 0xe5, 0x36, 0x70, 0x02} }, -{ 0x0714, 16, {0x05, 0x35, 0x80, 0x8c, 0xe4, 0xf5, 0x35, 0xf5, 0x36, 0xc3, 0xe5, 0x36, 0x95, 0x34, 0xe5, 0x35} }, -{ 0x0724, 16, {0x95, 0x33, 0x50, 0x27, 0xef, 0x25, 0x36, 0xf5, 0x82, 0xe5, 0x35, 0x3e, 0xf5, 0x83, 0xe0, 0x65} }, -{ 0x0734, 16, {0x36, 0x60, 0x02, 0xc3, 0x22, 0xef, 0x25, 0x36, 0xf5, 0x82, 0xe5, 0x35, 0x3e, 0xf5, 0x83, 0xe4} }, -{ 0x0744, 13, {0xf0, 0x05, 0x36, 0xe5, 0x36, 0x70, 0x02, 0x05, 0x35, 0x80, 0xce, 0xd3, 0x22} }, -{ 0x0751, 16, {0xc2, 0x04, 0xd2, 0x05, 0xc2, 0x03, 0xc2, 0x00, 0xc2, 0x02, 0xc2, 0x01, 0x12, 0x0e, 0x3d, 0xd2} }, -{ 0x0761, 16, {0xe8, 0x43, 0xd8, 0x20, 0x90, 0x7f, 0xab, 0x74, 0xff, 0xf0, 0x90, 0x7f, 0xa9, 0xf0, 0x90, 0x7f} }, -{ 0x0771, 16, {0xaa, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f, 0x95, 0xe0, 0x44, 0xc0, 0xf0, 0x90, 0x7f, 0x93, 0x74} }, -{ 0x0781, 16, {0x30, 0xf0, 0x12, 0x0a, 0x19, 0x90, 0x7f, 0xaf, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xae, 0xe0} }, -{ 0x0791, 16, {0x44, 0x0d, 0xf0, 0xd2, 0xaf, 0x12, 0x0e, 0x35, 0x20, 0x01, 0x42, 0x75, 0x24, 0x00, 0x75, 0x23} }, -{ 0x07a1, 16, {0x00, 0x75, 0x22, 0x00, 0x75, 0x21, 0x00, 0x7f, 0x48, 0x7e, 0x92, 0x7d, 0x00, 0x7c, 0x00, 0xab} }, -{ 0x07b1, 16, {0x24, 0xaa, 0x23, 0xa9, 0x22, 0xa8, 0x21, 0xc3, 0x12, 0x08, 0xa9, 0x50, 0xdb, 0x20, 0x01, 0xd8} }, -{ 0x07c1, 16, {0x7a, 0x00, 0x79, 0x00, 0x78, 0x00, 0xe5, 0x24, 0x24, 0x01, 0xf5, 0x24, 0xea, 0x35, 0x23, 0xf5} }, -{ 0x07d1, 16, {0x23, 0xe9, 0x35, 0x22, 0xf5, 0x22, 0xe8, 0x35, 0x21, 0xf5, 0x21, 0x80, 0xca, 0x30, 0x01, 0x05} }, -{ 0x07e1, 16, {0x12, 0x03, 0x7a, 0xc2, 0x01, 0x30, 0x04, 0x1a, 0x12, 0x0e, 0x40, 0x50, 0x13, 0x12, 0x09, 0x00} }, -{ 0x07f1, 16, {0x30, 0x00, 0x07, 0x90, 0x7f, 0xd6, 0xe0, 0x30, 0xe7, 0xf3, 0x12, 0x0d, 0x4a, 0x12, 0x0e, 0x42} }, -{ 0x0801, 8, {0xc2, 0x03, 0x12, 0x08, 0xff, 0x80, 0xd6, 0x22} }, -{ 0x0809, 16, {0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, 0xfe, 0x02} }, -{ 0x0819, 9, {0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22} }, -{ 0x0822, 16, {0xbb, 0x01, 0x0c, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50} }, -{ 0x0832, 16, {0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22} }, -{ 0x0842, 13, {0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22} }, -{ 0x084f, 16, {0xf8, 0xbb, 0x01, 0x0d, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe8, 0xf0} }, -{ 0x085f, 16, {0x22, 0x50, 0x06, 0xe9, 0x25, 0x82, 0xc8, 0xf6, 0x22, 0xbb, 0xfe, 0x05, 0xe9, 0x25, 0x82, 0xc8} }, -{ 0x086f, 2, {0xf2, 0x22} }, -{ 0x0871, 16, {0xbb, 0x01, 0x10, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0xf5, 0xf0} }, -{ 0x0881, 16, {0xa3, 0xe0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 0xf8, 0x86, 0xf0, 0x08, 0xe6, 0x22, 0xbb, 0xfe} }, -{ 0x0891, 16, {0x0a, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0xf5, 0xf0, 0x08, 0xe2, 0x22, 0xe5, 0x83, 0x2a, 0xf5, 0x83} }, -{ 0x08a1, 8, {0xe9, 0x93, 0xf5, 0xf0, 0xa3, 0xe9, 0x93, 0x22} }, -{ 0x08a9, 16, {0xeb, 0x9f, 0xf5, 0xf0, 0xea, 0x9e, 0x42, 0xf0, 0xe9, 0x9d, 0x42, 0xf0, 0xe8, 0x9c, 0x45, 0xf0} }, -{ 0x08b9, 1, {0x22} }, -{ 0x08ba, 2, {0x8f, 0x28} }, -{ 0x08bc, 16, {0xe4, 0xf5, 0x29, 0x75, 0x2a, 0xff, 0x75, 0x2b, 0x11, 0x75, 0x2c, 0x32, 0xab, 0x2a, 0xaa, 0x2b} }, -{ 0x08cc, 16, {0xa9, 0x2c, 0x90, 0x00, 0x01, 0x12, 0x08, 0x22, 0xb4, 0x03, 0x1d, 0xaf, 0x29, 0x05, 0x29, 0xef} }, -{ 0x08dc, 16, {0xb5, 0x28, 0x01, 0x22, 0x12, 0x08, 0x09, 0x7e, 0x00, 0x29, 0xff, 0xee, 0x3a, 0xa9, 0x07, 0x75} }, -{ 0x08ec, 14, {0x2a, 0xff, 0xf5, 0x2b, 0x89, 0x2c, 0x80, 0xd4, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} }, -{ 0x08fa, 1, {0x22} }, -{ 0x08fb, 4, {0x53, 0xd8, 0xef, 0x32} }, -{ 0x08ff, 1, {0x22} }, -{ 0x0900, 9, {0x90, 0x7f, 0xd6, 0xe0, 0x44, 0x80, 0xf0, 0x80, 0x74} }, -{ 0x097d, 16, {0x43, 0x87, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22} }, -{ 0x098d, 12, {0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x39, 0x02, 0x09, 0xd4} }, -{ 0x0999, 16, {0x02, 0x07, 0x51, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2} }, -{ 0x09a9, 16, {0x08, 0xdf, 0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33} }, -{ 0x09b9, 16, {0xc4, 0x54, 0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf} }, -{ 0x09c9, 16, {0xe4, 0x80, 0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x0d, 0xec, 0xe4, 0x7e} }, -{ 0x09d9, 16, {0x01, 0x93, 0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93} }, -{ 0x09e9, 16, {0xa3, 0x60, 0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3} }, -{ 0x09f9, 16, {0xfa, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca} }, -{ 0x0a09, 16, {0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe} }, -{ 0x0a19, 16, {0xe4, 0x90, 0x7f, 0x9c, 0xf0, 0x7f, 0x0a, 0xfe, 0x12, 0x0d, 0x94, 0x90, 0x7f, 0x96, 0x74, 0x89} }, -{ 0x0a29, 16, {0xf0, 0x90, 0x7f, 0x9c, 0x74, 0xcf, 0xf0, 0x7f, 0xf4, 0x7e, 0x01, 0x12, 0x0d, 0x94, 0x90, 0x7f} }, -{ 0x0a39, 16, {0x96, 0xe0, 0x54, 0xfe, 0xf0, 0x7f, 0x0a, 0x7e, 0x00, 0x12, 0x0d, 0x94, 0x7f, 0x05, 0x7e, 0x00} }, -{ 0x0a49, 16, {0x12, 0x0d, 0x94, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x02, 0xf0, 0xe0, 0x54, 0x7f, 0xf0, 0x7f, 0x05} }, -{ 0x0a59, 16, {0x7e, 0x00, 0x12, 0x0d, 0x94, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x05, 0x7e, 0x00} }, -{ 0x0a69, 16, {0x12, 0x0d, 0x94, 0x90, 0x7f, 0x96, 0xe0, 0x54, 0xbf, 0xf0, 0x7f, 0x32, 0x7e, 0x00, 0x12, 0x0d} }, -{ 0x0a79, 16, {0x94, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x32, 0x7e, 0x00, 0x12, 0x0d, 0x94, 0x22} }, -{ 0x0a89, 16, {0x75, 0x32, 0x01, 0xe5, 0x32, 0x60, 0x1b, 0x7f, 0x01, 0x12, 0x0d, 0xd7, 0x7f, 0x00, 0x7e, 0x0e} }, -{ 0x0a99, 16, {0x7d, 0x00, 0x7c, 0x01, 0x12, 0x06, 0x94, 0xe4, 0x33, 0xf5, 0x32, 0x70, 0x05, 0x7f, 0x0f, 0x12} }, -{ 0x0aa9, 16, {0x0d, 0xd7, 0xe5, 0x32, 0x60, 0x1b, 0x7f, 0x02, 0x12, 0x0d, 0xd7, 0x7f, 0x00, 0x7e, 0x80, 0x7d} }, -{ 0x0ab9, 16, {0x00, 0x7c, 0x80, 0x12, 0x06, 0x94, 0xe4, 0x33, 0xf5, 0x32, 0x70, 0x05, 0x7f, 0x0f, 0x12, 0x0d} }, -{ 0x0ac9, 16, {0xd7, 0xe5, 0x32, 0x60, 0x1b, 0x7f, 0x03, 0x12, 0x0d, 0xd7, 0x7f, 0x00, 0x7e, 0x20, 0x7d, 0x40} }, -{ 0x0ad9, 16, {0x7c, 0x5b, 0x12, 0x06, 0x94, 0xe4, 0x33, 0xf5, 0x32, 0x70, 0x05, 0x7f, 0x0f, 0x12, 0x0d, 0xd7} }, -{ 0x0ae9, 14, {0xe5, 0x32, 0x60, 0x05, 0xe4, 0xff, 0x12, 0x0d, 0xd7, 0xe5, 0x32, 0x24, 0xff, 0x22} }, -{ 0x0af7, 8, {0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x10, 0xd3, 0x22} }, -{ 0x0aff, 1, {0x32} }, -{ 0x0b00, 16, {0x02, 0x0d, 0x64, 0x00, 0x02, 0x0d, 0xab, 0x00, 0x02, 0x0d, 0x2f, 0x00, 0x02, 0x0d, 0x7c, 0x00} }, -{ 0x0b10, 16, {0x02, 0x0d, 0xc1, 0x00, 0x02, 0x0a, 0xff, 0x00, 0x02, 0x0e, 0x4c, 0x00, 0x02, 0x0e, 0x4d, 0x00} }, -{ 0x0b20, 16, {0x02, 0x0e, 0x4e, 0x00, 0x02, 0x0e, 0x4f, 0x00, 0x02, 0x0e, 0x50, 0x00, 0x02, 0x0e, 0x51, 0x00} }, -{ 0x0b30, 16, {0x02, 0x0e, 0x52, 0x00, 0x02, 0x0e, 0x53, 0x00, 0x02, 0x0e, 0x54, 0x00, 0x02, 0x0e, 0x55, 0x00} }, -{ 0x0b40, 16, {0x02, 0x0e, 0x56, 0x00, 0x02, 0x0e, 0x57, 0x00, 0x02, 0x0e, 0x58, 0x00, 0x02, 0x0e, 0x59, 0x00} }, -{ 0x0b50, 8, {0x02, 0x0e, 0x5a, 0x00, 0x02, 0x0e, 0x5b, 0x00} }, -{ 0x0b58, 16, {0xe4, 0xfe, 0x75, 0x2a, 0xff, 0x75, 0x2b, 0x11, 0x75, 0x2c, 0x12, 0xab, 0x2a, 0xaa, 0x2b, 0xa9} }, -{ 0x0b68, 16, {0x2c, 0x90, 0x00, 0x01, 0x12, 0x08, 0x22, 0x64, 0x02, 0x70, 0x2d, 0xad, 0x06, 0x0e, 0xed, 0xb5} }, -{ 0x0b78, 16, {0x07, 0x01, 0x22, 0x90, 0x00, 0x02, 0x12, 0x08, 0x71, 0x85, 0xf0, 0x28, 0xf5, 0x29, 0x62, 0x28} }, -{ 0x0b88, 16, {0xe5, 0x28, 0x62, 0x29, 0xe5, 0x29, 0x62, 0x28, 0x29, 0xfd, 0xe5, 0x28, 0x3a, 0xa9, 0x05, 0x75} }, -{ 0x0b98, 14, {0x2a, 0xff, 0xf5, 0x2b, 0x89, 0x2c, 0x80, 0xc3, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} }, -{ 0x0ba6, 1, {0x22} }, -{ 0x0ba7, 16, {0xab, 0x07, 0xaa, 0x06, 0xac, 0x05, 0xe4, 0xfd, 0xe5, 0x11, 0x60, 0x11, 0xea, 0xff, 0xae, 0x05} }, -{ 0x0bb7, 16, {0x0d, 0xee, 0x24, 0x10, 0xf5, 0x82, 0xe4, 0x34, 0x0f, 0xf5, 0x83, 0xef, 0xf0, 0xeb, 0xae, 0x05} }, -{ 0x0bc7, 16, {0x0d, 0x74, 0x10, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x0f, 0xf5, 0x83, 0xeb, 0xf0, 0xaf, 0x05, 0x0d} }, -{ 0x0bd7, 16, {0x74, 0x10, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x0f, 0xf5, 0x83, 0xec, 0xf0, 0xaf, 0x0f, 0x7a, 0x0f} }, -{ 0x0be7, 13, {0x7b, 0x10, 0x12, 0x0d, 0x10, 0x7f, 0x0a, 0x7e, 0x00, 0x12, 0x0d, 0x94, 0x22} }, -{ 0x0bf4, 16, {0x8e, 0x32, 0x8f, 0x33, 0x8d, 0x34, 0x8a, 0x35, 0x8b, 0x36, 0xe4, 0xfd, 0xf5, 0x37, 0xe5, 0x11} }, -{ 0x0c04, 16, {0x60, 0x12, 0xe5, 0x32, 0xff, 0xae, 0x05, 0x0d, 0xee, 0x24, 0x13, 0xf5, 0x82, 0xe4, 0x34, 0x0f} }, -{ 0x0c14, 16, {0xf5, 0x83, 0xef, 0xf0, 0xe5, 0x33, 0xae, 0x05, 0x0d, 0x74, 0x13, 0x2e, 0xf5, 0x82, 0xe4, 0x34} }, -{ 0x0c24, 16, {0x0f, 0xf5, 0x83, 0xe5, 0x33, 0xf0, 0xaf, 0x0f, 0x7a, 0x0f, 0x7b, 0x13, 0x12, 0x0d, 0x10, 0xaf} }, -{ 0x0c34, 11, {0x0f, 0xad, 0x34, 0xab, 0x36, 0xaa, 0x35, 0x12, 0x0c, 0xf1, 0x22} }, -{ 0x0c3f, 16, {0x8e, 0x32, 0x8f, 0x33, 0x8d, 0x34, 0x8a, 0x35, 0x8b, 0x36, 0xe4, 0xf5, 0x37, 0xe5, 0x37, 0xc3} }, -{ 0x0c4f, 16, {0x95, 0x34, 0x50, 0x20, 0x05, 0x33, 0xe5, 0x33, 0xae, 0x32, 0x70, 0x02, 0x05, 0x32, 0x14, 0xff} }, -{ 0x0c5f, 16, {0xe5, 0x36, 0x25, 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x35, 0xf5, 0x83, 0xe0, 0xfd, 0x12, 0x0b, 0xa7} }, -{ 0x0c6f, 5, {0x05, 0x37, 0x80, 0xd9, 0x22} }, -{ 0x0c74, 16, {0xa9, 0x07, 0xe5, 0x0d, 0x70, 0x25, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0, 0xe9, 0x25, 0xe0} }, -{ 0x0c84, 16, {0x44, 0x01, 0x90, 0x7f, 0xa6, 0xf0, 0x8d, 0x08, 0xaf, 0x03, 0xa9, 0x07, 0x75, 0x09, 0x01, 0x8a} }, -{ 0x0c94, 13, {0x0a, 0x89, 0x0b, 0xe4, 0xf5, 0x0c, 0x75, 0x0d, 0x03, 0xd3, 0x22, 0xc3, 0x22} }, -{ 0x0ca1, 16, {0xa9, 0x07, 0xe5, 0x0d, 0x70, 0x23, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0, 0xe9, 0x25, 0xe0} }, -{ 0x0cb1, 16, {0x90, 0x7f, 0xa6, 0xf0, 0x8d, 0x08, 0xaf, 0x03, 0xa9, 0x07, 0x75, 0x09, 0x01, 0x8a, 0x0a, 0x89} }, -{ 0x0cc1, 11, {0x0b, 0xe4, 0xf5, 0x0c, 0x75, 0x0d, 0x01, 0xd3, 0x22, 0xc3, 0x22} }, -{ 0x0ccc, 16, {0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x30, 0x06, 0x04, 0xe0, 0x44} }, -{ 0x0cdc, 16, {0x02, 0xf0, 0x7f, 0xd0, 0x7e, 0x07, 0x12, 0x0d, 0x94, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xf7, 0xf0} }, -{ 0x0cec, 5, {0xe0, 0x44, 0x04, 0xf0, 0x22} }, -{ 0x0cf1, 16, {0x12, 0x0c, 0x74, 0xe5, 0x0d, 0x24, 0xfa, 0x60, 0x10, 0x14, 0x60, 0x07, 0x24, 0x07, 0x70, 0xf3} }, -{ 0x0d01, 15, {0x7f, 0x08, 0x22, 0xe4, 0xf5, 0x0d, 0x7f, 0x07, 0x22, 0xe4, 0xf5, 0x0d, 0x7f, 0x06, 0x22} }, -{ 0x0d10, 16, {0x12, 0x0c, 0xa1, 0xe5, 0x0d, 0x24, 0xfa, 0x60, 0x10, 0x14, 0x60, 0x07, 0x24, 0x07, 0x70, 0xf3} }, -{ 0x0d20, 15, {0x7f, 0x08, 0x22, 0xe4, 0xf5, 0x0d, 0x7f, 0x07, 0x22, 0xe4, 0xf5, 0x0d, 0x7f, 0x06, 0x22} }, -{ 0x0d2f, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x90, 0x7f, 0xc4, 0xe4, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f} }, -{ 0x0d3f, 11, {0xab, 0x74, 0x04, 0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, -{ 0x0d4a, 16, {0x90, 0x7f, 0xd6, 0xe0, 0x30, 0xe7, 0x12, 0xe0, 0x44, 0x01, 0xf0, 0x7f, 0x14, 0x7e, 0x00, 0x12} }, -{ 0x0d5a, 10, {0x0d, 0x94, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xfe, 0xf0, 0x22} }, -{ 0x0d64, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xd2, 0x01, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x01} }, -{ 0x0d74, 8, {0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, -{ 0x0d7c, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xd2, 0x03, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x08} }, -{ 0x0d8c, 8, {0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, -{ 0x0d94, 16, {0x8e, 0x38, 0x8f, 0x39, 0xe5, 0x39, 0x15, 0x39, 0xae, 0x38, 0x70, 0x02, 0x15, 0x38, 0x4e, 0x60} }, -{ 0x0da4, 7, {0x05, 0x12, 0x0e, 0x00, 0x80, 0xee, 0x22} }, -{ 0x0dab, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x02, 0xf0, 0xd0} }, -{ 0x0dbb, 6, {0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, -{ 0x0dc1, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x10, 0xf0, 0xd0} }, -{ 0x0dd1, 6, {0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, -{ 0x0dd7, 16, {0xae, 0x07, 0x7f, 0x21, 0x7d, 0x01, 0x74, 0x00, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x0f, 0xab, 0x82} }, -{ 0x0de7, 5, {0xfa, 0x12, 0x0d, 0x10, 0x22} }, -{ 0x0dec, 16, {0x50, 0x0f, 0x00, 0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x98, 0x88, 0x83, 0xc6} }, -{ 0x0dfc, 3, {0xa1, 0x86, 0x8e} }, -{ 0x0dff, 1, {0x00} }, -{ 0x0e00, 16, {0x74, 0x00, 0xf5, 0x86, 0x90, 0xfd, 0xa5, 0x7c, 0x05, 0xa3, 0xe5, 0x82, 0x45, 0x83, 0x70, 0xf9} }, -{ 0x0e10, 1, {0x22} }, -{ 0x0e11, 14, {0x90, 0x7f, 0x00, 0xe5, 0x10, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0xd3, 0x22} }, -{ 0x0e1f, 14, {0x90, 0x7f, 0x00, 0xe5, 0x0e, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0xd3, 0x22} }, -{ 0x0e2d, 8, {0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x0e, 0xd3, 0x22} }, -{ 0x0e35, 8, {0xe4, 0xf5, 0x0d, 0xd2, 0xe9, 0xd2, 0xaf, 0x22} }, -{ 0x0e3d, 3, {0xd2, 0x00, 0x22} }, -{ 0x0e40, 2, {0xd3, 0x22} }, -{ 0x0e42, 2, {0xd3, 0x22} }, -{ 0x0e44, 2, {0xd3, 0x22} }, -{ 0x0e46, 2, {0xd3, 0x22} }, -{ 0x0e48, 2, {0xd3, 0x22} }, -{ 0x0e4a, 2, {0xd3, 0x22} }, -{ 0x0e4c, 1, {0x32} }, -{ 0x0e4d, 1, {0x32} }, -{ 0x0e4e, 1, {0x32} }, -{ 0x0e4f, 1, {0x32} }, -{ 0x0e50, 1, {0x32} }, -{ 0x0e51, 1, {0x32} }, -{ 0x0e52, 1, {0x32} }, -{ 0x0e53, 1, {0x32} }, -{ 0x0e54, 1, {0x32} }, -{ 0x0e55, 1, {0x32} }, -{ 0x0e56, 1, {0x32} }, -{ 0x0e57, 1, {0x32} }, -{ 0x0e58, 1, {0x32} }, -{ 0x0e59, 1, {0x32} }, -{ 0x0e5a, 1, {0x32} }, -{ 0x0e5b, 1, {0x32} }, -{ 0x1100, 16, {0x12, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x47, 0x05, 0x10, 0x27, 0x01, 0x00, 0x01, 0x02} }, -{ 0x1110, 16, {0x00, 0x01, 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x03, 0xa0, 0x00, 0x09, 0x04, 0x00, 0x00, 0x02} }, -{ 0x1120, 16, {0xff, 0x00, 0x00, 0x04, 0x07, 0x05, 0x82, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x02, 0x02, 0x40} }, -{ 0x1130, 16, {0x00, 0x00, 0x04, 0x03, 0x09, 0x04, 0x26, 0x03, 0x41, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x68, 0x00} }, -{ 0x1140, 16, {0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x43, 0x00, 0x68, 0x00, 0x69, 0x00, 0x70, 0x00, 0x73, 0x00} }, -{ 0x1150, 16, {0x2c, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x2e, 0x00, 0x28, 0x03, 0x46, 0x00} }, -{ 0x1160, 16, {0x69, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x77, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00} }, -{ 0x1170, 16, {0x46, 0x00, 0x72, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x57, 0x00, 0x6f, 0x00, 0x72, 0x00} }, -{ 0x1180, 16, {0x6b, 0x00, 0x73, 0x00, 0x2a, 0x03, 0x43, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x69, 0x00} }, -{ 0x1190, 16, {0x67, 0x00, 0x75, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00} }, -{ 0x11a0, 16, {0x20, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x22, 0x03} }, -{ 0x11b0, 16, {0x49, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x66, 0x00, 0x61, 0x00, 0x63, 0x00} }, -{ 0x11c0, 16, {0x65, 0x00, 0x20, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00} }, -{ 0x11d0, 2, {0x00, 0x00} }, -{ 0xffff, 0, {0x00} } -}; -#endif diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/serial/whiteheat_fw.h linux/drivers/usb/serial/whiteheat_fw.h --- v2.3.99-pre3/linux/drivers/usb/serial/whiteheat_fw.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/serial/whiteheat_fw.h Mon Apr 10 22:54:09 2000 @@ -0,0 +1,1556 @@ +/***************************************************************************** + * + * whiteheat.h -- ConnectTech WhiteHEAT Firmware. + * + * Copyright (C) 2000 ConnectTech Inc (http://www.connecttech.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. + * + * (04/09/2000) gkh + * Updated the firmware with the latest provided by ConnectTech. + * + * (01/16/2000) gkh + * Fixed my intel hex processing tool, so now the firmware actually + * matches the original file (this was causing a few problems...) + * + * (01/15/2000) gkh + * Added debug loader firmware if DEBUG is #defined: + * Port 1 LED flashes when the vend_ax program is running + * Port 2 LED flashes when any SETUP command arrives + * Port 3 LED flashes when any valid VENDOR request occurs + * Port 4 LED flashes when the EXTERNAL RAM DOWNLOAD request occurs + * + * version 1.0 (01/09/2000) gkh + * Original firmware from ConnectTech massaged a little to be program + * readable. + * + *****************************************************************************/ + +#define whiteheat_DATE "20000106" + +struct whiteheat_hex_record { + __u16 address; + __u8 data_size; + __u8 data[16]; +}; + +static const struct whiteheat_hex_record whiteheat_firmware[] = { +{ 0x0000, 3, {0x02, 0x93, 0xa9} }, +{ 0x0003, 3, {0x02, 0x13, 0x12} }, +{ 0x000b, 3, {0x02, 0x0a, 0x80} }, +{ 0x0033, 3, {0x02, 0x08, 0x15} }, +{ 0x0043, 3, {0x02, 0x0a, 0x00} }, +{ 0x005b, 3, {0x02, 0x82, 0x31} }, +{ 0x0370, 16, {0x90, 0x7f, 0xe9, 0xe0, 0x70, 0x03, 0x02, 0x04, 0x73, 0x14, 0x70, 0x03, 0x02, 0x04, 0xe7, 0x24} }, +{ 0x0380, 16, {0xfe, 0x70, 0x03, 0x02, 0x05, 0x45, 0x24, 0xfb, 0x70, 0x03, 0x02, 0x04, 0x64, 0x14, 0x70, 0x03} }, +{ 0x0390, 16, {0x02, 0x04, 0x52, 0x14, 0x70, 0x03, 0x02, 0x04, 0x3a, 0x14, 0x70, 0x03, 0x02, 0x04, 0x49, 0x24} }, +{ 0x03a0, 16, {0x05, 0x60, 0x03, 0x02, 0x05, 0x94, 0x90, 0x7f, 0xeb, 0xe0, 0x24, 0xfe, 0x60, 0x16, 0x14, 0x60} }, +{ 0x03b0, 16, {0x36, 0x24, 0x02, 0x70, 0x7b, 0x74, 0x12, 0x90, 0x7f, 0xd4, 0xf0, 0x74, 0x00, 0x90, 0x7f, 0xd5} }, +{ 0x03c0, 16, {0xf0, 0x02, 0x05, 0x9b, 0x90, 0x7f, 0xea, 0xe0, 0xff, 0x12, 0x09, 0x7b, 0xea, 0x49, 0x60, 0x0d} }, +{ 0x03d0, 16, {0xea, 0x90, 0x7f, 0xd4, 0xf0, 0xe9, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x05, 0x9b, 0x90, 0x7f, 0xb4} }, +{ 0x03e0, 16, {0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0x9b, 0x90, 0x7f, 0xea, 0xe0, 0xff, 0x12, 0x09, 0x3a, 0xea} }, +{ 0x03f0, 16, {0x49, 0x60, 0x33, 0x12, 0x9b, 0x72, 0xf5, 0x4b, 0x90, 0x7f, 0xee, 0xe0, 0xff, 0xe5, 0x4b, 0xd3} }, +{ 0x0400, 16, {0x9f, 0x40, 0x03, 0xe0, 0xf5, 0x4b, 0xe5, 0x4b, 0xd3, 0x94, 0x40, 0x40, 0x03, 0x75, 0x4b, 0x40} }, +{ 0x0410, 16, {0xae, 0x02, 0xaf, 0x01, 0x7c, 0x7f, 0x7d, 0x00, 0xab, 0x4b, 0x12, 0x8d, 0xd9, 0x90, 0x7f, 0xb5} }, +{ 0x0420, 16, {0xe5, 0x4b, 0xf0, 0x02, 0x05, 0x9b, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0x9b} }, +{ 0x0430, 16, {0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0x9b, 0x90, 0x7f, 0x00, 0xe5, 0x21, 0xf0} }, +{ 0x0440, 16, {0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x02, 0x05, 0x9b, 0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x21, 0x02} }, +{ 0x0450, 16, {0x05, 0x9b, 0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x31, 0xd2, 0x02, 0x43, 0x88, 0x10, 0xd2, 0xeb, 0xd2} }, +{ 0x0460, 16, {0xa8, 0x02, 0x05, 0x9b, 0x90, 0x7f, 0x00, 0xe5, 0x31, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0} }, +{ 0x0470, 16, {0x02, 0x05, 0x9b, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0x7f, 0x60, 0x24, 0x14, 0x60, 0x31, 0x24, 0x02} }, +{ 0x0480, 16, {0x70, 0x5b, 0xa2, 0x00, 0xe4, 0x33, 0xff, 0x25, 0xe0, 0xff, 0xa2, 0x05, 0xe4, 0x33, 0x4f, 0x90} }, +{ 0x0490, 16, {0x7f, 0x00, 0xf0, 0xe4, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0x9b, 0xe4} }, +{ 0x04a0, 16, {0x90, 0x7f, 0x00, 0xf0, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0x9b, 0x90} }, +{ 0x04b0, 16, {0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25} }, +{ 0x04c0, 16, {0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe0, 0x54, 0x01, 0x90, 0x7f, 0x00} }, +{ 0x04d0, 16, {0xf0, 0xe4, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0x9b, 0x90, 0x7f, 0xb4} }, +{ 0x04e0, 16, {0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0x9b, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0xfe, 0x60, 0x1d, 0x24} }, +{ 0x04f0, 16, {0x02, 0x60, 0x03, 0x02, 0x05, 0x9b, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x05, 0xc2, 0x00, 0x02} }, +{ 0x0500, 16, {0x05, 0x9b, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0x9b, 0x90, 0x7f, 0xea, 0xe0} }, +{ 0x0510, 16, {0x70, 0x2a, 0x90, 0x7f, 0xec, 0xe0, 0xff, 0xf4, 0x54, 0x80, 0xfe, 0xc4, 0x54, 0x0f, 0xfe, 0xef} }, +{ 0x0520, 16, {0x54, 0x07, 0xfd, 0x2e, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe4} }, +{ 0x0530, 16, {0xf0, 0x90, 0x7f, 0xd7, 0xed, 0xf0, 0xef, 0x44, 0x20, 0xf0, 0x80, 0x5f, 0x90, 0x7f, 0xb4, 0xe0} }, +{ 0x0540, 16, {0x44, 0x01, 0xf0, 0x80, 0x56, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0xfe, 0x60, 0x18, 0x24, 0x02, 0x70} }, +{ 0x0550, 16, {0x4a, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x04, 0xd2, 0x00, 0x80, 0x3f, 0x90, 0x7f, 0xb4, 0xe0} }, +{ 0x0560, 16, {0x44, 0x01, 0xf0, 0x80, 0x36, 0x90, 0x7f, 0xea, 0xe0, 0x70, 0x20, 0x90, 0x7f, 0xec, 0xe0, 0xf4} }, +{ 0x0570, 16, {0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5} }, +{ 0x0580, 16, {0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0x74, 0x01, 0xf0, 0x80, 0x10, 0x90, 0x7f, 0xb4, 0xe0, 0x44} }, +{ 0x0590, 16, {0x01, 0xf0, 0x80, 0x07, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44} }, +{ 0x05a0, 2, {0x02, 0xf0} }, +{ 0x05a2, 1, {0x22} }, +{ 0x05a3, 16, {0x75, 0x47, 0xff, 0x75, 0x46, 0xff, 0x75, 0x45, 0x0f, 0x75, 0x44, 0x00, 0xd2, 0x03, 0xc2, 0x06} }, +{ 0x05b3, 16, {0xc2, 0x02, 0xc2, 0x00, 0xc2, 0x05, 0xc2, 0x01, 0x90, 0x03, 0x00, 0x74, 0x19, 0xf0, 0xe4, 0x90} }, +{ 0x05c3, 16, {0x01, 0xbc, 0xf0, 0xc2, 0x04, 0x90, 0x01, 0xc0, 0xf0, 0xa3, 0xf0, 0xc2, 0xaf, 0xc2, 0xa8, 0x12} }, +{ 0x05d3, 16, {0x0b, 0x8d, 0xe4, 0x90, 0x02, 0xaf, 0xf0, 0x90, 0x01, 0x00, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3} }, +{ 0x05e3, 16, {0xf0, 0xa3, 0xf0, 0xa3, 0x74, 0x10, 0xf0, 0xa3, 0x74, 0x01, 0xf0, 0xa3, 0x74, 0x08, 0xf0, 0x7e} }, +{ 0x05f3, 16, {0x01, 0x7f, 0x00, 0x12, 0x19, 0xc1, 0x75, 0x49, 0x12, 0x75, 0x4a, 0x0a, 0x90, 0x01, 0x0b, 0xe0} }, +{ 0x0603, 16, {0xff, 0x05, 0x4a, 0xe5, 0x4a, 0xac, 0x49, 0x70, 0x02, 0x05, 0x49, 0x14, 0xf5, 0x82, 0x8c, 0x83} }, +{ 0x0613, 16, {0xef, 0xf0, 0x90, 0x01, 0x0c, 0xe0, 0x44, 0x80, 0xff, 0x05, 0x4a, 0xe5, 0x4a, 0xac, 0x49, 0x70} }, +{ 0x0623, 16, {0x02, 0x05, 0x49, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x90, 0x01, 0x0d, 0xe0, 0xff, 0x05} }, +{ 0x0633, 16, {0x4a, 0xe5, 0x4a, 0xac, 0x49, 0x70, 0x02, 0x05, 0x49, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0} }, +{ 0x0643, 16, {0x90, 0x01, 0x0e, 0xe0, 0xff, 0x05, 0x4a, 0xe5, 0x4a, 0xac, 0x49, 0x70, 0x02, 0x05, 0x49, 0x14} }, +{ 0x0653, 16, {0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x90, 0x12, 0x0a, 0xe4, 0x93, 0xff, 0x74, 0x01, 0x93, 0x90} }, +{ 0x0663, 16, {0x01, 0x1c, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0x01, 0x1c, 0xe0, 0xff, 0xa3, 0xe0, 0xfe, 0xef} }, +{ 0x0673, 16, {0x6e, 0xff, 0x90, 0x01, 0x1c, 0xf0, 0xa3, 0xe0, 0x6f, 0xff, 0xf0, 0x90, 0x01, 0x1c, 0xe0, 0x6f} }, +{ 0x0683, 16, {0xf0, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xe4, 0xfc, 0xfd, 0x75, 0x4f, 0x10, 0x75, 0x50, 0x02, 0x75} }, +{ 0x0693, 16, {0x51, 0x12, 0x75, 0x52, 0xac, 0x12, 0x90, 0x15, 0x75, 0x49, 0x12, 0x75, 0x4a, 0xb2, 0x90, 0x01} }, +{ 0x06a3, 16, {0x0d, 0xe0, 0xff, 0x05, 0x4a, 0xe5, 0x4a, 0xac, 0x49, 0x70, 0x02, 0x05, 0x49, 0x14, 0xf5, 0x82} }, +{ 0x06b3, 16, {0x8c, 0x83, 0xef, 0xf0, 0x90, 0x01, 0x0e, 0xe0, 0xff, 0x05, 0x4a, 0xe5, 0x4a, 0xac, 0x49, 0x70} }, +{ 0x06c3, 16, {0x02, 0x05, 0x49, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x90, 0x7f, 0x92, 0xe0, 0xff, 0xc4} }, +{ 0x06d3, 16, {0x54, 0x0f, 0x24, 0x41, 0xff, 0x05, 0x4a, 0xe5, 0x4a, 0xac, 0x49, 0x70, 0x02, 0x05, 0x49, 0x14} }, +{ 0x06e3, 16, {0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x05, 0x4a, 0xe5, 0x4a, 0xae, 0x49, 0x70, 0x02, 0x05, 0x49} }, +{ 0x06f3, 16, {0x14, 0xf5, 0x82, 0x8e, 0x83, 0xe4, 0xf0, 0x75, 0x82, 0x10, 0x75, 0x83, 0x01, 0xe0, 0xfc, 0xa3} }, +{ 0x0703, 16, {0xe0, 0xfd, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x90, 0x01, 0x18, 0x12, 0x9d, 0x25, 0x7e, 0x01} }, +{ 0x0713, 16, {0x7f, 0x18, 0x12, 0x85, 0x08, 0x90, 0x01, 0x18, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe} }, +{ 0x0723, 16, {0xa3, 0xe0, 0xff, 0x75, 0x4f, 0x0a, 0x75, 0x50, 0x06, 0x75, 0x51, 0x12, 0x75, 0x52, 0xb8, 0x12} }, +{ 0x0733, 16, {0x90, 0x15, 0xd2, 0xe8, 0x43, 0xd8, 0x20, 0x90, 0x7f, 0xab, 0x74, 0xff, 0xf0, 0x53, 0x91, 0xef} }, +{ 0x0743, 16, {0x90, 0x7f, 0xaf, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xae, 0xe0, 0x44, 0x1f, 0xf0, 0xd2, 0xaf} }, +{ 0x0753, 16, {0x20, 0x01, 0x2e, 0x20, 0x01, 0x2b, 0xa2, 0x03, 0x92, 0x07, 0x12, 0x09, 0xca, 0x75, 0x43, 0x50} }, +{ 0x0763, 16, {0x75, 0x42, 0x6d, 0x75, 0x41, 0x33, 0x75, 0x40, 0x00, 0x20, 0x01, 0xe4, 0x7f, 0xff, 0x7e, 0xff} }, +{ 0x0773, 16, {0x7d, 0xff, 0x7c, 0xff, 0x78, 0x40, 0x12, 0x9d, 0x0e, 0xec, 0x4d, 0x4e, 0x4f, 0x60, 0xd1, 0x80} }, +{ 0x0783, 16, {0xe8, 0x30, 0x01, 0x05, 0x12, 0x03, 0x70, 0xc2, 0x01, 0x30, 0x06, 0x0d, 0x12, 0x0a, 0xed, 0x50} }, +{ 0x0793, 16, {0x06, 0x12, 0x0b, 0x00, 0x12, 0x0a, 0xf2, 0xc2, 0x06, 0x12, 0x92, 0x38, 0x90, 0x01, 0xbd, 0xe0} }, +{ 0x07a3, 16, {0x60, 0x10, 0x7e, 0x7b, 0x7f, 0x40, 0x12, 0x8e, 0xc1, 0xe4, 0x90, 0x01, 0xbd, 0xf0, 0x90, 0x7f} }, +{ 0x07b3, 16, {0xd3, 0xf0, 0x90, 0x02, 0xaf, 0xe0, 0xb4, 0x0f, 0x03, 0x12, 0x95, 0x30, 0x12, 0x99, 0xcc, 0xe4} }, +{ 0x07c3, 16, {0xff, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xfe, 0x90, 0x01, 0xbc} }, +{ 0x07d3, 16, {0xe0, 0x5e, 0x60, 0x14, 0x74, 0x27, 0x2f, 0xf8, 0xe6, 0xd3, 0x94, 0x0a, 0x40, 0x04, 0x7e, 0x01} }, +{ 0x07e3, 16, {0x80, 0x02, 0x7e, 0x00, 0x8e, 0x48, 0x80, 0x03, 0x75, 0x48, 0x01, 0x74, 0x68, 0x2f, 0xf5, 0x82} }, +{ 0x07f3, 16, {0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe5, 0x48, 0xf0, 0x0f, 0xbf, 0x04, 0xc5, 0xe5, 0x2b, 0xd3, 0x94} }, +{ 0x0803, 16, {0x0a, 0x40, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0x90, 0x20, 0x6c, 0xef, 0xf0, 0x02, 0x07} }, +{ 0x0813, 1, {0x84} }, +{ 0x0814, 1, {0x22} }, +{ 0x0815, 4, {0x53, 0xd8, 0xef, 0x32} }, +{ 0x0819, 16, {0xe4, 0x90, 0x7f, 0x9c, 0xf0, 0x7f, 0x0a, 0xfe, 0x12, 0x09, 0x23, 0x90, 0x7f, 0x96, 0x74, 0x89} }, +{ 0x0829, 16, {0xf0, 0x90, 0x7f, 0x9c, 0x74, 0xcf, 0xf0, 0x7f, 0xf4, 0x7e, 0x01, 0x12, 0x09, 0x23, 0x90, 0x7f} }, +{ 0x0839, 16, {0x96, 0xe0, 0x54, 0xfe, 0xf0, 0x7f, 0x0a, 0x7e, 0x00, 0x12, 0x09, 0x23, 0x7f, 0x02, 0x7d, 0xff} }, +{ 0x0849, 16, {0x12, 0x81, 0xe0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x09, 0x23, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x02} }, +{ 0x0859, 16, {0xf0, 0xe0, 0x54, 0x7f, 0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x09, 0x23, 0x90, 0x7f, 0x96, 0xe0} }, +{ 0x0869, 16, {0x44, 0x40, 0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x09, 0x23, 0x90, 0x7f, 0x96, 0xe0, 0x54, 0xbf} }, +{ 0x0879, 16, {0xf0, 0x7f, 0x32, 0x7e, 0x00, 0x12, 0x09, 0x23, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x40, 0xf0, 0x7f} }, +{ 0x0889, 7, {0x32, 0x7e, 0x00, 0x12, 0x09, 0x23, 0x22} }, +{ 0x0890, 16, {0x90, 0x7f, 0x96, 0xe0, 0x54, 0xfd, 0xf0, 0xe0, 0x44, 0x80, 0xf0, 0x7f, 0x0a, 0x7e, 0x00, 0x12} }, +{ 0x08a0, 16, {0x09, 0x23, 0x7f, 0x02, 0xe4, 0xfd, 0x12, 0x81, 0xe0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x09, 0x23} }, +{ 0x08b0, 16, {0x90, 0x7f, 0x96, 0xe0, 0x54, 0xbf, 0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x09, 0x23, 0x90, 0x7f} }, +{ 0x08c0, 16, {0x96, 0xe0, 0x44, 0x04, 0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x09, 0x23, 0x90, 0x7f, 0x96, 0xe0} }, +{ 0x08d0, 16, {0x54, 0xf7, 0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x09, 0x23, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x01} }, +{ 0x08e0, 12, {0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x09, 0x23, 0x12, 0x0b, 0x00, 0x22} }, +{ 0x08ec, 16, {0x90, 0x11, 0xfc, 0xe4, 0x93, 0x70, 0x2f, 0x90, 0x7f, 0x93, 0x74, 0x30, 0xf0, 0x90, 0x7f, 0x94} }, +{ 0x08fc, 16, {0x74, 0x3c, 0xf0, 0x90, 0x7f, 0x95, 0x74, 0xc6, 0xf0, 0xe4, 0x90, 0x7f, 0x97, 0xf0, 0x90, 0x7f} }, +{ 0x090c, 16, {0x9d, 0x74, 0x02, 0xf0, 0x90, 0x7f, 0xe2, 0x74, 0x12, 0xf0, 0x12, 0x08, 0x19, 0x75, 0x82, 0xfc} }, +{ 0x091c, 7, {0x75, 0x83, 0x11, 0x74, 0xff, 0xf0, 0x22} }, +{ 0x0923, 16, {0x8e, 0x58, 0x8f, 0x59, 0xe5, 0x59, 0x15, 0x59, 0xae, 0x58, 0x70, 0x02, 0x15, 0x58, 0x4e, 0x60} }, +{ 0x0933, 7, {0x05, 0x12, 0x09, 0xef, 0x80, 0xee, 0x22} }, +{ 0x093a, 2, {0x8f, 0x4c} }, +{ 0x093c, 16, {0xe4, 0xf5, 0x4d, 0x75, 0x4e, 0xff, 0x75, 0x4f, 0x12, 0x75, 0x50, 0x6a, 0xab, 0x4e, 0xaa, 0x4f} }, +{ 0x094c, 16, {0xa9, 0x50, 0x90, 0x00, 0x01, 0x12, 0x9b, 0x8b, 0xb4, 0x03, 0x1d, 0xaf, 0x4d, 0x05, 0x4d, 0xef} }, +{ 0x095c, 16, {0xb5, 0x4c, 0x01, 0x22, 0x12, 0x9b, 0x72, 0x7e, 0x00, 0x29, 0xff, 0xee, 0x3a, 0xa9, 0x07, 0x75} }, +{ 0x096c, 14, {0x4e, 0xff, 0xf5, 0x4f, 0x89, 0x50, 0x80, 0xd4, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} }, +{ 0x097a, 1, {0x22} }, +{ 0x097b, 16, {0xe4, 0xfe, 0x75, 0x4e, 0xff, 0x75, 0x4f, 0x12, 0x75, 0x50, 0x12, 0xab, 0x4e, 0xaa, 0x4f, 0xa9} }, +{ 0x098b, 16, {0x50, 0x90, 0x00, 0x01, 0x12, 0x9b, 0x8b, 0x64, 0x02, 0x70, 0x2d, 0xad, 0x06, 0x0e, 0xed, 0xb5} }, +{ 0x099b, 16, {0x07, 0x01, 0x22, 0x90, 0x00, 0x02, 0x12, 0x9b, 0xe4, 0x85, 0xf0, 0x4c, 0xf5, 0x4d, 0x62, 0x4c} }, +{ 0x09ab, 16, {0xe5, 0x4c, 0x62, 0x4d, 0xe5, 0x4d, 0x62, 0x4c, 0x29, 0xfd, 0xe5, 0x4c, 0x3a, 0xa9, 0x05, 0x75} }, +{ 0x09bb, 14, {0x4e, 0xff, 0xf5, 0x4f, 0x89, 0x50, 0x80, 0xc3, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} }, +{ 0x09c9, 1, {0x22} }, +{ 0x09ca, 16, {0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x30, 0x07, 0x04, 0xe0, 0x44} }, +{ 0x09da, 16, {0x02, 0xf0, 0x7f, 0xd0, 0x7e, 0x07, 0x12, 0x09, 0x23, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xf7, 0xf0} }, +{ 0x09ea, 5, {0xe0, 0x44, 0x04, 0xf0, 0x22} }, +{ 0x09ef, 16, {0x74, 0x00, 0xf5, 0x86, 0x90, 0xfd, 0xa5, 0x7c, 0x05, 0xa3, 0xe5, 0x82, 0x45, 0x83, 0x70, 0xf9} }, +{ 0x09ff, 1, {0x22} }, +{ 0x0a00, 16, {0x02, 0x0b, 0xaa, 0x00, 0x02, 0x0b, 0xdd, 0x00, 0x02, 0x0b, 0xc2, 0x00, 0x02, 0x0c, 0x1c, 0x00} }, +{ 0x0a10, 16, {0x02, 0x0c, 0x06, 0x00, 0x02, 0x0a, 0xf7, 0x00, 0x02, 0x0a, 0xf8, 0x00, 0x02, 0x0a, 0xf9, 0x00} }, +{ 0x0a20, 16, {0x02, 0x0c, 0x37, 0x00, 0x02, 0x0d, 0x27, 0x00, 0x02, 0x0c, 0x73, 0x00, 0x02, 0x0d, 0x7b, 0x00} }, +{ 0x0a30, 16, {0x02, 0x0c, 0xaf, 0x00, 0x02, 0x0d, 0xcf, 0x00, 0x02, 0x0c, 0xeb, 0x00, 0x02, 0x0e, 0x23, 0x00} }, +{ 0x0a40, 16, {0x02, 0x0a, 0xfa, 0x00, 0x02, 0x0a, 0xfc, 0x00, 0x02, 0x0a, 0xfb, 0x00, 0x02, 0x0a, 0xfd, 0x00} }, +{ 0x0a50, 8, {0x02, 0x0e, 0x77, 0x00, 0x02, 0x0e, 0x8d, 0x00} }, +{ 0x0a58, 16, {0x53, 0x8e, 0xf7, 0xe5, 0x89, 0x54, 0xf1, 0x44, 0x01, 0xf5, 0x89, 0x75, 0x8c, 0xb1, 0xd2, 0xa9} }, +{ 0x0a68, 16, {0x75, 0x98, 0x40, 0x75, 0xcb, 0xff, 0x75, 0xca, 0xf3, 0x75, 0xc8, 0x34, 0xe4, 0xff, 0x7f, 0x05} }, +{ 0x0a78, 7, {0x78, 0x27, 0xe4, 0xf6, 0x08, 0xdf, 0xfc} }, +{ 0x0a7f, 1, {0x22} }, +{ 0x0a80, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x00, 0xc0, 0x00, 0xc0, 0x06, 0xc0} }, +{ 0x0a90, 1, {0x07} }, +{ 0x0a91, 16, {0x30, 0x04, 0x16, 0x75, 0x8c, 0xf8, 0x75, 0x8a, 0x30, 0x7f, 0x2f, 0xae, 0x07, 0x1f, 0xee, 0x60} }, +{ 0x0aa1, 16, {0x3c, 0x90, 0x20, 0x00, 0x74, 0x55, 0xf0, 0x80, 0xf2, 0x75, 0x8c, 0xb1, 0x7f, 0x27, 0xef, 0xd3} }, +{ 0x0ab1, 16, {0x94, 0x2b, 0x50, 0x09, 0xa8, 0x07, 0xe6, 0x60, 0x01, 0x16, 0x0f, 0x80, 0xf1, 0x90, 0x03, 0x00} }, +{ 0x0ac1, 16, {0xe0, 0x60, 0x02, 0x14, 0xf0, 0x90, 0x01, 0xc0, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x0e, 0x90} }, +{ 0x0ad1, 13, {0x01, 0xc1, 0xe0, 0x24, 0xff, 0xf0, 0x90, 0x01, 0xc0, 0xe0, 0x34, 0xff, 0xf0} }, +{ 0x0ade, 15, {0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x00, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0aed, 5, {0x12, 0x08, 0x90, 0xd3, 0x22} }, +{ 0x0af2, 5, {0x12, 0x08, 0x19, 0xd3, 0x22} }, +{ 0x0af7, 1, {0x32} }, +{ 0x0af8, 1, {0x32} }, +{ 0x0af9, 1, {0x32} }, +{ 0x0afa, 1, {0x32} }, +{ 0x0afb, 1, {0x32} }, +{ 0x0afc, 1, {0x32} }, +{ 0x0afd, 1, {0x32} }, +{ 0x0b00, 9, {0x90, 0x7f, 0xd6, 0xe0, 0x44, 0x80, 0xf0, 0x80, 0x74} }, +{ 0x0b7d, 16, {0x43, 0x87, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22} }, +{ 0x0b8d, 16, {0xd2, 0x00, 0x75, 0x8e, 0x10, 0xe4, 0x90, 0x7f, 0x92, 0xf0, 0x12, 0x10, 0x0c, 0x12, 0x08, 0xec} }, +{ 0x0b9d, 13, {0x12, 0x0e, 0xa9, 0x12, 0x90, 0xe6, 0x12, 0x1b, 0x0c, 0x12, 0x0a, 0x58, 0x22} }, +{ 0x0baa, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xd2, 0x01, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x01} }, +{ 0x0bba, 8, {0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0bc2, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x90, 0x7f, 0xc4, 0xe4, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f} }, +{ 0x0bd2, 11, {0xab, 0x74, 0x04, 0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0bdd, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x02, 0xf0, 0x90} }, +{ 0x0bed, 16, {0x7f, 0xd8, 0xe0, 0x70, 0x0d, 0x90, 0x7f, 0xd9, 0xe0, 0x70, 0x07, 0xe5, 0x2b, 0x70, 0x03, 0x75} }, +{ 0x0bfd, 9, {0x2b, 0x14, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0c06, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x10, 0xf0, 0xd0} }, +{ 0x0c16, 6, {0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0c1c, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x30, 0x02, 0x02, 0xd2, 0x06, 0x53, 0x91, 0xef, 0x90, 0x7f} }, +{ 0x0c2c, 11, {0xab, 0x74, 0x08, 0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0c37, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x10, 0x53, 0x91, 0xef, 0x90, 0x7f} }, +{ 0x0c47, 16, {0xa9, 0x74, 0x02, 0xf0, 0xe5, 0x30, 0x30, 0xe0, 0x13, 0xe5, 0x3b, 0x30, 0xe0, 0x07, 0x90, 0x20} }, +{ 0x0c57, 16, {0x04, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x20, 0x01, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x2b, 0x70, 0x03} }, +{ 0x0c67, 12, {0x75, 0x2b, 0x14, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0c73, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x10, 0x53, 0x91, 0xef, 0x90, 0x7f} }, +{ 0x0c83, 16, {0xa9, 0x74, 0x04, 0xf0, 0xe5, 0x30, 0x30, 0xe1, 0x13, 0xe5, 0x3b, 0x30, 0xe1, 0x07, 0x90, 0x20} }, +{ 0x0c93, 16, {0x0c, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x20, 0x09, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x2b, 0x70, 0x03} }, +{ 0x0ca3, 12, {0x75, 0x2b, 0x14, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0caf, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x10, 0x53, 0x91, 0xef, 0x90, 0x7f} }, +{ 0x0cbf, 16, {0xa9, 0x74, 0x08, 0xf0, 0xe5, 0x30, 0x30, 0xe2, 0x13, 0xe5, 0x3b, 0x30, 0xe2, 0x07, 0x90, 0x20} }, +{ 0x0ccf, 16, {0x14, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x20, 0x11, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x2b, 0x70, 0x03} }, +{ 0x0cdf, 12, {0x75, 0x2b, 0x14, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0ceb, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x10, 0x53, 0x91, 0xef, 0x90, 0x7f} }, +{ 0x0cfb, 16, {0xa9, 0x74, 0x10, 0xf0, 0xe5, 0x30, 0x30, 0xe3, 0x13, 0xe5, 0x3b, 0x30, 0xe3, 0x07, 0x90, 0x20} }, +{ 0x0d0b, 16, {0x1c, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x20, 0x19, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x2b, 0x70, 0x03} }, +{ 0x0d1b, 12, {0x75, 0x2b, 0x14, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0d27, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xc0} }, +{ 0x0d37, 16, {0xd0, 0x75, 0xd0, 0x10, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xaa, 0x74, 0x02, 0xf0, 0xe5, 0x30, 0x20} }, +{ 0x0d47, 16, {0xe0, 0x06, 0x90, 0x7f, 0xc7, 0xf0, 0x80, 0x16, 0xe5, 0x3b, 0x30, 0xe0, 0x0a, 0x90, 0x7f, 0xc7} }, +{ 0x0d57, 16, {0xe0, 0x90, 0x02, 0xf8, 0xf0, 0x80, 0x07, 0x90, 0x20, 0x01, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x2b} }, +{ 0x0d67, 16, {0x70, 0x03, 0x75, 0x2b, 0x14, 0xd0, 0xd0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0} }, +{ 0x0d77, 4, {0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0d7b, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xc0} }, +{ 0x0d8b, 16, {0xd0, 0x75, 0xd0, 0x10, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xaa, 0x74, 0x04, 0xf0, 0xe5, 0x30, 0x20} }, +{ 0x0d9b, 16, {0xe1, 0x06, 0x90, 0x7f, 0xc9, 0xf0, 0x80, 0x16, 0xe5, 0x3b, 0x30, 0xe1, 0x0a, 0x90, 0x7f, 0xc9} }, +{ 0x0dab, 16, {0xe0, 0x90, 0x02, 0xf9, 0xf0, 0x80, 0x07, 0x90, 0x20, 0x09, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x2b} }, +{ 0x0dbb, 16, {0x70, 0x03, 0x75, 0x2b, 0x14, 0xd0, 0xd0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0} }, +{ 0x0dcb, 4, {0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0dcf, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xc0} }, +{ 0x0ddf, 16, {0xd0, 0x75, 0xd0, 0x10, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xaa, 0x74, 0x08, 0xf0, 0xe5, 0x30, 0x20} }, +{ 0x0def, 16, {0xe2, 0x06, 0x90, 0x7f, 0xcb, 0xf0, 0x80, 0x16, 0xe5, 0x3b, 0x30, 0xe2, 0x0a, 0x90, 0x7f, 0xcb} }, +{ 0x0dff, 16, {0xe0, 0x90, 0x02, 0xfa, 0xf0, 0x80, 0x07, 0x90, 0x20, 0x11, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x2b} }, +{ 0x0e0f, 16, {0x70, 0x03, 0x75, 0x2b, 0x14, 0xd0, 0xd0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0} }, +{ 0x0e1f, 4, {0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0e23, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xc0} }, +{ 0x0e33, 16, {0xd0, 0x75, 0xd0, 0x10, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xaa, 0x74, 0x10, 0xf0, 0xe5, 0x30, 0x20} }, +{ 0x0e43, 16, {0xe3, 0x06, 0x90, 0x7f, 0xcd, 0xf0, 0x80, 0x16, 0xe5, 0x3b, 0x30, 0xe3, 0x0a, 0x90, 0x7f, 0xcd} }, +{ 0x0e53, 16, {0xe0, 0x90, 0x02, 0xfb, 0xf0, 0x80, 0x07, 0x90, 0x20, 0x19, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x2b} }, +{ 0x0e63, 16, {0x70, 0x03, 0x75, 0x2b, 0x14, 0xd0, 0xd0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0} }, +{ 0x0e73, 4, {0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0e77, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xa9, 0x74, 0x80, 0xf0, 0xd0} }, +{ 0x0e87, 6, {0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0e8d, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xaa, 0x74, 0x80, 0xf0, 0x90} }, +{ 0x0e9d, 12, {0x01, 0xbd, 0x74, 0xff, 0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0ea9, 16, {0x90, 0x01, 0x20, 0x12, 0x9d, 0x31, 0x00, 0x00, 0x25, 0x80, 0x90, 0x01, 0x24, 0x74, 0x08, 0xf0} }, +{ 0x0eb9, 16, {0xa3, 0x74, 0x01, 0xf0, 0xa3, 0x74, 0x6e, 0xf0, 0xa3, 0xf0, 0xa3, 0x74, 0x13, 0xf0, 0xa3, 0x74} }, +{ 0x0ec9, 16, {0x11, 0xf0, 0xe4, 0xa3, 0xf0, 0xa3, 0xf0, 0x90, 0x01, 0x1e, 0xf0, 0x90, 0x01, 0x1e, 0xe0, 0xff} }, +{ 0x0ed9, 16, {0xc3, 0x94, 0x04, 0x50, 0x13, 0xef, 0x04, 0xa3, 0xf0, 0x7e, 0x01, 0x7f, 0x1f, 0x12, 0x85, 0xe1} }, +{ 0x0ee9, 16, {0x90, 0x01, 0x1e, 0xe0, 0x04, 0xf0, 0x80, 0xe3, 0xe4, 0xf5, 0x26, 0x90, 0x01, 0x1e, 0xf0, 0x90} }, +{ 0x0ef9, 16, {0x01, 0x1e, 0xe0, 0xff, 0xc3, 0x94, 0x04, 0x50, 0x1a, 0x74, 0xf8, 0x2f, 0xf5, 0x82, 0xe4, 0x34} }, +{ 0x0f09, 16, {0x02, 0xf5, 0x83, 0xe4, 0xf0, 0x74, 0x22, 0x2f, 0xf8, 0xe4, 0xf6, 0x90, 0x01, 0x1e, 0xe0, 0x04} }, +{ 0x0f19, 16, {0xf0, 0x80, 0xdc, 0xe4, 0xf5, 0x30, 0xe5, 0xc0, 0x60, 0x2f, 0x90, 0x01, 0x1e, 0x74, 0x01, 0xf0} }, +{ 0x0f29, 16, {0x90, 0x01, 0x1e, 0xe0, 0xff, 0xd3, 0x94, 0x04, 0x50, 0x1f, 0xef, 0x14, 0xff, 0x74, 0x01, 0xa8} }, +{ 0x0f39, 16, {0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x42, 0x30, 0x7e, 0x01, 0x7f, 0x1e, 0x12, 0x83} }, +{ 0x0f49, 16, {0x5f, 0x90, 0x01, 0x1e, 0xe0, 0x04, 0xf0, 0x80, 0xd7, 0xe4, 0xf5, 0x3a, 0x90, 0x01, 0x1e, 0xf0} }, +{ 0x0f59, 16, {0x90, 0x01, 0x1e, 0xe0, 0xff, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x34, 0x20} }, +{ 0x0f69, 16, {0xf5, 0x83, 0xe0, 0x54, 0xf0, 0xfe, 0x74, 0xc5, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x01, 0xf5, 0x83} }, +{ 0x0f79, 16, {0xee, 0xf0, 0x74, 0x36, 0x2f, 0xf8, 0xa6, 0x06, 0x74, 0x32, 0x2f, 0xf8, 0xe4, 0xf6, 0x74, 0x2c} }, +{ 0x0f89, 16, {0x2f, 0xf8, 0xe4, 0xf6, 0x74, 0xfc, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe4, 0xf0} }, +{ 0x0f99, 16, {0x90, 0x01, 0x1e, 0xe0, 0x04, 0xf0, 0xe0, 0xb4, 0x04, 0xb6, 0x90, 0x20, 0x60, 0xe0, 0x54, 0x0f} }, +{ 0x0fa9, 16, {0xf5, 0x4b, 0x60, 0x5e, 0xe4, 0x90, 0x01, 0x1e, 0xf0, 0x90, 0x01, 0x1e, 0xe0, 0xff, 0xc3, 0x94} }, +{ 0x0fb9, 16, {0x04, 0x50, 0xe7, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x55, 0x4b} }, +{ 0x0fc9, 16, {0x60, 0x38, 0x90, 0x01, 0x1e, 0xe0, 0xff, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x02, 0xf5, 0x82, 0xe4} }, +{ 0x0fd9, 16, {0x34, 0x20, 0xf5, 0x83, 0xe0, 0xfe, 0xef, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4} }, +{ 0x0fe9, 16, {0x34, 0x20, 0xf5, 0x83, 0xe0, 0xef, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x34} }, +{ 0x0ff9, 16, {0x20, 0xf5, 0x83, 0xe0, 0xfe, 0x7d, 0x06, 0x12, 0x82, 0xd5, 0x90, 0x01, 0x1e, 0xe0, 0x04, 0xf0} }, +{ 0x1009, 3, {0x80, 0xa7, 0x22} }, +{ 0x100c, 16, {0x7b, 0xff, 0x7a, 0x12, 0x79, 0x1b, 0x90, 0x00, 0x04, 0x12, 0x9b, 0x8b, 0xfd, 0x8b, 0x4d, 0x75} }, +{ 0x101c, 16, {0x4e, 0x12, 0x75, 0x4f, 0x24, 0xe4, 0x90, 0x7f, 0xe1, 0xf0, 0x90, 0x7f, 0xe0, 0xf0, 0xf5, 0x4b} }, +{ 0x102c, 16, {0xf5, 0x4c, 0x90, 0x02, 0xae, 0xf0, 0x90, 0x7f, 0xdf, 0xf0, 0x90, 0x7f, 0xde, 0xf0, 0x90, 0x7f} }, +{ 0x103c, 16, {0xa9, 0x74, 0xff, 0xf0, 0x90, 0x7f, 0xaa, 0xf0, 0xe4, 0xfc, 0xec, 0x25, 0xe0, 0x24, 0xb4, 0xf5} }, +{ 0x104c, 16, {0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe4, 0xf0, 0x0c, 0xbc, 0x10, 0xee, 0xe4, 0x90, 0x7f, 0xdd} }, +{ 0x105c, 16, {0xf0, 0xaf, 0x05, 0x1d, 0xef, 0x70, 0x03, 0x02, 0x11, 0xd2, 0xab, 0x4d, 0xaa, 0x4e, 0xa9, 0x4f} }, +{ 0x106c, 16, {0x90, 0x00, 0x01, 0x12, 0x9b, 0x8b, 0x64, 0x05, 0x60, 0x03, 0x02, 0x11, 0xc1, 0x90, 0x00, 0x03} }, +{ 0x107c, 16, {0x12, 0x9b, 0x8b, 0x64, 0x01, 0x60, 0x03, 0x02, 0x11, 0x48, 0x90, 0x00, 0x02, 0x12, 0x9b, 0x8b} }, +{ 0x108c, 16, {0xff, 0x54, 0x7f, 0xfc, 0xd3, 0x94, 0x07, 0x50, 0x03, 0x02, 0x11, 0x22, 0xec, 0xc3, 0x94, 0x10} }, +{ 0x109c, 16, {0x40, 0x03, 0x02, 0x11, 0x22, 0xef, 0x30, 0xe7, 0x42, 0xe5, 0x4c, 0xae, 0x4b, 0x78, 0x02, 0xce} }, +{ 0x10ac, 16, {0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff, 0x74, 0xf0, 0x2c, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5} }, +{ 0x10bc, 16, {0x83, 0xef, 0xf0, 0x90, 0x7f, 0xe0, 0xe0, 0xff, 0xec, 0x24, 0xf8, 0xfe, 0x74, 0x01, 0xa8, 0x06} }, +{ 0x10cc, 16, {0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x4f, 0x90, 0x7f, 0xe0, 0xf0, 0x90, 0x02, 0xae, 0xe0} }, +{ 0x10dc, 16, {0x04, 0xf0, 0x90, 0x7f, 0xdd, 0xe0, 0x44, 0x80, 0xf0, 0x80, 0x3e, 0xe5, 0x4c, 0xae, 0x4b, 0x78} }, +{ 0x10ec, 16, {0x02, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff, 0x74, 0xe8, 0x2c, 0xf5, 0x82, 0xe4, 0x34} }, +{ 0x10fc, 16, {0x7f, 0xf5, 0x83, 0xef, 0xf0, 0x90, 0x7f, 0xe1, 0xe0, 0xff, 0xec, 0x24, 0xf8, 0xfe, 0x74, 0x01} }, +{ 0x110c, 16, {0xa8, 0x06, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x4f, 0x90, 0x7f, 0xe1, 0xf0, 0x90, 0x02} }, +{ 0x111c, 16, {0xae, 0xe0, 0x04, 0xf0, 0x80, 0x03, 0x7f, 0xff, 0x22, 0x90, 0x00, 0x04, 0x12, 0x9b, 0x8b, 0x25} }, +{ 0x112c, 16, {0x4c, 0xf5, 0x4c, 0xe4, 0x35, 0x4b, 0xf5, 0x4b, 0x90, 0x00, 0x05, 0x12, 0x9b, 0x8b, 0xfe, 0xe4} }, +{ 0x113c, 16, {0x25, 0x4c, 0xf5, 0x4c, 0xee, 0x35, 0x4b, 0xf5, 0x4b, 0x02, 0x11, 0xc4, 0xab, 0x4d, 0xaa, 0x4e} }, +{ 0x114c, 16, {0xa9, 0x4f, 0x90, 0x00, 0x03, 0x12, 0x9b, 0x8b, 0xff, 0x64, 0x02, 0x60, 0x05, 0xef, 0x64, 0x03} }, +{ 0x115c, 16, {0x70, 0x60, 0x90, 0x00, 0x02, 0x12, 0x9b, 0x8b, 0xff, 0x54, 0x7f, 0xfc, 0xd3, 0x94, 0x07, 0x50} }, +{ 0x116c, 16, {0x4e, 0xef, 0x30, 0xe7, 0x1e, 0x90, 0x7f, 0xde, 0xe0, 0xff, 0x74, 0x01, 0xa8, 0x04, 0x08, 0x80} }, +{ 0x117c, 16, {0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xfe, 0x4f, 0x90, 0x7f, 0xde, 0xf0, 0x90, 0x7f, 0xac, 0xe0, 0x4e} }, +{ 0x118c, 16, {0xf0, 0x80, 0x35, 0x90, 0x7f, 0xdf, 0xe0, 0xff, 0x74, 0x01, 0xa8, 0x04, 0x08, 0x80, 0x02, 0xc3} }, +{ 0x119c, 16, {0x33, 0xd8, 0xfc, 0xfe, 0x4f, 0x90, 0x7f, 0xdf, 0xf0, 0x90, 0x7f, 0xad, 0xe0, 0x4e, 0xf0, 0xec} }, +{ 0x11ac, 16, {0x25, 0xe0, 0x24, 0xc5, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xec, 0xf0, 0x80, 0x09, 0x7f} }, +{ 0x11bc, 16, {0xff, 0x22, 0x7f, 0xff, 0x22, 0x7f, 0xff, 0x22, 0x74, 0x07, 0x25, 0x4f, 0xf5, 0x4f, 0xe4, 0x35} }, +{ 0x11cc, 16, {0x4e, 0xf5, 0x4e, 0x02, 0x10, 0x5d, 0x20, 0x03, 0x0d, 0x90, 0x02, 0xae, 0xe0, 0x60, 0x07, 0x90} }, +{ 0x11dc, 8, {0x7f, 0xae, 0xe0, 0x44, 0x02, 0xf0, 0x7f, 0x00} }, +{ 0x11e4, 1, {0x22} }, +{ 0x11e5, 16, {0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xff, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33} }, +{ 0x11f5, 7, {0xd8, 0xfc, 0x42, 0x3a, 0x7f, 0x00, 0x22} }, +{ 0x11fc, 3, {0x00, 0x03, 0x15} }, +{ 0x1200, 16, {0x12, 0x01, 0x00, 0x01, 0xff, 0xff, 0xff, 0x40, 0x10, 0x07, 0x01, 0x80, 0x42, 0x00, 0x01, 0x02} }, +{ 0x1210, 16, {0x03, 0x01, 0x09, 0x02, 0x58, 0x00, 0x01, 0x01, 0x04, 0x80, 0x3c, 0x09, 0x04, 0x00, 0x00, 0x0a} }, +{ 0x1220, 16, {0xff, 0xff, 0xff, 0x05, 0x07, 0x05, 0x81, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x01, 0x02, 0x40} }, +{ 0x1230, 16, {0x00, 0x00, 0x07, 0x05, 0x82, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x02, 0x02, 0x40, 0x00, 0x00} }, +{ 0x1240, 16, {0x07, 0x05, 0x83, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x03, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05} }, +{ 0x1250, 16, {0x84, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x04, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x87, 0x02} }, +{ 0x1260, 16, {0x40, 0x00, 0x00, 0x07, 0x05, 0x07, 0x02, 0x40, 0x00, 0x00, 0x04, 0x03, 0x09, 0x04, 0x24, 0x03} }, +{ 0x1270, 16, {0x43, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x20, 0x00} }, +{ 0x1280, 16, {0x54, 0x00, 0x65, 0x00, 0x63, 0x00, 0x68, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00} }, +{ 0x1290, 16, {0x2e, 0x00, 0x18, 0x03, 0x57, 0x00, 0x68, 0x00, 0x69, 0x00, 0x74, 0x00, 0x65, 0x00, 0x48, 0x00} }, +{ 0x12a0, 16, {0x45, 0x00, 0x41, 0x00, 0x54, 0x00, 0x2d, 0x00, 0x34, 0x00, 0x1a, 0x03, 0x58, 0x00, 0x58, 0x00} }, +{ 0x12b0, 16, {0x2d, 0x00, 0x58, 0x00, 0x58, 0x00, 0x2d, 0x00, 0x58, 0x00, 0x58, 0x00, 0x58, 0x00, 0x58, 0x00} }, +{ 0x12c0, 16, {0x58, 0x00, 0x58, 0x00, 0x2a, 0x03, 0x43, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x69, 0x00} }, +{ 0x12d0, 16, {0x67, 0x00, 0x75, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00} }, +{ 0x12e0, 16, {0x20, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x22, 0x03} }, +{ 0x12f0, 16, {0x49, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x66, 0x00, 0x61, 0x00, 0x63, 0x00} }, +{ 0x1300, 16, {0x65, 0x00, 0x20, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00} }, +{ 0x1310, 2, {0x00, 0x00} }, +{ 0x1312, 16, {0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0xc0, 0xd0} }, +{ 0x1322, 16, {0x75, 0x86, 0x00, 0x75, 0xd0, 0x18, 0x90, 0x20, 0x60, 0xe0, 0x54, 0x0f, 0xf5, 0xf0, 0x70, 0x11} }, +{ 0x1332, 16, {0xd0, 0xd0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0} }, +{ 0x1342, 16, {0x32, 0x75, 0x86, 0x00, 0x10, 0xf0, 0x0b, 0x10, 0xf1, 0x12, 0x10, 0xf2, 0x19, 0x10, 0xf3, 0x20} }, +{ 0x1352, 16, {0x80, 0xd4, 0xe5, 0x27, 0x70, 0x03, 0x75, 0x27, 0x14, 0x02, 0x13, 0x7c, 0xe5, 0x28, 0x70, 0x03} }, +{ 0x1362, 16, {0x75, 0x28, 0x14, 0x02, 0x15, 0x0d, 0xe5, 0x29, 0x70, 0x03, 0x75, 0x29, 0x14, 0x02, 0x16, 0x9e} }, +{ 0x1372, 16, {0xe5, 0x2a, 0x70, 0x03, 0x75, 0x2a, 0x14, 0x02, 0x18, 0x2f, 0x90, 0x20, 0x02, 0xe0, 0x54, 0x3f} }, +{ 0x1382, 16, {0x20, 0xe2, 0x3a, 0x20, 0xe1, 0x0b, 0x20, 0xe4, 0x0b, 0x20, 0xe5, 0x14, 0x60, 0x09, 0x02, 0x13} }, +{ 0x1392, 16, {0x43, 0x02, 0x14, 0x65, 0x02, 0x13, 0x43, 0x43, 0x82, 0x04, 0xe0, 0xf5, 0x36, 0x02, 0x13, 0x43} }, +{ 0x13a2, 16, {0x43, 0x82, 0x04, 0xe0, 0x43, 0x2c, 0x01, 0x02, 0x13, 0x43, 0x53, 0x82, 0xf8, 0x43, 0x82, 0x05} }, +{ 0x13b2, 16, {0xe0, 0x42, 0x32, 0x53, 0x82, 0xfb, 0xe0, 0x54, 0xfb, 0xf0, 0x02, 0x13, 0x43, 0x30, 0xe1, 0x02} }, +{ 0x13c2, 16, {0x80, 0xe8, 0xf5, 0x85, 0xe5, 0x3b, 0x30, 0xe0, 0x0a, 0x53, 0x82, 0xf8, 0x43, 0x82, 0x04, 0xe0} }, +{ 0x13d2, 16, {0x54, 0xfe, 0xf0, 0xe5, 0x85, 0x20, 0xe3, 0x56, 0x90, 0x20, 0x50, 0x74, 0x00, 0xf0, 0x90, 0x20} }, +{ 0x13e2, 16, {0x58, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xe2, 0xe0, 0x44, 0x40, 0xf0, 0x90, 0x7f, 0xe3, 0x05, 0x86} }, +{ 0x13f2, 16, {0x90, 0x7e, 0x80, 0x05, 0x86, 0xe5, 0x85, 0xf0, 0xa3, 0xe5, 0x84, 0xf0, 0x05, 0x86, 0x90, 0x7f} }, +{ 0x1402, 16, {0xe5, 0xe5, 0x3c, 0xfd, 0x03, 0x03, 0x03, 0xfe, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0} }, +{ 0x1412, 16, {0xde, 0xf6, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00, 0xf0, 0x90} }, +{ 0x1422, 16, {0x7f, 0xb7, 0xed, 0xf0, 0x90, 0x20, 0x01, 0xe0, 0x54, 0xfe, 0xf0, 0x02, 0x13, 0x43, 0x7f, 0x40} }, +{ 0x1432, 16, {0x90, 0x7e, 0x80, 0x05, 0x86, 0x90, 0x20, 0x00, 0xe5, 0x84, 0xfe, 0x24, 0x05, 0xfd, 0x8d, 0x84} }, +{ 0x1442, 16, {0xe0, 0x8e, 0x84, 0x30, 0xe0, 0x09, 0xe0, 0x05, 0x86, 0xf0, 0xa3, 0x05, 0x86, 0xdf, 0xef, 0x05} }, +{ 0x1452, 16, {0x86, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0x7f, 0xb7, 0xf0, 0x05, 0x86, 0xa3, 0xe0, 0x54, 0xfe, 0xf0} }, +{ 0x1462, 16, {0x02, 0x13, 0x43, 0x53, 0x2c, 0xfa, 0xe5, 0x22, 0x60, 0x08, 0x75, 0x22, 0x00, 0xd2, 0xe7, 0xfe} }, +{ 0x1472, 16, {0x80, 0x0a, 0x90, 0x7f, 0xc7, 0xe0, 0xfe, 0x70, 0x03, 0x02, 0x14, 0xff, 0x90, 0x20, 0x50, 0x74} }, +{ 0x1482, 16, {0x00, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xe2, 0xe0, 0x44, 0x40, 0xf0, 0x90} }, +{ 0x1492, 16, {0x7f, 0xe3, 0x05, 0x86, 0x90, 0x7e, 0x40, 0x05, 0x86, 0xe5, 0x85, 0xf0, 0xa3, 0xe5, 0x84, 0xf0} }, +{ 0x14a2, 16, {0x05, 0x86, 0x90, 0x7f, 0xe5, 0xee, 0x30, 0xe7, 0x08, 0x05, 0x86, 0xe0, 0x24, 0x38, 0xf0, 0x05} }, +{ 0x14b2, 16, {0x86, 0xee, 0x54, 0x7f, 0xfe, 0x54, 0x07, 0xfb, 0xee, 0x54, 0x78, 0x60, 0x30, 0x03, 0x03, 0x03} }, +{ 0x14c2, 16, {0x30, 0xe3, 0x04, 0x74, 0x07, 0x7b, 0x08, 0xfd, 0xfc, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0} }, +{ 0x14d2, 16, {0xe0, 0xdd, 0xf6, 0xeb, 0xfe, 0x60, 0x19, 0xec, 0x64, 0x07, 0x70, 0x11, 0x8b, 0x22, 0x90, 0x7f} }, +{ 0x14e2, 16, {0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00, 0xf0, 0x80, 0x1b, 0xe0, 0xde, 0xfd} }, +{ 0x14f2, 16, {0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00, 0xf0, 0x90, 0x20, 0x01} }, +{ 0x1502, 16, {0xe0, 0x54, 0xfd, 0xf0, 0x90, 0x7f, 0xc7, 0xf0, 0x02, 0x13, 0x43, 0x90, 0x20, 0x0a, 0xe0, 0x54} }, +{ 0x1512, 16, {0x3f, 0x20, 0xe2, 0x3a, 0x20, 0xe1, 0x0b, 0x20, 0xe4, 0x0b, 0x20, 0xe5, 0x14, 0x60, 0x09, 0x02} }, +{ 0x1522, 16, {0x13, 0x43, 0x02, 0x15, 0xf6, 0x02, 0x13, 0x43, 0x43, 0x82, 0x04, 0xe0, 0xf5, 0x37, 0x02, 0x13} }, +{ 0x1532, 16, {0x43, 0x43, 0x82, 0x04, 0xe0, 0x43, 0x2d, 0x01, 0x02, 0x13, 0x43, 0x53, 0x82, 0xf8, 0x43, 0x82} }, +{ 0x1542, 16, {0x05, 0xe0, 0x42, 0x33, 0x53, 0x82, 0xfb, 0xe0, 0x54, 0xfb, 0xf0, 0x02, 0x13, 0x43, 0x30, 0xe1} }, +{ 0x1552, 16, {0x02, 0x80, 0xe8, 0xf5, 0x85, 0xe5, 0x3b, 0x30, 0xe1, 0x0a, 0x53, 0x82, 0xf8, 0x43, 0x82, 0x04} }, +{ 0x1562, 16, {0xe0, 0x54, 0xfe, 0xf0, 0xe5, 0x85, 0x20, 0xe3, 0x56, 0x90, 0x20, 0x50, 0x74, 0x01, 0xf0, 0x90} }, +{ 0x1572, 16, {0x20, 0x58, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xe2, 0xe0, 0x44, 0x40, 0xf0, 0x90, 0x7f, 0xe3, 0x05} }, +{ 0x1582, 16, {0x86, 0x90, 0x7e, 0x00, 0x05, 0x86, 0xe5, 0x85, 0xf0, 0xa3, 0xe5, 0x84, 0xf0, 0x05, 0x86, 0x90} }, +{ 0x1592, 16, {0x7f, 0xe5, 0xe5, 0x3d, 0xfd, 0x03, 0x03, 0x03, 0xfe, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0} }, +{ 0x15a2, 16, {0xf0, 0xde, 0xf6, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00, 0xf0} }, +{ 0x15b2, 16, {0x90, 0x7f, 0xb9, 0xed, 0xf0, 0x90, 0x20, 0x09, 0xe0, 0x54, 0xfe, 0xf0, 0x02, 0x13, 0x43, 0x7f} }, +{ 0x15c2, 16, {0x40, 0x90, 0x7e, 0x00, 0x05, 0x86, 0x90, 0x20, 0x08, 0xe5, 0x84, 0xfe, 0x24, 0x05, 0xfd, 0x8d} }, +{ 0x15d2, 16, {0x84, 0xe0, 0x8e, 0x84, 0x30, 0xe0, 0x09, 0xe0, 0x05, 0x86, 0xf0, 0xa3, 0x05, 0x86, 0xdf, 0xef} }, +{ 0x15e2, 16, {0x05, 0x86, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0x7f, 0xb9, 0xf0, 0x05, 0x86, 0xa3, 0xe0, 0x54, 0xfe} }, +{ 0x15f2, 16, {0xf0, 0x02, 0x13, 0x43, 0x53, 0x2d, 0xfa, 0xe5, 0x23, 0x60, 0x08, 0x75, 0x23, 0x00, 0xd2, 0xe7} }, +{ 0x1602, 16, {0xfe, 0x80, 0x0a, 0x90, 0x7f, 0xc9, 0xe0, 0xfe, 0x70, 0x03, 0x02, 0x16, 0x90, 0x90, 0x20, 0x50} }, +{ 0x1612, 16, {0x74, 0x01, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xe2, 0xe0, 0x44, 0x40, 0xf0} }, +{ 0x1622, 16, {0x90, 0x7f, 0xe3, 0x05, 0x86, 0x90, 0x7d, 0xc0, 0x05, 0x86, 0xe5, 0x85, 0xf0, 0xa3, 0xe5, 0x84} }, +{ 0x1632, 16, {0xf0, 0x05, 0x86, 0x90, 0x7f, 0xe5, 0xee, 0x30, 0xe7, 0x08, 0x05, 0x86, 0xe0, 0x24, 0x38, 0xf0} }, +{ 0x1642, 16, {0x05, 0x86, 0xee, 0x54, 0x7f, 0xfe, 0x54, 0x07, 0xfb, 0xee, 0x54, 0x78, 0x60, 0x30, 0x03, 0x03} }, +{ 0x1652, 16, {0x03, 0x30, 0xe3, 0x04, 0x74, 0x07, 0x7b, 0x08, 0xfd, 0xfc, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0} }, +{ 0x1662, 16, {0xe0, 0xe0, 0xdd, 0xf6, 0xeb, 0xfe, 0x60, 0x19, 0xec, 0x64, 0x07, 0x70, 0x11, 0x8b, 0x23, 0x90} }, +{ 0x1672, 16, {0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00, 0xf0, 0x80, 0x1b, 0xe0, 0xde} }, +{ 0x1682, 14, {0xfd, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00, 0xf0} }, +{ 0x1690, 16, {0x90, 0x20, 0x09, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0x7f, 0xc9, 0xf0, 0x02, 0x13, 0x43, 0x90, 0x20} }, +{ 0x16a0, 16, {0x12, 0xe0, 0x54, 0x3f, 0x20, 0xe2, 0x3a, 0x20, 0xe1, 0x0b, 0x20, 0xe4, 0x0b, 0x20, 0xe5, 0x14} }, +{ 0x16b0, 16, {0x60, 0x09, 0x02, 0x13, 0x43, 0x02, 0x17, 0x87, 0x02, 0x13, 0x43, 0x43, 0x82, 0x04, 0xe0, 0xf5} }, +{ 0x16c0, 16, {0x38, 0x02, 0x13, 0x43, 0x43, 0x82, 0x04, 0xe0, 0x43, 0x2e, 0x01, 0x02, 0x13, 0x43, 0x53, 0x82} }, +{ 0x16d0, 16, {0xf8, 0x43, 0x82, 0x05, 0xe0, 0x42, 0x34, 0x53, 0x82, 0xfb, 0xe0, 0x54, 0xfb, 0xf0, 0x02, 0x13} }, +{ 0x16e0, 16, {0x43, 0x30, 0xe1, 0x02, 0x80, 0xe8, 0xf5, 0x85, 0xe5, 0x3b, 0x30, 0xe2, 0x0a, 0x53, 0x82, 0xf8} }, +{ 0x16f0, 16, {0x43, 0x82, 0x04, 0xe0, 0x54, 0xfe, 0xf0, 0xe5, 0x85, 0x20, 0xe3, 0x56, 0x90, 0x20, 0x50, 0x74} }, +{ 0x1700, 16, {0x02, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xe2, 0xe0, 0x44, 0x40, 0xf0, 0x90} }, +{ 0x1710, 16, {0x7f, 0xe3, 0x05, 0x86, 0x90, 0x7d, 0x80, 0x05, 0x86, 0xe5, 0x85, 0xf0, 0xa3, 0xe5, 0x84, 0xf0} }, +{ 0x1720, 16, {0x05, 0x86, 0x90, 0x7f, 0xe5, 0xe5, 0x3e, 0xfd, 0x03, 0x03, 0x03, 0xfe, 0xf0, 0xf0, 0xf0, 0xf0} }, +{ 0x1730, 16, {0xf0, 0xf0, 0xf0, 0xf0, 0xde, 0xf6, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58} }, +{ 0x1740, 16, {0x74, 0x00, 0xf0, 0x90, 0x7f, 0xbb, 0xed, 0xf0, 0x90, 0x20, 0x11, 0xe0, 0x54, 0xfe, 0xf0, 0x02} }, +{ 0x1750, 16, {0x13, 0x43, 0x7f, 0x40, 0x90, 0x7d, 0x80, 0x05, 0x86, 0x90, 0x20, 0x10, 0xe5, 0x84, 0xfe, 0x24} }, +{ 0x1760, 16, {0x05, 0xfd, 0x8d, 0x84, 0xe0, 0x8e, 0x84, 0x30, 0xe0, 0x09, 0xe0, 0x05, 0x86, 0xf0, 0xa3, 0x05} }, +{ 0x1770, 16, {0x86, 0xdf, 0xef, 0x05, 0x86, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0x7f, 0xbb, 0xf0, 0x05, 0x86, 0xa3} }, +{ 0x1780, 16, {0xe0, 0x54, 0xfe, 0xf0, 0x02, 0x13, 0x43, 0x53, 0x2e, 0xfa, 0xe5, 0x24, 0x60, 0x08, 0x75, 0x24} }, +{ 0x1790, 16, {0x00, 0xd2, 0xe7, 0xfe, 0x80, 0x0a, 0x90, 0x7f, 0xcb, 0xe0, 0xfe, 0x70, 0x03, 0x02, 0x18, 0x21} }, +{ 0x17a0, 16, {0x90, 0x20, 0x50, 0x74, 0x02, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xe2, 0xe0} }, +{ 0x17b0, 16, {0x44, 0x40, 0xf0, 0x90, 0x7f, 0xe3, 0x05, 0x86, 0x90, 0x7d, 0x40, 0x05, 0x86, 0xe5, 0x85, 0xf0} }, +{ 0x17c0, 16, {0xa3, 0xe5, 0x84, 0xf0, 0x05, 0x86, 0x90, 0x7f, 0xe5, 0xee, 0x30, 0xe7, 0x08, 0x05, 0x86, 0xe0} }, +{ 0x17d0, 16, {0x24, 0x38, 0xf0, 0x05, 0x86, 0xee, 0x54, 0x7f, 0xfe, 0x54, 0x07, 0xfb, 0xee, 0x54, 0x78, 0x60} }, +{ 0x17e0, 16, {0x30, 0x03, 0x03, 0x03, 0x30, 0xe3, 0x04, 0x74, 0x07, 0x7b, 0x08, 0xfd, 0xfc, 0xe0, 0xe0, 0xe0} }, +{ 0x17f0, 16, {0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xdd, 0xf6, 0xeb, 0xfe, 0x60, 0x19, 0xec, 0x64, 0x07, 0x70, 0x11} }, +{ 0x1800, 16, {0x8b, 0x24, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00, 0xf0, 0x80} }, +{ 0x1810, 16, {0x1b, 0xe0, 0xde, 0xfd, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00} }, +{ 0x1820, 16, {0xf0, 0x90, 0x20, 0x11, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0x7f, 0xcb, 0xf0, 0x02, 0x13, 0x43, 0x90} }, +{ 0x1830, 16, {0x20, 0x1a, 0xe0, 0x54, 0x3f, 0x20, 0xe2, 0x3a, 0x20, 0xe1, 0x0b, 0x20, 0xe4, 0x0b, 0x20, 0xe5} }, +{ 0x1840, 16, {0x14, 0x60, 0x09, 0x02, 0x13, 0x43, 0x02, 0x19, 0x18, 0x02, 0x13, 0x43, 0x43, 0x82, 0x04, 0xe0} }, +{ 0x1850, 16, {0xf5, 0x39, 0x02, 0x13, 0x43, 0x43, 0x82, 0x04, 0xe0, 0x43, 0x2f, 0x01, 0x02, 0x13, 0x43, 0x53} }, +{ 0x1860, 16, {0x82, 0xf8, 0x43, 0x82, 0x05, 0xe0, 0x42, 0x35, 0x53, 0x82, 0xfb, 0xe0, 0x54, 0xfb, 0xf0, 0x02} }, +{ 0x1870, 16, {0x13, 0x43, 0x30, 0xe1, 0x02, 0x80, 0xe8, 0xf5, 0x85, 0xe5, 0x3b, 0x30, 0xe3, 0x0a, 0x53, 0x82} }, +{ 0x1880, 16, {0xf8, 0x43, 0x82, 0x04, 0xe0, 0x54, 0xfe, 0xf0, 0xe5, 0x85, 0x20, 0xe3, 0x56, 0x90, 0x20, 0x50} }, +{ 0x1890, 16, {0x74, 0x03, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xe2, 0xe0, 0x44, 0x40, 0xf0} }, +{ 0x18a0, 16, {0x90, 0x7f, 0xe3, 0x05, 0x86, 0x90, 0x7d, 0x00, 0x05, 0x86, 0xe5, 0x85, 0xf0, 0xa3, 0xe5, 0x84} }, +{ 0x18b0, 16, {0xf0, 0x05, 0x86, 0x90, 0x7f, 0xe5, 0xe5, 0x3f, 0xfd, 0x03, 0x03, 0x03, 0xfe, 0xf0, 0xf0, 0xf0} }, +{ 0x18c0, 16, {0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xde, 0xf6, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20} }, +{ 0x18d0, 16, {0x58, 0x74, 0x00, 0xf0, 0x90, 0x7f, 0xbd, 0xed, 0xf0, 0x90, 0x20, 0x19, 0xe0, 0x54, 0xfe, 0xf0} }, +{ 0x18e0, 16, {0x02, 0x13, 0x43, 0x7f, 0x40, 0x90, 0x7d, 0x00, 0x05, 0x86, 0x90, 0x20, 0x18, 0xe5, 0x84, 0xfe} }, +{ 0x18f0, 16, {0x24, 0x05, 0xfd, 0x8d, 0x84, 0xe0, 0x8e, 0x84, 0x30, 0xe0, 0x09, 0xe0, 0x05, 0x86, 0xf0, 0xa3} }, +{ 0x1900, 16, {0x05, 0x86, 0xdf, 0xef, 0x05, 0x86, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0x7f, 0xbd, 0xf0, 0x05, 0x86} }, +{ 0x1910, 16, {0xa3, 0xe0, 0x54, 0xfe, 0xf0, 0x02, 0x13, 0x43, 0x53, 0x2f, 0xfa, 0xe5, 0x25, 0x60, 0x08, 0x75} }, +{ 0x1920, 16, {0x25, 0x00, 0xd2, 0xe7, 0xfe, 0x80, 0x0a, 0x90, 0x7f, 0xcd, 0xe0, 0xfe, 0x70, 0x03, 0x02, 0x19} }, +{ 0x1930, 16, {0xb2, 0x90, 0x20, 0x50, 0x74, 0x03, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xe2} }, +{ 0x1940, 16, {0xe0, 0x44, 0x40, 0xf0, 0x90, 0x7f, 0xe3, 0x05, 0x86, 0x90, 0x7c, 0xc0, 0x05, 0x86, 0xe5, 0x85} }, +{ 0x1950, 16, {0xf0, 0xa3, 0xe5, 0x84, 0xf0, 0x05, 0x86, 0x90, 0x7f, 0xe5, 0xee, 0x30, 0xe7, 0x08, 0x05, 0x86} }, +{ 0x1960, 16, {0xe0, 0x24, 0x38, 0xf0, 0x05, 0x86, 0xee, 0x54, 0x7f, 0xfe, 0x54, 0x07, 0xfb, 0xee, 0x54, 0x78} }, +{ 0x1970, 16, {0x60, 0x30, 0x03, 0x03, 0x03, 0x30, 0xe3, 0x04, 0x74, 0x07, 0x7b, 0x08, 0xfd, 0xfc, 0xe0, 0xe0} }, +{ 0x1980, 16, {0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xdd, 0xf6, 0xeb, 0xfe, 0x60, 0x19, 0xec, 0x64, 0x07, 0x70} }, +{ 0x1990, 16, {0x11, 0x8b, 0x25, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00, 0xf0} }, +{ 0x19a0, 16, {0x80, 0x1b, 0xe0, 0xde, 0xfd, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74} }, +{ 0x19b0, 16, {0x00, 0xf0, 0x90, 0x20, 0x19, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0x7f, 0xcd, 0xf0, 0x02, 0x13, 0x43} }, +{ 0x19c0, 1, {0x32} }, +{ 0x19c1, 4, {0xad, 0x07, 0xac, 0x06} }, +{ 0x19c5, 16, {0x79, 0x06, 0xed, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x3c, 0xf5, 0x83, 0xe0, 0xfa, 0xa3, 0xe0, 0xfb} }, +{ 0x19d5, 16, {0x4a, 0x70, 0x03, 0x02, 0x1b, 0x09, 0xe9, 0xb4, 0x07, 0x00, 0x40, 0x03, 0x02, 0x1a, 0xdb, 0x90} }, +{ 0x19e5, 16, {0x19, 0xeb, 0xf8, 0x28, 0x28, 0x73, 0x02, 0x1a, 0xb9, 0x02, 0x1a, 0x71, 0x02, 0x1a, 0x5a, 0x02} }, +{ 0x19f5, 16, {0x1a, 0x40, 0x02, 0x1a, 0x2f, 0x02, 0x1a, 0x1a, 0x02, 0x1a, 0x00, 0x90, 0x7f, 0xa5, 0xe0, 0x44} }, +{ 0x1a05, 16, {0x80, 0xf0, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xe0, 0xff, 0x25, 0xe0, 0x44, 0xa0, 0x90, 0x7f, 0xa6} }, +{ 0x1a15, 16, {0xf0, 0x19, 0x02, 0x1a, 0xdb, 0x19, 0x8d, 0x82, 0x8c, 0x83, 0xe0, 0xc3, 0x94, 0x20, 0x40, 0x0a} }, +{ 0x1a25, 16, {0xa3, 0xa3, 0xe0, 0x90, 0x7f, 0xa6, 0xf0, 0x02, 0x1a, 0xdb, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3} }, +{ 0x1a35, 16, {0xe0, 0xa3, 0xe0, 0x90, 0x7f, 0xa6, 0xf0, 0x19, 0x02, 0x1a, 0xdb, 0x90, 0x7f, 0xa5, 0xe0, 0x44} }, +{ 0x1a45, 16, {0x80, 0xf0, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xe0, 0xff, 0x25, 0xe0, 0x44, 0xa1, 0x90, 0x7f, 0xa6} }, +{ 0x1a55, 16, {0xf0, 0x19, 0x02, 0x1a, 0xdb, 0xeb, 0x64, 0x01, 0x4a, 0x70, 0x08, 0x90, 0x7f, 0xa5, 0xe0, 0x44} }, +{ 0x1a65, 16, {0x20, 0xf0, 0x19, 0x90, 0x7f, 0xa6, 0xe0, 0xf5, 0x54, 0x19, 0x80, 0x6a, 0xed, 0x24, 0x04, 0xf5} }, +{ 0x1a75, 16, {0x82, 0xe4, 0x3c, 0xf5, 0x83, 0xe0, 0xfe, 0xa3, 0xe0, 0x64, 0x02, 0x4e, 0x70, 0x08, 0x90, 0x7f} }, +{ 0x1a85, 16, {0xa5, 0xe0, 0x44, 0x20, 0xf0, 0x19, 0x90, 0x7f, 0xa6, 0xe0, 0xff, 0xed, 0x24, 0x06, 0xf5, 0x82} }, +{ 0x1a95, 16, {0xe4, 0x3c, 0xf5, 0x83, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9b, 0xce, 0x85, 0xf0, 0x82, 0xf5, 0x83} }, +{ 0x1aa5, 16, {0xef, 0xf0, 0xed, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x3c, 0xf5, 0x83, 0x74, 0xff, 0xf5, 0xf0, 0x12} }, +{ 0x1ab5, 16, {0x9b, 0xb8, 0x80, 0x22, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x90, 0x7f, 0xa6, 0xe0, 0xff} }, +{ 0x1ac5, 16, {0xed, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x3c, 0xf5, 0x83, 0xe0, 0xfa, 0xa3, 0xe0, 0xf5, 0x82, 0x8a} }, +{ 0x1ad5, 16, {0x83, 0xef, 0xf0, 0x7f, 0x08, 0x22, 0x90, 0x7f, 0xa5, 0xe0, 0xf5, 0x54, 0x30, 0xe0, 0xf7, 0x30} }, +{ 0x1ae5, 16, {0xe2, 0x07, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x06, 0x22, 0xe9, 0xd3, 0x94, 0x02, 0x50, 0x03, 0x02} }, +{ 0x1af5, 16, {0x19, 0xc7, 0xe5, 0x54, 0x30, 0xe1, 0x03, 0x02, 0x19, 0xc7, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40} }, +{ 0x1b05, 6, {0xf0, 0x7f, 0x07, 0x22, 0x7f, 0x08} }, +{ 0x1b0b, 1, {0x22} }, +{ 0x1b0c, 16, {0x7f, 0x05, 0x7e, 0x00, 0x12, 0x09, 0x23, 0x7f, 0x02, 0x7d, 0xff, 0x12, 0x81, 0xe0, 0x7f, 0x05} }, +{ 0x1b1c, 13, {0x7e, 0x00, 0x12, 0x09, 0x23, 0x7f, 0x03, 0x7d, 0xff, 0x12, 0x81, 0xe0, 0x22} }, +{ 0x1b29, 16, {0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0} }, +{ 0x8000, 4, {0x8e, 0x54, 0x8f, 0x55} }, +{ 0x8004, 16, {0x75, 0x56, 0x03, 0xe5, 0x55, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x54, 0xf5, 0x83, 0xe0, 0xfe} }, +{ 0x8014, 16, {0xa3, 0xe0, 0x4e, 0x70, 0x03, 0x02, 0x81, 0x0e, 0xe5, 0x56, 0x60, 0x4e, 0x14, 0x60, 0x38, 0x14} }, +{ 0x8024, 16, {0x60, 0x20, 0x14, 0x60, 0x03, 0x02, 0x80, 0xb2, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0, 0x85} }, +{ 0x8034, 16, {0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0xe0, 0xff, 0x25, 0xe0, 0x44, 0xa0, 0x90, 0x7f, 0xa6, 0xf0} }, +{ 0x8044, 16, {0x80, 0x6c, 0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xe0, 0xc3, 0x94, 0x20, 0x40, 0x09, 0xa3, 0xa3} }, +{ 0x8054, 16, {0xe0, 0x90, 0x7f, 0xa6, 0xf0, 0x80, 0x57, 0x15, 0x56, 0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3} }, +{ 0x8064, 16, {0xa3, 0xe0, 0xa3, 0xe0, 0x90, 0x7f, 0xa6, 0xf0, 0x80, 0x44, 0xe5, 0x55, 0x24, 0x06, 0xf5, 0x82} }, +{ 0x8074, 16, {0xe4, 0x35, 0x54, 0xf5, 0x83, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9b, 0xce, 0x85, 0xf0, 0x82, 0xf5} }, +{ 0x8084, 16, {0x83, 0xe0, 0x90, 0x7f, 0xa6, 0xf0, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0xe5, 0x55, 0x24} }, +{ 0x8094, 16, {0x04, 0xf5, 0x82, 0xe4, 0x35, 0x54, 0xf5, 0x83, 0x74, 0xff, 0xf5, 0xf0, 0x12, 0x9b, 0xb8, 0x85} }, +{ 0x80a4, 16, {0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0xa3, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9b, 0xb8, 0x90, 0x7f} }, +{ 0x80b4, 16, {0xa5, 0xe0, 0xf5, 0x57, 0x30, 0xe0, 0xf7, 0x30, 0xe2, 0x07, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x06} }, +{ 0x80c4, 16, {0x22, 0xe5, 0x57, 0x20, 0xe1, 0x0a, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x07, 0x22} }, +{ 0x80d4, 16, {0xe5, 0x56, 0x70, 0x31, 0x7f, 0x01, 0x7e, 0x00, 0x12, 0x09, 0x23, 0x90, 0x7f, 0xa5, 0xe0, 0x44} }, +{ 0x80e4, 16, {0x80, 0xf0, 0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0xe0, 0xff, 0x25, 0xe0, 0x44, 0xa0, 0x90} }, +{ 0x80f4, 16, {0x7f, 0xa6, 0xf0, 0x90, 0x7f, 0xa5, 0xe0, 0xf5, 0x57, 0x30, 0xe0, 0xf7, 0x30, 0xe1, 0xd5, 0x75} }, +{ 0x8104, 12, {0x56, 0x03, 0x02, 0x80, 0x07, 0x15, 0x56, 0x02, 0x80, 0x07, 0x7f, 0x08} }, +{ 0x8110, 1, {0x22} }, +{ 0x8111, 2, {0xac, 0x07} }, +{ 0x8113, 16, {0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0, 0xec, 0x25, 0xe0, 0x44, 0x41, 0x90, 0x7f, 0xa6, 0xf0} }, +{ 0x8123, 16, {0x7b, 0x3c, 0xaf, 0x03, 0x1b, 0xef, 0x70, 0x16, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x90} }, +{ 0x8133, 16, {0x7f, 0xa6, 0xe0, 0xfd, 0x7d, 0x32, 0xaf, 0x05, 0x1d, 0xef, 0x60, 0xd4, 0x80, 0xf8, 0x90, 0x7f} }, +{ 0x8143, 16, {0xa5, 0xe0, 0xfd, 0x30, 0xe0, 0xdc, 0x20, 0xe1, 0x09, 0xe0, 0x44, 0x40, 0xf0, 0x7e, 0xff, 0x7f} }, +{ 0x8153, 16, {0xf9, 0x22, 0xed, 0x30, 0xe2, 0x0c, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x7e, 0xff, 0x7f} }, +{ 0x8163, 16, {0xfa, 0x22, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0x7f, 0xa6, 0xe0, 0xfd, 0x7b, 0x1e} }, +{ 0x8173, 16, {0xaf, 0x03, 0x1b, 0xef, 0x70, 0x16, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x90, 0x7f, 0xa6} }, +{ 0x8183, 16, {0xe0, 0xfd, 0x7d, 0x32, 0xaf, 0x05, 0x1d, 0xef, 0x60, 0x86, 0x80, 0xf8, 0x90, 0x7f, 0xa5, 0xe0} }, +{ 0x8193, 16, {0xfd, 0x20, 0xe0, 0xdc, 0x7b, 0x3c, 0xaf, 0x03, 0x1b, 0xef, 0x70, 0x19, 0x90, 0x7f, 0xa5, 0xe0} }, +{ 0x81a3, 16, {0x44, 0x40, 0xf0, 0x90, 0x7f, 0xa6, 0xe0, 0xfd, 0x7d, 0x32, 0xaf, 0x05, 0x1d, 0xef, 0x70, 0x03} }, +{ 0x81b3, 16, {0x02, 0x81, 0x13, 0x80, 0xf5, 0x90, 0x7f, 0xa5, 0xe0, 0xfd, 0x30, 0xe0, 0xd9, 0x30, 0xe2, 0x09} }, +{ 0x81c3, 16, {0xe0, 0x44, 0x40, 0xf0, 0x7e, 0xff, 0x7f, 0xfa, 0x22, 0xc2, 0xaf, 0x90, 0x7f, 0xa5, 0xe0, 0x44} }, +{ 0x81d3, 12, {0x40, 0xf0, 0x90, 0x7f, 0xa6, 0xe0, 0xfd, 0xd2, 0xaf, 0xff, 0x7e, 0x00} }, +{ 0x81df, 1, {0x22} }, +{ 0x81e0, 2, {0xae, 0x07} }, +{ 0x81e2, 16, {0x7c, 0x02, 0xec, 0x14, 0x60, 0x15, 0x14, 0x70, 0x1e, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0} }, +{ 0x81f2, 16, {0xee, 0x25, 0xe0, 0x44, 0x40, 0x90, 0x7f, 0xa6, 0xf0, 0x80, 0x0c, 0x90, 0x7f, 0xa6, 0xed, 0xf0} }, +{ 0x8202, 16, {0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x90, 0x7f, 0xa5, 0xe0, 0xfb, 0x30, 0xe0, 0xf8, 0xbc} }, +{ 0x8212, 16, {0x02, 0x0a, 0x20, 0xe1, 0x07, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x07, 0x22, 0xeb, 0x30, 0xe2, 0x0a} }, +{ 0x8222, 14, {0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x06, 0x22, 0xdc, 0xb6, 0x7f, 0x08} }, +{ 0x8230, 1, {0x22} }, +{ 0x8231, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc2, 0xa9, 0x90, 0x03, 0x00, 0x74, 0x19, 0xf0, 0xd2, 0xa9} }, +{ 0x8241, 15, {0x53, 0x91, 0x7f, 0x90, 0x01, 0xc4, 0xe4, 0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x8250, 16, {0xef, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xab, 0x82, 0xfa, 0xf5} }, +{ 0x8260, 16, {0x83, 0xa3, 0xe4, 0xf0, 0x8b, 0x82, 0x8a, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xf5, 0x5e, 0x74, 0xbf} }, +{ 0x8270, 16, {0xf0, 0x8b, 0x82, 0x8a, 0x83, 0xa3, 0xa3, 0xe0, 0x44, 0x10, 0xf0, 0x8b, 0x82, 0x8a, 0x83, 0xa3} }, +{ 0x8280, 16, {0xa3, 0xa3, 0xe4, 0xf0, 0x8b, 0x82, 0x8a, 0x83, 0xa3, 0xf0, 0xf9, 0xed, 0x60, 0x1d, 0x74, 0x01} }, +{ 0x8290, 16, {0x7e, 0x00, 0xa8, 0x07, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff, 0xe4} }, +{ 0x82a0, 16, {0xef, 0x55, 0x3b, 0x60, 0x04, 0x79, 0x09, 0x80, 0x02, 0x79, 0x0d, 0x8b, 0x82, 0x8a, 0x83, 0xa3} }, +{ 0x82b0, 16, {0xa3, 0xa3, 0x74, 0xbf, 0xf0, 0x8b, 0x82, 0x8a, 0x83, 0xa3, 0xa3, 0xe0, 0x54, 0xef, 0xf0, 0x8b} }, +{ 0x82c0, 16, {0x82, 0x8a, 0x83, 0xa3, 0xa3, 0xa3, 0xe5, 0x5e, 0xf0, 0xae, 0x02, 0xaf, 0x03, 0x8f, 0x82, 0x8e} }, +{ 0x82d0, 4, {0x83, 0xa3, 0xe9, 0xf0} }, +{ 0x82d4, 1, {0x22} }, +{ 0x82d5, 4, {0x8f, 0x5e, 0x8d, 0x5f} }, +{ 0x82d9, 16, {0xe4, 0xf5, 0x60, 0x74, 0x3c, 0x2f, 0xf8, 0x76, 0x08, 0xe5, 0x5e, 0x75, 0xf0, 0x0d, 0xa4, 0x24} }, +{ 0x82e9, 16, {0x02, 0xf5, 0x82, 0xe4, 0x34, 0x03, 0xf5, 0x83, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe} }, +{ 0x82f9, 16, {0xa3, 0xe0, 0xff, 0x7b, 0x80, 0x7a, 0x25, 0x79, 0x00, 0x78, 0x00, 0xc3, 0x12, 0x9c, 0xea, 0x50} }, +{ 0x8309, 16, {0x3c, 0xe5, 0x5e, 0x75, 0xf0, 0x0d, 0xa4, 0x24, 0x02, 0xf5, 0x82, 0xe4, 0x34, 0x03, 0xf5, 0x83} }, +{ 0x8319, 16, {0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x7b, 0x00, 0x7a, 0x96, 0x78} }, +{ 0x8329, 16, {0x00, 0xc3, 0x12, 0x9c, 0xea, 0x40, 0x0c, 0x75, 0x60, 0x40, 0x74, 0x3c, 0x25, 0x5e, 0xf8, 0x76} }, +{ 0x8339, 16, {0x10, 0x80, 0x0a, 0x75, 0x60, 0x80, 0x74, 0x3c, 0x25, 0x5e, 0xf8, 0x76, 0x38, 0xe5, 0x60, 0x45} }, +{ 0x8349, 16, {0x5f, 0x44, 0x01, 0xff, 0xe5, 0x5e, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x02, 0xf5, 0x82, 0xe4, 0x34} }, +{ 0x8359, 5, {0x20, 0xf5, 0x83, 0xef, 0xf0} }, +{ 0x835e, 1, {0x22} }, +{ 0x835f, 16, {0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xf5, 0x54, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82} }, +{ 0x836f, 16, {0xe4, 0x34, 0x20, 0xaf, 0x82, 0xf5, 0x55, 0x8f, 0x56, 0xe5, 0x54, 0x25, 0xe0, 0x24, 0xc6, 0xf5} }, +{ 0x837f, 16, {0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe0, 0x20, 0xe1, 0x0f, 0xe5, 0x54, 0x25, 0xe0, 0x24, 0xc7} }, +{ 0x838f, 16, {0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe4, 0xf0, 0x74, 0x22, 0x25, 0x54, 0xf8, 0xe4, 0xf6} }, +{ 0x839f, 16, {0xe5, 0x56, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x55, 0xf5, 0x83, 0xe0, 0x44, 0x03, 0xf0, 0xaf} }, +{ 0x83af, 16, {0x54, 0x7d, 0x06, 0x12, 0x82, 0xd5, 0xaf, 0x54, 0x7d, 0x01, 0x12, 0x82, 0x50, 0x85, 0x56, 0x82} }, +{ 0x83bf, 16, {0x85, 0x55, 0x83, 0xa3, 0xa3, 0xe0, 0x20, 0xe0, 0x22, 0xe0, 0xff, 0xe5, 0x56, 0x24, 0x05, 0xf5} }, +{ 0x83cf, 16, {0x82, 0xe4, 0x35, 0x55, 0xf5, 0x83, 0xe0, 0xe5, 0x56, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x35, 0x55} }, +{ 0x83df, 16, {0xf5, 0x83, 0xe0, 0xff, 0xaf, 0x54, 0x7d, 0x06, 0x12, 0x82, 0xd5, 0x74, 0xf8, 0x25, 0x54, 0xf5} }, +{ 0x83ef, 16, {0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x54, 0x25, 0xe0, 0xff, 0xc3, 0x74, 0x0c} }, +{ 0x83ff, 16, {0x9f, 0x75, 0xf0, 0x40, 0xa4, 0x24, 0x40, 0xf5, 0x82, 0xe5, 0xf0, 0x34, 0x7b, 0xaf, 0x82, 0xfe} }, +{ 0x840f, 16, {0xe5, 0x54, 0x25, 0xe0, 0x24, 0xef, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xee, 0xf0, 0xa3} }, +{ 0x841f, 16, {0xef, 0xf0, 0xaf, 0x54, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x42} }, +{ 0x842f, 3, {0x30, 0x7f, 0x00} }, +{ 0x8432, 1, {0x22} }, +{ 0x8433, 16, {0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xf5, 0x54, 0xff, 0xe4, 0xfd, 0x12, 0x82, 0x50, 0x74, 0xf8} }, +{ 0x8443, 16, {0x25, 0x54, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x54, 0x75, 0xf0, 0x08} }, +{ 0x8453, 16, {0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xaf, 0x82, 0xf5, 0x56, 0x8f, 0x57, 0xf5, 0x83} }, +{ 0x8463, 16, {0xe5, 0x82, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0xe0, 0x54, 0xfc, 0xf0, 0xaf} }, +{ 0x8473, 16, {0x54, 0x7d, 0x06, 0x12, 0x82, 0xd5, 0xe5, 0x57, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x56, 0xf5} }, +{ 0x8483, 16, {0x83, 0xe0, 0x30, 0xe0, 0x09, 0x85, 0x57, 0x82, 0x85, 0x56, 0x83, 0xe0, 0xf5, 0x55, 0xaf, 0x54} }, +{ 0x8493, 16, {0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xf4, 0x52, 0x30, 0xe5, 0x54} }, +{ 0x84a3, 16, {0x25, 0xe0, 0x24, 0xc6, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe0, 0x20, 0xe1, 0x0f, 0xe5} }, +{ 0x84b3, 16, {0x54, 0x25, 0xe0, 0x24, 0xc7, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe4, 0xf0, 0x7f, 0x00} }, +{ 0x84c3, 1, {0x22} }, +{ 0x84c4, 4, {0x8e, 0x54, 0x8f, 0x55} }, +{ 0x84c8, 16, {0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xf5, 0x56, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x01, 0xf5, 0x82} }, +{ 0x84d8, 16, {0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0, 0x54, 0x03, 0x70, 0x23, 0x85, 0x55, 0x82, 0x8e, 0x83, 0xa3} }, +{ 0x84e8, 16, {0xe0, 0x30, 0xe0, 0x07, 0xaf, 0x56, 0x7d, 0x02, 0x12, 0x82, 0xd5, 0x85, 0x55, 0x82, 0x85, 0x54} }, +{ 0x84f8, 15, {0x83, 0xa3, 0xe0, 0x30, 0xe1, 0x07, 0xaf, 0x56, 0x7d, 0x04, 0x12, 0x82, 0xd5, 0x7f, 0x00} }, +{ 0x8507, 1, {0x22} }, +{ 0x8508, 16, {0x8f, 0x82, 0x8e, 0x83, 0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfd, 0xa3, 0xa3, 0xa3, 0xe0, 0xfc, 0xed} }, +{ 0x8518, 16, {0x6c, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xa3, 0xc0, 0x83, 0xc0} }, +{ 0x8528, 16, {0x82, 0xe0, 0xfd, 0x8f, 0x82, 0x8e, 0x83, 0xe0, 0xfc, 0xed, 0x6c, 0xd0, 0x82, 0xd0, 0x83, 0xf0} }, +{ 0x8538, 16, {0x8f, 0x82, 0x8e, 0x83, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0xe0, 0xfd, 0xec, 0x6d, 0xd0} }, +{ 0x8548, 16, {0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfd, 0x8f} }, +{ 0x8558, 16, {0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xe0, 0xfc, 0xed, 0x6c, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82} }, +{ 0x8568, 16, {0x8e, 0x83, 0xa3, 0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfd, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xe0} }, +{ 0x8578, 16, {0xfc, 0xed, 0x6c, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xc0, 0x83, 0xc0} }, +{ 0x8588, 16, {0x82, 0xe0, 0xfd, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xe0, 0xff, 0xed, 0x6f, 0xd0, 0x82, 0xd0} }, +{ 0x8598, 3, {0x83, 0xf0, 0x22} }, +{ 0x859b, 16, {0x79, 0x0d, 0x8e, 0x54, 0x8f, 0x55, 0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x75, 0xf0, 0x0d, 0xa4, 0x24} }, +{ 0x85ab, 16, {0xf4, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xaf, 0x82, 0xfe, 0xad, 0x01, 0x19, 0xed, 0x60, 0x24, 0x0f} }, +{ 0x85bb, 16, {0xef, 0xac, 0x06, 0x70, 0x01, 0x0e, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xe0, 0xfd, 0x05, 0x55, 0xe5} }, +{ 0x85cb, 16, {0x55, 0xaa, 0x54, 0x70, 0x02, 0x05, 0x54, 0x14, 0xf5, 0x82, 0x8a, 0x83, 0xe0, 0x6d, 0x60, 0xd9} }, +{ 0x85db, 5, {0x7f, 0x01, 0x22, 0x7f, 0x00} }, +{ 0x85e0, 1, {0x22} }, +{ 0x85e1, 4, {0x8e, 0x54, 0x8f, 0x55} }, +{ 0x85e5, 16, {0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xf5, 0x5b, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82} }, +{ 0x85f5, 16, {0xe4, 0x34, 0x20, 0xaf, 0x82, 0xf5, 0x5c, 0x8f, 0x5d, 0xaa, 0x06, 0xa9, 0x55, 0x7b, 0x01, 0xc0} }, +{ 0x8605, 16, {0x03, 0xc0, 0x01, 0xe5, 0x5b, 0x75, 0xf0, 0x0d, 0xa4, 0x24, 0x01, 0xf9, 0x74, 0x03, 0x35, 0xf0} }, +{ 0x8615, 16, {0xa8, 0x01, 0xfc, 0xad, 0x03, 0xd0, 0x01, 0xd0, 0x03, 0x7e, 0x00, 0x7f, 0x0d, 0x12, 0x9b, 0x49} }, +{ 0x8625, 16, {0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe, 0xa3} }, +{ 0x8635, 16, {0xe0, 0xff, 0x7b, 0x08, 0x7a, 0x00, 0x79, 0x00, 0x78, 0x00, 0xd3, 0x12, 0x9c, 0xea, 0x40, 0x10} }, +{ 0x8645, 16, {0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0x12, 0x9d, 0x31, 0x00, 0x00, 0x00, 0x08, 0x80, 0x2e} }, +{ 0x8655, 16, {0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe, 0xa3} }, +{ 0x8665, 16, {0xe0, 0xff, 0x7b, 0x00, 0x7a, 0x08, 0x79, 0x07, 0x78, 0x00, 0xc3, 0x12, 0x9c, 0xea, 0x50, 0x0e} }, +{ 0x8675, 16, {0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0x12, 0x9d, 0x31, 0x00, 0x07, 0x08, 0x00, 0x85, 0x55} }, +{ 0x8685, 16, {0x82, 0x85, 0x54, 0x83, 0xa3, 0xe0, 0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, 0xfa, 0xa3, 0xe0, 0xfb} }, +{ 0x8695, 16, {0x7f, 0x00, 0x7e, 0x50, 0x7d, 0x46, 0x7c, 0x00, 0x12, 0x9c, 0x58, 0x8f, 0x59, 0x8e, 0x58, 0x8d} }, +{ 0x86a5, 16, {0x57, 0x8c, 0x56, 0x7b, 0x0a, 0x7a, 0x00, 0x79, 0x00, 0x78, 0x00, 0x12, 0x9c, 0x58, 0xaf, 0x03} }, +{ 0x86b5, 16, {0x8f, 0x5a, 0xaf, 0x59, 0xae, 0x58, 0xad, 0x57, 0xac, 0x56, 0x7b, 0x0a, 0x7a, 0x00, 0x79, 0x00} }, +{ 0x86c5, 16, {0x78, 0x00, 0x12, 0x9c, 0x58, 0x8f, 0x59, 0x8e, 0x58, 0x8d, 0x57, 0x8c, 0x56, 0xe5, 0x5a, 0xc3} }, +{ 0x86d5, 16, {0x94, 0x05, 0x40, 0x15, 0xe5, 0x59, 0x24, 0x01, 0xf5, 0x59, 0xe4, 0x35, 0x58, 0xf5, 0x58, 0xe4} }, +{ 0x86e5, 16, {0x35, 0x57, 0xf5, 0x57, 0xe4, 0x35, 0x56, 0xf5, 0x56, 0x85, 0x5d, 0x82, 0x85, 0x5c, 0x83, 0xa3} }, +{ 0x86f5, 16, {0xe4, 0xf0, 0x85, 0x5d, 0x82, 0x85, 0x5c, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0x44, 0x80, 0xf0, 0x85} }, +{ 0x8705, 16, {0x5d, 0x82, 0x85, 0x5c, 0x83, 0xe5, 0x59, 0xf0, 0xaf, 0x59, 0xae, 0x58, 0xad, 0x57, 0xac, 0x56} }, +{ 0x8715, 16, {0x78, 0x08, 0x12, 0x9c, 0xfb, 0x85, 0x5d, 0x82, 0x85, 0x5c, 0x83, 0xa3, 0xef, 0xf0, 0x85, 0x5d} }, +{ 0x8725, 16, {0x82, 0x85, 0x5c, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0x54, 0x7f, 0xf0, 0xe4, 0xf5, 0x5a, 0xe5, 0x55} }, +{ 0x8735, 16, {0x24, 0x08, 0xf5, 0x82, 0xe4, 0x35, 0x54, 0xf5, 0x83, 0xe0, 0xff, 0xb4, 0x62, 0x05, 0x43, 0x5a} }, +{ 0x8745, 16, {0x0a, 0x80, 0x10, 0xef, 0xb4, 0x72, 0x05, 0x43, 0x5a, 0x08, 0x80, 0x07, 0xef, 0xb4, 0x74, 0x03} }, +{ 0x8755, 16, {0x43, 0x5a, 0x02, 0xe5, 0x55, 0x24, 0x0b, 0xf5, 0x82, 0xe4, 0x35, 0x54, 0xf5, 0x83, 0xe0, 0xff} }, +{ 0x8765, 16, {0x30, 0xe3, 0x03, 0x43, 0x5a, 0x80, 0xef, 0x30, 0xe7, 0x12, 0x43, 0x5a, 0x40, 0xe5, 0x5d, 0x24} }, +{ 0x8775, 16, {0x04, 0xf5, 0x82, 0xe4, 0x35, 0x5c, 0xf5, 0x83, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x55, 0x24, 0x0b} }, +{ 0x8785, 16, {0xf5, 0x82, 0xe4, 0x35, 0x54, 0xf5, 0x83, 0xe0, 0xff, 0x20, 0xe1, 0x03, 0x30, 0xe4, 0x23, 0xaf} }, +{ 0x8795, 16, {0x5b, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x42, 0x3b, 0xe5, 0x5d} }, +{ 0x87a5, 16, {0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x5c, 0xf5, 0x83, 0xe0, 0x44, 0x01, 0xf0, 0xe4, 0xf5, 0x5a} }, +{ 0x87b5, 16, {0x80, 0x10, 0xaf, 0x5b, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xf4} }, +{ 0x87c5, 16, {0x52, 0x3b, 0x85, 0x5d, 0x82, 0x85, 0x5c, 0x83, 0xa3, 0xa3, 0xa3, 0x74, 0xbf, 0xf0, 0x85, 0x5d} }, +{ 0x87d5, 16, {0x82, 0x85, 0x5c, 0x83, 0xa3, 0xa3, 0xe4, 0xf0, 0xe5, 0x5a, 0xf0, 0xe5, 0x55, 0x24, 0x0a, 0xf5} }, +{ 0x87e5, 16, {0x82, 0xe4, 0x35, 0x54, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x5d, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35} }, +{ 0x87f5, 16, {0x5c, 0xf5, 0x83, 0xef, 0xf0, 0xe5, 0x55, 0x24, 0x0a, 0xf5, 0x82, 0xe4, 0x35, 0x54, 0xf5, 0x83} }, +{ 0x8805, 16, {0xe0, 0xff, 0xe5, 0x5d, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x5c, 0xf5, 0x83, 0xef, 0xf0, 0xe5} }, +{ 0x8815, 16, {0x55, 0x24, 0x09, 0xf5, 0x82, 0xe4, 0x35, 0x54, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x5d, 0x24, 0x06} }, +{ 0x8825, 16, {0xf5, 0x82, 0xe4, 0x35, 0x5c, 0xf5, 0x83, 0xef, 0xf0, 0xe5, 0x55, 0x24, 0x09, 0xf5, 0x82, 0xe4} }, +{ 0x8835, 16, {0x35, 0x54, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x5d, 0x24, 0x07, 0xf5, 0x82, 0xe4, 0x35, 0x5c, 0xf5} }, +{ 0x8845, 16, {0x83, 0xef, 0xf0, 0x85, 0x5d, 0x82, 0x85, 0x5c, 0x83, 0xa3, 0xa3, 0xa3, 0xe4, 0xf0, 0x85, 0x5d} }, +{ 0x8855, 16, {0x82, 0x85, 0x5c, 0x83, 0xa3, 0xa3, 0xf0, 0xaf, 0x5b, 0x7d, 0x06, 0x12, 0x82, 0xd5, 0x75, 0x5a} }, +{ 0x8865, 16, {0x08, 0xe5, 0x55, 0x24, 0x0c, 0xf5, 0x82, 0xe4, 0x35, 0x54, 0xf5, 0x83, 0xe0, 0x60, 0x03, 0x43} }, +{ 0x8875, 16, {0x5a, 0x10, 0xe5, 0x5d, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x5c, 0xf5, 0x83, 0xe0, 0x54, 0x03} }, +{ 0x8885, 16, {0x45, 0x5a, 0xf0, 0xe5, 0x55, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x35, 0x54, 0xf5, 0x83, 0xe0, 0x14} }, +{ 0x8895, 16, {0xff, 0x25, 0xe0, 0x25, 0xe0, 0xff, 0xe5, 0x55, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x54, 0xf5} }, +{ 0x88a5, 16, {0x83, 0xe0, 0x24, 0xfb, 0x4f, 0xf5, 0x5a, 0xe5, 0x55, 0x24, 0x07, 0xf5, 0x82, 0xe4, 0x35, 0x54} }, +{ 0x88b5, 16, {0xf5, 0x83, 0xe0, 0x24, 0xd0, 0x60, 0x15, 0x14, 0x60, 0x17, 0x24, 0xc2, 0x60, 0x09, 0x24, 0x0a} }, +{ 0x88c5, 16, {0x70, 0x12, 0x43, 0x5a, 0x18, 0x80, 0x0d, 0x43, 0x5a, 0x08, 0x80, 0x08, 0x43, 0x5a, 0x38, 0x80} }, +{ 0x88d5, 16, {0x03, 0x43, 0x5a, 0x28, 0x85, 0x5d, 0x82, 0x85, 0x5c, 0x83, 0xa3, 0xa3, 0xa3, 0xe5, 0x5a, 0xf0} }, +{ 0x88e5, 9, {0xaf, 0x5b, 0x7d, 0x01, 0x12, 0x82, 0x50, 0x7f, 0x00} }, +{ 0x88ee, 1, {0x22} }, +{ 0x88ef, 16, {0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xff, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4} }, +{ 0x88ff, 16, {0x34, 0x20, 0xad, 0x82, 0xfc, 0x90, 0x01, 0x2c, 0x74, 0x08, 0xf0, 0xef, 0x04, 0xa3, 0xf0, 0xe4} }, +{ 0x890f, 16, {0xa3, 0xf0, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5} }, +{ 0x891f, 16, {0x83, 0xe0, 0x90, 0x01, 0x2f, 0xf0, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 0x05, 0xf5, 0x82} }, +{ 0x892f, 16, {0xe4, 0x35, 0x83, 0xf5, 0x83, 0xe0, 0x54, 0x1e, 0x90, 0x01, 0x30, 0xf0, 0x74, 0x2c, 0x2f, 0xf8} }, +{ 0x893f, 16, {0xe6, 0xa3, 0xf0, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xf5, 0x54} }, +{ 0x894f, 16, {0x7f, 0x02, 0x12, 0x81, 0x11, 0xc3, 0xee, 0x64, 0x80, 0x94, 0x80, 0x40, 0xf3, 0xe5, 0x54, 0x5f} }, +{ 0x895f, 16, {0x90, 0x01, 0x32, 0xf0, 0x7e, 0x01, 0x7f, 0x2c, 0x75, 0x60, 0x00, 0x75, 0x5f, 0x00, 0x75, 0x5e} }, +{ 0x896f, 11, {0x00, 0x75, 0x5d, 0x00, 0x7d, 0x07, 0x12, 0x8e, 0x0c, 0x7f, 0x00} }, +{ 0x897a, 1, {0x22} }, +{ 0x897b, 16, {0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0xf8, 0xf5, 0x82, 0xe4, 0x34, 0x1f} }, +{ 0x898b, 16, {0xaf, 0x82, 0xfe, 0x90, 0x01, 0x33, 0x74, 0x0a, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xe5, 0x82, 0x24} }, +{ 0x899b, 16, {0x04, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0xe0, 0x90, 0x01, 0x34, 0xf0, 0x7e, 0x01, 0x7f} }, +{ 0x89ab, 16, {0x33, 0x75, 0x60, 0x00, 0x75, 0x5f, 0x00, 0x75, 0x5e, 0x00, 0x75, 0x5d, 0x00, 0x7d, 0x02, 0x12} }, +{ 0x89bb, 4, {0x8e, 0x0c, 0x7f, 0x00} }, +{ 0x89bf, 1, {0x22} }, +{ 0x89c0, 16, {0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0xf8, 0xf5, 0x82, 0xe4, 0x34, 0x1f} }, +{ 0x89d0, 16, {0xad, 0x82, 0xfc, 0x8f, 0x82, 0xa3, 0xe0, 0x60, 0x0f, 0xed, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x3c} }, +{ 0x89e0, 16, {0xf5, 0x83, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x11, 0xae, 0x04, 0xaf, 0x05, 0xef, 0x24, 0x04, 0xf5} }, +{ 0x89f0, 11, {0x82, 0xe4, 0x3e, 0xf5, 0x83, 0xe0, 0x54, 0xfd, 0xf0, 0x7f, 0x00} }, +{ 0x89fb, 1, {0x22} }, +{ 0x89fc, 16, {0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0xf8, 0xf5, 0x82, 0xe4, 0x34, 0x1f} }, +{ 0x8a0c, 16, {0xad, 0x82, 0xfc, 0x8f, 0x82, 0xa3, 0xe0, 0x60, 0x0f, 0xed, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x3c} }, +{ 0x8a1c, 16, {0xf5, 0x83, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x11, 0xae, 0x04, 0xaf, 0x05, 0xef, 0x24, 0x04, 0xf5} }, +{ 0x8a2c, 11, {0x82, 0xe4, 0x3e, 0xf5, 0x83, 0xe0, 0x54, 0xfe, 0xf0, 0x7f, 0x00} }, +{ 0x8a37, 1, {0x22} }, +{ 0x8a38, 16, {0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0xf8, 0xf5, 0x82, 0xe4, 0x34, 0x1f} }, +{ 0x8a48, 16, {0xad, 0x82, 0xfc, 0x8f, 0x82, 0xa3, 0xe0, 0x60, 0x0d, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xa3} }, +{ 0x8a58, 16, {0xe0, 0x44, 0x40, 0xf0, 0x80, 0x0f, 0xae, 0x04, 0xaf, 0x05, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3} }, +{ 0x8a68, 7, {0xa3, 0xe0, 0x54, 0xbf, 0xf0, 0x7f, 0x00} }, +{ 0x8a6f, 1, {0x22} }, +{ 0x8a70, 4, {0x8e, 0x54, 0x8f, 0x55} }, +{ 0x8a74, 16, {0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xe0, 0xf5, 0x58, 0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x24, 0xfe, 0x60} }, +{ 0x8a84, 16, {0x16, 0x14, 0x60, 0x1f, 0x14, 0x60, 0x28, 0x24, 0x03, 0x70, 0x2e, 0x7e, 0x7e, 0x7f, 0x80, 0x75} }, +{ 0x8a94, 16, {0x56, 0x7e, 0x75, 0x57, 0x80, 0x80, 0x22, 0x7e, 0x7e, 0x7f, 0x00, 0x75, 0x56, 0x7e, 0x75, 0x57} }, +{ 0x8aa4, 16, {0x00, 0x80, 0x16, 0x7e, 0x7d, 0x7f, 0x80, 0x75, 0x56, 0x7d, 0x75, 0x57, 0x80, 0x80, 0x0a, 0x7e} }, +{ 0x8ab4, 16, {0x7d, 0x7f, 0x00, 0x75, 0x56, 0x7d, 0x75, 0x57, 0x00, 0xe5, 0x58, 0x70, 0x20, 0x85, 0x57, 0x82} }, +{ 0x8ac4, 16, {0x85, 0x56, 0x83, 0x74, 0xff, 0xf0, 0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xe0, 0x25, 0xe0, 0x24} }, +{ 0x8ad4, 16, {0xb5, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0x74, 0x01, 0xf0, 0x80, 0x4d, 0xe5, 0x55, 0x24} }, +{ 0x8ae4, 16, {0x02, 0xff, 0xe4, 0x35, 0x54, 0xfe, 0xe5, 0x58, 0x60, 0x23, 0x0f, 0xef, 0xac, 0x06, 0x70, 0x01} }, +{ 0x8af4, 16, {0x0e, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xe0, 0xfd, 0x05, 0x57, 0xe5, 0x57, 0xaa, 0x56, 0x70, 0x02} }, +{ 0x8b04, 16, {0x05, 0x56, 0x14, 0xf5, 0x82, 0x8a, 0x83, 0xed, 0xf0, 0x15, 0x58, 0x80, 0xd9, 0x85, 0x55, 0x82} }, +{ 0x8b14, 16, {0x85, 0x54, 0x83, 0xa3, 0xe0, 0xff, 0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xe0, 0x25, 0xe0, 0x24} }, +{ 0x8b24, 12, {0xb5, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xef, 0xf0, 0x7f, 0x00} }, +{ 0x8b30, 1, {0x22} }, +{ 0x8b31, 16, {0xef, 0x24, 0x05, 0xf5, 0x55, 0xe4, 0x3e, 0xf5, 0x54, 0x90, 0x01, 0x35, 0x74, 0x07, 0xf0, 0x90} }, +{ 0x8b41, 16, {0x01, 0x7a, 0x74, 0x01, 0xf0, 0xa3, 0x74, 0x36, 0xf0, 0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3} }, +{ 0x8b51, 16, {0xa3, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0x8e, 0x56, 0xf5, 0x57, 0x85, 0x55, 0x82, 0x85, 0x54, 0x83} }, +{ 0x8b61, 16, {0xe0, 0x24, 0x9e, 0x60, 0x61, 0x24, 0xf9, 0x60, 0x0e, 0x24, 0xf1, 0x70, 0x03, 0x02, 0x8c, 0x12} }, +{ 0x8b71, 16, {0x24, 0x14, 0x60, 0x03, 0x02, 0x8c, 0x5e, 0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0xe0, 0xfe} }, +{ 0x8b81, 16, {0xa3, 0xe0, 0xff, 0xc3, 0xe4, 0x9f, 0xf5, 0x59, 0x74, 0x01, 0x9e, 0xf5, 0x58, 0xd3, 0xe5, 0x59} }, +{ 0x8b91, 16, {0x94, 0x40, 0xe5, 0x58, 0x94, 0x00, 0x40, 0x06, 0x75, 0x58, 0x00, 0x75, 0x59, 0x40, 0xd3, 0xe5} }, +{ 0x8ba1, 16, {0x57, 0x95, 0x59, 0xe5, 0x56, 0x95, 0x58, 0x50, 0x03, 0x02, 0x8c, 0x61, 0xae, 0x58, 0xaf, 0x59} }, +{ 0x8bb1, 16, {0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0xa3, 0xa3, 0xee, 0xf0, 0xfe, 0xa3, 0xef, 0xf0, 0x8e} }, +{ 0x8bc1, 16, {0x56, 0xf5, 0x57, 0x02, 0x8c, 0x61, 0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0xe0, 0xfe, 0xa3} }, +{ 0x8bd1, 16, {0xe0, 0xff, 0xc3, 0x74, 0x30, 0x9f, 0xf5, 0x59, 0xe4, 0x9e, 0xf5, 0x58, 0xd3, 0xe5, 0x59, 0x94} }, +{ 0x8be1, 16, {0x10, 0xe5, 0x58, 0x94, 0x00, 0x40, 0x06, 0x75, 0x58, 0x00, 0x75, 0x59, 0x10, 0xd3, 0xe5, 0x57} }, +{ 0x8bf1, 16, {0x95, 0x59, 0xe5, 0x56, 0x95, 0x58, 0x40, 0x68, 0xae, 0x58, 0xaf, 0x59, 0x85, 0x55, 0x82, 0x85} }, +{ 0x8c01, 16, {0x54, 0x83, 0xa3, 0xa3, 0xa3, 0xee, 0xf0, 0xfe, 0xa3, 0xef, 0xf0, 0x8e, 0x56, 0xf5, 0x57, 0x80} }, +{ 0x8c11, 16, {0x4f, 0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xc3, 0xe4, 0x9f} }, +{ 0x8c21, 16, {0xf5, 0x59, 0xe4, 0x9e, 0xf5, 0x58, 0x45, 0x59, 0x60, 0x0b, 0xd3, 0xe5, 0x59, 0x94, 0x40, 0xe5} }, +{ 0x8c31, 16, {0x58, 0x94, 0x00, 0x40, 0x06, 0x75, 0x58, 0x00, 0x75, 0x59, 0x40, 0xd3, 0xe5, 0x57, 0x95, 0x59} }, +{ 0x8c41, 16, {0xe5, 0x56, 0x95, 0x58, 0x40, 0x17, 0xae, 0x58, 0xaf, 0x59, 0x85, 0x55, 0x82, 0x85, 0x54, 0x83} }, +{ 0x8c51, 16, {0xa3, 0xa3, 0xa3, 0xee, 0xf0, 0xfe, 0xa3, 0xef, 0xf0, 0x8e, 0x56, 0xf5, 0x57, 0x7f, 0x01, 0x22} }, +{ 0x8c61, 16, {0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xe0, 0x24, 0x9e, 0x70, 0x03, 0x02, 0x8d, 0x21, 0x24, 0xf9} }, +{ 0x8c71, 16, {0x60, 0x58, 0x24, 0xf1, 0x70, 0x03, 0x02, 0x8d, 0x71, 0x24, 0x14, 0x60, 0x03, 0x02, 0x8d, 0xb5} }, +{ 0x8c81, 16, {0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xd3, 0x94, 0xff, 0xee} }, +{ 0x8c91, 16, {0x94, 0x00, 0x40, 0x03, 0x02, 0x8d, 0xb5, 0x90, 0x01, 0x75, 0xef, 0xf0, 0xe5, 0x57, 0x15, 0x57} }, +{ 0x8ca1, 16, {0xae, 0x56, 0x70, 0x02, 0x15, 0x56, 0x4e, 0x70, 0x03, 0x02, 0x8d, 0xb5, 0x90, 0x01, 0x75, 0xe0} }, +{ 0x8cb1, 16, {0xff, 0x04, 0xf0, 0xa8, 0x07, 0xe6, 0xff, 0x90, 0x01, 0x7a, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9b} }, +{ 0x8cc1, 16, {0xce, 0x85, 0xf0, 0x82, 0xf5, 0x83, 0xef, 0xf0, 0x80, 0xd2, 0x85, 0x55, 0x82, 0x85, 0x54, 0x83} }, +{ 0x8cd1, 16, {0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xc3, 0x94, 0x80, 0xee, 0x94, 0x00, 0x50, 0x03, 0x02, 0x8d} }, +{ 0x8ce1, 16, {0xb5, 0xd3, 0xef, 0x94, 0xff, 0xee, 0x94, 0x00, 0x40, 0x03, 0x02, 0x8d, 0xb5, 0x90, 0x01, 0x76} }, +{ 0x8cf1, 16, {0xef, 0xf0, 0xe5, 0x57, 0x15, 0x57, 0xae, 0x56, 0x70, 0x02, 0x15, 0x56, 0x4e, 0x70, 0x03, 0x02} }, +{ 0x8d01, 16, {0x8d, 0xb5, 0x90, 0x01, 0x76, 0xe0, 0xff, 0x04, 0xf0, 0xa8, 0x07, 0xe6, 0xff, 0x90, 0x01, 0x7a} }, +{ 0x8d11, 16, {0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9b, 0xce, 0x85, 0xf0, 0x82, 0xf5, 0x83, 0xef, 0xf0, 0x80, 0xd2} }, +{ 0x8d21, 16, {0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xc3, 0x94, 0x20, 0xee} }, +{ 0x8d31, 16, {0x94, 0x00, 0x50, 0x03, 0x02, 0x8d, 0xb5, 0xd3, 0xef, 0x94, 0x2f, 0xee, 0x94, 0x00, 0x50, 0x74} }, +{ 0x8d41, 16, {0x90, 0x01, 0x77, 0xef, 0xf0, 0xe5, 0x57, 0x15, 0x57, 0xae, 0x56, 0x70, 0x02, 0x15, 0x56, 0x4e} }, +{ 0x8d51, 16, {0x60, 0x62, 0x90, 0x01, 0x77, 0xe0, 0xff, 0x04, 0xf0, 0xa8, 0x07, 0xe6, 0xff, 0x90, 0x01, 0x7a} }, +{ 0x8d61, 16, {0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9b, 0xce, 0x85, 0xf0, 0x82, 0xf5, 0x83, 0xef, 0xf0, 0x80, 0xd5} }, +{ 0x8d71, 16, {0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0xe0, 0xff, 0xa3, 0xe0, 0x90, 0x01, 0x78, 0xcf, 0xf0} }, +{ 0x8d81, 16, {0xa3, 0xef, 0xf0, 0xe5, 0x57, 0x15, 0x57, 0xae, 0x56, 0x70, 0x02, 0x15, 0x56, 0x4e, 0x60, 0x24} }, +{ 0x8d91, 16, {0x90, 0x01, 0x78, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9b, 0xce, 0x85, 0xf0, 0x82, 0xf5, 0x83, 0xe0} }, +{ 0x8da1, 16, {0xff, 0x90, 0x01, 0x7a, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9b, 0xce, 0x85, 0xf0, 0x82, 0xf5, 0x83} }, +{ 0x8db1, 16, {0xef, 0xf0, 0x80, 0xcf, 0x7e, 0x01, 0x7f, 0x35, 0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0xa3} }, +{ 0x8dc1, 16, {0xa3, 0xe0, 0xa3, 0xe0, 0x04, 0xfd, 0x75, 0x60, 0x00, 0x75, 0x5f, 0x00, 0x75, 0x5e, 0x00, 0x75} }, +{ 0x8dd1, 7, {0x5d, 0x00, 0x12, 0x8e, 0x0c, 0x7f, 0x00} }, +{ 0x8dd8, 1, {0x22} }, +{ 0x8dd9, 16, {0x8e, 0x61, 0x8f, 0x62, 0x8c, 0x63, 0x8d, 0x64, 0xaf, 0x03, 0x1b, 0xef, 0x60, 0x24, 0x05, 0x62} }, +{ 0x8de9, 16, {0xe5, 0x62, 0xae, 0x61, 0x70, 0x02, 0x05, 0x61, 0x14, 0xf5, 0x82, 0x8e, 0x83, 0xe0, 0xff, 0x05} }, +{ 0x8df9, 16, {0x64, 0xe5, 0x64, 0xac, 0x63, 0x70, 0x02, 0x05, 0x63, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0} }, +{ 0x8e09, 3, {0x80, 0xd6, 0x22} }, +{ 0x8e0c, 16, {0x8d, 0x5c, 0xab, 0x07, 0xaa, 0x06, 0xaf, 0x60, 0xae, 0x5f, 0xad, 0x5e, 0xac, 0x5d, 0xec, 0x4d} }, +{ 0x8e1c, 16, {0x4e, 0x4f, 0x60, 0x1c, 0x90, 0x7f, 0xc2, 0xe0, 0x30, 0xe1, 0x1c, 0x7f, 0xff, 0x7e, 0xff, 0x7d} }, +{ 0x8e2c, 16, {0xff, 0x7c, 0xff, 0x78, 0x5d, 0x12, 0x9d, 0x0e, 0xec, 0x4d, 0x4e, 0x4f, 0x60, 0x09, 0x80, 0xe4} }, +{ 0x8e3c, 16, {0x90, 0x7f, 0xc2, 0xe0, 0x20, 0xe1, 0xf9, 0x90, 0x7f, 0xc2, 0xe0, 0x20, 0xe1, 0x16, 0xaf, 0x03} }, +{ 0x8e4c, 16, {0xae, 0x02, 0x7c, 0x7b, 0x7d, 0x80, 0xab, 0x5c, 0x12, 0x8d, 0xd9, 0x90, 0x7f, 0xc3, 0xe5, 0x5c} }, +{ 0x8e5c, 7, {0xf0, 0x7f, 0x01, 0x22, 0x7f, 0x00, 0x22} }, +{ 0x8e63, 16, {0x90, 0x01, 0x84, 0x74, 0x0b, 0xf0, 0x90, 0x20, 0x70, 0xe0, 0x54, 0xf0, 0xff, 0xc4, 0x54, 0x0f} }, +{ 0x8e73, 16, {0x90, 0x01, 0x85, 0xf0, 0x90, 0x11, 0xfd, 0xe4, 0x93, 0x90, 0x01, 0x86, 0xf0, 0x90, 0x11, 0xfe} }, +{ 0x8e83, 16, {0xe4, 0x93, 0x90, 0x01, 0x87, 0xf0, 0xe4, 0x90, 0x01, 0x7c, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3} }, +{ 0x8e93, 16, {0xf0, 0xa3, 0xf0, 0xa3, 0x74, 0x10, 0xf0, 0xa3, 0x74, 0x01, 0xf0, 0xa3, 0x74, 0x88, 0xf0, 0x7e} }, +{ 0x8ea3, 16, {0x01, 0x7f, 0x7c, 0x12, 0x19, 0xc1, 0x7e, 0x01, 0x7f, 0x84, 0x75, 0x60, 0x00, 0x75, 0x5f, 0x00} }, +{ 0x8eb3, 13, {0x75, 0x5e, 0x00, 0x75, 0x5d, 0x00, 0x7d, 0x14, 0x12, 0x8e, 0x0c, 0x7f, 0x00} }, +{ 0x8ec0, 1, {0x22} }, +{ 0x8ec1, 4, {0x8e, 0x4b, 0x8f, 0x4c} }, +{ 0x8ec5, 16, {0x85, 0x4b, 0x4e, 0x85, 0x4c, 0x4f, 0xe5, 0x4f, 0x24, 0x01, 0xf5, 0x53, 0xe4, 0x35, 0x4e, 0xf5} }, +{ 0x8ed5, 16, {0x52, 0x85, 0x4f, 0x82, 0x85, 0x4e, 0x83, 0xe0, 0x14, 0xb4, 0x0f, 0x00, 0x40, 0x03, 0x02, 0x8f} }, +{ 0x8ee5, 16, {0xd6, 0x90, 0x8e, 0xed, 0xf8, 0x28, 0x28, 0x73, 0x02, 0x8f, 0x1a, 0x02, 0x8f, 0x26, 0x02, 0x8f} }, +{ 0x8ef5, 16, {0x32, 0x02, 0x8f, 0x5c, 0x02, 0x8f, 0x67, 0x02, 0x8f, 0x72, 0x02, 0x8f, 0x7d, 0x02, 0x8f, 0x88} }, +{ 0x8f05, 16, {0x02, 0x8f, 0x93, 0x02, 0x8f, 0x9e, 0x02, 0x8f, 0xa9, 0x02, 0x8f, 0xb0, 0x02, 0x8f, 0xd6, 0x02} }, +{ 0x8f15, 16, {0x8f, 0xbb, 0x02, 0x8f, 0xc6, 0xaf, 0x53, 0xae, 0x52, 0x12, 0x83, 0x5f, 0x8f, 0x4d, 0x02, 0x8f} }, +{ 0x8f25, 16, {0xd6, 0xaf, 0x53, 0xae, 0x52, 0x12, 0x84, 0x33, 0x8f, 0x4d, 0x02, 0x8f, 0xd6, 0x85, 0x52, 0x50} }, +{ 0x8f35, 16, {0x85, 0x53, 0x51, 0xe5, 0x51, 0x24, 0x01, 0xff, 0xe4, 0x35, 0x50, 0xfe, 0x12, 0x85, 0x08, 0xaf} }, +{ 0x8f45, 16, {0x51, 0xae, 0x50, 0x12, 0x85, 0x9b, 0xef, 0x70, 0x03, 0x02, 0x8f, 0xd6, 0xaf, 0x51, 0xae, 0x50} }, +{ 0x8f55, 16, {0x12, 0x85, 0xe1, 0x8f, 0x4d, 0x80, 0x7a, 0xaf, 0x53, 0xae, 0x52, 0x12, 0x89, 0xc0, 0x8f, 0x4d} }, +{ 0x8f65, 16, {0x80, 0x6f, 0xaf, 0x53, 0xae, 0x52, 0x12, 0x89, 0xfc, 0x8f, 0x4d, 0x80, 0x64, 0xaf, 0x53, 0xae} }, +{ 0x8f75, 16, {0x52, 0x12, 0x8a, 0x38, 0x8f, 0x4d, 0x80, 0x59, 0xaf, 0x4c, 0xae, 0x4b, 0x12, 0x8b, 0x31, 0x8f} }, +{ 0x8f85, 16, {0x4d, 0x80, 0x4e, 0xaf, 0x53, 0xae, 0x52, 0x12, 0x88, 0xef, 0x8f, 0x4d, 0x80, 0x43, 0xaf, 0x53} }, +{ 0x8f95, 16, {0xae, 0x52, 0x12, 0x84, 0xc4, 0x8f, 0x4d, 0x80, 0x38, 0xaf, 0x53, 0xae, 0x52, 0x12, 0x89, 0x7b} }, +{ 0x8fa5, 16, {0x8f, 0x4d, 0x80, 0x2d, 0x12, 0x8e, 0x63, 0x8f, 0x4d, 0x80, 0x26, 0xaf, 0x53, 0xae, 0x52, 0x12} }, +{ 0x8fb5, 16, {0x11, 0xe5, 0x8f, 0x4d, 0x80, 0x1b, 0xaf, 0x53, 0xae, 0x52, 0x12, 0x8a, 0x70, 0x8f, 0x4d, 0x80} }, +{ 0x8fc5, 16, {0x10, 0xaf, 0x4c, 0xae, 0x4b, 0x7c, 0x02, 0x7d, 0xaf, 0x7b, 0x40, 0x12, 0x8d, 0xd9, 0xe4, 0xf5} }, +{ 0x8fd5, 16, {0x4d, 0x85, 0x4f, 0x82, 0x85, 0x4e, 0x83, 0xe0, 0xff, 0x14, 0x24, 0xfa, 0x50, 0x04, 0x24, 0xfe} }, +{ 0x8fe5, 16, {0x70, 0x2b, 0x90, 0x01, 0x98, 0x74, 0x10, 0xf0, 0xa3, 0xef, 0xf0, 0x85, 0x53, 0x82, 0x85, 0x52} }, +{ 0x8ff5, 16, {0x83, 0xe0, 0x90, 0x01, 0x9a, 0xf0, 0x7e, 0x01, 0x7f, 0x98, 0x75, 0x60, 0x00, 0x75, 0x5f, 0x00} }, +{ 0x9005, 15, {0x75, 0x5e, 0x00, 0x75, 0x5d, 0x00, 0x7d, 0x03, 0x12, 0x8e, 0x0c, 0x8f, 0x4d, 0xaf, 0x4d} }, +{ 0x9014, 1, {0x22} }, +{ 0x9015, 8, {0x8f, 0x4e, 0x8e, 0x4d, 0x8d, 0x4c, 0x8c, 0x4b} }, +{ 0x901d, 16, {0x75, 0x55, 0x01, 0x75, 0x56, 0x9c, 0xe4, 0xf5, 0x54, 0xaf, 0x50, 0x15, 0x50, 0xef, 0x70, 0x03} }, +{ 0x902d, 16, {0x02, 0x90, 0xb3, 0xaf, 0x4f, 0xe4, 0xfc, 0xfd, 0xfe, 0xf8, 0xf9, 0xfa, 0xab, 0x07, 0xaf, 0x4e} }, +{ 0x903d, 16, {0xae, 0x4d, 0xad, 0x4c, 0xac, 0x4b, 0x12, 0x9c, 0x58, 0xaf, 0x03, 0x8f, 0x53, 0xaf, 0x4e, 0xae} }, +{ 0x904d, 16, {0x4d, 0xad, 0x4c, 0xac, 0x4b, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0xaf, 0x4f, 0xe4} }, +{ 0x905d, 16, {0xfc, 0xfd, 0xfe, 0xf8, 0xf9, 0xfa, 0xab, 0x07, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04} }, +{ 0x906d, 16, {0x12, 0x9c, 0x58, 0x8f, 0x4e, 0x8e, 0x4d, 0x8d, 0x4c, 0x8c, 0x4b, 0xe5, 0x53, 0x24, 0x30, 0xf5} }, +{ 0x907d, 16, {0x53, 0xd3, 0x94, 0x39, 0x40, 0x06, 0x74, 0x07, 0x25, 0x53, 0xf5, 0x53, 0x05, 0x56, 0xe5, 0x56} }, +{ 0x908d, 16, {0xae, 0x55, 0x70, 0x02, 0x05, 0x55, 0x14, 0xf5, 0x82, 0x8e, 0x83, 0xe4, 0xf0, 0x05, 0x56, 0xe5} }, +{ 0x909d, 16, {0x56, 0xae, 0x55, 0x70, 0x02, 0x05, 0x55, 0x14, 0xf5, 0x82, 0x8e, 0x83, 0xe5, 0x53, 0xf0, 0x05} }, +{ 0x90ad, 16, {0x54, 0x05, 0x54, 0x02, 0x90, 0x26, 0xe5, 0x56, 0x15, 0x56, 0x70, 0x02, 0x15, 0x55, 0xaf, 0x54} }, +{ 0x90bd, 16, {0x15, 0x54, 0xef, 0x60, 0x23, 0xe5, 0x56, 0x15, 0x56, 0xae, 0x55, 0x70, 0x02, 0x15, 0x55, 0xf5} }, +{ 0x90cd, 16, {0x82, 0x8e, 0x83, 0xe0, 0xff, 0x05, 0x52, 0xe5, 0x52, 0xac, 0x51, 0x70, 0x02, 0x05, 0x51, 0x14} }, +{ 0x90dd, 8, {0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x80, 0xd6} }, +{ 0x90e5, 1, {0x22} }, +{ 0x90e6, 16, {0xe4, 0x90, 0x01, 0xc9, 0xf0, 0x7e, 0x01, 0x7f, 0xca, 0x90, 0x01, 0xbe, 0xee, 0xf0, 0xa3, 0xef} }, +{ 0x90f6, 10, {0xf0, 0x90, 0x01, 0xc2, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x22} }, +{ 0x9100, 16, {0xaa, 0x07, 0xa9, 0x05, 0x90, 0x01, 0xc9, 0xe0, 0xc3, 0x94, 0x40, 0x50, 0x61, 0xac, 0x02, 0x74} }, +{ 0x9110, 16, {0x01, 0x7e, 0x00, 0xa8, 0x04, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff} }, +{ 0x9120, 16, {0xe4, 0xef, 0x55, 0x30, 0x60, 0x45, 0xea, 0x04, 0xff, 0x90, 0x01, 0xc2, 0xe0, 0xfc, 0xa3, 0xe0} }, +{ 0x9130, 16, {0xfd, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0xa3, 0xe9, 0xf0, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3} }, +{ 0x9140, 16, {0xeb, 0xf0, 0x90, 0x01, 0xc2, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x9b, 0xb8, 0xfc, 0xd3, 0xe5, 0xf0} }, +{ 0x9150, 16, {0x94, 0x87, 0xec, 0x94, 0x02, 0x40, 0x0a, 0x90, 0x01, 0xc2, 0x74, 0x01, 0xf0, 0xa3, 0x74, 0xca} }, +{ 0x9160, 16, {0xf0, 0xc2, 0xaf, 0x90, 0x01, 0xc9, 0xe0, 0x04, 0xf0, 0xd2, 0xaf, 0x7f, 0x01, 0x22, 0x7f, 0x00} }, +{ 0x9170, 1, {0x22} }, +{ 0x9171, 16, {0x90, 0x01, 0xc9, 0xe0, 0xd3, 0x94, 0x00, 0x40, 0x55, 0x90, 0x01, 0xbe, 0xe0, 0xfc, 0xa3, 0xe0} }, +{ 0x9181, 16, {0xaa, 0x04, 0xf9, 0x7b, 0x01, 0xc0, 0x03, 0xc0, 0x02, 0xc0, 0x01, 0xaa, 0x06, 0xa9, 0x07, 0xa8} }, +{ 0x9191, 16, {0x01, 0xac, 0x02, 0xad, 0x03, 0xd0, 0x01, 0xd0, 0x02, 0xd0, 0x03, 0x7e, 0x00, 0x7f, 0x03, 0x12} }, +{ 0x91a1, 16, {0x9b, 0x49, 0x90, 0x01, 0xbe, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x9b, 0xb8, 0xfc, 0xd3, 0xe5, 0xf0} }, +{ 0x91b1, 16, {0x94, 0x87, 0xec, 0x94, 0x02, 0x40, 0x0a, 0x90, 0x01, 0xbe, 0x74, 0x01, 0xf0, 0xa3, 0x74, 0xca} }, +{ 0x91c1, 16, {0xf0, 0xc2, 0xaf, 0x90, 0x01, 0xc9, 0xe0, 0x14, 0xf0, 0xd2, 0xaf, 0x7f, 0x01, 0x22, 0x7f, 0x00} }, +{ 0x91d1, 1, {0x22} }, +{ 0x91d2, 16, {0x90, 0x7f, 0xc2, 0xe0, 0x20, 0xe1, 0x5e, 0x7e, 0x7b, 0x7f, 0x80, 0x75, 0x50, 0x7b, 0x75, 0x51} }, +{ 0x91e2, 16, {0x80, 0xe5, 0x51, 0x24, 0x01, 0xff, 0xe4, 0x35, 0x50, 0xa9, 0x07, 0x7b, 0x01, 0x8b, 0x52, 0xf5} }, +{ 0x91f2, 16, {0x53, 0x89, 0x54, 0xfe, 0x12, 0x91, 0x71, 0xef, 0x60, 0x3b, 0xab, 0x52, 0xaa, 0x53, 0xa9, 0x54} }, +{ 0x9202, 16, {0x12, 0x9b, 0x72, 0x14, 0xff, 0x90, 0x00, 0x01, 0x12, 0x9b, 0x8b, 0xb4, 0x02, 0x16, 0xc2, 0xaf} }, +{ 0x9212, 16, {0xef, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x01, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0, 0x44} }, +{ 0x9222, 16, {0x04, 0xf0, 0xd2, 0xaf, 0x85, 0x51, 0x82, 0x85, 0x50, 0x83, 0x74, 0x0d, 0xf0, 0x90, 0x7f, 0xc3} }, +{ 0x9232, 5, {0x74, 0x04, 0xf0, 0xd2, 0xaf} }, +{ 0x9237, 1, {0x22} }, +{ 0x9238, 16, {0x12, 0x91, 0xd2, 0xe4, 0xf5, 0x4b, 0x74, 0x36, 0x25, 0x4b, 0xf8, 0xe6, 0x54, 0xf0, 0xf5, 0x4c} }, +{ 0x9248, 16, {0x74, 0xc5, 0x25, 0x4b, 0xf5, 0x82, 0xe4, 0x34, 0x01, 0xf5, 0x83, 0xe0, 0x65, 0x4c, 0xff, 0xc4} }, +{ 0x9258, 16, {0x54, 0x0f, 0xf5, 0x4d, 0x60, 0x22, 0x74, 0xc5, 0x25, 0x4b, 0xf5, 0x82, 0xe4, 0x34, 0x01, 0xf5} }, +{ 0x9268, 16, {0x83, 0xe5, 0x4c, 0xf0, 0xaf, 0x4b, 0x7d, 0x01, 0xe5, 0x4c, 0x45, 0x4d, 0xfb, 0x12, 0x91, 0x00} }, +{ 0x9278, 16, {0xef, 0x70, 0x05, 0x12, 0x91, 0xd2, 0x80, 0xec, 0x05, 0x4b, 0xe5, 0x4b, 0xc3, 0x94, 0x04, 0x40} }, +{ 0x9288, 16, {0xb5, 0x12, 0x91, 0xd2, 0xe5, 0x3a, 0x60, 0x48, 0xe4, 0xf5, 0x4b, 0xaf, 0x4b, 0x74, 0x01, 0xa8} }, +{ 0x9298, 16, {0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xf5, 0x4c, 0x55, 0x3a, 0x60, 0x29, 0xe5, 0x4b} }, +{ 0x92a8, 16, {0x75, 0xf0, 0x08, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0, 0x30, 0xe6} }, +{ 0x92b8, 16, {0x16, 0xaf, 0x4b, 0x7d, 0x04, 0x7b, 0x80, 0x12, 0x91, 0x00, 0xef, 0x70, 0x05, 0x12, 0x91, 0xd2} }, +{ 0x92c8, 16, {0x80, 0xef, 0xe5, 0x4c, 0xf4, 0x52, 0x3a, 0x05, 0x4b, 0xe5, 0x4b, 0xc3, 0x94, 0x04, 0x40, 0xbb} }, +{ 0x92d8, 16, {0x90, 0x03, 0x00, 0xe0, 0x60, 0x03, 0x02, 0x93, 0xa5, 0x74, 0x19, 0xf0, 0x7f, 0x02, 0x12, 0x81} }, +{ 0x92e8, 16, {0x11, 0x8e, 0x4e, 0x8f, 0x4f, 0xc3, 0xe5, 0x4e, 0x64, 0x80, 0x94, 0x80, 0x40, 0xee, 0x90, 0x01} }, +{ 0x92f8, 16, {0xbc, 0xe0, 0x65, 0x4f, 0xf0, 0x60, 0x37, 0xe4, 0xf5, 0x4b, 0xaf, 0x4b, 0x74, 0x01, 0xa8, 0x07} }, +{ 0x9308, 16, {0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xf5, 0x4c, 0x90, 0x01, 0xbc, 0xe0, 0x55, 0x4c, 0x60} }, +{ 0x9318, 16, {0x14, 0xaf, 0x4b, 0x7d, 0x08, 0xe5, 0x4c, 0x55, 0x4f, 0xfb, 0x12, 0x91, 0x00, 0xef, 0x70, 0x05} }, +{ 0x9328, 16, {0x12, 0x91, 0xd2, 0x80, 0xec, 0x05, 0x4b, 0xe5, 0x4b, 0xc3, 0x94, 0x04, 0x40, 0xcc, 0x90, 0x01} }, +{ 0x9338, 16, {0xbc, 0xe5, 0x4f, 0xf0, 0xe4, 0xf5, 0x4b, 0xc2, 0xaf, 0x74, 0x32, 0x25, 0x4b, 0xf8, 0xe6, 0xf5} }, +{ 0x9348, 16, {0x4c, 0xe4, 0xf6, 0xd2, 0xaf, 0x53, 0x4c, 0x1e, 0xe5, 0x4c, 0x60, 0x11, 0xaf, 0x4b, 0x7d, 0x02} }, +{ 0x9358, 16, {0xab, 0x4c, 0x12, 0x91, 0x00, 0xef, 0x70, 0x05, 0x12, 0x91, 0xd2, 0x80, 0xef, 0x74, 0x2c, 0x25} }, +{ 0x9368, 16, {0x4b, 0xf8, 0xe6, 0xf5, 0x4c, 0x74, 0xfc, 0x25, 0x4b, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83} }, +{ 0x9378, 16, {0xe0, 0x65, 0x4c, 0x60, 0x11, 0xaf, 0x4b, 0x7d, 0x04, 0xab, 0x4c, 0x12, 0x91, 0x00, 0xef, 0x70} }, +{ 0x9388, 16, {0x05, 0x12, 0x91, 0xd2, 0x80, 0xef, 0x74, 0xfc, 0x25, 0x4b, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5} }, +{ 0x9398, 16, {0x83, 0xe5, 0x4c, 0xf0, 0x05, 0x4b, 0xe5, 0x4b, 0xc3, 0x94, 0x04, 0x40, 0x9a, 0x12, 0x91, 0xd2} }, +{ 0x93a8, 1, {0x22} }, +{ 0x93a9, 12, {0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x64, 0x02, 0x93, 0xf0} }, +{ 0x93b5, 16, {0x02, 0x05, 0xa3, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2} }, +{ 0x93c5, 16, {0x08, 0xdf, 0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33} }, +{ 0x93d5, 16, {0xc4, 0x54, 0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf} }, +{ 0x93e5, 16, {0xe4, 0x80, 0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x94, 0x35, 0xe4, 0x7e} }, +{ 0x93f5, 16, {0x01, 0x93, 0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93} }, +{ 0x9405, 16, {0xa3, 0x60, 0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3} }, +{ 0x9415, 16, {0xfa, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca} }, +{ 0x9425, 16, {0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe} }, +{ 0x9435, 16, {0x60, 0x24, 0x02, 0x8a, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x81, 0x82, 0x84, 0x88} }, +{ 0x9445, 16, {0x90, 0xa0, 0xc0, 0xc1, 0xc2, 0xc4, 0xc8, 0xd0, 0xe0, 0xe1, 0xe2, 0xe4, 0xe8, 0xf0, 0xf1, 0xf2} }, +{ 0x9455, 8, {0xf4, 0xf8, 0xf9, 0xfa, 0xfc, 0xfd, 0xfe, 0xff} }, +{ 0x945d, 1, {0x00} }, +{ 0x945e, 11, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x18} }, +{ 0x9469, 16, {0x90, 0x20, 0x60, 0xe0, 0x54, 0x0f, 0xfe, 0x30, 0xe0, 0x05, 0x90, 0x20, 0x02, 0xe0, 0xff, 0xee} }, +{ 0x9479, 16, {0x30, 0xe1, 0x05, 0x90, 0x20, 0x0a, 0xe0, 0xff, 0xee, 0x30, 0xe2, 0x05, 0x90, 0x20, 0x12, 0xe0} }, +{ 0x9489, 16, {0xff, 0xee, 0x30, 0xe3, 0x05, 0x90, 0x20, 0x1a, 0xe0, 0xff, 0x90, 0x01, 0xc4, 0xe0, 0xb5, 0x1e} }, +{ 0x9499, 10, {0x04, 0xe4, 0xf0, 0x80, 0x05, 0x90, 0x01, 0xc4, 0xee, 0xf0} }, +{ 0x94a3, 9, {0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x94ac, 2, {0xa9, 0x03} }, +{ 0x94ae, 16, {0xef, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xab, 0x82, 0xfa, 0xe5} }, +{ 0x94be, 16, {0x57, 0x45, 0x58, 0xf5, 0x59, 0xe9, 0x60, 0x14, 0x8a, 0x83, 0xe5, 0x82, 0x24, 0x04, 0xf5, 0x82} }, +{ 0x94ce, 16, {0xe4, 0x35, 0x83, 0xf5, 0x83, 0xe0, 0x4d, 0xf0, 0xe4, 0xfe, 0x80, 0x13, 0xeb, 0x24, 0x04, 0xf5} }, +{ 0x94de, 16, {0x82, 0xe4, 0x3a, 0xf5, 0x83, 0xe0, 0xff, 0xed, 0xf4, 0xfc, 0xef, 0x5c, 0xf0, 0xae, 0x59, 0xeb} }, +{ 0x94ee, 16, {0x24, 0x06, 0xf5, 0x82, 0xe4, 0x3a, 0xf5, 0x83, 0xe0, 0x55, 0x59, 0xfc, 0xb5, 0x06, 0x03, 0xaf} }, +{ 0x94fe, 16, {0x05, 0x22, 0xe5, 0x57, 0x5c, 0xfe, 0xe5, 0x58, 0x5c, 0xfd, 0xe9, 0x60, 0x16, 0xee, 0x70, 0x04} }, +{ 0x950e, 16, {0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0xae, 0x07, 0xed, 0x70, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f} }, +{ 0x951e, 16, {0x00, 0xad, 0x07, 0xee, 0x60, 0x03, 0xaf, 0x57, 0x22, 0xed, 0x60, 0x03, 0xaf, 0x58, 0x22, 0x7f} }, +{ 0x952e, 1, {0x00} }, +{ 0x952f, 1, {0x22} }, +{ 0x9530, 16, {0x75, 0x50, 0x02, 0x75, 0x51, 0xb0, 0x90, 0x03, 0x35, 0x74, 0x0f, 0xf0, 0x85, 0x51, 0x82, 0x85} }, +{ 0x9540, 16, {0x50, 0x83, 0xe0, 0xff, 0x90, 0x03, 0x36, 0xf0, 0x85, 0x51, 0x82, 0x85, 0x50, 0x83, 0xa3, 0xe0} }, +{ 0x9550, 16, {0x90, 0x03, 0x37, 0xf0, 0xa3, 0x74, 0xff, 0xf0, 0x75, 0x52, 0x03, 0x75, 0x53, 0x39, 0xef, 0x14} }, +{ 0x9560, 16, {0xb4, 0x0b, 0x00, 0x40, 0x03, 0x02, 0x99, 0x98, 0x90, 0x95, 0x6f, 0xf8, 0x28, 0x28, 0x73, 0x02} }, +{ 0x9570, 16, {0x95, 0x90, 0x02, 0x96, 0x2f, 0x02, 0x97, 0x34, 0x02, 0x97, 0x54, 0x02, 0x97, 0x54, 0x02, 0x97} }, +{ 0x9580, 16, {0xef, 0x02, 0x98, 0x2a, 0x02, 0x98, 0x4f, 0x02, 0x99, 0x0d, 0x02, 0x99, 0x39, 0x02, 0x99, 0x65} }, +{ 0x9590, 16, {0xe4, 0xf5, 0x4b, 0xe5, 0x4b, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20} }, +{ 0x95a0, 16, {0xaf, 0x82, 0xf5, 0x4e, 0x8f, 0x4f, 0xe4, 0xff, 0xe4, 0xfe, 0xef, 0x60, 0x10, 0x74, 0x8a, 0x2e} }, +{ 0x95b0, 16, {0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe0, 0xf4, 0xf5, 0x4c, 0x80, 0x0d, 0x74, 0x8a, 0x2e} }, +{ 0x95c0, 16, {0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe0, 0xf5, 0x4c, 0xe5, 0x4f, 0x24, 0x07, 0xf5, 0x82} }, +{ 0x95d0, 16, {0xe4, 0x35, 0x4e, 0xf5, 0x83, 0xe5, 0x4c, 0xf0, 0xe0, 0xf5, 0x4d, 0x65, 0x4c, 0x60, 0x38, 0xe4} }, +{ 0x95e0, 16, {0x90, 0x03, 0x38, 0xf0, 0xe5, 0x4b, 0x04, 0xfd, 0x05, 0x53, 0xe5, 0x53, 0xaa, 0x52, 0x70, 0x02} }, +{ 0x95f0, 16, {0x05, 0x52, 0x14, 0xf5, 0x82, 0x8a, 0x83, 0xed, 0xf0, 0x05, 0x53, 0xe5, 0x53, 0xac, 0x52, 0x70} }, +{ 0x9600, 16, {0x02, 0x05, 0x52, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xe5, 0x4c, 0xf0, 0x85, 0x53, 0x82, 0x85, 0x52} }, +{ 0x9610, 16, {0x83, 0xe5, 0x4d, 0xf0, 0x02, 0x99, 0x9e, 0x0e, 0xbe, 0x24, 0x8f, 0x0f, 0xef, 0x64, 0x02, 0x70} }, +{ 0x9620, 16, {0x87, 0x05, 0x4b, 0xe5, 0x4b, 0x64, 0x04, 0x60, 0x03, 0x02, 0x95, 0x93, 0x02, 0x99, 0x9e, 0xe4} }, +{ 0x9630, 16, {0xf5, 0x4b, 0xaf, 0x4b, 0xe4, 0xfd, 0x12, 0x82, 0x50, 0x05, 0x4b, 0xe5, 0x4b, 0xd3, 0x94, 0x03} }, +{ 0x9640, 16, {0x40, 0xf0, 0x90, 0x00, 0x04, 0x74, 0x94, 0xf0, 0xa3, 0x74, 0x5e, 0xf0, 0xe4, 0xf5, 0x4d, 0x7e} }, +{ 0x9650, 16, {0x20, 0x7f, 0x00, 0x75, 0x4e, 0x20, 0x75, 0x4f, 0x00, 0xf5, 0x4b, 0xaf, 0x4b, 0x74, 0x01, 0xa8} }, +{ 0x9660, 16, {0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xf5, 0x4c, 0x90, 0x01, 0xc4, 0xf0, 0x90, 0x01} }, +{ 0x9670, 16, {0xc0, 0xe4, 0xf0, 0xa3, 0x74, 0x0a, 0xf0, 0x85, 0x4f, 0x82, 0x85, 0x4e, 0x83, 0xa3, 0x74, 0x02} }, +{ 0x9680, 16, {0xf0, 0x90, 0x01, 0xc4, 0xe0, 0xb5, 0x4c, 0x34, 0x90, 0x01, 0xc0, 0xe0, 0x70, 0x02, 0xa3, 0xe0} }, +{ 0x9690, 16, {0x70, 0xef, 0x90, 0x03, 0x38, 0xf0, 0xe5, 0x4b, 0x04, 0xff, 0x05, 0x53, 0xe5, 0x53, 0xac, 0x52} }, +{ 0x96a0, 16, {0x70, 0x02, 0x05, 0x52, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x85, 0x53, 0x82, 0x85, 0x52} }, +{ 0x96b0, 16, {0x83, 0x74, 0xff, 0xf0, 0xe4, 0x90, 0x01, 0xc4, 0xf0, 0x75, 0x4d, 0xff, 0x90, 0x01, 0xc4, 0xe0} }, +{ 0x96c0, 16, {0xff, 0x60, 0x37, 0xe4, 0x90, 0x03, 0x38, 0xf0, 0xe5, 0x4b, 0x04, 0xfe, 0x05, 0x53, 0xe5, 0x53} }, +{ 0x96d0, 16, {0xac, 0x52, 0x70, 0x02, 0x05, 0x52, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xee, 0xf0, 0x05, 0x53, 0xe5} }, +{ 0x96e0, 16, {0x53, 0xac, 0x52, 0x70, 0x02, 0x05, 0x52, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x85, 0x53} }, +{ 0x96f0, 16, {0x82, 0x85, 0x52, 0x83, 0xe5, 0x4c, 0xf0, 0x75, 0x4d, 0xff, 0xe5, 0x4d, 0x70, 0x16, 0x74, 0x08} }, +{ 0x9700, 16, {0x25, 0x4f, 0xf5, 0x4f, 0xe4, 0x35, 0x4e, 0xf5, 0x4e, 0x05, 0x4b, 0xe5, 0x4b, 0x64, 0x04, 0x60} }, +{ 0x9710, 16, {0x03, 0x02, 0x96, 0x5b, 0xe4, 0xf5, 0x4b, 0xaf, 0x4b, 0x7d, 0x01, 0x12, 0x82, 0x50, 0x05, 0x4b} }, +{ 0x9720, 16, {0xe5, 0x4b, 0xd3, 0x94, 0x03, 0x40, 0xf0, 0x90, 0x00, 0x04, 0x74, 0x13, 0xf0, 0xa3, 0x74, 0x12} }, +{ 0x9730, 16, {0xf0, 0x02, 0x99, 0x9e, 0x85, 0x51, 0x82, 0x85, 0x50, 0x83, 0xa3, 0xe0, 0x14, 0xff, 0x74, 0x01} }, +{ 0x9740, 16, {0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x90, 0x02, 0xf7, 0xf0, 0x90, 0x01, 0xc4} }, +{ 0x9750, 16, {0xf0, 0x02, 0x99, 0x9e, 0x90, 0x01, 0xc0, 0x74, 0x03, 0xf0, 0xa3, 0x74, 0xe8, 0xf0, 0xe4, 0xf5} }, +{ 0x9760, 16, {0x4d, 0x90, 0x02, 0xf7, 0xe0, 0xff, 0x90, 0x01, 0xc4, 0xe0, 0xb5, 0x07, 0x19, 0x90, 0x01, 0xc0} }, +{ 0x9770, 16, {0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x70, 0xea, 0x90, 0x03, 0x38, 0xf0, 0x85, 0x53, 0x82, 0x85, 0x52} }, +{ 0x9780, 16, {0x83, 0x74, 0xff, 0xf0, 0xf5, 0x4d, 0xe5, 0x4d, 0x60, 0x03, 0x02, 0x99, 0x9e, 0x90, 0x01, 0xc0} }, +{ 0x9790, 16, {0xf0, 0xa3, 0x74, 0x96, 0xf0, 0x90, 0x01, 0xc0, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x70, 0xf6, 0x7f} }, +{ 0x97a0, 16, {0x02, 0x12, 0x81, 0x11, 0xc3, 0xee, 0x64, 0x80, 0x94, 0x80, 0x40, 0xf3, 0xef, 0x54, 0x0f, 0xf5} }, +{ 0x97b0, 16, {0x4d, 0x90, 0x02, 0xf7, 0xe0, 0x55, 0x4d, 0x70, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0x8f} }, +{ 0x97c0, 16, {0x4c, 0x85, 0x51, 0x82, 0x85, 0x50, 0x83, 0xe0, 0xb4, 0x05, 0x0c, 0xe5, 0x4c, 0x70, 0x04, 0x7f} }, +{ 0x97d0, 16, {0x01, 0x80, 0x02, 0x7f, 0x00, 0x8f, 0x4c, 0xe5, 0x4c, 0x70, 0x03, 0x02, 0x99, 0x9e, 0xe4, 0x90} }, +{ 0x97e0, 16, {0x03, 0x38, 0xf0, 0x85, 0x53, 0x82, 0x85, 0x52, 0x83, 0xe5, 0x4d, 0xf0, 0x02, 0x99, 0x9e, 0xe4} }, +{ 0x97f0, 16, {0xff, 0xfd, 0x12, 0x82, 0x50, 0x7e, 0x20, 0x7f, 0x00, 0x75, 0x4e, 0x20, 0x75, 0x4f, 0x00, 0x85} }, +{ 0x9800, 16, {0x4f, 0x82, 0x85, 0x4e, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0x44, 0x80, 0xf0, 0x85, 0x4f, 0x82, 0x85} }, +{ 0x9810, 16, {0x4e, 0x83, 0x74, 0x01, 0xf0, 0xa3, 0xe4, 0xf0, 0x85, 0x4f, 0x82, 0x85, 0x4e, 0x83, 0xa3, 0xa3} }, +{ 0x9820, 16, {0xa3, 0xe0, 0x54, 0x7f, 0xf0, 0xd2, 0x04, 0x02, 0x99, 0x9e, 0xc2, 0x04, 0x7e, 0x20, 0x7f, 0x00} }, +{ 0x9830, 16, {0x75, 0x4e, 0x20, 0x75, 0x4f, 0x00, 0xe5, 0x4f, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x4e, 0xf5} }, +{ 0x9840, 16, {0x83, 0xe0, 0x30, 0xe6, 0xf1, 0xe4, 0xff, 0x7d, 0x01, 0x12, 0x82, 0x50, 0x02, 0x99, 0x9e, 0xe4} }, +{ 0x9850, 16, {0xf5, 0x4d, 0xf5, 0x4b, 0xaf, 0x4b, 0xe4, 0xfd, 0x12, 0x82, 0x50, 0xe5, 0x4b, 0x75, 0xf0, 0x08} }, +{ 0x9860, 16, {0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xaf, 0x82, 0xf5, 0x4e, 0x8f, 0x4f, 0xf5, 0x83} }, +{ 0x9870, 16, {0xe5, 0x82, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0xe0, 0x54, 0xfc, 0xf0, 0xaf} }, +{ 0x9880, 16, {0x4b, 0x7d, 0x01, 0x7b, 0x01, 0x75, 0x57, 0x80, 0x75, 0x58, 0x40, 0x12, 0x94, 0xac, 0x8f, 0x4d} }, +{ 0x9890, 16, {0xe5, 0x4d, 0x70, 0x11, 0xaf, 0x4b, 0x7d, 0x02, 0x7b, 0x01, 0x75, 0x57, 0x10, 0x75, 0x58, 0x20} }, +{ 0x98a0, 16, {0x12, 0x94, 0xac, 0x8f, 0x4d, 0xe5, 0x4d, 0x70, 0x10, 0xaf, 0x4b, 0x7d, 0x01, 0xfb, 0x75, 0x57} }, +{ 0x98b0, 16, {0x80, 0x75, 0x58, 0x40, 0x12, 0x94, 0xac, 0x8f, 0x4d, 0xe5, 0x4d, 0x70, 0x10, 0xaf, 0x4b, 0x7d} }, +{ 0x98c0, 16, {0x02, 0xfb, 0x75, 0x57, 0x10, 0x75, 0x58, 0x20, 0x12, 0x94, 0xac, 0x8f, 0x4d, 0xaf, 0x4b, 0x7d} }, +{ 0x98d0, 16, {0x01, 0x12, 0x82, 0x50, 0xe5, 0x4d, 0x60, 0x26, 0xe4, 0x90, 0x03, 0x38, 0xf0, 0xe5, 0x4b, 0x04} }, +{ 0x98e0, 16, {0xff, 0x05, 0x53, 0xe5, 0x53, 0xac, 0x52, 0x70, 0x02, 0x05, 0x52, 0x14, 0xf5, 0x82, 0x8c, 0x83} }, +{ 0x98f0, 16, {0xef, 0xf0, 0x85, 0x53, 0x82, 0x85, 0x52, 0x83, 0xe5, 0x4d, 0xf0, 0x02, 0x99, 0x9e, 0x05, 0x4b} }, +{ 0x9900, 16, {0xe5, 0x4b, 0xd3, 0x94, 0x03, 0x50, 0x03, 0x02, 0x98, 0x54, 0x02, 0x99, 0x9e, 0xe4, 0x90, 0x03} }, +{ 0x9910, 16, {0x59, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0x74, 0x10, 0xf0, 0xa3, 0x74} }, +{ 0x9920, 16, {0x1b, 0xf0, 0xa3, 0x74, 0x29, 0xf0, 0x7e, 0x03, 0x7f, 0x59, 0x12, 0x80, 0x00, 0xef, 0x64, 0x08} }, +{ 0x9930, 16, {0x60, 0x6c, 0xe4, 0x90, 0x03, 0x38, 0xf0, 0x80, 0x65, 0xe4, 0x90, 0x03, 0x59, 0xf0, 0xa3, 0xf0} }, +{ 0x9940, 16, {0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0x74, 0x10, 0xf0, 0xa3, 0xe5, 0x52, 0xf0, 0xa3, 0xe5} }, +{ 0x9950, 16, {0x53, 0xf0, 0x7e, 0x03, 0x7f, 0x59, 0x12, 0x19, 0xc1, 0xef, 0x64, 0x08, 0x60, 0x40, 0xe4, 0x90} }, +{ 0x9960, 16, {0x03, 0x38, 0xf0, 0x80, 0x39, 0xe4, 0x90, 0x03, 0x59, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0} }, +{ 0x9970, 16, {0xa3, 0xf0, 0xa3, 0x74, 0x10, 0xf0, 0xe5, 0x51, 0x24, 0x02, 0x90, 0x03, 0x60, 0xf0, 0xe4, 0x35} }, +{ 0x9980, 16, {0x50, 0x90, 0x03, 0x5f, 0xf0, 0x7e, 0x03, 0x7f, 0x59, 0x12, 0x80, 0x00, 0xef, 0x64, 0x08, 0x60} }, +{ 0x9990, 16, {0x0d, 0xe4, 0x90, 0x03, 0x38, 0xf0, 0x80, 0x06, 0x90, 0x03, 0x38, 0x74, 0x01, 0xf0, 0x90, 0x01} }, +{ 0x99a0, 16, {0xc0, 0xe4, 0xf0, 0xa3, 0x74, 0x0a, 0xf0, 0x90, 0x01, 0xc0, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x70} }, +{ 0x99b0, 16, {0xf6, 0x7e, 0x03, 0x7f, 0x35, 0x75, 0x60, 0x00, 0x75, 0x5f, 0x00, 0x75, 0x5e, 0x00, 0x75, 0x5d} }, +{ 0x99c0, 11, {0x00, 0x7d, 0x24, 0x12, 0x8e, 0x0c, 0xe4, 0x90, 0x02, 0xaf, 0xf0} }, +{ 0x99cb, 1, {0x22} }, +{ 0x99cc, 16, {0xe4, 0xff, 0x74, 0xf8, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe0, 0x70, 0x03, 0x02} }, +{ 0x99dc, 16, {0x9a, 0x6f, 0x74, 0x36, 0x2f, 0xf8, 0xe6, 0x20, 0xe5, 0x03, 0x02, 0x9a, 0x6f, 0xef, 0x75, 0xf0} }, +{ 0x99ec, 16, {0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xad, 0x82, 0xfc, 0xf5, 0x83, 0xe5, 0x82} }, +{ 0x99fc, 16, {0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0xe0, 0x54, 0x60, 0x64, 0x60, 0x70, 0x63} }, +{ 0x9a0c, 16, {0xef, 0x25, 0xe0, 0x24, 0xef, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe4, 0x75, 0xf0, 0x01} }, +{ 0x9a1c, 16, {0x12, 0x9b, 0xce, 0x85, 0xf0, 0x82, 0xf5, 0x83, 0xe0, 0x8d, 0x82, 0x8c, 0x83, 0xf0, 0x74, 0xf8} }, +{ 0x9a2c, 16, {0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe0, 0x14, 0xf0, 0x70, 0x36, 0xef, 0x25, 0xe0} }, +{ 0x9a3c, 16, {0x24, 0xc7, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe4, 0xf0, 0xef, 0x25, 0xe0, 0xfe, 0xc3} }, +{ 0x9a4c, 16, {0x74, 0x0c, 0x9e, 0x75, 0xf0, 0x40, 0xa4, 0x24, 0x40, 0xf5, 0x82, 0xe5, 0xf0, 0x34, 0x7b, 0xad} }, +{ 0x9a5c, 16, {0x82, 0xfc, 0xef, 0x25, 0xe0, 0x24, 0xef, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xec, 0xf0} }, +{ 0x9a6c, 12, {0xa3, 0xed, 0xf0, 0x0f, 0xef, 0x64, 0x04, 0x60, 0x03, 0x02, 0x99, 0xce} }, +{ 0x9a78, 1, {0x22} }, +{ 0x9a79, 16, {0xe7, 0x09, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x46, 0xe7, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x3e} }, +{ 0x9a89, 16, {0x88, 0x82, 0x8c, 0x83, 0xe7, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x32, 0xe3, 0x09, 0xf6, 0x08} }, +{ 0x9a99, 16, {0xdf, 0xfa, 0x80, 0x78, 0xe3, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x70, 0x88, 0x82, 0x8c, 0x83} }, +{ 0x9aa9, 16, {0xe3, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x64, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf6, 0x08} }, +{ 0x9ab9, 16, {0xdf, 0xfa, 0x80, 0x58, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x4c} }, +{ 0x9ac9, 16, {0x80, 0xd2, 0x80, 0xfa, 0x80, 0xc6, 0x80, 0xd4, 0x80, 0x69, 0x80, 0xf2, 0x80, 0x33, 0x80, 0x10} }, +{ 0x9ad9, 16, {0x80, 0xa6, 0x80, 0xea, 0x80, 0x9a, 0x80, 0xa8, 0x80, 0xda, 0x80, 0xe2, 0x80, 0xca, 0x80, 0x33} }, +{ 0x9ae9, 16, {0x89, 0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83} }, +{ 0x9af9, 16, {0xcc, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xe9, 0xde, 0xe7, 0x80} }, +{ 0x9b09, 16, {0x0d, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf6, 0x08, 0xdf, 0xf9, 0xec, 0xfa, 0xa9, 0xf0} }, +{ 0x9b19, 16, {0xed, 0xfb, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc} }, +{ 0x9b29, 16, {0xc5, 0x83, 0xcc, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xea, 0xde} }, +{ 0x9b39, 16, {0xe8, 0x80, 0xdb, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf2, 0x08, 0xdf, 0xf9, 0x80, 0xcc} }, +{ 0x9b49, 16, {0x88, 0xf0, 0xed, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xc2, 0xf5, 0x82, 0xeb, 0x24, 0x02, 0xb4} }, +{ 0x9b59, 16, {0x04, 0x00, 0x50, 0xb8, 0x23, 0x23, 0x45, 0x82, 0xf5, 0x82, 0xef, 0x4e, 0x60, 0xae, 0xef, 0x60} }, +{ 0x9b69, 9, {0x01, 0x0e, 0xe5, 0x82, 0x23, 0x90, 0x9a, 0xc9, 0x73} }, +{ 0x9b72, 16, {0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, 0xfe, 0x02} }, +{ 0x9b82, 9, {0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22} }, +{ 0x9b8b, 16, {0xbb, 0x01, 0x0c, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50} }, +{ 0x9b9b, 16, {0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22} }, +{ 0x9bab, 13, {0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22} }, +{ 0x9bb8, 16, {0xc5, 0xf0, 0xf8, 0xa3, 0xe0, 0x28, 0xf0, 0xc5, 0xf0, 0xf8, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x02} }, +{ 0x9bc8, 6, {0x15, 0x83, 0xe0, 0x38, 0xf0, 0x22} }, +{ 0x9bce, 16, {0xa3, 0xf8, 0xe0, 0xc5, 0xf0, 0x25, 0xf0, 0xf0, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x02, 0x15, 0x83} }, +{ 0x9bde, 6, {0xe0, 0xc8, 0x38, 0xf0, 0xe8, 0x22} }, +{ 0x9be4, 16, {0xbb, 0x01, 0x10, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0xf5, 0xf0} }, +{ 0x9bf4, 16, {0xa3, 0xe0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 0xf8, 0x86, 0xf0, 0x08, 0xe6, 0x22, 0xbb, 0xfe} }, +{ 0x9c04, 16, {0x0a, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0xf5, 0xf0, 0x08, 0xe2, 0x22, 0xe5, 0x83, 0x2a, 0xf5, 0x83} }, +{ 0x9c14, 8, {0xe9, 0x93, 0xf5, 0xf0, 0xa3, 0xe9, 0x93, 0x22} }, +{ 0x9c1c, 16, {0x75, 0xf0, 0x08, 0x75, 0x82, 0x00, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xcd, 0x33, 0xcd, 0xcc} }, +{ 0x9c2c, 16, {0x33, 0xcc, 0xc5, 0x82, 0x33, 0xc5, 0x82, 0x9b, 0xed, 0x9a, 0xec, 0x99, 0xe5, 0x82, 0x98, 0x40} }, +{ 0x9c3c, 16, {0x0c, 0xf5, 0x82, 0xee, 0x9b, 0xfe, 0xed, 0x9a, 0xfd, 0xec, 0x99, 0xfc, 0x0f, 0xd5, 0xf0, 0xd6} }, +{ 0x9c4c, 16, {0xe4, 0xce, 0xfb, 0xe4, 0xcd, 0xfa, 0xe4, 0xcc, 0xf9, 0xa8, 0x82, 0x22, 0xb8, 0x00, 0xc1, 0xb9} }, +{ 0x9c5c, 16, {0x00, 0x59, 0xba, 0x00, 0x2d, 0xec, 0x8b, 0xf0, 0x84, 0xcf, 0xce, 0xcd, 0xfc, 0xe5, 0xf0, 0xcb} }, +{ 0x9c6c, 16, {0xf9, 0x78, 0x18, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xec, 0x33, 0xfc, 0xeb} }, +{ 0x9c7c, 16, {0x33, 0xfb, 0x10, 0xd7, 0x03, 0x99, 0x40, 0x04, 0xeb, 0x99, 0xfb, 0x0f, 0xd8, 0xe5, 0xe4, 0xf9} }, +{ 0x9c8c, 16, {0xfa, 0x22, 0x78, 0x18, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xec, 0x33, 0xfc} }, +{ 0x9c9c, 16, {0xc9, 0x33, 0xc9, 0x10, 0xd7, 0x05, 0x9b, 0xe9, 0x9a, 0x40, 0x07, 0xec, 0x9b, 0xfc, 0xe9, 0x9a} }, +{ 0x9cac, 16, {0xf9, 0x0f, 0xd8, 0xe0, 0xe4, 0xc9, 0xfa, 0xe4, 0xcc, 0xfb, 0x22, 0x75, 0xf0, 0x10, 0xef, 0x2f} }, +{ 0x9cbc, 16, {0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xcc, 0x33, 0xcc, 0xc8, 0x33, 0xc8, 0x10, 0xd7, 0x07} }, +{ 0x9ccc, 16, {0x9b, 0xec, 0x9a, 0xe8, 0x99, 0x40, 0x0a, 0xed, 0x9b, 0xfd, 0xec, 0x9a, 0xfc, 0xe8, 0x99, 0xf8} }, +{ 0x9cdc, 14, {0x0f, 0xd5, 0xf0, 0xda, 0xe4, 0xcd, 0xfb, 0xe4, 0xcc, 0xfa, 0xe4, 0xc8, 0xf9, 0x22} }, +{ 0x9cea, 16, {0xeb, 0x9f, 0xf5, 0xf0, 0xea, 0x9e, 0x42, 0xf0, 0xe9, 0x9d, 0x42, 0xf0, 0xe8, 0x9c, 0x45, 0xf0} }, +{ 0x9cfa, 1, {0x22} }, +{ 0x9cfb, 16, {0xe8, 0x60, 0x0f, 0xec, 0xc3, 0x13, 0xfc, 0xed, 0x13, 0xfd, 0xee, 0x13, 0xfe, 0xef, 0x13, 0xff} }, +{ 0x9d0b, 3, {0xd8, 0xf1, 0x22} }, +{ 0x9d0e, 16, {0x08, 0x08, 0x08, 0xe6, 0xcf, 0x2f, 0xf6, 0x18, 0xe6, 0xce, 0x3e, 0xf6, 0x18, 0xe6, 0xcd, 0x3d} }, +{ 0x9d1e, 7, {0xf6, 0x18, 0xe6, 0xcc, 0x3c, 0xf6, 0x22} }, +{ 0x9d25, 12, {0xec, 0xf0, 0xa3, 0xed, 0xf0, 0xa3, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x22} }, +{ 0x9d31, 16, {0xa8, 0x82, 0x85, 0x83, 0xf0, 0xd0, 0x83, 0xd0, 0x82, 0x12, 0x9d, 0x48, 0x12, 0x9d, 0x48, 0x12} }, +{ 0x9d41, 16, {0x9d, 0x48, 0x12, 0x9d, 0x48, 0xe4, 0x73, 0xe4, 0x93, 0xa3, 0xc5, 0x83, 0xc5, 0xf0, 0xc5, 0x83} }, +{ 0x9d51, 16, {0xc8, 0xc5, 0x82, 0xc8, 0xf0, 0xa3, 0xc5, 0x83, 0xc5, 0xf0, 0xc5, 0x83, 0xc8, 0xc5, 0x82, 0xc8} }, +{ 0x9d61, 1, {0x22} }, +{ 0xffff, 0, {0x00} } +}; + +#ifdef DEBUG +static const struct whiteheat_hex_record whiteheat_loader[] = { +{ 0x0000, 3, {0x02, 0x09, 0x8d} }, +{ 0x0033, 3, {0x02, 0x0e, 0x70} }, +{ 0x0043, 3, {0x02, 0x0b, 0x00} }, +{ 0x004b, 3, {0x02, 0x05, 0xb3} }, +{ 0x0100, 16, {0x90, 0x7f, 0xa5, 0xe0, 0x54, 0x10, 0xff, 0xc4, 0x54, 0x0f, 0x44, 0x50, 0xf5, 0x0f, 0x13, 0xe4} }, +{ 0x0110, 16, {0x33, 0xf5, 0x11, 0x90, 0x7f, 0xe9, 0xe0, 0x24, 0x5e, 0xb4, 0x07, 0x00, 0x40, 0x03, 0x02, 0x03} }, +{ 0x0120, 16, {0x7c, 0x90, 0x01, 0x28, 0xf8, 0x28, 0x28, 0x73, 0x02, 0x01, 0xbc, 0x02, 0x01, 0xbc, 0x02, 0x01} }, +{ 0x0130, 16, {0x91, 0x02, 0x01, 0x3d, 0x02, 0x01, 0x53, 0x02, 0x01, 0x6f, 0x02, 0x01, 0x9a, 0x90, 0x7f, 0x00} }, +{ 0x0140, 16, {0xe5, 0x11, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0} }, +{ 0x0150, 16, {0x02, 0x03, 0x7c, 0x90, 0x7f, 0x92, 0xe0, 0xff, 0xc4, 0x54, 0x0f, 0x90, 0x7f, 0x00, 0xf0, 0x90} }, +{ 0x0160, 16, {0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x02, 0x03, 0x7c, 0x12} }, +{ 0x0170, 16, {0x0a, 0x89, 0x50, 0x07, 0xe4, 0x90, 0x7f, 0x00, 0xf0, 0x80, 0x06, 0x90, 0x7f, 0x00, 0x74, 0x0f} }, +{ 0x0180, 16, {0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x02, 0x03} }, +{ 0x0190, 16, {0x7c, 0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x0f, 0x02, 0x03, 0x7c, 0x90, 0x7f, 0x00, 0x74, 0x07, 0xf0} }, +{ 0x01a0, 16, {0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x7f, 0xe8, 0x7e} }, +{ 0x01b0, 16, {0x03, 0x12, 0x0d, 0xd5, 0xd2, 0x06, 0x12, 0x0d, 0x0d, 0x02, 0x03, 0x7c, 0x90, 0x7f, 0xea, 0xe0} }, +{ 0x01c0, 16, {0x75, 0x29, 0x00, 0xf5, 0x2a, 0xa3, 0xe0, 0xfe, 0xe4, 0xee, 0x42, 0x29, 0x90, 0x7f, 0xee, 0xe0} }, +{ 0x01d0, 16, {0x75, 0x2b, 0x00, 0xf5, 0x2c, 0xa3, 0xe0, 0xfe, 0xe4, 0xee, 0x42, 0x2b, 0x90, 0x7f, 0xe8, 0xe0} }, +{ 0x01e0, 16, {0x64, 0xc0, 0x60, 0x03, 0x02, 0x02, 0xc9, 0xe5, 0x2c, 0x45, 0x2b, 0x70, 0x03, 0x02, 0x03, 0x7c} }, +{ 0x01f0, 16, {0xc3, 0xe5, 0x2c, 0x94, 0x40, 0xe5, 0x2b, 0x94, 0x00, 0x50, 0x08, 0x85, 0x2b, 0x2d, 0x85, 0x2c} }, +{ 0x0200, 16, {0x2e, 0x80, 0x06, 0x75, 0x2d, 0x00, 0x75, 0x2e, 0x40, 0x90, 0x7f, 0xe9, 0xe0, 0x64, 0xa3, 0x70} }, +{ 0x0210, 16, {0x34, 0xf5, 0x31, 0xf5, 0x32, 0xc3, 0xe5, 0x32, 0x95, 0x2e, 0xe5, 0x31, 0x95, 0x2d, 0x50, 0x5c} }, +{ 0x0220, 16, {0xe5, 0x2a, 0x25, 0x32, 0xf5, 0x82, 0xe5, 0x31, 0x35, 0x29, 0xf5, 0x83, 0xe0, 0xff, 0x74, 0x00} }, +{ 0x0230, 16, {0x25, 0x32, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xef, 0xf0, 0x05, 0x32, 0xe5, 0x32, 0x70} }, +{ 0x0240, 16, {0x02, 0x05, 0x31, 0x80, 0xd0, 0xe4, 0xf5, 0x31, 0xf5, 0x32, 0xc3, 0xe5, 0x32, 0x95, 0x2e, 0xe5} }, +{ 0x0250, 16, {0x31, 0x95, 0x2d, 0x50, 0x18, 0x74, 0x00, 0x25, 0x32, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83} }, +{ 0x0260, 16, {0x74, 0xcd, 0xf0, 0x05, 0x32, 0xe5, 0x32, 0x70, 0x02, 0x05, 0x31, 0x80, 0xdd, 0xaf, 0x2a, 0xae} }, +{ 0x0270, 16, {0x29, 0xad, 0x2e, 0x7a, 0x7f, 0x79, 0x00, 0x7b, 0x00, 0x12, 0x0b, 0xf4, 0x90, 0x7f, 0xb5, 0xe5} }, +{ 0x0280, 16, {0x2e, 0xf0, 0xe5, 0x2e, 0x25, 0x2a, 0xf5, 0x2a, 0xe5, 0x2d, 0x35, 0x29, 0xf5, 0x29, 0xc3, 0xe5} }, +{ 0x0290, 16, {0x2c, 0x95, 0x2e, 0xf5, 0x2c, 0xe5, 0x2b, 0x95, 0x2d, 0xf5, 0x2b, 0x90, 0x7f, 0x92, 0xe0, 0xff} }, +{ 0x02a0, 16, {0xc4, 0x54, 0x0f, 0x75, 0x2f, 0x00, 0xf5, 0x30, 0xd3, 0x94, 0x00, 0xe5, 0x2f, 0x94, 0x00, 0x50} }, +{ 0x02b0, 16, {0x0c, 0x90, 0x7f, 0xb4, 0xe0, 0x20, 0xe1, 0x03, 0x02, 0x01, 0xe7, 0x80, 0xf4, 0x90, 0x7f, 0xb4} }, +{ 0x02c0, 16, {0xe0, 0x20, 0xe2, 0x03, 0x02, 0x01, 0xe7, 0x80, 0xf4, 0x90, 0x7f, 0xe8, 0xe0, 0x64, 0x40, 0x60} }, +{ 0x02d0, 16, {0x03, 0x02, 0x03, 0x7c, 0xe5, 0x2c, 0x45, 0x2b, 0x70, 0x03, 0x02, 0x03, 0x7c, 0xe4, 0x90, 0x7f} }, +{ 0x02e0, 16, {0xc5, 0xf0, 0x90, 0x7f, 0x92, 0xe0, 0xff, 0xc4, 0x54, 0x0f, 0x75, 0x2f, 0x00, 0xf5, 0x30, 0xd3} }, +{ 0x02f0, 16, {0x94, 0x00, 0xe5, 0x2f, 0x94, 0x00, 0x50, 0x09, 0x90, 0x7f, 0xc4, 0xe0, 0x30, 0xe1, 0x09, 0x80} }, +{ 0x0300, 16, {0xf7, 0x90, 0x7f, 0xb4, 0xe0, 0x20, 0xe3, 0xf9, 0x90, 0x7f, 0xc5, 0xe0, 0x75, 0x2d, 0x00, 0xf5} }, +{ 0x0310, 16, {0x2e, 0x90, 0x7f, 0xe9, 0xe0, 0x64, 0xa3, 0x70, 0x38, 0x90, 0x20, 0x6b, 0xf0, 0xf5, 0x31, 0xf5} }, +{ 0x0320, 16, {0x32, 0xc3, 0xe5, 0x32, 0x95, 0x2e, 0xe5, 0x31, 0x95, 0x2d, 0x50, 0x34, 0x74, 0xc0, 0x25, 0x32} }, +{ 0x0330, 16, {0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x2a, 0x25, 0x32, 0xf5, 0x82, 0xe5} }, +{ 0x0340, 16, {0x31, 0x35, 0x29, 0xf5, 0x83, 0xef, 0xf0, 0x05, 0x32, 0xe5, 0x32, 0x70, 0x02, 0x05, 0x31, 0x80} }, +{ 0x0350, 16, {0xd0, 0xaf, 0x2a, 0xae, 0x29, 0xad, 0x2e, 0x7a, 0x7e, 0x79, 0xc0, 0x7b, 0xc0, 0x12, 0x0c, 0x80} }, +{ 0x0360, 16, {0xe5, 0x2e, 0x25, 0x2a, 0xf5, 0x2a, 0xe5, 0x2d, 0x35, 0x29, 0xf5, 0x29, 0xc3, 0xe5, 0x2c, 0x95} }, +{ 0x0370, 13, {0x2e, 0xf5, 0x2c, 0xe5, 0x2b, 0x95, 0x2d, 0xf5, 0x2b, 0x02, 0x02, 0xd4, 0xc3} }, +{ 0x037d, 1, {0x22} }, +{ 0x037e, 16, {0x90, 0x7f, 0xe9, 0xe0, 0x70, 0x03, 0x02, 0x04, 0x56, 0x14, 0x70, 0x03, 0x02, 0x04, 0xd2, 0x24} }, +{ 0x038e, 16, {0xfe, 0x70, 0x03, 0x02, 0x05, 0x46, 0x24, 0xfb, 0x70, 0x03, 0x02, 0x04, 0x50, 0x14, 0x70, 0x03} }, +{ 0x039e, 16, {0x02, 0x04, 0x4a, 0x14, 0x70, 0x03, 0x02, 0x04, 0x3e, 0x14, 0x70, 0x03, 0x02, 0x04, 0x44, 0x24} }, +{ 0x03ae, 16, {0x05, 0x60, 0x03, 0x02, 0x05, 0x9a, 0x12, 0x0e, 0x7b, 0x40, 0x03, 0x02, 0x05, 0xab, 0x90, 0x7f} }, +{ 0x03be, 16, {0xeb, 0xe0, 0x24, 0xfe, 0x60, 0x16, 0x14, 0x60, 0x40, 0x24, 0x02, 0x70, 0x69, 0x74, 0x11, 0x90} }, +{ 0x03ce, 16, {0x7f, 0xd4, 0xf0, 0x74, 0x00, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xea, 0xe0} }, +{ 0x03de, 16, {0xff, 0x12, 0x0b, 0x58, 0x8b, 0x26, 0x8a, 0x27, 0x89, 0x28, 0xea, 0x49, 0x60, 0x11, 0xae, 0x02} }, +{ 0x03ee, 16, {0xee, 0x90, 0x7f, 0xd4, 0xf0, 0xaf, 0x01, 0xef, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x05, 0xab, 0x90} }, +{ 0x03fe, 16, {0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xea, 0xe0, 0xff, 0x12, 0x0c} }, +{ 0x040e, 16, {0x3f, 0x8b, 0x26, 0x8a, 0x27, 0x89, 0x28, 0xea, 0x49, 0x60, 0x11, 0xae, 0x02, 0xee, 0x90, 0x7f} }, +{ 0x041e, 16, {0xd4, 0xf0, 0xaf, 0x01, 0xef, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xb4, 0xe0} }, +{ 0x042e, 16, {0x44, 0x01, 0xf0, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0xab} }, +{ 0x043e, 16, {0x12, 0x0e, 0x52, 0x02, 0x05, 0xab, 0x12, 0x0e, 0x60, 0x02, 0x05, 0xab, 0x12, 0x0a, 0xf7, 0x02} }, +{ 0x044e, 16, {0x05, 0xab, 0x12, 0x08, 0xf1, 0x02, 0x05, 0xab, 0x12, 0x0e, 0x7d, 0x40, 0x03, 0x02, 0x05, 0xab} }, +{ 0x045e, 16, {0x90, 0x7f, 0xe8, 0xe0, 0x24, 0x7f, 0x60, 0x24, 0x14, 0x60, 0x31, 0x24, 0x02, 0x70, 0x5b, 0xa2} }, +{ 0x046e, 16, {0x00, 0xe4, 0x33, 0xff, 0x25, 0xe0, 0xff, 0xa2, 0x02, 0xe4, 0x33, 0x4f, 0x90, 0x7f, 0x00, 0xf0} }, +{ 0x047e, 16, {0xe4, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0xab, 0xe4, 0x90, 0x7f, 0x00} }, +{ 0x048e, 16, {0xf0, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xec, 0xe0} }, +{ 0x049e, 16, {0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4} }, +{ 0x04ae, 16, {0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe0, 0x54, 0xfd, 0x90, 0x7f, 0x00, 0xf0, 0xe4, 0xa3} }, +{ 0x04be, 16, {0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01} }, +{ 0x04ce, 16, {0xf0, 0x02, 0x05, 0xab, 0x12, 0x0e, 0x7f, 0x40, 0x03, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xe8, 0xe0} }, +{ 0x04de, 16, {0x24, 0xfe, 0x60, 0x1d, 0x24, 0x02, 0x60, 0x03, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xea, 0xe0, 0xb4} }, +{ 0x04ee, 16, {0x01, 0x05, 0xc2, 0x00, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05} }, +{ 0x04fe, 16, {0xab, 0x90, 0x7f, 0xea, 0xe0, 0x70, 0x38, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4} }, +{ 0x050e, 16, {0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f} }, +{ 0x051e, 16, {0xf5, 0x83, 0xe4, 0xf0, 0x90, 0x7f, 0xec, 0xe0, 0x54, 0x80, 0xff, 0x13, 0x13, 0x13, 0x54, 0x1f} }, +{ 0x052e, 16, {0xff, 0xe0, 0x54, 0x07, 0x2f, 0x90, 0x7f, 0xd7, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x6e, 0x90} }, +{ 0x053e, 16, {0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x65, 0x12, 0x0e, 0x81, 0x50, 0x60, 0x90, 0x7f, 0xe8} }, +{ 0x054e, 16, {0xe0, 0x24, 0xfe, 0x60, 0x18, 0x24, 0x02, 0x70, 0x54, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x04} }, +{ 0x055e, 16, {0xd2, 0x00, 0x80, 0x49, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x40, 0x90, 0x7f, 0xea} }, +{ 0x056e, 16, {0xe0, 0x70, 0x20, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0} }, +{ 0x057e, 16, {0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0x74, 0x01} }, +{ 0x058e, 16, {0xf0, 0x80, 0x1a, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x11, 0xe4, 0x90, 0x20, 0x6a} }, +{ 0x059e, 16, {0xf0, 0x12, 0x01, 0x00, 0x50, 0x07, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xb4} }, +{ 0x05ae, 4, {0xe0, 0x44, 0x02, 0xf0} }, +{ 0x05b2, 1, {0x22} }, +{ 0x05b3, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xc0} }, +{ 0x05c3, 16, {0xd0, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x06, 0xc0, 0x07, 0x90, 0x7f, 0xa5} }, +{ 0x05d3, 16, {0xe0, 0x30, 0xe2, 0x06, 0x75, 0x0d, 0x06, 0x02, 0x06, 0x7f, 0x90, 0x7f, 0xa5, 0xe0, 0x20, 0xe1} }, +{ 0x05e3, 16, {0x0c, 0xe5, 0x0d, 0x64, 0x02, 0x60, 0x06, 0x75, 0x0d, 0x07, 0x02, 0x06, 0x7f, 0xaf, 0x0d, 0xef} }, +{ 0x05f3, 16, {0x24, 0xfe, 0x60, 0x48, 0x14, 0x60, 0x2c, 0x24, 0xfe, 0x60, 0x77, 0x24, 0x04, 0x60, 0x03, 0x02} }, +{ 0x0603, 16, {0x06, 0x7f, 0xab, 0x09, 0xaa, 0x0a, 0xa9, 0x0b, 0xaf, 0x0c, 0x05, 0x0c, 0x8f, 0x82, 0x75, 0x83} }, +{ 0x0613, 16, {0x00, 0x12, 0x07, 0x85, 0x90, 0x7f, 0xa6, 0xf0, 0xe5, 0x0c, 0x65, 0x08, 0x70, 0x5e, 0x75, 0x0d} }, +{ 0x0623, 16, {0x05, 0x80, 0x59, 0x90, 0x7f, 0xa6, 0xe0, 0xab, 0x09, 0xaa, 0x0a, 0xa9, 0x0b, 0xae, 0x0c, 0x8e} }, +{ 0x0633, 16, {0x82, 0x75, 0x83, 0x00, 0x12, 0x07, 0xb2, 0x75, 0x0d, 0x02, 0x80, 0x40, 0xe5, 0x08, 0x24, 0xfe} }, +{ 0x0643, 16, {0xb5, 0x0c, 0x07, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x20, 0xf0, 0xe5, 0x08, 0x14, 0xb5, 0x0c, 0x0a} }, +{ 0x0653, 16, {0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0xe4, 0xf5, 0x0d, 0x90, 0x7f, 0xa6, 0xe0, 0xab, 0x09} }, +{ 0x0663, 16, {0xaa, 0x0a, 0xa9, 0x0b, 0xae, 0x0c, 0x8e, 0x82, 0x75, 0x83, 0x00, 0x12, 0x07, 0xb2, 0x05, 0x0c} }, +{ 0x0673, 16, {0x80, 0x0a, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0xe4, 0xf5, 0x0d, 0x53, 0x91, 0xdf, 0xd0} }, +{ 0x0683, 16, {0x07, 0xd0, 0x06, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0xd0, 0xd0, 0x86, 0xd0} }, +{ 0x0693, 10, {0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x069d, 16, {0xc2, 0x04, 0xd2, 0x05, 0xe4, 0xf5, 0x25, 0xc2, 0x03, 0xc2, 0x00, 0xc2, 0x02, 0xc2, 0x01, 0x12} }, +{ 0x06ad, 16, {0x0e, 0x74, 0xd2, 0xe8, 0x43, 0xd8, 0x20, 0x90, 0x7f, 0xab, 0x74, 0xff, 0xf0, 0x90, 0x7f, 0xa9} }, +{ 0x06bd, 16, {0xf0, 0x90, 0x7f, 0xaa, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f, 0x95, 0xe0, 0x44, 0xc0, 0xf0, 0x90} }, +{ 0x06cd, 16, {0x7f, 0x93, 0x74, 0x30, 0xf0, 0x12, 0x0a, 0x19, 0x75, 0x24, 0x48, 0x75, 0x23, 0x92, 0x75, 0x22} }, +{ 0x06dd, 16, {0x00, 0x75, 0x21, 0x00, 0xe4, 0xff, 0xfe, 0x7e, 0x05, 0x90, 0x20, 0x68, 0x74, 0x01, 0xf0, 0xa3} }, +{ 0x06ed, 16, {0xde, 0xfc, 0x7e, 0x00, 0x7f, 0x05, 0x90, 0x7f, 0xaf, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xae} }, +{ 0x06fd, 16, {0xe0, 0x44, 0x0d, 0xf0, 0xd2, 0xaf, 0x12, 0x0e, 0x68, 0x30, 0x01, 0x0a, 0xe4, 0x90, 0x20, 0x69} }, +{ 0x070d, 16, {0xf0, 0x12, 0x03, 0x7e, 0xc2, 0x01, 0x30, 0x04, 0x1a, 0x12, 0x0e, 0x77, 0x50, 0x13, 0x12, 0x09} }, +{ 0x071d, 16, {0x00, 0x30, 0x00, 0x07, 0x90, 0x7f, 0xd6, 0xe0, 0x30, 0xe7, 0xf3, 0x12, 0x0d, 0x8b, 0x12, 0x0e} }, +{ 0x072d, 16, {0x79, 0xc2, 0x03, 0x7f, 0xff, 0x7e, 0xff, 0x7d, 0xff, 0x7c, 0xff, 0x78, 0x21, 0x12, 0x08, 0x1d} }, +{ 0x073d, 16, {0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00, 0x78, 0x00, 0xc3, 0x12, 0x08, 0x0c, 0x70, 0x1b, 0x75, 0x24} }, +{ 0x074d, 16, {0x48, 0x75, 0x23, 0x92, 0xf5, 0x22, 0xf5, 0x21, 0x63, 0x25, 0xff, 0x90, 0x20, 0x68, 0xe5, 0x25} }, +{ 0x075d, 14, {0xf0, 0xa3, 0x74, 0x01, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0x12, 0x08, 0xff, 0x80, 0x9b} }, +{ 0x076b, 1, {0x22} }, +{ 0x076c, 16, {0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, 0xfe, 0x02} }, +{ 0x077c, 9, {0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22} }, +{ 0x0785, 16, {0xbb, 0x01, 0x0c, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50} }, +{ 0x0795, 16, {0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22} }, +{ 0x07a5, 13, {0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22} }, +{ 0x07b2, 16, {0xf8, 0xbb, 0x01, 0x0d, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe8, 0xf0} }, +{ 0x07c2, 16, {0x22, 0x50, 0x06, 0xe9, 0x25, 0x82, 0xc8, 0xf6, 0x22, 0xbb, 0xfe, 0x05, 0xe9, 0x25, 0x82, 0xc8} }, +{ 0x07d2, 2, {0xf2, 0x22} }, +{ 0x07d4, 16, {0xbb, 0x01, 0x10, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0xf5, 0xf0} }, +{ 0x07e4, 16, {0xa3, 0xe0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 0xf8, 0x86, 0xf0, 0x08, 0xe6, 0x22, 0xbb, 0xfe} }, +{ 0x07f4, 16, {0x0a, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0xf5, 0xf0, 0x08, 0xe2, 0x22, 0xe5, 0x83, 0x2a, 0xf5, 0x83} }, +{ 0x0804, 8, {0xe9, 0x93, 0xf5, 0xf0, 0xa3, 0xe9, 0x93, 0x22} }, +{ 0x080c, 16, {0xeb, 0x9f, 0xf5, 0xf0, 0xea, 0x9e, 0x42, 0xf0, 0xe9, 0x9d, 0x42, 0xf0, 0xe8, 0x9c, 0x45, 0xf0} }, +{ 0x081c, 1, {0x22} }, +{ 0x081d, 16, {0x08, 0x08, 0x08, 0xe6, 0x2f, 0xff, 0xf6, 0x18, 0xe6, 0x3e, 0xfe, 0xf6, 0x18, 0xe6, 0x3d, 0xfd} }, +{ 0x082d, 7, {0xf6, 0x18, 0xe6, 0x3c, 0xfc, 0xf6, 0x22} }, +{ 0x0834, 4, {0x8c, 0x34, 0x8d, 0x35} }, +{ 0x0838, 16, {0x90, 0x7f, 0x95, 0xe0, 0x44, 0xc0, 0xf0, 0xe4, 0xf5, 0x36, 0xf5, 0x37, 0xc3, 0xe5, 0x37, 0x95} }, +{ 0x0848, 16, {0x35, 0xe5, 0x36, 0x95, 0x34, 0x50, 0x69, 0xef, 0x25, 0x37, 0xf5, 0x82, 0xe5, 0x36, 0x3e, 0xf5} }, +{ 0x0858, 16, {0x83, 0x74, 0xff, 0xf0, 0xf4, 0x60, 0x02, 0xc3, 0x22, 0xef, 0x25, 0x37, 0xf5, 0x82, 0xe5, 0x36} }, +{ 0x0868, 16, {0x3e, 0xf5, 0x83, 0xe4, 0xf0, 0x60, 0x02, 0xc3, 0x22, 0xef, 0x25, 0x37, 0xf5, 0x82, 0xe5, 0x36} }, +{ 0x0878, 16, {0x3e, 0xf5, 0x83, 0x74, 0xaa, 0xf0, 0x64, 0xaa, 0x60, 0x02, 0xc3, 0x22, 0xef, 0x25, 0x37, 0xf5} }, +{ 0x0888, 16, {0x82, 0xe5, 0x36, 0x3e, 0xf5, 0x83, 0x74, 0x55, 0xf0, 0x64, 0x55, 0x60, 0x02, 0xc3, 0x22, 0xad} }, +{ 0x0898, 16, {0x37, 0xe5, 0x37, 0x2f, 0xf5, 0x82, 0xe5, 0x36, 0x3e, 0xf5, 0x83, 0xed, 0xf0, 0xfc, 0xac, 0x05} }, +{ 0x08a8, 16, {0xed, 0x6c, 0x60, 0x02, 0xc3, 0x22, 0x05, 0x37, 0xe5, 0x37, 0x70, 0x02, 0x05, 0x36, 0x80, 0x8c} }, +{ 0x08b8, 16, {0xe4, 0xf5, 0x36, 0xf5, 0x37, 0xc3, 0xe5, 0x37, 0x95, 0x35, 0xe5, 0x36, 0x95, 0x34, 0x50, 0x27} }, +{ 0x08c8, 16, {0xef, 0x25, 0x37, 0xf5, 0x82, 0xe5, 0x36, 0x3e, 0xf5, 0x83, 0xe0, 0x65, 0x37, 0x60, 0x02, 0xc3} }, +{ 0x08d8, 16, {0x22, 0xef, 0x25, 0x37, 0xf5, 0x82, 0xe5, 0x36, 0x3e, 0xf5, 0x83, 0xe4, 0xf0, 0x05, 0x37, 0xe5} }, +{ 0x08e8, 8, {0x37, 0x70, 0x02, 0x05, 0x36, 0x80, 0xce, 0xd3} }, +{ 0x08f0, 1, {0x22} }, +{ 0x08f1, 14, {0x90, 0x7f, 0x00, 0xe5, 0x10, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0xd3, 0x22} }, +{ 0x08ff, 1, {0x22} }, +{ 0x0900, 9, {0x90, 0x7f, 0xd6, 0xe0, 0x44, 0x80, 0xf0, 0x80, 0x74} }, +{ 0x097d, 16, {0x43, 0x87, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22} }, +{ 0x098d, 12, {0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x3a, 0x02, 0x09, 0xd4} }, +{ 0x0999, 16, {0x02, 0x06, 0x9d, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2} }, +{ 0x09a9, 16, {0x08, 0xdf, 0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33} }, +{ 0x09b9, 16, {0xc4, 0x54, 0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf} }, +{ 0x09c9, 16, {0xe4, 0x80, 0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x0e, 0x2d, 0xe4, 0x7e} }, +{ 0x09d9, 16, {0x01, 0x93, 0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93} }, +{ 0x09e9, 16, {0xa3, 0x60, 0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3} }, +{ 0x09f9, 16, {0xfa, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca} }, +{ 0x0a09, 16, {0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe} }, +{ 0x0a19, 16, {0xe4, 0x90, 0x7f, 0x9c, 0xf0, 0x7f, 0x0a, 0xfe, 0x12, 0x0d, 0xd5, 0x90, 0x7f, 0x96, 0x74, 0x89} }, +{ 0x0a29, 16, {0xf0, 0x90, 0x7f, 0x9c, 0x74, 0xcf, 0xf0, 0x7f, 0xf4, 0x7e, 0x01, 0x12, 0x0d, 0xd5, 0x90, 0x7f} }, +{ 0x0a39, 16, {0x96, 0xe0, 0x54, 0xfe, 0xf0, 0x7f, 0x0a, 0x7e, 0x00, 0x12, 0x0d, 0xd5, 0x7f, 0x05, 0x7e, 0x00} }, +{ 0x0a49, 16, {0x12, 0x0d, 0xd5, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x02, 0xf0, 0xe0, 0x54, 0x7f, 0xf0, 0x7f, 0x05} }, +{ 0x0a59, 16, {0x7e, 0x00, 0x12, 0x0d, 0xd5, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x05, 0x7e, 0x00} }, +{ 0x0a69, 16, {0x12, 0x0d, 0xd5, 0x90, 0x7f, 0x96, 0xe0, 0x54, 0xbf, 0xf0, 0x7f, 0x32, 0x7e, 0x00, 0x12, 0x0d} }, +{ 0x0a79, 16, {0xd5, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x32, 0x7e, 0x00, 0x12, 0x0d, 0xd5, 0x22} }, +{ 0x0a89, 16, {0x75, 0x33, 0x01, 0xe5, 0x33, 0x60, 0x1b, 0x7f, 0x01, 0x12, 0x0e, 0x18, 0x7f, 0x00, 0x7e, 0x0e} }, +{ 0x0a99, 16, {0x7d, 0x00, 0x7c, 0x01, 0x12, 0x08, 0x34, 0xe4, 0x33, 0xf5, 0x33, 0x70, 0x05, 0x7f, 0x0f, 0x12} }, +{ 0x0aa9, 16, {0x0e, 0x18, 0xe5, 0x33, 0x60, 0x1b, 0x7f, 0x02, 0x12, 0x0e, 0x18, 0x7f, 0x00, 0x7e, 0x80, 0x7d} }, +{ 0x0ab9, 16, {0x00, 0x7c, 0x80, 0x12, 0x08, 0x34, 0xe4, 0x33, 0xf5, 0x33, 0x70, 0x05, 0x7f, 0x0f, 0x12, 0x0e} }, +{ 0x0ac9, 16, {0x18, 0xe5, 0x33, 0x60, 0x1b, 0x7f, 0x03, 0x12, 0x0e, 0x18, 0x7f, 0x00, 0x7e, 0x20, 0x7d, 0x40} }, +{ 0x0ad9, 16, {0x7c, 0x5b, 0x12, 0x08, 0x34, 0xe4, 0x33, 0xf5, 0x33, 0x70, 0x05, 0x7f, 0x0f, 0x12, 0x0e, 0x18} }, +{ 0x0ae9, 13, {0xe5, 0x33, 0x60, 0x05, 0xe4, 0xff, 0x12, 0x0e, 0x18, 0xe5, 0x33, 0x24, 0xff} }, +{ 0x0af6, 1, {0x22} }, +{ 0x0af7, 8, {0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x10, 0xd3, 0x22} }, +{ 0x0aff, 1, {0x32} }, +{ 0x0b00, 16, {0x02, 0x0d, 0xa5, 0x00, 0x02, 0x0d, 0xec, 0x00, 0x02, 0x0d, 0x70, 0x00, 0x02, 0x0d, 0xbd, 0x00} }, +{ 0x0b10, 16, {0x02, 0x0e, 0x02, 0x00, 0x02, 0x0a, 0xff, 0x00, 0x02, 0x0e, 0x83, 0x00, 0x02, 0x0e, 0x84, 0x00} }, +{ 0x0b20, 16, {0x02, 0x0e, 0x85, 0x00, 0x02, 0x0e, 0x86, 0x00, 0x02, 0x0e, 0x87, 0x00, 0x02, 0x0e, 0x88, 0x00} }, +{ 0x0b30, 16, {0x02, 0x0e, 0x89, 0x00, 0x02, 0x0e, 0x8a, 0x00, 0x02, 0x0e, 0x8b, 0x00, 0x02, 0x0e, 0x8c, 0x00} }, +{ 0x0b40, 16, {0x02, 0x0e, 0x8d, 0x00, 0x02, 0x0e, 0x8e, 0x00, 0x02, 0x0e, 0x8f, 0x00, 0x02, 0x0e, 0x90, 0x00} }, +{ 0x0b50, 8, {0x02, 0x0e, 0x91, 0x00, 0x02, 0x0e, 0x92, 0x00} }, +{ 0x0b58, 16, {0xe4, 0xfe, 0x75, 0x2b, 0xff, 0x75, 0x2c, 0x11, 0x75, 0x2d, 0x12, 0xab, 0x2b, 0xaa, 0x2c, 0xa9} }, +{ 0x0b68, 16, {0x2d, 0x90, 0x00, 0x01, 0x12, 0x07, 0x85, 0x64, 0x02, 0x70, 0x2d, 0xad, 0x06, 0x0e, 0xed, 0xb5} }, +{ 0x0b78, 16, {0x07, 0x01, 0x22, 0x90, 0x00, 0x02, 0x12, 0x07, 0xd4, 0x85, 0xf0, 0x29, 0xf5, 0x2a, 0x62, 0x29} }, +{ 0x0b88, 16, {0xe5, 0x29, 0x62, 0x2a, 0xe5, 0x2a, 0x62, 0x29, 0x29, 0xfd, 0xe5, 0x29, 0x3a, 0xa9, 0x05, 0x75} }, +{ 0x0b98, 14, {0x2b, 0xff, 0xf5, 0x2c, 0x89, 0x2d, 0x80, 0xc3, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} }, +{ 0x0ba6, 1, {0x22} }, +{ 0x0ba7, 6, {0xab, 0x07, 0xaa, 0x06, 0xac, 0x05} }, +{ 0x0bad, 16, {0xe4, 0xfd, 0xe5, 0x11, 0x60, 0x11, 0xea, 0xff, 0xae, 0x05, 0x0d, 0xee, 0x24, 0x10, 0xf5, 0x82} }, +{ 0x0bbd, 16, {0xe4, 0x34, 0x0f, 0xf5, 0x83, 0xef, 0xf0, 0xeb, 0xae, 0x05, 0x0d, 0x74, 0x10, 0x2e, 0xf5, 0x82} }, +{ 0x0bcd, 16, {0xe4, 0x34, 0x0f, 0xf5, 0x83, 0xeb, 0xf0, 0xaf, 0x05, 0x0d, 0x74, 0x10, 0x2f, 0xf5, 0x82, 0xe4} }, +{ 0x0bdd, 16, {0x34, 0x0f, 0xf5, 0x83, 0xec, 0xf0, 0xaf, 0x0f, 0x7a, 0x0f, 0x7b, 0x10, 0x12, 0x0d, 0x51, 0x7f} }, +{ 0x0bed, 6, {0x0a, 0x7e, 0x00, 0x12, 0x0d, 0xd5} }, +{ 0x0bf3, 1, {0x22} }, +{ 0x0bf4, 10, {0x8e, 0x33, 0x8f, 0x34, 0x8d, 0x35, 0x8a, 0x36, 0x8b, 0x37} }, +{ 0x0bfe, 16, {0xe4, 0xfd, 0xf5, 0x38, 0xe5, 0x11, 0x60, 0x12, 0xe5, 0x33, 0xff, 0xae, 0x05, 0x0d, 0xee, 0x24} }, +{ 0x0c0e, 16, {0x13, 0xf5, 0x82, 0xe4, 0x34, 0x0f, 0xf5, 0x83, 0xef, 0xf0, 0xe5, 0x34, 0xae, 0x05, 0x0d, 0x74} }, +{ 0x0c1e, 16, {0x13, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x0f, 0xf5, 0x83, 0xe5, 0x34, 0xf0, 0xaf, 0x0f, 0x7a, 0x0f} }, +{ 0x0c2e, 16, {0x7b, 0x13, 0x12, 0x0d, 0x51, 0xaf, 0x0f, 0xad, 0x35, 0xab, 0x37, 0xaa, 0x36, 0x12, 0x0d, 0x32} }, +{ 0x0c3e, 1, {0x22} }, +{ 0x0c3f, 2, {0x8f, 0x29} }, +{ 0x0c41, 16, {0xe4, 0xf5, 0x2a, 0x75, 0x2b, 0xff, 0x75, 0x2c, 0x11, 0x75, 0x2d, 0x32, 0xab, 0x2b, 0xaa, 0x2c} }, +{ 0x0c51, 16, {0xa9, 0x2d, 0x90, 0x00, 0x01, 0x12, 0x07, 0x85, 0xb4, 0x03, 0x1d, 0xaf, 0x2a, 0x05, 0x2a, 0xef} }, +{ 0x0c61, 16, {0xb5, 0x29, 0x01, 0x22, 0x12, 0x07, 0x6c, 0x7e, 0x00, 0x29, 0xff, 0xee, 0x3a, 0xa9, 0x07, 0x75} }, +{ 0x0c71, 14, {0x2b, 0xff, 0xf5, 0x2c, 0x89, 0x2d, 0x80, 0xd4, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} }, +{ 0x0c7f, 1, {0x22} }, +{ 0x0c80, 10, {0x8e, 0x33, 0x8f, 0x34, 0x8d, 0x35, 0x8a, 0x36, 0x8b, 0x37} }, +{ 0x0c8a, 16, {0xe4, 0xf5, 0x38, 0xe5, 0x38, 0xc3, 0x95, 0x35, 0x50, 0x20, 0x05, 0x34, 0xe5, 0x34, 0xae, 0x33} }, +{ 0x0c9a, 16, {0x70, 0x02, 0x05, 0x33, 0x14, 0xff, 0xe5, 0x37, 0x25, 0x38, 0xf5, 0x82, 0xe4, 0x35, 0x36, 0xf5} }, +{ 0x0caa, 10, {0x83, 0xe0, 0xfd, 0x12, 0x0b, 0xa7, 0x05, 0x38, 0x80, 0xd9} }, +{ 0x0cb4, 1, {0x22} }, +{ 0x0cb5, 16, {0xa9, 0x07, 0xe5, 0x0d, 0x70, 0x25, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0, 0xe9, 0x25, 0xe0} }, +{ 0x0cc5, 16, {0x44, 0x01, 0x90, 0x7f, 0xa6, 0xf0, 0x8d, 0x08, 0xaf, 0x03, 0xa9, 0x07, 0x75, 0x09, 0x01, 0x8a} }, +{ 0x0cd5, 13, {0x0a, 0x89, 0x0b, 0xe4, 0xf5, 0x0c, 0x75, 0x0d, 0x03, 0xd3, 0x22, 0xc3, 0x22} }, +{ 0x0ce2, 16, {0xa9, 0x07, 0xe5, 0x0d, 0x70, 0x23, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0, 0xe9, 0x25, 0xe0} }, +{ 0x0cf2, 16, {0x90, 0x7f, 0xa6, 0xf0, 0x8d, 0x08, 0xaf, 0x03, 0xa9, 0x07, 0x75, 0x09, 0x01, 0x8a, 0x0a, 0x89} }, +{ 0x0d02, 11, {0x0b, 0xe4, 0xf5, 0x0c, 0x75, 0x0d, 0x01, 0xd3, 0x22, 0xc3, 0x22} }, +{ 0x0d0d, 16, {0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x30, 0x06, 0x04, 0xe0, 0x44} }, +{ 0x0d1d, 16, {0x02, 0xf0, 0x7f, 0xd0, 0x7e, 0x07, 0x12, 0x0d, 0xd5, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xf7, 0xf0} }, +{ 0x0d2d, 5, {0xe0, 0x44, 0x04, 0xf0, 0x22} }, +{ 0x0d32, 16, {0x12, 0x0c, 0xb5, 0xe5, 0x0d, 0x24, 0xfa, 0x60, 0x10, 0x14, 0x60, 0x07, 0x24, 0x07, 0x70, 0xf3} }, +{ 0x0d42, 15, {0x7f, 0x08, 0x22, 0xe4, 0xf5, 0x0d, 0x7f, 0x07, 0x22, 0xe4, 0xf5, 0x0d, 0x7f, 0x06, 0x22} }, +{ 0x0d51, 16, {0x12, 0x0c, 0xe2, 0xe5, 0x0d, 0x24, 0xfa, 0x60, 0x10, 0x14, 0x60, 0x07, 0x24, 0x07, 0x70, 0xf3} }, +{ 0x0d61, 15, {0x7f, 0x08, 0x22, 0xe4, 0xf5, 0x0d, 0x7f, 0x07, 0x22, 0xe4, 0xf5, 0x0d, 0x7f, 0x06, 0x22} }, +{ 0x0d70, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x90, 0x7f, 0xc4, 0xe4, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f} }, +{ 0x0d80, 11, {0xab, 0x74, 0x04, 0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0d8b, 16, {0x90, 0x7f, 0xd6, 0xe0, 0x30, 0xe7, 0x12, 0xe0, 0x44, 0x01, 0xf0, 0x7f, 0x14, 0x7e, 0x00, 0x12} }, +{ 0x0d9b, 10, {0x0d, 0xd5, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xfe, 0xf0, 0x22} }, +{ 0x0da5, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xd2, 0x01, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x01} }, +{ 0x0db5, 8, {0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0dbd, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xd2, 0x03, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x08} }, +{ 0x0dcd, 8, {0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0dd5, 16, {0x8e, 0x39, 0x8f, 0x3a, 0xe5, 0x3a, 0x15, 0x3a, 0xae, 0x39, 0x70, 0x02, 0x15, 0x39, 0x4e, 0x60} }, +{ 0x0de5, 7, {0x05, 0x12, 0x0e, 0x41, 0x80, 0xee, 0x22} }, +{ 0x0dec, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x02, 0xf0, 0xd0} }, +{ 0x0dfc, 6, {0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0e02, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x10, 0xf0, 0xd0} }, +{ 0x0e12, 6, {0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0e18, 16, {0xae, 0x07, 0x7f, 0x21, 0x7d, 0x01, 0x74, 0x00, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x0f, 0xab, 0x82} }, +{ 0x0e28, 5, {0xfa, 0x12, 0x0d, 0x51, 0x22} }, +{ 0x0e2d, 16, {0x50, 0x0f, 0x00, 0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x98, 0x88, 0x83, 0xc6} }, +{ 0x0e3d, 3, {0xa1, 0x86, 0x8e} }, +{ 0x0e40, 1, {0x00} }, +{ 0x0e41, 16, {0x74, 0x00, 0xf5, 0x86, 0x90, 0xfd, 0xa5, 0x7c, 0x05, 0xa3, 0xe5, 0x82, 0x45, 0x83, 0x70, 0xf9} }, +{ 0x0e51, 1, {0x22} }, +{ 0x0e52, 14, {0x90, 0x7f, 0x00, 0xe5, 0x0e, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0xd3, 0x22} }, +{ 0x0e60, 8, {0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x0e, 0xd3, 0x22} }, +{ 0x0e68, 8, {0xe4, 0xf5, 0x0d, 0xd2, 0xe9, 0xd2, 0xaf, 0x22} }, +{ 0x0e70, 4, {0x53, 0xd8, 0xef, 0x32} }, +{ 0x0e74, 3, {0xd2, 0x00, 0x22} }, +{ 0x0e77, 2, {0xd3, 0x22} }, +{ 0x0e79, 2, {0xd3, 0x22} }, +{ 0x0e7b, 2, {0xd3, 0x22} }, +{ 0x0e7d, 2, {0xd3, 0x22} }, +{ 0x0e7f, 2, {0xd3, 0x22} }, +{ 0x0e81, 2, {0xd3, 0x22} }, +{ 0x0e83, 1, {0x32} }, +{ 0x0e84, 1, {0x32} }, +{ 0x0e85, 1, {0x32} }, +{ 0x0e86, 1, {0x32} }, +{ 0x0e87, 1, {0x32} }, +{ 0x0e88, 1, {0x32} }, +{ 0x0e89, 1, {0x32} }, +{ 0x0e8a, 1, {0x32} }, +{ 0x0e8b, 1, {0x32} }, +{ 0x0e8c, 1, {0x32} }, +{ 0x0e8d, 1, {0x32} }, +{ 0x0e8e, 1, {0x32} }, +{ 0x0e8f, 1, {0x32} }, +{ 0x0e90, 1, {0x32} }, +{ 0x0e91, 1, {0x32} }, +{ 0x0e92, 1, {0x32} }, +{ 0x1100, 16, {0x12, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x47, 0x05, 0x10, 0x27, 0x01, 0x00, 0x01, 0x02} }, +{ 0x1110, 16, {0x00, 0x01, 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x03, 0xa0, 0x00, 0x09, 0x04, 0x00, 0x00, 0x02} }, +{ 0x1120, 16, {0xff, 0x00, 0x00, 0x04, 0x07, 0x05, 0x82, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x02, 0x02, 0x40} }, +{ 0x1130, 16, {0x00, 0x00, 0x04, 0x03, 0x09, 0x04, 0x26, 0x03, 0x41, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x68, 0x00} }, +{ 0x1140, 16, {0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x43, 0x00, 0x68, 0x00, 0x69, 0x00, 0x70, 0x00, 0x73, 0x00} }, +{ 0x1150, 16, {0x2c, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x2e, 0x00, 0x28, 0x03, 0x46, 0x00} }, +{ 0x1160, 16, {0x69, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x77, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00} }, +{ 0x1170, 16, {0x46, 0x00, 0x72, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x57, 0x00, 0x6f, 0x00, 0x72, 0x00} }, +{ 0x1180, 16, {0x6b, 0x00, 0x73, 0x00, 0x2a, 0x03, 0x43, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x69, 0x00} }, +{ 0x1190, 16, {0x67, 0x00, 0x75, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00} }, +{ 0x11a0, 16, {0x20, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x22, 0x03} }, +{ 0x11b0, 16, {0x49, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x66, 0x00, 0x61, 0x00, 0x63, 0x00} }, +{ 0x11c0, 16, {0x65, 0x00, 0x20, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00} }, +{ 0x11d0, 2, {0x00, 0x00} }, +{ 0xffff, 0, {0x00} } +}; + +#else + +static const struct whiteheat_hex_record whiteheat_loader[] = { +{ 0x0000, 3, {0x02, 0x09, 0x8d} }, +{ 0x0033, 3, {0x02, 0x08, 0xfb} }, +{ 0x0043, 3, {0x02, 0x0b, 0x00} }, +{ 0x004b, 3, {0x02, 0x05, 0xaa} }, +{ 0x0100, 16, {0x90, 0x7f, 0xa5, 0xe0, 0x54, 0x10, 0xff, 0xc4, 0x54, 0x0f, 0x44, 0x50, 0xf5, 0x0f, 0x13, 0xe4} }, +{ 0x0110, 16, {0x33, 0xf5, 0x11, 0x90, 0x7f, 0xe9, 0xe0, 0x24, 0x5e, 0xb4, 0x07, 0x00, 0x40, 0x03, 0x02, 0x03} }, +{ 0x0120, 16, {0x78, 0x90, 0x01, 0x28, 0xf8, 0x28, 0x28, 0x73, 0x02, 0x01, 0xbc, 0x02, 0x01, 0xbc, 0x02, 0x01} }, +{ 0x0130, 16, {0x91, 0x02, 0x01, 0x3d, 0x02, 0x01, 0x53, 0x02, 0x01, 0x6f, 0x02, 0x01, 0x9a, 0x90, 0x7f, 0x00} }, +{ 0x0140, 16, {0xe5, 0x11, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0} }, +{ 0x0150, 16, {0x02, 0x03, 0x78, 0x90, 0x7f, 0x92, 0xe0, 0xff, 0xc4, 0x54, 0x0f, 0x90, 0x7f, 0x00, 0xf0, 0x90} }, +{ 0x0160, 16, {0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x02, 0x03, 0x78, 0x12} }, +{ 0x0170, 16, {0x0a, 0x89, 0x50, 0x07, 0xe4, 0x90, 0x7f, 0x00, 0xf0, 0x80, 0x06, 0x90, 0x7f, 0x00, 0x74, 0x0f} }, +{ 0x0180, 16, {0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x02, 0x03} }, +{ 0x0190, 16, {0x78, 0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x0f, 0x02, 0x03, 0x78, 0x90, 0x7f, 0x00, 0x74, 0x07, 0xf0} }, +{ 0x01a0, 16, {0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x7f, 0xe8, 0x7e} }, +{ 0x01b0, 16, {0x03, 0x12, 0x0d, 0x94, 0xd2, 0x06, 0x12, 0x0c, 0xcc, 0x02, 0x03, 0x78, 0x90, 0x7f, 0xea, 0xe0} }, +{ 0x01c0, 16, {0x75, 0x28, 0x00, 0xf5, 0x29, 0xa3, 0xe0, 0xfe, 0xe4, 0xee, 0x42, 0x28, 0x90, 0x7f, 0xee, 0xe0} }, +{ 0x01d0, 16, {0x75, 0x2a, 0x00, 0xf5, 0x2b, 0xa3, 0xe0, 0xfe, 0xe4, 0xee, 0x42, 0x2a, 0x90, 0x7f, 0xe8, 0xe0} }, +{ 0x01e0, 16, {0x64, 0xc0, 0x60, 0x03, 0x02, 0x02, 0xc9, 0xe5, 0x2b, 0x45, 0x2a, 0x70, 0x03, 0x02, 0x03, 0x78} }, +{ 0x01f0, 16, {0xc3, 0xe5, 0x2b, 0x94, 0x40, 0xe5, 0x2a, 0x94, 0x00, 0x50, 0x08, 0x85, 0x2a, 0x2c, 0x85, 0x2b} }, +{ 0x0200, 16, {0x2d, 0x80, 0x06, 0x75, 0x2c, 0x00, 0x75, 0x2d, 0x40, 0x90, 0x7f, 0xe9, 0xe0, 0x64, 0xa3, 0x70} }, +{ 0x0210, 16, {0x34, 0xf5, 0x30, 0xf5, 0x31, 0xc3, 0xe5, 0x31, 0x95, 0x2d, 0xe5, 0x30, 0x95, 0x2c, 0x50, 0x5c} }, +{ 0x0220, 16, {0xe5, 0x29, 0x25, 0x31, 0xf5, 0x82, 0xe5, 0x30, 0x35, 0x28, 0xf5, 0x83, 0xe0, 0xff, 0x74, 0x00} }, +{ 0x0230, 16, {0x25, 0x31, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xef, 0xf0, 0x05, 0x31, 0xe5, 0x31, 0x70} }, +{ 0x0240, 16, {0x02, 0x05, 0x30, 0x80, 0xd0, 0xe4, 0xf5, 0x30, 0xf5, 0x31, 0xc3, 0xe5, 0x31, 0x95, 0x2d, 0xe5} }, +{ 0x0250, 16, {0x30, 0x95, 0x2c, 0x50, 0x18, 0x74, 0x00, 0x25, 0x31, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83} }, +{ 0x0260, 16, {0x74, 0xcd, 0xf0, 0x05, 0x31, 0xe5, 0x31, 0x70, 0x02, 0x05, 0x30, 0x80, 0xdd, 0xaf, 0x29, 0xae} }, +{ 0x0270, 16, {0x28, 0xad, 0x2d, 0x7a, 0x7f, 0x79, 0x00, 0x7b, 0x00, 0x12, 0x0b, 0xf4, 0x90, 0x7f, 0xb5, 0xe5} }, +{ 0x0280, 16, {0x2d, 0xf0, 0xe5, 0x2d, 0x25, 0x29, 0xf5, 0x29, 0xe5, 0x2c, 0x35, 0x28, 0xf5, 0x28, 0xc3, 0xe5} }, +{ 0x0290, 16, {0x2b, 0x95, 0x2d, 0xf5, 0x2b, 0xe5, 0x2a, 0x95, 0x2c, 0xf5, 0x2a, 0x90, 0x7f, 0x92, 0xe0, 0xff} }, +{ 0x02a0, 16, {0xc4, 0x54, 0x0f, 0x75, 0x2e, 0x00, 0xf5, 0x2f, 0xd3, 0x94, 0x00, 0xe5, 0x2e, 0x94, 0x00, 0x50} }, +{ 0x02b0, 16, {0x0c, 0x90, 0x7f, 0xb4, 0xe0, 0x20, 0xe1, 0x03, 0x02, 0x01, 0xe7, 0x80, 0xf4, 0x90, 0x7f, 0xb4} }, +{ 0x02c0, 16, {0xe0, 0x20, 0xe2, 0x03, 0x02, 0x01, 0xe7, 0x80, 0xf4, 0x90, 0x7f, 0xe8, 0xe0, 0x64, 0x40, 0x60} }, +{ 0x02d0, 16, {0x03, 0x02, 0x03, 0x78, 0xe5, 0x2b, 0x45, 0x2a, 0x70, 0x03, 0x02, 0x03, 0x78, 0xe4, 0x90, 0x7f} }, +{ 0x02e0, 16, {0xc5, 0xf0, 0x90, 0x7f, 0x92, 0xe0, 0xff, 0xc4, 0x54, 0x0f, 0x75, 0x2e, 0x00, 0xf5, 0x2f, 0xd3} }, +{ 0x02f0, 16, {0x94, 0x00, 0xe5, 0x2e, 0x94, 0x00, 0x50, 0x09, 0x90, 0x7f, 0xc4, 0xe0, 0x30, 0xe1, 0x09, 0x80} }, +{ 0x0300, 16, {0xf7, 0x90, 0x7f, 0xb4, 0xe0, 0x20, 0xe3, 0xf9, 0x90, 0x7f, 0xc5, 0xe0, 0x75, 0x2c, 0x00, 0xf5} }, +{ 0x0310, 16, {0x2d, 0x90, 0x7f, 0xe9, 0xe0, 0x64, 0xa3, 0x70, 0x34, 0xf5, 0x30, 0xf5, 0x31, 0xc3, 0xe5, 0x31} }, +{ 0x0320, 16, {0x95, 0x2d, 0xe5, 0x30, 0x95, 0x2c, 0x50, 0x34, 0x74, 0xc0, 0x25, 0x31, 0xf5, 0x82, 0xe4, 0x34} }, +{ 0x0330, 1, {0x7e} }, +{ 0x0331, 16, {0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x29, 0x25, 0x31, 0xf5, 0x82, 0xe5, 0x30, 0x35, 0x28, 0xf5, 0x83} }, +{ 0x0341, 16, {0xef, 0xf0, 0x05, 0x31, 0xe5, 0x31, 0x70, 0x02, 0x05, 0x30, 0x80, 0xd0, 0xaf, 0x29, 0xae, 0x28} }, +{ 0x0351, 16, {0xad, 0x2d, 0x7a, 0x7e, 0x79, 0xc0, 0x7b, 0xc0, 0x12, 0x0c, 0x3f, 0xe5, 0x2d, 0x25, 0x29, 0xf5} }, +{ 0x0361, 16, {0x29, 0xe5, 0x2c, 0x35, 0x28, 0xf5, 0x28, 0xc3, 0xe5, 0x2b, 0x95, 0x2d, 0xf5, 0x2b, 0xe5, 0x2a} }, +{ 0x0371, 9, {0x95, 0x2c, 0xf5, 0x2a, 0x02, 0x02, 0xd4, 0xc3, 0x22} }, +{ 0x037a, 16, {0x90, 0x7f, 0xe9, 0xe0, 0x70, 0x03, 0x02, 0x04, 0x52, 0x14, 0x70, 0x03, 0x02, 0x04, 0xce, 0x24} }, +{ 0x038a, 16, {0xfe, 0x70, 0x03, 0x02, 0x05, 0x42, 0x24, 0xfb, 0x70, 0x03, 0x02, 0x04, 0x4c, 0x14, 0x70, 0x03} }, +{ 0x039a, 16, {0x02, 0x04, 0x46, 0x14, 0x70, 0x03, 0x02, 0x04, 0x3a, 0x14, 0x70, 0x03, 0x02, 0x04, 0x40, 0x24} }, +{ 0x03aa, 16, {0x05, 0x60, 0x03, 0x02, 0x05, 0x96, 0x12, 0x0e, 0x44, 0x40, 0x03, 0x02, 0x05, 0xa2, 0x90, 0x7f} }, +{ 0x03ba, 16, {0xeb, 0xe0, 0x24, 0xfe, 0x60, 0x16, 0x14, 0x60, 0x40, 0x24, 0x02, 0x70, 0x69, 0x74, 0x11, 0x90} }, +{ 0x03ca, 16, {0x7f, 0xd4, 0xf0, 0x74, 0x00, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xea, 0xe0} }, +{ 0x03da, 16, {0xff, 0x12, 0x0b, 0x58, 0x8b, 0x25, 0x8a, 0x26, 0x89, 0x27, 0xea, 0x49, 0x60, 0x11, 0xae, 0x02} }, +{ 0x03ea, 16, {0xee, 0x90, 0x7f, 0xd4, 0xf0, 0xaf, 0x01, 0xef, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x05, 0xa2, 0x90} }, +{ 0x03fa, 16, {0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xea, 0xe0, 0xff, 0x12, 0x08} }, +{ 0x040a, 16, {0xba, 0x8b, 0x25, 0x8a, 0x26, 0x89, 0x27, 0xea, 0x49, 0x60, 0x11, 0xae, 0x02, 0xee, 0x90, 0x7f} }, +{ 0x041a, 16, {0xd4, 0xf0, 0xaf, 0x01, 0xef, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xb4, 0xe0} }, +{ 0x042a, 16, {0x44, 0x01, 0xf0, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0xa2} }, +{ 0x043a, 16, {0x12, 0x0e, 0x1f, 0x02, 0x05, 0xa2, 0x12, 0x0e, 0x2d, 0x02, 0x05, 0xa2, 0x12, 0x0a, 0xf7, 0x02} }, +{ 0x044a, 16, {0x05, 0xa2, 0x12, 0x0e, 0x11, 0x02, 0x05, 0xa2, 0x12, 0x0e, 0x46, 0x40, 0x03, 0x02, 0x05, 0xa2} }, +{ 0x045a, 16, {0x90, 0x7f, 0xe8, 0xe0, 0x24, 0x7f, 0x60, 0x24, 0x14, 0x60, 0x31, 0x24, 0x02, 0x70, 0x5b, 0xa2} }, +{ 0x046a, 16, {0x00, 0xe4, 0x33, 0xff, 0x25, 0xe0, 0xff, 0xa2, 0x02, 0xe4, 0x33, 0x4f, 0x90, 0x7f, 0x00, 0xf0} }, +{ 0x047a, 16, {0xe4, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0xa2, 0xe4, 0x90, 0x7f, 0x00} }, +{ 0x048a, 16, {0xf0, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xec, 0xe0} }, +{ 0x049a, 16, {0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4} }, +{ 0x04aa, 16, {0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe0, 0x54, 0xfd, 0x90, 0x7f, 0x00, 0xf0, 0xe4, 0xa3} }, +{ 0x04ba, 16, {0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01} }, +{ 0x04ca, 16, {0xf0, 0x02, 0x05, 0xa2, 0x12, 0x0e, 0x48, 0x40, 0x03, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xe8, 0xe0} }, +{ 0x04da, 16, {0x24, 0xfe, 0x60, 0x1d, 0x24, 0x02, 0x60, 0x03, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xea, 0xe0, 0xb4} }, +{ 0x04ea, 16, {0x01, 0x05, 0xc2, 0x00, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05} }, +{ 0x04fa, 16, {0xa2, 0x90, 0x7f, 0xea, 0xe0, 0x70, 0x38, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4} }, +{ 0x050a, 16, {0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f} }, +{ 0x051a, 16, {0xf5, 0x83, 0xe4, 0xf0, 0x90, 0x7f, 0xec, 0xe0, 0x54, 0x80, 0xff, 0x13, 0x13, 0x13, 0x54, 0x1f} }, +{ 0x052a, 16, {0xff, 0xe0, 0x54, 0x07, 0x2f, 0x90, 0x7f, 0xd7, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x69, 0x90} }, +{ 0x053a, 16, {0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x60, 0x12, 0x0e, 0x4a, 0x50, 0x5b, 0x90, 0x7f, 0xe8} }, +{ 0x054a, 16, {0xe0, 0x24, 0xfe, 0x60, 0x18, 0x24, 0x02, 0x70, 0x4f, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x04} }, +{ 0x055a, 16, {0xd2, 0x00, 0x80, 0x44, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x3b, 0x90, 0x7f, 0xea} }, +{ 0x056a, 16, {0xe0, 0x70, 0x20, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0} }, +{ 0x057a, 16, {0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0x74, 0x01} }, +{ 0x058a, 16, {0xf0, 0x80, 0x15, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x0c, 0x12, 0x01, 0x00, 0x50} }, +{ 0x059a, 16, {0x07, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x22} }, +{ 0x05aa, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xc0} }, +{ 0x05ba, 16, {0xd0, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x06, 0xc0, 0x07, 0x90, 0x7f, 0xa5} }, +{ 0x05ca, 16, {0xe0, 0x30, 0xe2, 0x06, 0x75, 0x0d, 0x06, 0x02, 0x06, 0x76, 0x90, 0x7f, 0xa5, 0xe0, 0x20, 0xe1} }, +{ 0x05da, 16, {0x0c, 0xe5, 0x0d, 0x64, 0x02, 0x60, 0x06, 0x75, 0x0d, 0x07, 0x02, 0x06, 0x76, 0xaf, 0x0d, 0xef} }, +{ 0x05ea, 16, {0x24, 0xfe, 0x60, 0x48, 0x14, 0x60, 0x2c, 0x24, 0xfe, 0x60, 0x77, 0x24, 0x04, 0x60, 0x03, 0x02} }, +{ 0x05fa, 16, {0x06, 0x76, 0xab, 0x09, 0xaa, 0x0a, 0xa9, 0x0b, 0xaf, 0x0c, 0x05, 0x0c, 0x8f, 0x82, 0x75, 0x83} }, +{ 0x060a, 16, {0x00, 0x12, 0x08, 0x22, 0x90, 0x7f, 0xa6, 0xf0, 0xe5, 0x0c, 0x65, 0x08, 0x70, 0x5e, 0x75, 0x0d} }, +{ 0x061a, 16, {0x05, 0x80, 0x59, 0x90, 0x7f, 0xa6, 0xe0, 0xab, 0x09, 0xaa, 0x0a, 0xa9, 0x0b, 0xae, 0x0c, 0x8e} }, +{ 0x062a, 16, {0x82, 0x75, 0x83, 0x00, 0x12, 0x08, 0x4f, 0x75, 0x0d, 0x02, 0x80, 0x40, 0xe5, 0x08, 0x24, 0xfe} }, +{ 0x063a, 16, {0xb5, 0x0c, 0x07, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x20, 0xf0, 0xe5, 0x08, 0x14, 0xb5, 0x0c, 0x0a} }, +{ 0x064a, 16, {0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0xe4, 0xf5, 0x0d, 0x90, 0x7f, 0xa6, 0xe0, 0xab, 0x09} }, +{ 0x065a, 16, {0xaa, 0x0a, 0xa9, 0x0b, 0xae, 0x0c, 0x8e, 0x82, 0x75, 0x83, 0x00, 0x12, 0x08, 0x4f, 0x05, 0x0c} }, +{ 0x066a, 16, {0x80, 0x0a, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0xe4, 0xf5, 0x0d, 0x53, 0x91, 0xdf, 0xd0} }, +{ 0x067a, 16, {0x07, 0xd0, 0x06, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0xd0, 0xd0, 0x86, 0xd0} }, +{ 0x068a, 10, {0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0694, 16, {0x8c, 0x33, 0x8d, 0x34, 0x90, 0x7f, 0x95, 0xe0, 0x44, 0xc0, 0xf0, 0xe4, 0xf5, 0x35, 0xf5, 0x36} }, +{ 0x06a4, 16, {0xc3, 0xe5, 0x36, 0x95, 0x34, 0xe5, 0x35, 0x95, 0x33, 0x50, 0x69, 0xef, 0x25, 0x36, 0xf5, 0x82} }, +{ 0x06b4, 16, {0xe5, 0x35, 0x3e, 0xf5, 0x83, 0x74, 0xff, 0xf0, 0xf4, 0x60, 0x02, 0xc3, 0x22, 0xef, 0x25, 0x36} }, +{ 0x06c4, 16, {0xf5, 0x82, 0xe5, 0x35, 0x3e, 0xf5, 0x83, 0xe4, 0xf0, 0x60, 0x02, 0xc3, 0x22, 0xef, 0x25, 0x36} }, +{ 0x06d4, 16, {0xf5, 0x82, 0xe5, 0x35, 0x3e, 0xf5, 0x83, 0x74, 0xaa, 0xf0, 0x64, 0xaa, 0x60, 0x02, 0xc3, 0x22} }, +{ 0x06e4, 16, {0xef, 0x25, 0x36, 0xf5, 0x82, 0xe5, 0x35, 0x3e, 0xf5, 0x83, 0x74, 0x55, 0xf0, 0x64, 0x55, 0x60} }, +{ 0x06f4, 16, {0x02, 0xc3, 0x22, 0xad, 0x36, 0xe5, 0x36, 0x2f, 0xf5, 0x82, 0xe5, 0x35, 0x3e, 0xf5, 0x83, 0xed} }, +{ 0x0704, 16, {0xf0, 0xfc, 0xac, 0x05, 0xed, 0x6c, 0x60, 0x02, 0xc3, 0x22, 0x05, 0x36, 0xe5, 0x36, 0x70, 0x02} }, +{ 0x0714, 16, {0x05, 0x35, 0x80, 0x8c, 0xe4, 0xf5, 0x35, 0xf5, 0x36, 0xc3, 0xe5, 0x36, 0x95, 0x34, 0xe5, 0x35} }, +{ 0x0724, 16, {0x95, 0x33, 0x50, 0x27, 0xef, 0x25, 0x36, 0xf5, 0x82, 0xe5, 0x35, 0x3e, 0xf5, 0x83, 0xe0, 0x65} }, +{ 0x0734, 16, {0x36, 0x60, 0x02, 0xc3, 0x22, 0xef, 0x25, 0x36, 0xf5, 0x82, 0xe5, 0x35, 0x3e, 0xf5, 0x83, 0xe4} }, +{ 0x0744, 13, {0xf0, 0x05, 0x36, 0xe5, 0x36, 0x70, 0x02, 0x05, 0x35, 0x80, 0xce, 0xd3, 0x22} }, +{ 0x0751, 16, {0xc2, 0x04, 0xd2, 0x05, 0xc2, 0x03, 0xc2, 0x00, 0xc2, 0x02, 0xc2, 0x01, 0x12, 0x0e, 0x3d, 0xd2} }, +{ 0x0761, 16, {0xe8, 0x43, 0xd8, 0x20, 0x90, 0x7f, 0xab, 0x74, 0xff, 0xf0, 0x90, 0x7f, 0xa9, 0xf0, 0x90, 0x7f} }, +{ 0x0771, 16, {0xaa, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f, 0x95, 0xe0, 0x44, 0xc0, 0xf0, 0x90, 0x7f, 0x93, 0x74} }, +{ 0x0781, 16, {0x30, 0xf0, 0x12, 0x0a, 0x19, 0x90, 0x7f, 0xaf, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xae, 0xe0} }, +{ 0x0791, 16, {0x44, 0x0d, 0xf0, 0xd2, 0xaf, 0x12, 0x0e, 0x35, 0x20, 0x01, 0x42, 0x75, 0x24, 0x00, 0x75, 0x23} }, +{ 0x07a1, 16, {0x00, 0x75, 0x22, 0x00, 0x75, 0x21, 0x00, 0x7f, 0x48, 0x7e, 0x92, 0x7d, 0x00, 0x7c, 0x00, 0xab} }, +{ 0x07b1, 16, {0x24, 0xaa, 0x23, 0xa9, 0x22, 0xa8, 0x21, 0xc3, 0x12, 0x08, 0xa9, 0x50, 0xdb, 0x20, 0x01, 0xd8} }, +{ 0x07c1, 16, {0x7a, 0x00, 0x79, 0x00, 0x78, 0x00, 0xe5, 0x24, 0x24, 0x01, 0xf5, 0x24, 0xea, 0x35, 0x23, 0xf5} }, +{ 0x07d1, 16, {0x23, 0xe9, 0x35, 0x22, 0xf5, 0x22, 0xe8, 0x35, 0x21, 0xf5, 0x21, 0x80, 0xca, 0x30, 0x01, 0x05} }, +{ 0x07e1, 16, {0x12, 0x03, 0x7a, 0xc2, 0x01, 0x30, 0x04, 0x1a, 0x12, 0x0e, 0x40, 0x50, 0x13, 0x12, 0x09, 0x00} }, +{ 0x07f1, 16, {0x30, 0x00, 0x07, 0x90, 0x7f, 0xd6, 0xe0, 0x30, 0xe7, 0xf3, 0x12, 0x0d, 0x4a, 0x12, 0x0e, 0x42} }, +{ 0x0801, 8, {0xc2, 0x03, 0x12, 0x08, 0xff, 0x80, 0xd6, 0x22} }, +{ 0x0809, 16, {0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, 0xfe, 0x02} }, +{ 0x0819, 9, {0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22} }, +{ 0x0822, 16, {0xbb, 0x01, 0x0c, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50} }, +{ 0x0832, 16, {0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22} }, +{ 0x0842, 13, {0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22} }, +{ 0x084f, 16, {0xf8, 0xbb, 0x01, 0x0d, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe8, 0xf0} }, +{ 0x085f, 16, {0x22, 0x50, 0x06, 0xe9, 0x25, 0x82, 0xc8, 0xf6, 0x22, 0xbb, 0xfe, 0x05, 0xe9, 0x25, 0x82, 0xc8} }, +{ 0x086f, 2, {0xf2, 0x22} }, +{ 0x0871, 16, {0xbb, 0x01, 0x10, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0xf5, 0xf0} }, +{ 0x0881, 16, {0xa3, 0xe0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 0xf8, 0x86, 0xf0, 0x08, 0xe6, 0x22, 0xbb, 0xfe} }, +{ 0x0891, 16, {0x0a, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0xf5, 0xf0, 0x08, 0xe2, 0x22, 0xe5, 0x83, 0x2a, 0xf5, 0x83} }, +{ 0x08a1, 8, {0xe9, 0x93, 0xf5, 0xf0, 0xa3, 0xe9, 0x93, 0x22} }, +{ 0x08a9, 16, {0xeb, 0x9f, 0xf5, 0xf0, 0xea, 0x9e, 0x42, 0xf0, 0xe9, 0x9d, 0x42, 0xf0, 0xe8, 0x9c, 0x45, 0xf0} }, +{ 0x08b9, 1, {0x22} }, +{ 0x08ba, 2, {0x8f, 0x28} }, +{ 0x08bc, 16, {0xe4, 0xf5, 0x29, 0x75, 0x2a, 0xff, 0x75, 0x2b, 0x11, 0x75, 0x2c, 0x32, 0xab, 0x2a, 0xaa, 0x2b} }, +{ 0x08cc, 16, {0xa9, 0x2c, 0x90, 0x00, 0x01, 0x12, 0x08, 0x22, 0xb4, 0x03, 0x1d, 0xaf, 0x29, 0x05, 0x29, 0xef} }, +{ 0x08dc, 16, {0xb5, 0x28, 0x01, 0x22, 0x12, 0x08, 0x09, 0x7e, 0x00, 0x29, 0xff, 0xee, 0x3a, 0xa9, 0x07, 0x75} }, +{ 0x08ec, 14, {0x2a, 0xff, 0xf5, 0x2b, 0x89, 0x2c, 0x80, 0xd4, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} }, +{ 0x08fa, 1, {0x22} }, +{ 0x08fb, 4, {0x53, 0xd8, 0xef, 0x32} }, +{ 0x08ff, 1, {0x22} }, +{ 0x0900, 9, {0x90, 0x7f, 0xd6, 0xe0, 0x44, 0x80, 0xf0, 0x80, 0x74} }, +{ 0x097d, 16, {0x43, 0x87, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22} }, +{ 0x098d, 12, {0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x39, 0x02, 0x09, 0xd4} }, +{ 0x0999, 16, {0x02, 0x07, 0x51, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2} }, +{ 0x09a9, 16, {0x08, 0xdf, 0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33} }, +{ 0x09b9, 16, {0xc4, 0x54, 0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf} }, +{ 0x09c9, 16, {0xe4, 0x80, 0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x0d, 0xec, 0xe4, 0x7e} }, +{ 0x09d9, 16, {0x01, 0x93, 0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93} }, +{ 0x09e9, 16, {0xa3, 0x60, 0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3} }, +{ 0x09f9, 16, {0xfa, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca} }, +{ 0x0a09, 16, {0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe} }, +{ 0x0a19, 16, {0xe4, 0x90, 0x7f, 0x9c, 0xf0, 0x7f, 0x0a, 0xfe, 0x12, 0x0d, 0x94, 0x90, 0x7f, 0x96, 0x74, 0x89} }, +{ 0x0a29, 16, {0xf0, 0x90, 0x7f, 0x9c, 0x74, 0xcf, 0xf0, 0x7f, 0xf4, 0x7e, 0x01, 0x12, 0x0d, 0x94, 0x90, 0x7f} }, +{ 0x0a39, 16, {0x96, 0xe0, 0x54, 0xfe, 0xf0, 0x7f, 0x0a, 0x7e, 0x00, 0x12, 0x0d, 0x94, 0x7f, 0x05, 0x7e, 0x00} }, +{ 0x0a49, 16, {0x12, 0x0d, 0x94, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x02, 0xf0, 0xe0, 0x54, 0x7f, 0xf0, 0x7f, 0x05} }, +{ 0x0a59, 16, {0x7e, 0x00, 0x12, 0x0d, 0x94, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x05, 0x7e, 0x00} }, +{ 0x0a69, 16, {0x12, 0x0d, 0x94, 0x90, 0x7f, 0x96, 0xe0, 0x54, 0xbf, 0xf0, 0x7f, 0x32, 0x7e, 0x00, 0x12, 0x0d} }, +{ 0x0a79, 16, {0x94, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x32, 0x7e, 0x00, 0x12, 0x0d, 0x94, 0x22} }, +{ 0x0a89, 16, {0x75, 0x32, 0x01, 0xe5, 0x32, 0x60, 0x1b, 0x7f, 0x01, 0x12, 0x0d, 0xd7, 0x7f, 0x00, 0x7e, 0x0e} }, +{ 0x0a99, 16, {0x7d, 0x00, 0x7c, 0x01, 0x12, 0x06, 0x94, 0xe4, 0x33, 0xf5, 0x32, 0x70, 0x05, 0x7f, 0x0f, 0x12} }, +{ 0x0aa9, 16, {0x0d, 0xd7, 0xe5, 0x32, 0x60, 0x1b, 0x7f, 0x02, 0x12, 0x0d, 0xd7, 0x7f, 0x00, 0x7e, 0x80, 0x7d} }, +{ 0x0ab9, 16, {0x00, 0x7c, 0x80, 0x12, 0x06, 0x94, 0xe4, 0x33, 0xf5, 0x32, 0x70, 0x05, 0x7f, 0x0f, 0x12, 0x0d} }, +{ 0x0ac9, 16, {0xd7, 0xe5, 0x32, 0x60, 0x1b, 0x7f, 0x03, 0x12, 0x0d, 0xd7, 0x7f, 0x00, 0x7e, 0x20, 0x7d, 0x40} }, +{ 0x0ad9, 16, {0x7c, 0x5b, 0x12, 0x06, 0x94, 0xe4, 0x33, 0xf5, 0x32, 0x70, 0x05, 0x7f, 0x0f, 0x12, 0x0d, 0xd7} }, +{ 0x0ae9, 14, {0xe5, 0x32, 0x60, 0x05, 0xe4, 0xff, 0x12, 0x0d, 0xd7, 0xe5, 0x32, 0x24, 0xff, 0x22} }, +{ 0x0af7, 8, {0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x10, 0xd3, 0x22} }, +{ 0x0aff, 1, {0x32} }, +{ 0x0b00, 16, {0x02, 0x0d, 0x64, 0x00, 0x02, 0x0d, 0xab, 0x00, 0x02, 0x0d, 0x2f, 0x00, 0x02, 0x0d, 0x7c, 0x00} }, +{ 0x0b10, 16, {0x02, 0x0d, 0xc1, 0x00, 0x02, 0x0a, 0xff, 0x00, 0x02, 0x0e, 0x4c, 0x00, 0x02, 0x0e, 0x4d, 0x00} }, +{ 0x0b20, 16, {0x02, 0x0e, 0x4e, 0x00, 0x02, 0x0e, 0x4f, 0x00, 0x02, 0x0e, 0x50, 0x00, 0x02, 0x0e, 0x51, 0x00} }, +{ 0x0b30, 16, {0x02, 0x0e, 0x52, 0x00, 0x02, 0x0e, 0x53, 0x00, 0x02, 0x0e, 0x54, 0x00, 0x02, 0x0e, 0x55, 0x00} }, +{ 0x0b40, 16, {0x02, 0x0e, 0x56, 0x00, 0x02, 0x0e, 0x57, 0x00, 0x02, 0x0e, 0x58, 0x00, 0x02, 0x0e, 0x59, 0x00} }, +{ 0x0b50, 8, {0x02, 0x0e, 0x5a, 0x00, 0x02, 0x0e, 0x5b, 0x00} }, +{ 0x0b58, 16, {0xe4, 0xfe, 0x75, 0x2a, 0xff, 0x75, 0x2b, 0x11, 0x75, 0x2c, 0x12, 0xab, 0x2a, 0xaa, 0x2b, 0xa9} }, +{ 0x0b68, 16, {0x2c, 0x90, 0x00, 0x01, 0x12, 0x08, 0x22, 0x64, 0x02, 0x70, 0x2d, 0xad, 0x06, 0x0e, 0xed, 0xb5} }, +{ 0x0b78, 16, {0x07, 0x01, 0x22, 0x90, 0x00, 0x02, 0x12, 0x08, 0x71, 0x85, 0xf0, 0x28, 0xf5, 0x29, 0x62, 0x28} }, +{ 0x0b88, 16, {0xe5, 0x28, 0x62, 0x29, 0xe5, 0x29, 0x62, 0x28, 0x29, 0xfd, 0xe5, 0x28, 0x3a, 0xa9, 0x05, 0x75} }, +{ 0x0b98, 14, {0x2a, 0xff, 0xf5, 0x2b, 0x89, 0x2c, 0x80, 0xc3, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} }, +{ 0x0ba6, 1, {0x22} }, +{ 0x0ba7, 16, {0xab, 0x07, 0xaa, 0x06, 0xac, 0x05, 0xe4, 0xfd, 0xe5, 0x11, 0x60, 0x11, 0xea, 0xff, 0xae, 0x05} }, +{ 0x0bb7, 16, {0x0d, 0xee, 0x24, 0x10, 0xf5, 0x82, 0xe4, 0x34, 0x0f, 0xf5, 0x83, 0xef, 0xf0, 0xeb, 0xae, 0x05} }, +{ 0x0bc7, 16, {0x0d, 0x74, 0x10, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x0f, 0xf5, 0x83, 0xeb, 0xf0, 0xaf, 0x05, 0x0d} }, +{ 0x0bd7, 16, {0x74, 0x10, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x0f, 0xf5, 0x83, 0xec, 0xf0, 0xaf, 0x0f, 0x7a, 0x0f} }, +{ 0x0be7, 13, {0x7b, 0x10, 0x12, 0x0d, 0x10, 0x7f, 0x0a, 0x7e, 0x00, 0x12, 0x0d, 0x94, 0x22} }, +{ 0x0bf4, 16, {0x8e, 0x32, 0x8f, 0x33, 0x8d, 0x34, 0x8a, 0x35, 0x8b, 0x36, 0xe4, 0xfd, 0xf5, 0x37, 0xe5, 0x11} }, +{ 0x0c04, 16, {0x60, 0x12, 0xe5, 0x32, 0xff, 0xae, 0x05, 0x0d, 0xee, 0x24, 0x13, 0xf5, 0x82, 0xe4, 0x34, 0x0f} }, +{ 0x0c14, 16, {0xf5, 0x83, 0xef, 0xf0, 0xe5, 0x33, 0xae, 0x05, 0x0d, 0x74, 0x13, 0x2e, 0xf5, 0x82, 0xe4, 0x34} }, +{ 0x0c24, 16, {0x0f, 0xf5, 0x83, 0xe5, 0x33, 0xf0, 0xaf, 0x0f, 0x7a, 0x0f, 0x7b, 0x13, 0x12, 0x0d, 0x10, 0xaf} }, +{ 0x0c34, 11, {0x0f, 0xad, 0x34, 0xab, 0x36, 0xaa, 0x35, 0x12, 0x0c, 0xf1, 0x22} }, +{ 0x0c3f, 16, {0x8e, 0x32, 0x8f, 0x33, 0x8d, 0x34, 0x8a, 0x35, 0x8b, 0x36, 0xe4, 0xf5, 0x37, 0xe5, 0x37, 0xc3} }, +{ 0x0c4f, 16, {0x95, 0x34, 0x50, 0x20, 0x05, 0x33, 0xe5, 0x33, 0xae, 0x32, 0x70, 0x02, 0x05, 0x32, 0x14, 0xff} }, +{ 0x0c5f, 16, {0xe5, 0x36, 0x25, 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x35, 0xf5, 0x83, 0xe0, 0xfd, 0x12, 0x0b, 0xa7} }, +{ 0x0c6f, 5, {0x05, 0x37, 0x80, 0xd9, 0x22} }, +{ 0x0c74, 16, {0xa9, 0x07, 0xe5, 0x0d, 0x70, 0x25, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0, 0xe9, 0x25, 0xe0} }, +{ 0x0c84, 16, {0x44, 0x01, 0x90, 0x7f, 0xa6, 0xf0, 0x8d, 0x08, 0xaf, 0x03, 0xa9, 0x07, 0x75, 0x09, 0x01, 0x8a} }, +{ 0x0c94, 13, {0x0a, 0x89, 0x0b, 0xe4, 0xf5, 0x0c, 0x75, 0x0d, 0x03, 0xd3, 0x22, 0xc3, 0x22} }, +{ 0x0ca1, 16, {0xa9, 0x07, 0xe5, 0x0d, 0x70, 0x23, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0, 0xe9, 0x25, 0xe0} }, +{ 0x0cb1, 16, {0x90, 0x7f, 0xa6, 0xf0, 0x8d, 0x08, 0xaf, 0x03, 0xa9, 0x07, 0x75, 0x09, 0x01, 0x8a, 0x0a, 0x89} }, +{ 0x0cc1, 11, {0x0b, 0xe4, 0xf5, 0x0c, 0x75, 0x0d, 0x01, 0xd3, 0x22, 0xc3, 0x22} }, +{ 0x0ccc, 16, {0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x30, 0x06, 0x04, 0xe0, 0x44} }, +{ 0x0cdc, 16, {0x02, 0xf0, 0x7f, 0xd0, 0x7e, 0x07, 0x12, 0x0d, 0x94, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xf7, 0xf0} }, +{ 0x0cec, 5, {0xe0, 0x44, 0x04, 0xf0, 0x22} }, +{ 0x0cf1, 16, {0x12, 0x0c, 0x74, 0xe5, 0x0d, 0x24, 0xfa, 0x60, 0x10, 0x14, 0x60, 0x07, 0x24, 0x07, 0x70, 0xf3} }, +{ 0x0d01, 15, {0x7f, 0x08, 0x22, 0xe4, 0xf5, 0x0d, 0x7f, 0x07, 0x22, 0xe4, 0xf5, 0x0d, 0x7f, 0x06, 0x22} }, +{ 0x0d10, 16, {0x12, 0x0c, 0xa1, 0xe5, 0x0d, 0x24, 0xfa, 0x60, 0x10, 0x14, 0x60, 0x07, 0x24, 0x07, 0x70, 0xf3} }, +{ 0x0d20, 15, {0x7f, 0x08, 0x22, 0xe4, 0xf5, 0x0d, 0x7f, 0x07, 0x22, 0xe4, 0xf5, 0x0d, 0x7f, 0x06, 0x22} }, +{ 0x0d2f, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x90, 0x7f, 0xc4, 0xe4, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f} }, +{ 0x0d3f, 11, {0xab, 0x74, 0x04, 0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0d4a, 16, {0x90, 0x7f, 0xd6, 0xe0, 0x30, 0xe7, 0x12, 0xe0, 0x44, 0x01, 0xf0, 0x7f, 0x14, 0x7e, 0x00, 0x12} }, +{ 0x0d5a, 10, {0x0d, 0x94, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xfe, 0xf0, 0x22} }, +{ 0x0d64, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xd2, 0x01, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x01} }, +{ 0x0d74, 8, {0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0d7c, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xd2, 0x03, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x08} }, +{ 0x0d8c, 8, {0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0d94, 16, {0x8e, 0x38, 0x8f, 0x39, 0xe5, 0x39, 0x15, 0x39, 0xae, 0x38, 0x70, 0x02, 0x15, 0x38, 0x4e, 0x60} }, +{ 0x0da4, 7, {0x05, 0x12, 0x0e, 0x00, 0x80, 0xee, 0x22} }, +{ 0x0dab, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x02, 0xf0, 0xd0} }, +{ 0x0dbb, 6, {0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0dc1, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x10, 0xf0, 0xd0} }, +{ 0x0dd1, 6, {0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x0dd7, 16, {0xae, 0x07, 0x7f, 0x21, 0x7d, 0x01, 0x74, 0x00, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x0f, 0xab, 0x82} }, +{ 0x0de7, 5, {0xfa, 0x12, 0x0d, 0x10, 0x22} }, +{ 0x0dec, 16, {0x50, 0x0f, 0x00, 0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x98, 0x88, 0x83, 0xc6} }, +{ 0x0dfc, 3, {0xa1, 0x86, 0x8e} }, +{ 0x0dff, 1, {0x00} }, +{ 0x0e00, 16, {0x74, 0x00, 0xf5, 0x86, 0x90, 0xfd, 0xa5, 0x7c, 0x05, 0xa3, 0xe5, 0x82, 0x45, 0x83, 0x70, 0xf9} }, +{ 0x0e10, 1, {0x22} }, +{ 0x0e11, 14, {0x90, 0x7f, 0x00, 0xe5, 0x10, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0xd3, 0x22} }, +{ 0x0e1f, 14, {0x90, 0x7f, 0x00, 0xe5, 0x0e, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0xd3, 0x22} }, +{ 0x0e2d, 8, {0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x0e, 0xd3, 0x22} }, +{ 0x0e35, 8, {0xe4, 0xf5, 0x0d, 0xd2, 0xe9, 0xd2, 0xaf, 0x22} }, +{ 0x0e3d, 3, {0xd2, 0x00, 0x22} }, +{ 0x0e40, 2, {0xd3, 0x22} }, +{ 0x0e42, 2, {0xd3, 0x22} }, +{ 0x0e44, 2, {0xd3, 0x22} }, +{ 0x0e46, 2, {0xd3, 0x22} }, +{ 0x0e48, 2, {0xd3, 0x22} }, +{ 0x0e4a, 2, {0xd3, 0x22} }, +{ 0x0e4c, 1, {0x32} }, +{ 0x0e4d, 1, {0x32} }, +{ 0x0e4e, 1, {0x32} }, +{ 0x0e4f, 1, {0x32} }, +{ 0x0e50, 1, {0x32} }, +{ 0x0e51, 1, {0x32} }, +{ 0x0e52, 1, {0x32} }, +{ 0x0e53, 1, {0x32} }, +{ 0x0e54, 1, {0x32} }, +{ 0x0e55, 1, {0x32} }, +{ 0x0e56, 1, {0x32} }, +{ 0x0e57, 1, {0x32} }, +{ 0x0e58, 1, {0x32} }, +{ 0x0e59, 1, {0x32} }, +{ 0x0e5a, 1, {0x32} }, +{ 0x0e5b, 1, {0x32} }, +{ 0x1100, 16, {0x12, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x47, 0x05, 0x10, 0x27, 0x01, 0x00, 0x01, 0x02} }, +{ 0x1110, 16, {0x00, 0x01, 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x03, 0xa0, 0x00, 0x09, 0x04, 0x00, 0x00, 0x02} }, +{ 0x1120, 16, {0xff, 0x00, 0x00, 0x04, 0x07, 0x05, 0x82, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x02, 0x02, 0x40} }, +{ 0x1130, 16, {0x00, 0x00, 0x04, 0x03, 0x09, 0x04, 0x26, 0x03, 0x41, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x68, 0x00} }, +{ 0x1140, 16, {0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x43, 0x00, 0x68, 0x00, 0x69, 0x00, 0x70, 0x00, 0x73, 0x00} }, +{ 0x1150, 16, {0x2c, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x2e, 0x00, 0x28, 0x03, 0x46, 0x00} }, +{ 0x1160, 16, {0x69, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x77, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00} }, +{ 0x1170, 16, {0x46, 0x00, 0x72, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x57, 0x00, 0x6f, 0x00, 0x72, 0x00} }, +{ 0x1180, 16, {0x6b, 0x00, 0x73, 0x00, 0x2a, 0x03, 0x43, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x69, 0x00} }, +{ 0x1190, 16, {0x67, 0x00, 0x75, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00} }, +{ 0x11a0, 16, {0x20, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x22, 0x03} }, +{ 0x11b0, 16, {0x49, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x66, 0x00, 0x61, 0x00, 0x63, 0x00} }, +{ 0x11c0, 16, {0x65, 0x00, 0x20, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00} }, +{ 0x11d0, 2, {0x00, 0x00} }, +{ 0xffff, 0, {0x00} } +}; +#endif diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/uhci.c linux/drivers/usb/uhci.c --- v2.3.99-pre3/linux/drivers/usb/uhci.c Mon Mar 27 08:08:28 2000 +++ linux/drivers/usb/uhci.c Tue Apr 11 09:57:43 2000 @@ -56,11 +56,11 @@ static LIST_HEAD(uhci_list); -static int rh_submit_urb(urb_t *urb); -static int rh_unlink_urb(urb_t *urb); +static int rh_submit_urb(struct urb *urb); +static int rh_unlink_urb(struct urb *urb); static int uhci_get_current_frame_number(struct usb_device *dev); -static int uhci_unlink_generic(urb_t *urb); -static int uhci_unlink_urb(urb_t *urb); +static int uhci_unlink_generic(struct urb *urb); +static int uhci_unlink_urb(struct urb *urb); #define min(a,b) (((a)<(b))?(a):(b)) @@ -77,9 +77,8 @@ static int uhci_free_dev(struct usb_device *dev) { - urb_t *u; struct uhci *uhci = (struct uhci *)dev->bus->hcpriv; - struct list_head *tmp, *next, *head = &uhci->urb_list; + struct list_head *tmp, *head = &uhci->urb_list; unsigned long flags; /* Walk through the entire URB list and forcefully remove any */ @@ -87,14 +86,12 @@ nested_lock(&uhci->urblist_lock, flags); tmp = head->next; while (tmp != head) { - u = list_entry(tmp, urb_t, urb_list); + struct urb *u = list_entry(tmp, struct urb, urb_list); - next = tmp->next; + tmp = tmp->next; if (u->dev == dev) uhci_unlink_urb(u); - - tmp = next; } nested_unlock(&uhci->urblist_lock, flags); @@ -115,13 +112,31 @@ unsigned long flags; nested_lock(&uhci->urblist_lock, flags); - if (urb->urb_list.next != &urb->urb_list) { + if (!list_empty(&urb->urb_list)) { list_del(&urb->urb_list); INIT_LIST_HEAD(&urb->urb_list); } nested_unlock(&uhci->urblist_lock, flags); } +void uhci_set_next_interrupt(struct uhci *uhci) +{ + unsigned long flags; + + spin_lock_irqsave(&uhci->framelist_lock, flags); + uhci->skel_term_td.status |= TD_CTRL_IOC; + spin_unlock_irqrestore(&uhci->framelist_lock, flags); +} + +void uhci_clear_next_interrupt(struct uhci *uhci) +{ + unsigned long flags; + + spin_lock_irqsave(&uhci->framelist_lock, flags); + uhci->skel_term_td.status &= ~TD_CTRL_IOC; + spin_unlock_irqrestore(&uhci->framelist_lock, flags); +} + static struct uhci_td *uhci_alloc_td(struct usb_device *dev) { struct uhci_td *td; @@ -135,8 +150,8 @@ td->frameptr = NULL; td->nexttd = td->prevtd = NULL; - td->list.next = td->list.prev = NULL; td->dev = dev; + INIT_LIST_HEAD(&td->list); usb_inc_dev_use(dev); @@ -235,23 +250,32 @@ */ static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct urb *urb, int breadth) { + struct list_head *tmp, *head; struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; struct uhci_td *td, *prevtd; if (!urbp) return; - td = urbp->list.begin; - if (!td) + head = &urbp->list; + tmp = head->next; + if (head == tmp) return; + td = list_entry(tmp, struct uhci_td, list); + /* Add the first TD to the QH element pointer */ qh->element = virt_to_bus(td) | (breadth ? 0 : UHCI_PTR_DEPTH); prevtd = td; /* Then link the rest of the TD's */ - for (td = td->list.next; td; td = td->list.next) { + tmp = tmp->next; + while (tmp != head) { + td = list_entry(tmp, struct uhci_td, list); + + tmp = tmp->next; + prevtd->link = virt_to_bus(td) | (breadth ? 0 : UHCI_PTR_DEPTH); prevtd = td; @@ -260,9 +284,45 @@ prevtd->link = UHCI_PTR_TERM; } +/* This function will append one URB's QH to another URB's QH. This is for */ +/* USB_QUEUE_BULK support */ +static void uhci_append_urb_qh(struct uhci *uhci, struct urb *eurb, struct urb *urb) +{ + struct urb *nurb; + struct urb_priv *eurbp, *urbp, *nurbp; + struct list_head *tmp; + struct uhci_td *td, *ntd; + unsigned long flags; + + eurbp = eurb->hcpriv; + urbp = urb->hcpriv; + + spin_lock_irqsave(&eurb->lock, flags); + + /* Grab the last URB in the queue */ + tmp = eurbp->urb_queue_list.prev; + + /* Add this one to the end */ + list_add_tail(&urbp->urb_queue_list, &eurbp->urb_queue_list); + + spin_unlock_irqrestore(&eurb->lock, flags); + + nurbp = list_entry(tmp, struct urb_priv, urb_queue_list); + nurb = nurbp->urb; + + tmp = nurbp->list.prev; + td = list_entry(tmp, struct uhci_td, list); + + tmp = urbp->list.next; + ntd = list_entry(tmp, struct uhci_td, list); + + /* No breadth since this will only be called for bulk transfers */ + td->link = virt_to_bus(ntd); +} + static void uhci_free_td(struct uhci_td *td) { - if (td->list.next || td->list.prev) + if (!list_empty(&td->list)) dbg("td is still in URB list!"); kmem_cache_free(uhci_td_cachep, td); @@ -322,6 +382,10 @@ static void uhci_remove_qh(struct uhci *uhci, struct uhci_qh *qh) { unsigned long flags; + int delayed; + + /* If the QH isn't queued, then we don't need to delay unlink it */ + delayed = (qh->prevqh || qh->nextqh); spin_lock_irqsave(&uhci->framelist_lock, flags); if (qh->prevqh) { @@ -333,9 +397,20 @@ qh->prevqh = qh->nextqh = NULL; spin_unlock_irqrestore(&uhci->framelist_lock, flags); - spin_lock_irqsave(&uhci->qh_remove_lock, flags); - list_add(&qh->remove_list, &uhci->qh_remove_list); - spin_unlock_irqrestore(&uhci->qh_remove_lock, flags); + if (delayed) { + spin_lock_irqsave(&uhci->qh_remove_lock, flags); + + /* Check to see if the remove list is empty */ + /* Set the IOC bit to force an interrupt so we can remove the QH */ + if (list_empty(&uhci->qh_remove_list)) + uhci_set_next_interrupt(uhci); + + /* Add it */ + list_add(&qh->remove_list, &uhci->qh_remove_list); + + spin_unlock_irqrestore(&uhci->qh_remove_lock, flags); + } else + uhci_free_qh(qh); } struct urb_priv *uhci_alloc_urb_priv(struct urb *urb) @@ -348,91 +423,86 @@ memset((void *)urbp, 0, sizeof(*urbp)); - urbp->list.begin = urbp->list.end = NULL; + urbp->inserttime = jiffies; + urbp->urb = urb; + + INIT_LIST_HEAD(&urbp->list); + INIT_LIST_HEAD(&urbp->urb_queue_list); urb->hcpriv = urbp; - urbp->inserttime = jiffies; - usb_inc_dev_use(urb->dev); return urbp; } -static void uhci_add_td_to_urb(urb_t *urb, struct uhci_td *td) +static void uhci_add_td_to_urb(struct urb *urb, struct uhci_td *td) { struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; td->urb = urb; - if (!urbp->list.begin) - urbp->list.begin = td; - - if (urbp->list.end) { - urbp->list.end->list.next = td; - td->list.prev = urbp->list.end; - } - urbp->list.end = td; + list_add_tail(&td->list, &urbp->list); } -static void uhci_remove_td_from_urb(urb_t *urb, struct uhci_td *td) +static void uhci_remove_td_from_urb(struct urb *urb, struct uhci_td *td) { - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; + urb = NULL; /* No warnings */ - if (!urbp->list.begin && !urbp->list.end) + if (list_empty(&td->list)) return; - if (td->list.prev) - td->list.prev->list.next = td->list.next; - else - urbp->list.begin = td->list.next; - - if (td->list.next) - td->list.next->list.prev = td->list.prev; - else - urbp->list.end = td->list.prev; + list_del(&td->list); + INIT_LIST_HEAD(&td->list); - td->list.next = td->list.prev = NULL; td->urb = NULL; } -static void uhci_destroy_urb_priv(urb_t *urb) +static void uhci_destroy_urb_priv(struct urb *urb) { + struct list_head *tmp, *head; struct urb_priv *urbp; struct uhci *uhci; - struct uhci_td *td, *nexttd; + struct uhci_td *td; unsigned long flags; spin_lock_irqsave(&urb->lock, flags); urbp = (struct urb_priv *)urb->hcpriv; if (!urbp) - return; + goto unlock; if (!urb->dev || !urb->dev->bus || !urb->dev->bus->hcpriv) - return; + goto unlock; uhci = urb->dev->bus->hcpriv; - td = urbp->list.begin; - while (td) { - nexttd = td->list.next; + head = &urbp->list; + tmp = head->next; + while (tmp != head) { + td = list_entry(tmp, struct uhci_td, list); + + tmp = tmp->next; uhci_remove_td_from_urb(urb, td); uhci_remove_td(uhci, td); uhci_free_td(td); - - td = nexttd; + } + + if (!list_empty(&urbp->urb_queue_list)) { + list_del(&urbp->urb_queue_list); + INIT_LIST_HEAD(&urbp->urb_queue_list); } urb->hcpriv = NULL; kmem_cache_free(uhci_up_cachep, urbp); - spin_unlock_irqrestore(&urb->lock, flags); - usb_dec_dev_use(urb->dev); + +unlock: + spin_unlock_irqrestore(&urb->lock, flags); } static void uhci_inc_fsbr(struct uhci *uhci, struct urb *urb) @@ -448,7 +518,7 @@ if (!urbp->fsbr) { urbp->fsbr = 1; if (!uhci->fsbr++) - uhci->skel_term_td.link = virt_to_bus(&uhci->skel_hs_control_qh) | UHCI_PTR_QH; + uhci->skel_term_qh.link = virt_to_bus(&uhci->skel_hs_control_qh) | UHCI_PTR_QH; } spin_unlock_irqrestore(&uhci->framelist_lock, flags); @@ -467,7 +537,7 @@ if (urbp->fsbr) { urbp->fsbr = 0; if (!--uhci->fsbr) - uhci->skel_term_td.link = UHCI_PTR_TERM; + uhci->skel_term_qh.link = UHCI_PTR_TERM; } spin_unlock_irqrestore(&uhci->framelist_lock, flags); @@ -508,7 +578,7 @@ /* * Control transfers */ -static int uhci_submit_control(urb_t *urb) +static int uhci_submit_control(struct urb *urb) { struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; @@ -602,10 +672,12 @@ if (urb->pipe & TD_CTRL_LS) { uhci_insert_tds_in_qh(qh, urb, 0); uhci_insert_qh(uhci, &uhci->skel_ls_control_qh, qh); + urbp->queued = 0; } else { uhci_insert_tds_in_qh(qh, urb, 1); uhci_insert_qh(uhci, &uhci->skel_hs_control_qh, qh); uhci_inc_fsbr(uhci, urb); + urbp->queued = 0; } urbp->qh = qh; @@ -617,10 +689,11 @@ return -EINPROGRESS; } -static int usb_control_retrigger_status(urb_t *urb); +static int usb_control_retrigger_status(struct urb *urb); -static int uhci_result_control(urb_t *urb) +static int uhci_result_control(struct urb *urb) { + struct list_head *tmp, *head; struct urb_priv *urbp = urb->hcpriv; struct uhci_td *td; unsigned int status; @@ -628,13 +701,16 @@ if (!urbp) return -EINVAL; - td = urbp->list.begin; - if (!td) + head = &urbp->list; + tmp = head->next; + if (head == tmp) return -EINVAL; if (urbp->short_control_packet) goto status_phase; + td = list_entry(tmp, struct uhci_td, list); + /* The first TD is the SETUP phase, check the status, but skip */ /* the count */ status = uhci_status_bits(td->status); @@ -646,10 +722,13 @@ urb->actual_length = 0; - td = td->list.next; - /* The rest of the TD's (but the last) are data */ - while (td && td->list.next) { + tmp = tmp->next; + while (tmp != head && tmp->next != head) { + td = list_entry(tmp, struct uhci_td, list); + + tmp = tmp->next; + status = uhci_status_bits(td->status); if (status & TD_CTRL_ACTIVE) return -EINPROGRESS; @@ -664,18 +743,18 @@ if (status) goto td_error; - - td = td->list.next; } status_phase: + td = list_entry(tmp, struct uhci_td, list); + /* Control status phase */ status = uhci_status_bits(td->status); /* APC BackUPS Pro kludge */ /* It tries to send all of the descriptor instead of the amount */ /* we requested */ - if (td->status & TD_CTRL_IOC && + if (td->status & TD_CTRL_IOC && /* IOC is masked out by uhci_status_bits */ status & TD_CTRL_ACTIVE && status & TD_CTRL_NAK) return 0; @@ -704,34 +783,37 @@ return uhci_map_status(status, uhci_packetout(td->info)); } -static int usb_control_retrigger_status(urb_t *urb) +static int usb_control_retrigger_status(struct urb *urb) { + struct list_head *tmp, *head; struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; struct uhci *uhci = urb->dev->bus->hcpriv; - struct uhci_td *td, *nexttd; urbp->short_control_packet = 1; + /* Create a new QH to avoid pointer overwriting problems */ + uhci_remove_qh(uhci, urbp->qh); + /* Delete all of the TD's except for the status TD at the end */ - td = urbp->list.begin; - while (td && td->list.next) { - nexttd = td->list.next; + head = &urbp->list; + tmp = head->next; + while (tmp != head && tmp->next != head) { + struct uhci_td *td = list_entry(tmp, struct uhci_td, list); + + tmp = tmp->next; uhci_remove_td_from_urb(urb, td); uhci_remove_td(uhci, td); uhci_free_td(td); - - td = nexttd; } - /* Create a new QH to avoid pointer overwriting problems */ - uhci_remove_qh(uhci, urbp->qh); - urbp->qh = uhci_alloc_qh(urb->dev); - if (!urbp->qh) + if (!urbp->qh) { + err("unable to allocate new QH for control retrigger"); return -ENOMEM; + } /* One TD, who cares about Breadth first? */ uhci_insert_tds_in_qh(urbp->qh, urb, 0); @@ -741,6 +823,7 @@ uhci_insert_qh(uhci, &uhci->skel_ls_control_qh, urbp->qh); else uhci_insert_qh(uhci, &uhci->skel_hs_control_qh, urbp->qh); + urbp->queued = 0; return -EINPROGRESS; } @@ -748,7 +831,7 @@ /* * Interrupt transfers */ -static int uhci_submit_interrupt(urb_t *urb) +static int uhci_submit_interrupt(struct urb *urb) { struct uhci_td *td; unsigned long destination, status; @@ -782,18 +865,25 @@ return -EINPROGRESS; } -static int uhci_result_interrupt(urb_t *urb) +static int uhci_result_interrupt(struct urb *urb) { + struct list_head *tmp, *head; struct urb_priv *urbp = urb->hcpriv; - struct uhci_td *td; unsigned int status; + struct uhci_td *td; if (!urbp) return -EINVAL; urb->actual_length = 0; - for (td = urbp->list.begin; td; td = td->list.next) { + head = &urbp->list; + tmp = head->next; + while (tmp != head) { + td = list_entry(tmp, struct uhci_td, list); + + tmp = tmp->next; + status = uhci_status_bits(td->status); if (status & TD_CTRL_ACTIVE) return -EINPROGRESS; @@ -836,15 +926,17 @@ return uhci_map_status(status, uhci_packetout(td->info)); } -static void uhci_reset_interrupt(urb_t *urb) +static void uhci_reset_interrupt(struct urb *urb) { + struct list_head *tmp; struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; struct uhci_td *td; if (!urbp) return; - td = urbp->list.begin; + tmp = urbp->list.next; + td = list_entry(tmp, struct uhci_td, list); if (!td) return; @@ -859,7 +951,7 @@ /* * Bulk transfers */ -static int uhci_submit_bulk(urb_t *urb) +static int uhci_submit_bulk(struct urb *urb, struct urb *eurb) { struct uhci_td *td; struct uhci_qh *qh; @@ -881,14 +973,14 @@ destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); /* 3 errors */ - status = TD_CTRL_ACTIVE | (3 << 27); + status = TD_CTRL_ACTIVE | (3 << TD_CTRL_C_ERR_SHIFT); if (!(urb->transfer_flags & USB_DISABLE_SPD)) status |= TD_CTRL_SPD; /* * Build the DATA TD's */ - while (len > 0) { + do { /* Allow zero length packets */ int pktsze = len; if (pktsze > maxsze) @@ -912,16 +1004,24 @@ usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)); - } + } while (len > 0); qh = uhci_alloc_qh(urb->dev); if (!qh) return -ENOMEM; + urbp->qh = qh; + + /* Always assume depth first */ uhci_insert_tds_in_qh(qh, urb, 1); - uhci_insert_qh(uhci, &uhci->skel_bulk_qh, qh); - urbp->qh = qh; + if (urb->transfer_flags & USB_QUEUE_BULK && eurb) { + uhci_append_urb_qh(uhci, eurb, urb); + urbp->queued = 1; + } else { + uhci_insert_qh(uhci, &uhci->skel_bulk_qh, qh); + urbp->queued = 0; + } uhci_add_urb_list(uhci, urb); @@ -936,9 +1036,9 @@ /* * Isochronous transfers */ -static int isochronous_find_limits(urb_t *urb, unsigned int *start, unsigned int *end) +static int isochronous_find_limits(struct urb *urb, unsigned int *start, unsigned int *end) { - urb_t *u, *last_urb = NULL; + struct urb *last_urb = NULL; struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; struct list_head *tmp, *head = &uhci->urb_list; int ret = 0; @@ -947,7 +1047,7 @@ nested_lock(&uhci->urblist_lock, flags); tmp = head->next; while (tmp != head) { - u = list_entry(tmp, urb_t, urb_list); + struct urb *u = list_entry(tmp, struct urb, urb_list); /* look for pending URB's with identical pipe handle */ if ((urb->pipe == u->pipe) && (urb->dev == u->dev) && @@ -970,7 +1070,7 @@ return ret; } -static int isochronous_find_start(urb_t *urb) +static int isochronous_find_start(struct urb *urb) { int limits; unsigned int start = 0, end = 0; @@ -996,7 +1096,7 @@ return 0; } -static int uhci_submit_isochronous(urb_t *urb) +static int uhci_submit_isochronous(struct urb *urb) { struct uhci_td *td; struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; @@ -1034,10 +1134,10 @@ return -EINPROGRESS; } -static int uhci_result_isochronous(urb_t *urb) +static int uhci_result_isochronous(struct urb *urb) { + struct list_head *tmp, *head; struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - struct uhci_td *td; int status; int i, ret = 0; @@ -1046,9 +1146,15 @@ urb->actual_length = 0; - for (i = 0, td = urbp->list.begin; td; i++, td = td->list.next) { + i = 0; + head = &urbp->list; + tmp = head->next; + while (tmp != head) { + struct uhci_td *td = list_entry(tmp, struct uhci_td, list); int actlength; + tmp = tmp->next; + if (td->status & TD_CTRL_ACTIVE) return -EINPROGRESS; @@ -1062,16 +1168,47 @@ urb->error_count++; ret = status; } + + i++; } return ret; } -static int uhci_submit_urb(urb_t *urb) +static struct urb *uhci_find_urb_ep(struct uhci *uhci, struct urb *urb) +{ + struct list_head *tmp, *head = &uhci->urb_list; + unsigned long flags; + struct urb *u = NULL; + + if (usb_pipeisoc(urb->pipe)) + return NULL; + + nested_lock(&uhci->urblist_lock, flags); + tmp = head->next; + while (tmp != head) { + u = list_entry(tmp, struct urb, urb_list); + + tmp = tmp->next; + + if (u->dev == urb->dev && + u->pipe == urb->pipe) + goto found; + } + u = NULL; + +found: + nested_unlock(&uhci->urblist_lock, flags); + + return u; +} + +static int uhci_submit_urb(struct urb *urb) { int ret = -EINVAL; struct uhci *uhci; unsigned long flags; + struct urb *u; if (!urb) return -EINVAL; @@ -1085,6 +1222,10 @@ if (usb_pipedevice(urb->pipe) == uhci->rh.devnum) return rh_submit_urb(urb); + u = uhci_find_urb_ep(uhci, urb); + if (u && !(urb->transfer_flags & USB_QUEUE_BULK)) + return -ENXIO; + spin_lock_irqsave(&urb->lock, flags); if (!uhci_alloc_urb_priv(urb)) { @@ -1100,7 +1241,7 @@ ret = uhci_submit_interrupt(urb); break; case PIPE_BULK: - ret = uhci_submit_bulk(urb); + ret = uhci_submit_bulk(urb, u); break; case PIPE_ISOCHRONOUS: ret = uhci_submit_isochronous(urb); @@ -1124,9 +1265,9 @@ * * Must be called with urblist_lock acquired */ -static void uhci_transfer_result(urb_t *urb) +static void uhci_transfer_result(struct urb *urb) { - urb_t *turb; + struct urb *turb; int proceed = 0, is_ring = 0; int ret = -EINVAL; unsigned long flags; @@ -1206,7 +1347,7 @@ } } -static int uhci_unlink_generic(urb_t *urb) +static int uhci_unlink_generic(struct urb *urb) { struct urb_priv *urbp = urb->hcpriv; struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; @@ -1222,12 +1363,21 @@ /* The interrupt loop will reclaim the QH's */ uhci_remove_qh(uhci, urbp->qh); + if (!list_empty(&urbp->urb_queue_list)) { + struct list_head *tmp = urbp->urb_queue_list.next; + struct urb_priv *nurbp = list_entry(tmp, struct urb_priv, urb_queue_list); + if (nurbp->queued) { + uhci_insert_qh(uhci, &uhci->skel_bulk_qh, nurbp->qh); + nurbp->queued = 0; + } + } + uhci_destroy_urb_priv(urb); return 0; } -static int uhci_unlink_urb(urb_t *urb) +static int uhci_unlink_urb(struct urb *urb) { struct uhci *uhci; int ret = 0; @@ -1252,7 +1402,13 @@ urb->status = -ECONNABORTED; spin_lock_irqsave(&uhci->urb_remove_lock, flags); + + /* Check to see if the remove list is empty */ + if (list_empty(&uhci->urb_remove_list)) + uhci_set_next_interrupt(uhci); + list_add(&urb->urb_list, &uhci->urb_remove_list); + spin_unlock_irqrestore(&uhci->urb_remove_lock, flags); } else { urb->status = -ENOENT; @@ -1372,7 +1528,7 @@ /*-------------------------------------------------------------------------*/ /* prepare Interrupt pipe transaction data; HUB INTERRUPT ENDPOINT */ -static int rh_send_irq(urb_t *urb) +static int rh_send_irq(struct urb *urb) { int i, len = 1; struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; @@ -1399,11 +1555,11 @@ /*-------------------------------------------------------------------------*/ /* Virtual Root Hub INTs are polled by this timer every "interval" ms */ -static int rh_init_int_timer(urb_t *urb); +static int rh_init_int_timer(struct urb *urb); static void rh_int_timer_do(unsigned long ptr) { - urb_t *urb = (urb_t *)ptr, *u; + struct urb *urb = (struct urb *)ptr; struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; struct list_head *tmp, *head = &uhci->urb_list; struct urb_priv *urbp; @@ -1422,15 +1578,22 @@ nested_lock(&uhci->urblist_lock, flags); tmp = head->next; while (tmp != head) { - u = list_entry(tmp, urb_t, urb_list); + struct urb *u = list_entry(tmp, urb_t, urb_list); + + tmp = tmp->next; urbp = (struct urb_priv *)u->hcpriv; if (urbp) { - if (urbp->fsbr && time_after(jiffies, urbp->inserttime + IDLE_TIMEOUT)) + /* Check if the FSBR timed out */ + if (urbp->fsbr && time_after(urbp->inserttime + IDLE_TIMEOUT, jiffies)) uhci_dec_fsbr(uhci, u); - } - tmp = tmp->next; + /* Check if the URB timed out */ + if (u->timeout && time_after(u->timeout, jiffies)) { + u->transfer_flags |= USB_ASYNC_UNLINK | USB_TIMEOUT_KILLED; + uhci_unlink_urb(u); + } + } } nested_unlock(&uhci->urblist_lock, flags); @@ -1439,7 +1602,7 @@ /*-------------------------------------------------------------------------*/ /* Root Hub INTs are polled by this timer */ -static int rh_init_int_timer(urb_t *urb) +static int rh_init_int_timer(struct urb *urb) { struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; @@ -1472,7 +1635,7 @@ ** Root Hub Control Pipe *************************/ -static int rh_submit_urb(urb_t *urb) +static int rh_submit_urb(struct urb *urb) { struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; unsigned int pipe = urb->pipe; @@ -1588,7 +1751,7 @@ OK(0); case RH_PORT_RESET: SET_RH_PORTSTAT(USBPORTSC_PR); - wait_ms(10); + wait_ms(50); /* USB v1.1 7.1.7.3 */ uhci->rh.c_p_r[wIndex - 1] = 1; CLR_RH_PORTSTAT(USBPORTSC_PR); udelay(10); @@ -1636,6 +1799,11 @@ OK(1); case RH_SET_CONFIGURATION: OK(0); + case RH_GET_INTERFACE | RH_INTERFACE: + *(__u8 *)data = 0x00; + OK(1); + case RH_SET_INTERFACE | RH_INTERFACE: + OK(0); default: stat = -EPIPE; } @@ -1649,7 +1817,7 @@ } /*-------------------------------------------------------------------------*/ -static int rh_unlink_urb(urb_t *urb) +static int rh_unlink_urb(struct urb *urb) { struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; @@ -1728,6 +1896,8 @@ } spin_unlock(&uhci->urb_remove_lock); + uhci_clear_next_interrupt(uhci); + /* Walk the list of pending TD's to see which ones completed */ nested_lock(&uhci->urblist_lock, flags); head = &uhci->urb_list; @@ -2137,7 +2307,7 @@ /* We only want to return an error code if ther was an error */ /* and we didn't find a UHCI controller */ - if (retval && uhci_list.next == &uhci_list) + if (retval && list_empty(&uhci_list)) goto init_failed; return 0; diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/uhci.h linux/drivers/usb/uhci.h --- v2.3.99-pre3/linux/drivers/usb/uhci.h Tue Mar 14 19:10:40 2000 +++ linux/drivers/usb/uhci.h Mon Apr 10 22:57:06 2000 @@ -97,6 +97,10 @@ #define UHCI_MAX_SOF_NUMBER 2047 /* in an SOF packet */ #define CAN_SCHEDULE_FRAMES 1000 /* how far future frames can be scheduled */ +struct uhci_framelist { + __u32 frame[UHCI_NUMFRAMES]; +} __attribute__((aligned(4096))); + struct uhci_td; struct uhci_qh { @@ -106,22 +110,19 @@ /* Software fields */ /* Can't use list_head since we want a specific order */ - struct uhci_qh *prevqh, *nextqh; - struct usb_device *dev; /* The owning device */ + struct uhci_qh *prevqh, *nextqh; + struct list_head remove_list; } __attribute__((aligned(16))); -struct uhci_framelist { - __u32 frame[UHCI_NUMFRAMES]; -} __attribute__((aligned(4096))); - /* * for TD : */ #define TD_CTRL_SPD (1 << 29) /* Short Packet Detect */ #define TD_CTRL_C_ERR_MASK (3 << 27) /* Error Counter bits */ +#define TD_CTRL_C_ERR_SHIFT 27 #define TD_CTRL_LS (1 << 26) /* Low Speed Device */ #define TD_CTRL_IOS (1 << 25) /* Isochronous Select */ #define TD_CTRL_IOC (1 << 24) /* Interrupt on Complete */ @@ -184,10 +185,8 @@ struct usb_device *dev; struct urb *urb; /* URB this TD belongs to */ - /* We can't use list_head since we need a specific order */ - struct ut_list { - struct uhci_td *prev, *next; - } list; + + struct list_head list; } __attribute__((aligned(16))); /* @@ -336,9 +335,12 @@ }; struct urb_priv { + struct urb *urb; + struct uhci_qh *qh; /* QH for this URB */ - int fsbr; /* Did this URB turn on FSBR? */ + int fsbr : 1; /* Did this URB turn on FSBR? */ + int queued : 1; /* 0 if QH was linked in */ char short_control_packet; /* If we get a short packet during */ /* a control transfer, retrigger */ @@ -346,15 +348,16 @@ unsigned long inserttime; /* In jiffies */ - struct up_list { - struct uhci_td *begin, *end; - } list; + struct list_head list; + + struct list_head urb_queue_list; /* URB's linked together */ }; /* ------------------------------------------------------------------------- Virtual Root HUB ------------------------------------------------------------------------- */ /* destination of request */ +#define RH_DEVICE 0x00 #define RH_INTERFACE 0x01 #define RH_ENDPOINT 0x02 #define RH_OTHER 0x03 diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/usb-core.c linux/drivers/usb/usb-core.c --- v2.3.99-pre3/linux/drivers/usb/usb-core.c Tue Mar 14 19:10:40 2000 +++ linux/drivers/usb/usb-core.c Sun Apr 2 15:20:16 2000 @@ -29,10 +29,10 @@ */ int usb_audio_init(void); -int usb_cpia_init(void); int usb_ibmcam_init(void); int dabusb_init(void); int plusb_init(void); +int dsbr100_init(void); /* * HCI drivers @@ -70,9 +70,6 @@ #ifndef CONFIG_USB_MODULE #ifdef CONFIG_USB_AUDIO usb_audio_init(); -#endif -#ifdef CONFIG_USB_CPIA - usb_cpia_init(); #endif #ifdef CONFIG_USB_IBMCAM usb_ibmcam_init(); diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/usb-debug.c linux/drivers/usb/usb-debug.c --- v2.3.99-pre3/linux/drivers/usb/usb-debug.c Fri Mar 10 16:40:45 2000 +++ linux/drivers/usb/usb-debug.c Thu Mar 30 18:00:01 2000 @@ -4,11 +4,16 @@ * I just want these out of the way where they aren't in your * face, but so that you can still use them.. */ +#include #include #include #include #include -#define DEBUG +#ifdef CONFIG_USB_DEBUG + #define DEBUG +#else + #undef DEBUG +#endif #include static void usb_show_endpoint(struct usb_endpoint_descriptor *endpoint) diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/usb-ohci.c linux/drivers/usb/usb-ohci.c --- v2.3.99-pre3/linux/drivers/usb/usb-ohci.c Mon Mar 27 08:08:28 2000 +++ linux/drivers/usb/usb-ohci.c Mon Apr 10 22:53:24 2000 @@ -49,7 +49,7 @@ #include #include -#define OHCI_USE_NPS +#define OHCI_USE_NPS // force NoPowerSwitching mode #include "usb-ohci.h" @@ -61,6 +61,12 @@ #include #endif + +/* For initializing controller (mask in an HCFS mode too) */ +#define OHCI_CONTROL_INIT \ + (OHCI_CTRL_CBSR & 0x3) \ + | OHCI_CTRL_BLE | OHCI_CTRL_CLE | OHCI_CTRL_IE | OHCI_CTRL_PLE + static DECLARE_WAIT_QUEUE_HEAD (op_wakeup); static LIST_HEAD (ohci_hcd_list); static spinlock_t usb_ed_lock = SPIN_LOCK_UNLOCKED; @@ -143,16 +149,18 @@ printk ("%s stat:%d\n", i < len? "...": "", urb->status); } } - } -/* just for debugging; prints all 32 branches of the int ed tree inclusive iso eds*/ + +/* just for debugging; prints non-empty branches of the int ed tree inclusive iso eds*/ void ep_print_int_eds (ohci_t * ohci, char * str) { int i, j; __u32 * ed_p; for (i= 0; i < 32; i++) { j = 5; - printk (KERN_DEBUG __FILE__ " %s branch int %2d(%2x):", str, i, i); ed_p = &(ohci->hcca.int_table [i]); + if (*ed_p == 0) + continue; + printk (KERN_DEBUG __FILE__ ": %s branch int %2d(%2x):", str, i, i); while (*ed_p != 0 && j--) { ed_t *ed = (ed_t *) bus_to_virt(le32_to_cpup(ed_p)); printk (" ed: %4x;", ed->hwINFO); @@ -161,7 +169,161 @@ printk ("\n"); } } - + + +static void ohci_dump_intr_mask (char *label, __u32 mask) +{ + dbg ("%s: 0x%08x%s%s%s%s%s%s%s%s%s", + label, + mask, + (mask & OHCI_INTR_MIE) ? " MIE" : "", + (mask & OHCI_INTR_OC) ? " OC" : "", + (mask & OHCI_INTR_RHSC) ? " RHSC" : "", + (mask & OHCI_INTR_FNO) ? " FNO" : "", + (mask & OHCI_INTR_UE) ? " UE" : "", + (mask & OHCI_INTR_RD) ? " RD" : "", + (mask & OHCI_INTR_SF) ? " SF" : "", + (mask & OHCI_INTR_WDH) ? " WDH" : "", + (mask & OHCI_INTR_SO) ? " SO" : "" + ); +} + +static void maybe_print_eds (char *label, __u32 value) +{ + if (value) + dbg ("%s %08x", label, value); +} + +static char *hcfs2string (int state) +{ + switch (state) { + case OHCI_USB_RESET: return "reset"; + case OHCI_USB_RESUME: return "resume"; + case OHCI_USB_OPER: return "operational"; + case OHCI_USB_SUSPEND: return "suspend"; + } + return "?"; +} + +// dump control and status registers +static void ohci_dump_status (ohci_t *controller) +{ + struct ohci_regs *regs = controller->regs; + __u32 temp; + + temp = readl (®s->revision) & 0xff; + if (temp != 0x10) + dbg ("spec %d.%d", (temp >> 4), (temp & 0x0f)); + + temp = readl (®s->control); + dbg ("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp, + (temp & OHCI_CTRL_RWE) ? " RWE" : "", + (temp & OHCI_CTRL_RWC) ? " RWC" : "", + (temp & OHCI_CTRL_IR) ? " IR" : "", + hcfs2string (temp & OHCI_CTRL_HCFS), + (temp & OHCI_CTRL_BLE) ? " BLE" : "", + (temp & OHCI_CTRL_CLE) ? " CLE" : "", + (temp & OHCI_CTRL_IE) ? " IE" : "", + (temp & OHCI_CTRL_PLE) ? " PLE" : "", + temp & OHCI_CTRL_CBSR + ); + + temp = readl (®s->cmdstatus); + dbg ("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp, + (temp & OHCI_SOC) >> 16, + (temp & OHCI_OCR) ? " OCR" : "", + (temp & OHCI_BLF) ? " BLF" : "", + (temp & OHCI_CLF) ? " CLF" : "", + (temp & OHCI_HCR) ? " HCR" : "" + ); + + ohci_dump_intr_mask ("intrstatus", readl (®s->intrstatus)); + ohci_dump_intr_mask ("intrenable", readl (®s->intrenable)); + // intrdisable always same as intrenable + // ohci_dump_intr_mask ("intrdisable", readl (®s->intrdisable)); + + maybe_print_eds ("ed_periodcurrent", readl (®s->ed_periodcurrent)); + + maybe_print_eds ("ed_controlhead", readl (®s->ed_controlhead)); + maybe_print_eds ("ed_controlcurrent", readl (®s->ed_controlcurrent)); + + maybe_print_eds ("ed_bulkhead", readl (®s->ed_bulkhead)); + maybe_print_eds ("ed_bulkcurrent", readl (®s->ed_bulkcurrent)); + + maybe_print_eds ("donehead", readl (®s->donehead)); +} + +static void ohci_dump_roothub (ohci_t *controller, int verbose) +{ + struct ohci_regs *regs = controller->regs; + __u32 temp, ndp, i; + + temp = readl (®s->roothub.a); + ndp = (temp & RH_A_NDP); + + if (verbose) { + dbg ("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp, + ((temp & RH_A_POTPGT) >> 24) & 0xff, + (temp & RH_A_NOCP) ? " NOCP" : "", + (temp & RH_A_OCPM) ? " OCPM" : "", + (temp & RH_A_DT) ? " DT" : "", + (temp & RH_A_NPS) ? " NPS" : "", + (temp & RH_A_PSM) ? " PSM" : "", + ndp + ); + temp = readl (®s->roothub.b); + dbg ("roothub.b: %08x PPCM=%04x DR=%04x", + temp, + (temp & RH_B_PPCM) >> 16, + (temp & RH_B_DR) + ); + temp = readl (®s->roothub.status); + dbg ("roothub.status: %08x%s%s%s%s%s%s", + temp, + (temp & RH_HS_CRWE) ? " CRWE" : "", + (temp & RH_HS_OCIC) ? " OCIC" : "", + (temp & RH_HS_LPSC) ? " LPSC" : "", + (temp & RH_HS_DRWE) ? " DRWE" : "", + (temp & RH_HS_OCI) ? " OCI" : "", + (temp & RH_HS_LPS) ? " LPS" : "" + ); + } + + for (i = 0; i < ndp; i++) { + temp = readl (®s->roothub.portstatus [i]); + dbg ("roothub.portstatus [%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s", + i, + temp, + (temp & RH_PS_PRSC) ? " PRSC" : "", + (temp & RH_PS_OCIC) ? " OCIC" : "", + (temp & RH_PS_PSSC) ? " PSSC" : "", + (temp & RH_PS_PESC) ? " PESC" : "", + (temp & RH_PS_CSC) ? " CSC" : "", + + (temp & RH_PS_LSDA) ? " LSDA" : "", + (temp & RH_PS_PPS) ? " PPS" : "", + (temp & RH_PS_PRS) ? " PRS" : "", + (temp & RH_PS_POCI) ? " POCI" : "", + (temp & RH_PS_PSS) ? " PSS" : "", + + (temp & RH_PS_PES) ? " PES" : "", + (temp & RH_PS_CCS) ? " CCS" : "" + ); + } +} + +static void ohci_dump (ohci_t *controller, int verbose) +{ + dbg ("OHCI controller %p state", controller->regs); + + // dumps some of the state we know about + ohci_dump_status (controller); + if (verbose) + ep_print_int_eds (controller, "hcca"); + dbg ("hcca frame #%04x", controller->hcca.frame_no); + ohci_dump_roothub (controller, 1); +} + #endif @@ -365,12 +527,12 @@ if (!urb) /* just to be sure */ return -EINVAL; + ohci = (ohci_t *) urb->dev->bus->hcpriv; + #ifdef DEBUG urb_print (urb, "UNLINK", 1); #endif - ohci = (ohci_t *) urb->dev->bus->hcpriv; - if (usb_pipedevice (urb->pipe) == ohci->rh.devnum) return rh_unlink_urb (urb); /* a request to the virtual root hub */ @@ -448,8 +610,8 @@ } spin_unlock_irqrestore (&usb_ed_lock, flags); - if (cnt > 0) { - dev->wait = &wait; + if (cnt > 0) { + dev->wait = &wait; current->state = TASK_UNINTERRUPTIBLE; schedule_timeout (HZ / 10); remove_wait_queue (&op_wakeup, &wait); @@ -673,10 +835,12 @@ } } } - for (i = int_branch; i < 32; i += interval) ohci->ohci_int_load[i] -= ed->int_load; + for (i = int_branch; i < 32; i += interval) + ohci->ohci_int_load[i] -= ed->int_load; #ifdef DEBUG ep_print_int_eds (ohci, "UNLINK_INT"); -#endif break; +#endif + break; case ISO: if (ohci->ed_isotail == ed) @@ -787,10 +951,10 @@ switch (ed->type) { case CTRL: /* stop CTRL list */ - writel (ohci->hc_control &= ~(0x01 << 4), &ohci->regs->control); + writel (ohci->hc_control &= ~OHCI_CTRL_CLE, &ohci->regs->control); break; case BULK: /* stop BULK list */ - writel (ohci->hc_control &= ~(0x01 << 5), &ohci->regs->control); + writel (ohci->hc_control &= ~OHCI_CTRL_BLE, &ohci->regs->control); break; } } @@ -1012,8 +1176,10 @@ if (ctrl) writel (0, &ohci->regs->ed_controlcurrent); /* reset CTRL list */ if (bulk) writel (0, &ohci->regs->ed_bulkcurrent); /* reset BULK list */ - if (!ohci->ed_rm_list[!frame]) /* start CTRL u. BULK list */ - writel (ohci->hc_control |= (0x03<<4), &ohci->regs->control); + if (!ohci->ed_rm_list[!frame]) { /* enable CTRL and BULK lists */ + ohci->hc_control |= OHCI_CTRL_CLE | OHCI_CTRL_BLE; + writel (ohci->hc_control, &ohci->regs->control); + } ohci->ed_rm_list[frame] = NULL; spin_unlock_irqrestore (&usb_ed_lock, flags); @@ -1112,6 +1278,7 @@ * Virtual Root Hub *-------------------------------------------------------------------------*/ +/* Device descriptor */ static __u8 root_hub_dev_des[] = { 0x12, /* __u8 bLength; */ @@ -1170,23 +1337,8 @@ 0xff /* __u8 ep_bInterval; 255 ms */ }; -/* -For OHCI we need just the 2nd Byte, so we -don't need this constant byte-array +/* Hub class-specific descriptor is constructed dynamically */ -static __u8 root_hub_hub_des[] = -{ - 0x00, * __u8 bLength; * - 0x29, * __u8 bDescriptorType; Hub-descriptor * - 0x02, * __u8 bNbrPorts; * - 0x00, * __u16 wHubCharacteristics; * - 0x00, - 0x01, * __u8 bPwrOn2pwrGood; 2ms * - 0x00, * __u8 bHubContrCurrent; 0 mA * - 0x00, * __u8 DeviceRemovable; *** 8 Ports max *** * - 0xff * __u8 PortPwrCtrlMask; *** 8 ports max *** * -}; -*/ /*-------------------------------------------------------------------------*/ @@ -1201,13 +1353,16 @@ __u8 data[8]; - num_ports = readl (&ohci->regs->roothub.a) & 0xff; - *(__u8 *) data = (readl (&ohci->regs->roothub.status) & 0x00030000) > 0? 1: 0; + num_ports = readl (&ohci->regs->roothub.a) & RH_A_NDP; + *(__u8 *) data = (readl (&ohci->regs->roothub.status) & (RH_HS_LPSC | RH_HS_OCIC)) + ? 1: 0; ret = *(__u8 *) data; for ( i = 0; i < num_ports; i++) { *(__u8 *) (data + (i + 1) / 8) |= - ((readl (&ohci->regs->roothub.portstatus[i]) & 0x001f0000) > 0? 1: 0) << ((i + 1) % 8); + ((readl (&ohci->regs->roothub.portstatus[i]) & + (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC | RH_PS_OCIC | RH_PS_PRSC)) + ? 1: 0) << ((i + 1) % 8); ret += *(__u8 *) (data + (i + 1) / 8); } len = i/8 + 1; @@ -1221,7 +1376,7 @@ /*-------------------------------------------------------------------------*/ -/* Virtual Root Hub INTs are polled by this timer every "intervall" ms */ +/* Virtual Root Hub INTs are polled by this timer every "interval" ms */ static void rh_int_timer_do (unsigned long ptr) { @@ -1267,10 +1422,10 @@ /*-------------------------------------------------------------------------*/ -#define OK(x) len = (x); break +#define OK(x) len = (x); break #define WR_RH_STAT(x) writel((x), &ohci->regs->roothub.status) #define WR_RH_PORTSTAT(x) writel((x), &ohci->regs->roothub.portstatus[wIndex-1]) -#define RD_RH_STAT readl(&ohci->regs->roothub.status) +#define RD_RH_STAT readl(&ohci->regs->roothub.status) #define RD_RH_PORTSTAT readl(&ohci->regs->roothub.portstatus[wIndex-1]) /* request to virtual root hub */ @@ -1309,6 +1464,10 @@ wValue = le16_to_cpu (cmd->value); wIndex = le16_to_cpu (cmd->index); wLength = le16_to_cpu (cmd->length); + + dbg ("rh_submit_urb, req = %d(%x) len=%d", bmRType_bReq, + bmRType_bReq, wLength); + switch (bmRType_bReq) { /* Request Destination: without flags: Device, @@ -1325,7 +1484,9 @@ case RH_GET_STATUS | RH_ENDPOINT: *(__u16 *) data_buf = cpu_to_le16 (0); OK (2); case RH_GET_STATUS | RH_CLASS: - *(__u32 *) data_buf = cpu_to_le32 (RD_RH_STAT & 0x7fff7fff); OK (4); + *(__u32 *) data_buf = cpu_to_le32 ( + RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE)); + OK (4); case RH_GET_STATUS | RH_OTHER | RH_CLASS: *(__u32 *) data_buf = cpu_to_le32 (RD_RH_PORTSTAT); OK (4); @@ -1370,11 +1531,15 @@ case (RH_PORT_SUSPEND): WR_RH_PORTSTAT (RH_PS_PSS ); OK (0); case (RH_PORT_RESET): /* BUG IN HUP CODE *********/ - if((RD_RH_PORTSTAT &1) != 0) WR_RH_PORTSTAT (RH_PS_PRS ); OK (0); + if (RD_RH_PORTSTAT & RH_PS_CCS) + WR_RH_PORTSTAT (RH_PS_PRS); + OK (0); case (RH_PORT_POWER): WR_RH_PORTSTAT (RH_PS_PPS ); OK (0); case (RH_PORT_ENABLE): /* BUG IN HUP CODE *********/ - if((RD_RH_PORTSTAT &1) != 0) WR_RH_PORTSTAT (RH_PS_PES ); OK (0); + if (RD_RH_PORTSTAT & RH_PS_CCS) + WR_RH_PORTSTAT (RH_PS_PES ); + OK (0); } break; @@ -1438,11 +1603,13 @@ case RH_SET_CONFIGURATION: WR_RH_STAT (0x10000); OK (0); default: + dbg ("unsupported root hub command"); status = TD_CC_STALL; } - dbg("USB HC roothubstat1: %x", readl ( &(ohci->regs->roothub.portstatus[0]) )); - dbg("USB HC roothubstat2: %x", readl ( &(ohci->regs->roothub.portstatus[1]) )); +#ifdef DEBUG + ohci_dump_roothub (ohci, 0); +#endif len = min(len, leni); if (data != data_buf) @@ -1473,39 +1640,44 @@ * HC functions *-------------------------------------------------------------------------*/ -/* reset the HC not the BUS */ +/* reset the HC and BUS */ -static void hc_reset (ohci_t * ohci) +static int hc_reset (ohci_t * ohci) { int timeout = 30; int smm_timeout = 50; /* 0,5 sec */ - if (readl (&ohci->regs->control) & 0x100) { /* SMM owns the HC */ - writel (0x08, &ohci->regs->cmdstatus); /* request ownership */ + if (readl (&ohci->regs->control) & OHCI_CTRL_IR) { /* SMM owns the HC */ + writel (OHCI_OCR, &ohci->regs->cmdstatus); /* request ownership */ dbg("USB HC TakeOver from SMM"); - while (readl (&ohci->regs->control) & 0x100) { + while (readl (&ohci->regs->control) & OHCI_CTRL_IR) { wait_ms (10); if (--smm_timeout == 0) { err("USB HC TakeOver failed!"); - break; + return -1; } } } - writel ((1 << 31), &ohci->regs->intrdisable); /* Disable HC interrupts */ + /* Disable HC interrupts */ + writel (OHCI_INTR_MIE, &ohci->regs->intrdisable); + dbg("USB HC reset_hc: %x ;", readl (&ohci->regs->control)); - /* this seems to be needed for the lucent controller on powerbooks.. */ - writel (0, &ohci->regs->control); /* Move USB to reset state */ + + /* Reset USB (needed by some controllers) */ + writel (0, &ohci->regs->control); - writel (1, &ohci->regs->cmdstatus); /* HC Reset */ - while ((readl (&ohci->regs->cmdstatus) & 0x01) != 0) { /* 10us Reset */ + /* HC Reset requires max 10 ms delay */ + writel (OHCI_HCR, &ohci->regs->cmdstatus); + while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) { if (--timeout == 0) { err("USB HC reset timed out!"); - return; + return -1; } udelay (1); } ohci->disabled = 0; + return 0; } /*-------------------------------------------------------------------------*/ @@ -1516,7 +1688,7 @@ static int hc_start (ohci_t * ohci) { - unsigned int mask; + __u32 mask; unsigned int fminterval; struct usb_device * usb_dev; struct ohci_device * dev; @@ -1535,31 +1707,35 @@ writel (fminterval, &ohci->regs->fminterval); writel (0x628, &ohci->regs->lsthresh); + /* start controller operations */ + ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; + writel (ohci->hc_control, &ohci->regs->control); + /* Choose the interrupts we care about now, others later on demand */ mask = OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_WDH | OHCI_INTR_SO; - - writel (ohci->hc_control = 0xBF, &ohci->regs->control); /* USB Operational */ writel (mask, &ohci->regs->intrenable); writel (mask, &ohci->regs->intrstatus); -#ifdef OHCI_USE_NPS - writel ((readl(&ohci->regs->roothub.a) | 0x200) & ~0x100, +#ifdef OHCI_USE_NPS + writel ((readl(&ohci->regs->roothub.a) | RH_A_NPS) & ~RH_A_PSM, &ohci->regs->roothub.a); - writel (0x10000, &ohci->regs->roothub.status); + writel (RH_HS_LPSC, &ohci->regs->roothub.status); + // POTPGT delay is bits 24-31, in 2 ms units. mdelay ((readl(&ohci->regs->roothub.a) >> 23) & 0x1fe); -#endif /* OHCI_USE_NPS */ +#endif /* OHCI_USE_NPS */ /* connect the virtual root hub */ - + ohci->rh.devnum = 0; usb_dev = usb_alloc_dev (NULL, ohci->bus); - if (!usb_dev) return -1; + if (!usb_dev) + return -ENOMEM; dev = usb_to_ohci (usb_dev); ohci->bus->root_hub = usb_dev; usb_connect (usb_dev); if (usb_new_device (usb_dev) != 0) { usb_free_dev (usb_dev); - return -1; + return -ENODEV; } return 0; @@ -1582,11 +1758,12 @@ return; } - dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca.frame_no)); - + // dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca.frame_no)); + if (ints & OHCI_INTR_UE) { ohci->disabled++; err ("OHCI Unrecoverable Error, controller disabled"); + // e.g. due to PCI Master/Target Abort } if (ints & OHCI_INTR_WDH) { @@ -1661,8 +1838,9 @@ dbg("USB HC release ohci"); /* disconnect all devices */ - if (ohci->bus->root_hub) usb_disconnect (&ohci->bus->root_hub); - + if (ohci->bus->root_hub) + usb_disconnect (&ohci->bus->root_hub); + hc_reset (ohci); writel (OHCI_USB_RESET, &ohci->regs->control); wait_ms (10); @@ -1698,6 +1876,7 @@ #endif printk(KERN_INFO __FILE__ ": USB OHCI at membase 0x%lx, IRQ %s\n", (unsigned long) mem_base, bufp); + printk(KERN_INFO __FILE__ ": %s\n", dev->name); ohci = hc_alloc_ohci (mem_base); if (!ohci) { @@ -1707,12 +1886,16 @@ INIT_LIST_HEAD (&ohci->ohci_hcd_list); list_add (&ohci->ohci_hcd_list, &ohci_hcd_list); - hc_reset (ohci); + if (hc_reset (ohci) < 0) { + hc_release_ohci (ohci); + return -ENODEV; + } + writel (ohci->hc_control = OHCI_USB_RESET, &ohci->regs->control); wait_ms (10); usb_register_bus (ohci->bus); - if (request_irq (irq, hc_interrupt, SA_SHIRQ, "ohci-usb", ohci) == 0) { + if (request_irq (irq, hc_interrupt, SA_SHIRQ, "usb-ohci", ohci) == 0) { struct pm_dev *pmdev; ohci->irq = irq; @@ -1724,6 +1907,10 @@ if (pmdev) pmdev->data = ohci; +#ifdef DEBUG + ohci_dump (ohci, 1); +#endif + return 0; } err("request interrupt %d failed", irq); @@ -1787,7 +1974,8 @@ case PBOOK_WAKE: writel (ohci->hc_control = OHCI_USB_RESUME, &ohci->regs->control); wait_ms (20); - writel (ohci->hc_control = 0xBF, &ohci->regs->control); + ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; + writel (ohci->hc_control, &ohci->regs->control); enable_irq (ohci->irq); break; } @@ -1801,22 +1989,24 @@ #endif /* CONFIG_PMAC_PBOOK */ /*-------------------------------------------------------------------------*/ - + static int handle_pm_event (struct pm_dev *dev, pm_request_t rqst, void *data) { ohci_t * ohci = (ohci_t*) dev->data; + int temp = 0; + if (ohci) { switch (rqst) { case PM_SUSPEND: - dbg("USB-Bus suspend: %p", ohci); - writel (ohci->hc_control = 0xFF, &ohci->regs->control); - wait_ms (10); + dbg("USB-Bus suspend: %p", ohci->regs); + if (ohci->bus->root_hub) + usb_disconnect (&ohci->bus->root_hub); + hc_reset (ohci); break; case PM_RESUME: - dbg("USB-Bus resume: %p", ohci); - writel (ohci->hc_control = 0x7F, &ohci->regs->control); - wait_ms (20); - writel (ohci->hc_control = 0xBF, &ohci->regs->control); + dbg("USB-Bus resume: %p", ohci->regs); + if ((temp = hc_reset (ohci)) < 0 || (temp = hc_start (ohci)) < 0) + err ("can't restart controller, %d", temp); break; } } diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/usb-storage.c linux/drivers/usb/usb-storage.c --- v2.3.99-pre3/linux/drivers/usb/usb-storage.c Mon Mar 27 08:08:28 2000 +++ linux/drivers/usb/usb-storage.c Wed Apr 5 17:01:25 2000 @@ -27,7 +27,6 @@ #include #include #include -#include #include #include @@ -39,14 +38,6 @@ #include "usb-storage.h" #include "usb-storage-debug.h" -/* - * This is the size of the structure Scsi_Host_Template. We create - * an instance of this structure in this file and this is a check - * to see if this structure may have changed within the SCSI module. - * This is by no means foolproof, but it does help us some. - */ -#define SCSI_HOST_TEMPLATE_SIZE (104) - /* direction table -- this indicates the direction of the data * transfer for each command code -- a 1 indicates input */ @@ -76,7 +67,11 @@ /* we allocate one of these for every device that we remember */ struct us_data { struct us_data *next; /* next device */ + + /* the device we're working with */ + struct semaphore dev_semaphore; /* protect pusb_dev */ struct usb_device *pusb_dev; /* this usb_device */ + unsigned int flags; /* from filter initially */ /* information about the device -- only good if device is attached */ @@ -113,7 +108,7 @@ unsigned int irqpipe; /* pipe for release_irq */ /* mutual exclusion structures */ - struct semaphore notify; /* wait for thread to begin */ + struct semaphore notify; /* thread begin/end */ struct semaphore sleeper; /* to sleep on */ struct semaphore queue_exclusion; /* to protect data structs */ }; @@ -131,7 +126,7 @@ /* The list of structures and the protective lock for them */ static struct us_data *us_list; -spinlock_t us_list_spinlock = SPIN_LOCK_UNLOCKED; +struct semaphore us_list_semaphore; static void * storage_probe(struct usb_device *dev, unsigned int ifnum); static void storage_disconnect(struct usb_device *dev, void *ptr); @@ -249,547 +244,267 @@ { int i; unsigned int total = 0; + struct scatterlist *sg; - /* always zero for some commands */ - switch (srb->cmnd[0]) { - case SEEK_6: - case SEEK_10: - case REZERO_UNIT: - case ALLOW_MEDIUM_REMOVAL: - case START_STOP: - case TEST_UNIT_READY: - return 0; - - /* FIXME: these should be removed and tested */ - case REQUEST_SENSE: - case INQUIRY: - case MODE_SENSE: - return srb->cmnd[4]; - - /* FIXME: these should be removed and tested */ - case LOG_SENSE: - case MODE_SENSE_10: - return (srb->cmnd[7] << 8) + srb->cmnd[8]; - - default: - break; - } - + /* Are we going to scatter gather? */ if (srb->use_sg) { - struct scatterlist *sg; - + /* Add up the sizes of all the scatter-gather segments */ sg = (struct scatterlist *) srb->request_buffer; - for (i = 0; i < srb->use_sg; i++) { + for (i = 0; i < srb->use_sg; i++) total += sg[i].length; - } + return total; } else + /* Just return the length of the buffer */ return srb->request_bufflen; } /*********************************************************************** - * Protocol routines + * Transport routines ***********************************************************************/ -static void ATAPI_command(Scsi_Cmnd *srb, struct us_data *us) +/* Invoke the transport and basic error-handling/recovery methods + * + * This is used by the protocol layers to actually send the message to + * the device and recieve the response. + */ +static void invoke_transport(Scsi_Cmnd *srb, struct us_data *us) { - int old_cmnd = 0; + int need_auto_sense; int result; - - /* Fix some commands -- this is a form of mode translation - * ATAPI devices only accept 12 byte long commands - * - * NOTE: This only works because a Scsi_Cmnd struct field contains - * a unsigned char cmnd[12], so we know we have storage available - */ - - /* set command length to 12 bytes */ - srb->cmd_len = 12; - - /* determine the correct (or minimum) data length for these commands */ - switch (us->srb->cmnd[0]) { - - /* change MODE_SENSE/MODE_SELECT from 6 to 10 byte commands */ - case MODE_SENSE: - case MODE_SELECT: - /* save the command so we can tell what it was */ - old_cmnd = srb->cmnd[0]; - - srb->cmnd[11] = 0; - srb->cmnd[10] = 0; - srb->cmnd[9] = 0; - srb->cmnd[8] = srb->cmnd[4]; - srb->cmnd[7] = 0; - srb->cmnd[6] = 0; - srb->cmnd[5] = 0; - srb->cmnd[4] = 0; - srb->cmnd[3] = 0; - srb->cmnd[2] = srb->cmnd[2]; - srb->cmnd[1] = srb->cmnd[1]; - srb->cmnd[0] = srb->cmnd[0] | 0x40; - break; - /* change READ_6/WRITE_6 to READ_10/WRITE_10, which - * are ATAPI commands */ - case WRITE_6: - case READ_6: - srb->cmnd[11] = 0; - srb->cmnd[10] = 0; - srb->cmnd[9] = 0; - srb->cmnd[8] = srb->cmnd[4]; - srb->cmnd[7] = 0; - srb->cmnd[6] = 0; - srb->cmnd[5] = srb->cmnd[3]; - srb->cmnd[4] = srb->cmnd[2]; - srb->cmnd[3] = srb->cmnd[1] & 0x1F; - srb->cmnd[2] = 0; - srb->cmnd[1] = srb->cmnd[1] & 0xE0; - srb->cmnd[0] = srb->cmnd[0] | 0x20; - break; - } /* end switch on cmnd[0] */ - /* send the command to the transport layer */ result = us->transport(srb, us); - /* If we got a short transfer, but it was for a command that - * can have short transfers, we're actually okay + /* Determine if we need to auto-sense + * + * I normally don't use a flag like this, but it's almost impossible + * to understand what's going on here if I don't. */ - if ((us->srb->result == US_BULK_TRANSFER_SHORT) && - ((us->srb->cmnd[0] == REQUEST_SENSE) || - (us->srb->cmnd[0] == INQUIRY) || - (us->srb->cmnd[0] == MODE_SENSE) || - (us->srb->cmnd[0] == LOG_SENSE) || - (us->srb->cmnd[0] == MODE_SENSE_10))) { - us->srb->result = DID_OK; + need_auto_sense = 0; + + /* + * If we're running the CB transport, which is incapable + * of determining status on it's own, we need to auto-sense almost + * every time. + */ + if (us->protocol == US_PR_CB) { + US_DEBUGP("-- CB transport device requiring auto-sense\n"); + need_auto_sense = 1; + + /* There are some exceptions to this. Notably, if this is + * a UFI device and the command is REQUEST_SENSE or INQUIRY, + * then it is impossible to truly determine status. + */ + if (us->subclass == US_SC_UFI && + ((srb->cmnd[0] == REQUEST_SENSE) || + (srb->cmnd[0] == INQUIRY))) + need_auto_sense = 0; + } + + /* + * If we have an error, we're going to do a REQUEST_SENSE + * automatically. Note that we differentiate between a command + * "failure" and an "error" in the transport mechanism. + */ + if (result == USB_STOR_TRANSPORT_FAILED) { + US_DEBUGP("-- transport indicates command failure\n"); + need_auto_sense = 1; + } + if (result == USB_STOR_TRANSPORT_ERROR) { + /* FIXME: we need to invoke a transport reset here */ + US_DEBUGP("-- transport indicates transport failure\n"); + need_auto_sense = 0; + srb->result = DID_ERROR << 16; + return; } /* - * If we have an error, we're going to do a - * REQUEST_SENSE automatically + * Also, if we have a short transfer on a command that can't have + * a short transfer, we're going to do this. */ - if (result != USB_STOR_TRANSPORT_GOOD) { + if ((srb->result == US_BULK_TRANSFER_SHORT) && + !((srb->cmnd[0] == REQUEST_SENSE) || + (srb->cmnd[0] == INQUIRY) || + (srb->cmnd[0] == MODE_SENSE) || + (srb->cmnd[0] == LOG_SENSE) || + (srb->cmnd[0] == MODE_SENSE_10))) { + US_DEBUGP("-- unexpectedly short transfer\n"); + need_auto_sense = 1; + } + + /* Now, if we need to do the auto-sense, let's do it */ + if (need_auto_sense) { int temp_result; void* old_request_buffer; int old_sg; US_DEBUGP("Command FAILED: Issuing auto-REQUEST_SENSE\n"); - us->srb->cmnd[0] = REQUEST_SENSE; - us->srb->cmnd[1] = 0; - us->srb->cmnd[2] = 0; - us->srb->cmnd[3] = 0; - us->srb->cmnd[4] = 18; - us->srb->cmnd[5] = 0; + srb->cmnd[0] = REQUEST_SENSE; + srb->cmnd[1] = 0; + srb->cmnd[2] = 0; + srb->cmnd[3] = 0; + srb->cmnd[4] = 18; + srb->cmnd[5] = 0; /* set the buffer length for transfer */ - old_request_buffer = us->srb->request_buffer; - old_sg = us->srb->use_sg; - us->srb->request_bufflen = 18; - us->srb->request_buffer = us->srb->sense_buffer; + old_request_buffer = srb->request_buffer; + old_sg = srb->use_sg; + srb->request_bufflen = 18; + srb->request_buffer = us->srb->sense_buffer; /* FIXME: what if this command fails? */ temp_result = us->transport(us->srb, us); US_DEBUGP("-- Result from auto-sense is %d\n", temp_result); US_DEBUGP("-- sense key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n", - us->srb->sense_buffer[2] & 0xf, - us->srb->sense_buffer[12], - us->srb->sense_buffer[13]); + srb->sense_buffer[2] & 0xf, + srb->sense_buffer[12], + srb->sense_buffer[13]); /* set the result so the higher layers expect this data */ - us->srb->result = CHECK_CONDITION; + srb->result = CHECK_CONDITION; /* we're done here */ - us->srb->request_buffer = old_request_buffer; - us->srb->use_sg = old_sg; - return; - } - - /* Fix the MODE_SENSE data if we translated the command - */ - if (old_cmnd == MODE_SENSE) { - unsigned char *dta = (unsigned char *)us->srb->request_buffer; - - /* FIXME: we need to compress the entire data structure here - */ - dta[0] = dta[1]; /* data len */ - dta[1] = dta[2]; /* med type */ - dta[2] = dta[3]; /* dev-spec prm */ - dta[3] = dta[7]; /* block desc len */ - printk (KERN_DEBUG USB_STORAGE - "new MODE_SENSE_6 data = %.2X %.2X %.2X %.2X\n", - dta[0], dta[1], dta[2], dta[3]); + srb->request_buffer = old_request_buffer; + srb->use_sg = old_sg; } - /* Fix-up the return data from an INQUIRY command to show - * ANSI SCSI rev 2 so we don't confuse the SCSI layers above us - */ - if (us->srb->cmnd[0] == INQUIRY) { - ((unsigned char *)us->srb->request_buffer)[2] |= 0x2; - } + /* Set return code, if necessary */ + if (need_auto_sense && (srb->sense_buffer[0] == 0x0)) + srb->result = GOOD; + if (!need_auto_sense) + srb->result = GOOD; } - -static void ufi_command(Scsi_Cmnd *srb, struct us_data *us) +/* + * Control/Bulk/Interrupt transport + */ +static int CBI_irq(int state, void *buffer, int len, void *dev_id) { - int old_cmnd = 0; - int result; - - /* fix some commands -- this is a form of mode translation - * UFI devices only accept 12 byte long commands - * - * NOTE: This only works because a Scsi_Cmnd struct field contains - * a unsigned char cmnd[12], so we know we have storage available - */ - - /* set command length to 12 bytes (this affects the transport layer) */ - srb->cmd_len = 12; - - /* determine the correct (or minimum) data length for these commands */ - switch (us->srb->cmnd[0]) { - - /* for INQUIRY, UFI devices only ever return 36 bytes */ - case INQUIRY: - us->srb->cmnd[4] = 36; - break; - - /* change MODE_SENSE/MODE_SELECT from 6 to 10 byte commands */ - case MODE_SENSE: - case MODE_SELECT: - /* save the command so we can tell what it was */ - old_cmnd = srb->cmnd[0]; - - srb->cmnd[11] = 0; - srb->cmnd[10] = 0; - srb->cmnd[9] = 0; - - /* if we're sending data, we send all. If getting data, - * get the minimum */ - if (srb->cmnd[0] == MODE_SELECT) - srb->cmnd[8] = srb->cmnd[4]; - else - srb->cmnd[8] = 8; - - srb->cmnd[7] = 0; - srb->cmnd[6] = 0; - srb->cmnd[5] = 0; - srb->cmnd[4] = 0; - srb->cmnd[3] = 0; - srb->cmnd[2] = srb->cmnd[2]; - srb->cmnd[1] = srb->cmnd[1]; - srb->cmnd[0] = srb->cmnd[0] | 0x40; - break; + struct us_data *us = (struct us_data *)dev_id; - /* again, for MODE_SENSE_10, we get the minimum (8) */ - case MODE_SENSE_10: - us->srb->cmnd[7] = 0; - us->srb->cmnd[8] = 8; - break; - - /* for REQUEST_SENSE, UFI devices only ever return 18 bytes */ - case REQUEST_SENSE: - us->srb->cmnd[4] = 18; - break; + US_DEBUGP("USB IRQ recieved for device on host %d\n", us->host_no); + US_DEBUGP("-- IRQ data length is %d\n", len); + US_DEBUGP("-- IRQ state is %d\n", state); - /* change READ_6/WRITE_6 to READ_10/WRITE_10, which - * are UFI commands */ - case WRITE_6: - case READ_6: - srb->cmnd[11] = 0; - srb->cmnd[10] = 0; - srb->cmnd[9] = 0; - srb->cmnd[8] = srb->cmnd[4]; - srb->cmnd[7] = 0; - srb->cmnd[6] = 0; - srb->cmnd[5] = srb->cmnd[3]; - srb->cmnd[4] = srb->cmnd[2]; - srb->cmnd[3] = srb->cmnd[1] & 0x1F; - srb->cmnd[2] = 0; - srb->cmnd[1] = srb->cmnd[1] & 0xE0; - srb->cmnd[0] = srb->cmnd[0] | 0x20; - break; - } /* end switch on cmnd[0] */ + /* is the device removed? */ + if (state != -ENOENT) { + /* save the data for interpretation later */ + us->ip_data = le16_to_cpup((__u16 *)buffer); + US_DEBUGP("-- Interrupt Status 0x%x\n", us->ip_data); - /* send the command to the transport layer */ - result = us->transport(srb, us); + /* was this a wanted interrupt? */ + if (us->ip_wanted) { + us->ip_wanted = 0; + up(&(us->ip_waitq)); + } else + US_DEBUGP("ERROR: Unwanted interrupt received!\n"); + } else + US_DEBUGP("-- device has been removed\n"); - /* If we got a short transfer, but it was for a command that - * can have short transfers, we're actually okay + /* This return code is truly meaningless -- and I mean truly. It gets + * ignored by other layers. It used to indicate if we wanted to get + * another interrupt or disable the interrupt callback */ - if ((us->srb->result == US_BULK_TRANSFER_SHORT) && - ((us->srb->cmnd[0] == REQUEST_SENSE) || - (us->srb->cmnd[0] == INQUIRY) || - (us->srb->cmnd[0] == MODE_SENSE) || - (us->srb->cmnd[0] == LOG_SENSE) || - (us->srb->cmnd[0] == MODE_SENSE_10))) { - us->srb->result = DID_OK; - } + return 0; +} - /* - * If we have an error, we're going to do a - * REQUEST_SENSE automatically - */ - if (result != USB_STOR_TRANSPORT_GOOD) { - int temp_result; - void* old_request_buffer; - int old_sg; +static int CBI_transport(Scsi_Cmnd *srb, struct us_data *us) +{ + int result; - US_DEBUGP("Command FAILED: Issuing auto-REQUEST_SENSE\n"); + /* COMMAND STAGE */ + /* let's send the command via the control pipe */ + result = usb_control_msg(us->pusb_dev, + usb_sndctrlpipe(us->pusb_dev,0), US_CBI_ADSC, + USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, + us->ifnum, srb->cmnd, srb->cmd_len, HZ*5); - us->srb->cmnd[0] = REQUEST_SENSE; - us->srb->cmnd[1] = 0; - us->srb->cmnd[2] = 0; - us->srb->cmnd[3] = 0; - us->srb->cmnd[4] = 18; - us->srb->cmnd[5] = 0; - - /* set the buffer length for transfer */ - old_request_buffer = us->srb->request_buffer; - old_sg = us->srb->use_sg; - us->srb->request_bufflen = 18; - us->srb->request_buffer = us->srb->sense_buffer; + /* check the return code for the command */ + US_DEBUGP("Call to usb_control_msg() returned %d\n", result); + if (result < 0) { + /* STALL must be cleared when they are detected */ + if (result == -EPIPE) { + US_DEBUGP("-- Stall on control pipe. Clearing\n"); + result = usb_clear_halt(us->pusb_dev, + usb_sndctrlpipe(us->pusb_dev, + 0)); + US_DEBUGP("-- usb_clear_halt() returns %d\n", result); + return USB_STOR_TRANSPORT_FAILED; + } - /* FIXME: what if this command fails? */ - temp_result = us->transport(us->srb, us); - US_DEBUGP("-- Result from auto-sense is %d\n", temp_result); - US_DEBUGP("-- sense key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n", - us->srb->sense_buffer[2] & 0xf, - us->srb->sense_buffer[12], - us->srb->sense_buffer[13]); + /* Uh oh... serious problem here */ + return USB_STOR_TRANSPORT_ERROR; + } - /* set the result so the higher layers expect this data */ - us->srb->result = CHECK_CONDITION; + /* Set up for status notification */ + us->ip_wanted = 1; - /* we're done here */ - us->srb->request_buffer = old_request_buffer; - us->srb->use_sg = old_sg; - return; + /* DATA STAGE */ + /* transfer the data payload for this command, if one exists*/ + if (us_transfer_length(srb)) { + us_transfer(srb, US_DIRECTION(srb->cmnd[0])); + US_DEBUGP("CBI data stage result is 0x%x\n", srb->result); } - - /* Fix the MODE_SENSE data here if we had to translate the command - */ - if (old_cmnd == MODE_SENSE) { - unsigned char *dta = (unsigned char *)us->srb->request_buffer; - /* FIXME: we need to compress the entire data structure here - */ - dta[0] = dta[1]; /* data len */ - dta[1] = dta[2]; /* med type */ - dta[2] = dta[3]; /* dev-spec prm */ - dta[3] = dta[7]; /* block desc len */ - printk (KERN_DEBUG USB_STORAGE - "new MODE_SENSE_6 data = %.2X %.2X %.2X %.2X\n", - dta[0], dta[1], dta[2], dta[3]); - } + /* STATUS STAGE */ - /* Fix-up the return data from an INQUIRY command to show - * ANSI SCSI rev 2 so we don't confuse the SCSI layers above us - */ - if (us->srb->cmnd[0] == INQUIRY) { - ((unsigned char *)us->srb->request_buffer)[2] |= 0x2; - } -} - -static void transparent_scsi_command(Scsi_Cmnd *srb, struct us_data *us) -{ - unsigned int result = 0; - - /* This code supports devices which do not support {READ|WRITE}_6 - * Apparently, neither Windows or MacOS will use these commands, - * so some devices do not support them - */ - if (us->flags & US_FL_MODE_XLATE) { - - /* translate READ_6 to READ_10 */ - if (us->srb->cmnd[0] == 0x08) { - - /* get the control */ - us->srb->cmnd[9] = us->srb->cmnd[5]; - - /* get the length */ - us->srb->cmnd[8] = us->srb->cmnd[6]; - us->srb->cmnd[7] = 0; - - /* set the reserved area to 0 */ - us->srb->cmnd[6] = 0; - - /* get LBA */ - us->srb->cmnd[5] = us->srb->cmnd[3]; - us->srb->cmnd[4] = us->srb->cmnd[2]; - us->srb->cmnd[3] = 0; - us->srb->cmnd[2] = 0; - - /* LUN and other info in cmnd[1] can stay */ - - /* fix command code */ - us->srb->cmnd[0] = 0x28; - - US_DEBUGP("Changing READ_6 to READ_10\n"); - US_DEBUG(us_show_command(us->srb)); - } - - /* translate WRITE_6 to WRITE_10 */ - if (us->srb->cmnd[0] == 0x0A) { - - /* get the control */ - us->srb->cmnd[9] = us->srb->cmnd[5]; - - /* get the length */ - us->srb->cmnd[8] = us->srb->cmnd[4]; - us->srb->cmnd[7] = 0; - - /* set the reserved area to 0 */ - us->srb->cmnd[6] = 0; - - /* get LBA */ - us->srb->cmnd[5] = us->srb->cmnd[3]; - us->srb->cmnd[4] = us->srb->cmnd[2]; - us->srb->cmnd[3] = 0; - us->srb->cmnd[2] = 0; - - /* LUN and other info in cmnd[1] can stay */ - - /* fix command code */ - us->srb->cmnd[0] = 0x2A; - - US_DEBUGP("Changing WRITE_6 to WRITE_10\n"); - US_DEBUG(us_show_command(us->srb)); - } - } /* if (us->flags & US_FL_MODE_XLATE) */ - - /* send the command to the transport layer */ - result = us->transport(us->srb, us); - - /* If we got a short transfer, but it was for a command that - * can have short transfers, we're actually okay - */ - if ((us->srb->result == US_BULK_TRANSFER_SHORT) && - ((us->srb->cmnd[0] == REQUEST_SENSE) || - (us->srb->cmnd[0] == INQUIRY) || - (us->srb->cmnd[0] == MODE_SENSE) || - (us->srb->cmnd[0] == LOG_SENSE) || - (us->srb->cmnd[0] == MODE_SENSE_10))) { - us->srb->result = DID_OK; - } - - /* if we have an error, we're going to do a REQUEST_SENSE - * automatically */ - if (result != USB_STOR_TRANSPORT_GOOD) { - int temp_result; - int old_sg; - void* old_request_buffer; - - US_DEBUGP("Command FAILED: Issuing auto-REQUEST_SENSE\n"); - - /* set up the REQUEST_SENSE command and parameters */ - us->srb->cmnd[0] = REQUEST_SENSE; - us->srb->cmnd[1] = 0; - us->srb->cmnd[2] = 0; - us->srb->cmnd[3] = 0; - us->srb->cmnd[4] = 18; - us->srb->cmnd[5] = 0; - - /* set the buffer length for transfer */ - old_request_buffer = us->srb->request_buffer; - old_sg = us->srb->use_sg; - us->srb->request_bufflen = 18; - us->srb->request_buffer = us->srb->sense_buffer; - - /* FIXME: what if this command fails? */ - temp_result = us->transport(us->srb, us); - US_DEBUGP("-- Result from auto-sense is %d\n", temp_result); - US_DEBUGP("-- sense key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n", - us->srb->sense_buffer[2] & 0xf, - us->srb->sense_buffer[12], - us->srb->sense_buffer[13]); - - /* set the result so the higher layers expect this data */ - us->srb->result = CHECK_CONDITION; - - /* we're done here */ - us->srb->use_sg = old_sg; - us->srb->request_buffer = old_request_buffer; - return; - } - - /* fix the results of an INQUIRY */ - if (us->srb->cmnd[0] == INQUIRY) { - US_DEBUGP("Fixing INQUIRY data, setting SCSI rev to 2\n"); - ((unsigned char*)us->srb->request_buffer)[2] |= 2; - } -} - -/*********************************************************************** - * Transport routines - ***********************************************************************/ - -static int CBI_irq(int state, void *buffer, int len, void *dev_id) -{ - struct us_data *us = (struct us_data *)dev_id; - - US_DEBUGP("USB IRQ recieved for device on host %d\n", us->host_no); - - /* save the data for interpretation later */ - if (state != USB_ST_REMOVED) { - us->ip_data = le16_to_cpup((__u16 *)buffer); - US_DEBUGP("Interrupt Status 0x%x\n", us->ip_data); - } - - /* was this a wanted interrupt? */ + /* go to sleep until we get this interrupt */ + down(&(us->ip_waitq)); + + /* if we were woken up by a reset instead of the actual interrupt */ if (us->ip_wanted) { + US_DEBUGP("Did not get interrupt on CBI\n"); us->ip_wanted = 0; - up(&(us->ip_waitq)); - } else { - US_DEBUGP("ERROR: Unwanted interrupt received!\n"); + return USB_STOR_TRANSPORT_ERROR; } - - /* This return code is truly meaningless -- and I mean truly. It gets - * ignored by other layers. It used to indicate if we wanted to get - * another interrupt or disable the interrupt callback + + US_DEBUGP("Got interrupt data 0x%x\n", us->ip_data); + + /* UFI gives us ASC and ASCQ, like a request sense + * + * REQUEST_SENSE and INQUIRY don't affect the sense data on UFI + * devices, so we ignore the information for those commands. Note + * that this means we could be ignoring a real error on these + * commands, but that can't be helped. */ - return 0; -} - -/* This issues a CB[I] Reset to the device in question - */ -static int CB_reset(struct us_data *us) -{ - unsigned char cmd[12]; - int result; - - US_DEBUGP("CB_reset\n"); - - memset(cmd, 0xFF, sizeof(cmd)); - cmd[0] = SEND_DIAGNOSTIC; - cmd[1] = 4; - result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0), - US_CBI_ADSC, - USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0, us->ifnum, cmd, sizeof(cmd), HZ*5); - - /* long wait for reset */ - schedule_timeout(HZ*6); - - US_DEBUGP("CB_reset: clearing endpoint halt\n"); - usb_clear_halt(us->pusb_dev, - usb_rcvbulkpipe(us->pusb_dev, us->ep_in)); - usb_clear_halt(us->pusb_dev, - usb_rcvbulkpipe(us->pusb_dev, us->ep_out)); + if (us->subclass == US_SC_UFI) { + if (srb->cmnd[0] == REQUEST_SENSE || + srb->cmnd[0] == INQUIRY) + return USB_STOR_TRANSPORT_GOOD; + else + if (us->ip_data) + return USB_STOR_TRANSPORT_FAILED; + else + return USB_STOR_TRANSPORT_GOOD; + } + + /* If not UFI, we interpret the data as a result code + * The first byte should always be a 0x0 + * The second byte & 0x0F should be 0x0 for good, otherwise error + */ + switch ((us->ip_data & 0xFF0F)) { + case 0x0000: + return USB_STOR_TRANSPORT_GOOD; + case 0x0001: + return USB_STOR_TRANSPORT_FAILED; + default: + return USB_STOR_TRANSPORT_ERROR; + } - US_DEBUGP("CB_reset done\n"); - return 0; + US_DEBUGP("CBI_transport() reached end of function\n"); + return USB_STOR_TRANSPORT_ERROR; } /* - * Control/Bulk/Interrupt transport + * Control/Bulk transport */ -static int CBI_transport(Scsi_Cmnd *srb, struct us_data *us) +static int CB_transport(Scsi_Cmnd *srb, struct us_data *us) { int result; - US_DEBUGP("CBI gets a command:\n"); - US_DEBUG(us_show_command(srb)); - /* COMMAND STAGE */ /* let's send the command via the control pipe */ result = usb_control_msg(us->pusb_dev, @@ -798,142 +513,449 @@ us->ifnum, srb->cmnd, srb->cmd_len, HZ*5); /* check the return code for the command */ - US_DEBUGP("Call to usb_control_msg() returned %d\n", result); if (result < 0) { + US_DEBUGP("Call to usb_control_msg() returned %d\n", result); + /* a stall is a fatal condition from the device */ if (result == -EPIPE) { US_DEBUGP("-- Stall on control pipe. Clearing\n"); - US_DEBUGP("-- Return from usb_clear_halt() is %d\n", - usb_clear_halt(us->pusb_dev, - usb_sndctrlpipe(us->pusb_dev, - 0))); - return USB_STOR_TRANSPORT_ERROR; + result = usb_clear_halt(us->pusb_dev, + usb_sndctrlpipe(us->pusb_dev, + 0)); + US_DEBUGP("-- usb_clear_halt() returns %d\n", result); + return USB_STOR_TRANSPORT_FAILED; } - /* FIXME: we need to handle NAKs here */ + /* Uh oh... serious problem here */ return USB_STOR_TRANSPORT_ERROR; } - /* Set up for status notification */ - us->ip_wanted = 1; - /* DATA STAGE */ /* transfer the data payload for this command, if one exists*/ if (us_transfer_length(srb)) { us_transfer(srb, US_DIRECTION(srb->cmnd[0])); - US_DEBUGP("CBI data stage result is 0x%x\n", result); + US_DEBUGP("CB data stage result is 0x%x\n", srb->result); } - + + /* STATUS STAGE */ + /* NOTE: CB does not have a status stage. Silly, I know. So + * we have to catch this at a higher level. + */ + return USB_STOR_TRANSPORT_GOOD; +} - /* go to sleep until we get this interrupt */ - down(&(us->ip_waitq)); +/* + * Bulk only transport + */ +static int Bulk_transport(Scsi_Cmnd *srb, struct us_data *us) +{ + struct bulk_cb_wrap bcb; + struct bulk_cs_wrap bcs; + int result; + int pipe; + int partial; - /* if we were woken up by a reset instead of the actual interrupt */ - if (us->ip_wanted) { - US_DEBUGP("Did not get interrupt on CBI\n"); - us->ip_wanted = 0; - return USB_STOR_TRANSPORT_ERROR; + /* set up the command wrapper */ + bcb.Signature = US_BULK_CB_SIGN; + bcb.DataTransferLength = us_transfer_length(srb); + bcb.Flags = US_DIRECTION(srb->cmnd[0]) << 7; + bcb.Tag = srb->serial_number; + bcb.Lun = srb->cmnd[1] >> 5; + bcb.Length = srb->cmd_len; + + /* construct the pipe handle */ + pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out); + + /* copy the command payload */ + memset(bcb.CDB, 0, sizeof(bcb.CDB)); + memcpy(bcb.CDB, srb->cmnd, bcb.Length); + + /* send it to out endpoint */ + US_DEBUGP("Bulk command S 0x%x T 0x%x LUN %d L %d F %d CL %d\n", + bcb.Signature, bcb.Tag, bcb.Lun, bcb.DataTransferLength, + bcb.Flags, bcb.Length); + result = usb_bulk_msg(us->pusb_dev, pipe, &bcb, + US_BULK_CB_WRAP_LEN, &partial, HZ*5); + US_DEBUGP("Bulk command transfer result=%d\n", result); + + /* if we stall, we need to clear it before we go on */ + if (result == -EPIPE) { + US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); + usb_clear_halt(us->pusb_dev, pipe); } - US_DEBUGP("Got interrupt data 0x%x\n", us->ip_data); + /* if the command transfered well, then we go to the data stage */ + if (result == 0) { + /* send/receive data payload, if there is any */ + if (bcb.DataTransferLength) { + us_transfer(srb, bcb.Flags); + US_DEBUGP("Bulk data transfer result 0x%x\n", + srb->result); + } + } - /* UFI gives us ASC and ASCQ, like a request sense - * - * REQUEST_SENSE and INQUIRY don't affect the sense data, so we - * ignore the information for those commands + /* See flow chart on pg 15 of the Bulk Only Transport spec for + * an explanation of how this code works. */ - if (us->subclass == US_SC_UFI) { - if (srb->cmnd[0] == REQUEST_SENSE || - srb->cmnd[0] == INQUIRY) - return USB_STOR_TRANSPORT_GOOD; - else - if (us->ip_data) - return USB_STOR_TRANSPORT_FAILED; - else - return USB_STOR_TRANSPORT_GOOD; + + /* construct the pipe handle */ + pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in); + + /* get CSW for device status */ + result = usb_bulk_msg(us->pusb_dev, pipe, &bcs, + US_BULK_CS_WRAP_LEN, &partial, HZ*5); + + /* did the attempt to read the CSW fail? */ + if (result == -EPIPE) { + US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); + usb_clear_halt(us->pusb_dev, pipe); + + /* get the status again */ + result = usb_bulk_msg(us->pusb_dev, pipe, &bcs, + US_BULK_CS_WRAP_LEN, &partial, HZ*5); + + /* if it fails again, we need a reset and return an error*/ + if (result == -EPIPE) { + return USB_STOR_TRANSPORT_ERROR; + } } - /* otherwise, we interpret the data normally */ - switch (us->ip_data) { - case 0x0001: + /* if we still have a failure at this point, we're in trouble */ + if (result) { + US_DEBUGP("Bulk status result = %d\n", result); + return USB_STOR_TRANSPORT_ERROR; + } + + /* check bulk status */ + US_DEBUGP("Bulk status S 0x%x T 0x%x R %d V 0x%x\n", + bcs.Signature, bcs.Tag, bcs.Residue, bcs.Status); + if (bcs.Signature != US_BULK_CS_SIGN || bcs.Tag != bcb.Tag || + bcs.Status > US_BULK_STAT_PHASE || partial != 13) { + US_DEBUGP("Bulk logical error\n"); + return USB_STOR_TRANSPORT_ERROR; + } + + /* based on the status code, we report good or bad */ + switch (bcs.Status) { + case US_BULK_STAT_OK: + /* command good -- note that we could be short on data */ return USB_STOR_TRANSPORT_GOOD; - case 0x0002: + + case US_BULK_STAT_FAIL: + /* command failed */ return USB_STOR_TRANSPORT_FAILED; - default: + + case US_BULK_STAT_PHASE: + /* phase error */ return USB_STOR_TRANSPORT_ERROR; } + + /* we should never get here, but if we do, we're in trouble */ + return USB_STOR_TRANSPORT_ERROR; +} + +/*********************************************************************** + * Protocol routines + ***********************************************************************/ + +static void ATAPI_command(Scsi_Cmnd *srb, struct us_data *us) +{ + int old_cmnd = 0; + + /* Fix some commands -- this is a form of mode translation + * ATAPI devices only accept 12 byte long commands + * + * NOTE: This only works because a Scsi_Cmnd struct field contains + * a unsigned char cmnd[12], so we know we have storage available + */ + + /* set command length to 12 bytes */ + srb->cmd_len = 12; + + /* determine the correct (or minimum) data length for these commands */ + switch (srb->cmnd[0]) { + + /* change MODE_SENSE/MODE_SELECT from 6 to 10 byte commands */ + case MODE_SENSE: + case MODE_SELECT: + /* save the command so we can tell what it was */ + old_cmnd = srb->cmnd[0]; + + srb->cmnd[11] = 0; + srb->cmnd[10] = 0; + srb->cmnd[9] = 0; + srb->cmnd[8] = srb->cmnd[4]; + srb->cmnd[7] = 0; + srb->cmnd[6] = 0; + srb->cmnd[5] = 0; + srb->cmnd[4] = 0; + srb->cmnd[3] = 0; + srb->cmnd[2] = srb->cmnd[2]; + srb->cmnd[1] = srb->cmnd[1]; + srb->cmnd[0] = srb->cmnd[0] | 0x40; + break; + + /* change READ_6/WRITE_6 to READ_10/WRITE_10, which + * are ATAPI commands */ + case WRITE_6: + case READ_6: + srb->cmnd[11] = 0; + srb->cmnd[10] = 0; + srb->cmnd[9] = 0; + srb->cmnd[8] = srb->cmnd[4]; + srb->cmnd[7] = 0; + srb->cmnd[6] = 0; + srb->cmnd[5] = srb->cmnd[3]; + srb->cmnd[4] = srb->cmnd[2]; + srb->cmnd[3] = srb->cmnd[1] & 0x1F; + srb->cmnd[2] = 0; + srb->cmnd[1] = srb->cmnd[1] & 0xE0; + srb->cmnd[0] = srb->cmnd[0] | 0x20; + break; + } /* end switch on cmnd[0] */ + + /* send the command to the transport layer */ + invoke_transport(srb, us); + + /* Fix the MODE_SENSE data if we translated the command + */ + if (old_cmnd == MODE_SENSE) { + unsigned char *dta = (unsigned char *)us->srb->request_buffer; + + /* FIXME: we need to compress the entire data structure here + */ + dta[0] = dta[1]; /* data len */ + dta[1] = dta[2]; /* med type */ + dta[2] = dta[3]; /* dev-spec prm */ + dta[3] = dta[7]; /* block desc len */ + printk (KERN_DEBUG USB_STORAGE + "new MODE_SENSE_6 data = %.2X %.2X %.2X %.2X\n", + dta[0], dta[1], dta[2], dta[3]); + } + + /* Fix-up the return data from an INQUIRY command to show + * ANSI SCSI rev 2 so we don't confuse the SCSI layers above us + */ + if (srb->cmnd[0] == INQUIRY) { + ((unsigned char *)us->srb->request_buffer)[2] |= 0x2; + } +} + + +static void ufi_command(Scsi_Cmnd *srb, struct us_data *us) +{ + int old_cmnd = 0; + + /* fix some commands -- this is a form of mode translation + * UFI devices only accept 12 byte long commands + * + * NOTE: This only works because a Scsi_Cmnd struct field contains + * a unsigned char cmnd[12], so we know we have storage available + */ + + /* set command length to 12 bytes (this affects the transport layer) */ + srb->cmd_len = 12; + + /* determine the correct (or minimum) data length for these commands */ + switch (srb->cmnd[0]) { + + /* for INQUIRY, UFI devices only ever return 36 bytes */ + case INQUIRY: + srb->cmnd[4] = 36; + break; + + /* change MODE_SENSE/MODE_SELECT from 6 to 10 byte commands */ + case MODE_SENSE: + case MODE_SELECT: + /* save the command so we can tell what it was */ + old_cmnd = srb->cmnd[0]; + + srb->cmnd[11] = 0; + srb->cmnd[10] = 0; + srb->cmnd[9] = 0; + + /* if we're sending data, we send all. If getting data, + * get the minimum */ + if (srb->cmnd[0] == MODE_SELECT) + srb->cmnd[8] = srb->cmnd[4]; + else + srb->cmnd[8] = 8; + + srb->cmnd[7] = 0; + srb->cmnd[6] = 0; + srb->cmnd[5] = 0; + srb->cmnd[4] = 0; + srb->cmnd[3] = 0; + srb->cmnd[2] = srb->cmnd[2]; + srb->cmnd[1] = srb->cmnd[1]; + srb->cmnd[0] = srb->cmnd[0] | 0x40; + break; + + /* again, for MODE_SENSE_10, we get the minimum (8) */ + case MODE_SENSE_10: + srb->cmnd[7] = 0; + srb->cmnd[8] = 8; + break; + + /* for REQUEST_SENSE, UFI devices only ever return 18 bytes */ + case REQUEST_SENSE: + srb->cmnd[4] = 18; + break; + + /* change READ_6/WRITE_6 to READ_10/WRITE_10, which + * are UFI commands */ + case WRITE_6: + case READ_6: + srb->cmnd[11] = 0; + srb->cmnd[10] = 0; + srb->cmnd[9] = 0; + srb->cmnd[8] = srb->cmnd[4]; + srb->cmnd[7] = 0; + srb->cmnd[6] = 0; + srb->cmnd[5] = srb->cmnd[3]; + srb->cmnd[4] = srb->cmnd[2]; + srb->cmnd[3] = srb->cmnd[1] & 0x1F; + srb->cmnd[2] = 0; + srb->cmnd[1] = srb->cmnd[1] & 0xE0; + srb->cmnd[0] = srb->cmnd[0] | 0x20; + break; + } /* end switch on cmnd[0] */ + + /* send the command to the transport layer */ + invoke_transport(srb, us); + + /* Fix the MODE_SENSE data here if we had to translate the command + */ + if (old_cmnd == MODE_SENSE) { + unsigned char *dta = (unsigned char *)us->srb->request_buffer; + + /* FIXME: we need to compress the entire data structure here + */ + dta[0] = dta[1]; /* data len */ + dta[1] = dta[2]; /* med type */ + dta[2] = dta[3]; /* dev-spec prm */ + dta[3] = dta[7]; /* block desc len */ + printk (KERN_DEBUG USB_STORAGE + "new MODE_SENSE_6 data = %.2X %.2X %.2X %.2X\n", + dta[0], dta[1], dta[2], dta[3]); + } + + /* Fix-up the return data from an INQUIRY command to show + * ANSI SCSI rev 2 so we don't confuse the SCSI layers above us + */ + if (srb->cmnd[0] == INQUIRY) { + ((unsigned char *)us->srb->request_buffer)[2] |= 0x2; + } +} + +static void transparent_scsi_command(Scsi_Cmnd *srb, struct us_data *us) +{ + /* This code supports devices which do not support {READ|WRITE}_6 + * Apparently, neither Windows or MacOS will use these commands, + * so some devices do not support them + */ + if (us->flags & US_FL_MODE_XLATE) { + + /* translate READ_6 to READ_10 */ + if (srb->cmnd[0] == 0x08) { + + /* get the control */ + srb->cmnd[9] = us->srb->cmnd[5]; + + /* get the length */ + srb->cmnd[8] = us->srb->cmnd[6]; + srb->cmnd[7] = 0; + + /* set the reserved area to 0 */ + srb->cmnd[6] = 0; + + /* get LBA */ + srb->cmnd[5] = us->srb->cmnd[3]; + srb->cmnd[4] = us->srb->cmnd[2]; + srb->cmnd[3] = 0; + srb->cmnd[2] = 0; + + /* LUN and other info in cmnd[1] can stay */ + + /* fix command code */ + srb->cmnd[0] = 0x28; + + US_DEBUGP("Changing READ_6 to READ_10\n"); + US_DEBUG(us_show_command(srb)); + } + + /* translate WRITE_6 to WRITE_10 */ + if (srb->cmnd[0] == 0x0A) { + + /* get the control */ + srb->cmnd[9] = us->srb->cmnd[5]; + + /* get the length */ + srb->cmnd[8] = us->srb->cmnd[4]; + srb->cmnd[7] = 0; + + /* set the reserved area to 0 */ + srb->cmnd[6] = 0; + + /* get LBA */ + srb->cmnd[5] = us->srb->cmnd[3]; + srb->cmnd[4] = us->srb->cmnd[2]; + srb->cmnd[3] = 0; + srb->cmnd[2] = 0; + + /* LUN and other info in cmnd[1] can stay */ + + /* fix command code */ + srb->cmnd[0] = 0x2A; - US_DEBUGP("CBI_transport() reached end of function\n"); - return USB_STOR_TRANSPORT_ERROR; + US_DEBUGP("Changing WRITE_6 to WRITE_10\n"); + US_DEBUG(us_show_command(us->srb)); + } + } /* if (us->flags & US_FL_MODE_XLATE) */ + + /* send the command to the transport layer */ + invoke_transport(srb, us); + + /* fix the results of an INQUIRY */ + if (srb->cmnd[0] == INQUIRY) { + US_DEBUGP("Fixing INQUIRY data, setting SCSI rev to 2\n"); + ((unsigned char*)us->srb->request_buffer)[2] |= 2; + } } -/* - * Control/Bulk transport +/*********************************************************************** + * Reset routines + ***********************************************************************/ + +/* This issues a CB[I] Reset to the device in question */ -static int CB_transport(Scsi_Cmnd *srb, struct us_data *us) +static int CB_reset(struct us_data *us) { + unsigned char cmd[12]; int result; - __u8 status[2]; - - US_DEBUGP("CBC gets a command:\n"); - US_DEBUG(us_show_command(srb)); - - /* COMMAND STAGE */ - /* let's send the command via the control pipe */ - result = usb_control_msg(us->pusb_dev, - usb_sndctrlpipe(us->pusb_dev,0), US_CBI_ADSC, - USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, - us->ifnum, srb->cmnd, srb->cmd_len, HZ*5); - - /* check the return code for the command */ - if (result < 0) { - US_DEBUGP("Call to usb_control_msg() returned %d\n", result); - /* a stall is a fatal condition from the device */ - if (result == -EPIPE) { - US_DEBUGP("-- Stall on control pipe. Clearing\n"); - US_DEBUGP("-- Return from usb_clear_halt() is %d\n", - usb_clear_halt(us->pusb_dev, - usb_sndctrlpipe(us->pusb_dev, - 0))); - return USB_STOR_TRANSPORT_ERROR; - } + US_DEBUGP("CB_reset() called\n"); - /* FIXME: we need to handle NAKs here */ - return USB_STOR_TRANSPORT_ERROR; - } + memset(cmd, 0xFF, sizeof(cmd)); + cmd[0] = SEND_DIAGNOSTIC; + cmd[1] = 4; + result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0), + US_CBI_ADSC, + USB_TYPE_CLASS | USB_RECIP_INTERFACE, + 0, us->ifnum, cmd, sizeof(cmd), HZ*5); - /* DATA STAGE */ - /* transfer the data payload for this command, if one exists*/ - if (us_transfer_length(srb)) { - us_transfer(srb, US_DIRECTION(srb->cmnd[0])); - US_DEBUGP("CBC data stage result is 0x%x\n", result); - } - - - /* STATUS STAGE */ - /* FIXME: this is wrong */ - result = usb_control_msg(us->pusb_dev, - usb_rcvctrlpipe(us->pusb_dev,0), - USB_REQ_GET_STATUS, USB_DIR_IN | - USB_TYPE_STANDARD | USB_RECIP_DEVICE, - 0, us->ifnum, status, sizeof(status), HZ*5); + /* long wait for reset */ + schedule_timeout(HZ*6); - if (result < 0) { - US_DEBUGP("CBC Status stage returns %d\n", result); - return USB_STOR_TRANSPORT_ERROR; - } + US_DEBUGP("CB_reset: clearing endpoint halt\n"); + usb_clear_halt(us->pusb_dev, + usb_rcvbulkpipe(us->pusb_dev, us->ep_in)); + usb_clear_halt(us->pusb_dev, + usb_rcvbulkpipe(us->pusb_dev, us->ep_out)); - US_DEBUGP("Got CB status 0x%x 0x%x\n", status[0], status[1]); - if (srb->cmnd[0] != REQUEST_SENSE && srb->cmnd[0] != INQUIRY && - ( (status[0] & ~3) || status[1])) - return USB_STOR_TRANSPORT_FAILED; - else - return USB_STOR_TRANSPORT_GOOD; - - US_DEBUGP("CB_transport() reached end of function\n"); - return USB_STOR_TRANSPORT_ERROR; + US_DEBUGP("CB_reset done\n"); + return 0; } /* FIXME: Does this work? */ @@ -961,135 +983,31 @@ return result; } -/* - * Bulk only transport - */ -static int Bulk_transport(Scsi_Cmnd *srb, struct us_data *us) -{ - struct bulk_cb_wrap bcb; - struct bulk_cs_wrap bcs; - int result; - int pipe; - int partial; - - /* set up the command wrapper */ - bcb.Signature = US_BULK_CB_SIGN; - bcb.DataTransferLength = us_transfer_length(srb); - bcb.Flags = US_DIRECTION(srb->cmnd[0]) << 7; - bcb.Tag = srb->serial_number; - bcb.Lun = 0; - bcb.Length = srb->cmd_len; - - /* construct the pipe handle */ - pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out); - - /* copy the command payload */ - memset(bcb.CDB, 0, sizeof(bcb.CDB)); - memcpy(bcb.CDB, srb->cmnd, bcb.Length); - - /* send it to out endpoint */ - US_DEBUGP("Bulk command S 0x%x T 0x%x L %d F %d CL %d\n", - bcb.Signature, bcb.Tag, bcb.DataTransferLength, - bcb.Flags, bcb.Length); - result = usb_bulk_msg(us->pusb_dev, pipe, &bcb, - US_BULK_CB_WRAP_LEN, &partial, HZ*5); - US_DEBUGP("Bulk command transfer result=%d\n", result); - - /* if we stall, we need to clear it before we go on */ - if (result == -EPIPE) { - US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); - usb_clear_halt(us->pusb_dev, pipe); - } - - /* if the command transfered well, then we go to the data stage */ - if (result == 0) { - /* send/receive data payload, if there is any */ - if (bcb.DataTransferLength) { - us_transfer(srb, bcb.Flags); - US_DEBUGP("Bulk data transfer result 0x%x\n", - srb->result); - } - } - - /* See flow chart on pg 15 of the Bulk Only Transport spec for - * an explanation of how this code works. - */ - - /* construct the pipe handle */ - pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in); - - /* get CSW for device status */ - result = usb_bulk_msg(us->pusb_dev, pipe, &bcs, - US_BULK_CS_WRAP_LEN, &partial, HZ*5); - - /* did the attempt to read the CSW fail? */ - if (result == -EPIPE) { - US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); - usb_clear_halt(us->pusb_dev, pipe); - - /* get the status again */ - result = usb_bulk_msg(us->pusb_dev, pipe, &bcs, - US_BULK_CS_WRAP_LEN, &partial, HZ*5); - - /* if it fails again, we need a reset and return an error*/ - if (result == -EPIPE) { - Bulk_reset(us); - return USB_STOR_TRANSPORT_ERROR; - } - } - - /* if we still have a failure at this point, we're in trouble */ - if (result) { - US_DEBUGP("Bulk status result = %d\n", result); - return USB_STOR_TRANSPORT_ERROR; - } - - /* check bulk status */ - US_DEBUGP("Bulk status S 0x%x T 0x%x R %d V 0x%x\n", - bcs.Signature, bcs.Tag, bcs.Residue, bcs.Status); - if (bcs.Signature != US_BULK_CS_SIGN || bcs.Tag != bcb.Tag || - bcs.Status > US_BULK_STAT_PHASE || partial != 13) { - US_DEBUGP("Bulk logical error\n"); - return USB_STOR_TRANSPORT_ERROR; - } - - /* based on the status code, we report good or bad */ - switch (bcs.Status) { - case US_BULK_STAT_OK: - /* command good -- note that we could be short on data */ - return USB_STOR_TRANSPORT_GOOD; - - case US_BULK_STAT_FAIL: - /* command failed */ - return USB_STOR_TRANSPORT_FAILED; - - case US_BULK_STAT_PHASE: - /* phase error */ - Bulk_reset(us); - return USB_STOR_TRANSPORT_ERROR; - } - - /* we should never get here, but if we do, we're in trouble */ - return USB_STOR_TRANSPORT_ERROR; -} - /*********************************************************************** * Host functions ***********************************************************************/ -/* detect adapter (always true ) */ +static const char* us_info(struct Scsi_Host *host) +{ + return "SCSI emulation for USB Mass Storage devices\n"; +} + +/* detect a virtual adapter (always works) */ static int us_detect(struct SHT *sht) { - /* FIXME - not nice at all, but how else ? */ - struct us_data *us = (struct us_data *)sht->proc_dir; - char name[32]; - - /* set up our name */ - sprintf(name, "usbscsi%d", us->host_number); - sht->name = sht->proc_name = kmalloc(strlen(name)+1, GFP_KERNEL); + struct us_data *us; + char local_name[32]; + + /* This is not nice at all, but how else are we to get the + * data here? */ + us = (struct us_data *)sht->proc_dir; + + /* set up the name of our subdirectory under /proc/scsi/ */ + sprintf(local_name, "usb-storage-%d", us->host_number); + sht->proc_name = kmalloc (strlen(local_name) + 1, GFP_KERNEL); if (!sht->proc_name) return 0; - strcpy(sht->proc_name, name); + strcpy(sht->proc_name, local_name); /* we start with no /proc directory entry */ sht->proc_dir = NULL; @@ -1105,36 +1023,34 @@ /* odd... didn't register properly. Abort and free pointers */ kfree(sht->proc_name); sht->proc_name = NULL; - sht->name = NULL; return 0; } -/* release - must be here to stop scsi - * from trying to release IRQ etc. - * Kill off our data +/* Release all resources used by the virtual host + * + * NOTE: There is no contention here, because we're allready deregistered + * the driver and we're doing each virtual host in turn, not in parallel */ static int us_release(struct Scsi_Host *psh) { struct us_data *us = (struct us_data *)psh->hostdata[0]; - unsigned long flags; - int result; - - /* lock the data structures */ - spin_lock_irqsave(&us_list_spinlock, flags); US_DEBUGP("us_release() called for host %s\n", us->htmplt.name); - /* release the interrupt handler, if necessary */ - if (us->irq_handle) { - US_DEBUGP("-- releasing irq\n"); - result = usb_release_irq(us->pusb_dev, us->irq_handle, - us->irqpipe); - US_DEBUGP("-- usb_release_irq() returned %d\n", result); - us->irq_handle = NULL; - } - - /* lock the data structures */ - spin_unlock_irqrestore(&us_list_spinlock, flags); + /* Kill the control threads + * + * Enqueue the command, wake up the thread, and wait for + * notification that it's exited. + */ + US_DEBUGP("-- sending US_ACT_EXIT command to thread\n"); + us->action = US_ACT_EXIT; + up(&(us->sleeper)); + down(&(us->notify)); + + /* free the data structure we were using */ + US_DEBUGP("-- freeing private host data structure\n"); + kfree(us); + (struct us_data*)psh->hostdata[0] = NULL; /* we always have a successful release */ return 0; @@ -1171,20 +1087,38 @@ return 0; } -/* FIXME: This doesn't actually abort anything */ +/*********************************************************************** + * Error handling functions + ***********************************************************************/ + +/* Command abort + * + * Note that this is really only meaningful right now for CBI transport + * devices which have failed to give us the command completion interrupt + */ static int us_abort( Scsi_Cmnd *srb ) { - return 0; + struct us_data *us = (struct us_data *)srb->host->hostdata[0]; + + US_DEBUGP("us_abort() called\n"); + + /* if we're stuck waiting for an IRQ, simulate it */ + if (us->ip_wanted) { + US_DEBUGP("-- simulating missing IRQ\n"); + up(&(us->ip_waitq)); + return SUCCESS; + } + + return FAILED; } /* FIXME: this doesn't do anything right now */ static int us_bus_reset( Scsi_Cmnd *srb ) { - struct us_data *us = (struct us_data *)srb->host->hostdata[0]; + // struct us_data *us = (struct us_data *)srb->host->hostdata[0]; + printk(KERN_CRIT "usb-storage: bus_reset() requested but not implemented\n" ); US_DEBUGP("Bus reset requested\n"); - if (us->ip_wanted) - up(&(us->ip_waitq)); // us->transport_reset(us); return SUCCESS; } @@ -1192,6 +1126,7 @@ /* FIXME: This doesn't actually reset anything */ static int us_host_reset( Scsi_Cmnd *srb ) { + printk(KERN_CRIT "usb-storage: host_reset() requested but not implemented\n" ); return 0; } @@ -1209,14 +1144,13 @@ struct us_data *us; char *pos = buffer; char *tmp_ptr; - unsigned long flags; /* if someone is sending us data, just throw it away */ if (inout) return length; /* lock the data structures */ - spin_lock_irqsave(&us_list_spinlock, flags); + down(&us_list_semaphore); /* find our data from hostno */ us = us_list; @@ -1228,7 +1162,7 @@ /* if we couldn't find it, we return an error */ if (!us) { - spin_unlock_irqrestore(&us_list_spinlock, flags); + up(&us_list_semaphore); return -ESRCH; } @@ -1274,11 +1208,42 @@ break; } + SPRINTF(" Transport: "); + switch (us->subclass) { + case US_SC_RBC: + SPRINTF("Reduced Block Commands\n"); + break; + + case US_SC_8020: + SPRINTF("8020i\n"); + break; + + case US_SC_QIC: + SPRINTF("QIC-157\n"); + break; + + case US_SC_8070: + SPRINTF("8070i\n"); + break; + + case US_SC_SCSI: + SPRINTF("Transparent SCSI\n"); + break; + + case US_SC_UFI: + SPRINTF("Uniform Floppy Interface\n"); + break; + + default: + SPRINTF("Unknown Transport\n"); + break; + } + /* show the GUID of the device */ SPRINTF(" GUID: " GUID_FORMAT "\n", GUID_ARGS(us->guid)); /* release our lock on the data structures */ - spin_unlock_irqrestore(&us_list_spinlock, flags); + up(&us_list_semaphore); /* * Calculate start of next buffer, and return value. @@ -1298,36 +1263,30 @@ */ static Scsi_Host_Template my_host_template = { - NULL, /* next */ - NULL, /* module */ - NULL, /* proc_dir */ - usb_stor_proc_info, - NULL, /* name - points to unique */ - us_detect, - us_release, - NULL, /* info */ - NULL, /* ioctl */ - us_command, - us_queuecommand, - NULL, /* eh_strategy */ - us_abort, - us_bus_reset, - us_bus_reset, - us_host_reset, - NULL, /* abort */ - NULL, /* reset */ - NULL, /* slave_attach */ - NULL, /* bios_param */ - NULL, /* select_queue_depths */ - 1, /* can_queue */ - -1, /* this_id */ - SG_ALL, /* sg_tablesize */ - 1, /* cmd_per_lun */ - 0, /* present */ - FALSE, /* unchecked_isa_dma */ - TRUE, /* use_clustering */ - TRUE, /* use_new_eh_code */ - TRUE /* emulated */ + name: "usb-storage", + proc_info: usb_stor_proc_info, + info: us_info, + + detect: us_detect, + release: us_release, + command: us_command, + queuecommand: us_queuecommand, + + eh_abort_handler: us_abort, + eh_device_reset_handler:us_bus_reset, + eh_bus_reset_handler: us_bus_reset, + eh_host_reset_handler: us_host_reset, + + can_queue: 1, + this_id: -1, + + sg_tablesize: SG_ALL, + cmd_per_lun: 1, + present: 0, + unchecked_isa_dma: FALSE, + use_clustering: TRUE, + use_new_eh_code: TRUE, + emulated: TRUE, }; static unsigned char sense_notready[] = { @@ -1362,10 +1321,11 @@ */ daemonize(); - sprintf(current->comm, "usbscsi%d", us->host_number); + sprintf(current->comm, "usb-storage-%d", us->host_number); unlock_kernel(); + /* signal that we've started the thread */ up(&(us->notify)); for(;;) { @@ -1382,14 +1342,10 @@ /* release the queue lock as fast as possible */ up(&(us->queue_exclusion)); - /* FIXME: we need to examine placment of break; and - * scsi_done() calls */ - switch (action) { case US_ACT_COMMAND: /* bad device */ - /* FIXME: we need to enable and test multiple LUNs */ - if (us->srb->target || us->srb->lun) { + if (us->srb->target) { US_DEBUGP( "Bad device number (%d/%d) or dev 0x%x\n", us->srb->target, us->srb->lun, (unsigned int)us->pusb_dev); us->srb->result = DID_BAD_TARGET << 16; @@ -1399,6 +1355,9 @@ break; } + /* lock the device pointers */ + down(&(us->dev_semaphore)); + /* our device has gone - pretend not ready */ /* FIXME: we also need to handle INQUIRY here, * probably */ @@ -1414,6 +1373,10 @@ us->srb->result = (DID_OK << 16) | 2; } + /* unlock the device pointers */ + up(&(us->dev_semaphore)); + + /* indicate that the command is done */ us->srb->scsi_done(us->srb); us->srb = NULL; break; @@ -1434,6 +1397,11 @@ US_DEBUGP("scsi cmd done, result=0x%x\n", us->srb->result); + + /* unlock the device pointers */ + up(&(us->dev_semaphore)); + + /* indicate that the command is done */ us->srb->scsi_done(us->srb); us->srb = NULL; break; @@ -1453,11 +1421,15 @@ } /* end switch on action */ /* exit if we get a signal to exit */ - if (action == US_ACT_EXIT) + if (action == US_ACT_EXIT) { + US_DEBUGP("-- US_ACT_EXIT command recieved\n"); break; + } } /* for (;;) */ - printk("usb_stor_control_thread exiting\n"); + /* notify the exit routine that we're actually exiting now */ + up(&(us->notify)); + return 0; } @@ -1471,7 +1443,6 @@ struct us_data *ss = NULL; GUID(guid); /* Global Unique Identifier */ int result; - unsigned long flags; /* these are temporary copies -- we test on these, then put them * in the us-data structure @@ -1531,9 +1502,6 @@ &ss->irq_handle); if (result < 0) return NULL; - - /* FIXME: what is this?? */ - down(&(ss->ip_waitq)); } /* @@ -1613,7 +1581,7 @@ } /* lock access to the data structures */ - spin_lock_irqsave(&us_list_spinlock, flags); + down(&us_list_semaphore); /* * Now check if we have seen this GUID before @@ -1655,7 +1623,7 @@ if ((ss = (struct us_data *)kmalloc(sizeof(struct us_data), GFP_KERNEL)) == NULL) { printk(KERN_WARNING USB_STORAGE "Out of memory\n"); - spin_unlock_irqrestore(&us_list_spinlock, flags); + up(&us_list_semaphore); return NULL; } memset(ss, 0, sizeof(struct us_data)); @@ -1664,6 +1632,7 @@ init_MUTEX_LOCKED(&(ss->sleeper)); init_MUTEX_LOCKED(&(ss->notify)); init_MUTEX(&(ss->queue_exclusion)); + init_MUTEX(&(ss->dev_semaphore)); /* copy over the subclass and protocol data */ ss->subclass = subclass; @@ -1725,7 +1694,7 @@ break; case US_SC_QIC: - US_DEBUGPX("QIC157\n"); + US_DEBUGPX("QIC-157\n"); break; case US_SC_8070: @@ -1774,9 +1743,9 @@ /* Grab the next host number */ ss->host_number = my_host_number++; - /* FIXME: this is bad. We abuse this pointer so we - * can pass the ss pointer to the host controler thread - * in us_detect + /* We abuse this pointer so we can pass the ss pointer to + * the host controler thread in us_detect. But how else are + * we to do it? */ (struct us_data *)ss->htmplt.proc_dir = ss; @@ -1795,7 +1764,7 @@ down(&(ss->notify)); /* now register - our detect function will be called */ - ss->htmplt.module = &__this_module; + ss->htmplt.module = THIS_MODULE; scsi_register_module(MODULE_SCSI_HA, &(ss->htmplt)); /* put us in the list */ @@ -1804,7 +1773,7 @@ } /* release the data structure lock */ - spin_unlock_irqrestore(&us_list_spinlock, flags); + up(&us_list_semaphore); printk(KERN_DEBUG "WARNING: USB Mass Storage data integrity not assured\n"); @@ -1829,6 +1798,9 @@ return; } + /* lock access to the device data structure */ + down(&(ss->dev_semaphore)); + /* release the IRQ, if we have one */ if (ss->irq_handle) { US_DEBUGP("-- releasing irq handle\n"); @@ -1840,6 +1812,9 @@ /* mark the device as gone */ ss->pusb_dev = NULL; + + /* lock access to the device data structure */ + up(&(ss->dev_semaphore)); } @@ -1849,18 +1824,10 @@ int __init usb_stor_init(void) { - /* - * Check to see if the host template is a different size from - * what we're expected -- people have updated this in the past - * and forgotten about this driver. - */ - if (sizeof(my_host_template) != SCSI_HOST_TEMPLATE_SIZE) { - printk(KERN_ERR "usb-storage: SCSI_HOST_TEMPLATE_SIZE bad\n"); - printk(KERN_ERR - "usb-storage: expected %d bytes, got %d bytes\n", - SCSI_HOST_TEMPLATE_SIZE, sizeof(my_host_template)) ; - return -1 ; - } + /* initialize internal global data elements */ + us_list = NULL; + init_MUTEX(&us_list_semaphore); + my_host_number = 0; /* register the driver, return -1 if error */ if (usb_register(&storage_driver) < 0) @@ -1873,36 +1840,38 @@ void __exit usb_stor_exit(void) { - static struct us_data *ptr; - static struct us_data *next; - unsigned long flags; + struct us_data *next; - /* - * deregister the driver -- this eliminates races with probes and - * disconnects + US_DEBUGP("usb_stor_exit() called\n"); + + /* Deregister the driver + * This eliminates races with probes and disconnects */ + US_DEBUGP("-- calling usb_deregister()\n"); usb_deregister(&storage_driver) ; /* lock access to the data structures */ - spin_lock_irqsave(&us_list_spinlock, flags); - - /* unregister all the virtual hosts */ - for (ptr = us_list; ptr != NULL; ptr = ptr->next) - scsi_unregister_module(MODULE_SCSI_HA, &(ptr->htmplt)); - - /* kill the threads */ - /* FIXME: we can do this by sending them a signal to die */ - - /* free up the data structures */ - /* FIXME: we need to eliminate the host structure also */ - while (ptr) { - next = ptr->next; - kfree(ptr); - ptr = next; + down(&us_list_semaphore); + + /* While there are still virtual hosts, unregister them + * + * Note that the us_release() routine will destroy the local data + * structure. So we have to peel these off the top of the list + * and keep updating the head pointer as we go. + */ + while (us_list) { + /* keep track of where the next one is */ + next = us_list->next; + + US_DEBUGP("-- calling scsi_unregister_module()\n"); + scsi_unregister_module(MODULE_SCSI_HA, &(us_list->htmplt)); + + /* advance the list pointer */ + us_list = next; } /* unlock the data structures */ - spin_unlock_irqrestore(&us_list_spinlock, flags); + up(&us_list_semaphore); } module_init(usb_stor_init) ; diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/usb-storage.h linux/drivers/usb/usb-storage.h --- v2.3.99-pre3/linux/drivers/usb/usb-storage.h Tue Mar 14 19:10:40 2000 +++ linux/drivers/usb/usb-storage.h Wed Apr 5 17:01:25 2000 @@ -129,8 +129,8 @@ } /* Flag definitions */ -#define US_FL_IP_STATUS 0x00000001 /* status uses interrupt */ -#define US_FL_FIXED_COMMAND 0x00000002 /* expand commands to fixed size */ +#define US_FL_IP_STATUS 0x00000001 /* status uses interrupt */ +#define US_FL_FIXED_COMMAND 0x00000002 /* expand commands to fixed size */ #define US_FL_MODE_XLATE 0x00000004 /* translate _6 to _10 comands for - Win/MacOS compatibility */ - + Win/MacOS compatibility */ +#define US_FL_CBI_AS_CB 0x00000008 /* treat a CBI dev as a CB dev */ diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/usb-uhci.c linux/drivers/usb/usb-uhci.c --- v2.3.99-pre3/linux/drivers/usb/usb-uhci.c Mon Mar 27 08:08:28 2000 +++ linux/drivers/usb/usb-uhci.c Wed Apr 5 17:01:25 2000 @@ -12,7 +12,7 @@ * (C) Copyright 1999 Johannes Erdfelt * (C) Copyright 1999 Randy Dunlap * - * $Id: usb-uhci.c,v 1.222 2000/03/13 21:18:02 fliegl Exp $ + * $Id: usb-uhci.c,v 1.228 2000/04/02 19:55:51 acher Exp $ */ #include @@ -50,6 +50,8 @@ /* This enables an extra UHCI slab for memory debugging */ #define DEBUG_SLAB +#define VERSTR "$Revision: 1.228 $ time " __TIME__ " " __DATE__ + #include #include "usb-uhci.h" #include "usb-uhci-debug.h" @@ -116,6 +118,26 @@ } } /*-------------------------------------------------------------------*/ +_static void uhci_switch_timer_int(uhci_t *s) +{ + + if (!list_empty(&s->urb_unlinked)) { + s->td1ms->hw.td.status |= TD_CTRL_IOC; + } + else { + s->td1ms->hw.td.status &= ~TD_CTRL_IOC; + } + + if (s->timeout_urbs) { + s->td32ms->hw.td.status |= TD_CTRL_IOC; + } + else { + s->td32ms->hw.td.status &= ~TD_CTRL_IOC; + } + + wmb(); +} +/*-------------------------------------------------------------------*/ #ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH _static void enable_desc_loop(uhci_t *s, urb_t *urb) { @@ -162,6 +184,9 @@ #endif ((urb_priv_t*)urb->hcpriv)->started=jiffies; list_add (p, &s->urb_list); + if (urb->timeout) + s->timeout_urbs++; + uhci_switch_timer_int(s); } /*-------------------------------------------------------------------*/ _static void queue_urb (uhci_t *s, urb_t *urb) @@ -185,6 +210,9 @@ #endif list_del (&urb->urb_list); + if (urb->timeout && s->timeout_urbs) + s->timeout_urbs--; + } /*-------------------------------------------------------------------*/ _static int alloc_td (uhci_desc_t ** new, int flags) @@ -439,6 +467,13 @@ clean_descs(s,1); + + if (s->td32ms) { + + unlink_td(s,s->td32ms,1); + delete_desc(s->td32ms); + } + for (n = 0; n < 8; n++) { td = s->int_chain[n]; clean_td_chain (td); @@ -531,8 +566,9 @@ if (ret) goto init_skel_cleanup; - fill_td (td, TD_CTRL_IOC, 0, 0); // generate 1ms interrupt + fill_td (td, 0 * TD_CTRL_IOC, 0, 0); // generate 1ms interrupt (enabled on demand) insert_td (s, qh, td, 0); + s->td1ms=td; dbg("allocating qh: bulk_chain"); ret = alloc_qh (&qh); @@ -597,6 +633,16 @@ ((uhci_desc_t*) s->iso_td[n])->hw.td.link = virt_to_bus (s->int_chain[o]); } + ret = alloc_td (&td, 0); + + if (ret) + goto init_skel_cleanup; + + fill_td (td, 0 * TD_CTRL_IOC, 0, 0); // generate 32ms interrupt + s->td32ms=td; + + insert_td_horizontal (s, s->int_chain[5], td); + mb(); //uhci_show_queue(s->control_chain); dbg("init_skel exit"); @@ -995,6 +1041,7 @@ if (urb->status == -EINPROGRESS) { // URB probably still in work dequeue_urb (s, urb); + uhci_switch_timer_int(s); s->unlink_urb_done=1; spin_unlock_irqrestore (&s->urb_list_lock, flags); @@ -1125,9 +1172,11 @@ if (urb->status == -EINPROGRESS) { ((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" @@ -1495,7 +1544,7 @@ (!(urb->transfer_flags & USB_QUEUE_BULK) || !(bulk_urb->transfer_flags & USB_QUEUE_BULK)))) { spin_unlock_irqrestore (&s->urb_list_lock, flags); usb_dec_dev_use (urb->dev); - err("ENXIO1 %08x, flags %x, urb %p, burb %p",urb->pipe,urb->transfer_flags,urb,bulk_urb); + err("ENXIO %08x, flags %x, urb %p, burb %p",urb->pipe,urb->transfer_flags,urb,bulk_urb); return -ENXIO; // urb already queued } } @@ -1599,6 +1648,7 @@ #endif } + s->timeout_check=jiffies; } /*------------------------------------------------------------------- @@ -1922,7 +1972,7 @@ OK (len); case (0x03): /* string descriptors */ len = usb_root_hub_string (wValue & 0xff, - uhci->io_addr, "UHCI", + uhci->io_addr, "UHCI", data, wLength); if (len > 0) { OK (min (leni, len)); @@ -2481,15 +2531,15 @@ goto restart; } } - if ((s->frame_counter & 63) == 0) + if ((jiffies - s->timeout_check) > (HZ/30)) uhci_check_timeouts(s); clean_descs(s,0); uhci_cleanup_unlink(s, 0); - + uhci_switch_timer_int(s); + spin_unlock (&s->urb_list_lock); - s->frame_counter++; outw (status, io_addr + USBSTS); //dbg("uhci_interrupt: done"); @@ -2630,12 +2680,14 @@ 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->next = devs; //chain new uhci device into global list - s->frame_counter = 0; - + s->timeout_check = 0; + s->uhci_pci=dev; + bus = usb_alloc_bus (&uhci_device_operations); if (!bus) { kfree (s); @@ -2739,6 +2791,7 @@ info("Intel USB controller: setting latency timer to %d", UHCI_LATENCY_TIMER); pci_write_config_byte(dev, PCI_LATENCY_TIMER, UHCI_LATENCY_TIMER); } + return alloc_uhci(dev, dev->irq, io_addr, io_size); } return -1; diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/usb-uhci.h linux/drivers/usb/usb-uhci.h --- v2.3.99-pre3/linux/drivers/usb/usb-uhci.h Tue Mar 14 19:10:40 2000 +++ linux/drivers/usb/usb-uhci.h Wed Apr 5 17:01:25 2000 @@ -2,10 +2,9 @@ #define __LINUX_UHCI_H /* - $Id: usb-uhci.h,v 1.50 2000/03/13 21:18:04 fliegl Exp $ + $Id: usb-uhci.h,v 1.54 2000/04/02 19:55:53 acher Exp $ */ #define MODNAME "usb-uhci" -#define VERSTR "$Revision: 1.50 $ time " __TIME__ " " __DATE__ #define UHCI_LATENCY_TIMER 0 static __inline__ void uhci_wait_ms(unsigned int ms) @@ -202,6 +201,8 @@ uhci_desc_t *control_chain; uhci_desc_t *bulk_chain; uhci_desc_t *chain_end; + uhci_desc_t *td1ms; + uhci_desc_t *td32ms; struct list_head free_desc; spinlock_t qh_lock; spinlock_t td_lock; @@ -209,7 +210,9 @@ int loop_usage; // URBs using bandwidth reclamation struct list_head urb_unlinked; // list of all unlinked urbs - int frame_counter; + long timeout_check; + int timeout_urbs; + struct pci_dev *uhci_pci; } uhci_t, *puhci_t; diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/usb.c linux/drivers/usb/usb.c --- v2.3.99-pre3/linux/drivers/usb/usb.c Mon Mar 27 08:08:28 2000 +++ linux/drivers/usb/usb.c Tue Apr 11 09:57:43 2000 @@ -24,7 +24,11 @@ #include #include #include /* for in_interrupt() */ -#define DEBUG +#ifdef CONFIG_USB_DEBUG + #define DEBUG +#else + #undef DEBUG +#endif #include /* @@ -1080,7 +1084,7 @@ int size; struct usb_descriptor_header *header; - memcpy(config, buffer, USB_DT_INTERFACE_SIZE); + memcpy(config, buffer, USB_DT_CONFIG_SIZE); le16_to_cpus(&config->wTotalLength); size = config->wTotalLength; @@ -1419,32 +1423,28 @@ static void usb_set_maxpacket(struct usb_device *dev) { - int i, j, b; - struct usb_interface *ifp; + int i, b; for (i=0; iactconfig->bNumInterfaces; i++) { - ifp = dev->actconfig->interface + i; - - for (j = 0; j < ifp->num_altsetting; j++) { - struct usb_interface_descriptor *as = ifp->altsetting + j; - struct usb_endpoint_descriptor *ep = as->endpoint; - int e; - - for (e=0; ebNumEndpoints; e++) { - b = ep[e].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; - if ((ep[e].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_CONTROL) { /* Control => bidirectional */ + struct usb_interface *ifp = dev->actconfig->interface + i; + struct usb_interface_descriptor *as = ifp->altsetting + ifp->act_altsetting; + struct usb_endpoint_descriptor *ep = as->endpoint; + int e; + + for (e=0; ebNumEndpoints; e++) { + b = ep[e].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; + if ((ep[e].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_CONTROL) { /* Control => bidirectional */ + dev->epmaxpacketout[b] = ep[e].wMaxPacketSize; + dev->epmaxpacketin [b] = ep[e].wMaxPacketSize; + } + else if (usb_endpoint_out(ep[e].bEndpointAddress)) { + if (ep[e].wMaxPacketSize > dev->epmaxpacketout[b]) dev->epmaxpacketout[b] = ep[e].wMaxPacketSize; + } + else { + if (ep[e].wMaxPacketSize > dev->epmaxpacketin [b]) dev->epmaxpacketin [b] = ep[e].wMaxPacketSize; - } - else if (usb_endpoint_out(ep[e].bEndpointAddress)) { - if (ep[e].wMaxPacketSize > dev->epmaxpacketout[b]) - dev->epmaxpacketout[b] = ep[e].wMaxPacketSize; - } - else { - if (ep[e].wMaxPacketSize > dev->epmaxpacketin [b]) - dev->epmaxpacketin [b] = ep[e].wMaxPacketSize; - } } } } @@ -1512,6 +1512,8 @@ return ret; iface->act_altsetting = alternate; + dev->toggle[0] = 0; /* 9.1.1.5 says to do this */ + dev->toggle[1] = 0; usb_set_maxpacket(dev); return 0; } @@ -1624,7 +1626,7 @@ err("config descriptor too short (expected %i, got %i)",tmp,result); kfree(bigbuffer); goto err; - } + } result = usb_parse_configuration(dev, &dev->config[cfgno], bigbuffer); kfree(bigbuffer); @@ -1638,8 +1640,8 @@ } return 0; - err: - dev->descriptor.bNumConfigurations=cfgno; +err: + dev->descriptor.bNumConfigurations = cfgno; return result; } @@ -1674,7 +1676,7 @@ dev->have_langid = -1; dev->string_langid = tbuf[2] | (tbuf[3]<< 8); /* always use the first langid listed */ - info("USB device number %d default language ID 0x%x", + dbg("USB device number %d default language ID 0x%x", dev->devnum, dev->string_langid); } } @@ -1789,14 +1791,16 @@ return -1; } - info("new device strings: Mfr=%d, Product=%d, SerialNumber=%d", + dbg("new device strings: Mfr=%d, Product=%d, SerialNumber=%d", dev->descriptor.iManufacturer, dev->descriptor.iProduct, dev->descriptor.iSerialNumber); +#ifdef DEBUG if (dev->descriptor.iManufacturer) usb_show_string(dev, "Manufacturer", dev->descriptor.iManufacturer); if (dev->descriptor.iProduct) usb_show_string(dev, "Product", dev->descriptor.iProduct); if (dev->descriptor.iSerialNumber) usb_show_string(dev, "SerialNumber", dev->descriptor.iSerialNumber); +#endif /* now that the basic setup is over, add a /proc/bus/usb entry */ usbdevfs_add_device(dev); @@ -1874,6 +1878,7 @@ EXPORT_SYMBOL(usb_init_root_hub); EXPORT_SYMBOL(usb_root_hub_string); EXPORT_SYMBOL(usb_new_device); +EXPORT_SYMBOL(usb_reset_device); EXPORT_SYMBOL(usb_connect); EXPORT_SYMBOL(usb_disconnect); EXPORT_SYMBOL(usb_release_bandwidth); diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/usbdevice_fs.h linux/drivers/usb/usbdevice_fs.h --- v2.3.99-pre3/linux/drivers/usb/usbdevice_fs.h Thu Mar 2 14:36:23 2000 +++ linux/drivers/usb/usbdevice_fs.h Wed Dec 31 16:00:00 1969 @@ -1,170 +0,0 @@ -/*****************************************************************************/ - -/* - * usbdevice_fs.h -- USB device file system. - * - * Copyright (C) 2000 - * Thomas Sailer (sailer@ife.ee.ethz.ch) - * - * 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. - * - * History: - * 0.1 04.01.2000 Created - * - * $Id: usbdevice_fs.h,v 1.1 2000/01/06 18:40:41 tom Exp $ - */ - -/*****************************************************************************/ - -#ifndef _LINUX_USBDEVICE_FS_H -#define _LINUX_USBDEVICE_FS_H - -/* --------------------------------------------------------------------- */ - -#define USBDEVICE_SUPER_MAGIC 0x9fa2 - -/* usbdevfs ioctl codes */ - -struct usbdevfs_ctrltransfer { - __u8 requesttype; - __u8 request; - __u16 value; - __u16 index; - __u16 length; - __u32 timeout; /* in milliseconds */ - void *data; -}; - -struct usbdevfs_bulktransfer { - unsigned int ep; - unsigned int len; - unsigned int timeout; /* in milliseconds */ - void *data; -}; - -struct usbdevfs_setinterface { - unsigned int interface; - unsigned int altsetting; -}; - -struct usbdevfs_disconnectsignal { - unsigned int signr; - void *context; -}; - -#define USBDEVFS_URB_DISABLE_SPD 1 -#define USBDEVFS_URB_ISO_ASAP 2 - -#define USBDEVFS_URB_TYPE_ISO 0 -#define USBDEVFS_URB_TYPE_INTERRUPT 1 -#define USBDEVFS_URB_TYPE_CONTROL 2 -#define USBDEVFS_URB_TYPE_BULK 3 - -struct usbdevfs_iso_packet_desc { - unsigned int length; - unsigned int actual_length; - unsigned int status; -}; - -struct usbdevfs_urb { - unsigned char type; - unsigned char endpoint; - int status; - unsigned int flags; - void *buffer; - int buffer_length; - int actual_length; - int start_frame; - int number_of_packets; - int error_count; - unsigned int signr; /* signal to be sent on error, -1 if none should be sent */ - void *usercontext; - struct usbdevfs_iso_packet_desc iso_frame_desc[0]; -}; - -#define USBDEVFS_CONTROL _IOWR('U', 0, struct usbdevfs_ctrltransfer) -#define USBDEVFS_BULK _IOWR('U', 2, struct usbdevfs_bulktransfer) -#define USBDEVFS_RESETEP _IOR('U', 3, unsigned int) -#define USBDEVFS_SETINTERFACE _IOR('U', 4, struct usbdevfs_setinterface) -#define USBDEVFS_SETCONFIGURATION _IOR('U', 5, unsigned int) -#define USBDEVFS_SUBMITURB _IOR('U', 10, struct usbdevfs_urb) -#define USBDEVFS_DISCARDURB _IO('U', 11) -#define USBDEVFS_REAPURB _IOW('U', 12, void *) -#define USBDEVFS_REAPURBNDELAY _IOW('U', 13, void *) -#define USBDEVFS_DISCSIGNAL _IOR('U', 14, struct usbdevfs_disconnectsignal) -#define USBDEVFS_CLAIMINTERFACE _IOR('U', 15, unsigned int) -#define USBDEVFS_RELEASEINTERFACE _IOR('U', 16, unsigned int) - -/* --------------------------------------------------------------------- */ - -#ifdef __KERNEL__ - -#include -#include - -/* - * inode number macros - */ -#define ITYPE(x) ((x)&(0xf<<28)) -#define ISPECIAL (0<<28) -#define IBUS (1<<28) -#define IDEVICE (2<<28) -#define IBUSNR(x) (((x)>>8)&0xff) -#define IDEVNR(x) ((x)&0xff) - -#define IROOT 1 - -/* - * sigh. rwsemaphores do not (yet) work from modules - */ - -#define rw_semaphore semaphore -#define init_rwsem init_MUTEX -#define down_read down -#define down_write down -#define up_read up -#define up_write up - - -struct dev_state { - struct list_head list; /* state list */ - struct rw_semaphore devsem; /* protects modifications to dev (dev == NULL indicating disconnect) */ - struct usb_device *dev; - struct file *file; - spinlock_t lock; /* protects the async urb lists */ - struct list_head async_pending; - struct list_head async_completed; - wait_queue_head_t wait; /* wake up if a request completed */ - unsigned int discsignr; - struct task_struct *disctask; - void *disccontext; - unsigned long ifclaimed; -}; - -/* internal methods & data */ -extern struct usb_driver usbdevfs_driver; -extern struct file_operations usbdevfs_drivers_fops; -extern struct file_operations usbdevfs_devices_fops; -extern struct file_operations usbdevfs_device_file_operations; -extern struct inode_operations usbdevfs_device_inode_operations; -extern struct inode_operations usbdevfs_bus_inode_operations; -extern struct file_operations usbdevfs_bus_file_operations; -extern void usbdevfs_conn_disc_event(void); - - -#endif /* __KERNEL__ */ - -/* --------------------------------------------------------------------- */ -#endif /* _LINUX_USBDEVICE_FS_H */ diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/video/Config.in linux/drivers/video/Config.in --- v2.3.99-pre3/linux/drivers/video/Config.in Fri Mar 10 16:40:45 2000 +++ linux/drivers/video/Config.in Mon Mar 27 10:48:23 2000 @@ -33,6 +33,9 @@ if [ "$CONFIG_ARCH_NETWINDER" = "y" ]; then tristate ' Cyber2000 support' CONFIG_FB_CYBER2000 fi + if [ "$CONFIG_ARCH_SA1100" = "y" ]; then + bool ' SA-1100 LCD support' CONFIG_FB_SA1100 + fi if [ "$CONFIG_APOLLO" = "y" ]; then define_bool CONFIG_FB_APOLLO y fi @@ -193,12 +196,12 @@ fi fi if [ "$CONFIG_FB_ACORN" = "y" -o "$CONFIG_FB_MAC" = "y" -o \ - "$CONFIG_FB_VIRTUAL" = "y" ]; then + "$CONFIG_FB_SA1100" = "y" -o "$CONFIG_FB_VIRTUAL" = "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_VIRTUAL" = "m" ]; then + "$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" ]; then define_tristate CONFIG_FBCON_CFB2 m define_tristate CONFIG_FBCON_CFB4 m fi @@ -217,7 +220,7 @@ "$CONFIG_FB_P9100" = "y" -o "$CONFIG_FB_ATY128" = "y" -o \ "$CONFIG_FB_RIVA" = "y" -o \ "$CONFIG_FB_SGIVW" = "y" -o "$CONFIG_FB_CYBER2000" = "y" -o \ - "$CONFIG_FB_3DFX" = "y" ]; then + "$CONFIG_FB_SA1100" = "y" -o "$CONFIG_FB_3DFX" = "y" ]; then define_tristate CONFIG_FBCON_CFB8 y else if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \ @@ -232,7 +235,8 @@ "$CONFIG_FB_IGA" = "m" -o "$CONFIG_FB_MATROX" = "m" -o \ "$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_PM2" = "m" -o \ "$CONFIG_FB_P9100" = "m" -o "$CONFIG_FB_ATY128" = "m" -o \ - "$CONFIG_FB_SGIVW" = "m" -o "$CONFIG_FB_CYBER2000" = "m" ]; then + "$CONFIG_FB_SGIVW" = "m" -o "$CONFIG_FB_CYBER2000" = "m" -o \ + "$CONFIG_FB_SA1100" = "m" ]; then define_tristate CONFIG_FBCON_CFB8 m fi fi diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/video/Makefile linux/drivers/video/Makefile --- v2.3.99-pre3/linux/drivers/video/Makefile Mon Mar 27 08:08:28 2000 +++ linux/drivers/video/Makefile Mon Apr 10 23:00:08 2000 @@ -46,7 +46,8 @@ obj-$(CONFIG_FONT_PEARL_8x8) += font_pearl_8x8.o obj-$(CONFIG_FONT_ACORN_8x8) += font_acorn_8x8.o -obj-$(CONFIG_FB) += fbmem.o fbcmap.o modedb.o fbcon.o fonts.o fbmon.o +# Add fbmon.o back into obj-$(CONFIG_FB) in 2.5.x +obj-$(CONFIG_FB) += fbmem.o fbcmap.o modedb.o fbcon.o fonts.o obj-$(CONFIG_FB_COMPAT_XPMAC) += macmodes.o obj-$(CONFIG_FB_ACORN) += acornfb.o @@ -111,6 +112,7 @@ obj-$(CONFIG_FB_SUN3) += sun3fb.o obj-$(CONFIG_FB_BWTWO) += bwtwofb.o obj-$(CONFIG_FB_HGA) += hgafb.o +obj-$(CONFIG_FB_SA1100) += sa1100fb.o obj-$(CONFIG_FB_VIRTUAL) += vfb.o # Generic Low Level Drivers diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/video/amifb.c linux/drivers/video/amifb.c --- v2.3.99-pre3/linux/drivers/video/amifb.c Mon Mar 27 08:08:28 2000 +++ linux/drivers/video/amifb.c Mon Apr 10 23:00:08 2000 @@ -2415,11 +2415,13 @@ par->crsr.spot_x = par->crsr.spot_y = 0; par->crsr.height = par->crsr.width = 0; +#if 0 /* fbmon not done. uncomment for 2.5.x -brad */ if (!fbmon_valid_timings(pixclock[clk_shift], htotal, vtotal, &fb_info)) { DPRINTK("mode doesn't fit for monitor\n"); return -EINVAL; } +#endif return 0; } diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/video/aty128fb.c linux/drivers/video/aty128fb.c --- v2.3.99-pre3/linux/drivers/video/aty128fb.c Sun Mar 19 18:35:31 2000 +++ linux/drivers/video/aty128fb.c Mon Mar 27 22:30:29 2000 @@ -1210,7 +1210,7 @@ if (par->accel_flags & FB_ACCELF_TEXT) aty128_init_engine(par, info); -#ifdef CONFIG_FB_COMPAT_XPMAC +#if 0/*def CONFIG_FB_COMPAT_XPMAC*/ #if 0 /* use this when macmodes gets updated */ if (!console_fb_info || console_fb_info == &info->fb_info) { disp_info.width = ((par->crtc.v_total >> 16) & 0x7ff)+1; diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/video/atyfb.c linux/drivers/video/atyfb.c --- v2.3.99-pre3/linux/drivers/video/atyfb.c Tue Mar 14 19:10:40 2000 +++ linux/drivers/video/atyfb.c Mon Apr 10 23:00:08 2000 @@ -2539,7 +2539,7 @@ else par->accel_flags = 0; -#if 0 +#if 0 /* fbmon is not done. uncomment for 2.5.x -brad */ if (!fbmon_valid_timings(var->pixclock, htotal, vtotal, info)) return -EINVAL; #endif diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/video/fbmem.c linux/drivers/video/fbmem.c --- v2.3.99-pre3/linux/drivers/video/fbmem.c Tue Mar 14 19:10:40 2000 +++ linux/drivers/video/fbmem.c Mon Mar 27 10:48:23 2000 @@ -98,6 +98,8 @@ extern int control_init(void); extern int control_setup(char*); extern int g364fb_init(void); +extern void sa1100fb_init(void); +extern void sa1100fb_setup(char*); extern int fm2fb_init(void); extern int fm2fb_setup(char*); extern int q40fb_init(void); @@ -215,6 +217,9 @@ #endif #ifdef CONFIG_FB_G364 { "g364", g364fb_init, NULL }, +#endif +#ifdef CONFIG_FB_SA1100 + { "sa1100", sa1100fb_init, sa1100fb_setup }, #endif #ifdef CONFIG_FB_FM2 { "fm2fb", fm2fb_init, fm2fb_setup }, diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/video/sa1100fb.c linux/drivers/video/sa1100fb.c --- v2.3.99-pre3/linux/drivers/video/sa1100fb.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/video/sa1100fb.c Mon Mar 27 10:48:23 2000 @@ -0,0 +1,1147 @@ +/* + * linux/drivers/video/sa1100fb.c -- StrongARM 1100 LCD Controller Frame Buffer Device + * + * Copyright (C) 1999 Eric A. Thomas + * + * 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. + * + */ + + +/* + * Code Status: + * 4/1/99 - Driver appears to be working for Brutus 320x200x8bpp mode. Other + * resolutions are working, but only the 8bpp mode is supported. + * Changes need to be made to the palette encode and decode routines + * to support 4 and 16 bpp modes. + * Driver is not designed to be a module. The FrameBuffer is statically + * allocated since dynamic allocation of a 300k buffer cannot be guaranteed. + * + * 6/17/99 - FrameBuffer memory is now allocated at run-time when the + * driver is initialized. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include