diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/alpha/config.in linux.19rc3-ac4/arch/alpha/config.in --- linux.19rc3/arch/alpha/config.in 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/arch/alpha/config.in 2002-07-29 13:58:35.000000000 +0100 @@ -385,6 +385,7 @@ # fi # fi source drivers/video/Config.in + source drivers/char/speakup/Config.in if [ "$CONFIG_FB" = "y" ]; then define_bool CONFIG_PCI_CONSOLE y fi @@ -423,3 +424,5 @@ fi endmenu + +source lib/Config.in diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/alpha/kernel/process.c linux.19rc3-ac4/arch/alpha/kernel/process.c --- linux.19rc3/arch/alpha/kernel/process.c 2002-07-29 12:50:05.000000000 +0100 +++ linux.19rc3-ac4/arch/alpha/kernel/process.c 2002-07-29 13:58:35.000000000 +0100 @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -74,9 +75,6 @@ cpu_idle(void) { /* An endless idle loop with no priority at all. */ - current->nice = 20; - current->counter = -100; - while (1) { /* FIXME -- EV6 and LCA45 know how to power down the CPU. */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/alpha/kernel/smp.c linux.19rc3-ac4/arch/alpha/kernel/smp.c --- linux.19rc3/arch/alpha/kernel/smp.c 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/arch/alpha/kernel/smp.c 2002-07-29 13:58:35.000000000 +0100 @@ -82,6 +82,7 @@ int smp_num_cpus = 1; /* Number that came online. */ int smp_threads_ready; /* True once the per process idle is forked. */ cycles_t cacheflush_time; +unsigned long cache_decay_ticks; int __cpu_number_map[NR_CPUS]; int __cpu_logical_map[NR_CPUS]; @@ -156,11 +157,6 @@ { int cpuid = hard_smp_processor_id(); - if (current != init_tasks[cpu_number_map(cpuid)]) { - printk("BUG: smp_calling: cpu %d current %p init_tasks[cpu_number_map(cpuid)] %p\n", - cpuid, current, init_tasks[cpu_number_map(cpuid)]); - } - DBGS(("CALLIN %d state 0x%lx\n", cpuid, current->state)); /* Turn on machine checks. */ @@ -215,9 +211,6 @@ DBGS(("smp_callin: commencing CPU %d current %p\n", cpuid, current)); - /* Setup the scheduler for this processor. */ - init_idle(); - /* ??? This should be in init_idle. */ atomic_inc(&init_mm.mm_count); current->active_mm = &init_mm; @@ -236,8 +229,9 @@ smp_tune_scheduling (int cpuid) { struct percpu_struct *cpu; - unsigned long on_chip_cache; - unsigned long freq; + unsigned long on_chip_cache; /* kB */ + unsigned long freq; /* Hz */ + unsigned long bandwidth = 350; /* MB/s */ cpu = (struct percpu_struct*)((char*)hwrpb + hwrpb->processor_offset + cpuid * hwrpb->processor_size); @@ -258,29 +252,21 @@ case EV6_CPU: case EV67_CPU: - on_chip_cache = 64 + 64; - break; - default: - on_chip_cache = 8 + 8; + on_chip_cache = 64 + 64; break; } freq = hwrpb->cycle_freq ? : est_cycle_freq; -#if 0 - /* Magic estimation stolen from x86 port. */ - cacheflush_time = freq / 1024L * on_chip_cache / 5000L; - - printk("Using heuristic of %d cycles.\n", - cacheflush_time); -#else - /* Magic value to force potential preemption of other CPUs. */ - cacheflush_time = INT_MAX; + cacheflush_time = (freq / 1000000) * (on_chip_cache << 10) / bandwidth; + cache_decay_ticks = cacheflush_time / (freq / 1000) * HZ / 1000; - printk("Using heuristic of %d cycles.\n", - cacheflush_time); -#endif + printk("per-CPU timeslice cutoff: %ld.%02ld usecs.\n", + cacheflush_time/(freq/1000000), + (cacheflush_time*100/(freq/1000000)) % 100); + printk("task migration cache decay timeout: %ld msecs.\n", + (cache_decay_ticks + 1) * 1000 / HZ); } /* @@ -505,14 +491,11 @@ if (idle == &init_task) panic("idle process is init_task for CPU %d", cpuid); - idle->processor = cpuid; - idle->cpus_runnable = 1 << cpuid; /* we schedule the first task manually */ + init_idle(idle, cpuid); + unhash_process(idle); + __cpu_logical_map[cpunum] = cpuid; __cpu_number_map[cpuid] = cpunum; - - del_from_runqueue(idle); - unhash_process(idle); - init_tasks[cpunum] = idle; DBGS(("smp_boot_one_cpu: CPU %d state 0x%lx flags 0x%lx\n", cpuid, idle->state, idle->flags)); @@ -619,14 +602,11 @@ __cpu_number_map[boot_cpuid] = 0; __cpu_logical_map[0] = boot_cpuid; - current->processor = boot_cpuid; smp_store_cpu_info(boot_cpuid); smp_tune_scheduling(boot_cpuid); smp_setup_percpu_timer(boot_cpuid); - init_idle(); - /* ??? This should be in init_idle. */ atomic_inc(&init_mm.mm_count); current->active_mm = &init_mm; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/alpha/mm/fault.c linux.19rc3-ac4/arch/alpha/mm/fault.c --- linux.19rc3/arch/alpha/mm/fault.c 2002-07-29 12:50:04.000000000 +0100 +++ linux.19rc3-ac4/arch/alpha/mm/fault.c 2002-07-29 17:22:23.000000000 +0100 @@ -119,8 +119,6 @@ goto bad_area; if (vma->vm_start <= address) goto good_area; - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; if (expand_stack(vma, address)) goto bad_area; /* @@ -196,8 +194,7 @@ */ out_of_memory: if (current->pid == 1) { - current->policy |= SCHED_YIELD; - schedule(); + yield(); down_read(&mm->mmap_sem); goto survive; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/arm/config.in linux.19rc3-ac4/arch/arm/config.in --- linux.19rc3/arch/arm/config.in 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/arch/arm/config.in 2002-07-29 15:21:52.000000000 +0100 @@ -606,6 +606,7 @@ bool 'VGA text console' CONFIG_VGA_CONSOLE fi source drivers/video/Config.in + source drivers/char/speakup/Config.in endmenu fi @@ -646,6 +647,7 @@ bool 'Kernel debugging' CONFIG_DEBUG_KERNEL dep_bool ' Debug memory allocations' CONFIG_DEBUG_SLAB $CONFIG_DEBUG_KERNEL dep_bool ' Magic SysRq key' CONFIG_MAGIC_SYSRQ $CONFIG_DEBUG_KERNEL +dep_bool ' Morse code panics' CONFIG_PANIC_MORSE $CONFIG_DEBUG_KERNEL $CONFIG_PC_KEYB dep_bool ' Spinlock debugging' CONFIG_DEBUG_SPINLOCK $CONFIG_DEBUG_KERNEL dep_bool ' Wait queue debugging' CONFIG_DEBUG_WAITQ $CONFIG_DEBUG_KERNEL dep_bool ' Verbose BUG() reporting (adds 70K)' CONFIG_DEBUG_BUGVERBOSE $CONFIG_DEBUG_KERNEL @@ -655,3 +657,5 @@ dep_bool ' Kernel low-level debugging messages via footbridge serial port' CONFIG_DEBUG_DC21285_PORT $CONFIG_DEBUG_LL $CONFIG_FOOTBRIDGE dep_bool ' Kernel low-level debugging messages via UART2' CONFIG_DEBUG_CLPS711X_UART2 $CONFIG_DEBUG_LL $CONFIG_ARCH_CLPS711X endmenu + +source lib/Config.in diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/arm/mach-integrator/cpu.c linux.19rc3-ac4/arch/arm/mach-integrator/cpu.c --- linux.19rc3/arch/arm/mach-integrator/cpu.c 2002-07-29 12:50:05.000000000 +0100 +++ linux.19rc3-ac4/arch/arm/mach-integrator/cpu.c 2002-07-29 13:58:35.000000000 +0100 @@ -121,7 +121,7 @@ cpu_freq_khz = vco_to_freq(vco, 1); #ifdef CONFIG_CPU_FREQ - cpufreq_init(cpu_freq_khz); + cpufreq_init(cpu_freq_khz, 1000, 0); cpufreq_setfunctions(integrator_validatespeed, integrator_setspeed); #endif diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/arm/mach-sa1100/generic.c linux.19rc3-ac4/arch/arm/mach-sa1100/generic.c --- linux.19rc3/arch/arm/mach-sa1100/generic.c 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/arch/arm/mach-sa1100/generic.c 2002-07-29 13:58:35.000000000 +0100 @@ -86,7 +86,7 @@ static int __init sa11x0_init_clock(void) { - cpufreq_init(cclk_frequency_100khz[PPCR & 0xf] * 100); + cpufreq_init(cclk_frequency_100khz[PPCR & 0xf] * 100, 0, 0); return 0; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/arm/mm/fault-common.c linux.19rc3-ac4/arch/arm/mm/fault-common.c --- linux.19rc3/arch/arm/mm/fault-common.c 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/arch/arm/mm/fault-common.c 2002-07-29 17:22:23.000000000 +0100 @@ -225,12 +225,11 @@ * If we are out of memory for pid1, * sleep for a while and retry */ - tsk->policy |= SCHED_YIELD; - schedule(); + yield(); goto survive; check_stack: - if (vma->vm_flags & VM_GROWSDOWN && !expand_stack(vma, addr)) + if (!expand_stack(vma, addr)) goto good_area; out: return fault; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/cris/config.in linux.19rc3-ac4/arch/cris/config.in --- linux.19rc3/arch/cris/config.in 2002-07-29 12:50:07.000000000 +0100 +++ linux.19rc3-ac4/arch/cris/config.in 2002-07-29 13:58:35.000000000 +0100 @@ -253,4 +253,6 @@ if [ "$CONFIG_PROFILE" = "y" ]; then int ' Profile shift count' CONFIG_PROFILE_SHIFT 2 fi + +source lib/Config.in endmenu diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/cris/drivers/ide.c linux.19rc3-ac4/arch/cris/drivers/ide.c --- linux.19rc3/arch/cris/drivers/ide.c 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/arch/cris/drivers/ide.c 2002-07-29 13:58:35.000000000 +0100 @@ -816,13 +816,13 @@ rq = HWGROUP(drive)->rq; for (i = rq->nr_sectors; i > 0;) { i -= rq->current_nr_sectors; - ide_end_request(1, HWGROUP(drive)); + DRIVER(drive)->end_request(drive, 1); } return ide_stopped; } printk("%s: bad DMA status\n", drive->name); } - return ide_error(drive, "dma_intr", stat); + return DRIVER(drive)->error(drive, "dma_intr", stat); } /* diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/i386/config.in linux.19rc3-ac4/arch/i386/config.in --- linux.19rc3/arch/i386/config.in 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/arch/i386/config.in 2002-07-29 15:21:52.000000000 +0100 @@ -54,6 +54,7 @@ define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n define_bool CONFIG_X86_PPRO_FENCE y + define_bool CONFIG_X86_F00F_WORKS_OK n else define_bool CONFIG_X86_WP_WORKS_OK y define_bool CONFIG_X86_INVLPG y @@ -69,12 +70,14 @@ define_bool CONFIG_X86_USE_STRING_486 y define_bool CONFIG_X86_ALIGNMENT_16 y define_bool CONFIG_X86_PPRO_FENCE y + define_bool CONFIG_X86_F00F_WORKS_OK n fi if [ "$CONFIG_M586" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 5 define_bool CONFIG_X86_USE_STRING_486 y define_bool CONFIG_X86_ALIGNMENT_16 y define_bool CONFIG_X86_PPRO_FENCE y + define_bool CONFIG_X86_F00F_WORKS_OK n fi if [ "$CONFIG_M586TSC" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 5 @@ -82,6 +85,7 @@ define_bool CONFIG_X86_ALIGNMENT_16 y define_bool CONFIG_X86_TSC y define_bool CONFIG_X86_PPRO_FENCE y + define_bool CONFIG_X86_F00F_WORKS_OK n fi if [ "$CONFIG_M586MMX" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 5 @@ -90,21 +94,24 @@ define_bool CONFIG_X86_TSC y define_bool CONFIG_X86_GOOD_APIC y define_bool CONFIG_X86_PPRO_FENCE y + define_bool CONFIG_X86_F00F_WORKS_OK n fi if [ "$CONFIG_M686" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 5 define_bool CONFIG_X86_TSC y define_bool CONFIG_X86_GOOD_APIC y - define_bool CONFIG_X86_PGE y + bool 'PGE extensions (not for Cyrix/Transmeta)' CONFIG_X86_PGE define_bool CONFIG_X86_USE_PPRO_CHECKSUM y define_bool CONFIG_X86_PPRO_FENCE y + define_bool CONFIG_X86_F00F_WORKS_OK y fi if [ "$CONFIG_MPENTIUMIII" = "y" ]; then - define_int CONFIG_X86_L1_CACHE_SHIFT 5 + define_int CONFIG_X86_L1_CACHE_SHIFT 7 define_bool CONFIG_X86_TSC y define_bool CONFIG_X86_GOOD_APIC y define_bool CONFIG_X86_PGE y define_bool CONFIG_X86_USE_PPRO_CHECKSUM y + define_bool CONFIG_X86_F00F_WORKS_OK y fi if [ "$CONFIG_MPENTIUM4" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 7 @@ -112,6 +119,7 @@ define_bool CONFIG_X86_GOOD_APIC y define_bool CONFIG_X86_PGE y define_bool CONFIG_X86_USE_PPRO_CHECKSUM y + define_bool CONFIG_X86_F00F_WORKS_OK y fi if [ "$CONFIG_MK6" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 5 @@ -126,11 +134,13 @@ define_bool CONFIG_X86_USE_3DNOW y define_bool CONFIG_X86_PGE y define_bool CONFIG_X86_USE_PPRO_CHECKSUM y + define_bool CONFIG_X86_F00F_WORKS_OK y fi if [ "$CONFIG_MELAN" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 4 define_bool CONFIG_X86_USE_STRING_486 y define_bool CONFIG_X86_ALIGNMENT_16 y + define_bool CONFIG_X86_F00F_WORKS_OK y fi if [ "$CONFIG_MCYRIXIII" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 5 @@ -142,12 +152,14 @@ if [ "$CONFIG_MCRUSOE" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 5 define_bool CONFIG_X86_TSC y + define_bool CONFIG_X86_F00F_WORKS_OK y fi if [ "$CONFIG_MWINCHIPC6" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 5 define_bool CONFIG_X86_ALIGNMENT_16 y define_bool CONFIG_X86_USE_PPRO_CHECKSUM y define_bool CONFIG_X86_OOSTORE y + define_bool CONFIG_X86_F00F_WORKS_OK y fi if [ "$CONFIG_MWINCHIP2" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 5 @@ -155,6 +167,7 @@ define_bool CONFIG_X86_TSC y define_bool CONFIG_X86_USE_PPRO_CHECKSUM y define_bool CONFIG_X86_OOSTORE y + define_bool CONFIG_X86_F00F_WORKS_OK y fi if [ "$CONFIG_MWINCHIP3D" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 5 @@ -162,10 +175,22 @@ define_bool CONFIG_X86_TSC y define_bool CONFIG_X86_USE_PPRO_CHECKSUM y define_bool CONFIG_X86_OOSTORE y + define_bool CONFIG_X86_F00F_WORKS_OK y fi bool 'Machine Check Exception' CONFIG_X86_MCE +dep_bool 'CPU Frequency scaling' CONFIG_CPU_FREQ $CONFIG_EXPERIMENTAL +if [ "$CONFIG_CPU_FREQ" != "n" ]; then + tristate ' AMD K6-2/K6-3 PowerNow!' CONFIG_X86_POWERNOW_K6 + tristate ' VIA C3/C5/Cyrix III Longhaul' CONFIG_X86_LONGHAUL + if [ "$CONFIG_X86_LONGHAUL" != "n" ]; then + bool ' Scale voltage according to speed' CONFIG_X86_LONGHAUL_SCALE_VOLTAGE + fi + tristate ' Intel Speedstep' CONFIG_X86_SPEEDSTEP + tristate ' Intel Pentium 4 throttling' CONFIG_X86_P4_CLOCKMOD +fi + tristate 'Toshiba Laptop support' CONFIG_TOSHIBA tristate 'Dell laptop support' CONFIG_I8K @@ -199,6 +224,7 @@ fi else bool 'Multiquad NUMA system' CONFIG_MULTIQUAD + dep_bool 'Summit Architecture support' CONFIG_SUMMIT $CONFIG_MULTIQUAD fi if [ "$CONFIG_SMP" = "y" -a "$CONFIG_X86_CMPXCHG" = "y" ]; then @@ -270,6 +296,8 @@ tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC +bool 'Kernel .config support' CONFIG_IKCONFIG + bool 'Power Management support' CONFIG_PM if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then @@ -396,6 +424,7 @@ tristate 'MDA text console (dual-headed) (EXPERIMENTAL)' CONFIG_MDA_CONSOLE source drivers/video/Config.in fi + source drivers/char/speakup/Config.in endmenu fi @@ -417,12 +446,15 @@ bool 'Kernel debugging' CONFIG_DEBUG_KERNEL if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then + bool ' Compile the kernel with frame pointers' CONFIG_FRAME_POINTER bool ' Debug high memory support' CONFIG_DEBUG_HIGHMEM bool ' Debug memory allocations' CONFIG_DEBUG_SLAB bool ' Memory mapped I/O debugging' CONFIG_DEBUG_IOVIRT bool ' Magic SysRq key' CONFIG_MAGIC_SYSRQ + bool ' Morse code panics' CONFIG_PANIC_MORSE bool ' Spinlock debugging' CONFIG_DEBUG_SPINLOCK - bool ' Compile the kernel with frame pointers' CONFIG_FRAME_POINTER fi endmenu + +source lib/Config.in diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/i386/defconfig linux.19rc3-ac4/arch/i386/defconfig --- linux.19rc3/arch/i386/defconfig 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/arch/i386/defconfig 2002-07-29 13:58:35.000000000 +0100 @@ -107,6 +107,7 @@ CONFIG_BINFMT_AOUT=y CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=y +# CONFIG_IKCONFIG is not set CONFIG_PM=y # CONFIG_APM is not set @@ -136,7 +137,6 @@ # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_CISS_SCSI_TAPE is not set # CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_RAM is not set @@ -283,6 +283,7 @@ # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_VIA82CXXX is not set # CONFIG_IDE_CHIPSETS is not set +# CONFIG_BLK_DEV_ELEVATOR_NOOP is not set CONFIG_IDEDMA_AUTO=y # CONFIG_IDEDMA_IVB is not set # CONFIG_DMA_NONPCI is not set @@ -589,6 +590,7 @@ # CONFIG_WATCHDOG is not set # CONFIG_AMD_RNG is not set # CONFIG_INTEL_RNG is not set +# CONFIG_AMD_PM768 is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set # CONFIG_DTLK is not set @@ -618,6 +620,7 @@ # CONFIG_DRM_R128 is not set CONFIG_DRM_RADEON=y # CONFIG_DRM_I810 is not set +# CONFIG_DRM_I830 is not set # CONFIG_DRM_MGA is not set # CONFIG_DRM_SIS is not set @@ -625,7 +628,6 @@ # PCMCIA character devices # # CONFIG_PCMCIA_SERIAL_CS is not set -# CONFIG_MWAVE is not set # # Multimedia devices @@ -662,6 +664,9 @@ CONFIG_ISO9660_FS=y # CONFIG_JOLIET is not set # CONFIG_ZISOFS is not set +# CONFIG_JFS_FS is not set +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set # CONFIG_MINIX_FS is not set # CONFIG_VXFS_FS is not set # CONFIG_NTFS_FS is not set @@ -705,7 +710,6 @@ # CONFIG_NCPFS_NLS is not set # CONFIG_NCPFS_EXTRAS is not set # CONFIG_ZISOFS_FS is not set -# CONFIG_ZLIB_FS_INFLATE is not set # # Partition Types @@ -867,14 +871,14 @@ # # CONFIG_USB_RIO500 is not set # CONFIG_USB_AUERSWALD is not set -# CONFIG_USB_BRLVGER is not set # -# Bluetooth support +# Kernel hacking # -# CONFIG_BLUEZ is not set +# CONFIG_DEBUG_KERNEL is not set # -# Kernel hacking +# Library routines # -# CONFIG_DEBUG_KERNEL is not set +# CONFIG_ZLIB_INFLATE is not set +# CONFIG_ZLIB_DEFLATE is not set diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/i386/kernel/apic.c linux.19rc3-ac4/arch/i386/kernel/apic.c --- linux.19rc3/arch/i386/kernel/apic.c 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/arch/i386/kernel/apic.c 2002-07-29 13:58:35.000000000 +0100 @@ -29,6 +29,7 @@ #include #include #include +#include /* Using APIC to generate smp_local_timer_interrupt? */ int using_apic_timer = 0; @@ -260,6 +261,16 @@ apic_write_around(APIC_LVT1, value); } +static unsigned long apic_ldr_value(unsigned long value) +{ + if (clustered_apic_logical) + return (value); + if (clustered_apic_physical) + return (((value) & ~APIC_LDR_MASK) | + SET_APIC_LOGICAL_ID(physical_to_logical_apicid(hard_smp_processor_id()))); + return (((value) & ~APIC_LDR_MASK) | SET_APIC_LOGICAL_ID(1UL << smp_processor_id())); +} + void __init setup_local_APIC (void) { unsigned long value, ver, maxlvt; @@ -292,21 +303,23 @@ * document number 292116). So here it goes... */ - if (!clustered_apic_mode) { + if (!clustered_apic_logical) { /* - * In clustered apic mode, the firmware does this for us - * Put the APIC into flat delivery mode. - * Must be "all ones" explicitly for 82489DX. + * For NUMA-Q (clustered apic logical), the firmware does this + * for us. Otherwise put the APIC into clustered or flat + * delivery mode. Must be "all ones" explicitly for 82489DX. */ - apic_write_around(APIC_DFR, 0xffffffff); + + if(clustered_apic_mode) + apic_write_around(APIC_DFR, APIC_DFR_CLUSTER); + else + apic_write_around(APIC_DFR, APIC_DFR_FLAT); /* * Set up the logical destination ID. */ value = apic_read(APIC_LDR); - value &= ~APIC_LDR_MASK; - value |= (1<<(smp_processor_id()+24)); - apic_write_around(APIC_LDR, value); + apic_write_around(APIC_LDR, apic_ldr_value(value)); } /* @@ -1055,7 +1068,6 @@ * [ if a single-CPU system runs an SMP kernel then we call the local * interrupt as well. Thus we cannot inline the local irq ... ] */ -unsigned int apic_timer_irqs [NR_CPUS]; void smp_apic_timer_interrupt(struct pt_regs * regs) { @@ -1064,7 +1076,7 @@ /* * the NMI deadlock-detector uses this. */ - apic_timer_irqs[cpu]++; + irq_stat[cpu].apic_timer_irqs++; /* * NOTE! We'd better ACK the irq immediately, diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/i386/kernel/apm.c linux.19rc3-ac4/arch/i386/kernel/apm.c --- linux.19rc3/arch/i386/kernel/apm.c 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/arch/i386/kernel/apm.c 2002-07-29 16:56:33.000000000 +0100 @@ -247,6 +247,7 @@ * powering off * [no-]debug log some debugging messages * [no-]power[-_]off power off on shutdown + * [no-]smp Use apm even on an SMP box * bounce[-_]interval= number of ticks to ignore suspend * bounces * idle[-_]threshold= System idle percentage above which to @@ -393,6 +394,7 @@ static int got_clock_diff; #endif static int debug; +static int smp = 0; static int apm_disabled = -1; #ifdef CONFIG_SMP static int power_off; @@ -847,6 +849,7 @@ case 1: apm_idle_done = 1; break; default: /* BIOS refused */ + break; } } if (original_pm_idle) @@ -1403,7 +1406,7 @@ as = fp->private_data; if (check_apm_user(as, "read")) return -EIO; - if (count < sizeof(apm_event_t)) + if ((int)count < sizeof(apm_event_t)) return -EINVAL; if ((queue_empty(as)) && (fp->f_flags & O_NONBLOCK)) return -EAGAIN; @@ -1577,7 +1580,7 @@ p = buf; - if ((smp_num_cpus == 1) && + if ((smp_num_cpus == 1 || smp) && !(error = apm_get_power_status(&bx, &cx, &dx))) { ac_line_status = (bx >> 8) & 0xff; battery_status = bx & 0xff; @@ -1707,7 +1710,7 @@ } } - if (debug && (smp_num_cpus == 1)) { + if (debug && (smp_num_cpus == 1 || smp )) { error = apm_get_power_status(&bx, &cx, &dx); if (error) printk(KERN_INFO "apm: power status not available\n"); @@ -1751,7 +1754,7 @@ pm_power_off = apm_power_off; register_sysrq_key('o', &sysrq_poweroff_op); - if (smp_num_cpus == 1) { + if (smp_num_cpus == 1 || smp) { #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT) console_blank_hook = apm_console_blank; #endif @@ -1790,6 +1793,8 @@ str += 3; if (strncmp(str, "debug", 5) == 0) debug = !invert; + if (strncmp(str, "smp", 3) == 0) + smp = !invert; if ((strncmp(str, "power-off", 9) == 0) || (strncmp(str, "power_off", 9) == 0)) power_off = !invert; @@ -1894,7 +1899,7 @@ printk(KERN_NOTICE "apm: disabled on user request.\n"); return -ENODEV; } - if ((smp_num_cpus > 1) && !power_off) { + if ((smp_num_cpus > 1) && !power_off && !smp) { printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n"); return -ENODEV; } @@ -1948,7 +1953,7 @@ kernel_thread(apm, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD); - if (smp_num_cpus > 1) { + if (smp_num_cpus > 1 && !smp) { printk(KERN_NOTICE "apm: disabled - APM is not SMP safe (power off active).\n"); return 0; @@ -2016,5 +2021,8 @@ MODULE_PARM(idle_period, "i"); MODULE_PARM_DESC(idle_period, "Period (in sec/100) over which to caculate the idle percentage"); +MODULE_PARM(smp, "i"); +MODULE_PARM_DESC(smp, + "Set this to enable APM use on an SMP platform. Use with caution on older systems"); EXPORT_NO_SYMBOLS; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/i386/kernel/dmi_scan.c linux.19rc3-ac4/arch/i386/kernel/dmi_scan.c --- linux.19rc3/arch/i386/kernel/dmi_scan.c 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/arch/i386/kernel/dmi_scan.c 2002-07-29 13:58:35.000000000 +0100 @@ -475,6 +475,22 @@ return 0; } +/* + * Work around broken HP Pavilion Notebooks which assign USB to + * IRQ 9 even though it is actually wired to IRQ 11 + */ +static __init int fix_broken_hp_bios_irq9(struct dmi_blacklist *d) +{ +#ifdef CONFIG_PCI + extern int broken_hp_bios_irq9; + if (broken_hp_bios_irq9 == 0) + { + broken_hp_bios_irq9 = 1; + printk(KERN_INFO "%s detected - fixing broken IRQ routing\n", d->ident); + } +#endif + return 0; +} /* * Simple "print if true" callback @@ -738,7 +754,14 @@ NO_MATCH, NO_MATCH } }, - + { fix_broken_hp_bios_irq9, "HP Pavilion N5400 Series Laptop", { + MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + MATCH(DMI_BIOS_VERSION, "GE.M1.03"), + MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook Model GE"), + MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736") + } }, + + /* * Generic per vendor APM settings */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/i386/kernel/elanfreq.c linux.19rc3-ac4/arch/i386/kernel/elanfreq.c --- linux.19rc3/arch/i386/kernel/elanfreq.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/i386/kernel/elanfreq.c 2002-07-29 13:58:35.000000000 +0100 @@ -0,0 +1,235 @@ +/* + * elanfreq: cpufreq driver for the AMD ELAN family + * + * (c) Copyright 2002 Robert Schwebel + * + * Parts of this code are (c) Sven Geggus + * + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * 2002-02-13: - initial revision for 2.4.18-pre9 by Robert Schwebel + * + */ + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#define REG_CSCIR 0x22 /* Chip Setup and Control Index Register */ +#define REG_CSCDR 0x23 /* Chip Setup and Control Data Register */ + +#define SAFE_FREQ 33000 /* every Elan CPU can run at 33 MHz */ + +static int currentspeed; /* current frequency in kHz */ +static unsigned int elanfreq_initialised; + +MODULE_LICENSE("GPL"); + +MODULE_AUTHOR( + "Robert Schwebel , Sven Geggus " +); +MODULE_DESCRIPTION("cpufreq driver for AMD's Elan CPUs"); + +struct s_elan_multiplier { + int clock; /* frequency in kHz */ + int val40h; /* PMU Force Mode register */ + int val80h; /* CPU Clock Speed Register */ +}; + +/* + * It is important that the frequencies + * are listed in ascending order here! + */ +struct s_elan_multiplier elan_multiplier[] = { + {1000, 0x02, 0x18}, + {2000, 0x02, 0x10}, + {4000, 0x02, 0x08}, + {8000, 0x00, 0x00}, + {16000, 0x00, 0x02}, + {33000, 0x00, 0x04}, + {66000, 0x01, 0x04}, + {99000, 0x01, 0x05} +}; + + +/** + * elanfreq_get_cpu_frequency: determine current cpu speed + * + * Finds out at which frequency the CPU of the Elan SOC runs + * at the moment. Frequencies from 1 to 33 MHz are generated + * the normal way, 66 and 99 MHz are called "Hyperspeed Mode" + * and have the rest of the chip running with 33 MHz. + */ + +static unsigned int elanfreq_get_cpu_frequency(void) +{ + u8 clockspeed_reg; /* Clock Speed Register */ + + cli(); + outb_p(0x80,REG_CSCIR); + clockspeed_reg = inb_p(REG_CSCDR); + sti(); + + if ((clockspeed_reg & 0xE0) == 0xE0) { return 0; } + + /* Are we in CPU clock multiplied mode (66/99 MHz)? */ + if ((clockspeed_reg & 0xE0) == 0xC0) { + if ((clockspeed_reg & 0x01) == 0) { + return 66000; + } else { + return 99000; + } + } + + /* 33 MHz is not 32 MHz... */ + if ((clockspeed_reg & 0xE0)==0xA0) + return 33000; + + return ((1<<((clockspeed_reg & 0xE0) >> 5)) * 1000); +} + + +/** + * elanfreq_set_cpu_frequency: Change the CPU core frequency + * @freq: frequency in kHz + * + * This function takes a frequency value and changes the CPU frequency + * according to this. Note that the frequency has to be checked by + * elanfreq_validatespeed() for correctness! + * + * There is no return value. + */ + +static void elanfreq_set_cpu_frequency (unsigned int freq) { + + int i; + + printk(KERN_INFO "elanfreq: attempting to set frequency to %i kHz\n",freq); + + /* search table entry for given Mhz value */ + for (i=0; i<(sizeof(elan_multiplier)/sizeof(struct s_elan_multiplier)); i++) + { + if (elan_multiplier[i].clock==freq) break; + } + + /* XXX Shouldn't we have a sanity check here or can we rely on + the frequency having been checked before ??? */ + + /* + * Access to the Elan's internal registers is indexed via + * 0x22: Chip Setup & Control Register Index Register (CSCI) + * 0x23: Chip Setup & Control Register Data Register (CSCD) + * + */ + + /* + * 0x40 is the Power Management Unit's Force Mode Register. + * Bit 6 enables Hyperspeed Mode (66/100 MHz core frequency) + */ + + cli(); + outb_p(0x40,REG_CSCIR); /* Disable hyperspeed mode */ + outb_p(0x00,REG_CSCDR); + sti(); /* wait till internal pipelines and */ + udelay(1000); /* buffers have cleaned up */ + + cli(); + + /* now, set the CPU clock speed register (0x80) */ + outb_p(0x80,REG_CSCIR); + outb_p(elan_multiplier[i].val80h,REG_CSCDR); + + /* now, the hyperspeed bit in PMU Force Mode Register (0x40) */ + outb_p(0x40,REG_CSCIR); + outb_p(elan_multiplier[i].val40h,REG_CSCDR); + udelay(10000); + sti(); + + currentspeed=freq; + +}; + + +/** + * elanfreq_validatespeed: test if frequency is valid + * @freq: frequency in kHz + * + * This function checks if a given frequency in kHz is valid for the + * hardware supported by the driver. It returns a "best fit" frequency + * which might be different from the given one. + */ + +static unsigned int elanfreq_validatespeed (unsigned int freq) +{ + unsigned int best = 0; + int i; + + for (i=0; i<(sizeof(elan_multiplier)/sizeof(struct s_elan_multiplier)); i++) + { + if (freq >= elan_multiplier[i].clock) + { + best = elan_multiplier[i].clock; + + } + } + + return best; +} + + + +/* + * Module init and exit code + */ + +static int __init elanfreq_init(void) +{ + struct cpuinfo_x86 *c = cpu_data; + struct cpufreq_driver driver; + int ret; + + /* Test if we have the right hardware */ + if ((c->x86_vendor != X86_VENDOR_AMD) || + (c->x86 != 4) || (c->x86_model!=10)) + { + printk(KERN_INFO "elanfreq: error: no Elan processor found!\n"); + return -ENODEV; + } + + driver.freq.cur = elanfreq_get_cpu_frequency(); + driver.validate = &elanfreq_validatespeed; + driver.setspeed = &elanfreq_set_cpu_frequency; + + ret = cpufreq_register(driver); + if (ret) + return ret; + + elanfreq_initialised = 1, + + return 0; +} + + +static void __exit elanfreq_exit(void) +{ + if (elanfreq_initialised) + cpufreq_unregister(); +} + +module_init(elanfreq_init); +module_exit(elanfreq_exit); + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/i386/kernel/entry.S linux.19rc3-ac4/arch/i386/kernel/entry.S --- linux.19rc3/arch/i386/kernel/entry.S 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/arch/i386/kernel/entry.S 2002-07-29 13:58:35.000000000 +0100 @@ -77,7 +77,7 @@ exec_domain = 16 need_resched = 20 tsk_ptrace = 24 -processor = 52 +cpu = 32 ENOSYS = 38 @@ -176,9 +176,11 @@ ENTRY(ret_from_fork) +#if CONFIG_SMP pushl %ebx call SYMBOL_NAME(schedule_tail) addl $4, %esp +#endif GET_CURRENT(%ebx) testb $0x02,tsk_ptrace(%ebx) # PT_TRACESYS jne tracesys_exit @@ -637,8 +639,8 @@ .long SYMBOL_NAME(sys_tkill) .long SYMBOL_NAME(sys_ni_syscall) /* reserved for sendfile64 */ .long SYMBOL_NAME(sys_ni_syscall) /* 240 reserved for futex */ - .long SYMBOL_NAME(sys_ni_syscall) /* reserved for sched_setaffinity */ - .long SYMBOL_NAME(sys_ni_syscall) /* reserved for sched_getaffinity */ + .long SYMBOL_NAME(sys_sched_setaffinity) + .long SYMBOL_NAME(sys_sched_getaffinity) .rept NR_syscalls-(.-sys_call_table)/4 .long SYMBOL_NAME(sys_ni_syscall) diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/i386/kernel/head.S linux.19rc3-ac4/arch/i386/kernel/head.S --- linux.19rc3/arch/i386/kernel/head.S 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/arch/i386/kernel/head.S 2002-07-29 14:44:12.000000000 +0100 @@ -445,4 +445,15 @@ .quad 0x00409a0000000000 /* 0x48 APM CS code */ .quad 0x00009a0000000000 /* 0x50 APM CS 16 code (16 bit) */ .quad 0x0040920000000000 /* 0x58 APM DS data */ + /* Segments used for calling PnP BIOS */ + .quad 0x00c09a0000000000 /* 0x60 32-bit code */ + .quad 0x00809a0000000000 /* 0x68 16-bit code */ + .quad 0x0080920000000000 /* 0x70 16-bit data */ + .quad 0x0080920000000000 /* 0x78 16-bit data */ + .quad 0x0080920000000000 /* 0x80 16-bit data */ + .quad 0x0000000000000000 /* 0x88 not used */ + .quad 0x0000000000000000 /* 0x90 not used */ + .quad 0x0000000000000000 /* 0x98 not used */ + /* Per CPU segments */ .fill NR_CPUS*4,8,0 /* space for TSS's and LDT's */ + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/i386/kernel/i386_ksyms.c linux.19rc3-ac4/arch/i386/kernel/i386_ksyms.c --- linux.19rc3/arch/i386/kernel/i386_ksyms.c 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/arch/i386/kernel/i386_ksyms.c 2002-07-29 13:58:35.000000000 +0100 @@ -49,6 +49,7 @@ EXPORT_SYMBOL(drive_info); #endif +extern unsigned long cpu_khz; extern unsigned long get_cmos_time(void); /* platform dependent support */ @@ -57,6 +58,9 @@ EXPORT_SYMBOL(EISA_bus); #endif EXPORT_SYMBOL(MCA_bus); +#ifdef CONFIG_MULTIQUAD +EXPORT_SYMBOL(xquad_portio); +#endif EXPORT_SYMBOL(__verify_write); EXPORT_SYMBOL(dump_thread); EXPORT_SYMBOL(dump_fpu); @@ -71,6 +75,7 @@ EXPORT_SYMBOL(pm_idle); EXPORT_SYMBOL(pm_power_off); EXPORT_SYMBOL(get_cmos_time); +EXPORT_SYMBOL(cpu_khz); EXPORT_SYMBOL(apm_info); EXPORT_SYMBOL(gdt); EXPORT_SYMBOL(empty_zero_page); @@ -175,7 +180,3 @@ extern int is_sony_vaio_laptop; EXPORT_SYMBOL(is_sony_vaio_laptop); - -#ifdef CONFIG_MULTIQUAD -EXPORT_SYMBOL(xquad_portio); -#endif diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/i386/kernel/i387.c linux.19rc3-ac4/arch/i386/kernel/i387.c --- linux.19rc3/arch/i386/kernel/i387.c 2002-07-29 12:50:04.000000000 +0100 +++ linux.19rc3-ac4/arch/i386/kernel/i387.c 2002-07-29 13:58:35.000000000 +0100 @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -24,6 +25,29 @@ #define HAVE_HWFP 1 #endif +static union i387_union empty_fpu_state; + +void __init boot_init_fpu(void) +{ + memset(&empty_fpu_state, 0, sizeof(union i387_union)); + + if (!cpu_has_fxsr) { + empty_fpu_state.fsave.cwd = 0xffff037f; + empty_fpu_state.fsave.swd = 0xffff0000; + empty_fpu_state.fsave.twd = 0xffffffff; + empty_fpu_state.fsave.fos = 0xffff0000; + } else { + empty_fpu_state.fxsave.cwd = 0x37f; + if (cpu_has_xmm) + empty_fpu_state.fxsave.mxcsr = 0x1f80; + } +} + +void load_empty_fpu(struct task_struct * tsk) +{ + memcpy(&tsk->thread.i387, &empty_fpu_state, sizeof(union i387_union)); +} + /* * The _current_ task is using the FPU for the first time * so initialize it and set the mxcsr to its default @@ -32,10 +56,10 @@ */ void init_fpu(void) { - __asm__("fninit"); - if ( cpu_has_xmm ) - load_mxcsr(0x1f80); - + if (cpu_has_fxsr) + asm volatile("fxrstor %0" : : "m" (empty_fpu_state.fxsave)); + else + __asm__("fninit"); current->used_math = 1; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/i386/kernel/io_apic.c linux.19rc3-ac4/arch/i386/kernel/io_apic.c --- linux.19rc3/arch/i386/kernel/io_apic.c 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/arch/i386/kernel/io_apic.c 2002-07-29 15:25:33.000000000 +0100 @@ -28,10 +28,12 @@ #include #include #include +#include #include #include #include +#include #undef APIC_LOCKUP_DEBUG @@ -183,6 +185,86 @@ clear_IO_APIC_pin(apic, pin); } +static void set_ioapic_affinity (unsigned int irq, unsigned long mask) +{ + unsigned long flags; + + /* + * Only the first 8 bits are valid. + */ + mask = mask << 24; + spin_lock_irqsave(&ioapic_lock, flags); + __DO_ACTION(1, = mask, ) + spin_unlock_irqrestore(&ioapic_lock, flags); +} + +#if CONFIG_SMP + +typedef struct { + unsigned int cpu; + unsigned long timestamp; +} ____cacheline_aligned irq_balance_t; + +static irq_balance_t irq_balance[NR_IRQS] __cacheline_aligned + = { [ 0 ... NR_IRQS-1 ] = { 0, 0 } }; + +extern unsigned long irq_affinity [NR_IRQS]; + +#endif + +#define IDLE_ENOUGH(cpu,now) \ + (idle_cpu(cpu) && ((now) - irq_stat[(cpu)].idle_timestamp > 1)) + +#define IRQ_ALLOWED(cpu,allowed_mask) \ + ((1 << cpu) & (allowed_mask)) + +static unsigned long move(int curr_cpu, unsigned long allowed_mask, unsigned long now, int direction) +{ + int search_idle = 1; + int cpu = curr_cpu; + + goto inside; + + do { + if (unlikely(cpu == curr_cpu)) + search_idle = 0; +inside: + if (direction == 1) { + cpu++; + if (cpu >= smp_num_cpus) + cpu = 0; + } else { + cpu--; + if (cpu == -1) + cpu = smp_num_cpus-1; + } + } while (!IRQ_ALLOWED(cpu,allowed_mask) || + (search_idle && !IDLE_ENOUGH(cpu,now))); + + return cpu; +} + +static inline void balance_irq(int irq) +{ +#if CONFIG_SMP + irq_balance_t *entry = irq_balance + irq; + unsigned long now = jiffies; + + if (unlikely(entry->timestamp != now)) { + unsigned long allowed_mask; + int random_number; + + rdtscl(random_number); + random_number &= 1; + + allowed_mask = cpu_online_map & irq_affinity[irq]; + entry->timestamp = now; + entry->cpu = move(entry->cpu, allowed_mask, now, random_number); + set_ioapic_affinity(irq, cpu_present_to_apicid(entry->cpu)); + } +#endif +} + /* * support for broken MP BIOSs, enables hand-redirection of PIRQ0-7 to * specific CPU-side IRQs. @@ -287,7 +369,7 @@ Dprintk("querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n", bus, slot, pin); - if (mp_bus_id_to_pci_bus[bus] == -1) { + if ((mp_bus_id_to_pci_bus==NULL) || (mp_bus_id_to_pci_bus[bus] == -1)) { printk(KERN_WARNING "PCI BIOS passed nonexistent PCI bus %d!\n", bus); return -1; } @@ -605,6 +687,31 @@ return current_vector; } +#ifdef CONFIG_MULTIQUAD + +/* + * round_robin_cpu_apic_id -- Since Linux doesn't use either the APIC TPRs or + * XTPRs to set task/interrupt priority, xAPICs and SAPICs tend to hit one CPU + * with all interrupts for each quad. Distribute the interrupts using a simple + * round robin scheme. + */ +static inline int round_robin_cpu_apic_id(void) +{ + int val; + static unsigned next_cpu = 0; + + for (;; ++next_cpu) { + if (next_cpu >= smp_num_cpus) + next_cpu = 0; + if (!(logical_cpu_present_map & (1UL << next_cpu))) + continue; + val = cpu_present_to_apicid(next_cpu); + ++next_cpu; + return (val); + } +} +#endif + extern void (*interrupt[NR_IRQS])(void); static struct hw_interrupt_type ioapic_level_irq_type; static struct hw_interrupt_type ioapic_edge_irq_type; @@ -625,8 +732,8 @@ */ memset(&entry,0,sizeof(entry)); - entry.delivery_mode = dest_LowestPrio; - entry.dest_mode = INT_DELIVERY_MODE; + entry.delivery_mode = INT_DELIVERY_MODE; + entry.dest_mode = (INT_DEST_ADDR_MODE != 0); entry.mask = 0; /* enable IRQ */ entry.dest.logical.logical_dest = TARGET_CPUS; @@ -646,7 +753,6 @@ if (irq_trigger(idx)) { entry.trigger = 1; entry.mask = 1; - entry.dest.logical.logical_dest = TARGET_CPUS; } irq = pin_2_irq(idx, apic, pin); @@ -654,7 +760,7 @@ * skip adding the timer int on secondary nodes, which causes * a small but painful rift in the time-space continuum */ - if (clustered_apic_mode && (apic != 0) && (irq == 0)) + if (clustered_apic_logical && (apic != 0) && (irq == 0)) continue; else add_pin_to_irq(irq, apic, pin); @@ -688,8 +794,7 @@ } /* - * Set up the 8259A-master output pin as broadcast to all - * CPUs. + * Set up the 8259A-master output pin: */ void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector) { @@ -707,10 +812,10 @@ * We use logical delivery to get the timer IRQ * to the first CPU. */ - entry.dest_mode = INT_DELIVERY_MODE; + entry.dest_mode = (INT_DEST_ADDR_MODE != 0); entry.mask = 0; /* unmask IRQ now */ entry.dest.logical.logical_dest = TARGET_CPUS; - entry.delivery_mode = dest_LowestPrio; + entry.delivery_mode = INT_DELIVERY_MODE; entry.polarity = 0; entry.trigger = 0; entry.vector = vector; @@ -734,8 +839,9 @@ void __init UNEXPECTED_IO_APIC(void) { - printk(KERN_WARNING " WARNING: unexpected IO-APIC, please mail\n"); - printk(KERN_WARNING " to linux-smp@vger.kernel.org\n"); + printk(KERN_WARNING + "An unexpected IO-APIC was found. If this kernel release is less than\n" + "three months old please report this to linux-smp@vger.kernel.org\n"); } void __init print_IO_APIC(void) @@ -788,6 +894,7 @@ printk(KERN_DEBUG "....... : PRQ implemented: %X\n", reg_01.PRQ); printk(KERN_DEBUG "....... : IO APIC version: %04X\n", reg_01.version); if ( (reg_01.version != 0x01) && /* 82489DX IO-APICs */ + (reg_01.version != 0x02) && /* VIA */ (reg_01.version != 0x10) && /* oldest IO-APICs */ (reg_01.version != 0x11) && /* Pentium/Pro IO-APICs */ (reg_01.version != 0x13) && /* Xeon IO-APICs */ @@ -1062,7 +1169,7 @@ old_id = mp_ioapics[apic].mpc_apicid; - if (mp_ioapics[apic].mpc_apicid >= 0xf) { + if (mp_ioapics[apic].mpc_apicid >= apic_broadcast_id) { printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n", apic, mp_ioapics[apic].mpc_apicid); printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n", @@ -1074,14 +1181,16 @@ * Sanity check, is the ID really free? Every APIC in a * system must have a unique ID or we get lots of nice * 'stuck on smp_invalidate_needed IPI wait' messages. + * I/O APIC IDs no longer have any meaning for xAPICs and SAPICs. */ - if (phys_id_present_map & (1 << mp_ioapics[apic].mpc_apicid)) { + if (!clustered_apic_physical && + (phys_id_present_map & (1 << mp_ioapics[apic].mpc_apicid))) { printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n", apic, mp_ioapics[apic].mpc_apicid); for (i = 0; i < 0xf; i++) if (!(phys_id_present_map & (1 << i))) break; - if (i >= 0xf) + if (i >= apic_broadcast_id) panic("Max APIC ID exceeded!\n"); printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n", i); @@ -1209,6 +1318,7 @@ */ static void ack_edge_ioapic_irq(unsigned int irq) { + balance_irq(irq); if ((irq_desc[irq].status & (IRQ_PENDING | IRQ_DISABLED)) == (IRQ_PENDING | IRQ_DISABLED)) mask_IO_APIC_irq(irq); @@ -1248,6 +1358,7 @@ unsigned long v; int i; + balance_irq(irq); /* * It appears there is an erratum which affects at least version 0x11 * of I/O APIC (that's the 82093AA and cores integrated into various @@ -1304,19 +1415,6 @@ static void mask_and_ack_level_ioapic_irq (unsigned int irq) { /* nothing */ } -static void set_ioapic_affinity (unsigned int irq, unsigned long mask) -{ - unsigned long flags; - /* - * Only the first 8 bits are valid. - */ - mask = mask << 24; - - spin_lock_irqsave(&ioapic_lock, flags); - __DO_ACTION(1, = mask, ) - spin_unlock_irqrestore(&ioapic_lock, flags); -} - /* * Level and edge triggered IO-APIC interrupts need different handling, * so we use two separate IRQ descriptors. Edge triggered IRQs can be diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/i386/kernel/irq.c linux.19rc3-ac4/arch/i386/kernel/irq.c --- linux.19rc3/arch/i386/kernel/irq.c 2002-07-29 12:50:04.000000000 +0100 +++ linux.19rc3-ac4/arch/i386/kernel/irq.c 2002-07-29 13:58:35.000000000 +0100 @@ -170,7 +170,7 @@ p += sprintf(p, "LOC: "); for (j = 0; j < smp_num_cpus; j++) p += sprintf(p, "%10u ", - apic_timer_irqs[cpu_logical_map(j)]); + irq_stat[cpu_logical_map(j)].apic_timer_irqs); p += sprintf(p, "\n"); #endif p += sprintf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); @@ -1076,7 +1076,7 @@ static struct proc_dir_entry * smp_affinity_entry [NR_IRQS]; -static unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL }; +unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL }; static int irq_affinity_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/i386/kernel/longhaul.c linux.19rc3-ac4/arch/i386/kernel/longhaul.c --- linux.19rc3/arch/i386/kernel/longhaul.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/i386/kernel/longhaul.c 2002-07-29 13:58:35.000000000 +0100 @@ -0,0 +1,699 @@ +/* + * $Id: longhaul.c,v 1.52 2002/06/26 15:33:29 db Exp $ + * + * (C) 2001 Dave Jones. + * (C) 2002 Padraig Brady. + * + * Licensed under the terms of the GNU GPL License version 2. + * Based upon datasheets & sample CPUs kindly provided by VIA. + * + * VIA have currently 3 different versions of Longhaul. + * + * +---------------------+----------+---------------------------------+ + * | Marketing name | Codename | longhaul version / features. | + * +---------------------+----------+---------------------------------+ + * | Samuel/CyrixIII | C5A | v1 : multipliers only | + * | Samuel2/C3 | C3E/C5B | v1 : multiplier only | + * | Ezra | C5C | v2 : multipliers & voltage | + * | Ezra-T | C5M/C5N | v3 : multipliers, voltage & FSB | + * +---------------------+----------+---------------------------------+ + * + * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous* + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEBUG + +#ifdef DEBUG +#define dprintk(msg...) printk(msg) +#else +#define dprintk(msg...) do { } while(0); +#endif + +static int numscales=16, numvscales; +static int minvid, maxvid; +static int can_scale_voltage; +static int can_scale_fsb; +static int vrmrev; + + +/* Module parameters */ +static int dont_scale_voltage; +static int dont_scale_fsb; +static int current_fsb; +static int favour_fast_fsb; + +#define __hlt() __asm__ __volatile__("hlt": : :"memory") + +/* + * Clock ratio tables. + * The eblcr ones specify the ratio read from the CPU. + * The clock_ratio ones specify what to write to the CPU. + */ + +/* VIA C3 Samuel 1 & Samuel 2 (stepping 0)*/ +static int __initdata longhaul1_clock_ratio[16] = { + -1, /* 0000 -> RESERVED */ + 30, /* 0001 -> 3.0x */ + 40, /* 0010 -> 4.0x */ + -1, /* 0011 -> RESERVED */ + -1, /* 0100 -> RESERVED */ + 35, /* 0101 -> 3.5x */ + 45, /* 0110 -> 4.5x */ + 55, /* 0111 -> 5.5x */ + 60, /* 1000 -> 6.0x */ + 70, /* 1001 -> 7.0x */ + 80, /* 1010 -> 8.0x */ + 50, /* 1011 -> 5.0x */ + 65, /* 1100 -> 6.5x */ + 75, /* 1101 -> 7.5x */ + -1, /* 1110 -> RESERVED */ + -1, /* 1111 -> RESERVED */ +}; + +static int __initdata samuel1_eblcr[16] = { + 50, /* 0000 -> RESERVED */ + 30, /* 0001 -> 3.0x */ + 40, /* 0010 -> 4.0x */ + -1, /* 0011 -> RESERVED */ + 55, /* 0100 -> 5.5x */ + 35, /* 0101 -> 3.5x */ + 45, /* 0110 -> 4.5x */ + -1, /* 0111 -> RESERVED */ + -1, /* 1000 -> RESERVED */ + 70, /* 1001 -> 7.0x */ + 80, /* 1010 -> 8.0x */ + 60, /* 1011 -> 6.0x */ + -1, /* 1100 -> RESERVED */ + 75, /* 1101 -> 7.5x */ + -1, /* 1110 -> RESERVED */ + 65, /* 1111 -> 6.5x */ +}; + +/* VIA C3 Samuel2 Stepping 1->15 & VIA C3 Ezra */ +static int __initdata longhaul2_clock_ratio[16] = { + 100, /* 0000 -> 10.0x */ + 30, /* 0001 -> 3.0x */ + 40, /* 0010 -> 4.0x */ + 90, /* 0011 -> 9.0x */ + 95, /* 0100 -> 9.5x */ + 35, /* 0101 -> 3.5x */ + 45, /* 0110 -> 4.5x */ + 55, /* 0111 -> 5.5x */ + 60, /* 1000 -> 6.0x */ + 70, /* 1001 -> 7.0x */ + 80, /* 1010 -> 8.0x */ + 50, /* 1011 -> 5.0x */ + 65, /* 1100 -> 6.5x */ + 75, /* 1101 -> 7.5x */ + 85, /* 1110 -> 8.5x */ + 120, /* 1111 -> 12.0x */ +}; + +static int __initdata samuel2_eblcr[16] = { + 90, /* 0000 -> 9.0x */ + 30, /* 0001 -> 3.0x */ + 40, /* 0010 -> 4.0x */ + 100, /* 0011 -> 10.0x */ + 55, /* 0100 -> 5.5x */ + 35, /* 0101 -> 3.5x */ + 45, /* 0110 -> 4.5x */ + 110, /* 0111 -> 11.0x */ + 90, /* 1000 -> 9.0x */ + 70, /* 1001 -> 7.0x */ + 80, /* 1010 -> 8.0x */ + 60, /* 1011 -> 6.0x */ + 120, /* 1100 -> 12.0x */ + 75, /* 1101 -> 7.5x */ + 130, /* 1110 -> 13.0x */ + 65, /* 1111 -> 6.5x */ +}; + +static int __initdata ezra_eblcr[16] = { + 90, /* 0000 -> 9.0x */ + 30, /* 0001 -> 3.0x */ + 40, /* 0010 -> 4.0x */ + 100, /* 0011 -> 10.0x */ + 55, /* 0100 -> 5.5x */ + 35, /* 0101 -> 3.5x */ + 45, /* 0110 -> 4.5x */ + 95, /* 0111 -> 9.5x */ + 50, /* 1000 -> 5.0x */ + 70, /* 1001 -> 7.0x */ + 80, /* 1010 -> 8.0x */ + 60, /* 1011 -> 6.0x */ + 120, /* 1100 -> 12.0x */ + 75, /* 1101 -> 7.5x */ + 85, /* 1110 -> 8.5x */ + 65, /* 1111 -> 6.5x */ +}; + +/* VIA C5M. */ +static int __initdata longhaul3_clock_ratio[32] = { + 100, /* 0000 -> 10.0x */ + 30, /* 0001 -> 3.0x */ + 40, /* 0010 -> 4.0x */ + 90, /* 0011 -> 9.0x */ + 95, /* 0100 -> 9.5x */ + 35, /* 0101 -> 3.5x */ + 45, /* 0110 -> 4.5x */ + 55, /* 0111 -> 5.5x */ + 60, /* 1000 -> 6.0x */ + 70, /* 1001 -> 7.0x */ + 80, /* 1010 -> 8.0x */ + 50, /* 1011 -> 5.0x */ + 65, /* 1100 -> 6.5x */ + 75, /* 1101 -> 7.5x */ + 85, /* 1110 -> 8.5x */ + 120, /* 1111 -> 12.0x */ + + -1, /* 0000 -> RESERVED (10.0x) */ + 110, /* 0001 -> 11.0x */ + 120, /* 0010 -> 12.0x */ + -1, /* 0011 -> RESERVED (9.0x)*/ + 105, /* 0100 -> 10.5x */ + 115, /* 0101 -> 11.5x */ + 125, /* 0110 -> 12.5x */ + 135, /* 0111 -> 13.5x */ + 140, /* 1000 -> 14.0x */ + 150, /* 1001 -> 15.0x */ + 160, /* 1010 -> 16.0x */ + 130, /* 1011 -> 13.0x */ + 145, /* 1100 -> 14.5x */ + 155, /* 1101 -> 15.5x */ + -1, /* 1110 -> RESERVED (13.0x) */ + -1, /* 1111 -> RESERVED (12.0x) */ +}; + +static int __initdata c5m_eblcr[32] = { + 90, /* 0000 -> 9.0x */ + 30, /* 0001 -> 3.0x */ + 40, /* 0010 -> 4.0x */ + 100, /* 0011 -> 10.0x */ + 55, /* 0100 -> 5.5x */ + 35, /* 0101 -> 3.5x */ + 45, /* 0110 -> 4.5x */ + 95, /* 0111 -> 9.5x */ + 50, /* 1000 -> 5.0x */ + 70, /* 1001 -> 7.0x */ + 80, /* 1010 -> 8.0x */ + 60, /* 1011 -> 6.0x */ + 120, /* 1100 -> 12.0x */ + 75, /* 1101 -> 7.5x */ + 85, /* 1110 -> 8.5x */ + 65, /* 1111 -> 6.5x */ + + -1, /* 0000 -> RESERVED (9.0x) */ + 110, /* 0001 -> 11.0x */ + 120, /* 0010 -> 12.0x */ + -1, /* 0011 -> RESERVED (10.0x)*/ + 135, /* 0100 -> 13.5x */ + 115, /* 0101 -> 11.5x */ + 125, /* 0110 -> 12.5x */ + 105, /* 0111 -> 10.5x */ + 130, /* 1000 -> 13.0x */ + 150, /* 1001 -> 15.0x */ + 160, /* 1010 -> 16.0x */ + 140, /* 1011 -> 14.0x */ + -1, /* 1100 -> RESERVED (12.0x) */ + 155, /* 1101 -> 15.5x */ + -1, /* 1110 -> RESERVED (13.0x) */ + 145, /* 1111 -> 14.5x */ +}; + +/* fsb values as defined in CPU */ +static unsigned int eblcr_fsb_table[] = { 66, 133, 100, -1 }; +/* fsb values to favour low fsb speed (lower power) */ +static unsigned int power_fsb_table[] = { 66, 100, 133, -1 }; +/* fsb values to favour high fsb speed (for e.g. if lowering CPU + freq because of heat, but want to maintain highest performance possible) */ +static unsigned int perf_fsb_table[] = { 133, 100, 66, -1 }; +static unsigned int *fsb_search_table; + +/* Voltage scales. Div by 1000 to get actual voltage. */ +static int __initdata vrm85scales[32] = { + 1250, 1200, 1150, 1100, 1050, 1800, 1750, 1700, + 1650, 1600, 1550, 1500, 1450, 1400, 1350, 1300, + 1275, 1225, 1175, 1125, 1075, 1825, 1775, 1725, + 1675, 1625, 1575, 1525, 1475, 1425, 1375, 1325, +}; + +static int __initdata mobilevrmscales[32] = { + 2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650, + 1600, 1550, 1500, 1450, 1500, 1350, 1300, -1, + 1275, 1250, 1225, 1200, 1175, 1150, 1125, 1100, + 1075, 1050, 1025, 1000, 975, 950, 925, -1, +}; + +/* Clock ratios multiplied by 10 */ +static int clock_ratio[32]; +static int eblcr_table[32]; +static int voltage_table[32]; +static int highest_speed, lowest_speed; +static int longhaul; /* version. */ + +/* + * All integer math. + * Input: + * ratio is multiplier*10, for e.g. 15 = 1.5, 12=1.2 + * Output: + * return value is in units of fsb input parameter + */ +static unsigned int get_clock_from_ratio(int ratio, unsigned fsb) +{ + unsigned int clock=0; + + if (ratio > 0 && fsb != 0) { + clock = (ratio/10)*fsb; + if (ratio%10) + clock += (fsb/(10/(ratio%10))); + } + return clock; +} + +static unsigned int longhaul_validatespeed_fsb(unsigned int freq, unsigned fsb, unsigned int oldbest) +{ + int i; + unsigned int newclock; + unsigned int best=0; + + best = oldbest; + + /* Find closest MHz match. */ + for (i=0; i best) && (newclock <= (freq+1))) + if ((newclock>=lowest_speed) && (newclock<=highest_speed)) + best = newclock; + } + return best; +} + +/* Determine nearest speed possible for the desired fsb speed */ +static unsigned int longhaul_validatespeed (unsigned int freq) +{ + unsigned int best=0; + + if (freqhighest_speed) + freq=highest_speed; + + if (can_scale_fsb==1) { + int fsb_index; + for (fsb_index=0; fsb_search_table[fsb_index]!=-1; fsb_index++) + best = longhaul_validatespeed_fsb (freq, fsb_search_table[fsb_index], best); + } else { + /* Can only scale multiplier. */ + best = longhaul_validatespeed_fsb (freq, current_fsb, best); + } + + return best; +} + +/* + * longhaul_set_cpu_frequency() + * This gets passed a MHz value that has been preprocessed + * with longhaul_validatespeed(). + * + * Note this function is only called if a new frequency has been selected. + */ + +static void longhaul_set_cpu_frequency (unsigned int Mhz) +{ + int index; + unsigned int bestfsb=-1; + unsigned long lo, hi; + int bits=-1; + int revkey; + int vidindex, i; + + /* Find out which mult bit-pattern & FSB we want */ + for (index=0; index>18; + return eblcr_fsb_table[invalue]; + } else { + return current_fsb; + } +} + + +static int __init longhaul_get_cpu_mult (void) +{ + unsigned long invalue=0,lo, hi; + + rdmsr (0x2a, lo, hi); + invalue = (lo & (1<<22|1<<23|1<<24|1<<25)) >>22; + if (longhaul==3) { + if (lo & (1<<27)) + invalue+=16; + } + return eblcr_table[invalue]; +} + + +static void __init longhaul_get_ranges (void) +{ + unsigned long lo, hi, invalue; + unsigned int minmult=0, maxmult=0, minfsb=0, maxfsb=0; + unsigned int multipliers[32]= { + 50,30,40,100,55,35,45,95,90,70,80,60,120,75,85,65, + -1,110,120,-1,135,115,125,105,130,150,160,140,-1,155,-1,145 }; + unsigned int fsb_table[4] = { 133, 100, -1, 66 }; + + switch (longhaul) { + case 1: + //FIXME: fill in from datasheet + break; + + case 2 ... 3: + rdmsr (0x110a, lo, hi); + + invalue = (hi & (1<<0|1<<1|1<<2|1<<3)); + if (hi & (1<<11)) + invalue += 16; + maxmult=multipliers[invalue]; + + #if 0 /* This is MaxMhz @ Min Voltage. Ignore for now */ + invalue = (hi & (1<<16|1<<17|1<<18|1<<19)) >> 16; + if (hi & (1<<27)) + invalue += 16; + minmult = multipliers[invalue]; + #else + minmult = 3; /* as per spec */ + #endif + + if (can_scale_fsb==1) { + invalue = (hi & (1<<9|1<<10)) >> 9; + maxfsb = fsb_table[invalue]; + + invalue = (hi & (1<<25|1<<26)) >> 25; + minfsb = fsb_table[invalue]; + + dprintk (KERN_INFO "longhaul: Min FSB=%d Max FSB=%d\n", + minfsb, maxfsb); + } else { + minfsb = maxfsb = current_fsb; + } + break; + } + + highest_speed = get_clock_from_ratio(maxmult, maxfsb); + lowest_speed = get_clock_from_ratio(minmult, minfsb); + + dprintk (KERN_INFO "longhaul: MinMult(x10)=%d MaxMult(x10)=%d\n", + minmult, maxmult); + dprintk (KERN_INFO "longhaul: Lowestspeed=%d Highestspeed=%d\n", + lowest_speed, highest_speed); +} + + +static void __init longhaul_setup_voltagescaling (unsigned long lo, unsigned long hi) +{ + int revkey; + + can_scale_voltage = 1; + + minvid = (hi & (1<<20|1<<21|1<<22|1<<23|1<<24)) >> 20; /* 56:52 */ + maxvid = (hi & (1<<4|1<<5|1<<6|1<<7|1<<8)) >> 4; /* 40:36 */ + vrmrev = (lo & (1<<15))>>15; + + if (vrmrev==0) { + dprintk (KERN_INFO "longhaul: VRM 8.5 : "); + memcpy (voltage_table, vrm85scales, sizeof(voltage_table)); + numvscales = (voltage_table[maxvid]-voltage_table[minvid])/25; + } else { + dprintk (KERN_INFO "longhaul: Mobile VRM : "); + memcpy (voltage_table, mobilevrmscales, sizeof(voltage_table)); + numvscales = (voltage_table[maxvid]-voltage_table[minvid])/5; + } + + /* Current voltage isn't readable at first, so we need to + set it to a known value. The spec says to use maxvid */ + revkey = (lo & 0xf)<<4; /* Rev key. */ + lo &= 0xfe0fff0f; /* Mask unneeded bits */ + lo |= (1<<9); /* EnableSoftVID */ + lo |= revkey; /* Reinsert key */ + lo |= maxvid << 20; + wrmsr (0x110a, lo, hi); + minvid = voltage_table[minvid]; + maxvid = voltage_table[maxvid]; + dprintk ("Min VID=%d.%03d Max VID=%d.%03d, %d possible voltage scales\n", + maxvid/1000, maxvid%1000, minvid/1000, minvid%1000, numvscales); +} + + +static int __init longhaul_init (void) +{ + struct cpuinfo_x86 *c = cpu_data; + unsigned int currentspeed; + static int currentmult; + unsigned long lo, hi; + int ret; + struct cpufreq_driver driver; + + if ((c->x86_vendor != X86_VENDOR_CENTAUR) || (c->x86 !=6) ) + return -ENODEV; + + switch (c->x86_model) { + case 6: /* VIA C3 Samuel C5A */ + return -ENODEV; // See line 499 + longhaul=1; + memcpy (clock_ratio, longhaul1_clock_ratio, sizeof(longhaul1_clock_ratio)); + memcpy (eblcr_table, samuel1_eblcr, sizeof(samuel1_eblcr)); + break; + + case 7: /* C5B / C5C */ + switch (c->x86_mask) { + case 0: + return -ENODEV; // See line 499 + longhaul=1; + memcpy (clock_ratio, longhaul1_clock_ratio, sizeof(longhaul1_clock_ratio)); + memcpy (eblcr_table, samuel2_eblcr, sizeof(samuel2_eblcr)); + break; + case 1 ... 15: + longhaul=2; + memcpy (clock_ratio, longhaul2_clock_ratio, sizeof(longhaul2_clock_ratio)); + memcpy (eblcr_table, ezra_eblcr, sizeof(ezra_eblcr)); + break; + } + break; + + case 8: /* C5M/C5N */ + return -ENODEV; // Waiting on updated docs from VIA before this is usable + longhaul=3; + numscales=32; + memcpy (clock_ratio, longhaul3_clock_ratio, sizeof(longhaul3_clock_ratio)); + memcpy (eblcr_table, c5m_eblcr, sizeof(c5m_eblcr)); + break; + + default: + printk (KERN_INFO "longhaul: Unknown VIA CPU. Contact davej@suse.de\n"); + return -ENODEV; + } + + printk (KERN_INFO "longhaul: VIA CPU detected. Longhaul version %d supported\n", longhaul); + + if (favour_fast_fsb==1) + fsb_search_table = perf_fsb_table; + else + fsb_search_table = power_fsb_table; + + current_fsb = longhaul_get_cpu_fsb(); + currentmult = longhaul_get_cpu_mult(); + currentspeed = get_clock_from_ratio(currentmult, current_fsb); + + dprintk (KERN_INFO "longhaul: CPU currently at %dMHz (%d x %d.%d)\n", + currentspeed, current_fsb, currentmult/10, currentmult%10); + + if (longhaul==2 || longhaul==3) { + rdmsr (0x110a, lo, hi); + if ((lo & (1<<0)) && (dont_scale_voltage==0)) + longhaul_setup_voltagescaling (lo, hi); + + if ((lo & (1<<1)) && (dont_scale_fsb==0) && (current_fsb==0)) + can_scale_fsb = 1; + } + + longhaul_get_ranges(); + + driver.freq.min = (unsigned int) lowest_speed * 1000; + driver.freq.max = (unsigned int) highest_speed * 1000; + driver.freq.cur = currentspeed * 1000; + driver.validate = &longhaul_validatespeed; + driver.setspeed = &longhaul_set_cpu_frequency; + + ret = cpufreq_register(driver); + + if (ret) { + longhaul = 0; + return ret; + } + + return 0; +} + + +static void __exit longhaul_exit (void) +{ + if (longhaul) + cpufreq_unregister(); +} + +MODULE_PARM (dont_scale_fsb, "i"); +MODULE_PARM (dont_scale_voltage, "i"); +MODULE_PARM (current_fsb, "i"); +MODULE_PARM (favour_fast_fsb, "i"); + +MODULE_AUTHOR ("Dave Jones "); +MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors."); +MODULE_LICENSE ("GPL"); + +module_init(longhaul_init); +module_exit(longhaul_exit); + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/i386/kernel/Makefile linux.19rc3-ac4/arch/i386/kernel/Makefile --- linux.19rc3/arch/i386/kernel/Makefile 2002-07-29 12:50:04.000000000 +0100 +++ linux.19rc3-ac4/arch/i386/kernel/Makefile 2002-07-29 13:58:35.000000000 +0100 @@ -40,5 +40,11 @@ obj-$(CONFIG_X86_LOCAL_APIC) += mpparse.o apic.o nmi.o obj-$(CONFIG_X86_IO_APIC) += io_apic.o acpitable.o obj-$(CONFIG_X86_VISWS_APIC) += visws_apic.o +obj-$(CONFIG_X86_POWERNOW_K6) += powernow-k6.o +obj-$(CONFIG_X86_LONGHAUL) += longhaul.o +obj-$(CONFIG_X86_SPEEDSTEP) += speedstep.o +obj-$(CONFIG_X86_P4_CLOCKMOD) += p4-clockmod.o +obj-$(CONFIG_ELAN_CPUFREQ) += elanfreq.o + include $(TOPDIR)/Rules.make diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/i386/kernel/mpparse.c linux.19rc3-ac4/arch/i386/kernel/mpparse.c --- linux.19rc3/arch/i386/kernel/mpparse.c 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/arch/i386/kernel/mpparse.c 2002-07-29 13:58:35.000000000 +0100 @@ -26,6 +26,7 @@ #include #include #include +#include /* Have we found an MP table */ int smp_found_config; @@ -35,18 +36,20 @@ * MP-table. */ int apic_version [MAX_APICS]; -int mp_bus_id_to_type [MAX_MP_BUSSES]; -int mp_bus_id_to_node [MAX_MP_BUSSES]; -int mp_bus_id_to_local [MAX_MP_BUSSES]; int quad_local_to_mp_bus_id [NR_CPUS/4][4]; -int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 }; int mp_current_pci_id; +int *mp_bus_id_to_type; +int *mp_bus_id_to_node; +int *mp_bus_id_to_local; +int *mp_bus_id_to_pci_bus; +int max_mp_busses; +int max_irq_sources; /* I/O APIC entries */ struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS]; /* # of MP IRQ source entries */ -struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES]; +struct mpc_config_intsrc *mp_irqs; /* MP IRQ source entries */ int mp_irq_entries; @@ -64,6 +67,19 @@ /* Bitmask of physically existing CPUs */ unsigned long phys_cpu_present_map; +unsigned long logical_cpu_present_map; + +unsigned int apic_broadcast_id = APIC_BROADCAST_ID_APIC; +unsigned int int_dest_addr_mode = APIC_DEST_LOGICAL; +unsigned char int_delivery_mode = dest_LowestPrio; +unsigned char target_cpus = 0; +unsigned char clustered_apic_mode = 0; +unsigned char clustered_apic_logical = 0; +unsigned char clustered_apic_physical = 0; +unsigned char esr_disable = 0; + +unsigned char raw_phys_apicid[NR_CPUS] = { 0 }; + /* * Intel MP BIOS table parsing routines: @@ -115,6 +131,8 @@ case 0x0F: if (model == 0x00) return("Pentium 4(tm)"); + if (model == 0x02) + return("Pentium 4(tm) XEON(tm)"); if (model == 0x0F) return("Special controller"); } @@ -144,8 +162,8 @@ if (!(m->mpc_cpuflag & CPU_ENABLED)) return; - logical_apicid = m->mpc_apicid; - if (clustered_apic_mode) { + logical_apicid = 0x01; + if (clustered_apic_logical) { quad = translation_table[mpc_record]->trans_quad; logical_apicid = (quad << 4) + (m->mpc_apicid ? m->mpc_apicid << 1 : 1); @@ -221,15 +239,14 @@ if (m->mpc_apicid > MAX_APICS) { printk("Processor #%d INVALID. (Max ID: %d).\n", m->mpc_apicid, MAX_APICS); + --num_processors; return; } ver = m->mpc_apicver; - if (clustered_apic_mode) { - phys_cpu_present_map |= (logical_apicid&0xf) << (4*quad); - } else { - phys_cpu_present_map |= 1 << m->mpc_apicid; - } + logical_cpu_present_map |= 1 << (num_processors-1); + phys_cpu_present_map |= apicid_to_phys_cpu_present(m->mpc_apicid); + /* * Validate version */ @@ -238,6 +255,7 @@ ver = 0x10; } apic_version[m->mpc_apicid] = ver; + raw_phys_apicid[num_processors - 1] = m->mpc_apicid; } static void __init MP_bus_info (struct mpc_config_bus *m) @@ -248,7 +266,7 @@ memcpy(str, m->mpc_bustype, 6); str[6] = 0; - if (clustered_apic_mode) { + if (clustered_apic_logical) { quad = translation_table[mpc_record]->trans_quad; mp_bus_id_to_node[m->mpc_busid] = quad; mp_bus_id_to_local[m->mpc_busid] = translation_table[mpc_record]->trans_local; @@ -302,7 +320,7 @@ m->mpc_irqtype, m->mpc_irqflag & 3, (m->mpc_irqflag >> 2) & 3, m->mpc_srcbus, m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq); - if (++mp_irq_entries == MAX_IRQ_SOURCES) + if (++mp_irq_entries == max_irq_sources) panic("Max # of irq sources exceeded!!\n"); } @@ -392,9 +410,14 @@ static int __init smp_read_mpc(struct mp_config_table *mpc) { - char str[16]; + char oem[16], prod[14]; int count=sizeof(*mpc); unsigned char *mpt=((unsigned char *)mpc)+count; + int num_bus = 0; + int num_irq = 0; + unsigned char *bus_data; + int xapic = 0; + int numaq = 0; if (memcmp(mpc->mpc_signature,MPC_SIGNATURE,4)) { panic("SMP mptable: bad signature [%c%c%c%c]!\n", @@ -417,13 +440,21 @@ printk(KERN_ERR "SMP mptable: null local APIC address!\n"); return 0; } - memcpy(str,mpc->mpc_oem,8); - str[8]=0; - printk("OEM ID: %s ",str); - - memcpy(str,mpc->mpc_productid,12); - str[12]=0; - printk("Product ID: %s ",str); + memcpy(oem,mpc->mpc_oem,8); + oem[8]=0; + printk("OEM ID: %s ",oem); + + memcpy(prod,mpc->mpc_productid,12); + prod[12]=0; + printk("Product ID: %s ",prod); + + /* + * Can't recognize Summit xAPICs at present, so use the OEM ID. + */ + if (!strncmp(oem, "IBM ENSW", 8) && (!strncmp(prod, "NF 6000R", 8) || !strncmp(prod, "VIGIL SMP", 9))) + xapic = 1; + else if (!strncmp(oem, "IBM NUMA", 8)) + numaq = 2; printk("APIC at: 0x%lX\n",mpc->mpc_lapic); @@ -433,16 +464,77 @@ if (!have_acpi_tables) mp_lapic_addr = mpc->mpc_lapic; - if (clustered_apic_mode && mpc->mpc_oemptr) { + if (clustered_apic_logical && mpc->mpc_oemptr) { /* We need to process the oem mpc tables to tell us which quad things are in ... */ mpc_record = 0; smp_read_mpc_oem((struct mp_config_oemtable *) mpc->mpc_oemptr, mpc->mpc_oemsize); mpc_record = 0; } + /* Pre-scan to determine the number of bus and + * interrupts records we have + */ + while (count < mpc->mpc_length) { + switch (*mpt) { + case MP_PROCESSOR: + mpt += sizeof(struct mpc_config_processor); + count += sizeof(struct mpc_config_processor); + break; + case MP_BUS: + ++num_bus; + mpt += sizeof(struct mpc_config_bus); + count += sizeof(struct mpc_config_bus); + break; + case MP_INTSRC: + ++num_irq; + mpt += sizeof(struct mpc_config_intsrc); + count += sizeof(struct mpc_config_intsrc); + break; + case MP_IOAPIC: + mpt += sizeof(struct mpc_config_ioapic); + count += sizeof(struct mpc_config_ioapic); + break; + case MP_LINTSRC: + mpt += sizeof(struct mpc_config_lintsrc); + count += sizeof(struct mpc_config_lintsrc); + break; + default: + count = mpc->mpc_length; + break; + } + } + /* + * Paranoia: Allocate one extra of both the number of busses and number + * of irqs, and make sure that we have at least 4 interrupts per PCI + * slot. But some machines do not report very many busses, so we need + * to fall back on the older defaults. + */ + ++num_bus; + max_mp_busses = max(num_bus, MAX_MP_BUSSES); + if (num_irq < (4 * max_mp_busses)) + num_irq = 4 * num_bus; /* 4 intr/PCI slot */ + ++num_irq; + max_irq_sources = max(num_irq, MAX_IRQ_SOURCES); + + count = (max_mp_busses * sizeof(int)) * 4; + count += (max_irq_sources * sizeof(struct mpc_config_intsrc)); + bus_data = alloc_bootmem(count); + if (!bus_data) { + printk(KERN_ERR "SMP mptable: out of memory!\n"); + return 0; + } + mp_bus_id_to_type = (int *)&bus_data[0]; + mp_bus_id_to_node = (int *)&bus_data[(max_mp_busses * sizeof(int))]; + mp_bus_id_to_local = (int *)&bus_data[(max_mp_busses * sizeof(int)) * 2]; + mp_bus_id_to_pci_bus = (int *)&bus_data[(max_mp_busses * sizeof(int)) * 3]; + mp_irqs = (struct mpc_config_intsrc *)&bus_data[(max_mp_busses * sizeof(int)) * 4]; + memset(mp_bus_id_to_pci_bus, -1, max_mp_busses); + /* * Now process the configuration blocks. */ + count = sizeof(*mpc); + mpt = ((unsigned char *)mpc)+count; while (count < mpc->mpc_length) { switch(*mpt) { case MP_PROCESSOR: @@ -502,6 +594,25 @@ } ++mpc_record; } + if (xapic || numaq) { + if (numaq) { + xapic = 0; /* NUMA-Q boxes never had xAPICs */ + /* Broadcast intrs to local quad only. */ + target_cpus = APIC_BROADCAST_ID_APIC; + } + clustered_apic_logical = (unsigned char) numaq; + clustered_apic_physical = (unsigned char) xapic; + clustered_apic_mode = clustered_apic_logical | clustered_apic_physical; + esr_disable = 1; + apic_broadcast_id = (xapic ? APIC_BROADCAST_ID_XAPIC : APIC_BROADCAST_ID_APIC); + int_dest_addr_mode = (xapic ? APIC_DEST_PHYSICAL : APIC_DEST_LOGICAL); + int_delivery_mode = (xapic ? dest_Fixed : dest_LowestPrio); + phys_cpu_present_map = logical_cpu_present_map; + } + printk("Enabling APIC mode: %s. Using %d I/O APICs\n", + (clustered_apic_logical ? "Clustered Logical" : + (clustered_apic_physical ?"Physical" : "Flat")), + nr_ioapics); if (!num_processors) printk(KERN_ERR "SMP mptable: no processors registered!\n"); return num_processors; @@ -797,18 +908,16 @@ * there is a real-mode segmented pointer pointing to the * 4K EBDA area at 0x40E, calculate and scan it here. * - * NOTE! There are Linux loaders that will corrupt the EBDA + * NOTE! There were Linux loaders that will corrupt the EBDA * area, and as such this kind of SMP config may be less * trustworthy, simply because the SMP table may have been - * stomped on during early boot. These loaders are buggy and - * should be fixed. + * stomped on during early boot. Thankfully the bootloaders + * now honour the EBDA. */ address = *(unsigned short *)phys_to_virt(0x40E); address <<= 4; smp_scan_config(address, 0x1000); - if (smp_found_config) - printk(KERN_WARNING "WARNING: MP table in the EBDA can be UNSAFE, contact linux-smp@vger.kernel.org if you experience SMP problems!\n"); } #else diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/i386/kernel/nmi.c linux.19rc3-ac4/arch/i386/kernel/nmi.c --- linux.19rc3/arch/i386/kernel/nmi.c 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/arch/i386/kernel/nmi.c 2002-07-29 13:58:35.000000000 +0100 @@ -343,7 +343,7 @@ */ int sum, cpu = smp_processor_id(); - sum = apic_timer_irqs[cpu]; + sum = irq_stat[cpu].apic_timer_irqs; if (last_irq_sums[cpu] == sum) { /* diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/i386/kernel/p4-clockmod.c linux.19rc3-ac4/arch/i386/kernel/p4-clockmod.c --- linux.19rc3/arch/i386/kernel/p4-clockmod.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/i386/kernel/p4-clockmod.c 2002-07-29 13:58:35.000000000 +0100 @@ -0,0 +1,233 @@ +/* + * Pentium 4/Xeon CPU on demand clock modulation/speed scaling + * (C) 2002 Zwane Mwaikambo + * (C) 2002 Tora T. Engstad + * (C) 2002 Arjan van de Ven + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * The author(s) of this software shall not be held liable for damages + * of any nature resulting due to the use of this software. This + * software is provided AS-IS with no warranties. + * + * Date Errata Description + * 20020525 N44, O17 12.5% or 25% DC causes lockup + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +/* i'll be submitting a patch to lkml for this */ +#ifndef MSR_IA32_THERM_CONTROL +#define MSR_IA32_THERM_CONTROL 0x19a +#endif +#ifndef MSR_IA32_THERM_STATUS +#define MSR_IA32_THERM_STATUS 0x19c +#endif + +#define PFX "cpufreq: " + +/* + * Duty Cycle (3bits), note DC_DISABLE is not specified in + * intel docs i just use it to mean disable + */ +enum { + DC_RESV, DC_DFLT, DC_25PT, DC_38PT, DC_50PT, + DC_64PT, DC_75PT, DC_88PT, DC_DISABLE +}; + +static int cycle_table[8][2] = { + {13, DC_DFLT }, + {25, DC_25PT }, + {38, DC_38PT }, + {50, DC_50PT }, + {64, DC_64PT }, + {75, DC_75PT }, + {88, DC_88PT }, + {100, DC_DISABLE} }; + +static int has_N44_O17_errata; +static int stock_freq; +MODULE_PARM(stock_freq, "i"); + +static unsigned int cpufreq_p4_initialised; + +static int cpufreq_p4_validatedc(unsigned int percent, unsigned int *pct) +{ + u32 l, h; + int dc = DC_DISABLE, cpu = smp_processor_id(); + int i; + + /* FYI: Thermal monitor takes precedence and does a 50% DC modulation + * so we'll just return the thermal throttled settings to keep everybody + * happy. returning -EBUSY would have been better. + * + * I disagree; if we want to set the percentage LOWER than the thermal throttle + * we should allow that so that it takes effect once the thermal throttle situation + * ends -- Arjan + */ + + rdmsr(MSR_IA32_THERM_STATUS, l, h); + if (l & 0x01) { + printk(KERN_INFO PFX "CPU#%d currently thermal throttled\n", cpu); + if (percent > 50) + goto done; + dc = DC_50PT; + *pct = 50; + goto done; + } + + dc = DC_DFLT; + *pct = 13; + + + /* look up the closest (but lower) duty cycle in the table */ + for (i=0; i<8; i++) + if (percent <= cycle_table[i][0]) { + dc = cycle_table[i][1]; + *pct = cycle_table[i][0]; + break; + } + + + if (has_N44_O17_errata && (dc == DC_25PT || dc == DC_DFLT)) { + dc = DC_38PT; + *pct = 38; + } + +done: + return dc; +} + +static int cpufreq_p4_setdc(unsigned int percent) +{ + u32 l, h; + int pct, dc, cpu = smp_processor_id(); + + dc = cpufreq_p4_validatedc(percent, &pct); + rdmsr(MSR_IA32_THERM_CONTROL, l, h); + + if (dc == DC_DISABLE) { + printk(KERN_INFO PFX "CPU#%d disabling modulation\n", cpu); + wrmsr(MSR_IA32_THERM_CONTROL, l & ~(1<<4), h); + } else { + printk(KERN_INFO PFX "CPU#%d setting duty cycle to %d%%\n", cpu, pct); + /* bits 63 - 5 : reserved + * bit 4 : enable/disable + * bits 3-1 : duty cycle + * bit 0 : reserved + */ + l = (l & ~14); + l = l | (1<<4) | ((dc & 0x7)<<1); + wrmsr(MSR_IA32_THERM_CONTROL, l, h); + } + + return 0; +} + +static unsigned int cpufreq_p4_validate_speed(unsigned int khz) +{ + unsigned int percent, valid_percent, valid_khz; + + percent = (khz * 100) / stock_freq; + cpufreq_p4_validatedc(percent, &valid_percent); + valid_khz = (stock_freq * valid_percent) / 100; + + return valid_khz; +} + +static void cpufreq_p4_set_cpuspeed(unsigned int khz) +{ + unsigned int percent; + + percent = (khz * 100) / stock_freq; + cpufreq_p4_setdc(percent); +} + +int __init cpufreq_p4_init(void) +{ + u32 l, h; + struct cpuinfo_x86 *c = cpu_data; + int cpu = smp_processor_id(); + int cpuid; + int ret; + struct cpufreq_driver driver; + + /* + * THERM_CONTROL is architectural for IA32 now, so + * we can rely on the capability checks + */ + if (c->x86_vendor != X86_VENDOR_INTEL) + return -ENODEV; + + if (!test_bit(X86_FEATURE_ACPI, c->x86_capability) || + !test_bit(X86_FEATURE_ACC, c->x86_capability)) + return -ENODEV; + + /* Errata workarounds */ + cpuid = (c->x86 << 8) | (c->x86_model << 4) | c->x86_mask; + switch (cpuid) { + case 0x0f07: + case 0x0f0a: + case 0x0f11: + case 0x0f12: + has_N44_O17_errata = 1; + default: + break; + } + + printk(KERN_INFO PFX "CPU#%d P4/Xeon(TM) CPU On-Demand Clock Modulation available\n", cpu); + + stock_freq = cpu_khz; /* ugg :( */ + + if (!stock_freq) + return -ENODEV; + + driver.freq.cur=cpu_khz; + driver.freq.min=cpu_khz/10; + driver.freq.max=stock_freq; + driver.validate=&cpufreq_p4_validate_speed; + driver.setspeed=&cpufreq_p4_set_cpuspeed; + + ret = cpufreq_register(driver); + if (ret) + return ret; + + cpufreq_p4_initialised = 1; + + return 0; +} + + +void __exit cpufreq_p4_exit(void) +{ + u32 l, h; + + if (cpufreq_p4_initialised) { + cpufreq_unregister(); + /* return back to a non modulated state */ + rdmsr(MSR_IA32_THERM_CONTROL, l, h); + wrmsr(MSR_IA32_THERM_CONTROL, l & ~(1<<4), h); + cpufreq_p4_initialised = 0; + } +} + +MODULE_AUTHOR ("Zwane Mwaikambo "); +MODULE_DESCRIPTION ("cpufreq driver for Pentium(TM) 4/Xeon(TM)"); +MODULE_LICENSE ("GPL"); + +module_init(cpufreq_p4_init); +module_exit(cpufreq_p4_exit); + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/i386/kernel/pci-irq.c linux.19rc3-ac4/arch/i386/kernel/pci-irq.c --- linux.19rc3/arch/i386/kernel/pci-irq.c 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/arch/i386/kernel/pci-irq.c 2002-07-29 13:58:35.000000000 +0100 @@ -22,6 +22,8 @@ #define PIRQ_SIGNATURE (('$' << 0) + ('P' << 8) + ('I' << 16) + ('R' << 24)) #define PIRQ_VERSION 0x0100 +int broken_hp_bios_irq9; + static struct irq_routing_table *pirq_table; /* @@ -596,6 +598,15 @@ DBG(" -> PIRQ %02x, mask %04x, excl %04x", pirq, mask, pirq_table->exclusive_irqs); mask &= pcibios_irq_mask; + /* Work around broken HP Pavilion Notebooks which assign USB to + IRQ 9 even though it is actually wired to IRQ 11 */ + + if (broken_hp_bios_irq9 && pirq == 0x59 && dev->irq == 9) { + dev->irq = 11; + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11); + r->set(pirq_router_dev, dev, pirq, 11); + } + /* * Find the best IRQ to assign: use the one * reported by the device if possible. diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/i386/kernel/pci-pc.c linux.19rc3-ac4/arch/i386/kernel/pci-pc.c --- linux.19rc3/arch/i386/kernel/pci-pc.c 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/arch/i386/kernel/pci-pc.c 2002-07-29 13:58:35.000000000 +0100 @@ -54,7 +54,7 @@ #define PCI_CONF1_ADDRESS(bus, dev, fn, reg) \ (0x80000000 | (BUS2LOCAL(bus) << 16) | (dev << 11) | (fn << 8) | (reg & ~3)) -static int pci_conf1_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value) /* CONFIG_MULTIQUAD */ +static int pci_conf1_mq_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value) /* CONFIG_MULTIQUAD */ { unsigned long flags; @@ -82,7 +82,7 @@ return 0; } -static int pci_conf1_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value) /* CONFIG_MULTIQUAD */ +static int pci_conf1_mq_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value) /* CONFIG_MULTIQUAD */ { unsigned long flags; @@ -110,7 +110,75 @@ return 0; } -#else /* !CONFIG_MULTIQUAD */ +static int pci_conf1_read_mq_config_byte(struct pci_dev *dev, int where, u8 *value) +{ + int result; + u32 data; + + if (!value) + return -EINVAL; + + result = pci_conf1_mq_read(0, dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), where, 1, &data); + + *value = (u8)data; + + return result; +} + +static int pci_conf1_read_mq_config_word(struct pci_dev *dev, int where, u16 *value) +{ + int result; + u32 data; + + if (!value) + return -EINVAL; + + result = pci_conf1_mq_read(0, dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), where, 2, &data); + + *value = (u16)data; + + return result; +} + +static int pci_conf1_read_mq_config_dword(struct pci_dev *dev, int where, u32 *value) +{ + if (!value) + return -EINVAL; + + return pci_conf1_mq_read(0, dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), where, 4, value); +} + +static int pci_conf1_write_mq_config_byte(struct pci_dev *dev, int where, u8 value) +{ + return pci_conf1_mq_write(0, dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), where, 1, value); +} + +static int pci_conf1_write_mq_config_word(struct pci_dev *dev, int where, u16 value) +{ + return pci_conf1_mq_write(0, dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), where, 2, value); +} + +static int pci_conf1_write_mq_config_dword(struct pci_dev *dev, int where, u32 value) +{ + return pci_conf1_mq_write(0, dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), where, 4, value); +} + +static struct pci_ops pci_direct_mq_conf1 = { + pci_conf1_read_mq_config_byte, + pci_conf1_read_mq_config_word, + pci_conf1_read_mq_config_dword, + pci_conf1_write_mq_config_byte, + pci_conf1_write_mq_config_word, + pci_conf1_write_mq_config_dword +}; + +#endif /* !CONFIG_MULTIQUAD */ #define PCI_CONF1_ADDRESS(bus, dev, fn, reg) \ (0x80000000 | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3)) @@ -170,8 +238,6 @@ return 0; } -#endif /* CONFIG_MULTIQUAD */ - #undef PCI_CONF1_ADDRESS static int pci_conf1_read_config_byte(struct pci_dev *dev, int where, u8 *value) @@ -423,6 +489,12 @@ __restore_flags(flags); printk(KERN_INFO "PCI: Using configuration type 1\n"); request_region(0xCF8, 8, "PCI conf1"); + +#ifdef CONFIG_MULTIQUAD + /* Multi-Quad has an extended PCI Conf1 */ + if(clustered_apic_mode) + return &pci_direct_mq_conf1; +#endif return &pci_direct_conf1; } outl (tmp, 0xCF8); @@ -1156,6 +1228,12 @@ */ if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE) return; + /* + * PCI IDE controllers who are not function 1 off the south bridge + * need to be skipped. + */ + if (!(PCI_FUNC(d->devfn) & 1)) + return; DBG("PCI: IDE base address fixup for %s\n", d->slot_name); for(i=0; i<4; i++) { struct resource *r = &d->resource[i]; @@ -1227,6 +1305,11 @@ pci_read_config_byte(d, PCI_REVISION_ID, &revision); if (d->device == PCI_DEVICE_ID_VIA_8367_0) { + /* fix pci bus latency issues resulted by NB bios error + it appears on bug free^Wreduced kt266x's bios forces + NB latency to zero */ + pci_write_config_byte(d, PCI_LATENCY_TIMER, 0); + where = 0x95; /* the memory write queue timer register is different for the KT266x's: 0x95 not 0x55 */ } else if (d->device == PCI_DEVICE_ID_VIA_8363_0 && @@ -1281,6 +1364,11 @@ * both PCI BIOS and direct access, with a preference for direct. */ +#ifdef CONFIG_PCI_DIRECT + struct pci_ops *tmp = NULL; +#endif + + #ifdef CONFIG_PCI_BIOS if ((pci_probe & PCI_PROBE_BIOS) && ((pci_root_ops = pci_find_bios()))) { @@ -1293,7 +1381,8 @@ #ifdef CONFIG_PCI_DIRECT if ((pci_probe & (PCI_PROBE_CONF1 | PCI_PROBE_CONF2)) - && (pci_root_ops = pci_check_direct())) { + && (tmp = pci_check_direct())) { + pci_root_ops = tmp; if (pci_root_ops == &pci_direct_conf1) { pci_config_read = pci_conf1_read; pci_config_write = pci_conf1_write; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/i386/kernel/powernow-k6.c linux.19rc3-ac4/arch/i386/kernel/powernow-k6.c --- linux.19rc3/arch/i386/kernel/powernow-k6.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/i386/kernel/powernow-k6.c 2002-07-29 13:58:35.000000000 +0100 @@ -0,0 +1,123 @@ +/* + * $Id: powernow-k6.c,v 1.18 2002/06/12 14:37:27 db Exp $ + * This file is part of Powertweak Linux (http://www.powertweak.org) + * and is shared with the Linux Kernel module. + * + * (C) 2000, 2001 Dave Jones, Arjan van de Ven, Janne Pänkälä. + * + * Licensed under the terms of the GNU GPL License version 2. + * + * Version $Id: powernow-k6.c,v 1.18 2002/06/12 14:37:27 db Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static unsigned long cpu_khz=350000; + +/* Clock ratio multiplied by 10 */ +static int clock_ratio[8] = { + 45, /* 000 -> 4.5x */ + 50, /* 001 -> 5.0x */ + 40, /* 010 -> 4.0x */ + 55, /* 011 -> 5.5x */ + 20, /* 100 -> 2.0x */ + 30, /* 101 -> 3.0x */ + 60, /* 110 -> 6.0x */ + 35 /* 111 -> 3.5x */ +}; + +static unsigned int clock_bogomips[8]; + +static unsigned int busfreq; +unsigned int minfreq,maxfreq; + +void set_cpu_frequency_K6(unsigned int Mhz) +{ + int i; + unsigned int best=200; /* safe initial values */ + unsigned int besti=4; + unsigned long outvalue=0,invalue=0; + unsigned long msrval; + + /* Find out which bit-pattern we want */ + + for (i=0;i<8;i++) { + unsigned int newclock; + newclock = (clock_ratio[i]*busfreq/10); + if ((newclock > best) && (newclock <= (Mhz+1))) { + /* +1 is for compensating rounding errors */ + best = newclock; + besti = i; + } + } + + /* "besti" now contains the bitpattern of the new multiplier. + we now need to transform it to the BVC format, see AMD#23446 */ + + outvalue = (1<<12) | (1<<10) | (1<<9) | (besti<<5); + + msrval = 0xFFF1; /* FIXME!! we should check if 0xfff0 is available */ + wrmsr(0xC0000086,msrval,0); /* enable the PowerNow port */ + invalue=inl(0xfff8); + invalue = invalue & 15; + outvalue = outvalue | invalue; + outl(outvalue ,0xFFF8); + msrval = 0xFFF0; + wrmsr(0xC0000086,msrval,0); /* disable it again */ + + /* now adjust bogomips */ + if (!clock_bogomips[besti]) { + /*scale_bogomips(clock_ratio[besti]);*/ + clock_bogomips[besti] = loops_per_jiffy; + } else { + loops_per_jiffy = clock_bogomips[besti]; + } +} + +static int get_cpu_multiplier(void) +{ + unsigned long invalue=0,msrval; + + + msrval = 0xFFF1; /* FIXME!! we should check if 0xfff0 is available */ + wrmsr(0xC0000086, msrval,0 ); /* enable the PowerNow port */ + invalue=inl(0xfff8); + msrval = 0xFFF0; + wrmsr(0xC0000086, msrval,0 ); /* disable it again */ + + printk("Clock ratio is %i\n",clock_ratio[(invalue >> 5)&7]); + return clock_ratio[(invalue >> 5)&7]; +} + +int PowerNow_k6plus_init(void) +{ + struct cpuinfo_x86 *c = cpu_data; + + if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 != 5) || + ((c->x86_model != 12) && (c->x86_model != 13))) + return -ENODEV; + + busfreq = cpu_khz / get_cpu_multiplier() / 100; + //cpufreq_init(0, 0, 0); + return 0; +} + +void PowerNow_k6plus_exit(void) +{ +} + +MODULE_AUTHOR ("Arjan van de Ven , Dave Jones "); +MODULE_DESCRIPTION ("Longhaul driver for AMD K6-2+ / K6-3+ processors."); + +MODULE_LICENSE ("GPL"); +module_init(PowerNow_k6plus_init); +module_exit(PowerNow_k6plus_exit); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/i386/kernel/process.c linux.19rc3-ac4/arch/i386/kernel/process.c --- linux.19rc3/arch/i386/kernel/process.c 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/arch/i386/kernel/process.c 2002-07-29 14:53:49.000000000 +0100 @@ -124,15 +124,12 @@ void cpu_idle (void) { /* endless idle loop with no priority at all */ - init_idle(); - current->nice = 20; - current->counter = -100; while (1) { void (*idle)(void) = pm_idle; if (!idle) idle = default_idle; - while (!current->need_resched) + if (!current->need_resched) idle(); schedule(); check_pgt_cache(); @@ -187,7 +184,7 @@ } /* we will leave sorting out the final value when we are ready to reboot, since we might not - have set up boot_cpu_id or smp_num_cpu */ + have set up boot_cpu_physical_apicid or smp_num_cpu */ break; #endif } @@ -253,7 +250,7 @@ 0x66, 0x0f, 0x20, 0xc3, /* movl %cr0,%ebx */ 0x66, 0x81, 0xe3, 0x00, 0x00, 0x00, 0x60, /* andl $0x60000000,%ebx */ 0x74, 0x02, /* jz f */ - 0x0f, 0x08, /* invd */ + 0x0f, 0x09, /* wbinvd */ 0x24, 0x10, /* f: andb $0x10,al */ 0x66, 0x0f, 0x22, 0xc0 /* movl %eax,%cr0 */ }; @@ -697,15 +694,17 @@ asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->gs)); /* - * Restore %fs and %gs. + * Restore %fs and %gs if needed. */ - loadsegment(fs, next->fs); - loadsegment(gs, next->gs); + if (unlikely(prev->fs | prev->gs | next->fs | next->gs)) { + loadsegment(fs, next->fs); + loadsegment(gs, next->gs); + } /* * Now maybe reload the debug registers */ - if (next->debugreg[7]){ + if (unlikely(next->debugreg[7])) { loaddebug(next, 0); loaddebug(next, 1); loaddebug(next, 2); @@ -715,7 +714,7 @@ loaddebug(next, 7); } - if (prev->ioperm || next->ioperm) { + if (unlikely(prev->ioperm || next->ioperm)) { if (next->ioperm) { /* * 4 cachelines copy ... not good, but not that @@ -739,6 +738,7 @@ } } + asmlinkage int sys_fork(struct pt_regs regs) { return do_fork(SIGCHLD, regs.esp, ®s, 0); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/i386/kernel/ptrace.c linux.19rc3-ac4/arch/i386/kernel/ptrace.c --- linux.19rc3/arch/i386/kernel/ptrace.c 2002-07-29 12:50:04.000000000 +0100 +++ linux.19rc3-ac4/arch/i386/kernel/ptrace.c 2002-07-29 13:58:35.000000000 +0100 @@ -369,12 +369,8 @@ break; } ret = 0; - if ( !child->used_math ) { - /* Simulate an empty FPU. */ - set_fpu_cwd(child, 0x037f); - set_fpu_swd(child, 0x0000); - set_fpu_twd(child, 0xffff); - } + if ( !child->used_math ) + load_empty_fpu(child); get_fpregs((struct user_i387_struct *)data, child); break; } @@ -397,13 +393,8 @@ ret = -EIO; break; } - if ( !child->used_math ) { - /* Simulate an empty FPU. */ - set_fpu_cwd(child, 0x037f); - set_fpu_swd(child, 0x0000); - set_fpu_twd(child, 0xffff); - set_fpu_mxcsr(child, 0x1f80); - } + if ( !child->used_math ) + load_empty_fpu(child); ret = get_fpxregs((struct user_fxsr_struct *)data, child); break; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/i386/kernel/setup.c linux.19rc3-ac4/arch/i386/kernel/setup.c --- linux.19rc3/arch/i386/kernel/setup.c 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/arch/i386/kernel/setup.c 2002-07-29 15:02:45.000000000 +0100 @@ -71,13 +71,6 @@ * CacheSize bug workaround updates for AMD, Intel & VIA Cyrix. * Dave Jones , September, October 2001. * - * Short-term fix for a conflicting cache attribute bug in the kernel - * that is exposed by advanced speculative caching on new AMD Athlon - * processors. - * Richard Brunner and Mark Langsdorf - * , June 2002 - * Adapted to work with uniprocessor APIC by Bryan O'Sullivan - * , June 2002. */ /* @@ -177,12 +170,6 @@ int enable_acpi_smp_table; -#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE) -int disable_adv_spec_cache __initdata = 1; -#else -int disable_adv_spec_cache __initdata = 0; -#endif /* CONFIG_AGP */ - /* * This is set up by the setup-routine at boot-time */ @@ -741,41 +728,6 @@ } /* setup_memory_region */ -int __init amd_adv_spec_cache_feature(void) -{ - char vendor_id[16]; - int ident; - int family, model; - - /* Must have CPUID */ - if(!have_cpuid_p()) - goto donthave; - if(cpuid_eax(0)<1) - goto donthave; - - /* Must be x86 architecture */ - cpuid(0, &ident, - (int *)&vendor_id[0], - (int *)&vendor_id[8], - (int *)&vendor_id[4]); - - if (memcmp(vendor_id, "AuthenticAMD", 12)) - goto donthave; - - ident = cpuid_eax(1); - family = (ident >> 8) & 0xf; - model = (ident >> 4) & 0xf; - if (((family == 6) && (model >= 6)) || (family == 15)) { - printk(KERN_INFO "Advanced speculative caching feature present\n"); - return 1; - } - -donthave: - printk(KERN_INFO "Advanced speculative caching feature not present\n"); - return 0; -} - - static void __init parse_cmdline_early (char ** cmdline_p) { char c = ' ', *to = command_line, *from = COMMAND_LINE; @@ -841,17 +793,6 @@ */ else if (!memcmp(from, "highmem=", 8)) highmem_pages = memparse(from+8, &from) >> PAGE_SHIFT; - /* - * unsafe-gart-alias overrides the short-term fix for a - * conflicting cache attribute bug in the kernel that is - * exposed by advanced speculative caching in newer AMD - * Athlon processors. Overriding the fix will allow - * higher performance but the kernel bug can cause system - * lock-ups if the system uses an AGP card. unsafe-gart-alias - * can be turned on for higher performance in servers. - */ - else if (!memcmp(from, "unsafe-gart-alias", 17)) - disable_adv_spec_cache = 0; nextchar: c = *(from++); if (!c) @@ -1116,14 +1057,6 @@ #ifdef CONFIG_SMP smp_alloc_memory(); /* AP processor realmode stacks in low memory*/ #endif - /* - * short-term fix for a conflicting cache attribute bug in the - * kernel that is exposed by advanced speculative caching on - * newer AMD Athlon processors. - */ - if (disable_adv_spec_cache && amd_adv_spec_cache_feature()) - clear_bit(X86_FEATURE_PSE, &boot_cpu_data.x86_capability); - paging_init(); #ifdef CONFIG_X86_LOCAL_APIC /* @@ -1264,15 +1197,6 @@ l2size = 256; } - /* Intel PIII Tualatin. This comes in two flavours. - * One has 256kb of cache, the other 512. We have no way - * to determine which, so we use a boottime override - * for the 512kb model, and assume 256 otherwise. - */ - if ((c->x86_vendor == X86_VENDOR_INTEL) && (c->x86 == 6) && - (c->x86_model == 11) && (l2size == 0)) - l2size = 256; - /* VIA C3 CPUs (670-68F) need further shifting. */ if (c->x86_vendor == X86_VENDOR_CENTAUR && (c->x86 == 6) && ((c->x86_model == 7) || (c->x86_model == 8))) { @@ -1292,31 +1216,6 @@ l2size, ecx & 0xFF); } - -/*======================================================================= - * amd_adv_spec_cache_disable - * Setting a special MSR big that disables a small part of advanced - * speculative caching as part of a short-term fix for a conflicting cache - * attribute bug in the kernel that is exposed by advanced speculative - * caching in newer AMD Athlon processors. - =======================================================================*/ -static void amd_adv_spec_cache_disable(void) -{ - printk(KERN_INFO "Disabling advanced speculative caching\n"); - - __asm__ __volatile__ ( - " movl $0x9c5a203a,%%edi \n" /* msr enable */ - " movl $0xc0011022,%%ecx \n" /* msr addr */ - " rdmsr \n" /* get reg val */ - " orl $0x00010000,%%eax \n" /* set bit 16 */ - " wrmsr \n" /* put it back */ - " xorl %%edi, %%edi \n" /* clear msr enable */ - : /* no outputs */ - : /* no inputs, either */ - : "%eax","%ecx","%edx","%edi" /* clobbered regs */ ); -} - - /* * B step AMD K6 before B 9730xxxx have hardware bugs that can cause * misexecution of code under Linux. Owners of such processors should @@ -1450,21 +1349,10 @@ * to enable SSE on Palomino/Morgan CPU's. * If the BIOS didn't enable it already, enable it * here. - * - * Avoiding the use of 4MB/2MB pages along with - * setting a special MSR bit that disables a small - * part of advanced speculative caching as part of a - * short-term fix for a conflicting cache attribute - * bug in the kernel that is exposed by advanced - * speculative caching in newer AMD Atlon processors. - * - * If we cleared the PSE bit earlier as part - * of the workaround for this problem, we need - * to clear it again, as our caller may have - * clobbered it if uniprocessor APIC is enabled. */ - if (c->x86_model >= 6) { - if (!cpu_has_xmm) { + if (c->x86_model == 6 || c->x86_model == 7) { + if (!test_bit(X86_FEATURE_XMM, + &c->x86_capability)) { printk(KERN_INFO "Enabling Disabled K7/SSE Support...\n"); rdmsr(MSR_K7_HWCR, l, h); @@ -1473,18 +1361,6 @@ set_bit(X86_FEATURE_XMM, &c->x86_capability); } - if (disable_adv_spec_cache && - amd_adv_spec_cache_feature()) { - clear_bit(X86_FEATURE_PSE, - &c->x86_capability); - amd_adv_spec_cache_disable(); - } - } - break; - case 15: - if (disable_adv_spec_cache && amd_adv_spec_cache_feature()) { - clear_bit(X86_FEATURE_PSE, &c->x86_capability); - amd_adv_spec_cache_disable(); } break; @@ -2229,29 +2105,26 @@ static void __init init_intel(struct cpuinfo_x86 *c) { -#ifndef CONFIG_M686 - static int f00f_workaround_enabled = 0; -#endif - char *p = NULL; unsigned int l1i = 0, l1d = 0, l2 = 0, l3 = 0; /* Cache sizes */ + char *p = NULL; +#ifndef CONFIG_X86_F00F_WORKS_OK + static int f00f_workaround_enabled = 0; -#ifndef CONFIG_M686 /* * All current models of Pentium and Pentium with MMX technology CPUs * have the F0 0F bug, which lets nonpriviledged users lock up the system. * Note that the workaround only should be initialized once... */ c->f00f_bug = 0; - if ( c->x86 == 5 ) { + if (c->x86 == 5) { c->f00f_bug = 1; - if ( !f00f_workaround_enabled ) { + if (!f00f_workaround_enabled) { trap_init_f00f_bug(); printk(KERN_NOTICE "Intel Pentium with F0 0F bug - workaround enabled.\n"); f00f_workaround_enabled = 1; } } -#endif - +#endif /* CONFIG_X86_F00F_WORKS_OK */ if (c->cpuid_level > 1) { /* supports eax=2 call */ @@ -2353,6 +2226,20 @@ } } } + + /* Intel PIII Tualatin. This comes in two flavours. + * One has 256kb of cache, the other 512. We have no way + * to determine which, so we use a boottime override + * for the 512kb model, and assume 256 otherwise. + */ + if ((c->x86_vendor == X86_VENDOR_INTEL) && (c->x86 == 6) && + (c->x86_model == 11) && (l2 == 0)) + l2 = 256; + + /* Allow user to override all this if necessary. */ + if (cachesize_override != -1) + l2 = cachesize_override; + if ( l1i || l1d ) printk(KERN_INFO "CPU: L1 I cache: %dK, L1 D cache: %dK\n", l1i, l1d); @@ -2970,6 +2857,7 @@ * applications want to get the raw CPUID data, they should access * /dev/cpu//cpuid instead. */ + extern int phys_proc_id[NR_CPUS]; static char *x86_cap_flags[] = { /* Intel-defined */ "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce", @@ -3027,6 +2915,11 @@ /* Cache size */ if (c->x86_cache_size >= 0) seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size); + +#ifdef CONFIG_SMP + seq_printf(m, "processor id\t: %d\n",phys_proc_id[n]); + seq_printf(m, "siblings\t: %d\n",smp_num_siblings); +#endif /* We use exception 16 if we have hardware math and we've either seen it or the CPU claims it is internal */ fpu_exception = c->hard_math && (ignore_irq13 || cpu_has_fpu); @@ -3131,9 +3024,10 @@ load_TR(nr); load_LDT(&init_mm); - /* - * Clear all 6 debug registers: - */ + /* Clear %fs and %gs. */ + asm volatile ("xorl %eax, %eax; movl %eax, %fs; movl %eax, %gs"); + + /* Clear all 6 debug registers: */ #define CD(register) __asm__("movl %0,%%db" #register ::"r"(0) ); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/i386/kernel/smpboot.c linux.19rc3-ac4/arch/i386/kernel/smpboot.c --- linux.19rc3/arch/i386/kernel/smpboot.c 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/arch/i386/kernel/smpboot.c 2002-07-29 15:06:28.000000000 +0100 @@ -365,7 +365,7 @@ * (This works even if the APIC is not enabled.) */ phys_id = GET_APIC_ID(apic_read(APIC_ID)); - cpuid = current->processor; + cpuid = cpu(); if (test_and_set_bit(cpuid, &cpu_online_map)) { printk("huh, phys CPU#%d, CPU#%d already present??\n", phys_id, cpuid); @@ -435,6 +435,7 @@ */ smp_store_cpu_info(cpuid); + disable_APIC_timer(); /* * Allow the master to continue. */ @@ -465,6 +466,7 @@ smp_callin(); while (!atomic_read(&smp_commenced)) rep_nop(); + enable_APIC_timer(); /* * low-memory mappings have been cleared, flush them from * the local TLBs too. @@ -509,59 +511,28 @@ return do_fork(CLONE_VM|CLONE_PID, 0, ®s, 0); } -/* which physical APIC ID maps to which logical CPU number */ -volatile int physical_apicid_2_cpu[MAX_APICID]; /* which logical CPU number maps to which physical APIC ID */ -volatile int cpu_2_physical_apicid[NR_CPUS]; +volatile u8 cpu_2_physical_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID }; -/* which logical APIC ID maps to which logical CPU number */ -volatile int logical_apicid_2_cpu[MAX_APICID]; /* which logical CPU number maps to which logical APIC ID */ -volatile int cpu_2_logical_apicid[NR_CPUS]; +volatile u8 cpu_2_logical_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID }; -static inline void init_cpu_to_apicid(void) -/* Initialize all maps between cpu number and apicids */ -{ - int apicid, cpu; - - for (apicid = 0; apicid < MAX_APICID; apicid++) { - physical_apicid_2_cpu[apicid] = -1; - logical_apicid_2_cpu[apicid] = -1; - } - for (cpu = 0; cpu < NR_CPUS; cpu++) { - cpu_2_physical_apicid[cpu] = -1; - cpu_2_logical_apicid[cpu] = -1; - } -} - -static inline void map_cpu_to_boot_apicid(int cpu, int apicid) +static inline void map_cpu_to_boot_apicid(int cpu, int phys_apicid, int log_apicid) /* - * set up a mapping between cpu and apicid. Uses logical apicids for multiquad, - * else physical apic ids + * set up a mapping between cpu and apicids. */ { - if (clustered_apic_mode) { - logical_apicid_2_cpu[apicid] = cpu; - cpu_2_logical_apicid[cpu] = apicid; - } else { - physical_apicid_2_cpu[apicid] = cpu; - cpu_2_physical_apicid[cpu] = apicid; - } + cpu_2_logical_apicid[cpu] = (u8) log_apicid; + cpu_2_physical_apicid[cpu] = (u8) phys_apicid; } -static inline void unmap_cpu_to_boot_apicid(int cpu, int apicid) +static inline void unmap_cpu_to_boot_apicid(int cpu) /* - * undo a mapping between cpu and apicid. Uses logical apicids for multiquad, - * else physical apic ids + * undo a mapping between cpu and apicids. */ { - if (clustered_apic_mode) { - logical_apicid_2_cpu[apicid] = -1; - cpu_2_logical_apicid[cpu] = -1; - } else { - physical_apicid_2_cpu[apicid] = -1; - cpu_2_physical_apicid[cpu] = -1; - } + cpu_2_logical_apicid[cpu] = BAD_APICID; + cpu_2_physical_apicid[cpu] = BAD_APICID; } #if APIC_DEBUG @@ -775,17 +746,13 @@ extern unsigned long cpu_initialized; -static void __init do_boot_cpu (int apicid) -/* - * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad - * (ie clustered apic addressing mode), this is a LOGICAL apic ID. - */ +static void __init do_boot_cpu (int phys_apicid, int log_apicid) { struct task_struct *idle; unsigned long boot_error = 0; int timeout, cpu; unsigned long start_eip; - unsigned short nmi_high, nmi_low; + unsigned short nmi_high = 0, nmi_low = 0; cpu = ++cpucount; /* @@ -803,22 +770,19 @@ if (!idle) panic("No idle process for CPU %d", cpu); - idle->processor = cpu; - idle->cpus_runnable = 1 << cpu; /* we schedule the first task manually */ + init_idle(idle, cpu); - map_cpu_to_boot_apicid(cpu, apicid); + map_cpu_to_boot_apicid(cpu, phys_apicid, log_apicid); idle->thread.eip = (unsigned long) start_secondary; - del_from_runqueue(idle); unhash_process(idle); - init_tasks[cpu] = idle; /* start_eip had better be page-aligned! */ start_eip = setup_trampoline(); /* So we see what's up */ - printk("Booting processor %d/%d eip %lx\n", cpu, apicid, start_eip); + printk("Booting processor %d/%d eip %lx\n", cpu, log_apicid, start_eip); stack_start.esp = (void *) (1024 + PAGE_SIZE + (char *)idle); /* @@ -830,7 +794,7 @@ Dprintk("Setting warm reset code and vector.\n"); - if (clustered_apic_mode) { + if (clustered_apic_logical) { /* stash the current NMI vector, so we can put things back */ nmi_high = *((volatile unsigned short *) TRAMPOLINE_HIGH); nmi_low = *((volatile unsigned short *) TRAMPOLINE_LOW); @@ -847,7 +811,7 @@ /* * Be paranoid about clearing APIC errors. */ - if (!clustered_apic_mode && APIC_INTEGRATED(apic_version[apicid])) { + if (!clustered_apic_mode && APIC_INTEGRATED(apic_version[phys_apicid])) { apic_read_around(APIC_SPIV); apic_write(APIC_ESR, 0); apic_read(APIC_ESR); @@ -862,10 +826,10 @@ * Starting actual IPI sequence... */ - if (clustered_apic_mode) - boot_error = wakeup_secondary_via_NMI(apicid); + if (clustered_apic_logical) + boot_error = wakeup_secondary_via_NMI(log_apicid); else - boot_error = wakeup_secondary_via_INIT(apicid, start_eip); + boot_error = wakeup_secondary_via_INIT(phys_apicid, start_eip); if (!boot_error) { /* @@ -901,13 +865,13 @@ printk("Not responding.\n"); #if APIC_DEBUG if (!clustered_apic_mode) - inquire_remote_apic(apicid); + inquire_remote_apic(phys_apicid); #endif } } if (boot_error) { /* Try to put things back the way they were before ... */ - unmap_cpu_to_boot_apicid(cpu, apicid); + unmap_cpu_to_boot_apicid(cpu); clear_bit(cpu, &cpu_callout_map); /* was set here (do_boot_cpu()) */ clear_bit(cpu, &cpu_initialized); /* was set by cpu_init() */ clear_bit(cpu, &cpu_online_map); /* was set in smp_callin() */ @@ -917,7 +881,7 @@ /* mark "stuck" area as not stuck */ *((volatile unsigned long *)phys_to_virt(8192)) = 0; - if(clustered_apic_mode) { + if (clustered_apic_logical) { printk("Restoring NMI vector\n"); *((volatile unsigned short *) TRAMPOLINE_HIGH) = nmi_high; *((volatile unsigned short *) TRAMPOLINE_LOW) = nmi_low; @@ -925,6 +889,7 @@ } cycles_t cacheflush_time; +unsigned long cache_decay_ticks; static void smp_tune_scheduling (void) { @@ -958,9 +923,13 @@ cacheflush_time = (cpu_khz>>10) * (cachesize<<10) / bandwidth; } + cache_decay_ticks = (long)cacheflush_time/cpu_khz * HZ / 1000; + printk("per-CPU timeslice cutoff: %ld.%02ld usecs.\n", (long)cacheflush_time/(cpu_khz/1000), ((long)cacheflush_time*100/(cpu_khz/1000)) % 100); + printk("task migration cache decay timeout: %ld msecs.\n", + (cache_decay_ticks + 1) * 1000 / HZ); } /* @@ -971,17 +940,19 @@ extern int prof_old_multiplier[NR_CPUS]; extern int prof_counter[NR_CPUS]; -static int boot_cpu_logical_apicid; +#ifdef CONFIG_MULTIQUAD /* Where the IO area was mapped on multiquad, always 0 otherwise */ void *xquad_portio; +#endif int cpu_sibling_map[NR_CPUS] __cacheline_aligned; void __init smp_boot_cpus(void) { - int apicid, cpu, bit; + int phys_apicid, log_apicid, cpu, bit; - if (clustered_apic_mode && (numnodes > 1)) { +#ifdef CONFIG_MULTIQUAD + if (clustered_apic_logical && (numnodes > 1)) { printk("Remapping cross-quad port I/O for %d quads\n", numnodes); printk("xquad_portio vaddr 0x%08lx, len %08lx\n", @@ -990,6 +961,7 @@ xquad_portio = ioremap (XQUAD_PORTIO_BASE, numnodes * XQUAD_PORTIO_LEN); } +#endif #ifdef CONFIG_MTRR /* Must be done before other processors booted */ @@ -1006,8 +978,6 @@ prof_multiplier[cpu] = 1; } - init_cpu_to_apicid(); - /* * Setup boot CPU information */ @@ -1019,12 +989,16 @@ * We have the boot CPU online for sure. */ set_bit(0, &cpu_online_map); - boot_cpu_logical_apicid = logical_smp_processor_id(); - map_cpu_to_boot_apicid(0, boot_cpu_apicid); + if (clustered_apic_physical) + boot_cpu_logical_apicid = physical_to_logical_apicid(boot_cpu_physical_apicid); + else if (clustered_apic_logical) + boot_cpu_logical_apicid = logical_smp_processor_id(); + else + boot_cpu_logical_apicid = 0x01; + map_cpu_to_boot_apicid(0, boot_cpu_physical_apicid, boot_cpu_logical_apicid); global_irq_holder = 0; - current->processor = 0; - init_idle(); + current->cpu = 0; smp_tune_scheduling(); /* @@ -1103,28 +1077,36 @@ */ Dprintk("CPU present map: %lx\n", phys_cpu_present_map); + cpu = 1; for (bit = 0; bit < NR_CPUS; bit++) { - apicid = cpu_present_to_apicid(bit); + if (!(phys_cpu_present_map & (1UL << bit))) + continue; + if ((max_cpus >= 0) && (max_cpus <= cpucount+1)) + continue; + phys_apicid = raw_phys_apicid[bit]; /* * Don't even attempt to start the boot CPU! */ - if (apicid == boot_cpu_apicid) - continue; - - if (!(phys_cpu_present_map & (1 << bit))) - continue; - if ((max_cpus >= 0) && (max_cpus <= cpucount+1)) + if (phys_apicid == boot_cpu_physical_apicid) continue; + if (clustered_apic_physical) + log_apicid = physical_to_logical_apicid(phys_apicid); + else if (clustered_apic_logical) + log_apicid = ((bit >> 2) << 4) | (1 << (bit & 0x3)); + else + log_apicid = 1u << cpu; - do_boot_cpu(apicid); + do_boot_cpu(phys_apicid, log_apicid); /* * Make sure we unmap all failed CPUs */ - if ((boot_apicid_to_cpu(apicid) == -1) && - (phys_cpu_present_map & (1 << bit))) + if ((cpu_to_physical_apicid(bit) == BAD_APICID) && + (phys_cpu_present_map & (1ul << bit))) printk("CPU #%d not responding - cannot use it.\n", - apicid); + bit); + else + ++cpu; } /* diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/i386/kernel/smp.c linux.19rc3-ac4/arch/i386/kernel/smp.c --- linux.19rc3/arch/i386/kernel/smp.c 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/arch/i386/kernel/smp.c 2002-07-29 13:58:35.000000000 +0100 @@ -115,7 +115,7 @@ static inline int __prepare_ICR (unsigned int shortcut, int vector) { - return APIC_DM_FIXED | shortcut | vector | APIC_DEST_LOGICAL; + return APIC_DM_FIXED | shortcut | vector | INT_DEST_ADDR_MODE; } static inline int __prepare_ICR2 (unsigned int mask) @@ -214,7 +214,9 @@ /* * prepare target chip field */ - cfg = __prepare_ICR2(cpu_to_logical_apicid(query_cpu)); + cfg = __prepare_ICR2(clustered_apic_physical ? + cpu_to_physical_apicid(query_cpu) : + cpu_to_logical_apicid(query_cpu)); apic_write_around(APIC_ICR2, cfg); /* @@ -493,13 +495,23 @@ * it goes straight through and wastes no time serializing * anything. Worst case is that we lose a reschedule ... */ - void smp_send_reschedule(int cpu) { send_IPI_mask(1 << cpu, RESCHEDULE_VECTOR); } /* + * this function sends a reschedule IPI to all (other) CPUs. + * This should only be used if some 'global' task became runnable, + * such as a RT task, that must be handled now. The first CPU + * that manages to grab the task will run it. + */ +void smp_send_reschedule_all(void) +{ + send_IPI_allbutself(RESCHEDULE_VECTOR); +} + +/* * Structure and data for smp_call_function(). This is designed to minimise * static memory requirements. It also looks cleaner. */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/i386/kernel/speedstep.c linux.19rc3-ac4/arch/i386/kernel/speedstep.c --- linux.19rc3/arch/i386/kernel/speedstep.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/i386/kernel/speedstep.c 2002-07-29 13:58:35.000000000 +0100 @@ -0,0 +1,693 @@ +/* + * $Id: speedstep.c,v 1.34 2002/07/07 12:29:13 db Exp $ + * + * (C) 2001 Dave Jones, Arjan van de ven. + * (C) 2002 Dominik Brodowski + * + * Licensed under the terms of the GNU GPL License version 2. + * Based upon reverse engineered information, and on Intel documentation + * for chipsets ICH2-M and ICH3-M. + * + * Many thanks to Ducrot Bruno for finding and fixing the last + * "missing link" for ICH2-M/ICH3-M support, and to Thomas Winkler + * for extensive testing. + * + * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous* + * + * Version $Id: speedstep.c,v 1.34 2002/07/07 12:29:13 db Exp $ + */ + + +/********************************************************************* + * SPEEDSTEP - DEFINITIONS * + *********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* speedstep_chipset: + * It is necessary to know which chipset is used. As accesses to + * this device occur at various places in this module, we need a + * static struct pci_dev * pointing to that device. + */ +static unsigned int speedstep_chipset; +static struct pci_dev *speedstep_chipset_dev; + +#define SPEEDSTEP_CHIPSET_ICH2M 0x00000002 +#define SPEEDSTEP_CHIPSET_ICH3M 0x00000003 +//#define SPEEDSTEP_CHIPSET_PIIX4 0x00000004 + + +/* speedstep_processor + */ +static unsigned int speedstep_processor; + +#define SPEEDSTEP_PROCESSOR_PIII_C 0x00000001 /* Coppermine core */ +#define SPEEDSTEP_PROCESSOR_PIII_T 0x00000002 /* Tulatin core */ +#define SPEEDSTEP_PROCESSOR_P4M 0x00000003 /* P4-M with 100 MHz FSB */ + + +/* speedstep_[low,high]_freq + * There are only two frequency states for each processor. Values + * are in kHz for the time being. + */ +static unsigned int speedstep_low_freq; +static unsigned int speedstep_high_freq; + + +/* DEBUG + * Undefine it if you do not want verbose debug output + */ +#define SPEEDSTEP_DEBUG + +#ifdef SPEEDSTEP_DEBUG +#define dprintk(msg...) printk(msg) +#else +#define dprintk(msg...) do { } while(0); +#endif + + + +/********************************************************************* + * LOW LEVEL CHIPSET INTERFACE * + *********************************************************************/ + +/** + * speedstep_get_frequency - read the current SpeedStep state + * @freq: current processor frequency in kHz + * + * Tries to read the SpeedStep state. Returns -EIO when there has been + * trouble to read the status or write to the control register, -EINVAL + * on an unsupported chipset, and zero on success. + */ +static int speedstep_get_frequency (unsigned int *freq) +{ + u32 pmbase; + u8 value; + + if (!speedstep_chipset_dev || !freq) + return -EINVAL; + + switch (speedstep_chipset) { + case SPEEDSTEP_CHIPSET_ICH2M: + case SPEEDSTEP_CHIPSET_ICH3M: + /* get PMBASE */ + pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase); + if (!(pmbase & 0x01)) + return -EIO; + + pmbase &= 0xFFFFFFFE; + if (!pmbase) + return -EIO; + + /* read state */ + local_irq_disable(); + value = inb(pmbase + 0x50); + local_irq_enable(); + + dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value); + + *freq = (value & 0x01) ? speedstep_low_freq : \ + speedstep_high_freq; + return 0; + + } + + printk (KERN_ERR "cpufreq: setting CPU frequency on this chipset unsupported.\n"); + return -EINVAL; +} + + +/** + * speedstep_set_frequency - set the SpeedStep state + * @freq: new processor frequency in kHz + * + * Tries to change the SpeedStep state. + */ +void speedstep_set_frequency (unsigned int freq) +{ + u32 pmbase; + u8 pm2_blk; + u8 value; + unsigned long flags; + + if (!speedstep_chipset_dev || !freq) { + printk(KERN_ERR "cpufreq: unknown chipset or state\n"); + return; + } + + switch (speedstep_chipset) { + case SPEEDSTEP_CHIPSET_ICH2M: + case SPEEDSTEP_CHIPSET_ICH3M: + /* get PMBASE */ + pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase); + if (!(pmbase & 0x01)) + return; + + pmbase &= 0xFFFFFFFE; + if (!pmbase) + return; + + /* read state */ + local_irq_disable(); + value = inb(pmbase + 0x50); + local_irq_enable(); + + dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value); + + /* write new state, but only if indeed a transition + * is necessary */ + if (freq == ((value & 0x01) ? speedstep_low_freq : \ + speedstep_high_freq)) + return; + + value = (freq == speedstep_high_freq) ? 0x00 : 0x01; + + dprintk(KERN_DEBUG "cpufreq: writing 0x%x to pmbase 0x%x + 0x50\n", value, pmbase); + + /* Disable IRQs */ + local_irq_save(flags); + local_irq_disable(); + + /* Disable bus master arbitration */ + pm2_blk = inb(pmbase + 0x20); + pm2_blk |= 0x01; + outb(pm2_blk, (pmbase + 0x20)); + + /* Actual transition */ + outb(value, (pmbase + 0x50)); + + /* Restore bus master arbitration */ + pm2_blk &= 0xfe; + outb(pm2_blk, (pmbase + 0x20)); + + /* Enable IRQs */ + local_irq_enable(); + local_irq_restore(flags); + + /* check if transition was sucessful */ + local_irq_disable(); + value = inb(pmbase + 0x50); + local_irq_enable(); + + dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value); + + if (freq == ((value & 0x01) ? speedstep_low_freq : \ + speedstep_high_freq)) { + dprintk (KERN_INFO "cpufreq: change to %u MHz succeded\n", (freq / 1000)); + return; + } + + printk (KERN_ERR "cpufreq: change failed - I/O error\n"); + return; + } + + printk (KERN_ERR "cpufreq: setting CPU frequency on this chipset unsupported.\n"); + return; +} + + +/** + * speedstep_activate - activate SpeedStep control in the chipset + * + * Tries to activate the SpeedStep status and control registers. + * Returns -EINVAL on an unsupported chipset, and zero on success. + */ +static int speedstep_activate (void) +{ + if (!speedstep_chipset_dev) + return -EINVAL; + + switch (speedstep_chipset) { + case SPEEDSTEP_CHIPSET_ICH2M: + case SPEEDSTEP_CHIPSET_ICH3M: + { + u16 value = 0; + + pci_read_config_word(speedstep_chipset_dev, + 0x00A0, &value); + if (!(value & 0x08)) { + value |= 0x08; + dprintk(KERN_DEBUG "cpufreq: activating SpeedStep (TM) registers\n"); + pci_write_config_word(speedstep_chipset_dev, + 0x00A0, value); + } + + return 0; + } +/* case SPEEDSTEP_CHIPSET_PIIX4: + { + printk (KERN_ERR "cpufreq: SpeedStep (TM) on PIIX4 not yet supported.\n"); + return -EINVAL; + }*/ + } + + printk (KERN_ERR "cpufreq: SpeedStep (TM) on this chipset unsupported.\n"); + return -EINVAL; +} + + +/** + * speedstep_detect_chipset - detect the Southbridge which contains SpeedStep logic + * + * Detects PIIX4, ICH2-M and ICH3-M so far. The pci_dev points to + * the LPC bridge / PM module which contains all power-management + * functions. Returns the SPEEDSTEP_CHIPSET_-number for the detected + * chipset, or zero on failure. + */ +static unsigned int speedstep_detect_chipset (void) +{ + speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82801CA_12, + PCI_ANY_ID, + PCI_ANY_ID, + NULL); + if (speedstep_chipset_dev) + return SPEEDSTEP_CHIPSET_ICH3M; + + + speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82801BA_10, + PCI_ANY_ID, + PCI_ANY_ID, + NULL); + if (speedstep_chipset_dev) + return SPEEDSTEP_CHIPSET_ICH2M; + + speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82371AB_3, + PCI_ANY_ID, + PCI_ANY_ID, + NULL); +// if (speedstep_chipset_dev) +// return SPEEDSTEP_CHIPSET_PIIX4; + + return 0; +} + + + +/********************************************************************* + * LOW LEVEL PROCESSOR INTERFACE * + *********************************************************************/ + + +/** + * pentium6_get_fsb - read the FSB on Intel PIII + * + * Returns the Front Side Bus speed of a Pentium III processor (in MHz). + */ +static inline unsigned int pentium6_get_fsb (void) +{ + /* PIII(-M) FSB settings: see table b1-b of 24547206.pdf */ + struct { + unsigned int value; /* Front Side Bus speed in MHz */ + u8 bitmap; /* power on configuration bits [18: 19] + (in MSR 0x2a) */ + } msr_decode_fsb [] = { + { 66, 0x0 }, + { 100, 0x2 }, + { 133, 0x1 }, + { 0, 0xff} + }; + u32 msr_lo, msr_hi; + int i = 0; + + rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_hi); + + msr_lo &= 0x00c0000; + msr_lo >>= 18; + + while (msr_lo != msr_decode_fsb[i].bitmap) { + if (msr_decode_fsb[i].bitmap == 0xff) + return -EINVAL; + i++; + } + + return msr_decode_fsb[i].value; +} + + +/** + * pentium6_get_ratio - read the frequency multiplier on Intel PIII + * + * Detects the current processor frequency multiplier ratio. + * Returns 10 times the value to properly manage .5 settings. + */ +static inline unsigned int pentium6_get_ratio(void) +{ + /* Intel processor frequency multipliers: + * See table 14 of p3_ds.pdf and table 22 of 29834003.pdf + */ + struct { + unsigned int ratio; /* Frequency Multiplier (x10) */ + u8 bitmap; /* power on configuration bits + [27, 25:22] (in MSR 0x2a) */ + } msr_decode_mult [] = { + { 30, 0x01 }, + { 35, 0x05 }, + { 40, 0x02 }, + { 45, 0x06 }, + { 50, 0x00 }, + { 55, 0x04 }, + { 60, 0x0b }, + { 65, 0x0f }, + { 70, 0x09 }, + { 75, 0x0d }, + { 80, 0x0a }, + { 85, 0x26 }, + { 90, 0x20 }, + { 100, 0x2b }, + { 0, 0xff } /* error or unknown value */ + }; + u32 msr_lo, msr_hi; + int i = 0; + struct cpuinfo_x86 *c = cpu_data; + + rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_hi); + + /* decode value */ + if ((c->x86_model == 0x08) && (c->x86_mask == 0x01)) + /* different on early Coppermine PIII */ + msr_lo &= 0x03c00000; + else + msr_lo &= 0x0bc00000; + + msr_lo >>= 22; + while (msr_lo != msr_decode_mult[i].bitmap) { + if (msr_decode_mult[i].bitmap == 0xff) + return -EINVAL; + i++; + } + + return msr_decode_mult[i].ratio; +} + + +/** + * pentium4_get_frequency - get the core frequency for P4-Ms + * + * Should return the core frequency for P4-Ms. + */ +static inline unsigned int pentium4_get_frequency(void) +{ + u32 msr_lo, msr_hi; + + rdmsr(0x2c, msr_lo, msr_hi); + + dprintk(KERN_DEBUG "cpufreq: P4 - MSR_EBC_FREQUENCY_ID: 0x%x 0x%x\n", msr_lo, msr_hi); + + /* Don't trust unseen values yet, except in the MHz field + */ + if (msr_hi || ((msr_lo & 0x00FFFFFF) != 0x300511)) { + printk(KERN_INFO "cpufreq: Due to incomplete documentation, please send a mail to devel@brodo.de\n"); + printk(KERN_INFO "with a dmesg of a boot while on ac-power, and one of a boot on battery-power.\n"); + printk(KERN_INFO "Thanks in advance.\n"); + return 0; + } + + /* It seems that the frequency is equal to the + * value in bits 24:31 (in 100 MHz). + */ + msr_lo >>= 24; + return (msr_lo * 100); +} + + +/** + * speedstep_detect_processor - detect Intel SpeedStep-capable processors. + * + * Returns the SPEEDSTEP_PROCESSOR_-number for the detected chipset, + * or zero on failure. + */ +static unsigned int speedstep_detect_processor (void) +{ + struct cpuinfo_x86 *c = cpu_data; + u32 ebx; + int check = 0; + + if ((c->x86_vendor != X86_VENDOR_INTEL) || ((c->x86 != 6) && (c->x86 != 0xF))) + return 0; + + if (c->x86 == 0xF) { + /* Intel Pentium 4 Mobile P4-M */ + if (c->x86_model != 2) + return 0; + + if (c->x86_mask != 4) + return 0; /* all those seem to support Enhanced + SpeedStep */ + + return SPEEDSTEP_PROCESSOR_P4M; + } + + switch (c->x86_model) { + case 0x0B: /* Intel PIII [Tulatin] */ + /* cpuid_ebx(1) is 0x04 for desktop PIII, + 0x06 for mobile PIII-M */ + ebx = cpuid_ebx(0x00000001); + + ebx &= 0x000000FF; + if (ebx != 0x06) + return 0; + + /* So far all PIII-M processors support SpeedStep. See + * Intel's 24540628.pdf of March 2002 + */ + + return SPEEDSTEP_PROCESSOR_PIII_T; + + case 0x08: /* Intel PIII [Coppermine] */ + /* all mobile PIII Coppermines have FSB 100 MHz */ + if (pentium6_get_fsb() != 100) + return 0; + + /* Unfortunatey, no information exists on how to check + * whether the processor is capable of SpeedStep. On + * processors that don't support it, doing such + * transitions might be harmful. So the user has to + * override this safety abort. + */ + +/* ---> */ check = 1; /* remove this line to enable SpeedStep. */ + /* See the comment above on why this check + * is necessary - Sorry for the inconvenience! + */ + + if (check) { + printk(KERN_INFO "cpufreq: Intel PIII (Coppermine) detected. If you are sure this is a\n"); + printk(KERN_INFO "cpufreq: SpeedStep capable processor, please remove line %u in\n", (__LINE__ - 7)); + printk(KERN_INFO "cpufreq: linux/arch/i386/kernel/cpufreq/speedstep.c.\n"); + return 0; + } + + return SPEEDSTEP_PROCESSOR_PIII_C; + + default: + return 0; + } +} + + + +/********************************************************************* + * HIGH LEVEL FUNCTIONS * + *********************************************************************/ + + +/** + * speedstep_detect_speeds - detects low and high CPU frequencies. + * + * Detects the low and high CPU frequencies in kHz. Returns 0 on + * success or -EINVAL / -EIO on problems. + */ +static int speedstep_detect_speeds (void) +{ + switch (speedstep_processor) { + case SPEEDSTEP_PROCESSOR_PIII_C: + case SPEEDSTEP_PROCESSOR_PIII_T: + { + unsigned int state; + unsigned int fsb; + int i = 0; + int result; + + fsb = pentium6_get_fsb(); + + for (i=0; i<2; i++) { + /* read the current state */ + result = speedstep_get_frequency(&state); + if (result) + return result; + + /* save the correct value, and switch to other */ + if (state == speedstep_low_freq) { + speedstep_low_freq = + pentium6_get_ratio() * fsb * 100; + speedstep_set_frequency(speedstep_high_freq); + } else { + speedstep_high_freq = + pentium6_get_ratio() * fsb * 100; + speedstep_set_frequency(speedstep_low_freq); + } + } + + if (!speedstep_low_freq || !speedstep_high_freq) + return -EIO; + else + return 0; + } + case SPEEDSTEP_PROCESSOR_P4M: + { + unsigned int state; + int i = 0; + int result; + + for (i=0; i<2; i++) { + /* read the current state */ + result = speedstep_get_frequency(&state); + if (result) + return result; + + /* save the correct value, and switch to other */ + if (state == speedstep_low_freq) { + speedstep_low_freq = + pentium4_get_frequency() * 1000; + speedstep_set_frequency(speedstep_high_freq); + } else { + speedstep_high_freq = + pentium4_get_frequency() * 1000; + speedstep_set_frequency(speedstep_low_freq); + } + } + + if (!speedstep_low_freq || !speedstep_high_freq) + return -EIO; + else + return 0; + } + } + return -EINVAL; +} + + +/** + * speedstep_validate_frequency - validates the CPU frequency to be set + * @kHz: suggested new CPU frequency + * + * Makes sure the CPU frequency to be set is valid. + */ +unsigned int speedstep_validate_frequency(unsigned int kHz) +{ + if (((int) (kHz - speedstep_low_freq)) < + ((int) (speedstep_high_freq - kHz))) + return speedstep_low_freq; + else + return speedstep_high_freq; +} + + +/** + * speedstep_init - initializes the SpeedStep CPUFreq driver + * + * Initializes the SpeedStep support. Returns -ENODEV on unsupported + * devices, -EINVAL on problems during initiatization, and zero on + * success. + */ +static int __init speedstep_init(void) +{ + int result; + unsigned int speed; + struct cpufreq_driver driver; + + printk(KERN_INFO "cpufreq: Intel(R) SpeedStep(TM) support $Revision: 1.34 $\n"); + + /* detect processor */ + speedstep_processor = speedstep_detect_processor(); + + /* detect chipset */ + speedstep_chipset = speedstep_detect_chipset(); + if ((!speedstep_chipset) || (!speedstep_processor)) { + printk(KERN_INFO "cpufreq: Intel(R) SpeedStep(TM) for this %s not (yet) available.\n", speedstep_processor ? "chipset" : "processor"); + return -ENODEV; + } + + /* startup values, correct ones will be detected later */ + speedstep_low_freq = 1; + speedstep_high_freq = 2; + + /* define method to be used */ + dprintk(KERN_DEBUG "cpufreq: chipset 0x%x - processor 0x%x\n", + speedstep_chipset, speedstep_processor); + + /* activate speedstep support */ + result = speedstep_activate(); + if (result) { + speedstep_chipset = 0; + return result; + } + + /* detect low and high frequency */ + result = speedstep_detect_speeds(); + if (result) { + speedstep_chipset = 0; + return result; + } + + /* get current speed setting */ + result = speedstep_get_frequency(&speed); + if (result) { + speedstep_chipset = 0; + return result; + } + + dprintk(KERN_INFO "cpufreq: currently at %s speed setting - %i MHz\n", + (speed == speedstep_low_freq) ? "low" : "high", + (speed / 1000)); + + /* initialization of main "cpufreq" code*/ + driver.freq.min = speedstep_low_freq; + driver.freq.max = speedstep_high_freq; + driver.freq.cur = speed; + driver.validate = &speedstep_validate_frequency; + driver.setspeed = &speedstep_set_frequency; + + result = cpufreq_register(driver); + if (result) { + speedstep_chipset = 0; + return result; + } + + return 0; +} + + +/** + * speedstep_exit - unregisters SpeedStep support + * + * Unregisters SpeedStep support. + */ +static void __exit speedstep_exit(void) +{ + if (speedstep_chipset) + cpufreq_unregister(); +} + + + +MODULE_AUTHOR ("Dave Jones , Dominik Brodowski "); +MODULE_DESCRIPTION ("Speedstep driver for Intel mobile processors."); +MODULE_LICENSE ("GPL"); +module_init(speedstep_init); +module_exit(speedstep_exit); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/i386/kernel/trampoline.S linux.19rc3-ac4/arch/i386/kernel/trampoline.S --- linux.19rc3/arch/i386/kernel/trampoline.S 2002-07-29 12:50:04.000000000 +0100 +++ linux.19rc3-ac4/arch/i386/kernel/trampoline.S 2002-07-29 13:58:35.000000000 +0100 @@ -36,9 +36,7 @@ ENTRY(trampoline_data) r_base = . -#ifdef CONFIG_MULTIQUAD - wbinvd -#endif /* CONFIG_MULTIQUAD */ + wbinvd # Needed for NUMA-Q should be harmless for others mov %cs, %ax # Code and data in the same place mov %ax, %ds diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/i386/kernel/traps.c linux.19rc3-ac4/arch/i386/kernel/traps.c --- linux.19rc3/arch/i386/kernel/traps.c 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/arch/i386/kernel/traps.c 2002-07-29 14:42:39.000000000 +0100 @@ -40,9 +40,9 @@ #include #include +#include #ifdef CONFIG_X86_VISWS_APIC -#include #include #include #endif @@ -276,6 +276,20 @@ void die(const char * str, struct pt_regs * regs, long err) { +#ifdef CONFIG_PNPBIOS + if (regs->xcs == 0x60 || regs->xcs == 0x68) + { + extern u32 pnp_bios_fault_eip, pnp_bios_fault_esp; + extern u32 pnp_bios_is_utter_crap; + pnp_bios_is_utter_crap = 1; + printk(KERN_CRIT "PNPBIOS fault.. attempting recovery.\n"); + __asm__ volatile( + "movl %0, %%esp\n\t" + "jmp %1\n\t" + : "=a" (pnp_bios_fault_esp), "=b" (pnp_bios_fault_eip)); + panic("do_trap: can't hit this"); + } +#endif console_verbose(); spin_lock_irq(&die_lock); bust_spinlocks(1); @@ -305,8 +319,13 @@ static void inline do_trap(int trapnr, int signr, char *str, int vm86, struct pt_regs * regs, long error_code, siginfo_t *info) { - if (vm86 && regs->eflags & VM_MASK) - goto vm86_trap; + if (regs->eflags & VM_MASK) { + if (vm86) + goto vm86_trap; + else + goto trap_signal; + } + if (!(regs->xcs & 3)) goto kernel_trap; @@ -514,10 +533,15 @@ { unsigned int condition; struct task_struct *tsk = current; + unsigned long eip = regs->eip; siginfo_t info; __asm__ __volatile__("movl %%db6,%0" : "=r" (condition)); + /* If the user set TF, it's simplest to clear it right away. */ + if ((eip >=PAGE_OFFSET) && (regs->eflags & TF_MASK)) + goto clear_TF; + /* Mask out spurious debug traps due to lazy DR7 setting */ if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) { if (!tsk->thread.debugreg[7]) @@ -758,35 +782,17 @@ #endif /* CONFIG_MATH_EMULATION */ -#ifndef CONFIG_M686 +#ifndef CONFIG_X86_F00F_WORKS_OK void __init trap_init_f00f_bug(void) { - unsigned long page; - pgd_t * pgd; - pmd_t * pmd; - pte_t * pte; - - /* - * Allocate a new page in virtual address space, - * move the IDT into it and write protect this page. - */ - page = (unsigned long) vmalloc(PAGE_SIZE); - pgd = pgd_offset(&init_mm, page); - pmd = pmd_offset(pgd, page); - pte = pte_offset(pmd, page); - __free_page(pte_page(*pte)); - *pte = mk_pte_phys(__pa(&idt_table), PAGE_KERNEL_RO); - /* - * Not that any PGE-capable kernel should have the f00f bug ... - */ - __flush_tlb_all(); - /* * "idt" is magic - it overlaps the idt_descr * variable so that updating idt will automatically * update the idt descriptor.. */ - idt = (struct desc_struct *)page; + __set_fixmap(FIX_F00F, __pa(&idt_table), PAGE_KERNEL_RO); + idt = (struct desc_struct *)__fix_to_virt(FIX_F00F); + __asm__ __volatile__("lidt %0": "=m" (idt_descr)); } #endif diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/i386/kernel/vm86.c linux.19rc3-ac4/arch/i386/kernel/vm86.c --- linux.19rc3/arch/i386/kernel/vm86.c 2002-07-29 12:50:04.000000000 +0100 +++ linux.19rc3-ac4/arch/i386/kernel/vm86.c 2002-07-29 14:42:00.000000000 +0100 @@ -2,7 +2,34 @@ * linux/kernel/vm86.c * * Copyright (C) 1994 Linus Torvalds + * + * 29 dec 2001 - Fixed oopses caused by unchecked access to the vm86 + * stack - Manfred Spraul + * + * 22 mar 2002 - Manfred detected the stackfaults, but didn't handle + * them correctly. Now the emulation will be in a + * consistent state after stackfaults - Kasper Dupont + * + * + * 22 mar 2002 - Added missing clear_IF in set_vflags_* Kasper Dupont + * + * + * ?? ??? 2002 - Fixed premature returns from handle_vm86_fault + * caused by Kasper Dupont's changes - Stas Sergeev + * + * 4 apr 2002 - Fixed CHECK_IF_IN_TRAP broken by Stas' changes. + * Kasper Dupont + * + * 9 apr 2002 - Changed syntax of macros in handle_vm86_fault. + * Kasper Dupont + * + * 9 apr 2002 - Changed stack access macros to jump to a label + * instead of returning to userspace. This simplifies + * do_int, and is needed by handle_vm6_fault. Kasper + * Dupont + * */ + #include #include #include @@ -97,21 +124,22 @@ pte_t *pte; int i; + spin_lock(&tsk->mm->page_table_lock); pgd = pgd_offset(tsk->mm, 0xA0000); if (pgd_none(*pgd)) - return; + goto out; if (pgd_bad(*pgd)) { pgd_ERROR(*pgd); pgd_clear(pgd); - return; + goto out; } pmd = pmd_offset(pgd, 0xA0000); if (pmd_none(*pmd)) - return; + goto out; if (pmd_bad(*pmd)) { pmd_ERROR(*pmd); pmd_clear(pmd); - return; + goto out; } pte = pte_offset(pmd, 0xA0000); for (i = 0; i < 32; i++) { @@ -119,6 +147,8 @@ set_pte(pte, pte_wrprotect(*pte)); pte++; } +out: + spin_unlock(&tsk->mm->page_table_lock); flush_tlb(); } @@ -290,12 +320,30 @@ regs->eflags &= ~TF_MASK; } +static inline void clear_AC(struct kernel_vm86_regs * regs) +{ + regs->eflags &= ~AC_MASK; +} + +/* It is correct to call set_IF(regs) from the set_vflags_* + * functions. However someone forgot to call clear_IF(regs) + * in the opposite case. + * After the command sequence CLI PUSHF STI POPF you should + * end up with interrups disabled, but you ended up with + * interrupts enabled. + * ( I was testing my own changes, but the only bug I + * could find was in a function I had not changed. ) + * [KD] + */ + static inline void set_vflags_long(unsigned long eflags, struct kernel_vm86_regs * regs) { set_flags(VEFLAGS, eflags, current->thread.v86mask); set_flags(regs->eflags, eflags, SAFE_MASK); if (eflags & IF_MASK) set_IF(regs); + else + clear_IF(regs); } static inline void set_vflags_short(unsigned short flags, struct kernel_vm86_regs * regs) @@ -304,6 +352,8 @@ set_flags(regs->eflags, flags, SAFE_MASK); if (flags & IF_MASK) set_IF(regs); + else + clear_IF(regs); } static inline unsigned long get_vflags(struct kernel_vm86_regs * regs) @@ -323,80 +373,90 @@ return nr; } -/* - * Boy are these ugly, but we need to do the correct 16-bit arithmetic. - * Gcc makes a mess of it, so we do it inline and use non-obvious calling - * conventions.. - */ -#define pushb(base, ptr, val) \ -__asm__ __volatile__( \ - "decw %w0\n\t" \ - "movb %2,0(%1,%0)" \ - : "=r" (ptr) \ - : "r" (base), "q" (val), "0" (ptr)) - -#define pushw(base, ptr, val) \ -__asm__ __volatile__( \ - "decw %w0\n\t" \ - "movb %h2,0(%1,%0)\n\t" \ - "decw %w0\n\t" \ - "movb %b2,0(%1,%0)" \ - : "=r" (ptr) \ - : "r" (base), "q" (val), "0" (ptr)) - -#define pushl(base, ptr, val) \ -__asm__ __volatile__( \ - "decw %w0\n\t" \ - "rorl $16,%2\n\t" \ - "movb %h2,0(%1,%0)\n\t" \ - "decw %w0\n\t" \ - "movb %b2,0(%1,%0)\n\t" \ - "decw %w0\n\t" \ - "rorl $16,%2\n\t" \ - "movb %h2,0(%1,%0)\n\t" \ - "decw %w0\n\t" \ - "movb %b2,0(%1,%0)" \ - : "=r" (ptr) \ - : "r" (base), "q" (val), "0" (ptr)) - -#define popb(base, ptr) \ -({ unsigned long __res; \ -__asm__ __volatile__( \ - "movb 0(%1,%0),%b2\n\t" \ - "incw %w0" \ - : "=r" (ptr), "=r" (base), "=q" (__res) \ - : "0" (ptr), "1" (base), "2" (0)); \ -__res; }) - -#define popw(base, ptr) \ -({ unsigned long __res; \ -__asm__ __volatile__( \ - "movb 0(%1,%0),%b2\n\t" \ - "incw %w0\n\t" \ - "movb 0(%1,%0),%h2\n\t" \ - "incw %w0" \ - : "=r" (ptr), "=r" (base), "=q" (__res) \ - : "0" (ptr), "1" (base), "2" (0)); \ -__res; }) - -#define popl(base, ptr) \ -({ unsigned long __res; \ -__asm__ __volatile__( \ - "movb 0(%1,%0),%b2\n\t" \ - "incw %w0\n\t" \ - "movb 0(%1,%0),%h2\n\t" \ - "incw %w0\n\t" \ - "rorl $16,%2\n\t" \ - "movb 0(%1,%0),%b2\n\t" \ - "incw %w0\n\t" \ - "movb 0(%1,%0),%h2\n\t" \ - "incw %w0\n\t" \ - "rorl $16,%2" \ - : "=r" (ptr), "=r" (base), "=q" (__res) \ - : "0" (ptr), "1" (base)); \ -__res; }) +#define val_byte(val, n) (((__u8 *)&val)[n]) -static void do_int(struct kernel_vm86_regs *regs, int i, unsigned char * ssp, unsigned long sp) +#define pushb(base, ptr, val, err_label) \ + do { \ + __u8 __val = val; \ + ptr--; \ + if (put_user(__val, base + ptr) < 0) \ + goto err_label; \ + } while(0) + +#define pushw(base, ptr, val, err_label) \ + do { \ + __u16 __val = val; \ + ptr--; \ + if (put_user(val_byte(__val, 1), base + ptr) < 0) \ + goto err_label; \ + ptr--; \ + if (put_user(val_byte(__val, 0), base + ptr) < 0) \ + goto err_label; \ + } while(0) + +#define pushl(base, ptr, val, err_label) \ + do { \ + __u32 __val = val; \ + ptr--; \ + if (put_user(val_byte(__val, 3), base + ptr) < 0) \ + goto err_label; \ + ptr--; \ + if (put_user(val_byte(__val, 2), base + ptr) < 0) \ + goto err_label; \ + ptr--; \ + if (put_user(val_byte(__val, 1), base + ptr) < 0) \ + goto err_label; \ + ptr--; \ + if (put_user(val_byte(__val, 0), base + ptr) < 0) \ + goto err_label; \ + } while(0) + +#define popb(base, ptr, err_label) \ + ({ \ + __u8 __res; \ + if (get_user(__res, base + ptr) < 0) \ + goto err_label; \ + ptr++; \ + __res; \ + }) + +#define popw(base, ptr, err_label) \ + ({ \ + __u16 __res; \ + if (get_user(val_byte(__res, 0), base + ptr) < 0) \ + goto err_label; \ + ptr++; \ + if (get_user(val_byte(__res, 1), base + ptr) < 0) \ + goto err_label; \ + ptr++; \ + __res; \ + }) + +#define popl(base, ptr, err_label) \ + ({ \ + __u32 __res; \ + if (get_user(val_byte(__res, 0), base + ptr) < 0) \ + goto err_label; \ + ptr++; \ + if (get_user(val_byte(__res, 1), base + ptr) < 0) \ + goto err_label; \ + ptr++; \ + if (get_user(val_byte(__res, 2), base + ptr) < 0) \ + goto err_label; \ + ptr++; \ + if (get_user(val_byte(__res, 3), base + ptr) < 0) \ + goto err_label; \ + ptr++; \ + __res; \ + }) + +/* There are so many possible reasons for this function to return + * VM86_INTx, so adding another doesn't bother me. We can expect + * userspace programs to be able to handle it. (Getting a problem + * in userspace is always better than an Oops anyway.) [KD] + */ +static void do_int(struct kernel_vm86_regs *regs, int i, + unsigned char * ssp, unsigned short sp) { unsigned long *intr_ptr, segoffs; @@ -411,14 +471,15 @@ goto cannot_handle; if ((segoffs >> 16) == BIOSSEG) goto cannot_handle; - pushw(ssp, sp, get_vflags(regs)); - pushw(ssp, sp, regs->cs); - pushw(ssp, sp, IP(regs)); + pushw(ssp, sp, get_vflags(regs), cannot_handle); + pushw(ssp, sp, regs->cs, cannot_handle); + pushw(ssp, sp, IP(regs), cannot_handle); regs->cs = segoffs >> 16; SP(regs) -= 6; IP(regs) = segoffs & 0xffff; clear_TF(regs); clear_IF(regs); + clear_AC(regs); return; cannot_handle: @@ -450,75 +511,80 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code) { - unsigned char *csp, *ssp; - unsigned long ip, sp; + unsigned char *csp, *ssp, opcode; + unsigned short ip, sp; + int data32, pref_done; #define CHECK_IF_IN_TRAP \ if (VMPI.vm86dbg_active && VMPI.vm86dbg_TFpendig) \ - pushw(ssp,sp,popw(ssp,sp) | TF_MASK); -#define VM86_FAULT_RETURN \ + newflags |= TF_MASK +#define VM86_FAULT_RETURN do { \ if (VMPI.force_return_for_pic && (VEFLAGS & (IF_MASK | VIF_MASK))) \ return_to_32bit(regs, VM86_PICRETURN); \ - return; + return; } while (0) csp = (unsigned char *) (regs->cs << 4); ssp = (unsigned char *) (regs->ss << 4); sp = SP(regs); ip = IP(regs); - switch (popb(csp, ip)) { - - /* operand size override */ - case 0x66: - switch (popb(csp, ip)) { - - /* pushfd */ - case 0x9c: - SP(regs) -= 4; - IP(regs) += 2; - pushl(ssp, sp, get_vflags(regs)); - VM86_FAULT_RETURN; - - /* popfd */ - case 0x9d: - SP(regs) += 4; - IP(regs) += 2; - CHECK_IF_IN_TRAP - set_vflags_long(popl(ssp, sp), regs); - VM86_FAULT_RETURN; - - /* iretd */ - case 0xcf: - SP(regs) += 12; - IP(regs) = (unsigned short)popl(ssp, sp); - regs->cs = (unsigned short)popl(ssp, sp); - CHECK_IF_IN_TRAP - set_vflags_long(popl(ssp, sp), regs); - VM86_FAULT_RETURN; - /* need this to avoid a fallthrough */ - default: - return_to_32bit(regs, VM86_UNKNOWN); + data32 = 0; + pref_done = 0; + do { + switch (opcode = popb(csp, ip, simulate_sigsegv)) { + case 0x66: /* 32-bit data */ data32=1; break; + case 0x67: /* 32-bit address */ break; + case 0x2e: /* CS */ break; + case 0x3e: /* DS */ break; + case 0x26: /* ES */ break; + case 0x36: /* SS */ break; + case 0x65: /* GS */ break; + case 0x64: /* FS */ break; + case 0xf2: /* repnz */ break; + case 0xf3: /* rep */ break; + default: pref_done = 1; } + } while (!pref_done); + + switch (opcode) { /* pushf */ case 0x9c: - SP(regs) -= 2; - IP(regs)++; - pushw(ssp, sp, get_vflags(regs)); + if (data32) { + pushl(ssp, sp, get_vflags(regs), simulate_sigsegv); + SP(regs) -= 4; + } else { + pushw(ssp, sp, get_vflags(regs), simulate_sigsegv); + SP(regs) -= 2; + } + IP(regs) = ip; VM86_FAULT_RETURN; /* popf */ case 0x9d: - SP(regs) += 2; - IP(regs)++; - CHECK_IF_IN_TRAP - set_vflags_short(popw(ssp, sp), regs); + { + unsigned long newflags; + if (data32) { + newflags=popl(ssp, sp, simulate_sigsegv); + SP(regs) += 4; + } else { + newflags = popw(ssp, sp, simulate_sigsegv); + SP(regs) += 2; + } + IP(regs) = ip; + CHECK_IF_IN_TRAP; + if (data32) { + set_vflags_long(newflags, regs); + } else { + set_vflags_short(newflags, regs); + } VM86_FAULT_RETURN; + } /* int xx */ case 0xcd: { - int intno=popb(csp, ip); - IP(regs) += 2; + int intno=popb(csp, ip, simulate_sigsegv); + IP(regs) = ip; if (VMPI.vm86dbg_active) { if ( (1 << (intno &7)) & VMPI.vm86dbg_intxxtab[intno >> 3] ) return_to_32bit(regs, VM86_INTx + (intno << 8)); @@ -529,16 +595,35 @@ /* iret */ case 0xcf: - SP(regs) += 6; - IP(regs) = popw(ssp, sp); - regs->cs = popw(ssp, sp); - CHECK_IF_IN_TRAP - set_vflags_short(popw(ssp, sp), regs); + { + unsigned long newip; + unsigned long newcs; + unsigned long newflags; + if (data32) { + newip=popl(ssp, sp, simulate_sigsegv); + newcs=popl(ssp, sp, simulate_sigsegv); + newflags=popl(ssp, sp, simulate_sigsegv); + SP(regs) += 12; + } else { + newip = popw(ssp, sp, simulate_sigsegv); + newcs = popw(ssp, sp, simulate_sigsegv); + newflags = popw(ssp, sp, simulate_sigsegv); + SP(regs) += 6; + } + IP(regs) = newip; + regs->cs = newcs; + CHECK_IF_IN_TRAP; + if (data32) { + set_vflags_long(newflags, regs); + } else { + set_vflags_short(newflags, regs); + } VM86_FAULT_RETURN; + } /* cli */ case 0xfa: - IP(regs)++; + IP(regs) = ip; clear_IF(regs); VM86_FAULT_RETURN; @@ -550,13 +635,28 @@ * Probably needs some horsing around with the TF flag. Aiee.. */ case 0xfb: - IP(regs)++; + IP(regs) = ip; set_IF(regs); VM86_FAULT_RETURN; default: return_to_32bit(regs, VM86_UNKNOWN); } + + return; + +simulate_sigsegv: + /* FIXME: After a long discussion with Stas we finally + * agreed, that this is wrong. Here we should + * really send a SIGSEGV to the user program. + * But how do we create the correct context? We + * are inside a general protection fault handler + * and has just returned from a page fault handler. + * The correct context for the signal handler + * should be a mixture of the two, but how do we + * get the information? [KD] + */ + return_to_32bit(regs, VM86_UNKNOWN); } /* ---------------- vm86 special IRQ passing stuff ----------------- */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/i386/mm/fault.c linux.19rc3-ac4/arch/i386/mm/fault.c --- linux.19rc3/arch/i386/mm/fault.c 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/arch/i386/mm/fault.c 2002-07-29 17:22:23.000000000 +0100 @@ -76,9 +76,7 @@ return 1; check_stack: - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; - if (expand_stack(vma, start) == 0) + if (!expand_stack(vma, start)) goto good_area; bad_area: @@ -86,8 +84,7 @@ out_of_memory: if (current->pid == 1) { - current->policy |= SCHED_YIELD; - schedule(); + yield(); goto survive; } goto bad_area; @@ -336,8 +333,7 @@ out_of_memory: up_read(&mm->mmap_sem); if (tsk->pid == 1) { - tsk->policy |= SCHED_YIELD; - schedule(); + yield(); down_read(&mm->mmap_sem); goto survive; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/ia64/config.in linux.19rc3-ac4/arch/ia64/config.in --- linux.19rc3/arch/ia64/config.in 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/arch/ia64/config.in 2002-07-29 13:58:35.000000000 +0100 @@ -239,6 +239,8 @@ source drivers/usb/Config.in +source lib/Config.in + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then source net/bluetooth/Config.in fi diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/ia64/defconfig linux.19rc3-ac4/arch/ia64/defconfig --- linux.19rc3/arch/ia64/defconfig 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/arch/ia64/defconfig 2002-07-29 13:58:35.000000000 +0100 @@ -672,7 +672,6 @@ # CONFIG_SOLARIS_X86_PARTITION is not set # CONFIG_UNIXWARE_DISKLABEL is not set CONFIG_EFI_PARTITION=y -# CONFIG_DEVFS_GUID is not set # CONFIG_LDM_PARTITION is not set # CONFIG_SGI_PARTITION is not set # CONFIG_ULTRIX_PARTITION is not set diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/ia64/ia32/sys_ia32.c linux.19rc3-ac4/arch/ia64/ia32/sys_ia32.c --- linux.19rc3/arch/ia64/ia32/sys_ia32.c 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/arch/ia64/ia32/sys_ia32.c 2002-07-29 13:58:35.000000000 +0100 @@ -3693,7 +3693,11 @@ return result; } -struct dqblk32 { +extern asmlinkage long sys_quotactl(int cmd, const char *special, int id, caddr_t addr); + +#ifdef CONFIG_QIFACE_COMPAT +#ifdef CONFIG_QIFACE_V1 +struct user_dqblk32 { __u32 dqb_bhardlimit; __u32 dqb_bsoftlimit; __u32 dqb_curblocks; @@ -3703,49 +3707,82 @@ __kernel_time_t32 dqb_btime; __kernel_time_t32 dqb_itime; }; +typedef struct v1c_mem_dqblk comp_dqblk_t; -asmlinkage long -sys32_quotactl (int cmd, unsigned int special, int id, struct dqblk32 *addr) +#define Q_COMP_GETQUOTA Q_V1_GETQUOTA +#define Q_COMP_SETQUOTA Q_V1_SETQUOTA +#define Q_COMP_SETQLIM Q_V1_SETQLIM +#define Q_COMP_SETUSE Q_V1_SETUSE +#else +struct user_dqblk32 { + __u32 dqb_ihardlimit; + __u32 dqb_isoftlimit; + __u32 dqb_curinodes; + __u32 dqb_bhardlimit; + __u32 dqb_bsoftlimit; + __u64 dqb_curspace; + __kernel_time_t32 dqb_btime; + __kernel_time_t32 dqb_itime; +}; +typedef struct v2c_mem_dqblk comp_dqblk_t; + +#define Q_COMP_GETQUOTA Q_V2_GETQUOTA +#define Q_COMP_SETQUOTA Q_V2_SETQUOTA +#define Q_COMP_SETQLIM Q_V2_SETQLIM +#define Q_COMP_SETUSE Q_V2_SETUSE +#endif + +asmlinkage long sys32_quotactl(int cmd, const char *special, int id, caddr_t addr) { - extern asmlinkage long sys_quotactl (int, const char *, int, caddr_t); int cmds = cmd >> SUBCMDSHIFT; + long err; + comp_dqblk_t d; mm_segment_t old_fs; - struct dqblk d; char *spec; - long err; - + switch (cmds) { - case Q_GETQUOTA: - break; - case Q_SETQUOTA: - case Q_SETUSE: - case Q_SETQLIM: - if (copy_from_user (&d, addr, sizeof(struct dqblk32))) - return -EFAULT; - d.dqb_itime = ((struct dqblk32 *)&d)->dqb_itime; - d.dqb_btime = ((struct dqblk32 *)&d)->dqb_btime; - break; - default: - return sys_quotactl(cmd, (void *) A(special), id, (caddr_t) addr); + case Q_COMP_GETQUOTA: + break; + case Q_COMP_SETQUOTA: + case Q_COMP_SETUSE: + case Q_COMP_SETQLIM: + if (copy_from_user(&d, (struct user_dqblk32 *)addr, + sizeof (struct user_dqblk32))) + return -EFAULT; + d.dqb_itime = ((struct user_dqblk32 *)&d)->dqb_itime; + d.dqb_btime = ((struct user_dqblk32 *)&d)->dqb_btime; + break; + default: + return sys_quotactl(cmd, special, id, (__kernel_caddr_t)addr); } - spec = getname32((void *) A(special)); + spec = getname (special); err = PTR_ERR(spec); - if (IS_ERR(spec)) + if (IS_ERR(spec)) return err; + old_fs = get_fs(); + set_fs (KERNEL_DS); + err = sys_quotactl(cmd, (const char *)spec, id, (__kernel_caddr_t)&d); + set_fs (old_fs); + putname (spec); + if (err) return err; - old_fs = get_fs (); - set_fs(KERNEL_DS); - err = sys_quotactl(cmd, (const char *)spec, id, (caddr_t)&d); - set_fs(old_fs); - putname(spec); - if (cmds == Q_GETQUOTA) { + if (cmds == Q_COMP_GETQUOTA) { __kernel_time_t b = d.dqb_btime, i = d.dqb_itime; - ((struct dqblk32 *)&d)->dqb_itime = i; - ((struct dqblk32 *)&d)->dqb_btime = b; - if (copy_to_user(addr, &d, sizeof(struct dqblk32))) + ((struct user_dqblk32 *)&d)->dqb_itime = i; + ((struct user_dqblk32 *)&d)->dqb_btime = b; + if (copy_to_user ((struct user_dqblk32 *)addr, &d, + sizeof (struct user_dqblk32))) return -EFAULT; } - return err; + return 0; +} + +#else +/* No conversion needed for new interface */ +asmlinkage long sys32_quotactl(int cmd, const char *special, int id, caddr_t addr) +{ + return sys_quotactl(cmd, special, id, addr); } +#endif asmlinkage long sys32_sched_rr_get_interval (pid_t pid, struct timespec32 *interval) diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/ia64/kernel/efivars.c linux.19rc3-ac4/arch/ia64/kernel/efivars.c --- linux.19rc3/arch/ia64/kernel/efivars.c 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/arch/ia64/kernel/efivars.c 2002-07-29 13:58:35.000000000 +0100 @@ -29,6 +29,9 @@ * * Changelog: * + * 25 Mar 2002 - Matt Domsch + * move uuid_unparse() to include/asm-ia64/efi.h:efi_guid_unparse() + * * 12 Feb 2002 - Matt Domsch * use list_for_each_safe when deleting vars. * remove ifdef CONFIG_SMP around include @@ -70,7 +73,7 @@ MODULE_DESCRIPTION("/proc interface to EFI Variables"); MODULE_LICENSE("GPL"); -#define EFIVARS_VERSION "0.04 2002-Feb-12" +#define EFIVARS_VERSION "0.05 2002-Mar-26" static int efivar_read(char *page, char **start, off_t off, @@ -141,20 +144,6 @@ return len; } - -static void -uuid_unparse(efi_guid_t *guid, char *out) -{ - sprintf(out, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", - guid->data1, guid->data2, guid->data3, - guid->data4[0], guid->data4[1], guid->data4[2], guid->data4[3], - guid->data4[4], guid->data4[5], guid->data4[6], guid->data4[7]); -} - - - - - /* * efivar_create_proc_entry() * Requires: @@ -197,7 +186,7 @@ private variables from another's. */ *(short_name + strlen(short_name)) = '-'; - uuid_unparse(vendor_guid, short_name + strlen(short_name)); + efi_guid_unparse(vendor_guid, short_name + strlen(short_name)); /* Create the entry in proc */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/ia64/kernel/irq.c linux.19rc3-ac4/arch/ia64/kernel/irq.c --- linux.19rc3/arch/ia64/kernel/irq.c 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/arch/ia64/kernel/irq.c 2002-07-29 13:58:35.000000000 +0100 @@ -172,7 +172,7 @@ p += sprintf(p, "LOC: "); for (j = 0; j < smp_num_cpus; j++) p += sprintf(p, "%10u ", - apic_timer_irqs[cpu_logical_map(j)]); + irq_stat[cpu_logical_map(j)].apic_timer_irqs); p += sprintf(p, "\n"); #endif p += sprintf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/ia64/kernel/mca.c linux.19rc3-ac4/arch/ia64/kernel/mca.c --- linux.19rc3/arch/ia64/kernel/mca.c 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/arch/ia64/kernel/mca.c 2002-07-29 13:58:35.000000000 +0100 @@ -3,6 +3,9 @@ * Purpose: Generic MCA handling layer * * Updated for latest kernel + * Copyright (C) 2002 Dell Computer Corporation + * Copyright (C) Matt Domsch (Matt_Domsch@dell.com) + * * Copyright (C) 2002 Intel * Copyright (C) Jenna Hall (jenna.s.hall@intel.com) * @@ -15,6 +18,8 @@ * Copyright (C) 1999 Silicon Graphics, Inc. * Copyright (C) Vijay Chander(vijay@engr.sgi.com) * + * 02/03/25 M. Domsch GUID cleanups + * * 02/01/04 J. Hall Aligned MCA stack to 16 bytes, added platform vs. CPU * error flag, set SAL default return values, changed * error record structure to linked list, added init call @@ -348,17 +353,13 @@ verify_guid (efi_guid_t *test, efi_guid_t *target) { int rc; + char out[40]; - if ((rc = memcmp((void *)test, (void *)target, sizeof(efi_guid_t)))) { - IA64_MCA_DEBUG("ia64_mca_print: invalid guid = " - "{ %08x, %04x, %04x, { %#02x, %#02x, %#02x, %#02x, " - "%#02x, %#02x, %#02x, %#02x, } } \n ", - test->data1, test->data2, test->data3, test->data4[0], - test->data4[1], test->data4[2], test->data4[3], - test->data4[4], test->data4[5], test->data4[6], - test->data4[7]); + if ((rc = efi_guidcmp(*test, *target))) { + IA64_MCA_DEBUG(KERN_DEBUG + "verify_guid: invalid GUID = %s\n", + efi_guid_unparse(test, out)); } - return rc; } @@ -856,11 +857,8 @@ void ia64_log_prt_guid (efi_guid_t *p_guid, prfunc_t prfunc) { - printk("GUID = { %08x, %04x, %04x, { %#02x, %#02x, %#02x, %#02x, " - "%#02x, %#02x, %#02x, %#02x, } } \n ", p_guid->data1, - p_guid->data2, p_guid->data3, p_guid->data4[0], p_guid->data4[1], - p_guid->data4[2], p_guid->data4[3], p_guid->data4[4], - p_guid->data4[5], p_guid->data4[6], p_guid->data4[7]); + char out[40]; + printk(KERN_DEBUG "GUID = %s\n", efi_guid_unparse(p_guid, out)); } static void @@ -1754,7 +1752,7 @@ ia64_log_prt_section_header(slsh, prfunc); #endif // MCA_PRT_XTRA_DATA for test only @FVL - if (verify_guid((void *)&slsh->guid, (void *)&(SAL_PROC_DEV_ERR_SECT_GUID))) { + if (verify_guid(&slsh->guid, &(SAL_PROC_DEV_ERR_SECT_GUID))) { IA64_MCA_DEBUG("ia64_mca_log_print: unsupported record section\n"); continue; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/ia64/kernel/perfmon.c linux.19rc3-ac4/arch/ia64/kernel/perfmon.c --- linux.19rc3/arch/ia64/kernel/perfmon.c 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/arch/ia64/kernel/perfmon.c 2002-07-29 13:58:35.000000000 +0100 @@ -387,34 +387,8 @@ return ia64_get_itc(); } -/* 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 = (unsigned long) page_address(pte_page(pte)); - ret |= (adr & (PAGE_SIZE - 1)); - } - } - } - DBprintk(("[%d] uv2kva(%lx-->%lx)\n", current->pid, 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. + * This is used when initializing the contents of the area. */ static inline unsigned long pfm_kvirt_to_pa(unsigned long adr) @@ -424,21 +398,19 @@ return pa; } - static void * pfm_rvmalloc(unsigned long size) { void *mem; - unsigned long adr, page; + unsigned long adr; + size=PAGE_ALIGN(size); mem=vmalloc(size); if (mem) { - //printk("perfmon: CPU%d pfm_rvmalloc(%ld)=%p\n", smp_processor_id(), size, mem); memset(mem, 0, size); /* Clear the ram out, no junk to the user */ adr=(unsigned long) mem; while (size > 0) { - page = pfm_kvirt_to_pa(adr); - mem_map_reserve(virt_to_page(__va(page))); + mem_map_reserve(vmalloc_to_page((void *)adr)); adr += PAGE_SIZE; size -= PAGE_SIZE; } @@ -449,13 +421,12 @@ static void pfm_rvfree(void *mem, unsigned long size) { - unsigned long adr, page = 0; + unsigned long adr; if (mem) { adr=(unsigned long) mem; - while (size > 0) { - page = pfm_kvirt_to_pa(adr); - mem_map_unreserve(virt_to_page(__va(page))); + while ((long) size > 0) { + mem_map_unreserve(vmalloc_to_page((void *)adr)); adr+=PAGE_SIZE; size-=PAGE_SIZE; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/ia64/mm/fault.c linux.19rc3-ac4/arch/ia64/mm/fault.c --- linux.19rc3/arch/ia64/mm/fault.c 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/arch/ia64/mm/fault.c 2002-07-29 17:22:23.000000000 +0100 @@ -119,8 +119,6 @@ check_expansion: if (!(prev_vma && (prev_vma->vm_flags & VM_GROWSUP) && (address == prev_vma->vm_end))) { - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; if (rgn_index(address) != rgn_index(vma->vm_start) || rgn_offset(address) >= RGN_MAP_LIMIT) goto bad_area; @@ -196,8 +194,7 @@ out_of_memory: up_read(&mm->mmap_sem); if (current->pid == 1) { - current->policy |= SCHED_YIELD; - schedule(); + yield(); down_read(&mm->mmap_sem); goto survive; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/m68k/config.in linux.19rc3-ac4/arch/m68k/config.in --- linux.19rc3/arch/m68k/config.in 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/arch/m68k/config.in 2002-07-29 13:58:35.000000000 +0100 @@ -565,3 +565,5 @@ fi endmenu + +source lib/Config.in diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/m68k/mm/fault.c linux.19rc3-ac4/arch/m68k/mm/fault.c --- linux.19rc3/arch/m68k/mm/fault.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/arch/m68k/mm/fault.c 2002-07-29 13:58:35.000000000 +0100 @@ -181,8 +181,7 @@ out_of_memory: up_read(&mm->mmap_sem); if (current->pid == 1) { - current->policy |= SCHED_YIELD; - schedule(); + yield(); down_read(&mm->mmap_sem); goto survive; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/mips/config.in linux.19rc3-ac4/arch/mips/config.in --- linux.19rc3/arch/mips/config.in 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/arch/mips/config.in 2002-07-29 15:21:52.000000000 +0100 @@ -631,4 +631,7 @@ if [ "$CONFIG_SMP" != "y" ]; then bool 'Run uncached' CONFIG_MIPS_UNCACHED fi +dep_bool 'Morse code panics' CONFIG_PANIC_MORSE $CONFIG_DEBUG $CONFIG_PC_KEYB endmenu + +source lib/Config.in diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/mips/mm/fault.c linux.19rc3-ac4/arch/mips/mm/fault.c --- linux.19rc3/arch/mips/mm/fault.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/arch/mips/mm/fault.c 2002-07-29 17:22:23.000000000 +0100 @@ -111,8 +111,6 @@ goto bad_area; if (vma->vm_start <= address) goto good_area; - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; if (expand_stack(vma, address)) goto bad_area; /* @@ -213,8 +211,7 @@ out_of_memory: up_read(&mm->mmap_sem); if (tsk->pid == 1) { - tsk->policy |= SCHED_YIELD; - schedule(); + yield(); down_read(&mm->mmap_sem); goto survive; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/mips64/config.in linux.19rc3-ac4/arch/mips64/config.in --- linux.19rc3/arch/mips64/config.in 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/arch/mips64/config.in 2002-07-29 13:58:35.000000000 +0100 @@ -336,3 +336,5 @@ bool 'Run uncached' CONFIG_MIPS_UNCACHED fi endmenu + +source lib/Config.in diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/mips64/mm/fault.c linux.19rc3-ac4/arch/mips64/mm/fault.c --- linux.19rc3/arch/mips64/mm/fault.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/arch/mips64/mm/fault.c 2002-07-29 17:22:23.000000000 +0100 @@ -135,8 +135,6 @@ goto bad_area; if (vma->vm_start <= address) goto good_area; - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; if (expand_stack(vma, address)) goto bad_area; /* @@ -238,8 +236,7 @@ out_of_memory: up_read(&mm->mmap_sem); if (tsk->pid == 1) { - tsk->policy |= SCHED_YIELD; - schedule(); + yield(); down_read(&mm->mmap_sem); goto survive; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/config.in linux.19rc3-ac4/arch/parisc/config.in --- linux.19rc3/arch/parisc/config.in 2002-07-29 12:50:07.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/config.in 2002-07-29 13:58:35.000000000 +0100 @@ -16,98 +16,106 @@ endmenu mainmenu_option next_comment +comment 'Loadable module support' +bool 'Enable loadable module support' CONFIG_MODULES +if [ "$CONFIG_MODULES" = "y" ] ; then + bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS + bool 'Kernel module loader' CONFIG_KMOD +fi +endmenu + +mainmenu_option next_comment +comment 'Processor type' +choice 'Processor family' \ + "PA7000/PA7100 CONFIG_PA7100 \ + PA7200 CONFIG_PA7200 \ + PA7100LC/PA7300LC CONFIG_PA7100LC \ + PA8x00 CONFIG_PA8X00" PA7000 + +if [ "$CONFIG_PA8X00" = "y" ] ; then + define_bool CONFIG_PA20 y + bool '64-bit kernel' CONFIG_PARISC64 + dep_bool '32-bit PDC' CONFIG_PDC_NARROW $CONFIG_PARISC64 +else + define_bool CONFIG_PA11 y +fi +endmenu + +mainmenu_option next_comment comment 'General options' -# bool 'Symmetric multi-processing support' CONFIG_SMP -define_bool CONFIG_SMP n +bool 'Symmetric multi-processing support' CONFIG_SMP +bool 'Chassis LCD and LED support' CONFIG_CHASSIS_LCD_LED bool 'Kernel Debugger support' CONFIG_KWDB # define_bool CONFIG_KWDB n -# bool 'GSC/Gecko bus support' CONFIG_GSC y -define_bool CONFIG_GSC y - -bool 'U2/Uturn I/O MMU' CONFIG_IOMMU_CCIO y -bool 'LASI I/O support' CONFIG_GSC_LASI y - -bool 'PCI bus support' CONFIG_PCI y +bool 'U2/Uturn I/O MMU' CONFIG_IOMMU_CCIO +bool 'VSC/GSC/HSC bus support' CONFIG_GSC +dep_bool ' Lasi I/O support' CONFIG_GSC_LASI $CONFIG_GSC +dep_bool ' Wax I/O support' CONFIG_GSC_WAX $CONFIG_GSC + +dep_bool 'EISA support' CONFIG_EISA $CONFIG_GSC +define_bool CONFIG_ISA $CONFIG_EISA +bool 'PCI support' CONFIG_PCI if [ "$CONFIG_PCI" = "y" ]; then - bool 'GSCtoPCI/DINO PCI support' CONFIG_GSC_DINO y - bool 'LBA/Elroy PCI support' CONFIG_PCI_LBA n -fi + dep_bool ' GSCtoPCI/Dino PCI support' CONFIG_GSC_DINO $CONFIG_GSC + bool ' LBA/Elroy PCI support' CONFIG_PCI_LBA + define_bool CONFIG_IOSAPIC $CONFIG_PCI_LBA + define_bool CONFIG_IOMMU_SBA $CONFIG_PCI_LBA -if [ "$CONFIG_PCI_LBA" = "y" ]; then - define_bool CONFIG_IOSAPIC y - define_bool CONFIG_IOMMU_SBA y -fi +# bool ' EPIC PCI support' CONFIG_PCI_EPIC n + bool ' SuperIO support' CONFIG_SUPERIO +fi -# -# if [ "$CONFIG_PCI_EPIC" = "y" ]; then... -# +source drivers/pci/Config.in endmenu mainmenu_option next_comment -comment 'Loadable module support' -bool 'Enable loadable module support' CONFIG_MODULES -if [ "$CONFIG_MODULES" = "y" ]; then - bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS - bool 'Kernel module loader' CONFIG_KMOD -fi -endmenu - -mainmenu_option next_comment comment 'General setup' +bool 'Support for hot-pluggable devices' CONFIG_HOTPLUG + bool 'Networking support' CONFIG_NET bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT bool 'Sysctl support' CONFIG_SYSCTL -tristate 'Kernel support for SOM binaries' CONFIG_BINFMT_SOM +define_bool CONFIG_KCORE_ELF y tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF +tristate 'Kernel support for SOM binaries' CONFIG_BINFMT_SOM tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC -if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate 'Kernel support for JAVA binaries (obsolete)' CONFIG_BINFMT_JAVA -fi + +# anyone want to get ACPI working on PA/RISC? +define_bool CONFIG_PM n endmenu -##source drivers/parport/Config.in -mainmenu_option next_comment -comment 'Parallel port support' +source drivers/parport/Config.in -tristate 'Parallel port support' CONFIG_PARPORT -if [ "$CONFIG_PARPORT" != "n" ]; then - if [ "$CONFIG_PCI" = "y" ]; then - dep_tristate ' PC-style hardware' CONFIG_PARPORT_PC $CONFIG_PARPORT - if [ "$CONFIG_PARPORT_PC" != "n" ]; then - bool ' Use FIFO/DMA if available' CONFIG_PARPORT_PC_FIFO - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - bool ' SuperIO chipset support (EXPERIMENTAL)' CONFIG_PARPORT_PC_SUPERIO - fi - fi - fi - if [ "$CONFIG_GSC_LASI" = "y" ]; then - dep_tristate ' LASI/ASP builtin parallel-port' CONFIG_PARPORT_GSC $CONFIG_PARPORT - else - define_tristate CONFIG_PARPORT_GSC n - fi +source drivers/block/Config.in - # If exactly one hardware type is selected then parport will optimise away - # support for loading any others. Defeat this if the user is keen. - bool ' Support foreign hardware' CONFIG_PARPORT_OTHER +source drivers/md/Config.in - bool ' IEEE 1284 transfer modes' CONFIG_PARPORT_1284 +if [ "$CONFIG_NET" = "y" ]; then + source net/Config.in fi -endmenu +if [ "$CONFIG_SUPERIO" = "y" ]; then + mainmenu_option next_comment + comment 'ATA/IDE/MFM/RLL support' -source drivers/block/Config.in + tristate 'ATA/IDE/MFM/RLL support' CONFIG_IDE -if [ "$CONFIG_NET" = "y" ]; then - source net/Config.in + if [ "$CONFIG_IDE" != "n" ]; then + source drivers/ide/Config.in + else + define_bool CONFIG_BLK_DEV_IDE_MODES n + define_bool CONFIG_BLK_DEV_HD n + fi + endmenu fi mainmenu_option next_comment @@ -116,90 +124,70 @@ tristate 'SCSI support' CONFIG_SCSI if [ "$CONFIG_SCSI" != "n" ]; then - comment 'SCSI support type (disk, tape, CDrom)' - - dep_tristate 'SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI - if [ "$CONFIG_BLK_DEV_SD" != "n" ]; then - int 'Maximum number of SCSI disks that can be loaded as modules' CONFIG_SD_EXTRA_DEVS 40 - fi - - dep_tristate 'SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI - dep_tristate 'SCSI CDROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI - if [ "$CONFIG_BLK_DEV_SR" != "n" ]; then - bool ' Enable vendor-specific extensions (for SCSI CDROM)' CONFIG_BLK_DEV_SR_VENDOR - int 'Maximum number of CDROM devices that can be loaded as modules' CONFIG_SR_EXTRA_DEVS 2 - fi - dep_tristate 'SCSI generic support' CONFIG_CHR_DEV_SG $CONFIG_SCSI - - comment 'Some SCSI devices (e.g. CD jukebox) support multiple LUNs' - bool 'Probe all LUNs on each SCSI device' CONFIG_SCSI_MULTI_LUN - bool 'Verbose SCSI error reporting (kernel size +=12K)' CONFIG_SCSI_CONSTANTS - - mainmenu_option next_comment - comment 'SCSI low-level drivers' - if [ "$CONFIG_GSC_LASI" = "y" ]; then - dep_tristate 'Lasi SCSI support' CONFIG_SCSI_LASI $CONFIG_SCSI - dep_tristate 'Zalon SCSI support' CONFIG_SCSI_ZALON $CONFIG_SCSI - fi - if [ "$CONFIG_PCI" = "y" ]; then - dep_tristate 'SYM53C8XX SCSI support' CONFIG_SCSI_SYM53C8XX $CONFIG_SCSI - fi - if [ "$CONFIG_SCSI_ZALON" != "n" -o "$CONFIG_SCSI_SYM53C8XX" != "n" ]; then - int ' default tagged command queue depth' CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS 8 - int ' maximum number of queued commands' CONFIG_SCSI_NCR53C8XX_MAX_TAGS 32 - int ' synchronous transfers frequency in MHz' CONFIG_SCSI_NCR53C8XX_SYNC 20 - bool ' enable profiling' CONFIG_SCSI_NCR53C8XX_PROFILE - bool ' use normal IO' CONFIG_SCSI_NCR53C8XX_IOMAPPED - fi - endmenu + source drivers/scsi/Config.in fi endmenu if [ "$CONFIG_NET" = "y" ]; then - mainmenu_option next_comment - comment 'Network device support' + mainmenu_option next_comment + comment 'Network device support' - bool 'Network device support' CONFIG_NETDEVICES + bool 'Network device support' CONFIG_NETDEVICES - if [ "$CONFIG_NETDEVICES" = "y" ]; then - if [ "$CONFIG_GSC_LASI" = "y" ]; then - tristate 'Lasi ethernet' CONFIG_LASI_82596 - fi - source drivers/net/Config.in - fi - endmenu + if [ "$CONFIG_NETDEVICES" = "y" ]; then + source drivers/net/Config.in + if [ "$CONFIG_ATM" = "y" ]; then + source drivers/atm/Config.in + fi + fi + endmenu fi +# +# input before char - char/joystick depends on it. As does USB. +# +source drivers/input/Config.in source drivers/char/Config.in +source drivers/hil/Config.in + +source drivers/media/Config.in source fs/Config.in +if [ "$CONFIG_VT" = "y" ]; then + mainmenu_option next_comment + comment 'Console drivers' + source drivers/video/Config.in + + bool 'STI console' CONFIG_STI_CONSOLE + if [ "$CONFIG_GSC_PS2" = "y" ]; then + define_bool CONFIG_DUMMY_CONSOLE y + fi + if [ "$CONFIG_STI_CONSOLE" = "y" ]; then + define_bool CONFIG_DUMMY_CONSOLE y + define_bool CONFIG_FBCON y + define_bool CONFIG_FBCON_FONT y +# define_bool CONFIG_FBCON_FONTWIDTH8_ONLY n + define_bool CONFIG_FONT_8x8 y + define_bool CONFIG_FONT_8x16 y + define_bool CONFIG_FONT_6x11 y + define_bool CONFIG_FONT_SUN12x22 y + fi + endmenu +fi + mainmenu_option next_comment -comment 'Sound Drivers' +comment 'Sound' + tristate 'Sound card support' CONFIG_SOUND if [ "$CONFIG_SOUND" != "n" ]; then source drivers/sound/Config.in fi endmenu -if [ "$CONFIG_VT" = "y" ]; then - mainmenu_option next_comment - comment 'Console drivers' - source drivers/video/Config.in - -# bool 'IODC console' CONFIG_IODC_CONSOLE - bool 'STI console' CONFIG_STI_CONSOLE - if [ "$CONFIG_IODC_CONSOLE" = "n" ]; then - if [ "$CONFIG_GSC_PS2" = "y" ]; then - define_bool CONFIG_DUMMY_CONSOLE y - fi - fi - if [ "$CONFIG_STI_CONSOLE" = "y" ]; then - define_bool CONFIG_DUMMY_CONSOLE y - fi - endmenu +if [ "$CONFIG_SUPERIO" = "y" ]; then + source drivers/usb/Config.in fi -# endmenu mainmenu_option next_comment comment 'Kernel hacking' @@ -208,3 +196,4 @@ bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ endmenu +source lib/Config.in diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/defconfig linux.19rc3-ac4/arch/parisc/defconfig --- linux.19rc3/arch/parisc/defconfig 2002-07-29 12:50:07.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/defconfig 2002-07-29 13:58:35.000000000 +0100 @@ -1,8 +1,10 @@ # -# Automatically generated by make menuconfig: don't edit +# Automatically generated make config: don't edit # CONFIG_PARISC=y # CONFIG_UID16 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set # # Code maturity level options @@ -10,44 +12,70 @@ CONFIG_EXPERIMENTAL=y # +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y + +# +# Processor type +# +# CONFIG_PA7100 is not set +# CONFIG_PA7200 is not set +# CONFIG_PA7100LC is not set +# CONFIG_PA8X00 is not set +# CONFIG_PA11 is not set + +# # General options # # CONFIG_SMP is not set +CONFIG_CHASSIS_LCD_LED=y # CONFIG_KWDB is not set -CONFIG_GSC=y CONFIG_IOMMU_CCIO=y +CONFIG_GSC=y CONFIG_GSC_LASI=y +CONFIG_GSC_WAX=y +CONFIG_EISA=y +CONFIG_ISA=y CONFIG_PCI=y CONFIG_GSC_DINO=y CONFIG_PCI_LBA=y CONFIG_IOSAPIC=y CONFIG_IOMMU_SBA=y - -# -# Loadable module support -# -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y +CONFIG_SUPERIO=y +CONFIG_PCI_NAMES=y # # General setup # +CONFIG_HOTPLUG=y CONFIG_NET=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y -CONFIG_BINFMT_SOM=y +CONFIG_KCORE_ELF=y CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_SOM=y # CONFIG_BINFMT_MISC is not set -# CONFIG_BINFMT_JAVA is not set +# CONFIG_PM is not set # # Parallel port support # CONFIG_PARPORT=y -# CONFIG_PARPORT_PC is not set +CONFIG_PARPORT_PC=y +CONFIG_PARPORT_PC_CML1=y +# CONFIG_PARPORT_SERIAL is not set +# CONFIG_PARPORT_PC_FIFO is not set +# CONFIG_PARPORT_PC_SUPERIO is not set +# CONFIG_PARPORT_PC_PCMCIA is not set +# CONFIG_PARPORT_AMIGA is not set +# CONFIG_PARPORT_MFC3 is not set +# CONFIG_PARPORT_ATARI is not set CONFIG_PARPORT_GSC=y +# CONFIG_PARPORT_SUNBPP is not set # CONFIG_PARPORT_OTHER is not set # CONFIG_PARPORT_1284 is not set @@ -60,33 +88,54 @@ # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_LOOP is not set +CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_NBD is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y # +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=y +CONFIG_MD_RAID0=y +CONFIG_MD_RAID1=y +CONFIG_MD_RAID5=y +# CONFIG_MD_MULTIPATH is not set +# CONFIG_BLK_DEV_LVM is not set + +# # Networking options # -# CONFIG_PACKET is not set -# CONFIG_NETLINK is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_NETLINK_DEV=y # CONFIG_NETFILTER is not set -# CONFIG_FILTER is not set +CONFIG_FILTER=y CONFIG_UNIX=y CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set +CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set # CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set # CONFIG_IPV6 is not set # CONFIG_KHTTPD is not set # CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set + +# +# +# # CONFIG_IPX is not set # CONFIG_ATALK is not set # CONFIG_DECNET is not set @@ -106,36 +155,181 @@ # CONFIG_NET_SCHED is not set # +# 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 is not set +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set +# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set +# CONFIG_BLK_DEV_IDEDISK_IBM is not set +# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set +# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set +# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set +# CONFIG_BLK_DEV_IDEDISK_WD is not set +# CONFIG_BLK_DEV_COMMERIAL is not set +# CONFIG_BLK_DEV_TIVO is not set +# CONFIG_BLK_DEV_IDECS is not set +CONFIG_BLK_DEV_IDECD=y +# 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_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 is not set +CONFIG_BLK_DEV_IDEDMA_PCI=y +CONFIG_BLK_DEV_ADMA=y +# CONFIG_BLK_DEV_OFFBOARD is not set +# CONFIG_IDEDMA_PCI_AUTO is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_PCI_WIP is not set +# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_AEC62XX_TUNING is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_WDC_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_AMD74XX_OVERRIDE is not set +# CONFIG_BLK_DEV_CMD64X is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_HPT34X_AUTODMA is not set +# CONFIG_BLK_DEV_HPT366 is not set +CONFIG_BLK_DEV_NS87415=y +# CONFIG_BLK_DEV_OPTI621 is not set +# CONFIG_BLK_DEV_PDC202XX is not set +# CONFIG_PDC202XX_BURST is not set +# CONFIG_PDC202XX_FORCE is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIS5513 is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_IDE_CHIPSETS is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_IDEDMA_IVB is not set +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_ATARAID is not set +# CONFIG_BLK_DEV_ATARAID_PDC is not set +# CONFIG_BLK_DEV_ATARAID_HPT is not set + +# # SCSI support # CONFIG_SCSI=y + +# +# SCSI support type (disk, tape, CD-ROM) +# CONFIG_BLK_DEV_SD=y CONFIG_SD_EXTRA_DEVS=40 CONFIG_CHR_DEV_ST=y +# CONFIG_CHR_DEV_OSST is not set CONFIG_BLK_DEV_SR=y # CONFIG_BLK_DEV_SR_VENDOR is not set CONFIG_SR_EXTRA_DEVS=2 CONFIG_CHR_DEV_SG=y + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_DEBUG_QUEUES is not set # CONFIG_SCSI_MULTI_LUN is not set # CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set # # SCSI low-level drivers # -CONFIG_SCSI_LASI=y -CONFIG_SCSI_ZALON=y +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_7000FASST is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AHA152X is not set +# CONFIG_SCSI_AHA1542 is not set +# CONFIG_SCSI_AHA1740 is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_IN2000 is not set +# CONFIG_SCSI_AM53C974 is not set +# CONFIG_SCSI_MEGARAID is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_CPQFCTS is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_EATA_DMA is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_PPA is not set +# CONFIG_SCSI_IMM is not set +# CONFIG_SCSI_NCR53C406A is not set +CONFIG_SCSI_LASI700=y +CONFIG_53C700_MEM_MAPPED=y +CONFIG_53C700_LE_ON_BE=y +CONFIG_53C700_USE_CONSISTENT=y +# CONFIG_SCSI_NCR53C7xx is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_NCR53C8XX is not set CONFIG_SCSI_SYM53C8XX=y +CONFIG_SCSI_ZALON=y CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 CONFIG_SCSI_NCR53C8XX_SYNC=20 # CONFIG_SCSI_NCR53C8XX_PROFILE is not set # CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set +# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set +# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_PCI2000 is not set +# CONFIG_SCSI_PCI2220I is not set +# CONFIG_SCSI_PSI240I is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +# CONFIG_SCSI_QLOGIC_ISP is not set +# CONFIG_SCSI_QLOGIC_FC is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_SIM710 is not set +# CONFIG_SCSI_SYM53C416 is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_T128 is not set +# CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_DEBUG is not set + +# +# PCMCIA SCSI adapter support +# +# CONFIG_SCSI_PCMCIA is not set # # Network device support # CONFIG_NETDEVICES=y -CONFIG_LASI_82596=y # # ARCnet devices @@ -145,12 +339,18 @@ # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set -# CONFIG_NET_SB1000 is not set +# CONFIG_ETHERTAP is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y +CONFIG_LASI_82596=y +# CONFIG_SUNLANCE is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +# CONFIG_SUNGEM is not set # CONFIG_NET_VENDOR_3COM is not set # CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set @@ -165,23 +365,31 @@ # CONFIG_AC3200 is not set # CONFIG_APRICOT is not set # CONFIG_CS89x0 is not set -# CONFIG_DE4X5 is not set CONFIG_TULIP=y +# CONFIG_TULIP_MWI is not set +# CONFIG_TULIP_MMIO is not set +# CONFIG_DE4X5 is not set # CONFIG_DGRS is not set # CONFIG_DM9102 is not set # CONFIG_EEPRO100 is not set # CONFIG_LNE390 is not set +# CONFIG_FEALNX is not set # CONFIG_NATSEMI is not set # CONFIG_NE2K_PCI is not set # CONFIG_NE3210 is not set # CONFIG_ES3210 is not set -# CONFIG_RTL8129 is not set +# CONFIG_8139CP is not set # CONFIG_8139TOO is not set +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +# CONFIG_8139TOO_8129 is not set +# CONFIG_8139_NEW_RX_RESET is not set # CONFIG_SIS900 is not set # CONFIG_EPIC100 is not set # CONFIG_SUNDANCE is not set # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set +# CONFIG_VIA_RHINE_MMIO is not set # CONFIG_WINBOND_840 is not set # CONFIG_NET_POCKET is not set @@ -189,6 +397,9 @@ # Ethernet (1000 Mbit) # # CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_SK98LIN is not set @@ -217,12 +428,27 @@ # CONFIG_WAN is not set # +# PCMCIA network device support +# +# CONFIG_NET_PCMCIA is not set + +# +# Input core support +# +CONFIG_INPUT=y +CONFIG_INPUT_KEYBDEV=y +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y + +# # Character devices # CONFIG_VT=y CONFIG_VT_CONSOLE=y CONFIG_GSC_PS2=y -CONFIG_HIL=y CONFIG_SERIAL=y CONFIG_SERIAL_CONSOLE=y CONFIG_SERIAL_GSC=y @@ -243,12 +469,45 @@ # Mice # # CONFIG_BUSMOUSE is not set -# CONFIG_MOUSE is not set +CONFIG_MOUSE=y +CONFIG_PSMOUSE=y +# CONFIG_82C710_MOUSE is not set +# CONFIG_PC110_PAD is not set + +# +# Joysticks +# +# CONFIG_INPUT_GAMEPORT is not set +# CONFIG_INPUT_NS558 is not set +# CONFIG_INPUT_LIGHTNING is not set +# CONFIG_INPUT_PCIGAME is not set +# CONFIG_INPUT_CS461X is not set +# CONFIG_INPUT_EMU10K1 is not set +CONFIG_INPUT_SERIO=y +# CONFIG_INPUT_SERPORT is not set # # Joysticks # -# CONFIG_JOYSTICK is not set +# CONFIG_INPUT_ANALOG is not set +# CONFIG_INPUT_A3D is not set +# CONFIG_INPUT_ADI is not set +# CONFIG_INPUT_COBRA is not set +# CONFIG_INPUT_GF2K is not set +# CONFIG_INPUT_GRIP is not set +# CONFIG_INPUT_INTERACT is not set +# CONFIG_INPUT_TMDC is not set +# CONFIG_INPUT_SIDEWINDER is not set +# CONFIG_INPUT_IFORCE_USB is not set +# CONFIG_INPUT_IFORCE_232 is not set +# CONFIG_INPUT_WARRIOR is not set +# CONFIG_INPUT_MAGELLAN is not set +# CONFIG_INPUT_SPACEORB is not set +# CONFIG_INPUT_SPACEBALL is not set +# CONFIG_INPUT_STINGER is not set +# CONFIG_INPUT_DB9 is not set +# CONFIG_INPUT_GAMECON is not set +# CONFIG_INPUT_TURBOGRAFX is not set # CONFIG_QIC02_TAPE is not set # @@ -271,27 +530,67 @@ # CONFIG_DRM is not set # +# PCMCIA character devices +# +# CONFIG_PCMCIA_SERIAL_CS is not set + +# +# HIL support +# +CONFIG_HIL=y +# CONFIG_HIL_KBD_BASIC is not set + +# +# HIL driver core support +# +CONFIG_HP_SDC=y +# CONFIG_HP_SDC_RTC is not set +CONFIG_HIL_MLC=y +CONFIG_HP_SDC_MLC=y + +# +# HIL device driver +# +CONFIG_HIL_KBD=y +CONFIG_HIL_PTR=y + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# # File systems # # CONFIG_QUOTA is not set # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set # CONFIG_ADFS_FS is not set # CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_BFS_FS is not set +CONFIG_EXT3_FS=y +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set # CONFIG_FAT_FS is not set # CONFIG_MSDOS_FS is not set # CONFIG_UMSDOS_FS is not set # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set # CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set # CONFIG_CRAMFS is not set +# CONFIG_TMPFS is not set # CONFIG_RAMFS is not set CONFIG_ISO9660_FS=y -# CONFIG_JOLIET is not set +CONFIG_JOLIET=y +# CONFIG_ZISOFS is not set # CONFIG_MINIX_FS is not set +# CONFIG_VXFS_FS is not set # CONFIG_NTFS_FS is not set # CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set @@ -299,13 +598,12 @@ # CONFIG_DEVFS_FS is not set # CONFIG_DEVFS_MOUNT is not set # CONFIG_DEVFS_DEBUG is not set -# CONFIG_DEVPTS_FS is not set +CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set # CONFIG_QNX4FS_RW is not set # CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_SYSV_FS_WRITE is not set # CONFIG_UDF_FS is not set # CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set @@ -315,13 +613,15 @@ # Network File Systems # # CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set +CONFIG_NFS_V3=y CONFIG_ROOT_NFS=y -# CONFIG_NFSD is not set -# CONFIG_NFSD_V3 is not set +CONFIG_NFSD=y +CONFIG_NFSD_V3=y CONFIG_SUNRPC=y CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y # CONFIG_SMB_FS is not set # CONFIG_NCP_FS is not set # CONFIG_NCPFS_PACKET_SIGNING is not set @@ -330,22 +630,60 @@ # 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 +# CONFIG_ZISOFS_FS is not set +# CONFIG_ZLIB_FS_INFLATE is not set # # Partition Types # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y -# CONFIG_NLS is not set +# CONFIG_SMB_NLS is not set +CONFIG_NLS=y # -# Sound Drivers +# Native Language Support # -# CONFIG_SOUND is not set +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set # # Console drivers @@ -354,8 +692,171 @@ # # Frame-buffer support # -# CONFIG_FB is not set -# CONFIG_STI_CONSOLE is not set +CONFIG_FB=y +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FB_RIVA is not set +# CONFIG_FB_CLGEN is not set +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +CONFIG_FB_STI=y +# CONFIG_FB_MATROX is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_RADEON is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FBCON_ADVANCED is not set +CONFIG_FBCON_CFB8=y +CONFIG_FBCON_CFB32=y +CONFIG_FBCON_STI=y +# CONFIG_FBCON_FONTWIDTH8_ONLY is not set +# CONFIG_FBCON_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +CONFIG_STI_CONSOLE=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_FBCON=y +CONFIG_FBCON_FONT=y +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +CONFIG_FONT_6x11=y +CONFIG_FONT_SUN12x22=y + +# +# Sound +# +CONFIG_SOUND=y +# CONFIG_SOUND_BT878 is not set +# CONFIG_SOUND_CMPCI is not set +# CONFIG_SOUND_EMU10K1 is not set +# CONFIG_MIDI_EMU10K1 is not set +# CONFIG_SOUND_FUSION is not set +# CONFIG_SOUND_CS4281 is not set +# CONFIG_SOUND_ES1370 is not set +# CONFIG_SOUND_ES1371 is not set +# CONFIG_SOUND_ESSSOLO1 is not set +# CONFIG_SOUND_MAESTRO is not set +# CONFIG_SOUND_MAESTRO3 is not set +# CONFIG_SOUND_ICH is not set +CONFIG_SOUND_HARMONY=y +# CONFIG_SOUND_RME96XX is not set +# CONFIG_SOUND_SONICVIBES is not set +# CONFIG_SOUND_TRIDENT is not set +# CONFIG_SOUND_MSNDCLAS is not set +# CONFIG_SOUND_MSNDPIN is not set +# CONFIG_SOUND_VIA82CXXX is not set +# CONFIG_MIDI_VIA82CXXX is not set +# CONFIG_SOUND_OSS is not set +# CONFIG_SOUND_TVMIXER is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Controllers +# +# CONFIG_USB_UHCI is not set +# CONFIG_USB_UHCI_ALT is not set +# CONFIG_USB_OHCI is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_BLUETOOTH is not set +# CONFIG_USB_STORAGE is not set +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_HP8200e is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# USB Human Interface Devices (HID) +# +# CONFIG_USB_HID is not set +# CONFIG_USB_HIDDEV is not set +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_WACOM is not set + +# +# USB Imaging devices +# +# CONFIG_USB_DC2XX is not set +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_SCANNER is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_HPUSBSCSI is not set + +# +# USB Multimedia devices +# + +# +# Video4Linux support is needed for USB Multimedia device support +# + +# +# USB Network adaptors +# +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_CATC is not set +# CONFIG_USB_CDCETHER is not set +# CONFIG_USB_USBNET is not set + +# +# USB port drivers +# +# CONFIG_USB_USS720 is not set + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set +# CONFIG_USB_SERIAL_GENERIC is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_IPAQ is not set +# CONFIG_USB_SERIAL_IR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_KLSI is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_XIRCOM is not set +# CONFIG_USB_SERIAL_OMNINET is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_RIO500 is not set # # Kernel hacking diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/hpux/entry_hpux.S linux.19rc3-ac4/arch/parisc/hpux/entry_hpux.S --- linux.19rc3/arch/parisc/hpux/entry_hpux.S 2002-07-29 12:50:07.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/hpux/entry_hpux.S 2002-07-29 13:58:35.000000000 +0100 @@ -1,6 +1,6 @@ -/* ----------------------------------------------------------------------------- +/* * - * Native PARISC/Linux Project (http://www.puffingroup.com/parisc) + * Linux/PARISC Project (http://www.parisc-linux.org/) * * modified by Matthew Wilcox 1999-07-26 */ @@ -10,13 +10,13 @@ #include #include - .text #define ENTRY_NAME(_name_) .word _name_ .align 4 .export hpux_call_table + .import hpux_unimplemented_wrapper hpux_call_table: ENTRY_NAME(sys_ni_syscall) /* 0 */ ENTRY_NAME(sys_exit) @@ -36,7 +36,7 @@ ENTRY_NAME(sys_chmod) /* 15 */ ENTRY_NAME(sys_chown) ENTRY_NAME(hpux_brk) - ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(hpux_unimplemented_wrapper) ENTRY_NAME(sys_lseek) ENTRY_NAME(sys_getpid) /* 20 */ ENTRY_NAME(hpux_mount) @@ -46,34 +46,34 @@ ENTRY_NAME(sys_stime) /* 25 */ ENTRY_NAME(hpux_ptrace) ENTRY_NAME(sys_alarm) - ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(hpux_unimplemented_wrapper) ENTRY_NAME(sys_pause) ENTRY_NAME(sys_utime) /* 30 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) ENTRY_NAME(sys_access) ENTRY_NAME(hpux_nice) - ENTRY_NAME(sys_ni_syscall) /* 35 */ + ENTRY_NAME(hpux_unimplemented_wrapper) /* 35 */ ENTRY_NAME(sys_sync) - ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(hpux_unimplemented_wrapper) ENTRY_NAME(sys_newstat) - ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(hpux_setpgrp3) ENTRY_NAME(sys_newlstat) /* 40 */ ENTRY_NAME(sys_dup) ENTRY_NAME(hpux_pipe_wrapper) ENTRY_NAME(sys_times) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 45 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 45 */ ENTRY_NAME(sys_setgid) ENTRY_NAME(sys_getgid) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 50 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 50 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) ENTRY_NAME(hpux_ioctl) - ENTRY_NAME(sys_ni_syscall) /* 55 */ + ENTRY_NAME(hpux_unimplemented_wrapper) /* 55 */ ENTRY_NAME(sys_symlink) ENTRY_NAME(hpux_utssys) ENTRY_NAME(sys_readlink) @@ -81,218 +81,218 @@ ENTRY_NAME(sys_umask) /* 60 */ ENTRY_NAME(sys_chroot) ENTRY_NAME(sys_fcntl) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 65 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 65 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) ENTRY_NAME(hpux_sbrk) - ENTRY_NAME(sys_ni_syscall) /* 70 */ + ENTRY_NAME(hpux_unimplemented_wrapper) /* 70 */ ENTRY_NAME(sys_mmap) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 75 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 80 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 75 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 80 */ ENTRY_NAME(sys_getpgid) ENTRY_NAME(sys_setpgid) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 85 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_setitimer) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 85 */ + ENTRY_NAME(sys_getitimer) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) ENTRY_NAME(sys_dup2) /* 90 */ - ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(hpux_unimplemented_wrapper) ENTRY_NAME(sys_newfstat) ENTRY_NAME(sys_select) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 95 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 100 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 105 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 110 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 115 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 95 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 100 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 105 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 110 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 115 */ ENTRY_NAME(sys_gettimeofday) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 120 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 120 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) ENTRY_NAME(sys_fchown) ENTRY_NAME(sys_fchmod) - ENTRY_NAME(sys_ni_syscall) /* 125 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 125 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) ENTRY_NAME(sys_rename) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 130 */ - ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 130 */ + ENTRY_NAME(hpux_unimplemented_wrapper) ENTRY_NAME(hpux_sysconf) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 135 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 135 */ ENTRY_NAME(sys_mkdir) ENTRY_NAME(sys_rmdir) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 140 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 145 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 150 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 155 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 160 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 165 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 170 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 175 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 180 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 185 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 190 */ - ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 140 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(sys_getrlimit) + ENTRY_NAME(sys_setrlimit) /* 145 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 150 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_lockf) /* 155 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 160 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 165 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 170 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 175 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 180 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(sys_sigprocmask) /* 185 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 190 */ + ENTRY_NAME(hpux_unimplemented_wrapper) ENTRY_NAME(hpux_getdomainname) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 195 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 195 */ + ENTRY_NAME(hpux_statfs) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) ENTRY_NAME(sys_waitpid) /* 200 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 205 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 210 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 215 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 220 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 225 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 230 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 235 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 240 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 245 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 250 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 255 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 260 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 265 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 270 */ - ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 205 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 210 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 215 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 220 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 225 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 230 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 235 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 240 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 245 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 250 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 255 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 260 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 265 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 270 */ + ENTRY_NAME(hpux_unimplemented_wrapper) ENTRY_NAME(sys_fchdir) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) ENTRY_NAME(sys_accept) /* 275 */ ENTRY_NAME(sys_bind) ENTRY_NAME(sys_connect) @@ -309,227 +309,227 @@ ENTRY_NAME(sys_setsockopt) ENTRY_NAME(sys_shutdown) ENTRY_NAME(sys_socket) /* 290 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 295 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 300 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 305 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 310 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 315 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 320 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 325 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 330 */ - ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 295 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 300 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 305 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 310 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 315 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 320 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 325 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 330 */ + ENTRY_NAME(hpux_unimplemented_wrapper) ENTRY_NAME(sys_lchown) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 335 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 340 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 345 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 350 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_sysfs) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 335 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 340 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 345 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 350 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) ENTRY_NAME(sys_nanosleep) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 355 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 355 */ ENTRY_NAME(hpux_getdents) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 360 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 360 */ ENTRY_NAME(hpux_fstat64) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 365 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 365 */ ENTRY_NAME(hpux_lstat64) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) ENTRY_NAME(hpux_stat64) - ENTRY_NAME(sys_ni_syscall) /* 370 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 375 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 380 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 385 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 390 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 395 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 400 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 405 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 410 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 415 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 420 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 425 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 430 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 435 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 440 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 445 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 450 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 455 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 460 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 465 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 470 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 475 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 480 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 485 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 490 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 495 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 500 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 505 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) /* 510 */ - ENTRY_NAME(sys_ni_syscall) - ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 370 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 375 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 380 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_setpgrp) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 385 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 390 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 395 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 400 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 405 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 410 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 415 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 420 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 425 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 430 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 435 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 440 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 445 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 450 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 455 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 460 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 465 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 470 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 475 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 480 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 485 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 490 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 495 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 500 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 505 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) /* 510 */ + ENTRY_NAME(hpux_unimplemented_wrapper) + ENTRY_NAME(hpux_unimplemented_wrapper) .end diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/hpux/fs.c linux.19rc3-ac4/arch/parisc/hpux/fs.c --- linux.19rc3/arch/parisc/hpux/fs.c 2002-07-29 12:50:07.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/hpux/fs.c 2002-07-29 13:58:35.000000000 +0100 @@ -52,7 +52,8 @@ #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de))) #define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1)) -static int filldir(void * __buf, const char * name, int namlen, loff_t offset, ino_t ino) +static int filldir(void * __buf, const char * name, int namlen, loff_t offset, + ino_t ino, unsigned int d_type) { struct hpux_dirent * dirent; struct getdents_callback * buf = (struct getdents_callback *) __buf; @@ -83,42 +84,21 @@ int hpux_getdents(unsigned int fd, struct hpux_dirent *dirent, unsigned int count) { struct file * file; - struct dentry * dentry; - struct inode * inode; struct hpux_dirent * lastdirent; struct getdents_callback buf; int error; - lock_kernel(); error = -EBADF; file = fget(fd); if (!file) goto out; - dentry = file->f_dentry; - if (!dentry) - goto out_putf; - - inode = dentry->d_inode; - if (!inode) - goto out_putf; - buf.current_dir = dirent; buf.previous = NULL; buf.count = count; buf.error = 0; - error = -ENOTDIR; - if (!file->f_op || !file->f_op->readdir) - goto out_putf; - - /* - * Get the inode's semaphore to prevent changes - * to the directory while we read it. - */ - down(&inode->i_sem); - error = file->f_op->readdir(file, &buf, filldir); - up(&inode->i_sem); + error = vfs_readdir(file, filldir, &buf); if (error < 0) goto out_putf; error = buf.error; @@ -131,7 +111,6 @@ out_putf: fput(file); out: - unlock_kernel(); return error; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/hpux/gate.S linux.19rc3-ac4/arch/parisc/hpux/gate.S --- linux.19rc3/arch/parisc/hpux/gate.S 2002-07-29 12:50:07.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/hpux/gate.S 2002-07-29 13:58:35.000000000 +0100 @@ -1,6 +1,6 @@ -/* ------------------------------------------------------------------------------ +/* * - * Linux/PARISC Project (http://www.thepuffingroup.com/parisc) + * Linux/PARISC Project (http://www.parisc-linux.org/) * * System call entry code Copyright (c) Matthew Wilcox 1999 * Licensed under the GNU GPL. @@ -8,14 +8,23 @@ * sorry about the wall, puffin.. */ -#define __ASSEMBLY__ #include #include #include #include +#ifdef __LP64__ + .level 2.0w +#else + .level 1.1 +#endif .text +#ifdef __LP64__ +#define FRAME_SIZE 128 +#else +#define FRAME_SIZE 64 +#endif .import hpux_call_table .import hpux_syscall_exit,code .export hpux_gateway_page @@ -23,35 +32,70 @@ .align 4096 hpux_gateway_page: nop - mfsp %sr7,%r1 ;! we must set sr3 to the space - mtsp %r1,%sr3 ;! of the user before the gate #ifdef __LP64__ #warning NEEDS WORK for 64-bit #endif - ldw -64(%r30), %r28 ;! 8th argument + ldw -64(%r30), %r29 ;! 8th argument ldw -60(%r30), %r19 ;! 7th argument ldw -56(%r30), %r20 ;! 6th argument ldw -52(%r30), %r21 ;! 5th argument - gate .+8, %r0 ;! become privileged - mtsp %r0,%sr4 ;! get kernel space into sr4 - mtsp %r0,%sr5 ;! get kernel space into sr5 - mtsp %r0,%sr6 ;! get kernel space into sr6 - mtsp %r0,%sr7 ;! get kernel space into sr7 - mfctl %cr30,%r1 ;! get the kernel task ptr - mtctl %r0,%cr30 ;! zero it (flag) - STREG %r30,TASK_PT_GR30(%r1) ;! preserve userspace sp - STREG %r2,TASK_PT_GR2(%r1) ;! preserve rp - STREG %r27,TASK_PT_GR27(%r1) ;! user dp - STREG %r31,TASK_PT_GR31(%r1) ;! preserve syscall return ptr + gate .+8, %r0 /* become privileged */ + mtsp %r0,%sr4 /* get kernel space into sr4 */ + mtsp %r0,%sr5 /* get kernel space into sr5 */ + mtsp %r0,%sr6 /* get kernel space into sr6 */ + mfsp %sr7,%r1 /* save user sr7 */ + mtsp %r1,%sr3 /* and store it in sr3 */ + + mtctl %r30,%cr28 + mfctl %cr30,%r1 + xor %r1,%r30,%r30 /* ye olde xor trick */ + xor %r1,%r30,%r1 + xor %r1,%r30,%r30 + ldo TASK_SZ_ALGN+FRAME_SIZE(%r30),%r30 /* set up kernel stack */ + + /* N.B.: It is critical that we don't set sr7 to 0 until r30 + * contains a valid kernel stack pointer. It is also + * critical that we don't start using the kernel stack + * until after sr7 has been set to 0. + */ + + mtsp %r0,%sr7 /* get kernel space into sr7 */ + STREG %r1,TASK_PT_GR30-TASK_SZ_ALGN-FRAME_SIZE(%r30) /* save usp */ + ldo -TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr in %r1 */ + + /* Save some registers for sigcontext and potential task + switch (see entry.S for the details of which ones are + saved/restored). TASK_PT_PSW is zeroed so we can see whether + a process is on a syscall or not. For an interrupt the real + PSW value is stored. This is needed for gdb and sys_ptrace. */ + STREG %r0, TASK_PT_PSW(%r1) + STREG %r2, TASK_PT_GR2(%r1) /* preserve rp */ + STREG %r19, TASK_PT_GR19(%r1) /* 7th argument */ + STREG %r20, TASK_PT_GR20(%r1) /* 6th argument */ + STREG %r21, TASK_PT_GR21(%r1) /* 5th argument */ + STREG %r22, TASK_PT_GR22(%r1) /* syscall # */ + STREG %r23, TASK_PT_GR23(%r1) /* 4th argument */ + STREG %r24, TASK_PT_GR24(%r1) /* 3rd argument */ + STREG %r25, TASK_PT_GR25(%r1) /* 2nd argument */ + STREG %r26, TASK_PT_GR26(%r1) /* 1st argument */ + STREG %r27, TASK_PT_GR27(%r1) /* user dp */ + STREG %r28, TASK_PT_GR28(%r1) /* return value 0 */ + STREG %r28, TASK_PT_ORIG_R28(%r1) /* return value 0 (saved for signals) */ + STREG %r29, TASK_PT_GR29(%r1) /* 8th argument */ + STREG %r31, TASK_PT_GR31(%r1) /* preserve syscall return ptr */ + + ldo TASK_PT_FR0(%r1), %r27 /* save fpregs from the kernel */ + save_fp %r27 /* or potential task switch */ - loadgp ;! setup kernel dp + mfctl %cr11, %r27 /* i.e. SAR */ + STREG %r27, TASK_PT_SAR(%r1) - ldo TASK_SZ_ALGN+64(%r1),%r30 ;! set up kernel stack + loadgp stw %r21, -52(%r30) ;! 5th argument stw %r20, -56(%r30) ;! 6th argument stw %r19, -60(%r30) ;! 7th argument - stw %r28, -64(%r30) ;! 8th argument + stw %r29, -64(%r30) ;! 8th argument ldil L%hpux_call_table, %r21 ldo R%hpux_call_table(%r21), %r21 diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/hpux/ioctl.c linux.19rc3-ac4/arch/parisc/hpux/ioctl.c --- linux.19rc3/arch/parisc/hpux/ioctl.c 2002-07-29 12:50:07.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/hpux/ioctl.c 2002-07-29 13:58:35.000000000 +0100 @@ -19,6 +19,7 @@ * TIOCSPGRP */ +#include #include #include #include @@ -54,10 +55,6 @@ case 't': result = hpux_ioctl_t(fd, cmd, arg); break; - default: - /* If my mother ever sees this, I hope she disowns me. - * Take this out after NYLWE. */ - result = sys_ioctl(fd, cmd, arg); } return result; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/hpux/Makefile linux.19rc3-ac4/arch/parisc/hpux/Makefile --- linux.19rc3/arch/parisc/hpux/Makefile 2002-07-29 12:50:07.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/hpux/Makefile 2002-07-29 13:58:35.000000000 +0100 @@ -7,10 +7,7 @@ # # Note 2! The CFLAGS definitions are now in the main makefile... -all: hpux.o O_TARGET = hpux.o -O_OBJS = entry_hpux.o gate.o wrappers.o fs.o ioctl.o sys_hpux.o - -.o.S: $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $*.S -o $*.o +obj-y := entry_hpux.o gate.o wrappers.o fs.o ioctl.o sys_hpux.o include $(TOPDIR)/Rules.make diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/hpux/sys_hpux.c linux.19rc3-ac4/arch/parisc/hpux/sys_hpux.c --- linux.19rc3/arch/parisc/hpux/sys_hpux.c 2002-07-29 12:50:07.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/hpux/sys_hpux.c 2002-07-29 13:58:35.000000000 +0100 @@ -9,6 +9,9 @@ #include #include #include +#include +#include +#include unsigned long sys_brk(unsigned long addr); @@ -41,6 +44,17 @@ return sys_waitpid(-1, stat_loc, 0); } +int hpux_setpgrp(void) +{ + extern int sys_setpgid(int, int); + return sys_setpgid(0,0); +} + +int hpux_setpgrp3(void) +{ + return hpux_setpgrp(); +} + #define _SC_CPU_VERSION 10001 #define _SC_OPEN_MAX 4 #define CPU_PA_RISC1_1 0x210 @@ -129,6 +143,66 @@ return err; } +/* + * Wrapper for hpux statfs call. At the moment, just calls the linux native one + * and ignores the extra fields at the end of the hpux statfs struct. + * + */ + +typedef int32_t hpux_fsid_t[2]; /* file system ID type */ +typedef uint16_t hpux_site_t; + +struct hpux_statfs { + int32_t f_type; /* type of info, zero for now */ + int32_t f_bsize; /* fundamental file system block size */ + int32_t f_blocks; /* total blocks in file system */ + int32_t f_bfree; /* free block in fs */ + int32_t f_bavail; /* free blocks avail to non-superuser */ + int32_t f_files; /* total file nodes in file system */ + int32_t f_ffree; /* free file nodes in fs */ + hpux_fsid_t f_fsid; /* file system ID */ + int32_t f_magic; /* file system magic number */ + int32_t f_featurebits; /* file system features */ + int32_t f_spare[4]; /* spare for later */ + hpux_site_t f_cnode; /* cluster node where mounted */ + int16_t f_pad; +}; + +/* hpux statfs */ +int hpux_statfs(const char *path, struct hpux_statfs *buf) +{ + int error; + int len; + char *kpath; + + len = strlen_user((char *)path); + + kpath = (char *) kmalloc(len+1, GFP_KERNEL); + if ( !kpath ) { + printk(KERN_DEBUG "failed to kmalloc kpath\n"); + return 0; + } + + if ( copy_from_user(kpath, (char *)path, len+1) ) { + printk(KERN_DEBUG "failed to copy_from_user kpath\n"); + kfree(kpath); + return 0; + } + + printk(KERN_DEBUG "hpux_statfs(\"%s\",-)\n", kpath); + + kfree(kpath); + + /* just fake it, beginning of structures match */ + extern int sys_statfs(const char *, struct statfs *); + error = sys_statfs(path, (struct statfs *) buf); + + /* ignoring rest of statfs struct, but it should be zeros. Need to do + something with f_fsid[1], which is the fstype for sysfs */ + + return error; +} + /* This function is called from hpux_utssys(); HP-UX implements * uname() as an option to utssys(). @@ -333,3 +407,541 @@ unlock_kernel(); return error; } + +/* lies - says it works, but it really didn't lock anything */ +int hpux_lockf(int fildes, int function, off_t size) +{ + return 0; +} + +int hpux_sysfs(int opcode, unsigned long arg1, unsigned long arg2) +{ + char *fsname = NULL; + int len = 0; + int fstype; + +/*Unimplemented HP-UX syscall emulation. Syscall #334 (sysfs) + Args: 1 80057bf4 0 400179f0 0 0 0 */ + printk(KERN_DEBUG "in hpux_sysfs\n"); + printk(KERN_DEBUG "hpux_sysfs called with opcode = %d\n", opcode); + printk(KERN_DEBUG "hpux_sysfs called with arg1='%lx'\n", arg1); + + if ( opcode == 1 ) { /* GETFSIND */ + len = strlen_user((char *)arg1); + printk(KERN_DEBUG "len of arg1 = %d\n", len); + + fsname = (char *) kmalloc(len+1, GFP_KERNEL); + if ( !fsname ) { + printk(KERN_DEBUG "failed to kmalloc fsname\n"); + return 0; + } + + if ( copy_from_user(fsname, (char *)arg1, len+1) ) { + printk(KERN_DEBUG "failed to copy_from_user fsname\n"); + kfree(fsname); + return 0; + } + + printk(KERN_DEBUG "that is '%s' as (char *)\n", fsname); + if ( !strcmp(fsname, "hfs") ) { + fstype = 0; + } else { + fstype = 0; + }; + + kfree(fsname); + + printk(KERN_DEBUG "returning fstype=%d\n", fstype); + return fstype; /* something other than default */ + } + + + return 0; +} + + +/* Table of syscall names and handle for unimplemented routines */ +static const char *syscall_names[] = { + "nosys", /* 0 */ + "exit", + "fork", + "read", + "write", + "open", /* 5 */ + "close", + "wait", + "creat", + "link", + "unlink", /* 10 */ + "execv", + "chdir", + "time", + "mknod", + "chmod", /* 15 */ + "chown", + "brk", + "lchmod", + "lseek", + "getpid", /* 20 */ + "mount", + "umount", + "setuid", + "getuid", + "stime", /* 25 */ + "ptrace", + "alarm", + NULL, + "pause", + "utime", /* 30 */ + "stty", + "gtty", + "access", + "nice", + "ftime", /* 35 */ + "sync", + "kill", + "stat", + "setpgrp3", + "lstat", /* 40 */ + "dup", + "pipe", + "times", + "profil", + "ki_call", /* 45 */ + "setgid", + "getgid", + NULL, + NULL, + NULL, /* 50 */ + "acct", + "set_userthreadid", + NULL, + "ioctl", + "reboot", /* 55 */ + "symlink", + "utssys", + "readlink", + "execve", + "umask", /* 60 */ + "chroot", + "fcntl", + "ulimit", + NULL, + NULL, /* 65 */ + "vfork", + NULL, + NULL, + NULL, + NULL, /* 70 */ + "mmap", + NULL, + "munmap", + "mprotect", + "madvise", /* 75 */ + "vhangup", + "swapoff", + NULL, + "getgroups", + "setgroups", /* 80 */ + "getpgrp2", + "setpgid/setpgrp2", + "setitimer", + "wait3", + "swapon", /* 85 */ + "getitimer", + NULL, + NULL, + NULL, + "dup2", /* 90 */ + NULL, + "fstat", + "select", + NULL, + "fsync", /* 95 */ + "setpriority", + NULL, + NULL, + NULL, + "getpriority", /* 100 */ + NULL, + NULL, + NULL, + NULL, + NULL, /* 105 */ + NULL, + NULL, + "sigvector", + "sigblock", + "sigsetmask", /* 110 */ + "sigpause", + "sigstack", + NULL, + NULL, + NULL, /* 115 */ + "gettimeofday", + "getrusage", + NULL, + NULL, + "readv", /* 120 */ + "writev", + "settimeofday", + "fchown", + "fchmod", + NULL, /* 125 */ + "setresuid", + "setresgid", + "rename", + "truncate", + "ftruncate", /* 130 */ + NULL, + "sysconf", + NULL, + NULL, + NULL, /* 135 */ + "mkdir", + "rmdir", + NULL, + "sigcleanup", + "setcore", /* 140 */ + NULL, + "gethostid", + "sethostid", + "getrlimit", + "setrlimit", /* 145 */ + NULL, + NULL, + "quotactl", + "get_sysinfo", + NULL, /* 150 */ + "privgrp", + "rtprio", + "plock", + NULL, + "lockf", /* 155 */ + "semget", + NULL, + "semop", + "msgget", + NULL, /* 160 */ + "msgsnd", + "msgrcv", + "shmget", + NULL, + "shmat", /* 165 */ + "shmdt", + NULL, + "csp/nsp_init", + "cluster", + "mkrnod", /* 170 */ + "test", + "unsp_open", + NULL, + "getcontext", + "osetcontext", /* 175 */ + "bigio", + "pipenode", + "lsync", + "getmachineid", + "cnodeid/mysite", /* 180 */ + "cnodes/sitels", + "swapclients", + "rmtprocess", + "dskless_stats", + "sigprocmask", /* 185 */ + "sigpending", + "sigsuspend", + "sigaction", + NULL, + "nfssvc", /* 190 */ + "getfh", + "getdomainname", + "setdomainname", + "async_daemon", + "getdirentries", /* 195 */ + "statfs", + "fstatfs", + "vfsmount", + NULL, + "waitpid", /* 200 */ + NULL, + NULL, + NULL, + NULL, + NULL, /* 205 */ + NULL, + NULL, + NULL, + NULL, + NULL, /* 210 */ + NULL, + NULL, + NULL, + NULL, + NULL, /* 215 */ + NULL, + NULL, + NULL, + NULL, + NULL, /* 220 */ + NULL, + NULL, + NULL, + "sigsetreturn", + "sigsetstatemask", /* 225 */ + "bfactl", + "cs", + "cds", + NULL, + "pathconf", /* 230 */ + "fpathconf", + NULL, + NULL, + "nfs_fcntl", + "ogetacl", /* 235 */ + "ofgetacl", + "osetacl", + "ofsetacl", + "pstat", + "getaudid", /* 240 */ + "setaudid", + "getaudproc", + "setaudproc", + "getevent", + "setevent", /* 245 */ + "audwrite", + "audswitch", + "audctl", + "ogetaccess", + "fsctl", /* 250 */ + "ulconnect", + "ulcontrol", + "ulcreate", + "uldest", + "ulrecv", /* 255 */ + "ulrecvcn", + "ulsend", + "ulshutdown", + "swapfs", + "fss", /* 260 */ + NULL, + NULL, + NULL, + NULL, + NULL, /* 265 */ + NULL, + "tsync", + "getnumfds", + "poll", + "getmsg", /* 270 */ + "putmsg", + "fchdir", + "getmount_cnt", + "getmount_entry", + "accept", /* 275 */ + "bind", + "connect", + "getpeername", + "getsockname", + "getsockopt", /* 280 */ + "listen", + "recv", + "recvfrom", + "recvmsg", + "send", /* 285 */ + "sendmsg", + "sendto", + "setsockopt", + "shutdown", + "socket", /* 290 */ + "socketpair", + "proc_open", + "proc_close", + "proc_send", + "proc_recv", /* 295 */ + "proc_sendrecv", + "proc_syscall", + "ipccreate", + "ipcname", + "ipcnamerase", /* 300 */ + "ipclookup", + "ipcselect", + "ipcconnect", + "ipcrecvcn", + "ipcsend", /* 305 */ + "ipcrecv", + "ipcgetnodename", + "ipcsetnodename", + "ipccontrol", + "ipcshutdown", /* 310 */ + "ipcdest", + "semctl", + "msgctl", + "shmctl", + "mpctl", /* 315 */ + "exportfs", + "getpmsg", + "putpmsg", + "strioctl", + "msync", /* 320 */ + "msleep", + "mwakeup", + "msem_init", + "msem_remove", + "adjtime", /* 325 */ + "kload", + "fattach", + "fdetach", + "serialize", + "statvfs", /* 330 */ + "fstatvfs", + "lchown", + "getsid", + "sysfs", + NULL, /* 335 */ + NULL, + "sched_setparam", + "sched_getparam", + "sched_setscheduler", + "sched_getscheduler", /* 340 */ + "sched_yield", + "sched_get_priority_max", + "sched_get_priority_min", + "sched_rr_get_interval", + "clock_settime", /* 345 */ + "clock_gettime", + "clock_getres", + "timer_create", + "timer_delete", + "timer_settime", /* 350 */ + "timer_gettime", + "timer_getoverrun", + "nanosleep", + "toolbox", + NULL, /* 355 */ + "getdents", + "getcontext", + "sysinfo", + "fcntl64", + "ftruncate64", /* 360 */ + "fstat64", + "getdirentries64", + "getrlimit64", + "lockf64", + "lseek64", /* 365 */ + "lstat64", + "mmap64", + "setrlimit64", + "stat64", + "truncate64", /* 370 */ + "ulimit64", + NULL, + NULL, + NULL, + NULL, /* 375 */ + NULL, + NULL, + NULL, + NULL, + "setcontext", /* 380 */ + "sigaltstack", + "waitid", + "setpgrp", + "recvmsg2", + "sendmsg2", /* 385 */ + "socket2", + "socketpair2", + "setregid", + "lwp_create", + "lwp_terminate", /* 390 */ + "lwp_wait", + "lwp_suspend", + "lwp_resume", + "lwp_self", + "lwp_abort_syscall", /* 395 */ + "lwp_info", + "lwp_kill", + "ksleep", + "kwakeup", + "ksleep_abort", /* 400 */ + "lwp_proc_info", + "lwp_exit", + "lwp_continue", + "getacl", + "fgetacl", /* 405 */ + "setacl", + "fsetacl", + "getaccess", + "lwp_mutex_init", + "lwp_mutex_lock_sys", /* 410 */ + "lwp_mutex_unlock", + "lwp_cond_init", + "lwp_cond_signal", + "lwp_cond_broadcast", + "lwp_cond_wait_sys", /* 415 */ + "lwp_getscheduler", + "lwp_setscheduler", + "lwp_getprivate", + "lwp_setprivate", + "lwp_detach", /* 420 */ + "mlock", + "munlock", + "mlockall", + "munlockall", + "shm_open", /* 425 */ + "shm_unlink", + "sigqueue", + "sigwaitinfo", + "sigtimedwait", + "sigwait", /* 430 */ + "aio_read", + "aio_write", + "lio_listio", + "aio_error", + "aio_return", /* 435 */ + "aio_cancel", + "aio_suspend", + "aio_fsync", + "mq_open", + "mq_unlink", /* 440 */ + "mq_send", + "mq_receive", + "mq_notify", + "mq_setattr", + "mq_getattr", /* 445 */ + "ksem_open", + "ksem_unlink", + "ksem_close", + "ksem_destroy", + "lw_sem_incr", /* 450 */ + "lw_sem_decr", + "lw_sem_read", + "mq_close", +}; +static const int syscall_names_max = 453; + +int +hpux_unimplemented(unsigned long arg1,unsigned long arg2,unsigned long arg3, + unsigned long arg4,unsigned long arg5,unsigned long arg6, + unsigned long arg7,unsigned long sc_num) +{ + /* NOTE: sc_num trashes arg8 for the few syscalls that actually + * have a valid 8th argument. + */ + const char *name = NULL; + if ( sc_num <= syscall_names_max && sc_num >= 0 ) { + name = syscall_names[sc_num]; + } + + if ( name ) { + printk(KERN_DEBUG "Unimplemented HP-UX syscall emulation. Syscall #%lu (%s)\n", + sc_num, name); + } else { + printk(KERN_DEBUG "Unimplemented unknown HP-UX syscall emulation. Syscall #%lu\n", + sc_num); + } + + printk(KERN_DEBUG " Args: %lx %lx %lx %lx %lx %lx %lx\n", + arg1, arg2, arg3, arg4, arg5, arg6, arg7); + + return -ENOSYS; +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/hpux/wrappers.S linux.19rc3-ac4/arch/parisc/hpux/wrappers.S --- linux.19rc3/arch/parisc/hpux/wrappers.S 2002-07-29 12:50:07.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/hpux/wrappers.S 2002-07-29 13:58:35.000000000 +0100 @@ -1,5 +1,5 @@ -/*------------------------------------------------------------------------------ - * Native PARISC/Linux Project (http://www.puffingroup.com/parisc) +/* + * Linux/PARISC Project (http://www.parisc-linux.org/) * * HP-UX System Call Wrapper routines and System Call Return Path * @@ -29,7 +29,6 @@ .level 1.1 .text -#define __ASSEMBLY__ #include #include @@ -81,6 +80,7 @@ .export hpux_fork_wrapper + .export hpux_child_return .import sys_fork hpux_fork_wrapper: @@ -91,12 +91,10 @@ stw %r2,-20(%r30) ldo 64(%r30),%r30 stw %r2,PT_GR19(%r1) ;! save for child - stw %r30,PT_GR20(%r1) ;! save for child - ldil L%child_return,%r3 - ldo R%child_return(%r3),%r3 - stw %r3,PT_GR21(%r1) ;! save for child + stw %r30,PT_GR21(%r1) ;! save for child - ldw TASK_PT_GR30(%r1),%r25 + ldw PT_GR30(%r1),%r25 + mtctl %r25,%cr29 copy %r1,%r24 bl sys_clone,%r2 ldi SIGCHLD,%r26 @@ -130,7 +128,10 @@ /* Set the return value for the child */ -child_return: +hpux_child_return: + bl schedule_tail, %r2 + nop + ldw TASK_PT_GR19-TASK_SZ_ALGN-128(%r30),%r2 b fork_return copy %r0,%r28 @@ -242,3 +243,10 @@ no_error: b syscall_exit nop + + .export hpux_unimplemented_wrapper + .import hpux_unimplemented + +hpux_unimplemented_wrapper: + b hpux_unimplemented + stw %r22,-64(%r30) /* overwrite arg8 with syscall number */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/binfmt_elf32.c linux.19rc3-ac4/arch/parisc/kernel/binfmt_elf32.c --- linux.19rc3/arch/parisc/kernel/binfmt_elf32.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/binfmt_elf32.c 2002-07-29 13:58:35.000000000 +0100 @@ -0,0 +1,93 @@ +/* + * Support for 32-bit Linux/Parisc ELF binaries on 64 bit kernels + * + * Copyright (C) 2000 John Marvin + * Copyright (C) 2000 Hewlett Packard Co. + * + * Heavily inspired from various other efforts to do the same thing + * (ia64,sparc64/mips64) + */ + +/* Make sure include/asm-parisc/elf.h does the right thing */ + +#define ELF_CLASS ELFCLASS32 + +typedef unsigned int elf_greg_t; + +#include +#include +#include +#include +#include +#include "sys32.h" /* struct timeval32 */ + +#define elf_prstatus elf_prstatus32 +struct elf_prstatus32 +{ + struct elf_siginfo pr_info; /* Info associated with signal */ + short pr_cursig; /* Current signal */ + unsigned int pr_sigpend; /* Set of pending signals */ + unsigned int pr_sighold; /* Set of held signals */ + pid_t pr_pid; + pid_t pr_ppid; + pid_t pr_pgrp; + pid_t pr_sid; + struct timeval32 pr_utime; /* User time */ + struct timeval32 pr_stime; /* System time */ + struct timeval32 pr_cutime; /* Cumulative user time */ + struct timeval32 pr_cstime; /* Cumulative system time */ + elf_gregset_t pr_reg; /* GP registers */ + int pr_fpvalid; /* True if math co-processor being used. */ +}; + +#define elf_prpsinfo elf_prpsinfo32 +struct elf_prpsinfo32 +{ + char pr_state; /* numeric process state */ + char pr_sname; /* char for pr_state */ + char pr_zomb; /* zombie */ + char pr_nice; /* nice val */ + unsigned int pr_flag; /* flags */ + u16 pr_uid; + u16 pr_gid; + pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* filename of executable */ + char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */ +}; + +#define elf_addr_t unsigned int +typedef unsigned int elf_caddr_t; +#define init_elf_binfmt init_elf32_binfmt + +#define ELF_PLATFORM ("PARISC32\0") + +#define ELF_CORE_COPY_REGS(dst, pt) \ + memset(dst, 0, sizeof(dst)); /* don't leak any "random" bits */ \ + { int i; \ + for (i = 0; i < 32; i++) dst[i] = (elf_greg_t) pt->gr[i]; \ + for (i = 0; i < 8; i++) dst[32 + i] = (elf_greg_t) pt->sr[i]; \ + } \ + dst[40] = (elf_greg_t) pt->iaoq[0]; dst[41] = (elf_greg_t) pt->iaoq[1]; \ + dst[42] = (elf_greg_t) pt->iasq[0]; dst[43] = (elf_greg_t) pt->iasq[1]; \ + dst[44] = (elf_greg_t) pt->sar; dst[45] = (elf_greg_t) pt->iir; \ + dst[46] = (elf_greg_t) pt->isr; dst[47] = (elf_greg_t) pt->ior; \ + dst[48] = (elf_greg_t) mfctl(22); dst[49] = (elf_greg_t) mfctl(0); \ + dst[50] = (elf_greg_t) mfctl(24); dst[51] = (elf_greg_t) mfctl(25); \ + dst[52] = (elf_greg_t) mfctl(26); dst[53] = (elf_greg_t) mfctl(27); \ + dst[54] = (elf_greg_t) mfctl(28); dst[55] = (elf_greg_t) mfctl(29); \ + dst[56] = (elf_greg_t) mfctl(30); dst[57] = (elf_greg_t) mfctl(31); \ + dst[58] = (elf_greg_t) mfctl( 8); dst[59] = (elf_greg_t) mfctl( 9); \ + dst[60] = (elf_greg_t) mfctl(12); dst[61] = (elf_greg_t) mfctl(13); \ + dst[62] = (elf_greg_t) mfctl(10); dst[63] = (elf_greg_t) mfctl(15); + +/* + * We should probably use this macro to set a flag somewhere to indicate + * this is a 32 on 64 process. We could use PER_LINUX_32BIT, or we + * could set a processor dependent flag in the thread_struct. + */ + +#define SET_PERSONALITY(ex, ibcs2) \ + current->personality = PER_LINUX_32BIT + +#include "../../../fs/binfmt_elf.c" diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/cache.c linux.19rc3-ac4/arch/parisc/kernel/cache.c --- linux.19rc3/arch/parisc/kernel/cache.c 2002-07-29 12:50:06.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/cache.c 2002-07-29 13:58:35.000000000 +0100 @@ -15,202 +15,85 @@ #include #include #include +#include #include #include #include #include #include +#include + +int split_tlb; +int dcache_stride; +int icache_stride; struct pdc_cache_info cache_info; -#ifndef __LP64__ +#ifndef CONFIG_PA20 static struct pdc_btlb_info btlb_info; #endif - -void __flush_page_to_ram(unsigned long address) -{ - __flush_dcache_range(address, PAGE_SIZE); - __flush_icache_range(address, PAGE_SIZE); -} - - - -void flush_data_cache(void) +#ifdef CONFIG_SMP +void +flush_data_cache(void) { - register unsigned long base = cache_info.dc_base; - register unsigned long count = cache_info.dc_count; - register unsigned long loop = cache_info.dc_loop; - register unsigned long stride = cache_info.dc_stride; - register unsigned long addr; - register long i, j; - - for(i=0,addr=base; imapping && + test_bit(PG_dcache_dirty, &page->flags)) { - for(i=0,addr=base; iflags); + } } -int get_cache_info(char *buffer) +void +show_cache_info(struct seq_file *m) { - char *p = buffer; - - p += sprintf(p, "I-cache\t\t: %ld KB\n", + seq_printf(m, "I-cache\t\t: %ld KB\n", cache_info.ic_size/1024 ); - p += sprintf(p, "D-cache\t\t: %ld KB (%s)%s\n", + seq_printf(m, "D-cache\t\t: %ld KB (%s)%s\n", cache_info.dc_size/1024, (cache_info.dc_conf.cc_wt ? "WT":"WB"), (cache_info.dc_conf.cc_sh ? " - shared I/D":"") ); - p += sprintf(p, "ITLB entries\t: %ld\n" "DTLB entries\t: %ld%s\n", + seq_printf(m, "ITLB entries\t: %ld\n" "DTLB entries\t: %ld%s\n", cache_info.it_size, cache_info.dt_size, cache_info.dt_conf.tc_sh ? " - shared with ITLB":"" ); -#ifndef __LP64__ +#ifndef CONFIG_PA20 /* BTLB - Block TLB */ if (btlb_info.max_size==0) { - p += sprintf(p, "BTLB\t\t: not supported\n" ); + seq_printf(m, "BTLB\t\t: not supported\n" ); } else { - p += sprintf(p, + seq_printf(m, "BTLB fixed\t: max. %d pages, pagesize=%d (%dMB)\n" "BTLB fix-entr.\t: %d instruction, %d data (%d combined)\n" "BTLB var-entr.\t: %d instruction, %d data (%d combined)\n", @@ -225,11 +108,8 @@ ); } #endif - - return p - buffer; } - void __init cache_init(void) { @@ -237,17 +117,108 @@ panic("cache_init: pdc_cache_info failed"); #if 0 - printk("ic_size %lx dc_size %lx it_size %lx pdc_cache_info %d*long pdc_cache_cf %d\n", + printk(KERN_DEBUG "ic_size %lx dc_size %lx it_size %lx pdc_cache_info %d*long pdc_cache_cf %d\n", cache_info.ic_size, cache_info.dc_size, cache_info.it_size, sizeof (struct pdc_cache_info) / sizeof (long), sizeof (struct pdc_cache_cf) ); + + printk(KERN_DEBUG "dc base %x dc stride %x dc count %x dc loop %d\n", + cache_info.dc_base, + cache_info.dc_stride, + cache_info.dc_count, + cache_info.dc_loop); + + printk(KERN_DEBUG "dc conf: alias %d block %d line %d wt %d sh %d cst %d assoc %d\n", + cache_info.dc_conf.cc_alias, + cache_info.dc_conf.cc_block, + cache_info.dc_conf.cc_line, + cache_info.dc_conf.cc_wt, + cache_info.dc_conf.cc_sh, + cache_info.dc_conf.cc_cst, + cache_info.dc_conf.cc_assoc); + + printk(KERN_DEBUG "ic conf: alias %d block %d line %d wt %d sh %d cst %d assoc %d\n", + cache_info.ic_conf.cc_alias, + cache_info.ic_conf.cc_block, + cache_info.ic_conf.cc_line, + cache_info.ic_conf.cc_wt, + cache_info.ic_conf.cc_sh, + cache_info.ic_conf.cc_cst, + cache_info.ic_conf.cc_assoc); + + printk(KERN_DEBUG "dt conf: sh %d page %d cst %d aid %d pad1 %d \n", + cache_info.dt_conf.tc_sh, + cache_info.dt_conf.tc_page, + cache_info.dt_conf.tc_cst, + cache_info.dt_conf.tc_aid, + cache_info.dt_conf.tc_pad1); + + printk(KERN_DEBUG "it conf: sh %d page %d cst %d aid %d pad1 %d \n", + cache_info.it_conf.tc_sh, + cache_info.it_conf.tc_page, + cache_info.it_conf.tc_cst, + cache_info.it_conf.tc_aid, + cache_info.it_conf.tc_pad1); #endif -#ifndef __LP64__ + + split_tlb = 0; + if (cache_info.dt_conf.tc_sh == 0 || cache_info.dt_conf.tc_sh == 2) { + + if (cache_info.dt_conf.tc_sh == 2) + printk(KERN_WARNING "Unexpected TLB configuration. " + "Will flush I/D separately (could be optimized).\n"); + + split_tlb = 1; + } + + dcache_stride = ( (1<<(cache_info.dc_conf.cc_block+3)) * + cache_info.dc_conf.cc_line ); + icache_stride = ( (1<<(cache_info.ic_conf.cc_block+3)) * + cache_info.ic_conf.cc_line ); +#ifndef CONFIG_PA20 if(pdc_btlb_info(&btlb_info)<0) { memset(&btlb_info, 0, sizeof btlb_info); } #endif + + if ((boot_cpu_data.pdc.capabilities & PDC_MODEL_NVA_MASK) == PDC_MODEL_NVA_UNSUPPORTED) { + printk(KERN_WARNING "Only equivalent aliasing supported\n"); +#ifndef CONFIG_SMP + panic("SMP kernel required to avoid non-equivalent aliasing"); +#endif + } +} + +void disable_sr_hashing(void) +{ + int srhash_type; + + if (boot_cpu_data.cpu_type == pcxl2) + return; /* pcxl2 doesn't support space register hashing */ + + switch (boot_cpu_data.cpu_type) { + + case pcx: + BUG(); /* We shouldn't get here. code in setup.c should prevent it */ + return; + + case pcxs: + case pcxt: + case pcxt_: + srhash_type = SRHASH_PCXST; + break; + + case pcxl: + srhash_type = SRHASH_PCXL; + break; + + default: /* Currently all PA2.0 machines use the same ins. sequence */ + srhash_type = SRHASH_PA20; + break; + } + + disable_sr_hashing_asm(srhash_type); } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/ccio-dma.c linux.19rc3-ac4/arch/parisc/kernel/ccio-dma.c --- linux.19rc3/arch/parisc/kernel/ccio-dma.c 2002-07-29 12:50:06.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/ccio-dma.c 2002-07-29 13:58:36.000000000 +0100 @@ -38,16 +38,19 @@ #include #include #include +#define PCI_DEBUG #include +#undef PCI_DEBUG #include #include /* for L1_CACHE_BYTES */ #include #include #include - +#include #include #include /* for gsc_writeN()... */ +#include /* for register_module() */ /* ** Choose "ccio" since that's what HP-UX calls it. @@ -55,12 +58,10 @@ */ #define MODULE_NAME "ccio" -/* -#define DEBUG_CCIO_RES -#define DEBUG_CCIO_RUN -#define DEBUG_CCIO_INIT -#define DUMP_RESMAP -*/ +#undef DEBUG_CCIO_RES +#undef DEBUG_CCIO_RUN +#undef DEBUG_CCIO_INIT +#undef DEBUG_CCIO_RUN_SG #include #include /* for proc_runway_root */ @@ -83,68 +84,20 @@ #define DBG_RES(x...) #endif +#ifdef DEBUG_CCIO_RUN_SG +#define DBG_RUN_SG(x...) printk(x) +#else +#define DBG_RUN_SG(x...) +#endif + #define CCIO_INLINE /* inline */ -#define WRITE_U32(value, addr) gsc_writel(value, (u32 *) (addr)) +#define WRITE_U32(value, addr) gsc_writel(value, (u32 *)(addr)) +#define READ_U32(addr) gsc_readl((u32 *)(addr)) #define U2_IOA_RUNWAY 0x580 #define U2_BC_GSC 0x501 #define UTURN_IOA_RUNWAY 0x581 #define UTURN_BC_GSC 0x502 -/* We *can't* support JAVA (T600). Venture there at your own risk. */ - -static void dump_resmap(void); - -static int ccio_driver_callback(struct hp_device *, struct pa_iodc_driver *); - -static struct pa_iodc_driver ccio_drivers_for[] = { - - {HPHW_IOA, U2_IOA_RUNWAY, 0x0, 0xb, 0, 0x10, - DRIVER_CHECK_HVERSION + - DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE, - MODULE_NAME, "U2 I/O MMU", (void *) ccio_driver_callback}, - - {HPHW_IOA, UTURN_IOA_RUNWAY, 0x0, 0xb, 0, 0x10, - DRIVER_CHECK_HVERSION + - DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE, - MODULE_NAME, "Uturn I/O MMU", (void *) ccio_driver_callback}, - -/* -** FIXME: The following claims the GSC bus port, not the IOA. -** And there are two busses below a single I/O TLB. -** -** These should go away once we have a real PA bus walk. -** Firmware wants to tell the PA bus walk code about the GSC ports -** since they are not "architected" PA I/O devices. Ie a PA bus walk -** wouldn't discover them. But the PA bus walk code could check -** the "fixed module table" to add such devices to an I/O Tree -** and proceed with the recursive, depth first bus walk. -*/ - {HPHW_BCPORT, U2_BC_GSC, 0x0, 0xc, 0, 0x10, - DRIVER_CHECK_HVERSION + - DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE, - MODULE_NAME, "U2 GSC+ BC", (void *) ccio_driver_callback}, - - {HPHW_BCPORT, UTURN_BC_GSC, 0x0, 0xc, 0, 0x10, - DRIVER_CHECK_HVERSION + - DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE, - MODULE_NAME, "Uturn GSC+ BC", (void *) ccio_driver_callback}, - - {0,0,0,0,0,0, - 0, - (char *) NULL, (char *) NULL, (void *) NULL } -}; - - -#define IS_U2(id) ( \ - (((id)->hw_type == HPHW_IOA) && ((id)->hversion == U2_IOA_RUNWAY)) || \ - (((id)->hw_type == HPHW_BCPORT) && ((id)->hversion == U2_BC_GSC)) \ -) - -#define IS_UTURN(id) ( \ - (((id)->hw_type == HPHW_IOA) && ((id)->hversion == UTURN_IOA_RUNWAY)) || \ - (((id)->hw_type == HPHW_BCPORT) && ((id)->hversion == UTURN_BC_GSC)) \ -) - #define IOA_NORMAL_MODE 0x00020080 /* IO_CONTROL to turn on CCIO */ #define CMD_TLB_DIRECT_WRITE 35 /* IO_COMMAND for I/O TLB Writes */ @@ -176,41 +129,46 @@ volatile uint32_t io_io_high; /* Offset 15 */ }; +struct ioc { + struct ioa_registers *ioc_hpa; /* I/O MMU base address */ + u8 *res_map; /* resource map, bit == pdir entry */ + u64 *pdir_base; /* physical base address */ + u32 res_hint; /* next available IOVP - + circular search */ + u32 res_size; /* size of resource map in bytes */ + spinlock_t res_lock; + +#ifdef CONFIG_PROC_FS +#define CCIO_SEARCH_SAMPLE 0x100 + unsigned long avg_search[CCIO_SEARCH_SAMPLE]; + unsigned long avg_idx; /* current index into avg_search */ + unsigned long used_pages; + unsigned long msingle_calls; + unsigned long msingle_pages; + unsigned long msg_calls; + unsigned long msg_pages; + unsigned long usingle_calls; + unsigned long usingle_pages; + unsigned long usg_calls; + unsigned long usg_pages; -struct ccio_device { - struct ccio_device *next; /* list of LBA's in system */ - struct hp_device *iodc; /* data about dev from firmware */ - spinlock_t ccio_lock; - - struct ioa_registers *ccio_hpa; /* base address */ - u64 *pdir_base; /* physical base address */ - char *res_map; /* resource map, bit == pdir entry */ - - int res_hint; /* next available IOVP - circular search */ - int res_size; /* size of resource map in bytes */ - int chainid_shift; /* specify bit location of chain_id */ - int flags; /* state/functionality enabled */ -#ifdef DELAYED_RESOURCE_CNT - dma_addr_t res_delay[DELAYED_RESOURCE_CNT]; + unsigned short cujo20_bug; #endif /* STUFF We don't need in performance path */ - int pdir_size; /* in bytes, determined by IOV Space size */ - int hw_rev; /* HW revision of chip */ + u32 pdir_size; /* in bytes, determined by IOV Space size */ + u32 chainid_shift; /* specify bit location of chain_id */ + struct ioc *next; /* Linked list of discovered iocs */ + const char *name; /* device name from firmware */ + unsigned int hw_path; /* the hardware path this ioc is associatd with */ + struct pci_dev *fake_pci_dev; /* the fake pci_dev for non-pci devs */ + struct resource mmio_region[2]; /* The "routed" MMIO regions */ }; - /* Ratio of Host MEM to IOV Space size */ static unsigned long ccio_mem_ratio = 4; -static struct ccio_device *ccio_list = NULL; - -static int ccio_proc_info(char *buffer, char **start, off_t offset, int length); -static unsigned long ccio_used_bytes = 0; -static unsigned long ccio_used_pages = 0; -static int ccio_cujo_bug = 0; - -static unsigned long ccio_alloc_size = 0; -static unsigned long ccio_free_size = 0; +static struct ioc *ioc_list; +static int ioc_count; /************************************************************** * @@ -227,55 +185,41 @@ * match the I/O TLB replacement policy. * ***************************************************************/ -#define PAGES_PER_RANGE 1 /* could increase this to 4 or 8 if needed */ #define IOVP_SIZE PAGE_SIZE #define IOVP_SHIFT PAGE_SHIFT #define IOVP_MASK PAGE_MASK /* Convert from IOVP to IOVA and vice versa. */ #define CCIO_IOVA(iovp,offset) ((iovp) | (offset)) -#define CCIO_IOVP(iova) ((iova) & ~(IOVP_SIZE-1) ) +#define CCIO_IOVP(iova) ((iova) & IOVP_MASK) #define PDIR_INDEX(iovp) ((iovp)>>IOVP_SHIFT) #define MKIOVP(pdir_idx) ((long)(pdir_idx) << IOVP_SHIFT) #define MKIOVA(iovp,offset) (dma_addr_t)((long)iovp | (long)offset) - -/* CUJO20 KLUDGE start */ -#define CUJO_20_BITMASK 0x0ffff000 /* upper nibble is a don't care */ -#define CUJO_20_STEP 0x10000000 /* inc upper nibble */ -#define CUJO_20_BADPAGE1 0x01003000 /* pages that hpmc on raven U+ */ -#define CUJO_20_BADPAGE2 0x01607000 /* pages that hpmc on firehawk U+ */ -#define CUJO_20_BADHVERS 0x6821 /* low nibble 1 is cujo rev 2.0 */ -#define CUJO_RAVEN_LOC 0xf1000000UL /* cujo location on raven U+ */ -#define CUJO_FIREHAWK_LOC 0xf1604000UL /* cujo location on firehawk U+ */ -/* CUJO20 KLUDGE end */ +#define ROUNDUP(x,y) ((x + ((y)-1)) & ~((y)-1)) /* ** Don't worry about the 150% average search length on a miss. ** If the search wraps around, and passes the res_hint, it will ** cause the kernel to panic anyhow. */ - -/* ioa->res_hint = idx + (size >> 3); \ */ - -#define CCIO_SEARCH_LOOP(ioa, idx, mask, size) \ - for(; res_ptr < res_end; ++res_ptr) \ - { \ - if(0 == ((*res_ptr) & mask)) { \ - *res_ptr |= mask; \ - idx = (int)((unsigned long)res_ptr - (unsigned long)ioa->res_map); \ - ioa->res_hint = 0;\ +#define CCIO_SEARCH_LOOP(ioc, res_idx, mask_ptr, size) \ + for(; res_ptr < res_end; ++res_ptr) { \ + if(0 == (*res_ptr & *mask_ptr)) { \ + *res_ptr |= *mask_ptr; \ + res_idx = (int)((unsigned long)res_ptr - (unsigned long)ioc->res_map); \ + ioc->res_hint = res_idx + (size >> 3); \ goto resource_found; \ } \ } -#define CCIO_FIND_FREE_MAPPING(ioa, idx, mask, size) { \ - u##size *res_ptr = (u##size *)&((ioa)->res_map[ioa->res_hint & ~((size >> 3) - 1)]); \ - u##size *res_end = (u##size *)&(ioa)->res_map[ioa->res_size]; \ - CCIO_SEARCH_LOOP(ioa, idx, mask, size); \ - res_ptr = (u##size *)&(ioa)->res_map[0]; \ - CCIO_SEARCH_LOOP(ioa, idx, mask, size); \ -} +#define CCIO_FIND_FREE_MAPPING(ioa, res_idx, mask, size) \ + u##size *res_ptr = (u##size *)&((ioc)->res_map[ioa->res_hint & ~((size >> 3) - 1)]); \ + u##size *res_end = (u##size *)&(ioc)->res_map[ioa->res_size]; \ + u##size *mask_ptr = (u##size *)&mask; \ + CCIO_SEARCH_LOOP(ioc, res_idx, mask_ptr, size); \ + res_ptr = (u##size *)&(ioc)->res_map[0]; \ + CCIO_SEARCH_LOOP(ioa, res_idx, mask_ptr, size); /* ** Find available bit in this ioa's resource map. @@ -290,123 +234,132 @@ ** o use different search for "large" (eg > 4 pages) or "very large" ** (eg > 16 pages) mappings. */ + +/** + * ccio_alloc_range - Allocate pages in the ioc's resource map. + * @ioc: The I/O Controller. + * @pages_needed: The requested number of pages to be mapped into the + * I/O Pdir... + * + * This function searches the resource map of the ioc to locate a range + * of available pages for the requested size. + */ static int -ccio_alloc_range(struct ccio_device *ioa, size_t size) +ccio_alloc_range(struct ioc *ioc, unsigned long pages_needed) { int res_idx; - unsigned long mask, flags; - unsigned int pages_needed = size >> PAGE_SHIFT; - + unsigned long mask; +#ifdef CONFIG_PROC_FS + unsigned long cr_start = mfctl(16); +#endif + ASSERT(pages_needed); - ASSERT((pages_needed * IOVP_SIZE) < DMA_CHUNK_SIZE); - ASSERT(pages_needed < (BITS_PER_LONG - IOVP_SHIFT)); + ASSERT((pages_needed * IOVP_SIZE) <= DMA_CHUNK_SIZE); + ASSERT(pages_needed <= BITS_PER_LONG); - mask = (unsigned long) -1L; - mask >>= BITS_PER_LONG - pages_needed; - - DBG_RES(__FUNCTION__ " size: %d pages_needed %d pages_mask 0x%08lx\n", - size, pages_needed, mask); - - spin_lock_irqsave(&ioa->ccio_lock, flags); + mask = ~(~0UL >> pages_needed); + + DBG_RES("%s() size: %d pages_needed %d mask 0x%08lx\n", + __FUNCTION__, size, pages_needed, mask); /* ** "seek and ye shall find"...praying never hurts either... - ** ggg sacrafices another 710 to the computer gods. + ** ggg sacrifices another 710 to the computer gods. */ if(pages_needed <= 8) { - CCIO_FIND_FREE_MAPPING(ioa, res_idx, mask, 8); + CCIO_FIND_FREE_MAPPING(ioc, res_idx, mask, 8); } else if(pages_needed <= 16) { - CCIO_FIND_FREE_MAPPING(ioa, res_idx, mask, 16); + CCIO_FIND_FREE_MAPPING(ioc, res_idx, mask, 16); } else if(pages_needed <= 32) { - CCIO_FIND_FREE_MAPPING(ioa, res_idx, mask, 32); + CCIO_FIND_FREE_MAPPING(ioc, res_idx, mask, 32); #ifdef __LP64__ } else if(pages_needed <= 64) { - CCIO_FIND_FREE_MAPPING(ioa, res_idx, mask, 64) + CCIO_FIND_FREE_MAPPING(ioc, res_idx, mask, 64); #endif } else { - panic(__FILE__ ":" __FUNCTION__ "() Too many pages to map.\n"); + panic(__FILE__ ": %s() Too many pages to map. pages_needed: %ld\n", + __FUNCTION__, pages_needed); } -#ifdef DUMP_RESMAP - dump_resmap(); -#endif - panic(__FILE__ ":" __FUNCTION__ "() I/O MMU is out of mapping resources\n"); + panic(__FILE__ ": %s() I/O MMU is out of mapping resources.\n", + __FUNCTION__); resource_found: - DBG_RES(__FUNCTION__ " res_idx %d mask 0x%08lx res_hint: %d\n", - res_idx, mask, ioa->res_hint); + DBG_RES("%s() res_idx %d mask 0x%08lx res_hint: %d\n", + __FUNCTION__, res_idx, mask, ioc->res_hint); - ccio_used_pages += pages_needed; - ccio_used_bytes += ((pages_needed >> 3) ? (pages_needed >> 3) : 1); - - spin_unlock_irqrestore(&ioa->ccio_lock, flags); +#ifdef CONFIG_PROC_FS + { + unsigned long cr_end = mfctl(16); + unsigned long tmp = cr_end - cr_start; + /* check for roll over */ + cr_start = (cr_end < cr_start) ? -(tmp) : (tmp); + } + ioc->avg_search[ioc->avg_idx++] = cr_start; + ioc->avg_idx &= CCIO_SEARCH_SAMPLE - 1; -#ifdef DUMP_RESMAP - dump_resmap(); + ioc->used_pages += pages_needed; #endif /* - ** return the bit address (convert from byte to bit). + ** return the bit address. */ - return (res_idx << 3); + return res_idx << 3; } - -#define CCIO_FREE_MAPPINGS(ioa, idx, mask, size) \ - u##size *res_ptr = (u##size *)&((ioa)->res_map[idx + (((size >> 3) - 1) & ~((size >> 3) - 1))]); \ - ASSERT((*res_ptr & mask) == mask); \ - *res_ptr &= ~mask; - -/* -** clear bits in the ioa's resource map -*/ +#define CCIO_FREE_MAPPINGS(ioc, res_idx, mask, size) \ + u##size *res_ptr = (u##size *)&((ioc)->res_map[res_idx]); \ + u##size *mask_ptr = (u##size *)&mask; \ + ASSERT((*res_ptr & *mask_ptr) == *mask_ptr); \ + *res_ptr &= ~(*mask_ptr); + +/** + * ccio_free_range - Free pages from the ioc's resource map. + * @ioc: The I/O Controller. + * @iova: The I/O Virtual Address. + * @pages_mapped: The requested number of pages to be freed from the + * I/O Pdir. + * + * This function frees the resouces allocated for the iova. + */ static void -ccio_free_range(struct ccio_device *ioa, dma_addr_t iova, size_t size) +ccio_free_range(struct ioc *ioc, dma_addr_t iova, unsigned long pages_mapped) { - unsigned long mask, flags; + unsigned long mask; unsigned long iovp = CCIO_IOVP(iova); - unsigned int res_idx = PDIR_INDEX(iovp)>>3; - unsigned int pages_mapped = (size >> IOVP_SHIFT) + !!(size & ~IOVP_MASK); + unsigned int res_idx = PDIR_INDEX(iovp) >> 3; - ASSERT(pages_needed); - ASSERT((pages_needed * IOVP_SIZE) < DMA_CHUNK_SIZE); - ASSERT(pages_needed < (BITS_PER_LONG - IOVP_SHIFT)); + ASSERT(pages_mapped); + ASSERT((pages_mapped * IOVP_SIZE) <= DMA_CHUNK_SIZE); + ASSERT(pages_mapped <= BITS_PER_LONG); - mask = (unsigned long) -1L; - mask >>= BITS_PER_LONG - pages_mapped; + mask = ~(~0UL >> pages_mapped); - DBG_RES(__FUNCTION__ " res_idx: %d size: %d pages_mapped %d mask 0x%08lx\n", - res_idx, size, pages_mapped, mask); + DBG_RES("%s(): res_idx: %d pages_mapped %d mask 0x%08lx\n", + __FUNCTION__, res_idx, pages_mapped, mask); - spin_lock_irqsave(&ioa->ccio_lock, flags); +#ifdef CONFIG_PROC_FS + ioc->used_pages -= pages_mapped; +#endif if(pages_mapped <= 8) { - CCIO_FREE_MAPPINGS(ioa, res_idx, mask, 8); + CCIO_FREE_MAPPINGS(ioc, res_idx, mask, 8); } else if(pages_mapped <= 16) { - CCIO_FREE_MAPPINGS(ioa, res_idx, mask, 16); + CCIO_FREE_MAPPINGS(ioc, res_idx, mask, 16); } else if(pages_mapped <= 32) { - CCIO_FREE_MAPPINGS(ioa, res_idx, mask, 32); + CCIO_FREE_MAPPINGS(ioc, res_idx, mask, 32); #ifdef __LP64__ } else if(pages_mapped <= 64) { - CCIO_FREE_MAPPINGS(ioa, res_idx, mask, 64); + CCIO_FREE_MAPPINGS(ioc, res_idx, mask, 64); #endif } else { - panic(__FILE__ ":" __FUNCTION__ "() Too many pages to unmap.\n"); + panic(__FILE__ ":%s() Too many pages to unmap.\n", + __FUNCTION__); } - - ccio_used_pages -= (pages_mapped ? pages_mapped : 1); - ccio_used_bytes -= ((pages_mapped >> 3) ? (pages_mapped >> 3) : 1); - - spin_unlock_irqrestore(&ioa->ccio_lock, flags); - -#ifdef DUMP_RESMAP - dump_resmap(); -#endif } - /**************************************************************** ** ** CCIO dma_ops support routines @@ -416,7 +369,6 @@ typedef unsigned long space_t; #define KERNEL_SPACE 0 - /* ** DMA "Page Type" and Hints ** o if SAFE_DMA isn't set, mapping is for FAST_DMA. SAFE_DMA should be @@ -466,32 +418,35 @@ [PCI_DMA_NONE] 0, /* not valid */ }; -/* -** Initialize an I/O Pdir entry -** -** Given a virtual address (vba, arg2) and space id, (sid, arg1), -** load the I/O PDIR entry pointed to by pdir_ptr (arg0). Each IO Pdir -** entry consists of 8 bytes as shown below (MSB == bit 0): -** -** -** WORD 0: -** +------+----------------+-----------------------------------------------+ -** | Phys | Virtual Index | Phys | -** | 0:3 | 0:11 | 4:19 | -** |4 bits| 12 bits | 16 bits | -** +------+----------------+-----------------------------------------------+ -** WORD 1: -** +-----------------------+-----------------------------------------------+ -** | Phys | Rsvd | Prefetch |Update |Rsvd |Lock |Safe |Valid | -** | 20:39 | | Enable |Enable | |Enable|DMA | | -** | 20 bits | 5 bits | 1 bit |1 bit |2 bits|1 bit |1 bit |1 bit | -** +-----------------------+-----------------------------------------------+ -** -** The virtual index field is filled with the results of the LCI -** (Load Coherence Index) instruction. The 8 bits used for the virtual -** index are bits 12:19 of the value returned by LCI. -*/ - +/** + * ccio_io_pdir_entry - Initialize an I/O Pdir. + * @pdir_ptr: A pointer into I/O Pdir. + * @sid: The Space Identifier. + * @vba: The virtual address. + * @hints: The DMA Hint. + * + * Given a virtual address (vba, arg2) and space id, (sid, arg1), + * load the I/O PDIR entry pointed to by pdir_ptr (arg0). Each IO Pdir + * entry consists of 8 bytes as shown below (MSB == bit 0): + * + * + * WORD 0: + * +------+----------------+-----------------------------------------------+ + * | Phys | Virtual Index | Phys | + * | 0:3 | 0:11 | 4:19 | + * |4 bits| 12 bits | 16 bits | + * +------+----------------+-----------------------------------------------+ + * WORD 1: + * +-----------------------+-----------------------------------------------+ + * | Phys | Rsvd | Prefetch |Update |Rsvd |Lock |Safe |Valid | + * | 20:39 | | Enable |Enable | |Enable|DMA | | + * | 20 bits | 5 bits | 1 bit |1 bit |2 bits|1 bit |1 bit |1 bit | + * +-----------------------+-----------------------------------------------+ + * + * The virtual index field is filled with the results of the LCI + * (Load Coherence Index) instruction. The 8 bits used for the virtual + * index are bits 12:19 of the value returned by LCI. + */ void CCIO_INLINE ccio_io_pdir_entry(u64 *pdir_ptr, space_t sid, void * vba, unsigned long hints) { @@ -499,8 +454,7 @@ register unsigned long ci; /* coherent index */ /* We currently only support kernel addresses */ - ASSERT(sid == 0); - ASSERT(((unsigned long) vba & 0xf0000000UL) == 0xc0000000UL); + ASSERT(sid == KERNEL_SPACE); mtsp(sid,1); @@ -524,7 +478,7 @@ ** and deposit them */ asm volatile ("extrd,u %1,15,4,%0" : "=r" (ci) : "r" (pa)); - asm volatile ("extrd,u %1,31,16,%0" : "+r" (ci) : "r" (ci)); + asm volatile ("extrd,u %1,31,16,%0" : "+r" (pa) : "r" (pa)); asm volatile ("depd %1,35,4,%0" : "+r" (pa) : "r" (ci)); #else pa = 0; @@ -556,31 +510,39 @@ asm volatile("sync"); } - -/* -** Remove stale entries from the I/O TLB. -** Need to do this whenever an entry in the PDIR is marked invalid. -*/ +/** + * ccio_clear_io_tlb - Remove stale entries from the I/O TLB. + * @ioc: The I/O Controller. + * @iovp: The I/O Virtual Page. + * @byte_cnt: The requested number of bytes to be freed from the I/O Pdir. + * + * Purge invalid I/O PDIR entries from the I/O TLB. + * + * FIXME: Can we change the byte_cnt to pages_mapped? + */ static CCIO_INLINE void -ccio_clear_io_tlb( struct ccio_device *d, dma_addr_t iovp, size_t byte_cnt) +ccio_clear_io_tlb(struct ioc *ioc, dma_addr_t iovp, size_t byte_cnt) { - u32 chain_size = 1 << d->chainid_shift; + u32 chain_size = 1 << ioc->chainid_shift; - iovp &= ~(IOVP_SIZE-1); /* clear offset bits, just want pagenum */ + iovp &= IOVP_MASK; /* clear offset bits, just want pagenum */ byte_cnt += chain_size; - while (byte_cnt > chain_size) { - WRITE_U32(CMD_TLB_PURGE | iovp, &d->ccio_hpa->io_command); - iovp += chain_size; + while(byte_cnt > chain_size) { + WRITE_U32(CMD_TLB_PURGE | iovp, &ioc->ioc_hpa->io_command); + iovp += chain_size; byte_cnt -= chain_size; - } + } } - -/*********************************************************** +/** + * ccio_mark_invalid - Mark the I/O Pdir entries invalid. + * @ioc: The I/O Controller. + * @iova: The I/O Virtual Address. + * @byte_cnt: The requested number of bytes to be freed from the I/O Pdir. * - * Mark the I/O Pdir entries invalid and blow away the - * corresponding I/O TLB entries. + * Mark the I/O Pdir entries invalid and blow away the corresponding I/O + * TLB entries. * * FIXME: at some threshhold it might be "cheaper" to just blow * away the entire I/O TLB instead of individual entries. @@ -588,25 +550,25 @@ * FIXME: Uturn has 256 TLB entries. We don't need to purge every * PDIR entry - just once for each possible TLB entry. * (We do need to maker I/O PDIR entries invalid regardless). - ***********************************************************/ + * + * FIXME: Can we change byte_cnt to pages_mapped? + */ static CCIO_INLINE void -ccio_mark_invalid(struct ccio_device *d, dma_addr_t iova, size_t byte_cnt) +ccio_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt) { - u32 iovp = (u32) CCIO_IOVP(iova); + u32 iovp = (u32)CCIO_IOVP(iova); size_t saved_byte_cnt; /* round up to nearest page size */ - saved_byte_cnt = byte_cnt = (byte_cnt + IOVP_SIZE - 1) & IOVP_MASK; + saved_byte_cnt = byte_cnt = ROUNDUP(byte_cnt, IOVP_SIZE); - while (byte_cnt > 0) { + while(byte_cnt > 0) { /* invalidate one page at a time */ unsigned int idx = PDIR_INDEX(iovp); - char *pdir_ptr = (char *) &(d->pdir_base[idx]); - - ASSERT( idx < (d->pdir_size/sizeof(u64))); - - pdir_ptr[7] = 0; /* clear only VALID bit */ + char *pdir_ptr = (char *) &(ioc->pdir_base[idx]); + ASSERT(idx < (ioc->pdir_size / sizeof(u64))); + pdir_ptr[7] = 0; /* clear only VALID bit */ /* ** FIXME: PCX_W platforms don't need FDC/SYNC. (eg C360) ** PCX-U/U+ do. (eg C200/C240) @@ -622,232 +584,485 @@ } asm volatile("sync"); - ccio_clear_io_tlb(d, CCIO_IOVP(iova), saved_byte_cnt); + ccio_clear_io_tlb(ioc, CCIO_IOVP(iova), saved_byte_cnt); } - /**************************************************************** ** ** CCIO dma_ops ** *****************************************************************/ -void __init ccio_init(void) -{ - register_driver(ccio_drivers_for); -} - - -static int ccio_dma_supported( struct pci_dev *dev, u64 mask) +/** + * ccio_dma_supported - Verify the IOMMU supports the DMA address range. + * @dev: The PCI device. + * @mask: A bit mask describing the DMA address range of the device. + * + * This function implements the pci_dma_supported function. + */ +static int +ccio_dma_supported(struct pci_dev *dev, u64 mask) { - if (dev == NULL) { - printk(MODULE_NAME ": EISA/ISA/et al not supported\n"); + if(dev == NULL) { + printk(KERN_ERR MODULE_NAME ": EISA/ISA/et al not supported\n"); BUG(); - return(0); + return 0; } dev->dma_mask = mask; /* save it */ /* only support 32-bit devices (ie PCI/GSC) */ - return((int) (mask >= 0xffffffffUL)); + return (int)(mask == 0xffffffffUL); } -/* -** Dump a hex representation of the resource map. -*/ - -#ifdef DUMP_RESMAP -static -void dump_resmap() -{ - struct ccio_device *ioa = ccio_list; - unsigned long *res_ptr = (unsigned long *)ioa->res_map; - unsigned long i = 0; - - printk("res_map: "); - for(; i < (ioa->res_size / sizeof(unsigned long)); ++i, ++res_ptr) - printk("%08lx ", *res_ptr); - - printk("\n"); -} -#endif - -/* -** map_single returns a fully formed IOVA -*/ -static dma_addr_t ccio_map_single(struct pci_dev *dev, void *addr, size_t size, int direction) +/** + * ccio_map_single - Map an address range into the IOMMU. + * @dev: The PCI device. + * @addr: The start address of the DMA region. + * @size: The length of the DMA region. + * @direction: The direction of the DMA transaction (to/from device). + * + * This function implements the pci_map_single function. + */ +static dma_addr_t +ccio_map_single(struct pci_dev *dev, void *addr, size_t size, int direction) { - struct ccio_device *ioa = ccio_list; /* FIXME : see Multi-IOC below */ + int idx; + struct ioc *ioc; + unsigned long flags; dma_addr_t iovp; dma_addr_t offset; u64 *pdir_start; unsigned long hint = hint_lookup[direction]; - int idx; + + ASSERT(dev); + ASSERT(dev->sysdata); + ASSERT(HBA_DATA(dev->sysdata)->iommu); + ioc = GET_IOC(dev); ASSERT(size > 0); /* save offset bits */ - offset = ((dma_addr_t) addr) & ~IOVP_MASK; + offset = ((unsigned long) addr) & ~IOVP_MASK; /* round up to nearest IOVP_SIZE */ - size = (size + offset + IOVP_SIZE - 1) & IOVP_MASK; + size = ROUNDUP(size + offset, IOVP_SIZE); + spin_lock_irqsave(&ioc->res_lock, flags); + +#ifdef CONFIG_PROC_FS + ioc->msingle_calls++; + ioc->msingle_pages += size >> IOVP_SHIFT; +#endif - idx = ccio_alloc_range(ioa, size); - iovp = (dma_addr_t) MKIOVP(idx); + idx = ccio_alloc_range(ioc, (size >> IOVP_SHIFT)); + iovp = (dma_addr_t)MKIOVP(idx); - DBG_RUN(__FUNCTION__ " 0x%p -> 0x%lx", addr, (long) iovp | offset); + pdir_start = &(ioc->pdir_base[idx]); - pdir_start = &(ioa->pdir_base[idx]); + DBG_RUN("%s() 0x%p -> 0x%lx size: %0x%x\n", + __FUNCTION__, addr, (long)iovp | offset, size); /* If not cacheline aligned, force SAFE_DMA on the whole mess */ - if ((size % L1_CACHE_BYTES) || ((unsigned long) addr % L1_CACHE_BYTES)) + if((size % L1_CACHE_BYTES) || ((unsigned long)addr % L1_CACHE_BYTES)) hint |= HINT_SAFE_DMA; - /* round up to nearest IOVP_SIZE */ - size = (size + IOVP_SIZE - 1) & IOVP_MASK; - - while (size > 0) { - + while(size > 0) { ccio_io_pdir_entry(pdir_start, KERNEL_SPACE, addr, hint); DBG_RUN(" pdir %p %08x%08x\n", pdir_start, (u32) (((u32 *) pdir_start)[0]), - (u32) (((u32 *) pdir_start)[1]) - ); + (u32) (((u32 *) pdir_start)[1])); + ++pdir_start; addr += IOVP_SIZE; size -= IOVP_SIZE; - pdir_start++; } + + spin_unlock_irqrestore(&ioc->res_lock, flags); + /* form complete address */ return CCIO_IOVA(iovp, offset); } - -static void ccio_unmap_single(struct pci_dev *dev, dma_addr_t iova, size_t size, int direction) -{ -#ifdef FIXME -/* Multi-IOC (ie N-class) : need to lookup IOC from dev -** o If we can't know about lba PCI data structs, that eliminates ->sysdata. -** o walking up pcidev->parent dead ends at elroy too -** o leaves hashing dev->bus->number into some lookup. -** (may only work for N-class) -*/ - struct ccio_device *ioa = dev->sysdata -#else - struct ccio_device *ioa = ccio_list; -#endif - dma_addr_t offset; +/** + * ccio_unmap_single - Unmap an address range from the IOMMU. + * @dev: The PCI device. + * @addr: The start address of the DMA region. + * @size: The length of the DMA region. + * @direction: The direction of the DMA transaction (to/from device). + * + * This function implements the pci_unmap_single function. + */ +static void +ccio_unmap_single(struct pci_dev *dev, dma_addr_t iova, size_t size, + int direction) +{ + struct ioc *ioc; + unsigned long flags; + dma_addr_t offset = iova & ~IOVP_MASK; - offset = iova & ~IOVP_MASK; - - /* round up to nearest IOVP_SIZE */ - size = (size + offset + IOVP_SIZE - 1) & IOVP_MASK; + ASSERT(dev); + ASSERT(dev->sysdata); + ASSERT(HBA_DATA(dev->sysdata)->iommu); + ioc = GET_IOC(dev); + + DBG_RUN("%s() iovp 0x%lx/%x\n", + __FUNCTION__, (long)iova, size); + + iova ^= offset; /* clear offset bits */ + size += offset; + size = ROUNDUP(size, IOVP_SIZE); - /* Mask off offset */ - iova &= IOVP_MASK; + spin_lock_irqsave(&ioc->res_lock, flags); - DBG_RUN(__FUNCTION__ " iovp 0x%lx\n", (long) iova); - -#ifdef DELAYED_RESOURCE_CNT - if (ioa->saved_cnt < DELAYED_RESOURCE_CNT) { - ioa->saved_iova[ioa->saved_cnt] = iova; - ioa->saved_size[ioa->saved_cnt] = size; - ccio_saved_cnt++; - } else { - do { +#ifdef CONFIG_PROC_FS + ioc->usingle_calls++; + ioc->usingle_pages += size >> IOVP_SHIFT; #endif - ccio_mark_invalid(ioa, iova, size); - ccio_free_range(ioa, iova, size); -#ifdef DELAYED_RESOURCE_CNT - d->saved_cnt--; - iova = ioa->saved_iova[ioa->saved_cnt]; - size = ioa->saved_size[ioa->saved_cnt]; - } while (ioa->saved_cnt) - } -#endif + ccio_mark_invalid(ioc, iova, size); + ccio_free_range(ioc, iova, (size >> IOVP_SHIFT)); + spin_unlock_irqrestore(&ioc->res_lock, flags); } - -static void * ccio_alloc_consistent (struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle) +/** + * ccio_alloc_consistent - Allocate a consistent DMA mapping. + * @dev: The PCI device. + * @size: The length of the DMA region. + * @dma_handle: The DMA address handed back to the device (not the cpu). + * + * This function implements the pci_alloc_consistent function. + */ +static void * +ccio_alloc_consistent(struct pci_dev *dev, size_t size, dma_addr_t *dma_handle) { - void *ret; - unsigned long flags; - struct ccio_device *ioa = ccio_list; - - DBG_RUN(__FUNCTION__ " size 0x%x\n", size); - + void *ret; #if 0 /* GRANT Need to establish hierarchy for non-PCI devs as well ** and then provide matching gsc_map_xxx() functions for them as well. */ - if (!hwdev) { + if(!hwdev) { /* only support PCI */ *dma_handle = 0; return 0; } #endif - spin_lock_irqsave(&ioa->ccio_lock, flags); - ccio_alloc_size += get_order(size); - spin_unlock_irqrestore(&ioa->ccio_lock, flags); - ret = (void *) __get_free_pages(GFP_ATOMIC, get_order(size)); if (ret) { memset(ret, 0, size); - *dma_handle = ccio_map_single(hwdev, ret, size, PCI_DMA_BIDIRECTIONAL); + *dma_handle = ccio_map_single(dev, ret, size, PCI_DMA_BIDIRECTIONAL); } - DBG_RUN(__FUNCTION__ " ret %p\n", ret); return ret; } - -static void ccio_free_consistent (struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle) +/** + * ccio_free_consistent - Free a consistent DMA mapping. + * @dev: The PCI device. + * @size: The length of the DMA region. + * @cpu_addr: The cpu address returned from the ccio_alloc_consistent. + * @dma_handle: The device address returned from the ccio_alloc_consistent. + * + * This function implements the pci_free_consistent function. + */ +static void +ccio_free_consistent(struct pci_dev *dev, size_t size, void *cpu_addr, + dma_addr_t dma_handle) { - unsigned long flags; - struct ccio_device *ioa = ccio_list; + ccio_unmap_single(dev, dma_handle, size, 0); + free_pages((unsigned long)cpu_addr, get_order(size)); +} - spin_lock_irqsave(&ioa->ccio_lock, flags); - ccio_free_size += get_order(size); - spin_unlock_irqrestore(&ioa->ccio_lock, flags); +/* +** Since 0 is a valid pdir_base index value, can't use that +** to determine if a value is valid or not. Use a flag to indicate +** the SG list entry contains a valid pdir index. +*/ +#define PIDE_FLAG 0x80000000UL - ccio_unmap_single(hwdev, dma_handle, size, 0); - free_pages((unsigned long) vaddr, get_order(size)); +/** + * ccio_fill_pdir - Insert coalesced scatter/gather chunks into the I/O Pdir. + * @ioc: The I/O Controller. + * @startsg: The scatter/gather list of coalesced chunks. + * @nents: The number of entries in the scatter/gather list. + * @hint: The DMA Hint. + * + * This function inserts the coalesced scatter/gather list chunks into the + * I/O Controller's I/O Pdir. + */ +static CCIO_INLINE int +ccio_fill_pdir(struct ioc *ioc, struct scatterlist *startsg, int nents, + unsigned long hint) +{ + struct scatterlist *dma_sg = startsg; /* pointer to current DMA */ + int n_mappings = 0; + u64 *pdirp = 0; + unsigned long dma_offset = 0; + + dma_sg--; + while (nents-- > 0) { + int cnt = sg_dma_len(startsg); + sg_dma_len(startsg) = 0; + + DBG_RUN_SG(" %d : %08lx/%05x %p/%05x\n", nents, + (unsigned long)sg_dma_address(startsg), cnt, + startsg->address, startsg->length + ); + + /* + ** Look for the start of a new DMA stream + */ + if(sg_dma_address(startsg) & PIDE_FLAG) { + u32 pide = sg_dma_address(startsg) & ~PIDE_FLAG; + dma_offset = (unsigned long) pide & ~IOVP_MASK; + sg_dma_address(startsg) = 0; + dma_sg++; + sg_dma_address(dma_sg) = pide; + pdirp = &(ioc->pdir_base[pide >> IOVP_SHIFT]); + n_mappings++; + } + + /* + ** Look for a VCONTIG chunk + */ + if (cnt) { + unsigned long vaddr = (unsigned long)startsg->address; + ASSERT(pdirp); + + /* Since multiple Vcontig blocks could make up + ** one DMA stream, *add* cnt to dma_len. + */ + sg_dma_len(dma_sg) += cnt; + cnt += dma_offset; + dma_offset=0; /* only want offset on first chunk */ + cnt = ROUNDUP(cnt, IOVP_SIZE); +#ifdef CONFIG_PROC_FS + ioc->msg_pages += cnt >> IOVP_SHIFT; +#endif + do { + ccio_io_pdir_entry(pdirp, KERNEL_SPACE, + (void *)vaddr, hint); + vaddr += IOVP_SIZE; + cnt -= IOVP_SIZE; + pdirp++; + } while (cnt > 0); + } + startsg++; + } + return(n_mappings); } +/* +** First pass is to walk the SG list and determine where the breaks are +** in the DMA stream. Allocates PDIR entries but does not fill them. +** Returns the number of DMA chunks. +** +** Doing the fill seperate from the coalescing/allocation keeps the +** code simpler. Future enhancement could make one pass through +** the sglist do both. +*/ -static int ccio_map_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction) +static CCIO_INLINE int +ccio_coalesce_chunks(struct ioc *ioc, struct scatterlist *startsg, int nents) { - int tmp = nents; + struct scatterlist *vcontig_sg; /* VCONTIG chunk head */ + unsigned long vcontig_len; /* len of VCONTIG chunk */ + unsigned long vcontig_end; + struct scatterlist *dma_sg; /* next DMA stream head */ + unsigned long dma_offset, dma_len; /* start/len of DMA stream */ + int n_mappings = 0; + + while (nents > 0) { + + /* + ** Prepare for first/next DMA stream + */ + dma_sg = vcontig_sg = startsg; + dma_len = vcontig_len = vcontig_end = startsg->length; + vcontig_end += (unsigned long) startsg->address; + dma_offset = (unsigned long) startsg->address & ~IOVP_MASK; + + /* PARANOID: clear entries */ + sg_dma_address(startsg) = 0; + sg_dma_len(startsg) = 0; + + /* + ** This loop terminates one iteration "early" since + ** it's always looking one "ahead". + */ + while(--nents > 0) { + unsigned long startsg_end; - DBG_RUN(KERN_WARNING __FUNCTION__ " START\n"); + startsg++; + startsg_end = (unsigned long)startsg->address + + startsg->length; + + /* PARANOID: clear entries */ + sg_dma_address(startsg) = 0; + sg_dma_len(startsg) = 0; + + /* + ** First make sure current dma stream won't + ** exceed DMA_CHUNK_SIZE if we coalesce the + ** next entry. + */ + if(ROUNDUP(dma_len + dma_offset + startsg->length, + IOVP_SIZE) > DMA_CHUNK_SIZE) + break; + + /* + ** Append the next transaction? + */ + if(vcontig_end == (unsigned long) startsg->address) { + vcontig_len += startsg->length; + vcontig_end += startsg->length; + dma_len += startsg->length; + continue; + } + + /* + ** Not virtually contigous. + ** Terminate prev chunk. + ** Start a new chunk. + ** + ** Once we start a new VCONTIG chunk, dma_offset + ** can't change. And we need the offset from the first + ** chunk - not the last one. Ergo Successive chunks + ** must start on page boundaries and dove tail + ** with it's predecessor. + */ + sg_dma_len(vcontig_sg) = vcontig_len; + + vcontig_sg = startsg; + vcontig_len = startsg->length; + break; + } - /* KISS: map each buffer seperately. */ - while (nents) { - sg_dma_address(sglist) = ccio_map_single(dev, sglist->address, sglist->length, direction); - sg_dma_len(sglist) = sglist->length; - nents--; - sglist++; + /* + ** End of DMA Stream + ** Terminate last VCONTIG block. + ** Allocate space for DMA stream. + */ + sg_dma_len(vcontig_sg) = vcontig_len; + dma_len = ROUNDUP(dma_len + dma_offset, IOVP_SIZE); + sg_dma_address(dma_sg) = + PIDE_FLAG + | (ccio_alloc_range(ioc, (dma_len >> IOVP_SHIFT)) << IOVP_SHIFT) + | dma_offset; + n_mappings++; } - DBG_RUN(KERN_WARNING __FUNCTION__ " DONE\n"); - return tmp; + return n_mappings; } - -static void ccio_unmap_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction) +/** + * ccio_map_sg - Map the scatter/gather list into the IOMMU. + * @dev: The PCI device. + * @sglist: The scatter/gather list to be mapped in the IOMMU. + * @nents: The number of entries in the scatter/gather list. + * @direction: The direction of the DMA transaction (to/from device). + * + * This function implements the pci_map_sg function. + */ +static int +ccio_map_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, + int direction) { - DBG_RUN(KERN_WARNING __FUNCTION__ " : unmapping %d entries\n", nents); - while (nents) { - ccio_unmap_single(dev, sg_dma_address(sglist), sg_dma_len(sglist), direction); - nents--; - sglist++; + struct ioc *ioc; + int coalesced, filled = 0; + unsigned long flags; + unsigned long hint = hint_lookup[direction]; + + ASSERT(dev); + ASSERT(dev->sysdata); + ASSERT(HBA_DATA(dev->sysdata)->iommu); + ioc = GET_IOC(dev); + + DBG_RUN_SG("%s() START %d entries\n", __FUNCTION__, nents); + + /* Fast path single entry scatterlists. */ + if(nents == 1) { + sg_dma_address(sglist)= ccio_map_single(dev, sglist->address, + sglist->length, + direction); + sg_dma_len(sglist)= sglist->length; + return 1; } - return; + + spin_lock_irqsave(&ioc->res_lock, flags); + +#ifdef CONFIG_PROC_FS + ioc->msg_calls++; +#endif + + /* + ** First coalesce the chunks and allocate I/O pdir space + ** + ** If this is one DMA stream, we can properly map using the + ** correct virtual address associated with each DMA page. + ** w/o this association, we wouldn't have coherent DMA! + ** Access to the virtual address is what forces a two pass algorithm. + */ + coalesced = ccio_coalesce_chunks(ioc, sglist, nents); + + /* + ** Program the I/O Pdir + ** + ** map the virtual addresses to the I/O Pdir + ** o dma_address will contain the pdir index + ** o dma_len will contain the number of bytes to map + ** o address contains the virtual address. + */ + filled = ccio_fill_pdir(ioc, sglist, nents, hint); + + spin_unlock_irqrestore(&ioc->res_lock, flags); + + ASSERT(coalesced == filled); + DBG_RUN_SG("%s() DONE %d mappings\n", __FUNCTION__, filled); + + return filled; } +/** + * ccio_unmap_sg - Unmap the scatter/gather list from the IOMMU. + * @dev: The PCI device. + * @sglist: The scatter/gather list to be unmapped from the IOMMU. + * @nents: The number of entries in the scatter/gather list. + * @direction: The direction of the DMA transaction (to/from device). + * + * This function implements the pci_unmap_sg function. + */ +static void +ccio_unmap_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, + int direction) +{ + struct ioc *ioc; + + ASSERT(dev); + ASSERT(dev->sysdata); + ASSERT(HBA_DATA(dev->sysdata)->iommu); + ioc = GET_IOC(dev); + + DBG_RUN_SG("%s() START %d entries, %p,%x\n", + __FUNCTION__, nents, sglist->address, sglist->length); + +#ifdef CONFIG_PROC_FS + ioc->usg_calls++; +#endif + + while(sg_dma_len(sglist) && nents--) { + +#ifdef CONFIG_PROC_FS + ioc->usg_pages += sg_dma_len(sglist) >> PAGE_SHIFT; +#endif + ccio_unmap_single(dev, sg_dma_address(sglist), + sg_dma_len(sglist), direction); + ++sglist; + } + + DBG_RUN_SG("%s() DONE (nents %d)\n", __FUNCTION__, nents); +} static struct pci_dma_ops ccio_ops = { ccio_dma_supported, @@ -861,6 +1076,201 @@ NULL, /* dma_sync_sg : ditto */ }; +#ifdef CONFIG_PROC_FS +static int proc_append(char *src, int len, char **dst, off_t *offset, int *max) +{ + if (len < *offset) { + *offset -= len; + return 0; + } + if (*offset > 0) { + src += *offset; + len -= *offset; + *offset = 0; + } + if (len > *max) { + len = *max; + } + memcpy(*dst, src, len); + *dst += len; + *max -= len; + return (*max == 0); +} + +static int ccio_proc_info(char *buf, char **start, off_t offset, int count, + int *eof, void *data) +{ + int max = count; + char tmp[80]; /* width of an ANSI-standard terminal */ + struct ioc *ioc = ioc_list; + + while (ioc != NULL) { + unsigned int total_pages = ioc->res_size << 3; + unsigned long avg = 0, min, max; + int j, len; + + len = sprintf(tmp, "%s\n", ioc->name); + if (proc_append(tmp, len, &buf, &offset, &count)) + break; + + len = sprintf(tmp, "Cujo 2.0 bug : %s\n", + (ioc->cujo20_bug ? "yes" : "no")); + if (proc_append(tmp, len, &buf, &offset, &count)) + break; + + len = sprintf(tmp, "IO PDIR size : %d bytes (%d entries)\n", + total_pages * 8, total_pages); + if (proc_append(tmp, len, &buf, &offset, &count)) + break; + + len = sprintf(tmp, "IO PDIR entries : %ld free %ld used (%d%%)\n", + total_pages - ioc->used_pages, ioc->used_pages, + (int)(ioc->used_pages * 100 / total_pages)); + if (proc_append(tmp, len, &buf, &offset, &count)) + break; + + len = sprintf(tmp, "Resource bitmap : %d bytes (%d pages)\n", + ioc->res_size, total_pages); + if (proc_append(tmp, len, &buf, &offset, &count)) + break; + + min = max = ioc->avg_search[0]; + for(j = 0; j < CCIO_SEARCH_SAMPLE; ++j) { + avg += ioc->avg_search[j]; + if(ioc->avg_search[j] > max) + max = ioc->avg_search[j]; + if(ioc->avg_search[j] < min) + min = ioc->avg_search[j]; + } + avg /= CCIO_SEARCH_SAMPLE; + len = sprintf(tmp, " Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n", + min, avg, max); + if (proc_append(tmp, len, &buf, &offset, &count)) + break; + + len = sprintf(tmp, "pci_map_single(): %8ld calls %8ld pages (avg %d/1000)\n", + ioc->msingle_calls, ioc->msingle_pages, + (int)((ioc->msingle_pages * 1000)/ioc->msingle_calls)); + if (proc_append(tmp, len, &buf, &offset, &count)) + break; + + + /* KLUGE - unmap_sg calls unmap_single for each mapped page */ + min = ioc->usingle_calls - ioc->usg_calls; + max = ioc->usingle_pages - ioc->usg_pages; + len = sprintf(tmp, "pci_unmap_single: %8ld calls %8ld pages (avg %d/1000)\n", + min, max, (int)((max * 1000)/min)); + if (proc_append(tmp, len, &buf, &offset, &count)) + break; + + len = sprintf(tmp, "pci_map_sg() : %8ld calls %8ld pages (avg %d/1000)\n", + ioc->msg_calls, ioc->msg_pages, + (int)((ioc->msg_pages * 1000)/ioc->msg_calls)); + if (proc_append(tmp, len, &buf, &offset, &count)) + break; + len = sprintf(tmp, "pci_unmap_sg() : %8ld calls %8ld pages (avg %d/1000)\n\n\n", + ioc->usg_calls, ioc->usg_pages, + (int)((ioc->usg_pages * 1000)/ioc->usg_calls)); + if (proc_append(tmp, len, &buf, &offset, &count)) + break; + + ioc = ioc->next; + } + + if (count == 0) { + *eof = 1; + } + return (max - count); +} + +static int ccio_resource_map(char *buf, char **start, off_t offset, int len, + int *eof, void *data) +{ + struct ioc *ioc = ioc_list; + + buf[0] = '\0'; + while (ioc != NULL) { + u32 *res_ptr = (u32 *)ioc->res_map; + int j; + + for (j = 0; j < (ioc->res_size / sizeof(u32)); j++) { + if ((j & 7) == 0) + strcat(buf,"\n "); + sprintf(buf, "%s %08x", buf, *res_ptr); + res_ptr++; + } + strcat(buf, "\n\n"); + ioc = ioc->next; + break; /* XXX - remove me */ + } + + return strlen(buf); +} +#endif + +/** + * ccio_find_ioc - Find the ioc in the ioc_list + * @hw_path: The hardware path of the ioc. + * + * This function searches the ioc_list for an ioc that matches + * the provide hardware path. + */ +static struct ioc * ccio_find_ioc(int hw_path) +{ + int i; + struct ioc *ioc; + + ioc = ioc_list; + for (i = 0; i < ioc_count; i++) { + if (ioc->hw_path == hw_path) + return ioc; + + ioc = ioc->next; + } + + return NULL; +} + +/** + * ccio_get_iommu - Find the iommu which controls this device + * @dev: The parisc device. + * + * This function searches through the registerd IOMMU's and returns the + * appropriate IOMMU for the device based upon the devices hardware path. + */ +void * ccio_get_iommu(const struct parisc_device *dev) +{ + dev = find_pa_parent_type(dev, HPHW_IOA); + if (!dev) + return NULL; + + return ccio_find_ioc(dev->hw_path); +} + +#define CUJO_20_STEP 0x10000000 /* inc upper nibble */ + +/* Cujo 2.0 has a bug which will silently corrupt data being transferred + * to/from certain pages. To avoid this happening, we mark these pages + * as `used', and ensure that nothing will try to allocate from them. + */ +void ccio_cujo20_fixup(struct parisc_device *dev, u32 iovp) +{ + unsigned int idx; + struct ioc *ioc = ccio_get_iommu(dev); + u8 *res_ptr; + +#ifdef CONFIG_PROC_FS + ioc->cujo20_bug = 1; +#endif + res_ptr = ioc->res_map; + idx = PDIR_INDEX(iovp) >> 3; + + while (idx < ioc->res_size) { + res_ptr[idx] |= 0xff; + idx += PDIR_INDEX(CUJO_20_STEP) >> 3; + } +} + #if 0 /* GRANT - is this needed for U2 or not? */ @@ -875,38 +1285,37 @@ ** I think only Java (K/D/R-class too?) systems don't do this. */ static int -ccio_get_iotlb_size(struct hp_device *d) +ccio_get_iotlb_size(struct parisc_device *dev) { - if(d->spa_shift == 0) { - panic(__FUNCTION__ ": Can't determine I/O TLB size.\n"); + if (dev->spa_shift == 0) { + panic("%s() : Can't determine I/O TLB size.\n", __FUNCTION__); } - return(1 << d->spa_shift); + return (1 << dev->spa_shift); } #else /* Uturn supports 256 TLB entries */ #define CCIO_CHAINID_SHIFT 8 #define CCIO_CHAINID_MASK 0xff - #endif /* 0 */ - -/* -** Figure out how big the I/O PDIR should be and alloc it. -** Also sets variables which depend on pdir size. -*/ +/** + * ccio_ioc_init - Initalize the I/O Controller + * @ioc: The I/O Controller. + * + * Initalize the I/O Controller which includes setting up the + * I/O Page Directory, the resource map, and initalizing the + * U2/Uturn chip into virtual mode. + */ static void -ccio_alloc_pdir(struct ccio_device *ioa) +ccio_ioc_init(struct ioc *ioc) { - extern unsigned long mem_max; /* arch.../setup.c */ - - u32 iova_space_size = 0; - void * pdir_base; - int pdir_size, iov_order; + int i, iov_order; + u32 iova_space_size; + unsigned long physmem; /* ** Determine IOVA Space size from memory size. - ** Using "mem_max" is a kluge. ** ** Ideally, PCI drivers would register the maximum number ** of DMA they can have outstanding for each device they @@ -915,15 +1324,18 @@ ** methods still require some "extra" to support PCI ** Hot-Plug/Removal of PCI cards. (aka PCI OLARD). */ + /* limit IOVA space size to 1MB-1GB */ - if (mem_max < (ccio_mem_ratio*1024*1024)) { - iova_space_size = 1024*1024; + + physmem = num_physpages << PAGE_SHIFT; + if(physmem < (ccio_mem_ratio * 1024 * 1024)) { + iova_space_size = 1024 * 1024; #ifdef __LP64__ - } else if (mem_max > (ccio_mem_ratio*512*1024*1024)) { - iova_space_size = 512*1024*1024; + } else if(physmem > (ccio_mem_ratio * 512 * 1024 * 1024)) { + iova_space_size = 512 * 1024 * 1024; #endif } else { - iova_space_size = (u32) (mem_max/ccio_mem_ratio); + iova_space_size = (u32)(physmem / ccio_mem_ratio); } /* @@ -933,277 +1345,271 @@ /* We could use larger page sizes in order to *decrease* the number ** of mappings needed. (ie 8k pages means 1/2 the mappings). - ** + ** ** Note: Grant Grunder says "Using 8k I/O pages isn't trivial either ** since the pages must also be physically contiguous - typically ** this is the case under linux." */ - iov_order = get_order(iova_space_size); + iov_order = get_order(iova_space_size) >> (IOVP_SHIFT - PAGE_SHIFT); ASSERT(iov_order <= (30 - IOVP_SHIFT)); /* iova_space_size <= 1GB */ ASSERT(iov_order >= (20 - IOVP_SHIFT)); /* iova_space_size >= 1MB */ iova_space_size = 1 << (iov_order + IOVP_SHIFT); - ioa->pdir_size = pdir_size = (iova_space_size/IOVP_SIZE) * sizeof(u64); + ioc->pdir_size = (iova_space_size / IOVP_SIZE) * sizeof(u64); - ASSERT(pdir_size < 4*1024*1024); /* max pdir size < 4MB */ + ASSERT(ioc->pdir_size < 4 * 1024 * 1024); /* max pdir size < 4MB */ /* Verify it's a power of two */ - ASSERT((1 << get_order(pdir_size)) == (pdir_size >> PAGE_SHIFT)); + ASSERT((1 << get_order(ioc->pdir_size)) == (ioc->pdir_size >> PAGE_SHIFT)); - DBG_INIT(__FUNCTION__ " hpa 0x%p mem %dMB IOV %dMB (%d bits)\n PDIR size 0x%0x", - ioa->ccio_hpa, (int) (mem_max>>20), iova_space_size>>20, - iov_order + PAGE_SHIFT, pdir_size); - - ioa->pdir_base = - pdir_base = (void *) __get_free_pages(GFP_KERNEL, get_order(pdir_size)); - if (NULL == pdir_base) - { - panic(__FILE__ ":" __FUNCTION__ "() could not allocate I/O Page Table\n"); + DBG_INIT("%s() hpa 0x%p mem %luMB IOV %dMB (%d bits) PDIR size 0x%0x", + __FUNCTION__, ioc->ioc_hpa, physmem>>20, iova_space_size>>20, + iov_order + PAGE_SHIFT, ioc->pdir_size); + + ioc->pdir_base = (u64 *)__get_free_pages(GFP_KERNEL, + get_order(ioc->pdir_size)); + if(NULL == ioc->pdir_base) { + panic(__FILE__ ":%s() could not allocate I/O Page Table\n", __FUNCTION__); } - memset(pdir_base, 0, pdir_size); + memset(ioc->pdir_base, 0, ioc->pdir_size); - ASSERT((((unsigned long) pdir_base) & PAGE_MASK) == (unsigned long) pdir_base); + ASSERT((((unsigned long)ioc->pdir_base) & PAGE_MASK) == (unsigned long)ioc->pdir_base); + DBG_INIT(" base %p", ioc->pdir_base); - DBG_INIT(" base %p", pdir_base); + /* resource map size dictated by pdir_size */ + ioc->res_size = (ioc->pdir_size / sizeof(u64)) >> 3; + DBG_INIT("%s() res_size 0x%x\n", __FUNCTION__, ioc->res_size); + + ioc->res_map = (u8 *)__get_free_pages(GFP_KERNEL, + get_order(ioc->res_size)); + if(NULL == ioc->res_map) { + panic(__FILE__ ":%s() could not allocate resource map\n", __FUNCTION__); + } + memset(ioc->res_map, 0, ioc->res_size); + + /* Initialize the res_hint to 16 */ + ioc->res_hint = 16; + + /* Initialize the spinlock */ + spin_lock_init(&ioc->res_lock); /* ** Chainid is the upper most bits of an IOVP used to determine ** which TLB entry an IOVP will use. */ - ioa->chainid_shift = get_order(iova_space_size)+PAGE_SHIFT-CCIO_CHAINID_SHIFT; - - DBG_INIT(" chainid_shift 0x%x\n", ioa->chainid_shift); -} - - -static void -ccio_hw_init(struct ccio_device *ioa) -{ - int i; + ioc->chainid_shift = get_order(iova_space_size) + PAGE_SHIFT - CCIO_CHAINID_SHIFT; + DBG_INIT(" chainid_shift 0x%x\n", ioc->chainid_shift); /* ** Initialize IOA hardware */ - WRITE_U32(CCIO_CHAINID_MASK << ioa->chainid_shift, &ioa->ccio_hpa->io_chain_id_mask); - WRITE_U32(virt_to_phys(ioa->pdir_base), &ioa->ccio_hpa->io_pdir_base); + WRITE_U32(CCIO_CHAINID_MASK << ioc->chainid_shift, + &ioc->ioc_hpa->io_chain_id_mask); + WRITE_U32(virt_to_phys(ioc->pdir_base), + &ioc->ioc_hpa->io_pdir_base); /* ** Go to "Virtual Mode" */ - WRITE_U32(IOA_NORMAL_MODE, &ioa->ccio_hpa->io_control); + WRITE_U32(IOA_NORMAL_MODE, &ioc->ioc_hpa->io_control); /* ** Initialize all I/O TLB entries to 0 (Valid bit off). */ - WRITE_U32(0, &ioa->ccio_hpa->io_tlb_entry_m); - WRITE_U32(0, &ioa->ccio_hpa->io_tlb_entry_l); + WRITE_U32(0, &ioc->ioc_hpa->io_tlb_entry_m); + WRITE_U32(0, &ioc->ioc_hpa->io_tlb_entry_l); - for (i = 1 << CCIO_CHAINID_SHIFT; i ; i--) { - WRITE_U32((CMD_TLB_DIRECT_WRITE | (i << ioa->chainid_shift)), - &ioa->ccio_hpa->io_command); + for(i = 1 << CCIO_CHAINID_SHIFT; i ; i--) { + WRITE_U32((CMD_TLB_DIRECT_WRITE | (i << ioc->chainid_shift)), + &ioc->ioc_hpa->io_command); } - } - static void -ccio_resmap_init(struct ccio_device *ioa) +ccio_init_resource(struct resource *res, char *name, unsigned long ioaddr) { - u32 res_size; - - /* - ** Ok...we do more than just init resource map - */ - ioa->ccio_lock = SPIN_LOCK_UNLOCKED; + int result; - ioa->res_hint = 16; /* next available IOVP - circular search */ - - /* resource map size dictated by pdir_size */ - res_size = ioa->pdir_size/sizeof(u64); /* entries */ - res_size >>= 3; /* convert bit count to byte count */ - DBG_INIT(__FUNCTION__ "() res_size 0x%x\n", res_size); - - ioa->res_size = res_size; - ioa->res_map = (char *) __get_free_pages(GFP_KERNEL, get_order(res_size)); - if (NULL == ioa->res_map) - { - panic(__FILE__ ":" __FUNCTION__ "() could not allocate resource map\n"); + res->flags = IORESOURCE_MEM; + res->start = (unsigned long)(signed) __raw_readl(ioaddr) << 16; + res->end = (unsigned long)(signed) (__raw_readl(ioaddr + 4) << 16) - 1; + if (res->end + 1 == res->start) + return; + res->name = name; + result = request_resource(&iomem_resource, res); + if (result < 0) { + printk(KERN_ERR + "%s: failed to claim CCIO bus address space (%p,%p)\n", + __FILE__, res->start, res->end); } - memset(ioa->res_map, 0, res_size); } -/* CUJO20 KLUDGE start */ -static struct { - u16 hversion; - u8 spa; - u8 type; - u32 foo[3]; /* 16 bytes total */ -} cujo_iodc __attribute__ ((aligned (64))); -static unsigned long cujo_result[32] __attribute__ ((aligned (16))) = {0,0,0,0}; +static void __init ccio_init_resources(struct ioc *ioc) +{ + struct resource *res = ioc->mmio_region; + char *name = kmalloc(14, GFP_KERNEL); -/* -** CUJO 2.0 incorrectly decodes a memory access for specific -** pages (every page at specific iotlb locations dependent -** upon where the cujo is flexed - diff on raven/firehawk. -** resulting in an hpmc and/or silent data corruption. -** Workaround is to prevent use of those I/O TLB entries -** by marking the suspect bitmap range entries as busy. -*/ -static void -ccio_cujo20_hack(struct ccio_device *ioa) + sprintf(name, "GSC Bus [%d/]", ioc->hw_path); + + ccio_init_resource(res, name, (unsigned long)&ioc->ioc_hpa->io_io_low); + ccio_init_resource(res + 1, name, + (unsigned long)&ioc->ioc_hpa->io_io_low_hv); +} + +static void expand_ioc_area(struct ioc *ioc, unsigned long size, + unsigned long min, unsigned long max, unsigned long align) { - unsigned long status; - unsigned int idx; - u8 *res_ptr = ioa->res_map; - u32 iovp=0x0; - unsigned long mask; +#ifdef NASTY_HACK_FOR_K_CLASS + __raw_writel(0xfffff600, (unsigned long)&(ioc->ioc_hpa->io_io_high)); + ioc->mmio_region[0].end = 0xf5ffffff; +#endif +} - status = pdc_iodc_read( &cujo_result, (void *) CUJO_RAVEN_LOC, 0, &cujo_iodc, 16); - if (status == 0) { - if (cujo_iodc.hversion==CUJO_20_BADHVERS) - iovp = CUJO_20_BADPAGE1; +static struct resource *ccio_get_resource(struct ioc* ioc, + const struct parisc_device *dev) +{ + if (!ioc) { + return &iomem_resource; + } else if ((ioc->mmio_region->start <= dev->hpa) && + (dev->hpa < ioc->mmio_region->end)) { + return ioc->mmio_region; + } else if (((ioc->mmio_region + 1)->start <= dev->hpa) && + (dev->hpa < (ioc->mmio_region + 1)->end)) { + return ioc->mmio_region + 1; } else { - status = pdc_iodc_read( &cujo_result, (void *) CUJO_FIREHAWK_LOC, 0, &cujo_iodc, 16); - if (status == 0) { - if (cujo_iodc.hversion==CUJO_20_BADHVERS) - iovp = CUJO_20_BADPAGE2; - } else { - /* not a defective system */ - return; - } + return NULL; } +} - printk(MODULE_NAME ": Cujo 2.0 bug needs a work around\n"); - ccio_cujo_bug = 1; +int ccio_allocate_resource(const struct parisc_device *dev, + struct resource *res, unsigned long size, + unsigned long min, unsigned long max, unsigned long align, + void (*alignf)(void *, struct resource *, unsigned long), + void *alignf_data) +{ + struct ioc *ioc = ccio_get_iommu(dev); + struct resource *parent = ccio_get_resource(ioc, dev); + if (!parent) + return -EBUSY; - /* - ** mark bit entries that match "bad page" - */ - idx = PDIR_INDEX(iovp)>>3; - mask = 0xff; - - while(idx * sizeof(u8) < ioa->res_size) { - res_ptr[idx] |= mask; - idx += (PDIR_INDEX(CUJO_20_STEP)>>3); - ccio_used_pages += 8; - ccio_used_bytes += 1; - } + if (!allocate_resource(parent, res, size, min, max, align, alignf, + alignf_data)) + return 0; + + expand_ioc_area(ioc, size, min, max, align); + return allocate_resource(parent, res, size, min, max, align, alignf, + alignf_data); } -/* CUJO20 KLUDGE end */ -#ifdef CONFIG_PROC_FS -static int ccio_proc_info(char *buf, char **start, off_t offset, int len) +int ccio_request_resource(const struct parisc_device *dev, + struct resource *res) { - unsigned long i = 0; - struct ccio_device *ioa = ccio_list; - unsigned long *res_ptr = (unsigned long *)ioa->res_map; - unsigned long total_pages = ioa->res_size << 3; /* 8 bits per byte */ - - sprintf(buf, "%s\nCujo 2.0 bug : %s\n", - parisc_getHWdescription(ioa->iodc->hw_type, ioa->iodc->hversion, - ioa->iodc->sversion), - (ccio_cujo_bug ? "yes" : "no")); - - sprintf(buf, "%sIO pdir size : %d bytes (%d entries)\n", - buf, ((ioa->res_size << 3) * sizeof(u64)), /* 8 bits per byte */ - ioa->res_size << 3); /* 8 bits per byte */ + struct ioc *ioc = ccio_get_iommu(dev); + struct resource *parent = ccio_get_resource(ioc, dev); + + return request_resource(parent, res); +} +/** + * ccio_probe - Determine if ccio should claim this device. + * @dev: The device which has been found + * + * Determine if ccio should claim this chip (return 0) or not (return 1). + * If so, initialize the chip and tell other partners in crime they + * have work to do. + */ +static int ccio_probe(struct parisc_device *dev) +{ + int i; + struct ioc *ioc, **ioc_p = &ioc_list; - sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n", - buf, ioa->res_size, ioa->res_size << 3); /* 8 bits per byte */ + ioc = kmalloc(sizeof(struct ioc), GFP_KERNEL); + if (ioc == NULL) { + printk(KERN_ERR MODULE_NAME ": memory allocation failure\n"); + return 1; + } + memset(ioc, 0, sizeof(struct ioc)); - strcat(buf, " total: free: used: % used:\n"); - sprintf(buf, "%sblocks %8d %8ld %8ld %8ld%%\n", buf, ioa->res_size, - ioa->res_size - ccio_used_bytes, ccio_used_bytes, - (ccio_used_bytes * 100) / ioa->res_size); - - sprintf(buf, "%spages %8ld %8ld %8ld %8ld%%\n", buf, total_pages, - total_pages - ccio_used_pages, ccio_used_pages, - (ccio_used_pages * 100 / total_pages)); + ioc->name = dev->id.hversion == U2_IOA_RUNWAY ? "U2" : "UTurn"; - sprintf(buf, "%sconsistent %8ld %8ld\n", buf, - ccio_alloc_size, ccio_free_size); - - strcat(buf, "\nResource bitmap:\n"); + printk(KERN_INFO "Found %s at 0x%lx\n", ioc->name, dev->hpa); - for(; i < (ioa->res_size / sizeof(unsigned long)); ++i, ++res_ptr) - len += sprintf(buf, "%s%08lx ", buf, *res_ptr); + for (i = 0; i < ioc_count; i++) { + ioc_p = &(*ioc_p)->next; + } + *ioc_p = ioc; - strcat(buf, "\n"); - return strlen(buf); + ioc->hw_path = dev->hw_path; + ioc->ioc_hpa = (struct ioa_registers *)dev->hpa; + ccio_ioc_init(ioc); + ccio_init_resources(ioc); + hppa_dma_ops = &ccio_ops; + + if (ioc_count == 0) { + /* XXX: Create separate entries for each ioc */ + create_proc_read_entry(MODULE_NAME, S_IRWXU, proc_runway_root, + ccio_proc_info, NULL); + create_proc_read_entry(MODULE_NAME"-bitmap", S_IRWXU, + proc_runway_root, ccio_resource_map, NULL); + } + + ioc_count++; + return 0; } -#endif -/* -** Determine if ccio should claim this chip (return 0) or not (return 1). -** If so, initialize the chip and tell other partners in crime they -** have work to do. -*/ -static int -ccio_driver_callback(struct hp_device *d, struct pa_iodc_driver *dri) +struct pci_dev * ccio_get_fake(const struct parisc_device *dev) { - struct ccio_device *ioa; + struct ioc *ioc; - printk("%s found %s at 0x%p\n", dri->name, dri->version, d->hpa); + dev = find_pa_parent_type(dev, HPHW_IOA); + if(!dev) + return NULL; - if (ccio_list) { - printk(MODULE_NAME ": already initialized one device\n"); - return(0); - } + ioc = ccio_find_ioc(dev->hw_path); + if(!ioc) + return NULL; - ioa = kmalloc(sizeof(struct ccio_device), GFP_KERNEL); - if (NULL == ioa) - { - printk(MODULE_NAME " - couldn't alloc ccio_device\n"); - return(1); - } - memset(ioa, 0, sizeof(struct ccio_device)); + if(ioc->fake_pci_dev) + return ioc->fake_pci_dev; - /* - ** ccio list is used mainly as a kluge to support a single instance. - ** Eventually, with core dumps, it'll be useful for debugging. - */ - ccio_list = ioa; - ioa->iodc = d; + ioc->fake_pci_dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL); + if(ioc->fake_pci_dev == NULL) { + printk(KERN_ERR MODULE_NAME ": memory allocation failure\n"); + return NULL; + } + memset(ioc->fake_pci_dev, 0, sizeof(struct pci_dev)); -#if 1 -/* KLUGE: determine IOA hpa based on GSC port value. -** Needed until we have a PA bus walk. Can only discover IOA via -** walking the architected PA MMIO space as described by the I/O ACD. -** "Legacy" PA Firmware only tells us about unarchitected devices -** that can't be detected by PA/EISA/PCI bus walks. -*/ - switch((long) d->hpa) { - case 0xf3fbf000L: /* C110 IOA0 LBC (aka GSC port) */ - /* ccio_hpa same as C200 IOA0 */ - case 0xf203f000L: /* C180/C200/240/C360 IOA0 LBC (aka GSC port) */ - ioa->ccio_hpa = (struct ioa_registers *) 0xfff88000L; - break; - case 0xf103f000L: /* C180/C200/240/C360 IOA1 LBC (aka GSC port) */ - ioa->ccio_hpa = (struct ioa_registers *) 0xfff8A000L; - break; - default: - panic("ccio-dma.c doesn't know this GSC port Address!\n"); - break; - }; -#else - ioa->ccio_hpa = d->hpa; -#endif + ioc->fake_pci_dev->sysdata = kmalloc(sizeof(struct pci_hba_data), GFP_KERNEL); + if(ioc->fake_pci_dev->sysdata == NULL) { + printk(KERN_ERR MODULE_NAME ": memory allocation failure\n"); + return NULL; + } - ccio_alloc_pdir(ioa); - ccio_hw_init(ioa); - ccio_resmap_init(ioa); + HBA_DATA(ioc->fake_pci_dev->sysdata)->iommu = ioc; + return ioc->fake_pci_dev; +} - /* CUJO20 KLUDGE start */ - ccio_cujo20_hack(ioa); - /* CUJO20 KLUDGE end */ +/* We *can't* support JAVA (T600). Venture there at your own risk. */ +static struct parisc_device_id ccio_tbl[] = { + { HPHW_IOA, HVERSION_REV_ANY_ID, U2_IOA_RUNWAY, 0xb }, /* U2 */ + { HPHW_IOA, HVERSION_REV_ANY_ID, UTURN_IOA_RUNWAY, 0xb }, /* UTurn */ + { 0, } +}; - hppa_dma_ops = &ccio_ops; +static struct parisc_driver ccio_driver = { + name: "U2/Uturn", + id_table: ccio_tbl, + probe: ccio_probe, +}; - create_proc_info_entry(MODULE_NAME, 0, proc_runway_root, ccio_proc_info); - return(0); +/** + * ccio_init - ccio initalization procedure. + * + * Register this driver. + */ +void __init ccio_init(void) +{ + register_parisc_driver(&ccio_driver); } - - diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/ccio-rm-dma.c linux.19rc3-ac4/arch/parisc/kernel/ccio-rm-dma.c --- linux.19rc3/arch/parisc/kernel/ccio-rm-dma.c 2002-07-29 12:50:06.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/ccio-rm-dma.c 2002-07-29 13:58:36.000000000 +0100 @@ -56,26 +56,6 @@ #define UTURN_IOA_RUNWAY 0x581 #define UTURN_BC_GSC 0x502 -static int ccio_driver_callback(struct hp_device *, struct pa_iodc_driver *); - -static struct pa_iodc_driver ccio_drivers_for[] = { - - {HPHW_BCPORT, U2_BC_GSC, 0x0, 0xb, 0, 0x10, - DRIVER_CHECK_HVERSION + - DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE, - MODULE_NAME, "U2 I/O MMU", (void *) ccio_driver_callback}, - - {HPHW_BCPORT, UTURN_BC_GSC, 0x0, 0xb, 0, 0x10, - DRIVER_CHECK_HVERSION + - DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE, - MODULE_NAME, "Uturn I/O MMU", (void *) ccio_driver_callback}, - - {0,0,0,0,0,0, - 0, - (char *) NULL, (char *) NULL, (void *) NULL } -}; - - #define IS_U2(id) ( \ (((id)->hw_type == HPHW_IOA) && ((id)->hversion == U2_IOA_RUNWAY)) || \ (((id)->hw_type == HPHW_BCPORT) && ((id)->hversion == U2_BC_GSC)) \ @@ -86,17 +66,10 @@ (((id)->hw_type == HPHW_BCPORT) && ((id)->hversion == UTURN_BC_GSC)) \ ) - -void __init ccio_init(void) -{ - register_driver(ccio_drivers_for); -} - - static int ccio_dma_supported( struct pci_dev *dev, u64 mask) { if (dev == NULL) { - printk(MODULE_NAME ": EISA/ISA/et al not supported\n"); + printk(KERN_ERR MODULE_NAME ": EISA/ISA/et al not supported\n"); BUG(); return(0); } @@ -182,8 +155,6 @@ ccio_unmap_sg, NULL, /* dma_sync_single : NOP for U2 */ NULL, /* dma_sync_sg : ditto */ - - }; @@ -193,9 +164,11 @@ ** have work to do. */ static int -ccio_driver_callback(struct hp_device *d, struct pa_iodc_driver *dri) +ccio_probe(struct parisc_device *dev) { - printk("%s found %s at 0x%p\n", dri->name, dri->version, d->hpa); + printk(KERN_INFO "%s found %s at 0x%lx\n", MODULE_NAME, + dev->id.hversion == U2_BC_GSC ? "U2" : "UTurn", + dev->hpa); /* ** FIXME - should check U2 registers to verify it's really running @@ -210,3 +183,20 @@ hppa_dma_ops = &ccio_ops; return 0; } + +static struct parisc_device_id ccio_tbl[] = { + { HPHW_BCPORT, HVERSION_REV_ANY_ID, U2_BC_GSC, 0xc }, + { HPHW_BCPORT, HVERSION_REV_ANY_ID, UTURN_BC_GSC, 0xc }, + { 0, } +}; + +static struct parisc_driver ccio_driver = { + name: "U2/Uturn", + id_table: ccio_tbl, + probe: ccio_probe, +}; + +void __init ccio_init(void) +{ + register_parisc_driver(&ccio_driver); +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/drivers.c linux.19rc3-ac4/arch/parisc/kernel/drivers.c --- linux.19rc3/arch/parisc/kernel/drivers.c 2002-07-29 12:50:06.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/drivers.c 2002-07-29 13:58:36.000000000 +0100 @@ -1,134 +1,591 @@ /* - -drivers.c - -Copyright (c) 1999 The Puffin Group - -This is a collection of routines intended to register all the devices -in a system, and register device drivers. - -*/ + * drivers.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Copyright (c) 1999 The Puffin Group + * Copyright (c) 2001 Matthew Wilcox for Hewlett Packard + * Copyright (c) 2001 Helge Deller + * + * The file handles registering devices and drivers, then matching them. + * It's the closest we get to a dating agency. + */ #include #include #include +#include +#include +#include #include #include #include +#include +/* See comments in include/asm-parisc/pci.h */ +struct pci_dma_ops *hppa_dma_ops; -extern struct hp_hardware *parisc_get_reference( - unsigned short hw_type, unsigned long hversion, - unsigned long sversion ); +static struct parisc_driver *pa_drivers; +static struct parisc_device root; +/* This lock protects the pa_drivers list _only_ since all parisc_devices + * are registered before smp_init() is called. If you wish to add devices + * after that, this muct be serialised somehow. I recommend a semaphore + * rather than a spinlock since driver ->probe functions are allowed to + * sleep (for example when allocating memory). + */ +static spinlock_t pa_lock = SPIN_LOCK_UNLOCKED; -/* I'm assuming there'll never be 64 devices. We should probably make - this more flexible. */ +#define for_each_padev(dev) \ + for (dev = root.child; dev != NULL; dev = next_dev(dev)) -#define MAX_DEVICES 64 +#define check_dev(dev) \ + (dev->id.hw_type != HPHW_FAULTY) ? dev : next_dev(dev) -unsigned int num_devices = 0; +/** + * next_dev - enumerates registered devices + * @dev: the previous device returned from next_dev + * + * next_dev does a depth-first search of the tree, returning parents + * before children. Returns NULL when there are no more devices. + */ +struct parisc_device *next_dev(struct parisc_device *dev) +{ + if (dev->child) { + return check_dev(dev->child); + } else if (dev->sibling) { + return dev->sibling; + } -struct hp_device devices[MAX_DEVICES]; + /* Exhausted tree at this level, time to go up. */ + do { + dev = dev->parent; + if (dev && dev->sibling) + return dev->sibling; + } while (dev != &root); -static unsigned long pdc_result[32] __attribute__ ((aligned (16))) = {0,0,0,0}; -static u8 iodc_data[32] __attribute__ ((aligned (64))); + return NULL; +} -/* - * XXX should we be using a locked array ? +/** + * match_device - Report whether this driver can handle this device + * @driver: the PA-RISC driver to try + * @dev: the PA-RISC device to try */ - -int register_driver(struct pa_iodc_driver *driver) +static int match_device(struct parisc_driver *driver, struct parisc_device *dev) { - unsigned int i; - struct hp_device * device; + const struct parisc_device_id *ids; - for (;driver->check;driver++) { + for (ids = driver->id_table; ids->sversion; ids++) { + if ((ids->sversion != SVERSION_ANY_ID) && + (ids->sversion != dev->id.sversion)) + continue; + + if ((ids->hw_type != HWTYPE_ANY_ID) && + (ids->hw_type != dev->id.hw_type)) + continue; + + if ((ids->hversion != HVERSION_ANY_ID) && + (ids->hversion != dev->id.hversion)) + continue; - for (i=0;imanaged) continue; +static void claim_device(struct parisc_driver *driver, struct parisc_device *dev) +{ + dev->driver = driver; + request_mem_region(dev->hpa, 0x1000, driver->name); +} - if ((driver->check & DRIVER_CHECK_HWTYPE) && - (driver->hw_type != device->hw_type)) - continue; - if ((driver->check & DRIVER_CHECK_HVERSION) && - (driver->hversion != device->hversion)) - continue; - if ((driver->check & DRIVER_CHECK_HVERSION_REV) && - (driver->hversion_rev != device->hversion_rev)) - continue; - if ((driver->check & DRIVER_CHECK_SVERSION) && - (driver->sversion != device->sversion)) - continue; - if ((driver->check & DRIVER_CHECK_SVERSION_REV) && - (driver->sversion_rev != device->sversion_rev)) - continue; - if ((driver->check & DRIVER_CHECK_OPT) && - (driver->opt != device->opt)) - continue; - if ( (*driver->callback)(device,driver) ==0) { - device->managed=1; - } else { - printk("Warning : device (%d, 0x%x, 0x%x, 0x%x, 0x%x) NOT claimed by %s %s\n", - device->hw_type, - device->hversion, device->hversion_rev, - device->sversion, device->sversion_rev, - driver->name, driver->version); - } +/** + * register_parisc_driver - Register this driver if it can handle a device + * @driver: the PA-RISC driver to try + */ +int register_parisc_driver(struct parisc_driver *driver) +{ + struct parisc_device *device; + + if (driver->next) { + printk(KERN_WARNING + "BUG: Skipping previously registered driver: %s\n", + driver->name); + return 1; + } + + for_each_padev(device) { + if (device->driver) + continue; + if (!match_device(driver, device)) + continue; + + if (driver->probe(device) < 0) + continue; + claim_device(driver, device); + } + + /* Note that the list is in reverse order of registration. This + * may be significant if we ever actually support hotplug and have + * multiple drivers capable of claiming the same chip. + */ + + spin_lock(&pa_lock); + driver->next = pa_drivers; + pa_drivers = driver; + spin_unlock(&pa_lock); + + return 0; +} + +/** + * count_parisc_driver - count # of devices this driver would match + * @driver: the PA-RISC driver to try + * + * Use by IOMMU support to "guess" the right size IOPdir. + * Formula is something like memsize/(num_iommu * entry_size). + */ +int count_parisc_driver(struct parisc_driver *driver) +{ + struct parisc_device *device; + int cnt = 0; + + for_each_padev(device) { + if (match_device(driver, device)) + cnt++; + } + + return cnt; +} + + + +/** + * unregister_parisc_driver - Unregister this driver from the list of drivers + * @driver: the PA-RISC driver to unregister + */ +int unregister_parisc_driver(struct parisc_driver *driver) +{ + struct parisc_device *dev; + + spin_lock(&pa_lock); + + if (pa_drivers == driver) { + /* was head of list - update head */ + pa_drivers = driver->next; + } else { + struct parisc_driver *prev = pa_drivers; + + while (prev && driver != prev->next) { + prev = prev->next; + } + + if (!prev) { + printk(KERN_WARNING "unregister_parisc_driver: %s wasn't registered\n", driver->name); + } else { + /* Drop driver from list */ + prev->next = driver->next; + driver->next = NULL; } + } + + spin_unlock(&pa_lock); + + for_each_padev(dev) { + if (dev->driver != driver) + continue; + dev->driver = NULL; + release_mem_region(dev->hpa, 0x1000); + } + return 0; } +static struct parisc_device *find_device_by_addr(unsigned long hpa) +{ + struct parisc_device *dev; + for_each_padev(dev) { + if (dev->hpa == hpa) + return dev; + } + return NULL; +} -struct hp_device * register_module(void *hpa) +/** + * find_pa_parent_type - Find a parent of a specific type + * @dev: The device to start searching from + * @type: The device type to search for. + * + * Walks up the device tree looking for a device of the specified type. + * If it finds it, it returns it. If not, it returns NULL. + */ +const struct parisc_device *find_pa_parent_type(const struct parisc_device *dev, int type) { + while (dev != &root) { + if (dev->id.hw_type == type) + return dev; + dev = dev->parent; + } - struct hp_device * d; + return NULL; +} + +static void +get_node_path(struct parisc_device *dev, struct hardware_path *path) +{ + int i = 5; + memset(&path->bc, -1, 6); + while (dev != &root) { + path->bc[i--] = dev->hw_path; + dev = dev->parent; + } +} + +static char *print_hwpath(struct hardware_path *path, char *output) +{ + int i; + for (i = 0; i < 6; i++) { + if (path->bc[i] == -1) + continue; + output += sprintf(output, "%u/", (unsigned char) path->bc[i]); + } + output += sprintf(output, "%u", (unsigned char) path->mod); + return output; +} + +/** + * print_pa_hwpath - Returns hardware path for PA devices + * dev: The device to return the path for + * output: Pointer to a previously-allocated array to place the path in. + * + * This function fills in the output array with a human-readable path + * to a PA device. This string is compatible with that used by PDC, and + * may be printed on the outside of the box. + */ +char *print_pa_hwpath(struct parisc_device *dev, char *output) +{ + struct hardware_path path; + + get_node_path(dev->parent, &path); + path.mod = dev->hw_path; + return print_hwpath(&path, output); +} + + +#if defined(CONFIG_PCI) || defined(CONFIG_ISA) +/** + * get_pci_node_path - Returns hardware path for PCI devices + * dev: The device to return the path for + * output: Pointer to a previously-allocated array to place the path in. + * + * This function fills in the hardware_path structure with the route to + * the specified PCI device. This structure is suitable for passing to + * PDC calls. + */ +void get_pci_node_path(struct pci_dev *dev, struct hardware_path *path) +{ + struct pci_bus *bus; + const struct parisc_device *padev; + int i = 5; + + memset(&path->bc, -1, 6); + path->mod = PCI_FUNC(dev->devfn); + path->bc[i--] = PCI_SLOT(dev->devfn); + for (bus = dev->bus; bus->parent; bus = bus->parent) { + unsigned int devfn = bus->self->devfn; + path->bc[i--] = PCI_SLOT(devfn) | (PCI_FUNC(devfn) << 5); + } + + padev = HBA_DATA(bus->sysdata)->dev; + while (padev != &root) { + path->bc[i--] = padev->hw_path; + padev = padev->parent; + } +} + +/** + * print_pci_hwpath - Returns hardware path for PCI devices + * dev: The device to return the path for + * output: Pointer to a previously-allocated array to place the path in. + * + * This function fills in the output array with a human-readable path + * to a PCI device. This string is compatible with that used by PDC, and + * may be printed on the outside of the box. + */ +char *print_pci_hwpath(struct pci_dev *dev, char *output) +{ + struct hardware_path path; + + get_pci_node_path(dev, &path); + return print_hwpath(&path, output); +} +#endif /* defined(CONFIG_PCI) || defined(CONFIG_ISA) */ + + +struct parisc_device * create_tree_node(char id, struct parisc_device *parent, + struct parisc_device **insert) +{ + struct parisc_device *dev = kmalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return NULL; + memset(dev, 0, sizeof(*dev)); + dev->hw_path = id; + dev->id.hw_type = HPHW_FAULTY; + dev->parent = parent; + dev->sibling = *insert; + *insert = dev; + return dev; +} + +/** + * alloc_tree_node - returns a device entry in the iotree + * @parent: the parent node in the tree + * @id: the element of the module path for this entry + * + * Checks all the children of @parent for a matching @id. If none + * found, it allocates a new device and returns it. + */ +struct parisc_device * +alloc_tree_node(struct parisc_device *parent, char id) +{ + struct parisc_device *prev; + if ((!parent->child) || (parent->child->hw_path > id)) { + return create_tree_node(id, parent, &parent->child); + } + + prev = parent->child; + if (prev->hw_path == id) + return prev; + + while (prev->sibling && prev->sibling->hw_path < id) { + prev = prev->sibling; + } + + if ((prev->sibling) && (prev->sibling->hw_path == id)) + return prev->sibling; + + return create_tree_node(id, parent, &prev->sibling); +} + +static struct parisc_device *find_parisc_device(struct hardware_path *modpath) +{ + int i; + struct parisc_device *parent = &root; + for (i = 0; i < 6; i++) { + if (modpath->bc[i] == -1) + continue; + parent = alloc_tree_node(parent, modpath->bc[i]); + } + return alloc_tree_node(parent, modpath->mod); +} + +struct parisc_device * +alloc_pa_dev(unsigned long hpa, struct hardware_path *mod_path) +{ int status; + unsigned long bytecnt; + u8 iodc_data[32]; + struct parisc_device *dev; + const char *name; + + /* Check to make sure this device has not already been added - Ryan */ + if (find_device_by_addr(hpa) != NULL) + return NULL; + + status = pdc_iodc_read(&bytecnt, hpa, 0, &iodc_data, 32); + if (status != PDC_OK) + return NULL; + + dev = find_parisc_device(mod_path); + if (dev->id.hw_type != HPHW_FAULTY) { + char p[64]; + print_pa_hwpath(dev, p); + printk("Two devices have hardware path %s. Please file a bug with HP.\n" + "In the meantime, you could try rearranging your cards.\n", p); + return NULL; + } + + dev->id.hw_type = iodc_data[3] & 0x1f; + dev->id.hversion = (iodc_data[0] << 4) | ((iodc_data[1] & 0xf0) >> 4); + dev->id.hversion_rev = iodc_data[1] & 0x0f; + dev->id.sversion = ((iodc_data[4] & 0x0f) << 16) | + (iodc_data[5] << 8) | iodc_data[6]; + dev->hpa = hpa; + name = parisc_hardware_description(&dev->id); + if (name) { + strncpy(dev->name, name, sizeof(dev->name)-1); + } + + return dev; +} - d = &devices[num_devices]; - status = pdc_iodc_read(&pdc_result,hpa,0,&iodc_data,32 ); - if (status !=PDC_RET_OK) { - /* There is no device here, so we'll skip it */ +/** + * register_parisc_device - Locate a driver to manage this device. + * @dev: The parisc device. + * + * Search the driver list for a driver that is willing to manage + * this device. + */ +int register_parisc_device(struct parisc_device *dev) +{ + struct parisc_driver *driver; + + if (!dev) return 0; + + if (dev->driver) + return 1; + + spin_lock(&pa_lock); + + /* Locate a driver which agrees to manage this device. */ + for (driver = pa_drivers; driver; driver = driver->next) { + if (!match_device(driver,dev)) + continue; + if (driver->probe(dev) == 0) + break; } - d->hw_type = iodc_data[3]&0x1f; - d->hversion = (iodc_data[0]<<4)|((iodc_data[1]&0xf0)>>4); - d->sversion = - ((iodc_data[4]&0x0f)<<16)|(iodc_data[5]<<8)|(iodc_data[6]); - d->hversion_rev = iodc_data[1]&0x0f; - d->sversion_rev = iodc_data[4]>>4; - d->opt = iodc_data[7]; - d->hpa = hpa; - d->managed=0; - d->reference = parisc_get_reference(d->hw_type, d->hversion, - d->sversion); - - num_devices++; + if (driver != NULL) { + claim_device(driver, dev); + } + spin_unlock(&pa_lock); + return driver != NULL; +} + +#define BC_PORT_MASK 0x8 +#define BC_LOWER_PORT 0x8 + +#define BUS_CONVERTER(dev) \ + ((dev->id.hw_type == HPHW_IOA) || (dev->id.hw_type == HPHW_BCPORT)) + +#define IS_LOWER_PORT(dev) \ + ((gsc_readl(&((struct bc_module *)dev->hpa)->io_status) \ + & BC_PORT_MASK) == BC_LOWER_PORT) + +#define READ_IO_IO_LOW(dev) \ + (dev->id.hw_type == HPHW_IOA ? \ + __raw_readl((unsigned long)&((struct bc_module *)dev->hpa)->io_io_low) << 16 : \ + __raw_readl((unsigned long)&((struct bc_module *)dev->hpa)->io_io_low)) - return d; -} +static void walk_native_bus(unsigned long addr, struct parisc_device *parent); +void walk_lower_bus(struct parisc_device *dev) +{ + + if(!BUS_CONVERTER(dev) || IS_LOWER_PORT(dev)) + return; -void print_devices(char * buf) { + walk_native_bus((unsigned long)(signed int)READ_IO_IO_LOW(dev), dev); +} +#define MAX_NATIVE_DEVICES 64 +#define NATIVE_DEVICE_OFFSET 0x1000 + +/** + * walk_native_bus -- Probe a bus for devices + * @addr: Base address of this bus. + * + * A native bus (eg Runway or GSC) may have up to 64 devices on it, + * spaced at intervals of 0x1000 bytes. PDC may not inform us of these + * devices, so we have to probe for them. Unfortunately, we may find + * devices which are not physically connected (such as extra serial & + * keyboard ports). This problem is not yet solved. + */ +static void walk_native_bus(unsigned long addr, struct parisc_device *parent) +{ int i; - struct hp_device *d; - printk("Found devices:\n"); - for (i=0;ireference) ? d->reference->name : "Unknown device", - d->hw_type,d->hpa, d->hversion, d->hversion_rev, - d->sversion, d->sversion_rev, d->opt); + struct hardware_path path; + + get_node_path(parent, &path); + for (i = 0; i < MAX_NATIVE_DEVICES; i++) { + unsigned long hpa = (addr + i * NATIVE_DEVICE_OFFSET); + struct parisc_device *dev; + + /* Was the device already added by Firmware? */ + dev = find_device_by_addr(hpa); + if (!dev) { + path.mod = i; + dev = alloc_pa_dev(hpa, &path); + if (!dev) + continue; + + register_parisc_device(dev); + } + walk_lower_bus(dev); + } +} + +#define CENTRAL_BUS_ADDR (unsigned long) 0xfffffffffff80000 + +/** + * walk_central_bus - Find devices attached to the central bus + * + * PDC doesn't tell us about all devices in the system. This routine + * finds devices connected to the central bus. + */ +void walk_central_bus(void) +{ + walk_native_bus(CENTRAL_BUS_ADDR, &root); +} + +void fixup_child_irqs(struct parisc_device *parent, int base, + int (*choose_irq)(struct parisc_device *)) +{ + struct parisc_device *dev; + if (!parent->child) + return; + + for (dev = check_dev(parent->child); dev; dev = dev->sibling) { + int irq = choose_irq(dev); + if (irq > 0) { +#ifdef __LP64__ + irq += 32; +#endif + dev->irq = base + irq; + } } - printk("That's a total of %d devices.\n",num_devices); } +static void print_parisc_device(struct parisc_device *dev) +{ + char hw_path[64]; + static int count; + print_pa_hwpath(dev, hw_path); + printk(KERN_INFO "%d. %s (%d) at 0x%lx [%s], versions 0x%x, 0x%x, 0x%x", + ++count, dev->name, dev->id.hw_type, dev->hpa, hw_path, + dev->id.hversion, dev->id.hversion_rev, dev->id.sversion); + + if (dev->num_addrs) { + int k; + printk(", additional addresses: "); + for (k = 0; k < dev->num_addrs; k++) + printk("0x%lx ", dev->addr[k]); + } + printk("\n"); +} + +void print_subdevices(struct parisc_device *parent) +{ + struct parisc_device *dev; + for (dev = parent->child; dev != parent->sibling; dev = next_dev(dev)) { + print_parisc_device(dev); + } +} + +/** + * print_parisc_devices - Print out a list of devices found in this system + */ +void print_parisc_devices(void) +{ + struct parisc_device *dev; + for_each_padev(dev) { + print_parisc_device(dev); + } +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/entry.S linux.19rc3-ac4/arch/parisc/kernel/entry.S --- linux.19rc3/arch/parisc/kernel/entry.S 2002-07-29 12:50:06.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/entry.S 2002-07-29 13:58:36.000000000 +0100 @@ -1,5 +1,5 @@ -/*------------------------------------------------------------------------------ - * Native PARISC/Linux Project (http://www.puffingroup.com/parisc) +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) * * kernel entry points (interruptions, system call wrappers) * Copyright (C) 1999,2000 Philipp Rumpf @@ -25,39 +25,51 @@ #include #include -/* the following is the setup i think we should follow: - * whenever the CPU is interruptible, the following has to be true: - * CR30 is the kernel sp or 0 if we currently use the kernel stack - * CR31 is the kernel gp */ - /* we have the following possibilities to act on an interruption: * - handle in assembly and use shadowed registers only * - save registers to kernel stack and handle in assembly or C */ - .text - -#ifdef __LP64__ - .level 2.0w -#endif -#define __ASSEMBLY__ #include /* for LDREG/STREG defines */ #include #include #include +#include #ifdef __LP64__ -#define FRAME_SIZE 64 +#define FRAME_SIZE 128 +#define CMPIB cmpib,* +#define CMPB cmpb,* + + .level 2.0w #else #define FRAME_SIZE 64 +#define CMPIB cmpib, +#define CMPB cmpb, + + .level 2.0 +#endif + + .import pa_dbit_lock,data + + /* space_to_prot macro creates a prot id from a space id */ + +#if (SPACEID_SHIFT) == 0 + .macro space_to_prot spc prot + depd,z \spc,62,31,\prot + .endm +#else + .macro space_to_prot spc prot + extrd,u \spc,(64 - (SPACEID_SHIFT)),32,\prot + .endm #endif /* Switch to virtual mapping, trashing only %r1 */ - .macro virt_map rfi_type - mtsm %r0 - tovirt %r29 - tovirt %r30 + .macro virt_map + rsm PSW_SM_Q,%r0 + tovirt_r1 %r29 mfsp %sr7, %r1 + or,= %r0,%r1,%r0 /* Only save sr7 in sr3 if sr7 != 0 */ mtsp %r1, %sr3 mtsp %r0, %sr4 mtsp %r0, %sr5 @@ -65,95 +77,114 @@ mtsp %r0, %sr7 ldil L%KERNEL_PSW, %r1 ldo R%KERNEL_PSW(%r1), %r1 - LDIL_FIXUP(%r1) mtctl %r1, %cr22 mtctl %r0, %cr17 mtctl %r0, %cr17 - ldil L%.+28, %r1 - ldo R%.+24(%r1), %r1 - LDIL_FIXUP(%r1) + ldil L%4f, %r1 + ldo R%4f(%r1), %r1 mtctl %r1, %cr18 ldo 4(%r1), %r1 mtctl %r1, %cr18 - \rfi_type + rfir nop +4: .endm - .macro get_stack - mfctl %cr30, %r1 - comib,=,n 0, %r1, 0f /* forward so predicted not taken */ + /* + * The "get_stack" macros are responsible for determining the + * kernel stack value. + * + * For Faults: + * If sr7 == 0 + * Already using a kernel stack, so call the + * get_stack_use_r30 macro to push a pt_regs structure + * on the stack, and store registers there. + * else + * Need to set up a kernel stack, so call the + * get_stack_use_cr30 macro to set up a pointer + * to the pt_regs structure contained within the + * task pointer pointed to by cr30. Set the stack + * pointer to point to the end of the task structure. + * + * For Interrupts: + * If sr7 == 0 + * Already using a kernel stack, check to see if r30 + * is already pointing to the per processor interrupt + * stack. If it is, call the get_stack_use_r30 macro + * to push a pt_regs structure on the stack, and store + * registers there. Otherwise, call get_stack_use_cr31 + * to get a pointer to the base of the interrupt stack + * and push a pt_regs structure on that stack. + * else + * Need to set up a kernel stack, so call the + * get_stack_use_cr30 macro to set up a pointer + * to the pt_regs structure contained within the + * task pointer pointed to by cr30. Set the stack + * pointer to point to the end of the task structure. + * N.B: We don't use the interrupt stack for the + * first interrupt from userland, because signals/ + * resched's are processed when returning to userland, + * and we can sleep in those cases. + * + * Note that we use shadowed registers for temps until + * we can save %r26 and %r29. %r26 is used to preserve + * %r8 (a shadowed register) which temporarily contained + * either the fault type ("code") or the eirr. We need + * to use a non-shadowed register to carry the value over + * the rfir in virt_map. We use %r26 since this value winds + * up being passed as the argument to either do_cpu_irq_mask + * or handle_interruption. %r29 is used to hold a pointer + * the register save area, and once again, it needs to + * be a non-shadowed register so that it survives the rfir. + * + * N.B. TASK_SZ_ALGN and PT_SZ_ALGN include space for a stack frame. + */ + + .macro get_stack_use_cr30 /* we save the registers in the task struct */ - ldo TASK_REGS(%r1), %r29 - tophys %r29 - STREG %r30, PT_GR30(%r29) - STREG %r1, PT_CR30(%r29) + + mfctl %cr30, %r1 + tophys %r1,%r9 + ldo TASK_REGS(%r9),%r9 + STREG %r30, PT_GR30(%r9) ldo TASK_SZ_ALGN(%r1), %r30 - b 1f /* unconditional so predicted taken */ - mtctl %r0,%cr30 -0: - /* we put a struct pt_regs on the stack and save the registers there */ - copy %r30,%r29 - ldo PT_SZ_ALGN(%r30),%r30 - tophys %r29 - STREG %r30,PT_GR30(%r29) - STREG %r0,PT_CR30(%r29) -1: + STREG %r29,PT_GR29(%r9) + STREG %r26,PT_GR26(%r9) + copy %r9,%r29 .endm - .macro rest_stack regs - LDREG PT_CR30(\regs), %r1 - comib,=,n 0, %r1, 2f/* forward so predicted not taken */ - - /* we restore the registers out of the task struct */ - mtctl %r1, %cr30 - LDREG PT_GR1(\regs), %r1 - LDREG PT_GR30(\regs),%r30 - b 3f - LDREG PT_GR29(\regs),%r29 -2: - /* we take a struct pt_regs off the stack */ - LDREG PT_GR1(\regs), %r1 - LDREG PT_GR29(\regs), %r29 - ldo -PT_SZ_ALGN(%r30), %r30 -3: - .endm + .macro get_stack_use_r30 -#ifdef OLD - /* fixme interruption handler */ - .macro def code - /* WARNING!!! THIS IS DEBUG CODE ONLY!!! */ - b unimplemented_64bitirq - ldi \code, %r1 - .align 32 + /* we put a struct pt_regs on the stack and save the registers there */ + + tophys %r30,%r9 + STREG %r30,PT_GR30(%r9) + ldo PT_SZ_ALGN(%r30),%r30 + STREG %r29,PT_GR29(%r9) + STREG %r26,PT_GR26(%r9) + copy %r9,%r29 .endm - /* Use def to enable break - KWDB wants em - * (calls traps.c:handle_interruption) */ - .macro pass_break code + .macro rest_stack + LDREG PT_GR1(%r29), %r1 + LDREG PT_GR30(%r29),%r30 + LDREG PT_GR29(%r29),%r29 + .endm -#else /* default interruption handler * (calls traps.c:handle_interruption) */ .macro def code -#endif - mtctl %r29, %cr31 - mtctl %r1, %cr28 - ldi \code, %r1 b intr_save - mtctl %r1, %cr29 + ldi \code, %r8 .align 32 .endm /* Interrupt interruption handler - * (calls irq.c:do_irq_mask) */ + * (calls irq.c:do_cpu_irq_mask) */ .macro extint code - mtctl %r29, %cr31 - mtctl %r1, %cr28 - mfctl %cr23, %r1 - mtctl %r1, %cr23 b intr_extint - mtctl %r1, %cr29 + mfsp %sr7,%r16 .align 32 .endm @@ -203,7 +234,6 @@ */ .macro itlb_20 code - mfctl %pcsq, spc #ifdef __LP64__ b itlb_miss_20w @@ -298,37 +328,27 @@ .endm #ifndef __LP64__ - /* nadtlb miss interruption handler (parisc 1.1 - 32 bit) - * - * Note: nadtlb misses will be treated - * as an ordinary dtlb miss for now. - * - */ + /* nadtlb miss interruption handler (parisc 1.1 - 32 bit) */ .macro nadtlb_11 code mfctl %isr,spc - b dtlb_miss_11 + b nadtlb_miss_11 mfctl %ior,va .align 32 .endm #endif - /* nadtlb miss interruption handler (parisc 2.0) - * - * Note: nadtlb misses will be treated - * as an ordinary dtlb miss for now. - * - */ + /* nadtlb miss interruption handler (parisc 2.0) */ .macro nadtlb_20 code mfctl %isr,spc #ifdef __LP64__ - b dtlb_miss_20w + b nadtlb_miss_20w #else - b dtlb_miss_20 + b nadtlb_miss_20 #endif mfctl %ior,va @@ -372,13 +392,14 @@ * fault_vector_11 and fault_vector_20 are on the * same page. This is only necessary as long as we * write protect the kernel text, which we may stop - * doing once we use large parge translations to cover + * doing once we use large page translations to cover * the static part of the kernel address space. */ - .export fault_vector_20 + .text + .align 4096 fault_vector_20: @@ -402,7 +423,11 @@ def 13 def 14 dtlb_20 15 +#if 0 naitlb_20 16 +#else + def 16 +#endif nadtlb_20 17 def 18 def 19 @@ -446,7 +471,11 @@ def 13 def 14 dtlb_11 15 +#if 0 naitlb_11 16 +#else + def 16 +#endif nadtlb_11 17 def 18 def 19 @@ -467,7 +496,7 @@ .import handle_interruption,code .import handle_real_interruption,code - .import do_irq_mask,code + .import do_cpu_irq_mask,code .import parisc_stopkernel,code .import cpu_irq_region,data @@ -492,7 +521,8 @@ ldo PT_SZ_ALGN(%r30),%r30 #ifdef __LP64__ /* Yo, function pointers in wide mode are little structs... -PB */ - /* XXX FIXME do we need to honor the fptr's %dp value too? */ + ldd 24(%r26), %r2 + STREG %r2, PT_GR27(%r1) /* Store childs %dp */ ldd 16(%r26), %r26 #endif STREG %r26, PT_GR26(%r1) /* Store function & argument for child */ @@ -500,15 +530,17 @@ ldo CLONE_VM(%r0), %r26 /* Force CLONE_VM since only init_mm */ or %r26, %r24, %r26 /* will have kernel mappings. */ copy %r0, %r25 +#ifdef __LP64__ + ldo -16(%r30),%r29 /* Reference param save area */ +#endif bl do_fork, %r2 copy %r1, %r24 /* Parent Returns here */ - ldo -PT_SZ_ALGN(%r30), %r30 - LDREG -RP_OFFSET(%r30), %r2 + LDREG -PT_SZ_ALGN-RP_OFFSET(%r30), %r2 bv %r0(%r2) - nop + ldo -PT_SZ_ALGN(%r30), %r30 /* * Child Returns here @@ -520,11 +552,22 @@ .export ret_from_kernel_thread ret_from_kernel_thread: + /* Call schedule_tail first though */ + bl schedule_tail, %r2 + nop + LDREG TASK_PT_GR26-TASK_SZ_ALGN(%r30), %r1 LDREG TASK_PT_GR25-TASK_SZ_ALGN(%r30), %r26 +#ifdef __LP64__ + LDREG TASK_PT_GR27-TASK_SZ_ALGN(%r30), %r27 +#endif ble 0(%sr7, %r1) copy %r31, %r2 +#ifdef __LP64__ + ldo -16(%r30),%r29 /* Reference param save area */ + loadgp /* Thread could have been in a module */ +#endif b sys_exit ldi 0, %r26 @@ -532,23 +575,22 @@ .export __execve, code __execve: copy %r2, %r15 - copy %r23, %r17 copy %r30, %r16 ldo PT_SZ_ALGN(%r30), %r30 STREG %r26, PT_GR26(%r16) STREG %r25, PT_GR25(%r16) STREG %r24, PT_GR24(%r16) +#ifdef __LP64__ + ldo -16(%r30),%r29 /* Reference param save area */ +#endif bl sys_execve, %r2 copy %r16, %r26 - comib,<>,n 0,%r28,__execve_failed - - b intr_return - STREG %r17, PT_CR30(%r16) + cmpib,=,n 0,%r28,intr_return /* forward */ -__execve_failed: /* yes, this will trap and die. */ copy %r15, %r2 + copy %r16, %r30 bv %r0(%r2) nop @@ -567,16 +609,14 @@ ldil L%_switch_to_ret, %r2 ldo R%_switch_to_ret(%r2), %r2 - LDIL_FIXUP(%r2) STREG %r2, TASK_PT_KPC(%r26) LDREG TASK_PT_KPC(%r25), %r2 STREG %r30, TASK_PT_KSP(%r26) LDREG TASK_PT_KSP(%r25), %r30 - bv %r0(%r2) - nop + mtctl %r25,%cr30 _switch_to_ret: mtctl %r0, %cr0 /* Needed for single stepping */ @@ -587,27 +627,30 @@ copy %r26, %r28 /* - * Common rfi return path for interruptions, kernel execve, and some - * syscalls. The sys_rt_sigreturn syscall will return via this path - * if the signal was received when the process was running; if the - * process was blocked on a syscall then the normal syscall_exit - * path is used. All syscalls for traced proceses exit via - * intr_restore. - * Note that the following code uses a "relied upon translation". See - * the parisc ACD for details. The ssm is necessary due to a PCXT bug. + * Common rfi return path for interruptions, kernel execve, and + * sys_rt_sigreturn (sometimes). The sys_rt_sigreturn syscall will + * return via this path if the signal was received when the process + * was running; if the process was blocked on a syscall then the + * normal syscall_exit path is used. All syscalls for traced + * proceses exit via intr_restore. + * + * XXX If any syscalls that change a processes space id ever exit + * this way, then we will need to copy %sr3 in to PT_SR[3..7], and + * adjust IASQ[0..1]. + * + * Note that the following code uses a "relied upon translation". + * See the parisc ACD for details. The ssm is necessary due to a + * PCXT bug. */ .align 4096 .export syscall_exit_rfi syscall_exit_rfi: - copy %r30,%r16 - /* FIXME! depi below has hardcoded dependency on kernel stack size */ - depi 0,31,14,%r16 /* get task pointer */ + mfctl %cr30,%r16 ldo TASK_REGS(%r16),%r16 /* Force iaoq to userspace, as the user has had access to our current - * context via sigcontext. - * XXX do we need any other protection here? + * context via sigcontext. Also Filter the PSW for the same reason. */ LDREG PT_IAOQ0(%r16),%r19 depi 3,31,2,%r19 @@ -615,57 +658,84 @@ LDREG PT_IAOQ1(%r16),%r19 depi 3,31,2,%r19 STREG %r19,PT_IAOQ1(%r16) - + LDREG PT_PSW(%r16),%r19 + ldil L%USER_PSW_MASK,%r1 + ldo R%USER_PSW_MASK(%r1),%r1 +#ifdef __LP64__ + ldil L%USER_PSW_HI_MASK,%r20 + ldo R%USER_PSW_HI_MASK(%r20),%r20 + depd %r20,31,32,%r1 +#endif + and %r19,%r1,%r19 /* Mask out bits that user shouldn't play with */ + ldil L%USER_PSW,%r1 + ldo R%USER_PSW(%r1),%r1 + or %r19,%r1,%r19 /* Make sure default USER_PSW bits are set */ + STREG %r19,PT_PSW(%r16) + + /* + * If we aren't being traced, we never saved space registers + * (we don't store them in the sigcontext), so set them + * to "proper" values now (otherwise we'll wind up restoring + * whatever was last stored in the task structure, which might + * be inconsistant if an interrupt occured while on the gateway + * page) Note that we may be "trashing" values the user put in + * them, but we don't support the the user changing them. + */ + + STREG %r0,PT_SR2(%r16) + mfsp %sr3,%r19 + STREG %r19,PT_SR0(%r16) + STREG %r19,PT_SR1(%r16) + STREG %r19,PT_SR3(%r16) + STREG %r19,PT_SR4(%r16) + STREG %r19,PT_SR5(%r16) + STREG %r19,PT_SR6(%r16) + STREG %r19,PT_SR7(%r16) + intr_return: + ssm PSW_SM_I, %r0 /* Check for software interrupts */ .import irq_stat,data - ldil L%irq_stat,%r19 - ldo R%irq_stat(%r19),%r19 - LDIL_FIXUP(%r19) - + ldil L%irq_stat,%r19 + ldo R%irq_stat(%r19),%r19 #ifdef CONFIG_SMP - copy %r30,%r1 - /* FIXME! depi below has hardcoded dependency on kernel stack size */ - depi 0,31,14,%r1 /* get task pointer */ - ldw TASK_PROCESSOR(%r1),%r20 /* get cpu # - int */ -#if (IRQSTAT_SZ == 32) - dep %r20,26,27,%r20 /* shift left 5 bits */ -#else -#error IRQSTAT_SZ changed, fix dep -#endif /* IRQSTAT_SZ */ - add %r19,%r20,%r19 + mfctl %cr30,%r1 + ldw TASK_PROCESSOR(%r1),%r1 /* get cpu # - int */ + /* shift left ____cacheline_aligned (aka L1_CACHE_BYTES) amount + ** irq_stat[] is defined using ____cacheline_aligned. + */ +#ifdef __LP64__ + shld %r1, 6, %r20 +#else + shlw %r1, 5, %r20 +#endif + add %r19,%r20,%r19 /* now have &irq_stat[smp_processor_id()] */ #endif /* CONFIG_SMP */ - ldw IRQSTAT_SI_ACTIVE(%r19),%r20 /* hardirq.h: unsigned int */ - ldw IRQSTAT_SI_MASK(%r19),%r19 /* hardirq.h: unsigned int */ - and %r19,%r20,%r20 - comib,<>,n 0,%r20,intr_do_softirq /* forward */ + LDREG IRQSTAT_SIRQ_PEND(%r19),%r20 /* hardirq.h: unsigned long */ + cmpib,<>,n 0,%r20,intr_do_softirq /* forward */ intr_check_resched: /* check for reschedule */ - copy %r30,%r1 - /* FIXME! depi below has hardcoded dependency on kernel stack size */ - depi 0,31,14,%r1 /* get task pointer */ + mfctl %cr30,%r1 LDREG TASK_NEED_RESCHED(%r1),%r19 /* sched.h: long need_resched */ - comib,<>,n 0,%r19,intr_do_resched /* forward */ + CMPIB<>,n 0,%r19,intr_do_resched /* forward */ intr_check_sig: /* As above */ - copy %r30,%r1 - depi 0,31,14,%r1 /* get task pointer */ + mfctl %cr30,%r1 ldw TASK_SIGPENDING(%r1),%r19 /* sched.h: int sigpending */ - comib,<>,n 0,%r19,intr_do_signal /* forward */ + cmpib,<>,n 0,%r19,intr_do_signal /* forward */ intr_restore: - copy %r16, %r29 - ldo PT_FR31(%r29), %r29 - rest_fp %r29 - copy %r16, %r29 - rest_general %r29 + copy %r16,%r29 + ldo PT_FR31(%r29),%r1 + rest_fp %r1 + rest_general %r29 ssm 0,%r0 nop nop @@ -674,10 +744,10 @@ nop nop nop - tophys %r29 - mtsm %r0 + tophys_r1 %r29 + rsm (PSW_SM_Q|PSW_SM_P|PSW_SM_D|PSW_SM_I),%r0 rest_specials %r29 - rest_stack %r29 + rest_stack rfi nop nop @@ -691,88 +761,175 @@ .import do_softirq,code intr_do_softirq: bl do_softirq,%r2 +#ifdef __LP64__ + ldo -16(%r30),%r29 /* Reference param save area */ +#else nop +#endif b intr_check_resched nop .import schedule,code intr_do_resched: /* Only do reschedule if we are returning to user space */ - LDREG PT_SR7(%r16), %r20 - comib,= 0,%r20,intr_restore /* backward */ + LDREG PT_IASQ0(%r16), %r20 + CMPIB= 0,%r20,intr_restore /* backward */ + nop + LDREG PT_IASQ1(%r16), %r20 + CMPIB= 0,%r20,intr_restore /* backward */ nop - bl schedule,%r2 - ssm PSW_SM_I, %r0 +#ifdef __LP64__ + ldo -16(%r30),%r29 /* Reference param save area */ +#endif + + ldil L%intr_return, %r2 + b schedule + ldo R%intr_return(%r2), %r2 /* return to intr_return, not here */ - /* It's OK to leave I bit on */ - b intr_return /* start over if we got a resched */ - nop .import do_signal,code intr_do_signal: /* Only do signals if we are returning to user space */ - LDREG PT_SR7(%r16), %r20 - comib,= 0,%r20,intr_restore /* backward */ + LDREG PT_IASQ0(%r16), %r20 + CMPIB= 0,%r20,intr_restore /* backward */ + nop + LDREG PT_IASQ1(%r16), %r20 + CMPIB= 0,%r20,intr_restore /* backward */ nop copy %r0, %r24 /* unsigned long in_syscall */ copy %r16, %r25 /* struct pt_regs *regs */ ssm PSW_SM_I, %r0 +#ifdef __LP64__ + ldo -16(%r30),%r29 /* Reference param save area */ +#endif bl do_signal,%r2 copy %r0, %r26 /* sigset_t *oldset = NULL */ b intr_restore nop - /* CR28 - saved GR1 - * CR29 - argument for do_irq_mask */ + /* + * External interrupts. + */ - /* External interrupts */ intr_extint: - get_stack + CMPIB=,n 0,%r16,1f + get_stack_use_cr30 + b,n 3f + +1: +#if 0 /* Interrupt Stack support not working yet! */ + mfctl %cr31,%r1 + copy %r30,%r17 + /* FIXME! depi below has hardcoded idea of interrupt stack size (32k)*/ +#ifdef __LP64__ + depdi 0,63,15,%r17 +#else + depi 0,31,15,%r17 +#endif + CMPB=,n %r1,%r17,2f + get_stack_use_cr31 + b,n 3f +#endif +2: + get_stack_use_r30 + +3: save_specials %r29 - virt_map rfi + virt_map save_general %r29 - ldo PT_FR0(%r29), %r24 - save_fp %r24 + ldo PT_FR0(%r29), %r24 + save_fp %r24 loadgp - copy %r29, %r24 /* arg2 is pt_regs */ - copy %r29, %r16 /* save pt_regs */ + copy %r29, %r25 /* arg1 is pt_regs */ + copy %r29, %r16 /* save pt_regs */ #ifdef CONFIG_KWDB - copy %r29, %r3 /* KWDB - update frame pointer (gr3) */ + copy %r29, %r3 /* KWDB - update frame pointer (gr3) */ #endif - /* sorry to put this cruft in the interrupt path */ - ldil L%cpu_irq_region, %r25 - ldo R%cpu_irq_region(%r25), %r25 - bl do_irq_mask,%r2 #ifdef __LP64__ - LDIL_FIXUP(%r25) + ldo -16(%r30),%r29 /* Reference param save area */ #else nop #endif - - b intr_return - nop + + /* + * We need to either load the CPU's ID or IRQ region. + * Until we have "per CPU" IRQ regions, this is easy. + */ + ldil L%cpu_irq_region, %r26 + ldil L%intr_return, %r2 + ldo R%cpu_irq_region(%r26), %r26 + + b do_cpu_irq_mask + ldo R%intr_return(%r2), %r2 /* return to intr_return, not here */ /* Generic interruptions (illegal insn, unaligned, page fault, etc) */ .export intr_save, code /* for os_hpmc */ intr_save: - get_stack + mfsp %sr7,%r16 + CMPIB=,n 0,%r16,1f + get_stack_use_cr30 + b 2f + copy %r8,%r26 + +1: + get_stack_use_r30 + copy %r8,%r26 + +2: save_specials %r29 - mfctl %cr20, %r1 - STREG %r1, PT_ISR(%r29) - mfctl %cr21, %r1 - STREG %r1, PT_IOR(%r29) + /* If this trap is a itlb miss, skip saving/adjusting isr/ior */ + + /* + * FIXME: 1) Use a #define for the hardwired "6" below (and in + * traps.c. + * 2) Once we start executing code above 4 Gb, we need + * to adjust iasq/iaoq here in the same way we + * adjust isr/ior below. + */ + + CMPIB=,n 6,%r26,skip_save_ior + + /* save_specials left ipsw value in r8 for us to test */ + + mfctl %cr20, %r16 /* isr */ + mfctl %cr21, %r17 /* ior */ + +#ifdef __LP64__ + /* + * If the interrupted code was running with W bit off (32 bit), + * clear the b bits (bits 0 & 1) in the ior. + */ + extrd,u,*<> %r8,PSW_W_BIT,1,%r0 + depdi 0,1,2,%r17 + + /* + * FIXME: This code has hardwired assumptions about the split + * between space bits and offset bits. This will change + * when we allow alternate page sizes. + */ + + /* adjust isr/ior. */ + + extrd,u %r16,63,7,%r1 /* get high bits from isr for ior */ + depd %r1,31,7,%r17 /* deposit them into ior */ + depdi 0,63,7,%r16 /* clear them from isr */ +#endif + STREG %r16, PT_ISR(%r29) + STREG %r17, PT_IOR(%r29) + - virt_map rfi +skip_save_ior: + virt_map save_general %r29 ldo PT_FR0(%r29), %r25 @@ -785,11 +942,16 @@ copy %r29, %r3 /* KWDB - update frame pointer (gr3) */ #endif - bl handle_interruption,%r2 - copy %r29, %r16 /* save pt_regs */ +#ifdef __LP64__ + ldo -16(%r30),%r29 /* Reference param save area */ +#endif + + ldil L%intr_return, %r2 + copy %r25, %r16 /* save pt_regs */ + + b handle_interruption + ldo R%intr_return(%r2), %r2 /* return to intr_return */ - b intr_return - nop /* * Note for all tlb miss handlers: @@ -821,10 +983,9 @@ #ifdef __LP64__ dtlb_miss_20w: - - extrd,u spc,31,7,t1 /* adjust va */ + extrd,u spc,63,7,t1 /* adjust va */ depd t1,31,7,va /* adjust va */ - depdi 0,31,7,spc /* adjust space */ + depdi 0,63,7,spc /* adjust space */ mfctl %cr25,ptp /* Assume user space miss */ or,*<> %r0,spc,%r0 /* If it is user space, nullify */ mfctl %cr24,ptp /* Load kernel pgd instead */ @@ -832,20 +993,20 @@ mfsp %sr7,t0 /* Get current space */ or,*= %r0,t0,%r0 /* If kernel, nullify following test */ - comb,<>,n t0,spc,dtlb_fault /* forward */ + cmpb,*<>,n t0,spc,dtlb_fault /* forward */ /* First level page table lookup */ ldd,s t1(ptp),ptp extrd,u va,42,9,t0 /* get second-level index */ - bb,>=,n ptp,_PAGE_PRESENT_BIT,dtlb_fault + bb,>=,n ptp,_PAGE_PRESENT_BIT,dtlb_check_alias_20w depdi 0,63,12,ptp /* clear prot bits */ /* Second level page table lookup */ ldd,s t0(ptp),ptp extrd,u va,51,9,t0 /* get third-level index */ - bb,>=,n ptp,_PAGE_PRESENT_BIT,dtlb_fault + bb,>=,n ptp,_PAGE_PRESENT_BIT,dtlb_check_alias_20w depdi 0,63,12,ptp /* clear prot bits */ /* Third level page table lookup */ @@ -853,7 +1014,7 @@ shladd t0,3,ptp,ptp ldi _PAGE_ACCESSED,t1 ldd 0(ptp),pte - bb,>=,n pte,_PAGE_PRESENT_BIT,dtlb_fault + bb,>=,n pte,_PAGE_PRESENT_BIT,dtlb_check_alias_20w /* Check whether the "accessed" bit was set, otherwise do so */ @@ -861,11 +1022,9 @@ and,*<> t1,pte,%r0 /* test and nullify if already set */ std t0,0(ptp) /* write back pte */ - copy spc,prot /* init prot with faulting space */ - - depd pte,8,7,prot - extrd,u,*= pte,_PAGE_NO_CACHE_BIT+32,1,r0 - depdi 1,12,1,prot + space_to_prot spc prot /* create prot id from space */ + depd pte,8,7,prot /* add in prot bits from pte */ + extrd,u,*= pte,_PAGE_USER_BIT+32,1,r0 depdi 7,11,3,prot /* Set for user space (1 rsvd for read) */ extrd,u,*= pte,_PAGE_GATEWAY_BIT+32,1,r0 @@ -874,11 +1033,106 @@ /* Get rid of prot bits and convert to page addr for idtlbt */ depdi 0,63,12,pte - extrd,u pte,56,32,pte - idtlbt %r16,%r17 + extrd,u pte,56,52,pte + idtlbt pte,prot rfir nop + +dtlb_check_alias_20w: + + /* Check to see if fault is in the temporary alias region */ + + cmpib,*<>,n 0,spc,dtlb_fault /* forward */ + ldil L%(TMPALIAS_MAP_START),t0 + copy va,t1 + depdi 0,63,23,t1 + cmpb,*<>,n t0,t1,dtlb_fault /* forward */ + ldi (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),prot + depd,z prot,8,7,prot + + /* + * OK, it is in the temp alias region, check whether "from" or "to". + * Check "subtle" note in pacache.S re: r23/r26. + */ + + extrd,u,*= va,41,1,r0 + or,*tr %r23,%r0,pte /* If "from" use "from" page */ + or,* %r26,%r0,pte /* else "to", use "to" page */ + + idtlbt pte,prot + + rfir + nop + +nadtlb_miss_20w: + extrd,u spc,63,7,t1 /* adjust va */ + depd t1,31,7,va /* adjust va */ + depdi 0,63,7,spc /* adjust space */ + mfctl %cr25,ptp /* Assume user space miss */ + or,*<> %r0,spc,%r0 /* If it is user space, nullify */ + mfctl %cr24,ptp /* Load kernel pgd instead */ + extrd,u va,33,9,t1 /* Get pgd index */ + + mfsp %sr7,t0 /* Get current space */ + or,*= %r0,t0,%r0 /* If kernel, nullify following test */ + cmpb,*<>,n t0,spc,nadtlb_fault /* forward */ + + /* First level page table lookup */ + + ldd,s t1(ptp),ptp + extrd,u va,42,9,t0 /* get second-level index */ + bb,>=,n ptp,_PAGE_PRESENT_BIT,nadtlb_emulate + depdi 0,63,12,ptp /* clear prot bits */ + + /* Second level page table lookup */ + + ldd,s t0(ptp),ptp + extrd,u va,51,9,t0 /* get third-level index */ + bb,>=,n ptp,_PAGE_PRESENT_BIT,nadtlb_emulate + depdi 0,63,12,ptp /* clear prot bits */ + + /* Third level page table lookup */ + + shladd t0,3,ptp,ptp + ldi _PAGE_ACCESSED,t1 + ldd 0(ptp),pte + bb,>=,n pte,_PAGE_PRESENT_BIT,nadtlb_check_flush_20w + + space_to_prot spc prot /* create prot id from space */ + depd pte,8,7,prot /* add in prot bits from pte */ + + extrd,u,*= pte,_PAGE_USER_BIT+32,1,r0 + depdi 7,11,3,prot /* Set for user space (1 rsvd for read) */ + extrd,u,*= pte,_PAGE_GATEWAY_BIT+32,1,r0 + depdi 0,11,2,prot /* If Gateway, Set PL2 to 0 */ + + /* Get rid of prot bits and convert to page addr for idtlbt */ + + depdi 0,63,12,pte + extrd,u pte,56,52,pte + idtlbt pte,prot + + rfir + nop + +nadtlb_check_flush_20w: + bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate + + /* Insert a "flush only" translation */ + + depdi,z 7,7,3,prot + depdi 1,10,1,prot + + /* Get rid of prot bits and convert to page addr for idtlbt */ + + depdi 0,63,12,pte + extrd,u pte,56,52,pte + idtlbt pte,prot + + rfir + nop + #else dtlb_miss_11: @@ -889,13 +1143,13 @@ mfsp %sr7,t0 /* Get current space */ or,= %r0,t0,%r0 /* If kernel, nullify following test */ - comb,<>,n t0,spc,dtlb_fault /* forward */ + cmpb,<>,n t0,spc,dtlb_fault /* forward */ /* First level page table lookup */ ldwx,s t1(ptp),ptp extru va,19,10,t0 /* get second-level index */ - bb,>=,n ptp,_PAGE_PRESENT_BIT,dtlb_fault + bb,>=,n ptp,_PAGE_PRESENT_BIT,dtlb_check_alias_11 depi 0,31,12,ptp /* clear prot bits */ /* Second level page table lookup */ @@ -903,7 +1157,7 @@ sh2addl t0,ptp,ptp ldi _PAGE_ACCESSED,t1 ldw 0(ptp),pte - bb,>=,n pte,_PAGE_PRESENT_BIT,dtlb_fault + bb,>=,n pte,_PAGE_PRESENT_BIT,dtlb_check_alias_11 /* Check whether the "accessed" bit was set, otherwise do so */ @@ -911,8 +1165,8 @@ and,<> t1,pte,%r0 /* test and nullify if already set */ stw t0,0(ptp) /* write back pte */ - copy spc,prot /* init prot with faulting space */ - dep pte,8,7,prot + zdep spc,30,15,prot /* create prot id from space */ + dep pte,8,7,prot /* add in prot bits from pte */ extru,= pte,_PAGE_NO_CACHE_BIT,1,r0 depi 1,12,1,prot @@ -937,9 +1191,108 @@ rfir nop -dtlb_miss_20: - .level 2.0 +dtlb_check_alias_11: + + /* Check to see if fault is in the temporary alias region */ + + cmpib,<>,n 0,spc,dtlb_fault /* forward */ + ldil L%(TMPALIAS_MAP_START),t0 + copy va,t1 + depwi 0,31,23,t1 + cmpb,<>,n t0,t1,dtlb_fault /* forward */ + ldi (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),prot + depw,z prot,8,7,prot + + /* + * OK, it is in the temp alias region, check whether "from" or "to". + * Check "subtle" note in pacache.S re: r23/r26. + */ + + extrw,u,= va,9,1,r0 + or,tr %r23,%r0,pte /* If "from" use "from" page */ + or %r26,%r0,pte /* else "to", use "to" page */ + + idtlba pte,(va) + idtlbp prot,(va) + + rfir + nop + +nadtlb_miss_11: + mfctl %cr25,ptp /* Assume user space miss */ + or,<> %r0,spc,%r0 /* If it is user space, nullify */ + mfctl %cr24,ptp /* Load kernel pgd instead */ + extru va,9,10,t1 /* Get pgd index */ + + mfsp %sr7,t0 /* Get current space */ + or,= %r0,t0,%r0 /* If kernel, nullify following test */ + cmpb,<>,n t0,spc,nadtlb_fault /* forward */ + + /* First level page table lookup */ + + ldwx,s t1(ptp),ptp + extru va,19,10,t0 /* get second-level index */ + bb,>=,n ptp,_PAGE_PRESENT_BIT,nadtlb_emulate + depi 0,31,12,ptp /* clear prot bits */ + + /* Second level page table lookup */ + + sh2addl t0,ptp,ptp + ldi _PAGE_ACCESSED,t1 + ldw 0(ptp),pte + bb,>=,n pte,_PAGE_PRESENT_BIT,nadtlb_check_flush_11 + + zdep spc,30,15,prot /* create prot id from space */ + dep pte,8,7,prot /* add in prot bits from pte */ + + extru,= pte,_PAGE_NO_CACHE_BIT,1,r0 + depi 1,12,1,prot + extru,= pte,_PAGE_USER_BIT,1,r0 + depi 7,11,3,prot /* Set for user space (1 rsvd for read) */ + extru,= pte,_PAGE_GATEWAY_BIT,1,r0 + depi 0,11,2,prot /* If Gateway, Set PL2 to 0 */ + + /* Get rid of prot bits and convert to page addr for idtlba */ + + depi 0,31,12,pte + extru pte,24,25,pte + + mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ + mtsp spc,%sr1 + + idtlba pte,(%sr1,va) + idtlbp prot,(%sr1,va) + + mtsp t0, %sr1 /* Restore sr1 */ + + rfir + nop + +nadtlb_check_flush_11: + bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate + + /* Insert a "flush only" translation */ + + zdepi 7,7,3,prot + depi 1,10,1,prot + + /* Get rid of prot bits and convert to page addr for idtlba */ + + depi 0,31,12,pte + extru pte,24,25,pte + mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ + mtsp spc,%sr1 + + idtlba pte,(%sr1,va) + idtlbp prot,(%sr1,va) + + mtsp t0, %sr1 /* Restore sr1 */ + + rfir + nop + +dtlb_miss_20: mfctl %cr25,ptp /* Assume user space miss */ or,<> %r0,spc,%r0 /* If it is user space, nullify */ mfctl %cr24,ptp /* Load kernel pgd instead */ @@ -947,13 +1300,13 @@ mfsp %sr7,t0 /* Get current space */ or,= %r0,t0,%r0 /* If kernel, nullify following test */ - comb,<>,n t0,spc,dtlb_fault /* forward */ + cmpb,<>,n t0,spc,dtlb_fault /* forward */ /* First level page table lookup */ ldwx,s t1(ptp),ptp extru va,19,10,t0 /* get second-level index */ - bb,>=,n ptp,_PAGE_PRESENT_BIT,dtlb_fault + bb,>=,n ptp,_PAGE_PRESENT_BIT,dtlb_check_alias_20 depi 0,31,12,ptp /* clear prot bits */ /* Second level page table lookup */ @@ -961,7 +1314,7 @@ sh2addl t0,ptp,ptp ldi _PAGE_ACCESSED,t1 ldw 0(ptp),pte - bb,>=,n pte,_PAGE_PRESENT_BIT,dtlb_fault + bb,>=,n pte,_PAGE_PRESENT_BIT,dtlb_check_alias_20 /* Check whether the "accessed" bit was set, otherwise do so */ @@ -969,11 +1322,9 @@ and,<> t1,pte,%r0 /* test and nullify if already set */ stw t0,0(ptp) /* write back pte */ - copy spc,prot /* init prot with faulting space */ - - depd pte,8,7,prot - extrd,u,*= pte,_PAGE_NO_CACHE_BIT+32,1,r0 - depdi 1,12,1,prot + space_to_prot spc prot /* create prot id from space */ + depd pte,8,7,prot /* add in prot bits from pte */ + extrd,u,*= pte,_PAGE_USER_BIT+32,1,r0 depdi 7,11,3,prot /* Set for user space (1 rsvd for read) */ extrd,u,*= pte,_PAGE_GATEWAY_BIT+32,1,r0 @@ -981,16 +1332,145 @@ /* Get rid of prot bits and convert to page addr for idtlbt */ - depdi 0,63,12,pte - extrd,u pte,56,25,pte - idtlbt %r16,%r17 + extrd,s pte,35,4,t0 + depdi 0,63,12,pte /* clear lower 12 bits */ + addi,= 1,t0,0 + extrd,u,*tr pte,56,25,pte + extrd,s pte,56,25,pte /* bit 31:8 >> 8 */ + idtlbt pte,prot + + rfir + nop + +dtlb_check_alias_20: + + /* Check to see if fault is in the temporary alias region */ - .level 1.1 + cmpib,<>,n 0,spc,dtlb_fault /* forward */ + ldil L%(TMPALIAS_MAP_START),t0 + copy va,t1 + depwi 0,31,23,t1 + cmpb,<>,n t0,t1,dtlb_fault /* forward */ + ldi (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),prot + depd,z prot,8,7,prot + + /* + * OK, it is in the temp alias region, check whether "from" or "to". + * Check "subtle" note in pacache.S re: r23/r26. + */ + + extrw,u,= va,9,1,r0 + or,tr %r23,%r0,pte /* If "from" use "from" page */ + or %r26,%r0,pte /* else "to", use "to" page */ + + idtlbt pte,prot + + rfir + nop + +nadtlb_miss_20: + mfctl %cr25,ptp /* Assume user space miss */ + or,<> %r0,spc,%r0 /* If it is user space, nullify */ + mfctl %cr24,ptp /* Load kernel pgd instead */ + extru va,9,10,t1 /* Get pgd index */ + + mfsp %sr7,t0 /* Get current space */ + or,= %r0,t0,%r0 /* If kernel, nullify following test */ + cmpb,<>,n t0,spc,nadtlb_fault /* forward */ + + /* First level page table lookup */ + + ldwx,s t1(ptp),ptp + extru va,19,10,t0 /* get second-level index */ + bb,>=,n ptp,_PAGE_PRESENT_BIT,nadtlb_emulate + depi 0,31,12,ptp /* clear prot bits */ + + /* Second level page table lookup */ + + sh2addl t0,ptp,ptp + ldi _PAGE_ACCESSED,t1 + ldw 0(ptp),pte + bb,>=,n pte,_PAGE_PRESENT_BIT,nadtlb_check_flush_20 + + space_to_prot spc prot /* create prot id from space */ + depd pte,8,7,prot /* add in prot bits from pte */ + + extrd,u,*= pte,_PAGE_USER_BIT+32,1,r0 + depdi 7,11,3,prot /* Set for user space (1 rsvd for read) */ + extrd,u,*= pte,_PAGE_GATEWAY_BIT+32,1,r0 + depdi 0,11,2,prot /* If Gateway, Set PL2 to 0 */ + + /* Get rid of prot bits and convert to page addr for idtlbt */ + + extrd,s pte,35,4,t0 + depdi 0,63,12,pte /* clear lower 12 bits */ + addi,= 1,t0,0 + extrd,u,*tr pte,56,25,pte + extrd,s pte,56,25,pte /* bit 31:8 >> 8 */ + idtlbt pte,prot + + rfir + nop + +nadtlb_check_flush_20: + bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate + + /* Insert a "flush only" translation */ + + depdi,z 7,7,3,prot + depdi 1,10,1,prot + + /* Get rid of prot bits and convert to page addr for idtlbt */ + + depdi 0,63,12,pte + extrd,u pte,56,32,pte + idtlbt pte,prot rfir nop #endif +nadtlb_emulate: + + /* + * Non access misses can be caused by fdc,fic,pdc,lpa,probe and + * probei instructions. We don't want to fault for these + * instructions (not only does it not make sense, it can cause + * deadlocks, since some flushes are done with the mmap + * semaphore held). If the translation doesn't exist, we can't + * insert a translation, so have to emulate the side effects + * of the instruction. Since we don't insert a translation + * we can get a lot of faults during a flush loop, so it makes + * sense to try to do it here with minimum overhead. We only + * emulate fdc,fic & pdc instructions whose base and index + * registers are not shadowed. We defer everything else to the + * "slow" path. + */ + + mfctl %cr19,%r9 /* Get iir */ + ldi 0x280,%r16 + and %r9,%r16,%r17 + cmpb,<>,n %r16,%r17,nadtlb_fault /* Not fdc,fic,pdc */ + bb,>=,n %r9,26,nadtlb_nullify /* m bit not set, just nullify */ + b,l get_register,%r25 + extrw,u %r9,15,5,%r8 /* Get index register # */ + CMPIB=,n -1,%r1,nadtlb_fault /* have to use slow path */ + copy %r1,%r24 + b,l get_register,%r25 + extrw,u %r9,10,5,%r8 /* Get base register # */ + CMPIB=,n -1,%r1,nadtlb_fault /* have to use slow path */ + b,l set_register,%r25 + add,l %r1,%r24,%r1 /* doesn't affect c/b bits */ + +nadtlb_nullify: + mfctl %cr22,%r8 /* Get ipsw */ + ldil L%PSW_N,%r9 + or %r8,%r9,%r8 /* Set PSW_N */ + mtctl %r8,%cr22 + + rfir + nop + #ifdef __LP64__ itlb_miss_20w: @@ -999,9 +1479,9 @@ * on the gateway page which is in the kernel address space. */ - extrd,u spc,31,7,t1 /* adjust va */ + extrd,u spc,63,7,t1 /* adjust va */ depd t1,31,7,va /* adjust va */ - depdi 0,31,7,spc /* adjust space */ + depdi 0,63,7,spc /* adjust space */ cmpib,*= 0,spc,itlb_miss_kernel_20w extrd,u va,33,9,t1 /* Get pgd index */ @@ -1039,11 +1519,9 @@ and,*<> t1,pte,%r0 /* test and nullify if already set */ std t0,0(ptp) /* write back pte */ - copy spc,prot /* init prot with faulting space */ - - depd pte,8,7,prot - extrd,u,*= pte,_PAGE_NO_CACHE_BIT+32,1,r0 - depdi 1,12,1,prot + space_to_prot spc prot /* create prot id from space */ + depd pte,8,7,prot /* add in prot bits from pte */ + extrd,u,*= pte,_PAGE_USER_BIT+32,1,r0 depdi 7,11,3,prot /* Set for user space (1 rsvd for read) */ extrd,u,*= pte,_PAGE_GATEWAY_BIT+32,1,r0 @@ -1053,7 +1531,7 @@ depdi 0,63,12,pte extrd,u pte,56,32,pte - iitlbt %r16,%r17 + iitlbt pte,prot rfir nop @@ -1070,14 +1548,14 @@ * on the gateway page which is in the kernel address space. */ - comib,= 0,spc,itlb_miss_kernel_11 + cmpib,= 0,spc,itlb_miss_kernel_11 extru va,9,10,t1 /* Get pgd index */ mfctl %cr25,ptp /* load user pgd */ mfsp %sr7,t0 /* Get current space */ or,= %r0,t0,%r0 /* If kernel, nullify following test */ - comb,<>,n t0,spc,itlb_fault /* forward */ + cmpb,<>,n t0,spc,itlb_fault /* forward */ /* First level page table lookup */ @@ -1100,8 +1578,8 @@ and,<> t1,pte,%r0 /* test and nullify if already set */ stw t0,0(ptp) /* write back pte */ - copy spc,prot /* init prot with faulting space */ - dep pte,8,7,prot + zdep spc,30,15,prot /* create prot id from space */ + dep pte,8,7,prot /* add in prot bits from pte */ extru,= pte,_PAGE_NO_CACHE_BIT,1,r0 depi 1,12,1,prot @@ -1137,14 +1615,14 @@ * on the gateway page which is in the kernel address space. */ - comib,= 0,spc,itlb_miss_kernel_20 + cmpib,= 0,spc,itlb_miss_kernel_20 extru va,9,10,t1 /* Get pgd index */ mfctl %cr25,ptp /* load user pgd */ mfsp %sr7,t0 /* Get current space */ or,= %r0,t0,%r0 /* If kernel, nullify following test */ - comb,<>,n t0,spc,itlb_fault /* forward */ + cmpb,<>,n t0,spc,itlb_fault /* forward */ /* First level page table lookup */ @@ -1167,13 +1645,9 @@ and,<> t1,pte,%r0 /* test and nullify if already set */ stw t0,0(ptp) /* write back pte */ - copy spc,prot /* init prot with faulting space */ - - .level 2.0 + space_to_prot spc prot /* create prot id from space */ + depd pte,8,7,prot /* add in prot bits from pte */ - depd pte,8,7,prot - extrd,u,*= pte,_PAGE_NO_CACHE_BIT+32,1,r0 - depdi 1,12,1,prot extrd,u,*= pte,_PAGE_USER_BIT+32,1,r0 depdi 7,11,3,prot /* Set for user space (1 rsvd for read) */ extrd,u,*= pte,_PAGE_GATEWAY_BIT+32,1,r0 @@ -1181,10 +1655,12 @@ /* Get rid of prot bits and convert to page addr for iitlbt */ - depdi 0,63,12,pte - extrd,u pte,56,25,pte - iitlbt %r16,%r17 - .level 1.1 + extrd,s pte,35,4,t0 + depdi 0,63,12,pte /* clear lower 12 bits */ + addi,= 1,t0,0 + extrd,u,*tr pte,56,25,pte + extrd,s pte,56,25,pte /* bit 31:8 >> 8 */ + iitlbt pte,prot rfir nop @@ -1198,11 +1674,10 @@ #ifdef __LP64__ dbit_trap_20w: - - extrd,u spc,31,7,t1 /* adjust va */ + extrd,u spc,63,7,t1 /* adjust va */ depd t1,31,7,va /* adjust va */ depdi 0,1,2,va /* adjust va */ - depdi 0,31,7,spc /* adjust space */ + depdi 0,63,7,spc /* adjust space */ mfctl %cr25,ptp /* Assume user space miss */ or,*<> %r0,spc,%r0 /* If it is user space, nullify */ mfctl %cr24,ptp /* Load kernel pgd instead */ @@ -1210,7 +1685,7 @@ mfsp %sr7,t0 /* Get current space */ or,*= %r0,t0,%r0 /* If kernel, nullify following test */ - comb,<>,n t0,spc,dbit_fault /* forward */ + cmpb,*<>,n t0,spc,dbit_fault /* forward */ /* First level page table lookup */ @@ -1229,6 +1704,18 @@ /* Third level page table lookup */ shladd t0,3,ptp,ptp +#ifdef CONFIG_SMP + CMPIB=,n 0,spc,dbit_nolock_20w + ldil L%PA(pa_dbit_lock),t0 + ldo R%PA(pa_dbit_lock)(t0),t0 + +dbit_spin_20w: + ldcw 0(t0),t1 + cmpib,= 0,t1,dbit_spin_20w + nop + +dbit_nolock_20w: +#endif ldi (_PAGE_ACCESSED|_PAGE_DIRTY),t1 ldd 0(ptp),pte bb,>=,n pte,_PAGE_PRESENT_BIT,dbit_fault @@ -1238,11 +1725,9 @@ or t1,pte,pte std pte,0(ptp) /* write back pte */ - copy spc,prot /* init prot with faulting space */ - - depd pte,8,7,prot - extrd,u,*= pte,_PAGE_NO_CACHE_BIT+32,1,r0 - depdi 1,12,1,prot + space_to_prot spc prot /* create prot id from space */ + depd pte,8,7,prot /* add in prot bits from pte */ + extrd,u,*= pte,_PAGE_USER_BIT+32,1,r0 depdi 7,11,3,prot /* Set for user space (1 rsvd for read) */ extrd,u,*= pte,_PAGE_GATEWAY_BIT+32,1,r0 @@ -1251,8 +1736,15 @@ /* Get rid of prot bits and convert to page addr for idtlbt */ depdi 0,63,12,pte - extrd,u pte,56,32,pte - idtlbt %r16,%r17 + extrd,u pte,56,52,pte + idtlbt pte,prot +#ifdef CONFIG_SMP + CMPIB=,n 0,spc,dbit_nounlock_20w + ldi 1,t1 + stw t1,0(t0) + +dbit_nounlock_20w: +#endif rfir nop @@ -1266,7 +1758,7 @@ mfsp %sr7,t0 /* Get current space */ or,= %r0,t0,%r0 /* If kernel, nullify following test */ - comb,<>,n t0,spc,dbit_fault /* forward */ + cmpb,<>,n t0,spc,dbit_fault /* forward */ /* First level page table lookup */ @@ -1278,6 +1770,18 @@ /* Second level page table lookup */ sh2addl t0,ptp,ptp +#ifdef CONFIG_SMP + CMPIB=,n 0,spc,dbit_nolock_11 + ldil L%PA(pa_dbit_lock),t0 + ldo R%PA(pa_dbit_lock)(t0),t0 + +dbit_spin_11: + ldcw 0(t0),t1 + cmpib,= 0,t1,dbit_spin_11 + nop + +dbit_nolock_11: +#endif ldi (_PAGE_ACCESSED|_PAGE_DIRTY),t1 ldw 0(ptp),pte bb,>=,n pte,_PAGE_PRESENT_BIT,dbit_fault @@ -1287,8 +1791,8 @@ or t1,pte,pte stw pte,0(ptp) /* write back pte */ - copy spc,prot /* init prot with faulting space */ - dep pte,8,7,prot + zdep spc,30,15,prot /* create prot id from space */ + dep pte,8,7,prot /* add in prot bits from pte */ extru,= pte,_PAGE_NO_CACHE_BIT,1,r0 depi 1,12,1,prot @@ -1302,13 +1806,20 @@ depi 0,31,12,pte extru pte,24,25,pte - mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ + mfsp %sr1,t1 /* Save sr1 so we can use it in tlb inserts */ mtsp spc,%sr1 idtlba pte,(%sr1,va) idtlbp prot,(%sr1,va) - mtsp t0, %sr1 /* Restore sr1 */ + mtsp t1, %sr1 /* Restore sr1 */ +#ifdef CONFIG_SMP + CMPIB=,n 0,spc,dbit_nounlock_11 + ldi 1,t1 + stw t1,0(t0) + +dbit_nounlock_11: +#endif rfir nop @@ -1321,7 +1832,7 @@ mfsp %sr7,t0 /* Get current space */ or,= %r0,t0,%r0 /* If kernel, nullify following test */ - comb,<>,n t0,spc,dbit_fault /* forward */ + cmpb,<>,n t0,spc,dbit_fault /* forward */ /* First level page table lookup */ @@ -1333,6 +1844,18 @@ /* Second level page table lookup */ sh2addl t0,ptp,ptp +#ifdef CONFIG_SMP + CMPIB=,n 0,spc,dbit_nolock_20 + ldil L%PA(pa_dbit_lock),t0 + ldo R%PA(pa_dbit_lock)(t0),t0 + +dbit_spin_20: + ldcw 0(t0),t1 + cmpib,= 0,t1,dbit_spin_20 + nop + +dbit_nolock_20: +#endif ldi (_PAGE_ACCESSED|_PAGE_DIRTY),t1 ldw 0(ptp),pte bb,>=,n pte,_PAGE_PRESENT_BIT,dbit_fault @@ -1342,25 +1865,28 @@ or t1,pte,pte stw pte,0(ptp) /* write back pte */ - copy spc,prot /* init prot with faulting space */ - - .level 2.0 + space_to_prot spc prot /* create prot id from space */ + depd pte,8,7,prot /* add in prot bits from pte */ - depd pte,8,7,prot - extrd,u,*= pte,_PAGE_NO_CACHE_BIT+32,1,r0 - depdi 1,12,1,prot extrd,u,*= pte,_PAGE_USER_BIT+32,1,r0 depdi 7,11,3,prot /* Set for user space (1 rsvd for read) */ extrd,u,*= pte,_PAGE_GATEWAY_BIT+32,1,r0 depdi 0,11,2,prot /* If Gateway, Set PL2 to 0 */ - /* Get rid of prot bits and convert to page addr for idtlbt */ + extrd,s pte,35,4,t0 + depdi 0,63,12,pte /* clear lower 12 bits */ + addi,= 1,t0,0 + extrd,u,*tr pte,56,25,pte + extrd,s pte,56,25,pte /* bit 31:8 >> 8 */ + idtlbt pte,prot - depdi 0,63,12,pte - extrd,u pte,56,25,pte - idtlbt %r16,%r17 +#ifdef CONFIG_SMP + CMPIB=,n 0,spc,dbit_nounlock_20 + ldi 1,t1 + stw t1,0(t0) - .level 1.1 +dbit_nounlock_20: +#endif rfir nop @@ -1369,50 +1895,24 @@ .import handle_interruption,code kernel_bad_space: - b tlb_fault - ldi 31,%r1 /* Use an unused code */ + b intr_save + ldi 31,%r8 /* Use an unused code */ dbit_fault: - b tlb_fault - ldi 20,%r1 + b intr_save + ldi 20,%r8 itlb_fault: - b tlb_fault - ldi 6,%r1 - -dtlb_fault: - ldi 15,%r1 + b intr_save + ldi 6,%r8 - /* Fall Through */ +nadtlb_fault: + b intr_save + ldi 17,%r8 -tlb_fault: - mtctl %r1,%cr29 - mtctl %r29,%cr31 - - get_stack - save_specials %r29 /* Note this saves a trashed r1 */ - - SAVE_CR (%cr20, PT_ISR(%r29)) - SAVE_CR (%cr21, PT_IOR(%r29)) - - virt_map rfir - - STREG %r1,PT_GR1(%r29) /* save good value after rfir */ - - save_general %r29 - - ldo PT_FR0(%r29), %r25 - save_fp %r25 - - loadgp - - copy %r29, %r25 - - bl handle_interruption, %r2 - copy %r29, %r16 - - b intr_return - nop +dtlb_fault: + b intr_save + ldi 15,%r8 /* Register saving semantics for system calls: @@ -1475,21 +1975,23 @@ .endm .export sys_fork_wrapper + .export child_return sys_fork_wrapper: ldo TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get pt regs */ reg_save %r1 + mfctl %cr27, %r3 + STREG %r3, PT_CR27(%r1) STREG %r2,-RP_OFFSET(%r30) ldo FRAME_SIZE(%r30),%r30 +#ifdef __LP64__ + ldo -16(%r30),%r29 /* Reference param save area */ +#endif /* These are call-clobbered registers and therefore also syscall-clobbered (we hope). */ STREG %r2,PT_GR19(%r1) /* save for child */ - STREG %r30,PT_GR20(%r1) - ldil L%child_return, %r3 - ldo R%child_return(%r3), %r3 - LDIL_FIXUP(%r3) - STREG %r3,PT_GR21(%r1) /* save for child */ + STREG %r30,PT_GR21(%r1) LDREG PT_GR30(%r1),%r25 copy %r1,%r24 @@ -1501,14 +2003,21 @@ ldo -FRAME_SIZE(%r30),%r30 /* get the stackframe */ ldo TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get pt regs */ + LDREG PT_CR27(%r1), %r3 + mtctl %r3, %cr27 reg_restore %r1 + /* strace expects syscall # to be preserved in r20 */ + ldi __NR_fork,%r20 bv %r0(%r2) - nop + STREG %r20,PT_GR20(%r1) /* Set the return value for the child */ child_return: - LDREG TASK_PT_GR19-TASK_SZ_ALGN-128(%r30),%r2 + bl schedule_tail, %r2 + nop + + LDREG TASK_PT_GR19-TASK_SZ_ALGN-FRAME_SIZE-FRAME_SIZE(%r30),%r2 b wrapper_exit copy %r0,%r28 @@ -1517,35 +2026,38 @@ sys_clone_wrapper: ldo TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get pt regs */ reg_save %r1 + mfctl %cr27, %r3 + STREG %r3, PT_CR27(%r1) STREG %r2,-RP_OFFSET(%r30) ldo FRAME_SIZE(%r30),%r30 +#ifdef __LP64__ + ldo -16(%r30),%r29 /* Reference param save area */ +#endif - STREG %r30,PT_GR20(%r1) - ldil L%child_return,%r3 - ldo R%child_return(%r3),%r3 - LDIL_FIXUP(%r3) - + STREG %r2,PT_GR19(%r1) /* save for child */ + STREG %r30,PT_GR21(%r1) bl sys_clone,%r2 - STREG %r3,PT_GR21(%r1) /* save for child */ + copy %r1,%r24 b wrapper_exit LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2 - .export sys_vfork_wrapper sys_vfork_wrapper: ldo TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get pt regs */ reg_save %r1 + mfctl %cr27, %r3 + STREG %r3, PT_CR27(%r1) STREG %r2,-RP_OFFSET(%r30) ldo FRAME_SIZE(%r30),%r30 +#ifdef __LP64__ + ldo -16(%r30),%r29 /* Reference param save area */ +#endif - STREG %r30,PT_GR20(%r1) - ldil L%child_return,%r3 - ldo R%child_return(%r3),%r3 - LDIL_FIXUP(%r3) - STREG %r3,PT_GR21(%r1) /* save for child */ + STREG %r2,PT_GR19(%r1) /* save for child */ + STREG %r30,PT_GR21(%r1) bl sys_vfork,%r2 copy %r1,%r26 @@ -1567,6 +2079,9 @@ STREG %r2,-RP_OFFSET(%r30) ldo FRAME_SIZE(%r30),%r30 +#ifdef __LP64__ + ldo -16(%r30),%r29 /* Reference param save area */ +#endif bl \execve,%r2 copy %r1,%arg0 @@ -1576,7 +2091,7 @@ /* If exec succeeded we need to load the args */ ldo -1024(%r0),%r1 - comb,>>= %r28,%r1,error_\execve + cmpb,>>= %r28,%r1,error_\execve copy %r2,%r19 error_\execve: @@ -1603,8 +2118,14 @@ ldo TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30), %r26 /* Don't save regs, we are going to restore them from sigcontext. */ STREG %r2, -RP_OFFSET(%r30) +#ifdef __LP64__ + ldo FRAME_SIZE(%r30), %r30 + bl sys_rt_sigreturn,%r2 + ldo -16(%r30),%r29 /* Reference param save area */ +#else bl sys_rt_sigreturn,%r2 ldo FRAME_SIZE(%r30), %r30 +#endif ldo -FRAME_SIZE(%r30), %r30 LDREG -RP_OFFSET(%r30), %r2 @@ -1625,22 +2146,50 @@ /* Get the user stack pointer */ LDREG -TASK_SZ_ALGN-FRAME_SIZE+TASK_PT_GR30(%r30), %r24 STREG %r2, -RP_OFFSET(%r30) +#ifdef __LP64__ + ldo FRAME_SIZE(%r30), %r30 + bl do_sigaltstack,%r2 + ldo -16(%r30),%r29 /* Reference param save area */ +#else bl do_sigaltstack,%r2 ldo FRAME_SIZE(%r30), %r30 +#endif ldo -FRAME_SIZE(%r30), %r30 LDREG -RP_OFFSET(%r30), %r2 bv %r0(%r2) nop +#ifdef __LP64__ + .export sys32_sigaltstack_wrapper +sys32_sigaltstack_wrapper: + /* Get the user stack pointer */ + LDREG -TASK_SZ_ALGN-FRAME_SIZE+TASK_PT_GR30(%r30), %r24 + STREG %r2, -RP_OFFSET(%r30) + ldo FRAME_SIZE(%r30), %r30 + bl do_sigaltstack32,%r2 + ldo -16(%r30),%r29 /* Reference param save area */ + + ldo -FRAME_SIZE(%r30), %r30 + LDREG -RP_OFFSET(%r30), %r2 + bv %r0(%r2) + nop +#endif + .export sys_rt_sigsuspend_wrapper sys_rt_sigsuspend_wrapper: ldo TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30), %r24 reg_save %r24 STREG %r2, -RP_OFFSET(%r30) +#ifdef __LP64__ + ldo FRAME_SIZE(%r30), %r30 + bl sys_rt_sigsuspend,%r2 + ldo -16(%r30),%r29 /* Reference param save area */ +#else bl sys_rt_sigsuspend,%r2 ldo FRAME_SIZE(%r30), %r30 +#endif ldo -FRAME_SIZE(%r30), %r30 LDREG -RP_OFFSET(%r30), %r2 @@ -1658,66 +2207,80 @@ values. */ /* NOTE: Not all syscalls exit this way. rt_sigreturn will exit * via syscall_exit_rfi if the signal was received while the process - * was running. All traced processes will probably exit via - * syscall_exit_rfi in the future. + * was running. */ /* save return value now */ STREG %r28,TASK_PT_GR28-TASK_SZ_ALGN-FRAME_SIZE(%r30) + /* Save other hpux returns if personality is PER_HPUX */ + +#define PER_HPUX 0xe /* cannot be easily included */ + + LDREG TASK_PERSONALITY-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r19 + CMPIB<>,n PER_HPUX,%r19,1f + STREG %r22,TASK_PT_GR22-TASK_SZ_ALGN-FRAME_SIZE(%r30) + STREG %r29,TASK_PT_GR29-TASK_SZ_ALGN-FRAME_SIZE(%r30) +1: + + /* Seems to me that dp could be wrong here, if the syscall involved + * calling a module, and nothing got round to restoring dp on return. + */ + loadgp + syscall_check_bh: -/* #ifdef NOTNOW */ /* Check for software interrupts */ .import irq_stat,data ldil L%irq_stat,%r19 ldo R%irq_stat(%r19),%r19 - LDIL_FIXUP(%r19) #ifdef CONFIG_SMP /* sched.h: int processor */ - ldw TASK_PROCESSOR-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r20 /* get cpu # */ -#if (IRQSTAT_SZ == 32) - dep %r20,26,27,%r20 /* shift left 5 bits */ -#else -#error IRQSTAT_SZ changed, fix dep -#endif /* IRQSTAT_SZ */ - add %r19,%r20,%r19 -#endif /* CONFIG_SMP */ + /* %r26 is used as scratch register to index into irq_stat[] */ + ldw TASK_PROCESSOR-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r26 /* cpu # */ - ldw IRQSTAT_SI_ACTIVE(%r19),%r20 /* hardirq.h: unsigned int */ - ldw IRQSTAT_SI_MASK(%r19),%r19 /* hardirq.h: unsigned int */ - and %r19,%r20,%r20 - comib,<>,n 0,%r20,syscall_do_softirq /* forward */ -/* #endif */ + /* shift left ____cacheline_aligned (aka L1_CACHE_BYTES) bits */ +#ifdef __LP64__ + shld %r26, 6, %r20 +#else + shlw %r26, 5, %r20 +#endif + add %r19,%r20,%r19 /* now have &irq_stat[smp_processor_id()] */ +#endif /* CONFIG_SMP */ + LDREG IRQSTAT_SIRQ_PEND(%r19),%r20 /* hardirq.h: unsigned long */ + cmpib,<>,n 0,%r20,syscall_do_softirq /* forward */ syscall_check_resched: /* check for reschedule */ LDREG TASK_NEED_RESCHED-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r19 /* long */ - comib,<>,n 0,%r19,syscall_do_resched /* forward */ + CMPIB<>,n 0,%r19,syscall_do_resched /* forward */ syscall_check_sig: ldo -TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */ /* check for pending signals */ ldw TASK_SIGPENDING(%r1),%r19 - comib,<>,n 0,%r19,syscall_do_signal /* forward */ + cmpib,<>,n 0,%r19,syscall_do_signal /* forward */ syscall_restore: - /* disable interrupts while dicking with the kernel stack, */ - /* or life can become unpleasant */ - rsm PSW_SM_I, %r20 LDREG TASK_PTRACE(%r1), %r19 /* Are we being ptraced? */ bb,<,n %r19,31,syscall_restore_rfi - LDREG TASK_PT_GR20(%r1),%r19 - mtctl %r19, %cr27 + + ldo TASK_PT_FR31(%r1),%r19 /* reload fpregs */ + rest_fp %r19 + + LDREG TASK_PT_SAR(%r1),%r19 /* restore SAR */ + mtsar %r19 LDREG TASK_PT_GR2(%r1),%r2 /* restore user rp */ + LDREG TASK_PT_GR19(%r1),%r19 + LDREG TASK_PT_GR20(%r1),%r20 LDREG TASK_PT_GR21(%r1),%r21 LDREG TASK_PT_GR22(%r1),%r22 LDREG TASK_PT_GR23(%r1),%r23 @@ -1727,43 +2290,31 @@ LDREG TASK_PT_GR27(%r1),%r27 /* restore user dp */ LDREG TASK_PT_GR28(%r1),%r28 /* syscall return value */ LDREG TASK_PT_GR29(%r1),%r29 - LDREG TASK_PT_GR30(%r1),%r30 /* restore user sp */ LDREG TASK_PT_GR31(%r1),%r31 /* restore syscall rp */ - ldo TASK_PT_FR31(%r1),%r19 /* reload fpregs */ - rest_fp %r19 - LDREG TASK_PT_SAR(%r1),%r19 /* restore SAR */ - mtsar %r19 - LDREG TASK_PT_GR19(%r1),%r19 - mtctl %r1,%cr30 /* intrhandler okay. */ + rsm PSW_SM_I, %r0 + LDREG TASK_PT_GR30(%r1),%r30 /* restore user sp */ mfsp %sr3,%r1 /* Get users space id */ + mtsp %r1,%sr7 /* Restore sr7 */ + ssm PSW_SM_I, %r0 mtsp %r1,%sr4 /* Restore sr4 */ mtsp %r1,%sr5 /* Restore sr5 */ mtsp %r1,%sr6 /* Restore sr6 */ depi 3,31,2,%r31 /* ensure return to user mode. */ - mtsm %r20 /* restore irq state */ - mfctl %cr27,%r20 - - /* - * Due to a dependency in the tlb miss handlers on sr7, it - * is essential that sr7 get set in the delay slot. - */ - #ifdef __LP64__ - - /* Note the be (and mtsp) is executed in narrow mode. This is OK - * for 32 bit processes, but won't work once we support 64 bit - * processes. + /* Since we are returning to a 32 bit user process, we always + * clear the W bit. This means that the be (and mtsp) gets + * executed in narrow mode, but that is OK, since we are + * returning to a 32 bit process. When we support 64 bit processes + * we won't clear the W bit, so the be will run in wide mode. */ - rsm PSW_SM_W, %r0 be 0(%sr3,%r31) /* return to user space */ - mtsp %r1,%sr7 /* Restore sr7 */ + rsm PSW_SM_W, %r0 #else - be 0(%sr3,%r31) /* return to user space */ - mtsp %r1,%sr7 /* Restore sr7 */ + be,n 0(%sr3,%r31) /* return to user space */ #endif /* We have to return via an RFI, so that PSW T and R bits can be set @@ -1774,43 +2325,52 @@ syscall_restore_rfi: ldo -1(%r0),%r2 /* Set recovery cntr to -1 */ mtctl %r2,%cr0 /* for immediate trap */ - copy %r0,%r2 /* Create a reasonable PSW */ + LDREG TASK_PT_PSW(%r1),%r2 /* Get old PSW */ + ldi 0x0b,%r20 /* Create new PSW */ + depi -1,13,1,%r20 /* C, Q, D, and I bits */ + bb,>=,n %r19,15,try_tbit /* PT_SINGLESTEP */ + depi -1,27,1,%r20 /* R bit */ +try_tbit: + bb,>=,n %r19,14,psw_setup /* PT_BLOCKSTEP, see ptrace.c */ + depi -1,7,1,%r20 /* T bit */ +psw_setup: + STREG %r20,TASK_PT_PSW(%r1) + + /* Always store space registers, since sr3 can be changed (e.g. fork) */ + + mfsp %sr3,%r25 + STREG %r25,TASK_PT_SR3(%r1) + STREG %r25,TASK_PT_SR4(%r1) + STREG %r25,TASK_PT_SR5(%r1) + STREG %r25,TASK_PT_SR6(%r1) + STREG %r25,TASK_PT_SR7(%r1) + STREG %r25,TASK_PT_IASQ0(%r1) + STREG %r25,TASK_PT_IASQ1(%r1) + /* XXX W bit??? */ - depi -1,13,1,%r2 - depi -1,28,1,%r2 - depi -1,30,1,%r2 - depi -1,31,1,%r2 - bb,<,n %r19,15,set_rbit /* PT_SINGLESTEP */ - bb,>=,n %r19,14,set_nobit /* PT_BLOCKSTEP, see ptrace.c */ -set_tbit: - depi -1,7,1,%r2 - b,n set_nobit -set_rbit: - depi -1,27,1,%r2 -set_nobit: - STREG %r2,TASK_PT_PSW(%r1) - STREG %r1,TASK_PT_CR30(%r1) + /* Now if old D bit is clear, it means we didn't save all registers + * on syscall entry, so do that now. This only happens on TRACEME + * calls, or if someone attached to us while we were on a syscall. + * We could make this more efficient by not saving r3-r18, but + * then we wouldn't be able to use the common intr_restore path. + * It is only for traced processes anyway, so performance is not + * an issue. + */ + bb,< %r2,30,pt_regs_ok /* Branch if D set */ + ldo TASK_REGS(%r1),%r25 + reg_save %r25 /* Save r3 to r18 */ mfsp %sr0,%r2 STREG %r2,TASK_PT_SR0(%r1) mfsp %sr1,%r2 STREG %r2,TASK_PT_SR1(%r1) mfsp %sr2,%r2 STREG %r2,TASK_PT_SR2(%r1) - mfsp %sr3,%r2 - STREG %r2,TASK_PT_SR3(%r1) - STREG %r2,TASK_PT_SR4(%r1) - STREG %r2,TASK_PT_SR5(%r1) - STREG %r2,TASK_PT_SR6(%r1) - STREG %r2,TASK_PT_SR7(%r1) - STREG %r2,TASK_PT_IASQ0(%r1) - STREG %r2,TASK_PT_IASQ1(%r1) +pt_regs_ok: LDREG TASK_PT_GR31(%r1),%r2 depi 3,31,2,%r2 /* ensure return to user mode. */ STREG %r2,TASK_PT_IAOQ0(%r1) ldo 4(%r2),%r2 STREG %r2,TASK_PT_IAOQ1(%r1) - ldo TASK_REGS(%r1),%r25 - reg_save %r25 /* Save r3 to r18 */ copy %r25,%r16 b intr_restore nop @@ -1825,7 +2385,11 @@ .import schedule,code syscall_do_resched: bl schedule,%r2 +#ifdef __LP64__ + ldo -16(%r30),%r29 /* Reference param save area */ +#else nop +#endif b syscall_check_bh /* if resched, we start over again */ nop @@ -1840,6 +2404,9 @@ ldi 1, %r24 /* unsigned long in_syscall */ +#ifdef __LP64__ + ldo -16(%r30),%r29 /* Reference param save area */ +#endif bl do_signal,%r2 copy %r0, %r26 /* sigset_t *oldset = NULL */ @@ -1849,19 +2416,155 @@ b,n syscall_restore -#ifdef __LP64__ -unimplemented_64bitirq: - ssm PSW_SM_Q+PSW_SM_I, %r0 - /* indicate that we had an interrupt */ - ldi 0x77, %r28 - ldi 0x77, %r29 - /* save interrupt registers in GRs for diagnosis */ - mfctl %cr17, %r17 - mfctl %cr18, %r18 - mfctl %cr19, %r19 - mfctl %cr20, %r20 - mfctl %cr21, %r21 - mfctl %cr22, %r22 - b,n . - nop -#endif + /* + * get_register is used by the non access tlb miss handlers to + * copy the value of the general register specified in r8 into + * r1. This routine can't be used for shadowed registers, since + * the rfir will restore the original value. So, for the shadowed + * registers we put a -1 into r1 to indicate that the register + * should not be used (the register being copied could also have + * a -1 in it, but that is OK, it just means that we will have + * to use the slow path instead). + */ + +get_register: + blr %r8,%r0 + nop + bv %r0(%r25) /* r0 */ + copy %r0,%r1 + bv %r0(%r25) /* r1 - shadowed */ + ldi -1,%r1 + bv %r0(%r25) /* r2 */ + copy %r2,%r1 + bv %r0(%r25) /* r3 */ + copy %r3,%r1 + bv %r0(%r25) /* r4 */ + copy %r4,%r1 + bv %r0(%r25) /* r5 */ + copy %r5,%r1 + bv %r0(%r25) /* r6 */ + copy %r6,%r1 + bv %r0(%r25) /* r7 */ + copy %r7,%r1 + bv %r0(%r25) /* r8 - shadowed */ + ldi -1,%r1 + bv %r0(%r25) /* r9 - shadowed */ + ldi -1,%r1 + bv %r0(%r25) /* r10 */ + copy %r10,%r1 + bv %r0(%r25) /* r11 */ + copy %r11,%r1 + bv %r0(%r25) /* r12 */ + copy %r12,%r1 + bv %r0(%r25) /* r13 */ + copy %r13,%r1 + bv %r0(%r25) /* r14 */ + copy %r14,%r1 + bv %r0(%r25) /* r15 */ + copy %r15,%r1 + bv %r0(%r25) /* r16 - shadowed */ + ldi -1,%r1 + bv %r0(%r25) /* r17 - shadowed */ + ldi -1,%r1 + bv %r0(%r25) /* r18 */ + copy %r18,%r1 + bv %r0(%r25) /* r19 */ + copy %r19,%r1 + bv %r0(%r25) /* r20 */ + copy %r20,%r1 + bv %r0(%r25) /* r21 */ + copy %r21,%r1 + bv %r0(%r25) /* r22 */ + copy %r22,%r1 + bv %r0(%r25) /* r23 */ + copy %r23,%r1 + bv %r0(%r25) /* r24 - shadowed */ + ldi -1,%r1 + bv %r0(%r25) /* r25 - shadowed */ + ldi -1,%r1 + bv %r0(%r25) /* r26 */ + copy %r26,%r1 + bv %r0(%r25) /* r27 */ + copy %r27,%r1 + bv %r0(%r25) /* r28 */ + copy %r28,%r1 + bv %r0(%r25) /* r29 */ + copy %r29,%r1 + bv %r0(%r25) /* r30 */ + copy %r30,%r1 + bv %r0(%r25) /* r31 */ + copy %r31,%r1 + + /* + * set_register is used by the non access tlb miss handlers to + * copy the value of r1 into the general register specified in + * r8. + */ + +set_register: + blr %r8,%r0 + nop + bv %r0(%r25) /* r0 (silly, but it is a place holder) */ + copy %r1,%r0 + bv %r0(%r25) /* r1 */ + copy %r1,%r1 + bv %r0(%r25) /* r2 */ + copy %r1,%r2 + bv %r0(%r25) /* r3 */ + copy %r1,%r3 + bv %r0(%r25) /* r4 */ + copy %r1,%r4 + bv %r0(%r25) /* r5 */ + copy %r1,%r5 + bv %r0(%r25) /* r6 */ + copy %r1,%r6 + bv %r0(%r25) /* r7 */ + copy %r1,%r7 + bv %r0(%r25) /* r8 */ + copy %r1,%r8 + bv %r0(%r25) /* r9 */ + copy %r1,%r9 + bv %r0(%r25) /* r10 */ + copy %r1,%r10 + bv %r0(%r25) /* r11 */ + copy %r1,%r11 + bv %r0(%r25) /* r12 */ + copy %r1,%r12 + bv %r0(%r25) /* r13 */ + copy %r1,%r13 + bv %r0(%r25) /* r14 */ + copy %r1,%r14 + bv %r0(%r25) /* r15 */ + copy %r1,%r15 + bv %r0(%r25) /* r16 */ + copy %r1,%r16 + bv %r0(%r25) /* r17 */ + copy %r1,%r17 + bv %r0(%r25) /* r18 */ + copy %r1,%r18 + bv %r0(%r25) /* r19 */ + copy %r1,%r19 + bv %r0(%r25) /* r20 */ + copy %r1,%r20 + bv %r0(%r25) /* r21 */ + copy %r1,%r21 + bv %r0(%r25) /* r22 */ + copy %r1,%r22 + bv %r0(%r25) /* r23 */ + copy %r1,%r23 + bv %r0(%r25) /* r24 */ + copy %r1,%r24 + bv %r0(%r25) /* r25 */ + copy %r1,%r25 + bv %r0(%r25) /* r26 */ + copy %r1,%r26 + bv %r0(%r25) /* r27 */ + copy %r1,%r27 + bv %r0(%r25) /* r28 */ + copy %r1,%r28 + bv %r0(%r25) /* r29 */ + copy %r1,%r29 + bv %r0(%r25) /* r30 */ + copy %r1,%r30 + bv %r0(%r25) /* r31 */ + copy %r1,%r31 diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/firmware.c linux.19rc3-ac4/arch/parisc/kernel/firmware.c --- linux.19rc3/arch/parisc/kernel/firmware.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/firmware.c 2002-07-29 13:58:36.000000000 +0100 @@ -0,0 +1,1111 @@ +/* arch/parisc/kernel/pdc.c - safe pdc access routines + * + * Copyright 1999 SuSE GmbH Nuernberg (Philipp Rumpf, prumpf@tux.org) + * portions Copyright 1999 The Puffin Group, (Alex deVries, David Kennedy) + * + * only these routines should be used out of the real kernel (i.e. everything + * using virtual addresses) for obvious reasons */ + +/* I think it would be in everyone's best interest to follow this + * guidelines when writing PDC wrappers: + * + * - the name of the pdc wrapper should match one of the macros + * used for the first two arguments + * - don't use caps for random parts of the name + * - use the static PDC result buffers and "copyout" to structs + * supplied by the caller to encapsulate alignment restrictions + * - hold pdc_lock while in PDC or using static result buffers + * - use __pa() to convert virtual (kernel) pointers to physical + * ones. + * - the name of the struct used for pdc return values should equal + * one of the macros used for the first two arguments to the + * corresponding PDC call + * - keep the order of arguments + * - don't be smart (setting trailing NUL bytes for strings, return + * something useful even if the call failed) unless you are sure + * it's not going to affect functionality or performance + * + * Example: + * int pdc_cache_info(struct pdc_cache_info *cache_info ) + * { + * int retval; + * + * spin_lock_irq(&pdc_lock); + * retval = mem_pdc_call(PDC_CACHE,PDC_CACHE_INFO,__pa(cache_info),0); + * convert_to_wide(pdc_result); + * memcpy(cache_info, pdc_result, sizeof(*cache_info)); + * spin_unlock_irq(&pdc_lock); + * + * return retval; + * } + * prumpf 991016 + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include /* for boot_cpu_data */ + +#include + +static spinlock_t pdc_lock = SPIN_LOCK_UNLOCKED; +static unsigned long pdc_result[32] __attribute__ ((aligned (8))); +static unsigned long pdc_result2[32] __attribute__ ((aligned (8))); + +/* on all currently-supported platforms, IODC I/O calls are always + * 32-bit calls, and MEM_PDC calls are always the same width as the OS. + * This means Cxxx boxes can't run wide kernels right now. -PB + * + * CONFIG_PDC_NARROW has been added to allow 64-bit kernels to run on + * systems with 32-bit MEM_PDC calls. This will allow wide kernels to + * run on Cxxx boxes now. -RB + * + * Note that some PAT boxes may have 64-bit IODC I/O... + */ + +#ifdef __LP64__ +static long real64_call(unsigned long function, ...); +#endif +static long real32_call(unsigned long function, ...); + +#if defined(__LP64__) && ! defined(CONFIG_PDC_NARROW) +#define MEM_PDC (unsigned long)(PAGE0->mem_pdc_hi) << 32 | PAGE0->mem_pdc +# define mem_pdc_call(args...) real64_call(MEM_PDC, args) +#else +#define MEM_PDC (unsigned long)PAGE0->mem_pdc +# define mem_pdc_call(args...) real32_call(MEM_PDC, args) +#endif + + +/** + * f_extend - Convert PDC addresses to kernel addresses. + * @address: Address returned from PDC. + * + * This function is used to convert PDC addresses into kernel addresses + * when the PDC address size and kernel address size are different. + */ +static unsigned long f_extend(unsigned long address) +{ +#ifdef CONFIG_PDC_NARROW + if((address & 0xff000000) == 0xf0000000) + return 0xf0f0f0f000000000 | (u32)address; + + if((address & 0xf0000000) == 0xf0000000) + return 0xffffffff00000000 | (u32)address; +#endif + return address; +} + +/** + * convert_to_wide - Convert the return buffer addresses into kernel addresses. + * @address: The return buffer from PDC. + * + * This function is used to convert the return buffer addresses retrieved from PDC + * into kernel addresses when the PDC address size and kernel address size are + * different. + */ +static void convert_to_wide(unsigned long *addr) +{ +#ifdef CONFIG_PDC_NARROW + int i; + unsigned *p = (unsigned int *)addr; + for(i = 31; i >= 0; --i) + addr[i] = p[i]; +#endif +} + +/** + * pdc_emergency_unlock - Unlock the linux pdc lock + * + * This call unlocks the linux pdc lock in case we need some PDC functions + * (like pdc_add_valid) during kernel stack dump. + */ +void pdc_emergency_unlock(void) +{ + spin_unlock(&pdc_lock); +} + + +/** + * pdc_add_valid - Verify address can be accessed without causing a HPMC. + * @address: Address to be verified. + * + * This PDC call attempts to read from the specified address and verifies + * if the address is valid. + * + * The return value is PDC_OK (0) in case accessing this address is valid. + */ +int pdc_add_valid(unsigned long address) +{ + int retval; + + spin_lock_irq(&pdc_lock); + retval = mem_pdc_call(PDC_ADD_VALID, PDC_ADD_VALID_VERIFY, address); + spin_unlock_irq(&pdc_lock); + + return retval; +} + +/** + * pdc_chassis_info - Return chassis information. + * @result: The return buffer. + * @chassis_info: The memory buffer address. + * @len: The size of the memory buffer address. + * + * An HVERSION dependent call for returning the chassis information. + */ +int __init pdc_chassis_info(struct pdc_chassis_info *chassis_info, void *led_info, unsigned long len) +{ + int retval; + + spin_lock_irq(&pdc_lock); + memcpy(&pdc_result, chassis_info, sizeof(*chassis_info)); + memcpy(&pdc_result2, led_info, len); + retval = mem_pdc_call(PDC_CHASSIS, PDC_RETURN_CHASSIS_INFO, + __pa(pdc_result), __pa(pdc_result2), len); + memcpy(chassis_info, pdc_result, sizeof(*chassis_info)); + memcpy(led_info, pdc_result2, len); + spin_unlock_irq(&pdc_lock); + + return retval; +} + +/** + * pdc_coproc_cfg - To identify coprocessors attached to the processor. + * @pdc_coproc_info: Return buffer address. + * + * This PDC call returns the presence and status of all the coprocessors + * attached to the processor. + */ +int __init pdc_coproc_cfg(struct pdc_coproc_cfg *pdc_coproc_info) +{ + int retval; + + spin_lock_irq(&pdc_lock); + retval = mem_pdc_call(PDC_COPROC, PDC_COPROC_CFG, __pa(pdc_result)); + convert_to_wide(pdc_result); + pdc_coproc_info->ccr_functional = pdc_result[0]; + pdc_coproc_info->ccr_present = pdc_result[1]; + pdc_coproc_info->revision = pdc_result[17]; + pdc_coproc_info->model = pdc_result[18]; + spin_unlock_irq(&pdc_lock); + + return retval; +} + +/** + * pdc_iodc_read - Read data from the modules IODC. + * @actcnt: The actual number of bytes. + * @hpa: The HPA of the module for the iodc read. + * @index: The iodc entry point. + * @iodc_data: A buffer memory for the iodc options. + * @iodc_data_size: Size of the memory buffer. + * + * This PDC call reads from the IODC of the module specified by the hpa + * argument. + */ +int pdc_iodc_read(unsigned long *actcnt, unsigned long hpa, unsigned int index, + void *iodc_data, unsigned int iodc_data_size) +{ + int retval; + + spin_lock_irq(&pdc_lock); + retval = mem_pdc_call(PDC_IODC, PDC_IODC_READ, __pa(pdc_result), hpa, + index, __pa(pdc_result2), iodc_data_size); + convert_to_wide(pdc_result); + *actcnt = pdc_result[0]; + memcpy(iodc_data, pdc_result2, iodc_data_size); + spin_unlock_irq(&pdc_lock); + + return retval; +} + +/** + * pdc_system_map_find_mods - Locate unarchitected modules. + * @pdc_mod_info: Return buffer address. + * @mod_path: pointer to dev path structure. + * @mod_index: fixed address module index. + * + * To locate and identify modules which reside at fixed I/O addresses, which + * do not self-identify via architected bus walks. + */ +int pdc_system_map_find_mods(struct pdc_system_map_mod_info *pdc_mod_info, + struct pdc_module_path *mod_path, long mod_index) +{ + int retval; + + spin_lock_irq(&pdc_lock); + retval = mem_pdc_call(PDC_SYSTEM_MAP, PDC_FIND_MODULE, __pa(pdc_result), + __pa(pdc_result2), mod_index); + convert_to_wide(pdc_result); + memcpy(pdc_mod_info, pdc_result, sizeof(*pdc_mod_info)); + memcpy(mod_path, pdc_result2, sizeof(*mod_path)); + spin_unlock_irq(&pdc_lock); + + pdc_mod_info->mod_addr = f_extend(pdc_mod_info->mod_addr); + return retval; +} + +/** + * pdc_system_map_find_addrs - Retrieve additional address ranges. + * @pdc_addr_info: Return buffer address. + * @mod_index: Fixed address module index. + * @addr_index: Address range index. + * + * Retrieve additional information about subsequent address ranges for modules + * with multiple address ranges. + */ +int pdc_system_map_find_addrs(struct pdc_system_map_addr_info *pdc_addr_info, + long mod_index, long addr_index) +{ + int retval; + + spin_lock_irq(&pdc_lock); + retval = mem_pdc_call(PDC_SYSTEM_MAP, PDC_FIND_ADDRESS, __pa(pdc_result), + mod_index, addr_index); + convert_to_wide(pdc_result); + memcpy(pdc_addr_info, pdc_result, sizeof(*pdc_addr_info)); + spin_unlock_irq(&pdc_lock); + + pdc_addr_info->mod_addr = f_extend(pdc_addr_info->mod_addr); + return retval; +} + +/** + * pdc_model_info - Return model information about the processor. + * @model: The return buffer. + * + * Returns the version numbers, identifiers, and capabilities from the processor module. + */ +int pdc_model_info(struct pdc_model *model) +{ + int retval; + + spin_lock_irq(&pdc_lock); + retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_INFO, __pa(pdc_result), 0); + convert_to_wide(pdc_result); + memcpy(model, pdc_result, sizeof(*model)); + spin_unlock_irq(&pdc_lock); + + return retval; +} + +/** + * pdc_model_sysmodel - Get the system model name. + * @name: A char array of at least 81 characters. + * + * Get system model name from PDC ROM (e.g. 9000/715 or 9000/778/B160L) + */ +int pdc_model_sysmodel(char *name) +{ + int retval; + + spin_lock_irq(&pdc_lock); + retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_SYSMODEL, __pa(pdc_result), + OS_ID_HPUX, __pa(name)); + convert_to_wide(pdc_result); + + if (retval == PDC_OK) { + name[pdc_result[0]] = '\0'; /* add trailing '\0' */ + } else { + name[0] = 0; + } + spin_unlock_irq(&pdc_lock); + + return retval; +} + +/** + * pdc_model_versions - Identify the version number of each processor. + * @cpu_id: The return buffer. + * @id: The id of the processor to check. + * + * Returns the version number for each processor component. + * + * This comment was here before, but I do not know what it means :( -RB + * id: 0 = cpu revision, 1 = boot-rom-version + */ +int pdc_model_versions(unsigned long *versions, int id) +{ + int retval; + + spin_lock_irq(&pdc_lock); + retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_VERSIONS, __pa(pdc_result), id); + convert_to_wide(pdc_result); + *versions = pdc_result[0]; + spin_unlock_irq(&pdc_lock); + + return retval; +} + +/** + * pdc_model_cpuid - Returns the CPU_ID. + * @cpu_id: The return buffer. + * + * Returns the CPU_ID value which uniquely identifies the cpu portion of + * the processor module. + */ +int pdc_model_cpuid(unsigned long *cpu_id) +{ + int retval; + + spin_lock_irq(&pdc_lock); + pdc_result[0] = 0; /* preset zero (call may not be implemented!) */ + retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_CPU_ID, __pa(pdc_result), 0); + convert_to_wide(pdc_result); + *cpu_id = pdc_result[0]; + spin_unlock_irq(&pdc_lock); + + return retval; +} + +/** + * pdc_model_capabilities - Returns the platform capabilities. + * @capabilities: The return buffer. + * + * Returns information about platform support for 32- and/or 64-bit + * OSes, IO-PDIR coherency, and virtual aliasing. + */ +int pdc_model_capabilities(unsigned long *capabilities) +{ + int retval; + + spin_lock_irq(&pdc_lock); + pdc_result[0] = 0; /* preset zero (call may not be implemented!) */ + retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_CAPABILITIES, __pa(pdc_result), 0); + convert_to_wide(pdc_result); + *capabilities = pdc_result[0]; + spin_unlock_irq(&pdc_lock); + + return retval; +} + +/** + * pdc_cache_info - Return cache and TLB information. + * @cache_info: The return buffer. + * + * Returns information about the processor's cache and TLB. + */ +int pdc_cache_info(struct pdc_cache_info *cache_info) +{ + int retval; + + spin_lock_irq(&pdc_lock); + retval = mem_pdc_call(PDC_CACHE, PDC_CACHE_INFO, __pa(pdc_result), 0); + convert_to_wide(pdc_result); + memcpy(cache_info, pdc_result, sizeof(*cache_info)); + spin_unlock_irq(&pdc_lock); + + return retval; +} + +#ifndef CONFIG_PA20 +/** + * pdc_btlb_info - Return block TLB information. + * @btlb: The return buffer. + * + * Returns information about the hardware Block TLB. + */ +int pdc_btlb_info(struct pdc_btlb_info *btlb) +{ + int retval; + + spin_lock_irq(&pdc_lock); + retval = mem_pdc_call(PDC_BLOCK_TLB, PDC_BTLB_INFO, __pa(pdc_result), 0); + memcpy(btlb, pdc_result, sizeof(*btlb)); + spin_unlock_irq(&pdc_lock); + + if(retval < 0) { + btlb->max_size = 0; + } + return retval; +} + +/** + * pdc_mem_map_hpa - Find fixed module information. + * @address: The return buffer + * @mod_path: pointer to dev path structure. + * + * This call was developed for S700 workstations to allow the kernel to find + * the I/O devices (Core I/O). In the future (Kittyhawk and beyond) this + * call will be replaced (on workstations) by the architected PDC_SYSTEM_MAP + * call. + * + * This call is supported by all existing S700 workstations (up to Gecko). + */ +int pdc_mem_map_hpa(struct pdc_memory_map *address, + struct pdc_module_path *mod_path) +{ + int retval; + + spin_lock_irq(&pdc_lock); + memcpy(pdc_result2, mod_path, sizeof(*mod_path)); + retval = mem_pdc_call(PDC_MEM_MAP, PDC_MEM_MAP_HPA, __pa(pdc_result), + __pa(pdc_result2)); + memcpy(address, pdc_result, sizeof(*address)); + spin_unlock_irq(&pdc_lock); + + return retval; +} +#endif /* !CONFIG_PA20 */ + +/** + * pdc_lan_station_id - Get the LAN address. + * @lan_addr: The return buffer. + * @hpa: The network device HPA. + * + * Get the LAN station address when it is not directly available from the LAN hardware. + */ +int pdc_lan_station_id(char *lan_addr, unsigned long hpa) +{ + int retval; + + spin_lock_irq(&pdc_lock); + retval = mem_pdc_call(PDC_LAN_STATION_ID, PDC_LAN_STATION_ID_READ, + __pa(pdc_result), hpa); + if (retval < 0) { + /* FIXME: else read MAC from NVRAM */ + memset(lan_addr, 0, PDC_LAN_STATION_ID_SIZE); + } else { + memcpy(lan_addr, pdc_result, PDC_LAN_STATION_ID_SIZE); + } + spin_unlock_irq(&pdc_lock); + + return retval; +} + + +/** + * pdc_get_initiator - Get the SCSI Interface Card params (SCSI ID, SDTR, SE or LVD) + * @hwpath: fully bc.mod style path to the device. + * @scsi_id: what someone told firmware the ID should be. + * @period: time in cycles + * @width: 8 or 16-bit wide bus + * @mode: 0,1,2 -> SE,HVD,LVD signalling mode + * + * Get the SCSI operational parameters from PDC. + * Needed since HPUX never used BIOS or symbios card NVRAM. + * Most ncr/sym cards won't have an entry and just use whatever + * capabilities of the card are (eg Ultra, LVD). But there are + * several cases where it's useful: + * o set SCSI id for Multi-initiator clusters, + * o cable too long (ie SE scsi 10Mhz won't support 6m length), + * o bus width exported is less than what the interface chip supports. + */ +int pdc_get_initiator( struct hardware_path *hwpath, unsigned char *scsi_id, + unsigned long *period, char *width, char *mode) +{ + int retval; + + spin_lock_irq(&pdc_lock); + +/* BCJ-XXXX series boxes. E.G. "9000/785/C3000" */ +#define IS_SPROCKETS() (strlen(boot_cpu_data.pdc.sys_model_name) == 14 && \ + strncmp(boot_cpu_data.pdc.sys_model_name, "9000/785", 9) == 0) + + retval = mem_pdc_call(PDC_INITIATOR, PDC_GET_INITIATOR, + __pa(pdc_result), __pa(hwpath)); + + + if (retval >= PDC_OK) { + *scsi_id = (unsigned char) pdc_result[0]; + + /* convert Bus speed in Mhz to period (in 1/10 ns) */ + switch(pdc_result[1]) { + /* + ** case 0: driver determines rate + ** case -1: Settings are uninitialized. + */ + case 5: *period = 2000; break; + case 10: *period = 1000; break; + case 20: *period = 500; break; + case 40: *period = 250; break; + default: /* Do nothing */ break; + } + + /* + ** pdc_result[2] PDC suggested SCSI id + ** pdc_result[3] PDC suggested SCSI rate + */ + + if (IS_SPROCKETS()) { + /* + ** Revisit: PAT PDC do the same thing? + ** A500 also exports 50-pin SE SCSI. + ** 0 == 8-bit + ** 1 == 16-bit + */ + *width = (char) pdc_result[4]; + + /* ...in case someone needs it in the future. + ** sym53c8xx.c comments say it can't autodetect + ** for 825/825A/875 chips. + ** 0 == SE, 1 == HVD, 2 == LVD + */ + *mode = (char) pdc_result[5]; + } + } + + spin_unlock_irq(&pdc_lock); + return retval >= PDC_OK; +} + + +/** + * pdc_pci_irt_size - Get the number of entries in the interrupt routing table. + * @num_entries: The return value. + * @hpa: The HPA for the device. + * + * This PDC function returns the number of entries in the specified cell's + * interrupt table. + * Similar to PDC_PAT stuff - but added for Forte/Allegro boxes + */ +int pdc_pci_irt_size(unsigned long *num_entries, unsigned long hpa) +{ + int retval; + + spin_lock_irq(&pdc_lock); + retval = mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL_SIZE, + __pa(pdc_result), hpa); + convert_to_wide(pdc_result); + *num_entries = pdc_result[0]; + spin_unlock_irq(&pdc_lock); + + return retval; +} + +/** + * pdc_pci_irt - Get the PCI interrupt routing table. + * @num_entries: The number of entries in the table. + * @hpa: The Hard Physical Address of the device. + * @tbl: + * + * Get the PCI interrupt routing table for the device at the given HPA. + * Similar to PDC_PAT stuff - but added for Forte/Allegro boxes + */ +int pdc_pci_irt(unsigned long num_entries, unsigned long hpa, void *tbl) +{ + int retval; + + spin_lock_irq(&pdc_lock); + pdc_result[0] = num_entries; + retval = mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL, + __pa(pdc_result), hpa, __pa(tbl)); + spin_unlock_irq(&pdc_lock); + + return retval; +} + + +/** + * pdc_tod_read - Read the Time-Of-Day clock. + * @tod: The return buffer: + * + * Read the Time-Of-Day clock + */ +int pdc_tod_read(struct pdc_tod *tod) +{ + int retval; + + spin_lock_irq(&pdc_lock); + retval = mem_pdc_call(PDC_TOD, PDC_TOD_READ, __pa(pdc_result), 0); + convert_to_wide(pdc_result); + memcpy(tod, pdc_result, sizeof(*tod)); + spin_unlock_irq(&pdc_lock); + + return retval; +} + +/** + * pdc_tod_set - Set the Time-Of-Day clock. + * @sec: The number of seconds since epoch. + * @usec: The number of micro seconds. + * + * Set the Time-Of-Day clock. + */ +int pdc_tod_set(unsigned long sec, unsigned long usec) +{ + int retval; + + spin_lock_irq(&pdc_lock); + retval = mem_pdc_call(PDC_TOD, PDC_TOD_WRITE, sec, usec); + spin_unlock_irq(&pdc_lock); + + return retval; +} + +#ifdef __LP64__ +int pdc_mem_mem_table(struct pdc_memory_table_raddr *r_addr, + struct pdc_memory_table *tbl, unsigned long entries) +{ + int retval; + + spin_lock_irq(&pdc_lock); + retval = mem_pdc_call(PDC_MEM, PDC_MEM_TABLE, __pa(pdc_result), __pa(pdc_result2), entries); + convert_to_wide(pdc_result); + memcpy(r_addr, pdc_result, sizeof(*r_addr)); + memcpy(tbl, pdc_result2, entries * sizeof(*tbl)); + spin_unlock_irq(&pdc_lock); + + return retval; +} +#endif /* __LP64__ */ + +/* FIXME: Is this pdc used? I could not find type reference to ftc_bitmap + * so I guessed at unsigned long. Someone who knows what this does, can fix + * it later. :) + */ +int pdc_do_firm_test_reset(unsigned long ftc_bitmap) +{ + int retval; + + spin_lock_irq(&pdc_lock); + retval = mem_pdc_call(PDC_BROADCAST_RESET, PDC_DO_FIRM_TEST_RESET, + PDC_FIRM_TEST_MAGIC, ftc_bitmap); + spin_unlock_irq(&pdc_lock); + + return retval; +} + +/* + * pdc_do_reset - Reset the system. + * + * Reset the system. + */ +int pdc_do_reset() +{ + int retval; + + spin_lock_irq(&pdc_lock); + retval = mem_pdc_call(PDC_BROADCAST_RESET, PDC_DO_RESET); + spin_unlock_irq(&pdc_lock); + + return retval; +} + +/* + * pdc_soft_power_info - Enable soft power switch. + * @power_reg: address of soft power register + * + * Return the absolute address of the soft power switch register + */ +int __init pdc_soft_power_info(unsigned long *power_reg) +{ + int retval; + + *power_reg = (unsigned long) (-1); + + spin_lock_irq(&pdc_lock); + retval = mem_pdc_call(PDC_SOFT_POWER, PDC_SOFT_POWER_INFO, __pa(pdc_result), 0); + if (retval == PDC_OK) { + convert_to_wide(pdc_result); + *power_reg = f_extend(pdc_result[0]); + } + spin_unlock_irq(&pdc_lock); + + return retval; +} + +/* + * pdc_soft_power_button - Control the soft power button behaviour + * @sw_control: 0 for hardware control, 1 for software control + * + * + * This PDC function places the soft power button under software or + * hardware control. + * Under software control the OS may control to when to allow to shut + * down the system. Under hardware control pressing the power button + * powers off the system immediately. + */ +int pdc_soft_power_button(int sw_control) +{ + int retval; + spin_lock_irq(&pdc_lock); + retval = mem_pdc_call(PDC_SOFT_POWER, PDC_SOFT_POWER_ENABLE, __pa(pdc_result), sw_control); + spin_unlock_irq(&pdc_lock); + return retval; +} + +/* + * pdc_suspend_usb - Stop USB controller + * + * If PDC used the usb controller, the usb controller + * is still running and will crash the machines during iommu + * setup, because of still running DMA. This PDC call + * stops the USB controller + */ +void pdc_suspend_usb(void) +{ + spin_lock_irq(&pdc_lock); + mem_pdc_call(PDC_IO, PDC_IO_SUSPEND_USB, 0); + spin_unlock_irq(&pdc_lock); +} + +/** + * pdc_iodc_putc - Console character print using IODC. + * @c: the character to output. + * + * Note that only these special chars are architected for console IODC io: + * BEL, BS, CR, and LF. Others are passed through. + * Since the HP console requires CR+LF to perform a 'newline', we translate + * "\n" to "\r\n". + */ +void pdc_iodc_putc(unsigned char c) +{ + /* XXX Should we spinlock posx usage */ + static int posx; /* for simple TAB-Simulation... */ + static int __attribute__((aligned(8))) iodc_retbuf[32]; + static char __attribute__((aligned(64))) iodc_dbuf[4096]; + unsigned int n; + unsigned int flags; + + switch (c) { + case '\n': + iodc_dbuf[0] = '\r'; + iodc_dbuf[1] = '\n'; + n = 2; + posx = 0; + break; + case '\t': + pdc_iodc_putc(' '); + while (posx & 7) /* expand TAB */ + pdc_iodc_putc(' '); + return; /* return since IODC can't handle this */ + case '\b': + posx-=2; /* BS */ + default: + iodc_dbuf[0] = c; + n = 1; + posx++; + break; + } + + spin_lock_irqsave(&pdc_lock, flags); + real32_call(PAGE0->mem_cons.iodc_io, + (unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT, + PAGE0->mem_cons.spa, __pa(PAGE0->mem_cons.dp.layers), + __pa(iodc_retbuf), 0, __pa(iodc_dbuf), n, 0); + spin_unlock_irqrestore(&pdc_lock, flags); +} + +/** + * pdc_iodc_outc - Console character print using IODC (without conversions). + * @c: the character to output. + * + * Write the character directly to the IODC console. + */ +void pdc_iodc_outc(unsigned char c) +{ + unsigned int n, flags; + + /* fill buffer with one caracter and print it */ + static int __attribute__((aligned(8))) iodc_retbuf[32]; + static char __attribute__((aligned(64))) iodc_dbuf[4096]; + + n = 1; + iodc_dbuf[0] = c; + + spin_lock_irqsave(&pdc_lock, flags); + real32_call(PAGE0->mem_cons.iodc_io, + (unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT, + PAGE0->mem_cons.spa, __pa(PAGE0->mem_cons.dp.layers), + __pa(iodc_retbuf), 0, __pa(iodc_dbuf), n, 0); + spin_unlock_irqrestore(&pdc_lock, flags); +} + +/** + * pdc_iodc_getc - Read a character (non-blocking) from the PDC console. + * + * Read a character (non-blocking) from the PDC console, returns -1 if + * key is not present. + */ +int pdc_iodc_getc(void) +{ + unsigned int flags; + static int __attribute__((aligned(8))) iodc_retbuf[32]; + static char __attribute__((aligned(64))) iodc_dbuf[4096]; + int ch; + int status; + + /* Bail if no console input device. */ + if (!PAGE0->mem_kbd.iodc_io) + return 0; + + /* wait for a keyboard (rs232)-input */ + spin_lock_irqsave(&pdc_lock, flags); + real32_call(PAGE0->mem_kbd.iodc_io, + (unsigned long)PAGE0->mem_kbd.hpa, ENTRY_IO_CIN, + PAGE0->mem_kbd.spa, __pa(PAGE0->mem_kbd.dp.layers), + __pa(iodc_retbuf), 0, __pa(iodc_dbuf), 1, 0); + + ch = *iodc_dbuf; + status = *iodc_retbuf; + spin_unlock_irqrestore(&pdc_lock, flags); + + if (status == 0) + return -1; + + return ch; +} + +int pdc_sti_call(unsigned long func, unsigned long flags, + unsigned long inptr, unsigned long outputr, + unsigned long glob_cfg) +{ + int retval; + + spin_lock_irq(&pdc_lock); + retval = real32_call(func, flags, inptr, outputr, glob_cfg); + spin_unlock_irq(&pdc_lock); + + return retval; +} + +#ifdef __LP64__ +/** + * pdc_pat_cell_get_number - Returns the cell number. + * @cell_info: The return buffer. + * + * This PDC call returns the cell number of the cell from which the call + * is made. + */ +int pdc_pat_cell_get_number(struct pdc_pat_cell_num *cell_info) +{ + int retval; + + spin_lock_irq(&pdc_lock); + retval = mem_pdc_call(PDC_PAT_CELL, PDC_PAT_CELL_GET_NUMBER, __pa(pdc_result)); + memcpy(cell_info, pdc_result, sizeof(*cell_info)); + spin_unlock_irq(&pdc_lock); + + return retval; +} + +/** + * pdc_pat_cell_module - Retrieve the cell's module information. + * @actcnt: The number of bytes written to mem_addr. + * @ploc: The physical location. + * @mod: The module index. + * @view_type: The view of the address type. + * @mem_addr: The return buffer. + * + * This PDC call returns information about each module attached to the cell + * at the specified location. + */ +int pdc_pat_cell_module(unsigned long *actcnt, unsigned long ploc, unsigned long mod, + unsigned long view_type, void *mem_addr) +{ + int retval; + static struct pdc_pat_cell_mod_maddr_block result __attribute__ ((aligned (8))); + + spin_lock_irq(&pdc_lock); + retval = mem_pdc_call(PDC_PAT_CELL, PDC_PAT_CELL_MODULE, __pa(pdc_result), + ploc, mod, view_type, __pa(&result)); + if(!retval) { + *actcnt = pdc_result[0]; + memcpy(mem_addr, &result, *actcnt); + } + spin_unlock_irq(&pdc_lock); + + return retval; +} + +/** + * pdc_pat_cpu_get_number - Retrieve the cpu number. + * @cpu_info: The return buffer. + * @hpa: The Hard Physical Address of the CPU. + * + * Retrieve the cpu number for the cpu at the specified HPA. + */ +int pdc_pat_cpu_get_number(struct pdc_pat_cpu_num *cpu_info, void *hpa) +{ + int retval; + + spin_lock_irq(&pdc_lock); + retval = mem_pdc_call(PDC_PAT_CPU, PDC_PAT_CPU_GET_NUMBER, + __pa(&pdc_result), hpa); + memcpy(cpu_info, pdc_result, sizeof(*cpu_info)); + spin_unlock_irq(&pdc_lock); + + return retval; +} + +/** + * pdc_pat_get_irt_size - Retrieve the number of entries in the cell's interrupt table. + * @num_entries: The return value. + * @cell_num: The target cell. + * + * This PDC function returns the number of entries in the specified cell's + * interrupt table. + */ +int pdc_pat_get_irt_size(unsigned long *num_entries, unsigned long cell_num) +{ + int retval; + + spin_lock_irq(&pdc_lock); + retval = mem_pdc_call(PDC_PAT_IO, PDC_PAT_IO_GET_PCI_ROUTING_TABLE_SIZE, + __pa(pdc_result), cell_num); + *num_entries = pdc_result[0]; + spin_unlock_irq(&pdc_lock); + + return retval; +} + +/** + * pdc_pat_get_irt - Retrieve the cell's interrupt table. + * @r_addr: The return buffer. + * @cell_num: The target cell. + * + * This PDC function returns the actual interrupt table for the specified cell. + */ +int pdc_pat_get_irt(void *r_addr, unsigned long cell_num) +{ + int retval; + + spin_lock_irq(&pdc_lock); + retval = mem_pdc_call(PDC_PAT_IO, PDC_PAT_IO_GET_PCI_ROUTING_TABLE, + __pa(r_addr), cell_num); + spin_unlock_irq(&pdc_lock); + + return retval; +} + +/** + * pdc_pat_pd_get_addr_map - Retrieve information about memory address ranges. + * @actlen: The return buffer. + * @mem_addr: Pointer to the memory buffer. + * @count: The number of bytes to read from the buffer. + * @offset: The offset with respect to the beginning of the buffer. + * + */ +int pdc_pat_pd_get_addr_map(unsigned long *actual_len, void *mem_addr, + unsigned long count, unsigned long offset) +{ + int retval; + + spin_lock_irq(&pdc_lock); + retval = mem_pdc_call(PDC_PAT_PD, PDC_PAT_PD_GET_ADDR_MAP, __pa(pdc_result), + __pa(pdc_result2), count, offset); + *actual_len = pdc_result[0]; + memcpy(mem_addr, pdc_result2, *actual_len); + spin_unlock_irq(&pdc_lock); + + return retval; +} +#endif /* __LP64__ */ + + +/***************** 32-bit real-mode calls ***********/ +/* The struct below is used + * to overlay real_stack (real2.S), preparing a 32-bit call frame. + * real32_call_asm() then uses this stack in narrow real mode + */ + +struct narrow_stack { + /* use int, not long which is 64 bits */ + unsigned int arg13; + unsigned int arg12; + unsigned int arg11; + unsigned int arg10; + unsigned int arg9; + unsigned int arg8; + unsigned int arg7; + unsigned int arg6; + unsigned int arg5; + unsigned int arg4; + unsigned int arg3; + unsigned int arg2; + unsigned int arg1; + unsigned int arg0; + unsigned int frame_marker[8]; + unsigned int sp; + /* in reality, there's nearly 8k of stack after this */ +}; + +static long real32_call(unsigned long fn, ...) +{ + va_list args; + extern struct narrow_stack real_stack; + extern unsigned long real32_call_asm(unsigned int *, + unsigned int *, + unsigned int); + + va_start(args, fn); + real_stack.arg0 = va_arg(args, unsigned int); + real_stack.arg1 = va_arg(args, unsigned int); + real_stack.arg2 = va_arg(args, unsigned int); + real_stack.arg3 = va_arg(args, unsigned int); + real_stack.arg4 = va_arg(args, unsigned int); + real_stack.arg5 = va_arg(args, unsigned int); + real_stack.arg6 = va_arg(args, unsigned int); + real_stack.arg7 = va_arg(args, unsigned int); + real_stack.arg8 = va_arg(args, unsigned int); + real_stack.arg9 = va_arg(args, unsigned int); + real_stack.arg10 = va_arg(args, unsigned int); + real_stack.arg11 = va_arg(args, unsigned int); + real_stack.arg12 = va_arg(args, unsigned int); + real_stack.arg13 = va_arg(args, unsigned int); + va_end(args); + + return real32_call_asm(&real_stack.sp, &real_stack.arg0, fn); +} + +#ifdef __LP64__ +/***************** 64-bit real-mode calls ***********/ + +struct wide_stack { + unsigned long arg0; + unsigned long arg1; + unsigned long arg2; + unsigned long arg3; + unsigned long arg4; + unsigned long arg5; + unsigned long arg6; + unsigned long arg7; + unsigned long arg8; + unsigned long arg9; + unsigned long arg10; + unsigned long arg11; + unsigned long arg12; + unsigned long arg13; + unsigned long frame_marker[2]; /* rp, previous sp */ + unsigned long sp; + /* in reality, there's nearly 8k of stack after this */ +}; + +static long real64_call(unsigned long fn, ...) +{ + va_list args; + extern struct wide_stack real_stack; + extern unsigned long real64_call_asm(unsigned long *, + unsigned long *, + unsigned long); + + va_start(args, fn); + real_stack.arg0 = va_arg(args, unsigned long); + real_stack.arg1 = va_arg(args, unsigned long); + real_stack.arg2 = va_arg(args, unsigned long); + real_stack.arg3 = va_arg(args, unsigned long); + real_stack.arg4 = va_arg(args, unsigned long); + real_stack.arg5 = va_arg(args, unsigned long); + real_stack.arg6 = va_arg(args, unsigned long); + real_stack.arg7 = va_arg(args, unsigned long); + real_stack.arg8 = va_arg(args, unsigned long); + real_stack.arg9 = va_arg(args, unsigned long); + real_stack.arg10 = va_arg(args, unsigned long); + real_stack.arg11 = va_arg(args, unsigned long); + real_stack.arg12 = va_arg(args, unsigned long); + real_stack.arg13 = va_arg(args, unsigned long); + va_end(args); + + return real64_call_asm(&real_stack.sp, &real_stack.arg0, fn); +} + +#endif /* __LP64__ */ + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/hardware.c linux.19rc3-ac4/arch/parisc/kernel/hardware.c --- linux.19rc3/arch/parisc/kernel/hardware.c 2002-07-29 12:50:06.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/hardware.c 2002-07-29 13:58:36.000000000 +0100 @@ -5,7 +5,7 @@ * * Based on the document "PA-RISC 1.1 I/O Firmware Architecture * Reference Specification", March 7, 1999, version 0.96. This - * is available at ?. + * is available at http://parisc-linux.org/documentation/ * * Copyright 1999 by Alex deVries * and copyright 1999 The Puffin Group Inc. @@ -30,32 +30,15 @@ #include #include #include - -#define HPHW_NUM_TYPES 3431 - -static char * hw_type_name[16] = { - "Processor", - "Memory", - "B DMA", - "Obsolete", - "A DMA", - "A Direct", - "Obsolete", - "Bus Converter Port", - "HP CIO Adapter", - "Console", - "Foreign I/O Module", - "Bus Adapter", - "IOA (?)", - "Bus Bridge to Foreign Bus", - "HP Clothing: Fabric Component" -}; +#include /* - * XXX Could this be __init ?? + * HP PARISC Hardware Database + * Access to this database is only possible during bootup + * so don't reference this table after starting the init process */ -static struct hp_hardware hp_hardware_list[] = { +static struct hp_hardware hp_hardware_list[] __initdata = { {HPHW_NPROC,0x01,0x4,0x0,"Indigo (840, 930)"}, {HPHW_NPROC,0x8,0x4,0x01,"Firefox(825,925)"}, {HPHW_NPROC,0xA,0x4,0x01,"Top Gun (835,834,935,635)"}, @@ -169,9 +152,10 @@ {HPHW_NPROC,0x59A,0x4,0x91,"Unlisted but reserved"}, {HPHW_NPROC,0x59A,0x4,0x81,"Unlisted but reserved"}, {HPHW_NPROC,0x59B,0x4,0x81,"Raven U 160 (9000/780/C160)"}, + {HPHW_NPROC,0x59C,0x4,0x81,"Raven U 180 (9000/780/C180)"}, {HPHW_NPROC,0x59D,0x4,0x81,"Raven U 200 (9000/780/C200)"}, {HPHW_NPROC,0x59E,0x4,0x91,"ThunderHawk T' 120"}, - {HPHW_NPROC,0x59F,0x4,0x91,"Raven U 180+ (9000/780/\?\?\?\?)"}, + {HPHW_NPROC,0x59F,0x4,0x91,"Raven U 180+ (9000/780)"}, {HPHW_NPROC,0x5A0,0x4,0x81,"UL 1w T120 1MB/1MB (841/D260,D360)"}, {HPHW_NPROC,0x5A1,0x4,0x91,"UL 2w T120 1MB/1MB (851/D260,D360)"}, {HPHW_NPROC,0x5A2,0x4,0x81,"UL 1w U160 512K/512K (861/D270,D370)"}, @@ -201,7 +185,7 @@ {HPHW_NPROC,0x5B8,0x4,0x91,"SPP2250 240 MHz"}, {HPHW_NPROC,0x5B9,0x4,0x81,"UL 1w U+/240 (350/550)"}, {HPHW_NPROC,0x5BA,0x4,0x91,"UL 2w U+/240 (350/550)"}, - {HPHW_NPROC,0x5BB,0x4,0x81,"AllegroHigh W "}, + {HPHW_NPROC,0x5BB,0x4,0x81,"AllegroHigh W"}, {HPHW_NPROC,0x5BC,0x4,0x91,"AllegroLow W"}, {HPHW_NPROC,0x5BD,0x4,0x91,"Forte W 2-way"}, {HPHW_NPROC,0x5BE,0x4,0x91,"Prelude W"}, @@ -212,12 +196,41 @@ {HPHW_NPROC,0x5C3,0x4,0x91,"Sonata 360"}, {HPHW_NPROC,0x5C4,0x4,0x91,"Rhapsody 440"}, {HPHW_NPROC,0x5C5,0x4,0x91,"Rhapsody 360"}, - {HPHW_NPROC,0x5C6,0x4,0x91,"Raven W 360 (9000/780/\?\?\?\?)"}, + {HPHW_NPROC,0x5C6,0x4,0x91,"Raven W 360 (9000/780)"}, {HPHW_NPROC,0x5C7,0x4,0x91,"Halfdome W 440"}, {HPHW_NPROC,0x5C8,0x4,0x81,"Lego 360 processor"}, {HPHW_NPROC,0x5C9,0x4,0x91,"Rhapsody DC- 440"}, {HPHW_NPROC,0x5CA,0x4,0x91,"Rhapsody DC- 360"}, {HPHW_NPROC,0x5CB,0x4,0x91,"Crescendo 440"}, + {HPHW_NPROC,0x5CC,0x4,0x91,"Prelude W 440"}, + {HPHW_NPROC,0x5CD,0x4,0x91,"SPP2600"}, + {HPHW_NPROC,0x5CE,0x4,0x91,"M2600"}, + {HPHW_NPROC,0x5CF,0x4,0x81,"Allegro W+"}, + {HPHW_NPROC,0x5D0,0x4,0x81,"Kazoo W+"}, + {HPHW_NPROC,0x5D1,0x4,0x91,"Forte W+ 2w"}, + {HPHW_NPROC,0x5D2,0x4,0x91,"Forte W+ 4w"}, + {HPHW_NPROC,0x5D3,0x4,0x91,"Prelude W+ 540"}, + {HPHW_NPROC,0x5D4,0x4,0x91,"Duet W+"}, + {HPHW_NPROC,0x5D5,0x4,0x91,"Crescendo 550"}, + {HPHW_NPROC,0x5D6,0x4,0x81,"Crescendo DC- 440"}, + {HPHW_NPROC,0x5D7,0x4,0x91,"Keystone W+"}, + {HPHW_NPROC,0x5D8,0x4,0x91,"Rhapsody wave 2 W+ DC-"}, + {HPHW_NPROC,0x5D9,0x4,0x91,"Rhapsody wave 2 W+"}, + {HPHW_NPROC,0x5DA,0x4,0x91,"Marcato W+ DC-"}, + {HPHW_NPROC,0x5DB,0x4,0x91,"Marcato W+"}, + {HPHW_NPROC,0x5DC,0x4,0x91,"Allegro W2"}, + {HPHW_NPROC,0x5DD,0x4,0x81,"Duet W2"}, + {HPHW_NPROC,0x5DE,0x4,0x81,"Piccolo W+"}, + {HPHW_NPROC,0x5DF,0x4,0x81,"Cantata W2"}, + {HPHW_NPROC,0x5E0,0x4,0x91,"Cantata DC- W2"}, + {HPHW_NPROC,0x5E1,0x4,0x91,"Crescendo DC- W2"}, + {HPHW_NPROC,0x5E2,0x4,0x91,"Crescendo 650 W2"}, + {HPHW_NPROC,0x5E3,0x4,0x91,"Crescendo 750 W2"}, + {HPHW_NPROC,0x5E4,0x4,0x91,"Keystone/Matterhorn W2 750"}, + {HPHW_NPROC,0x5E5,0x4,0x91,"PowerBar W+"}, + {HPHW_NPROC,0x5E6,0x4,0x91,"Keystone/Matterhorn W2 650"}, + {HPHW_NPROC,0x5E7,0x4,0x91,"Caribe W2 800"}, + {HPHW_NPROC,0x5E8,0x4,0x91,"Pikes Peak W2"}, {HPHW_NPROC,0x5FF,0x4,0x91,"Hitachi W"}, {HPHW_NPROC,0x600,0x4,0x81,"Gecko (712/60)"}, {HPHW_NPROC,0x601,0x4,0x81,"Gecko 80 (712/80)"}, @@ -243,7 +256,7 @@ {HPHW_NPROC,0x616,0x4,0x81,"Piranha 120"}, {HPHW_NPROC,0x617,0x4,0x81,"Jason 50"}, {HPHW_NPROC,0x618,0x4,0x81,"Jason 100"}, - {HPHW_NPROC,0x619,0x4,0x81,"Mirage 80 "}, + {HPHW_NPROC,0x619,0x4,0x81,"Mirage 80"}, {HPHW_NPROC,0x61A,0x4,0x81,"SAIC L-80"}, {HPHW_NPROC,0x61B,0x4,0x81,"Rocky1 L-60"}, {HPHW_NPROC,0x61C,0x4,0x81,"Anole T (743/T)"}, @@ -311,6 +324,7 @@ {HPHW_A_DMA, 0x004, 0x00050, 0x80, "Lanbrusca 802.3 (36967A)"}, {HPHW_A_DMA, 0x004, 0x00056, 0x80, "HP-PB LoQuix FDDI"}, {HPHW_A_DMA, 0x004, 0x00057, 0x80, "HP-PB LoQuix FDDI (28670A)"}, + {HPHW_A_DMA, 0x004, 0x0005E, 0x00, "Gecko Add-on Token Ring"}, {HPHW_A_DMA, 0x012, 0x00089, 0x80, "Barracuda Add-on FW-SCSI"}, {HPHW_A_DMA, 0x013, 0x00089, 0x80, "Bluefish Add-on FW-SCSI"}, {HPHW_A_DMA, 0x014, 0x00089, 0x80, "Shrike Add-on FW-SCSI"}, @@ -319,6 +333,7 @@ {HPHW_A_DMA, 0x01F, 0x00089, 0x80, "SkyHawk 100/120 FW-SCSI"}, {HPHW_A_DMA, 0x027, 0x00089, 0x80, "Piranha 100 FW-SCSI"}, {HPHW_A_DMA, 0x032, 0x00089, 0x80, "Raven T' Core FW-SCSI"}, + {HPHW_A_DMA, 0x03b, 0x00089, 0x80, "Raven U/L2 Core FW-SCSI"}, {HPHW_A_DMA, 0x03d, 0x00089, 0x80, "Merlin 160 Core FW-SCSI"}, {HPHW_A_DMA, 0x044, 0x00089, 0x80, "Mohawk Core FW-SCSI"}, {HPHW_A_DMA, 0x051, 0x00089, 0x80, "Firehawk FW-SCSI"}, @@ -440,6 +455,8 @@ {HPHW_BA, 0x801, 0x00081, 0x0, "Hitachi Tiny 80 Core BA"}, {HPHW_BA, 0x004, 0x0008B, 0x0, "Anole Optional PCMCIA BA"}, {HPHW_BA, 0x004, 0x0008E, 0x0, "GSC ITR Wax BA"}, + {HPHW_BA, 0x00C, 0x0008E, 0x0, "Gecko Optional Wax BA"}, + {HPHW_BA, 0x010, 0x0008E, 0x0, "Pace Wax BA"}, {HPHW_BA, 0x011, 0x0008E, 0x0, "SuperPace Wax BA"}, {HPHW_BA, 0x012, 0x0008E, 0x0, "Mirage Jr Wax BA"}, {HPHW_BA, 0x013, 0x0008E, 0x0, "Mirage Wax BA"}, @@ -489,7 +506,7 @@ {HPHW_BA, 0x800, 0x00090, 0x0, "Hitachi Tiny 64 Wax EISA BA"}, {HPHW_BA, 0x801, 0x00090, 0x0, "Hitachi Tiny 80 Wax EISA BA"}, {HPHW_BA, 0x01A, 0x00093, 0x0, "Anole 64 TIMI BA"}, - {HPHW_BA, 0x01B, 0x00093, 0x0, "Anole 64 TIMI BA"}, + {HPHW_BA, 0x01B, 0x00093, 0x0, "Anole 100 TIMI BA"}, {HPHW_BA, 0x034, 0x00093, 0x0, "Anole T TIMI BA"}, {HPHW_BA, 0x04A, 0x00093, 0x0, "Anole L2 132 TIMI BA"}, {HPHW_BA, 0x04C, 0x00093, 0x0, "Anole L2 165 TIMI BA"}, @@ -551,6 +568,7 @@ {HPHW_CONSOLE, 0x01A, 0x0001F, 0x00, "Jason/Anole 64 Null Console"}, {HPHW_CONSOLE, 0x01B, 0x0001F, 0x00, "Jason/Anole 100 Null Console"}, {HPHW_FABRIC, 0x004, 0x000AA, 0x80, "Halfdome DNA Central Agent"}, + {HPHW_FABRIC, 0x007, 0x000AA, 0x80, "Caribe DNA Central Agent"}, {HPHW_FABRIC, 0x004, 0x000AB, 0x00, "Halfdome TOGO Fabric Crossbar"}, {HPHW_FABRIC, 0x004, 0x000AC, 0x00, "Halfdome Sakura Fabric Router"}, {HPHW_FIO, 0x025, 0x0002E, 0x80, "Armyknife Optional X.25"}, @@ -588,14 +606,14 @@ {HPHW_FIO, 0x00D, 0x00072, 0x0, "Strider-33 Core LAN (802.3)"}, {HPHW_FIO, 0x00E, 0x00072, 0x0, "Trailways-50 Core LAN (802.3)"}, {HPHW_FIO, 0x00F, 0x00072, 0x0, "Trailways-33 Core LAN (802.3)"}, - {HPHW_FIO, 0x010, 0x00072, 0x0, "Pace Core Lan (802.3)"}, - {HPHW_FIO, 0x011, 0x00072, 0x0, "Sidewinder Core Lan (802.3)"}, + {HPHW_FIO, 0x010, 0x00072, 0x0, "Pace Core LAN (802.3)"}, + {HPHW_FIO, 0x011, 0x00072, 0x0, "Sidewinder Core LAN (802.3)"}, {HPHW_FIO, 0x019, 0x00072, 0x0, "Scorpio Sr. Core LAN (802.3)"}, {HPHW_FIO, 0x020, 0x00072, 0x0, "Scorpio 100 Core LAN (802.3)"}, {HPHW_FIO, 0x021, 0x00072, 0x0, "Spectra 50 Core LAN (802.3)"}, {HPHW_FIO, 0x022, 0x00072, 0x0, "Spectra 75 Core LAN (802.3)"}, {HPHW_FIO, 0x023, 0x00072, 0x0, "Spectra 100 Core LAN (802.3)"}, - {HPHW_FIO, 0x024, 0x00072, 0x0, "Fast Pace Core Lan (802.3)"}, + {HPHW_FIO, 0x024, 0x00072, 0x0, "Fast Pace Core LAN (802.3)"}, {HPHW_FIO, 0x026, 0x00072, 0x0, "CoralII Jaguar Core LAN (802.3)"}, {HPHW_FIO, 0x004, 0x00073, 0x0, "Cobra Core HIL"}, {HPHW_FIO, 0x005, 0x00073, 0x0, "Coral Core HIL"}, @@ -694,8 +712,8 @@ {HPHW_FIO, 0x04D, 0x00074, 0x0, "Anole L2 165 Core Centronics"}, {HPHW_FIO, 0x050, 0x00074, 0x0, "Merlin Jr 132 Core Centronics"}, {HPHW_FIO, 0x051, 0x00074, 0x0, "Firehawk Core Centronics"}, - {HPHW_FIO, 0x056, 0x00074, 0x0, "Raven+ wSE FWSCSI Core Centronics"}, - {HPHW_FIO, 0x057, 0x00074, 0x0, "Raven+ wDiff FWSCSI Core Centronics"}, + {HPHW_FIO, 0x056, 0x00074, 0x0, "Raven+ w SE FWSCSI Core Centronics"}, + {HPHW_FIO, 0x057, 0x00074, 0x0, "Raven+ w Diff FWSCSI Core Centronics"}, {HPHW_FIO, 0x058, 0x00074, 0x0, "FireHawk 200 Core Centronics"}, {HPHW_FIO, 0x05C, 0x00074, 0x0, "SummitHawk 230 Core Centronics"}, {HPHW_FIO, 0x800, 0x00074, 0x0, "Hitachi Tiny 64 Core Centronics"}, @@ -861,66 +879,66 @@ {HPHW_FIO, 0x02E, 0x00083, 0x0, "UL 350 Core PC Floppy"}, {HPHW_FIO, 0x02F, 0x00083, 0x0, "UL 550 Core PC Floppy"}, {HPHW_FIO, 0x032, 0x00083, 0x0, "Raven T' Core PC Floppy"}, - {HPHW_FIO, 0x034, 0x00083, 0x0, "SAIC L-80 Core PC Floopy"}, - {HPHW_FIO, 0x035, 0x00083, 0x0, "PCX-L2 712/132 Core Floopy"}, - {HPHW_FIO, 0x036, 0x00083, 0x0, "PCX-L2 712/160 Core Floopy"}, - {HPHW_FIO, 0x03B, 0x00083, 0x0, "Raven U/L2 Core PC Floopy"}, - {HPHW_FIO, 0x03C, 0x00083, 0x0, "Merlin 132 Core PC Floopy"}, - {HPHW_FIO, 0x03D, 0x00083, 0x0, "Merlin 160 Core PC Floopy"}, - {HPHW_FIO, 0x03E, 0x00083, 0x0, "Merlin+ 132 Core PC Floopy"}, - {HPHW_FIO, 0x03F, 0x00083, 0x0, "Merlin+ 180 Core PC Floopy"}, - {HPHW_FIO, 0x045, 0x00083, 0x0, "Rocky1 Core PC Floopy"}, - {HPHW_FIO, 0x046, 0x00083, 0x0, "Rocky2 120 Core PC Floopy"}, - {HPHW_FIO, 0x047, 0x00083, 0x0, "Rocky2 150 Core PC Floopy"}, - {HPHW_FIO, 0x04E, 0x00083, 0x0, "Kiji L2 132 Core PC Floopy"}, - {HPHW_FIO, 0x050, 0x00083, 0x0, "Merlin Jr 132 Core PC Floopy"}, - {HPHW_FIO, 0x056, 0x00083, 0x0, "Raven+ w SE FWSCSI Core PC Floopy"}, - {HPHW_FIO, 0x057, 0x00083, 0x0, "Raven+ w Diff FWSCSI Core PC Floopy"}, - {HPHW_FIO, 0x800, 0x00083, 0x0, "Hitachi Tiny 64 Core PC Floopy"}, - {HPHW_FIO, 0x801, 0x00083, 0x0, "Hitachi Tiny 80 Core PC Floopy"}, - {HPHW_FIO, 0x015, 0x00084, 0x0, "KittyHawk GSY Core PC Keyboard"}, - {HPHW_FIO, 0x016, 0x00084, 0x0, "Gecko Core PC Keyboard"}, - {HPHW_FIO, 0x018, 0x00084, 0x0, "Gecko Optional PC Keyboard"}, - {HPHW_FIO, 0x01A, 0x00084, 0x0, "Anole 64 Core PC Keyboard"}, - {HPHW_FIO, 0x01B, 0x00084, 0x0, "Anole 100 Core PC Keyboard"}, - {HPHW_FIO, 0x01C, 0x00084, 0x0, "Gecko 80 Core PC Keyboard"}, - {HPHW_FIO, 0x01D, 0x00084, 0x0, "Gecko 100 Core PC Keyboard"}, - {HPHW_FIO, 0x01F, 0x00084, 0x0, "SkyHawk 100/120 Core PC Keyboard"}, - {HPHW_FIO, 0x027, 0x00084, 0x0, "Piranha 100 Core PC Keyboard"}, - {HPHW_FIO, 0x028, 0x00084, 0x0, "Mirage Jr Core PC Keyboard"}, - {HPHW_FIO, 0x029, 0x00084, 0x0, "Mirage Core PC Keyboard"}, - {HPHW_FIO, 0x02A, 0x00084, 0x0, "Electra Core PC Keyboard"}, - {HPHW_FIO, 0x02B, 0x00084, 0x0, "Mirage 80 Core PC Keyboard"}, - {HPHW_FIO, 0x02C, 0x00084, 0x0, "Mirage 100+ Core PC Keyboard"}, - {HPHW_FIO, 0x02E, 0x00084, 0x0, "UL 350 Core PC Keyboard"}, - {HPHW_FIO, 0x02F, 0x00084, 0x0, "UL 550 Core PC Keyboard"}, - {HPHW_FIO, 0x032, 0x00084, 0x0, "Raven T' Core PC Keyboard"}, - {HPHW_FIO, 0x033, 0x00084, 0x0, "Anole T Core PC Keyboard"}, - {HPHW_FIO, 0x034, 0x00084, 0x0, "SAIC L-80 Core PC Keyboard"}, - {HPHW_FIO, 0x035, 0x00084, 0x0, "PCX-L2 712/132 Core Keyboard"}, - {HPHW_FIO, 0x036, 0x00084, 0x0, "PCX-L2 712/160 Core Keyboard"}, - {HPHW_FIO, 0x03B, 0x00084, 0x0, "Raven U/L2 Core PC Keyboard"}, - {HPHW_FIO, 0x03C, 0x00084, 0x0, "Merlin 132 Core PC Keyboard"}, - {HPHW_FIO, 0x03D, 0x00084, 0x0, "Merlin 160 Core PC Keyboard"}, - {HPHW_FIO, 0x03E, 0x00084, 0x0, "Merlin+ 132 Core PC Keyboard"}, - {HPHW_FIO, 0x03F, 0x00084, 0x0, "Merlin+ 180 Core PC Keyboard"}, - {HPHW_FIO, 0x044, 0x00084, 0x0, "Mohawk Core PC Keyboard"}, - {HPHW_FIO, 0x045, 0x00084, 0x0, "Rocky1 Core PC Keyboard"}, - {HPHW_FIO, 0x046, 0x00084, 0x0, "Rocky2 120 Core PC Keyboard"}, - {HPHW_FIO, 0x047, 0x00084, 0x0, "Rocky2 150 Core PC Keyboard"}, - {HPHW_FIO, 0x048, 0x00084, 0x0, "Rocky2 120 Dino PC Keyboard"}, - {HPHW_FIO, 0x049, 0x00084, 0x0, "Rocky2 150 Dino PC Keyboard"}, - {HPHW_FIO, 0x04B, 0x00084, 0x0, "Anole L2 132 Core PC Keyboard"}, - {HPHW_FIO, 0x04D, 0x00084, 0x0, "Anole L2 165 Core PC Keyboard"}, - {HPHW_FIO, 0x04E, 0x00084, 0x0, "Kiji L2 132 Core PC Keyboard"}, - {HPHW_FIO, 0x050, 0x00084, 0x0, "Merlin Jr 132 Core PC Keyboard"}, - {HPHW_FIO, 0x051, 0x00084, 0x0, "Firehawk Core PC Keyboard"}, - {HPHW_FIO, 0x056, 0x00084, 0x0, "Raven+ w SE FWSCSI Core PC Keyboard"}, - {HPHW_FIO, 0x057, 0x00084, 0x0, "Raven+ w Diff FWSCSI Core PC Keyboard"}, - {HPHW_FIO, 0x058, 0x00084, 0x0, "FireHawk 200 Core PC Keyboard"}, - {HPHW_FIO, 0x05C, 0x00084, 0x0, "SummitHawk 230 Core PC Keyboard"}, - {HPHW_FIO, 0x800, 0x00084, 0x0, "Hitachi Tiny 64 Core PC Keyboard"}, - {HPHW_FIO, 0x801, 0x00084, 0x0, "Hitachi Tiny 80 Core PC Keyboard"}, + {HPHW_FIO, 0x034, 0x00083, 0x0, "SAIC L-80 Core PC Floppy"}, + {HPHW_FIO, 0x035, 0x00083, 0x0, "PCX-L2 712/132 Core Floppy"}, + {HPHW_FIO, 0x036, 0x00083, 0x0, "PCX-L2 712/160 Core Floppy"}, + {HPHW_FIO, 0x03B, 0x00083, 0x0, "Raven U/L2 Core PC Floppy"}, + {HPHW_FIO, 0x03C, 0x00083, 0x0, "Merlin 132 Core PC Floppy"}, + {HPHW_FIO, 0x03D, 0x00083, 0x0, "Merlin 160 Core PC Floppy"}, + {HPHW_FIO, 0x03E, 0x00083, 0x0, "Merlin+ 132 Core PC Floppy"}, + {HPHW_FIO, 0x03F, 0x00083, 0x0, "Merlin+ 180 Core PC Floppy"}, + {HPHW_FIO, 0x045, 0x00083, 0x0, "Rocky1 Core PC Floppy"}, + {HPHW_FIO, 0x046, 0x00083, 0x0, "Rocky2 120 Core PC Floppy"}, + {HPHW_FIO, 0x047, 0x00083, 0x0, "Rocky2 150 Core PC Floppy"}, + {HPHW_FIO, 0x04E, 0x00083, 0x0, "Kiji L2 132 Core PC Floppy"}, + {HPHW_FIO, 0x050, 0x00083, 0x0, "Merlin Jr 132 Core PC Floppy"}, + {HPHW_FIO, 0x056, 0x00083, 0x0, "Raven+ w SE FWSCSI Core PC Floppy"}, + {HPHW_FIO, 0x057, 0x00083, 0x0, "Raven+ w Diff FWSCSI Core PC Floppy"}, + {HPHW_FIO, 0x800, 0x00083, 0x0, "Hitachi Tiny 64 Core PC Floppy"}, + {HPHW_FIO, 0x801, 0x00083, 0x0, "Hitachi Tiny 80 Core PC Floppy"}, + {HPHW_FIO, 0x015, 0x00084, 0x0, "KittyHawk GSY Core PS/2 Port"}, + {HPHW_FIO, 0x016, 0x00084, 0x0, "Gecko Core PS/2 Port"}, + {HPHW_FIO, 0x018, 0x00084, 0x0, "Gecko Optional PS/2 Port"}, + {HPHW_FIO, 0x01A, 0x00084, 0x0, "Anole 64 Core PS/2 Port"}, + {HPHW_FIO, 0x01B, 0x00084, 0x0, "Anole 100 Core PS/2 Port"}, + {HPHW_FIO, 0x01C, 0x00084, 0x0, "Gecko 80 Core PS/2 Port"}, + {HPHW_FIO, 0x01D, 0x00084, 0x0, "Gecko 100 Core PS/2 Port"}, + {HPHW_FIO, 0x01F, 0x00084, 0x0, "SkyHawk 100/120 Core PS/2 Port"}, + {HPHW_FIO, 0x027, 0x00084, 0x0, "Piranha 100 Core PS/2 Port"}, + {HPHW_FIO, 0x028, 0x00084, 0x0, "Mirage Jr Core PS/2 Port"}, + {HPHW_FIO, 0x029, 0x00084, 0x0, "Mirage Core PS/2 Port"}, + {HPHW_FIO, 0x02A, 0x00084, 0x0, "Electra Core PS/2 Port"}, + {HPHW_FIO, 0x02B, 0x00084, 0x0, "Mirage 80 Core PS/2 Port"}, + {HPHW_FIO, 0x02C, 0x00084, 0x0, "Mirage 100+ Core PS/2 Port"}, + {HPHW_FIO, 0x02E, 0x00084, 0x0, "UL 350 Core PS/2 Port"}, + {HPHW_FIO, 0x02F, 0x00084, 0x0, "UL 550 Core PS/2 Port"}, + {HPHW_FIO, 0x032, 0x00084, 0x0, "Raven T' Core PS/2 Port"}, + {HPHW_FIO, 0x033, 0x00084, 0x0, "Anole T Core PS/2 Port"}, + {HPHW_FIO, 0x034, 0x00084, 0x0, "SAIC L-80 Core PS/2 Port"}, + {HPHW_FIO, 0x035, 0x00084, 0x0, "PCX-L2 712/132 Core PS/2 Port"}, + {HPHW_FIO, 0x036, 0x00084, 0x0, "PCX-L2 712/160 Core PS/2 Port"}, + {HPHW_FIO, 0x03B, 0x00084, 0x0, "Raven U/L2 Core PS/2 Port"}, + {HPHW_FIO, 0x03C, 0x00084, 0x0, "Merlin 132 Core PS/2 Port"}, + {HPHW_FIO, 0x03D, 0x00084, 0x0, "Merlin 160 Core PS/2 Port"}, + {HPHW_FIO, 0x03E, 0x00084, 0x0, "Merlin+ 132 Core PS/2 Port"}, + {HPHW_FIO, 0x03F, 0x00084, 0x0, "Merlin+ 180 Core PS/2 Port"}, + {HPHW_FIO, 0x044, 0x00084, 0x0, "Mohawk Core PS/2 Port"}, + {HPHW_FIO, 0x045, 0x00084, 0x0, "Rocky1 Core PS/2 Port"}, + {HPHW_FIO, 0x046, 0x00084, 0x0, "Rocky2 120 Core PS/2 Port"}, + {HPHW_FIO, 0x047, 0x00084, 0x0, "Rocky2 150 Core PS/2 Port"}, + {HPHW_FIO, 0x048, 0x00084, 0x0, "Rocky2 120 Dino PS/2 Port"}, + {HPHW_FIO, 0x049, 0x00084, 0x0, "Rocky2 150 Dino PS/2 Port"}, + {HPHW_FIO, 0x04B, 0x00084, 0x0, "Anole L2 132 Core PS/2 Port"}, + {HPHW_FIO, 0x04D, 0x00084, 0x0, "Anole L2 165 Core PS/2 Port"}, + {HPHW_FIO, 0x04E, 0x00084, 0x0, "Kiji L2 132 Core PS/2 Port"}, + {HPHW_FIO, 0x050, 0x00084, 0x0, "Merlin Jr 132 Core PS/2 Port"}, + {HPHW_FIO, 0x051, 0x00084, 0x0, "Firehawk Core PS/2 Port"}, + {HPHW_FIO, 0x056, 0x00084, 0x0, "Raven+ w SE FWSCSI Core PS/2 Port"}, + {HPHW_FIO, 0x057, 0x00084, 0x0, "Raven+ w Diff FWSCSI Core PS/2 Port"}, + {HPHW_FIO, 0x058, 0x00084, 0x0, "FireHawk 200 Core PS/2 Port"}, + {HPHW_FIO, 0x05C, 0x00084, 0x0, "SummitHawk 230 Core PS/2 Port"}, + {HPHW_FIO, 0x800, 0x00084, 0x0, "Hitachi Tiny 64 Core PS/2 Port"}, + {HPHW_FIO, 0x801, 0x00084, 0x0, "Hitachi Tiny 80 Core PS/2 Port"}, {HPHW_FIO, 0x004, 0x00085, 0x0, "Solo GSC Optional Graphics"}, {HPHW_FIO, 0x005, 0x00085, 0x0, "Duet GSC Optional Graphics"}, {HPHW_FIO, 0x008, 0x00085, 0x0, "Anole Artist Optional Graphics"}, @@ -969,18 +987,17 @@ {HPHW_FIO, 0x034, 0x00088, 0x0, "Anole T VME Networking"}, {HPHW_FIO, 0x04A, 0x00088, 0x0, "Anole L2 132 VME Networking"}, {HPHW_FIO, 0x04C, 0x00088, 0x0, "Anole L2 165 VME Networking"}, - {HPHW_FIO, 0x03B, 0x00089, 0x0, "Raven U/L2 Core FW-SCSI"}, - {HPHW_FIO, 0x011, 0x0008A, 0x0, "WB-96 Core Lan (802.3)"}, - {HPHW_FIO, 0x012, 0x0008A, 0x0, "Orville Core Lan (802.3)"}, - {HPHW_FIO, 0x013, 0x0008A, 0x0, "Wilbur Core Lan (802.3)"}, - {HPHW_FIO, 0x014, 0x0008A, 0x0, "WB-80 Core Lan (802.3)"}, - {HPHW_FIO, 0x015, 0x0008A, 0x0, "KittyHawk GSY Core Lan (802.3)"}, - {HPHW_FIO, 0x016, 0x0008A, 0x0, "Gecko Core Lan (802.3)"}, - {HPHW_FIO, 0x018, 0x0008A, 0x0, "Gecko Optional Lan (802.3)"}, - {HPHW_FIO, 0x01A, 0x0008A, 0x0, "Anole 64 Core Lan (802.3)"}, - {HPHW_FIO, 0x01B, 0x0008A, 0x0, "Anole 100 Core Lan (802.3)"}, - {HPHW_FIO, 0x01C, 0x0008A, 0x0, "Gecko 80 Core Lan (802.3)"}, - {HPHW_FIO, 0x01D, 0x0008A, 0x0, "Gecko 100 Core Lan (802.3)"}, + {HPHW_FIO, 0x011, 0x0008A, 0x0, "WB-96 Core LAN (802.3)"}, + {HPHW_FIO, 0x012, 0x0008A, 0x0, "Orville Core LAN (802.3)"}, + {HPHW_FIO, 0x013, 0x0008A, 0x0, "Wilbur Core LAN (802.3)"}, + {HPHW_FIO, 0x014, 0x0008A, 0x0, "WB-80 Core LAN (802.3)"}, + {HPHW_FIO, 0x015, 0x0008A, 0x0, "KittyHawk GSY Core LAN (802.3)"}, + {HPHW_FIO, 0x016, 0x0008A, 0x0, "Gecko Core LAN (802.3)"}, + {HPHW_FIO, 0x018, 0x0008A, 0x0, "Gecko Optional LAN (802.3)"}, + {HPHW_FIO, 0x01A, 0x0008A, 0x0, "Anole 64 Core LAN (802.3)"}, + {HPHW_FIO, 0x01B, 0x0008A, 0x0, "Anole 100 Core LAN (802.3)"}, + {HPHW_FIO, 0x01C, 0x0008A, 0x0, "Gecko 80 Core LAN (802.3)"}, + {HPHW_FIO, 0x01D, 0x0008A, 0x0, "Gecko 100 Core LAN (802.3)"}, {HPHW_FIO, 0x01F, 0x0008A, 0x0, "SkyHawk 100/120 Core LAN (802.3)"}, {HPHW_FIO, 0x027, 0x0008A, 0x0, "Piranha 100 Core LAN (802.3)"}, {HPHW_FIO, 0x028, 0x0008A, 0x0, "Mirage Jr Core LAN (802.3)"}, @@ -991,24 +1008,24 @@ {HPHW_FIO, 0x02E, 0x0008A, 0x0, "UL 350 Core LAN (802.3)"}, {HPHW_FIO, 0x02F, 0x0008A, 0x0, "UL 350 Core LAN (802.3)"}, {HPHW_FIO, 0x032, 0x0008A, 0x0, "Raven T' Core LAN (802.3)"}, - {HPHW_FIO, 0x033, 0x0008A, 0x0, "Anole T Core Lan (802.3)"}, - {HPHW_FIO, 0x034, 0x0008A, 0x0, "SAIC L-80 Core Lan (802.3)"}, - {HPHW_FIO, 0x035, 0x0008A, 0x0, "PCX-L2 712/132 Core Lan (802.3)"}, - {HPHW_FIO, 0x036, 0x0008A, 0x0, "PCX-L2 712/160 Core Lan (802.3)"}, - {HPHW_FIO, 0x03B, 0x0008A, 0x0, "Raven U/L2 Core Lan (802.3)"}, - {HPHW_FIO, 0x03C, 0x0008A, 0x0, "Merlin 132 Core Lan (802.3)"}, - {HPHW_FIO, 0x03D, 0x0008A, 0x0, "Merlin 160 Core Lan (802.3)"}, - {HPHW_FIO, 0x044, 0x0008A, 0x0, "Mohawk Core Lan (802.3)"}, + {HPHW_FIO, 0x033, 0x0008A, 0x0, "Anole T Core LAN (802.3)"}, + {HPHW_FIO, 0x034, 0x0008A, 0x0, "SAIC L-80 Core LAN (802.3)"}, + {HPHW_FIO, 0x035, 0x0008A, 0x0, "PCX-L2 712/132 Core LAN (802.3)"}, + {HPHW_FIO, 0x036, 0x0008A, 0x0, "PCX-L2 712/160 Core LAN (802.3)"}, + {HPHW_FIO, 0x03B, 0x0008A, 0x0, "Raven U/L2 Core LAN (802.3)"}, + {HPHW_FIO, 0x03C, 0x0008A, 0x0, "Merlin 132 Core LAN (802.3)"}, + {HPHW_FIO, 0x03D, 0x0008A, 0x0, "Merlin 160 Core LAN (802.3)"}, + {HPHW_FIO, 0x044, 0x0008A, 0x0, "Mohawk Core LAN (802.3)"}, {HPHW_FIO, 0x045, 0x0008A, 0x0, "Rocky1 Core LAN (802.3)"}, {HPHW_FIO, 0x046, 0x0008A, 0x0, "Rocky2 120 Core LAN (802.3)"}, {HPHW_FIO, 0x047, 0x0008A, 0x0, "Rocky2 150 Core LAN (802.3)"}, {HPHW_FIO, 0x04B, 0x0008A, 0x0, "Anole L2 132 Core LAN (802.3)"}, {HPHW_FIO, 0x04D, 0x0008A, 0x0, "Anole L2 165 Core LAN (802.3)"}, {HPHW_FIO, 0x04E, 0x0008A, 0x0, "Kiji L2 132 Core LAN (802.3)"}, - {HPHW_FIO, 0x050, 0x0008A, 0x0, "Merlin Jr 132 Core Lan (802.3)"}, + {HPHW_FIO, 0x050, 0x0008A, 0x0, "Merlin Jr 132 Core LAN (802.3)"}, {HPHW_FIO, 0x058, 0x0008A, 0x0, "FireHawk 200 Core LAN (802.3)"}, - {HPHW_FIO, 0x800, 0x0008A, 0x0, "Hitachi Tiny 64 Core Lan (802.3)"}, - {HPHW_FIO, 0x801, 0x0008A, 0x0, "Hitachi Tiny 80 Core Lan (802.3)"}, + {HPHW_FIO, 0x800, 0x0008A, 0x0, "Hitachi Tiny 64 Core LAN (802.3)"}, + {HPHW_FIO, 0x801, 0x0008A, 0x0, "Hitachi Tiny 80 Core LAN (802.3)"}, {HPHW_FIO, 0x004, 0x0008C, 0x0, "SkyHawk 100/120 Wax RS-232"}, {HPHW_FIO, 0x005, 0x0008C, 0x0, "SAIC L-80 Wax RS-232"}, {HPHW_FIO, 0x006, 0x0008C, 0x0, "Raven U/L2 Dino RS-232"}, @@ -1099,14 +1116,15 @@ {HPHW_FIO, 0x005, 0x0008F, 0x0, "Rocky1 Boot Rom"}, {HPHW_FIO, 0x006, 0x0008F, 0x0, "Rocky2 120 Boot Rom"}, {HPHW_FIO, 0x007, 0x0008F, 0x0, "Rocky2 150 Boot Rom"}, - {HPHW_FIO, 0x006, 0x00096, 0x0, "Raven U/L2 Dino PS2 Keyboard"}, - {HPHW_FIO, 0x007, 0x00096, 0x0, "Dino PS2 Keyboard"}, - {HPHW_FIO, 0x008, 0x00096, 0x0, "Merlin 132 Dino PS2 Keyboard"}, - {HPHW_FIO, 0x009, 0x00096, 0x0, "Merlin 160 Dino PS2 Keyboard"}, - {HPHW_FIO, 0x00A, 0x00096, 0x0, "Merlin Jr 132 Dino PS2 Keyboard"}, - {HPHW_FIO, 0x019, 0x00096, 0x0, "Merlin+ 180 Dino PS2 Keyboard"}, - {HPHW_FIO, 0x022, 0x00096, 0x0, "Merlin+ 132 Dino PS2 Keyboard"}, - {HPHW_FIO, 0x004, 0x00097, 0x0, "Cascade EISA 100VG lan"}, + {HPHW_FIO, 0x01B, 0x0008F, 0x0, "Anole 100 Boot Rom"}, + {HPHW_FIO, 0x006, 0x00096, 0x0, "Raven U/L2 Dino PS/2 Port"}, + {HPHW_FIO, 0x007, 0x00096, 0x0, "Dino PS/2 Port"}, + {HPHW_FIO, 0x008, 0x00096, 0x0, "Merlin 132 Dino PS/2 Port"}, + {HPHW_FIO, 0x009, 0x00096, 0x0, "Merlin 160 Dino PS/2 Port"}, + {HPHW_FIO, 0x00A, 0x00096, 0x0, "Merlin Jr 132 Dino PS/2 Port"}, + {HPHW_FIO, 0x019, 0x00096, 0x0, "Merlin+ 180 Dino PS/2 Port"}, + {HPHW_FIO, 0x022, 0x00096, 0x0, "Merlin+ 132 Dino PS/2 Port"}, + {HPHW_FIO, 0x004, 0x00097, 0x0, "Cascade EISA 100VG LAN"}, {HPHW_FIO, 0x023, 0x00099, 0x0, "Rocky1 Wax HPIB"}, {HPHW_FIO, 0x048, 0x00099, 0x0, "Rocky2 120 Clark/Dino HPIB"}, {HPHW_FIO, 0x049, 0x00099, 0x0, "Rocky2 150 Clark/Dino HPIB"}, @@ -1114,14 +1132,14 @@ {HPHW_FIO, 0x004, 0x000A2, 0x0, "Forte Core PCI 10/100BT LAN"}, {HPHW_FIO, 0x005, 0x000A2, 0x0, "AllegroLow PCI 10/100BT LAN"}, {HPHW_FIO, 0x006, 0x000A2, 0x0, "AllegroHIgh Core PCI 10/100BT LAN"}, - {HPHW_FIO, 0x007, 0x000A2, 0x0, "PCI Plug-in Lan"}, - {HPHW_FIO, 0x00A, 0x000A2, 0x0, "Lego 360 Core PCI 10/100BT Lan"}, - {HPHW_FIO, 0x03E, 0x000A2, 0x0, "Merlin+ 132 Core PCI Lan"}, - {HPHW_FIO, 0x03F, 0x000A2, 0x0, "Merlin+ 180 Core PCI Lan"}, - {HPHW_FIO, 0x056, 0x000A2, 0x0, "Raven+ w SE FWSCSI Core PCI Lan"}, - {HPHW_FIO, 0x057, 0x000A2, 0x0, "Raven+ w Diff FWSCSI Core PCI Lan"}, - {HPHW_FIO, 0x05E, 0x000A2, 0x0, "Staccato 132 PCI Lan"}, - {HPHW_FIO, 0x05F, 0x000A2, 0x0, "Staccato 180 PCI Lan"}, + {HPHW_FIO, 0x007, 0x000A2, 0x0, "PCI Plug-in LAN"}, + {HPHW_FIO, 0x00A, 0x000A2, 0x0, "Lego 360 Core PCI 10/100BT LAN"}, + {HPHW_FIO, 0x03E, 0x000A2, 0x0, "Merlin+ 132 Core PCI LAN"}, + {HPHW_FIO, 0x03F, 0x000A2, 0x0, "Merlin+ 180 Core PCI LAN"}, + {HPHW_FIO, 0x056, 0x000A2, 0x0, "Raven+ w SE FWSCSI Core PCI LAN"}, + {HPHW_FIO, 0x057, 0x000A2, 0x0, "Raven+ w Diff FWSCSI Core PCI LAN"}, + {HPHW_FIO, 0x05E, 0x000A2, 0x0, "Staccato 132 PCI LAN"}, + {HPHW_FIO, 0x05F, 0x000A2, 0x0, "Staccato 180 PCI LAN"}, {HPHW_FIO, 0x004, 0x000A3, 0x0, "Forte Core PCI LVD Ultra2 SCSI"}, {HPHW_FIO, 0x004, 0x000A3, 0x0, "Forte Core PCI SE UltraSCSI"}, {HPHW_FIO, 0x004, 0x000A3, 0x0, "Forte Core PCI IDE/ATAPI CD-ROM"}, @@ -1157,160 +1175,19 @@ {HPHW_IOA, 0x185, 0x0000B, 0x00, "Java BC Summit Port"}, {HPHW_IOA, 0x1FF, 0x0000B, 0x00, "Hitachi Ghostview Summit Port"}, {HPHW_IOA, 0x580, 0x0000B, 0x10, "U2-IOA BC Runway Port"}, - {HPHW_IOA, 0x581, 0x0000B, 0x10, "Uturn-IOA BC Runway Port"}, - {HPHW_IOA, 0x582, 0x0000B, 0x10, "Astro BC Runway Port"}, - {HPHW_IOA, 0x700, 0x0000B, 0x00, "NEC-IOS BC System Bus Port"}, + {HPHW_IOA, 0x581, 0x0000B, 0x10, "Uturn-IOA BC Runway Port"}, + {HPHW_IOA, 0x582, 0x0000B, 0x10, "Astro BC Runway Port"}, + {HPHW_IOA, 0x700, 0x0000B, 0x00, "NEC-IOS BC System Bus Port"}, {HPHW_MEMORY, 0x002, 0x00008, 0x00, "MID_BUS"}, - {HPHW_MEMORY, 0x00C, 0x00008, 0x08, "Kahlua 8MB"}, - {HPHW_MEMORY, 0x00D, 0x00008, 0x08, "Kahlua 4MB"}, - {HPHW_MEMORY, 0x00E, 0x00008, 0x08, "Tequila 16MB"}, - {HPHW_MEMORY, 0x00F, 0x00008, 0x08, "Tequila 32MB"}, - {HPHW_MEMORY, 0x040, 0x00008, 0x00, "Hitachi"}, - {HPHW_MEMORY, 0x004, 0x00009, 0x00, "Cheetah"}, - {HPHW_MEMORY, 0x005, 0x00009, 0x00, "Emerald"}, - {HPHW_MEMORY, 0x008, 0x00009, 0x00, "Indigo 3MB/5MB"}, - {HPHW_MEMORY, 0x00C, 0x00009, 0x00, "Indigo 8MB"}, - {HPHW_MEMORY, 0x00D, 0x00009, 0x00, "Paradise 4MB"}, - {HPHW_MEMORY, 0x00E, 0x00009, 0x00, "Burgundy Onboard"}, - {HPHW_MEMORY, 0x012, 0x00009, 0x00, "Indigo 12MB/20MB"}, - {HPHW_MEMORY, 0x013, 0x00009, 0x00, "Cobra"}, - {HPHW_MEMORY, 0x014, 0x00009, 0x00, "Nova"}, - {HPHW_MEMORY, 0x015, 0x00009, 0x00, "Coral"}, - {HPHW_MEMORY, 0x016, 0x00009, 0x00, "Bushmaster"}, - {HPHW_MEMORY, 0x017, 0x00009, 0x00, "Scorpio"}, - {HPHW_MEMORY, 0x018, 0x00009, 0x00, "Flounder"}, - {HPHW_MEMORY, 0x019, 0x00009, 0x00, "Hardball"}, - {HPHW_MEMORY, 0x01A, 0x00009, 0x00, "CoralII 99"}, - {HPHW_MEMORY, 0x01B, 0x00009, 0x00, "Scorpio Jr."}, - {HPHW_MEMORY, 0x01C, 0x00009, 0x00, "Strider-50 (715T)"}, - {HPHW_MEMORY, 0x01D, 0x00009, 0x00, "Strider-33 (707T)"}, - {HPHW_MEMORY, 0x01E, 0x00009, 0x00, "Trailways-50 (715S)"}, - {HPHW_MEMORY, 0x01F, 0x00009, 0x00, "Trailways-33 (707S)"}, - {HPHW_MEMORY, 0x020, 0x00009, 0x00, "Pace"}, - {HPHW_MEMORY, 0x021, 0x00009, 0x00, "Sidewinder"}, - {HPHW_MEMORY, 0x022, 0x00009, 0x00, "Orville"}, - {HPHW_MEMORY, 0x023, 0x00009, 0x00, "Wilbur"}, - {HPHW_MEMORY, 0x026, 0x00009, 0x00, "Gecko"}, - {HPHW_MEMORY, 0x027, 0x00009, 0x00, "Scorpio Sr."}, - {HPHW_MEMORY, 0x028, 0x00009, 0x00, "Scorpio 100"}, - {HPHW_MEMORY, 0x029, 0x00009, 0x00, "Spectra 50"}, - {HPHW_MEMORY, 0x02A, 0x00009, 0x00, "CoralII 132"}, - {HPHW_MEMORY, 0x02F, 0x00009, 0x00, "KittyHawk DC2-"}, - {HPHW_MEMORY, 0x030, 0x00009, 0x00, "Spectra 75"}, - {HPHW_MEMORY, 0x031, 0x00009, 0x00, "Spectra 100"}, - {HPHW_MEMORY, 0x032, 0x00009, 0x00, "KittyHawk DC3"}, - {HPHW_MEMORY, 0x033, 0x00009, 0x00, "Fast Pace"}, - {HPHW_MEMORY, 0x034, 0x00009, 0x00, "Snake Eagle"}, - {HPHW_MEMORY, 0x035, 0x00009, 0x00, "Anole 64"}, - {HPHW_MEMORY, 0x036, 0x00009, 0x00, "Anole 100"}, - {HPHW_MEMORY, 0x037, 0x00009, 0x00, "Snake Cheetah"}, - {HPHW_MEMORY, 0x038, 0x00009, 0x00, "Gecko 80"}, - {HPHW_MEMORY, 0x039, 0x00009, 0x00, "Gecko 100"}, - {HPHW_MEMORY, 0x03A, 0x00009, 0x00, "Gecko 120"}, - {HPHW_MEMORY, 0x03B, 0x00009, 0x00, "Gila 80"}, - {HPHW_MEMORY, 0x03C, 0x00009, 0x00, "Gila 100"}, - {HPHW_MEMORY, 0x03D, 0x00009, 0x00, "Gila 120"}, - {HPHW_MEMORY, 0x03E, 0x00009, 0x00, "Scorpio-L 80"}, - {HPHW_MEMORY, 0x03F, 0x00009, 0x00, "Scorpio-L 100"}, - {HPHW_MEMORY, 0x040, 0x00009, 0x00, "Scorpio-L 120"}, - {HPHW_MEMORY, 0x041, 0x00009, 0x00, "Spectra-L 80"}, - {HPHW_MEMORY, 0x042, 0x00009, 0x00, "Spectra-L 100"}, - {HPHW_MEMORY, 0x043, 0x00009, 0x00, "Spectra-L 120"}, - {HPHW_MEMORY, 0x044, 0x00009, 0x00, "Piranha 100"}, - {HPHW_MEMORY, 0x045, 0x00009, 0x00, "Piranha 120"}, - {HPHW_MEMORY, 0x046, 0x00009, 0x00, "Jason 50"}, - {HPHW_MEMORY, 0x047, 0x00009, 0x00, "Jason 100"}, - {HPHW_MEMORY, 0x049, 0x00009, 0x00, "SkyHawk 100/120"}, - {HPHW_MEMORY, 0x04A, 0x00009, 0x00, "Mirage Jr"}, - {HPHW_MEMORY, 0x04B, 0x00009, 0x00, "Mirage 100"}, - {HPHW_MEMORY, 0x04C, 0x00009, 0x00, "Mirage 100+"}, - {HPHW_MEMORY, 0x04D, 0x00009, 0x00, "Electra 100"}, - {HPHW_MEMORY, 0x04E, 0x00009, 0x00, "Electra 120"}, - {HPHW_MEMORY, 0x04F, 0x00009, 0x00, "Mirage 80"}, - {HPHW_MEMORY, 0x050, 0x00009, 0x00, "UL Proc 1 way T'100"}, - {HPHW_MEMORY, 0x051, 0x00009, 0x00, "UL Proc 1 way T'120"}, - {HPHW_MEMORY, 0x052, 0x00009, 0x00, "UL Proc 2 way T'100"}, - {HPHW_MEMORY, 0x053, 0x00009, 0x00, "KittyHawk DC3-"}, - {HPHW_MEMORY, 0x054, 0x00009, 0x00, "UL Proc 2 way T'120"}, - {HPHW_MEMORY, 0x055, 0x00009, 0x00, "Raven 120 mem"}, - {HPHW_MEMORY, 0x056, 0x00009, 0x00, "UL Proc L 75"}, - {HPHW_MEMORY, 0x057, 0x00009, 0x00, "UL Proc L 100"}, - {HPHW_MEMORY, 0x058, 0x00009, 0x00, "Anole T"}, - {HPHW_MEMORY, 0x059, 0x00009, 0x00, "SAIC L-80"}, - {HPHW_MEMORY, 0x05A, 0x00009, 0x00, "Merlin+ L2 180"}, - {HPHW_MEMORY, 0x05B, 0x00009, 0x00, "Raven U 200 2-way"}, - {HPHW_MEMORY, 0x05C, 0x00009, 0x00, "Raven U 180+"}, - {HPHW_MEMORY, 0x05D, 0x00009, 0x00, "Raven U 200"}, - {HPHW_MEMORY, 0x05E, 0x00009, 0x00, "Rocky2 150 Memory"}, - {HPHW_MEMORY, 0x08A, 0x00009, 0x00, "Staccato L2 132 Memory"}, - {HPHW_MEMORY, 0x08B, 0x00009, 0x00, "Staccato L2 180 Memory"}, - {HPHW_MEMORY, 0x05F, 0x00009, 0x00, "SPP2000 Memory"}, - {HPHW_MEMORY, 0x060, 0x00009, 0x00, "Merlin L2 132"}, - {HPHW_MEMORY, 0x061, 0x00009, 0x00, "Merlin+ L2 132"}, {HPHW_MEMORY, 0x063, 0x00009, 0x00, "712/132 L2 Upgrade"}, {HPHW_MEMORY, 0x064, 0x00009, 0x00, "712/160 L2 Upgrade"}, {HPHW_MEMORY, 0x065, 0x00009, 0x00, "715/132 L2 Upgrade"}, - {HPHW_MEMORY, 0x066, 0x00009, 0x00, "715/160 L2 Upgrade"}, - {HPHW_MEMORY, 0x067, 0x00009, 0x00, "Merlin 160/ThunderHawk Memory"}, - {HPHW_MEMORY, 0x068, 0x00009, 0x00, "LightningHawk Memory"}, - {HPHW_MEMORY, 0x069, 0x00009, 0x00, "Rocky1 Memory"}, - {HPHW_MEMORY, 0x06A, 0x00009, 0x00, "Raven L2 132"}, - {HPHW_MEMORY, 0x06B, 0x00009, 0x00, "Raven L2 160"}, - {HPHW_MEMORY, 0x06C, 0x00009, 0x00, "Raven L2 187"}, - {HPHW_MEMORY, 0x06D, 0x00009, 0x00, "Raven L2 200"}, - {HPHW_MEMORY, 0x06E, 0x00009, 0x00, "Raven U 230"}, - {HPHW_MEMORY, 0x06F, 0x00009, 0x00, "Raven U 240"}, - {HPHW_MEMORY, 0x070, 0x00009, 0x00, "Rocky2 120 Memory"}, - {HPHW_MEMORY, 0x071, 0x00009, 0x00, "Raven U 160"}, - {HPHW_MEMORY, 0x072, 0x00009, 0x00, "Raven U 180"}, - {HPHW_MEMORY, 0x072, 0x00009, 0x00, "UL Proc 1 way T'120 1MB/1MB"}, - {HPHW_MEMORY, 0x073, 0x00009, 0x00, "UL Proc 2 way T'120 1MB/1MB"}, - {HPHW_MEMORY, 0x074, 0x00009, 0x00, "Anole L2 132 memory"}, - {HPHW_MEMORY, 0x075, 0x00009, 0x00, "Anole L2 165 memory"}, - {HPHW_MEMORY, 0x076, 0x00009, 0x00, "UL 1 way U160 512K/512K memory"}, - {HPHW_MEMORY, 0x077, 0x00009, 0x00, "UL 2 way U160 512K/512K memory"}, - {HPHW_MEMORY, 0x078, 0x00009, 0x00, "Kiji L2 132 memory"}, - {HPHW_MEMORY, 0x079, 0x00009, 0x00, "UL 1 way U160 1M/1M memory"}, - {HPHW_MEMORY, 0x07A, 0x00009, 0x00, "UL 2 way U160 1M/1M memory"}, - {HPHW_MEMORY, 0x07B, 0x00009, 0x00, "UL 1 way U180 1M/1M memory"}, - {HPHW_MEMORY, 0x07C, 0x00009, 0x00, "UL 2 way U180 1M/1M memory"}, - {HPHW_MEMORY, 0x07D, 0x00009, 0x00, "UL 1 way U240 U+ 2M/2M memory"}, - {HPHW_MEMORY, 0x07E, 0x00009, 0x00, "UL 2 way U240 U+ 2M/2M memory"}, - {HPHW_MEMORY, 0x07F, 0x00009, 0x00, "UL L2 132 memory"}, - {HPHW_MEMORY, 0x080, 0x00009, 0x00, "UL L2 160 memory"}, - {HPHW_MEMORY, 0x081, 0x00009, 0x00, "Merlin Jr 132 memory"}, - {HPHW_MEMORY, 0x082, 0x00009, 0x00, "FireHawk 200 Memory"}, - {HPHW_MEMORY, 0x083, 0x00009, 0x00, "SummitHawk Memory"}, - {HPHW_MEMORY, 0x084, 0x00009, 0x00, "Jade Upgrade Memory"}, - {HPHW_MEMORY, 0x085, 0x00009, 0x00, "SPP2500 Memory"}, - {HPHW_MEMORY, 0x086, 0x00009, 0x00, "AllegroHigh Memory"}, - {HPHW_MEMORY, 0x087, 0x00009, 0x00, "AllegroLow Memory"}, - {HPHW_MEMORY, 0x088, 0x00009, 0x00, "Forte 2w Memory"}, - {HPHW_MEMORY, 0x089, 0x00009, 0x00, "Forte 4w Memory"}, - {HPHW_MEMORY, 0x08A, 0x00009, 0x00, "Staccato L2 132 Memory"}, - {HPHW_MEMORY, 0x08B, 0x00009, 0x00, "Staccato L2 180 Memory"}, - {HPHW_MEMORY, 0x090, 0x00009, 0x00, "Prelude SMC Memory"}, - {HPHW_MEMORY, 0x091, 0x00009, 0x00, "Lego 360 Memory"}, - {HPHW_MEMORY, 0x7FF, 0x00009, 0x00, "NEC Aska memory"}, - {HPHW_MEMORY, 0x800, 0x00009, 0x00, "Hitachi Tiny 64"}, - {HPHW_MEMORY, 0x801, 0x00009, 0x00, "Hitachi Tiny 80"}, - {HPHW_MEMORY, 0x8FF, 0x00009, 0x00, "Hitachi X memory"}, - {HPHW_MEMORY, 0x091, 0x00009, 0x00, "M2250 Memory"}, - {HPHW_MEMORY, 0x092, 0x00009, 0x00, "M2500 Memory"}, - {HPHW_MEMORY, 0x093, 0x00009, 0x00, "Sonata 440 Memory"}, - {HPHW_MEMORY, 0x094, 0x00009, 0x00, "Sonata 360 Memory"}, - {HPHW_MEMORY, 0x095, 0x00009, 0x00, "Rhapsody 440 Memory"}, - {HPHW_MEMORY, 0x096, 0x00009, 0x00, "Rhapsody 360 Memory"}, - {HPHW_MEMORY, 0x097, 0x00009, 0x00, "Raven W 360 Memory"}, - {HPHW_MEMORY, 0x098, 0x00009, 0x00, "Halfdome W 440 Memory"}, - {HPHW_MEMORY, 0x099, 0x00009, 0x00, "Rhapsody DC- 440 Memory"}, - {HPHW_MEMORY, 0x09A, 0x00009, 0x00, "Rhapsody DC- 360 Memory"}, - {HPHW_MEMORY, 0x09B, 0x00009, 0x00, "Crescendo Memory"}, + {HPHW_MEMORY, 0x066, 0x00009, 0x00, "715/160 L2 Upgrade"}, {HPHW_OTHER, 0x004, 0x00030, 0x00, "Master"}, {HPHW_OTHER, 0x004, 0x00034, 0x00, "Slave"}, {HPHW_OTHER, 0x004, 0x00038, 0x00, "EDU"}, {HPHW_OTHER, 0x004, 0x00049, 0x00, "LGB Control"}, - {0, } /* leave the last entry empty ! */ + {HPHW_FAULTY, 0, } /* Special Marker for last entry */ }; @@ -1318,7 +1195,7 @@ unsigned short model; unsigned short mask; enum cpu_type cpu; -} hp_cpu_type_mask_list[] = { +} hp_cpu_type_mask_list[] __initdata = { { 0x0000, 0x0ff0, pcx }, /* 0x0000 - 0x000f */ { 0x0048, 0x0ff0, pcxl }, /* 0x0040 - 0x004f */ @@ -1350,8 +1227,10 @@ { 0x0592, 0x0fff, pcxt_ }, /* 0x0592 - 0x0592 */ { 0x0593, 0x0fff, pcxu }, /* 0x0593 - 0x0593 */ { 0x0594, 0x0ffc, pcxu }, /* 0x0594 - 0x0597 */ - { 0x0598, 0x0ffc, pcxu }, /* 0x0598 - 0x059b */ - { 0x059c, 0x0ffe, pcxu_ }, /* 0x059c - 0x059d */ + { 0x0598, 0x0ffe, pcxu_ }, /* 0x0598 - 0x0599 */ + { 0x059a, 0x0ffe, pcxu }, /* 0x059a - 0x059b */ + { 0x059c, 0x0fff, pcxu }, /* 0x059c - 0x059c */ + { 0x059d, 0x0fff, pcxu_ }, /* 0x059d - 0x059d */ { 0x059e, 0x0fff, pcxt_ }, /* 0x059e - 0x059e */ { 0x059f, 0x0fff, pcxu }, /* 0x059f - 0x059f */ { 0x05a0, 0x0ffe, pcxt_ }, /* 0x05a0 - 0x05a1 */ @@ -1370,7 +1249,27 @@ { 0x05ba, 0x0fff, pcxu_ }, /* 0x05ba - 0x05ba */ { 0x05bb, 0x0fff, pcxw }, /* 0x05bb - 0x05bb */ { 0x05bc, 0x0ffc, pcxw }, /* 0x05bc - 0x05bf */ - { 0x05c0, 0x0fc0, pcxw }, /* 0x05c0 - 0x05ff */ + { 0x05c0, 0x0ffc, pcxw }, /* 0x05c0 - 0x05c3 */ + { 0x05c4, 0x0ffe, pcxw }, /* 0x05c4 - 0x05c5 */ + { 0x05c6, 0x0fff, pcxw }, /* 0x05c6 - 0x05c6 */ + { 0x05c7, 0x0fff, pcxw_ }, /* 0x05c7 - 0x05c7 */ + { 0x05c8, 0x0ffc, pcxw }, /* 0x05c8 - 0x05cb */ + { 0x05cc, 0x0ffe, pcxw }, /* 0x05cc - 0x05cd */ + { 0x05ce, 0x0ffe, pcxw_ }, /* 0x05ce - 0x05cf */ + { 0x05d0, 0x0ffc, pcxw_ }, /* 0x05d0 - 0x05d3 */ + { 0x05d4, 0x0ffe, pcxw_ }, /* 0x05d4 - 0x05d5 */ + { 0x05d6, 0x0fff, pcxw }, /* 0x05d6 - 0x05d6 */ + { 0x05d7, 0x0fff, pcxw_ }, /* 0x05d7 - 0x05d7 */ + { 0x05d8, 0x0ffc, pcxw_ }, /* 0x05d8 - 0x05db */ + { 0x05dc, 0x0ffe, pcxw2 }, /* 0x05dc - 0x05dd */ + { 0x05de, 0x0fff, pcxw_ }, /* 0x05de - 0x05de */ + { 0x05df, 0x0fff, pcxw2 }, /* 0x05df - 0x05df */ + { 0x05e0, 0x0ffc, pcxw2 }, /* 0x05e0 - 0x05e3 */ + { 0x05e4, 0x0fff, pcxw2 }, /* 0x05e4 - 0x05e4 */ + { 0x05e5, 0x0fff, pcxw_ }, /* 0x05e5 - 0x05e5 */ + { 0x05e6, 0x0ffe, pcxw2 }, /* 0x05e6 - 0x05e7 */ + { 0x05e8, 0x0ff8, pcxw2 }, /* 0x05e8 - 0x05ef */ + { 0x05f0, 0x0ff0, pcxw2 }, /* 0x05f0 - 0x05ff */ { 0x0600, 0x0ff0, pcxl }, /* 0x0600 - 0x060f */ { 0x0610, 0x0ff0, pcxl }, /* 0x0610 - 0x061f */ { 0x0000, 0x0000, pcx } /* terminate table */ @@ -1386,36 +1285,51 @@ [pcxu] { "PA8000 (PCX-U)", "2.0" }, [pcxu_] { "PA8200 (PCX-U+)", "2.0" }, [pcxw] { "PA8500 (PCX-W)", "2.0" }, - [pcxw_] { "PA8600 (PCX-W+)", "2.0" } + [pcxw_] { "PA8600 (PCX-W+)", "2.0" }, + [pcxw2] { "PA8700 (PCX-W2)", "2.0" } }; -char *parisc_getHWtype(unsigned short hw_type) -{ - if (hw_type <= HPHW_CIO) { - return hw_type_name[hw_type]; - } else { - return "Unknown Type"; - } -} - -char *parisc_getHWdescription(unsigned short hw_type, unsigned long hversion, - unsigned long sversion) +const char * __init +parisc_hardware_description(struct parisc_device_id *id) { struct hp_hardware *listptr; - for (listptr = hp_hardware_list; listptr->name; listptr++) { - if ((listptr->hw_type==hw_type) && - (listptr->hversion==hversion) && - (listptr->sversion==sversion)){ + for (listptr = hp_hardware_list; listptr->hw_type != HPHW_FAULTY; listptr++) { + if ((listptr->hw_type == id->hw_type) && + (listptr->hversion == id->hversion) && + (listptr->sversion == id->sversion)){ return listptr->name; } } + + /* + * ok, the above hardware table isn't complete, and we haven't found + * our device in this table. So let's now try to find a generic name + * to describe the given hardware... + */ + switch (id->hw_type) { + case HPHW_NPROC: + return "Unknown machine"; + + case HPHW_A_DIRECT: + switch (id->sversion) { + case 0x0D: return "MUX port"; + case 0x0E: return "RS-232 port"; + } + break; + + case HPHW_MEMORY: + return "Memory"; + + } + return "unknown device"; } /* Interpret hversion (ret[0]) from PDC_MODEL(4)/PDC_MODEL_INFO(0) */ -enum cpu_type parisc_get_cpu_type(unsigned long hversion) +enum cpu_type __init +parisc_get_cpu_type(unsigned long hversion) { struct hp_cpu_type_mask *ptr; unsigned short model = ((unsigned short) (hversion)) >> 4; @@ -1424,23 +1338,8 @@ if (ptr->model == (model & ptr->mask)) return ptr->cpu; } - panic("parisc_get_cpu_type() could not identify CPU type\n"); + panic("could not identify CPU type\n"); return pcx; /* not reached: */ } - -struct hp_hardware *parisc_get_reference(unsigned short hw_type, - unsigned long hversion, unsigned long sversion) -{ - struct hp_hardware *listptr = hp_hardware_list; - - for (listptr = hp_hardware_list; listptr->name; listptr++) { - if ((listptr->hw_type == hw_type) && - (listptr->hversion == hversion) && - (listptr->sversion == sversion)) { - return listptr; - } - } - return NULL; -} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/head64.S linux.19rc3-ac4/arch/parisc/kernel/head64.S --- linux.19rc3/arch/parisc/kernel/head64.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/head64.S 2002-07-29 13:58:36.000000000 +0100 @@ -0,0 +1,333 @@ +/* + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1999 by Helge Deller + * Copyright 1999 SuSE GmbH (Philipp Rumpf) + * Copyright 1999 Philipp Rumpf (prumpf@tux.org) + * Copyright 2000 Hewlett Packard (Paul Bame, bame@puffin.external.hp.com) + * Copyright (C) 2001 Grant Grundler (Hewlett Packard) + * + * Initial Version 04-23-1999 by Helge Deller + */ + + +#include /* for CONFIG_SMP */ + +#include +#include + +#include +#include +#include /* for PDC_PSW defines */ + + + .level 2.0 + + .section .initcall.init + .align 4 + .export __initcall_start +__initcall_start: + .export __initcall_end +__initcall_end: + .export __setup_start +__setup_start: + .export __setup_end +__setup_end: + + .data + + .export boot_args +boot_args: + .word 0 /* arg0 */ + .word 0 /* arg1 */ + .word 0 /* arg2 */ + .word 0 /* arg3 */ + + .text + .align 4 + + .export stext + .export _stext,data /* Kernel want it this way! */ +_stext: +stext: + .proc + .callinfo + + /* Make sure sr4-sr7 are set to zero for the kernel address space */ + mtsp %r0,%sr4 + mtsp %r0,%sr5 + mtsp %r0,%sr6 + mtsp %r0,%sr7 + + /* Clear BSS (shouldn't the boot loader do this?) */ + + .import _edata,data + .import _end,data + + ldil L%PA(_edata),%r3 + ldo R%PA(_edata)(%r3),%r3 + ldil L%PA(_end),%r4 + ldo R%PA(_end)(%r4),%r4 +$bss_loop: + cmpb,<<,n %r3,%r4,$bss_loop + stb,ma %r0,1(%r3) + + /* Save away the arguments the boot loader passed in (32 bit args) */ + + ldil L%PA(boot_args),%r1 + ldo R%PA(boot_args)(%r1),%r1 + stw,ma %arg0,4(%r1) + stw,ma %arg1,4(%r1) + stw,ma %arg2,4(%r1) + stw,ma %arg3,4(%r1) + + /* Initialize startup VM. Just map first 8 MB of memory */ + + ldil L%PA(pg0),%r1 + ldo R%PA(pg0)(%r1),%r1 + + ldil L%PA(pmd0),%r5 + ldo R%PA(pmd0)(%r5),%r5 + ldo _PAGE_TABLE(%r5),%r3 + + ldil L%PA(swapper_pg_dir),%r4 + ldo R%PA(swapper_pg_dir)(%r4),%r4 + + mtctl %r4,%cr24 /* Initialize kernel root pointer */ + mtctl %r4,%cr25 /* Initialize user root pointer */ + +#if (__PAGE_OFFSET != 0x10000000UL) +Error! Code below (the next five std's) needs to be changed +#endif + + std %r3,0x00(%r4) /* Hardwired 0x1... kernel Vaddr start*/ + + ldo _PAGE_TABLE(%r1),%r3 + std %r3,0x400(%r5) /* Hardwired 0x1... kernel Vaddr start*/ + ldo 0x1000(%r3),%r3 + std %r3,0x408(%r5) + ldo 0x1000(%r3),%r3 + std %r3,0x410(%r5) + ldo 0x1000(%r3),%r3 + std %r3,0x418(%r5) + + ldo _PAGE_KERNEL(%r0),%r3 /* Hardwired 0 phys addr start */ +$pgt_fill_loop: + std,ma %r3,8(%r1) + ldo 0x1000(%r3),%r3 + bb,>= %r3,8,$pgt_fill_loop + nop + + /* And the RFI Target address too */ + load32 start_kernel, %r11 + + /* And the stack pointer too */ + load32 PA(init_task_union+TASK_SZ_ALGN),%sp + + /* And the initial task pointer */ + + load32 init_task_union,%r6 + mtctl %r6,%cr30 + + /* And the interrupt stack */ + + load32 interrupt_stack,%r6 + mtctl %r6,%cr31 + + /* Act like PDC just called us - that's how slave CPUs enter */ +#define MEM_PDC_LO 0x388 +#define MEM_PDC_HI 0x35C + ldw MEM_PDC_LO(%r0),%r3 + ldw MEM_PDC_HI(%r0),%r6 + depd %r6, 31, 32, %r3 /* move to upper word */ + +#ifdef CONFIG_SMP + /* Set the smp rendevous address into page zero. + ** It would be safer to do this in init_smp_config() but + ** it's just way easier to deal with here because + ** of 64-bit function ptrs and the address is local to this file. + */ + ldil L%PA(smp_slave_stext),%r10 + ldo R%PA(smp_slave_stext)(%r10),%r10 + stw %r10,0x10(%r0) /* MEM_RENDEZ */ + stw %r0,0x28(%r0) /* MEM_RENDEZ_HI - assume addr < 4GB */ + + /* FALLTHROUGH */ + .procend + + /* + ** Code Common to both Monarch and Slave processors. + ** Entry: + ** %r3 PDCE_PROC address + ** %r11 RFI target address. + ** + ** Caller must init: SR4-7, %sp, %r10, %cr24/25, + */ +common_stext: + .proc + .callinfo +#else /* CONFIG_SMP */ + /* Clear PDC's CPU handoff address - we won't use it */ + stw %r0,0x10(%r0) /* MEM_RENDEZ */ + stw %r0,0x28(%r0) /* MEM_RENDEZ_HI */ +#endif /* CONFIG_SMP */ + + /* Save the rfi target address */ + std %r11, TASK_PT_GR11-TASK_SZ_ALGN(%sp) + +#ifndef CONFIG_PDC_NARROW + /* Switch to wide mode; Superdome doesn't support narrow PDC + ** calls. + */ +1: mfia %rp /* clear upper part of pcoq */ + ldo 2f-1b(%rp),%rp + depdi 0,31,32,%rp + bv (%rp) + ssm PSW_SM_W,%r0 +2: +#endif /* CONFIG_PDC_NARROW */ + + /* Set Wide mode as the "Default" (eg for traps) + ** First trap occurs *right* after (or part of) rfi for slave CPUs. + ** Someday, palo might not do this for the Monarch either. + */ + + ldo PDC_PSW(%r0),%arg0 /* 21 */ + ldo PDC_PSW_SET_DEFAULTS(%r0),%arg1 /* 2 */ + ldo PDC_PSW_WIDE_BIT(%r0),%arg2 /* 2 */ + + load32 PA(stext_pdc_ret), %rp + + bv (%r3) + copy %r0,%arg3 + +stext_pdc_ret: + /* restore rfi target address*/ + ldd TASK_PT_GR11-TASK_SZ_ALGN(%sp), %r11 + + /* PARANOID: clear user scratch/user space SR's */ + mtsp %r0,%sr0 + mtsp %r0,%sr1 + mtsp %r0,%sr2 + mtsp %r0,%sr3 + + /* Initialize Protection Registers */ + mtctl %r0,%cr8 + mtctl %r0,%cr9 + mtctl %r0,%cr12 + mtctl %r0,%cr13 + + /* Prepare to RFI! Man all the cannons! */ + tovirt_r1 %sp + + /* Initialize the global data pointer */ + load32 __gp,%dp + + /* Set up our interrupt table. HPMCs might not work after this! */ + ldil L%PA(fault_vector_20),%r10 + ldo R%PA(fault_vector_20)(%r10),%r10 + mtctl %r10,%cr14 + + b aligned_rfi + nop + + /* the magic spell */ + .align 256 +aligned_rfi: + ssm 0,0 + nop /* 1 */ + nop /* 2 */ + nop /* 3 */ + nop /* 4 */ + nop /* 5 */ + nop /* 6 */ + nop /* 7 */ + nop /* 8 */ + + /* turn off troublesome PSW bits */ + rsm PSW_Q+PSW_I+PSW_D+PSW_P+PSW_R, %r0 + + /* kernel PSW: + * - no interruptions except HPMC and TOC (which are handled by PDC) + * - Q bit set (IODC / PDC interruptions) + * - big-endian + * - virtually mapped + */ + load32 KERNEL_PSW,%r10 + mtctl %r10,%ipsw + + /* Set the space pointers for the post-RFI world + ** Clear the two-level IIA Space Queue, effectively setting + ** Kernel space. + */ + mtctl %r0,%cr17 + mtctl %r0,%cr17 + + /* Load RFI target into PC queue */ + mtctl %r11,%cr18 + ldo 4(%r11),%r11 + mtctl %r11,%cr18 + + /* Jump to hyperspace */ + rfi + nop + + .procend + + +#ifdef CONFIG_SMP + + .import smp_init_current_idle_task,data + .import smp_callin,code + +/*************************************************************************** +* +* smp_slave_stext is executed by all non-monarch Processors when the Monarch +* pokes the slave CPUs in smp.c:smp_boot_cpus(). +* +* Once here, registers values are initialized in order to branch to virtual +* mode. Once all available/eligible CPUs are in virtual mode, all are +* released and start out by executing their own idle task. +*****************************************************************************/ + + +smp_slave_stext: + .proc + .callinfo + + /* + ** Initialize Space registers + */ + mtsp %r0,%sr4 + mtsp %r0,%sr5 + mtsp %r0,%sr6 + mtsp %r0,%sr7 + + /* Initialize the SP - monarch sets up smp_init_current_idle_task */ + load32 PA(smp_init_current_idle_task),%sp + ldd 0(%sp),%sp /* load task address */ + mtctl %sp,%cr30 /* store in cr30 */ + ldo TASK_SZ_ALGN(%sp),%sp + tophys_r1 %sp + + /* point CPU to kernel page tables */ + load32 PA(swapper_pg_dir),%r4 + mtctl %r4,%cr24 /* Initialize kernel root pointer */ + mtctl %r4,%cr25 /* Initialize user root pointer */ + + /* Setup PDCE_PROC entry */ + copy %arg0,%r3 + + /* Load RFI target address. */ + load32 smp_callin, %r11 + + /* ok...common code can handle the rest */ + b common_stext + nop + + .procend +#endif /* CONFIG_SMP */ + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/head.S linux.19rc3-ac4/arch/parisc/kernel/head.S --- linux.19rc3/arch/parisc/kernel/head.S 2002-07-29 12:50:06.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/head.S 2002-07-29 13:58:36.000000000 +0100 @@ -8,17 +8,14 @@ * Copyright 1999 SuSE GmbH (Philipp Rumpf) * Copyright 1999 Philipp Rumpf (prumpf@tux.org) * - * Initial Version 04-23-1999 by Helge Deller (helge.deller@ruhr-uni-bochum.de) + * Initial Version 04-23-1999 by Helge Deller */ +#include /* for CONFIG_SMP */ #include #include -#define __ASSEMBLY__ -/********* -#include -*********/ #include #include @@ -36,6 +33,15 @@ .export __setup_end __setup_end: + .data + + .export boot_args +boot_args: + .word 0 /* arg0 */ + .word 0 /* arg1 */ + .word 0 /* arg2 */ + .word 0 /* arg3 */ + .text .align 4 .import init_task_union,data @@ -52,43 +58,129 @@ .callinfo /* Make sure sr4-sr7 are set to zero for the kernel address space */ - - mtsp %r0,%sr4 - mtsp %r0,%sr5 - mtsp %r0,%sr6 - mtsp %r0,%sr7 + mtsp %r0,%sr4 + mtsp %r0,%sr5 + mtsp %r0,%sr6 + mtsp %r0,%sr7 + + /* Clear BSS (shouldn't the boot loader do this?) */ + + .import _edata,data + .import _end,data + + ldil L%PA(_edata),%r3 + ldo R%PA(_edata)(%r3),%r3 + ldil L%PA(_end),%r4 + ldo R%PA(_end)(%r4),%r4 +$bss_loop: + cmpb,<<,n %r3,%r4,$bss_loop + stb,ma %r0,1(%r3) + + /* Save away the arguments the boot loader passed in (32 bit args) */ + + ldil L%PA(boot_args),%r1 + ldo R%PA(boot_args)(%r1),%r1 + stw,ma %arg0,4(%r1) + stw,ma %arg1,4(%r1) + stw,ma %arg2,4(%r1) + stw,ma %arg3,4(%r1) /* Initialize startup VM. Just map first 8 MB of memory */ - ldil L%PA(pg0),%r1 ldo R%PA(pg0)(%r1),%r1 ldo _PAGE_TABLE(%r1),%r3 + ldil L%PA(swapper_pg_dir),%r4 ldo R%PA(swapper_pg_dir)(%r4),%r4 mtctl %r4,%cr24 /* Initialize kernel root pointer */ mtctl %r4,%cr25 /* Initialize user root pointer */ - stw %r3,0xc00(%r4) /* Hardwired 0xc0000000 kernel vaddr start */ + +#if (__PAGE_OFFSET != 0x10000000UL) +Error! Code below (the next two stw's) needs to be changed +#endif + + stw %r3,0x100(%r4) /* Hardwired 0x1... kernel Vaddr start*/ ldo 0x1000(%r3),%r3 - stw %r3,0xc04(%r4) - ldo _PAGE_KERNEL(%r0),%r3 /* Hardwired 0x0 phys addr start */ + stw %r3,0x104(%r4) + ldo _PAGE_KERNEL(%r0),%r3 /* Hardwired 0 phys addr start */ $pgt_fill_loop: stwm %r3,4(%r1) ldo 0x1000(%r3),%r3 bb,>= %r3,8,$pgt_fill_loop nop + + /* Load the return address...er...crash 'n burn */ + copy %r0,%r2 + + /* And the RFI Target address too */ + ldil L%start_kernel,%r11 + ldo R%start_kernel(%r11),%r11 + + /* And the initial task pointer */ + + ldil L%init_task_union,%r6 + ldo R%init_task_union(%r6),%r6 + mtctl %r6,%cr30 + + /* And the stack pointer too */ + + ldo TASK_SZ_ALGN(%r6),%sp + + /* And the interrupt stack */ + + ldil L%interrupt_stack,%r6 + ldo R%interrupt_stack(%r6),%r6 + mtctl %r6,%cr31 + +#ifdef CONFIG_SMP + /* Set the smp rendevous address into page zero. + ** It would be safer to do this in init_smp_config() but + ** it's just way easier to deal with here because + ** of 64-bit function ptrs and the address is local to this file. + */ + ldil L%PA(smp_slave_stext),%r10 + ldo R%PA(smp_slave_stext)(%r10),%r10 + stw %r10,0x10(%r0) /* MEM_RENDEZ */ + stw %r0,0x28(%r0) /* MEM_RENDEZ_HI - assume addr < 4GB */ + + /* FALLTHROUGH */ + .procend + + /* + ** Code Common to both Monarch and Slave processors. + ** Entry: + ** %r11 must contain RFI target address. + ** %r25/%r26 args to pass to target function + ** %r2 in case rfi target decides it didn't like something + ** + ** Caller must init: SR4-7, %sp, %r10, %cr24/25, + */ +common_stext: + .proc + .callinfo +#else + /* Clear PDC entry point - we won't use it */ + stw %r0,0x10(%r0) /* MEM_RENDEZ */ + stw %r0,0x28(%r0) /* MEM_RENDEZ_HI */ +#endif + + /* PARANOID: clear user scratch/user space SR's */ + mtsp %r0,%sr0 + mtsp %r0,%sr1 + mtsp %r0,%sr2 + mtsp %r0,%sr3 + + /* Initialize Protection Registers */ + mtctl %r0,%cr8 + mtctl %r0,%cr9 + mtctl %r0,%cr12 + mtctl %r0,%cr13 + /* Initialize the global data pointer */ ldil L%$global$,%dp ldo R%$global$(%dp),%dp - - /* And the stack pointer, physical too */ - ldil L%init_task_union+TASK_SZ_ALGN,%sp - ldo R%init_task_union+TASK_SZ_ALGN(%sp),%sp - - /* we need this to take interruptions directly after the rfi below */ - /* (which we need for PA2.0 boxes) */ - mtctl %r0, %cr30 - + /* * Set up our interrupt table. HPMCs might not work after this! * @@ -96,7 +188,6 @@ * following short sequence of instructions can determine this * (without being illegal on a PA1.1 machine). */ - ldi 32,%r10 mtctl %r10,%cr11 .level 2.0 @@ -114,30 +205,30 @@ $install_iva: mtctl %r10,%cr14 - /* Disable (most) interruptions */ - mtsm %r0 - + /* Disable Q bit so we can load the iia queue */ + rsm PSW_SM_Q,%r0 + /* kernel PSW: - * - no interruptions except for HPMC and TOC (which are handled by PDC) + * - no interruptions except HPMC and TOC (which are handled by PDC) * - Q bit set (IODC / PDC interruptions) * - big-endian * - virtually mapped */ - ldil L%KERNEL_PSW,%r10 ldo R%KERNEL_PSW(%r10),%r10 mtctl %r10,%ipsw - - /* Set the space pointers for the post-RFI world */ - mtctl %r0,%cr17 /* Clear two-level IIA Space Queue */ - mtctl %r0,%cr17 /* effectively setting kernel space. */ - - /* And the return address(es) too */ - ldil L%start_parisc,%r10 - ldo R%start_parisc(%r10),%r10 - mtctl %r10,%cr18 - ldo 4(%r10),%r10 - mtctl %r10,%cr18 + + /* Set the space pointers for the post-RFI world + ** Clear the two-level IIA Space Queue, effectively setting + ** Kernel space. + */ + mtctl %r0,%cr17 + mtctl %r0,%cr17 + + /* Load RFI target into PC queue */ + mtctl %r11,%cr18 + ldo 4(%r11),%r11 + mtctl %r11,%cr18 /* Jump to hyperspace */ rfi @@ -145,6 +236,71 @@ .procend +#ifdef CONFIG_SMP + + .import smp_init_current_idle_task,data + .import smp_callin,code + +smp_callin_rtn: + .proc + .callinfo + break 1,1 /* Break if returned from start_secondary */ + nop + nop + .procend + +/*************************************************************************** +* +* smp_slave_stext is executed by all non-monarch Processors when the Monarch +* pokes the slave CPUs in smp.c:smp_boot_cpus(). +* +* Once here, registers values are initialized in order to branch to virtual +* mode. Once all available/eligible CPUs are in virtual mode, all are +* released and start out by executing their own idle task. +*****************************************************************************/ + + +smp_slave_stext: + .proc + .callinfo + + /* + ** Initialize Space registers + */ + mtsp %r0,%sr4 + mtsp %r0,%sr5 + mtsp %r0,%sr6 + mtsp %r0,%sr7 + + /* Initialize the SP - monarch sets up smp_init_current_idle_task */ + ldil L%PA(smp_init_current_idle_task),%sp + ldo R%PA(smp_init_current_idle_task)(%sp),%sp + ldw 0(%sp),%sp /* load task address */ + mtctl %sp,%cr30 /* store in cr30 */ + addil L%TASK_SZ_ALGN,%sp /* stack is above task */ + ldo R%TASK_SZ_ALGN(%r1),%sp + + /* point CPU to kernel page tables */ + ldil L%PA(swapper_pg_dir),%r4 + ldo R%PA(swapper_pg_dir)(%r4),%r4 + mtctl %r4,%cr24 /* Initialize kernel root pointer */ + mtctl %r4,%cr25 /* Initialize user root pointer */ + + /* Load RFI *return* address in case smp_callin bails */ + ldil L%smp_callin_rtn,%r2 + ldo R%smp_callin_rtn(%r2),%r2 + + /* Load RFI target address. */ + ldil L%smp_callin,%r11 + ldo R%smp_callin(%r11),%r11 + + /* ok...common code can handle the rest */ + b common_stext + nop + + .procend +#endif /* CONFIG_SMP */ + .data .align 4 diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/hpmc.S linux.19rc3-ac4/arch/parisc/kernel/hpmc.S --- linux.19rc3/arch/parisc/kernel/hpmc.S 2002-07-29 12:50:06.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/hpmc.S 2002-07-29 13:58:36.000000000 +0100 @@ -43,7 +43,6 @@ .level 1.1 .data -#define __ASSEMBLY__ #include #include @@ -262,12 +261,10 @@ mtsp %r0, %sr6 mtsp %r0, %sr7 - tovirt %r30 /* make sp virtual */ + tovirt_r1 %r30 /* make sp virtual */ rsm 8,%r0 /* Clear Q bit */ - ldi 1,%r1 - mtctl %r1,%cr29 /* Set trap code to "1" for HPMC */ - mtctl %r0,%cr30 /* Force interruptions to use hpmc stack */ + ldi 1,%r8 /* Set trap code to "1" for HPMC */ ldil L%PA(intr_save), %r1 ldo R%PA(intr_save)(%r1), %r1 be 0(%sr7,%r1) diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/init_task.c linux.19rc3-ac4/arch/parisc/kernel/init_task.c --- linux.19rc3/arch/parisc/kernel/init_task.c 2002-07-29 12:50:06.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/init_task.c 2002-07-29 13:58:36.000000000 +0100 @@ -18,10 +18,11 @@ * way process stacks are handled. This is done by having a special * "init_task" linker map entry.. */ +unsigned char interrupt_stack[ISTACK_SIZE] __attribute__ ((section("init_istack"), aligned(4096))); union task_union init_task_union __attribute__((section("init_task"), aligned(4096))) = { INIT_TASK(init_task_union.task) }; -unsigned long swapper_pg_dir[PTRS_PER_PGD] __attribute__ ((aligned(4096))) = { 0, }; +pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__ ((aligned(4096))) = { {0}, }; #ifdef __LP64__ unsigned long pmd0[PTRS_PER_PMD] __attribute__ ((aligned(4096))) = { 0, }; #endif diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/inventory.c linux.19rc3-ac4/arch/parisc/kernel/inventory.c --- linux.19rc3/arch/parisc/kernel/inventory.c 2002-07-29 12:50:06.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/inventory.c 2002-07-29 13:58:36.000000000 +0100 @@ -1,40 +1,157 @@ - -/* Copyright (c) 1999 The Puffin Group */ -/* Written by David Kennedy and Alex deVries */ +/* + * inventory.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Copyright (c) 1999 The Puffin Group (David Kennedy and Alex deVries) + * Copyright (c) 2001 Matthew Wilcox for Hewlett-Packard + * + * These are the routines to discover what hardware exists in this box. + * This task is complicated by there being 3 different ways of + * performing an inventory, depending largely on the age of the box. + * The recommended way to do this is to check to see whether the machine + * is a `Snake' first, then try System Map, then try PAT. We try System + * Map before checking for a Snake -- this probably doesn't cause any + * problems, but... + */ #include #include +#include +#include +#include #include #include #include +#include +#include /* ** Debug options -** DEBUG_PAT Dump details which PDC PAT provides about ranges/devices. +** DEBUG_PAT Dump details which PDC PAT provides about ranges/devices. */ #undef DEBUG_PAT -extern char *parisc_getHWtype(unsigned short hw_type); +int pdc_type = PDC_TYPE_ILLEGAL; + +void __init setup_pdc(void) +{ + long status; + unsigned int bus_id; + struct pdc_system_map_mod_info module_result; + struct pdc_module_path module_path; + struct pdc_model model; +#ifdef __LP64__ + struct pdc_pat_cell_num cell_info; +#endif -extern struct hp_device * register_module(void *hpa); -extern void print_devices(char * buf); + /* Determine the pdc "type" used on this machine */ + printk(KERN_INFO "Determining PDC firmware type: "); -int pdc_hpa_processor(void *address); + status = pdc_system_map_find_mods(&module_result, &module_path, 0); + if (status == PDC_OK) { + pdc_type = PDC_TYPE_SYSTEM_MAP; + printk("System Map.\n"); + return; + } -#ifndef __LP64__ -static u8 iodc_data[32] __attribute__ ((aligned (64))); -static struct pdc_model model __attribute__ ((aligned (8))); + /* + * If the machine doesn't support PDC_SYSTEM_MAP then either it + * is a pdc pat box, or it is an older box. All 64 bit capable + * machines are either pdc pat boxes or they support PDC_SYSTEM_MAP. + */ + + /* + * TODO: We should test for 64 bit capability and give a + * clearer message. + */ + +#ifdef __LP64__ + status = pdc_pat_cell_get_number(&cell_info); + if (status == PDC_OK) { + pdc_type = PDC_TYPE_PAT; + printk("64 bit PAT.\n"); + return; + } #endif -static unsigned long pdc_result[32] __attribute__ ((aligned (8))) = {0,0,0,0}; -static struct pdc_hpa processor_hpa __attribute__ ((aligned (8))); -static struct pdc_system_map module_result __attribute__ ((aligned (8))); -static struct pdc_module_path module_path __attribute__ ((aligned (8))); + + /* Check the CPU's bus ID. There's probably a better test. */ + + status = pdc_model_info(&model); + + bus_id = (model.hversion >> (4 + 7)) & 0x1f; + + switch (bus_id) { + case 0x4: /* 720, 730, 750, 735, 755 */ + case 0x6: /* 705, 710 */ + case 0x7: /* 715, 725 */ + case 0x8: /* 745, 747, 742 */ + case 0xA: /* 712 and similiar */ + case 0xC: /* 715/64, at least */ + + pdc_type = PDC_TYPE_SNAKE; + printk("Snake.\n"); + return; + + default: /* Everything else */ + + printk("Unsupported.\n"); + panic("If this is a 64-bit machine, please try a 64-bit kernel.\n"); + } +} + +#define PDC_PAGE_ADJ_SHIFT (PAGE_SHIFT - 12) /* pdc pages are always 4k */ + +static void __init +set_pmem_entry(physmem_range_t *pmem_ptr, unsigned long start, + unsigned long pages4k) +{ + /* Rather than aligning and potentially throwing away + * memory, we'll assume that any ranges are already + * nicely aligned with any reasonable page size, and + * panic if they are not (it's more likely that the + * pdc info is bad in this case). + */ + + if ( ((start & (PAGE_SIZE - 1)) != 0) + || ((pages4k & ((1UL << PDC_PAGE_ADJ_SHIFT) - 1)) != 0) ) { + + panic("Memory range doesn't align with page size!\n"); + } + + pmem_ptr->start_pfn = (start >> PAGE_SHIFT); + pmem_ptr->pages = (pages4k >> PDC_PAGE_ADJ_SHIFT); +} + +static void __init pagezero_memconfig(void) +{ + unsigned long npages; + + /* Use the 32 bit information from page zero to create a single + * entry in the pmem_ranges[] table. + * + * We currently don't support machines with contiguous memory + * >= 4 Gb, who report that memory using 64 bit only fields + * on page zero. It's not worth doing until it can be tested, + * and it is not clear we can support those machines for other + * reasons. + * + * If that support is done in the future, this is where it + * should be done. + */ + + npages = (PAGE_ALIGN(PAGE0->imm_max_mem) >> PAGE_SHIFT); + set_pmem_entry(pmem_ranges,0UL,npages); + npmem_ranges = 1; +} #ifdef __LP64__ -#include -int pdc_pat = 0; +/* All of the PDC PAT specific code is 64-bit only */ /* ** The module object is filled via PDC_PAT_CELL[Return Cell Module]. @@ -47,30 +164,37 @@ ** */ -static int -pat_query_module( ulong pcell_loc, ulong mod_index) +static int __init +pat_query_module(ulong pcell_loc, ulong mod_index) { - extern int num_devices; - extern struct hp_device devices[]; - pdc_pat_cell_mod_maddr_block_t pa_pdc_cell; - struct hp_device * dev = &devices[num_devices]; - uint64_t temp; /* 64-bit scratch value */ - long status; /* PDC return value status */ + pdc_pat_cell_mod_maddr_block_t io_pdc_cell; + unsigned long bytecnt; + unsigned long temp; /* 64-bit scratch value */ + long status; /* PDC return value status */ + struct parisc_device *dev; /* return cell module (PA or Processor view) */ - status = pdc_pat_cell_module(& pdc_result, pcell_loc, mod_index, - PA_VIEW, & pa_pdc_cell); + status = pdc_pat_cell_module(&bytecnt, pcell_loc, mod_index, + PA_VIEW, &pa_pdc_cell); - if (status != PDC_RET_OK) { + if (status != PDC_OK) { /* no more cell modules or error */ return status; } + temp = pa_pdc_cell.cba; + dev = alloc_pa_dev(PAT_GET_CBA(temp), &pa_pdc_cell.mod_path); + if (!dev) { + return PDC_NE_MOD; + } + + /* alloc_pa_dev sets dev->hpa */ + /* - ** save parameters in the hp_device + ** save parameters in the parisc_device ** (The idea being the device driver will call pdc_pat_cell_module() - ** and store the results in it's own data structure.) + ** and store the results in its own data structure.) */ dev->pcell_loc = pcell_loc; dev->mod_index = mod_index; @@ -79,319 +203,410 @@ /* REVISIT: who is the consumer of this? not sure yet... */ dev->mod_info = pa_pdc_cell.mod_info; /* pass to PAT_GET_ENTITY() */ dev->pmod_loc = pa_pdc_cell.mod_location; - dev->mod_path = pa_pdc_cell.mod_path; - temp = pa_pdc_cell.cba; - register_module((void *) PAT_GET_CBA(temp)); /* fills in dev->hpa */ + register_parisc_device(dev); /* advertise device */ #ifdef DEBUG_PAT /* dump what we see so far... */ switch (PAT_GET_ENTITY(dev->mod_info)) { - ulong i; + unsigned long i; case PAT_ENTITY_PROC: - printk ("PAT_ENTITY_PROC: id_eid 0x%lx\n", pa_pdc_cell.mod[0]); + printk(KERN_DEBUG "PAT_ENTITY_PROC: id_eid 0x%lx\n", + pa_pdc_cell.mod[0]); break; case PAT_ENTITY_MEM: - printk ("PAT_ENTITY_MEM: amount 0x%lx min_gni_base 0x%lx min_gni_len 0x%lx\n", - pa_pdc_cell.mod[0], - pa_pdc_cell.mod[1], + printk(KERN_DEBUG + "PAT_ENTITY_MEM: amount 0x%lx min_gni_base 0x%lx min_gni_len 0x%lx\n", + pa_pdc_cell.mod[0], pa_pdc_cell.mod[1], pa_pdc_cell.mod[2]); break; case PAT_ENTITY_CA: - printk ("PAT_ENTITY_CA: %ld\n",pcell_loc); + printk(KERN_DEBUG "PAT_ENTITY_CA: %ld\n", pcell_loc); break; case PAT_ENTITY_PBC: - printk ("PAT_ENTITY_PBC: "); + printk(KERN_DEBUG "PAT_ENTITY_PBC: "); goto print_ranges; case PAT_ENTITY_SBA: - printk ("PAT_ENTITY_SBA: "); + printk(KERN_DEBUG "PAT_ENTITY_SBA: "); goto print_ranges; case PAT_ENTITY_LBA: - printk ("PAT_ENTITY_LBA: "); + printk(KERN_DEBUG "PAT_ENTITY_LBA: "); -print_ranges: - printk ("ranges %ld\n", pa_pdc_cell.mod[1]); + print_ranges: + pdc_pat_cell_module(&bytecnt, pcell_loc, mod_index, + IO_VIEW, &io_pdc_cell); + printk(KERN_DEBUG "ranges %ld\n", pa_pdc_cell.mod[1]); for (i = 0; i < pa_pdc_cell.mod[1]; i++) { - printk (" %ld: 0x%016lx 0x%016lx 0x%016lx\n", i, - pa_pdc_cell.mod[2+i*3], /* type */ - pa_pdc_cell.mod[3+i*3], /* start */ - pa_pdc_cell.mod[4+i*3]); /* finish (ie end) */ + printk(KERN_DEBUG + " PA_VIEW %ld: 0x%016lx 0x%016lx 0x%016lx\n", + i, pa_pdc_cell.mod[2 + i * 3], /* type */ + pa_pdc_cell.mod[3 + i * 3], /* start */ + pa_pdc_cell.mod[4 + i * 3]); /* finish (ie end) */ + printk(KERN_DEBUG + " IO_VIEW %ld: 0x%016lx 0x%016lx 0x%016lx\n", + i, io_pdc_cell.mod[2 + i * 3], /* type */ + io_pdc_cell.mod[3 + i * 3], /* start */ + io_pdc_cell.mod[4 + i * 3]); /* finish (ie end) */ } - printk("\n"); + printk(KERN_DEBUG "\n"); break; } #endif /* DEBUG_PAT */ - return PDC_RET_OK; + return PDC_OK; } -static int do_pat_inventory(void) -{ - ulong mod_index=0; - int status; - ulong cell_num; - ulong pcell_loc; +/* pat pdc can return information about a variety of different + * types of memory (e.g. firmware,i/o, etc) but we only care about + * the usable physical ram right now. Since the firmware specific + * information is allocated on the stack, we'll be generous, in + * case there is a lot of other information we don't care about. + */ - pdc_pat = (pdc_pat_cell_get_number(&pdc_result) == PDC_OK); - if (!pdc_pat) - { - return 0; - } - - cell_num = pdc_result[0]; /* Cell number call was made */ - - /* As of PDC PAT ARS 2.5, ret[1] is NOT architected! */ - pcell_loc = pdc_result[1]; /* Physical location of the cell */ - -#ifdef DEBUG_PAT - printk("CELL_GET_NUMBER: 0x%lx 0x%lx\n", cell_num, pcell_loc); -#endif - - status = pdc_pat_cell_num_to_loc(&pdc_result, cell_num); - if (status == PDC_BAD_OPTION) - { - /* Prelude (and it's successors: Lclass, A400/500) only - ** implement PDC_PAT_CELL sub-options 0 and 2. - ** "Home cook'n is best anyhow!" - */ - } else if (PDC_OK == status) { - /* so far only Halfdome supports this */ - pcell_loc = pdc_result[0]; - } else { - panic("WTF? CELL_GET_NUMBER give me invalid cell number?"); - } - - while (PDC_RET_OK == pat_query_module(pcell_loc, mod_index)) - { - mod_index++; - } - - return mod_index; -} -#endif /* __LP64__ */ +#define PAT_MAX_RANGES (4 * MAX_PHYSMEM_RANGES) -static int do_newer_workstation_inventory(void) +static void __init pat_memconfig(void) { + unsigned long actual_len; + struct pdc_pat_pd_addr_map_entry mem_table[PAT_MAX_RANGES+1]; + struct pdc_pat_pd_addr_map_entry *mtbl_ptr; + physmem_range_t *pmem_ptr; long status; - int i, num = 0; + int entries; + unsigned long length; + int i; + + length = (PAT_MAX_RANGES + 1) * sizeof(struct pdc_pat_pd_addr_map_entry); + + status = pdc_pat_pd_get_addr_map(&actual_len, mem_table, length, 0L); + + if ((status != PDC_OK) + || ((actual_len % sizeof(struct pdc_pat_pd_addr_map_entry)) != 0)) { + + /* The above pdc call shouldn't fail, but, just in + * case, just use the PAGE0 info. + */ + + printk("\n\n\n"); + printk(KERN_WARNING "WARNING! Could not get full memory configuration. " + "All memory may not be used!\n\n\n"); + pagezero_memconfig(); + return; + } - /* So the idea here is to simply try one SYSTEM_MAP call. If - that one works, great, otherwise do it another way */ + entries = actual_len / sizeof(struct pdc_pat_pd_addr_map_entry); - status = pdc_system_map_find_mods(&module_result,&module_path,0); + if (entries > PAT_MAX_RANGES) { + printk(KERN_WARNING "This Machine has more memory ranges than we support!\n"); + printk(KERN_WARNING "Some memory may not be used!\n"); + } - if (status == PDC_RET_OK) { - /* This is for newer non-PDC-PAT boxes */ + /* Copy information into the firmware independent pmem_ranges + * array, skipping types we don't care about. Notice we said + * "may" above. We'll use all the entries that were returned. + */ + + npmem_ranges = 0; + mtbl_ptr = mem_table; + pmem_ptr = pmem_ranges; /* Global firmware independent table */ + for (i = 0; i < entries; i++,mtbl_ptr++) { + if ( (mtbl_ptr->entry_type != PAT_MEMORY_DESCRIPTOR) + || (mtbl_ptr->memory_type != PAT_MEMTYPE_MEMORY) + || (mtbl_ptr->pages == 0) + || ( (mtbl_ptr->memory_usage != PAT_MEMUSE_GENERAL) + && (mtbl_ptr->memory_usage != PAT_MEMUSE_GI) + && (mtbl_ptr->memory_usage != PAT_MEMUSE_GNI) ) ) { - printk("a newer box...\n"); - for(i=0, status=PDC_RET_OK; status != PDC_RET_NE_PROC && - status != PDC_RET_NE_MOD ;i++) { + continue; + } - status = pdc_system_map_find_mods(&module_result,&module_path,i); - if (status == PDC_RET_OK) { - num++; - register_module(module_result.mod_addr); - } + if (npmem_ranges == MAX_PHYSMEM_RANGES) { + printk(KERN_WARNING "This Machine has more memory ranges than we support!\n"); + printk(KERN_WARNING "Some memory will not be used!\n"); + break; } - } - return (num > 0); + set_pmem_entry(pmem_ptr++,mtbl_ptr->paddr,mtbl_ptr->pages); + npmem_ranges++; + } } -#ifndef __LP64__ -static struct pdc_memory_map r_addr __attribute__ ((aligned (8))); - -static int really_do_oldhw_inventory(void) +static int __init pat_inventory(void) { - int i, mod, num = 0; int status; - unsigned int hw_type; - unsigned int func; + ulong mod_index = 0; + struct pdc_pat_cell_num cell_info; - /* This is undocumented at the time of writing, but basically - we're setting up mod_path so that bc[0..4]=0xff, and step - through mod to get the "Path Structure for GSC Modules". If - it works, use the returned HPA and determine the hardware type. */ + /* + ** Note: Prelude (and it's successors: Lclass, A400/500) only + ** implement PDC_PAT_CELL sub-options 0 and 2. + */ + status = pdc_pat_cell_get_number(&cell_info); + if (status != PDC_OK) { + return 0; + } - for (i=0;i<6;i++) module_path.bc[i]=0xff; +#ifdef DEBUG_PAT + printk(KERN_DEBUG "CELL_GET_NUMBER: 0x%lx 0x%lx\n", cell_info.cell_num, + cell_info.cell_loc); +#endif - for (mod=0;mod<16;mod++) { - char *stype = NULL; + while (PDC_OK == pat_query_module(cell_info.cell_loc, mod_index)) { + mod_index++; + } - module_path.mod=mod; - status = pdc_mem_map_hpa(&r_addr, &module_path); - if (status!=PDC_RET_OK) continue; - - status = pdc_iodc_read(&pdc_result,(void *) r_addr.hpa, - 0, &iodc_data,32 ); - if (status!=PDC_RET_OK) continue; - hw_type = iodc_data[3]&0x1f; + return mod_index; +} - switch (hw_type) - { - case HPHW_NPROC: /* 0 */ - stype="Processor"; break; +/* We only look for extended memory ranges on a 64 bit capable box */ +static void __init sprockets_memconfig(void) +{ + struct pdc_memory_table_raddr r_addr; + struct pdc_memory_table mem_table[MAX_PHYSMEM_RANGES]; + struct pdc_memory_table *mtbl_ptr; + physmem_range_t *pmem_ptr; + long status; + int entries; + int i; - case HPHW_MEMORY: /* 1 */ - stype="Memory"; break; + status = pdc_mem_mem_table(&r_addr,mem_table, + (unsigned long)MAX_PHYSMEM_RANGES); - case HPHW_B_DMA: /* 2 */ - stype="Type B DMA"; break; + if (status != PDC_OK) { - case HPHW_A_DMA: /* 4 */ - stype="Type A DMA"; break; + /* The above pdc call only works on boxes with sprockets + * firmware (newer B,C,J class). Other non PAT PDC machines + * do support more than 3.75 Gb of memory, but we don't + * support them yet. + */ - case HPHW_A_DIRECT: /* 5 */ - stype="Type A Direct"; break; + pagezero_memconfig(); + return; + } + + if (r_addr.entries_total > MAX_PHYSMEM_RANGES) { + printk(KERN_WARNING "This Machine has more memory ranges than we support!\n"); + printk(KERN_WARNING "Some memory will not be used!\n"); + } - case HPHW_BCPORT: /* 7 */ - stype="Bus Converter Port"; break; + entries = (int)r_addr.entries_returned; - case HPHW_CONSOLE: /* 9 */ - stype="Console"; break; + npmem_ranges = 0; + mtbl_ptr = mem_table; + pmem_ptr = pmem_ranges; /* Global firmware independent table */ + for (i = 0; i < entries; i++,mtbl_ptr++) { + set_pmem_entry(pmem_ptr++,mtbl_ptr->paddr,mtbl_ptr->pages); + npmem_ranges++; + } +} - case HPHW_FIO: /* 10 - Graphics */ - stype="Foreign I/O (Graphics)"; break; +#else /* !__LP64__ */ - case HPHW_BA: /* 11 - Bus Adapter */ - stype="Bus Adapter"; break; +#define pat_inventory() do { } while (0) +#define pat_memconfig() do { } while (0) +#define sprockets_memconfig() pagezero_memconfig() - case HPHW_IOA: /* 12 */ - stype="I/O Adapter"; break; +#endif /* !__LP64__ */ - case HPHW_BRIDGE: /* 13 */ - stype="Bridge"; break; - case HPHW_FABRIC: /* 14 */ - stype="Fabric"; break; +#ifndef CONFIG_PA20 - case HPHW_FAULTY: /* 31 */ - stype="Faulty HW"; break; +/* Code to support Snake machines (7[2350], 7[235]5, 715/Scorpio) */ - case HPHW_OTHER: /* 42 */ - default: - printk("Don't know this hw_type: %d\n", hw_type); - break; - } +static struct parisc_device * __init +legacy_create_device(struct pdc_memory_map *r_addr, + struct pdc_module_path *module_path) +{ + struct parisc_device *dev; + int status = pdc_mem_map_hpa(r_addr, module_path); + if (status != PDC_OK) + return NULL; + + dev = alloc_pa_dev(r_addr->hpa, &module_path->path); + if (dev == NULL) + return NULL; - // This is kluged. But don't want to replicate code for - // most of the above cases. - if (stype) { -#ifdef DBG_PDC_QUERY - // parisc/kernel/drivers.c - extern int num_devices; - extern struct hp_device devices[]; - struct hp_hardware *h; -#endif + register_parisc_device(dev); + return dev; +} - status = pdc_mem_map_hpa(&r_addr, &module_path); - if (status==PDC_RET_OK && register_module((void *) r_addr.hpa) != NULL) - num++; - - - if (hw_type == HPHW_BA) { - /* Now, we're checking for devices for each - module. I seem to think that the - modules in question are Lasi (2), 2nd Lasi (6) - Wax (5). To do this, set bc[5]=0, and set - bc[4] to the module, and step through the - functions. */ - - for (i=0;i<4;i++) module_path.bc[i]=0xff; - module_path.bc[4]=mod; - for (func=0;func<16;func++) { - module_path.mod = func; - module_path.bc[5]=0; - status = pdc_mem_map_hpa(&r_addr, &module_path); - if (status!=PDC_RET_OK) continue; - if (register_module((void *) r_addr.hpa) != NULL) - num++; - } +/** + * snake_inventory + * + * Before PDC_SYSTEM_MAP was invented, the PDC_MEM_MAP call was used. + * To use it, we initialise the mod_path.bc to 0xff and try all values of + * mod to get the HPA for the top-level devices. Bus adapters may have + * sub-devices which are discovered by setting bc[5] to 0 and bc[4] to the + * module, then trying all possible functions. + */ +static void __init snake_inventory(void) +{ + int mod; + for (mod = 0; mod < 16; mod++) { + struct parisc_device *dev; + struct pdc_module_path module_path; + struct pdc_memory_map r_addr; + unsigned int func; + + memset(module_path.path.bc, 0xff, 6); + module_path.path.mod = mod; + dev = legacy_create_device(&r_addr, &module_path); + if ((!dev) || (dev->id.hw_type != HPHW_BA)) + continue; + + memset(module_path.path.bc, 0xff, 4); + module_path.path.bc[4] = mod; + + for (func = 0; func < 16; func++) { + module_path.path.bc[5] = 0; + module_path.path.mod = func; + legacy_create_device(&r_addr, &module_path); } - // reset module_path.bc[] - for (i=0;i<6;i++) module_path.bc[i]=0xff; + } +} +#else /* CONFIG_PA20 */ +#define snake_inventory() do { } while (0) +#endif /* CONFIG_PA20 */ + +/* Common 32/64 bit based code goes here */ + +/** + * add_system_map_addresses - Add additional addresses to the parisc device. + * @dev: The parisc device. + * @num_addrs: Then number of addresses to add; + * @module_instance: The system_map module instance. + * + * This function adds any additional addresses reported by the system_map + * firmware to the parisc device. + */ +static void __init +add_system_map_addresses(struct parisc_device *dev, int num_addrs, + int module_instance) +{ + int i; + long status; + struct pdc_system_map_addr_info addr_result; -#ifdef DBG_PDC_QUERY -// -// Let print_devices() dump everything which is registered. -// - h = devices[num_devices-1].reference; + dev->addr = kmalloc(num_addrs * sizeof(unsigned long), GFP_KERNEL); + if(!dev->addr) { + printk(KERN_ERR "%s %s(): memory allocation failure\n", + __FILE__, __FUNCTION__); + return; + } - if (h) stype = h->name; - printk("Found %s at %d\n", stype, module_path.mod); -#endif + for(i = 1; i <= num_addrs; ++i) { + status = pdc_system_map_find_addrs(&addr_result, + module_instance, i); + if(PDC_OK == status) { + dev->addr[dev->num_addrs] = (unsigned long)addr_result.mod_addr; + dev->num_addrs++; + } else { + printk(KERN_WARNING + "Bad PDC_FIND_ADDRESS status return (%ld) for index %d\n", + status, i); } } - return num; } -static int -do_old_inventory(void) +/** + * do_system_map_inventory - Retrieve firmware devices via SYSTEM_MAP. + * + * This function attempts to retrieve and register all the devices firmware + * knows about via the SYSTEM_MAP PDC call. + */ +static void __init system_map_inventory(void) { - unsigned int bus_id; - long status; - int ok = 0; - - printk(" an older box...\n"); + int i; + long status = PDC_OK; + + /* + * first stop the usb controller, otherwise the machine + * might crash during iommu setup + */ + pdc_suspend_usb(); + + for (i = 0; status != PDC_BAD_PROC && status != PDC_NE_MOD; i++) { + struct parisc_device *dev; + struct pdc_system_map_mod_info module_result; + struct pdc_module_path module_path; + + status = pdc_system_map_find_mods(&module_result, + &module_path, i); + if (status != PDC_OK) + continue; + + dev = alloc_pa_dev(module_result.mod_addr, &module_path.path); + if (!dev) + continue; + + register_parisc_device(dev); + + /* if available, get the additional addresses for a module */ + if (!module_result.add_addrs) + continue; - /* Here, we're going to check the model, and decide - if we should even bother trying. */ + add_system_map_addresses(dev, module_result.add_addrs, i); + } - status = pdc_model_info(&model); + walk_central_bus(); + return; +} - bus_id = (model.hversion >> (4+7) ) &0x1f; +void __init do_memory_inventory(void) +{ + switch (pdc_type) { - /* Here, we're checking the HVERSION of the CPU. - We're only checking the 0th CPU, since it'll - be the same on an SMP box. */ + case PDC_TYPE_PAT: + pat_memconfig(); + break; - switch (bus_id) { - case 0x4: /* 720, 730, 750, 735, 755 */ - case 0x6: /* 705, 710 */ - case 0x7: /* 715, 725 */ - case 0x8: /* 745, 747, 742 */ - case 0xA: /* 712 and similiar */ - case 0xC: /* 715/64, at least */ - - /* Do inventory using MEM_MAP */ - really_do_oldhw_inventory(); - ok = 1; + case PDC_TYPE_SYSTEM_MAP: + sprockets_memconfig(); break; - default: /* Everything else */ - printk("This is a very very old machine, with a bus_id of 0x%x.\n",bus_id); - panic("This will probably never run Linux.\n"); + + case PDC_TYPE_SNAKE: + pagezero_memconfig(); + return; + + default: + panic("Unknown PDC type!\n"); } - return ok; + if (npmem_ranges == 0 || pmem_ranges[0].start_pfn != 0) { + printk(KERN_WARNING "Bad memory configuration returned!\n"); + printk(KERN_WARNING "Some memory may not be used!\n"); + pagezero_memconfig(); + } } -#endif /* !__LP64__ */ +void __init do_device_inventory(void) +{ + printk(KERN_INFO "Searching for devices...\n"); -void do_inventory(void){ - if((pdc_hpa_processor(&processor_hpa))<0){ - printk(KERN_INFO "Couldn't get the HPA of the processor.\n" ); - } + switch (pdc_type) { + + case PDC_TYPE_PAT: + pat_inventory(); + break; - printk("Searching for devices in PDC firmware... "); - printk("processor hpa 0x%lx\n", processor_hpa.hpa); + case PDC_TYPE_SYSTEM_MAP: + system_map_inventory(); + break; - if (!( - do_newer_workstation_inventory() -#ifdef __LP64__ - || do_pat_inventory() -#else /* __LP64__ */ - || do_old_inventory() -#endif /* __LP64__ */ - )) - { - panic("I can't get the hardware inventory on this machine"); + case PDC_TYPE_SNAKE: + snake_inventory(); + break; + + default: + panic("Unknown PDC type!\n"); } - print_devices(NULL); -} + printk(KERN_INFO "Found devices:\n"); + print_parisc_devices(); +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/ioctl32.c linux.19rc3-ac4/arch/parisc/kernel/ioctl32.c --- linux.19rc3/arch/parisc/kernel/ioctl32.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/ioctl32.c 2002-07-29 13:58:36.000000000 +0100 @@ -0,0 +1,3758 @@ +/* $Id: ioctl32.c,v 1.12 2002/07/08 20:52:15 grundler Exp $ + * ioctl32.c: Conversion between 32bit and 64bit native ioctls. + * + * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) + * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) + * + * These routines maintain argument size conversion between 32bit and 64bit + * ioctls. + */ + +#include +#include +#include "sys32.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE) +/* Ugh. This header really is not clean */ +/* #define min min +#define max max */ +#include +#endif /* LVM */ + +#include +/* Ugly hack. */ +#undef __KERNEL__ +#include +#define __KERNEL__ +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include /* get #define module_map() */ + +/* Use this to get at 32-bit user passed pointers. + See sys_sparc32.c for description about these. */ +#define A(__x) ((unsigned long)(__x)) + +/* Aiee. Someone does not find a difference between int and long */ +#define EXT2_IOC32_GETFLAGS _IOR('f', 1, int) +#define EXT2_IOC32_SETFLAGS _IOW('f', 2, int) +#define EXT2_IOC32_GETVERSION _IOR('v', 1, int) +#define EXT2_IOC32_SETVERSION _IOW('v', 2, int) + +extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); + +static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + mm_segment_t old_fs = get_fs(); + int err; + unsigned long val; + + set_fs (KERNEL_DS); + err = sys_ioctl(fd, cmd, (unsigned long)&val); + set_fs (old_fs); + if (!err && put_user(val, (u32 *)arg)) + return -EFAULT; + return err; +} + +static int rw_long(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + mm_segment_t old_fs = get_fs(); + int err; + unsigned long val; + + if(get_user(val, (u32 *)arg)) + return -EFAULT; + set_fs (KERNEL_DS); + err = sys_ioctl(fd, cmd, (unsigned long)&val); + set_fs (old_fs); + if (!err && put_user(val, (u32 *)arg)) + return -EFAULT; + return err; +} + +static int siocprivate(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + int err = sys_ioctl(fd, cmd, arg); + if ((unsigned) err > -4095) + printk(KERN_WARNING + "ioctl(%d, 0x%x, %p) -- SIOCDEVPRIVATE-based ioctls aren't really\n" + "supported, though some will work by accident.\n", + fd, cmd, (void *)arg); + return err; +} + +static int do_ext2_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + /* These are just misnamed, they actually get/put from/to user an int */ + switch (cmd) { + case EXT2_IOC32_GETFLAGS: cmd = EXT2_IOC_GETFLAGS; break; + case EXT2_IOC32_SETFLAGS: cmd = EXT2_IOC_SETFLAGS; break; + case EXT2_IOC32_GETVERSION: cmd = EXT2_IOC_GETVERSION; break; + case EXT2_IOC32_SETVERSION: cmd = EXT2_IOC_SETVERSION; break; + } + return sys_ioctl(fd, cmd, arg); +} + +static int do_siocgstamp(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct timeval32 *up = (struct timeval32 *)arg; + struct timeval ktv; + mm_segment_t old_fs = get_fs(); + int err; + + set_fs(KERNEL_DS); + err = sys_ioctl(fd, cmd, (unsigned long)&ktv); + set_fs(old_fs); + if(!err) { + err = put_user(ktv.tv_sec, &up->tv_sec); + err |= __put_user(ktv.tv_usec, &up->tv_usec); + } + return err; +} + +struct ifmap32 { + u32 mem_start; + u32 mem_end; + unsigned short base_addr; + unsigned char irq; + unsigned char dma; + unsigned char port; +}; + +struct ifreq32 { +#define IFHWADDRLEN 6 +#define IFNAMSIZ 16 + union { + char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */ + } ifr_ifrn; + union { + struct sockaddr ifru_addr; + struct sockaddr ifru_dstaddr; + struct sockaddr ifru_broadaddr; + struct sockaddr ifru_netmask; + struct sockaddr ifru_hwaddr; + short ifru_flags; + int ifru_ivalue; + int ifru_mtu; + struct ifmap32 ifru_map; + char ifru_slave[IFNAMSIZ]; /* Just fits the size */ + char ifru_newname[IFNAMSIZ]; + __kernel_caddr_t32 ifru_data; + } ifr_ifru; +}; + +struct ifconf32 { + int ifc_len; /* size of buffer */ + __kernel_caddr_t32 ifcbuf; +}; + +static int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct net_device *dev; + struct ifreq32 ifr32; + int err; + + if (copy_from_user(&ifr32, (struct ifreq32 *)arg, sizeof(struct ifreq32))) + return -EFAULT; + + dev = dev_get_by_index(ifr32.ifr_ifindex); + if (!dev) + return -ENODEV; + + strcpy(ifr32.ifr_name, dev->name); + + err = copy_to_user((struct ifreq32 *)arg, &ifr32, sizeof(struct ifreq32)); + return (err ? -EFAULT : 0); +} + +static inline int dev_ifconf(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct ifconf32 ifc32; + struct ifconf ifc; + struct ifreq32 *ifr32; + struct ifreq *ifr; + mm_segment_t old_fs; + unsigned int i, j; + int err; + + if (copy_from_user(&ifc32, (struct ifconf32 *)arg, sizeof(struct ifconf32))) + return -EFAULT; + + if(ifc32.ifcbuf == 0) { + ifc32.ifc_len = 0; + ifc.ifc_len = 0; + ifc.ifc_buf = NULL; + } else { + ifc.ifc_len = ((ifc32.ifc_len / sizeof (struct ifreq32)) + 1) * + sizeof (struct ifreq); + ifc.ifc_buf = kmalloc (ifc.ifc_len, GFP_KERNEL); + if (!ifc.ifc_buf) + return -ENOMEM; + } + ifr = ifc.ifc_req; + ifr32 = (struct ifreq32 *)A(ifc32.ifcbuf); + for (i = 0; i < ifc32.ifc_len; i += sizeof (struct ifreq32)) { + if (copy_from_user(ifr++, ifr32++, sizeof (struct ifreq32))) { + kfree (ifc.ifc_buf); + return -EFAULT; + } + } + old_fs = get_fs(); set_fs (KERNEL_DS); + err = sys_ioctl (fd, SIOCGIFCONF, (unsigned long)&ifc); + set_fs (old_fs); + if (!err) { + ifr = ifc.ifc_req; + ifr32 = (struct ifreq32 *)A(ifc32.ifcbuf); + for (i = 0, j = 0; i < ifc32.ifc_len && j < ifc.ifc_len; + i += sizeof (struct ifreq32), j += sizeof (struct ifreq)) { + if (copy_to_user(ifr32++, ifr++, sizeof (struct ifreq32))) { + err = -EFAULT; + break; + } + } + if (!err) { + if (i <= ifc32.ifc_len) + ifc32.ifc_len = i; + else + ifc32.ifc_len = i - sizeof (struct ifreq32); + if (copy_to_user((struct ifconf32 *)arg, &ifc32, sizeof(struct ifconf32))) + err = -EFAULT; + } + } + if(ifc.ifc_buf != NULL) + kfree (ifc.ifc_buf); + return err; +} + +static int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct ifreq ifr; + mm_segment_t old_fs; + int err; + + switch (cmd) { + case SIOCSIFMAP: + err = copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(ifr.ifr_name)); + err |= __get_user(ifr.ifr_map.mem_start, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_start)); + err |= __get_user(ifr.ifr_map.mem_end, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_end)); + err |= __get_user(ifr.ifr_map.base_addr, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.base_addr)); + err |= __get_user(ifr.ifr_map.irq, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.irq)); + err |= __get_user(ifr.ifr_map.dma, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.dma)); + err |= __get_user(ifr.ifr_map.port, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.port)); + if (err) + return -EFAULT; + break; + case SIOCGPPPSTATS: + case SIOCGPPPCSTATS: + case SIOCGPPPVER: + case SIOCETHTOOL: + if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32))) + return -EFAULT; + ifr.ifr_data = (__kernel_caddr_t)get_free_page(GFP_KERNEL); + if (!ifr.ifr_data) + return -EAGAIN; + if(cmd == SIOCETHTOOL) { + u32 data; + + __get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data)); + if(copy_from_user(ifr.ifr_data, + (char *)A(data), + sizeof(struct ethtool_cmd))) { + free_page((unsigned long)ifr.ifr_data); + return -EFAULT; + } + } + break; + default: + if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32))) + return -EFAULT; + break; + } + old_fs = get_fs(); + set_fs (KERNEL_DS); + err = sys_ioctl (fd, cmd, (unsigned long)&ifr); + set_fs (old_fs); + if (!err) { + switch (cmd) { + case SIOCGIFFLAGS: + case SIOCGIFMETRIC: + case SIOCGIFMTU: + case SIOCGIFMEM: + case SIOCGIFHWADDR: + case SIOCGIFINDEX: + case SIOCGIFADDR: + case SIOCGIFBRDADDR: + case SIOCGIFDSTADDR: + case SIOCGIFNETMASK: + case SIOCGIFTXQLEN: + if (copy_to_user((struct ifreq32 *)arg, &ifr, sizeof(struct ifreq32))) + return -EFAULT; + break; + case SIOCGPPPSTATS: + case SIOCGPPPCSTATS: + case SIOCGPPPVER: + case SIOCETHTOOL: + { + u32 data; + int len; + + __get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data)); + if(cmd == SIOCETHTOOL) + len = sizeof(struct ethtool_cmd); + if(cmd == SIOCGPPPVER) + len = strlen((char *)ifr.ifr_data) + 1; + else if(cmd == SIOCGPPPCSTATS) + len = sizeof(struct ppp_comp_stats); + else + len = sizeof(struct ppp_stats); + + len = copy_to_user((char *)A(data), ifr.ifr_data, len); + free_page((unsigned long)ifr.ifr_data); + if(len) + return -EFAULT; + break; + } + case SIOCGIFMAP: + err = copy_to_user((struct ifreq32 *)arg, &ifr, sizeof(ifr.ifr_name)); + err |= __put_user(ifr.ifr_map.mem_start, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_start)); + err |= __put_user(ifr.ifr_map.mem_end, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_end)); + err |= __put_user(ifr.ifr_map.base_addr, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.base_addr)); + err |= __put_user(ifr.ifr_map.irq, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.irq)); + err |= __put_user(ifr.ifr_map.dma, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.dma)); + err |= __put_user(ifr.ifr_map.port, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.port)); + if (err) + err = -EFAULT; + break; + } + } + return err; +} + +struct rtentry32 { + u32 rt_pad1; + struct sockaddr rt_dst; /* target address */ + struct sockaddr rt_gateway; /* gateway addr (RTF_GATEWAY) */ + struct sockaddr rt_genmask; /* target network mask (IP) */ + unsigned short rt_flags; + short rt_pad2; + u32 rt_pad3; + unsigned char rt_tos; + unsigned char rt_class; + short rt_pad4; + short rt_metric; /* +1 for binary compatibility! */ + /* char * */ u32 rt_dev; /* forcing the device at add */ + u32 rt_mtu; /* per route MTU/Window */ + u32 rt_window; /* Window clamping */ + unsigned short rt_irtt; /* Initial RTT */ + +}; + +static inline int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct rtentry r; + char devname[16]; + u32 rtdev; + int ret; + mm_segment_t old_fs = get_fs(); + + ret = copy_from_user (&r.rt_dst, &(((struct rtentry32 *)arg)->rt_dst), 3 * sizeof(struct sockaddr)); + ret |= __get_user (r.rt_flags, &(((struct rtentry32 *)arg)->rt_flags)); + ret |= __get_user (r.rt_metric, &(((struct rtentry32 *)arg)->rt_metric)); + ret |= __get_user (r.rt_mtu, &(((struct rtentry32 *)arg)->rt_mtu)); + ret |= __get_user (r.rt_window, &(((struct rtentry32 *)arg)->rt_window)); + ret |= __get_user (r.rt_irtt, &(((struct rtentry32 *)arg)->rt_irtt)); + ret |= __get_user (rtdev, &(((struct rtentry32 *)arg)->rt_dev)); + if (rtdev) { + ret |= copy_from_user (devname, (char *)A(rtdev), 15); + r.rt_dev = devname; devname[15] = 0; + } else + r.rt_dev = 0; + if (ret) + return -EFAULT; + set_fs (KERNEL_DS); + ret = sys_ioctl (fd, cmd, (long)&r); + set_fs (old_fs); + return ret; +} + +struct hd_geometry32 { + unsigned char heads; + unsigned char sectors; + unsigned short cylinders; + u32 start; +}; + +static inline int hdio_getgeo(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + mm_segment_t old_fs = get_fs(); + struct hd_geometry geo; + int err; + + set_fs (KERNEL_DS); + err = sys_ioctl(fd, HDIO_GETGEO, (unsigned long)&geo); + set_fs (old_fs); + if (!err) { + err = copy_to_user ((struct hd_geometry32 *)arg, &geo, 4); + err |= __put_user (geo.start, &(((struct hd_geometry32 *)arg)->start)); + } + return err ? -EFAULT : 0; +} + + +#if 0 +/* looks like SPARC only - eg sbus video */ +struct fbcmap32 { + int index; /* first element (0 origin) */ + int count; + u32 red; + u32 green; + u32 blue; +}; + + +static inline int fbiogetputcmap(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct fbcmap f; + int ret; + char red[256], green[256], blue[256]; + u32 r, g, b; + mm_segment_t old_fs = get_fs(); + + ret = get_user(f.index, &(((struct fbcmap32 *)arg)->index)); + ret |= __get_user(f.count, &(((struct fbcmap32 *)arg)->count)); + ret |= __get_user(r, &(((struct fbcmap32 *)arg)->red)); + ret |= __get_user(g, &(((struct fbcmap32 *)arg)->green)); + ret |= __get_user(b, &(((struct fbcmap32 *)arg)->blue)); + if (ret) + return -EFAULT; + if ((f.index < 0) || (f.index > 255)) return -EINVAL; + if (f.index + f.count > 256) + f.count = 256 - f.index; + if (cmd == FBIOPUTCMAP32) { + ret = copy_from_user (red, (char *)A(r), f.count); + ret |= copy_from_user (green, (char *)A(g), f.count); + ret |= copy_from_user (blue, (char *)A(b), f.count); + if (ret) + return -EFAULT; + } + f.red = red; f.green = green; f.blue = blue; + set_fs (KERNEL_DS); + ret = sys_ioctl (fd, (cmd == FBIOPUTCMAP32) ? FBIOPUTCMAP_SPARC : FBIOGETCMAP_SPARC, (long)&f); + set_fs (old_fs); + if (!ret && cmd == FBIOGETCMAP32) { + ret = copy_to_user ((char *)A(r), red, f.count); + ret |= copy_to_user ((char *)A(g), green, f.count); + ret |= copy_to_user ((char *)A(b), blue, f.count); + } + return ret ? -EFAULT : 0; +} + +struct fbcursor32 { + short set; /* what to set, choose from the list above */ + short enable; /* cursor on/off */ + struct fbcurpos pos; /* cursor position */ + struct fbcurpos hot; /* cursor hot spot */ + struct fbcmap32 cmap; /* color map info */ + struct fbcurpos size; /* cursor bit map size */ + u32 image; /* cursor image bits */ + u32 mask; /* cursor mask bits */ +}; + +static inline int fbiogscursor(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct fbcursor f; + int ret; + char red[2], green[2], blue[2]; + char image[128], mask[128]; + u32 r, g, b; + u32 m, i; + mm_segment_t old_fs = get_fs(); + + ret = copy_from_user (&f, (struct fbcursor32 *)arg, 2 * sizeof (short) + 2 * sizeof(struct fbcurpos)); + ret |= __get_user(f.size.fbx, &(((struct fbcursor32 *)arg)->size.fbx)); + ret |= __get_user(f.size.fby, &(((struct fbcursor32 *)arg)->size.fby)); + ret |= __get_user(f.cmap.index, &(((struct fbcursor32 *)arg)->cmap.index)); + ret |= __get_user(f.cmap.count, &(((struct fbcursor32 *)arg)->cmap.count)); + ret |= __get_user(r, &(((struct fbcursor32 *)arg)->cmap.red)); + ret |= __get_user(g, &(((struct fbcursor32 *)arg)->cmap.green)); + ret |= __get_user(b, &(((struct fbcursor32 *)arg)->cmap.blue)); + ret |= __get_user(m, &(((struct fbcursor32 *)arg)->mask)); + ret |= __get_user(i, &(((struct fbcursor32 *)arg)->image)); + if (ret) + return -EFAULT; + if (f.set & FB_CUR_SETCMAP) { + if ((uint) f.size.fby > 32) + return -EINVAL; + ret = copy_from_user (mask, (char *)A(m), f.size.fby * 4); + ret |= copy_from_user (image, (char *)A(i), f.size.fby * 4); + if (ret) + return -EFAULT; + f.image = image; f.mask = mask; + } + if (f.set & FB_CUR_SETCMAP) { + ret = copy_from_user (red, (char *)A(r), 2); + ret |= copy_from_user (green, (char *)A(g), 2); + ret |= copy_from_user (blue, (char *)A(b), 2); + if (ret) + return -EFAULT; + f.cmap.red = red; f.cmap.green = green; f.cmap.blue = blue; + } + set_fs (KERNEL_DS); + ret = sys_ioctl (fd, FBIOSCURSOR, (long)&f); + set_fs (old_fs); + return ret; +} +#endif /* 0 */ + +struct fb_fix_screeninfo32 { + char id[16]; + __kernel_caddr_t32 smem_start; + __u32 smem_len; + __u32 type; + __u32 type_aux; + __u32 visual; + __u16 xpanstep; + __u16 ypanstep; + __u16 ywrapstep; + __u32 line_length; + __kernel_caddr_t32 mmio_start; + __u32 mmio_len; + __u32 accel; + __u16 reserved[3]; +}; + +struct fb_cmap32 { + __u32 start; + __u32 len; + __kernel_caddr_t32 red; + __kernel_caddr_t32 green; + __kernel_caddr_t32 blue; + __kernel_caddr_t32 transp; +}; + +static int fb_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + mm_segment_t old_fs = get_fs(); + u32 red = 0, green = 0, blue = 0, transp = 0; + struct fb_fix_screeninfo fix; + struct fb_cmap cmap; + void *karg; + int err = 0; + + memset(&cmap, 0, sizeof(cmap)); + switch (cmd) { + case FBIOGET_FSCREENINFO: + karg = &fix; + break; + case FBIOGETCMAP: + case FBIOPUTCMAP: + karg = &cmap; + err = __get_user(cmap.start, &((struct fb_cmap32 *)arg)->start); + err |= __get_user(cmap.len, &((struct fb_cmap32 *)arg)->len); + err |= __get_user(red, &((struct fb_cmap32 *)arg)->red); + err |= __get_user(green, &((struct fb_cmap32 *)arg)->green); + err |= __get_user(blue, &((struct fb_cmap32 *)arg)->blue); + err |= __get_user(transp, &((struct fb_cmap32 *)arg)->transp); + if (err) { + err = -EFAULT; + goto out; + } + err = -ENOMEM; + cmap.red = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL); + if (!cmap.red) + goto out; + cmap.green = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL); + if (!cmap.green) + goto out; + cmap.blue = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL); + if (!cmap.blue) + goto out; + if (transp) { + cmap.transp = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL); + if (!cmap.transp) + goto out; + } + + if (cmd == FBIOGETCMAP) + break; + + err = __copy_from_user(cmap.red, (char *)A(red), cmap.len * sizeof(__u16)); + err |= __copy_from_user(cmap.green, (char *)A(green), cmap.len * sizeof(__u16)); + err |= __copy_from_user(cmap.blue, (char *)A(blue), cmap.len * sizeof(__u16)); + if (cmap.transp) err |= __copy_from_user(cmap.transp, (char *)A(transp), cmap.len * sizeof(__u16)); + if (err) { + err = -EFAULT; + goto out; + } + break; + default: + do { + static int count = 0; + if (++count <= 20) + printk(KERN_WARNING + "%s: Unknown fb ioctl cmd fd(%d) " + "cmd(%08x) arg(%08lx)\n", + __FUNCTION__, fd, cmd, arg); + } while(0); + return -ENOSYS; + } + set_fs(KERNEL_DS); + err = sys_ioctl(fd, cmd, (unsigned long)karg); + set_fs(old_fs); + if (err) + goto out; + switch (cmd) { + struct fb_fix_screeninfo32 fix32; + case FBIOGET_FSCREENINFO: + memset(&fix32, 0, sizeof(fix32)); + memcpy(fix32.id, fix.id, sizeof(fix32.id)); + fix32.smem_start = (__u32)(unsigned long)fix.smem_start; + fix32.smem_len = fix.smem_len; + fix32.type = fix.type; + fix32.type_aux = fix.type_aux; + fix32.visual = fix.visual; + fix32.xpanstep = fix.xpanstep; + fix32.ypanstep = fix.ypanstep; + fix32.ywrapstep = fix.ywrapstep; + fix32.line_length = fix.line_length; + fix32.mmio_start = (__u32)(unsigned long)fix.mmio_start; + fix32.mmio_len = fix.mmio_len; + fix32.accel = fix.accel; + memcpy(fix32.reserved, fix.reserved, sizeof(fix32.reserved)); + err = __copy_to_user((void *) arg, (const void *) &fix32, sizeof(fix32)); + +printk("fix : %lx %x %x %x %x %x %x %x %x %lx %x %x\n", + fix.smem_start, fix.smem_len, + fix.type, fix.type_aux, fix.visual, + fix.xpanstep, fix.ypanstep, fix.ywrapstep, fix.line_length, + fix.mmio_start, fix.mmio_len, fix.accel); +printk("fix32: %x %x %x %x %x %x %x %x %x %x %x %x\n", + fix32.smem_start, fix32.smem_len, + fix32.type, fix32.type_aux, fix32.visual, + fix32.xpanstep, fix32.ypanstep, fix32.ywrapstep, fix32.line_length, + fix32.mmio_start, fix32.mmio_len, fix32.accel); + + break; + case FBIOGETCMAP: + err = __copy_to_user((char *)A(red), cmap.red, cmap.len * sizeof(__u16)); + err |= __copy_to_user((char *)A(green), cmap.blue, cmap.len * sizeof(__u16)); + err |= __copy_to_user((char *)A(blue), cmap.blue, cmap.len * sizeof(__u16)); + if (cmap.transp) + err |= __copy_to_user((char *)A(transp), cmap.transp, cmap.len * sizeof(__u16)); + break; + case FBIOPUTCMAP: + break; + } + if (err) + err = -EFAULT; + +out: if (cmap.red) kfree(cmap.red); + if (cmap.green) kfree(cmap.green); + if (cmap.blue) kfree(cmap.blue); + if (cmap.transp) kfree(cmap.transp); + return err; +} + +static int hdio_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + mm_segment_t old_fs = get_fs(); + unsigned long kval; + unsigned int *uvp; + int error; + + set_fs(KERNEL_DS); + error = sys_ioctl(fd, cmd, (long)&kval); + set_fs(old_fs); + + if(error == 0) { + uvp = (unsigned int *)arg; + if(put_user(kval, uvp)) + error = -EFAULT; + } + return error; +} + +struct floppy_struct32 { + unsigned int size; + unsigned int sect; + unsigned int head; + unsigned int track; + unsigned int stretch; + unsigned char gap; + unsigned char rate; + unsigned char spec1; + unsigned char fmt_gap; + const __kernel_caddr_t32 name; +}; + +struct floppy_drive_params32 { + char cmos; + u32 max_dtr; + u32 hlt; + u32 hut; + u32 srt; + u32 spinup; + u32 spindown; + unsigned char spindown_offset; + unsigned char select_delay; + unsigned char rps; + unsigned char tracks; + u32 timeout; + unsigned char interleave_sect; + struct floppy_max_errors max_errors; + char flags; + char read_track; + short autodetect[8]; + int checkfreq; + int native_format; +}; + +struct floppy_drive_struct32 { + signed char flags; + u32 spinup_date; + u32 select_date; + u32 first_read_date; + short probed_format; + short track; + short maxblock; + short maxtrack; + int generation; + int keep_data; + int fd_ref; + int fd_device; + int last_checked; + __kernel_caddr_t32 dmabuf; + int bufblocks; +}; + +struct floppy_fdc_state32 { + int spec1; + int spec2; + int dtr; + unsigned char version; + unsigned char dor; + u32 address; + unsigned int rawcmd:2; + unsigned int reset:1; + unsigned int need_configure:1; + unsigned int perp_mode:2; + unsigned int has_fifo:1; + unsigned int driver_version; + unsigned char track[4]; +}; + +struct floppy_write_errors32 { + unsigned int write_errors; + u32 first_error_sector; + int first_error_generation; + u32 last_error_sector; + int last_error_generation; + unsigned int badness; +}; + +#define FDSETPRM32 _IOW(2, 0x42, struct floppy_struct32) +#define FDDEFPRM32 _IOW(2, 0x43, struct floppy_struct32) +#define FDGETPRM32 _IOR(2, 0x04, struct floppy_struct32) +#define FDSETDRVPRM32 _IOW(2, 0x90, struct floppy_drive_params32) +#define FDGETDRVPRM32 _IOR(2, 0x11, struct floppy_drive_params32) +#define FDGETDRVSTAT32 _IOR(2, 0x12, struct floppy_drive_struct32) +#define FDPOLLDRVSTAT32 _IOR(2, 0x13, struct floppy_drive_struct32) +#define FDGETFDCSTAT32 _IOR(2, 0x15, struct floppy_fdc_state32) +#define FDWERRORGET32 _IOR(2, 0x17, struct floppy_write_errors32) + +static struct { + unsigned int cmd32; + unsigned int cmd; +} fd_ioctl_trans_table[] = { + { FDSETPRM32, FDSETPRM }, + { FDDEFPRM32, FDDEFPRM }, + { FDGETPRM32, FDGETPRM }, + { FDSETDRVPRM32, FDSETDRVPRM }, + { FDGETDRVPRM32, FDGETDRVPRM }, + { FDGETDRVSTAT32, FDGETDRVSTAT }, + { FDPOLLDRVSTAT32, FDPOLLDRVSTAT }, + { FDGETFDCSTAT32, FDGETFDCSTAT }, + { FDWERRORGET32, FDWERRORGET } +}; + +#define NR_FD_IOCTL_TRANS (sizeof(fd_ioctl_trans_table)/sizeof(fd_ioctl_trans_table[0])) + +static int fd_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + mm_segment_t old_fs = get_fs(); + void *karg = NULL; + unsigned int kcmd = 0; + int i, err; + + for (i = 0; i < NR_FD_IOCTL_TRANS; i++) + if (cmd == fd_ioctl_trans_table[i].cmd32) { + kcmd = fd_ioctl_trans_table[i].cmd; + break; + } + if (!kcmd) + return -EINVAL; + + switch (cmd) { + case FDSETPRM32: + case FDDEFPRM32: + case FDGETPRM32: + { + struct floppy_struct *f; + + f = karg = kmalloc(sizeof(struct floppy_struct), GFP_KERNEL); + if (!karg) + return -ENOMEM; + if (cmd == FDGETPRM32) + break; + err = __get_user(f->size, &((struct floppy_struct32 *)arg)->size); + err |= __get_user(f->sect, &((struct floppy_struct32 *)arg)->sect); + err |= __get_user(f->head, &((struct floppy_struct32 *)arg)->head); + err |= __get_user(f->track, &((struct floppy_struct32 *)arg)->track); + err |= __get_user(f->stretch, &((struct floppy_struct32 *)arg)->stretch); + err |= __get_user(f->gap, &((struct floppy_struct32 *)arg)->gap); + err |= __get_user(f->rate, &((struct floppy_struct32 *)arg)->rate); + err |= __get_user(f->spec1, &((struct floppy_struct32 *)arg)->spec1); + err |= __get_user(f->fmt_gap, &((struct floppy_struct32 *)arg)->fmt_gap); + err |= __get_user((u64)f->name, &((struct floppy_struct32 *)arg)->name); + if (err) { + err = -EFAULT; + goto out; + } + break; + } + case FDSETDRVPRM32: + case FDGETDRVPRM32: + { + struct floppy_drive_params *f; + + f = karg = kmalloc(sizeof(struct floppy_drive_params), GFP_KERNEL); + if (!karg) + return -ENOMEM; + if (cmd == FDGETDRVPRM32) + break; + err = __get_user(f->cmos, &((struct floppy_drive_params32 *)arg)->cmos); + err |= __get_user(f->max_dtr, &((struct floppy_drive_params32 *)arg)->max_dtr); + err |= __get_user(f->hlt, &((struct floppy_drive_params32 *)arg)->hlt); + err |= __get_user(f->hut, &((struct floppy_drive_params32 *)arg)->hut); + err |= __get_user(f->srt, &((struct floppy_drive_params32 *)arg)->srt); + err |= __get_user(f->spinup, &((struct floppy_drive_params32 *)arg)->spinup); + err |= __get_user(f->spindown, &((struct floppy_drive_params32 *)arg)->spindown); + err |= __get_user(f->spindown_offset, &((struct floppy_drive_params32 *)arg)->spindown_offset); + err |= __get_user(f->select_delay, &((struct floppy_drive_params32 *)arg)->select_delay); + err |= __get_user(f->rps, &((struct floppy_drive_params32 *)arg)->rps); + err |= __get_user(f->tracks, &((struct floppy_drive_params32 *)arg)->tracks); + err |= __get_user(f->timeout, &((struct floppy_drive_params32 *)arg)->timeout); + err |= __get_user(f->interleave_sect, &((struct floppy_drive_params32 *)arg)->interleave_sect); + err |= __copy_from_user(&f->max_errors, &((struct floppy_drive_params32 *)arg)->max_errors, sizeof(f->max_errors)); + err |= __get_user(f->flags, &((struct floppy_drive_params32 *)arg)->flags); + err |= __get_user(f->read_track, &((struct floppy_drive_params32 *)arg)->read_track); + err |= __copy_from_user(f->autodetect, ((struct floppy_drive_params32 *)arg)->autodetect, sizeof(f->autodetect)); + err |= __get_user(f->checkfreq, &((struct floppy_drive_params32 *)arg)->checkfreq); + err |= __get_user(f->native_format, &((struct floppy_drive_params32 *)arg)->native_format); + if (err) { + err = -EFAULT; + goto out; + } + break; + } + case FDGETDRVSTAT32: + case FDPOLLDRVSTAT32: + karg = kmalloc(sizeof(struct floppy_drive_struct), GFP_KERNEL); + if (!karg) + return -ENOMEM; + break; + case FDGETFDCSTAT32: + karg = kmalloc(sizeof(struct floppy_fdc_state), GFP_KERNEL); + if (!karg) + return -ENOMEM; + break; + case FDWERRORGET32: + karg = kmalloc(sizeof(struct floppy_write_errors), GFP_KERNEL); + if (!karg) + return -ENOMEM; + break; + default: + return -EINVAL; + } + set_fs (KERNEL_DS); + err = sys_ioctl (fd, kcmd, (unsigned long)karg); + set_fs (old_fs); + if (err) + goto out; + switch (cmd) { + case FDGETPRM32: + { + struct floppy_struct *f = karg; + + err = __put_user(f->size, &((struct floppy_struct32 *)arg)->size); + err |= __put_user(f->sect, &((struct floppy_struct32 *)arg)->sect); + err |= __put_user(f->head, &((struct floppy_struct32 *)arg)->head); + err |= __put_user(f->track, &((struct floppy_struct32 *)arg)->track); + err |= __put_user(f->stretch, &((struct floppy_struct32 *)arg)->stretch); + err |= __put_user(f->gap, &((struct floppy_struct32 *)arg)->gap); + err |= __put_user(f->rate, &((struct floppy_struct32 *)arg)->rate); + err |= __put_user(f->spec1, &((struct floppy_struct32 *)arg)->spec1); + err |= __put_user(f->fmt_gap, &((struct floppy_struct32 *)arg)->fmt_gap); + err |= __put_user((u64)f->name, &((struct floppy_struct32 *)arg)->name); + break; + } + case FDGETDRVPRM32: + { + struct floppy_drive_params *f = karg; + + err = __put_user(f->cmos, &((struct floppy_drive_params32 *)arg)->cmos); + err |= __put_user(f->max_dtr, &((struct floppy_drive_params32 *)arg)->max_dtr); + err |= __put_user(f->hlt, &((struct floppy_drive_params32 *)arg)->hlt); + err |= __put_user(f->hut, &((struct floppy_drive_params32 *)arg)->hut); + err |= __put_user(f->srt, &((struct floppy_drive_params32 *)arg)->srt); + err |= __put_user(f->spinup, &((struct floppy_drive_params32 *)arg)->spinup); + err |= __put_user(f->spindown, &((struct floppy_drive_params32 *)arg)->spindown); + err |= __put_user(f->spindown_offset, &((struct floppy_drive_params32 *)arg)->spindown_offset); + err |= __put_user(f->select_delay, &((struct floppy_drive_params32 *)arg)->select_delay); + err |= __put_user(f->rps, &((struct floppy_drive_params32 *)arg)->rps); + err |= __put_user(f->tracks, &((struct floppy_drive_params32 *)arg)->tracks); + err |= __put_user(f->timeout, &((struct floppy_drive_params32 *)arg)->timeout); + err |= __put_user(f->interleave_sect, &((struct floppy_drive_params32 *)arg)->interleave_sect); + err |= __copy_to_user(&((struct floppy_drive_params32 *)arg)->max_errors, &f->max_errors, sizeof(f->max_errors)); + err |= __put_user(f->flags, &((struct floppy_drive_params32 *)arg)->flags); + err |= __put_user(f->read_track, &((struct floppy_drive_params32 *)arg)->read_track); + err |= __copy_to_user(((struct floppy_drive_params32 *)arg)->autodetect, f->autodetect, sizeof(f->autodetect)); + err |= __put_user(f->checkfreq, &((struct floppy_drive_params32 *)arg)->checkfreq); + err |= __put_user(f->native_format, &((struct floppy_drive_params32 *)arg)->native_format); + break; + } + case FDGETDRVSTAT32: + case FDPOLLDRVSTAT32: + { + struct floppy_drive_struct *f = karg; + + err = __put_user(f->flags, &((struct floppy_drive_struct32 *)arg)->flags); + err |= __put_user(f->spinup_date, &((struct floppy_drive_struct32 *)arg)->spinup_date); + err |= __put_user(f->select_date, &((struct floppy_drive_struct32 *)arg)->select_date); + err |= __put_user(f->first_read_date, &((struct floppy_drive_struct32 *)arg)->first_read_date); + err |= __put_user(f->probed_format, &((struct floppy_drive_struct32 *)arg)->probed_format); + err |= __put_user(f->track, &((struct floppy_drive_struct32 *)arg)->track); + err |= __put_user(f->maxblock, &((struct floppy_drive_struct32 *)arg)->maxblock); + err |= __put_user(f->maxtrack, &((struct floppy_drive_struct32 *)arg)->maxtrack); + err |= __put_user(f->generation, &((struct floppy_drive_struct32 *)arg)->generation); + err |= __put_user(f->keep_data, &((struct floppy_drive_struct32 *)arg)->keep_data); + err |= __put_user(f->fd_ref, &((struct floppy_drive_struct32 *)arg)->fd_ref); + err |= __put_user(f->fd_device, &((struct floppy_drive_struct32 *)arg)->fd_device); + err |= __put_user(f->last_checked, &((struct floppy_drive_struct32 *)arg)->last_checked); + err |= __put_user((u64)f->dmabuf, &((struct floppy_drive_struct32 *)arg)->dmabuf); + err |= __put_user((u64)f->bufblocks, &((struct floppy_drive_struct32 *)arg)->bufblocks); + break; + } + case FDGETFDCSTAT32: + { + struct floppy_fdc_state *f = karg; + + err = __put_user(f->spec1, &((struct floppy_fdc_state32 *)arg)->spec1); + err |= __put_user(f->spec2, &((struct floppy_fdc_state32 *)arg)->spec2); + err |= __put_user(f->dtr, &((struct floppy_fdc_state32 *)arg)->dtr); + err |= __put_user(f->version, &((struct floppy_fdc_state32 *)arg)->version); + err |= __put_user(f->dor, &((struct floppy_fdc_state32 *)arg)->dor); + err |= __put_user(f->address, &((struct floppy_fdc_state32 *)arg)->address); + err |= __copy_to_user((char *)&((struct floppy_fdc_state32 *)arg)->address + + sizeof(((struct floppy_fdc_state32 *)arg)->address), + (char *)&f->address + sizeof(f->address), sizeof(int)); + err |= __put_user(f->driver_version, &((struct floppy_fdc_state32 *)arg)->driver_version); + err |= __copy_to_user(((struct floppy_fdc_state32 *)arg)->track, f->track, sizeof(f->track)); + break; + } + case FDWERRORGET32: + { + struct floppy_write_errors *f = karg; + + err = __put_user(f->write_errors, &((struct floppy_write_errors32 *)arg)->write_errors); + err |= __put_user(f->first_error_sector, &((struct floppy_write_errors32 *)arg)->first_error_sector); + err |= __put_user(f->first_error_generation, &((struct floppy_write_errors32 *)arg)->first_error_generation); + err |= __put_user(f->last_error_sector, &((struct floppy_write_errors32 *)arg)->last_error_sector); + err |= __put_user(f->last_error_generation, &((struct floppy_write_errors32 *)arg)->last_error_generation); + err |= __put_user(f->badness, &((struct floppy_write_errors32 *)arg)->badness); + break; + } + default: + break; + } + if (err) + err = -EFAULT; + +out: if (karg) kfree(karg); + return err; +} + +struct ppp_option_data32 { + __kernel_caddr_t32 ptr; + __u32 length; + int transmit; +}; +#define PPPIOCSCOMPRESS32 _IOW('t', 77, struct ppp_option_data32) + +struct ppp_idle32 { + __kernel_time_t32 xmit_idle; + __kernel_time_t32 recv_idle; +}; +#define PPPIOCGIDLE32 _IOR('t', 63, struct ppp_idle32) + +static int ppp_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + mm_segment_t old_fs = get_fs(); + struct ppp_option_data32 data32; + struct ppp_option_data data; + struct ppp_idle32 idle32; + struct ppp_idle idle; + unsigned int kcmd; + void *karg; + int err = 0; + + switch (cmd) { + case PPPIOCGIDLE32: + kcmd = PPPIOCGIDLE; + karg = &idle; + break; + case PPPIOCSCOMPRESS32: + if (copy_from_user(&data32, (struct ppp_option_data32 *)arg, sizeof(struct ppp_option_data32))) + return -EFAULT; + data.ptr = kmalloc (data32.length, GFP_KERNEL); + if (!data.ptr) + return -ENOMEM; + if (copy_from_user(data.ptr, (__u8 *)A(data32.ptr), data32.length)) { + kfree(data.ptr); + return -EFAULT; + } + data.length = data32.length; + data.transmit = data32.transmit; + kcmd = PPPIOCSCOMPRESS; + karg = &data; + break; + default: + do { + static int count = 0; + if (++count <= 20) + printk(KERN_WARNING + "ppp_ioctl: Unknown cmd fd(%d) " + "cmd(%08x) arg(%08x)\n", + (int)fd, (unsigned int)cmd, (unsigned int)arg); + } while(0); + return -EINVAL; + } + set_fs (KERNEL_DS); + err = sys_ioctl (fd, kcmd, (unsigned long)karg); + set_fs (old_fs); + switch (cmd) { + case PPPIOCGIDLE32: + if (err) + return err; + idle32.xmit_idle = idle.xmit_idle; + idle32.recv_idle = idle.recv_idle; + if (copy_to_user((struct ppp_idle32 *)arg, &idle32, sizeof(struct ppp_idle32))) + return -EFAULT; + break; + case PPPIOCSCOMPRESS32: + kfree(data.ptr); + break; + default: + break; + } + return err; +} + + +struct mtget32 { + __u32 mt_type; + __u32 mt_resid; + __u32 mt_dsreg; + __u32 mt_gstat; + __u32 mt_erreg; + __kernel_daddr_t32 mt_fileno; + __kernel_daddr_t32 mt_blkno; +}; +#define MTIOCGET32 _IOR('m', 2, struct mtget32) + +struct mtpos32 { + __u32 mt_blkno; +}; +#define MTIOCPOS32 _IOR('m', 3, struct mtpos32) + +struct mtconfiginfo32 { + __u32 mt_type; + __u32 ifc_type; + __u16 irqnr; + __u16 dmanr; + __u16 port; + __u32 debug; + __u32 have_dens:1; + __u32 have_bsf:1; + __u32 have_fsr:1; + __u32 have_bsr:1; + __u32 have_eod:1; + __u32 have_seek:1; + __u32 have_tell:1; + __u32 have_ras1:1; + __u32 have_ras2:1; + __u32 have_ras3:1; + __u32 have_qfa:1; + __u32 pad1:5; + char reserved[10]; +}; +#define MTIOCGETCONFIG32 _IOR('m', 4, struct mtconfiginfo32) +#define MTIOCSETCONFIG32 _IOW('m', 5, struct mtconfiginfo32) + +static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + mm_segment_t old_fs = get_fs(); + struct mtconfiginfo info; + struct mtget get; + struct mtpos pos; + unsigned long kcmd; + void *karg; + int err = 0; + + switch(cmd) { + case MTIOCPOS32: + kcmd = MTIOCPOS; + karg = &pos; + break; + case MTIOCGET32: + kcmd = MTIOCGET; + karg = &get; + break; + case MTIOCGETCONFIG32: + kcmd = MTIOCGETCONFIG; + karg = &info; + break; + case MTIOCSETCONFIG32: + kcmd = MTIOCSETCONFIG; + karg = &info; + err = __get_user(info.mt_type, &((struct mtconfiginfo32 *)arg)->mt_type); + err |= __get_user(info.ifc_type, &((struct mtconfiginfo32 *)arg)->ifc_type); + err |= __get_user(info.irqnr, &((struct mtconfiginfo32 *)arg)->irqnr); + err |= __get_user(info.dmanr, &((struct mtconfiginfo32 *)arg)->dmanr); + err |= __get_user(info.port, &((struct mtconfiginfo32 *)arg)->port); + err |= __get_user(info.debug, &((struct mtconfiginfo32 *)arg)->debug); + err |= __copy_from_user((char *)&info.debug + sizeof(info.debug), + (char *)&((struct mtconfiginfo32 *)arg)->debug + + sizeof(((struct mtconfiginfo32 *)arg)->debug), sizeof(__u32)); + if (err) + return -EFAULT; + break; + default: + do { + static int count = 0; + if (++count <= 20) + printk(KERN_WARNING + "mt_ioctl: Unknown cmd fd(%d) " + "cmd(%08x) arg(%08x)\n", + (int)fd, (unsigned int)cmd, (unsigned int)arg); + } while(0); + return -EINVAL; + } + set_fs (KERNEL_DS); + err = sys_ioctl (fd, kcmd, (unsigned long)karg); + set_fs (old_fs); + if (err) + return err; + switch (cmd) { + case MTIOCPOS32: + err = __put_user(pos.mt_blkno, &((struct mtpos32 *)arg)->mt_blkno); + break; + case MTIOCGET32: + err = __put_user(get.mt_type, &((struct mtget32 *)arg)->mt_type); + err |= __put_user(get.mt_resid, &((struct mtget32 *)arg)->mt_resid); + err |= __put_user(get.mt_dsreg, &((struct mtget32 *)arg)->mt_dsreg); + err |= __put_user(get.mt_gstat, &((struct mtget32 *)arg)->mt_gstat); + err |= __put_user(get.mt_erreg, &((struct mtget32 *)arg)->mt_erreg); + err |= __put_user(get.mt_fileno, &((struct mtget32 *)arg)->mt_fileno); + err |= __put_user(get.mt_blkno, &((struct mtget32 *)arg)->mt_blkno); + break; + case MTIOCGETCONFIG32: + err = __put_user(info.mt_type, &((struct mtconfiginfo32 *)arg)->mt_type); + err |= __put_user(info.ifc_type, &((struct mtconfiginfo32 *)arg)->ifc_type); + err |= __put_user(info.irqnr, &((struct mtconfiginfo32 *)arg)->irqnr); + err |= __put_user(info.dmanr, &((struct mtconfiginfo32 *)arg)->dmanr); + err |= __put_user(info.port, &((struct mtconfiginfo32 *)arg)->port); + err |= __put_user(info.debug, &((struct mtconfiginfo32 *)arg)->debug); + err |= __copy_to_user((char *)&((struct mtconfiginfo32 *)arg)->debug + + sizeof(((struct mtconfiginfo32 *)arg)->debug), + (char *)&info.debug + sizeof(info.debug), sizeof(__u32)); + break; + case MTIOCSETCONFIG32: + break; + } + return err ? -EFAULT: 0; +} + +struct cdrom_read32 { + int cdread_lba; + __kernel_caddr_t32 cdread_bufaddr; + int cdread_buflen; +}; + +struct cdrom_read_audio32 { + union cdrom_addr addr; + u_char addr_format; + int nframes; + __kernel_caddr_t32 buf; +}; + +struct cdrom_generic_command32 { + unsigned char cmd[CDROM_PACKET_SIZE]; + __kernel_caddr_t32 buffer; + unsigned int buflen; + int stat; + __kernel_caddr_t32 sense; + __kernel_caddr_t32 reserved[3]; +}; + +static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + mm_segment_t old_fs = get_fs(); + struct cdrom_read cdread; + struct cdrom_read_audio cdreadaudio; + struct cdrom_generic_command cgc; + __kernel_caddr_t32 addr; + char *data = 0; + void *karg; + int err = 0; + + switch(cmd) { + case CDROMREADMODE2: + case CDROMREADMODE1: + case CDROMREADRAW: + case CDROMREADCOOKED: + karg = &cdread; + err = __get_user(cdread.cdread_lba, &((struct cdrom_read32 *)arg)->cdread_lba); + err |= __get_user(addr, &((struct cdrom_read32 *)arg)->cdread_bufaddr); + err |= __get_user(cdread.cdread_buflen, &((struct cdrom_read32 *)arg)->cdread_buflen); + if (err) + return -EFAULT; + data = kmalloc(cdread.cdread_buflen, GFP_KERNEL); + if (!data) + return -ENOMEM; + cdread.cdread_bufaddr = data; + break; + case CDROMREADAUDIO: + karg = &cdreadaudio; + err = copy_from_user(&cdreadaudio.addr, &((struct cdrom_read_audio32 *)arg)->addr, sizeof(cdreadaudio.addr)); + err |= __get_user(cdreadaudio.addr_format, &((struct cdrom_read_audio32 *)arg)->addr_format); + err |= __get_user(cdreadaudio.nframes, &((struct cdrom_read_audio32 *)arg)->nframes); + err |= __get_user(addr, &((struct cdrom_read_audio32 *)arg)->buf); + if (err) + return -EFAULT; + data = kmalloc(cdreadaudio.nframes * 2352, GFP_KERNEL); + if (!data) + return -ENOMEM; + cdreadaudio.buf = data; + break; + case CDROM_SEND_PACKET: + karg = &cgc; + err = copy_from_user(cgc.cmd, &((struct cdrom_generic_command32 *)arg)->cmd, sizeof(cgc.cmd)); + err |= __get_user(addr, &((struct cdrom_generic_command32 *)arg)->buffer); + err |= __get_user(cgc.buflen, &((struct cdrom_generic_command32 *)arg)->buflen); + if (err) + return -EFAULT; + if ((data = kmalloc(cgc.buflen, GFP_KERNEL)) == NULL) + return -ENOMEM; + cgc.buffer = data; + break; + default: + do { + static int count = 0; + if (++count <= 20) + printk(KERN_WARNING + "cdrom_ioctl: Unknown cmd fd(%d) " + "cmd(%08x) arg(%08x)\n", + (int)fd, (unsigned int)cmd, (unsigned int)arg); + } while(0); + return -EINVAL; + } + set_fs (KERNEL_DS); + err = sys_ioctl (fd, cmd, (unsigned long)karg); + set_fs (old_fs); + if (err) + goto out; + switch (cmd) { + case CDROMREADMODE2: + case CDROMREADMODE1: + case CDROMREADRAW: + case CDROMREADCOOKED: + err = copy_to_user((char *)A(addr), data, cdread.cdread_buflen); + break; + case CDROMREADAUDIO: + err = copy_to_user((char *)A(addr), data, cdreadaudio.nframes * 2352); + break; + case CDROM_SEND_PACKET: + err = copy_to_user((char *)A(addr), data, cgc.buflen); + break; + default: + break; + } +out: if (data) + kfree(data); + return err ? -EFAULT : 0; +} + +struct loop_info32 { + int lo_number; /* ioctl r/o */ + __kernel_dev_t32 lo_device; /* ioctl r/o */ + unsigned int lo_inode; /* ioctl r/o */ + __kernel_dev_t32 lo_rdevice; /* ioctl r/o */ + int lo_offset; + int lo_encrypt_type; + int lo_encrypt_key_size; /* ioctl w/o */ + int lo_flags; /* ioctl r/o */ + char lo_name[LO_NAME_SIZE]; + unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */ + unsigned int lo_init[2]; + char reserved[4]; +}; + +static int loop_status(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + mm_segment_t old_fs = get_fs(); + struct loop_info l; + int err = -EINVAL; + + switch(cmd) { + case LOOP_SET_STATUS: + err = get_user(l.lo_number, &((struct loop_info32 *)arg)->lo_number); + err |= __get_user(l.lo_device, &((struct loop_info32 *)arg)->lo_device); + err |= __get_user(l.lo_inode, &((struct loop_info32 *)arg)->lo_inode); + err |= __get_user(l.lo_rdevice, &((struct loop_info32 *)arg)->lo_rdevice); + err |= __copy_from_user((char *)&l.lo_offset, (char *)&((struct loop_info32 *)arg)->lo_offset, + 8 + (unsigned long)l.lo_init - (unsigned long)&l.lo_offset); + if (err) { + err = -EFAULT; + } else { + set_fs (KERNEL_DS); + err = sys_ioctl (fd, cmd, (unsigned long)&l); + set_fs (old_fs); + } + break; + case LOOP_GET_STATUS: + set_fs (KERNEL_DS); + err = sys_ioctl (fd, cmd, (unsigned long)&l); + set_fs (old_fs); + if (!err) { + err = put_user(l.lo_number, &((struct loop_info32 *)arg)->lo_number); + err |= __put_user(l.lo_device, &((struct loop_info32 *)arg)->lo_device); + err |= __put_user(l.lo_inode, &((struct loop_info32 *)arg)->lo_inode); + err |= __put_user(l.lo_rdevice, &((struct loop_info32 *)arg)->lo_rdevice); + err |= __copy_to_user((char *)&((struct loop_info32 *)arg)->lo_offset, + (char *)&l.lo_offset, (unsigned long)l.lo_init - (unsigned long)&l.lo_offset); + if (err) + err = -EFAULT; + } + break; + default: { + static int count = 0; + if (++count <= 20) + printk(KERN_WARNING + "%s: Unknown loop ioctl cmd, fd(%d) " + "cmd(%08x) arg(%08lx)\n", + __FUNCTION__, fd, cmd, arg); + } + } + return err; +} + +#ifdef CONFIG_VT +extern int tty_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg); + +static int vt_check(struct file *file) +{ + struct tty_struct *tty; + struct inode *inode = file->f_dentry->d_inode; + + if (file->f_op->ioctl != tty_ioctl) + return -EINVAL; + + tty = (struct tty_struct *)file->private_data; + if (tty_paranoia_check(tty, inode->i_rdev, "tty_ioctl")) + return -EINVAL; + + if (tty->driver.ioctl != vt_ioctl) + return -EINVAL; + + /* + * To have permissions to do most of the vt ioctls, we either have + * to be the owner of the tty, or super-user. + */ + if (current->tty == tty || suser()) + return 1; + return 0; +} + +struct consolefontdesc32 { + unsigned short charcount; /* characters in font (256 or 512) */ + unsigned short charheight; /* scan lines per character (1-32) */ + u32 chardata; /* font data in expanded form */ +}; + +static int do_fontx_ioctl(unsigned int fd, int cmd, struct consolefontdesc32 *user_cfd, struct file *file) +{ + struct consolefontdesc cfdarg; + struct console_font_op op; + int i, perm; + + perm = vt_check(file); + if (perm < 0) return perm; + + if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc32))) + return -EFAULT; + + cfdarg.chardata = (unsigned char *)A(((struct consolefontdesc32 *)&cfdarg)->chardata); + + switch (cmd) { + case PIO_FONTX: + if (!perm) + return -EPERM; + op.op = KD_FONT_OP_SET; + op.flags = 0; + op.width = 8; + op.height = cfdarg.charheight; + op.charcount = cfdarg.charcount; + op.data = cfdarg.chardata; + return con_font_op(fg_console, &op); + case GIO_FONTX: + if (!cfdarg.chardata) + return 0; + op.op = KD_FONT_OP_GET; + op.flags = 0; + op.width = 8; + op.height = cfdarg.charheight; + op.charcount = cfdarg.charcount; + op.data = cfdarg.chardata; + i = con_font_op(fg_console, &op); + if (i) + return i; + cfdarg.charheight = op.height; + cfdarg.charcount = op.charcount; + ((struct consolefontdesc32 *)&cfdarg)->chardata = (unsigned long)cfdarg.chardata; + if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc32))) + return -EFAULT; + return 0; + } + return -EINVAL; +} + +struct console_font_op32 { + unsigned int op; /* operation code KD_FONT_OP_* */ + unsigned int flags; /* KD_FONT_FLAG_* */ + unsigned int width, height; /* font size */ + unsigned int charcount; + u32 data; /* font data with height fixed to 32 */ +}; + +static int do_kdfontop_ioctl(unsigned int fd, unsigned int cmd, struct console_font_op32 *fontop, struct file *file) +{ + struct console_font_op op; + int perm = vt_check(file), i; + struct vt_struct *vt; + + if (perm < 0) return perm; + + if (copy_from_user(&op, (void *) fontop, sizeof(struct console_font_op32))) + return -EFAULT; + if (!perm && op.op != KD_FONT_OP_GET) + return -EPERM; + op.data = (unsigned char *)A(((struct console_font_op32 *)&op)->data); + op.flags |= KD_FONT_FLAG_OLD; + vt = (struct vt_struct *)((struct tty_struct *)file->private_data)->driver_data; + i = con_font_op(vt->vc_num, &op); + if (i) return i; + ((struct console_font_op32 *)&op)->data = (unsigned long)op.data; + if (copy_to_user((void *) fontop, &op, sizeof(struct console_font_op32))) + return -EFAULT; + return 0; +} + +struct unimapdesc32 { + unsigned short entry_ct; + u32 entries; +}; + +static int do_unimap_ioctl(unsigned int fd, unsigned int cmd, struct unimapdesc32 *user_ud, struct file *file) +{ + struct unimapdesc32 tmp; + int perm = vt_check(file); + + if (perm < 0) return perm; + if (copy_from_user(&tmp, user_ud, sizeof tmp)) + return -EFAULT; + switch (cmd) { + case PIO_UNIMAP: + if (!perm) return -EPERM; + return con_set_unimap(fg_console, tmp.entry_ct, (struct unipair *)A(tmp.entries)); + case GIO_UNIMAP: + return con_get_unimap(fg_console, tmp.entry_ct, &(user_ud->entry_ct), (struct unipair *)A(tmp.entries)); + } + return 0; +} +#endif + +#if 0 +static int do_smb_getmountuid(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + mm_segment_t old_fs = get_fs(); + __kernel_uid_t kuid; + int err; + + cmd = SMB_IOC_GETMOUNTUID; + + set_fs(KERNEL_DS); + err = sys_ioctl(fd, cmd, (unsigned long)&kuid); + set_fs(old_fs); + + if (err >= 0) + err = put_user(kuid, (__kernel_uid_t32 *)arg); + + return err; +} +#endif + +struct atmif_sioc32 { + int number; + int length; + __kernel_caddr_t32 arg; +}; + +struct atm_iobuf32 { + int length; + __kernel_caddr_t32 buffer; +}; + +#define ATM_GETLINKRATE32 _IOW('a', ATMIOC_ITF+1, struct atmif_sioc32) +#define ATM_GETNAMES32 _IOW('a', ATMIOC_ITF+3, struct atm_iobuf32) +#define ATM_GETTYPE32 _IOW('a', ATMIOC_ITF+4, struct atmif_sioc32) +#define ATM_GETESI32 _IOW('a', ATMIOC_ITF+5, struct atmif_sioc32) +#define ATM_GETADDR32 _IOW('a', ATMIOC_ITF+6, struct atmif_sioc32) +#define ATM_RSTADDR32 _IOW('a', ATMIOC_ITF+7, struct atmif_sioc32) +#define ATM_ADDADDR32 _IOW('a', ATMIOC_ITF+8, struct atmif_sioc32) +#define ATM_DELADDR32 _IOW('a', ATMIOC_ITF+9, struct atmif_sioc32) +#define ATM_GETCIRANGE32 _IOW('a', ATMIOC_ITF+10, struct atmif_sioc32) +#define ATM_SETCIRANGE32 _IOW('a', ATMIOC_ITF+11, struct atmif_sioc32) +#define ATM_SETESI32 _IOW('a', ATMIOC_ITF+12, struct atmif_sioc32) +#define ATM_SETESIF32 _IOW('a', ATMIOC_ITF+13, struct atmif_sioc32) +#define ATM_GETSTAT32 _IOW('a', ATMIOC_SARCOM+0, struct atmif_sioc32) +#define ATM_GETSTATZ32 _IOW('a', ATMIOC_SARCOM+1, struct atmif_sioc32) +#define ATM_GETLOOP32 _IOW('a', ATMIOC_SARCOM+2, struct atmif_sioc32) +#define ATM_SETLOOP32 _IOW('a', ATMIOC_SARCOM+3, struct atmif_sioc32) +#define ATM_QUERYLOOP32 _IOW('a', ATMIOC_SARCOM+4, struct atmif_sioc32) + +static struct { + unsigned int cmd32; + unsigned int cmd; +} atm_ioctl_map[] = { + { ATM_GETLINKRATE32, ATM_GETLINKRATE }, + { ATM_GETNAMES32, ATM_GETNAMES }, + { ATM_GETTYPE32, ATM_GETTYPE }, + { ATM_GETESI32, ATM_GETESI }, + { ATM_GETADDR32, ATM_GETADDR }, + { ATM_RSTADDR32, ATM_RSTADDR }, + { ATM_ADDADDR32, ATM_ADDADDR }, + { ATM_DELADDR32, ATM_DELADDR }, + { ATM_GETCIRANGE32, ATM_GETCIRANGE }, + { ATM_SETCIRANGE32, ATM_SETCIRANGE }, + { ATM_SETESI32, ATM_SETESI }, + { ATM_SETESIF32, ATM_SETESIF }, + { ATM_GETSTAT32, ATM_GETSTAT }, + { ATM_GETSTATZ32, ATM_GETSTATZ }, + { ATM_GETLOOP32, ATM_GETLOOP }, + { ATM_SETLOOP32, ATM_SETLOOP }, + { ATM_QUERYLOOP32, ATM_QUERYLOOP } +}; + +#define NR_ATM_IOCTL (sizeof(atm_ioctl_map)/sizeof(atm_ioctl_map[0])) + + +static int do_atm_iobuf(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct atm_iobuf32 iobuf32; + struct atm_iobuf iobuf = { 0, NULL }; + mm_segment_t old_fs; + int err; + + err = copy_from_user(&iobuf32, (struct atm_iobuf32*)arg, + sizeof(struct atm_iobuf32)); + if (err) + return -EFAULT; + + iobuf.length = iobuf32.length; + + if (iobuf32.buffer == (__kernel_caddr_t32) NULL || iobuf32.length == 0) { + iobuf.buffer = (void*)(unsigned long)iobuf32.buffer; + } else { + iobuf.buffer = kmalloc(iobuf.length, GFP_KERNEL); + if (iobuf.buffer == NULL) { + err = -ENOMEM; + goto out; + } + + err = copy_from_user(iobuf.buffer, A(iobuf32.buffer), iobuf.length); + if (err) { + err = -EFAULT; + goto out; + } + } + + old_fs = get_fs(); set_fs (KERNEL_DS); + err = sys_ioctl (fd, cmd, (unsigned long)&iobuf); + set_fs (old_fs); + if(err) + goto out; + + if(iobuf.buffer && iobuf.length > 0) { + err = copy_to_user(A(iobuf32.buffer), iobuf.buffer, iobuf.length); + if (err) { + err = -EFAULT; + goto out; + } + } + err = __put_user(iobuf.length, &(((struct atm_iobuf32*)arg)->length)); + + out: + if(iobuf32.buffer && iobuf32.length > 0) + kfree(iobuf.buffer); + + return err; +} + + +static int do_atmif_sioc(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct atmif_sioc32 sioc32; + struct atmif_sioc sioc = { 0, 0, NULL }; + mm_segment_t old_fs; + int err; + + err = copy_from_user(&sioc32, (struct atmif_sioc32*)arg, + sizeof(struct atmif_sioc32)); + if (err) + return -EFAULT; + + sioc.number = sioc32.number; + sioc.length = sioc32.length; + + if (sioc32.arg == (__kernel_caddr_t32) NULL || sioc32.length == 0) { + sioc.arg = (void*)(unsigned long)sioc32.arg; + } else { + sioc.arg = kmalloc(sioc.length, GFP_KERNEL); + if (sioc.arg == NULL) { + err = -ENOMEM; + goto out; + } + + err = copy_from_user(sioc.arg, A(sioc32.arg), sioc32.length); + if (err) { + err = -EFAULT; + goto out; + } + } + + old_fs = get_fs(); set_fs (KERNEL_DS); + err = sys_ioctl (fd, cmd, (unsigned long)&sioc); + set_fs (old_fs); + if(err) { + goto out; + } + + if(sioc.arg && sioc.length > 0) { + err = copy_to_user(A(sioc32.arg), sioc.arg, sioc.length); + if (err) { + err = -EFAULT; + goto out; + } + } + err = __put_user(sioc.length, &(((struct atmif_sioc32*)arg)->length)); + + out: + if(sioc32.arg && sioc32.length > 0) + kfree(sioc.arg); + + return err; +} + + +static int do_atm_ioctl(unsigned int fd, unsigned int cmd32, unsigned long arg) +{ + int i; + unsigned int cmd = 0; + + switch (cmd32) { + case SONET_GETSTAT: + case SONET_GETSTATZ: + case SONET_GETDIAG: + case SONET_SETDIAG: + case SONET_CLRDIAG: + case SONET_SETFRAMING: + case SONET_GETFRAMING: + case SONET_GETFRSENSE: + return do_atmif_sioc(fd, cmd32, arg); + } + + for (i = 0; i < NR_ATM_IOCTL; i++) { + if (cmd32 == atm_ioctl_map[i].cmd32) { + cmd = atm_ioctl_map[i].cmd; + break; + } + } + if (i == NR_ATM_IOCTL) { + return -EINVAL; + } + + switch (cmd) { + case ATM_GETNAMES: + return do_atm_iobuf(fd, cmd, arg); + + case ATM_GETLINKRATE: + case ATM_GETTYPE: + case ATM_GETESI: + case ATM_GETADDR: + case ATM_RSTADDR: + case ATM_ADDADDR: + case ATM_DELADDR: + case ATM_GETCIRANGE: + case ATM_SETCIRANGE: + case ATM_SETESI: + case ATM_SETESIF: + case ATM_GETSTAT: + case ATM_GETSTATZ: + case ATM_GETLOOP: + case ATM_SETLOOP: + case ATM_QUERYLOOP: + return do_atmif_sioc(fd, cmd, arg); + } + + return -EINVAL; +} + +#if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE) +/* Ugh, LVM. Pitty it was not cleaned up before accepted :((. */ +typedef struct { + uint8_t vg_name[NAME_LEN]; + uint32_t vg_number; + uint32_t vg_access; + uint32_t vg_status; + uint32_t lv_max; + uint32_t lv_cur; + uint32_t lv_open; + uint32_t pv_max; + uint32_t pv_cur; + uint32_t pv_act; + uint32_t dummy; + uint32_t vgda; + uint32_t pe_size; + uint32_t pe_total; + uint32_t pe_allocated; + uint32_t pvg_total; + u32 proc; + u32 pv[ABS_MAX_PV + 1]; + u32 lv[ABS_MAX_LV + 1]; + uint8_t vg_uuid[UUID_LEN+1]; /* volume group UUID */ + uint8_t dummy1[200]; +} vg32_t; + +typedef struct { + uint8_t id[2]; + uint16_t version; + lvm_disk_data_t pv_on_disk; + lvm_disk_data_t vg_on_disk; + lvm_disk_data_t pv_namelist_on_disk; + lvm_disk_data_t lv_on_disk; + lvm_disk_data_t pe_on_disk; + uint8_t pv_name[NAME_LEN]; + uint8_t vg_name[NAME_LEN]; + uint8_t system_id[NAME_LEN]; + kdev_t pv_dev; + uint32_t pv_number; + uint32_t pv_status; + uint32_t pv_allocatable; + uint32_t pv_size; + uint32_t lv_cur; + uint32_t pe_size; + uint32_t pe_total; + uint32_t pe_allocated; + uint32_t pe_stale; + u32 pe; + u32 inode; + uint8_t pv_uuid[UUID_LEN+1]; +} pv32_t; + +typedef struct { + char lv_name[NAME_LEN]; + u32 lv; +} lv_req32_t; + +typedef struct { + u32 lv_index; + u32 lv; + /* Transfer size because user space and kernel space differ */ + uint16_t size; +} lv_status_byindex_req32_t; + +typedef struct { + __kernel_dev_t32 dev; + u32 lv; +} lv_status_bydev_req32_t; + +typedef struct { + uint8_t lv_name[NAME_LEN]; + kdev_t old_dev; + kdev_t new_dev; + u32 old_pe; + u32 new_pe; +} le_remap_req32_t; + +typedef struct { + char pv_name[NAME_LEN]; + u32 pv; +} pv_status_req32_t; + +typedef struct { + uint8_t lv_name[NAME_LEN]; + uint8_t vg_name[NAME_LEN]; + uint32_t lv_access; + uint32_t lv_status; + uint32_t lv_open; + kdev_t lv_dev; + uint32_t lv_number; + uint32_t lv_mirror_copies; + uint32_t lv_recovery; + uint32_t lv_schedule; + uint32_t lv_size; + u32 lv_current_pe; + uint32_t lv_current_le; + uint32_t lv_allocated_le; + uint32_t lv_stripes; + uint32_t lv_stripesize; + uint32_t lv_badblock; + uint32_t lv_allocation; + uint32_t lv_io_timeout; + uint32_t lv_read_ahead; + /* delta to version 1 starts here */ + u32 lv_snapshot_org; + u32 lv_snapshot_prev; + u32 lv_snapshot_next; + u32 lv_block_exception; + uint32_t lv_remap_ptr; + uint32_t lv_remap_end; + uint32_t lv_chunk_size; + uint32_t lv_snapshot_minor; + char dummy[200]; +} lv32_t; + +typedef struct { + u32 hash[2]; + u32 rsector_org; + kdev_t rdev_org; + u32 rsector_new; + kdev_t rdev_new; +} lv_block_exception32_t; + +static void put_lv_t(lv_t *l) +{ + if (l->lv_current_pe) vfree(l->lv_current_pe); + if (l->lv_block_exception) vfree(l->lv_block_exception); + kfree(l); +} + +static lv_t *get_lv_t(u32 p, int *errp) +{ + int err, i; + u32 ptr1, ptr2; + size_t size; + lv_block_exception32_t *lbe32; + lv_block_exception_t *lbe; + lv32_t *ul = (lv32_t *)A(p); + lv_t *l = (lv_t *) kmalloc(sizeof(lv_t), GFP_KERNEL); + + if (!l) { + *errp = -ENOMEM; + return NULL; + } + memset(l, 0, sizeof(lv_t)); + err = copy_from_user(l, ul, (long)&((lv32_t *)0)->lv_current_pe); + err |= __copy_from_user(&l->lv_current_le, &ul->lv_current_le, + ((long)&ul->lv_snapshot_org) - ((long)&ul->lv_current_le)); + err |= __copy_from_user(&l->lv_remap_ptr, &ul->lv_remap_ptr, + ((long)&ul->dummy[0]) - ((long)&ul->lv_remap_ptr)); + err |= __get_user(ptr1, &ul->lv_current_pe); + err |= __get_user(ptr2, &ul->lv_block_exception); + if (err) { + kfree(l); + *errp = -EFAULT; + return NULL; + } + if (ptr1) { + size = l->lv_allocated_le * sizeof(pe_t); + l->lv_current_pe = vmalloc(size); + if (l->lv_current_pe) + err = copy_from_user(l->lv_current_pe, (void *)A(ptr1), size); + } + if (!err && ptr2) { + size = l->lv_remap_end * sizeof(lv_block_exception_t); + l->lv_block_exception = lbe = vmalloc(size); + if (l->lv_block_exception) { + lbe32 = (lv_block_exception32_t *)A(ptr2); + memset(lbe, 0, size); + for (i = 0; i < l->lv_remap_end; i++, lbe++, lbe32++) { + err |= get_user(lbe->rsector_org, &lbe32->rsector_org); + err |= __get_user(lbe->rdev_org, &lbe32->rdev_org); + err |= __get_user(lbe->rsector_new, &lbe32->rsector_new); + err |= __get_user(lbe->rdev_new, &lbe32->rdev_new); + } + } + } + if (err || (ptr1 && !l->lv_current_pe) || (ptr2 && !l->lv_block_exception)) { + if (!err) + *errp = -ENOMEM; + else + *errp = -EFAULT; + put_lv_t(l); + return NULL; + } + return l; +} + +static int copy_lv_t(u32 ptr, lv_t *l) +{ + int err; + lv32_t *ul = (lv32_t *)A(ptr); + u32 ptr1; + size_t size; + + err = get_user(ptr1, &ul->lv_current_pe); + if (err) + return -EFAULT; + err = copy_to_user(ul, l, (long)&((lv32_t *)0)->lv_current_pe); + err |= __copy_to_user(&ul->lv_current_le, &l->lv_current_le, + ((long)&ul->lv_snapshot_org) - ((long)&ul->lv_current_le)); + err |= __copy_to_user(&ul->lv_remap_ptr, &l->lv_remap_ptr, + ((long)&ul->dummy[0]) - ((long)&ul->lv_remap_ptr)); + size = l->lv_allocated_le * sizeof(pe_t); + if (ptr1) + err |= __copy_to_user((void *)A(ptr1), l->lv_current_pe, size); + return err ? -EFAULT : 0; +} + +static int do_lvm_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + vg_t *v = NULL; + union { + lv_req_t lv_req; + le_remap_req_t le_remap; + lv_status_byindex_req_t lv_byindex; + lv_status_bydev_req_t lv_bydev; + pv_status_req_t pv_status; + } u; + pv_t p; + int err; + u32 ptr = 0; + int i; + mm_segment_t old_fs; + void *karg = &u; + + switch (cmd) { + case VG_STATUS: + v = kmalloc(sizeof(vg_t), GFP_KERNEL); + if (!v) + return -ENOMEM; + karg = v; + break; + + case VG_CREATE_OLD: + case VG_CREATE: + v = kmalloc(sizeof(vg_t), GFP_KERNEL); + if (!v) + return -ENOMEM; + if (copy_from_user(v, (void *)arg, (long)&((vg32_t *)0)->proc)) { + kfree(v); + return -EFAULT; + } + /* 'proc' field is unused, just NULL it out. */ + v->proc = NULL; + if (copy_from_user(v->vg_uuid, ((vg32_t *)arg)->vg_uuid, UUID_LEN+1)) { + kfree(v); + return -EFAULT; + } + + karg = v; + memset(v->pv, 0, sizeof(v->pv) + sizeof(v->lv)); + if (v->pv_max > ABS_MAX_PV || v->lv_max > ABS_MAX_LV) + return -EPERM; + for (i = 0; i < v->pv_max; i++) { + err = __get_user(ptr, &((vg32_t *)arg)->pv[i]); + if (err) + break; + if (ptr) { + v->pv[i] = kmalloc(sizeof(pv_t), GFP_KERNEL); + if (!v->pv[i]) { + err = -ENOMEM; + break; + } + err = copy_from_user(v->pv[i], (void *)A(ptr), + sizeof(pv32_t) - 8 - UUID_LEN+1); + if (err) { + err = -EFAULT; + break; + } + err = copy_from_user(v->pv[i]->pv_uuid, + ((pv32_t *)A(ptr))->pv_uuid, + UUID_LEN+1); + if (err) { + err = -EFAULT; + break; + } + + v->pv[i]->pe = NULL; + v->pv[i]->bd = NULL; + } + } + if (!err) { + for (i = 0; i < v->lv_max; i++) { + err = __get_user(ptr, &((vg32_t *)arg)->lv[i]); + if (err) + break; + if (ptr) { + v->lv[i] = get_lv_t(ptr, &err); + if (err) + break; + } + } + } + break; + + case LV_CREATE: + case LV_EXTEND: + case LV_REDUCE: + case LV_REMOVE: + case LV_RENAME: + case LV_STATUS_BYNAME: + err = copy_from_user(&u.pv_status, arg, sizeof(u.pv_status.pv_name)); + if (err) + return -EFAULT; + if (cmd != LV_REMOVE) { + err = __get_user(ptr, &((lv_req32_t *)arg)->lv); + if (err) + return err; + u.lv_req.lv = get_lv_t(ptr, &err); + } else + u.lv_req.lv = NULL; + break; + + case LV_STATUS_BYINDEX: + err = get_user(u.lv_byindex.lv_index, + &((lv_status_byindex_req32_t *)arg)->lv_index); + err |= __get_user(ptr, &((lv_status_byindex_req32_t *)arg)->lv); + if (err) + return err; + u.lv_byindex.lv = get_lv_t(ptr, &err); + break; + + case LV_STATUS_BYDEV: + err = get_user(u.lv_bydev.dev, &((lv_status_bydev_req32_t *)arg)->dev); + err |= __get_user(ptr, &((lv_status_bydev_req32_t *)arg)->lv); + if (err) + return err; + u.lv_bydev.lv = get_lv_t(ptr, &err); + break; + + case VG_EXTEND: + err = copy_from_user(&p, (void *)arg, sizeof(pv32_t) - 8 - UUID_LEN+1); + if (err) + return -EFAULT; + err = copy_from_user(p.pv_uuid, ((pv32_t *)arg)->pv_uuid, UUID_LEN+1); + if (err) + return -EFAULT; + p.pe = NULL; + p.bd = NULL; + karg = &p; + break; + + case PV_CHANGE: + case PV_STATUS: + err = copy_from_user(&u.pv_status, arg, sizeof(u.lv_req.lv_name)); + if (err) + return -EFAULT; + err = __get_user(ptr, &((pv_status_req32_t *)arg)->pv); + if (err) + return err; + u.pv_status.pv = &p; + if (cmd == PV_CHANGE) { + err = copy_from_user(&p, (void *)A(ptr), + sizeof(pv32_t) - 8 - UUID_LEN+1); + if (err) + return -EFAULT; + p.pe = NULL; + p.bd = NULL; + } + break; + }; + + old_fs = get_fs(); set_fs (KERNEL_DS); + err = sys_ioctl (fd, cmd, (unsigned long)karg); + set_fs (old_fs); + + switch (cmd) { + case VG_STATUS: + if (!err) { + if (copy_to_user((void *)arg, v, (long)&((vg32_t *)0)->proc) || + clear_user(&((vg32_t *)arg)->proc, sizeof(vg32_t) - (long)&((vg32_t *)0)->proc)) + err = -EFAULT; + } + if (copy_to_user(((vg32_t *)arg)->vg_uuid, v->vg_uuid, UUID_LEN+1)) { + err = -EFAULT; + } + kfree(v); + break; + + case VG_CREATE_OLD: + case VG_CREATE: + for (i = 0; i < v->pv_max; i++) { + if (v->pv[i]) + kfree(v->pv[i]); + } + for (i = 0; i < v->lv_max; i++) { + if (v->lv[i]) + put_lv_t(v->lv[i]); + } + kfree(v); + break; + + case LV_STATUS_BYNAME: + if (!err && u.lv_req.lv) + err = copy_lv_t(ptr, u.lv_req.lv); + /* Fall through */ + + case LV_CREATE: + case LV_EXTEND: + case LV_REDUCE: + if (u.lv_req.lv) + put_lv_t(u.lv_req.lv); + break; + + case LV_STATUS_BYINDEX: + if (u.lv_byindex.lv) { + if (!err) + err = copy_lv_t(ptr, u.lv_byindex.lv); + put_lv_t(u.lv_byindex.lv); + } + break; + + case LV_STATUS_BYDEV: + if (u.lv_bydev.lv) { + if (!err) + err = copy_lv_t(ptr, u.lv_bydev.lv); + put_lv_t(u.lv_byindex.lv); + } + break; + + case PV_STATUS: + if (!err) { + err = copy_to_user((void *)A(ptr), &p, sizeof(pv32_t) - 8 - UUID_LEN+1); + if (err) + return -EFAULT; + err = copy_to_user(((pv_t *)A(ptr))->pv_uuid, p.pv_uuid, UUID_LEN + 1); + if (err) + return -EFAULT; + } + break; + }; + + return err; +} +#endif + +#ifdef CONFIG_GENRTC +#endif + +#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) +/* This really belongs in include/linux/drm.h -DaveM */ +#include "../../../drivers/char/drm/drm.h" + +typedef struct drm32_version { + int version_major; /* Major version */ + int version_minor; /* Minor version */ + int version_patchlevel;/* Patch level */ + int name_len; /* Length of name buffer */ + u32 name; /* Name of driver */ + int date_len; /* Length of date buffer */ + u32 date; /* User-space buffer to hold date */ + int desc_len; /* Length of desc buffer */ + u32 desc; /* User-space buffer to hold desc */ +} drm32_version_t; +#define DRM32_IOCTL_VERSION DRM_IOWR(0x00, drm32_version_t) + +static int drm32_version(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + drm32_version_t *uversion = (drm32_version_t *)arg; + char *name_ptr, *date_ptr, *desc_ptr; + u32 tmp1, tmp2, tmp3; + drm_version_t kversion; + mm_segment_t old_fs; + int ret; + + memset(&kversion, 0, sizeof(kversion)); + if (get_user(kversion.name_len, &uversion->name_len) || + get_user(kversion.date_len, &uversion->date_len) || + get_user(kversion.desc_len, &uversion->desc_len) || + get_user(tmp1, &uversion->name) || + get_user(tmp2, &uversion->date) || + get_user(tmp3, &uversion->desc)) + return -EFAULT; + + name_ptr = (char *) A(tmp1); + date_ptr = (char *) A(tmp2); + desc_ptr = (char *) A(tmp3); + + ret = -ENOMEM; + if (kversion.name_len && name_ptr) { + kversion.name = kmalloc(kversion.name_len, GFP_KERNEL); + if (!kversion.name) + goto out; + } + if (kversion.date_len && date_ptr) { + kversion.date = kmalloc(kversion.date_len, GFP_KERNEL); + if (!kversion.date) + goto out; + } + if (kversion.desc_len && desc_ptr) { + kversion.desc = kmalloc(kversion.desc_len, GFP_KERNEL); + if (!kversion.desc) + goto out; + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_ioctl (fd, DRM_IOCTL_VERSION, (unsigned long)&kversion); + set_fs(old_fs); + + if (!ret) { + if ((kversion.name && + copy_to_user(name_ptr, kversion.name, kversion.name_len)) || + (kversion.date && + copy_to_user(date_ptr, kversion.date, kversion.date_len)) || + (kversion.desc && + copy_to_user(desc_ptr, kversion.desc, kversion.desc_len))) + ret = -EFAULT; + if (put_user(kversion.version_major, &uversion->version_major) || + put_user(kversion.version_minor, &uversion->version_minor) || + put_user(kversion.version_patchlevel, &uversion->version_patchlevel) || + put_user(kversion.name_len, &uversion->name_len) || + put_user(kversion.date_len, &uversion->date_len) || + put_user(kversion.desc_len, &uversion->desc_len)) + ret = -EFAULT; + } + +out: + if (kversion.name) + kfree(kversion.name); + if (kversion.date) + kfree(kversion.date); + if (kversion.desc) + kfree(kversion.desc); + return ret; +} + +typedef struct drm32_unique { + int unique_len; /* Length of unique */ + u32 unique; /* Unique name for driver instantiation */ +} drm32_unique_t; +#define DRM32_IOCTL_GET_UNIQUE DRM_IOWR(0x01, drm32_unique_t) +#define DRM32_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm32_unique_t) + +static int drm32_getsetunique(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + drm32_unique_t *uarg = (drm32_unique_t *)arg; + drm_unique_t karg; + mm_segment_t old_fs; + char *uptr; + u32 tmp; + int ret; + + if (get_user(karg.unique_len, &uarg->unique_len)) + return -EFAULT; + karg.unique = NULL; + + if (get_user(tmp, &uarg->unique)) + return -EFAULT; + + uptr = (char *) A(tmp); + + if (uptr) { + karg.unique = kmalloc(karg.unique_len, GFP_KERNEL); + if (!karg.unique) + return -ENOMEM; + if (cmd == DRM32_IOCTL_SET_UNIQUE && + copy_from_user(karg.unique, uptr, karg.unique_len)) { + kfree(karg.unique); + return -EFAULT; + } + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + if (cmd == DRM32_IOCTL_GET_UNIQUE) + ret = sys_ioctl (fd, DRM_IOCTL_GET_UNIQUE, (unsigned long)&karg); + else + ret = sys_ioctl (fd, DRM_IOCTL_SET_UNIQUE, (unsigned long)&karg); + set_fs(old_fs); + + if (!ret) { + if (cmd == DRM32_IOCTL_GET_UNIQUE && + uptr != NULL && + copy_to_user(uptr, karg.unique, karg.unique_len)) + ret = -EFAULT; + if (put_user(karg.unique_len, &uarg->unique_len)) + ret = -EFAULT; + } + + if (karg.unique != NULL) + kfree(karg.unique); + + return ret; +} + +typedef struct drm32_map { + u32 offset; /* Requested physical address (0 for SAREA)*/ + u32 size; /* Requested physical size (bytes) */ + drm_map_type_t type; /* Type of memory to map */ + drm_map_flags_t flags; /* Flags */ + u32 handle; /* User-space: "Handle" to pass to mmap */ + /* Kernel-space: kernel-virtual address */ + int mtrr; /* MTRR slot used */ + /* Private data */ +} drm32_map_t; +#define DRM32_IOCTL_ADD_MAP DRM_IOWR(0x15, drm32_map_t) + +static int drm32_addmap(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + drm32_map_t *uarg = (drm32_map_t *) arg; + drm_map_t karg; + mm_segment_t old_fs; + u32 tmp; + int ret; + + ret = get_user(karg.offset, &uarg->offset); + ret |= get_user(karg.size, &uarg->size); + ret |= get_user(karg.type, &uarg->type); + ret |= get_user(karg.flags, &uarg->flags); + ret |= get_user(tmp, &uarg->handle); + ret |= get_user(karg.mtrr, &uarg->mtrr); + if (ret) + return -EFAULT; + + karg.handle = (void *) A(tmp); + + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_ioctl(fd, DRM_IOCTL_ADD_MAP, (unsigned long) &karg); + set_fs(old_fs); + + if (!ret) { + ret = put_user(karg.offset, &uarg->offset); + ret |= put_user(karg.size, &uarg->size); + ret |= put_user(karg.type, &uarg->type); + ret |= put_user(karg.flags, &uarg->flags); + tmp = (u32) (long)karg.handle; + ret |= put_user(tmp, &uarg->handle); + ret |= put_user(karg.mtrr, &uarg->mtrr); + if (ret) + ret = -EFAULT; + } + + return ret; +} + +typedef struct drm32_buf_info { + int count; /* Entries in list */ + u32 list; /* (drm_buf_desc_t *) */ +} drm32_buf_info_t; +#define DRM32_IOCTL_INFO_BUFS DRM_IOWR(0x18, drm32_buf_info_t) + +static int drm32_info_bufs(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + drm32_buf_info_t *uarg = (drm32_buf_info_t *)arg; + drm_buf_desc_t *ulist; + drm_buf_info_t karg; + mm_segment_t old_fs; + int orig_count, ret; + u32 tmp; + + if (get_user(karg.count, &uarg->count) || + get_user(tmp, &uarg->list)) + return -EFAULT; + + ulist = (drm_buf_desc_t *) A(tmp); + + orig_count = karg.count; + + karg.list = kmalloc(karg.count * sizeof(drm_buf_desc_t), GFP_KERNEL); + if (!karg.list) + return -EFAULT; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_ioctl(fd, DRM_IOCTL_INFO_BUFS, (unsigned long) &karg); + set_fs(old_fs); + + if (!ret) { + if (karg.count <= orig_count && + (copy_to_user(ulist, karg.list, + karg.count * sizeof(drm_buf_desc_t)))) + ret = -EFAULT; + if (put_user(karg.count, &uarg->count)) + ret = -EFAULT; + } + + kfree(karg.list); + + return ret; +} + +typedef struct drm32_buf_free { + int count; + u32 list; /* (int *) */ +} drm32_buf_free_t; +#define DRM32_IOCTL_FREE_BUFS DRM_IOW( 0x1a, drm32_buf_free_t) + +static int drm32_free_bufs(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + drm32_buf_free_t *uarg = (drm32_buf_free_t *)arg; + drm_buf_free_t karg; + mm_segment_t old_fs; + int *ulist; + int ret; + u32 tmp; + + if (get_user(karg.count, &uarg->count) || + get_user(tmp, &uarg->list)) + return -EFAULT; + + ulist = (int *) A(tmp); + + karg.list = kmalloc(karg.count * sizeof(int), GFP_KERNEL); + if (!karg.list) + return -ENOMEM; + + ret = -EFAULT; + if (copy_from_user(karg.list, ulist, (karg.count * sizeof(int)))) + goto out; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_ioctl(fd, DRM_IOCTL_FREE_BUFS, (unsigned long) &karg); + set_fs(old_fs); + +out: + kfree(karg.list); + + return ret; +} + +typedef struct drm32_buf_pub { + int idx; /* Index into master buflist */ + int total; /* Buffer size */ + int used; /* Amount of buffer in use (for DMA) */ + u32 address; /* Address of buffer (void *) */ +} drm32_buf_pub_t; + +typedef struct drm32_buf_map { + int count; /* Length of buflist */ + u32 virtual; /* Mmaped area in user-virtual (void *) */ + u32 list; /* Buffer information (drm_buf_pub_t *) */ +} drm32_buf_map_t; +#define DRM32_IOCTL_MAP_BUFS DRM_IOWR(0x19, drm32_buf_map_t) + +static int drm32_map_bufs(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + drm32_buf_map_t *uarg = (drm32_buf_map_t *)arg; + drm32_buf_pub_t *ulist; + drm_buf_map_t karg; + mm_segment_t old_fs; + int orig_count, ret, i; + u32 tmp1, tmp2; + + if (get_user(karg.count, &uarg->count) || + get_user(tmp1, &uarg->virtual) || + get_user(tmp2, &uarg->list)) + return -EFAULT; + + karg.virtual = (void *) A(tmp1); + ulist = (drm32_buf_pub_t *) A(tmp2); + + orig_count = karg.count; + + karg.list = kmalloc(karg.count * sizeof(drm_buf_pub_t), GFP_KERNEL); + if (!karg.list) + return -ENOMEM; + + ret = -EFAULT; + for (i = 0; i < karg.count; i++) { + if (get_user(karg.list[i].idx, &ulist[i].idx) || + get_user(karg.list[i].total, &ulist[i].total) || + get_user(karg.list[i].used, &ulist[i].used) || + get_user(tmp1, &ulist[i].address)) + goto out; + + karg.list[i].address = (void *) A(tmp1); + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_ioctl(fd, DRM_IOCTL_MAP_BUFS, (unsigned long) &karg); + set_fs(old_fs); + + if (!ret) { + for (i = 0; i < orig_count; i++) { + tmp1 = (u32) (long) karg.list[i].address; + if (put_user(karg.list[i].idx, &ulist[i].idx) || + put_user(karg.list[i].total, &ulist[i].total) || + put_user(karg.list[i].used, &ulist[i].used) || + put_user(tmp1, &ulist[i].address)) { + ret = -EFAULT; + goto out; + } + } + if (put_user(karg.count, &uarg->count)) + ret = -EFAULT; + } + +out: + kfree(karg.list); + return ret; +} + +typedef struct drm32_dma { + /* Indices here refer to the offset into + buflist in drm_buf_get_t. */ + int context; /* Context handle */ + int send_count; /* Number of buffers to send */ + u32 send_indices; /* List of handles to buffers (int *) */ + u32 send_sizes; /* Lengths of data to send (int *) */ + drm_dma_flags_t flags; /* Flags */ + int request_count; /* Number of buffers requested */ + int request_size; /* Desired size for buffers */ + u32 request_indices; /* Buffer information (int *) */ + u32 request_sizes; /* (int *) */ + int granted_count; /* Number of buffers granted */ +} drm32_dma_t; +#define DRM32_IOCTL_DMA DRM_IOWR(0x29, drm32_dma_t) + +/* RED PEN The DRM layer blindly dereferences the send/request + * indice/size arrays even though they are userland + * pointers. -DaveM + */ +static int drm32_dma(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + drm32_dma_t *uarg = (drm32_dma_t *) arg; + int *u_si, *u_ss, *u_ri, *u_rs; + drm_dma_t karg; + mm_segment_t old_fs; + int ret; + u32 tmp1, tmp2, tmp3, tmp4; + + karg.send_indices = karg.send_sizes = NULL; + karg.request_indices = karg.request_sizes = NULL; + + if (get_user(karg.context, &uarg->context) || + get_user(karg.send_count, &uarg->send_count) || + get_user(tmp1, &uarg->send_indices) || + get_user(tmp2, &uarg->send_sizes) || + get_user(karg.flags, &uarg->flags) || + get_user(karg.request_count, &uarg->request_count) || + get_user(karg.request_size, &uarg->request_size) || + get_user(tmp3, &uarg->request_indices) || + get_user(tmp4, &uarg->request_sizes) || + get_user(karg.granted_count, &uarg->granted_count)) + return -EFAULT; + + u_si = (int *) A(tmp1); + u_ss = (int *) A(tmp2); + u_ri = (int *) A(tmp3); + u_rs = (int *) A(tmp4); + + if (karg.send_count) { + karg.send_indices = kmalloc(karg.send_count * sizeof(int), GFP_KERNEL); + karg.send_sizes = kmalloc(karg.send_count * sizeof(int), GFP_KERNEL); + + ret = -ENOMEM; + if (!karg.send_indices || !karg.send_sizes) + goto out; + + ret = -EFAULT; + if (copy_from_user(karg.send_indices, u_si, + (karg.send_count * sizeof(int))) || + copy_from_user(karg.send_sizes, u_ss, + (karg.send_count * sizeof(int)))) + goto out; + } + + if (karg.request_count) { + karg.request_indices = kmalloc(karg.request_count * sizeof(int), GFP_KERNEL); + karg.request_sizes = kmalloc(karg.request_count * sizeof(int), GFP_KERNEL); + + ret = -ENOMEM; + if (!karg.request_indices || !karg.request_sizes) + goto out; + + ret = -EFAULT; + if (copy_from_user(karg.request_indices, u_ri, + (karg.request_count * sizeof(int))) || + copy_from_user(karg.request_sizes, u_rs, + (karg.request_count * sizeof(int)))) + goto out; + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_ioctl(fd, DRM_IOCTL_DMA, (unsigned long) &karg); + set_fs(old_fs); + + if (!ret) { + if (put_user(karg.context, &uarg->context) || + put_user(karg.send_count, &uarg->send_count) || + put_user(karg.flags, &uarg->flags) || + put_user(karg.request_count, &uarg->request_count) || + put_user(karg.request_size, &uarg->request_size) || + put_user(karg.granted_count, &uarg->granted_count)) + ret = -EFAULT; + + if (karg.send_count) { + if (copy_to_user(u_si, karg.send_indices, + (karg.send_count * sizeof(int))) || + copy_to_user(u_ss, karg.send_sizes, + (karg.send_count * sizeof(int)))) + ret = -EFAULT; + } + if (karg.request_count) { + if (copy_to_user(u_ri, karg.request_indices, + (karg.request_count * sizeof(int))) || + copy_to_user(u_rs, karg.request_sizes, + (karg.request_count * sizeof(int)))) + ret = -EFAULT; + } + } + +out: + if (karg.send_indices) + kfree(karg.send_indices); + if (karg.send_sizes) + kfree(karg.send_sizes); + if (karg.request_indices) + kfree(karg.request_indices); + if (karg.request_sizes) + kfree(karg.request_sizes); + + return ret; +} + +typedef struct drm32_ctx_res { + int count; + u32 contexts; /* (drm_ctx_t *) */ +} drm32_ctx_res_t; +#define DRM32_IOCTL_RES_CTX DRM_IOWR(0x26, drm32_ctx_res_t) + +static int drm32_res_ctx(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + drm32_ctx_res_t *uarg = (drm32_ctx_res_t *) arg; + drm_ctx_t *ulist; + drm_ctx_res_t karg; + mm_segment_t old_fs; + int orig_count, ret; + u32 tmp; + + karg.contexts = NULL; + if (get_user(karg.count, &uarg->count) || + get_user(tmp, &uarg->contexts)) + return -EFAULT; + + ulist = (drm_ctx_t *) A(tmp); + + orig_count = karg.count; + if (karg.count && ulist) { + karg.contexts = kmalloc((karg.count * sizeof(drm_ctx_t)), GFP_KERNEL); + if (!karg.contexts) + return -ENOMEM; + if (copy_from_user(karg.contexts, ulist, + (karg.count * sizeof(drm_ctx_t)))) { + kfree(karg.contexts); + return -EFAULT; + } + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_ioctl(fd, DRM_IOCTL_RES_CTX, (unsigned long) &karg); + set_fs(old_fs); + + if (!ret) { + if (orig_count) { + if (copy_to_user(ulist, karg.contexts, + (orig_count * sizeof(drm_ctx_t)))) + ret = -EFAULT; + } + if (put_user(karg.count, &uarg->count)) + ret = -EFAULT; + } + + if (karg.contexts) + kfree(karg.contexts); + + return ret; +} + +#endif + +static int ret_einval(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + return -EINVAL; +} + +static int broken_blkgetsize(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + /* The mkswap binary hard codes it to Intel value :-((( */ + return w_long(fd, BLKGETSIZE, arg); +} + +struct blkpg_ioctl_arg32 { + int op; + int flags; + int datalen; + u32 data; +}; + +static int blkpg_ioctl_trans(unsigned int fd, unsigned int cmd, struct blkpg_ioctl_arg32 *arg) +{ + struct blkpg_ioctl_arg a; + struct blkpg_partition p; + int err; + mm_segment_t old_fs = get_fs(); + + err = get_user(a.op, &arg->op); + err |= __get_user(a.flags, &arg->flags); + err |= __get_user(a.datalen, &arg->datalen); + err |= __get_user((long)a.data, &arg->data); + if (err) return err; + switch (a.op) { + case BLKPG_ADD_PARTITION: + case BLKPG_DEL_PARTITION: + if (a.datalen < sizeof(struct blkpg_partition)) + return -EINVAL; + if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition))) + return -EFAULT; + a.data = &p; + set_fs (KERNEL_DS); + err = sys_ioctl(fd, cmd, (unsigned long)&a); + set_fs (old_fs); + default: + return -EINVAL; + } + return err; +} + +static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg); +} + + +struct serial_struct32 { + int type; + int line; + unsigned int port; + int irq; + int flags; + int xmit_fifo_size; + int custom_divisor; + int baud_base; + unsigned short close_delay; + char io_type; + char reserved_char[1]; + int hub6; + unsigned short closing_wait; /* time to wait before closing */ + unsigned short closing_wait2; /* no longer used... */ + unsigned int iomem_base; /* char * really */ + unsigned short iomem_reg_shift; + unsigned int port_high; + int reserved[1]; +}; + +static int do_tiocgserial(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct serial_struct ss; + int ret; + struct serial_struct32 * uptr = (struct serial_struct32 *)arg; + mm_segment_t old_fs = get_fs(); + + set_fs (KERNEL_DS); + ret = sys_ioctl(fd, cmd, (unsigned long) &ss); + set_fs(old_fs); + + if (!ret) { + /* structs match up to iomem_base */ + ret = copy_to_user(uptr, &ss, sizeof(struct serial_struct32)); + ret |= put_user(ss.iomem_base, &uptr->iomem_base); + ret |= put_user(ss.iomem_reg_shift, &uptr->iomem_reg_shift); + ret |= put_user(ss.port_high, &uptr->port_high); + if (ret) + ret = -EFAULT; + } + return ret; +} + + +struct ioctl_trans { + unsigned long handler; + unsigned int cmd; + unsigned int next; +}; +#define HANDLE_IOCTL(cmd, handler) asm volatile(".dword %1\n.word %0, 0" : : "i" (cmd), "i" (handler)); + +#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd, sys_ioctl) + + +#define IOCTL_TABLE_START void ioctl32_foo(void) { asm volatile(".data\nioctl_translations:"); +#define IOCTL_TABLE_END asm volatile("\nioctl_translations_end:\n\t.previous"); } + +IOCTL_TABLE_START +/* List here exlicitly which ioctl's are known to have + * compatable types passed or none at all... + */ +/* Big T */ +COMPATIBLE_IOCTL(TCGETA) +COMPATIBLE_IOCTL(TCSETA) +COMPATIBLE_IOCTL(TCSETAW) +COMPATIBLE_IOCTL(TCSETAF) +COMPATIBLE_IOCTL(TCSBRK) +COMPATIBLE_IOCTL(TCXONC) +COMPATIBLE_IOCTL(TCFLSH) +COMPATIBLE_IOCTL(TCGETS) +COMPATIBLE_IOCTL(TCSETS) +COMPATIBLE_IOCTL(TCSETSW) +COMPATIBLE_IOCTL(TCSETSF) +COMPATIBLE_IOCTL(TIOCLINUX) +/* Little t */ +COMPATIBLE_IOCTL(TIOCGETD) +COMPATIBLE_IOCTL(TIOCSETD) +COMPATIBLE_IOCTL(TIOCEXCL) +COMPATIBLE_IOCTL(TIOCNXCL) +COMPATIBLE_IOCTL(TIOCCONS) +COMPATIBLE_IOCTL(TIOCGSOFTCAR) +COMPATIBLE_IOCTL(TIOCSSOFTCAR) +COMPATIBLE_IOCTL(TIOCSWINSZ) +COMPATIBLE_IOCTL(TIOCGWINSZ) +COMPATIBLE_IOCTL(TIOCMGET) +COMPATIBLE_IOCTL(TIOCMBIC) +COMPATIBLE_IOCTL(TIOCMBIS) +COMPATIBLE_IOCTL(TIOCMSET) +COMPATIBLE_IOCTL(TIOCPKT) +COMPATIBLE_IOCTL(TIOCNOTTY) +COMPATIBLE_IOCTL(TIOCSTI) +COMPATIBLE_IOCTL(TIOCOUTQ) +COMPATIBLE_IOCTL(TIOCSPGRP) +COMPATIBLE_IOCTL(TIOCGPGRP) +COMPATIBLE_IOCTL(TIOCSCTTY) +COMPATIBLE_IOCTL(TIOCGPTN) +COMPATIBLE_IOCTL(TIOCSPTLCK) +COMPATIBLE_IOCTL(TIOCSSERIAL) +COMPATIBLE_IOCTL(TIOCSERGETLSR) +/* Big F */ +#if 0 +COMPATIBLE_IOCTL(FBIOGTYPE) +COMPATIBLE_IOCTL(FBIOSATTR) +COMPATIBLE_IOCTL(FBIOGATTR) +COMPATIBLE_IOCTL(FBIOSVIDEO) +COMPATIBLE_IOCTL(FBIOGVIDEO) +COMPATIBLE_IOCTL(FBIOGCURSOR32) /* This is not implemented yet. Later it should be converted... */ +COMPATIBLE_IOCTL(FBIOSCURPOS) +COMPATIBLE_IOCTL(FBIOGCURPOS) +COMPATIBLE_IOCTL(FBIOGCURMAX) +#endif +COMPATIBLE_IOCTL(FBIOGET_VSCREENINFO) +COMPATIBLE_IOCTL(FBIOPUT_VSCREENINFO) + +COMPATIBLE_IOCTL(FBIOPAN_DISPLAY) +COMPATIBLE_IOCTL(FBIOGET_FCURSORINFO) +COMPATIBLE_IOCTL(FBIOGET_VCURSORINFO) +COMPATIBLE_IOCTL(FBIOPUT_VCURSORINFO) +COMPATIBLE_IOCTL(FBIOGET_CURSORSTATE) +COMPATIBLE_IOCTL(FBIOPUT_CURSORSTATE) +COMPATIBLE_IOCTL(FBIOGET_CON2FBMAP) +COMPATIBLE_IOCTL(FBIOPUT_CON2FBMAP) +/* Little f */ +COMPATIBLE_IOCTL(FIOCLEX) +COMPATIBLE_IOCTL(FIONCLEX) +COMPATIBLE_IOCTL(FIOASYNC) +COMPATIBLE_IOCTL(FIONBIO) +COMPATIBLE_IOCTL(FIONREAD) /* This is also TIOCINQ */ +/* 0x00 */ +COMPATIBLE_IOCTL(FIBMAP) +COMPATIBLE_IOCTL(FIGETBSZ) +/* 0x03 -- HD/IDE ioctl's used by hdparm and friends. + * Some need translations, these do not. + */ +COMPATIBLE_IOCTL(HDIO_GET_IDENTITY) +COMPATIBLE_IOCTL(HDIO_SET_DMA) +COMPATIBLE_IOCTL(HDIO_SET_KEEPSETTINGS) +COMPATIBLE_IOCTL(HDIO_SET_UNMASKINTR) +COMPATIBLE_IOCTL(HDIO_SET_NOWERR) +COMPATIBLE_IOCTL(HDIO_SET_32BIT) +COMPATIBLE_IOCTL(HDIO_SET_MULTCOUNT) +COMPATIBLE_IOCTL(HDIO_DRIVE_CMD) +COMPATIBLE_IOCTL(HDIO_SET_PIO_MODE) +COMPATIBLE_IOCTL(HDIO_SCAN_HWIF) +COMPATIBLE_IOCTL(HDIO_SET_NICE) +/* 0x02 -- Floppy ioctls */ +COMPATIBLE_IOCTL(FDMSGON) +COMPATIBLE_IOCTL(FDMSGOFF) +COMPATIBLE_IOCTL(FDSETEMSGTRESH) +COMPATIBLE_IOCTL(FDFLUSH) +COMPATIBLE_IOCTL(FDWERRORCLR) +COMPATIBLE_IOCTL(FDSETMAXERRS) +COMPATIBLE_IOCTL(FDGETMAXERRS) +COMPATIBLE_IOCTL(FDGETDRVTYP) +COMPATIBLE_IOCTL(FDEJECT) +COMPATIBLE_IOCTL(FDCLRPRM) +COMPATIBLE_IOCTL(FDFMTBEG) +COMPATIBLE_IOCTL(FDFMTEND) +COMPATIBLE_IOCTL(FDRESET) +COMPATIBLE_IOCTL(FDTWADDLE) +COMPATIBLE_IOCTL(FDFMTTRK) +COMPATIBLE_IOCTL(FDRAWCMD) +/* 0x12 */ +COMPATIBLE_IOCTL(BLKROSET) +COMPATIBLE_IOCTL(BLKROGET) +COMPATIBLE_IOCTL(BLKRRPART) +COMPATIBLE_IOCTL(BLKFLSBUF) +COMPATIBLE_IOCTL(BLKRASET) +COMPATIBLE_IOCTL(BLKFRASET) +COMPATIBLE_IOCTL(BLKSECTSET) +COMPATIBLE_IOCTL(BLKSSZGET) + +/* RAID */ +COMPATIBLE_IOCTL(RAID_VERSION) +COMPATIBLE_IOCTL(GET_ARRAY_INFO) +COMPATIBLE_IOCTL(GET_DISK_INFO) +COMPATIBLE_IOCTL(PRINT_RAID_DEBUG) +COMPATIBLE_IOCTL(CLEAR_ARRAY) +COMPATIBLE_IOCTL(ADD_NEW_DISK) +COMPATIBLE_IOCTL(HOT_REMOVE_DISK) +COMPATIBLE_IOCTL(SET_ARRAY_INFO) +COMPATIBLE_IOCTL(SET_DISK_INFO) +COMPATIBLE_IOCTL(WRITE_RAID_INFO) +COMPATIBLE_IOCTL(UNPROTECT_ARRAY) +COMPATIBLE_IOCTL(PROTECT_ARRAY) +COMPATIBLE_IOCTL(HOT_ADD_DISK) +COMPATIBLE_IOCTL(SET_DISK_FAULTY) +COMPATIBLE_IOCTL(RUN_ARRAY) +COMPATIBLE_IOCTL(START_ARRAY) +COMPATIBLE_IOCTL(STOP_ARRAY) +COMPATIBLE_IOCTL(STOP_ARRAY_RO) +COMPATIBLE_IOCTL(RESTART_ARRAY_RW) + +/* Big K */ +COMPATIBLE_IOCTL(PIO_FONT) +COMPATIBLE_IOCTL(GIO_FONT) +COMPATIBLE_IOCTL(KDSIGACCEPT) +COMPATIBLE_IOCTL(KDGETKEYCODE) +COMPATIBLE_IOCTL(KDSETKEYCODE) +COMPATIBLE_IOCTL(KIOCSOUND) +COMPATIBLE_IOCTL(KDMKTONE) +COMPATIBLE_IOCTL(KDGKBTYPE) +COMPATIBLE_IOCTL(KDSETMODE) +COMPATIBLE_IOCTL(KDGETMODE) +COMPATIBLE_IOCTL(KDSKBMODE) +COMPATIBLE_IOCTL(KDGKBMODE) +COMPATIBLE_IOCTL(KDSKBMETA) +COMPATIBLE_IOCTL(KDGKBMETA) +COMPATIBLE_IOCTL(KDGKBENT) +COMPATIBLE_IOCTL(KDSKBENT) +COMPATIBLE_IOCTL(KDGKBSENT) +COMPATIBLE_IOCTL(KDSKBSENT) +COMPATIBLE_IOCTL(KDGKBDIACR) +COMPATIBLE_IOCTL(KDSKBDIACR) +COMPATIBLE_IOCTL(KDGKBLED) +COMPATIBLE_IOCTL(KDSKBLED) +COMPATIBLE_IOCTL(KDGETLED) +COMPATIBLE_IOCTL(KDSETLED) +COMPATIBLE_IOCTL(GIO_SCRNMAP) +COMPATIBLE_IOCTL(PIO_SCRNMAP) +COMPATIBLE_IOCTL(GIO_UNISCRNMAP) +COMPATIBLE_IOCTL(PIO_UNISCRNMAP) +COMPATIBLE_IOCTL(PIO_FONTRESET) +COMPATIBLE_IOCTL(PIO_UNIMAPCLR) +/* Little k */ +#if 0 +COMPATIBLE_IOCTL(KIOCTYPE) +COMPATIBLE_IOCTL(KIOCLAYOUT) +COMPATIBLE_IOCTL(KIOCGTRANS) +COMPATIBLE_IOCTL(KIOCTRANS) +COMPATIBLE_IOCTL(KIOCCMD) +COMPATIBLE_IOCTL(KIOCSDIRECT) +COMPATIBLE_IOCTL(KIOCSLED) +COMPATIBLE_IOCTL(KIOCGLED) +COMPATIBLE_IOCTL(KIOCSRATE) +COMPATIBLE_IOCTL(KIOCGRATE) +#endif +/* Big S */ +COMPATIBLE_IOCTL(SCSI_IOCTL_GET_IDLUN) +COMPATIBLE_IOCTL(SCSI_IOCTL_DOORLOCK) +COMPATIBLE_IOCTL(SCSI_IOCTL_DOORUNLOCK) +COMPATIBLE_IOCTL(SCSI_IOCTL_TEST_UNIT_READY) +COMPATIBLE_IOCTL(SCSI_IOCTL_TAGGED_ENABLE) +COMPATIBLE_IOCTL(SCSI_IOCTL_TAGGED_DISABLE) +COMPATIBLE_IOCTL(SCSI_IOCTL_GET_BUS_NUMBER) +COMPATIBLE_IOCTL(SCSI_IOCTL_SEND_COMMAND) +/* Big V */ +COMPATIBLE_IOCTL(VT_SETMODE) +COMPATIBLE_IOCTL(VT_GETMODE) +COMPATIBLE_IOCTL(VT_GETSTATE) +COMPATIBLE_IOCTL(VT_OPENQRY) +COMPATIBLE_IOCTL(VT_ACTIVATE) +COMPATIBLE_IOCTL(VT_WAITACTIVE) +COMPATIBLE_IOCTL(VT_RELDISP) +COMPATIBLE_IOCTL(VT_DISALLOCATE) +COMPATIBLE_IOCTL(VT_RESIZE) +COMPATIBLE_IOCTL(VT_RESIZEX) +COMPATIBLE_IOCTL(VT_LOCKSWITCH) +COMPATIBLE_IOCTL(VT_UNLOCKSWITCH) +/* Little v, the video4linux ioctls */ +COMPATIBLE_IOCTL(VIDIOCGCAP) +COMPATIBLE_IOCTL(VIDIOCGCHAN) +COMPATIBLE_IOCTL(VIDIOCSCHAN) +COMPATIBLE_IOCTL(VIDIOCGPICT) +COMPATIBLE_IOCTL(VIDIOCSPICT) +COMPATIBLE_IOCTL(VIDIOCCAPTURE) +COMPATIBLE_IOCTL(VIDIOCKEY) +COMPATIBLE_IOCTL(VIDIOCGAUDIO) +COMPATIBLE_IOCTL(VIDIOCSAUDIO) +COMPATIBLE_IOCTL(VIDIOCSYNC) +COMPATIBLE_IOCTL(VIDIOCMCAPTURE) +COMPATIBLE_IOCTL(VIDIOCGMBUF) +COMPATIBLE_IOCTL(VIDIOCGUNIT) +COMPATIBLE_IOCTL(VIDIOCGCAPTURE) +COMPATIBLE_IOCTL(VIDIOCSCAPTURE) +/* BTTV specific... */ +COMPATIBLE_IOCTL(_IOW('v', BASE_VIDIOCPRIVATE+0, char [256])) +COMPATIBLE_IOCTL(_IOR('v', BASE_VIDIOCPRIVATE+1, char [256])) +COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int)) +COMPATIBLE_IOCTL(_IOW('v' , BASE_VIDIOCPRIVATE+3, char [16])) /* struct bttv_pll_info */ +COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+4, int)) +COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+5, int)) +COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+6, int)) +COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+7, int)) +/* Little m */ +COMPATIBLE_IOCTL(MTIOCTOP) +/* Socket level stuff */ +COMPATIBLE_IOCTL(FIOSETOWN) +COMPATIBLE_IOCTL(SIOCSPGRP) +COMPATIBLE_IOCTL(FIOGETOWN) +COMPATIBLE_IOCTL(SIOCGPGRP) +COMPATIBLE_IOCTL(SIOCATMARK) +COMPATIBLE_IOCTL(SIOCSIFLINK) +COMPATIBLE_IOCTL(SIOCSIFENCAP) +COMPATIBLE_IOCTL(SIOCGIFENCAP) +COMPATIBLE_IOCTL(SIOCSIFBR) +COMPATIBLE_IOCTL(SIOCGIFBR) +COMPATIBLE_IOCTL(SIOCSARP) +COMPATIBLE_IOCTL(SIOCGARP) +COMPATIBLE_IOCTL(SIOCDARP) +COMPATIBLE_IOCTL(SIOCSRARP) +COMPATIBLE_IOCTL(SIOCGRARP) +COMPATIBLE_IOCTL(SIOCDRARP) +COMPATIBLE_IOCTL(SIOCADDDLCI) +COMPATIBLE_IOCTL(SIOCDELDLCI) +/* SG stuff */ +COMPATIBLE_IOCTL(SG_SET_TIMEOUT) +COMPATIBLE_IOCTL(SG_GET_TIMEOUT) +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) +COMPATIBLE_IOCTL(PPPIOCGASYNCMAP) +COMPATIBLE_IOCTL(PPPIOCSASYNCMAP) +COMPATIBLE_IOCTL(PPPIOCGUNIT) +COMPATIBLE_IOCTL(PPPIOCGRASYNCMAP) +COMPATIBLE_IOCTL(PPPIOCSRASYNCMAP) +COMPATIBLE_IOCTL(PPPIOCGMRU) +COMPATIBLE_IOCTL(PPPIOCSMRU) +COMPATIBLE_IOCTL(PPPIOCSMAXCID) +COMPATIBLE_IOCTL(PPPIOCGXASYNCMAP) +COMPATIBLE_IOCTL(PPPIOCSXASYNCMAP) +COMPATIBLE_IOCTL(PPPIOCXFERUNIT) +COMPATIBLE_IOCTL(PPPIOCGNPMODE) +COMPATIBLE_IOCTL(PPPIOCSNPMODE) +COMPATIBLE_IOCTL(PPPIOCGDEBUG) +COMPATIBLE_IOCTL(PPPIOCSDEBUG) +COMPATIBLE_IOCTL(PPPIOCNEWUNIT) +COMPATIBLE_IOCTL(PPPIOCATTACH) +COMPATIBLE_IOCTL(PPPIOCDETACH) +COMPATIBLE_IOCTL(PPPIOCSMRRU) +COMPATIBLE_IOCTL(PPPIOCCONNECT) +COMPATIBLE_IOCTL(PPPIOCDISCONN) +COMPATIBLE_IOCTL(PPPIOCATTCHAN) +/* PPPOX */ +COMPATIBLE_IOCTL(PPPOEIOCSFWD); +COMPATIBLE_IOCTL(PPPOEIOCDFWD); +/* CDROM stuff */ +COMPATIBLE_IOCTL(CDROMPAUSE) +COMPATIBLE_IOCTL(CDROMRESUME) +COMPATIBLE_IOCTL(CDROMPLAYMSF) +COMPATIBLE_IOCTL(CDROMPLAYTRKIND) +COMPATIBLE_IOCTL(CDROMREADTOCHDR) +COMPATIBLE_IOCTL(CDROMREADTOCENTRY) +COMPATIBLE_IOCTL(CDROMSTOP) +COMPATIBLE_IOCTL(CDROMSTART) +COMPATIBLE_IOCTL(CDROMEJECT) +COMPATIBLE_IOCTL(CDROMVOLCTRL) +COMPATIBLE_IOCTL(CDROMSUBCHNL) +COMPATIBLE_IOCTL(CDROMEJECT_SW) +COMPATIBLE_IOCTL(CDROMMULTISESSION) +COMPATIBLE_IOCTL(CDROM_GET_MCN) +COMPATIBLE_IOCTL(CDROMRESET) +COMPATIBLE_IOCTL(CDROMVOLREAD) +COMPATIBLE_IOCTL(CDROMSEEK) +COMPATIBLE_IOCTL(CDROMPLAYBLK) +COMPATIBLE_IOCTL(CDROMCLOSETRAY) +COMPATIBLE_IOCTL(CDROM_SET_OPTIONS) +COMPATIBLE_IOCTL(CDROM_CLEAR_OPTIONS) +COMPATIBLE_IOCTL(CDROM_SELECT_SPEED) +COMPATIBLE_IOCTL(CDROM_SELECT_DISC) +COMPATIBLE_IOCTL(CDROM_MEDIA_CHANGED) +COMPATIBLE_IOCTL(CDROM_DRIVE_STATUS) +COMPATIBLE_IOCTL(CDROM_DISC_STATUS) +COMPATIBLE_IOCTL(CDROM_CHANGER_NSLOTS) +COMPATIBLE_IOCTL(CDROM_LOCKDOOR) +COMPATIBLE_IOCTL(CDROM_DEBUG) +COMPATIBLE_IOCTL(CDROM_GET_CAPABILITY) +/* Big L */ +COMPATIBLE_IOCTL(LOOP_SET_FD) +COMPATIBLE_IOCTL(LOOP_CLR_FD) +/* Big Q for sound/OSS */ +COMPATIBLE_IOCTL(SNDCTL_SEQ_RESET) +COMPATIBLE_IOCTL(SNDCTL_SEQ_SYNC) +COMPATIBLE_IOCTL(SNDCTL_SYNTH_INFO) +COMPATIBLE_IOCTL(SNDCTL_SEQ_CTRLRATE) +COMPATIBLE_IOCTL(SNDCTL_SEQ_GETOUTCOUNT) +COMPATIBLE_IOCTL(SNDCTL_SEQ_GETINCOUNT) +COMPATIBLE_IOCTL(SNDCTL_SEQ_PERCMODE) +COMPATIBLE_IOCTL(SNDCTL_FM_LOAD_INSTR) +COMPATIBLE_IOCTL(SNDCTL_SEQ_TESTMIDI) +COMPATIBLE_IOCTL(SNDCTL_SEQ_RESETSAMPLES) +COMPATIBLE_IOCTL(SNDCTL_SEQ_NRSYNTHS) +COMPATIBLE_IOCTL(SNDCTL_SEQ_NRMIDIS) +COMPATIBLE_IOCTL(SNDCTL_MIDI_INFO) +COMPATIBLE_IOCTL(SNDCTL_SEQ_THRESHOLD) +COMPATIBLE_IOCTL(SNDCTL_SYNTH_MEMAVL) +COMPATIBLE_IOCTL(SNDCTL_FM_4OP_ENABLE) +COMPATIBLE_IOCTL(SNDCTL_SEQ_PANIC) +COMPATIBLE_IOCTL(SNDCTL_SEQ_OUTOFBAND) +COMPATIBLE_IOCTL(SNDCTL_SEQ_GETTIME) +COMPATIBLE_IOCTL(SNDCTL_SYNTH_ID) +COMPATIBLE_IOCTL(SNDCTL_SYNTH_CONTROL) +COMPATIBLE_IOCTL(SNDCTL_SYNTH_REMOVESAMPLE) +/* Big T for sound/OSS */ +COMPATIBLE_IOCTL(SNDCTL_TMR_TIMEBASE) +COMPATIBLE_IOCTL(SNDCTL_TMR_START) +COMPATIBLE_IOCTL(SNDCTL_TMR_STOP) +COMPATIBLE_IOCTL(SNDCTL_TMR_CONTINUE) +COMPATIBLE_IOCTL(SNDCTL_TMR_TEMPO) +COMPATIBLE_IOCTL(SNDCTL_TMR_SOURCE) +COMPATIBLE_IOCTL(SNDCTL_TMR_METRONOME) +COMPATIBLE_IOCTL(SNDCTL_TMR_SELECT) +/* Little m for sound/OSS */ +COMPATIBLE_IOCTL(SNDCTL_MIDI_PRETIME) +COMPATIBLE_IOCTL(SNDCTL_MIDI_MPUMODE) +COMPATIBLE_IOCTL(SNDCTL_MIDI_MPUCMD) +/* Big P for sound/OSS */ +COMPATIBLE_IOCTL(SNDCTL_DSP_RESET) +COMPATIBLE_IOCTL(SNDCTL_DSP_SYNC) +COMPATIBLE_IOCTL(SNDCTL_DSP_SPEED) +COMPATIBLE_IOCTL(SNDCTL_DSP_STEREO) +COMPATIBLE_IOCTL(SNDCTL_DSP_GETBLKSIZE) +COMPATIBLE_IOCTL(SNDCTL_DSP_CHANNELS) +COMPATIBLE_IOCTL(SOUND_PCM_WRITE_FILTER) +COMPATIBLE_IOCTL(SNDCTL_DSP_POST) +COMPATIBLE_IOCTL(SNDCTL_DSP_SUBDIVIDE) +COMPATIBLE_IOCTL(SNDCTL_DSP_SETFRAGMENT) +COMPATIBLE_IOCTL(SNDCTL_DSP_GETFMTS) +COMPATIBLE_IOCTL(SNDCTL_DSP_SETFMT) +COMPATIBLE_IOCTL(SNDCTL_DSP_GETOSPACE) +COMPATIBLE_IOCTL(SNDCTL_DSP_GETISPACE) +COMPATIBLE_IOCTL(SNDCTL_DSP_NONBLOCK) +COMPATIBLE_IOCTL(SNDCTL_DSP_GETCAPS) +COMPATIBLE_IOCTL(SNDCTL_DSP_GETTRIGGER) +COMPATIBLE_IOCTL(SNDCTL_DSP_SETTRIGGER) +COMPATIBLE_IOCTL(SNDCTL_DSP_GETIPTR) +COMPATIBLE_IOCTL(SNDCTL_DSP_GETOPTR) +/* SNDCTL_DSP_MAPINBUF, XXX needs translation */ +/* SNDCTL_DSP_MAPOUTBUF, XXX needs translation */ +COMPATIBLE_IOCTL(SNDCTL_DSP_SETSYNCRO) +COMPATIBLE_IOCTL(SNDCTL_DSP_SETDUPLEX) +COMPATIBLE_IOCTL(SNDCTL_DSP_GETODELAY) +COMPATIBLE_IOCTL(SNDCTL_DSP_PROFILE) +COMPATIBLE_IOCTL(SOUND_PCM_READ_RATE) +COMPATIBLE_IOCTL(SOUND_PCM_READ_CHANNELS) +COMPATIBLE_IOCTL(SOUND_PCM_READ_BITS) +COMPATIBLE_IOCTL(SOUND_PCM_READ_FILTER) +/* Big C for sound/OSS */ +COMPATIBLE_IOCTL(SNDCTL_COPR_RESET) +COMPATIBLE_IOCTL(SNDCTL_COPR_LOAD) +COMPATIBLE_IOCTL(SNDCTL_COPR_RDATA) +COMPATIBLE_IOCTL(SNDCTL_COPR_RCODE) +COMPATIBLE_IOCTL(SNDCTL_COPR_WDATA) +COMPATIBLE_IOCTL(SNDCTL_COPR_WCODE) +COMPATIBLE_IOCTL(SNDCTL_COPR_RUN) +COMPATIBLE_IOCTL(SNDCTL_COPR_HALT) +COMPATIBLE_IOCTL(SNDCTL_COPR_SENDMSG) +COMPATIBLE_IOCTL(SNDCTL_COPR_RCVMSG) +/* Big M for sound/OSS */ +COMPATIBLE_IOCTL(SOUND_MIXER_READ_VOLUME) +COMPATIBLE_IOCTL(SOUND_MIXER_READ_BASS) +COMPATIBLE_IOCTL(SOUND_MIXER_READ_TREBLE) +COMPATIBLE_IOCTL(SOUND_MIXER_READ_SYNTH) +COMPATIBLE_IOCTL(SOUND_MIXER_READ_PCM) +COMPATIBLE_IOCTL(SOUND_MIXER_READ_SPEAKER) +COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE) +COMPATIBLE_IOCTL(SOUND_MIXER_READ_MIC) +COMPATIBLE_IOCTL(SOUND_MIXER_READ_CD) +COMPATIBLE_IOCTL(SOUND_MIXER_READ_IMIX) +COMPATIBLE_IOCTL(SOUND_MIXER_READ_ALTPCM) +COMPATIBLE_IOCTL(SOUND_MIXER_READ_RECLEV) +COMPATIBLE_IOCTL(SOUND_MIXER_READ_IGAIN) +COMPATIBLE_IOCTL(SOUND_MIXER_READ_OGAIN) +COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE1) +COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE2) +COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE3) +COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL1)) +COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL2)) +COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL3)) +COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_PHONEIN)) +COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_PHONEOUT)) +COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_VIDEO)) +COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_RADIO)) +COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_MONITOR)) +COMPATIBLE_IOCTL(SOUND_MIXER_MUTE) +/* SOUND_MIXER_READ_ENHANCE, same value as READ_MUTE */ +/* SOUND_MIXER_READ_LOUD, same value as READ_MUTE */ +COMPATIBLE_IOCTL(SOUND_MIXER_READ_RECSRC) +COMPATIBLE_IOCTL(SOUND_MIXER_READ_DEVMASK) +COMPATIBLE_IOCTL(SOUND_MIXER_READ_RECMASK) +COMPATIBLE_IOCTL(SOUND_MIXER_READ_STEREODEVS) +COMPATIBLE_IOCTL(SOUND_MIXER_READ_CAPS) +COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_VOLUME) +COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_BASS) +COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_TREBLE) +COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_SYNTH) +COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_PCM) +COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_SPEAKER) +COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE) +COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_MIC) +COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_CD) +COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_IMIX) +COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_ALTPCM) +COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_RECLEV) +COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_IGAIN) +COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_OGAIN) +COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE1) +COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE2) +COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE3) +COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_DIGITAL1)) +COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_DIGITAL2)) +COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_DIGITAL3)) +COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_PHONEIN)) +COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_PHONEOUT)) +COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_VIDEO)) +COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_RADIO)) +COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_MONITOR)) +COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_MUTE) +/* SOUND_MIXER_WRITE_ENHANCE, same value as WRITE_MUTE */ +/* SOUND_MIXER_WRITE_LOUD, same value as WRITE_MUTE */ +COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_RECSRC) +COMPATIBLE_IOCTL(SOUND_MIXER_INFO) +COMPATIBLE_IOCTL(SOUND_OLD_MIXER_INFO) +COMPATIBLE_IOCTL(SOUND_MIXER_ACCESS) +COMPATIBLE_IOCTL(SOUND_MIXER_AGC) +COMPATIBLE_IOCTL(SOUND_MIXER_3DSE) +COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE1) +COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE2) +COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE3) +COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE4) +COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE5) +COMPATIBLE_IOCTL(SOUND_MIXER_GETLEVELS) +COMPATIBLE_IOCTL(SOUND_MIXER_SETLEVELS) +COMPATIBLE_IOCTL(OSS_GETVERSION) +/* AUTOFS */ +COMPATIBLE_IOCTL(AUTOFS_IOC_READY) +COMPATIBLE_IOCTL(AUTOFS_IOC_FAIL) +COMPATIBLE_IOCTL(AUTOFS_IOC_CATATONIC) +COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOVER) +COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE) +/* DEVFS */ +COMPATIBLE_IOCTL(DEVFSDIOC_GET_PROTO_REV) +COMPATIBLE_IOCTL(DEVFSDIOC_SET_EVENT_MASK) +COMPATIBLE_IOCTL(DEVFSDIOC_RELEASE_EVENT_QUEUE) +COMPATIBLE_IOCTL(DEVFSDIOC_SET_DEBUG_MASK) +/* Raw devices */ +COMPATIBLE_IOCTL(RAW_SETBIND) +COMPATIBLE_IOCTL(RAW_GETBIND) +/* SMB ioctls which do not need any translations */ +COMPATIBLE_IOCTL(SMB_IOC_NEWCONN) +/* Little a */ +COMPATIBLE_IOCTL(ATMSIGD_CTRL) +COMPATIBLE_IOCTL(ATMARPD_CTRL) +COMPATIBLE_IOCTL(ATMLEC_CTRL) +COMPATIBLE_IOCTL(ATMLEC_MCAST) +COMPATIBLE_IOCTL(ATMLEC_DATA) +COMPATIBLE_IOCTL(ATM_SETSC) +COMPATIBLE_IOCTL(SIOCSIFATMTCP) +COMPATIBLE_IOCTL(SIOCMKCLIP) +COMPATIBLE_IOCTL(ATMARP_MKIP) +COMPATIBLE_IOCTL(ATMARP_SETENTRY) +COMPATIBLE_IOCTL(ATMARP_ENCAP) +COMPATIBLE_IOCTL(ATMTCP_CREATE) +COMPATIBLE_IOCTL(ATMTCP_REMOVE) +COMPATIBLE_IOCTL(ATMMPC_CTRL) +COMPATIBLE_IOCTL(ATMMPC_DATA) +#if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE) +/* 0xfe - lvm */ +COMPATIBLE_IOCTL(VG_SET_EXTENDABLE) +COMPATIBLE_IOCTL(VG_STATUS_GET_COUNT) +COMPATIBLE_IOCTL(VG_STATUS_GET_NAMELIST) +COMPATIBLE_IOCTL(VG_REMOVE) +COMPATIBLE_IOCTL(VG_RENAME) +COMPATIBLE_IOCTL(VG_REDUCE) +COMPATIBLE_IOCTL(PE_LOCK_UNLOCK) +COMPATIBLE_IOCTL(PV_FLUSH) +COMPATIBLE_IOCTL(LVM_LOCK_LVM) +COMPATIBLE_IOCTL(LVM_GET_IOP_VERSION) +#ifdef LVM_TOTAL_RESET +COMPATIBLE_IOCTL(LVM_RESET) +#endif +COMPATIBLE_IOCTL(LV_SET_ACCESS) +COMPATIBLE_IOCTL(LV_SET_STATUS) +COMPATIBLE_IOCTL(LV_SET_ALLOCATION) +COMPATIBLE_IOCTL(LE_REMAP) +COMPATIBLE_IOCTL(LV_BMAP) +COMPATIBLE_IOCTL(LV_SNAPSHOT_USE_RATE) +#endif /* LVM */ +#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) +COMPATIBLE_IOCTL(DRM_IOCTL_GET_MAGIC) +COMPATIBLE_IOCTL(DRM_IOCTL_IRQ_BUSID) +COMPATIBLE_IOCTL(DRM_IOCTL_AUTH_MAGIC) +COMPATIBLE_IOCTL(DRM_IOCTL_BLOCK) +COMPATIBLE_IOCTL(DRM_IOCTL_UNBLOCK) +COMPATIBLE_IOCTL(DRM_IOCTL_CONTROL) +COMPATIBLE_IOCTL(DRM_IOCTL_ADD_BUFS) +COMPATIBLE_IOCTL(DRM_IOCTL_MARK_BUFS) +COMPATIBLE_IOCTL(DRM_IOCTL_ADD_CTX) +COMPATIBLE_IOCTL(DRM_IOCTL_RM_CTX) +COMPATIBLE_IOCTL(DRM_IOCTL_MOD_CTX) +COMPATIBLE_IOCTL(DRM_IOCTL_GET_CTX) +COMPATIBLE_IOCTL(DRM_IOCTL_SWITCH_CTX) +COMPATIBLE_IOCTL(DRM_IOCTL_NEW_CTX) +COMPATIBLE_IOCTL(DRM_IOCTL_ADD_DRAW) +COMPATIBLE_IOCTL(DRM_IOCTL_RM_DRAW) +COMPATIBLE_IOCTL(DRM_IOCTL_LOCK) +COMPATIBLE_IOCTL(DRM_IOCTL_UNLOCK) +COMPATIBLE_IOCTL(DRM_IOCTL_FINISH) +#endif /* DRM */ +/* elevator */ +COMPATIBLE_IOCTL(BLKELVGET) +COMPATIBLE_IOCTL(BLKELVSET) +/* And these ioctls need translation */ +HANDLE_IOCTL(TIOCGSERIAL, do_tiocgserial) +HANDLE_IOCTL(SIOCGIFNAME, dev_ifname32) +HANDLE_IOCTL(SIOCGIFCONF, dev_ifconf) +HANDLE_IOCTL(SIOCGIFFLAGS, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFFLAGS, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFMETRIC, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFMETRIC, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFMTU, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFMTU, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFMEM, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFMEM, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFHWADDR, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFHWADDR, dev_ifsioc) +HANDLE_IOCTL(SIOCADDMULTI, dev_ifsioc) +HANDLE_IOCTL(SIOCDELMULTI, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFINDEX, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFMAP, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFMAP, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFADDR, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFADDR, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFBRDADDR, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFBRDADDR, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFDSTADDR, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFDSTADDR, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFNETMASK, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFNETMASK, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFPFLAGS, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFPFLAGS, dev_ifsioc) +HANDLE_IOCTL(SIOCGPPPSTATS, dev_ifsioc) +HANDLE_IOCTL(SIOCGPPPCSTATS, dev_ifsioc) +HANDLE_IOCTL(SIOCGPPPVER, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFTXQLEN, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFTXQLEN, dev_ifsioc) +HANDLE_IOCTL(SIOCADDRT, routing_ioctl) +HANDLE_IOCTL(SIOCDELRT, routing_ioctl) +/* Note SIOCRTMSG is no longer, so this is safe and * the user would have seen just an -EINVAL anyways. */ +HANDLE_IOCTL(SIOCRTMSG, ret_einval) +HANDLE_IOCTL(SIOCGSTAMP, do_siocgstamp) +HANDLE_IOCTL(HDIO_GETGEO, hdio_getgeo) +HANDLE_IOCTL(BLKRAGET, w_long) +HANDLE_IOCTL(BLKGETSIZE, w_long) +HANDLE_IOCTL(0x1260, broken_blkgetsize) +HANDLE_IOCTL(BLKFRAGET, w_long) +HANDLE_IOCTL(BLKSECTGET, w_long) +HANDLE_IOCTL(BLKPG, blkpg_ioctl_trans) + +HANDLE_IOCTL(FBIOGET_FSCREENINFO, fb_ioctl_trans) +HANDLE_IOCTL(FBIOGETCMAP, fb_ioctl_trans) +HANDLE_IOCTL(FBIOPUTCMAP, fb_ioctl_trans) + +HANDLE_IOCTL(HDIO_GET_KEEPSETTINGS, hdio_ioctl_trans) +HANDLE_IOCTL(HDIO_GET_UNMASKINTR, hdio_ioctl_trans) +HANDLE_IOCTL(HDIO_GET_DMA, hdio_ioctl_trans) +HANDLE_IOCTL(HDIO_GET_32BIT, hdio_ioctl_trans) +HANDLE_IOCTL(HDIO_GET_MULTCOUNT, hdio_ioctl_trans) +HANDLE_IOCTL(HDIO_GET_NOWERR, hdio_ioctl_trans) +HANDLE_IOCTL(HDIO_GET_NICE, hdio_ioctl_trans) +HANDLE_IOCTL(FDSETPRM32, fd_ioctl_trans) +HANDLE_IOCTL(FDDEFPRM32, fd_ioctl_trans) +HANDLE_IOCTL(FDGETPRM32, fd_ioctl_trans) +HANDLE_IOCTL(FDSETDRVPRM32, fd_ioctl_trans) +HANDLE_IOCTL(FDGETDRVPRM32, fd_ioctl_trans) +HANDLE_IOCTL(FDGETDRVSTAT32, fd_ioctl_trans) +HANDLE_IOCTL(FDPOLLDRVSTAT32, fd_ioctl_trans) +HANDLE_IOCTL(FDGETFDCSTAT32, fd_ioctl_trans) +HANDLE_IOCTL(FDWERRORGET32, fd_ioctl_trans) +HANDLE_IOCTL(PPPIOCGIDLE32, ppp_ioctl_trans) +HANDLE_IOCTL(PPPIOCSCOMPRESS32, ppp_ioctl_trans) +HANDLE_IOCTL(MTIOCGET32, mt_ioctl_trans) +HANDLE_IOCTL(MTIOCPOS32, mt_ioctl_trans) +HANDLE_IOCTL(MTIOCGETCONFIG32, mt_ioctl_trans) +HANDLE_IOCTL(MTIOCSETCONFIG32, mt_ioctl_trans) +HANDLE_IOCTL(CDROMREADMODE2, cdrom_ioctl_trans) +HANDLE_IOCTL(CDROMREADMODE1, cdrom_ioctl_trans) +HANDLE_IOCTL(CDROMREADRAW, cdrom_ioctl_trans) +HANDLE_IOCTL(CDROMREADCOOKED, cdrom_ioctl_trans) +HANDLE_IOCTL(CDROMREADAUDIO, cdrom_ioctl_trans) +HANDLE_IOCTL(CDROMREADALL, cdrom_ioctl_trans) +HANDLE_IOCTL(CDROM_SEND_PACKET, cdrom_ioctl_trans) +HANDLE_IOCTL(LOOP_SET_STATUS, loop_status) +HANDLE_IOCTL(LOOP_GET_STATUS, loop_status) +#define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int) +HANDLE_IOCTL(AUTOFS_IOC_SETTIMEOUT32, ioc_settimeout) +#ifdef CONFIG_VT +HANDLE_IOCTL(PIO_FONTX, do_fontx_ioctl) +HANDLE_IOCTL(GIO_FONTX, do_fontx_ioctl) +HANDLE_IOCTL(PIO_UNIMAP, do_unimap_ioctl) +HANDLE_IOCTL(GIO_UNIMAP, do_unimap_ioctl) +HANDLE_IOCTL(KDFONTOP, do_kdfontop_ioctl) +#endif +HANDLE_IOCTL(EXT2_IOC32_GETFLAGS, do_ext2_ioctl) +HANDLE_IOCTL(EXT2_IOC32_SETFLAGS, do_ext2_ioctl) +HANDLE_IOCTL(EXT2_IOC32_GETVERSION, do_ext2_ioctl) +HANDLE_IOCTL(EXT2_IOC32_SETVERSION, do_ext2_ioctl) +#if 0 +/* One SMB ioctl needs translations. */ +#define SMB_IOC_GETMOUNTUID_32 _IOR('u', 1, __kernel_uid_t32) +HANDLE_IOCTL(SMB_IOC_GETMOUNTUID_32, do_smb_getmountuid) +#endif +HANDLE_IOCTL(ATM_GETLINKRATE32, do_atm_ioctl) +HANDLE_IOCTL(ATM_GETNAMES32, do_atm_ioctl) +HANDLE_IOCTL(ATM_GETTYPE32, do_atm_ioctl) +HANDLE_IOCTL(ATM_GETESI32, do_atm_ioctl) +HANDLE_IOCTL(ATM_GETADDR32, do_atm_ioctl) +HANDLE_IOCTL(ATM_RSTADDR32, do_atm_ioctl) +HANDLE_IOCTL(ATM_ADDADDR32, do_atm_ioctl) +HANDLE_IOCTL(ATM_DELADDR32, do_atm_ioctl) +HANDLE_IOCTL(ATM_GETCIRANGE32, do_atm_ioctl) +HANDLE_IOCTL(ATM_SETCIRANGE32, do_atm_ioctl) +HANDLE_IOCTL(ATM_SETESI32, do_atm_ioctl) +HANDLE_IOCTL(ATM_SETESIF32, do_atm_ioctl) +HANDLE_IOCTL(ATM_GETSTAT32, do_atm_ioctl) +HANDLE_IOCTL(ATM_GETSTATZ32, do_atm_ioctl) +HANDLE_IOCTL(ATM_GETLOOP32, do_atm_ioctl) +HANDLE_IOCTL(ATM_SETLOOP32, do_atm_ioctl) +HANDLE_IOCTL(ATM_QUERYLOOP32, do_atm_ioctl) +HANDLE_IOCTL(SONET_GETSTAT, do_atm_ioctl) +HANDLE_IOCTL(SONET_GETSTATZ, do_atm_ioctl) +HANDLE_IOCTL(SONET_GETDIAG, do_atm_ioctl) +HANDLE_IOCTL(SONET_SETDIAG, do_atm_ioctl) +HANDLE_IOCTL(SONET_CLRDIAG, do_atm_ioctl) +HANDLE_IOCTL(SONET_SETFRAMING, do_atm_ioctl) +HANDLE_IOCTL(SONET_GETFRAMING, do_atm_ioctl) +HANDLE_IOCTL(SONET_GETFRSENSE, do_atm_ioctl) +#if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE) +HANDLE_IOCTL(VG_STATUS, do_lvm_ioctl) +HANDLE_IOCTL(VG_CREATE_OLD, do_lvm_ioctl) +HANDLE_IOCTL(VG_CREATE, do_lvm_ioctl) +HANDLE_IOCTL(VG_EXTEND, do_lvm_ioctl) +HANDLE_IOCTL(LV_CREATE, do_lvm_ioctl) +HANDLE_IOCTL(LV_REMOVE, do_lvm_ioctl) +HANDLE_IOCTL(LV_EXTEND, do_lvm_ioctl) +HANDLE_IOCTL(LV_REDUCE, do_lvm_ioctl) +HANDLE_IOCTL(LV_RENAME, do_lvm_ioctl) +HANDLE_IOCTL(LV_STATUS_BYNAME, do_lvm_ioctl) +HANDLE_IOCTL(LV_STATUS_BYINDEX, do_lvm_ioctl) +HANDLE_IOCTL(LV_STATUS_BYDEV, do_lvm_ioctl) +HANDLE_IOCTL(PV_CHANGE, do_lvm_ioctl) +HANDLE_IOCTL(PV_STATUS, do_lvm_ioctl) +#endif /* LVM */ +#if defined(CONFIG_GENRTC) +COMPATIBLE_IOCTL(RTC_AIE_ON) +COMPATIBLE_IOCTL(RTC_AIE_OFF) +COMPATIBLE_IOCTL(RTC_UIE_ON) +COMPATIBLE_IOCTL(RTC_UIE_OFF) +COMPATIBLE_IOCTL(RTC_PIE_ON) +COMPATIBLE_IOCTL(RTC_PIE_OFF) +COMPATIBLE_IOCTL(RTC_WIE_ON) +COMPATIBLE_IOCTL(RTC_WIE_OFF) +COMPATIBLE_IOCTL(RTC_ALM_SET) /* struct rtc_time only has ints */ +COMPATIBLE_IOCTL(RTC_ALM_READ) /* struct rtc_time only has ints */ +COMPATIBLE_IOCTL(RTC_RD_TIME) /* struct rtc_time only has ints */ +COMPATIBLE_IOCTL(RTC_SET_TIME) /* struct rtc_time only has ints */ +HANDLE_IOCTL(RTC_IRQP_READ, w_long) +COMPATIBLE_IOCTL(RTC_IRQP_SET) +HANDLE_IOCTL(RTC_EPOCH_READ, w_long) +COMPATIBLE_IOCTL(RTC_EPOCH_SET) +#endif +#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) +HANDLE_IOCTL(DRM32_IOCTL_VERSION, drm32_version); +HANDLE_IOCTL(DRM32_IOCTL_GET_UNIQUE, drm32_getsetunique); +HANDLE_IOCTL(DRM32_IOCTL_SET_UNIQUE, drm32_getsetunique); +HANDLE_IOCTL(DRM32_IOCTL_ADD_MAP, drm32_addmap); +HANDLE_IOCTL(DRM32_IOCTL_INFO_BUFS, drm32_info_bufs); +HANDLE_IOCTL(DRM32_IOCTL_FREE_BUFS, drm32_free_bufs); +HANDLE_IOCTL(DRM32_IOCTL_MAP_BUFS, drm32_map_bufs); +HANDLE_IOCTL(DRM32_IOCTL_DMA, drm32_dma); +HANDLE_IOCTL(DRM32_IOCTL_RES_CTX, drm32_res_ctx); +#endif /* DRM */ +COMPATIBLE_IOCTL(PA_PERF_ON) +COMPATIBLE_IOCTL(PA_PERF_OFF) +COMPATIBLE_IOCTL(PA_PERF_VERSION) +IOCTL_TABLE_END + +unsigned int ioctl32_hash_table[1024]; + +extern inline unsigned long ioctl32_hash(unsigned long cmd) +{ + return ((cmd >> 6) ^ (cmd >> 4) ^ cmd) & 0x3ff; +} + +static void ioctl32_insert_translation(struct ioctl_trans *trans) +{ + unsigned long hash; + struct ioctl_trans *t; + + hash = ioctl32_hash (trans->cmd); + if (!ioctl32_hash_table[hash]) + ioctl32_hash_table[hash] = (u32)(long)trans; + else { + t = (struct ioctl_trans *)(long)ioctl32_hash_table[hash]; + while (t->next) + t = (struct ioctl_trans *)(long)t->next; + trans->next = 0; + t->next = (u32)(long)trans; + } +} + +static int __init init_sys32_ioctl(void) +{ + int i; + extern struct ioctl_trans ioctl_translations[], ioctl_translations_end[]; + + for (i = 0; &ioctl_translations[i] < &ioctl_translations_end[0]; i++) + ioctl32_insert_translation(&ioctl_translations[i]); + return 0; +} + +__initcall(init_sys32_ioctl); + +static struct ioctl_trans *additional_ioctls; + +/* Always call these with kernel lock held! */ + +int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, unsigned int, unsigned long, struct file *)) +{ + int i; + +panic("register_ioctl32_conversion() is B0RKEN! Called by %p\n", __builtin_return_address(0)); + + if (!additional_ioctls) { + additional_ioctls = module_map(PAGE_SIZE); + if (!additional_ioctls) + return -ENOMEM; + memset(additional_ioctls, 0, PAGE_SIZE); + } + for (i = 0; i < PAGE_SIZE/sizeof(struct ioctl_trans); i++) + if (!additional_ioctls[i].cmd) + break; + if (i == PAGE_SIZE/sizeof(struct ioctl_trans)) + return -ENOMEM; + additional_ioctls[i].cmd = cmd; + if (!handler) + additional_ioctls[i].handler = (u32)(long)sys_ioctl; + else + additional_ioctls[i].handler = (u32)(long)handler; + ioctl32_insert_translation(&additional_ioctls[i]); + return 0; +} + +int unregister_ioctl32_conversion(unsigned int cmd) +{ + unsigned long hash = ioctl32_hash(cmd); + struct ioctl_trans *t, *t1; + + t = (struct ioctl_trans *)(long)ioctl32_hash_table[hash]; + if (!t) return -EINVAL; + if (t->cmd == cmd && t >= additional_ioctls && + (unsigned long)t < ((unsigned long)additional_ioctls) + PAGE_SIZE) { + ioctl32_hash_table[hash] = t->next; + t->cmd = 0; + return 0; + } else while (t->next) { + t1 = (struct ioctl_trans *)(long)t->next; + if (t1->cmd == cmd && t1 >= additional_ioctls && + (unsigned long)t1 < ((unsigned long)additional_ioctls) + PAGE_SIZE) { + t1->cmd = 0; + t->next = t1->next; + return 0; + } + t = t1; + } + return -EINVAL; +} + +asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct file * filp; + int (*handler)(unsigned int, unsigned int, unsigned long, struct file * filp); + unsigned long pafnptr[4]; + extern char __gp; + struct ioctl_trans *t; + int error = -EBADF; + + filp = fget(fd); + if(!filp) + goto out2; + + if (!filp->f_op || !filp->f_op->ioctl) { + error = sys_ioctl (fd, cmd, arg); + goto out; + } + + /* intercept private networking ioctl() calls here since it is + * an onerous task to figure out which ones of the HANDLE_IOCTL + * list map to these values. + */ + if (cmd >= SIOCDEVPRIVATE && cmd <= SIOCDEVPRIVATE + 0xf) { + error = siocprivate(fd, cmd, arg); + goto out; + } + + t = (struct ioctl_trans *)(long)ioctl32_hash_table [ioctl32_hash (cmd)]; + + while (t && t->cmd != cmd) + t = (struct ioctl_trans *)(long)t->next; + if (t) { + handler = (void *) pafnptr; + pafnptr[0] = pafnptr[1] = 0UL; + pafnptr[2] = (unsigned long) t->handler; + pafnptr[3] = A(&__gp); + error = handler(fd, cmd, arg, filp); + } else { + static int count = 0; + if (++count <= 20) + printk(KERN_WARNING + "sys32_ioctl: Unknown cmd fd(%d) " + "cmd(%08x) arg(%08x)\n", + (int)fd, (unsigned int)cmd, (unsigned int)arg); + error = -EINVAL; + } +out: + fput(filp); +out2: + return error; +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/iosapic.c linux.19rc3-ac4/arch/parisc/kernel/iosapic.c --- linux.19rc3/arch/parisc/kernel/iosapic.c 2002-07-29 12:50:06.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/iosapic.c 2002-07-29 13:58:36.000000000 +0100 @@ -169,11 +169,13 @@ #include /* get in-line asm for swab */ #include -#include #include #include #include #include /* gsc_read/write functions */ +#ifdef CONFIG_SUPERIO +#include +#endif #include #include "./iosapic_private.h" @@ -181,7 +183,6 @@ #define MODULE_NAME "iosapic" /* "local" compile flags */ -#undef IOSAPIC_CALLBACK #undef PCI_BRIDGE_FUNCS #undef DEBUG_IOSAPIC #undef DEBUG_IOSAPIC_IRT @@ -282,28 +283,6 @@ #define IOSAPIC_EOI(eoi_addr, eoi_data) gsc_writel(eoi_data, eoi_addr) -#if IOSAPIC_CALLBACK -/* -** Shouldn't use callback since SAPIC doesn't have an officially assigned -** H or S version numbers. Slight long term risk the number chosen would -** collide with something else. -** But benefit is cleaner lba/sapic interface. -** Might be worth it but for just use direct calls for now. -** -** Entry below is copied from lba driver. -** Only thing different is hw_type. -*/ -static struct pa_iodc_driver iosapic_driver_for[] = { - {HPHW_OTHER, 0x782, 0, 0x0000A, 0, 0x00, - DRIVER_CHECK_HWTYPE + DRIVER_CHECK_HVERSION + DRIVER_CHECK_SVERSION, - "I/O Sapic", "",(void *) iosapic_callback}, - {0,0,0,0,0,0, - 0, - (char *) NULL,(char *) NULL,(void *) NULL} -}; -#endif /* IOSAPIO_CALLBACK */ - - static struct iosapic_info *iosapic_list; static spinlock_t iosapic_lock; static int iosapic_count; @@ -350,25 +329,22 @@ static int __init /* return number of entries as success/fail flag */ iosapic_load_irt(unsigned long cell_num, struct irt_entry **irt) { - struct pdc_pat_io_num pdc_io_num; /* PAT PDC return block */ long status; /* PDC return value status */ - struct irt_entry *table = NULL; /* start of interrupt routing tbl */ + struct irt_entry *table; /* start of interrupt routing tbl */ unsigned long num_entries = 0UL; ASSERT(NULL != irt); - /* FIXME ASSERT(((&pdc_io_num) & (0x3f)) == 0); enforce 32-byte alignment */ - /* Try PAT_PDC to get interrupt routing table size */ - DBG(KERN_DEBUG "calling get_irt_size\n"); - status = pdc_pat_get_irt_size( &pdc_io_num, cell_num); - DBG(KERN_DEBUG "get_irt_size: %ld\n", status); + if (is_pdc_pat()) { - switch(status) { + /* Use pat pdc routine to get interrupt routing table size */ + DBG("calling get_irt_size (cell %ld)\n", cell_num); + status = pdc_pat_get_irt_size(&num_entries, cell_num); + DBG("get_irt_size: %ld\n", status); - case PDC_RET_OK: /* PAT box. Proceed to get the IRT */ + ASSERT(status == PDC_OK); /* save the number of entries in the table */ - num_entries = pdc_io_num.num; ASSERT(0UL != num_entries); /* @@ -384,30 +360,27 @@ } /* get PCI INT routing table */ - status = pdc_pat_get_irt( (void *) table, cell_num); - DBG(KERN_DEBUG "pdc_pat_get_irt: %ld\n", status); - ASSERT(status == PDC_RET_OK); - break; - - case PDC_RET_NE_PROC: /* Not a PAT platform. Try PDC_PCI extensions */ + status = pdc_pat_get_irt(table, cell_num); + DBG("pdc_pat_get_irt: %ld\n", status); + ASSERT(status == PDC_OK); + } else { /* - ** C3000/J5000 (and similar) platforms with "legacy" PDC - ** will return exactly one IRT. + ** C3000/J5000 (and similar) platforms with Sprockets PDC + ** will return exactly one IRT for all iosapics. ** So if we have one, don't need to get it again. */ if (NULL != irt_cell) - break; + return 0; - status = pdc_pci_irt_size( (void *)&pdc_io_num, - /* elroy HPA (really a NOP) */ 0); - DBG(KERN_WARNING "pdc_pci_irt_size: %ld\n", status); + /* Should be using the Elroy's HPA, but it's ignored anyway */ + status = pdc_pci_irt_size(&num_entries, 0); + DBG("pdc_pci_irt_size: %ld\n", status); - if (PDC_RET_OK != status) { + if (PDC_OK != status) { /* Not a "legacy" system with I/O SAPIC either */ return 0; } - num_entries = pdc_io_num.num; ASSERT(0UL != num_entries); table = IOSAPIC_KALLOC(struct irt_entry, num_entries); @@ -416,36 +389,27 @@ return 0; } - status = pdc_pci_irt( (void *) &pdc_io_num, - (void *) NULL, /* Elroy HPA - not used */ - (void *) table); - - ASSERT(PDC_RET_OK == status); - break; - - default: - printk(KERN_WARNING MODULE_NAME ": PDC_PAT_IO call failed with %ld\n", status); - break; + /* HPA ignored by this call too. */ + status = pdc_pci_irt(num_entries, 0, table); + ASSERT(PDC_OK == status); } /* return interrupt table address */ *irt = table; - #ifdef DEBUG_IOSAPIC_IRT - { +{ struct irt_entry *p = table; int i; - printk(MODULE_NAME " Interrupt Routing Table (cell %ld)\n", cell_num); - printk(MODULE_NAME " start = 0x%p num_entries %ld entry_size %d\n", + printk(KERN_DEBUG MODULE_NAME " Interrupt Routing Table (cell %ld)\n", cell_num); + printk(KERN_DEBUG MODULE_NAME " start = 0x%p num_entries %ld entry_size %d\n", table, num_entries, (int) sizeof(struct irt_entry)); - for (i = 0 ; i < num_entries ; i++, p++) - { - printk(MODULE_NAME " %02x %02x %02x %02x %02x %02x %02x %02x %08x%08x\n", + for (i = 0 ; i < num_entries ; i++, p++) { + printk(KERN_DEBUG MODULE_NAME " %02x %02x %02x %02x %02x %02x %02x %02x %08x%08x\n", p->entry_type, p->entry_length, p->interrupt_type, p->polarity_trigger, p->src_bus_irq_devno, p->src_bus_id, p->src_seg_id, p->dest_iosapic_intin, @@ -453,7 +417,7 @@ ((u32 *) p)[3] ); } - } +} #endif /* DEBUG_IOSAPIC_IRT */ return num_entries; @@ -464,6 +428,8 @@ void __init iosapic_init(void) { + unsigned long cell = 0; + /* init global data */ iosapic_lock = SPIN_LOCK_UNLOCKED; iosapic_list = (struct iosapic_info *) NULL; @@ -471,22 +437,24 @@ DBG("iosapic_init()\n"); +#ifdef __LP64__ + if (is_pdc_pat()) { + int status; + struct pdc_pat_cell_num cell_info; + + status = pdc_pat_cell_get_number(&cell_info); + if (status == PDC_OK) { + cell = cell_info.cell_num; + } + } +#endif + /* ** get IRT for this cell. */ - irt_num_entry = iosapic_load_irt(0L, &irt_cell); + irt_num_entry = iosapic_load_irt(cell, &irt_cell); if (0 == irt_num_entry) irt_cell = NULL; /* old PDC w/o iosapic */ - -#ifdef IOSAPIC_CALLBACK - /* - ** When new I/O SAPICs are discovered, this callback - ** will get invoked. Implies lba driver will register - ** I/O Sapic as a device it "discovered" with faked - ** IODC data. - */ - register_driver(iosapic_driver_for); -#endif /* IOSAPIC_CALLBACK */ } @@ -546,7 +514,7 @@ return i; } - printk(KERN_WARNING MODULE_NAME ": 0x%p : no IRT entry for slot %d, pin %d\n", + printk(KERN_WARNING MODULE_NAME ": 0x%lx : no IRT entry for slot %d, pin %d\n", isi->isi_hpa, slot, intr_pin); return NULL; } @@ -571,21 +539,18 @@ { u8 intr_pin, intr_slot; - (void) pci_read_config_byte(pcidev, PCI_INTERRUPT_PIN, &intr_pin); + pci_read_config_byte(pcidev, PCI_INTERRUPT_PIN, &intr_pin); - DBG_IRT("iosapic_xlate_pin() SLOT %d pin %d\n", PCI_SLOT(pcidev->devfn), intr_pin); + DBG_IRT("iosapic_xlate_pin() SLOT %d pin %d\n", + PCI_SLOT(pcidev->devfn), intr_pin); - if (0 == intr_pin) - { - /* - ** The device does NOT support/use IRQ lines. - */ + if (0 == intr_pin) { + /* The device does NOT support/use IRQ lines. */ return NULL; } /* Check if pcidev behind a PPB */ - if (NULL != pcidev->bus->self) - { + if (NULL != pcidev->bus->self) { /* Convert pcidev INTR_PIN into something we ** can lookup in the IRT. */ @@ -600,7 +565,7 @@ ** or by some ambitous soul who wants to watch TV. */ if (pci_bridge_funcs->xlate_intr_line) { - intr_pin = (*pci_bridge_funcs->xlate_intr_line)(pcidev); + intr_pin = pci_bridge_funcs->xlate_intr_line(pcidev); } #else /* PCI_BRIDGE_FUNCS */ struct pci_bus *p = pcidev->bus; @@ -646,8 +611,8 @@ extern void do_irq(struct irqaction *a, int i, struct pt_regs *p); int irq_num = vi->vi_ios->isi_region->data.irqbase + vi->vi_irqline; - DBG("iosapic_interrupt(): irq %d line %d eoi %p\n", irq, vi->vi_irqline, - vi->vi_eoi_addr); + DBG("iosapic_interrupt(): irq %d line %d eoi %p\n", + irq, vi->vi_irqline, vi->vi_eoi_addr); /* FIXME: Need to mask/unmask? processor IRQ is already masked... */ do_irq(&vi->vi_ios->isi_region->action[vi->vi_irqline], irq_num, regs); @@ -668,12 +633,39 @@ struct vector_info *vi; int isi_line; /* line used by device */ int tmp; + int return_irq; +#ifdef CONFIG_SUPERIO + int superio_irq = -1; +#endif if (NULL == isi) { - printk(KERN_WARNING MODULE_NAME ": 0x%p hpa not registered\n", isi->isi_hpa); + printk(KERN_WARNING MODULE_NAME ": hpa not registered for %s\n", + pcidev->name); return(-1); } +#ifdef CONFIG_SUPERIO + if (is_superio_device(pcidev)) { + superio_irq = superio_fixup_irq(pcidev); + if (superio_irq == -1) + return(-1); + + if (PCI_FUNC(pcidev->devfn) != SUPERIO_USB_FN) { + + /* + * SuperIO USB controller has an irt entry. + * Only let the USB controller hookup the rest + * of the interrupt routing when it comes through. + * Note that interrupts for all three functions + * actually come through the PIC's on function 1! + */ + + pcidev->irq = superio_irq; + return superio_irq; + } + } +#endif /* CONFIG_SUPERIO */ + /* lookup IRT entry for isi/slot/pin set */ irte = iosapic_xlate_pin(isi, pcidev); if (NULL == irte) { @@ -714,22 +706,31 @@ vi->vi_txn_data = txn_alloc_data(vi->vi_txn_irq, 8); ASSERT(vi->vi_txn_data < 256); /* matches 8 above */ - tmp = request_irq(vi->vi_txn_irq, iosapic_interrupt, 0, "iosapic", vi); + tmp = request_irq(vi->vi_txn_irq, iosapic_interrupt, 0, + vi->vi_name, vi); ASSERT(tmp == 0); - vi->vi_eoi_addr = ((void *) isi->isi_hpa) + IOSAPIC_REG_EOI; + vi->vi_eoi_addr = (u32 *) (isi->isi_hpa + IOSAPIC_REG_EOI); vi->vi_eoi_data = cpu_to_le32(vi->vi_irqline); ASSERT(NULL != isi->isi_region); - /* - ** pcidev->irq still needs to be virtualized. - */ - pcidev->irq = isi->isi_region->data.irqbase + isi_line; + /* pcidev->irq still needs to be virtualized. */ + + return_irq = isi->isi_region->data.irqbase + isi_line; - DBG_IRT("iosapic_fixup_irq() %d:%d %x %x line %d irq %d\n", PCI_SLOT(pcidev->devfn), - PCI_FUNC(pcidev->devfn), pcidev->vendor, pcidev->device, isi_line, pcidev->irq); +#ifdef CONFIG_SUPERIO + if (superio_irq != -1) { + superio_inform_irq(return_irq); + return_irq = superio_irq; + } +#endif + pcidev->irq = return_irq; + + DBG_IRT("iosapic_fixup_irq() %d:%d %x %x line %d irq %d\n", + PCI_SLOT(pcidev->devfn), + PCI_FUNC(pcidev->devfn), pcidev->vendor, pcidev->device, isi_line, return_irq); - return(pcidev->irq); + return return_irq; } @@ -755,7 +756,7 @@ struct iosapic_info *isp = vi->vi_ios; ASSERT(NULL != isp); - ASSERT(NULL != isp->isi_hpa); + ASSERT(0 != isp->isi_hpa); DBG_IRT("iosapic_wr_irt_entry(): irq %d hpa %p WINDOW %p 0x%x 0x%x\n", vi->vi_irqline, isp->isi_hpa, isp->isi_hpa+IOSAPIC_REG_WINDOW, @@ -807,16 +808,13 @@ ** Extracting id_eid isn't a real clean way of getting it. ** But the encoding is the same for both PA and IA64 platforms. */ -#ifdef __LP64__ - if (pdc_pat) { + if (is_pdc_pat()) { /* ** PAT PDC just hands it to us "right". ** vi_txn_addr comes from cpu_data[x].txn_addr. */ *dp1 = (u32) (vi->vi_txn_addr); - } else -#endif - { + } else { /* ** eg if base_addr == 0xfffa0000), ** we want to get 0xa0ff0000. @@ -886,7 +884,6 @@ /* data is initialized by fixup_irq */ ASSERT(0 < vi->vi_txn_irq); - ASSERT(0UL != vi->vi_txn_addr); ASSERT(0UL != vi->vi_txn_data); iosapic_set_irt_data(vi, &d0, &d1); @@ -895,10 +892,10 @@ #ifdef DEBUG_IOSAPIC_IRT { -u32 *t = (u32 *) ((ulong) vi->vi_eoi_addr & ~0xffUL); -printk("iosapic_enable_irq(): regs %p", vi->vi_eoi_addr); -while (t < vi->vi_eoi_addr) printk(" %x", READ_U32(t++)); -printk("\n"); + u32 *t = (u32 *) ((ulong) vi->vi_eoi_addr & ~0xffUL); + printk("iosapic_enable_irq(): regs %p", vi->vi_eoi_addr); + while (t < vi->vi_eoi_addr) printk(" %x", READ_U32(t++)); + printk("\n"); } printk("iosapic_enable_irq(): sel "); @@ -943,10 +940,10 @@ static struct irq_region_ops iosapic_irq_ops = { - iosapic_disable_irq, - iosapic_enable_irq, - iosapic_mask_irq, - iosapic_unmask_irq + disable_irq: iosapic_disable_irq, + enable_irq: iosapic_enable_irq, + mask_irq: iosapic_mask_irq, + unmask_irq: iosapic_unmask_irq }; @@ -967,15 +964,9 @@ } -#ifndef IOSAPIC_CALLBACK -/* -** iosapic_register() is the alternative to iosapic_driver_for(). -** (Only one or the other should be implemented.) -*/ - /* ** iosapic_register() is called by "drivers" with an integrated I/O SAPIC. -** Caller must be certain they have an I/O SAPIC and know it's MMIO address. +** Caller must be certain they have an I/O SAPIC and know its MMIO address. ** ** o allocate iosapic_info and add it to the list ** o read iosapic version and squirrel that away @@ -984,7 +975,7 @@ ** o allocate isi_region (registers region handlers) */ void * -iosapic_register(void *hpa) +iosapic_register(unsigned long hpa) { struct iosapic_info *isi = NULL; struct irt_entry *irte = irt_cell; @@ -1021,7 +1012,7 @@ memset(isi, 0, sizeof(struct iosapic_info)); - isi->isi_hpa = (unsigned char *) hpa; + isi->isi_hpa = hpa; isi->isi_version = iosapic_rd_version(isi); isi->isi_num_vectors = IOSAPIC_IRDT_MAX_ENTRY(isi->isi_version) + 1; @@ -1034,6 +1025,7 @@ } memset(vip, 0, sizeof(struct vector_info) * isi->isi_num_vectors); + sprintf(isi->isi_name, "IO-SAPIC%02d", iosapic_count++); /* ** Initialize vector array @@ -1041,17 +1033,16 @@ for (cnt=0; cnt < isi->isi_num_vectors; cnt++, vip++) { vip->vi_irqline = (unsigned char) cnt; vip->vi_ios = isi; + sprintf(vip->vi_name, "%s-L%d", isi->isi_name, cnt); } isi->isi_region = alloc_irq_region(isi->isi_num_vectors, - &iosapic_irq_ops, IRQ_REG_DIS|IRQ_REG_MASK, - "I/O Sapic", (void *) isi->isi_vector); + &iosapic_irq_ops, isi->isi_name, + (void *) isi->isi_vector); ASSERT(NULL != isi->isi_region); return ((void *) isi); } -#endif /* !IOSAPIC_CALLBACK */ - #ifdef DEBUG_IOSAPIC @@ -1092,8 +1083,8 @@ { ASSERT(NULL != isi); printk(KERN_DEBUG MODULE_NAME ": io_sapic_info at %p\n", isi); - printk(KERN_DEBUG "\t\tisi_hpa: %p\n", isi->isi_hpa); - printk(KERN_DEBUG "\t\tisi_satus: %x\n", isi->isi_status); + printk(KERN_DEBUG "\t\tisi_hpa: %lx\n", isi->isi_hpa); + printk(KERN_DEBUG "\t\tisi_status: %x\n", isi->isi_status); printk(KERN_DEBUG "\t\tisi_version: %x\n", isi->isi_version); printk(KERN_DEBUG "\t\tisi_vector: %p\n", isi->isi_vector); } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/iosapic_private.h linux.19rc3-ac4/arch/parisc/kernel/iosapic_private.h --- linux.19rc3/arch/parisc/kernel/iosapic_private.h 2002-07-29 12:50:06.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/iosapic_private.h 2002-07-29 13:58:36.000000000 +0100 @@ -111,22 +111,25 @@ struct irt_entry *vi_irte; /* IRT entry */ u32 *vi_eoi_addr; /* precalculate EOI reg address */ u32 vi_eoi_data; /* IA64: ? PA: swapped txn_data */ - u8 vi_status; /* status/flags */ - u8 vi_irqline; /* INTINn(IRQ) */ int vi_txn_irq; /* virtual IRQ number for processor */ ulong vi_txn_addr; /* IA64: id_eid PA: partial HPA */ ulong vi_txn_data; /* IA64: vector PA: EIR bit */ + u8 vi_status; /* status/flags */ + u8 vi_irqline; /* INTINn(IRQ) */ + char vi_name[32]; /* user visible identity */ }; struct iosapic_info { struct iosapic_info *isi_next; /* list of I/O SAPIC */ - volatile void *isi_hpa; /* physical base address */ + unsigned long isi_hpa; /* physical base address */ struct irq_region *isi_region; /* each I/O SAPIC is one region */ struct vector_info *isi_vector; /* IRdT (IRQ line) array */ int isi_num_vectors; /* size of IRdT array */ int isi_status; /* status/flags */ unsigned int isi_version; /* DEBUG: data fr version reg */ + /* round up to next cacheline */ + char isi_name[20]; /* identify region for users */ }; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/irq.c linux.19rc3-ac4/arch/parisc/kernel/irq.c --- linux.19rc3/arch/parisc/kernel/irq.c 2002-07-29 12:50:06.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/irq.c 2002-07-29 13:58:36.000000000 +0100 @@ -1,13 +1,10 @@ -/* $Id: irq.c,v 1.8 2000/02/08 02:01:17 grundler Exp $ - * +/* * Code to handle x86 style IRQs plus some generic interrupt stuff. * - * This is not in any way SMP-clean. - * * Copyright (C) 1992 Linus Torvalds * Copyright (C) 1994, 1995, 1996, 1997, 1998 Ralf Baechle - * Copyright (C) 1999 SuSE GmbH (Author: Philipp Rumpf, prumpf@tux.org) - * Copyright (C) 2000 Hewlett Packard Corp (Co-Author: Grant Grundler, grundler@cup.hp.com) + * Copyright (C) 1999 SuSE GmbH (Philipp Rumpf, prumpf@tux.org) + * Copyright (C) 1999-2000 Grant Grundler * * 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 @@ -23,138 +20,167 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include +#include #include #include #include -#include #include -#include #include #include #include #include #include +#include #include +#include #include +#include #include #undef DEBUG_IRQ +#undef PARISC_IRQ_CR16_COUNTS extern void timer_interrupt(int, void *, struct pt_regs *); extern void ipi_interrupt(int, void *, struct pt_regs *); #ifdef DEBUG_IRQ -#define DBG_IRQ(x...) printk(x) +#define DBG_IRQ(irq, x) if ((irq) != TIMER_IRQ) printk x #else /* DEBUG_IRQ */ -#define DBG_IRQ(x...) +#define DBG_IRQ(irq, x) do { } while (0) #endif /* DEBUG_IRQ */ -#define EIEM_MASK(irq) (1L<<(MAX_CPU_IRQ-IRQ_OFFSET(irq))) -#define CLEAR_EIEM_BIT(irq) set_eiem(get_eiem() & ~EIEM_MASK(irq)) -#define SET_EIEM_BIT(irq) set_eiem(get_eiem() | EIEM_MASK(irq)) +#define EIEM_MASK(irq) (1UL<<(MAX_CPU_IRQ-IRQ_OFFSET(irq))) + +/* Bits in EIEM correlate with cpu_irq_action[]. +** Numbered *Big Endian*! (ie bit 0 is MSB) +*/ +static unsigned long cpu_eiem = 0; + +static spinlock_t irq_lock = SPIN_LOCK_UNLOCKED; /* protect IRQ regions */ + +#ifdef CONFIG_SMP +static void cpu_set_eiem(void *info) +{ + set_eiem((unsigned long) info); +} +#endif -static void disable_cpu_irq(void *unused, int irq) +static inline void disable_cpu_irq(void *unused, int irq) { - CLEAR_EIEM_BIT(irq); + unsigned long eirr_bit = EIEM_MASK(irq); + + cpu_eiem &= ~eirr_bit; + set_eiem(cpu_eiem); + smp_call_function(cpu_set_eiem, (void *) cpu_eiem, 1, 1); } static void enable_cpu_irq(void *unused, int irq) { - unsigned long mask = EIEM_MASK(irq); + unsigned long eirr_bit = EIEM_MASK(irq); + + mtctl(eirr_bit, 23); /* clear EIRR bit before unmasking */ + cpu_eiem |= eirr_bit; + smp_call_function(cpu_set_eiem, (void *) cpu_eiem, 1, 1); + set_eiem(cpu_eiem); +} + +/* mask and disable are the same at the CPU level +** Difference is enable clears pending interrupts +*/ +#define mask_cpu_irq disable_cpu_irq - mtctl(mask, 23); - SET_EIEM_BIT(irq); +static inline void unmask_cpu_irq(void *unused, int irq) +{ + unsigned long eirr_bit = EIEM_MASK(irq); + cpu_eiem |= eirr_bit; + /* NOTE: sending an IPI will cause do_cpu_irq_mask() to + ** handle *any* unmasked pending interrupts. + ** ie We don't need to check for pending interrupts here. + */ + smp_call_function(cpu_set_eiem, (void *) cpu_eiem, 1, 1); + set_eiem(cpu_eiem); } static struct irqaction cpu_irq_actions[IRQ_PER_REGION] = { - [IRQ_OFFSET(TIMER_IRQ)] { timer_interrupt, 0, 0, "timer", NULL, NULL }, - [IRQ_OFFSET(IPI_IRQ)] { ipi_interrupt, 0, 0, "IPI", NULL, NULL }, + [IRQ_OFFSET(TIMER_IRQ)] { handler: timer_interrupt, name: "timer", }, +#ifdef CONFIG_SMP + [IRQ_OFFSET(IPI_IRQ)] { handler: ipi_interrupt, name: "IPI", }, +#endif }; struct irq_region cpu_irq_region = { - { disable_cpu_irq, enable_cpu_irq, NULL, NULL }, - { &cpu_data[0], "PA-PIC", IRQ_REG_MASK|IRQ_REG_DIS, IRQ_FROM_REGION(CPU_IRQ_REGION)}, - cpu_irq_actions + ops: { disable_cpu_irq, enable_cpu_irq, unmask_cpu_irq, unmask_cpu_irq }, + data: { dev: &cpu_data[0], + name: "PA-CPU-00", + irqbase: IRQ_FROM_REGION(CPU_IRQ_REGION), }, + action: cpu_irq_actions, }; struct irq_region *irq_region[NR_IRQ_REGS] = { - [ 0 ] NULL, /* abuse will data page fault (aka code 15) */ + [ 0 ] NULL, /* reserved for EISA, else causes data page fault (aka code 15) */ [ CPU_IRQ_REGION ] &cpu_irq_region, }; +/* +** Generic interfaces that device drivers can use: +** mask_irq() block IRQ +** unmask_irq() re-enable IRQ and trigger if IRQ is pending +** disable_irq() block IRQ +** enable_irq() clear pending and re-enable IRQ +*/ -/* we special-case the real IRQs here, which feels right given the relatively - * high cost of indirect calls. If anyone is bored enough to benchmark this - * and find out whether I am right, feel free to. prumpf */ - -static inline void mask_irq(int irq) +void mask_irq(int irq) { struct irq_region *region; - -#ifdef DEBUG_IRQ - if (irq != TIMER_IRQ) -#endif - DBG_IRQ("mask_irq(%d) %d+%d\n", irq, IRQ_REGION(irq), IRQ_OFFSET(irq)); - if(IRQ_REGION(irq) != CPU_IRQ_REGION) { - region = irq_region[IRQ_REGION(irq)]; - if(region->data.flags & IRQ_REG_MASK) - region->ops.mask_irq(region->data.dev, IRQ_OFFSET(irq)); - } else { - CLEAR_EIEM_BIT(irq); - } + DBG_IRQ(irq, ("mask_irq(%d) %d+%d eiem 0x%lx\n", irq, + IRQ_REGION(irq), IRQ_OFFSET(irq), cpu_eiem)); + irq = irq_cannonicalize(irq); + region = irq_region[IRQ_REGION(irq)]; + if (region->ops.mask_irq) + region->ops.mask_irq(region->data.dev, IRQ_OFFSET(irq)); } -static inline void unmask_irq(int irq) +void unmask_irq(int irq) { struct irq_region *region; -#ifdef DEBUG_IRQ - if (irq != TIMER_IRQ) -#endif - DBG_IRQ("unmask_irq(%d) %d+%d\n", irq, IRQ_REGION(irq), IRQ_OFFSET(irq)); - - if(IRQ_REGION(irq) != CPU_IRQ_REGION) { - region = irq_region[IRQ_REGION(irq)]; - if(region->data.flags & IRQ_REG_MASK) - region->ops.unmask_irq(region->data.dev, IRQ_OFFSET(irq)); - } else { - SET_EIEM_BIT(irq); - } + DBG_IRQ(irq, ("unmask_irq(%d) %d+%d eiem 0x%lx\n", irq, + IRQ_REGION(irq), IRQ_OFFSET(irq), cpu_eiem)); + irq = irq_cannonicalize(irq); + region = irq_region[IRQ_REGION(irq)]; + if (region->ops.unmask_irq) + region->ops.unmask_irq(region->data.dev, IRQ_OFFSET(irq)); } void disable_irq(int irq) { struct irq_region *region; -#ifdef DEBUG_IRQ - if (irq != TIMER_IRQ) -#endif - DBG_IRQ("disable_irq(%d) %d+%d\n", irq, IRQ_REGION(irq), IRQ_OFFSET(irq)); + DBG_IRQ(irq, ("disable_irq(%d) %d+%d eiem 0x%lx\n", irq, + IRQ_REGION(irq), IRQ_OFFSET(irq), cpu_eiem)); + irq = irq_cannonicalize(irq); region = irq_region[IRQ_REGION(irq)]; - - if(region->data.flags & IRQ_REG_DIS) + if (region->ops.disable_irq) region->ops.disable_irq(region->data.dev, IRQ_OFFSET(irq)); else BUG(); } -void enable_irq(int irq) +void enable_irq(int irq) { struct irq_region *region; -#ifdef DEBUG_IRQ - if (irq != TIMER_IRQ) -#endif - DBG_IRQ("enable_irq(%d) %d+%d\n", irq, IRQ_REGION(irq), IRQ_OFFSET(irq)); + DBG_IRQ(irq, ("enable_irq(%d) %d+%d eiem 0x%lx\n", irq, + IRQ_REGION(irq), IRQ_OFFSET(irq), cpu_eiem)); + irq = irq_cannonicalize(irq); region = irq_region[IRQ_REGION(irq)]; - if(region->data.flags & IRQ_REG_DIS) + if (region->ops.enable_irq) region->ops.enable_irq(region->data.dev, IRQ_OFFSET(irq)); else BUG(); @@ -164,30 +190,40 @@ { #ifdef CONFIG_PROC_FS char *p = buf; - int i, j; - int regnr, irq_no; - struct irq_region *region; - struct irqaction *action, *mainaction; + unsigned int regnr = 0; - p += sprintf(p, " "); - for (j=0; jaction) + unsigned int i; + struct irq_region *region = irq_region[regnr]; + + if (!region || !region->action) continue; - - mainaction = region->action; for (i = 0; i <= MAX_CPU_IRQ; i++) { - action = mainaction++; - if (!action || !action->name) - continue; - - irq_no = IRQ_FROM_REGION(regnr) + i; - + struct irqaction *action = ®ion->action[i]; + unsigned int irq_no = IRQ_FROM_REGION(regnr) + i; +#ifdef CONFIG_SMP + unsigned int j; +#endif + + if (!action->handler) + continue; + p += sprintf(p, "%3d: ", irq_no); #ifndef CONFIG_SMP p += sprintf(p, "%10u ", kstat_irqs(irq_no)); @@ -196,30 +232,48 @@ p += sprintf(p, "%10u ", kstat.irqs[cpu_logical_map(j)][irq_no]); #endif - p += sprintf(p, " %14s", + p += sprintf(p, " %14s", region->data.name ? region->data.name : "N/A"); +#ifndef PARISC_IRQ_CR16_COUNTS p += sprintf(p, " %s", action->name); - for (action=action->next; action; action = action->next) - p += sprintf(p, ", %s", action->name); - *p++ = '\n'; - } - } + while ((action = action->next)) + p += sprintf(p, ", %s", action->name); +#else + for ( ;action; action = action->next) { + unsigned int i, avg, min, max; - p += sprintf(p, "\n"); -#if CONFIG_SMP - p += sprintf(p, "LOC: "); - for (j = 0; j < smp_num_cpus; j++) - p += sprintf(p, "%10u ", - apic_timer_irqs[cpu_logical_map(j)]); - p += sprintf(p, "\n"); + min = max = action->cr16_hist[0]; + + for (avg = i = 0; i < PARISC_CR16_HIST_SIZE; i++) { + int hist = action->cr16_hist[i]; + + if (hist) { + avg += hist; + } else + break; + + if (hist > max) max = hist; + if (hist < min) min = hist; + } + + avg /= i; + p += sprintf(p, " %s[%d/%d/%d]", action->name, + min,avg,max); + } #endif + *p++ = '\n'; + } + } + spin_unlock(&irq_lock); + + p += sprintf(p, "\n"); return p - buf; #else /* CONFIG_PROC_FS */ - return 0; + return 0; #endif /* CONFIG_PROC_FS */ } @@ -240,8 +294,8 @@ int irq; /* never return irq 0 cause that's the interval timer */ - for(irq=1; irq<=MAX_CPU_IRQ; irq++) { - if(cpu_irq_region.action[irq].handler == NULL) { + for (irq = 1; irq <= MAX_CPU_IRQ; irq++) { + if (cpu_irq_region.action[irq].handler == NULL) { return (IRQ_FROM_REGION(CPU_IRQ_REGION) + irq); } } @@ -254,9 +308,7 @@ txn_claim_irq(int irq) { if (irq_region[IRQ_REGION(irq)]->action[IRQ_OFFSET(irq)].handler ==NULL) - { return irq; - } /* unlikely, but be prepared */ return -1; @@ -267,10 +319,10 @@ { struct cpuinfo_parisc *dev = (struct cpuinfo_parisc *) (irq_region[IRQ_REGION(virt_irq)]->data.dev); - if (0==dev) { + if (!dev) { printk(KERN_ERR "txn_alloc_addr(0x%x): CPU IRQ region? dev %p\n", virt_irq,dev); - return(0UL); + return 0; } return (dev->txn_addr); } @@ -283,7 +335,7 @@ ** V-class (EPIC): 6 bits ** N/L-class/A500: 8 bits (iosapic) ** PCI 2.2 MSI: 16 bits (I think) -** Existing PCI devices: 32-bits (NCR c720/ATM/GigE/HyperFabric) +** Existing PCI devices: 32-bits (all Symbios SCSI/ATM/HyperFabric) ** ** On the service provider side: ** o PA 1.1 (and PA2.0 narrow mode) 5-bits (width of EIR register) @@ -308,117 +360,204 @@ panic("Sorry -- didn't allocate valid IRQ for this device\n"); } - return(IRQ_OFFSET(virt_irq)); + return (IRQ_OFFSET(virt_irq)); } - -/* FIXME: SMP, flags, bottom halves, rest */ void do_irq(struct irqaction *action, int irq, struct pt_regs * regs) { int cpu = smp_processor_id(); irq_enter(cpu, irq); + ++kstat.irqs[IRQ_REGION(irq)][IRQ_OFFSET(irq)]; -#ifdef DEBUG_IRQ - if (irq != TIMER_IRQ) + DBG_IRQ(irq, ("do_irq(%d) %d+%d\n", irq, IRQ_REGION(irq), IRQ_OFFSET(irq))); + + for (; action; action = action->next) { +#ifdef PARISC_IRQ_CR16_COUNTS + unsigned long cr_start = mfctl(16); #endif - DBG_IRQ("do_irq(%d) %d+%d\n", irq, IRQ_REGION(irq), IRQ_OFFSET(irq)); - if (action->handler == NULL) - printk(KERN_ERR "No handler for interrupt %d !\n", irq); - for(; action && action->handler; action = action->next) { + if (action->handler == NULL) { + if (IRQ_REGION(irq) == EISA_IRQ_REGION && irq_region[EISA_IRQ_REGION]) { + /* were we called due to autodetecting (E)ISA irqs ? */ + unsigned int *status; + status = &irq_region[EISA_IRQ_REGION]->data.status[IRQ_OFFSET(irq)]; + if (*status & IRQ_AUTODETECT) { + *status &= ~IRQ_WAITING; + continue; + } + } + printk(KERN_ERR "IRQ: CPU:%d No handler for IRQ %d !\n", cpu, irq); + continue; + } + action->handler(irq, action->dev_id, regs); + +#ifdef PARISC_IRQ_CR16_COUNTS + { + unsigned long cr_end = mfctl(16); + unsigned long tmp = cr_end - cr_start; + /* check for roll over */ + cr_start = (cr_end < cr_start) ? -(tmp) : (tmp); + } + action->cr16_hist[action->cr16_idx++] = (int) cr_start; + action->cr16_idx &= PARISC_CR16_HIST_SIZE - 1; +#endif } - + irq_exit(cpu, irq); +} + + +/* ONLY called from entry.S:intr_extint() */ +void do_cpu_irq_mask(struct irq_region *region, struct pt_regs *regs) +{ + unsigned long eirr_val; + unsigned int i=3; /* limit time in interrupt context */ + + /* + * PSW_I or EIEM bits cannot be enabled until after the + * interrupts are processed. + * timer_interrupt() assumes it won't get interrupted when it + * holds the xtime_lock...an unmasked interrupt source could + * interrupt and deadlock by trying to grab xtime_lock too. + * Keeping PSW_I and EIEM disabled avoids this. + */ + set_eiem(0UL); /* disable all extr interrupt for now */ + + /* 1) only process IRQs that are enabled/unmasked (cpu_eiem) + * 2) We loop here on EIRR contents in order to avoid + * nested interrupts or having to take another interupt + * when we could have just handled it right away. + * 3) Limit the number of times we loop to make sure other + * processing can occur. + */ + while ((eirr_val = (mfctl(23) & cpu_eiem)) && --i) { + unsigned long bit = (1UL<>=1, irq++) + { + unsigned int irq_num; + if (!(bit&eirr_val)) + continue; - /* don't need to care about unmasking and stuff */ - do_softirq(); + /* clear bit in mask - can exit loop sooner */ + eirr_val &= ~bit; + + irq_num = region->data.irqbase + irq; + do_irq(®ion->action[irq], irq_num, regs); + } + } + set_eiem(cpu_eiem); } + +/* Called from second level IRQ regions: eg dino or iosapic. */ void do_irq_mask(unsigned long mask, struct irq_region *region, struct pt_regs *regs) { unsigned long bit; - int irq; - int cpu = smp_processor_id(); + unsigned int irq; #ifdef DEBUG_IRQ - if (mask != (1L << MAX_CPU_IRQ)) - printk("do_irq_mask %08lx %p %p\n", mask, region, regs); + if (mask != (1L<>=1, irq++) { - int irq_num; - if(!(bit&mask)) + for (bit = (1L<>=1, irq++) { + unsigned int irq_num; + if (!(bit&mask)) continue; + mask &= ~bit; /* clear bit in mask - can exit loop sooner */ irq_num = region->data.irqbase + irq; - ++kstat.irqs[cpu][IRQ_FROM_REGION(CPU_IRQ_REGION) | irq]; - if (IRQ_REGION(irq_num) != CPU_IRQ_REGION) - ++kstat.irqs[cpu][irq_num]; - mask_irq(irq_num); do_irq(®ion->action[irq], irq_num, regs); unmask_irq(irq_num); } } -static inline int alloc_irqregion(void) + +static inline int find_free_region(void) { int irqreg; - for(irqreg=1; irqreg<=(NR_IRQ_REGS); irqreg++) { - if(irq_region[irqreg] == NULL) + for (irqreg=1; irqreg <= (NR_IRQ_REGS); irqreg++) { + if (irq_region[irqreg] == NULL) return irqreg; } return 0; } -struct irq_region *alloc_irq_region( - int count, struct irq_region_ops *ops, unsigned long flags, - const char *name, void *dev) + +/***** + * alloc_irq_region - allocate/init a new IRQ region + * @count: number of IRQs in this region. + * @ops: function table with request/release/mask/unmask/etc.. entries. + * @name: name of region owner for /proc/interrupts output. + * @dev: private data to associate with the new IRQ region. + * + * Every IRQ must become a MMIO write to the CPU's EIRR in + * order to get CPU service. The IRQ region represents the + * number of unique events the region handler can (or must) + * identify. For PARISC CPU, that's the width of the EIR Register. + * IRQ regions virtualize IRQs (eg EISA or PCI host bus controllers) + * for line based devices. + */ +struct irq_region *alloc_irq_region( int count, struct irq_region_ops *ops, + const char *name, void *dev) { struct irq_region *region; int index; - index = alloc_irqregion(); + index = find_free_region(); + if (index == 0) { + printk(KERN_ERR "Maximum number of irq regions exceeded. Increase NR_IRQ_REGS!\n"); + return NULL; + } - if((IRQ_REGION(count-1))) + if ((IRQ_REGION(count-1))) return NULL; - + if (count < IRQ_PER_REGION) { - DBG_IRQ("alloc_irq_region() using minimum of %d irq lines for %s (%d)\n", - IRQ_PER_REGION, name, count); + DBG_IRQ(0, ("alloc_irq_region() using minimum of %d irq lines for %s (%d)\n", + IRQ_PER_REGION, name, count)); count = IRQ_PER_REGION; } - if(flags & IRQ_REG_MASK) - if(!(ops->mask_irq && ops->unmask_irq)) - return NULL; - - if(flags & IRQ_REG_DIS) - if(!(ops->disable_irq && ops->enable_irq)) + /* if either mask *or* unmask is set, both have to be set. */ + if((ops->mask_irq || ops->unmask_irq) && + !(ops->mask_irq && ops->unmask_irq)) return NULL; - if((irq_region[index])) - return NULL; + /* ditto for enable/disable */ + if( (ops->disable_irq || ops->enable_irq) && + !(ops->disable_irq && ops->enable_irq) ) + return NULL; - region = kmalloc(sizeof *region, GFP_ATOMIC); - if(!region) + region = kmalloc(sizeof(*region), GFP_ATOMIC); + if (!region) return NULL; + memset(region, 0, sizeof(*region)); - region->action = kmalloc(sizeof *region->action * count, GFP_ATOMIC); - if(!region->action) { + region->action = kmalloc(count * sizeof(*region->action), GFP_ATOMIC); + if (!region->action) { kfree(region); return NULL; } - memset(region->action, 0, sizeof *region->action * count); + memset(region->action, 0, count * sizeof(*region->action)); region->ops = *ops; region->data.irqbase = IRQ_FROM_REGION(index); - region->data.flags = flags; region->data.name = name; region->data.dev = dev; @@ -426,14 +565,12 @@ return irq_region[index]; } - - /* FIXME: SMP, flags, bottom halves, rest */ -int request_irq(unsigned int irq, +int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, + unsigned long irqflags, const char * devname, void *dev_id) { @@ -442,13 +579,19 @@ #if 0 printk(KERN_INFO "request_irq(%d, %p, 0x%lx, %s, %p)\n",irq, handler, irqflags, devname, dev_id); #endif - if(!handler) { + + irq = irq_cannonicalize(irq); + /* request_irq()/free_irq() may not be called from interrupt context. */ + if (in_interrupt()) + BUG(); + + if (!handler) { printk(KERN_ERR "request_irq(%d,...): Augh! No handler for irq!\n", irq); return -EINVAL; } - if ((IRQ_REGION(irq) == 0) || irq_region[IRQ_REGION(irq)] == NULL) { + if (irq_region[IRQ_REGION(irq)] == NULL) { /* ** Bug catcher for drivers which use "char" or u8 for ** the IRQ number. They lose the region number which @@ -459,19 +602,24 @@ return -EINVAL; } - action = &irq_region[IRQ_REGION(irq)]->action[IRQ_OFFSET(irq)]; + spin_lock(&irq_lock); + action = &(irq_region[IRQ_REGION(irq)]->action[IRQ_OFFSET(irq)]); - if(action->handler) { - while(action->next) + /* First one is preallocated. */ + if (action->handler) { + /* But it's in use...find the tail and allocate a new one */ + while (action->next) action = action->next; - action->next = kmalloc(sizeof *action, GFP_ATOMIC); + action->next = kmalloc(sizeof(*action), GFP_ATOMIC); + memset(action->next, 0, sizeof(*action)); action = action->next; - } + } - if(!action) { - printk(KERN_ERR "request_irq():Augh! No action!\n") ; + if (!action) { + spin_unlock(&irq_lock); + printk(KERN_ERR "request_irq(): Augh! No action!\n") ; return -ENOMEM; } @@ -481,6 +629,7 @@ action->name = devname; action->next = NULL; action->dev_id = dev_id; + spin_unlock(&irq_lock); enable_irq(irq); return 0; @@ -490,14 +639,22 @@ { struct irqaction *action, **p; + /* See comments in request_irq() about interrupt context */ + irq = irq_cannonicalize(irq); + + if (in_interrupt()) BUG(); + + spin_lock(&irq_lock); action = &irq_region[IRQ_REGION(irq)]->action[IRQ_OFFSET(irq)]; - if(action->dev_id == dev_id) { - if(action->next == NULL) + if (action->dev_id == dev_id) { + if (action->next == NULL) { action->handler = NULL; - else - memcpy(action, action->next, sizeof *action); + } else { + memcpy(action, action->next, sizeof(*action)); + } + spin_unlock(&irq_lock); return; } @@ -512,27 +669,175 @@ *p = action->next; kfree(action); + spin_unlock(&irq_lock); return; } + spin_unlock(&irq_lock); printk(KERN_ERR "Trying to free free IRQ%d\n",irq); } -unsigned long probe_irq_on (void) + +/* + * IRQ autodetection code.. + * + * This depends on the fact that any interrupt that + * comes in on to an unassigned handler will get stuck + * with "IRQ_WAITING" cleared and the interrupt + * disabled. + */ + +static DECLARE_MUTEX(probe_sem); + +/** + * probe_irq_on - begin an interrupt autodetect + * + * Commence probing for an interrupt. The interrupts are scanned + * and a mask of potential interrupt lines is returned. + * + */ + +/* TODO: spin_lock_irq(desc->lock -> irq_lock) */ + +unsigned long probe_irq_on(void) { - return 0; + unsigned int i; + unsigned long val; + unsigned long delay; + struct irq_region *region; + + /* support for irq autoprobing is limited to EISA (irq region 0) */ + region = irq_region[EISA_IRQ_REGION]; + if (!EISA_bus || !region) + return 0; + + down(&probe_sem); + + /* + * enable any unassigned irqs + * (we must startup again here because if a longstanding irq + * happened in the previous stage, it may have masked itself) + */ + for (i = EISA_MAX_IRQS-1; i > 0; i--) { + struct irqaction *action; + + spin_lock_irq(&irq_lock); + action = region->action + i; + if (!action->handler) { + region->data.status[i] |= IRQ_AUTODETECT | IRQ_WAITING; + region->ops.enable_irq(region->data.dev,i); + } + spin_unlock_irq(&irq_lock); + } + + /* + * Wait for spurious interrupts to trigger + */ + for (delay = jiffies + HZ/10; time_after(delay, jiffies); ) + /* about 100ms delay */ synchronize_irq(); + + /* + * Now filter out any obviously spurious interrupts + */ + val = 0; + for (i = 0; i < EISA_MAX_IRQS; i++) { + unsigned int status; + + spin_lock_irq(&irq_lock); + status = region->data.status[i]; + + if (status & IRQ_AUTODETECT) { + /* It triggered already - consider it spurious. */ + if (!(status & IRQ_WAITING)) { + region->data.status[i] = status & ~IRQ_AUTODETECT; + region->ops.disable_irq(region->data.dev,i); + } else + if (i < BITS_PER_LONG) + val |= (1 << i); + } + spin_unlock_irq(&irq_lock); + } + + return val; } -int probe_irq_off (unsigned long irqs) +/* + * Return the one interrupt that triggered (this can + * handle any interrupt source). + */ + +/** + * probe_irq_off - end an interrupt autodetect + * @val: mask of potential interrupts (unused) + * + * Scans the unused interrupt lines and returns the line which + * appears to have triggered the interrupt. If no interrupt was + * found then zero is returned. If more than one interrupt is + * found then minus the first candidate is returned to indicate + * their is doubt. + * + * The interrupt probe logic state is returned to its previous + * value. + * + * BUGS: When used in a module (which arguably shouldnt happen) + * nothing prevents two IRQ probe callers from overlapping. The + * results of this are non-optimal. + */ + +int probe_irq_off(unsigned long val) { - return 0; + struct irq_region *region; + int i, irq_found, nr_irqs; + + /* support for irq autoprobing is limited to EISA (irq region 0) */ + region = irq_region[EISA_IRQ_REGION]; + if (!EISA_bus || !region) + return 0; + + nr_irqs = 0; + irq_found = 0; + for (i = 0; i < EISA_MAX_IRQS; i++) { + unsigned int status; + + spin_lock_irq(&irq_lock); + status = region->data.status[i]; + + if (status & IRQ_AUTODETECT) { + if (!(status & IRQ_WAITING)) { + if (!nr_irqs) + irq_found = i; + nr_irqs++; + } + region->ops.disable_irq(region->data.dev,i); + region->data.status[i] = status & ~IRQ_AUTODETECT; + } + spin_unlock_irq(&irq_lock); + } + up(&probe_sem); + + if (nr_irqs > 1) + irq_found = -irq_found; + return irq_found; } void __init init_IRQ(void) { + local_irq_disable(); /* PARANOID - should already be disabled */ + mtctl(-1L, 23); /* EIRR : clear all pending external intr */ +#ifdef CONFIG_SMP + if (!cpu_eiem) + cpu_eiem = EIEM_MASK(IPI_IRQ) | EIEM_MASK(TIMER_IRQ); +#else + cpu_eiem = EIEM_MASK(TIMER_IRQ); +#endif + set_eiem(cpu_eiem); /* EIEM : enable all external intr */ + } -void init_irq_proc(void) +#ifdef CONFIG_PROC_FS +/* called from kernel/sysctl.c:sysctl_init() */ +void __init init_irq_proc(void) { } +#endif diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/irq_smp.c linux.19rc3-ac4/arch/parisc/kernel/irq_smp.c --- linux.19rc3/arch/parisc/kernel/irq_smp.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/irq_smp.c 2002-07-29 13:58:36.000000000 +0100 @@ -0,0 +1,232 @@ +/* + * linux/arch/parisc/kernel/irq_smp.c + * (90% stolen from alpha port, 9% from ia64, rest is mine -ggg) + * + * Copyright (C) 2001 Hewlett-Packard Co + * Copyright (C) 2001 Grant Grundler + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +int global_irq_holder = NO_PROC_ID; /* Who has global_irq_lock. */ +spinlock_t global_irq_lock = SPIN_LOCK_UNLOCKED; /* protects IRQ's. */ + + +/* Global IRQ locking depth. */ +static void *previous_irqholder = NULL; + +#define MAXCOUNT 100000000 + + +static void +show(char * str, void *where) +{ + int cpu = smp_processor_id(); + + printk("\n%s, CPU %d: %p\n", str, cpu, where); + printk("irq: %d [%d %d]\n", + irqs_running(), + local_irq_count(0), + local_irq_count(1)); + + printk("bh: %d [%d %d]\n", + spin_is_locked(&global_bh_lock) ? 1 : 0, + local_bh_count(0), + local_bh_count(1)); +} + +static inline void +wait_on_irq(int cpu, void *where) +{ + int count = MAXCOUNT; + + for (;;) { + + /* + * Wait until all interrupts are gone. Wait + * for bottom half handlers unless we're + * already executing in one.. + */ + if (!irqs_running()) { + if (local_bh_count(cpu) + || !spin_is_locked(&global_bh_lock)) + break; + } + + /* Duh, we have to loop. Release the lock to avoid deadlocks */ + spin_unlock(&global_irq_lock); + + for (;;) { + if (!--count) { + show("wait_on_irq", where); + count = MAXCOUNT; + } + __sti(); + udelay(1); /* make sure to run pending irqs */ + __cli(); + + if (irqs_running()) + continue; + if (spin_is_locked(&global_irq_lock)) + continue; + if (!local_bh_count(cpu) + && spin_is_locked(&global_bh_lock)) + continue; + if (spin_trylock(&global_irq_lock)) + break; + } + } +} + +static inline void +get_irqlock(int cpu, void* where) +{ + if (!spin_trylock(&global_irq_lock)) { + /* Do we already hold the lock? */ + if (cpu == global_irq_holder) + return; + /* Uhhuh.. Somebody else got it. Wait. */ + spin_lock(&global_irq_lock); + } + + /* + * Ok, we got the lock bit. + * But that's actually just the easy part.. Now + * we need to make sure that nobody else is running + * in an interrupt context. + */ + wait_on_irq(cpu, where); + + /* + * Finally. + */ +#if DEBUG_SPINLOCK + global_irq_lock.task = current; + global_irq_lock.previous = where; +#endif + global_irq_holder = cpu; + previous_irqholder = where; +} + + +/* +** A global "cli()" while in an interrupt context +** turns into just a local cli(). Interrupts +** should use spinlocks for the (very unlikely) +** case that they ever want to protect against +** each other. +** +** If we already have local interrupts disabled, +** this will not turn a local disable into a +** global one (problems with spinlocks: this makes +** save_flags+cli+sti usable inside a spinlock). +*/ +void +__global_cli(void) +{ + unsigned int flags; + __save_flags(flags); + if (flags & PSW_I) { + int cpu = smp_processor_id(); + __cli(); + if (!local_irq_count(cpu)) { + void *where = __builtin_return_address(0); + get_irqlock(cpu, where); + } + } +} + +void +__global_sti(void) +{ + int cpu = smp_processor_id(); + + if (!local_irq_count(cpu)) + release_irqlock(cpu); + __sti(); +} + +/* + * SMP flags value to restore to: + * 0 - global cli + * 1 - global sti + * 2 - local cli + * 3 - local sti + */ +unsigned long +__global_save_flags(void) +{ + int retval; + int local_enabled; + unsigned long flags; + int cpu = smp_processor_id(); + + __save_flags(flags); + local_enabled = (flags & PSW_I) != 0; + /* default to local */ + retval = 2 + local_enabled; + + /* Check for global flags if we're not in an interrupt. */ + if (!local_irq_count(cpu)) { + if (local_enabled) + retval = 1; + if (global_irq_holder == cpu) + retval = 0; + } + return retval; +} + +void +__global_restore_flags(unsigned long flags) +{ + switch (flags) { + case 0: + __global_cli(); + break; + case 1: + __global_sti(); + break; + case 2: + __cli(); + break; + case 3: + __sti(); + break; + default: + printk(KERN_ERR "global_restore_flags: %08lx (%p)\n", + flags, __builtin_return_address(0)); + } +} + +/* + * From its use, I infer that synchronize_irq() stalls a thread until + * the effects of a command to an external device are known to have + * taken hold. Typically, the command is to stop sending interrupts. + * The strategy here is wait until there is at most one processor + * (this one) in an irq. The memory barrier serializes the write to + * the device and the subsequent accesses of global_irq_count. + * --jmartin + */ +#define DEBUG_SYNCHRONIZE_IRQ 0 + +void +synchronize_irq(void) +{ + /* Jay's version. */ + if (irqs_running()) { + cli(); + sti(); + } +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/keyboard.c linux.19rc3-ac4/arch/parisc/kernel/keyboard.c --- linux.19rc3/arch/parisc/kernel/keyboard.c 2002-07-29 12:50:06.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/keyboard.c 2002-07-29 13:58:36.000000000 +0100 @@ -1,4 +1,12 @@ /* + * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING + * --------------------------------------------------------------- + * This source file will be removed as soon as we have converted + * hp_psaux.c and hp_keyb.c to the input layer ! + * + */ + +/* * linux/arch/parisc/kernel/keyboard.c * * Alex deVries @@ -7,8 +15,10 @@ * Copyright 2000 Philipp Rumpf */ +#include #include #include +#include static int def_setkeycode(unsigned int x, unsigned int y) { @@ -43,20 +53,29 @@ static char def_sysrq_xlate[NR_KEYS]; -static struct kbd_ops def_kbd_ops = { - setkeycode: def_setkeycode, - getkeycode: def_getkeycode, - translate: def_translate, - unexpected_up: def_unexpected_up, - leds: def_leds, - init_hw: def_init_hw, - - sysrq_key: 0xff, +#define DEFAULT_KEYB_OPS \ + setkeycode: def_setkeycode, \ + getkeycode: def_getkeycode, \ + translate: def_translate, \ + unexpected_up: def_unexpected_up, \ + leds: def_leds, \ + init_hw: def_init_hw, \ + sysrq_key: 0xff, \ sysrq_xlate: def_sysrq_xlate, + +static struct kbd_ops def_kbd_ops = { + DEFAULT_KEYB_OPS }; struct kbd_ops *kbd_ops = &def_kbd_ops; +void unregister_kbd_ops(void) +{ + struct kbd_ops new_kbd_ops = { DEFAULT_KEYB_OPS }; + register_kbd_ops(&new_kbd_ops); +} +EXPORT_SYMBOL(unregister_kbd_ops); + void register_kbd_ops(struct kbd_ops *ops) { if(ops->setkeycode) diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/lasimap.map linux.19rc3-ac4/arch/parisc/kernel/lasimap.map --- linux.19rc3/arch/parisc/kernel/lasimap.map 2002-07-29 12:50:06.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/lasimap.map 1970-01-01 01:00:00.000000000 +0100 @@ -1,322 +0,0 @@ -# HP 712 kernel keymap. This uses 7 modifier combinations. - -keymaps 0-2,4-5,8,12 -# ie, plain, Shift, AltGr, Control, Control+Shift, Alt and Control+Alt - - -# Change the above line into -# keymaps 0-2,4-6,8,12 -# in case you want the entries -# altgr control keycode 83 = Boot -# altgr control keycode 111 = Boot -# below. -# -# In fact AltGr is used very little, and one more keymap can -# be saved by mapping AltGr to Alt (and adapting a few entries): -# keycode 100 = Alt -# -keycode 1 = F9 F19 Console_21 - control keycode 1 = F9 - alt keycode 1 = Console_9 - control alt keycode 1 = Console_9 -keycode 2 = -keycode 3 = F5 F15 Console_17 - control keycode 3 = F5 - alt keycode 3 = Console_5 - control alt keycode 3 = Console_5 -keycode 4 = F3 F13 Console_15 - control keycode 4 = F3 - alt keycode 4 = Console_3 - control alt keycode 4 = Console_3 -keycode 5 = F1 F11 Console_13 - control keycode 5 = F1 - alt keycode 5 = Console_1 - control alt keycode 5 = Console_1 -keycode 6 = F2 F12 Console_14 - control keycode 6 = F2 - alt keycode 6 = Console_2 - control alt keycode 6 = Console_2 -keycode 7 = F12 F12 Console_24 - control keycode 7 = F12 - alt keycode 7 = Console_12 - control alt keycode 7 = Console_12 -keycode 8 = -keycode 9 = F10 F20 Console_22 - control keycode 9 = F10 - alt keycode 9 = Console_10 - control alt keycode 9 = Console_10 -keycode 10 = F8 F18 Console_20 - control keycode 10 = F8 - alt keycode 10 = Console_8 - control alt keycode 10 = Console_8 -keycode 11 = F6 F16 Console_18 - control keycode 11 = F6 - alt keycode 11 = Console_6 - control alt keycode 11 = Console_6 -keycode 12 = F4 F14 Console_16 - control keycode 12 = F4 - alt keycode 12 = Console_4 - control alt keycode 12 = Console_4 -keycode 13 = Tab Tab - alt keycode 13 = Meta_Tab -keycode 14 = grave asciitilde - control keycode 14 = nul - alt keycode 14 = Meta_grave -keycode 15 = -keycode 16 = -keycode 17 = Alt -keycode 18 = Shift -keycode 19 = -keycode 20 = Control -keycode 21 = q -keycode 22 = one exclam exclam -keycode 23 = -keycode 24 = -keycode 25 = -keycode 26 = z -keycode 27 = s -keycode 28 = a - altgr keycode 28 = Hex_A -keycode 29 = w -keycode 30 = two at at -keycode 31 = -keycode 32 = -keycode 33 = c - altgr keycode 46 = Hex_C -keycode 34 = x -keycode 35 = d - altgr keycode 35 = Hex_D -keycode 36 = e - altgr keycode 36 = Hex_E -keycode 37 = four dollar -keycode 38 = three numbersign -keycode 39 = -keycode 40 = -keycode 41 = -keycode 42 = v -keycode 43 = f - altgr keycode 43 = Hex_F -keycode 44 = t -keycode 45 = r -keycode 46 = five percent -keycode 47 = -keycode 48 = -keycode 49 = n -keycode 50 = b - altgr keycode 50 = Hex_B -keycode 51 = h -keycode 52 = g -keycode 53 = y -keycode 54 = six asciicircum -keycode 55 = -keycode 56 = -keycode 57 = -keycode 58 = m -keycode 59 = j -keycode 60 = u -keycode 61 = seven ampersand -keycode 62 = eight asterisk asterisk -keycode 63 = -keycode 64 = -keycode 65 = comma less - alt keycode 65 = Meta_comma -keycode 66 = k -keycode 67 = i -keycode 68 = o -keycode 69 = zero parenright bracketright -keycode 70 = nine parenleft bracketleft -keycode 71 = -keycode 72 = -keycode 73 = period greater - control keycode 73 = Compose - alt keycode 73 = Meta_period -keycode 74 = slash question - control keycode 74 = Delete - alt keycode 53 = Meta_slash -keycode 75 = l -keycode 76 = semicolon colon - alt keycode 39 = Meta_semicolon -keycode 77 = p -keycode 78 = minus underscore -keycode 79 = -keycode 80 = -keycode 81 = -keycode 82 = apostrophe quotedbl - control keycode 82 = Control_g - alt keycode 40 = Meta_apostrophe -keycode 83 = -keycode 84 = bracketleft braceleft - control keycode 84 = Escape - alt keycode 26 = Meta_bracketleft -keycode 85 = equal plus -keycode 86 = -keycode 87 = -keycode 88 = Caps_Lock -keycode 88 = -keycode 89 = -keycode 89 = -keycode 89 = -keycode 90 = Return - alt keycode 90 = Meta_Control_m -keycode 91 = bracketright braceright asciitilde - control keycode 91 = Control_bracketright - alt keycode 91 = Meta_bracketright -keycode 92 = -keycode 93 = backslash bar - control keycode 43 = Control_backslash - alt keycode 43 = Meta_backslash -keycode 94 = -keycode 95 = -keycode 96 = -keycode 97 = -keycode 98 = -keycode 99 = -keycode 100 = -keycode 101 = -keycode 102 = BackSpace -keycode 103 = -keycode 104 = -keycode 105 = KP_1 - alt keycode 105 = Ascii_1 - altgr keycode 105 = Hex_1 -keycode 106 = -keycode 107 = KP_4 - alt keycode 107 = Ascii_4 - altgr keycode 107 = Hex_4 -keycode 108 = KP_7 - alt keycode 108 = Ascii_7 - altgr keycode 108 = Hex_7 -keycode 109 = -keycode 110 = -keycode 111 = -keycode 112 = KP_0 - alt keycode 82 = Ascii_0 - altgr keycode 82 = Hex_0 -keycode 113 = KP_Period -keycode 114 = KP_2 - alt keycode 114 = Ascii_2 - altgr keycode 114 = Hex_2 -keycode 115 = KP_5 - alt keycode 115 = Ascii_5 - altgr keycode 115 = Hex_5 -keycode 116 = KP_6 - alt keycode 116 = Ascii_6 - altgr keycode 116 = Hex_6 -keycode 117 = KP_8 - alt keycode 117 = Ascii_8 - altgr keycode 117 = Hex_8 -keycode 118 = Escape -keycode 119 = -keycode 120 = F11 -keycode 121 = KP_Add -keycode 122 = KP_3 - alt keycode 122 = Ascii_3 - altgr keycode 122 = Hex_3 -keycode 123 = KP_Subtract -keycode 124 = KP_Multiply -keycode 125 = KP_9 - alt keycode 125 = Ascii_9 - altgr keycode 125 = Hex_9 -keycode 126 = -# 131!! -keycode 127 = F7 F17 Console_19 - control keycode 127 = F7 - alt keycode 127 = Console_7 - control alt keycode 127 = Console_7 - -string F1 = "\033[[A" -string F2 = "\033[[B" -string F3 = "\033[[C" -string F4 = "\033[[D" -string F5 = "\033[[E" -string F6 = "\033[17~" -string F7 = "\033[18~" -string F8 = "\033[19~" -string F9 = "\033[20~" -string F10 = "\033[21~" -string F11 = "\033[23~" -string F12 = "\033[24~" -string F13 = "\033[25~" -string F14 = "\033[26~" -string F15 = "\033[28~" -string F16 = "\033[29~" -string F17 = "\033[31~" -string F18 = "\033[32~" -string F19 = "\033[33~" -string F20 = "\033[34~" -string Find = "\033[1~" -string Insert = "\033[2~" -string Remove = "\033[3~" -string Select = "\033[4~" -string Prior = "\033[5~" -string Next = "\033[6~" -string Macro = "\033[M" -string Pause = "\033[P" -compose '`' 'A' to 'À' -compose '`' 'a' to 'à' -compose '\'' 'A' to 'Á' -compose '\'' 'a' to 'á' -compose '^' 'A' to 'Â' -compose '^' 'a' to 'â' -compose '~' 'A' to 'Ã' -compose '~' 'a' to 'ã' -compose '"' 'A' to 'Ä' -compose '"' 'a' to 'ä' -compose 'O' 'A' to 'Å' -compose 'o' 'a' to 'å' -compose '0' 'A' to 'Å' -compose '0' 'a' to 'å' -compose 'A' 'A' to 'Å' -compose 'a' 'a' to 'å' -compose 'A' 'E' to 'Æ' -compose 'a' 'e' to 'æ' -compose ',' 'C' to 'Ç' -compose ',' 'c' to 'ç' -compose '`' 'E' to 'È' -compose '`' 'e' to 'è' -compose '\'' 'E' to 'É' -compose '\'' 'e' to 'é' -compose '^' 'E' to 'Ê' -compose '^' 'e' to 'ê' -compose '"' 'E' to 'Ë' -compose '"' 'e' to 'ë' -compose '`' 'I' to 'Ì' -compose '`' 'i' to 'ì' -compose '\'' 'I' to 'Í' -compose '\'' 'i' to 'í' -compose '^' 'I' to 'Î' -compose '^' 'i' to 'î' -compose '"' 'I' to 'Ï' -compose '"' 'i' to 'ï' -compose '-' 'D' to 'Ð' -compose '-' 'd' to 'ð' -compose '~' 'N' to 'Ñ' -compose '~' 'n' to 'ñ' -compose '`' 'O' to 'Ò' -compose '`' 'o' to 'ò' -compose '\'' 'O' to 'Ó' -compose '\'' 'o' to 'ó' -compose '^' 'O' to 'Ô' -compose '^' 'o' to 'ô' -compose '~' 'O' to 'Õ' -compose '~' 'o' to 'õ' -compose '"' 'O' to 'Ö' -compose '"' 'o' to 'ö' -compose '/' 'O' to 'Ø' -compose '/' 'o' to 'ø' -compose '`' 'U' to 'Ù' -compose '`' 'u' to 'ù' -compose '\'' 'U' to 'Ú' -compose '\'' 'u' to 'ú' -compose '^' 'U' to 'Û' -compose '^' 'u' to 'û' -compose '"' 'U' to 'Ü' -compose '"' 'u' to 'ü' -compose '\'' 'Y' to 'Ý' -compose '\'' 'y' to 'ý' -compose 'T' 'H' to 'Þ' -compose 't' 'h' to 'þ' -compose 's' 's' to 'ß' -compose '"' 'y' to 'ÿ' -compose 's' 'z' to 'ß' -compose 'i' 'j' to 'ÿ' diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/lba_pci.c linux.19rc3-ac4/arch/parisc/kernel/lba_pci.c --- linux.19rc3/arch/parisc/kernel/lba_pci.c 2002-07-29 12:50:06.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/lba_pci.c 2002-07-29 13:58:36.000000000 +0100 @@ -34,6 +34,7 @@ #include #include #include /* for __init and __devinit */ +/* #define PCI_DEBUG enable ASSERT */ #include #include #include @@ -42,15 +43,13 @@ #include #include /* for struct irq_region support */ #include -#include #include #include #include -#include /* for register_driver() stuff */ +#include /* for register_parisc_driver() stuff */ #include /* for iosapic_register() */ -#include /* gsc_read/write stuff */ - +#include /* read/write stuff */ #ifndef TRUE #define TRUE (1 == 1) @@ -62,6 +61,9 @@ #undef DEBUG_LBA_CFG /* debug Config Space Access (ie PCI Bus walk) */ #undef DEBUG_LBA_PAT /* debug PCI Resource Mgt code - PDC PAT only */ +#undef FBB_SUPPORT /* Fast Back-Back xfers - NOT READY YET */ + + #ifdef DEBUG_LBA #define DBG(x...) printk(x) #else @@ -102,22 +104,6 @@ #define MODULE_NAME "lba" -static int lba_driver_callback(struct hp_device *, struct pa_iodc_driver *); - - -static struct pa_iodc_driver lba_drivers_for[]= { - - {HPHW_BRIDGE, 0x782, 0x0, 0xa, 0,0, - DRIVER_CHECK_HVERSION + - DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE, - MODULE_NAME, "tbd", (void *) lba_driver_callback}, - - {0,0,0,0,0,0, - 0, - (char *) NULL, (char *) NULL, (void *) NULL} -}; - - #define LBA_FUNC_ID 0x0000 /* function id */ #define LBA_FCLASS 0x0008 /* function class, bist, header, rev... */ #define LBA_CAPABLE 0x0030 /* capabilities register */ @@ -137,6 +123,9 @@ #define LBA_MOD_ID 0x0100 /* Module ID. PDC_PAT_CELL reports 4 */ #define LBA_STAT_CTL 0x0108 /* Status & Control */ +#define LBA_BUS_RESET 0x01 /* Deassert PCI Bus Reset Signal */ +#define CLEAR_ERRLOG 0x10 /* "Clear Error Log" cmd */ +#define CLEAR_ERRLOG_ENABLE 0x20 /* "Clear Error Log" Enable */ #define HF_ENABLE 0x40 /* enable HF mode (default is -1 mode) */ #define LBA_LMMIO_BASE 0x0200 /* < 4GB I/O address range */ @@ -162,15 +151,18 @@ #define LBA_DMA_CTL 0x0278 /* firmware sets this */ -/* RESET: ignore DMA stuff until we can measure performance */ -#define LBA_IBASE 0x0300 /* DMA support */ +#define LBA_IBASE 0x0300 /* SBA DMA support */ #define LBA_IMASK 0x0308 + +/* FIXME: ignore DMA Hint stuff until we can measure performance */ #define LBA_HINT_CFG 0x0310 #define LBA_HINT_BASE 0x0380 /* 14 registers at every 8 bytes. */ /* ERROR regs are needed for config cycle kluges */ #define LBA_ERROR_CONFIG 0x0680 +#define LBA_SMART_MODE 0x20 #define LBA_ERROR_STATUS 0x0688 +#define LBA_ROPE_CTL 0x06A0 #define LBA_IOSAPIC_BASE 0x800 /* Offset of IRQ logic */ @@ -232,19 +224,20 @@ * BE WARNED: register writes are posted. * (ie follow writes which must reach HW with a read) */ -#define READ_U8(addr) gsc_readb(addr) -#define READ_U16(addr) gsc_readw((u16 *) (addr)) -#define READ_U32(addr) gsc_readl((u32 *) (addr)) -#define WRITE_U8(value, addr) gsc_writeb(value, addr) -#define WRITE_U16(value, addr) gsc_writew(value, (u16 *) (addr)) -#define WRITE_U32(value, addr) gsc_writel(value, (u32 *) (addr)) - -#define READ_REG8(addr) gsc_readb(addr) -#define READ_REG16(addr) le16_to_cpu(gsc_readw((u16 *) (addr))) -#define READ_REG32(addr) le32_to_cpu(gsc_readl((u32 *) (addr))) -#define WRITE_REG8(value, addr) gsc_writeb(value, addr) -#define WRITE_REG16(value, addr) gsc_writew(cpu_to_le16(value), (u16 *) (addr)) -#define WRITE_REG32(value, addr) gsc_writel(cpu_to_le32(value), (u32 *) (addr)) +#define READ_U8(addr) __raw_readb(addr) +#define READ_U16(addr) __raw_readw(addr) +#define READ_U32(addr) __raw_readl(addr) +#define WRITE_U8(value, addr) __raw_writeb(value, addr) +#define WRITE_U16(value, addr) __raw_writew(value, addr) +#define WRITE_U32(value, addr) __raw_writel(value, addr) + +#define READ_REG8(addr) readb(addr) +#define READ_REG16(addr) readw(addr) +#define READ_REG32(addr) readl(addr) +#define READ_REG64(addr) readq(addr) +#define WRITE_REG8(value, addr) writeb(value, addr) +#define WRITE_REG16(value, addr) writew(value, addr) +#define WRITE_REG32(value, addr) writel(value, addr) #define LBA_CFG_TOK(bus,dfn) ((u32) ((bus)<<16 | (dfn)<<8)) @@ -253,25 +246,12 @@ #define LBA_CFG_FUNC(tok) ((u8) ((tok)>>8 ) & 0x7) -#ifdef DEBUG_LBA -/* Extract LBA (Rope) number from HPA */ -#define LBA_NUM(x) ((((uintptr_t) x) >> 13) & 0xf) -#endif /* DEBUG_LBA */ - -#ifdef __LP64__ -/* PDC_PAT */ -static unsigned long pdc_result[32] __attribute__ ((aligned (8))) = {0,0,0,0}; -#endif - /* -** One time initialization to let the world know the LBA was found. -** This is the only routine which is NOT static. -** Must be called exactly once before pci_init(). +** Extract LBA (Rope) number from HPA +** REVISIT: 16 ropes for Stretch/Ike? */ -void __init lba_init(void) -{ - register_driver(lba_drivers_for); -} +#define ROPES_PER_SBA 8 +#define LBA_NUM(x) ((((unsigned long) x) >> 13) & (ROPES_PER_SBA-1)) static void @@ -282,9 +262,9 @@ if (NULL == r) return; - printk("(%p)", r->parent); + printk(KERN_DEBUG "(%p)", r->parent); for (i = d; i ; --i) printk(" "); - printk("%p [%lx,%lx]/%x\n", r, r->start, r->end, (int) r->flags); + printk(KERN_DEBUG "%p [%lx,%lx]/%x\n", r, r->start, r->end, (int) r->flags); lba_dump_res(r->child, d+2); lba_dump_res(r->sibling, d); } @@ -369,7 +349,7 @@ * Set the smart mode bit so that master aborts don't cause \ * LBA to go into PCI fatal mode (required). \ */ \ - WRITE_REG32(error_config | 0x20, d->hba.base_addr + LBA_ERROR_CONFIG); \ + WRITE_REG32(error_config | LBA_SMART_MODE, d->hba.base_addr + LBA_ERROR_CONFIG); \ } @@ -414,9 +394,9 @@ * * Actually, there is still a race in which * we could be clearing a fatal error. We will - * live with this during our real mode bus walk + * live with this during our initial bus walk * until rev 4.0 (no driver activity during - * real mode bus walk). The real mode bus walk + * initial bus walk). The initial bus walk * has race conditions concerning the use of * smart mode as well. */ @@ -430,7 +410,7 @@ * Set clear enable (CE) bit. Unset by HW when new \ * errors are logged -- LBA HW ERS section 14.3.3). \ */ \ - WRITE_REG32(status_control | 0x20, base + LBA_STAT_CTL); \ + WRITE_REG32(status_control | CLEAR_ERRLOG_ENABLE, base + LBA_STAT_CTL); \ error_status = READ_REG32(base + LBA_ERROR_STATUS); \ if ((error_status & 0x1f) != 0) { \ /* \ @@ -442,7 +422,7 @@ * Clear error status (if fatal bit not set) by setting \ * clear error log bit (CL). \ */ \ - WRITE_REG32(status_control | 0x10, base + LBA_STAT_CTL); \ + WRITE_REG32(status_control | CLEAR_ERRLOG, base + LBA_STAT_CTL); \ } \ } \ } @@ -483,7 +463,7 @@ static unsigned int -lba_rd_cfg( struct lba_device *d, u32 tok, u8 reg, u32 size) +lba_rd_cfg(struct lba_device *d, u32 tok, u8 reg, u32 size) { u32 data = ~0; int error = 0; @@ -525,7 +505,6 @@ } - #define LBA_CFG_RD(size, mask) \ static int lba_cfg_read##size (struct pci_dev *dev, int pos, u##size *data) \ { \ @@ -533,17 +512,18 @@ u32 local_bus = (dev->bus->parent == NULL) ? 0 : dev->bus->secondary; \ u32 tok = LBA_CFG_TOK(local_bus,dev->devfn); \ \ - if ((!LBA_TR4PLUS(d)) && (!LBA_SKIP_PROBE(d))) { \ +/* FIXME: B2K/C3600 workaround is always use old method... */ \ + /* if (!LBA_TR4PLUS(d) && !LBA_SKIP_PROBE(d)) */ { \ /* original - Generate config cycle on broken elroy \ with risk we will miss PCI bus errors. */ \ *data = (u##size) lba_rd_cfg(d, tok, pos, sizeof(u##size)); \ - DBG_CFG(KERN_DEBUG "%s(%s+%2x) -> 0x%x (a)\n", __FUNCTION__, dev->slot_name, pos, *data); \ + DBG_CFG("%s(%s+%2x) -> 0x%x (a)\n", __FUNCTION__, dev->slot_name, pos, *data); \ return(*data == (u##size) -1); \ } \ \ if (LBA_SKIP_PROBE(d) && (!lba_device_present(dev->bus->secondary, dev->devfn, d))) \ { \ - DBG_CFG(KERN_DEBUG "%s(%s+%2x) -> -1 (b)\n", __FUNCTION__, dev->slot_name, pos, *data); \ + DBG_CFG("%s(%s+%2x) -> -1 (b)\n", __FUNCTION__, dev->slot_name, pos); \ /* either don't want to look or know device isn't present. */ \ *data = (u##size) -1; \ return(0); \ @@ -555,7 +535,7 @@ */ \ LBA_CFG_TR4_ADDR_SETUP(d, tok | pos); \ *data = READ_REG##size(d->hba.base_addr + LBA_PCI_CFG_DATA + (pos & mask));\ - DBG_CFG(KERN_DEBUG "%s(%s+%2x) -> 0x%x (c)\n", __FUNCTION__, dev->slot_name, pos, *data);\ + DBG_CFG("%s(%s+%2x) -> 0x%x (c)\n", __FUNCTION__, dev->slot_name, pos, *data);\ return(*data == (u##size) -1); \ } @@ -618,19 +598,19 @@ ASSERT((tok & 0xff) == 0); \ ASSERT(pos < 0x100); \ \ - if ((!LBA_TR4PLUS(d)) && (!LBA_SKIP_PROBE(d))) { \ + if (!LBA_TR4PLUS(d) && !LBA_SKIP_PROBE(d)) { \ /* Original Workaround */ \ lba_wr_cfg(d, tok, pos, (u32) data, sizeof(u##size)); \ - DBG_CFG(KERN_DEBUG "%s(%s+%2x) = 0x%x (a)\n", __FUNCTION__, dev->slot_name, pos, data); \ + DBG_CFG("%s(%s+%2x) = 0x%x (a)\n", __FUNCTION__, dev->slot_name, pos, data); \ return 0; \ } \ \ if (LBA_SKIP_PROBE(d) && (!lba_device_present(dev->bus->secondary, dev->devfn, d))) { \ - DBG_CFG(KERN_DEBUG "%s(%s+%2x) = 0x%x (b)\n", __FUNCTION__, dev->slot_name, pos, data); \ + DBG_CFG("%s(%s+%2x) = 0x%x (b)\n", __FUNCTION__, dev->slot_name, pos, data); \ return 1; /* New Workaround */ \ } \ \ - DBG_CFG(KERN_DEBUG "%s(%s+%2x) = 0x%x (c)\n", __FUNCTION__, dev->slot_name, pos, data); \ + DBG_CFG("%s(%s+%2x) = 0x%x (c)\n", __FUNCTION__, dev->slot_name, pos, data); \ /* Basic Algorithm */ \ LBA_CFG_TR4_ADDR_SETUP(d, tok | pos); \ WRITE_REG##size(data, d->hba.base_addr + LBA_PCI_CFG_DATA + (pos & mask)); \ @@ -644,9 +624,12 @@ LBA_CFG_WR(32, 0) static struct pci_ops lba_cfg_ops = { - lba_cfg_read8, lba_cfg_read16, lba_cfg_read32, - lba_cfg_write8, lba_cfg_write16, lba_cfg_write32 - + read_byte: lba_cfg_read8, + read_word: lba_cfg_read16, + read_dword: lba_cfg_read32, + write_byte: lba_cfg_write8, + write_word: lba_cfg_write16, + write_dword: lba_cfg_write32 }; @@ -654,7 +637,7 @@ static void lba_bios_init(void) { - DBG(KERN_DEBUG MODULE_NAME ": lba_bios_init\n"); + DBG(MODULE_NAME ": lba_bios_init\n"); } @@ -712,15 +695,15 @@ lba_fixup_bus(struct pci_bus *bus) { struct list_head *ln; - struct pci_dev *dev; +#ifdef FBB_SUPPORT u16 fbb_enable = PCI_STATUS_FAST_BACK; u16 status; - struct lba_device *ldev = LBA_DEV(bus->sysdata); -#ifdef __LP64__ - int i; #endif + struct lba_device *ldev = LBA_DEV(bus->sysdata); + int lba_portbase = HBA_PORT_BASE(ldev->hba.hba_num); + DBG("lba_fixup_bus(0x%p) bus %d sysdata 0x%p\n", - bus, bus->secondary, bus->sysdata); + bus, bus->secondary, bus->sysdata); /* ** Properly Setup MMIO resources for this bus. @@ -731,63 +714,119 @@ DBG("lba_fixup_bus() %s [%lx/%lx]/%x\n", ldev->hba.io_space.name, - ldev->hba.io_space.start, - ldev->hba.io_space.end, + ldev->hba.io_space.start, ldev->hba.io_space.end, (int) ldev->hba.io_space.flags); DBG("lba_fixup_bus() %s [%lx/%lx]/%x\n", - ldev->hba.mem_space.name, - ldev->hba.mem_space.start, - ldev->hba.mem_space.end, - (int) ldev->hba.mem_space.flags); + ldev->hba.lmmio_space.name, + ldev->hba.lmmio_space.start, ldev->hba.lmmio_space.end, + (int) ldev->hba.lmmio_space.flags); err = request_resource(&ioport_resource, &(ldev->hba.io_space)); if (err < 0) { BUG(); lba_dump_res(&ioport_resource, 2); } - err = request_resource(&iomem_resource, &(ldev->hba.mem_space)); + err = request_resource(&iomem_resource, &(ldev->hba.lmmio_space)); if (err < 0) { BUG(); lba_dump_res(&iomem_resource, 2); } bus->resource[0] = &(ldev->hba.io_space); - bus->resource[1] = &(ldev->hba.mem_space); + bus->resource[1] = &(ldev->hba.lmmio_space); + } else { + /* KLUGE ALERT! + ** PCI-PCI Bridge resource munging. + ** This hack should go away in the near future. + ** It's based on the Alpha port. + */ + int i; + u16 cmd; + + for (i = 0; i < 4; i++) { + bus->resource[i] = + &bus->self->resource[PCI_BRIDGE_RESOURCES+i]; + bus->resource[i]->name = bus->name; + } +#if 0 + bus->resource[0]->flags |= pci_bridge_check_io(bus->self); +#else + bus->resource[0]->flags |= IORESOURCE_IO; +#endif + bus->resource[1]->flags |= IORESOURCE_MEM; + bus->resource[2]->flags = 0; /* Don't support prefetchable */ + bus->resource[3]->flags = 0; /* not used */ + + /* + ** If the PPB is enabled (ie already configured) then + ** just read those values. + */ + (void) lba_cfg_read16(bus->self, PCI_COMMAND, &cmd); + if (cmd & (PCI_COMMAND_MEMORY | PCI_COMMAND_IO)) { + pci_read_bridge_bases(bus); + } else { + /* Not configured. + ** For now, propogate HBA limits to the bus; + ** PCI will adjust them later. + */ + bus->resource[0]->end = ldev->hba.io_space.end; + bus->resource[1]->end = ldev->hba.lmmio_space.end; + } + + /* Turn off downstream PF memory address range by default */ + bus->resource[2]->start = 1024*1024; + bus->resource[2]->end = bus->resource[2]->start - 1; } - list_for_each(ln, &bus->devices) { - dev = pci_dev_b(ln); + list_for_each(ln, &bus->devices) { + int i; + struct pci_dev *dev = pci_dev_b(ln); -#ifdef __LP64__ - /* - ** 0-5 are the "standard PCI regions" - ** (see comments near PCI_NUM_RESOURCES in include/linux/pci.h) - */ - for (i = 0; i <= PCI_ROM_RESOURCE; i++) { - struct resource *res = &(dev->resource[i]); + DBG("lba_fixup_bus() %s\n", dev->name); - if (res->flags & IORESOURCE_MEM) { - /* "Globalize" PCI address */ - res->start |= ldev->lmmio_base; - res->end |= ldev->lmmio_base; + /* Virtualize Device/Bridge Resources. */ + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + struct resource *res = &dev->resource[i]; + + /* If resource not allocated - skip it */ + if (!res->start) + continue; + + if (res->flags & IORESOURCE_IO) { + DBG("lba_fixup_bus() I/O Ports [%lx/%lx] -> ", + res->start, res->end); + res->start |= lba_portbase; + res->end |= lba_portbase; + DBG("[%lx/%lx]\n", res->start, res->end); + } else if (res->flags & IORESOURCE_MEM) { + /* + ** Convert PCI (IO_VIEW) addresses to + ** processor (PA_VIEW) addresses + */ + DBG("lba_fixup_bus() MMIO [%lx/%lx] -> ", + res->start, res->end); + res->start = PCI_HOST_ADDR(HBA_DATA(ldev), res->start); + res->end = PCI_HOST_ADDR(HBA_DATA(ldev), res->end); + DBG("[%lx/%lx]\n", res->start, res->end); } } -#endif +#ifdef FBB_SUPPORT /* ** If one device does not support FBB transfers, ** No one on the bus can be allowed to use them. */ (void) lba_cfg_read16(dev, PCI_STATUS, &status); fbb_enable &= status; +#endif #ifdef __LP64__ - if (pdc_pat) { + if (is_pdc_pat()) { /* Claim resources for PDC's devices */ lba_claim_dev_resources(dev); } -#endif /* __LP64__ */ +#endif /* ** P2PB's have no IRQs. ignore them. @@ -796,12 +835,12 @@ continue; /* Adjust INTERRUPT_LINE for this dev */ - iosapic_fixup_irq(LBA_DEV(bus->sysdata)->iosapic_obj, dev); + iosapic_fixup_irq(ldev->iosapic_obj, dev); } -#if 0 +#ifdef FBB_SUPPORT /* FIXME/REVISIT - finish figuring out to set FBB on both -** pbus_set_ranges() clobbers PCI_BRIDGE_CONTROL. +** pci_setup_bridge() clobbers PCI_BRIDGE_CONTROL. ** Can't fixup here anyway....garr... */ if (fbb_enable) { @@ -828,8 +867,8 @@ struct pci_bios_ops lba_bios_ops = { - lba_bios_init, - lba_fixup_bus /* void lba_fixup_bus(struct pci_bus *bus) */ + init: lba_bios_init, + fixup_bus: lba_fixup_bus, }; @@ -853,8 +892,6 @@ static u##size lba_astro_in##size (struct pci_hba_data *d, u16 addr) \ { \ u##size t; \ - ASSERT(bus != NULL); \ - DBG_PORT(KERN_DEBUG "%s(0x%p, 0x%x) ->", __FUNCTION__, bus, addr); \ t = READ_REG##size(LBA_ASTRO_PORT_BASE + addr); \ DBG_PORT(" 0x%x\n", t); \ return (t); \ @@ -895,8 +932,8 @@ #define LBA_PORT_OUT(size, mask) \ static void lba_astro_out##size (struct pci_hba_data *d, u16 addr, u##size val) \ { \ - ASSERT(bus != NULL); \ - DBG_PORT(KERN_DEBUG "%s(0x%p, 0x%x, 0x%x)\n", __FUNCTION__, d, addr, val); \ + ASSERT(d != NULL); \ + DBG_PORT("%s(0x%p, 0x%x, 0x%x)\n", __FUNCTION__, d, addr, val); \ WRITE_REG##size(val, LBA_ASTRO_PORT_BASE + addr); \ if (LBA_DEV(d)->hw_rev < 3) \ lba_t32 = READ_U32(d->base_addr + LBA_FUNC_ID); \ @@ -908,13 +945,16 @@ static struct pci_port_ops lba_astro_port_ops = { - lba_astro_in8, lba_astro_in16, lba_astro_in32, - lba_astro_out8, lba_astro_out16, lba_astro_out32 + inb: lba_astro_in8, + inw: lba_astro_in16, + inl: lba_astro_in32, + outb: lba_astro_out8, + outw: lba_astro_out16, + outl: lba_astro_out32 }; #ifdef __LP64__ - #define PIOP_TO_GMMIO(lba, addr) \ ((lba)->iop_base + (((addr)&0xFFFC)<<10) + ((addr)&3)) @@ -936,7 +976,7 @@ { \ u##size t; \ ASSERT(bus != NULL); \ - DBG_PORT(KERN_DEBUG "%s(0x%p, 0x%x) ->", __FUNCTION__, l, addr); \ + DBG_PORT("%s(0x%p, 0x%x) ->", __FUNCTION__, l, addr); \ t = READ_REG##size(PIOP_TO_GMMIO(LBA_DEV(l), addr)); \ DBG_PORT(" 0x%x\n", t); \ return (t); \ @@ -953,7 +993,7 @@ { \ void *where = (void *) PIOP_TO_GMMIO(LBA_DEV(l), addr); \ ASSERT(bus != NULL); \ - DBG_PORT(KERN_DEBUG "%s(0x%p, 0x%x, 0x%x)\n", __FUNCTION__, l, addr, val); \ + DBG_PORT("%s(0x%p, 0x%x, 0x%x)\n", __FUNCTION__, l, addr, val); \ WRITE_REG##size(val, where); \ /* flush the I/O down to the elroy at least */ \ lba_t32 = READ_U32(l->base_addr + LBA_FUNC_ID); \ @@ -965,8 +1005,12 @@ static struct pci_port_ops lba_pat_port_ops = { - lba_pat_in8, lba_pat_in16, lba_pat_in32, - lba_pat_out8, lba_pat_out16, lba_pat_out32 + inb: lba_pat_in8, + inw: lba_pat_in16, + inl: lba_pat_in32, + outb: lba_pat_out8, + outw: lba_pat_out16, + outl: lba_pat_out32 }; @@ -978,30 +1022,27 @@ ** We don't have a struct pci_bus assigned to us yet. */ static void -lba_pat_resources( struct hp_device *d, struct lba_device *lba_dev) +lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) { + unsigned long bytecnt; pdc_pat_cell_mod_maddr_block_t pa_pdc_cell; /* PA_VIEW */ -#ifdef DONT_NEED_THIS_FOR_ASTRO pdc_pat_cell_mod_maddr_block_t io_pdc_cell; /* IO_VIEW */ long io_count; -#endif long status; /* PDC return status */ long pa_count; int i; /* return cell module (IO view) */ - status = pdc_pat_cell_module(& pdc_result, d->pcell_loc, d->mod_index, + status = pdc_pat_cell_module(&bytecnt, pa_dev->pcell_loc, pa_dev->mod_index, PA_VIEW, & pa_pdc_cell); pa_count = pa_pdc_cell.mod[1]; -#ifdef DONT_NEED_THIS_FOR_ASTRO - status |= pdc_pat_cell_module(& pdc_result, d->pcell_loc, d->mod_index, - IO_VIEW, & io_pdc_cell); + status |= pdc_pat_cell_module(&bytecnt, pa_dev->pcell_loc, pa_dev->mod_index, + IO_VIEW, &io_pdc_cell); io_count = io_pdc_cell.mod[1]; -#endif /* We've already done this once for device discovery...*/ - if (status != PDC_RET_OK) { + if (status != PDC_OK) { panic("pdc_pat_cell_module() call failed for LBA!\n"); } @@ -1017,10 +1058,11 @@ unsigned long type; unsigned long start; unsigned long end; /* aka finish */ - } *p; + } *p, *io; struct resource *r; p = (void *) &(pa_pdc_cell.mod[2+i*3]); + io = (void *) &(io_pdc_cell.mod[2+i*3]); /* Convert the PAT range data to PCI "struct resource" */ switch(p->type & 0xff) { @@ -1030,9 +1072,9 @@ break; case PAT_LMMIO: /* used to fix up pre-initialized MEM BARs */ - lba_dev->lmmio_base = p->start; + lba_dev->hba.lmmio_space_offset = p->start - io->start; - r = &(lba_dev->hba.mem_space); + r = &(lba_dev->hba.lmmio_space); r->name = "LBA LMMIO"; r->start = p->start; r->end = p->end; @@ -1060,8 +1102,8 @@ r = &(lba_dev->hba.io_space); r->name = "LBA I/O Port"; - r->start = lba_dev->hba.hba_num << 16; - r->end = r->start + 0xffffUL; + r->start = HBA_PORT_BASE(lba_dev->hba.hba_num); + r->end = r->start + HBA_PORT_SPACE_SIZE - 1; r->flags = IORESOURCE_IO; r->parent = r->sibling = r->child = NULL; break; @@ -1077,17 +1119,22 @@ static void -lba_legacy_resources( struct hp_device *d, struct lba_device *lba_dev) +lba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) { - int lba_num; struct resource *r; + unsigned long rsize; + int lba_num; + #ifdef __LP64__ /* - ** Used to sign extend instead BAR values are only 32-bit. - ** 64-bit BARs have the upper 32-bit's zero'd by firmware. - ** "Sprockets" PDC initializes for 32-bit OS. + ** Sign extend all BAR values on "legacy" platforms. + ** "Sprockets" PDC (Forte/Allegro) initializes everything + ** for "legacy" 32-bit OS (HPUX 10.20). + ** Upper 32-bits of 64-bit BAR will be zero too. */ - lba_dev->lmmio_base = 0xffffffff00000000UL; + lba_dev->hba.lmmio_space_offset = 0xffffffff00000000UL; +#else + lba_dev->hba.lmmio_space_offset = 0UL; #endif /* @@ -1097,7 +1144,7 @@ ** PCI bus walk *should* end up with the same result. ** FIXME: But we don't have sanity checks in PCI or LBA. */ - lba_num = READ_REG32(d->hpa + LBA_FW_SCRATCH); + lba_num = READ_REG32(pa_dev->hpa + LBA_FW_SCRATCH); r = &(lba_dev->hba.bus_num); r->name = "LBA PCI Busses"; r->start = lba_num & 0xff; @@ -1106,19 +1153,67 @@ /* Set up local PCI Bus resources - we don't really need ** them for Legacy boxes but it's nice to see in /proc. */ - r = &(lba_dev->hba.mem_space); + r = &(lba_dev->hba.lmmio_space); r->name = "LBA PCI LMMIO"; r->flags = IORESOURCE_MEM; - r->start = READ_REG32(d->hpa + LBA_LMMIO_BASE); - r->end = r->start + ~ (READ_REG32(d->hpa + LBA_LMMIO_MASK)); + /* Ignore "Range Enable" bit in the BASE register */ + r->start = PCI_HOST_ADDR(HBA_DATA(lba_dev), + ((long) READ_REG32(pa_dev->hpa + LBA_LMMIO_BASE)) & ~1UL); + rsize = ~READ_REG32(pa_dev->hpa + LBA_LMMIO_MASK) + 1; + + /* + ** Each rope only gets part of the distributed range. + ** Adjust "window" for this rope + */ + rsize /= ROPES_PER_SBA; + r->start += rsize * LBA_NUM(pa_dev->hpa); + r->end = r->start + rsize - 1 ; + + /* + ** XXX FIXME - ignore LBA_ELMMIO_BASE for now + ** "Directed" ranges are used when the "distributed range" isn't + ** sufficient for all devices below a given LBA. Typically devices + ** like graphics cards or X25 may need a directed range when the + ** bus has multiple slots (ie multiple devices) or the device + ** needs more than the typical 4 or 8MB a distributed range offers. + ** + ** The main reason for ignoring it now frigging complications. + ** Directed ranges may overlap (and have precedence) over + ** distributed ranges. Ie a distributed range assigned to a unused + ** rope may be used by a directed range on a different rope. + ** Support for graphics devices may require fixing this + ** since they may be assigned a directed range which overlaps + ** an existing (but unused portion of) distributed range. + */ + r = &(lba_dev->hba.elmmio_space); + r->name = "extra LBA PCI LMMIO"; + r->flags = IORESOURCE_MEM; + r->start = READ_REG32(pa_dev->hpa + LBA_ELMMIO_BASE); + r->end = 0; + + /* check Range Enable bit */ + if (r->start & 1) { + /* First baby step to getting Direct Ranges listed in /proc. + ** AFAIK, only Sprockets PDC will setup a directed Range. + */ + + r->start &= ~1; + r->end = r->start; + r->end += ~READ_REG32(pa_dev->hpa + LBA_ELMMIO_MASK); + printk(KERN_DEBUG "WARNING: Ignoring enabled ELMMIO BASE 0x%0lx SIZE 0x%lx\n", + r->start, + r->end + 1); + + } r = &(lba_dev->hba.io_space); r->name = "LBA PCI I/O Ports"; r->flags = IORESOURCE_IO; - r->start = READ_REG32(d->hpa + LBA_IOS_BASE); - r->end = r->start + (READ_REG32(d->hpa + LBA_IOS_MASK) ^ 0xffff); + r->start = READ_REG32(pa_dev->hpa + LBA_IOS_BASE) & ~1L; + r->end = r->start + (READ_REG32(pa_dev->hpa + LBA_IOS_MASK) ^ (HBA_PORT_SPACE_SIZE - 1)); - lba_num = lba_dev->hba.hba_num << 16; + /* Virtualize the I/O Port space ranges */ + lba_num = HBA_PORT_BASE(lba_dev->hba.hba_num); r->start |= lba_num; r->end |= lba_num; } @@ -1136,29 +1231,92 @@ ** **************************************************************************/ -static void +static int __init lba_hw_init(struct lba_device *d) { u32 stat; + u32 bus_reset; /* PDC_PAT_BUG */ + +#if 0 + printk(KERN_DEBUG "LBA %lx STAT_CTL %Lx ERROR_CFG %Lx STATUS %Lx DMA_CTL %Lx\n", + d->hba.base_addr, + READ_REG64(d->hba.base_addr + LBA_STAT_CTL), + READ_REG64(d->hba.base_addr + LBA_ERROR_CONFIG), + READ_REG64(d->hba.base_addr + LBA_ERROR_STATUS), + READ_REG64(d->hba.base_addr + LBA_DMA_CTL) ); + printk(KERN_DEBUG " ARB mask %Lx pri %Lx mode %Lx mtlt %Lx\n", + READ_REG64(d->hba.base_addr + LBA_ARB_MASK), + READ_REG64(d->hba.base_addr + LBA_ARB_PRI), + READ_REG64(d->hba.base_addr + LBA_ARB_MODE), + READ_REG64(d->hba.base_addr + LBA_ARB_MTLT) ); + printk(KERN_DEBUG " HINT cfg 0x%Lx\n", + READ_REG64(d->hba.base_addr + LBA_HINT_CFG)); + printk(KERN_DEBUG " HINT reg "); + { int i; + for (i=LBA_HINT_BASE; i< (14*8 + LBA_HINT_BASE); i+=8) + printk(" %Lx", READ_REG64(d->hba.base_addr + i)); + } + printk("\n"); +#endif /* DEBUG_LBA_PAT */ + +#ifdef __LP64__ +#warning FIXME add support for PDC_PAT_IO "Get slot status" - OLAR support +#endif + + /* PDC_PAT_BUG: exhibited in rev 40.48 on L2000 */ + bus_reset = READ_REG32(d->hba.base_addr + LBA_STAT_CTL + 4) & 1; + if (bus_reset) { + printk(KERN_DEBUG "NOTICE: PCI bus reset still asserted! (clearing)\n"); + } + + stat = READ_REG32(d->hba.base_addr + LBA_ERROR_CONFIG); + if (stat & LBA_SMART_MODE) { + printk(KERN_DEBUG "NOTICE: LBA in SMART mode! (cleared)\n"); + stat &= ~LBA_SMART_MODE; + WRITE_REG32(stat, d->hba.base_addr + LBA_ERROR_CONFIG); + } /* Set HF mode as the default (vs. -1 mode). */ stat = READ_REG32(d->hba.base_addr + LBA_STAT_CTL); WRITE_REG32(stat | HF_ENABLE, d->hba.base_addr + LBA_STAT_CTL); /* + ** Writing a zero to STAT_CTL.rf (bit 0) will clear reset signal + ** if it's not already set. If we just cleared the PCI Bus Reset + ** signal, wait a bit for the PCI devices to recover and setup. + */ + if (bus_reset) + mdelay(pci_post_reset_delay); + + if (0 == READ_REG32(d->hba.base_addr + LBA_ARB_MASK)) { + /* + ** PDC_PAT_BUG: PDC rev 40.48 on L2000. + ** B2000/C3600/J6000 also have this problem? + ** + ** Elroys with hot pluggable slots don't get configured + ** correctly if the slot is empty. ARB_MASK is set to 0 + ** and we can't master transactions on the bus if it's + ** not at least one. 0x3 enables elroy and first slot. + */ + printk(KERN_DEBUG "NOTICE: Enabling PCI Arbitration\n"); + WRITE_REG32(0x3, d->hba.base_addr + LBA_ARB_MASK); + } + + /* ** FIXME: Hint registers are programmed with default hint ** values by firmware. Hints should be sane even if we ** can't reprogram them the way drivers want. */ + return 0; } -static void +static void __init lba_common_init(struct lba_device *lba_dev) { pci_bios = &lba_bios_ops; - pcibios_register_hba((struct pci_hba_data *)lba_dev); + pcibios_register_hba(HBA_DATA(lba_dev)); lba_dev->lba_lock = SPIN_LOCK_UNLOCKED; /* @@ -1176,32 +1334,31 @@ ** If so, initialize the chip and tell other partners in crime they ** have work to do. */ -static __init int -lba_driver_callback(struct hp_device *d, struct pa_iodc_driver *dri) +static int __init +lba_driver_callback(struct parisc_device *dev) { struct lba_device *lba_dev; struct pci_bus *lba_bus; u32 func_class; void *tmp_obj; - - /* from drivers/pci/setup-bus.c */ - extern void __init pbus_set_ranges(struct pci_bus *, struct pbus_set_ranges_data *); + char *version; /* Read HW Rev First */ - func_class = READ_REG32(d->hpa + LBA_FCLASS); + func_class = READ_REG32(dev->hpa + LBA_FCLASS); func_class &= 0xf; switch (func_class) { - case 0: dri->version = "TR1.0"; break; - case 1: dri->version = "TR2.0"; break; - case 2: dri->version = "TR2.1"; break; - case 3: dri->version = "TR2.2"; break; - case 4: dri->version = "TR3.0"; break; - case 5: dri->version = "TR4.0"; break; - default: dri->version = "TR4+"; + case 0: version = "TR1.0"; break; + case 1: version = "TR2.0"; break; + case 2: version = "TR2.1"; break; + case 3: version = "TR2.2"; break; + case 4: version = "TR3.0"; break; + case 5: version = "TR4.0"; break; + default: version = "TR4+"; } - printk("%s version %s (0x%x) found at 0x%p\n", dri->name, dri->version, func_class & 0xf, d->hpa); + printk(KERN_INFO "%s version %s (0x%x) found at 0x%lx\n", + MODULE_NAME, version, func_class & 0xf, dev->hpa); /* Just in case we find some prototypes... */ if (func_class < 2) { @@ -1212,22 +1369,16 @@ /* ** Tell I/O SAPIC driver we have a IRQ handler/region. */ - tmp_obj = iosapic_register(d->hpa+LBA_IOSAPIC_BASE); - if (NULL == tmp_obj) { - /* iosapic may have failed. But more likely the - ** slot isn't occupied and thus has no IRT entries. - ** iosapic_register looks for this iosapic in the IRT - ** before bothering to allocating data structures - ** we don't need. - */ - DBG(KERN_WARNING MODULE_NAME ": iosapic_register says not used\n"); - return (1); - } + tmp_obj = iosapic_register(dev->hpa + LBA_IOSAPIC_BASE); + /* NOTE: PCI devices (e.g. 103c:1005 graphics card) which don't + ** have an IRT entry will get NULL back from iosapic code. + */ + lba_dev = kmalloc(sizeof(struct lba_device), GFP_KERNEL); if (NULL == lba_dev) { - printk("lba_init_chip - couldn't alloc lba_device\n"); + printk(KERN_ERR "lba_init_chip - couldn't alloc lba_device\n"); return(1); } @@ -1242,48 +1393,45 @@ */ lba_dev->hw_rev = func_class; - lba_dev->hba.base_addr = d->hpa; /* faster access */ + lba_dev->hba.base_addr = dev->hpa; /* faster access */ + lba_dev->hba.dev = dev; lba_dev->iosapic_obj = tmp_obj; /* save interrupt handle */ + lba_dev->hba.iommu = sba_get_iommu(dev); /* get iommu data */ /* ------------ Second : initialize common stuff ---------- */ lba_common_init(lba_dev); - lba_hw_init(lba_dev); + + if (lba_hw_init(lba_dev)) + return(1); /* ---------- Third : setup I/O Port and MMIO resources --------- */ -#ifdef __LP64__ - if (pdc_pat) { +#ifdef __LP64__ + if (is_pdc_pat()) { /* PDC PAT firmware uses PIOP region of GMMIO space. */ pci_port = &lba_pat_port_ops; /* Go ask PDC PAT what resources this LBA has */ - lba_pat_resources(d, lba_dev); - - } else { + lba_pat_resources(dev, lba_dev); + } else #endif + { /* Sprockets PDC uses NPIOP region */ pci_port = &lba_astro_port_ops; /* Poke the chip a bit for /proc output */ - lba_legacy_resources(d, lba_dev); -#ifdef __LP64__ + lba_legacy_resources(dev, lba_dev); } -#endif /* ** Tell PCI support another PCI bus was found. ** Walks PCI bus for us too. */ lba_bus = lba_dev->hba.hba_bus = - pci_scan_bus( lba_dev->hba.bus_num.start, &lba_cfg_ops, (void *) lba_dev); + pci_scan_bus(lba_dev->hba.bus_num.start, &lba_cfg_ops, (void *) lba_dev); #ifdef __LP64__ - if (pdc_pat) { - - /* determine window sizes needed by PCI-PCI bridges */ - DBG_PAT("LBA pcibios_size_bridge()\n"); - pcibios_size_bridge(lba_bus, NULL); - + if (is_pdc_pat()) { /* assign resources to un-initialized devices */ DBG_PAT("LBA pcibios_assign_unassigned_resources()\n"); pcibios_assign_unassigned_resources(lba_bus); @@ -1292,14 +1440,10 @@ DBG_PAT("\nLBA PIOP resource tree\n"); lba_dump_res(&lba_dev->hba.io_space, 2); DBG_PAT("\nLBA LMMIO resource tree\n"); - lba_dump_res(&lba_dev->hba.mem_space, 2); + lba_dump_res(&lba_dev->hba.lmmio_space, 2); #endif - - /* program *all* PCI-PCI bridge range registers */ - DBG_PAT("LBA pbus_set_ranges()\n"); - pbus_set_ranges(lba_bus, NULL); } -#endif /* __LP64__ */ +#endif /* ** Once PCI register ops has walked the bus, access to config @@ -1314,33 +1458,43 @@ return 0; } +static struct parisc_device_id lba_tbl[] = { + { HPHW_BRIDGE, HVERSION_REV_ANY_ID, 0x782, 0xa }, + { 0, } +}; + +static struct parisc_driver lba_driver = { + name: MODULE_NAME, + id_table: lba_tbl, + probe: lba_driver_callback +}; + +/* +** One time initialization to let the world know the LBA was found. +** Must be called exactly once before pci_init(). +*/ +void __init lba_init(void) +{ + register_parisc_driver(&lba_driver); +} /* ** Initialize the IBASE/IMASK registers for LBA (Elroy). -** Only called from sba_iommu.c initialization sequence. +** Only called from sba_iommu.c in order to route ranges (MMIO vs DMA). +** sba_iommu is responsible for locking (none needed at init time). */ -void lba_init_iregs(void *sba_hpa, u32 ibase, u32 imask) +void +lba_set_iregs(struct parisc_device *lba, u32 ibase, u32 imask) { - extern struct pci_hba_data *hba_list; /* arch/parisc/kernel/pci.c */ - struct pci_hba_data *lba; + unsigned long base_addr = lba->hpa; imask <<= 2; /* adjust for hints - 2 more bits */ ASSERT((ibase & 0x003fffff) == 0); ASSERT((imask & 0x003fffff) == 0); - /* FIXME: sba_hpa is intended to search some table to - ** determine which LBA's belong to the caller's SBA. - ** IS_ASTRO: just assume only one SBA for now. - */ - ASSERT(NULL != hba_list); - DBG(KERN_DEBUG "%s() ibase 0x%x imask 0x%x\n", __FUNCTION__, ibase, imask); - - for (lba = hba_list; NULL != lba; lba = lba->next) { - DBG(KERN_DEBUG "%s() base_addr %p\n", __FUNCTION__, lba->base_addr); - WRITE_REG32( imask, lba->base_addr + LBA_IMASK); - WRITE_REG32( ibase, lba->base_addr + LBA_IBASE); - } - DBG(KERN_DEBUG "%s() done\n", __FUNCTION__); + DBG("%s() ibase 0x%x imask 0x%x\n", __FUNCTION__, ibase, imask); + WRITE_REG32( imask, base_addr + LBA_IMASK); + WRITE_REG32( ibase, base_addr + LBA_IBASE); } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/led.c linux.19rc3-ac4/arch/parisc/kernel/led.c --- linux.19rc3/arch/parisc/kernel/led.c 2002-07-29 12:50:06.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/led.c 2002-07-29 13:58:36.000000000 +0100 @@ -3,34 +3,64 @@ * * (c) Copyright 2000 Red Hat Software * (c) Copyright 2000 Helge Deller + * (c) Copyright 2001-2002 Helge Deller + * (c) Copyright 2001 Randolph Chung * * 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. * + * TODO: + * - speed-up calculations with inlined assembler + * - interface to write to second row of LCD from /proc */ #include +#include +#include /* for offsetof() */ #include -#include #include -#include #include #include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include #include #include /* HZ */ #include +#include +#include +/* The control of the LEDs and LCDs on PARISC-machines have to be done + completely in software. The necessary calculations are done in a tasklet + which is scheduled at every timer interrupt and since the calculations + may consume relatively much CPU-time some of the calculations can be + turned off with the following variables (controlled via procfs) */ + +static int led_type = -1; +static int led_heartbeat = 1; +static int led_diskio = 1; +static int led_lanrxtx = 1; +static char lcd_text[32]; -/* define to disable all LED functions */ -#undef DISABLE_LEDS +#if 0 +#define DPRINTK(x) printk x +#else +#define DPRINTK(x) +#endif -#define CPU_HVERSION ((boot_cpu_data.hversion >> 4) & 0x0FFF) +#define CALC_ADD(val, comp, add) \ + (val<=(comp/8) ? add/16 : val<=(comp/4) ? add/8 : val<=(comp/2) ? add/4 : add) struct lcd_block { @@ -40,8 +70,10 @@ }; /* Structure returned by PDC_RETURN_CHASSIS_INFO */ +/* NOTE: we use unsigned long:16 two times, since the following member + lcd_cmd_reg_addr needs to be 64bit aligned on 64bit PA2.0-machines */ struct pdc_chassis_lcd_info_ret_block { - unsigned long model:16; /* DISPLAY_MODEL_XXXX (see below) */ + unsigned long model:16; /* DISPLAY_MODEL_XXXX */ unsigned long lcd_width:16; /* width of the LCD in chars (DISPLAY_MODEL_LCD only) */ char *lcd_cmd_reg_addr; /* ptr to LCD cmd-register & data ptr for LED */ char *lcd_data_reg_addr; /* ptr to LCD data-register (LCD only) */ @@ -56,33 +88,23 @@ char _pad; }; -/* values for pdc_chassis_lcd_info_ret_block.model: */ -#define DISPLAY_MODEL_LCD 0 /* KittyHawk LED or LCD */ -#define DISPLAY_MODEL_NONE 1 /* no LED or LCD */ -#define DISPLAY_MODEL_LASI 2 /* LASI style 8 bit LED */ -#define DISPLAY_MODEL_OLD_ASP 0x7F /* faked: ASP style 8 x 1 bit LED (only very old ASP versions) */ - /* LCD_CMD and LCD_DATA for KittyHawk machines */ -#ifdef __LP64__ -#define KITTYHAWK_LCD_CMD 0xfffffffff0190000L -#else -#define KITTYHAWK_LCD_CMD 0xf0190000 -#endif -#define KITTYHAWK_LCD_DATA (KITTYHAWK_LCD_CMD + 1) +#define KITTYHAWK_LCD_CMD (0xfffffffff0190000UL) /* 64bit-ready */ +#define KITTYHAWK_LCD_DATA (KITTYHAWK_LCD_CMD+1) - -/* lcd_info is pre-initialized to the values needed to program KittyHawk LCD's */ +/* lcd_info is pre-initialized to the values needed to program KittyHawk LCD's + * HP seems to have used Sharp/Hitachi HD44780 LCDs most of the time. */ static struct pdc_chassis_lcd_info_ret_block lcd_info __attribute__((aligned(8))) = { - model:DISPLAY_MODEL_LCD, - lcd_width:16, - lcd_cmd_reg_addr:(char *) KITTYHAWK_LCD_CMD, + model: DISPLAY_MODEL_LCD, + lcd_width: 16, + lcd_cmd_reg_addr: (char *) KITTYHAWK_LCD_CMD, lcd_data_reg_addr:(char *) KITTYHAWK_LCD_DATA, - min_cmd_delay:40, - reset_cmd1:0x80, - reset_cmd2:0xc0, + min_cmd_delay: 40, + reset_cmd1: 0x80, + reset_cmd2: 0xc0, }; @@ -92,7 +114,143 @@ #define LED_DATA_REG lcd_info.lcd_cmd_reg_addr /* LASI & ASP only */ +/* ptr to LCD/LED-specific function */ +static void (*led_func_ptr) (unsigned char); + +#define LED_HASLCD 1 +#define LED_NOLCD 0 +#ifdef CONFIG_PROC_FS +static int led_proc_read(char *page, char **start, off_t off, int count, + int *eof, void *data) +{ + char *out = page; + int len; + + switch ((long)data) + { + case LED_NOLCD: + out += sprintf(out, "Heartbeat: %d\n", led_heartbeat); + out += sprintf(out, "Disk IO: %d\n", led_diskio); + out += sprintf(out, "LAN Rx/Tx: %d\n", led_lanrxtx); + break; + case LED_HASLCD: + out += sprintf(out, "%s\n", lcd_text); + break; + default: + *eof = 1; + return 0; + } + + len = out - page - off; + if (len < count) { + *eof = 1; + if (len <= 0) return 0; + } else { + len = count; + } + *start = page + off; + return len; +} + +static int led_proc_write(struct file *file, const char *buf, + unsigned long count, void *data) +{ + char *cur, lbuf[count]; + int d; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + memset(lbuf, 0, count); + + copy_from_user(lbuf, buf, count); + cur = lbuf; + + /* skip initial spaces */ + while (*cur && isspace(*cur)) + { + cur++; + } + + switch ((long)data) + { + case LED_NOLCD: + d = *cur++ - '0'; + if (d != 0 && d != 1) goto parse_error; + led_heartbeat = d; + + if (*cur++ != ' ') goto parse_error; + + d = *cur++ - '0'; + if (d != 0 && d != 1) goto parse_error; + led_diskio = d; + + if (*cur++ != ' ') goto parse_error; + + d = *cur++ - '0'; + if (d != 0 && d != 1) goto parse_error; + led_lanrxtx = d; + + break; + case LED_HASLCD: + if (*cur == 0) + { + /* reset to default */ + lcd_print("Linux " UTS_RELEASE); + } + else + { + /* chop off trailing \n.. if the user gives multiple + * \n then it's all their fault.. */ + if (*cur && cur[strlen(cur)-1] == '\n') + cur[strlen(cur)-1] = 0; + lcd_print(cur); + } + break; + default: + return 0; + } + + return count; + +parse_error: + if ((long)data == LED_NOLCD) + printk(KERN_CRIT "Parse error: expect \"n n n\" (n == 0 or 1) for heartbeat,\ndisk io and lan tx/rx indicators\n"); + return -EINVAL; +} + +static int __init led_create_procfs(void) +{ + struct proc_dir_entry *proc_pdc_root = NULL; + struct proc_dir_entry *ent; + + if (led_type == -1) return -1; + + proc_pdc_root = proc_mkdir("pdc", 0); + if (!proc_pdc_root) return -1; + proc_pdc_root->owner = THIS_MODULE; + ent = create_proc_entry("led", S_IFREG|S_IRUGO|S_IWUSR, proc_pdc_root); + if (!ent) return -1; + ent->nlink = 1; + ent->data = (void *)LED_NOLCD; /* LED */ + ent->read_proc = led_proc_read; + ent->write_proc = led_proc_write; + ent->owner = THIS_MODULE; + + if (led_type == LED_HASLCD) + { + ent = create_proc_entry("lcd", S_IFREG|S_IRUGO|S_IWUSR, proc_pdc_root); + if (!ent) return -1; + ent->nlink = 1; + ent->data = (void *)LED_HASLCD; /* LCD */ + ent->read_proc = led_proc_read; + ent->write_proc = led_proc_write; + ent->owner = THIS_MODULE; + } + return 0; +} +#endif /* ** @@ -132,24 +290,20 @@ ** ** led_LCD_driver() ** - ** The logic of the LCD driver is, that we write at every interrupt + ** The logic of the LCD driver is, that we write at every scheduled call ** only to one of LCD_CMD_REG _or_ LCD_DATA_REG - registers. - ** That way we don't need to let this interrupt routine busywait - ** the "min_cmd_delay", since idlewaiting in an interrupt-routine is - ** allways a BAD IDEA ! + ** That way we don't need to let this tasklet busywait for min_cmd_delay + ** milliseconds. ** ** TODO: check the value of "min_cmd_delay" against the value of HZ. ** */ - static void led_LCD_driver(unsigned char leds) { static int last_index; /* 0:heartbeat, 1:disk, 2:lan_in, 3:lan_out */ static int last_was_cmd;/* 0: CMD was written last, 1: DATA was last */ struct lcd_block *block_ptr; int value; - - // leds = ~leds; /* needed ? */ switch (last_index) { case 0: block_ptr = &lcd_info.heartbeat; @@ -165,7 +319,6 @@ value = leds & LED_LAN_TX; break; default: /* should never happen: */ - BUG(); return; } @@ -178,179 +331,293 @@ } /* now update the vars for the next interrupt iteration */ - if (++last_was_cmd == 2) { + if (++last_was_cmd == 2) { /* switch between cmd & data */ last_was_cmd = 0; - if (++last_index == 4) - last_index = 0; + if (++last_index == 4) + last_index = 0; /* switch back to heartbeat index */ } } +/* + ** + ** led_get_net_stats() + ** + ** calculate the TX- & RX-troughput on the network interfaces in + ** the system for usage in the LED code + ** + ** (analog to dev_get_info() from net/core/dev.c) + ** + */ +static unsigned long led_net_rx_counter, led_net_tx_counter; + +static void led_get_net_stats(int addvalue) +{ + static unsigned long rx_total_last, tx_total_last; + unsigned long rx_total, tx_total; + struct net_device *dev; + struct net_device_stats *stats; + + rx_total = tx_total = 0; + + /* we are running as a tasklet, so locking dev_base + * for reading should be OK */ + read_lock(&dev_base_lock); + for (dev = dev_base; dev != NULL; dev = dev->next) { + if (dev->get_stats) { + stats = dev->get_stats(dev); + rx_total += stats->rx_packets; + tx_total += stats->tx_packets; + } + } + read_unlock(&dev_base_lock); -static char currentleds; /* stores current value of the LEDs */ + rx_total -= rx_total_last; + tx_total -= tx_total_last; + + if (rx_total) + led_net_rx_counter += CALC_ADD(rx_total, tx_total, addvalue); + + if (tx_total) + led_net_tx_counter += CALC_ADD(tx_total, rx_total, addvalue); + + rx_total_last += rx_total; + tx_total_last += tx_total; +} -static void (*led_func_ptr) (unsigned char); /* ptr to LCD/LED-specific function */ /* - ** led_interrupt_func() ** - ** is called at every timer interrupt from time.c, + ** led_get_diskio_stats() + ** + ** calculate the disk-io througput in the system + ** (analog to linux/fs/proc/proc_misc.c) + ** + */ +static unsigned long led_diskio_counter; + +static void led_get_diskio_stats(int addvalue) +{ + static unsigned int diskio_total_last, diskio_max; + int major, disk, total; + + total = 0; + for (major = 0; major < DK_MAX_MAJOR; major++) { + for (disk = 0; disk < DK_MAX_DISK; disk++) + total += kstat.dk_drive[major][disk]; + } + total -= diskio_total_last; + + if (total) { + if (total >= diskio_max) { + led_diskio_counter += addvalue; + diskio_max = total; /* new maximum value found */ + } else + led_diskio_counter += CALC_ADD(total, diskio_max, addvalue); + } + + diskio_total_last += total; +} + + + +/* + ** led_tasklet_func() + ** + ** is scheduled at every timer interrupt from time.c and ** updates the chassis LCD/LED + + TODO: + - display load average (older machines like 715/64 have 4 "free" LED's for that) + - optimizations */ -#define HEARTBEAT_LEN (HZ/16) +static unsigned char currentleds; /* stores current value of the LEDs */ + +#define HEARTBEAT_LEN (HZ*6/100) +#define HEARTBEAT_2ND_RANGE_START (HZ*22/100) +#define HEARTBEAT_2ND_RANGE_END (HEARTBEAT_2ND_RANGE_START + HEARTBEAT_LEN) -void led_interrupt_func(void) +static void led_tasklet_func(unsigned long unused) { -#ifndef DISABLE_LEDS - static int count; - static int lastleds = -1; - static int nr; + static unsigned int count, count_HZ; + static unsigned char lastleds; - /* exit, if not initialized */ + /* exit if not initialized */ if (!led_func_ptr) return; - - /* increment the local counter */ - if (count == (HZ-1)) - count = 0; - else - count++; - /* calculate the Heartbeat */ - if ((count % (HZ/2)) < HEARTBEAT_LEN) - currentleds |= LED_HEARTBEAT; - else - currentleds &= ~LED_HEARTBEAT; + /* increment the local counters */ + ++count; + if (++count_HZ == HZ) + count_HZ = 0; + + if (led_heartbeat) + { + /* flash heartbeat-LED like a real heart (2 x short then a long delay) */ + if (count_HZ=HEARTBEAT_2ND_RANGE_START && count_HZ= 2) - nr = 0; - currentleds &= ~7; - currentleds |= (1 << nr); + if (led_diskio) + { + /* avoid to calculate diskio-stats at same irq as netio-stats ! */ + if ((count & 31) == 15) + led_get_diskio_stats(30); + + if (led_diskio_counter) { + led_diskio_counter--; + currentleds |= LED_DISK_IO; + } + else + currentleds &= ~LED_DISK_IO; } - /* now update the LEDs */ + /* update the LCD/LEDs */ if (currentleds != lastleds) { led_func_ptr(currentleds); lastleds = currentleds; } -#endif } +/* main led tasklet struct (scheduled from time.c) */ +DECLARE_TASKLET_DISABLED(led_tasklet, led_tasklet_func, 0); + + +/* + ** led_halt() + ** + ** called by the reboot notifier chain at shutdown and stops all + ** LED/LCD activities. + ** + */ + +static int led_halt(struct notifier_block *, unsigned long, void *); + +static struct notifier_block led_notifier = { + notifier_call: led_halt, +}; + +static int led_halt(struct notifier_block *nb, unsigned long event, void *buf) +{ + char *txt; + + switch (event) { + case SYS_RESTART: txt = "SYSTEM RESTART"; + break; + case SYS_HALT: txt = "SYSTEM HALT"; + break; + case SYS_POWER_OFF: txt = "SYSTEM POWER OFF"; + break; + default: return NOTIFY_DONE; + } + + /* completely stop the LED/LCD tasklet */ + tasklet_disable(&led_tasklet); + + if (lcd_info.model == DISPLAY_MODEL_LCD) + lcd_print(txt); + else + if (led_func_ptr) + led_func_ptr(0xff); /* turn all LEDs ON */ + + unregister_reboot_notifier(&led_notifier); + return NOTIFY_OK; +} /* ** register_led_driver() ** - ** All information in lcd_info needs to be set up prior - ** calling this function. + ** registers an external LED or LCD for usage by this driver. + ** currently only LCD-, LASI- and ASP-style LCD/LED's are supported. + ** */ -static void __init register_led_driver(void) +int __init register_led_driver(int model, char *cmd_reg, char *data_reg) { -#ifndef DISABLE_LEDS + static int initialized; + + if (initialized || !data_reg) + return 1; + + lcd_info.model = model; /* store the values */ + LCD_CMD_REG = (cmd_reg == LED_CMD_REG_NONE) ? NULL : cmd_reg; + switch (lcd_info.model) { case DISPLAY_MODEL_LCD: - printk(KERN_INFO "LCD display at (%p,%p)\n", - LCD_CMD_REG , LCD_DATA_REG); + LCD_DATA_REG = data_reg; + printk(KERN_INFO "LCD display at %p,%p registered\n", + LCD_CMD_REG , LCD_DATA_REG); led_func_ptr = led_LCD_driver; + lcd_print( "Linux " UTS_RELEASE ); + led_type = LED_HASLCD; break; case DISPLAY_MODEL_LASI: - printk(KERN_INFO "LED display at %p\n", - LED_DATA_REG); + LED_DATA_REG = data_reg; led_func_ptr = led_LASI_driver; + printk(KERN_INFO "LED display at %p registered\n", LED_DATA_REG); + led_type = LED_NOLCD; break; case DISPLAY_MODEL_OLD_ASP: - printk(KERN_INFO "LED (ASP-style) display at %p\n", - LED_DATA_REG); + LED_DATA_REG = data_reg; led_func_ptr = led_ASP_driver; + printk(KERN_INFO "LED (ASP-style) display at %p registered\n", + LED_DATA_REG); + led_type = LED_NOLCD; break; default: printk(KERN_ERR "%s: Wrong LCD/LED model %d !\n", __FUNCTION__, lcd_info.model); - return; + return 1; } -#endif -} - -/* - * XXX - could this move to lasi.c ?? - */ - -/* - ** lasi_led_init() - ** - ** lasi_led_init() is called from lasi.c with the base hpa - ** of the lasi controller chip. - ** Since Mirage and Electra machines use a different LED - ** address register, we need to check for these machines - ** explicitly. - */ - -#ifdef CONFIG_GSC_LASI -void __init lasi_led_init(unsigned long lasi_hpa) -{ - if (lcd_info.model != DISPLAY_MODEL_NONE || - lasi_hpa == 0) - return; - - printk("%s: CPU_HVERSION %x\n", __FUNCTION__, CPU_HVERSION); - - /* Mirage and Electra machines need special offsets */ - switch (CPU_HVERSION) { - case 0x60A: /* Mirage Jr (715/64) */ - case 0x60B: /* Mirage 100 */ - case 0x60C: /* Mirage 100+ */ - case 0x60D: /* Electra 100 */ - case 0x60E: /* Electra 120 */ - LED_DATA_REG = (char *) (lasi_hpa - 0x00020000); - break; - default: - LED_DATA_REG = (char *) (lasi_hpa + 0x0000C000); - break; - } /* switch() */ - - lcd_info.model = DISPLAY_MODEL_LASI; - register_led_driver(); -} -#endif - - -/* - ** asp_led_init() - ** - ** asp_led_init() is called from asp.c with the ptr - ** to the LED display. - */ - -#ifdef CONFIG_GSC_LASI -void __init asp_led_init(unsigned long led_ptr) -{ - if (lcd_info.model != DISPLAY_MODEL_NONE || - led_ptr == 0) - return; - - lcd_info.model = DISPLAY_MODEL_OLD_ASP; - LED_DATA_REG = (char *) led_ptr; + + /* mark the LCD/LED driver now as initialized and + * register to the reboot notifier chain */ + initialized++; + register_reboot_notifier(&led_notifier); - register_led_driver(); + /* start the led tasklet for the first time */ + tasklet_enable(&led_tasklet); + + return 0; } -#endif - - - /* ** register_led_regions() ** - ** Simple function, which registers the LCD/LED regions for /procfs. + ** register_led_regions() registers the LCD/LED regions for /procfs. ** At bootup - where the initialisation of the LCD/LED normally happens - ** not all internal structures of request_region() are properly set up, - ** so that we delay the registration until busdevice.c is executed. + ** so that we delay the led-registration until after busdevices_init() + ** has been executed. ** */ @@ -358,17 +625,57 @@ { switch (lcd_info.model) { case DISPLAY_MODEL_LCD: - request_region((unsigned long)LCD_CMD_REG, 1, "lcd_cmd"); - request_region((unsigned long)LCD_DATA_REG, 1, "lcd_data"); + request_mem_region((unsigned long)LCD_CMD_REG, 1, "lcd_cmd"); + request_mem_region((unsigned long)LCD_DATA_REG, 1, "lcd_data"); break; case DISPLAY_MODEL_LASI: case DISPLAY_MODEL_OLD_ASP: - request_region((unsigned long)LED_DATA_REG, 1, "led_data"); + request_mem_region((unsigned long)LED_DATA_REG, 1, "led_data"); break; } } +/* + ** + ** lcd_print() + ** + ** Displays the given string on the LCD-Display of newer machines. + ** lcd_print() disables the timer-based led tasklet during its + ** execution and enables it afterwards again. + ** + */ +int lcd_print( char *str ) +{ + int i; + + if (!led_func_ptr || lcd_info.model != DISPLAY_MODEL_LCD) + return 0; + + /* temporarily disable the led tasklet */ + tasklet_disable(&led_tasklet); + + /* copy display string to buffer for procfs */ + strncpy(lcd_text, str, sizeof(lcd_text)-1); + + /* Set LCD Cursor to 1st character */ + gsc_writeb(lcd_info.reset_cmd1, LCD_CMD_REG); + udelay(lcd_info.min_cmd_delay); + + /* Print the string */ + for (i=0; i < lcd_info.lcd_width; i++) { + if (str && *str) + gsc_writeb(*str++, LCD_DATA_REG); + else + gsc_writeb(' ', LCD_DATA_REG); + udelay(lcd_info.min_cmd_delay); + } + + /* re-enable the led tasklet */ + tasklet_enable(&led_tasklet); + + return lcd_info.lcd_width; +} /* ** led_init() @@ -384,10 +691,8 @@ int __init led_init(void) { -#ifndef DISABLE_LEDS - long pdc_result[32]; - - printk("%s: CPU_HVERSION %x\n", __FUNCTION__, CPU_HVERSION); + struct pdc_chassis_info chassis_info; + int ret; /* Work around the buggy PDC of KittyHawk-machines */ switch (CPU_HVERSION) { @@ -396,56 +701,74 @@ case 0x582: /* KittyHawk DC3 100 (K400) */ case 0x583: /* KittyHawk DC3 120 (K410) */ case 0x58B: /* KittyHawk DC2 100 (K200) */ - printk("%s: KittyHawk-Machine found !!\n", __FUNCTION__); + printk(KERN_INFO "%s: KittyHawk-Machine (hversion 0x%x) found, " + "LED detection skipped.\n", __FILE__, CPU_HVERSION); goto found; /* use the preinitialized values of lcd_info */ - - default: - break; } - /* initialize pdc_result, so we can check the return values of pdc_chassis_info() */ - pdc_result[0] = pdc_result[1] = 0; - - if (pdc_chassis_info(&pdc_result, &lcd_info, sizeof(lcd_info)) == PDC_OK) { - printk("%s: chassis info: model %d, ret0=%d, ret1=%d\n", - __FUNCTION__, lcd_info.model, pdc_result[0], pdc_result[1]); + /* initialize the struct, so that we can check for valid return values */ + lcd_info.model = DISPLAY_MODEL_NONE; + chassis_info.actcnt = chassis_info.maxcnt = 0; + if ((ret = pdc_chassis_info(&chassis_info, &lcd_info, sizeof(lcd_info))) == PDC_OK) { + DPRINTK((KERN_INFO "%s: chassis info: model=%d (%s), " + "lcd_width=%d, cmd_delay=%u,\n" + "%s: sizecnt=%d, actcnt=%ld, maxcnt=%ld\n", + __FILE__, lcd_info.model, + (lcd_info.model==DISPLAY_MODEL_LCD) ? "LCD" : + (lcd_info.model==DISPLAY_MODEL_LASI) ? "LED" : "unknown", + lcd_info.lcd_width, lcd_info.min_cmd_delay, + __FILE__, sizeof(lcd_info), + chassis_info.actcnt, chassis_info.maxcnt)); + DPRINTK((KERN_INFO "%s: cmd=%p, data=%p, reset1=%x, reset2=%x, act_enable=%d\n", + __FILE__, lcd_info.lcd_cmd_reg_addr, + lcd_info.lcd_data_reg_addr, lcd_info.reset_cmd1, + lcd_info.reset_cmd2, lcd_info.act_enable )); + /* check the results. Some machines have a buggy PDC */ - if (pdc_result[0] <= 0 || pdc_result[0] != pdc_result[1]) + if (chassis_info.actcnt <= 0 || chassis_info.actcnt != chassis_info.maxcnt) goto not_found; switch (lcd_info.model) { - case DISPLAY_MODEL_LCD: /* LCD display */ - if (pdc_result[0] != sizeof(struct pdc_chassis_lcd_info_ret_block) - && pdc_result[0] != sizeof(struct pdc_chassis_lcd_info_ret_block) - 1) - goto not_found; - printk("%s: min_cmd_delay = %d uS\n", - __FUNCTION__, lcd_info.min_cmd_delay); + case DISPLAY_MODEL_LCD: /* LCD display */ + if (chassis_info.actcnt < + offsetof(struct pdc_chassis_lcd_info_ret_block, _pad)-1) + goto not_found; + if (!lcd_info.act_enable) { + DPRINTK((KERN_INFO "PDC prohibited usage of the LCD.\n")); + goto not_found; + } break; case DISPLAY_MODEL_NONE: /* no LED or LCD available */ + printk(KERN_INFO "PDC reported no LCD or LED.\n"); goto not_found; case DISPLAY_MODEL_LASI: /* Lasi style 8 bit LED display */ - if (pdc_result[0] != 8 && pdc_result[0] != 32) + if (chassis_info.actcnt != 8 && chassis_info.actcnt != 32) goto not_found; break; default: - printk(KERN_WARNING "Unknown LCD/LED model %d\n", + printk(KERN_WARNING "PDC reported unknown LCD/LED model %d\n", lcd_info.model); goto not_found; - } /* switch() */ + } /* switch() */ found: /* register the LCD/LED driver */ - register_led_driver(); + register_led_driver(lcd_info.model, LCD_CMD_REG, LCD_DATA_REG); return 0; - } /* if() */ + } else { /* if() */ + DPRINTK((KERN_INFO "pdc_chassis_info call failed with retval = %d\n", ret)); + } not_found: lcd_info.model = DISPLAY_MODEL_NONE; return 1; -#endif } + +#ifdef CONFIG_PROC_FS +module_init(led_create_procfs) +#endif diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/Makefile linux.19rc3-ac4/arch/parisc/kernel/Makefile --- linux.19rc3/arch/parisc/kernel/Makefile 2002-07-29 12:50:06.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/Makefile 2002-07-29 13:58:35.000000000 +0100 @@ -7,26 +7,30 @@ # # Note 2! The CFLAGS definitions are now in the main makefile... -all: kernel.o init_task.o pdc_cons.o process.o head.o -O_TARGET = kernel.o -O_OBJS = +ifdef CONFIG_PARISC64 +all: kernel.o init_task.o pdc_cons.o process.o head64.o unaligned.o perf.o perf_asm.o +else +all: kernel.o init_task.o pdc_cons.o process.o head.o unaligned.o +endif -# Object file lists. +O_TARGET = kernel.o obj-y := obj-m := obj-n := obj- := -obj-y += cache.o setup.o traps.o time.o irq.o \ - syscall.o entry.o sys_parisc.o pdc.o ptrace.o hardware.o \ - inventory.o drivers.o semaphore.o pa7300lc.o pci-dma.o \ - signal.o hpmc.o \ - real1.o real2.o led.o parisc_ksyms.o +obj-y += cache.o pacache.o setup.o traps.o time.o irq.o \ + pa7300lc.o syscall.o entry.o sys_parisc.o firmware.o \ + ptrace.o hardware.o inventory.o drivers.o semaphore.o \ + signal.o hpmc.o real2.o parisc_ksyms.o unaligned.o \ + processor.o power.o -export-objs := parisc_ksyms.o +export-objs := parisc_ksyms.o superio.o keyboard.o +obj-$(CONFIG_SMP) += smp.o irq_smp.o +obj-$(CONFIG_PA11) += pci-dma.o obj-$(CONFIG_PCI) += pci.o obj-$(CONFIG_VT) += keyboard.o obj-$(CONFIG_PCI_LBA) += lba_pci.o @@ -37,16 +41,11 @@ # Only use one of them: ccio-rm-dma is for PCX-W systems *only* # obj-$(CONFIG_IOMMU_CCIO) += ccio-rm-dma.o obj-$(CONFIG_IOMMU_CCIO) += ccio-dma.o - -.o.S: $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $*.S -o $*.o - -# 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))) -MI_OBJS := $(sort $(filter-out $(export-objs), $(int-m))) -MIX_OBJS := $(sort $(filter $(export-objs), $(int-m))) +obj-$(CONFIG_CHASSIS_LCD_LED) += led.o +obj-$(CONFIG_SUPERIO) += superio.o +obj-$(CONFIG_PARISC64) += binfmt_elf32.o sys_parisc32.o \ + ioctl32.o signal32.o +# only supported for PCX-W/U in 64-bit mode at the moment +obj-$(CONFIG_PARISC64) += perf.o perf_asm.o include $(TOPDIR)/Rules.make diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/pa7300lc.c linux.19rc3-ac4/arch/parisc/kernel/pa7300lc.c --- linux.19rc3/arch/parisc/kernel/pa7300lc.c 2002-07-29 12:50:06.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/pa7300lc.c 2002-07-29 13:58:36.000000000 +0100 @@ -4,11 +4,12 @@ * * Copyright (C) 2000 Philipp Rumpf */ +#include +#include +#include #include #include #include -#include -#include /* CPU register indices */ @@ -19,12 +20,6 @@ #define DIOERR 0xf0ec #define HIDMAMEM 0xf0f4 -/* read CPU Diagnose register index */ -static u32 diag_read(int index) -{ - return 0; -} - /* this returns the HPA of the CPU it was called on */ static u32 cpu_hpa(void) { diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/pacache.S linux.19rc3-ac4/arch/parisc/kernel/pacache.S --- linux.19rc3/arch/parisc/kernel/pacache.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/pacache.S 2002-07-29 13:58:36.000000000 +0100 @@ -0,0 +1,908 @@ +/* + * Parisc tlb and cache flushing support + * Copyright (C) 2000 Hewlett-Packard (John Marvin) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * NOTE: fdc,fic, and pdc instructions that use base register modification + * should only use index and base registers that are not shadowed, + * so that the fast path emulation in the non access miss handler + * can be used. + */ + +#ifdef __LP64__ +#define ADDIB addib,* +#define CMPB cmpb,* +#define ANDCM andcm,* + + .level 2.0w +#else +#define ADDIB addib, +#define CMPB cmpb, +#define ANDCM andcm + + .level 2.0 +#endif + +#include +#include +#include +#include + + .text + .align 128 + + .export flush_tlb_all_local,code + +flush_tlb_all_local: + .proc + .callinfo NO_CALLS + .entry + + /* + * The pitlbe and pdtlbe instructions should only be used to + * flush the entire tlb. Also, there needs to be no intervening + * tlb operations, e.g. tlb misses, so the operation needs + * to happen in real mode with all interruptions disabled. + */ + + /* + * Once again, we do the rfi dance ... some day we need examine + * all of our uses of this type of code and see what can be + * consolidated. + */ + + rsm PSW_SM_I,%r19 /* relied upon translation! */ + nop + nop + nop + nop + nop + nop + nop + + rsm PSW_SM_Q,%r0 /* Turn off Q bit to load iia queue */ + ldil L%REAL_MODE_PSW, %r1 + ldo R%REAL_MODE_PSW(%r1), %r1 + mtctl %r1, %cr22 + mtctl %r0, %cr17 + mtctl %r0, %cr17 + ldil L%PA(1f),%r1 + ldo R%PA(1f)(%r1),%r1 + mtctl %r1, %cr18 + ldo 4(%r1), %r1 + mtctl %r1, %cr18 + rfi + nop + +1: ldil L%PA(cache_info),%r1 + ldo R%PA(cache_info)(%r1),%r1 + + /* Flush Instruction Tlb */ + + LDREG ITLB_SID_BASE(%r1),%r20 + LDREG ITLB_SID_STRIDE(%r1),%r21 + LDREG ITLB_SID_COUNT(%r1),%r22 + LDREG ITLB_OFF_BASE(%r1),%arg0 + LDREG ITLB_OFF_STRIDE(%r1),%arg1 + LDREG ITLB_OFF_COUNT(%r1),%arg2 + LDREG ITLB_LOOP(%r1),%arg3 + + ADDIB= -1,%arg3,fitoneloop /* Preadjust and test */ + movb,<,n %arg3,%r31,fitdone /* If loop < 0, skip */ + copy %arg0,%r28 /* Init base addr */ + +fitmanyloop: /* Loop if LOOP >= 2 */ + mtsp %r20,%sr1 + add %r21,%r20,%r20 /* increment space */ + copy %arg2,%r29 /* Init middle loop count */ + +fitmanymiddle: /* Loop if LOOP >= 2 */ + ADDIB> -1,%r31,fitmanymiddle /* Adjusted inner loop decr */ + pitlbe 0(%sr1,%r28) + pitlbe,m %arg1(%sr1,%r28) /* Last pitlbe and addr adjust */ + ADDIB> -1,%r29,fitmanymiddle /* Middle loop decr */ + copy %arg3,%r31 /* Re-init inner loop count */ + + movb,tr %arg0,%r28,fitmanyloop /* Re-init base addr */ + ADDIB<=,n -1,%r22,fitdone /* Outer loop count decr */ + +fitoneloop: /* Loop if LOOP = 1 */ + mtsp %r20,%sr1 + copy %arg0,%r28 /* init base addr */ + copy %arg2,%r29 /* init middle loop count */ + +fitonemiddle: /* Loop if LOOP = 1 */ + ADDIB> -1,%r29,fitonemiddle /* Middle loop count decr */ + pitlbe,m %arg1(%sr1,%r28) /* pitlbe for one loop */ + + ADDIB> -1,%r22,fitoneloop /* Outer loop count decr */ + add %r21,%r20,%r20 /* increment space */ + +fitdone: + + /* Flush Data Tlb */ + + LDREG DTLB_SID_BASE(%r1),%r20 + LDREG DTLB_SID_STRIDE(%r1),%r21 + LDREG DTLB_SID_COUNT(%r1),%r22 + LDREG DTLB_OFF_BASE(%r1),%arg0 + LDREG DTLB_OFF_STRIDE(%r1),%arg1 + LDREG DTLB_OFF_COUNT(%r1),%arg2 + LDREG DTLB_LOOP(%r1),%arg3 + + ADDIB= -1,%arg3,fdtoneloop /* Preadjust and test */ + movb,<,n %arg3,%r31,fdtdone /* If loop < 0, skip */ + copy %arg0,%r28 /* Init base addr */ + +fdtmanyloop: /* Loop if LOOP >= 2 */ + mtsp %r20,%sr1 + add %r21,%r20,%r20 /* increment space */ + copy %arg2,%r29 /* Init middle loop count */ + +fdtmanymiddle: /* Loop if LOOP >= 2 */ + ADDIB> -1,%r31,fdtmanymiddle /* Adjusted inner loop decr */ + pdtlbe 0(%sr1,%r28) + pdtlbe,m %arg1(%sr1,%r28) /* Last pdtlbe and addr adjust */ + ADDIB> -1,%r29,fdtmanymiddle /* Middle loop decr */ + copy %arg3,%r31 /* Re-init inner loop count */ + + movb,tr %arg0,%r28,fdtmanyloop /* Re-init base addr */ + ADDIB<=,n -1,%r22,fdtdone /* Outer loop count decr */ + +fdtoneloop: /* Loop if LOOP = 1 */ + mtsp %r20,%sr1 + copy %arg0,%r28 /* init base addr */ + copy %arg2,%r29 /* init middle loop count */ + +fdtonemiddle: /* Loop if LOOP = 1 */ + ADDIB> -1,%r29,fdtonemiddle /* Middle loop count decr */ + pdtlbe,m %arg1(%sr1,%r28) /* pdtlbe for one loop */ + + ADDIB> -1,%r22,fdtoneloop /* Outer loop count decr */ + add %r21,%r20,%r20 /* increment space */ + +fdtdone: + + /* Switch back to virtual mode */ + + rsm PSW_SM_Q,%r0 /* clear Q bit to load iia queue */ + ldil L%KERNEL_PSW, %r1 + ldo R%KERNEL_PSW(%r1), %r1 + or %r1,%r19,%r1 /* Set I bit if set on entry */ + mtctl %r1, %cr22 + mtctl %r0, %cr17 + mtctl %r0, %cr17 + ldil L%(2f), %r1 + ldo R%(2f)(%r1), %r1 + mtctl %r1, %cr18 + ldo 4(%r1), %r1 + mtctl %r1, %cr18 + rfi + nop + +2: bv %r0(%r2) + nop + .exit + + .procend + + .export flush_instruction_cache_local,code + .import cache_info,data + +flush_instruction_cache_local: + .proc + .callinfo NO_CALLS + .entry + + mtsp %r0,%sr1 + ldil L%cache_info,%r1 + ldo R%cache_info(%r1),%r1 + + /* Flush Instruction Cache */ + + LDREG ICACHE_BASE(%r1),%arg0 + LDREG ICACHE_STRIDE(%r1),%arg1 + LDREG ICACHE_COUNT(%r1),%arg2 + LDREG ICACHE_LOOP(%r1),%arg3 + ADDIB= -1,%arg3,fioneloop /* Preadjust and test */ + movb,<,n %arg3,%r31,fisync /* If loop < 0, do sync */ + +fimanyloop: /* Loop if LOOP >= 2 */ + ADDIB> -1,%r31,fimanyloop /* Adjusted inner loop decr */ + fice 0(%sr1,%arg0) + fice,m %arg1(%sr1,%arg0) /* Last fice and addr adjust */ + movb,tr %arg3,%r31,fimanyloop /* Re-init inner loop count */ + ADDIB<=,n -1,%arg2,fisync /* Outer loop decr */ + +fioneloop: /* Loop if LOOP = 1 */ + ADDIB> -1,%arg2,fioneloop /* Outer loop count decr */ + fice,m %arg1(%sr1,%arg0) /* Fice for one loop */ + +fisync: + sync + bv %r0(%r2) + nop + .exit + + .procend + + .export flush_data_cache_local,code + .import cache_info,data + +flush_data_cache_local: + .proc + .callinfo NO_CALLS + .entry + + mtsp %r0,%sr1 + ldil L%cache_info,%r1 + ldo R%cache_info(%r1),%r1 + + /* Flush Data Cache */ + + LDREG DCACHE_BASE(%r1),%arg0 + LDREG DCACHE_STRIDE(%r1),%arg1 + LDREG DCACHE_COUNT(%r1),%arg2 + LDREG DCACHE_LOOP(%r1),%arg3 + rsm PSW_SM_I,%r22 + ADDIB= -1,%arg3,fdoneloop /* Preadjust and test */ + movb,<,n %arg3,%r31,fdsync /* If loop < 0, do sync */ + +fdmanyloop: /* Loop if LOOP >= 2 */ + ADDIB> -1,%r31,fdmanyloop /* Adjusted inner loop decr */ + fdce 0(%sr1,%arg0) + fdce,m %arg1(%sr1,%arg0) /* Last fdce and addr adjust */ + movb,tr %arg3,%r31,fdmanyloop /* Re-init inner loop count */ + ADDIB<=,n -1,%arg2,fdsync /* Outer loop decr */ + +fdoneloop: /* Loop if LOOP = 1 */ + ADDIB> -1,%arg2,fdoneloop /* Outer loop count decr */ + fdce,m %arg1(%sr1,%arg0) /* Fdce for one loop */ + +fdsync: + syncdma + sync + mtsm %r22 + bv %r0(%r2) + nop + .exit + + .procend + + .export copy_user_page_asm,code + +copy_user_page_asm: + .proc + .callinfo NO_CALLS + .entry + + ldi 64,%r1 + + /* + * This loop is optimized for PCXL/PCXL2 ldw/ldw and stw/stw + * bundles (very restricted rules for bundling). It probably + * does OK on PCXU and better, but we could do better with + * ldd/std instructions. Note that until (if) we start saving + * the full 64 bit register values on interrupt, we can't + * use ldd/std on a 32 bit kernel. + */ + + +1: + ldw 0(%r25),%r19 + ldw 4(%r25),%r20 + ldw 8(%r25),%r21 + ldw 12(%r25),%r22 + stw %r19,0(%r26) + stw %r20,4(%r26) + stw %r21,8(%r26) + stw %r22,12(%r26) + ldw 16(%r25),%r19 + ldw 20(%r25),%r20 + ldw 24(%r25),%r21 + ldw 28(%r25),%r22 + stw %r19,16(%r26) + stw %r20,20(%r26) + stw %r21,24(%r26) + stw %r22,28(%r26) + ldw 32(%r25),%r19 + ldw 36(%r25),%r20 + ldw 40(%r25),%r21 + ldw 44(%r25),%r22 + stw %r19,32(%r26) + stw %r20,36(%r26) + stw %r21,40(%r26) + stw %r22,44(%r26) + ldw 48(%r25),%r19 + ldw 52(%r25),%r20 + ldw 56(%r25),%r21 + ldw 60(%r25),%r22 + stw %r19,48(%r26) + stw %r20,52(%r26) + stw %r21,56(%r26) + stw %r22,60(%r26) + ldo 64(%r26),%r26 + ADDIB> -1,%r1,1b + ldo 64(%r25),%r25 + + bv %r0(%r2) + nop + .exit + + .procend + +#if (TMPALIAS_MAP_START >= 0x80000000UL) +Warning TMPALIAS_MAP_START changed. If > 2 Gb, code in pacache.S is bogus +#endif + +/* + * NOTE: Code in clear_user_page has a hard coded dependency on the + * maximum alias boundary being 4 Mb. We've been assured by the + * parisc chip designers that there will not ever be a parisc + * chip with a larger alias boundary (Never say never :-) ). + * + * Subtle: the dtlb miss handlers support the temp alias region by + * "knowing" that if a dtlb miss happens within the temp alias + * region it must have occurred while in clear_user_page. Since + * this routine makes use of processor local translations, we + * don't want to insert them into the kernel page table. Instead, + * we load up some general registers (they need to be registers + * which aren't shadowed) with the physical page numbers (preshifted + * for tlb insertion) needed to insert the translations. When we + * miss on the translation, the dtlb miss handler inserts the + * translation into the tlb using these values: + * + * %r26 physical page (shifted for tlb insert) of "to" translation + * %r23 physical page (shifted for tlb insert) of "from" translation + */ + +#if 0 + + /* + * We can't do this since copy_user_page is used to bring in + * file data that might have instructions. Since the data would + * then need to be flushed out so the i-fetch can see it, it + * makes more sense to just copy through the kernel translation + * and flush it. + * + * I'm still keeping this around because it may be possible to + * use it if more information is passed into copy_user_page(). + * Have to do some measurements to see if it is worthwhile to + * lobby for such a change. + */ + + .export copy_user_page_asm,code + +copy_user_page_asm: + .proc + .callinfo NO_CALLS + .entry + + ldil L%(__PAGE_OFFSET),%r1 + sub %r26,%r1,%r26 + sub %r25,%r1,%r23 /* move physical addr into non shadowed reg */ + + ldil L%(TMPALIAS_MAP_START),%r28 +#ifdef __LP64__ + extrd,u %r26,56,32,%r26 /* convert phys addr to tlb insert format */ + extrd,u %r23,56,32,%r23 /* convert phys addr to tlb insert format */ + depd %r24,63,22,%r28 /* Form aliased virtual address 'to' */ + depdi 0,63,12,%r28 /* Clear any offset bits */ + copy %r28,%r29 + depdi 1,41,1,%r29 /* Form aliased virtual address 'from' */ +#else + extrw,u %r26,24,25,%r26 /* convert phys addr to tlb insert format */ + extrw,u %r23,24,25,%r23 /* convert phys addr to tlb insert format */ + depw %r24,31,22,%r28 /* Form aliased virtual address 'to' */ + depwi 0,31,12,%r28 /* Clear any offset bits */ + copy %r28,%r29 + depwi 1,9,1,%r29 /* Form aliased virtual address 'from' */ +#endif + + /* Purge any old translations */ + + pdtlb 0(%r28) + pdtlb 0(%r29) + + ldi 64,%r1 + + /* + * This loop is optimized for PCXL/PCXL2 ldw/ldw and stw/stw + * bundles (very restricted rules for bundling). It probably + * does OK on PCXU and better, but we could do better with + * ldd/std instructions. Note that until (if) we start saving + * the full 64 bit register values on interrupt, we can't + * use ldd/std on a 32 bit kernel. + */ + + +1: + ldw 0(%r29),%r19 + ldw 4(%r29),%r20 + ldw 8(%r29),%r21 + ldw 12(%r29),%r22 + stw %r19,0(%r28) + stw %r20,4(%r28) + stw %r21,8(%r28) + stw %r22,12(%r28) + ldw 16(%r29),%r19 + ldw 20(%r29),%r20 + ldw 24(%r29),%r21 + ldw 28(%r29),%r22 + stw %r19,16(%r28) + stw %r20,20(%r28) + stw %r21,24(%r28) + stw %r22,28(%r28) + ldw 32(%r29),%r19 + ldw 36(%r29),%r20 + ldw 40(%r29),%r21 + ldw 44(%r29),%r22 + stw %r19,32(%r28) + stw %r20,36(%r28) + stw %r21,40(%r28) + stw %r22,44(%r28) + ldw 48(%r29),%r19 + ldw 52(%r29),%r20 + ldw 56(%r29),%r21 + ldw 60(%r29),%r22 + stw %r19,48(%r28) + stw %r20,52(%r28) + stw %r21,56(%r28) + stw %r22,60(%r28) + ldo 64(%r28),%r28 + ADDIB> -1,%r1,1b + ldo 64(%r29),%r29 + + bv %r0(%r2) + nop + .exit + + .procend +#endif + + .export clear_user_page_asm,code + +clear_user_page_asm: + .proc + .callinfo NO_CALLS + .entry + + tophys_r1 %r26 + + ldil L%(TMPALIAS_MAP_START),%r28 +#ifdef __LP64__ + extrd,u %r26,56,32,%r26 /* convert phys addr to tlb insert format */ + depd %r25,63,22,%r28 /* Form aliased virtual address 'to' */ + depdi 0,63,12,%r28 /* Clear any offset bits */ +#else + extrw,u %r26,24,25,%r26 /* convert phys addr to tlb insert format */ + depw %r25,31,22,%r28 /* Form aliased virtual address 'to' */ + depwi 0,31,12,%r28 /* Clear any offset bits */ +#endif + + /* Purge any old translation */ + + pdtlb 0(%r28) + + ldi 64,%r1 + +1: + stw %r0,0(%r28) + stw %r0,4(%r28) + stw %r0,8(%r28) + stw %r0,12(%r28) + stw %r0,16(%r28) + stw %r0,20(%r28) + stw %r0,24(%r28) + stw %r0,28(%r28) + stw %r0,32(%r28) + stw %r0,36(%r28) + stw %r0,40(%r28) + stw %r0,44(%r28) + stw %r0,48(%r28) + stw %r0,52(%r28) + stw %r0,56(%r28) + stw %r0,60(%r28) + ADDIB> -1,%r1,1b + ldo 64(%r28),%r28 + + bv %r0(%r2) + nop + .exit + + .procend + + .export flush_kernel_dcache_page + +flush_kernel_dcache_page: + .proc + .callinfo NO_CALLS + .entry + + ldil L%dcache_stride,%r1 + ldw R%dcache_stride(%r1),%r23 + +#ifdef __LP64__ + depdi,z 1,63-PAGE_SHIFT,1,%r25 +#else + depwi,z 1,31-PAGE_SHIFT,1,%r25 +#endif + add %r26,%r25,%r25 + sub %r25,%r23,%r25 + + +1: fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + fdc,m %r23(%r26) + CMPB<< %r26,%r25,1b + fdc,m %r23(%r26) + + sync + bv %r0(%r2) + nop + .exit + + .procend + + .export purge_kernel_dcache_page + +purge_kernel_dcache_page: + .proc + .callinfo NO_CALLS + .entry + + ldil L%dcache_stride,%r1 + ldw R%dcache_stride(%r1),%r23 + +#ifdef __LP64__ + depdi,z 1,63-PAGE_SHIFT,1,%r25 +#else + depwi,z 1,31-PAGE_SHIFT,1,%r25 +#endif + add %r26,%r25,%r25 + sub %r25,%r23,%r25 + +1: pdc,m %r23(%r26) + pdc,m %r23(%r26) + pdc,m %r23(%r26) + pdc,m %r23(%r26) + pdc,m %r23(%r26) + pdc,m %r23(%r26) + pdc,m %r23(%r26) + pdc,m %r23(%r26) + pdc,m %r23(%r26) + pdc,m %r23(%r26) + pdc,m %r23(%r26) + pdc,m %r23(%r26) + pdc,m %r23(%r26) + pdc,m %r23(%r26) + pdc,m %r23(%r26) + CMPB<< %r26,%r25,1b + pdc,m %r23(%r26) + + sync + bv %r0(%r2) + nop + .exit + + .procend + +#if 0 + /* Currently not used, but it still is a possible alternate + * solution. + */ + + .export flush_alias_page + +flush_alias_page: + .proc + .callinfo NO_CALLS + .entry + + tophys_r1 %r26 + + ldil L%(TMPALIAS_MAP_START),%r28 +#ifdef __LP64__ + extrd,u %r26,56,32,%r26 /* convert phys addr to tlb insert format */ + depd %r25,63,22,%r28 /* Form aliased virtual address 'to' */ + depdi 0,63,12,%r28 /* Clear any offset bits */ +#else + extrw,u %r26,24,25,%r26 /* convert phys addr to tlb insert format */ + depw %r25,31,22,%r28 /* Form aliased virtual address 'to' */ + depwi 0,31,12,%r28 /* Clear any offset bits */ +#endif + + /* Purge any old translation */ + + pdtlb 0(%r28) + + ldil L%dcache_stride,%r1 + ldw R%dcache_stride(%r1),%r23 + +#ifdef __LP64__ + depdi,z 1,63-PAGE_SHIFT,1,%r29 +#else + depwi,z 1,31-PAGE_SHIFT,1,%r29 +#endif + add %r28,%r29,%r29 + sub %r29,%r23,%r29 + +1: fdc,m %r23(%r28) + fdc,m %r23(%r28) + fdc,m %r23(%r28) + fdc,m %r23(%r28) + fdc,m %r23(%r28) + fdc,m %r23(%r28) + fdc,m %r23(%r28) + fdc,m %r23(%r28) + fdc,m %r23(%r28) + fdc,m %r23(%r28) + fdc,m %r23(%r28) + fdc,m %r23(%r28) + fdc,m %r23(%r28) + fdc,m %r23(%r28) + fdc,m %r23(%r28) + CMPB<< %r28,%r29,1b + fdc,m %r23(%r28) + + sync + bv %r0(%r2) + nop + .exit + + .procend +#endif + + .export flush_user_dcache_range_asm + +flush_user_dcache_range_asm: + .proc + .callinfo NO_CALLS + .entry + + ldil L%dcache_stride,%r1 + ldw R%dcache_stride(%r1),%r23 + ldo -1(%r23),%r21 + ANDCM %r26,%r21,%r26 + +1: CMPB<<,n %r26,%r25,1b + fdc,m %r23(%sr3,%r26) + + sync + bv %r0(%r2) + nop + .exit + + .procend + + .export flush_kernel_dcache_range_asm + +flush_kernel_dcache_range_asm: + .proc + .callinfo NO_CALLS + .entry + + ldil L%dcache_stride,%r1 + ldw R%dcache_stride(%r1),%r23 + ldo -1(%r23),%r21 + ANDCM %r26,%r21,%r26 + +1: CMPB<<,n %r26,%r25,1b + fdc,m %r23(%r26) + + sync + syncdma + bv %r0(%r2) + nop + .exit + + .procend + + .export flush_user_icache_range_asm + +flush_user_icache_range_asm: + .proc + .callinfo NO_CALLS + .entry + + ldil L%icache_stride,%r1 + ldw R%icache_stride(%r1),%r23 + ldo -1(%r23),%r21 + ANDCM %r26,%r21,%r26 + +1: CMPB<<,n %r26,%r25,1b + fic,m %r23(%sr3,%r26) + + sync + bv %r0(%r2) + nop + .exit + + .procend + + .export flush_kernel_icache_page + +flush_kernel_icache_page: + .proc + .callinfo NO_CALLS + .entry + + ldil L%icache_stride,%r1 + ldw R%icache_stride(%r1),%r23 + +#ifdef __LP64__ + depdi,z 1,63-PAGE_SHIFT,1,%r25 +#else + depwi,z 1,31-PAGE_SHIFT,1,%r25 +#endif + add %r26,%r25,%r25 + sub %r25,%r23,%r25 + + +1: fic,m %r23(%r26) + fic,m %r23(%r26) + fic,m %r23(%r26) + fic,m %r23(%r26) + fic,m %r23(%r26) + fic,m %r23(%r26) + fic,m %r23(%r26) + fic,m %r23(%r26) + fic,m %r23(%r26) + fic,m %r23(%r26) + fic,m %r23(%r26) + fic,m %r23(%r26) + fic,m %r23(%r26) + fic,m %r23(%r26) + fic,m %r23(%r26) + CMPB<< %r26,%r25,1b + fic,m %r23(%r26) + + sync + bv %r0(%r2) + nop + .exit + + .procend + + .export flush_kernel_icache_range_asm + +flush_kernel_icache_range_asm: + .proc + .callinfo NO_CALLS + .entry + + ldil L%icache_stride,%r1 + ldw R%icache_stride(%r1),%r23 + ldo -1(%r23),%r21 + ANDCM %r26,%r21,%r26 + +1: CMPB<<,n %r26,%r25,1b + fic,m %r23(%r26) + + sync + bv %r0(%r2) + nop + .exit + + .procend + + .align 128 + + .export disable_sr_hashing_asm,code + +disable_sr_hashing_asm: + .proc + .callinfo NO_CALLS + .entry + + /* Switch to real mode */ + + ssm 0,%r0 /* relied upon translation! */ + nop + nop + nop + nop + nop + nop + nop + + rsm (PSW_SM_Q|PSW_SM_I),%r0 /* disable Q&I to load the iia queue */ + ldil L%REAL_MODE_PSW, %r1 + ldo R%REAL_MODE_PSW(%r1), %r1 + mtctl %r1, %cr22 + mtctl %r0, %cr17 + mtctl %r0, %cr17 + ldil L%PA(1f),%r1 + ldo R%PA(1f)(%r1),%r1 + mtctl %r1, %cr18 + ldo 4(%r1), %r1 + mtctl %r1, %cr18 + rfi + nop + +1: cmpib,=,n SRHASH_PCXST,%r26,srdis_pcxs + cmpib,=,n SRHASH_PCXL,%r26,srdis_pcxl + cmpib,=,n SRHASH_PA20,%r26,srdis_pa20 + b,n srdis_done + +srdis_pcxs: + + /* Disable Space Register Hashing for PCXS,PCXT,PCXT' */ + + .word 0x141c1a00 /* mfdiag %dr0,%r28 */ + .word 0x141c1a00 /* must issue twice */ + depwi 0,18,1,%r28 /* Clear DHE (dcache hash enable) */ + depwi 0,20,1,%r28 /* Clear IHE (icache hash enable) */ + .word 0x141c1600 /* mtdiag %r28,%dr0 */ + .word 0x141c1600 /* must issue twice */ + b,n srdis_done + +srdis_pcxl: + + /* Disable Space Register Hashing for PCXL */ + + .word 0x141c0600 /* mfdiag %dr0,%r28 */ + depwi 0,28,2,%r28 /* Clear DHASH_EN & IHASH_EN */ + .word 0x141c0240 /* mtdiag %r28,%dr0 */ + b,n srdis_done + +srdis_pa20: + + /* Disable Space Register Hashing for PCXU,PCXU+,PCXW,PCXW+ */ + + .word 0x144008bc /* mfdiag %dr2,%r28 */ + depdi 0,54,1,%r28 /* clear DIAG_SPHASH_ENAB (bit 54) */ + .word 0x145c1840 /* mtdiag %r28,%dr2 */ + +srdis_done: + + /* Switch back to virtual mode */ + + rsm PSW_SM_Q,%r0 /* clear Q bit to load iia queue */ + ldil L%KERNEL_PSW, %r1 + ldo R%KERNEL_PSW(%r1), %r1 + mtctl %r1, %cr22 + mtctl %r0, %cr17 + mtctl %r0, %cr17 + ldil L%(2f), %r1 + ldo R%(2f)(%r1), %r1 + mtctl %r1, %cr18 + ldo 4(%r1), %r1 + mtctl %r1, %cr18 + rfi + nop + +2: bv %r0(%r2) + nop + .exit + + .procend + + .end diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/parisc_ksyms.c linux.19rc3-ac4/arch/parisc/kernel/parisc_ksyms.c --- linux.19rc3/arch/parisc/kernel/parisc_ksyms.c 2002-07-29 12:50:06.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/parisc_ksyms.c 2002-07-29 13:58:36.000000000 +0100 @@ -14,17 +14,29 @@ EXPORT_SYMBOL(memmove); EXPORT_SYMBOL(strcat); EXPORT_SYMBOL(strchr); +EXPORT_SYMBOL(strrchr); EXPORT_SYMBOL(strcmp); EXPORT_SYMBOL(strcpy); EXPORT_SYMBOL(strlen); +EXPORT_SYMBOL(strnlen); EXPORT_SYMBOL(strncat); EXPORT_SYMBOL(strncmp); EXPORT_SYMBOL(strncpy); EXPORT_SYMBOL(strtok); +EXPORT_SYMBOL(strstr); +#include /* struct parisc_device for asm/pci.h */ #include EXPORT_SYMBOL(hppa_dma_ops); +#if defined(CONFIG_PCI) || defined(CONFIG_ISA) +EXPORT_SYMBOL(get_pci_node_path); +#endif + +#ifdef CONFIG_IOMMU_CCIO +EXPORT_SYMBOL(ccio_get_fake); +#endif +#include #include EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); @@ -32,6 +44,13 @@ #include EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(boot_cpu_data); +EXPORT_SYMBOL(map_hpux_gateway_page); +#ifdef CONFIG_EISA +EXPORT_SYMBOL(EISA_bus); +#endif + +#include +EXPORT_SYMBOL(pm_power_off); #ifdef CONFIG_SMP EXPORT_SYMBOL(synchronize_irq); @@ -39,35 +58,100 @@ #include EXPORT_SYMBOL(kernel_flag); +/* from asm/system.h */ #include EXPORT_SYMBOL(__global_sti); EXPORT_SYMBOL(__global_cli); EXPORT_SYMBOL(__global_save_flags); EXPORT_SYMBOL(__global_restore_flags); +#include +EXPORT_SYMBOL(smp_num_cpus); +#endif /* CONFIG_SMP */ + +#include +EXPORT_SYMBOL(__xchg8); +EXPORT_SYMBOL(__xchg32); +EXPORT_SYMBOL(__cmpxchg_u32); +#ifdef CONFIG_SMP +EXPORT_SYMBOL(__atomic_hash); +#endif +#ifdef __LP64__ +EXPORT_SYMBOL(__xchg64); +EXPORT_SYMBOL(__cmpxchg_u64); #endif #include EXPORT_SYMBOL(lcopy_to_user); EXPORT_SYMBOL(lcopy_from_user); +EXPORT_SYMBOL(lstrnlen_user); +EXPORT_SYMBOL(lclear_user); +#ifndef __LP64__ /* Needed so insmod can set dp value */ - -extern int data_start; - -EXPORT_SYMBOL_NOVERS(data_start); +extern int $global$; +EXPORT_SYMBOL_NOVERS($global$); +#endif #include -EXPORT_SYMBOL(_gsc_writeb); -EXPORT_SYMBOL(_gsc_writew); -EXPORT_SYMBOL(_gsc_writel); -EXPORT_SYMBOL(_gsc_readb); -EXPORT_SYMBOL(_gsc_readw); -EXPORT_SYMBOL(_gsc_readl); -EXPORT_SYMBOL(busdevice_alloc_irq); -EXPORT_SYMBOL(register_driver); -EXPORT_SYMBOL(gsc_alloc_irq); +EXPORT_SYMBOL(register_parisc_driver); +EXPORT_SYMBOL(unregister_parisc_driver); EXPORT_SYMBOL(pdc_iodc_read); +#ifdef CONFIG_GSC +EXPORT_SYMBOL(gsc_alloc_irq); +#endif + +#include +EXPORT_SYMBOL(__ioremap); +EXPORT_SYMBOL(iounmap); +EXPORT_SYMBOL(memcpy_toio); +EXPORT_SYMBOL(memcpy_fromio); +EXPORT_SYMBOL(memset_io); + +#if defined(CONFIG_PCI) || defined(CONFIG_ISA) +EXPORT_SYMBOL(inb); +EXPORT_SYMBOL(inw); +EXPORT_SYMBOL(inl); +EXPORT_SYMBOL(outb); +EXPORT_SYMBOL(outw); +EXPORT_SYMBOL(outl); + +EXPORT_SYMBOL(insb); +EXPORT_SYMBOL(insw); +EXPORT_SYMBOL(insl); +EXPORT_SYMBOL(outsb); +EXPORT_SYMBOL(outsw); +EXPORT_SYMBOL(outsl); +#endif + +#include +EXPORT_SYMBOL(flush_kernel_dcache_range_asm); +EXPORT_SYMBOL(flush_kernel_dcache_page); +EXPORT_SYMBOL(flush_all_caches); + +#include +extern long sys_open(const char *, int, int); +extern off_t sys_lseek(int, off_t, int); +extern int sys_read(int, char *, int); +extern int sys_write(int, const char *, int); +EXPORT_SYMBOL(sys_open); +EXPORT_SYMBOL(sys_lseek); +EXPORT_SYMBOL(sys_read); +EXPORT_SYMBOL(sys_write); + +#include +EXPORT_SYMBOL(__up); +EXPORT_SYMBOL(__down_interruptible); +EXPORT_SYMBOL(__down); + +#include +#include +EXPORT_SYMBOL(csum_partial_copy); + +#include +EXPORT_SYMBOL(pdc_add_valid); +EXPORT_SYMBOL(pdc_lan_station_id); +EXPORT_SYMBOL(pdc_get_initiator); extern void $$divI(void); extern void $$divU(void); @@ -99,7 +183,9 @@ EXPORT_SYMBOL_NOVERS($$remI); EXPORT_SYMBOL_NOVERS($$remU); EXPORT_SYMBOL_NOVERS($$mulI); +#ifndef __LP64__ EXPORT_SYMBOL_NOVERS($$mulU); +#endif EXPORT_SYMBOL_NOVERS($$divU_3); EXPORT_SYMBOL_NOVERS($$divU_5); EXPORT_SYMBOL_NOVERS($$divU_6); @@ -120,15 +206,25 @@ EXPORT_SYMBOL_NOVERS($$divI_15); extern void __ashrdi3(void); +extern void __ashldi3(void); +extern void __lshrdi3(void); +extern void __muldi3(void); EXPORT_SYMBOL_NOVERS(__ashrdi3); +EXPORT_SYMBOL_NOVERS(__ashldi3); +EXPORT_SYMBOL_NOVERS(__lshrdi3); +EXPORT_SYMBOL_NOVERS(__muldi3); #ifdef __LP64__ extern void __divdi3(void); extern void __udivdi3(void); +extern void __umoddi3(void); +extern void __moddi3(void); EXPORT_SYMBOL_NOVERS(__divdi3); EXPORT_SYMBOL_NOVERS(__udivdi3); +EXPORT_SYMBOL_NOVERS(__umoddi3); +EXPORT_SYMBOL_NOVERS(__moddi3); #endif #ifndef __LP64__ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/pci.c linux.19rc3-ac4/arch/parisc/kernel/pci.c --- linux.19rc3/arch/parisc/kernel/pci.c 2002-07-29 12:50:06.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/pci.c 2002-07-29 13:58:36.000000000 +0100 @@ -6,25 +6,32 @@ * * Copyright (C) 1997, 1998 Ralf Baechle * Copyright (C) 1999 SuSE GmbH - * Copyright (C) 1999 Hewlett-Packard Company - * Copyright (C) 1999, 2000 Grant Grundler + * Copyright (C) 1999-2001 Hewlett-Packard Company + * Copyright (C) 1999-2001 Grant Grundler */ #include #include #include #include /* for __init and __devinit */ #include -#include -#include /* for memcpy() */ +#include +#include #include +#include /* for L1_CACHE_BYTES */ -#ifdef CONFIG_PCI +#define DEBUG_RESOURCES 0 +#define DEBUG_CONFIG 0 + +#if DEBUG_CONFIG +# define DBGC(x...) printk(KERN_DEBUG x) +#else +# define DBGC(x...) +#endif -#undef DEBUG_RESOURCES -#ifdef DEBUG_RESOURCES -#define DBG_RES(x...) printk(x) +#if DEBUG_RESOURCES +#define DBG_RES(x...) printk(KERN_DEBUG x) #else #define DBG_RES(x...) #endif @@ -42,14 +49,13 @@ struct pci_port_ops *pci_port; struct pci_bios_ops *pci_bios; -struct pci_hba_data *hba_list = NULL; -int hba_count = 0; +int pci_hba_count = 0; /* ** parisc_pci_hba used by pci_port->in/out() ops to lookup bus data. */ #define PCI_HBA_MAX 32 -static struct pci_hba_data *parisc_pci_hba[PCI_HBA_MAX]; +struct pci_hba_data *parisc_pci_hba[PCI_HBA_MAX]; /******************************************************************** @@ -58,24 +64,31 @@ ** *********************************************************************/ -#define PCI_PORT_HBA(a) ((a)>>16) -#define PCI_PORT_ADDR(a) ((a) & 0xffffUL) +/* EISA port numbers and PCI port numbers share the same interface. Some + * machines have both EISA and PCI adapters installed. Rather than turn + * pci_port into an array, we reserve bus 0 for EISA and call the EISA + * routines if the access is to a port on bus 0. We don't want to fix + * EISA and ISA drivers which assume port space is <= 0xffff. + */ -/* KLUGE : inb needs to be defined differently for PCI devices than -** for other bus interfaces. Doing this at runtime sucks but is the -** only way one driver binary can support devices on different bus types. -** -*/ +#ifdef CONFIG_EISA +#define EISA_IN(size) if (EISA_bus && (b == 0)) return eisa_in##size(addr) +#define EISA_OUT(size) if (EISA_bus && (b == 0)) return eisa_out##size(d, addr) +#else +#define EISA_IN(size) +#define EISA_OUT(size) +#endif #define PCI_PORT_IN(type, size) \ u##size in##type (int addr) \ { \ int b = PCI_PORT_HBA(addr); \ u##size d = (u##size) -1; \ + EISA_IN(size); \ ASSERT(pci_port); /* make sure services are defined */ \ ASSERT(parisc_pci_hba[b]); /* make sure ioaddr are "fixed up" */ \ if (parisc_pci_hba[b] == NULL) { \ - printk(KERN_WARNING "\nPCI Host Bus Adapter %d not registered. in" #size "(0x%x) returning -1\n", b, addr); \ + printk(KERN_WARNING "\nPCI or EISA Host Bus Adapter %d not registered. in" #size "(0x%x) returning -1\n", b, addr); \ } else { \ d = pci_port->in##type(parisc_pci_hba[b], PCI_PORT_ADDR(addr)); \ } \ @@ -91,6 +104,7 @@ void out##type (u##size d, int addr) \ { \ int b = PCI_PORT_HBA(addr); \ + EISA_OUT(size); \ ASSERT(pci_port); \ pci_port->out##type(parisc_pci_hba[b], PCI_PORT_ADDR(addr), d); \ } @@ -106,15 +120,13 @@ */ void pcibios_init(void) { - ASSERT(pci_bios != NULL); + if (!pci_bios) + return; - if (pci_bios) - { - if (pci_bios->init) { - (*pci_bios->init)(); - } else { - printk(KERN_WARNING "pci_bios != NULL but init() is!\n"); - } + if (pci_bios->init) { + pci_bios->init(); + } else { + printk(KERN_WARNING "pci_bios != NULL but init() is!\n"); } } @@ -124,17 +136,10 @@ { ASSERT(pci_bios != NULL); - /* If this is a bridge, get the current bases */ - if (bus->self) { - pci_read_bridge_bases(bus); - } - - if (pci_bios) { - if (pci_bios->fixup_bus) { - (*pci_bios->fixup_bus)(bus); - } else { - printk(KERN_WARNING "pci_bios != NULL but fixup_bus() is!\n"); - } + if (pci_bios->fixup_bus) { + pci_bios->fixup_bus(bus); + } else { + printk(KERN_WARNING "pci_bios != NULL but fixup_bus() is!\n"); } } @@ -144,14 +149,6 @@ return str; } -#endif /* defined(CONFIG_PCI) */ - - - -/* ------------------------------------------------------------------- -** linux-2.4: NEW STUFF -** -------------------- -*/ /* ** Used in drivers/pci/quirks.c @@ -201,19 +198,11 @@ ** ------------------------------------ ** PAT PDC systems need this routine. PA legacy PDC does not. ** -** Used by alpha/arm: -** alpha/kernel/pci.c:common_init_pci() -** (or arm/kernel/pci.c:pcibios_init()) -** drivers/pci/setup.c:pci_assign_unassigned_resources() -** drivers/pci/setup.c:pdev_assign_unassigned_resources() -** arch//kernel/pci.c:pcibios_update_resource() -** -** When BAR's are configured by linux, this routine -** will update configuration space with the "normalized" -** address. "root" indicates where the range starts and res -** is some portion of that range. +** When BAR's are configured by linux, this routine will update +** configuration space with the "normalized" address. "root" indicates +** where the range starts and res is some portion of that range. ** -** For all PA-RISC systems except V-class, root->start would be zero. +** VCLASS: For all PA-RISC systems except V-class, root->start would be zero. ** ** PAT PDC can tell us which MMIO ranges are available or already in use. ** I/O port space and such are not memory mapped anyway for PA-Risc. @@ -234,7 +223,7 @@ barnum, res->start, res->end, (int) res->flags); if (barnum >= PCI_BRIDGE_RESOURCES) { - /* handled in pbus_set_ranges_data() */ + /* handled in PCI-PCI bridge specific support */ return; } @@ -248,8 +237,7 @@ if (res->flags & IORESOURCE_IO) { barval = PCI_PORT_ADDR(res->start); } else if (res->flags & IORESOURCE_MEM) { - /* This should work for VCLASS too */ - barval = res->start & 0xffffffffUL; + barval = PCI_BUS_ADDR(HBA_DATA(dev->bus->sysdata), res->start); } else { panic("pcibios_update_resource() WTF? flags not IO or MEM"); } @@ -267,7 +255,7 @@ == (PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64)) { pci_write_config_dword(dev, where+4, 0); - printk(KERN_WARNING "PCI: dev %s type 64-bit\n", dev->name); + DBGC("PCIBIOS: dev %s type 64-bit\n", dev->name); } } @@ -290,25 +278,78 @@ pcibios_set_master(struct pci_dev *dev) { u8 lat; + + /* If someone already mucked with this, don't touch it. */ pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); if (lat >= 16) return; /* ** HP generally has fewer devices on the bus than other architectures. + ** upper byte is PCI_LATENCY_TIMER. */ - printk("PCIBIOS: Setting latency timer of %s to 128\n", dev->slot_name); - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80); + pci_write_config_word(dev, PCI_CACHE_LINE_SIZE, + (0x80 << 8) | (L1_CACHE_BYTES / sizeof(u32))); +} + + +void __init +pcibios_init_bus(struct pci_bus *bus) +{ + struct pci_dev *dev = bus->self; + + /* We deal only with pci controllers and pci-pci bridges. */ + if (dev && (dev->class >> 8) != PCI_CLASS_BRIDGE_PCI) + return; + + if (dev) { + /* PCI-PCI bridge - set the cache line and default latency + (32) for primary and secondary buses. */ + pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 32); + + /* Read bridge control */ + pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &bus->bridge_ctl); + } + + /* Set FBB bit for now. Disable ISA IO forwarding. Enable PERR/SERR */ + bus->bridge_ctl |= PCI_BRIDGE_CTL_FAST_BACK | + PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR; } /* -** called by drivers/pci/setup-res.c:pbus_set_ranges(). +** KLUGE: Link the child and parent resources - generic PCI didn't +*/ +static void +pcibios_link_hba_resources( struct resource *hba_res, struct resource *r) +{ + if (!r->parent) { + r->parent = hba_res; + + /* reverse link is harder *sigh* */ + if (r->parent->child) { + if (r->parent->sibling) { + struct resource *next = r->parent->sibling; + while (next->sibling) + next = next->sibling; + next->sibling = r; + } else { + r->parent->sibling = r; + } + } else + r->parent->child = r; + } +} + +/* +** called by drivers/pci/setup-res.c:pci_setup_bridge(). */ void pcibios_fixup_pbus_ranges( struct pci_bus *bus, struct pbus_set_ranges_data *ranges ) { + struct pci_hba_data *hba = HBA_DATA(bus->sysdata); + /* ** I/O space may see busnumbers here. Something ** in the form of 0xbbxxxx where bb is the bus num @@ -319,9 +360,20 @@ ranges->io_start = PCI_PORT_ADDR(ranges->io_start); ranges->io_end = PCI_PORT_ADDR(ranges->io_end); + /* Convert MMIO addr to PCI addr (undo global virtualization) */ + ranges->mem_start = PCI_BUS_ADDR(hba, ranges->mem_start); + ranges->mem_end = PCI_BUS_ADDR(hba, ranges->mem_end); + DBG_RES("pcibios_fixup_pbus_ranges(%02x, [%lx,%lx %lx,%lx])\n", bus->number, ranges->io_start, ranges->io_end, ranges->mem_start, ranges->mem_end); + + /* KLUGE ALERT + ** if this resource isn't linked to a "parent", then it seems + ** to be a child of the HBA - lets link it in. + */ + pcibios_link_hba_resources(&hba->io_space, bus->resource[0]); + pcibios_link_hba_resources(&hba->lmmio_space, bus->resource[1]); } #define MAX(val1, val2) ((val1) > (val2) ? (val1) : (val2)) @@ -360,107 +412,15 @@ /* ** WARNING : caller is expected to update "end" field. ** We can't since it might really represent the *size*. - ** The difference is "end = start + size" vs "end += size". + ** The difference is "end = start + size" vs "end += start". */ } -#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1)) - -void __devinit -pcibios_size_bridge(struct pci_bus *bus, struct pbus_set_ranges_data *outer) -{ - struct pbus_set_ranges_data inner; - struct pci_dev *dev; - struct pci_dev *bridge = bus->self; - struct list_head *ln; - - /* set reasonable default "window" for pcibios_align_resource */ - inner.io_start = inner.io_end = 0; - inner.mem_start = inner.mem_end = 0; - - /* Collect information about how our direct children are layed out. */ - for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) { - int i; - dev = pci_dev_b(ln); - - /* Skip bridges here - we'll catch them below */ - if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) - continue; - - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - struct resource res; - unsigned long size; - - if (dev->resource[i].flags == 0) - continue; - - memcpy(&res, &dev->resource[i], sizeof(res)); - size = res.end - res.start + 1; - - if (res.flags & IORESOURCE_IO) { - res.start = inner.io_end; - pcibios_align_resource(dev, &res, size); - inner.io_end += res.start + size; - } else if (res.flags & IORESOURCE_MEM) { - res.start = inner.mem_end; - pcibios_align_resource(dev, &res, size); - inner.mem_end = res.start + size; - } - - DBG_RES(" %s inner size %lx/%x IO %lx MEM %lx\n", - dev->slot_name, - size, res.flags, inner.io_end, inner.mem_end); - } - } - - /* And for all of the subordinate busses. */ - for (ln=bus->children.next; ln != &bus->children; ln=ln->next) - pcibios_size_bridge(pci_bus_b(ln), &inner); - - /* turn the ending locations into sizes (subtract start) */ - inner.io_end -= inner.io_start - 1; - inner.mem_end -= inner.mem_start - 1; - - /* Align the sizes up by bridge rules */ - inner.io_end = ROUND_UP(inner.io_end, 4*1024) - 1; - inner.mem_end = ROUND_UP(inner.mem_end, 1*1024*1024) - 1; - - /* PPB - PCI bridge Device will normaller also have "outer" != NULL. */ - if (bridge) { - /* Adjust the bus' allocation requirements */ - /* PPB's pci device Bridge resources */ - - bus->resource[0] = &bridge->resource[PCI_BRIDGE_RESOURCES]; - bus->resource[1] = &bridge->resource[PCI_BRIDGE_RESOURCES + 1]; - - bus->resource[0]->start = bus->resource[1]->start = 0; - bus->resource[0]->parent= bus->resource[1]->parent = NULL; - - bus->resource[0]->end = inner.io_end; - bus->resource[0]->flags = IORESOURCE_IO; - - bus->resource[1]->end = inner.mem_end; - bus->resource[1]->flags = IORESOURCE_MEM; - } - - /* adjust parent's resource requirements */ - if (outer) { - outer->io_end = ROUND_UP(outer->io_end, 4*1024); - outer->io_end += inner.io_end; - - outer->mem_end = ROUND_UP(outer->mem_end, 1*1024*1024); - outer->mem_end += inner.mem_end; - } -} - -#undef ROUND_UP - - int __devinit pcibios_enable_device(struct pci_dev *dev) { - u16 cmd, old_cmd; + u16 cmd; int idx; /* @@ -468,12 +428,13 @@ ** enable all the same bits. We just make sure they are here. */ pci_read_config_word(dev, PCI_COMMAND, &cmd); - old_cmd = cmd; /* ** See if any resources have been allocated + ** While "regular" PCI devices only use 0-5, Bridges use a few + ** beyond that for window registers. */ - for (idx=0; idx<6; idx++) { + for (idx=0; idxresource[idx]; if (r->flags & IORESOURCE_IO) cmd |= PCI_COMMAND_IO; @@ -482,7 +443,7 @@ } /* - ** System error and Parity Error reporting are enabled by default. + ** Enable System error and Parity Error reporting by default. ** Devices that do NOT want those behaviors should clear them ** (eg PCI graphics, possibly networking). ** Interfaces like SCSI certainly should not. We want the @@ -491,30 +452,48 @@ */ cmd |= (PCI_COMMAND_SERR | PCI_COMMAND_PARITY); - if (cmd != old_cmd) { - printk("PCIBIOS: Enabling device %s (%04x -> %04x)\n", - dev->slot_name, old_cmd, cmd); - pci_write_config_word(dev, PCI_COMMAND, cmd); - } + /* If bridge/bus controller has FBB enabled, child must too. */ + if (dev->bus->bridge_ctl & PCI_BRIDGE_CTL_FAST_BACK) + cmd |= PCI_COMMAND_FAST_BACK; + DBGC("PCIBIOS: Enabling device %s cmd 0x%04x\n", dev->slot_name, cmd); + pci_write_config_word(dev, PCI_COMMAND, cmd); return 0; } - -void __devinit -pcibios_assign_unassigned_resources(struct pci_bus *bus) +void __init +pcibios_setup_host_bridge(struct pci_bus *bus) { - struct list_head *ln; + ASSERT(pci_bios != NULL); - for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) +#if 0 + if (pci_bios) { - pdev_assign_unassigned_resources(pci_dev_b(ln)); + if (pci_bios->setup_host_bridge) { + (*pci_bios->setup_host_bridge)(bus); + } } +#endif +} - /* And for all of the sub-busses. */ - for (ln=bus->children.next; ln != &bus->children; ln=ln->next) - pcibios_assign_unassigned_resources(pci_bus_b(ln)); +/* +** Mostly copied from drivers/pci/setup-bus.c:pci_assign_unassigned_resources() +*/ +void __devinit +pcibios_assign_unassigned_resources(struct pci_bus *bus) +{ + /* from drivers/pci/setup-bus.c */ + extern void pbus_assign_resources(struct pci_bus *bus, struct pbus_set_ranges_data *ranges); + + struct pbus_set_ranges_data ranges; + + ranges.io_end = ranges.io_start + = bus->resource[0]->start + PCIBIOS_MIN_IO; + ranges.mem_end = ranges.mem_start + = bus->resource[1]->start + PCIBIOS_MIN_MEM; + ranges.found_vga = 0; + pbus_assign_resources(bus, &ranges); } /* @@ -522,14 +501,9 @@ */ void pcibios_register_hba(struct pci_hba_data *hba) { - hba->next = hba_list; - hba_list = hba; - - ASSERT(hba_count < PCI_HBA_MAX); + ASSERT(pci_hba_count < PCI_HBA_MAX); - /* - ** pci_port->in/out() uses parisc_pci_hba to lookup parameter. - */ - parisc_pci_hba[hba_count] = hba; - hba->hba_num = hba_count++; + /* pci_port->in/out() uses parisc_pci_hba to lookup parameter. */ + parisc_pci_hba[pci_hba_count] = hba; + hba->hba_num = pci_hba_count++; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/pci-dma.c linux.19rc3-ac4/arch/parisc/kernel/pci-dma.c --- linux.19rc3/arch/parisc/kernel/pci-dma.c 2002-07-29 12:50:06.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/pci-dma.c 2002-07-29 13:58:36.000000000 +0100 @@ -1,5 +1,7 @@ /* -** Dynamic DMA mapping support. +** PARISC 1.1 Dynamic DMA mapping support. +** This implementation is for PA-RISC platforms that do not support +** I/O TLBs (aka DMA address translation hardware). ** See Documentation/DMA-mapping.txt for interface definitions. ** ** (c) Copyright 1999,2000 Hewlett-Packard Company @@ -7,15 +9,10 @@ ** (c) Copyright 2000 Philipp Rumpf ** (c) Copyright 2000 John Marvin ** -** This implementation is for PA-RISC platforms that do not support -** I/O TLBs (aka DMA address translation hardware). -** ** "leveraged" from 2.3.47: arch/ia64/kernel/pci-dma.c. ** (I assume it's from David Mosberger-Tang but there was no Copyright) ** ** AFAIK, all PA7100LC and PA7300LC platforms can use this code. -** All PA2.0 machines but V-class can alias xxx_alloc_consistent() -** to use regular cacheable memory. ** ** - ggg */ @@ -117,7 +114,7 @@ if (end > PGDIR_SIZE) end = PGDIR_SIZE; do { - pte_t * pte = pte_alloc_kernel(pmd, vaddr); + pte_t * pte = pte_alloc(NULL, pmd, vaddr); if (!pte) return -ENOMEM; if (map_pte_uncached(pte, orig_vaddr, end - vaddr, paddr_ptr)) @@ -139,7 +136,7 @@ do { pmd_t *pmd; - pmd = pmd_alloc_kernel(dir, vaddr); + pmd = pmd_alloc(NULL, dir, vaddr); if (!pmd) return -ENOMEM; if (map_pmd_uncached(pmd, vaddr, end - vaddr, &paddr)) @@ -510,7 +507,6 @@ pa11_dma_sync_sg /* dma_sync_sg */ }; -struct pci_dma_ops *hppa_dma_ops; static int pcxl_proc_info(char *buf, char **start, off_t offset, int len) { diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/pdc.c linux.19rc3-ac4/arch/parisc/kernel/pdc.c --- linux.19rc3/arch/parisc/kernel/pdc.c 2002-07-29 12:50:06.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/pdc.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,217 +0,0 @@ -/* arch/parisc/kernel/pdc.c - safe pdc access routines - * - * Copyright 1999 SuSE GmbH Nuernberg (Philipp Rumpf, prumpf@tux.org) - * portions Copyright 1999 The Puffin Group, (Alex deVries, David Kennedy) - * - * only these routines should be used out of the real kernel (i.e. everything - * using virtual addresses) for obvious reasons */ - -/* I think it would be in everyone's best interest to follow this - * guidelines when writing PDC wrappers: - * - * - the name of the pdc wrapper should match one of the macros - * used for the first two arguments - * - don't use caps for random parts of the name - * - use ASSERT_ALIGN to ensure the aligment of the arguments is - * correct - * - use __pa() to convert virtual (kernel) pointers to physical - * ones. - * - the name of the struct used for pdc return values should equal - * one of the macros used for the first two arguments to the - * corresponding PDC call - * - keep the order of arguments - * - don't be smart (setting trailing NUL bytes for strings, return - * something useful even if the call failed) unless you are sure - * it's not going to affect functionality or performance - * - * Example: - * int pdc_cache_info(struct pdc_cache_info *cache_info ) - * { - * ASSERT_ALIGN(cache_info, 8); - * - * return mem_pdc_call(PDC_CACHE,PDC_CACHE_INFO,__pa(cache_info),0); - * } - * prumpf 991016 - */ - -#include -#include - -#include -#include -#include -#include - - -#define ASSERT_ALIGN(ptr, align) \ - do { if(((unsigned long)(ptr)) & (align-1)) { \ - printk("PDC: %s:%d %s() called with " \ - "unaligned argument from %p", __FILE__, __LINE__, \ - __FUNCTION__, __builtin_return_address(0)); \ - \ - return -1; \ - } } while(0) - -/* verify address can be accessed without an HPMC */ -int pdc_add_valid(void *address) -{ - ASSERT_ALIGN(address, 4); - - return mem_pdc_call(PDC_ADD_VALID, PDC_ADD_VALID_VERIFY, (unsigned long)address); -} - -#if 0 -int pdc_chassis_warn(struct pdc_chassis_warn *address) -{ - ASSERT_ALIGN(address, 4); - - return mem_pdc_call(PDC_CHASSIS, PDC_CHASSIS_WARN, __pa(address), 0); -} -#endif - -int pdc_chassis_disp(unsigned long disp) -{ - return mem_pdc_call(PDC_CHASSIS, PDC_CHASSIS_DISP, disp); -} - -int pdc_chassis_info(void *pdc_result, void *chassis_info, unsigned long len) -{ - ASSERT_ALIGN(pdc_result, 4); - ASSERT_ALIGN(chassis_info, 4); - return mem_pdc_call(PDC_CHASSIS,PDC_RETURN_CHASSIS_INFO, - __pa(pdc_result), __pa(chassis_info), len); -} - -int pdc_hpa_processor(void *address) -{ - /* We're using 0 for the last parameter just to make sure. - It's actually HVERSION dependant. And remember, life is - hard without a backspace. */ - ASSERT_ALIGN(address, 4); - - return mem_pdc_call(PDC_HPA, PDC_HPA_PROCESSOR, __pa(address),0); -} - -#if 0 -int pdc_hpa_modules(void *address) -{ - return mem_pdc_call(PDC_HPA, PDC_HPA_MODULES, address); -} -#endif - -int pdc_iodc_read(void *address, void * hpa, unsigned int index, - void * iodc_data, unsigned int iodc_data_size) -{ - ASSERT_ALIGN(address, 4); - ASSERT_ALIGN(iodc_data, 8); - return mem_pdc_call(PDC_IODC, PDC_IODC_READ, - __pa(address), hpa, index, __pa(iodc_data), iodc_data_size); -} - - -int pdc_system_map_find_mods(void *pdc_mod_info, - void *mod_path, int index) -{ - return mem_pdc_call(PDC_SYSTEM_MAP, PDC_FIND_MODULE, - __pa(pdc_mod_info), __pa(mod_path), (long)index); -} - - -int pdc_model_info(struct pdc_model *model) { - ASSERT_ALIGN(model, 8); - return mem_pdc_call(PDC_MODEL,PDC_MODEL_INFO,__pa(model),0); -} - -/* get system model name from PDC ROM (e.g. 9000/715 or 9000/778/B160L) */ -int pdc_model_sysmodel(char * name) -{ - struct pdc_model_sysmodel sys_model; - int retval; - - ASSERT_ALIGN(&sys_model, 8); - ASSERT_ALIGN(name, 4); - - sys_model.mod_len = 0; - retval = mem_pdc_call(PDC_MODEL,PDC_MODEL_SYSMODEL,__pa(&sys_model), - OS_ID_HPUX,__pa(name)); - - if (retval == PDC_RET_OK) - name[sys_model.mod_len] = '\0'; /* add trailing '\0' */ - else - name[0] = 0; - - return retval; -} - -/* id: 0 = cpu revision, 1 = boot-rom-version */ -int pdc_model_versions(struct pdc_model_cpuid *cpu_id, int id) { - return mem_pdc_call(PDC_MODEL,PDC_MODEL_VERSIONS,__pa(cpu_id),id); -} - -int pdc_model_cpuid(struct pdc_model_cpuid *cpu_id) { - cpu_id->cpuid = 0; /* preset zero (call maybe not implemented!) */ - return mem_pdc_call(PDC_MODEL,6,__pa(cpu_id),0); /* 6="return CPU ID" */ -} - -int pdc_cache_info(struct pdc_cache_info *cache_info) { - ASSERT_ALIGN(cache_info, 8); - - return mem_pdc_call(PDC_CACHE,PDC_CACHE_INFO,__pa(cache_info),0); -} - -#ifndef __LP64__ -int pdc_btlb_info( struct pdc_btlb_info *btlb ) { - int status; - status = mem_pdc_call(PDC_BLOCK_TLB,PDC_BTLB_INFO,__pa(btlb),0); - if (status<0) btlb->max_size = 0; - return status; -} - -int pdc_mem_map_hpa(void *r_addr, void *mod_path) { - return mem_pdc_call(PDC_MEM_MAP,PDC_MEM_MAP_HPA, - __pa(r_addr),__pa(mod_path)); -} - -int pdc_lan_station_id(char *lan_addr, void *net_hpa) { - struct pdc_lan_station_id id; - unsigned char *addr; - - if (mem_pdc_call(PDC_LAN_STATION_ID, PDC_LAN_STATION_ID_READ, - __pa(&id), net_hpa) < 0) - addr = 0; /* FIXME: else read MAC from NVRAM */ - else - addr = id.addr; - if (addr) - memmove( lan_addr, addr, PDC_LAN_STATION_ID_SIZE); - else - memset( lan_addr, 0, PDC_LAN_STATION_ID_SIZE); - return (addr != 0); -} -#endif - - -/* Similar to PDC_PAT stuff in pdcpat.c - but added for Forte/Allegro boxes */ -int pdc_pci_irt_size(void *r_addr, void *hpa) -{ - return mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL_SIZE, - __pa(r_addr), hpa); - -} - -int pdc_pci_irt(void *r_addr, void *hpa, void *tbl) -{ - return mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL, - __pa(r_addr), hpa, __pa(tbl)); -} - -/* access the TOD clock */ -int pdc_tod_read(struct pdc_tod *tod) -{ - ASSERT_ALIGN(tod, 8); - return mem_pdc_call(PDC_TOD, PDC_TOD_READ, __pa(tod), 0); -} - -int pdc_tod_set(unsigned long sec, unsigned long usec) -{ - return mem_pdc_call(PDC_TOD, PDC_TOD_WRITE, sec, usec); -} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/pdc_cons.c linux.19rc3-ac4/arch/parisc/kernel/pdc_cons.c --- linux.19rc3/arch/parisc/kernel/pdc_cons.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/pdc_cons.c 2002-07-29 13:58:36.000000000 +0100 @@ -1,100 +1,49 @@ +/* + * linux/arch/parisc/kernel/pdc_console.c + * + * The PDC console is a simple console, which can be used for debugging + * boot related problems on HP PA-RISC machines. + * + * This code uses the ROM (=PDC) based functions to read and write characters + * from and to PDC's boot path. + * Since all character read from that path must be polled, this code never + * can or will be a fully functional linux console. + */ + +/* Define EARLY_BOOTUP_DEBUG to debug kernel related boot problems. + * On production kernels EARLY_BOOTUP_DEBUG should be undefined. */ +#undef EARLY_BOOTUP_DEBUG + + #include #include #include #include #include #include +#include #include #include #include #include -#include /* for iodc_call() proto and friends */ -#include +#include /* for iodc_call() proto and friends */ -static int __attribute__((aligned(8))) iodc_retbuf[32]; -static char __attribute__((aligned(64))) iodc_dbuf[4096]; - -/* - * pdc_putc: - * Console character print using IODC. - * - * Note that only these special chars are architected for console IODC io: - * BEL, BS, CR, and LF. Others are passed through. - * Since the HP console requires CR+LF to perform a 'newline', we translate - * "\n" to "\r\n". - */ - -static int posx; /* for simple TAB-Simulation... */ - -/* XXX Should we spinlock posx usage */ - -void pdc_putc(unsigned char c) -{ - unsigned int n; - unsigned long flags; - - switch (c) { - case '\n': - iodc_dbuf[0] = '\r'; - iodc_dbuf[1] = '\n'; - n = 2; - posx = 0; - break; - case '\t': - pdc_putc(' '); - while (posx & 7) /* expand TAB */ - pdc_putc(' '); - return; /* return since IODC can't handle this */ - case '\b': - posx-=2; /* BS */ - default: - iodc_dbuf[0] = c; - n = 1; - posx++; - break; - } - { - real32_call(PAGE0->mem_cons.iodc_io, - (unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT, - PAGE0->mem_cons.spa, __pa(PAGE0->mem_cons.dp.layers), - __pa(iodc_retbuf), 0, __pa(iodc_dbuf), n, 0); - } -} static void pdc_console_write(struct console *co, const char *s, unsigned count) { while(count--) - pdc_putc(*s++); + pdc_iodc_putc(*s++); } -int pdc_console_wait_key(struct console *co) +void pdc_outc(unsigned char c) { - int ch = 'X'; - int status; - - /* Bail if no console input device. */ - if (!PAGE0->mem_kbd.iodc_io) - return 0; - - /* wait for a keyboard (rs232)-input */ - do { - unsigned long flags; - - save_flags(flags); - cli(); - status = real32_call(PAGE0->mem_kbd.iodc_io, - (unsigned long)PAGE0->mem_kbd.hpa, ENTRY_IO_CIN, - PAGE0->mem_kbd.spa, __pa(PAGE0->mem_kbd.dp.layers), - __pa(iodc_retbuf), 0, __pa(iodc_dbuf), 1, 0); - restore_flags(flags); - ch = *iodc_dbuf; /* save the character directly to ch */ - } while (*iodc_retbuf == 0); /* wait for a key */ - return ch; + pdc_iodc_outc(c); } -int pdc_getc(void) + +int pdc_console_poll_key(struct console *co) { - return pdc_console_wait_key(NULL); + return pdc_iodc_getc(); } static int pdc_console_setup(struct console *co, char *options) @@ -102,17 +51,34 @@ return 0; } +#ifdef CONFIG_PDC_CONSOLE +static kdev_t pdc_console_device (struct console *c) +{ + return MKDEV(PDCCONS_MAJOR, 0); +} +#endif + +#ifdef CONFIG_PDC_CONSOLE +#define PDC_CONSOLE_DEVICE pdc_console_device +#else +#define PDC_CONSOLE_DEVICE NULL +#endif + static struct console pdc_cons = { name: "ttyB", write: pdc_console_write, + device: PDC_CONSOLE_DEVICE, setup: pdc_console_setup, - flags: CON_PRINTBUFFER|CON_ENABLED, // |CON_CONSDEV, + flags: CON_BOOT|CON_PRINTBUFFER|CON_ENABLED, index: -1, }; static int pdc_console_initialized; -void pdc_console_init(void) +extern unsigned long con_start; /* kernel/printk.c */ +extern unsigned long log_end; /* kernel/printk.c */ + +static void pdc_console_init_force(void) { if (pdc_console_initialized) return; @@ -122,23 +88,32 @@ if (PAGE0->mem_cons.cl_class == CL_DUPLEX) memcpy(&PAGE0->mem_kbd, &PAGE0->mem_cons, sizeof(PAGE0->mem_cons)); - pdc_console_write(0, "PDC Console Initialized\n", 24); /* register the pdc console */ register_console(&pdc_cons); } +void pdc_console_init(void) +{ +#if defined(EARLY_BOOTUP_DEBUG) || defined(CONFIG_PDC_CONSOLE) + pdc_console_init_force(); +#endif +#ifdef EARLY_BOOTUP_DEBUG + printk(KERN_INFO "Initialized PDC Console for debugging.\n"); +#endif +} + /* Unregister the pdc console with the printk console layer */ void pdc_console_die(void) { - printk("Switching from PDC console\n"); if (!pdc_console_initialized) return; --pdc_console_initialized; - -#ifdef CONFIG_VT_CONSOLE - schedule_console_callback(); -#endif + + printk(KERN_INFO "Switching from PDC console\n"); + + /* Don't repeat what we've already printed */ + con_start = log_end; unregister_console(&pdc_cons); } @@ -155,17 +130,17 @@ void pdc_console_restart(void) { struct console *console; - extern int log_size; if (pdc_console_initialized) return; - while ((console = console_drivers) != (struct console *)0) + while ((console = console_drivers) != NULL) unregister_console(console_drivers); - log_size = 0; - pdc_console_init(); - printk("Switched to PDC console\n"); - return; + /* Don't repeat what we've already printed */ + con_start = log_end; + + /* force registering the pdc console */ + pdc_console_init_force(); } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/perf_asm.S linux.19rc3-ac4/arch/parisc/kernel/perf_asm.S --- linux.19rc3/arch/parisc/kernel/perf_asm.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/perf_asm.S 2002-07-29 13:58:36.000000000 +0100 @@ -0,0 +1,1679 @@ +; +; Purpose: +; This file has the overall purpose of suppyling low-level +; assembly to program the intrigue portion of the cpu. +; + +#include +#include + +#ifdef __LP64__ + .level 2.0w +#endif /* __LP64__ */ + +#define MTDIAG_1(gr) .word 0x14201840 + gr*0x10000 +#define MTDIAG_2(gr) .word 0x14401840 + gr*0x10000 +#define MFDIAG_1(gr) .word 0x142008A0 + gr +#define MFDIAG_2(gr) .word 0x144008A0 + gr +#define STDIAG(dr) .word 0x14000AA0 + dr*0x200000 +#define SFDIAG(dr) .word 0x14000BA0 + dr*0x200000 +#define DR2_SLOW_RET 53 + + +; +; Enable the performance counters +; +; The coprocessor only needs to be enabled when +; starting/stopping the coprocessor with the pmenb/pmdis. +; + .text + .align 32 + + .export perf_intrigue_enable_perf_counters,code +perf_intrigue_enable_perf_counters: + .proc + .callinfo frame=0,NO_CALLS + .entry + + ldi 0x20,%r25 ; load up perfmon bit + mfctl ccr,%r26 ; get coprocessor register + or %r25,%r26,%r26 ; set bit + mtctl %r26,ccr ; turn on performance coprocessor + pmenb ; enable performance monitor + ssm 0,0 ; dummy op to ensure completion + sync ; follow ERS + andcm %r26,%r25,%r26 ; clear bit now + mtctl %r26,ccr ; turn off performance coprocessor + nop ; NOPs as specified in ERS + nop + nop + nop + nop + nop + nop + bve (%r2) + nop + .exit + .procend + + .export perf_intrigue_disable_perf_counters,code +perf_intrigue_disable_perf_counters: + .proc + .callinfo frame=0,NO_CALLS + .entry + ldi 0x20,%r25 ; load up perfmon bit + mfctl ccr,%r26 ; get coprocessor register + or %r25,%r26,%r26 ; set bit + mtctl %r26,ccr ; turn on performance coprocessor + pmdis ; disable performance monitor + ssm 0,0 ; dummy op to ensure completion + andcm %r26,%r25,%r26 ; clear bit now + bve (%r2) + mtctl %r26,ccr ; turn off performance coprocessor + .exit + .procend + +;************************************************************************ +;* * +;* Name: perf_rdr_shift_in_W * +;* * +;* Description: * +;* This routine shifts data in from the RDR in arg0 and returns * +;* the result in ret0. If the RDR is <= 64 bits in length, it * +;* is shifted shifted backup immediately. This is to compensate * +;* for RDR10 which has bits that preclude PDC stack operations * +;* when they are in the wrong state. * +;* * +;* Arguments: * +;* arg0 : rdr to be read * +;* arg1 : bit length of rdr * +;* * +;* Returns: * +;* ret0 = next 64 bits of rdr data from staging register * +;* * +;* Register usage: * +;* arg0 : rdr to be read * +;* arg1 : bit length of rdr * +;* %r24 - original DR2 value * +;* %r1 - scratch * +;* %r29 - scratch * +;* * +;* Returns: * +;* ret0 = RDR data (right justified) * +;* * +;************************************************************************ + + .export perf_rdr_shift_in_W,code +perf_rdr_shift_in_W: + .proc + .callinfo frame=0,NO_CALLS + .entry +; +; read(shift in) the RDR. +; + +; NOTE: The PCX-W ERS states that DR2_SLOW_RET must be set before any +; shifting is done, from or to, remote diagnose registers. +; + + depdi,z 1,DR2_SLOW_RET,1,%r29 + MFDIAG_2 (24) + or %r24,%r29,%r29 + MTDIAG_2 (29) ; set DR2_SLOW_RET + + nop + nop + nop + nop + +; +; Cacheline start (32-byte cacheline) +; + nop + nop + nop + extrd,u arg1,63,6,%r1 ; setup shift amount based on bits to move + + mtsar %r1 + shladd arg0,2,%r0,%r1 ; %r1 = 4 * RDR number + blr %r1,%r0 ; branch to 8-instruction sequence + nop + +; +; Cacheline start (32-byte cacheline) +; + + ; + ; RDR 0 sequence + ; + SFDIAG (0) + ssm 0,0 + MFDIAG_1 (28) + shrpd ret0,%r0,%sar,%r1 + MTDIAG_1 (1) ; mtdiag %dr1, %r1 + STDIAG (0) + ssm 0,0 + b,n perf_rdr_shift_in_W_leave + + ; + ; RDR 1 sequence + ; + sync + ssm 0,0 + SFDIAG (1) + ssm 0,0 + MFDIAG_1 (28) + ssm 0,0 + b,n perf_rdr_shift_in_W_leave + nop + + ; + ; RDR 2 read sequence + ; + SFDIAG (2) + ssm 0,0 + MFDIAG_1 (28) + shrpd ret0,%r0,%sar,%r1 + MTDIAG_1 (1) + STDIAG (2) + ssm 0,0 + b,n perf_rdr_shift_in_W_leave + + ; + ; RDR 3 read sequence + ; + b,n perf_rdr_shift_in_W_leave + nop + nop + nop + nop + nop + nop + nop + + ; + ; RDR 4 read sequence + ; + sync + ssm 0,0 + SFDIAG (4) + ssm 0,0 + MFDIAG_1 (28) + b,n perf_rdr_shift_in_W_leave + ssm 0,0 + nop + + ; + ; RDR 5 read sequence + ; + sync + ssm 0,0 + SFDIAG (5) + ssm 0,0 + MFDIAG_1 (28) + b,n perf_rdr_shift_in_W_leave + ssm 0,0 + nop + + ; + ; RDR 6 read sequence + ; + sync + ssm 0,0 + SFDIAG (6) + ssm 0,0 + MFDIAG_1 (28) + b,n perf_rdr_shift_in_W_leave + ssm 0,0 + nop + + ; + ; RDR 7 read sequence + ; + b,n perf_rdr_shift_in_W_leave + nop + nop + nop + nop + nop + nop + nop + + ; + ; RDR 8 read sequence + ; + b,n perf_rdr_shift_in_W_leave + nop + nop + nop + nop + nop + nop + nop + + ; + ; RDR 9 read sequence + ; + b,n perf_rdr_shift_in_W_leave + nop + nop + nop + nop + nop + nop + nop + + ; + ; RDR 10 read sequence + ; + SFDIAG (10) + ssm 0,0 + MFDIAG_1 (28) + shrpd ret0,%r0,%sar,%r1 + MTDIAG_1 (1) + STDIAG (10) + ssm 0,0 + b,n perf_rdr_shift_in_W_leave + + ; + ; RDR 11 read sequence + ; + SFDIAG (11) + ssm 0,0 + MFDIAG_1 (28) + shrpd ret0,%r0,%sar,%r1 + MTDIAG_1 (1) + STDIAG (11) + ssm 0,0 + b,n perf_rdr_shift_in_W_leave + + ; + ; RDR 12 read sequence + ; + b,n perf_rdr_shift_in_W_leave + nop + nop + nop + nop + nop + nop + nop + + ; + ; RDR 13 read sequence + ; + sync + ssm 0,0 + SFDIAG (13) + ssm 0,0 + MFDIAG_1 (28) + b,n perf_rdr_shift_in_W_leave + ssm 0,0 + nop + + ; + ; RDR 14 read sequence + ; + SFDIAG (14) + ssm 0,0 + MFDIAG_1 (28) + shrpd ret0,%r0,%sar,%r1 + MTDIAG_1 (1) + STDIAG (14) + ssm 0,0 + b,n perf_rdr_shift_in_W_leave + + ; + ; RDR 15 read sequence + ; + sync ; RDR 15 read sequence + ssm 0,0 + SFDIAG (15) + ssm 0,0 + MFDIAG_1 (28) + ssm 0,0 + b,n perf_rdr_shift_in_W_leave + nop + + ; + ; RDR 16 read sequence + ; + sync ; RDR 16 read sequence + ssm 0,0 + SFDIAG (16) + ssm 0,0 + MFDIAG_1 (28) + b,n perf_rdr_shift_in_W_leave + ssm 0,0 + nop + + ; + ; RDR 17 read sequence + ; + SFDIAG (17) + ssm 0,0 + MFDIAG_1 (28) + shrpd ret0,%r0,%sar,%r1 + MTDIAG_1 (1) + STDIAG (17) + ssm 0,0 + b,n perf_rdr_shift_in_W_leave + + ; + ; RDR 18 read sequence + ; + SFDIAG (18) + ssm 0,0 + MFDIAG_1 (28) + shrpd ret0,%r0,%sar,%r1 + MTDIAG_1 (1) + STDIAG (18) + ssm 0,0 + b,n perf_rdr_shift_in_W_leave + +; +; RDR 19 read sequence +; + b,n perf_rdr_shift_in_W_leave + nop + nop + nop + nop + nop + nop + nop + + ; + ; RDR 20 read sequence + ; + sync + ssm 0,0 + SFDIAG (20) + ssm 0,0 + MFDIAG_1 (28) + b,n perf_rdr_shift_in_W_leave + ssm 0,0 + nop + + ; + ; RDR 21 read sequence + ; + sync + ssm 0,0 + SFDIAG (21) + ssm 0,0 + MFDIAG_1 (28) + b,n perf_rdr_shift_in_W_leave + ssm 0,0 + nop + + ; + ; RDR 22 read sequence + ; + sync + ssm 0,0 + SFDIAG (22) + ssm 0,0 + MFDIAG_1 (28) + b,n perf_rdr_shift_in_W_leave + ssm 0,0 + nop + + ; + ; RDR 23 read sequence + ; + sync + ssm 0,0 + SFDIAG (23) + ssm 0,0 + MFDIAG_1 (28) + b,n perf_rdr_shift_in_W_leave + ssm 0,0 + nop + + ; + ; RDR 24 read sequence + ; + sync + ssm 0,0 + SFDIAG (24) + ssm 0,0 + MFDIAG_1 (28) + b,n perf_rdr_shift_in_W_leave + ssm 0,0 + nop + + ; + ; RDR 25 read sequence + ; + sync + ssm 0,0 + SFDIAG (25) + ssm 0,0 + MFDIAG_1 (28) + b,n perf_rdr_shift_in_W_leave + ssm 0,0 + nop + + ; + ; RDR 26 read sequence + ; + SFDIAG (26) + ssm 0,0 + MFDIAG_1 (28) + shrpd ret0,%r0,%sar,%r1 + MTDIAG_1 (1) + STDIAG (26) + ssm 0,0 + b,n perf_rdr_shift_in_W_leave + + ; + ; RDR 27 read sequence + ; + SFDIAG (27) + ssm 0,0 + MFDIAG_1 (28) + shrpd ret0,%r0,%sar,%r1 + MTDIAG_1 (1) + STDIAG (27) + ssm 0,0 + b,n perf_rdr_shift_in_W_leave + + ; + ; RDR 28 read sequence + ; + sync + ssm 0,0 + SFDIAG (28) + ssm 0,0 + MFDIAG_1 (28) + b,n perf_rdr_shift_in_W_leave + ssm 0,0 + nop + + ; + ; RDR 29 read sequence + ; + sync + ssm 0,0 + SFDIAG (29) + ssm 0,0 + MFDIAG_1 (28) + b,n perf_rdr_shift_in_W_leave + ssm 0,0 + nop + + ; + ; RDR 30 read sequence + ; + SFDIAG (30) + ssm 0,0 + MFDIAG_1 (28) + shrpd ret0,%r0,%sar,%r1 + MTDIAG_1 (1) + STDIAG (30) + ssm 0,0 + b,n perf_rdr_shift_in_W_leave + + ; + ; RDR 31 read sequence + ; + sync + ssm 0,0 + SFDIAG (31) + ssm 0,0 + MFDIAG_1 (28) + nop + ssm 0,0 + nop + + ; + ; Fallthrough + ; + +perf_rdr_shift_in_W_leave: + bve (%r2) + .exit + MTDIAG_2 (24) ; restore DR2 + .procend + + +;************************************************************************ +;* * +;* Name: perf_rdr_shift_out_W * +;* * +;* Description: * +;* This routine moves data to the RDR's. The double-word that * +;* arg1 points to is loaded and moved into the staging register. * +;* Then the STDIAG instruction for the RDR # in arg0 is called * +;* to move the data to the RDR. * +;* * +;* Arguments: * +;* arg0 = rdr number * +;* arg1 = 64-bit value to write * +;* %r24 - DR2 | DR2_SLOW_RET * +;* %r23 - original DR2 value * +;* * +;* Returns: * +;* None * +;* * +;* Register usage: * +;* * +;************************************************************************ + + .export perf_rdr_shift_out_W,code +perf_rdr_shift_out_W: + .proc + .callinfo frame=0,NO_CALLS + .entry +; +; NOTE: The PCX-W ERS states that DR2_SLOW_RET must be set before any +; shifting is done, from or to, the remote diagnose registers. +; + + depdi,z 1,DR2_SLOW_RET,1,%r24 + MFDIAG_2 (23) + or %r24,%r23,%r24 + MTDIAG_2 (24) ; set DR2_SLOW_RET + + MTDIAG_1 (25) ; data to the staging register + shladd arg0,2,%r0,%r1 ; %r1 = 4 * RDR number + blr %r1,%r0 ; branch to 8-instruction sequence + nop + + ; + ; RDR 0 write sequence + ; + sync ; RDR 0 write sequence + ssm 0,0 + STDIAG (0) + ssm 0,0 + b,n perf_rdr_shift_out_W_leave + nop + ssm 0,0 + nop + + ; + ; RDR 1 write sequence + ; + sync + ssm 0,0 + STDIAG (1) + ssm 0,0 + b,n perf_rdr_shift_out_W_leave + nop + ssm 0,0 + nop + + ; + ; RDR 2 write sequence + ; + sync + ssm 0,0 + STDIAG (2) + ssm 0,0 + b,n perf_rdr_shift_out_W_leave + nop + ssm 0,0 + nop + + ; + ; RDR 3 write sequence + ; + sync + ssm 0,0 + STDIAG (3) + ssm 0,0 + b,n perf_rdr_shift_out_W_leave + nop + ssm 0,0 + nop + + ; + ; RDR 4 write sequence + ; + sync + ssm 0,0 + STDIAG (4) + ssm 0,0 + b,n perf_rdr_shift_out_W_leave + nop + ssm 0,0 + nop + + ; + ; RDR 5 write sequence + ; + sync + ssm 0,0 + STDIAG (5) + ssm 0,0 + b,n perf_rdr_shift_out_W_leave + nop + ssm 0,0 + nop + + ; + ; RDR 6 write sequence + ; + sync + ssm 0,0 + STDIAG (6) + ssm 0,0 + b,n perf_rdr_shift_out_W_leave + nop + ssm 0,0 + nop + + ; + ; RDR 7 write sequence + ; + sync + ssm 0,0 + STDIAG (7) + ssm 0,0 + b,n perf_rdr_shift_out_W_leave + nop + ssm 0,0 + nop + + ; + ; RDR 8 write sequence + ; + sync + ssm 0,0 + STDIAG (8) + ssm 0,0 + b,n perf_rdr_shift_out_W_leave + nop + ssm 0,0 + nop + + ; + ; RDR 9 write sequence + ; + sync + ssm 0,0 + STDIAG (9) + ssm 0,0 + b,n perf_rdr_shift_out_W_leave + nop + ssm 0,0 + nop + + ; + ; RDR 10 write sequence + ; + sync + ssm 0,0 + STDIAG (10) + STDIAG (26) + ssm 0,0 + b,n perf_rdr_shift_out_W_leave + ssm 0,0 + nop + + ; + ; RDR 11 write sequence + ; + sync + ssm 0,0 + STDIAG (11) + STDIAG (27) + ssm 0,0 + b,n perf_rdr_shift_out_W_leave + ssm 0,0 + nop + + ; + ; RDR 12 write sequence + ; + sync + ssm 0,0 + STDIAG (12) + ssm 0,0 + b,n perf_rdr_shift_out_W_leave + nop + ssm 0,0 + nop + + ; + ; RDR 13 write sequence + ; + sync + ssm 0,0 + STDIAG (13) + ssm 0,0 + b,n perf_rdr_shift_out_W_leave + nop + ssm 0,0 + nop + + ; + ; RDR 14 write sequence + ; + sync + ssm 0,0 + STDIAG (14) + ssm 0,0 + b,n perf_rdr_shift_out_W_leave + nop + ssm 0,0 + nop + + ; + ; RDR 15 write sequence + ; + sync + ssm 0,0 + STDIAG (15) + ssm 0,0 + b,n perf_rdr_shift_out_W_leave + nop + ssm 0,0 + nop + + ; + ; RDR 16 write sequence + ; + sync + ssm 0,0 + STDIAG (16) + ssm 0,0 + b,n perf_rdr_shift_out_W_leave + nop + ssm 0,0 + nop + + ; + ; RDR 17 write sequence + ; + sync + ssm 0,0 + STDIAG (17) + ssm 0,0 + b,n perf_rdr_shift_out_W_leave + nop + ssm 0,0 + nop + + ; + ; RDR 18 write sequence + ; + sync + ssm 0,0 + STDIAG (18) + ssm 0,0 + b,n perf_rdr_shift_out_W_leave + nop + ssm 0,0 + nop + + ; + ; RDR 19 write sequence + ; + sync + ssm 0,0 + STDIAG (19) + ssm 0,0 + b,n perf_rdr_shift_out_W_leave + nop + ssm 0,0 + nop + + ; + ; RDR 20 write sequence + ; + sync + ssm 0,0 + STDIAG (20) + ssm 0,0 + b,n perf_rdr_shift_out_W_leave + nop + ssm 0,0 + nop + + ; + ; RDR 21 write sequence + ; + sync + ssm 0,0 + STDIAG (21) + ssm 0,0 + b,n perf_rdr_shift_out_W_leave + nop + ssm 0,0 + nop + + ; + ; RDR 22 write sequence + ; + sync + ssm 0,0 + STDIAG (22) + ssm 0,0 + b,n perf_rdr_shift_out_W_leave + nop + ssm 0,0 + nop + + ; + ; RDR 23 write sequence + ; + sync + ssm 0,0 + STDIAG (23) + ssm 0,0 + b,n perf_rdr_shift_out_W_leave + nop + ssm 0,0 + nop + + ; + ; RDR 24 write sequence + ; + sync + ssm 0,0 + STDIAG (24) + ssm 0,0 + b,n perf_rdr_shift_out_W_leave + nop + ssm 0,0 + nop + + ; + ; RDR 25 write sequence + ; + sync + ssm 0,0 + STDIAG (25) + ssm 0,0 + b,n perf_rdr_shift_out_W_leave + nop + ssm 0,0 + nop + + ; + ; RDR 26 write sequence + ; + sync + ssm 0,0 + STDIAG (10) + STDIAG (26) + ssm 0,0 + b,n perf_rdr_shift_out_W_leave + ssm 0,0 + nop + + ; + ; RDR 27 write sequence + ; + sync + ssm 0,0 + STDIAG (11) + STDIAG (27) + ssm 0,0 + b,n perf_rdr_shift_out_W_leave + ssm 0,0 + nop + + ; + ; RDR 28 write sequence + ; + sync + ssm 0,0 + STDIAG (28) + ssm 0,0 + b,n perf_rdr_shift_out_W_leave + nop + ssm 0,0 + nop + + ; + ; RDR 29 write sequence + ; + sync + ssm 0,0 + STDIAG (29) + ssm 0,0 + b,n perf_rdr_shift_out_W_leave + nop + ssm 0,0 + nop + + ; + ; RDR 30 write sequence + ; + sync + ssm 0,0 + STDIAG (30) + ssm 0,0 + b,n perf_rdr_shift_out_W_leave + nop + ssm 0,0 + nop + + ; + ; RDR 31 write sequence + ; + sync + ssm 0,0 + STDIAG (31) + ssm 0,0 + b,n perf_rdr_shift_out_W_leave + nop + ssm 0,0 + nop + +perf_rdr_shift_out_W_leave: + bve (%r2) + .exit + MTDIAG_2 (23) ; restore DR2 + .procend + + +;**************************** CHRIS *********************************** + +;************************************************************************ +;* * +;* Name: rdr_shift_in_U * +;* * +;* Description: * +;* This routine shifts data in from the RDR in arg0 and returns * +;* the result in ret0. If the RDR is <= 64 bits in length, it * +;* is shifted shifted backup immediately. This is to compensate * +;* for RDR10 which has bits that preclude PDC stack operations * +;* when they are in the wrong state. * +;* * +;* Arguments: * +;* arg0 : rdr to be read * +;* arg1 : bit length of rdr * +;* * +;* Returns: * +;* ret0 = next 64 bits of rdr data from staging register * +;* * +;* Register usage: * +;* arg0 : rdr to be read * +;* arg1 : bit length of rdr * +;* %r24 - original DR2 value * +;* %r23 - DR2 | DR2_SLOW_RET * +;* %r1 - scratch * +;* * +;************************************************************************ + + .export perf_rdr_shift_in_U,code +perf_rdr_shift_in_U: + .proc + .callinfo frame=0,NO_CALLS + .entry + +; read(shift in) the RDR. +; +; NOTE: The PCX-U ERS states that DR2_SLOW_RET must be set before any +; shifting is done, from or to, remote diagnose registers. + + depdi,z 1,DR2_SLOW_RET,1,%r29 + MFDIAG_2 (24) + or %r24,%r29,%r29 + MTDIAG_2 (29) ; set DR2_SLOW_RET + + nop + nop + nop + nop + +; +; Start of next 32-byte cacheline +; + nop + nop + nop + extrd,u arg1,63,6,%r1 + + mtsar %r1 + shladd arg0,2,%r0,%r1 ; %r1 = 4 * RDR number + blr %r1,%r0 ; branch to 8-instruction sequence + nop + +; +; Start of next 32-byte cacheline +; + SFDIAG (0) ; RDR 0 read sequence + ssm 0,0 + MFDIAG_1 (28) + shrpd ret0,%r0,%sar,%r1 + MTDIAG_1 (1) + STDIAG (0) + ssm 0,0 + b,n perf_rdr_shift_in_U_leave + + SFDIAG (1) ; RDR 1 read sequence + ssm 0,0 + MFDIAG_1 (28) + shrpd ret0,%r0,%sar,%r1 + MTDIAG_1 (1) + STDIAG (1) + ssm 0,0 + b,n perf_rdr_shift_in_U_leave + + sync ; RDR 2 read sequence + ssm 0,0 + SFDIAG (4) + ssm 0,0 + MFDIAG_1 (28) + b,n perf_rdr_shift_in_U_leave + ssm 0,0 + nop + + sync ; RDR 3 read sequence + ssm 0,0 + SFDIAG (3) + ssm 0,0 + MFDIAG_1 (28) + b,n perf_rdr_shift_in_U_leave + ssm 0,0 + nop + + sync ; RDR 4 read sequence + ssm 0,0 + SFDIAG (4) + ssm 0,0 + MFDIAG_1 (28) + b,n perf_rdr_shift_in_U_leave + ssm 0,0 + nop + + sync ; RDR 5 read sequence + ssm 0,0 + SFDIAG (5) + ssm 0,0 + MFDIAG_1 (28) + b,n perf_rdr_shift_in_U_leave + ssm 0,0 + nop + + sync ; RDR 6 read sequence + ssm 0,0 + SFDIAG (6) + ssm 0,0 + MFDIAG_1 (28) + b,n perf_rdr_shift_in_U_leave + ssm 0,0 + nop + + sync ; RDR 7 read sequence + ssm 0,0 + SFDIAG (7) + ssm 0,0 + MFDIAG_1 (28) + b,n perf_rdr_shift_in_U_leave + ssm 0,0 + nop + + b,n perf_rdr_shift_in_U_leave + nop + nop + nop + nop + nop + nop + nop + + SFDIAG (9) ; RDR 9 read sequence + ssm 0,0 + MFDIAG_1 (28) + shrpd ret0,%r0,%sar,%r1 + MTDIAG_1 (1) + STDIAG (9) + ssm 0,0 + b,n perf_rdr_shift_in_U_leave + + SFDIAG (10) ; RDR 10 read sequence + ssm 0,0 + MFDIAG_1 (28) + shrpd ret0,%r0,%sar,%r1 + MTDIAG_1 (1) + STDIAG (10) + ssm 0,0 + b,n perf_rdr_shift_in_U_leave + + SFDIAG (11) ; RDR 11 read sequence + ssm 0,0 + MFDIAG_1 (28) + shrpd ret0,%r0,%sar,%r1 + MTDIAG_1 (1) + STDIAG (11) + ssm 0,0 + b,n perf_rdr_shift_in_U_leave + + SFDIAG (12) ; RDR 12 read sequence + ssm 0,0 + MFDIAG_1 (28) + shrpd ret0,%r0,%sar,%r1 + MTDIAG_1 (1) + STDIAG (12) + ssm 0,0 + b,n perf_rdr_shift_in_U_leave + + SFDIAG (13) ; RDR 13 read sequence + ssm 0,0 + MFDIAG_1 (28) + shrpd ret0,%r0,%sar,%r1 + MTDIAG_1 (1) + STDIAG (13) + ssm 0,0 + b,n perf_rdr_shift_in_U_leave + + SFDIAG (14) ; RDR 14 read sequence + ssm 0,0 + MFDIAG_1 (28) + shrpd ret0,%r0,%sar,%r1 + MTDIAG_1 (1) + STDIAG (14) + ssm 0,0 + b,n perf_rdr_shift_in_U_leave + + SFDIAG (15) ; RDR 15 read sequence + ssm 0,0 + MFDIAG_1 (28) + shrpd ret0,%r0,%sar,%r1 + MTDIAG_1 (1) + STDIAG (15) + ssm 0,0 + b,n perf_rdr_shift_in_U_leave + + sync ; RDR 16 read sequence + ssm 0,0 + SFDIAG (16) + ssm 0,0 + MFDIAG_1 (28) + b,n perf_rdr_shift_in_U_leave + ssm 0,0 + nop + + SFDIAG (17) ; RDR 17 read sequence + ssm 0,0 + MFDIAG_1 (28) + shrpd ret0,%r0,%sar,%r1 + MTDIAG_1 (1) + STDIAG (17) + ssm 0,0 + b,n perf_rdr_shift_in_U_leave + + SFDIAG (18) ; RDR 18 read sequence + ssm 0,0 + MFDIAG_1 (28) + shrpd ret0,%r0,%sar,%r1 + MTDIAG_1 (1) + STDIAG (18) + ssm 0,0 + b,n perf_rdr_shift_in_U_leave + + b,n perf_rdr_shift_in_U_leave + nop + nop + nop + nop + nop + nop + nop + + sync ; RDR 20 read sequence + ssm 0,0 + SFDIAG (20) + ssm 0,0 + MFDIAG_1 (28) + b,n perf_rdr_shift_in_U_leave + ssm 0,0 + nop + + sync ; RDR 21 read sequence + ssm 0,0 + SFDIAG (21) + ssm 0,0 + MFDIAG_1 (28) + b,n perf_rdr_shift_in_U_leave + ssm 0,0 + nop + + sync ; RDR 22 read sequence + ssm 0,0 + SFDIAG (22) + ssm 0,0 + MFDIAG_1 (28) + b,n perf_rdr_shift_in_U_leave + ssm 0,0 + nop + + sync ; RDR 23 read sequence + ssm 0,0 + SFDIAG (23) + ssm 0,0 + MFDIAG_1 (28) + b,n perf_rdr_shift_in_U_leave + ssm 0,0 + nop + + sync ; RDR 24 read sequence + ssm 0,0 + SFDIAG (24) + ssm 0,0 + MFDIAG_1 (28) + b,n perf_rdr_shift_in_U_leave + ssm 0,0 + nop + + sync ; RDR 25 read sequence + ssm 0,0 + SFDIAG (25) + ssm 0,0 + MFDIAG_1 (28) + b,n perf_rdr_shift_in_U_leave + ssm 0,0 + nop + + SFDIAG (26) ; RDR 26 read sequence + ssm 0,0 + MFDIAG_1 (28) + shrpd ret0,%r0,%sar,%r1 + MTDIAG_1 (1) + STDIAG (26) + ssm 0,0 + b,n perf_rdr_shift_in_U_leave + + SFDIAG (27) ; RDR 27 read sequence + ssm 0,0 + MFDIAG_1 (28) + shrpd ret0,%r0,%sar,%r1 + MTDIAG_1 (1) + STDIAG (27) + ssm 0,0 + b,n perf_rdr_shift_in_U_leave + + sync ; RDR 28 read sequence + ssm 0,0 + SFDIAG (28) + ssm 0,0 + MFDIAG_1 (28) + b,n perf_rdr_shift_in_U_leave + ssm 0,0 + nop + + b,n perf_rdr_shift_in_U_leave + nop + nop + nop + nop + nop + nop + nop + + SFDIAG (30) ; RDR 30 read sequence + ssm 0,0 + MFDIAG_1 (28) + shrpd ret0,%r0,%sar,%r1 + MTDIAG_1 (1) + STDIAG (30) + ssm 0,0 + b,n perf_rdr_shift_in_U_leave + + SFDIAG (31) ; RDR 31 read sequence + ssm 0,0 + MFDIAG_1 (28) + shrpd ret0,%r0,%sar,%r1 + MTDIAG_1 (1) + STDIAG (31) + ssm 0,0 + b,n perf_rdr_shift_in_U_leave + nop + +perf_rdr_shift_in_U_leave: + bve (%r2) + .exit + MTDIAG_2 (24) ; restore DR2 + .procend + +;************************************************************************ +;* * +;* Name: rdr_shift_out_U * +;* * +;* Description: * +;* This routine moves data to the RDR's. The double-word that * +;* arg1 points to is loaded and moved into the staging register. * +;* Then the STDIAG instruction for the RDR # in arg0 is called * +;* to move the data to the RDR. * +;* * +;* Arguments: * +;* arg0 = rdr target * +;* arg1 = buffer pointer * +;* * +;* Returns: * +;* None * +;* * +;* Register usage: * +;* arg0 = rdr target * +;* arg1 = buffer pointer * +;* %r24 - DR2 | DR2_SLOW_RET * +;* %r23 - original DR2 value * +;* * +;************************************************************************ + + .export perf_rdr_shift_out_U,code +perf_rdr_shift_out_U: + .proc + .callinfo frame=0,NO_CALLS + .entry + +; +; NOTE: The PCX-U ERS states that DR2_SLOW_RET must be set before any +; shifting is done, from or to, the remote diagnose registers. +; + + depdi,z 1,DR2_SLOW_RET,1,%r24 + MFDIAG_2 (23) + or %r24,%r23,%r24 + MTDIAG_2 (24) ; set DR2_SLOW_RET + + MTDIAG_1 (25) ; data to the staging register + shladd arg0,2,%r0,%r1 ; %r1 = 4 * RDR number + blr %r1,%r0 ; branch to 8-instruction sequence + nop + +; +; 32-byte cachline aligned +; + + sync ; RDR 0 write sequence + ssm 0,0 + STDIAG (0) + ssm 0,0 + b,n perf_rdr_shift_out_U_leave + nop + ssm 0,0 + nop + + sync ; RDR 1 write sequence + ssm 0,0 + STDIAG (1) + ssm 0,0 + b,n perf_rdr_shift_out_U_leave + nop + ssm 0,0 + nop + + sync ; RDR 2 write sequence + ssm 0,0 + STDIAG (2) + ssm 0,0 + b,n perf_rdr_shift_out_U_leave + nop + ssm 0,0 + nop + + sync ; RDR 3 write sequence + ssm 0,0 + STDIAG (3) + ssm 0,0 + b,n perf_rdr_shift_out_U_leave + nop + ssm 0,0 + nop + + sync ; RDR 4 write sequence + ssm 0,0 + STDIAG (4) + ssm 0,0 + b,n perf_rdr_shift_out_U_leave + nop + ssm 0,0 + nop + + sync ; RDR 5 write sequence + ssm 0,0 + STDIAG (5) + ssm 0,0 + b,n perf_rdr_shift_out_U_leave + nop + ssm 0,0 + nop + + sync ; RDR 6 write sequence + ssm 0,0 + STDIAG (6) + ssm 0,0 + b,n perf_rdr_shift_out_U_leave + nop + ssm 0,0 + nop + + sync ; RDR 7 write sequence + ssm 0,0 + STDIAG (7) + ssm 0,0 + b,n perf_rdr_shift_out_U_leave + nop + ssm 0,0 + nop + + sync ; RDR 8 write sequence + ssm 0,0 + STDIAG (8) + ssm 0,0 + b,n perf_rdr_shift_out_U_leave + nop + ssm 0,0 + nop + + sync ; RDR 9 write sequence + ssm 0,0 + STDIAG (9) + ssm 0,0 + b,n perf_rdr_shift_out_U_leave + nop + ssm 0,0 + nop + + sync ; RDR 10 write sequence + ssm 0,0 + STDIAG (10) + ssm 0,0 + b,n perf_rdr_shift_out_U_leave + nop + ssm 0,0 + nop + + sync ; RDR 11 write sequence + ssm 0,0 + STDIAG (11) + ssm 0,0 + b,n perf_rdr_shift_out_U_leave + nop + ssm 0,0 + nop + + sync ; RDR 12 write sequence + ssm 0,0 + STDIAG (12) + ssm 0,0 + b,n perf_rdr_shift_out_U_leave + nop + ssm 0,0 + nop + + sync ; RDR 13 write sequence + ssm 0,0 + STDIAG (13) + ssm 0,0 + b,n perf_rdr_shift_out_U_leave + nop + ssm 0,0 + nop + + sync ; RDR 14 write sequence + ssm 0,0 + STDIAG (14) + ssm 0,0 + b,n perf_rdr_shift_out_U_leave + nop + ssm 0,0 + nop + + sync ; RDR 15 write sequence + ssm 0,0 + STDIAG (15) + ssm 0,0 + b,n perf_rdr_shift_out_U_leave + nop + ssm 0,0 + nop + + sync ; RDR 16 write sequence + ssm 0,0 + STDIAG (16) + ssm 0,0 + b,n perf_rdr_shift_out_U_leave + nop + ssm 0,0 + nop + + sync ; RDR 17 write sequence + ssm 0,0 + STDIAG (17) + ssm 0,0 + b,n perf_rdr_shift_out_U_leave + nop + ssm 0,0 + nop + + sync ; RDR 18 write sequence + ssm 0,0 + STDIAG (18) + ssm 0,0 + b,n perf_rdr_shift_out_U_leave + nop + ssm 0,0 + nop + + sync ; RDR 19 write sequence + ssm 0,0 + STDIAG (19) + ssm 0,0 + b,n perf_rdr_shift_out_U_leave + nop + ssm 0,0 + nop + + sync ; RDR 20 write sequence + ssm 0,0 + STDIAG (20) + ssm 0,0 + b,n perf_rdr_shift_out_U_leave + nop + ssm 0,0 + nop + + sync ; RDR 21 write sequence + ssm 0,0 + STDIAG (21) + ssm 0,0 + b,n perf_rdr_shift_out_U_leave + nop + ssm 0,0 + nop + + sync ; RDR 22 write sequence + ssm 0,0 + STDIAG (22) + ssm 0,0 + b,n perf_rdr_shift_out_U_leave + nop + ssm 0,0 + nop + + sync ; RDR 23 write sequence + ssm 0,0 + STDIAG (23) + ssm 0,0 + b,n perf_rdr_shift_out_U_leave + nop + ssm 0,0 + nop + + sync ; RDR 24 write sequence + ssm 0,0 + STDIAG (24) + ssm 0,0 + b,n perf_rdr_shift_out_U_leave + nop + ssm 0,0 + nop + + sync ; RDR 25 write sequence + ssm 0,0 + STDIAG (25) + ssm 0,0 + b,n perf_rdr_shift_out_U_leave + nop + ssm 0,0 + nop + + sync ; RDR 26 write sequence + ssm 0,0 + STDIAG (26) + ssm 0,0 + b,n perf_rdr_shift_out_U_leave + nop + ssm 0,0 + nop + + sync ; RDR 27 write sequence + ssm 0,0 + STDIAG (27) + ssm 0,0 + b,n perf_rdr_shift_out_U_leave + nop + ssm 0,0 + nop + + sync ; RDR 28 write sequence + ssm 0,0 + STDIAG (28) + ssm 0,0 + b,n perf_rdr_shift_out_U_leave + nop + ssm 0,0 + nop + + sync ; RDR 29 write sequence + ssm 0,0 + STDIAG (29) + ssm 0,0 + b,n perf_rdr_shift_out_U_leave + nop + ssm 0,0 + nop + + sync ; RDR 30 write sequence + ssm 0,0 + STDIAG (30) + ssm 0,0 + b,n perf_rdr_shift_out_U_leave + nop + ssm 0,0 + nop + + sync ; RDR 31 write sequence + ssm 0,0 + STDIAG (31) + ssm 0,0 + b,n perf_rdr_shift_out_U_leave + nop + ssm 0,0 + nop + +perf_rdr_shift_out_U_leave: + bve (%r2) + .exit + MTDIAG_2 (23) ; restore DR2 + .procend + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/perf.c linux.19rc3-ac4/arch/parisc/kernel/perf.c --- linux.19rc3/arch/parisc/kernel/perf.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/perf.c 2002-07-29 13:58:36.000000000 +0100 @@ -0,0 +1,838 @@ +/* + * Parisc performance counters + * Copyright (C) 2001 Randolph Chung + * + * This code is derived, with permission, from HP/UX sources. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * Edited comment from original sources: + * + * This driver programs the PCX-U/PCX-W performance counters + * on the PA-RISC 2.0 chips. The driver keeps all images now + * internally to the kernel to hopefully eliminate the possiblity + * of a bad image halting the CPU. Also, there are different + * images for the PCX-W and later chips vs the PCX-U chips. + * + * Only 1 process is allowed to access the driver at any time, + * so the only protection that is needed is at open and close. + * A variable "perf_enabled" is used to hold the state of the + * driver. The spinlock "perf_lock" is used to protect the + * modification of the state during open/close operations so + * multiple processes don't get into the driver simultaneously. + * + * This driver accesses the processor directly vs going through + * the PDC INTRIGUE calls. This is done to eliminate bugs introduced + * in various PDC revisions. The code is much more maintainable + * and reliable this way vs having to debug on every version of PDC + * on every box. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "perf_images.h" + +#define MAX_RDR_WORDS 24 +#define PERF_VERSION 2 /* derived from hpux's PI v2 interface */ + +/* definition of RDR regs */ +struct rdr_tbl_ent { + uint16_t width; + uint8_t num_words; + uint8_t write_control; +}; + +static int perf_processor_interface = UNKNOWN_INTF; +static int perf_enabled = 0; +static spinlock_t perf_lock; +struct parisc_device *cpu_device = NULL; + +/* RDRs to write for PCX-W */ +static int perf_rdrs_W[] = + { 0, 1, 4, 5, 6, 15, 16, 17, 18, 20, 21, 22, 23, 24, 25, -1 }; + +/* RDRs to write for PCX-U */ +static int perf_rdrs_U[] = + { 0, 1, 4, 5, 6, 7, 16, 17, 18, 20, 21, 22, 23, 24, 25, -1 }; + +/* RDR register descriptions for PCX-W */ +static struct rdr_tbl_ent perf_rdr_tbl_W[] = { + { 19, 1, 8 }, /* RDR 0 */ + { 16, 1, 16 }, /* RDR 1 */ + { 72, 2, 0 }, /* RDR 2 */ + { 81, 2, 0 }, /* RDR 3 */ + { 328, 6, 0 }, /* RDR 4 */ + { 160, 3, 0 }, /* RDR 5 */ + { 336, 6, 0 }, /* RDR 6 */ + { 164, 3, 0 }, /* RDR 7 */ + { 0, 0, 0 }, /* RDR 8 */ + { 35, 1, 0 }, /* RDR 9 */ + { 6, 1, 0 }, /* RDR 10 */ + { 18, 1, 0 }, /* RDR 11 */ + { 13, 1, 0 }, /* RDR 12 */ + { 8, 1, 0 }, /* RDR 13 */ + { 8, 1, 0 }, /* RDR 14 */ + { 8, 1, 0 }, /* RDR 15 */ + { 1530, 24, 0 }, /* RDR 16 */ + { 16, 1, 0 }, /* RDR 17 */ + { 4, 1, 0 }, /* RDR 18 */ + { 0, 0, 0 }, /* RDR 19 */ + { 152, 3, 24 }, /* RDR 20 */ + { 152, 3, 24 }, /* RDR 21 */ + { 233, 4, 48 }, /* RDR 22 */ + { 233, 4, 48 }, /* RDR 23 */ + { 71, 2, 0 }, /* RDR 24 */ + { 71, 2, 0 }, /* RDR 25 */ + { 11, 1, 0 }, /* RDR 26 */ + { 18, 1, 0 }, /* RDR 27 */ + { 128, 2, 0 }, /* RDR 28 */ + { 0, 0, 0 }, /* RDR 29 */ + { 16, 1, 0 }, /* RDR 30 */ + { 16, 1, 0 }, /* RDR 31 */ +}; + +/* RDR register descriptions for PCX-U */ +static struct rdr_tbl_ent perf_rdr_tbl_U[] = { + { 19, 1, 8 }, /* RDR 0 */ + { 32, 1, 16 }, /* RDR 1 */ + { 20, 1, 0 }, /* RDR 2 */ + { 0, 0, 0 }, /* RDR 3 */ + { 344, 6, 0 }, /* RDR 4 */ + { 176, 3, 0 }, /* RDR 5 */ + { 336, 6, 0 }, /* RDR 6 */ + { 0, 0, 0 }, /* RDR 7 */ + { 0, 0, 0 }, /* RDR 8 */ + { 0, 0, 0 }, /* RDR 9 */ + { 28, 1, 0 }, /* RDR 10 */ + { 33, 1, 0 }, /* RDR 11 */ + { 0, 0, 0 }, /* RDR 12 */ + { 230, 4, 0 }, /* RDR 13 */ + { 32, 1, 0 }, /* RDR 14 */ + { 128, 2, 0 }, /* RDR 15 */ + { 1494, 24, 0 }, /* RDR 16 */ + { 18, 1, 0 }, /* RDR 17 */ + { 4, 1, 0 }, /* RDR 18 */ + { 0, 0, 0 }, /* RDR 19 */ + { 158, 3, 24 }, /* RDR 20 */ + { 158, 3, 24 }, /* RDR 21 */ + { 194, 4, 48 }, /* RDR 22 */ + { 194, 4, 48 }, /* RDR 23 */ + { 71, 2, 0 }, /* RDR 24 */ + { 71, 2, 0 }, /* RDR 25 */ + { 28, 1, 0 }, /* RDR 26 */ + { 33, 1, 0 }, /* RDR 27 */ + { 88, 2, 0 }, /* RDR 28 */ + { 32, 1, 0 }, /* RDR 29 */ + { 24, 1, 0 }, /* RDR 30 */ + { 16, 1, 0 }, /* RDR 31 */ +}; + +/* + * A non-zero write_control in the above tables is a byte offset into + * this array. + */ +static uint64_t perf_bitmasks[] = { + 0x0000000000000000, /* first dbl word must be zero */ + 0xfdffe00000000000, /* RDR0 bitmask */ + 0x003f000000000000, /* RDR1 bitmask */ + 0x00ffffffffffffff, /* RDR20-RDR21 bitmask (152 bits) */ + 0xffffffffffffffff, + 0xfffffffc00000000, + 0xffffffffffffffff, /* RDR22-RDR23 bitmask (233 bits) */ + 0xffffffffffffffff, + 0xfffffffffffffffc, + 0xff00000000000000 +}; + +/* + * Write control bitmasks for Pa-8700 processor given + * somethings have changed slightly. + */ +static uint64_t perf_bitmasks_piranha[] = { + 0x0000000000000000, /* first dbl word must be zero */ + 0xfdffe00000000000, /* RDR0 bitmask */ + 0x003f000000000000, /* RDR1 bitmask */ + 0x00ffffffffffffff, /* RDR20-RDR21 bitmask (158 bits) */ + 0xffffffffffffffff, + 0xfffffffc00000000, + 0xffffffffffffffff, /* RDR22-RDR23 bitmask (210 bits) */ + 0xffffffffffffffff, + 0xffffffffffffffff, + 0xfffc000000000000 +}; + +static uint64_t *bitmask_array; /* array of bitmasks to use */ + +/****************************************************************************** + * Function Prototypes + *****************************************************************************/ +static int perf_config(uint32_t *image_ptr); +static int perf_release(struct inode *inode, struct file *file); +static int perf_open(struct inode *inode, struct file *file); +static ssize_t perf_read(struct file *file, char *buf, size_t cnt, loff_t *ppos); +static ssize_t perf_write(struct file *file, const char *buf, size_t count, + loff_t *ppos); +static int perf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg); +static void perf_start_counters(void); +static int perf_stop_counters(uint32_t *raddr); +static struct rdr_tbl_ent * perf_rdr_get_entry(uint32_t rdr_num); +static int perf_rdr_read_ubuf(uint32_t rdr_num, uint64_t *buffer); +static int perf_rdr_clear(uint32_t rdr_num); +static int perf_write_image(uint64_t *memaddr); +static void perf_rdr_write(uint32_t rdr_num, uint64_t *buffer); + +/* External Assembly Routines */ +extern uint64_t perf_rdr_shift_in_W (uint32_t rdr_num, uint16_t width); +extern uint64_t perf_rdr_shift_in_U (uint32_t rdr_num, uint16_t width); +extern void perf_rdr_shift_out_W (uint32_t rdr_num, uint64_t buffer); +extern void perf_rdr_shift_out_U (uint32_t rdr_num, uint64_t buffer); +extern void perf_intrigue_enable_perf_counters (void); +extern void perf_intrigue_disable_perf_counters (void); + +/****************************************************************************** + * Function Definitions + *****************************************************************************/ + + +/* + * configure: + * + * Configure the cpu with a given data image. First turn off the counters, + * then download the image, then turn the counters back on. + */ +static int perf_config(uint32_t *image_ptr) +{ + long error; + uint32_t raddr[4]; + + /* Stop the counters*/ + error = perf_stop_counters(raddr); + if (error != 0) { + printk("perf_config: perf_stop_counters = %ld\n", error); + return -EINVAL; + } + +printk("Preparing to write image\n"); + /* Write the image to the chip */ + error = perf_write_image((uint64_t *)image_ptr); + if (error != 0) { + printk("perf_config: DOWNLOAD = %ld\n", error); + return -EINVAL; + } + +printk("Preparing to start counters\n"); + + /* Start the counters */ + perf_start_counters(); + + return sizeof(uint32_t); +} + +/* + * Open the device and initialize all of it's memory. The device is only + * opened once, but can be "queried" by multiple processes that know its + * file descriptor. + */ +static int perf_open(struct inode *inode, struct file *file) +{ + spin_lock(&perf_lock); + if (perf_enabled) { + spin_unlock(&perf_lock); + return -EBUSY; + } + perf_enabled = 1; + spin_unlock(&perf_lock); + + MOD_INC_USE_COUNT; + + return 0; +} + +/* + * Close the device. + */ +static int perf_release(struct inode *inode, struct file *file) +{ + spin_lock(&perf_lock); + perf_enabled = 0; + spin_unlock(&perf_lock); + + MOD_DEC_USE_COUNT; + + return 0; +} + +/* + * Read does nothing for this driver + */ +static ssize_t perf_read(struct file *file, char *buf, size_t cnt, loff_t *ppos) +{ + return 0; +} + +/* + * write: + * + * This routine downloads the image to the chip. It must be + * called on the processor that the download should happen + * on. + */ +static ssize_t perf_write(struct file *file, const char *buf, size_t count, + loff_t *ppos) +{ + int err; + size_t image_size; + uint32_t image_type; + uint32_t interface_type; + uint32_t test; + + if (perf_processor_interface == ONYX_INTF) + image_size = PCXU_IMAGE_SIZE; + else if (perf_processor_interface == CUDA_INTF) + image_size = PCXW_IMAGE_SIZE; + else + return -EFAULT; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + if (count != sizeof(uint32_t)) + return -EIO; + + if ((err = copy_from_user(&image_type, buf, sizeof(uint32_t))) != 0) + return err; + + /* Get the interface type and test type */ + interface_type = (image_type >> 16) & 0xffff; + test = (image_type & 0xffff); + + /* Make sure everything makes sense */ + + /* First check the machine type is correct for + the requested image */ + if (((perf_processor_interface == CUDA_INTF) && + (interface_type != CUDA_INTF)) || + ((perf_processor_interface == ONYX_INTF) && + (interface_type != ONYX_INTF))) + return -EINVAL; + + /* Next check to make sure the requested image + is valid */ + if (((interface_type == CUDA_INTF) && + (test >= MAX_CUDA_IMAGES)) || + ((interface_type == ONYX_INTF) && + (test >= MAX_ONYX_IMAGES))) + return -EINVAL; + + /* Copy the image into the processor */ + if (interface_type == CUDA_INTF) + return perf_config(cuda_images[test]); + else + return perf_config(onyx_images[test]); + + return count; +} + +/* + * Patch the images that need to know the IVA addresses. + */ +static void perf_patch_images(void) +{ +#if 0 /* FIXME!! */ +/* + * NOTE: this routine is VERY specific to the current TLB image. + * If the image is changed, this routine might also need to be changed. + */ + extern void $i_itlb_miss_2_0(); + extern void $i_dtlb_miss_2_0(); + extern void PA2_0_iva(); + + /* + * We can only use the lower 32-bits, the upper 32-bits should be 0 + * anyway given this is in the kernel + */ + uint32_t itlb_addr = (uint32_t)&($i_itlb_miss_2_0); + uint32_t dtlb_addr = (uint32_t)&($i_dtlb_miss_2_0); + uint32_t IVAaddress = (uint32_t)&PA2_0_iva; + + if (perf_processor_interface == ONYX_INTF) { + /* clear last 2 bytes */ + onyx_images[TLBMISS][15] &= 0xffffff00; + /* set 2 bytes */ + onyx_images[TLBMISS][15] |= (0x000000ff&((dtlb_addr) >> 24)); + onyx_images[TLBMISS][16] = (dtlb_addr << 8)&0xffffff00; + onyx_images[TLBMISS][17] = itlb_addr; + + /* clear last 2 bytes */ + onyx_images[TLBHANDMISS][15] &= 0xffffff00; + /* set 2 bytes */ + onyx_images[TLBHANDMISS][15] |= (0x000000ff&((dtlb_addr) >> 24)); + onyx_images[TLBHANDMISS][16] = (dtlb_addr << 8)&0xffffff00; + onyx_images[TLBHANDMISS][17] = itlb_addr; + + /* clear last 2 bytes */ + onyx_images[BIG_CPI][15] &= 0xffffff00; + /* set 2 bytes */ + onyx_images[BIG_CPI][15] |= (0x000000ff&((dtlb_addr) >> 24)); + onyx_images[BIG_CPI][16] = (dtlb_addr << 8)&0xffffff00; + onyx_images[BIG_CPI][17] = itlb_addr; + + onyx_images[PANIC][15] &= 0xffffff00; /* clear last 2 bytes */ + onyx_images[PANIC][15] |= (0x000000ff&((IVAaddress) >> 24)); /* set 2 bytes */ + onyx_images[PANIC][16] = (IVAaddress << 8)&0xffffff00; + + + } else if (perf_processor_interface == CUDA_INTF) { + /* Cuda interface */ + cuda_images[TLBMISS][16] = + (cuda_images[TLBMISS][16]&0xffff0000) | + ((dtlb_addr >> 8)&0x0000ffff); + cuda_images[TLBMISS][17] = + ((dtlb_addr << 24)&0xff000000) | ((itlb_addr >> 16)&0x000000ff); + cuda_images[TLBMISS][18] = (itlb_addr << 16)&0xffff0000; + + cuda_images[TLBHANDMISS][16] = + (cuda_images[TLBHANDMISS][16]&0xffff0000) | + ((dtlb_addr >> 8)&0x0000ffff); + cuda_images[TLBHANDMISS][17] = + ((dtlb_addr << 24)&0xff000000) | ((itlb_addr >> 16)&0x000000ff); + cuda_images[TLBHANDMISS][18] = (itlb_addr << 16)&0xffff0000; + + cuda_images[BIG_CPI][16] = + (cuda_images[BIG_CPI][16]&0xffff0000) | + ((dtlb_addr >> 8)&0x0000ffff); + cuda_images[BIG_CPI][17] = + ((dtlb_addr << 24)&0xff000000) | ((itlb_addr >> 16)&0x000000ff); + cuda_images[BIG_CPI][18] = (itlb_addr << 16)&0xffff0000; + } else { + /* Unknown type */ + } +#endif +} + + +/* + * ioctl routine + * All routines effect the processor that they are executed on. Thus you + * must be running on the processor that you wish to change. + */ + +static int perf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + long error_start; + uint32_t raddr[4]; + + switch (cmd) { + + case PA_PERF_ON: + /* Start the counters */ + perf_start_counters(); + return 0; + + case PA_PERF_OFF: + error_start = perf_stop_counters(raddr); + if (error_start != 0) { + printk(KERN_ERR "perf_off: perf_stop_counters = %ld\n", error_start); + return -EFAULT; + } + + /* copy out the Counters */ + if (copy_to_user((void *)arg, raddr, + sizeof (raddr)) != 0) { + return -EFAULT; + } + return 0; + + case PA_PERF_VERSION: + /* Return the version # */ + return put_user(PERF_VERSION, (int *)arg); + + default: + break; + } + return -ENOTTY; +} + +static struct file_operations perf_fops = { + llseek: no_llseek, + read: perf_read, + write: perf_write, + ioctl: perf_ioctl, + open: perf_open, + release: perf_release +}; + +static struct miscdevice perf_dev = { + MISC_DYNAMIC_MINOR, + PA_PERF_DEV, + &perf_fops +}; + +/* + * Initialize the module + */ +static int __init perf_init(void) +{ + /* Determine correct processor interface to use */ + bitmask_array = perf_bitmasks; + + if (boot_cpu_data.cpu_type == pcxu || + boot_cpu_data.cpu_type == pcxu_) { + perf_processor_interface = ONYX_INTF; + } else if (boot_cpu_data.cpu_type == pcxw || + boot_cpu_data.cpu_type == pcxw_ || + boot_cpu_data.cpu_type == pcxw2) { + perf_processor_interface = CUDA_INTF; + if (boot_cpu_data.cpu_type == pcxw2) + bitmask_array = perf_bitmasks_piranha; + } else { + perf_processor_interface = UNKNOWN_INTF; + printk("Performance monitoring counters not supported on this processor\n"); + return -ENODEV; + } + + /* Patch the images to match the system */ + perf_patch_images(); + + spin_lock_init(&perf_lock); + misc_register(&perf_dev); + + /* TODO: this only lets us access the first cpu.. what to do for SMP? */ + cpu_device = cpu_data[0].dev; + printk("Performance monitoring counters enabled for %s\n", + cpu_data[0].dev->name); + + return 0; +} + +/* + * perf_start_counters(void) + * + * Start the counters. + */ +static void perf_start_counters(void) +{ + /* Enable performance monitor counters */ + perf_intrigue_enable_perf_counters(); +} + +/* + * perf_stop_counters + * + * Stop the performance counters and save counts + * in a per_processor array. + */ +static int perf_stop_counters(uint32_t *raddr) +{ + uint64_t userbuf[MAX_RDR_WORDS]; + + /* Disable performance counters */ + perf_intrigue_disable_perf_counters(); + + if (perf_processor_interface == ONYX_INTF) { + uint64_t tmp64; + /* + * Read the counters + */ + if (!perf_rdr_read_ubuf(16, userbuf)) + return -13; + + /* Counter0 is bits 1398 thru 1429 */ + tmp64 = (userbuf[21] << 22) & 0x00000000ffc00000; + tmp64 |= (userbuf[22] >> 42) & 0x00000000003fffff; + /* OR sticky0 (bit 1430) to counter0 bit 32 */ + tmp64 |= (userbuf[22] >> 10) & 0x0000000080000000; + raddr[0] = (uint32_t)tmp64; + + /* Counter1 is bits 1431 thru 1462 */ + tmp64 = (userbuf[22] >> 9) & 0x00000000ffffffff; + /* OR sticky1 (bit 1463) to counter1 bit 32 */ + tmp64 |= (userbuf[22] << 23) & 0x0000000080000000; + raddr[1] = (uint32_t)tmp64; + + /* Counter2 is bits 1464 thru 1495 */ + tmp64 = (userbuf[22] << 24) & 0x00000000ff000000; + tmp64 |= (userbuf[23] >> 40) & 0x0000000000ffffff; + /* OR sticky2 (bit 1496) to counter2 bit 32 */ + tmp64 |= (userbuf[23] >> 8) & 0x0000000080000000; + raddr[2] = (uint32_t)tmp64; + + /* Counter3 is bits 1497 thru 1528 */ + tmp64 = (userbuf[23] >> 7) & 0x00000000ffffffff; + /* OR sticky3 (bit 1529) to counter3 bit 32 */ + tmp64 |= (userbuf[23] << 25) & 0x0000000080000000; + raddr[3] = (uint32_t)tmp64; + + /* + * Zero out the counters + */ + + /* + * The counters and sticky-bits comprise the last 132 bits + * (1398 - 1529) of RDR16 on a U chip. We'll zero these + * out the easy way: zero out last 10 bits of dword 21, + * all of dword 22 and 58 bits (plus 6 don't care bits) of + * dword 23. + */ + userbuf[21] &= 0xfffffffffffffc00; /* 0 to last 10 bits */ + userbuf[22] = 0; + userbuf[23] = 0; + + /* + * Write back the zero'ed bytes + the image given + * the read was destructive. + */ + perf_rdr_write(16, userbuf); + } else { + + /* + * Read RDR-15 which contains the counters and sticky bits + */ + if (!perf_rdr_read_ubuf(15, userbuf)) { + return -13; + } + + /* + * Clear out the counters + */ + perf_rdr_clear(15); + + /* + * Copy the counters + */ + raddr[0] = (uint32_t)((userbuf[0] >> 32) & 0x00000000ffffffffUL); + raddr[1] = (uint32_t)(userbuf[0] & 0x00000000ffffffffUL); + raddr[2] = (uint32_t)((userbuf[1] >> 32) & 0x00000000ffffffffUL); + raddr[3] = (uint32_t)(userbuf[1] & 0x00000000ffffffffUL); + } + + return 0; +} + +/* + * perf_rdr_get_entry + * + * Retrieve a pointer to the description of what this + * RDR contains. + */ +static struct rdr_tbl_ent * perf_rdr_get_entry(uint32_t rdr_num) +{ + if (perf_processor_interface == ONYX_INTF) { + return &perf_rdr_tbl_U[rdr_num]; + } else { + return &perf_rdr_tbl_W[rdr_num]; + } +} + +/* + * perf_rdr_read_ubuf + * + * Read the RDR value into the buffer specified. + */ +static int perf_rdr_read_ubuf(uint32_t rdr_num, uint64_t *buffer) +{ + uint64_t data, data_mask = 0; + uint32_t width, xbits, i; + struct rdr_tbl_ent *tentry; + + tentry = perf_rdr_get_entry(rdr_num); + if ((width = tentry->width) == 0) + return 0; + + /* Clear out buffer */ + i = tentry->num_words; + while (i--) { + buffer[i] = 0; + } + + /* Check for bits an even number of 64 */ + if ((xbits = width & 0x03f) != 0) { + data_mask = 1; + data_mask <<= (64 - xbits); + data_mask--; + } + + /* Grab all of the data */ + i = tentry->num_words; + while (i--) { + + if (perf_processor_interface == ONYX_INTF) { + data = perf_rdr_shift_in_U(rdr_num, width); + } else { + data = perf_rdr_shift_in_W(rdr_num, width); + } + if (xbits) { + buffer[i] |= (data << (64 - xbits)); + if (i) { + buffer[i-1] |= ((data >> xbits) & data_mask); + } + } else { + buffer[i] = data; + } + } + + return 1; +} + +/* + * perf_rdr_clear + * + * Zero out the given RDR register + */ +static int perf_rdr_clear(uint32_t rdr_num) +{ + struct rdr_tbl_ent *tentry; + int32_t i; + + tentry = perf_rdr_get_entry(rdr_num); + + if (tentry->width == 0) { + return -1; + } + + i = tentry->num_words; + while (i--) { + if (perf_processor_interface == ONYX_INTF) { + perf_rdr_shift_out_U(rdr_num, 0UL); + } else { + perf_rdr_shift_out_W(rdr_num, 0UL); + } + } + + return 0; +} + + +/* + * perf_write_image + * + * Write the given image out to the processor + */ +static int perf_write_image(uint64_t *memaddr) +{ + uint64_t buffer[MAX_RDR_WORDS]; + uint64_t *bptr; + uint32_t dwords; + uint32_t *intrigue_rdr; + uint64_t *intrigue_bitmask, tmp64, proc_hpa, *ptr64; + struct rdr_tbl_ent *tentry; + int i; + + /* Clear out counters */ + if (perf_processor_interface == ONYX_INTF) { + + perf_rdr_clear(16); + + /* Toggle performance monitor */ + perf_intrigue_enable_perf_counters(); + perf_intrigue_disable_perf_counters(); + + intrigue_rdr = perf_rdrs_U; + } else { + perf_rdr_clear(15); + intrigue_rdr = perf_rdrs_W; + } + + /* Write all RDRs */ + while (*intrigue_rdr != -1) { + tentry = perf_rdr_get_entry(*intrigue_rdr); + perf_rdr_read_ubuf(*intrigue_rdr, buffer); + bptr = &buffer[0]; + dwords = tentry->num_words; + if (tentry->write_control) { + intrigue_bitmask = &bitmask_array[tentry->write_control >> 3]; + while (dwords--) { + tmp64 = *intrigue_bitmask & *memaddr++; + tmp64 |= (~(*intrigue_bitmask++)) & *bptr; + *bptr++ = tmp64; + } + } else { + while (dwords--) { + *bptr++ = *memaddr++; + } + } + + perf_rdr_write(*intrigue_rdr, buffer); + intrigue_rdr++; + } + + /* + * Now copy out the Runway stuff which is not in RDRs + */ + + if (cpu_device == NULL) + { + printk(KERN_ERR "write_image: cpu_device not yet initialized!\n"); + return -1; + } + + proc_hpa = cpu_device->hpa; + + /* Merge intrigue bits into Runway STATUS 0 */ + ptr64 = (uint64_t *)(proc_hpa + 0x10); /* Runway STATUS 0 */ + tmp64 = __raw_readq((u64 *)ptr64) & 0xffecffffffffffff; + __raw_writeq(tmp64 | (*memaddr++ & 0x0013000000000000), (u64 *)ptr64); + + /* Write RUNWAY DEBUG registers */ + ptr64 = (uint64_t *)(proc_hpa + 0x40); /* Runway DEBUG 0 */ + for (i = 0; i < 8; i++) { + __raw_writeq(*memaddr++, (u64 *)ptr64); + ptr64++; + } + + return 0; +} + +/* + * perf_rdr_write + * + * Write the given RDR register with the contents + * of the given buffer. + */ +static void perf_rdr_write(uint32_t rdr_num, uint64_t *buffer) +{ + struct rdr_tbl_ent *tentry; + int32_t i; + +printk("perf_rdr_write\n"); + tentry = perf_rdr_get_entry(rdr_num); + if (tentry->width == 0) { return; } + + i = tentry->num_words; + while (i--) { + if (perf_processor_interface == ONYX_INTF) { + perf_rdr_shift_out_U(rdr_num, buffer[i]); + } else { + perf_rdr_shift_out_W(rdr_num, buffer[i]); + } + } +printk("perf_rdr_write done\n"); +} + +module_init(perf_init); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/perf_images.h linux.19rc3-ac4/arch/parisc/kernel/perf_images.h --- linux.19rc3/arch/parisc/kernel/perf_images.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/perf_images.h 2002-07-29 13:58:36.000000000 +0100 @@ -0,0 +1,3122 @@ +#ifndef PERF_IMAGES_H +#define PERF_IMAGES_H + +/* Magic numbers taken without modification from HPUX stuff */ + +/* + * Imagine for use with the Onyx cpu interface + */ + +#define PCXU_IMAGE_SIZE 584 + +static uint32_t onyx_images[][PCXU_IMAGE_SIZE/sizeof(uint32_t)] = { +/* + * CPI: + * + * Counts the following: + * + * ctr0 : total cycles + * ctr1 : total cycles where nothing retired + * ctr2 : total instructions retired, including nullified + * ctr3 : total instructions retired, less nullified instructions + */ + { + 0x4c00c000, 0x00000000, 0x00060000, 0x00000000, + 0xe0e0e0e0, 0x004e0004, 0x07ffffff, 0xffc01380, + 0x0101ffff, 0xfffff104, 0xe000c07f, 0xfffffffc, + 0x01380010, 0x1fffffff, 0xff000000, 0x00000000, + 0x00000fff, 0xff00000f, 0xffff0000, 0x0fffff00, + 0x000fffff, 0x00000000, 0x00000000, 0x00ffffff, + 0xfffff000, 0x0000000f, 0xffffffff, 0xff000000, + 0x0000ffff, 0xfffffff0, 0x00000000, 0x0fffffff, + 0xffff0000, 0x00000000, 0x6fffffff, 0xffffffff, + 0xfff55fff, 0xffffffff, 0xffffffff, 0xf0000000, + 0xf0000030, 0x00003c00, 0x067f080c, 0x02019fc0, + 0x02804067, 0xf0009030, 0x19fc002c, 0x40067f08, + 0x0c12019f, 0xc0028440, 0x67f00091, 0x3019fc00, + 0x2fc007ff, 0xf800f001, 0xfffe003c, 0x007fff80, + 0x0f001fff, 0xe003c007, 0xfff800f0, 0x01fffe00, + 0x3c007fff, 0x800f001f, 0xffe003c0, 0x07fff800, + 0xf001fffe, 0x003c007f, 0xff800f00, 0x1fffe003, + 0xc007fff8, 0x00f001ff, 0xfe003c00, 0x7fff800f, + 0x001fffe0, 0x03c007ff, 0xf800f001, 0xfffe003c, + 0x007fff80, 0x0f001fff, 0xe003c007, 0xfff800f0, + 0x01fffe00, 0x3c007fff, 0x800f001f, 0xffe00000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x6fff0000, 0x00000000, 0x60000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000, + 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff, + 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, + 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff, + 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, + 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, + 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, + 0x00030000, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff}, + +/* Bus utilization image (bus_util) + * + * ctr0 : counts address valid cycles + * ctr1 : counts data valid cycles + * ctr2 : counts overflow from counter 0 + * ctr3 : counts overflow from counter 1 + */ + { + 0x0c01e000, 0x00000000, 0x00060000, 0x00000000, + 0xefefefef, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xff000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffff0000, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xf0000000, + 0x0000000c, 0x00003c00, 0x07930000, 0x0041e4c0, + 0x01002079, 0x3000800c, 0x1e4c0030, 0x00279300, + 0x010049e4, 0xc0014022, 0x79300090, 0x0c9e4c00, + 0x34004793, 0x00020051, 0xe4c00180, 0x24793000, + 0xa00d1e4c, 0x00380067, 0x93000300, 0x59e4c001, + 0xc0267930, 0x00b00d9e, 0x4c003fff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffc00, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffff0000, 0x00000000, 0xf0000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000, + 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff, + 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff, + 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, + 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, + 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, + 0x00100000, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff }, + +/* + * TLB counts (same as tlbStats image): + * + * Counts the following: + * + * ctr0: DTLB misses + * ctr1: ITLB misses + * ctr2: total cycles in the miss handlers + * ctr3: total cycles + */ + + { + 0x0c00c000, 0x00000000, 0x00060000, 0x00000000, + 0xe7e7e0e0, 0x004e0004, 0x07ffffff, 0xffc01380, + 0x0101ffff, 0xfffff104, 0xe000c06a, 0xafffc85c, + 0x01380010, 0x1fffffff, 0xff000000, 0x00000000, + 0x01b9e000, 0x0001b8c0, 0x00000000, 0x0fffff00, + 0x000fffff, 0x00000000, 0x00000000, 0x00400000, + 0x00001000, 0x00000004, 0x00000000, 0x01000000, + 0x0000ffff, 0xfffffff0, 0x00000000, 0x0fffffff, + 0xffff0000, 0x00000000, 0x6fffffff, 0xffffffff, + 0xfff55ff5, 0xffffffff, 0xffffffff, 0xf0000000, + 0xf0000000, 0x00003c00, 0x01ff0001, 0x08007fc2, + 0x02c1001f, 0xf0807100, 0x1bfc200c, 0x4806ff00, + 0x03f001ff, 0xfe003c00, 0x7fff800f, 0x001fffe0, + 0x03c007ff, 0xf800f001, 0xfffe003c, 0x007fff80, + 0x0f001fff, 0xe003c007, 0xfff800f0, 0x01fffe00, + 0x3c007fff, 0x800f001f, 0xffe003c0, 0x07fff800, + 0xf001fffe, 0x003c007f, 0xff800f00, 0x1fffe003, + 0xc007fff8, 0x00f001ff, 0xfe003c00, 0x7fff800f, + 0x001fffe0, 0x03c007ff, 0xf800f001, 0xfffe003c, + 0x007fff80, 0x0f001fff, 0xe003c007, 0xfff800f0, + 0x01fffe00, 0x3c007fff, 0x800f001f, 0xffe00000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x6fff0000, 0x00000000, 0x60000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000, + 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff, + 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, + 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff, + 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, + 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, + 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, + 0x00030000, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff }, + +/* tlbHandMiss + * + * ctr0: counts TLB misses + * ctr1: counts dmisses inside tlb miss handlers + * ctr2: counts cycles in the tlb miss handlers + * ctr3: counts overflows of ctr2 + */ +{ +0x1c00c000,00000000,0x00060000,00000000, +0xe7e7e0e0,0x004e0004,0x07ffffff,0xffc01380, +0x0101ffff,0xfffff104,0xe000c06a,0xafffc85c, +0x01380010,0x1fffffff,0xff000000,00000000, +0x01b9e000,0x0001b8c0,00000000,0x0fffff00, +0x000fffff,00000000,00000000,0x00400000, +0x00001000,0x00000004,00000000,0x01000000, +0x0000ffff,0xfffffff0,00000000,0x0fffffff, +0xffff0000,00000000,0x6fffffff,0xffffffff, +0xfff55ff5,0xffffffff,0xffffffff,0xf0000000, +0xf0000000,0x00003c00,0x01fd0000,0x08007f42, +0x0281001f,0xd080a100,0x19f42008,0x44067d08, +0x0612019f,0x400084c0,0x67d00060,0x0047f400, +0x042011fd,0x080b0404,0x7f4202c4,0x0167d080, +0x311059f4,0x201c4816,0x7d000313,0x059f4001, +0xfc007fff,0x800f001f,0xffe003c0,0x07fff800, +0xf001fffe,0x003c007f,0xff800f00,0x1fffe003, +0xc007fff8,0x00f001ff,0xfe003c00,0x7fff800f, +0x001fffe0,0x03c007ff,0xf800f001,0xfffe003c, +0x007fff80,0x0f001fff,0xe003c007,0xfff800f0, +0x01fffe00,0x3c007fff,0x800f001f,0xffe00000, +00000000,00000000,00000000,00000000, +0x6fff0000,00000000,0x60000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xfffffc00,00000000, +0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00030000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff}, + +/* branch_taken image (ptkn image) + * + * ctr0: overflow for ctr1 + * ctr1: predicted taken branches, actually taken + * ctr2: all predicted taken branches (nullfied or not) + * ctr3: overflow for ctr2 + */ + + { + 0xcc01e000, 0x00000000, 0x00060000, 0x00000000, + 0xa08080a0, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xff000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffff0000, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xf0000000, + 0xf0000000, 0x00003c00, 0x04f90000, 0x02013e40, + 0x0081004f, 0x90004060, 0x13e40018, 0x0024f900, + 0x0802093e, 0x40028102, 0x4f9000c0, 0x6093e400, + 0x380014f9, 0x00010205, 0x3e4000c1, 0x014f9000, + 0x506053e4, 0x001c0034, 0xf9000902, 0x0d3e4002, + 0xc1034f90, 0x00d060d3, 0xe4003fff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffc00, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffff0000, 0x00000000, 0xf0000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000, + 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff, + 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff, + 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, + 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, + 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, + 0x00030000, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff }, + +/* branch_nottaken (pntkn image) + * + * ctr0: overflow for ctr1 + * ctr1: counts branches predicted not-taken, but actually taken + * ctr2: counts all predictable branches predicted not-taken + * ctr3: overflow for ctr2 + */ +{ +0xcc01e000,00000000,0x00060000,00000000, +0xc0c0c0e0,0xffb1fffb,0xfff7ffff,0xffffffff, +0xffffffff,0xfffffffb,0x1fffbfff,0x7fffffff, +0xfcc7ffff,0xffdffffa,0x5f000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffff0000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xf0000000, +0xf0000060,0x00003c00,0x04f90000,0x02013e40, +0x0081004f,0x90004060,0x13e40018,0x0024f900, +0x0802093e,0x40028102,0x4f9000c0,0x6093e400, +0x380014f9,0x00010205,0x3e4000c1,0x014f9000, +0x506053e4,0x001c0034,0xf9000902,0x0d3e4002, +0xc1034f90,0x00d060d3,0xe4003fff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xfffffc00, +00000000,00000000,00000000,00000000, +0xffff0000,00000000,0xf0000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xfffffc00,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00030000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff}, + + +/* imiss image + * + * ctr0 : counts imiss aligned on 0 + * ctr1 : counts imiss aligned on 4 + * ctr2 : counts imiss aligned on 8 + * ctr3 : counts imiss aligned on C + */ + { + 0x0c00c000, 0x00000000, 0x00010000, 0x00000000, + 0xe7ebedee, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xff000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffff0000, 0x00000000, 0x6fffffff, 0xffffffff, + 0xfff55fff, 0xffffffff, 0xffffffff, 0xf0000000, + 0xf0000000, 0x00003c00, 0x007f0000, 0x01001fc0, + 0x00408007, 0xf0002030, 0x01fc000c, 0x10007f00, + 0x0405001f, 0xc0014180, 0x07f00060, 0x7001fc00, + 0x1c20007f, 0x00080900, 0x1fc00242, 0x8007f000, + 0xa0b001fc, 0x002c3000, 0x7f000c0d, 0x001fc003, + 0x438007f0, 0x00e0f001, 0xfc003fff, 0xfffff800, + 0xfffffffe, 0x003fffff, 0xff800fff, 0xffffe003, + 0xfffffff8, 0x00ffffff, 0xfe003fff, 0xffff800f, + 0xffffffe0, 0x03ffffff, 0xf800ffff, 0xfffe003f, + 0xffffff80, 0x0fffffff, 0xe003ffff, 0xfff800ff, + 0xfffffe00, 0x3fffffff, 0x800fffff, 0xffe00000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x6fff0000, 0x00000000, 0x60000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000, + 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff, + 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, + 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff, + 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, + 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, + 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, + 0x00030000, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff}, + +/* dmiss image + * + * ctr0 : counts cycles + * ctr1 : counts cycles where something retired + * ctr2 : counts dmisses + * ctr3 : (same as ctr2) + */ + { + 0x3c00c000, 0x00000000, 0x00060000, 0x00000000, + 0xe0e0e0e0, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xff000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffff0000, 0x00000000, 0x6fffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xf0000000, + 0xf0000000, 0x00003c04, 0x007f0009, 0x02001fc0, + 0x0280c007, 0xf000b040, 0x01fc0030, 0x14007f00, + 0x0d06001f, 0xc00381c0, 0x07f000f0, 0x8001fc00, + 0x2024007f, 0x00090a00, 0x1fc00282, 0xc007f000, + 0xb0c001fc, 0x00303400, 0x7f000d0e, 0x001fc003, + 0x83c007f0, 0x00f00001, 0xfc0023ff, 0xfffff800, + 0xfffffffe, 0x003fffff, 0xff800fff, 0xffffe003, + 0xfffffff8, 0x00ffffff, 0xfe003fff, 0xffff800f, + 0xffffffe0, 0x03ffffff, 0xf800ffff, 0xfffe003f, + 0xffffff80, 0x0fffffff, 0xe003ffff, 0xfff800ff, + 0xfffffe00, 0x3fffffff, 0x800fffff, 0xffe00000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x6fff0000, 0x00000000, 0x60000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000, + 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff, + 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, + 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff, + 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, + 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, + 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, + 0x00030000, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff }, + +/* dcmiss + * + * ctr0: counts store instructions retired + * ctr1: counts load instructions retired + * ctr2: counts dmisses + * ctr3: counts READ_SHARED_OR_PRIV and READ_PRIVATE transactions on Runway + */ +{ +0x2c90c000,00000000,0x00060000,00000000, +0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xff000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffff0000,00000000,0x6fffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xf0000000, +0xf00000e8,0x00003c02,0x00bf0001,0x02002fc0, +0x0080a00b,0xf0003040,0x02fc0010,0x1200bf00, +0x0506002f,0xc00181a0,0x0bf00070,0x8002fc00, +0x202200bf,0x00090a00,0x2fc00282,0xa00bf000, +0xb0c002fc,0x00303200,0xbf000d0e,0x002fc003, +0x83a00bf0,0x00ffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xfffffc00, +00000000,00000000,00000000,00000000, +0x6fff0000,00000000,0x60000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0x55555555,0xd5555555, +0x55555555,0x75555555,0x5e1ffc00,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00100000,00000000,0xf8000000,00000000, +00000000,00000000,0xf4000000,00000000, +0xffffffff,0xffffffff,0x00ffffff,0xffffffff, +00000000,00000000,0x00ffffff,0xffffffff, +0xffffffff,0xffffffff }, + +/* big_cpi + * + * ctr0: counts total cycles + * ctr1: counts overflows of ctr0 (for greater than 32-bit values) + * ctr2: counts overflows of ctr3 (for greater than 32-bit values) + * ctr3: counts unnullified instructions retired + */ +{ +0x0c00c000,00000000,0x00060000,00000000, +0xe7e7e0e0,0x004e0004,0x07ffffff,0xffc01380, +0x0101ffff,0xfffff104,0xe000c06a,0xafffc85c, +0x01380010,0x1fffffff,0xff000000,00000000, +0x01b9e000,0x0001b8c0,00000000,0x0fffff00, +0x000fffff,00000000,00000000,0x00400000, +0x00001000,0x00000004,00000000,0x01000000, +0x0000ffff,0xfffffff0,00000000,0x0fffffff, +0xffff0000,00000000,0x6fffffff,0xffffffff, +0xfff55ff5,0xffffffff,0xffffffff,0xf0000000, +0xf0000010,0x00003c00,0x01760008,0x00025d80, +0x02800417,0x6000c001,0x25d80038,0x04017600, +0x0901025d,0x8002c044,0x176000d0,0x1125d800, +0x3c2001f6,0x08080400,0x7d820203,0x001f6080, +0x804027d8,0x20282009,0xf6080a0c,0x027d8202, +0x81041f60,0x80c08107,0xd8203030,0x41f6080c, +0x04127d82,0x0382049f,0x6080e0c1,0x27d82038, +0x4006f608,0x081011bd,0x82030400,0xef6080a1, +0x013bd820,0x384806f6,0x00081211,0xbd800304, +0x80ef6000,0xa1213bd8,0x003bc007,0xfff800f0, +0x01fffe00,0x3c007fff,0x800f001f,0xffe00000, +00000000,00000000,00000000,00000000, +0x6fff0000,00000000,0x60000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xfffffc00,00000000, +0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00030000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff }, + +/* big_ls + * + * ctr0:counts the total number of cycles for which local_stall_A1 is asserted. + * ctr1: is the overflow for counter 0. + * ctr2: counts IFLUSH_AV + * ctr3: is the overflow for counter 2. + */ +{ +0x0c000000,00000000,0x00060000,00000000, +0xefefefef,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xff000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffff0000,00000000,0x0fffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xf0000000, +00000000,0x00029408,0x02f50002,0x0800bd40, +0x0202802f,0x5000a000,0x4bd40004,0x0812f500, +0x030804bd,0x40024281,0x2f5000b0,0x010bd400, +0x100842f5,0x00060810,0xbd400302,0x842f5000, +0xe0014bd4,0x00140852,0xf5000708,0x14bd4003, +0x42852f50,0x00ff001f,0xffe003c0,0x07fff800, +0xf001fffe,0x003c007f,0xff800f00,0x1fffe003, +0xc007fff8,0x00f001ff,0xfe003c00,0x7fff800f, +0x001fffe0,0x03c007ff,0xf800f001,0xfffe003c, +0x007fff80,0x0f001fff,0xe003c007,0xfff800f0, +0x01fffe00,0x3c007fff,0x800f001f,0xffe00000, +00000000,00000000,00000000,00000000, +0x0df70000,00000000,00000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xfffffc00,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00030000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff }, + +/* br_abort + * + * ctr0: counts BRAD_STALLH + * ctr1: counts ONE_QUAD + * ctr2: counts BR0_ABRT + * ctr3: counts BR1_ABRT + */ +{ +0x0c002000,00000000,0x00060000,00000000, +0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffa5ffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xff000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffff0000,00000000,0x1fffffff,0xffffffff, +0xfff7fff7,0xffffffff,0xffffffff,0xf0000000, +00000000,0x0003f800,0x007f000e,0x01001fc0, +0x03c08007,0xf000c030,0x01fc0034,0x10007f00, +0x0a05001f,0xc002c180,0x07f00080,0x7001fc00, +0x2420007f,0x00060900,0x1fc001c2,0x8007f000, +0x40b001fc,0x00143000,0x7f00020d,0x001fc000, +0xc38007f0,0x0000f001,0xfc0007ff,0xfffff800, +0xfffffffe,0x003fffff,0xff800fff,0xffffe003, +0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f, +0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f, +0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff, +0xfffffe00,0x3fffffff,0x800fffff,0xffe00000, +00000000,00000000,00000000,00000000, +0x1a250000,00000000,0x10000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xfffffc00,00000000, +0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00030000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff}, + +/* isnt + * + * ctr0: counts the total number of cycles for which iside_notrans is asserted + * ctr1: counts the number of times iside_notrans is asserted for 1-4 cycles + * ctr2: counts the number of times iside_notrans is asserted for 5-7 cycles + * ctr3: counts the number of times iside_notrans is asserted for > 7 cycles + */ +{ +0x0c018000,00000000,0x00060000,00000000, +0xefefefef,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xff000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffff0000,00000000,0xcfffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xf0000000, +00000000,0x00021c20,0x03ff0808,0x1800ffc4, +0x0204003f,0xf0004280,0x0ffc6020,0x8003ff00, +0x043800ff,0xc8020c00,0x3ff00044,0x800ffca0, +0x210003ff,0x00045800,0xffcc0214,0x003ff000, +0x26800ffc,0xe0218003,0xff000278,0x00ffd002, +0x1c003ff0,0x0028800f,0xfd002200,0x03ff0001, +0xf001fffe,0x003c007f,0xff800f00,0x1fffe003, +0xc007fff8,0x00f001ff,0xfe003c00,0x7fff800f, +0x001fffe0,0x03c007ff,0xf800f001,0xfffe003c, +0x007fff80,0x0f001fff,0xe003c007,0xfff800f0, +0x01fffe00,0x3c007fff,0x800f001f,0xffe00000, +00000000,00000000,00000000,00000000, +0xcdff0000,00000000,0xc0000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xfffffc00,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00030000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff}, + +/* quadrant + * + * ctr0: Total number of instructions in quadrant 0 + * ctr1: Total number of instructions in quadrant 1 + * ctr2: Total number of instructions in quadrant 2 + * ctr3: Total number of instructions in quadrant 3 + * Works only with 32-bit + */ + + { + 0x0c01e000, 0x00000000, 0x00060000, 0x00000000, + 0xe0e0e0e0, 0x004e0004, 0x07ffffff, 0xffc01380, + 0x0101ffff, 0xfffff004, 0xe000407f, 0xfffffffc, + 0x01380010, 0x1fffffff, 0xff000000, 0x00000000, + 0x00000fff, 0xff00000f, 0xffff0000, 0x0fffff00, + 0x000fffff, 0x00000000, 0x00000000, 0x00ffffff, + 0xffcff000, 0x0000040f, 0xfffffffc, 0xff000000, + 0x0080ffff, 0xffffcff0, 0x0000000c, 0x0fffffff, + 0xfcff0000, 0x00000000, 0xffffffff, 0xffffffff, + 0xfff55ff5, 0x5fffffff, 0xffffffff, 0xf0000000, + 0xf00000f0, 0x00003c00, 0x007f0000, 0x01001fc0, + 0x00408007, 0xf0002030, 0x01fc000c, 0x10007f00, + 0x0405001f, 0xc0014180, 0x07f00060, 0x7001fc00, + 0x1c20007f, 0x00080900, 0x1fc00242, 0x8007f000, + 0xa0b001fc, 0x002c3000, 0x7f000c0d, 0x001fc003, + 0x438007f0, 0x00e0f001, 0xfc003fff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffc00, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffff0000, 0x00000000, 0xf0000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000, + 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff, + 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff, + 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, + 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, + 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, + 0x00030000, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff}, + +/* rw_pdfet (READ_PRIV transactions) + * + * ctr0: counts address valid cycles + * ctr1: counts *all* data valid cycles + * ctr2: is the overflow from counter 0 + * ctr3: is the overflow from counter 1 + */ +{ +0x0c01e000,00000000,0x00060000,00000000, +0xefefefef,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xff000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffff0000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xf0000000, +0x0000000c,0x00003c00,0x07930000,0x0041e4c0, +0x01002079,0x3000800c,0x1e4c0030,0x00279300, +0x010049e4,0xc0014022,0x79300090,0x0c9e4c00, +0x34004793,0x00020051,0xe4c00180,0x24793000, +0xa00d1e4c,0x00380067,0x93000300,0x59e4c001, +0xc0267930,0x00b00d9e,0x4c003fff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xfffffc00, +00000000,00000000,00000000,00000000, +0xffff0000,00000000,0xf0000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xfffffc00,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00100000,00000000,0xf8000000,00000000, +00000000,00000000,00000000,00000000, +0xffffffff,0xffffffff,0x00ffffff,0xffffffff, +00000000,00000000,00000000,00000000, +0xffffffff,0xffffffff}, + +/* rw_wdfet (WRITEBACKS) + * + * ctr0: counts address valid cycles + * ctr1: counts *all* data valid cycles + * ctr2: is the overflow from counter 0 + * ctr3: is the overflow from counter 1 + */ +{ +0x0c01e000,00000000,0x00060000,00000000, +0xefefefef,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xff000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffff0000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xf0000000, +0x0000000c,0x00003c00,0x07930000,0x0041e4c0, +0x01002079,0x3000800c,0x1e4c0030,0x00279300, +0x010049e4,0xc0014022,0x79300090,0x0c9e4c00, +0x34004793,0x00020051,0xe4c00180,0x24793000, +0xa00d1e4c,0x00380067,0x93000300,0x59e4c001, +0xc0267930,0x00b00d9e,0x4c003fff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xfffffc00, +00000000,00000000,00000000,00000000, +0xffff0000,00000000,0xf0000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xfffffc00,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00100000,00000000,0x98000000,00000000, +00000000,00000000,00000000,00000000, +0xffffffff,0xffffffff,0x00ffffff,0xffffffff, +00000000,00000000,00000000,00000000, +0xffffffff,0xffffffff}, + +/* shlib_cpi + * + * ctr0: Total number of instructions in quad 0 + * ctr1: Total number of CPU clock cycles in quad 0 + * ctr2: total instructions without nullified + * ctr3: total number of CPU clock cycles + */ + { + 0x0c01e000, 0x00000000, 0x00060000, 0x00000000, + 0xe0e0e0e0, 0x004e0004, 0x07ffffff, 0xffc01380, + 0x0101ffff, 0xfffff004, 0xe000407f, 0xfffffffc, + 0x01380010, 0x1fffffff, 0xff000000, 0x00000000, + 0x00000fff, 0xff00000f, 0xffffffff, 0xffffffff, + 0xffffffff, 0x00000000, 0x00000000, 0x00ffffff, + 0xffcff000, 0x0000000f, 0xfffffffc, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffff0000, 0x00000000, 0xffffffff, 0xffffffff, + 0xfff77ff5, 0x7fffffff, 0xffffffff, 0xf0000000, + 0xf00000a0, 0x00003c00, 0x01ff0005, 0x08007fc0, + 0x03c1001f, 0xf08030c0, 0x07fc203c, 0x4001ff08, + 0x0118007f, 0xc003c500, 0x1ff08031, 0xc007fc00, + 0x3fffffff, 0xf800ffff, 0xfffe003f, 0xffffff80, + 0x0fffffff, 0xe003ffff, 0xfff800ff, 0xfffffe00, + 0x3fffffff, 0x800fffff, 0xffe003ff, 0xfffff800, + 0xfffffffe, 0x003fffff, 0xff800fff, 0xffffe003, + 0xfffffff8, 0x00ffffff, 0xfe003fff, 0xffff800f, + 0xffffffe0, 0x03ffffff, 0xf800ffff, 0xfffe003f, + 0xffffff80, 0x0fffffff, 0xe003ffff, 0xfff800ff, + 0xfffffe00, 0x3fffffff, 0x800fffff, 0xffe00000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffff0000, 0x00000000, 0xf0000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000, + 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff, + 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff, + 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, + 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, + 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, + 0x00030000, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff}, + + +/* addr_inv_abort_alu + * + * ctr0: counts ABORT_ALU0L + * ctr1: counts ABORT_ALU1L + * ctr2: counts ADDR0_INVALID + * ctr3: counts ADDR1_INVALID + */ + +{ +0x0c00c000,00000000,0x00060000,00000000, +0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffa5ffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xff000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffff0000,00000000,0x6fffffff,0xffffffff, +0xfff7fff7,0xffffffff,0xffffffff,0xf0000000, +00000000,0x0003f800,0x007f000d,0x01001fc0, +0x03008007,0xf000f030,0x01fc0038,0x10007f00, +0x0905001f,0xc0020180,0x07f000b0,0x7001fc00, +0x2820007f,0x00050900,0x1fc00102,0x8007f000, +0x70b001fc,0x00183000,0x7f00010d,0x001fc000, +0x038007f0,0x0030f001,0xfc000bff,0xfffff800, +0xfffffffe,0x003fffff,0xff800fff,0xffffe003, +0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f, +0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f, +0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff, +0xfffffe00,0x3fffffff,0x800fffff,0xffe00000, +00000000,00000000,00000000,00000000, +0x65380000,00000000,0x60000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xfffffc00,00000000, +0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00030000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff }, + + + +/* brad_stall + * + * ctr0: counts the total number of cycles for which brad_stall is asserted + * ctr1: counts the number of times brad_stall is asserted for 1-4 cycles + * ctr2: counts the number of times brad_stall is asserted for 5-7 cycles + * ctr3: counts the number of times brad_stall is asserted for > 7 cycles + */ +{ +0x0c002000,00000000,0x00060000,00000000, +0xefefefef,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xff000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffff0000,00000000,0x1fffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xf0000000, +00000000,0x00021c20,0x03ff0808,0x1800ffc4, +0x0204003f,0xf0004280,0x0ffc6020,0x8003ff00, +0x043800ff,0xc8020c00,0x3ff00044,0x800ffca0, +0x210003ff,0x00045800,0xffcc0214,0x003ff000, +0x26800ffc,0xe0218003,0xff000278,0x00ffd002, +0x1c003ff0,0x0028800f,0xfd002200,0x03ff0001, +0xf001fffe,0x003c007f,0xff800f00,0x1fffe003, +0xc007fff8,0x00f001ff,0xfe003c00,0x7fff800f, +0x001fffe0,0x03c007ff,0xf800f001,0xfffe003c, +0x007fff80,0x0f001fff,0xe003c007,0xfff800f0, +0x01fffe00,0x3c007fff,0x800f001f,0xffe00000, +00000000,00000000,00000000,00000000, +0x1bff0000,00000000,0x10000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xfffffc00,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00030000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff}, + +/* cntl_in_pipel + * + * ctr0: counts the total number of cycles for which cntl_in_pipel is asserted + * ctr1: counts the number of times cntl_in_pipel is asserted for 1-4 cycles + * ctr2: counts the number of times cntl_in_pipel is asserted for 5-7 cycles + * ctr3: counts the number of times cntl_in_pipel is asserted for > 7 cycles + */ +{ +0x0c006000,00000000,0x00060000,00000000, +0xefefefef,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xff000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffff0000,00000000,0x3fffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xf0000000, +00000000,0x00021c00,0x03ff0808,0x1000ffc4, +0x0206003f,0xf0004200,0x0ffc6020,0xa003ff00, +0x043000ff,0xc8020e00,0x3ff00044,0x000ffca0, +0x212003ff,0x00045000,0xffcc0216,0x003ff000, +0x26000ffc,0xe021a003,0xff000270,0x00ffd002, +0x1e003ff0,0x0028000f,0xfd002220,0x03ff0001, +0xf001fffe,0x003c007f,0xff800f00,0x1fffe003, +0xc007fff8,0x00f001ff,0xfe003c00,0x7fff800f, +0x001fffe0,0x03c007ff,0xf800f001,0xfffe003c, +0x007fff80,0x0f001fff,0xe003c007,0xfff800f0, +0x01fffe00,0x3c007fff,0x800f001f,0xffe00000, +00000000,00000000,00000000,00000000, +0x3fff0000,00000000,0x30000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xfffffc00,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00030000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff }, + + +/* dsnt_xfh + * + * ctr0: counts dside_notrans + * ctr1: counts xfhang + * ctr2: is the overflow for ctr0 + * ctr3: is the overflow for ctr1 + */ +{ +0x0c018000,00000000,0x00060000,00000000, +0xefefefef,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xff000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffff0000,00000000,0xcfffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xf0000000, +00000000,0x00030000,0x01f30000,0x00087cc0, +0x0040041f,0x30002001,0x87cc000c,0x1001f300, +0x0404087c,0xc0014104,0x1f300060,0x4187cc00, +0x1c2001f3,0x00080808,0x7cc00242,0x041f3000, +0xa08187cc,0x002c3001,0xf3000c0c,0x087cc003, +0x43041f30,0x00e0c187,0xcc003fc0,0x07fff800, +0xf001fffe,0x003c007f,0xff800f00,0x1fffe003, +0xc007fff8,0x00f001ff,0xfe003c00,0x7fff800f, +0x001fffe0,0x03c007ff,0xf800f001,0xfffe003c, +0x007fff80,0x0f001fff,0xe003c007,0xfff800f0, +0x01fffe00,0x3c007fff,0x800f001f,0xffe00000, +00000000,00000000,00000000,00000000, +0xcb3f0000,00000000,0xc0000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xfffffc00,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00030000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff }, + +/* fet_sig1 + * + * ctr0: counts ICORE_AV + * ctr1: counts ITRANS_STALL + * ctr2: counts SEL_PCQH + * ctr3: counts OUT_OF_CONTEXT + */ +{ +0x0c000000,00000000,0x00060000,00000000, +0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffa5ffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xff000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffff0000,00000000,0x0fffffff,0xffffffff, +0xfff7fff7,0xffffffff,0xffffffff,0xf0000000, +00000000,0x0003f800,0x007f000e,0x01001fc0, +0x03c08007,0xf000c030,0x01fc0034,0x10007f00, +0x0a05001f,0xc002c180,0x07f00080,0x7001fc00, +0x2420007f,0x00060900,0x1fc001c2,0x8007f000, +0x40b001fc,0x00143000,0x7f00020d,0x001fc000, +0xc38007f0,0x0000f001,0xfc0007ff,0xfffff800, +0xfffffffe,0x003fffff,0xff800fff,0xffffe003, +0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f, +0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f, +0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff, +0xfffffe00,0x3fffffff,0x800fffff,0xffe00000, +00000000,00000000,00000000,00000000, +0x07c10000,00000000,00000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xfffffc00,00000000, +0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00030000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff}, + +/* fet_sig2 + * + * ctr0: counts ICORE_AV + * ctr1: counts IRTN_AV + * ctr2: counts ADDRESS_INC + * ctr3: counts ADDRESS_DEC + */ +{ +0x0c000000,00000000,0x00060000,00000000, +0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffa5ffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xff000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffff0000,00000000,0x0fffffff,0xffffffff, +0xfff7fff7,0xffffffff,0xffffffff,0xf0000000, +00000000,0x0003f800,0x007f000e,0x01001fc0, +0x03c08007,0xf000c030,0x01fc0034,0x10007f00, +0x0a05001f,0xc002c180,0x07f00080,0x7001fc00, +0x2420007f,0x00060900,0x1fc001c2,0x8007f000, +0x40b001fc,0x00143000,0x7f00020d,0x001fc000, +0xc38007f0,0x0000f001,0xfc0007ff,0xfffff800, +0xfffffffe,0x003fffff,0xff800fff,0xffffe003, +0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f, +0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f, +0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff, +0xfffffe00,0x3fffffff,0x800fffff,0xffe00000, +00000000,00000000,00000000,00000000, +0x06930000,00000000,00000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xfffffc00,00000000, +0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00030000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff }, + +/* g7_1 + * + * ctr0: counts HIT_RETRY0 + * ctr1: counts HIT_RETRY1 + * ctr2: counts GO_TAG_E + * ctr3: counts GO_TAG_O + */ +{ +0x0c00e000,00000000,0x00060000,00000000, +0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffa5ffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xff000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffff0000,00000000,0x7fffffff,0xffffffff, +0xfff7fff7,0xffffffff,0xffffffff,0xf0000000, +00000000,0x0003f800,0x007f000e,0x01001fc0, +0x03c08007,0xf000c030,0x01fc0034,0x10007f00, +0x0a05001f,0xc002c180,0x07f00080,0x7001fc00, +0x2420007f,0x00060900,0x1fc001c2,0x8007f000, +0x40b001fc,0x00143000,0x7f00020d,0x001fc000, +0xc38007f0,0x0000f001,0xfc0007ff,0xfffff800, +0xfffffffe,0x003fffff,0xff800fff,0xffffe003, +0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f, +0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f, +0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff, +0xfffffe00,0x3fffffff,0x800fffff,0xffe00000, +00000000,00000000,00000000,00000000, +0x71c10000,00000000,0x70000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xfffffc00,00000000, +0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00030000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff }, + +/* g7_2 + * + * ctr0: counts HIT_DM0 + * ctr1: counts HIT_DM1 + * ctr2: counts GO_STORE_E + * ctr3: counts GO_STORE_O + */ +{ +0x0c00e000,00000000,0x00060000,00000000, +0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffa5ffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xff000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffff0000,00000000,0x7fffffff,0xffffffff, +0xfff7fff7,0xffffffff,0xffffffff,0xf0000000, +00000000,0x0003f800,0x007f000e,0x01001fc0, +0x03c08007,0xf000c030,0x01fc0034,0x10007f00, +0x0a05001f,0xc002c180,0x07f00080,0x7001fc00, +0x2420007f,0x00060900,0x1fc001c2,0x8007f000, +0x40b001fc,0x00143000,0x7f00020d,0x001fc000, +0xc38007f0,0x0000f001,0xfc0007ff,0xfffff800, +0xfffffffe,0x003fffff,0xff800fff,0xffffe003, +0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f, +0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f, +0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff, +0xfffffe00,0x3fffffff,0x800fffff,0xffe00000, +00000000,00000000,00000000,00000000, +0x72930000,00000000,0x70000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xfffffc00,00000000, +0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00030000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff }, + +/* g7_3 + * + * ctr0: counts HIT_DV0 + * ctr1: counts HIT_DV1 + * ctr2: counts STBYPT_E (load bypasses from store queue) + * ctr3: counts STBYPT_O + */ +{ +0x0c00e000,00000000,0x00060000,00000000, +0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffa5ffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xff000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffff0000,00000000,0x7fffffff,0xffffffff, +0xfff7fff7,0xffffffff,0xffffffff,0xf0000000, +00000000,0x0003f800,0x007f0002,0x01001fc0, +0x00c08007,0xf0000030,0x01fc0004,0x10007f00, +0x0605001f,0xc001c180,0x07f00040,0x7001fc00, +0x1420007f,0x000a0900,0x1fc002c2,0x8007f000, +0x80b001fc,0x00243000,0x7f000e0d,0x001fc003, +0xc38007f0,0x00c0f001,0xfc0037ff,0xfffff800, +0xfffffffe,0x003fffff,0xff800fff,0xffffe003, +0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f, +0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f, +0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff, +0xfffffe00,0x3fffffff,0x800fffff,0xffe00000, +00000000,00000000,00000000,00000000, +0x77250000,00000000,0x70000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xfffffc00,00000000, +0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00030000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff }, + +/* g7_4 + * + * ctr0: counts HIT_DIRTY0 + * ctr1: counts HIT_DIRTY1 + * ctr2: counts CA_BYP_E (quick launch) + * ctr3: counts CA_BYP_O + */ +{ +0x0c00e000,00000000,0x00060000,00000000, +0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffa5ffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xff000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffff0000,00000000,0x7fffffff,0xffffffff, +0xfff7fff7,0xffffffff,0xffffffff,0xf0000000, +00000000,0x0003f800,0x007f000e,0x01001fc0, +0x03c08007,0xf000c030,0x01fc0034,0x10007f00, +0x0a05001f,0xc002c180,0x07f00080,0x7001fc00, +0x2420007f,0x00060900,0x1fc001c2,0x8007f000, +0x40b001fc,0x00143000,0x7f00020d,0x001fc000, +0xc38007f0,0x0000f001,0xfc0007ff,0xfffff800, +0xfffffffe,0x003fffff,0xff800fff,0xffffe003, +0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f, +0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f, +0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff, +0xfffffe00,0x3fffffff,0x800fffff,0xffe00000, +00000000,00000000,00000000,00000000, +0x7bb70000,00000000,0x70000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xfffffc00,00000000, +0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00030000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff }, + + +/* mpb_labort + * + * ctr0: counts L_ABORT_ALU0L + * ctr1: counts L_ABORT_ALU1L + * ctr2: counts MPB0H + * ctr3: counts MPB1H + */ +{ +0x0c00c000,00000000,0x00060000,00000000, +0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffa5ffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xff000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffff0000,00000000,0x6fffffff,0xffffffff, +0xfff7fff7,0xffffffff,0xffffffff,0xf0000000, +00000000,0x0003f800,0x007f000e,0x01001fc0, +0x03c08007,0xf000c030,0x01fc0034,0x10007f00, +0x0a05001f,0xc002c180,0x07f00080,0x7001fc00, +0x2420007f,0x00060900,0x1fc001c2,0x8007f000, +0x40b001fc,0x00143000,0x7f00020d,0x001fc000, +0xc38007f0,0x0000f001,0xfc0007ff,0xfffff800, +0xfffffffe,0x003fffff,0xff800fff,0xffffe003, +0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f, +0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f, +0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff, +0xfffffe00,0x3fffffff,0x800fffff,0xffe00000, +00000000,00000000,00000000,00000000, +0x605c0000,00000000,0x60000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xfffffc00,00000000, +0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00030000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff }, + +/* panic + * + * ctr0: is the overflow for counter 1 + * ctr1: counts traps and RFI's + * ctr2: counts panic traps + * ctr3: is the overflow for counter 2 + */ +{ +0x0c002000,00000000,0x00060000,00000000, +0xe7efe0e0,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xfffffffc, +0x41380030,0x1aabfff2,0x17000000,00000000, +0x01b80000,0x3effffff,0xffffffff,0xffffffff, +0xffffffff,00000000,00000000,0x00400000, +0x00001fff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffff0000,00000000,0x1fffffff,0xffffffff, +0xfff7fff7,0xffffffff,0xffffffff,0xf0000000, +0xb0000000,0x00012c04,0x05790804,0x14013e44, +0x0008004f,0x90000040,0x15e46000,0xc0047920, +0x004a003e,0x40011080,0x0f900024,0x4003e460, +0x00c80479,0x00023301,0x1e400100,0x4157d080, +0x514053f4,0x40048014,0xfd000104,0x055f4600, +0x4c0147d2,0x0014a043,0xf4001508,0x10fd0003, +0x44043f46,0x004c8147,0xd0003330,0x51f40014, +0x04257908,0x0c14093e,0x44020802,0x4f900080, +0x4095e460,0x20c02479,0x20084a08,0x3e400310, +0x820f9000,0xa44083e4,0x6020c824,0x79000a33, +0x091e4003,0x3c007fff,0x800f001f,0xffe00000, +00000000,00000000,00000000,00000000, +0x10400000,00000000,0x10000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xfffffc00,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00030000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff }, + +/* rare_inst + * + * ctr0: counts sync and syncdma instructions + * ctr1: counts pxtlbx,x instructions + * ctr2: counts ixtlbt instructions + * ctr3: counts cycles + */ +{ +0x0c01e000,00000000,0x00060000,00000000, +0xe0e0e0e0,0x004e000c,0x000843fc,0x85c09380, +0x0121ebfd,0xff217124,0xe0004000,0x943fc85f, +0xffffffff,0xffffffff,0xff000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffff0000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xf0000000, +0xe00000e0,0x00003c00,0x007f0001,0x01001fc0, +0x00408007,0xf0003030,0x01fc000c,0x10007f00, +0x0505001f,0xc0014180,0x07f00070,0x7001fc00, +0x1c20007f,0x00090900,0x1fc00242,0x8007f000, +0xb0b001fc,0x002c3000,0x7f000d0d,0x001fc003, +0x438007f0,0x00f0f001,0xfc003fff,0xfffff800, +0xfffffffe,0x003fffff,0xff800fff,0xffffe003, +0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f, +0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f, +0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff, +0xfffffe00,0x3fffffff,0x800fffff,0xffe00000, +00000000,00000000,00000000,00000000, +0xffff0000,00000000,0xf0000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xfffffc00,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00030000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff }, + +/* rw_dfet (for D-cache misses and writebacks) + * + * ctr0: counts address valid cycles + * ctr1: counts *all* data valid cycles + * ctr2: is the overflow from counter 0 + * ctr3: is the overflow from counter 1 + */ +{ +0x0c01e000,00000000,0x00060000,00000000, +0xefefefef,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xff000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffff0000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xf0000000, +0x0000000c,0x00003c00,0x07930000,0x0041e4c0, +0x01002079,0x3000800c,0x1e4c0030,0x00279300, +0x010049e4,0xc0014022,0x79300090,0x0c9e4c00, +0x34004793,0x00020051,0xe4c00180,0x24793000, +0xa00d1e4c,0x00380067,0x93000300,0x59e4c001, +0xc0267930,0x00b00d9e,0x4c003fff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xfffffc00, +00000000,00000000,00000000,00000000, +0xffff0000,00000000,0xf0000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xfffffc00,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00100000,00000000,0xf0000000,00000000, +00000000,00000000,0x98000000,00000000, +0xffffffff,0xffffffff,0x0fffffff,0xffffffff, +00000000,00000000,0x00ffffff,0xffffffff, +0xffffffff,0xffffffff }, + +/* rw_ifet (I-cache misses -- actually dumb READ transactions) + * + * ctr0: counts address valid cycles + * ctr1: counts *all* data valid cycles + * ctr2: is the overflow from counter 0 + * ctr3: is the overflow from counter 1 + */ +{ +0x0c01e000,00000000,0x00060000,00000000, +0xefefefef,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xff000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffff0000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xf0000000, +0x0000000c,0x00003c00,0x07930000,0x0041e4c0, +0x01002079,0x3000800c,0x1e4c0030,0x00279300, +0x010049e4,0xc0014022,0x79300090,0x0c9e4c00, +0x34004793,0x00020051,0xe4c00180,0x24793000, +0xa00d1e4c,0x00380067,0x93000300,0x59e4c001, +0xc0267930,0x00b00d9e,0x4c003fff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xfffffc00, +00000000,00000000,00000000,00000000, +0xffff0000,00000000,0xf0000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xfffffc00,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00100000,00000000,0xd0000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0x00ffffff,0xffffffff, +0xffffffff,0xffffffff,00000000,00000000, +0xffffffff,0xffffffff }, + + +/* rw_sdfet (READ_SHARED_OR_PRIVATE transactions) + * + * ctr0: counts address valid cycles + * ctr1: counts *all* data valid cycles + * ctr2: is the overflow from counter 0 + * ctr3: is the overflow from counter 1 + */ +{ +0x0c01e000,00000000,0x00060000,00000000, +0xefefefef,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xff000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffff0000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xf0000000, +0x0000000c,0x00003c00,0x07930000,0x0041e4c0, +0x01002079,0x3000800c,0x1e4c0030,0x00279300, +0x010049e4,0xc0014022,0x79300090,0x0c9e4c00, +0x34004793,0x00020051,0xe4c00180,0x24793000, +0xa00d1e4c,0x00380067,0x93000300,0x59e4c001, +0xc0267930,0x00b00d9e,0x4c003fff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xfffffc00, +00000000,00000000,00000000,00000000, +0xffff0000,00000000,0xf0000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xfffffc00,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00100000,00000000,0xf4000000,00000000, +00000000,00000000,00000000,00000000, +0xffffffff,0xffffffff,0x00ffffff,0xffffffff, +00000000,00000000,00000000,00000000, +0xffffffff,0xffffffff }, + + +/* spec_ifet + * + * ICORE_AV fires for every request which the Instruction Fetch Unit sends + * to the Runway Interface Block. Hence, this counts all I-misses, speculative + * or not, but does *not* include I-cache prefetches, which are generated by + * RIB. + * IRTN_AV fires twice for every I-cache miss returning from RIB to the IFU. + * It will not fire if a second I-cache miss is issued from the IFU to RIB + * before the first returns. Therefore, if the IRTN_AV count is much less + * than 2x the ICORE_AV count, many speculative I-cache misses are occuring + * which are "discovered" to be incorrect fairly quickly. + * The ratio of I-cache miss transactions on Runway to the ICORE_AV count is + * a measure of the effectiveness of instruction prefetching. This ratio + * should be between 1 and 2. If it is close to 1, most prefetches are + * eventually called for by the IFU; if it is close to 2, almost no prefetches + * are useful and they are wasted bus traffic. + * + * ctr0: counts ICORE_AV + * ctr1: counts IRTN_AV + * ctr2: counts all non-coherent READ transactions on Runway. (TTYPE D0) + * This should be just I-cache miss and I-prefetch transactions. + * ctr3: counts total processor cycles + */ +{ +0x0c000000,00000000,0x00060000,00000000, +0xefefefef,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xff000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffff0000,00000000,0x0fffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xf0000000, +0x00000008,0x00030c00,0x01bf0001,0x00806fc0, +0x00c1001b,0xf0005048,0x06fc001c,0x2001bf00, +0x0908806f,0xc002c300,0x1bf000d0,0xc806fc00, +0x3fffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xfffffc00, +00000000,00000000,00000000,00000000, +0x06bf0000,00000000,00000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xfffffc00,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00110000,00000000,0xd0ffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0x00ffffff,0xffffffff, +0xffffffff,0xffffffff,00000000,00000000, +0xffffffff,0xffffffff }, + +/* st_cond0 + * + * ctr0: is the overflow for ctr1 + * ctr1: counts major ops 0C and 0E (fp ops, not fmac or fmpyadd) + * ctr2: counts B,L (including long and push) and GATE (including nullified), + * predicted not-taken + * ctr3: is the overflow for ctr2 + */ +{ +0x4c01e000,00000000,0x00060000,00000000, +0xe0e0c0e0,0xffffffff,0xffffffff,0xffc13380, +0x0101ffff,0xffa1f057,0xe000407f,0xdfffc87f, +0xffffffff,0xffffffff,0xff000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffff0000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xf0000000, +0xf0000060,0x00003c00,0x04f90000,0x02013e40, +0x0081004f,0x90004060,0x13e40018,0x0024f900, +0x0802093e,0x40028102,0x4f9000c0,0x6093e400, +0x380014f9,0x00010205,0x3e4000c1,0x014f9000, +0x506053e4,0x001c0034,0xf9000902,0x0d3e4002, +0xc1034f90,0x00d060d3,0xe4003fff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xfffffc00, +00000000,00000000,00000000,00000000, +0xffff0000,00000000,0xf0000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xfffffc00,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00030000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff }, + +/* st_cond1 + * + * ctr0: is the overflow for ctr1 + * ctr1: counts major ops 1x (most of the load/stores) + * ctr2: counts CMPB (dw) predicted not-taken + * ctr3: is the overflow for ctr2 + */ +{ +0x4c01e000,00000000,0x00060000,00000000, +0xe0e0c0e0,0xffffffff,0xffffffff,0xffc01b80, +0x0101ffff,0xffb7f03d,0xe000407f,0xffffc8ff, +0xffffffff,0xffffffff,0xff000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffff0000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xf0000000, +0xf0000060,0x00003c00,0x04f90000,0x02013e40, +0x0081004f,0x90004060,0x13e40018,0x0024f900, +0x0802093e,0x40028102,0x4f9000c0,0x6093e400, +0x380014f9,0x00010205,0x3e4000c1,0x014f9000, +0x506053e4,0x001c0034,0xf9000902,0x0d3e4002, +0xc1034f90,0x00d060d3,0xe4003fff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xfffffc00, +00000000,00000000,00000000,00000000, +0xffff0000,00000000,0xf0000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xfffffc00,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00030000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff }, + +/* st_cond2 + * + * ctr0: is the overflow for ctr1 + * ctr1: counts major op 03 + * ctr2: counts CMPIB (dw) predicted not taken. + * ctr3: is the overflow for ctr2 + */ +{ +0x4c01e000,00000000,0x00060000,00000000, +0xe0e0c0e0,0xffffffff,0xffffffff,0xffc09780, +0x0101ffff,0xff21f077,0xe000407f,0xffffc87f, +0xffffffff,0xffffffff,0xff000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffff0000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xf0000000, +0xf0000060,0x00003c00,0x04f90000,0x02013e40, +0x0081004f,0x90004060,0x13e40018,0x0024f900, +0x0802093e,0x40028102,0x4f9000c0,0x6093e400, +0x380014f9,0x00010205,0x3e4000c1,0x014f9000, +0x506053e4,0x001c0034,0xf9000902,0x0d3e4002, +0xc1034f90,0x00d060d3,0xe4003fff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xfffffc00, +00000000,00000000,00000000,00000000, +0xffff0000,00000000,0xf0000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xfffffc00,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00030000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff }, + +/* st_cond3 + * + * ctr0: is the overflow for ctr1 + * ctr1: counts major ops 06 & 26 + * ctr2: counts BB, BVB, MOVB, MOVIB (incl. nullified) predicted not-taken + * ctr3: is the overflow for ctr2 + */ +{ +0x4c01e000,00000000,0x00060000,00000000, +0xe0e0c0e0,0xffffffff,0xffffffff,0xffc03780, +0x0101ffff,0xff29f016,0xe000407f,0xffffe97f, +0xffffffff,0xffffffff,0xff000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffff0000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xf0000000, +0xf0000060,0x00003c00,0x04f90000,0x02013e40, +0x0081004f,0x90004060,0x13e40018,0x0024f900, +0x0802093e,0x40028102,0x4f9000c0,0x6093e400, +0x380014f9,0x00010205,0x3e4000c1,0x014f9000, +0x506053e4,0x001c0034,0xf9000902,0x0d3e4002, +0xc1034f90,0x00d060d3,0xe4003fff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xfffffc00, +00000000,00000000,00000000,00000000, +0xffff0000,00000000,0xf0000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xfffffc00,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00030000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff }, + +/* st_cond4 + * + * ctr0: is the overflow for ctr1 + * ctr1: counts major op 2E + * ctr2: counts CMPB, CMPIB, ADDB, ADDIB (incl. nullified) predicted not-taken + * ctr3: is the overflow for ctr2 + */ +{ +0x4c01e000,00000000,0x00060000,00000000, +0xe0e0c0e0,0xffffffff,0xffffffff,0xffc17780, +0x0101ffff,0xff21f014,0xe000407f,0xffffe9ff, +0xffffffff,0xffffffff,0xff000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffff0000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xf0000000, +0xf0000060,0x00003c00,0x04f90000,0x02013e40, +0x0081004f,0x90004060,0x13e40018,0x0024f900, +0x0802093e,0x40028102,0x4f9000c0,0x6093e400, +0x380014f9,0x00010205,0x3e4000c1,0x014f9000, +0x506053e4,0x001c0034,0xf9000902,0x0d3e4002, +0xc1034f90,0x00d060d3,0xe4003fff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xfffffc00, +00000000,00000000,00000000,00000000, +0xffff0000,00000000,0xf0000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xfffffc00,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00030000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff }, + +/* st_unpred0 + * + * ctr0: is the overflow for ctr1 + * ctr1: counts BE and BE,L + * ctr2: counts BE and BE,L including nullified + * ctr3: is the overflow for ctr2 + */ +{ +0x4c01e000,00000000,0x00060000,00000000, +0xe0c0c0e0,0xffffffff,0xffffffff,0xffdf5bbf, +0xffffffff,0xff25f7d6,0xefffffff,0xffffc97f, +0xffffffff,0xffffffff,0xff000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffff0000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xf0000000, +0xf0000060,0x00003c00,0x04f90000,0x02013e40, +0x0081004f,0x90004060,0x13e40018,0x0024f900, +0x0802093e,0x40028102,0x4f9000c0,0x6093e400, +0x380014f9,0x00010205,0x3e4000c1,0x014f9000, +0x506053e4,0x001c0034,0xf9000902,0x0d3e4002, +0xc1034f90,0x00d060d3,0xe4003fff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xfffffc00, +00000000,00000000,00000000,00000000, +0xffff0000,00000000,0xf0000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xfffffc00,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00030000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff }, + +/* st_unpred1 + * + * ctr0: is the overflow for ctr1 + * ctr1: counts BLR, BV, BVE, BVE,L + * ctr2: counts BLR, BV, BVE, BVE,L including nullified + * ctr3: is the overflow for ctr2 + */ +{ +0x4c01e000,00000000,0x00060000,00000000, +0xe0c0c0e0,0xffffffff,0xffffffff,0xffc15f80, +0x0501ff7f,0xff21f057,0xe001407f,0xdfffc87f, +0xffffffff,0xffffffff,0xff000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffff0000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xf0000000, +0xf0000060,0x00003c00,0x04f90000,0x02013e40, +0x0081004f,0x90004060,0x13e40018,0x0024f900, +0x0802093e,0x40028102,0x4f9000c0,0x6093e400, +0x380014f9,0x00010205,0x3e4000c1,0x014f9000, +0x506053e4,0x001c0034,0xf9000902,0x0d3e4002, +0xc1034f90,0x00d060d3,0xe4003fff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xfffffc00, +00000000,00000000,00000000,00000000, +0xffff0000,00000000,0xf0000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xfffffc00,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00030000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff }, + +/* unpred + * + * ctr0: counts non-nullified unpredictable branches + * ctr1: is the overflow for ctr0 + * ctr2: counts all unpredictable branches (nullified or not) + * ctr3: is the overflow for ctr2 + */ +{ +0xcc01e000,00000000,0x00060000,00000000, +0x20202020,0xff31ffff,0xfff7fffe,0x97ffcc7f, +0xfffffdff,0xffa5fff3,0x1fffffff,0x7fffe97f, +0xffffffff,0xffffffff,0xff000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffff0000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xf0000000, +0xf00000a0,0x00003c00,0x02f50000,0x0004bd40, +0x0040802f,0x50002020,0x4bd4000c,0x0042f500, +0x040014bd,0x40014084,0x2f500060,0x214bd400, +0x1c2002f5,0x00080804,0xbd400242,0x802f5000, +0xa0a04bd4,0x002c2042,0xf5000c08,0x14bd4003, +0x42842f50,0x00e0a14b,0xd4003fff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xfffffc00, +00000000,00000000,00000000,00000000, +0xffff0000,00000000,0xf0000000,00000000, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xfffffc00,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xfffffc00,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, +0xfdffffff,0xffffffff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0xffffffff,0xfffff9ff,0xfe000000,00000000, +0x00030000,00000000,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff,0xffffffff,0xffffffff, +0xffffffff,0xffffffff }, + + +/* go_store + * + * ctr0: Overflow for counter 2 + * ctr1: Overflow for counter 3 + * ctr2: count of GO_STORE_E signal + * ctr3: count of GO_STORE_O signal + */ + + { + 0x0c00e000, 0x00000000, 0x00060000, 0x00000000, + 0xe0e0e0e0, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffa5ffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xff000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffff0000, 0x00000000, 0x7fffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xf0000000, + 0x00000000, 0x0000c000, 0x067c0000, 0x01019f00, + 0x00408067, 0xc0002030, 0x19f0000c, 0x000e7c00, + 0x0401039f, 0x00014080, 0xe7c00060, 0x3039f000, + 0x1c00167c, 0x00080105, 0x9f000240, 0x8167c000, + 0xa03059f0, 0x002c001e, 0x7c000c01, 0x079f0003, + 0x4081e7c0, 0x00e03079, 0xf0003fc0, 0x07fff800, + 0xf001fffe, 0x003c007f, 0xff800f00, 0x1fffe003, + 0xc007fff8, 0x00f001ff, 0xfe003c00, 0x7fff800f, + 0x001fffe0, 0x03c007ff, 0xf800f001, 0xfffe003c, + 0x007fff80, 0x0f001fff, 0xe003c007, 0xfff800f0, + 0x01fffe00, 0x3c007fff, 0x800f001f, 0xffe00000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x70130000, 0x00000000, 0x70000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000, + 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff, + 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, + 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff, + 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, + 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, + 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, + 0x00030000, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff + }, + + +/* shlib_call + * + * ctr0: SharedLib call Depth1 + * ctr1: SharedLib call Depth2 + * ctr2: SharedLib call Depth3 + * ctr3: SharedLib call Depth>3 + */ + { + 0x0c01e000, 0x00000000, 0x00060000, 0x00000000, + 0xe0e0e0e0, 0xc76fa005, 0x07dd7e9c, 0x87115b80, + 0x01100200, 0x07200004, 0xe000407f, 0xfffffffc, + 0x01380010, 0x1fffffff, 0xff000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffff0000, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xf0000000, + 0xf0000000, 0x00003c20, 0x01ff0808, 0x04007fc0, + 0x0003001f, 0xf0000180, 0x07fc4010, 0x5001ff00, + 0x001c007f, 0xc2000a00, 0x1ff18022, 0x4007fc20, + 0x00b001ff, 0x10003800, 0x7fc8004d, 0x001ff100, + 0x03c007fc, 0x60012001, 0xff280144, 0x007fc600, + 0x13001ff2, 0x00058007, 0xfcc00550, 0x01ff2000, + 0x5c007fca, 0x001a001f, 0xf3801640, 0x07fca001, + 0xb001ff30, 0x0078007f, 0xd0005d00, 0x1ff30007, + 0xc007fce0, 0x022001ff, 0x48018400, 0x7fce0023, + 0x001ff400, 0x098007fd, 0x20065001, 0xff40009c, + 0x007fd200, 0x3fffffff, 0x800fffff, 0xffe00000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffff0000, 0x00000000, 0xf0000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000, + 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff, + 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff, + 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, + 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, + 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, + 0x00030000, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff + } +}; +#define PCXW_IMAGE_SIZE 576 + +static uint32_t cuda_images[][PCXW_IMAGE_SIZE/sizeof(uint32_t)] = { +/* + * CPI: FROM CPI.IDF (Image 0) + * + * Counts the following: + * + * ctr0 : total cycles + * ctr1 : total cycles where nothing retired + * ctr2 : total instructions retired, including nullified + * ctr3 : total instructions retired, less nullified instructions + */ + { + 0x4c00c000, 0x00000000, 0x00060000, 0x00000000, + 0xe0e0e0e0, 0x00001fff, 0xfc00007f, 0xfff00001, + 0xffffc000, 0x07ffff00, 0x07ffffff, 0x6007ffff, + 0xff0007ff, 0xffff0007, 0xffffff00, 0x00000000, + 0x60f00000, 0x0fffff00, 0x000fffff, 0x00000fff, + 0xff00000f, 0xffff0000, 0x00000000, 0x00ffffff, + 0xfffff000, 0x0000000f, 0xffffffff, 0xff000000, + 0x0000ffff, 0xfffffff0, 0x00000000, 0x0fffffff, + 0xffff0000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00270000, 0x00000055, + 0x0200000e, 0x4d300000, 0x00000000, 0x0ff00002, + 0x70000000, 0x00000020, 0x0000e400, 0x00000ff0, + 0x00000000, 0x00000000, 0x00000055, 0xffffff00, + 0x00000000, 0x0000ff00, 0x00000000, 0x0f000000, + 0x0000055f, 0xfffff000, 0x00000000, 0x000ff000, + 0x00000000, 0x00000000, 0x000055ff, 0xffff0000, + 0x00000000, 0x00ff0000, 0x00000000, 0xf0000000, + 0x000055ff, 0xffff0000, 0x00000000, 0x00ff0000, + 0x00000000, 0x00000000, 0x00055fff, 0xfff00000, + 0x00000000, 0x0ff00000, 0x00000030, 0x00000000, + 0x00157fff, 0xffc00000, 0x034c0000, 0x00000000, + 0x03fc0000, 0x00000000, 0x6fff0000, 0x00000000, + 0x60000000, 0x00000000, 0x00ffffff, 0xff3fffff, + 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000, + 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, + 0xfff7fbfc, 0x00000000, 0xffffafff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffafff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0x00030000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + }, + +/* Bus utilization image FROM BUS_UTIL.IDF (Image 1) + * + * ctr0 : counts address valid cycles + * ctr1 : counts data valid cycles + * ctr2 : counts overflow from counter 0 + * ctr3 : counts overflow from counter 1 + */ + { + 0x0c01e000, 0x00000000, 0x00060000, 0x00000000, + 0xefefefef, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000, + 0xf0ffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffff0000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00001b00, 0xaa000000, + 0x00000001, 0x30700000, 0x00055aaf, 0xf0000000, + 0x01b00000, 0x00000000, 0x00001037, 0x00000000, + 0x55aaff00, 0x00c00000, 0x1b55aa00, 0x00000000, + 0x0001fff0, 0xcfffff00, 0x00000000, 0x0f0fffff, + 0xffffffff, 0xffffffff, 0x30ffff0c, 0xfffff000, + 0x00000000, 0x00ffffff, 0xffffffff, 0xfffffff3, + 0x0ffff0cf, 0xffff0000, 0x00000000, 0x00ffffff, + 0xffffffff, 0xfffffff3, 0x0ffff0cf, 0xffff0000, + 0x00000000, 0x0fffffff, 0xffffffff, 0xffffff30, + 0xfff70000, 0x000055aa, 0xff000000, 0x000006d5, + 0x40000000, 0x00000000, 0x731c0000, 0x000156ab, + 0xfc000000, 0x00000000, 0xffff0000, 0x00000000, + 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff, + 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000, + 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, + 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0x00100000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + }, + +/* + * TLB counts: FROM TLBSTATS.IDF (Image 2) + * + * Counts the following: + * + * ctr0: DTLB misses + * ctr1: ITLB misses + * ctr2: total cycles in the miss handlers + * ctr3: total cycles + */ + + { + 0x0c00c000, 0x00000000, 0x00060000, 0x00000000, + 0xe7e7e0e0, 0x00001fff, 0xfc00007f, 0xfff00001, + 0xfff00000, 0x07ffff00, 0x07ffffff, 0x6007ffff, + 0xa00007ff, 0xffff0007, 0xffffff00, 0x00000000, + 0x603001c1, 0xe0000001, 0xc0c00000, 0x00000fff, + 0xff00000f, 0xffff0000, 0x00000000, 0x00400000, + 0x00001000, 0x00000004, 0x00000000, 0x01000000, + 0x0000ffff, 0xfffffff0, 0x00000000, 0x0fffffff, + 0xffff0000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00800000, 0x00153f7f, + 0x55000000, 0xaf800000, 0xc0000000, 0x0403f240, + 0x00000000, 0x00001010, 0x00004700, 0x00000ff0, + 0x00000000, 0x00000000, 0x00000055, 0xffffff00, + 0x00000000, 0x0000ff00, 0x00000000, 0x0f000000, + 0x0000055f, 0xfffff000, 0x00000000, 0x000ff000, + 0x00000000, 0x00000000, 0x000055ff, 0xffff0000, + 0x00000000, 0x00ff0000, 0x00000000, 0xf0000000, + 0x000055ff, 0xffff0000, 0x00000000, 0x00ff0000, + 0x00000000, 0x00000000, 0x00055fff, 0xfff00000, + 0x00000000, 0x0ff00000, 0x00000000, 0x00000000, + 0x00157fff, 0xffc00000, 0x00000000, 0x3fc00000, + 0x00040000, 0x00000000, 0x6fff0000, 0x00000000, + 0x60000000, 0x00000000, 0x00ffffff, 0xff3fffff, + 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000, + 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, + 0xfff7fbfc, 0x00000000, 0xffffafff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffafff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0x00030000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + }, + +/* tlbhandler FROM tlbHandMiss.idf (Image 3) + * + * ctr0: TLB misses + * ctr1: dmisses inside the TLB miss handler + * ctr2: cycles in the TLB miss handler + * ctr3: overflow of ctr2 + */ + { + 0x1c00c000, 0x00000000, 0x00060000, 0x00000000, + 0xe7e7e0e0, 0x00001fff, 0xfc00007f, 0xfff00001, + 0xfff00000, 0x07ffff00, 0x07ffffff, 0x6007ffff, + 0xa00007ff, 0xffff0007, 0xffffff00, 0x00000000, + 0x603001c1, 0xe0000001, 0xc0c00000, 0x00000fff, + 0xff00000f, 0xffff0000, 0x00000000, 0x00400000, + 0x00001000, 0x00000004, 0x00000000, 0x01000000, + 0x0000ffff, 0xfffffff0, 0x00000000, 0x0fffffff, + 0xffff0000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x006c0000, 0x01000054, + 0x02000002, 0xc3200000, 0xc00aa000, 0x0c03f240, + 0x00000000, 0x00001010, 0x000044f4, 0x00000c00, + 0xaa0000f0, 0x0f0000b0, 0x00005005, 0x0f5f0000, + 0x0001f000, 0x0000ff00, 0x00000000, 0x0f000000, + 0x0000055f, 0xfffff000, 0x00000000, 0x000ff000, + 0x00000000, 0x00000000, 0x000055ff, 0xffff0000, + 0x00000000, 0x00ff0000, 0x00000000, 0xf0000000, + 0x000055ff, 0xffff0000, 0x00000000, 0x00ff0000, + 0x00000000, 0x00000000, 0x00055fff, 0xfff00000, + 0x00000000, 0x0ff00a00, 0x000f0000, 0x24004000, + 0x15400001, 0x40c00003, 0x3da00000, 0x0002a800, + 0x00ff0000, 0x00000000, 0x6fff0000, 0x00000000, + 0x60000000, 0x00000000, 0x00ffffff, 0xff3fffff, + 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000, + 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, + 0xfff7fbfc, 0x00000000, 0xffffafff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffafff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0x00030000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + }, + +/* branch_taken image FROM PTKN.IDF (Image 4) + * + * ctr0: mispredicted branches + * ctr1: predicted taken branches, actually taken + * ctr2: predicted taken branches (includes nullfied) + * ctr3: all branches + */ + + { + 0xcc01e000, 0x00000000, 0x00000000, 0x00000000, + 0xa08080a0, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xfffffeff, 0xfffeffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000, + 0xf4ffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffff0000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xd22d0000, 0x00000000, + 0x0000000b, 0x46000000, 0x00000000, 0x0ffff900, + 0x90000000, 0x00000000, 0x0000907e, 0x00000000, + 0x000000ff, 0xff00bfdf, 0x03030303, 0x03030000, + 0x000dbfff, 0xffffff00, 0x00000000, 0x0f0fffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000, + 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000, + 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff, + 0xffff5555, 0x55500000, 0x003f3ff0, 0x2766c000, + 0x00000000, 0x00000002, 0x67840000, 0x00000000, + 0x03fffc00, 0x00000000, 0xffff0000, 0x00000000, + 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff, + 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000, + 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, + 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0x00030000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + }, + +/* branch_nottaken FROM PNTKN.IDF (Image 5) + * + * ctr0: mispredicted branches + * ctr1: branches predicted not-taken, but actually taken + * ctr2: branches predicted not-taken (includes nullified) + * ctr3: all branches + */ + { + 0xcc01e000, 0x00000000, 0x00000000, 0x00000000, + 0xe0c0c0e0, 0xffffffff, 0xffffffff, 0xffefffff, + 0xffffbfff, 0xfffffeff, 0xfffeffff, 0xfffffeff, + 0xfffffffe, 0xffffffff, 0xffffff00, 0x00000000, + 0xf4ffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffff0000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xd22d0000, 0x00000000, + 0x0000000b, 0x46000000, 0x00000000, 0x0ffff900, + 0x90000000, 0x00000000, 0x0000907e, 0x00000000, + 0x000000ff, 0xff00bfdf, 0x03030303, 0x03030000, + 0x000dbfff, 0xffffff00, 0x00000000, 0x0f0fffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000, + 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000, + 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff, + 0xffff5555, 0x55500000, 0x003f3ff0, 0x2766c000, + 0x00000000, 0x00000002, 0x67840000, 0x00000000, + 0x03fffc00, 0x00000000, 0xffff0000, 0x00000000, + 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff, + 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000, + 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, + 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0x00030000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + }, + +/* IMISS image (Image 6) + * + * ctr0 : icache misses for retired instructions + * ctr1 : total cycles + * ctr2 : dcache misses for retired instructions + * ctr3 : number of retired instructions + */ + { + 0x2801e000, 0x00000000, 0x00010000, 0x00000000, + 0x00001000, 0xffffffff, 0xffffffff, 0xfff00fff, + 0xfffa3fff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000, + 0xf0ffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffff0000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xf2fdf0f0, 0xf0f0f0f0, + 0xffffffff, 0xf6c00000, 0x00000000, 0x0ff55800, + 0x90000000, 0x00000000, 0x0000b0ff, 0xfffffff0, + 0x00000003, 0x0100bfff, 0x3f3f3f3f, 0x3f3f5555, + 0x555fffff, 0xffffff00, 0x00000000, 0x000fffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000, + 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000, + 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xfff00000, 0x000301b0, 0x2fefcfcf, + 0xcfcfcfcf, 0xd5555557, 0xf7b40000, 0x00000000, + 0x03c14000, 0x00000000, 0xffff0000, 0x00000000, + 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff, + 0xffffffff, 0xffcfffff, 0xfff6fb7c, 0x00000000, + 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, + 0xfff6fb7c, 0x00000000, 0xffff0fff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffff0fff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0x00130000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + }, + +/* DMISS image (Image 7) + * + * ctr0 : icache misses for retired instructions + * ctr1 : total cycles + * ctr2 : dcache misses for retired instructions + * ctr3 : number of retired instructions + */ + { + 0x2801e000, 0x00000000, 0x00010000, 0x00000000, + 0x00001000, 0xffffffff, 0xffffffff, 0xfff00fff, + 0xfffa3fff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000, + 0xf0ffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffff0000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xf2fdf0f0, 0xf0f0f0f0, + 0xffffffff, 0xf6c00000, 0x00000000, 0x0ff55800, + 0x90000000, 0x00000000, 0x0000b0ff, 0xfffffff0, + 0x00000003, 0x0100bfff, 0x3f3f3f3f, 0x3f3f5555, + 0x555fffff, 0xffffff00, 0x00000000, 0x000fffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000, + 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000, + 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xfff00000, 0x000301b0, 0x2fefcfcf, + 0xcfcfcfcf, 0xd5555557, 0xf7b40000, 0x00000000, + 0x03c14000, 0x00000000, 0xffff0000, 0x00000000, + 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff, + 0xffffffff, 0xffcfffff, 0xfff6fb7c, 0x00000000, + 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, + 0xfff6fb7c, 0x00000000, 0xffff0fff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffff0fff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0x00130000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + }, + +/* dmiss_access image FROM DMISS_RATIO.IDF (Image 8) + * + * ctr0 : all loads and stores that retire (even lines) + * ctr1 : all loads and stores that retire (odd lines) + * ctr2 : dcache misses of retired loads/stores + * ctr3 : all READ_PRIV and READ_SHAR_OR_PRIV on Runway + * (Speculative and Non-Speculative) + */ + { + 0x2d81e000, 0x00000000, 0x00000000, 0x00000000, + 0x10101010, 0x00ffffff, 0xa003ffff, 0xfe800fff, + 0xfffa003f, 0xffffe8ff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000, + 0xf0ffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffff0000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xd2280a00, 0x00000000, + 0x0000000b, 0x46000000, 0x00000005, 0x555ff900, + 0x80200000, 0x00000000, 0x0000907e, 0x00000000, + 0x00005555, 0xff80bf8b, 0xab030303, 0x03030000, + 0x000dbfff, 0xffffff00, 0x00000000, 0x000fffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000, + 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000, + 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff, + 0xffff5555, 0x55500000, 0x15153fe0, 0x27628880, + 0x00000000, 0x00000002, 0x67840000, 0x00000001, + 0x5557fc00, 0x00000000, 0xffff0000, 0x00000000, + 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff, + 0xffffffff, 0xffcfffff, 0xfff6fb7c, 0x00000000, + 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, + 0xfff6fb7c, 0x00000000, 0xffff0fff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffff0fff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0x00110000, 0x00000000, + 0xf4ffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xf8ffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x00ffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x00ffffff, 0xffffffff, 0xffffffff, 0xffffffff, + }, + + +/* big_cpi image (Image 9) + * + * ctr0 : Total number of CPU clock cycles. + * ctr1 : Unused + * ctr2 : Unused + * ctr3 : Total number of Non-Nullified instructions retired. + */ + { + 0x0c00c000, 0x00000000, 0x00060000, 0x00000000, + 0xe7e7e0e0, 0x00001fff, 0xfc00007f, 0xfff00001, + 0xfff00000, 0x07ffff00, 0x07ffffff, 0x6007ffff, + 0xa00007ff, 0xffff0007, 0xffffff00, 0x00000000, + 0x603001c1, 0xe0000001, 0xc0c00000, 0x00000fff, + 0xff00000f, 0xffff0000, 0x00000000, 0x00400000, + 0x00001000, 0x00000004, 0x00000000, 0x01000000, + 0x0000ffff, 0xfffffff0, 0x00000000, 0x0fffffff, + 0xffff0000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00550005, 0x00220000, + 0x0000000c, 0x71f00000, 0x00f00aa0, 0x0aaff000, + 0x00005002, 0x20000000, 0x0000c413, 0x00000c0f, + 0x00aa0000, 0xff00b600, 0x000500a0, 0x00000300, + 0x000cc3f0, 0x0000c0f0, 0x0aa0000f, 0xff000000, + 0x011000a0, 0x05503000, 0x00d03700, 0x00000f00, + 0xaa005500, 0x00000000, 0x000055ff, 0xffff0000, + 0x00000000, 0x00ff0000, 0x00000000, 0xf000aa00, + 0x11000a00, 0x55000000, 0x0d037000, 0x00c0f00a, + 0xa0055000, 0x0db00005, 0x5002a000, 0x00300000, + 0xf40f0000, 0x0c0f00aa, 0x0000ff10, 0x27400000, + 0x00008000, 0x00c00003, 0x037c0000, 0x003c02a8, + 0x02abfc00, 0x00000000, 0x6fff0000, 0x00000000, + 0x60000000, 0x00000000, 0x00ffffff, 0xff3fffff, + 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000, + 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, + 0xfff7fbfc, 0x00000000, 0xffffafff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffafff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0x00030000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + }, + +/* big_ls image (Image 10) + * + * ctr0 : Total number of CPU clock cycles during which local_stall_A1 is asserted + * ctr1 : Overflow of Counter 0 + * ctr2 : Total number of IFLUSH_AV + * ctr3 : Overflow of Counter 2 + */ + { + 0x0c000000, 0x00000000, 0x00060000, 0x00000000, + 0xefefefef, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000, + 0x00ffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffff0000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x28880001, 0x54000000, + 0x00000004, 0xb6200000, 0x000aaaa0, 0x05555288, + 0x80000010, 0x00000000, 0x0000486e, 0x00000000, + 0xaaaa0055, 0x55002888, 0x00545401, 0x03030000, + 0x0007b000, 0x0000ff00, 0x00000000, 0x05000000, + 0x0000055f, 0xfffff000, 0x00000000, 0x000ff000, + 0x00000000, 0x00000000, 0x000055ff, 0xffff0000, + 0x00000000, 0x00ff0000, 0x00000000, 0x00000000, + 0x000055ff, 0xffff0000, 0x00000000, 0x00ff0000, + 0x00000000, 0xa0000000, 0x00055fff, 0xfff00000, + 0x00aa0000, 0x05502a2a, 0x00151500, 0x0a220015, + 0x40400000, 0x00000001, 0xe2980000, 0x0002aaa8, + 0x01555400, 0x00000000, 0x0df70000, 0x00000000, + 0x00000000, 0x00000000, 0x00ffffff, 0xff3fffff, + 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000, + 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, + 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0x00030000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + }, + +/* br_abort image (Image 12) + * + * ctr0 : Total number of BRAD_STALLH + * ctr1 : Total number of ONE_QUAD + * ctr2 : Total number of BR0_ABRT + * ctr3 : Total number of BR1_ABRT + */ + + { + 0x0c002000, 0x00000000, 0x00060000, 0x00000000, + 0xe0e0e0e0, 0xffffffff, 0xffffffff, 0xff0fffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000, + 0x1077ffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffff0000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x551b0000, 0x00000000, + 0x0000000c, 0xd4f00000, 0x00000000, 0x0ffff001, + 0xb0000000, 0x00000000, 0x0000fd4c, 0x00000000, + 0x000000ff, 0xff00ff1b, 0x00000000, 0x00000000, + 0x0000d000, 0x0000ff00, 0x00000000, 0x0e0fffff, + 0xffffffff, 0xfffff000, 0x00000000, 0x000ff000, + 0x00000000, 0x00ffffff, 0xffffffff, 0xffff0000, + 0x00000000, 0x00ff0000, 0x00000000, 0x00ffffff, + 0xffffffff, 0xffff0000, 0x00000000, 0x00ff0000, + 0x00000000, 0xffffffff, 0xffffffff, 0xfff00000, + 0x00400000, 0x00000000, 0x00ffff00, 0x2a86c000, + 0x00000000, 0x00000000, 0xf50c0000, 0x00000000, + 0x03fffc00, 0x00000000, 0x1a250000, 0x00000000, + 0x10000000, 0x00000000, 0x00ffffff, 0xff3fffff, + 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000, + 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, + 0xfff7fbfc, 0x00000000, 0xffffafff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffafff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0x00030000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + }, + + +/* isnt image (Image 13) + * + * ctr0 : Total number of cycles for which iside_notrans is asserted. + * ctr1 : Total number of times iside_notrans is asserted for 1-4 cycles. + * ctr2 : Total number of times iside_notrans is asserted for 5-7 cycles. + * ctr3 : Total number of times iside_notrans is asserted for > 7 cycles. + */ + + { + 0x0c018000, 0x00000000, 0x00060000, 0x00000000, + 0xefefefef, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000, + 0xc0ffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffff0000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x22000000, 0x000001bc, + 0x10000006, 0x00900000, 0x50000000, 0x00055a20, + 0x00000000, 0x00016060, 0x0000c021, 0x00000540, + 0x00000000, 0x55002200, 0x00000000, 0x56bc4000, + 0x00048000, 0x0000ff00, 0x00000000, 0x17000000, + 0x0000055f, 0xfffff000, 0x00000000, 0x000ff000, + 0x00000000, 0x00000000, 0x000055ff, 0xffff0000, + 0x00000000, 0x00ff0000, 0x00000000, 0x00000000, + 0x000055ff, 0xffff0000, 0x00000000, 0x00ff0000, + 0x00000000, 0x80000000, 0x00015bf3, 0xf5500000, + 0x02210000, 0x00100000, 0x00005500, 0x08800000, + 0x00001545, 0x85000001, 0x80240000, 0x11000000, + 0x00015400, 0x00000000, 0xcdff0000, 0x00000000, + 0xc0000000, 0x00000000, 0x00ffffff, 0xff3fffff, + 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000, + 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, + 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0x00030000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + }, + +/* quadrant image (image 14) + * + * ctr0 : Total number of instructions in quadrant 0. + * ctr1 : Total number of instructions in quadrant 1. + * ctr2 : Total number of instructions in quadrant 2. + * ctr3 : Total number of instructions in quadrant 3. + * + * Only works for 32-bit applications. + */ + + { + 0x0c01e000, 0x00000000, 0x00060000, 0x00000000, + 0xe0e0e0e0, 0x00001fff, 0xfc00007f, 0xfff00001, + 0xffffc000, 0x07ffff00, 0x07ffffff, 0x0007ffff, + 0xff0007ff, 0xffff0007, 0xffffff00, 0x00000000, + 0xf0000000, 0x0fffff00, 0x000fffff, 0x00000fff, + 0xff00000f, 0xffff0000, 0x00000000, 0x00ffffff, + 0xffcff000, 0x0000040f, 0xfffffffc, 0xff000000, + 0x0080ffff, 0xffffcff0, 0x0000000c, 0x0fffffff, + 0xfcff0000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x551b0000, 0x00000000, + 0x00000003, 0x17000000, 0x00000000, 0x0ffff001, + 0xb0000000, 0x00000000, 0x00000173, 0x00000000, + 0x000000ff, 0xff00ff1b, 0x00000000, 0x00000000, + 0x000f1ff0, 0xcfffff00, 0x00000000, 0x0f0fffff, + 0xffffffff, 0xffffffff, 0x30ffff0c, 0xfffff000, + 0x00000000, 0x00ffffff, 0xffffffff, 0xfffffff3, + 0x0ffff0cf, 0xffff0000, 0x00000000, 0xf0ffffff, + 0xffffffff, 0xfffffff3, 0x0ffff0cf, 0xffff0000, + 0x00000000, 0x0fffffff, 0xffffffff, 0xffffff30, + 0xff7f0000, 0x00000000, 0x00fffff0, 0x2a86c000, + 0x00000000, 0x00000003, 0x05f00000, 0x00000000, + 0x03fffc00, 0x00000000, 0xffff0000, 0x00000000, + 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff, + 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000, + 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, + 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0x00030000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + }, + +/* rw_pdfet image (Image 15) + * + * ctr0 : Total of all READ_PRIV address valid cycles. + * ctr1 : Total of all READ_PRIV data valid cycles. + * ctr2 : Overflow of Counter 0. + * ctr3 : Overflow of Counter 1. + */ + + { + 0x0c01e000, 0x00000000, 0x00060000, 0x00000000, + 0xefefefef, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000, + 0xf0ffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffff0000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00001b00, 0xaa000000, + 0x00000001, 0x30700000, 0x00055aaf, 0xf0000000, + 0x01b00000, 0x00000000, 0x00001037, 0x00000000, + 0x55aaff00, 0x00c00000, 0x1b55aa00, 0x00000000, + 0x0001fff0, 0xcfffff00, 0x00000000, 0x0f0fffff, + 0xffffffff, 0xffffffff, 0x30ffff0c, 0xfffff000, + 0x00000000, 0x00ffffff, 0xffffffff, 0xfffffff3, + 0x0ffff0cf, 0xffff0000, 0x00000000, 0x00ffffff, + 0xffffffff, 0xfffffff3, 0x0ffff0cf, 0xffff0000, + 0x00000000, 0x0fffffff, 0xffffffff, 0xffffff30, + 0xfff70000, 0x000055aa, 0xff000000, 0x000006d5, + 0x40000000, 0x00000000, 0x731c0000, 0x000156ab, + 0xfc000000, 0x00000000, 0xffff0000, 0x00000000, + 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff, + 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000, + 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, + 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0x00100000, 0x00000000, + 0xf8000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, + 0x00ffffff, 0xffffffff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, + }, + + +/* rw_wdfet image (Image 16) + * + * ctr0 : Counts total number of writeback transactions. + * ctr1 : Total number of data valid Runway cycles. + * ctr2 : Overflow of Counter 0. + * ctr3 : Overflow of Counter 1. + */ + + { + 0x0c01e000, 0x00000000, 0x00060000, 0x00000000, + 0xefefefef, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000, + 0xf0ffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffff0000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00001b00, 0xaa000000, + 0x00000001, 0x30700000, 0x00055aaf, 0xf0000000, + 0x01b00000, 0x00000000, 0x00001037, 0x00000000, + 0x55aaff00, 0x00c00000, 0x1b55aa00, 0x00000000, + 0x0001fff0, 0xcfffff00, 0x00000000, 0x0f0fffff, + 0xffffffff, 0xffffffff, 0x30ffff0c, 0xfffff000, + 0x00000000, 0x00ffffff, 0xffffffff, 0xfffffff3, + 0x0ffff0cf, 0xffff0000, 0x00000000, 0x00ffffff, + 0xffffffff, 0xfffffff3, 0x0ffff0cf, 0xffff0000, + 0x00000000, 0x0fffffff, 0xffffffff, 0xffffff30, + 0xfff70000, 0x000055aa, 0xff000000, 0x000006d5, + 0x40000000, 0x00000000, 0x731c0000, 0x000156ab, + 0xfc000000, 0x00000000, 0xffff0000, 0x00000000, + 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff, + 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000, + 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, + 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0x00100000, 0x00000000, + 0x98000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, + 0x00ffffff, 0xffffffff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, + }, + +/* shlib_cpi image (Image 17) + * + * ctr0 : Total number of instructions in quadrant 0. + * ctr1 : Total number of CPU clock cycles in quadrant 0. + * ctr2 : Total number of Non-Nullified instructions retired. + * ctr3 : Total number of CPU clock cycles. + * + * Only works for 32-bit shared libraries. + */ + + { + 0x0c01e000, 0x00000000, 0x00060000, 0x00000000, + 0xe0e0e0e0, 0x00001fff, 0xfc00007f, 0xfff00001, + 0xffffc000, 0x07ffff00, 0x07ffffff, 0x0007ffff, + 0xff0007ff, 0xffff0007, 0xffffff00, 0x00000000, + 0xf0150000, 0x0fffff00, 0x000fffff, 0xffffffff, + 0xffffffff, 0xffff0000, 0x00000000, 0x00ffffff, + 0xffcff000, 0x0000000f, 0xfffffffc, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffff0000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x27000000, 0x00000055, + 0x02000005, 0x7f500000, 0xc0000000, 0x000ff270, + 0x00000000, 0x00000000, 0x00007700, 0x00000ff0, + 0x00000000, 0x0000ffff, 0xffffffff, 0xffffff00, + 0x00000000, 0x0000ff00, 0x00000000, 0x0f0fffff, + 0xffffffff, 0xfffff000, 0x00000000, 0x000ff000, + 0x00000000, 0x00ffffff, 0xffffffff, 0xffff0000, + 0x00000000, 0x00ff0000, 0x00000000, 0xf0ffffff, + 0xffffffff, 0xffff0000, 0x00000000, 0x00ff0000, + 0x00000000, 0x0fffffff, 0xffffffff, 0xfff00000, + 0x00000000, 0x0ff00000, 0x000000a0, 0x3fffffff, + 0xffffffff, 0xffc00000, 0x03d40000, 0x20000000, + 0x0003fc00, 0x00000000, 0xffff0000, 0x00000000, + 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff, + 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000, + 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, + 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0x00030000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + }, + +/* flop image (Image 18) + * + * ctr0 : Total number of floating point instructions (opcode = 0xc). + * ctr1 : Total number of floating point instructions (opcode = 0xe, 0x6, 0x2e, 0x26). + * ctr2 : Unused + * ctr3 : Unused + */ + + { + 0x0001e000, 0x00000000, 0x00000000, 0x00000000, + 0x00001010, 0x33ffffff, 0x006fffff, 0xfc5fffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000, + 0xf0ffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffff0000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xd22d0000, 0x00000000, + 0x0000000b, 0x46000000, 0x00000000, 0x0ffff900, + 0x90000000, 0x00000000, 0x0000907e, 0x00000000, + 0x000000ff, 0xff00bfdf, 0x03030303, 0x03030000, + 0x000dbfff, 0xffffff00, 0x00000000, 0x000fffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000, + 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000, + 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff, + 0xffff5555, 0x55500000, 0x003f3ff0, 0x2766c000, + 0x00000000, 0x00000002, 0x67840000, 0x00000000, + 0x03fffc00, 0x00000000, 0xffff0000, 0x00000000, + 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff, + 0xffffffff, 0xffcfffff, 0xfff6fb7c, 0x00000000, + 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, + 0xfff6fb7c, 0x00000000, 0xffff0fff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffff0fff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0x00130000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + }, + +/* cachemiss image FROM I_D_MISSES.IDF (Image 19) + * + * ctr0 : icache misses for retired instructions + * ctr1 : total cycles + * ctr2 : dcache misses for retired instructions + * ctr3 : number of retired instructions + */ + { + 0x2801e000, 0x00000000, 0x00010000, 0x00000000, + 0x00001000, 0xffffffff, 0xffffffff, 0xfff00fff, + 0xfffa3fff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000, + 0xf0ffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffff0000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xf2fdf0f0, 0xf0f0f0f0, + 0xffffffff, 0xf6c00000, 0x00000000, 0x0ff55800, + 0x90000000, 0x00000000, 0x0000b0ff, 0xfffffff0, + 0x00000003, 0x0100bfff, 0x3f3f3f3f, 0x3f3f5555, + 0x555fffff, 0xffffff00, 0x00000000, 0x000fffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000, + 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000, + 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xfff00000, 0x000301b0, 0x2fefcfcf, + 0xcfcfcfcf, 0xd5555557, 0xf7b40000, 0x00000000, + 0x03c14000, 0x00000000, 0xffff0000, 0x00000000, + 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff, + 0xffffffff, 0xffcfffff, 0xfff6fb7c, 0x00000000, + 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, + 0xfff6fb7c, 0x00000000, 0xffff0fff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffff0fff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0x00130000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + }, + +/* branch FROM br_report3.idf + * + * ctr0 : Total number of mispredicted branches. + * ctr1 : Some Non-Nullified unpredictable branches. + * ctr2 : Total number of branches (Nullified + Non-Nullified) + * (Unpredicted+ Predicted Taken +Predicted Not Taken). + * Total of All Branches. + * ctr3 : Remaining Non-Nullified unpredictable branches. + */ + { + 0x4001e000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0xffffffff, 0xff9fffff, 0xfe0fffff, + 0xffffbaff, 0xfdffc0ff, 0xfffdffff, 0xfffffeff, + 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000, + 0xf4ffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffff0000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xd22d0000, 0x00000000, + 0x0000000b, 0x46000000, 0x00000000, 0x0ffff900, + 0x90000000, 0x00000000, 0x0000907e, 0x00000000, + 0x000000ff, 0xff00bfdf, 0x03030303, 0x03030000, + 0x000dbfff, 0xffffff00, 0x00000000, 0x000fffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000, + 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000, + 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff, + 0xffff5555, 0x55500000, 0x003f3ff0, 0x2766c000, + 0x00000000, 0x00000002, 0x67840000, 0x00000000, + 0x03fffc00, 0x00000000, 0xffff0000, 0x00000000, + 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff, + 0xffffffff, 0xffcfffff, 0xfff6fb7c, 0x00000000, + 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, + 0xfff6fb7c, 0x00000000, 0xffff0fff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffff0fff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0x00130000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + }, + +/* crstack FROM crs_report.idf + * + * ctr0: correctly predicted branches by the pop_latch + * ctr1: some procedure returns + * ctr2: all branches, (includes nullified) + * ctr3: remaining procedure returns + */ + { + 0x4001e000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0xffffffff, 0xffa10300, 0x000fffff, + 0xffffbaf8, 0x3000007f, 0xffffffff, 0xfffffeff, + 0xff7fffff, 0xffffffff, 0xffffff00, 0x00000000, + 0xf2ffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffff0000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xd22d0000, 0x00000000, + 0x0000000b, 0x46000000, 0x00000000, 0x0ffff900, + 0x90000000, 0x00000000, 0x0000907e, 0x00000000, + 0x000000ff, 0xff00bfdf, 0x03030303, 0x03030000, + 0x000dbfff, 0xffffff00, 0x00000000, 0x000fffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000, + 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000, + 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff, + 0xffff5555, 0x55500000, 0x003f3ff0, 0x2766c000, + 0x00000000, 0x00000002, 0x67840000, 0x00000000, + 0x03fffc00, 0x00000000, 0xffff0000, 0x00000000, + 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff, + 0xffffffff, 0xffcfffff, 0xfff6fb7c, 0x00000000, + 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, + 0xfff6fb7c, 0x00000000, 0xffff0fff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffff0fff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0x00130000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + }, + +/* icache_report image + * + * ctr0 : Icache misses actually used by the core. + * ctr1 : ICORE_AV (Icache misses the core THINKS it needs, including fetching down speculative paths). + * ctr2 : READs on Runway (Icache misses that made it out to Runway, including + * prefetches). + * ctr3 : Prefetch returns (1x and 2x). + */ + { + 0x00000000, 0x00000000, 0x00010000, 0x00000000, + 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000, + 0x00ffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffff0000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xd2002d00, 0x00000000, + 0x0000000b, 0x46000000, 0x0000000f, 0xf00ff900, + 0x00900000, 0x00000000, 0x0000907e, 0x00000000, + 0x0000ff00, 0xff83bf03, 0xdf030303, 0x03030000, + 0x000dbfff, 0xffffff00, 0x00000000, 0x000fffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000, + 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffff0000, 0x00000000, 0x80ffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000, + 0x00000000, 0x4fffffff, 0xffffffff, 0xffffffff, + 0xffff5555, 0x55500000, 0x3f003f80, 0x274026c0, + 0x00000000, 0x00000002, 0x67840000, 0x00000003, + 0xfc03fc00, 0x00000000, 0x0eff0000, 0x00000000, + 0x00000000, 0x00000000, 0x00ffffff, 0xff3fffff, + 0xffffffff, 0xffcfffff, 0xfff6fb7c, 0x00000000, + 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, + 0xfff6fb7c, 0x00000000, 0xffff0fff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffff0fff, 0xffffff3f, + 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, + 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, + 0xfe000000, 0x00000000, 0x00130000, 0x00000000, + 0xd0ffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x00ffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + + } + +}; + +#endif diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/power.c linux.19rc3-ac4/arch/parisc/kernel/power.c --- linux.19rc3/arch/parisc/kernel/power.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/power.c 2002-07-29 13:58:36.000000000 +0100 @@ -0,0 +1,377 @@ +/* + * linux/arch/parisc/kernel/power.c + * HP PARISC soft power switch support driver + * + * Copyright (c) 2001-2002 Helge Deller + * All rights reserved. + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL"). + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * + * + * + * HINT: + * Support of the soft power switch button may be enabled or disabled at + * runtime through the "/proc/sys/kernel/power" procfs entry. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +#ifdef DEBUG +# define DPRINTK(x) printk x +#else +# define DPRINTK(x) do { } while (0) +#endif + + +/* filename in /proc which can be used to enable/disable the power switch */ +#define SYSCTL_FILENAME "sys/kernel/power" + + +#define DIAG_CODE(code) (0x14000000 + ((code)<<5)) + +/* this will go to processor.h or any other place... */ +/* taken from PCXL ERS page 82 */ +#define MFCPU_X(rDiagReg, t_ch, t_th, code) \ + (DIAG_CODE(code) + ((rDiagReg)<<21) + ((t_ch)<<16) + ((t_th)<<0) ) + +#define MTCPU(dr, gr) MFCPU_X(dr, gr, 0, 0x12) /* move value of gr to dr[dr] */ +#define MFCPU_C(dr, gr) MFCPU_X(dr, gr, 0, 0x30) /* for dr0 and dr8 only ! */ +#define MFCPU_T(dr, gr) MFCPU_X(dr, 0, gr, 0xa0) /* all dr except dr0 and dr8 */ + +#define __getDIAG(dr) ( { \ + register unsigned long __res asm("r28");\ + __asm__ __volatile__ ( \ + ".word %1\n nop\n" : "=&r" (__res) : "i" (MFCPU_T(dr,28)) \ + ); \ + __res; \ +} ) + + +static void deferred_poweroff(void *dummy) +{ + extern int cad_pid; /* from kernel/sys.c */ + if (kill_proc(cad_pid, SIGINT, 1)) { + /* just in case killing init process failed */ + machine_power_off(); + } +} + +/* + * This function gets called from interrupt context. + * As it's called within an interrupt, it wouldn't sync if we don't + * use schedule_task(). + */ + +static void poweroff(void) +{ + static int powering_off; + static struct tq_struct poweroff_tq = { + routine: deferred_poweroff, + }; + + if (powering_off) + return; + + powering_off++; + schedule_task(&poweroff_tq); +} + + +/* local time-counter for shutdown */ +static int shutdown_timer; + +/* check, give feedback and start shutdown after one second */ +static void process_shutdown(void) +{ + if (shutdown_timer == 0) + DPRINTK((KERN_INFO "Shutdown requested...\n")); + + shutdown_timer++; + + /* wait until the button was pressed for 1 second */ + if (shutdown_timer == HZ) { + static char msg[] = "Shutting down..."; + DPRINTK((KERN_INFO "%s\n", msg)); +#ifdef CONFIG_CHASSIS_LCD_LED + lcd_print(msg); +#endif + poweroff(); + } +} + + +/* main power switch tasklet struct (scheduled from time.c) */ +DECLARE_TASKLET_DISABLED(power_tasklet, NULL, 0); + +/* soft power switch enabled/disabled */ +#ifdef CONFIG_PROC_FS +static int pwrsw_enabled = 1; +#else +#define pwrsw_enabled (1) +#endif + +/* + * On gecko style machines (e.g. 712/xx and 715/xx) + * the power switch status is stored in Bit 0 ("the highest bit") + * of CPU diagnose register 25. + * + */ +static void gecko_tasklet_func(unsigned long unused) +{ + if (!pwrsw_enabled) + return; + + if (__getDIAG(25) & 0x80000000) { + /* power switch button not pressed or released again */ + /* Warning: Some machines do never reset this DIAG flag! */ + shutdown_timer = 0; + } else { + process_shutdown(); + } +} + + + +/* + * Check the power switch status which is read from the + * real I/O location at soft_power_reg. + * Bit 31 ("the lowest bit) is the status of the power switch. + */ + +static void polling_tasklet_func(unsigned long soft_power_reg) +{ + unsigned long current_status; + + if (!pwrsw_enabled) + return; + + current_status = gsc_readl(soft_power_reg); + if (current_status & 0x1) { + /* power switch button not pressed */ + shutdown_timer = 0; + } else { + process_shutdown(); + } +} + + +/* + * powerfail interruption handler (irq IRQ_FROM_REGION(CPU_IRQ_REGION)+2) + */ +#if 0 +static void powerfail_interrupt(int code, void *x, struct pt_regs *regs) +{ + printk(KERN_CRIT "POWERFAIL INTERRUPTION !\n"); + poweroff(); +} +#endif + + + + +/* + * /proc filesystem support + */ + +#ifdef CONFIG_SYSCTL +static int power_proc_read(char *page, char **start, off_t off, int count, + int *eof, void *data) +{ + char *out = page; + int len; + + out += sprintf(out, "Software power switch support: "); + out += sprintf(out, pwrsw_enabled ? "enabled (1)" : "disabled (0)" ); + out += sprintf(out, "\n"); + + len = out - page - off; + if (len < count) { + *eof = 1; + if (len <= 0) return 0; + } else { + len = count; + } + *start = page + off; + return len; +} + +static int power_proc_write(struct file *file, const char *buf, + unsigned long count, void *data) +{ + char *cur, lbuf[count]; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + memset(lbuf, 0, count); + + copy_from_user(lbuf, buf, count); + cur = lbuf; + + /* skip initial spaces */ + while (*cur && isspace(*cur)) + cur++; + + switch (*cur) { + case '0': pwrsw_enabled = 0; + break; + case '1': pwrsw_enabled = 1; + break; + default: printk(KERN_CRIT "/proc/" SYSCTL_FILENAME + ": Parse error: only '0' or '1' allowed!\n"); + return -EINVAL; + } /* switch() */ + + return count; +} + +static struct proc_dir_entry *ent; + +static void __init power_create_procfs(void) +{ + if (!power_tasklet.func) + return; + + ent = create_proc_entry(SYSCTL_FILENAME, S_IFREG|S_IRUGO|S_IWUSR, 0); + if (!ent) return; + + ent->nlink = 1; + ent->read_proc = power_proc_read; + ent->write_proc = power_proc_write; + ent->owner = THIS_MODULE; +} + +static void __exit power_remove_procfs(void) +{ + remove_proc_entry(SYSCTL_FILENAME, NULL); +} + +#else +#define power_create_procfs() do { } while (0) +#define power_remove_procfs() do { } while (0) +#endif /* CONFIG_SYSCTL */ + + + +/* parisc_panic_event() is called by the panic handler. + * As soon as a panic occurs, our tasklets above will not be + * executed any longer. This function then re-enables the + * soft-power switch and allows the user to switch off the system + */ +static int parisc_panic_event(struct notifier_block *this, + unsigned long event, void *ptr) +{ + /* re-enable the soft-power switch */ + pdc_soft_power_button(0); + return NOTIFY_DONE; +} + +static struct notifier_block parisc_panic_block = { + notifier_call: parisc_panic_event, + priority: INT_MAX, +}; + + +static int __init power_init(void) +{ + unsigned long ret; + unsigned long soft_power_reg = 0; + +#if 0 + request_irq( IRQ_FROM_REGION(CPU_IRQ_REGION)+2, &powerfail_interrupt, + 0, "powerfail", NULL); +#endif + + /* enable the soft power switch if possible */ + ret = pdc_soft_power_info(&soft_power_reg); + if (ret == PDC_OK) + ret = pdc_soft_power_button(1); + if (ret != PDC_OK) + soft_power_reg = -1UL; + + switch (soft_power_reg) { + case 0: printk(KERN_INFO "Gecko-style soft power switch enabled.\n"); + power_tasklet.func = gecko_tasklet_func; + break; + + case -1UL: printk(KERN_INFO "Soft power switch support not available.\n"); + return -ENODEV; + + default: printk(KERN_INFO "Soft power switch enabled, polling @ 0x%08lx.\n", + soft_power_reg); + power_tasklet.data = soft_power_reg; + power_tasklet.func = polling_tasklet_func; + } + + /* Register a call for panic conditions. */ + notifier_chain_register(&panic_notifier_list, &parisc_panic_block); + + power_create_procfs(); + tasklet_enable(&power_tasklet); + + return 0; +} + +static void __exit power_exit(void) +{ + if (!power_tasklet.func) + return; + + tasklet_disable(&power_tasklet); + notifier_chain_unregister(&panic_notifier_list, &parisc_panic_block); + power_remove_procfs(); + power_tasklet.func = NULL; + pdc_soft_power_button(0); +} + +module_init(power_init); +module_exit(power_exit); + + +MODULE_AUTHOR("Helge Deller"); +MODULE_DESCRIPTION("Soft power switch driver"); +MODULE_LICENSE("Dual BSD/GPL"); + + +EXPORT_NO_SYMBOLS; + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/process.c linux.19rc3-ac4/arch/parisc/kernel/process.c --- linux.19rc3/arch/parisc/kernel/process.c 2002-07-29 12:50:06.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/process.c 2002-07-29 13:58:36.000000000 +0100 @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -36,19 +37,12 @@ #include #include -spinlock_t semaphore_wake_lock = SPIN_LOCK_UNLOCKED; +int hlt_counter; -#ifdef __LP64__ -/* The 64-bit code should work equally well in 32-bit land but I didn't - * want to take the time to confirm that. -PB - */ -extern unsigned int ret_from_kernel_thread; -#else -asmlinkage void ret_from_kernel_thread(void) __asm__("ret_from_kernel_thread"); -#endif - - -int hlt_counter=0; +/* + * Power off function, if any + */ +void (*pm_power_off)(void); void disable_hlt(void) { @@ -81,35 +75,86 @@ } } -void __init reboot_setup(char *str, int *ints) -{ -} -struct notifier_block *mach_notifier; +#ifdef __LP64__ +#define COMMAND_GLOBAL 0xfffffffffffe0030UL +#else +#define COMMAND_GLOBAL 0xfffe0030 +#endif + +#define CMD_RESET 5 /* reset any module */ -void machine_restart(char *ptr) +/* +** The Wright Brothers and Gecko systems have a H/W problem +** (Lasi...'nuf said) may cause a broadcast reset to lockup +** the system. An HVERSION dependent PDC call was developed +** to perform a "safe", platform specific broadcast reset instead +** of kludging up all the code. +** +** Older machines which do not implement PDC_BROADCAST_RESET will +** return (with an error) and the regular broadcast reset can be +** issued. Obviously, if the PDC does implement PDC_BROADCAST_RESET +** the PDC call will not return (the system will be reset). +*/ +void machine_restart(char *cmd) { - notifier_call_chain(&mach_notifier, MACH_RESTART, ptr); +#ifdef FASTBOOT_SELFTEST_SUPPORT + /* + ** If user has modified the Firmware Selftest Bitmap, + ** run the tests specified in the bitmap after the + ** system is rebooted w/PDC_DO_RESET. + ** + ** ftc_bitmap = 0x1AUL "Skip destructive memory tests" + ** + ** Using "directed resets" at each processor with the MEM_TOC + ** vector cleared will also avoid running destructive + ** memory self tests. (Not implemented yet) + */ + if (ftc_bitmap) { + pdc_do_firm_test_reset(ftc_bitmap); + } +#endif + + /* "Normal" system reset */ + pdc_do_reset(); + + /* Nope...box should reset with just CMD_RESET now */ + gsc_writel(CMD_RESET, COMMAND_GLOBAL); + + /* Wait for RESET to lay us to rest. */ + while (1) ; + } void machine_halt(void) { - notifier_call_chain(&mach_notifier, MACH_HALT, NULL); + /* + ** The LED/ChassisCodes are updated by the led_halt() + ** function, called by the reboot notifier chain. + */ } -void machine_power_on(void) -{ - notifier_call_chain(&mach_notifier, MACH_POWER_ON, NULL); -} +/* + * This routine is called from sys_reboot to actually turn off the + * machine + */ void machine_power_off(void) { - notifier_call_chain(&mach_notifier, MACH_POWER_OFF, NULL); -} + /* If there is a registered power off handler, call it. */ + if(pm_power_off) + pm_power_off(); + + /* Put the soft power button back under hardware control. + * If the user had already pressed the power button, the + * following call will immediately power off. */ + pdc_soft_power_button(0); + /* It seems we have no way to power the system off via + * software. The user has to press the button himself. */ -void machine_heartbeat(void) -{ + printk(KERN_EMERG "System shut down completed.\n" + KERN_EMERG "Please power this system off now."); } @@ -138,6 +183,9 @@ void flush_thread(void) { + /* Only needs to handle fpu stuff or perf monitors. + ** REVISIT: several arches implement a "lazy fpu state". + */ set_fs(USER_DS); } @@ -148,6 +196,7 @@ /* * Fill in the FPU structure for a core dump. */ + int dump_fpu (struct pt_regs * regs, elf_fpregset_t *r) { memcpy(r, regs->fr, sizeof *r); @@ -176,7 +225,13 @@ struct task_struct * p, struct pt_regs * pregs) { struct pt_regs * cregs = &(p->thread.regs); - long ksp; + + /* We have to use void * instead of a function pointer, because + * function pointers aren't a pointer to the function on 64-bit. + * Make them const so the compiler knows they live in .text */ + extern void * const ret_from_kernel_thread; + extern void * const child_return; + extern void * const hpux_child_return; *cregs = *pregs; @@ -193,34 +248,37 @@ * in zero for usp. */ if (usp == 0) { - /* Kernel Thread */ - ksp = (((unsigned long)(p)) + TASK_SZ_ALGN); - cregs->ksp = ksp; /* always return to kernel */ -#ifdef __LP64__ + /* kernel thread */ + cregs->ksp = (((unsigned long)(p)) + TASK_SZ_ALGN); + /* Must exit via ret_from_kernel_thread in order + * to call schedule_tail() + */ cregs->kpc = (unsigned long) &ret_from_kernel_thread; -#else - cregs->kpc = (unsigned long) ret_from_kernel_thread; -#endif - /* * Copy function and argument to be called from * ret_from_kernel_thread. */ +#ifdef __LP64__ + cregs->gr[27] = pregs->gr[27]; +#endif cregs->gr[26] = pregs->gr[26]; cregs->gr[25] = pregs->gr[25]; - } else { - /* User Thread: - * - * Use same stack depth as parent when in wrapper - * + /* user thread */ + /* * Note that the fork wrappers are responsible - * for setting gr[20] and gr[21]. + * for setting gr[21]. */ + /* Use same stack depth as parent */ cregs->ksp = ((unsigned long)(p)) - + (pregs->gr[20] & (INIT_TASK_SIZE - 1)); - cregs->kpc = pregs->gr[21]; + + (pregs->gr[21] & (INIT_TASK_SIZE - 1)); + cregs->gr[30] = usp; + if (p->personality == PER_HPUX) { + cregs->kpc = (unsigned long) &hpux_child_return; + } else { + cregs->kpc = (unsigned long) &child_return; + } } return 0; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/processor.c linux.19rc3-ac4/arch/parisc/kernel/processor.c --- linux.19rc3/arch/parisc/kernel/processor.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/processor.c 2002-07-29 13:58:36.000000000 +0100 @@ -0,0 +1,374 @@ +/* $Id: processor.c,v 1.13 2002/07/04 19:33:01 grundler Exp $ + * + * Initial setup-routines for HP 9000 based hardware. + * + * Copyright (C) 1991, 1992, 1995 Linus Torvalds + * Modifications for PA-RISC (C) 1999 Helge Deller + * Modifications copyright 1999 SuSE GmbH (Philipp Rumpf) + * Modifications copyright 2000 Martin K. Petersen + * Modifications copyright 2000 Philipp Rumpf + * Modifications copyright 2001 Ryan Bradetich + * + * Initial PA-RISC Version: 04-23-1999 by Helge Deller + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include +#include +#include +#include +#include +#include +#define PCI_DEBUG +#include +#undef PCI_DEBUG + +#include +#include /* for register_parisc_driver() stuff */ +#include +#include +#include +#include /* for struct irq_region */ + +struct system_cpuinfo_parisc boot_cpu_data; +struct cpuinfo_parisc cpu_data[NR_CPUS]; + +/* +** PARISC CPU driver - claim "device" and initialize CPU data structures. +** +** Consolidate per CPU initialization into (mostly) one module. +** Monarch CPU will initialize boot_cpu_data which shouldn't +** change once the system has booted. +** +** The callback *should* do per-instance initialization of +** everything including the monarch. "Per CPU" init code in +** setup.c:start_parisc() has migrated here and start_parisc() +** will call register_parisc_driver(&cpu_driver) before calling do_inventory(). +** +** The goal of consolidating CPU initialization into one place is +** to make sure all CPU's get initialized the same way. +** The code path not shared is how PDC hands control of the CPU to the OS. +** The initialization of OS data structures is the same (done below). +*/ + +/** + * processor_probe - Determine if processor driver should claim this device. + * @dev: The device which has been found. + * + * Determine if processor driver should claim this chip (return 0) or not + * (return 1). If so, initialize the chip and tell other partners in crime + * they have work to do. + */ +static int __init processor_probe(struct parisc_device *dev) +{ + unsigned long txn_addr; + unsigned long cpuid; + struct cpuinfo_parisc *p; + +#ifndef CONFIG_SMP + if (boot_cpu_data.cpu_count > 0) { + printk(KERN_INFO "CONFIG_SMP=n ignoring additional CPUs\n"); + return 1; + } +#endif + + /* logical CPU ID and update global counter + * May get overwritten by PAT code. + */ + cpuid = boot_cpu_data.cpu_count; + txn_addr = dev->hpa; /* for legacy PDC */ + +#ifdef __LP64__ + if (is_pdc_pat()) { + ulong status; + unsigned long bytecnt; + pdc_pat_cell_mod_maddr_block_t pa_pdc_cell; +#undef USE_PAT_CPUID +#ifdef USE_PAT_CPUID + struct pdc_pat_cpu_num cpu_info; +#endif + + status = pdc_pat_cell_module(&bytecnt, dev->pcell_loc, + dev->mod_index, PA_VIEW, &pa_pdc_cell); + + ASSERT(PDC_OK == status); + + /* verify it's the same as what do_pat_inventory() found */ + ASSERT(dev->mod_info == pa_pdc_cell.mod_info); + ASSERT(dev->pmod_loc == pa_pdc_cell.mod_location); + + txn_addr = pa_pdc_cell.mod[0]; /* id_eid for IO sapic */ + +#ifdef USE_PAT_CPUID +/* We need contiguous numbers for cpuid. Firmware's notion + * of cpuid is for physical CPUs and we just don't care yet. + * We'll care when we need to query PAT PDC about a CPU *after* + * boot time (ie shutdown a CPU from an OS perspective). + */ + /* get the cpu number */ + status = pdc_pat_cpu_get_number(&cpu_info, dev->hpa); + + ASSERT(PDC_OK == status); + + if (cpu_info.cpu_num >= NR_CPUS) { + printk(KERN_WARNING "IGNORING CPU at 0x%x," + " cpu_slot_id > NR_CPUS" + " (%ld > %d)\n", + dev->hpa, cpu_info.cpu_num, NR_CPUS); + /* Ignore CPU since it will only crash */ + boot_cpu_data.cpu_count--; + return 1; + } else { + cpuid = cpu_info.cpu_num; + } +#endif + } +#endif + + p = &cpu_data[cpuid]; + boot_cpu_data.cpu_count++; + + /* initialize counters */ + memset(p, 0, sizeof(struct cpuinfo_parisc)); + + p->dev = dev; /* Save IODC data in case we need it */ + p->hpa = dev->hpa; /* save CPU hpa */ + p->cpuid = cpuid; /* save CPU id */ + p->txn_addr = txn_addr; /* save CPU IRQ address */ +#ifdef CONFIG_SMP + p->lock = SPIN_LOCK_UNLOCKED; + + /* + ** FIXME: review if any other initialization is clobbered + ** for boot_cpu by the above memset(). + */ + + /* stolen from init_percpu_prof() */ + cpu_data[cpuid].prof_counter = 1; + cpu_data[cpuid].prof_multiplier = 1; +#endif + + /* + ** CONFIG_SMP: init_smp_config() will attempt to get CPU's into + ** OS control. RENDEZVOUS is the default state - see mem_set above. + ** p->state = STATE_RENDEZVOUS; + */ + + /* + ** itimer and ipi IRQ handlers are statically initialized in + ** arch/parisc/kernel/irq.c. ie Don't need to register them. + */ + p->region = irq_region[IRQ_FROM_REGION(CPU_IRQ_REGION)]; + + return 0; +} + +/** + * collect_boot_cpu_data - Fill the boot_cpu_data structure. + * + * This function collects and stores the generic processor information + * in the boot_cpu_data structure. + */ +void __init collect_boot_cpu_data(void) +{ + memset(&boot_cpu_data, 0, sizeof(boot_cpu_data)); + + boot_cpu_data.cpu_hz = 100 * PAGE0->mem_10msec; /* Hz of this PARISC */ + + /* get CPU-Model Information... */ +#define p ((unsigned long *)&boot_cpu_data.pdc.model) + if (pdc_model_info(&boot_cpu_data.pdc.model) == PDC_OK) + printk(KERN_INFO + "model %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", + p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8]); +#undef p + + if (pdc_model_versions(&boot_cpu_data.pdc.versions, 0) == PDC_OK) + printk(KERN_INFO "vers %08lx\n", + boot_cpu_data.pdc.versions); + + if (pdc_model_cpuid(&boot_cpu_data.pdc.cpuid) == PDC_OK) + printk(KERN_INFO "CPUID vers %ld rev %ld (0x%08lx)\n", + (boot_cpu_data.pdc.cpuid >> 5) & 127, + boot_cpu_data.pdc.cpuid & 31, + boot_cpu_data.pdc.cpuid); + + if (pdc_model_capabilities(&boot_cpu_data.pdc.capabilities) == PDC_OK) + printk(KERN_INFO "capabilities 0x%lx\n", + boot_cpu_data.pdc.capabilities); + + if (pdc_model_sysmodel(boot_cpu_data.pdc.sys_model_name) == PDC_OK) + printk(KERN_INFO "model %s\n", + boot_cpu_data.pdc.sys_model_name); + + boot_cpu_data.hversion = boot_cpu_data.pdc.model.hversion; + boot_cpu_data.sversion = boot_cpu_data.pdc.model.sversion; + + boot_cpu_data.cpu_type = + parisc_get_cpu_type(boot_cpu_data.hversion); + + boot_cpu_data.cpu_name = cpu_name_version[boot_cpu_data.cpu_type][0]; + boot_cpu_data.family_name = cpu_name_version[boot_cpu_data.cpu_type][1]; +} + + +/** + * init_cpu_profiler - enable/setup per cpu profiling hooks. + * @cpunum: The processor instance. + * + * FIXME: doesn't do much yet... + */ +static inline void __init +init_percpu_prof(int cpunum) +{ + cpu_data[cpunum].prof_counter = 1; + cpu_data[cpunum].prof_multiplier = 1; +} + + +/** + * init_per_cpu - Handle individual processor initializations. + * @cpunum: logical processor number. + * + * This function handles initialization for *every* CPU + * in the system: + * + * o Set "default" CPU width for trap handlers + * + * o Enable FP coprocessor + * REVISIT: this could be done in the "code 22" trap handler. + * (frowands idea - that way we know which processes need FP + * registers saved on the interrupt stack.) + * NEWS FLASH: wide kernels need FP coprocessor enabled to handle + * formatted printing of %lx for example (double divides I think) + * + * o Enable CPU profiling hooks. + */ +int __init init_per_cpu(int cpunum) +{ + int ret; + struct pdc_coproc_cfg coproc_cfg; + + ret = pdc_coproc_cfg(&coproc_cfg); + + if(ret >= 0 && coproc_cfg.ccr_functional) { + mtctl(coproc_cfg.ccr_functional, 10); /* 10 == Coprocessor Control Reg */ + + /* FWIW, FP rev/model is a more accurate way to determine + ** CPU type. CPU rev/model has some ambiguous cases. + */ + cpu_data[cpunum].fp_rev = coproc_cfg.revision; + cpu_data[cpunum].fp_model = coproc_cfg.model; + + printk(KERN_INFO "FP[%d] enabled: Rev %ld Model %ld\n", + cpunum, coproc_cfg.revision, coproc_cfg.model); + + /* + ** store status register to stack (hopefully aligned) + ** and clear the T-bit. + */ + asm volatile ("fstd %fr0,8(%sp)"); + + } else { + printk(KERN_WARNING "WARNING: No FP CoProcessor?!" + " (coproc_cfg.ccr_functional == 0x%lx, expected 0xc0)\n" +#ifdef __LP64__ + "Halting Machine - FP required\n" +#endif + , coproc_cfg.ccr_functional); +#ifdef __LP64__ + mdelay(100); /* previous chars get pushed to console */ + panic("FP CoProc not reported"); +#endif + } + + /* FUTURE: Enable Performance Monitor : ccr bit 0x20 */ + init_percpu_prof(cpunum); + + return ret; +} + +/* + * Display cpu info for all cpu's. + */ +int +show_cpuinfo (struct seq_file *m, void *v) +{ + int n; + + for(n=0; nname : "Unknown" ); + + seq_printf(m, "hversion\t: 0x%08x\n" + "sversion\t: 0x%08x\n", + boot_cpu_data.hversion, + boot_cpu_data.sversion ); + + /* print cachesize info */ + show_cache_info(m); + + seq_printf(m, "bogomips\t: %lu.%02lu\n", + loops_per_jiffy / (500000 / HZ), + (loops_per_jiffy / (5000 / HZ)) % 100); + + seq_printf(m, "software id\t: %ld\n\n", + boot_cpu_data.pdc.model.sw_id); + } + return 0; +} + +static struct parisc_device_id processor_tbl[] = { + { HPHW_NPROC, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, SVERSION_ANY_ID }, + { 0, } +}; + +static struct parisc_driver cpu_driver = { + name: "CPU", + id_table: processor_tbl, + probe: processor_probe +}; + +/** + * processor_init - Processor initalization procedure. + * + * Register this driver. + */ +void __init processor_init(void) +{ + register_parisc_driver(&cpu_driver); +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/ptrace.c linux.19rc3-ac4/arch/parisc/kernel/ptrace.c --- linux.19rc3/arch/parisc/kernel/ptrace.c 2002-07-29 12:50:06.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/ptrace.c 2002-07-29 13:58:36.000000000 +0100 @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -31,6 +32,47 @@ #define PT_SINGLESTEP 0x10000 #define PT_BLOCKSTEP 0x20000 +/* PSW bits we allow the debugger to modify */ +#define USER_PSW_BITS (PSW_N | PSW_V | PSW_CB) + +#undef DEBUG_PTRACE + +#ifdef DEBUG_PTRACE +#define DBG(x) printk x +#else +#define DBG(x) +#endif + +#ifdef __LP64__ + +#define CHILD_IS_32BIT (child->personality == PER_LINUX_32BIT) + +/* This function is needed to translate 32 bit pt_regs offsets in to + * 64 bit pt_regs offsets. For example, a 32 bit gdb under a 64 bit kernel + * will request offset 12 if it wants gr3, but the lower 32 bits of + * the 64 bit kernels view of gr3 will be at offset 28 (3*8 + 4). + * This code relies on a 32 bit pt_regs being comprised of 32 bit values + * except for the fp registers which (a) are 64 bits, and (b) follow + * the gr registers at the start of pt_regs. The 32 bit pt_regs should + * be half the size of the 64 bit pt_regs, plus 32*4 to allow for fr[] + * being 64 bit in both cases. + */ + +static long translate_usr_offset(long offset) +{ + if (offset < 0) + return -1; + else if (offset <= 32*4) /* gr[0..31] */ + return offset * 2 + 4; + else if (offset <= 32*4+32*8) /* gr[0..31] + fr[0..31] */ + return offset + 32*4; + else if (offset < sizeof(struct pt_regs)/2 + 32*4) + return offset * 2 + 4 - 32*8; + else + return -1; +} +#endif + /* * Called by kernel/ptrace.c when detaching.. * @@ -49,6 +91,9 @@ { struct task_struct *child; long ret; +#ifdef DEBUG_PTRACE + long oaddr=addr, odata=data; +#endif lock_kernel(); ret = -EPERM; @@ -91,14 +136,33 @@ switch (request) { 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_tsk; - ret = put_user(tmp,(unsigned long *) data); +#ifdef __LP64__ + if (CHILD_IS_32BIT) { + unsigned int tmp; + + addr &= 0xffffffffL; + copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); + ret = -EIO; + if (copied != sizeof(tmp)) + goto out_tsk; + ret = put_user(tmp,(unsigned int *) data); + DBG(("sys_ptrace(PEEK%s, %d, %lx, %lx) returning %ld, data %x\n", + request == PTRACE_PEEKTEXT ? "TEXT" : "DATA", + pid, oaddr, odata, ret, tmp)); + } + else +#endif + { + unsigned long tmp; + + copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); + ret = -EIO; + if (copied != sizeof(tmp)) + goto out_tsk; + ret = put_user(tmp,(unsigned long *) data); + } goto out_tsk; } @@ -106,22 +170,53 @@ 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_tsk; +#ifdef __LP64__ + if (CHILD_IS_32BIT) { + unsigned int tmp = (unsigned int)data; + DBG(("sys_ptrace(POKE%s, %d, %lx, %lx)\n", + request == PTRACE_POKETEXT ? "TEXT" : "DATA", + pid, oaddr, odata)); + addr &= 0xffffffffL; + if (access_process_vm(child, addr, &tmp, sizeof(tmp), 1) == sizeof(tmp)) + goto out_tsk; + } + else +#endif + { + if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) + goto out_tsk; + } ret = -EIO; goto out_tsk; - /* Read the word at location addr in the USER area. This will need - to change when the kernel no longer saves all regs on a syscall. */ + /* Read the word at location addr in the USER area. For ptraced + processes, the kernel saves all regs on a syscall. */ case PTRACE_PEEKUSR: { - unsigned long tmp; - ret = -EIO; - if ((addr & 3) || (unsigned long) addr >= sizeof(struct pt_regs)) - goto out_tsk; - - tmp = *(unsigned long *) ((char *) task_regs(child) + addr); - ret = put_user(tmp, (unsigned long *) data); +#ifdef __LP64__ + if (CHILD_IS_32BIT) { + unsigned int tmp; + + if (addr & (sizeof(int)-1)) + goto out_tsk; + if ((addr = translate_usr_offset(addr)) < 0) + goto out_tsk; + + tmp = *(unsigned int *) ((char *) task_regs(child) + addr); + ret = put_user(tmp, (unsigned int *) data); + DBG(("sys_ptrace(PEEKUSR, %d, %lx, %lx) returning %ld, addr %lx, data %x\n", + pid, oaddr, odata, ret, addr, tmp)); + } + else +#endif + { + unsigned long tmp; + + if ((addr & (sizeof(long)-1)) || (unsigned long) addr >= sizeof(struct pt_regs)) + goto out_tsk; + tmp = *(unsigned long *) ((char *) task_regs(child) + addr); + ret = put_user(tmp, (unsigned long *) data); + } goto out_tsk; } @@ -133,25 +228,73 @@ exit. */ case PTRACE_POKEUSR: ret = -EIO; - if ((addr & 3) || (unsigned long) addr >= sizeof(struct pt_regs)) - goto out_tsk; - /* XXX This test probably needs adjusting. We probably want to - * allow writes to some bits of PSW, and may want to block writes - * to (some) space registers. Some register values written here - * may be ignored in entry.S:syscall_restore_rfi; e.g. iaoq is - * written with r31/r31+4, and not with the values in pt_regs. + /* Some register values written here may be ignored in + * entry.S:syscall_restore_rfi; e.g. iaoq is written with + * r31/r31+4, and not with the values in pt_regs. + */ + /* PT_PSW=0, so this is valid for 32 bit processes under 64 + * bit kernels. */ - /* Allow writing of gr1-gr31, fr*, sr*, iasq*, iaoq*, sar */ - if (addr == PT_PSW || (addr > PT_IAOQ1 && addr != PT_SAR)) + if (addr == PT_PSW) { + /* PT_PSW=0, so this is valid for 32 bit processes + * under 64 bit kernels. + * + * Allow writing to Nullify, Divide-step-correction, + * and carry/borrow bits. + * BEWARE, if you set N, and then single step, it wont + * stop on the nullified instruction. + */ + DBG(("sys_ptrace(POKEUSR, %d, %lx, %lx)\n", + pid, oaddr, odata)); + data &= USER_PSW_BITS; + task_regs(child)->gr[0] &= ~USER_PSW_BITS; + task_regs(child)->gr[0] |= data; + ret = 0; goto out_tsk; - - *(unsigned long *) ((char *) task_regs(child) + addr) = data; - ret = 0; - goto out_tsk; + } +#ifdef __LP64__ + if (CHILD_IS_32BIT) { + if (addr & (sizeof(int)-1)) + goto out_tsk; + if ((addr = translate_usr_offset(addr)) < 0) + goto out_tsk; + DBG(("sys_ptrace(POKEUSR, %d, %lx, %lx) addr %lx\n", + pid, oaddr, odata, addr)); + if (addr >= PT_FR0 && addr <= PT_FR31) { + /* Special case, fp regs are 64 bits anyway */ + *(unsigned int *) ((char *) task_regs(child) + addr) = data; + ret = 0; + } + else if ((addr >= PT_GR1+4 && addr <= PT_GR31+4) || + addr == PT_IAOQ0+4 || addr == PT_IAOQ1+4 || + addr == PT_SAR+4) { + /* Zero the top 32 bits */ + *(unsigned int *) ((char *) task_regs(child) + addr - 4) = 0; + *(unsigned int *) ((char *) task_regs(child) + addr) = data; + ret = 0; + } + goto out_tsk; + } + else +#endif + { + if ((addr & (sizeof(long)-1)) || (unsigned long) addr >= sizeof(struct pt_regs)) + goto out_tsk; + if ((addr >= PT_GR1 && addr <= PT_GR31) || + addr == PT_IAOQ0 || addr == PT_IAOQ1 || + (addr >= PT_FR0 && addr <= PT_FR31) || + addr == PT_SAR) { + *(unsigned long *) ((char *) task_regs(child) + addr) = data; + ret = 0; + } + goto out_tsk; + } case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_CONT: ret = -EIO; + DBG(("sys_ptrace(%s)\n", + request == PTRACE_SYSCALL ? "SYSCALL" : "CONT")); if ((unsigned long) data > _NSIG) goto out_tsk; child->ptrace &= ~(PT_SINGLESTEP|PT_BLOCKSTEP); @@ -168,12 +311,14 @@ * sigkill. perhaps it should be put in the status * that it wants to exit. */ + DBG(("sys_ptrace(KILL)\n")); if (child->state == TASK_ZOMBIE) /* already dead */ goto out_tsk; child->exit_code = SIGKILL; goto out_wake_notrap; case PTRACE_SINGLEBLOCK: + DBG(("sys_ptrace(SINGLEBLOCK)\n")); ret = -EIO; if ((unsigned long) data > _NSIG) goto out_tsk; @@ -189,6 +334,7 @@ goto out_wake; case PTRACE_SINGLESTEP: + DBG(("sys_ptrace(SINGLESTEP)\n")); ret = -EIO; if ((unsigned long) data > _NSIG) goto out_tsk; @@ -208,10 +354,7 @@ pa_psw(child)->y = 0; pa_psw(child)->z = 0; pa_psw(child)->b = 0; - pa_psw(child)->r = 0; - pa_psw(child)->t = 0; - pa_psw(child)->h = 0; - pa_psw(child)->l = 0; + ptrace_disable(child); /* Don't wake up the child, but let the parent know something happened. */ si.si_code = TRAP_TRACE; @@ -249,11 +392,7 @@ } out_wake_notrap: - /* make sure the trap bits are not set */ - pa_psw(child)->r = 0; - pa_psw(child)->t = 0; - pa_psw(child)->h = 0; - pa_psw(child)->l = 0; + ptrace_disable(child); out_wake: wake_up_process(child); ret = 0; @@ -261,6 +400,8 @@ free_task_struct(child); out: unlock_kernel(); + DBG(("sys_ptrace(%ld, %d, %lx, %lx) returning %ld\n", + request, pid, oaddr, odata, ret)); return ret; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/real1.c linux.19rc3-ac4/arch/parisc/kernel/real1.c --- linux.19rc3/arch/parisc/kernel/real1.c 2002-07-29 12:50:06.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/real1.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,154 +0,0 @@ -/* - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2000 Hewlett Packard (Paul Bame bame@puffin.external.hp.com) - * - * most of these calls might reasonably be moved to ../kernel -PB - * - * The basic principle is to construct a stack frame in C then call - * some assembly which adopts that stack, does some rfi magic, may - * switch wide/narrow mode, and calls the routine described by the - * 'fn' parameter WHICH IS NOT A FUNCTION POINTER!!!!!!!!!!!!!!!! - */ -#include -#include -#include -#include /* for __pa() */ -#include - -static spinlock_t pdc_lock = SPIN_LOCK_UNLOCKED; - -/***************** 32-bit real-mode calls ***********/ -/* The struct below is used - * to overlay real_stack (real2.S), preparing a 32-bit call frame. - * real32_call_asm() then uses this stack in narrow real mode - */ - -struct narrow_stack { - /* use int, not long which is 64 bits */ - unsigned int arg13; - unsigned int arg12; - unsigned int arg11; - unsigned int arg10; - unsigned int arg9; - unsigned int arg8; - unsigned int arg7; - unsigned int arg6; - unsigned int arg5; - unsigned int arg4; - unsigned int arg3; - unsigned int arg2; - unsigned int arg1; - unsigned int arg0; - unsigned int frame_marker[8]; - unsigned int sp; - /* in reality, there's nearly 8k of stack after this */ -}; - -long -real32_call(unsigned long fn, ...) -{ - unsigned long r; - va_list args; - unsigned long flags; - extern struct narrow_stack real_stack; - extern unsigned long real32_call_asm(unsigned int *, - unsigned int *, unsigned int); - - va_start(args, fn); - real_stack.arg0 = va_arg(args, unsigned int); - real_stack.arg1 = va_arg(args, unsigned int); - real_stack.arg2 = va_arg(args, unsigned int); - real_stack.arg3 = va_arg(args, unsigned int); - real_stack.arg4 = va_arg(args, unsigned int); - real_stack.arg5 = va_arg(args, unsigned int); - real_stack.arg6 = va_arg(args, unsigned int); - real_stack.arg7 = va_arg(args, unsigned int); - real_stack.arg8 = va_arg(args, unsigned int); - real_stack.arg9 = va_arg(args, unsigned int); - real_stack.arg10 = va_arg(args, unsigned int); - real_stack.arg11 = va_arg(args, unsigned int); - real_stack.arg12 = va_arg(args, unsigned int); - real_stack.arg13 = va_arg(args, unsigned int); - va_end(args); - - if (fn == 0) { - /* mem_pdc call */ - fn = PAGE0->mem_pdc; - } - - spin_lock_irqsave(&pdc_lock, flags); - r = real32_call_asm(&real_stack.sp, &real_stack.arg0, fn); - spin_unlock_irqrestore(&pdc_lock, flags); - - return r; -} - -#ifdef __LP64__ -/***************** 64-bit real-mode calls ***********/ - -struct wide_stack { - unsigned long arg0; - unsigned long arg1; - unsigned long arg2; - unsigned long arg3; - unsigned long arg4; - unsigned long arg5; - unsigned long arg6; - unsigned long arg7; - unsigned long arg8; - unsigned long arg9; - unsigned long arg10; - unsigned long arg11; - unsigned long arg12; - unsigned long arg13; - unsigned long frame_marker[2]; /* rp, previous sp */ - unsigned long sp; - /* in reality, there's nearly 8k of stack after this */ -}; - -long -real64_call(unsigned long fn, ...) -{ - unsigned long r; - va_list args; - unsigned long flags; - extern struct wide_stack real_stack; - extern unsigned long real64_call_asm(unsigned long *, - unsigned long *, unsigned long); - - va_start(args, fn); - real_stack.arg0 = va_arg(args, unsigned long); - real_stack.arg1 = va_arg(args, unsigned long); - real_stack.arg2 = va_arg(args, unsigned long); - real_stack.arg3 = va_arg(args, unsigned long); - real_stack.arg4 = va_arg(args, unsigned long); - real_stack.arg5 = va_arg(args, unsigned long); - real_stack.arg6 = va_arg(args, unsigned long); - real_stack.arg7 = va_arg(args, unsigned long); - real_stack.arg8 = va_arg(args, unsigned long); - real_stack.arg9 = va_arg(args, unsigned long); - real_stack.arg10 = va_arg(args, unsigned long); - real_stack.arg11 = va_arg(args, unsigned long); - real_stack.arg12 = va_arg(args, unsigned long); - real_stack.arg13 = va_arg(args, unsigned long); - va_end(args); - - if (fn == 0) { - /* mem_pdc call */ - fn = PAGE0->mem_pdc_hi; - fn <<= 32; - fn |= PAGE0->mem_pdc; - } - - spin_lock_irqsave(&pdc_lock, flags); - r = real64_call_asm(&real_stack.sp, &real_stack.arg0, fn); - spin_unlock_irqrestore(&pdc_lock, flags); - - return r; -} - -#endif diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/real2.S linux.19rc3-ac4/arch/parisc/kernel/real2.S --- linux.19rc3/arch/parisc/kernel/real2.S 2002-07-29 12:50:06.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/real2.S 2002-07-29 13:58:36.000000000 +0100 @@ -7,7 +7,6 @@ * Copyright (C) 2000 Hewlett Packard (Paul Bame bame@puffin.external.hp.com) * */ -#define __ASSEMBLY__ #include #include @@ -31,8 +30,11 @@ /************************ 32-bit real-mode calls ***********************/ /* This can be called in both narrow and wide kernels */ + .text + .export real32_call_asm + /* unsigned long real32_call_asm(unsigned int *sp, * unsigned int *arg0p, * unsigned int iodc_fn) @@ -40,6 +42,7 @@ * arg0p points to where saved arg values may be found * iodc_fn is the IODC function to call */ + real32_call_asm: STREG %rp, -RP_OFFSET(%sp) /* save RP */ #ifdef __LP64__ @@ -61,7 +64,7 @@ ldw -12(%arg1), %arg3 ldw -4(%arg1), %arg1 /* obviously must do this one last! */ - tophys %sp + tophys_r1 %sp b,l rfi_virt2real,%r2 nop @@ -88,7 +91,7 @@ b,l rfi_real2virt,%r2 nop - tovirt %sp + tovirt_r1 %sp LDREG -REG_SZ(%sp), %sp /* restore SP */ #ifdef __LP64__ LDREG -1*REG_SZ(%sp), %r27 @@ -150,14 +153,14 @@ nop nop - mtsm 0 /* disable interruptions */ + rsm (PSW_SM_Q|PSW_SM_I),%r0 /* disable Q & I bits to load iia queue */ mtctl 0, %cr17 /* space 0 */ mtctl 0, %cr17 load32 PA(rfi_v2r_1), %r1 mtctl %r1, %cr18 ldo 4(%r1), %r1 mtctl %r1, %cr18 - load32 PDC_PSW, %r1 + load32 REAL_MODE_PSW, %r1 mtctl %r1, %cr22 rfi @@ -170,7 +173,7 @@ nop nop rfi_v2r_1: - tophys %r2 + tophys_r1 %r2 bv 0(%r2) nop @@ -187,7 +190,7 @@ nop nop - mtsm 0 /* disable interruptions */ + rsm PSW_SM_Q,%r0 /* disable Q bit to load iia queue */ mtctl 0, %cr17 /* space 0 */ mtctl 0, %cr17 load32 (rfi_r2v_1), %r1 @@ -207,7 +210,7 @@ nop nop rfi_r2v_1: - tovirt %r2 + tovirt_r1 %r2 bv 0(%r2) nop @@ -246,7 +249,7 @@ ldd 7*REG_SZ(%arg1), %r19 ldd 1*REG_SZ(%arg1), %arg1 /* do this one last! */ - tophys %sp + tophys_r1 %sp b,l rfi_virt2real,%r2 nop @@ -265,10 +268,18 @@ b,l rfi_real2virt,%r2 nop - tovirt %sp + tovirt_r1 %sp ldd -8(%sp), %sp /* restore SP */ ldd -0x10(%sp), %rp /* restore RP */ bv 0(%rp) nop #endif + .export pc_in_user_space + .text + /* Doesn't belong here but I couldn't find a nicer spot. */ + /* Should never get called, only used by profile stuff in time.c */ +pc_in_user_space: + bv,n 0(%rp) + nop + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/sba_iommu.c linux.19rc3-ac4/arch/parisc/kernel/sba_iommu.c --- linux.19rc3/arch/parisc/kernel/sba_iommu.c 2002-07-29 12:50:06.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/sba_iommu.c 2002-07-29 13:58:37.000000000 +0100 @@ -15,7 +15,6 @@ ** This module initializes the IOC (I/O Controller) found on B1000/C3000/ ** J5000/J7000/N-class/L-class machines and their successors. ** -** FIXME: Multi-IOC support missing - depends on hp_device data ** FIXME: add DMA hint support programming in both sba and lba modules. */ @@ -28,7 +27,7 @@ #include #include -#define PCI_DEBUG /* for ASSERT */ +#undef PCI_DEBUG /* for ASSERT */ #include #undef PCI_DEBUG @@ -36,19 +35,19 @@ #include #include /* for DMA_CHUNK_SIZE */ -#include /* for register_driver() stuff */ +#include /* for register_parisc_driver() stuff */ #include /* FIXME: for gsc_read/gsc_write */ #include #include /* for proc_runway_root */ - +#include /* for PDC_MODEL_* */ #define MODULE_NAME "SBA" /* ** The number of debug flags is a clue - this code is fragile. ** Don't even think about messing with it unless you have -** plenty of 710's to sacrafice to the computer gods. :^) +** plenty of 710's to sacrifice to the computer gods. :^) */ #undef DEBUG_SBA_INIT #undef DEBUG_SBA_RUN @@ -56,12 +55,9 @@ #undef DEBUG_SBA_RESOURCE #undef ASSERT_PDIR_SANITY #undef DEBUG_LARGE_SG_ENTRIES +#undef DEBUG_DMB_TRAP -#if 1 -#define SBA_INLINE -#else #define SBA_INLINE __inline__ -#endif #ifdef DEBUG_SBA_INIT #define DBG_INIT(x...) printk(x) @@ -95,73 +91,43 @@ ** allocated and free'd/purged at a time might make this ** less interesting). */ -#if 0 #define DELAYED_RESOURCE_CNT 16 -#else -#undef DELAYED_RESOURCE_CNT -#endif #define DEFAULT_DMA_HINT_REG 0 -#define ASTRO_RUNWAY_PORT 0x582 -#define ASTRO_ROPES_PORT 0x780 - -#define IKE_MERCED_PORT 0x803 -#define IKE_ROPES_PORT 0x781 - -int sba_driver_callback(struct hp_device *, struct pa_iodc_driver *); +#define ASTRO_RUNWAY_PORT 0x582 +#define ASTRO_ROPES_PORT 0x780 -static struct pa_iodc_driver sba_drivers_for[] = { +#define IKE_MERCED_PORT 0x803 +#define IKE_ROPES_PORT 0x781 -/* FIXME: why is SVERSION checked? */ - - {HPHW_IOA, ASTRO_RUNWAY_PORT, 0x0, 0xb, 0, 0x10, - DRIVER_CHECK_HVERSION + - DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE, - MODULE_NAME, "I/O MMU", (void *) sba_driver_callback}, - - {HPHW_BCPORT, ASTRO_ROPES_PORT, 0x0, 0xb, 0, 0x10, - DRIVER_CHECK_HVERSION + - DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE, - MODULE_NAME, "I/O MMU", (void *) sba_driver_callback}, - -#if 0 -/* FIXME : N-class! Use a different "callback"? */ - {HPHW_BCPORT, IKE_MERCED_PORT, 0x0, 0xb, 0, 0x10, - DRIVER_CHECK_HVERSION + - DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE, - MODULE_NAME, "I/O MMU", (void *) sba_driver_callback}, - - {HPHW_BCPORT, IKE_ROPES_PORT, 0x0, 0xb, 0, 0x10, - DRIVER_CHECK_HVERSION + - DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE, - MODULE_NAME, "I/O MMU", (void *) sba_driver_callback}, -#endif - - {0,0,0,0,0,0, - 0, - (char *) NULL, (char *) NULL, (void *) NULL } -}; +#define REO_MERCED_PORT 0x804 +#define REO_ROPES_PORT 0x782 +#define REOG_MERCED_PORT 0x805 +#define REOG_ROPES_PORT 0x783 #define SBA_FUNC_ID 0x0000 /* function id */ #define SBA_FCLASS 0x0008 /* function class, bist, header, rev... */ -#define IS_ASTRO(id) ( \ - (((id)->hw_type == HPHW_IOA) && ((id)->hversion == ASTRO_RUNWAY_PORT)) || \ - (((id)->hw_type == HPHW_BCPORT) && ((id)->hversion == ASTRO_ROPES_PORT)) \ -) +#define IS_ASTRO(id) \ +(((id)->hversion == ASTRO_RUNWAY_PORT) || ((id)->hversion == ASTRO_ROPES_PORT)) + +#define IS_IKE(id) \ +(((id)->hversion == IKE_MERCED_PORT) || ((id)->hversion == IKE_ROPES_PORT)) -#define CONFIG_FUNC_SIZE 4096 /* SBA configuration function reg set */ +#define SBA_FUNC_SIZE 4096 /* SBA configuration function reg set */ #define ASTRO_IOC_OFFSET 0x20000 /* Ike's IOC's occupy functions 2 and 3 (not 0 and 1) */ -#define IKE_IOC_OFFSET(p) ((p+2)*CONFIG_FUNC_SIZE) +#define IKE_IOC_OFFSET(p) ((p+2)*SBA_FUNC_SIZE) #define IOC_CTRL 0x8 /* IOC_CTRL offset */ -#define IOC_CTRL_TE (0x1 << 0) /* TOC Enable */ -#define IOC_CTRL_RM (0x1 << 8) /* Real Mode */ -#define IOC_CTRL_NC (0x1 << 9) /* Non Coherent Mode */ +#define IOC_CTRL_TC (1 << 0) /* TOC Enable */ +#define IOC_CTRL_CE (1 << 1) /* Coalesce Enable */ +#define IOC_CTRL_DE (1 << 2) /* Dillon Enable */ +#define IOC_CTRL_RM (1 << 8) /* Real Mode */ +#define IOC_CTRL_NC (1 << 9) /* Non Coherent Mode */ #define MAX_IOC 2 /* per Ike. Astro only has 1 */ @@ -233,18 +199,22 @@ struct ioc { - char *ioc_hpa; /* I/O MMU base address */ + unsigned long ioc_hpa; /* I/O MMU base address */ char *res_map; /* resource map, bit == pdir entry */ u64 *pdir_base; /* physical base address */ - unsigned long *res_hint; /* next available IOVP - circular search */ + unsigned long *res_hint; /* next avail IOVP - circular search */ + spinlock_t res_lock; + unsigned long hint_mask_pdir; /* bits used for DMA hints */ unsigned int res_bitshift; /* from the LEFT! */ unsigned int res_size; /* size of resource map in bytes */ unsigned int hint_shift_pdir; - spinlock_t res_lock; - unsigned long hint_mask_pdir; /* bits used for DMA hints */ -#ifdef DELAYED_RESOURCE_CNT - dma_addr_t res_delay[DELAYED_RESOURCE_CNT]; +#if DELAYED_RESOURCE_CNT > 0 + int saved_cnt; + struct sba_dma_pair { + dma_addr_t iova; + size_t size; + } saved[DELAYED_RESOURCE_CNT]; #endif #ifdef CONFIG_PROC_FS @@ -269,23 +239,32 @@ }; struct sba_device { - struct sba_device *next; /* list of LBA's in system */ - struct hp_device *iodc; /* data about dev from firmware */ - char *sba_hpa; /* base address */ + struct sba_device *next; /* list of SBA's in system */ + struct parisc_device *dev; /* dev found in bus walk */ + struct parisc_device_id *iodc; /* data about dev from firmware */ + const char *name; + unsigned long sba_hpa; /* base address */ spinlock_t sba_lock; - unsigned int flags; /* state/functionality enabled */ - unsigned int hw_rev; /* HW revision of chip */ + unsigned int flags; /* state/functionality enabled */ + unsigned int hw_rev; /* HW revision of chip */ - unsigned int num_ioc; /* number of on-board IOC's */ + unsigned int num_ioc; /* number of on-board IOC's */ struct ioc ioc[MAX_IOC]; }; static struct sba_device *sba_list; -static int sba_count; + +static unsigned long ioc_needs_fdc = 0; /* Ratio of Host MEM to IOV Space size */ -static unsigned long sba_mem_ratio = 4; +static unsigned long sba_mem_ratio = 8; + +/* global count of IOMMUs in the system */ +static unsigned int global_ioc_cnt = 0; + +/* PA8700 (Piranha 2.2) bug workaround */ +static unsigned long piranha_bad_128k = 0; /* Looks nice and keeps the compiler happy */ #define SBA_DEV(d) ((struct sba_device *) (d)) @@ -299,73 +278,75 @@ ** ** BE WARNED: register writes are posted. ** (ie follow writes which must reach HW with a read) +** +** Superdome (in particular, REO) allows only 64-bit CSR accesses. */ -#define READ_U8(addr) gsc_readb(addr) -#define READ_U16(addr) gsc_readw((u16 *) (addr)) -#define READ_U32(addr) gsc_readl((u32 *) (addr)) -#define WRITE_U8(value, addr) gsc_writeb(value, addr) -#define WRITE_U16(value, addr) gsc_writew(value, (u16 *) (addr)) -#define WRITE_U32(value, addr) gsc_writel(value, (u32 *) (addr)) - -#define READ_REG8(addr) gsc_readb(addr) -#define READ_REG16(addr) le16_to_cpu(gsc_readw((u16 *) (addr))) -#define READ_REG32(addr) le32_to_cpu(gsc_readl((u32 *) (addr))) -#define READ_REG64(addr) le64_to_cpu(gsc_readq((u64 *) (addr))) -#define WRITE_REG8(value, addr) gsc_writeb(value, addr) -#define WRITE_REG16(value, addr) gsc_writew(cpu_to_le16(value), (u16 *) (addr)) -#define WRITE_REG32(value, addr) gsc_writel(cpu_to_le32(value), (u32 *) (addr)) -#define WRITE_REG64(value, addr) gsc_writeq(cpu_to_le64(value), (u64 *) (addr)) +#define READ_REG32(addr) le32_to_cpu(__raw_readl(addr)) +#define READ_REG64(addr) le64_to_cpu(__raw_readq(addr)) +#define WRITE_REG32(val, addr) __raw_writel(cpu_to_le32(val), addr) +#define WRITE_REG64(val, addr) __raw_writeq(cpu_to_le64(val), addr) + +#ifdef __LP64__ +#define READ_REG(addr) READ_REG64(addr) +#define WRITE_REG(value, addr) WRITE_REG64(value, addr) +#else +#define READ_REG(addr) READ_REG32(addr) +#define WRITE_REG(value, addr) WRITE_REG32(value, addr) +#endif #ifdef DEBUG_SBA_INIT +/* NOTE: When __LP64__ isn't defined, READ_REG64() is two 32-bit reads */ + +/** + * sba_dump_ranges - debugging only - print ranges assigned to this IOA + * @hpa: base address of the sba + * + * Print the MMIO and IO Port address ranges forwarded by an Astro/Ike/RIO + * IO Adapter (aka Bus Converter). + */ static void -sba_dump_ranges(char *hpa) +sba_dump_ranges(unsigned long hpa) { - printk("SBA at 0x%p\n", hpa); - printk("IOS_DIST_BASE : %08x %08x\n", - READ_REG32(hpa+IOS_DIST_BASE+4), - READ_REG32(hpa+IOS_DIST_BASE)); - printk("IOS_DIST_MASK : %08x %08x\n", - READ_REG32(hpa+IOS_DIST_MASK+4), - READ_REG32(hpa+IOS_DIST_MASK)); - printk("IOS_DIST_ROUTE : %08x %08x\n", - READ_REG32(hpa+IOS_DIST_ROUTE+4), - READ_REG32(hpa+IOS_DIST_ROUTE)); - printk("\n"); - printk("IOS_DIRECT_BASE : %08x %08x\n", - READ_REG32(hpa+IOS_DIRECT_BASE+4), - READ_REG32(hpa+IOS_DIRECT_BASE)); - printk("IOS_DIRECT_MASK : %08x %08x\n", - READ_REG32(hpa+IOS_DIRECT_MASK+4), - READ_REG32(hpa+IOS_DIRECT_MASK)); - printk("IOS_DIRECT_ROUTE: %08x %08x\n", - READ_REG32(hpa+IOS_DIRECT_ROUTE+4), - READ_REG32(hpa+IOS_DIRECT_ROUTE)); + DBG_INIT("SBA at 0x%lx\n", hpa); + DBG_INIT("IOS_DIST_BASE : %Lx\n", READ_REG64(hpa+IOS_DIST_BASE)); + DBG_INIT("IOS_DIST_MASK : %Lx\n", READ_REG64(hpa+IOS_DIST_MASK)); + DBG_INIT("IOS_DIST_ROUTE : %Lx\n", READ_REG64(hpa+IOS_DIST_ROUTE)); + DBG_INIT("\n"); + DBG_INIT("IOS_DIRECT_BASE : %Lx\n", READ_REG64(hpa+IOS_DIRECT_BASE)); + DBG_INIT("IOS_DIRECT_MASK : %Lx\n", READ_REG64(hpa+IOS_DIRECT_MASK)); + DBG_INIT("IOS_DIRECT_ROUTE: %Lx\n", READ_REG64(hpa+IOS_DIRECT_ROUTE)); } +/** + * sba_dump_tlb - debugging only - print IOMMU operating parameters + * @hpa: base address of the IOMMU + * + * Print the size/location of the IO MMU PDIR. + */ static void -sba_dump_tlb(char *hpa) +sba_dump_tlb(unsigned long hpa) { - printk("IO TLB at 0x%p\n", hpa); - printk("IOC_IBASE : %08x %08x\n", - READ_REG32(hpa+IOC_IBASE+4), - READ_REG32(hpa+IOC_IBASE)); - printk("IOC_IMASK : %08x %08x\n", - READ_REG32(hpa+IOC_IMASK+4), - READ_REG32(hpa+IOC_IMASK)); - printk("IOC_TCNFG : %08x %08x\n", - READ_REG32(hpa+IOC_TCNFG+4), - READ_REG32(hpa+IOC_TCNFG)); - printk("IOC_PDIR_BASE: %08x %08x\n", - READ_REG32(hpa+IOC_PDIR_BASE+4), - READ_REG32(hpa+IOC_PDIR_BASE)); - printk("\n"); + DBG_INIT("IO TLB at 0x%lx\n", hpa); + DBG_INIT("IOC_IBASE : %Lx\n", READ_REG64(hpa+IOC_IBASE)); + DBG_INIT("IOC_IMASK : %Lx\n", READ_REG64(hpa+IOC_IMASK)); + DBG_INIT("IOC_TCNFG : %Lx\n", READ_REG64(hpa+IOC_TCNFG)); + DBG_INIT("IOC_PDIR_BASE: %Lx\n", READ_REG64(hpa+IOC_PDIR_BASE)); + DBG_INIT("\n"); } #endif #ifdef ASSERT_PDIR_SANITY +/** + * sba_dump_pdir_entry - debugging only - print one IOMMU PDIR entry + * @ioc: IO MMU structure which owns the pdir we are interested in. + * @msg: text to print ont the output line. + * @pide: pdir index. + * + * Print one entry of the IO MMU PDIR in human readable form. + */ static void sba_dump_pdir_entry(struct ioc *ioc, char *msg, uint pide) { @@ -374,24 +355,30 @@ unsigned long *rptr = (unsigned long *) &(ioc->res_map[(pide >>3) & ~(sizeof(unsigned long) - 1)]); uint rcnt; - printk("SBA: %s rp %p bit %d rval 0x%lx\n", + printk(KERN_DEBUG "SBA: %s rp %p bit %d rval 0x%lx\n", msg, rptr, pide & (BITS_PER_LONG - 1), *rptr); rcnt = 0; while (rcnt < BITS_PER_LONG) { - printk("%s %2d %p %016Lx\n", + printk(KERN_DEBUG "%s %2d %p %016Lx\n", (rcnt == (pide & (BITS_PER_LONG - 1))) ? " -->" : " ", rcnt, ptr, *ptr ); rcnt++; ptr++; } - printk(msg); + printk(KERN_DEBUG "%s", msg); } -/* Verify the resource map and pdir state is consistent */ +/** + * sba_check_pdir - debugging only - consistency checker + * @ioc: IO MMU structure which owns the pdir we are interested in. + * @msg: text to print ont the output line. + * + * Verify the resource map and pdir state is consistent + */ static int sba_check_pdir(struct ioc *ioc, char *msg) { @@ -428,15 +415,23 @@ } +/** + * sba_dump_sg - debugging only - print Scatter-Gather list + * @ioc: IO MMU structure which owns the pdir we are interested in. + * @startsg: head of the SG list + * @nents: number of entries in SG list + * + * print the SG list so we can verify it's correct by hand. + */ static void sba_dump_sg( struct ioc *ioc, struct scatterlist *startsg, int nents) { while (nents-- > 0) { - printk(" %d : %08lx/%05x %p/%05x\n", + printk(KERN_DEBUG " %d : %08lx/%05x %p/%05x\n", nents, (unsigned long) sg_dma_address(startsg), sg_dma_len(startsg), - startsg->address, startsg->length); + sg_virt_addr(startsg), startsg->length); startsg++; } } @@ -445,25 +440,6 @@ -/* -** One time initialization to let the world know the LBA was found. -** This is the only routine which is NOT static. -** Must be called exactly once before pci_init(). -*/ -void __init -sba_init(void) -{ - sba_list = (struct sba_device *) NULL; - sba_count = 0; - -#ifdef DEBUG_SBA_INIT - sba_dump_ranges((char *) 0xFED00000L); -#endif - - register_driver(sba_drivers_for); -} - - /************************************************************** * @@ -489,13 +465,15 @@ #define RESMAP_IDX_MASK (sizeof(unsigned long) - 1) -/* -** Perf optimizations: -** o search for log2(size) bits at a time. -** -** Search should use register width as "stride" to search the res_map. -*/ - +/** + * sba_search_bitmap - find free space in IO PDIR resource bitmap + * @ioc: IO MMU structure which owns the pdir we are interested in. + * @bits_wanted: number of entries we need. + * + * Find consecutive free bits in resource bitmap. + * Each bit represents one entry in the IO Pdir. + * Cool perf optimization: search for log2(size) bits at a time. + */ static SBA_INLINE unsigned long sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted) { @@ -512,7 +490,6 @@ *res_ptr = RESMAP_MASK(bits_wanted); pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map); pide <<= 3; /* convert to bit address */ - ASSERT(0 != pide); break; } } @@ -536,7 +513,7 @@ } mask = RESMAP_MASK(bits_wanted) >> bitshiftcnt; - DBG_RES("sba_search_bitmap() o %ld %p", o, res_ptr); + DBG_RES("%s() o %ld %p", __FUNCTION__, o, res_ptr); while(res_ptr < res_end) { DBG_RES(" %p %lx %lx\n", res_ptr, mask, *res_ptr); @@ -546,7 +523,6 @@ pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map); pide <<= 3; /* convert to bit address */ pide += bitshiftcnt; - ASSERT(0 != pide); break; } mask >>= o; @@ -562,11 +538,24 @@ } /* wrapped ? */ - ioc->res_hint = (res_end == res_ptr) ? (unsigned long *) ioc->res_map : res_ptr; + if (res_end <= res_ptr) { + ioc->res_hint = (unsigned long *) ioc->res_map; + ioc->res_bitshift = 0; + } else { + ioc->res_hint = res_ptr; + } return (pide); } +/** + * sba_alloc_range - find free bits and mark them in IO PDIR resource bitmap + * @ioc: IO MMU structure which owns the pdir we are interested in. + * @size: number of bytes to create a mapping for + * + * Given a size, find consecutive unmarked and then mark those bits in the + * resource bit map. + */ static int sba_alloc_range(struct ioc *ioc, size_t size) { @@ -577,8 +566,8 @@ unsigned long pide; ASSERT(pages_needed); - ASSERT((pages_needed * IOVP_SIZE) < DMA_CHUNK_SIZE); - ASSERT(pages_needed < BITS_PER_LONG); + ASSERT((pages_needed * IOVP_SIZE) <= DMA_CHUNK_SIZE); + ASSERT(pages_needed <= BITS_PER_LONG); ASSERT(0 == (size & ~IOVP_MASK)); /* @@ -590,7 +579,7 @@ if (pide >= (ioc->res_size << 3)) { pide = sba_search_bitmap(ioc, pages_needed); if (pide >= (ioc->res_size << 3)) - panic(__FILE__ ": I/O MMU @ %p is out of mapping resources\n", ioc->ioc_hpa); + panic(__FILE__ ": I/O MMU @ %lx is out of mapping resources\n", ioc->ioc_hpa); } #ifdef ASSERT_PDIR_SANITY @@ -600,8 +589,8 @@ } #endif - DBG_RES("sba_alloc_range(%x) %d -> %lx hint %x/%x\n", - size, pages_needed, pide, + DBG_RES("%s(%x) %d -> %lx hint %x/%x\n", + __FUNCTION__, size, pages_needed, pide, (uint) ((unsigned long) ioc->res_hint - (unsigned long) ioc->res_map), ioc->res_bitshift ); @@ -622,9 +611,14 @@ } -/* -** clear bits in the ioc's resource map -*/ +/** + * sba_free_range - unmark bits in IO PDIR resource bitmap + * @ioc: IO MMU structure which owns the pdir we are interested in. + * @iova: IO virtual address which was previously allocated. + * @size: number of bytes to create a mapping for + * + * clear bits in the ioc's resource map + */ static SBA_INLINE void sba_free_range(struct ioc *ioc, dma_addr_t iova, size_t size) { @@ -638,8 +632,8 @@ /* 3-bits "bit" address plus 2 (or 3) bits for "byte" == bit in word */ unsigned long m = RESMAP_MASK(bits_not_wanted) >> (pide & (BITS_PER_LONG - 1)); - DBG_RES("sba_free_range( ,%x,%x) %x/%lx %x %p %lx\n", - (uint) iova, size, + DBG_RES("%s( ,%x,%x) %x/%lx %x %p %lx\n", + __FUNCTION__, (uint) iova, size, bits_not_wanted, m, pide, res_ptr, *res_ptr); #ifdef CONFIG_PROC_FS @@ -648,8 +642,8 @@ ASSERT(m != 0); ASSERT(bits_not_wanted); - ASSERT((bits_not_wanted * IOVP_SIZE) < DMA_CHUNK_SIZE); - ASSERT(bits_not_wanted < BITS_PER_LONG); + ASSERT((bits_not_wanted * IOVP_SIZE) <= DMA_CHUNK_SIZE); + ASSERT(bits_not_wanted <= BITS_PER_LONG); ASSERT((*res_ptr & m) == m); /* verify same bits are set */ *res_ptr &= ~m; } @@ -667,31 +661,37 @@ typedef unsigned long space_t; #define KERNEL_SPACE 0 -/* -* SBA Mapping Routine -* -* Given a virtual address (vba, arg2) and space id, (sid, arg1) -* sba_io_pdir_entry() loads the I/O PDIR entry pointed to by -* pdir_ptr (arg0). Each IO Pdir entry consists of 8 bytes as -* shown below (MSB == bit 0): -* -* 0 19 51 55 63 -* +-+---------------------+----------------------------------+----+--------+ -* |V| U | PPN[43:12] | U | VI | -* +-+---------------------+----------------------------------+----+--------+ -* -* V == Valid Bit -* U == Unused -* PPN == Physical Page Number -* VI == Virtual Index (aka Coherent Index) -* -* The physical address fields are filled with the results of the LPA -* instruction. The virtual index field is filled with the results of -* of the LCI (Load Coherence Index) instruction. The 8 bits used for -* the virtual index are bits 12:19 of the value returned by LCI. -* -* We need to pre-swap the bytes since PCX-W is Big Endian. -*/ +/** + * sba_io_pdir_entry - fill in one IO PDIR entry + * @pdir_ptr: pointer to IO PDIR entry + * @sid: process Space ID + * @vba: Virtual CPU address of buffer to map + * + * SBA Mapping Routine + * + * Given a virtual address (vba, arg2) and space id, (sid, arg1) + * sba_io_pdir_entry() loads the I/O PDIR entry pointed to by + * pdir_ptr (arg0). Each IO Pdir entry consists of 8 bytes as + * shown below (MSB == bit 0): + * + * 0 19 51 55 63 + * +-+---------------------+----------------------------------+----+--------+ + * |V| U | PPN[43:12] | U | VI | + * +-+---------------------+----------------------------------+----+--------+ + * + * V == Valid Bit + * U == Unused + * PPN == Physical Page Number + * VI == Virtual Index (aka Coherent Index) + * + * The physical address fields are filled with the results of the LPA + * instruction. The virtual index field is filled with the results of + * of the LCI (Load Coherence Index) instruction. The 8 bits used for + * the virtual index are bits 12:19 of the value returned by LCI. + * + * We need to pre-swap the bytes since PCX-W is Big Endian. + */ + void SBA_INLINE sba_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba) @@ -699,9 +699,11 @@ u64 pa; /* physical address */ register unsigned ci; /* coherent index */ - /* We currently only support kernel addresses */ - ASSERT(sid == 0); - ASSERT(((unsigned long) vba & 0xc0000000UL) == 0xc0000000UL); + /* We currently only support kernel addresses. + * fdc instr below will need to reload sr1 with KERNEL_SPACE + * once we try to support direct DMA to user space. + */ + ASSERT(sid == KERNEL_SPACE); pa = virt_to_phys(vba); pa &= ~4095ULL; /* clear out offset bits */ @@ -712,25 +714,41 @@ pa |= 0x8000000000000000ULL; /* set "valid" bit */ *pdir_ptr = cpu_to_le64(pa); /* swap and store into I/O Pdir */ + + /* + * If the PDC_MODEL capabilities has Non-coherent IO-PDIR bit set + * (bit #61, big endian), we have to flush and sync every time + * IO-PDIR is changed in Ike/Astro. + */ + if (ioc_needs_fdc) { + asm volatile("fdc 0(%%sr1,%0)\n\tsync" : : "r" (pdir_ptr)); + } } -/*********************************************************** - * The Ike PCOM (Purge Command Register) is to purge - * stale entries in the IO TLB when unmapping entries. +/** + * sba_mark_invalid - invalidate one or more IO PDIR entries + * @ioc: IO MMU structure which owns the pdir we are interested in. + * @iova: IO Virtual Address mapped earlier + * @byte_cnt: number of bytes this mapping covers. + * + * Marking the IO PDIR entry(ies) as Invalid and invalidate + * corresponding IO TLB entry. The Ike PCOM (Purge Command Register) + * is to purge stale entries in the IO TLB when unmapping entries. * * The PCOM register supports purging of multiple pages, with a minium * of 1 page and a maximum of 2GB. Hardware requires the address be * aligned to the size of the range being purged. The size of the range - * must be a power of 2. - ***********************************************************/ + * must be a power of 2. The "Cool perf optimization" in the + * allocation routine helps keep that true. + */ static SBA_INLINE void sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt) { u32 iovp = (u32) SBA_IOVP(ioc,iova); /* Even though this is a big-endian machine, the entries - ** in the iopdir are swapped. That's why we clear the byte + ** in the iopdir are little endian. That's why we clear the byte ** at +7 instead of at +0. */ int off = PDIR_INDEX(iovp)*sizeof(u64)+7; @@ -775,32 +793,45 @@ } while (byte_cnt > 0); } - WRITE_REG32(iovp, ioc->ioc_hpa+IOC_PCOM); + WRITE_REG(iovp, ioc->ioc_hpa+IOC_PCOM); } +/** + * sba_dma_supported - PCI driver can query DMA support + * @dev: instance of PCI owned by the driver that's asking + * @mask: number of address bits this PCI device can handle + * + * See Documentation/DMA-mapping.txt + */ static int sba_dma_supported( struct pci_dev *dev, u64 mask) { if (dev == NULL) { - printk(MODULE_NAME ": EISA/ISA/et al not supported\n"); + printk(KERN_ERR MODULE_NAME ": EISA/ISA/et al not supported\n"); BUG(); return(0); } dev->dma_mask = mask; /* save it */ - /* only support PCI devices */ - return((int) (mask >= 0xffffffff)); + /* only support 32-bit PCI devices - no DAC support (yet) */ + return((int) (mask == 0xffffffff)); } -/* -** map_single returns a fully formed IOVA -*/ +/** + * sba_map_single - map one buffer and return IOVA for DMA + * @dev: instance of PCI owned by the driver that's asking. + * @addr: driver buffer to map. + * @size: number of bytes to map in driver buffer. + * @direction: R/W or both. + * + * See Documentation/DMA-mapping.txt + */ static dma_addr_t sba_map_single(struct pci_dev *dev, void *addr, size_t size, int direction) { - struct ioc *ioc = &sba_list->ioc[0]; /* FIXME : see Multi-IOC below */ + struct ioc *ioc; unsigned long flags; dma_addr_t iovp; dma_addr_t offset; @@ -808,9 +839,14 @@ int pide; ASSERT(size > 0); + ASSERT(size <= DMA_CHUNK_SIZE); + + ASSERT(dev->sysdata); + ioc = GET_IOC(dev); + ASSERT(ioc); /* save offset bits */ - offset = ((dma_addr_t) addr) & ~IOVP_MASK; + offset = ((dma_addr_t) (long) addr) & ~IOVP_MASK; /* round up to nearest IOVP_SIZE */ size = (size + offset + ~IOVP_MASK) & IOVP_MASK; @@ -827,7 +863,8 @@ pide = sba_alloc_range(ioc, size); iovp = (dma_addr_t) pide << IOVP_SHIFT; - DBG_RUN("sba_map_single() 0x%p -> 0x%lx", addr, (long) iovp | offset); + DBG_RUN("%s() 0x%p -> 0x%lx", + __FUNCTION__, addr, (long) iovp | offset); pdir_start = &(ioc->pdir_base[pide]); @@ -860,72 +897,85 @@ } +/** + * sba_unmap_single - unmap one IOVA and free resources + * @dev: instance of PCI owned by the driver that's asking. + * @iova: IOVA of driver buffer previously mapped. + * @size: number of bytes mapped in driver buffer. + * @direction: R/W or both. + * + * See Documentation/DMA-mapping.txt + */ static void sba_unmap_single(struct pci_dev *dev, dma_addr_t iova, size_t size, int direction) { -#ifdef FIXME -/* Multi-IOC (ie N-class) : need to lookup IOC from dev -** o If we can't know about lba PCI data structs, that eliminates ->sysdata. -** o walking up pcidev->parent dead ends at elroy too -** o leaves hashing dev->bus->number into some lookup. -** (may only work for N-class) -** o use (struct pci_hba) and put fields in there for DMA. -** (ioc and per device dma_hint.) -** -** Last one seems the clearest and most promising. -** sba_dma_supported() fill in those fields when the driver queries -** the system for support. -*/ - struct ioc *ioc = (struct ioc *) ((struct pci_hba *) (dev->sysdata))->dma_data; -#else - struct ioc *ioc = &sba_list->ioc[0]; + struct ioc *ioc; +#if DELAYED_RESOURCE_CNT > 0 + struct sba_dma_pair *d; #endif - unsigned long flags; dma_addr_t offset; + + ASSERT(dev->sysdata); + ioc = GET_IOC(dev); + ASSERT(ioc); + offset = iova & ~IOVP_MASK; - DBG_RUN("%s() iovp 0x%lx/%x\n", __FUNCTION__, (long) iova, size); + DBG_RUN("%s() iovp 0x%lx/%x\n", + __FUNCTION__, (long) iova, size); iova ^= offset; /* clear offset bits */ size += offset; size = ROUNDUP(size, IOVP_SIZE); - ASSERT(0 != iova); - spin_lock_irqsave(&ioc->res_lock, flags); + #ifdef CONFIG_PROC_FS ioc->usingle_calls++; ioc->usingle_pages += size >> IOVP_SHIFT; #endif -#ifdef DELAYED_RESOURCE_CNT - if (ioc->saved_cnt < DELAYED_RESOURCE_CNT) { - ioc->saved_iova[ioc->saved_cnt] = iova; - ioc->saved_size[ioc->saved_cnt] = size; - ioc_saved_cnt++; - } else { - do { -#endif - sba_mark_invalid(ioc, iova, size); - sba_free_range(ioc, iova, size); -#ifdef DELAYED_RESOURCE_CNT - ioc->saved_cnt--; - iova = ioc->saved_iova[ioc->saved_cnt]; - size = ioc->saved_size[ioc->saved_cnt]; - } while (ioc->saved_cnt) - - /* flush purges */ - (void) (volatile) READ_REG32(ioc->ioc_hpa+IOC_PCOM); +#if DELAYED_RESOURCE_CNT > 0 + d = &(ioc->saved[ioc->saved_cnt]); + d->iova = iova; + d->size = size; + if (++(ioc->saved_cnt) >= DELAYED_RESOURCE_CNT) { + int cnt = ioc->saved_cnt; + while (cnt--) { + sba_mark_invalid(ioc, d->iova, d->size); + sba_free_range(ioc, d->iova, d->size); + d--; + } + ioc->saved_cnt = 0; + READ_REG(ioc->ioc_hpa+IOC_PCOM); /* flush purges */ } -#else - /* flush purges */ - READ_REG32(ioc->ioc_hpa+IOC_PCOM); -#endif +#else /* DELAYED_RESOURCE_CNT == 0 */ + sba_mark_invalid(ioc, iova, size); + sba_free_range(ioc, iova, size); + READ_REG(ioc->ioc_hpa+IOC_PCOM); /* flush purges */ +#endif /* DELAYED_RESOURCE_CNT == 0 */ spin_unlock_irqrestore(&ioc->res_lock, flags); + + /* XXX REVISIT for 2.5 Linux - need syncdma for zero-copy support. + ** For Astro based systems this isn't a big deal WRT performance. + ** As long as 2.4 kernels copyin/copyout data from/to userspace, + ** we don't need the syncdma. The issue here is I/O MMU cachelines + ** are *not* coherent in all cases. May be hwrev dependent. + ** Need to investigate more. + asm volatile("syncdma"); + */ } +/** + * sba_alloc_consistent - allocate/map shared mem for DMA + * @hwdev: instance of PCI owned by the driver that's asking. + * @size: number of bytes mapped in driver buffer. + * @dma_handle: IOVA of new buffer. + * + * See Documentation/DMA-mapping.txt + */ static void * sba_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle) { @@ -948,6 +998,15 @@ } +/** + * sba_free_consistent - free/unmap shared mem for DMA + * @hwdev: instance of PCI owned by the driver that's asking. + * @size: number of bytes mapped in driver buffer. + * @vaddr: virtual address IOVA of "consistent" buffer. + * @dma_handler: IO virtual address of "consistent" buffer. + * + * See Documentation/DMA-mapping.txt + */ static void sba_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle) { @@ -955,27 +1014,6 @@ free_pages((unsigned long) vaddr, get_order(size)); } -/* -** Two address ranges are "virtually contiguous" iff: -** 1) end of prev == start of next, or... append case -** 3) end of next == start of prev prepend case -** -** and they are DMA contiguous *iff*: -** 2) end of prev and start of next are both on a page boundry -** -** (shift left is a quick trick to mask off upper bits) -*/ -#define DMA_CONTIG(__X, __Y) \ - (((((unsigned long) __X) | ((unsigned long) __Y)) << (BITS_PER_LONG - PAGE_SHIFT)) == 0UL) - -/* -** Assumption is two transactions are mutually exclusive. -** ie both go to different parts of memory. -** If both are true, then both transaction are on the same page. -*/ -#define DMA_SAME_PAGE(s1,e1,s2,e2) \ - ( ((((s1) ^ (s2)) >> PAGE_SHIFT) == 0) \ - && ((((e1) ^ (e2)) >> PAGE_SHIFT) == 0) ) /* ** Since 0 is a valid pdir_base index value, can't use that @@ -988,6 +1026,17 @@ int dump_run_sg = 0; #endif + +/** + * sba_fill_pdir - write allocated SG entries into IO PDIR + * @ioc: IO MMU structure which owns the pdir we are interested in. + * @startsg: list of IOVA/size pairs + * @nents: number of entries in startsg list + * + * Take preprocessed SG list and write corresponding entries + * in the IO PDIR. + */ + static SBA_INLINE int sba_fill_pdir( struct ioc *ioc, @@ -1006,16 +1055,16 @@ #ifdef DEBUG_LARGE_SG_ENTRIES if (dump_run_sg) - printk(" %d : %08lx/%05x %p/%05x\n", + printk(KERN_DEBUG " %2d : %08lx/%05x %p/%05x\n", nents, (unsigned long) sg_dma_address(startsg), cnt, - startsg->address, startsg->length + sg_virt_address(startsg), startsg->length ); #else DBG_RUN_SG(" %d : %08lx/%05x %p/%05x\n", nents, (unsigned long) sg_dma_address(startsg), cnt, - startsg->address, startsg->length + sg_virt_addr(startsg), startsg->length ); #endif /* @@ -1024,11 +1073,10 @@ if (sg_dma_address(startsg) & PIDE_FLAG) { u32 pide = sg_dma_address(startsg) & ~PIDE_FLAG; dma_offset = (unsigned long) pide & ~IOVP_MASK; - pide >>= IOVP_SHIFT; - pdirp = &(ioc->pdir_base[pide]); sg_dma_address(startsg) = 0; - ++dma_sg; - sg_dma_address(dma_sg) = (pide << IOVP_SHIFT) + dma_offset; + dma_sg++; + sg_dma_address(dma_sg) = pide; + pdirp = &(ioc->pdir_base[pide >> IOVP_SHIFT]); n_mappings++; } @@ -1036,9 +1084,12 @@ ** Look for a VCONTIG chunk */ if (cnt) { - unsigned long vaddr = (unsigned long) startsg->address; + unsigned long vaddr = (unsigned long) sg_virt_addr(startsg); ASSERT(pdirp); + /* Since multiple Vcontig blocks could make up + ** one DMA stream, *add* cnt to dma_len. + */ sg_dma_len(dma_sg) += cnt; cnt += dma_offset; dma_offset=0; /* only want offset on first chunk */ @@ -1062,133 +1113,142 @@ } - /* -** First pass is to walk the SG list and determine where the breaks are -** in the DMA stream. Allocates PDIR entries but does not fill them. -** Returns the number of DMA chunks. +** Two address ranges are DMA contiguous *iff* "end of prev" and +** "start of next" are both on a page boundry. ** -** Doing the fill seperate from the coalescing/allocation keeps the -** code simpler. Future enhancement could make one pass through -** the sglist do both. +** (shift left is a quick trick to mask off upper bits) */ +#define DMA_CONTIG(__X, __Y) \ + (((((unsigned long) __X) | ((unsigned long) __Y)) << (BITS_PER_LONG - PAGE_SHIFT)) == 0UL) + + +/** + * sba_coalesce_chunks - preprocess the SG list + * @ioc: IO MMU structure which owns the pdir we are interested in. + * @startsg: list of IOVA/size pairs + * @nents: number of entries in startsg list + * + * First pass is to walk the SG list and determine where the breaks are + * in the DMA stream. Allocates PDIR entries but does not fill them. + * Returns the number of DMA chunks. + * + * Doing the fill seperate from the coalescing/allocation keeps the + * code simpler. Future enhancement could make one pass through + * the sglist do both. + */ static SBA_INLINE int sba_coalesce_chunks( struct ioc *ioc, struct scatterlist *startsg, int nents) { + struct scatterlist *vcontig_sg; /* VCONTIG chunk head */ + unsigned long vcontig_len; /* len of VCONTIG chunk */ + unsigned long vcontig_end; + struct scatterlist *dma_sg; /* next DMA stream head */ + unsigned long dma_offset, dma_len; /* start/len of DMA stream */ int n_mappings = 0; while (nents > 0) { - struct scatterlist *dma_sg; /* next DMA stream head */ - unsigned long dma_offset, dma_len; /* start/len of DMA stream */ - struct scatterlist *chunksg; /* virtually contig chunk head */ - unsigned long chunk_addr, chunk_len; /* start/len of VCONTIG chunk */ + unsigned long vaddr = (unsigned long) sg_virt_addr(startsg); /* ** Prepare for first/next DMA stream */ - dma_sg = chunksg = startsg; - dma_len = chunk_len = startsg->length; - chunk_addr = (unsigned long) startsg->address; - dma_offset = 0UL; + dma_sg = vcontig_sg = startsg; + dma_len = vcontig_len = vcontig_end = startsg->length; + vcontig_end += vaddr; + dma_offset = vaddr & ~IOVP_MASK; + + /* PARANOID: clear entries */ + sg_dma_address(startsg) = 0; + sg_dma_len(startsg) = 0; /* ** This loop terminates one iteration "early" since ** it's always looking one "ahead". */ while (--nents > 0) { - /* ptr to coalesce prev and next */ - struct scatterlist *prev_sg = startsg; - unsigned long prev_end = (unsigned long) prev_sg->address + prev_sg->length; - unsigned long current_end; + unsigned long vaddr; /* tmp */ + + startsg++; /* PARANOID: clear entries */ sg_dma_address(startsg) = 0; sg_dma_len(startsg) = 0; - /* Now start looking ahead */ - startsg++; - current_end = (unsigned long) startsg->address + startsg->length; + /* catch brokenness in SCSI layer */ + ASSERT(startsg->length <= DMA_CHUNK_SIZE); /* - ** First look for virtually contiguous blocks. - ** PARISC needs this since it's cache is virtually - ** indexed and we need the associated virtual - ** address for each I/O address we map. - ** - ** 1) can we *prepend* the next transaction? + ** First make sure current dma stream won't + ** exceed DMA_CHUNK_SIZE if we coalesce the + ** next entry. */ - if (current_end == (unsigned long) prev_sg->address) - { - /* prepend : get new offset */ - chunksg = startsg; - chunk_addr = (unsigned long) prev_sg->address; - chunk_len += startsg->length; - dma_len += startsg->length; - continue; - } + if (((dma_len + dma_offset + startsg->length + ~IOVP_MASK) & IOVP_MASK) > DMA_CHUNK_SIZE) + break; /* - ** 2) or append the next transaction? + ** Then look for virtually contiguous blocks. + ** PARISC needs to associate a virtual address + ** with each IO address mapped. The CPU cache is + ** virtually tagged and the IOMMU uses part + ** of the virtual address to participate in + ** CPU cache coherency. + ** + ** append the next transaction? */ - if (prev_end == (unsigned long) startsg->address) + vaddr = (unsigned long) sg_virt_addr(startsg); + if (vcontig_end == vaddr) { - chunk_len += startsg->length; - dma_len += startsg->length; + vcontig_len += startsg->length; + vcontig_end += startsg->length; + dma_len += startsg->length; continue; } #ifdef DEBUG_LARGE_SG_ENTRIES - dump_run_sg = (chunk_len > IOVP_SIZE); + dump_run_sg = (vcontig_len > IOVP_SIZE); #endif + /* ** Not virtually contigous. ** Terminate prev chunk. ** Start a new chunk. ** - ** Once we start a new VCONTIG chunk, the offset + ** Once we start a new VCONTIG chunk, dma_offset ** can't change. And we need the offset from the first ** chunk - not the last one. Ergo Successive chunks ** must start on page boundaries and dove tail ** with it's predecessor. */ - sg_dma_len(prev_sg) = chunk_len; + sg_dma_len(vcontig_sg) = vcontig_len; - chunk_len = startsg->length; - dma_offset |= (chunk_addr & ~IOVP_MASK); - ASSERT((0 == (chunk_addr & ~IOVP_MASK)) || - (dma_offset == (chunk_addr & ~IOVP_MASK))); + vcontig_sg = startsg; + vcontig_len = startsg->length; -#if 0 /* - ** 4) do the chunks end/start on page boundaries? - ** Easier than 3 since no offsets are involved. + ** 3) do the entries end/start on page boundaries? + ** Don't update vcontig_end until we've checked. */ - if (DMA_CONTIG(prev_end, startsg->address)) + if (DMA_CONTIG(vcontig_end, vaddr)) { - /* - ** Yes. - ** Reset chunk ptr. - */ - chunksg = startsg; - chunk_addr = (unsigned long) startsg->address; - + vcontig_end = vcontig_len + vaddr; + dma_len += vcontig_len; continue; - } else -#endif - { + } else { break; } } /* ** End of DMA Stream - ** Terminate chunk. + ** Terminate last VCONTIG block. ** Allocate space for DMA stream. */ - sg_dma_len(startsg) = chunk_len; + sg_dma_len(vcontig_sg) = vcontig_len; dma_len = (dma_len + dma_offset + ~IOVP_MASK) & IOVP_MASK; + ASSERT(dma_len <= DMA_CHUNK_SIZE); sg_dma_address(dma_sg) = PIDE_FLAG | (sba_alloc_range(ioc, dma_len) << IOVP_SHIFT) @@ -1200,24 +1260,34 @@ } -/* -** And this algorithm still generally only ends up coalescing entries -** that happens to be on the same page due to how sglists are assembled. -*/ +/** + * sba_map_sg - map Scatter/Gather list + * @dev: instance of PCI owned by the driver that's asking. + * @sglist: array of buffer/length pairs + * @nents: number of entries in list + * @direction: R/W or both. + * + * See Documentation/DMA-mapping.txt + */ static int sba_map_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction) { - struct ioc *ioc = &sba_list->ioc[0]; /* FIXME : see Multi-IOC below */ + struct ioc *ioc; int coalesced, filled = 0; unsigned long flags; DBG_RUN_SG("%s() START %d entries\n", __FUNCTION__, nents); + ASSERT(dev->sysdata); + ioc = GET_IOC(dev); + ASSERT(ioc); + /* Fast path single entry scatterlists. */ if (nents == 1) { - sg_dma_address(sglist)= sba_map_single(dev, sglist->address, + sg_dma_address(sglist) = sba_map_single(dev, + sg_virt_addr(sglist), sglist->length, direction); - sg_dma_len(sglist)= sglist->length; + sg_dma_len(sglist) = sglist->length; return 1; } @@ -1272,16 +1342,29 @@ } +/** + * sba_unmap_sg - unmap Scatter/Gather list + * @dev: instance of PCI owned by the driver that's asking. + * @sglist: array of buffer/length pairs + * @nents: number of entries in list + * @direction: R/W or both. + * + * See Documentation/DMA-mapping.txt + */ static void sba_unmap_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction) { - struct ioc *ioc = &sba_list->ioc[0]; /* FIXME : see Multi-IOC below */ + struct ioc *ioc; #ifdef ASSERT_PDIR_SANITY unsigned long flags; #endif DBG_RUN_SG("%s() START %d entries, %p,%x\n", - __FUNCTION__, nents, sglist->address, sglist->length); + __FUNCTION__, nents, sg_virt_addr(sglist), sglist->length); + + ASSERT(dev->sysdata); + ioc = GET_IOC(dev); + ASSERT(ioc); #ifdef CONFIG_PROC_FS ioc->usg_calls++; @@ -1295,10 +1378,11 @@ while (sg_dma_len(sglist) && nents--) { + sba_unmap_single(dev, sg_dma_address(sglist), sg_dma_len(sglist), direction); #ifdef CONFIG_PROC_FS - ioc->usg_pages += sg_dma_len(sglist) >> PAGE_SHIFT; + ioc->usg_pages += ((sg_dma_address(sglist) & ~IOVP_MASK) + sg_dma_len(sglist) + IOVP_SIZE - 1) >> PAGE_SHIFT; + ioc->usingle_calls--; /* kluge since call is unmap_sg() */ #endif - sba_unmap_single(dev, sg_dma_address(sglist), sg_dma_len(sglist), direction); ++sglist; } @@ -1359,21 +1443,117 @@ * Initialization and claim * ***************************************************************/ +#define PIRANHA_ADDR_MASK 0x00160000UL /* bit 17,18,20 */ +#define PIRANHA_ADDR_VAL 0x00060000UL /* bit 17,18 on */ +static void * +sba_alloc_pdir(unsigned int pdir_size) +{ + unsigned long pdir_base; + unsigned long pdir_order = get_order(pdir_size); + + pdir_base = __get_free_pages(GFP_KERNEL, pdir_order); + if (NULL == (void *) pdir_base) + panic("sba_ioc_init() could not allocate I/O Page Table\n"); + + /* If this is not PA8700 (PCX-W2) + ** OR newer than ver 2.2 + ** OR in a system that doesn't need VINDEX bits from SBA, + ** + ** then we aren't exposed to the HW bug. + */ + if ( ((boot_cpu_data.pdc.cpuid >> 5) & 0x7f) != 0x13 + || (boot_cpu_data.pdc.versions > 0x202) + || (boot_cpu_data.pdc.capabilities & 0x08L) ) + return (void *) pdir_base; + + /* + * PA8700 (PCX-W2, aka piranha) silent data corruption fix + * + * An interaction between PA8700 CPU (Ver 2.2 or older) and + * Ike/Astro can cause silent data corruption. This is only + * a problem if the I/O PDIR is located in memory such that + * (little-endian) bits 17 and 18 are on and bit 20 is off. + * + * Since the max IO Pdir size is 2MB, by cleverly allocating the + * right physical address, we can either avoid (IOPDIR <= 1MB) + * or minimize (2MB IO Pdir) the problem if we restrict the + * IO Pdir to a maximum size of 2MB-128K (1902K). + * + * Because we always allocate 2^N sized IO pdirs, either of the + * "bad" regions will be the last 128K if at all. That's easy + * to test for. + * + */ + if (pdir_order <= (19-12)) { + if (((virt_to_phys(pdir_base)+pdir_size-1) & PIRANHA_ADDR_MASK) == PIRANHA_ADDR_VAL) { + /* allocate a new one on 512k alignment */ + unsigned long new_pdir = __get_free_pages(GFP_KERNEL, (19-12)); + /* release original */ + free_pages(pdir_base, pdir_order); + + pdir_base = new_pdir; + + /* release excess */ + while (pdir_order < (19-12)) { + new_pdir += pdir_size; + free_pages(new_pdir, pdir_order); + pdir_order +=1; + pdir_size <<=1; + } + } + } else { + /* + ** 1MB or 2MB Pdir + ** Needs to be aligned on an "odd" 1MB boundary. + */ + unsigned long new_pdir = __get_free_pages(GFP_KERNEL, pdir_order+1); /* 2 or 4MB */ + + /* release original */ + free_pages( pdir_base, pdir_order); + + /* release first 1MB */ + free_pages(new_pdir, 20-12); + + pdir_base = new_pdir + 1024*1024; + + if (pdir_order > (20-12)) { + /* + ** 2MB Pdir. + ** + ** Flag tells init_bitmap() to mark bad 128k as used + ** and to reduce the size by 128k. + */ + piranha_bad_128k = 1; + + new_pdir += 3*1024*1024; + /* release last 1MB */ + free_pages(new_pdir, 20-12); + + /* release unusable 128KB */ + free_pages(new_pdir - 128*1024 , 17-12); + + pdir_size -= 128*1024; + } + } + + memset((void *) pdir_base, 0, pdir_size); + return (void *) pdir_base; +} static void -sba_ioc_init(struct ioc *ioc) +sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num) { - extern unsigned long mem_max; /* arch.../setup.c */ - extern void lba_init_iregs(void *, u32, u32); /* arch.../lba_pci.c */ + /* lba_set_iregs() is in arch/parisc/kernel/lba_pci.c */ + extern void lba_set_iregs(struct parisc_device *, u32, u32); u32 iova_space_size, iova_space_mask; - void * pdir_base; int pdir_size, iov_order; + unsigned long physmem; + struct parisc_device *lba; /* ** Determine IOVA Space size from memory size. - ** Using "mem_max" is a kluge. ** ** Ideally, PCI drivers would register the maximum number ** of DMA they can have outstanding for each device they @@ -1385,20 +1565,24 @@ ** While we have 32-bits "IOVA" space, top two 2 bits are used ** for DMA hints - ergo only 30 bits max. */ + + physmem = num_physpages << PAGE_SHIFT; + iova_space_size = (u32) (physmem/(sba_mem_ratio*global_ioc_cnt)); + /* limit IOVA space size to 1MB-1GB */ - if (mem_max < (sba_mem_ratio*1024*1024)) { + if (iova_space_size < 1024*1024) { iova_space_size = 1024*1024; + } #ifdef __LP64__ - } else if (mem_max > (sba_mem_ratio*512*1024*1024)) { + else if (iova_space_size > 512*1024*1024) { iova_space_size = 512*1024*1024; -#endif - } else { - iova_space_size = (u32) (mem_max/sba_mem_ratio); } +#endif /* ** iova space must be log2() in size. ** thus, pdir/res_map will also be log2(). + ** PIRANHA BUG: Exception is when IO Pdir is 2MB (gets reduced) */ iov_order = get_order(iova_space_size >> (IOVP_SHIFT-PAGE_SHIFT)); ASSERT(iov_order <= (30 - IOVP_SHIFT)); /* iova_space_size <= 1GB */ @@ -1407,35 +1591,27 @@ ioc->pdir_size = pdir_size = (iova_space_size/IOVP_SIZE) * sizeof(u64); - ASSERT(pdir_size < 4*1024*1024); /* max pdir size < 4MB */ + ASSERT(pdir_size < 4*1024*1024); /* max pdir size == 2MB */ /* Verify it's a power of two */ ASSERT((1 << get_order(pdir_size)) == (pdir_size >> PAGE_SHIFT)); - DBG_INIT("%s() hpa 0x%p mem %dMBIOV %dMB (%d bits) PDIR size 0x%0x", - __FUNCTION__, ioc->ioc_hpa, (int) (mem_max>>20), + DBG_INIT("%s() hpa 0x%lx mem %dMB IOV %dMB (%d bits) PDIR size 0x%0x\n", + __FUNCTION__, ioc->ioc_hpa, (int) (physmem>>20), iova_space_size>>20, iov_order + PAGE_SHIFT, pdir_size); /* FIXME : DMA HINTs not used */ ioc->hint_shift_pdir = iov_order + PAGE_SHIFT; ioc->hint_mask_pdir = ~(0x3 << (iov_order + PAGE_SHIFT)); - ioc->pdir_base = - pdir_base = (void *) __get_free_pages(GFP_KERNEL, get_order(pdir_size)); - if (NULL == pdir_base) - { - panic(__FILE__ ":%s() could not allocate I/O Page Table\n", __FUNCTION__); - } - memset(pdir_base, 0, pdir_size); + ioc->pdir_base = sba_alloc_pdir(pdir_size); - DBG_INIT("sba_ioc_init() pdir %p size %x hint_shift_pdir %x hint_mask_pdir %lx\n", - pdir_base, pdir_size, + DBG_INIT("%s() pdir %p size %x hint_shift_pdir %x hint_mask_pdir %lx\n", + __FUNCTION__, ioc->pdir_base, pdir_size, ioc->hint_shift_pdir, ioc->hint_mask_pdir); - ASSERT((((unsigned long) pdir_base) & PAGE_MASK) == (unsigned long) pdir_base); - WRITE_REG64(virt_to_phys(pdir_base), (u64 *)(ioc->ioc_hpa+IOC_PDIR_BASE)); - - DBG_INIT(" base %p\n", pdir_base); + ASSERT((((unsigned long) ioc->pdir_base) & PAGE_MASK) == (unsigned long) ioc->pdir_base); + WRITE_REG64(virt_to_phys(ioc->pdir_base), ioc->ioc_hpa + IOC_PDIR_BASE); /* build IMASK for IOC and Elroy */ iova_space_mask = 0xffffffff; @@ -1448,8 +1624,8 @@ ioc->ibase = IOC_IOVA_SPACE_BASE | 1; /* bit 0 == enable bit */ ioc->imask = iova_space_mask; /* save it */ - DBG_INIT("%s() IOV base 0x%lx mask 0x%0lx\n", __FUNCTION__, - ioc->ibase, ioc->imask); + DBG_INIT("%s() IOV base 0x%lx mask 0x%0lx\n", + __FUNCTION__, ioc->ibase, ioc->imask); /* ** FIXME: Hint registers are programmed with default hint @@ -1460,22 +1636,26 @@ /* ** setup Elroy IBASE/IMASK registers as well. */ - lba_init_iregs(ioc->ioc_hpa, ioc->ibase, ioc->imask); + for (lba = sba->child; lba; lba = lba->sibling) { + int rope_num = (lba->hpa >> 13) & 0xf; + if (rope_num >> 3 == ioc_num) + lba_set_iregs(lba, ioc->ibase, ioc->imask); + } /* ** Program the IOC's ibase and enable IOVA translation */ - WRITE_REG32(ioc->ibase, ioc->ioc_hpa+IOC_IBASE); - WRITE_REG32(ioc->imask, ioc->ioc_hpa+IOC_IMASK); + WRITE_REG(ioc->ibase, ioc->ioc_hpa+IOC_IBASE); + WRITE_REG(ioc->imask, ioc->ioc_hpa+IOC_IMASK); /* Set I/O PDIR Page size to 4K */ - WRITE_REG32(0, ioc->ioc_hpa+IOC_TCNFG); + WRITE_REG(0, ioc->ioc_hpa+IOC_TCNFG); /* ** Clear I/O TLB of any possible entries. - ** (Yes. This is a it paranoid...but so what) + ** (Yes. This is a bit paranoid...but so what) */ - WRITE_REG32(0 | 31, ioc->ioc_hpa+IOC_PCOM); + WRITE_REG(0 | 31, ioc->ioc_hpa+IOC_PCOM); DBG_INIT("%s() DONE\n", __FUNCTION__); } @@ -1498,23 +1678,24 @@ { int i; int num_ioc; - u32 ioc_ctl; + u64 ioc_ctl; + + ioc_ctl = READ_REG(sba_dev->sba_hpa+IOC_CTRL); + DBG_INIT("%s() hpa 0x%lx ioc_ctl 0x%Lx ->", + __FUNCTION__, sba_dev->sba_hpa, ioc_ctl); + ioc_ctl &= ~(IOC_CTRL_RM | IOC_CTRL_NC | IOC_CTRL_CE); + ioc_ctl |= IOC_CTRL_TC; /* Astro: firmware enables this */ - ioc_ctl = READ_REG32(sba_dev->sba_hpa+IOC_CTRL); - DBG_INIT("%s() hpa 0x%p ioc_ctl 0x%x ->", __FUNCTION__, sba_dev->sba_hpa, ioc_ctl ); - ioc_ctl &= ~(IOC_CTRL_RM | IOC_CTRL_NC); - ASSERT(ioc_ctl & IOC_CTRL_TE); /* astro: firmware enables this */ - - WRITE_REG32(ioc_ctl, sba_dev->sba_hpa+IOC_CTRL); - -#ifdef SBA_DEBUG_INIT - ioc_ctl = READ_REG32(sba_dev->sba_hpa+IOC_CTRL); - DBG_INIT(" 0x%x\n", ioc_ctl ); + WRITE_REG(ioc_ctl, sba_dev->sba_hpa+IOC_CTRL); + +#ifdef DEBUG_SBA_INIT + ioc_ctl = READ_REG64(sba_dev->sba_hpa+IOC_CTRL); + DBG_INIT(" 0x%Lx\n", ioc_ctl); #endif if (IS_ASTRO(sba_dev->iodc)) { /* PAT_PDC (L-class) also reports the same goofy base */ - sba_dev->ioc[0].ioc_hpa = (char *) ASTRO_IOC_OFFSET; + sba_dev->ioc[0].ioc_hpa = ASTRO_IOC_OFFSET; num_ioc = 1; } else { sba_dev->ioc[0].ioc_hpa = sba_dev->ioc[1].ioc_hpa = 0; @@ -1522,26 +1703,25 @@ } sba_dev->num_ioc = num_ioc; - for( i = 0; i < num_ioc; i++) - { - (unsigned long) sba_dev->ioc[i].ioc_hpa += (unsigned long) sba_dev->sba_hpa + IKE_IOC_OFFSET(i); + for (i = 0; i < num_ioc; i++) { + sba_dev->ioc[i].ioc_hpa += sba_dev->sba_hpa + IKE_IOC_OFFSET(i); /* ** Make sure the box crashes if we get any errors on a rope. */ - WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE0_CTL); - WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE1_CTL); - WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE2_CTL); - WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE3_CTL); - WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE4_CTL); - WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE5_CTL); - WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE6_CTL); - WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE7_CTL); + WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE0_CTL); + WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE1_CTL); + WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE2_CTL); + WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE3_CTL); + WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE4_CTL); + WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE5_CTL); + WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE6_CTL); + WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE7_CTL); /* flush out the writes */ - READ_REG32(sba_dev->ioc[i].ioc_hpa + ROPE7_CTL); + READ_REG(sba_dev->ioc[i].ioc_hpa + ROPE7_CTL); - sba_ioc_init(&(sba_dev->ioc[i])); + sba_ioc_init(sba_dev->dev, &(sba_dev->ioc[i]), i); } } @@ -1555,11 +1735,10 @@ */ sba_dev->next = sba_list; sba_list = sba_dev; - sba_count++; for(i=0; i< sba_dev->num_ioc; i++) { int res_size; -#ifdef CONFIG_DMB_TRAP +#ifdef DEBUG_DMB_TRAP extern void iterate_pages(unsigned long , unsigned long , void (*)(pte_t * , unsigned long), unsigned long ); @@ -1567,13 +1746,20 @@ #endif /* resource map size dictated by pdir_size */ res_size = sba_dev->ioc[i].pdir_size/sizeof(u64); /* entries */ + + /* Second part of PIRANHA BUG */ + if (piranha_bad_128k) { + res_size -= (128*1024)/sizeof(u64); + } + res_size >>= 3; /* convert bit count to byte count */ - DBG_INIT("%s() res_size 0x%x\n", __FUNCTION__, res_size); + DBG_INIT("%s() res_size 0x%x\n", + __FUNCTION__, res_size); sba_dev->ioc[i].res_size = res_size; sba_dev->ioc[i].res_map = (char *) __get_free_pages(GFP_KERNEL, get_order(res_size)); -#ifdef CONFIG_DMB_TRAP +#ifdef DEBUG_DMB_TRAP iterate_pages( sba_dev->ioc[i].res_map, res_size, set_data_memory_break, 0); #endif @@ -1594,39 +1780,66 @@ sba_dev->ioc[i].pdir_base[0] = 0xeeffc0addbba0080ULL; #endif -#ifdef CONFIG_DMB_TRAP + /* Third (and last) part of PIRANHA BUG */ + if (piranha_bad_128k) { + /* region from +1408K to +1536 is un-usable. */ + + int idx_start = (1408*1024/sizeof(u64)) >> 3; + int idx_end = (1536*1024/sizeof(u64)) >> 3; + long *p_start = (long *) &(sba_dev->ioc[i].res_map[idx_start]); + long *p_end = (long *) &(sba_dev->ioc[i].res_map[idx_end]); + + /* mark that part of the io pdir busy */ + while (p_start < p_end) + *p_start++ = -1; + + } + +#ifdef DEBUG_DMB_TRAP iterate_pages( sba_dev->ioc[i].res_map, res_size, set_data_memory_break, 0); iterate_pages( sba_dev->ioc[i].pdir_base, sba_dev->ioc[i].pdir_size, set_data_memory_break, 0); #endif - DBG_INIT("sba_common_init() %d res_map %x %p\n", - i, res_size, sba_dev->ioc[i].res_map); + DBG_INIT("%s() %d res_map %x %p\n", + __FUNCTION__, i, res_size, sba_dev->ioc[i].res_map); } sba_dev->sba_lock = SPIN_LOCK_UNLOCKED; + ioc_needs_fdc = boot_cpu_data.pdc.capabilities & PDC_MODEL_IOPDIR_FDC; + +#ifdef DEBUG_SBA_INIT + /* + * If the PDC_MODEL capabilities has Non-coherent IO-PDIR bit set + * (bit #61, big endian), we have to flush and sync every time + * IO-PDIR is changed in Ike/Astro. + */ + if (boot_cpu_data.pdc.capabilities & PDC_MODEL_IOPDIR_FDC) { + printk(KERN_INFO MODULE_NAME " FDC/SYNC required.\n"); + } else { + printk(KERN_INFO MODULE_NAME " IOC has cache coherent PDIR.\n"); + } +#endif } #ifdef CONFIG_PROC_FS static int sba_proc_info(char *buf, char **start, off_t offset, int len) { struct sba_device *sba_dev = sba_list; -/* FIXME: Multi-IOC support broken! */ - struct ioc *ioc = &sba_dev->ioc[0]; + struct ioc *ioc = &sba_dev->ioc[0]; /* FIXME: Multi-IOC support! */ int total_pages = (int) (ioc->res_size << 3); /* 8 bits per byte */ unsigned long i = 0, avg = 0, min, max; sprintf(buf, "%s rev %d.%d\n", - parisc_getHWdescription(sba_dev->iodc->hw_type, - sba_dev->iodc->hversion, sba_dev->iodc->sversion), + sba_dev->name, (sba_dev->hw_rev & 0x7) + 1, (sba_dev->hw_rev & 0x18) >> 3 ); sprintf(buf, "%sIO PDIR size : %d bytes (%d entries)\n", buf, - ((ioc->res_size << 3) * sizeof(u64)), /* 8 bits per byte */ - total_pages); /* 8 bits per byte */ + (int) ((ioc->res_size << 3) * sizeof(u64)), /* 8 bits/byte */ + total_pages); sprintf(buf, "%sIO PDIR entries : %ld free %ld used (%d%%)\n", buf, total_pages - ioc->used_pages, ioc->used_pages, @@ -1645,46 +1858,72 @@ sprintf(buf, "%s Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n", buf, min, avg, max); - sprintf(buf, "%spci_map_single(): %8ld calls %8ld pages (avg %d/1000)\n", + sprintf(buf, "%spci_map_single(): %12ld calls %12ld pages (avg %d/1000)\n", buf, ioc->msingle_calls, ioc->msingle_pages, (int) ((ioc->msingle_pages * 1000)/ioc->msingle_calls)); /* KLUGE - unmap_sg calls unmap_single for each mapped page */ - min = ioc->usingle_calls - ioc->usg_calls; + min = ioc->usingle_calls; max = ioc->usingle_pages - ioc->usg_pages; - sprintf(buf, "%spci_unmap_single: %8ld calls %8ld pages (avg %d/1000)\n", + sprintf(buf, "%spci_unmap_single: %12ld calls %12ld pages (avg %d/1000)\n", buf, min, max, (int) ((max * 1000)/min)); - sprintf(buf, "%spci_map_sg() : %8ld calls %8ld pages (avg %d/1000)\n", + sprintf(buf, "%spci_map_sg() : %12ld calls %12ld pages (avg %d/1000)\n", buf, ioc->msg_calls, ioc->msg_pages, (int) ((ioc->msg_pages * 1000)/ioc->msg_calls)); - sprintf(buf, "%spci_unmap_sg() : %8ld calls %8ld pages (avg %d/1000)\n", + sprintf(buf, "%spci_unmap_sg() : %12ld calls %12ld pages (avg %d/1000)\n", buf, ioc->usg_calls, ioc->usg_pages, (int) ((ioc->usg_pages * 1000)/ioc->usg_calls)); return strlen(buf); } +#if 0 +/* XXX too much output - exceeds 4k limit and needs to be re-written */ static int sba_resource_map(char *buf, char **start, off_t offset, int len) { struct sba_device *sba_dev = sba_list; - struct ioc *ioc = &sba_dev->ioc[0]; - unsigned long *res_ptr = (unsigned long *)ioc->res_map; + struct ioc *ioc = &sba_dev->ioc[0]; /* FIXME: Mutli-IOC suppoer! */ + unsigned int *res_ptr = (unsigned int *)ioc->res_map; int i; - for(i = 0; i < (ioc->res_size / sizeof(unsigned long)); ++i, ++res_ptr) { + buf[0] = '\0'; + for(i = 0; i < (ioc->res_size / sizeof(unsigned int)); ++i, ++res_ptr) { if ((i & 7) == 0) strcat(buf,"\n "); - sprintf(buf, "%s %08lx", buf, *res_ptr); + sprintf(buf, "%s %08x", buf, *res_ptr); } strcat(buf, "\n"); return strlen(buf); } -#endif +#endif /* 0 */ +#endif /* CONFIG_PROC_FS */ + +static struct parisc_device_id sba_tbl[] = { + { HPHW_IOA, HVERSION_REV_ANY_ID, ASTRO_RUNWAY_PORT, 0xb }, + { HPHW_BCPORT, HVERSION_REV_ANY_ID, IKE_MERCED_PORT, 0xc }, + { HPHW_BCPORT, HVERSION_REV_ANY_ID, REO_MERCED_PORT, 0xc }, + { HPHW_BCPORT, HVERSION_REV_ANY_ID, REOG_MERCED_PORT, 0xc }, +/* These two entries commented out because we don't find them in a + * buswalk yet. If/when we do, they would cause us to think we had + * many more SBAs then we really do. + * { HPHW_BCPORT, HVERSION_REV_ANY_ID, ASTRO_ROPES_PORT, 0xc }, + * { HPHW_BCPORT, HVERSION_REV_ANY_ID, IKE_ROPES_PORT, 0xc }, + */ + { 0, } +}; + +int sba_driver_callback(struct parisc_device *); + +static struct parisc_driver sba_driver = { + name: MODULE_NAME, + id_table: sba_tbl, + probe: sba_driver_callback, +}; /* ** Determine if lba should claim this chip (return 0) or not (return 1). @@ -1692,47 +1931,75 @@ ** have work to do. */ int -sba_driver_callback(struct hp_device *d, struct pa_iodc_driver *dri) +sba_driver_callback(struct parisc_device *dev) { struct sba_device *sba_dev; u32 func_class; int i; + char *version; - if (IS_ASTRO(d)) { +#ifdef DEBUG_SBA_INIT + sba_dump_ranges(dev->hpa); +#endif + + /* Read HW Rev First */ + func_class = READ_REG(dev->hpa + SBA_FCLASS); + + if (IS_ASTRO(&dev->id)) { + unsigned long fclass; static char astro_rev[]="Astro ?.?"; - /* Read HW Rev First */ - func_class = READ_REG32(d->hpa); + /* Astro is broken...Read HW Rev First */ + fclass = READ_REG(dev->hpa); - astro_rev[6] = '1' + (char) (func_class & 0x7); - astro_rev[8] = '0' + (char) ((func_class & 0x18) >> 3); - dri->version = astro_rev; - } else { - static char ike_rev[]="Ike rev ?"; + astro_rev[6] = '1' + (char) (fclass & 0x7); + astro_rev[8] = '0' + (char) ((fclass & 0x18) >> 3); + version = astro_rev; - /* Read HW Rev First */ - func_class = READ_REG32(d->hpa + SBA_FCLASS); + } else if (IS_IKE(&dev->id)) { + static char ike_rev[]="Ike rev ?"; ike_rev[8] = '0' + (char) (func_class & 0xff); - dri->version = ike_rev; + version = ike_rev; + } else { + static char reo_rev[]="REO rev ?"; + + reo_rev[8] = '0' + (char) (func_class & 0xff); + version = reo_rev; + } + + if (!global_ioc_cnt) { + global_ioc_cnt = count_parisc_driver(&sba_driver); + + /* Only Astro has one IOC per SBA */ + if (!IS_ASTRO(&dev->id)) + global_ioc_cnt *= 2; } - printk("%s found %s at 0x%p\n", dri->name, dri->version, d->hpa); + printk(KERN_INFO "%s found %s at 0x%lx\n", + MODULE_NAME, version, dev->hpa); + +#ifdef DEBUG_SBA_INIT + sba_dump_tlb(dev->hpa); +#endif sba_dev = kmalloc(sizeof(struct sba_device), GFP_KERNEL); - if (NULL == sba_dev) - { - printk(MODULE_NAME " - couldn't alloc sba_device\n"); + if (NULL == sba_dev) { + printk(KERN_ERR MODULE_NAME " - couldn't alloc sba_device\n"); return(1); } + + dev->sysdata = (void *) sba_dev; memset(sba_dev, 0, sizeof(struct sba_device)); + for(i=0; iioc[i].res_lock)); - + sba_dev->dev = dev; sba_dev->hw_rev = func_class; - sba_dev->iodc = d; - sba_dev->sba_hpa = d->hpa; /* faster access */ + sba_dev->iodc = &dev->id; + sba_dev->name = dev->name; + sba_dev->sba_hpa = dev->hpa; /* faster access */ sba_get_pat_resources(sba_dev); sba_hw_init(sba_dev); @@ -1741,12 +2008,46 @@ hppa_dma_ops = &sba_ops; #ifdef CONFIG_PROC_FS - if (IS_ASTRO(d)) { + if (IS_ASTRO(&dev->id)) { create_proc_info_entry("Astro", 0, proc_runway_root, sba_proc_info); - } else { + } else if (IS_IKE(&dev->id)) { create_proc_info_entry("Ike", 0, proc_runway_root, sba_proc_info); + } else { + create_proc_info_entry("Reo", 0, proc_runway_root, sba_proc_info); } +#if 0 create_proc_info_entry("bitmap", 0, proc_runway_root, sba_resource_map); #endif +#endif return 0; } + +/* +** One time initialization to let the world know the SBA was found. +** This is the only routine which is NOT static. +** Must be called exactly once before pci_init(). +*/ +void __init sba_init(void) +{ + register_parisc_driver(&sba_driver); +} + + +/** + * sba_get_iommu - Assign the iommu pointer for the pci bus controller. + * @dev: The parisc device. + * + * This function searches through the registerd IOMMU's and returns the + * appropriate IOMMU data for the given parisc PCI controller. + */ +void * sba_get_iommu(struct parisc_device *pci_hba) +{ + struct sba_device *sba = (struct sba_device *) pci_hba->parent->sysdata; + char t = pci_hba->parent->id.hw_type; + int iocnum = (pci_hba->hw_path >> 3); /* rope # */ + + if ((t!=HPHW_IOA) && (t!=HPHW_BCPORT)) + BUG(); + + return &(sba->ioc[iocnum]); +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/semaphore.c linux.19rc3-ac4/arch/parisc/kernel/semaphore.c --- linux.19rc3/arch/parisc/kernel/semaphore.c 2002-07-29 12:50:06.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/semaphore.c 2002-07-29 13:58:37.000000000 +0100 @@ -1,131 +1,100 @@ /* - * Just taken from alpha implementation. - * This can't work well, perhaps. - */ -/* - * Generic semaphore code. Buyer beware. Do your own - * specific changes in + * Semaphore implementation Copyright (c) 2001 Matthew Wilcox, Hewlett-Packard */ #include -#include +#include /* - * Semaphores are implemented using a two-way counter: - * The "count" variable is decremented for each process - * that tries to sleep, while the "waking" variable is - * incremented when the "up()" code goes to wake up waiting - * processes. - * - * Notably, the inline "up()" and "down()" functions can - * efficiently test if they need to do any extra work (up - * needs to do something only if count was negative before - * the increment operation. - * - * waking_non_zero() (from asm/semaphore.h) must execute - * atomically. - * - * When __up() is called, the count was negative before - * incrementing it, and we need to wake up somebody. - * - * This routine adds one to the count of processes that need to - * wake up and exit. ALL waiting processes actually wake up but - * only the one that gets to the "waking" field first will gate - * through and acquire the semaphore. The others will go back - * to sleep. - * - * Note that these functions are only called when there is - * contention on the lock, and as such all this is the - * "non-critical" part of the whole semaphore business. The - * critical part is the inline stuff in - * where we want to avoid any extra jumps and calls. + * Semaphores are complex as we wish to avoid using two variables. + * `count' has multiple roles, depending on its value. If it is positive + * or zero, there are no waiters. The functions here will never be + * called; see + * + * When count is -1 it indicates there is at least one task waiting + * for the semaphore. + * + * When count is less than that, there are '- count - 1' wakeups + * pending. ie if it has value -3, there are 2 wakeups pending. + * + * Note that these functions are only called when there is contention + * on the lock, and as such all this is the "non-critical" part of the + * whole semaphore business. The critical part is the inline stuff in + * where we want to avoid any extra jumps and calls. */ void __up(struct semaphore *sem) { - wake_one_more(sem); + sem->count--; wake_up(&sem->wait); } -/* - * Perform the "down" function. Return zero for semaphore acquired, - * return negative for signalled out of the function. - * - * If called from __down, the return is ignored and the wait loop is - * not interruptible. This means that a task waiting on a semaphore - * using "down()" cannot be killed until someone does an "up()" on - * the semaphore. - * - * If called from __down_interruptible, the return value gets checked - * upon return. If the return value is negative then the task continues - * with the negative value in the return register (it can be tested by - * the caller). - * - * Either form may be used in conjunction with "up()". - * - */ - +#define wakers(count) (-1 - count) -#define DOWN_HEAD(task_state) \ +#define DOWN_HEAD \ + int ret = 0; \ + DECLARE_WAITQUEUE(wait, current); \ \ + /* Note that someone is waiting */ \ + if (sem->count == 0) \ + sem->count = -1; \ \ - current->state = (task_state); \ - add_wait_queue(&sem->wait, &wait); \ - \ - /* \ - * Ok, we're set up. sem->count is known to be less than zero \ - * so we must wait. \ - * \ - * We can let go the lock for purposes of waiting. \ - * We re-acquire it after awaking so as to protect \ - * all semaphore operations. \ - * \ - * If "up()" is called before we call waking_non_zero() then \ - * we will catch it right away. If it is called later then \ - * we will have to go through a wakeup cycle to catch it. \ - * \ - * Multiple waiters contend for the semaphore lock to see \ - * who gets to gate through and who has to wait some more. \ - */ \ - for (;;) { - -#define DOWN_TAIL(task_state) \ - current->state = (task_state); \ - } \ - current->state = TASK_RUNNING; \ - remove_wait_queue(&sem->wait, &wait); + /* protected by the sentry still -- use unlocked version */ \ + wait.flags = WQ_FLAG_EXCLUSIVE; \ + __add_wait_queue_tail(&sem->wait, &wait); \ + lost_race: \ + spin_unlock_irq(&sem->sentry); \ + +#define DOWN_TAIL \ + spin_lock_irq(&sem->sentry); \ + if (wakers(sem->count) == 0 && ret == 0) \ + goto lost_race; /* Someone stole our wakeup */ \ + __remove_wait_queue(&sem->wait, &wait); \ + current->state = TASK_RUNNING; \ + if (!waitqueue_active(&sem->wait) && (sem->count < 0)) \ + sem->count = wakers(sem->count); + +#define UPDATE_COUNT \ + sem->count += (sem->count < 0) ? 1 : - 1; + void __down(struct semaphore * sem) { - DECLARE_WAITQUEUE(wait, current); + DOWN_HEAD + + for(;;) { + set_task_state(current, TASK_UNINTERRUPTIBLE); + /* we can _read_ this without the sentry */ + if (sem->count != -1) + break; + schedule(); + } - DOWN_HEAD(TASK_UNINTERRUPTIBLE) - if (waking_non_zero(sem)) - break; - schedule(); - DOWN_TAIL(TASK_UNINTERRUPTIBLE) + DOWN_TAIL + UPDATE_COUNT } int __down_interruptible(struct semaphore * sem) { - DECLARE_WAITQUEUE(wait, current); - int ret = 0; + DOWN_HEAD - DOWN_HEAD(TASK_INTERRUPTIBLE) + for(;;) { + set_task_state(current, TASK_INTERRUPTIBLE); + /* we can _read_ this without the sentry */ + if (sem->count != -1) + break; + + if (signal_pending(current)) { + ret = -EINTR; + break; + } + schedule(); + } - ret = waking_non_zero_interruptible(sem, current); - if (ret) - { - if (ret == 1) - /* ret != 0 only if we get interrupted -arca */ - ret = 0; - break; + DOWN_TAIL + + if (!ret) { + UPDATE_COUNT } - schedule(); - DOWN_TAIL(TASK_INTERRUPTIBLE) - return ret; -} -int __down_trylock(struct semaphore * sem) -{ - return waking_non_zero_trylock(sem); + return ret; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/setup.c linux.19rc3-ac4/arch/parisc/kernel/setup.c --- linux.19rc3/arch/parisc/kernel/setup.c 2002-07-29 12:50:07.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/setup.c 2002-07-29 13:58:37.000000000 +0100 @@ -1,12 +1,13 @@ /* $Id: setup.c,v 1.8 2000/02/02 04:42:38 prumpf Exp $ * * Initial setup-routines for HP 9000 based hardware. - * + * * Copyright (C) 1991, 1992, 1995 Linus Torvalds - * Modifications for PA-RISC (C) 1999 Helge Deller + * Modifications for PA-RISC (C) 1999 Helge Deller * Modifications copyright 1999 SuSE GmbH (Philipp Rumpf) * Modifications copyright 2000 Martin K. Petersen * Modifications copyright 2000 Philipp Rumpf + * Modifications copyright 2001 Ryan Bradetich * * Initial PA-RISC Version: 04-23-1999 by Helge Deller * @@ -19,596 +20,308 @@ * 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 -#include -#include -#include -#include +#include +#include /* for initrd_start and initrd_end */ #include -#include #include -#include -#include +#include +#define PCI_DEBUG #include -#include +#undef PCI_DEBUG +#include -#include -#include /* for register_driver() stuff */ #include -#include #include #include -#include -#include #include /* for pa7300lc_init() proto */ -#include /* for struct irq_region */ -#include /* for PA_VIEW PDC_PAT_CPU_GET_NUMBER etc */ - -#include - #define COMMAND_LINE_SIZE 1024 char saved_command_line[COMMAND_LINE_SIZE]; +char command_line[COMMAND_LINE_SIZE]; -/* -** KLUGE ALERT! -** -** We *really* should be using a combination of request_resource() -** and request_region()! But request_region() requires kmalloc since -** returns a new struct resource. And kmalloc just isn't available -** until after mem_init() is called from start_kernel(). -** -** FIXME: assume contiguous memory initially. -** Additional chunks of memory might be added to sysram_resource.sibling. -*/ -static struct resource sysrom_resource = { - name: "System ROM", start: 0x0f0000000UL, end: 0x0f00fffffUL, - flags: IORESOURCE_BUSY | IORESOURCE_MEM, - parent: &iomem_resource, sibling: NULL, child: NULL }; - -static struct resource pdcdata_resource; - -static struct resource sysram_resource = { - name: "System RAM", start: 0UL, end: ~0UL /* bogus */, - flags: IORESOURCE_MEM, - parent: &iomem_resource, sibling: &sysrom_resource, child: &pdcdata_resource}; - -extern char _text; /* start of kernel code, defined by linker */ -extern int data_start; -extern char _edata; /* end of data, begin BSS, defined by linker */ -extern char _end; /* end of BSS, defined by linker */ - -static struct resource data_resource = { - name: "kernel Data", start: virt_to_phys(&data_start), end: virt_to_phys(&_end)-1, - flags: IORESOURCE_BUSY | IORESOURCE_MEM, - parent: &sysram_resource, sibling: NULL, child: NULL}; - -static struct resource code_resource = { - name: "Kernel Code", start: virt_to_phys(&_text), end: virt_to_phys(&data_start)-1, - flags: IORESOURCE_BUSY | IORESOURCE_MEM, - parent: &sysram_resource, sibling: &data_resource, child: NULL}; - -static struct resource pdcdata_resource = { - name: "PDC data (Page Zero)", start: 0, end: 0x9ff, - flags: IORESOURCE_BUSY | IORESOURCE_MEM, - parent: &sysram_resource, sibling: &code_resource, child: NULL}; - - +/* Intended for ccio/sba/cpu statistics under /proc/bus/{runway|gsc} */ +struct proc_dir_entry * proc_runway_root = NULL; +struct proc_dir_entry * proc_gsc_root = NULL; +#ifdef CONFIG_EISA +int EISA_bus; /* This has to go somewhere in architecture specific code. */ +#endif -struct system_cpuinfo_parisc boot_cpu_data; -struct cpuinfo_parisc cpu_data[NR_CPUS]; - -extern void do_inventory(void); -extern void cache_init(void); -extern struct hp_device * register_module(void *hpa); - -static int cpu_driver_callback(struct hp_device *, struct pa_iodc_driver *); - -static struct pa_iodc_driver cpu_drivers_for[] = { - {HPHW_NPROC, 0x0, 0x0, 0x0, 0, 0, - DRIVER_CHECK_HWTYPE, - "CPU", "PARISC", (void *) cpu_driver_callback}, - {0,0,0,0,0,0, - 0, - (char *) NULL, (char *) NULL, (void *) NULL } -}; +void __init setup_cmdline(char **cmdline_p) +{ + extern unsigned int boot_args[]; -static long fallback_cpu_hpa[] = { 0xfffa0000L, 0xfffbe000L, 0x0 }; + /* Collect stuff passed in from the boot loader */ + /* boot_args[0] is free-mem start, boot_args[1] is ptr to command line */ + if (boot_args[0] < 64) { + /* called from hpux boot loader */ + saved_command_line[0] = '\0'; + } else { + strcpy(saved_command_line, (char *)__va(boot_args[1])); -/* -** PARISC CPU driver - claim "device" and initialize CPU data structures. -** -** Consolidate per CPU initialization into (mostly) one module. -** Monarch CPU will initialize boot_cpu_data which shouldn't -** change once the system has booted. -** -** The callback *should* do per-instance initialization of -** everything including the monarch. Some of the code that's -** in setup.c:start_parisc() should migrate here and start_parisc() -** should "register_driver(cpu_driver_for)" before calling -** do_inventory(). -** -** The goal of consolidating CPU initialization into one place is -** to make sure all CPU's get initialized the same way. -** It would be nice if the even the manarch through the exact same code path. -** (up to rendevous at least). -*/ -#undef ASSERT -#define ASSERT(expr) \ - if(!(expr)) { \ - printk( "\n" __FILE__ ":%d: Assertion " #expr " failed!\n",__LINE__); \ - panic(#expr); \ +#ifdef CONFIG_BLK_DEV_INITRD + if (boot_args[2] != 0) /* did palo pass us a ramdisk? */ + { + initrd_start = (unsigned long)__va(boot_args[2]); + initrd_end = (unsigned long)__va(boot_args[3]); + } +#endif } -static int -cpu_driver_callback(struct hp_device *d, struct pa_iodc_driver *dri) + strcpy(command_line, saved_command_line); + *cmdline_p = command_line; +} + +#ifdef CONFIG_PA11 +void __init dma_ops_init(void) { -#ifdef __LP64__ - extern int pdc_pat; /* arch/parisc/kernel/inventory.c */ - static unsigned long pdc_result[32] __attribute__ ((aligned (8))) = {0,0,0,0}; -#endif - struct cpuinfo_parisc *p; + switch (boot_cpu_data.cpu_type) { + case pcx: + /* + * We've got way too many dependencies on 1.1 semantics + * to support 1.0 boxes at this point. + */ + panic( "PA-RISC Linux currently only supports machines that conform to\n" + "the PA-RISC 1.1 or 2.0 architecture specification.\n"); -#ifndef CONFIG_SMP - if (boot_cpu_data.cpu_count > 0) { - printk(KERN_INFO "CONFIG_SMP disabled - not claiming addional CPUs\n"); - return(1); + case pcxs: + case pcxt: + hppa_dma_ops = &pcx_dma_ops; + break; + case pcxl2: + pa7300lc_init(); + case pcxl: /* falls through */ + hppa_dma_ops = &pcxl_dma_ops; + break; + default: + break; } +} #endif - p = &cpu_data[boot_cpu_data.cpu_count]; - boot_cpu_data.cpu_count++; - -/* TODO: Enable FP regs - done early in start_parisc() now */ - - /* initialize counters */ - memset(p, 0, sizeof(struct cpuinfo_parisc)); +extern int init_per_cpu(int cpuid); +extern void collect_boot_cpu_data(void); - p->hpa = (unsigned long) d->hpa; /* save CPU hpa */ +void __init setup_arch(char **cmdline_p) +{ + init_per_cpu(smp_processor_id()); /* Set Modes & Enable FP */ #ifdef __LP64__ - if (pdc_pat) { - ulong status; - pdc_pat_cell_mod_maddr_block_t pa_pdc_cell; - - status = pdc_pat_cell_module(& pdc_result, d->pcell_loc, - d->mod_index, PA_VIEW, & pa_pdc_cell); - - ASSERT(PDC_RET_OK == status); - - /* verify it's the same as what do_pat_inventory() found */ - ASSERT(d->mod_info == pa_pdc_cell.mod_info); - ASSERT(d->pmod_loc == pa_pdc_cell.mod_location); - ASSERT(d->mod_path == pa_pdc_cell.mod_path); - - p->txn_addr = pa_pdc_cell.mod[0]; /* id_eid for IO sapic */ - - /* get the cpu number */ - status = mem_pdc_call( PDC_PAT_CPU, PDC_PAT_CPU_GET_NUMBER, - __pa(& pdc_result), d->hpa); + printk(KERN_INFO "The 64-bit Kernel has started...\n"); +#else + printk(KERN_INFO "The 32-bit Kernel has started...\n"); +#endif - ASSERT(PDC_RET_OK == status); + pdc_console_init(); - p->cpuid = pdc_result[0]; +#ifdef CONFIG_PDC_NARROW + printk(KERN_INFO "Kernel is using PDC in 32-bit mode.\n"); +#endif + setup_pdc(); + setup_cmdline(cmdline_p); + collect_boot_cpu_data(); + do_memory_inventory(); /* probe for physical memory */ + cache_init(); + paging_init(); - } else +#ifdef CONFIG_CHASSIS_LCD_LED + /* initialize the LCD/LED after boot_cpu_data is available ! */ + led_init(); /* LCD/LED initialization */ #endif - { - p->txn_addr = (unsigned long) d->hpa; /* for normal parisc */ - /* logical CPU ID and update global counter */ - p->cpuid = boot_cpu_data.cpu_count - 1; - } +#ifdef CONFIG_PA11 + dma_ops_init(); +#endif - /* - ** itimer and ipi IRQ handlers are statically initialized in - ** arch/parisc/kernel/irq.c - */ - p->region = irq_region[IRQ_FROM_REGION(CPU_IRQ_REGION)]; +#ifdef CONFIG_VT +# if defined(CONFIG_STI_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE) + conswitchp = &dummy_con; /* we use take_over_console() later ! */ +# endif +#endif - return(0); } +/* + * Display cpu info for all cpu's. + * for parisc this is in processor.c + */ +extern int show_cpuinfo (struct seq_file *m, void *v); -void __xchg_called_with_bad_pointer(void) +static void * +c_start (struct seq_file *m, loff_t *pos) { - printk(KERN_EMERG "xchg() called with bad pointer !\n"); + /* Looks like the caller will call repeatedly until we return + * 0, signaling EOF perhaps. This could be used to sequence + * through CPUs for example. Since we print all cpu info in our + * show_cpuinfo() disregarding 'pos' (which I assume is 'v' above) + * we only allow for one "position". */ + return ((long)*pos < 1) ? (void *)1 : NULL; } - -/* Some versions of IODC don't list the CPU, and since we don't walk - * the bus yet, we have to probe for processors at well known hpa - * addresses. - */ - -void __init register_fallback_cpu (void) +static void * +c_next (struct seq_file *m, void *v, loff_t *pos) { - struct hp_device *d = NULL; - int i = 0; - -#ifdef CONFIG_SMP -#error "Revisit CPU fallback addresses for SMP (Assuming bus walk hasn't been implemented)" -#endif - printk ("No CPUs reported by firmware - probing...\n"); - - while (fallback_cpu_hpa[i]) { - - d = register_module ((void *) fallback_cpu_hpa[i]); - - if (d > 0) { - printk ("Found CPU at %lx\n", fallback_cpu_hpa[i]); - cpu_driver_callback (d, 0); - return; - } - - i++; - } - - panic ("No CPUs found. System halted.\n"); - return; + ++*pos; + return c_start(m, pos); } - -/* - * Get CPU information and store it in the boot_cpu_data structure. */ -void __init collect_boot_cpu_data(void) +static void +c_stop (struct seq_file *m, void *v) { - memset(&boot_cpu_data,0,sizeof(boot_cpu_data)); - - boot_cpu_data.cpu_hz = 100 * PAGE0->mem_10msec; /* Hz of this PARISC */ - - /* get CPU-Model Information... */ -#define p ((unsigned long *)&boot_cpu_data.pdc.model) - if(pdc_model_info(&boot_cpu_data.pdc.model)==0) - printk("model %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", - p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8]); -#undef p - - if(pdc_model_versions(&boot_cpu_data.pdc.versions, 0)==0) - printk("vers %08lx\n", boot_cpu_data.pdc.versions.cpuid); - - if(pdc_model_cpuid(&boot_cpu_data.pdc.cpuid)==0) - printk("cpuid %08lx\n", boot_cpu_data.pdc.cpuid.cpuid); - - printk("CPUID vers %ld rev %ld\n", - (boot_cpu_data.pdc.cpuid.cpuid >> 5) & 127, - boot_cpu_data.pdc.cpuid.cpuid & 31); - - if (pdc_model_sysmodel(boot_cpu_data.pdc.sys_model_name)==0) - printk("model %s\n",boot_cpu_data.pdc.sys_model_name); - - boot_cpu_data.model_name = parisc_getHWdescription(HPHW_NPROC, - boot_cpu_data.pdc.model.hversion>>4, - boot_cpu_data.pdc.model.sversion>>8); - - boot_cpu_data.hversion = boot_cpu_data.pdc.model.hversion; - boot_cpu_data.sversion = boot_cpu_data.pdc.model.sversion; - - boot_cpu_data.cpu_type = - parisc_get_cpu_type(boot_cpu_data.pdc.model.hversion); - - boot_cpu_data.cpu_name = cpu_name_version[boot_cpu_data.cpu_type][0]; - boot_cpu_data.family_name = cpu_name_version[boot_cpu_data.cpu_type][1]; } +struct seq_operations cpuinfo_op = { + start: c_start, + next: c_next, + stop: c_stop, + show: show_cpuinfo +}; -#ifdef __LP64__ -#define COMMAND_GLOBAL 0xfffffffffffe0030UL -#else -#define COMMAND_GLOBAL 0xfffe0030 -#endif - -#define CMD_RESET 5 /* reset any module */ - -/* -** The Wright Brothers and Gecko systems have a H/W problem -** (Lasi...'nuf said) may cause a broadcast reset to lockup -** the system. An HVERSION dependent PDC call was developed -** to perform a "safe", platform specific broadcast reset instead -** of kludging up all the code. -** -** Older machines which do not implement PDC_BROADCAST_RESET will -** return (with an error) and the regular broadcast reset can be -** issued. Obviously, if the PDC does implement PDC_BROADCAST_RESET -** the PDC call will not return (the system will be reset). -*/ -static int -reset_parisc(struct notifier_block *self, unsigned long command, void *ptr) +static void parisc_proc_mkdir(void) { - printk("%s: %s(cmd=%lu)\n", __FILE__, __FUNCTION__, command); - - switch(command) { - case MACH_RESTART: -#ifdef FASTBOOT_SELFTEST_SUPPORT - /* - ** If user has modified the Firmware Selftest Bitmap, - ** run the tests specified in the bitmap after the - ** system is rebooted w/PDC_DO_RESET. - ** - ** ftc_bitmap = 0x1AUL "Skip destructive memory tests" - ** - ** Using "directed resets" at each processor with the MEM_TOC - ** vector cleared will also avoid running destructive - ** memory self tests. (Not implemented yet) - */ - if (ftc_bitmap) { - mem_pdc_call( PDC_BROADCAST_RESET, - PDC_DO_FIRM_TEST_RESET, PDC_FIRM_TEST_MAGIC, - ftc_bitmap); + /* + ** Can't call proc_mkdir() until after proc_root_init() has been + ** called by start_kernel(). In other words, this code can't + ** live in arch/.../setup.c because start_parisc() calls + ** start_kernel(). + */ + switch (boot_cpu_data.cpu_type) { + case pcxl: + case pcxl2: + if (NULL == proc_gsc_root) + { + proc_gsc_root = proc_mkdir("bus/gsc", 0); } -#endif - - /* "Normal" system reset */ - (void) mem_pdc_call(PDC_BROADCAST_RESET, PDC_DO_RESET, - 0L, 0L, 0L); - - /* Nope...box should reset with just CMD_RESET now */ - gsc_writel(CMD_RESET, COMMAND_GLOBAL); - - /* Wait for RESET to lay us to rest. */ - while (1) ; - break; + case pcxt_: + case pcxu: + case pcxu_: + case pcxw: + case pcxw_: + case pcxw2: + if (NULL == proc_runway_root) + { + proc_runway_root = proc_mkdir("bus/runway", 0); + } + break; } - return NOTIFY_DONE; } -static struct notifier_block parisc_block = { reset_parisc, NULL, 0 }; +static struct resource central_bus = { + name: "Central Bus", + start: (unsigned long)0xfffffffffff80000, + end: (unsigned long)0xfffffffffffaffff, + flags: IORESOURCE_MEM, +}; +static struct resource local_broadcast = { + name: "Local Broadcast", + start: (unsigned long)0xfffffffffffb0000, + end: (unsigned long)0xfffffffffffdffff, + flags: IORESOURCE_MEM, +}; -/* start_parisc() will be called from head.S to setup our new memory_start - and actually start our kernel ! - Memory-Layout is: - - Kernel-Image (code+data+BSS) - - Stack (stack-size see below!, stack-setup-code is in head.S) - - memory_start at end of stack.. -*/ - -unsigned long mem_start, mem_max; -unsigned long start_pfn, max_pfn; -extern asmlinkage void __init start_kernel(void); - -#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) -#define PFN_DOWN(x) ((x) >> PAGE_SHIFT) -#define PFN_PHYS(x) ((x) << PAGE_SHIFT) +static struct resource global_broadcast = { + name: "Global Broadcast", + start: (unsigned long)0xfffffffffffe0000, + end: (unsigned long)0xffffffffffffffff, + flags: IORESOURCE_MEM, +}; -void __init start_parisc(unsigned arg0, unsigned arg1, - unsigned arg2, unsigned arg3) +int __init parisc_init_resources(void) { - register unsigned long ccr; - unsigned long memory_start; - - /* Clear BSS */ + int result; - { - char *p = &_edata, *q = &_end; - - while (p < q) { - *p++ = 0; - } + result = request_resource(&iomem_resource, ¢ral_bus); + if (result < 0) { + printk(KERN_ERR + "%s: failed to claim %s address space!\n", + __FILE__, central_bus.name); + return result; } - - pdc_console_init(); - -#ifdef __LP64__ - printk("The 64-bit Kernel has started...\n"); -#else - printk("The 32-bit Kernel has started...\n"); -#endif - - /* - ** Enable FP coprocessor - ** - ** REVISIT: ccr should be set by PDC_COPROC results to support PA1.0. - ** Hardcoding works for PA1.1 processors. - ** - ** REVISIT: this could be done in the "code 22" trap handler. - ** (frowands idea - that way we know which processes need FP - ** registers saved on the interrupt stack.) - ** - ** NEWS FLASH: wide kernels need FP coprocessor enabled to handle - ** formatted printing of %lx for example (double divides I think) - */ - ccr = 0xc0; - mtctl(ccr, 10); - printk("Enabled FP coprocessor\n"); - -#ifdef __LP64__ - printk( "If this is the LAST MESSAGE YOU SEE, you're probably using\n" - "32-bit millicode by mistake.\n"); -#endif - - memory_start = (unsigned long) &_end; - memory_start = (memory_start + PAGE_SIZE) & PAGE_MASK; - printk("Free memory starts at: 0x%lx\n", memory_start); - - /* Collect stuff passed in from the boot loader */ - printk(KERN_WARNING "%s(0x%x,0x%x,0x%x,0x%x)\n", - __FUNCTION__, arg0, arg1, arg2, arg3); - - /* arg0 is free-mem start, arg1 is ptr to command line */ - if (arg0 < 64) { - /* called from hpux boot loader */ - saved_command_line[0] = '\0'; - } else { - strcpy(saved_command_line, (char *)__va(arg1)); - printk("PALO command line: '%s'\nPALO initrd %x-%x\n", - saved_command_line, arg2, arg3); - -#ifdef CONFIG_BLK_DEV_INITRD - if (arg2 != 0) /* did palo pass us a ramdisk? */ - { - initrd_start = (unsigned long)__va(arg2); - initrd_end = (unsigned long)__va(arg3); - } -#endif + result = request_resource(&iomem_resource, &local_broadcast); + if (result < 0) { + printk(KERN_ERR + "%s: failed to claim %saddress space!\n", + __FILE__, local_broadcast.name); + return result; } - mem_start = __pa(memory_start); -#define MAX_MEM (512*1024*1024) - mem_max = (PAGE0->imm_max_mem > MAX_MEM ? MAX_MEM : PAGE0->imm_max_mem); - - collect_boot_cpu_data(); + result = request_resource(&iomem_resource, &global_broadcast); + if (result < 0) { + printk(KERN_ERR + "%s: failed to claim %s address space!\n", + __FILE__, global_broadcast.name); + return result; + } - /* initialize the LCD/LED after boot_cpu_data is available ! */ - led_init(); /* LCD/LED initialization */ + return 0; +} - do_inventory(); /* probe for hardware */ - register_driver(cpu_drivers_for); /* claim all the CPUs */ +extern void gsc_init(void); +extern void processor_init(void); +extern void ccio_init(void); +extern void dino_init(void); +extern void iosapic_init(void); +extern void lba_init(void); +extern void sba_init(void); +extern void eisa_init(void); - if (boot_cpu_data.cpu_count == 0) - register_fallback_cpu(); +void __init parisc_init(void) +{ + parisc_proc_mkdir(); + parisc_init_resources(); + do_device_inventory(); /* probe for hardware */ - printk("CPU(s): %d x %s at %d.%06d MHz\n", + processor_init(); + printk(KERN_INFO "CPU(s): %d x %s at %d.%06d MHz\n", boot_cpu_data.cpu_count, boot_cpu_data.cpu_name, - boot_cpu_data.cpu_hz / 1000000, + boot_cpu_data.cpu_hz / 1000000, boot_cpu_data.cpu_hz % 1000000 ); - switch (boot_cpu_data.cpu_type) { - case pcx: - case pcxs: - case pcxt: - hppa_dma_ops = &pcx_dma_ops; - break; - case pcxl2: - pa7300lc_init(); - case pcxl: /* falls through */ - hppa_dma_ops = &pcxl_dma_ops; - break; - default: - break; - } - -#if 1 - /* KLUGE! this really belongs in kernel/resource.c! */ - iomem_resource.end = ~0UL; -#endif - sysram_resource.end = mem_max - 1; - notifier_chain_register(&mach_notifier, &parisc_block); - start_kernel(); /* now back to arch-generic code... */ -} - -void __init setup_arch(char **cmdline_p) -{ - unsigned long bootmap_size; - unsigned long start_pfn; - unsigned long mem_free; - - *cmdline_p = saved_command_line; - - /* initialize bootmem */ - - start_pfn = PFN_UP(mem_start); - max_pfn = PFN_DOWN(mem_max); - - bootmap_size = init_bootmem(start_pfn, max_pfn); - - mem_start += bootmap_size; - mem_free = mem_max - mem_start; - - /* free_bootmem handles rounding nicely */ - printk("free_bootmem(0x%lx, 0x%lx)\n", (unsigned long)mem_start, - (unsigned long)mem_free); - free_bootmem(mem_start, mem_free); - -#ifdef CONFIG_BLK_DEV_INITRD - printk("initrd: %08x-%08x\n", (int) initrd_start, (int) initrd_end); - - if (initrd_end != 0) { - initrd_below_start_ok = 1; - reserve_bootmem(__pa(initrd_start), initrd_end - initrd_start); - } + /* These are in a non-obvious order, will fix when we have an iotree */ +#if defined(CONFIG_IOSAPIC) + iosapic_init(); #endif - - cache_init(); - - paging_init(); - - if((unsigned long)&init_task_union&(INIT_TASK_SIZE - 1)) { - printk("init_task_union not aligned. Please recompile the kernel after changing the first line in arch/parisc/kernel/init_task.c from \n\"#define PAD 0\" to\n\"#define PAD 1\" or vice versa\n"); - for(;;); - } - - -#ifdef CONFIG_SERIAL_CONSOLE - /* nothing */ -#elif CONFIG_VT -#if defined(CONFIG_STI_CONSOLE) - conswitchp = &dummy_con; /* we use take_over_console() later ! */ -#elif defined(CONFIG_IODC_CONSOLE) - conswitchp = &prom_con; /* it's currently really "prom_con" */ -#elif defined(CONFIG_DUMMY_CONSOLE) - conswitchp = &dummy_con; +#if defined(CONFIG_IOMMU_SBA) + sba_init(); #endif +#if defined(CONFIG_PCI_LBA) + lba_init(); #endif -} - -#ifdef CONFIG_PROC_FS -/* - * Get CPU information for use by procfs. - */ - -int get_cpuinfo(char *buffer) -{ - char *p = buffer; - int n; + /* CCIO before any potential subdevices */ +#if defined(CONFIG_IOMMU_CCIO) + ccio_init(); +#endif - for(n=0; n +#include +#include +#include +#include +#include +#include +#include + +#include +#include "sys32.h" + +struct k_sigaction32 { + struct sigaction32 sa; +}; + +typedef unsigned int old_sigset_t32; + +static int +put_old_sigset32(old_sigset_t32 *up, old_sigset_t *set) +{ + old_sigset_t32 set32 = *set; + return put_user(set32, up); +} + +static int +get_old_segset32(old_sigset_t32 *up, old_sigset_t *set) +{ + old_sigset_t32 set32; + int r; + + if ((r = get_user(set32, up)) == 0) + *set = set32; + + return r; +} + +long +sys32_sigpending(old_sigset_t32 *set) +{ + extern long sys_sigpending(old_sigset_t *set); + old_sigset_t pending; + int ret; + + KERNEL_SYSCALL(ret, sys_sigpending, &pending); + + /* can't put_user an old_sigset_t -- it is too big */ + if (put_old_sigset32(set, &pending)) + return -EFAULT; + + return ret; +} + +int sys32_sigprocmask(int how, old_sigset_t32 *set, + old_sigset_t32 *oset) +{ + extern int sys_sigprocmask(int how, old_sigset_t *set, + old_sigset_t *oset); + old_sigset_t s; + int ret; + + if (set && get_old_segset32 (set, &s)) + return -EFAULT; + KERNEL_SYSCALL(ret, sys_sigprocmask, how, set ? &s : NULL, oset ? &s : NULL); + if (!ret && oset && put_old_sigset32(oset, &s)) + return -EFAULT; + return ret; +} + +static inline void +sigset_32to64(sigset_t *s64, sigset_t32 *s32) +{ + s64->sig[0] = s32->sig[0] | ((unsigned long)s32->sig[1] << 32); +} + +static inline void +sigset_64to32(sigset_t32 *s32, sigset_t *s64) +{ + s32->sig[0] = s64->sig[0] & 0xffffffffUL; + s32->sig[1] = (s64->sig[0] >> 32) & 0xffffffffUL; +} + +static int +put_sigset32(sigset_t32 *up, sigset_t *set, size_t sz) +{ + sigset_t32 s; + + if (sz != sizeof *set) panic("put_sigset32()"); + sigset_64to32(&s, set); + + return copy_to_user(up, &s, sizeof s); +} + +static int +get_sigset32(sigset_t32 *up, sigset_t *set, size_t sz) +{ + sigset_t32 s; + int r; + + if (sz != sizeof *set) panic("put_sigset32()"); + + if ((r = copy_from_user(&s, up, sz)) == 0) { + sigset_32to64(set, &s); + } + + return r; +} + +int sys32_rt_sigprocmask(int how, sigset_t32 *set, sigset_t32 *oset, + unsigned int sigsetsize) +{ + extern long sys_rt_sigprocmask(int how, + sigset_t *set, sigset_t *oset, + size_t sigsetsize); + sigset_t old_set, new_set; + int ret; + + if (set && get_sigset32(set, &new_set, sigsetsize)) + return -EFAULT; + + KERNEL_SYSCALL(ret, sys_rt_sigprocmask, how, set ? &new_set : NULL, + oset ? &old_set : NULL, sigsetsize); + + if (!ret && oset && put_sigset32(oset, &old_set, sigsetsize)) + return -EFAULT; + + return ret; +} + + +int sys32_rt_sigpending(sigset_t32 *uset, unsigned int sigsetsize) +{ + int ret; + sigset_t set; + extern long sys_rt_sigpending(sigset_t *set, size_t sigsetsize); + + KERNEL_SYSCALL(ret, sys_rt_sigpending, &set, sigsetsize); + + if (!ret && put_sigset32(uset, &set, sigsetsize)) + return -EFAULT; + + return ret; +} + +long +sys32_rt_sigaction(int sig, const struct sigaction32 *act, struct sigaction32 *oact, + size_t sigsetsize) +{ + struct k_sigaction32 new_sa32, old_sa32; + struct k_sigaction new_sa, old_sa; + int ret = -EINVAL; + + if (act) { + if (copy_from_user(&new_sa32.sa, act, sizeof new_sa32.sa)) + return -EFAULT; + new_sa.sa.sa_handler = (__sighandler_t)(unsigned long)new_sa32.sa.sa_handler; + new_sa.sa.sa_flags = new_sa32.sa.sa_flags; + sigset_32to64(&new_sa.sa.sa_mask, &new_sa32.sa.sa_mask); + } + + ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL); + + if (!ret && oact) { + sigset_64to32(&old_sa32.sa.sa_mask, &old_sa.sa.sa_mask); + old_sa32.sa.sa_flags = old_sa.sa.sa_flags; + old_sa32.sa.sa_handler = (__sighandler_t32)(unsigned long)old_sa.sa.sa_handler; + if (copy_to_user(oact, &old_sa32.sa, sizeof old_sa32.sa)) + return -EFAULT; + } + return ret; +} + +typedef struct { + unsigned int ss_sp; + int ss_flags; + __kernel_size_t32 ss_size; +} stack_t32; + +int +do_sigaltstack32 (const stack_t32 *uss32, stack_t32 *uoss32, unsigned long sp) +{ + stack_t32 ss32, oss32; + stack_t ss, oss; + stack_t *ssp = NULL, *ossp = NULL; + int ret; + + if (uss32) { + if (copy_from_user(&ss32, uss32, sizeof ss32)) + return -EFAULT; + + ss.ss_sp = (void *)ss32.ss_sp; + ss.ss_flags = ss32.ss_flags; + ss.ss_size = ss32.ss_size; + + ssp = &ss; + } + + if (uoss32) + ossp = &oss; + + KERNEL_SYSCALL(ret, do_sigaltstack, ssp, ossp, sp); + + if (!ret && uoss32) { + oss32.ss_sp = (unsigned int)(unsigned long)oss.ss_sp; + oss32.ss_flags = oss.ss_flags; + oss32.ss_size = oss.ss_size; + if (copy_to_user(uoss32, &oss32, sizeof *uoss32)) + return -EFAULT; + } + + return ret; +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/signal.c linux.19rc3-ac4/arch/parisc/kernel/signal.c --- linux.19rc3/arch/parisc/kernel/signal.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/signal.c 2002-07-29 13:58:37.000000000 +0100 @@ -26,20 +26,24 @@ #include #include #include +#include #include #include #define DEBUG_SIG 0 +#if DEBUG_SIG +#define DBG(x) printk x +#else +#define DBG(x) +#endif + #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) -extern long sys_wait4 (int, int *, int, struct rusage *); int do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall); int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from) { - if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t))) - return -EFAULT; if (from->si_code < 0) return __copy_to_user(to, from, sizeof(siginfo_t)); else { @@ -128,30 +132,15 @@ * Do a signal return - restore sigcontext. */ -struct rt_sigframe { - unsigned int tramp[4]; - struct siginfo info; - struct ucontext uc; -}; - /* Trampoline for calling rt_sigreturn() */ #define INSN_LDI_R25_0 0x34190000 /* ldi 0,%r25 (in_syscall=0) */ #define INSN_LDI_R25_1 0x34190002 /* ldi 1,%r25 (in_syscall=1) */ #define INSN_LDI_R20 0x3414015a /* ldi __NR_rt_sigreturn,%r20 */ #define INSN_BLE_SR2_R0 0xe4008200 /* be,l 0x100(%sr2,%r0),%sr0,%r31 */ -#define INSN_NOP 0x80000240 /* nop */ +#define INSN_NOP 0x08000240 /* nop */ /* For debugging */ #define INSN_DIE_HORRIBLY 0x68000ccc /* stw %r0,0x666(%sr0,%r0) */ -/* - * The 32-bit ABI wants at least 48 bytes for a function call frame: - * 16 bytes for arg0-arg3, and 32 bytes for magic (the only part of - * which Linux/parisc uses is sp-20 for the saved return pointer...) - * Then, the stack pointer must be rounded to a cache line (64 bytes). - */ -#define PARISC_RT_SIGFRAME_SIZE \ - (((sizeof(struct rt_sigframe) + 48) + 63) & -64) - static long restore_sigcontext(struct sigcontext *sc, struct pt_regs *regs) { @@ -162,10 +151,7 @@ err |= __copy_from_user(regs->iaoq, sc->sc_iaoq, sizeof(regs->iaoq)); err |= __copy_from_user(regs->iasq, sc->sc_iasq, sizeof(regs->iasq)); err |= __get_user(regs->sar, &sc->sc_sar); - -#if DEBUG_SIG - printk("restore_sigcontext: r28 is %ld\n", regs->gr[28]); -#endif + DBG(("restore_sigcontext: r28 is %ld\n", regs->gr[28])); return err; } @@ -180,13 +166,8 @@ /* Unwind the user stack to get the rt_sigframe structure. */ frame = (struct rt_sigframe *) (usp - PARISC_RT_SIGFRAME_SIZE); -#if DEBUG_SIG - printk("in sys_rt_sigreturn, frame is %p\n", frame); -#endif + DBG(("in sys_rt_sigreturn, frame is %p\n", frame)); - /* Verify that it's a good sigcontext before using it */ - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) - goto give_sigsegv; if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto give_sigsegv; @@ -200,10 +181,7 @@ if (restore_sigcontext(&frame->uc.uc_mcontext, regs)) goto give_sigsegv; -#if DEBUG_SIG - printk("usp: %#08lx stack %p", - usp, &frame->uc.uc_stack); -#endif + DBG(("usp: %#08lx stack %p", usp, &frame->uc.uc_stack)); /* I don't know why everyone else assumes they can call this with a pointer to a stack_t on the kernel stack. That @@ -218,16 +196,14 @@ if (in_syscall) regs->gr[31] = regs->iaoq[0]; #if DEBUG_SIG - printk("returning to %#lx\n", regs->iaoq[0]); - printk("in sys_rt_sigreturn:\n"); + DBG(("returning to %#lx\n", regs->iaoq[0])); + DBG(("in sys_rt_sigreturn:\n")); show_regs(regs); #endif return; give_sigsegv: -#if DEBUG_SIG - printk("fuckup in sys_rt_sigreturn, sending SIGSEGV\n"); -#endif + DBG(("sys_rt_sigreturn sending SIGSEGV\n")); si.si_signo = SIGSEGV; si.si_errno = 0; si.si_code = SI_KERNEL; @@ -246,7 +222,7 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) { if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp)) - sp = current->sas_ss_sp + current->sas_ss_size; + sp = current->sas_ss_sp; /* Stacks grow up! */ return (void *) sp; /* Stacks grow up. Fun. */ } @@ -265,24 +241,22 @@ /* regs->iaoq is undefined in the syscall return path */ err |= __put_user(regs->gr[31], &sc->sc_iaoq[0]); err |= __put_user(regs->gr[31]+4, &sc->sc_iaoq[1]); -#if DEBUG_SIG - printk("setup_sigcontext: iaoq %#lx/%#lx\n", regs->gr[31], regs->gr[31]); -#endif + err |= __put_user(regs->sr[3], &sc->sc_iasq[0]); + err |= __put_user(regs->sr[3], &sc->sc_iasq[1]); + DBG(("setup_sigcontext: iaoq %#lx/%#lx\n", + regs->gr[31], regs->gr[31])); } else { err |= __copy_to_user(sc->sc_iaoq, regs->iaoq, sizeof(regs->iaoq)); err |= __copy_to_user(sc->sc_iasq, regs->iasq, sizeof(regs->iasq)); -#if DEBUG_SIG - printk("setup_sigcontext: iaoq %#lx/%#lx\n", regs->iaoq[0], regs->iaoq[1]); -#endif + DBG(("setup_sigcontext: iaoq %#lx/%#lx\n", + regs->iaoq[0], regs->iaoq[1])); } err |= __put_user(flags, &sc->sc_flags); err |= __copy_to_user(sc->sc_gr, regs->gr, sizeof(regs->gr)); err |= __copy_to_user(sc->sc_fr, regs->fr, sizeof(regs->fr)); err |= __put_user(regs->sar, &sc->sc_sar); -#if DEBUG_SIG - printk("setup_sigcontext: r28 is %ld\n", regs->gr[28]); -#endif + DBG(("setup_sigcontext: r28 is %ld\n", regs->gr[28])); return err; } @@ -297,22 +271,9 @@ int err = 0; usp = regs->gr[30]; - /* access_ok is broken, so do a simplistic "are we stomping on - kernel space" assertion. */ - if (usp > PAGE_OFFSET) { - printk("setup_rt_frame: called on kernel space (usp=%#lx), NOW YOU MUST DIE!!!\n", - usp); - show_regs(regs); - while(1); - } - frame = get_sigframe(ka, usp, sizeof(*frame)); - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - goto give_sigsegv; -#if DEBUG_SIG - printk("setup_rt_frame 1: frame %p info %p\n", frame, info); -#endif + DBG(("setup_rt_frame 1: frame %p info %p\n", frame, info)); err |= __copy_to_user(&frame->info, info, sizeof(siginfo_t)); err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); @@ -337,8 +298,8 @@ { int sid; asm ("mfsp %%sr3,%0" : "=r" (sid)); - printk("flushing 64 bytes at space %#x offset %p\n", - sid, frame->tramp); + DBG(("flushing 64 bytes at space %#x offset %p\n", + sid, frame->tramp)); } #endif @@ -387,6 +348,7 @@ if (in_syscall) regs->gr[31] = (HACK) haddr; else { + regs->gr[0] = USER_PSW; regs->iaoq[0] = (HACK) haddr | 3; regs->iaoq[1] = regs->iaoq[0] + 4; } @@ -395,26 +357,20 @@ regs->gr[26] = sig; /* signal number */ regs->gr[25] = (HACK) &frame->info; /* siginfo pointer */ regs->gr[24] = (HACK) &frame->uc; /* ucontext pointer */ -#if DEBUG_SIG - printk("making sigreturn frame: %#lx + %#lx = %#lx\n", + DBG(("making sigreturn frame: %#lx + %#x = %#lx\n", regs->gr[30], PARISC_RT_SIGFRAME_SIZE, - regs->gr[30] + PARISC_RT_SIGFRAME_SIZE); -#endif + regs->gr[30] + PARISC_RT_SIGFRAME_SIZE)); /* Raise the user stack pointer to make a proper call frame. */ regs->gr[30] = ((HACK) frame + PARISC_RT_SIGFRAME_SIZE); -#if DEBUG_SIG - printk("SIG deliver (%s:%d): frame=0x%p sp=%#lx iaoq=%#lx/%#lx rp=%#lx\n", + DBG(("SIG deliver (%s:%d): frame=0x%p sp=%#lx iaoq=%#lx/%#lx rp=%#lx\n", current->comm, current->pid, frame, regs->gr[30], - regs->iaoq[0], regs->iaoq[1], rp); -#endif + regs->iaoq[0], regs->iaoq[1], rp)); return 1; give_sigsegv: -#if DEBUG_SIG - printk("fuckup in setup_rt_frame, sending SIGSEGV\n"); -#endif + DBG(("setup_rt_frame sending SIGSEGV\n")); if (sig == SIGSEGV) ka->sa.sa_handler = SIG_DFL; si.si_signo = SIGSEGV; @@ -436,10 +392,9 @@ siginfo_t *info, sigset_t *oldset, struct pt_regs *regs, int in_syscall) { -#if DEBUG_SIG - printk("handle_signal(sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p)\n", - sig, ka, info, oldset, regs); -#endif + DBG(("handle_signal(sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p)\n", + sig, ka, info, oldset, regs)); + /* Set up the stack frame */ if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall)) return 0; @@ -468,16 +423,16 @@ * registers). As noted below, the syscall number gets restored for * us due to the magic of delayed branching. */ + asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall) { siginfo_t info; struct k_sigaction *ka; -#if DEBUG_SIG - printk("do_signal(oldset=0x%p, regs=0x%p, sr7 %#lx, pending %d, in_syscall=%d\n", - oldset, regs, regs->sr[7], current->sigpending, in_syscall); -#endif + DBG(("do_signal(oldset=0x%p, regs=0x%p, sr7 %#lx, pending %d, in_syscall=%d\n", + oldset, regs, regs->sr[7], current->sigpending, in_syscall)); + /* Everyone else checks to see if they are in kernel mode at this point and exits if that's the case. I'm not sure why we would be called in that case, but for some reason we @@ -486,9 +441,8 @@ if (!oldset) oldset = ¤t->blocked; -#if DEBUG_SIG - printk("do_signal: oldset %08lx:%08lx\n", oldset->sig[0], oldset->sig[1]); -#endif + DBG(("do_signal: oldset %08lx:%08lx\n", + oldset->sig[0], oldset->sig[1])); for (;;) { unsigned long signr; @@ -496,10 +450,7 @@ spin_lock_irq(¤t->sigmask_lock); signr = dequeue_signal(¤t->blocked, &info); spin_unlock_irq(¤t->sigmask_lock); -#if DEBUG_SIG - printk("do_signal: signr=%ld, pid=%d\n", signr, current->pid); -#endif - + DBG(("do_signal: signr=%ld, pid=%d\n", signr, current->pid)); if (!signr) break; @@ -536,10 +487,9 @@ } ka = ¤t->sig->action[signr-1]; -#if DEBUG_SIG - printk("sa_handler is %lx\n", ka->sa.sa_handler); -#endif - if ((unsigned long) ka->sa.sa_handler == (unsigned long) SIG_IGN) { + DBG(("sa_handler is %x\n", + (unsigned int) ka->sa.sa_handler)); + if (ka->sa.sa_handler == SIG_IGN) { if (signr != SIGCHLD) continue; while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0) @@ -547,7 +497,7 @@ continue; } - if ((unsigned long) ka->sa.sa_handler == (unsigned long) SIG_DFL) { + if (ka->sa.sa_handler == SIG_DFL) { int exit_code = signr; /* Init gets no signals it doesn't want. */ @@ -591,17 +541,13 @@ /* Check the return code */ switch (regs->gr[28]) { case -ERESTARTNOHAND: -#if DEBUG_SIG - printk("ERESTARTNOHAND: returning -EINTR\n"); -#endif + DBG(("ERESTARTNOHAND: returning -EINTR\n")); regs->gr[28] = -EINTR; break; case -ERESTARTSYS: if (!(ka->sa.sa_flags & SA_RESTART)) { -#if DEBUG_SIG - printk("ERESTARTSYS: putting -EINTR\n"); -#endif + DBG(("ERESTARTSYS: putting -EINTR\n")); regs->gr[28] = -EINTR; break; } @@ -620,9 +566,9 @@ delivery failed, we need to continue to iterate in this loop so we can deliver the SIGSEGV... */ if (handle_signal(signr, ka, &info, oldset, regs, in_syscall)) { -#if DEBUG_SIG - printk("Exiting do_signal (success), regs->gr[28] = %ld\n", regs->gr[28]); -#endif + DBG((KERN_DEBUG + "Exiting do_signal (success), regs->gr[28] = %ld\n", + regs->gr[28])); return 1; } } @@ -642,8 +588,9 @@ regs->gr[28] = regs->orig_r28; } } -#if DEBUG_SIG - printk("Exiting do_signal (not delivered), regs->gr[28] = %ld\n", regs->gr[28]); -#endif + + DBG(("Exiting do_signal (not delivered), regs->gr[28] = %ld\n", + regs->gr[28])); + return 0; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/smp.c linux.19rc3-ac4/arch/parisc/kernel/smp.c --- linux.19rc3/arch/parisc/kernel/smp.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/smp.c 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,794 @@ +/* +** SMP Support +** +** Copyright (C) 1999 Walt Drummond +** Copyright (C) 1999 David Mosberger-Tang +** Copyright (C) 2001 Grant Grundler +** +** Lots of stuff stolen from arch/alpha/kernel/smp.c +** ...and then parisc stole from arch/ia64/kernel/smp.c. Thanks David! :^) +** +** Thanks to John Curry and Ullas Ponnadi. I learned alot from their work. +** -grant (1/12/2001) +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +*/ +#define __KERNEL_SYSCALLS__ +#undef ENTRY_SYS_CPUS /* syscall support for iCOD-like functionality */ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include /* for flush_tlb_all() proto/macro */ + +#include +#include /* for CPU_IRQ_REGION and friends */ +#include +#include +#include +#include +#include +#include +#include + +#define kDEBUG 0 + +spinlock_t pa_dbit_lock = SPIN_LOCK_UNLOCKED; + +spinlock_t smp_lock = SPIN_LOCK_UNLOCKED; + +volatile struct task_struct *smp_init_current_idle_task; +spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED; + +static volatile int smp_commenced = 0; /* Set when the idlers are all forked */ +static volatile int cpu_now_booting = 0; /* track which CPU is booting */ +volatile unsigned long cpu_online_map = 0; /* Bitmap of online CPUs */ +#define IS_LOGGED_IN(cpunum) (test_bit(cpunum, (atomic_t *)&cpu_online_map)) + +int smp_num_cpus = 1; +int smp_threads_ready = 0; +static int max_cpus = -1; /* Command line */ +struct smp_call_struct { + void (*func) (void *info); + void *info; + long wait; + atomic_t unstarted_count; + atomic_t unfinished_count; +}; +static volatile struct smp_call_struct *smp_call_function_data; + +enum ipi_message_type { + IPI_NOP=0, + IPI_RESCHEDULE=1, + IPI_CALL_FUNC, + IPI_CPU_START, + IPI_CPU_STOP, + IPI_CPU_TEST +}; + + +/********** SMP inter processor interrupt and communication routines */ + +#undef PER_CPU_IRQ_REGION +#ifdef PER_CPU_IRQ_REGION +/* XXX REVISIT Ignore for now. +** *May* need this "hook" to register IPI handler +** once we have perCPU ExtIntr switch tables. +*/ +static void +ipi_init(int cpuid) +{ + + /* If CPU is present ... */ +#ifdef ENTRY_SYS_CPUS + /* *and* running (not stopped) ... */ +#error iCOD support wants state checked here. +#endif + +#error verify IRQ_OFFSET(IPI_IRQ) is ipi_interrupt() in new IRQ region + + if(IS_LOGGED_IN(cpuid) ) + { + switch_to_idle_task(current); + } + + return; +} +#endif + + +/* +** Yoink this CPU from the runnable list... +** +*/ +static void +halt_processor(void) +{ +#ifdef ENTRY_SYS_CPUS +#error halt_processor() needs rework +/* +** o migrate I/O interrupts off this CPU. +** o leave IPI enabled - __cli() will disable IPI. +** o leave CPU in online map - just change the state +*/ + cpu_data[this_cpu].state = STATE_STOPPED; + mark_bh(IPI_BH); +#else + /* REVISIT : redirect I/O Interrupts to another CPU? */ + /* REVISIT : does PM *know* this CPU isn't available? */ + clear_bit(smp_processor_id(), (void *)&cpu_online_map); + __cli(); + for (;;) + ; +#endif +} + + +void +ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + int this_cpu = smp_processor_id(); + struct cpuinfo_parisc *p = &cpu_data[this_cpu]; + unsigned long ops; + unsigned long flags; + + /* Count this now; we may make a call that never returns. */ + p->ipi_count++; + + mb(); /* Order interrupt and bit testing. */ + + for (;;) { + spin_lock_irqsave(&(p->lock),flags); + ops = p->pending_ipi; + p->pending_ipi = 0; + spin_unlock_irqrestore(&(p->lock),flags); + + mb(); /* Order bit clearing and data access. */ + + if (!ops) + break; + + while (ops) { + unsigned long which = ffz(~ops); + + switch (which) { + case IPI_RESCHEDULE: +#if (kDEBUG>=100) + printk(KERN_DEBUG "CPU%d IPI_RESCHEDULE\n",this_cpu); +#endif /* kDEBUG */ + ops &= ~(1 << IPI_RESCHEDULE); + /* + * Reschedule callback. Everything to be + * done is done by the interrupt return path. + */ + break; + + case IPI_CALL_FUNC: +#if (kDEBUG>=100) + printk(KERN_DEBUG "CPU%d IPI_CALL_FUNC\n",this_cpu); +#endif /* kDEBUG */ + ops &= ~(1 << IPI_CALL_FUNC); + { + volatile struct smp_call_struct *data; + void (*func)(void *info); + void *info; + int wait; + + data = smp_call_function_data; + func = data->func; + info = data->info; + wait = data->wait; + + mb(); + atomic_dec ((atomic_t *)&data->unstarted_count); + + /* At this point, *data can't + * be relied upon. + */ + + (*func)(info); + + /* Notify the sending CPU that the + * task is done. + */ + mb(); + if (wait) + atomic_dec ((atomic_t *)&data->unfinished_count); + } + break; + + case IPI_CPU_START: +#if (kDEBUG>=100) + printk(KERN_DEBUG "CPU%d IPI_CPU_START\n",this_cpu); +#endif /* kDEBUG */ + ops &= ~(1 << IPI_CPU_START); +#ifdef ENTRY_SYS_CPUS + p->state = STATE_RUNNING; +#endif + break; + + case IPI_CPU_STOP: +#if (kDEBUG>=100) + printk(KERN_DEBUG "CPU%d IPI_CPU_STOP\n",this_cpu); +#endif /* kDEBUG */ + ops &= ~(1 << IPI_CPU_STOP); +#ifdef ENTRY_SYS_CPUS +#else + halt_processor(); +#endif + break; + + case IPI_CPU_TEST: +#if (kDEBUG>=100) + printk(KERN_DEBUG "CPU%d is alive!\n",this_cpu); +#endif /* kDEBUG */ + ops &= ~(1 << IPI_CPU_TEST); + break; + + default: + printk(KERN_CRIT "Unknown IPI num on CPU%d: %lu\n", + this_cpu, which); + ops &= ~(1 << which); + return; + } /* Switch */ + } /* while (ops) */ + } + return; +} + + +static inline void +ipi_send(int cpu, enum ipi_message_type op) +{ + struct cpuinfo_parisc *p = &cpu_data[cpu]; + unsigned long flags; + + spin_lock_irqsave(&(p->lock),flags); + p->pending_ipi |= 1 << op; + __raw_writel(IRQ_OFFSET(IPI_IRQ), cpu_data[cpu].hpa); + spin_unlock_irqrestore(&(p->lock),flags); +} + + +static inline void +send_IPI_single(int dest_cpu, enum ipi_message_type op) +{ + if (dest_cpu == NO_PROC_ID) { + BUG(); + return; + } + + ipi_send(dest_cpu, op); +} + +static inline void +send_IPI_allbutself(enum ipi_message_type op) +{ + int i; + + for (i = 0; i < smp_num_cpus; i++) { + if (i != smp_processor_id()) + send_IPI_single(i, op); + } +} + +inline void +smp_send_stop(void) { send_IPI_allbutself(IPI_CPU_STOP); } + +static inline void +smp_send_start(void) { send_IPI_allbutself(IPI_CPU_START); } + +void +smp_send_reschedule(int cpu) { send_IPI_single(cpu, IPI_RESCHEDULE); } + + +/** + * Run a function on all other CPUs. + * The function to run. This must be fast and non-blocking. + * An arbitrary pointer to pass to the function. + * If true, keep retrying until ready. + * If true, wait until function has completed on other CPUs. + * [RETURNS] 0 on success, else a negative status code. + * + * Does not return until remote CPUs are nearly ready to execute + * or have executed. + */ + +int +smp_call_function (void (*func) (void *info), void *info, int retry, int wait) +{ + struct smp_call_struct data; + long timeout; + static spinlock_t lock = SPIN_LOCK_UNLOCKED; + + data.func = func; + data.info = info; + data.wait = wait; + atomic_set(&data.unstarted_count, smp_num_cpus - 1); + atomic_set(&data.unfinished_count, smp_num_cpus - 1); + + if (retry) { + spin_lock (&lock); + while (smp_call_function_data != 0) + barrier(); + } + else { + spin_lock (&lock); + if (smp_call_function_data) { + spin_unlock (&lock); + return -EBUSY; + } + } + + smp_call_function_data = &data; + spin_unlock (&lock); + + /* Send a message to all other CPUs and wait for them to respond */ + send_IPI_allbutself(IPI_CALL_FUNC); + + /* Wait for response */ + timeout = jiffies + HZ; + while ( (atomic_read (&data.unstarted_count) > 0) && + time_before (jiffies, timeout) ) + barrier (); + + /* We either got one or timed out. Release the lock */ + + mb(); + smp_call_function_data = NULL; + if (atomic_read (&data.unstarted_count) > 0) { + printk(KERN_CRIT "SMP CALL FUNCTION TIMED OUT! (cpu=%d)\n", + smp_processor_id()); + return -ETIMEDOUT; + } + + while (wait && atomic_read (&data.unfinished_count) > 0) + barrier (); + + return 0; +} + + + +/* + * Setup routine for controlling SMP activation + * + * Command-line option of "nosmp" or "maxcpus=0" will disable SMP + * activation entirely (the MPS table probe still happens, though). + * + * Command-line option of "maxcpus=", where is an integer + * greater than 0, limits the maximum number of CPUs activated in + * SMP mode to . + */ + +static int __init nosmp(char *str) +{ + max_cpus = 0; + return 1; +} + +__setup("nosmp", nosmp); + +static int __init maxcpus(char *str) +{ + get_option(&str, &max_cpus); + return 1; +} + +__setup("maxcpus=", maxcpus); + +/* + * Flush all other CPU's tlb and then mine. Do this with smp_call_function() + * as we want to ensure all TLB's flushed before proceeding. + */ + +extern void flush_tlb_all_local(void); + +void +smp_flush_tlb_all(void) +{ + smp_call_function((void (*)(void *))flush_tlb_all_local, NULL, 1, 1); + flush_tlb_all_local(); +} + + +void +smp_do_timer(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + struct cpuinfo_parisc *data = &cpu_data[cpu]; + + if (!--data->prof_counter) { + data->prof_counter = data->prof_multiplier; + update_process_times(user_mode(regs)); + } +} + +/* + * Called by secondaries to update state and initialize CPU registers. + */ +static void __init +smp_cpu_init(int cpunum) +{ + extern int init_per_cpu(int); /* arch/parisc/kernel/setup.c */ + extern void init_IRQ(void); /* arch/parisc/kernel/irq.c */ + + /* Set modes and Enable floating point coprocessor */ + (void) init_per_cpu(cpunum); + + disable_sr_hashing(); + + mb(); + + /* Well, support 2.4 linux scheme as well. */ + if (test_and_set_bit(cpunum, (unsigned long *) (&cpu_online_map))) + { + extern void machine_halt(void); /* arch/parisc.../process.c */ + + printk(KERN_CRIT "CPU#%d already initialized!\n", cpunum); + machine_halt(); + } + + /* Initialise the idle task for this CPU */ + atomic_inc(&init_mm.mm_count); + current->active_mm = &init_mm; + if(current->mm) + BUG(); + enter_lazy_tlb(&init_mm, current, cpunum); + + init_IRQ(); /* make sure no IRQ's are enabled or pending */ +} + + +/* + * Slaves start using C here. Indirectly called from smp_slave_stext. + * Do what start_kernel() and main() do for boot strap processor (aka monarch) + */ +void __init smp_callin(void) +{ + extern void cpu_idle(void); /* arch/parisc/kernel/process.c */ + int slave_id = cpu_now_booting; +#if 0 + void *istack; +#endif + + smp_cpu_init(slave_id); + +#if 0 /* NOT WORKING YET - see entry.S */ + istack = (void *)__get_free_pages(GFP_KERNEL,ISTACK_ORDER); + if (istack == NULL) { + printk(KERN_CRIT "Failed to allocate interrupt stack for cpu %d\n",slave_id); + BUG(); + } + mtctl(istack,31); +#endif + + flush_cache_all_local(); /* start with known state */ + flush_tlb_all_local(); + + local_irq_enable(); /* Interrupts have been off until now */ + + /* Slaves wait here until Big Poppa daddy say "jump" */ + mb(); /* PARANOID */ + while (!smp_commenced) ; + mb(); /* PARANOID */ + + cpu_idle(); /* Wait for timer to schedule some work */ + + /* NOTREACHED */ + panic("smp_callin() AAAAaaaaahhhh....\n"); +} + +/* + * Create the idle task for a new Slave CPU. DO NOT use kernel_thread() + * because that could end up calling schedule(). If it did, the new idle + * task could get scheduled before we had a chance to remove it from the + * run-queue... + */ +static int fork_by_hand(void) +{ + struct pt_regs regs; + + /* + * don't care about the regs settings since + * we'll never reschedule the forked task. + */ + return do_fork(CLONE_VM|CLONE_PID, 0, ®s, 0); +} + + +/* + * Bring one cpu online. + */ +static int smp_boot_one_cpu(int cpuid, int cpunum) +{ + struct task_struct *idle; + long timeout; + + /* + * Create an idle task for this CPU. Note the address wed* give + * to kernel_thread is irrelevant -- it's going to start + * where OS_BOOT_RENDEVZ vector in SAL says to start. But + * this gets all the other task-y sort of data structures set + * up like we wish. We need to pull the just created idle task + * off the run queue and stuff it into the init_tasks[] array. + * Sheesh . . . + */ + + if (fork_by_hand() < 0) + panic("SMP: fork failed for CPU:%d", cpuid); + + idle = init_task.prev_task; + if (!idle) + panic("SMP: No idle process for CPU:%d", cpuid); + + task_set_cpu(idle, cpunum); /* manually schedule idle task */ + del_from_runqueue(idle); + unhash_process(idle); + init_tasks[cpunum] = idle; + + /* Let _start know what logical CPU we're booting + ** (offset into init_tasks[],cpu_data[]) + */ + cpu_now_booting = cpunum; + + /* + ** boot strap code needs to know the task address since + ** it also contains the process stack. + */ + smp_init_current_idle_task = idle ; + mb(); + + /* + ** This gets PDC to release the CPU from a very tight loop. + ** See MEM_RENDEZ comments in head.S. + */ + __raw_writel(IRQ_OFFSET(TIMER_IRQ), cpu_data[cpunum].hpa); + mb(); + + /* + * OK, wait a bit for that CPU to finish staggering about. + * Slave will set a bit when it reaches smp_cpu_init() and then + * wait for smp_commenced to be 1. + * Once we see the bit change, we can move on. + */ + for (timeout = 0; timeout < 10000; timeout++) { + if(IS_LOGGED_IN(cpunum)) { + /* Which implies Slave has started up */ + cpu_now_booting = 0; + smp_init_current_idle_task = NULL; + goto alive ; + } + udelay(100); + barrier(); + } + + init_tasks[cpunum] = NULL; + free_task_struct(idle); + + printk(KERN_CRIT "SMP: CPU:%d is stuck.\n", cpuid); + return -1; + +alive: + /* Remember the Slave data */ +#if (kDEBUG>=100) + printk(KERN_DEBUG "SMP: CPU:%d (num %d) came alive after %ld _us\n", + cpuid, cpunum, timeout * 100); +#endif /* kDEBUG */ +#ifdef ENTRY_SYS_CPUS + cpu_data[cpunum].state = STATE_RUNNING; +#endif + return 0; +} + + + + +/* +** inventory.c:do_inventory() has already 'discovered' the additional CPU's. +** We are ready to wrest them from PDC's control now. +** Called by smp_init bring all the secondaries online and hold them. +** +** o Setup of the IPI irq handler is done in irq.c. +** o MEM_RENDEZ is initialzed in head.S:stext() +** +*/ +void __init smp_boot_cpus(void) +{ + int i, cpu_count = 1; + unsigned long bogosum = loops_per_jiffy; /* Count Monarch */ + + /* REVISIT - assumes first CPU reported by PAT PDC is BSP */ + int bootstrap_processor=cpu_data[0].cpuid; /* CPU ID of BSP */ + + /* Setup BSP mappings */ + printk(KERN_DEBUG "SMP: bootstrap CPU ID is %d\n",bootstrap_processor); + init_task.processor = bootstrap_processor; + current->processor = bootstrap_processor; + cpu_online_map = 1 << bootstrap_processor; /* Mark Boostrap processor as present */ + current->active_mm = &init_mm; + +#ifdef ENTRY_SYS_CPUS + cpu_data[0].state = STATE_RUNNING; +#endif + + /* Nothing to do when told not to. */ + if (max_cpus == 0) { + printk(KERN_INFO "SMP mode deactivated.\n"); + return; + } + + if (max_cpus != -1) + printk(KERN_INFO "Limiting CPUs to %d\n", max_cpus); + + /* We found more than one CPU.... */ + if (boot_cpu_data.cpu_count > 1) { + + for (i = 0; i < NR_CPUS; i++) { + if (cpu_data[i].cpuid == NO_PROC_ID || + cpu_data[i].cpuid == bootstrap_processor) + continue; + + if (smp_boot_one_cpu(cpu_data[i].cpuid, cpu_count) < 0) + continue; + + bogosum += loops_per_jiffy; + cpu_count++; /* Count good CPUs only... */ + + /* Bail when we've started as many CPUS as told to */ + if (cpu_count == max_cpus) + break; + } + } + if (cpu_count == 1) { + printk(KERN_INFO "SMP: Bootstrap processor only.\n"); + } + + printk(KERN_INFO "SMP: Total %d of %d processors activated " + "(%lu.%02lu BogoMIPS noticed).\n", + cpu_count, boot_cpu_data.cpu_count, (bogosum + 25) / 5000, + ((bogosum + 25) / 50) % 100); + + smp_num_cpus = cpu_count; +#ifdef PER_CPU_IRQ_REGION + ipi_init(); +#endif + return; +} + +/* + * Called from main.c by Monarch Processor. + * After this, any CPU can schedule any task. + */ +void smp_commence(void) +{ + smp_commenced = 1; + mb(); + return; +} + +#ifdef ENTRY_SYS_CPUS +/* Code goes along with: +** entry.s: ENTRY_NAME(sys_cpus) / * 215, for cpu stat * / +*/ +int sys_cpus(int argc, char **argv) +{ + int i,j=0; + extern int current_pid(int cpu); + + if( argc > 2 ) { + printk("sys_cpus:Only one argument supported\n"); + return (-1); + } + if ( argc == 1 ){ + +#ifdef DUMP_MORE_STATE + for(i=0; ipid)?"RUNNING ": "IDLING ",current->pid); +#endif + } else if ((argc==2) && !(strcmp(argv[1],"-s"))) { +#ifdef DUMP_MORE_STATE + printk("\nCPUSTATE CPUID\n"); + for (i=0;ipid==0)?"RUNNING ":"IDLING "); +#endif + } else { + printk("sys_cpus:Unknown request\n"); + return (-1); + } + return 0; +} +#endif /* ENTRY_SYS_CPUS */ + +#ifdef CONFIG_PROC_FS +int __init +setup_profiling_timer(unsigned int multiplier) +{ + return -EINVAL; +} +#endif diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/superio.c linux.19rc3-ac4/arch/parisc/kernel/superio.c --- linux.19rc3/arch/parisc/kernel/superio.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/superio.c 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,543 @@ +/* National Semiconductor NS87560UBD Super I/O controller used in + * HP [BCJ]x000 workstations. + * + * This chip is a horrid piece of engineering, and National + * denies any knowledge of its existence. Thus no datasheet is + * available off www.national.com. + * + * (C) Copyright 2000 Linuxcare, Inc. + * (C) Copyright 2000 Linuxcare Canada, Inc. + * (C) Copyright 2000 Martin K. Petersen + * (C) Copyright 2000 Alex deVries + * (C) Copyright 2001 John Marvin + * + * 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. + * + * The initial version of this is by Martin Peterson. Alex deVries + * has spent a bit of time trying to coax it into working. + * + * Major changes to get basic interrupt infrastructure working to + * hopefully be able to support all SuperIO devices. Currently + * works with serial. -- John Marvin + */ + + +/* NOTES: + * + * Function 0 is an IDE controller. It is identical to a PC87415 IDE + * controller (and identifies itself as such). + * + * Function 1 is a "Legacy I/O" controller. Under this function is a + * whole mess of legacy I/O peripherals. Of course, HP hasn't enabled + * all the functionality in hardware, but the following is available: + * + * Two 16550A compatible serial controllers + * An IEEE 1284 compatible parallel port + * A floppy disk controller + * + * Function 2 is a USB controller. + * + * We must be incredibly careful during initialization. Since all + * interrupts are routed through function 1 (which is not allowed by + * the PCI spec), we need to program the PICs on the legacy I/O port + * *before* we attempt to set up IDE and USB. @#$!& + * + * According to HP, devices are only enabled by firmware if they have + * a physical device connected. + * + * Configuration register bits: + * 0x5A: FDC, SP1, IDE1, SP2, IDE2, PAR, Reserved, P92 + * 0x5B: RTC, 8259, 8254, DMA1, DMA2, KBC, P61, APM + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct superio_device sio_dev = { + iosapic_irq: -1 +}; + + +#undef DEBUG_INIT + +void +superio_inform_irq(int irq) +{ + if (sio_dev.iosapic_irq != -1) { + printk(KERN_ERR "SuperIO: superio_inform_irq called twice! (more than one SuperIO?)\n"); + BUG(); + return; + } + + sio_dev.iosapic_irq = irq; +} + +static void +superio_interrupt(int irq, void *devp, struct pt_regs *regs) +{ + struct superio_device *sio = (struct superio_device *)devp; + u8 results; + u8 local_irq; + + /* Poll the 8259 to see if there's an interrupt. */ + outb (OCW3_POLL,IC_PIC1+0); + + results = inb(IC_PIC1+0); + + if ((results & 0x80) == 0) { +#ifndef CONFIG_SMP + /* HACK: need to investigate why this happens if SMP enabled */ + BUG(); /* This shouldn't happen */ +#endif + return; + } + + /* Check to see which device is interrupting */ + + local_irq = results & 0x0f; + + if (local_irq == 2 || local_irq > 7) { + printk(KERN_ERR "SuperIO: slave interrupted!\n"); + BUG(); + return; + } + + if (local_irq == 7) { + + /* Could be spurious. Check in service bits */ + + outb(OCW3_ISR,IC_PIC1+0); + results = inb(IC_PIC1+0); + if ((results & 0x80) == 0) { /* if ISR7 not set: spurious */ + printk(KERN_WARNING "SuperIO: spurious interrupt!\n"); + return; + } + } + + /* Call the appropriate device's interrupt */ + + do_irq(&sio->irq_region->action[local_irq], + sio->irq_region->data.irqbase + local_irq, + regs); + + /* set EOI */ + + outb((OCW2_SEOI|local_irq),IC_PIC1 + 0); + return; +} + +/* Initialize Super I/O device */ + +static void __devinit +superio_init(struct superio_device *sio) +{ + struct pci_dev *pdev = sio->lio_pdev; + u16 word; + u8 i; + + if (!pdev || sio->iosapic_irq == -1) { + printk(KERN_ERR "All SuperIO functions not found!\n"); + BUG(); + return; + } + + printk (KERN_INFO "SuperIO: Found NS87560 Legacy I/O device at %s (IRQ %i) \n", + pdev->slot_name,sio->iosapic_irq); + + /* Find our I/O devices */ + pci_read_config_word (pdev, SIO_SP1BAR, &sio->sp1_base); + sio->sp1_base &= ~1; + printk (KERN_INFO "SuperIO: Serial port 1 at 0x%x\n", sio->sp1_base); + + pci_read_config_word (pdev, SIO_SP2BAR, &sio->sp2_base); + sio->sp2_base &= ~1; + printk (KERN_INFO "SuperIO: Serial port 2 at 0x%x\n", sio->sp2_base); + + pci_read_config_word (pdev, SIO_PPBAR, &sio->pp_base); + sio->pp_base &= ~1; + printk (KERN_INFO "SuperIO: Parallel port at 0x%x\n", sio->pp_base); + + pci_read_config_word (pdev, SIO_FDCBAR, &sio->fdc_base); + sio->fdc_base &= ~1; + printk (KERN_INFO "SuperIO: Floppy controller at 0x%x\n", sio->fdc_base); + pci_read_config_word (pdev, SIO_ACPIBAR, &sio->acpi_base); + sio->acpi_base &= ~1; + printk (KERN_INFO "SuperIO: ACPI at 0x%x\n", sio->acpi_base); + + request_region (IC_PIC1, 0x1f, "pic1"); + request_region (IC_PIC2, 0x1f, "pic2"); + request_region (sio->acpi_base, 0x1f, "acpi"); + + /* Enable the legacy I/O function */ + pci_read_config_word (pdev, PCI_COMMAND, &word); + word |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_IO; + pci_write_config_word (pdev, PCI_COMMAND, word); + pci_set_master (pdev); + + /* Next project is programming the onboard interrupt + * controllers. PDC hasn't done this for us, since it's using + * polled I/O. + */ + + /* Set PIC interrupts to edge triggered */ + pci_write_config_byte (pdev, TRIGGER_1, 0x0); + pci_write_config_byte (pdev, TRIGGER_2, 0x0); + + /* Disable all interrupt routing */ + for (i = IR_LOW ; i < IR_HIGH ; i++) + pci_write_config_byte (pdev, i, 0x0); + + /* PIC1 Initialization Command Word register programming */ + outb (0x11,IC_PIC1+0); /* ICW1: ICW4 write req | ICW1 */ + outb (0x00,IC_PIC1+1); /* ICW2: N/A */ + outb (0x04,IC_PIC1+1); /* ICW3: Cascade */ + outb (0x01,IC_PIC1+1); /* ICW4: x86 mode */ + + /* PIC1 Program Operational Control Words */ + outb (0xff,IC_PIC1+1); /* OCW1: Mask all interrupts */ + outb (0xc2,IC_PIC1+0); /* OCW2: priority (3-7,0-2) */ + + /* PIC2 Initialization Command Word register programming */ + outb (0x11,IC_PIC2+0); /* ICW1: ICW4 write req | ICW1 */ + outb (0x00,IC_PIC2+1); /* ICW2: N/A */ + outb (0x02,IC_PIC2+1); /* ICW3: Slave ID code */ + outb (0x01,IC_PIC2+1); /* ICW4: x86 mode */ + + /* Program Operational Control Words */ + outb (0xff,IC_PIC1+1); /* OCW1: Mask all interrupts */ + outb (0x68,IC_PIC1+0); /* OCW3: OCW3 select | ESMM | SMM */ + + /* Write master mask reg */ + + outb (0xff,IC_PIC1+1); + + /* Set up interrupt routing */ + + pci_write_config_byte (pdev, IR_USB, 0x10); /* USB on IRQ1 */ + pci_write_config_byte (pdev, IR_SER, 0x43); /* SP1 on IRQ3, SP2 on IRQ4 */ + pci_write_config_byte (pdev, IR_PFD, 0x65); /* PAR on IRQ5, FDC on IRQ6 */ + pci_write_config_byte (pdev, IR_IDE, 0x07); /* IDE1 on IRQ7 */ + + /* Set USB and IDE to level triggered interrupts, rest to edge */ + pci_write_config_byte (pdev, TRIGGER_1, 0x82); /* IRQ 1 and 7 */ + + /* Setup USB power regulation */ + outb(1, sio->acpi_base + USB_REG_CR); + if (inb(sio->acpi_base + USB_REG_CR) & 1) + printk(KERN_INFO "SuperIO: USB regulator enabled\n"); + else + printk(KERN_ERR "USB regulator not initialized!\n"); + + pci_enable_device(pdev); + + if (request_irq(sio->iosapic_irq,superio_interrupt,SA_INTERRUPT, + "SuperIO",(void *)sio)) { + + printk(KERN_ERR "SuperIO: could not get irq\n"); + BUG(); + return; + } + + sio->iosapic_irq_enabled = 1; + +} + +static void +superio_disable_irq(void *dev, int local_irq) +{ + u8 r8; + + if ((local_irq < 1) || (local_irq == 2) || (local_irq > 7)) { + printk(KERN_ERR "SuperIO: Illegal irq number.\n"); + BUG(); + return; + } + + /* Mask interrupt */ + + r8 = inb(IC_PIC1+1); + r8 |= (1 << local_irq); + outb (r8,IC_PIC1+1); +} + +static void +superio_enable_irq(void *dev, int local_irq) +{ + struct superio_device *sio = (struct superio_device *)dev; + u8 r8; + + if ((local_irq < 1) || (local_irq == 2) || (local_irq > 7)) { + printk(KERN_ERR "SuperIO: Illegal irq number.\n"); + BUG(); + return; + } + + /* + * It's possible that we haven't initialized the legacy IO + * function yet. If not, do it now. + */ + + if (!sio->iosapic_irq_enabled) + superio_init(sio); + + /* Unmask interrupt */ + + r8 = inb(IC_PIC1+1); + r8 &= ~(1 << local_irq); + outb (r8,IC_PIC1+1); +} + +static void +superio_mask_irq(void *dev, int local_irq) +{ + BUG(); +} + +static void +superio_unmask_irq(void *dev, int local_irq) +{ + BUG(); +} + +static struct irq_region_ops superio_irq_ops = { + disable_irq: superio_disable_irq, + enable_irq: superio_enable_irq, + mask_irq: superio_mask_irq, + unmask_irq: superio_unmask_irq +}; + +#ifdef DEBUG_INIT +static unsigned short expected_device[3] = { + PCI_DEVICE_ID_NS_87415, + PCI_DEVICE_ID_NS_87560_LIO, + PCI_DEVICE_ID_NS_87560_USB +}; +#endif + +int superio_fixup_irq(struct pci_dev *pcidev) +{ + int local_irq; + +#ifdef DEBUG_INIT + int fn; + fn = PCI_FUNC(pcidev->devfn); + + /* Verify the function number matches the expected device id. */ + if (expected_device[fn] != pcidev->device) { + BUG(); + return -1; + } + printk("superio_fixup_irq(%s) ven 0x%x dev 0x%x from %p\n", + pcidev->slot_name, + pcidev->vendor, pcidev->device, + __builtin_return_address(0)); +#endif + + if (!sio_dev.irq_region) { + /* Allocate an irq region for SuperIO devices */ + sio_dev.irq_region = alloc_irq_region(SUPERIO_NIRQS, + &superio_irq_ops, + "SuperIO", (void *) &sio_dev); + if (!sio_dev.irq_region) { + printk(KERN_WARNING "SuperIO: alloc_irq_region failed\n"); + return -1; + } + } + + /* + * We don't allocate a SuperIO irq for the legacy IO function, + * since it is a "bridge". Instead, we will allocate irq's for + * each legacy device as they are initialized. + */ + + switch(pcidev->device) { + case PCI_DEVICE_ID_NS_87415: /* Function 0 */ + local_irq = IDE_IRQ; + break; + case PCI_DEVICE_ID_NS_87560_LIO: /* Function 1 */ + sio_dev.lio_pdev = pcidev; /* save for later initialization */ + return -1; + case PCI_DEVICE_ID_NS_87560_USB: /* Function 2 */ + local_irq = USB_IRQ; + break; + default: + local_irq = -1; + BUG(); + break; + } + + return(sio_dev.irq_region->data.irqbase + local_irq); +} + +void __devinit +superio_serial_init(void) +{ +#ifdef CONFIG_SERIAL + struct serial_struct *serial; + int retval; + + if (!sio_dev.irq_region) + return; /* superio not present */ + + if (!sio_dev.iosapic_irq_enabled) + superio_init(&sio_dev); + + serial = kmalloc(2 * sizeof (struct serial_struct), GFP_KERNEL); + + if (!serial) { + printk(KERN_WARNING "SuperIO: Could not get memory for serial struct.\n"); + return; + } + + memset(serial, 0, 2 * sizeof (struct serial_struct)); + + serial->type = PORT_16550A; + serial->line = 0; + serial->port = sio_dev.sp1_base; + serial->port_high = 0; + serial->irq = sio_dev.irq_region->data.irqbase + SP1_IRQ; + serial->io_type = SERIAL_IO_PORT; + serial->flags = 0; + serial->xmit_fifo_size = 16; + serial->custom_divisor = 0; + serial->baud_base = 115200; + + retval = register_serial(serial); + if (retval < 0) { + printk(KERN_WARNING "SuperIO: Register Serial #0 failed.\n"); + kfree (serial); + return; + } + + serial++; + + serial->type = PORT_16550A; + serial->line = 1; + serial->port = sio_dev.sp2_base; + serial->port_high = 0; + serial->irq = sio_dev.irq_region->data.irqbase + SP2_IRQ; + serial->io_type = SERIAL_IO_PORT; + serial->flags = 0; + serial->xmit_fifo_size = 16; + serial->custom_divisor = 0; + serial->baud_base = 115200; + + retval = register_serial(serial); + if (retval < 0) + printk(KERN_WARNING "SuperIO: Register Serial #1 failed.\n"); +#endif /* CONFIG_SERIAL */ +} + +EXPORT_SYMBOL(superio_serial_init); + + +#ifdef CONFIG_PARPORT_PC +void __devinit +superio_parport_init(void) +{ + if (!sio_dev.irq_region) + return; /* superio not present */ + + if (!sio_dev.iosapic_irq_enabled) + superio_init(&sio_dev); + + if (!parport_pc_probe_port(sio_dev.pp_base, + 0 /*base_hi*/, + sio_dev.irq_region->data.irqbase + PAR_IRQ, + PARPORT_DMA_NONE /* dma */, + NULL /*struct pci_dev* */)) + + printk(KERN_WARNING "SuperIO: Probing parallel port failed.\n"); +} + +EXPORT_SYMBOL(superio_parport_init); +#endif /* CONFIG_PARPORT_PC */ + + +int +superio_get_ide_irq(void) +{ + if (sio_dev.irq_region) + return sio_dev.irq_region->data.irqbase + IDE_IRQ; + else + return 0; +} + +EXPORT_SYMBOL(superio_get_ide_irq); + +static int __devinit superio_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ +#ifdef DEBUG_INIT + printk("superio_probe(%s) ven 0x%x dev 0x%x sv 0x%x sd 0x%x class 0x%x\n", + dev->slot_name, + dev->vendor, dev->device, + dev->subsystem_vendor, dev->subsystem_device, + dev->class); +/* +** superio_probe(00:0e.0) ven 0x100b dev 0x2 sv 0x0 sd 0x0 class 0x1018a +** superio_probe(00:0e.1) ven 0x100b dev 0xe sv 0x0 sd 0x0 class 0x68000 +** superio_probe(00:0e.2) ven 0x100b dev 0x12 sv 0x0 sd 0x0 class 0xc0310 +*/ +#endif + + /* superio_fixup_irq(dev); */ + + if (dev->device == PCI_DEVICE_ID_NS_87560_LIO) { +#ifdef CONFIG_PARPORT_PC + superio_parport_init(); +#endif + /* Don't call superio_serial_init() - see rs_init() */ + /* REVISIT : superio_fdc_init() ? */ + return 0; + } + else + { + /* don't claim this device; let whatever either driver + * do it + */ + return -1; + } +} + +static struct pci_device_id superio_tbl[] __devinitdata = { + { PCI_VENDOR_ID_NS, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { 0, } +}; + +static struct pci_driver superio_driver = { + name: "SuperIO", + id_table: superio_tbl, + probe: superio_probe, +}; + +static int __init superio_modinit(void) +{ + return pci_module_init(&superio_driver); +} + +static void __exit superio_exit(void) +{ + pci_unregister_driver(&superio_driver); +} + +module_init(superio_modinit); +module_exit(superio_exit); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/sys32.h linux.19rc3-ac4/arch/parisc/kernel/sys32.h --- linux.19rc3/arch/parisc/kernel/sys32.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/sys32.h 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,33 @@ +#ifndef _PARISC64_KERNEL_SYS32_H +#define _PARISC64_KERNEL_SYS32_H + +/* Call a kernel syscall which will use kernel space instead of user + * space for its copy_to/from_user. + */ +#define KERNEL_SYSCALL(ret, syscall, args...) \ +{ \ + mm_segment_t old_fs = get_fs(); \ + set_fs(KERNEL_DS); \ + ret = syscall(args); \ + set_fs (old_fs); \ +} + +struct timeval32 { + int tv_sec; + int tv_usec; +}; + +typedef __u32 __sighandler_t32; + +#include +typedef struct { + unsigned int sig[_NSIG_WORDS * 2]; +} sigset_t32; + +struct sigaction32 { + __sighandler_t32 sa_handler; + unsigned int sa_flags; + sigset_t32 sa_mask; /* mask last for extensibility */ +}; + +#endif diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/syscall.S linux.19rc3-ac4/arch/parisc/kernel/syscall.S --- linux.19rc3/arch/parisc/kernel/syscall.S 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/syscall.S 2002-07-29 13:58:37.000000000 +0100 @@ -1,5 +1,5 @@ /* - * Linux/PARISC Project (http://www.thepuffingroup.com/parisc) + * Linux/PA-RISC Project (http://www.parisc-linux.org/) * * System call entry code Copyright (c) Matthew Wilcox 1999 * Licensed under the GNU GPL. @@ -12,7 +12,6 @@ #include #include -#define __ASSEMBLY__ #include #include #include @@ -23,7 +22,13 @@ .level 1.1 #endif .text - + +#ifdef __LP64__ +#define FRAME_SIZE 128 +#else +#define FRAME_SIZE 64 +#endif + .import syscall_exit,code .import syscall_exit_rfi,code .export linux_gateway_page @@ -39,17 +44,30 @@ .align 4096 linux_gateway_page: + .rept 56 break 0,0 + .endr +set_thread_pointer: + gate .+8, %r0 /* increase privilege */ + depi 3, 31, 2, %r31 /* Ensure we return into user mode. */ + be 0(%sr7,%r31) /* return to user space */ + mtctl %r26, %cr27 /* move arg0 to the control register */ + + .rept 4 + break 0,0 + .endr + +/* This address must remain fixed, or user binaries go splat. */ .align 256 linux_gateway_entry: - mfsp %sr7,%r1 /* we must set sr3 to the space */ - mtsp %r1,%sr3 /* of the user before the gate */ gate .+8, %r0 /* become privileged */ mtsp %r0,%sr4 /* get kernel space into sr4 */ mtsp %r0,%sr5 /* get kernel space into sr5 */ mtsp %r0,%sr6 /* get kernel space into sr6 */ - mtsp %r0,%sr7 /* get kernel space into sr7 */ + mfsp %sr7,%r1 /* save user sr7 */ + mtsp %r1,%sr3 /* and store it in sr3 */ + #ifdef __LP64__ /* for now we can *always* set the W bit on entry to the syscall * since we don't support wide userland processes. We could @@ -58,15 +76,38 @@ * whether to do narrow or wide syscalls. -PB */ ssm PSW_SM_W, %r0 + /* The top halves of argument registers must be cleared on syscall + * entry. + */ + depdi 0, 31, 32, %r26 + depdi 0, 31, 32, %r25 + depdi 0, 31, 32, %r24 + depdi 0, 31, 32, %r23 + depdi 0, 31, 32, %r22 + depdi 0, 31, 32, %r21 #endif - mtctl %r28,%cr27 - rsm PSW_I, %r28 /* no ints for a bit */ - mfctl %cr30,%r1 /* get the kernel task ptr */ - mtctl %r0,%cr30 /* zero it (flag) */ + mfctl %cr30,%r1 + xor %r1,%r30,%r30 /* ye olde xor trick */ + xor %r1,%r30,%r1 + xor %r1,%r30,%r30 + ldo TASK_SZ_ALGN+FRAME_SIZE(%r30),%r30 /* set up kernel stack */ + + /* N.B.: It is critical that we don't set sr7 to 0 until r30 + * contains a valid kernel stack pointer. It is also + * critical that we don't start using the kernel stack + * until after sr7 has been set to 0. + */ + + mtsp %r0,%sr7 /* get kernel space into sr7 */ + STREG %r1,TASK_PT_GR30-TASK_SZ_ALGN-FRAME_SIZE(%r30) /* save usp */ + ldo -TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr in %r1 */ /* Save some registers for sigcontext and potential task switch (see entry.S for the details of which ones are - saved/restored) */ + saved/restored). TASK_PT_PSW is zeroed so we can see whether + a process is on a syscall or not. For an interrupt the real + PSW value is stored. This is needed for gdb and sys_ptrace. */ + STREG %r0, TASK_PT_PSW(%r1) STREG %r2, TASK_PT_GR2(%r1) /* preserve rp */ STREG %r19, TASK_PT_GR19(%r1) STREG %r20, TASK_PT_GR20(%r1) @@ -77,11 +118,9 @@ STREG %r25, TASK_PT_GR25(%r1) /* 2nd argument */ STREG %r26, TASK_PT_GR26(%r1) /* 1st argument */ STREG %r27, TASK_PT_GR27(%r1) /* user dp */ - mfctl %cr27,%r19 - STREG %r19, TASK_PT_GR28(%r1) /* return value 0 */ - STREG %r19, TASK_PT_ORIG_R28(%r1) /* return value 0 (saved for signals) */ + STREG %r28, TASK_PT_GR28(%r1) /* return value 0 */ + STREG %r28, TASK_PT_ORIG_R28(%r1) /* return value 0 (saved for signals) */ STREG %r29, TASK_PT_GR29(%r1) /* return value 1 */ - STREG %r30, TASK_PT_GR30(%r1) /* preserve userspace sp */ STREG %r31, TASK_PT_GR31(%r1) /* preserve syscall return ptr */ ldo TASK_PT_FR0(%r1), %r27 /* save fpregs from the kernel */ @@ -92,10 +131,10 @@ loadgp - ldo TASK_SZ_ALGN+64(%r1),%r30 /* set up kernel stack */ - -#ifndef __LP64__ - /* no need to save these on stack because in wide mode the first 8 +#ifdef __LP64__ + ldo -16(%r30),%r29 /* Reference param save area */ +#else + /* no need to save these on stack in wide mode because the first 8 * args are passed in registers */ stw %r22, -52(%r30) /* 5th argument */ stw %r21, -56(%r30) /* 6th argument */ @@ -103,7 +142,6 @@ /* for some unknown reason, task_struct.ptrace is an unsigned long so use LDREG */ LDREG TASK_PTRACE(%r1), %r19 /* Are we being ptraced? */ - mtsm %r28 /* irqs back */ bb,<,n %r19, 31, .Ltracesys /* must match PT_PTRACE bit */ @@ -112,7 +150,6 @@ ldil L%sys_call_table, %r1 ldo R%sys_call_table(%r1), %r19 - LDIL_FIXUP(%r19) comiclr,>>= __NR_Linux_syscalls, %r20, %r0 b,n .Lsyscall_nosys @@ -131,13 +168,11 @@ comb,= %r2,%r20,.Lrt_sigreturn .Lin_syscall: ldil L%syscall_exit,%r2 - LDIL_FIXUP(%r2) be 0(%sr7,%r19) ldo R%syscall_exit(%r2),%r2 .Lrt_sigreturn: comib,<> 0,%r25,.Lin_syscall ldil L%syscall_exit_rfi,%r2 - LDIL_FIXUP(%r2) be 0(%sr7,%r19) ldo R%syscall_exit_rfi(%r2),%r2 @@ -149,7 +184,6 @@ .Lsyscall_nosys: syscall_nosys: ldil L%syscall_exit,%r1 - LDIL_FIXUP(%r1) be R%syscall_exit(%sr7,%r1) ldo -ENOSYS(%r0),%r28 /* set errno */ @@ -159,12 +193,17 @@ .Ltracesys: tracesys: /* Need to save more registers so the debugger can see where we - * are. + * are. This saves only the lower 8 bits of PSW, so that the C + * bit is still clear on syscalls, and the D bit is set if this + * full register save path has been executed. We check the D + * bit on syscall_return_rfi to determine which registers to + * restore. An interrupt results in a full PSW saved with the + * C bit set, a non-straced syscall entry results in C and D clear + * in the saved PSW. */ - ldo -TASK_SZ_ALGN-64(%r30),%r1 /* get task ptr */ - ssm 0,%r2 /* Lower 8 bits only!! */ - STREG %r2,TASK_PT_PSW(%r1) - STREG %r1,TASK_PT_CR30(%r1) + ldo -TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */ + ssm 0,%r2 + STREG %r2,TASK_PT_PSW(%r1) /* Lower 8 bits only!! */ mfsp %sr0,%r2 STREG %r2,TASK_PT_SR0(%r1) mfsp %sr1,%r2 @@ -204,18 +243,15 @@ /* Finished saving things for the debugger */ ldil L%syscall_trace,%r1 - LDIL_FIXUP(%r1) ldil L%tracesys_next,%r2 - LDIL_FIXUP(%r2) be R%syscall_trace(%sr7,%r1) ldo R%tracesys_next(%r2),%r2 tracesys_next: ldil L%sys_call_table,%r1 - LDIL_FIXUP(%r1) ldo R%sys_call_table(%r1), %r19 - ldo -TASK_SZ_ALGN-64(%r30),%r1 /* get task ptr */ + ldo -TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */ LDREG TASK_PT_GR20(%r1), %r20 LDREG TASK_PT_GR26(%r1), %r26 /* Restore the users args */ LDREG TASK_PT_GR25(%r1), %r25 @@ -224,6 +260,7 @@ #ifdef __LP64__ LDREG TASK_PT_GR22(%r1), %r22 LDREG TASK_PT_GR21(%r1), %r21 + ldo -16(%r30),%r29 /* Reference param save area */ #endif comiclr,>>= __NR_Linux_syscalls, %r20, %r0 @@ -243,7 +280,6 @@ comb,= %r2,%r20,.Ltrace_rt_sigreturn .Ltrace_in_syscall: ldil L%tracesys_exit,%r2 - LDIL_FIXUP(%r2) be 0(%sr7,%r19) ldo R%tracesys_exit(%r2),%r2 @@ -251,30 +287,33 @@ makes a direct call to syscall_trace. */ tracesys_exit: - ldo -TASK_SZ_ALGN-64(%r30),%r1 /* get task ptr */ + ldo -TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */ +#ifdef __LP64__ + ldo -16(%r30),%r29 /* Reference param save area */ +#endif bl syscall_trace, %r2 STREG %r28,TASK_PT_GR28(%r1) /* save return value now */ - ldo -TASK_SZ_ALGN-64(%r30),%r1 /* get task ptr */ + ldo -TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */ LDREG TASK_PT_GR28(%r1), %r28 /* Restore return val. */ ldil L%syscall_exit,%r1 - LDIL_FIXUP(%r1) be,n R%syscall_exit(%sr7,%r1) .Ltrace_rt_sigreturn: comib,<> 0,%r25,.Ltrace_in_syscall ldil L%tracesys_sigexit,%r2 - LDIL_FIXUP(%r2) be 0(%sr7,%r19) ldo R%tracesys_sigexit(%r2),%r2 tracesys_sigexit: - ldo -TASK_SZ_ALGN-64(%r30),%r1 /* get task ptr */ + ldo -TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */ +#ifdef __LP64__ + ldo -16(%r30),%r29 /* Reference param save area */ +#endif bl syscall_trace, %r2 nop ldil L%syscall_exit_rfi,%r1 - LDIL_FIXUP(%r1) be,n R%syscall_exit_rfi(%sr7,%r1) #ifdef __LP64__ @@ -282,13 +321,13 @@ * narrow palinux. Use ENTRY_DIFF for those where a 32-bit specific * implementation is required on wide palinux. */ -#define ENTRY_SAME(_name_) .dword sys_##_name_ -#define ENTRY_DIFF(_name_) .dword sys32_##_name_ -#define ENTRY_UHOH(_name_) .dword sys32_unimplemented +#define ENTRY_SAME(_name_) .dword sys_/**/_name_ +#define ENTRY_DIFF(_name_) .dword sys32_/**/_name_ +#define ENTRY_UHOH(_name_) .dword sys32_/**/unimplemented #else -#define ENTRY_SAME(_name_) .word sys_##_name_ -#define ENTRY_DIFF(_name_) .word sys_##_name_ -#define ENTRY_UHOH(_name_) .word sys_##_name_ +#define ENTRY_SAME(_name_) .word sys_/**/_name_ +#define ENTRY_DIFF(_name_) .word sys_/**/_name_ +#define ENTRY_UHOH(_name_) .word sys_/**/_name_ #endif .align 8 @@ -316,7 +355,7 @@ ENTRY_SAME(socket) /* struct stat is MAYBE identical wide and narrow ?? */ ENTRY_DIFF(newstat) - ENTRY_SAME(lseek) + ENTRY_DIFF(lseek) ENTRY_SAME(getpid) /* 20 */ /* the 'void * data' parameter may need re-packing in wide */ ENTRY_DIFF(mount) @@ -391,8 +430,8 @@ ENTRY_DIFF(getrlimit) ENTRY_DIFF(getrusage) /* struct timeval and timezone are maybe?? consistent wide and narrow */ - ENTRY_SAME(gettimeofday) - ENTRY_SAME(settimeofday) + ENTRY_DIFF(gettimeofday) + ENTRY_DIFF(settimeofday) ENTRY_SAME(getgroups) /* 80 */ ENTRY_SAME(setgroups) /* struct socketaddr... */ @@ -402,12 +441,12 @@ ENTRY_DIFF(newlstat) ENTRY_SAME(readlink) /* 85 */ /* suspect we'll need some work for narrow shlibs on wide kernel */ + /* NOTE this doesn't get used when I boot 32-bit userspace */ + /* containing working shlib apps -- can this be nuked? */ ENTRY_UHOH(uselib) ENTRY_SAME(swapon) ENTRY_SAME(reboot) - /* argh! struct dirent contains a long */ - ENTRY_UHOH(old_readdir) - /* I'm not certain about off_t... */ + ENTRY_SAME(mmap2) ENTRY_SAME(mmap) /* 90 */ ENTRY_SAME(munmap) ENTRY_SAME(truncate) @@ -419,28 +458,27 @@ ENTRY_SAME(recv) ENTRY_DIFF(statfs) ENTRY_DIFF(fstatfs) /* 100 */ - ENTRY_SAME(ni_syscall) + ENTRY_SAME(stat64) /* don't think hppa glibc even provides an entry pt for this * so disable for now */ ENTRY_UHOH(socketcall) ENTRY_SAME(syslog) /* even though manpage says struct timeval contains longs, ours has * time_t and suseconds_t -- both of which are safe wide/narrow */ - ENTRY_SAME(setitimer) - ENTRY_SAME(getitimer) /* 105 */ + ENTRY_DIFF(setitimer) + ENTRY_DIFF(getitimer) /* 105 */ ENTRY_SAME(capget) ENTRY_SAME(capset) - ENTRY_SAME(pread) - ENTRY_SAME(pwrite) + ENTRY_DIFF(pread) + ENTRY_DIFF(pwrite) ENTRY_SAME(getcwd) /* 110 */ ENTRY_SAME(vhangup) - ENTRY_SAME(ni_syscall) + ENTRY_SAME(fstat64) ENTRY_SAME(vfork_wrapper) /* struct rusage contains longs... */ ENTRY_DIFF(wait4) ENTRY_SAME(swapoff) /* 115 */ - /* struct sysinfo contains longs */ - ENTRY_SAME(sysinfo) + ENTRY_DIFF(sysinfo) ENTRY_SAME(shutdown) ENTRY_SAME(fsync) ENTRY_SAME(madvise) @@ -450,7 +488,7 @@ /* struct sockaddr... */ ENTRY_SAME(recvfrom) /* struct timex contains longs */ - ENTRY_UHOH(adjtimex) + ENTRY_DIFF(adjtimex) ENTRY_SAME(mprotect) /* 125 */ /* old_sigset_t forced to 32 bits. Beware glibc sigset_t */ ENTRY_DIFF(sigprocmask) @@ -461,12 +499,11 @@ ENTRY_SAME(delete_module) /* struct kernel_sym contains a long. Linus never heard of size_t? */ ENTRY_DIFF(get_kernel_syms) /* 130 */ - ENTRY_SAME(quotactl) + /* time_t inside struct dqblk */ + ENTRY_DIFF(quotactl) ENTRY_SAME(getpgid) ENTRY_SAME(fchdir) - /* bdflush(func, addr) where func has least-significant-bit set means - * addr is a pointer to long :-( */ - ENTRY_UHOH(bdflush) + ENTRY_SAME(bdflush) ENTRY_SAME(sysfs) /* 135 */ ENTRY_SAME(personality) ENTRY_SAME(ni_syscall) /* for afs_syscall */ @@ -479,12 +516,12 @@ ENTRY_DIFF(getdents) /* it is POSSIBLE that select will be OK because even though fd_set * contains longs, the macros and sizes are clever. */ - ENTRY_SAME(select) + ENTRY_DIFF(select) ENTRY_SAME(flock) ENTRY_SAME(msync) /* struct iovec contains pointers */ - ENTRY_UHOH(readv) /* 145 */ - ENTRY_UHOH(writev) + ENTRY_DIFF(readv) /* 145 */ + ENTRY_DIFF(writev) ENTRY_SAME(getsid) ENTRY_SAME(fdatasync) /* struct __sysctl_args is a mess */ @@ -509,13 +546,12 @@ ENTRY_SAME(mremap) ENTRY_SAME(setresuid) ENTRY_SAME(getresuid) /* 165 */ - /* might work, but in general signals need a thorough review */ - ENTRY_UHOH(sigaltstack_wrapper) + ENTRY_DIFF(sigaltstack_wrapper) /* struct passed back to user can contain long symbol values */ ENTRY_DIFF(query_module) ENTRY_SAME(poll) /* structs contain pointers and an in_addr... */ - ENTRY_UHOH(nfsservctl) + ENTRY_DIFF(nfsservctl) ENTRY_SAME(setresgid) /* 170 */ ENTRY_SAME(getresgid) ENTRY_SAME(prctl) @@ -525,35 +561,43 @@ ENTRY_DIFF(rt_sigprocmask) /* 175 */ ENTRY_DIFF(rt_sigpending) ENTRY_UHOH(rt_sigtimedwait) - ENTRY_UHOH(rt_sigqueueinfo) + /* even though the struct siginfo_t is different, it appears like + * all the paths use values which should be same wide and narrow. + * Also the struct is padded to 128 bytes which means we don't have + * to worry about faulting trying to copy in a larger 64-bit + * struct from a 32-bit user-space app. + */ + ENTRY_SAME(rt_sigqueueinfo) ENTRY_SAME(rt_sigsuspend_wrapper) /* not really SAME -- see the code */ ENTRY_SAME(chown) /* 180 */ - /* *sockopt() might work... */ - ENTRY_SAME(setsockopt) + /* setsockopt() used by iptables: SO_SET_REPLACE/SO_SET_ADD_COUNTERS */ + ENTRY_DIFF(setsockopt) ENTRY_SAME(getsockopt) - /* struct msghdr contains pointers... */ - ENTRY_UHOH(sendmsg) - ENTRY_UHOH(recvmsg) + ENTRY_DIFF(sendmsg) + ENTRY_DIFF(recvmsg) ENTRY_SAME(semop) /* 185 */ ENTRY_SAME(semget) - /* needs a more careful review */ - ENTRY_UHOH(semctl) - /* struct msgbuf contains a long */ - ENTRY_UHOH(msgsnd) - ENTRY_UHOH(msgrcv) + ENTRY_DIFF(semctl_broken) + ENTRY_DIFF(msgsnd) + ENTRY_DIFF(msgrcv) ENTRY_SAME(msgget) /* 190 */ - /* struct msqid_ds contains pointers */ - ENTRY_UHOH(msgctl) + ENTRY_SAME(msgctl_broken) ENTRY_SAME(shmat_wrapper) ENTRY_SAME(shmdt) ENTRY_SAME(shmget) - /***************/ - /* struct shmid_ds contains pointers */ - ENTRY_UHOH(shmctl) /* 195 */ + ENTRY_SAME(shmctl_broken) /* 195 */ ENTRY_SAME(ni_syscall) /* streams1 */ ENTRY_SAME(ni_syscall) /* streams2 */ + ENTRY_SAME(lstat64) + ENTRY_DIFF(truncate64) + ENTRY_DIFF(ftruncate64) /* 200 */ + ENTRY_SAME(getdents64) + ENTRY_DIFF(fcntl64) + ENTRY_SAME(ni_syscall) /* attrctl */ + ENTRY_SAME(ni_syscall) /* acl_get */ + ENTRY_SAME(ni_syscall) /* acl_set */ ENTRY_SAME(gettid) - ENTRY_SAME(tkill) + ENTRY_SAME(readahead) .end diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/sys_parisc32.c linux.19rc3-ac4/arch/parisc/kernel/sys_parisc32.c --- linux.19rc3/arch/parisc/kernel/sys_parisc32.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/sys_parisc32.c 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,3117 @@ +/* + * sys_parisc32.c: Conversion between 32bit and 64bit native syscalls. + * + * Copyright (C) 2000-2001 Hewlett Packard Company + * Copyright (C) 2000 John Marvin + * Copyright (C) 2001 Matthew Wilcox + * + * These routines maintain argument size conversion between 32bit and 64bit + * environment. Based heavily on sys_ia32.c and sys_sparc32.c. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for setsockopt() */ +#include /* for setsockopt() */ +#include /* for setsockopt() */ +#include /* for setsockopt() */ +#include /* for setsockopt() */ +#include +#include +#include + +#include +#include +#include + +#include "sys32.h" + +#define A(__x) ((unsigned long)(__x)) + + +#undef DEBUG + +#ifdef DEBUG +#define DBG(x) printk x +#else +#define DBG(x) +#endif + + +/* + * count32() counts the number of arguments/envelopes. It is basically + * a copy of count() from fs/exec.c, except that it works + * with 32 bit argv and envp pointers. + */ + +static int count32(u32 *argv, int max) +{ + int i = 0; + + if (argv != NULL) { + for (;;) { + u32 p; + int error; + + error = get_user(p,argv); + if (error) + return error; + if (!p) + break; + argv++; + if(++i > max) + return -E2BIG; + } + } + return i; +} + + +/* + * copy_strings32() is basically a copy of copy_strings() from fs/exec.c + * except that it works with 32 bit argv and envp pointers. + */ + + +static int copy_strings32(int argc, u32 *argv, struct linux_binprm *bprm) +{ + while (argc-- > 0) { + u32 str; + int len; + unsigned long pos; + + if (get_user(str, argv + argc) || + !str || + !(len = strnlen_user((char *)A(str), bprm->p))) + return -EFAULT; + + if (bprm->p < len) + return -E2BIG; + + bprm->p -= len; + + pos = bprm->p; + while (len > 0) { + char *kaddr; + int i, new, err; + struct page *page; + int offset, bytes_to_copy; + + offset = pos % PAGE_SIZE; + i = pos/PAGE_SIZE; + page = bprm->page[i]; + new = 0; + if (!page) { + page = alloc_page(GFP_HIGHUSER); + bprm->page[i] = page; + if (!page) + return -ENOMEM; + new = 1; + } + kaddr = (char *)kmap(page); + + if (new && offset) + memset(kaddr, 0, offset); + bytes_to_copy = PAGE_SIZE - offset; + if (bytes_to_copy > len) { + bytes_to_copy = len; + if (new) + memset(kaddr+offset+len, 0, PAGE_SIZE-offset-len); + } + err = copy_from_user(kaddr + offset, (char *)A(str), bytes_to_copy); + flush_dcache_page(page); + flush_page_to_ram(page); + kunmap(page); + + if (err) + return -EFAULT; + + pos += bytes_to_copy; + str += bytes_to_copy; + len -= bytes_to_copy; + } + } + return 0; +} + +/* + * do_execve32() is mostly a copy of do_execve(), with the exception + * that it processes 32 bit argv and envp pointers. + */ + +static inline int +do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs) +{ + struct linux_binprm bprm; + struct file *file; + int retval; + int i; + + file = open_exec(filename); + + retval = PTR_ERR(file); + if (IS_ERR(file)) + return retval; + + bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); + memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0])); + + DBG(("do_execve32(%s, %p, %p, %p)\n", filename, argv, envp, regs)); + + bprm.file = file; + bprm.filename = filename; + bprm.sh_bang = 0; + bprm.loader = 0; + bprm.exec = 0; + if ((bprm.argc = count32(argv, bprm.p / sizeof(u32))) < 0) { + allow_write_access(file); + fput(file); + return bprm.argc; + } + if ((bprm.envc = count32(envp, bprm.p / sizeof(u32))) < 0) { + allow_write_access(file); + fput(file); + return bprm.envc; + } + + retval = prepare_binprm(&bprm); + if (retval < 0) + goto out; + + retval = copy_strings_kernel(1, &bprm.filename, &bprm); + if (retval < 0) + goto out; + + bprm.exec = bprm.p; + retval = copy_strings32(bprm.envc, envp, &bprm); + if (retval < 0) + goto out; + + retval = copy_strings32(bprm.argc, argv, &bprm); + if (retval < 0) + goto out; + + retval = search_binary_handler(&bprm,regs); + if (retval >= 0) + /* execve success */ + return retval; + +out: + /* Something went wrong, return the inode and free the argument pages*/ + allow_write_access(bprm.file); + if (bprm.file) + fput(bprm.file); + + for (i = 0 ; i < MAX_ARG_PAGES ; i++) { + struct page * page = bprm.page[i]; + if (page) + __free_page(page); + } + + return retval; +} + +/* + * sys32_execve() executes a new program. + */ + +asmlinkage int sys32_execve(struct pt_regs *regs) +{ + int error; + char *filename; + + DBG(("sys32_execve(%p) r26 = 0x%lx\n", regs, regs->gr[26])); + filename = getname((char *) regs->gr[26]); + error = PTR_ERR(filename); + if (IS_ERR(filename)) + goto out; + error = do_execve32(filename, (u32 *) regs->gr[25], + (u32 *) regs->gr[24], regs); + if (error == 0) + current->ptrace &= ~PT_DTRACE; + putname(filename); +out: + + return error; +} + +asmlinkage long sys32_unimplemented(int r26, int r25, int r24, int r23, + int r22, int r21, int r20) +{ + printk(KERN_ERR "%s(%d): Unimplemented 32 on 64 syscall #%d!\n", + current->comm, current->pid, r20); + return -ENOSYS; +} + +/* 32-bit user apps use struct statfs which uses 'long's */ +struct statfs32 { + __s32 f_type; + __s32 f_bsize; + __s32 f_blocks; + __s32 f_bfree; + __s32 f_bavail; + __s32 f_files; + __s32 f_ffree; + __kernel_fsid_t f_fsid; + __s32 f_namelen; + __s32 f_spare[6]; +}; + +/* convert statfs struct to statfs32 struct and copy result to user */ +static unsigned long statfs32_to_user(struct statfs32 *ust32, struct statfs *st) +{ + struct statfs32 st32; +#undef CP +#define CP(a) st32.a = st->a + CP(f_type); + CP(f_bsize); + CP(f_blocks); + CP(f_bfree); + CP(f_bavail); + CP(f_files); + CP(f_ffree); + CP(f_fsid); + CP(f_namelen); + return copy_to_user(ust32, &st32, sizeof st32); +} + +/* The following statfs calls are copies of code from linux/fs/open.c and + * should be checked against those from time to time */ +asmlinkage long sys32_statfs(const char * path, struct statfs32 * buf) +{ + struct nameidata nd; + int error; + + error = user_path_walk(path, &nd); + if (!error) { + struct statfs tmp; + error = vfs_statfs(nd.dentry->d_inode->i_sb, &tmp); + if (!error && statfs32_to_user(buf, &tmp)) + error = -EFAULT; + path_release(&nd); + } + return error; +} + +asmlinkage long sys32_fstatfs(unsigned int fd, struct statfs32 * buf) +{ + struct file * file; + struct statfs tmp; + int error; + + error = -EBADF; + file = fget(fd); + if (!file) + goto out; + error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp); + if (!error && statfs32_to_user(buf, &tmp)) + error = -EFAULT; + fput(file); +out: + return error; +} + +/* These may not work without my local types changes, but I wanted the + * code available in case it's useful to others. -PB + */ + +/* from utime.h */ +struct utimbuf32 { + __kernel_time_t32 actime; + __kernel_time_t32 modtime; +}; + +asmlinkage long sys32_utime(char *filename, struct utimbuf32 *times) +{ + struct utimbuf32 times32; + struct utimbuf times64; + extern long sys_utime(char *filename, struct utimbuf *times); + char *fname; + long ret; + + if (!times) + return sys_utime(filename, NULL); + + /* get the 32-bit struct from user space */ + if (copy_from_user(×32, times, sizeof times32)) + return -EFAULT; + + /* convert it into the 64-bit one */ + times64.actime = times32.actime; + times64.modtime = times32.modtime; + + /* grab the file name */ + fname = getname(filename); + + KERNEL_SYSCALL(ret, sys_utime, fname, ×64); + + /* free the file name */ + putname(fname); + + return ret; +} + +struct tms32 { + __kernel_clock_t32 tms_utime; + __kernel_clock_t32 tms_stime; + __kernel_clock_t32 tms_cutime; + __kernel_clock_t32 tms_cstime; +}; + +asmlinkage long sys32_times(struct tms32 *tbuf) +{ + struct tms t; + long ret; + extern asmlinkage long sys_times(struct tms * tbuf); +int err; + + KERNEL_SYSCALL(ret, sys_times, tbuf ? &t : NULL); + if (tbuf) { + err = put_user (t.tms_utime, &tbuf->tms_utime); + err |= __put_user (t.tms_stime, &tbuf->tms_stime); + err |= __put_user (t.tms_cutime, &tbuf->tms_cutime); + err |= __put_user (t.tms_cstime, &tbuf->tms_cstime); + if (err) + ret = -EFAULT; + } + return ret; +} + +struct flock32 { + short l_type; + short l_whence; + __kernel_off_t32 l_start; + __kernel_off_t32 l_len; + __kernel_pid_t32 l_pid; +}; + + +static inline int get_flock(struct flock *kfl, struct flock32 *ufl) +{ + int err; + + err = get_user(kfl->l_type, &ufl->l_type); + err |= __get_user(kfl->l_whence, &ufl->l_whence); + err |= __get_user(kfl->l_start, &ufl->l_start); + err |= __get_user(kfl->l_len, &ufl->l_len); + err |= __get_user(kfl->l_pid, &ufl->l_pid); + return err; +} + +static inline int put_flock(struct flock *kfl, struct flock32 *ufl) +{ + int err; + + err = __put_user(kfl->l_type, &ufl->l_type); + err |= __put_user(kfl->l_whence, &ufl->l_whence); + err |= __put_user(kfl->l_start, &ufl->l_start); + err |= __put_user(kfl->l_len, &ufl->l_len); + err |= __put_user(kfl->l_pid, &ufl->l_pid); + return err; +} + +extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg); + +asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case F_GETLK: + case F_SETLK: + case F_SETLKW: + { + struct flock f; + long ret; + + if(get_flock(&f, (struct flock32 *)arg)) + return -EFAULT; + KERNEL_SYSCALL(ret, sys_fcntl, fd, cmd, (unsigned long)&f); + if (ret) return ret; + if (f.l_start >= 0x7fffffffUL || + f.l_len >= 0x7fffffffUL || + f.l_start + f.l_len >= 0x7fffffffUL) + return -EOVERFLOW; + if(put_flock(&f, (struct flock32 *)arg)) + return -EFAULT; + return 0; + } + default: + return sys_fcntl(fd, cmd, (unsigned long)arg); + } +} + +#ifdef CONFIG_SYSCTL + +struct __sysctl_args32 { + u32 name; + int nlen; + u32 oldval; + u32 oldlenp; + u32 newval; + u32 newlen; + u32 __unused[4]; +}; + +asmlinkage long sys32_sysctl(struct __sysctl_args32 *args) +{ + struct __sysctl_args32 tmp; + int error; + unsigned int oldlen32; + size_t oldlen, *oldlenp = NULL; + unsigned long addr = (((long)&args->__unused[0]) + 7) & ~7; + extern int do_sysctl(int *name, int nlen, void *oldval, size_t *oldlenp, + void *newval, size_t newlen); + + DBG(("sysctl32(%p)\n", args)); + + if (copy_from_user(&tmp, args, sizeof(tmp))) + return -EFAULT; + + if (tmp.oldval && tmp.oldlenp) { + /* Duh, this is ugly and might not work if sysctl_args + is in read-only memory, but do_sysctl does indirectly + a lot of uaccess in both directions and we'd have to + basically copy the whole sysctl.c here, and + glibc's __sysctl uses rw memory for the structure + anyway. */ + /* a possibly better hack than this, which will avoid the + * problem if the struct is read only, is to push the + * 'oldlen' value out to the user's stack instead. -PB + */ + if (get_user(oldlen32, (u32 *)(u64)tmp.oldlenp)) + return -EFAULT; + oldlen = oldlen32; + if (put_user(oldlen, (size_t *)addr)) + return -EFAULT; + oldlenp = (size_t *)addr; + } + + lock_kernel(); + error = do_sysctl((int *)(u64)tmp.name, tmp.nlen, (void *)(u64)tmp.oldval, + oldlenp, (void *)(u64)tmp.newval, tmp.newlen); + unlock_kernel(); + if (oldlenp) { + if (!error) { + if (get_user(oldlen, (size_t *)addr)) { + error = -EFAULT; + } else { + oldlen32 = oldlen; + if (put_user(oldlen32, (u32 *)(u64)tmp.oldlenp)) + error = -EFAULT; + } + } + if (copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused))) + error = -EFAULT; + } + return error; +} + +#else /* CONFIG_SYSCTL */ + +asmlinkage long sys32_sysctl(struct __sysctl_args *args) +{ + return -ENOSYS; +} +#endif /* CONFIG_SYSCTL */ + +struct timespec32 { + s32 tv_sec; + s32 tv_nsec; +}; + +static int +put_timespec32(struct timespec32 *u, struct timespec *t) +{ + struct timespec32 t32; + t32.tv_sec = t->tv_sec; + t32.tv_nsec = t->tv_nsec; + return copy_to_user(u, &t32, sizeof t32); +} + +asmlinkage int sys32_nanosleep(struct timespec32 *rqtp, struct timespec32 *rmtp) +{ + struct timespec t; + struct timespec32 t32; + int ret; + extern asmlinkage int sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp); + + if (copy_from_user(&t32, rqtp, sizeof t32)) + return -EFAULT; + t.tv_sec = t32.tv_sec; + t.tv_nsec = t32.tv_nsec; + + DBG(("sys32_nanosleep({%d, %d})\n", t32.tv_sec, t32.tv_nsec)); + + KERNEL_SYSCALL(ret, sys_nanosleep, &t, rmtp ? &t : NULL); + if (rmtp && ret == -EINTR) { + if (put_timespec32(rmtp, &t)) + return -EFAULT; + } + return ret; +} + +asmlinkage long sys32_sched_rr_get_interval(pid_t pid, + struct timespec32 *interval) +{ + struct timespec t; + int ret; + extern asmlinkage long sys_sched_rr_get_interval(pid_t pid, struct timespec *interval); + + KERNEL_SYSCALL(ret, sys_sched_rr_get_interval, pid, &t); + if (put_timespec32(interval, &t)) + return -EFAULT; + return ret; +} + +typedef __kernel_time_t32 time_t32; + +static int +put_timeval32(struct timeval32 *u, struct timeval *t) +{ + struct timeval32 t32; + t32.tv_sec = t->tv_sec; + t32.tv_usec = t->tv_usec; + return copy_to_user(u, &t32, sizeof t32); +} + +static int +get_timeval32(struct timeval32 *u, struct timeval *t) +{ + int err; + struct timeval32 t32; + + if ((err = copy_from_user(&t32, u, sizeof t32)) == 0) + { + t->tv_sec = t32.tv_sec; + t->tv_usec = t32.tv_usec; + } + return err; +} + +asmlinkage long sys32_time(time_t32 *tloc) +{ + time_t now = CURRENT_TIME; + time_t32 now32 = now; + + if (tloc) + if (put_user(now32, tloc)) + now32 = -EFAULT; + + return now32; +} + +asmlinkage int +sys32_gettimeofday(struct timeval32 *tv, struct timezone *tz) +{ + extern void do_gettimeofday(struct timeval *tv); + + if (tv) { + struct timeval ktv; + do_gettimeofday(&ktv); + if (put_timeval32(tv, &ktv)) + return -EFAULT; + } + if (tz) { + extern struct timezone sys_tz; + if (copy_to_user(tz, &sys_tz, sizeof(sys_tz))) + return -EFAULT; + } + return 0; +} + +asmlinkage int +sys32_settimeofday(struct timeval32 *tv, struct timezone *tz) +{ + struct timeval ktv; + struct timezone ktz; + extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz); + + if (tv) { + if (get_timeval32(tv, &ktv)) + return -EFAULT; + } + if (tz) { + if (copy_from_user(&ktz, tz, sizeof(ktz))) + return -EFAULT; + } + + return do_sys_settimeofday(tv ? &ktv : NULL, tz ? &ktz : NULL); +} + +struct itimerval32 { + struct timeval32 it_interval; /* timer interval */ + struct timeval32 it_value; /* current value */ +}; + +asmlinkage long sys32_getitimer(int which, struct itimerval32 *ov32) +{ + int error = -EFAULT; + struct itimerval get_buffer; + extern int do_getitimer(int which, struct itimerval *value); + + if (ov32) { + error = do_getitimer(which, &get_buffer); + if (!error) { + struct itimerval32 gb32; + gb32.it_interval.tv_sec = get_buffer.it_interval.tv_sec; + gb32.it_interval.tv_usec = get_buffer.it_interval.tv_usec; + gb32.it_value.tv_sec = get_buffer.it_value.tv_sec; + gb32.it_value.tv_usec = get_buffer.it_value.tv_usec; + if (copy_to_user(ov32, &gb32, sizeof(gb32))) + error = -EFAULT; + } + } + return error; +} + +asmlinkage long sys32_setitimer(int which, struct itimerval32 *v32, + struct itimerval32 *ov32) +{ + struct itimerval set_buffer, get_buffer; + struct itimerval32 sb32, gb32; + extern int do_setitimer(int which, struct itimerval *value, struct itimerval *ov32); + int error; + + if (v32) { + if(copy_from_user(&sb32, v32, sizeof(sb32))) + return -EFAULT; + + set_buffer.it_interval.tv_sec = sb32.it_interval.tv_sec; + set_buffer.it_interval.tv_usec = sb32.it_interval.tv_usec; + set_buffer.it_value.tv_sec = sb32.it_value.tv_sec; + set_buffer.it_value.tv_usec = sb32.it_value.tv_usec; + } else + memset((char *) &set_buffer, 0, sizeof(set_buffer)); + + error = do_setitimer(which, &set_buffer, ov32 ? &get_buffer : 0); + if (error || !ov32) + return error; + + gb32.it_interval.tv_sec = get_buffer.it_interval.tv_sec; + gb32.it_interval.tv_usec = get_buffer.it_interval.tv_usec; + gb32.it_value.tv_sec = get_buffer.it_value.tv_sec; + gb32.it_value.tv_usec = get_buffer.it_value.tv_usec; + if (copy_to_user(ov32, &gb32, sizeof(gb32))) + return -EFAULT; + return 0; +} + +struct rusage32 { + struct timeval32 ru_utime; + struct timeval32 ru_stime; + int ru_maxrss; + int ru_ixrss; + int ru_idrss; + int ru_isrss; + int ru_minflt; + int ru_majflt; + int ru_nswap; + int ru_inblock; + int ru_oublock; + int ru_msgsnd; + int ru_msgrcv; + int ru_nsignals; + int ru_nvcsw; + int ru_nivcsw; +}; + +static int +put_rusage32(struct rusage32 *ru32p, struct rusage *r) +{ + struct rusage32 r32; +#undef CP +#define CP(t) r32.t = r->t; + CP(ru_utime.tv_sec); CP(ru_utime.tv_usec); + CP(ru_stime.tv_sec); CP(ru_stime.tv_usec); + CP(ru_maxrss); + CP(ru_ixrss); + CP(ru_idrss); + CP(ru_isrss); + CP(ru_minflt); + CP(ru_majflt); + CP(ru_nswap); + CP(ru_inblock); + CP(ru_oublock); + CP(ru_msgsnd); + CP(ru_msgrcv); + CP(ru_nsignals); + CP(ru_nvcsw); + CP(ru_nivcsw); + return copy_to_user(ru32p, &r32, sizeof r32); +} + +asmlinkage int +sys32_getrusage(int who, struct rusage32 *ru) +{ + struct rusage r; + int ret; + extern asmlinkage int sys_getrusage(int who, struct rusage *ru); + + KERNEL_SYSCALL(ret, sys_getrusage, who, &r); + if (put_rusage32(ru, &r)) return -EFAULT; + return ret; +} + +asmlinkage int +sys32_wait4(__kernel_pid_t32 pid, unsigned int * stat_addr, int options, + struct rusage32 * ru) +{ + if (!ru) + return sys_wait4(pid, stat_addr, options, NULL); + else { + struct rusage r; + int ret; + unsigned int status; + + KERNEL_SYSCALL(ret, sys_wait4, pid, stat_addr ? &status : NULL, options, &r); + if (put_rusage32(ru, &r)) return -EFAULT; + if (stat_addr && put_user(status, stat_addr)) + return -EFAULT; + return ret; + } +} + +struct stat32 { + __kernel_dev_t32 st_dev; /* dev_t is 32 bits on parisc */ + __kernel_ino_t32 st_ino; /* 32 bits */ + __kernel_mode_t32 st_mode; /* 16 bits */ + __kernel_nlink_t32 st_nlink; /* 16 bits */ + unsigned short st_reserved1; /* old st_uid */ + unsigned short st_reserved2; /* old st_gid */ + __kernel_dev_t32 st_rdev; + __kernel_off_t32 st_size; + __kernel_time_t32 st_atime; + unsigned int st_spare1; + __kernel_time_t32 st_mtime; + unsigned int st_spare2; + __kernel_time_t32 st_ctime; + unsigned int st_spare3; + int st_blksize; + int st_blocks; + unsigned int __unused1; /* ACL stuff */ + __kernel_dev_t32 __unused2; /* network */ + __kernel_ino_t32 __unused3; /* network */ + unsigned int __unused4; /* cnodes */ + unsigned short __unused5; /* netsite */ + short st_fstype; + __kernel_dev_t32 st_realdev; + unsigned short st_basemode; + unsigned short st_spareshort; + __kernel_uid_t32 st_uid; + __kernel_gid_t32 st_gid; + unsigned int st_spare4[3]; +}; + +/* + * Revalidate the inode. This is required for proper NFS attribute caching. + */ +static __inline__ int +do_revalidate(struct dentry *dentry) +{ + struct inode * inode = dentry->d_inode; + if (inode->i_op && inode->i_op->revalidate) + return inode->i_op->revalidate(dentry); + return 0; +} + + +static int cp_new_stat32(struct inode *inode, struct stat32 *statbuf) +{ + struct stat32 tmp; + unsigned int blocks, indirect; + + memset(&tmp, 0, sizeof(tmp)); + tmp.st_dev = kdev_t_to_nr(inode->i_dev); + tmp.st_ino = inode->i_ino; + tmp.st_mode = inode->i_mode; + tmp.st_nlink = inode->i_nlink; + SET_STAT_UID(tmp, inode->i_uid); + SET_STAT_GID(tmp, inode->i_gid); + tmp.st_rdev = kdev_t_to_nr(inode->i_rdev); +#if BITS_PER_LONG == 32 + if (inode->i_size > 0x7fffffff) + return -EOVERFLOW; +#endif + tmp.st_size = inode->i_size; + tmp.st_atime = inode->i_atime; + tmp.st_mtime = inode->i_mtime; + tmp.st_ctime = inode->i_ctime; +/* + * st_blocks and st_blksize are approximated with a simple algorithm if + * they aren't supported directly by the filesystem. The minix and msdos + * filesystems don't keep track of blocks, so they would either have to + * be counted explicitly (by delving into the file itself), or by using + * this simple algorithm to get a reasonable (although not 100% accurate) + * value. + */ + +/* + * Use minix fs values for the number of direct and indirect blocks. The + * count is now exact for the minix fs except that it counts zero blocks. + * Everything is in units of BLOCK_SIZE until the assignment to + * tmp.st_blksize. + */ +#define D_B 7 +#define I_B (BLOCK_SIZE / sizeof(unsigned short)) + + if (!inode->i_blksize) { + blocks = (tmp.st_size + BLOCK_SIZE - 1) / BLOCK_SIZE; + if (blocks > D_B) { + indirect = (blocks - D_B + I_B - 1) / I_B; + blocks += indirect; + if (indirect > 1) { + indirect = (indirect - 1 + I_B - 1) / I_B; + blocks += indirect; + if (indirect > 1) + blocks++; + } + } + tmp.st_blocks = (BLOCK_SIZE / 512) * blocks; + tmp.st_blksize = BLOCK_SIZE; + } else { + tmp.st_blocks = inode->i_blocks; + tmp.st_blksize = inode->i_blksize; + } + return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; +} + +asmlinkage long sys32_newstat(char * filename, struct stat32 *statbuf) +{ + struct nameidata nd; + int error; + + error = user_path_walk(filename, &nd); + if (!error) { + error = do_revalidate(nd.dentry); + if (!error) + error = cp_new_stat32(nd.dentry->d_inode, statbuf); + path_release(&nd); + } + return error; +} + +asmlinkage long sys32_newlstat(char * filename, struct stat32 *statbuf) +{ + struct nameidata nd; + int error; + + error = user_path_walk_link(filename, &nd); + if (!error) { + error = do_revalidate(nd.dentry); + if (!error) + error = cp_new_stat32(nd.dentry->d_inode, statbuf); + path_release(&nd); + } + return error; +} + +asmlinkage long sys32_newfstat(unsigned int fd, struct stat32 *statbuf) +{ + struct file * f; + int err = -EBADF; + + f = fget(fd); + if (f) { + struct dentry * dentry = f->f_dentry; + + err = do_revalidate(dentry); + if (!err) + err = cp_new_stat32(dentry->d_inode, statbuf); + fput(f); + } + return err; +} + +struct linux32_dirent { + u32 d_ino; + __kernel_off_t32 d_off; + u16 d_reclen; + char d_name[1]; +}; + +struct old_linux32_dirent { + u32 d_ino; + u32 d_offset; + u16 d_namlen; + char d_name[1]; +}; + +struct getdents32_callback { + struct linux32_dirent * current_dir; + struct linux32_dirent * previous; + int count; + int error; +}; + +struct readdir32_callback { + struct old_linux32_dirent * dirent; + int count; +}; + +#define ROUND_UP(x,a) ((__typeof__(x))(((unsigned long)(x) + ((a) - 1)) & ~((a) - 1))) +#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de))) +static int +filldir32 (void *__buf, const char *name, int namlen, loff_t offset, ino_t ino, + unsigned int d_type) +{ + struct linux32_dirent * dirent; + struct getdents32_callback * buf = (struct getdents32_callback *) __buf; + int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1, 4); + + buf->error = -EINVAL; /* only used if we fail.. */ + if (reclen > buf->count) + return -EINVAL; + dirent = buf->previous; + if (dirent) + put_user(offset, &dirent->d_off); + dirent = buf->current_dir; + buf->previous = dirent; + put_user(ino, &dirent->d_ino); + put_user(reclen, &dirent->d_reclen); + copy_to_user(dirent->d_name, name, namlen); + put_user(0, dirent->d_name + namlen); + ((char *) dirent) += reclen; + buf->current_dir = dirent; + buf->count -= reclen; + return 0; +} + +asmlinkage long +sys32_getdents (unsigned int fd, void * dirent, unsigned int count) +{ + struct file * file; + struct linux32_dirent * lastdirent; + struct getdents32_callback buf; + int error; + + error = -EBADF; + file = fget(fd); + if (!file) + goto out; + + buf.current_dir = (struct linux32_dirent *) dirent; + buf.previous = NULL; + buf.count = count; + buf.error = 0; + + error = vfs_readdir(file, filldir32, &buf); + if (error < 0) + goto out_putf; + error = buf.error; + lastdirent = buf.previous; + if (lastdirent) { + put_user(file->f_pos, &lastdirent->d_off); + error = count - buf.count; + } + +out_putf: + fput(file); +out: + return error; +} + +static int +fillonedir32 (void * __buf, const char * name, int namlen, loff_t offset, ino_t ino, + unsigned int d_type) +{ + struct readdir32_callback * buf = (struct readdir32_callback *) __buf; + struct old_linux32_dirent * dirent; + + if (buf->count) + return -EINVAL; + buf->count++; + dirent = buf->dirent; + put_user(ino, &dirent->d_ino); + put_user(offset, &dirent->d_offset); + put_user(namlen, &dirent->d_namlen); + copy_to_user(dirent->d_name, name, namlen); + put_user(0, dirent->d_name + namlen); + return 0; +} + +asmlinkage long +sys32_readdir (unsigned int fd, void * dirent, unsigned int count) +{ + int error; + struct file * file; + struct readdir32_callback buf; + + error = -EBADF; + file = fget(fd); + if (!file) + goto out; + + buf.count = 0; + buf.dirent = dirent; + + error = vfs_readdir(file, fillonedir32, &buf); + if (error >= 0) + error = buf.count; + fput(file); +out: + return error; +} + +struct rlimit32 { + __u32 rlim_cur; + __u32 rlim_max; +}; + +#define RLIM32_INFINITY 0xffffffff + +asmlinkage long sys32_getrlimit(unsigned int resource, struct rlimit32 *rlim) +{ + struct rlimit32 rlim32; + struct rlimit *rlimip; + + if (resource >= RLIM_NLIMITS) + return -EINVAL; + rlimip = current->rlim + resource; + if (rlimip->rlim_cur >= RLIM32_INFINITY) { + rlim32.rlim_cur = RLIM32_INFINITY; + } else { + rlim32.rlim_cur = rlimip->rlim_cur; + } + if (rlimip->rlim_max >= RLIM32_INFINITY) { + rlim32.rlim_max = RLIM32_INFINITY; + } else { + rlim32.rlim_max = rlimip->rlim_max; + } + return copy_to_user(rlim, &rlim32, sizeof (struct rlimit32)); +} + +asmlinkage long sys32_setrlimit(unsigned int resource, struct rlimit32 *rlim) +{ + struct rlimit32 rlim32; + struct rlimit new_rlim, *old_rlim; + + if (resource >= RLIM_NLIMITS) + return -EINVAL; + if (copy_from_user(&rlim32, rlim, sizeof(rlim))) + return -EFAULT; + if (rlim32.rlim_cur == RLIM32_INFINITY) { + new_rlim.rlim_cur = RLIM_INFINITY; + } else { + new_rlim.rlim_cur = rlim32.rlim_cur; + } + if (rlim32.rlim_max == RLIM32_INFINITY) { + new_rlim.rlim_max = RLIM_INFINITY; + } else { + new_rlim.rlim_max = rlim32.rlim_max; + } + + old_rlim = current->rlim + resource; + if (((new_rlim.rlim_cur > old_rlim->rlim_max) || + (new_rlim.rlim_max > old_rlim->rlim_max)) && + !capable(CAP_SYS_RESOURCE)) + return -EPERM; + if (resource == RLIMIT_NOFILE) { + if (new_rlim.rlim_cur > NR_OPEN || new_rlim.rlim_max > NR_OPEN) + return -EPERM; + } + if (resource == RLIMIT_STACK) { + if (new_rlim.rlim_max > 1024 * 1024 * 1024) { + new_rlim.rlim_max = 1024 * 1024 * 1024; + } + new_rlim.rlim_max = PAGE_ALIGN(new_rlim.rlim_max); + } + + *old_rlim = new_rlim; + return 0; +} + +static int copy_mount_stuff_to_kernel(const void *user, unsigned long *kernel) +{ + int i; + unsigned long page; + struct vm_area_struct *vma; + + *kernel = 0; + if(!user) + return 0; + vma = find_vma(current->mm, (unsigned long)user); + if(!vma || (unsigned long)user < vma->vm_start) + return -EFAULT; + if(!(vma->vm_flags & VM_READ)) + return -EFAULT; + i = vma->vm_end - (unsigned long) user; + if(PAGE_SIZE <= (unsigned long) i) + i = PAGE_SIZE - 1; + if(!(page = __get_free_page(GFP_KERNEL))) + return -ENOMEM; + if(copy_from_user((void *) page, user, i)) { + free_page(page); + return -EFAULT; + } + *kernel = page; + return 0; +} + +#define SMBFS_NAME "smbfs" +#define NCPFS_NAME "ncpfs" + +asmlinkage int sys32_mount(char *dev_name, char *dir_name, char *type, unsigned long new_flags, u32 data) +{ + 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; + + err = copy_mount_stuff_to_kernel((const void *)type, &type_page); + if (err) + goto out; + + if (!type_page) { + err = -EINVAL; + goto out; + } + + is_smb = !strcmp((char *)type_page, SMBFS_NAME); + is_ncp = !strcmp((char *)type_page, NCPFS_NAME); + + err = copy_mount_stuff_to_kernel((const void *)(unsigned long)data, &data_page); + 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) { + lock_kernel(); + err = do_mount((char*)dev_page, (char*)dir_page, + (char*)type_page, new_flags, (char*)data_page); + unlock_kernel(); + } else { + if (is_ncp) + panic("NCP mounts not yet supported 32/64 parisc"); + /* do_ncp_super_data_conv((void *)data_page); */ + else { + panic("SMB mounts not yet supported 32/64 parisc"); + /* do_smb_super_data_conv((void *)data_page); */ + } + + lock_kernel(); + err = do_mount((char*)dev_page, (char*)dir_page, + (char*)type_page, new_flags, (char*)data_page); + unlock_kernel(); + } + free_page(dir_page); + +dev_out: + free_page(dev_page); + +data_out: + free_page(data_page); + +type_out: + free_page(type_page); + +out: + return err; +} + + +#ifdef CONFIG_MODULES + +struct module_info32 { + u32 addr; + u32 size; + u32 flags; + s32 usecount; +}; + +/* Query various bits about modules. */ + +static inline long +get_mod_name(const char *user_name, char **buf) +{ + unsigned long page; + long retval; + + if ((unsigned long)user_name >= TASK_SIZE + && !segment_eq(get_fs (), KERNEL_DS)) + return -EFAULT; + + page = __get_free_page(GFP_KERNEL); + if (!page) + return -ENOMEM; + + retval = strncpy_from_user((char *)page, user_name, PAGE_SIZE); + if (retval > 0) { + if (retval < PAGE_SIZE) { + *buf = (char *)page; + return retval; + } + retval = -ENAMETOOLONG; + } else if (!retval) + retval = -EINVAL; + + free_page(page); + return retval; +} + +static inline void +put_mod_name(char *buf) +{ + free_page((unsigned long)buf); +} + +static __inline__ struct module *find_module(const char *name) +{ + struct module *mod; + + for (mod = module_list; mod ; mod = mod->next) { + if (mod->flags & MOD_DELETED) + continue; + if (!strcmp(mod->name, name)) + break; + } + + return mod; +} + +static int +qm_modules(char *buf, size_t bufsize, __kernel_size_t32 *ret) +{ + struct module *mod; + size_t nmod, space, len; + + nmod = space = 0; + + for (mod = module_list; mod->next != NULL; mod = mod->next, ++nmod) { + len = strlen(mod->name)+1; + if (len > bufsize) + goto calc_space_needed; + if (copy_to_user(buf, mod->name, len)) + return -EFAULT; + buf += len; + bufsize -= len; + space += len; + } + + if (put_user(nmod, ret)) + return -EFAULT; + else + return 0; + +calc_space_needed: + space += len; + while ((mod = mod->next)->next != NULL) + space += strlen(mod->name)+1; + + if (put_user(space, ret)) + return -EFAULT; + else + return -ENOSPC; +} + +static int +qm_deps(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret) +{ + size_t i, space, len; + + if (mod->next == NULL) + return -EINVAL; + if (!MOD_CAN_QUERY(mod)) + return put_user(0, ret); + + space = 0; + for (i = 0; i < mod->ndeps; ++i) { + const char *dep_name = mod->deps[i].dep->name; + + len = strlen(dep_name)+1; + if (len > bufsize) + goto calc_space_needed; + if (copy_to_user(buf, dep_name, len)) + return -EFAULT; + buf += len; + bufsize -= len; + space += len; + } + + return put_user(i, ret); + +calc_space_needed: + space += len; + while (++i < mod->ndeps) + space += strlen(mod->deps[i].dep->name)+1; + + if (put_user(space, ret)) + return -EFAULT; + else + return -ENOSPC; +} + +static int +qm_refs(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret) +{ + size_t nrefs, space, len; + struct module_ref *ref; + + if (mod->next == NULL) + return -EINVAL; + if (!MOD_CAN_QUERY(mod)) + if (put_user(0, ret)) + return -EFAULT; + else + return 0; + + space = 0; + for (nrefs = 0, ref = mod->refs; ref ; ++nrefs, ref = ref->next_ref) { + const char *ref_name = ref->ref->name; + + len = strlen(ref_name)+1; + if (len > bufsize) + goto calc_space_needed; + if (copy_to_user(buf, ref_name, len)) + return -EFAULT; + buf += len; + bufsize -= len; + space += len; + } + + if (put_user(nrefs, ret)) + return -EFAULT; + else + return 0; + +calc_space_needed: + space += len; + while ((ref = ref->next_ref) != NULL) + space += strlen(ref->ref->name)+1; + + if (put_user(space, ret)) + return -EFAULT; + else + return -ENOSPC; +} + +static inline int +qm_symbols(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret) +{ + size_t i, space, len; + struct module_symbol *s; + char *strings; + unsigned *vals; + + if (!MOD_CAN_QUERY(mod)) + if (put_user(0, ret)) + return -EFAULT; + else + return 0; + + space = mod->nsyms * 2*sizeof(u32); + + i = len = 0; + s = mod->syms; + + if (space > bufsize) + goto calc_space_needed; + + if (!access_ok(VERIFY_WRITE, buf, space)) + return -EFAULT; + + bufsize -= space; + vals = (unsigned *)buf; + strings = buf+space; + + for (; i < mod->nsyms ; ++i, ++s, vals += 2) { + len = strlen(s->name)+1; + if (len > bufsize) + goto calc_space_needed; + + if (copy_to_user(strings, s->name, len) + || __put_user(s->value, vals+0) + || __put_user(space, vals+1)) + return -EFAULT; + + strings += len; + bufsize -= len; + space += len; + } + + if (put_user(i, ret)) + return -EFAULT; + else + return 0; + +calc_space_needed: + for (; i < mod->nsyms; ++i, ++s) + space += strlen(s->name)+1; + + if (put_user(space, ret)) + return -EFAULT; + else + return -ENOSPC; +} + +static inline int +qm_info(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret) +{ + int error = 0; + + if (mod->next == NULL) + return -EINVAL; + + if (sizeof(struct module_info32) <= bufsize) { + struct module_info32 info; + info.addr = (unsigned long)mod; + info.size = mod->size; + info.flags = mod->flags; + info.usecount = + ((mod_member_present(mod, can_unload) + && mod->can_unload) + ? -1 : atomic_read(&mod->uc.usecount)); + + if (copy_to_user(buf, &info, sizeof(struct module_info32))) + return -EFAULT; + } else + error = -ENOSPC; + + if (put_user(sizeof(struct module_info32), ret)) + return -EFAULT; + + return error; +} + +asmlinkage int sys32_query_module(char *name_user, int which, char *buf, __kernel_size_t32 bufsize, __kernel_size_t32 *ret) +{ + struct module *mod; + int err; + + lock_kernel(); + if (name_user == 0) { + /* This finds "kernel_module" which is not exported. */ + for(mod = module_list; mod->next != NULL; mod = mod->next) + ; + } else { + long namelen; + char *name; + + if ((namelen = get_mod_name(name_user, &name)) < 0) { + err = namelen; + goto out; + } + err = -ENOENT; + if (namelen == 0) { + /* This finds "kernel_module" which is not exported. */ + for(mod = module_list; mod->next != NULL; mod = mod->next) + ; + } else if ((mod = find_module(name)) == NULL) { + put_mod_name(name); + goto out; + } + put_mod_name(name); + } + + switch (which) + { + case 0: + err = 0; + break; + case QM_MODULES: + err = qm_modules(buf, bufsize, ret); + break; + case QM_DEPS: + err = qm_deps(mod, buf, bufsize, ret); + break; + case QM_REFS: + err = qm_refs(mod, buf, bufsize, ret); + break; + case QM_SYMBOLS: + err = qm_symbols(mod, buf, bufsize, ret); + break; + case QM_INFO: + err = qm_info(mod, buf, bufsize, ret); + break; + default: + err = -EINVAL; + break; + } +out: + unlock_kernel(); + return err; +} + +struct kernel_sym32 { + u32 value; + char name[60]; +}; + +extern asmlinkage int sys_get_kernel_syms(struct kernel_sym *table); + +asmlinkage int sys32_get_kernel_syms(struct kernel_sym32 *table) +{ + int len, i; + struct kernel_sym *tbl; + mm_segment_t old_fs; + + len = sys_get_kernel_syms(NULL); + if (!table) return len; + tbl = kmalloc (len * sizeof (struct kernel_sym), GFP_KERNEL); + if (!tbl) return -ENOMEM; + old_fs = get_fs(); + set_fs (KERNEL_DS); + sys_get_kernel_syms(tbl); + set_fs (old_fs); + for (i = 0; i < len; i++, table++) { + if (put_user (tbl[i].value, &table->value) || + copy_to_user (table->name, tbl[i].name, 60)) + break; + } + kfree (tbl); + return i; +} + +#else /* CONFIG_MODULES */ + +asmlinkage int +sys32_query_module(const char *name_user, int which, char *buf, size_t bufsize, + size_t *ret) +{ + /* Let the program know about the new interface. Not that + it'll do them much good. */ + if (which == 0) + return 0; + + return -ENOSYS; +} + +asmlinkage int +sys32_get_kernel_syms(struct kernel_sym *table) +{ + return -ENOSYS; +} + +#endif /* CONFIG_MODULES */ + +/* readv/writev stolen from mips64 */ +struct iovec32 { unsigned int iov_base; int iov_len; }; + +typedef ssize_t (*IO_fn_t)(struct file *, char *, size_t, loff_t *); + +static long +do_readv_writev32(int type, struct file *file, const struct iovec32 *vector, + u32 count) +{ + unsigned long tot_len; + struct iovec iovstack[UIO_FASTIOV]; + struct iovec *iov=iovstack, *ivp; + struct inode *inode; + long retval, i; + IO_fn_t fn; + + /* First get the "struct iovec" from user memory and + * verify all the pointers + */ + if (!count) + return 0; + if(verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count)) + return -EFAULT; + if (count > UIO_MAXIOV) + return -EINVAL; + if (count > UIO_FASTIOV) { + iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL); + if (!iov) + return -ENOMEM; + } + + tot_len = 0; + i = count; + ivp = iov; + while (i > 0) { + u32 len; + u32 buf; + + __get_user(len, &vector->iov_len); + __get_user(buf, &vector->iov_base); + tot_len += len; + ivp->iov_base = (void *)A(buf); + ivp->iov_len = (__kernel_size_t) len; + vector++; + ivp++; + i--; + } + + inode = file->f_dentry->d_inode; + /* VERIFY_WRITE actually means a read, as we write to user space */ + retval = locks_verify_area((type == VERIFY_WRITE + ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE), + inode, file, file->f_pos, tot_len); + if (retval) { + if (iov != iovstack) + kfree(iov); + return retval; + } + + /* Then do the actual IO. Note that sockets need to be handled + * specially as they have atomicity guarantees and can handle + * iovec's natively + */ + if (inode->i_sock) { + int err; + err = sock_readv_writev(type, inode, file, iov, count, tot_len); + if (iov != iovstack) + kfree(iov); + return err; + } + + if (!file->f_op) { + if (iov != iovstack) + kfree(iov); + return -EINVAL; + } + /* VERIFY_WRITE actually means a read, as we write to user space */ + fn = file->f_op->read; + if (type == VERIFY_READ) + fn = (IO_fn_t) file->f_op->write; + ivp = iov; + while (count > 0) { + void * base; + int len, nr; + + base = ivp->iov_base; + len = ivp->iov_len; + ivp++; + count--; + nr = fn(file, base, len, &file->f_pos); + if (nr < 0) { + if (retval) + break; + retval = nr; + break; + } + retval += nr; + if (nr != len) + break; + } + if (iov != iovstack) + kfree(iov); + + return retval; +} + +asmlinkage long +sys32_readv(int fd, struct iovec32 *vector, u32 count) +{ + struct file *file; + ssize_t ret; + + ret = -EBADF; + file = fget(fd); + if (!file) + goto bad_file; + if (file->f_op && (file->f_mode & FMODE_READ) && + (file->f_op->readv || file->f_op->read)) + ret = do_readv_writev32(VERIFY_WRITE, file, vector, count); + + fput(file); + +bad_file: + return ret; +} + +asmlinkage long +sys32_writev(int fd, struct iovec32 *vector, u32 count) +{ + struct file *file; + ssize_t ret; + + ret = -EBADF; + file = fget(fd); + if(!file) + goto bad_file; + if (file->f_op && (file->f_mode & FMODE_WRITE) && + (file->f_op->writev || file->f_op->write)) + ret = do_readv_writev32(VERIFY_READ, file, vector, count); + fput(file); + +bad_file: + return ret; +} + +/********** Borrowed from sparc64 -- hardly reviewed, not tested *****/ +#include +/* XXX This really belongs in some header file... -DaveM */ +#define MAX_SOCK_ADDR 128 /* 108 for Unix domain - + 16 for IP, 16 for IPX, + 24 for IPv6, + about 80 for AX.25 */ + +extern struct socket *sockfd_lookup(int fd, int *err); + +/* XXX This as well... */ +extern __inline__ void sockfd_put(struct socket *sock) +{ + fput(sock->file); +} + +struct msghdr32 { + u32 msg_name; + int msg_namelen; + u32 msg_iov; + __kernel_size_t32 msg_iovlen; + u32 msg_control; + __kernel_size_t32 msg_controllen; + unsigned msg_flags; +}; + +struct cmsghdr32 { + __kernel_size_t32 cmsg_len; + int cmsg_level; + int cmsg_type; +}; + +/* Bleech... */ +#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen)) +#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen)) + +#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) ) + +#define CMSG32_DATA(cmsg) ((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32)))) +#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len)) +#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len)) + +#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \ + (struct cmsghdr32 *)(ctl) : \ + (struct cmsghdr32 *)NULL) +#define CMSG32_FIRSTHDR(msg) __CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen) + +__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size, + struct cmsghdr32 *__cmsg, int __cmsg_len) +{ + struct cmsghdr32 * __ptr; + + __ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) + + CMSG32_ALIGN(__cmsg_len)); + if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size) + return NULL; + + return __ptr; +} + +__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg, + struct cmsghdr32 *__cmsg, + int __cmsg_len) +{ + return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen, + __cmsg, __cmsg_len); +} + +static inline int iov_from_user32_to_kern(struct iovec *kiov, + struct iovec32 *uiov32, + int niov) +{ + int tot_len = 0; + + while(niov > 0) { + u32 len, buf; + + if(get_user(len, &uiov32->iov_len) || + get_user(buf, &uiov32->iov_base)) { + tot_len = -EFAULT; + break; + } + tot_len += len; + kiov->iov_base = (void *)A(buf); + kiov->iov_len = (__kernel_size_t) len; + uiov32++; + kiov++; + niov--; + } + return tot_len; +} + +static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg, + struct msghdr32 *umsg) +{ + u32 tmp1, tmp2, tmp3; + int err; + + err = get_user(tmp1, &umsg->msg_name); + err |= __get_user(tmp2, &umsg->msg_iov); + err |= __get_user(tmp3, &umsg->msg_control); + if (err) + return -EFAULT; + + kmsg->msg_name = (void *)A(tmp1); + kmsg->msg_iov = (struct iovec *)A(tmp2); + kmsg->msg_control = (void *)A(tmp3); + + err = get_user(kmsg->msg_namelen, &umsg->msg_namelen); + err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen); + err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen); + err |= get_user(kmsg->msg_flags, &umsg->msg_flags); + + return err; +} + +/* I've named the args so it is easy to tell whose space the pointers are in. */ +static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov, + char *kern_address, int mode) +{ + int tot_len; + + if(kern_msg->msg_namelen) { + if(mode==VERIFY_READ) { + int err = move_addr_to_kernel(kern_msg->msg_name, + kern_msg->msg_namelen, + kern_address); + if(err < 0) + return err; + } + kern_msg->msg_name = kern_address; + } else + kern_msg->msg_name = NULL; + + if(kern_msg->msg_iovlen > UIO_FASTIOV) { + kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec), + GFP_KERNEL); + if(!kern_iov) + return -ENOMEM; + } + + tot_len = iov_from_user32_to_kern(kern_iov, + (struct iovec32 *)kern_msg->msg_iov, + kern_msg->msg_iovlen); + if(tot_len >= 0) + kern_msg->msg_iov = kern_iov; + else if(kern_msg->msg_iovlen > UIO_FASTIOV) + kfree(kern_iov); + + return tot_len; +} + +/* There is a lot of hair here because the alignment rules (and + * thus placement) of cmsg headers and length are different for + * 32-bit apps. -DaveM + */ +static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg, + unsigned char *stackbuf, int stackbuf_size) +{ + struct cmsghdr32 *ucmsg; + struct cmsghdr *kcmsg, *kcmsg_base; + __kernel_size_t32 ucmlen; + __kernel_size_t kcmlen, tmp; + + kcmlen = 0; + kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf; + ucmsg = CMSG32_FIRSTHDR(kmsg); + while(ucmsg != NULL) { + if(get_user(ucmlen, &ucmsg->cmsg_len)) + return -EFAULT; + + /* Catch bogons. */ + if(CMSG32_ALIGN(ucmlen) < + CMSG32_ALIGN(sizeof(struct cmsghdr32))) + return -EINVAL; + if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control) + + ucmlen) > kmsg->msg_controllen) + return -EINVAL; + + tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + + CMSG_ALIGN(sizeof(struct cmsghdr))); + kcmlen += tmp; + ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); + } + if(kcmlen == 0) + return -EINVAL; + + /* The kcmlen holds the 64-bit version of the control length. + * It may not be modified as we do not stick it into the kmsg + * until we have successfully copied over all of the data + * from the user. + */ + if(kcmlen > stackbuf_size) + kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL); + if(kcmsg == NULL) + return -ENOBUFS; + + /* Now copy them over neatly. */ + memset(kcmsg, 0, kcmlen); + ucmsg = CMSG32_FIRSTHDR(kmsg); + while(ucmsg != NULL) { + __get_user(ucmlen, &ucmsg->cmsg_len); + tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + + CMSG_ALIGN(sizeof(struct cmsghdr))); + kcmsg->cmsg_len = tmp; + __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level); + __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type); + + /* Copy over the data. */ + if(copy_from_user(CMSG_DATA(kcmsg), + CMSG32_DATA(ucmsg), + (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))))) + goto out_free_efault; + + /* Advance. */ + kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp)); + ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); + } + + /* Ok, looks like we made it. Hook it up and return success. */ + kmsg->msg_control = kcmsg_base; + kmsg->msg_controllen = kcmlen; + return 0; + +out_free_efault: + if(kcmsg_base != (struct cmsghdr *)stackbuf) + kfree(kcmsg_base); + return -EFAULT; +} + +static void put_cmsg32(struct msghdr *kmsg, int level, int type, + int len, void *data) +{ + struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; + struct cmsghdr32 cmhdr; + int cmlen = CMSG32_LEN(len); + + if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) { + kmsg->msg_flags |= MSG_CTRUNC; + return; + } + + if(kmsg->msg_controllen < cmlen) { + kmsg->msg_flags |= MSG_CTRUNC; + cmlen = kmsg->msg_controllen; + } + cmhdr.cmsg_level = level; + cmhdr.cmsg_type = type; + cmhdr.cmsg_len = cmlen; + + if(copy_to_user(cm, &cmhdr, sizeof cmhdr)) + return; + if(copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32))) + return; + cmlen = CMSG32_SPACE(len); + kmsg->msg_control += cmlen; + kmsg->msg_controllen -= cmlen; +} + +static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm) +{ + struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; + int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int); + int fdnum = scm->fp->count; + struct file **fp = scm->fp->fp; + int *cmfptr; + int err = 0, i; + + if (fdnum < fdmax) + fdmax = fdnum; + + for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) { + int new_fd; + err = get_unused_fd(); + if (err < 0) + break; + new_fd = err; + err = put_user(new_fd, cmfptr); + if (err) { + put_unused_fd(new_fd); + break; + } + /* Bump the usage count and install the file. */ + get_file(fp[i]); + fd_install(new_fd, fp[i]); + } + + if (i > 0) { + int cmlen = CMSG32_LEN(i * sizeof(int)); + if (!err) + err = put_user(SOL_SOCKET, &cm->cmsg_level); + if (!err) + err = put_user(SCM_RIGHTS, &cm->cmsg_type); + if (!err) + err = put_user(cmlen, &cm->cmsg_len); + if (!err) { + cmlen = CMSG32_SPACE(i * sizeof(int)); + kmsg->msg_control += cmlen; + kmsg->msg_controllen -= cmlen; + } + } + if (i < fdnum) + kmsg->msg_flags |= MSG_CTRUNC; + + /* + * All of the files that fit in the message have had their + * usage counts incremented, so we just free the list. + */ + __scm_destroy(scm); +} + +/* In these cases we (currently) can just copy to data over verbatim + * because all CMSGs created by the kernel have well defined types which + * have the same layout in both the 32-bit and 64-bit API. One must add + * some special cased conversions here if we start sending control messages + * with incompatible types. + * + * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after + * we do our work. The remaining cases are: + * + * SOL_IP IP_PKTINFO struct in_pktinfo 32-bit clean + * IP_TTL int 32-bit clean + * IP_TOS __u8 32-bit clean + * IP_RECVOPTS variable length 32-bit clean + * IP_RETOPTS variable length 32-bit clean + * (these last two are clean because the types are defined + * by the IPv4 protocol) + * IP_RECVERR struct sock_extended_err + + * struct sockaddr_in 32-bit clean + * SOL_IPV6 IPV6_RECVERR struct sock_extended_err + + * struct sockaddr_in6 32-bit clean + * IPV6_PKTINFO struct in6_pktinfo 32-bit clean + * IPV6_HOPLIMIT int 32-bit clean + * IPV6_FLOWINFO u32 32-bit clean + * IPV6_HOPOPTS ipv6 hop exthdr 32-bit clean + * IPV6_DSTOPTS ipv6 dst exthdr(s) 32-bit clean + * IPV6_RTHDR ipv6 routing exthdr 32-bit clean + * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean + */ +static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr) +{ + unsigned char *workbuf, *wp; + unsigned long bufsz, space_avail; + struct cmsghdr *ucmsg; + + bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr; + space_avail = kmsg->msg_controllen + bufsz; + wp = workbuf = kmalloc(bufsz, GFP_KERNEL); + if(workbuf == NULL) + goto fail; + + /* To make this more sane we assume the kernel sends back properly + * formatted control messages. Because of how the kernel will truncate + * the cmsg_len for MSG_TRUNC cases, we need not check that case either. + */ + ucmsg = (struct cmsghdr *) orig_cmsg_uptr; + while(((unsigned long)ucmsg) <= + (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) { + struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp; + int clen64, clen32; + + /* UCMSG is the 64-bit format CMSG entry in user-space. + * KCMSG32 is within the kernel space temporary buffer + * we use to convert into a 32-bit style CMSG. + */ + __get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len); + __get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level); + __get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type); + + clen64 = kcmsg32->cmsg_len; + copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg), + clen64 - CMSG_ALIGN(sizeof(*ucmsg))); + clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) + + CMSG32_ALIGN(sizeof(struct cmsghdr32))); + kcmsg32->cmsg_len = clen32; + + ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64)); + wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32)); + } + + /* Copy back fixed up data, and adjust pointers. */ + bufsz = (wp - workbuf); + copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz); + + kmsg->msg_control = (struct cmsghdr *) + (((char *)orig_cmsg_uptr) + bufsz); + kmsg->msg_controllen = space_avail - bufsz; + + kfree(workbuf); + return; + +fail: + /* If we leave the 64-bit format CMSG chunks in there, + * the application could get confused and crash. So to + * ensure greater recovery, we report no CMSGs. + */ + kmsg->msg_controllen += bufsz; + kmsg->msg_control = (void *) orig_cmsg_uptr; +} + +asmlinkage int sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags) +{ + struct socket *sock; + char address[MAX_SOCK_ADDR]; + struct iovec iov[UIO_FASTIOV]; + unsigned char ctl[sizeof(struct cmsghdr) + 20]; + unsigned char *ctl_buf = ctl; + struct msghdr kern_msg; + int err, total_len; + + if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) + return -EFAULT; + if(kern_msg.msg_iovlen > UIO_MAXIOV) + return -EINVAL; + err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ); + if (err < 0) + goto out; + total_len = err; + + if(kern_msg.msg_controllen) { + err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl)); + if(err) + goto out_freeiov; + ctl_buf = kern_msg.msg_control; + } + kern_msg.msg_flags = user_flags; + + sock = sockfd_lookup(fd, &err); + if (sock != NULL) { + if (sock->file->f_flags & O_NONBLOCK) + kern_msg.msg_flags |= MSG_DONTWAIT; + err = sock_sendmsg(sock, &kern_msg, total_len); + sockfd_put(sock); + } + + /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */ + if(ctl_buf != ctl) + kfree(ctl_buf); +out_freeiov: + if(kern_msg.msg_iov != iov) + kfree(kern_msg.msg_iov); +out: + return err; +} + +asmlinkage int sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags) +{ + struct iovec iovstack[UIO_FASTIOV]; + struct msghdr kern_msg; + char addr[MAX_SOCK_ADDR]; + struct socket *sock; + struct iovec *iov = iovstack; + struct sockaddr *uaddr; + int *uaddr_len; + unsigned long cmsg_ptr; + int err, total_len, len = 0; + + if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) + return -EFAULT; + if(kern_msg.msg_iovlen > UIO_MAXIOV) + return -EINVAL; + + uaddr = kern_msg.msg_name; + uaddr_len = &user_msg->msg_namelen; + err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE); + if (err < 0) + goto out; + total_len = err; + + cmsg_ptr = (unsigned long) kern_msg.msg_control; + kern_msg.msg_flags = 0; + + sock = sockfd_lookup(fd, &err); + if (sock != NULL) { + struct scm_cookie scm; + + if (sock->file->f_flags & O_NONBLOCK) + user_flags |= MSG_DONTWAIT; + memset(&scm, 0, sizeof(scm)); + err = sock->ops->recvmsg(sock, &kern_msg, total_len, + user_flags, &scm); + if(err >= 0) { + len = err; + if(!kern_msg.msg_control) { + if(sock->passcred || scm.fp) + kern_msg.msg_flags |= MSG_CTRUNC; + if(scm.fp) + __scm_destroy(&scm); + } else { + /* If recvmsg processing itself placed some + * control messages into user space, it's is + * using 64-bit CMSG processing, so we need + * to fix it up before we tack on more stuff. + */ + if((unsigned long) kern_msg.msg_control != cmsg_ptr) + cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr); + + /* Wheee... */ + if(sock->passcred) + put_cmsg32(&kern_msg, + SOL_SOCKET, SCM_CREDENTIALS, + sizeof(scm.creds), &scm.creds); + if(scm.fp != NULL) + scm_detach_fds32(&kern_msg, &scm); + } + } + sockfd_put(sock); + } + + if(uaddr != NULL && err >= 0) + err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len); + if(cmsg_ptr != 0 && err >= 0) { + unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control); + __kernel_size_t32 uclen = (__kernel_size_t32) (ucmsg_ptr - cmsg_ptr); + err |= __put_user(uclen, &user_msg->msg_controllen); + } + if(err >= 0) + err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags); + if(kern_msg.msg_iov != iov) + kfree(kern_msg.msg_iov); +out: + if(err < 0) + return err; + return len; +} + + +extern asmlinkage int sys_setsockopt(int fd, int level, int optname, + char *optval, int optlen); + +static int do_set_attach_filter(int fd, int level, int optname, + char *optval, int optlen) +{ + struct sock_fprog32 { + __u16 len; + __u32 filter; + } *fprog32 = (struct sock_fprog32 *)optval; + struct sock_fprog kfprog; + struct sock_filter *kfilter; + unsigned int fsize; + mm_segment_t old_fs; + __u32 uptr; + int ret; + + if (get_user(kfprog.len, &fprog32->len) || + __get_user(uptr, &fprog32->filter)) + return -EFAULT; + + kfprog.filter = (struct sock_filter *)A(uptr); + fsize = kfprog.len * sizeof(struct sock_filter); + + kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL); + if (kfilter == NULL) + return -ENOMEM; + + if (copy_from_user(kfilter, kfprog.filter, fsize)) { + kfree(kfilter); + return -EFAULT; + } + + kfprog.filter = kfilter; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_setsockopt(fd, level, optname, + (char *)&kfprog, sizeof(kfprog)); + set_fs(old_fs); + + kfree(kfilter); + + return ret; +} + +static int do_set_icmpv6_filter(int fd, int level, int optname, + char *optval, int optlen) +{ + struct icmp6_filter kfilter; + mm_segment_t old_fs; + int ret, i; + + if (copy_from_user(&kfilter, optval, sizeof(kfilter))) + return -EFAULT; + + + for (i = 0; i < 8; i += 2) { + u32 tmp = kfilter.data[i]; + + kfilter.data[i] = kfilter.data[i + 1]; + kfilter.data[i + 1] = tmp; + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_setsockopt(fd, level, optname, + (char *) &kfilter, sizeof(kfilter)); + set_fs(old_fs); + + return ret; +} + + +static int do_ipv4_set_replace(int fd, int level, int optname, + char *optval, int optlen) +#if 1 +/* Fields happen to be padded such that this works. +** Don't need to change iptables.h:struct ipt_replace +*/ +{ + struct ipt_replace *repl = (struct ipt_replace *) optval; + unsigned long ptr64; + unsigned int ptr32; + int ret; + + if (copy_from_user(&ptr32, &repl->counters, sizeof(ptr32))) + return -EFAULT; + ptr64 = (unsigned long) ptr32; + if (copy_to_user(&repl->counters, &ptr64, sizeof(ptr64))) + return -EFAULT; + + ret = sys_setsockopt(fd, level, optname, (char *) optval, optlen); + + /* Restore 32-bit ptr */ + if (copy_to_user(&repl->counters, &ptr32, sizeof(ptr32))) + return -EFAULT; + + return ret; +} +#else +/* This version tries to "do it right". ie allocate kernel buffers for +** everything and copy data in/out. Way too complicated. +** NOT TESTED for correctness! +*/ +{ + struct ipt_replace *kern_repl; + struct ipt_counters *kern_counters; + unsigned int user_counters; + mm_segment_t old_fs; + int ret = 0; + + kern_repl = (struct ipt_replace *) kmalloc(optlen+8, GFP_KERNEL); + if (!kern_repl) + return -ENOMEM; + + if (copy_from_user(kern_repl, optval, optlen)) { + ret = -EFAULT; + goto err02; + } + + /* 32-bit ptr is in the MSB's */ + user_counters = (unsigned int) (((unsigned long) kern_repl->counters) >> 32); + /* + ** We are going to set_fs() to kernel space - and thus need + ** "relocate" the counters buffer to the kernel space. + */ + kern_counters = (struct ipt_counters *) kmalloc(kern_repl->num_counters * sizeof(struct ipt_counters), GFP_KERNEL); + if (!user_counters) { + ret = -ENOMEM; + goto err02; + } + + if (copy_from_user(kern_counters, (char *) user_counters, optlen)) { + ret = -EFAULT; + goto err01; + } + + /* We can update the kernel ptr now that we have the data. */ + kern_repl->counters = kern_counters; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + + ret = sys_setsockopt(fd, level, optname, (char *) optval, optlen); + + set_fs(old_fs); + + /* Copy counters back out to user space */ + if (copy_to_user((char *) user_counters, kern_counters, + kern_repl->num_counters * sizeof(struct ipt_counters))) + { + ret = -EFAULT; + goto err01; + } + + /* restore counters so userspace can consume it */ + kern_repl->counters = NULL; + (unsigned int) kern_repl->counters = user_counters; + + /* Copy repl back out to user space */ + if (copy_to_user(optval, kern_repl, optlen)) + { + ret = -EFAULT; + } + +err01: + kfree(kern_counters); +err02: + kfree(kern_repl); + return ret; +} +#endif + + +asmlinkage int sys32_setsockopt(int fd, int level, int optname, + char *optval, int optlen) +{ + if (optname == SO_ATTACH_FILTER) + return do_set_attach_filter(fd, level, optname, optval, optlen); + + if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER) + return do_set_icmpv6_filter(fd, level, optname, optval, optlen); + + /* + ** Beware: IPT_SO_SET_REPLACE == IP6T_SO_SET_REPLACE + */ + if (level == IPPROTO_IP && optname == IPT_SO_SET_REPLACE) + return do_ipv4_set_replace(fd, level, optname, optval, optlen); + + if (level == IPPROTO_IPV6 && optname == IP6T_SO_SET_REPLACE) +#if 0 + /* FIXME: I don't (yet) use IPV6. -ggg */ + return do_ipv6_set_replace(fd, level, optname, optval, optlen); +#else + { + BUG(); + return -ENXIO; + } +#endif + + return sys_setsockopt(fd, level, optname, optval, optlen); +} + + +/*** copied from mips64 ***/ +/* + * Ooo, nasty. We need here to frob 32-bit unsigned longs to + * 64-bit unsigned longs. + */ + +static inline int +get_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset) +{ + n = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32)); + if (ufdset) { + unsigned long odd; + + if (verify_area(VERIFY_WRITE, ufdset, n*sizeof(u32))) + return -EFAULT; + + odd = n & 1UL; + n &= ~1UL; + while (n) { + unsigned long h, l; + __get_user(l, ufdset); + __get_user(h, ufdset+1); + ufdset += 2; + *fdset++ = h << 32 | l; + n -= 2; + } + if (odd) + __get_user(*fdset, ufdset); + } else { + /* Tricky, must clear full unsigned long in the + * kernel fdset at the end, this makes sure that + * actually happens. + */ + memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32)); + } + return 0; +} + +static inline void +set_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset) +{ + unsigned long odd; + n = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32)); + + if (!ufdset) + return; + + odd = n & 1UL; + n &= ~1UL; + while (n) { + unsigned long h, l; + l = *fdset++; + h = l >> 32; + __put_user(l, ufdset); + __put_user(h, ufdset+1); + ufdset += 2; + n -= 2; + } + if (odd) + __put_user(*fdset, ufdset); +} + +/*** This is a virtual copy of sys_select from fs/select.c and probably + *** should be compared to it from time to time + ***/ +static inline void *select_bits_alloc(int size) +{ + return kmalloc(6 * size, GFP_KERNEL); +} + +static inline void select_bits_free(void *bits, int size) +{ + kfree(bits); +} + +/* + * We can actually return ERESTARTSYS instead of EINTR, but I'd + * like to be certain this leads to no problems. So I return + * EINTR just for safety. + * + * Update: ERESTARTSYS breaks at least the xview clock binary, so + * I'm trying ERESTARTNOHAND which restart only when you want to. + */ +#define MAX_SELECT_SECONDS \ + ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1) +#define DIVIDE_ROUND_UP(x,y) (((x)+(y)-1)/(y)) + +asmlinkage long +sys32_select(int n, u32 *inp, u32 *outp, u32 *exp, struct timeval32 *tvp) +{ + fd_set_bits fds; + char *bits; + long timeout; + int ret, size, err; + + timeout = MAX_SCHEDULE_TIMEOUT; + if (tvp) { + struct timeval32 tv32; + time_t sec, usec; + + if ((ret = copy_from_user(&tv32, tvp, sizeof tv32))) + goto out_nofds; + + sec = tv32.tv_sec; + usec = tv32.tv_usec; + + ret = -EINVAL; + if (sec < 0 || usec < 0) + goto out_nofds; + + if ((unsigned long) sec < MAX_SELECT_SECONDS) { + timeout = DIVIDE_ROUND_UP(usec, 1000000/HZ); + timeout += sec * (unsigned long) HZ; + } + } + + ret = -EINVAL; + if (n < 0) + goto out_nofds; + + if (n > current->files->max_fdset) + n = current->files->max_fdset; + + /* + * We need 6 bitmaps (in/out/ex for both incoming and outgoing), + * since we used fdset we need to allocate memory in units of + * long-words. + */ + ret = -ENOMEM; + size = FDS_BYTES(n); + bits = select_bits_alloc(size); + if (!bits) + goto out_nofds; + fds.in = (unsigned long *) bits; + fds.out = (unsigned long *) (bits + size); + fds.ex = (unsigned long *) (bits + 2*size); + fds.res_in = (unsigned long *) (bits + 3*size); + fds.res_out = (unsigned long *) (bits + 4*size); + fds.res_ex = (unsigned long *) (bits + 5*size); + + if ((ret = get_fd_set32(n, inp, fds.in)) || + (ret = get_fd_set32(n, outp, fds.out)) || + (ret = get_fd_set32(n, exp, fds.ex))) + goto out; + zero_fd_set(n, fds.res_in); + zero_fd_set(n, fds.res_out); + zero_fd_set(n, fds.res_ex); + + ret = do_select(n, &fds, &timeout); + + if (tvp && !(current->personality & STICKY_TIMEOUTS)) { + time_t sec = 0, usec = 0; + if (timeout) { + sec = timeout / HZ; + usec = timeout % HZ; + usec *= (1000000/HZ); + } + err = put_user(sec, &tvp->tv_sec); + err |= __put_user(usec, &tvp->tv_usec); + if (err) + ret = -EFAULT; + } + + if (ret < 0) + goto out; + if (!ret) { + ret = -ERESTARTNOHAND; + if (signal_pending(current)) + goto out; + ret = 0; + } + + set_fd_set32(n, inp, fds.res_in); + set_fd_set32(n, outp, fds.res_out); + set_fd_set32(n, exp, fds.res_ex); + +out: + select_bits_free(bits, size); +out_nofds: + return ret; +} + +struct msgbuf32 { + int mtype; + char mtext[1]; +}; + +asmlinkage long sys32_msgsnd(int msqid, + struct msgbuf32 *umsgp32, + size_t msgsz, int msgflg) +{ + struct msgbuf *mb; + struct msgbuf32 mb32; + int err; + + if ((mb = kmalloc(msgsz + sizeof *mb + 4, GFP_KERNEL)) == NULL) + return -ENOMEM; + + err = get_user(mb32.mtype, &umsgp32->mtype); + mb->mtype = mb32.mtype; + err |= copy_from_user(mb->mtext, &umsgp32->mtext, msgsz); + + if (err) + err = -EFAULT; + else + KERNEL_SYSCALL(err, sys_msgsnd, msqid, mb, msgsz, msgflg); + + kfree(mb); + return err; +} + +asmlinkage long sys32_msgrcv(int msqid, + struct msgbuf32 *umsgp32, + size_t msgsz, long msgtyp, int msgflg) +{ + struct msgbuf *mb; + struct msgbuf32 mb32; + int err, len; + + if ((mb = kmalloc(msgsz + sizeof *mb + 4, GFP_KERNEL)) == NULL) + return -ENOMEM; + + KERNEL_SYSCALL(err, sys_msgrcv, msqid, mb, msgsz, msgtyp, msgflg); + + if (err >= 0) { + len = err; + mb32.mtype = mb->mtype; + err = put_user(mb32.mtype, &umsgp32->mtype); + err |= copy_to_user(&umsgp32->mtext, mb->mtext, len); + if (err) + err = -EFAULT; + else + err = len; + } + + kfree(mb); + return err; +} + +/* LFS */ + +extern asmlinkage long sys_truncate(const char *, loff_t); +extern asmlinkage long sys_ftruncate(unsigned int, loff_t); +extern asmlinkage long sys_fcntl(unsigned int, unsigned int, unsigned long); +extern asmlinkage ssize_t sys_pread(unsigned int, char *, size_t, loff_t); +extern asmlinkage ssize_t sys_pwrite(unsigned int, char *, size_t, loff_t); + +asmlinkage long sys32_truncate64(const char * path, unsigned int high, unsigned int low) +{ + return sys_truncate(path, (loff_t)high << 32 | low); +} + +asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned int high, unsigned int low) +{ + return sys_ftruncate(fd, (loff_t)high << 32 | low); +} + +asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case F_GETLK64: + cmd = F_GETLK; + break; + case F_SETLK64: + cmd = F_SETLK; + break; + case F_SETLKW64: + cmd = F_SETLKW; + break; + default: + break; + } + return sys_fcntl(fd, cmd, arg); +} + +asmlinkage int sys32_pread(int fd, void *buf, size_t count, unsigned int high, unsigned int low) +{ + return sys_pread(fd, buf, count, (loff_t)high << 32 | low); +} + +asmlinkage int sys32_pwrite(int fd, void *buf, size_t count, unsigned int high, unsigned int low) +{ + return sys_pwrite(fd, buf, count, (loff_t)high << 32 | low); +} + +/* EXPORT/UNEXPORT */ +struct nfsctl_export32 { + char ex_client[NFSCLNT_IDMAX+1]; + char ex_path[NFS_MAXPATHLEN+1]; + __kernel_dev_t ex_dev; + __kernel_ino_t32 ex_ino; + int ex_flags; + __kernel_uid_t ex_anon_uid; + __kernel_gid_t ex_anon_gid; +}; + +/* GETFH */ +struct nfsctl_fhparm32 { + struct sockaddr gf_addr; + __kernel_dev_t gf_dev; + __kernel_ino_t32 gf_ino; + int gf_version; +}; + +/* UGIDUPDATE */ +struct nfsctl_uidmap32 { + __kernel_caddr_t32 ug_ident; + __kernel_uid_t ug_uidbase; + int ug_uidlen; + __kernel_caddr_t32 ug_udimap; + __kernel_gid_t ug_gidbase; + int ug_gidlen; + __kernel_caddr_t32 ug_gdimap; +}; + +struct nfsctl_arg32 { + int ca_version; /* safeguard */ + /* wide kernel places this union on 8-byte boundary, narrow on 4 */ + union { + struct nfsctl_svc u_svc; + struct nfsctl_client u_client; + struct nfsctl_export32 u_export; + struct nfsctl_uidmap32 u_umap; + struct nfsctl_fhparm32 u_getfh; + struct nfsctl_fdparm u_getfd; + struct nfsctl_fsparm u_getfs; + } u; +}; + +asmlinkage int sys32_nfsservctl(int cmd, void *argp, void *resp) +{ + int ret, tmp; + struct nfsctl_arg32 n32; + struct nfsctl_arg n; + + ret = copy_from_user(&n, argp, sizeof n.ca_version); + if (ret != 0) + return ret; + + /* adjust argp to point at the union inside the user's n32 struct */ + tmp = (unsigned long)&n32.u - (unsigned long)&n32; + argp = (void *)((unsigned long)argp + tmp); + switch(cmd) { + case NFSCTL_SVC: + ret = copy_from_user(&n.u, argp, sizeof n.u.u_svc); + break; + + case NFSCTL_ADDCLIENT: + case NFSCTL_DELCLIENT: + ret = copy_from_user(&n.u, argp, sizeof n.u.u_client); + break; + + case NFSCTL_GETFD: + ret = copy_from_user(&n.u, argp, sizeof n.u.u_getfd); + break; + + case NFSCTL_GETFS: + ret = copy_from_user(&n.u, argp, sizeof n.u.u_getfs); + break; + + case NFSCTL_GETFH: /* nfsctl_fhparm */ + ret = copy_from_user(&n32.u, argp, sizeof n32.u.u_getfh); +#undef CP +#define CP(x) n.u.u_getfh.gf_##x = n32.u.u_getfh.gf_##x + CP(addr); + CP(dev); + CP(ino); + CP(version); + break; + + case NFSCTL_UGIDUPDATE: /* nfsctl_uidmap */ + ret = copy_from_user(&n32.u, argp, sizeof n32.u.u_umap); +#undef CP +#define CP(x) n.u.u_umap.ug_##x = n32.u.u_umap.ug_##x + n.u.u_umap.ug_ident = (char *)(u_long)n32.u.u_umap.ug_ident; + CP(uidbase); + CP(uidlen); + n.u.u_umap.ug_udimap = (__kernel_uid_t *)(u_long)n32.u.u_umap.ug_udimap; + CP(gidbase); + CP(gidlen); + n.u.u_umap.ug_gdimap = (__kernel_gid_t *)(u_long)n32.u.u_umap.ug_gdimap; + break; + + case NFSCTL_UNEXPORT: /* nfsctl_export */ + case NFSCTL_EXPORT: /* nfsctl_export */ + ret = copy_from_user(&n32.u, argp, sizeof n32.u.u_export); +#undef CP +#define CP(x) n.u.u_export.ex_##x = n32.u.u_export.ex_##x + memcpy(n.u.u_export.ex_client, n32.u.u_export.ex_client, sizeof n32.u.u_export.ex_client); + memcpy(n.u.u_export.ex_path, n32.u.u_export.ex_path, sizeof n32.u.u_export.ex_path); + CP(dev); + CP(ino); + CP(flags); + CP(anon_uid); + CP(anon_gid); + break; + + default: + BUG(); /* new cmd values to be translated... */ + ret = -EINVAL; + break; + } + + if (ret == 0) { + unsigned char rbuf[NFS_FHSIZE + sizeof (struct knfsd_fh)]; + KERNEL_SYSCALL(ret, sys_nfsservctl, cmd, &n, &rbuf); + if (cmd == NFSCTL_GETFH || cmd == NFSCTL_GETFD) { + ret = copy_to_user(resp, rbuf, NFS_FHSIZE); + } else if (cmd == NFSCTL_GETFS) { + ret = copy_to_user(resp, rbuf, sizeof (struct knfsd_fh)); + } + } + + return ret; +} + +#include + +struct dqblk32 { + __u32 dqb_bhardlimit; + __u32 dqb_bsoftlimit; + __u32 dqb_curblocks; + __u32 dqb_ihardlimit; + __u32 dqb_isoftlimit; + __u32 dqb_curinodes; + __kernel_time_t32 dqb_btime; + __kernel_time_t32 dqb_itime; +}; + + +asmlinkage int sys32_quotactl(int cmd, const char *special, int id, unsigned long addr) +{ + extern int sys_quotactl(int cmd, const char *special, int id, caddr_t addr); + int cmds = cmd >> SUBCMDSHIFT; + int err; + struct dqblk d; + char *spec; + + switch (cmds) { + case Q_GETQUOTA: + break; + case Q_SETQUOTA: + case Q_SETUSE: + case Q_SETQLIM: + if (copy_from_user (&d, (struct dqblk32 *)addr, + sizeof (struct dqblk32))) + return -EFAULT; + d.dqb_itime = ((struct dqblk32 *)&d)->dqb_itime; + d.dqb_btime = ((struct dqblk32 *)&d)->dqb_btime; + break; + default: + return sys_quotactl(cmd, special, + id, (caddr_t)addr); + } + spec = getname (special); + err = PTR_ERR(spec); + if (IS_ERR(spec)) return err; + KERNEL_SYSCALL(err, sys_quotactl, cmd, (const char *)spec, id, (caddr_t)&d); + putname (spec); + if (cmds == Q_GETQUOTA) { + __kernel_time_t b = d.dqb_btime, i = d.dqb_itime; + ((struct dqblk32 *)&d)->dqb_itime = i; + ((struct dqblk32 *)&d)->dqb_btime = b; + if (copy_to_user ((struct dqblk32 *)addr, &d, + sizeof (struct dqblk32))) + return -EFAULT; + } + return err; +} + +struct timex32 { + unsigned int modes; /* mode selector */ + int offset; /* time offset (usec) */ + int freq; /* frequency offset (scaled ppm) */ + int maxerror; /* maximum error (usec) */ + int esterror; /* estimated error (usec) */ + int status; /* clock command/status */ + int constant; /* pll time constant */ + int precision; /* clock precision (usec) (read only) */ + int tolerance; /* clock frequency tolerance (ppm) + * (read only) + */ + struct timeval32 time; /* (read only) */ + int tick; /* (modified) usecs between clock ticks */ + + int ppsfreq; /* pps frequency (scaled ppm) (ro) */ + int jitter; /* pps jitter (us) (ro) */ + int shift; /* interval duration (s) (shift) (ro) */ + int stabil; /* pps stability (scaled ppm) (ro) */ + int jitcnt; /* jitter limit exceeded (ro) */ + int calcnt; /* calibration intervals (ro) */ + int errcnt; /* calibration errors (ro) */ + int stbcnt; /* stability limit exceeded (ro) */ + + int :32; int :32; int :32; int :32; + int :32; int :32; int :32; int :32; + int :32; int :32; int :32; int :32; +}; + +asmlinkage long sys32_adjtimex(struct timex32 *txc_p32) +{ + struct timex txc; + struct timex32 t32; + int ret; + extern int do_adjtimex(struct timex *txc); + + if(copy_from_user(&t32, txc_p32, sizeof(struct timex32))) + return -EFAULT; +#undef CP +#define CP(x) txc.x = t32.x + CP(modes); CP(offset); CP(freq); CP(maxerror); CP(esterror); + CP(status); CP(constant); CP(precision); CP(tolerance); + CP(time.tv_sec); CP(time.tv_usec); CP(tick); CP(ppsfreq); CP(jitter); + CP(shift); CP(stabil); CP(jitcnt); CP(calcnt); CP(errcnt); + CP(stbcnt); + ret = do_adjtimex(&txc); +#define CP(x) t32.x = txc.x + CP(modes); CP(offset); CP(freq); CP(maxerror); CP(esterror); + CP(status); CP(constant); CP(precision); CP(tolerance); + CP(time.tv_sec); CP(time.tv_usec); CP(tick); CP(ppsfreq); CP(jitter); + CP(shift); CP(stabil); CP(jitcnt); CP(calcnt); CP(errcnt); + CP(stbcnt); + return copy_to_user(txc_p32, &t32, sizeof(struct timex32)) ? -EFAULT : ret; +} + + +struct sysinfo32 { + s32 uptime; + u32 loads[3]; + u32 totalram; + u32 freeram; + u32 sharedram; + u32 bufferram; + u32 totalswap; + u32 freeswap; + unsigned short procs; + u32 totalhigh; + u32 freehigh; + u32 mem_unit; + char _f[12]; +}; + +/* We used to call sys_sysinfo and translate the result. But sys_sysinfo + * undoes the good work done elsewhere, and rather than undoing the + * damage, I decided to just duplicate the code from sys_sysinfo here. + */ + +asmlinkage int sys32_sysinfo(struct sysinfo32 *info) +{ + struct sysinfo val; + int err; + + /* We don't need a memset here because we copy the + * struct to userspace once element at a time. + */ + + cli(); + val.uptime = jiffies / HZ; + + val.loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT); + val.loads[1] = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT); + val.loads[2] = avenrun[2] << (SI_LOAD_SHIFT - FSHIFT); + + val.procs = nr_threads-1; + sti(); + + si_meminfo(&val); + si_swapinfo(&val); + + err = put_user (val.uptime, &info->uptime); + err |= __put_user (val.loads[0], &info->loads[0]); + err |= __put_user (val.loads[1], &info->loads[1]); + err |= __put_user (val.loads[2], &info->loads[2]); + err |= __put_user (val.totalram, &info->totalram); + err |= __put_user (val.freeram, &info->freeram); + err |= __put_user (val.sharedram, &info->sharedram); + err |= __put_user (val.bufferram, &info->bufferram); + err |= __put_user (val.totalswap, &info->totalswap); + err |= __put_user (val.freeswap, &info->freeswap); + err |= __put_user (val.procs, &info->procs); + err |= __put_user (val.totalhigh, &info->totalhigh); + err |= __put_user (val.freehigh, &info->freehigh); + err |= __put_user (val.mem_unit, &info->mem_unit); + return err ? -EFAULT : 0; +} + + +/* lseek() needs a wrapper because 'offset' can be negative, but the top + * half of the argument has been zeroed by syscall.S. + */ + +extern asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin); + +asmlinkage int sys32_lseek(unsigned int fd, int offset, unsigned int origin) +{ + return sys_lseek(fd, offset, origin); +} + +asmlinkage long sys32_semctl_broken(int semid, int semnum, int cmd, union semun arg) +{ + union semun u; + + cmd &= ~IPC_64; /* should be removed together with the _broken suffix */ + + if (cmd == SETVAL) { + /* Ugh. arg is a union of int,ptr,ptr,ptr, so is 8 bytes. + * The int should be in the first 4, but our argument + * frobbing has left it in the last 4. + */ + u.val = *((int *)&arg + 1); + return sys_semctl (semid, semnum, cmd, u); + } + return sys_semctl (semid, semnum, cmd, arg); +} + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/sys_parisc.c linux.19rc3-ac4/arch/parisc/kernel/sys_parisc.c --- linux.19rc3/arch/parisc/kernel/sys_parisc.c 2002-07-29 12:50:07.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/sys_parisc.c 2002-07-29 13:58:37.000000000 +0100 @@ -1,7 +1,7 @@ /* * linux/arch/parisc/kernel/sys_parisc.c * - * this implements the missing syscalls. + * this implements syscalls which are handled per-arch. */ #include @@ -10,26 +10,15 @@ #include #include #include +#include #include -/* for some reason, "old_readdir" is the only syscall which does not begin - * with "sys_", which breaks the ENTRY_* macros in syscall.S so I "fixed" - * it here. - */ - -int sys_old_readdir(unsigned int fd, void *dirent, unsigned int count) -{ - return old_readdir(fd, dirent, count); -} - int sys_pipe(int *fildes) { int fd[2]; int error; - lock_kernel(); error = do_pipe(fd); - unlock_kernel(); if (!error) { if (copy_to_user(fildes, fd, 2*sizeof(int))) error = -EFAULT; @@ -44,40 +33,117 @@ return -ERESTARTNOHAND; } -int sys_mmap(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, unsigned long fd, - unsigned long offset) +static unsigned long get_unshared_area(unsigned long addr, unsigned long len) { - struct file * file = NULL; - int error; + struct vm_area_struct *vma; - down_write(¤t->mm->mmap_sem); - lock_kernel(); + if (!addr) + addr = TASK_UNMAPPED_BASE; + addr = PAGE_ALIGN(addr); + + for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) { + /* At this point: (!vma || addr < vma->vm_end). */ + if (TASK_SIZE - len < addr) + return -ENOMEM; + if (!vma || addr + len <= vma->vm_start) + return addr; + addr = vma->vm_end; + } +} + +#define DCACHE_ALIGN(addr) (((addr) + (SHMLBA - 1)) &~ (SHMLBA - 1)) + +static unsigned long get_shared_area(struct inode *inode, unsigned long addr, + unsigned long len, unsigned long pgoff) +{ + struct vm_area_struct *vma, *first_vma; + int offset; + + first_vma = inode->i_mapping->i_mmap_shared; + offset = (first_vma->vm_start + ((pgoff - first_vma->vm_pgoff) << PAGE_SHIFT)) & (SHMLBA - 1); + + if (!addr) + addr = TASK_UNMAPPED_BASE; + addr = DCACHE_ALIGN(addr - offset) + offset; + + for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) { + /* At this point: (!vma || addr < vma->vm_end). */ + if (TASK_SIZE - len < addr) + return -ENOMEM; + if (!vma || addr + len <= vma->vm_start) + return addr; + addr = DCACHE_ALIGN(vma->vm_end - offset) + offset; + if (addr < vma->vm_end) /* handle wraparound */ + return -ENOMEM; + } +} + +unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, + unsigned long len, unsigned long pgoff, unsigned long flags) +{ + struct inode *inode = NULL; + + if (len > TASK_SIZE) + return -ENOMEM; + + if (filp) { + inode = filp->f_dentry->d_inode; + } + + if (inode && (flags & MAP_SHARED) && (inode->i_mapping->i_mmap_shared)) { + addr = get_shared_area(inode, addr, len, pgoff); + } else { + addr = get_unshared_area(addr, len); + } + return addr; +} + +static unsigned long do_mmap2(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, unsigned long fd, + unsigned long pgoff) +{ + struct file * file = NULL; + unsigned long error = -EBADF; if (!(flags & MAP_ANONYMOUS)) { - error = -EBADF; file = fget(fd); if (!file) goto out; } + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - error = do_mmap(file, addr, len, prot, flags, offset); + + down_write(¤t->mm->mmap_sem); + error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); + up_write(¤t->mm->mmap_sem); + if (file != NULL) fput(file); out: - unlock_kernel(); - up_write(¤t->mm->mmap_sem); return error; } -int sys_ioperm(unsigned long from, unsigned long num, int on) +asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, unsigned long fd, + unsigned long pgoff) { - return -ENOSYS; + /* Make sure the shift for mmap2 is constant (12), no matter what PAGE_SIZE + we have. */ + return do_mmap2(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT - 12)); } -long sys_shmat_wrapper(int shmid, void *shmaddr, int shmflag) +asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, unsigned long fd, + unsigned long offset) +{ + if (!(offset & ~PAGE_MASK)) { + return do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); + } else { + return -EINVAL; + } +} + +long sys_shmat_wrapper(int shmid, char *shmaddr, int shmflag) { - extern int sys_shmat(int shmid, char *shmaddr, int shmflg, - unsigned long * raddr); unsigned long raddr; int r; @@ -86,3 +152,107 @@ return r; return raddr; } + + +/* + * FIXME, please remove this crap as soon as possible + * + * This is here to fix up broken glibc structures, + * which are already fixed in newer glibcs + */ +#include +#include +#include +#include "sys32.h" + +struct broken_ipc_perm +{ + key_t key; /* Key. */ + uid_t uid; /* Owner's user ID. */ + gid_t gid; /* Owner's group ID. */ + uid_t cuid; /* Creator's user ID. */ + gid_t cgid; /* Creator's group ID. */ + unsigned short int mode; /* Read/write permission. */ + unsigned short int __pad1; + unsigned short int seq; /* Sequence number. */ + unsigned short int __pad2; + unsigned long int __unused1; + unsigned long int __unused2; +}; + +struct broken_shmid64_ds { + struct broken_ipc_perm shm_perm; /* operation perms */ + size_t shm_segsz; /* size of segment (bytes) */ +#ifndef __LP64__ + unsigned int __pad1; +#endif + __kernel_time_t shm_atime; /* last attach time */ +#ifndef __LP64__ + unsigned int __pad2; +#endif + __kernel_time_t shm_dtime; /* last detach time */ +#ifndef __LP64__ + unsigned int __pad3; +#endif + __kernel_time_t shm_ctime; /* last change time */ + __kernel_pid_t shm_cpid; /* pid of creator */ + __kernel_pid_t shm_lpid; /* pid of last operator */ + unsigned int shm_nattch; /* no. of current attaches */ + unsigned int __unused1; + unsigned int __unused2; +}; + +static void convert_broken_perm (struct broken_ipc_perm *out, struct ipc64_perm *in) +{ + out->key = in->key; + out->uid = in->uid; + out->gid = in->gid; + out->cuid = in->cuid; + out->cgid = in->cgid; + out->mode = in->mode; + out->seq = in->seq; +} + +static int copyout_broken_shmid64(struct broken_shmid64_ds *buf, struct shmid64_ds *sbuf) +{ + struct broken_shmid64_ds tbuf; + + memset(&tbuf, 0, sizeof tbuf); + convert_broken_perm (&tbuf.shm_perm, &sbuf->shm_perm); + tbuf.shm_segsz = sbuf->shm_segsz; + tbuf.shm_atime = sbuf->shm_atime; + tbuf.shm_dtime = sbuf->shm_dtime; + tbuf.shm_ctime = sbuf->shm_ctime; + tbuf.shm_cpid = sbuf->shm_cpid; + tbuf.shm_lpid = sbuf->shm_lpid; + tbuf.shm_nattch = sbuf->shm_nattch; + return copy_to_user(buf, &tbuf, sizeof tbuf); +} + +int sys_msgctl_broken(int msqid, int cmd, struct msqid_ds *buf) +{ + return sys_msgctl (msqid, cmd & ~IPC_64, buf); +} + +int sys_semctl_broken(int semid, int semnum, int cmd, union semun arg) +{ + return sys_semctl (semid, semnum, cmd & ~IPC_64, arg); +} + +int sys_shmctl_broken(int shmid, int cmd, struct shmid64_ds *buf) +{ + struct shmid64_ds sbuf; + int err; + + if (cmd & IPC_64) { + cmd &= ~IPC_64; + if (cmd == IPC_STAT || cmd == SHM_STAT) { + KERNEL_SYSCALL(err, sys_shmctl, shmid, cmd, (struct shmid_ds *)&sbuf); + if (err == 0) + err = copyout_broken_shmid64((struct broken_shmid64_ds *)buf, &sbuf); + return err; + } + } + return sys_shmctl (shmid, cmd, (struct shmid_ds *)buf); +} + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/time.c linux.19rc3-ac4/arch/parisc/kernel/time.c --- linux.19rc3/arch/parisc/kernel/time.c 2002-07-29 12:50:07.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/time.c 2002-07-29 13:58:37.000000000 +0100 @@ -1,5 +1,5 @@ /* - * linux/arch/arm/kernel/time.c + * linux/arch/parisc/kernel/time.c * * Copyright (C) 1991, 1992, 1995 Linus Torvalds * Modifications for ARM (C) 1994, 1995, 1996,1997 Russell King @@ -10,6 +10,7 @@ * 1998-12-20 Updated NTP code according to technical memorandum Jan '96 * "A Kernel Model for Precision Timekeeping" by Dave Mills */ +#include #include #include #include @@ -30,69 +31,208 @@ #include +/* xtime and wall_jiffies keep wall-clock time */ +extern unsigned long wall_jiffies; extern rwlock_t xtime_lock; -static int timer_value; -static int timer_delta; -static struct pdc_tod tod_data __attribute__((aligned(8))); +static long clocktick; /* timer cycles per tick */ +static long halftick; -void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +#ifdef CONFIG_SMP +extern void smp_do_timer(struct pt_regs *regs); +#endif + +static inline void +parisc_do_profile(unsigned long pc) { - int old; - int lost = 0; - int cr16; - - old = timer_value; + extern char _stext; - cr16 = mfctl(16); - while((timer_value - cr16) < (timer_delta / 2)) { - timer_value += timer_delta; - lost++; - } + if (!prof_buffer) + return; - mtctl(timer_value ,16); + pc -= (unsigned long) &_stext; + pc >>= prof_shift; + /* + * Don't ignore out-of-bounds PC values silently, + * put them into the last histogram slot, so if + * present, they will show up as a sharp peak. + */ + if (pc > prof_len - 1) + pc = prof_len - 1; + atomic_inc((atomic_t *)&prof_buffer[pc]); +} + +void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + long now = mfctl(16); + long next_tick; + int nticks; + int cpu = smp_processor_id(); + + /* initialize next_tick to time at last clocktick */ + + next_tick = cpu_data[cpu].it_value; + + /* since time passes between the interrupt and the mfctl() + * above, it is never true that last_tick + clocktick == now. If we + * never miss a clocktick, we could set next_tick = last_tick + clocktick + * but maybe we'll miss ticks, hence the loop. + * + * Variables are *signed*. + */ + + nticks = 0; + while((next_tick - now) < halftick) { + next_tick += clocktick; + nticks++; + } + mtctl(next_tick, 16); + cpu_data[cpu].it_value = next_tick; - do_timer(regs); + while (nticks--) { +#ifdef CONFIG_SMP + smp_do_timer(regs); +#endif + if (cpu == 0) { + extern int pc_in_user_space; + write_lock(&xtime_lock); +#ifndef CONFIG_SMP + if (!user_mode(regs)) + parisc_do_profile(regs->iaoq[0]); + else + parisc_do_profile(&pc_in_user_space); +#endif + do_timer(regs); + write_unlock(&xtime_lock); + } + } - led_interrupt_func(); +#ifdef CONFIG_CHASSIS_LCD_LED + /* Only schedule the led tasklet on cpu 0, and only if it + * is enabled. + */ + if (cpu == 0 && !atomic_read(&led_tasklet.count)) + tasklet_schedule(&led_tasklet); +#endif + + /* check soft power switch status */ + if (cpu == 0 && !atomic_read(&power_tasklet.count)) + tasklet_schedule(&power_tasklet); } -void do_gettimeofday(struct timeval *tv) +/*** converted from ia64 ***/ +/* + * Return the number of micro-seconds that elapsed since the last + * update to wall time (aka xtime aka wall_jiffies). The xtime_lock + * must be at least read-locked when calling this routine. + */ +static inline unsigned long +gettimeoffset (void) { - unsigned long flags; - +#ifndef CONFIG_SMP + /* + * FIXME: This won't work on smp because jiffies are updated by cpu 0. + * Once parisc-linux learns the cr16 difference between processors, + * this could be made to work. + */ + long last_tick; + long elapsed_cycles; + + /* it_value is the intended time of the next tick */ + last_tick = cpu_data[smp_processor_id()].it_value; + + /* Subtract one tick and account for possible difference between + * when we expected the tick and when it actually arrived. + * (aka wall vs real) + */ + last_tick -= clocktick * (jiffies - wall_jiffies + 1); + elapsed_cycles = mfctl(16) - last_tick; + + /* the precision of this math could be improved */ + return elapsed_cycles / (PAGE0->mem_10msec / 10000); +#else + return 0; +#endif +} + +void +do_gettimeofday (struct timeval *tv) +{ + unsigned long flags, usec, sec; + read_lock_irqsave(&xtime_lock, flags); - tv->tv_sec = xtime.tv_sec; - tv->tv_usec = xtime.tv_usec; + { + usec = gettimeoffset(); + + sec = xtime.tv_sec; + usec += xtime.tv_usec; + } read_unlock_irqrestore(&xtime_lock, flags); + while (usec >= 1000000) { + usec -= 1000000; + ++sec; + } + + tv->tv_sec = sec; + tv->tv_usec = usec; } -void do_settimeofday(struct timeval *tv) +void +do_settimeofday (struct timeval *tv) { write_lock_irq(&xtime_lock); - xtime.tv_sec = tv->tv_sec; - xtime.tv_usec = tv->tv_usec; + { + /* + * This is revolting. We need to set "xtime" + * correctly. However, the value in this location is + * the value at the most recent update of wall time. + * Discover what correction gettimeofday would have + * done, and then undo it! + */ + tv->tv_usec -= gettimeoffset(); + tv->tv_usec -= (jiffies - wall_jiffies) * (1000000 / HZ); + + while (tv->tv_usec < 0) { + tv->tv_usec += 1000000; + tv->tv_sec--; + } + + xtime = *tv; + time_adjust = 0; /* stop active adjtime() */ + time_status |= STA_UNSYNC; + time_maxerror = NTP_PHASE_LIMIT; + time_esterror = NTP_PHASE_LIMIT; + } write_unlock_irq(&xtime_lock); } + void __init time_init(void) { - timer_delta = (100 * PAGE0->mem_10msec) / HZ; + unsigned long next_tick; + static struct pdc_tod tod_data; + + clocktick = (100 * PAGE0->mem_10msec) / HZ; + halftick = clocktick / 2; - /* make the first timer interrupt go off in one second */ - timer_value = mfctl(16) + (HZ * timer_delta); - mtctl(timer_value, 16); + /* Setup clock interrupt timing */ + next_tick = mfctl(16); + next_tick += clocktick; + cpu_data[smp_processor_id()].it_value = next_tick; + + /* kick off Itimer (CR16) */ + mtctl(next_tick, 16); if(pdc_tod_read(&tod_data) == 0) { + write_lock_irq(&xtime_lock); xtime.tv_sec = tod_data.tod_sec; xtime.tv_usec = tod_data.tod_usec; + write_unlock_irq(&xtime_lock); } else { printk(KERN_ERR "Error reading tod clock\n"); xtime.tv_sec = 0; xtime.tv_usec = 0; } - } - diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/traps.c linux.19rc3-ac4/arch/parisc/kernel/traps.c --- linux.19rc3/arch/parisc/kernel/traps.c 2002-07-29 12:50:07.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/traps.c 2002-07-29 13:58:37.000000000 +0100 @@ -23,15 +23,20 @@ #include #include #include +#include + #include #include #include #include +#include +#include #include - #include #include +#include "../math-emu/math-emu.h" /* for handle_fpe() */ + #ifdef CONFIG_KWDB #include /* for BI2_KGDB_GDB */ #include /* for __() */ @@ -40,150 +45,205 @@ #include /* for I_BRK_INST */ #endif /* CONFIG_KWDB */ +#define PRINT_USER_FAULTS /* (turn this on if you want user faults to be */ + /* dumped to the console via printk) */ -static inline void console_verbose(void) -{ - console_loglevel = 15; -} - - -void page_exception(void); - -/* - * These constants are for searching for possible module text - * segments. VMALLOC_OFFSET comes from mm/vmalloc.c; MODULE_RANGE is - * a guess of how much space is likely to be vmalloced. - */ -#define VMALLOC_OFFSET (8*1024*1024) -#define MODULE_RANGE (8*1024*1024) - -int kstack_depth_to_print = 24; - -static void printbinary(unsigned long x, int nbits) +static int printbinary(char *buf, unsigned long x, int nbits) { unsigned long mask = 1UL << (nbits - 1); while (mask != 0) { - printk(mask & x ? "1" : "0"); + *buf++ = (mask & x ? '1' : '0'); mask >>= 1; } + *buf = '\0'; + + return nbits; } -void show_regs(struct pt_regs *regs) -{ - int i; #ifdef __LP64__ -#define RFMT " %016lx" +#define RFMT "%016lx" #else -#define RFMT " %08lx" +#define RFMT "%08lx" #endif - printk("\n"); /* don't want to have that pretty register dump messed up */ - - printk(" YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI\nPSW: "); - printbinary(regs->gr[0], 32); - printk(" %s\n", print_tainted()); +void show_regs(struct pt_regs *regs) +{ + int i; + char buf[128], *p; + char *level; + unsigned long cr30; + unsigned long cr31; + + level = user_mode(regs) ? KERN_DEBUG : KERN_CRIT; + + printk("%s\n", level); /* don't want to have that pretty register dump messed up */ + + printk("%s YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI\n", level); + printbinary(buf, regs->gr[0], 32); + printk("%sPSW: %s %s\n", level, buf, print_tainted()); for (i = 0; i < 32; i += 4) { int j; - printk("r%d-%d\t", i, i + 3); + p = buf; + p += sprintf(p, "%sr%02d-%02d ", level, i, i + 3); for (j = 0; j < 4; j++) { - printk(RFMT, i + j == 0 ? 0 : regs->gr[i + j]); + p += sprintf(p, " " RFMT, (i+j) == 0 ? 0 : regs->gr[i + j]); } - printk("\n"); + printk("%s\n", buf); } for (i = 0; i < 8; i += 4) { int j; - printk("sr%d-%d\t", i, i + 4); + p = buf; + p += sprintf(p, "%ssr%d-%d ", level, i, i + 3); for (j = 0; j < 4; j++) { - printk(RFMT, regs->sr[i + j]); + p += sprintf(p, " " RFMT, regs->sr[i + j]); } - printk("\n"); + printk("%s\n", buf); } -#if REDICULOUSLY_VERBOSE - for (i = 0; i < 32; i++) { - printk("FR%2d : %016lx ", i, regs->fr[i]); - if ((i & 1) == 1) - printk("\n"); - } +#if RIDICULOUSLY_VERBOSE + for (i = 0; i < 32; i += 2) + printk("%sFR%02d : %016lx FR%2d : %016lx", level, i, + regs->fr[i], i+1, regs->fr[i+1]); #endif - printk("\nIASQ:" RFMT RFMT " IAOQ:" RFMT RFMT "\n", - regs->iasq[0], regs->iasq[1], regs->iaoq[0], regs->iaoq[1]); - printk(" IIR: %08lx ISR:" RFMT " IOR:" RFMT "\nORIG_R28:" RFMT - "\n", regs->iir, regs->isr, regs->ior, regs->orig_r28); + cr30 = mfctl(30); + cr31 = mfctl(31); + printk("%s\n", level); + printk("%sIASQ: " RFMT " " RFMT " IAOQ: " RFMT " " RFMT "\n", + level, regs->iasq[0], regs->iasq[1], regs->iaoq[0], regs->iaoq[1]); + printk("%s IIR: %08lx ISR: " RFMT " IOR: " RFMT "\n", + level, regs->iir, regs->isr, regs->ior); + printk("%s CPU: %8d CR30: " RFMT " CR31: " RFMT "\n", + level, ((struct task_struct *)cr30)->processor, cr30, cr31); + printk("%s ORIG_R28: " RFMT "\n", level, regs->orig_r28); } -void -die_if_kernel (char *str, struct pt_regs *regs, long err) + +static void dump_stack(unsigned long from, unsigned long to, int istackflag) +{ + unsigned int *fromptr; + unsigned int *toptr; + + fromptr = (unsigned int *)from; + toptr = (unsigned int *)to; + + printk("\n"); + printk(KERN_CRIT "Dumping %sStack from 0x%p to 0x%p:\n", + istackflag ? "Interrupt " : "", + fromptr, toptr); + + while (fromptr < toptr) { + printk(KERN_CRIT "%04lx %08x %08x %08x %08x %08x %08x %08x %08x\n", + ((unsigned long)fromptr) & 0xffff, + fromptr[0], fromptr[1], fromptr[2], fromptr[3], + fromptr[4], fromptr[5], fromptr[6], fromptr[7]); + fromptr += 8; + } +} + + +void show_stack(struct pt_regs *regs) { - if (user_mode(regs)) { #if 1 + /* If regs->sr[7] == 0, we are on a kernel stack */ + if (regs->sr[7] == 0) { + + unsigned long sp = regs->gr[30]; + unsigned long cr30; + unsigned long cr31; + unsigned long stack_start; + struct pt_regs *int_regs; + + cr30 = mfctl(30); + cr31 = mfctl(31); + stack_start = sp & ~(ISTACK_SIZE - 1); + if (stack_start == cr31) { + /* + * We are on the interrupt stack, get the stack + * pointer from the first pt_regs structure on + * the interrupt stack, so we can dump the task + * stack first. + */ + + int_regs = (struct pt_regs *)cr31; + sp = int_regs->gr[30]; + stack_start = sp & ~(INIT_TASK_SIZE - 1); + if (stack_start != cr30) { + printk(KERN_CRIT "WARNING! Interrupt-Stack pointer and cr30 do not correspond!\n"); + printk(KERN_CRIT "Dumping virtual address stack instead\n"); + dump_stack((unsigned long)__va(stack_start), (unsigned long)__va(sp), 0); + } else { + dump_stack(stack_start, sp, 0); + }; + + printk("\n\n" KERN_DEBUG "Registers at Interrupt:\n"); + show_regs(int_regs); + + /* Now dump the interrupt stack */ + + sp = regs->gr[30]; + stack_start = sp & ~(ISTACK_SIZE - 1); + dump_stack(stack_start,sp,1); + } + else + { + /* Stack Dump! */ + printk(KERN_CRIT "WARNING! Stack pointer and cr30 do not correspond!\n"); + printk(KERN_CRIT "Dumping virtual address stack instead\n"); + dump_stack((unsigned long)__va(stack_start), (unsigned long)__va(sp), 0); + } + } +#endif +} + + +void die_if_kernel(char *str, struct pt_regs *regs, long err) +{ + if (user_mode(regs)) { +#ifdef PRINT_USER_FAULTS if (err == 0) return; /* STFU */ /* XXX for debugging only */ - printk ("!!die_if_kernel: %s(%d): %s %ld\n", + printk(KERN_DEBUG "%s (pid %d): %s (code %ld)\n", current->comm, current->pid, str, err); show_regs(regs); #endif return; } + + /* unlock the pdc lock if necessary */ + pdc_emergency_unlock(); - printk("%s[%d]: %s %ld\n", current->comm, current->pid, str, err); - + /* maybe the kernel hasn't booted very far yet and hasn't been able + * to initialize the serial or STI console. In that case we should + * re-enable the pdc console, so that the user will be able to + * identify the problem. */ + if (!console_drivers) + pdc_console_restart(); + + printk(KERN_CRIT "%s (pid %d): %s (code %ld)\n", + current->comm, current->pid, str, err); show_regs(regs); /* Wot's wrong wif bein' racy? */ if (current->thread.flags & PARISC_KERNEL_DEATH) { - printk("die_if_kernel recursion detected.\n"); + printk(KERN_CRIT "%s() recursion detected.\n", __FUNCTION__); sti(); while (1); } + current->thread.flags |= PARISC_KERNEL_DEATH; do_exit(SIGSEGV); } -asmlinkage void cache_flush_denied(struct pt_regs * regs, long error_code) -{ -} - -asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) -{ -} - -#ifndef CONFIG_MATH_EMULATION - -asmlinkage void math_emulate(long arg) -{ -} - -#endif /* CONFIG_MATH_EMULATION */ - int syscall_ipi(int (*syscall) (struct pt_regs *), struct pt_regs *regs) { return syscall(regs); } -struct { - int retval; - - int (*func) (void *, struct pt_regs *); - void * data; -} ipi_action[NR_CPUS]; - -void ipi_interrupt(int irq, void *unused, struct pt_regs *regs) -{ - int cpu = smp_processor_id(); - - if(!ipi_action[cpu].func) - BUG(); - - ipi_action[cpu].retval = - ipi_action[cpu].func(ipi_action[cpu].data, regs); -} - /* gdb uses break 4,8 */ #define GDB_BREAK_INSN 0x10004 void handle_gdb_break(struct pt_regs *regs, int wot) @@ -204,15 +264,16 @@ struct save_state ssp; #endif /* CONFIG_KWDB */ - flush_all_caches(); switch(iir) { case 0x00: - /* show registers, halt */ - cli(); - printk("break 0,0: pid=%d command='%s'\n", +#ifdef PRINT_USER_FAULTS + printk(KERN_DEBUG "break 0,0: pid=%d command='%s'\n", current->pid, current->comm); +#endif die_if_kernel("Breakpoint", regs, 0); +#ifdef PRINT_USER_FAULTS show_regs(regs); +#endif si.si_code = TRAP_BRKPT; si.si_addr = (void *) (regs->iaoq[0] & ~3); si.si_signo = SIGTRAP; @@ -225,7 +286,6 @@ break; #ifdef CONFIG_KWDB - case KGDB_BREAK_INSN: mtctl(0, 15); pt_regs_to_ssp(regs, &ssp); @@ -243,14 +303,14 @@ regs->iaoq[0] = regs->iaoq[1]; regs->iaoq[1] += 4; break; - #endif /* CONFIG_KWDB */ default: - set_eiem(0); - printk("break %#08x: pid=%d command='%s'\n", +#ifdef PRINT_USER_FAULTS + printk(KERN_DEBUG "break %#08x: pid=%d command='%s'\n", iir, current->pid, current->comm); show_regs(regs); +#endif si.si_signo = SIGTRAP; si.si_code = TRAP_BRKPT; si.si_addr = (void *) (regs->iaoq[0] & ~3); @@ -259,252 +319,151 @@ } } -/* Format of the floating-point exception registers. */ -struct exc_reg { - unsigned int exception : 6; - unsigned int ei : 26; -}; - -/* Macros for grabbing bits of the instruction format from the 'ei' - field above. */ -/* Major opcode 0c and 0e */ -#define FP0CE_UID(i) (((i) >> 6) & 3) -#define FP0CE_CLASS(i) (((i) >> 9) & 3) -#define FP0CE_SUBOP(i) (((i) >> 13) & 7) -#define FP0CE_SUBOP1(i) (((i) >> 15) & 7) /* Class 1 subopcode */ -#define FP0C_FORMAT(i) (((i) >> 11) & 3) -#define FP0E_FORMAT(i) (((i) >> 11) & 1) - -/* Major opcode 0c, uid 2 (performance monitoring) */ -#define FPPM_SUBOP(i) (((i) >> 9) & 0x1f) - -/* Major opcode 2e (fused operations). */ -#define FP2E_SUBOP(i) (((i) >> 5) & 1) -#define FP2E_FORMAT(i) (((i) >> 11) & 1) - -/* Major opcode 26 (FMPYSUB) */ -/* Major opcode 06 (FMPYADD) */ -#define FPx6_FORMAT(i) ((i) & 0x1f) - -/* Flags and enable bits of the status word. */ -#define FPSW_FLAGS(w) ((w) >> 27) -#define FPSW_ENABLE(w) ((w) & 0x1f) -#define FPSW_V (1<<4) -#define FPSW_Z (1<<3) -#define FPSW_O (1<<2) -#define FPSW_U (1<<1) -#define FPSW_I (1<<0) - -/* Emulate a floating point instruction if necessary and possible - (this will be moved elsewhere eventually). Return zero if - successful or if emulation was not required, -1 if the instruction - is actually illegal or unimplemented. The status word passed as - the first parameter will be modified to signal exceptions, if - any. */ - -/* FIXME!!! This is really incomplete and, at the moment, most - illegal FP instructions will simply act as no-ops. Obviously that - is *not* what we want. Also we don't even try to handle exception - types other than the 'unimplemented' ones. */ -int -fp_emul_insn(u32 *sw, struct exc_reg exc, struct pt_regs *regs) -{ - switch (exc.exception) { - case 0x3: /* Unimplemented, opcode 06 */ - break; - case 0x9: /* Unimplemented, opcode 0c */ - /* We do not support quadword operations, end of - story. There's no support for them in GCC. */ - if (FP0C_FORMAT(exc.ei) == 3) - return -1; /* SIGILL */ - /* Fall through. */ - case 0xa: /* Unimplemented, opcode 0e */ - if (FP0CE_CLASS(exc.ei) == 1) { - /* FCNV instructions of various sorts. */ - } else { - if (FP0CE_CLASS(exc.ei == 0) - && FP0CE_SUBOP(exc.ei == 5)) { - /* FRND instructions should be - emulated, at some point, I - guess. */ - return -1; /* SIGILL */ - } - } - break; - case 0x23: /* Unimplemented, opcode 26 */ - break; - case 0x2b: /* Unimplemented, opcode 2e */ - break; - case 0x1: /* Unimplemented, opcode 0e/0c */ - /* FIXME: How the hell are we supposed to tell which - opcode it is? */ - break; - default: - return -1; /* Punt */ - } +int handle_toc(void) +{ + printk(KERN_CRIT "TOC call.\n"); return 0; } -/* Handle a floating point exception. Return zero if the faulting - instruction can be completed successfully. */ -int -handle_fpe(struct pt_regs *regs) +static void default_trap(int code, struct pt_regs *regs) { - struct siginfo si; - union { - struct fpsw { - /* flag bits */ - unsigned int fv : 1; - unsigned int fz : 1; - unsigned int fo : 1; - unsigned int fu : 1; - unsigned int fi : 1; - - unsigned int c : 1; - unsigned int pad1 : 4; - unsigned int cq : 11; - unsigned int rm : 2; - unsigned int pad2 : 2; - unsigned int t : 1; - unsigned int d : 1; - - /* enable bits */ - unsigned int ev : 1; - unsigned int ez : 1; - unsigned int eo : 1; - unsigned int eu : 1; - unsigned int ei : 1; - } status; - u32 word; - } sw; - struct exc_reg excepts[7]; - unsigned int code = 0; - unsigned int throw; - - /* Status word = FR0L. */ - memcpy(&sw, regs->fr, sizeof(sw)); - /* Exception words = FR0R-FR3R. */ - memcpy(excepts, ((char *) regs->fr) + 4, sizeof(excepts)); - - /* This is all CPU dependent. Since there is no public - documentation on the PA2.0 processors we will just assume - everything is like the 7100/7100LC/7300LC for now. - - Specifically: All exceptions are marked as "unimplemented" - in the exception word, and the only exception word used is - excepts[1]. */ - - /* Try to emulate the instruction. Also determine if it is - really an illegal instruction in the process. - - FIXME: fp_emul_insn() only checks for the "unimplemented" - exceptions at the moment. So this may break horribly on - PA2.0, where we may want to also check to see if we should - just send SIGFPE (or maybe not, let's see the documentation - first...) */ - if (fp_emul_insn(&sw.word, excepts[1], regs) == -1) - goto send_sigill; - - /* Take the intersection of the flag bits in the FPSW and the - enable bits in the FPSW. */ - throw = FPSW_FLAGS(sw.word) & FPSW_ENABLE(sw.word); - - /* Concoct an appropriate si_code. Of course we don't know - what to do if multiple exceptions were enabled and multiple - flags were set. Maybe that's why HP/UX doesn't implement - feenableexcept(). */ - - if (throw == 0) - goto success; /* Duh. */ - else if (throw & FPSW_V) - code = FPE_FLTINV; - else if (throw & FPSW_Z) - code = FPE_FLTDIV; - else if (throw & FPSW_O) - code = FPE_FLTOVF; - else if (throw & FPSW_U) - code = FPE_FLTUND; - else if (throw & FPSW_I) - code = FPE_FLTRES; - -#if 1 /* Debugging... */ - printk("Unemulated floating point exception, pid=%d (%s)\n", - current->pid, current->comm); + printk(KERN_ERR "Trap %d on CPU %d\n", code, smp_processor_id()); show_regs(regs); - { - int i; - printk("FP Status: %08x\n", sw.word); - printk("FP Exceptions:\n"); - for (i = 0; i < 7; i++) { - printk("\tExcept%d: exception %03x insn %06x\n", - i, excepts[i].exception, excepts[i].ei); - } - } -#endif +} - /* FIXME: Should we clear the flag bits, T bit, and exception - registers here? */ +void (*cpu_lpmc) (int code, struct pt_regs *regs) = default_trap; - si.si_signo = SIGFPE; - si.si_errno = 0; - si.si_code = code; - si.si_addr = (void *) regs->iaoq[0]; - force_sig_info(SIGFPE, &si, current); - return -1; - send_sigill: - si.si_signo = SIGILL; - si.si_errno = 0; - si.si_code = ILL_COPROC; - si.si_addr = (void *) regs->iaoq[0]; - force_sig_info(SIGILL, &si, current); - return -1; - - success: - /* We absolutely have to clear the T bit and exception - registers to allow the process to recover. Otherwise every - subsequent floating point instruction will trap. */ - sw.status.t = 0; - memset(excepts, 0, sizeof(excepts)); - - memcpy(regs->fr, &sw, sizeof(sw)); - memcpy(((char *) regs->fr) + 4,excepts , sizeof(excepts)); - return 0; +#ifdef CONFIG_KWDB +int debug_call (void) +{ + printk (KERN_DEBUG "Debug call.\n"); + return 0; } -int handle_toc(void) +int debug_call_leaf (void) { - return 0; + return 0; } +#endif /* CONFIG_KWDB */ + -void default_trap(int code, struct pt_regs *regs) +void transfer_pim_to_trap_frame(struct pt_regs *regs) { - printk("Trap %d on CPU %d\n", code, smp_processor_id()); + register int i; + extern unsigned int hpmc_pim_data[]; + struct pdc_hpmc_pim_11 *pim_narrow; + struct pdc_hpmc_pim_20 *pim_wide; - show_regs(regs); -} + if (boot_cpu_data.cpu_type >= pcxu) { -void (*cpu_lpmc) (int code, struct pt_regs *regs) = default_trap; + pim_wide = (struct pdc_hpmc_pim_20 *)hpmc_pim_data; + /* + * Note: The following code will probably generate a + * bunch of truncation error warnings from the compiler. + * Could be handled with an ifdef, but perhaps there + * is a better way. + */ -#ifdef CONFIG_KWDB -int -debug_call (void) { - printk ("Debug call.\n"); - return 0; -} + regs->gr[0] = pim_wide->cr[22]; -int -debug_call_leaf (void) { - return 0; + for (i = 1; i < 32; i++) + regs->gr[i] = pim_wide->gr[i]; + + for (i = 0; i < 32; i++) + regs->fr[i] = pim_wide->fr[i]; + + for (i = 0; i < 8; i++) + regs->sr[i] = pim_wide->sr[i]; + + regs->iasq[0] = pim_wide->cr[17]; + regs->iasq[1] = pim_wide->iasq_back; + regs->iaoq[0] = pim_wide->cr[18]; + regs->iaoq[1] = pim_wide->iaoq_back; + + regs->sar = pim_wide->cr[11]; + regs->iir = pim_wide->cr[19]; + regs->isr = pim_wide->cr[20]; + regs->ior = pim_wide->cr[21]; + } + else { + pim_narrow = (struct pdc_hpmc_pim_11 *)hpmc_pim_data; + + regs->gr[0] = pim_narrow->cr[22]; + + for (i = 1; i < 32; i++) + regs->gr[i] = pim_narrow->gr[i]; + + for (i = 0; i < 32; i++) + regs->fr[i] = pim_narrow->fr[i]; + + for (i = 0; i < 8; i++) + regs->sr[i] = pim_narrow->sr[i]; + + regs->iasq[0] = pim_narrow->cr[17]; + regs->iasq[1] = pim_narrow->iasq_back; + regs->iaoq[0] = pim_narrow->cr[18]; + regs->iaoq[1] = pim_narrow->iaoq_back; + + regs->sar = pim_narrow->cr[11]; + regs->iir = pim_narrow->cr[19]; + regs->isr = pim_narrow->cr[20]; + regs->ior = pim_narrow->cr[21]; + } + + /* + * The following fields only have meaning if we came through + * another path. So just zero them here. + */ + + regs->ksp = 0; + regs->kpc = 0; + regs->orig_r28 = 0; } -#endif /* CONFIG_KWDB */ -extern void do_page_fault(struct pt_regs *, int, unsigned long); -extern void parisc_terminate(char *, struct pt_regs *, int, unsigned long); -extern void transfer_pim_to_trap_frame(struct pt_regs *); -extern void pdc_console_restart(void); + +/* + * This routine handles page faults. It determines the address, + * and the problem, and then passes it off to one of the appropriate + * routines. + */ +void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long offset) +{ + static spinlock_t terminate_lock = SPIN_LOCK_UNLOCKED; + + set_eiem(0); + __cli(); + spin_lock(&terminate_lock); + + /* unlock the pdc lock if necessary */ + pdc_emergency_unlock(); + + /* restart pdc console if necessary */ + if (!console_drivers) + pdc_console_restart(); + + if (code == 1) + transfer_pim_to_trap_frame(regs); + + show_stack(regs); + + printk("\n"); + printk(KERN_CRIT "%s: Code=%d regs=%p (Addr=" RFMT ")\n", + msg, code, regs, offset); + show_regs(regs); + + spin_unlock(&terminate_lock); + + /* put soft power button back under hardware control; + * if the user had pressed it once at any time, the + * system will shut down immediately right here. */ + pdc_soft_power_button(0); + + for(;;) + ; +} void handle_interruption(int code, struct pt_regs *regs) { @@ -520,75 +479,127 @@ else sti(); -#ifdef __LP64__ - - /* - * FIXME: - * For 32 bit processes we don't want the b bits (bits 0 & 1) - * in the ior. This is more appropriately handled in the tlb - * miss handlers. Changes need to be made to support addresses - * >32 bits for 64 bit processes. - */ - - regs->ior &= 0x3FFFFFFFFFFFFFFFUL; -#endif - #if 0 - printk("interrupted with code %d, regs %p\n", code, regs); - show_regs(regs); + printk(KERN_CRIT "Interruption # %d\n", code); #endif switch(code) { + case 1: - parisc_terminate("High Priority Machine Check (HPMC)",regs,code,0); + /* High-priority machine check (HPMC) */ + parisc_terminate("High Priority Machine Check (HPMC)", + regs, code, 0); /* NOT REACHED */ - case 3: /* Recovery counter trap */ + + case 2: + /* Power failure interrupt */ + printk(KERN_CRIT "Power failure interrupt !\n"); + return; + + case 3: + /* Recovery counter trap */ regs->gr[0] &= ~PSW_R; if (regs->iasq[0]) handle_gdb_break(regs, TRAP_TRACE); - /* else this must be the start of a syscall - just let it - * run. - */ + /* else this must be the start of a syscall - just let it run */ return; case 5: + /* Low-priority machine check */ flush_all_caches(); cpu_lpmc(5, regs); return; case 6: + /* Instruction TLB miss fault/Instruction page fault */ fault_address = regs->iaoq[0]; fault_space = regs->iasq[0]; break; - case 9: /* Break Instruction */ + case 8: + /* Illegal instruction trap */ + die_if_kernel("Illegal instruction", regs, code); + si.si_code = ILL_ILLOPC; + goto give_sigill; + + case 9: + /* Break instruction trap */ handle_break(regs->iir,regs); return; + + case 10: + /* Privileged operation trap */ + die_if_kernel("Privileged operation", regs, code); + si.si_code = ILL_PRVOPC; + goto give_sigill; + + case 11: + /* Privileged register trap */ + if ((regs->iir & 0xffdfffe0) == 0x034008a0) { + + /* This is a MFCTL cr26/cr27 to gr instruction. + * PCXS traps on this, so we need to emulate it. + */ + + if (regs->iir & 0x00200000) + regs->gr[regs->iir & 0x1f] = mfctl(27); + else + regs->gr[regs->iir & 0x1f] = mfctl(26); + + regs->iaoq[0] = regs->iaoq[1]; + regs->iaoq[1] += 4; + regs->iasq[0] = regs->iasq[1]; + return; + } + + die_if_kernel("Privileged register usage", regs, code); + si.si_code = ILL_PRVREG; + give_sigill: + si.si_signo = SIGILL; + si.si_errno = 0; + si.si_addr = (void *) regs->iaoq[0]; + force_sig_info(SIGILL, &si, current); + return; case 14: /* Assist Exception Trap, i.e. floating point exception. */ die_if_kernel("Floating point exception", regs, 0); /* quiet */ handle_fpe(regs); return; - case 15: - case 16: /* Non-Access TLB miss faulting address is in IOR */ + case 17: - case 26: + /* Non-access data TLB miss fault/Non-access data page fault */ + /* TODO: Still need to add slow path emulation code here */ fault_address = regs->ior; - fault_space = regs->isr; + parisc_terminate("Non access data tlb fault!",regs,code,fault_address); - if (code == 26 && fault_space == 0) - parisc_terminate("Data access rights fault in kernel",regs,code,fault_address); + case 18: + /* PCXS only -- later cpu's split this into types 26,27 & 28 */ + /* Check for unaligned access */ + if (check_unaligned(regs)) { + handle_unaligned(regs); + return; + } + /* Fall Through */ + + case 15: /* Data TLB miss fault/Data page fault */ + case 26: /* PCXL: Data memory access rights trap */ + fault_address = regs->ior; + fault_space = regs->isr; break; case 19: + /* Data memory break trap */ regs->gr[0] |= PSW_X; /* So we can single-step over the trap */ /* fall thru */ case 21: + /* Page reference trap */ handle_gdb_break(regs, TRAP_HWBKPT); return; - case 25: /* Taken branch trap */ + case 25: + /* Taken branch trap */ +#ifndef CONFIG_KWDB regs->gr[0] &= ~PSW_T; if (regs->iasq[0]) handle_gdb_break(regs, TRAP_BRANCH); @@ -596,9 +607,8 @@ * run. */ return; - -#if 0 /* def CONFIG_KWDB */ - case I_TAKEN_BR: /* 25 */ +#else + /* Kernel debugger: */ mtctl(0, 15); pt_regs_to_ssp(regs, &ssp); kgdb_trap(I_TAKEN_BR, &ssp, 1); @@ -606,39 +616,64 @@ break; #endif /* CONFIG_KWDB */ - case 8: - die_if_kernel("Illegal instruction", regs, code); - si.si_code = ILL_ILLOPC; - goto give_sigill; + case 7: + /* Instruction access rights */ + /* PCXL: Instruction memory protection trap */ + + /* + * This could be caused by either: 1) a process attempting + * to execute within a vma that does not have execute + * permission, or 2) an access rights violation caused by a + * flush only translation set up by ptep_get_and_clear(). + * So we check the vma permissions to differentiate the two. + * If the vma indicates we have execute permission, then + * the cause is the latter one. In this case, we need to + * call do_page_fault() to fix the problem. + */ - case 10: - die_if_kernel("Priviledged operation - shouldn't happen!", regs, code); - si.si_code = ILL_PRVOPC; - goto give_sigill; - case 11: - die_if_kernel("Priviledged register - shouldn't happen!", regs, code); - si.si_code = ILL_PRVREG; - give_sigill: - si.si_signo = SIGILL; + if (user_mode(regs)) { + struct vm_area_struct *vma; + + down_read(¤t->mm->mmap_sem); + vma = find_vma(current->mm,regs->iaoq[0]); + if (vma && (regs->iaoq[0] >= vma->vm_start) + && (vma->vm_flags & VM_EXEC)) { + + fault_address = regs->iaoq[0]; + fault_space = regs->iasq[0]; + + up_read(¤t->mm->mmap_sem); + break; /* call do_page_fault() */ + } + up_read(¤t->mm->mmap_sem); + } + /* Fall Through */ + + case 27: + /* Data memory protection ID trap */ + die_if_kernel("Protection id trap", regs, code); + si.si_code = SEGV_MAPERR; + si.si_signo = SIGSEGV; si.si_errno = 0; - si.si_addr = (void *) regs->iaoq[0]; - force_sig_info(SIGILL, &si, current); + if (code == 7) + si.si_addr = (void *) regs->iaoq[0]; + else + si.si_addr = (void *) regs->ior; + force_sig_info(SIGSEGV, &si, current); return; - case 28: /* Unaligned just causes SIGBUS for now */ - die_if_kernel("Unaligned data reference", regs, code); - si.si_code = BUS_ADRALN; - si.si_signo = SIGBUS; - si.si_errno = 0; - si.si_addr = (void *) regs->ior; - force_sig_info(SIGBUS, &si, current); + case 28: + /* Unaligned data reference trap */ + handle_unaligned(regs); return; default: if (user_mode(regs)) { - printk("\nhandle_interruption() pid=%d command='%s'\n", +#ifdef PRINT_USER_FAULTS + printk(KERN_DEBUG "\nhandle_interruption() pid=%d command='%s'\n", current->pid, current->comm); show_regs(regs); +#endif /* SIGBUS, for lack of a better one. */ si.si_signo = SIGBUS; si.si_code = BUS_OBJERR; @@ -647,18 +682,20 @@ force_sig_info(SIGBUS, &si, current); return; } - parisc_terminate("Unexpected Interruption!",regs,code,0); + parisc_terminate("Unexpected interruption", regs, code, 0); /* NOT REACHED */ } if (user_mode(regs)) { if (fault_space != regs->sr[7]) { +#ifdef PRINT_USER_FAULTS if (fault_space == 0) - printk("User Fault on Kernel Space "); - else /* this case should never happen, but whatever... */ - printk("User Fault (long pointer) "); + printk(KERN_DEBUG "User Fault on Kernel Space "); + else + printk(KERN_DEBUG "User Fault (long pointer) "); printk("pid=%d command='%s'\n", current->pid, current->comm); show_regs(regs); +#endif si.si_signo = SIGSEGV; si.si_errno = 0; si.si_code = SEGV_MAPERR; @@ -674,7 +711,7 @@ */ if (fault_space == 0) - parisc_terminate("Kernel Fault",regs,code,fault_address); + parisc_terminate("Kernel Fault", regs, code, fault_address); } #ifdef CONFIG_KWDB @@ -682,149 +719,15 @@ #endif /* CONFIG_KWDB */ do_page_fault(regs, code, fault_address); - - /* - * This should not be necessary. - * However, we do not currently - * implement flush_page_to_ram. - * - * The problem is that if we just - * brought in some code through the - * D-cache, the I-cache may not see - * it since it hasn't been flushed - * to ram. - */ - -/* flush_all_caches(); */ - -#if 0 - printk("returning %p\n", regs); -/* show_regs(regs); */ -#endif - - return; - -} - -void show_stack(unsigned long sp) -{ -#if 1 - if ((sp & 0xc0000000UL) == 0xc0000000UL) { - - __u32 *stackptr; - __u32 *dumpptr; - - /* Stack Dump! */ - - stackptr = (__u32 *)sp; - dumpptr = (__u32 *)(sp & ~(INIT_TASK_SIZE - 1)); - printk("\nDumping Stack from %p to %p:\n",dumpptr,stackptr); - while (dumpptr < stackptr) { - printk("%04x %08x %08x %08x %08x %08x %08x %08x %08x\n", - ((__u32)dumpptr) & 0xffff, - dumpptr[0], dumpptr[1], dumpptr[2], dumpptr[3], - dumpptr[4], dumpptr[5], dumpptr[6], dumpptr[7]); - dumpptr += 8; - } - } -#endif } -void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long offset) +void show_trace_task(struct task_struct *tsk) { - set_eiem(0); - cli(); - - if (code == 1) - transfer_pim_to_trap_frame(regs); - -#if 1 - show_stack(regs->gr[30]); -#endif - - printk("\n%s: Code=%d regs=%p (Addr=%08lx)\n",msg,code,regs,offset); - show_regs(regs); - - for(;;) - ; + BUG(); } -void transfer_pim_to_trap_frame(struct pt_regs *regs) -{ - register int i; - extern unsigned int hpmc_pim_data[]; - struct pdc_hpmc_pim_11 *pim_narrow; - struct pdc_hpmc_pim_20 *pim_wide; - - if (boot_cpu_data.cpu_type >= pcxu) { - pim_wide = (struct pdc_hpmc_pim_20 *)hpmc_pim_data; - - /* - * Note: The following code will probably generate a - * bunch of truncation error warnings from the compiler. - * Could be handled with an ifdef, but perhaps there - * is a better way. - */ - - regs->gr[0] = pim_wide->cr[22]; - - for (i = 1; i < 32; i++) - regs->gr[i] = pim_wide->gr[i]; - - for (i = 0; i < 32; i++) - regs->fr[i] = pim_wide->fr[i]; - - for (i = 0; i < 8; i++) - regs->sr[i] = pim_wide->sr[i]; - - regs->iasq[0] = pim_wide->cr[17]; - regs->iasq[1] = pim_wide->iasq_back; - regs->iaoq[0] = pim_wide->cr[18]; - regs->iaoq[1] = pim_wide->iaoq_back; - - regs->cr30 = pim_wide->cr[30]; - regs->sar = pim_wide->cr[11]; - regs->iir = pim_wide->cr[19]; - regs->isr = pim_wide->cr[20]; - regs->ior = pim_wide->cr[21]; - } - else { - pim_narrow = (struct pdc_hpmc_pim_11 *)hpmc_pim_data; - - regs->gr[0] = pim_narrow->cr[22]; - - for (i = 1; i < 32; i++) - regs->gr[i] = pim_narrow->gr[i]; - - for (i = 0; i < 32; i++) - regs->fr[i] = pim_narrow->fr[i]; - - for (i = 0; i < 8; i++) - regs->sr[i] = pim_narrow->sr[i]; - - regs->iasq[0] = pim_narrow->cr[17]; - regs->iasq[1] = pim_narrow->iasq_back; - regs->iaoq[0] = pim_narrow->cr[18]; - regs->iaoq[1] = pim_narrow->iaoq_back; - - regs->cr30 = pim_narrow->cr[30]; - regs->sar = pim_narrow->cr[11]; - regs->iir = pim_narrow->cr[19]; - regs->isr = pim_narrow->cr[20]; - regs->ior = pim_narrow->cr[21]; - } - - /* - * The following fields only have meaning if we came through - * another path. So just zero them here. - */ - - regs->ksp = 0; - regs->kpc = 0; - regs->orig_r28 = 0; -} int __init check_ivt(void *iva) { @@ -836,7 +739,7 @@ extern void os_hpmc(void); extern void os_hpmc_end(void); - if(strcmp((char *)iva, "cows can fly")) + if (strcmp((char *)iva, "cows can fly")) return -1; ivap = (u32 *)iva; @@ -851,10 +754,10 @@ hpmcp = (u32 *)os_hpmc; - for(i=0; i= pcxu) iva = (void *) &fault_vector_20; else @@ -883,12 +783,6 @@ iva = (void *) &fault_vector_11; #endif - if(check_ivt(iva)) + if (check_ivt(iva)) panic("IVT invalid"); - - mtctl(0, 30); - mtctl(90000000, 16); - set_eiem(-1L); - mtctl(-1L, 23); - asm volatile ("rsm 0,%0" : "=r" (eiem)); } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/kernel/unaligned.c linux.19rc3-ac4/arch/parisc/kernel/unaligned.c --- linux.19rc3/arch/parisc/kernel/unaligned.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/kernel/unaligned.c 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,434 @@ +/* $Id: unaligned.c,v 1.9 2001/10/04 03:31:08 tausq Exp $ + * + * Unaligned memory access handler + * + * Copyright (C) 2001 Randolph Chung + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* #define DEBUG_UNALIGNED 1 */ + +#ifdef DEBUG_UNALIGNED +#define DPRINTF(fmt, args...) do { printk(KERN_DEBUG "%s:%d:%s ", __FILE__, __LINE__, __FUNCTION__ ); printk(KERN_DEBUG fmt, ##args ); } while (0) +#else +#define DPRINTF(fmt, args...) +#endif + +#ifdef __LP64__ +#define RFMT "%016lx" +#else +#define RFMT "%08lx" +#endif + +/* 1111 1100 0000 0000 0001 0011 1100 0000 */ +#define OPCODE1(a,b,c) ((a)<<26|(b)<<12|(c)<<6) +#define OPCODE2(a,b) ((a)<<26|(b)<<1) +#define OPCODE3(a,b) ((a)<<26|(b)<<2) +#define OPCODE4(a) ((a)<<26) +#define OPCODE1_MASK OPCODE1(0x3f,1,0xf) +#define OPCODE2_MASK OPCODE2(0x3f,1) +#define OPCODE3_MASK OPCODE3(0x3f,1) +#define OPCODE4_MASK OPCODE4(0x3f) + +/* skip LDB (index) */ +#define OPCODE_LDH_I OPCODE1(0x03,0,0x1) +#define OPCODE_LDW_I OPCODE1(0x03,0,0x2) +#define OPCODE_LDD_I OPCODE1(0x03,0,0x3) +#define OPCODE_LDDA_I OPCODE1(0x03,0,0x4) +/* skip LDCD (index) */ +#define OPCODE_LDWA_I OPCODE1(0x03,0,0x6) +/* skip LDCW (index) */ +/* skip LDB (short) */ +#define OPCODE_LDH_S OPCODE1(0x03,1,0x1) +#define OPCODE_LDW_S OPCODE1(0x03,1,0x2) +#define OPCODE_LDD_S OPCODE1(0x03,1,0x3) +#define OPCODE_LDDA_S OPCODE1(0x03,1,0x4) +/* skip LDCD (short) */ +#define OPCODE_LDWA_S OPCODE1(0x03,1,0x6) +/* skip LDCW (short) */ +/* skip STB */ +#define OPCODE_STH OPCODE1(0x03,1,0x9) +#define OPCODE_STW OPCODE1(0x03,1,0xa) +#define OPCODE_STD OPCODE1(0x03,1,0xb) +/* skip STBY */ +/* skip STDBY */ +#define OPCODE_STWA OPCODE1(0x03,1,0xe) +#define OPCODE_STDA OPCODE1(0x03,1,0xf) + +#define OPCODE_LDD_L OPCODE2(0x14,0) +#define OPCODE_FLDD_L OPCODE2(0x14,1) +#define OPCODE_STD_L OPCODE2(0x1c,0) +#define OPCODE_FSTD_L OPCODE2(0x1c,1) + +#define OPCODE_LDW_M OPCODE3(0x17,1) +#define OPCODE_FLDW_L OPCODE3(0x17,0) +#define OPCODE_FSTW_L OPCODE3(0x1f,0) +#define OPCODE_STW_M OPCODE3(0x1f,1) + +#define OPCODE_LDH_L OPCODE4(0x11) +#define OPCODE_LDW_L OPCODE4(0x12) +#define OPCODE_LDW_L2 OPCODE4(0x13) +#define OPCODE_STH_L OPCODE4(0x19) +#define OPCODE_STW_L OPCODE4(0x1A) +#define OPCODE_STW_L2 OPCODE4(0x1B) + + + +void die_if_kernel (char *str, struct pt_regs *regs, long err); + +static int emulate_load(struct pt_regs *regs, int len, int toreg) +{ + unsigned long saddr = regs->ior; + unsigned long val = 0; + int ret = 0; + + if (regs->isr != regs->sr[7]) + { + printk(KERN_CRIT "isr verification failed (isr: " RFMT ", sr7: " RFMT "\n", + regs->isr, regs->sr[7]); + return 1; + } + + DPRINTF("load " RFMT ":" RFMT " to r%d for %d bytes\n", + regs->isr, regs->ior, toreg, len); + + __asm__ __volatile__ ( +" mfsp %%sr1, %%r20\n" +" mtsp %6, %%sr1\n" +" copy %%r0, %0\n" +"0: ldbs,ma 1(%%sr1,%4), %%r19\n" +" addi -1, %5, %5\n" +" cmpib,>= 0, %5, 2f\n" +" or %%r19, %0, %0\n" +" b 0b\n" + +#ifdef __LP64__ + "depd,z %0, 55, 56, %0\n" +#else + "depw,z %0, 23, 24, %0\n" +#endif + +"1: ldi 10, %1\n" +"2: mtsp %%r20, %%sr1\n" +" .section __ex_table,\"a\"\n" +#ifdef __LP64__ + ".dword 0b, (1b-0b)\n" +#else + ".word 0b, (1b-0b)\n" +#endif + ".previous\n" + : "=r" (val), "=r" (ret) + : "0" (val), "1" (ret), "r" (saddr), "r" (len), "r" (regs->isr) + : "r19", "r20" ); + + DPRINTF("val = 0x" RFMT "\n", val); + + regs->gr[toreg] = val; + + return ret; +} + +static int emulate_store(struct pt_regs *regs, int len, int frreg) +{ + int ret = 0; +#ifdef __LP64__ + unsigned long val = regs->gr[frreg] << (64 - (len << 3)); +#else + unsigned long val = regs->gr[frreg] << (32 - (len << 3)); +#endif + + if (regs->isr != regs->sr[7]) + { + printk(KERN_CRIT "isr verification failed (isr: " RFMT ", sr7: " RFMT "\n", + regs->isr, regs->sr[7]); + return 1; + } + + DPRINTF("store r%d (0x" RFMT ") to " RFMT ":" RFMT " for %d bytes\n", frreg, + regs->gr[frreg], regs->isr, regs->ior, len); + + + __asm__ __volatile__ ( +" mfsp %%sr1, %%r20\n" /* save sr1 */ +" mtsp %5, %%sr1\n" +#ifdef __LP64__ +"0: extrd,u %2, 7, 8, %%r19\n" +#else +"0: extrw,u %2, 7, 8, %%r19\n" +#endif +"1: stb,ma %%r19, 1(%%sr1, %3)\n" +" addi -1, %4, %4\n" +" cmpib,>= 0, %4, 3f\n" + +#ifdef __LP64__ + "depd,z %2, 55, 56, %2\n" +#else + "depw,z %2, 23, 24, %2\n" +#endif + +" b 0b\n" +" nop\n" + +"2: ldi 11, %0\n" +"3: mtsp %%r20, %%sr1\n" +" .section __ex_table,\"a\"\n" +#ifdef __LP64__ + ".dword 1b, (2b-1b)\n" +#else + ".word 1b, (2b-1b)\n" +#endif + ".previous\n" + : "=r" (ret) + : "0" (ret), "r" (val), "r" (regs->ior), "r" (len), "r" (regs->isr) + : "r19", "r20" ); + + return ret; +} + + +void handle_unaligned(struct pt_regs *regs) +{ + unsigned long unaligned_count = 0; + unsigned long last_time = 0; + int ret = -1; + struct siginfo si; + + /* if the unaligned access is inside the kernel: + * if the access is caused by a syscall, then we fault the calling + * user process + * otherwise we halt the kernel + */ + if (!user_mode(regs)) + { + const struct exception_table_entry *fix; + + /* see if the offending code have its own + * exception handler + */ + + fix = search_exception_table(regs->iaoq[0]); + if (fix) + { + /* lower bits of fix->skip are flags + * upper bits are the handler addr + */ + if (fix->skip & 1) + regs->gr[8] = -EFAULT; + if (fix->skip & 2) + regs->gr[9] = 0; + + regs->iaoq[0] += ((fix->skip) & ~3); + regs->iaoq[1] = regs->iaoq[0] + 4; + regs->gr[0] &= ~PSW_B; + + return; + } + } + + /* log a message with pacing */ + if (user_mode(regs)) + { + if (unaligned_count > 5 && jiffies - last_time > 5*HZ) + { + unaligned_count = 0; + last_time = jiffies; + } + if (++unaligned_count < 5) + { + char buf[256]; + sprintf(buf, "%s(%d): unaligned access to 0x" RFMT " at ip=0x" RFMT "\n", + current->comm, current->pid, regs->ior, regs->iaoq[0]); + printk(KERN_WARNING "%s", buf); +#ifdef DEBUG_UNALIGNED + show_regs(regs); +#endif + } + } + + /* TODO: make this cleaner... */ + switch (regs->iir & OPCODE1_MASK) + { + case OPCODE_LDH_I: + case OPCODE_LDH_S: + ret = emulate_load(regs, 2, regs->iir & 0x1f); + break; + + case OPCODE_LDW_I: + case OPCODE_LDWA_I: + case OPCODE_LDW_S: + case OPCODE_LDWA_S: + ret = emulate_load(regs, 4, regs->iir&0x1f); + break; + + case OPCODE_LDD_I: + case OPCODE_LDDA_I: + case OPCODE_LDD_S: + case OPCODE_LDDA_S: + ret = emulate_load(regs, 8, regs->iir&0x1f); + break; + + case OPCODE_STH: + ret = emulate_store(regs, 2, (regs->iir>>16)&0x1f); + break; + + case OPCODE_STW: + case OPCODE_STWA: + ret = emulate_store(regs, 4, (regs->iir>>16)&0x1f); + break; + + case OPCODE_STD: + case OPCODE_STDA: + ret = emulate_store(regs, 8, (regs->iir>>16)&0x1f); + break; + } + switch (regs->iir & OPCODE2_MASK) + { + case OPCODE_LDD_L: + case OPCODE_FLDD_L: + ret = emulate_load(regs, 8, (regs->iir>>16)&0x1f); + break; + + case OPCODE_STD_L: + case OPCODE_FSTD_L: + ret = emulate_store(regs, 8, (regs->iir>>16)&0x1f); + break; + } + switch (regs->iir & OPCODE3_MASK) + { + case OPCODE_LDW_M: + case OPCODE_FLDW_L: + ret = emulate_load(regs, 4, (regs->iir>>16)&0x1f); + break; + + case OPCODE_FSTW_L: + case OPCODE_STW_M: + ret = emulate_store(regs, 4, (regs->iir>>16)&0x1f); + break; + } + switch (regs->iir & OPCODE4_MASK) + { + case OPCODE_LDH_L: + ret = emulate_load(regs, 2, (regs->iir>>16)&0x1f); + break; + case OPCODE_LDW_L: + case OPCODE_LDW_L2: + ret = emulate_load(regs, 4, (regs->iir>>16)&0x1f); + break; + case OPCODE_STH_L: + ret = emulate_store(regs, 2, (regs->iir>>16)&0x1f); + break; + case OPCODE_STW_L: + case OPCODE_STW_L2: + ret = emulate_store(regs, 4, (regs->iir>>16)&0x1f); + break; + } + + if (ret < 0) + printk(KERN_CRIT "Not-handled unaligned insn 0x%08lx\n", regs->iir); + + DPRINTF("ret = %d\n", ret); + + if (ret) + { + printk(KERN_CRIT "Unaligned handler failed, ret = %d\n", ret); + die_if_kernel("Unaligned data reference", regs, 28); + + /* couldn't handle it ... */ + si.si_signo = SIGBUS; + si.si_errno = 0; + si.si_code = BUS_ADRALN; + si.si_addr = (void *)regs->ior; + force_sig_info(SIGBUS, &si, current); + + return; + } + + /* else we handled it, advance the PC.... */ + regs->iaoq[0] = regs->iaoq[1]; + regs->iaoq[1] = regs->iaoq[0] + 4; +} + +/* + * NB: check_unaligned() is only used for PCXS processors right + * now, so we only check for PA1.1 encodings at this point. + */ + +int +check_unaligned(struct pt_regs *regs) +{ + unsigned long align_mask; + + /* Get alignment mask */ + + align_mask = 0UL; + switch (regs->iir & OPCODE1_MASK) { + + case OPCODE_LDH_I: + case OPCODE_LDH_S: + case OPCODE_STH: + align_mask = 1UL; + break; + + case OPCODE_LDW_I: + case OPCODE_LDWA_I: + case OPCODE_LDW_S: + case OPCODE_LDWA_S: + case OPCODE_STW: + case OPCODE_STWA: + align_mask = 3UL; + break; + + default: + switch (regs->iir & OPCODE4_MASK) { + case OPCODE_LDH_L: + case OPCODE_STH_L: + align_mask = 1UL; + break; + case OPCODE_LDW_L: + case OPCODE_LDW_L2: + case OPCODE_STW_L: + case OPCODE_STW_L2: + align_mask = 3UL; + break; + } + break; + } + + return (int)(regs->ior & align_mask); +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/lib/bitops.c linux.19rc3-ac4/arch/parisc/lib/bitops.c --- linux.19rc3/arch/parisc/lib/bitops.c 2002-07-29 12:50:06.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/lib/bitops.c 2002-07-29 13:58:37.000000000 +0100 @@ -1,7 +1,10 @@ -/* atomic.c: atomic operations which got too long to be inlined all over - * the place. +/* + * bitops.c: atomic operations which got too long to be inlined all over + * the place. * - * Copyright 1999 Philipp Rumpf (prumpf@tux.org */ + * Copyright 1999 Philipp Rumpf (prumpf@tux.org) + * Copyright 2000 Grant Grundler (grundler@cup.hp.com) + */ #include #include @@ -17,44 +20,67 @@ spinlock_t __atomic_lock = SPIN_LOCK_UNLOCKED; -#ifndef __LP64__ -unsigned long __xchg(unsigned long x, unsigned long *ptr, int size) +#ifdef __LP64__ +unsigned long __xchg64(unsigned long x, unsigned long *ptr) { unsigned long temp, flags; - if (size != sizeof x) { - printk("__xchg called with bad pointer\n"); - } - spin_lock_irqsave(&__atomic_lock, flags); + SPIN_LOCK_IRQSAVE(ATOMIC_HASH(ptr), flags); temp = *ptr; *ptr = x; - spin_unlock_irqrestore(&__atomic_lock, flags); + SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(ptr), flags); return temp; } -#else -unsigned long __xchg(unsigned long x, unsigned long *ptr, int size) +#endif + +unsigned long __xchg32(int x, int *ptr) { - unsigned long temp, flags; - unsigned int *ptr32; + unsigned long flags; + unsigned long temp; + + SPIN_LOCK_IRQSAVE(ATOMIC_HASH(ptr), flags); + (long) temp = (long) *ptr; /* XXX - sign extension wanted? */ + *ptr = x; + SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(ptr), flags); + return temp; +} + + +unsigned long __xchg8(char x, char *ptr) +{ + unsigned long flags; + unsigned long temp; - if (size == 8) { -try_long: - spin_lock_irqsave(&__atomic_lock, flags); - temp = *ptr; - *ptr = x; - spin_unlock_irqrestore(&__atomic_lock, flags); - return temp; - } - if (size == 4) { - ptr32 = (unsigned int *)ptr; - spin_lock_irqsave(&__atomic_lock, flags); - temp = (unsigned long)*ptr32; - *ptr32 = (unsigned int)x; - spin_unlock_irqrestore(&__atomic_lock, flags); - return temp; - } + SPIN_LOCK_IRQSAVE(ATOMIC_HASH(ptr), flags); + (long) temp = (long) *ptr; /* XXX - sign extension wanted? */ + *ptr = x; + SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(ptr), flags); + return temp; +} + + +#ifdef __LP64__ +unsigned long __cmpxchg_u64(volatile unsigned long *ptr, unsigned long old, unsigned long new) +{ + unsigned long flags; + unsigned long prev; - printk("__xchg called with bad pointer\n"); - goto try_long; + SPIN_LOCK_IRQSAVE(ATOMIC_HASH(ptr), flags); + if ((prev = *ptr) == old) + *ptr = new; + SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(ptr), flags); + return prev; } #endif + +unsigned long __cmpxchg_u32(volatile unsigned int *ptr, unsigned int old, unsigned int new) +{ + unsigned long flags; + unsigned int prev; + + SPIN_LOCK_IRQSAVE(ATOMIC_HASH(ptr), flags); + if ((prev = *ptr) == old) + *ptr = new; + SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(ptr), flags); + return (unsigned long)prev; +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/lib/io.c linux.19rc3-ac4/arch/parisc/lib/io.c --- linux.19rc3/arch/parisc/lib/io.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/lib/io.c 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,459 @@ +/* + * arch/parisc/lib/io.c + * + * Copyright (c) Matthew Wilcox 2001 for Hewlett-Packard + * Copyright (c) Randolph Chung 2001 + * + * IO accessing functions which shouldn't be inlined because they're too big + */ + +#include +#include + +/* Copies a block of memory to a device in an efficient manner. + * Assumes the device can cope with 32-bit transfers. If it can't, + * don't use this function. + */ +void memcpy_toio(unsigned long dest, const void *src, int count) +{ + if ((dest & 3) != ((unsigned long)src & 3)) + goto bytecopy; + while (dest & 3) { + writeb(*(char *)src, dest++); + ((char *)src)++; + count--; + } + while (count > 3) { + __raw_writel(*(u32 *)src, dest); + (unsigned long) src += 4; + dest += 4; + count -= 4; + } + bytecopy: + while (count--) { + writeb(*(char *)src, dest++); + ((char *)src)++; + } +} + +/* +** Copies a block of memory from a device in an efficient manner. +** Assumes the device can cope with 32-bit transfers. If it can't, +** don't use this function. +** +** CR16 counts on C3000 reading 256 bytes from Symbios 896 RAM: +** 27341/64 = 427 cyc per int +** 61311/128 = 478 cyc per short +** 122637/256 = 479 cyc per byte +** Ergo bus latencies dominant (not transfer size). +** Minimize total number of transfers at cost of CPU cycles. +** TODO: only look at src alignment and adjust the stores to dest. +*/ +void memcpy_fromio(void *dest, unsigned long src, int count) +{ + /* first compare alignment of src/dst */ + if ( (((unsigned long)dest ^ src) & 1) || (count < 2) ) + goto bytecopy; + + if ( (((unsigned long)dest ^ src) & 2) || (count < 4) ) + goto shortcopy; + + /* Then check for misaligned start address */ + if (src & 1) { + *(u8 *)dest = readb(src); + ((u8 *)src)++; + ((u8 *)dest)++; + count--; + if (count < 2) goto bytecopy; + } + + if (src & 2) { + *(u16 *)dest = __raw_readw(src); + ((u16 *)src)++; + ((u16 *)dest)++; + count-=2; + } + + while (count > 3) { + *(u32 *)dest = __raw_readl(src); + dest += 4; + src += 4; + count -= 4; + } + + shortcopy: + while (count > 1) { + *(u16 *)dest = __raw_readw(src); + ((u16 *)src)++; + ((u16 *)dest)++; + count-=2; + } + + bytecopy: + while (count--) { + *(char *)dest = readb(src); + ((char *)src)++; + ((char *)dest)++; + } +} + +/* Sets a block of memory on a device to a given value. + * Assumes the device can cope with 32-bit transfers. If it can't, + * don't use this function. + */ +void memset_io(unsigned long dest, char fill, int count) +{ + u32 fill32 = (fill << 24) | (fill << 16) | (fill << 8) | fill; + while (dest & 3) { + writeb(fill, dest++); + count--; + } + while (count > 3) { + __raw_writel(fill32, dest); + dest += 4; + count -= 4; + } + while (count--) { + writeb(fill, dest++); + } +} + +/* + * Read COUNT 8-bit bytes from port PORT into memory starting at + * SRC. + */ +void insb (unsigned long port, void *dst, unsigned long count) +{ + while (((unsigned long)dst) & 0x3) { + if (!count) + return; + count--; + *(unsigned char *) dst = inb(port); + ((unsigned char *) dst)++; + } + + while (count >= 4) { + unsigned int w; + count -= 4; + w = inb(port) << 24; + w |= inb(port) << 16; + w |= inb(port) << 8; + w |= inb(port); + *(unsigned int *) dst = w; + ((unsigned int *) dst)++; + } + + while (count) { + --count; + *(unsigned char *) dst = inb(port); + ((unsigned char *) dst)++; + } +} + + +/* + * Read COUNT 16-bit words from port PORT into memory starting at + * SRC. SRC must be at least short aligned. This is used by the + * IDE driver to read disk sectors. Performance is important, but + * the interfaces seems to be slow: just using the inlined version + * of the inw() breaks things. + */ +void insw (unsigned long port, void *dst, unsigned long count) +{ + unsigned int l = 0, l2; + + if (!count) + return; + + switch (((unsigned long) dst) & 0x3) + { + case 0x00: /* Buffer 32-bit aligned */ + while (count>=2) { + + count -= 2; + l = cpu_to_le16(inw(port)) << 16; + l |= cpu_to_le16(inw(port)); + *(unsigned int *) dst = l; + ((unsigned int *) dst)++; + } + if (count) { + *(unsigned short *) dst = cpu_to_le16(inw(port)); + } + break; + + case 0x02: /* Buffer 16-bit aligned */ + *(unsigned short *) dst = cpu_to_le16(inw(port)); + ((unsigned short *) dst)++; + count--; + while (count>=2) { + + count -= 2; + l = cpu_to_le16(inw(port)) << 16; + l |= cpu_to_le16(inw(port)); + *(unsigned int *) dst = l; + ((unsigned int *) dst)++; + } + if (count) { + *(unsigned short *) dst = cpu_to_le16(inw(port)); + } + break; + + case 0x01: /* Buffer 8-bit aligned */ + case 0x03: + /* I don't bother with 32bit transfers + * in this case, 16bit will have to do -- DE */ + --count; + + l = cpu_to_le16(inw(port)); + *(unsigned char *) dst = l >> 8; + ((unsigned char *) dst)++; + while (count--) + { + l2 = cpu_to_le16(inw(port)); + *(unsigned short *) dst = (l & 0xff) << 8 | (l2 >> 8); + ((unsigned short *) dst)++; + l = l2; + } + *(unsigned char *) dst = l & 0xff; + break; + } +} + + + +/* + * Read COUNT 32-bit words from port PORT into memory starting at + * SRC. Now works with any alignment in SRC. Performance is important, + * but the interfaces seems to be slow: just using the inlined version + * of the inl() breaks things. + */ +void insl (unsigned long port, void *dst, unsigned long count) +{ + unsigned int l = 0, l2; + + if (!count) + return; + + switch (((unsigned long) dst) & 0x3) + { + case 0x00: /* Buffer 32-bit aligned */ + while (count--) + { + *(unsigned int *) dst = cpu_to_le32(inl(port)); + ((unsigned int *) dst)++; + } + break; + + case 0x02: /* Buffer 16-bit aligned */ + --count; + + l = cpu_to_le32(inl(port)); + *(unsigned short *) dst = l >> 16; + ((unsigned short *) dst)++; + + while (count--) + { + l2 = cpu_to_le32(inl(port)); + *(unsigned int *) dst = (l & 0xffff) << 16 | (l2 >> 16); + ((unsigned int *) dst)++; + l = l2; + } + *(unsigned short *) dst = l & 0xffff; + break; + case 0x01: /* Buffer 8-bit aligned */ + --count; + + l = cpu_to_le32(inl(port)); + *(unsigned char *) dst = l >> 24; + ((unsigned char *) dst)++; + *(unsigned short *) dst = (l >> 8) & 0xffff; + ((unsigned short *) dst)++; + while (count--) + { + l2 = cpu_to_le32(inl(port)); + *(unsigned int *) dst = (l & 0xff) << 24 | (l2 >> 8); + ((unsigned int *) dst)++; + l = l2; + } + *(unsigned char *) dst = l & 0xff; + break; + case 0x03: /* Buffer 8-bit aligned */ + --count; + + l = cpu_to_le32(inl(port)); + *(unsigned char *) dst = l >> 24; + ((unsigned char *) dst)++; + while (count--) + { + l2 = cpu_to_le32(inl(port)); + *(unsigned int *) dst = (l & 0xffffff) << 8 | l2 >> 24; + ((unsigned int *) dst)++; + l = l2; + } + *(unsigned short *) dst = (l >> 8) & 0xffff; + ((unsigned short *) dst)++; + *(unsigned char *) dst = l & 0xff; + break; + } +} + + +/* + * Like insb but in the opposite direction. + * Don't worry as much about doing aligned memory transfers: + * doing byte reads the "slow" way isn't nearly as slow as + * doing byte writes the slow way (no r-m-w cycle). + */ +void outsb(unsigned long port, const void * src, unsigned long count) +{ + while (count) { + count--; + outb(*(char *)src, port); + ((char *) src)++; + } +} + +/* + * Like insw but in the opposite direction. This is used by the IDE + * driver to write disk sectors. Performance is important, but the + * interfaces seems to be slow: just using the inlined version of the + * outw() breaks things. + */ +void outsw (unsigned long port, const void *src, unsigned long count) +{ + unsigned int l = 0, l2; + + if (!count) + return; + + switch (((unsigned long) src) & 0x3) + { + case 0x00: /* Buffer 32-bit aligned */ + while (count>=2) { + count -= 2; + l = *(unsigned int *) src; + ((unsigned int *) src)++; + outw(le16_to_cpu(l >> 16), port); + outw(le16_to_cpu(l & 0xffff), port); + } + if (count) { + outw(le16_to_cpu(*(unsigned short*)src), port); + } + break; + + case 0x02: /* Buffer 16-bit aligned */ + + outw(le16_to_cpu(*(unsigned short*)src), port); + ((unsigned short *) src)++; + count--; + + while (count>=2) { + count -= 2; + l = *(unsigned int *) src; + ((unsigned int *) src)++; + outw(le16_to_cpu(l >> 16), port); + outw(le16_to_cpu(l & 0xffff), port); + } + if (count) { + outw(le16_to_cpu(*(unsigned short*)src), port); + } + break; + + case 0x01: /* Buffer 8-bit aligned */ + /* I don't bother with 32bit transfers + * in this case, 16bit will have to do -- DE */ + + l = *(unsigned char *) src << 8; + ((unsigned char *) src)++; + count--; + while (count) + { + count--; + l2 = *(unsigned short *) src; + ((unsigned short *) src)++; + outw(le16_to_cpu(l | l2 >> 8), port); + l = l2 << 8; + } + l2 = *(unsigned char *) src; + outw (le16_to_cpu(l | l2>>8), port); + break; + + } +} + + +/* + * Like insl but in the opposite direction. This is used by the IDE + * driver to write disk sectors. Works with any alignment in SRC. + * Performance is important, but the interfaces seems to be slow: + * just using the inlined version of the outl() breaks things. + */ +void outsl (unsigned long port, const void *src, unsigned long count) +{ + unsigned int l = 0, l2; + + if (!count) + return; + + switch (((unsigned long) src) & 0x3) + { + case 0x00: /* Buffer 32-bit aligned */ + while (count--) + { + outl(le32_to_cpu(*(unsigned int *) src), port); + ((unsigned int *) src)++; + } + break; + + case 0x02: /* Buffer 16-bit aligned */ + --count; + + l = *(unsigned short *) src; + ((unsigned short *) src)++; + + while (count--) + { + l2 = *(unsigned int *) src; + ((unsigned int *) src)++; + outl (le32_to_cpu(l << 16 | l2 >> 16), port); + l = l2; + } + l2 = *(unsigned short *) src; + outl (le32_to_cpu(l << 16 | l2), port); + break; + case 0x01: /* Buffer 8-bit aligned */ + --count; + + l = *(unsigned char *) src << 24; + ((unsigned char *) src)++; + l |= *(unsigned short *) src << 8; + ((unsigned short *) src)++; + while (count--) + { + l2 = *(unsigned int *) src; + ((unsigned int *) src)++; + outl (le32_to_cpu(l | l2 >> 24), port); + l = l2 << 8; + } + l2 = *(unsigned char *) src; + outl (le32_to_cpu(l | l2), port); + break; + case 0x03: /* Buffer 8-bit aligned */ + --count; + + l = *(unsigned char *) src << 24; + ((unsigned char *) src)++; + while (count--) + { + l2 = *(unsigned int *) src; + ((unsigned int *) src)++; + outl (le32_to_cpu(l | l2 >> 8), port); + l = l2 << 24; + } + l2 = *(unsigned short *) src << 16; + ((unsigned short *) src)++; + l2 |= *(unsigned char *) src; + outl (le32_to_cpu(l | l2), port); + break; + } +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/lib/lusercopy.S linux.19rc3-ac4/arch/parisc/lib/lusercopy.S --- linux.19rc3/arch/parisc/lib/lusercopy.S 2002-07-29 12:50:06.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/lib/lusercopy.S 2002-07-29 13:58:37.000000000 +0100 @@ -1,5 +1,5 @@ -/*------------------------------------------------------------------------------ - * Native PARISC/Linux Project (http://www.puffingroup.com/parisc) +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) * * Assembly Language User Access Routines * Copyright (C) 2000 Hewlett-Packard (John Marvin) @@ -30,7 +30,6 @@ */ - .level 1.1 .text #include @@ -42,11 +41,8 @@ * on the flag stored in the task structure. */ - /* FIXME! depi below has hardcoded idea of kernel stack size */ - .macro get_sr - copy %r30,%r1 ;! Get task structure - depi 0,31,14,%r1 ;! into r1 + mfctl %cr30,%r1 ldw TASK_SEGMENT(%r1),%r22 mfsp %sr3,%r1 or,<> %r22,%r0,%r0 @@ -82,7 +78,11 @@ ldo 1(%r24),%r24 .section __ex_table,"a" +#ifdef __LP64__ + .dword 1b,(2b-1b) +#else .word 1b,(2b-1b) +#endif .previous .procend @@ -123,7 +123,11 @@ nop .section __ex_table,"a" +#ifdef __LP64__ + .dword 1b,(2b-1b) +#else .word 1b,(2b-1b) +#endif .previous .procend @@ -133,7 +137,7 @@ * * Returns -EFAULT if exception before terminator, * N if the entire buffer filled, - * otherwise strlen + 1 (i.e. includes zero byte) + * otherwise strlen (i.e. excludes zero byte) */ .export lstrncpy_from_user,code @@ -142,7 +146,7 @@ .callinfo NO_CALLS .entry comib,= 0,%r24,$lsfu_done - copy %r26,%r23 + copy %r24,%r23 get_sr 1: ldbs,ma 1(%sr1,%r25),%r1 $lsfu_loop: @@ -151,7 +155,7 @@ addib,<>,n -1,%r24,$lsfu_loop 2: ldbs,ma 1(%sr1,%r25),%r1 $lsfu_done: - sub %r26,%r23,%r28 + sub %r23,%r24,%r28 $lsfu_exit: bv %r0(%r2) nop @@ -161,8 +165,13 @@ ldi -EFAULT,%r28 .section __ex_table,"a" +#ifdef __LP64__ + .dword 1b,(3b-1b) + .dword 2b,(3b-2b) +#else .word 1b,(3b-1b) - .word 2b,(2b-1b) + .word 2b,(3b-2b) +#endif .previous .procend @@ -194,7 +203,11 @@ ldo 1(%r25),%r25 .section __ex_table,"a" +#ifdef __LP64__ + .dword 1b,(2b-1b) +#else .word 1b,(2b-1b) +#endif .previous .procend @@ -233,8 +246,13 @@ copy %r24,%r26 /* reset r26 so 0 is returned on fault */ .section __ex_table,"a" +#ifdef __LP64__ + .dword 1b,(3b-1b) + .dword 2b,(3b-2b) +#else .word 1b,(3b-1b) - .word 2b,(2b-1b) + .word 2b,(3b-2b) +#endif .previous .procend diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/lib/Makefile linux.19rc3-ac4/arch/parisc/lib/Makefile --- linux.19rc3/arch/parisc/lib/Makefile 2002-07-29 12:50:06.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/lib/Makefile 2002-07-29 13:58:37.000000000 +0100 @@ -4,10 +4,6 @@ L_TARGET = lib.a -L_OBJS = lusercopy.o bitops.o checksum.o - - -.S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o +obj-y := lusercopy.o bitops.o checksum.o io.o memset.o include $(TOPDIR)/Rules.make diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/lib/memset.c linux.19rc3-ac4/arch/parisc/lib/memset.c --- linux.19rc3/arch/parisc/lib/memset.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/lib/memset.c 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,91 @@ +/* Copyright (C) 1991, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Slight modifications for pa-risc linux - Paul Bame */ + +#include +#include + +#define OPSIZ (BITS_PER_LONG/8) +typedef unsigned long op_t; + +void * +memset (void *dstpp, int sc, size_t len) +{ + unsigned int c = sc; + long int dstp = (long int) dstpp; + + if (len >= 8) + { + size_t xlen; + op_t cccc; + + cccc = (unsigned char) c; + cccc |= cccc << 8; + cccc |= cccc << 16; + if (OPSIZ > 4) + /* Do the shift in two steps to avoid warning if long has 32 bits. */ + cccc |= (cccc << 16) << 16; + + /* There are at least some bytes to set. + No need to test for LEN == 0 in this alignment loop. */ + while (dstp % OPSIZ != 0) + { + ((unsigned char *) dstp)[0] = c; + dstp += 1; + len -= 1; + } + + /* Write 8 `op_t' per iteration until less than 8 `op_t' remain. */ + xlen = len / (OPSIZ * 8); + while (xlen > 0) + { + ((op_t *) dstp)[0] = cccc; + ((op_t *) dstp)[1] = cccc; + ((op_t *) dstp)[2] = cccc; + ((op_t *) dstp)[3] = cccc; + ((op_t *) dstp)[4] = cccc; + ((op_t *) dstp)[5] = cccc; + ((op_t *) dstp)[6] = cccc; + ((op_t *) dstp)[7] = cccc; + dstp += 8 * OPSIZ; + xlen -= 1; + } + len %= OPSIZ * 8; + + /* Write 1 `op_t' per iteration until less than OPSIZ bytes remain. */ + xlen = len / OPSIZ; + while (xlen > 0) + { + ((op_t *) dstp)[0] = cccc; + dstp += OPSIZ; + xlen -= 1; + } + len %= OPSIZ; + } + + /* Write the last few bytes. */ + while (len > 0) + { + ((unsigned char *) dstp)[0] = c; + dstp += 1; + len -= 1; + } + + return dstpp; +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/Makefile linux.19rc3-ac4/arch/parisc/Makefile --- linux.19rc3/arch/parisc/Makefile 2002-07-29 12:50:07.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/Makefile 2002-07-29 13:58:35.000000000 +0100 @@ -17,12 +17,28 @@ # Mike Shaver, Helge Deller and Martin K. Petersen # +ifdef CONFIG_PARISC64 +LINKFLAGS =-T $(TOPDIR)/arch/parisc/vmlinux64.lds $(LDFLAGS) +CROSS_COMPILE := hppa64-linux- +UTS_MACHINE := parisc64 +#CFLAGS += -b hppa64-linux + +else +LINKFLAGS =-T $(TOPDIR)/arch/parisc/vmlinux.lds $(LDFLAGS) +MACHINE := $(subst 64,,$(shell uname -m)) +ifneq (${MACHINE},parisc) +# cross compilation +CROSS_COMPILE := hppa-linux- +endif +endif + +OFFSET_H := $(TOPDIR)/include/asm-parisc/offset.h FINAL_LD=$(CROSS_COMPILE)ld --warn-common --warn-section-align CPP=$(CC) -E OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S LDFLAGS = -LINKFLAGS =-T $(TOPDIR)/arch/parisc/vmlinux.lds $(LDFLAGS) + CFLAGS_PIPE := -pipe CFLAGS_NSR := -fno-strength-reduce @@ -32,25 +48,48 @@ # enable them by default. CFLAGS += -mno-space-regs -mfast-indirect-calls -# If we become able to compile for specific platforms, this should be -# conditional on that. -CFLAGS += -mschedule=7200 - # No fixed-point multiply CFLAGS += -mdisable-fpregs -HEAD = arch/parisc/kernel/head.o +# Without this, "ld -r" results in .text sections that are too big +# (> 0x40000) for branches to reach stubs. +CFLAGS += -ffunction-sections + +# select which processor to optimise for +ifdef CONFIG_PA7100 +CFLAGS += -march=1.1 -mschedule=7100 +endif + +ifdef CONFIG_PA7200 +CFLAGS += -march=1.1 -mschedule=7200 +endif + +ifdef CONFIG_PA7100LC +CFLAGS += -march=1.1 -mschedule=7100LC +endif + +ifdef CONFIG_PA8X00 +CFLAGS += -march=2.0 -mschedule=8000 +endif + +ASFLAGS := -D__ASSEMBLY__ -traditional + +HEAD := arch/parisc/kernel/head.o SUBDIRS := $(SUBDIRS) $(addprefix arch/parisc/, tools kernel mm lib hpux) CORE_FILES := $(addprefix arch/parisc/, kernel/pdc_cons.o kernel/process.o \ lib/lib.a mm/mm.o kernel/kernel.o hpux/hpux.o) \ $(CORE_FILES) arch/parisc/kernel/init_task.o +CLEAN_FILES := $(CLEAN_FILES) arch/parisc/tools/offset.[hs] + +ifdef CONFIG_PARISC64 +HEAD := arch/parisc/kernel/head64.o +endif + LIBS := `$(CC) -print-libgcc-file-name` $(TOPDIR)/arch/parisc/lib/lib.a $(LIBS) -ifdef CONFIG_MATH_EMULATION SUBDIRS := $(SUBDIRS) arch/parisc/math-emu -DRIVERS := $(DRIVERS) arch/parisc/math-emu/math.a -endif +DRIVERS := $(DRIVERS) arch/parisc/math-emu/math.o ifdef CONFIG_KWDB SUBDIRS := $(SUBDIRS) arch/parisc/kdb @@ -67,7 +106,7 @@ $(MAKE) linuxsubdirs SUBDIRS=arch/parisc/mm palo: vmlinux - export TOPDIR=`pwd`; export CONFIG_STI_CONSOLE=$(CONFIG_STI_CONSOLE); \ + export TOPDIR=`pwd`; \ unset STRIP LDFLAGS CPP CPPFLAGS AFLAGS CFLAGS CC LD; cd ../palo && make lifimage Image: palo @@ -84,8 +123,14 @@ install: +archmrproper: + rm -f $(OFFSET_H) + archclean: -archmrproper: +archdep: $(OFFSET_H) + +$(OFFSET_H): include/linux/version.h + $(MAKE) -C $(TOPDIR)/arch/$(ARCH)/tools all -archdep: +.PHONY: $(OFFSET_H) diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/cnv_float.h linux.19rc3-ac4/arch/parisc/math-emu/cnv_float.h --- linux.19rc3/arch/parisc/math-emu/cnv_float.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/cnv_float.h 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,377 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifdef __NO_PA_HDRS + PA header file -- do not include this header file for non-PA builds. +#endif + +/* + * Some more constants + */ +#define SGL_FX_MAX_EXP 30 +#define DBL_FX_MAX_EXP 62 +#define QUAD_FX_MAX_EXP 126 + +#define Dintp1(object) (object) +#define Dintp2(object) (object) + +#define Duintp1(object) (object) +#define Duintp2(object) (object) + +#define Qintp0(object) (object) +#define Qintp1(object) (object) +#define Qintp2(object) (object) +#define Qintp3(object) (object) + + +/* + * These macros will be used specifically by the convert instructions. + * + * + * Single format macros + */ + +#define Sgl_to_dbl_exponent(src_exponent,dest) \ + Deposit_dexponent(dest,src_exponent+(DBL_BIAS-SGL_BIAS)) + +#define Sgl_to_dbl_mantissa(src_mantissa,destA,destB) \ + Deposit_dmantissap1(destA,src_mantissa>>3); \ + Dmantissap2(destB) = src_mantissa << 29 + +#define Sgl_isinexact_to_fix(sgl_value,exponent) \ + ((exponent < (SGL_P - 1)) ? \ + (Sall(sgl_value) << (SGL_EXP_LENGTH + 1 + exponent)) : FALSE) + +#define Int_isinexact_to_sgl(int_value) (int_value << 33 - SGL_EXP_LENGTH) + +#define Sgl_roundnearest_from_int(int_value,sgl_value) \ + if (int_value & 1<<(SGL_EXP_LENGTH - 2)) /* round bit */ \ + if ((int_value << 34 - SGL_EXP_LENGTH) || Slow(sgl_value)) \ + Sall(sgl_value)++ + +#define Dint_isinexact_to_sgl(dint_valueA,dint_valueB) \ + ((Dintp1(dint_valueA) << 33 - SGL_EXP_LENGTH) || Dintp2(dint_valueB)) + +#define Sgl_roundnearest_from_dint(dint_valueA,dint_valueB,sgl_value) \ + if (Dintp1(dint_valueA) & 1<<(SGL_EXP_LENGTH - 2)) \ + if ((Dintp1(dint_valueA) << 34 - SGL_EXP_LENGTH) || \ + Dintp2(dint_valueB) || Slow(sgl_value)) Sall(sgl_value)++ + +#define Dint_isinexact_to_dbl(dint_value) \ + (Dintp2(dint_value) << 33 - DBL_EXP_LENGTH) + +#define Dbl_roundnearest_from_dint(dint_opndB,dbl_opndA,dbl_opndB) \ + if (Dintp2(dint_opndB) & 1<<(DBL_EXP_LENGTH - 2)) \ + if ((Dintp2(dint_opndB) << 34 - DBL_EXP_LENGTH) || Dlowp2(dbl_opndB)) \ + if ((++Dallp2(dbl_opndB))==0) Dallp1(dbl_opndA)++ + +#define Sgl_isone_roundbit(sgl_value,exponent) \ + ((Sall(sgl_value) << (SGL_EXP_LENGTH + 1 + exponent)) >> 31) + +#define Sgl_isone_stickybit(sgl_value,exponent) \ + (exponent < (SGL_P - 2) ? \ + Sall(sgl_value) << (SGL_EXP_LENGTH + 2 + exponent) : FALSE) + + +/* + * Double format macros + */ + +#define Dbl_to_sgl_exponent(src_exponent,dest) \ + dest = src_exponent + (SGL_BIAS - DBL_BIAS) + +#define Dbl_to_sgl_mantissa(srcA,srcB,dest,inexact,guard,sticky,odd) \ + Shiftdouble(Dmantissap1(srcA),Dmantissap2(srcB),29,dest); \ + guard = Dbit3p2(srcB); \ + sticky = Dallp2(srcB)<<4; \ + inexact = guard | sticky; \ + odd = Dbit2p2(srcB) + +#define Dbl_to_sgl_denormalized(srcA,srcB,exp,dest,inexact,guard,sticky,odd,tiny) \ + Deposit_dexponent(srcA,1); \ + tiny = TRUE; \ + if (exp >= -2) { \ + if (exp == 0) { \ + inexact = Dallp2(srcB) << 3; \ + guard = inexact >> 31; \ + sticky = inexact << 1; \ + Shiftdouble(Dmantissap1(srcA),Dmantissap2(srcB),29,dest); \ + odd = dest << 31; \ + if (inexact) { \ + switch(Rounding_mode()) { \ + case ROUNDPLUS: \ + if (Dbl_iszero_sign(srcA)) { \ + dest++; \ + if (Sgl_isone_hidden(dest)) \ + tiny = FALSE; \ + dest--; \ + } \ + break; \ + case ROUNDMINUS: \ + if (Dbl_isone_sign(srcA)) { \ + dest++; \ + if (Sgl_isone_hidden(dest)) \ + tiny = FALSE; \ + dest--; \ + } \ + break; \ + case ROUNDNEAREST: \ + if (guard && (sticky || odd)) { \ + dest++; \ + if (Sgl_isone_hidden(dest)) \ + tiny = FALSE; \ + dest--; \ + } \ + break; \ + } \ + } \ + /* shift right by one to get correct result */ \ + guard = odd; \ + sticky = inexact; \ + inexact |= guard; \ + dest >>= 1; \ + Deposit_dsign(srcA,0); \ + Shiftdouble(Dallp1(srcA),Dallp2(srcB),30,dest); \ + odd = dest << 31; \ + } \ + else { \ + inexact = Dallp2(srcB) << (2 + exp); \ + guard = inexact >> 31; \ + sticky = inexact << 1; \ + Deposit_dsign(srcA,0); \ + if (exp == -2) dest = Dallp1(srcA); \ + else Variable_shift_double(Dallp1(srcA),Dallp2(srcB),30-exp,dest); \ + odd = dest << 31; \ + } \ + } \ + else { \ + Deposit_dsign(srcA,0); \ + if (exp > (1 - SGL_P)) { \ + dest = Dallp1(srcA) >> (- 2 - exp); \ + inexact = Dallp1(srcA) << (34 + exp); \ + guard = inexact >> 31; \ + sticky = (inexact << 1) | Dallp2(srcB); \ + inexact |= Dallp2(srcB); \ + odd = dest << 31; \ + } \ + else { \ + dest = 0; \ + inexact = Dallp1(srcA) | Dallp2(srcB); \ + if (exp == (1 - SGL_P)) { \ + guard = Dhidden(srcA); \ + sticky = Dmantissap1(srcA) | Dallp2(srcB); \ + } \ + else { \ + guard = 0; \ + sticky = inexact; \ + } \ + odd = 0; \ + } \ + } \ + exp = 0 + +#define Dbl_isinexact_to_fix(dbl_valueA,dbl_valueB,exponent) \ + (exponent < (DBL_P-33) ? \ + Dallp2(dbl_valueB) || Dallp1(dbl_valueA) << (DBL_EXP_LENGTH+1+exponent) : \ + (exponent < (DBL_P-1) ? Dallp2(dbl_valueB) << (exponent + (33-DBL_P)) : \ + FALSE)) + +#define Dbl_isoverflow_to_int(exponent,dbl_valueA,dbl_valueB) \ + ((exponent > SGL_FX_MAX_EXP + 1) || Dsign(dbl_valueA)==0 || \ + Dmantissap1(dbl_valueA)!=0 || (Dallp2(dbl_valueB)>>21)!=0 ) + +#define Dbl_isone_roundbit(dbl_valueA,dbl_valueB,exponent) \ + ((exponent < (DBL_P - 33) ? \ + Dallp1(dbl_valueA) >> ((30 - DBL_EXP_LENGTH) - exponent) : \ + Dallp2(dbl_valueB) >> ((DBL_P - 2) - exponent)) & 1) + +#define Dbl_isone_stickybit(dbl_valueA,dbl_valueB,exponent) \ + (exponent < (DBL_P-34) ? \ + (Dallp2(dbl_valueB) || Dallp1(dbl_valueA)<<(DBL_EXP_LENGTH+2+exponent)) : \ + (exponent<(DBL_P-2) ? (Dallp2(dbl_valueB) << (exponent + (34-DBL_P))) : \ + FALSE)) + + +/* Int macros */ + +#define Int_from_sgl_mantissa(sgl_value,exponent) \ + Sall(sgl_value) = \ + (unsigned)(Sall(sgl_value) << SGL_EXP_LENGTH)>>(31 - exponent) + +#define Int_from_dbl_mantissa(dbl_valueA,dbl_valueB,exponent) \ + Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),22,Dallp1(dbl_valueA)); \ + if (exponent < 31) Dallp1(dbl_valueA) >>= 30 - exponent; \ + else Dallp1(dbl_valueA) <<= 1 + +#define Int_negate(int_value) int_value = -int_value + + +/* Dint macros */ + +#define Dint_from_sgl_mantissa(sgl_value,exponent,dresultA,dresultB) \ + {Sall(sgl_value) <<= SGL_EXP_LENGTH; /* left-justify */ \ + if (exponent <= 31) { \ + Dintp1(dresultA) = 0; \ + Dintp2(dresultB) = (unsigned)Sall(sgl_value) >> (31 - exponent); \ + } \ + else { \ + Dintp1(dresultA) = Sall(sgl_value) >> (63 - exponent); \ + Dintp2(dresultB) = Sall(sgl_value) << (exponent - 31); \ + }} + + +#define Dint_from_dbl_mantissa(dbl_valueA,dbl_valueB,exponent,destA,destB) \ + {if (exponent < 32) { \ + Dintp1(destA) = 0; \ + if (exponent <= 20) \ + Dintp2(destB) = Dallp1(dbl_valueA) >> 20-exponent; \ + else Variable_shift_double(Dallp1(dbl_valueA),Dallp2(dbl_valueB), \ + 52-exponent,Dintp2(destB)); \ + } \ + else { \ + if (exponent <= 52) { \ + Dintp1(destA) = Dallp1(dbl_valueA) >> 52-exponent; \ + if (exponent == 52) Dintp2(destB) = Dallp2(dbl_valueB); \ + else Variable_shift_double(Dallp1(dbl_valueA),Dallp2(dbl_valueB), \ + 52-exponent,Dintp2(destB)); \ + } \ + else { \ + Variable_shift_double(Dallp1(dbl_valueA),Dallp2(dbl_valueB), \ + 84-exponent,Dintp1(destA)); \ + Dintp2(destB) = Dallp2(dbl_valueB) << exponent-52; \ + } \ + }} + +#define Dint_setzero(dresultA,dresultB) \ + Dintp1(dresultA) = 0; \ + Dintp2(dresultB) = 0 + +#define Dint_setone_sign(dresultA,dresultB) \ + Dintp1(dresultA) = ~Dintp1(dresultA); \ + if ((Dintp2(dresultB) = -Dintp2(dresultB)) == 0) Dintp1(dresultA)++ + +#define Dint_set_minint(dresultA,dresultB) \ + Dintp1(dresultA) = (unsigned int)1<<31; \ + Dintp2(dresultB) = 0 + +#define Dint_isone_lowp2(dresultB) (Dintp2(dresultB) & 01) + +#define Dint_increment(dresultA,dresultB) \ + if ((++Dintp2(dresultB))==0) Dintp1(dresultA)++ + +#define Dint_decrement(dresultA,dresultB) \ + if ((Dintp2(dresultB)--)==0) Dintp1(dresultA)-- + +#define Dint_negate(dresultA,dresultB) \ + Dintp1(dresultA) = ~Dintp1(dresultA); \ + if ((Dintp2(dresultB) = -Dintp2(dresultB))==0) Dintp1(dresultA)++ + +#define Dint_copyfromptr(src,destA,destB) \ + Dintp1(destA) = src->wd0; \ + Dintp2(destB) = src->wd1 +#define Dint_copytoptr(srcA,srcB,dest) \ + dest->wd0 = Dintp1(srcA); \ + dest->wd1 = Dintp2(srcB) + + +/* other macros */ + +#define Find_ms_one_bit(value, position) \ + { \ + int var; \ + for (var=8; var >=1; var >>= 1) { \ + if (value >> 32 - position) \ + position -= var; \ + else position += var; \ + } \ + if ((value >> 32 - position) == 0) \ + position--; \ + else position -= 2; \ + } + + +/* + * Unsigned int macros + */ +#define Duint_copyfromptr(src,destA,destB) \ + Dint_copyfromptr(src,destA,destB) +#define Duint_copytoptr(srcA,srcB,dest) \ + Dint_copytoptr(srcA,srcB,dest) + +#define Suint_isinexact_to_sgl(int_value) \ + (int_value << 32 - SGL_EXP_LENGTH) + +#define Sgl_roundnearest_from_suint(suint_value,sgl_value) \ + if (suint_value & 1<<(SGL_EXP_LENGTH - 1)) /* round bit */ \ + if ((suint_value << 33 - SGL_EXP_LENGTH) || Slow(sgl_value)) \ + Sall(sgl_value)++ + +#define Duint_isinexact_to_sgl(duint_valueA,duint_valueB) \ + ((Duintp1(duint_valueA) << 32 - SGL_EXP_LENGTH) || Duintp2(duint_valueB)) + +#define Sgl_roundnearest_from_duint(duint_valueA,duint_valueB,sgl_value) \ + if (Duintp1(duint_valueA) & 1<<(SGL_EXP_LENGTH - 1)) \ + if ((Duintp1(duint_valueA) << 33 - SGL_EXP_LENGTH) || \ + Duintp2(duint_valueB) || Slow(sgl_value)) Sall(sgl_value)++ + +#define Duint_isinexact_to_dbl(duint_value) \ + (Duintp2(duint_value) << 32 - DBL_EXP_LENGTH) + +#define Dbl_roundnearest_from_duint(duint_opndB,dbl_opndA,dbl_opndB) \ + if (Duintp2(duint_opndB) & 1<<(DBL_EXP_LENGTH - 1)) \ + if ((Duintp2(duint_opndB) << 33 - DBL_EXP_LENGTH) || Dlowp2(dbl_opndB)) \ + if ((++Dallp2(dbl_opndB))==0) Dallp1(dbl_opndA)++ + +#define Suint_from_sgl_mantissa(src,exponent,result) \ + Sall(result) = (unsigned)(Sall(src) << SGL_EXP_LENGTH)>>(31 - exponent) + +#define Sgl_isinexact_to_unsigned(sgl_value,exponent) \ + Sgl_isinexact_to_fix(sgl_value,exponent) + +#define Duint_from_sgl_mantissa(sgl_value,exponent,dresultA,dresultB) \ + {Sall(sgl_value) <<= SGL_EXP_LENGTH; /* left-justify */ \ + if (exponent <= 31) { \ + Dintp1(dresultA) = 0; \ + Dintp2(dresultB) = (unsigned)Sall(sgl_value) >> (31 - exponent); \ + } \ + else { \ + Dintp1(dresultA) = Sall(sgl_value) >> (63 - exponent); \ + Dintp2(dresultB) = Sall(sgl_value) << (exponent - 31); \ + } \ + Sall(sgl_value) >>= SGL_EXP_LENGTH; /* return to original */ \ + } + +#define Duint_setzero(dresultA,dresultB) \ + Dint_setzero(dresultA,dresultB) + +#define Duint_increment(dresultA,dresultB) Dint_increment(dresultA,dresultB) + +#define Duint_isone_lowp2(dresultB) Dint_isone_lowp2(dresultB) + +#define Suint_from_dbl_mantissa(srcA,srcB,exponent,dest) \ + Shiftdouble(Dallp1(srcA),Dallp2(srcB),21,dest); \ + dest = (unsigned)dest >> 31 - exponent + +#define Dbl_isinexact_to_unsigned(dbl_valueA,dbl_valueB,exponent) \ + Dbl_isinexact_to_fix(dbl_valueA,dbl_valueB,exponent) + +#define Duint_from_dbl_mantissa(dbl_valueA,dbl_valueB,exponent,destA,destB) \ + Dint_from_dbl_mantissa(dbl_valueA,dbl_valueB,exponent,destA,destB) diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/dbl_float.h linux.19rc3-ac4/arch/parisc/math-emu/dbl_float.h --- linux.19rc3/arch/parisc/math-emu/dbl_float.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/dbl_float.h 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,847 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifdef __NO_PA_HDRS + PA header file -- do not include this header file for non-PA builds. +#endif + +/* 32-bit word grabing functions */ +#define Dbl_firstword(value) Dallp1(value) +#define Dbl_secondword(value) Dallp2(value) +#define Dbl_thirdword(value) dummy_location +#define Dbl_fourthword(value) dummy_location + +#define Dbl_sign(object) Dsign(object) +#define Dbl_exponent(object) Dexponent(object) +#define Dbl_signexponent(object) Dsignexponent(object) +#define Dbl_mantissap1(object) Dmantissap1(object) +#define Dbl_mantissap2(object) Dmantissap2(object) +#define Dbl_exponentmantissap1(object) Dexponentmantissap1(object) +#define Dbl_allp1(object) Dallp1(object) +#define Dbl_allp2(object) Dallp2(object) + +/* dbl_and_signs ands the sign bits of each argument and puts the result + * into the first argument. dbl_or_signs ors those same sign bits */ +#define Dbl_and_signs( src1dst, src2) \ + Dallp1(src1dst) = (Dallp1(src2)|~((unsigned int)1<<31)) & Dallp1(src1dst) +#define Dbl_or_signs( src1dst, src2) \ + Dallp1(src1dst) = (Dallp1(src2)&((unsigned int)1<<31)) | Dallp1(src1dst) + +/* The hidden bit is always the low bit of the exponent */ +#define Dbl_clear_exponent_set_hidden(srcdst) Deposit_dexponent(srcdst,1) +#define Dbl_clear_signexponent_set_hidden(srcdst) \ + Deposit_dsignexponent(srcdst,1) +#define Dbl_clear_sign(srcdst) Dallp1(srcdst) &= ~((unsigned int)1<<31) +#define Dbl_clear_signexponent(srcdst) \ + Dallp1(srcdst) &= Dmantissap1((unsigned int)-1) + +/* Exponent field for doubles has already been cleared and may be + * included in the shift. Here we need to generate two double width + * variable shifts. The insignificant bits can be ignored. + * MTSAR f(varamount) + * VSHD srcdst.high,srcdst.low => srcdst.low + * VSHD 0,srcdst.high => srcdst.high + * This is very difficult to model with C expressions since the shift amount + * could exceed 32. */ +/* varamount must be less than 64 */ +#define Dbl_rightshift(srcdstA, srcdstB, varamount) \ + {if((varamount) >= 32) { \ + Dallp2(srcdstB) = Dallp1(srcdstA) >> (varamount-32); \ + Dallp1(srcdstA)=0; \ + } \ + else if(varamount > 0) { \ + Variable_shift_double(Dallp1(srcdstA), Dallp2(srcdstB), \ + (varamount), Dallp2(srcdstB)); \ + Dallp1(srcdstA) >>= varamount; \ + } } +/* varamount must be less than 64 */ +#define Dbl_rightshift_exponentmantissa(srcdstA, srcdstB, varamount) \ + {if((varamount) >= 32) { \ + Dallp2(srcdstB) = Dexponentmantissap1(srcdstA) >> (varamount-32); \ + Dallp1(srcdstA) &= ((unsigned int)1<<31); /* clear expmant field */ \ + } \ + else if(varamount > 0) { \ + Variable_shift_double(Dexponentmantissap1(srcdstA), Dallp2(srcdstB), \ + (varamount), Dallp2(srcdstB)); \ + Deposit_dexponentmantissap1(srcdstA, \ + (Dexponentmantissap1(srcdstA)>>varamount)); \ + } } +/* varamount must be less than 64 */ +#define Dbl_leftshift(srcdstA, srcdstB, varamount) \ + {if((varamount) >= 32) { \ + Dallp1(srcdstA) = Dallp2(srcdstB) << (varamount-32); \ + Dallp2(srcdstB)=0; \ + } \ + else { \ + if ((varamount) > 0) { \ + Dallp1(srcdstA) = (Dallp1(srcdstA) << (varamount)) | \ + (Dallp2(srcdstB) >> (32-(varamount))); \ + Dallp2(srcdstB) <<= varamount; \ + } \ + } } +#define Dbl_leftshiftby1_withextent(lefta,leftb,right,resulta,resultb) \ + Shiftdouble(Dallp1(lefta), Dallp2(leftb), 31, Dallp1(resulta)); \ + Shiftdouble(Dallp2(leftb), Extall(right), 31, Dallp2(resultb)) + +#define Dbl_rightshiftby1_withextent(leftb,right,dst) \ + Extall(dst) = (Dallp2(leftb) << 31) | ((unsigned int)Extall(right) >> 1) | \ + Extlow(right) + +#define Dbl_arithrightshiftby1(srcdstA,srcdstB) \ + Shiftdouble(Dallp1(srcdstA),Dallp2(srcdstB),1,Dallp2(srcdstB));\ + Dallp1(srcdstA) = (int)Dallp1(srcdstA) >> 1 + +/* Sign extend the sign bit with an integer destination */ +#define Dbl_signextendedsign(value) Dsignedsign(value) + +#define Dbl_isone_hidden(dbl_value) (Is_dhidden(dbl_value)!=0) +/* Singles and doubles may include the sign and exponent fields. The + * hidden bit and the hidden overflow must be included. */ +#define Dbl_increment(dbl_valueA,dbl_valueB) \ + if( (Dallp2(dbl_valueB) += 1) == 0 ) Dallp1(dbl_valueA) += 1 +#define Dbl_increment_mantissa(dbl_valueA,dbl_valueB) \ + if( (Dmantissap2(dbl_valueB) += 1) == 0 ) \ + Deposit_dmantissap1(dbl_valueA,dbl_valueA+1) +#define Dbl_decrement(dbl_valueA,dbl_valueB) \ + if( Dallp2(dbl_valueB) == 0 ) Dallp1(dbl_valueA) -= 1; \ + Dallp2(dbl_valueB) -= 1 + +#define Dbl_isone_sign(dbl_value) (Is_dsign(dbl_value)!=0) +#define Dbl_isone_hiddenoverflow(dbl_value) (Is_dhiddenoverflow(dbl_value)!=0) +#define Dbl_isone_lowmantissap1(dbl_valueA) (Is_dlowp1(dbl_valueA)!=0) +#define Dbl_isone_lowmantissap2(dbl_valueB) (Is_dlowp2(dbl_valueB)!=0) +#define Dbl_isone_signaling(dbl_value) (Is_dsignaling(dbl_value)!=0) +#define Dbl_is_signalingnan(dbl_value) (Dsignalingnan(dbl_value)==0xfff) +#define Dbl_isnotzero(dbl_valueA,dbl_valueB) \ + (Dallp1(dbl_valueA) || Dallp2(dbl_valueB)) +#define Dbl_isnotzero_hiddenhigh7mantissa(dbl_value) \ + (Dhiddenhigh7mantissa(dbl_value)!=0) +#define Dbl_isnotzero_exponent(dbl_value) (Dexponent(dbl_value)!=0) +#define Dbl_isnotzero_mantissa(dbl_valueA,dbl_valueB) \ + (Dmantissap1(dbl_valueA) || Dmantissap2(dbl_valueB)) +#define Dbl_isnotzero_mantissap1(dbl_valueA) (Dmantissap1(dbl_valueA)!=0) +#define Dbl_isnotzero_mantissap2(dbl_valueB) (Dmantissap2(dbl_valueB)!=0) +#define Dbl_isnotzero_exponentmantissa(dbl_valueA,dbl_valueB) \ + (Dexponentmantissap1(dbl_valueA) || Dmantissap2(dbl_valueB)) +#define Dbl_isnotzero_low4p2(dbl_value) (Dlow4p2(dbl_value)!=0) +#define Dbl_iszero(dbl_valueA,dbl_valueB) (Dallp1(dbl_valueA)==0 && \ + Dallp2(dbl_valueB)==0) +#define Dbl_iszero_allp1(dbl_value) (Dallp1(dbl_value)==0) +#define Dbl_iszero_allp2(dbl_value) (Dallp2(dbl_value)==0) +#define Dbl_iszero_hidden(dbl_value) (Is_dhidden(dbl_value)==0) +#define Dbl_iszero_hiddenoverflow(dbl_value) (Is_dhiddenoverflow(dbl_value)==0) +#define Dbl_iszero_hiddenhigh3mantissa(dbl_value) \ + (Dhiddenhigh3mantissa(dbl_value)==0) +#define Dbl_iszero_hiddenhigh7mantissa(dbl_value) \ + (Dhiddenhigh7mantissa(dbl_value)==0) +#define Dbl_iszero_sign(dbl_value) (Is_dsign(dbl_value)==0) +#define Dbl_iszero_exponent(dbl_value) (Dexponent(dbl_value)==0) +#define Dbl_iszero_mantissa(dbl_valueA,dbl_valueB) \ + (Dmantissap1(dbl_valueA)==0 && Dmantissap2(dbl_valueB)==0) +#define Dbl_iszero_exponentmantissa(dbl_valueA,dbl_valueB) \ + (Dexponentmantissap1(dbl_valueA)==0 && Dmantissap2(dbl_valueB)==0) +#define Dbl_isinfinity_exponent(dbl_value) \ + (Dexponent(dbl_value)==DBL_INFINITY_EXPONENT) +#define Dbl_isnotinfinity_exponent(dbl_value) \ + (Dexponent(dbl_value)!=DBL_INFINITY_EXPONENT) +#define Dbl_isinfinity(dbl_valueA,dbl_valueB) \ + (Dexponent(dbl_valueA)==DBL_INFINITY_EXPONENT && \ + Dmantissap1(dbl_valueA)==0 && Dmantissap2(dbl_valueB)==0) +#define Dbl_isnan(dbl_valueA,dbl_valueB) \ + (Dexponent(dbl_valueA)==DBL_INFINITY_EXPONENT && \ + (Dmantissap1(dbl_valueA)!=0 || Dmantissap2(dbl_valueB)!=0)) +#define Dbl_isnotnan(dbl_valueA,dbl_valueB) \ + (Dexponent(dbl_valueA)!=DBL_INFINITY_EXPONENT || \ + (Dmantissap1(dbl_valueA)==0 && Dmantissap2(dbl_valueB)==0)) + +#define Dbl_islessthan(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b) \ + (Dallp1(dbl_op1a) < Dallp1(dbl_op2a) || \ + (Dallp1(dbl_op1a) == Dallp1(dbl_op2a) && \ + Dallp2(dbl_op1b) < Dallp2(dbl_op2b))) +#define Dbl_isgreaterthan(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b) \ + (Dallp1(dbl_op1a) > Dallp1(dbl_op2a) || \ + (Dallp1(dbl_op1a) == Dallp1(dbl_op2a) && \ + Dallp2(dbl_op1b) > Dallp2(dbl_op2b))) +#define Dbl_isnotlessthan(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b) \ + (Dallp1(dbl_op1a) > Dallp1(dbl_op2a) || \ + (Dallp1(dbl_op1a) == Dallp1(dbl_op2a) && \ + Dallp2(dbl_op1b) >= Dallp2(dbl_op2b))) +#define Dbl_isnotgreaterthan(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b) \ + (Dallp1(dbl_op1a) < Dallp1(dbl_op2a) || \ + (Dallp1(dbl_op1a) == Dallp1(dbl_op2a) && \ + Dallp2(dbl_op1b) <= Dallp2(dbl_op2b))) +#define Dbl_isequal(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b) \ + ((Dallp1(dbl_op1a) == Dallp1(dbl_op2a)) && \ + (Dallp2(dbl_op1b) == Dallp2(dbl_op2b))) + +#define Dbl_leftshiftby8(dbl_valueA,dbl_valueB) \ + Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),24,Dallp1(dbl_valueA)); \ + Dallp2(dbl_valueB) <<= 8 +#define Dbl_leftshiftby7(dbl_valueA,dbl_valueB) \ + Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),25,Dallp1(dbl_valueA)); \ + Dallp2(dbl_valueB) <<= 7 +#define Dbl_leftshiftby4(dbl_valueA,dbl_valueB) \ + Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),28,Dallp1(dbl_valueA)); \ + Dallp2(dbl_valueB) <<= 4 +#define Dbl_leftshiftby3(dbl_valueA,dbl_valueB) \ + Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),29,Dallp1(dbl_valueA)); \ + Dallp2(dbl_valueB) <<= 3 +#define Dbl_leftshiftby2(dbl_valueA,dbl_valueB) \ + Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),30,Dallp1(dbl_valueA)); \ + Dallp2(dbl_valueB) <<= 2 +#define Dbl_leftshiftby1(dbl_valueA,dbl_valueB) \ + Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),31,Dallp1(dbl_valueA)); \ + Dallp2(dbl_valueB) <<= 1 + +#define Dbl_rightshiftby8(dbl_valueA,dbl_valueB) \ + Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),8,Dallp2(dbl_valueB)); \ + Dallp1(dbl_valueA) >>= 8 +#define Dbl_rightshiftby4(dbl_valueA,dbl_valueB) \ + Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),4,Dallp2(dbl_valueB)); \ + Dallp1(dbl_valueA) >>= 4 +#define Dbl_rightshiftby2(dbl_valueA,dbl_valueB) \ + Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),2,Dallp2(dbl_valueB)); \ + Dallp1(dbl_valueA) >>= 2 +#define Dbl_rightshiftby1(dbl_valueA,dbl_valueB) \ + Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),1,Dallp2(dbl_valueB)); \ + Dallp1(dbl_valueA) >>= 1 + +/* This magnitude comparison uses the signless first words and + * the regular part2 words. The comparison is graphically: + * + * 1st greater? ------------- + * | + * 1st less?-----------------+--------- + * | | + * 2nd greater or equal----->| | + * False True + */ +#define Dbl_ismagnitudeless(leftB,rightB,signlessleft,signlessright) \ + ((signlessleft <= signlessright) && \ + ( (signlessleft < signlessright) || (Dallp2(leftB)wd0; \ + Dallp2(destb) = src->wd1 +#define Dbl_copytoptr(srca,srcb,dest) \ + dest->wd0 = Dallp1(srca); \ + dest->wd1 = Dallp2(srcb) + +/* An infinity is represented with the max exponent and a zero mantissa */ +#define Dbl_setinfinity_exponent(dbl_value) \ + Deposit_dexponent(dbl_value,DBL_INFINITY_EXPONENT) +#define Dbl_setinfinity_exponentmantissa(dbl_valueA,dbl_valueB) \ + Deposit_dexponentmantissap1(dbl_valueA, \ + (DBL_INFINITY_EXPONENT << (32-(1+DBL_EXP_LENGTH)))); \ + Dmantissap2(dbl_valueB) = 0 +#define Dbl_setinfinitypositive(dbl_valueA,dbl_valueB) \ + Dallp1(dbl_valueA) \ + = (DBL_INFINITY_EXPONENT << (32-(1+DBL_EXP_LENGTH))); \ + Dmantissap2(dbl_valueB) = 0 +#define Dbl_setinfinitynegative(dbl_valueA,dbl_valueB) \ + Dallp1(dbl_valueA) = ((unsigned int)1<<31) | \ + (DBL_INFINITY_EXPONENT << (32-(1+DBL_EXP_LENGTH))); \ + Dmantissap2(dbl_valueB) = 0 +#define Dbl_setinfinity(dbl_valueA,dbl_valueB,sign) \ + Dallp1(dbl_valueA) = ((unsigned int)sign << 31) | \ + (DBL_INFINITY_EXPONENT << (32-(1+DBL_EXP_LENGTH))); \ + Dmantissap2(dbl_valueB) = 0 + +#define Dbl_sethigh4bits(dbl_value, extsign) Deposit_dhigh4p1(dbl_value,extsign) +#define Dbl_set_sign(dbl_value,sign) Deposit_dsign(dbl_value,sign) +#define Dbl_invert_sign(dbl_value) Deposit_dsign(dbl_value,~Dsign(dbl_value)) +#define Dbl_setone_sign(dbl_value) Deposit_dsign(dbl_value,1) +#define Dbl_setone_lowmantissap2(dbl_value) Deposit_dlowp2(dbl_value,1) +#define Dbl_setzero_sign(dbl_value) Dallp1(dbl_value) &= 0x7fffffff +#define Dbl_setzero_exponent(dbl_value) \ + Dallp1(dbl_value) &= 0x800fffff +#define Dbl_setzero_mantissa(dbl_valueA,dbl_valueB) \ + Dallp1(dbl_valueA) &= 0xfff00000; \ + Dallp2(dbl_valueB) = 0 +#define Dbl_setzero_mantissap1(dbl_value) Dallp1(dbl_value) &= 0xfff00000 +#define Dbl_setzero_mantissap2(dbl_value) Dallp2(dbl_value) = 0 +#define Dbl_setzero_exponentmantissa(dbl_valueA,dbl_valueB) \ + Dallp1(dbl_valueA) &= 0x80000000; \ + Dallp2(dbl_valueB) = 0 +#define Dbl_setzero_exponentmantissap1(dbl_valueA) \ + Dallp1(dbl_valueA) &= 0x80000000 +#define Dbl_setzero(dbl_valueA,dbl_valueB) \ + Dallp1(dbl_valueA) = 0; Dallp2(dbl_valueB) = 0 +#define Dbl_setzerop1(dbl_value) Dallp1(dbl_value) = 0 +#define Dbl_setzerop2(dbl_value) Dallp2(dbl_value) = 0 +#define Dbl_setnegativezero(dbl_value) \ + Dallp1(dbl_value) = (unsigned int)1 << 31; Dallp2(dbl_value) = 0 +#define Dbl_setnegativezerop1(dbl_value) Dallp1(dbl_value) = (unsigned int)1<<31 + +/* Use the following macro for both overflow & underflow conditions */ +#define ovfl - +#define unfl + +#define Dbl_setwrapped_exponent(dbl_value,exponent,op) \ + Deposit_dexponent(dbl_value,(exponent op DBL_WRAP)) + +#define Dbl_setlargestpositive(dbl_valueA,dbl_valueB) \ + Dallp1(dbl_valueA) = ((DBL_EMAX+DBL_BIAS) << (32-(1+DBL_EXP_LENGTH))) \ + | ((1<<(32-(1+DBL_EXP_LENGTH))) - 1 ); \ + Dallp2(dbl_valueB) = 0xFFFFFFFF +#define Dbl_setlargestnegative(dbl_valueA,dbl_valueB) \ + Dallp1(dbl_valueA) = ((DBL_EMAX+DBL_BIAS) << (32-(1+DBL_EXP_LENGTH))) \ + | ((1<<(32-(1+DBL_EXP_LENGTH))) - 1 ) \ + | ((unsigned int)1<<31); \ + Dallp2(dbl_valueB) = 0xFFFFFFFF +#define Dbl_setlargest_exponentmantissa(dbl_valueA,dbl_valueB) \ + Deposit_dexponentmantissap1(dbl_valueA, \ + (((DBL_EMAX+DBL_BIAS) << (32-(1+DBL_EXP_LENGTH))) \ + | ((1<<(32-(1+DBL_EXP_LENGTH))) - 1 ))); \ + Dallp2(dbl_valueB) = 0xFFFFFFFF + +#define Dbl_setnegativeinfinity(dbl_valueA,dbl_valueB) \ + Dallp1(dbl_valueA) = ((1<= 32 ) \ + { \ + /* Big shift requires examining the portion shift off \ + the end to properly set inexact. */ \ + if(shift < 64) \ + { \ + if(shift > 32) \ + { \ + Variable_shift_double(Dallp1(srcdstA),Dallp2(srcdstB), \ + shift-32, Extall(extent)); \ + if(Dallp2(srcdstB) << 64 - (shift)) Ext_setone_low(extent); \ + } \ + else Extall(extent) = Dallp2(srcdstB); \ + Dallp2(srcdstB) = Dallp1(srcdstA) >> (shift - 32); \ + } \ + else \ + { \ + Extall(extent) = Dallp1(srcdstA); \ + if(Dallp2(srcdstB)) Ext_setone_low(extent); \ + Dallp2(srcdstB) = 0; \ + } \ + Dallp1(srcdstA) = 0; \ + } \ + else \ + { \ + /* Small alignment is simpler. Extension is easily set. */ \ + if (shift > 0) \ + { \ + Extall(extent) = Dallp2(srcdstB) << 32 - (shift); \ + Variable_shift_double(Dallp1(srcdstA),Dallp2(srcdstB),shift, \ + Dallp2(srcdstB)); \ + Dallp1(srcdstA) >>= shift; \ + } \ + else Extall(extent) = 0; \ + } + +/* + * Here we need to shift the result right to correct for an overshift + * (due to the exponent becoming negative) during normalization. + */ +#define Dbl_fix_overshift(srcdstA,srcdstB,shift,extent) \ + Extall(extent) = Dallp2(srcdstB) << 32 - (shift); \ + Dallp2(srcdstB) = (Dallp1(srcdstA) << 32 - (shift)) | \ + (Dallp2(srcdstB) >> (shift)); \ + Dallp1(srcdstA) = Dallp1(srcdstA) >> shift + +#define Dbl_hiddenhigh3mantissa(dbl_value) Dhiddenhigh3mantissa(dbl_value) +#define Dbl_hidden(dbl_value) Dhidden(dbl_value) +#define Dbl_lowmantissap2(dbl_value) Dlowp2(dbl_value) + +/* The left argument is never smaller than the right argument */ +#define Dbl_subtract(lefta,leftb,righta,rightb,resulta,resultb) \ + if( Dallp2(rightb) > Dallp2(leftb) ) Dallp1(lefta)--; \ + Dallp2(resultb) = Dallp2(leftb) - Dallp2(rightb); \ + Dallp1(resulta) = Dallp1(lefta) - Dallp1(righta) + +/* Subtract right augmented with extension from left augmented with zeros and + * store into result and extension. */ +#define Dbl_subtract_withextension(lefta,leftb,righta,rightb,extent,resulta,resultb) \ + Dbl_subtract(lefta,leftb,righta,rightb,resulta,resultb); \ + if( (Extall(extent) = 0-Extall(extent)) ) \ + { \ + if((Dallp2(resultb)--) == 0) Dallp1(resulta)--; \ + } + +#define Dbl_addition(lefta,leftb,righta,rightb,resulta,resultb) \ + /* If the sum of the low words is less than either source, then \ + * an overflow into the next word occurred. */ \ + Dallp1(resulta) = Dallp1(lefta) + Dallp1(righta); \ + if((Dallp2(resultb) = Dallp2(leftb) + Dallp2(rightb)) < Dallp2(rightb)) \ + Dallp1(resulta)++ + +#define Dbl_xortointp1(left,right,result) \ + result = Dallp1(left) XOR Dallp1(right) + +#define Dbl_xorfromintp1(left,right,result) \ + Dallp1(result) = left XOR Dallp1(right) + +#define Dbl_swap_lower(left,right) \ + Dallp2(left) = Dallp2(left) XOR Dallp2(right); \ + Dallp2(right) = Dallp2(left) XOR Dallp2(right); \ + Dallp2(left) = Dallp2(left) XOR Dallp2(right) + +/* Need to Initialize */ +#define Dbl_makequietnan(desta,destb) \ + Dallp1(desta) = ((DBL_EMAX+DBL_BIAS)+1)<< (32-(1+DBL_EXP_LENGTH)) \ + | (1<<(32-(1+DBL_EXP_LENGTH+2))); \ + Dallp2(destb) = 0 +#define Dbl_makesignalingnan(desta,destb) \ + Dallp1(desta) = ((DBL_EMAX+DBL_BIAS)+1)<< (32-(1+DBL_EXP_LENGTH)) \ + | (1<<(32-(1+DBL_EXP_LENGTH+1))); \ + Dallp2(destb) = 0 + +#define Dbl_normalize(dbl_opndA,dbl_opndB,exponent) \ + while(Dbl_iszero_hiddenhigh7mantissa(dbl_opndA)) { \ + Dbl_leftshiftby8(dbl_opndA,dbl_opndB); \ + exponent -= 8; \ + } \ + if(Dbl_iszero_hiddenhigh3mantissa(dbl_opndA)) { \ + Dbl_leftshiftby4(dbl_opndA,dbl_opndB); \ + exponent -= 4; \ + } \ + while(Dbl_iszero_hidden(dbl_opndA)) { \ + Dbl_leftshiftby1(dbl_opndA,dbl_opndB); \ + exponent -= 1; \ + } + +#define Twoword_add(src1dstA,src1dstB,src2A,src2B) \ + /* \ + * want this macro to generate: \ + * ADD src1dstB,src2B,src1dstB; \ + * ADDC src1dstA,src2A,src1dstA; \ + */ \ + if ((src1dstB) + (src2B) < (src1dstB)) Dallp1(src1dstA)++; \ + Dallp1(src1dstA) += (src2A); \ + Dallp2(src1dstB) += (src2B) + +#define Twoword_subtract(src1dstA,src1dstB,src2A,src2B) \ + /* \ + * want this macro to generate: \ + * SUB src1dstB,src2B,src1dstB; \ + * SUBB src1dstA,src2A,src1dstA; \ + */ \ + if ((src1dstB) < (src2B)) Dallp1(src1dstA)--; \ + Dallp1(src1dstA) -= (src2A); \ + Dallp2(src1dstB) -= (src2B) + +#define Dbl_setoverflow(resultA,resultB) \ + /* set result to infinity or largest number */ \ + switch (Rounding_mode()) { \ + case ROUNDPLUS: \ + if (Dbl_isone_sign(resultA)) { \ + Dbl_setlargestnegative(resultA,resultB); \ + } \ + else { \ + Dbl_setinfinitypositive(resultA,resultB); \ + } \ + break; \ + case ROUNDMINUS: \ + if (Dbl_iszero_sign(resultA)) { \ + Dbl_setlargestpositive(resultA,resultB); \ + } \ + else { \ + Dbl_setinfinitynegative(resultA,resultB); \ + } \ + break; \ + case ROUNDNEAREST: \ + Dbl_setinfinity_exponentmantissa(resultA,resultB); \ + break; \ + case ROUNDZERO: \ + Dbl_setlargest_exponentmantissa(resultA,resultB); \ + } + +#define Dbl_denormalize(opndp1,opndp2,exponent,guard,sticky,inexact) \ + Dbl_clear_signexponent_set_hidden(opndp1); \ + if (exponent >= (1-DBL_P)) { \ + if (exponent >= -31) { \ + guard = (Dallp2(opndp2) >> -exponent) & 1; \ + if (exponent < 0) sticky |= Dallp2(opndp2) << (32+exponent); \ + if (exponent > -31) { \ + Variable_shift_double(opndp1,opndp2,1-exponent,opndp2); \ + Dallp1(opndp1) >>= 1-exponent; \ + } \ + else { \ + Dallp2(opndp2) = Dallp1(opndp1); \ + Dbl_setzerop1(opndp1); \ + } \ + } \ + else { \ + guard = (Dallp1(opndp1) >> -32-exponent) & 1; \ + if (exponent == -32) sticky |= Dallp2(opndp2); \ + else sticky |= (Dallp2(opndp2) | Dallp1(opndp1) << 64+exponent); \ + Dallp2(opndp2) = Dallp1(opndp1) >> -31-exponent; \ + Dbl_setzerop1(opndp1); \ + } \ + inexact = guard | sticky; \ + } \ + else { \ + guard = 0; \ + sticky |= (Dallp1(opndp1) | Dallp2(opndp2)); \ + Dbl_setzero(opndp1,opndp2); \ + inexact = sticky; \ + } + +/* + * The fused multiply add instructions requires a double extended format, + * with 106 bits of mantissa. + */ +#define DBLEXT_THRESHOLD 106 + +#define Dblext_setzero(valA,valB,valC,valD) \ + Dextallp1(valA) = 0; Dextallp2(valB) = 0; \ + Dextallp3(valC) = 0; Dextallp4(valD) = 0 + + +#define Dblext_isnotzero_mantissap3(valC) (Dextallp3(valC)!=0) +#define Dblext_isnotzero_mantissap4(valD) (Dextallp3(valD)!=0) +#define Dblext_isone_lowp2(val) (Dextlowp2(val)!=0) +#define Dblext_isone_highp3(val) (Dexthighp3(val)!=0) +#define Dblext_isnotzero_low31p3(val) (Dextlow31p3(val)!=0) +#define Dblext_iszero(valA,valB,valC,valD) (Dextallp1(valA)==0 && \ + Dextallp2(valB)==0 && Dextallp3(valC)==0 && Dextallp4(valD)==0) + +#define Dblext_copy(srca,srcb,srcc,srcd,desta,destb,destc,destd) \ + Dextallp1(desta) = Dextallp4(srca); \ + Dextallp2(destb) = Dextallp4(srcb); \ + Dextallp3(destc) = Dextallp4(srcc); \ + Dextallp4(destd) = Dextallp4(srcd) + +#define Dblext_swap_lower(leftp2,leftp3,leftp4,rightp2,rightp3,rightp4) \ + Dextallp2(leftp2) = Dextallp2(leftp2) XOR Dextallp2(rightp2); \ + Dextallp2(rightp2) = Dextallp2(leftp2) XOR Dextallp2(rightp2); \ + Dextallp2(leftp2) = Dextallp2(leftp2) XOR Dextallp2(rightp2); \ + Dextallp3(leftp3) = Dextallp3(leftp3) XOR Dextallp3(rightp3); \ + Dextallp3(rightp3) = Dextallp3(leftp3) XOR Dextallp3(rightp3); \ + Dextallp3(leftp3) = Dextallp3(leftp3) XOR Dextallp3(rightp3); \ + Dextallp4(leftp4) = Dextallp4(leftp4) XOR Dextallp4(rightp4); \ + Dextallp4(rightp4) = Dextallp4(leftp4) XOR Dextallp4(rightp4); \ + Dextallp4(leftp4) = Dextallp4(leftp4) XOR Dextallp4(rightp4) + +#define Dblext_setone_lowmantissap4(dbl_value) Deposit_dextlowp4(dbl_value,1) + +/* The high bit is always zero so arithmetic or logical shifts will work. */ +#define Dblext_right_align(srcdstA,srcdstB,srcdstC,srcdstD,shift) \ + {int shiftamt, sticky; \ + shiftamt = shift % 32; \ + sticky = 0; \ + switch (shift/32) { \ + case 0: if (shiftamt > 0) { \ + sticky = Dextallp4(srcdstD) << 32 - (shiftamt); \ + Variable_shift_double(Dextallp3(srcdstC), \ + Dextallp4(srcdstD),shiftamt,Dextallp4(srcdstD)); \ + Variable_shift_double(Dextallp2(srcdstB), \ + Dextallp3(srcdstC),shiftamt,Dextallp3(srcdstC)); \ + Variable_shift_double(Dextallp1(srcdstA), \ + Dextallp2(srcdstB),shiftamt,Dextallp2(srcdstB)); \ + Dextallp1(srcdstA) >>= shiftamt; \ + } \ + break; \ + case 1: if (shiftamt > 0) { \ + sticky = (Dextallp3(srcdstC) << 31 - shiftamt) | \ + Dextallp4(srcdstD); \ + Variable_shift_double(Dextallp2(srcdstB), \ + Dextallp3(srcdstC),shiftamt,Dextallp4(srcdstD)); \ + Variable_shift_double(Dextallp1(srcdstA), \ + Dextallp2(srcdstB),shiftamt,Dextallp3(srcdstC)); \ + } \ + else { \ + sticky = Dextallp4(srcdstD); \ + Dextallp4(srcdstD) = Dextallp3(srcdstC); \ + Dextallp3(srcdstC) = Dextallp2(srcdstB); \ + } \ + Dextallp2(srcdstB) = Dextallp1(srcdstA) >> shiftamt; \ + Dextallp1(srcdstA) = 0; \ + break; \ + case 2: if (shiftamt > 0) { \ + sticky = (Dextallp2(srcdstB) << 31 - shiftamt) | \ + Dextallp3(srcdstC) | Dextallp4(srcdstD); \ + Variable_shift_double(Dextallp1(srcdstA), \ + Dextallp2(srcdstB),shiftamt,Dextallp4(srcdstD)); \ + } \ + else { \ + sticky = Dextallp3(srcdstC) | Dextallp4(srcdstD); \ + Dextallp4(srcdstD) = Dextallp2(srcdstB); \ + } \ + Dextallp3(srcdstC) = Dextallp1(srcdstA) >> shiftamt; \ + Dextallp1(srcdstA) = Dextallp2(srcdstB) = 0; \ + break; \ + case 3: if (shiftamt > 0) { \ + sticky = (Dextallp1(srcdstA) << 31 - shiftamt) | \ + Dextallp2(srcdstB) | Dextallp3(srcdstC) | \ + Dextallp4(srcdstD); \ + } \ + else { \ + sticky = Dextallp2(srcdstB) | Dextallp3(srcdstC) | \ + Dextallp4(srcdstD); \ + } \ + Dextallp4(srcdstD) = Dextallp1(srcdstA) >> shiftamt; \ + Dextallp1(srcdstA) = Dextallp2(srcdstB) = 0; \ + Dextallp3(srcdstC) = 0; \ + break; \ + } \ + if (sticky) Dblext_setone_lowmantissap4(srcdstD); \ + } + +/* The left argument is never smaller than the right argument */ +#define Dblext_subtract(lefta,leftb,leftc,leftd,righta,rightb,rightc,rightd,resulta,resultb,resultc,resultd) \ + if( Dextallp4(rightd) > Dextallp4(leftd) ) \ + if( (Dextallp3(leftc)--) == 0) \ + if( (Dextallp2(leftb)--) == 0) Dextallp1(lefta)--; \ + Dextallp4(resultd) = Dextallp4(leftd) - Dextallp4(rightd); \ + if( Dextallp3(rightc) > Dextallp3(leftc) ) \ + if( (Dextallp2(leftb)--) == 0) Dextallp1(lefta)--; \ + Dextallp3(resultc) = Dextallp3(leftc) - Dextallp3(rightc); \ + if( Dextallp2(rightb) > Dextallp2(leftb) ) Dextallp1(lefta)--; \ + Dextallp2(resultb) = Dextallp2(leftb) - Dextallp2(rightb); \ + Dextallp1(resulta) = Dextallp1(lefta) - Dextallp1(righta) + +#define Dblext_addition(lefta,leftb,leftc,leftd,righta,rightb,rightc,rightd,resulta,resultb,resultc,resultd) \ + /* If the sum of the low words is less than either source, then \ + * an overflow into the next word occurred. */ \ + if ((Dextallp4(resultd) = Dextallp4(leftd)+Dextallp4(rightd)) < \ + Dextallp4(rightd)) \ + if((Dextallp3(resultc) = Dextallp3(leftc)+Dextallp3(rightc)+1) <= \ + Dextallp3(rightc)) \ + if((Dextallp2(resultb) = Dextallp2(leftb)+Dextallp2(rightb)+1) \ + <= Dextallp2(rightb)) \ + Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta)+1; \ + else Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta); \ + else \ + if ((Dextallp2(resultb) = Dextallp2(leftb)+Dextallp2(rightb)) < \ + Dextallp2(rightb)) \ + Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta)+1; \ + else Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta); \ + else \ + if ((Dextallp3(resultc) = Dextallp3(leftc)+Dextallp3(rightc)) < \ + Dextallp3(rightc)) \ + if ((Dextallp2(resultb) = Dextallp2(leftb)+Dextallp2(rightb)+1) \ + <= Dextallp2(rightb)) \ + Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta)+1; \ + else Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta); \ + else \ + if ((Dextallp2(resultb) = Dextallp2(leftb)+Dextallp2(rightb)) < \ + Dextallp2(rightb)) \ + Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta)+1; \ + else Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta) + + +#define Dblext_arithrightshiftby1(srcdstA,srcdstB,srcdstC,srcdstD) \ + Shiftdouble(Dextallp3(srcdstC),Dextallp4(srcdstD),1,Dextallp4(srcdstD)); \ + Shiftdouble(Dextallp2(srcdstB),Dextallp3(srcdstC),1,Dextallp3(srcdstC)); \ + Shiftdouble(Dextallp1(srcdstA),Dextallp2(srcdstB),1,Dextallp2(srcdstB)); \ + Dextallp1(srcdstA) = (int)Dextallp1(srcdstA) >> 1 + +#define Dblext_leftshiftby8(valA,valB,valC,valD) \ + Shiftdouble(Dextallp1(valA),Dextallp2(valB),24,Dextallp1(valA)); \ + Shiftdouble(Dextallp2(valB),Dextallp3(valC),24,Dextallp2(valB)); \ + Shiftdouble(Dextallp3(valC),Dextallp4(valD),24,Dextallp3(valC)); \ + Dextallp4(valD) <<= 8 +#define Dblext_leftshiftby4(valA,valB,valC,valD) \ + Shiftdouble(Dextallp1(valA),Dextallp2(valB),28,Dextallp1(valA)); \ + Shiftdouble(Dextallp2(valB),Dextallp3(valC),28,Dextallp2(valB)); \ + Shiftdouble(Dextallp3(valC),Dextallp4(valD),28,Dextallp3(valC)); \ + Dextallp4(valD) <<= 4 +#define Dblext_leftshiftby3(valA,valB,valC,valD) \ + Shiftdouble(Dextallp1(valA),Dextallp2(valB),29,Dextallp1(valA)); \ + Shiftdouble(Dextallp2(valB),Dextallp3(valC),29,Dextallp2(valB)); \ + Shiftdouble(Dextallp3(valC),Dextallp4(valD),29,Dextallp3(valC)); \ + Dextallp4(valD) <<= 3 +#define Dblext_leftshiftby2(valA,valB,valC,valD) \ + Shiftdouble(Dextallp1(valA),Dextallp2(valB),30,Dextallp1(valA)); \ + Shiftdouble(Dextallp2(valB),Dextallp3(valC),30,Dextallp2(valB)); \ + Shiftdouble(Dextallp3(valC),Dextallp4(valD),30,Dextallp3(valC)); \ + Dextallp4(valD) <<= 2 +#define Dblext_leftshiftby1(valA,valB,valC,valD) \ + Shiftdouble(Dextallp1(valA),Dextallp2(valB),31,Dextallp1(valA)); \ + Shiftdouble(Dextallp2(valB),Dextallp3(valC),31,Dextallp2(valB)); \ + Shiftdouble(Dextallp3(valC),Dextallp4(valD),31,Dextallp3(valC)); \ + Dextallp4(valD) <<= 1 + +#define Dblext_rightshiftby4(valueA,valueB,valueC,valueD) \ + Shiftdouble(Dextallp3(valueC),Dextallp4(valueD),4,Dextallp4(valueD)); \ + Shiftdouble(Dextallp2(valueB),Dextallp3(valueC),4,Dextallp3(valueC)); \ + Shiftdouble(Dextallp1(valueA),Dextallp2(valueB),4,Dextallp2(valueB)); \ + Dextallp1(valueA) >>= 4 +#define Dblext_rightshiftby1(valueA,valueB,valueC,valueD) \ + Shiftdouble(Dextallp3(valueC),Dextallp4(valueD),1,Dextallp4(valueD)); \ + Shiftdouble(Dextallp2(valueB),Dextallp3(valueC),1,Dextallp3(valueC)); \ + Shiftdouble(Dextallp1(valueA),Dextallp2(valueB),1,Dextallp2(valueB)); \ + Dextallp1(valueA) >>= 1 + +#define Dblext_xortointp1(left,right,result) Dbl_xortointp1(left,right,result) + +#define Dblext_xorfromintp1(left,right,result) \ + Dbl_xorfromintp1(left,right,result) + +#define Dblext_copytoint_exponentmantissap1(src,dest) \ + Dbl_copytoint_exponentmantissap1(src,dest) + +#define Dblext_ismagnitudeless(leftB,rightB,signlessleft,signlessright) \ + Dbl_ismagnitudeless(leftB,rightB,signlessleft,signlessright) + +#define Dbl_copyto_dblext(src1,src2,dest1,dest2,dest3,dest4) \ + Dextallp1(dest1) = Dallp1(src1); Dextallp2(dest2) = Dallp2(src2); \ + Dextallp3(dest3) = 0; Dextallp4(dest4) = 0 + +#define Dblext_set_sign(dbl_value,sign) Dbl_set_sign(dbl_value,sign) +#define Dblext_clear_signexponent_set_hidden(srcdst) \ + Dbl_clear_signexponent_set_hidden(srcdst) +#define Dblext_clear_signexponent(srcdst) Dbl_clear_signexponent(srcdst) +#define Dblext_clear_sign(srcdst) Dbl_clear_sign(srcdst) +#define Dblext_isone_hidden(dbl_value) Dbl_isone_hidden(dbl_value) + +/* + * The Fourword_add() macro assumes that integers are 4 bytes in size. + * It will break if this is not the case. + */ + +#define Fourword_add(src1dstA,src1dstB,src1dstC,src1dstD,src2A,src2B,src2C,src2D) \ + /* \ + * want this macro to generate: \ + * ADD src1dstD,src2D,src1dstD; \ + * ADDC src1dstC,src2C,src1dstC; \ + * ADDC src1dstB,src2B,src1dstB; \ + * ADDC src1dstA,src2A,src1dstA; \ + */ \ + if ((unsigned int)(src1dstD += (src2D)) < (unsigned int)(src2D)) { \ + if ((unsigned int)(src1dstC += (src2C) + 1) <= \ + (unsigned int)(src2C)) { \ + if ((unsigned int)(src1dstB += (src2B) + 1) <= \ + (unsigned int)(src2B)) src1dstA++; \ + } \ + else if ((unsigned int)(src1dstB += (src2B)) < \ + (unsigned int)(src2B)) src1dstA++; \ + } \ + else { \ + if ((unsigned int)(src1dstC += (src2C)) < \ + (unsigned int)(src2C)) { \ + if ((unsigned int)(src1dstB += (src2B) + 1) <= \ + (unsigned int)(src2B)) src1dstA++; \ + } \ + else if ((unsigned int)(src1dstB += (src2B)) < \ + (unsigned int)(src2B)) src1dstA++; \ + } \ + src1dstA += (src2A) + +#define Dblext_denormalize(opndp1,opndp2,opndp3,opndp4,exponent,is_tiny) \ + {int shiftamt, sticky; \ + is_tiny = TRUE; \ + if (exponent == 0 && (Dextallp3(opndp3) || Dextallp4(opndp4))) { \ + switch (Rounding_mode()) { \ + case ROUNDPLUS: \ + if (Dbl_iszero_sign(opndp1)) { \ + Dbl_increment(opndp1,opndp2); \ + if (Dbl_isone_hiddenoverflow(opndp1)) \ + is_tiny = FALSE; \ + Dbl_decrement(opndp1,opndp2); \ + } \ + break; \ + case ROUNDMINUS: \ + if (Dbl_isone_sign(opndp1)) { \ + Dbl_increment(opndp1,opndp2); \ + if (Dbl_isone_hiddenoverflow(opndp1)) \ + is_tiny = FALSE; \ + Dbl_decrement(opndp1,opndp2); \ + } \ + break; \ + case ROUNDNEAREST: \ + if (Dblext_isone_highp3(opndp3) && \ + (Dblext_isone_lowp2(opndp2) || \ + Dblext_isnotzero_low31p3(opndp3))) { \ + Dbl_increment(opndp1,opndp2); \ + if (Dbl_isone_hiddenoverflow(opndp1)) \ + is_tiny = FALSE; \ + Dbl_decrement(opndp1,opndp2); \ + } \ + break; \ + } \ + } \ + Dblext_clear_signexponent_set_hidden(opndp1); \ + if (exponent >= (1-QUAD_P)) { \ + shiftamt = (1-exponent) % 32; \ + switch((1-exponent)/32) { \ + case 0: sticky = Dextallp4(opndp4) << 32-(shiftamt); \ + Variableshiftdouble(opndp3,opndp4,shiftamt,opndp4); \ + Variableshiftdouble(opndp2,opndp3,shiftamt,opndp3); \ + Variableshiftdouble(opndp1,opndp2,shiftamt,opndp2); \ + Dextallp1(opndp1) >>= shiftamt; \ + break; \ + case 1: sticky = (Dextallp3(opndp3) << 32-(shiftamt)) | \ + Dextallp4(opndp4); \ + Variableshiftdouble(opndp2,opndp3,shiftamt,opndp4); \ + Variableshiftdouble(opndp1,opndp2,shiftamt,opndp3); \ + Dextallp2(opndp2) = Dextallp1(opndp1) >> shiftamt; \ + Dextallp1(opndp1) = 0; \ + break; \ + case 2: sticky = (Dextallp2(opndp2) << 32-(shiftamt)) | \ + Dextallp3(opndp3) | Dextallp4(opndp4); \ + Variableshiftdouble(opndp1,opndp2,shiftamt,opndp4); \ + Dextallp3(opndp3) = Dextallp1(opndp1) >> shiftamt; \ + Dextallp1(opndp1) = Dextallp2(opndp2) = 0; \ + break; \ + case 3: sticky = (Dextallp1(opndp1) << 32-(shiftamt)) | \ + Dextallp2(opndp2) | Dextallp3(opndp3) | \ + Dextallp4(opndp4); \ + Dextallp4(opndp4) = Dextallp1(opndp1) >> shiftamt; \ + Dextallp1(opndp1) = Dextallp2(opndp2) = 0; \ + Dextallp3(opndp3) = 0; \ + break; \ + } \ + } \ + else { \ + sticky = Dextallp1(opndp1) | Dextallp2(opndp2) | \ + Dextallp3(opndp3) | Dextallp4(opndp4); \ + Dblext_setzero(opndp1,opndp2,opndp3,opndp4); \ + } \ + if (sticky) Dblext_setone_lowmantissap4(opndp4); \ + exponent = 0; \ + } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/decode_exc.c linux.19rc3-ac4/arch/parisc/math-emu/decode_exc.c --- linux.19rc3/arch/parisc/math-emu/decode_exc.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/decode_exc.c 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,368 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * BEGIN_DESC + * + * File: + * @(#) pa/fp/decode_exc.c $ Revision: $ + * + * Purpose: + * <> + * + * External Interfaces: + * <> + * decode_fpu(Fpu_register, trap_counts) + * + * Internal Interfaces: + * <> + * + * Theory: + * <> + * + * END_DESC +*/ + + +#include "float.h" +#include "sgl_float.h" +#include "dbl_float.h" +#include "cnv_float.h" +/* #include "types.h" */ +#include +#include +/* #include */ + +#undef Fpustatus_register +#define Fpustatus_register Fpu_register[0] + +/* General definitions */ +#define DOESTRAP 1 +#define NOTRAP 0 +#define SIGNALCODE(signal, code) ((signal) << 24 | (code)); +#define copropbit 1<<31-2 /* bit position 2 */ +#define opclass 9 /* bits 21 & 22 */ +#define fmt 11 /* bits 19 & 20 */ +#define df 13 /* bits 17 & 18 */ +#define twobits 3 /* mask low-order 2 bits */ +#define fivebits 31 /* mask low-order 5 bits */ +#define MAX_EXCP_REG 7 /* number of excpeption registers to check */ + +/* Exception register definitions */ +#define Excp_type(index) Exceptiontype(Fpu_register[index]) +#define Excp_instr(index) Instructionfield(Fpu_register[index]) +#define Clear_excp_register(index) Allexception(Fpu_register[index]) = 0 +#define Excp_format() \ + (current_ir >> ((current_ir>>opclass & twobits)==1 ? df : fmt) & twobits) + +/* Miscellaneous definitions */ +#define Fpu_sgl(index) Fpu_register[index*2] + +#define Fpu_dblp1(index) Fpu_register[index*2] +#define Fpu_dblp2(index) Fpu_register[(index*2)+1] + +#define Fpu_quadp1(index) Fpu_register[index*2] +#define Fpu_quadp2(index) Fpu_register[(index*2)+1] +#define Fpu_quadp3(index) Fpu_register[(index*2)+2] +#define Fpu_quadp4(index) Fpu_register[(index*2)+3] + +/* Single precision floating-point definitions */ +#ifndef Sgl_decrement +# define Sgl_decrement(sgl_value) Sall(sgl_value)-- +#endif + +/* Double precision floating-point definitions */ +#ifndef Dbl_decrement +# define Dbl_decrement(dbl_valuep1,dbl_valuep2) \ + if ((Dallp2(dbl_valuep2)--) == 0) Dallp1(dbl_valuep1)-- +#endif + + +#define update_trap_counts(Fpu_register, aflags, bflags, trap_counts) { \ + aflags=(Fpu_register[0])>>27; /* assumes zero fill. 32 bit */ \ + Fpu_register[0] |= bflags; \ +} + +u_int +decode_fpu(unsigned int Fpu_register[], unsigned int trap_counts[]) +{ + unsigned int current_ir, excp; + int target, exception_index = 1; + boolean inexact; + unsigned int aflags; + unsigned int bflags; + unsigned int excptype; + + + /* Keep stats on how many floating point exceptions (based on type) + * that happen. Want to keep this overhead low, but still provide + * some information to the customer. All exits from this routine + * need to restore Fpu_register[0] + */ + + bflags=(Fpu_register[0] & 0xf8000000); + Fpu_register[0] &= 0x07ffffff; + + /* exception_index is used to index the exception register queue. It + * always points at the last register that contains a valid exception. A + * zero value implies no exceptions (also the initialized value). Setting + * the T-bit resets the exception_index to zero. + */ + + /* + * Check for reserved-op exception. A reserved-op exception does not + * set any exception registers nor does it set the T-bit. If the T-bit + * is not set then a reserved-op exception occurred. + * + * At some point, we may want to report reserved op exceptions as + * illegal instructions. + */ + + if (!Is_tbit_set()) { + update_trap_counts(Fpu_register, aflags, bflags, trap_counts); + return SIGNALCODE(SIGILL, ILL_COPROC); + } + + /* + * Is a coprocessor op. + * + * Now we need to determine what type of exception occurred. + */ + for (exception_index=1; exception_index<=MAX_EXCP_REG; exception_index++) { + current_ir = Excp_instr(exception_index); + /* + * On PA89: there are 5 different unimplemented exception + * codes: 0x1, 0x9, 0xb, 0x3, and 0x23. PA-RISC 2.0 adds + * another, 0x2b. Only these have the low order bit set. + */ + excptype = Excp_type(exception_index); + if (excptype & UNIMPLEMENTEDEXCEPTION) { + /* + * Clear T-bit and exception register so that + * we can tell if a trap really occurs while + * emulating the instruction. + */ + Clear_tbit(); + Clear_excp_register(exception_index); + /* + * Now emulate this instruction. If a trap occurs, + * fpudispatch will return a non-zero number + */ + excp = fpudispatch(current_ir,excptype,0,Fpu_register); + /* accumulate the status flags, don't lose them as in hpux */ + if (excp) { + /* + * We now need to make sure that the T-bit and the + * exception register contain the correct values + * before continuing. + */ + /* + * Set t-bit since it might still be needed for a + * subsequent real trap (I don't understand fully -PB) + */ + Set_tbit(); + /* some of the following code uses + * Excp_type(exception_index) so fix that up */ + Set_exceptiontype_and_instr_field(excp,current_ir, + Fpu_register[exception_index]); + if (excp == UNIMPLEMENTEDEXCEPTION) { + /* + * it is really unimplemented, so restore the + * TIMEX extended unimplemented exception code + */ + excp = excptype; + update_trap_counts(Fpu_register, aflags, bflags, + trap_counts); + return SIGNALCODE(SIGILL, ILL_COPROC); + } + /* some of the following code uses excptype, so + * fix that up too */ + excptype = excp; + } + /* handle exceptions other than the real UNIMPLIMENTED the + * same way as if the hardware had caused them */ + if (excp == NOEXCEPTION) + /* For now use 'break', should technically be 'continue' */ + break; + } + + /* + * In PA89, the underflow exception has been extended to encode + * additional information. The exception looks like pp01x0, + * where x is 1 if inexact and pp represent the inexact bit (I) + * and the round away bit (RA) + */ + if (excptype & UNDERFLOWEXCEPTION) { + /* check for underflow trap enabled */ + if (Is_underflowtrap_enabled()) { + update_trap_counts(Fpu_register, aflags, bflags, + trap_counts); + return SIGNALCODE(SIGFPE, FPE_FLTUND); + } else { + /* + * Isn't a real trap; we need to + * return the default value. + */ + target = current_ir & fivebits; +#ifndef lint + if (Ibit(Fpu_register[exception_index])) inexact = TRUE; + else inexact = FALSE; +#endif + switch (Excp_format()) { + case SGL: + /* + * If ra (round-away) is set, will + * want to undo the rounding done + * by the hardware. + */ + if (Rabit(Fpu_register[exception_index])) + Sgl_decrement(Fpu_sgl(target)); + + /* now denormalize */ + sgl_denormalize(&Fpu_sgl(target),&inexact,Rounding_mode()); + break; + case DBL: + /* + * If ra (round-away) is set, will + * want to undo the rounding done + * by the hardware. + */ + if (Rabit(Fpu_register[exception_index])) + Dbl_decrement(Fpu_dblp1(target),Fpu_dblp2(target)); + + /* now denormalize */ + dbl_denormalize(&Fpu_dblp1(target),&Fpu_dblp2(target), + &inexact,Rounding_mode()); + break; + } + if (inexact) Set_underflowflag(); + /* + * Underflow can generate an inexact + * exception. If inexact trap is enabled, + * want to do an inexact trap, otherwise + * set inexact flag. + */ + if (inexact && Is_inexacttrap_enabled()) { + /* + * Set exception field of exception register + * to inexact, parm field to zero. + * Underflow bit should be cleared. + */ + Set_exceptiontype(Fpu_register[exception_index], + INEXACTEXCEPTION); + Set_parmfield(Fpu_register[exception_index],0); + update_trap_counts(Fpu_register, aflags, bflags, + trap_counts); + return SIGNALCODE(SIGFPE, FPE_FLTRES); + } + else { + /* + * Exception register needs to be cleared. + * Inexact flag needs to be set if inexact. + */ + Clear_excp_register(exception_index); + if (inexact) Set_inexactflag(); + } + } + continue; + } + switch(Excp_type(exception_index)) { + case OVERFLOWEXCEPTION: + case OVERFLOWEXCEPTION | INEXACTEXCEPTION: + /* check for overflow trap enabled */ + update_trap_counts(Fpu_register, aflags, bflags, + trap_counts); + if (Is_overflowtrap_enabled()) { + update_trap_counts(Fpu_register, aflags, bflags, + trap_counts); + return SIGNALCODE(SIGFPE, FPE_FLTOVF); + } else { + /* + * Isn't a real trap; we need to + * return the default value. + */ + target = current_ir & fivebits; + switch (Excp_format()) { + case SGL: + Sgl_setoverflow(Fpu_sgl(target)); + break; + case DBL: + Dbl_setoverflow(Fpu_dblp1(target),Fpu_dblp2(target)); + break; + } + Set_overflowflag(); + /* + * Overflow always generates an inexact + * exception. If inexact trap is enabled, + * want to do an inexact trap, otherwise + * set inexact flag. + */ + if (Is_inexacttrap_enabled()) { + /* + * Set exception field of exception + * register to inexact. Overflow + * bit should be cleared. + */ + Set_exceptiontype(Fpu_register[exception_index], + INEXACTEXCEPTION); + update_trap_counts(Fpu_register, aflags, bflags, + trap_counts); + return SIGNALCODE(SIGFPE, FPE_FLTRES); + } + else { + /* + * Exception register needs to be cleared. + * Inexact flag needs to be set. + */ + Clear_excp_register(exception_index); + Set_inexactflag(); + } + } + break; + case INVALIDEXCEPTION: + update_trap_counts(Fpu_register, aflags, bflags, trap_counts); + return SIGNALCODE(SIGFPE, FPE_FLTINV); + case DIVISIONBYZEROEXCEPTION: + update_trap_counts(Fpu_register, aflags, bflags, trap_counts); + return SIGNALCODE(SIGFPE, FPE_FLTDIV); + case INEXACTEXCEPTION: + update_trap_counts(Fpu_register, aflags, bflags, trap_counts); + return SIGNALCODE(SIGFPE, FPE_FLTRES); + default: + update_trap_counts(Fpu_register, aflags, bflags, trap_counts); + printk(__FILE__ "(%d) Unknown FPU exception 0x%x\n", + __LINE__, Excp_type(exception_index)); + return SIGNALCODE(SIGILL, ILL_COPROC); + case NOEXCEPTION: /* no exception */ + /* + * Clear exception register in case + * other fields are non-zero. + */ + Clear_excp_register(exception_index); + break; + } + } + /* + * No real exceptions occurred. + */ + Clear_tbit(); + update_trap_counts(Fpu_register, aflags, bflags, trap_counts); + return(NOTRAP); +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/denormal.c linux.19rc3-ac4/arch/parisc/math-emu/denormal.c --- linux.19rc3/arch/parisc/math-emu/denormal.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/denormal.c 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,135 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * BEGIN_DESC + * + * File: + * @(#) pa/fp/denormal.c $ Revision: $ + * + * Purpose: + * <> + * + * External Interfaces: + * <> + * dbl_denormalize(dbl_opndp1,dbl_opndp2,inexactflag,rmode) + * sgl_denormalize(sgl_opnd,inexactflag,rmode) + * + * Internal Interfaces: + * <> + * + * Theory: + * <> + * + * END_DESC +*/ + + + +#include "float.h" +#include "sgl_float.h" +#include "dbl_float.h" +#include "hppa.h" +#include "types.h" +/* #include */ + +#undef Fpustatus_register +#define Fpustatus_register Fpu_register[0] + +void +sgl_denormalize(unsigned int *sgl_opnd, boolean *inexactflag, int rmode) +{ + unsigned int opnd; + int sign, exponent; + boolean guardbit = FALSE, stickybit, inexact; + + opnd = *sgl_opnd; + stickybit = *inexactflag; + exponent = Sgl_exponent(opnd) - SGL_WRAP; + sign = Sgl_sign(opnd); + Sgl_denormalize(opnd,exponent,guardbit,stickybit,inexact); + if (inexact) { + switch (rmode) { + case ROUNDPLUS: + if (sign == 0) { + Sgl_increment(opnd); + } + break; + case ROUNDMINUS: + if (sign != 0) { + Sgl_increment(opnd); + } + break; + case ROUNDNEAREST: + if (guardbit && (stickybit || + Sgl_isone_lowmantissa(opnd))) { + Sgl_increment(opnd); + } + break; + } + } + Sgl_set_sign(opnd,sign); + *sgl_opnd = opnd; + *inexactflag = inexact; + return; +} + +void +dbl_denormalize(unsigned int *dbl_opndp1, + unsigned int * dbl_opndp2, + boolean *inexactflag, + int rmode) +{ + unsigned int opndp1, opndp2; + int sign, exponent; + boolean guardbit = FALSE, stickybit, inexact; + + opndp1 = *dbl_opndp1; + opndp2 = *dbl_opndp2; + stickybit = *inexactflag; + exponent = Dbl_exponent(opndp1) - DBL_WRAP; + sign = Dbl_sign(opndp1); + Dbl_denormalize(opndp1,opndp2,exponent,guardbit,stickybit,inexact); + if (inexact) { + switch (rmode) { + case ROUNDPLUS: + if (sign == 0) { + Dbl_increment(opndp1,opndp2); + } + break; + case ROUNDMINUS: + if (sign != 0) { + Dbl_increment(opndp1,opndp2); + } + break; + case ROUNDNEAREST: + if (guardbit && (stickybit || + Dbl_isone_lowmantissap2(opndp2))) { + Dbl_increment(opndp1,opndp2); + } + break; + } + } + Dbl_set_sign(opndp1,sign); + *dbl_opndp1 = opndp1; + *dbl_opndp2 = opndp2; + *inexactflag = inexact; + return; +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/dfadd.c linux.19rc3-ac4/arch/parisc/math-emu/dfadd.c --- linux.19rc3/arch/parisc/math-emu/dfadd.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/dfadd.c 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,524 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * BEGIN_DESC + * + * File: + * @(#) pa/spmath/dfadd.c $Revision: 1.1 $ + * + * Purpose: + * Double_add: add two double precision values. + * + * External Interfaces: + * dbl_fadd(leftptr, rightptr, dstptr, status) + * + * Internal Interfaces: + * + * Theory: + * <> + * + * END_DESC +*/ + + +#include "float.h" +#include "dbl_float.h" + +/* + * Double_add: add two double precision values. + */ +dbl_fadd( + dbl_floating_point *leftptr, + dbl_floating_point *rightptr, + dbl_floating_point *dstptr, + unsigned int *status) +{ + register unsigned int signless_upper_left, signless_upper_right, save; + register unsigned int leftp1, leftp2, rightp1, rightp2, extent; + register unsigned int resultp1 = 0, resultp2 = 0; + + register int result_exponent, right_exponent, diff_exponent; + register int sign_save, jumpsize; + register boolean inexact = FALSE; + register boolean underflowtrap; + + /* Create local copies of the numbers */ + Dbl_copyfromptr(leftptr,leftp1,leftp2); + Dbl_copyfromptr(rightptr,rightp1,rightp2); + + /* A zero "save" helps discover equal operands (for later), * + * and is used in swapping operands (if needed). */ + Dbl_xortointp1(leftp1,rightp1,/*to*/save); + + /* + * check first operand for NaN's or infinity + */ + if ((result_exponent = Dbl_exponent(leftp1)) == DBL_INFINITY_EXPONENT) + { + if (Dbl_iszero_mantissa(leftp1,leftp2)) + { + if (Dbl_isnotnan(rightp1,rightp2)) + { + if (Dbl_isinfinity(rightp1,rightp2) && save!=0) + { + /* + * invalid since operands are opposite signed infinity's + */ + if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); + Set_invalidflag(); + Dbl_makequietnan(resultp1,resultp2); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + /* + * return infinity + */ + Dbl_copytoptr(leftp1,leftp2,dstptr); + return(NOEXCEPTION); + } + } + else + { + /* + * is NaN; signaling or quiet? + */ + if (Dbl_isone_signaling(leftp1)) + { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Dbl_set_quiet(leftp1); + } + /* + * is second operand a signaling NaN? + */ + else if (Dbl_is_signalingnan(rightp1)) + { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Dbl_set_quiet(rightp1); + Dbl_copytoptr(rightp1,rightp2,dstptr); + return(NOEXCEPTION); + } + /* + * return quiet NaN + */ + Dbl_copytoptr(leftp1,leftp2,dstptr); + return(NOEXCEPTION); + } + } /* End left NaN or Infinity processing */ + /* + * check second operand for NaN's or infinity + */ + if (Dbl_isinfinity_exponent(rightp1)) + { + if (Dbl_iszero_mantissa(rightp1,rightp2)) + { + /* return infinity */ + Dbl_copytoptr(rightp1,rightp2,dstptr); + return(NOEXCEPTION); + } + /* + * is NaN; signaling or quiet? + */ + if (Dbl_isone_signaling(rightp1)) + { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Dbl_set_quiet(rightp1); + } + /* + * return quiet NaN + */ + Dbl_copytoptr(rightp1,rightp2,dstptr); + return(NOEXCEPTION); + } /* End right NaN or Infinity processing */ + + /* Invariant: Must be dealing with finite numbers */ + + /* Compare operands by removing the sign */ + Dbl_copytoint_exponentmantissap1(leftp1,signless_upper_left); + Dbl_copytoint_exponentmantissap1(rightp1,signless_upper_right); + + /* sign difference selects add or sub operation. */ + if(Dbl_ismagnitudeless(leftp2,rightp2,signless_upper_left,signless_upper_right)) + { + /* Set the left operand to the larger one by XOR swap * + * First finish the first word using "save" */ + Dbl_xorfromintp1(save,rightp1,/*to*/rightp1); + Dbl_xorfromintp1(save,leftp1,/*to*/leftp1); + Dbl_swap_lower(leftp2,rightp2); + result_exponent = Dbl_exponent(leftp1); + } + /* Invariant: left is not smaller than right. */ + + if((right_exponent = Dbl_exponent(rightp1)) == 0) + { + /* Denormalized operands. First look for zeroes */ + if(Dbl_iszero_mantissa(rightp1,rightp2)) + { + /* right is zero */ + if(Dbl_iszero_exponentmantissa(leftp1,leftp2)) + { + /* Both operands are zeros */ + if(Is_rounding_mode(ROUNDMINUS)) + { + Dbl_or_signs(leftp1,/*with*/rightp1); + } + else + { + Dbl_and_signs(leftp1,/*with*/rightp1); + } + } + else + { + /* Left is not a zero and must be the result. Trapped + * underflows are signaled if left is denormalized. Result + * is always exact. */ + if( (result_exponent == 0) && Is_underflowtrap_enabled() ) + { + /* need to normalize results mantissa */ + sign_save = Dbl_signextendedsign(leftp1); + Dbl_leftshiftby1(leftp1,leftp2); + Dbl_normalize(leftp1,leftp2,result_exponent); + Dbl_set_sign(leftp1,/*using*/sign_save); + Dbl_setwrapped_exponent(leftp1,result_exponent,unfl); + Dbl_copytoptr(leftp1,leftp2,dstptr); + /* inexact = FALSE */ + return(UNDERFLOWEXCEPTION); + } + } + Dbl_copytoptr(leftp1,leftp2,dstptr); + return(NOEXCEPTION); + } + + /* Neither are zeroes */ + Dbl_clear_sign(rightp1); /* Exponent is already cleared */ + if(result_exponent == 0 ) + { + /* Both operands are denormalized. The result must be exact + * and is simply calculated. A sum could become normalized and a + * difference could cancel to a true zero. */ + if( (/*signed*/int) save < 0 ) + { + Dbl_subtract(leftp1,leftp2,/*minus*/rightp1,rightp2, + /*into*/resultp1,resultp2); + if(Dbl_iszero_mantissa(resultp1,resultp2)) + { + if(Is_rounding_mode(ROUNDMINUS)) + { + Dbl_setone_sign(resultp1); + } + else + { + Dbl_setzero_sign(resultp1); + } + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + } + else + { + Dbl_addition(leftp1,leftp2,rightp1,rightp2, + /*into*/resultp1,resultp2); + if(Dbl_isone_hidden(resultp1)) + { + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + } + if(Is_underflowtrap_enabled()) + { + /* need to normalize result */ + sign_save = Dbl_signextendedsign(resultp1); + Dbl_leftshiftby1(resultp1,resultp2); + Dbl_normalize(resultp1,resultp2,result_exponent); + Dbl_set_sign(resultp1,/*using*/sign_save); + Dbl_setwrapped_exponent(resultp1,result_exponent,unfl); + Dbl_copytoptr(resultp1,resultp2,dstptr); + /* inexact = FALSE */ + return(UNDERFLOWEXCEPTION); + } + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + right_exponent = 1; /* Set exponent to reflect different bias + * with denomalized numbers. */ + } + else + { + Dbl_clear_signexponent_set_hidden(rightp1); + } + Dbl_clear_exponent_set_hidden(leftp1); + diff_exponent = result_exponent - right_exponent; + + /* + * Special case alignment of operands that would force alignment + * beyond the extent of the extension. A further optimization + * could special case this but only reduces the path length for this + * infrequent case. + */ + if(diff_exponent > DBL_THRESHOLD) + { + diff_exponent = DBL_THRESHOLD; + } + + /* Align right operand by shifting to right */ + Dbl_right_align(/*operand*/rightp1,rightp2,/*shifted by*/diff_exponent, + /*and lower to*/extent); + + /* Treat sum and difference of the operands separately. */ + if( (/*signed*/int) save < 0 ) + { + /* + * Difference of the two operands. Their can be no overflow. A + * borrow can occur out of the hidden bit and force a post + * normalization phase. + */ + Dbl_subtract_withextension(leftp1,leftp2,/*minus*/rightp1,rightp2, + /*with*/extent,/*into*/resultp1,resultp2); + if(Dbl_iszero_hidden(resultp1)) + { + /* Handle normalization */ + /* A straight foward algorithm would now shift the result + * and extension left until the hidden bit becomes one. Not + * all of the extension bits need participate in the shift. + * Only the two most significant bits (round and guard) are + * needed. If only a single shift is needed then the guard + * bit becomes a significant low order bit and the extension + * must participate in the rounding. If more than a single + * shift is needed, then all bits to the right of the guard + * bit are zeros, and the guard bit may or may not be zero. */ + sign_save = Dbl_signextendedsign(resultp1); + Dbl_leftshiftby1_withextent(resultp1,resultp2,extent,resultp1,resultp2); + + /* Need to check for a zero result. The sign and exponent + * fields have already been zeroed. The more efficient test + * of the full object can be used. + */ + if(Dbl_iszero(resultp1,resultp2)) + /* Must have been "x-x" or "x+(-x)". */ + { + if(Is_rounding_mode(ROUNDMINUS)) Dbl_setone_sign(resultp1); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + result_exponent--; + /* Look to see if normalization is finished. */ + if(Dbl_isone_hidden(resultp1)) + { + if(result_exponent==0) + { + /* Denormalized, exponent should be zero. Left operand * + * was normalized, so extent (guard, round) was zero */ + goto underflow; + } + else + { + /* No further normalization is needed. */ + Dbl_set_sign(resultp1,/*using*/sign_save); + Ext_leftshiftby1(extent); + goto round; + } + } + + /* Check for denormalized, exponent should be zero. Left * + * operand was normalized, so extent (guard, round) was zero */ + if(!(underflowtrap = Is_underflowtrap_enabled()) && + result_exponent==0) goto underflow; + + /* Shift extension to complete one bit of normalization and + * update exponent. */ + Ext_leftshiftby1(extent); + + /* Discover first one bit to determine shift amount. Use a + * modified binary search. We have already shifted the result + * one position right and still not found a one so the remainder + * of the extension must be zero and simplifies rounding. */ + /* Scan bytes */ + while(Dbl_iszero_hiddenhigh7mantissa(resultp1)) + { + Dbl_leftshiftby8(resultp1,resultp2); + if((result_exponent -= 8) <= 0 && !underflowtrap) + goto underflow; + } + /* Now narrow it down to the nibble */ + if(Dbl_iszero_hiddenhigh3mantissa(resultp1)) + { + /* The lower nibble contains the normalizing one */ + Dbl_leftshiftby4(resultp1,resultp2); + if((result_exponent -= 4) <= 0 && !underflowtrap) + goto underflow; + } + /* Select case were first bit is set (already normalized) + * otherwise select the proper shift. */ + if((jumpsize = Dbl_hiddenhigh3mantissa(resultp1)) > 7) + { + /* Already normalized */ + if(result_exponent <= 0) goto underflow; + Dbl_set_sign(resultp1,/*using*/sign_save); + Dbl_set_exponent(resultp1,/*using*/result_exponent); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + Dbl_sethigh4bits(resultp1,/*using*/sign_save); + switch(jumpsize) + { + case 1: + { + Dbl_leftshiftby3(resultp1,resultp2); + result_exponent -= 3; + break; + } + case 2: + case 3: + { + Dbl_leftshiftby2(resultp1,resultp2); + result_exponent -= 2; + break; + } + case 4: + case 5: + case 6: + case 7: + { + Dbl_leftshiftby1(resultp1,resultp2); + result_exponent -= 1; + break; + } + } + if(result_exponent > 0) + { + Dbl_set_exponent(resultp1,/*using*/result_exponent); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); /* Sign bit is already set */ + } + /* Fixup potential underflows */ + underflow: + if(Is_underflowtrap_enabled()) + { + Dbl_set_sign(resultp1,sign_save); + Dbl_setwrapped_exponent(resultp1,result_exponent,unfl); + Dbl_copytoptr(resultp1,resultp2,dstptr); + /* inexact = FALSE */ + return(UNDERFLOWEXCEPTION); + } + /* + * Since we cannot get an inexact denormalized result, + * we can now return. + */ + Dbl_fix_overshift(resultp1,resultp2,(1-result_exponent),extent); + Dbl_clear_signexponent(resultp1); + Dbl_set_sign(resultp1,sign_save); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } /* end if(hidden...)... */ + /* Fall through and round */ + } /* end if(save < 0)... */ + else + { + /* Add magnitudes */ + Dbl_addition(leftp1,leftp2,rightp1,rightp2,/*to*/resultp1,resultp2); + if(Dbl_isone_hiddenoverflow(resultp1)) + { + /* Prenormalization required. */ + Dbl_rightshiftby1_withextent(resultp2,extent,extent); + Dbl_arithrightshiftby1(resultp1,resultp2); + result_exponent++; + } /* end if hiddenoverflow... */ + } /* end else ...add magnitudes... */ + + /* Round the result. If the extension is all zeros,then the result is + * exact. Otherwise round in the correct direction. No underflow is + * possible. If a postnormalization is necessary, then the mantissa is + * all zeros so no shift is needed. */ + round: + if(Ext_isnotzero(extent)) + { + inexact = TRUE; + switch(Rounding_mode()) + { + case ROUNDNEAREST: /* The default. */ + if(Ext_isone_sign(extent)) + { + /* at least 1/2 ulp */ + if(Ext_isnotzero_lower(extent) || + Dbl_isone_lowmantissap2(resultp2)) + { + /* either exactly half way and odd or more than 1/2ulp */ + Dbl_increment(resultp1,resultp2); + } + } + break; + + case ROUNDPLUS: + if(Dbl_iszero_sign(resultp1)) + { + /* Round up positive results */ + Dbl_increment(resultp1,resultp2); + } + break; + + case ROUNDMINUS: + if(Dbl_isone_sign(resultp1)) + { + /* Round down negative results */ + Dbl_increment(resultp1,resultp2); + } + + case ROUNDZERO:; + /* truncate is simple */ + } /* end switch... */ + if(Dbl_isone_hiddenoverflow(resultp1)) result_exponent++; + } + if(result_exponent == DBL_INFINITY_EXPONENT) + { + /* Overflow */ + if(Is_overflowtrap_enabled()) + { + Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl); + Dbl_copytoptr(resultp1,resultp2,dstptr); + if (inexact) + if (Is_inexacttrap_enabled()) + return(OVERFLOWEXCEPTION | INEXACTEXCEPTION); + else Set_inexactflag(); + return(OVERFLOWEXCEPTION); + } + else + { + inexact = TRUE; + Set_overflowflag(); + Dbl_setoverflow(resultp1,resultp2); + } + } + else Dbl_set_exponent(resultp1,result_exponent); + Dbl_copytoptr(resultp1,resultp2,dstptr); + if(inexact) + if(Is_inexacttrap_enabled()) + return(INEXACTEXCEPTION); + else Set_inexactflag(); + return(NOEXCEPTION); +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/dfcmp.c linux.19rc3-ac4/arch/parisc/math-emu/dfcmp.c --- linux.19rc3/arch/parisc/math-emu/dfcmp.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/dfcmp.c 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,181 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * BEGIN_DESC + * + * File: + * @(#) pa/spmath/dfcmp.c $Revision: 1.1 $ + * + * Purpose: + * dbl_cmp: compare two values + * + * External Interfaces: + * dbl_fcmp(leftptr, rightptr, cond, status) + * + * Internal Interfaces: + * + * Theory: + * <> + * + * END_DESC +*/ + + + +#include "float.h" +#include "dbl_float.h" + +/* + * dbl_cmp: compare two values + */ +int +dbl_fcmp (dbl_floating_point * leftptr, dbl_floating_point * rightptr, + unsigned int cond, unsigned int *status) + + /* The predicate to be tested */ + + { + register unsigned int leftp1, leftp2, rightp1, rightp2; + register int xorresult; + + /* Create local copies of the numbers */ + Dbl_copyfromptr(leftptr,leftp1,leftp2); + Dbl_copyfromptr(rightptr,rightp1,rightp2); + /* + * Test for NaN + */ + if( (Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT) + || (Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT) ) + { + /* Check if a NaN is involved. Signal an invalid exception when + * comparing a signaling NaN or when comparing quiet NaNs and the + * low bit of the condition is set */ + if( ((Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT) + && Dbl_isnotzero_mantissa(leftp1,leftp2) + && (Exception(cond) || Dbl_isone_signaling(leftp1))) + || + ((Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT) + && Dbl_isnotzero_mantissa(rightp1,rightp2) + && (Exception(cond) || Dbl_isone_signaling(rightp1))) ) + { + if( Is_invalidtrap_enabled() ) { + Set_status_cbit(Unordered(cond)); + return(INVALIDEXCEPTION); + } + else Set_invalidflag(); + Set_status_cbit(Unordered(cond)); + return(NOEXCEPTION); + } + /* All the exceptional conditions are handled, now special case + NaN compares */ + else if( ((Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT) + && Dbl_isnotzero_mantissa(leftp1,leftp2)) + || + ((Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT) + && Dbl_isnotzero_mantissa(rightp1,rightp2)) ) + { + /* NaNs always compare unordered. */ + Set_status_cbit(Unordered(cond)); + return(NOEXCEPTION); + } + /* infinities will drop down to the normal compare mechanisms */ + } + /* First compare for unequal signs => less or greater or + * special equal case */ + Dbl_xortointp1(leftp1,rightp1,xorresult); + if( xorresult < 0 ) + { + /* left negative => less, left positive => greater. + * equal is possible if both operands are zeros. */ + if( Dbl_iszero_exponentmantissa(leftp1,leftp2) + && Dbl_iszero_exponentmantissa(rightp1,rightp2) ) + { + Set_status_cbit(Equal(cond)); + } + else if( Dbl_isone_sign(leftp1) ) + { + Set_status_cbit(Lessthan(cond)); + } + else + { + Set_status_cbit(Greaterthan(cond)); + } + } + /* Signs are the same. Treat negative numbers separately + * from the positives because of the reversed sense. */ + else if(Dbl_isequal(leftp1,leftp2,rightp1,rightp2)) + { + Set_status_cbit(Equal(cond)); + } + else if( Dbl_iszero_sign(leftp1) ) + { + /* Positive compare */ + if( Dbl_allp1(leftp1) < Dbl_allp1(rightp1) ) + { + Set_status_cbit(Lessthan(cond)); + } + else if( Dbl_allp1(leftp1) > Dbl_allp1(rightp1) ) + { + Set_status_cbit(Greaterthan(cond)); + } + else + { + /* Equal first parts. Now we must use unsigned compares to + * resolve the two possibilities. */ + if( Dbl_allp2(leftp2) < Dbl_allp2(rightp2) ) + { + Set_status_cbit(Lessthan(cond)); + } + else + { + Set_status_cbit(Greaterthan(cond)); + } + } + } + else + { + /* Negative compare. Signed or unsigned compares + * both work the same. That distinction is only + * important when the sign bits differ. */ + if( Dbl_allp1(leftp1) > Dbl_allp1(rightp1) ) + { + Set_status_cbit(Lessthan(cond)); + } + else if( Dbl_allp1(leftp1) < Dbl_allp1(rightp1) ) + { + Set_status_cbit(Greaterthan(cond)); + } + else + { + /* Equal first parts. Now we must use unsigned compares to + * resolve the two possibilities. */ + if( Dbl_allp2(leftp2) > Dbl_allp2(rightp2) ) + { + Set_status_cbit(Lessthan(cond)); + } + else + { + Set_status_cbit(Greaterthan(cond)); + } + } + } + return(NOEXCEPTION); + } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/dfdiv.c linux.19rc3-ac4/arch/parisc/math-emu/dfdiv.c --- linux.19rc3/arch/parisc/math-emu/dfdiv.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/dfdiv.c 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,400 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * BEGIN_DESC + * + * File: + * @(#) pa/spmath/dfdiv.c $Revision: 1.1 $ + * + * Purpose: + * Double Precision Floating-point Divide + * + * External Interfaces: + * dbl_fdiv(srcptr1,srcptr2,dstptr,status) + * + * Internal Interfaces: + * + * Theory: + * <> + * + * END_DESC +*/ + + +#include "float.h" +#include "dbl_float.h" + +/* + * Double Precision Floating-point Divide + */ + +int +dbl_fdiv (dbl_floating_point * srcptr1, dbl_floating_point * srcptr2, + dbl_floating_point * dstptr, unsigned int *status) +{ + register unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2; + register unsigned int opnd3p1, opnd3p2, resultp1, resultp2; + register int dest_exponent, count; + register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE; + boolean is_tiny; + + Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2); + Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2); + /* + * set sign bit of result + */ + if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1)) + Dbl_setnegativezerop1(resultp1); + else Dbl_setzerop1(resultp1); + /* + * check first operand for NaN's or infinity + */ + if (Dbl_isinfinity_exponent(opnd1p1)) { + if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { + if (Dbl_isnotnan(opnd2p1,opnd2p2)) { + if (Dbl_isinfinity(opnd2p1,opnd2p2)) { + /* + * invalid since both operands + * are infinity + */ + if (Is_invalidtrap_enabled()) + return(INVALIDEXCEPTION); + Set_invalidflag(); + Dbl_makequietnan(resultp1,resultp2); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + /* + * return infinity + */ + Dbl_setinfinity_exponentmantissa(resultp1,resultp2); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + } + else { + /* + * is NaN; signaling or quiet? + */ + if (Dbl_isone_signaling(opnd1p1)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Dbl_set_quiet(opnd1p1); + } + /* + * is second operand a signaling NaN? + */ + else if (Dbl_is_signalingnan(opnd2p1)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Dbl_set_quiet(opnd2p1); + Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); + return(NOEXCEPTION); + } + /* + * return quiet NaN + */ + Dbl_copytoptr(opnd1p1,opnd1p2,dstptr); + return(NOEXCEPTION); + } + } + /* + * check second operand for NaN's or infinity + */ + if (Dbl_isinfinity_exponent(opnd2p1)) { + if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) { + /* + * return zero + */ + Dbl_setzero_exponentmantissa(resultp1,resultp2); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + /* + * is NaN; signaling or quiet? + */ + if (Dbl_isone_signaling(opnd2p1)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Dbl_set_quiet(opnd2p1); + } + /* + * return quiet NaN + */ + Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); + return(NOEXCEPTION); + } + /* + * check for division by zero + */ + if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) { + if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) { + /* invalid since both operands are zero */ + if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); + Set_invalidflag(); + Dbl_makequietnan(resultp1,resultp2); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + if (Is_divisionbyzerotrap_enabled()) + return(DIVISIONBYZEROEXCEPTION); + Set_divisionbyzeroflag(); + Dbl_setinfinity_exponentmantissa(resultp1,resultp2); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + /* + * Generate exponent + */ + dest_exponent = Dbl_exponent(opnd1p1) - Dbl_exponent(opnd2p1) + DBL_BIAS; + + /* + * Generate mantissa + */ + if (Dbl_isnotzero_exponent(opnd1p1)) { + /* set hidden bit */ + Dbl_clear_signexponent_set_hidden(opnd1p1); + } + else { + /* check for zero */ + if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { + Dbl_setzero_exponentmantissa(resultp1,resultp2); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + /* is denormalized, want to normalize */ + Dbl_clear_signexponent(opnd1p1); + Dbl_leftshiftby1(opnd1p1,opnd1p2); + Dbl_normalize(opnd1p1,opnd1p2,dest_exponent); + } + /* opnd2 needs to have hidden bit set with msb in hidden bit */ + if (Dbl_isnotzero_exponent(opnd2p1)) { + Dbl_clear_signexponent_set_hidden(opnd2p1); + } + else { + /* is denormalized; want to normalize */ + Dbl_clear_signexponent(opnd2p1); + Dbl_leftshiftby1(opnd2p1,opnd2p2); + while (Dbl_iszero_hiddenhigh7mantissa(opnd2p1)) { + dest_exponent+=8; + Dbl_leftshiftby8(opnd2p1,opnd2p2); + } + if (Dbl_iszero_hiddenhigh3mantissa(opnd2p1)) { + dest_exponent+=4; + Dbl_leftshiftby4(opnd2p1,opnd2p2); + } + while (Dbl_iszero_hidden(opnd2p1)) { + dest_exponent++; + Dbl_leftshiftby1(opnd2p1,opnd2p2); + } + } + + /* Divide the source mantissas */ + + /* + * A non-restoring divide algorithm is used. + */ + Twoword_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2); + Dbl_setzero(opnd3p1,opnd3p2); + for (count=1; count <= DBL_P && (opnd1p1 || opnd1p2); count++) { + Dbl_leftshiftby1(opnd1p1,opnd1p2); + Dbl_leftshiftby1(opnd3p1,opnd3p2); + if (Dbl_iszero_sign(opnd1p1)) { + Dbl_setone_lowmantissap2(opnd3p2); + Twoword_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2); + } + else { + Twoword_add(opnd1p1, opnd1p2, opnd2p1, opnd2p2); + } + } + if (count <= DBL_P) { + Dbl_leftshiftby1(opnd3p1,opnd3p2); + Dbl_setone_lowmantissap2(opnd3p2); + Dbl_leftshift(opnd3p1,opnd3p2,(DBL_P-count)); + if (Dbl_iszero_hidden(opnd3p1)) { + Dbl_leftshiftby1(opnd3p1,opnd3p2); + dest_exponent--; + } + } + else { + if (Dbl_iszero_hidden(opnd3p1)) { + /* need to get one more bit of result */ + Dbl_leftshiftby1(opnd1p1,opnd1p2); + Dbl_leftshiftby1(opnd3p1,opnd3p2); + if (Dbl_iszero_sign(opnd1p1)) { + Dbl_setone_lowmantissap2(opnd3p2); + Twoword_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2); + } + else { + Twoword_add(opnd1p1,opnd1p2,opnd2p1,opnd2p2); + } + dest_exponent--; + } + if (Dbl_iszero_sign(opnd1p1)) guardbit = TRUE; + stickybit = Dbl_allp1(opnd1p1) || Dbl_allp2(opnd1p2); + } + inexact = guardbit | stickybit; + + /* + * round result + */ + if (inexact && (dest_exponent > 0 || Is_underflowtrap_enabled())) { + Dbl_clear_signexponent(opnd3p1); + switch (Rounding_mode()) { + case ROUNDPLUS: + if (Dbl_iszero_sign(resultp1)) + Dbl_increment(opnd3p1,opnd3p2); + break; + case ROUNDMINUS: + if (Dbl_isone_sign(resultp1)) + Dbl_increment(opnd3p1,opnd3p2); + break; + case ROUNDNEAREST: + if (guardbit && (stickybit || + Dbl_isone_lowmantissap2(opnd3p2))) { + Dbl_increment(opnd3p1,opnd3p2); + } + } + if (Dbl_isone_hidden(opnd3p1)) dest_exponent++; + } + Dbl_set_mantissa(resultp1,resultp2,opnd3p1,opnd3p2); + + /* + * Test for overflow + */ + if (dest_exponent >= DBL_INFINITY_EXPONENT) { + /* trap if OVERFLOWTRAP enabled */ + if (Is_overflowtrap_enabled()) { + /* + * Adjust bias of result + */ + Dbl_setwrapped_exponent(resultp1,dest_exponent,ovfl); + Dbl_copytoptr(resultp1,resultp2,dstptr); + if (inexact) + if (Is_inexacttrap_enabled()) + return(OVERFLOWEXCEPTION | INEXACTEXCEPTION); + else Set_inexactflag(); + return(OVERFLOWEXCEPTION); + } + Set_overflowflag(); + /* set result to infinity or largest number */ + Dbl_setoverflow(resultp1,resultp2); + inexact = TRUE; + } + /* + * Test for underflow + */ + else if (dest_exponent <= 0) { + /* trap if UNDERFLOWTRAP enabled */ + if (Is_underflowtrap_enabled()) { + /* + * Adjust bias of result + */ + Dbl_setwrapped_exponent(resultp1,dest_exponent,unfl); + Dbl_copytoptr(resultp1,resultp2,dstptr); + if (inexact) + if (Is_inexacttrap_enabled()) + return(UNDERFLOWEXCEPTION | INEXACTEXCEPTION); + else Set_inexactflag(); + return(UNDERFLOWEXCEPTION); + } + + /* Determine if should set underflow flag */ + is_tiny = TRUE; + if (dest_exponent == 0 && inexact) { + switch (Rounding_mode()) { + case ROUNDPLUS: + if (Dbl_iszero_sign(resultp1)) { + Dbl_increment(opnd3p1,opnd3p2); + if (Dbl_isone_hiddenoverflow(opnd3p1)) + is_tiny = FALSE; + Dbl_decrement(opnd3p1,opnd3p2); + } + break; + case ROUNDMINUS: + if (Dbl_isone_sign(resultp1)) { + Dbl_increment(opnd3p1,opnd3p2); + if (Dbl_isone_hiddenoverflow(opnd3p1)) + is_tiny = FALSE; + Dbl_decrement(opnd3p1,opnd3p2); + } + break; + case ROUNDNEAREST: + if (guardbit && (stickybit || + Dbl_isone_lowmantissap2(opnd3p2))) { + Dbl_increment(opnd3p1,opnd3p2); + if (Dbl_isone_hiddenoverflow(opnd3p1)) + is_tiny = FALSE; + Dbl_decrement(opnd3p1,opnd3p2); + } + break; + } + } + + /* + * denormalize result or set to signed zero + */ + stickybit = inexact; + Dbl_denormalize(opnd3p1,opnd3p2,dest_exponent,guardbit, + stickybit,inexact); + + /* return rounded number */ + if (inexact) { + switch (Rounding_mode()) { + case ROUNDPLUS: + if (Dbl_iszero_sign(resultp1)) { + Dbl_increment(opnd3p1,opnd3p2); + } + break; + case ROUNDMINUS: + if (Dbl_isone_sign(resultp1)) { + Dbl_increment(opnd3p1,opnd3p2); + } + break; + case ROUNDNEAREST: + if (guardbit && (stickybit || + Dbl_isone_lowmantissap2(opnd3p2))) { + Dbl_increment(opnd3p1,opnd3p2); + } + break; + } + if (is_tiny) Set_underflowflag(); + } + Dbl_set_exponentmantissa(resultp1,resultp2,opnd3p1,opnd3p2); + } + else Dbl_set_exponent(resultp1,dest_exponent); + Dbl_copytoptr(resultp1,resultp2,dstptr); + + /* check for inexact */ + if (inexact) { + if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + } + return(NOEXCEPTION); +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/dfmpy.c linux.19rc3-ac4/arch/parisc/math-emu/dfmpy.c --- linux.19rc3/arch/parisc/math-emu/dfmpy.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/dfmpy.c 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,394 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * BEGIN_DESC + * + * File: + * @(#) pa/spmath/dfmpy.c $Revision: 1.1 $ + * + * Purpose: + * Double Precision Floating-point Multiply + * + * External Interfaces: + * dbl_fmpy(srcptr1,srcptr2,dstptr,status) + * + * Internal Interfaces: + * + * Theory: + * <> + * + * END_DESC +*/ + + +#include "float.h" +#include "dbl_float.h" + +/* + * Double Precision Floating-point Multiply + */ + +int +dbl_fmpy( + dbl_floating_point *srcptr1, + dbl_floating_point *srcptr2, + dbl_floating_point *dstptr, + unsigned int *status) +{ + register unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2; + register unsigned int opnd3p1, opnd3p2, resultp1, resultp2; + register int dest_exponent, count; + register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE; + boolean is_tiny; + + Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2); + Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2); + + /* + * set sign bit of result + */ + if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1)) + Dbl_setnegativezerop1(resultp1); + else Dbl_setzerop1(resultp1); + /* + * check first operand for NaN's or infinity + */ + if (Dbl_isinfinity_exponent(opnd1p1)) { + if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { + if (Dbl_isnotnan(opnd2p1,opnd2p2)) { + if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) { + /* + * invalid since operands are infinity + * and zero + */ + if (Is_invalidtrap_enabled()) + return(INVALIDEXCEPTION); + Set_invalidflag(); + Dbl_makequietnan(resultp1,resultp2); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + /* + * return infinity + */ + Dbl_setinfinity_exponentmantissa(resultp1,resultp2); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + } + else { + /* + * is NaN; signaling or quiet? + */ + if (Dbl_isone_signaling(opnd1p1)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Dbl_set_quiet(opnd1p1); + } + /* + * is second operand a signaling NaN? + */ + else if (Dbl_is_signalingnan(opnd2p1)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Dbl_set_quiet(opnd2p1); + Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); + return(NOEXCEPTION); + } + /* + * return quiet NaN + */ + Dbl_copytoptr(opnd1p1,opnd1p2,dstptr); + return(NOEXCEPTION); + } + } + /* + * check second operand for NaN's or infinity + */ + if (Dbl_isinfinity_exponent(opnd2p1)) { + if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) { + if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) { + /* invalid since operands are zero & infinity */ + if (Is_invalidtrap_enabled()) + return(INVALIDEXCEPTION); + Set_invalidflag(); + Dbl_makequietnan(opnd2p1,opnd2p2); + Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); + return(NOEXCEPTION); + } + /* + * return infinity + */ + Dbl_setinfinity_exponentmantissa(resultp1,resultp2); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + /* + * is NaN; signaling or quiet? + */ + if (Dbl_isone_signaling(opnd2p1)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Dbl_set_quiet(opnd2p1); + } + /* + * return quiet NaN + */ + Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); + return(NOEXCEPTION); + } + /* + * Generate exponent + */ + dest_exponent = Dbl_exponent(opnd1p1) + Dbl_exponent(opnd2p1) -DBL_BIAS; + + /* + * Generate mantissa + */ + if (Dbl_isnotzero_exponent(opnd1p1)) { + /* set hidden bit */ + Dbl_clear_signexponent_set_hidden(opnd1p1); + } + else { + /* check for zero */ + if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { + Dbl_setzero_exponentmantissa(resultp1,resultp2); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + /* is denormalized, adjust exponent */ + Dbl_clear_signexponent(opnd1p1); + Dbl_leftshiftby1(opnd1p1,opnd1p2); + Dbl_normalize(opnd1p1,opnd1p2,dest_exponent); + } + /* opnd2 needs to have hidden bit set with msb in hidden bit */ + if (Dbl_isnotzero_exponent(opnd2p1)) { + Dbl_clear_signexponent_set_hidden(opnd2p1); + } + else { + /* check for zero */ + if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) { + Dbl_setzero_exponentmantissa(resultp1,resultp2); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + /* is denormalized; want to normalize */ + Dbl_clear_signexponent(opnd2p1); + Dbl_leftshiftby1(opnd2p1,opnd2p2); + Dbl_normalize(opnd2p1,opnd2p2,dest_exponent); + } + + /* Multiply two source mantissas together */ + + /* make room for guard bits */ + Dbl_leftshiftby7(opnd2p1,opnd2p2); + Dbl_setzero(opnd3p1,opnd3p2); + /* + * Four bits at a time are inspected in each loop, and a + * simple shift and add multiply algorithm is used. + */ + for (count=1;count<=DBL_P;count+=4) { + stickybit |= Dlow4p2(opnd3p2); + Dbl_rightshiftby4(opnd3p1,opnd3p2); + if (Dbit28p2(opnd1p2)) { + /* Twoword_add should be an ADDC followed by an ADD. */ + Twoword_add(opnd3p1, opnd3p2, opnd2p1<<3 | opnd2p2>>29, + opnd2p2<<3); + } + if (Dbit29p2(opnd1p2)) { + Twoword_add(opnd3p1, opnd3p2, opnd2p1<<2 | opnd2p2>>30, + opnd2p2<<2); + } + if (Dbit30p2(opnd1p2)) { + Twoword_add(opnd3p1, opnd3p2, opnd2p1<<1 | opnd2p2>>31, + opnd2p2<<1); + } + if (Dbit31p2(opnd1p2)) { + Twoword_add(opnd3p1, opnd3p2, opnd2p1, opnd2p2); + } + Dbl_rightshiftby4(opnd1p1,opnd1p2); + } + if (Dbit3p1(opnd3p1)==0) { + Dbl_leftshiftby1(opnd3p1,opnd3p2); + } + else { + /* result mantissa >= 2. */ + dest_exponent++; + } + /* check for denormalized result */ + while (Dbit3p1(opnd3p1)==0) { + Dbl_leftshiftby1(opnd3p1,opnd3p2); + dest_exponent--; + } + /* + * check for guard, sticky and inexact bits + */ + stickybit |= Dallp2(opnd3p2) << 25; + guardbit = (Dallp2(opnd3p2) << 24) >> 31; + inexact = guardbit | stickybit; + + /* align result mantissa */ + Dbl_rightshiftby8(opnd3p1,opnd3p2); + + /* + * round result + */ + if (inexact && (dest_exponent>0 || Is_underflowtrap_enabled())) { + Dbl_clear_signexponent(opnd3p1); + switch (Rounding_mode()) { + case ROUNDPLUS: + if (Dbl_iszero_sign(resultp1)) + Dbl_increment(opnd3p1,opnd3p2); + break; + case ROUNDMINUS: + if (Dbl_isone_sign(resultp1)) + Dbl_increment(opnd3p1,opnd3p2); + break; + case ROUNDNEAREST: + if (guardbit) { + if (stickybit || Dbl_isone_lowmantissap2(opnd3p2)) + Dbl_increment(opnd3p1,opnd3p2); + } + } + if (Dbl_isone_hidden(opnd3p1)) dest_exponent++; + } + Dbl_set_mantissa(resultp1,resultp2,opnd3p1,opnd3p2); + + /* + * Test for overflow + */ + if (dest_exponent >= DBL_INFINITY_EXPONENT) { + /* trap if OVERFLOWTRAP enabled */ + if (Is_overflowtrap_enabled()) { + /* + * Adjust bias of result + */ + Dbl_setwrapped_exponent(resultp1,dest_exponent,ovfl); + Dbl_copytoptr(resultp1,resultp2,dstptr); + if (inexact) + if (Is_inexacttrap_enabled()) + return (OVERFLOWEXCEPTION | INEXACTEXCEPTION); + else Set_inexactflag(); + return (OVERFLOWEXCEPTION); + } + inexact = TRUE; + Set_overflowflag(); + /* set result to infinity or largest number */ + Dbl_setoverflow(resultp1,resultp2); + } + /* + * Test for underflow + */ + else if (dest_exponent <= 0) { + /* trap if UNDERFLOWTRAP enabled */ + if (Is_underflowtrap_enabled()) { + /* + * Adjust bias of result + */ + Dbl_setwrapped_exponent(resultp1,dest_exponent,unfl); + Dbl_copytoptr(resultp1,resultp2,dstptr); + if (inexact) + if (Is_inexacttrap_enabled()) + return (UNDERFLOWEXCEPTION | INEXACTEXCEPTION); + else Set_inexactflag(); + return (UNDERFLOWEXCEPTION); + } + + /* Determine if should set underflow flag */ + is_tiny = TRUE; + if (dest_exponent == 0 && inexact) { + switch (Rounding_mode()) { + case ROUNDPLUS: + if (Dbl_iszero_sign(resultp1)) { + Dbl_increment(opnd3p1,opnd3p2); + if (Dbl_isone_hiddenoverflow(opnd3p1)) + is_tiny = FALSE; + Dbl_decrement(opnd3p1,opnd3p2); + } + break; + case ROUNDMINUS: + if (Dbl_isone_sign(resultp1)) { + Dbl_increment(opnd3p1,opnd3p2); + if (Dbl_isone_hiddenoverflow(opnd3p1)) + is_tiny = FALSE; + Dbl_decrement(opnd3p1,opnd3p2); + } + break; + case ROUNDNEAREST: + if (guardbit && (stickybit || + Dbl_isone_lowmantissap2(opnd3p2))) { + Dbl_increment(opnd3p1,opnd3p2); + if (Dbl_isone_hiddenoverflow(opnd3p1)) + is_tiny = FALSE; + Dbl_decrement(opnd3p1,opnd3p2); + } + break; + } + } + + /* + * denormalize result or set to signed zero + */ + stickybit = inexact; + Dbl_denormalize(opnd3p1,opnd3p2,dest_exponent,guardbit, + stickybit,inexact); + + /* return zero or smallest number */ + if (inexact) { + switch (Rounding_mode()) { + case ROUNDPLUS: + if (Dbl_iszero_sign(resultp1)) { + Dbl_increment(opnd3p1,opnd3p2); + } + break; + case ROUNDMINUS: + if (Dbl_isone_sign(resultp1)) { + Dbl_increment(opnd3p1,opnd3p2); + } + break; + case ROUNDNEAREST: + if (guardbit && (stickybit || + Dbl_isone_lowmantissap2(opnd3p2))) { + Dbl_increment(opnd3p1,opnd3p2); + } + break; + } + if (is_tiny) Set_underflowflag(); + } + Dbl_set_exponentmantissa(resultp1,resultp2,opnd3p1,opnd3p2); + } + else Dbl_set_exponent(resultp1,dest_exponent); + /* check for inexact */ + Dbl_copytoptr(resultp1,resultp2,dstptr); + if (inexact) { + if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + } + return(NOEXCEPTION); +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/dfrem.c linux.19rc3-ac4/arch/parisc/math-emu/dfrem.c --- linux.19rc3/arch/parisc/math-emu/dfrem.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/dfrem.c 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,297 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * BEGIN_DESC + * + * File: + * @(#) pa/spmath/dfrem.c $Revision: 1.1 $ + * + * Purpose: + * Double Precision Floating-point Remainder + * + * External Interfaces: + * dbl_frem(srcptr1,srcptr2,dstptr,status) + * + * Internal Interfaces: + * + * Theory: + * <> + * + * END_DESC +*/ + + + +#include "float.h" +#include "dbl_float.h" + +/* + * Double Precision Floating-point Remainder + */ + +int +dbl_frem (dbl_floating_point * srcptr1, dbl_floating_point * srcptr2, + dbl_floating_point * dstptr, unsigned int *status) +{ + register unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2; + register unsigned int resultp1, resultp2; + register int opnd1_exponent, opnd2_exponent, dest_exponent, stepcount; + register boolean roundup = FALSE; + + Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2); + Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2); + /* + * check first operand for NaN's or infinity + */ + if ((opnd1_exponent = Dbl_exponent(opnd1p1)) == DBL_INFINITY_EXPONENT) { + if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { + if (Dbl_isnotnan(opnd2p1,opnd2p2)) { + /* invalid since first operand is infinity */ + if (Is_invalidtrap_enabled()) + return(INVALIDEXCEPTION); + Set_invalidflag(); + Dbl_makequietnan(resultp1,resultp2); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + } + else { + /* + * is NaN; signaling or quiet? + */ + if (Dbl_isone_signaling(opnd1p1)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Dbl_set_quiet(opnd1p1); + } + /* + * is second operand a signaling NaN? + */ + else if (Dbl_is_signalingnan(opnd2p1)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Dbl_set_quiet(opnd2p1); + Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); + return(NOEXCEPTION); + } + /* + * return quiet NaN + */ + Dbl_copytoptr(opnd1p1,opnd1p2,dstptr); + return(NOEXCEPTION); + } + } + /* + * check second operand for NaN's or infinity + */ + if ((opnd2_exponent = Dbl_exponent(opnd2p1)) == DBL_INFINITY_EXPONENT) { + if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) { + /* + * return first operand + */ + Dbl_copytoptr(opnd1p1,opnd1p2,dstptr); + return(NOEXCEPTION); + } + /* + * is NaN; signaling or quiet? + */ + if (Dbl_isone_signaling(opnd2p1)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Dbl_set_quiet(opnd2p1); + } + /* + * return quiet NaN + */ + Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); + return(NOEXCEPTION); + } + /* + * check second operand for zero + */ + if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) { + /* invalid since second operand is zero */ + if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); + Set_invalidflag(); + Dbl_makequietnan(resultp1,resultp2); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + + /* + * get sign of result + */ + resultp1 = opnd1p1; + + /* + * check for denormalized operands + */ + if (opnd1_exponent == 0) { + /* check for zero */ + if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { + Dbl_copytoptr(opnd1p1,opnd1p2,dstptr); + return(NOEXCEPTION); + } + /* normalize, then continue */ + opnd1_exponent = 1; + Dbl_normalize(opnd1p1,opnd1p2,opnd1_exponent); + } + else { + Dbl_clear_signexponent_set_hidden(opnd1p1); + } + if (opnd2_exponent == 0) { + /* normalize, then continue */ + opnd2_exponent = 1; + Dbl_normalize(opnd2p1,opnd2p2,opnd2_exponent); + } + else { + Dbl_clear_signexponent_set_hidden(opnd2p1); + } + + /* find result exponent and divide step loop count */ + dest_exponent = opnd2_exponent - 1; + stepcount = opnd1_exponent - opnd2_exponent; + + /* + * check for opnd1/opnd2 < 1 + */ + if (stepcount < 0) { + /* + * check for opnd1/opnd2 > 1/2 + * + * In this case n will round to 1, so + * r = opnd1 - opnd2 + */ + if (stepcount == -1 && + Dbl_isgreaterthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) { + /* set sign */ + Dbl_allp1(resultp1) = ~Dbl_allp1(resultp1); + /* align opnd2 with opnd1 */ + Dbl_leftshiftby1(opnd2p1,opnd2p2); + Dbl_subtract(opnd2p1,opnd2p2,opnd1p1,opnd1p2, + opnd2p1,opnd2p2); + /* now normalize */ + while (Dbl_iszero_hidden(opnd2p1)) { + Dbl_leftshiftby1(opnd2p1,opnd2p2); + dest_exponent--; + } + Dbl_set_exponentmantissa(resultp1,resultp2,opnd2p1,opnd2p2); + goto testforunderflow; + } + /* + * opnd1/opnd2 <= 1/2 + * + * In this case n will round to zero, so + * r = opnd1 + */ + Dbl_set_exponentmantissa(resultp1,resultp2,opnd1p1,opnd1p2); + dest_exponent = opnd1_exponent; + goto testforunderflow; + } + + /* + * Generate result + * + * Do iterative subtract until remainder is less than operand 2. + */ + while (stepcount-- > 0 && (Dbl_allp1(opnd1p1) || Dbl_allp2(opnd1p2))) { + if (Dbl_isnotlessthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) { + Dbl_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2,opnd1p1,opnd1p2); + } + Dbl_leftshiftby1(opnd1p1,opnd1p2); + } + /* + * Do last subtract, then determine which way to round if remainder + * is exactly 1/2 of opnd2 + */ + if (Dbl_isnotlessthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) { + Dbl_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2,opnd1p1,opnd1p2); + roundup = TRUE; + } + if (stepcount > 0 || Dbl_iszero(opnd1p1,opnd1p2)) { + /* division is exact, remainder is zero */ + Dbl_setzero_exponentmantissa(resultp1,resultp2); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + + /* + * Check for cases where opnd1/opnd2 < n + * + * In this case the result's sign will be opposite that of + * opnd1. The mantissa also needs some correction. + */ + Dbl_leftshiftby1(opnd1p1,opnd1p2); + if (Dbl_isgreaterthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) { + Dbl_invert_sign(resultp1); + Dbl_leftshiftby1(opnd2p1,opnd2p2); + Dbl_subtract(opnd2p1,opnd2p2,opnd1p1,opnd1p2,opnd1p1,opnd1p2); + } + /* check for remainder being exactly 1/2 of opnd2 */ + else if (Dbl_isequal(opnd1p1,opnd1p2,opnd2p1,opnd2p2) && roundup) { + Dbl_invert_sign(resultp1); + } + + /* normalize result's mantissa */ + while (Dbl_iszero_hidden(opnd1p1)) { + dest_exponent--; + Dbl_leftshiftby1(opnd1p1,opnd1p2); + } + Dbl_set_exponentmantissa(resultp1,resultp2,opnd1p1,opnd1p2); + + /* + * Test for underflow + */ + testforunderflow: + if (dest_exponent <= 0) { + /* trap if UNDERFLOWTRAP enabled */ + if (Is_underflowtrap_enabled()) { + /* + * Adjust bias of result + */ + Dbl_setwrapped_exponent(resultp1,dest_exponent,unfl); + /* frem is always exact */ + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(UNDERFLOWEXCEPTION); + } + /* + * denormalize result or set to signed zero + */ + if (dest_exponent >= (1 - DBL_P)) { + Dbl_rightshift_exponentmantissa(resultp1,resultp2, + 1-dest_exponent); + } + else { + Dbl_setzero_exponentmantissa(resultp1,resultp2); + } + } + else Dbl_set_exponent(resultp1,dest_exponent); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/dfsqrt.c linux.19rc3-ac4/arch/parisc/math-emu/dfsqrt.c --- linux.19rc3/arch/parisc/math-emu/dfsqrt.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/dfsqrt.c 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,195 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * BEGIN_DESC + * + * File: + * @(#) pa/spmath/dfsqrt.c $Revision: 1.1 $ + * + * Purpose: + * Double Floating-point Square Root + * + * External Interfaces: + * dbl_fsqrt(srcptr,nullptr,dstptr,status) + * + * Internal Interfaces: + * + * Theory: + * <> + * + * END_DESC +*/ + + +#include "float.h" +#include "dbl_float.h" + +/* + * Double Floating-point Square Root + */ + +/*ARGSUSED*/ +unsigned int +dbl_fsqrt( + dbl_floating_point *srcptr, + unsigned int *nullptr, + dbl_floating_point *dstptr, + unsigned int *status) +{ + register unsigned int srcp1, srcp2, resultp1, resultp2; + register unsigned int newbitp1, newbitp2, sump1, sump2; + register int src_exponent; + register boolean guardbit = FALSE, even_exponent; + + Dbl_copyfromptr(srcptr,srcp1,srcp2); + /* + * check source operand for NaN or infinity + */ + if ((src_exponent = Dbl_exponent(srcp1)) == DBL_INFINITY_EXPONENT) { + /* + * is signaling NaN? + */ + if (Dbl_isone_signaling(srcp1)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Dbl_set_quiet(srcp1); + } + /* + * Return quiet NaN or positive infinity. + * Fall thru to negative test if negative infinity. + */ + if (Dbl_iszero_sign(srcp1) || + Dbl_isnotzero_mantissa(srcp1,srcp2)) { + Dbl_copytoptr(srcp1,srcp2,dstptr); + return(NOEXCEPTION); + } + } + + /* + * check for zero source operand + */ + if (Dbl_iszero_exponentmantissa(srcp1,srcp2)) { + Dbl_copytoptr(srcp1,srcp2,dstptr); + return(NOEXCEPTION); + } + + /* + * check for negative source operand + */ + if (Dbl_isone_sign(srcp1)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Dbl_makequietnan(srcp1,srcp2); + Dbl_copytoptr(srcp1,srcp2,dstptr); + return(NOEXCEPTION); + } + + /* + * Generate result + */ + if (src_exponent > 0) { + even_exponent = Dbl_hidden(srcp1); + Dbl_clear_signexponent_set_hidden(srcp1); + } + else { + /* normalize operand */ + Dbl_clear_signexponent(srcp1); + src_exponent++; + Dbl_normalize(srcp1,srcp2,src_exponent); + even_exponent = src_exponent & 1; + } + if (even_exponent) { + /* exponent is even */ + /* Add comment here. Explain why odd exponent needs correction */ + Dbl_leftshiftby1(srcp1,srcp2); + } + /* + * Add comment here. Explain following algorithm. + * + * Trust me, it works. + * + */ + Dbl_setzero(resultp1,resultp2); + Dbl_allp1(newbitp1) = 1 << (DBL_P - 32); + Dbl_setzero_mantissap2(newbitp2); + while (Dbl_isnotzero(newbitp1,newbitp2) && Dbl_isnotzero(srcp1,srcp2)) { + Dbl_addition(resultp1,resultp2,newbitp1,newbitp2,sump1,sump2); + if(Dbl_isnotgreaterthan(sump1,sump2,srcp1,srcp2)) { + Dbl_leftshiftby1(newbitp1,newbitp2); + /* update result */ + Dbl_addition(resultp1,resultp2,newbitp1,newbitp2, + resultp1,resultp2); + Dbl_subtract(srcp1,srcp2,sump1,sump2,srcp1,srcp2); + Dbl_rightshiftby2(newbitp1,newbitp2); + } + else { + Dbl_rightshiftby1(newbitp1,newbitp2); + } + Dbl_leftshiftby1(srcp1,srcp2); + } + /* correct exponent for pre-shift */ + if (even_exponent) { + Dbl_rightshiftby1(resultp1,resultp2); + } + + /* check for inexact */ + if (Dbl_isnotzero(srcp1,srcp2)) { + if (!even_exponent && Dbl_islessthan(resultp1,resultp2,srcp1,srcp2)) { + Dbl_increment(resultp1,resultp2); + } + guardbit = Dbl_lowmantissap2(resultp2); + Dbl_rightshiftby1(resultp1,resultp2); + + /* now round result */ + switch (Rounding_mode()) { + case ROUNDPLUS: + Dbl_increment(resultp1,resultp2); + break; + case ROUNDNEAREST: + /* stickybit is always true, so guardbit + * is enough to determine rounding */ + if (guardbit) { + Dbl_increment(resultp1,resultp2); + } + break; + } + /* increment result exponent by 1 if mantissa overflowed */ + if (Dbl_isone_hiddenoverflow(resultp1)) src_exponent+=2; + + if (Is_inexacttrap_enabled()) { + Dbl_set_exponent(resultp1, + ((src_exponent-DBL_BIAS)>>1)+DBL_BIAS); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(INEXACTEXCEPTION); + } + else Set_inexactflag(); + } + else { + Dbl_rightshiftby1(resultp1,resultp2); + } + Dbl_set_exponent(resultp1,((src_exponent-DBL_BIAS)>>1)+DBL_BIAS); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/dfsub.c linux.19rc3-ac4/arch/parisc/math-emu/dfsub.c --- linux.19rc3/arch/parisc/math-emu/dfsub.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/dfsub.c 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,526 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * BEGIN_DESC + * + * File: + * @(#) pa/spmath/dfsub.c $Revision: 1.1 $ + * + * Purpose: + * Double_subtract: subtract two double precision values. + * + * External Interfaces: + * dbl_fsub(leftptr, rightptr, dstptr, status) + * + * Internal Interfaces: + * + * Theory: + * <> + * + * END_DESC +*/ + + +#include "float.h" +#include "dbl_float.h" + +/* + * Double_subtract: subtract two double precision values. + */ +int +dbl_fsub( + dbl_floating_point *leftptr, + dbl_floating_point *rightptr, + dbl_floating_point *dstptr, + unsigned int *status) + { + register unsigned int signless_upper_left, signless_upper_right, save; + register unsigned int leftp1, leftp2, rightp1, rightp2, extent; + register unsigned int resultp1 = 0, resultp2 = 0; + + register int result_exponent, right_exponent, diff_exponent; + register int sign_save, jumpsize; + register boolean inexact = FALSE, underflowtrap; + + /* Create local copies of the numbers */ + Dbl_copyfromptr(leftptr,leftp1,leftp2); + Dbl_copyfromptr(rightptr,rightp1,rightp2); + + /* A zero "save" helps discover equal operands (for later), * + * and is used in swapping operands (if needed). */ + Dbl_xortointp1(leftp1,rightp1,/*to*/save); + + /* + * check first operand for NaN's or infinity + */ + if ((result_exponent = Dbl_exponent(leftp1)) == DBL_INFINITY_EXPONENT) + { + if (Dbl_iszero_mantissa(leftp1,leftp2)) + { + if (Dbl_isnotnan(rightp1,rightp2)) + { + if (Dbl_isinfinity(rightp1,rightp2) && save==0) + { + /* + * invalid since operands are same signed infinity's + */ + if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); + Set_invalidflag(); + Dbl_makequietnan(resultp1,resultp2); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + /* + * return infinity + */ + Dbl_copytoptr(leftp1,leftp2,dstptr); + return(NOEXCEPTION); + } + } + else + { + /* + * is NaN; signaling or quiet? + */ + if (Dbl_isone_signaling(leftp1)) + { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Dbl_set_quiet(leftp1); + } + /* + * is second operand a signaling NaN? + */ + else if (Dbl_is_signalingnan(rightp1)) + { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Dbl_set_quiet(rightp1); + Dbl_copytoptr(rightp1,rightp2,dstptr); + return(NOEXCEPTION); + } + /* + * return quiet NaN + */ + Dbl_copytoptr(leftp1,leftp2,dstptr); + return(NOEXCEPTION); + } + } /* End left NaN or Infinity processing */ + /* + * check second operand for NaN's or infinity + */ + if (Dbl_isinfinity_exponent(rightp1)) + { + if (Dbl_iszero_mantissa(rightp1,rightp2)) + { + /* return infinity */ + Dbl_invert_sign(rightp1); + Dbl_copytoptr(rightp1,rightp2,dstptr); + return(NOEXCEPTION); + } + /* + * is NaN; signaling or quiet? + */ + if (Dbl_isone_signaling(rightp1)) + { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Dbl_set_quiet(rightp1); + } + /* + * return quiet NaN + */ + Dbl_copytoptr(rightp1,rightp2,dstptr); + return(NOEXCEPTION); + } /* End right NaN or Infinity processing */ + + /* Invariant: Must be dealing with finite numbers */ + + /* Compare operands by removing the sign */ + Dbl_copytoint_exponentmantissap1(leftp1,signless_upper_left); + Dbl_copytoint_exponentmantissap1(rightp1,signless_upper_right); + + /* sign difference selects add or sub operation. */ + if(Dbl_ismagnitudeless(leftp2,rightp2,signless_upper_left,signless_upper_right)) + { + /* Set the left operand to the larger one by XOR swap * + * First finish the first word using "save" */ + Dbl_xorfromintp1(save,rightp1,/*to*/rightp1); + Dbl_xorfromintp1(save,leftp1,/*to*/leftp1); + Dbl_swap_lower(leftp2,rightp2); + result_exponent = Dbl_exponent(leftp1); + Dbl_invert_sign(leftp1); + } + /* Invariant: left is not smaller than right. */ + + if((right_exponent = Dbl_exponent(rightp1)) == 0) + { + /* Denormalized operands. First look for zeroes */ + if(Dbl_iszero_mantissa(rightp1,rightp2)) + { + /* right is zero */ + if(Dbl_iszero_exponentmantissa(leftp1,leftp2)) + { + /* Both operands are zeros */ + Dbl_invert_sign(rightp1); + if(Is_rounding_mode(ROUNDMINUS)) + { + Dbl_or_signs(leftp1,/*with*/rightp1); + } + else + { + Dbl_and_signs(leftp1,/*with*/rightp1); + } + } + else + { + /* Left is not a zero and must be the result. Trapped + * underflows are signaled if left is denormalized. Result + * is always exact. */ + if( (result_exponent == 0) && Is_underflowtrap_enabled() ) + { + /* need to normalize results mantissa */ + sign_save = Dbl_signextendedsign(leftp1); + Dbl_leftshiftby1(leftp1,leftp2); + Dbl_normalize(leftp1,leftp2,result_exponent); + Dbl_set_sign(leftp1,/*using*/sign_save); + Dbl_setwrapped_exponent(leftp1,result_exponent,unfl); + Dbl_copytoptr(leftp1,leftp2,dstptr); + /* inexact = FALSE */ + return(UNDERFLOWEXCEPTION); + } + } + Dbl_copytoptr(leftp1,leftp2,dstptr); + return(NOEXCEPTION); + } + + /* Neither are zeroes */ + Dbl_clear_sign(rightp1); /* Exponent is already cleared */ + if(result_exponent == 0 ) + { + /* Both operands are denormalized. The result must be exact + * and is simply calculated. A sum could become normalized and a + * difference could cancel to a true zero. */ + if( (/*signed*/int) save >= 0 ) + { + Dbl_subtract(leftp1,leftp2,/*minus*/rightp1,rightp2, + /*into*/resultp1,resultp2); + if(Dbl_iszero_mantissa(resultp1,resultp2)) + { + if(Is_rounding_mode(ROUNDMINUS)) + { + Dbl_setone_sign(resultp1); + } + else + { + Dbl_setzero_sign(resultp1); + } + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + } + else + { + Dbl_addition(leftp1,leftp2,rightp1,rightp2, + /*into*/resultp1,resultp2); + if(Dbl_isone_hidden(resultp1)) + { + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + } + if(Is_underflowtrap_enabled()) + { + /* need to normalize result */ + sign_save = Dbl_signextendedsign(resultp1); + Dbl_leftshiftby1(resultp1,resultp2); + Dbl_normalize(resultp1,resultp2,result_exponent); + Dbl_set_sign(resultp1,/*using*/sign_save); + Dbl_setwrapped_exponent(resultp1,result_exponent,unfl); + Dbl_copytoptr(resultp1,resultp2,dstptr); + /* inexact = FALSE */ + return(UNDERFLOWEXCEPTION); + } + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + right_exponent = 1; /* Set exponent to reflect different bias + * with denomalized numbers. */ + } + else + { + Dbl_clear_signexponent_set_hidden(rightp1); + } + Dbl_clear_exponent_set_hidden(leftp1); + diff_exponent = result_exponent - right_exponent; + + /* + * Special case alignment of operands that would force alignment + * beyond the extent of the extension. A further optimization + * could special case this but only reduces the path length for this + * infrequent case. + */ + if(diff_exponent > DBL_THRESHOLD) + { + diff_exponent = DBL_THRESHOLD; + } + + /* Align right operand by shifting to right */ + Dbl_right_align(/*operand*/rightp1,rightp2,/*shifted by*/diff_exponent, + /*and lower to*/extent); + + /* Treat sum and difference of the operands separately. */ + if( (/*signed*/int) save >= 0 ) + { + /* + * Difference of the two operands. Their can be no overflow. A + * borrow can occur out of the hidden bit and force a post + * normalization phase. + */ + Dbl_subtract_withextension(leftp1,leftp2,/*minus*/rightp1,rightp2, + /*with*/extent,/*into*/resultp1,resultp2); + if(Dbl_iszero_hidden(resultp1)) + { + /* Handle normalization */ + /* A straight foward algorithm would now shift the result + * and extension left until the hidden bit becomes one. Not + * all of the extension bits need participate in the shift. + * Only the two most significant bits (round and guard) are + * needed. If only a single shift is needed then the guard + * bit becomes a significant low order bit and the extension + * must participate in the rounding. If more than a single + * shift is needed, then all bits to the right of the guard + * bit are zeros, and the guard bit may or may not be zero. */ + sign_save = Dbl_signextendedsign(resultp1); + Dbl_leftshiftby1_withextent(resultp1,resultp2,extent,resultp1,resultp2); + + /* Need to check for a zero result. The sign and exponent + * fields have already been zeroed. The more efficient test + * of the full object can be used. + */ + if(Dbl_iszero(resultp1,resultp2)) + /* Must have been "x-x" or "x+(-x)". */ + { + if(Is_rounding_mode(ROUNDMINUS)) Dbl_setone_sign(resultp1); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + result_exponent--; + /* Look to see if normalization is finished. */ + if(Dbl_isone_hidden(resultp1)) + { + if(result_exponent==0) + { + /* Denormalized, exponent should be zero. Left operand * + * was normalized, so extent (guard, round) was zero */ + goto underflow; + } + else + { + /* No further normalization is needed. */ + Dbl_set_sign(resultp1,/*using*/sign_save); + Ext_leftshiftby1(extent); + goto round; + } + } + + /* Check for denormalized, exponent should be zero. Left * + * operand was normalized, so extent (guard, round) was zero */ + if(!(underflowtrap = Is_underflowtrap_enabled()) && + result_exponent==0) goto underflow; + + /* Shift extension to complete one bit of normalization and + * update exponent. */ + Ext_leftshiftby1(extent); + + /* Discover first one bit to determine shift amount. Use a + * modified binary search. We have already shifted the result + * one position right and still not found a one so the remainder + * of the extension must be zero and simplifies rounding. */ + /* Scan bytes */ + while(Dbl_iszero_hiddenhigh7mantissa(resultp1)) + { + Dbl_leftshiftby8(resultp1,resultp2); + if((result_exponent -= 8) <= 0 && !underflowtrap) + goto underflow; + } + /* Now narrow it down to the nibble */ + if(Dbl_iszero_hiddenhigh3mantissa(resultp1)) + { + /* The lower nibble contains the normalizing one */ + Dbl_leftshiftby4(resultp1,resultp2); + if((result_exponent -= 4) <= 0 && !underflowtrap) + goto underflow; + } + /* Select case were first bit is set (already normalized) + * otherwise select the proper shift. */ + if((jumpsize = Dbl_hiddenhigh3mantissa(resultp1)) > 7) + { + /* Already normalized */ + if(result_exponent <= 0) goto underflow; + Dbl_set_sign(resultp1,/*using*/sign_save); + Dbl_set_exponent(resultp1,/*using*/result_exponent); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + Dbl_sethigh4bits(resultp1,/*using*/sign_save); + switch(jumpsize) + { + case 1: + { + Dbl_leftshiftby3(resultp1,resultp2); + result_exponent -= 3; + break; + } + case 2: + case 3: + { + Dbl_leftshiftby2(resultp1,resultp2); + result_exponent -= 2; + break; + } + case 4: + case 5: + case 6: + case 7: + { + Dbl_leftshiftby1(resultp1,resultp2); + result_exponent -= 1; + break; + } + } + if(result_exponent > 0) + { + Dbl_set_exponent(resultp1,/*using*/result_exponent); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); /* Sign bit is already set */ + } + /* Fixup potential underflows */ + underflow: + if(Is_underflowtrap_enabled()) + { + Dbl_set_sign(resultp1,sign_save); + Dbl_setwrapped_exponent(resultp1,result_exponent,unfl); + Dbl_copytoptr(resultp1,resultp2,dstptr); + /* inexact = FALSE */ + return(UNDERFLOWEXCEPTION); + } + /* + * Since we cannot get an inexact denormalized result, + * we can now return. + */ + Dbl_fix_overshift(resultp1,resultp2,(1-result_exponent),extent); + Dbl_clear_signexponent(resultp1); + Dbl_set_sign(resultp1,sign_save); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } /* end if(hidden...)... */ + /* Fall through and round */ + } /* end if(save >= 0)... */ + else + { + /* Subtract magnitudes */ + Dbl_addition(leftp1,leftp2,rightp1,rightp2,/*to*/resultp1,resultp2); + if(Dbl_isone_hiddenoverflow(resultp1)) + { + /* Prenormalization required. */ + Dbl_rightshiftby1_withextent(resultp2,extent,extent); + Dbl_arithrightshiftby1(resultp1,resultp2); + result_exponent++; + } /* end if hiddenoverflow... */ + } /* end else ...subtract magnitudes... */ + + /* Round the result. If the extension is all zeros,then the result is + * exact. Otherwise round in the correct direction. No underflow is + * possible. If a postnormalization is necessary, then the mantissa is + * all zeros so no shift is needed. */ + round: + if(Ext_isnotzero(extent)) + { + inexact = TRUE; + switch(Rounding_mode()) + { + case ROUNDNEAREST: /* The default. */ + if(Ext_isone_sign(extent)) + { + /* at least 1/2 ulp */ + if(Ext_isnotzero_lower(extent) || + Dbl_isone_lowmantissap2(resultp2)) + { + /* either exactly half way and odd or more than 1/2ulp */ + Dbl_increment(resultp1,resultp2); + } + } + break; + + case ROUNDPLUS: + if(Dbl_iszero_sign(resultp1)) + { + /* Round up positive results */ + Dbl_increment(resultp1,resultp2); + } + break; + + case ROUNDMINUS: + if(Dbl_isone_sign(resultp1)) + { + /* Round down negative results */ + Dbl_increment(resultp1,resultp2); + } + + case ROUNDZERO:; + /* truncate is simple */ + } /* end switch... */ + if(Dbl_isone_hiddenoverflow(resultp1)) result_exponent++; + } + if(result_exponent == DBL_INFINITY_EXPONENT) + { + /* Overflow */ + if(Is_overflowtrap_enabled()) + { + Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl); + Dbl_copytoptr(resultp1,resultp2,dstptr); + if (inexact) + if (Is_inexacttrap_enabled()) + return(OVERFLOWEXCEPTION | INEXACTEXCEPTION); + else Set_inexactflag(); + return(OVERFLOWEXCEPTION); + } + else + { + inexact = TRUE; + Set_overflowflag(); + Dbl_setoverflow(resultp1,resultp2); + } + } + else Dbl_set_exponent(resultp1,result_exponent); + Dbl_copytoptr(resultp1,resultp2,dstptr); + if(inexact) + if(Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + return(NOEXCEPTION); + } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/driver.c linux.19rc3-ac4/arch/parisc/math-emu/driver.c --- linux.19rc3/arch/parisc/math-emu/driver.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/driver.c 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,125 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * linux/arch/math-emu/driver.c.c + * + * decodes and dispatches unimplemented FPU instructions + * + * Copyright (C) 1999, 2000 Philipp Rumpf + * Copyright (C) 2001 Hewlett-Packard + */ + +#include +#include +#include "float.h" +#include "math-emu.h" + + +#define fptpos 31 +#define fpr1pos 10 +#define extru(r,pos,len) (((r) >> (31-(pos))) & (( 1 << (len)) - 1)) + +#define FPUDEBUG 0 + +/* Format of the floating-point exception registers. */ +struct exc_reg { + unsigned int exception : 6; + unsigned int ei : 26; +}; + +/* Macros for grabbing bits of the instruction format from the 'ei' + field above. */ +/* Major opcode 0c and 0e */ +#define FP0CE_UID(i) (((i) >> 6) & 3) +#define FP0CE_CLASS(i) (((i) >> 9) & 3) +#define FP0CE_SUBOP(i) (((i) >> 13) & 7) +#define FP0CE_SUBOP1(i) (((i) >> 15) & 7) /* Class 1 subopcode */ +#define FP0C_FORMAT(i) (((i) >> 11) & 3) +#define FP0E_FORMAT(i) (((i) >> 11) & 1) + +/* Major opcode 0c, uid 2 (performance monitoring) */ +#define FPPM_SUBOP(i) (((i) >> 9) & 0x1f) + +/* Major opcode 2e (fused operations). */ +#define FP2E_SUBOP(i) (((i) >> 5) & 1) +#define FP2E_FORMAT(i) (((i) >> 11) & 1) + +/* Major opcode 26 (FMPYSUB) */ +/* Major opcode 06 (FMPYADD) */ +#define FPx6_FORMAT(i) ((i) & 0x1f) + +/* Flags and enable bits of the status word. */ +#define FPSW_FLAGS(w) ((w) >> 27) +#define FPSW_ENABLE(w) ((w) & 0x1f) +#define FPSW_V (1<<4) +#define FPSW_Z (1<<3) +#define FPSW_O (1<<2) +#define FPSW_U (1<<1) +#define FPSW_I (1<<0) + +/* Handle a floating point exception. Return zero if the faulting + instruction can be completed successfully. */ +int +handle_fpe(struct pt_regs *regs) +{ + extern void printbinary(unsigned long x, int nbits); + struct siginfo si; + unsigned int orig_sw, sw; + int signalcode; + /* need an intermediate copy of float regs because FPU emulation + * code expects an artificial last entry which contains zero + */ + __u64 frcopy[33]; + + memcpy(frcopy, regs->fr, sizeof regs->fr); + frcopy[32] = 0; + + memcpy(&orig_sw, frcopy, sizeof(orig_sw)); + + if (FPUDEBUG) { + printk(KERN_DEBUG "FP VZOUICxxxxCQCQCQCQCQCRMxxTDVZOUI ->\n "); + printbinary(orig_sw, 32); + printk(KERN_DEBUG "\n"); + } + + signalcode = decode_fpu(frcopy, 0x666); + + /* Status word = FR0L. */ + memcpy(&sw, frcopy, sizeof(sw)); + if (FPUDEBUG) { + printk(KERN_DEBUG "VZOUICxxxxCQCQCQCQCQCRMxxTDVZOUI decode_fpu returns %d|0x%x\n", + signalcode >> 24, signalcode & 0xffffff); + printbinary(sw, 32); + printk(KERN_DEBUG "\n"); + } + + memcpy(regs->fr, frcopy, sizeof regs->fr); + if (signalcode != 0) { + si.si_signo = signalcode >> 24; + si.si_errno = 0; + si.si_code = signalcode & 0xffffff; + si.si_addr = (void *) regs->iaoq[0]; + force_sig_info(si.si_signo, &si, current); + return -1; + } + + return signalcode ? -1 : 0; +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/fcnvff.c linux.19rc3-ac4/arch/parisc/math-emu/fcnvff.c --- linux.19rc3/arch/parisc/math-emu/fcnvff.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/fcnvff.c 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,309 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * BEGIN_DESC + * + * File: + * @(#) pa/spmath/fcnvff.c $Revision: 1.1 $ + * + * Purpose: + * Single Floating-point to Double Floating-point + * Double Floating-point to Single Floating-point + * + * External Interfaces: + * dbl_to_sgl_fcnvff(srcptr,nullptr,dstptr,status) + * sgl_to_dbl_fcnvff(srcptr,nullptr,dstptr,status) + * + * Internal Interfaces: + * + * Theory: + * <> + * + * END_DESC +*/ + + +#include "float.h" +#include "sgl_float.h" +#include "dbl_float.h" +#include "cnv_float.h" + +/* + * Single Floating-point to Double Floating-point + */ +/*ARGSUSED*/ +int +sgl_to_dbl_fcnvff( + sgl_floating_point *srcptr, + unsigned int *nullptr, + dbl_floating_point *dstptr, + unsigned int *status) +{ + register unsigned int src, resultp1, resultp2; + register int src_exponent; + + src = *srcptr; + src_exponent = Sgl_exponent(src); + Dbl_allp1(resultp1) = Sgl_all(src); /* set sign of result */ + /* + * Test for NaN or infinity + */ + if (src_exponent == SGL_INFINITY_EXPONENT) { + /* + * determine if NaN or infinity + */ + if (Sgl_iszero_mantissa(src)) { + /* + * is infinity; want to return double infinity + */ + Dbl_setinfinity_exponentmantissa(resultp1,resultp2); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + else { + /* + * is NaN; signaling or quiet? + */ + if (Sgl_isone_signaling(src)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(INVALIDEXCEPTION); + /* make NaN quiet */ + else { + Set_invalidflag(); + Sgl_set_quiet(src); + } + } + /* + * NaN is quiet, return as double NaN + */ + Dbl_setinfinity_exponent(resultp1); + Sgl_to_dbl_mantissa(src,resultp1,resultp2); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + } + /* + * Test for zero or denormalized + */ + if (src_exponent == 0) { + /* + * determine if zero or denormalized + */ + if (Sgl_isnotzero_mantissa(src)) { + /* + * is denormalized; want to normalize + */ + Sgl_clear_signexponent(src); + Sgl_leftshiftby1(src); + Sgl_normalize(src,src_exponent); + Sgl_to_dbl_exponent(src_exponent,resultp1); + Sgl_to_dbl_mantissa(src,resultp1,resultp2); + } + else { + Dbl_setzero_exponentmantissa(resultp1,resultp2); + } + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + /* + * No special cases, just complete the conversion + */ + Sgl_to_dbl_exponent(src_exponent, resultp1); + Sgl_to_dbl_mantissa(Sgl_mantissa(src), resultp1,resultp2); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); +} + +/* + * Double Floating-point to Single Floating-point + */ +/*ARGSUSED*/ +int +dbl_to_sgl_fcnvff( + dbl_floating_point *srcptr, + unsigned int *nullptr, + sgl_floating_point *dstptr, + unsigned int *status) +{ + register unsigned int srcp1, srcp2, result; + register int src_exponent, dest_exponent, dest_mantissa; + register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE; + register boolean lsb_odd = FALSE; + boolean is_tiny; + + Dbl_copyfromptr(srcptr,srcp1,srcp2); + src_exponent = Dbl_exponent(srcp1); + Sgl_all(result) = Dbl_allp1(srcp1); /* set sign of result */ + /* + * Test for NaN or infinity + */ + if (src_exponent == DBL_INFINITY_EXPONENT) { + /* + * determine if NaN or infinity + */ + if (Dbl_iszero_mantissa(srcp1,srcp2)) { + /* + * is infinity; want to return single infinity + */ + Sgl_setinfinity_exponentmantissa(result); + *dstptr = result; + return(NOEXCEPTION); + } + /* + * is NaN; signaling or quiet? + */ + if (Dbl_isone_signaling(srcp1)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); + else { + Set_invalidflag(); + /* make NaN quiet */ + Dbl_set_quiet(srcp1); + } + } + /* + * NaN is quiet, return as single NaN + */ + Sgl_setinfinity_exponent(result); + Sgl_set_mantissa(result,Dallp1(srcp1)<<3 | Dallp2(srcp2)>>29); + if (Sgl_iszero_mantissa(result)) Sgl_set_quiet(result); + *dstptr = result; + return(NOEXCEPTION); + } + /* + * Generate result + */ + Dbl_to_sgl_exponent(src_exponent,dest_exponent); + if (dest_exponent > 0) { + Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact,guardbit, + stickybit,lsb_odd); + } + else { + if (Dbl_iszero_exponentmantissa(srcp1,srcp2)){ + Sgl_setzero_exponentmantissa(result); + *dstptr = result; + return(NOEXCEPTION); + } + if (Is_underflowtrap_enabled()) { + Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact, + guardbit,stickybit,lsb_odd); + } + else { + /* compute result, determine inexact info, + * and set Underflowflag if appropriate + */ + Dbl_to_sgl_denormalized(srcp1,srcp2,dest_exponent, + dest_mantissa,inexact,guardbit,stickybit,lsb_odd, + is_tiny); + } + } + /* + * Now round result if not exact + */ + if (inexact) { + switch (Rounding_mode()) { + case ROUNDPLUS: + if (Sgl_iszero_sign(result)) dest_mantissa++; + break; + case ROUNDMINUS: + if (Sgl_isone_sign(result)) dest_mantissa++; + break; + case ROUNDNEAREST: + if (guardbit) { + if (stickybit || lsb_odd) dest_mantissa++; + } + } + } + Sgl_set_exponentmantissa(result,dest_mantissa); + + /* + * check for mantissa overflow after rounding + */ + if ((dest_exponent>0 || Is_underflowtrap_enabled()) && + Sgl_isone_hidden(result)) dest_exponent++; + + /* + * Test for overflow + */ + if (dest_exponent >= SGL_INFINITY_EXPONENT) { + /* trap if OVERFLOWTRAP enabled */ + if (Is_overflowtrap_enabled()) { + /* + * Check for gross overflow + */ + if (dest_exponent >= SGL_INFINITY_EXPONENT+SGL_WRAP) + return(UNIMPLEMENTEDEXCEPTION); + + /* + * Adjust bias of result + */ + Sgl_setwrapped_exponent(result,dest_exponent,ovfl); + *dstptr = result; + if (inexact) + if (Is_inexacttrap_enabled()) + return(OVERFLOWEXCEPTION|INEXACTEXCEPTION); + else Set_inexactflag(); + return(OVERFLOWEXCEPTION); + } + Set_overflowflag(); + inexact = TRUE; + /* set result to infinity or largest number */ + Sgl_setoverflow(result); + } + /* + * Test for underflow + */ + else if (dest_exponent <= 0) { + /* trap if UNDERFLOWTRAP enabled */ + if (Is_underflowtrap_enabled()) { + /* + * Check for gross underflow + */ + if (dest_exponent <= -(SGL_WRAP)) + return(UNIMPLEMENTEDEXCEPTION); + /* + * Adjust bias of result + */ + Sgl_setwrapped_exponent(result,dest_exponent,unfl); + *dstptr = result; + if (inexact) + if (Is_inexacttrap_enabled()) + return(UNDERFLOWEXCEPTION|INEXACTEXCEPTION); + else Set_inexactflag(); + return(UNDERFLOWEXCEPTION); + } + /* + * result is denormalized or signed zero + */ + if (inexact && is_tiny) Set_underflowflag(); + + } + else Sgl_set_exponent(result,dest_exponent); + *dstptr = result; + /* + * Trap if inexact trap is enabled + */ + if (inexact) + if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + return(NOEXCEPTION); +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/fcnvfu.c linux.19rc3-ac4/arch/parisc/math-emu/fcnvfu.c --- linux.19rc3/arch/parisc/math-emu/fcnvfu.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/fcnvfu.c 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,536 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * BEGIN_DESC + * + * File: + * @(#) pa/spmath/fcnvfu.c $Revision: 1.1 $ + * + * Purpose: + * Floating-point to Unsigned Fixed-point Converts + * + * External Interfaces: + * dbl_to_dbl_fcnvfu(srcptr,nullptr,dstptr,status) + * dbl_to_sgl_fcnvfu(srcptr,nullptr,dstptr,status) + * sgl_to_dbl_fcnvfu(srcptr,nullptr,dstptr,status) + * sgl_to_sgl_fcnvfu(srcptr,nullptr,dstptr,status) + * + * Internal Interfaces: + * + * Theory: + * <> + * + * END_DESC +*/ + + +#include "float.h" +#include "sgl_float.h" +#include "dbl_float.h" +#include "cnv_float.h" + +/************************************************************************ + * Floating-point to Unsigned Fixed-point Converts * + ************************************************************************/ + +/* + * Single Floating-point to Single Unsigned Fixed + */ +/*ARGSUSED*/ +int +sgl_to_sgl_fcnvfu( + sgl_floating_point *srcptr, + unsigned int *nullptr, + unsigned int *dstptr, + unsigned int *status) +{ + register unsigned int src, result; + register int src_exponent; + register boolean inexact = FALSE; + + src = *srcptr; + src_exponent = Sgl_exponent(src) - SGL_BIAS; + + /* + * Test for overflow + */ + if (src_exponent > SGL_FX_MAX_EXP + 1) { + if (Sgl_isone_sign(src)) { + result = 0; + } else { + result = 0xffffffff; + } + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + *dstptr = result; + return(NOEXCEPTION); + } + /* + * Generate result + */ + if (src_exponent >= 0) { + /* + * Check sign. + * If negative, trap unimplemented. + */ + if (Sgl_isone_sign(src)) { + result = 0; + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + *dstptr = result; + return(NOEXCEPTION); + } + Sgl_clear_signexponent_set_hidden(src); + Suint_from_sgl_mantissa(src,src_exponent,result); + + /* check for inexact */ + if (Sgl_isinexact_to_unsigned(src,src_exponent)) { + inexact = TRUE; + /* round result */ + switch (Rounding_mode()) { + case ROUNDPLUS: + result++; + break; + case ROUNDMINUS: /* never negative */ + break; + case ROUNDNEAREST: + if (Sgl_isone_roundbit(src,src_exponent) && + (Sgl_isone_stickybit(src,src_exponent) || + (result & 1))) { + result++; + } + break; + } + } + } else { + result = 0; + + /* check for inexact */ + if (Sgl_isnotzero_exponentmantissa(src)) { + inexact = TRUE; + /* round result */ + switch (Rounding_mode()) { + case ROUNDPLUS: + if (Sgl_iszero_sign(src)) { + result++; + } + break; + case ROUNDMINUS: + if (Sgl_isone_sign(src)) { + result = 0; + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + inexact = FALSE; + } + break; + case ROUNDNEAREST: + if (src_exponent == -1 && + Sgl_isnotzero_mantissa(src)) { + if (Sgl_isone_sign(src)) { + result = 0; + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + inexact = FALSE; + } + else result++; + } + break; + } + } + } + *dstptr = result; + if (inexact) { + if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + } + return(NOEXCEPTION); +} + +/* + * Single Floating-point to Double Unsigned Fixed + */ +/*ARGSUSED*/ +int +sgl_to_dbl_fcnvfu( + sgl_floating_point *srcptr, + unsigned int *nullptr, + dbl_unsigned *dstptr, + unsigned int *status) +{ + register int src_exponent; + register unsigned int src, resultp1, resultp2; + register boolean inexact = FALSE; + + src = *srcptr; + src_exponent = Sgl_exponent(src) - SGL_BIAS; + + /* + * Test for overflow + */ + if (src_exponent > DBL_FX_MAX_EXP + 1) { + if (Sgl_isone_sign(src)) { + resultp1 = resultp2 = 0; + } else { + resultp1 = resultp2 = 0xffffffff; + } + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + Duint_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + /* + * Generate result + */ + if (src_exponent >= 0) { + /* + * Check sign. + * If negative, trap unimplemented. + */ + if (Sgl_isone_sign(src)) { + resultp1 = resultp2 = 0; + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + Duint_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + Sgl_clear_signexponent_set_hidden(src); + Duint_from_sgl_mantissa(src,src_exponent,resultp1,resultp2); + + /* check for inexact */ + if (Sgl_isinexact_to_unsigned(src,src_exponent)) { + inexact = TRUE; + /* round result */ + switch (Rounding_mode()) { + case ROUNDPLUS: + Duint_increment(resultp1,resultp2); + break; + case ROUNDMINUS: /* never negative */ + break; + case ROUNDNEAREST: + if (Sgl_isone_roundbit(src,src_exponent) && + (Sgl_isone_stickybit(src,src_exponent) || + Duint_isone_lowp2(resultp2))) { + Duint_increment(resultp1,resultp2); + } + break; + } + } + } else { + Duint_setzero(resultp1,resultp2); + + /* check for inexact */ + if (Sgl_isnotzero_exponentmantissa(src)) { + inexact = TRUE; + /* round result */ + switch (Rounding_mode()) { + case ROUNDPLUS: + if (Sgl_iszero_sign(src)) { + Duint_increment(resultp1,resultp2); + } + break; + case ROUNDMINUS: + if (Sgl_isone_sign(src)) { + resultp1 = resultp2 = 0; + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + inexact = FALSE; + } + break; + case ROUNDNEAREST: + if (src_exponent == -1 && + Sgl_isnotzero_mantissa(src)) { + if (Sgl_isone_sign(src)) { + resultp1 = 0; + resultp2 = 0; + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + inexact = FALSE; + } + else Duint_increment(resultp1,resultp2); + } + } + } + } + Duint_copytoptr(resultp1,resultp2,dstptr); + if (inexact) { + if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + } + return(NOEXCEPTION); +} + +/* + * Double Floating-point to Single Unsigned Fixed + */ +/*ARGSUSED*/ +int +dbl_to_sgl_fcnvfu (dbl_floating_point * srcptr, unsigned int *nullptr, + unsigned int *dstptr, unsigned int *status) +{ + register unsigned int srcp1, srcp2, result; + register int src_exponent; + register boolean inexact = FALSE; + + Dbl_copyfromptr(srcptr,srcp1,srcp2); + src_exponent = Dbl_exponent(srcp1) - DBL_BIAS; + + /* + * Test for overflow + */ + if (src_exponent > SGL_FX_MAX_EXP + 1) { + if (Dbl_isone_sign(srcp1)) { + result = 0; + } else { + result = 0xffffffff; + } + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + *dstptr = result; + return(NOEXCEPTION); + } + /* + * Generate result + */ + if (src_exponent >= 0) { + /* + * Check sign. + * If negative, trap unimplemented. + */ + if (Dbl_isone_sign(srcp1)) { + result = 0; + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + *dstptr = result; + return(NOEXCEPTION); + } + Dbl_clear_signexponent_set_hidden(srcp1); + Suint_from_dbl_mantissa(srcp1,srcp2,src_exponent,result); + + /* check for inexact */ + if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) { + inexact = TRUE; + /* round result */ + switch (Rounding_mode()) { + case ROUNDPLUS: + result++; + break; + case ROUNDMINUS: /* never negative */ + break; + case ROUNDNEAREST: + if(Dbl_isone_roundbit(srcp1,srcp2,src_exponent) && + (Dbl_isone_stickybit(srcp1,srcp2,src_exponent)|| + result&1)) + result++; + break; + } + /* check for overflow */ + if (result == 0) { + result = 0xffffffff; + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + *dstptr = result; + return(NOEXCEPTION); + } + } + } else { + result = 0; + + /* check for inexact */ + if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { + inexact = TRUE; + /* round result */ + switch (Rounding_mode()) { + case ROUNDPLUS: + if (Dbl_iszero_sign(srcp1)) result++; + break; + case ROUNDMINUS: + if (Dbl_isone_sign(srcp1)) { + result = 0; + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + inexact = FALSE; + } + break; + case ROUNDNEAREST: + if (src_exponent == -1 && + Dbl_isnotzero_mantissa(srcp1,srcp2)) + if (Dbl_isone_sign(srcp1)) { + result = 0; + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + inexact = FALSE; + } + else result++; + } + } + } + *dstptr = result; + if (inexact) { + if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + } + return(NOEXCEPTION); +} + +/* + * Double Floating-point to Double Unsigned Fixed + */ +/*ARGSUSED*/ +int +dbl_to_dbl_fcnvfu (dbl_floating_point * srcptr, unsigned int *nullptr, + dbl_unsigned * dstptr, unsigned int *status) +{ + register int src_exponent; + register unsigned int srcp1, srcp2, resultp1, resultp2; + register boolean inexact = FALSE; + + Dbl_copyfromptr(srcptr,srcp1,srcp2); + src_exponent = Dbl_exponent(srcp1) - DBL_BIAS; + + /* + * Test for overflow + */ + if (src_exponent > DBL_FX_MAX_EXP + 1) { + if (Dbl_isone_sign(srcp1)) { + resultp1 = resultp2 = 0; + } else { + resultp1 = resultp2 = 0xffffffff; + } + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + Duint_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + + /* + * Generate result + */ + if (src_exponent >= 0) { + /* + * Check sign. + * If negative, trap unimplemented. + */ + if (Dbl_isone_sign(srcp1)) { + resultp1 = resultp2 = 0; + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + Duint_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + Dbl_clear_signexponent_set_hidden(srcp1); + Duint_from_dbl_mantissa(srcp1,srcp2,src_exponent,resultp1, + resultp2); + + /* check for inexact */ + if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) { + inexact = TRUE; + /* round result */ + switch (Rounding_mode()) { + case ROUNDPLUS: + Duint_increment(resultp1,resultp2); + break; + case ROUNDMINUS: /* never negative */ + break; + case ROUNDNEAREST: + if(Dbl_isone_roundbit(srcp1,srcp2,src_exponent)) + if(Dbl_isone_stickybit(srcp1,srcp2,src_exponent) || + Duint_isone_lowp2(resultp2)) + Duint_increment(resultp1,resultp2); + } + } + } else { + Duint_setzero(resultp1,resultp2); + + /* check for inexact */ + if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { + inexact = TRUE; + /* round result */ + switch (Rounding_mode()) { + case ROUNDPLUS: + if (Dbl_iszero_sign(srcp1)) { + Duint_increment(resultp1,resultp2); + } + break; + case ROUNDMINUS: + if (Dbl_isone_sign(srcp1)) { + resultp1 = resultp2 = 0; + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + inexact = FALSE; + } + break; + case ROUNDNEAREST: + if (src_exponent == -1 && + Dbl_isnotzero_mantissa(srcp1,srcp2)) + if (Dbl_iszero_sign(srcp1)) { + Duint_increment(resultp1,resultp2); + } else { + resultp1 = 0; + resultp2 = 0; + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + inexact = FALSE; + } + } + } + } + Duint_copytoptr(resultp1,resultp2,dstptr); + if (inexact) { + if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + } + return(NOEXCEPTION); +} + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/fcnvfut.c linux.19rc3-ac4/arch/parisc/math-emu/fcnvfut.c --- linux.19rc3/arch/parisc/math-emu/fcnvfut.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/fcnvfut.c 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,332 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * BEGIN_DESC + * + * File: + * @(#) pa/spmath/fcnvfut.c $Revision: 1.1 $ + * + * Purpose: + * Floating-point to Unsigned Fixed-point Converts with Truncation + * + * External Interfaces: + * dbl_to_dbl_fcnvfut(srcptr,nullptr,dstptr,status) + * dbl_to_sgl_fcnvfut(srcptr,nullptr,dstptr,status) + * sgl_to_dbl_fcnvfut(srcptr,nullptr,dstptr,status) + * sgl_to_sgl_fcnvfut(srcptr,nullptr,dstptr,status) + * + * Internal Interfaces: + * + * Theory: + * <> + * + * END_DESC +*/ + + +#include "float.h" +#include "sgl_float.h" +#include "dbl_float.h" +#include "cnv_float.h" + +/************************************************************************ + * Floating-point to Unsigned Fixed-point Converts with Truncation * + ************************************************************************/ + +/* + * Convert single floating-point to single fixed-point format + * with truncated result + */ +/*ARGSUSED*/ +int +sgl_to_sgl_fcnvfut (sgl_floating_point * srcptr, unsigned int *nullptr, + unsigned int *dstptr, unsigned int *status) +{ + register unsigned int src, result; + register int src_exponent; + + src = *srcptr; + src_exponent = Sgl_exponent(src) - SGL_BIAS; + + /* + * Test for overflow + */ + if (src_exponent > SGL_FX_MAX_EXP + 1) { + if (Sgl_isone_sign(src)) { + result = 0; + } else { + result = 0xffffffff; + } + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + *dstptr = result; + return(NOEXCEPTION); + } + /* + * Generate result + */ + if (src_exponent >= 0) { + /* + * Check sign. + * If negative, trap unimplemented. + */ + if (Sgl_isone_sign(src)) { + result = 0; + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + *dstptr = result; + return(NOEXCEPTION); + } + Sgl_clear_signexponent_set_hidden(src); + Suint_from_sgl_mantissa(src,src_exponent,result); + *dstptr = result; + + /* check for inexact */ + if (Sgl_isinexact_to_unsigned(src,src_exponent)) { + if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + } + } + else { + *dstptr = 0; + + /* check for inexact */ + if (Sgl_isnotzero_exponentmantissa(src)) { + if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + } + } + return(NOEXCEPTION); +} + +/* + * Single Floating-point to Double Unsigned Fixed + */ +/*ARGSUSED*/ +int +sgl_to_dbl_fcnvfut (sgl_floating_point * srcptr, unsigned int *nullptr, + dbl_unsigned * dstptr, unsigned int *status) +{ + register int src_exponent; + register unsigned int src, resultp1, resultp2; + + src = *srcptr; + src_exponent = Sgl_exponent(src) - SGL_BIAS; + + /* + * Test for overflow + */ + if (src_exponent > DBL_FX_MAX_EXP + 1) { + if (Sgl_isone_sign(src)) { + resultp1 = resultp2 = 0; + } else { + resultp1 = resultp2 = 0xffffffff; + } + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + Duint_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + /* + * Generate result + */ + if (src_exponent >= 0) { + /* + * Check sign. + * If negative, trap unimplemented. + */ + if (Sgl_isone_sign(src)) { + resultp1 = resultp2 = 0; + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + Duint_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + Sgl_clear_signexponent_set_hidden(src); + Duint_from_sgl_mantissa(src,src_exponent,resultp1,resultp2); + Duint_copytoptr(resultp1,resultp2,dstptr); + + /* check for inexact */ + if (Sgl_isinexact_to_unsigned(src,src_exponent)) { + if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + } + } + else { + Duint_setzero(resultp1,resultp2); + Duint_copytoptr(resultp1,resultp2,dstptr); + + /* check for inexact */ + if (Sgl_isnotzero_exponentmantissa(src)) { + if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + } + } + return(NOEXCEPTION); +} + +/* + * Double Floating-point to Single Unsigned Fixed + */ +/*ARGSUSED*/ +int +dbl_to_sgl_fcnvfut (dbl_floating_point * srcptr, unsigned int *nullptr, + unsigned int *dstptr, unsigned int *status) +{ + register unsigned int srcp1, srcp2, result; + register int src_exponent; + + Dbl_copyfromptr(srcptr,srcp1,srcp2); + src_exponent = Dbl_exponent(srcp1) - DBL_BIAS; + + /* + * Test for overflow + */ + if (src_exponent > SGL_FX_MAX_EXP + 1) { + if (Dbl_isone_sign(srcp1)) { + result = 0; + } else { + result = 0xffffffff; + } + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + *dstptr = result; + return(NOEXCEPTION); + } + /* + * Generate result + */ + if (src_exponent >= 0) { + /* + * Check sign. + * If negative, trap unimplemented. + */ + if (Dbl_isone_sign(srcp1)) { + result = 0; + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + *dstptr = result; + return(NOEXCEPTION); + } + Dbl_clear_signexponent_set_hidden(srcp1); + Suint_from_dbl_mantissa(srcp1,srcp2,src_exponent,result); + *dstptr = result; + + /* check for inexact */ + if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) { + if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + } + } + else { + *dstptr = 0; + + /* check for inexact */ + if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { + if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + } + } + return(NOEXCEPTION); +} + +/* + * Double Floating-point to Double Unsigned Fixed + */ +/*ARGSUSED*/ +int +dbl_to_dbl_fcnvfut (dbl_floating_point * srcptr, unsigned int *nullptr, + dbl_unsigned * dstptr, unsigned int *status) +{ + register int src_exponent; + register unsigned int srcp1, srcp2, resultp1, resultp2; + + Dbl_copyfromptr(srcptr,srcp1,srcp2); + src_exponent = Dbl_exponent(srcp1) - DBL_BIAS; + + /* + * Test for overflow + */ + if (src_exponent > DBL_FX_MAX_EXP + 1) { + if (Dbl_isone_sign(srcp1)) { + resultp1 = resultp2 = 0; + } else { + resultp1 = resultp2 = 0xffffffff; + } + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + Duint_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + /* + * Generate result + */ + if (src_exponent >= 0) { + /* + * Check sign. + * If negative, trap unimplemented. + */ + if (Dbl_isone_sign(srcp1)) { + resultp1 = resultp2 = 0; + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + Duint_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + Dbl_clear_signexponent_set_hidden(srcp1); + Duint_from_dbl_mantissa(srcp1,srcp2,src_exponent, + resultp1,resultp2); + Duint_copytoptr(resultp1,resultp2,dstptr); + + /* check for inexact */ + if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) { + if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + } + } + else { + Duint_setzero(resultp1,resultp2); + Duint_copytoptr(resultp1,resultp2,dstptr); + + /* check for inexact */ + if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { + if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + } + } + return(NOEXCEPTION); +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/fcnvfx.c linux.19rc3-ac4/arch/parisc/math-emu/fcnvfx.c --- linux.19rc3/arch/parisc/math-emu/fcnvfx.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/fcnvfx.c 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,501 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * BEGIN_DESC + * + * File: + * @(#) pa/spmath/fcnvfx.c $Revision: 1.1 $ + * + * Purpose: + * Single Floating-point to Single Fixed-point + * Single Floating-point to Double Fixed-point + * Double Floating-point to Single Fixed-point + * Double Floating-point to Double Fixed-point + * + * External Interfaces: + * dbl_to_dbl_fcnvfx(srcptr,nullptr,dstptr,status) + * dbl_to_sgl_fcnvfx(srcptr,nullptr,dstptr,status) + * sgl_to_dbl_fcnvfx(srcptr,nullptr,dstptr,status) + * sgl_to_sgl_fcnvfx(srcptr,nullptr,dstptr,status) + * + * Internal Interfaces: + * + * Theory: + * <> + * + * END_DESC +*/ + + +#include "float.h" +#include "sgl_float.h" +#include "dbl_float.h" +#include "cnv_float.h" + +/* + * Single Floating-point to Single Fixed-point + */ +/*ARGSUSED*/ +int +sgl_to_sgl_fcnvfx( + sgl_floating_point *srcptr, + sgl_floating_point *nullptr, + int *dstptr, + sgl_floating_point *status) +{ + register unsigned int src, temp; + register int src_exponent, result; + register boolean inexact = FALSE; + + src = *srcptr; + src_exponent = Sgl_exponent(src) - SGL_BIAS; + + /* + * Test for overflow + */ + if (src_exponent > SGL_FX_MAX_EXP) { + /* check for MININT */ + if ((src_exponent > SGL_FX_MAX_EXP + 1) || + Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) { + if (Sgl_iszero_sign(src)) result = 0x7fffffff; + else result = 0x80000000; + + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + *dstptr = result; + return(NOEXCEPTION); + } + } + /* + * Generate result + */ + if (src_exponent >= 0) { + temp = src; + Sgl_clear_signexponent_set_hidden(temp); + Int_from_sgl_mantissa(temp,src_exponent); + if (Sgl_isone_sign(src)) result = -Sgl_all(temp); + else result = Sgl_all(temp); + + /* check for inexact */ + if (Sgl_isinexact_to_fix(src,src_exponent)) { + inexact = TRUE; + /* round result */ + switch (Rounding_mode()) { + case ROUNDPLUS: + if (Sgl_iszero_sign(src)) result++; + break; + case ROUNDMINUS: + if (Sgl_isone_sign(src)) result--; + break; + case ROUNDNEAREST: + if (Sgl_isone_roundbit(src,src_exponent)) { + if (Sgl_isone_stickybit(src,src_exponent) + || (Sgl_isone_lowmantissa(temp))) + if (Sgl_iszero_sign(src)) result++; + else result--; + } + } + } + } + else { + result = 0; + + /* check for inexact */ + if (Sgl_isnotzero_exponentmantissa(src)) { + inexact = TRUE; + /* round result */ + switch (Rounding_mode()) { + case ROUNDPLUS: + if (Sgl_iszero_sign(src)) result++; + break; + case ROUNDMINUS: + if (Sgl_isone_sign(src)) result--; + break; + case ROUNDNEAREST: + if (src_exponent == -1) + if (Sgl_isnotzero_mantissa(src)) + if (Sgl_iszero_sign(src)) result++; + else result--; + } + } + } + *dstptr = result; + if (inexact) { + if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + } + return(NOEXCEPTION); +} + +/* + * Single Floating-point to Double Fixed-point + */ +/*ARGSUSED*/ +int +sgl_to_dbl_fcnvfx( + sgl_floating_point *srcptr, + unsigned int *nullptr, + dbl_integer *dstptr, + unsigned int *status) +{ + register int src_exponent, resultp1; + register unsigned int src, temp, resultp2; + register boolean inexact = FALSE; + + src = *srcptr; + src_exponent = Sgl_exponent(src) - SGL_BIAS; + + /* + * Test for overflow + */ + if (src_exponent > DBL_FX_MAX_EXP) { + /* check for MININT */ + if ((src_exponent > DBL_FX_MAX_EXP + 1) || + Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) { + if (Sgl_iszero_sign(src)) { + resultp1 = 0x7fffffff; + resultp2 = 0xffffffff; + } + else { + resultp1 = 0x80000000; + resultp2 = 0; + } + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + Dint_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + Dint_set_minint(resultp1,resultp2); + Dint_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + /* + * Generate result + */ + if (src_exponent >= 0) { + temp = src; + Sgl_clear_signexponent_set_hidden(temp); + Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2); + if (Sgl_isone_sign(src)) { + Dint_setone_sign(resultp1,resultp2); + } + + /* check for inexact */ + if (Sgl_isinexact_to_fix(src,src_exponent)) { + inexact = TRUE; + /* round result */ + switch (Rounding_mode()) { + case ROUNDPLUS: + if (Sgl_iszero_sign(src)) { + Dint_increment(resultp1,resultp2); + } + break; + case ROUNDMINUS: + if (Sgl_isone_sign(src)) { + Dint_decrement(resultp1,resultp2); + } + break; + case ROUNDNEAREST: + if (Sgl_isone_roundbit(src,src_exponent)) + if (Sgl_isone_stickybit(src,src_exponent) || + (Dint_isone_lowp2(resultp2))) + if (Sgl_iszero_sign(src)) { + Dint_increment(resultp1,resultp2); + } + else { + Dint_decrement(resultp1,resultp2); + } + } + } + } + else { + Dint_setzero(resultp1,resultp2); + + /* check for inexact */ + if (Sgl_isnotzero_exponentmantissa(src)) { + inexact = TRUE; + /* round result */ + switch (Rounding_mode()) { + case ROUNDPLUS: + if (Sgl_iszero_sign(src)) { + Dint_increment(resultp1,resultp2); + } + break; + case ROUNDMINUS: + if (Sgl_isone_sign(src)) { + Dint_decrement(resultp1,resultp2); + } + break; + case ROUNDNEAREST: + if (src_exponent == -1) + if (Sgl_isnotzero_mantissa(src)) + if (Sgl_iszero_sign(src)) { + Dint_increment(resultp1,resultp2); + } + else { + Dint_decrement(resultp1,resultp2); + } + } + } + } + Dint_copytoptr(resultp1,resultp2,dstptr); + if (inexact) { + if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + } + return(NOEXCEPTION); +} + +/* + * Double Floating-point to Single Fixed-point + */ +/*ARGSUSED*/ +int +dbl_to_sgl_fcnvfx( + dbl_floating_point *srcptr, + unsigned int *nullptr, + int *dstptr, + unsigned int *status) +{ + register unsigned int srcp1,srcp2, tempp1,tempp2; + register int src_exponent, result; + register boolean inexact = FALSE; + + Dbl_copyfromptr(srcptr,srcp1,srcp2); + src_exponent = Dbl_exponent(srcp1) - DBL_BIAS; + + /* + * Test for overflow + */ + if (src_exponent > SGL_FX_MAX_EXP) { + /* check for MININT */ + if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) { + if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff; + else result = 0x80000000; + + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + *dstptr = result; + return(NOEXCEPTION); + } + } + /* + * Generate result + */ + if (src_exponent >= 0) { + tempp1 = srcp1; + tempp2 = srcp2; + Dbl_clear_signexponent_set_hidden(tempp1); + Int_from_dbl_mantissa(tempp1,tempp2,src_exponent); + if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP)) + result = -Dbl_allp1(tempp1); + else result = Dbl_allp1(tempp1); + + /* check for inexact */ + if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) { + inexact = TRUE; + /* round result */ + switch (Rounding_mode()) { + case ROUNDPLUS: + if (Dbl_iszero_sign(srcp1)) result++; + break; + case ROUNDMINUS: + if (Dbl_isone_sign(srcp1)) result--; + break; + case ROUNDNEAREST: + if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent)) + if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) || + (Dbl_isone_lowmantissap1(tempp1))) + if (Dbl_iszero_sign(srcp1)) result++; + else result--; + } + /* check for overflow */ + if ((Dbl_iszero_sign(srcp1) && result < 0) || + (Dbl_isone_sign(srcp1) && result > 0)) { + + if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff; + else result = 0x80000000; + + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + *dstptr = result; + return(NOEXCEPTION); + } + } + } + else { + result = 0; + + /* check for inexact */ + if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { + inexact = TRUE; + /* round result */ + switch (Rounding_mode()) { + case ROUNDPLUS: + if (Dbl_iszero_sign(srcp1)) result++; + break; + case ROUNDMINUS: + if (Dbl_isone_sign(srcp1)) result--; + break; + case ROUNDNEAREST: + if (src_exponent == -1) + if (Dbl_isnotzero_mantissa(srcp1,srcp2)) + if (Dbl_iszero_sign(srcp1)) result++; + else result--; + } + } + } + *dstptr = result; + if (inexact) { + if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + } + return(NOEXCEPTION); +} + +/* + * Double Floating-point to Double Fixed-point + */ +/*ARGSUSED*/ +int +dbl_to_dbl_fcnvfx( + dbl_floating_point *srcptr, + unsigned int *nullptr, + dbl_integer *dstptr, + unsigned int *status) +{ + register int src_exponent, resultp1; + register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2; + register boolean inexact = FALSE; + + Dbl_copyfromptr(srcptr,srcp1,srcp2); + src_exponent = Dbl_exponent(srcp1) - DBL_BIAS; + + /* + * Test for overflow + */ + if (src_exponent > DBL_FX_MAX_EXP) { + /* check for MININT */ + if ((src_exponent > DBL_FX_MAX_EXP + 1) || + Dbl_isnotzero_mantissa(srcp1,srcp2) || Dbl_iszero_sign(srcp1)) { + if (Dbl_iszero_sign(srcp1)) { + resultp1 = 0x7fffffff; + resultp2 = 0xffffffff; + } + else { + resultp1 = 0x80000000; + resultp2 = 0; + } + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + Dint_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + } + + /* + * Generate result + */ + if (src_exponent >= 0) { + tempp1 = srcp1; + tempp2 = srcp2; + Dbl_clear_signexponent_set_hidden(tempp1); + Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent,resultp1, + resultp2); + if (Dbl_isone_sign(srcp1)) { + Dint_setone_sign(resultp1,resultp2); + } + + /* check for inexact */ + if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) { + inexact = TRUE; + /* round result */ + switch (Rounding_mode()) { + case ROUNDPLUS: + if (Dbl_iszero_sign(srcp1)) { + Dint_increment(resultp1,resultp2); + } + break; + case ROUNDMINUS: + if (Dbl_isone_sign(srcp1)) { + Dint_decrement(resultp1,resultp2); + } + break; + case ROUNDNEAREST: + if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent)) + if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) || + (Dint_isone_lowp2(resultp2))) + if (Dbl_iszero_sign(srcp1)) { + Dint_increment(resultp1,resultp2); + } + else { + Dint_decrement(resultp1,resultp2); + } + } + } + } + else { + Dint_setzero(resultp1,resultp2); + + /* check for inexact */ + if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { + inexact = TRUE; + /* round result */ + switch (Rounding_mode()) { + case ROUNDPLUS: + if (Dbl_iszero_sign(srcp1)) { + Dint_increment(resultp1,resultp2); + } + break; + case ROUNDMINUS: + if (Dbl_isone_sign(srcp1)) { + Dint_decrement(resultp1,resultp2); + } + break; + case ROUNDNEAREST: + if (src_exponent == -1) + if (Dbl_isnotzero_mantissa(srcp1,srcp2)) + if (Dbl_iszero_sign(srcp1)) { + Dint_increment(resultp1,resultp2); + } + else { + Dint_decrement(resultp1,resultp2); + } + } + } + } + Dint_copytoptr(resultp1,resultp2,dstptr); + if (inexact) { + if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + } + return(NOEXCEPTION); +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/fcnvfxt.c linux.19rc3-ac4/arch/parisc/math-emu/fcnvfxt.c --- linux.19rc3/arch/parisc/math-emu/fcnvfxt.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/fcnvfxt.c 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,328 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * BEGIN_DESC + * + * File: + * @(#) pa/spmath/fcnvfxt.c $Revision: 1.1 $ + * + * Purpose: + * Single Floating-point to Single Fixed-point /w truncated result + * Single Floating-point to Double Fixed-point /w truncated result + * Double Floating-point to Single Fixed-point /w truncated result + * Double Floating-point to Double Fixed-point /w truncated result + * + * External Interfaces: + * dbl_to_dbl_fcnvfxt(srcptr,nullptr,dstptr,status) + * dbl_to_sgl_fcnvfxt(srcptr,nullptr,dstptr,status) + * sgl_to_dbl_fcnvfxt(srcptr,nullptr,dstptr,status) + * sgl_to_sgl_fcnvfxt(srcptr,nullptr,dstptr,status) + * + * Internal Interfaces: + * + * Theory: + * <> + * + * END_DESC +*/ + + +#include "float.h" +#include "sgl_float.h" +#include "dbl_float.h" +#include "cnv_float.h" + +/* + * Convert single floating-point to single fixed-point format + * with truncated result + */ +/*ARGSUSED*/ +int +sgl_to_sgl_fcnvfxt( + sgl_floating_point *srcptr, + unsigned int *nullptr, + int *dstptr, + unsigned int *status) +{ + register unsigned int src, temp; + register int src_exponent, result; + + src = *srcptr; + src_exponent = Sgl_exponent(src) - SGL_BIAS; + + /* + * Test for overflow + */ + if (src_exponent > SGL_FX_MAX_EXP) { + /* check for MININT */ + if ((src_exponent > SGL_FX_MAX_EXP + 1) || + Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) { + if (Sgl_iszero_sign(src)) result = 0x7fffffff; + else result = 0x80000000; + + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + *dstptr = result; + return(NOEXCEPTION); + } + } + /* + * Generate result + */ + if (src_exponent >= 0) { + temp = src; + Sgl_clear_signexponent_set_hidden(temp); + Int_from_sgl_mantissa(temp,src_exponent); + if (Sgl_isone_sign(src)) result = -Sgl_all(temp); + else result = Sgl_all(temp); + *dstptr = result; + + /* check for inexact */ + if (Sgl_isinexact_to_fix(src,src_exponent)) { + if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + } + } + else { + *dstptr = 0; + + /* check for inexact */ + if (Sgl_isnotzero_exponentmantissa(src)) { + if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + } + } + return(NOEXCEPTION); +} + +/* + * Single Floating-point to Double Fixed-point + */ +/*ARGSUSED*/ +int +sgl_to_dbl_fcnvfxt( + sgl_floating_point *srcptr, + unsigned int *nullptr, + dbl_integer *dstptr, + unsigned int *status) +{ + register int src_exponent, resultp1; + register unsigned int src, temp, resultp2; + + src = *srcptr; + src_exponent = Sgl_exponent(src) - SGL_BIAS; + + /* + * Test for overflow + */ + if (src_exponent > DBL_FX_MAX_EXP) { + /* check for MININT */ + if ((src_exponent > DBL_FX_MAX_EXP + 1) || + Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) { + if (Sgl_iszero_sign(src)) { + resultp1 = 0x7fffffff; + resultp2 = 0xffffffff; + } + else { + resultp1 = 0x80000000; + resultp2 = 0; + } + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + Dint_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + Dint_set_minint(resultp1,resultp2); + Dint_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + /* + * Generate result + */ + if (src_exponent >= 0) { + temp = src; + Sgl_clear_signexponent_set_hidden(temp); + Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2); + if (Sgl_isone_sign(src)) { + Dint_setone_sign(resultp1,resultp2); + } + Dint_copytoptr(resultp1,resultp2,dstptr); + + /* check for inexact */ + if (Sgl_isinexact_to_fix(src,src_exponent)) { + if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + } + } + else { + Dint_setzero(resultp1,resultp2); + Dint_copytoptr(resultp1,resultp2,dstptr); + + /* check for inexact */ + if (Sgl_isnotzero_exponentmantissa(src)) { + if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + } + } + return(NOEXCEPTION); +} + +/* + * Double Floating-point to Single Fixed-point + */ +/*ARGSUSED*/ +int +dbl_to_sgl_fcnvfxt( + dbl_floating_point *srcptr, + unsigned int *nullptr, + int *dstptr, + unsigned int *status) +{ + register unsigned int srcp1, srcp2, tempp1, tempp2; + register int src_exponent, result; + + Dbl_copyfromptr(srcptr,srcp1,srcp2); + src_exponent = Dbl_exponent(srcp1) - DBL_BIAS; + + /* + * Test for overflow + */ + if (src_exponent > SGL_FX_MAX_EXP) { + /* check for MININT */ + if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) { + if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff; + else result = 0x80000000; + + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + *dstptr = result; + return(NOEXCEPTION); + } + } + /* + * Generate result + */ + if (src_exponent >= 0) { + tempp1 = srcp1; + tempp2 = srcp2; + Dbl_clear_signexponent_set_hidden(tempp1); + Int_from_dbl_mantissa(tempp1,tempp2,src_exponent); + if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP)) + result = -Dbl_allp1(tempp1); + else result = Dbl_allp1(tempp1); + *dstptr = result; + + /* check for inexact */ + if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) { + if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + } + } + else { + *dstptr = 0; + + /* check for inexact */ + if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { + if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + } + } + return(NOEXCEPTION); +} + +/* + * Double Floating-point to Double Fixed-point + */ +/*ARGSUSED*/ +int +dbl_to_dbl_fcnvfxt( + dbl_floating_point *srcptr, + unsigned int *nullptr, + dbl_integer *dstptr, + unsigned int *status) +{ + register int src_exponent, resultp1; + register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2; + + Dbl_copyfromptr(srcptr,srcp1,srcp2); + src_exponent = Dbl_exponent(srcp1) - DBL_BIAS; + + /* + * Test for overflow + */ + if (src_exponent > DBL_FX_MAX_EXP) { + /* check for MININT */ + if ((src_exponent > DBL_FX_MAX_EXP + 1) || + Dbl_isnotzero_mantissa(srcp1,srcp2) || Dbl_iszero_sign(srcp1)) { + if (Dbl_iszero_sign(srcp1)) { + resultp1 = 0x7fffffff; + resultp2 = 0xffffffff; + } + else { + resultp1 = 0x80000000; + resultp2 = 0; + } + if (Is_invalidtrap_enabled()) { + return(INVALIDEXCEPTION); + } + Set_invalidflag(); + Dint_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + } + /* + * Generate result + */ + if (src_exponent >= 0) { + tempp1 = srcp1; + tempp2 = srcp2; + Dbl_clear_signexponent_set_hidden(tempp1); + Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent, + resultp1,resultp2); + if (Dbl_isone_sign(srcp1)) { + Dint_setone_sign(resultp1,resultp2); + } + Dint_copytoptr(resultp1,resultp2,dstptr); + + /* check for inexact */ + if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) { + if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + } + } + else { + Dint_setzero(resultp1,resultp2); + Dint_copytoptr(resultp1,resultp2,dstptr); + + /* check for inexact */ + if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { + if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + } + } + return(NOEXCEPTION); +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/fcnvuf.c linux.19rc3-ac4/arch/parisc/math-emu/fcnvuf.c --- linux.19rc3/arch/parisc/math-emu/fcnvuf.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/fcnvuf.c 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,318 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * BEGIN_DESC + * + * File: + * @(#) pa/spmath/fcnvuf.c $Revision: 1.1 $ + * + * Purpose: + * Fixed point to Floating-point Converts + * + * External Interfaces: + * dbl_to_dbl_fcnvuf(srcptr,nullptr,dstptr,status) + * dbl_to_sgl_fcnvuf(srcptr,nullptr,dstptr,status) + * sgl_to_dbl_fcnvuf(srcptr,nullptr,dstptr,status) + * sgl_to_sgl_fcnvuf(srcptr,nullptr,dstptr,status) + * + * Internal Interfaces: + * + * Theory: + * <> + * + * END_DESC +*/ + + +#include "float.h" +#include "sgl_float.h" +#include "dbl_float.h" +#include "cnv_float.h" + +/************************************************************************ + * Fixed point to Floating-point Converts * + ************************************************************************/ + +/* + * Convert Single Unsigned Fixed to Single Floating-point format + */ + +int +sgl_to_sgl_fcnvuf( + unsigned int *srcptr, + unsigned int *nullptr, + sgl_floating_point *dstptr, + unsigned int *status) +{ + register unsigned int src, result = 0; + register int dst_exponent; + + src = *srcptr; + + /* Check for zero */ + if (src == 0) { + Sgl_setzero(result); + *dstptr = result; + return(NOEXCEPTION); + } + /* + * Generate exponent and normalized mantissa + */ + dst_exponent = 16; /* initialize for normalization */ + /* + * Check word for most significant bit set. Returns + * a value in dst_exponent indicating the bit position, + * between -1 and 30. + */ + Find_ms_one_bit(src,dst_exponent); + /* left justify source, with msb at bit position 0 */ + src <<= dst_exponent+1; + Sgl_set_mantissa(result, src >> SGL_EXP_LENGTH); + Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent); + + /* check for inexact */ + if (Suint_isinexact_to_sgl(src)) { + switch (Rounding_mode()) { + case ROUNDPLUS: + Sgl_increment(result); + break; + case ROUNDMINUS: /* never negative */ + break; + case ROUNDNEAREST: + Sgl_roundnearest_from_suint(src,result); + break; + } + if (Is_inexacttrap_enabled()) { + *dstptr = result; + return(INEXACTEXCEPTION); + } + else Set_inexactflag(); + } + *dstptr = result; + return(NOEXCEPTION); +} + +/* + * Single Unsigned Fixed to Double Floating-point + */ + +int +sgl_to_dbl_fcnvuf( + unsigned int *srcptr, + unsigned int *nullptr, + dbl_floating_point *dstptr, + unsigned int *status) +{ + register int dst_exponent; + register unsigned int src, resultp1 = 0, resultp2 = 0; + + src = *srcptr; + + /* Check for zero */ + if (src == 0) { + Dbl_setzero(resultp1,resultp2); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + /* + * Generate exponent and normalized mantissa + */ + dst_exponent = 16; /* initialize for normalization */ + /* + * Check word for most significant bit set. Returns + * a value in dst_exponent indicating the bit position, + * between -1 and 30. + */ + Find_ms_one_bit(src,dst_exponent); + /* left justify source, with msb at bit position 0 */ + src <<= dst_exponent+1; + Dbl_set_mantissap1(resultp1, src >> DBL_EXP_LENGTH); + Dbl_set_mantissap2(resultp2, src << (32-DBL_EXP_LENGTH)); + Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); +} + +/* + * Double Unsigned Fixed to Single Floating-point + */ + +int +dbl_to_sgl_fcnvuf( + dbl_unsigned *srcptr, + unsigned int *nullptr, + sgl_floating_point *dstptr, + unsigned int *status) +{ + int dst_exponent; + unsigned int srcp1, srcp2, result = 0; + + Duint_copyfromptr(srcptr,srcp1,srcp2); + + /* Check for zero */ + if (srcp1 == 0 && srcp2 == 0) { + Sgl_setzero(result); + *dstptr = result; + return(NOEXCEPTION); + } + /* + * Generate exponent and normalized mantissa + */ + dst_exponent = 16; /* initialize for normalization */ + if (srcp1 == 0) { + /* + * Check word for most significant bit set. Returns + * a value in dst_exponent indicating the bit position, + * between -1 and 30. + */ + Find_ms_one_bit(srcp2,dst_exponent); + /* left justify source, with msb at bit position 0 */ + srcp1 = srcp2 << dst_exponent+1; + srcp2 = 0; + /* + * since msb set is in second word, need to + * adjust bit position count + */ + dst_exponent += 32; + } + else { + /* + * Check word for most significant bit set. Returns + * a value in dst_exponent indicating the bit position, + * between -1 and 30. + * + */ + Find_ms_one_bit(srcp1,dst_exponent); + /* left justify source, with msb at bit position 0 */ + if (dst_exponent >= 0) { + Variable_shift_double(srcp1,srcp2,(31-dst_exponent), + srcp1); + srcp2 <<= dst_exponent+1; + } + } + Sgl_set_mantissa(result, srcp1 >> SGL_EXP_LENGTH); + Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent); + + /* check for inexact */ + if (Duint_isinexact_to_sgl(srcp1,srcp2)) { + switch (Rounding_mode()) { + case ROUNDPLUS: + Sgl_increment(result); + break; + case ROUNDMINUS: /* never negative */ + break; + case ROUNDNEAREST: + Sgl_roundnearest_from_duint(srcp1,srcp2,result); + break; + } + if (Is_inexacttrap_enabled()) { + *dstptr = result; + return(INEXACTEXCEPTION); + } + else Set_inexactflag(); + } + *dstptr = result; + return(NOEXCEPTION); +} + +/* + * Double Unsigned Fixed to Double Floating-point + */ + +int +dbl_to_dbl_fcnvuf( + dbl_unsigned *srcptr, + unsigned int *nullptr, + dbl_floating_point *dstptr, + unsigned int *status) +{ + register int dst_exponent; + register unsigned int srcp1, srcp2, resultp1 = 0, resultp2 = 0; + + Duint_copyfromptr(srcptr,srcp1,srcp2); + + /* Check for zero */ + if (srcp1 == 0 && srcp2 ==0) { + Dbl_setzero(resultp1,resultp2); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + /* + * Generate exponent and normalized mantissa + */ + dst_exponent = 16; /* initialize for normalization */ + if (srcp1 == 0) { + /* + * Check word for most significant bit set. Returns + * a value in dst_exponent indicating the bit position, + * between -1 and 30. + */ + Find_ms_one_bit(srcp2,dst_exponent); + /* left justify source, with msb at bit position 0 */ + srcp1 = srcp2 << dst_exponent+1; + srcp2 = 0; + /* + * since msb set is in second word, need to + * adjust bit position count + */ + dst_exponent += 32; + } + else { + /* + * Check word for most significant bit set. Returns + * a value in dst_exponent indicating the bit position, + * between -1 and 30. + */ + Find_ms_one_bit(srcp1,dst_exponent); + /* left justify source, with msb at bit position 0 */ + if (dst_exponent >= 0) { + Variable_shift_double(srcp1,srcp2,(31-dst_exponent), + srcp1); + srcp2 <<= dst_exponent+1; + } + } + Dbl_set_mantissap1(resultp1, srcp1 >> DBL_EXP_LENGTH); + Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH,resultp2); + Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent); + + /* check for inexact */ + if (Duint_isinexact_to_dbl(srcp2)) { + switch (Rounding_mode()) { + case ROUNDPLUS: + Dbl_increment(resultp1,resultp2); + break; + case ROUNDMINUS: /* never negative */ + break; + case ROUNDNEAREST: + Dbl_roundnearest_from_duint(srcp2,resultp1, + resultp2); + break; + } + if (Is_inexacttrap_enabled()) { + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(INEXACTEXCEPTION); + } + else Set_inexactflag(); + } + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); +} + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/fcnvxf.c linux.19rc3-ac4/arch/parisc/math-emu/fcnvxf.c --- linux.19rc3/arch/parisc/math-emu/fcnvxf.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/fcnvxf.c 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,386 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * BEGIN_DESC + * + * File: + * @(#) pa/spmath/fcnvxf.c $Revision: 1.1 $ + * + * Purpose: + * Single Fixed-point to Single Floating-point + * Single Fixed-point to Double Floating-point + * Double Fixed-point to Single Floating-point + * Double Fixed-point to Double Floating-point + * + * External Interfaces: + * dbl_to_dbl_fcnvxf(srcptr,nullptr,dstptr,status) + * dbl_to_sgl_fcnvxf(srcptr,nullptr,dstptr,status) + * sgl_to_dbl_fcnvxf(srcptr,nullptr,dstptr,status) + * sgl_to_sgl_fcnvxf(srcptr,nullptr,dstptr,status) + * + * Internal Interfaces: + * + * Theory: + * <> + * + * END_DESC +*/ + + +#include "float.h" +#include "sgl_float.h" +#include "dbl_float.h" +#include "cnv_float.h" + +/* + * Convert single fixed-point to single floating-point format + */ + +int +sgl_to_sgl_fcnvxf( + int *srcptr, + unsigned int *nullptr, + sgl_floating_point *dstptr, + unsigned int *status) +{ + register int src, dst_exponent; + register unsigned int result = 0; + + src = *srcptr; + /* + * set sign bit of result and get magnitude of source + */ + if (src < 0) { + Sgl_setone_sign(result); + Int_negate(src); + } + else { + Sgl_setzero_sign(result); + /* Check for zero */ + if (src == 0) { + Sgl_setzero(result); + *dstptr = result; + return(NOEXCEPTION); + } + } + /* + * Generate exponent and normalized mantissa + */ + dst_exponent = 16; /* initialize for normalization */ + /* + * Check word for most significant bit set. Returns + * a value in dst_exponent indicating the bit position, + * between -1 and 30. + */ + Find_ms_one_bit(src,dst_exponent); + /* left justify source, with msb at bit position 1 */ + if (dst_exponent >= 0) src <<= dst_exponent; + else src = 1 << 30; + Sgl_set_mantissa(result, src >> (SGL_EXP_LENGTH-1)); + Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent); + + /* check for inexact */ + if (Int_isinexact_to_sgl(src)) { + switch (Rounding_mode()) { + case ROUNDPLUS: + if (Sgl_iszero_sign(result)) + Sgl_increment(result); + break; + case ROUNDMINUS: + if (Sgl_isone_sign(result)) + Sgl_increment(result); + break; + case ROUNDNEAREST: + Sgl_roundnearest_from_int(src,result); + } + if (Is_inexacttrap_enabled()) { + *dstptr = result; + return(INEXACTEXCEPTION); + } + else Set_inexactflag(); + } + *dstptr = result; + return(NOEXCEPTION); +} + +/* + * Single Fixed-point to Double Floating-point + */ + +int +sgl_to_dbl_fcnvxf( + int *srcptr, + unsigned int *nullptr, + dbl_floating_point *dstptr, + unsigned int *status) +{ + register int src, dst_exponent; + register unsigned int resultp1 = 0, resultp2 = 0; + + src = *srcptr; + /* + * set sign bit of result and get magnitude of source + */ + if (src < 0) { + Dbl_setone_sign(resultp1); + Int_negate(src); + } + else { + Dbl_setzero_sign(resultp1); + /* Check for zero */ + if (src == 0) { + Dbl_setzero(resultp1,resultp2); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + } + /* + * Generate exponent and normalized mantissa + */ + dst_exponent = 16; /* initialize for normalization */ + /* + * Check word for most significant bit set. Returns + * a value in dst_exponent indicating the bit position, + * between -1 and 30. + */ + Find_ms_one_bit(src,dst_exponent); + /* left justify source, with msb at bit position 1 */ + if (dst_exponent >= 0) src <<= dst_exponent; + else src = 1 << 30; + Dbl_set_mantissap1(resultp1, src >> DBL_EXP_LENGTH - 1); + Dbl_set_mantissap2(resultp2, src << (33-DBL_EXP_LENGTH)); + Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); +} + +/* + * Double Fixed-point to Single Floating-point + */ + +int +dbl_to_sgl_fcnvxf( + dbl_integer *srcptr, + unsigned int *nullptr, + sgl_floating_point *dstptr, + unsigned int *status) +{ + int dst_exponent, srcp1; + unsigned int result = 0, srcp2; + + Dint_copyfromptr(srcptr,srcp1,srcp2); + /* + * set sign bit of result and get magnitude of source + */ + if (srcp1 < 0) { + Sgl_setone_sign(result); + Dint_negate(srcp1,srcp2); + } + else { + Sgl_setzero_sign(result); + /* Check for zero */ + if (srcp1 == 0 && srcp2 == 0) { + Sgl_setzero(result); + *dstptr = result; + return(NOEXCEPTION); + } + } + /* + * Generate exponent and normalized mantissa + */ + dst_exponent = 16; /* initialize for normalization */ + if (srcp1 == 0) { + /* + * Check word for most significant bit set. Returns + * a value in dst_exponent indicating the bit position, + * between -1 and 30. + */ + Find_ms_one_bit(srcp2,dst_exponent); + /* left justify source, with msb at bit position 1 */ + if (dst_exponent >= 0) { + srcp1 = srcp2 << dst_exponent; + srcp2 = 0; + } + else { + srcp1 = srcp2 >> 1; + srcp2 <<= 31; + } + /* + * since msb set is in second word, need to + * adjust bit position count + */ + dst_exponent += 32; + } + else { + /* + * Check word for most significant bit set. Returns + * a value in dst_exponent indicating the bit position, + * between -1 and 30. + * + */ + Find_ms_one_bit(srcp1,dst_exponent); + /* left justify source, with msb at bit position 1 */ + if (dst_exponent > 0) { + Variable_shift_double(srcp1,srcp2,(32-dst_exponent), + srcp1); + srcp2 <<= dst_exponent; + } + /* + * If dst_exponent = 0, we don't need to shift anything. + * If dst_exponent = -1, src = - 2**63 so we won't need to + * shift srcp2. + */ + else srcp1 >>= -(dst_exponent); + } + Sgl_set_mantissa(result, srcp1 >> SGL_EXP_LENGTH - 1); + Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent); + + /* check for inexact */ + if (Dint_isinexact_to_sgl(srcp1,srcp2)) { + switch (Rounding_mode()) { + case ROUNDPLUS: + if (Sgl_iszero_sign(result)) + Sgl_increment(result); + break; + case ROUNDMINUS: + if (Sgl_isone_sign(result)) + Sgl_increment(result); + break; + case ROUNDNEAREST: + Sgl_roundnearest_from_dint(srcp1,srcp2,result); + } + if (Is_inexacttrap_enabled()) { + *dstptr = result; + return(INEXACTEXCEPTION); + } + else Set_inexactflag(); + } + *dstptr = result; + return(NOEXCEPTION); +} + +/* + * Double Fixed-point to Double Floating-point + */ + +int +dbl_to_dbl_fcnvxf( + dbl_integer *srcptr, + unsigned int *nullptr, + dbl_floating_point *dstptr, + unsigned int *status) +{ + register int srcp1, dst_exponent; + register unsigned int srcp2, resultp1 = 0, resultp2 = 0; + + Dint_copyfromptr(srcptr,srcp1,srcp2); + /* + * set sign bit of result and get magnitude of source + */ + if (srcp1 < 0) { + Dbl_setone_sign(resultp1); + Dint_negate(srcp1,srcp2); + } + else { + Dbl_setzero_sign(resultp1); + /* Check for zero */ + if (srcp1 == 0 && srcp2 ==0) { + Dbl_setzero(resultp1,resultp2); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + } + /* + * Generate exponent and normalized mantissa + */ + dst_exponent = 16; /* initialize for normalization */ + if (srcp1 == 0) { + /* + * Check word for most significant bit set. Returns + * a value in dst_exponent indicating the bit position, + * between -1 and 30. + */ + Find_ms_one_bit(srcp2,dst_exponent); + /* left justify source, with msb at bit position 1 */ + if (dst_exponent >= 0) { + srcp1 = srcp2 << dst_exponent; + srcp2 = 0; + } + else { + srcp1 = srcp2 >> 1; + srcp2 <<= 31; + } + /* + * since msb set is in second word, need to + * adjust bit position count + */ + dst_exponent += 32; + } + else { + /* + * Check word for most significant bit set. Returns + * a value in dst_exponent indicating the bit position, + * between -1 and 30. + */ + Find_ms_one_bit(srcp1,dst_exponent); + /* left justify source, with msb at bit position 1 */ + if (dst_exponent > 0) { + Variable_shift_double(srcp1,srcp2,(32-dst_exponent), + srcp1); + srcp2 <<= dst_exponent; + } + /* + * If dst_exponent = 0, we don't need to shift anything. + * If dst_exponent = -1, src = - 2**63 so we won't need to + * shift srcp2. + */ + else srcp1 >>= -(dst_exponent); + } + Dbl_set_mantissap1(resultp1, srcp1 >> (DBL_EXP_LENGTH-1)); + Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH-1,resultp2); + Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent); + + /* check for inexact */ + if (Dint_isinexact_to_dbl(srcp2)) { + switch (Rounding_mode()) { + case ROUNDPLUS: + if (Dbl_iszero_sign(resultp1)) { + Dbl_increment(resultp1,resultp2); + } + break; + case ROUNDMINUS: + if (Dbl_isone_sign(resultp1)) { + Dbl_increment(resultp1,resultp2); + } + break; + case ROUNDNEAREST: + Dbl_roundnearest_from_dint(srcp2,resultp1, + resultp2); + } + if (Is_inexacttrap_enabled()) { + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(INEXACTEXCEPTION); + } + else Set_inexactflag(); + } + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/float.h linux.19rc3-ac4/arch/parisc/math-emu/float.h --- linux.19rc3/arch/parisc/math-emu/float.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/float.h 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,582 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * BEGIN_DESC + * + * File: + * @(#) pa/spmath/float.h $Revision: 1.2 $ + * + * Purpose: + * <> + * + * BE header: no + * + * Shipped: yes + * /usr/conf/pa/spmath/float.h + * + * END_DESC +*/ + +#ifdef __NO_PA_HDRS + PA header file -- do not include this header file for non-PA builds. +#endif + +#include "fpbits.h" +#include "hppa.h" +/* + * Want to pick up the FPU capability flags, not the PDC structures. + * 'LOCORE' isn't really true in this case, but we don't want the C structures + * so it suits our purposes + */ +#define LOCORE +#include "fpu.h" + +/* + * Declare the basic structures for the 3 different + * floating-point precisions. + * + * Single number + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * |s| exp | mantissa | + * +-------+-------+-------+-------+-------+-------+-------+-------+ + */ +#define Sall(object) (object) +#define Ssign(object) Bitfield_extract( 0, 1,object) +#define Ssignedsign(object) Bitfield_signed_extract( 0, 1,object) +#define Sexponent(object) Bitfield_extract( 1, 8,object) +#define Smantissa(object) Bitfield_mask( 9, 23,object) +#define Ssignaling(object) Bitfield_extract( 9, 1,object) +#define Ssignalingnan(object) Bitfield_extract( 1, 9,object) +#define Shigh2mantissa(object) Bitfield_extract( 9, 2,object) +#define Sexponentmantissa(object) Bitfield_mask( 1, 31,object) +#define Ssignexponent(object) Bitfield_extract( 0, 9,object) +#define Shidden(object) Bitfield_extract( 8, 1,object) +#define Shiddenoverflow(object) Bitfield_extract( 7, 1,object) +#define Shiddenhigh7mantissa(object) Bitfield_extract( 8, 8,object) +#define Shiddenhigh3mantissa(object) Bitfield_extract( 8, 4,object) +#define Slow(object) Bitfield_mask( 31, 1,object) +#define Slow4(object) Bitfield_mask( 28, 4,object) +#define Slow31(object) Bitfield_mask( 1, 31,object) +#define Shigh31(object) Bitfield_extract( 0, 31,object) +#define Ssignedhigh31(object) Bitfield_signed_extract( 0, 31,object) +#define Shigh4(object) Bitfield_extract( 0, 4,object) +#define Sbit24(object) Bitfield_extract( 24, 1,object) +#define Sbit28(object) Bitfield_extract( 28, 1,object) +#define Sbit29(object) Bitfield_extract( 29, 1,object) +#define Sbit30(object) Bitfield_extract( 30, 1,object) +#define Sbit31(object) Bitfield_mask( 31, 1,object) + +#define Deposit_ssign(object,value) Bitfield_deposit(value,0,1,object) +#define Deposit_sexponent(object,value) Bitfield_deposit(value,1,8,object) +#define Deposit_smantissa(object,value) Bitfield_deposit(value,9,23,object) +#define Deposit_shigh2mantissa(object,value) Bitfield_deposit(value,9,2,object) +#define Deposit_sexponentmantissa(object,value) \ + Bitfield_deposit(value,1,31,object) +#define Deposit_ssignexponent(object,value) Bitfield_deposit(value,0,9,object) +#define Deposit_slow(object,value) Bitfield_deposit(value,31,1,object) +#define Deposit_shigh4(object,value) Bitfield_deposit(value,0,4,object) + +#define Is_ssign(object) Bitfield_mask( 0, 1,object) +#define Is_ssignaling(object) Bitfield_mask( 9, 1,object) +#define Is_shidden(object) Bitfield_mask( 8, 1,object) +#define Is_shiddenoverflow(object) Bitfield_mask( 7, 1,object) +#define Is_slow(object) Bitfield_mask( 31, 1,object) +#define Is_sbit24(object) Bitfield_mask( 24, 1,object) +#define Is_sbit28(object) Bitfield_mask( 28, 1,object) +#define Is_sbit29(object) Bitfield_mask( 29, 1,object) +#define Is_sbit30(object) Bitfield_mask( 30, 1,object) +#define Is_sbit31(object) Bitfield_mask( 31, 1,object) + +/* + * Double number. + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * |s| exponent | mantissa part 1 | + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * | mantissa part 2 | + * +-------+-------+-------+-------+-------+-------+-------+-------+ + */ +#define Dallp1(object) (object) +#define Dsign(object) Bitfield_extract( 0, 1,object) +#define Dsignedsign(object) Bitfield_signed_extract( 0, 1,object) +#define Dexponent(object) Bitfield_extract( 1, 11,object) +#define Dmantissap1(object) Bitfield_mask( 12, 20,object) +#define Dsignaling(object) Bitfield_extract( 12, 1,object) +#define Dsignalingnan(object) Bitfield_extract( 1, 12,object) +#define Dhigh2mantissa(object) Bitfield_extract( 12, 2,object) +#define Dexponentmantissap1(object) Bitfield_mask( 1, 31,object) +#define Dsignexponent(object) Bitfield_extract( 0, 12,object) +#define Dhidden(object) Bitfield_extract( 11, 1,object) +#define Dhiddenoverflow(object) Bitfield_extract( 10, 1,object) +#define Dhiddenhigh7mantissa(object) Bitfield_extract( 11, 8,object) +#define Dhiddenhigh3mantissa(object) Bitfield_extract( 11, 4,object) +#define Dlowp1(object) Bitfield_mask( 31, 1,object) +#define Dlow31p1(object) Bitfield_mask( 1, 31,object) +#define Dhighp1(object) Bitfield_extract( 0, 1,object) +#define Dhigh4p1(object) Bitfield_extract( 0, 4,object) +#define Dhigh31p1(object) Bitfield_extract( 0, 31,object) +#define Dsignedhigh31p1(object) Bitfield_signed_extract( 0, 31,object) +#define Dbit3p1(object) Bitfield_extract( 3, 1,object) + +#define Deposit_dsign(object,value) Bitfield_deposit(value,0,1,object) +#define Deposit_dexponent(object,value) Bitfield_deposit(value,1,11,object) +#define Deposit_dmantissap1(object,value) Bitfield_deposit(value,12,20,object) +#define Deposit_dhigh2mantissa(object,value) Bitfield_deposit(value,12,2,object) +#define Deposit_dexponentmantissap1(object,value) \ + Bitfield_deposit(value,1,31,object) +#define Deposit_dsignexponent(object,value) Bitfield_deposit(value,0,12,object) +#define Deposit_dlowp1(object,value) Bitfield_deposit(value,31,1,object) +#define Deposit_dhigh4p1(object,value) Bitfield_deposit(value,0,4,object) + +#define Is_dsign(object) Bitfield_mask( 0, 1,object) +#define Is_dsignaling(object) Bitfield_mask( 12, 1,object) +#define Is_dhidden(object) Bitfield_mask( 11, 1,object) +#define Is_dhiddenoverflow(object) Bitfield_mask( 10, 1,object) +#define Is_dlowp1(object) Bitfield_mask( 31, 1,object) +#define Is_dhighp1(object) Bitfield_mask( 0, 1,object) +#define Is_dbit3p1(object) Bitfield_mask( 3, 1,object) + +#define Dallp2(object) (object) +#define Dmantissap2(object) (object) +#define Dlowp2(object) Bitfield_mask( 31, 1,object) +#define Dlow4p2(object) Bitfield_mask( 28, 4,object) +#define Dlow31p2(object) Bitfield_mask( 1, 31,object) +#define Dhighp2(object) Bitfield_extract( 0, 1,object) +#define Dhigh31p2(object) Bitfield_extract( 0, 31,object) +#define Dbit2p2(object) Bitfield_extract( 2, 1,object) +#define Dbit3p2(object) Bitfield_extract( 3, 1,object) +#define Dbit21p2(object) Bitfield_extract( 21, 1,object) +#define Dbit28p2(object) Bitfield_extract( 28, 1,object) +#define Dbit29p2(object) Bitfield_extract( 29, 1,object) +#define Dbit30p2(object) Bitfield_extract( 30, 1,object) +#define Dbit31p2(object) Bitfield_mask( 31, 1,object) + +#define Deposit_dlowp2(object,value) Bitfield_deposit(value,31,1,object) + +#define Is_dlowp2(object) Bitfield_mask( 31, 1,object) +#define Is_dhighp2(object) Bitfield_mask( 0, 1,object) +#define Is_dbit2p2(object) Bitfield_mask( 2, 1,object) +#define Is_dbit3p2(object) Bitfield_mask( 3, 1,object) +#define Is_dbit21p2(object) Bitfield_mask( 21, 1,object) +#define Is_dbit28p2(object) Bitfield_mask( 28, 1,object) +#define Is_dbit29p2(object) Bitfield_mask( 29, 1,object) +#define Is_dbit30p2(object) Bitfield_mask( 30, 1,object) +#define Is_dbit31p2(object) Bitfield_mask( 31, 1,object) + +/* + * Quad number. + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * |s| exponent | mantissa part 1 | + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * | mantissa part 2 | + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * | mantissa part 3 | + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * | mantissa part 4 | + * +-------+-------+-------+-------+-------+-------+-------+-------+ + */ +typedef struct + { + union + { + struct { unsigned qallp1; } u_qallp1; +/* Not needed for now... + Bitfield_extract( 0, 1,u_qsign,qsign) + Bitfield_signed_extract( 0, 1,u_qsignedsign,qsignedsign) + Bitfield_extract( 1, 15,u_qexponent,qexponent) + Bitfield_extract(16, 16,u_qmantissap1,qmantissap1) + Bitfield_extract(16, 1,u_qsignaling,qsignaling) + Bitfield_extract(1, 16,u_qsignalingnan,qsignalingnan) + Bitfield_extract(16, 2,u_qhigh2mantissa,qhigh2mantissa) + Bitfield_extract( 1, 31,u_qexponentmantissap1,qexponentmantissap1) + Bitfield_extract( 0, 16,u_qsignexponent,qsignexponent) + Bitfield_extract(15, 1,u_qhidden,qhidden) + Bitfield_extract(14, 1,u_qhiddenoverflow,qhiddenoverflow) + Bitfield_extract(15, 8,u_qhiddenhigh7mantissa,qhiddenhigh7mantissa) + Bitfield_extract(15, 4,u_qhiddenhigh3mantissa,qhiddenhigh3mantissa) + Bitfield_extract(31, 1,u_qlowp1,qlowp1) + Bitfield_extract( 1, 31,u_qlow31p1,qlow31p1) + Bitfield_extract( 0, 1,u_qhighp1,qhighp1) + Bitfield_extract( 0, 4,u_qhigh4p1,qhigh4p1) + Bitfield_extract( 0, 31,u_qhigh31p1,qhigh31p1) + */ + } quad_u1; + union + { + struct { unsigned qallp2; } u_qallp2; + /* Not needed for now... + Bitfield_extract(31, 1,u_qlowp2,qlowp2) + Bitfield_extract( 1, 31,u_qlow31p2,qlow31p2) + Bitfield_extract( 0, 1,u_qhighp2,qhighp2) + Bitfield_extract( 0, 31,u_qhigh31p2,qhigh31p2) + */ + } quad_u2; + union + { + struct { unsigned qallp3; } u_qallp3; + /* Not needed for now... + Bitfield_extract(31, 1,u_qlowp3,qlowp3) + Bitfield_extract( 1, 31,u_qlow31p3,qlow31p3) + Bitfield_extract( 0, 1,u_qhighp3,qhighp3) + Bitfield_extract( 0, 31,u_qhigh31p3,qhigh31p3) + */ + } quad_u3; + union + { + struct { unsigned qallp4; } u_qallp4; + /* Not need for now... + Bitfield_extract(31, 1,u_qlowp4,qlowp4) + Bitfield_extract( 1, 31,u_qlow31p4,qlow31p4) + Bitfield_extract( 0, 1,u_qhighp4,qhighp4) + Bitfield_extract( 0, 31,u_qhigh31p4,qhigh31p4) + */ + } quad_u4; + } quad_floating_point; + +/* Extension - An additional structure to hold the guard, round and + * sticky bits during computations. + */ +#define Extall(object) (object) +#define Extsign(object) Bitfield_extract( 0, 1,object) +#define Exthigh31(object) Bitfield_extract( 0, 31,object) +#define Extlow31(object) Bitfield_extract( 1, 31,object) +#define Extlow(object) Bitfield_extract( 31, 1,object) + +/* + * Single extended - The upper word is just like single precision, + * but one additional word of mantissa is needed. + */ +#define Sextallp1(object) (object) +#define Sextallp2(object) (object) +#define Sextlowp1(object) Bitfield_extract( 31, 1,object) +#define Sexthighp2(object) Bitfield_extract( 0, 1,object) +#define Sextlow31p2(object) Bitfield_extract( 1, 31,object) +#define Sexthiddenoverflow(object) Bitfield_extract( 4, 1,object) +#define Is_sexthiddenoverflow(object) Bitfield_mask( 4, 1,object) + +/* + * Double extended - The upper two words are just like double precision, + * but two additional words of mantissa are needed. + */ +#define Dextallp1(object) (object) +#define Dextallp2(object) (object) +#define Dextallp3(object) (object) +#define Dextallp4(object) (object) +#define Dextlowp2(object) Bitfield_extract( 31, 1,object) +#define Dexthighp3(object) Bitfield_extract( 0, 1,object) +#define Dextlow31p3(object) Bitfield_extract( 1, 31,object) +#define Dexthiddenoverflow(object) Bitfield_extract( 10, 1,object) +#define Is_dexthiddenoverflow(object) Bitfield_mask( 10, 1,object) +#define Deposit_dextlowp4(object,value) Bitfield_deposit(value,31,1,object) + +/* + * Declare the basic structures for the 3 different + * fixed-point precisions. + * + * Single number + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * |s| integer | + * +-------+-------+-------+-------+-------+-------+-------+-------+ + */ +typedef int sgl_integer; + +/* + * Double number. + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * |s| high integer | + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * | low integer | + * +-------+-------+-------+-------+-------+-------+-------+-------+ + */ +struct dint { + int wd0; + unsigned int wd1; +}; + +struct dblwd { + unsigned int wd0; + unsigned int wd1; +}; + +/* + * Quad number. + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * |s| integer part1 | + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * | integer part 2 | + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * | integer part 3 | + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * | integer part 4 | + * +-------+-------+-------+-------+-------+-------+-------+-------+ + */ + +struct quadwd { + int wd0; + unsigned int wd1; + unsigned int wd2; + unsigned int wd3; +}; + +typedef struct quadwd quad_integer; + + +/* useful typedefs */ +typedef unsigned int sgl_floating_point; +typedef struct dblwd dbl_floating_point; +typedef struct dint dbl_integer; +typedef struct dblwd dbl_unsigned; + +/* + * Define the different precisions' parameters. + */ +#define SGL_BITLENGTH 32 +#define SGL_EMAX 127 +#define SGL_EMIN (-126) +#define SGL_BIAS 127 +#define SGL_WRAP 192 +#define SGL_INFINITY_EXPONENT (SGL_EMAX+SGL_BIAS+1) +#define SGL_THRESHOLD 32 +#define SGL_EXP_LENGTH 8 +#define SGL_P 24 + +#define DBL_BITLENGTH 64 +#define DBL_EMAX 1023 +#define DBL_EMIN (-1022) +#define DBL_BIAS 1023 +#define DBL_WRAP 1536 +#define DBL_INFINITY_EXPONENT (DBL_EMAX+DBL_BIAS+1) +#define DBL_THRESHOLD 64 +#define DBL_EXP_LENGTH 11 +#define DBL_P 53 + +#define QUAD_BITLENGTH 128 +#define QUAD_EMAX 16383 +#define QUAD_EMIN (-16382) +#define QUAD_BIAS 16383 +#define QUAD_WRAP 24576 +#define QUAD_INFINITY_EXPONENT (QUAD_EMAX+QUAD_BIAS+1) +#define QUAD_P 113 + +/* Boolean Values etc. */ +#define FALSE 0 +#define TRUE (!FALSE) +#define NOT ! +#define XOR ^ + +/* other constants */ +#undef NULL +#define NULL 0 +#define NIL 0 +#define SGL 0 +#define DBL 1 +#define BADFMT 2 +#define QUAD 3 + + +/* Types */ +typedef int boolean; +typedef int FORMAT; +typedef int VOID; + + +/* Declare status register equivalent to FPUs architecture. + * + * 0 1 2 3 4 5 6 7 8 910 1 2 3 4 5 6 7 8 920 1 2 3 4 5 6 7 8 930 1 + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * |V|Z|O|U|I|C| rsv | model | version |RM |rsv|T|r|V|Z|O|U|I| + * +-------+-------+-------+-------+-------+-------+-------+-------+ + */ +#define Cbit(object) Bitfield_extract( 5, 1,object) +#define Tbit(object) Bitfield_extract( 25, 1,object) +#define Roundingmode(object) Bitfield_extract( 21, 2,object) +#define Invalidtrap(object) Bitfield_extract( 27, 1,object) +#define Divisionbyzerotrap(object) Bitfield_extract( 28, 1,object) +#define Overflowtrap(object) Bitfield_extract( 29, 1,object) +#define Underflowtrap(object) Bitfield_extract( 30, 1,object) +#define Inexacttrap(object) Bitfield_extract( 31, 1,object) +#define Invalidflag(object) Bitfield_extract( 0, 1,object) +#define Divisionbyzeroflag(object) Bitfield_extract( 1, 1,object) +#define Overflowflag(object) Bitfield_extract( 2, 1,object) +#define Underflowflag(object) Bitfield_extract( 3, 1,object) +#define Inexactflag(object) Bitfield_extract( 4, 1,object) +#define Allflags(object) Bitfield_extract( 0, 5,object) + +/* Definitions relevant to the status register */ + +/* Rounding Modes */ +#define ROUNDNEAREST 0 +#define ROUNDZERO 1 +#define ROUNDPLUS 2 +#define ROUNDMINUS 3 + +/* Exceptions */ +#define NOEXCEPTION 0x0 +#define INVALIDEXCEPTION 0x20 +#define DIVISIONBYZEROEXCEPTION 0x10 +#define OVERFLOWEXCEPTION 0x08 +#define UNDERFLOWEXCEPTION 0x04 +#define INEXACTEXCEPTION 0x02 +#define UNIMPLEMENTEDEXCEPTION 0x01 + +/* New exceptions for the 2E Opcode */ +#define OPC_2E_INVALIDEXCEPTION 0x30 +#define OPC_2E_OVERFLOWEXCEPTION 0x18 +#define OPC_2E_UNDERFLOWEXCEPTION 0x0c +#define OPC_2E_INEXACTEXCEPTION 0x12 + +/* Declare exception registers equivalent to FPUs architecture + * + * 0 1 2 3 4 5 6 7 8 910 1 2 3 4 5 6 7 8 920 1 2 3 4 5 6 7 8 930 1 + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * |excepttype | r1 | r2/ext | operation |parm |n| t/cond | + * +-------+-------+-------+-------+-------+-------+-------+-------+ + */ +#define Allexception(object) (object) +#define Exceptiontype(object) Bitfield_extract( 0, 6,object) +#define Instructionfield(object) Bitfield_mask( 6,26,object) +#define Parmfield(object) Bitfield_extract( 23, 3,object) +#define Rabit(object) Bitfield_extract( 24, 1,object) +#define Ibit(object) Bitfield_extract( 25, 1,object) + +#define Set_exceptiontype(object,value) Bitfield_deposit(value, 0, 6,object) +#define Set_parmfield(object,value) Bitfield_deposit(value, 23, 3,object) +#define Set_exceptiontype_and_instr_field(exception,instruction,object) \ + object = exception << 26 | instruction + +/* Declare the condition field + * + * 0 1 2 3 4 5 6 7 8 910 1 2 3 4 5 6 7 8 920 1 2 3 4 5 6 7 8 930 1 + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * | |G|L|E|U|X| + * +-------+-------+-------+-------+-------+-------+-------+-------+ + */ +#define Allexception(object) (object) +#define Greaterthanbit(object) Bitfield_extract( 27, 1,object) +#define Lessthanbit(object) Bitfield_extract( 28, 1,object) +#define Equalbit(object) Bitfield_extract( 29, 1,object) +#define Unorderedbit(object) Bitfield_extract( 30, 1,object) +#define Exceptionbit(object) Bitfield_extract( 31, 1,object) + +/* An alias name for the status register */ +#define Fpustatus_register (*status) + +/************************************************** + * Status register referencing and manipulation. * + **************************************************/ + +/* Rounding mode */ +#define Rounding_mode() Roundingmode(Fpustatus_register) +#define Is_rounding_mode(rmode) \ + (Roundingmode(Fpustatus_register) == rmode) +#define Set_rounding_mode(value) \ + Bitfield_deposit(value,21,2,Fpustatus_register) + +/* Boolean testing of the trap enable bits */ +#define Is_invalidtrap_enabled() Invalidtrap(Fpustatus_register) +#define Is_divisionbyzerotrap_enabled() Divisionbyzerotrap(Fpustatus_register) +#define Is_overflowtrap_enabled() Overflowtrap(Fpustatus_register) +#define Is_underflowtrap_enabled() Underflowtrap(Fpustatus_register) +#define Is_inexacttrap_enabled() Inexacttrap(Fpustatus_register) + +/* Set the indicated flags in the status register */ +#define Set_invalidflag() Bitfield_deposit(1,0,1,Fpustatus_register) +#define Set_divisionbyzeroflag() Bitfield_deposit(1,1,1,Fpustatus_register) +#define Set_overflowflag() Bitfield_deposit(1,2,1,Fpustatus_register) +#define Set_underflowflag() Bitfield_deposit(1,3,1,Fpustatus_register) +#define Set_inexactflag() Bitfield_deposit(1,4,1,Fpustatus_register) + +#define Clear_all_flags() Bitfield_deposit(0,0,5,Fpustatus_register) + +/* Manipulate the trap and condition code bits (tbit and cbit) */ +#define Set_tbit() Bitfield_deposit(1,25,1,Fpustatus_register) +#define Clear_tbit() Bitfield_deposit(0,25,1,Fpustatus_register) +#define Is_tbit_set() Tbit(Fpustatus_register) +#define Is_cbit_set() Cbit(Fpustatus_register) + +#define Set_status_cbit(value) \ + Bitfield_deposit(value,5,1,Fpustatus_register) + +/******************************* + * Condition field referencing * + *******************************/ +#define Unordered(cond) Unorderedbit(cond) +#define Equal(cond) Equalbit(cond) +#define Lessthan(cond) Lessthanbit(cond) +#define Greaterthan(cond) Greaterthanbit(cond) +#define Exception(cond) Exceptionbit(cond) + + +/* Defines for the extension */ +#define Ext_isone_sign(extent) (Extsign(extent)) +#define Ext_isnotzero(extent) \ + (Extall(extent)) +#define Ext_isnotzero_lower(extent) \ + (Extlow31(extent)) +#define Ext_leftshiftby1(extent) \ + Extall(extent) <<= 1 +#define Ext_negate(extent) \ + (int )Extall(extent) = 0 - (int )Extall(extent) +#define Ext_setone_low(extent) Bitfield_deposit(1,31,1,extent) +#define Ext_setzero(extent) Extall(extent) = 0 + +typedef int operation; + +/* error messages */ + +#define NONE 0 +#define UNDEFFPINST 1 + +/* Function definitions: opcode, opclass */ +#define FTEST (1<<2) | 0 +#define FCPY (2<<2) | 0 +#define FABS (3<<2) | 0 +#define FSQRT (4<<2) | 0 +#define FRND (5<<2) | 0 + +#define FCNVFF (0<<2) | 1 +#define FCNVXF (1<<2) | 1 +#define FCNVFX (2<<2) | 1 +#define FCNVFXT (3<<2) | 1 + +#define FCMP (0<<2) | 2 + +#define FADD (0<<2) | 3 +#define FSUB (1<<2) | 3 +#define FMPY (2<<2) | 3 +#define FDIV (3<<2) | 3 +#define FREM (4<<2) | 3 + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/fmpyfadd.c linux.19rc3-ac4/arch/parisc/math-emu/fmpyfadd.c --- linux.19rc3/arch/parisc/math-emu/fmpyfadd.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/fmpyfadd.c 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,2655 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * BEGIN_DESC + * + * File: + * @(#) pa/spmath/fmpyfadd.c $Revision: 1.1 $ + * + * Purpose: + * Double Floating-point Multiply Fused Add + * Double Floating-point Multiply Negate Fused Add + * Single Floating-point Multiply Fused Add + * Single Floating-point Multiply Negate Fused Add + * + * External Interfaces: + * dbl_fmpyfadd(src1ptr,src2ptr,src3ptr,status,dstptr) + * dbl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr) + * sgl_fmpyfadd(src1ptr,src2ptr,src3ptr,status,dstptr) + * sgl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr) + * + * Internal Interfaces: + * + * Theory: + * <> + * + * END_DESC +*/ + + +#include "float.h" +#include "sgl_float.h" +#include "dbl_float.h" + + +/* + * Double Floating-point Multiply Fused Add + */ + +int +dbl_fmpyfadd( + dbl_floating_point *src1ptr, + dbl_floating_point *src2ptr, + dbl_floating_point *src3ptr, + unsigned int *status, + dbl_floating_point *dstptr) +{ + unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2, opnd3p1, opnd3p2; + register unsigned int tmpresp1, tmpresp2, tmpresp3, tmpresp4; + unsigned int rightp1, rightp2, rightp3, rightp4; + unsigned int resultp1, resultp2 = 0, resultp3 = 0, resultp4 = 0; + register int mpy_exponent, add_exponent, count; + boolean inexact = FALSE, is_tiny = FALSE; + + unsigned int signlessleft1, signlessright1, save; + register int result_exponent, diff_exponent; + int sign_save, jumpsize; + + Dbl_copyfromptr(src1ptr,opnd1p1,opnd1p2); + Dbl_copyfromptr(src2ptr,opnd2p1,opnd2p2); + Dbl_copyfromptr(src3ptr,opnd3p1,opnd3p2); + + /* + * set sign bit of result of multiply + */ + if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1)) + Dbl_setnegativezerop1(resultp1); + else Dbl_setzerop1(resultp1); + + /* + * Generate multiply exponent + */ + mpy_exponent = Dbl_exponent(opnd1p1) + Dbl_exponent(opnd2p1) - DBL_BIAS; + + /* + * check first operand for NaN's or infinity + */ + if (Dbl_isinfinity_exponent(opnd1p1)) { + if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { + if (Dbl_isnotnan(opnd2p1,opnd2p2) && + Dbl_isnotnan(opnd3p1,opnd3p2)) { + if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) { + /* + * invalid since operands are infinity + * and zero + */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + Set_invalidflag(); + Dbl_makequietnan(resultp1,resultp2); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + /* + * Check third operand for infinity with a + * sign opposite of the multiply result + */ + if (Dbl_isinfinity(opnd3p1,opnd3p2) && + (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) { + /* + * invalid since attempting a magnitude + * subtraction of infinities + */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + Set_invalidflag(); + Dbl_makequietnan(resultp1,resultp2); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + + /* + * return infinity + */ + Dbl_setinfinity_exponentmantissa(resultp1,resultp2); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + } + else { + /* + * is NaN; signaling or quiet? + */ + if (Dbl_isone_signaling(opnd1p1)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Dbl_set_quiet(opnd1p1); + } + /* + * is second operand a signaling NaN? + */ + else if (Dbl_is_signalingnan(opnd2p1)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Dbl_set_quiet(opnd2p1); + Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); + return(NOEXCEPTION); + } + /* + * is third operand a signaling NaN? + */ + else if (Dbl_is_signalingnan(opnd3p1)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Dbl_set_quiet(opnd3p1); + Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); + return(NOEXCEPTION); + } + /* + * return quiet NaN + */ + Dbl_copytoptr(opnd1p1,opnd1p2,dstptr); + return(NOEXCEPTION); + } + } + + /* + * check second operand for NaN's or infinity + */ + if (Dbl_isinfinity_exponent(opnd2p1)) { + if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) { + if (Dbl_isnotnan(opnd3p1,opnd3p2)) { + if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) { + /* + * invalid since multiply operands are + * zero & infinity + */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + Set_invalidflag(); + Dbl_makequietnan(opnd2p1,opnd2p2); + Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); + return(NOEXCEPTION); + } + + /* + * Check third operand for infinity with a + * sign opposite of the multiply result + */ + if (Dbl_isinfinity(opnd3p1,opnd3p2) && + (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) { + /* + * invalid since attempting a magnitude + * subtraction of infinities + */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + Set_invalidflag(); + Dbl_makequietnan(resultp1,resultp2); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + + /* + * return infinity + */ + Dbl_setinfinity_exponentmantissa(resultp1,resultp2); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + } + else { + /* + * is NaN; signaling or quiet? + */ + if (Dbl_isone_signaling(opnd2p1)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Dbl_set_quiet(opnd2p1); + } + /* + * is third operand a signaling NaN? + */ + else if (Dbl_is_signalingnan(opnd3p1)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Dbl_set_quiet(opnd3p1); + Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); + return(NOEXCEPTION); + } + /* + * return quiet NaN + */ + Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); + return(NOEXCEPTION); + } + } + + /* + * check third operand for NaN's or infinity + */ + if (Dbl_isinfinity_exponent(opnd3p1)) { + if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) { + /* return infinity */ + Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); + return(NOEXCEPTION); + } else { + /* + * is NaN; signaling or quiet? + */ + if (Dbl_isone_signaling(opnd3p1)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Dbl_set_quiet(opnd3p1); + } + /* + * return quiet NaN + */ + Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); + return(NOEXCEPTION); + } + } + + /* + * Generate multiply mantissa + */ + if (Dbl_isnotzero_exponent(opnd1p1)) { + /* set hidden bit */ + Dbl_clear_signexponent_set_hidden(opnd1p1); + } + else { + /* check for zero */ + if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { + /* + * Perform the add opnd3 with zero here. + */ + if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) { + if (Is_rounding_mode(ROUNDMINUS)) { + Dbl_or_signs(opnd3p1,resultp1); + } else { + Dbl_and_signs(opnd3p1,resultp1); + } + } + /* + * Now let's check for trapped underflow case. + */ + else if (Dbl_iszero_exponent(opnd3p1) && + Is_underflowtrap_enabled()) { + /* need to normalize results mantissa */ + sign_save = Dbl_signextendedsign(opnd3p1); + result_exponent = 0; + Dbl_leftshiftby1(opnd3p1,opnd3p2); + Dbl_normalize(opnd3p1,opnd3p2,result_exponent); + Dbl_set_sign(opnd3p1,/*using*/sign_save); + Dbl_setwrapped_exponent(opnd3p1,result_exponent, + unfl); + Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); + /* inexact = FALSE */ + return(OPC_2E_UNDERFLOWEXCEPTION); + } + Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); + return(NOEXCEPTION); + } + /* is denormalized, adjust exponent */ + Dbl_clear_signexponent(opnd1p1); + Dbl_leftshiftby1(opnd1p1,opnd1p2); + Dbl_normalize(opnd1p1,opnd1p2,mpy_exponent); + } + /* opnd2 needs to have hidden bit set with msb in hidden bit */ + if (Dbl_isnotzero_exponent(opnd2p1)) { + Dbl_clear_signexponent_set_hidden(opnd2p1); + } + else { + /* check for zero */ + if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) { + /* + * Perform the add opnd3 with zero here. + */ + if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) { + if (Is_rounding_mode(ROUNDMINUS)) { + Dbl_or_signs(opnd3p1,resultp1); + } else { + Dbl_and_signs(opnd3p1,resultp1); + } + } + /* + * Now let's check for trapped underflow case. + */ + else if (Dbl_iszero_exponent(opnd3p1) && + Is_underflowtrap_enabled()) { + /* need to normalize results mantissa */ + sign_save = Dbl_signextendedsign(opnd3p1); + result_exponent = 0; + Dbl_leftshiftby1(opnd3p1,opnd3p2); + Dbl_normalize(opnd3p1,opnd3p2,result_exponent); + Dbl_set_sign(opnd3p1,/*using*/sign_save); + Dbl_setwrapped_exponent(opnd3p1,result_exponent, + unfl); + Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); + /* inexact = FALSE */ + return(OPC_2E_UNDERFLOWEXCEPTION); + } + Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); + return(NOEXCEPTION); + } + /* is denormalized; want to normalize */ + Dbl_clear_signexponent(opnd2p1); + Dbl_leftshiftby1(opnd2p1,opnd2p2); + Dbl_normalize(opnd2p1,opnd2p2,mpy_exponent); + } + + /* Multiply the first two source mantissas together */ + + /* + * The intermediate result will be kept in tmpres, + * which needs enough room for 106 bits of mantissa, + * so lets call it a Double extended. + */ + Dblext_setzero(tmpresp1,tmpresp2,tmpresp3,tmpresp4); + + /* + * Four bits at a time are inspected in each loop, and a + * simple shift and add multiply algorithm is used. + */ + for (count = DBL_P-1; count >= 0; count -= 4) { + Dblext_rightshiftby4(tmpresp1,tmpresp2,tmpresp3,tmpresp4); + if (Dbit28p2(opnd1p2)) { + /* Fourword_add should be an ADD followed by 3 ADDC's */ + Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, + opnd2p1<<3 | opnd2p2>>29, opnd2p2<<3, 0, 0); + } + if (Dbit29p2(opnd1p2)) { + Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, + opnd2p1<<2 | opnd2p2>>30, opnd2p2<<2, 0, 0); + } + if (Dbit30p2(opnd1p2)) { + Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, + opnd2p1<<1 | opnd2p2>>31, opnd2p2<<1, 0, 0); + } + if (Dbit31p2(opnd1p2)) { + Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, + opnd2p1, opnd2p2, 0, 0); + } + Dbl_rightshiftby4(opnd1p1,opnd1p2); + } + if (Is_dexthiddenoverflow(tmpresp1)) { + /* result mantissa >= 2 (mantissa overflow) */ + mpy_exponent++; + Dblext_rightshiftby1(tmpresp1,tmpresp2,tmpresp3,tmpresp4); + } + + /* + * Restore the sign of the mpy result which was saved in resultp1. + * The exponent will continue to be kept in mpy_exponent. + */ + Dblext_set_sign(tmpresp1,Dbl_sign(resultp1)); + + /* + * No rounding is required, since the result of the multiply + * is exact in the extended format. + */ + + /* + * Now we are ready to perform the add portion of the operation. + * + * The exponents need to be kept as integers for now, since the + * multiply result might not fit into the exponent field. We + * can't overflow or underflow because of this yet, since the + * add could bring the final result back into range. + */ + add_exponent = Dbl_exponent(opnd3p1); + + /* + * Check for denormalized or zero add operand. + */ + if (add_exponent == 0) { + /* check for zero */ + if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) { + /* right is zero */ + /* Left can't be zero and must be result. + * + * The final result is now in tmpres and mpy_exponent, + * and needs to be rounded and squeezed back into + * double precision format from double extended. + */ + result_exponent = mpy_exponent; + Dblext_copy(tmpresp1,tmpresp2,tmpresp3,tmpresp4, + resultp1,resultp2,resultp3,resultp4); + sign_save = Dbl_signextendedsign(resultp1);/*save sign*/ + goto round; + } + + /* + * Neither are zeroes. + * Adjust exponent and normalize add operand. + */ + sign_save = Dbl_signextendedsign(opnd3p1); /* save sign */ + Dbl_clear_signexponent(opnd3p1); + Dbl_leftshiftby1(opnd3p1,opnd3p2); + Dbl_normalize(opnd3p1,opnd3p2,add_exponent); + Dbl_set_sign(opnd3p1,sign_save); /* restore sign */ + } else { + Dbl_clear_exponent_set_hidden(opnd3p1); + } + /* + * Copy opnd3 to the double extended variable called right. + */ + Dbl_copyto_dblext(opnd3p1,opnd3p2,rightp1,rightp2,rightp3,rightp4); + + /* + * A zero "save" helps discover equal operands (for later), + * and is used in swapping operands (if needed). + */ + Dblext_xortointp1(tmpresp1,rightp1,/*to*/save); + + /* + * Compare magnitude of operands. + */ + Dblext_copytoint_exponentmantissap1(tmpresp1,signlessleft1); + Dblext_copytoint_exponentmantissap1(rightp1,signlessright1); + if (mpy_exponent < add_exponent || mpy_exponent == add_exponent && + Dblext_ismagnitudeless(tmpresp2,rightp2,signlessleft1,signlessright1)){ + /* + * Set the left operand to the larger one by XOR swap. + * First finish the first word "save". + */ + Dblext_xorfromintp1(save,rightp1,/*to*/rightp1); + Dblext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1); + Dblext_swap_lower(tmpresp2,tmpresp3,tmpresp4, + rightp2,rightp3,rightp4); + /* also setup exponents used in rest of routine */ + diff_exponent = add_exponent - mpy_exponent; + result_exponent = add_exponent; + } else { + /* also setup exponents used in rest of routine */ + diff_exponent = mpy_exponent - add_exponent; + result_exponent = mpy_exponent; + } + /* Invariant: left is not smaller than right. */ + + /* + * Special case alignment of operands that would force alignment + * beyond the extent of the extension. A further optimization + * could special case this but only reduces the path length for + * this infrequent case. + */ + if (diff_exponent > DBLEXT_THRESHOLD) { + diff_exponent = DBLEXT_THRESHOLD; + } + + /* Align right operand by shifting it to the right */ + Dblext_clear_sign(rightp1); + Dblext_right_align(rightp1,rightp2,rightp3,rightp4, + /*shifted by*/diff_exponent); + + /* Treat sum and difference of the operands separately. */ + if ((int)save < 0) { + /* + * Difference of the two operands. Overflow can occur if the + * multiply overflowed. A borrow can occur out of the hidden + * bit and force a post normalization phase. + */ + Dblext_subtract(tmpresp1,tmpresp2,tmpresp3,tmpresp4, + rightp1,rightp2,rightp3,rightp4, + resultp1,resultp2,resultp3,resultp4); + sign_save = Dbl_signextendedsign(resultp1); + if (Dbl_iszero_hidden(resultp1)) { + /* Handle normalization */ + /* A straight foward algorithm would now shift the + * result and extension left until the hidden bit + * becomes one. Not all of the extension bits need + * participate in the shift. Only the two most + * significant bits (round and guard) are needed. + * If only a single shift is needed then the guard + * bit becomes a significant low order bit and the + * extension must participate in the rounding. + * If more than a single shift is needed, then all + * bits to the right of the guard bit are zeros, + * and the guard bit may or may not be zero. */ + Dblext_leftshiftby1(resultp1,resultp2,resultp3, + resultp4); + + /* Need to check for a zero result. The sign and + * exponent fields have already been zeroed. The more + * efficient test of the full object can be used. + */ + if(Dblext_iszero(resultp1,resultp2,resultp3,resultp4)){ + /* Must have been "x-x" or "x+(-x)". */ + if (Is_rounding_mode(ROUNDMINUS)) + Dbl_setone_sign(resultp1); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + result_exponent--; + + /* Look to see if normalization is finished. */ + if (Dbl_isone_hidden(resultp1)) { + /* No further normalization is needed */ + goto round; + } + + /* Discover first one bit to determine shift amount. + * Use a modified binary search. We have already + * shifted the result one position right and still + * not found a one so the remainder of the extension + * must be zero and simplifies rounding. */ + /* Scan bytes */ + while (Dbl_iszero_hiddenhigh7mantissa(resultp1)) { + Dblext_leftshiftby8(resultp1,resultp2,resultp3,resultp4); + result_exponent -= 8; + } + /* Now narrow it down to the nibble */ + if (Dbl_iszero_hiddenhigh3mantissa(resultp1)) { + /* The lower nibble contains the + * normalizing one */ + Dblext_leftshiftby4(resultp1,resultp2,resultp3,resultp4); + result_exponent -= 4; + } + /* Select case where first bit is set (already + * normalized) otherwise select the proper shift. */ + jumpsize = Dbl_hiddenhigh3mantissa(resultp1); + if (jumpsize <= 7) switch(jumpsize) { + case 1: + Dblext_leftshiftby3(resultp1,resultp2,resultp3, + resultp4); + result_exponent -= 3; + break; + case 2: + case 3: + Dblext_leftshiftby2(resultp1,resultp2,resultp3, + resultp4); + result_exponent -= 2; + break; + case 4: + case 5: + case 6: + case 7: + Dblext_leftshiftby1(resultp1,resultp2,resultp3, + resultp4); + result_exponent -= 1; + break; + } + } /* end if (hidden...)... */ + /* Fall through and round */ + } /* end if (save < 0)... */ + else { + /* Add magnitudes */ + Dblext_addition(tmpresp1,tmpresp2,tmpresp3,tmpresp4, + rightp1,rightp2,rightp3,rightp4, + /*to*/resultp1,resultp2,resultp3,resultp4); + sign_save = Dbl_signextendedsign(resultp1); + if (Dbl_isone_hiddenoverflow(resultp1)) { + /* Prenormalization required. */ + Dblext_arithrightshiftby1(resultp1,resultp2,resultp3, + resultp4); + result_exponent++; + } /* end if hiddenoverflow... */ + } /* end else ...add magnitudes... */ + + /* Round the result. If the extension and lower two words are + * all zeros, then the result is exact. Otherwise round in the + * correct direction. Underflow is possible. If a postnormalization + * is necessary, then the mantissa is all zeros so no shift is needed. + */ + round: + if (result_exponent <= 0 && !Is_underflowtrap_enabled()) { + Dblext_denormalize(resultp1,resultp2,resultp3,resultp4, + result_exponent,is_tiny); + } + Dbl_set_sign(resultp1,/*using*/sign_save); + if (Dblext_isnotzero_mantissap3(resultp3) || + Dblext_isnotzero_mantissap4(resultp4)) { + inexact = TRUE; + switch(Rounding_mode()) { + case ROUNDNEAREST: /* The default. */ + if (Dblext_isone_highp3(resultp3)) { + /* at least 1/2 ulp */ + if (Dblext_isnotzero_low31p3(resultp3) || + Dblext_isnotzero_mantissap4(resultp4) || + Dblext_isone_lowp2(resultp2)) { + /* either exactly half way and odd or + * more than 1/2ulp */ + Dbl_increment(resultp1,resultp2); + } + } + break; + + case ROUNDPLUS: + if (Dbl_iszero_sign(resultp1)) { + /* Round up positive results */ + Dbl_increment(resultp1,resultp2); + } + break; + + case ROUNDMINUS: + if (Dbl_isone_sign(resultp1)) { + /* Round down negative results */ + Dbl_increment(resultp1,resultp2); + } + + case ROUNDZERO:; + /* truncate is simple */ + } /* end switch... */ + if (Dbl_isone_hiddenoverflow(resultp1)) result_exponent++; + } + if (result_exponent >= DBL_INFINITY_EXPONENT) { + /* trap if OVERFLOWTRAP enabled */ + if (Is_overflowtrap_enabled()) { + /* + * Adjust bias of result + */ + Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl); + Dbl_copytoptr(resultp1,resultp2,dstptr); + if (inexact) + if (Is_inexacttrap_enabled()) + return (OPC_2E_OVERFLOWEXCEPTION | + OPC_2E_INEXACTEXCEPTION); + else Set_inexactflag(); + return (OPC_2E_OVERFLOWEXCEPTION); + } + inexact = TRUE; + Set_overflowflag(); + /* set result to infinity or largest number */ + Dbl_setoverflow(resultp1,resultp2); + + } else if (result_exponent <= 0) { /* underflow case */ + if (Is_underflowtrap_enabled()) { + /* + * Adjust bias of result + */ + Dbl_setwrapped_exponent(resultp1,result_exponent,unfl); + Dbl_copytoptr(resultp1,resultp2,dstptr); + if (inexact) + if (Is_inexacttrap_enabled()) + return (OPC_2E_UNDERFLOWEXCEPTION | + OPC_2E_INEXACTEXCEPTION); + else Set_inexactflag(); + return(OPC_2E_UNDERFLOWEXCEPTION); + } + else if (inexact && is_tiny) Set_underflowflag(); + } + else Dbl_set_exponent(resultp1,result_exponent); + Dbl_copytoptr(resultp1,resultp2,dstptr); + if (inexact) + if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION); + else Set_inexactflag(); + return(NOEXCEPTION); +} + +/* + * Double Floating-point Multiply Negate Fused Add + */ + +dbl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr) + +dbl_floating_point *src1ptr, *src2ptr, *src3ptr, *dstptr; +unsigned int *status; +{ + unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2, opnd3p1, opnd3p2; + register unsigned int tmpresp1, tmpresp2, tmpresp3, tmpresp4; + unsigned int rightp1, rightp2, rightp3, rightp4; + unsigned int resultp1, resultp2 = 0, resultp3 = 0, resultp4 = 0; + register int mpy_exponent, add_exponent, count; + boolean inexact = FALSE, is_tiny = FALSE; + + unsigned int signlessleft1, signlessright1, save; + register int result_exponent, diff_exponent; + int sign_save, jumpsize; + + Dbl_copyfromptr(src1ptr,opnd1p1,opnd1p2); + Dbl_copyfromptr(src2ptr,opnd2p1,opnd2p2); + Dbl_copyfromptr(src3ptr,opnd3p1,opnd3p2); + + /* + * set sign bit of result of multiply + */ + if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1)) + Dbl_setzerop1(resultp1); + else + Dbl_setnegativezerop1(resultp1); + + /* + * Generate multiply exponent + */ + mpy_exponent = Dbl_exponent(opnd1p1) + Dbl_exponent(opnd2p1) - DBL_BIAS; + + /* + * check first operand for NaN's or infinity + */ + if (Dbl_isinfinity_exponent(opnd1p1)) { + if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { + if (Dbl_isnotnan(opnd2p1,opnd2p2) && + Dbl_isnotnan(opnd3p1,opnd3p2)) { + if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) { + /* + * invalid since operands are infinity + * and zero + */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + Set_invalidflag(); + Dbl_makequietnan(resultp1,resultp2); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + /* + * Check third operand for infinity with a + * sign opposite of the multiply result + */ + if (Dbl_isinfinity(opnd3p1,opnd3p2) && + (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) { + /* + * invalid since attempting a magnitude + * subtraction of infinities + */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + Set_invalidflag(); + Dbl_makequietnan(resultp1,resultp2); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + + /* + * return infinity + */ + Dbl_setinfinity_exponentmantissa(resultp1,resultp2); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + } + else { + /* + * is NaN; signaling or quiet? + */ + if (Dbl_isone_signaling(opnd1p1)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Dbl_set_quiet(opnd1p1); + } + /* + * is second operand a signaling NaN? + */ + else if (Dbl_is_signalingnan(opnd2p1)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Dbl_set_quiet(opnd2p1); + Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); + return(NOEXCEPTION); + } + /* + * is third operand a signaling NaN? + */ + else if (Dbl_is_signalingnan(opnd3p1)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Dbl_set_quiet(opnd3p1); + Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); + return(NOEXCEPTION); + } + /* + * return quiet NaN + */ + Dbl_copytoptr(opnd1p1,opnd1p2,dstptr); + return(NOEXCEPTION); + } + } + + /* + * check second operand for NaN's or infinity + */ + if (Dbl_isinfinity_exponent(opnd2p1)) { + if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) { + if (Dbl_isnotnan(opnd3p1,opnd3p2)) { + if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) { + /* + * invalid since multiply operands are + * zero & infinity + */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + Set_invalidflag(); + Dbl_makequietnan(opnd2p1,opnd2p2); + Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); + return(NOEXCEPTION); + } + + /* + * Check third operand for infinity with a + * sign opposite of the multiply result + */ + if (Dbl_isinfinity(opnd3p1,opnd3p2) && + (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) { + /* + * invalid since attempting a magnitude + * subtraction of infinities + */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + Set_invalidflag(); + Dbl_makequietnan(resultp1,resultp2); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + + /* + * return infinity + */ + Dbl_setinfinity_exponentmantissa(resultp1,resultp2); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + } + else { + /* + * is NaN; signaling or quiet? + */ + if (Dbl_isone_signaling(opnd2p1)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Dbl_set_quiet(opnd2p1); + } + /* + * is third operand a signaling NaN? + */ + else if (Dbl_is_signalingnan(opnd3p1)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Dbl_set_quiet(opnd3p1); + Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); + return(NOEXCEPTION); + } + /* + * return quiet NaN + */ + Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); + return(NOEXCEPTION); + } + } + + /* + * check third operand for NaN's or infinity + */ + if (Dbl_isinfinity_exponent(opnd3p1)) { + if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) { + /* return infinity */ + Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); + return(NOEXCEPTION); + } else { + /* + * is NaN; signaling or quiet? + */ + if (Dbl_isone_signaling(opnd3p1)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Dbl_set_quiet(opnd3p1); + } + /* + * return quiet NaN + */ + Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); + return(NOEXCEPTION); + } + } + + /* + * Generate multiply mantissa + */ + if (Dbl_isnotzero_exponent(opnd1p1)) { + /* set hidden bit */ + Dbl_clear_signexponent_set_hidden(opnd1p1); + } + else { + /* check for zero */ + if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { + /* + * Perform the add opnd3 with zero here. + */ + if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) { + if (Is_rounding_mode(ROUNDMINUS)) { + Dbl_or_signs(opnd3p1,resultp1); + } else { + Dbl_and_signs(opnd3p1,resultp1); + } + } + /* + * Now let's check for trapped underflow case. + */ + else if (Dbl_iszero_exponent(opnd3p1) && + Is_underflowtrap_enabled()) { + /* need to normalize results mantissa */ + sign_save = Dbl_signextendedsign(opnd3p1); + result_exponent = 0; + Dbl_leftshiftby1(opnd3p1,opnd3p2); + Dbl_normalize(opnd3p1,opnd3p2,result_exponent); + Dbl_set_sign(opnd3p1,/*using*/sign_save); + Dbl_setwrapped_exponent(opnd3p1,result_exponent, + unfl); + Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); + /* inexact = FALSE */ + return(OPC_2E_UNDERFLOWEXCEPTION); + } + Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); + return(NOEXCEPTION); + } + /* is denormalized, adjust exponent */ + Dbl_clear_signexponent(opnd1p1); + Dbl_leftshiftby1(opnd1p1,opnd1p2); + Dbl_normalize(opnd1p1,opnd1p2,mpy_exponent); + } + /* opnd2 needs to have hidden bit set with msb in hidden bit */ + if (Dbl_isnotzero_exponent(opnd2p1)) { + Dbl_clear_signexponent_set_hidden(opnd2p1); + } + else { + /* check for zero */ + if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) { + /* + * Perform the add opnd3 with zero here. + */ + if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) { + if (Is_rounding_mode(ROUNDMINUS)) { + Dbl_or_signs(opnd3p1,resultp1); + } else { + Dbl_and_signs(opnd3p1,resultp1); + } + } + /* + * Now let's check for trapped underflow case. + */ + else if (Dbl_iszero_exponent(opnd3p1) && + Is_underflowtrap_enabled()) { + /* need to normalize results mantissa */ + sign_save = Dbl_signextendedsign(opnd3p1); + result_exponent = 0; + Dbl_leftshiftby1(opnd3p1,opnd3p2); + Dbl_normalize(opnd3p1,opnd3p2,result_exponent); + Dbl_set_sign(opnd3p1,/*using*/sign_save); + Dbl_setwrapped_exponent(opnd3p1,result_exponent, + unfl); + Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); + /* inexact = FALSE */ + return(OPC_2E_UNDERFLOWEXCEPTION); + } + Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); + return(NOEXCEPTION); + } + /* is denormalized; want to normalize */ + Dbl_clear_signexponent(opnd2p1); + Dbl_leftshiftby1(opnd2p1,opnd2p2); + Dbl_normalize(opnd2p1,opnd2p2,mpy_exponent); + } + + /* Multiply the first two source mantissas together */ + + /* + * The intermediate result will be kept in tmpres, + * which needs enough room for 106 bits of mantissa, + * so lets call it a Double extended. + */ + Dblext_setzero(tmpresp1,tmpresp2,tmpresp3,tmpresp4); + + /* + * Four bits at a time are inspected in each loop, and a + * simple shift and add multiply algorithm is used. + */ + for (count = DBL_P-1; count >= 0; count -= 4) { + Dblext_rightshiftby4(tmpresp1,tmpresp2,tmpresp3,tmpresp4); + if (Dbit28p2(opnd1p2)) { + /* Fourword_add should be an ADD followed by 3 ADDC's */ + Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, + opnd2p1<<3 | opnd2p2>>29, opnd2p2<<3, 0, 0); + } + if (Dbit29p2(opnd1p2)) { + Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, + opnd2p1<<2 | opnd2p2>>30, opnd2p2<<2, 0, 0); + } + if (Dbit30p2(opnd1p2)) { + Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, + opnd2p1<<1 | opnd2p2>>31, opnd2p2<<1, 0, 0); + } + if (Dbit31p2(opnd1p2)) { + Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, + opnd2p1, opnd2p2, 0, 0); + } + Dbl_rightshiftby4(opnd1p1,opnd1p2); + } + if (Is_dexthiddenoverflow(tmpresp1)) { + /* result mantissa >= 2 (mantissa overflow) */ + mpy_exponent++; + Dblext_rightshiftby1(tmpresp1,tmpresp2,tmpresp3,tmpresp4); + } + + /* + * Restore the sign of the mpy result which was saved in resultp1. + * The exponent will continue to be kept in mpy_exponent. + */ + Dblext_set_sign(tmpresp1,Dbl_sign(resultp1)); + + /* + * No rounding is required, since the result of the multiply + * is exact in the extended format. + */ + + /* + * Now we are ready to perform the add portion of the operation. + * + * The exponents need to be kept as integers for now, since the + * multiply result might not fit into the exponent field. We + * can't overflow or underflow because of this yet, since the + * add could bring the final result back into range. + */ + add_exponent = Dbl_exponent(opnd3p1); + + /* + * Check for denormalized or zero add operand. + */ + if (add_exponent == 0) { + /* check for zero */ + if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) { + /* right is zero */ + /* Left can't be zero and must be result. + * + * The final result is now in tmpres and mpy_exponent, + * and needs to be rounded and squeezed back into + * double precision format from double extended. + */ + result_exponent = mpy_exponent; + Dblext_copy(tmpresp1,tmpresp2,tmpresp3,tmpresp4, + resultp1,resultp2,resultp3,resultp4); + sign_save = Dbl_signextendedsign(resultp1);/*save sign*/ + goto round; + } + + /* + * Neither are zeroes. + * Adjust exponent and normalize add operand. + */ + sign_save = Dbl_signextendedsign(opnd3p1); /* save sign */ + Dbl_clear_signexponent(opnd3p1); + Dbl_leftshiftby1(opnd3p1,opnd3p2); + Dbl_normalize(opnd3p1,opnd3p2,add_exponent); + Dbl_set_sign(opnd3p1,sign_save); /* restore sign */ + } else { + Dbl_clear_exponent_set_hidden(opnd3p1); + } + /* + * Copy opnd3 to the double extended variable called right. + */ + Dbl_copyto_dblext(opnd3p1,opnd3p2,rightp1,rightp2,rightp3,rightp4); + + /* + * A zero "save" helps discover equal operands (for later), + * and is used in swapping operands (if needed). + */ + Dblext_xortointp1(tmpresp1,rightp1,/*to*/save); + + /* + * Compare magnitude of operands. + */ + Dblext_copytoint_exponentmantissap1(tmpresp1,signlessleft1); + Dblext_copytoint_exponentmantissap1(rightp1,signlessright1); + if (mpy_exponent < add_exponent || mpy_exponent == add_exponent && + Dblext_ismagnitudeless(tmpresp2,rightp2,signlessleft1,signlessright1)){ + /* + * Set the left operand to the larger one by XOR swap. + * First finish the first word "save". + */ + Dblext_xorfromintp1(save,rightp1,/*to*/rightp1); + Dblext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1); + Dblext_swap_lower(tmpresp2,tmpresp3,tmpresp4, + rightp2,rightp3,rightp4); + /* also setup exponents used in rest of routine */ + diff_exponent = add_exponent - mpy_exponent; + result_exponent = add_exponent; + } else { + /* also setup exponents used in rest of routine */ + diff_exponent = mpy_exponent - add_exponent; + result_exponent = mpy_exponent; + } + /* Invariant: left is not smaller than right. */ + + /* + * Special case alignment of operands that would force alignment + * beyond the extent of the extension. A further optimization + * could special case this but only reduces the path length for + * this infrequent case. + */ + if (diff_exponent > DBLEXT_THRESHOLD) { + diff_exponent = DBLEXT_THRESHOLD; + } + + /* Align right operand by shifting it to the right */ + Dblext_clear_sign(rightp1); + Dblext_right_align(rightp1,rightp2,rightp3,rightp4, + /*shifted by*/diff_exponent); + + /* Treat sum and difference of the operands separately. */ + if ((int)save < 0) { + /* + * Difference of the two operands. Overflow can occur if the + * multiply overflowed. A borrow can occur out of the hidden + * bit and force a post normalization phase. + */ + Dblext_subtract(tmpresp1,tmpresp2,tmpresp3,tmpresp4, + rightp1,rightp2,rightp3,rightp4, + resultp1,resultp2,resultp3,resultp4); + sign_save = Dbl_signextendedsign(resultp1); + if (Dbl_iszero_hidden(resultp1)) { + /* Handle normalization */ + /* A straight foward algorithm would now shift the + * result and extension left until the hidden bit + * becomes one. Not all of the extension bits need + * participate in the shift. Only the two most + * significant bits (round and guard) are needed. + * If only a single shift is needed then the guard + * bit becomes a significant low order bit and the + * extension must participate in the rounding. + * If more than a single shift is needed, then all + * bits to the right of the guard bit are zeros, + * and the guard bit may or may not be zero. */ + Dblext_leftshiftby1(resultp1,resultp2,resultp3, + resultp4); + + /* Need to check for a zero result. The sign and + * exponent fields have already been zeroed. The more + * efficient test of the full object can be used. + */ + if (Dblext_iszero(resultp1,resultp2,resultp3,resultp4)) { + /* Must have been "x-x" or "x+(-x)". */ + if (Is_rounding_mode(ROUNDMINUS)) + Dbl_setone_sign(resultp1); + Dbl_copytoptr(resultp1,resultp2,dstptr); + return(NOEXCEPTION); + } + result_exponent--; + + /* Look to see if normalization is finished. */ + if (Dbl_isone_hidden(resultp1)) { + /* No further normalization is needed */ + goto round; + } + + /* Discover first one bit to determine shift amount. + * Use a modified binary search. We have already + * shifted the result one position right and still + * not found a one so the remainder of the extension + * must be zero and simplifies rounding. */ + /* Scan bytes */ + while (Dbl_iszero_hiddenhigh7mantissa(resultp1)) { + Dblext_leftshiftby8(resultp1,resultp2,resultp3,resultp4); + result_exponent -= 8; + } + /* Now narrow it down to the nibble */ + if (Dbl_iszero_hiddenhigh3mantissa(resultp1)) { + /* The lower nibble contains the + * normalizing one */ + Dblext_leftshiftby4(resultp1,resultp2,resultp3,resultp4); + result_exponent -= 4; + } + /* Select case where first bit is set (already + * normalized) otherwise select the proper shift. */ + jumpsize = Dbl_hiddenhigh3mantissa(resultp1); + if (jumpsize <= 7) switch(jumpsize) { + case 1: + Dblext_leftshiftby3(resultp1,resultp2,resultp3, + resultp4); + result_exponent -= 3; + break; + case 2: + case 3: + Dblext_leftshiftby2(resultp1,resultp2,resultp3, + resultp4); + result_exponent -= 2; + break; + case 4: + case 5: + case 6: + case 7: + Dblext_leftshiftby1(resultp1,resultp2,resultp3, + resultp4); + result_exponent -= 1; + break; + } + } /* end if (hidden...)... */ + /* Fall through and round */ + } /* end if (save < 0)... */ + else { + /* Add magnitudes */ + Dblext_addition(tmpresp1,tmpresp2,tmpresp3,tmpresp4, + rightp1,rightp2,rightp3,rightp4, + /*to*/resultp1,resultp2,resultp3,resultp4); + sign_save = Dbl_signextendedsign(resultp1); + if (Dbl_isone_hiddenoverflow(resultp1)) { + /* Prenormalization required. */ + Dblext_arithrightshiftby1(resultp1,resultp2,resultp3, + resultp4); + result_exponent++; + } /* end if hiddenoverflow... */ + } /* end else ...add magnitudes... */ + + /* Round the result. If the extension and lower two words are + * all zeros, then the result is exact. Otherwise round in the + * correct direction. Underflow is possible. If a postnormalization + * is necessary, then the mantissa is all zeros so no shift is needed. + */ + round: + if (result_exponent <= 0 && !Is_underflowtrap_enabled()) { + Dblext_denormalize(resultp1,resultp2,resultp3,resultp4, + result_exponent,is_tiny); + } + Dbl_set_sign(resultp1,/*using*/sign_save); + if (Dblext_isnotzero_mantissap3(resultp3) || + Dblext_isnotzero_mantissap4(resultp4)) { + inexact = TRUE; + switch(Rounding_mode()) { + case ROUNDNEAREST: /* The default. */ + if (Dblext_isone_highp3(resultp3)) { + /* at least 1/2 ulp */ + if (Dblext_isnotzero_low31p3(resultp3) || + Dblext_isnotzero_mantissap4(resultp4) || + Dblext_isone_lowp2(resultp2)) { + /* either exactly half way and odd or + * more than 1/2ulp */ + Dbl_increment(resultp1,resultp2); + } + } + break; + + case ROUNDPLUS: + if (Dbl_iszero_sign(resultp1)) { + /* Round up positive results */ + Dbl_increment(resultp1,resultp2); + } + break; + + case ROUNDMINUS: + if (Dbl_isone_sign(resultp1)) { + /* Round down negative results */ + Dbl_increment(resultp1,resultp2); + } + + case ROUNDZERO:; + /* truncate is simple */ + } /* end switch... */ + if (Dbl_isone_hiddenoverflow(resultp1)) result_exponent++; + } + if (result_exponent >= DBL_INFINITY_EXPONENT) { + /* Overflow */ + if (Is_overflowtrap_enabled()) { + /* + * Adjust bias of result + */ + Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl); + Dbl_copytoptr(resultp1,resultp2,dstptr); + if (inexact) + if (Is_inexacttrap_enabled()) + return (OPC_2E_OVERFLOWEXCEPTION | + OPC_2E_INEXACTEXCEPTION); + else Set_inexactflag(); + return (OPC_2E_OVERFLOWEXCEPTION); + } + inexact = TRUE; + Set_overflowflag(); + Dbl_setoverflow(resultp1,resultp2); + } else if (result_exponent <= 0) { /* underflow case */ + if (Is_underflowtrap_enabled()) { + /* + * Adjust bias of result + */ + Dbl_setwrapped_exponent(resultp1,result_exponent,unfl); + Dbl_copytoptr(resultp1,resultp2,dstptr); + if (inexact) + if (Is_inexacttrap_enabled()) + return (OPC_2E_UNDERFLOWEXCEPTION | + OPC_2E_INEXACTEXCEPTION); + else Set_inexactflag(); + return(OPC_2E_UNDERFLOWEXCEPTION); + } + else if (inexact && is_tiny) Set_underflowflag(); + } + else Dbl_set_exponent(resultp1,result_exponent); + Dbl_copytoptr(resultp1,resultp2,dstptr); + if (inexact) + if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION); + else Set_inexactflag(); + return(NOEXCEPTION); +} + +/* + * Single Floating-point Multiply Fused Add + */ + +sgl_fmpyfadd(src1ptr,src2ptr,src3ptr,status,dstptr) + +sgl_floating_point *src1ptr, *src2ptr, *src3ptr, *dstptr; +unsigned int *status; +{ + unsigned int opnd1, opnd2, opnd3; + register unsigned int tmpresp1, tmpresp2; + unsigned int rightp1, rightp2; + unsigned int resultp1, resultp2 = 0; + register int mpy_exponent, add_exponent, count; + boolean inexact = FALSE, is_tiny = FALSE; + + unsigned int signlessleft1, signlessright1, save; + register int result_exponent, diff_exponent; + int sign_save, jumpsize; + + Sgl_copyfromptr(src1ptr,opnd1); + Sgl_copyfromptr(src2ptr,opnd2); + Sgl_copyfromptr(src3ptr,opnd3); + + /* + * set sign bit of result of multiply + */ + if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2)) + Sgl_setnegativezero(resultp1); + else Sgl_setzero(resultp1); + + /* + * Generate multiply exponent + */ + mpy_exponent = Sgl_exponent(opnd1) + Sgl_exponent(opnd2) - SGL_BIAS; + + /* + * check first operand for NaN's or infinity + */ + if (Sgl_isinfinity_exponent(opnd1)) { + if (Sgl_iszero_mantissa(opnd1)) { + if (Sgl_isnotnan(opnd2) && Sgl_isnotnan(opnd3)) { + if (Sgl_iszero_exponentmantissa(opnd2)) { + /* + * invalid since operands are infinity + * and zero + */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + Set_invalidflag(); + Sgl_makequietnan(resultp1); + Sgl_copytoptr(resultp1,dstptr); + return(NOEXCEPTION); + } + /* + * Check third operand for infinity with a + * sign opposite of the multiply result + */ + if (Sgl_isinfinity(opnd3) && + (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) { + /* + * invalid since attempting a magnitude + * subtraction of infinities + */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + Set_invalidflag(); + Sgl_makequietnan(resultp1); + Sgl_copytoptr(resultp1,dstptr); + return(NOEXCEPTION); + } + + /* + * return infinity + */ + Sgl_setinfinity_exponentmantissa(resultp1); + Sgl_copytoptr(resultp1,dstptr); + return(NOEXCEPTION); + } + } + else { + /* + * is NaN; signaling or quiet? + */ + if (Sgl_isone_signaling(opnd1)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Sgl_set_quiet(opnd1); + } + /* + * is second operand a signaling NaN? + */ + else if (Sgl_is_signalingnan(opnd2)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Sgl_set_quiet(opnd2); + Sgl_copytoptr(opnd2,dstptr); + return(NOEXCEPTION); + } + /* + * is third operand a signaling NaN? + */ + else if (Sgl_is_signalingnan(opnd3)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Sgl_set_quiet(opnd3); + Sgl_copytoptr(opnd3,dstptr); + return(NOEXCEPTION); + } + /* + * return quiet NaN + */ + Sgl_copytoptr(opnd1,dstptr); + return(NOEXCEPTION); + } + } + + /* + * check second operand for NaN's or infinity + */ + if (Sgl_isinfinity_exponent(opnd2)) { + if (Sgl_iszero_mantissa(opnd2)) { + if (Sgl_isnotnan(opnd3)) { + if (Sgl_iszero_exponentmantissa(opnd1)) { + /* + * invalid since multiply operands are + * zero & infinity + */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + Set_invalidflag(); + Sgl_makequietnan(opnd2); + Sgl_copytoptr(opnd2,dstptr); + return(NOEXCEPTION); + } + + /* + * Check third operand for infinity with a + * sign opposite of the multiply result + */ + if (Sgl_isinfinity(opnd3) && + (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) { + /* + * invalid since attempting a magnitude + * subtraction of infinities + */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + Set_invalidflag(); + Sgl_makequietnan(resultp1); + Sgl_copytoptr(resultp1,dstptr); + return(NOEXCEPTION); + } + + /* + * return infinity + */ + Sgl_setinfinity_exponentmantissa(resultp1); + Sgl_copytoptr(resultp1,dstptr); + return(NOEXCEPTION); + } + } + else { + /* + * is NaN; signaling or quiet? + */ + if (Sgl_isone_signaling(opnd2)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Sgl_set_quiet(opnd2); + } + /* + * is third operand a signaling NaN? + */ + else if (Sgl_is_signalingnan(opnd3)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Sgl_set_quiet(opnd3); + Sgl_copytoptr(opnd3,dstptr); + return(NOEXCEPTION); + } + /* + * return quiet NaN + */ + Sgl_copytoptr(opnd2,dstptr); + return(NOEXCEPTION); + } + } + + /* + * check third operand for NaN's or infinity + */ + if (Sgl_isinfinity_exponent(opnd3)) { + if (Sgl_iszero_mantissa(opnd3)) { + /* return infinity */ + Sgl_copytoptr(opnd3,dstptr); + return(NOEXCEPTION); + } else { + /* + * is NaN; signaling or quiet? + */ + if (Sgl_isone_signaling(opnd3)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Sgl_set_quiet(opnd3); + } + /* + * return quiet NaN + */ + Sgl_copytoptr(opnd3,dstptr); + return(NOEXCEPTION); + } + } + + /* + * Generate multiply mantissa + */ + if (Sgl_isnotzero_exponent(opnd1)) { + /* set hidden bit */ + Sgl_clear_signexponent_set_hidden(opnd1); + } + else { + /* check for zero */ + if (Sgl_iszero_mantissa(opnd1)) { + /* + * Perform the add opnd3 with zero here. + */ + if (Sgl_iszero_exponentmantissa(opnd3)) { + if (Is_rounding_mode(ROUNDMINUS)) { + Sgl_or_signs(opnd3,resultp1); + } else { + Sgl_and_signs(opnd3,resultp1); + } + } + /* + * Now let's check for trapped underflow case. + */ + else if (Sgl_iszero_exponent(opnd3) && + Is_underflowtrap_enabled()) { + /* need to normalize results mantissa */ + sign_save = Sgl_signextendedsign(opnd3); + result_exponent = 0; + Sgl_leftshiftby1(opnd3); + Sgl_normalize(opnd3,result_exponent); + Sgl_set_sign(opnd3,/*using*/sign_save); + Sgl_setwrapped_exponent(opnd3,result_exponent, + unfl); + Sgl_copytoptr(opnd3,dstptr); + /* inexact = FALSE */ + return(OPC_2E_UNDERFLOWEXCEPTION); + } + Sgl_copytoptr(opnd3,dstptr); + return(NOEXCEPTION); + } + /* is denormalized, adjust exponent */ + Sgl_clear_signexponent(opnd1); + Sgl_leftshiftby1(opnd1); + Sgl_normalize(opnd1,mpy_exponent); + } + /* opnd2 needs to have hidden bit set with msb in hidden bit */ + if (Sgl_isnotzero_exponent(opnd2)) { + Sgl_clear_signexponent_set_hidden(opnd2); + } + else { + /* check for zero */ + if (Sgl_iszero_mantissa(opnd2)) { + /* + * Perform the add opnd3 with zero here. + */ + if (Sgl_iszero_exponentmantissa(opnd3)) { + if (Is_rounding_mode(ROUNDMINUS)) { + Sgl_or_signs(opnd3,resultp1); + } else { + Sgl_and_signs(opnd3,resultp1); + } + } + /* + * Now let's check for trapped underflow case. + */ + else if (Sgl_iszero_exponent(opnd3) && + Is_underflowtrap_enabled()) { + /* need to normalize results mantissa */ + sign_save = Sgl_signextendedsign(opnd3); + result_exponent = 0; + Sgl_leftshiftby1(opnd3); + Sgl_normalize(opnd3,result_exponent); + Sgl_set_sign(opnd3,/*using*/sign_save); + Sgl_setwrapped_exponent(opnd3,result_exponent, + unfl); + Sgl_copytoptr(opnd3,dstptr); + /* inexact = FALSE */ + return(OPC_2E_UNDERFLOWEXCEPTION); + } + Sgl_copytoptr(opnd3,dstptr); + return(NOEXCEPTION); + } + /* is denormalized; want to normalize */ + Sgl_clear_signexponent(opnd2); + Sgl_leftshiftby1(opnd2); + Sgl_normalize(opnd2,mpy_exponent); + } + + /* Multiply the first two source mantissas together */ + + /* + * The intermediate result will be kept in tmpres, + * which needs enough room for 106 bits of mantissa, + * so lets call it a Double extended. + */ + Sglext_setzero(tmpresp1,tmpresp2); + + /* + * Four bits at a time are inspected in each loop, and a + * simple shift and add multiply algorithm is used. + */ + for (count = SGL_P-1; count >= 0; count -= 4) { + Sglext_rightshiftby4(tmpresp1,tmpresp2); + if (Sbit28(opnd1)) { + /* Twoword_add should be an ADD followed by 2 ADDC's */ + Twoword_add(tmpresp1, tmpresp2, opnd2<<3, 0); + } + if (Sbit29(opnd1)) { + Twoword_add(tmpresp1, tmpresp2, opnd2<<2, 0); + } + if (Sbit30(opnd1)) { + Twoword_add(tmpresp1, tmpresp2, opnd2<<1, 0); + } + if (Sbit31(opnd1)) { + Twoword_add(tmpresp1, tmpresp2, opnd2, 0); + } + Sgl_rightshiftby4(opnd1); + } + if (Is_sexthiddenoverflow(tmpresp1)) { + /* result mantissa >= 2 (mantissa overflow) */ + mpy_exponent++; + Sglext_rightshiftby4(tmpresp1,tmpresp2); + } else { + Sglext_rightshiftby3(tmpresp1,tmpresp2); + } + + /* + * Restore the sign of the mpy result which was saved in resultp1. + * The exponent will continue to be kept in mpy_exponent. + */ + Sglext_set_sign(tmpresp1,Sgl_sign(resultp1)); + + /* + * No rounding is required, since the result of the multiply + * is exact in the extended format. + */ + + /* + * Now we are ready to perform the add portion of the operation. + * + * The exponents need to be kept as integers for now, since the + * multiply result might not fit into the exponent field. We + * can't overflow or underflow because of this yet, since the + * add could bring the final result back into range. + */ + add_exponent = Sgl_exponent(opnd3); + + /* + * Check for denormalized or zero add operand. + */ + if (add_exponent == 0) { + /* check for zero */ + if (Sgl_iszero_mantissa(opnd3)) { + /* right is zero */ + /* Left can't be zero and must be result. + * + * The final result is now in tmpres and mpy_exponent, + * and needs to be rounded and squeezed back into + * double precision format from double extended. + */ + result_exponent = mpy_exponent; + Sglext_copy(tmpresp1,tmpresp2,resultp1,resultp2); + sign_save = Sgl_signextendedsign(resultp1);/*save sign*/ + goto round; + } + + /* + * Neither are zeroes. + * Adjust exponent and normalize add operand. + */ + sign_save = Sgl_signextendedsign(opnd3); /* save sign */ + Sgl_clear_signexponent(opnd3); + Sgl_leftshiftby1(opnd3); + Sgl_normalize(opnd3,add_exponent); + Sgl_set_sign(opnd3,sign_save); /* restore sign */ + } else { + Sgl_clear_exponent_set_hidden(opnd3); + } + /* + * Copy opnd3 to the double extended variable called right. + */ + Sgl_copyto_sglext(opnd3,rightp1,rightp2); + + /* + * A zero "save" helps discover equal operands (for later), + * and is used in swapping operands (if needed). + */ + Sglext_xortointp1(tmpresp1,rightp1,/*to*/save); + + /* + * Compare magnitude of operands. + */ + Sglext_copytoint_exponentmantissa(tmpresp1,signlessleft1); + Sglext_copytoint_exponentmantissa(rightp1,signlessright1); + if (mpy_exponent < add_exponent || mpy_exponent == add_exponent && + Sglext_ismagnitudeless(signlessleft1,signlessright1)) { + /* + * Set the left operand to the larger one by XOR swap. + * First finish the first word "save". + */ + Sglext_xorfromintp1(save,rightp1,/*to*/rightp1); + Sglext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1); + Sglext_swap_lower(tmpresp2,rightp2); + /* also setup exponents used in rest of routine */ + diff_exponent = add_exponent - mpy_exponent; + result_exponent = add_exponent; + } else { + /* also setup exponents used in rest of routine */ + diff_exponent = mpy_exponent - add_exponent; + result_exponent = mpy_exponent; + } + /* Invariant: left is not smaller than right. */ + + /* + * Special case alignment of operands that would force alignment + * beyond the extent of the extension. A further optimization + * could special case this but only reduces the path length for + * this infrequent case. + */ + if (diff_exponent > SGLEXT_THRESHOLD) { + diff_exponent = SGLEXT_THRESHOLD; + } + + /* Align right operand by shifting it to the right */ + Sglext_clear_sign(rightp1); + Sglext_right_align(rightp1,rightp2,/*shifted by*/diff_exponent); + + /* Treat sum and difference of the operands separately. */ + if ((int)save < 0) { + /* + * Difference of the two operands. Overflow can occur if the + * multiply overflowed. A borrow can occur out of the hidden + * bit and force a post normalization phase. + */ + Sglext_subtract(tmpresp1,tmpresp2, rightp1,rightp2, + resultp1,resultp2); + sign_save = Sgl_signextendedsign(resultp1); + if (Sgl_iszero_hidden(resultp1)) { + /* Handle normalization */ + /* A straight foward algorithm would now shift the + * result and extension left until the hidden bit + * becomes one. Not all of the extension bits need + * participate in the shift. Only the two most + * significant bits (round and guard) are needed. + * If only a single shift is needed then the guard + * bit becomes a significant low order bit and the + * extension must participate in the rounding. + * If more than a single shift is needed, then all + * bits to the right of the guard bit are zeros, + * and the guard bit may or may not be zero. */ + Sglext_leftshiftby1(resultp1,resultp2); + + /* Need to check for a zero result. The sign and + * exponent fields have already been zeroed. The more + * efficient test of the full object can be used. + */ + if (Sglext_iszero(resultp1,resultp2)) { + /* Must have been "x-x" or "x+(-x)". */ + if (Is_rounding_mode(ROUNDMINUS)) + Sgl_setone_sign(resultp1); + Sgl_copytoptr(resultp1,dstptr); + return(NOEXCEPTION); + } + result_exponent--; + + /* Look to see if normalization is finished. */ + if (Sgl_isone_hidden(resultp1)) { + /* No further normalization is needed */ + goto round; + } + + /* Discover first one bit to determine shift amount. + * Use a modified binary search. We have already + * shifted the result one position right and still + * not found a one so the remainder of the extension + * must be zero and simplifies rounding. */ + /* Scan bytes */ + while (Sgl_iszero_hiddenhigh7mantissa(resultp1)) { + Sglext_leftshiftby8(resultp1,resultp2); + result_exponent -= 8; + } + /* Now narrow it down to the nibble */ + if (Sgl_iszero_hiddenhigh3mantissa(resultp1)) { + /* The lower nibble contains the + * normalizing one */ + Sglext_leftshiftby4(resultp1,resultp2); + result_exponent -= 4; + } + /* Select case where first bit is set (already + * normalized) otherwise select the proper shift. */ + jumpsize = Sgl_hiddenhigh3mantissa(resultp1); + if (jumpsize <= 7) switch(jumpsize) { + case 1: + Sglext_leftshiftby3(resultp1,resultp2); + result_exponent -= 3; + break; + case 2: + case 3: + Sglext_leftshiftby2(resultp1,resultp2); + result_exponent -= 2; + break; + case 4: + case 5: + case 6: + case 7: + Sglext_leftshiftby1(resultp1,resultp2); + result_exponent -= 1; + break; + } + } /* end if (hidden...)... */ + /* Fall through and round */ + } /* end if (save < 0)... */ + else { + /* Add magnitudes */ + Sglext_addition(tmpresp1,tmpresp2, + rightp1,rightp2, /*to*/resultp1,resultp2); + sign_save = Sgl_signextendedsign(resultp1); + if (Sgl_isone_hiddenoverflow(resultp1)) { + /* Prenormalization required. */ + Sglext_arithrightshiftby1(resultp1,resultp2); + result_exponent++; + } /* end if hiddenoverflow... */ + } /* end else ...add magnitudes... */ + + /* Round the result. If the extension and lower two words are + * all zeros, then the result is exact. Otherwise round in the + * correct direction. Underflow is possible. If a postnormalization + * is necessary, then the mantissa is all zeros so no shift is needed. + */ + round: + if (result_exponent <= 0 && !Is_underflowtrap_enabled()) { + Sglext_denormalize(resultp1,resultp2,result_exponent,is_tiny); + } + Sgl_set_sign(resultp1,/*using*/sign_save); + if (Sglext_isnotzero_mantissap2(resultp2)) { + inexact = TRUE; + switch(Rounding_mode()) { + case ROUNDNEAREST: /* The default. */ + if (Sglext_isone_highp2(resultp2)) { + /* at least 1/2 ulp */ + if (Sglext_isnotzero_low31p2(resultp2) || + Sglext_isone_lowp1(resultp1)) { + /* either exactly half way and odd or + * more than 1/2ulp */ + Sgl_increment(resultp1); + } + } + break; + + case ROUNDPLUS: + if (Sgl_iszero_sign(resultp1)) { + /* Round up positive results */ + Sgl_increment(resultp1); + } + break; + + case ROUNDMINUS: + if (Sgl_isone_sign(resultp1)) { + /* Round down negative results */ + Sgl_increment(resultp1); + } + + case ROUNDZERO:; + /* truncate is simple */ + } /* end switch... */ + if (Sgl_isone_hiddenoverflow(resultp1)) result_exponent++; + } + if (result_exponent >= SGL_INFINITY_EXPONENT) { + /* Overflow */ + if (Is_overflowtrap_enabled()) { + /* + * Adjust bias of result + */ + Sgl_setwrapped_exponent(resultp1,result_exponent,ovfl); + Sgl_copytoptr(resultp1,dstptr); + if (inexact) + if (Is_inexacttrap_enabled()) + return (OPC_2E_OVERFLOWEXCEPTION | + OPC_2E_INEXACTEXCEPTION); + else Set_inexactflag(); + return (OPC_2E_OVERFLOWEXCEPTION); + } + inexact = TRUE; + Set_overflowflag(); + Sgl_setoverflow(resultp1); + } else if (result_exponent <= 0) { /* underflow case */ + if (Is_underflowtrap_enabled()) { + /* + * Adjust bias of result + */ + Sgl_setwrapped_exponent(resultp1,result_exponent,unfl); + Sgl_copytoptr(resultp1,dstptr); + if (inexact) + if (Is_inexacttrap_enabled()) + return (OPC_2E_UNDERFLOWEXCEPTION | + OPC_2E_INEXACTEXCEPTION); + else Set_inexactflag(); + return(OPC_2E_UNDERFLOWEXCEPTION); + } + else if (inexact && is_tiny) Set_underflowflag(); + } + else Sgl_set_exponent(resultp1,result_exponent); + Sgl_copytoptr(resultp1,dstptr); + if (inexact) + if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION); + else Set_inexactflag(); + return(NOEXCEPTION); +} + +/* + * Single Floating-point Multiply Negate Fused Add + */ + +sgl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr) + +sgl_floating_point *src1ptr, *src2ptr, *src3ptr, *dstptr; +unsigned int *status; +{ + unsigned int opnd1, opnd2, opnd3; + register unsigned int tmpresp1, tmpresp2; + unsigned int rightp1, rightp2; + unsigned int resultp1, resultp2 = 0; + register int mpy_exponent, add_exponent, count; + boolean inexact = FALSE, is_tiny = FALSE; + + unsigned int signlessleft1, signlessright1, save; + register int result_exponent, diff_exponent; + int sign_save, jumpsize; + + Sgl_copyfromptr(src1ptr,opnd1); + Sgl_copyfromptr(src2ptr,opnd2); + Sgl_copyfromptr(src3ptr,opnd3); + + /* + * set sign bit of result of multiply + */ + if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2)) + Sgl_setzero(resultp1); + else + Sgl_setnegativezero(resultp1); + + /* + * Generate multiply exponent + */ + mpy_exponent = Sgl_exponent(opnd1) + Sgl_exponent(opnd2) - SGL_BIAS; + + /* + * check first operand for NaN's or infinity + */ + if (Sgl_isinfinity_exponent(opnd1)) { + if (Sgl_iszero_mantissa(opnd1)) { + if (Sgl_isnotnan(opnd2) && Sgl_isnotnan(opnd3)) { + if (Sgl_iszero_exponentmantissa(opnd2)) { + /* + * invalid since operands are infinity + * and zero + */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + Set_invalidflag(); + Sgl_makequietnan(resultp1); + Sgl_copytoptr(resultp1,dstptr); + return(NOEXCEPTION); + } + /* + * Check third operand for infinity with a + * sign opposite of the multiply result + */ + if (Sgl_isinfinity(opnd3) && + (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) { + /* + * invalid since attempting a magnitude + * subtraction of infinities + */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + Set_invalidflag(); + Sgl_makequietnan(resultp1); + Sgl_copytoptr(resultp1,dstptr); + return(NOEXCEPTION); + } + + /* + * return infinity + */ + Sgl_setinfinity_exponentmantissa(resultp1); + Sgl_copytoptr(resultp1,dstptr); + return(NOEXCEPTION); + } + } + else { + /* + * is NaN; signaling or quiet? + */ + if (Sgl_isone_signaling(opnd1)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Sgl_set_quiet(opnd1); + } + /* + * is second operand a signaling NaN? + */ + else if (Sgl_is_signalingnan(opnd2)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Sgl_set_quiet(opnd2); + Sgl_copytoptr(opnd2,dstptr); + return(NOEXCEPTION); + } + /* + * is third operand a signaling NaN? + */ + else if (Sgl_is_signalingnan(opnd3)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Sgl_set_quiet(opnd3); + Sgl_copytoptr(opnd3,dstptr); + return(NOEXCEPTION); + } + /* + * return quiet NaN + */ + Sgl_copytoptr(opnd1,dstptr); + return(NOEXCEPTION); + } + } + + /* + * check second operand for NaN's or infinity + */ + if (Sgl_isinfinity_exponent(opnd2)) { + if (Sgl_iszero_mantissa(opnd2)) { + if (Sgl_isnotnan(opnd3)) { + if (Sgl_iszero_exponentmantissa(opnd1)) { + /* + * invalid since multiply operands are + * zero & infinity + */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + Set_invalidflag(); + Sgl_makequietnan(opnd2); + Sgl_copytoptr(opnd2,dstptr); + return(NOEXCEPTION); + } + + /* + * Check third operand for infinity with a + * sign opposite of the multiply result + */ + if (Sgl_isinfinity(opnd3) && + (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) { + /* + * invalid since attempting a magnitude + * subtraction of infinities + */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + Set_invalidflag(); + Sgl_makequietnan(resultp1); + Sgl_copytoptr(resultp1,dstptr); + return(NOEXCEPTION); + } + + /* + * return infinity + */ + Sgl_setinfinity_exponentmantissa(resultp1); + Sgl_copytoptr(resultp1,dstptr); + return(NOEXCEPTION); + } + } + else { + /* + * is NaN; signaling or quiet? + */ + if (Sgl_isone_signaling(opnd2)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Sgl_set_quiet(opnd2); + } + /* + * is third operand a signaling NaN? + */ + else if (Sgl_is_signalingnan(opnd3)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Sgl_set_quiet(opnd3); + Sgl_copytoptr(opnd3,dstptr); + return(NOEXCEPTION); + } + /* + * return quiet NaN + */ + Sgl_copytoptr(opnd2,dstptr); + return(NOEXCEPTION); + } + } + + /* + * check third operand for NaN's or infinity + */ + if (Sgl_isinfinity_exponent(opnd3)) { + if (Sgl_iszero_mantissa(opnd3)) { + /* return infinity */ + Sgl_copytoptr(opnd3,dstptr); + return(NOEXCEPTION); + } else { + /* + * is NaN; signaling or quiet? + */ + if (Sgl_isone_signaling(opnd3)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(OPC_2E_INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Sgl_set_quiet(opnd3); + } + /* + * return quiet NaN + */ + Sgl_copytoptr(opnd3,dstptr); + return(NOEXCEPTION); + } + } + + /* + * Generate multiply mantissa + */ + if (Sgl_isnotzero_exponent(opnd1)) { + /* set hidden bit */ + Sgl_clear_signexponent_set_hidden(opnd1); + } + else { + /* check for zero */ + if (Sgl_iszero_mantissa(opnd1)) { + /* + * Perform the add opnd3 with zero here. + */ + if (Sgl_iszero_exponentmantissa(opnd3)) { + if (Is_rounding_mode(ROUNDMINUS)) { + Sgl_or_signs(opnd3,resultp1); + } else { + Sgl_and_signs(opnd3,resultp1); + } + } + /* + * Now let's check for trapped underflow case. + */ + else if (Sgl_iszero_exponent(opnd3) && + Is_underflowtrap_enabled()) { + /* need to normalize results mantissa */ + sign_save = Sgl_signextendedsign(opnd3); + result_exponent = 0; + Sgl_leftshiftby1(opnd3); + Sgl_normalize(opnd3,result_exponent); + Sgl_set_sign(opnd3,/*using*/sign_save); + Sgl_setwrapped_exponent(opnd3,result_exponent, + unfl); + Sgl_copytoptr(opnd3,dstptr); + /* inexact = FALSE */ + return(OPC_2E_UNDERFLOWEXCEPTION); + } + Sgl_copytoptr(opnd3,dstptr); + return(NOEXCEPTION); + } + /* is denormalized, adjust exponent */ + Sgl_clear_signexponent(opnd1); + Sgl_leftshiftby1(opnd1); + Sgl_normalize(opnd1,mpy_exponent); + } + /* opnd2 needs to have hidden bit set with msb in hidden bit */ + if (Sgl_isnotzero_exponent(opnd2)) { + Sgl_clear_signexponent_set_hidden(opnd2); + } + else { + /* check for zero */ + if (Sgl_iszero_mantissa(opnd2)) { + /* + * Perform the add opnd3 with zero here. + */ + if (Sgl_iszero_exponentmantissa(opnd3)) { + if (Is_rounding_mode(ROUNDMINUS)) { + Sgl_or_signs(opnd3,resultp1); + } else { + Sgl_and_signs(opnd3,resultp1); + } + } + /* + * Now let's check for trapped underflow case. + */ + else if (Sgl_iszero_exponent(opnd3) && + Is_underflowtrap_enabled()) { + /* need to normalize results mantissa */ + sign_save = Sgl_signextendedsign(opnd3); + result_exponent = 0; + Sgl_leftshiftby1(opnd3); + Sgl_normalize(opnd3,result_exponent); + Sgl_set_sign(opnd3,/*using*/sign_save); + Sgl_setwrapped_exponent(opnd3,result_exponent, + unfl); + Sgl_copytoptr(opnd3,dstptr); + /* inexact = FALSE */ + return(OPC_2E_UNDERFLOWEXCEPTION); + } + Sgl_copytoptr(opnd3,dstptr); + return(NOEXCEPTION); + } + /* is denormalized; want to normalize */ + Sgl_clear_signexponent(opnd2); + Sgl_leftshiftby1(opnd2); + Sgl_normalize(opnd2,mpy_exponent); + } + + /* Multiply the first two source mantissas together */ + + /* + * The intermediate result will be kept in tmpres, + * which needs enough room for 106 bits of mantissa, + * so lets call it a Double extended. + */ + Sglext_setzero(tmpresp1,tmpresp2); + + /* + * Four bits at a time are inspected in each loop, and a + * simple shift and add multiply algorithm is used. + */ + for (count = SGL_P-1; count >= 0; count -= 4) { + Sglext_rightshiftby4(tmpresp1,tmpresp2); + if (Sbit28(opnd1)) { + /* Twoword_add should be an ADD followed by 2 ADDC's */ + Twoword_add(tmpresp1, tmpresp2, opnd2<<3, 0); + } + if (Sbit29(opnd1)) { + Twoword_add(tmpresp1, tmpresp2, opnd2<<2, 0); + } + if (Sbit30(opnd1)) { + Twoword_add(tmpresp1, tmpresp2, opnd2<<1, 0); + } + if (Sbit31(opnd1)) { + Twoword_add(tmpresp1, tmpresp2, opnd2, 0); + } + Sgl_rightshiftby4(opnd1); + } + if (Is_sexthiddenoverflow(tmpresp1)) { + /* result mantissa >= 2 (mantissa overflow) */ + mpy_exponent++; + Sglext_rightshiftby4(tmpresp1,tmpresp2); + } else { + Sglext_rightshiftby3(tmpresp1,tmpresp2); + } + + /* + * Restore the sign of the mpy result which was saved in resultp1. + * The exponent will continue to be kept in mpy_exponent. + */ + Sglext_set_sign(tmpresp1,Sgl_sign(resultp1)); + + /* + * No rounding is required, since the result of the multiply + * is exact in the extended format. + */ + + /* + * Now we are ready to perform the add portion of the operation. + * + * The exponents need to be kept as integers for now, since the + * multiply result might not fit into the exponent field. We + * can't overflow or underflow because of this yet, since the + * add could bring the final result back into range. + */ + add_exponent = Sgl_exponent(opnd3); + + /* + * Check for denormalized or zero add operand. + */ + if (add_exponent == 0) { + /* check for zero */ + if (Sgl_iszero_mantissa(opnd3)) { + /* right is zero */ + /* Left can't be zero and must be result. + * + * The final result is now in tmpres and mpy_exponent, + * and needs to be rounded and squeezed back into + * double precision format from double extended. + */ + result_exponent = mpy_exponent; + Sglext_copy(tmpresp1,tmpresp2,resultp1,resultp2); + sign_save = Sgl_signextendedsign(resultp1);/*save sign*/ + goto round; + } + + /* + * Neither are zeroes. + * Adjust exponent and normalize add operand. + */ + sign_save = Sgl_signextendedsign(opnd3); /* save sign */ + Sgl_clear_signexponent(opnd3); + Sgl_leftshiftby1(opnd3); + Sgl_normalize(opnd3,add_exponent); + Sgl_set_sign(opnd3,sign_save); /* restore sign */ + } else { + Sgl_clear_exponent_set_hidden(opnd3); + } + /* + * Copy opnd3 to the double extended variable called right. + */ + Sgl_copyto_sglext(opnd3,rightp1,rightp2); + + /* + * A zero "save" helps discover equal operands (for later), + * and is used in swapping operands (if needed). + */ + Sglext_xortointp1(tmpresp1,rightp1,/*to*/save); + + /* + * Compare magnitude of operands. + */ + Sglext_copytoint_exponentmantissa(tmpresp1,signlessleft1); + Sglext_copytoint_exponentmantissa(rightp1,signlessright1); + if (mpy_exponent < add_exponent || mpy_exponent == add_exponent && + Sglext_ismagnitudeless(signlessleft1,signlessright1)) { + /* + * Set the left operand to the larger one by XOR swap. + * First finish the first word "save". + */ + Sglext_xorfromintp1(save,rightp1,/*to*/rightp1); + Sglext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1); + Sglext_swap_lower(tmpresp2,rightp2); + /* also setup exponents used in rest of routine */ + diff_exponent = add_exponent - mpy_exponent; + result_exponent = add_exponent; + } else { + /* also setup exponents used in rest of routine */ + diff_exponent = mpy_exponent - add_exponent; + result_exponent = mpy_exponent; + } + /* Invariant: left is not smaller than right. */ + + /* + * Special case alignment of operands that would force alignment + * beyond the extent of the extension. A further optimization + * could special case this but only reduces the path length for + * this infrequent case. + */ + if (diff_exponent > SGLEXT_THRESHOLD) { + diff_exponent = SGLEXT_THRESHOLD; + } + + /* Align right operand by shifting it to the right */ + Sglext_clear_sign(rightp1); + Sglext_right_align(rightp1,rightp2,/*shifted by*/diff_exponent); + + /* Treat sum and difference of the operands separately. */ + if ((int)save < 0) { + /* + * Difference of the two operands. Overflow can occur if the + * multiply overflowed. A borrow can occur out of the hidden + * bit and force a post normalization phase. + */ + Sglext_subtract(tmpresp1,tmpresp2, rightp1,rightp2, + resultp1,resultp2); + sign_save = Sgl_signextendedsign(resultp1); + if (Sgl_iszero_hidden(resultp1)) { + /* Handle normalization */ + /* A straight foward algorithm would now shift the + * result and extension left until the hidden bit + * becomes one. Not all of the extension bits need + * participate in the shift. Only the two most + * significant bits (round and guard) are needed. + * If only a single shift is needed then the guard + * bit becomes a significant low order bit and the + * extension must participate in the rounding. + * If more than a single shift is needed, then all + * bits to the right of the guard bit are zeros, + * and the guard bit may or may not be zero. */ + Sglext_leftshiftby1(resultp1,resultp2); + + /* Need to check for a zero result. The sign and + * exponent fields have already been zeroed. The more + * efficient test of the full object can be used. + */ + if (Sglext_iszero(resultp1,resultp2)) { + /* Must have been "x-x" or "x+(-x)". */ + if (Is_rounding_mode(ROUNDMINUS)) + Sgl_setone_sign(resultp1); + Sgl_copytoptr(resultp1,dstptr); + return(NOEXCEPTION); + } + result_exponent--; + + /* Look to see if normalization is finished. */ + if (Sgl_isone_hidden(resultp1)) { + /* No further normalization is needed */ + goto round; + } + + /* Discover first one bit to determine shift amount. + * Use a modified binary search. We have already + * shifted the result one position right and still + * not found a one so the remainder of the extension + * must be zero and simplifies rounding. */ + /* Scan bytes */ + while (Sgl_iszero_hiddenhigh7mantissa(resultp1)) { + Sglext_leftshiftby8(resultp1,resultp2); + result_exponent -= 8; + } + /* Now narrow it down to the nibble */ + if (Sgl_iszero_hiddenhigh3mantissa(resultp1)) { + /* The lower nibble contains the + * normalizing one */ + Sglext_leftshiftby4(resultp1,resultp2); + result_exponent -= 4; + } + /* Select case where first bit is set (already + * normalized) otherwise select the proper shift. */ + jumpsize = Sgl_hiddenhigh3mantissa(resultp1); + if (jumpsize <= 7) switch(jumpsize) { + case 1: + Sglext_leftshiftby3(resultp1,resultp2); + result_exponent -= 3; + break; + case 2: + case 3: + Sglext_leftshiftby2(resultp1,resultp2); + result_exponent -= 2; + break; + case 4: + case 5: + case 6: + case 7: + Sglext_leftshiftby1(resultp1,resultp2); + result_exponent -= 1; + break; + } + } /* end if (hidden...)... */ + /* Fall through and round */ + } /* end if (save < 0)... */ + else { + /* Add magnitudes */ + Sglext_addition(tmpresp1,tmpresp2, + rightp1,rightp2, /*to*/resultp1,resultp2); + sign_save = Sgl_signextendedsign(resultp1); + if (Sgl_isone_hiddenoverflow(resultp1)) { + /* Prenormalization required. */ + Sglext_arithrightshiftby1(resultp1,resultp2); + result_exponent++; + } /* end if hiddenoverflow... */ + } /* end else ...add magnitudes... */ + + /* Round the result. If the extension and lower two words are + * all zeros, then the result is exact. Otherwise round in the + * correct direction. Underflow is possible. If a postnormalization + * is necessary, then the mantissa is all zeros so no shift is needed. + */ + round: + if (result_exponent <= 0 && !Is_underflowtrap_enabled()) { + Sglext_denormalize(resultp1,resultp2,result_exponent,is_tiny); + } + Sgl_set_sign(resultp1,/*using*/sign_save); + if (Sglext_isnotzero_mantissap2(resultp2)) { + inexact = TRUE; + switch(Rounding_mode()) { + case ROUNDNEAREST: /* The default. */ + if (Sglext_isone_highp2(resultp2)) { + /* at least 1/2 ulp */ + if (Sglext_isnotzero_low31p2(resultp2) || + Sglext_isone_lowp1(resultp1)) { + /* either exactly half way and odd or + * more than 1/2ulp */ + Sgl_increment(resultp1); + } + } + break; + + case ROUNDPLUS: + if (Sgl_iszero_sign(resultp1)) { + /* Round up positive results */ + Sgl_increment(resultp1); + } + break; + + case ROUNDMINUS: + if (Sgl_isone_sign(resultp1)) { + /* Round down negative results */ + Sgl_increment(resultp1); + } + + case ROUNDZERO:; + /* truncate is simple */ + } /* end switch... */ + if (Sgl_isone_hiddenoverflow(resultp1)) result_exponent++; + } + if (result_exponent >= SGL_INFINITY_EXPONENT) { + /* Overflow */ + if (Is_overflowtrap_enabled()) { + /* + * Adjust bias of result + */ + Sgl_setwrapped_exponent(resultp1,result_exponent,ovfl); + Sgl_copytoptr(resultp1,dstptr); + if (inexact) + if (Is_inexacttrap_enabled()) + return (OPC_2E_OVERFLOWEXCEPTION | + OPC_2E_INEXACTEXCEPTION); + else Set_inexactflag(); + return (OPC_2E_OVERFLOWEXCEPTION); + } + inexact = TRUE; + Set_overflowflag(); + Sgl_setoverflow(resultp1); + } else if (result_exponent <= 0) { /* underflow case */ + if (Is_underflowtrap_enabled()) { + /* + * Adjust bias of result + */ + Sgl_setwrapped_exponent(resultp1,result_exponent,unfl); + Sgl_copytoptr(resultp1,dstptr); + if (inexact) + if (Is_inexacttrap_enabled()) + return (OPC_2E_UNDERFLOWEXCEPTION | + OPC_2E_INEXACTEXCEPTION); + else Set_inexactflag(); + return(OPC_2E_UNDERFLOWEXCEPTION); + } + else if (inexact && is_tiny) Set_underflowflag(); + } + else Sgl_set_exponent(resultp1,result_exponent); + Sgl_copytoptr(resultp1,dstptr); + if (inexact) + if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION); + else Set_inexactflag(); + return(NOEXCEPTION); +} + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/fpbits.h linux.19rc3-ac4/arch/parisc/math-emu/fpbits.h --- linux.19rc3/arch/parisc/math-emu/fpbits.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/fpbits.h 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,65 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifdef __NO_PA_HDRS + PA header file -- do not include this header file for non-PA builds. +#endif + + +/* + * These macros are designed to be portable to all machines that have + * a wordsize greater than or equal to 32 bits that support the portable + * C compiler and the standard C preprocessor. Wordsize (default 32) + * and bitfield assignment (default left-to-right, unlike VAX, PDP-11) + * should be predefined using the constants HOSTWDSZ and BITFRL and + * the C compiler "-D" flag (e.g., -DHOSTWDSZ=36 -DBITFLR for the DEC-20). + * Note that the macro arguments assume that the integer being referenced + * is a 32-bit integer (right-justified on the 20) and that bit 0 is the + * most significant bit. + */ + +#ifndef HOSTWDSZ +#define HOSTWDSZ 32 +#endif + + +/*########################### Macros ######################################*/ + +/*------------------------------------------------------------------------- + * NewDeclareBitField_Reference - Declare a structure similar to the simulator + * function "DeclBitfR" except its use is restricted to occur within a larger + * enclosing structure or union definition. This declaration is an unnamed + * structure with the argument, name, as the member name and the argument, + * uname, as the element name. + *----------------------------------------------------------------------- */ +#define Bitfield_extract(start, length, object) \ + ((object) >> (HOSTWDSZ - (start) - (length)) & \ + ((unsigned)-1 >> (HOSTWDSZ - (length)))) + +#define Bitfield_signed_extract(start, length, object) \ + ((int)((object) << start) >> (HOSTWDSZ - (length))) + +#define Bitfield_mask(start, len, object) \ + ((object) & (((unsigned)-1 >> (HOSTWDSZ-len)) << (HOSTWDSZ-start-len))) + +#define Bitfield_deposit(value,start,len,object) object = \ + ((object) & ~(((unsigned)-1 >> (HOSTWDSZ-len)) << (HOSTWDSZ-start-len))) | \ + (((value) & ((unsigned)-1 >> (HOSTWDSZ-len))) << (HOSTWDSZ-start-len)) diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/fpudispatch.c linux.19rc3-ac4/arch/parisc/math-emu/fpudispatch.c --- linux.19rc3/arch/parisc/math-emu/fpudispatch.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/fpudispatch.c 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,1425 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * BEGIN_DESC + * + * File: + * @(#) pa/fp/fpudispatch.c $Revision: 1.1 $ + * + * Purpose: + * <> + * + * External Interfaces: + * <> + * emfpudispatch(ir, dummy1, dummy2, fpregs) + * fpudispatch(ir, excp_code, holder, fpregs) + * + * Internal Interfaces: + * <> + * static u_int decode_06(u_int, u_int *) + * static u_int decode_0c(u_int, u_int, u_int, u_int *) + * static u_int decode_0e(u_int, u_int, u_int, u_int *) + * static u_int decode_26(u_int, u_int *) + * static u_int decode_2e(u_int, u_int *) + * static void update_status_cbit(u_int *, u_int, u_int, u_int) + * + * Theory: + * <> + * + * END_DESC +*/ + +#define FPUDEBUG 0 + +#include "float.h" +#include "types.h" +/* #include */ +/* #include */ + +#define COPR_INST 0x30000000 + +/* + * definition of extru macro. If pos and len are constants, the compiler + * will generate an extru instruction when optimized + */ +#define extru(r,pos,len) (((r) >> (31-(pos))) & (( 1 << (len)) - 1)) +/* definitions of bit field locations in the instruction */ +#define fpmajorpos 5 +#define fpr1pos 10 +#define fpr2pos 15 +#define fptpos 31 +#define fpsubpos 18 +#define fpclass1subpos 16 +#define fpclasspos 22 +#define fpfmtpos 20 +#define fpdfpos 18 +#define fpnulpos 26 +/* + * the following are the extra bits for the 0E major op + */ +#define fpxr1pos 24 +#define fpxr2pos 19 +#define fpxtpos 25 +#define fpxpos 23 +#define fp0efmtpos 20 +/* + * the following are for the multi-ops + */ +#define fprm1pos 10 +#define fprm2pos 15 +#define fptmpos 31 +#define fprapos 25 +#define fptapos 20 +#define fpmultifmt 26 +/* + * the following are for the fused FP instructions + */ + /* fprm1pos 10 */ + /* fprm2pos 15 */ +#define fpraupos 18 +#define fpxrm2pos 19 + /* fpfmtpos 20 */ +#define fpralpos 23 +#define fpxrm1pos 24 + /* fpxtpos 25 */ +#define fpfusedsubop 26 + /* fptpos 31 */ + +/* + * offset to constant zero in the FP emulation registers + */ +#define fpzeroreg (32*sizeof(double)/sizeof(u_int)) + +/* + * extract the major opcode from the instruction + */ +#define get_major(op) extru(op,fpmajorpos,6) +/* + * extract the two bit class field from the FP instruction. The class is at bit + * positions 21-22 + */ +#define get_class(op) extru(op,fpclasspos,2) +/* + * extract the 3 bit subop field. For all but class 1 instructions, it is + * located at bit positions 16-18 + */ +#define get_subop(op) extru(op,fpsubpos,3) +/* + * extract the 2 or 3 bit subop field from class 1 instructions. It is located + * at bit positions 15-16 (PA1.1) or 14-16 (PA2.0) + */ +#define get_subop1_PA1_1(op) extru(op,fpclass1subpos,2) /* PA89 (1.1) fmt */ +#define get_subop1_PA2_0(op) extru(op,fpclass1subpos,3) /* PA 2.0 fmt */ + +/* definitions of unimplemented exceptions */ +#define MAJOR_0C_EXCP 0x09 +#define MAJOR_0E_EXCP 0x0b +#define MAJOR_06_EXCP 0x03 +#define MAJOR_26_EXCP 0x23 +#define MAJOR_2E_EXCP 0x2b +#define PA83_UNIMP_EXCP 0x01 + +/* + * Special Defines for TIMEX specific code + */ + +#define FPU_TYPE_FLAG_POS (EM_FPU_TYPE_OFFSET>>2) +#define TIMEX_ROLEX_FPU_MASK (TIMEX_EXTEN_FLAG|ROLEX_EXTEN_FLAG) + +/* + * Static function definitions + */ +#define _PROTOTYPES +#if defined(_PROTOTYPES) || defined(_lint) +static u_int decode_0c(u_int, u_int, u_int, u_int *); +static u_int decode_0e(u_int, u_int, u_int, u_int *); +static u_int decode_06(u_int, u_int *); +static u_int decode_26(u_int, u_int *); +static u_int decode_2e(u_int, u_int *); +static void update_status_cbit(u_int *, u_int, u_int, u_int); +#else /* !_PROTOTYPES&&!_lint */ +static u_int decode_0c(); +static u_int decode_0e(); +static u_int decode_06(); +static u_int decode_26(); +static u_int decode_2e(); +static void update_status_cbit(); +#endif /* _PROTOTYPES&&!_lint */ + +#define VASSERT(x) + +/* + * this routine will decode the excepting floating point instruction and + * call the approiate emulation routine. + * It is called by decode_fpu with the following parameters: + * fpudispatch(current_ir, unimplemented_code, 0, &Fpu_register) + * where current_ir is the instruction to be emulated, + * unimplemented_code is the exception_code that the hardware generated + * and &Fpu_register is the address of emulated FP reg 0. + */ +u_int +fpudispatch(u_int ir, u_int excp_code, u_int holder, u_int fpregs[]) +{ + u_int class, subop; + u_int fpu_type_flags; + + /* All FP emulation code assumes that ints are 4-bytes in length */ + VASSERT(sizeof(int) == 4); + + fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */ + + class = get_class(ir); + if (class == 1) { + if (fpu_type_flags & PA2_0_FPU_FLAG) + subop = get_subop1_PA2_0(ir); + else + subop = get_subop1_PA1_1(ir); + } + else + subop = get_subop(ir); + + if (FPUDEBUG) printk("class %d subop %d\n", class, subop); + + switch (excp_code) { + case MAJOR_0C_EXCP: + case PA83_UNIMP_EXCP: + return(decode_0c(ir,class,subop,fpregs)); + case MAJOR_0E_EXCP: + return(decode_0e(ir,class,subop,fpregs)); + case MAJOR_06_EXCP: + return(decode_06(ir,fpregs)); + case MAJOR_26_EXCP: + return(decode_26(ir,fpregs)); + case MAJOR_2E_EXCP: + return(decode_2e(ir,fpregs)); + default: + /* "crashme Night Gallery painting nr 2. (asm_crash.s). + * This was fixed for multi-user kernels, but + * workstation kernels had a panic here. This allowed + * any arbitrary user to panic the kernel by executing + * setting the FP exception registers to strange values + * and generating an emulation trap. The emulation and + * exception code must never be able to panic the + * kernel. + */ + return(UNIMPLEMENTEDEXCEPTION); + } +} + +/* + * this routine is called by $emulation_trap to emulate a coprocessor + * instruction if one doesn't exist + */ +u_int +emfpudispatch(u_int ir, u_int dummy1, u_int dummy2, u_int fpregs[]) +{ + u_int class, subop, major; + u_int fpu_type_flags; + + /* All FP emulation code assumes that ints are 4-bytes in length */ + VASSERT(sizeof(int) == 4); + + fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */ + + major = get_major(ir); + class = get_class(ir); + if (class == 1) { + if (fpu_type_flags & PA2_0_FPU_FLAG) + subop = get_subop1_PA2_0(ir); + else + subop = get_subop1_PA1_1(ir); + } + else + subop = get_subop(ir); + switch (major) { + case 0x0C: + return(decode_0c(ir,class,subop,fpregs)); + case 0x0E: + return(decode_0e(ir,class,subop,fpregs)); + case 0x06: + return(decode_06(ir,fpregs)); + case 0x26: + return(decode_26(ir,fpregs)); + case 0x2E: + return(decode_2e(ir,fpregs)); + default: + return(PA83_UNIMP_EXCP); + } +} + + +static u_int +decode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[]) +{ + u_int r1,r2,t; /* operand register offsets */ + u_int fmt; /* also sf for class 1 conversions */ + u_int df; /* for class 1 conversions */ + u_int *status; + u_int retval, local_status; + u_int fpu_type_flags; + + if (ir == COPR_INST) { + fpregs[0] = EMULATION_VERSION << 11; + return(NOEXCEPTION); + } + status = &fpregs[0]; /* fp status register */ + local_status = fpregs[0]; /* and local copy */ + r1 = extru(ir,fpr1pos,5) * sizeof(double)/sizeof(u_int); + if (r1 == 0) /* map fr0 source to constant zero */ + r1 = fpzeroreg; + t = extru(ir,fptpos,5) * sizeof(double)/sizeof(u_int); + if (t == 0 && class != 2) /* don't allow fr0 as a dest */ + return(MAJOR_0C_EXCP); + fmt = extru(ir,fpfmtpos,2); /* get fmt completer */ + + switch (class) { + case 0: + switch (subop) { + case 0: /* COPR 0,0 emulated above*/ + case 1: + return(MAJOR_0C_EXCP); + case 2: /* FCPY */ + switch (fmt) { + case 2: /* illegal */ + return(MAJOR_0C_EXCP); + case 3: /* quad */ + t &= ~3; /* force to even reg #s */ + r1 &= ~3; + fpregs[t+3] = fpregs[r1+3]; + fpregs[t+2] = fpregs[r1+2]; + case 1: /* double */ + fpregs[t+1] = fpregs[r1+1]; + case 0: /* single */ + fpregs[t] = fpregs[r1]; + return(NOEXCEPTION); + } + case 3: /* FABS */ + switch (fmt) { + case 2: /* illegal */ + return(MAJOR_0C_EXCP); + case 3: /* quad */ + t &= ~3; /* force to even reg #s */ + r1 &= ~3; + fpregs[t+3] = fpregs[r1+3]; + fpregs[t+2] = fpregs[r1+2]; + case 1: /* double */ + fpregs[t+1] = fpregs[r1+1]; + case 0: /* single */ + /* copy and clear sign bit */ + fpregs[t] = fpregs[r1] & 0x7fffffff; + return(NOEXCEPTION); + } + case 6: /* FNEG */ + switch (fmt) { + case 2: /* illegal */ + return(MAJOR_0C_EXCP); + case 3: /* quad */ + t &= ~3; /* force to even reg #s */ + r1 &= ~3; + fpregs[t+3] = fpregs[r1+3]; + fpregs[t+2] = fpregs[r1+2]; + case 1: /* double */ + fpregs[t+1] = fpregs[r1+1]; + case 0: /* single */ + /* copy and invert sign bit */ + fpregs[t] = fpregs[r1] ^ 0x80000000; + return(NOEXCEPTION); + } + case 7: /* FNEGABS */ + switch (fmt) { + case 2: /* illegal */ + return(MAJOR_0C_EXCP); + case 3: /* quad */ + t &= ~3; /* force to even reg #s */ + r1 &= ~3; + fpregs[t+3] = fpregs[r1+3]; + fpregs[t+2] = fpregs[r1+2]; + case 1: /* double */ + fpregs[t+1] = fpregs[r1+1]; + case 0: /* single */ + /* copy and set sign bit */ + fpregs[t] = fpregs[r1] | 0x80000000; + return(NOEXCEPTION); + } + case 4: /* FSQRT */ + switch (fmt) { + case 0: + return(sgl_fsqrt(&fpregs[r1],0, + &fpregs[t],status)); + case 1: + return(dbl_fsqrt(&fpregs[r1],0, + &fpregs[t],status)); + case 2: + case 3: /* quad not implemented */ + return(MAJOR_0C_EXCP); + } + case 5: /* FRND */ + switch (fmt) { + case 0: + return(sgl_frnd(&fpregs[r1],0, + &fpregs[t],status)); + case 1: + return(dbl_frnd(&fpregs[r1],0, + &fpregs[t],status)); + case 2: + case 3: /* quad not implemented */ + return(MAJOR_0C_EXCP); + } + } /* end of switch (subop) */ + + case 1: /* class 1 */ + df = extru(ir,fpdfpos,2); /* get dest format */ + if ((df & 2) || (fmt & 2)) { + /* + * fmt's 2 and 3 are illegal of not implemented + * quad conversions + */ + return(MAJOR_0C_EXCP); + } + /* + * encode source and dest formats into 2 bits. + * high bit is source, low bit is dest. + * bit = 1 --> double precision + */ + fmt = (fmt << 1) | df; + switch (subop) { + case 0: /* FCNVFF */ + switch(fmt) { + case 0: /* sgl/sgl */ + return(MAJOR_0C_EXCP); + case 1: /* sgl/dbl */ + return(sgl_to_dbl_fcnvff(&fpregs[r1],0, + &fpregs[t],status)); + case 2: /* dbl/sgl */ + return(dbl_to_sgl_fcnvff(&fpregs[r1],0, + &fpregs[t],status)); + case 3: /* dbl/dbl */ + return(MAJOR_0C_EXCP); + } + case 1: /* FCNVXF */ + switch(fmt) { + case 0: /* sgl/sgl */ + return(sgl_to_sgl_fcnvxf(&fpregs[r1],0, + &fpregs[t],status)); + case 1: /* sgl/dbl */ + return(sgl_to_dbl_fcnvxf(&fpregs[r1],0, + &fpregs[t],status)); + case 2: /* dbl/sgl */ + return(dbl_to_sgl_fcnvxf(&fpregs[r1],0, + &fpregs[t],status)); + case 3: /* dbl/dbl */ + return(dbl_to_dbl_fcnvxf(&fpregs[r1],0, + &fpregs[t],status)); + } + case 2: /* FCNVFX */ + switch(fmt) { + case 0: /* sgl/sgl */ + return(sgl_to_sgl_fcnvfx(&fpregs[r1],0, + &fpregs[t],status)); + case 1: /* sgl/dbl */ + return(sgl_to_dbl_fcnvfx(&fpregs[r1],0, + &fpregs[t],status)); + case 2: /* dbl/sgl */ + return(dbl_to_sgl_fcnvfx(&fpregs[r1],0, + &fpregs[t],status)); + case 3: /* dbl/dbl */ + return(dbl_to_dbl_fcnvfx(&fpregs[r1],0, + &fpregs[t],status)); + } + case 3: /* FCNVFXT */ + switch(fmt) { + case 0: /* sgl/sgl */ + return(sgl_to_sgl_fcnvfxt(&fpregs[r1],0, + &fpregs[t],status)); + case 1: /* sgl/dbl */ + return(sgl_to_dbl_fcnvfxt(&fpregs[r1],0, + &fpregs[t],status)); + case 2: /* dbl/sgl */ + return(dbl_to_sgl_fcnvfxt(&fpregs[r1],0, + &fpregs[t],status)); + case 3: /* dbl/dbl */ + return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0, + &fpregs[t],status)); + } + case 5: /* FCNVUF (PA2.0 only) */ + switch(fmt) { + case 0: /* sgl/sgl */ + return(sgl_to_sgl_fcnvuf(&fpregs[r1],0, + &fpregs[t],status)); + case 1: /* sgl/dbl */ + return(sgl_to_dbl_fcnvuf(&fpregs[r1],0, + &fpregs[t],status)); + case 2: /* dbl/sgl */ + return(dbl_to_sgl_fcnvuf(&fpregs[r1],0, + &fpregs[t],status)); + case 3: /* dbl/dbl */ + return(dbl_to_dbl_fcnvuf(&fpregs[r1],0, + &fpregs[t],status)); + } + case 6: /* FCNVFU (PA2.0 only) */ + switch(fmt) { + case 0: /* sgl/sgl */ + return(sgl_to_sgl_fcnvfu(&fpregs[r1],0, + &fpregs[t],status)); + case 1: /* sgl/dbl */ + return(sgl_to_dbl_fcnvfu(&fpregs[r1],0, + &fpregs[t],status)); + case 2: /* dbl/sgl */ + return(dbl_to_sgl_fcnvfu(&fpregs[r1],0, + &fpregs[t],status)); + case 3: /* dbl/dbl */ + return(dbl_to_dbl_fcnvfu(&fpregs[r1],0, + &fpregs[t],status)); + } + case 7: /* FCNVFUT (PA2.0 only) */ + switch(fmt) { + case 0: /* sgl/sgl */ + return(sgl_to_sgl_fcnvfut(&fpregs[r1],0, + &fpregs[t],status)); + case 1: /* sgl/dbl */ + return(sgl_to_dbl_fcnvfut(&fpregs[r1],0, + &fpregs[t],status)); + case 2: /* dbl/sgl */ + return(dbl_to_sgl_fcnvfut(&fpregs[r1],0, + &fpregs[t],status)); + case 3: /* dbl/dbl */ + return(dbl_to_dbl_fcnvfut(&fpregs[r1],0, + &fpregs[t],status)); + } + case 4: /* undefined */ + return(MAJOR_0C_EXCP); + } /* end of switch subop */ + + case 2: /* class 2 */ + fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; + r2 = extru(ir, fpr2pos, 5) * sizeof(double)/sizeof(u_int); + if (r2 == 0) + r2 = fpzeroreg; + if (fpu_type_flags & PA2_0_FPU_FLAG) { + /* FTEST if nullify bit set, otherwise FCMP */ + if (extru(ir, fpnulpos, 1)) { /* FTEST */ + switch (fmt) { + case 0: + /* + * arg0 is not used + * second param is the t field used for + * ftest,acc and ftest,rej + * third param is the subop (y-field) + */ + BUG(); + /* Unsupported + * return(ftest(0L,extru(ir,fptpos,5), + * &fpregs[0],subop)); + */ + case 1: + case 2: + case 3: + return(MAJOR_0C_EXCP); + } + } else { /* FCMP */ + switch (fmt) { + case 0: + retval = sgl_fcmp(&fpregs[r1], + &fpregs[r2],extru(ir,fptpos,5), + &local_status); + update_status_cbit(status,local_status, + fpu_type_flags, subop); + return(retval); + case 1: + retval = dbl_fcmp(&fpregs[r1], + &fpregs[r2],extru(ir,fptpos,5), + &local_status); + update_status_cbit(status,local_status, + fpu_type_flags, subop); + return(retval); + case 2: /* illegal */ + case 3: /* quad not implemented */ + return(MAJOR_0C_EXCP); + } + } + } /* end of if for PA2.0 */ + else { /* PA1.0 & PA1.1 */ + switch (subop) { + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + return(MAJOR_0C_EXCP); + case 0: /* FCMP */ + switch (fmt) { + case 0: + retval = sgl_fcmp(&fpregs[r1], + &fpregs[r2],extru(ir,fptpos,5), + &local_status); + update_status_cbit(status,local_status, + fpu_type_flags, subop); + return(retval); + case 1: + retval = dbl_fcmp(&fpregs[r1], + &fpregs[r2],extru(ir,fptpos,5), + &local_status); + update_status_cbit(status,local_status, + fpu_type_flags, subop); + return(retval); + case 2: /* illegal */ + case 3: /* quad not implemented */ + return(MAJOR_0C_EXCP); + } + case 1: /* FTEST */ + switch (fmt) { + case 0: + /* + * arg0 is not used + * second param is the t field used for + * ftest,acc and ftest,rej + * third param is the subop (y-field) + */ + BUG(); + /* unsupported + * return(ftest(0L,extru(ir,fptpos,5), + * &fpregs[0],subop)); + */ + case 1: + case 2: + case 3: + return(MAJOR_0C_EXCP); + } + } /* end of switch subop */ + } /* end of else for PA1.0 & PA1.1 */ + case 3: /* class 3 */ + r2 = extru(ir,fpr2pos,5) * sizeof(double)/sizeof(u_int); + if (r2 == 0) + r2 = fpzeroreg; + switch (subop) { + case 5: + case 6: + case 7: + return(MAJOR_0C_EXCP); + + case 0: /* FADD */ + switch (fmt) { + case 0: + return(sgl_fadd(&fpregs[r1],&fpregs[r2], + &fpregs[t],status)); + case 1: + return(dbl_fadd(&fpregs[r1],&fpregs[r2], + &fpregs[t],status)); + case 2: /* illegal */ + case 3: /* quad not implemented */ + return(MAJOR_0C_EXCP); + } + case 1: /* FSUB */ + switch (fmt) { + case 0: + return(sgl_fsub(&fpregs[r1],&fpregs[r2], + &fpregs[t],status)); + case 1: + return(dbl_fsub(&fpregs[r1],&fpregs[r2], + &fpregs[t],status)); + case 2: /* illegal */ + case 3: /* quad not implemented */ + return(MAJOR_0C_EXCP); + } + case 2: /* FMPY */ + switch (fmt) { + case 0: + return(sgl_fmpy(&fpregs[r1],&fpregs[r2], + &fpregs[t],status)); + case 1: + return(dbl_fmpy(&fpregs[r1],&fpregs[r2], + &fpregs[t],status)); + case 2: /* illegal */ + case 3: /* quad not implemented */ + return(MAJOR_0C_EXCP); + } + case 3: /* FDIV */ + switch (fmt) { + case 0: + return(sgl_fdiv(&fpregs[r1],&fpregs[r2], + &fpregs[t],status)); + case 1: + return(dbl_fdiv(&fpregs[r1],&fpregs[r2], + &fpregs[t],status)); + case 2: /* illegal */ + case 3: /* quad not implemented */ + return(MAJOR_0C_EXCP); + } + case 4: /* FREM */ + switch (fmt) { + case 0: + return(sgl_frem(&fpregs[r1],&fpregs[r2], + &fpregs[t],status)); + case 1: + return(dbl_frem(&fpregs[r1],&fpregs[r2], + &fpregs[t],status)); + case 2: /* illegal */ + case 3: /* quad not implemented */ + return(MAJOR_0C_EXCP); + } + } /* end of class 3 switch */ + } /* end of switch(class) */ + + /* If we get here, something is really wrong! */ + return(MAJOR_0C_EXCP); +} + +static u_int +decode_0e(ir,class,subop,fpregs) +u_int ir,class,subop; +u_int fpregs[]; +{ + u_int r1,r2,t; /* operand register offsets */ + u_int fmt; /* also sf for class 1 conversions */ + u_int df; /* dest format for class 1 conversions */ + u_int *status; + u_int retval, local_status; + u_int fpu_type_flags; + + status = &fpregs[0]; + local_status = fpregs[0]; + r1 = ((extru(ir,fpr1pos,5)<<1)|(extru(ir,fpxr1pos,1))); + if (r1 == 0) + r1 = fpzeroreg; + t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1))); + if (t == 0 && class != 2) + return(MAJOR_0E_EXCP); + if (class < 2) /* class 0 or 1 has 2 bit fmt */ + fmt = extru(ir,fpfmtpos,2); + else /* class 2 and 3 have 1 bit fmt */ + fmt = extru(ir,fp0efmtpos,1); + /* + * An undefined combination, double precision accessing the + * right half of a FPR, can get us into trouble. + * Let's just force proper alignment on it. + */ + if (fmt == DBL) { + r1 &= ~1; + if (class != 1) + t &= ~1; + } + + switch (class) { + case 0: + switch (subop) { + case 0: /* unimplemented */ + case 1: + return(MAJOR_0E_EXCP); + case 2: /* FCPY */ + switch (fmt) { + case 2: + case 3: + return(MAJOR_0E_EXCP); + case 1: /* double */ + fpregs[t+1] = fpregs[r1+1]; + case 0: /* single */ + fpregs[t] = fpregs[r1]; + return(NOEXCEPTION); + } + case 3: /* FABS */ + switch (fmt) { + case 2: + case 3: + return(MAJOR_0E_EXCP); + case 1: /* double */ + fpregs[t+1] = fpregs[r1+1]; + case 0: /* single */ + fpregs[t] = fpregs[r1] & 0x7fffffff; + return(NOEXCEPTION); + } + case 6: /* FNEG */ + switch (fmt) { + case 2: + case 3: + return(MAJOR_0E_EXCP); + case 1: /* double */ + fpregs[t+1] = fpregs[r1+1]; + case 0: /* single */ + fpregs[t] = fpregs[r1] ^ 0x80000000; + return(NOEXCEPTION); + } + case 7: /* FNEGABS */ + switch (fmt) { + case 2: + case 3: + return(MAJOR_0E_EXCP); + case 1: /* double */ + fpregs[t+1] = fpregs[r1+1]; + case 0: /* single */ + fpregs[t] = fpregs[r1] | 0x80000000; + return(NOEXCEPTION); + } + case 4: /* FSQRT */ + switch (fmt) { + case 0: + return(sgl_fsqrt(&fpregs[r1],0, + &fpregs[t], status)); + case 1: + return(dbl_fsqrt(&fpregs[r1],0, + &fpregs[t], status)); + case 2: + case 3: + return(MAJOR_0E_EXCP); + } + case 5: /* FRMD */ + switch (fmt) { + case 0: + return(sgl_frnd(&fpregs[r1],0, + &fpregs[t], status)); + case 1: + return(dbl_frnd(&fpregs[r1],0, + &fpregs[t], status)); + case 2: + case 3: + return(MAJOR_0E_EXCP); + } + } /* end of switch (subop */ + + case 1: /* class 1 */ + df = extru(ir,fpdfpos,2); /* get dest format */ + /* + * Fix Crashme problem (writing to 31R in double precision) + * here too. + */ + if (df == DBL) { + t &= ~1; + } + if ((df & 2) || (fmt & 2)) + return(MAJOR_0E_EXCP); + + fmt = (fmt << 1) | df; + switch (subop) { + case 0: /* FCNVFF */ + switch(fmt) { + case 0: /* sgl/sgl */ + return(MAJOR_0E_EXCP); + case 1: /* sgl/dbl */ + return(sgl_to_dbl_fcnvff(&fpregs[r1],0, + &fpregs[t],status)); + case 2: /* dbl/sgl */ + return(dbl_to_sgl_fcnvff(&fpregs[r1],0, + &fpregs[t],status)); + case 3: /* dbl/dbl */ + return(MAJOR_0E_EXCP); + } + case 1: /* FCNVXF */ + switch(fmt) { + case 0: /* sgl/sgl */ + return(sgl_to_sgl_fcnvxf(&fpregs[r1],0, + &fpregs[t],status)); + case 1: /* sgl/dbl */ + return(sgl_to_dbl_fcnvxf(&fpregs[r1],0, + &fpregs[t],status)); + case 2: /* dbl/sgl */ + return(dbl_to_sgl_fcnvxf(&fpregs[r1],0, + &fpregs[t],status)); + case 3: /* dbl/dbl */ + return(dbl_to_dbl_fcnvxf(&fpregs[r1],0, + &fpregs[t],status)); + } + case 2: /* FCNVFX */ + switch(fmt) { + case 0: /* sgl/sgl */ + return(sgl_to_sgl_fcnvfx(&fpregs[r1],0, + &fpregs[t],status)); + case 1: /* sgl/dbl */ + return(sgl_to_dbl_fcnvfx(&fpregs[r1],0, + &fpregs[t],status)); + case 2: /* dbl/sgl */ + return(dbl_to_sgl_fcnvfx(&fpregs[r1],0, + &fpregs[t],status)); + case 3: /* dbl/dbl */ + return(dbl_to_dbl_fcnvfx(&fpregs[r1],0, + &fpregs[t],status)); + } + case 3: /* FCNVFXT */ + switch(fmt) { + case 0: /* sgl/sgl */ + return(sgl_to_sgl_fcnvfxt(&fpregs[r1],0, + &fpregs[t],status)); + case 1: /* sgl/dbl */ + return(sgl_to_dbl_fcnvfxt(&fpregs[r1],0, + &fpregs[t],status)); + case 2: /* dbl/sgl */ + return(dbl_to_sgl_fcnvfxt(&fpregs[r1],0, + &fpregs[t],status)); + case 3: /* dbl/dbl */ + return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0, + &fpregs[t],status)); + } + case 5: /* FCNVUF (PA2.0 only) */ + switch(fmt) { + case 0: /* sgl/sgl */ + return(sgl_to_sgl_fcnvuf(&fpregs[r1],0, + &fpregs[t],status)); + case 1: /* sgl/dbl */ + return(sgl_to_dbl_fcnvuf(&fpregs[r1],0, + &fpregs[t],status)); + case 2: /* dbl/sgl */ + return(dbl_to_sgl_fcnvuf(&fpregs[r1],0, + &fpregs[t],status)); + case 3: /* dbl/dbl */ + return(dbl_to_dbl_fcnvuf(&fpregs[r1],0, + &fpregs[t],status)); + } + case 6: /* FCNVFU (PA2.0 only) */ + switch(fmt) { + case 0: /* sgl/sgl */ + return(sgl_to_sgl_fcnvfu(&fpregs[r1],0, + &fpregs[t],status)); + case 1: /* sgl/dbl */ + return(sgl_to_dbl_fcnvfu(&fpregs[r1],0, + &fpregs[t],status)); + case 2: /* dbl/sgl */ + return(dbl_to_sgl_fcnvfu(&fpregs[r1],0, + &fpregs[t],status)); + case 3: /* dbl/dbl */ + return(dbl_to_dbl_fcnvfu(&fpregs[r1],0, + &fpregs[t],status)); + } + case 7: /* FCNVFUT (PA2.0 only) */ + switch(fmt) { + case 0: /* sgl/sgl */ + return(sgl_to_sgl_fcnvfut(&fpregs[r1],0, + &fpregs[t],status)); + case 1: /* sgl/dbl */ + return(sgl_to_dbl_fcnvfut(&fpregs[r1],0, + &fpregs[t],status)); + case 2: /* dbl/sgl */ + return(dbl_to_sgl_fcnvfut(&fpregs[r1],0, + &fpregs[t],status)); + case 3: /* dbl/dbl */ + return(dbl_to_dbl_fcnvfut(&fpregs[r1],0, + &fpregs[t],status)); + } + case 4: /* undefined */ + return(MAJOR_0C_EXCP); + } /* end of switch subop */ + case 2: /* class 2 */ + /* + * Be careful out there. + * Crashme can generate cases where FR31R is specified + * as the source or target of a double precision operation. + * Since we just pass the address of the floating-point + * register to the emulation routines, this can cause + * corruption of fpzeroreg. + */ + if (fmt == DBL) + r2 = (extru(ir,fpr2pos,5)<<1); + else + r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1))); + fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; + if (r2 == 0) + r2 = fpzeroreg; + if (fpu_type_flags & PA2_0_FPU_FLAG) { + /* FTEST if nullify bit set, otherwise FCMP */ + if (extru(ir, fpnulpos, 1)) { /* FTEST */ + /* not legal */ + return(MAJOR_0E_EXCP); + } else { /* FCMP */ + switch (fmt) { + /* + * fmt is only 1 bit long + */ + case 0: + retval = sgl_fcmp(&fpregs[r1], + &fpregs[r2],extru(ir,fptpos,5), + &local_status); + update_status_cbit(status,local_status, + fpu_type_flags, subop); + return(retval); + case 1: + retval = dbl_fcmp(&fpregs[r1], + &fpregs[r2],extru(ir,fptpos,5), + &local_status); + update_status_cbit(status,local_status, + fpu_type_flags, subop); + return(retval); + } + } + } /* end of if for PA2.0 */ + else { /* PA1.0 & PA1.1 */ + switch (subop) { + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + return(MAJOR_0E_EXCP); + case 0: /* FCMP */ + switch (fmt) { + /* + * fmt is only 1 bit long + */ + case 0: + retval = sgl_fcmp(&fpregs[r1], + &fpregs[r2],extru(ir,fptpos,5), + &local_status); + update_status_cbit(status,local_status, + fpu_type_flags, subop); + return(retval); + case 1: + retval = dbl_fcmp(&fpregs[r1], + &fpregs[r2],extru(ir,fptpos,5), + &local_status); + update_status_cbit(status,local_status, + fpu_type_flags, subop); + return(retval); + } + } /* end of switch subop */ + } /* end of else for PA1.0 & PA1.1 */ + case 3: /* class 3 */ + /* + * Be careful out there. + * Crashme can generate cases where FR31R is specified + * as the source or target of a double precision operation. + * Since we just pass the address of the floating-point + * register to the emulation routines, this can cause + * corruption of fpzeroreg. + */ + if (fmt == DBL) + r2 = (extru(ir,fpr2pos,5)<<1); + else + r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1))); + if (r2 == 0) + r2 = fpzeroreg; + switch (subop) { + case 5: + case 6: + case 7: + return(MAJOR_0E_EXCP); + + /* + * Note that fmt is only 1 bit for class 3 */ + case 0: /* FADD */ + switch (fmt) { + case 0: + return(sgl_fadd(&fpregs[r1],&fpregs[r2], + &fpregs[t],status)); + case 1: + return(dbl_fadd(&fpregs[r1],&fpregs[r2], + &fpregs[t],status)); + } + case 1: /* FSUB */ + switch (fmt) { + case 0: + return(sgl_fsub(&fpregs[r1],&fpregs[r2], + &fpregs[t],status)); + case 1: + return(dbl_fsub(&fpregs[r1],&fpregs[r2], + &fpregs[t],status)); + } + case 2: /* FMPY or XMPYU */ + /* + * check for integer multiply (x bit set) + */ + if (extru(ir,fpxpos,1)) { + /* + * emulate XMPYU + */ + switch (fmt) { + case 0: + /* + * bad instruction if t specifies + * the right half of a register + */ + if (t & 1) + return(MAJOR_0E_EXCP); + BUG(); + /* unsupported + * impyu(&fpregs[r1],&fpregs[r2], + * &fpregs[t]); + */ + return(NOEXCEPTION); + case 1: + return(MAJOR_0E_EXCP); + } + } + else { /* FMPY */ + switch (fmt) { + case 0: + return(sgl_fmpy(&fpregs[r1], + &fpregs[r2],&fpregs[t],status)); + case 1: + return(dbl_fmpy(&fpregs[r1], + &fpregs[r2],&fpregs[t],status)); + } + } + case 3: /* FDIV */ + switch (fmt) { + case 0: + return(sgl_fdiv(&fpregs[r1],&fpregs[r2], + &fpregs[t],status)); + case 1: + return(dbl_fdiv(&fpregs[r1],&fpregs[r2], + &fpregs[t],status)); + } + case 4: /* FREM */ + switch (fmt) { + case 0: + return(sgl_frem(&fpregs[r1],&fpregs[r2], + &fpregs[t],status)); + case 1: + return(dbl_frem(&fpregs[r1],&fpregs[r2], + &fpregs[t],status)); + } + } /* end of class 3 switch */ + } /* end of switch(class) */ + + /* If we get here, something is really wrong! */ + return(MAJOR_0E_EXCP); +} + + +/* + * routine to decode the 06 (FMPYADD and FMPYCFXT) instruction + */ +static u_int +decode_06(ir,fpregs) +u_int ir; +u_int fpregs[]; +{ + u_int rm1, rm2, tm, ra, ta; /* operands */ + u_int fmt; + u_int error = 0; + u_int status; + u_int fpu_type_flags; + union { + double dbl; + float flt; + struct { u_int i1; u_int i2; } ints; + } mtmp, atmp; + + + status = fpregs[0]; /* use a local copy of status reg */ + fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */ + fmt = extru(ir, fpmultifmt, 1); /* get sgl/dbl flag */ + if (fmt == 0) { /* DBL */ + rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int); + if (rm1 == 0) + rm1 = fpzeroreg; + rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int); + if (rm2 == 0) + rm2 = fpzeroreg; + tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int); + if (tm == 0) + return(MAJOR_06_EXCP); + ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int); + ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int); + if (ta == 0) + return(MAJOR_06_EXCP); + + if (fpu_type_flags & TIMEX_ROLEX_FPU_MASK) { + + if (ra == 0) { + /* special case FMPYCFXT, see sgl case below */ + if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2], + &mtmp.ints.i1,&status)) + error = 1; + if (dbl_to_sgl_fcnvfxt(&fpregs[ta], + &atmp.ints.i1,&atmp.ints.i1,&status)) + error = 1; + } + else { + + if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1, + &status)) + error = 1; + if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1, + &status)) + error = 1; + } + } + + else + + { + if (ra == 0) + ra = fpzeroreg; + + if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1, + &status)) + error = 1; + if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1, + &status)) + error = 1; + + } + + if (error) + return(MAJOR_06_EXCP); + else { + /* copy results */ + fpregs[tm] = mtmp.ints.i1; + fpregs[tm+1] = mtmp.ints.i2; + fpregs[ta] = atmp.ints.i1; + fpregs[ta+1] = atmp.ints.i2; + fpregs[0] = status; + return(NOEXCEPTION); + } + } + else { /* SGL */ + /* + * calculate offsets for single precision numbers + * See table 6-14 in PA-89 architecture for mapping + */ + rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1; /* get offset */ + rm1 |= extru(ir,fprm1pos-4,1); /* add right word offset */ + + rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1; /* get offset */ + rm2 |= extru(ir,fprm2pos-4,1); /* add right word offset */ + + tm = (extru(ir,fptmpos,4) | 0x10 ) << 1; /* get offset */ + tm |= extru(ir,fptmpos-4,1); /* add right word offset */ + + ra = (extru(ir,fprapos,4) | 0x10 ) << 1; /* get offset */ + ra |= extru(ir,fprapos-4,1); /* add right word offset */ + + ta = (extru(ir,fptapos,4) | 0x10 ) << 1; /* get offset */ + ta |= extru(ir,fptapos-4,1); /* add right word offset */ + + if (ra == 0x20 &&(fpu_type_flags & TIMEX_ROLEX_FPU_MASK)) { + /* special case FMPYCFXT (really 0) + * This instruction is only present on the Timex and + * Rolex fpu's in so if it is the special case and + * one of these fpu's we run the FMPYCFXT instruction + */ + if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1, + &status)) + error = 1; + if (sgl_to_sgl_fcnvfxt(&fpregs[ta],&atmp.ints.i1, + &atmp.ints.i1,&status)) + error = 1; + } + else { + if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1, + &status)) + error = 1; + if (sgl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1, + &status)) + error = 1; + } + if (error) + return(MAJOR_06_EXCP); + else { + /* copy results */ + fpregs[tm] = mtmp.ints.i1; + fpregs[ta] = atmp.ints.i1; + fpregs[0] = status; + return(NOEXCEPTION); + } + } +} + +/* + * routine to decode the 26 (FMPYSUB) instruction + */ +static u_int +decode_26(ir,fpregs) +u_int ir; +u_int fpregs[]; +{ + u_int rm1, rm2, tm, ra, ta; /* operands */ + u_int fmt; + u_int error = 0; + u_int status; + union { + double dbl; + float flt; + struct { u_int i1; u_int i2; } ints; + } mtmp, atmp; + + + status = fpregs[0]; + fmt = extru(ir, fpmultifmt, 1); /* get sgl/dbl flag */ + if (fmt == 0) { /* DBL */ + rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int); + if (rm1 == 0) + rm1 = fpzeroreg; + rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int); + if (rm2 == 0) + rm2 = fpzeroreg; + tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int); + if (tm == 0) + return(MAJOR_26_EXCP); + ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int); + if (ra == 0) + return(MAJOR_26_EXCP); + ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int); + if (ta == 0) + return(MAJOR_26_EXCP); + + if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status)) + error = 1; + if (dbl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status)) + error = 1; + if (error) + return(MAJOR_26_EXCP); + else { + /* copy results */ + fpregs[tm] = mtmp.ints.i1; + fpregs[tm+1] = mtmp.ints.i2; + fpregs[ta] = atmp.ints.i1; + fpregs[ta+1] = atmp.ints.i2; + fpregs[0] = status; + return(NOEXCEPTION); + } + } + else { /* SGL */ + /* + * calculate offsets for single precision numbers + * See table 6-14 in PA-89 architecture for mapping + */ + rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1; /* get offset */ + rm1 |= extru(ir,fprm1pos-4,1); /* add right word offset */ + + rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1; /* get offset */ + rm2 |= extru(ir,fprm2pos-4,1); /* add right word offset */ + + tm = (extru(ir,fptmpos,4) | 0x10 ) << 1; /* get offset */ + tm |= extru(ir,fptmpos-4,1); /* add right word offset */ + + ra = (extru(ir,fprapos,4) | 0x10 ) << 1; /* get offset */ + ra |= extru(ir,fprapos-4,1); /* add right word offset */ + + ta = (extru(ir,fptapos,4) | 0x10 ) << 1; /* get offset */ + ta |= extru(ir,fptapos-4,1); /* add right word offset */ + + if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status)) + error = 1; + if (sgl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status)) + error = 1; + if (error) + return(MAJOR_26_EXCP); + else { + /* copy results */ + fpregs[tm] = mtmp.ints.i1; + fpregs[ta] = atmp.ints.i1; + fpregs[0] = status; + return(NOEXCEPTION); + } + } + +} + +/* + * routine to decode the 2E (FMPYFADD,FMPYNFADD) instructions + */ +static u_int +decode_2e(ir,fpregs) +u_int ir; +u_int fpregs[]; +{ + u_int rm1, rm2, ra, t; /* operands */ + u_int fmt; + + fmt = extru(ir,fpfmtpos,1); /* get fmt completer */ + if (fmt == DBL) { /* DBL */ + rm1 = extru(ir,fprm1pos,5) * sizeof(double)/sizeof(u_int); + if (rm1 == 0) + rm1 = fpzeroreg; + rm2 = extru(ir,fprm2pos,5) * sizeof(double)/sizeof(u_int); + if (rm2 == 0) + rm2 = fpzeroreg; + ra = ((extru(ir,fpraupos,3)<<2)|(extru(ir,fpralpos,3)>>1)) * + sizeof(double)/sizeof(u_int); + if (ra == 0) + ra = fpzeroreg; + t = extru(ir,fptpos,5) * sizeof(double)/sizeof(u_int); + if (t == 0) + return(MAJOR_2E_EXCP); + + if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */ + return(dbl_fmpynfadd(&fpregs[rm1], &fpregs[rm2], + &fpregs[ra], &fpregs[0], &fpregs[t])); + } else { + return(dbl_fmpyfadd(&fpregs[rm1], &fpregs[rm2], + &fpregs[ra], &fpregs[0], &fpregs[t])); + } + } /* end DBL */ + else { /* SGL */ + rm1 = (extru(ir,fprm1pos,5)<<1)|(extru(ir,fpxrm1pos,1)); + if (rm1 == 0) + rm1 = fpzeroreg; + rm2 = (extru(ir,fprm2pos,5)<<1)|(extru(ir,fpxrm2pos,1)); + if (rm2 == 0) + rm2 = fpzeroreg; + ra = (extru(ir,fpraupos,3)<<3)|extru(ir,fpralpos,3); + if (ra == 0) + ra = fpzeroreg; + t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1))); + if (t == 0) + return(MAJOR_2E_EXCP); + + if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */ + return(sgl_fmpynfadd(&fpregs[rm1], &fpregs[rm2], + &fpregs[ra], &fpregs[0], &fpregs[t])); + } else { + return(sgl_fmpyfadd(&fpregs[rm1], &fpregs[rm2], + &fpregs[ra], &fpregs[0], &fpregs[t])); + } + } /* end SGL */ +} + +/* + * update_status_cbit + * + * This routine returns the correct FP status register value in + * *status, based on the C-bit & V-bit returned by the FCMP + * emulation routine in new_status. The architecture type + * (PA83, PA89 or PA2.0) is available in fpu_type. The y_field + * and the architecture type are used to determine what flavor + * of FCMP is being emulated. + */ +static void +update_status_cbit(status, new_status, fpu_type, y_field) +u_int *status, new_status; +u_int fpu_type; +u_int y_field; +{ + /* + * For PA89 FPU's which implement the Compare Queue and + * for PA2.0 FPU's, update the Compare Queue if the y-field = 0, + * otherwise update the specified bit in the Compare Array. + * Note that the y-field will always be 0 for non-PA2.0 FPU's. + */ + if ((fpu_type & TIMEX_EXTEN_FLAG) || + (fpu_type & ROLEX_EXTEN_FLAG) || + (fpu_type & PA2_0_FPU_FLAG)) { + if (y_field == 0) { + *status = ((*status & 0x04000000) >> 5) | /* old Cbit */ + ((*status & 0x003ff000) >> 1) | /* old CQ */ + (new_status & 0xffc007ff); /* all other bits*/ + } else { + *status = (*status & 0x04000000) | /* old Cbit */ + ((new_status & 0x04000000) >> (y_field+4)) | + (new_status & ~0x04000000 & /* other bits */ + ~(0x04000000 >> (y_field+4))); + } + } + /* if PA83, just update the C-bit */ + else { + *status = new_status; + } +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/fpu.h linux.19rc3-ac4/arch/parisc/math-emu/fpu.h --- linux.19rc3/arch/parisc/math-emu/fpu.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/fpu.h 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,76 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * BEGIN_DESC + * + * File: + * @(#) pa/fp/fpu.h $Revision: 1.2 $ + * + * Purpose: + * <> + * + * + * END_DESC +*/ + +#ifdef __NO_PA_HDRS + PA header file -- do not include this header file for non-PA builds. +#endif + + +#ifndef _MACHINE_FPU_INCLUDED /* allows multiple inclusion */ +#define _MACHINE_FPU_INCLUDED + +#if 0 +#ifndef _SYS_STDSYMS_INCLUDED +# include +#endif /* _SYS_STDSYMS_INCLUDED */ +#include +#endif + +#define PA83_FPU_FLAG 0x00000001 +#define PA89_FPU_FLAG 0x00000002 +#define PA2_0_FPU_FLAG 0x00000010 + +#define TIMEX_EXTEN_FLAG 0x00000004 + +#define ROLEX_EXTEN_FLAG 0x00000008 +#define COPR_FP 0x00000080 /* Floating point -- Coprocessor 0 */ +#define SFU_MPY_DIVIDE 0x00008000 /* Multiply/Divide __ SFU 0 */ + + +#define EM_FPU_TYPE_OFFSET 272 + +/* version of EMULATION software for COPR,0,0 instruction */ +#define EMULATION_VERSION 4 + +/* + * The only was to differeniate between TIMEX and ROLEX (or PCX-S and PCX-T) + * is thorough the potential type field from the PDC_MODEL call. The + * following flags are used at assist this differeniation. + */ + +#define ROLEX_POTENTIAL_KEY_FLAGS PDC_MODEL_CPU_KEY_WORD_TO_IO +#define TIMEX_POTENTIAL_KEY_FLAGS (PDC_MODEL_CPU_KEY_QUAD_STORE | \ + PDC_MODEL_CPU_KEY_RECIP_SQRT) + + +#endif /* ! _MACHINE_FPU_INCLUDED */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/frnd.c linux.19rc3-ac4/arch/parisc/math-emu/frnd.c --- linux.19rc3/arch/parisc/math-emu/frnd.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/frnd.c 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,252 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * BEGIN_DESC + * + * Purpose: + * Single Floating-point Round to Integer + * Double Floating-point Round to Integer + * Quad Floating-point Round to Integer (returns unimplemented) + * + * External Interfaces: + * dbl_frnd(srcptr,nullptr,dstptr,status) + * sgl_frnd(srcptr,nullptr,dstptr,status) + * + * END_DESC +*/ + + +#include "float.h" +#include "sgl_float.h" +#include "dbl_float.h" +#include "cnv_float.h" + +/* + * Single Floating-point Round to Integer + */ + +/*ARGSUSED*/ +int +sgl_frnd(sgl_floating_point *srcptr, + unsigned int *nullptr, + sgl_floating_point *dstptr, + unsigned int *status) +{ + register unsigned int src, result; + register int src_exponent; + register boolean inexact = FALSE; + + src = *srcptr; + /* + * check source operand for NaN or infinity + */ + if ((src_exponent = Sgl_exponent(src)) == SGL_INFINITY_EXPONENT) { + /* + * is signaling NaN? + */ + if (Sgl_isone_signaling(src)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Sgl_set_quiet(src); + } + /* + * return quiet NaN or infinity + */ + *dstptr = src; + return(NOEXCEPTION); + } + /* + * Need to round? + */ + if ((src_exponent -= SGL_BIAS) >= SGL_P - 1) { + *dstptr = src; + return(NOEXCEPTION); + } + /* + * Generate result + */ + if (src_exponent >= 0) { + Sgl_clear_exponent_set_hidden(src); + result = src; + Sgl_rightshift(result,(SGL_P-1) - (src_exponent)); + /* check for inexact */ + if (Sgl_isinexact_to_fix(src,src_exponent)) { + inexact = TRUE; + /* round result */ + switch (Rounding_mode()) { + case ROUNDPLUS: + if (Sgl_iszero_sign(src)) Sgl_increment(result); + break; + case ROUNDMINUS: + if (Sgl_isone_sign(src)) Sgl_increment(result); + break; + case ROUNDNEAREST: + if (Sgl_isone_roundbit(src,src_exponent)) + if (Sgl_isone_stickybit(src,src_exponent) + || (Sgl_isone_lowmantissa(result))) + Sgl_increment(result); + } + } + Sgl_leftshift(result,(SGL_P-1) - (src_exponent)); + if (Sgl_isone_hiddenoverflow(result)) + Sgl_set_exponent(result,src_exponent + (SGL_BIAS+1)); + else Sgl_set_exponent(result,src_exponent + SGL_BIAS); + } + else { + result = src; /* set sign */ + Sgl_setzero_exponentmantissa(result); + /* check for inexact */ + if (Sgl_isnotzero_exponentmantissa(src)) { + inexact = TRUE; + /* round result */ + switch (Rounding_mode()) { + case ROUNDPLUS: + if (Sgl_iszero_sign(src)) + Sgl_set_exponent(result,SGL_BIAS); + break; + case ROUNDMINUS: + if (Sgl_isone_sign(src)) + Sgl_set_exponent(result,SGL_BIAS); + break; + case ROUNDNEAREST: + if (src_exponent == -1) + if (Sgl_isnotzero_mantissa(src)) + Sgl_set_exponent(result,SGL_BIAS); + } + } + } + *dstptr = result; + if (inexact) { + if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + } + return(NOEXCEPTION); +} + +/* + * Double Floating-point Round to Integer + */ + +/*ARGSUSED*/ +int +dbl_frnd( + dbl_floating_point *srcptr, + unsigned int *nullptr, + dbl_floating_point *dstptr, + unsigned int *status) +{ + register unsigned int srcp1, srcp2, resultp1, resultp2; + register int src_exponent; + register boolean inexact = FALSE; + + Dbl_copyfromptr(srcptr,srcp1,srcp2); + /* + * check source operand for NaN or infinity + */ + if ((src_exponent = Dbl_exponent(srcp1)) == DBL_INFINITY_EXPONENT) { + /* + * is signaling NaN? + */ + if (Dbl_isone_signaling(srcp1)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Dbl_set_quiet(srcp1); + } + /* + * return quiet NaN or infinity + */ + Dbl_copytoptr(srcp1,srcp2,dstptr); + return(NOEXCEPTION); + } + /* + * Need to round? + */ + if ((src_exponent -= DBL_BIAS) >= DBL_P - 1) { + Dbl_copytoptr(srcp1,srcp2,dstptr); + return(NOEXCEPTION); + } + /* + * Generate result + */ + if (src_exponent >= 0) { + Dbl_clear_exponent_set_hidden(srcp1); + resultp1 = srcp1; + resultp2 = srcp2; + Dbl_rightshift(resultp1,resultp2,(DBL_P-1) - (src_exponent)); + /* check for inexact */ + if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) { + inexact = TRUE; + /* round result */ + switch (Rounding_mode()) { + case ROUNDPLUS: + if (Dbl_iszero_sign(srcp1)) + Dbl_increment(resultp1,resultp2); + break; + case ROUNDMINUS: + if (Dbl_isone_sign(srcp1)) + Dbl_increment(resultp1,resultp2); + break; + case ROUNDNEAREST: + if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent)) + if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) + || (Dbl_isone_lowmantissap2(resultp2))) + Dbl_increment(resultp1,resultp2); + } + } + Dbl_leftshift(resultp1,resultp2,(DBL_P-1) - (src_exponent)); + if (Dbl_isone_hiddenoverflow(resultp1)) + Dbl_set_exponent(resultp1,src_exponent + (DBL_BIAS+1)); + else Dbl_set_exponent(resultp1,src_exponent + DBL_BIAS); + } + else { + resultp1 = srcp1; /* set sign */ + Dbl_setzero_exponentmantissa(resultp1,resultp2); + /* check for inexact */ + if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { + inexact = TRUE; + /* round result */ + switch (Rounding_mode()) { + case ROUNDPLUS: + if (Dbl_iszero_sign(srcp1)) + Dbl_set_exponent(resultp1,DBL_BIAS); + break; + case ROUNDMINUS: + if (Dbl_isone_sign(srcp1)) + Dbl_set_exponent(resultp1,DBL_BIAS); + break; + case ROUNDNEAREST: + if (src_exponent == -1) + if (Dbl_isnotzero_mantissa(srcp1,srcp2)) + Dbl_set_exponent(resultp1,DBL_BIAS); + } + } + } + Dbl_copytoptr(resultp1,resultp2,dstptr); + if (inexact) { + if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + } + return(NOEXCEPTION); +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/hppa.h linux.19rc3-ac4/arch/parisc/math-emu/hppa.h --- linux.19rc3/arch/parisc/math-emu/hppa.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/hppa.h 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,42 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifdef __NO_PA_HDRS + PA header file -- do not include this header file for non-PA builds. +#endif + + +/* amount is assumed to be a constant between 0 and 32 (non-inclusive) */ +#define Shiftdouble(left,right,amount,dest) \ + /* int left, right, amount, dest; */ \ + dest = ((left) << (32-(amount))) | ((unsigned int)(right) >> (amount)) + +/* amount must be less than 32 */ +#define Variableshiftdouble(left,right,amount,dest) \ + /* unsigned int left, right; int amount, dest; */ \ + if (amount == 0) dest = right; \ + else dest = ((((unsigned) left)&0x7fffffff) << (32-(amount))) | \ + ((unsigned) right >> (amount)) + +/* amount must be between 0 and 32 (non-inclusive) */ +#define Variable_shift_double(left,right,amount,dest) \ + /* unsigned int left, right; int amount, dest; */ \ + dest = (left << (32-(amount))) | ((unsigned) right >> (amount)) diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/Makefile linux.19rc3-ac4/arch/parisc/math-emu/Makefile --- linux.19rc3/arch/parisc/math-emu/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/Makefile 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,22 @@ +# +# Makefile for the linux/parisc floating point code +# +# 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 definition is now in the main makefile... + +O_TARGET := math.o +obj-y := frnd.o driver.o decode_exc.o fpudispatch.o denormal.o \ + dfmpy.o sfmpy.o sfsqrt.o dfsqrt.o dfadd.o fmpyfadd.o \ + sfadd.o dfsub.o sfsub.o fcnvfxt.o fcnvff.o fcnvxf.o \ + fcnvfx.o fcnvuf.o fcnvfu.o fcnvfut.o dfdiv.o sfdiv.o \ + dfrem.o sfrem.o dfcmp.o sfcmp.o + +# Math emulation code beyond the FRND is required for 712/80i and +# other very old or stripped-down PA-RISC CPUs -- not currently supported + +obj-$CONFIG_MATH_EMULATION += unimplemented-math-emulation.o + +include $(TOPDIR)/Rules.make diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/math-emu.h linux.19rc3-ac4/arch/parisc/math-emu/math-emu.h --- linux.19rc3/arch/parisc/math-emu/math-emu.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/math-emu.h 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,27 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef _PARISC_MATH_EMU_H +#define _PARISC_MATH_EMU_H + +#include +extern int handle_fpe(struct pt_regs *regs); + +#endif diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/README linux.19rc3-ac4/arch/parisc/math-emu/README --- linux.19rc3/arch/parisc/math-emu/README 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/README 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,11 @@ +All files except driver.c are snapshots from the HP-UX kernel. They've +been modified as little as possible. Even though they don't fit the +Linux coding style, please leave them in their funny format just in case +someone in the future, with access to HP-UX source code, is generous +enough to update our copies with later changes from HP-UX -- it'll +make their 'diff' job easier if our code is relatively unmodified. + +Required Disclaimer: Hewlett-Packard makes no implied or expressed +warranties about this code nor any promises to maintain or test it +in any way. This copy of this snapshot is no longer the property +of Hewlett-Packard. diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/sfadd.c linux.19rc3-ac4/arch/parisc/math-emu/sfadd.c --- linux.19rc3/arch/parisc/math-emu/sfadd.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/sfadd.c 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,518 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * BEGIN_DESC + * + * File: + * @(#) pa/spmath/sfadd.c $Revision: 1.1 $ + * + * Purpose: + * Single_add: add two single precision values. + * + * External Interfaces: + * sgl_fadd(leftptr, rightptr, dstptr, status) + * + * Internal Interfaces: + * + * Theory: + * <> + * + * END_DESC +*/ + + +#include "float.h" +#include "sgl_float.h" + +/* + * Single_add: add two single precision values. + */ +int +sgl_fadd( + sgl_floating_point *leftptr, + sgl_floating_point *rightptr, + sgl_floating_point *dstptr, + unsigned int *status) + { + register unsigned int left, right, result, extent; + register unsigned int signless_upper_left, signless_upper_right, save; + + + register int result_exponent, right_exponent, diff_exponent; + register int sign_save, jumpsize; + register boolean inexact = FALSE; + register boolean underflowtrap; + + /* Create local copies of the numbers */ + left = *leftptr; + right = *rightptr; + + /* A zero "save" helps discover equal operands (for later), * + * and is used in swapping operands (if needed). */ + Sgl_xortointp1(left,right,/*to*/save); + + /* + * check first operand for NaN's or infinity + */ + if ((result_exponent = Sgl_exponent(left)) == SGL_INFINITY_EXPONENT) + { + if (Sgl_iszero_mantissa(left)) + { + if (Sgl_isnotnan(right)) + { + if (Sgl_isinfinity(right) && save!=0) + { + /* + * invalid since operands are opposite signed infinity's + */ + if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); + Set_invalidflag(); + Sgl_makequietnan(result); + *dstptr = result; + return(NOEXCEPTION); + } + /* + * return infinity + */ + *dstptr = left; + return(NOEXCEPTION); + } + } + else + { + /* + * is NaN; signaling or quiet? + */ + if (Sgl_isone_signaling(left)) + { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Sgl_set_quiet(left); + } + /* + * is second operand a signaling NaN? + */ + else if (Sgl_is_signalingnan(right)) + { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Sgl_set_quiet(right); + *dstptr = right; + return(NOEXCEPTION); + } + /* + * return quiet NaN + */ + *dstptr = left; + return(NOEXCEPTION); + } + } /* End left NaN or Infinity processing */ + /* + * check second operand for NaN's or infinity + */ + if (Sgl_isinfinity_exponent(right)) + { + if (Sgl_iszero_mantissa(right)) + { + /* return infinity */ + *dstptr = right; + return(NOEXCEPTION); + } + /* + * is NaN; signaling or quiet? + */ + if (Sgl_isone_signaling(right)) + { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Sgl_set_quiet(right); + } + /* + * return quiet NaN + */ + *dstptr = right; + return(NOEXCEPTION); + } /* End right NaN or Infinity processing */ + + /* Invariant: Must be dealing with finite numbers */ + + /* Compare operands by removing the sign */ + Sgl_copytoint_exponentmantissa(left,signless_upper_left); + Sgl_copytoint_exponentmantissa(right,signless_upper_right); + + /* sign difference selects add or sub operation. */ + if(Sgl_ismagnitudeless(signless_upper_left,signless_upper_right)) + { + /* Set the left operand to the larger one by XOR swap * + * First finish the first word using "save" */ + Sgl_xorfromintp1(save,right,/*to*/right); + Sgl_xorfromintp1(save,left,/*to*/left); + result_exponent = Sgl_exponent(left); + } + /* Invariant: left is not smaller than right. */ + + if((right_exponent = Sgl_exponent(right)) == 0) + { + /* Denormalized operands. First look for zeroes */ + if(Sgl_iszero_mantissa(right)) + { + /* right is zero */ + if(Sgl_iszero_exponentmantissa(left)) + { + /* Both operands are zeros */ + if(Is_rounding_mode(ROUNDMINUS)) + { + Sgl_or_signs(left,/*with*/right); + } + else + { + Sgl_and_signs(left,/*with*/right); + } + } + else + { + /* Left is not a zero and must be the result. Trapped + * underflows are signaled if left is denormalized. Result + * is always exact. */ + if( (result_exponent == 0) && Is_underflowtrap_enabled() ) + { + /* need to normalize results mantissa */ + sign_save = Sgl_signextendedsign(left); + Sgl_leftshiftby1(left); + Sgl_normalize(left,result_exponent); + Sgl_set_sign(left,/*using*/sign_save); + Sgl_setwrapped_exponent(left,result_exponent,unfl); + *dstptr = left; + return(UNDERFLOWEXCEPTION); + } + } + *dstptr = left; + return(NOEXCEPTION); + } + + /* Neither are zeroes */ + Sgl_clear_sign(right); /* Exponent is already cleared */ + if(result_exponent == 0 ) + { + /* Both operands are denormalized. The result must be exact + * and is simply calculated. A sum could become normalized and a + * difference could cancel to a true zero. */ + if( (/*signed*/int) save < 0 ) + { + Sgl_subtract(left,/*minus*/right,/*into*/result); + if(Sgl_iszero_mantissa(result)) + { + if(Is_rounding_mode(ROUNDMINUS)) + { + Sgl_setone_sign(result); + } + else + { + Sgl_setzero_sign(result); + } + *dstptr = result; + return(NOEXCEPTION); + } + } + else + { + Sgl_addition(left,right,/*into*/result); + if(Sgl_isone_hidden(result)) + { + *dstptr = result; + return(NOEXCEPTION); + } + } + if(Is_underflowtrap_enabled()) + { + /* need to normalize result */ + sign_save = Sgl_signextendedsign(result); + Sgl_leftshiftby1(result); + Sgl_normalize(result,result_exponent); + Sgl_set_sign(result,/*using*/sign_save); + Sgl_setwrapped_exponent(result,result_exponent,unfl); + *dstptr = result; + return(UNDERFLOWEXCEPTION); + } + *dstptr = result; + return(NOEXCEPTION); + } + right_exponent = 1; /* Set exponent to reflect different bias + * with denomalized numbers. */ + } + else + { + Sgl_clear_signexponent_set_hidden(right); + } + Sgl_clear_exponent_set_hidden(left); + diff_exponent = result_exponent - right_exponent; + + /* + * Special case alignment of operands that would force alignment + * beyond the extent of the extension. A further optimization + * could special case this but only reduces the path length for this + * infrequent case. + */ + if(diff_exponent > SGL_THRESHOLD) + { + diff_exponent = SGL_THRESHOLD; + } + + /* Align right operand by shifting to right */ + Sgl_right_align(/*operand*/right,/*shifted by*/diff_exponent, + /*and lower to*/extent); + + /* Treat sum and difference of the operands separately. */ + if( (/*signed*/int) save < 0 ) + { + /* + * Difference of the two operands. Their can be no overflow. A + * borrow can occur out of the hidden bit and force a post + * normalization phase. + */ + Sgl_subtract_withextension(left,/*minus*/right,/*with*/extent,/*into*/result); + if(Sgl_iszero_hidden(result)) + { + /* Handle normalization */ + /* A straight foward algorithm would now shift the result + * and extension left until the hidden bit becomes one. Not + * all of the extension bits need participate in the shift. + * Only the two most significant bits (round and guard) are + * needed. If only a single shift is needed then the guard + * bit becomes a significant low order bit and the extension + * must participate in the rounding. If more than a single + * shift is needed, then all bits to the right of the guard + * bit are zeros, and the guard bit may or may not be zero. */ + sign_save = Sgl_signextendedsign(result); + Sgl_leftshiftby1_withextent(result,extent,result); + + /* Need to check for a zero result. The sign and exponent + * fields have already been zeroed. The more efficient test + * of the full object can be used. + */ + if(Sgl_iszero(result)) + /* Must have been "x-x" or "x+(-x)". */ + { + if(Is_rounding_mode(ROUNDMINUS)) Sgl_setone_sign(result); + *dstptr = result; + return(NOEXCEPTION); + } + result_exponent--; + /* Look to see if normalization is finished. */ + if(Sgl_isone_hidden(result)) + { + if(result_exponent==0) + { + /* Denormalized, exponent should be zero. Left operand * + * was normalized, so extent (guard, round) was zero */ + goto underflow; + } + else + { + /* No further normalization is needed. */ + Sgl_set_sign(result,/*using*/sign_save); + Ext_leftshiftby1(extent); + goto round; + } + } + + /* Check for denormalized, exponent should be zero. Left * + * operand was normalized, so extent (guard, round) was zero */ + if(!(underflowtrap = Is_underflowtrap_enabled()) && + result_exponent==0) goto underflow; + + /* Shift extension to complete one bit of normalization and + * update exponent. */ + Ext_leftshiftby1(extent); + + /* Discover first one bit to determine shift amount. Use a + * modified binary search. We have already shifted the result + * one position right and still not found a one so the remainder + * of the extension must be zero and simplifies rounding. */ + /* Scan bytes */ + while(Sgl_iszero_hiddenhigh7mantissa(result)) + { + Sgl_leftshiftby8(result); + if((result_exponent -= 8) <= 0 && !underflowtrap) + goto underflow; + } + /* Now narrow it down to the nibble */ + if(Sgl_iszero_hiddenhigh3mantissa(result)) + { + /* The lower nibble contains the normalizing one */ + Sgl_leftshiftby4(result); + if((result_exponent -= 4) <= 0 && !underflowtrap) + goto underflow; + } + /* Select case were first bit is set (already normalized) + * otherwise select the proper shift. */ + if((jumpsize = Sgl_hiddenhigh3mantissa(result)) > 7) + { + /* Already normalized */ + if(result_exponent <= 0) goto underflow; + Sgl_set_sign(result,/*using*/sign_save); + Sgl_set_exponent(result,/*using*/result_exponent); + *dstptr = result; + return(NOEXCEPTION); + } + Sgl_sethigh4bits(result,/*using*/sign_save); + switch(jumpsize) + { + case 1: + { + Sgl_leftshiftby3(result); + result_exponent -= 3; + break; + } + case 2: + case 3: + { + Sgl_leftshiftby2(result); + result_exponent -= 2; + break; + } + case 4: + case 5: + case 6: + case 7: + { + Sgl_leftshiftby1(result); + result_exponent -= 1; + break; + } + } + if(result_exponent > 0) + { + Sgl_set_exponent(result,/*using*/result_exponent); + *dstptr = result; + return(NOEXCEPTION); /* Sign bit is already set */ + } + /* Fixup potential underflows */ + underflow: + if(Is_underflowtrap_enabled()) + { + Sgl_set_sign(result,sign_save); + Sgl_setwrapped_exponent(result,result_exponent,unfl); + *dstptr = result; + /* inexact = FALSE; */ + return(UNDERFLOWEXCEPTION); + } + /* + * Since we cannot get an inexact denormalized result, + * we can now return. + */ + Sgl_right_align(result,/*by*/(1-result_exponent),extent); + Sgl_clear_signexponent(result); + Sgl_set_sign(result,sign_save); + *dstptr = result; + return(NOEXCEPTION); + } /* end if(hidden...)... */ + /* Fall through and round */ + } /* end if(save < 0)... */ + else + { + /* Add magnitudes */ + Sgl_addition(left,right,/*to*/result); + if(Sgl_isone_hiddenoverflow(result)) + { + /* Prenormalization required. */ + Sgl_rightshiftby1_withextent(result,extent,extent); + Sgl_arithrightshiftby1(result); + result_exponent++; + } /* end if hiddenoverflow... */ + } /* end else ...add magnitudes... */ + + /* Round the result. If the extension is all zeros,then the result is + * exact. Otherwise round in the correct direction. No underflow is + * possible. If a postnormalization is necessary, then the mantissa is + * all zeros so no shift is needed. */ + round: + if(Ext_isnotzero(extent)) + { + inexact = TRUE; + switch(Rounding_mode()) + { + case ROUNDNEAREST: /* The default. */ + if(Ext_isone_sign(extent)) + { + /* at least 1/2 ulp */ + if(Ext_isnotzero_lower(extent) || + Sgl_isone_lowmantissa(result)) + { + /* either exactly half way and odd or more than 1/2ulp */ + Sgl_increment(result); + } + } + break; + + case ROUNDPLUS: + if(Sgl_iszero_sign(result)) + { + /* Round up positive results */ + Sgl_increment(result); + } + break; + + case ROUNDMINUS: + if(Sgl_isone_sign(result)) + { + /* Round down negative results */ + Sgl_increment(result); + } + + case ROUNDZERO:; + /* truncate is simple */ + } /* end switch... */ + if(Sgl_isone_hiddenoverflow(result)) result_exponent++; + } + if(result_exponent == SGL_INFINITY_EXPONENT) + { + /* Overflow */ + if(Is_overflowtrap_enabled()) + { + Sgl_setwrapped_exponent(result,result_exponent,ovfl); + *dstptr = result; + if (inexact) + if (Is_inexacttrap_enabled()) + return(OVERFLOWEXCEPTION | INEXACTEXCEPTION); + else Set_inexactflag(); + return(OVERFLOWEXCEPTION); + } + else + { + Set_overflowflag(); + inexact = TRUE; + Sgl_setoverflow(result); + } + } + else Sgl_set_exponent(result,result_exponent); + *dstptr = result; + if(inexact) + if(Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + return(NOEXCEPTION); + } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/sfcmp.c linux.19rc3-ac4/arch/parisc/math-emu/sfcmp.c --- linux.19rc3/arch/parisc/math-emu/sfcmp.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/sfcmp.c 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,155 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * BEGIN_DESC + * + * File: + * @(#) pa/spmath/sfcmp.c $Revision: 1.1 $ + * + * Purpose: + * sgl_cmp: compare two values + * + * External Interfaces: + * sgl_fcmp(leftptr, rightptr, cond, status) + * + * Internal Interfaces: + * + * Theory: + * <> + * + * END_DESC +*/ + + +#include "float.h" +#include "sgl_float.h" + +/* + * sgl_cmp: compare two values + */ +int +sgl_fcmp (sgl_floating_point * leftptr, sgl_floating_point * rightptr, + unsigned int cond, unsigned int *status) + + /* The predicate to be tested */ + + { + register unsigned int left, right; + register int xorresult; + + /* Create local copies of the numbers */ + left = *leftptr; + right = *rightptr; + + /* + * Test for NaN + */ + if( (Sgl_exponent(left) == SGL_INFINITY_EXPONENT) + || (Sgl_exponent(right) == SGL_INFINITY_EXPONENT) ) + { + /* Check if a NaN is involved. Signal an invalid exception when + * comparing a signaling NaN or when comparing quiet NaNs and the + * low bit of the condition is set */ + if( ( (Sgl_exponent(left) == SGL_INFINITY_EXPONENT) + && Sgl_isnotzero_mantissa(left) + && (Exception(cond) || Sgl_isone_signaling(left))) + || + ( (Sgl_exponent(right) == SGL_INFINITY_EXPONENT) + && Sgl_isnotzero_mantissa(right) + && (Exception(cond) || Sgl_isone_signaling(right)) ) ) + { + if( Is_invalidtrap_enabled() ) { + Set_status_cbit(Unordered(cond)); + return(INVALIDEXCEPTION); + } + else Set_invalidflag(); + Set_status_cbit(Unordered(cond)); + return(NOEXCEPTION); + } + /* All the exceptional conditions are handled, now special case + NaN compares */ + else if( ((Sgl_exponent(left) == SGL_INFINITY_EXPONENT) + && Sgl_isnotzero_mantissa(left)) + || + ((Sgl_exponent(right) == SGL_INFINITY_EXPONENT) + && Sgl_isnotzero_mantissa(right)) ) + { + /* NaNs always compare unordered. */ + Set_status_cbit(Unordered(cond)); + return(NOEXCEPTION); + } + /* infinities will drop down to the normal compare mechanisms */ + } + /* First compare for unequal signs => less or greater or + * special equal case */ + Sgl_xortointp1(left,right,xorresult); + if( xorresult < 0 ) + { + /* left negative => less, left positive => greater. + * equal is possible if both operands are zeros. */ + if( Sgl_iszero_exponentmantissa(left) + && Sgl_iszero_exponentmantissa(right) ) + { + Set_status_cbit(Equal(cond)); + } + else if( Sgl_isone_sign(left) ) + { + Set_status_cbit(Lessthan(cond)); + } + else + { + Set_status_cbit(Greaterthan(cond)); + } + } + /* Signs are the same. Treat negative numbers separately + * from the positives because of the reversed sense. */ + else if( Sgl_all(left) == Sgl_all(right) ) + { + Set_status_cbit(Equal(cond)); + } + else if( Sgl_iszero_sign(left) ) + { + /* Positive compare */ + if( Sgl_all(left) < Sgl_all(right) ) + { + Set_status_cbit(Lessthan(cond)); + } + else + { + Set_status_cbit(Greaterthan(cond)); + } + } + else + { + /* Negative compare. Signed or unsigned compares + * both work the same. That distinction is only + * important when the sign bits differ. */ + if( Sgl_all(left) > Sgl_all(right) ) + { + Set_status_cbit(Lessthan(cond)); + } + else + { + Set_status_cbit(Greaterthan(cond)); + } + } + return(NOEXCEPTION); + } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/sfdiv.c linux.19rc3-ac4/arch/parisc/math-emu/sfdiv.c --- linux.19rc3/arch/parisc/math-emu/sfdiv.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/sfdiv.c 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,392 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * BEGIN_DESC + * + * File: + * @(#) pa/spmath/sfdiv.c $Revision: 1.1 $ + * + * Purpose: + * Single Precision Floating-point Divide + * + * External Interfaces: + * sgl_fdiv(srcptr1,srcptr2,dstptr,status) + * + * Internal Interfaces: + * + * Theory: + * <> + * + * END_DESC +*/ + + +#include "float.h" +#include "sgl_float.h" + +/* + * Single Precision Floating-point Divide + */ + +int +sgl_fdiv (sgl_floating_point * srcptr1, sgl_floating_point * srcptr2, + sgl_floating_point * dstptr, unsigned int *status) +{ + register unsigned int opnd1, opnd2, opnd3, result; + register int dest_exponent, count; + register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE; + boolean is_tiny; + + opnd1 = *srcptr1; + opnd2 = *srcptr2; + /* + * set sign bit of result + */ + if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2)) Sgl_setnegativezero(result); + else Sgl_setzero(result); + /* + * check first operand for NaN's or infinity + */ + if (Sgl_isinfinity_exponent(opnd1)) { + if (Sgl_iszero_mantissa(opnd1)) { + if (Sgl_isnotnan(opnd2)) { + if (Sgl_isinfinity(opnd2)) { + /* + * invalid since both operands + * are infinity + */ + if (Is_invalidtrap_enabled()) + return(INVALIDEXCEPTION); + Set_invalidflag(); + Sgl_makequietnan(result); + *dstptr = result; + return(NOEXCEPTION); + } + /* + * return infinity + */ + Sgl_setinfinity_exponentmantissa(result); + *dstptr = result; + return(NOEXCEPTION); + } + } + else { + /* + * is NaN; signaling or quiet? + */ + if (Sgl_isone_signaling(opnd1)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Sgl_set_quiet(opnd1); + } + /* + * is second operand a signaling NaN? + */ + else if (Sgl_is_signalingnan(opnd2)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Sgl_set_quiet(opnd2); + *dstptr = opnd2; + return(NOEXCEPTION); + } + /* + * return quiet NaN + */ + *dstptr = opnd1; + return(NOEXCEPTION); + } + } + /* + * check second operand for NaN's or infinity + */ + if (Sgl_isinfinity_exponent(opnd2)) { + if (Sgl_iszero_mantissa(opnd2)) { + /* + * return zero + */ + Sgl_setzero_exponentmantissa(result); + *dstptr = result; + return(NOEXCEPTION); + } + /* + * is NaN; signaling or quiet? + */ + if (Sgl_isone_signaling(opnd2)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Sgl_set_quiet(opnd2); + } + /* + * return quiet NaN + */ + *dstptr = opnd2; + return(NOEXCEPTION); + } + /* + * check for division by zero + */ + if (Sgl_iszero_exponentmantissa(opnd2)) { + if (Sgl_iszero_exponentmantissa(opnd1)) { + /* invalid since both operands are zero */ + if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); + Set_invalidflag(); + Sgl_makequietnan(result); + *dstptr = result; + return(NOEXCEPTION); + } + if (Is_divisionbyzerotrap_enabled()) + return(DIVISIONBYZEROEXCEPTION); + Set_divisionbyzeroflag(); + Sgl_setinfinity_exponentmantissa(result); + *dstptr = result; + return(NOEXCEPTION); + } + /* + * Generate exponent + */ + dest_exponent = Sgl_exponent(opnd1) - Sgl_exponent(opnd2) + SGL_BIAS; + + /* + * Generate mantissa + */ + if (Sgl_isnotzero_exponent(opnd1)) { + /* set hidden bit */ + Sgl_clear_signexponent_set_hidden(opnd1); + } + else { + /* check for zero */ + if (Sgl_iszero_mantissa(opnd1)) { + Sgl_setzero_exponentmantissa(result); + *dstptr = result; + return(NOEXCEPTION); + } + /* is denormalized; want to normalize */ + Sgl_clear_signexponent(opnd1); + Sgl_leftshiftby1(opnd1); + Sgl_normalize(opnd1,dest_exponent); + } + /* opnd2 needs to have hidden bit set with msb in hidden bit */ + if (Sgl_isnotzero_exponent(opnd2)) { + Sgl_clear_signexponent_set_hidden(opnd2); + } + else { + /* is denormalized; want to normalize */ + Sgl_clear_signexponent(opnd2); + Sgl_leftshiftby1(opnd2); + while(Sgl_iszero_hiddenhigh7mantissa(opnd2)) { + Sgl_leftshiftby8(opnd2); + dest_exponent += 8; + } + if(Sgl_iszero_hiddenhigh3mantissa(opnd2)) { + Sgl_leftshiftby4(opnd2); + dest_exponent += 4; + } + while(Sgl_iszero_hidden(opnd2)) { + Sgl_leftshiftby1(opnd2); + dest_exponent += 1; + } + } + + /* Divide the source mantissas */ + + /* + * A non_restoring divide algorithm is used. + */ + Sgl_subtract(opnd1,opnd2,opnd1); + Sgl_setzero(opnd3); + for (count=1;count<=SGL_P && Sgl_all(opnd1);count++) { + Sgl_leftshiftby1(opnd1); + Sgl_leftshiftby1(opnd3); + if (Sgl_iszero_sign(opnd1)) { + Sgl_setone_lowmantissa(opnd3); + Sgl_subtract(opnd1,opnd2,opnd1); + } + else Sgl_addition(opnd1,opnd2,opnd1); + } + if (count <= SGL_P) { + Sgl_leftshiftby1(opnd3); + Sgl_setone_lowmantissa(opnd3); + Sgl_leftshift(opnd3,SGL_P-count); + if (Sgl_iszero_hidden(opnd3)) { + Sgl_leftshiftby1(opnd3); + dest_exponent--; + } + } + else { + if (Sgl_iszero_hidden(opnd3)) { + /* need to get one more bit of result */ + Sgl_leftshiftby1(opnd1); + Sgl_leftshiftby1(opnd3); + if (Sgl_iszero_sign(opnd1)) { + Sgl_setone_lowmantissa(opnd3); + Sgl_subtract(opnd1,opnd2,opnd1); + } + else Sgl_addition(opnd1,opnd2,opnd1); + dest_exponent--; + } + if (Sgl_iszero_sign(opnd1)) guardbit = TRUE; + stickybit = Sgl_all(opnd1); + } + inexact = guardbit | stickybit; + + /* + * round result + */ + if (inexact && (dest_exponent > 0 || Is_underflowtrap_enabled())) { + Sgl_clear_signexponent(opnd3); + switch (Rounding_mode()) { + case ROUNDPLUS: + if (Sgl_iszero_sign(result)) + Sgl_increment_mantissa(opnd3); + break; + case ROUNDMINUS: + if (Sgl_isone_sign(result)) + Sgl_increment_mantissa(opnd3); + break; + case ROUNDNEAREST: + if (guardbit) { + if (stickybit || Sgl_isone_lowmantissa(opnd3)) + Sgl_increment_mantissa(opnd3); + } + } + if (Sgl_isone_hidden(opnd3)) dest_exponent++; + } + Sgl_set_mantissa(result,opnd3); + + /* + * Test for overflow + */ + if (dest_exponent >= SGL_INFINITY_EXPONENT) { + /* trap if OVERFLOWTRAP enabled */ + if (Is_overflowtrap_enabled()) { + /* + * Adjust bias of result + */ + Sgl_setwrapped_exponent(result,dest_exponent,ovfl); + *dstptr = result; + if (inexact) + if (Is_inexacttrap_enabled()) + return(OVERFLOWEXCEPTION | INEXACTEXCEPTION); + else Set_inexactflag(); + return(OVERFLOWEXCEPTION); + } + Set_overflowflag(); + /* set result to infinity or largest number */ + Sgl_setoverflow(result); + inexact = TRUE; + } + /* + * Test for underflow + */ + else if (dest_exponent <= 0) { + /* trap if UNDERFLOWTRAP enabled */ + if (Is_underflowtrap_enabled()) { + /* + * Adjust bias of result + */ + Sgl_setwrapped_exponent(result,dest_exponent,unfl); + *dstptr = result; + if (inexact) + if (Is_inexacttrap_enabled()) + return(UNDERFLOWEXCEPTION | INEXACTEXCEPTION); + else Set_inexactflag(); + return(UNDERFLOWEXCEPTION); + } + + /* Determine if should set underflow flag */ + is_tiny = TRUE; + if (dest_exponent == 0 && inexact) { + switch (Rounding_mode()) { + case ROUNDPLUS: + if (Sgl_iszero_sign(result)) { + Sgl_increment(opnd3); + if (Sgl_isone_hiddenoverflow(opnd3)) + is_tiny = FALSE; + Sgl_decrement(opnd3); + } + break; + case ROUNDMINUS: + if (Sgl_isone_sign(result)) { + Sgl_increment(opnd3); + if (Sgl_isone_hiddenoverflow(opnd3)) + is_tiny = FALSE; + Sgl_decrement(opnd3); + } + break; + case ROUNDNEAREST: + if (guardbit && (stickybit || + Sgl_isone_lowmantissa(opnd3))) { + Sgl_increment(opnd3); + if (Sgl_isone_hiddenoverflow(opnd3)) + is_tiny = FALSE; + Sgl_decrement(opnd3); + } + break; + } + } + + /* + * denormalize result or set to signed zero + */ + stickybit = inexact; + Sgl_denormalize(opnd3,dest_exponent,guardbit,stickybit,inexact); + + /* return rounded number */ + if (inexact) { + switch (Rounding_mode()) { + case ROUNDPLUS: + if (Sgl_iszero_sign(result)) { + Sgl_increment(opnd3); + } + break; + case ROUNDMINUS: + if (Sgl_isone_sign(result)) { + Sgl_increment(opnd3); + } + break; + case ROUNDNEAREST: + if (guardbit && (stickybit || + Sgl_isone_lowmantissa(opnd3))) { + Sgl_increment(opnd3); + } + break; + } + if (is_tiny) Set_underflowflag(); + } + Sgl_set_exponentmantissa(result,opnd3); + } + else Sgl_set_exponent(result,dest_exponent); + *dstptr = result; + /* check for inexact */ + if (inexact) { + if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + } + return(NOEXCEPTION); +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/sfmpy.c linux.19rc3-ac4/arch/parisc/math-emu/sfmpy.c --- linux.19rc3/arch/parisc/math-emu/sfmpy.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/sfmpy.c 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,380 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * BEGIN_DESC + * + * File: + * @(#) pa/spmath/sfmpy.c $Revision: 1.1 $ + * + * Purpose: + * Single Precision Floating-point Multiply + * + * External Interfaces: + * sgl_fmpy(srcptr1,srcptr2,dstptr,status) + * + * Internal Interfaces: + * + * Theory: + * <> + * + * END_DESC +*/ + + +#include "float.h" +#include "sgl_float.h" + +/* + * Single Precision Floating-point Multiply + */ + +int +sgl_fmpy( + sgl_floating_point *srcptr1, + sgl_floating_point *srcptr2, + sgl_floating_point *dstptr, + unsigned int *status) +{ + register unsigned int opnd1, opnd2, opnd3, result; + register int dest_exponent, count; + register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE; + boolean is_tiny; + + opnd1 = *srcptr1; + opnd2 = *srcptr2; + /* + * set sign bit of result + */ + if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2)) Sgl_setnegativezero(result); + else Sgl_setzero(result); + /* + * check first operand for NaN's or infinity + */ + if (Sgl_isinfinity_exponent(opnd1)) { + if (Sgl_iszero_mantissa(opnd1)) { + if (Sgl_isnotnan(opnd2)) { + if (Sgl_iszero_exponentmantissa(opnd2)) { + /* + * invalid since operands are infinity + * and zero + */ + if (Is_invalidtrap_enabled()) + return(INVALIDEXCEPTION); + Set_invalidflag(); + Sgl_makequietnan(result); + *dstptr = result; + return(NOEXCEPTION); + } + /* + * return infinity + */ + Sgl_setinfinity_exponentmantissa(result); + *dstptr = result; + return(NOEXCEPTION); + } + } + else { + /* + * is NaN; signaling or quiet? + */ + if (Sgl_isone_signaling(opnd1)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Sgl_set_quiet(opnd1); + } + /* + * is second operand a signaling NaN? + */ + else if (Sgl_is_signalingnan(opnd2)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Sgl_set_quiet(opnd2); + *dstptr = opnd2; + return(NOEXCEPTION); + } + /* + * return quiet NaN + */ + *dstptr = opnd1; + return(NOEXCEPTION); + } + } + /* + * check second operand for NaN's or infinity + */ + if (Sgl_isinfinity_exponent(opnd2)) { + if (Sgl_iszero_mantissa(opnd2)) { + if (Sgl_iszero_exponentmantissa(opnd1)) { + /* invalid since operands are zero & infinity */ + if (Is_invalidtrap_enabled()) + return(INVALIDEXCEPTION); + Set_invalidflag(); + Sgl_makequietnan(opnd2); + *dstptr = opnd2; + return(NOEXCEPTION); + } + /* + * return infinity + */ + Sgl_setinfinity_exponentmantissa(result); + *dstptr = result; + return(NOEXCEPTION); + } + /* + * is NaN; signaling or quiet? + */ + if (Sgl_isone_signaling(opnd2)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); + + /* make NaN quiet */ + Set_invalidflag(); + Sgl_set_quiet(opnd2); + } + /* + * return quiet NaN + */ + *dstptr = opnd2; + return(NOEXCEPTION); + } + /* + * Generate exponent + */ + dest_exponent = Sgl_exponent(opnd1) + Sgl_exponent(opnd2) - SGL_BIAS; + + /* + * Generate mantissa + */ + if (Sgl_isnotzero_exponent(opnd1)) { + /* set hidden bit */ + Sgl_clear_signexponent_set_hidden(opnd1); + } + else { + /* check for zero */ + if (Sgl_iszero_mantissa(opnd1)) { + Sgl_setzero_exponentmantissa(result); + *dstptr = result; + return(NOEXCEPTION); + } + /* is denormalized, adjust exponent */ + Sgl_clear_signexponent(opnd1); + Sgl_leftshiftby1(opnd1); + Sgl_normalize(opnd1,dest_exponent); + } + /* opnd2 needs to have hidden bit set with msb in hidden bit */ + if (Sgl_isnotzero_exponent(opnd2)) { + Sgl_clear_signexponent_set_hidden(opnd2); + } + else { + /* check for zero */ + if (Sgl_iszero_mantissa(opnd2)) { + Sgl_setzero_exponentmantissa(result); + *dstptr = result; + return(NOEXCEPTION); + } + /* is denormalized; want to normalize */ + Sgl_clear_signexponent(opnd2); + Sgl_leftshiftby1(opnd2); + Sgl_normalize(opnd2,dest_exponent); + } + + /* Multiply two source mantissas together */ + + Sgl_leftshiftby4(opnd2); /* make room for guard bits */ + Sgl_setzero(opnd3); + /* + * Four bits at a time are inspected in each loop, and a + * simple shift and add multiply algorithm is used. + */ + for (count=1;count= 2. */ + dest_exponent++; + } + /* check for denormalized result */ + while (Sgl_iszero_sign(opnd3)) { + Sgl_leftshiftby1(opnd3); + dest_exponent--; + } + /* + * check for guard, sticky and inexact bits + */ + stickybit |= Sgl_all(opnd3) << (SGL_BITLENGTH - SGL_EXP_LENGTH + 1); + guardbit = Sbit24(opnd3); + inexact = guardbit | stickybit; + + /* re-align mantissa */ + Sgl_rightshiftby8(opnd3); + + /* + * round result + */ + if (inexact && (dest_exponent>0 || Is_underflowtrap_enabled())) { + Sgl_clear_signexponent(opnd3); + switch (Rounding_mode()) { + case ROUNDPLUS: + if (Sgl_iszero_sign(result)) + Sgl_increment(opnd3); + break; + case ROUNDMINUS: + if (Sgl_isone_sign(result)) + Sgl_increment(opnd3); + break; + case ROUNDNEAREST: + if (guardbit) { + if (stickybit || Sgl_isone_lowmantissa(opnd3)) + Sgl_increment(opnd3); + } + } + if (Sgl_isone_hidden(opnd3)) dest_exponent++; + } + Sgl_set_mantissa(result,opnd3); + + /* + * Test for overflow + */ + if (dest_exponent >= SGL_INFINITY_EXPONENT) { + /* trap if OVERFLOWTRAP enabled */ + if (Is_overflowtrap_enabled()) { + /* + * Adjust bias of result + */ + Sgl_setwrapped_exponent(result,dest_exponent,ovfl); + *dstptr = result; + if (inexact) + if (Is_inexacttrap_enabled()) + return(OVERFLOWEXCEPTION | INEXACTEXCEPTION); + else Set_inexactflag(); + return(OVERFLOWEXCEPTION); + } + inexact = TRUE; + Set_overflowflag(); + /* set result to infinity or largest number */ + Sgl_setoverflow(result); + } + /* + * Test for underflow + */ + else if (dest_exponent <= 0) { + /* trap if UNDERFLOWTRAP enabled */ + if (Is_underflowtrap_enabled()) { + /* + * Adjust bias of result + */ + Sgl_setwrapped_exponent(result,dest_exponent,unfl); + *dstptr = result; + if (inexact) + if (Is_inexacttrap_enabled()) + return(UNDERFLOWEXCEPTION | INEXACTEXCEPTION); + else Set_inexactflag(); + return(UNDERFLOWEXCEPTION); + } + + /* Determine if should set underflow flag */ + is_tiny = TRUE; + if (dest_exponent == 0 && inexact) { + switch (Rounding_mode()) { + case ROUNDPLUS: + if (Sgl_iszero_sign(result)) { + Sgl_increment(opnd3); + if (Sgl_isone_hiddenoverflow(opnd3)) + is_tiny = FALSE; + Sgl_decrement(opnd3); + } + break; + case ROUNDMINUS: + if (Sgl_isone_sign(result)) { + Sgl_increment(opnd3); + if (Sgl_isone_hiddenoverflow(opnd3)) + is_tiny = FALSE; + Sgl_decrement(opnd3); + } + break; + case ROUNDNEAREST: + if (guardbit && (stickybit || + Sgl_isone_lowmantissa(opnd3))) { + Sgl_increment(opnd3); + if (Sgl_isone_hiddenoverflow(opnd3)) + is_tiny = FALSE; + Sgl_decrement(opnd3); + } + break; + } + } + + /* + * denormalize result or set to signed zero + */ + stickybit = inexact; + Sgl_denormalize(opnd3,dest_exponent,guardbit,stickybit,inexact); + + /* return zero or smallest number */ + if (inexact) { + switch (Rounding_mode()) { + case ROUNDPLUS: + if (Sgl_iszero_sign(result)) { + Sgl_increment(opnd3); + } + break; + case ROUNDMINUS: + if (Sgl_isone_sign(result)) { + Sgl_increment(opnd3); + } + break; + case ROUNDNEAREST: + if (guardbit && (stickybit || + Sgl_isone_lowmantissa(opnd3))) { + Sgl_increment(opnd3); + } + break; + } + if (is_tiny) Set_underflowflag(); + } + Sgl_set_exponentmantissa(result,opnd3); + } + else Sgl_set_exponent(result,dest_exponent); + *dstptr = result; + + /* check for inexact */ + if (inexact) { + if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + } + return(NOEXCEPTION); +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/sfrem.c linux.19rc3-ac4/arch/parisc/math-emu/sfrem.c --- linux.19rc3/arch/parisc/math-emu/sfrem.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/sfrem.c 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,290 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * BEGIN_DESC + * + * File: + * @(#) pa/spmath/sfrem.c $Revision: 1.1 $ + * + * Purpose: + * Single Precision Floating-point Remainder + * + * External Interfaces: + * sgl_frem(srcptr1,srcptr2,dstptr,status) + * + * Internal Interfaces: + * + * Theory: + * <> + * + * END_DESC +*/ + + + +#include "float.h" +#include "sgl_float.h" + +/* + * Single Precision Floating-point Remainder + */ + +int +sgl_frem (sgl_floating_point * srcptr1, sgl_floating_point * srcptr2, + sgl_floating_point * dstptr, unsigned int *status) +{ + register unsigned int opnd1, opnd2, result; + register int opnd1_exponent, opnd2_exponent, dest_exponent, stepcount; + register boolean roundup = FALSE; + + opnd1 = *srcptr1; + opnd2 = *srcptr2; + /* + * check first operand for NaN's or infinity + */ + if ((opnd1_exponent = Sgl_exponent(opnd1)) == SGL_INFINITY_EXPONENT) { + if (Sgl_iszero_mantissa(opnd1)) { + if (Sgl_isnotnan(opnd2)) { + /* invalid since first operand is infinity */ + if (Is_invalidtrap_enabled()) + return(INVALIDEXCEPTION); + Set_invalidflag(); + Sgl_makequietnan(result); + *dstptr = result; + return(NOEXCEPTION); + } + } + else { + /* + * is NaN; signaling or quiet? + */ + if (Sgl_isone_signaling(opnd1)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Sgl_set_quiet(opnd1); + } + /* + * is second operand a signaling NaN? + */ + else if (Sgl_is_signalingnan(opnd2)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) + return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Sgl_set_quiet(opnd2); + *dstptr = opnd2; + return(NOEXCEPTION); + } + /* + * return quiet NaN + */ + *dstptr = opnd1; + return(NOEXCEPTION); + } + } + /* + * check second operand for NaN's or infinity + */ + if ((opnd2_exponent = Sgl_exponent(opnd2)) == SGL_INFINITY_EXPONENT) { + if (Sgl_iszero_mantissa(opnd2)) { + /* + * return first operand + */ + *dstptr = opnd1; + return(NOEXCEPTION); + } + /* + * is NaN; signaling or quiet? + */ + if (Sgl_isone_signaling(opnd2)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Sgl_set_quiet(opnd2); + } + /* + * return quiet NaN + */ + *dstptr = opnd2; + return(NOEXCEPTION); + } + /* + * check second operand for zero + */ + if (Sgl_iszero_exponentmantissa(opnd2)) { + /* invalid since second operand is zero */ + if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); + Set_invalidflag(); + Sgl_makequietnan(result); + *dstptr = result; + return(NOEXCEPTION); + } + + /* + * get sign of result + */ + result = opnd1; + + /* + * check for denormalized operands + */ + if (opnd1_exponent == 0) { + /* check for zero */ + if (Sgl_iszero_mantissa(opnd1)) { + *dstptr = opnd1; + return(NOEXCEPTION); + } + /* normalize, then continue */ + opnd1_exponent = 1; + Sgl_normalize(opnd1,opnd1_exponent); + } + else { + Sgl_clear_signexponent_set_hidden(opnd1); + } + if (opnd2_exponent == 0) { + /* normalize, then continue */ + opnd2_exponent = 1; + Sgl_normalize(opnd2,opnd2_exponent); + } + else { + Sgl_clear_signexponent_set_hidden(opnd2); + } + + /* find result exponent and divide step loop count */ + dest_exponent = opnd2_exponent - 1; + stepcount = opnd1_exponent - opnd2_exponent; + + /* + * check for opnd1/opnd2 < 1 + */ + if (stepcount < 0) { + /* + * check for opnd1/opnd2 > 1/2 + * + * In this case n will round to 1, so + * r = opnd1 - opnd2 + */ + if (stepcount == -1 && Sgl_isgreaterthan(opnd1,opnd2)) { + Sgl_all(result) = ~Sgl_all(result); /* set sign */ + /* align opnd2 with opnd1 */ + Sgl_leftshiftby1(opnd2); + Sgl_subtract(opnd2,opnd1,opnd2); + /* now normalize */ + while (Sgl_iszero_hidden(opnd2)) { + Sgl_leftshiftby1(opnd2); + dest_exponent--; + } + Sgl_set_exponentmantissa(result,opnd2); + goto testforunderflow; + } + /* + * opnd1/opnd2 <= 1/2 + * + * In this case n will round to zero, so + * r = opnd1 + */ + Sgl_set_exponentmantissa(result,opnd1); + dest_exponent = opnd1_exponent; + goto testforunderflow; + } + + /* + * Generate result + * + * Do iterative subtract until remainder is less than operand 2. + */ + while (stepcount-- > 0 && Sgl_all(opnd1)) { + if (Sgl_isnotlessthan(opnd1,opnd2)) + Sgl_subtract(opnd1,opnd2,opnd1); + Sgl_leftshiftby1(opnd1); + } + /* + * Do last subtract, then determine which way to round if remainder + * is exactly 1/2 of opnd2 + */ + if (Sgl_isnotlessthan(opnd1,opnd2)) { + Sgl_subtract(opnd1,opnd2,opnd1); + roundup = TRUE; + } + if (stepcount > 0 || Sgl_iszero(opnd1)) { + /* division is exact, remainder is zero */ + Sgl_setzero_exponentmantissa(result); + *dstptr = result; + return(NOEXCEPTION); + } + + /* + * Check for cases where opnd1/opnd2 < n + * + * In this case the result's sign will be opposite that of + * opnd1. The mantissa also needs some correction. + */ + Sgl_leftshiftby1(opnd1); + if (Sgl_isgreaterthan(opnd1,opnd2)) { + Sgl_invert_sign(result); + Sgl_subtract((opnd2<<1),opnd1,opnd1); + } + /* check for remainder being exactly 1/2 of opnd2 */ + else if (Sgl_isequal(opnd1,opnd2) && roundup) { + Sgl_invert_sign(result); + } + + /* normalize result's mantissa */ + while (Sgl_iszero_hidden(opnd1)) { + dest_exponent--; + Sgl_leftshiftby1(opnd1); + } + Sgl_set_exponentmantissa(result,opnd1); + + /* + * Test for underflow + */ + testforunderflow: + if (dest_exponent <= 0) { + /* trap if UNDERFLOWTRAP enabled */ + if (Is_underflowtrap_enabled()) { + /* + * Adjust bias of result + */ + Sgl_setwrapped_exponent(result,dest_exponent,unfl); + *dstptr = result; + /* frem is always exact */ + return(UNDERFLOWEXCEPTION); + } + /* + * denormalize result or set to signed zero + */ + if (dest_exponent >= (1 - SGL_P)) { + Sgl_rightshift_exponentmantissa(result,1-dest_exponent); + } + else { + Sgl_setzero_exponentmantissa(result); + } + } + else Sgl_set_exponent(result,dest_exponent); + *dstptr = result; + return(NOEXCEPTION); +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/sfsqrt.c linux.19rc3-ac4/arch/parisc/math-emu/sfsqrt.c --- linux.19rc3/arch/parisc/math-emu/sfsqrt.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/sfsqrt.c 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,187 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * BEGIN_DESC + * + * File: + * @(#) pa/spmath/sfsqrt.c $Revision: 1.1 $ + * + * Purpose: + * Single Floating-point Square Root + * + * External Interfaces: + * sgl_fsqrt(srcptr,nullptr,dstptr,status) + * + * Internal Interfaces: + * + * Theory: + * <> + * + * END_DESC +*/ + + +#include "float.h" +#include "sgl_float.h" + +/* + * Single Floating-point Square Root + */ + +/*ARGSUSED*/ +unsigned int +sgl_fsqrt( + sgl_floating_point *srcptr, + unsigned int *nullptr, + sgl_floating_point *dstptr, + unsigned int *status) +{ + register unsigned int src, result; + register int src_exponent; + register unsigned int newbit, sum; + register boolean guardbit = FALSE, even_exponent; + + src = *srcptr; + /* + * check source operand for NaN or infinity + */ + if ((src_exponent = Sgl_exponent(src)) == SGL_INFINITY_EXPONENT) { + /* + * is signaling NaN? + */ + if (Sgl_isone_signaling(src)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Sgl_set_quiet(src); + } + /* + * Return quiet NaN or positive infinity. + * Fall thru to negative test if negative infinity. + */ + if (Sgl_iszero_sign(src) || Sgl_isnotzero_mantissa(src)) { + *dstptr = src; + return(NOEXCEPTION); + } + } + + /* + * check for zero source operand + */ + if (Sgl_iszero_exponentmantissa(src)) { + *dstptr = src; + return(NOEXCEPTION); + } + + /* + * check for negative source operand + */ + if (Sgl_isone_sign(src)) { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Sgl_makequietnan(src); + *dstptr = src; + return(NOEXCEPTION); + } + + /* + * Generate result + */ + if (src_exponent > 0) { + even_exponent = Sgl_hidden(src); + Sgl_clear_signexponent_set_hidden(src); + } + else { + /* normalize operand */ + Sgl_clear_signexponent(src); + src_exponent++; + Sgl_normalize(src,src_exponent); + even_exponent = src_exponent & 1; + } + if (even_exponent) { + /* exponent is even */ + /* Add comment here. Explain why odd exponent needs correction */ + Sgl_leftshiftby1(src); + } + /* + * Add comment here. Explain following algorithm. + * + * Trust me, it works. + * + */ + Sgl_setzero(result); + newbit = 1 << SGL_P; + while (newbit && Sgl_isnotzero(src)) { + Sgl_addition(result,newbit,sum); + if(sum <= Sgl_all(src)) { + /* update result */ + Sgl_addition(result,(newbit<<1),result); + Sgl_subtract(src,sum,src); + } + Sgl_rightshiftby1(newbit); + Sgl_leftshiftby1(src); + } + /* correct exponent for pre-shift */ + if (even_exponent) { + Sgl_rightshiftby1(result); + } + + /* check for inexact */ + if (Sgl_isnotzero(src)) { + if (!even_exponent && Sgl_islessthan(result,src)) + Sgl_increment(result); + guardbit = Sgl_lowmantissa(result); + Sgl_rightshiftby1(result); + + /* now round result */ + switch (Rounding_mode()) { + case ROUNDPLUS: + Sgl_increment(result); + break; + case ROUNDNEAREST: + /* stickybit is always true, so guardbit + * is enough to determine rounding */ + if (guardbit) { + Sgl_increment(result); + } + break; + } + /* increment result exponent by 1 if mantissa overflowed */ + if (Sgl_isone_hiddenoverflow(result)) src_exponent+=2; + + if (Is_inexacttrap_enabled()) { + Sgl_set_exponent(result, + ((src_exponent-SGL_BIAS)>>1)+SGL_BIAS); + *dstptr = result; + return(INEXACTEXCEPTION); + } + else Set_inexactflag(); + } + else { + Sgl_rightshiftby1(result); + } + Sgl_set_exponent(result,((src_exponent-SGL_BIAS)>>1)+SGL_BIAS); + *dstptr = result; + return(NOEXCEPTION); +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/sfsub.c linux.19rc3-ac4/arch/parisc/math-emu/sfsub.c --- linux.19rc3/arch/parisc/math-emu/sfsub.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/sfsub.c 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,521 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * BEGIN_DESC + * + * File: + * @(#) pa/spmath/sfsub.c $Revision: 1.1 $ + * + * Purpose: + * Single_subtract: subtract two single precision values. + * + * External Interfaces: + * sgl_fsub(leftptr, rightptr, dstptr, status) + * + * Internal Interfaces: + * + * Theory: + * <> + * + * END_DESC +*/ + + +#include "float.h" +#include "sgl_float.h" + +/* + * Single_subtract: subtract two single precision values. + */ +int +sgl_fsub( + sgl_floating_point *leftptr, + sgl_floating_point *rightptr, + sgl_floating_point *dstptr, + unsigned int *status) + { + register unsigned int left, right, result, extent; + register unsigned int signless_upper_left, signless_upper_right, save; + + register int result_exponent, right_exponent, diff_exponent; + register int sign_save, jumpsize; + register boolean inexact = FALSE, underflowtrap; + + /* Create local copies of the numbers */ + left = *leftptr; + right = *rightptr; + + /* A zero "save" helps discover equal operands (for later), * + * and is used in swapping operands (if needed). */ + Sgl_xortointp1(left,right,/*to*/save); + + /* + * check first operand for NaN's or infinity + */ + if ((result_exponent = Sgl_exponent(left)) == SGL_INFINITY_EXPONENT) + { + if (Sgl_iszero_mantissa(left)) + { + if (Sgl_isnotnan(right)) + { + if (Sgl_isinfinity(right) && save==0) + { + /* + * invalid since operands are same signed infinity's + */ + if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); + Set_invalidflag(); + Sgl_makequietnan(result); + *dstptr = result; + return(NOEXCEPTION); + } + /* + * return infinity + */ + *dstptr = left; + return(NOEXCEPTION); + } + } + else + { + /* + * is NaN; signaling or quiet? + */ + if (Sgl_isone_signaling(left)) + { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Sgl_set_quiet(left); + } + /* + * is second operand a signaling NaN? + */ + else if (Sgl_is_signalingnan(right)) + { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Sgl_set_quiet(right); + *dstptr = right; + return(NOEXCEPTION); + } + /* + * return quiet NaN + */ + *dstptr = left; + return(NOEXCEPTION); + } + } /* End left NaN or Infinity processing */ + /* + * check second operand for NaN's or infinity + */ + if (Sgl_isinfinity_exponent(right)) + { + if (Sgl_iszero_mantissa(right)) + { + /* return infinity */ + Sgl_invert_sign(right); + *dstptr = right; + return(NOEXCEPTION); + } + /* + * is NaN; signaling or quiet? + */ + if (Sgl_isone_signaling(right)) + { + /* trap if INVALIDTRAP enabled */ + if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); + /* make NaN quiet */ + Set_invalidflag(); + Sgl_set_quiet(right); + } + /* + * return quiet NaN + */ + *dstptr = right; + return(NOEXCEPTION); + } /* End right NaN or Infinity processing */ + + /* Invariant: Must be dealing with finite numbers */ + + /* Compare operands by removing the sign */ + Sgl_copytoint_exponentmantissa(left,signless_upper_left); + Sgl_copytoint_exponentmantissa(right,signless_upper_right); + + /* sign difference selects sub or add operation. */ + if(Sgl_ismagnitudeless(signless_upper_left,signless_upper_right)) + { + /* Set the left operand to the larger one by XOR swap * + * First finish the first word using "save" */ + Sgl_xorfromintp1(save,right,/*to*/right); + Sgl_xorfromintp1(save,left,/*to*/left); + result_exponent = Sgl_exponent(left); + Sgl_invert_sign(left); + } + /* Invariant: left is not smaller than right. */ + + if((right_exponent = Sgl_exponent(right)) == 0) + { + /* Denormalized operands. First look for zeroes */ + if(Sgl_iszero_mantissa(right)) + { + /* right is zero */ + if(Sgl_iszero_exponentmantissa(left)) + { + /* Both operands are zeros */ + Sgl_invert_sign(right); + if(Is_rounding_mode(ROUNDMINUS)) + { + Sgl_or_signs(left,/*with*/right); + } + else + { + Sgl_and_signs(left,/*with*/right); + } + } + else + { + /* Left is not a zero and must be the result. Trapped + * underflows are signaled if left is denormalized. Result + * is always exact. */ + if( (result_exponent == 0) && Is_underflowtrap_enabled() ) + { + /* need to normalize results mantissa */ + sign_save = Sgl_signextendedsign(left); + Sgl_leftshiftby1(left); + Sgl_normalize(left,result_exponent); + Sgl_set_sign(left,/*using*/sign_save); + Sgl_setwrapped_exponent(left,result_exponent,unfl); + *dstptr = left; + /* inexact = FALSE */ + return(UNDERFLOWEXCEPTION); + } + } + *dstptr = left; + return(NOEXCEPTION); + } + + /* Neither are zeroes */ + Sgl_clear_sign(right); /* Exponent is already cleared */ + if(result_exponent == 0 ) + { + /* Both operands are denormalized. The result must be exact + * and is simply calculated. A sum could become normalized and a + * difference could cancel to a true zero. */ + if( (/*signed*/int) save >= 0 ) + { + Sgl_subtract(left,/*minus*/right,/*into*/result); + if(Sgl_iszero_mantissa(result)) + { + if(Is_rounding_mode(ROUNDMINUS)) + { + Sgl_setone_sign(result); + } + else + { + Sgl_setzero_sign(result); + } + *dstptr = result; + return(NOEXCEPTION); + } + } + else + { + Sgl_addition(left,right,/*into*/result); + if(Sgl_isone_hidden(result)) + { + *dstptr = result; + return(NOEXCEPTION); + } + } + if(Is_underflowtrap_enabled()) + { + /* need to normalize result */ + sign_save = Sgl_signextendedsign(result); + Sgl_leftshiftby1(result); + Sgl_normalize(result,result_exponent); + Sgl_set_sign(result,/*using*/sign_save); + Sgl_setwrapped_exponent(result,result_exponent,unfl); + *dstptr = result; + /* inexact = FALSE */ + return(UNDERFLOWEXCEPTION); + } + *dstptr = result; + return(NOEXCEPTION); + } + right_exponent = 1; /* Set exponent to reflect different bias + * with denomalized numbers. */ + } + else + { + Sgl_clear_signexponent_set_hidden(right); + } + Sgl_clear_exponent_set_hidden(left); + diff_exponent = result_exponent - right_exponent; + + /* + * Special case alignment of operands that would force alignment + * beyond the extent of the extension. A further optimization + * could special case this but only reduces the path length for this + * infrequent case. + */ + if(diff_exponent > SGL_THRESHOLD) + { + diff_exponent = SGL_THRESHOLD; + } + + /* Align right operand by shifting to right */ + Sgl_right_align(/*operand*/right,/*shifted by*/diff_exponent, + /*and lower to*/extent); + + /* Treat sum and difference of the operands separately. */ + if( (/*signed*/int) save >= 0 ) + { + /* + * Difference of the two operands. Their can be no overflow. A + * borrow can occur out of the hidden bit and force a post + * normalization phase. + */ + Sgl_subtract_withextension(left,/*minus*/right,/*with*/extent,/*into*/result); + if(Sgl_iszero_hidden(result)) + { + /* Handle normalization */ + /* A straight foward algorithm would now shift the result + * and extension left until the hidden bit becomes one. Not + * all of the extension bits need participate in the shift. + * Only the two most significant bits (round and guard) are + * needed. If only a single shift is needed then the guard + * bit becomes a significant low order bit and the extension + * must participate in the rounding. If more than a single + * shift is needed, then all bits to the right of the guard + * bit are zeros, and the guard bit may or may not be zero. */ + sign_save = Sgl_signextendedsign(result); + Sgl_leftshiftby1_withextent(result,extent,result); + + /* Need to check for a zero result. The sign and exponent + * fields have already been zeroed. The more efficient test + * of the full object can be used. + */ + if(Sgl_iszero(result)) + /* Must have been "x-x" or "x+(-x)". */ + { + if(Is_rounding_mode(ROUNDMINUS)) Sgl_setone_sign(result); + *dstptr = result; + return(NOEXCEPTION); + } + result_exponent--; + /* Look to see if normalization is finished. */ + if(Sgl_isone_hidden(result)) + { + if(result_exponent==0) + { + /* Denormalized, exponent should be zero. Left operand * + * was normalized, so extent (guard, round) was zero */ + goto underflow; + } + else + { + /* No further normalization is needed. */ + Sgl_set_sign(result,/*using*/sign_save); + Ext_leftshiftby1(extent); + goto round; + } + } + + /* Check for denormalized, exponent should be zero. Left * + * operand was normalized, so extent (guard, round) was zero */ + if(!(underflowtrap = Is_underflowtrap_enabled()) && + result_exponent==0) goto underflow; + + /* Shift extension to complete one bit of normalization and + * update exponent. */ + Ext_leftshiftby1(extent); + + /* Discover first one bit to determine shift amount. Use a + * modified binary search. We have already shifted the result + * one position right and still not found a one so the remainder + * of the extension must be zero and simplifies rounding. */ + /* Scan bytes */ + while(Sgl_iszero_hiddenhigh7mantissa(result)) + { + Sgl_leftshiftby8(result); + if((result_exponent -= 8) <= 0 && !underflowtrap) + goto underflow; + } + /* Now narrow it down to the nibble */ + if(Sgl_iszero_hiddenhigh3mantissa(result)) + { + /* The lower nibble contains the normalizing one */ + Sgl_leftshiftby4(result); + if((result_exponent -= 4) <= 0 && !underflowtrap) + goto underflow; + } + /* Select case were first bit is set (already normalized) + * otherwise select the proper shift. */ + if((jumpsize = Sgl_hiddenhigh3mantissa(result)) > 7) + { + /* Already normalized */ + if(result_exponent <= 0) goto underflow; + Sgl_set_sign(result,/*using*/sign_save); + Sgl_set_exponent(result,/*using*/result_exponent); + *dstptr = result; + return(NOEXCEPTION); + } + Sgl_sethigh4bits(result,/*using*/sign_save); + switch(jumpsize) + { + case 1: + { + Sgl_leftshiftby3(result); + result_exponent -= 3; + break; + } + case 2: + case 3: + { + Sgl_leftshiftby2(result); + result_exponent -= 2; + break; + } + case 4: + case 5: + case 6: + case 7: + { + Sgl_leftshiftby1(result); + result_exponent -= 1; + break; + } + } + if(result_exponent > 0) + { + Sgl_set_exponent(result,/*using*/result_exponent); + *dstptr = result; /* Sign bit is already set */ + return(NOEXCEPTION); + } + /* Fixup potential underflows */ + underflow: + if(Is_underflowtrap_enabled()) + { + Sgl_set_sign(result,sign_save); + Sgl_setwrapped_exponent(result,result_exponent,unfl); + *dstptr = result; + /* inexact = FALSE */ + return(UNDERFLOWEXCEPTION); + } + /* + * Since we cannot get an inexact denormalized result, + * we can now return. + */ + Sgl_right_align(result,/*by*/(1-result_exponent),extent); + Sgl_clear_signexponent(result); + Sgl_set_sign(result,sign_save); + *dstptr = result; + return(NOEXCEPTION); + } /* end if(hidden...)... */ + /* Fall through and round */ + } /* end if(save >= 0)... */ + else + { + /* Add magnitudes */ + Sgl_addition(left,right,/*to*/result); + if(Sgl_isone_hiddenoverflow(result)) + { + /* Prenormalization required. */ + Sgl_rightshiftby1_withextent(result,extent,extent); + Sgl_arithrightshiftby1(result); + result_exponent++; + } /* end if hiddenoverflow... */ + } /* end else ...sub magnitudes... */ + + /* Round the result. If the extension is all zeros,then the result is + * exact. Otherwise round in the correct direction. No underflow is + * possible. If a postnormalization is necessary, then the mantissa is + * all zeros so no shift is needed. */ + round: + if(Ext_isnotzero(extent)) + { + inexact = TRUE; + switch(Rounding_mode()) + { + case ROUNDNEAREST: /* The default. */ + if(Ext_isone_sign(extent)) + { + /* at least 1/2 ulp */ + if(Ext_isnotzero_lower(extent) || + Sgl_isone_lowmantissa(result)) + { + /* either exactly half way and odd or more than 1/2ulp */ + Sgl_increment(result); + } + } + break; + + case ROUNDPLUS: + if(Sgl_iszero_sign(result)) + { + /* Round up positive results */ + Sgl_increment(result); + } + break; + + case ROUNDMINUS: + if(Sgl_isone_sign(result)) + { + /* Round down negative results */ + Sgl_increment(result); + } + + case ROUNDZERO:; + /* truncate is simple */ + } /* end switch... */ + if(Sgl_isone_hiddenoverflow(result)) result_exponent++; + } + if(result_exponent == SGL_INFINITY_EXPONENT) + { + /* Overflow */ + if(Is_overflowtrap_enabled()) + { + Sgl_setwrapped_exponent(result,result_exponent,ovfl); + *dstptr = result; + if (inexact) + if (Is_inexacttrap_enabled()) + return(OVERFLOWEXCEPTION | INEXACTEXCEPTION); + else Set_inexactflag(); + return(OVERFLOWEXCEPTION); + } + else + { + Set_overflowflag(); + inexact = TRUE; + Sgl_setoverflow(result); + } + } + else Sgl_set_exponent(result,result_exponent); + *dstptr = result; + if(inexact) + if(Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); + else Set_inexactflag(); + return(NOEXCEPTION); + } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/sgl_float.h linux.19rc3-ac4/arch/parisc/math-emu/sgl_float.h --- linux.19rc3/arch/parisc/math-emu/sgl_float.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/sgl_float.h 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,486 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifdef __NO_PA_HDRS + PA header file -- do not include this header file for non-PA builds. +#endif + +/* 32-bit word grabing functions */ +#define Sgl_firstword(value) Sall(value) +#define Sgl_secondword(value) dummy_location +#define Sgl_thirdword(value) dummy_location +#define Sgl_fourthword(value) dummy_location + +#define Sgl_sign(object) Ssign(object) +#define Sgl_exponent(object) Sexponent(object) +#define Sgl_signexponent(object) Ssignexponent(object) +#define Sgl_mantissa(object) Smantissa(object) +#define Sgl_exponentmantissa(object) Sexponentmantissa(object) +#define Sgl_all(object) Sall(object) + +/* sgl_and_signs ands the sign bits of each argument and puts the result + * into the first argument. sgl_or_signs ors those same sign bits */ +#define Sgl_and_signs( src1dst, src2) \ + Sall(src1dst) = (Sall(src2)|~((unsigned int)1<<31)) & Sall(src1dst) +#define Sgl_or_signs( src1dst, src2) \ + Sall(src1dst) = (Sall(src2)&((unsigned int)1<<31)) | Sall(src1dst) + +/* The hidden bit is always the low bit of the exponent */ +#define Sgl_clear_exponent_set_hidden(srcdst) Deposit_sexponent(srcdst,1) +#define Sgl_clear_signexponent_set_hidden(srcdst) \ + Deposit_ssignexponent(srcdst,1) +#define Sgl_clear_sign(srcdst) Sall(srcdst) &= ~((unsigned int)1<<31) +#define Sgl_clear_signexponent(srcdst) Sall(srcdst) &= 0x007fffff + +/* varamount must be less than 32 for the next three functions */ +#define Sgl_rightshift(srcdst, varamount) \ + Sall(srcdst) >>= varamount +#define Sgl_leftshift(srcdst, varamount) \ + Sall(srcdst) <<= varamount +#define Sgl_rightshift_exponentmantissa(srcdst, varamount) \ + Sall(srcdst) = \ + (Sexponentmantissa(srcdst) >> varamount) | \ + (Sall(srcdst) & ((unsigned int)1<<31)) + +#define Sgl_leftshiftby1_withextent(left,right,result) \ + Shiftdouble(Sall(left),Extall(right),31,Sall(result)) + +#define Sgl_rightshiftby1_withextent(left,right,dst) \ + Shiftdouble(Sall(left),Extall(right),1,Extall(right)) +#define Sgl_arithrightshiftby1(srcdst) \ + Sall(srcdst) = (int)Sall(srcdst) >> 1 + +/* Sign extend the sign bit with an integer destination */ +#define Sgl_signextendedsign(value) Ssignedsign(value) + +#define Sgl_isone_hidden(sgl_value) (Shidden(sgl_value)) +#define Sgl_increment(sgl_value) Sall(sgl_value) += 1 +#define Sgl_increment_mantissa(sgl_value) \ + Deposit_smantissa(sgl_value,sgl_value+1) +#define Sgl_decrement(sgl_value) Sall(sgl_value) -= 1 + +#define Sgl_isone_sign(sgl_value) (Is_ssign(sgl_value)!=0) +#define Sgl_isone_hiddenoverflow(sgl_value) \ + (Is_shiddenoverflow(sgl_value)!=0) +#define Sgl_isone_lowmantissa(sgl_value) (Is_slow(sgl_value)!=0) +#define Sgl_isone_signaling(sgl_value) (Is_ssignaling(sgl_value)!=0) +#define Sgl_is_signalingnan(sgl_value) (Ssignalingnan(sgl_value)==0x1ff) +#define Sgl_isnotzero(sgl_value) (Sall(sgl_value)!=0) +#define Sgl_isnotzero_hiddenhigh7mantissa(sgl_value) \ + (Shiddenhigh7mantissa(sgl_value)!=0) +#define Sgl_isnotzero_low4(sgl_value) (Slow4(sgl_value)!=0) +#define Sgl_isnotzero_exponent(sgl_value) (Sexponent(sgl_value)!=0) +#define Sgl_isnotzero_mantissa(sgl_value) (Smantissa(sgl_value)!=0) +#define Sgl_isnotzero_exponentmantissa(sgl_value) \ + (Sexponentmantissa(sgl_value)!=0) +#define Sgl_iszero(sgl_value) (Sall(sgl_value)==0) +#define Sgl_iszero_signaling(sgl_value) (Is_ssignaling(sgl_value)==0) +#define Sgl_iszero_hidden(sgl_value) (Is_shidden(sgl_value)==0) +#define Sgl_iszero_hiddenoverflow(sgl_value) \ + (Is_shiddenoverflow(sgl_value)==0) +#define Sgl_iszero_hiddenhigh3mantissa(sgl_value) \ + (Shiddenhigh3mantissa(sgl_value)==0) +#define Sgl_iszero_hiddenhigh7mantissa(sgl_value) \ + (Shiddenhigh7mantissa(sgl_value)==0) +#define Sgl_iszero_sign(sgl_value) (Is_ssign(sgl_value)==0) +#define Sgl_iszero_exponent(sgl_value) (Sexponent(sgl_value)==0) +#define Sgl_iszero_mantissa(sgl_value) (Smantissa(sgl_value)==0) +#define Sgl_iszero_exponentmantissa(sgl_value) \ + (Sexponentmantissa(sgl_value)==0) +#define Sgl_isinfinity_exponent(sgl_value) \ + (Sgl_exponent(sgl_value)==SGL_INFINITY_EXPONENT) +#define Sgl_isnotinfinity_exponent(sgl_value) \ + (Sgl_exponent(sgl_value)!=SGL_INFINITY_EXPONENT) +#define Sgl_isinfinity(sgl_value) \ + (Sgl_exponent(sgl_value)==SGL_INFINITY_EXPONENT && \ + Sgl_mantissa(sgl_value)==0) +#define Sgl_isnan(sgl_value) \ + (Sgl_exponent(sgl_value)==SGL_INFINITY_EXPONENT && \ + Sgl_mantissa(sgl_value)!=0) +#define Sgl_isnotnan(sgl_value) \ + (Sgl_exponent(sgl_value)!=SGL_INFINITY_EXPONENT || \ + Sgl_mantissa(sgl_value)==0) +#define Sgl_islessthan(sgl_op1,sgl_op2) \ + (Sall(sgl_op1) < Sall(sgl_op2)) +#define Sgl_isgreaterthan(sgl_op1,sgl_op2) \ + (Sall(sgl_op1) > Sall(sgl_op2)) +#define Sgl_isnotlessthan(sgl_op1,sgl_op2) \ + (Sall(sgl_op1) >= Sall(sgl_op2)) +#define Sgl_isequal(sgl_op1,sgl_op2) \ + (Sall(sgl_op1) == Sall(sgl_op2)) + +#define Sgl_leftshiftby8(sgl_value) \ + Sall(sgl_value) <<= 8 +#define Sgl_leftshiftby4(sgl_value) \ + Sall(sgl_value) <<= 4 +#define Sgl_leftshiftby3(sgl_value) \ + Sall(sgl_value) <<= 3 +#define Sgl_leftshiftby2(sgl_value) \ + Sall(sgl_value) <<= 2 +#define Sgl_leftshiftby1(sgl_value) \ + Sall(sgl_value) <<= 1 +#define Sgl_rightshiftby1(sgl_value) \ + Sall(sgl_value) >>= 1 +#define Sgl_rightshiftby4(sgl_value) \ + Sall(sgl_value) >>= 4 +#define Sgl_rightshiftby8(sgl_value) \ + Sall(sgl_value) >>= 8 + +#define Sgl_ismagnitudeless(signlessleft,signlessright) \ +/* unsigned int signlessleft, signlessright; */ \ + (signlessleft < signlessright) + + +#define Sgl_copytoint_exponentmantissa(source,dest) \ + dest = Sexponentmantissa(source) + +/* A quiet NaN has the high mantissa bit clear and at least on other (in this + * case the adjacent bit) bit set. */ +#define Sgl_set_quiet(sgl_value) Deposit_shigh2mantissa(sgl_value,1) +#define Sgl_set_exponent(sgl_value,exp) Deposit_sexponent(sgl_value,exp) + +#define Sgl_set_mantissa(dest,value) Deposit_smantissa(dest,value) +#define Sgl_set_exponentmantissa(dest,value) \ + Deposit_sexponentmantissa(dest,value) + +/* An infinity is represented with the max exponent and a zero mantissa */ +#define Sgl_setinfinity_exponent(sgl_value) \ + Deposit_sexponent(sgl_value,SGL_INFINITY_EXPONENT) +#define Sgl_setinfinity_exponentmantissa(sgl_value) \ + Deposit_sexponentmantissa(sgl_value, \ + (SGL_INFINITY_EXPONENT << (32-(1+SGL_EXP_LENGTH)))) +#define Sgl_setinfinitypositive(sgl_value) \ + Sall(sgl_value) = (SGL_INFINITY_EXPONENT << (32-(1+SGL_EXP_LENGTH))) +#define Sgl_setinfinitynegative(sgl_value) \ + Sall(sgl_value) = (SGL_INFINITY_EXPONENT << (32-(1+SGL_EXP_LENGTH))) \ + | ((unsigned int)1<<31) +#define Sgl_setinfinity(sgl_value,sign) \ + Sall(sgl_value) = (SGL_INFINITY_EXPONENT << (32-(1+SGL_EXP_LENGTH))) | \ + ((unsigned int)sign << 31) +#define Sgl_sethigh4bits(sgl_value, extsign) \ + Deposit_shigh4(sgl_value,extsign) +#define Sgl_set_sign(sgl_value,sign) Deposit_ssign(sgl_value,sign) +#define Sgl_invert_sign(sgl_value) \ + Deposit_ssign(sgl_value,~Ssign(sgl_value)) +#define Sgl_setone_sign(sgl_value) Deposit_ssign(sgl_value,1) +#define Sgl_setone_lowmantissa(sgl_value) Deposit_slow(sgl_value,1) +#define Sgl_setzero_sign(sgl_value) Sall(sgl_value) &= 0x7fffffff +#define Sgl_setzero_exponent(sgl_value) Sall(sgl_value) &= 0x807fffff +#define Sgl_setzero_mantissa(sgl_value) Sall(sgl_value) &= 0xff800000 +#define Sgl_setzero_exponentmantissa(sgl_value) Sall(sgl_value) &= 0x80000000 +#define Sgl_setzero(sgl_value) Sall(sgl_value) = 0 +#define Sgl_setnegativezero(sgl_value) Sall(sgl_value) = (unsigned int)1 << 31 + +/* Use following macro for both overflow & underflow conditions */ +#define ovfl - +#define unfl + +#define Sgl_setwrapped_exponent(sgl_value,exponent,op) \ + Deposit_sexponent(sgl_value,(exponent op SGL_WRAP)) + +#define Sgl_setlargestpositive(sgl_value) \ + Sall(sgl_value) = ((SGL_EMAX+SGL_BIAS) << (32-(1+SGL_EXP_LENGTH))) \ + | ((1<<(32-(1+SGL_EXP_LENGTH))) - 1 ) +#define Sgl_setlargestnegative(sgl_value) \ + Sall(sgl_value) = ((SGL_EMAX+SGL_BIAS) << (32-(1+SGL_EXP_LENGTH))) \ + | ((1<<(32-(1+SGL_EXP_LENGTH))) - 1 ) \ + | ((unsigned int)1<<31) + +#define Sgl_setnegativeinfinity(sgl_value) \ + Sall(sgl_value) = \ + ((1<>= shift; \ + } \ + else { \ + Extall(extent) = Sall(srcdst); \ + Sall(srcdst) = 0; \ + } +#define Sgl_hiddenhigh3mantissa(sgl_value) Shiddenhigh3mantissa(sgl_value) +#define Sgl_hidden(sgl_value) Shidden(sgl_value) +#define Sgl_lowmantissa(sgl_value) Slow(sgl_value) + +/* The left argument is never smaller than the right argument */ +#define Sgl_subtract(sgl_left,sgl_right,sgl_result) \ + Sall(sgl_result) = Sall(sgl_left) - Sall(sgl_right) + +/* Subtract right augmented with extension from left augmented with zeros and + * store into result and extension. */ +#define Sgl_subtract_withextension(left,right,extent,result) \ + /* sgl_floating_point left,right,result; extension extent */ \ + Sgl_subtract(left,right,result); \ + if((Extall(extent) = 0-Extall(extent))) \ + Sall(result) = Sall(result)-1 + +#define Sgl_addition(sgl_left,sgl_right,sgl_result) \ + Sall(sgl_result) = Sall(sgl_left) + Sall(sgl_right) + +#define Sgl_xortointp1(left,right,result) \ + result = Sall(left) XOR Sall(right); + +#define Sgl_xorfromintp1(left,right,result) \ + Sall(result) = left XOR Sall(right) + +/* Need to Initialize */ +#define Sgl_makequietnan(dest) \ + Sall(dest) = ((SGL_EMAX+SGL_BIAS)+1)<< (32-(1+SGL_EXP_LENGTH)) \ + | (1<<(32-(1+SGL_EXP_LENGTH+2))) +#define Sgl_makesignalingnan(dest) \ + Sall(dest) = ((SGL_EMAX+SGL_BIAS)+1)<< (32-(1+SGL_EXP_LENGTH)) \ + | (1<<(32-(1+SGL_EXP_LENGTH+1))) + +#define Sgl_normalize(sgl_opnd,exponent) \ + while(Sgl_iszero_hiddenhigh7mantissa(sgl_opnd)) { \ + Sgl_leftshiftby8(sgl_opnd); \ + exponent -= 8; \ + } \ + if(Sgl_iszero_hiddenhigh3mantissa(sgl_opnd)) { \ + Sgl_leftshiftby4(sgl_opnd); \ + exponent -= 4; \ + } \ + while(Sgl_iszero_hidden(sgl_opnd)) { \ + Sgl_leftshiftby1(sgl_opnd); \ + exponent -= 1; \ + } + +#define Sgl_setoverflow(sgl_opnd) \ + /* set result to infinity or largest number */ \ + switch (Rounding_mode()) { \ + case ROUNDPLUS: \ + if (Sgl_isone_sign(sgl_opnd)) { \ + Sgl_setlargestnegative(sgl_opnd); \ + } \ + else { \ + Sgl_setinfinitypositive(sgl_opnd); \ + } \ + break; \ + case ROUNDMINUS: \ + if (Sgl_iszero_sign(sgl_opnd)) { \ + Sgl_setlargestpositive(sgl_opnd); \ + } \ + else { \ + Sgl_setinfinitynegative(sgl_opnd); \ + } \ + break; \ + case ROUNDNEAREST: \ + Sgl_setinfinity_exponentmantissa(sgl_opnd); \ + break; \ + case ROUNDZERO: \ + Sgl_setlargest_exponentmantissa(sgl_opnd); \ + } + +#define Sgl_denormalize(opnd,exponent,guard,sticky,inexact) \ + Sgl_clear_signexponent_set_hidden(opnd); \ + if (exponent >= (1 - SGL_P)) { \ + guard = (Sall(opnd) >> -exponent) & 1; \ + if (exponent < 0) sticky |= Sall(opnd) << (32+exponent); \ + inexact = guard | sticky; \ + Sall(opnd) >>= (1-exponent); \ + } \ + else { \ + guard = 0; \ + sticky |= Sall(opnd); \ + inexact = sticky; \ + Sgl_setzero(opnd); \ + } + +/* + * The fused multiply add instructions requires a single extended format, + * with 48 bits of mantissa. + */ +#define SGLEXT_THRESHOLD 48 + +#define Sglext_setzero(valA,valB) \ + Sextallp1(valA) = 0; Sextallp2(valB) = 0 + +#define Sglext_isnotzero_mantissap2(valB) (Sextallp2(valB)!=0) +#define Sglext_isone_lowp1(val) (Sextlowp1(val)!=0) +#define Sglext_isone_highp2(val) (Sexthighp2(val)!=0) +#define Sglext_isnotzero_low31p2(val) (Sextlow31p2(val)!=0) +#define Sglext_iszero(valA,valB) (Sextallp1(valA)==0 && Sextallp2(valB)==0) + +#define Sgl_copytoptr(src,destptr) *destptr = src +#define Sgl_copyfromptr(srcptr,dest) dest = *srcptr +#define Sglext_copy(srca,srcb,desta,destb) \ + Sextallp1(desta) = Sextallp1(srca); \ + Sextallp2(destb) = Sextallp2(srcb) +#define Sgl_copyto_sglext(src1,dest1,dest2) \ + Sextallp1(dest1) = Sall(src1); Sextallp2(dest2) = 0 + +#define Sglext_swap_lower(leftp2,rightp2) \ + Sextallp2(leftp2) = Sextallp2(leftp2) XOR Sextallp2(rightp2); \ + Sextallp2(rightp2) = Sextallp2(leftp2) XOR Sextallp2(rightp2); \ + Sextallp2(leftp2) = Sextallp2(leftp2) XOR Sextallp2(rightp2) + +#define Sglext_setone_lowmantissap2(value) Deposit_dlowp2(value,1) + +/* The high bit is always zero so arithmetic or logical shifts will work. */ +#define Sglext_right_align(srcdstA,srcdstB,shift) \ + {int shiftamt, sticky; \ + shiftamt = shift % 32; \ + sticky = 0; \ + switch (shift/32) { \ + case 0: if (shiftamt > 0) { \ + sticky = Sextallp2(srcdstB) << 32 - (shiftamt); \ + Variable_shift_double(Sextallp1(srcdstA), \ + Sextallp2(srcdstB),shiftamt,Sextallp2(srcdstB)); \ + Sextallp1(srcdstA) >>= shiftamt; \ + } \ + break; \ + case 1: if (shiftamt > 0) { \ + sticky = (Sextallp1(srcdstA) << 32 - (shiftamt)) | \ + Sextallp2(srcdstB); \ + } \ + else { \ + sticky = Sextallp2(srcdstB); \ + } \ + Sextallp2(srcdstB) = Sextallp1(srcdstA) >> shiftamt; \ + Sextallp1(srcdstA) = 0; \ + break; \ + } \ + if (sticky) Sglext_setone_lowmantissap2(srcdstB); \ + } + +/* The left argument is never smaller than the right argument */ +#define Sglext_subtract(lefta,leftb,righta,rightb,resulta,resultb) \ + if( Sextallp2(rightb) > Sextallp2(leftb) ) Sextallp1(lefta)--; \ + Sextallp2(resultb) = Sextallp2(leftb) - Sextallp2(rightb); \ + Sextallp1(resulta) = Sextallp1(lefta) - Sextallp1(righta) + +#define Sglext_addition(lefta,leftb,righta,rightb,resulta,resultb) \ + /* If the sum of the low words is less than either source, then \ + * an overflow into the next word occurred. */ \ + if ((Sextallp2(resultb) = Sextallp2(leftb)+Sextallp2(rightb)) < \ + Sextallp2(rightb)) \ + Sextallp1(resulta) = Sextallp1(lefta)+Sextallp1(righta)+1; \ + else Sextallp1(resulta) = Sextallp1(lefta)+Sextallp1(righta) + + +#define Sglext_arithrightshiftby1(srcdstA,srcdstB) \ + Shiftdouble(Sextallp1(srcdstA),Sextallp2(srcdstB),1,Sextallp2(srcdstB)); \ + Sextallp1(srcdstA) = (int)Sextallp1(srcdstA) >> 1 + +#define Sglext_leftshiftby8(valA,valB) \ + Shiftdouble(Sextallp1(valA),Sextallp2(valB),24,Sextallp1(valA)); \ + Sextallp2(valB) <<= 8 +#define Sglext_leftshiftby4(valA,valB) \ + Shiftdouble(Sextallp1(valA),Sextallp2(valB),28,Sextallp1(valA)); \ + Sextallp2(valB) <<= 4 +#define Sglext_leftshiftby3(valA,valB) \ + Shiftdouble(Sextallp1(valA),Sextallp2(valB),29,Sextallp1(valA)); \ + Sextallp2(valB) <<= 3 +#define Sglext_leftshiftby2(valA,valB) \ + Shiftdouble(Sextallp1(valA),Sextallp2(valB),30,Sextallp1(valA)); \ + Sextallp2(valB) <<= 2 +#define Sglext_leftshiftby1(valA,valB) \ + Shiftdouble(Sextallp1(valA),Sextallp2(valB),31,Sextallp1(valA)); \ + Sextallp2(valB) <<= 1 + +#define Sglext_rightshiftby4(valueA,valueB) \ + Shiftdouble(Sextallp1(valueA),Sextallp2(valueB),4,Sextallp2(valueB)); \ + Sextallp1(valueA) >>= 4 +#define Sglext_rightshiftby3(valueA,valueB) \ + Shiftdouble(Sextallp1(valueA),Sextallp2(valueB),3,Sextallp2(valueB)); \ + Sextallp1(valueA) >>= 3 +#define Sglext_rightshiftby1(valueA,valueB) \ + Shiftdouble(Sextallp1(valueA),Sextallp2(valueB),1,Sextallp2(valueB)); \ + Sextallp1(valueA) >>= 1 + +#define Sglext_xortointp1(left,right,result) Sgl_xortointp1(left,right,result) +#define Sglext_xorfromintp1(left,right,result) \ + Sgl_xorfromintp1(left,right,result) +#define Sglext_copytoint_exponentmantissa(src,dest) \ + Sgl_copytoint_exponentmantissa(src,dest) +#define Sglext_ismagnitudeless(signlessleft,signlessright) \ + Sgl_ismagnitudeless(signlessleft,signlessright) + +#define Sglext_set_sign(dbl_value,sign) Sgl_set_sign(dbl_value,sign) +#define Sglext_clear_signexponent_set_hidden(srcdst) \ + Sgl_clear_signexponent_set_hidden(srcdst) +#define Sglext_clear_signexponent(srcdst) Sgl_clear_signexponent(srcdst) +#define Sglext_clear_sign(srcdst) Sgl_clear_sign(srcdst) +#define Sglext_isone_hidden(dbl_value) Sgl_isone_hidden(dbl_value) + +#define Sglext_denormalize(opndp1,opndp2,exponent,is_tiny) \ + {int sticky; \ + is_tiny = TRUE; \ + if (exponent == 0 && Sextallp2(opndp2)) { \ + switch (Rounding_mode()) { \ + case ROUNDPLUS: \ + if (Sgl_iszero_sign(opndp1)) \ + if (Sgl_isone_hiddenoverflow(opndp1 + 1)) \ + is_tiny = FALSE; \ + break; \ + case ROUNDMINUS: \ + if (Sgl_isone_sign(opndp1)) { \ + if (Sgl_isone_hiddenoverflow(opndp1 + 1)) \ + is_tiny = FALSE; \ + } \ + break; \ + case ROUNDNEAREST: \ + if (Sglext_isone_highp2(opndp2) && \ + (Sglext_isone_lowp1(opndp1) || \ + Sglext_isnotzero_low31p2(opndp2))) \ + if (Sgl_isone_hiddenoverflow(opndp1 + 1)) \ + is_tiny = FALSE; \ + break; \ + } \ + } \ + Sglext_clear_signexponent_set_hidden(opndp1); \ + if (exponent >= (1-DBL_P)) { \ + if (exponent >= -31) { \ + if (exponent > -31) { \ + sticky = Sextallp2(opndp2) << 31+exponent; \ + Variable_shift_double(opndp1,opndp2,1-exponent,opndp2); \ + Sextallp1(opndp1) >>= 1-exponent; \ + } \ + else { \ + sticky = Sextallp2(opndp2); \ + Sextallp2(opndp2) = Sextallp1(opndp1); \ + Sextallp1(opndp1) = 0; \ + } \ + } \ + else { \ + sticky = (Sextallp1(opndp1) << 31+exponent) | \ + Sextallp2(opndp2); \ + Sextallp2(opndp2) = Sextallp1(opndp1) >> -31-exponent; \ + Sextallp1(opndp1) = 0; \ + } \ + } \ + else { \ + sticky = Sextallp1(opndp1) | Sextallp2(opndp2); \ + Sglext_setzero(opndp1,opndp2); \ + } \ + if (sticky) Sglext_setone_lowmantissap2(opndp2); \ + exponent = 0; \ + } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/math-emu/types.h linux.19rc3-ac4/arch/parisc/math-emu/types.h --- linux.19rc3/arch/parisc/math-emu/types.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/math-emu/types.h 2002-07-29 13:58:37.000000000 +0100 @@ -0,0 +1,25 @@ +/* + * Linux/PA-RISC Project (http://www.parisc-linux.org/) + * + * Floating-point emulation code + * Copyright (C) 2001 Hewlett-Packard (Paul Bame) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#define BUG() do { \ + printk(KERN_ERR "floating-pt emulation BUG at %s:%d!\n", __FILE__, __LINE__); \ +} while (0) diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/mm/extable.c linux.19rc3-ac4/arch/parisc/mm/extable.c --- linux.19rc3/arch/parisc/mm/extable.c 2002-07-29 12:50:07.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/mm/extable.c 2002-07-29 13:58:37.000000000 +0100 @@ -46,17 +46,17 @@ const struct exception_table_entry * search_exception_table (unsigned long addr) { -#ifndef CONFIG_MODULE +#ifndef CONFIG_MODULES /* There is only the kernel to search. */ return search_one_table(__start___ex_table, __stop___ex_table - 1, addr); #else - struct exception_table_entry *ret; /* The kernel is the last "module" -- no need to treat it special. */ struct module *mp; for (mp = module_list; mp ; mp = mp->next) { + const struct exception_table_entry *ret; if (!mp->ex_table_start) continue; ret = search_one_table(mp->ex_table_start, mp->ex_table_end - 1, diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/mm/fault.c linux.19rc3-ac4/arch/parisc/mm/fault.c --- linux.19rc3/arch/parisc/mm/fault.c 2002-07-29 12:50:07.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/mm/fault.c 2002-07-29 13:58:37.000000000 +0100 @@ -17,6 +17,10 @@ #include #include +#include + +#define PRINT_USER_FAULTS /* (turn this on if you want user faults to be */ + /* dumped to the console via printk) */ /* Defines for parisc_acctyp() */ @@ -114,59 +118,31 @@ #undef isGraphicsFlushRead #undef BITSSET -/* This is similar to expand_stack(), except that it is for stacks - * that grow upwards. - */ - -static inline int expand_stackup(struct vm_area_struct * vma, unsigned long address) -{ - unsigned long grow; - - address += 4 + PAGE_SIZE - 1; - address &= PAGE_MASK; - grow = (address - vma->vm_end) >> PAGE_SHIFT; - if (address - vma->vm_start > current->rlim[RLIMIT_STACK].rlim_cur || - ((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) > current->rlim[RLIMIT_AS].rlim_cur) - return -ENOMEM; - vma->vm_end = address; - vma->vm_mm->total_vm += grow; - if (vma->vm_flags & VM_LOCKED) - vma->vm_mm->locked_vm += grow; - return 0; -} - - -/* This is similar to find_vma(), except that it understands that stacks - * grow up rather than down. - * XXX Optimise by making use of cache and avl tree as per find_vma(). - */ -struct vm_area_struct * pa_find_vma(struct mm_struct * mm, unsigned long addr) -{ - struct vm_area_struct *vma = NULL; - - if (mm) { - vma = mm->mmap; - if (!vma || addr < vma->vm_start) - return NULL; - while (vma->vm_next && addr >= vma->vm_next->vm_start) - vma = vma->vm_next; - } - return vma; -} - - -/* - * This routine handles page faults. It determines the address, - * and the problem, and then passes it off to one of the appropriate - * routines. - */ -extern void parisc_terminate(char *, struct pt_regs *, int, unsigned long); +#if 0 +/* This is the treewalk to find a vma which is the highest that has + * a start < addr. We're using find_vma_prev instead right now, but + * we might want to use this at some point in the future. Probably + * not, but I want it committed to CVS so I don't lose it :-) + */ + while (tree != vm_avl_empty) { + if (tree->vm_start > addr) { + tree = tree->vm_avl_left; + } else { + prev = tree; + if (prev->vm_next == NULL) + break; + if (prev->vm_next->vm_start > addr) + break; + tree = tree->vm_avl_right; + } + } +#endif void do_page_fault(struct pt_regs *regs, unsigned long code, unsigned long address) { - struct vm_area_struct * vma; + struct vm_area_struct *vma, *prev_vma; struct task_struct *tsk = current; struct mm_struct *mm = tsk->mm; const struct exception_table_entry *fix; @@ -176,13 +152,9 @@ goto no_context; down_read(&mm->mmap_sem); - vma = pa_find_vma(mm, address); - if (!vma) - goto bad_area; - if (address < vma->vm_end) - goto good_area; - if (!(vma->vm_flags & VM_GROWSUP) || expand_stackup(vma, address)) - goto bad_area; + vma = find_vma_prev(mm, address, &prev_vma); + if (!vma || address < vma->vm_start) + goto check_expansion; /* * Ok, we have a good vm_area for this memory access. We still need to * check the access permissions. @@ -221,6 +193,11 @@ up_read(&mm->mmap_sem); return; +check_expansion: + vma = prev_vma; + if (vma && (expand_stack(vma, address) == 0)) + goto good_area; + /* * Something tried to access memory that isn't in our memory map.. */ @@ -230,9 +207,16 @@ if (user_mode(regs)) { struct siginfo si; - printk("\ndo_page_fault() pid=%d command='%s'\n", - tsk->pid, tsk->comm); +#ifdef PRINT_USER_FAULTS + printk(KERN_DEBUG "\n"); + printk(KERN_DEBUG "do_page_fault() pid=%d command='%s' type=%lu address=0x%08lx\n", + tsk->pid, tsk->comm, code, address); + if (vma) { + printk(KERN_DEBUG "vm_start = 0x%08lx, vm_end = 0x%08lx\n", + vma->vm_start, vma->vm_end); + } show_regs(regs); +#endif /* FIXME: actually we need to get the signo and code correct */ si.si_signo = SIGSEGV; si.si_errno = 0; @@ -272,11 +256,11 @@ } } - parisc_terminate("Bad Address (null pointer deref?)",regs,code,address); + parisc_terminate("Bad Address (null pointer deref?)", regs, code, address); out_of_memory: up_read(&mm->mmap_sem); - printk("VM: killing process %s\n", current->comm); + printk(KERN_CRIT "VM: killing process %s\n", current->comm); if (user_mode(regs)) do_exit(SIGKILL); goto no_context; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/mm/init.c linux.19rc3-ac4/arch/parisc/mm/init.c --- linux.19rc3/arch/parisc/mm/init.c 2002-07-29 12:50:07.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/mm/init.c 2002-07-29 13:58:38.000000000 +0100 @@ -15,15 +15,400 @@ #include #include #include /* for hppa_dma_ops and pcxl_dma_ops */ +#include /* for initrd_start and initrd_end */ #include #include #include +#include -static unsigned long totalram_pages; -extern unsigned long max_pfn, mem_max; +mmu_gather_t mmu_gathers[NR_CPUS]; -void free_initmem(void) { +extern char _text; /* start of kernel code, defined by linker */ +extern int data_start; +extern char _end; /* end of BSS, defined by linker */ +extern char __init_begin, __init_end; + +#ifdef CONFIG_DISCONTIGMEM +struct node_map_data node_data[MAX_PHYSMEM_RANGES]; +bootmem_data_t bmem_data[MAX_PHYSMEM_RANGES]; +unsigned char *chunkmap; +unsigned int maxchunkmap; +#endif + +static struct resource data_resource = { + name: "Kernel data", + flags: IORESOURCE_BUSY | IORESOURCE_MEM, +}; + +static struct resource code_resource = { + name: "Kernel code", + flags: IORESOURCE_BUSY | IORESOURCE_MEM, +}; + +static struct resource pdcdata_resource = { + name: "PDC data (Page Zero)", + start: 0, + end: 0x9ff, + flags: IORESOURCE_BUSY | IORESOURCE_MEM, +}; + +static struct resource sysram_resources[MAX_PHYSMEM_RANGES]; + +static unsigned long max_pfn; + +/* The following array is initialized from the firmware specific + * information retrieved in kernel/inventory.c. + */ + +physmem_range_t pmem_ranges[MAX_PHYSMEM_RANGES]; +int npmem_ranges; + +#ifdef __LP64__ +#define MAX_MEM (~0UL) +#else /* !__LP64__ */ +#define MAX_MEM (3584U*1024U*1024U) +#endif /* !__LP64__ */ + +static unsigned long mem_limit = MAX_MEM; + +static void __init mem_limit_func(void) +{ + char *cp, *end; + unsigned long limit; + extern char saved_command_line[]; + + /* We need this before __setup() functions are called */ + + limit = MAX_MEM; + for (cp = saved_command_line; *cp; ) { + if (memcmp(cp, "mem=", 4) == 0) { + cp += 4; + limit = memparse(cp, &end); + if (end != cp) + break; + cp = end; + } else { + while (*cp != ' ' && *cp) + ++cp; + while (*cp == ' ') + ++cp; + } + } + + if (limit < mem_limit) + mem_limit = limit; +} + +#define MAX_GAP (0x40000000UL >> PAGE_SHIFT) + +static void __init setup_bootmem(void) +{ + unsigned long bootmap_size; + unsigned long mem_max; + unsigned long bootmap_pages; + unsigned long bootmap_start_pfn; + unsigned long bootmap_pfn; +#ifndef CONFIG_DISCONTIGMEM + physmem_range_t pmem_holes[MAX_PHYSMEM_RANGES - 1]; + int npmem_holes; +#endif + int i, sysram_resource_count; + + disable_sr_hashing(); /* Turn off space register hashing */ + +#ifdef CONFIG_DISCONTIGMEM + /* + * The below is still true as of 2.4.2. If this is ever fixed, + * we can remove this warning! + */ + + printk(KERN_WARNING "\n\n"); + printk(KERN_WARNING "CONFIG_DISCONTIGMEM is enabled, which is probably a mistake. This\n"); + printk(KERN_WARNING "option can lead to heavy swapping, even when there are gigabytes\n"); + printk(KERN_WARNING "of free memory.\n\n"); +#endif + +#ifdef __LP64__ + +#ifndef CONFIG_DISCONTIGMEM + /* + * Sort the ranges. Since the number of ranges is typically + * small, and performance is not an issue here, just do + * a simple insertion sort. + */ + + for (i = 1; i < npmem_ranges; i++) { + int j; + + for (j = i; j > 0; j--) { + unsigned long tmp; + + if (pmem_ranges[j-1].start_pfn < + pmem_ranges[j].start_pfn) { + + break; + } + tmp = pmem_ranges[j-1].start_pfn; + pmem_ranges[j-1].start_pfn = pmem_ranges[j].start_pfn; + pmem_ranges[j].start_pfn = tmp; + tmp = pmem_ranges[j-1].pages; + pmem_ranges[j-1].pages = pmem_ranges[j].pages; + pmem_ranges[j].pages = tmp; + } + } + + /* + * Throw out ranges that are too far apart (controlled by + * MAX_GAP). If CONFIG_DISCONTIGMEM wasn't implemented so + * poorly, we would recommend enabling that option, but, + * until it is fixed, this is the best way to go. + */ + + for (i = 1; i < npmem_ranges; i++) { + if (pmem_ranges[i].start_pfn - + (pmem_ranges[i-1].start_pfn + + pmem_ranges[i-1].pages) > MAX_GAP) { + npmem_ranges = i; + break; + } + } +#endif + + if (npmem_ranges > 1) { + + /* Print the memory ranges */ + + printk(KERN_INFO "Memory Ranges:\n"); + + for (i = 0; i < npmem_ranges; i++) { + unsigned long start; + unsigned long size; + + size = (pmem_ranges[i].pages << PAGE_SHIFT); + start = (pmem_ranges[i].start_pfn << PAGE_SHIFT); + printk(KERN_INFO "%2d) Start 0x%016lx End 0x%016lx Size %6ld Mb\n", + i,start, start + (size - 1), size >> 20); + } + } + +#endif /* __LP64__ */ + +#if 1 + /* KLUGE! this really belongs in kernel/resource.c! */ + iomem_resource.end = ~0UL; +#endif + + sysram_resource_count = npmem_ranges; + for (i = 0; i < sysram_resource_count; i++) { + struct resource *res = &sysram_resources[i]; + res->name = "System RAM"; + res->start = pmem_ranges[i].start_pfn << PAGE_SHIFT; + res->end = res->start + (pmem_ranges[i].pages << PAGE_SHIFT)-1; + res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; + request_resource(&iomem_resource, res); + } + + /* + * For 32 bit kernels we limit the amount of memory we can + * support, in order to preserve enough kernel address space + * for other purposes. For 64 bit kernels we don't normally + * limit the memory, but this mechanism can be used to + * artificially limit the amount of memory (and it is written + * to work with multiple memory ranges). + */ + + mem_limit_func(); /* check for "mem=" argument */ + + mem_max = 0; + for (i = 0; i < npmem_ranges; i++) { + unsigned long rsize; + + rsize = pmem_ranges[i].pages << PAGE_SHIFT; + if ((mem_max + rsize) > mem_limit) { + printk(KERN_WARNING "Memory truncated to %ld Mb\n", mem_limit >> 20); + if (mem_max == mem_limit) + npmem_ranges = i; + else { + pmem_ranges[i].pages = (mem_limit >> PAGE_SHIFT) + - (mem_max >> PAGE_SHIFT); + npmem_ranges = i + 1; + mem_max = mem_limit; + } + break; + } + mem_max += rsize; + } + + printk(KERN_INFO "Total Memory: %ld Mb\n",mem_max >> 20); + +#ifndef CONFIG_DISCONTIGMEM + + /* Merge the ranges, keeping track of the holes */ + + { + unsigned long end_pfn; + unsigned long hole_pages; + + npmem_holes = 0; + end_pfn = pmem_ranges[0].start_pfn + pmem_ranges[0].pages; + for (i = 1; i < npmem_ranges; i++) { + + hole_pages = pmem_ranges[i].start_pfn - end_pfn; + if (hole_pages) { + pmem_holes[npmem_holes].start_pfn = end_pfn; + pmem_holes[npmem_holes++].pages = hole_pages; + end_pfn += hole_pages; + } + end_pfn += pmem_ranges[i].pages; + } + + pmem_ranges[0].pages = end_pfn - pmem_ranges[0].start_pfn; + npmem_ranges = 1; + } +#endif + + bootmap_pages = 0; + for (i = 0; i < npmem_ranges; i++) + bootmap_pages += bootmem_bootmap_pages(pmem_ranges[i].pages); + + bootmap_start_pfn = PAGE_ALIGN(__pa((unsigned long) &_end)) >> PAGE_SHIFT; + +#ifdef CONFIG_DISCONTIGMEM + for (i = 0; i < npmem_ranges; i++) + node_data[i].pg_data.bdata = &bmem_data[i]; +#endif + /* + * Initialize and free the full range of memory in each range. + * Note that the only writing these routines do are to the bootmap, + * and we've made sure to locate the bootmap properly so that they + * won't be writing over anything important. + */ + + bootmap_pfn = bootmap_start_pfn; + max_pfn = 0; + for (i = 0; i < npmem_ranges; i++) { + unsigned long start_pfn; + unsigned long npages; + + start_pfn = pmem_ranges[i].start_pfn; + npages = pmem_ranges[i].pages; + + bootmap_size = init_bootmem_node(NODE_DATA(i), + bootmap_pfn, + start_pfn, + (start_pfn + npages) ); + free_bootmem_node(NODE_DATA(i), + (start_pfn << PAGE_SHIFT), + (npages << PAGE_SHIFT) ); + bootmap_pfn += (bootmap_size + PAGE_SIZE - 1) >> PAGE_SHIFT; + if ((start_pfn + npages) > max_pfn) + max_pfn = start_pfn + npages; + } + + if ((bootmap_pfn - bootmap_start_pfn) != bootmap_pages) { + printk(KERN_WARNING "WARNING! bootmap sizing is messed up!\n"); + BUG(); + } + + /* reserve PAGE0 pdc memory, kernel text/data/bss & bootmap */ + +#define PDC_CONSOLE_IO_IODC_SIZE 32768 + + reserve_bootmem_node(NODE_DATA(0), 0UL, + (unsigned long)(PAGE0->mem_free + PDC_CONSOLE_IO_IODC_SIZE)); + reserve_bootmem_node(NODE_DATA(0),__pa((unsigned long)&_text), + (unsigned long)(&_end - &_text)); + reserve_bootmem_node(NODE_DATA(0), (bootmap_start_pfn << PAGE_SHIFT), + ((bootmap_pfn - bootmap_start_pfn) << PAGE_SHIFT)); + +#ifndef CONFIG_DISCONTIGMEM + + /* reserve the holes */ + + for (i = 0; i < npmem_holes; i++) { + reserve_bootmem_node(NODE_DATA(0), + (pmem_holes[i].start_pfn << PAGE_SHIFT), + (pmem_holes[i].pages << PAGE_SHIFT)); + } +#endif + +#ifdef CONFIG_BLK_DEV_INITRD + if (initrd_start) { + printk(KERN_INFO "initrd: %08lx-%08lx\n", initrd_start, initrd_end); + if (__pa(initrd_start) < mem_max) { + unsigned long initrd_reserve; + + if (__pa(initrd_end) > mem_max) { + initrd_reserve = mem_max - __pa(initrd_start); + } else { + initrd_reserve = initrd_end - initrd_start; + } + initrd_below_start_ok = 1; + printk(KERN_INFO "initrd: reserving %08lx-%08lx (mem_max %08lx)\n", __pa(initrd_start), __pa(initrd_start) + initrd_reserve, mem_max); + + reserve_bootmem_node(NODE_DATA(0),__pa(initrd_start), initrd_reserve); + } + } +#endif + + data_resource.start = virt_to_phys(&data_start); + data_resource.end = virt_to_phys(&_end)-1; + code_resource.start = virt_to_phys(&_text); + code_resource.end = virt_to_phys(&data_start)-1; + + /* We don't know which region the kernel will be in, so try + * all of them. + */ + for (i = 0; i < sysram_resource_count; i++) { + struct resource *res = &sysram_resources[i]; + request_resource(res, &code_resource); + request_resource(res, &data_resource); + } + request_resource(&sysram_resources[0], &pdcdata_resource); +} + +void free_initmem(void) +{ + /* FIXME: */ +#if 0 + printk(KERN_INFO "NOT FREEING INITMEM (%dk)\n", + (&__init_end - &__init_begin) >> 10); + return; +#endif + unsigned long addr; + + printk(KERN_INFO "Freeing unused kernel memory: "); + +#if 1 + /* Attempt to catch anyone trying to execute code here + * by filling the page with BRK insns. + * + * If we disable interrupts for all CPUs, then IPI stops working. + * Kinda breaks the global cache flushing. + */ + local_irq_disable(); + + memset(&__init_begin, 0x00, + (unsigned long)&__init_end - (unsigned long)&__init_begin); + + flush_data_cache(); + asm volatile("sync" : : ); + flush_icache_range((unsigned long)&__init_begin, (unsigned long)&__init_end); + asm volatile("sync" : : ); + + local_irq_enable(); +#endif + + addr = (unsigned long)(&__init_begin); + for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { + ClearPageReserved(virt_to_page(addr)); + set_page_count(virt_to_page(addr), 1); + free_page(addr); + num_physpages++; + } + + printk("%luk freed\n", (unsigned long)(&__init_end - &__init_begin) >> 10); } /* @@ -37,67 +422,42 @@ * a hole of 4kB between each vmalloced area for the same reason. */ +#define MAP_START 0x4000 /* Leave room for gateway page expansion */ #define VM_MAP_OFFSET (32*1024) #define SET_MAP_OFFSET(x) ((void *)(((unsigned long)(x) + VM_MAP_OFFSET) \ & ~(VM_MAP_OFFSET-1))) void *vmalloc_start; +#ifdef CONFIG_PA11 unsigned long pcxl_dma_start; +#endif void __init mem_init(void) { - max_mapnr = num_physpages = max_low_pfn; - high_memory = __va(max_low_pfn * PAGE_SIZE); + int i; + + high_memory = __va((max_pfn << PAGE_SHIFT)); + max_mapnr = (virt_to_page(high_memory - 1) - mem_map) + 1; + + num_physpages = 0; + for (i = 0; i < npmem_ranges; i++) + num_physpages += free_all_bootmem_node(NODE_DATA(i)); - totalram_pages += free_all_bootmem(); - printk("Memory: %luk available\n", totalram_pages << (PAGE_SHIFT-10)); + printk(KERN_INFO "Memory: %luk available\n", num_physpages << (PAGE_SHIFT-10)); +#ifdef CONFIG_PA11 if (hppa_dma_ops == &pcxl_dma_ops) { - pcxl_dma_start = (unsigned long)SET_MAP_OFFSET(high_memory); + pcxl_dma_start = (unsigned long)SET_MAP_OFFSET(MAP_START); vmalloc_start = SET_MAP_OFFSET(pcxl_dma_start + PCXL_DMA_MAP_SIZE); } else { pcxl_dma_start = 0; - vmalloc_start = SET_MAP_OFFSET(high_memory); - } -} - -void __bad_pgd(pgd_t *pgd) -{ - printk("Bad pgd in pmd_alloc: %08lx\n", pgd_val(*pgd)); - pgd_val(*pgd) = _PAGE_TABLE + __pa(BAD_PAGETABLE); -} - -void __bad_pmd(pmd_t *pmd) -{ - printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd)); - pmd_val(*pmd) = _PAGE_TABLE + __pa(BAD_PAGETABLE); -} - -pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset) -{ - pte_t *pte; - - pte = (pte_t *) __get_free_page(GFP_KERNEL); - - if (pmd_none(*pmd)) { - if (pte) { - clear_page(pte); - pmd_val(*pmd) = _PAGE_TABLE + __pa((unsigned long)pte); - return pte + offset; - } - pmd_val(*pmd) = _PAGE_TABLE + __pa(BAD_PAGETABLE); - return NULL; - } - - free_page((unsigned long)pte); - - if (pmd_bad(*pmd)) { - __bad_pmd(pmd); - return NULL; + vmalloc_start = SET_MAP_OFFSET(MAP_START); } +#else + vmalloc_start = SET_MAP_OFFSET(MAP_START); +#endif - return (pte_t *) pmd_page(*pmd) + offset; } int do_check_pgt_cache(int low, int high) @@ -105,40 +465,16 @@ return 0; } -/* - * BAD_PAGE is the page that is used for page faults when linux - * is out-of-memory. Older versions of linux just did a - * do_exit(), but using this instead means there is less risk - * for a process dying in kernel mode, possibly leaving an inode - * unused etc.. - * - * BAD_PAGETABLE is the accompanying page-table: it is initialized - * to point to BAD_PAGE entries. - * - * ZERO_PAGE is a special page that is used for zero-initialized - * data and COW. - */ -pte_t * __bad_pagetable(void) -{ - return (pte_t *) NULL; -} - unsigned long *empty_zero_page; -unsigned long *empty_bad_page; - -pte_t __bad_page(void) -{ - return *(pte_t *)NULL; -} void show_mem(void) { int i,free = 0,total = 0,reserved = 0; int shared = 0, cached = 0; - printk("Mem-info:\n"); + printk(KERN_INFO "Mem-info:\n"); show_free_areas(); - printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10)); + printk(KERN_INFO "Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10)); i = max_mapnr; while (i-- > 0) { total++; @@ -151,54 +487,50 @@ else shared += atomic_read(&mem_map[i].count) - 1; } - printk("%d pages of RAM\n",total); - printk("%d reserved pages\n",reserved); - printk("%d pages shared\n",shared); - printk("%d pages swap cached\n",cached); + printk(KERN_INFO "%d pages of RAM\n", total); + printk(KERN_INFO "%d reserved pages\n", reserved); + printk(KERN_INFO "%d pages shared\n", shared); + printk(KERN_INFO "%d pages swap cached\n", cached); show_buffers(); } -void set_pte_phys (unsigned long vaddr, unsigned long phys) -{ -} - -/* - * pagetable_init() sets up the page tables - * - * Note that gateway_init() places the Linux gateway page at page 0. - * Since gateway pages cannot be dereferenced this has the desirable - * side effect of trapping those pesky NULL-reference errors in the - * kernel. - */ -static void __init pagetable_init(void) +static void __init map_pages(unsigned long start_vaddr, unsigned long start_paddr, unsigned long size, pgprot_t pgprot) { pgd_t *pg_dir; pmd_t *pmd; pte_t *pg_table; + unsigned long end_paddr; + unsigned long start_pmd; + unsigned long start_pte; unsigned long tmp1; unsigned long tmp2; unsigned long address; unsigned long ro_start; unsigned long ro_end; unsigned long fv_addr; - extern const int stext; - extern int data_start; - extern const unsigned long fault_vector_20; + unsigned long gw_addr; + extern const unsigned long fault_vector_20; + extern void * const linux_gateway_page; - ro_start = __pa((unsigned long)&stext); + ro_start = __pa((unsigned long)&_text); ro_end = __pa((unsigned long)&data_start); fv_addr = __pa((unsigned long)&fault_vector_20) & PAGE_MASK; + gw_addr = __pa((unsigned long)&linux_gateway_page) & PAGE_MASK; - printk("pagetable_init\n"); + end_paddr = start_paddr + size; - /* Map whole memory from PAGE_OFFSET */ - pg_dir = (pgd_t *)swapper_pg_dir + USER_PGD_PTRS; + pg_dir = pgd_offset_k(start_vaddr); - address = 0; - while (address < mem_max) { - /* XXX: BTLB should be done here */ +#if PTRS_PER_PMD == 1 + start_pmd = 0; +#else + start_pmd = ((start_vaddr >> PMD_SHIFT) & (PTRS_PER_PMD - 1)); +#endif + start_pte = ((start_vaddr >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)); + address = start_paddr; + while (address < end_paddr) { #if PTRS_PER_PMD == 1 pmd = (pmd_t *)__pa(pg_dir); #else @@ -209,7 +541,7 @@ */ if (!pmd) { - pmd = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE); + pmd = (pmd_t *) alloc_bootmem_low_pages_node(NODE_DATA(0),PAGE_SIZE); pmd = (pmd_t *) __pa(pmd); } @@ -219,8 +551,8 @@ /* now change pmd to kernel virtual addresses */ - pmd = (pmd_t *) __va(pmd); - for (tmp1 = 0 ; tmp1 < PTRS_PER_PMD ; tmp1++,pmd++) { + pmd = (pmd_t *)__va(pmd) + start_pmd; + for (tmp1 = start_pmd; tmp1 < PTRS_PER_PMD; tmp1++,pmd++) { /* * pg_table is physical at this point @@ -229,7 +561,7 @@ pg_table = (pte_t *) (PAGE_MASK & pmd_val(*pmd)); if (!pg_table) { pg_table = (pte_t *) - alloc_bootmem_low_pages(PAGE_SIZE); + alloc_bootmem_low_pages_node(NODE_DATA(0),PAGE_SIZE); pg_table = (pte_t *) __pa(pg_table); } @@ -238,8 +570,8 @@ /* now change pg_table to kernel virtual addresses */ - pg_table = (pte_t *) __va(pg_table); - for (tmp2=0; tmp2 < PTRS_PER_PTE; tmp2++,pg_table++) { + pg_table = (pte_t *) __va(pg_table) + start_pte; + for (tmp2 = start_pte; tmp2 < PTRS_PER_PTE; tmp2++,pg_table++) { pte_t pte; #if !defined(CONFIG_KWDB) && !defined(CONFIG_STI_CONSOLE) @@ -249,53 +581,84 @@ ** The right thing to do seems like KWDB modify only the pte which ** has a break point on it...otherwise we might mask worse bugs. */ + /* + * Map the fault vector writable so we can + * write the HPMC checksum. + */ if (address >= ro_start && address < ro_end - && address != fv_addr) + && address != fv_addr + && address != gw_addr) pte = __mk_pte(address, PAGE_KERNEL_RO); else #endif - pte = __mk_pte(address, PAGE_KERNEL); + pte = __mk_pte(address, pgprot); - if (address >= mem_max) + if (address >= end_paddr) pte_val(pte) = 0; set_pte(pg_table, pte); address += PAGE_SIZE; } + start_pte = 0; - if (address >= mem_max) + if (address >= end_paddr) break; } + start_pmd = 0; } +} + +/* + * pagetable_init() sets up the page tables + * + * Note that gateway_init() places the Linux gateway page at page 0. + * Since gateway pages cannot be dereferenced this has the desirable + * side effect of trapping those pesky NULL-reference errors in the + * kernel. + */ +static void __init pagetable_init(void) +{ + int range; + + printk("pagetable_init\n"); + + /* Map each physical memory range to its kernel vaddr */ + + for (range = 0; range < npmem_ranges; range++) { + unsigned long start_paddr; + unsigned long end_paddr; + unsigned long size; + + start_paddr = pmem_ranges[range].start_pfn << PAGE_SHIFT; + end_paddr = start_paddr + (pmem_ranges[range].pages << PAGE_SHIFT); + size = pmem_ranges[range].pages << PAGE_SHIFT; + + map_pages((unsigned long)__va(start_paddr), start_paddr, + size, PAGE_KERNEL); + } + +#ifdef CONFIG_BLK_DEV_INITRD + if (initrd_end && initrd_end > mem_limit) { + printk("initrd: mapping %08lx-%08lx\n", initrd_start, initrd_end); + map_pages(initrd_start, __pa(initrd_start), + initrd_end - initrd_start, PAGE_KERNEL); + } +#endif empty_zero_page = alloc_bootmem_pages(PAGE_SIZE); memset(empty_zero_page, 0, PAGE_SIZE); } -unsigned long gateway_pgd_offset; -unsigned long gateway_pgd_entry; - static void __init gateway_init(void) { - unsigned long hpux_gateway_page_addr; unsigned long linux_gateway_page_addr; - pgd_t *pg_dir; - pmd_t *pmd_base; - pmd_t *pmd; - pte_t *pg_table_base; - pte_t *pg_table; - /* FIXME: These are 'const' in order to trick the compiler - into not treating them as DP-relative data. */ - extern void * const hpux_gateway_page; + /* FIXME: This is 'const' in order to trick the compiler + into not treating it as DP-relative data. */ extern void * const linux_gateway_page; - pte_t pte; - hpux_gateway_page_addr = HPUX_GATEWAY_ADDR & PAGE_MASK; linux_gateway_page_addr = LINUX_GATEWAY_ADDR & PAGE_MASK; - gateway_pgd_offset = hpux_gateway_page_addr >> PGDIR_SHIFT; - /* * Setup Linux Gateway page. * @@ -303,177 +666,356 @@ * page 0), so it doesn't need to be aliased into user space. */ - pg_dir = (pgd_t *)swapper_pg_dir; - -#if PTRS_PER_PMD == 1 - pmd_base = (pmd_t *)pg_dir; - pmd = pmd_base + - ((linux_gateway_page_addr) >> PGDIR_SHIFT); - -#else - pmd_base = (pmd_t *) alloc_bootmem_pages(PAGE_SIZE); - pgd_val(*(pg_dir + (linux_gateway_page_addr >> PGDIR_SHIFT))) = - _PAGE_TABLE | __pa(pmd_base); + map_pages(linux_gateway_page_addr, __pa(&linux_gateway_page), + PAGE_SIZE, PAGE_GATEWAY); +} - pmd = pmd_base + - ((linux_gateway_page_addr & (PMD_MASK) & (PGDIR_SIZE - 1)) >> - PMD_SHIFT); -#endif +void +map_hpux_gateway_page(struct task_struct *tsk, struct mm_struct *mm) +{ + pgd_t *pg_dir; + pmd_t *pmd; + pte_t *pg_table; + unsigned long start_pmd; + unsigned long start_pte; + unsigned long address; + unsigned long hpux_gw_page_addr; + /* FIXME: This is 'const' in order to trick the compiler + into not treating it as DP-relative data. */ + extern void * const hpux_gateway_page; - pg_table_base = (pte_t *) alloc_bootmem_pages(PAGE_SIZE); + hpux_gw_page_addr = HPUX_GATEWAY_ADDR & PAGE_MASK; - pmd_val(*pmd) = _PAGE_TABLE | __pa(pg_table_base); + /* + * Setup HP-UX Gateway page. + * + * The HP-UX gateway page resides in the user address space, + * so it needs to be aliased into each process. + */ - pte = __mk_pte(__pa(&linux_gateway_page), PAGE_GATEWAY); + pg_dir = pgd_offset(mm,hpux_gw_page_addr); - pg_table = pg_table_base + - ((linux_gateway_page_addr & (PAGE_MASK) & (PMD_SIZE - 1)) >> - PAGE_SHIFT); +#if PTRS_PER_PMD == 1 + start_pmd = 0; +#else + start_pmd = ((hpux_gw_page_addr >> PMD_SHIFT) & (PTRS_PER_PMD - 1)); +#endif + start_pte = ((hpux_gw_page_addr >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)); - set_pte(pg_table,pte); + address = __pa(&hpux_gateway_page); +#if PTRS_PER_PMD == 1 + pmd = (pmd_t *)__pa(pg_dir); +#else + pmd = (pmd_t *) (PAGE_MASK & pgd_val(*pg_dir)); /* - * Setup HP-UX gateway page. - * This page will be aliased into each user address space. + * pmd is physical at this point */ - pg_table_base = (pte_t *) alloc_bootmem_pages(PAGE_SIZE); - - pte = __mk_pte(__pa(&hpux_gateway_page), PAGE_GATEWAY); - pg_table = pg_table_base + - ((hpux_gateway_page_addr & (PAGE_MASK) & (PMD_SIZE - 1)) >> - PAGE_SHIFT); - - set_pte(pg_table,pte); - + if (!pmd) { + pmd = (pmd_t *) get_zeroed_page(GFP_KERNEL); + pmd = (pmd_t *) __pa(pmd); + } -#if PTRS_PER_PMD == 1 - pmd_base = (pmd_t *)pg_table_base; -#else - pmd_base = (pmd_t *) alloc_bootmem_pages(PAGE_SIZE); - pmd = pmd_base + - ((hpux_gateway_page_addr & (PMD_MASK) & (PGDIR_SIZE - 1)) >> - PMD_SHIFT); - pmd_val(*pmd) = _PAGE_TABLE | __pa(pg_table_base); + pgd_val(*pg_dir) = _PAGE_TABLE | (unsigned long) pmd; #endif + /* now change pmd to kernel virtual addresses */ - gateway_pgd_entry = _PAGE_TABLE | __pa(pmd_base); + pmd = (pmd_t *)__va(pmd) + start_pmd; /* - * We will be aliasing the HP-UX gateway page into all HP-UX - * user spaces at the same address (not counting the space register - * value) that will be equivalently mapped as long as space register - * hashing is disabled. It will be a problem if anyone touches - * the gateway pages at its "kernel" address, since that is - * NOT equivalently mapped. We'll flush the caches at this - * point, just in case some code has touched those addresses - * previous to this, but all bets are off if they get touched - * after this point. + * pg_table is physical at this point */ - flush_all_caches(); + pg_table = (pte_t *) (PAGE_MASK & pmd_val(*pmd)); + if (!pg_table) + pg_table = (pte_t *) __pa(get_zeroed_page(GFP_KERNEL)); - return; + pmd_val(*pmd) = _PAGE_TABLE | (unsigned long) pg_table; + + /* now change pg_table to kernel virtual addresses */ + + pg_table = (pte_t *) __va(pg_table) + start_pte; + set_pte(pg_table, __mk_pte(address, PAGE_GATEWAY)); } +extern void flush_tlb_all_local(void); + void __init paging_init(void) { + int i; + + setup_bootmem(); pagetable_init(); gateway_init(); + flush_cache_all_local(); /* start with known state */ + flush_tlb_all_local(); - { - unsigned long zones_size[MAX_NR_ZONES] = { max_pfn/2, max_pfn/2, }; + for (i = 0; i < npmem_ranges; i++) { + unsigned long zones_size[MAX_NR_ZONES] = { 0, 0, 0, }; - free_area_init(zones_size); + zones_size[ZONE_DMA] = pmem_ranges[i].pages; + free_area_init_node(i,NODE_DATA(i),NULL,zones_size, + (pmem_ranges[i].start_pfn << PAGE_SHIFT),0); } + +#ifdef CONFIG_DISCONTIGMEM + /* + * Initialize support for virt_to_page() macro. + * + * Note that MAX_ADDRESS is the largest virtual address that + * we can map. However, since we map all physical memory into + * the kernel address space, it also has an effect on the maximum + * physical address we can map (MAX_ADDRESS - PAGE_OFFSET). + */ + + maxchunkmap = MAX_ADDRESS >> CHUNKSHIFT; + chunkmap = (unsigned char *)alloc_bootmem(maxchunkmap); + + for (i = 0; i < maxchunkmap; i++) + chunkmap[i] = BADCHUNK; + + for (i = 0; i < npmem_ranges; i++) { + + ADJ_NODE_MEM_MAP(i) = NODE_MEM_MAP(i) - pmem_ranges[i].start_pfn; + { + unsigned long chunk_paddr; + unsigned long end_paddr; + int chunknum; + + chunk_paddr = (pmem_ranges[i].start_pfn << PAGE_SHIFT); + end_paddr = chunk_paddr + (pmem_ranges[i].pages << PAGE_SHIFT); + chunk_paddr &= CHUNKMASK; + + chunknum = (int)CHUNKNUM(chunk_paddr); + while (chunk_paddr < end_paddr) { + if (chunknum >= maxchunkmap) + goto badchunkmap1; + if (chunkmap[chunknum] != BADCHUNK) + goto badchunkmap2; + chunkmap[chunknum] = (unsigned char)i; + chunk_paddr += CHUNKSZ; + chunknum++; + } + } + } + + return; + +badchunkmap1: + panic("paging_init: Physical address exceeds maximum address space!\n"); +badchunkmap2: + panic("paging_init: Collision in chunk map array. CHUNKSZ needs to be smaller\n"); +#endif } -#define NR_SPACE_IDS 8192 +#ifdef CONFIG_PA20 -static unsigned long space_id[NR_SPACE_IDS / (8 * sizeof(long))]; -static unsigned long space_id_index; -static unsigned long free_space_ids = NR_SPACE_IDS; +/* + * Currently, all PA20 chips have 18 bit protection id's, which is the + * limiting factor (space ids are 32 bits). + */ + +#define NR_SPACE_IDS 262144 + +#else /* - * XXX: We should probably unfold the set_bit / test_bit / clear_bit - * locking out of these two functions and have a single spinlock on the - * space_id data structures. - * - * Don't bother. This is all going to be significantly changed in the - * very near future. + * Currently we have a one-to-one relationship between space id's and + * protection id's. Older parisc chips (PCXS, PCXT, PCXL, PCXL2) only + * support 15 bit protection id's, so that is the limiting factor. + * PCXT' has 18 bit protection id's, but only 16 bit spaceids, so it's + * probably not worth the effort for a special case here. */ -#define SPACEID_SHIFT (PAGE_SHIFT + (PT_NLEVELS)*(PAGE_SHIFT - PT_NLEVELS) - 32) +#define NR_SPACE_IDS 32768 + +#endif /* !CONFIG_PA20 */ + +#define RECYCLE_THRESHOLD (NR_SPACE_IDS / 2) +#define SID_ARRAY_SIZE (NR_SPACE_IDS / (8 * sizeof(long))) + +static unsigned long space_id[SID_ARRAY_SIZE] = { 1 }; /* disallow space 0 */ +static unsigned long dirty_space_id[SID_ARRAY_SIZE]; +static unsigned long space_id_index; +static unsigned long free_space_ids = NR_SPACE_IDS - 1; +static unsigned long dirty_space_ids = 0; + +static spinlock_t sid_lock = SPIN_LOCK_UNLOCKED; unsigned long alloc_sid(void) { unsigned long index; - if (free_space_ids == 0) - BUG(); + spin_lock(&sid_lock); - free_space_ids--; + if (free_space_ids == 0) { + if (dirty_space_ids != 0) { + spin_unlock(&sid_lock); + flush_tlb_all(); /* flush_tlb_all() calls recycle_sids() */ + spin_lock(&sid_lock); + } + if (free_space_ids == 0) + BUG(); + } - do { - index = find_next_zero_bit(space_id, NR_SPACE_IDS, space_id_index); - } while(test_and_set_bit(index, space_id)); + free_space_ids--; + index = find_next_zero_bit(space_id, NR_SPACE_IDS, space_id_index); + space_id[index >> SHIFT_PER_LONG] |= (1L << (index & (BITS_PER_LONG - 1))); space_id_index = index; + spin_unlock(&sid_lock); + return index << SPACEID_SHIFT; } void free_sid(unsigned long spaceid) { unsigned long index = spaceid >> SPACEID_SHIFT; - if (index < 0) - BUG(); + unsigned long *dirty_space_offset; + + dirty_space_offset = dirty_space_id + (index >> SHIFT_PER_LONG); + index &= (BITS_PER_LONG - 1); + + spin_lock(&sid_lock); + + if (*dirty_space_offset & (1L << index)) + BUG(); /* attempt to free space id twice */ + + *dirty_space_offset |= (1L << index); + dirty_space_ids++; + + spin_unlock(&sid_lock); +} + + +#ifdef CONFIG_SMP +static void get_dirty_sids(unsigned long *ndirtyptr,unsigned long *dirty_array) +{ + int i; + + /* NOTE: sid_lock must be held upon entry */ + + *ndirtyptr = dirty_space_ids; + if (dirty_space_ids != 0) { + for (i = 0; i < SID_ARRAY_SIZE; i++) { + dirty_array[i] = dirty_space_id[i]; + dirty_space_id[i] = 0; + } + dirty_space_ids = 0; + } - clear_bit(index, space_id); + return; +} + +static void recycle_sids(unsigned long ndirty,unsigned long *dirty_array) +{ + int i; + + /* NOTE: sid_lock must be held upon entry */ + + if (ndirty != 0) { + for (i = 0; i < SID_ARRAY_SIZE; i++) { + space_id[i] ^= dirty_array[i]; + } + + free_space_ids += ndirty; + space_id_index = 0; + } +} + +#else /* CONFIG_SMP */ + +static void recycle_sids(void) +{ + int i; + + /* NOTE: sid_lock must be held upon entry */ + + if (dirty_space_ids != 0) { + for (i = 0; i < SID_ARRAY_SIZE; i++) { + space_id[i] ^= dirty_space_id[i]; + dirty_space_id[i] = 0; + } + + free_space_ids += dirty_space_ids; + dirty_space_ids = 0; + space_id_index = 0; + } +} +#endif + +/* + * flush_tlb_all() calls recycle_sids(), since whenever the entire tlb is + * purged, we can safely reuse the space ids that were released but + * not flushed from the tlb. + */ + +#ifdef CONFIG_SMP - if (space_id_index > index) { - space_id_index = index; +static unsigned long recycle_ndirty; +static unsigned long recycle_dirty_array[SID_ARRAY_SIZE]; +static unsigned int recycle_inuse = 0; + +void flush_tlb_all(void) +{ + int do_recycle; + + do_recycle = 0; + spin_lock(&sid_lock); + if (dirty_space_ids > RECYCLE_THRESHOLD) { + if (recycle_inuse) { + BUG(); /* FIXME: Use a semaphore/wait queue here */ + } + get_dirty_sids(&recycle_ndirty,recycle_dirty_array); + recycle_inuse++; + do_recycle++; + } + spin_unlock(&sid_lock); + smp_call_function((void (*)(void *))flush_tlb_all_local, NULL, 1, 1); + flush_tlb_all_local(); + if (do_recycle) { + spin_lock(&sid_lock); + recycle_sids(recycle_ndirty,recycle_dirty_array); + recycle_inuse = 0; + spin_unlock(&sid_lock); } - free_space_ids++; } +#else +void flush_tlb_all(void) +{ + spin_lock(&sid_lock); + flush_tlb_all_local(); + recycle_sids(); + spin_unlock(&sid_lock); +} +#endif #ifdef CONFIG_BLK_DEV_INITRD void free_initrd_mem(unsigned long start, unsigned long end) { #if 0 + if (start < end) + printk(KERN_INFO "Freeing initrd memory: %ldk freed\n", (end - start) >> 10); for (; start < end; start += PAGE_SIZE) { - ClearPageReserved(mem_map + MAP_NR(start)); - set_page_count(mem_map+MAP_NR(start), 1); + ClearPageReserved(virt_to_page(start)); + set_page_count(virt_to_page(start), 1); free_page(start); - totalram_pages++; + num_physpages++; } - printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); #endif } #endif void si_meminfo(struct sysinfo *val) { - int i; - - i = max_mapnr; - val->totalram = totalram_pages; + val->totalram = num_physpages; val->sharedram = 0; val->freeram = nr_free_pages(); val->bufferram = atomic_read(&buffermem_pages); -#if 0 - while (i-- > 0) { - if (PageReserved(mem_map+i)) - continue; - val->totalram++; - if (!atomic_read(&mem_map[i].count)) - continue; - val->sharedram += atomic_read(&mem_map[i].count) - 1; - } - val->totalram <<= PAGE_SHIFT; - val->sharedram <<= PAGE_SHIFT; -#endif val->totalhigh = 0; val->freehigh = 0; + val->mem_unit = PAGE_SIZE; return; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/mm/ioremap.c linux.19rc3-ac4/arch/parisc/mm/ioremap.c --- linux.19rc3/arch/parisc/mm/ioremap.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/mm/ioremap.c 2002-07-29 13:58:38.000000000 +0100 @@ -0,0 +1,177 @@ +/* + * arch/parisc/mm/ioremap.c + * + * Re-map IO memory to kernel address space so that we can access it. + * This is needed for high PCI addresses that aren't mapped in the + * 640k-1MB IO memory area on PC's + * + * (C) Copyright 1995 1996 Linus Torvalds + * (C) Copyright 2001 Helge Deller + */ + +#include +#include +#include + +static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size, + unsigned long phys_addr, unsigned long flags) +{ + unsigned long end; + + address &= ~PMD_MASK; + end = address + size; + if (end > PMD_SIZE) + end = PMD_SIZE; + if (address >= end) + BUG(); + do { + if (!pte_none(*pte)) { + printk(KERN_ERR "remap_area_pte: page already exists\n"); + BUG(); + } + set_pte(pte, mk_pte_phys(phys_addr, __pgprot(_PAGE_PRESENT | _PAGE_RW | + _PAGE_DIRTY | _PAGE_ACCESSED | flags))); + address += PAGE_SIZE; + phys_addr += PAGE_SIZE; + pte++; + } while (address && (address < end)); +} + +static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, + unsigned long phys_addr, unsigned long flags) +{ + unsigned long end; + + address &= ~PGDIR_MASK; + end = address + size; + if (end > PGDIR_SIZE) + end = PGDIR_SIZE; + phys_addr -= address; + if (address >= end) + BUG(); + do { + pte_t * pte = pte_alloc(NULL, pmd, address); + if (!pte) + return -ENOMEM; + remap_area_pte(pte, address, end - address, address + phys_addr, flags); + address = (address + PMD_SIZE) & PMD_MASK; + pmd++; + } while (address && (address < end)); + return 0; +} + +#if (USE_HPPA_IOREMAP) +static int remap_area_pages(unsigned long address, unsigned long phys_addr, + unsigned long size, unsigned long flags) +{ + int error; + pgd_t * dir; + unsigned long end = address + size; + + phys_addr -= address; + dir = pgd_offset(&init_mm, address); + flush_cache_all(); + if (address >= end) + BUG(); + spin_lock(&init_mm.page_table_lock); + do { + pmd_t *pmd; + pmd = pmd_alloc(dir, address); + error = -ENOMEM; + if (!pmd) + break; + if (remap_area_pmd(pmd, address, end - address, + phys_addr + address, flags)) + break; + error = 0; + address = (address + PGDIR_SIZE) & PGDIR_MASK; + dir++; + } while (address && (address < end)); + spin_unlock(&init_mm.page_table_lock); + flush_tlb_all(); + return error; +} +#endif /* USE_HPPA_IOREMAP */ + +/* + * Generic mapping function (not visible outside): + */ + +/* + * Remap an arbitrary physical address space into the kernel virtual + * address space. Needed when the kernel wants to access high addresses + * directly. + * + * NOTE! We need to allow non-page-aligned mappings too: we will obviously + * have to convert them into an offset in a page-aligned mapping, but the + * caller shouldn't need to know that small detail. + */ +void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags) +{ +#if !(USE_HPPA_IOREMAP) + + unsigned long end = phys_addr + size - 1; + /* Support EISA addresses */ + if ((phys_addr >= 0x00080000 && end < 0x000fffff) + || (phys_addr >= 0x00500000 && end < 0x03bfffff)) { + phys_addr |= 0xfc000000; + } + + return (void *)phys_addr; + +#else + void * addr; + struct vm_struct * area; + unsigned long offset, last_addr; + + /* Don't allow wraparound or zero size */ + last_addr = phys_addr + size - 1; + if (!size || last_addr < phys_addr) + return NULL; + + /* + * Don't allow anybody to remap normal RAM that we're using.. + */ + if (phys_addr < virt_to_phys(high_memory)) { + char *t_addr, *t_end; + struct page *page; + + t_addr = __va(phys_addr); + t_end = t_addr + (size - 1); + + for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++) + if(!PageReserved(page)) + return NULL; + } + + /* + * Mappings have to be page-aligned + */ + offset = phys_addr & ~PAGE_MASK; + phys_addr &= PAGE_MASK; + size = PAGE_ALIGN(last_addr) - phys_addr; + + /* + * Ok, go for it.. + */ + area = get_vm_area(size, VM_IOREMAP); + if (!area) + return NULL; + addr = area->addr; + if (remap_area_pages(VMALLOC_VMADDR(addr), phys_addr, size, flags)) { + vfree(addr); + return NULL; + } + return (void *) (offset + (char *)addr); +#endif +} + +void iounmap(void *addr) +{ +#if !(USE_HPPA_IOREMAP) + return; +#else + if (addr > high_memory) + return vfree((void *) (PAGE_MASK & (unsigned long) addr)); +#endif +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/mm/kmap.c linux.19rc3-ac4/arch/parisc/mm/kmap.c --- linux.19rc3/arch/parisc/mm/kmap.c 2002-07-29 12:50:07.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/mm/kmap.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,143 +0,0 @@ -/* -** Stolen mostly from arch/parisc/kernel/pci-dma.c -*/ - -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include /* get_order */ - -#undef flush_cache_all -#define flush_cache_all flush_all_caches - -typedef void (*pte_iterator_t) (pte_t * pte, unsigned long arg); - -#if 0 -/* XXX This routine could be used with iterate_page() to replace - * unmap_uncached_page() and save a little code space but I didn't - * do that since I'm not certain whether this is the right path. -PB - */ -static void unmap_cached_pte(pte_t * pte, unsigned long arg) -{ - pte_t page = *pte; - pte_clear(pte); - if (!pte_none(page)) { - if (pte_present(page)) { - unsigned long map_nr = pte_pagenr(page); - if (map_nr < max_mapnr) - __free_page(mem_map + map_nr); - } else { - printk(KERN_CRIT - "Whee.. Swapped out page in kernel page table\n"); - } - } -} -#endif - -/* These two routines should probably check a few things... */ -static void set_uncached(pte_t * pte, unsigned long arg) -{ - pte_val(*pte) |= _PAGE_NO_CACHE; -} - -static void set_cached(pte_t * pte, unsigned long arg) -{ - pte_val(*pte) &= ~_PAGE_NO_CACHE; -} - -static inline void iterate_pte(pmd_t * pmd, unsigned long address, - unsigned long size, pte_iterator_t op, - unsigned long arg) -{ - pte_t *pte; - unsigned long end; - - if (pmd_none(*pmd)) - return; - if (pmd_bad(*pmd)) { - pmd_ERROR(*pmd); - pmd_clear(pmd); - return; - } - pte = pte_offset(pmd, address); - address &= ~PMD_MASK; - end = address + size; - if (end > PMD_SIZE) - end = PMD_SIZE; - do { - op(pte, arg); - address += PAGE_SIZE; - pte++; - } while (address < end); -} - -static inline void iterate_pmd(pgd_t * dir, unsigned long address, - unsigned long size, pte_iterator_t op, - unsigned long arg) -{ - pmd_t *pmd; - unsigned long end; - - if (pgd_none(*dir)) - return; - if (pgd_bad(*dir)) { - pgd_ERROR(*dir); - pgd_clear(dir); - return; - } - pmd = pmd_offset(dir, address); - address &= ~PGDIR_MASK; - end = address + size; - if (end > PGDIR_SIZE) - end = PGDIR_SIZE; - do { - iterate_pte(pmd, address, end - address, op, arg); - address = (address + PMD_SIZE) & PMD_MASK; - pmd++; - } while (address < end); -} - -static void iterate_pages(unsigned long address, unsigned long size, - pte_iterator_t op, unsigned long arg) -{ - pgd_t *dir; - unsigned long end = address + size; - - dir = pgd_offset_k(address); - flush_cache_all(); - do { - iterate_pmd(dir, address, end - address, op, arg); - address = (address + PGDIR_SIZE) & PGDIR_MASK; - dir++; - } while (address && (address < end)); - flush_tlb_all(); -} - -void -kernel_set_cachemode(unsigned long vaddr, unsigned long size, int what) -{ - switch (what) { - case IOMAP_FULL_CACHING: - iterate_pages(vaddr, size, set_cached, 0); - flush_tlb_range(&init_mm, vaddr, size); - break; - case IOMAP_NOCACHE_SER: - iterate_pages(vaddr, size, set_uncached, 0); - flush_tlb_range(&init_mm, vaddr, size); - break; - default: - printk(KERN_CRIT - "kernel_set_cachemode mode %d not understood\n", - what); - break; - } -} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/mm/Makefile linux.19rc3-ac4/arch/parisc/mm/Makefile --- linux.19rc3/arch/parisc/mm/Makefile 2002-07-29 12:50:07.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/mm/Makefile 2002-07-29 13:58:37.000000000 +0100 @@ -8,6 +8,6 @@ # Note 2! The CFLAGS definition is now in the main makefile... O_TARGET := mm.o -O_OBJS := init.o fault.o kmap.o extable.o +obj-y := init.o fault.o extable.o ioremap.o include $(TOPDIR)/Rules.make diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/mm/pa11.c linux.19rc3-ac4/arch/parisc/mm/pa11.c --- linux.19rc3/arch/parisc/mm/pa11.c 2002-07-29 12:50:07.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/mm/pa11.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,171 +0,0 @@ -/* $Id: pa11.c,v 1.1 1999/03/17 01:05:41 pjlahaie Exp $ - * - * pa11.c: PA 1.1 specific mmu/cache code. - * - */ -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -extern unsigned long mips_tlb_entries; - -/* page functions */ -void pa11_clear_page(unsigned long page) -{ -} - -static void pa11_copy_page(unsigned long to, unsigned long from) -{ -} - -/* Cache operations. */ -static inline void pa11_flush_cache_all(void) { } -static void pa11_flush_cache_mm(struct mm_struct *mm) { } -static void pa11_flush_cache_range(struct mm_struct *mm, - unsigned long start, - unsigned long end) -{ -} - -static void pa11_flush_cache_page(struct vm_area_struct *vma, - unsigned long page) -{ -} - -static void pa11_flush_page_to_ram(unsigned long page) -{ -} - -static void pa11_flush_cache_sigtramp(unsigned long page) -{ -} - -/* TLB operations. */ -static inline void pa11_flush_tlb_all(void) -{ - unsigned long flags; - int entry; - - save_and_cli(flags); -/* Here we will need to flush all the TLBs */ - restore_flags(flags); -} - -static void pa11_flush_tlb_mm(struct mm_struct *mm) -{ -/* This is what the MIPS does.. Is it the right thing for PA-RISC? */ - if(mm == current->mm) - pa11_flush_tlb_all(); -} - -static void pa11_flush_tlb_range(struct mm_struct *mm, unsigned long start, - unsigned long end) -{ - if(mm == current->mm) - pa11_flush_tlb_all(); -} - -static void pa11_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) -{ - if(vma->vm_mm == current->mm) - pa11_flush_tlb_all(); -} - -static void pa11_load_pgd(unsigned long pg_dir) -{ - unsigned long flags; - /* We need to do the right thing here */ -} - -/* - * Initialize new page directory with pointers to invalid ptes - */ -static void pa11_pgd_init(unsigned long page) -{ - unsigned long dummy1, dummy2; - -} - -static void pa11_update_mmu_cache(struct vm_area_struct * vma, - unsigned long address, pte_t pte) -{ - pa11_flush_tlb_page(vma, address); -} - -static void pa11_show_regs(struct pt_regs * regs) -{ - /* - * Saved main processor registers - */ - printk("$0 : %08x %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", - 0, (unsigned long) regs->regs[1], (unsigned long) regs->regs[2], - (unsigned long) regs->regs[3], (unsigned long) regs->regs[4], - (unsigned long) regs->regs[5], (unsigned long) regs->regs[6], - (unsigned long) regs->regs[7]); - printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", - (unsigned long) regs->regs[8], (unsigned long) regs->regs[9], - (unsigned long) regs->regs[10], (unsigned long) regs->regs[11], - (unsigned long) regs->regs[12], (unsigned long) regs->regs[13], - (unsigned long) regs->regs[14], (unsigned long) regs->regs[15]); - printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", - (unsigned long) regs->regs[16], (unsigned long) regs->regs[17], - (unsigned long) regs->regs[18], (unsigned long) regs->regs[19], - (unsigned long) regs->regs[20], (unsigned long) regs->regs[21], - (unsigned long) regs->regs[22], (unsigned long) regs->regs[23]); - printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx\n", - (unsigned long) regs->regs[24], (unsigned long) regs->regs[25], - (unsigned long) regs->regs[28], (unsigned long) regs->regs[29], - (unsigned long) regs->regs[30], (unsigned long) regs->regs[31]); - - /* - * Saved cp0 registers - */ - printk("epc : %08lx %s\nStatus: %08x\nCause : %08x\n", - (unsigned long) regs->cp0_epc, print_tainted(), - (unsigned int) regs->cp0_status, - (unsigned int) regs->cp0_cause); -} - -static int pa11_user_mode(struct pt_regs *regs) -{ - /* Return user mode stuff?? */ -} - -__initfunc(void ld_mmu_pa11(void)) -{ - - /* Taken directly from the MIPS arch.. Lots of bad things here */ - clear_page = pa11_clear_page; - copy_page = pa11_copy_page; - - flush_cache_all = pa11_flush_cache_all; - flush_cache_mm = pa11_flush_cache_mm; - flush_cache_range = pa11_flush_cache_range; - flush_cache_page = pa11_flush_cache_page; - flush_cache_sigtramp = pa11_flush_cache_sigtramp; - flush_page_to_ram = pa11_flush_page_to_ram; - - flush_tlb_all = pa11_flush_tlb_all; - flush_tlb_mm = pa11_flush_tlb_mm; - flush_tlb_range = pa11_flush_tlb_range; - flush_tlb_page = pa11_flush_tlb_page; - pa11_asid_setup(); - - load_pgd = pa11_load_pgd; - pgd_init = pa11_pgd_init; - update_mmu_cache = pa11_update_mmu_cache; - - show_regs = pa11_show_regs; - - add_wired_entry = pa11_add_wired_entry; - - user_mode = pa11_user_mode; - flush_tlb_all(); -} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/mm/pa20.c linux.19rc3-ac4/arch/parisc/mm/pa20.c --- linux.19rc3/arch/parisc/mm/pa20.c 2002-07-29 12:50:07.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/mm/pa20.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,171 +0,0 @@ -/* $Id: pa20.c,v 1.1 1999/03/17 01:05:41 pjlahaie Exp $ - * - * pa20.c: PA 2.0 specific mmu/cache code. - * - */ -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -extern unsigned long mips_tlb_entries; - -/* page functions */ -void pa20_clear_page(unsigned long page) -{ -} - -static void pa20_copy_page(unsigned long to, unsigned long from) -{ -} - -/* Cache operations. */ -static inline void pa20_flush_cache_all(void) { } -static void pa20_flush_cache_mm(struct mm_struct *mm) { } -static void pa20_flush_cache_range(struct mm_struct *mm, - unsigned long start, - unsigned long end) -{ -} - -static void pa20_flush_cache_page(struct vm_area_struct *vma, - unsigned long page) -{ -} - -static void pa20_flush_page_to_ram(unsigned long page) -{ -} - -static void pa20_flush_cache_sigtramp(unsigned long page) -{ -} - -/* TLB operations. */ -static inline void pa20_flush_tlb_all(void) -{ - unsigned long flags; - int entry; - - save_and_cli(flags); -/* Here we will need to flush all the TLBs */ - restore_flags(flags); -} - -static void pa20_flush_tlb_mm(struct mm_struct *mm) -{ -/* This is what the MIPS does.. Is it the right thing for PA-RISC? */ - if(mm == current->mm) - pa20_flush_tlb_all(); -} - -static void pa20_flush_tlb_range(struct mm_struct *mm, unsigned long start, - unsigned long end) -{ - if(mm == current->mm) - pa20_flush_tlb_all(); -} - -static void pa20_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) -{ - if(vma->vm_mm == current->mm) - pa20_flush_tlb_all(); -} - -static void pa20_load_pgd(unsigned long pg_dir) -{ - unsigned long flags; - /* We need to do the right thing here */ -} - -/* - * Initialize new page directory with pointers to invalid ptes - */ -static void pa20_pgd_init(unsigned long page) -{ - unsigned long dummy1, dummy2; - -} - -static void pa20_update_mmu_cache(struct vm_area_struct * vma, - unsigned long address, pte_t pte) -{ - pa20_flush_tlb_page(vma, address); -} - -static void pa20_show_regs(struct pt_regs * regs) -{ - /* - * Saved main processor registers - */ - printk("$0 : %08x %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", - 0, (unsigned long) regs->regs[1], (unsigned long) regs->regs[2], - (unsigned long) regs->regs[3], (unsigned long) regs->regs[4], - (unsigned long) regs->regs[5], (unsigned long) regs->regs[6], - (unsigned long) regs->regs[7]); - printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", - (unsigned long) regs->regs[8], (unsigned long) regs->regs[9], - (unsigned long) regs->regs[10], (unsigned long) regs->regs[11], - (unsigned long) regs->regs[12], (unsigned long) regs->regs[13], - (unsigned long) regs->regs[14], (unsigned long) regs->regs[15]); - printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", - (unsigned long) regs->regs[16], (unsigned long) regs->regs[17], - (unsigned long) regs->regs[18], (unsigned long) regs->regs[19], - (unsigned long) regs->regs[20], (unsigned long) regs->regs[21], - (unsigned long) regs->regs[22], (unsigned long) regs->regs[23]); - printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx\n", - (unsigned long) regs->regs[24], (unsigned long) regs->regs[25], - (unsigned long) regs->regs[28], (unsigned long) regs->regs[29], - (unsigned long) regs->regs[30], (unsigned long) regs->regs[31]); - - /* - * Saved cp0 registers - */ - printk("epc : %08lx %s\nStatus: %08x\nCause : %08x\n", - (unsigned long) regs->cp0_epc, print_tainted(), - (unsigned int) regs->cp0_status, - (unsigned int) regs->cp0_cause); -} - -static int pa20_user_mode(struct pt_regs *regs) -{ - /* Return user mode stuff?? */ -} - -__initfunc(void ld_mmu_pa20(void)) -{ - - /* Taken directly from the MIPS arch.. Lots of bad things here */ - clear_page = pa20_clear_page; - copy_page = pa20_copy_page; - - flush_cache_all = pa20_flush_cache_all; - flush_cache_mm = pa20_flush_cache_mm; - flush_cache_range = pa20_flush_cache_range; - flush_cache_page = pa20_flush_cache_page; - flush_cache_sigtramp = pa20_flush_cache_sigtramp; - flush_page_to_ram = pa20_flush_page_to_ram; - - flush_tlb_all = pa20_flush_tlb_all; - flush_tlb_mm = pa20_flush_tlb_mm; - flush_tlb_range = pa20_flush_tlb_range; - flush_tlb_page = pa20_flush_tlb_page; - pa20_asid_setup(); - - load_pgd = pa20_load_pgd; - pgd_init = pa20_pgd_init; - update_mmu_cache = pa20_update_mmu_cache; - - show_regs = pa20_show_regs; - - add_wired_entry = pa20_add_wired_entry; - - user_mode = pa20_user_mode; - flush_tlb_all(); -} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/tools/Makefile linux.19rc3-ac4/arch/parisc/tools/Makefile --- linux.19rc3/arch/parisc/tools/Makefile 2002-07-29 12:50:07.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/tools/Makefile 2002-07-29 13:58:38.000000000 +0100 @@ -22,7 +22,4 @@ offset.s: offset.c -clean: - rm -f offset.[hs] $(TARGET).new - include $(TOPDIR)/Rules.make diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/tools/offset.c linux.19rc3-ac4/arch/parisc/tools/offset.c --- linux.19rc3/arch/parisc/tools/offset.c 2002-07-29 12:50:07.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/tools/offset.c 2002-07-29 13:58:38.000000000 +0100 @@ -13,6 +13,13 @@ #include #include #include +#include + +#ifdef __LP64__ +#define FRAME_SIZE 128 +#else +#define FRAME_SIZE 64 +#endif #define text(t) __asm__("\n@@@" t) #define _offset(type, member) (&(((type *)NULL)->member)) @@ -21,7 +28,7 @@ __asm__("\n@@@" string "%0" : : "i" (_offset(ptr, member))) #define size(string, size) \ __asm__("\n@@@" string "%0" : : "i" (sizeof(size))) -#define align(x,y) (((x)+(2*(y))-1)-(((x)+(y)-1)%(y))) +#define align(x,y) (((x)+FRAME_SIZE+(y)-1)-(((x)+(y)-1)%(y))) #define size_align(string, size, algn) \ __asm__("\n@@@" string "%0" : : "i" \ align(sizeof(size),algn)) @@ -32,6 +39,15 @@ text("#ifndef _PARISC_OFFSET_H"); text("#define _PARISC_OFFSET_H"); linefeed; +#ifdef __LP64__ +text("#ifndef __LP64__"); +text("#error offset.h was generated for 64-bit build; did you do 'make dep'?"); +#else +text("#ifdef __LP64__"); +text("#error offset.h was generated for 32-bit build; did you do 'make dep'?"); +#endif +text("#endif"); +linefeed; void output_task_ptreg_defines(void) { @@ -113,23 +129,14 @@ offset("#define TASK_PT_IASQ1 ", struct task_struct, thread.regs.iasq[1]); offset("#define TASK_PT_IAOQ0 ", struct task_struct, thread.regs.iaoq[0]); offset("#define TASK_PT_IAOQ1 ", struct task_struct, thread.regs.iaoq[1]); - offset("#define TASK_PT_CR24 ", struct task_struct, thread.regs.cr24); - offset("#define TASK_PT_CR25 ", struct task_struct, thread.regs.cr25); - offset("#define TASK_PT_CR26 ", struct task_struct, thread.regs.cr26); offset("#define TASK_PT_CR27 ", struct task_struct, thread.regs.cr27); - offset("#define TASK_PT_CR30 ", struct task_struct, thread.regs.cr30); offset("#define TASK_PT_ORIG_R28 ", struct task_struct, thread.regs.orig_r28); offset("#define TASK_PT_KSP ", struct task_struct, thread.regs.ksp); offset("#define TASK_PT_KPC ", struct task_struct, thread.regs.kpc); offset("#define TASK_PT_SAR ", struct task_struct, thread.regs.sar); - offset("#define TASK_PT_CR11 ", struct task_struct, thread.regs.sar); offset("#define TASK_PT_IIR ", struct task_struct, thread.regs.iir); offset("#define TASK_PT_ISR ", struct task_struct, thread.regs.isr); offset("#define TASK_PT_IOR ", struct task_struct, thread.regs.ior); - offset("#define TASK_PT_CR_PID0 ", struct task_struct, thread.regs.cr_pid[0]); - offset("#define TASK_PT_CR_PID1 ", struct task_struct, thread.regs.cr_pid[1]); - offset("#define TASK_PT_CR_PID2 ", struct task_struct, thread.regs.cr_pid[2]); - offset("#define TASK_PT_CR_PID3 ", struct task_struct, thread.regs.cr_pid[3]); size("#define TASK_SZ ", struct task_struct); size_align("#define TASK_SZ_ALGN ", struct task_struct, 64); linefeed; @@ -214,23 +221,14 @@ offset("#define PT_IASQ1 ", struct pt_regs, iasq[1]); offset("#define PT_IAOQ0 ", struct pt_regs, iaoq[0]); offset("#define PT_IAOQ1 ", struct pt_regs, iaoq[1]); - offset("#define PT_CR24 ", struct pt_regs, cr24); - offset("#define PT_CR25 ", struct pt_regs, cr25); - offset("#define PT_CR26 ", struct pt_regs, cr26); offset("#define PT_CR27 ", struct pt_regs, cr27); - offset("#define PT_CR30 ", struct pt_regs, cr30); offset("#define PT_ORIG_R28 ", struct pt_regs, orig_r28); offset("#define PT_KSP ", struct pt_regs, ksp); offset("#define PT_KPC ", struct pt_regs, kpc); offset("#define PT_SAR ", struct pt_regs, sar); - offset("#define PT_CR11 ", struct pt_regs, sar); offset("#define PT_IIR ", struct pt_regs, iir); offset("#define PT_ISR ", struct pt_regs, isr); offset("#define PT_IOR ", struct pt_regs, ior); - offset("#define PT_CR_PID0 ", struct pt_regs, cr_pid[0]); - offset("#define PT_CR_PID1 ", struct pt_regs, cr_pid[1]); - offset("#define PT_CR_PID2 ", struct pt_regs, cr_pid[2]); - offset("#define PT_CR_PID3 ", struct pt_regs, cr_pid[3]); size("#define PT_SIZE ", struct pt_regs); size_align("#define PT_SZ_ALGN ", struct pt_regs, 64); linefeed; @@ -249,6 +247,7 @@ offset("#define TASK_NICE ", struct task_struct, nice); offset("#define TASK_MM ", struct task_struct, mm); offset("#define TASK_PROCESSOR ", struct task_struct, processor); + offset("#define TASK_PERSONALITY ", struct task_struct, personality); size ("#define TASK_SZ ", struct task_struct); size_align("#define TASK_SZ_ALGN ", struct task_struct, 64); linefeed; @@ -257,12 +256,39 @@ void output_irq_stat_defines(void) { text("/* PARISC irq_cpustat_t offsets. */"); - offset("#define IRQSTAT_SI_ACTIVE ", irq_cpustat_t, __softirq_active); - offset("#define IRQSTAT_SI_MASK ", irq_cpustat_t, __softirq_mask); + offset("#define IRQSTAT_SIRQ_PEND ", irq_cpustat_t, __softirq_pending); size ("#define IRQSTAT_SZ ", irq_cpustat_t); linefeed; } +void output_cache_info_defines(void) +{ + text("/* PARISC pdc_cache_info offsets. */"); + offset("#define ICACHE_BASE ", struct pdc_cache_info, ic_base); + offset("#define ICACHE_STRIDE ", struct pdc_cache_info, ic_stride); + offset("#define ICACHE_COUNT ", struct pdc_cache_info, ic_count); + offset("#define ICACHE_LOOP ", struct pdc_cache_info, ic_loop); + offset("#define DCACHE_BASE ", struct pdc_cache_info, dc_base); + offset("#define DCACHE_STRIDE ", struct pdc_cache_info, dc_stride); + offset("#define DCACHE_COUNT ", struct pdc_cache_info, dc_count); + offset("#define DCACHE_LOOP ", struct pdc_cache_info, dc_loop); + offset("#define ITLB_SID_BASE ", struct pdc_cache_info, it_sp_base); + offset("#define ITLB_SID_STRIDE ", struct pdc_cache_info, it_sp_stride); + offset("#define ITLB_SID_COUNT ", struct pdc_cache_info, it_sp_count); + offset("#define ITLB_OFF_BASE ", struct pdc_cache_info, it_off_base); + offset("#define ITLB_OFF_STRIDE ", struct pdc_cache_info, it_off_stride); + offset("#define ITLB_OFF_COUNT ", struct pdc_cache_info, it_off_count); + offset("#define ITLB_LOOP ", struct pdc_cache_info, it_loop); + offset("#define DTLB_SID_BASE ", struct pdc_cache_info, dt_sp_base); + offset("#define DTLB_SID_STRIDE ", struct pdc_cache_info, dt_sp_stride); + offset("#define DTLB_SID_COUNT ", struct pdc_cache_info, dt_sp_count); + offset("#define DTLB_OFF_BASE ", struct pdc_cache_info, dt_off_base); + offset("#define DTLB_OFF_STRIDE ", struct pdc_cache_info, dt_off_stride); + offset("#define DTLB_OFF_COUNT ", struct pdc_cache_info, dt_off_count); + offset("#define DTLB_LOOP ", struct pdc_cache_info, dt_loop); + linefeed; +} + #ifdef PRUMPF_HAD_MORE_TIME void output_thread_defines(void) { diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/vmlinux64.lds linux.19rc3-ac4/arch/parisc/vmlinux64.lds --- linux.19rc3/arch/parisc/vmlinux64.lds 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/vmlinux64.lds 2002-07-29 13:58:38.000000000 +0100 @@ -0,0 +1,76 @@ +/* ld script to make hppa Linux kernel */ +OUTPUT_ARCH(hppa:hppa2.0w) +ENTRY(_stext) +SECTIONS +{ + + . = 0x10100000; + + _text = .; /* Text and read-only data */ + .text BLOCK(16) : { + *(.text*) + *(.PARISC.unwind) + *(.fixup) + *(.lock.text) /* out-of-line lock text */ + *(.gnu.warning) + } = 0 + + . = ALIGN(16); + .rodata : { *(.rodata) } + .kstrtab : { *(.kstrtab) } + + _etext = .; /* End of text section */ + + .data BLOCK(8192) : { /* Data without special */ + data_start = .; + *(.data) + } + + . = ALIGN(16); /* Exception table */ + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + __start___ksymtab = .; /* Kernel symbol table */ + __ksymtab : { *(__ksymtab) } + __stop___ksymtab = .; + + . = ALIGN(16); /* Linkage tables */ + .opd : { *(.opd) } PROVIDE (__gp = .); .plt : { *(.plt) } .dlt : { *(.dlt) } + + . = ALIGN(16384); + __init_begin = .; + .init.text : { *(.init.text) } + .init.data : { *(.init.data) } + . = ALIGN(16); + __setup_start = .; + .setup.init : { *(.setup.init) } + __setup_end = .; + __initcall_start = .; + .initcall.init : { *(.initcall.init) } + __initcall_end = .; + __init_end = .; + + + init_task BLOCK(16384) : { *(init_task) } /* The initial task and kernel stack */ + init_istack BLOCK(32768) : { *(init_task) } /* The initial interrupt stack */ + + _edata = .; /* End of data section */ + + + .bss : { *(.bss) *(COMMON) } /* BSS */ + + + _end = . ; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .note 0 : { *(.note) } + +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/parisc/vmlinux.lds linux.19rc3-ac4/arch/parisc/vmlinux.lds --- linux.19rc3/arch/parisc/vmlinux.lds 2002-07-29 12:50:07.000000000 +0100 +++ linux.19rc3-ac4/arch/parisc/vmlinux.lds 2002-07-29 13:58:38.000000000 +0100 @@ -1,21 +1,14 @@ /* ld script to make hppa Linux kernel */ -OUTPUT_FORMAT("elf32-hppa") OUTPUT_ARCH(hppa) ENTRY(_stext) SECTIONS { -/* right now use 0x10000/0x11000, later when we don't use Console and - * Boot-Device IODC, we will change this to 0x8000 !!! - */ - - . = 0xc0100000; -/* . = 0x10000; */ + . = 0x10100000; _text = .; /* Text and read-only data */ .text BLOCK(16) : { *(.text*) - *(.PARISC.unwind) *(.fixup) *(.lock.text) /* out-of-line lock text */ *(.gnu.warning) @@ -57,12 +50,14 @@ init_task BLOCK(16384) : { *(init_task) } /* The initial task and kernel stack */ + init_istack BLOCK(32768) : { *(init_istack) } /* The initial interrupt stack */ _edata = .; /* End of data section */ .bss : { *(.bss) *(COMMON) } /* BSS */ + .PARISC.unwind : { *(.PARISC.unwind) } _end = . ; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/ppc/config.in linux.19rc3-ac4/arch/ppc/config.in --- linux.19rc3/arch/ppc/config.in 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/arch/ppc/config.in 2002-07-29 13:58:38.000000000 +0100 @@ -395,6 +395,8 @@ source net/bluetooth/Config.in +source lib/Config.in + mainmenu_option next_comment comment 'Kernel hacking' diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/ppc/kernel/setup.c linux.19rc3-ac4/arch/ppc/kernel/setup.c --- linux.19rc3/arch/ppc/kernel/setup.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/arch/ppc/kernel/setup.c 2002-07-29 13:58:38.000000000 +0100 @@ -693,14 +693,16 @@ id->cfs_enable_2 = __le16_to_cpu(id->cfs_enable_2); id->csf_default = __le16_to_cpu(id->csf_default); id->dma_ultra = __le16_to_cpu(id->dma_ultra); - id->word89 = __le16_to_cpu(id->word89); - id->word90 = __le16_to_cpu(id->word90); + id->trseuc = __le16_to_cpu(id->trseuc); + id->trsEuc = __le16_to_cpu(id->trsEuc); id->CurAPMvalues = __le16_to_cpu(id->CurAPMvalues); - id->word92 = __le16_to_cpu(id->word92); + id->mprc = __le16_to_cpu(id->mprc); id->hw_config = __le16_to_cpu(id->hw_config); id->acoustic = __le16_to_cpu(id->acoustic); - for (i = 0; i < 5; i++) - id->words95_99[i] = __le16_to_cpu(id->words95_99[i]); + id->msrqs = __le16_to_cpu(id->msrqs); + id->sxfert = __le16_to_cpu(id->sxfert); + id->sal = __le16_to_cpu(id->sal); + id->spg = __le32_to_cpu(id->spg); id->lba_capacity_2 = __le64_to_cpu(id->lba_capacity_2); for (i = 0; i < 22; i++) id->words104_125[i] = __le16_to_cpu(id->words104_125[i]); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/ppc/mm/fault.c linux.19rc3-ac4/arch/ppc/mm/fault.c --- linux.19rc3/arch/ppc/mm/fault.c 2002-07-29 12:50:05.000000000 +0100 +++ linux.19rc3-ac4/arch/ppc/mm/fault.c 2002-07-29 17:22:23.000000000 +0100 @@ -109,8 +109,6 @@ goto bad_area; if (vma->vm_start <= address) goto good_area; - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; if (expand_stack(vma, address)) goto bad_area; @@ -197,8 +195,7 @@ out_of_memory: up_read(&mm->mmap_sem); if (current->pid == 1) { - current->policy |= SCHED_YIELD; - schedule(); + yield(); down_read(&mm->mmap_sem); goto survive; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/ppc64/kernel/ioctl32.c linux.19rc3-ac4/arch/ppc64/kernel/ioctl32.c --- linux.19rc3/arch/ppc64/kernel/ioctl32.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/arch/ppc64/kernel/ioctl32.c 2002-07-29 13:58:38.000000000 +0100 @@ -4149,6 +4149,8 @@ COMPATIBLE_IOCTL(HCIDEVUP), COMPATIBLE_IOCTL(HCIDEVDOWN), COMPATIBLE_IOCTL(HCIDEVRESET), +COMPATIBLE_IOCTL(HCIDEVRESTAT), +COMPATIBLE_IOCTL(HCIGETDEVINFO), COMPATIBLE_IOCTL(HCIGETDEVLIST), COMPATIBLE_IOCTL(HCISETRAW), COMPATIBLE_IOCTL(HCISETSCAN), diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/ppc64/kernel/setup.c linux.19rc3-ac4/arch/ppc64/kernel/setup.c --- linux.19rc3/arch/ppc64/kernel/setup.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/arch/ppc64/kernel/setup.c 2002-07-29 13:58:38.000000000 +0100 @@ -607,17 +607,19 @@ id->cfs_enable_2 = __le16_to_cpu(id->cfs_enable_2); id->csf_default = __le16_to_cpu(id->csf_default); id->dma_ultra = __le16_to_cpu(id->dma_ultra); - id->word89 = __le16_to_cpu(id->word89); - id->word90 = __le16_to_cpu(id->word90); + id->trseuc = __le16_to_cpu(id->trseuc); + id->trsEuc = __le16_to_cpu(id->trsEuc); id->CurAPMvalues = __le16_to_cpu(id->CurAPMvalues); - id->word92 = __le16_to_cpu(id->word92); + id->mprc = __le16_to_cpu(id->mprc); id->hw_config = __le16_to_cpu(id->hw_config); id->acoustic = __le16_to_cpu(id->acoustic); - for (i = 0; i < 5; i++) - id->words95_99[i] = __le16_to_cpu(id->words95_99[i]); + id->msrqs = __le16_to_cpu(id->msrqs); + id->sxfert = __le16_to_cpu(id->sxfert); + id->sal = __le16_to_cpu(id->sal); + id->spg = __le32_to_cpu(id->spg); id->lba_capacity_2 = __le64_to_cpu(id->lba_capacity_2); - for (i = 0; i < 21; i++) - id->words104_125[i] = __le16_to_cpu(id->words104_125[i]); + for (i = 0; i < 22; i++) + id->words104_125[i] = __le16_to_cpu(id->words104_125[i]); id->last_lun = __le16_to_cpu(id->last_lun); id->word127 = __le16_to_cpu(id->word127); id->dlf = __le16_to_cpu(id->dlf); @@ -627,14 +629,14 @@ id->word156 = __le16_to_cpu(id->word156); for (i = 0; i < 3; i++) id->words157_159[i] = __le16_to_cpu(id->words157_159[i]); - id->cfa_power=__le16_to_cpu(id->cfa_power); - for (i = 0; i < 15; i++) + id->cfa_power = __le16_to_cpu(id->cfa_power); + for (i = 0; i < 14; i++) id->words161_175[i] = __le16_to_cpu(id->words161_175[i]); - for (i = 0; i < 29; i++) + for (i = 0; i < 31; i++) id->words176_205[i] = __le16_to_cpu(id->words176_205[i]); for (i = 0; i < 48; i++) id->words206_254[i] = __le16_to_cpu(id->words206_254[i]); - id->integrity_word=__le16_to_cpu(id->integrity_word); + id->integrity_word = __le16_to_cpu(id->integrity_word); } #endif diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/s390/config.in linux.19rc3-ac4/arch/s390/config.in --- linux.19rc3/arch/s390/config.in 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/arch/s390/config.in 2002-07-29 13:58:38.000000000 +0100 @@ -75,3 +75,4 @@ bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ endmenu +source lib/Config.in diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/s390/kernel/entry.S linux.19rc3-ac4/arch/s390/kernel/entry.S --- linux.19rc3/arch/s390/kernel/entry.S 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/arch/s390/kernel/entry.S 2002-07-29 13:58:38.000000000 +0100 @@ -254,13 +254,14 @@ ret_from_fork: basr %r13,0 l %r13,.Lentry_base-.(%r13) # setup base pointer to &entry_base + # not saving R14 here because we go to sysc_return ultimately + l %r1,BASED(.Lschedtail) + basr %r14,%r1 # call schedule_tail (unlock stuff) GET_CURRENT # load pointer to task_struct to R9 stosm 24(%r15),0x03 # reenable interrupts sr %r0,%r0 # child returns 0 st %r0,SP_R2(%r15) # store return value (change R2 on stack) - l %r1,BASED(.Lschedtail) - la %r14,BASED(sysc_return) - br %r1 # call schedule_tail, return to sysc_return + b BASED(sysc_return) # # clone, fork, vfork, exec and sigreturn need glue, diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/s390/mm/fault.c linux.19rc3-ac4/arch/s390/mm/fault.c --- linux.19rc3/arch/s390/mm/fault.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/arch/s390/mm/fault.c 2002-07-29 13:58:38.000000000 +0100 @@ -293,8 +293,7 @@ out_of_memory: up_read(&mm->mmap_sem); if (tsk->pid == 1) { - tsk->policy |= SCHED_YIELD; - schedule(); + yield(); down_read(&mm->mmap_sem); goto survive; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/s390x/config.in linux.19rc3-ac4/arch/s390x/config.in --- linux.19rc3/arch/s390x/config.in 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/arch/s390x/config.in 2002-07-29 13:58:38.000000000 +0100 @@ -77,3 +77,4 @@ bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ endmenu +source lib/Config.in diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/s390x/kernel/entry.S linux.19rc3-ac4/arch/s390x/kernel/entry.S --- linux.19rc3/arch/s390x/kernel/entry.S 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/arch/s390x/kernel/entry.S 2002-07-29 13:58:38.000000000 +0100 @@ -240,11 +240,11 @@ # .globl ret_from_fork ret_from_fork: + brasl %r14,schedule_tail GET_CURRENT # load pointer to task_struct to R9 stosm 48(%r15),0x03 # reenable interrupts xc SP_R2(8,%r15),SP_R2(%r15) # child returns 0 - larl %r14,sysc_return - jg schedule_tail # return to sysc_return + j sysc_return # # clone, fork, vfork, exec and sigreturn need glue, diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/s390x/kernel/linux32.c linux.19rc3-ac4/arch/s390x/kernel/linux32.c --- linux.19rc3/arch/s390x/kernel/linux32.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/arch/s390x/kernel/linux32.c 2002-07-29 13:58:38.000000000 +0100 @@ -912,64 +912,97 @@ return sys32_fcntl(fd, cmd, arg); } -struct dqblk32 { - __u32 dqb_bhardlimit; - __u32 dqb_bsoftlimit; - __u32 dqb_curblocks; - __u32 dqb_ihardlimit; - __u32 dqb_isoftlimit; - __u32 dqb_curinodes; - __kernel_time_t32 dqb_btime; - __kernel_time_t32 dqb_itime; -}; - extern asmlinkage int sys_quotactl(int cmd, const char *special, int id, caddr_t addr); -asmlinkage int sys32_quotactl(int cmd, const char *special, int id, unsigned long addr) +#ifdef CONFIG_QIFACE_COMPAT +#ifdef CONFIG_QIFACE_V1 +struct user_dqblk32 { + __u32 dqb_bhardlimit; + __u32 dqb_bsoftlimit; + __u32 dqb_curblocks; + __u32 dqb_ihardlimit; + __u32 dqb_isoftlimit; + __u32 dqb_curinodes; + __kernel_time_t32 dqb_btime; + __kernel_time_t32 dqb_itime; +}; +typedef struct v1c_mem_dqblk comp_dqblk_t; + +#define Q_COMP_GETQUOTA Q_V1_GETQUOTA +#define Q_COMP_SETQUOTA Q_V1_SETQUOTA +#define Q_COMP_SETQLIM Q_V1_SETQLIM +#define Q_COMP_SETUSE Q_V1_SETUSE +#else +struct user_dqblk32 { + __u32 dqb_ihardlimit; + __u32 dqb_isoftlimit; + __u32 dqb_curinodes; + __u32 dqb_bhardlimit; + __u32 dqb_bsoftlimit; + __u64 dqb_curspace; + __kernel_time_t32 dqb_btime; + __kernel_time_t32 dqb_itime; +}; +typedef struct v2c_mem_dqblk comp_dqblk_t; + +#define Q_COMP_GETQUOTA Q_V2_GETQUOTA +#define Q_COMP_SETQUOTA Q_V2_SETQUOTA +#define Q_COMP_SETQLIM Q_V2_SETQLIM +#define Q_COMP_SETUSE Q_V2_SETUSE +#endif + +asmlinkage int sys32_quotactl(int cmd, const char *special, int id, caddr_t addr) { int cmds = cmd >> SUBCMDSHIFT; int err; - struct dqblk d; + comp_dqblk_t d; mm_segment_t old_fs; char *spec; switch (cmds) { - case Q_GETQUOTA: - break; - case Q_SETQUOTA: - case Q_SETUSE: - case Q_SETQLIM: - if (copy_from_user (&d, (struct dqblk32 *)addr, - sizeof (struct dqblk32))) - return -EFAULT; - d.dqb_itime = ((struct dqblk32 *)&d)->dqb_itime; - d.dqb_btime = ((struct dqblk32 *)&d)->dqb_btime; - break; + case Q_COMP_GETQUOTA: + break; + case Q_COMP_SETQUOTA: + case Q_COMP_SETUSE: + case Q_COMP_SETQLIM: + if (copy_from_user(&d, (struct user_dqblk32 *)addr, + sizeof (struct user_dqblk32))) + return -EFAULT; + d.dqb_itime = ((struct user_dqblk32 *)&d)->dqb_itime; + d.dqb_btime = ((struct user_dqblk32 *)&d)->dqb_btime; + break; default: - return sys_quotactl(cmd, special, - id, (caddr_t)addr); + return sys_quotactl(cmd, special, id, (__kernel_caddr_t)addr); } spec = getname (special); err = PTR_ERR(spec); if (IS_ERR(spec)) return err; - old_fs = get_fs (); + old_fs = get_fs(); set_fs (KERNEL_DS); - err = sys_quotactl(cmd, (const char *)spec, id, (caddr_t)&d); + err = sys_quotactl(cmd, (const char *)spec, id, (__kernel_caddr_t)&d); set_fs (old_fs); putname (spec); if (err) return err; - if (cmds == Q_GETQUOTA) { + if (cmds == Q_COMP_GETQUOTA) { __kernel_time_t b = d.dqb_btime, i = d.dqb_itime; - ((struct dqblk32 *)&d)->dqb_itime = i; - ((struct dqblk32 *)&d)->dqb_btime = b; - if (copy_to_user ((struct dqblk32 *)addr, &d, - sizeof (struct dqblk32))) + ((struct user_dqblk32 *)&d)->dqb_itime = i; + ((struct user_dqblk32 *)&d)->dqb_btime = b; + if (copy_to_user ((struct user_dqblk32 *)addr, &d, + sizeof (struct user_dqblk32))) return -EFAULT; } return 0; } +#else +/* No conversion needed for new interface */ +asmlinkage int sys32_quotactl(int cmd, const char *special, int id, caddr_t addr) +{ + return sys_quotactl(cmd, special, id, addr); +} +#endif + static inline int put_statfs (struct statfs32 *ubuf, struct statfs *kbuf) { int err; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/s390x/mm/fault.c linux.19rc3-ac4/arch/s390x/mm/fault.c --- linux.19rc3/arch/s390x/mm/fault.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/arch/s390x/mm/fault.c 2002-07-29 13:58:38.000000000 +0100 @@ -293,8 +293,7 @@ out_of_memory: up_read(&mm->mmap_sem); if (tsk->pid == 1) { - tsk->policy |= SCHED_YIELD; - schedule(); + yield(); down_read(&mm->mmap_sem); goto survive; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/sh/config.in linux.19rc3-ac4/arch/sh/config.in --- linux.19rc3/arch/sh/config.in 2002-07-29 12:50:05.000000000 +0100 +++ linux.19rc3-ac4/arch/sh/config.in 2002-07-29 13:58:38.000000000 +0100 @@ -386,3 +386,5 @@ bool 'Early printk support' CONFIG_SH_EARLY_PRINTK fi endmenu + +source lib/Config.in diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/sh/mm/fault.c linux.19rc3-ac4/arch/sh/mm/fault.c --- linux.19rc3/arch/sh/mm/fault.c 2002-07-29 12:50:05.000000000 +0100 +++ linux.19rc3-ac4/arch/sh/mm/fault.c 2002-07-29 17:22:23.000000000 +0100 @@ -72,8 +72,6 @@ return 1; check_stack: - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; if (expand_stack(vma, start) == 0) goto good_area; @@ -207,8 +205,7 @@ out_of_memory: up_read(&mm->mmap_sem); if (current->pid == 1) { - current->policy |= SCHED_YIELD; - schedule(); + yield(); down_read(&mm->mmap_sem); goto survive; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/sparc/config.in linux.19rc3-ac4/arch/sparc/config.in --- linux.19rc3/arch/sparc/config.in 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/arch/sparc/config.in 2002-07-29 13:58:38.000000000 +0100 @@ -271,3 +271,5 @@ bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ endmenu + +source lib/Config.in diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/sparc/kernel/sunos_ioctl.c linux.19rc3-ac4/arch/sparc/kernel/sunos_ioctl.c --- linux.19rc3/arch/sparc/kernel/sunos_ioctl.c 2002-07-29 12:50:05.000000000 +0100 +++ linux.19rc3-ac4/arch/sparc/kernel/sunos_ioctl.c 2002-07-29 13:58:38.000000000 +0100 @@ -39,8 +39,12 @@ { int ret = -EBADF; - if (fd >= SUNOS_NR_OPEN || !fcheck(fd)) + read_lock(¤t->files->file_lock); + if (fd >= SUNOS_NR_OPEN || !fcheck(fd)) { + read_unlock(¤t->files->file_lock); goto out; + } + read_unlock(¤t->files->file_lock); /* First handle an easy compat. case for tty ldisc. */ if(cmd == TIOCSETD) { diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/sparc/mm/fault.c linux.19rc3-ac4/arch/sparc/mm/fault.c --- linux.19rc3/arch/sparc/mm/fault.c 2002-07-29 12:50:05.000000000 +0100 +++ linux.19rc3-ac4/arch/sparc/mm/fault.c 2002-07-29 17:22:23.000000000 +0100 @@ -249,8 +249,6 @@ goto bad_area; if(vma->vm_start <= address) goto good_area; - if(!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; if(expand_stack(vma, address)) goto bad_area; /* @@ -496,8 +494,6 @@ goto bad_area; if(vma->vm_start <= address) goto good_area; - if(!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; if(expand_stack(vma, address)) goto bad_area; good_area: diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/sparc/mm/init.c linux.19rc3-ac4/arch/sparc/mm/init.c --- linux.19rc3/arch/sparc/mm/init.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/arch/sparc/mm/init.c 2002-07-29 13:58:38.000000000 +0100 @@ -61,13 +61,15 @@ pte_t *kmap_pte; pgprot_t kmap_prot; +extern unsigned long fix_kmap_begin; /* calculated in srmmu.c */ + #define kmap_get_fixed_pte(vaddr) \ pte_offset(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)) void __init kmap_init(void) { /* cache the first kmap pte */ - kmap_pte = kmap_get_fixed_pte(FIX_KMAP_BEGIN); + kmap_pte = kmap_get_fixed_pte(fix_kmap_begin); kmap_prot = __pgprot(SRMMU_ET_PTE | SRMMU_PRIV | SRMMU_CACHE); } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/sparc/mm/srmmu.c linux.19rc3-ac4/arch/sparc/mm/srmmu.c --- linux.19rc3/arch/sparc/mm/srmmu.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/arch/sparc/mm/srmmu.c 2002-07-29 13:58:38.000000000 +0100 @@ -114,8 +114,16 @@ int srmmu_cache_pagetables; -/* XXX Make this dynamic based on ram size - Anton */ -#define SRMMU_NOCACHE_BITMAP_SIZE (SRMMU_NOCACHE_NPAGES * 16) +/* these will be initialized in srmmu_nocache_calcsize() */ +int srmmu_nocache_npages; +unsigned long srmmu_nocache_size; +unsigned long srmmu_nocache_end; +unsigned long fix_kmap_begin; +unsigned long fix_kmap_end; +unsigned long pkmap_base; +unsigned long pkmap_base_end; +unsigned long srmmu_nocache_bitmap_size; + #define SRMMU_NOCACHE_BITMAP_SHIFT (PAGE_SHIFT - 4) void *srmmu_nocache_pool; @@ -248,7 +256,7 @@ spin_lock(&srmmu_nocache_spinlock); repeat: - offset = find_next_zero_bit(srmmu_nocache_bitmap, SRMMU_NOCACHE_BITMAP_SIZE, offset); + offset = find_next_zero_bit(srmmu_nocache_bitmap, srmmu_nocache_bitmap_size, offset); /* we align on physical address */ if (align) { @@ -258,7 +266,7 @@ offset = (va_tmp - SRMMU_NOCACHE_VADDR) >> SRMMU_NOCACHE_BITMAP_SHIFT; } - if ((SRMMU_NOCACHE_BITMAP_SIZE - offset) < size) { + if ((srmmu_nocache_bitmap_size - offset) < size) { printk("Run out of nocached RAM!\n"); spin_unlock(&srmmu_nocache_spinlock); return 0; @@ -322,6 +330,35 @@ void srmmu_early_allocate_ptable_skeleton(unsigned long start, unsigned long end); +extern unsigned long probe_memory(void); /* in fault.c */ + +/* Reserve nocache dynamically proportionally to the amount of + * system RAM. -- Tomas Szepe , June 2002 + */ +void srmmu_nocache_calcsize(void) +{ + unsigned long sysmemavail = probe_memory() / 1024; + + srmmu_nocache_npages = + sysmemavail / SRMMU_NOCACHE_ALCRATIO / 1024 * 256; + if (sysmemavail % (SRMMU_NOCACHE_ALCRATIO * 1024)) + srmmu_nocache_npages += 256; + + /* anything above 1280 blows up */ + if (srmmu_nocache_npages > 1280) srmmu_nocache_npages = 1280; + + srmmu_nocache_size = srmmu_nocache_npages * PAGE_SIZE; + srmmu_nocache_bitmap_size = srmmu_nocache_npages * 16; + srmmu_nocache_end = SRMMU_NOCACHE_VADDR + srmmu_nocache_size; + fix_kmap_begin = srmmu_nocache_end; + fix_kmap_end = fix_kmap_begin + (KM_TYPE_NR * NR_CPUS - 1) * PAGE_SIZE; + pkmap_base = SRMMU_NOCACHE_VADDR + srmmu_nocache_size + 0x40000; + pkmap_base_end = pkmap_base + LAST_PKMAP * PAGE_SIZE; + + /* printk("system memory available = %luk\nnocache ram size = %luk\n", + sysmemavail, srmmu_nocache_size / 1024); */ +} + void srmmu_nocache_init(void) { pgd_t *pgd; @@ -330,24 +367,24 @@ unsigned long paddr, vaddr; unsigned long pteval; - srmmu_nocache_pool = __alloc_bootmem(SRMMU_NOCACHE_SIZE, PAGE_SIZE, 0UL); - memset(srmmu_nocache_pool, 0, SRMMU_NOCACHE_SIZE); + srmmu_nocache_pool = __alloc_bootmem(srmmu_nocache_size, PAGE_SIZE, 0UL); + memset(srmmu_nocache_pool, 0, srmmu_nocache_size); - srmmu_nocache_bitmap = __alloc_bootmem(SRMMU_NOCACHE_BITMAP_SIZE, SMP_CACHE_BYTES, 0UL); - memset(srmmu_nocache_bitmap, 0, SRMMU_NOCACHE_BITMAP_SIZE); + srmmu_nocache_bitmap = __alloc_bootmem(srmmu_nocache_bitmap_size, SMP_CACHE_BYTES, 0UL); + memset(srmmu_nocache_bitmap, 0, srmmu_nocache_bitmap_size); srmmu_swapper_pg_dir = (pgd_t *)__srmmu_get_nocache(SRMMU_PGD_TABLE_SIZE, SRMMU_PGD_TABLE_SIZE); memset(__nocache_fix(srmmu_swapper_pg_dir), 0, SRMMU_PGD_TABLE_SIZE); init_mm.pgd = srmmu_swapper_pg_dir; - srmmu_early_allocate_ptable_skeleton(SRMMU_NOCACHE_VADDR, SRMMU_NOCACHE_END); + srmmu_early_allocate_ptable_skeleton(SRMMU_NOCACHE_VADDR, srmmu_nocache_end); spin_lock_init(&srmmu_nocache_spinlock); paddr = __pa((unsigned long)srmmu_nocache_pool); vaddr = SRMMU_NOCACHE_VADDR; - while (vaddr < SRMMU_NOCACHE_END) { + while (vaddr < srmmu_nocache_end) { pgd = pgd_offset_k(vaddr); pmd = srmmu_pmd_offset(__nocache_fix(pgd), vaddr); pte = srmmu_pte_offset(__nocache_fix(pmd), vaddr); @@ -1144,6 +1181,7 @@ pages_avail = 0; last_valid_pfn = bootmem_init(&pages_avail); + srmmu_nocache_calcsize(); srmmu_nocache_init(); srmmu_inherit_prom_mappings(0xfe400000,(LINUX_OPPROM_ENDVM-PAGE_SIZE)); map_kernel(); @@ -1165,12 +1203,12 @@ srmmu_allocate_ptable_skeleton(DVMA_VADDR, DVMA_END); #endif - srmmu_allocate_ptable_skeleton(FIX_KMAP_BEGIN, FIX_KMAP_END); - srmmu_allocate_ptable_skeleton(PKMAP_BASE, PKMAP_BASE_END); + srmmu_allocate_ptable_skeleton(fix_kmap_begin, fix_kmap_end); + srmmu_allocate_ptable_skeleton(pkmap_base, pkmap_base_end); - pgd = pgd_offset_k(PKMAP_BASE); - pmd = pmd_offset(pgd, PKMAP_BASE); - pte = pte_offset(pmd, PKMAP_BASE); + pgd = pgd_offset_k(pkmap_base); + pmd = pmd_offset(pgd, pkmap_base); + pte = pte_offset(pmd, pkmap_base); pkmap_page_table = pte; flush_cache_all(); @@ -1219,7 +1257,7 @@ "nocache used\t: %d\n", srmmu_name, num_contexts, - SRMMU_NOCACHE_SIZE, + srmmu_nocache_size, (srmmu_nocache_used << SRMMU_NOCACHE_BITMAP_SHIFT)); } @@ -1956,7 +1994,7 @@ iaddr = &(insn); \ daddr = &(dest); \ *iaddr = SPARC_BRANCH((unsigned long) daddr, (unsigned long) iaddr); \ - } while(0); + } while(0) static void __init patch_window_trap_handlers(void) { diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/sparc/mm/sun4c.c linux.19rc3-ac4/arch/sparc/mm/sun4c.c --- linux.19rc3/arch/sparc/mm/sun4c.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/arch/sparc/mm/sun4c.c 2002-07-29 13:58:38.000000000 +0100 @@ -425,7 +425,7 @@ daddr = &(dst); \ iaddr = &(src); \ *daddr = *iaddr; \ - } while (0); + } while (0) static void patch_kernel_fault_handler(void) { diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/sparc64/config.in linux.19rc3-ac4/arch/sparc64/config.in --- linux.19rc3/arch/sparc64/config.in 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/arch/sparc64/config.in 2002-07-29 13:58:38.000000000 +0100 @@ -308,3 +308,5 @@ fi endmenu + +source lib/Config.in diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/sparc64/kernel/binfmt_elf32.c linux.19rc3-ac4/arch/sparc64/kernel/binfmt_elf32.c --- linux.19rc3/arch/sparc64/kernel/binfmt_elf32.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/arch/sparc64/kernel/binfmt_elf32.c 2002-07-29 13:58:38.000000000 +0100 @@ -43,7 +43,7 @@ dest[34] = (unsigned int) src->tnpc; \ dest[35] = src->y; \ dest[36] = dest[37] = 0; /* XXX */ \ -} while (0); +} while(0) typedef struct { union { diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/sparc64/kernel/ioctl32.c linux.19rc3-ac4/arch/sparc64/kernel/ioctl32.c --- linux.19rc3/arch/sparc64/kernel/ioctl32.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/arch/sparc64/kernel/ioctl32.c 2002-07-29 13:58:38.000000000 +0100 @@ -4558,19 +4558,11 @@ COMPATIBLE_IOCTL(HCIDEVDOWN) COMPATIBLE_IOCTL(HCIDEVRESET) COMPATIBLE_IOCTL(HCIDEVRESTAT) -COMPATIBLE_IOCTL(HCIGETDEVLIST) COMPATIBLE_IOCTL(HCIGETDEVINFO) -COMPATIBLE_IOCTL(HCIGETCONNLIST) -COMPATIBLE_IOCTL(HCIGETCONNINFO) +COMPATIBLE_IOCTL(HCIGETDEVLIST) COMPATIBLE_IOCTL(HCISETRAW) COMPATIBLE_IOCTL(HCISETSCAN) COMPATIBLE_IOCTL(HCISETAUTH) -COMPATIBLE_IOCTL(HCISETENCRYPT) -COMPATIBLE_IOCTL(HCISETPTYPE) -COMPATIBLE_IOCTL(HCISETLINKPOL) -COMPATIBLE_IOCTL(HCISETLINKMODE) -COMPATIBLE_IOCTL(HCISETACLMTU) -COMPATIBLE_IOCTL(HCISETSCOMTU) COMPATIBLE_IOCTL(HCIINQUIRY) /* Misc. */ COMPATIBLE_IOCTL(0x41545900) /* ATYIO_CLKR */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/sparc64/kernel/sunos_ioctl32.c linux.19rc3-ac4/arch/sparc64/kernel/sunos_ioctl32.c --- linux.19rc3/arch/sparc64/kernel/sunos_ioctl32.c 2002-07-29 12:50:05.000000000 +0100 +++ linux.19rc3-ac4/arch/sparc64/kernel/sunos_ioctl32.c 2002-07-29 13:58:38.000000000 +0100 @@ -100,8 +100,12 @@ if(fd >= SUNOS_NR_OPEN) goto out; - if(!fcheck(fd)) + read_lock(¤t->files->file_lock); + if(!fcheck(fd)) { + read_unlock(¤t->files->file_lock); goto out; + } + read_unlock(¤t->files->file_lock); if(cmd == TIOCSETD) { mm_segment_t old_fs = get_fs(); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/sparc64/kernel/sys_sparc32.c linux.19rc3-ac4/arch/sparc64/kernel/sys_sparc32.c --- linux.19rc3/arch/sparc64/kernel/sys_sparc32.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/arch/sparc64/kernel/sys_sparc32.c 2002-07-29 13:58:38.000000000 +0100 @@ -888,62 +888,97 @@ return sys32_fcntl(fd, cmd, arg); } -struct dqblk32 { - __u32 dqb_bhardlimit; - __u32 dqb_bsoftlimit; - __u32 dqb_curblocks; - __u32 dqb_ihardlimit; - __u32 dqb_isoftlimit; - __u32 dqb_curinodes; - __kernel_time_t32 dqb_btime; - __kernel_time_t32 dqb_itime; -}; - extern asmlinkage int sys_quotactl(int cmd, const char *special, int id, caddr_t addr); -asmlinkage int sys32_quotactl(int cmd, const char *special, int id, unsigned long addr) +#ifdef CONFIG_QIFACE_COMPAT +#ifdef CONFIG_QIFACE_V1 +struct user_dqblk32 { + __u32 dqb_bhardlimit; + __u32 dqb_bsoftlimit; + __u32 dqb_curblocks; + __u32 dqb_ihardlimit; + __u32 dqb_isoftlimit; + __u32 dqb_curinodes; + __kernel_time_t32 dqb_btime; + __kernel_time_t32 dqb_itime; +}; +typedef struct v1c_mem_dqblk comp_dqblk_t; + +#define Q_COMP_GETQUOTA Q_V1_GETQUOTA +#define Q_COMP_SETQUOTA Q_V1_SETQUOTA +#define Q_COMP_SETQLIM Q_V1_SETQLIM +#define Q_COMP_SETUSE Q_V1_SETUSE +#else +struct user_dqblk32 { + __u32 dqb_ihardlimit; + __u32 dqb_isoftlimit; + __u32 dqb_curinodes; + __u32 dqb_bhardlimit; + __u32 dqb_bsoftlimit; + __u64 dqb_curspace; + __kernel_time_t32 dqb_btime; + __kernel_time_t32 dqb_itime; +}; +typedef struct v2c_mem_dqblk comp_dqblk_t; + +#define Q_COMP_GETQUOTA Q_V2_GETQUOTA +#define Q_COMP_SETQUOTA Q_V2_SETQUOTA +#define Q_COMP_SETQLIM Q_V2_SETQLIM +#define Q_COMP_SETUSE Q_V2_SETUSE +#endif + +asmlinkage int sys32_quotactl(int cmd, const char *special, int id, caddr_t addr) { int cmds = cmd >> SUBCMDSHIFT; int err; - struct dqblk d; + comp_dqblk_t d; mm_segment_t old_fs; char *spec; switch (cmds) { - case Q_GETQUOTA: - break; - case Q_SETQUOTA: - case Q_SETUSE: - case Q_SETQLIM: - if (copy_from_user (&d, (struct dqblk32 *)addr, - sizeof (struct dqblk32))) - return -EFAULT; - d.dqb_itime = ((struct dqblk32 *)&d)->dqb_itime; - d.dqb_btime = ((struct dqblk32 *)&d)->dqb_btime; - break; + case Q_COMP_GETQUOTA: + break; + case Q_COMP_SETQUOTA: + case Q_COMP_SETUSE: + case Q_COMP_SETQLIM: + if (copy_from_user(&d, (struct user_dqblk32 *)addr, + sizeof (struct user_dqblk32))) + return -EFAULT; + d.dqb_itime = ((struct user_dqblk32 *)&d)->dqb_itime; + d.dqb_btime = ((struct user_dqblk32 *)&d)->dqb_btime; + break; default: - return sys_quotactl(cmd, special, - id, (caddr_t)addr); + return sys_quotactl(cmd, special, id, (__kernel_caddr_t)addr); } spec = getname (special); err = PTR_ERR(spec); if (IS_ERR(spec)) return err; - old_fs = get_fs (); + old_fs = get_fs(); set_fs (KERNEL_DS); - err = sys_quotactl(cmd, (const char *)spec, id, (caddr_t)&d); + err = sys_quotactl(cmd, (const char *)spec, id, (__kernel_caddr_t)&d); set_fs (old_fs); putname (spec); - if (cmds == Q_GETQUOTA) { + if (err) + return err; + if (cmds == Q_COMP_GETQUOTA) { __kernel_time_t b = d.dqb_btime, i = d.dqb_itime; - ((struct dqblk32 *)&d)->dqb_itime = i; - ((struct dqblk32 *)&d)->dqb_btime = b; - if (copy_to_user ((struct dqblk32 *)addr, &d, - sizeof (struct dqblk32))) + ((struct user_dqblk32 *)&d)->dqb_itime = i; + ((struct user_dqblk32 *)&d)->dqb_btime = b; + if (copy_to_user ((struct user_dqblk32 *)addr, &d, + sizeof (struct user_dqblk32))) return -EFAULT; } - return err; + return 0; } +#else +/* No conversion needed for new interface */ +asmlinkage int sys32_quotactl(int cmd, const char *special, int id, caddr_t addr) +{ + return sys_quotactl(cmd, special, id, addr); +} +#endif + static inline int put_statfs (struct statfs32 *ubuf, struct statfs *kbuf) { int err; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/sparc64/mm/fault.c linux.19rc3-ac4/arch/sparc64/mm/fault.c --- linux.19rc3/arch/sparc64/mm/fault.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/arch/sparc64/mm/fault.c 2002-07-29 17:22:43.000000000 +0100 @@ -346,8 +346,6 @@ if (vma->vm_start <= address) goto good_area; - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; if (!(fault_code & FAULT_CODE_WRITE)) { /* Non-faulting loads shouldn't expand stack. */ insn = get_fault_insn(regs, insn); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/arch/sparc64/solaris/timod.c linux.19rc3-ac4/arch/sparc64/solaris/timod.c --- linux.19rc3/arch/sparc64/solaris/timod.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/arch/sparc64/solaris/timod.c 2002-07-29 13:58:38.000000000 +0100 @@ -149,7 +149,9 @@ struct socket *sock; SOLD("wakeing socket"); + read_lock(¤t->files->file_lock); sock = ¤t->files->fd[fd]->f_dentry->d_inode->u.socket_i; + read_unlock(¤t->files->file_lock); wake_up_interruptible(&sock->wait); read_lock(&sock->sk->callback_lock); if (sock->fasync_list && !test_bit(SOCK_ASYNC_WAITDATA, &sock->flags)) @@ -163,7 +165,9 @@ struct sol_socket_struct *sock; SOLD("queuing primsg"); + read_lock(¤t->files->file_lock); sock = (struct sol_socket_struct *)current->files->fd[fd]->private_data; + read_unlock(¤t->files->file_lock); it->next = sock->pfirst; sock->pfirst = it; if (!sock->plast) @@ -177,7 +181,9 @@ struct sol_socket_struct *sock; SOLD("queuing primsg at end"); + read_lock(¤t->files->file_lock); sock = (struct sol_socket_struct *)current->files->fd[fd]->private_data; + read_unlock(¤t->files->file_lock); it->next = NULL; if (sock->plast) sock->plast->next = it; @@ -355,7 +361,11 @@ (int (*)(int, unsigned long *))SYS(socketcall); int (*sys_sendto)(int, void *, size_t, unsigned, struct sockaddr *, int) = (int (*)(int, void *, size_t, unsigned, struct sockaddr *, int))SYS(sendto); - filp = current->files->fd[fd]; + read_lock(¤t->files->file_lock); + filp = fcheck(fd); + read_unlock(¤t->files->file_lock); + if (!filp) + return -EBADF; ino = filp->f_dentry->d_inode; sock = (struct sol_socket_struct *)filp->private_data; SOLD("entry"); @@ -636,7 +646,11 @@ SOLD("entry"); SOLDD(("%u %p %d %p %p %d %p %d\n", fd, ctl_buf, ctl_maxlen, ctl_len, data_buf, data_maxlen, data_len, *flags_p)); - filp = current->files->fd[fd]; + read_lock(¤t->files->file_lock); + filp = fcheck(fd); + read_unlock(¤t->files->file_lock); + if (!filp) + return -EBADF; ino = filp->f_dentry->d_inode; sock = (struct sol_socket_struct *)filp->private_data; SOLDD(("%p %p\n", sock->pfirst, sock->pfirst ? sock->pfirst->next : NULL)); @@ -847,7 +861,9 @@ lock_kernel(); if(fd >= NR_OPEN) goto out; - filp = current->files->fd[fd]; + read_lock(¤t->files->file_lock); + filp = fcheck(fd); + read_unlock(¤t->files->file_lock); if(!filp) goto out; ino = filp->f_dentry->d_inode; @@ -914,7 +930,9 @@ lock_kernel(); if(fd >= NR_OPEN) goto out; - filp = current->files->fd[fd]; + read_lock(¤t->files->file_lock); + filp = fcheck(fd); + read_unlock(¤t->files->file_lock); if(!filp) goto out; ino = filp->f_dentry->d_inode; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/CREDITS linux.19rc3-ac4/CREDITS --- linux.19rc3/CREDITS 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/CREDITS 2002-07-29 15:23:41.000000000 +0100 @@ -1329,6 +1329,12 @@ S: Provo, Utah 84606-5607 S: USA +N: Marcel Holtmann +E: marcel@holtmann.org +W: http://www.holtmann.org +D: Author of the Linux Bluetooth Subsystem PC Card drivers +S: Germany + N: Rob W. W. Hooft E: hooft@EMBL-Heidelberg.DE D: Shared libs for graphics-tools and for the f2c compiler @@ -1877,7 +1883,8 @@ 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 +D: sun4/330 port, capabilities for elf, speedup for rm on ext2, USB, +D: x86-64 port, software suspend S: Volkova 1131 S: 198 00 Praha 9 S: Czech Republic @@ -2530,6 +2537,12 @@ S: 7000 Stuttgart 50 S: Germany +N: Andrew Rodland +E: arodland@linuxguru.net +D: That crazy morse code thing. +P: D2B1 5215 B1B9 18E0 B6AD 6ADD 4373 165F 1770 BD5C +S: Pennsylvania, USA + N: Christoph Rohland E: hans-christoph.rohland@sap.com E: ch.rohland@gmx.net diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/Documentation/Configure.help linux.19rc3-ac4/Documentation/Configure.help --- linux.19rc3/Documentation/Configure.help 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/Documentation/Configure.help 2002-07-29 15:21:52.000000000 +0100 @@ -437,8 +437,14 @@ The initial RAM disk is a RAM disk that is loaded by the boot loader (loadlin or lilo) and that is mounted as root before the normal boot procedure. It is typically used to load modules needed to mount the - "real" root file system, etc. See - for details. + "real" root file system, etc. + + Due to a problem elsewhere in the kernel, initial RAM disks _must_ + have the file system on them created with a 1024 byte block size. + If any other value is used, the kernel will be unable to mount the + RAM disk at boot time, causing a kernel panic. + + See for details. Loopback device support CONFIG_BLK_DEV_LOOP @@ -1067,10 +1073,10 @@ This effect can be also invoked by calling "idex=ata66" If unsure, say N. -CMD64X chipset support +CMD64X/CMD680 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. + chipsets: CMD643, CMD646, CMD648 or CMD680. CY82C693 chipset support CONFIG_BLK_DEV_CY82C693 @@ -3278,6 +3284,16 @@ a module, say M here and read . If unsure, say N. +CONFIG_SYNCLINK_CS + Enable support for the SyncLink PC Card serial adapter, running + asynchronous and HDLC communications up to 512Kbps. The port is + selectable for RS-232, V.35, RS-449, RS-530, and X.21 + + This driver may 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 synclinkmp.o. If you want to do that, say M + here. + ACP Modem (Mwave) support CONFIG_MWAVE The ACP modem (Mwave) for Linux is a WinModem. It is composed of a @@ -3511,6 +3527,16 @@ When in doubt, say N. +ACPI PCI Hotplug driver +CONFIG_HOTPLUG_PCI_ACPI + Say Y here if you have a system that supports PCI Hotplug using + ACPI. + + 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 acpiphp.o. If you want to compile it + as a module, say M here and read . + MCA support CONFIG_MCA MicroChannel Architecture is found in some IBM PS/2 machines and @@ -4378,14 +4404,11 @@ BIOS routines contained in a ROM chip in HP PA-RISC based machines. Enabling this option will implement the linux framebuffer device and an fbcon color text console using calls to the STI BIOS routines. - The HP framebuffer device is usually planar, uses a strange memory + The HP framebuffer device is sometimes planar, using a strange memory layout, and changing the plane mask to create colored pixels - requires a call to the STI routines, so do not expect /dev/fb to - actually be useful. However, it is the best we have as far as - graphics on the HP chipsets due to lack of hardware level - documentation for the various on-board HP chipsets used in these - systems. It is sufficient for basic text console functions, - including fonts. + can require a call to the STI routines, so /dev/fb may not actually + be useful. However, on some systems packed pixel formats are supported. + It is sufficient for basic text console functions, including fonts. You should probably enable this option, unless you are having trouble getting video when booting the kernel (make sure it isn't @@ -5083,6 +5106,19 @@ replacement for kerneld.) Say Y here and read about configuring it in . +Kernel .config file saved in kernel image +CONFIG_IKCONFIG + This option enables the complete Linux kernel ".config" file contents + to be saved in the kernel (zipped) image file. It provides + documentation of which kernel options are used in a running kernel or + in an on-disk kernel. It can be extracted from the kernel image file + with a script and used as input to rebuild the current kernel or to + build another kernel. Since the kernel image is zipped, using this + option adds approximately 8 KB to a kernel image file. + This option is not available as a module. If you want a separate + file to save the kernel's .config contents, use 'installkernel' or 'cp' + or a similar tool, or just save it in '/lib/modules/'. + ARP daemon support CONFIG_ARPD Normally, the kernel maintains an internal cache which maps IP @@ -6092,6 +6128,12 @@ This is a Logical Link Layer protocol used for X.25 connections over Ethernet, using ordinary Ethernet cards. +ANSI/IEEE 802.2 Data link layer User Interface SAPs (EXPERIMENTAL) +CONFIG_LLC_UI + LLC User Interface SAPs is a Linux socket interface into the LLC datalink + layer. This allows a user to create entire user space network layers tied + to a real SAP. + Frame Diverter CONFIG_NET_DIVERT The Frame Diverter allows you to divert packets from the @@ -8853,13 +8895,13 @@ Aironet 4500/4800 I365 broken support CONFIG_AIRONET4500_I365 If you have a PCMCIA Aironet 4500/4800 card which you want to use - without the standard PCMCIA cardservices provided by the pcmcia-cs + without the standard PCMCIA card provided by the pcmcia-cs package, say Y here. This is not recommended, so say N. Aironet 4500/4800 PCMCIA support CONFIG_AIRONET4500_CS 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 + want to use with the standard PCMCIA card provided by the pcmcia-cs package. This driver is also available as a module ( = code which can be @@ -12165,12 +12207,44 @@ Quota support CONFIG_QUOTA If you say Y here, you will be able to set per user limits for disk - usage (also called disk quotas). Currently, it works only for the - ext2 file system. You need additional software in order to use quota - support; for details, read the Quota mini-HOWTO, available from + usage (also called disk quotas). Currently, it works for the + ext2, ext3, and reiserfs file system. You need additional software + in order to use quota support (you can download sources from + ). For further details, read + the Quota mini-HOWTO, available from . Probably the quota support is only useful for multi user systems. If unsure, say N. +Old quota format support +CONFIG_QFMT_V1 + This quota format was (is) used by kernels earlier than 2.4.??. If + you have quota working and you don't want to convert to new quota + format say Y here. + +VFS v0 quota format support +CONFIG_QFMT_V2 + This quota format allows using quotas with 32-bit UIDs/GIDs. If you + need this functionality say Y here. Note that you will need latest + quota utilities for new quota format with this kernel. + +Compatible quota interfaces +CONFIG_QIFACE_COMPAT + This option will enable old quota interface in kernel. + If you have old quota tools (version <= 3.04) and you don't want to + upgrade them say Y here. + +Original quota interface +CONFIG_QIFACE_V1 + This is the oldest quota interface. It was used for old quota format. + If you have old quota tools and you use old quota format choose this + interface (if unsure, this interface is the best one to choose). + +VFS v0 quota interface +CONFIG_QIFACE_V2 + This quota interface was used by VFS v0 quota format. If you need + support for VFS v0 quota format (eg. you're using quota on ReiserFS) + and you don't want to upgrade quota tools, choose this interface. + Memory Technology Device (MTD) support CONFIG_MTD Memory Technology Devices are flash, RAM and similar chips, often @@ -13242,7 +13316,6 @@ inserted in and removed from the running kernel whenever you want). The module will be called audio.o. If you want to compile it as a module, say M here and read . - USB Modem (CDC ACM) support CONFIG_USB_ACM @@ -14441,6 +14514,36 @@ Because this option adds considerably to the size of each buffer, most people will want to say N here. +BeOS filesystem support (BeFS) (read only) +CONFIG_BEFS_FS + The BeOS File System (BeFS) is the native file system of Be, Inc's + BeOS. Notable features include support for arbitrary attributes + on files and directories, and database-like indices on selected + attributes. (Also note that this driver doesn't make those features + available at this time). It is a 64 bit filesystem, so it supports + extremely large volumes and files. + + If you use this filesystem, you should also say Y to at least one + of the NLS (native language support) options below. + + 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 befs.o. + +Debug BeFS +CONFIG_BEFS_DEBUG + If you say Y here, you can use the 'debug' mount option to enable + debugging output from the driver. This is unlike previous versions + of the driver, where enabling this option would turn on debugging + output automatically. + + Example: + mount -t befs /dev/hda2 /mnt -o debug + + BFS file system support CONFIG_BFS_FS Boot File System (BFS) is a file system used under SCO UnixWare to @@ -14884,13 +14987,10 @@ If you would like to include the NFSv3 server as well as the NFSv2 server, say Y here. If unsure, say Y. -Provide NFS over TCP server support DEVELOPER ONLY +Provide NFS over TCP server support EXPERIMENTAL CONFIG_NFSD_TCP - If you are a developer and want to work on fixing problems with - NFS server over TCP support, say Y here. If unsure, say N. - - Some problems can be found by looking for FIXME in - . + Enable NFS service over TCP connections. This the officially + still experimental, but seems to work well. OS/2 HPFS file system support CONFIG_HPFS_FS @@ -15328,14 +15428,9 @@ Intel EFI GUID partition support CONFIG_EFI_PARTITION Say Y here if you would like to use hard disks under Linux which - were partitioned using EFI GPT. Presently only useful on the - IA-64 platform. - -/dev/guid support (EXPERIMENTAL) -CONFIG_DEVFS_GUID - Say Y here if you would like to access disks and partitions by - their Globally Unique Identifiers (GUIDs) which will appear as - symbolic links in /dev/guid. + were partitioned using EFI GPT. This is the default partition + scheme on IA64, and can be used on other platforms when + large block device (64-bit block address) support is desired. Ultrix partition table support CONFIG_ULTRIX_PARTITION @@ -15375,6 +15470,25 @@ hard drives and ADFS-formatted floppy disks. This is experimental codes, so if you're unsure, say N. +JFS filesystem support +CONFIG_JFS_FS + This is a port of IBM's Journalling Filesystem . More information is + available in the file Documentation/filesystems/jfs.txt. + + If you do not intend to use the JFS filesystem, say N. + +JFS Debugging +CONFIG_JFS_DEBUG + If you are experiencing any problems with the JFS filesystem, say + Y here. This will result in additional debugging messages to be + written to the system log. Under normal circumstances, this + results in very little overhead. + +JFS Statistics +CONFIG_JFS_STATISTICS + Enabling this option will cause statistics from the JFS file system + to be made available to the user in the /proc/fs/jfs/ directory. + /dev/pts file system for Unix98 PTYs CONFIG_DEVPTS_FS You should say Y here if you said Y to "Unix98 PTY support" above. @@ -16156,17 +16270,36 @@ HIL keyboard support CONFIG_HIL The "Human Interface Loop" is a older, 8-channel USB-like controller - used in Hewlett Packard PA-RISC based machines. There are a few - cases where it is seen on PC/MAC architectures as well, usually also - manufactured by HP. This driver is based off MACH and BSD drivers, - and implements support for a keyboard attached to the HIL port. + used in several Hewlett Packard models. This driver is based off + MACH and BSD drivers, and implements support for a keyboard attached + to the HIL port, but not for any other types of HIL input devices + like mice or tablets. However, it has been thoroughly tested and is + stable. + Full support for the USB-like functions and non-keyboard channels of - the HIL is not provided for in this driver. There are vestiges of - mouse support in the driver, but it is probably not working. The - necessary hardware documentation to fully support the HIL controller - and interface it to the linux-input API is lacking. + the HIL is currently being added to the PA-RISC port and will + be backported to work on the m68k port as well. + + Enable this option if you intend to use a HIL keyboard as your + primary keyboard and/or do not wish to test the new HIL driver. - Enable this option if you intend to use a HIL keyboard. +HP System Device Controller support +CONFIG_HP_SDC + This option enables supports for the the "System Device Controller", + an i8042 carrying microcode to manage a few miscellanous devices + on some Hewlett Packard systems. The SDC itself contains a 10ms + resolution timer/clock capable of delivering interrupts on periodic + and one-shot basis. The SDC may also be connected to a battery-backed + real-time clock, a basic audio waveform generator, and an HP-HIL + Master Link Controller serving up to seven input devices. + + By itself this option is rather useless, but enabling it will + enable selection of drivers for the abovementioned devices. + It is, however, incompatible with the old, reliable HIL keyboard + driver, and the new HIL driver is experimental, so if you plan to + use a HIL keyboard as your primary keyboard, you may wish to + keep using that driver until the new HIL drivers have had more + testing. Include IOP (IIfx/Quadra 9x0) ADB driver CONFIG_ADB_IOP @@ -16476,6 +16609,19 @@ read . The module will be called istallion.o. +PDC software console support +CONFIG_PDC_CONSOLE + Saying Y here will enable the software based PDC console to be + used as the system console. This is useful for machines in + which the hardware based console has not been written yet. The + following steps must be competed to use the PDC console: + + 1. create the device entry (mknod /dev/ttyB0 c 60 0) + 2. Edit the /etc/inittab to start a getty listening on /dev/ttyB0 + 3. Add device ttyB0 to /etc/securetty (if you want to log on as + root on this console.) + 4. Change the kernel command console parameter to: console=ttyB0 + Microgate SyncLink adapter support CONFIG_SYNCLINK Provides support for the SyncLink ISA and PCI multiprotocol serial @@ -16614,6 +16760,10 @@ doing that; to actually get it to happen you need to pass the option "console=lp0" 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 behaviour + can be changed. See drivers/char/lp.c (do this at your own risk). + If the printer is out of paper (or off, or unplugged, or too busy..) the kernel will stall until the printer is ready again. By defining CONSOLE_LP_STRICT to 0 (at your own risk) you @@ -17501,7 +17651,134 @@ determined automatically, so you need to specify it here ONLY if running a DEC Alpha, otherwise this setting has no effect. -Double Talk PC internal speech card support +Speakup console speech output for Linux +CONFIG_SPEAKUP + Choosing this Option will include support for console speech output. + + Speakup provides access to Linux for the visually impaired community. + It does this by sending console output to a number of different + hardware speech synthesizers. It provides access to Linux by Making + screen review functions available such as are used in comercial screen + review packages for the MSDOS and MSWINDOWS world. + + The drivers supplied under this option are not standard devices in the + /dev/ sence of the meaning. They can be thought of as a video card + for the blind. They are used by speakup and only speakup. + + For more information about speakup and its drivers check out + http://www.linux-speakup.org, or read the Documentation in + linux/Documentation/speakup. + + The currently supported synthesizers are: + Accent PC internal synthesizer. + Accent SA external Accent synthesizer. + Apollo II external synthesizer. + Audapter external synthesizer. + Braille 'N Speak external synthesizer. + Dectalk Express and external synthesizers. + DoubleTalk PC Internal synthesizer, + LiteTalk/DoubleTalk-LT external serial synthesizers, + Speakout external synthesizer, + Transport external synthesizer. + + If you do not have one of these synths, say 'N' to this option. + +Default synthesizer for Speakup +CONFIG_SPEAKUP_DEFAULT + This option specifies which synthesizer Speakup should use by + default at boot time. + Valid values are: none, acntpc, acntsa, apolo, audptr, bns, decext, + dectlk dtlk, ltlk, spkout, txprt + + You can choose an alternatively compiled-in synthesizer at boot time + by using the speakup_synth kernel command line option, + I.E. speakup_synth=dtlk. + +Use Speakup keymap by default +CONFIG_SPEAKUP_KEYMAP + If this option is enabled, then a modified US keymap which includes + Speakup's screen review commands will be used by default. + +DoubleTalk driver for speakup. +CONFIG_SPEAKUP_DTLK + The DoubleTalk synthesizer is made by RC Systems. It is an internal + ISA card which uses no interrupts. Do not confuse this driver with + the standard DoubleTalk driver included in the kernel. + + If you don't have a DoubleTalk card say 'N' here. + +LiteTalk/DoubleTalk-LT driver for speakup. +CONFIG_SPEAKUP_LTLK + This driver is for the LiteTalk synthesizer made by MicroTalk or the + DoubleTalk-LT synthesizer made by RC Systems. These are serial + drivers for those external synths. + + If you don't have a LiteTalk or DoubleTalk-LT, say 'N' here. + +Speakout driver for speakup. +CONFIG_SPEAKUP_SPKOUT + This driver is for the Speakout external serial synthesizer made by + GW Micro. + + If you don't have a Speakout, say 'N' here. + +Accent PC driver for speakup. +CONFIG_SPEAKUP_ACNTPC + This driver is for the Accent PC internal synthesizer made by Aicom + Corp. + + If you Don't have an Accent PC, say 'N' here. + +Accent SA driver for speakup. +CONFIG_SPEAKUP_ACNTSA + This driver is for the Accent SA external synthesizer made by Aicom + Corp. + + If you Don't have an Accent SA, say 'N' here. + +Apollo II driver for speakup. +CONFIG_SPEAKUP_APOLO + This driver is for the Apollo II external synthesizer made + by Dolphin Computer Access limited. + + If you Don't have an Apollo II, say 'N' here. + +Audapter Speech System driver for speakup. +CONFIG_SPEAKUP_AUDPTR + This driver is for the Audapter external synthesizer made by + Personal Data System Inc. + + If you Don't have an Audapter, say 'N' here. + +Braille 'N Speak driver for speakup. +CONFIG_SPEAKUP_BNS + This driver is for the Braille 'N Speak external synthesizer made by + Blazie Engineering. + + If you Don't have a bns, say 'N' here. + +Dectalk Express driver for speakup. +CONFIG_SPEAKUP_DECTLK + This driver is for the Dectalk Express external synthesizer made by + Digital Equipment Corp. + + If you Don't have a Dectalk Express, say 'N' here. + +Dectalk External driver for speakup. +CONFIG_SPEAKUP_DECEXT + This driver is for the older Dectalk external synthesizer made by + Digital Equipment Corp. + + If you Don't have a Dectalk external, say 'N' here. + +Transport driver for speakup. +CONFIG_SPEAKUP_TXPRT + This driver is for the Artic Transport external synthesizer made by + Artic Technologies. + + If you Don't have a Transport, say 'N' here. + +Double Talk PC internal speech card support CONFIG_DTLK This driver is for the DoubleTalk PC, a speech synthesizer manufactured by RC Systems (). It is also @@ -17929,20 +18206,6 @@ computer, say `Y' here to support its built-in watchdog timer feature. See the help for CONFIG_WATCHDOG for discussion. -W83877F Watchdog Timer -CONFIG_W83877F_WDT - This is the driver for the hardware watchdog on the W83877F chipset - as used in EMACS PC-104 motherboards (and likely others). 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 . Most - people will say N. - ALi M7101 Watchdog Timer CONFIG_ALIM7101_WDT This is the driver for the hardware watchdog on the ALi M7101 PMU @@ -19581,16 +19844,6 @@ hardware debugging with a logic analyzer and need to see all traffic on the bus. -AU1000 serial console -CONFIG_AU1000_SERIAL_CONSOLE - If you have an Alchemy AU1000 processor (MIPS based) and you want - to use a console on a serial port, say Y. Otherwise, say N. - -AU1000 serial support -CONFIG_AU1000_UART - If you have an Alchemy AU1000 processor (MIPS based) and you want - to use serial ports, say Y. Otherwise, say N. - AU1000 ethernet controller on SGI MIPS system CONFIG_MIPS_AU1000_ENET If you have an Alchemy Semi AU1000 ethernet controller @@ -20494,11 +20747,37 @@ Bluetooth HCI DTL1 (PC Card) driver. This driver provides support for Bluetooth PCMCIA devices with Nokia DTL1 interface: - Nokia Bluetooth PC Card, Socketcom Bluetooth CF module + Nokia Bluetooth Card + Socket Bluetooth CF Card Say Y here to compile support for HCI DTL1 devices into the kernel or say M to compile it as module (dtl1_cs.o). +HCI BT3C (PC Card) device driver +CONFIG_BLUEZ_HCIBT3C + Bluetooth HCI BT3C (PC Card) driver. + This driver provides support for Bluetooth PCMCIA devices with + 3Com BT3C interface: + 3Com Bluetooth Card (3CRWB6096) + HP Bluetooth Card + + The HCI BT3C driver uses external firmware loader program provided in + the BlueFW package. For more information, see . + + Say Y here to compile support for HCI BT3C devices into the + kernel or say M to compile it as module (bt3c_cs.o). + +HCI BlueCard (PC Card) device driver +CONFIG_BLUEZ_HCIBLUECARD + Bluetooth HCI BlueCard (PC Card) driver. + This driver provides support for Bluetooth PCMCIA devices with + Anycom BlueCard interface: + Anycom Bluetooth PC Card + Anycom Bluetooth CF Card + + Say Y here to compile support for HCI BlueCard devices into the + kernel or say M to compile it as module (bluecard_cs.o). + # The following options are for Linux when running on the Hitachi # SuperH family of RISC microprocessors. @@ -20931,12 +21210,6 @@ Hades. This increases the SCSI transfer rates at least ten times compared to PIO transfers. -Sun3 NCR5380 OBIO SCSI -CONFIG_SUN3_SCSI - This option will enable support for the OBIO (onboard io) NCR5380 - SCSI controller found in the Sun 3/50 and 3/60. Note that this - driver does not provide support for VME SCSI boards. - Sun3x ESP SCSI CONFIG_SUN3X_ESP This option will enable support for the ESP SCSI controller found @@ -20990,11 +21263,6 @@ General Linux information on the Sun 3 series (now discontinued) is at . -Sun3x ESP SCSI driver -CONFIG_SUN3X_ESP - The ESP was an on-board SCSI controller used on Sun 3/80 - machines. Say Y here to compile in support for it. - PCMCIA NE2000 and compatibles support CONFIG_APNE If you have a PCMCIA NE2000 compatible adapter, say Y. Otherwise, @@ -21005,19 +21273,6 @@ want). The module is called apne.o. If you want to compile it as a module, say M here and read . -Sun3/Sun3x on-board LANCE support -CONFIG_SUN3LANCE - This driver enables support for the on-board LANCE ethernet adapter - found on the Sun 3/50, 3/60, and 3/80 workstations. If you have - one of these workstations, and would like Ethernet, say Y. - Otherwise, say N. - -Sun3 on-board Intel 82586 support -CONFIG_SUN3_82586 - This driver enables support for the on-board Intel 82586 based Ethernet - adapter found on Sun 3/1xx and 3/2xx motherboards. Note that this driver - does not support 82586-based adapters on additional VME boards. - Atari Lance support CONFIG_ATARILANCE Say Y to include support for several Atari Ethernet adapters based @@ -24526,15 +24781,6 @@ the IA32 instruction set. Say Y here to build in kernel support for this. If in doubt, say Y. -/proc/efi/vars support -CONFIG_EFI_VARS - If you say Y here, you are able to get EFI (Extensible Firmware - Interface) variable information in /proc/efi/vars. You may read, - write, create, and destroy EFI variables through this interface. - - To use this option, you have to check that the "/proc file system - support" (CONFIG_PROC_FS) is enabled, too. - Physical memory granularity (16 MB) CONFIG_IA64_GRANULE_16MB IA64 identity-mapped regions use a large page size. We'll call such @@ -24631,6 +24877,14 @@ of the BUG call as well as the EIP and oops trace. This aids debugging but costs about 70-100K of memory. +Morse code panics +CONFIG_PANIC_MORSE + Say Y here to receive panic messages in morse code on your keyboard LEDs, and + optionally the PC speaker, if available. + The kernel param "panicblink" controls this feature, set it to 0 to disable, + 1 for LEDs only, 2 for pc speaker, or 3 for both. If you disable this option, + then you will receive a steady blink on the LEDs instead. + Include kgdb kernel debugger CONFIG_KGDB Include in-kernel hooks for kgdb, the Linux kernel source level @@ -24664,9 +24918,11 @@ U2/Uturn I/O MMU CONFIG_IOMMU_CCIO - Say Y here to enable DMA management routines for the first - generation of PA-RISC cache-coherent machines. Programs the - U2/Uturn chip in "Virtual Mode" and use the I/O MMU. + The U2/UTurn is a bus converter with io mmu present in the Cxxx, D, + J, K, and R class machines. Compiling this driver into the kernel will + not hurt anything, removing it will reduce your kernel by about 14k. + + If unsure, say Y. LBA/Elroy PCI support CONFIG_PCI_LBA diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/Documentation/filesystems/00-INDEX linux.19rc3-ac4/Documentation/filesystems/00-INDEX --- linux.19rc3/Documentation/filesystems/00-INDEX 2002-07-29 12:50:07.000000000 +0100 +++ linux.19rc3-ac4/Documentation/filesystems/00-INDEX 2002-07-29 13:58:35.000000000 +0100 @@ -6,6 +6,8 @@ - info and mount options for the Acorn Advanced Disc Filing System. affs.txt - info and mount options for the Amiga Fast File System. +befs.txt + - info for the BeOS file system (BFS) bfs.txt - info for the SCO UnixWare Boot Filesystem (BFS). coda.txt @@ -22,6 +24,8 @@ - info and mount options for the OS/2 HPFS. isofs.txt - info and mount options for the ISO 9660 (CDROM) filesystem. +jfs.txt + - info and mount options for the JFS filesystem. ncpfs.txt - info on Novell Netware(tm) filesystem using NCP protocol. ntfs.txt diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/Documentation/filesystems/befs.txt linux.19rc3-ac4/Documentation/filesystems/befs.txt --- linux.19rc3/Documentation/filesystems/befs.txt 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/Documentation/filesystems/befs.txt 2002-07-29 13:58:35.000000000 +0100 @@ -0,0 +1,111 @@ +BeOS filesystem for Linux + +Document last updated: Dec 6, 2001 + +WARNING +======= +Make sure you understand that this is alpha software. This means that the +implementation is neither complete nor well-tested. + +I DISCLAIM ALL RESPONSIBILTY FOR ANY POSSIBLE BAD EFFECTS OF THIS CODE! + +LICENSE +===== +This software is covered by the GNU General Public License. +See the file COPYING for the complete text of the license. +Or the GNU website: + +AUTHOR +===== +Current maintainer: Will Dyson +Has been working on the code since Aug 13, 2001. See the changelog for details. + +Original Author: Makoto Kato +His orriginal code can still be found at: +Does anyone know of a more current email address for Makoto? He doesn't respond +to the address given above... + +WHAT IS THIS DRIVER? +================== +This module implements the native filesystem of BeOS +for the linux 2.4.1 and later kernels. Currently it is a read-only implementation. + +Which is it, BFS or BEFS? +================ +Be, Inc said, "BeOS Filesystem is officially called BFS, not BeFS". +But Unixware Boot Filesystem is called bfs, too. And they are already in the +kernel. +Because of this nameing conflict, on Linux the BeOS filesystem is called befs. + +HOW TO INSTALL +============== +step 1. Install the BeFS patch into the source code tree of linux. + +Apply the patchfile to your kernel source tree. +Assuming that your kernel source is in /foo/bar/linux and the patchfile is called +patch-befs-xxx, you would do the following: + + cd /foo/bar/linux + patch -p1 < /path/to/patch-befs-xxx + +if the patching step fails (i.e. there are rejected hunks), you can try to +figure it out yourself (it shouldn't be hard), or mail the maintainer +(Will Dyson ) for help. + +step 2. Configuretion & make kernel + +The linux kernel has many compile-time options. Most of them are beyond the +scope of this document. I suggest the Kernel-HOWTO document as a good general +reference on this topic. + +However, to use the BeFS module, you must enable it at configure time. + + cd /foo/bar/linux + make menuconfig (or xconfig) + +The BeFS module is not a standard part of the linux kernel, so you must first +enable support for experimental code under the "Code maturity level" menu. + +Then, under the "Filesystems" menu will be an option called "BeFS filesystem (experimental)", +or something like that. Enable that option (it is fine to make it a module). + +Save your kernel configuration and then build your kernel. + +step 3. Install + +See the kernel howto for +instructions on this critical step. + +USING BFS +========= +To use the BeOS filesystem, use filesystem type 'befs'. + +ex) + mount -t befs /dev/fd0 /beos + +MOUNT OPTIONS +============= +uid=nnn All files in the partition will be owned by user id nnn. +gid=nnn All files in the partition will be in group nnn. +iocharset=xxx Use xxx as the name of the NLS translation table. +debug The driver will output debugging information to the syslog. + +HOW TO GET LASTEST VERSION +========================== + +The latest version is currently available at: + + +ANY KNOWN BUGS? +=========== +As of Jan 20, 2002: + + None + +SPECIAL THANKS +============== +Dominic Giampalo ... Writing "Practical file system design with Be filesystem" +Hiroyuki Yamada ... Testing LinuxPPC. + + + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/Documentation/filesystems/changelog.jfs linux.19rc3-ac4/Documentation/filesystems/changelog.jfs --- linux.19rc3/Documentation/filesystems/changelog.jfs 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/Documentation/filesystems/changelog.jfs 2002-07-29 13:58:35.000000000 +0100 @@ -0,0 +1,191 @@ +IBM's Journaled File System (JFS) for Linux version 1.0.14 +Team members +Steve Best sbest@us.ibm.com +Dave Kleikamp shaggy@austin.ibm.com +Barry Arndt barndt@us.ibm.com +Christoph Hellwig hch@caldera.de + + +Release January 28, 2002 (version 1.0.14) + +This is our fifty-second release of IBM's Enterprise JFS technology port to Linux. +Beta 1 was release 0.1.0 on 12/8/2000, Beta 2 was release 0.2.0 on 3/7/2001, +Beta 3 was release 0.3.0 on 4/30/2001, and release 1.0.0 on 6/28/2001. + +Function and Fixes in drop 52 (1.0.14) + - Fix hang in invalidate_metapages when jfs.o is built as a module + - Fix anon_list removal logic in txLock + +Function and Fixes in drop 51 (1.0.13) + - chmod changes on newly created directories are lost after umount (bug 2535) + - Page locking race fixes + - Improve metapage locking + - Fix timing window. Lock page while metapage is active to avoid page going + away before the metadata is released. (Fixed crash during mount/umount testing) + - Make changes for 2.5.2 kernel + - Fix race condition truncating large files + +Function and Fixes in drop50 (1.0.12) + - Add O_DIRECT support + - Add support for 2.4.17 kernel + - Make sure COMMIT_STALE gets reset before the inode is unlocked. Fixing + this gets rid of XT_GETPAGE errors + - Remove invalid __exit keyword from metapage_exit and txExit. + - fix assert(log->cqueue.head == NULL by waiting longer + +Function and Fixes in drop49 (1.0.11) + - Readdir was not handling multibyte codepages correctly. + - Make mount option parsing more robust. + - Add iocharset mount option. + - Journalling of symlinks incorrect, resulting in logredo failure of -265. + - Add jfsutils information to Changes file + - Improve recoverability of the file system when metadata corruption is detected. + - Fix kernel OOPS when root inode is corrupted + +Function and Fixes in drop48 (1.0.10) + - put inodes later on hash queues + - Fix boundary case in xtTruncate + - When invalidating metadata, try to flush the dirty buffers rather than sync them. + - Add another sanity check to avoid trapping when imap is corrupt + - Fix file truncate while removing large file (assert(cmp == 0)) + - read_cache_page returns ERR_PTR, not NULL on error + - Add dtSearchNode and dtRelocate + - JFS needs to use generic_file_open & generic_file_llseek + - Remove lazyQwait, etc. It created an unnecessary bottleneck in TxBegin. + +Function and Fixes in drop47 (1.0.9) + - Fix data corruption problem when creating files while deleting others. (jitterbug 183) + - Make sure all metadata is written before finalizing the log + - Fix serialization problem in shutdown by setting i_size of directory sooner. (bugzilla #334) + - JFS should quit whining when special files are marked dirty during read-only mount. + - Must always check rc after DT_GETPAGE + - Add diExtendFS + - Removing defconfig form JFS source - not really needed + +Function and Fixes in drop46 (1.0.8) + - Synclist was being built backwards causing logredo to quit too early + - jfs_compat.h needs to include module.h + - uncomment EXPORTS_NO_SYMBOLS in super.c + - Minor code cleanup + - xtree of zero-truncated file not being logged + - Fix logging on file truncate + - remove unused metapage fields + +Function and Fixes in drop45 (1.0.7) + - cleanup remove IS_KIOBUFIO define. + - cleanup remove TRUNC_NO_TOSS define. + - have jFYI's use the name directly from dentry + - Remove nul _ALLOC and _FREE macros and also make spinlocks static. + - cleanup add externs where needed in the header files + - jfs_write_inode is a bad place to call iput. Also limit warnings. + - More truncate cleanup + - Truncate cleanup + - Add missing statics in jfs_metapage.c + - fsync fixes + - Clean up symlink code - use page_symlink_inode_operations + - unicode handling cleanup + - cleanup replace UniChar with wchar_t + - Get rid of CDLL_* macros - use list.h instead + - 2.4.11-prex mount problem Call new_inode instead of get_empty_inode + - use kernel min/max macros + - Add MODULE_LICENSE stub for older kernels + - IA64/gcc3 fixes + - Log Manager fixes, introduce __SLEEP_COND macro + - Mark superblock dirty when some errors detected (forcing fsck to be run). + - More robust remounting from r/o to r/w. + - Misc. cleanup add static where appropriate + - small cleanup in jfs_umount_rw + - add MODULE_ stuff + - Set *dropped_lock in alloc_metapage + - Get rid of unused log list + - cleanup jfs_imap.c to remove _OLD_STUFF and _NO_MORE_MOUNT_INODE defines + - Log manager cleanup + - Transaction manager cleanup + - correct memory allocations flags + - Better handling of iterative truncation + - Change continue to break, otherwise we don't re-acquire LAZY_LOCK + +Function and Fixes in drop44 (1.0.6) + - Create jfs_incore.h which merges linux/jfs_fs.h, linux/jfs_fs_i.h, and jfs_fs_sb.h + - Create a configuration option to handle JFS_DEBUG define + - Fixed a few cases where positive error codes were returned to the VFS. + - Replace jfs_dir_read by generic_read_dir. + - jfs_fsync_inode is only called by jfs_fsync_file, merge the two and rename to jfs_fsync. + - Add a bunch of missing externs. + - jfs_rwlock_lock is unused, nuke it. + - Always use atomic set/test_bit operations to protect jfs_ip->cflag + - Combine jfs_ip->flag with jfs_ip->cflag + - Fixed minor format errors reported by fsck + - cflags should be long so bitops always works correctly + - Use GFP_NOFS for runtime memory allocations + - Support VM changes in 2.4.10 of the kernel + - Remove ifdefs supporting older 2.4 kernels. JFS now requires at least 2.4.3 or 2.4.2-ac2 + - Simplify and remove one use of IWRITE_TRYLOCK + - jfs_truncate was not passing tid to xtTruncate + - removed obsolete extent_page workaround + - correct recovery from failed diAlloc call (disk full) + - In write_metapage, don't call commit_write if prepare_write failed + +Function and Fixes in drop43 (1.0.5) + - Allow separate allocation of JFS-private superblock/inode data. + - Remove checks in namei.c that are already done by the VFS. + - Remove redundant mutex defines. + - Replace all occurrences of #include with #include + - Work around race condition in remount -fixes OOPS during shutdown + - Truncate large files incrementally ( affects directories too) + +Function and Fixes in drop42 (1.0.4) + - Fixed compiler warnings in the FS when building on 64 bits systems + - Fixed deadlock where jfsCommit hung in hold_metapage + - Fixed problems with remount + - Reserve metapages for jfsCommit thread + - Get rid of buggy invalidate_metapage & use discard_metapage + - Don't hand metapages to jfsIOthread (too many context switches) (jitterbug 125, bugzilla 238) + - Fix error message in jfs_strtoUCS + +Function and Fixes in drop41 (1.0.3) + - Patch to move from previous release to latest release needs to update the version number in super.c + - Jitterbug problems (134,140,152) removing files have been fixed + - Set rc=ENOSPC if ialloc fails in jfs_create and jfs_mkdir + - Fixed jfs_txnmgr.c 775! assert + - Fixed jfs_txnmgr.c 884! assert(mp->nohomeok==0) + - Fix hang - prevent tblocks from being exhausted + - Fix oops trying to mount reiserfs + - Fail more gracefully in jfs_imap.c + - Print more information when char2uni fails + - Fix timing problem between Block map and metapage cache - jitterbug 139 + - Code Cleanup (removed many ifdef's, obsolete code, ran code through indent) Mostly 2.4 tree + - Split source tree (Now have a separate source tree for 2.2, 2.4, and jfsutils) + +Function and Fixes in drop40 (1.0.2) + - Fixed multiple truncate hang + - Fixed hang on unlink a file and sync happening at the same time + - Improved handling of kmalloc error conditions + - Fixed hang in blk_get_queue and SMP deadlock: bh_end_io call generic_make_request + (jitterbug 145 and 146) + - stbl was not set correctly set in dtDelete + - changed trap to printk in dbAllocAG to avoid system hang + +Function and Fixes in drop 39 (1.0.1) + - Fixed hang during copying files on 2.2.x series + - Fixed TxLock compile problem + - Fixed to correctly update the number of blocks for directories (this was causing the FS + to show fsck error after compiling mozilla). + - Fixed to prevent old data from being written to disk from the page cache. + +Function and Fixes in drop 38 (1.0.0) + - Fixed some general log problems + +Please send bugs, comments, cards and letters to linuxjfs@us.ibm.com. + +The JFS mailing list can be subscribed to by using the link labeled "Mail list Subscribe" +at our web page http://oss.software.ibm.com/jfs/. + + + + + + + + + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/Documentation/filesystems/jfs.txt linux.19rc3-ac4/Documentation/filesystems/jfs.txt --- linux.19rc3/Documentation/filesystems/jfs.txt 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/Documentation/filesystems/jfs.txt 2002-07-29 13:58:35.000000000 +0100 @@ -0,0 +1,136 @@ +IBM's Journaled File System (JFS) for Linux version 1.0.14 +Team members +Steve Best sbest@us.ibm.com +Dave Kleikamp shaggy@austin.ibm.com +Barry Arndt barndt@us.ibm.com +Christoph Hellwig hch@caldera.de + + +Release January 28, 2002 (version 1.0.14) + +This is our fifty-second release of IBM's Enterprise JFS technology port to Linux. +Beta 1 was release 0.1.0 on 12/8/2000, Beta 2 was release 0.2.0 on 3/7/2001, +Beta 3 was release 0.3.0 on 4/30/2001, and release 1.0.0 on 6/28/2001. + +The changelog.jfs file contains detailed information of changes done in each source +code drop. + +JFS has a source tree that can be built on 2.4.3 - 2.4.17 and 2.5.2 kernel.org +source trees. + +Our current goal on the 2.5.x series of the kernel is to update to the latest +2.5.x version and only support the latest version of this kernel. +This will change when the distros start shipping the 2.5.x series of the kernel. + +Our current goal on the 2.4.x series of the kernel is to continue to support +all of the kernels in this series as we do today. + +There is a anonymous cvs access available for the JFS tree. The steps below are +what is needed to pull the JFS cvs tree from the oss.software.ibm.com server. + +id anoncvs +password anoncvs + +To checkout 2.4.x series of the JFS files do the following: +CVSROOT should be set to :pserver:anoncvs@oss.software.ibm.com:/usr/cvs/jfs +cvs checkout linux24 + +To checkout 2.5.2 series of the JFS files do the following: +CVSROOT should be set to :pserver:anoncvs@oss.software.ibm.com:/usr/cvs/jfs +cvs checkout linux25 + +To checkout the JFS utilities do the following: +CVSROOT should be set to :pserver:anoncvs@oss.software.ibm.com:/usr/cvs/jfs +cvs checkout jfsutils + +The cvs tree contains the latest changes being done to JFS. To receive notification +of commits to the cvs tree, please send e-mail to linuxjfs@us.ibm.com stating that +you would like notifications sent to you. + +The jfs-2.4-1.0.14-patch.tar.gz is the easiest way to get the latest file system +source code on your system. There are also patch files that can move your jfs source +code from one release to another. If you have release 1.0.13 and would like to move +to release 1.0.14 the patch file named jfs-2.4-1_0_13-to-1_0_14-patch.gz will do that. + +The jfs-2.4-1.0.14-patch.tar.gz file contains a readme and patch files for different +levels of the 2.4 kernel. Please see the README in the jfs-2.4-1.0.14-patch.tar.gz +file for help on applying the two patch files. + + +The following files in the kernel source tree have been changed so JFS can be built. +The jfs-2.4-1.0.14.tar.gz source tar ball contains each of the files below with +the extension of the kernel level it is associated with. As an example, there are now +four Config.in files named Config.in-2.4.0, Config.in-2.4.5, Config.in-2.4.7 and +Config.in-2.4.17. + + +If you use the jfs-2.4-1.0.14.tar.gz to build JFS you must rename each of the +kernel files to the file names listed below. The standard kernel from www.kernel.org +is the source of the kernel files that are included in the jfs tar file. + + +In sub dir fs Config.in, Makefile +In sub dir fs/nls Config.in +In sub dir Documentation Configure.help, Changes +In sub dir Documentation/filesystems 00-INDEX +In sub dir linux MAINTAINERS + +Please backup the above files before the JFS tar file is added to the kernel source +tree. All JFS files are located in the include/linux/jfs or fs/jfs sub dirs. + +Our development team has used the Linux kernel levels 2.4.3 - 2.4.17 kernels +with gcc version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release) +for our port so far. A goal of the JFS team is to have JFS run on all architectures +that Linux supports, there is no architecture specific code in JFS. JFS has been run +on the following architectures (x86, PowerPC, Alpha, s/390, ARM) so far. + +To make JFS build, during the "make config" step of building the kernel answer y to +the Prompt for development and/or incomplete code/drivers in the Code maturity level +options section. In the Filesystems section use the m for the answer to +JFS filesystem support (experimental) (CONFIG_JFS_FS) [Y/m/n?] + + +Build in /usr/src/linux with the command: + + +make modules +make modules_install + +If you rebuild jfs.o after having mounted and unmounted a partition, "modprobe -r jfs" +will unload the old module. + +For the file system debugging messages are being written to /var/log/messages. + +Please see the readme in the utilities package for information about building +the JFS utilities. + +JFS TODO list: + +Plans for our near term development items + + - get defrag capabilities operational in the FS + - get extendfs capabilities operational in the FS + - test EXTENDFS utility, for growing JFS partitions + - test defrag utility, calls file system to defrag the file system. + - add support for block sizes (512,1024,2048) + - add support for logfile on dedicated partition + + +Longer term work items + + - get access control list functionality operational + - get extended attributes functionality operational + - add quota support + +Please send bugs, comments, cards and letters to linuxjfs@us.ibm.com. + +The JFS mailing list can be subscribed to by using the link labeled "Mail list Subscribe" +at our web page http://oss.software.ibm.com/jfs/. + + + + + + + + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/Documentation/filesystems/proc.txt linux.19rc3-ac4/Documentation/filesystems/proc.txt --- linux.19rc3/Documentation/filesystems/proc.txt 2002-07-29 12:50:07.000000000 +0100 +++ linux.19rc3-ac4/Documentation/filesystems/proc.txt 2002-07-29 15:05:38.000000000 +0100 @@ -708,36 +708,26 @@ used ones is far behind, you've encountered a peak in your usage of file handles and you don't need to increase the maximum. -inode-state, inode-nr and inode-max ------------------------------------ - -As with file handles, the kernel allocates the inode structures dynamically, -but can't free them yet. - -The value in inode-max denotes the maximum number of inode handlers. This -value should be 3 to 4 times larger than the value in file-max, since stdin, -stdout, and network sockets also need an inode struct to handle them. If you -regularly run out of inodes, you should increase this value. +inode-state and inode-nr +------------------------ The file inode-nr contains the first two items from inode-state, so we'll skip to that file... -inode-state contains three actual numbers and four dummy values. The numbers -are nr_inodes, nr_free_inodes, and preshrink (in order of appearance). +inode-state contains two actual numbers and five dummy values. The numbers +are nr_inodes and nr_free_inodes (in order of appearance). nr_inodes ~~~~~~~~~ -Denotes the number of inodes the system has allocated. This can be slightly -more than inode-max because Linux allocates them one pageful at a time. +Denotes the number of inodes the system has allocated. This number will +grow and shrink dynamically. nr_free_inodes -------------- -Represents the number of free inodes and preshrink is nonzero when nr_inodes -is greater than inode-max and the system needs to prune the inode list instead -of allocating more. - +Represents the number of free inodes. Ie. The number of inuse inodes is +(nr_inodes - nr_free_inodes). super-nr and super-max ---------------------- diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/Documentation/filesystems/ramfs.txt linux.19rc3-ac4/Documentation/filesystems/ramfs.txt --- linux.19rc3/Documentation/filesystems/ramfs.txt 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/Documentation/filesystems/ramfs.txt 2002-07-29 13:58:35.000000000 +0100 @@ -0,0 +1,47 @@ + ramfs - An automatically resizing memory based filesystem + + + Ramfs is a file system which keeps all files in RAM. It allows read + and write access. In contrast to RAM disks, which get allocated a + fixed amount of RAM, ramfs grows and shrinks to accommodate the + files it contains. + + You can mount the ramfs with: + mount -t ramfs none /mnt/wherever + + Then just create and use files. When the filesystem is unmounted, all + its contents are lost. + + NOTE! This filesystem is probably most useful not as a real + filesystem, but as an example of how virtual filesystems can be + written. + +Resource limits: + +By default a ramfs will be limited to using half of (physical) memory +for storing file contents, a bit over that when the metadata is +included. The resource usage limits of ramfs can be controlled with +the following mount options: + + maxsize=NNN + Sets the maximum allowed memory usage of the +filesystem to NNN kilobytes. This will be rounded down to a multiple +of the page size. The default is half of physical memory. NB. unlike +most of the other limits, setting this to zero does *not* mean no +limit, but will actually limit the size of the filesystem data to zero +pages. There might be a use for this in some perverse situation. + + maxfilesize=NNN + Sets the maximum size of a single file on the +filesystem to NNN kilobytes. This will be rounded down to a multiple +of the page size. If NNN=0 there is no limit. The default is no limit. + + maxdentries=NNN + Sets the maximum number of directory entries (hard +links) on the filesystem to NNN. If NNN=0 there is no limit. By +default this is set to maxsize/4. + + maxinodes=NNN + Sets the maximum number of inodes (i.e. distinct +files) on the filesystem to NNN. If NNN=0 there is no limit. The +default is no limit (but there can never be more inodes than dentries). diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/Documentation/initrd.txt linux.19rc3-ac4/Documentation/initrd.txt --- linux.19rc3/Documentation/initrd.txt 2002-07-29 12:50:07.000000000 +0100 +++ linux.19rc3-ac4/Documentation/initrd.txt 2002-07-29 13:58:35.000000000 +0100 @@ -115,8 +115,12 @@ 1) make sure loopback block devices are configured into the kernel 2) create an empty file system of the appropriate size, e.g. # dd if=/dev/zero of=initrd bs=300k count=1 - # mke2fs -F -m0 initrd + # mke2fs -F -m0 -b 1024 initrd (if space is critical, you may want to use the Minix FS instead of Ext2) + (Note that due to a problem elsewhere in the kernel, you _must_ use a + 1024-byte blocksize when creating your file system. If any other + value is used, the kernel will be unable to mount the initrd at boot + time, causing a kernel panic.) 3) mount the file system, e.g. # mount -t ext2 -o loop initrd /mnt 4) create the console device (not necessary if using devfs, but it can't diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/Documentation/isapnp.txt linux.19rc3-ac4/Documentation/isapnp.txt --- linux.19rc3/Documentation/isapnp.txt 2002-07-29 12:50:07.000000000 +0100 +++ linux.19rc3-ac4/Documentation/isapnp.txt 2002-07-29 13:58:35.000000000 +0100 @@ -29,6 +29,7 @@ poke - poke configuration byte to selected register pokew - poke configuration word to selected register poked - poke configuration dword to selected register +allow_dma0 - allow dma channel 0 during auto activation: 0=off, 1=on Explanation: - variable begins with zero diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/Documentation/parisc/00-INDEX linux.19rc3-ac4/Documentation/parisc/00-INDEX --- linux.19rc3/Documentation/parisc/00-INDEX 2002-07-29 12:50:07.000000000 +0100 +++ linux.19rc3-ac4/Documentation/parisc/00-INDEX 2002-07-29 13:58:35.000000000 +0100 @@ -1,10 +1,10 @@ 00-INDEX - this file. IODC.txt - - Documentation IODC + - Documentation for IODC debugging - some debugging hints for real-mode code -mm - - Documentation on parisc mm status +unwritten + - list of unwritten / incomplete functions registers - current/planned usage of registers diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/Documentation/parisc/registers linux.19rc3-ac4/Documentation/parisc/registers --- linux.19rc3/Documentation/parisc/registers 2002-07-29 12:50:07.000000000 +0100 +++ linux.19rc3-ac4/Documentation/parisc/registers 2002-07-29 13:58:35.000000000 +0100 @@ -25,8 +25,8 @@ CR27 (TR 3) Thread descriptor pointer CR28 (TR 4) not used CR29 (TR 5) not used -CR30 (TR 6) current / 0 -CR31 (TR 7) Temporary register, used in various places +CR30 (TR 6) current +CR31 (TR 7) interrupt stack base Space Registers (kernel mode) diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/Documentation/sched-coding.txt linux.19rc3-ac4/Documentation/sched-coding.txt --- linux.19rc3/Documentation/sched-coding.txt 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/Documentation/sched-coding.txt 2002-07-29 13:58:35.000000000 +0100 @@ -0,0 +1,126 @@ + Reference for various scheduler-related methods in the O(1) scheduler + Robert Love , MontaVista Software + + +Note most of these methods are local to kernel/sched.c - this is by design. +The scheduler is meant to be self-contained and abstracted away. This document +is primarily for understanding the scheduler, not interfacing to it. Some of +the discussed interfaces, however, are general process/scheduling methods. +They are typically defined in include/linux/sched.h. + + +Main Scheduling Methods +----------------------- + +void load_balance(runqueue_t *this_rq, int idle) + Attempts to pull tasks from one cpu to another to balance cpu usage, + if needed. This method is called explicitly if the runqueues are + inbalanced or periodically by the timer tick. Prior to calling, + the current runqueue must be locked and interrupts disabled. + +void schedule() + The main scheduling function. Upon return, the highest priority + process will be active. + + +Locking +------- + +Each runqueue has its own lock, rq->lock. When multiple runqueues need +to be locked, lock acquires must be ordered by ascending &runqueue value. + +A specific runqueue is locked via + + task_rq_lock(task_t pid, unsigned long *flags) + +which disables preemption, disables interrupts, and locks the runqueue pid is +running on. Likewise, + + task_rq_unlock(task_t pid, unsigned long *flags) + +unlocks the runqueue pid is running on, restores interrupts to their previous +state, and reenables preemption. + +The routines + + double_rq_lock(runqueue_t *rq1, runqueue_t *rq2) + +and + + double_rq_unlock(runqueue_t *rq1, runqueue_t rq2) + +safely lock and unlock, respectively, the two specified runqueues. They do +not, however, disable and restore interrupts. Users are required to do so +manually before and after calls. + + +Values +------ + +MAX_PRIO + The maximum priority of the system, stored in the task as task->prio. + Lower priorities are higher. Normal (non-RT) priorities range from + MAX_RT_PRIO to (MAX_PRIO - 1). +MAX_RT_PRIO + The maximum real-time priority of the system. Valid RT priorities + range from 0 to (MAX_RT_PRIO - 1). +MAX_USER_RT_PRIO + The maximum real-time priority that is exported to user-space. Should + always be equal to or less than MAX_RT_PRIO. Setting it less allows + kernel threads to have higher priorities than any user-space task. +MIN_TIMESLICE +MAX_TIMESLICE + Respectively, the minimum and maximum timeslices (quanta) of a process. + +Data +---- + +struct runqueue + The main per-CPU runqueue data structure. +struct task_struct + The main per-process data structure. + + +General Methods +--------------- + +cpu_rq(cpu) + Returns the runqueue of the specified cpu. +this_rq() + Returns the runqueue of the current cpu. +task_rq(pid) + Returns the runqueue which holds the specified pid. +cpu_curr(cpu) + Returns the task currently running on the given cpu. +rt_task(pid) + Returns true if pid is real-time, false if not. + + +Process Control Methods +----------------------- + +void set_user_nice(task_t *p, long nice) + Sets the "nice" value of task p to the given value. +int setscheduler(pid_t pid, int policy, struct sched_param *param) + Sets the scheduling policy and parameters for the given pid. +void set_cpus_allowed(task_t *p, unsigned long new_mask) + Sets a given task's CPU affinity and migrates it to a proper cpu. + Callers must have a valid reference to the task and assure the + task not exit prematurely. No locks can be held during the call. +set_task_state(tsk, state_value) + Sets the given task's state to the given value. +set_current_state(state_value) + Sets the current task's state to the given value. +void set_tsk_need_resched(struct task_struct *tsk) + Sets need_resched in the given task. +void clear_tsk_need_resched(struct task_struct *tsk) + Clears need_resched in the given task. +void set_need_resched() + Sets need_resched in the current task. +void clear_need_resched() + Clears need_resched in the current task. +int need_resched() + Returns true if need_resched is set in the current task, false + otherwise. +yield() + Place the current process at the end of the runqueue and call schedule. diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/Documentation/sched-design.txt linux.19rc3-ac4/Documentation/sched-design.txt --- linux.19rc3/Documentation/sched-design.txt 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/Documentation/sched-design.txt 2002-07-29 13:58:35.000000000 +0100 @@ -0,0 +1,165 @@ + Goals, Design and Implementation of the + new ultra-scalable O(1) scheduler + + + This is an edited version of an email Ingo Molnar sent to + lkml on 4 Jan 2002. It describes the goals, design, and + implementation of Ingo's new ultra-scalable O(1) scheduler. + Last Updated: 18 April 2002. + + +Goal +==== + +The main goal of the new scheduler is to keep all the good things we know +and love about the current Linux scheduler: + + - good interactive performance even during high load: if the user + types or clicks then the system must react instantly and must execute + the user tasks smoothly, even during considerable background load. + + - good scheduling/wakeup performance with 1-2 runnable processes. + + - fairness: no process should stay without any timeslice for any + unreasonable amount of time. No process should get an unjustly high + amount of CPU time. + + - priorities: less important tasks can be started with lower priority, + more important tasks with higher priority. + + - SMP efficiency: no CPU should stay idle if there is work to do. + + - SMP affinity: processes which run on one CPU should stay affine to + that CPU. Processes should not bounce between CPUs too frequently. + + - plus additional scheduler features: RT scheduling, CPU binding. + +and the goal is also to add a few new things: + + - fully O(1) scheduling. Are you tired of the recalculation loop + blowing the L1 cache away every now and then? Do you think the goodness + loop is taking a bit too long to finish if there are lots of runnable + processes? This new scheduler takes no prisoners: wakeup(), schedule(), + the timer interrupt are all O(1) algorithms. There is no recalculation + loop. There is no goodness loop either. + + - 'perfect' SMP scalability. With the new scheduler there is no 'big' + runqueue_lock anymore - it's all per-CPU runqueues and locks - two + tasks on two separate CPUs can wake up, schedule and context-switch + completely in parallel, without any interlocking. All + scheduling-relevant data is structured for maximum scalability. + + - better SMP affinity. The old scheduler has a particular weakness that + causes the random bouncing of tasks between CPUs if/when higher + priority/interactive tasks, this was observed and reported by many + people. The reason is that the timeslice recalculation loop first needs + every currently running task to consume its timeslice. But when this + happens on eg. an 8-way system, then this property starves an + increasing number of CPUs from executing any process. Once the last + task that has a timeslice left has finished using up that timeslice, + the recalculation loop is triggered and other CPUs can start executing + tasks again - after having idled around for a number of timer ticks. + The more CPUs, the worse this effect. + + Furthermore, this same effect causes the bouncing effect as well: + whenever there is such a 'timeslice squeeze' of the global runqueue, + idle processors start executing tasks which are not affine to that CPU. + (because the affine tasks have finished off their timeslices already.) + + The new scheduler solves this problem by distributing timeslices on a + per-CPU basis, without having any global synchronization or + recalculation. + + - batch scheduling. A significant proportion of computing-intensive tasks + benefit from batch-scheduling, where timeslices are long and processes + are roundrobin scheduled. The new scheduler does such batch-scheduling + of the lowest priority tasks - so nice +19 jobs will get + 'batch-scheduled' automatically. With this scheduler, nice +19 jobs are + in essence SCHED_IDLE, from an interactiveness point of view. + + - handle extreme loads more smoothly, without breakdown and scheduling + storms. + + - O(1) RT scheduling. For those RT folks who are paranoid about the + O(nr_running) property of the goodness loop and the recalculation loop. + + - run fork()ed children before the parent. Andrea has pointed out the + advantages of this a few months ago, but patches for this feature + do not work with the old scheduler as well as they should, + because idle processes often steal the new child before the fork()ing + CPU gets to execute it. + + +Design +====== + +the core of the new scheduler are the following mechanizms: + + - *two*, priority-ordered 'priority arrays' per CPU. There is an 'active' + array and an 'expired' array. The active array contains all tasks that + are affine to this CPU and have timeslices left. The expired array + contains all tasks which have used up their timeslices - but this array + is kept sorted as well. The active and expired array is not accessed + directly, it's accessed through two pointers in the per-CPU runqueue + structure. If all active tasks are used up then we 'switch' the two + pointers and from now on the ready-to-go (former-) expired array is the + active array - and the empty active array serves as the new collector + for expired tasks. + + - there is a 64-bit bitmap cache for array indices. Finding the highest + priority task is thus a matter of two x86 BSFL bit-search instructions. + +the split-array solution enables us to have an arbitrary number of active +and expired tasks, and the recalculation of timeslices can be done +immediately when the timeslice expires. Because the arrays are always +access through the pointers in the runqueue, switching the two arrays can +be done very quickly. + +this is a hybride priority-list approach coupled with roundrobin +scheduling and the array-switch method of distributing timeslices. + + - there is a per-task 'load estimator'. + +one of the toughest things to get right is good interactive feel during +heavy system load. While playing with various scheduler variants i found +that the best interactive feel is achieved not by 'boosting' interactive +tasks, but by 'punishing' tasks that want to use more CPU time than there +is available. This method is also much easier to do in an O(1) fashion. + +to establish the actual 'load' the task contributes to the system, a +complex-looking but pretty accurate method is used: there is a 4-entry +'history' ringbuffer of the task's activities during the last 4 seconds. +This ringbuffer is operated without much overhead. The entries tell the +scheduler a pretty accurate load-history of the task: has it used up more +CPU time or less during the past N seconds. [the size '4' and the interval +of 4x 1 seconds was found by lots of experimentation - this part is +flexible and can be changed in both directions.] + +the penalty a task gets for generating more load than the CPU can handle +is a priority decrease - there is a maximum amount to this penalty +relative to their static priority, so even fully CPU-bound tasks will +observe each other's priorities, and will share the CPU accordingly. + +the SMP load-balancer can be extended/switched with additional parallel +computing and cache hierarchy concepts: NUMA scheduling, multi-core CPUs +can be supported easily by changing the load-balancer. Right now it's +tuned for my SMP systems. + +i skipped the prev->mm == next->mm advantage - no workload i know of shows +any sensitivity to this. It can be added back by sacrificing O(1) +schedule() [the current and one-lower priority list can be searched for a +that->mm == current->mm condition], but costs a fair number of cycles +during a number of important workloads, so i wanted to avoid this as much +as possible. + +- the SMP idle-task startup code was still racy and the new scheduler +triggered this. So i streamlined the idle-setup code a bit. We do not call +into schedule() before all processors have started up fully and all idle +threads are in place. + +- the patch also cleans up a number of aspects of sched.c - moves code +into other areas of the kernel where it's appropriate, and simplifies +certain code paths and data constructs. As a result, the new scheduler's +code is smaller than the old one. + + Ingo diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/Documentation/speakup/DefaultKeyAssignments linux.19rc3-ac4/Documentation/speakup/DefaultKeyAssignments --- linux.19rc3/Documentation/speakup/DefaultKeyAssignments 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/Documentation/speakup/DefaultKeyAssignments 2002-07-29 13:58:35.000000000 +0100 @@ -0,0 +1,45 @@ +This file is intended to give you an overview of the default keys used +by speakup for it's review functions. You may change them to be +anything you want but that will take some familiarity with key +mapping. + +We have remapped the insert or zero key on the keypad to act as a +shift key. Well, actually as an altgr key. So in the following list +InsKeyPad-period means hold down the insert key like a shift key and +hit the keypad period. + +KeyPad-8 Say current Line +InsKeyPad-8 say from top of screen to reading cursor. +KeyPad-7 Say Previous Line (UP one line) +KeyPad-9 Say Next Line (down one line) +KeyPad-5 Say Current Word +InsKeyPad-5 Spell Current Word +KeyPad-4 Say Previous Word (left one word) +InsKeyPad-4 say from left edge of line to reading cursor. +KeyPad-6 Say Next Word (right one word) +InsKeyPad-6 Say from reading cursor to right edge of line. +KeyPad-2 Say Current Letter +InsKeyPad-2 say current letter phonetically +KeyPad-1 Say Previous Character (left one letter) +KeyPad-3 Say Next Character (right one letter) +KeyPad-plus Say Entire Screen +InsKeyPad-plus Say from reading cursor line to bottom of screen. +KeyPad-Minus Park reading cursor (toggle) +InsKeyPad-minus Say character hex and decimal value. +KeyPad-period Say Position (current line, position and console) +InsKeyPad-period say colour attributes of current position. +InsKeyPad-9 Move reading cursor to top of screen (insert pgup) +InsKeyPad-3 Move reading cursor to bottom of screen (insert pgdn) +InsKeyPad-7 Move reading cursor to left edge of screen (insert home) +InsKeyPad-1 Move reading cursor to right edge of screen (insert end) +KeyPad-Enter Shut Up (until another key is hit) and sync reading cursor +InsKeyPad-Enter Shut Up (until toggled back on) and sync cursors +InsKeyPad-star n go to line (y) or column (x). Where 'n' is any + allowed value for the row or column for your current screen. +KeyPad-/ Mark and Cut screen region. +InsKeyPad-/ Paste screen region into any console. + +Hitting any key while speakup is outputting speech will quiet the +synth until it has caught up with what is being printed on the +console. + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/Documentation/speakup/INSTALLATION linux.19rc3-ac4/Documentation/speakup/INSTALLATION --- linux.19rc3/Documentation/speakup/INSTALLATION 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/Documentation/speakup/INSTALLATION 2002-07-29 13:58:35.000000000 +0100 @@ -0,0 +1,108 @@ +This document assumes you have had some experience with kernel +compilation and installation. If you have not, I recommend you get +the kernel source and read the README and various documents in the +linux/Documentation directory. In particular the Changes file to make +sure you have the appropriate utilities needed for installing a 2.2.xx +or 2.4xx kernel. It isn't as difficult as you might think. The +kernel README is intimidating the first time but once you get the +steps down, it's really pretty easy. Getting through the "make +config" is the tedious bit. + +The first thing to do is to place a copy of the tarball in the /usr/src +directory which is the directory the linux tree is located in as well. +Next untar speakup by typing: + +tar zxf speakup-1.00.tar.gz +cd speakup-1.00 +./install + +Note the dot-slash before the install. This will copy the speakup +directory to the kernel tree and apply the various patches and +components to the appropriate kernel files. Depending on how +experienced you are with kernel compiling and hacking will determine +whether you should bother looking at any failed patches. If this +happens, you should probably write to the speakup mailing list for +help or myself. + +If all of the patch hunks apply successfully then just continue with +the standard steps to compile the kernel with: + +make mrproper +make config + +When you get to the section console speech output, answer 'y' to the +CONFIG_SPEAKUP prompt. You will be given a submenu with the list of +synthesizers which are currently supported. You can include as many +synths in the kernel as you wish but remember each one takes up kernel +space. You can only choose one of the synths as the default or none, +so just type dtlk or whatever is the correct string for the +synthesizer you have. You will also be asked if you wish to build-in +a speakup key map. If you do not say 'y' to this option you will need +to load a speakup map at boot time with whichever mechanism your +distribution uses for loading key maps. + +We have placed the speakup configuration options in make config just +after the vga console choice. For the DoubleTalk PC driver included +by Jim Van Zandt. I recommend you say no to that option. I have not +tried configuring them both in, but I wouldn't be at all surprised if +it didn't work. + +If all goes well up to this point you can continue with the compiling +process by doing: + +make dep >dep.file 2>&1 & +make bzImage >cc.file 2>&1 & +make modules >mod.file 2>&1 & + +I always redirect output to the files dep.file and cc.file so I can +look over the compilation record to make sure there are no errors and +warnings. + +Okay, you are ready to install the newly compiled kernel. Make sure +you make an linux.old entry in your lilo.conf file so you can recover +if it blows up. next as root run "make modules_install" to install +whatever modules you compiled and move the bzImage from +/usr/src/linux/arch/i386/boot to wherever your kernel lives. Also +move the System.map from /usr/src/linux to where your System.map +lives. On our systems we use debian so we create an vmlinuz-speakup +and System.map-speakup in our /boot directory and set the symbolic +links vmlinuz and System.map in the root (/) directory to point to the +images. Now type lilo to tell lilo to build the new booter file and +install it. + +As of version 0.07, the keymap for speakup is automatically built in +at compile time. If you have other keymaps installed at boot time, +you might want to consider removing them before you reboot the system. + +If everything has gone OK up until now, cross your fingers and type: + +shutdown -r now + +Your system should start talking to you as soon as it starts booting. +It will talk and talk and ... well, you might want to hit the +keypad-enter key to tell it to shut up. You should also read the +DefaultKeyAssignments file to learn the various review functions +available. + +As of v-0.10 the speakup configuration options are in the +/proc/speakup subtree. The individual options should be fairly +obvious by their names such as rate, volume, punc_level and so forth. +You can manipulate them by cat'ing or echoing new values to them such +as: + +echo 9 >/proc/speakup/rate + +You can see what the current values are by cat'ing those files to the console: + +cat /proc/speakup/rate + +I have probably managed to overlook a whole whack of things because +this is the, enter version number here, draft. Don't worry we'll get +it right eventually. If you like the package you really should get on +the mailing list and start participating in it's development. + + Kirk + +email: kirk@braille.uwo.ca +phone: (519) 679-6845 (home) + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/Documentation/speakup/keymap-tutorial linux.19rc3-ac4/Documentation/speakup/keymap-tutorial --- linux.19rc3/Documentation/speakup/keymap-tutorial 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/Documentation/speakup/keymap-tutorial 2002-07-29 13:58:35.000000000 +0100 @@ -0,0 +1,140 @@ + Speakup Keymap Tutorial + +This is meant to be a basic tutorial on how to change the Linux keymap +file to assign speakup review functions to desired keys. It is not +intended to be a replacement for the loadkeys(8) or keymap(5) man +pages. + +The basic lay-out of the keymap file is a series of lines with the +following fields. The keyword keycode indicates this is the start of +a new key assignment. It is then followed by a number which +represents the actual key on the keyboard. That number is followed by +the equals '=' operator and finally a list of keywords representing +key names such as keypad5. Each line can have quite a few key +functions on it. They are interpreted by loadkeys in order and +assigned to key shift states depending on the order they are +encountered. So for example, the first value after the equals is the +keys unshifted state, while the second is the keys shifted state. If +you wish to learn the order they are interpreted in read the +loadkeys(8) and keymap(5) man pages. + +You can have subsequent lines which are indented and start with +another keyword for the various shifted states. This way you can +assign some of the states without having to specify them all in order +up until you get to the one you want to assign. + +In speakup, we have assigned the insert key on the number pad to the +altgr keyword. This is not required; you could choose any other +shifted state keyword. We used altgr because it typically represents +the right hand alt key. In Linux each shift key is separate and +independent, so the left shift and the right shift keys are not +necessarily the same. The altgr key is not really used for anything +important, so we steel it. + +Here are the default key assignments for the number eight on the +keypad: + +keycode 72 = KP_8 + alt keycode 72 = Ascii_8 + +As you can see, the first line starts with keycode followed by 72 +which is the actual number assigned to the key when the keyboard port +is read. The KP_8 after the equal sign, is the symbolic representation +of the function called when that key is hit. + +The second line is the same format except it starts with the keyword +alt which is indented. That means that the function at the end of +that line Ascii_8 is applied to the alt-shifted eight key. + +Now here are the speakup assignments for that key: + +keycode 72 = 0x0d0a + altgr keycode 72 = 0x0d20 +#keycode 72 = KP_8 + alt keycode 72 = Ascii_8 + +Notice that the only thing which has changed on the first line is the +function called when the key is struck. It is a hexadecimal number +identifying the function called in a look up table. It is not a +symbolic representation yet because that means we need to change the +loadkeys program to understand our symbolic names. We will do this in +the future but for now it is more expedient to just use the table +indices. You will find a table at the bottom of this document +listing the review functions and their corresponding hex lookups. + +The 0x0d0a in the first line above is speakup's say line function. +The second line ends with 0x0d20 which is speakup's read from top of +screen to reading cursor line. + +The third line is the original key assignment commented out with a +number-sign '#' at the beginning. I do that so I can easily find the +keys I want to affect by symbolic name. Otherwise I would need to +keep a look up table for all the keycodes. I recommend you do this as +well or you'll be very sorry at some point in the future. + +The forth line is just the standard key assignment for the left hand +alt key. + +Now let's say we want to design a different keyboard layout. I'll use +an example for the JAWS style keypad because I've specifically been +asked to help with that. JAWS uses the eight on the keypad to move up +a line or the speakup function to read previous line. JAWS also uses +the keypad_8 key in a shifted mode to read the current line. I +apologize if these are not quite right. It has been a long time since +I used JAWS. So we would have the following two lines: + +keycode 72 = 0x0d0b + altgr keycode 72 = 0x0d0a + +The hex value 0x0d0b in the first line is speakup's SAY_PREVIOUS_LINE +function. The 0x0d0a in the second line is the same say_line function +as we had earlier. So when the number eight is hit on the keypad +speakup will read the previous line and when the number eight is +shifted with the insert key on the keypad it will read the current +line. + +As you can tell, it is not really very difficult to reassign the keys +to different review functions. + +Once you have carefully edited the keymap file, called default.map in +the speakup distribution, you copy it into the /etc/kbd directory. +Make sure you back up the original default.map from that directory +first, if there is one. Then you run loadkeys to load the new map +into the kernel: + +loadkeys /etc/kbd/default.map + +If you wish to build your new keyboard lay-out into the kernel, after +testing it, copy the default.map file into the drivers/char directory, +with the name defkeymap.map, of your Linux source tree. Then rm the +defkeymap.c file and recompile the kernel. Because there is no +defkeymap.c `make' will rebuild it on the next compile. + +Here is a list of the available speakup review functions at this point +in time. + +SAY_CHAR 0x0d04 /* say this character */ +SAY_PREV_CHAR 0x0d05 /* say character left of this char */ +SAY_NEXT_CHAR 0x0d06 /* say char right of this char */ +SAY_WORD 0x0d07 /* say this word under reading cursor */ +SAY_PREV_WORD 0x0d08 +SAY_NEXT_WORD 0x0d09 +SAY_LINE 0x0d0a /* say this line */ +SAY_PREV_LINE 0x0d0b /* say line above this line */ +SAY_NEXT_LINE 0x0d0c +TOP_EDGE 0x0d0d /* move to top edge of screen */ +BOTTOM_EDGE 0x0d0e +LEFT_EDGE 0x0d0f +RIGHT_EDGE 0x0d10 +SAY_PHONETIC_CHAR 0x0d11 /* say this character phonetically */ +SPELL_WORD 0x0d12 /* spell this word letter by letter */ +SAY_SCREEN 0x0d14 +SAY_POSITION 0x0d1b +SPEECH_OFF 0x0d1c +SAY_ATTRIBUTES 0x0d1d +SPEAKUP_PARKED 0x0d1e +SAY_FROM_TOP 0x0d20 +SAY_TO_BOTTOM 0x0d21 +SAY_FROM_LEFT 0x0d22 +SAY_TO_RIGHT 0x0d23 + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/Documentation/speakup/README linux.19rc3-ac4/Documentation/speakup/README --- linux.19rc3/Documentation/speakup/README 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/Documentation/speakup/README 2002-07-29 13:58:35.000000000 +0100 @@ -0,0 +1,98 @@ +Welcome to the speakup project for the Speakup speech package for Linux. + +Speakup is written by Kirk Reiser and Andy Berdan. It is licensed +under the GPL. If you don't already know, the GPL stands for the GNU +General Public License. Which basically states that this code is free to +copy, modify and distribute to anyone interested in playing with it. +The one thing you may not do is turn any part of it into proprietary +or commercial code without the permission of the author. That's me. + +If you are interested in being involved with the development of speech +output for Linux you can subscribe to the Speakup mailing list by +sending a message to speakup-request@braille.uwo.ca with the line: subscribe. You can also subscribe by going to the speakup web page and following the links at http://www.linux-speakup.org. + +We are at a very early stage in the development of this package. +Hopefully changes will happen often and many. The current files in +this directory are: + +DefaultKeyAssignments # speakup's default review keys +INSTALLATION # for installing speakup from the tar ball. +README # this file +keymap-tutorial # a tutorial on how to layout the keyboard + +Read the INSTALLATION file to learn how to apply the patches and the +default.map for the keyboard. You should also read the Changes file. +It really has any new things I've added since last time. + +There is no documentation in any of these files to instruct you what +to do if something goes wrong with the patching or compilation. If +you would like that information you will need to subscribe to the +mailing list and ask for help, or write me kirk@braille.uwo.ca for +help. I suggest the mailing list because I will probably tire quickly +of answering the same questions over and over. You could always +decide to dig-in and take on the task, and write documentation to help +others. + +There also is a speakup reflector for the Speak Freely package, which +many of us hang out on and discuss all sorts of topics from speakup +problems to ALSA driver installation and just about anything else +you'd like to talk about. The reflector is at lwl.braille.uwo.ca:4074 +with it's lwl page at lwl.braille.uwo.ca/speakup.html. Come and join +us, it's fun! + +Acknowledgements: + +I am really very new at kernel hacking and screen review package +writing, so I have depended heavily on other folks kindness to help me +a long. No doubt I will continue to abuse them freely and others +before this is a really good speech solution for Linux. (Oh Well!, +somebody's got to do it.) + +Theodore Ts'o. He gave me a good discussion of unicode and UTF and +the like. He doesn't even remember writing me about it. + +Alan Cox. He has answered many questions about scheduling and wait +queues and timers along with code fragments and so on. I just wish I +understood it all totally. He has also helped immensely in moving +this package toward inclusion in the standard kernel tree. (Maybe next +release!) + +Martin Mares. He pointed me in the right direction to figuring out +the colour attributes and other useful tidbits. + +Paul McDermott. He really is the catalyst for me to actually get +this all working. Besides I like seeing him bounce around and get all +excited every time I have something new working. + +John Covici, He was the first person to actually attempt writing +another synthesizer driver for speakup. It was the Speakout driver so +it was also the first serial driver. + +Brian Borowski, he was the first person to actually write a speakup +function other than Andy and I. + +Jim Danley, he has more or less become my main man in helping test +code, add new features, bounce ideas off and generally become a good +friend. + +Matt Campbell, he basically rewrote the drivers to be able to include +all synths in the kernel at the same time. The distribution +maintainers appreciate him a lot as well. + +Gene Collins, he was very helpful debugging the current release prior +to its public showing. He has also worked hard educating others on +the list and writing the ALSA mini howto. + +I would also like to really thank the folks that handle the +distribution packages. I and many other people would not find access +to speakup nearly so convenient without their efforts. They include +Bill Acker, Tom Moore, Matt Campbell, Joe Norton and Joshua Lambert. + +There are probably many more I am forgetting right now. I guess I'll +just have to add you all later. + + +Happy Hacking! + + Kirk + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/Documentation/sysctl/vm.txt linux.19rc3-ac4/Documentation/sysctl/vm.txt --- linux.19rc3/Documentation/sysctl/vm.txt 2002-07-29 12:54:46.000000000 +0100 +++ linux.19rc3-ac4/Documentation/sysctl/vm.txt 2002-07-29 13:58:35.000000000 +0100 @@ -1,4 +1,4 @@ -Documentation for /proc/sys/vm/* kernel version 2.2.10 +Documentation for /proc/sys/vm/* kernel version 2.4.19 (c) 1998, 1999, Rik van Riel For general info and legal blurb, please look in README. @@ -6,7 +6,7 @@ ============================================================== This file contains the documentation for the sysctl files in -/proc/sys/vm and is valid for Linux kernel version 2.2. +/proc/sys/vm and is valid for Linux kernel version 2.4. The files in this directory can be used to tune the operation of the virtual memory (VM) subsystem of the Linux kernel, and @@ -34,26 +34,27 @@ This file controls the operation of the bdflush kernel daemon. The source code to this struct can be found in linux/fs/buffer.c. It currently contains 9 integer values, -of which 4 are actually used by the kernel. +of which 6 are actually used by the kernel. From linux/fs/buffer.c: -------------------------------------------------------------- union bdflush_param { struct { - int nfract; /* Percentage of buffer cache dirty to + int nfract; /* Percentage of buffer cache dirty to activate bdflush */ - int dummy1; /* old "ndirty" */ + int ndirty; /* Maximum number of dirty blocks to write out per + wake-cycle */ int dummy2; /* old "nrefill" */ int dummy3; /* unused */ int interval; /* jiffies delay between kupdate flushes */ - int age_buffer; /* Time for normal buffer to age */ - int nfract_sync;/* Percentage of buffer cache dirty to + int age_buffer; /* Time for normal buffer to age before we flush it */ + int nfract_sync;/* Percentage of buffer cache dirty to activate bdflush synchronously */ - int dummy4; /* unused */ + int nfract_stop_bdflush; /* Percentage of buffer cache dirty to stop bdflush */ int dummy5; /* unused */ } b_un; unsigned int data[N_PARAM]; -} bdf_prm = {{30, 64, 64, 256, 5*HZ, 30*HZ, 60, 0, 0}}; +} bdf_prm = {{30, 500, 0, 0, 5*HZ, 30*HZ, 60, 20, 0}}; -------------------------------------------------------------- int nfract: @@ -68,6 +69,13 @@ more frequent I/O operations. The default value is 30%, the minimum is 0%, and the maximum is 100%. +int ndirty: +The second parameter (ndirty) gives the maximum number of +dirty buffers that bdflush can write to the disk in one time. +A high value will mean delayed, bursty I/O, while a small +value can lead to memory shortage when bdflush isn't woken +up often enough. + int interval: The fifth parameter, interval, is the minimum rate at which kupdate will wake and flush. The value is expressed in @@ -88,7 +96,11 @@ synchronously. This can be viewed as the hard limit before bdflush forces buffers to disk. The default is 60%, the minimum is 0%, and the maximum is 100%. - + +int nfract_stop_bdflush: +The eighth parameter, nfract_stop_bdflush, governs the percentage +of buffer cache that is dirty which will stop bdflush. +The default is 20%, the miniumum is 0%, and the maxiumum is 100%. ============================================================== buffermem: diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/Documentation/video4linux/README.cpia linux.19rc3-ac4/Documentation/video4linux/README.cpia --- linux.19rc3/Documentation/video4linux/README.cpia 2002-07-29 12:50:07.000000000 +0100 +++ linux.19rc3-ac4/Documentation/video4linux/README.cpia 2002-07-29 13:58:35.000000000 +0100 @@ -1,8 +1,18 @@ -This is a driver for the CPiA PPC2 driven parallel connected -Camera. For example the Creative WebcamII is CPiA driven. +This is a driver for the CPiA PPC2 driven parallel connected or USB +Camera. For example the Creative WebcamII is CPiA driven. Also +various USB cameras, and the Intel Play QX3 microscope. ) [1]Peter Pregler, Linz 2000, published under the [2]GNU GPL + +NOTE ADDED (2002/05/23): +An improved version of the driver (cpia.c, cpia.h, cpia_usb.c, cpia_pp.c) +with extra features not yet integrated into the Official Linux Kernel versions +is available from http://sourceforge.net/projects/webcam as +cpia-2.2.1.tgz. This is a drop-in replacement for the driver in the kernel +sources, at least up to 2.4.18 kernels. The driver at sourceforge has been +stable for over a year, and is currently in low maintenance mode +(tracking kernel changes only). --------------------------------------------------------------------------- USAGE: diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/Documentation/vm/overcommit-accounting linux.19rc3-ac4/Documentation/vm/overcommit-accounting --- linux.19rc3/Documentation/vm/overcommit-accounting 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/Documentation/vm/overcommit-accounting 2002-07-29 13:58:35.000000000 +0100 @@ -0,0 +1,73 @@ +* This describes the overcommit management facility in the latest kernel + tree (FIXME: actually it also describes the stuff that isnt yet done) + +The Linux kernel supports four overcommit handling modes + +0 - Heuristic overcommit handling. Obvious overcommits of + address space are refused. Used for a typical system. It + ensures a seriously wild allocation fails while allowing + overcommit to reduce swap usage + +1 - No overcommit handling. Appropriate for some scientific + applications + +2 - (NEW) strict overcommit. The total address space commit + for the system is not permitted to exceed swap + half ram. + In almost all situations this means a process will not be + killed while accessing pages but only by malloc failures + that are reported back by the kernel mmap/brk code. + +3 - (NEW) paranoid overcommit The total address space commit + for the system is not permitted to exceed swap. The machine + will never kill a process accessing pages it has mapped + except due to a bug (ie report it!) + +Gotchas +------- + +The C language stack growth does an implicit mremap. If you want absolute +guarantees and run close to the edge you MUST mmap your stack for the +largest size you think you will need. For typical stack usage is does +not matter much but its a corner case if you really really care + +In modes 2 and 3 the MAP_NORESERVE flag is ignored. + + +How It Works +------------ + +The overcommit is based on the following rules + +For a file backed map + SHARED or READ only - 0 cost (the file is the map not swap) + + WRITABLE SHARED - size of mapping per instance + +For a direct map + SHARED or READ only - size of mapping + PRIVATE WRITEABLE - size of mapping per instance + +Additional accounting + Pages made writable copies by mmap + shmfs memory drawn from the same pool + +Status +------ + +o We account mmap memory mappings +o We account mprotect changes in commit +o We account mremap changes in size +o We account brk +o We account munmap +o We report the commit status in /proc +o Account and check on fork +o Review stack handling/building on exec +o SHMfs accounting +o Implement actual limit enforcement + +To Do +----- +o Account ptrace pages (this is hard) +o Disable MAP_NORESERVE in mode 2/3 +o Account for shared anonymous mappings properly + - right now we account them per instance diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/acpi/ospm/system/sm_osl.c linux.19rc3-ac4/drivers/acpi/ospm/system/sm_osl.c --- linux.19rc3/drivers/acpi/ospm/system/sm_osl.c 2002-07-29 12:50:04.000000000 +0100 +++ linux.19rc3-ac4/drivers/acpi/ospm/system/sm_osl.c 2002-07-29 13:58:38.000000000 +0100 @@ -685,6 +685,9 @@ */ if (state == ACPI_S2 || state == ACPI_S3) { #ifdef DONT_USE_UNTIL_LOWLEVEL_CODE_EXISTS + /* That && trick is *not going to work*. Read gcc + specs. That explicitely says: jumping from other + function is *not allowed*. */ wakeup_address = acpi_save_state_mem((unsigned long)&&acpi_sleep_done); if (!wakeup_address) goto acpi_sleep_done; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/atm/firestream.c linux.19rc3-ac4/drivers/atm/firestream.c --- linux.19rc3/drivers/atm/firestream.c 2002-07-29 12:50:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/atm/firestream.c 2002-07-29 18:02:45.000000000 +0100 @@ -330,8 +330,8 @@ #define FS_DEBUG_QSIZE 0x00001000 -#define func_enter() fs_dprintk (FS_DEBUG_FLOW, "fs: enter " __FUNCTION__ "\n") -#define func_exit() fs_dprintk (FS_DEBUG_FLOW, "fs: exit " __FUNCTION__ "\n") +#define func_enter() fs_dprintk (FS_DEBUG_FLOW, "fs: enter %s\n", __FUNCTION__) +#define func_exit() fs_dprintk (FS_DEBUG_FLOW, "fs: exit %s\n", __FUNCTION__) struct fs_dev *fs_boards = NULL; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/block/cpqarray.c linux.19rc3-ac4/drivers/block/cpqarray.c --- linux.19rc3/drivers/block/cpqarray.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/drivers/block/cpqarray.c 2002-07-29 13:58:39.000000000 +0100 @@ -1301,7 +1301,8 @@ if (error) return error; error = ida_ctlr_ioctl(ctlr, dsk, &my_io); if (error) return error; - error = copy_to_user(io, &my_io, sizeof(my_io)); + if(copy_to_user(io, &my_io, sizeof(my_io))) + return -EFAULT; return error; case IDAGETCTLRSIG: if (!arg) return -EINVAL; @@ -1416,7 +1417,11 @@ cmd_free(h, c, 0); return(error); } - copy_from_user(p, (void*)io->sg[0].addr, io->sg[0].size); + if (copy_from_user(p, (void*)io->sg[0].addr, io->sg[0].size)) { + kfree(p); + cmd_free(h, c, 0); + return -EFAULT; + } c->req.hdr.blk = pci_map_single(h->pci_dev, &(io->c), sizeof(ida_ioctl_t), PCI_DMA_BIDIRECTIONAL); @@ -1453,7 +1458,11 @@ cmd_free(h, c, 0); return(error); } - copy_from_user(p, (void*)io->sg[0].addr, io->sg[0].size); + if (copy_from_user(p, (void*)io->sg[0].addr, io->sg[0].size)) { + kfree(p); + cmd_free(h, c, 0); + return -EFAULT; + } c->req.sg[0].size = io->sg[0].size; c->req.sg[0].addr = pci_map_single(h->pci_dev, p, c->req.sg[0].size, PCI_DMA_BIDIRECTIONAL); @@ -1490,7 +1499,10 @@ case DIAG_PASS_THRU: case SENSE_CONTROLLER_PERFORMANCE: case READ_FLASH_ROM: - copy_to_user((void*)io->sg[0].addr, p, io->sg[0].size); + if (copy_to_user((void*)io->sg[0].addr, p, io->sg[0].size)) { + kfree(p); + return -EFAULT; + } /* fall through and free p */ case IDA_WRITE: case IDA_WRITE_MEDIA: diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/block/DAC960.c linux.19rc3-ac4/drivers/block/DAC960.c --- linux.19rc3/drivers/block/DAC960.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/drivers/block/DAC960.c 2002-07-29 13:58:39.000000000 +0100 @@ -5534,7 +5534,7 @@ static int DAC960_UserIOCTL(Inode_T *Inode, File_T *File, unsigned int Request, unsigned long Argument) { - int ErrorCode; + int ErrorCode = 0 ; if (!capable(CAP_SYS_ADMIN)) return -EACCES; switch (Request) { @@ -5585,9 +5585,11 @@ int ControllerNumber, DataTransferLength; unsigned char *DataTransferBuffer = NULL; if (UserSpaceUserCommand == NULL) return -EINVAL; - ErrorCode = copy_from_user(&UserCommand, UserSpaceUserCommand, - sizeof(DAC960_V1_UserCommand_T)); - if (ErrorCode != 0) goto Failure1; + if (copy_from_user(&UserCommand, UserSpaceUserCommand, + sizeof(DAC960_V1_UserCommand_T))) { + ErrorCode = -EFAULT; + goto Failure1; + } ControllerNumber = UserCommand.ControllerNumber; if (ControllerNumber < 0 || ControllerNumber > DAC960_ControllerCount - 1) @@ -5600,9 +5602,11 @@ if (CommandOpcode & 0x80) return -EINVAL; if (CommandOpcode == DAC960_V1_DCDB) { - ErrorCode = - copy_from_user(&DCDB, UserCommand.DCDB, sizeof(DAC960_V1_DCDB_T)); - if (ErrorCode != 0) goto Failure1; + if (copy_from_user(&DCDB, UserCommand.DCDB, + sizeof(DAC960_V1_DCDB_T))) { + ErrorCode = -EFAULT; + goto Failure1; + } if (DCDB.Channel >= DAC960_V1_MaxChannels) return -EINVAL; if (!((DataTransferLength == 0 && DCDB.Direction @@ -5628,10 +5632,12 @@ { DataTransferBuffer = kmalloc(-DataTransferLength, GFP_KERNEL); if (DataTransferBuffer == NULL) return -ENOMEM; - ErrorCode = copy_from_user(DataTransferBuffer, - UserCommand.DataTransferBuffer, - -DataTransferLength); - if (ErrorCode != 0) goto Failure1; + if (copy_from_user(DataTransferBuffer, + UserCommand.DataTransferBuffer, + -DataTransferLength)) { + ErrorCode = -EFAULT; + goto Failure1; + } } if (CommandOpcode == DAC960_V1_DCDB) { @@ -5679,17 +5685,20 @@ DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); if (DataTransferLength > 0) { - ErrorCode = copy_to_user(UserCommand.DataTransferBuffer, - DataTransferBuffer, DataTransferLength); - if (ErrorCode != 0) goto Failure1; + if (copy_to_user(UserCommand.DataTransferBuffer, + DataTransferBuffer, DataTransferLength)) + ErrorCode = -EFAULT; + goto Failure1; } if (CommandOpcode == DAC960_V1_DCDB) { Controller->V1.DirectCommandActive[DCDB.Channel] [DCDB.TargetID] = false; - ErrorCode = - copy_to_user(UserCommand.DCDB, &DCDB, sizeof(DAC960_V1_DCDB_T)); - if (ErrorCode != 0) goto Failure1; + if (copy_to_user(UserCommand.DCDB, &DCDB, + sizeof(DAC960_V1_DCDB_T))) { + ErrorCode = -EFAULT; + goto Failure1; + } } ErrorCode = CommandStatus; Failure1: @@ -5712,9 +5721,11 @@ unsigned char *DataTransferBuffer = NULL; unsigned char *RequestSenseBuffer = NULL; if (UserSpaceUserCommand == NULL) return -EINVAL; - ErrorCode = copy_from_user(&UserCommand, UserSpaceUserCommand, - sizeof(DAC960_V2_UserCommand_T)); - if (ErrorCode != 0) goto Failure2; + if (copy_from_user(&UserCommand, UserSpaceUserCommand, + sizeof(DAC960_V2_UserCommand_T))) { + ErrorCode = -EFAULT; + goto Failure2; + } ControllerNumber = UserCommand.ControllerNumber; if (ControllerNumber < 0 || ControllerNumber > DAC960_ControllerCount - 1) @@ -5733,10 +5744,12 @@ { DataTransferBuffer = kmalloc(-DataTransferLength, GFP_KERNEL); if (DataTransferBuffer == NULL) return -ENOMEM; - ErrorCode = copy_from_user(DataTransferBuffer, - UserCommand.DataTransferBuffer, - -DataTransferLength); - if (ErrorCode != 0) goto Failure2; + if (copy_from_user(DataTransferBuffer, + UserCommand.DataTransferBuffer, + -DataTransferLength)) { + ErrorCode = -EFAULT; + goto Failure2; + } } RequestSenseLength = UserCommand.RequestSenseLength; if (RequestSenseLength > 0) @@ -5806,25 +5819,32 @@ DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); if (RequestSenseLength > UserCommand.RequestSenseLength) RequestSenseLength = UserCommand.RequestSenseLength; - ErrorCode = copy_to_user(&UserSpaceUserCommand->DataTransferLength, + if (copy_to_user(&UserSpaceUserCommand->DataTransferLength, &DataTransferResidue, - sizeof(DataTransferResidue)); - if (ErrorCode != 0) goto Failure2; - ErrorCode = copy_to_user(&UserSpaceUserCommand->RequestSenseLength, - &RequestSenseLength, - sizeof(RequestSenseLength)); - if (ErrorCode != 0) goto Failure2; + sizeof(DataTransferResidue))) { + ErrorCode = -EFAULT; + goto Failure2; + } + if (copy_to_user(&UserSpaceUserCommand->RequestSenseLength, + &RequestSenseLength, sizeof(RequestSenseLength))) { + ErrorCode = -EFAULT; + goto Failure2; + } if (DataTransferLength > 0) { - ErrorCode = copy_to_user(UserCommand.DataTransferBuffer, - DataTransferBuffer, DataTransferLength); - if (ErrorCode != 0) goto Failure2; + if (copy_to_user(UserCommand.DataTransferBuffer, + DataTransferBuffer, DataTransferLength)) { + ErrorCode = -EFAULT; + goto Failure2; + } } if (RequestSenseLength > 0) { - ErrorCode = copy_to_user(UserCommand.RequestSenseBuffer, - RequestSenseBuffer, RequestSenseLength); - if (ErrorCode != 0) goto Failure2; + if (copy_to_user(UserCommand.RequestSenseBuffer, + RequestSenseBuffer, RequestSenseLength)) { + ErrorCode = -EFAULT; + goto Failure2; + } } ErrorCode = CommandStatus; Failure2: @@ -5843,9 +5863,9 @@ DAC960_Controller_T *Controller; int ControllerNumber; if (UserSpaceGetHealthStatus == NULL) return -EINVAL; - ErrorCode = copy_from_user(&GetHealthStatus, UserSpaceGetHealthStatus, - sizeof(DAC960_V2_GetHealthStatus_T)); - if (ErrorCode != 0) return ErrorCode; + if (copy_from_user(&GetHealthStatus, UserSpaceGetHealthStatus, + sizeof(DAC960_V2_GetHealthStatus_T))) + return -EFAULT; ControllerNumber = GetHealthStatus.ControllerNumber; if (ControllerNumber < 0 || ControllerNumber > DAC960_ControllerCount - 1) @@ -5853,10 +5873,10 @@ Controller = DAC960_Controllers[ControllerNumber]; if (Controller == NULL) return -ENXIO; if (Controller->FirmwareType != DAC960_V2_Controller) return -EINVAL; - ErrorCode = copy_from_user(&HealthStatusBuffer, - GetHealthStatus.HealthStatusBuffer, - sizeof(DAC960_V2_HealthStatusBuffer_T)); - if (ErrorCode != 0) return ErrorCode; + if (copy_from_user(&HealthStatusBuffer, + GetHealthStatus.HealthStatusBuffer, + sizeof(DAC960_V2_HealthStatusBuffer_T))) + return -EFAULT; while (Controller->V2.HealthStatusBuffer->StatusChangeCounter == HealthStatusBuffer.StatusChangeCounter && Controller->V2.HealthStatusBuffer->NextEventSequenceNumber @@ -5866,10 +5886,11 @@ DAC960_MonitoringTimerInterval); if (signal_pending(current)) return -EINTR; } - ErrorCode = copy_to_user(GetHealthStatus.HealthStatusBuffer, - Controller->V2.HealthStatusBuffer, - sizeof(DAC960_V2_HealthStatusBuffer_T)); - return ErrorCode; + if (copy_to_user(GetHealthStatus.HealthStatusBuffer, + Controller->V2.HealthStatusBuffer, + sizeof(DAC960_V2_HealthStatusBuffer_T))) + return -EFAULT; + return 0; } } return -EINVAL; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/block/elevator.c linux.19rc3-ac4/drivers/block/elevator.c --- linux.19rc3/drivers/block/elevator.c 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/block/elevator.c 2002-07-29 13:58:39.000000000 +0100 @@ -80,30 +80,38 @@ struct buffer_head *bh, int rw, int max_sectors) { - struct list_head *entry = &q->queue_head; - unsigned int count = bh->b_size >> 9, ret = ELEVATOR_NO_MERGE; - + struct list_head *entry; + unsigned int count = bh->b_size >> 9; + unsigned int ret = ELEVATOR_NO_MERGE; + int merge_only = 0; + const int max_bomb_segments = q->elevator.max_bomb_segments; + + entry = &q->queue_head; while ((entry = entry->prev) != head) { struct request *__rq = blkdev_entry_to_request(entry); - /* - * simply "aging" of requests in queue - */ - if (__rq->elevator_sequence-- <= 0) - break; - + if (__rq->elevator_sequence-- <= 0) { + /* + * OK, we've exceeded someone's latency limit. + * But we still continue to look for merges, + * because they're so much better than seeks. + */ + merge_only = 1; + } if (__rq->waiting) continue; if (__rq->rq_dev != bh->b_rdev) continue; - if (!*req && bh_rq_in_between(bh, __rq, &q->queue_head)) + if (!*req && !merge_only && + bh_rq_in_between(bh, __rq, &q->queue_head)) { *req = __rq; + } if (__rq->cmd != rw) continue; if (__rq->nr_sectors + count > max_sectors) continue; if (__rq->elevator_sequence < count) - break; + merge_only = 1; if (__rq->sector + __rq->nr_sectors == bh->b_rsector) { ret = ELEVATOR_BACK_MERGE; *req = __rq; @@ -116,20 +124,57 @@ } } - return ret; -} - -void elevator_linus_merge_cleanup(request_queue_t *q, struct request *req, int count) -{ - struct list_head *entry = &req->queue, *head = &q->queue_head; - /* - * second pass scan of requests that got passed over, if any + * If we failed to merge a read anywhere in the request + * queue, we really don't want to place it at the end + * of the list, behind lots of writes. So place it near + * the front. + * + * We don't want to place it in front of _all_ writes: that + * would create lots of seeking, and isn't tunable. + * We try to avoid promoting this read in front of existing + * reads. + * + * max_bomb_sectors becomes the maximum number of write + * requests which we allow to remain in place in front of + * a newly introduced read. We weight things a little bit, + * so large writes are more expensive than small ones, but it's + * requests which count, not sectors. */ - while ((entry = entry->next) != head) { - struct request *tmp = blkdev_entry_to_request(entry); - tmp->elevator_sequence -= count; + if (max_bomb_segments && rw == READ && ret == ELEVATOR_NO_MERGE) { + int cur_latency = 0; + struct request * const cur_request = *req; + + entry = head->next; + while (entry != &q->queue_head) { + struct request *__rq; + + if (entry == &q->queue_head) + BUG(); + if (entry == q->queue_head.next && + q->head_active && !q->plugged) + BUG(); + __rq = blkdev_entry_to_request(entry); + + if (__rq == cur_request) { + /* + * This is where the old algorithm placed it. + * There's no point pushing it further back, + * so leave it here, in sorted order. + */ + break; + } + if (__rq->cmd == WRITE) { + cur_latency += 1 + __rq->nr_sectors / 64; + if (cur_latency >= max_bomb_segments) { + *req = __rq; + break; + } + } + entry = entry->next; + } } + return ret; } void elevator_linus_merge_req(struct request *req, struct request *next) @@ -177,8 +222,6 @@ return ELEVATOR_NO_MERGE; } -void elevator_noop_merge_cleanup(request_queue_t *q, struct request *req, int count) {} - void elevator_noop_merge_req(struct request *req, struct request *next) {} int blkelvget_ioctl(elevator_t * elevator, blkelv_ioctl_arg_t * arg) @@ -188,7 +231,7 @@ output.queue_ID = elevator->queue_ID; output.read_latency = elevator->read_latency; output.write_latency = elevator->write_latency; - output.max_bomb_segments = 0; + output.max_bomb_segments = elevator->max_bomb_segments; if (copy_to_user(arg, &output, sizeof(blkelv_ioctl_arg_t))) return -EFAULT; @@ -207,9 +250,12 @@ return -EINVAL; if (input.write_latency < 0) return -EINVAL; + if (input.max_bomb_segments < 0) + return -EINVAL; elevator->read_latency = input.read_latency; elevator->write_latency = input.write_latency; + elevator->max_bomb_segments = input.max_bomb_segments; return 0; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/block/genhd.c linux.19rc3-ac4/drivers/block/genhd.c --- linux.19rc3/drivers/block/genhd.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/drivers/block/genhd.c 2002-07-29 13:58:39.000000000 +0100 @@ -163,7 +163,10 @@ char buf[64]; int len, n; - len = sprintf(page, "major minor #blocks name\n\n"); + len = sprintf(page, "major minor #blocks name " + "rio rmerge rsect ruse wio wmerge " + "wsect wuse running use aveq\n\n"); + read_lock(&gendisk_lock); for (gp = gendisk_head; gp; gp = gp->next) { @@ -173,8 +176,21 @@ hd = &gp->part[n]; disk_round_stats(hd); len += sprintf(page + len, - "%4d %4d %10d %s\n", gp->major, - n, gp->sizes[n], disk_name(gp, n, buf)); + "%4d %4d %10d %s " + "%d %d %d %d %d %d %d %d %d %d %d\n", + gp->major, n, gp->sizes[n], + disk_name(gp, n, buf), + hd->rd_ios, hd->rd_merges, + hd->rd_sectors, +#define MSEC(x) ((x) * 1000 / HZ) + MSEC(hd->rd_ticks), + hd->wr_ios, hd->wr_merges, + hd->wr_sectors, + MSEC(hd->wr_ticks), + hd->ios_in_flight, + MSEC(hd->io_ticks), + MSEC(hd->aveq)); +#undef MSEC if (len < offset) offset -= len, len = 0; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/block/ll_rw_blk.c linux.19rc3-ac4/drivers/block/ll_rw_blk.c --- linux.19rc3/drivers/block/ll_rw_blk.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/drivers/block/ll_rw_blk.c 2002-07-29 13:58:39.000000000 +0100 @@ -117,6 +117,23 @@ */ int * max_sectors[MAX_BLKDEV]; +/* + * blkdev_varyio indicates if variable size IO can be done on a device. + * + * Currently used for doing variable size IO on RAW devices. + */ +char * blkdev_varyio[MAX_BLKDEV]; + +/* + * The total number of requests in each queue. + */ +static int queue_nr_requests; + +/* + * The threshold around which we make wakeup decisions + */ +static int batch_requests; + static inline int get_max_sectors(kdev_t dev) { if (!max_sectors[MAJOR(dev)]) @@ -170,7 +187,7 @@ **/ void blk_cleanup_queue(request_queue_t * q) { - int count = q->nr_requests; + int count = queue_nr_requests; count -= __blk_cleanup_queue(&q->rq[READ]); count -= __blk_cleanup_queue(&q->rq[WRITE]); @@ -320,67 +337,31 @@ spin_unlock_irqrestore(&io_request_lock, flags); } -/** blk_grow_request_list - * @q: The &request_queue_t - * @nr_requests: how many requests are desired - * - * More free requests are added to the queue's free lists, bringing - * the total number of requests to @nr_requests. - * - * The requests are added equally to the request queue's read - * and write freelists. - * - * This function can sleep. - * - * Returns the (new) number of requests which the queue has available. - */ -int blk_grow_request_list(request_queue_t *q, int nr_requests) -{ - unsigned long flags; - /* Several broken drivers assume that this function doesn't sleep, - * this causes system hangs during boot. - * As a temporary fix, make the the function non-blocking. - */ - spin_lock_irqsave(&io_request_lock, flags); - while (q->nr_requests < nr_requests) { - struct request *rq; - int rw; - - rq = kmem_cache_alloc(request_cachep, SLAB_ATOMIC); - if (rq == NULL) - break; - memset(rq, 0, sizeof(*rq)); - rq->rq_status = RQ_INACTIVE; - rw = q->nr_requests & 1; - list_add(&rq->queue, &q->rq[rw].free); - q->rq[rw].count++; - q->nr_requests++; - } - q->batch_requests = q->nr_requests / 4; - if (q->batch_requests > 32) - q->batch_requests = 32; - spin_unlock_irqrestore(&io_request_lock, flags); - return q->nr_requests; -} - static void blk_init_free_list(request_queue_t *q) { - struct sysinfo si; - int megs; /* Total memory, in megabytes */ - int nr_requests; + struct request *rq; + int i; INIT_LIST_HEAD(&q->rq[READ].free); INIT_LIST_HEAD(&q->rq[WRITE].free); q->rq[READ].count = 0; q->rq[WRITE].count = 0; - q->nr_requests = 0; - si_meminfo(&si); - megs = si.totalram >> (20 - PAGE_SHIFT); - nr_requests = 128; - if (megs < 32) - nr_requests /= 2; - blk_grow_request_list(q, nr_requests); + /* + * Divide requests in half between read and write + */ + for (i = 0; i < queue_nr_requests; i++) { + rq = kmem_cache_alloc(request_cachep, SLAB_KERNEL); + if (rq == NULL) { + /* We'll get a `leaked requests' message from blk_cleanup_queue */ + printk(KERN_EMERG "blk_init_free_list: error allocating requests\n"); + break; + } + memset(rq, 0, sizeof(struct request)); + rq->rq_status = RQ_INACTIVE; + list_add(&rq->queue, &q->rq[i&1].free); + q->rq[i&1].count++; + } init_waitqueue_head(&q->wait_for_requests[0]); init_waitqueue_head(&q->wait_for_requests[1]); @@ -749,7 +730,7 @@ */ if (q) { list_add(&req->queue, &q->rq[rw].free); - if (++q->rq[rw].count >= q->batch_requests && + if (++q->rq[rw].count >= batch_requests && waitqueue_active(&q->wait_for_requests[rw])) wake_up(&q->wait_for_requests[rw]); } @@ -898,7 +879,6 @@ insert_here = &req->queue; break; } - elevator->elevator_merge_cleanup_fn(q, req, count); req->bhtail->b_reqnext = bh; req->bhtail = bh; req->nr_sectors = req->hard_nr_sectors += count; @@ -913,11 +893,11 @@ insert_here = req->queue.prev; break; } - elevator->elevator_merge_cleanup_fn(q, req, count); bh->b_reqnext = req->bh; req->bh = bh; req->buffer = bh->b_data; req->current_nr_sectors = count; + req->hard_cur_sectors = count; req->sector = req->hard_sector = sector; req->nr_sectors = req->hard_nr_sectors += count; blk_started_io(count); @@ -953,7 +933,7 @@ * See description above __get_request_wait() */ if (rw_ahead) { - if (q->rq[rw].count < q->batch_requests) { + if (q->rq[rw].count < batch_requests) { spin_unlock_irq(&io_request_lock); goto end_io; } @@ -977,6 +957,7 @@ req->hard_sector = req->sector = sector; req->hard_nr_sectors = req->nr_sectors = count; req->current_nr_sectors = count; + req->hard_cur_sectors = count; req->nr_segments = 1; /* Always 1 for a new request. */ req->nr_hw_segments = 1; /* Always 1 for a new request. */ req->buffer = bh->b_data; @@ -1132,6 +1113,38 @@ } } +/* + * submit_bh_blknr() - same as submit_bh() except that b_rsector is + * set to b_blocknr. Used for RAW VARY. + */ +void submit_bh_blknr(int rw, struct buffer_head * bh) +{ + int count = bh->b_size >> 9; + + if (!test_bit(BH_Lock, &bh->b_state)) + BUG(); + + set_bit(BH_Req, &bh->b_state); + + /* + * First step, 'identity mapping' - RAID or LVM might + * further remap this. + */ + bh->b_rdev = bh->b_dev; + bh->b_rsector = bh->b_blocknr; + + generic_make_request(rw, bh); + + switch (rw) { + case WRITE: + kstat.pgpgout += count; + break; + default: + kstat.pgpgin += count; + break; + } +} + /** * ll_rw_block: low-level access to block devices * @rw: whether to %READ or %WRITE or maybe %READA (readahead) @@ -1284,6 +1297,7 @@ req->nr_sectors = req->hard_nr_sectors; req->current_nr_sectors = bh->b_size >> 9; + req->hard_cur_sectors = req->current_nr_sectors; if (req->nr_sectors < req->current_nr_sectors) { req->nr_sectors = req->current_nr_sectors; printk("end_request: buffer-list destroyed\n"); @@ -1304,9 +1318,12 @@ blkdev_release_request(req); } +#define MB(kb) ((kb) << 10) + int __init blk_dev_init(void) { struct blk_dev_struct *dev; + int total_ram; /* kilobytes */ request_cachep = kmem_cache_create("blkdev_requests", sizeof(struct request), @@ -1322,6 +1339,24 @@ memset(max_readahead, 0, sizeof(max_readahead)); memset(max_sectors, 0, sizeof(max_sectors)); + total_ram = nr_free_pages() << (PAGE_SHIFT - 10); + + /* + * Free request slots per queue. + * (Half for reads, half for writes) + */ + queue_nr_requests = (total_ram >> 9) & ~15; /* One per half-megabyte */ + if (queue_nr_requests < 32) + queue_nr_requests = 32; + if (queue_nr_requests > 1024) + queue_nr_requests = 1024; + + /* + * Batch frees according to queue length + */ + batch_requests = queue_nr_requests/4; + printk("block: %d slots per queue, batch=%d\n", queue_nr_requests, batch_requests); + #ifdef CONFIG_AMIGA_Z2RAM z2_init(); #endif @@ -1429,7 +1464,6 @@ EXPORT_SYMBOL(io_request_lock); EXPORT_SYMBOL(end_that_request_first); EXPORT_SYMBOL(end_that_request_last); -EXPORT_SYMBOL(blk_grow_request_list); EXPORT_SYMBOL(blk_init_queue); EXPORT_SYMBOL(blk_get_queue); EXPORT_SYMBOL(blk_cleanup_queue); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/block/loop.c linux.19rc3-ac4/drivers/block/loop.c --- linux.19rc3/drivers/block/loop.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/drivers/block/loop.c 2002-07-29 13:58:39.000000000 +0100 @@ -199,9 +199,9 @@ page = grab_cache_page(mapping, index); if (!page) goto fail; + kaddr = kmap(page); if (aops->prepare_write(file, page, offset, offset+size)) goto unlock; - kaddr = page_address(page); flush_dcache_page(page); transfer_result = lo_do_transfer(lo, WRITE, kaddr + offset, data, size, IV); if (transfer_result) { @@ -216,6 +216,7 @@ goto unlock; if (transfer_result) goto unlock; + kunmap(page); data += size; len -= size; offset = 0; @@ -228,6 +229,7 @@ return 0; unlock: + kunmap(page); UnlockPage(page); page_cache_release(page); fail: @@ -418,6 +420,7 @@ break; run_task_queue(&tq_disk); + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ); } while (1); memset(bh, 0, sizeof(*bh)); @@ -437,6 +440,7 @@ break; run_task_queue(&tq_disk); + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ); } while (1); @@ -565,6 +569,7 @@ daemonize(); exit_files(current); + reparent_to_init(); sprintf(current->comm, "loop%d", lo->lo_number); @@ -573,9 +578,6 @@ flush_signals(current); spin_unlock_irq(¤t->sigmask_lock); - current->policy = SCHED_OTHER; - current->nice = -20; - spin_lock_irq(&lo->lo_lock); lo->lo_state = Lo_bound; atomic_inc(&lo->lo_pending); @@ -647,7 +649,7 @@ lo_device = inode->i_rdev; if (lo_device == dev) { error = -EBUSY; - goto out; + goto out_putf; } } else if (S_ISREG(inode->i_mode)) { struct address_space_operations *aops = inode->i_mapping->a_ops; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/block/umem.c linux.19rc3-ac4/drivers/block/umem.c --- linux.19rc3/drivers/block/umem.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/drivers/block/umem.c 2002-07-29 17:49:20.000000000 +0100 @@ -341,9 +341,7 @@ offset = ((char*)desc) - ((char*)page->desc); writel(cpu_to_le32((page->page_dma+offset)&0xffffffff), card->csr_remap + DMA_DESCRIPTOR_ADDR); - /* Force the valiue to u64 before shifting otherwise >> 32 is undefined C - and on some ports will do nothing ! */ - writel(((u64)cpu_to_le32((page->page_dma)>>32)), + writel(cpu_to_le32((page->page_dma)>>31>>1), card->csr_remap + DMA_DESCRIPTOR_ADDR + 4); /* Go, go, go */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/bluetooth/bluecard_cs.c linux.19rc3-ac4/drivers/bluetooth/bluecard_cs.c --- linux.19rc3/drivers/bluetooth/bluecard_cs.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/bluetooth/bluecard_cs.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,1113 @@ +/* + * + * Bluetooth driver for the Anycom BlueCard (LSE039/LSE041) + * + * Copyright (C) 2001-2002 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The initial developer of the original code is David A. Hinds + * . Portions created by David A. Hinds + * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + * + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + + +/* ======================== Module parameters ======================== */ + + +/* Bit map of interrupts to choose from */ +static u_int irq_mask = 0x86bc; +static int irq_list[4] = { -1 }; + +MODULE_PARM(irq_mask, "i"); +MODULE_PARM(irq_list, "1-4i"); + +MODULE_AUTHOR("Marcel Holtmann "); +MODULE_DESCRIPTION("BlueZ driver for the Anycom BlueCard (LSE039/LSE041)"); +MODULE_LICENSE("GPL"); + + + +/* ======================== Local structures ======================== */ + + +typedef struct bluecard_info_t { + dev_link_t link; + dev_node_t node; + + struct hci_dev hdev; + + spinlock_t lock; /* For serializing operations */ + struct timer_list timer; /* For LED control */ + + struct sk_buff_head txq; + unsigned long tx_state; + + unsigned long rx_state; + unsigned long rx_count; + struct sk_buff *rx_skb; + + unsigned char ctrl_reg; + unsigned long hw_state; /* Status of the hardware and LED control */ +} bluecard_info_t; + + +void bluecard_config(dev_link_t *link); +void bluecard_release(u_long arg); +int bluecard_event(event_t event, int priority, event_callback_args_t *args); + +static dev_info_t dev_info = "bluecard_cs"; + +dev_link_t *bluecard_attach(void); +void bluecard_detach(dev_link_t *); + +static dev_link_t *dev_list = NULL; + + +/* Default baud rate: 57600, 115200, 230400 or 460800 */ +#define DEFAULT_BAUD_RATE 230400 + + +/* Hardware states */ +#define CARD_READY 1 +#define CARD_HAS_PCCARD_ID 4 +#define CARD_HAS_POWER_LED 5 +#define CARD_HAS_ACTIVITY_LED 6 + +/* Transmit states */ +#define XMIT_SENDING 1 +#define XMIT_WAKEUP 2 +#define XMIT_BUFFER_NUMBER 5 /* unset = buffer one, set = buffer two */ +#define XMIT_BUF_ONE_READY 6 +#define XMIT_BUF_TWO_READY 7 +#define XMIT_SENDING_READY 8 + +/* Receiver states */ +#define RECV_WAIT_PACKET_TYPE 0 +#define RECV_WAIT_EVENT_HEADER 1 +#define RECV_WAIT_ACL_HEADER 2 +#define RECV_WAIT_SCO_HEADER 3 +#define RECV_WAIT_DATA 4 + +/* Special packet types */ +#define PKT_BAUD_RATE_57600 0x80 +#define PKT_BAUD_RATE_115200 0x81 +#define PKT_BAUD_RATE_230400 0x82 +#define PKT_BAUD_RATE_460800 0x83 + + +/* These are the register offsets */ +#define REG_COMMAND 0x20 +#define REG_INTERRUPT 0x21 +#define REG_CONTROL 0x22 +#define REG_RX_CONTROL 0x24 +#define REG_CARD_RESET 0x30 +#define REG_LED_CTRL 0x30 + +/* REG_COMMAND */ +#define REG_COMMAND_TX_BUF_ONE 0x01 +#define REG_COMMAND_TX_BUF_TWO 0x02 +#define REG_COMMAND_RX_BUF_ONE 0x04 +#define REG_COMMAND_RX_BUF_TWO 0x08 +#define REG_COMMAND_RX_WIN_ONE 0x00 +#define REG_COMMAND_RX_WIN_TWO 0x10 + +/* REG_CONTROL */ +#define REG_CONTROL_BAUD_RATE_57600 0x00 +#define REG_CONTROL_BAUD_RATE_115200 0x01 +#define REG_CONTROL_BAUD_RATE_230400 0x02 +#define REG_CONTROL_BAUD_RATE_460800 0x03 +#define REG_CONTROL_RTS 0x04 +#define REG_CONTROL_BT_ON 0x08 +#define REG_CONTROL_BT_RESET 0x10 +#define REG_CONTROL_BT_RES_PU 0x20 +#define REG_CONTROL_INTERRUPT 0x40 +#define REG_CONTROL_CARD_RESET 0x80 + +/* REG_RX_CONTROL */ +#define RTS_LEVEL_SHIFT_BITS 0x02 + + + +/* ======================== LED handling routines ======================== */ + + +void bluecard_activity_led_timeout(u_long arg) +{ + bluecard_info_t *info = (bluecard_info_t *)arg; + unsigned int iobase = info->link.io.BasePort1; + + if (test_bit(CARD_HAS_ACTIVITY_LED, &(info->hw_state))) { + /* Disable activity LED */ + outb(0x08 | 0x20, iobase + 0x30); + } else { + /* Disable power LED */ + outb(0x00, iobase + 0x30); + } +} + + +static void bluecard_enable_activity_led(bluecard_info_t *info) +{ + unsigned int iobase = info->link.io.BasePort1; + + if (test_bit(CARD_HAS_ACTIVITY_LED, &(info->hw_state))) { + /* Enable activity LED */ + outb(0x10 | 0x40, iobase + 0x30); + + /* Stop the LED after HZ/4 */ + mod_timer(&(info->timer), jiffies + HZ / 4); + } else { + /* Enable power LED */ + outb(0x08 | 0x20, iobase + 0x30); + + /* Stop the LED after HZ/2 */ + mod_timer(&(info->timer), jiffies + HZ / 2); + } +} + + + +/* ======================== Interrupt handling ======================== */ + + +static int bluecard_write(unsigned int iobase, unsigned int offset, __u8 *buf, int len) +{ + int i, actual; + + actual = (len > 15) ? 15 : len; + + outb_p(actual, iobase + offset); + + for (i = 0; i < actual; i++) + outb_p(buf[i], iobase + offset + i + 1); + + return actual; +} + + +static void bluecard_write_wakeup(bluecard_info_t *info) +{ + if (!info) { + printk(KERN_WARNING "bluecard_cs: Call of write_wakeup for unknown device.\n"); + return; + } + + if (!test_bit(XMIT_SENDING_READY, &(info->tx_state))) + return; + + if (test_and_set_bit(XMIT_SENDING, &(info->tx_state))) { + set_bit(XMIT_WAKEUP, &(info->tx_state)); + return; + } + + do { + register unsigned int iobase = info->link.io.BasePort1; + register unsigned int offset; + register unsigned char command; + register unsigned long ready_bit; + register struct sk_buff *skb; + register int len; + + clear_bit(XMIT_WAKEUP, &(info->tx_state)); + + if (!(info->link.state & DEV_PRESENT)) + return; + + if (test_bit(XMIT_BUFFER_NUMBER, &(info->tx_state))) { + if (!test_bit(XMIT_BUF_TWO_READY, &(info->tx_state))) + break; + offset = 0x10; + command = REG_COMMAND_TX_BUF_TWO; + ready_bit = XMIT_BUF_TWO_READY; + } else { + if (!test_bit(XMIT_BUF_ONE_READY, &(info->tx_state))) + break; + offset = 0x00; + command = REG_COMMAND_TX_BUF_ONE; + ready_bit = XMIT_BUF_ONE_READY; + } + + if (!(skb = skb_dequeue(&(info->txq)))) + break; + + if (skb->pkt_type & 0x80) { + /* Disable RTS */ + info->ctrl_reg |= REG_CONTROL_RTS; + outb(info->ctrl_reg, iobase + REG_CONTROL); + } + + /* Activate LED */ + bluecard_enable_activity_led(info); + + /* Send frame */ + len = bluecard_write(iobase, offset, skb->data, skb->len); + + /* Tell the FPGA to send the data */ + outb_p(command, iobase + REG_COMMAND); + + /* Mark the buffer as dirty */ + clear_bit(ready_bit, &(info->tx_state)); + + if (skb->pkt_type & 0x80) { + + wait_queue_head_t wait; + unsigned char baud_reg; + + switch (skb->pkt_type) { + case PKT_BAUD_RATE_460800: + baud_reg = REG_CONTROL_BAUD_RATE_460800; + break; + case PKT_BAUD_RATE_230400: + baud_reg = REG_CONTROL_BAUD_RATE_230400; + break; + case PKT_BAUD_RATE_115200: + baud_reg = REG_CONTROL_BAUD_RATE_115200; + break; + case PKT_BAUD_RATE_57600: + /* Fall through... */ + default: + baud_reg = REG_CONTROL_BAUD_RATE_57600; + break; + } + + /* Wait until the command reaches the baseband */ + init_waitqueue_head(&wait); + interruptible_sleep_on_timeout(&wait, HZ / 10); + + /* Set baud on baseband */ + info->ctrl_reg &= ~0x03; + info->ctrl_reg |= baud_reg; + outb(info->ctrl_reg, iobase + REG_CONTROL); + + /* Enable RTS */ + info->ctrl_reg &= ~REG_CONTROL_RTS; + outb(info->ctrl_reg, iobase + REG_CONTROL); + + /* Wait before the next HCI packet can be send */ + interruptible_sleep_on_timeout(&wait, HZ); + + } + + if (len == skb->len) { + kfree_skb(skb); + } else { + skb_pull(skb, len); + skb_queue_head(&(info->txq), skb); + } + + info->hdev.stat.byte_tx += len; + + /* Change buffer */ + change_bit(XMIT_BUFFER_NUMBER, &(info->tx_state)); + + } while (test_bit(XMIT_WAKEUP, &(info->tx_state))); + + clear_bit(XMIT_SENDING, &(info->tx_state)); +} + + +static int bluecard_read(unsigned int iobase, unsigned int offset, __u8 *buf, int size) +{ + int i, n, len; + + outb(REG_COMMAND_RX_WIN_ONE, iobase + REG_COMMAND); + + len = inb(iobase + offset); + n = 0; + i = 1; + + while (n < len) { + + if (i == 16) { + outb(REG_COMMAND_RX_WIN_TWO, iobase + REG_COMMAND); + i = 0; + } + + buf[n] = inb(iobase + offset + i); + + n++; + i++; + + } + + return len; +} + + +static void bluecard_receive(bluecard_info_t *info, unsigned int offset) +{ + unsigned int iobase; + unsigned char buf[31]; + int i, len; + + if (!info) { + printk(KERN_WARNING "bluecard_cs: Call of receive for unknown device.\n"); + return; + } + + iobase = info->link.io.BasePort1; + + if (test_bit(XMIT_SENDING_READY, &(info->tx_state))) + bluecard_enable_activity_led(info); + + len = bluecard_read(iobase, offset, buf, sizeof(buf)); + + for (i = 0; i < len; i++) { + + /* Allocate packet */ + if (info->rx_skb == NULL) { + info->rx_state = RECV_WAIT_PACKET_TYPE; + info->rx_count = 0; + if (!(info->rx_skb = bluez_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) { + printk(KERN_WARNING "bluecard_cs: Can't allocate mem for new packet.\n"); + return; + } + } + + if (info->rx_state == RECV_WAIT_PACKET_TYPE) { + + info->rx_skb->dev = (void *)&(info->hdev); + info->rx_skb->pkt_type = buf[i]; + + switch (info->rx_skb->pkt_type) { + + case 0x00: + /* init packet */ + if (offset != 0x00) { + set_bit(XMIT_BUF_ONE_READY, &(info->tx_state)); + set_bit(XMIT_BUF_TWO_READY, &(info->tx_state)); + set_bit(XMIT_SENDING_READY, &(info->tx_state)); + bluecard_write_wakeup(info); + } + + kfree_skb(info->rx_skb); + info->rx_skb = NULL; + break; + + case HCI_EVENT_PKT: + info->rx_state = RECV_WAIT_EVENT_HEADER; + info->rx_count = HCI_EVENT_HDR_SIZE; + break; + + case HCI_ACLDATA_PKT: + info->rx_state = RECV_WAIT_ACL_HEADER; + info->rx_count = HCI_ACL_HDR_SIZE; + break; + + case HCI_SCODATA_PKT: + info->rx_state = RECV_WAIT_SCO_HEADER; + info->rx_count = HCI_SCO_HDR_SIZE; + break; + + default: + /* unknown packet */ + printk(KERN_WARNING "bluecard_cs: Unknown HCI packet with type 0x%02x received.\n", info->rx_skb->pkt_type); + info->hdev.stat.err_rx++; + + kfree_skb(info->rx_skb); + info->rx_skb = NULL; + break; + + } + + } else { + + *skb_put(info->rx_skb, 1) = buf[i]; + info->rx_count--; + + if (info->rx_count == 0) { + + int dlen; + hci_event_hdr *eh; + hci_acl_hdr *ah; + hci_sco_hdr *sh; + + switch (info->rx_state) { + + case RECV_WAIT_EVENT_HEADER: + eh = (hci_event_hdr *)(info->rx_skb->data); + info->rx_state = RECV_WAIT_DATA; + info->rx_count = eh->plen; + break; + + case RECV_WAIT_ACL_HEADER: + ah = (hci_acl_hdr *)(info->rx_skb->data); + dlen = __le16_to_cpu(ah->dlen); + info->rx_state = RECV_WAIT_DATA; + info->rx_count = dlen; + break; + + case RECV_WAIT_SCO_HEADER: + sh = (hci_sco_hdr *)(info->rx_skb->data); + info->rx_state = RECV_WAIT_DATA; + info->rx_count = sh->dlen; + break; + + case RECV_WAIT_DATA: + hci_recv_frame(info->rx_skb); + info->rx_skb = NULL; + break; + + } + + } + + } + + + } + + info->hdev.stat.byte_rx += len; +} + + +void bluecard_interrupt(int irq, void *dev_inst, struct pt_regs *regs) +{ + bluecard_info_t *info = dev_inst; + unsigned int iobase; + unsigned char reg; + + if (!info) { + printk(KERN_WARNING "bluecard_cs: Call of irq %d for unknown device.\n", irq); + return; + } + + if (!test_bit(CARD_READY, &(info->hw_state))) + return; + + iobase = info->link.io.BasePort1; + + spin_lock(&(info->lock)); + + /* Disable interrupt */ + info->ctrl_reg &= ~REG_CONTROL_INTERRUPT; + outb(info->ctrl_reg, iobase + REG_CONTROL); + + reg = inb(iobase + REG_INTERRUPT); + + if ((reg != 0x00) && (reg != 0xff)) { + + if (reg & 0x04) { + bluecard_receive(info, 0x00); + outb(0x04, iobase + REG_INTERRUPT); + outb(REG_COMMAND_RX_BUF_ONE, iobase + REG_COMMAND); + } + + if (reg & 0x08) { + bluecard_receive(info, 0x10); + outb(0x08, iobase + REG_INTERRUPT); + outb(REG_COMMAND_RX_BUF_TWO, iobase + REG_COMMAND); + } + + if (reg & 0x01) { + set_bit(XMIT_BUF_ONE_READY, &(info->tx_state)); + outb(0x01, iobase + REG_INTERRUPT); + bluecard_write_wakeup(info); + } + + if (reg & 0x02) { + set_bit(XMIT_BUF_TWO_READY, &(info->tx_state)); + outb(0x02, iobase + REG_INTERRUPT); + bluecard_write_wakeup(info); + } + + } + + /* Enable interrupt */ + info->ctrl_reg |= REG_CONTROL_INTERRUPT; + outb(info->ctrl_reg, iobase + REG_CONTROL); + + spin_unlock(&(info->lock)); +} + + + +/* ======================== Device specific HCI commands ======================== */ + + +static int bluecard_hci_set_baud_rate(struct hci_dev *hdev, int baud) +{ + bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data); + struct sk_buff *skb; + + /* Ericsson baud rate command */ + unsigned char cmd[] = { HCI_COMMAND_PKT, 0x09, 0xfc, 0x01, 0x03 }; + + if (!(skb = bluez_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) { + printk(KERN_WARNING "bluecard_cs: Can't allocate mem for new packet.\n"); + return -1; + } + + switch (baud) { + case 460800: + cmd[4] = 0x00; + skb->pkt_type = PKT_BAUD_RATE_460800; + break; + case 230400: + cmd[4] = 0x01; + skb->pkt_type = PKT_BAUD_RATE_230400; + break; + case 115200: + cmd[4] = 0x02; + skb->pkt_type = PKT_BAUD_RATE_115200; + break; + case 57600: + /* Fall through... */ + default: + cmd[4] = 0x03; + skb->pkt_type = PKT_BAUD_RATE_57600; + break; + } + + memcpy(skb_put(skb, sizeof(cmd)), cmd, sizeof(cmd)); + + skb_queue_tail(&(info->txq), skb); + + bluecard_write_wakeup(info); + + return 0; +} + + + +/* ======================== HCI interface ======================== */ + + +static int bluecard_hci_flush(struct hci_dev *hdev) +{ + bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data); + + /* Drop TX queue */ + skb_queue_purge(&(info->txq)); + + return 0; +} + + +static int bluecard_hci_open(struct hci_dev *hdev) +{ + bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data); + unsigned int iobase = info->link.io.BasePort1; + + bluecard_hci_set_baud_rate(hdev, DEFAULT_BAUD_RATE); + + if (test_and_set_bit(HCI_RUNNING, &(hdev->flags))) + return 0; + + /* Enable LED */ + outb(0x08 | 0x20, iobase + 0x30); + + return 0; +} + + +static int bluecard_hci_close(struct hci_dev *hdev) +{ + bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data); + unsigned int iobase = info->link.io.BasePort1; + + if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags))) + return 0; + + bluecard_hci_flush(hdev); + + /* Disable LED */ + outb(0x00, iobase + 0x30); + + return 0; +} + + +static int bluecard_hci_send_frame(struct sk_buff *skb) +{ + bluecard_info_t *info; + struct hci_dev *hdev = (struct hci_dev *)(skb->dev); + + if (!hdev) { + printk(KERN_WARNING "bluecard_cs: Frame for unknown HCI device (hdev=NULL)."); + return -ENODEV; + } + + info = (bluecard_info_t *)(hdev->driver_data); + + switch (skb->pkt_type) { + case HCI_COMMAND_PKT: + hdev->stat.cmd_tx++; + break; + case HCI_ACLDATA_PKT: + hdev->stat.acl_tx++; + break; + case HCI_SCODATA_PKT: + hdev->stat.sco_tx++; + break; + }; + + /* Prepend skb with frame type */ + memcpy(skb_push(skb, 1), &(skb->pkt_type), 1); + skb_queue_tail(&(info->txq), skb); + + bluecard_write_wakeup(info); + + return 0; +} + + +static void bluecard_hci_destruct(struct hci_dev *hdev) +{ +} + + +static int bluecard_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) +{ + return -ENOIOCTLCMD; +} + + + +/* ======================== Card services HCI interaction ======================== */ + + +int bluecard_open(bluecard_info_t *info) +{ + unsigned int iobase = info->link.io.BasePort1; + struct hci_dev *hdev; + unsigned char id; + + spin_lock_init(&(info->lock)); + + init_timer(&(info->timer)); + info->timer.function = &bluecard_activity_led_timeout; + info->timer.data = (u_long)info; + + skb_queue_head_init(&(info->txq)); + + info->rx_state = RECV_WAIT_PACKET_TYPE; + info->rx_count = 0; + info->rx_skb = NULL; + + id = inb(iobase + 0x30); + + if ((id & 0x0f) == 0x02) + set_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)); + + if (id & 0x10) + set_bit(CARD_HAS_POWER_LED, &(info->hw_state)); + + if (id & 0x20) + set_bit(CARD_HAS_ACTIVITY_LED, &(info->hw_state)); + + /* Reset card */ + info->ctrl_reg = REG_CONTROL_BT_RESET | REG_CONTROL_CARD_RESET; + outb(info->ctrl_reg, iobase + REG_CONTROL); + + /* Turn FPGA off */ + outb(0x80, iobase + 0x30); + + /* Wait some time */ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ / 100); + + /* Turn FPGA on */ + outb(0x00, iobase + 0x30); + + /* Activate card */ + info->ctrl_reg = REG_CONTROL_BT_ON | REG_CONTROL_BT_RES_PU; + outb(info->ctrl_reg, iobase + REG_CONTROL); + + /* Enable interrupt */ + outb(0xff, iobase + REG_INTERRUPT); + info->ctrl_reg |= REG_CONTROL_INTERRUPT; + outb(info->ctrl_reg, iobase + REG_CONTROL); + + /* Start the RX buffers */ + outb(REG_COMMAND_RX_BUF_ONE, iobase + REG_COMMAND); + outb(REG_COMMAND_RX_BUF_TWO, iobase + REG_COMMAND); + + /* Signal that the hardware is ready */ + set_bit(CARD_READY, &(info->hw_state)); + + /* Drop TX queue */ + skb_queue_purge(&(info->txq)); + + /* Control the point at which RTS is enabled */ + outb((0x0f << RTS_LEVEL_SHIFT_BITS) | 1, iobase + REG_RX_CONTROL); + + /* Timeout before it is safe to send the first HCI packet */ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout((HZ * 5) / 4); // or set it to 3/2 + + + /* Initialize and register HCI device */ + + hdev = &(info->hdev); + + hdev->type = HCI_PCCARD; + hdev->driver_data = info; + + hdev->open = bluecard_hci_open; + hdev->close = bluecard_hci_close; + hdev->flush = bluecard_hci_flush; + hdev->send = bluecard_hci_send_frame; + hdev->destruct = bluecard_hci_destruct; + hdev->ioctl = bluecard_hci_ioctl; + + if (hci_register_dev(hdev) < 0) { + printk(KERN_WARNING "bluecard_cs: Can't register HCI device %s.\n", hdev->name); + return -ENODEV; + } + + return 0; +} + + +int bluecard_close(bluecard_info_t *info) +{ + unsigned int iobase = info->link.io.BasePort1; + struct hci_dev *hdev = &(info->hdev); + + bluecard_hci_close(hdev); + + clear_bit(CARD_READY, &(info->hw_state)); + + /* Reset card */ + info->ctrl_reg = REG_CONTROL_BT_RESET | REG_CONTROL_CARD_RESET; + outb(info->ctrl_reg, iobase + REG_CONTROL); + + /* Turn FPGA off */ + outb(0x80, iobase + 0x30); + + if (hci_unregister_dev(hdev) < 0) + printk(KERN_WARNING "bluecard_cs: Can't unregister HCI device %s.\n", hdev->name); + + return 0; +} + + + +/* ======================== Card services ======================== */ + + +static void cs_error(client_handle_t handle, int func, int ret) +{ + error_info_t err = { func, ret }; + + CardServices(ReportError, handle, &err); +} + + +dev_link_t *bluecard_attach(void) +{ + bluecard_info_t *info; + client_reg_t client_reg; + dev_link_t *link; + int i, ret; + + /* Create new info 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 = &bluecard_release; + link->release.data = (u_long)link; + link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + link->io.NumPorts1 = 8; + 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 = bluecard_interrupt; + link->irq.Instance = info; + + link->conf.Attributes = CONF_ENABLE_IRQ; + link->conf.Vcc = 50; + link->conf.IntType = INT_MEMORY_AND_IO; + + /* Register with Card Services */ + link->next = dev_list; + dev_list = link; + client_reg.dev_info = &dev_info; + client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; + client_reg.EventMask = + CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | + CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | + CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; + client_reg.event_handler = &bluecard_event; + client_reg.Version = 0x0210; + client_reg.event_callback_args.client_data = link; + + ret = CardServices(RegisterClient, &link->handle, &client_reg); + if (ret != CS_SUCCESS) { + cs_error(link->handle, RegisterClient, ret); + bluecard_detach(link); + return NULL; + } + + return link; +} + + +void bluecard_detach(dev_link_t *link) +{ + bluecard_info_t *info = link->priv; + dev_link_t **linkp; + int ret; + + /* Locate device structure */ + for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) + if (*linkp == link) + break; + + if (*linkp == NULL) + return; + + del_timer(&link->release); + if (link->state & DEV_CONFIG) + bluecard_release((u_long)link); + + if (link->handle) { + ret = CardServices(DeregisterClient, link->handle); + if (ret != CS_SUCCESS) + cs_error(link->handle, DeregisterClient, ret); + } + + /* Unlink device structure, free bits */ + *linkp = link->next; + + kfree(info); +} + + +static int get_tuple(int fn, client_handle_t handle, tuple_t *tuple, cisparse_t *parse) +{ + int i; + + i = CardServices(fn, handle, tuple); + if (i != CS_SUCCESS) + return CS_NO_MORE_ITEMS; + + i = CardServices(GetTupleData, handle, tuple); + if (i != CS_SUCCESS) + return i; + + return CardServices(ParseTuple, handle, tuple, parse); +} + + +#define first_tuple(a, b, c) get_tuple(GetFirstTuple, a, b, c) +#define next_tuple(a, b, c) get_tuple(GetNextTuple, a, b, c) + +void bluecard_config(dev_link_t *link) +{ + client_handle_t handle = link->handle; + bluecard_info_t *info = link->priv; + tuple_t tuple; + u_short buf[256]; + cisparse_t parse; + config_info_t config; + int i, n, last_ret, last_fn; + + tuple.TupleData = (cisdata_t *)buf; + tuple.TupleOffset = 0; + tuple.TupleDataMax = 255; + tuple.Attributes = 0; + + /* Get configuration register information */ + tuple.DesiredTuple = CISTPL_CONFIG; + last_ret = first_tuple(handle, &tuple, &parse); + if (last_ret != CS_SUCCESS) { + last_fn = ParseTuple; + goto cs_failed; + } + link->conf.ConfigBase = parse.config.base; + link->conf.Present = parse.config.rmask[0]; + + /* Configure card */ + link->state |= DEV_CONFIG; + i = CardServices(GetConfigurationInfo, handle, &config); + link->conf.Vcc = config.Vcc; + + link->conf.ConfigIndex = 0x20; + link->io.NumPorts1 = 64; + link->io.IOAddrLines = 6; + + for (n = 0; n < 0x400; n += 0x40) { + link->io.BasePort1 = n ^ 0x300; + i = CardServices(RequestIO, link->handle, &link->io); + if (i == CS_SUCCESS) + break; + } + + if (i != CS_SUCCESS) { + cs_error(link->handle, RequestIO, i); + goto failed; + } + + i = CardServices(RequestIRQ, link->handle, &link->irq); + if (i != CS_SUCCESS) { + cs_error(link->handle, RequestIRQ, i); + link->irq.AssignedIRQ = 0; + } + + i = CardServices(RequestConfiguration, link->handle, &link->conf); + if (i != CS_SUCCESS) { + cs_error(link->handle, RequestConfiguration, i); + goto failed; + } + + MOD_INC_USE_COUNT; + + if (bluecard_open(info) != 0) + goto failed; + + strcpy(info->node.dev_name, info->hdev.name); + link->dev = &info->node; + link->state &= ~DEV_CONFIG_PENDING; + + return; + +cs_failed: + cs_error(link->handle, last_fn, last_ret); + +failed: + bluecard_release((u_long)link); +} + + +void bluecard_release(u_long arg) +{ + dev_link_t *link = (dev_link_t *)arg; + bluecard_info_t *info = link->priv; + + if (link->state & DEV_PRESENT) + bluecard_close(info); + + MOD_DEC_USE_COUNT; + + link->dev = NULL; + + CardServices(ReleaseConfiguration, link->handle); + CardServices(ReleaseIO, link->handle, &link->io); + CardServices(ReleaseIRQ, link->handle, &link->irq); + + link->state &= ~DEV_CONFIG; +} + + +int bluecard_event(event_t event, int priority, event_callback_args_t *args) +{ + dev_link_t *link = args->client_data; + bluecard_info_t *info = link->priv; + + switch (event) { + case CS_EVENT_CARD_REMOVAL: + link->state &= ~DEV_PRESENT; + if (link->state & DEV_CONFIG) { + bluecard_close(info); + mod_timer(&link->release, jiffies + HZ / 20); + } + break; + case CS_EVENT_CARD_INSERTION: + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + bluecard_config(link); + break; + case CS_EVENT_PM_SUSPEND: + link->state |= DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_RESET_PHYSICAL: + if (link->state & DEV_CONFIG) + CardServices(ReleaseConfiguration, link->handle); + break; + case CS_EVENT_PM_RESUME: + link->state &= ~DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_CARD_RESET: + if (DEV_OK(link)) + CardServices(RequestConfiguration, link->handle, &link->conf); + break; + } + + return 0; +} + + + +/* ======================== Module initialization ======================== */ + + +int __init init_bluecard_cs(void) +{ + servinfo_t serv; + int err; + + CardServices(GetCardServicesInfo, &serv); + if (serv.Revision != CS_RELEASE_CODE) { + printk(KERN_NOTICE "bluecard_cs: Card Services release does not match!\n"); + return -1; + } + + err = register_pccard_driver(&dev_info, &bluecard_attach, &bluecard_detach); + + return err; +} + + +void __exit exit_bluecard_cs(void) +{ + unregister_pccard_driver(&dev_info); + + while (dev_list != NULL) + bluecard_detach(dev_list); +} + + +module_init(init_bluecard_cs); +module_exit(exit_bluecard_cs); + +EXPORT_NO_SYMBOLS; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/bluetooth/bt3c_cs.c linux.19rc3-ac4/drivers/bluetooth/bt3c_cs.c --- linux.19rc3/drivers/bluetooth/bt3c_cs.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/bluetooth/bt3c_cs.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,946 @@ +/* + * + * Driver for the 3Com Bluetooth PCMCIA card + * + * Copyright (C) 2001-2002 Marcel Holtmann + * Jose Orlando Pereira + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The initial developer of the original code is David A. Hinds + * . Portions created by David A. Hinds + * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + * + */ + +#include +#include + +#define __KERNEL_SYSCALLS__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + + +/* ======================== Module parameters ======================== */ + + +/* Bit map of interrupts to choose from */ +static u_int irq_mask = 0xffff; +static int irq_list[4] = { -1 }; + +MODULE_PARM(irq_mask, "i"); +MODULE_PARM(irq_list, "1-4i"); + +MODULE_AUTHOR("Marcel Holtmann , Jose Orlando Pereira "); +MODULE_DESCRIPTION("BlueZ driver for the 3Com Bluetooth PCMCIA card"); +MODULE_LICENSE("GPL"); + + + +/* ======================== Local structures ======================== */ + + +typedef struct bt3c_info_t { + dev_link_t link; + dev_node_t node; + + struct hci_dev hdev; + + spinlock_t lock; /* For serializing operations */ + + struct sk_buff_head txq; + unsigned long tx_state; + + unsigned long rx_state; + unsigned long rx_count; + struct sk_buff *rx_skb; +} bt3c_info_t; + + +void bt3c_config(dev_link_t *link); +void bt3c_release(u_long arg); +int bt3c_event(event_t event, int priority, event_callback_args_t *args); + +static dev_info_t dev_info = "bt3c_cs"; + +dev_link_t *bt3c_attach(void); +void bt3c_detach(dev_link_t *); + +static dev_link_t *dev_list = NULL; + + +/* Transmit states */ +#define XMIT_SENDING 1 +#define XMIT_WAKEUP 2 +#define XMIT_WAITING 8 + +/* Receiver states */ +#define RECV_WAIT_PACKET_TYPE 0 +#define RECV_WAIT_EVENT_HEADER 1 +#define RECV_WAIT_ACL_HEADER 2 +#define RECV_WAIT_SCO_HEADER 3 +#define RECV_WAIT_DATA 4 + + + +/* ======================== Special I/O functions ======================== */ + + +#define DATA_L 0 +#define DATA_H 1 +#define ADDR_L 2 +#define ADDR_H 3 +#define CONTROL 4 + + +inline void bt3c_address(unsigned int iobase, unsigned short addr) +{ + outb(addr & 0xff, iobase + ADDR_L); + outb((addr >> 8) & 0xff, iobase + ADDR_H); +} + + +inline void bt3c_put(unsigned int iobase, unsigned short value) +{ + outb(value & 0xff, iobase + DATA_L); + outb((value >> 8) & 0xff, iobase + DATA_H); +} + + +inline void bt3c_io_write(unsigned int iobase, unsigned short addr, unsigned short value) +{ + bt3c_address(iobase, addr); + bt3c_put(iobase, value); +} + + +inline unsigned short bt3c_get(unsigned int iobase) +{ + unsigned short value = inb(iobase + DATA_L); + + value |= inb(iobase + DATA_H) << 8; + + return value; +} + + +inline unsigned short bt3c_read(unsigned int iobase, unsigned short addr) +{ + bt3c_address(iobase, addr); + + return bt3c_get(iobase); +} + + + +/* ======================== Interrupt handling ======================== */ + + +static int bt3c_write(unsigned int iobase, int fifo_size, __u8 *buf, int len) +{ + int actual = 0; + + bt3c_address(iobase, 0x7080); + + /* Fill FIFO with current frame */ + while (actual < len) { + /* Transmit next byte */ + bt3c_put(iobase, buf[actual]); + actual++; + } + + bt3c_io_write(iobase, 0x7005, actual); + + return actual; +} + + +static void bt3c_write_wakeup(bt3c_info_t *info, int from) +{ + unsigned long flags; + + if (!info) { + printk(KERN_WARNING "bt3c_cs: Call of write_wakeup for unknown device.\n"); + return; + } + + if (test_and_set_bit(XMIT_SENDING, &(info->tx_state))) + return; + + spin_lock_irqsave(&(info->lock), flags); + + do { + register unsigned int iobase = info->link.io.BasePort1; + register struct sk_buff *skb; + register int len; + + if (!(info->link.state & DEV_PRESENT)) + break; + + + if (!(skb = skb_dequeue(&(info->txq)))) { + clear_bit(XMIT_SENDING, &(info->tx_state)); + break; + } + + /* Send frame */ + len = bt3c_write(iobase, 256, skb->data, skb->len); + + if (len != skb->len) { + printk(KERN_WARNING "bt3c_cs: very strange\n"); + } + + kfree_skb(skb); + + info->hdev.stat.byte_tx += len; + + } while (0); + + spin_unlock_irqrestore(&(info->lock), flags); +} + + +static void bt3c_receive(bt3c_info_t *info) +{ + unsigned int iobase; + int size = 0, avail; + + if (!info) { + printk(KERN_WARNING "bt3c_cs: Call of receive for unknown device.\n"); + return; + } + + iobase = info->link.io.BasePort1; + + avail = bt3c_read(iobase, 0x7006); + //printk("bt3c_cs: receiving %d bytes\n", avail); + + bt3c_address(iobase, 0x7480); + while (size < avail) { + size++; + info->hdev.stat.byte_rx++; + + /* Allocate packet */ + if (info->rx_skb == NULL) { + info->rx_state = RECV_WAIT_PACKET_TYPE; + info->rx_count = 0; + if (!(info->rx_skb = bluez_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) { + printk(KERN_WARNING "bt3c_cs: Can't allocate mem for new packet.\n"); + return; + } + } + + + if (info->rx_state == RECV_WAIT_PACKET_TYPE) { + + info->rx_skb->dev = (void *)&(info->hdev); + info->rx_skb->pkt_type = inb(iobase + DATA_L); + inb(iobase + DATA_H); + //printk("bt3c: PACKET_TYPE=%02x\n", info->rx_skb->pkt_type); + + switch (info->rx_skb->pkt_type) { + + case HCI_EVENT_PKT: + info->rx_state = RECV_WAIT_EVENT_HEADER; + info->rx_count = HCI_EVENT_HDR_SIZE; + break; + + case HCI_ACLDATA_PKT: + info->rx_state = RECV_WAIT_ACL_HEADER; + info->rx_count = HCI_ACL_HDR_SIZE; + break; + + case HCI_SCODATA_PKT: + info->rx_state = RECV_WAIT_SCO_HEADER; + info->rx_count = HCI_SCO_HDR_SIZE; + break; + + default: + /* Unknown packet */ + printk(KERN_WARNING "bt3c_cs: Unknown HCI packet with type 0x%02x received.\n", info->rx_skb->pkt_type); + info->hdev.stat.err_rx++; + clear_bit(HCI_RUNNING, &(info->hdev.flags)); + + kfree_skb(info->rx_skb); + info->rx_skb = NULL; + break; + + } + + } else { + + __u8 x = inb(iobase + DATA_L); + + *skb_put(info->rx_skb, 1) = x; + inb(iobase + DATA_H); + info->rx_count--; + + if (info->rx_count == 0) { + + int dlen; + hci_event_hdr *eh; + hci_acl_hdr *ah; + hci_sco_hdr *sh; + + switch (info->rx_state) { + + case RECV_WAIT_EVENT_HEADER: + eh = (hci_event_hdr *)(info->rx_skb->data); + info->rx_state = RECV_WAIT_DATA; + info->rx_count = eh->plen; + break; + + case RECV_WAIT_ACL_HEADER: + ah = (hci_acl_hdr *)(info->rx_skb->data); + dlen = __le16_to_cpu(ah->dlen); + info->rx_state = RECV_WAIT_DATA; + info->rx_count = dlen; + break; + + case RECV_WAIT_SCO_HEADER: + sh = (hci_sco_hdr *)(info->rx_skb->data); + info->rx_state = RECV_WAIT_DATA; + info->rx_count = sh->dlen; + break; + + case RECV_WAIT_DATA: + hci_recv_frame(info->rx_skb); + info->rx_skb = NULL; + break; + + } + + } + + } + + } + + bt3c_io_write(iobase, 0x7006, 0x0000); +} + + +void bt3c_interrupt(int irq, void *dev_inst, struct pt_regs *regs) +{ + bt3c_info_t *info = dev_inst; + unsigned int iobase; + int iir; + + if (!info) { + printk(KERN_WARNING "bt3c_cs: Call of irq %d for unknown device.\n", irq); + return; + } + + iobase = info->link.io.BasePort1; + + spin_lock(&(info->lock)); + + iir = inb(iobase + CONTROL); + if (iir & 0x80) { + int stat = bt3c_read(iobase, 0x7001); + + if ((stat & 0xff) == 0x7f) { + printk(KERN_WARNING "bt3c_cs: STRANGE stat=%04x\n", stat); + } else if ((stat & 0xff) != 0xff) { + if (stat & 0x0020) { + int stat = bt3c_read(iobase, 0x7002) & 0x10; + printk(KERN_WARNING "bt3c_cs: antena %s\n", stat ? "OUT" : "IN"); + } + if (stat & 0x0001) + bt3c_receive(info); + if (stat & 0x0002) { + //printk("bt3c_cs: ACK %04x\n", stat); + clear_bit(XMIT_SENDING, &(info->tx_state)); + bt3c_write_wakeup(info, 1); + } + + bt3c_io_write(iobase, 0x7001, 0x0000); + + outb(iir, iobase + CONTROL); + } + } + + spin_unlock(&(info->lock)); +} + + + + +/* ======================== HCI interface ======================== */ + + +static int bt3c_hci_flush(struct hci_dev *hdev) +{ + bt3c_info_t *info = (bt3c_info_t *)(hdev->driver_data); + + /* Drop TX queue */ + skb_queue_purge(&(info->txq)); + + return 0; +} + + +static int bt3c_hci_open(struct hci_dev *hdev) +{ + set_bit(HCI_RUNNING, &(hdev->flags)); + + return 0; +} + + +static int bt3c_hci_close(struct hci_dev *hdev) +{ + if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags))) + return 0; + + bt3c_hci_flush(hdev); + + return 0; +} + + +static int bt3c_hci_send_frame(struct sk_buff *skb) +{ + bt3c_info_t *info; + struct hci_dev *hdev = (struct hci_dev *)(skb->dev); + + if (!hdev) { + printk(KERN_WARNING "bt3c_cs: Frame for unknown HCI device (hdev=NULL)."); + return -ENODEV; + } + + info = (bt3c_info_t *) (hdev->driver_data); + + switch (skb->pkt_type) { + case HCI_COMMAND_PKT: + hdev->stat.cmd_tx++; + break; + case HCI_ACLDATA_PKT: + hdev->stat.acl_tx++; + break; + case HCI_SCODATA_PKT: + hdev->stat.sco_tx++; + break; + }; + + /* Prepend skb with frame type */ + memcpy(skb_push(skb, 1), &(skb->pkt_type), 1); + skb_queue_tail(&(info->txq), skb); + + bt3c_write_wakeup(info, 0); + + return 0; +} + + +static void bt3c_hci_destruct(struct hci_dev *hdev) +{ +} + + +static int bt3c_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) +{ + return -ENOIOCTLCMD; +} + + + +/* ======================== User mode firmware loader ======================== */ + + +#define FW_LOADER "/sbin/bluefw" +static int errno; + + +static int bt3c_fw_loader_exec(void *dev) +{ + char *argv[] = { FW_LOADER, "pccard", dev, NULL }; + char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL }; + int err; + + err = exec_usermodehelper(FW_LOADER, argv, envp); + if (err) + printk(KERN_WARNING "bt3c_cs: Failed to exec \"%s pccard %s\".\n", FW_LOADER, (char *)dev); + + return err; +} + + +static int bt3c_firmware_load(bt3c_info_t *info) +{ + sigset_t tmpsig; + char dev[16]; + pid_t pid; + int result; + + /* Check if root fs is mounted */ + if (!current->fs->root) { + printk(KERN_WARNING "bt3c_cs: Root filesystem is not mounted.\n"); + return -EPERM; + } + + sprintf(dev, "%04x", info->link.io.BasePort1); + + pid = kernel_thread(bt3c_fw_loader_exec, (void *)dev, 0); + if (pid < 0) { + printk(KERN_WARNING "bt3c_cs: Forking of kernel thread failed (errno=%d).\n", -pid); + return pid; + } + + /* Block signals, everything but SIGKILL/SIGSTOP */ + spin_lock_irq(¤t->sigmask_lock); + tmpsig = current->blocked; + siginitsetinv(¤t->blocked, sigmask(SIGKILL) | sigmask(SIGSTOP)); + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + + result = waitpid(pid, NULL, __WCLONE); + + /* Allow signals again */ + spin_lock_irq(¤t->sigmask_lock); + current->blocked = tmpsig; + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + + if (result != pid) { + printk(KERN_WARNING "bt3c_cs: Waiting for pid %d failed (errno=%d).\n", pid, -result); + return -result; + } + + return 0; +} + + + +/* ======================== Card services HCI interaction ======================== */ + + +int bt3c_open(bt3c_info_t *info) +{ + struct hci_dev *hdev; + int err; + + spin_lock_init(&(info->lock)); + + skb_queue_head_init(&(info->txq)); + + info->rx_state = RECV_WAIT_PACKET_TYPE; + info->rx_count = 0; + info->rx_skb = NULL; + + /* Load firmware */ + + if ((err = bt3c_firmware_load(info)) < 0) + return err; + + /* Timeout before it is safe to send the first HCI packet */ + + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ); + + + /* Initialize and register HCI device */ + + hdev = &(info->hdev); + + hdev->type = HCI_PCCARD; + hdev->driver_data = info; + + hdev->open = bt3c_hci_open; + hdev->close = bt3c_hci_close; + hdev->flush = bt3c_hci_flush; + hdev->send = bt3c_hci_send_frame; + hdev->destruct = bt3c_hci_destruct; + hdev->ioctl = bt3c_hci_ioctl; + + if (hci_register_dev(hdev) < 0) { + printk(KERN_WARNING "bt3c_cs: Can't register HCI device %s.\n", hdev->name); + return -ENODEV; + } + + return 0; +} + + +int bt3c_close(bt3c_info_t *info) +{ + struct hci_dev *hdev = &(info->hdev); + + bt3c_hci_close(hdev); + + if (hci_unregister_dev(hdev) < 0) + printk(KERN_WARNING "bt3c_cs: Can't unregister HCI device %s.\n", hdev->name); + + return 0; +} + + + +/* ======================== Card services ======================== */ + + +static void cs_error(client_handle_t handle, int func, int ret) +{ + error_info_t err = { func, ret }; + + CardServices(ReportError, handle, &err); +} + + +dev_link_t *bt3c_attach(void) +{ + bt3c_info_t *info; + client_reg_t client_reg; + dev_link_t *link; + int i, ret; + + /* Create new info 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 = &bt3c_release; + link->release.data = (u_long)link; + link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + link->io.NumPorts1 = 8; + 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 = bt3c_interrupt; + link->irq.Instance = info; + + link->conf.Attributes = CONF_ENABLE_IRQ; + link->conf.Vcc = 50; + link->conf.IntType = INT_MEMORY_AND_IO; + + /* Register with Card Services */ + link->next = dev_list; + dev_list = link; + client_reg.dev_info = &dev_info; + client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; + client_reg.EventMask = + CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | + CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | + CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; + client_reg.event_handler = &bt3c_event; + client_reg.Version = 0x0210; + client_reg.event_callback_args.client_data = link; + + ret = CardServices(RegisterClient, &link->handle, &client_reg); + if (ret != CS_SUCCESS) { + cs_error(link->handle, RegisterClient, ret); + bt3c_detach(link); + return NULL; + } + + return link; +} + + +void bt3c_detach(dev_link_t *link) +{ + bt3c_info_t *info = link->priv; + dev_link_t **linkp; + int ret; + + /* Locate device structure */ + for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) + if (*linkp == link) + break; + + if (*linkp == NULL) + return; + + del_timer(&link->release); + + if (link->state & DEV_CONFIG) + bt3c_release((u_long)link); + + if (link->handle) { + ret = CardServices(DeregisterClient, link->handle); + if (ret != CS_SUCCESS) + cs_error(link->handle, DeregisterClient, ret); + } + + /* Unlink device structure, free bits */ + *linkp = link->next; + + kfree(info); +} + + +static int get_tuple(int fn, client_handle_t handle, tuple_t *tuple, cisparse_t *parse) +{ + int i; + + i = CardServices(fn, handle, tuple); + if (i != CS_SUCCESS) + return CS_NO_MORE_ITEMS; + + i = CardServices(GetTupleData, handle, tuple); + if (i != CS_SUCCESS) + return i; + + return CardServices(ParseTuple, handle, tuple, parse); +} + + +#define first_tuple(a, b, c) get_tuple(GetFirstTuple, a, b, c) +#define next_tuple(a, b, c) get_tuple(GetNextTuple, a, b, c) + +void bt3c_config(dev_link_t *link) +{ + static ioaddr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; + client_handle_t handle = link->handle; + bt3c_info_t *info = link->priv; + tuple_t tuple; + u_short buf[256]; + cisparse_t parse; + cistpl_cftable_entry_t *cf = &parse.cftable_entry; + config_info_t config; + int i, j, try, last_ret, last_fn; + + tuple.TupleData = (cisdata_t *)buf; + tuple.TupleOffset = 0; + tuple.TupleDataMax = 255; + tuple.Attributes = 0; + + /* Get configuration register information */ + tuple.DesiredTuple = CISTPL_CONFIG; + last_ret = first_tuple(handle, &tuple, &parse); + if (last_ret != CS_SUCCESS) { + last_fn = ParseTuple; + goto cs_failed; + } + link->conf.ConfigBase = parse.config.base; + link->conf.Present = parse.config.rmask[0]; + + /* Configure card */ + link->state |= DEV_CONFIG; + i = CardServices(GetConfigurationInfo, handle, &config); + link->conf.Vcc = config.Vcc; + + /* First pass: look for a config entry that looks normal. */ + tuple.TupleData = (cisdata_t *)buf; + tuple.TupleOffset = 0; + tuple.TupleDataMax = 255; + tuple.Attributes = 0; + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + /* Two tries: without IO aliases, then with aliases */ + for (try = 0; try < 2; try++) { + i = first_tuple(handle, &tuple, &parse); + while (i != CS_NO_MORE_ITEMS) { + if (i != CS_SUCCESS) + goto next_entry; + if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM)) + link->conf.Vpp1 = link->conf.Vpp2 = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000; + if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && (cf->io.win[0].base != 0)) { + link->conf.ConfigIndex = cf->index; + link->io.BasePort1 = cf->io.win[0].base; + link->io.IOAddrLines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK; + i = CardServices(RequestIO, link->handle, &link->io); + if (i == CS_SUCCESS) + goto found_port; + } +next_entry: + i = next_tuple(handle, &tuple, &parse); + } + } + + /* Second pass: try to find an entry that isn't picky about + its base address, then try to grab any standard serial port + address, and finally try to get any free port. */ + i = first_tuple(handle, &tuple, &parse); + while (i != CS_NO_MORE_ITEMS) { + if ((i == CS_SUCCESS) && (cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) { + link->conf.ConfigIndex = cf->index; + for (j = 0; j < 5; j++) { + link->io.BasePort1 = base[j]; + link->io.IOAddrLines = base[j] ? 16 : 3; + i = CardServices(RequestIO, link->handle, &link->io); + if (i == CS_SUCCESS) + goto found_port; + } + } + i = next_tuple(handle, &tuple, &parse); + } + +found_port: + if (i != CS_SUCCESS) { + printk(KERN_NOTICE "bt3c_cs: No usable port range found. Giving up.\n"); + cs_error(link->handle, RequestIO, i); + goto failed; + } + + i = CardServices(RequestIRQ, link->handle, &link->irq); + if (i != CS_SUCCESS) { + cs_error(link->handle, RequestIRQ, i); + link->irq.AssignedIRQ = 0; + } + + i = CardServices(RequestConfiguration, link->handle, &link->conf); + if (i != CS_SUCCESS) { + cs_error(link->handle, RequestConfiguration, i); + goto failed; + } + + MOD_INC_USE_COUNT; + + if (bt3c_open(info) != 0) + goto failed; + + strcpy(info->node.dev_name, info->hdev.name); + link->dev = &info->node; + link->state &= ~DEV_CONFIG_PENDING; + + return; + +cs_failed: + cs_error(link->handle, last_fn, last_ret); + +failed: + bt3c_release((u_long)link); +} + + +void bt3c_release(u_long arg) +{ + dev_link_t *link = (dev_link_t *)arg; + bt3c_info_t *info = link->priv; + + if (link->state & DEV_PRESENT) + bt3c_close(info); + + MOD_DEC_USE_COUNT; + + link->dev = NULL; + + CardServices(ReleaseConfiguration, link->handle); + CardServices(ReleaseIO, link->handle, &link->io); + CardServices(ReleaseIRQ, link->handle, &link->irq); + + link->state &= ~DEV_CONFIG; +} + + +int bt3c_event(event_t event, int priority, event_callback_args_t *args) +{ + dev_link_t *link = args->client_data; + bt3c_info_t *info = link->priv; + + switch (event) { + case CS_EVENT_CARD_REMOVAL: + link->state &= ~DEV_PRESENT; + if (link->state & DEV_CONFIG) { + bt3c_close(info); + mod_timer(&link->release, jiffies + HZ / 20); + } + break; + case CS_EVENT_CARD_INSERTION: + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + bt3c_config(link); + break; + case CS_EVENT_PM_SUSPEND: + link->state |= DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_RESET_PHYSICAL: + if (link->state & DEV_CONFIG) + CardServices(ReleaseConfiguration, link->handle); + break; + case CS_EVENT_PM_RESUME: + link->state &= ~DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_CARD_RESET: + if (DEV_OK(link)) + CardServices(RequestConfiguration, link->handle, &link->conf); + break; + } + + return 0; +} + + + +/* ======================== Module initialization ======================== */ + + +int __init init_bt3c_cs(void) +{ + servinfo_t serv; + int err; + + CardServices(GetCardServicesInfo, &serv); + if (serv.Revision != CS_RELEASE_CODE) { + printk(KERN_NOTICE "bt3c_cs: Card Services release does not match!\n"); + return -1; + } + + err = register_pccard_driver(&dev_info, &bt3c_attach, &bt3c_detach); + + return err; +} + + +void __exit exit_bt3c_cs(void) +{ + unregister_pccard_driver(&dev_info); + + while (dev_list != NULL) + bt3c_detach(dev_list); +} + + +module_init(init_bt3c_cs); +module_exit(exit_bt3c_cs); + +EXPORT_NO_SYMBOLS; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/bluetooth/Config.in linux.19rc3-ac4/drivers/bluetooth/Config.in --- linux.19rc3/drivers/bluetooth/Config.in 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/drivers/bluetooth/Config.in 2002-07-29 13:58:39.000000000 +0100 @@ -14,6 +14,10 @@ dep_tristate 'HCI DTL1 (PC Card) driver' CONFIG_BLUEZ_HCIDTL1 $CONFIG_PCMCIA $CONFIG_BLUEZ +dep_tristate 'HCI BT3C (PC Card) driver' CONFIG_BLUEZ_HCIBT3C $CONFIG_PCMCIA $CONFIG_BLUEZ + +dep_tristate 'HCI BlueCard (PC Card) driver' CONFIG_BLUEZ_HCIBLUECARD $CONFIG_PCMCIA $CONFIG_BLUEZ + dep_tristate 'HCI VHCI (Virtual HCI device) driver' CONFIG_BLUEZ_HCIVHCI $CONFIG_BLUEZ endmenu diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/bluetooth/dtl1_cs.c linux.19rc3-ac4/drivers/bluetooth/dtl1_cs.c --- linux.19rc3/drivers/bluetooth/dtl1_cs.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/drivers/bluetooth/dtl1_cs.c 2002-07-29 13:58:39.000000000 +0100 @@ -75,23 +75,22 @@ typedef struct dtl1_info_t { - dev_link_t link; - dev_node_t node; + dev_link_t link; + dev_node_t node; - struct hci_dev hdev; + struct hci_dev hdev; - spinlock_t lock; /* For serializing operations */ + spinlock_t lock; /* For serializing operations */ - unsigned long flowmask; /* HCI flow mask */ - int ri_latch; + unsigned long flowmask; /* HCI flow mask */ + int ri_latch; - struct sk_buff_head txq; - unsigned long tx_state; - - unsigned long rx_state; - unsigned long rx_count; - struct sk_buff *rx_skb; + struct sk_buff_head txq; + unsigned long tx_state; + unsigned long rx_state; + unsigned long rx_count; + struct sk_buff *rx_skb; } dtl1_info_t; @@ -104,7 +103,7 @@ dev_link_t *dtl1_attach(void); void dtl1_detach(dev_link_t *); -dev_link_t *dev_list = NULL; +static dev_link_t *dev_list = NULL; /* Transmit states */ @@ -118,282 +117,253 @@ typedef struct { - u8 type; - u8 zero; - u16 len; -} __attribute__ ((packed)) nsh_t; /* Nokia Specific Header */ + u8 type; + u8 zero; + u16 len; +} __attribute__ ((packed)) nsh_t; /* Nokia Specific Header */ -#define NSHL 4 /* Nokia Specific Header Length */ +#define NSHL 4 /* Nokia Specific Header Length */ /* ======================== Interrupt handling ======================== */ -static int dtl1_write(unsigned int iobase, int fifo_size, __u8 *buf, int len) { - - int actual = 0; - - - /* Tx FIFO should be empty */ - if (!(inb(iobase + UART_LSR) & UART_LSR_THRE)) - return 0; - - - /* Fill FIFO with current frame */ - while ((fifo_size-- > 0) && (actual < len)) { - /* Transmit next byte */ - outb(buf[actual], iobase + UART_TX); - actual++; - } - - - return actual; - -} - - -static void dtl1_write_wakeup(dtl1_info_t *info) { - - if (!info) { - printk(KERN_WARNING "dtl1_cs: Call of write_wakeup for unknown device.\n"); - return; - } - - - if (test_bit(XMIT_WAITING, &(info->tx_state))) { - set_bit(XMIT_WAKEUP, &(info->tx_state)); - return; - } - - if (test_and_set_bit(XMIT_SENDING, &(info->tx_state))) { - set_bit(XMIT_WAKEUP, &(info->tx_state)); - return; - } - - - do { - register unsigned int iobase = info->link.io.BasePort1; - register struct sk_buff *skb; - register int len; - - clear_bit(XMIT_WAKEUP, &(info->tx_state)); - - if (!(info->link.state & DEV_PRESENT)) - return; - - - if (!(skb = skb_dequeue(&(info->txq)))) - break; - - - /* Send frame */ - len = dtl1_write(iobase, 32, skb->data, skb->len); - - if (len == skb->len) { - set_bit(XMIT_WAITING, &(info->tx_state)); - kfree_skb(skb); - } - else { - skb_pull(skb, len); - skb_queue_head(&(info->txq), skb); - } - - info->hdev.stat.byte_tx += len; - - } while (test_bit(XMIT_WAKEUP, &(info->tx_state))); - - - clear_bit(XMIT_SENDING, &(info->tx_state)); - -} - - -static void dtl1_control(dtl1_info_t *info, struct sk_buff *skb) { - - u8 flowmask = *(u8 *)skb->data; - int i; - - - printk(KERN_INFO "dtl1_cs: Nokia control data = "); - for (i = 0; i < skb->len; i++) { - printk("%02x ", skb->data[i]); - } - printk("\n"); - - - /* transition to active state */ - if (((info->flowmask & 0x07) == 0) && ((flowmask & 0x07) != 0)) { - clear_bit(XMIT_WAITING, &(info->tx_state)); - dtl1_write_wakeup(info); - } - - info->flowmask = flowmask; - - - kfree_skb(skb); - -} - - -static void dtl1_receive(dtl1_info_t *info) { - - unsigned int iobase; - nsh_t *nsh; - int boguscount = 0; - - - if (!info) { - printk(KERN_WARNING "dtl1_cs: Call of receive for unknown device.\n"); - return; - } - - - iobase = info->link.io.BasePort1; - - do { - info->hdev.stat.byte_rx++; - - /* Allocate packet */ - if (info->rx_skb == NULL) - if (!(info->rx_skb = bluez_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) { - printk(KERN_WARNING "dtl1_cs: Can't allocate mem for new packet.\n"); - info->rx_state = RECV_WAIT_NSH; - info->rx_count = NSHL; - return; - } - - - *skb_put(info->rx_skb, 1) = inb(iobase + UART_RX); - nsh = (nsh_t *)info->rx_skb->data; - - info->rx_count--; - - - if (info->rx_count == 0) { - - switch (info->rx_state) { - case RECV_WAIT_NSH: - info->rx_state = RECV_WAIT_DATA; - info->rx_count = nsh->len + (nsh->len & 0x0001); - break; - case RECV_WAIT_DATA: - info->rx_skb->pkt_type = nsh->type; - - /* remove PAD byte if it exists */ - if (nsh->len & 0x0001) { - info->rx_skb->tail--; - info->rx_skb->len--; - } - - /* remove NSH */ - skb_pull(info->rx_skb, NSHL); - - - switch (info->rx_skb->pkt_type) { - case 0x80: - /* control data for the Nokia Card */ - dtl1_control(info, info->rx_skb); - break; - case 0x82: - case 0x83: - case 0x84: - /* send frame to the HCI layer */ - info->rx_skb->dev = (void *)&(info->hdev); - info->rx_skb->pkt_type &= 0x0f; - hci_recv_frame(info->rx_skb); - break; - default: - /* unknown packet */ - printk(KERN_WARNING "dtl1_cs: Unknown HCI packet with type 0x%02x received.\n", info->rx_skb->pkt_type); - kfree_skb(info->rx_skb); - break; - } - - - info->rx_state = RECV_WAIT_NSH; - info->rx_count = NSHL; - info->rx_skb = NULL; - break; - } - - } - - - /* Make sure we don't stay here to long */ - if (boguscount++ > 32) - break; - - } while (inb(iobase + UART_LSR) & UART_LSR_DR); - - -} - - -void dtl1_interrupt(int irq, void *dev_inst, struct pt_regs *regs) { - - dtl1_info_t *info = dev_inst; - unsigned int iobase; - unsigned char msr; - int boguscount = 0; - int iir, lsr; - - - if (!info) { - printk(KERN_WARNING "dtl1_cs: Call of irq %d for unknown device.\n", irq); - return; - } - - - iobase = info->link.io.BasePort1; - - - spin_lock(&(info->lock)); - - iir = inb(iobase + UART_IIR) & UART_IIR_ID; - while (iir) { - - /* Clear interrupt */ - lsr = inb(iobase + UART_LSR); - - switch (iir) { - case UART_IIR_RLSI: - printk(KERN_NOTICE "dtl1_cs: RLSI\n"); - break; - case UART_IIR_RDI: - /* Receive interrupt */ - dtl1_receive(info); - break; - case UART_IIR_THRI: - if (lsr & UART_LSR_THRE) { - /* Transmitter ready for data */ - dtl1_write_wakeup(info); - } - break; - default: - printk(KERN_NOTICE "dtl1_cs: Unhandled IIR=%#x\n", iir); - break; - } - - /* Make sure we don't stay here to long */ - if (boguscount++ > 100) - break; - - iir = inb(iobase + UART_IIR) & UART_IIR_ID; - - } - - - msr = inb(iobase + UART_MSR); - - if (info->ri_latch ^ (msr & UART_MSR_RI)) { - info->ri_latch = msr & UART_MSR_RI; - clear_bit(XMIT_WAITING, &(info->tx_state)); - dtl1_write_wakeup(info); - } - - spin_unlock(&(info->lock)); +static int dtl1_write(unsigned int iobase, int fifo_size, __u8 *buf, int len) +{ + int actual = 0; + + /* Tx FIFO should be empty */ + if (!(inb(iobase + UART_LSR) & UART_LSR_THRE)) + return 0; + + /* Fill FIFO with current frame */ + while ((fifo_size-- > 0) && (actual < len)) { + /* Transmit next byte */ + outb(buf[actual], iobase + UART_TX); + actual++; + } + + return actual; +} + + +static void dtl1_write_wakeup(dtl1_info_t *info) +{ + if (!info) { + printk(KERN_WARNING "dtl1_cs: Call of write_wakeup for unknown device.\n"); + return; + } + + if (test_bit(XMIT_WAITING, &(info->tx_state))) { + set_bit(XMIT_WAKEUP, &(info->tx_state)); + return; + } + + if (test_and_set_bit(XMIT_SENDING, &(info->tx_state))) { + set_bit(XMIT_WAKEUP, &(info->tx_state)); + return; + } + + do { + register unsigned int iobase = info->link.io.BasePort1; + register struct sk_buff *skb; + register int len; + + clear_bit(XMIT_WAKEUP, &(info->tx_state)); + + if (!(info->link.state & DEV_PRESENT)) + return; + + if (!(skb = skb_dequeue(&(info->txq)))) + break; + + /* Send frame */ + len = dtl1_write(iobase, 32, skb->data, skb->len); + + if (len == skb->len) { + set_bit(XMIT_WAITING, &(info->tx_state)); + kfree_skb(skb); + } else { + skb_pull(skb, len); + skb_queue_head(&(info->txq), skb); + } + + info->hdev.stat.byte_tx += len; + + } while (test_bit(XMIT_WAKEUP, &(info->tx_state))); + + clear_bit(XMIT_SENDING, &(info->tx_state)); +} + + +static void dtl1_control(dtl1_info_t *info, struct sk_buff *skb) +{ + u8 flowmask = *(u8 *)skb->data; + int i; + + printk(KERN_INFO "dtl1_cs: Nokia control data = "); + for (i = 0; i < skb->len; i++) { + printk("%02x ", skb->data[i]); + } + printk("\n"); + + /* transition to active state */ + if (((info->flowmask & 0x07) == 0) && ((flowmask & 0x07) != 0)) { + clear_bit(XMIT_WAITING, &(info->tx_state)); + dtl1_write_wakeup(info); + } + + info->flowmask = flowmask; + + kfree_skb(skb); +} + + +static void dtl1_receive(dtl1_info_t *info) +{ + unsigned int iobase; + nsh_t *nsh; + int boguscount = 0; + + if (!info) { + printk(KERN_WARNING "dtl1_cs: Call of receive for unknown device.\n"); + return; + } + + iobase = info->link.io.BasePort1; + + do { + info->hdev.stat.byte_rx++; + + /* Allocate packet */ + if (info->rx_skb == NULL) + if (!(info->rx_skb = bluez_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) { + printk(KERN_WARNING "dtl1_cs: Can't allocate mem for new packet.\n"); + info->rx_state = RECV_WAIT_NSH; + info->rx_count = NSHL; + return; + } + + *skb_put(info->rx_skb, 1) = inb(iobase + UART_RX); + nsh = (nsh_t *)info->rx_skb->data; + + info->rx_count--; + + if (info->rx_count == 0) { + + switch (info->rx_state) { + case RECV_WAIT_NSH: + info->rx_state = RECV_WAIT_DATA; + info->rx_count = nsh->len + (nsh->len & 0x0001); + break; + case RECV_WAIT_DATA: + info->rx_skb->pkt_type = nsh->type; + + /* remove PAD byte if it exists */ + if (nsh->len & 0x0001) { + info->rx_skb->tail--; + info->rx_skb->len--; + } + + /* remove NSH */ + skb_pull(info->rx_skb, NSHL); + + switch (info->rx_skb->pkt_type) { + case 0x80: + /* control data for the Nokia Card */ + dtl1_control(info, info->rx_skb); + break; + case 0x82: + case 0x83: + case 0x84: + /* send frame to the HCI layer */ + info->rx_skb->dev = (void *)&(info->hdev); + info->rx_skb->pkt_type &= 0x0f; + hci_recv_frame(info->rx_skb); + break; + default: + /* unknown packet */ + printk(KERN_WARNING "dtl1_cs: Unknown HCI packet with type 0x%02x received.\n", info->rx_skb->pkt_type); + kfree_skb(info->rx_skb); + break; + } + + info->rx_state = RECV_WAIT_NSH; + info->rx_count = NSHL; + info->rx_skb = NULL; + break; + } + + } + + /* Make sure we don't stay here to long */ + if (boguscount++ > 32) + break; + + } while (inb(iobase + UART_LSR) & UART_LSR_DR); +} + + +void dtl1_interrupt(int irq, void *dev_inst, struct pt_regs *regs) +{ + dtl1_info_t *info = dev_inst; + unsigned int iobase; + unsigned char msr; + int boguscount = 0; + int iir, lsr; + + if (!info) { + printk(KERN_WARNING "dtl1_cs: Call of irq %d for unknown device.\n", irq); + return; + } + + iobase = info->link.io.BasePort1; + + spin_lock(&(info->lock)); + + iir = inb(iobase + UART_IIR) & UART_IIR_ID; + while (iir) { + + /* Clear interrupt */ + lsr = inb(iobase + UART_LSR); + + switch (iir) { + case UART_IIR_RLSI: + printk(KERN_NOTICE "dtl1_cs: RLSI\n"); + break; + case UART_IIR_RDI: + /* Receive interrupt */ + dtl1_receive(info); + break; + case UART_IIR_THRI: + if (lsr & UART_LSR_THRE) { + /* Transmitter ready for data */ + dtl1_write_wakeup(info); + } + break; + default: + printk(KERN_NOTICE "dtl1_cs: Unhandled IIR=%#x\n", iir); + break; + } + + /* Make sure we don't stay here to long */ + if (boguscount++ > 100) + break; + + iir = inb(iobase + UART_IIR) & UART_IIR_ID; + + } + + msr = inb(iobase + UART_MSR); + + if (info->ri_latch ^ (msr & UART_MSR_RI)) { + info->ri_latch = msr & UART_MSR_RI; + clear_bit(XMIT_WAITING, &(info->tx_state)); + dtl1_write_wakeup(info); + } + spin_unlock(&(info->lock)); } @@ -401,107 +371,94 @@ /* ======================== HCI interface ======================== */ -static int dtl1_hci_open(struct hci_dev *hdev) { - - set_bit(HCI_RUNNING, &(hdev->flags)); - - - return 0; +static int dtl1_hci_open(struct hci_dev *hdev) +{ + set_bit(HCI_RUNNING, &(hdev->flags)); + return 0; } -static int dtl1_hci_flush(struct hci_dev *hdev) { - - dtl1_info_t *info = (dtl1_info_t *)(hdev->driver_data); - - - /* Drop TX queue */ - skb_queue_purge(&(info->txq)); - +static int dtl1_hci_flush(struct hci_dev *hdev) +{ + dtl1_info_t *info = (dtl1_info_t *)(hdev->driver_data); - return 0; + /* Drop TX queue */ + skb_queue_purge(&(info->txq)); + return 0; } -static int dtl1_hci_close(struct hci_dev *hdev) { +static int dtl1_hci_close(struct hci_dev *hdev) +{ + if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags))) + return 0; - if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags))) - return 0; - - - dtl1_hci_flush(hdev); - - - return 0; + dtl1_hci_flush(hdev); + return 0; } -static int dtl1_hci_send_frame(struct sk_buff *skb) { - - dtl1_info_t *info; - struct hci_dev* hdev = (struct hci_dev *)(skb->dev); - struct sk_buff *s; - nsh_t nsh; - +static int dtl1_hci_send_frame(struct sk_buff *skb) +{ + dtl1_info_t *info; + struct hci_dev *hdev = (struct hci_dev *)(skb->dev); + struct sk_buff *s; + nsh_t nsh; - if (!hdev) { - printk(KERN_WARNING "dtl1_cs: Frame for unknown HCI device (hdev=NULL)."); - return -ENODEV; - } + if (!hdev) { + printk(KERN_WARNING "dtl1_cs: Frame for unknown HCI device (hdev=NULL)."); + return -ENODEV; + } - info = (dtl1_info_t *)(hdev->driver_data); + info = (dtl1_info_t *)(hdev->driver_data); + switch (skb->pkt_type) { + case HCI_COMMAND_PKT: + hdev->stat.cmd_tx++; + nsh.type = 0x81; + break; + case HCI_ACLDATA_PKT: + hdev->stat.acl_tx++; + nsh.type = 0x82; + break; + case HCI_SCODATA_PKT: + hdev->stat.sco_tx++; + nsh.type = 0x83; + break; + }; - switch (skb->pkt_type) { - case HCI_COMMAND_PKT: - hdev->stat.cmd_tx++; - nsh.type = 0x81; - break; - case HCI_ACLDATA_PKT: - hdev->stat.acl_tx++; - nsh.type = 0x82; - break; - case HCI_SCODATA_PKT: - hdev->stat.sco_tx++; - nsh.type = 0x83; - break; - }; + nsh.zero = 0; + nsh.len = skb->len; - nsh.zero = 0; - nsh.len = skb->len; + s = bluez_skb_alloc(NSHL + skb->len + 1, GFP_ATOMIC); + skb_reserve(s, NSHL); + memcpy(skb_put(s, skb->len), skb->data, skb->len); + if (skb->len & 0x0001) + *skb_put(s, 1) = 0; /* PAD */ - s = bluez_skb_alloc(NSHL + skb->len + 1, GFP_ATOMIC); - skb_reserve(s, NSHL); - memcpy(skb_put(s, skb->len), skb->data, skb->len); - if (skb->len & 0x0001) - *skb_put(s, 1) = 0; /* PAD */ + /* Prepend skb with Nokia frame header and queue */ + memcpy(skb_push(s, NSHL), &nsh, NSHL); + skb_queue_tail(&(info->txq), s); - /* Prepend skb with Nokia frame header and queue */ - memcpy(skb_push(s, NSHL), &nsh, NSHL); - skb_queue_tail(&(info->txq), s); + dtl1_write_wakeup(info); + kfree_skb(skb); - dtl1_write_wakeup(info); - - kfree_skb(skb); - - - return 0; - + return 0; } -static void dtl1_hci_destruct(struct hci_dev *hdev) { +static void dtl1_hci_destruct(struct hci_dev *hdev) +{ } -static int dtl1_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) { - - return -ENOIOCTLCMD; - +static int dtl1_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) +{ + return -ENOIOCTLCMD; } @@ -509,101 +466,91 @@ /* ======================== Card services HCI interaction ======================== */ -int dtl1_open(dtl1_info_t *info) { +int dtl1_open(dtl1_info_t *info) +{ + unsigned long flags; + unsigned int iobase = info->link.io.BasePort1; + struct hci_dev *hdev; - unsigned long flags; - unsigned int iobase = info->link.io.BasePort1; - struct hci_dev *hdev; + spin_lock_init(&(info->lock)); + skb_queue_head_init(&(info->txq)); - spin_lock_init(&(info->lock)); + info->rx_state = RECV_WAIT_NSH; + info->rx_count = NSHL; + info->rx_skb = NULL; - skb_queue_head_init(&(info->txq)); + set_bit(XMIT_WAITING, &(info->tx_state)); - info->rx_state = RECV_WAIT_NSH; - info->rx_count = NSHL; - info->rx_skb = NULL; + spin_lock_irqsave(&(info->lock), flags); - set_bit(XMIT_WAITING, &(info->tx_state)); + /* Reset UART */ + outb(0, iobase + UART_MCR); + /* Turn off interrupts */ + outb(0, iobase + UART_IER); - spin_lock_irqsave(&(info->lock), flags); + /* Initialize UART */ + outb(UART_LCR_WLEN8, iobase + UART_LCR); /* Reset DLAB */ + outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase + UART_MCR); - /* Reset UART */ - outb(0, iobase + UART_MCR); + info->ri_latch = inb(info->link.io.BasePort1 + UART_MSR) & UART_MSR_RI; - /* Turn off interrupts */ - outb(0, iobase + UART_IER); + /* Turn on interrupts */ + outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER); - /* Initialize UART */ - outb(UART_LCR_WLEN8, iobase + UART_LCR); /* Reset DLAB */ - outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase + UART_MCR); + spin_unlock_irqrestore(&(info->lock), flags); - info->ri_latch = inb(info->link.io.BasePort1 + UART_MSR) & UART_MSR_RI; + /* Timeout before it is safe to send the first HCI packet */ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ * 2); - /* Turn on interrupts */ - outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER); - spin_unlock_irqrestore(&(info->lock), flags); + /* Initialize and register HCI device */ + hdev = &(info->hdev); - /* Timeout before it is safe to send the first HCI packet */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ * 2); + hdev->type = HCI_PCCARD; + hdev->driver_data = info; + hdev->open = dtl1_hci_open; + hdev->close = dtl1_hci_close; + hdev->flush = dtl1_hci_flush; + hdev->send = dtl1_hci_send_frame; + hdev->destruct = dtl1_hci_destruct; + hdev->ioctl = dtl1_hci_ioctl; - /* Initialize and register HCI device */ - - hdev = &(info->hdev); - - hdev->type = HCI_PCCARD; - hdev->driver_data = info; - - hdev->open = dtl1_hci_open; - hdev->close = dtl1_hci_close; - hdev->flush = dtl1_hci_flush; - hdev->send = dtl1_hci_send_frame; - hdev->destruct = dtl1_hci_destruct; - hdev->ioctl = dtl1_hci_ioctl; - - if (hci_register_dev(hdev) < 0) { - printk(KERN_WARNING "dtl1_cs: Can't register HCI device %s.\n", hdev->name); - return -ENODEV; - } - - - return 0; + if (hci_register_dev(hdev) < 0) { + printk(KERN_WARNING "dtl1_cs: Can't register HCI device %s.\n", hdev->name); + return -ENODEV; + } + return 0; } -int dtl1_close(dtl1_info_t *info) { - - unsigned long flags; - unsigned int iobase = info->link.io.BasePort1; - struct hci_dev *hdev = &(info->hdev); - - - dtl1_hci_close(hdev); - - - spin_lock_irqsave(&(info->lock), flags); - - /* Reset UART */ - outb(0, iobase + UART_MCR); +int dtl1_close(dtl1_info_t *info) +{ + unsigned long flags; + unsigned int iobase = info->link.io.BasePort1; + struct hci_dev *hdev = &(info->hdev); - /* Turn off interrupts */ - outb(0, iobase + UART_IER); + dtl1_hci_close(hdev); - spin_unlock_irqrestore(&(info->lock), flags); + spin_lock_irqsave(&(info->lock), flags); + /* Reset UART */ + outb(0, iobase + UART_MCR); - if (hci_unregister_dev(hdev) < 0) - printk(KERN_WARNING "dtl1_cs: Can't unregister HCI device %s.\n", hdev->name); + /* Turn off interrupts */ + outb(0, iobase + UART_IER); + spin_unlock_irqrestore(&(info->lock), flags); - return 0; + if (hci_unregister_dev(hdev) < 0) + printk(KERN_WARNING "dtl1_cs: Can't unregister HCI device %s.\n", hdev->name); + return 0; } @@ -611,291 +558,267 @@ /* ======================== Card services ======================== */ -static void cs_error(client_handle_t handle, int func, int ret) { - - error_info_t err = { func, ret }; - - - CardServices(ReportError, handle, &err); - -} - - -dev_link_t *dtl1_attach(void) { - - dtl1_info_t *info; - client_reg_t client_reg; - dev_link_t *link; - int i, ret; - - - /* Create new info 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 = &dtl1_release; - link->release.data = (u_long)link; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.NumPorts1 = 8; - 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 = dtl1_interrupt; - link->irq.Instance = info; - - link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; - link->conf.IntType = INT_MEMORY_AND_IO; - - - /* Register with Card Services */ - link->next = dev_list; - dev_list = link; - client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; - client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &dtl1_event; - client_reg.Version = 0x0210; - client_reg.event_callback_args.client_data = link; - - ret = CardServices(RegisterClient, &link->handle, &client_reg); - if (ret != CS_SUCCESS) { - cs_error(link->handle, RegisterClient, ret); - dtl1_detach(link); - return NULL; - } - - - return link; - -} - - -void dtl1_detach(dev_link_t *link) { - - dtl1_info_t *info = link->priv; - dev_link_t **linkp; - int ret; - - - /* Locate device structure */ - for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) - if (*linkp == link) - break; - - if (*linkp == NULL) - return; - - - del_timer(&link->release); - if (link->state & DEV_CONFIG) - dtl1_release((u_long)link); - - - if (link->handle) { - ret = CardServices(DeregisterClient, link->handle); - if (ret != CS_SUCCESS) - cs_error(link->handle, DeregisterClient, ret); - } - - - /* Unlink device structure, free bits */ - *linkp = link->next; - - kfree(info); - -} - - -static int get_tuple(int fn, client_handle_t handle, tuple_t *tuple, - cisparse_t *parse) { - - int i; - - - i = CardServices(fn, handle, tuple); - if (i != CS_SUCCESS) - return CS_NO_MORE_ITEMS; - - i = CardServices(GetTupleData, handle, tuple); - if (i != CS_SUCCESS) - return i; - - return CardServices(ParseTuple, handle, tuple, parse); +static void cs_error(client_handle_t handle, int func, int ret) +{ + error_info_t err = { func, ret }; + + CardServices(ReportError, handle, &err); +} + + +dev_link_t *dtl1_attach(void) +{ + dtl1_info_t *info; + client_reg_t client_reg; + dev_link_t *link; + int i, ret; + + /* Create new info 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 = &dtl1_release; + link->release.data = (u_long)link; + link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + link->io.NumPorts1 = 8; + 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 = dtl1_interrupt; + link->irq.Instance = info; + + link->conf.Attributes = CONF_ENABLE_IRQ; + link->conf.Vcc = 50; + link->conf.IntType = INT_MEMORY_AND_IO; + + /* Register with Card Services */ + link->next = dev_list; + dev_list = link; + client_reg.dev_info = &dev_info; + client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; + client_reg.EventMask = + CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | + CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | + CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; + client_reg.event_handler = &dtl1_event; + client_reg.Version = 0x0210; + client_reg.event_callback_args.client_data = link; + + ret = CardServices(RegisterClient, &link->handle, &client_reg); + if (ret != CS_SUCCESS) { + cs_error(link->handle, RegisterClient, ret); + dtl1_detach(link); + return NULL; + } + + return link; +} + + +void dtl1_detach(dev_link_t *link) +{ + dtl1_info_t *info = link->priv; + dev_link_t **linkp; + int ret; + + /* Locate device structure */ + for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) + if (*linkp == link) + break; + + if (*linkp == NULL) + return; + + del_timer(&link->release); + if (link->state & DEV_CONFIG) + dtl1_release((u_long)link); + + if (link->handle) { + ret = CardServices(DeregisterClient, link->handle); + if (ret != CS_SUCCESS) + cs_error(link->handle, DeregisterClient, ret); + } + + /* Unlink device structure, free bits */ + *linkp = link->next; + + kfree(info); +} + + +static int get_tuple(int fn, client_handle_t handle, tuple_t *tuple, cisparse_t *parse) +{ + int i; + + i = CardServices(fn, handle, tuple); + if (i != CS_SUCCESS) + return CS_NO_MORE_ITEMS; + + i = CardServices(GetTupleData, handle, tuple); + if (i != CS_SUCCESS) + return i; + return CardServices(ParseTuple, handle, tuple, parse); } #define first_tuple(a, b, c) get_tuple(GetFirstTuple, a, b, c) #define next_tuple(a, b, c) get_tuple(GetNextTuple, a, b, c) -void dtl1_config(dev_link_t *link) { - - client_handle_t handle = link->handle; - dtl1_info_t *info = link->priv; - tuple_t tuple; - u_short buf[256]; - cisparse_t parse; - cistpl_cftable_entry_t *cf = &parse.cftable_entry; - config_info_t config; - int i, last_ret, last_fn; - - - tuple.TupleData = (cisdata_t *)buf; - tuple.TupleOffset = 0; - tuple.TupleDataMax = 255; - tuple.Attributes = 0; - - /* Get configuration register information */ - tuple.DesiredTuple = CISTPL_CONFIG; - last_ret = first_tuple(handle, &tuple, &parse); - if (last_ret != CS_SUCCESS) { - last_fn = ParseTuple; - goto cs_failed; - } - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; - - - /* Configure card */ - link->state |= DEV_CONFIG; - i = CardServices(GetConfigurationInfo, handle, &config); - link->conf.Vcc = config.Vcc; - - tuple.TupleData = (cisdata_t *)buf; - tuple.TupleOffset = 0; tuple.TupleDataMax = 255; - tuple.Attributes = 0; - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - - /* Look for a generic full-sized window */ - link->io.NumPorts1 = 8; - i = first_tuple(handle, &tuple, &parse); - while (i != CS_NO_MORE_ITEMS) { - if ((i == CS_SUCCESS) && (cf->io.nwin == 1) && (cf->io.win[0].len > 8)) { - link->conf.ConfigIndex = cf->index; - link->io.BasePort1 = cf->io.win[0].base; - link->io.NumPorts1 = cf->io.win[0].len; /*yo*/ - link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK; - i = CardServices(RequestIO, link->handle, &link->io); - if (i == CS_SUCCESS) - break; - } - i = next_tuple(handle, &tuple, &parse); - } - - if (i != CS_SUCCESS) { - cs_error(link->handle, RequestIO, i); - goto failed; - } - - i = CardServices(RequestIRQ, link->handle, &link->irq); - if (i != CS_SUCCESS) { - cs_error(link->handle, RequestIRQ, i); - link->irq.AssignedIRQ = 0; - } - - i = CardServices(RequestConfiguration, link->handle, &link->conf); - if (i != CS_SUCCESS) { - cs_error(link->handle, RequestConfiguration, i); - goto failed; - } - - - MOD_INC_USE_COUNT; - - if (dtl1_open(info) != 0) - goto failed; - - - link->dev = &info->node; - link->state &= ~DEV_CONFIG_PENDING; - - - return; +void dtl1_config(dev_link_t *link) +{ + client_handle_t handle = link->handle; + dtl1_info_t *info = link->priv; + tuple_t tuple; + u_short buf[256]; + cisparse_t parse; + cistpl_cftable_entry_t *cf = &parse.cftable_entry; + config_info_t config; + int i, last_ret, last_fn; + + tuple.TupleData = (cisdata_t *)buf; + tuple.TupleOffset = 0; + tuple.TupleDataMax = 255; + tuple.Attributes = 0; + + /* Get configuration register information */ + tuple.DesiredTuple = CISTPL_CONFIG; + last_ret = first_tuple(handle, &tuple, &parse); + if (last_ret != CS_SUCCESS) { + last_fn = ParseTuple; + goto cs_failed; + } + link->conf.ConfigBase = parse.config.base; + link->conf.Present = parse.config.rmask[0]; + + /* Configure card */ + link->state |= DEV_CONFIG; + i = CardServices(GetConfigurationInfo, handle, &config); + link->conf.Vcc = config.Vcc; + + tuple.TupleData = (cisdata_t *)buf; + tuple.TupleOffset = 0; + tuple.TupleDataMax = 255; + tuple.Attributes = 0; + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + + /* Look for a generic full-sized window */ + link->io.NumPorts1 = 8; + i = first_tuple(handle, &tuple, &parse); + while (i != CS_NO_MORE_ITEMS) { + if ((i == CS_SUCCESS) && (cf->io.nwin == 1) && (cf->io.win[0].len > 8)) { + link->conf.ConfigIndex = cf->index; + link->io.BasePort1 = cf->io.win[0].base; + link->io.NumPorts1 = cf->io.win[0].len; /*yo */ + link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK; + i = CardServices(RequestIO, link->handle, &link->io); + if (i == CS_SUCCESS) + break; + } + i = next_tuple(handle, &tuple, &parse); + } + + if (i != CS_SUCCESS) { + cs_error(link->handle, RequestIO, i); + goto failed; + } + + i = CardServices(RequestIRQ, link->handle, &link->irq); + if (i != CS_SUCCESS) { + cs_error(link->handle, RequestIRQ, i); + link->irq.AssignedIRQ = 0; + } + + i = CardServices(RequestConfiguration, link->handle, &link->conf); + if (i != CS_SUCCESS) { + cs_error(link->handle, RequestConfiguration, i); + goto failed; + } + + MOD_INC_USE_COUNT; + + if (dtl1_open(info) != 0) + goto failed; + + strcpy(info->node.dev_name, info->hdev.name); + link->dev = &info->node; + link->state &= ~DEV_CONFIG_PENDING; + return; cs_failed: - cs_error(link->handle, last_fn, last_ret); -failed: - dtl1_release((u_long)link); + cs_error(link->handle, last_fn, last_ret); +failed: + dtl1_release((u_long)link); } -void dtl1_release(u_long arg) { - - dev_link_t *link = (dev_link_t *)arg; - dtl1_info_t *info = link->priv; - - - if (link->state & DEV_PRESENT) - dtl1_close(info); - - MOD_DEC_USE_COUNT; - - - link->dev = NULL; - - CardServices(ReleaseConfiguration, link->handle); - CardServices(ReleaseIO, link->handle, &link->io); - CardServices(ReleaseIRQ, link->handle, &link->irq); - - link->state &= ~DEV_CONFIG; - +void dtl1_release(u_long arg) +{ + dev_link_t *link = (dev_link_t *)arg; + dtl1_info_t *info = link->priv; + + if (link->state & DEV_PRESENT) + dtl1_close(info); + + MOD_DEC_USE_COUNT; + + link->dev = NULL; + + CardServices(ReleaseConfiguration, link->handle); + CardServices(ReleaseIO, link->handle, &link->io); + CardServices(ReleaseIRQ, link->handle, &link->irq); + + link->state &= ~DEV_CONFIG; } -int dtl1_event(event_t event, int priority, event_callback_args_t *args) { - - dev_link_t *link = args->client_data; - dtl1_info_t *info = link->priv; - - - switch (event) { - case CS_EVENT_CARD_REMOVAL: - link->state &= ~DEV_PRESENT; - if (link->state & DEV_CONFIG) { - dtl1_close(info); - mod_timer(&link->release, jiffies + HZ/20); - } - break; - case CS_EVENT_CARD_INSERTION: - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - dtl1_config(link); - break; - case CS_EVENT_PM_SUSPEND: - link->state |= DEV_SUSPEND; - /* Fall through... */ - case CS_EVENT_RESET_PHYSICAL: - if (link->state & DEV_CONFIG) - CardServices(ReleaseConfiguration, link->handle); - break; - case CS_EVENT_PM_RESUME: - link->state &= ~DEV_SUSPEND; - /* Fall through... */ - case CS_EVENT_CARD_RESET: - if (DEV_OK(link)) - CardServices(RequestConfiguration, link->handle, &link->conf); - break; - } - - - return 0; +int dtl1_event(event_t event, int priority, event_callback_args_t *args) +{ + dev_link_t *link = args->client_data; + dtl1_info_t *info = link->priv; + + switch (event) { + case CS_EVENT_CARD_REMOVAL: + link->state &= ~DEV_PRESENT; + if (link->state & DEV_CONFIG) { + dtl1_close(info); + mod_timer(&link->release, jiffies + HZ / 20); + } + break; + case CS_EVENT_CARD_INSERTION: + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + dtl1_config(link); + break; + case CS_EVENT_PM_SUSPEND: + link->state |= DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_RESET_PHYSICAL: + if (link->state & DEV_CONFIG) + CardServices(ReleaseConfiguration, link->handle); + break; + case CS_EVENT_PM_RESUME: + link->state &= ~DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_CARD_RESET: + if (DEV_OK(link)) + CardServices(RequestConfiguration, link->handle, &link->conf); + break; + } + return 0; } @@ -903,33 +826,29 @@ /* ======================== Module initialization ======================== */ -int __init init_dtl1_cs(void) { +int __init init_dtl1_cs(void) +{ + servinfo_t serv; + int err; - servinfo_t serv; - int err; + CardServices(GetCardServicesInfo, &serv); + if (serv.Revision != CS_RELEASE_CODE) { + printk(KERN_NOTICE "dtl1_cs: Card Services release does not match!\n"); + return -1; + } + err = register_pccard_driver(&dev_info, &dtl1_attach, &dtl1_detach); - CardServices(GetCardServicesInfo, &serv); - if (serv.Revision != CS_RELEASE_CODE) { - printk(KERN_NOTICE "dtl1_cs: Card Services release does not match!\n"); - return -1; - } - - - err = register_pccard_driver(&dev_info, &dtl1_attach, &dtl1_detach); - - - return err; - + return err; } -void __exit exit_dtl1_cs(void) { - - unregister_pccard_driver(&dev_info); - while (dev_list != NULL) - dtl1_detach(dev_list); +void __exit exit_dtl1_cs(void) +{ + unregister_pccard_driver(&dev_info); + while (dev_list != NULL) + dtl1_detach(dev_list); } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/bluetooth/Makefile linux.19rc3-ac4/drivers/bluetooth/Makefile --- linux.19rc3/drivers/bluetooth/Makefile 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/drivers/bluetooth/Makefile 2002-07-29 13:58:39.000000000 +0100 @@ -14,6 +14,8 @@ uart-$(CONFIG_BLUEZ_HCIUART_H4) += hci_h4.o obj-$(CONFIG_BLUEZ_HCIDTL1) += dtl1_cs.o +obj-$(CONFIG_BLUEZ_HCIBT3C) += bt3c_cs.o +obj-$(CONFIG_BLUEZ_HCIBLUECARD) += bluecard_cs.o include $(TOPDIR)/Rules.make diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/agp/agpgart_be.c linux.19rc3-ac4/drivers/char/agp/agpgart_be.c --- linux.19rc3/drivers/char/agp/agpgart_be.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/agp/agpgart_be.c 2002-07-29 13:58:39.000000000 +0100 @@ -1406,7 +1406,7 @@ /* Intel 815 chipsets have a _weird_ APSIZE register with only * one non-reserved bit, so mask the others out ... */ if (agp_bridge.type == INTEL_I815) - temp &= (1 << 3); + temp &= (1 << 3); values = A_SIZE_8(agp_bridge.aperture_sizes); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/amd76x_pm.c linux.19rc3-ac4/drivers/char/amd76x_pm.c --- linux.19rc3/drivers/char/amd76x_pm.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/amd76x_pm.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,398 @@ +/* + * Processor idle mode module for AMD SMP 760MP(X) based systems + * + * Copyright (C) 2002 Tony Lindgren + * Johnathan Hicks (768 support) + * + * Using this module saves about 70 - 90W of energy in the idle mode compared + * to the default idle mode. Waking up from the idle mode is fast to keep the + * system response time good. Currently no CPU load calculation is done, the + * system exits the idle mode if the idle function runs twice on the same + * processor in a row. This only works on SMP systems, but maybe the idle mode + * enabling can be integrated to ACPI to provide C2 mode at some point. + * + * NOTE: Currently there's a bug somewhere where the reading the + * P_LVL2 for the first time causes the system to sleep instead of + * idling. This means that you need to hit the power button once to + * wake the system after loading the module for the first time after + * reboot. After that the system idles as supposed. + * + * + * Influenced by Vcool, and LVCool. Rewrote everything from scratch to + * use the PCI features in Linux, and to support SMP systems. + * + * Currently only tested on a TYAN S2460 (760MP) system (Tony) and an + * ASUS A7M266-D (760MPX) system (Johnathan). Adding support for other Athlon + * SMP or single processor systems should be easy if desired. + * + * This software is licensed under GNU General Public License Version 2 + * as specified in file COPYING in the Linux kernel source tree main + * directory. + */ + +#include +#include +#include +#include +#include +#include + +#include "amd76x_pm.h" + +extern void default_idle(void); +static void amd_smp_idle(void); +static int amd_idle_main(void); +static int __devinit amd_nb_init(struct pci_dev *pdev, + const struct pci_device_id *ent); +static void amd_nb_remove(struct pci_dev *pdev); +static int __devinit amd_sb_init(struct pci_dev *pdev, + const struct pci_device_id *ent); +static void amd_sb_remove(struct pci_dev *pdev); + +#define DEBUG 1 +#define VERSION "20020702" + +static struct pci_dev *pdev_nb; +static struct pci_dev *pdev_sb; + +struct idle_cfg { + unsigned int status_reg; + unsigned int idle_reg; + unsigned int slp_reg; + unsigned int resume_reg; + void (*orig_idle) (void); + void (*curr_idle) (void); + int last_pr; +}; +static struct idle_cfg amd_idle_cfg; + +struct cpu_idle_state { + int idle; + int count; +}; +static struct cpu_idle_state prs[2]; + +static struct pci_device_id amd_nb_tbl[] __devinitdata = { + {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C, PCI_ANY_ID, PCI_ANY_ID,}, + {0,} +}; + +static struct pci_device_id amd_sb_tbl[] __devinitdata = { + {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413, PCI_ANY_ID, PCI_ANY_ID,}, + {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7443, PCI_ANY_ID, PCI_ANY_ID,}, + {0,} +}; + +static struct pci_driver amd_nb_driver = { + name:"amd-smp-idle-nb", + id_table:amd_nb_tbl, + probe:amd_nb_init, + remove:__devexit_p(amd_nb_remove), +}; + +static struct pci_driver amd_sb_driver = { + name:"amd-smp-idle-sb", + id_table:amd_sb_tbl, + probe:amd_sb_init, + remove:__devexit_p(amd_sb_remove), +}; + +static int __devinit +amd_nb_init(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + pdev_nb = pdev; + printk(KERN_INFO "amd-smp-idle: Initializing northbridge %s\n", + pdev_nb->name); + + return 0; +} + +static void __devexit +amd_nb_remove(struct pci_dev *pdev) +{ +} + +static int __devinit +amd_sb_init(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + pdev_sb = pdev; + printk(KERN_INFO "amd-smp-idle: Initializing southbridge %s\n", + pdev_sb->name); + + return 0; +} + +static void __devexit +amd_sb_remove(struct pci_dev *pdev) +{ +} + +/* + * Configures the 765 & 766 southbridges to support idle calls, and gets + * the processor idle call register location. + */ +static int +sb_idle_amd_766(int enable) +{ + unsigned int regdword; + unsigned char regbyte; + + + /* Get the address for pm status, P_LVL2, etc */ + pci_read_config_dword(pdev_sb, 0x58, ®dword); + regdword &= 0xff80; + amd_idle_cfg.status_reg = regdword + 0x00; + amd_idle_cfg.slp_reg = regdword + 0x04; + amd_idle_cfg.idle_reg = regdword + 0x14; + amd_idle_cfg.resume_reg = regdword + 0x16; + + /* Set C2 options in C3A50, page 63 in AMD-766 doc */ + pci_read_config_dword(pdev_sb, 0x50, ®dword); + + regdword &= ~((DCSTOP_EN | CPUSTP_EN | PCISTP_EN | + SUSPND_EN) << C2_REGS); + + regdword |= (STPCLK_EN << C2_REGS); /* ~ 20 Watt savings max */ + regdword |= (CPUSLP_EN << C2_REGS); /* Additional ~ 70 Watts max! */ + + pci_write_config_dword(pdev_sb, 0x50, regdword); + + /* Clear W4SG, set STPGNT and PMIOEN at C3A41 */ + pci_read_config_byte(pdev_sb, 0x41, ®byte); + regbyte &= ~(1 << 0); + regbyte |= ((1 << 1) | (1 << 7)); + pci_write_config_byte(pdev_sb, 0x41, regbyte); + + return 0; +} + +/* + * Configures the 765 & 766 southbridges to support idle calls, and gets + * the processor idle call register location. Configures C3 & POS (S1?) + * as well. + */ +static int +sb_idle_amd_768(int enable) +{ +/* Untested C3 support. The idle loop would need another delay handler for C3, + * but is would make more sense to integrate with ACPI as it already handles + * CX level transitions, but not for SMP systems. :( +*/ +/* #define USE_C3 0*/ + +/* Untested POS (S1?) support. Compare the 0x50 registers of the 766 and 768 + * and you will see why this is in here. This should also be integrated with + * ACPI. +*/ +/* #define USE_POS 0*/ /* Untested */ + + unsigned int regdword; + unsigned char regbyte; + + /* Get the address for pm status, P_LVL2, etc */ + pci_read_config_dword(pdev_sb, 0x58, ®dword); + regdword &= 0xff80; + amd_idle_cfg.status_reg = regdword + 0x00; + amd_idle_cfg.slp_reg = regdword + 0x04; + amd_idle_cfg.idle_reg = regdword + 0x14; + /*amd_idle_cfg.resume_reg = regdword + 0x16;*/ /* N/A for 768? */ + + /* Set C2/C3 options in DevB:3x4F, page 100 in AMD-768 doc */ + pci_read_config_byte(pdev_sb, 0x4F, ®byte); + regbyte |= C2EN; +#ifdef USE_C3 + regbyte |= (C3EN | ZZ_C3EN | CSLP_C3EN | CSTP_C3EN) ; +#endif + pci_write_config_byte(pdev_sb, 0x4F, regbyte); + +#ifdef USE_POS + /* I don't think this is the right place to handle POS... */ + /* Set POS options in DevB:3x50, page 101 in AMD-768 doc */ + pci_read_config_dword(pdev_sb, 0x50, ®dword); + regdword |= (POSEN | CSTP | PSTP | ASTP | DCSTP | SUSP); + regdword |= CSLP; + pci_write_config_dword(pdev_sb, 0x50, regdword); +#endif + + /* Clear W4SG, set PMIOEN at DevB:3x41, page 94 in AMD-768 doc */ + pci_read_config_byte(pdev_sb, 0x41, ®byte); + regbyte &= ~(1 << 0); + regbyte |= (1 << 7); + pci_write_config_byte(pdev_sb, 0x41, regbyte); + + return 0; +} + +/* + * Configures the northbridge to support idle calls + */ +static int +nb_idle_amd_762(int enable) +{ + unsigned int regdword; + + /* Enable STPGNT in BIU Status/Control for cpu0 */ + pci_read_config_dword(pdev_nb, 0x60, ®dword); + regdword |= (1 << 17); + pci_write_config_dword(pdev_nb, 0x60, regdword); + + /* Enable STPGNT in BIU Status/Control for cpu1 */ + pci_read_config_dword(pdev_nb, 0x68, ®dword); + regdword |= (1 << 17); + pci_write_config_dword(pdev_nb, 0x68, regdword); + + /* DRAM refresh enable */ + pci_read_config_dword(pdev_nb, 0x58, ®dword); + regdword &= ~(1 << 19); + pci_write_config_dword(pdev_nb, 0x58, regdword); + + /* Self refresh enable */ + pci_read_config_dword(pdev_nb, 0x70, ®dword); + regdword |= (1 << 18); + pci_write_config_dword(pdev_nb, 0x70, regdword); + + return 0; +} + +/* + * Idle loop for single processor systems + */ +void +amd_idle(void) +{ + // FIXME: Optionally add non-smp idle loop here +} + +/* + * Idle loop for SMP systems, supports currently only 2 processors. + * + * Note; for 2.5 folks - not pre-empt safe + */ + +static void +amd_smp_idle(void) +{ + + /* + * Exit idle mode immediately if the CPU does not change. + * Usually that means that we have some load on another CPU. + */ + if (prs[0].idle && prs[1].idle && amd_idle_cfg.last_pr == smp_processor_id()) { + prs[0].idle = 0; + prs[1].idle = 0; + amd_idle_cfg.last_pr = smp_processor_id(); + return; + } + + prs[smp_processor_id()].count++; + + /* Don't start the idle mode immediately */ + if (prs[smp_processor_id()].count >= LAZY_IDLE_DELAY) { + + /* Put the current processor into idle mode */ + prs[smp_processor_id()].idle = 1; + + /* Only idle if both processors are idle */ + if (prs[0].idle && prs[1].idle) + inb(amd_idle_cfg.idle_reg); + + prs[smp_processor_id()].count = 0; + + } + amd_idle_cfg.last_pr = smp_processor_id(); +} + +/* + * Finds and initializes the bridges, and then sets the idle function + */ +static int +amd_idle_main(void) +{ + int found; + + /* Find northbridge */ + found = pci_module_init(&amd_nb_driver); + if (found < 0) { + printk(KERN_ERR "amd-smp-idle: Could not find northbridge\n"); + return 1; + } + + /* Find southbridge */ + found = pci_module_init(&amd_sb_driver); + if (found < 0) { + printk(KERN_ERR "amd-smp-idle: Could not find southbridge\n"); + pci_unregister_driver(&amd_nb_driver); + return 1; + } + + /* Init southbridge */ + switch (pdev_sb->device) { + case PCI_DEVICE_ID_AMD_VIPER_7413: /* AMD-765 or 766 */ + sb_idle_amd_766(1); + printk(KERN_INFO "amd-smp-idle: AMD-765 or 766 southbridge initialized.\n"); + break; + case PCI_DEVICE_ID_AMD_VIPER_7443: /* AMD-768 */ + sb_idle_amd_768(1); + printk(KERN_INFO "amd-smp-idle: AMD-768 southbridge initialized.\n"); + break; + default: + printk(KERN_ERR "amd-smp-idle: No southbridge to initialize\n"); + break; + } + + /* Init northbridge and queue the new idle function */ + switch (pdev_nb->device) { + case PCI_DEVICE_ID_AMD_FE_GATE_700C: + nb_idle_amd_762(1); + printk(KERN_INFO "amd-smp-idle: AMD-762 northbridge initialized.\n"); + amd_idle_cfg.curr_idle = amd_smp_idle; + break; + default: + printk(KERN_ERR "amd-smp-idle: No northbridge to initialize\n"); + break; + } + + if (!amd_idle_cfg.curr_idle) { + printk(KERN_ERR "amd-smp-idle: Idle function not changed\n"); + return 1; + } + + amd_idle_cfg.orig_idle = pm_idle; + pm_idle = amd_idle_cfg.curr_idle; + + return 0; +} + +static int __init +amd_idle_init(void) +{ + printk(KERN_INFO "amd-smp-idle: AMD processor idle module version %s\n", + VERSION); + return amd_idle_main(); +} + +static void __exit +amd_idle_cleanup(void) +{ + pm_idle = amd_idle_cfg.orig_idle; + + /* + * FIXME: We want to wait until all CPUs have set the new + * idle function, otherwise we will oops. This may not be + * the right way to do it, but seems to work. + * + * - Best answer is going to be to ban unload, but when its debugged + * --- Alan + */ + schedule(); + mdelay(1000); + + pci_unregister_driver(&amd_nb_driver); + pci_unregister_driver(&amd_sb_driver); + +} + +MODULE_LICENSE("GPL"); +module_init(amd_idle_init); +module_exit(amd_idle_cleanup); + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/amd76x_pm.h linux.19rc3-ac4/drivers/char/amd76x_pm.h --- linux.19rc3/drivers/char/amd76x_pm.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/amd76x_pm.h 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,30 @@ +#define DCSTOP_EN (1 << 1) +#define STPCLK_EN (1 << 2) +#define CPUSTP_EN (1 << 3) +#define PCISTP_EN (1 << 4) +#define CPUSLP_EN (1 << 5) +#define SUSPND_EN (1 << 6) + +#define C2_REGS 0 +#define C3_REGS 8 +#define POS_REGS 16 + +/* C2/C3 options in DevB:3x4F, page 100 in AMD-768 doc */ +#define C2EN 1 +#define C3EN (1 << 1) +#define ZZ_C3EN (1 << 2) +#define CSLP_C3EN (1 << 3) +#define CSTP_C3EN (1 << 4) + +/* POS options in DevB:3x50, page 101 in AMD-768 doc */ +#define POSEN 1 +#define CSTP (1 << 2) +#define PSTP (1 << 3) +#define ASTP (1 << 4) +#define DCSTP (1 << 5) +#define CSLP (1 << 6) +#define SUSP (1 << 8) +#define MSRSM (1 << 14) +#define PITRSM (1 << 15) + +#define LAZY_IDLE_DELAY 800 /* 0: Best savings, 3000: More responsive */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/amd7xx_tco.c linux.19rc3-ac4/drivers/char/amd7xx_tco.c --- linux.19rc3/drivers/char/amd7xx_tco.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/amd7xx_tco.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,377 @@ +/* + * AMD 766/768 TCO Timer Driver + * (c) Copyright 2002 Zwane Mwaikambo + * All Rights Reserved. + * + * Parts from; + * Hardware driver for the AMD 768 Random Number Generator (RNG) + * (c) Copyright 2001 Red Hat Inc + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * The author(s) of this software shall not be held liable for damages + * of any nature resulting due to the use of this software. This + * software is provided AS-IS with no warranties. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define AMDTCO_MODULE_VER "build 20020601" +#define AMDTCO_MODULE_NAME "amd7xx_tco" +#define PFX AMDTCO_MODULE_NAME ": " + +#define MAX_TIMEOUT 38 /* max of 38 seconds */ + +/* pmbase registers */ +#define GLOBAL_SMI_REG 0x2a +#define TCO_EN (1 << 1) /* bit 1 in global SMI register */ +#define TCO_RELOAD_REG 0x40 /* bits 0-5 are current count, 6-7 are reserved */ +#define TCO_INITVAL_REG 0x41 /* bits 0-5 are value to load, 6-7 are reserved */ +#define TCO_TIMEOUT_MASK 0x3f +#define TCO_STATUS2_REG 0x46 +#define NDTO_STS2 (1 << 1) /* we're interested in the second timeout */ +#define BOOT_STS (1 << 2) /* will be set if NDTO_STS2 was set before reboot */ +#define TCO_CTRL1_REG 0x48 +#define TCO_HALT (1 << 11) + +static char banner[] __initdata = KERN_INFO PFX AMDTCO_MODULE_VER; +static int timeout = 38; +static u32 pmbase; /* PMxx I/O base */ +static struct pci_dev *dev; +static struct semaphore open_sem; +spinlock_t amdtco_lock; /* only for device access */ +static int expect_close = 0; + +MODULE_PARM(timeout, "i"); +MODULE_PARM_DESC(timeout, "range is 0-38 seconds, default is 38"); + +static inline int amdtco_status(void) +{ + u16 reg; + int status = 0; + + reg = inb(pmbase+TCO_CTRL1_REG); + if ((reg & TCO_HALT) == 0) + status |= WDIOF_KEEPALIVEPING; + + reg = inb(pmbase+TCO_STATUS2_REG); + if (reg & BOOT_STS) + status |= WDIOF_CARDRESET; + + return status; +} + +static inline void amdtco_ping(void) +{ + u8 reg; + + spin_lock(&amdtco_lock); + reg = inb(pmbase+TCO_RELOAD_REG); + outb(1 | reg, pmbase+TCO_RELOAD_REG); + spin_unlock(&amdtco_lock); +} + +static inline int amdtco_gettimeout(void) +{ + return inb(TCO_RELOAD_REG) & TCO_TIMEOUT_MASK; +} + +static inline void amdtco_settimeout(unsigned int timeout) +{ + u8 reg; + + spin_lock(&amdtco_lock); + reg = inb(pmbase+TCO_INITVAL_REG); + reg |= timeout & TCO_TIMEOUT_MASK; + outb(reg, pmbase+TCO_INITVAL_REG); + spin_unlock(&amdtco_lock); +} + +static inline void amdtco_global_enable(void) +{ + u16 reg; + + spin_lock(&amdtco_lock); + reg = inw(pmbase+GLOBAL_SMI_REG); + reg |= TCO_EN; + outw(reg, pmbase+GLOBAL_SMI_REG); + spin_unlock(&amdtco_lock); +} + +static inline void amdtco_enable(void) +{ + u16 reg; + + spin_lock(&amdtco_lock); + reg = inw(pmbase+TCO_CTRL1_REG); + reg &= ~TCO_HALT; + outw(reg, pmbase+TCO_CTRL1_REG); + spin_unlock(&amdtco_lock); +} + +static inline void amdtco_disable(void) +{ + u16 reg; + + spin_lock(&amdtco_lock); + reg = inw(pmbase+TCO_CTRL1_REG); + reg |= TCO_HALT; + outw(reg, pmbase+TCO_CTRL1_REG); + spin_unlock(&amdtco_lock); +} + +static int amdtco_fop_open(struct inode *inode, struct file *file) +{ + if (down_trylock(&open_sem)) + return -EBUSY; + +#ifdef CONFIG_WATCHDOG_NOWAYOUT + MOD_INC_USE_COUNT; +#endif + + if (timeout > MAX_TIMEOUT) + timeout = MAX_TIMEOUT; + + amdtco_settimeout(timeout); + amdtco_global_enable(); + amdtco_ping(); + printk(KERN_INFO PFX "Watchdog enabled, timeout = %d/%d seconds", + amdtco_gettimeout(), timeout); + + return 0; +} + + +static int amdtco_fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + int new_timeout; + int tmp; + + static struct watchdog_info ident = { + options: WDIOF_SETTIMEOUT | WDIOF_CARDRESET, + identity: "AMD 766/768" + }; + + switch (cmd) { + default: + return -ENOTTY; + + case WDIOC_GETSUPPORT: + if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof ident)) + return -EFAULT; + return 0; + + case WDIOC_GETSTATUS: + return put_user(amdtco_status(), (int *)arg); + + case WDIOC_KEEPALIVE: + amdtco_ping(); + return 0; + + case WDIOC_SETTIMEOUT: + if (get_user(new_timeout, (int *)arg)) + return -EFAULT; + + if (new_timeout < 0) + return -EINVAL; + + if (new_timeout > MAX_TIMEOUT) + new_timeout = MAX_TIMEOUT; + + timeout = new_timeout; + amdtco_settimeout(timeout); + /* fall through and return the new timeout */ + + case WDIOC_GETTIMEOUT: + return put_user(amdtco_gettimeout(), (int *)arg); + + case WDIOC_SETOPTIONS: + if (copy_from_user(&tmp, (int *)arg, sizeof tmp)) + return -EFAULT; + + if (tmp & WDIOS_DISABLECARD) + amdtco_disable(); + + if (tmp & WDIOS_ENABLECARD) + amdtco_enable(); + + return 0; + } +} + + +static int amdtco_fop_release(struct inode *inode, struct file *file) +{ + if (expect_close) { + amdtco_disable(); + printk(KERN_INFO PFX "Watchdog disabled\n"); + } else { + amdtco_ping(); + printk(KERN_CRIT PFX "Unexpected close!, timeout in %d seconds)\n", timeout); + } + + up(&open_sem); + return 0; +} + + +static ssize_t amdtco_fop_write(struct file *file, const char *data, size_t len, loff_t *ppos) +{ + if (ppos != &file->f_pos) + return -ESPIPE; + + if (len) { +#ifndef CONFIG_WATCHDOG_NOWAYOUT + size_t i; + char c; + expect_close = 0; + + for (i = 0; i != len; i++) { + if (get_user(c, data + i)) + return -EFAULT; + + if (c == 'V') + expect_close = 1; + } +#endif + amdtco_ping(); + return len; + } + + return 0; +} + + +static int amdtco_notify_sys(struct notifier_block *this, unsigned long code, void *unused) +{ + if (code == SYS_DOWN || code == SYS_HALT) + amdtco_disable(); + + return NOTIFY_DONE; +} + + +static struct notifier_block amdtco_notifier = +{ + notifier_call: amdtco_notify_sys +}; + +static struct file_operations amdtco_fops = +{ + owner: THIS_MODULE, + write: amdtco_fop_write, + ioctl: amdtco_fop_ioctl, + open: amdtco_fop_open, + release: amdtco_fop_release +}; + +static struct miscdevice amdtco_miscdev = +{ + minor: WATCHDOG_MINOR, + name: "watchdog", + fops: &amdtco_fops +}; + +static struct pci_device_id amdtco_pci_tbl[] __initdata = { + /* AMD 766 PCI_IDs here */ + { 0x1022, 0x7443, PCI_ANY_ID, PCI_ANY_ID, }, + { 0, } +}; + +MODULE_DEVICE_TABLE (pci, amdtco_pci_tbl); + +static int __init amdtco_init(void) +{ + int ret; + + sema_init(&open_sem, 1); + spin_lock_init(&amdtco_lock); + + pci_for_each_dev(dev) { + if (pci_match_device (amdtco_pci_tbl, dev) != NULL) + goto found_one; + } + + return -ENODEV; + +found_one: + + if ((ret = register_reboot_notifier(&amdtco_notifier))) { + printk(KERN_ERR PFX "Unable to register reboot notifier err = %d\n", ret); + goto out_clean; + } + + if ((ret = misc_register(&amdtco_miscdev))) { + printk(KERN_ERR PFX "Unable to register miscdev on minor %d\n", WATCHDOG_MINOR); + goto out_unreg_reboot; + } + + pci_read_config_dword(dev, 0x58, &pmbase); + pmbase &= 0x0000FF00; + + if (pmbase == 0) { + printk (KERN_ERR PFX "power management base not set\n"); + ret = -EIO; + goto out_unreg_misc; + } + + /* ret = 0; */ + printk(banner); + goto out_clean; + +out_unreg_misc: + misc_deregister(&amdtco_miscdev); +out_unreg_reboot: + unregister_reboot_notifier(&amdtco_notifier); +out_clean: + return ret; +} + +static void __exit amdtco_exit(void) +{ + misc_deregister(&amdtco_miscdev); + unregister_reboot_notifier(&amdtco_notifier); +} + + +#ifndef MODULE +static int __init amdtco_setup(char *str) +{ + int ints[4]; + + str = get_options (str, ARRAY_SIZE(ints), ints); + if (ints[0] > 0) + timeout = ints[1]; + + return 1; +} + +__setup("amd7xx_tco=", amdtco_setup); +#endif + +module_init(amdtco_init); +module_exit(amdtco_exit); + +MODULE_AUTHOR("Zwane Mwaikambo "); +MODULE_DESCRIPTION("AMD 766/768 TCO Timer Driver"); +MODULE_LICENSE("GPL"); +EXPORT_NO_SYMBOLS; + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/Config.in linux.19rc3-ac4/drivers/char/Config.in --- linux.19rc3/drivers/char/Config.in 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/Config.in 2002-07-29 13:58:39.000000000 +0100 @@ -209,6 +209,7 @@ fi fi tristate ' ZF MachZ Watchdog' CONFIG_MACHZ_WDT + dep_tristate ' AMD 766/768 TCO Timer/Watchdog' CONFIG_AMD7XX_TCO $CONFIG_EXPERIMENTAL fi endmenu @@ -227,6 +228,7 @@ if [ "$CONFIG_X86" = "y" -o "$CONFIG_IA64" = "y" ]; then dep_tristate 'Intel i8x0 Random Number Generator support' CONFIG_INTEL_RNG $CONFIG_PCI fi +dep_tristate 'AMD 76x native power management (Experimental)' CONFIG_AMD_PM768 $CONFIG_PCI tristate '/dev/nvram support' CONFIG_NVRAM tristate 'Enhanced Real Time Clock Support' CONFIG_RTC if [ "$CONFIG_IA64" = "y" ]; then @@ -251,7 +253,7 @@ fi endmenu -dep_tristate '/dev/agpgart (AGP Support)' CONFIG_AGP $CONFIG_DRM_AGP +tristate '/dev/agpgart (AGP Support)' CONFIG_AGP if [ "$CONFIG_AGP" != "n" ]; then bool ' Intel 440LX/BX/GX and I815/I820/I830M/I830MP/I840/I845/I850/I860 support' CONFIG_AGP_INTEL bool ' Intel I810/I815/I830M (on-board) support' CONFIG_AGP_I810 diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/console.c linux.19rc3-ac4/drivers/char/console.c --- linux.19rc3/drivers/char/console.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/console.c 2002-07-29 13:58:39.000000000 +0100 @@ -101,6 +101,7 @@ #include #include #include +#include #include #include @@ -155,6 +156,7 @@ static void unblank_screen_t(unsigned long dummy); static void console_callback(void *ignored); + static int printable; /* Is console ready for printing? */ int do_poke_blanked_console; @@ -686,6 +688,8 @@ screenbuf = (unsigned short *) q; kmalloced = 1; vc_init(currcons, video_num_lines, video_num_columns, 1); + speakup_allocate(currcons); /* speakup needs more too. */ + if (!pm_con) { pm_con = pm_register(PM_SYS_DEV, @@ -912,6 +916,7 @@ pos += video_size_row; } need_wrap = 0; + speakup_con_write(currcons, "\n",1); } static void ri(int currcons) @@ -938,8 +943,9 @@ { if (x) { pos -= 2; - x--; need_wrap = 0; + x--; + speakup_bs(currcons); } } @@ -1421,7 +1427,10 @@ kbd_table[currcons].slockstate = 0; kbd_table[currcons].ledmode = LED_SHOW_FLAGS; kbd_table[currcons].ledflagstate = kbd_table[currcons].default_ledflagstate; - set_leds(); + + /* Only schedule the keyboard_tasklet if it is enabled. */ + if(!atomic_read(&keyboard_tasklet.count)) + set_leds(); cursor_type = CUR_DEFAULT; complement_mask = s_complement_mask; @@ -1680,7 +1689,12 @@ if (par[0]) par[0]--; gotoxay(currcons,x,par[0]); return; - case 'H': case 'f': + case 'f': + if (par[0]) par[0]--; + if (par[1]) par[1]--; + gotoxay(currcons,par[1],par[0]); + return; + case 'H': if (par[0]) par[0]--; if (par[1]) par[1]--; gotoxay(currcons,par[1],par[0]); @@ -1957,6 +1971,7 @@ if (vc_state == ESnormal && ok) { /* Now try to find out how to display it */ tc = conv_uni_to_pc(vc_cons[currcons].d, tc); + if ( tc == -4 ) { /* If we got -4 (not found) then see if we have defined a replacement character (U+FFFD) */ @@ -1982,6 +1997,7 @@ } if (decim) insert_char(currcons, 1); + speakup_con_write(currcons, (char *) &tc,1); scr_writew(himask ? ((attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) : (attr << 8) + tc, @@ -2022,6 +2038,7 @@ up(&con_buf_sem); } + speakup_con_update(currcons); return n; #undef FLUSH @@ -2047,6 +2064,7 @@ /* we only changed when the console had already been allocated - a new console is not created in an interrupt routine */ + speakup_con_update(want_console); } want_console = -1; } @@ -2118,6 +2136,7 @@ /* Contrived structure to try to emulate original need_wrap behaviour * Problems caused when we have need_wrap set on '\n' character */ + speakup_con_write(currcons, b, count); while (count--) { c = *b++; if (c == 10 || c == 13 || c == 8 || need_wrap) { @@ -2162,6 +2181,7 @@ } } set_cursor(currcons); + speakup_con_update(currcons); if (!oops_in_progress) poke_blanked_console(); @@ -2509,6 +2529,8 @@ master_display_fg = vc_cons[currcons].d; set_origin(currcons); save_screen(currcons); + speakup_init(currcons); + gotoxy(currcons,x,y); csi_J(currcons, 0); update_screen(fg_console); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/cyclades.c linux.19rc3-ac4/drivers/char/cyclades.c --- linux.19rc3/drivers/char/cyclades.c 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/cyclades.c 2002-07-29 17:50:06.000000000 +0100 @@ -3446,8 +3446,8 @@ } #ifdef CY_DEBUG_DTR printk("cyc:set_line_char dropping DTR\n"); - printk(" status: 0x%x, - 0x%x\n", cy_readb(base_addr+(CyMSVR1<chipset = "Intel 440GX"; break; case INTEL_I810: head->chipset = "Intel i810"; break; -#if LINUX_VERSION_CODE >= 0x020400 case INTEL_I815: head->chipset = "Intel i815"; break; +#if LINUX_VERSION_CODE >= 0x020415 case INTEL_I820: head->chipset = "Intel i820"; break; +#endif case INTEL_I840: head->chipset = "Intel i840"; break; +#if LINUX_VERSION_CODE >= 0x020415 case INTEL_I845: head->chipset = "Intel i845"; break; - case INTEL_I850: head->chipset = "Intel i850"; break; #endif + case INTEL_I850: head->chipset = "Intel i850"; break; case VIA_GENERIC: head->chipset = "VIA"; break; case VIA_VP3: head->chipset = "VIA VP3"; break; case VIA_MVP3: head->chipset = "VIA MVP3"; break; -#if LINUX_VERSION_CODE >= 0x020400 case VIA_MVP4: head->chipset = "VIA MVP4"; break; case VIA_APOLLO_KX133: head->chipset = "VIA Apollo KX133"; break; case VIA_APOLLO_KT133: head->chipset = "VIA Apollo KT133"; break; -#endif case VIA_APOLLO_PRO: head->chipset = "VIA Apollo Pro"; break; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/drm/drm_bufs.h linux.19rc3-ac4/drivers/char/drm/drm_bufs.h --- linux.19rc3/drivers/char/drm/drm_bufs.h 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/drm/drm_bufs.h 2002-07-29 18:14:38.000000000 +0100 @@ -229,11 +229,7 @@ DRM(free)(list, sizeof(*list), DRM_MEM_MAPS); for (pt = dev->vmalist, prev = NULL; pt; prev = pt, pt = pt->next) { -#if LINUX_VERSION_CODE >= 0x020300 if (pt->vma->vm_private_data == map) found_maps++; -#else - if (pt->vma->vm_pte == map) found_maps++; -#endif } if(!found_maps) { diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/drm/drm_drv.h linux.19rc3-ac4/drivers/char/drm/drm_drv.h --- linux.19rc3/drivers/char/drm/drm_drv.h 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/drm/drm_drv.h 2002-07-29 13:58:39.000000000 +0100 @@ -113,7 +113,6 @@ #define DRIVER_IOCTLS #endif #ifndef DRIVER_FOPS -#if LINUX_VERSION_CODE >= 0x020400 #define DRIVER_FOPS \ static struct file_operations DRM(fops) = { \ owner: THIS_MODULE, \ @@ -126,19 +125,6 @@ fasync: DRM(fasync), \ poll: DRM(poll), \ } -#else -#define DRIVER_FOPS \ -static struct file_operations DRM(fops) = { \ - open: DRM(open), \ - flush: DRM(flush), \ - release: DRM(release), \ - ioctl: DRM(ioctl), \ - mmap: DRM(mmap), \ - read: DRM(read), \ - fasync: DRM(fasync), \ - poll: DRM(poll), \ -} -#endif #endif @@ -234,7 +220,9 @@ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); MODULE_PARM( drm_opts, "s" ); +#ifdef MODULE_LICENSE MODULE_LICENSE("GPL and additional rights"); +#endif static int DRM(setup)( drm_device_t *dev ) { @@ -732,9 +720,6 @@ retcode = DRM(open_helper)( inode, filp, dev ); if ( !retcode ) { -#if LINUX_VERSION_CODE < 0x020333 - MOD_INC_USE_COUNT; /* Needed before Linux 2.3.51 */ -#endif atomic_inc( &dev->counts[_DRM_STAT_OPENS] ); spin_lock( &dev->count_lock ); if ( !dev->open_count++ ) { @@ -853,9 +838,6 @@ * End inline drm_release */ -#if LINUX_VERSION_CODE < 0x020333 - MOD_DEC_USE_COUNT; /* Needed before Linux 2.3.51 */ -#endif atomic_inc( &dev->counts[_DRM_STAT_CLOSES] ); spin_lock( &dev->count_lock ); if ( !--dev->open_count ) { @@ -1047,25 +1029,6 @@ atomic_inc( &dev->counts[_DRM_STAT_UNLOCKS] ); -#if __HAVE_KERNEL_CTX_SWITCH - /* We no longer really hold it, but if we are the next - * agent to request it then we should just be able to - * take it immediately and not eat the ioctl. - */ - dev->lock.pid = 0; - { - __volatile__ unsigned int *plock = &dev->lock.hw_lock->lock; - unsigned int old, new, prev, ctx; - - ctx = lock.context; - do { - old = *plock; - new = ctx; - prev = cmpxchg(plock, old, new); - } while (prev != old); - } - wake_up_interruptible(&dev->lock.lock_queue); -#else DRM(lock_transfer)( dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT ); #if __HAVE_DMA_SCHEDULE @@ -1080,7 +1043,6 @@ DRM_ERROR( "\n" ); } } -#endif /* !__HAVE_KERNEL_CTX_SWITCH */ unblock_all_signals(); return 0; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/drm/drm_fops.h linux.19rc3-ac4/drivers/char/drm/drm_fops.h --- linux.19rc3/drivers/char/drm/drm_fops.h 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/drm/drm_fops.h 2002-07-29 18:14:38.000000000 +0100 @@ -125,21 +125,31 @@ int avail; int send; int cur; + DECLARE_WAITQUEUE(wait, current); DRM_DEBUG("%p, %p\n", dev->buf_rp, dev->buf_wp); + add_wait_queue(&dev->buf_readers, &wait); + set_current_state(TASK_INTERRUPTIBLE); while (dev->buf_rp == dev->buf_wp) { DRM_DEBUG(" sleeping\n"); if (filp->f_flags & O_NONBLOCK) { + remove_wait_queue(&dev->buf_readers, &wait); + set_current_state(TASK_RUNNING); return -EAGAIN; } - interruptible_sleep_on(&dev->buf_readers); + schedule(); /* wait for dev->buf_readers */ if (signal_pending(current)) { DRM_DEBUG(" interrupted\n"); + remove_wait_queue(&dev->buf_readers, &wait); + set_current_state(TASK_RUNNING); return -ERESTARTSYS; } DRM_DEBUG(" awake\n"); + set_current_state(TASK_INTERRUPTIBLE); } + remove_wait_queue(&dev->buf_readers, &wait); + set_current_state(TASK_RUNNING); left = (dev->buf_rp + DRM_BSZ - dev->buf_wp) % DRM_BSZ; avail = DRM_BSZ - left; @@ -191,24 +201,8 @@ send -= count; } -#if LINUX_VERSION_CODE < 0x020315 && !defined(KILLFASYNCHASTHREEPARAMETERS) - /* The extra parameter to kill_fasync was added in 2.3.21, and is - _not_ present in _stock_ 2.2.14 and 2.2.15. However, some - distributions patch 2.2.x kernels to add this parameter. The - Makefile.linux attempts to detect this addition and defines - KILLFASYNCHASTHREEPARAMETERS if three parameters are found. */ - if (dev->buf_async) kill_fasync(dev->buf_async, SIGIO); -#else - - /* Parameter added in 2.3.21. */ -#if LINUX_VERSION_CODE < 0x020400 - if (dev->buf_async) kill_fasync(dev->buf_async, SIGIO, POLL_IN); -#else - /* Type of first parameter changed in - Linux 2.4.0-test2... */ if (dev->buf_async) kill_fasync(&dev->buf_async, SIGIO, POLL_IN); -#endif -#endif + DRM_DEBUG("waking\n"); wake_up_interruptible(&dev->buf_readers); return 0; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/drm/drm.h linux.19rc3-ac4/drivers/char/drm/drm.h --- linux.19rc3/drivers/char/drm/drm.h 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/drm/drm.h 2002-07-29 13:58:39.000000000 +0100 @@ -104,9 +104,8 @@ #include "i810_drm.h" #include "r128_drm.h" #include "radeon_drm.h" -#if defined(CONFIG_DRM_SIS) || defined(CONFIG_DRM_SIS_MODULE) #include "sis_drm.h" -#endif +#include "i830_drm.h" typedef struct drm_version { int version_major; /* Major version */ @@ -449,6 +448,12 @@ #define DRM_IOCTL_I810_SWAP DRM_IO( 0x46) #define DRM_IOCTL_I810_COPY DRM_IOW( 0x47, drm_i810_copy_t) #define DRM_IOCTL_I810_DOCOPY DRM_IO( 0x48) +#define DRM_IOCTL_I810_OV0INFO DRM_IOR( 0x49, drm_i810_overlay_t) +#define DRM_IOCTL_I810_FSTATUS DRM_IO ( 0x4a) +#define DRM_IOCTL_I810_OV0FLIP DRM_IO ( 0x4b) +#define DRM_IOCTL_I810_MC DRM_IOW( 0x4c, drm_i810_mc_t) +#define DRM_IOCTL_I810_RSTATUS DRM_IO ( 0x4d ) + /* Rage 128 specific ioctls */ #define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t) @@ -483,7 +488,6 @@ #define DRM_IOCTL_RADEON_INDIRECT DRM_IOWR(0x4d, drm_radeon_indirect_t) #define DRM_IOCTL_RADEON_TEXTURE DRM_IOWR(0x4e, drm_radeon_texture_t) -#if defined(CONFIG_DRM_SIS) || defined(CONFIG_DRM_SIS_MODULE) /* SiS specific ioctls */ #define SIS_IOCTL_FB_ALLOC DRM_IOWR(0x44, drm_sis_mem_t) #define SIS_IOCTL_FB_FREE DRM_IOW( 0x45, drm_sis_mem_t) @@ -493,6 +497,16 @@ #define SIS_IOCTL_FLIP DRM_IOW( 0x48, drm_sis_flip_t) #define SIS_IOCTL_FLIP_INIT DRM_IO( 0x49) #define SIS_IOCTL_FLIP_FINAL DRM_IO( 0x50) -#endif + +/* I830 specific ioctls */ +#define DRM_IOCTL_I830_INIT DRM_IOW( 0x40, drm_i830_init_t) +#define DRM_IOCTL_I830_VERTEX DRM_IOW( 0x41, drm_i830_vertex_t) +#define DRM_IOCTL_I830_CLEAR DRM_IOW( 0x42, drm_i830_clear_t) +#define DRM_IOCTL_I830_FLUSH DRM_IO ( 0x43) +#define DRM_IOCTL_I830_GETAGE DRM_IO ( 0x44) +#define DRM_IOCTL_I830_GETBUF DRM_IOWR(0x45, drm_i830_dma_t) +#define DRM_IOCTL_I830_SWAP DRM_IO ( 0x46) +#define DRM_IOCTL_I830_COPY DRM_IOW( 0x47, drm_i830_copy_t) +#define DRM_IOCTL_I830_DOCOPY DRM_IO ( 0x48) #endif diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/drm/drm_memory.h linux.19rc3-ac4/drivers/char/drm/drm_memory.h --- linux.19rc3/drivers/char/drm/drm_memory.h 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/drm/drm_memory.h 2002-07-29 18:14:38.000000000 +0100 @@ -85,12 +85,7 @@ } si_meminfo(&si); -#if LINUX_VERSION_CODE < 0x020317 - /* Changed to page count in 2.3.23 */ - DRM(ram_available) = si.totalram >> PAGE_SHIFT; -#else DRM(ram_available) = si.totalram; -#endif DRM(ram_used) = 0; } @@ -257,12 +252,7 @@ for (addr = address, sz = bytes; sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { -#if LINUX_VERSION_CODE >= 0x020400 - /* Argument type changed in 2.4.0-test6/pre8 */ mem_map_reserve(virt_to_page(addr)); -#else - mem_map_reserve(MAP_NR(addr)); -#endif } return address; @@ -283,12 +273,7 @@ for (addr = address, sz = bytes; sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { -#if LINUX_VERSION_CODE >= 0x020400 - /* Argument type changed in 2.4.0-test6/pre8 */ mem_map_unreserve(virt_to_page(addr)); -#else - mem_map_unreserve(MAP_NR(addr)); -#endif } free_pages(address, order); } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/drm/drmP.h linux.19rc3-ac4/drivers/char/drm/drmP.h --- linux.19rc3/drivers/char/drm/drmP.h 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/drm/drmP.h 2002-07-29 18:14:37.000000000 +0100 @@ -66,13 +66,8 @@ #include #include #endif -#if LINUX_VERSION_CODE >= 0x020100 /* KERNEL_VERSION(2,1,0) */ #include #include -#endif -#if LINUX_VERSION_CODE < 0x020400 -#include "compat-pre24.h" -#endif #include #include "drm.h" @@ -81,12 +76,6 @@ #define page_to_bus(page) ((unsigned int)(virt_to_bus(page_address(page)))) #endif -/* We just use virt_to_bus for pci_map_single on older kernels */ -#if LINUX_VERSION_CODE < 0x020400 -#define pci_map_single(hwdev, ptr, size, direction) virt_to_bus(ptr) -#define pci_unmap_single(hwdev, dma_addr, size, direction) -#endif - /* DRM template customization defaults */ #ifndef __HAVE_AGP @@ -119,87 +108,6 @@ #define __REALLY_HAVE_MTRR (__HAVE_MTRR && defined(CONFIG_MTRR)) -/* Begin the DRM... - */ - -#define DRM_DEBUG_CODE 2 /* Include debugging code (if > 1, then - also include looping detection. */ - -#define DRM_HASH_SIZE 16 /* Size of key hash table */ -#define DRM_KERNEL_CONTEXT 0 /* Change drm_resctx if changed */ -#define DRM_RESERVED_CONTEXTS 1 /* Change drm_resctx if changed */ -#define DRM_LOOPING_LIMIT 5000000 -#define DRM_BSZ 1024 /* Buffer size for /dev/drm? output */ -#define DRM_TIME_SLICE (HZ/20) /* Time slice for GLXContexts */ -#define DRM_LOCK_SLICE 1 /* Time slice for lock, in jiffies */ - -#define DRM_FLAG_DEBUG 0x01 -#define DRM_FLAG_NOCTX 0x02 - -#define DRM_MEM_DMA 0 -#define DRM_MEM_SAREA 1 -#define DRM_MEM_DRIVER 2 -#define DRM_MEM_MAGIC 3 -#define DRM_MEM_IOCTLS 4 -#define DRM_MEM_MAPS 5 -#define DRM_MEM_VMAS 6 -#define DRM_MEM_BUFS 7 -#define DRM_MEM_SEGS 8 -#define DRM_MEM_PAGES 9 -#define DRM_MEM_FILES 10 -#define DRM_MEM_QUEUES 11 -#define DRM_MEM_CMDS 12 -#define DRM_MEM_MAPPINGS 13 -#define DRM_MEM_BUFLISTS 14 -#define DRM_MEM_AGPLISTS 15 -#define DRM_MEM_TOTALAGP 16 -#define DRM_MEM_BOUNDAGP 17 -#define DRM_MEM_CTXBITMAP 18 -#define DRM_MEM_STUB 19 -#define DRM_MEM_SGLISTS 20 - -#define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8) - - /* Backward compatibility section */ - /* _PAGE_WT changed to _PAGE_PWT in 2.2.6 */ -#ifndef _PAGE_PWT -#define _PAGE_PWT _PAGE_WT -#endif - /* Wait queue declarations changed in 2.3.1 */ -#ifndef DECLARE_WAITQUEUE -#define DECLARE_WAITQUEUE(w,c) struct wait_queue w = { c, NULL } -typedef struct wait_queue *wait_queue_head_t; -#define init_waitqueue_head(q) *q = NULL; -#endif - - /* _PAGE_4M changed to _PAGE_PSE in 2.3.23 */ -#ifndef _PAGE_PSE -#define _PAGE_PSE _PAGE_4M -#endif - - /* vm_offset changed to vm_pgoff in 2.3.25 */ -#if LINUX_VERSION_CODE < 0x020319 -#define VM_OFFSET(vma) ((vma)->vm_offset) -#else -#define VM_OFFSET(vma) ((vma)->vm_pgoff << PAGE_SHIFT) -#endif - - /* *_nopage return values defined in 2.3.26 */ -#ifndef NOPAGE_SIGBUS -#define NOPAGE_SIGBUS 0 -#endif -#ifndef NOPAGE_OOM -#define NOPAGE_OOM 0 -#endif - - /* module_init/module_exit added in 2.3.13 */ -#ifndef module_init -#define module_init(x) int init_module(void) { return x(); } -#endif -#ifndef module_exit -#define module_exit(x) void cleanup_module(void) { x(); } -#endif - /* Generic cmpxchg added in 2.3.x */ #ifndef __HAVE_ARCH_CMPXCHG /* Include this here so that driver can be @@ -211,7 +119,7 @@ unsigned long prev, cmp; __asm__ __volatile__( - "1: ldl_l %0,%5\n" + "1: ldl_l %0,%2\n" " cmpeq %0,%3,%1\n" " beq %1,2f\n" " mov %4,%1\n" @@ -222,8 +130,7 @@ "3: br 1b\n" ".previous" : "=&r"(prev), "=&r"(cmp), "=m"(*m) - : "r"((long) old), "r"(new), "m"(*m) - : "memory" ); + : "r"((long) old), "r"(new), "m"(*m)); return prev; } @@ -234,7 +141,7 @@ unsigned long prev, cmp; __asm__ __volatile__( - "1: ldq_l %0,%5\n" + "1: ldq_l %0,%2\n" " cmpeq %0,%3,%1\n" " beq %1,2f\n" " mov %4,%1\n" @@ -245,8 +152,7 @@ "3: br 1b\n" ".previous" : "=&r"(prev), "=&r"(cmp), "=m"(*m) - : "r"((long) old), "r"(new), "m"(*m) - : "memory" ); + : "r"((long) old), "r"(new), "m"(*m)); return prev; } @@ -298,48 +204,60 @@ return old; } -#elif defined(__powerpc__) -extern void __cmpxchg_called_with_bad_pointer(void); -static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, - unsigned long new, int size) -{ - unsigned long prev; - - switch (size) { - case 4: - __asm__ __volatile__( - "sync;" - "0: lwarx %0,0,%1 ;" - " cmpl 0,%0,%3;" - " bne 1f;" - " stwcx. %2,0,%1;" - " bne- 0b;" - "1: " - "sync;" - : "=&r"(prev) - : "r"(ptr), "r"(new), "r"(old) - : "cr0", "memory"); - return prev; - } - __cmpxchg_called_with_bad_pointer(); - return old; -} - -#endif /* i386, powerpc & alpha */ - -#ifndef __alpha__ #define cmpxchg(ptr,o,n) \ ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o), \ (unsigned long)(n),sizeof(*(ptr)))) +#endif /* i386 & alpha */ #endif -#endif /* !__HAVE_ARCH_CMPXCHG */ +/* Begin the DRM... + */ + +#define DRM_DEBUG_CODE 2 /* Include debugging code (if > 1, then + also include looping detection. */ + +#define DRM_HASH_SIZE 16 /* Size of key hash table */ +#define DRM_KERNEL_CONTEXT 0 /* Change drm_resctx if changed */ +#define DRM_RESERVED_CONTEXTS 1 /* Change drm_resctx if changed */ +#define DRM_LOOPING_LIMIT 5000000 +#define DRM_BSZ 1024 /* Buffer size for /dev/drm? output */ +#define DRM_TIME_SLICE (HZ/20) /* Time slice for GLXContexts */ +#define DRM_LOCK_SLICE 1 /* Time slice for lock, in jiffies */ + +#define DRM_FLAG_DEBUG 0x01 +#define DRM_FLAG_NOCTX 0x02 + +#define DRM_MEM_DMA 0 +#define DRM_MEM_SAREA 1 +#define DRM_MEM_DRIVER 2 +#define DRM_MEM_MAGIC 3 +#define DRM_MEM_IOCTLS 4 +#define DRM_MEM_MAPS 5 +#define DRM_MEM_VMAS 6 +#define DRM_MEM_BUFS 7 +#define DRM_MEM_SEGS 8 +#define DRM_MEM_PAGES 9 +#define DRM_MEM_FILES 10 +#define DRM_MEM_QUEUES 11 +#define DRM_MEM_CMDS 12 +#define DRM_MEM_MAPPINGS 13 +#define DRM_MEM_BUFLISTS 14 +#define DRM_MEM_AGPLISTS 15 +#define DRM_MEM_TOTALAGP 16 +#define DRM_MEM_BOUNDAGP 17 +#define DRM_MEM_CTXBITMAP 18 +#define DRM_MEM_STUB 19 +#define DRM_MEM_SGLISTS 20 + +#define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8) + +#define VM_OFFSET(vma) ((vma)->vm_pgoff << PAGE_SHIFT) /* Macros to make printk easier */ #define DRM_ERROR(fmt, arg...) \ - printk(KERN_ERR "[" DRM_NAME ":" __FUNCTION__ "] *ERROR* " fmt , ##arg) + printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* " fmt , __FUNCTION__, ##arg) #define DRM_MEM_ERROR(area, fmt, arg...) \ - printk(KERN_ERR "[" DRM_NAME ":" __FUNCTION__ ":%s] *ERROR* " fmt , \ + printk(KERN_ERR "[" DRM_NAME ":%s:%s] *ERROR* " fmt , __FUNCTION__, \ DRM(mem_stats)[area].name , ##arg) #define DRM_INFO(fmt, arg...) printk(KERN_INFO "[" DRM_NAME "] " fmt , ##arg) @@ -348,7 +266,8 @@ do { \ if ( DRM(flags) & DRM_FLAG_DEBUG ) \ printk(KERN_DEBUG \ - "[" DRM_NAME ":" __FUNCTION__ "] " fmt , \ + "[" DRM_NAME ":%s] " fmt , \ + __FUNCTION__, \ ##arg); \ } while (0) #else @@ -778,34 +697,18 @@ struct poll_table_struct *wait); /* Mapping support (drm_vm.h) */ -#if LINUX_VERSION_CODE < 0x020317 -extern unsigned long DRM(vm_nopage)(struct vm_area_struct *vma, - unsigned long address, - int unused); -extern unsigned long DRM(vm_shm_nopage)(struct vm_area_struct *vma, - unsigned long address, - int unused); -extern unsigned long DRM(vm_dma_nopage)(struct vm_area_struct *vma, - unsigned long address, - int unused); -extern unsigned long DRM(vm_sg_nopage)(struct vm_area_struct *vma, - unsigned long address, - int unused); -#else - /* Return type changed in 2.3.23 */ extern struct page *DRM(vm_nopage)(struct vm_area_struct *vma, unsigned long address, - int unused); + int write_access); extern struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma, unsigned long address, - int unused); + int write_access); extern struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma, unsigned long address, - int unused); + int write_access); extern struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma, unsigned long address, - int unused); -#endif + int write_access); extern void DRM(vm_open)(struct vm_area_struct *vma); extern void DRM(vm_close)(struct vm_area_struct *vma); extern void DRM(vm_shm_close)(struct vm_area_struct *vma); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/drm/drm_scatter.h linux.19rc3-ac4/drivers/char/drm/drm_scatter.h --- linux.19rc3/drivers/char/drm/drm_scatter.h 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/drm/drm_scatter.h 2002-07-29 18:14:38.000000000 +0100 @@ -66,9 +66,6 @@ drm_scatter_gather_t request; drm_sg_mem_t *entry; unsigned long pages, i, j; - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; DRM_DEBUG( "%s\n", __FUNCTION__ ); @@ -135,21 +132,10 @@ DRM_DEBUG( "sg alloc virtual = %p\n", entry->virtual ); for ( i = entry->handle, j = 0 ; j < pages ; i += PAGE_SIZE, j++ ) { - pgd = pgd_offset_k( i ); - if ( !pgd_present( *pgd ) ) + entry->pagelist[j] = vmalloc_to_page((void *)i); + if (!entry->pagelist[j]) goto failed; - - pmd = pmd_offset( pgd, i ); - if ( !pmd_present( *pmd ) ) - goto failed; - - pte = pte_offset( pmd, i ); - if ( !pte_present( *pte ) ) - goto failed; - - entry->pagelist[j] = pte_page( *pte ); - - SetPageReserved( entry->pagelist[j] ); + SetPageReserved(entry->pagelist[j]); } request.handle = entry->handle; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/drm/drm_stub.h linux.19rc3-ac4/drivers/char/drm/drm_stub.h --- linux.19rc3/drivers/char/drm/drm_stub.h 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/drm/drm_stub.h 2002-07-29 18:14:38.000000000 +0100 @@ -31,10 +31,6 @@ #define __NO_VERSION__ #include "drmP.h" -#if LINUX_VERSION_CODE < 0x020400 -#include "stubsupport-pre24.h" -#endif - #define DRM_STUB_MAXCARDS 16 /* Enough for one machine */ static struct drm_stub_list { @@ -70,9 +66,7 @@ } static struct file_operations DRM(stub_fops) = { -#if LINUX_VERSION_CODE >= 0x020400 owner: THIS_MODULE, -#endif open: DRM(stub_open) }; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/drm/drm_vm.h linux.19rc3-ac4/drivers/char/drm/drm_vm.h --- linux.19rc3/drivers/char/drm/drm_vm.h 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/drm/drm_vm.h 2002-07-29 18:14:38.000000000 +0100 @@ -56,16 +56,9 @@ close: DRM(vm_close), }; -#if LINUX_VERSION_CODE < 0x020317 -unsigned long DRM(vm_nopage)(struct vm_area_struct *vma, - unsigned long address, - int unused) -#else - /* Return type changed in 2.3.23 */ struct page *DRM(vm_nopage)(struct vm_area_struct *vma, unsigned long address, - int unused) -#endif + int write_access) { #if __REALLY_HAVE_AGP drm_file_t *priv = vma->vm_file->private_data; @@ -122,11 +115,7 @@ DRM_DEBUG("baddr = 0x%lx page = 0x%p, offset = 0x%lx\n", baddr, __va(agpmem->memory->memory[offset]), offset); -#if LINUX_VERSION_CODE < 0x020317 - return page_address(page); -#else return page; -#endif } vm_nopage_error: #endif /* __REALLY_HAVE_AGP */ @@ -134,27 +123,13 @@ return NOPAGE_SIGBUS; /* Disallow mremap */ } -#if LINUX_VERSION_CODE < 0x020317 -unsigned long DRM(vm_shm_nopage)(struct vm_area_struct *vma, - unsigned long address, - int unused) -#else - /* Return type changed in 2.3.23 */ struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma, unsigned long address, - int unused) -#endif + int write_access) { -#if LINUX_VERSION_CODE >= 0x020300 drm_map_t *map = (drm_map_t *)vma->vm_private_data; -#else - drm_map_t *map = (drm_map_t *)vma->vm_pte; -#endif unsigned long offset; unsigned long i; - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; struct page *page; if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */ @@ -162,25 +137,13 @@ offset = address - vma->vm_start; i = (unsigned long)map->handle + offset; - /* We have to walk page tables here because we need large SAREA's, and - * they need to be virtually contiguous in kernel space. - */ - pgd = pgd_offset_k( i ); - if( !pgd_present( *pgd ) ) return NOPAGE_OOM; - pmd = pmd_offset( pgd, i ); - if( !pmd_present( *pmd ) ) return NOPAGE_OOM; - pte = pte_offset( pmd, i ); - if( !pte_present( *pte ) ) return NOPAGE_OOM; - - page = pte_page(*pte); + page = vmalloc_to_page((void *)i); + if (!page) + return NOPAGE_OOM; get_page(page); - DRM_DEBUG("shm_nopage 0x%lx\n", address); -#if LINUX_VERSION_CODE < 0x020317 - return page_address(page); -#else + DRM_DEBUG("0x%08lx => 0x%08x\n", address, page_to_bus(page)); return page; -#endif } /* Special close routine which deletes map information if we are the last @@ -199,25 +162,14 @@ DRM_DEBUG("0x%08lx,0x%08lx\n", vma->vm_start, vma->vm_end - vma->vm_start); -#if LINUX_VERSION_CODE < 0x020333 - MOD_DEC_USE_COUNT; /* Needed before Linux 2.3.51 */ -#endif atomic_dec(&dev->vma_count); -#if LINUX_VERSION_CODE >= 0x020300 map = vma->vm_private_data; -#else - map = vma->vm_pte; -#endif down(&dev->struct_sem); for (pt = dev->vmalist, prev = NULL; pt; pt = next) { next = pt->next; -#if LINUX_VERSION_CODE >= 0x020300 if (pt->vma->vm_private_data == map) found_maps++; -#else - if (pt->vma->vm_pte == map) found_maps++; -#endif if (pt->vma == vma) { if (prev) { prev->next = pt->next; @@ -270,16 +222,9 @@ up(&dev->struct_sem); } -#if LINUX_VERSION_CODE < 0x020317 -unsigned long DRM(vm_dma_nopage)(struct vm_area_struct *vma, - unsigned long address, - int unused) -#else - /* Return type changed in 2.3.23 */ struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma, unsigned long address, - int unused) -#endif + int write_access) { drm_file_t *priv = vma->vm_file->private_data; drm_device_t *dev = priv->dev; @@ -299,30 +244,16 @@ get_page(page); - DRM_DEBUG("dma_nopage 0x%lx (page %lu)\n", address, page_nr); -#if LINUX_VERSION_CODE < 0x020317 - return page_address(page); -#else + DRM_DEBUG("0x%08lx (page %lu) => 0x%08x\n", address, page_nr, + page_to_bus(page)); return page; -#endif } -#if LINUX_VERSION_CODE < 0x020317 -unsigned long DRM(vm_sg_nopage)(struct vm_area_struct *vma, - unsigned long address, - int unused) -#else - /* Return type changed in 2.3.23 */ struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma, unsigned long address, - int unused) -#endif + int write_access) { -#if LINUX_VERSION_CODE >= 0x020300 drm_map_t *map = (drm_map_t *)vma->vm_private_data; -#else - drm_map_t *map = (drm_map_t *)vma->vm_pte; -#endif drm_file_t *priv = vma->vm_file->private_data; drm_device_t *dev = priv->dev; drm_sg_mem_t *entry = dev->sg; @@ -342,11 +273,7 @@ page = entry->pagelist[page_offset]; get_page(page); -#if LINUX_VERSION_CODE < 0x020317 - return page_address(page); -#else return page; -#endif } void DRM(vm_open)(struct vm_area_struct *vma) @@ -358,10 +285,6 @@ DRM_DEBUG("0x%08lx,0x%08lx\n", vma->vm_start, vma->vm_end - vma->vm_start); atomic_inc(&dev->vma_count); -#if LINUX_VERSION_CODE < 0x020333 - /* The map can exist after the fd is closed. */ - MOD_INC_USE_COUNT; /* Needed before Linux 2.3.51 */ -#endif vma_entry = DRM(alloc)(sizeof(*vma_entry), DRM_MEM_VMAS); if (vma_entry) { @@ -382,9 +305,6 @@ DRM_DEBUG("0x%08lx,0x%08lx\n", vma->vm_start, vma->vm_end - vma->vm_start); -#if LINUX_VERSION_CODE < 0x020333 - MOD_DEC_USE_COUNT; /* Needed before Linux 2.3.51 */ -#endif atomic_dec(&dev->vma_count); down(&dev->struct_sem); @@ -423,13 +343,13 @@ unlock_kernel(); vma->vm_ops = &DRM(vm_dma_ops); - vma->vm_flags |= VM_RESERVED; /* Don't swap */ -#if LINUX_VERSION_CODE < 0x020203 /* KERNEL_VERSION(2,2,3) */ - /* In Linux 2.2.3 and above, this is - handled in do_mmap() in mm/mmap.c. */ - ++filp->f_count; +#if LINUX_VERSION_CODE <= 0x020414 + vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */ +#else + vma->vm_flags |= VM_RESERVED; /* Don't swap */ #endif + vma->vm_file = filp; /* Needed for drm_vm_open() */ DRM(vm_open)(vma); return 0; @@ -531,17 +451,10 @@ vma->vm_flags |= VM_IO; /* not in core dump */ } offset = DRIVER_GET_REG_OFS(); -#ifdef __sparc__ - if (io_remap_page_range(vma->vm_start, - VM_OFFSET(vma) + offset, - vma->vm_end - vma->vm_start, - vma->vm_page_prot, 0)) -#else if (remap_page_range(vma->vm_start, VM_OFFSET(vma) + offset, vma->vm_end - vma->vm_start, vma->vm_page_prot)) -#endif return -EAGAIN; DRM_DEBUG(" Type = %d; start = 0x%lx, end = 0x%lx," " offset = 0x%lx\n", @@ -551,34 +464,33 @@ break; case _DRM_SHM: vma->vm_ops = &DRM(vm_shm_ops); -#if LINUX_VERSION_CODE >= 0x020300 vma->vm_private_data = (void *)map; -#else - vma->vm_pte = (unsigned long)map; -#endif /* Don't let this area swap. Change when DRM_KERNEL advisory is supported. */ +#if LINUX_VERSION_CODE <= 0x020414 + vma->vm_flags |= VM_LOCKED; +#else vma->vm_flags |= VM_RESERVED; +#endif break; case _DRM_SCATTER_GATHER: vma->vm_ops = &DRM(vm_sg_ops); -#if LINUX_VERSION_CODE >= 0x020300 vma->vm_private_data = (void *)map; +#if LINUX_VERSION_CODE <= 0x020414 + vma->vm_flags |= VM_LOCKED; #else - vma->vm_pte = (unsigned long)map; + vma->vm_flags |= VM_RESERVED; #endif - vma->vm_flags |= VM_RESERVED; break; default: return -EINVAL; /* This should never happen. */ } +#if LINUX_VERSION_CODE <= 0x020414 + vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */ +#else vma->vm_flags |= VM_RESERVED; /* Don't swap */ - -#if LINUX_VERSION_CODE < 0x020203 /* KERNEL_VERSION(2,2,3) */ - /* In Linux 2.2.3 and above, this is - handled in do_mmap() in mm/mmap.c. */ - ++filp->f_count; #endif + vma->vm_file = filp; /* Needed for drm_vm_open() */ DRM(vm_open)(vma); return 0; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/drm/i810_dma.c linux.19rc3-ac4/drivers/char/drm/i810_dma.c --- linux.19rc3/drivers/char/drm/i810_dma.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/drm/i810_dma.c 2002-07-29 18:23:08.000000000 +0100 @@ -35,6 +35,7 @@ #include "drmP.h" #include "i810_drv.h" #include /* For task queue support */ +#include /* in case we don't have a 2.3.99-pre6 kernel or later: */ #ifndef VM_DONTCOPY @@ -73,7 +74,7 @@ *(volatile unsigned int *)(virt + outring) = n; \ outring += 4; \ outring &= ringmask; \ -} while (0); +} while (0) static inline void i810_print_status_page(drm_device_t *dev) { @@ -86,6 +87,7 @@ DRM_DEBUG( "hw_status: LpRing Head ptr : %x\n", temp[1]); DRM_DEBUG( "hw_status: IRing Head ptr : %x\n", temp[2]); DRM_DEBUG( "hw_status: Reserved : %x\n", temp[3]); + DRM_DEBUG( "hw_status: Last Render: %x\n", temp[4]); DRM_DEBUG( "hw_status: Driver Counter : %d\n", temp[5]); for(i = 6; i < dma->buf_count + 6; i++) { DRM_DEBUG( "buffer status idx : %d used: %d\n", i - 6, temp[i]); @@ -227,14 +229,9 @@ #else down_write( ¤t->mm->mmap_sem ); #endif -#if LINUX_VERSION_CODE < 0x020399 - retcode = do_munmap((unsigned long)buf_priv->virtual, - (size_t) buf->total); -#else retcode = do_munmap(current->mm, (unsigned long)buf_priv->virtual, - (size_t) buf->total); -#endif + (size_t) buf->total, 1); #if LINUX_VERSION_CODE <= 0x020402 up( ¤t->mm->mmap_sem ); #else @@ -278,30 +275,6 @@ return retcode; } -static unsigned long i810_alloc_page(drm_device_t *dev) -{ - unsigned long address; - - address = __get_free_page(GFP_KERNEL); - if(address == 0UL) - return 0; - - get_page(virt_to_page(address)); - LockPage(virt_to_page(address)); - - return address; -} - -static void i810_free_page(drm_device_t *dev, unsigned long page) -{ - if (page) { - struct page *p = virt_to_page(page); - put_page(p); - UnlockPage(p); - free_page(page); - } -} - static int i810_dma_cleanup(drm_device_t *dev) { drm_device_dma_t *dma = dev->dma; @@ -316,7 +289,8 @@ dev_priv->ring.Size); } if(dev_priv->hw_status_page != 0UL) { - i810_free_page(dev, dev_priv->hw_status_page); + pci_free_consistent(dev->pdev, PAGE_SIZE, (void *)dev_priv->hw_status_page, + dev_priv->dma_status_page); /* Need to rewrite hardware status page */ I810_WRITE(0x02080, 0x1ffff000); } @@ -474,12 +448,16 @@ dev_priv->back_offset = init->back_offset; dev_priv->depth_offset = init->depth_offset; + dev_priv->overlay_offset = init->overlay_offset; + dev_priv->overlay_physical = init->overlay_physical; + dev_priv->front_di1 = init->front_offset | init->pitch_bits; dev_priv->back_di1 = init->back_offset | init->pitch_bits; dev_priv->zi1 = init->depth_offset | init->pitch_bits; /* Program Hardware Status Page */ - dev_priv->hw_status_page = i810_alloc_page(dev); + dev_priv->hw_status_page = (unsigned long)pci_alloc_consistent(dev->pdev, PAGE_SIZE, + &dev_priv->dma_status_page); if(dev_priv->hw_status_page == 0UL) { dev->dev_private = (void *)dev_priv; i810_dma_cleanup(dev); @@ -489,7 +467,7 @@ memset((void *) dev_priv->hw_status_page, 0, PAGE_SIZE); DRM_DEBUG("hw status page @ %lx\n", dev_priv->hw_status_page); - I810_WRITE(0x02080, virt_to_bus((void *)dev_priv->hw_status_page)); + I810_WRITE(0x02080, dev_priv->dma_status_page); DRM_DEBUG("Enabled hardware status page\n"); /* Now we need to init our freelist */ @@ -505,6 +483,12 @@ return 0; } + +int xfreeversion = -1; + +MODULE_PARM(xfreeversion, "i"); +MODULE_PARM_DESC(xfreeversion, "The version of XFree86 that needs to be supported"); + int i810_dma_init(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { @@ -516,6 +500,22 @@ if (copy_from_user(&init, (drm_i810_init_t *)arg, sizeof(init))) return -EFAULT; + + if ((xfreeversion==41) || ((xfreeversion==-1)&&(init.pitch==0))) { + /* Ok we have a problem here. Someone decided it was funny to add + * two fields in the middle of the drm_i810_init_it structure in the + * transition between XFree86 4.1.0 and 4.2.0. The code below tries + * to fix this ABI breakage up as good as possible, unfortionatly + * it's impossible to autodetect which interface the user wants, + * hence the module parameter -- Arjan + */ + init.pitch_bits = init.h; + init.pitch = init.w; + init.h = init.overlay_physical; + init.w = init.overlay_offset; + init.overlay_physical = 0; + init.overlay_offset = 0; + } switch(init.func) { case I810_INIT_DMA: @@ -1262,3 +1262,156 @@ if(VM_DONTCOPY == 0) return 1; return 0; } + +static void i810_dma_dispatch_mc(drm_device_t *dev, drm_buf_t *buf, int used, + unsigned int last_render) +{ + drm_i810_private_t *dev_priv = dev->dev_private; + drm_i810_buf_priv_t *buf_priv = buf->dev_private; + drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv; + unsigned long address = (unsigned long)buf->bus_address; + unsigned long start = address - dev->agp->base; + int u; + RING_LOCALS; + + i810_kernel_lost_context(dev); + + u = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, + I810_BUF_HARDWARE); + if(u != I810_BUF_CLIENT) { + DRM_DEBUG("MC found buffer that isn't mine!\n"); + } + + if (used > 4*1024) + used = 0; + + sarea_priv->dirty = 0x7f; + + DRM_DEBUG("dispatch mc addr 0x%lx, used 0x%x\n", + address, used); + + dev_priv->counter++; + DRM_DEBUG("dispatch counter : %ld\n", dev_priv->counter); + DRM_DEBUG("i810_dma_dispatch_mc\n"); + DRM_DEBUG("start : %lx\n", start); + DRM_DEBUG("used : %d\n", used); + DRM_DEBUG("start + used - 4 : %ld\n", start + used - 4); + + if (buf_priv->currently_mapped == I810_BUF_MAPPED) { + if (used & 4) { + *(u32 *)((u32)buf_priv->virtual + used) = 0; + used += 4; + } + + i810_unmap_buffer(buf); + } + BEGIN_LP_RING(4); + OUT_RING( CMD_OP_BATCH_BUFFER ); + OUT_RING( start | BB1_PROTECTED ); + OUT_RING( start + used - 4 ); + OUT_RING( 0 ); + ADVANCE_LP_RING(); + + + BEGIN_LP_RING(8); + OUT_RING( CMD_STORE_DWORD_IDX ); + OUT_RING( buf_priv->my_use_idx ); + OUT_RING( I810_BUF_FREE ); + OUT_RING( 0 ); + + OUT_RING( CMD_STORE_DWORD_IDX ); + OUT_RING( 16 ); + OUT_RING( last_render ); + OUT_RING( 0 ); + ADVANCE_LP_RING(); +} + +int i810_dma_mc(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_device_dma_t *dma = dev->dma; + drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; + u32 *hw_status = (u32 *)dev_priv->hw_status_page; + drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) + dev_priv->sarea_priv; + drm_i810_mc_t mc; + + if (copy_from_user(&mc, (drm_i810_mc_t *)arg, sizeof(mc))) + return -EFAULT; + + + if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { + DRM_ERROR("i810_dma_mc called without lock held\n"); + return -EINVAL; + } + + i810_dma_dispatch_mc(dev, dma->buflist[mc.idx], mc.used, + mc.last_render ); + + atomic_add(mc.used, &dev->counts[_DRM_STAT_SECONDARY]); + atomic_inc(&dev->counts[_DRM_STAT_DMA]); + sarea_priv->last_enqueue = dev_priv->counter-1; + sarea_priv->last_dispatch = (int) hw_status[5]; + + return 0; +} + +int i810_rstatus(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; + + return (int)(((u32 *)(dev_priv->hw_status_page))[4]); +} + +int i810_ov0_info(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; + drm_i810_overlay_t data; + + data.offset = dev_priv->overlay_offset; + data.physical = dev_priv->overlay_physical; + copy_to_user((drm_i810_overlay_t *)arg,&data,sizeof(data)); + return 0; +} + +int i810_fstatus(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; + + if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { + DRM_ERROR("i810_fstatus called without lock held\n"); + return -EINVAL; + } + return I810_READ(0x30008); +} + +int i810_ov0_flip(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; + + if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { + DRM_ERROR("i810_ov0_flip called without lock held\n"); + return -EINVAL; + } + + //Tell the overlay to update + I810_WRITE(0x30000,dev_priv->overlay_physical | 0x80000000); + + return 0; +} + + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/drm/i810_drm.h linux.19rc3-ac4/drivers/char/drm/i810_drm.h --- linux.19rc3/drivers/char/drm/i810_drm.h 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/drm/i810_drm.h 2002-07-29 13:58:39.000000000 +0100 @@ -112,6 +112,8 @@ unsigned int front_offset; unsigned int back_offset; unsigned int depth_offset; + unsigned int overlay_offset; + unsigned int overlay_physical; unsigned int w; unsigned int h; unsigned int pitch; @@ -196,4 +198,18 @@ int granted; } drm_i810_dma_t; +typedef struct _drm_i810_overlay_t { + unsigned int offset; /* Address of the Overlay Regs */ + unsigned int physical; +} drm_i810_overlay_t; + +typedef struct _drm_i810_mc { + int idx; /* buffer index */ + int used; /* nr bytes in use */ + int num_blocks; /* number of GFXBlocks */ + int *length; /* List of lengths for GFXBlocks (FUTURE)*/ + unsigned int last_render; /* Last Render Request */ +} drm_i810_mc_t; + + #endif /* _I810_DRM_H_ */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/drm/i810_drv.c linux.19rc3-ac4/drivers/char/drm/i810_drv.c --- linux.19rc3/drivers/char/drm/i810_drv.c 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/drm/i810_drv.c 2002-07-29 13:58:39.000000000 +0100 @@ -39,10 +39,10 @@ #define DRIVER_NAME "i810" #define DRIVER_DESC "Intel i810" -#define DRIVER_DATE "20010616" +#define DRIVER_DATE "20010920" #define DRIVER_MAJOR 1 -#define DRIVER_MINOR 1 +#define DRIVER_MINOR 2 #define DRIVER_PATCHLEVEL 0 #define DRIVER_IOCTLS \ @@ -54,7 +54,12 @@ [DRM_IOCTL_NR(DRM_IOCTL_I810_GETBUF)] = { i810_getbuf, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_I810_SWAP)] = { i810_swap_bufs, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_I810_COPY)] = { i810_copybuf, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_I810_DOCOPY)] = { i810_docopy, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_I810_DOCOPY)] = { i810_docopy, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I810_OV0INFO)] = { i810_ov0_info, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I810_FSTATUS)] = { i810_fstatus, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I810_OV0FLIP)] = { i810_ov0_flip, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I810_MC)] = { i810_dma_mc, 1, 1 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I810_RSTATUS)] = { i810_rstatus, 1, 0 } #define __HAVE_COUNTERS 4 diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/drm/i810_drv.h linux.19rc3-ac4/drivers/char/drm/i810_drv.h --- linux.19rc3/drivers/char/drm/i810_drv.h 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/drm/i810_drv.h 2002-07-29 13:58:39.000000000 +0100 @@ -63,6 +63,7 @@ unsigned long hw_status_page; unsigned long counter; + dma_addr_t dma_status_page; atomic_t flush_done; wait_queue_head_t flush_queue; /* Processes waiting until flush */ @@ -73,6 +74,8 @@ int back_offset; int depth_offset; + int overlay_offset; + int overlay_physical; int w, h; int pitch; } drm_i810_private_t; @@ -94,6 +97,18 @@ extern int i810_docopy(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +extern int i810_rstatus(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int i810_ov0_info(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int i810_fstatus(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int i810_ov0_flip(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int i810_dma_mc(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); + + extern void i810_dma_quiescent(drm_device_t *dev); #define I810_VERBOSE 0 diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/drm/i830_dma.c linux.19rc3-ac4/drivers/char/drm/i830_dma.c --- linux.19rc3/drivers/char/drm/i830_dma.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/drm/i830_dma.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,1381 @@ +/* i830_dma.c -- DMA support for the I830 -*- linux-c -*- + * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: Rickard E. (Rik) Faith + * Jeff Hartmann + * Keith Whitwell + * Abraham vd Merwe + * + */ + +#define __NO_VERSION__ +#include "i830.h" +#include "drmP.h" +#include "i830_drv.h" +#include /* For task queue support */ +#include +/* in case we don't have a 2.3.99-pre6 kernel or later: */ +#ifndef VM_DONTCOPY +#define VM_DONTCOPY 0 +#endif + +#define I830_BUF_FREE 2 +#define I830_BUF_CLIENT 1 +#define I830_BUF_HARDWARE 0 + +#define I830_BUF_UNMAPPED 0 +#define I830_BUF_MAPPED 1 + +#define RING_LOCALS unsigned int outring, ringmask; volatile char *virt; + + +#define DO_IDLE_WORKAROUND() \ +do { \ + int _head; \ + int _tail; \ + int _i; \ + do { \ + _head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR; \ + _tail = I830_READ(LP_RING + RING_TAIL) & TAIL_ADDR; \ + udelay(1); \ + } while(_head != _tail); \ +} while(0) + +#define I830_SYNC_WORKAROUND 0 + +#define BEGIN_LP_RING(n) do { \ + if (I830_VERBOSE) \ + DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", \ + n, __FUNCTION__); \ + if (I830_SYNC_WORKAROUND) \ + DO_IDLE_WORKAROUND(); \ + if (dev_priv->ring.space < n*4) \ + i830_wait_ring(dev, n*4); \ + dev_priv->ring.space -= n*4; \ + outring = dev_priv->ring.tail; \ + ringmask = dev_priv->ring.tail_mask; \ + virt = dev_priv->ring.virtual_start; \ +} while (0) + +#define ADVANCE_LP_RING() do { \ + if (I830_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING\n"); \ + dev_priv->ring.tail = outring; \ + I830_WRITE(LP_RING + RING_TAIL, outring); \ +} while(0) + +#define OUT_RING(n) do { \ + if (I830_VERBOSE) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \ + *(volatile unsigned int *)(virt + outring) = n; \ + outring += 4; \ + outring &= ringmask; \ +} while (0); + +static inline void i830_print_status_page(drm_device_t *dev) +{ + drm_device_dma_t *dma = dev->dma; + drm_i830_private_t *dev_priv = dev->dev_private; + u32 *temp = dev_priv->hw_status_page; + int i; + + DRM_DEBUG( "hw_status: Interrupt Status : %x\n", temp[0]); + DRM_DEBUG( "hw_status: LpRing Head ptr : %x\n", temp[1]); + DRM_DEBUG( "hw_status: IRing Head ptr : %x\n", temp[2]); + DRM_DEBUG( "hw_status: Reserved : %x\n", temp[3]); + DRM_DEBUG( "hw_status: Driver Counter : %d\n", temp[5]); + for(i = 9; i < dma->buf_count + 9; i++) { + DRM_DEBUG( "buffer status idx : %d used: %d\n", i - 9, temp[i]); + } +} + +static drm_buf_t *i830_freelist_get(drm_device_t *dev) +{ + drm_device_dma_t *dma = dev->dma; + int i; + int used; + + /* Linear search might not be the best solution */ + + for (i = 0; i < dma->buf_count; i++) { + drm_buf_t *buf = dma->buflist[ i ]; + drm_i830_buf_priv_t *buf_priv = buf->dev_private; + /* In use is already a pointer */ + used = cmpxchg(buf_priv->in_use, I830_BUF_FREE, + I830_BUF_CLIENT); + if(used == I830_BUF_FREE) { + return buf; + } + } + return NULL; +} + +/* This should only be called if the buffer is not sent to the hardware + * yet, the hardware updates in use for us once its on the ring buffer. + */ + +static int i830_freelist_put(drm_device_t *dev, drm_buf_t *buf) +{ + drm_i830_buf_priv_t *buf_priv = buf->dev_private; + int used; + + /* In use is already a pointer */ + used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, I830_BUF_FREE); + if(used != I830_BUF_CLIENT) { + DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx); + return -EINVAL; + } + + return 0; +} + +static struct file_operations i830_buffer_fops = { + open: DRM(open), + flush: DRM(flush), + release: DRM(release), + ioctl: DRM(ioctl), + mmap: i830_mmap_buffers, + read: DRM(read), + fasync: DRM(fasync), + poll: DRM(poll), +}; + +int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev; + drm_i830_private_t *dev_priv; + drm_buf_t *buf; + drm_i830_buf_priv_t *buf_priv; + + lock_kernel(); + dev = priv->dev; + dev_priv = dev->dev_private; + buf = dev_priv->mmap_buffer; + buf_priv = buf->dev_private; + + vma->vm_flags |= (VM_IO | VM_DONTCOPY); + vma->vm_file = filp; + + buf_priv->currently_mapped = I830_BUF_MAPPED; + unlock_kernel(); + + if (remap_page_range(vma->vm_start, + VM_OFFSET(vma), + vma->vm_end - vma->vm_start, + vma->vm_page_prot)) return -EAGAIN; + return 0; +} + +static int i830_map_buffer(drm_buf_t *buf, struct file *filp) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_i830_buf_priv_t *buf_priv = buf->dev_private; + drm_i830_private_t *dev_priv = dev->dev_private; + struct file_operations *old_fops; + int retcode = 0; + + if(buf_priv->currently_mapped == I830_BUF_MAPPED) return -EINVAL; + + if(VM_DONTCOPY != 0) { +#if LINUX_VERSION_CODE <= 0x020402 + down( ¤t->mm->mmap_sem ); +#else + down_write( ¤t->mm->mmap_sem ); +#endif + old_fops = filp->f_op; + filp->f_op = &i830_buffer_fops; + dev_priv->mmap_buffer = buf; + buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total, + PROT_READ|PROT_WRITE, + MAP_SHARED, + buf->bus_address); + dev_priv->mmap_buffer = NULL; + filp->f_op = old_fops; + if ((unsigned long)buf_priv->virtual > -1024UL) { + /* Real error */ + DRM_DEBUG("mmap error\n"); + retcode = (signed int)buf_priv->virtual; + buf_priv->virtual = 0; + } +#if LINUX_VERSION_CODE <= 0x020402 + up( ¤t->mm->mmap_sem ); +#else + up_write( ¤t->mm->mmap_sem ); +#endif + } else { + buf_priv->virtual = buf_priv->kernel_virtual; + buf_priv->currently_mapped = I830_BUF_MAPPED; + } + return retcode; +} + +static int i830_unmap_buffer(drm_buf_t *buf) +{ + drm_i830_buf_priv_t *buf_priv = buf->dev_private; + int retcode = 0; + + if(VM_DONTCOPY != 0) { + if(buf_priv->currently_mapped != I830_BUF_MAPPED) + return -EINVAL; + down_write( ¤t->mm->mmap_sem ); + retcode = do_munmap(current->mm, + (unsigned long)buf_priv->virtual, + (size_t) buf->total, 1); + up_write( ¤t->mm->mmap_sem ); + } + buf_priv->currently_mapped = I830_BUF_UNMAPPED; + buf_priv->virtual = 0; + + return retcode; +} + +static int i830_dma_get_buffer(drm_device_t *dev, drm_i830_dma_t *d, + struct file *filp) +{ + drm_file_t *priv = filp->private_data; + drm_buf_t *buf; + drm_i830_buf_priv_t *buf_priv; + int retcode = 0; + + buf = i830_freelist_get(dev); + if (!buf) { + retcode = -ENOMEM; + DRM_DEBUG("retcode=%d\n", retcode); + return retcode; + } + + retcode = i830_map_buffer(buf, filp); + if(retcode) { + i830_freelist_put(dev, buf); + DRM_DEBUG("mapbuf failed, retcode %d\n", retcode); + return retcode; + } + buf->pid = priv->pid; + buf_priv = buf->dev_private; + d->granted = 1; + d->request_idx = buf->idx; + d->request_size = buf->total; + d->virtual = buf_priv->virtual; + + return retcode; +} + +static int i830_dma_cleanup(drm_device_t *dev) +{ + drm_device_dma_t *dma = dev->dma; + + if(dev->dev_private) { + int i; + drm_i830_private_t *dev_priv = + (drm_i830_private_t *) dev->dev_private; + + if(dev_priv->ring.virtual_start) { + DRM(ioremapfree)((void *) dev_priv->ring.virtual_start, + dev_priv->ring.Size); + } + if(dev_priv->hw_status_page != NULL) { + pci_free_consistent(dev->pdev, PAGE_SIZE, + dev_priv->hw_status_page, dev_priv->dma_status_page); + /* Need to rewrite hardware status page */ + I830_WRITE(0x02080, 0x1ffff000); + } + DRM(free)(dev->dev_private, sizeof(drm_i830_private_t), + DRM_MEM_DRIVER); + dev->dev_private = NULL; + + for (i = 0; i < dma->buf_count; i++) { + drm_buf_t *buf = dma->buflist[ i ]; + drm_i830_buf_priv_t *buf_priv = buf->dev_private; + DRM(ioremapfree)(buf_priv->kernel_virtual, buf->total); + } + } + return 0; +} + +static int i830_wait_ring(drm_device_t *dev, int n) +{ + drm_i830_private_t *dev_priv = dev->dev_private; + drm_i830_ring_buffer_t *ring = &(dev_priv->ring); + int iters = 0; + unsigned long end; + unsigned int last_head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR; + + end = jiffies + (HZ*3); + while (ring->space < n) { + int i; + + ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR; + ring->space = ring->head - (ring->tail+8); + if (ring->space < 0) ring->space += ring->Size; + + if (ring->head != last_head) { + end = jiffies + (HZ*3); + last_head = ring->head; + } + + iters++; + if(time_before(end,jiffies)) { + DRM_ERROR("space: %d wanted %d\n", ring->space, n); + DRM_ERROR("lockup\n"); + goto out_wait_ring; + } + + udelay(1); + } + +out_wait_ring: + return iters; +} + +static void i830_kernel_lost_context(drm_device_t *dev) +{ + drm_i830_private_t *dev_priv = dev->dev_private; + drm_i830_ring_buffer_t *ring = &(dev_priv->ring); + + ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR; + ring->tail = I830_READ(LP_RING + RING_TAIL); + ring->space = ring->head - (ring->tail+8); + if (ring->space < 0) ring->space += ring->Size; +} + +static int i830_freelist_init(drm_device_t *dev, drm_i830_private_t *dev_priv) +{ + drm_device_dma_t *dma = dev->dma; + int my_idx = 36; + u32 *hw_status = (u32 *)(dev_priv->hw_status_page + my_idx); + int i; + + if(dma->buf_count > 1019) { + /* Not enough space in the status page for the freelist */ + return -EINVAL; + } + + for (i = 0; i < dma->buf_count; i++) { + drm_buf_t *buf = dma->buflist[ i ]; + drm_i830_buf_priv_t *buf_priv = buf->dev_private; + + buf_priv->in_use = hw_status++; + buf_priv->my_use_idx = my_idx; + my_idx += 4; + + *buf_priv->in_use = I830_BUF_FREE; + + buf_priv->kernel_virtual = DRM(ioremap)(buf->bus_address, + buf->total); + } + return 0; +} + +static int i830_dma_initialize(drm_device_t *dev, + drm_i830_private_t *dev_priv, + drm_i830_init_t *init) +{ + struct list_head *list; + + memset(dev_priv, 0, sizeof(drm_i830_private_t)); + + list_for_each(list, &dev->maplist->head) { + drm_map_list_t *r_list = (drm_map_list_t *)list; + if( r_list->map && + r_list->map->type == _DRM_SHM && + r_list->map->flags & _DRM_CONTAINS_LOCK ) { + dev_priv->sarea_map = r_list->map; + break; + } + } + + if(!dev_priv->sarea_map) { + dev->dev_private = (void *)dev_priv; + i830_dma_cleanup(dev); + DRM_ERROR("can not find sarea!\n"); + return -EINVAL; + } + DRM_FIND_MAP( dev_priv->mmio_map, init->mmio_offset ); + if(!dev_priv->mmio_map) { + dev->dev_private = (void *)dev_priv; + i830_dma_cleanup(dev); + DRM_ERROR("can not find mmio map!\n"); + return -EINVAL; + } + DRM_FIND_MAP( dev_priv->buffer_map, init->buffers_offset ); + if(!dev_priv->buffer_map) { + dev->dev_private = (void *)dev_priv; + i830_dma_cleanup(dev); + DRM_ERROR("can not find dma buffer map!\n"); + return -EINVAL; + } + + dev_priv->sarea_priv = (drm_i830_sarea_t *) + ((u8 *)dev_priv->sarea_map->handle + + init->sarea_priv_offset); + + atomic_set(&dev_priv->flush_done, 0); + init_waitqueue_head(&dev_priv->flush_queue); + + dev_priv->ring.Start = init->ring_start; + dev_priv->ring.End = init->ring_end; + dev_priv->ring.Size = init->ring_size; + + dev_priv->ring.virtual_start = DRM(ioremap)(dev->agp->base + + init->ring_start, + init->ring_size); + + if (dev_priv->ring.virtual_start == NULL) { + dev->dev_private = (void *) dev_priv; + i830_dma_cleanup(dev); + DRM_ERROR("can not ioremap virtual address for" + " ring buffer\n"); + return -ENOMEM; + } + + dev_priv->ring.tail_mask = dev_priv->ring.Size - 1; + + dev_priv->w = init->w; + dev_priv->h = init->h; + dev_priv->pitch = init->pitch; + dev_priv->back_offset = init->back_offset; + dev_priv->depth_offset = init->depth_offset; + + dev_priv->front_di1 = init->front_offset | init->pitch_bits; + dev_priv->back_di1 = init->back_offset | init->pitch_bits; + dev_priv->zi1 = init->depth_offset | init->pitch_bits; + + dev_priv->cpp = init->cpp; + /* We are using seperate values as placeholders for mechanisms for + * private backbuffer/depthbuffer usage. + */ + + dev_priv->back_pitch = init->back_pitch; + dev_priv->depth_pitch = init->depth_pitch; + + /* Program Hardware Status Page */ + dev_priv->hw_status_page = pci_alloc_consistent(dev->pdev, PAGE_SIZE, + &dev_priv->dma_status_page); + if(dev_priv->hw_status_page == NULL) { + dev->dev_private = (void *)dev_priv; + i830_dma_cleanup(dev); + DRM_ERROR("Can not allocate hardware status page\n"); + return -ENOMEM; + } + memset(dev_priv->hw_status_page, 0, PAGE_SIZE); + DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page); + + I830_WRITE(0x02080, dev_priv->dma_status_page); + DRM_DEBUG("Enabled hardware status page\n"); + + /* Now we need to init our freelist */ + if(i830_freelist_init(dev, dev_priv) != 0) { + dev->dev_private = (void *)dev_priv; + i830_dma_cleanup(dev); + DRM_ERROR("Not enough space in the status page for" + " the freelist\n"); + return -ENOMEM; + } + dev->dev_private = (void *)dev_priv; + + return 0; +} + +int i830_dma_init(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_i830_private_t *dev_priv; + drm_i830_init_t init; + int retcode = 0; + + if (copy_from_user(&init, (drm_i830_init_t *)arg, sizeof(init))) + return -EFAULT; + + switch(init.func) { + case I830_INIT_DMA: + dev_priv = DRM(alloc)(sizeof(drm_i830_private_t), + DRM_MEM_DRIVER); + if(dev_priv == NULL) return -ENOMEM; + retcode = i830_dma_initialize(dev, dev_priv, &init); + break; + case I830_CLEANUP_DMA: + retcode = i830_dma_cleanup(dev); + break; + default: + retcode = -EINVAL; + break; + } + + return retcode; +} + +/* Most efficient way to verify state for the i830 is as it is + * emitted. Non-conformant state is silently dropped. + * + * Use 'volatile' & local var tmp to force the emitted values to be + * identical to the verified ones. + */ +static void i830EmitContextVerified( drm_device_t *dev, + volatile unsigned int *code ) +{ + drm_i830_private_t *dev_priv = dev->dev_private; + int i, j = 0; + unsigned int tmp; + RING_LOCALS; + + BEGIN_LP_RING( I830_CTX_SETUP_SIZE ); + for ( i = 0 ; i < I830_CTX_SETUP_SIZE ; i++ ) { + tmp = code[i]; + +#if 0 + if ((tmp & (7<<29)) == (3<<29) && + (tmp & (0x1f<<24)) < (0x1d<<24)) { + OUT_RING( tmp ); + j++; + } else { + printk("Skipping %d\n", i); + } +#else + OUT_RING( tmp ); + j++; +#endif + } + + if (j & 1) + OUT_RING( 0 ); + + ADVANCE_LP_RING(); +} + +static void i830EmitTexVerified( drm_device_t *dev, + volatile unsigned int *code ) +{ + drm_i830_private_t *dev_priv = dev->dev_private; + int i, j = 0; + unsigned int tmp; + RING_LOCALS; + + BEGIN_LP_RING( I830_TEX_SETUP_SIZE ); + + OUT_RING( GFX_OP_MAP_INFO ); + OUT_RING( code[I830_TEXREG_MI1] ); + OUT_RING( code[I830_TEXREG_MI2] ); + OUT_RING( code[I830_TEXREG_MI3] ); + OUT_RING( code[I830_TEXREG_MI4] ); + OUT_RING( code[I830_TEXREG_MI5] ); + + for ( i = 6 ; i < I830_TEX_SETUP_SIZE ; i++ ) { + tmp = code[i]; + OUT_RING( tmp ); + j++; + } + + if (j & 1) + OUT_RING( 0 ); + + ADVANCE_LP_RING(); +} + +static void i830EmitTexBlendVerified( drm_device_t *dev, + volatile unsigned int *code, + volatile unsigned int num) +{ + drm_i830_private_t *dev_priv = dev->dev_private; + int i, j = 0; + unsigned int tmp; + RING_LOCALS; + + BEGIN_LP_RING( num ); + + for ( i = 0 ; i < num ; i++ ) { + tmp = code[i]; + OUT_RING( tmp ); + j++; + } + + if (j & 1) + OUT_RING( 0 ); + + ADVANCE_LP_RING(); +} + +static void i830EmitTexPalette( drm_device_t *dev, + unsigned int *palette, + int number, + int is_shared ) +{ + drm_i830_private_t *dev_priv = dev->dev_private; + int i; + RING_LOCALS; + + BEGIN_LP_RING( 258 ); + + if(is_shared == 1) { + OUT_RING(CMD_OP_MAP_PALETTE_LOAD | + MAP_PALETTE_NUM(0) | + MAP_PALETTE_BOTH); + } else { + OUT_RING(CMD_OP_MAP_PALETTE_LOAD | MAP_PALETTE_NUM(number)); + } + for(i = 0; i < 256; i++) { + OUT_RING(palette[i]); + } + OUT_RING(0); +} + +/* Need to do some additional checking when setting the dest buffer. + */ +static void i830EmitDestVerified( drm_device_t *dev, + volatile unsigned int *code ) +{ + drm_i830_private_t *dev_priv = dev->dev_private; + unsigned int tmp; + RING_LOCALS; + + BEGIN_LP_RING( I830_DEST_SETUP_SIZE + 6 ); + + tmp = code[I830_DESTREG_CBUFADDR]; + if (tmp == dev_priv->front_di1) { + /* Don't use fence when front buffer rendering */ + OUT_RING( CMD_OP_DESTBUFFER_INFO ); + OUT_RING( BUF_3D_ID_COLOR_BACK | + BUF_3D_PITCH(dev_priv->back_pitch * dev_priv->cpp) ); + OUT_RING( tmp ); + + OUT_RING( CMD_OP_DESTBUFFER_INFO ); + OUT_RING( BUF_3D_ID_DEPTH | + BUF_3D_PITCH(dev_priv->depth_pitch * dev_priv->cpp)); + OUT_RING( dev_priv->zi1 ); + } else if(tmp == dev_priv->back_di1) { + OUT_RING( CMD_OP_DESTBUFFER_INFO ); + OUT_RING( BUF_3D_ID_COLOR_BACK | + BUF_3D_PITCH(dev_priv->back_pitch * dev_priv->cpp) | + BUF_3D_USE_FENCE); + OUT_RING( tmp ); + + OUT_RING( CMD_OP_DESTBUFFER_INFO ); + OUT_RING( BUF_3D_ID_DEPTH | BUF_3D_USE_FENCE | + BUF_3D_PITCH(dev_priv->depth_pitch * dev_priv->cpp)); + OUT_RING( dev_priv->zi1 ); + } else { + DRM_DEBUG("bad di1 %x (allow %x or %x)\n", + tmp, dev_priv->front_di1, dev_priv->back_di1); + } + + /* invarient: + */ + + + OUT_RING( GFX_OP_DESTBUFFER_VARS ); + OUT_RING( code[I830_DESTREG_DV1] ); + + OUT_RING( GFX_OP_DRAWRECT_INFO ); + OUT_RING( code[I830_DESTREG_DR1] ); + OUT_RING( code[I830_DESTREG_DR2] ); + OUT_RING( code[I830_DESTREG_DR3] ); + OUT_RING( code[I830_DESTREG_DR4] ); + + /* Need to verify this */ + tmp = code[I830_DESTREG_SENABLE]; + if((tmp & ~0x3) == GFX_OP_SCISSOR_ENABLE) { + OUT_RING( tmp ); + } else { + DRM_DEBUG("bad scissor enable\n"); + OUT_RING( 0 ); + } + + OUT_RING( code[I830_DESTREG_SENABLE] ); + + OUT_RING( GFX_OP_SCISSOR_RECT ); + OUT_RING( code[I830_DESTREG_SR1] ); + OUT_RING( code[I830_DESTREG_SR2] ); + + ADVANCE_LP_RING(); +} + +static void i830EmitState( drm_device_t *dev ) +{ + drm_i830_private_t *dev_priv = dev->dev_private; + drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv; + unsigned int dirty = sarea_priv->dirty; + + if (dirty & I830_UPLOAD_BUFFERS) { + i830EmitDestVerified( dev, sarea_priv->BufferState ); + sarea_priv->dirty &= ~I830_UPLOAD_BUFFERS; + } + + if (dirty & I830_UPLOAD_CTX) { + i830EmitContextVerified( dev, sarea_priv->ContextState ); + sarea_priv->dirty &= ~I830_UPLOAD_CTX; + } + + if (dirty & I830_UPLOAD_TEX0) { + i830EmitTexVerified( dev, sarea_priv->TexState[0] ); + sarea_priv->dirty &= ~I830_UPLOAD_TEX0; + } + + if (dirty & I830_UPLOAD_TEX1) { + i830EmitTexVerified( dev, sarea_priv->TexState[1] ); + sarea_priv->dirty &= ~I830_UPLOAD_TEX1; + } + + if (dirty & I830_UPLOAD_TEXBLEND0) { + i830EmitTexBlendVerified( dev, sarea_priv->TexBlendState[0], + sarea_priv->TexBlendStateWordsUsed[0]); + sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND0; + } + + if (dirty & I830_UPLOAD_TEXBLEND1) { + i830EmitTexBlendVerified( dev, sarea_priv->TexBlendState[1], + sarea_priv->TexBlendStateWordsUsed[1]); + sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND1; + } + + if (dirty & I830_UPLOAD_TEX_PALETTE_SHARED) { + i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 1); + } else { + if (dirty & I830_UPLOAD_TEX_PALETTE_N(0)) { + i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 0); + sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(0); + } + if (dirty & I830_UPLOAD_TEX_PALETTE_N(1)) { + i830EmitTexPalette(dev, sarea_priv->Palette[1], 1, 0); + sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(1); + } + } +} + +static void i830_dma_dispatch_clear( drm_device_t *dev, int flags, + unsigned int clear_color, + unsigned int clear_zval, + unsigned int clear_depthmask) +{ + drm_i830_private_t *dev_priv = dev->dev_private; + drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv; + int nbox = sarea_priv->nbox; + drm_clip_rect_t *pbox = sarea_priv->boxes; + int pitch = dev_priv->pitch; + int cpp = dev_priv->cpp; + int i; + unsigned int BR13, CMD, D_CMD; + RING_LOCALS; + + i830_kernel_lost_context(dev); + + switch(cpp) { + case 2: + BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24); + D_CMD = CMD = XY_COLOR_BLT_CMD; + break; + case 4: + BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24) | (1<<25); + CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA | + XY_COLOR_BLT_WRITE_RGB); + D_CMD = XY_COLOR_BLT_CMD; + if(clear_depthmask & 0x00ffffff) + D_CMD |= XY_COLOR_BLT_WRITE_RGB; + if(clear_depthmask & 0xff000000) + D_CMD |= XY_COLOR_BLT_WRITE_ALPHA; + break; + default: + BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24); + D_CMD = CMD = XY_COLOR_BLT_CMD; + break; + } + + if (nbox > I830_NR_SAREA_CLIPRECTS) + nbox = I830_NR_SAREA_CLIPRECTS; + + for (i = 0 ; i < nbox ; i++, pbox++) { + if (pbox->x1 > pbox->x2 || + pbox->y1 > pbox->y2 || + pbox->x2 > dev_priv->w || + pbox->y2 > dev_priv->h) + continue; + + if ( flags & I830_FRONT ) { + DRM_DEBUG("clear front\n"); + BEGIN_LP_RING( 6 ); + OUT_RING( CMD ); + OUT_RING( BR13 ); + OUT_RING( (pbox->y1 << 16) | pbox->x1 ); + OUT_RING( (pbox->y2 << 16) | pbox->x2 ); + OUT_RING( 0 ); + OUT_RING( clear_color ); + ADVANCE_LP_RING(); + } + + if ( flags & I830_BACK ) { + DRM_DEBUG("clear back\n"); + BEGIN_LP_RING( 6 ); + OUT_RING( CMD ); + OUT_RING( BR13 ); + OUT_RING( (pbox->y1 << 16) | pbox->x1 ); + OUT_RING( (pbox->y2 << 16) | pbox->x2 ); + OUT_RING( dev_priv->back_offset ); + OUT_RING( clear_color ); + ADVANCE_LP_RING(); + } + + if ( flags & I830_DEPTH ) { + DRM_DEBUG("clear depth\n"); + BEGIN_LP_RING( 6 ); + OUT_RING( D_CMD ); + OUT_RING( BR13 ); + OUT_RING( (pbox->y1 << 16) | pbox->x1 ); + OUT_RING( (pbox->y2 << 16) | pbox->x2 ); + OUT_RING( dev_priv->depth_offset ); + OUT_RING( clear_zval ); + ADVANCE_LP_RING(); + } + } +} + +static void i830_dma_dispatch_swap( drm_device_t *dev ) +{ + drm_i830_private_t *dev_priv = dev->dev_private; + drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv; + int nbox = sarea_priv->nbox; + drm_clip_rect_t *pbox = sarea_priv->boxes; + int pitch = dev_priv->pitch; + int cpp = dev_priv->cpp; + int ofs = dev_priv->back_offset; + int i; + unsigned int CMD, BR13; + RING_LOCALS; + + DRM_DEBUG("swapbuffers\n"); + + switch(cpp) { + case 2: + BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24); + CMD = XY_SRC_COPY_BLT_CMD; + break; + case 4: + BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24) | (1<<25); + CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | + XY_SRC_COPY_BLT_WRITE_RGB); + break; + default: + BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24); + CMD = XY_SRC_COPY_BLT_CMD; + break; + } + + i830_kernel_lost_context(dev); + + if (nbox > I830_NR_SAREA_CLIPRECTS) + nbox = I830_NR_SAREA_CLIPRECTS; + + for (i = 0 ; i < nbox; i++, pbox++) + { + if (pbox->x1 > pbox->x2 || + pbox->y1 > pbox->y2 || + pbox->x2 > dev_priv->w || + pbox->y2 > dev_priv->h) + continue; + + DRM_DEBUG("dispatch swap %d,%d-%d,%d!\n", + pbox->x1, pbox->y1, + pbox->x2, pbox->y2); + + BEGIN_LP_RING( 8 ); + OUT_RING( CMD ); + OUT_RING( BR13 ); + + OUT_RING( (pbox->y1 << 16) | + pbox->x1 ); + OUT_RING( (pbox->y2 << 16) | + pbox->x2 ); + + OUT_RING( 0 /* front ofs always zero */ ); + OUT_RING( (pbox->y1 << 16) | + pbox->x1 ); + + OUT_RING( BR13 & 0xffff ); + OUT_RING( ofs ); + + ADVANCE_LP_RING(); + } +} + + +static void i830_dma_dispatch_vertex(drm_device_t *dev, + drm_buf_t *buf, + int discard, + int used) +{ + drm_i830_private_t *dev_priv = dev->dev_private; + drm_i830_buf_priv_t *buf_priv = buf->dev_private; + drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv; + drm_clip_rect_t *box = sarea_priv->boxes; + int nbox = sarea_priv->nbox; + unsigned long address = (unsigned long)buf->bus_address; + unsigned long start = address - dev->agp->base; + int i = 0, u; + RING_LOCALS; + + i830_kernel_lost_context(dev); + + if (nbox > I830_NR_SAREA_CLIPRECTS) + nbox = I830_NR_SAREA_CLIPRECTS; + + if (discard) { + u = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, + I830_BUF_HARDWARE); + if(u != I830_BUF_CLIENT) { + DRM_DEBUG("xxxx 2\n"); + } + } + + if (used > 4*1024) + used = 0; + + if (sarea_priv->dirty) + i830EmitState( dev ); + + DRM_DEBUG("dispatch vertex addr 0x%lx, used 0x%x nbox %d\n", + address, used, nbox); + + dev_priv->counter++; + DRM_DEBUG( "dispatch counter : %ld\n", dev_priv->counter); + DRM_DEBUG( "i830_dma_dispatch\n"); + DRM_DEBUG( "start : %lx\n", start); + DRM_DEBUG( "used : %d\n", used); + DRM_DEBUG( "start + used - 4 : %ld\n", start + used - 4); + + if (buf_priv->currently_mapped == I830_BUF_MAPPED) { + *(u32 *)buf_priv->virtual = (GFX_OP_PRIMITIVE | + sarea_priv->vertex_prim | + ((used/4)-2)); + + if (used & 4) { + *(u32 *)((u32)buf_priv->virtual + used) = 0; + used += 4; + } + + i830_unmap_buffer(buf); + } + + if (used) { + do { + if (i < nbox) { + BEGIN_LP_RING(6); + OUT_RING( GFX_OP_DRAWRECT_INFO ); + OUT_RING( sarea_priv->BufferState[I830_DESTREG_DR1] ); + OUT_RING( box[i].x1 | (box[i].y1<<16) ); + OUT_RING( box[i].x2 | (box[i].y2<<16) ); + OUT_RING( sarea_priv->BufferState[I830_DESTREG_DR4] ); + OUT_RING( 0 ); + ADVANCE_LP_RING(); + } + + BEGIN_LP_RING(4); + + OUT_RING( MI_BATCH_BUFFER ); + OUT_RING( start | MI_BATCH_NON_SECURE ); + OUT_RING( start + used - 4 ); + OUT_RING( 0 ); + ADVANCE_LP_RING(); + + } while (++i < nbox); + } + + BEGIN_LP_RING(10); + OUT_RING( CMD_STORE_DWORD_IDX ); + OUT_RING( 20 ); + OUT_RING( dev_priv->counter ); + OUT_RING( 0 ); + + if (discard) { + OUT_RING( CMD_STORE_DWORD_IDX ); + OUT_RING( buf_priv->my_use_idx ); + OUT_RING( I830_BUF_FREE ); + OUT_RING( 0 ); + } + + OUT_RING( CMD_REPORT_HEAD ); + OUT_RING( 0 ); + ADVANCE_LP_RING(); +} + +/* Interrupts are only for flushing */ +void i830_dma_service(int irq, void *device, struct pt_regs *regs) +{ + drm_device_t *dev = (drm_device_t *)device; + drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private; + u16 temp; + + temp = I830_READ16(I830REG_INT_IDENTITY_R); + temp = temp & ~(0x6000); + if(temp != 0) I830_WRITE16(I830REG_INT_IDENTITY_R, + temp); /* Clear all interrupts */ + else + return; + + queue_task(&dev->tq, &tq_immediate); + mark_bh(IMMEDIATE_BH); +} + +void DRM(dma_immediate_bh)(void *device) +{ + drm_device_t *dev = (drm_device_t *) device; + drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private; + + atomic_set(&dev_priv->flush_done, 1); + wake_up_interruptible(&dev_priv->flush_queue); +} + +static inline void i830_dma_emit_flush(drm_device_t *dev) +{ + drm_i830_private_t *dev_priv = dev->dev_private; + RING_LOCALS; + + i830_kernel_lost_context(dev); + + BEGIN_LP_RING(2); + OUT_RING( CMD_REPORT_HEAD ); + OUT_RING( GFX_OP_USER_INTERRUPT ); + ADVANCE_LP_RING(); + + i830_wait_ring( dev, dev_priv->ring.Size - 8 ); + atomic_set(&dev_priv->flush_done, 1); + wake_up_interruptible(&dev_priv->flush_queue); +} + +static inline void i830_dma_quiescent_emit(drm_device_t *dev) +{ + drm_i830_private_t *dev_priv = dev->dev_private; + RING_LOCALS; + + i830_kernel_lost_context(dev); + + BEGIN_LP_RING(4); + OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE ); + OUT_RING( CMD_REPORT_HEAD ); + OUT_RING( 0 ); + OUT_RING( GFX_OP_USER_INTERRUPT ); + ADVANCE_LP_RING(); + + i830_wait_ring( dev, dev_priv->ring.Size - 8 ); + atomic_set(&dev_priv->flush_done, 1); + wake_up_interruptible(&dev_priv->flush_queue); +} + +void i830_dma_quiescent(drm_device_t *dev) +{ + DECLARE_WAITQUEUE(entry, current); + drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private; + unsigned long end; + + if(dev_priv == NULL) { + return; + } + atomic_set(&dev_priv->flush_done, 0); + add_wait_queue(&dev_priv->flush_queue, &entry); + end = jiffies + (HZ*3); + + for (;;) { + current->state = TASK_INTERRUPTIBLE; + i830_dma_quiescent_emit(dev); + if (atomic_read(&dev_priv->flush_done) == 1) break; + if(time_before(end, jiffies)) { + DRM_ERROR("lockup\n"); + break; + } + schedule_timeout(HZ*3); + if (signal_pending(current)) { + break; + } + } + + current->state = TASK_RUNNING; + remove_wait_queue(&dev_priv->flush_queue, &entry); + + return; +} + +static int i830_flush_queue(drm_device_t *dev) +{ + DECLARE_WAITQUEUE(entry, current); + drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private; + drm_device_dma_t *dma = dev->dma; + unsigned long end; + int i, ret = 0; + + if(dev_priv == NULL) { + return 0; + } + atomic_set(&dev_priv->flush_done, 0); + add_wait_queue(&dev_priv->flush_queue, &entry); + end = jiffies + (HZ*3); + for (;;) { + current->state = TASK_INTERRUPTIBLE; + i830_dma_emit_flush(dev); + if (atomic_read(&dev_priv->flush_done) == 1) break; + if(time_before(end, jiffies)) { + DRM_ERROR("lockup\n"); + break; + } + schedule_timeout(HZ*3); + if (signal_pending(current)) { + ret = -EINTR; /* Can't restart */ + break; + } + } + + current->state = TASK_RUNNING; + remove_wait_queue(&dev_priv->flush_queue, &entry); + + + for (i = 0; i < dma->buf_count; i++) { + drm_buf_t *buf = dma->buflist[ i ]; + drm_i830_buf_priv_t *buf_priv = buf->dev_private; + + int used = cmpxchg(buf_priv->in_use, I830_BUF_HARDWARE, + I830_BUF_FREE); + + if (used == I830_BUF_HARDWARE) + DRM_DEBUG("reclaimed from HARDWARE\n"); + if (used == I830_BUF_CLIENT) + DRM_DEBUG("still on client HARDWARE\n"); + } + + return ret; +} + +/* Must be called with the lock held */ +void i830_reclaim_buffers(drm_device_t *dev, pid_t pid) +{ + drm_device_dma_t *dma = dev->dma; + int i; + + if (!dma) return; + if (!dev->dev_private) return; + if (!dma->buflist) return; + + i830_flush_queue(dev); + + for (i = 0; i < dma->buf_count; i++) { + drm_buf_t *buf = dma->buflist[ i ]; + drm_i830_buf_priv_t *buf_priv = buf->dev_private; + + if (buf->pid == pid && buf_priv) { + int used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, + I830_BUF_FREE); + + if (used == I830_BUF_CLIENT) + DRM_DEBUG("reclaimed from client\n"); + if(buf_priv->currently_mapped == I830_BUF_MAPPED) + buf_priv->currently_mapped = I830_BUF_UNMAPPED; + } + } +} + +int i830_flush_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + + DRM_DEBUG("i830_flush_ioctl\n"); + if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { + DRM_ERROR("i830_flush_ioctl called without lock held\n"); + return -EINVAL; + } + + i830_flush_queue(dev); + return 0; +} + +int i830_dma_vertex(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_device_dma_t *dma = dev->dma; + drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private; + u32 *hw_status = (u32 *)dev_priv->hw_status_page; + drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *) + dev_priv->sarea_priv; + drm_i830_vertex_t vertex; + + if (copy_from_user(&vertex, (drm_i830_vertex_t *)arg, sizeof(vertex))) + return -EFAULT; + + if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { + DRM_ERROR("i830_dma_vertex called without lock held\n"); + return -EINVAL; + } + + DRM_DEBUG("i830 dma vertex, idx %d used %d discard %d\n", + vertex.idx, vertex.used, vertex.discard); + + if(vertex.idx < 0 || vertex.idx > dma->buf_count) return -EINVAL; + + i830_dma_dispatch_vertex( dev, + dma->buflist[ vertex.idx ], + vertex.discard, vertex.used ); + + sarea_priv->last_enqueue = dev_priv->counter-1; + sarea_priv->last_dispatch = (int) hw_status[5]; + + return 0; +} + +int i830_clear_bufs(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_i830_clear_t clear; + + if (copy_from_user(&clear, (drm_i830_clear_t *)arg, sizeof(clear))) + return -EFAULT; + + if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { + DRM_ERROR("i830_clear_bufs called without lock held\n"); + return -EINVAL; + } + + /* GH: Someone's doing nasty things... */ + if (!dev->dev_private) { + return -EINVAL; + } + + i830_dma_dispatch_clear( dev, clear.flags, + clear.clear_color, + clear.clear_depth, + clear.clear_depthmask); + return 0; +} + +int i830_swap_bufs(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + + DRM_DEBUG("i830_swap_bufs\n"); + + if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { + DRM_ERROR("i830_swap_buf called without lock held\n"); + return -EINVAL; + } + + i830_dma_dispatch_swap( dev ); + return 0; +} + +int i830_getage(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private; + u32 *hw_status = (u32 *)dev_priv->hw_status_page; + drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *) + dev_priv->sarea_priv; + + sarea_priv->last_dispatch = (int) hw_status[5]; + return 0; +} + +int i830_getbuf(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + int retcode = 0; + drm_i830_dma_t d; + drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private; + u32 *hw_status = (u32 *)dev_priv->hw_status_page; + drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *) + dev_priv->sarea_priv; + + DRM_DEBUG("getbuf\n"); + if (copy_from_user(&d, (drm_i830_dma_t *)arg, sizeof(d))) + return -EFAULT; + + if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { + DRM_ERROR("i830_dma called without lock held\n"); + return -EINVAL; + } + + d.granted = 0; + + retcode = i830_dma_get_buffer(dev, &d, filp); + + DRM_DEBUG("i830_dma: %d returning %d, granted = %d\n", + current->pid, retcode, d.granted); + + if (copy_to_user((drm_dma_t *)arg, &d, sizeof(d))) + return -EFAULT; + sarea_priv->last_dispatch = (int) hw_status[5]; + + return retcode; +} + +int i830_copybuf(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_i830_copy_t d; + drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private; + u32 *hw_status = (u32 *)dev_priv->hw_status_page; + drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *) + dev_priv->sarea_priv; + drm_buf_t *buf; + drm_i830_buf_priv_t *buf_priv; + drm_device_dma_t *dma = dev->dma; + + if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { + DRM_ERROR("i830_dma called without lock held\n"); + return -EINVAL; + } + + if (copy_from_user(&d, (drm_i830_copy_t *)arg, sizeof(d))) + return -EFAULT; + + if(d.idx < 0 || d.idx > dma->buf_count) return -EINVAL; + buf = dma->buflist[ d.idx ]; + buf_priv = buf->dev_private; + if (buf_priv->currently_mapped != I830_BUF_MAPPED) return -EPERM; + + if(d.used < 0 || d.used > buf->total) return -EINVAL; + + if (copy_from_user(buf_priv->virtual, d.address, d.used)) + return -EFAULT; + + sarea_priv->last_dispatch = (int) hw_status[5]; + + return 0; +} + +int i830_docopy(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + if(VM_DONTCOPY == 0) return 1; + return 0; +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/drm/i830_drm.h linux.19rc3-ac4/drivers/char/drm/i830_drm.h --- linux.19rc3/drivers/char/drm/i830_drm.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/drm/i830_drm.h 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,238 @@ +#ifndef _I830_DRM_H_ +#define _I830_DRM_H_ + +/* WARNING: These defines must be the same as what the Xserver uses. + * if you change them, you must change the defines in the Xserver. + */ + +#ifndef _I830_DEFINES_ +#define _I830_DEFINES_ + +#define I830_DMA_BUF_ORDER 12 +#define I830_DMA_BUF_SZ (1< + * Jeff Hartmann + * Gareth Hughes + * Abraham vd Merwe + */ + +#include +#include "i830.h" +#include "drmP.h" +#include "i830_drv.h" + +#define DRIVER_AUTHOR "VA Linux Systems Inc." + +#define DRIVER_NAME "i830" +#define DRIVER_DESC "Intel 830M" +#define DRIVER_DATE "20011004" + +#define DRIVER_MAJOR 1 +#define DRIVER_MINOR 2 +#define DRIVER_PATCHLEVEL 0 + +#define DRIVER_IOCTLS \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_INIT)] = { i830_dma_init, 1, 1 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_VERTEX)] = { i830_dma_vertex, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_CLEAR)] = { i830_clear_bufs, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_FLUSH)] = { i830_flush_ioctl, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_GETAGE)] = { i830_getage, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_GETBUF)] = { i830_getbuf, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_SWAP)] = { i830_swap_bufs, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_COPY)] = { i830_copybuf, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_DOCOPY)] = { i830_docopy, 1, 0 }, + +#define __HAVE_COUNTERS 4 +#define __HAVE_COUNTER6 _DRM_STAT_IRQ +#define __HAVE_COUNTER7 _DRM_STAT_PRIMARY +#define __HAVE_COUNTER8 _DRM_STAT_SECONDARY +#define __HAVE_COUNTER9 _DRM_STAT_DMA + + +#include "drm_agpsupport.h" +#include "drm_auth.h" +#include "drm_bufs.h" +#include "drm_context.h" +#include "drm_dma.h" +#include "drm_drawable.h" +#include "drm_drv.h" + +#ifndef MODULE +/* DRM(options) is called by the kernel to parse command-line options + * passed via the boot-loader (e.g., LILO). It calls the insmod option + * routine, drm_parse_drm. + */ + +/* JH- We have to hand expand the string ourselves because of the cpp. If + * anyone can think of a way that we can fit into the __setup macro without + * changing it, then please send the solution my way. + */ +static int __init i830_options( char *str ) +{ + DRM(parse_options)( str ); + return 1; +} + +__setup( DRIVER_NAME "=", i830_options ); +#endif + +#include "drm_fops.h" +#include "drm_init.h" +#include "drm_ioctl.h" +#include "drm_lock.h" +#include "drm_lists.h" +#include "drm_memory.h" +#include "drm_proc.h" +#include "drm_vm.h" +#include "drm_stub.h" diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/drm/i830_drv.h linux.19rc3-ac4/drivers/char/drm/i830_drv.h --- linux.19rc3/drivers/char/drm/i830_drv.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/drm/i830_drv.h 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,215 @@ +/* i830_drv.h -- Private header for the I830 driver -*- linux-c -*- + * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: Rickard E. (Rik) Faith + * Jeff Hartmann + * + */ + +#ifndef _I830_DRV_H_ +#define _I830_DRV_H_ + +typedef struct drm_i830_buf_priv { + u32 *in_use; + int my_use_idx; + int currently_mapped; + void *virtual; + void *kernel_virtual; + int map_count; + struct vm_area_struct *vma; +} drm_i830_buf_priv_t; + +typedef struct _drm_i830_ring_buffer{ + int tail_mask; + unsigned long Start; + unsigned long End; + unsigned long Size; + u8 *virtual_start; + int head; + int tail; + int space; +} drm_i830_ring_buffer_t; + +typedef struct drm_i830_private { + drm_map_t *sarea_map; + drm_map_t *buffer_map; + drm_map_t *mmio_map; + + drm_i830_sarea_t *sarea_priv; + drm_i830_ring_buffer_t ring; + + u8 *hw_status_page; + unsigned long counter; + + dma_addr_t dma_status_page; + + atomic_t flush_done; + wait_queue_head_t flush_queue; /* Processes waiting until flush */ + drm_buf_t *mmap_buffer; + + u32 front_di1, back_di1, zi1; + + int back_offset; + int depth_offset; + int w, h; + int pitch; + int back_pitch; + int depth_pitch; + unsigned int cpp; +} drm_i830_private_t; + + /* i830_dma.c */ +extern int i830_dma_schedule(drm_device_t *dev, int locked); +extern int i830_getbuf(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int i830_dma_init(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int i830_flush_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern void i830_reclaim_buffers(drm_device_t *dev, pid_t pid); +extern int i830_getage(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg); +extern int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma); +extern int i830_copybuf(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int i830_docopy(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); + +extern void i830_dma_quiescent(drm_device_t *dev); + +extern int i830_dma_vertex(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); + +extern int i830_swap_bufs(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); + +extern int i830_clear_bufs(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); + +#define I830_VERBOSE 0 + +#define I830_BASE(reg) ((unsigned long) \ + dev_priv->mmio_map->handle) +#define I830_ADDR(reg) (I830_BASE(reg) + reg) +#define I830_DEREF(reg) *(__volatile__ int *)I830_ADDR(reg) +#define I830_READ(reg) I830_DEREF(reg) +#define I830_WRITE(reg,val) do { I830_DEREF(reg) = val; } while (0) +#define I830_DEREF16(reg) *(__volatile__ u16 *)I830_ADDR(reg) +#define I830_READ16(reg) I830_DEREF16(reg) +#define I830_WRITE16(reg,val) do { I830_DEREF16(reg) = val; } while (0) + +#define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23)) +#define GFX_OP_BREAKPOINT_INTERRUPT ((0<<29)|(1<<23)) +#define CMD_REPORT_HEAD (7<<23) +#define CMD_STORE_DWORD_IDX ((0x21<<23) | 0x1) +#define CMD_OP_BATCH_BUFFER ((0x0<<29)|(0x30<<23)|0x1) + +#define INST_PARSER_CLIENT 0x00000000 +#define INST_OP_FLUSH 0x02000000 +#define INST_FLUSH_MAP_CACHE 0x00000001 + + +#define BB1_START_ADDR_MASK (~0x7) +#define BB1_PROTECTED (1<<0) +#define BB1_UNPROTECTED (0<<0) +#define BB2_END_ADDR_MASK (~0x7) + +#define I830REG_HWSTAM 0x02098 +#define I830REG_INT_IDENTITY_R 0x020a4 +#define I830REG_INT_MASK_R 0x020a8 +#define I830REG_INT_ENABLE_R 0x020a0 + +#define LP_RING 0x2030 +#define HP_RING 0x2040 +#define RING_TAIL 0x00 +#define TAIL_ADDR 0x000FFFF8 +#define RING_HEAD 0x04 +#define HEAD_WRAP_COUNT 0xFFE00000 +#define HEAD_WRAP_ONE 0x00200000 +#define HEAD_ADDR 0x001FFFFC +#define RING_START 0x08 +#define START_ADDR 0x00FFFFF8 +#define RING_LEN 0x0C +#define RING_NR_PAGES 0x000FF000 +#define RING_REPORT_MASK 0x00000006 +#define RING_REPORT_64K 0x00000002 +#define RING_REPORT_128K 0x00000004 +#define RING_NO_REPORT 0x00000000 +#define RING_VALID_MASK 0x00000001 +#define RING_VALID 0x00000001 +#define RING_INVALID 0x00000000 + +#define GFX_OP_SCISSOR ((0x3<<29)|(0x1c<<24)|(0x10<<19)) +#define SC_UPDATE_SCISSOR (0x1<<1) +#define SC_ENABLE_MASK (0x1<<0) +#define SC_ENABLE (0x1<<0) + +#define GFX_OP_SCISSOR_INFO ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1)) +#define SCI_YMIN_MASK (0xffff<<16) +#define SCI_XMIN_MASK (0xffff<<0) +#define SCI_YMAX_MASK (0xffff<<16) +#define SCI_XMAX_MASK (0xffff<<0) + +#define GFX_OP_SCISSOR_ENABLE ((0x3<<29)|(0x1c<<24)|(0x10<<19)) +#define GFX_OP_SCISSOR_RECT ((0x3<<29)|(0x1d<<24)|(0x81<<16)|1) +#define GFX_OP_COLOR_FACTOR ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0) +#define GFX_OP_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16)) +#define GFX_OP_MAP_INFO ((0x3<<29)|(0x1d<<24)|0x4) +#define GFX_OP_DESTBUFFER_VARS ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0) +#define GFX_OP_DRAWRECT_INFO ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3)) +#define GFX_OP_PRIMITIVE ((0x3<<29)|(0x1f<<24)) + +#define CMD_OP_DESTBUFFER_INFO ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1) + + +#define BR00_BITBLT_CLIENT 0x40000000 +#define BR00_OP_COLOR_BLT 0x10000000 +#define BR00_OP_SRC_COPY_BLT 0x10C00000 +#define BR13_SOLID_PATTERN 0x80000000 + +#define BUF_3D_ID_COLOR_BACK (0x3<<24) +#define BUF_3D_ID_DEPTH (0x7<<24) +#define BUF_3D_USE_FENCE (1<<23) +#define BUF_3D_PITCH(x) (((x)/4)<<2) + +#define CMD_OP_MAP_PALETTE_LOAD ((3<<29)|(0x1d<<24)|(0x82<<16)|255) +#define MAP_PALETTE_NUM(x) ((x<<8) & (1<<8)) +#define MAP_PALETTE_BOTH (1<<11) + +#define XY_COLOR_BLT_CMD ((2<<29)|(0x50<<22)|0x4) +#define XY_COLOR_BLT_WRITE_ALPHA (1<<21) +#define XY_COLOR_BLT_WRITE_RGB (1<<20) + +#define XY_SRC_COPY_BLT_CMD ((2<<29)|(0x53<<22)|6) +#define XY_SRC_COPY_BLT_WRITE_ALPHA (1<<21) +#define XY_SRC_COPY_BLT_WRITE_RGB (1<<20) + +#define MI_BATCH_BUFFER ((0x30<<23)|1) +#define MI_BATCH_NON_SECURE (1) + + +#endif + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/drm/i830.h linux.19rc3-ac4/drivers/char/drm/i830.h --- linux.19rc3/drivers/char/drm/i830.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/drm/i830.h 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,116 @@ +/* i830.h -- Intel I830 DRM template customization -*- linux-c -*- + * Created: Thu Feb 15 00:01:12 2001 by gareth@valinux.com + * + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Gareth Hughes + */ + +#ifndef __I830_H__ +#define __I830_H__ + +/* This remains constant for all DRM template files. + */ +#define DRM(x) i830_##x + +/* General customization: + */ +#define __HAVE_AGP 1 +#define __MUST_HAVE_AGP 1 +#define __HAVE_MTRR 1 +#define __HAVE_CTX_BITMAP 1 + +/* Driver customization: + */ +#define __HAVE_RELEASE 1 +#define DRIVER_RELEASE() do { \ + i830_reclaim_buffers( dev, priv->pid ); \ +} while (0) + +/* DMA customization: + */ +#define __HAVE_DMA 1 +#define __HAVE_DMA_QUEUE 1 +#define __HAVE_DMA_WAITLIST 1 +#define __HAVE_DMA_RECLAIM 1 + +#define __HAVE_DMA_QUIESCENT 1 +#define DRIVER_DMA_QUIESCENT() do { \ + i830_dma_quiescent( dev ); \ +} while (0) + +#define __HAVE_DMA_IRQ 1 +#define __HAVE_DMA_IRQ_BH 1 +#define __HAVE_SHARED_IRQ 1 +#define DRIVER_PREINSTALL() do { \ + drm_i830_private_t *dev_priv = \ + (drm_i830_private_t *)dev->dev_private; \ + u16 tmp; \ + tmp = I830_READ16( I830REG_HWSTAM ); \ + tmp = tmp & 0x6000; \ + I830_WRITE16( I830REG_HWSTAM, tmp ); \ + \ + tmp = I830_READ16( I830REG_INT_MASK_R ); \ + tmp = tmp & 0x6000; /* Unmask interrupts */ \ + I830_WRITE16( I830REG_INT_MASK_R, tmp ); \ + tmp = I830_READ16( I830REG_INT_ENABLE_R ); \ + tmp = tmp & 0x6000; /* Disable all interrupts */ \ + I830_WRITE16( I830REG_INT_ENABLE_R, tmp ); \ +} while (0) + +#define DRIVER_POSTINSTALL() do { \ + drm_i830_private_t *dev_priv = \ + (drm_i830_private_t *)dev->dev_private; \ + u16 tmp; \ + tmp = I830_READ16( I830REG_INT_ENABLE_R ); \ + tmp = tmp & 0x6000; \ + tmp = tmp | 0x0003; /* Enable bp & user interrupts */ \ + I830_WRITE16( I830REG_INT_ENABLE_R, tmp ); \ +} while (0) + +#define DRIVER_UNINSTALL() do { \ + drm_i830_private_t *dev_priv = \ + (drm_i830_private_t *)dev->dev_private; \ + u16 tmp; \ + if ( dev_priv ) { \ + tmp = I830_READ16( I830REG_INT_IDENTITY_R ); \ + tmp = tmp & ~(0x6000); /* Clear all interrupts */ \ + if ( tmp != 0 ) \ + I830_WRITE16( I830REG_INT_IDENTITY_R, tmp ); \ + \ + tmp = I830_READ16( I830REG_INT_ENABLE_R ); \ + tmp = tmp & 0x6000; /* Disable all interrupts */ \ + I830_WRITE16( I830REG_INT_ENABLE_R, tmp ); \ + } \ +} while (0) + +/* Buffer customization: + */ + +#define DRIVER_BUF_PRIV_T drm_i830_buf_priv_t + +#define DRIVER_AGP_BUFFERS_MAP( dev ) \ + ((drm_i830_private_t *)((dev)->dev_private))->buffer_map + +#endif diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/drm/Makefile linux.19rc3-ac4/drivers/char/drm/Makefile --- linux.19rc3/drivers/char/drm/Makefile 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/drm/Makefile 2002-07-29 13:58:39.000000000 +0100 @@ -3,13 +3,15 @@ # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. O_TARGET := drm.o -list-multi := gamma.o tdfx.o r128.o mga.o i810.o radeon.o ffb.o sis.o +list-multi := gamma.o tdfx.o r128.o mga.o i810.o i830.o radeon.o ffb.o sis.o gamma-objs := gamma_drv.o gamma_dma.o tdfx-objs := tdfx_drv.o r128-objs := r128_drv.o r128_cce.o r128_state.o mga-objs := mga_drv.o mga_dma.o mga_state.o mga_warp.o i810-objs := i810_drv.o i810_dma.o +i830-objs := i830_drv.o i830_dma.o + radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o ffb-objs := ffb_drv.o ffb_context.o sis-objs := sis_drv.o sis_ds.o sis_mm.o @@ -20,6 +22,7 @@ obj-$(CONFIG_DRM_RADEON)+= radeon.o obj-$(CONFIG_DRM_MGA) += mga.o obj-$(CONFIG_DRM_I810) += i810.o +obj-$(CONFIG_DRM_I830) += i830.o obj-$(CONFIG_DRM_FFB) += ffb.o obj-$(CONFIG_DRM_SIS) += sis.o @@ -37,6 +40,9 @@ i810.o: $(i810-objs) $(lib) $(LD) -r -o $@ $(i810-objs) $(lib) +i830.o: $(i830-objs) $(lib) + $(LD) -r -o $@ $(i830-objs) $(lib) + r128.o: $(r128-objs) $(lib) $(LD) -r -o $@ $(r128-objs) $(lib) diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/drm/mga_drv.h linux.19rc3-ac4/drivers/char/drm/mga_drv.h --- linux.19rc3/drivers/char/drm/mga_drv.h 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/drm/mga_drv.h 2002-07-29 18:20:03.000000000 +0100 @@ -213,7 +213,7 @@ } else if ( dev_priv->prim.space < \ dev_priv->prim.high_mark ) { \ if ( MGA_DMA_DEBUG ) \ - DRM_INFO( __FUNCTION__": wrap...\n" ); \ + DRM_INFO( "%s: wrap...\n", __FUNCTION__ ); \ return -EBUSY; \ } \ } \ @@ -224,7 +224,7 @@ if ( test_bit( 0, &dev_priv->prim.wrapped ) ) { \ if ( mga_do_wait_for_idle( dev_priv ) < 0 ) { \ if ( MGA_DMA_DEBUG ) \ - DRM_INFO( __FUNCTION__": wrap...\n" ); \ + DRM_INFO( "%s: wrap...\n", __FUNCTION__ ); \ return -EBUSY; \ } \ mga_do_dma_wrap_end( dev_priv ); \ @@ -276,7 +276,7 @@ #define FLUSH_DMA() \ do { \ if ( 0 ) { \ - DRM_INFO( __FUNCTION__ ":\n" ); \ + DRM_INFO( "%s:\n" , __FUNCTION__); \ DRM_INFO( " tail=0x%06x head=0x%06lx\n", \ dev_priv->prim.tail, \ MGA_READ( MGA_PRIMADDRESS ) - \ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/drm/mga_state.c linux.19rc3-ac4/drivers/char/drm/mga_state.c --- linux.19rc3/drivers/char/drm/mga_state.c 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/drm/mga_state.c 2002-07-29 18:19:10.000000000 +0100 @@ -513,7 +513,7 @@ int nbox = sarea_priv->nbox; int i; DMA_LOCALS; - DRM_DEBUG( __FUNCTION__ ":\n" ); + DRM_DEBUG("%s:\n" , __FUNCTION__); BEGIN_DMA( 1 ); @@ -607,7 +607,7 @@ int nbox = sarea_priv->nbox; int i; DMA_LOCALS; - DRM_DEBUG( __FUNCTION__ ":\n" ); + DRM_DEBUG( "%s:\n", __FUNCTION__ ); sarea_priv->last_frame.head = dev_priv->prim.tail; sarea_priv->last_frame.wrap = dev_priv->prim.last_wrap; @@ -816,7 +816,7 @@ int nbox = sarea_priv->nbox; u32 scandir = 0, i; DMA_LOCALS; - DRM_DEBUG( __FUNCTION__ ":\n" ); + DRM_DEBUG( "%s:\n", __FUNCTION__ ); BEGIN_DMA( 4 + nbox ); @@ -1019,7 +1019,7 @@ drm_buf_t *buf; drm_mga_buf_priv_t *buf_priv; drm_mga_iload_t iload; - DRM_DEBUG( __FUNCTION__ ":\n" ); + DRM_DEBUG( "%s:\n", __FUNCTION__ ); LOCK_TEST_WITH_RETURN( dev ); @@ -1029,7 +1029,7 @@ #if 0 if ( mga_do_wait_for_idle( dev_priv ) < 0 ) { if ( MGA_DMA_DEBUG ) - DRM_INFO( __FUNCTION__": -EBUSY\n" ); + DRM_INFO( "%s: -EBUSY\n" , __FUNCTION__); return -EBUSY; } #endif diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/drm/picker.c linux.19rc3-ac4/drivers/char/drm/picker.c --- linux.19rc3/drivers/char/drm/picker.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/drm/picker.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,30 @@ + +#include +#include + +#ifndef CONFIG_SMP +#define CONFIG_SMP 0 +#endif + +#ifndef CONFIG_MODULES +#define CONFIG_MODULES 0 +#endif + +#ifndef CONFIG_MODVERSIONS +#define CONFIG_MODVERSIONS 0 +#endif + +#ifndef CONFIG_AGP_MODULE +#define CONFIG_AGP_MODULE 0 +#endif + +#ifndef CONFIG_AGP +#define CONFIG_AGP 0 +#endif + +SMP = CONFIG_SMP +MODULES = CONFIG_MODULES +MODVERSIONS = CONFIG_MODVERSIONS +AGP = CONFIG_AGP +AGP_MODULE = CONFIG_AGP_MODULE +RELEASE = UTS_RELEASE diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/drm/r128_drv.c linux.19rc3-ac4/drivers/char/drm/r128_drv.c --- linux.19rc3/drivers/char/drm/r128_drv.c 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/drm/r128_drv.c 2002-07-29 13:58:39.000000000 +0100 @@ -39,11 +39,11 @@ #define DRIVER_NAME "r128" #define DRIVER_DESC "ATI Rage 128" -#define DRIVER_DATE "20010405" +#define DRIVER_DATE "20010917" #define DRIVER_MAJOR 2 -#define DRIVER_MINOR 1 -#define DRIVER_PATCHLEVEL 6 +#define DRIVER_MINOR 2 +#define DRIVER_PATCHLEVEL 0 #define DRIVER_IOCTLS \ [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { r128_cce_buffers, 1, 0 }, \ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/drm/r128_drv.h linux.19rc3-ac4/drivers/char/drm/r128_drv.h --- linux.19rc3/drivers/char/drm/r128_drv.h 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/drm/r128_drv.h 2002-07-29 18:16:05.000000000 +0100 @@ -469,7 +469,7 @@ DRM_ERROR( "ring space check failed!\n" ); \ return -EBUSY; \ } \ - __ring_space_done: \ + __ring_space_done: ; \ } while (0) #define VB_AGE_TEST_WITH_RETURN( dev_priv ) \ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/drm/r128_state.c linux.19rc3-ac4/drivers/char/drm/r128_state.c --- linux.19rc3/drivers/char/drm/r128_state.c 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/drm/r128_state.c 2002-07-29 13:58:39.000000000 +0100 @@ -1519,10 +1519,75 @@ { drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; + drm_r128_private_t *dev_priv = dev->dev_private; + drm_device_dma_t *dma = dev->dma; + drm_buf_t *buf; + drm_r128_buf_priv_t *buf_priv; + drm_r128_indirect_t indirect; +#if 0 + RING_LOCALS; +#endif LOCK_TEST_WITH_RETURN( dev ); - /* Indirect buffer firing is not supported at this time. + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return -EINVAL; + } + + if ( copy_from_user( &indirect, (drm_r128_indirect_t *)arg, + sizeof(indirect) ) ) + return -EFAULT; + + DRM_DEBUG( "indirect: idx=%d s=%d e=%d d=%d\n", + indirect.idx, indirect.start, + indirect.end, indirect.discard ); + + if ( indirect.idx < 0 || indirect.idx >= dma->buf_count ) { + DRM_ERROR( "buffer index %d (of %d max)\n", + indirect.idx, dma->buf_count - 1 ); + return -EINVAL; + } + + buf = dma->buflist[indirect.idx]; + buf_priv = buf->dev_private; + + if ( buf->pid != current->pid ) { + DRM_ERROR( "process %d using buffer owned by %d\n", + current->pid, buf->pid ); + return -EINVAL; + } + if ( buf->pending ) { + DRM_ERROR( "sending pending buffer %d\n", indirect.idx ); + return -EINVAL; + } + + if ( indirect.start < buf->used ) { + DRM_ERROR( "reusing indirect: start=0x%x actual=0x%x\n", + indirect.start, buf->used ); + return -EINVAL; + } + + RING_SPACE_TEST_WITH_RETURN( dev_priv ); + VB_AGE_TEST_WITH_RETURN( dev_priv ); + + buf->used = indirect.end; + buf_priv->discard = indirect.discard; + +#if 0 + /* Wait for the 3D stream to idle before the indirect buffer + * containing 2D acceleration commands is processed. */ - return -EINVAL; + BEGIN_RING( 2 ); + RADEON_WAIT_UNTIL_3D_IDLE(); + ADVANCE_RING(); +#endif + + /* Dispatch the indirect buffer full of commands from the + * X server. This is insecure and is thus only available to + * privileged clients. + */ + r128_cce_dispatch_indirect( dev, buf, indirect.start, indirect.end ); + + return 0; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/drm/radeon_drv.h linux.19rc3-ac4/drivers/char/drm/radeon_drv.h --- linux.19rc3/drivers/char/drm/radeon_drv.h 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/drm/radeon_drv.h 2002-07-29 18:16:19.000000000 +0100 @@ -660,7 +660,7 @@ DRM_ERROR( "ring space check failed!\n" ); \ return -EBUSY; \ } \ - __ring_space_done: \ + __ring_space_done: ; \ } while (0) #define VB_AGE_TEST_WITH_RETURN( dev_priv ) \ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/drm-4.0/ffb_drv.c linux.19rc3-ac4/drivers/char/drm-4.0/ffb_drv.c --- linux.19rc3/drivers/char/drm-4.0/ffb_drv.c 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/drm-4.0/ffb_drv.c 2002-07-29 13:58:39.000000000 +0100 @@ -710,8 +710,7 @@ /* Contention */ atomic_inc(&dev->total_sleeps); current->state = TASK_INTERRUPTIBLE; - current->policy |= SCHED_YIELD; - schedule(); + yield(); if (signal_pending(current)) { ret = -ERESTARTSYS; break; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/drm-4.0/i810_dma.c linux.19rc3-ac4/drivers/char/drm-4.0/i810_dma.c --- linux.19rc3/drivers/char/drm-4.0/i810_dma.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/drm-4.0/i810_dma.c 2002-07-29 13:58:39.000000000 +0100 @@ -83,7 +83,7 @@ *(volatile unsigned int *)(virt + outring) = n; \ outring += 4; \ outring &= ringmask; \ -} while (0); +} while (0) static inline void i810_print_status_page(drm_device_t *dev) { @@ -231,7 +231,7 @@ #else retcode = do_munmap(current->mm, (unsigned long)buf_priv->virtual, - (size_t) buf->total); + (size_t) buf->total, 1); #endif up_write(¤t->mm->mmap_sem); } @@ -279,7 +279,7 @@ address = __get_free_page(GFP_KERNEL); if(address == 0UL) return 0; - + get_page(virt_to_page(address)); LockPage(virt_to_page(address)); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/drm-4.0/tdfx_drv.c linux.19rc3-ac4/drivers/char/drm-4.0/tdfx_drv.c --- linux.19rc3/drivers/char/drm-4.0/tdfx_drv.c 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/drm-4.0/tdfx_drv.c 2002-07-29 13:58:39.000000000 +0100 @@ -554,7 +554,6 @@ lock.context, current->pid, j, dev->lock.lock_time, jiffies); current->state = TASK_INTERRUPTIBLE; - current->policy |= SCHED_YIELD; schedule_timeout(DRM_LOCK_SLICE-j); DRM_DEBUG("jiffies=%d\n", jiffies); } @@ -578,10 +577,7 @@ /* Contention */ atomic_inc(&dev->total_sleeps); -#if 1 - current->policy |= SCHED_YIELD; -#endif - schedule(); + yield(); if (signal_pending(current)) { ret = -ERESTARTSYS; break; @@ -604,8 +600,7 @@ when dev->last_context == lock.context NOTE WE HOLD THE LOCK THROUGHOUT THIS TIME! */ - current->policy |= SCHED_YIELD; - schedule(); + yield(); current->state = TASK_RUNNING; remove_wait_queue(&dev->context_wait, &entry); if (signal_pending(current)) { diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/generic_serial.c linux.19rc3-ac4/drivers/char/generic_serial.c --- linux.19rc3/drivers/char/generic_serial.c 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/generic_serial.c 2002-07-29 18:09:00.000000000 +0100 @@ -41,8 +41,8 @@ #define gs_dprintk(f, str...) /* nothing */ #endif -#define func_enter() gs_dprintk (GS_DEBUG_FLOW, "gs: enter " __FUNCTION__ "\n") -#define func_exit() gs_dprintk (GS_DEBUG_FLOW, "gs: exit " __FUNCTION__ "\n") +#define func_enter() gs_dprintk (GS_DEBUG_FLOW, "gs: enter %s\n", __FUNCTION__) +#define func_exit() gs_dprintk (GS_DEBUG_FLOW, "gs: exit %s\n", __FUNCTION__) #if NEW_WRITE_LOCKING #define DECL /* Nothing */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/hp_keyb.c linux.19rc3-ac4/drivers/char/hp_keyb.c --- linux.19rc3/drivers/char/hp_keyb.c 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/hp_keyb.c 2002-07-29 13:58:39.000000000 +0100 @@ -176,7 +176,7 @@ /* 30 */ K_NONE, K_N , K_B , K_H , K_G , K_Y , K_6 , K_NONE, /* 38 */ K_NONE, K_NONE, K_M , K_J , K_U , K_7 , K_8 , K_NONE, /* 40 */ K_NONE, K_COMA, K_K , K_I , K_O , K_0 , K_9 , K_NONE, -/* 48 */ K_NONE, K_DOT , K_FSLH, K_L , K_SEMI, K_P , K_MINS, K_NONE, +/* 48 */ K_PGUP, K_DOT , K_FSLH, K_L , K_SEMI, K_P , K_MINS, K_NONE, /* 50 */ K_NONE, K_NONE, K_SQOT, K_NONE, K_LSBK, K_EQLS, K_NONE, K_NONE, /* 58 */ K_CAPS, K_RSFT, K_ENTR, K_RSBK, K_NONE, K_BSLH, K_NONE, K_NONE, /* 60 */ K_NONE, K_HASH, K_NONE, K_NONE, K_NONE, K_NONE, K_BKSP, K_NONE, @@ -267,6 +267,12 @@ #define FOCUS_PF12 123 #define JAP_86 124 + +/* On one Compaq UK keyboard, at least, bar/backslash generates scancode + * 0x7f. 0x7f generated on some .de and .no keyboards also. + */ +#define UK_86 86 + /* tfj@olivia.ping.dk: * The four keys are located over the numeric keypad, and are * labelled A1-A4. It's an rc930 keyboard, from @@ -284,7 +290,7 @@ 0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12, /* 0x68-0x6f */ 0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3, /* 0x70-0x77 */ FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7, /* 0x78-0x7b */ - FOCUS_PF8, JAP_86, FOCUS_PF10, 0 /* 0x7c-0x7f */ + FOCUS_PF8, JAP_86, FOCUS_PF10, UK_86 /* 0x7c-0x7f */ }; /* BTC */ @@ -327,7 +333,7 @@ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */ 0, 0, 0, 0, 0, 0, 0, E0_MACRO, /* 0x68-0x6f */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77 */ - 0, 0, 0, 0, 0, 0, 0, 0 /* 0x78-0x7f */ + 0, 0, 0, 0, 0, 0, 0, E0_MSLW /* 0x78-0x7f */ }; int pckbd_setkeycode(unsigned int scancode, unsigned int keycode) diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/hp_psaux.c linux.19rc3-ac4/drivers/char/hp_psaux.c --- linux.19rc3/drivers/char/hp_psaux.c 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/hp_psaux.c 2002-07-29 13:58:39.000000000 +0100 @@ -6,18 +6,16 @@ * Copyright 1999, 2000 Philipp Rumpf * * 2000/10/26 Debacker Xavier (debackex@esiee.fr) + * implemented the psaux and controlled the mouse scancode based on pc_keyb.c * Marteau Thomas (marteaut@esiee.fr) - * Djoudi Malek (djoudim@esiee.fr) * fixed leds control - * implemented the psaux and controlled the mouse scancode based on pc_keyb.c + * + * 2001/12/17 Marteau Thomas (marteaut@esiee.fr) + * get nice initialisation procedure */ #include -#include -#include -#include - #include #include /* interrupt.h wants struct pt_regs defined */ #include @@ -28,6 +26,7 @@ #include #include #include +#include #include #include @@ -37,11 +36,16 @@ #include #include #include -#include #include +#include +#include +#include +#include + /* HP specific LASI PS/2 keyboard and psaux constants */ #define AUX_REPLY_ACK 0xFA /* Command byte ACK. */ +#define AUX_RESEND 0xFE /* Sent by the keyb. Asking for resending the last command. */ #define AUX_RECONNECT 0xAA /* scancode when ps2 device is plugged (back) in */ #define LASI_PSAUX_OFFSET 0x0100 /* offset from keyboard to psaux port */ @@ -69,50 +73,63 @@ #define LASI_STAT_DATSHD 0x40 #define LASI_STAT_CLKSHD 0x80 -static void *lasikbd_hpa; -static void *lasips2_hpa; +static spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED; +static unsigned long lasikbd_hpa; +static volatile int cmd_status; -static inline u8 read_input(void *hpa) +static inline u8 read_input(unsigned long hpa) { return gsc_readb(hpa+LASI_RCVDATA); } -static inline u8 read_control(void *hpa) +static inline u8 read_control(unsigned long hpa) { return gsc_readb(hpa+LASI_CONTROL); } -static inline void write_control(u8 val, void *hpa) +static inline void write_control(u8 val, unsigned long hpa) { gsc_writeb(val, hpa+LASI_CONTROL); } -static inline u8 read_status(void *hpa) +static inline u8 read_status(unsigned long hpa) { return gsc_readb(hpa+LASI_STATUS); } -static int write_output(u8 val, void *hpa) +/* XXX should this grab the spinlock? */ + +static int write_output(u8 val, unsigned long hpa) { - int wait = 0; + int wait = 250; while (read_status(hpa) & LASI_STAT_TBNE) { - wait++; - if (wait>10000) { - /* printk(KERN_WARNING "Lasi PS/2 transmit buffer timeout\n"); */ + if (!--wait) { return 0; } + mdelay(1); } - - if (wait) - printk(KERN_DEBUG "Lasi PS/2 wait %d\n", wait); - gsc_writeb(val, hpa+LASI_XMTDATA); return 1; } +/* XXX should this grab the spinlock? */ + +static u8 wait_input(unsigned long hpa) +{ + int wait = 250; + + while (!(read_status(hpa) & LASI_STAT_RBNE)) { + if (!--wait) { + return 0; + } + mdelay(1); + } + return read_input(hpa); +} + /* This function is the PA-RISC adaptation of i386 source */ static inline int aux_write_ack(u8 val) @@ -120,11 +137,37 @@ return write_output(val, lasikbd_hpa+LASI_PSAUX_OFFSET); } +/* This is wrong, should do something like the pc driver, which sends + * the command up to 3 times at 1 second intervals, checking once + * per millisecond for an acknowledge. + */ + static void lasikbd_leds(unsigned char leds) { - write_output(KBD_CMD_SET_LEDS, lasikbd_hpa); - write_output(leds, lasikbd_hpa); - write_output(KBD_CMD_ENABLE, lasikbd_hpa); + int loop = 1000; + + if (!lasikbd_hpa) + return; + + cmd_status=2; + while (cmd_status!=0 && --loop > 0) { + write_output(KBD_CMD_SET_LEDS, lasikbd_hpa); + mdelay(5); + } + + cmd_status=2; + while (cmd_status!=0 && --loop > 0) { + write_output(leds, lasikbd_hpa); + mdelay(5); + } + + cmd_status=2; + while (cmd_status!=0 && --loop > 0) { + write_output(KBD_CMD_ENABLE, lasikbd_hpa); + mdelay(5); + } + if (loop <= 0) + printk("lasikbd_leds: timeout\n"); } #if 0 @@ -154,10 +197,30 @@ } #endif -static int __init lasi_ps2_reset(void *hpa, int id) +static int init_keyb(unsigned long hpa) +{ + int res = 0; + unsigned long flags; + + spin_lock_irqsave(&kbd_controller_lock, flags); + + if (write_output(KBD_CMD_SET_LEDS, hpa) && + wait_input(hpa) == AUX_REPLY_ACK && + write_output(0, hpa) && + wait_input(hpa) == AUX_REPLY_ACK && + write_output(KBD_CMD_ENABLE, hpa) && + wait_input(hpa) == AUX_REPLY_ACK) + res = 1; + + spin_unlock_irqrestore(&kbd_controller_lock, flags); + + return res; +} + + +static void __init lasi_ps2_reset(unsigned long hpa) { u8 control; - int ret = 1; /* reset the interface */ gsc_writeb(0xff, hpa+LASI_RESET); @@ -166,25 +229,8 @@ /* enable it */ control = read_control(hpa); write_control(control | LASI_CTRL_ENBL, hpa); - - /* initializes the leds at the default state */ - if (id==0) { - write_output(KBD_CMD_SET_LEDS, hpa); - write_output(0, hpa); - ret = write_output(KBD_CMD_ENABLE, hpa); - } - - return ret; -} - -static int inited; - -static void lasi_ps2_init_hw(void) -{ - ++inited; } - /* Greatly inspired by pc_keyb.c */ /* @@ -202,7 +248,6 @@ #ifdef CONFIG_PSMOUSE static struct aux_queue *queue; -static spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED; static unsigned char mouse_reply_expected; static int aux_count; @@ -315,7 +360,7 @@ schedule(); goto repeat; } - set_current_state(TASK_RUNNING); + current->state = TASK_RUNNING; remove_wait_queue(&queue->proc_list, &wait); } while (i > 0 && !queue_empty()) { @@ -362,7 +407,7 @@ lock_kernel(); fasync_aux(-1, file, 0); if (--aux_count) { - unlock_kernel(); + unlock_kernel(); return 0; } unlock_kernel(); @@ -389,7 +434,7 @@ /* This function is looking at the PS2 controller and empty the two buffers */ -static u8 handle_lasikbd_event(void *hpa) +static u8 handle_lasikbd_event(unsigned long hpa) { u8 status_keyb,status_mouse,scancode,id; extern void handle_at_scancode(int); /* in drivers/char/keyb_at.c */ @@ -398,62 +443,64 @@ id = gsc_readb(hpa+LASI_ID) & 0x0f; if (id==1) - hpa -= LASI_PSAUX_OFFSET; - lasikbd_hpa = hpa; - - + hpa -= LASI_PSAUX_OFFSET; + status_keyb = read_status(hpa); status_mouse = read_status(hpa+LASI_PSAUX_OFFSET); while ((status_keyb|status_mouse) & LASI_STAT_RBNE){ - while (status_keyb & LASI_STAT_RBNE) { + while (status_keyb & LASI_STAT_RBNE) { - scancode = read_input(hpa); + scancode = read_input(hpa); - /* XXX don't know if this is a valid fix, but filtering - * 0xfa avoids 'unknown scancode' errors on, eg, capslock - * on some keyboards. - */ - if (inited && scancode != 0xfa) - handle_at_scancode(scancode); + /* XXX don't know if this is a valid fix, but filtering + * 0xfa avoids 'unknown scancode' errors on, eg, capslock + * on some keyboards. + */ + + if (scancode == AUX_REPLY_ACK) + cmd_status=0; + + else if (scancode == AUX_RESEND) + cmd_status=1; + else + handle_at_scancode(scancode); - status_keyb =read_status(hpa); - } + status_keyb =read_status(hpa); + } #ifdef CONFIG_PSMOUSE - while (status_mouse & LASI_STAT_RBNE) { - scancode = read_input(hpa+LASI_PSAUX_OFFSET); - handle_mouse_scancode(scancode); - status_mouse = read_status(hpa+LASI_PSAUX_OFFSET); - } - status_mouse = read_status(hpa+LASI_PSAUX_OFFSET); + while (status_mouse & LASI_STAT_RBNE) { + scancode = read_input(hpa+LASI_PSAUX_OFFSET); + handle_mouse_scancode(scancode); + status_mouse = read_status(hpa+LASI_PSAUX_OFFSET); + } + status_mouse = read_status(hpa+LASI_PSAUX_OFFSET); #endif /* CONFIG_PSMOUSE */ - status_keyb = read_status(hpa); + status_keyb = read_status(hpa); } tasklet_schedule(&keyboard_tasklet); return (status_keyb|status_mouse); } - - - extern struct pt_regs *kbd_pt_regs; static void lasikbd_interrupt(int irq, void *dev, struct pt_regs *regs) { - lasips2_hpa = dev; /* save "hpa" for lasikbd_leds() */ kbd_pt_regs = regs; - handle_lasikbd_event(lasips2_hpa); + handle_lasikbd_event((unsigned long) dev); } - extern int pckbd_translate(unsigned char, unsigned char *, char); +extern int pckbd_setkeycode(unsigned int, unsigned int); +extern int pckbd_getkeycode(unsigned int); static struct kbd_ops gsc_ps2_kbd_ops = { - translate: pckbd_translate, - init_hw: lasi_ps2_init_hw, + setkeycode: pckbd_setkeycode, + getkeycode: pckbd_getkeycode, + translate: pckbd_translate, leds: lasikbd_leds, #ifdef CONFIG_MAGIC_SYSRQ sysrq_key: 0x54, @@ -461,13 +508,27 @@ #endif }; + + +#if 1 +/* XXX: HACK !!! + * remove this function and the call in hil_kbd.c + * if hp_psaux.c/hp_keyb.c is converted to the input layer... */ +int register_ps2_keybfuncs(void) +{ + gsc_ps2_kbd_ops.leds = NULL; + register_kbd_ops(&gsc_ps2_kbd_ops); +} +EXPORT_SYMBOL(register_ps2_keybfuncs); +#endif + + static int __init -lasi_ps2_register(struct hp_device *d, struct pa_iodc_driver *dri) +lasi_ps2_register(struct parisc_device *dev) { - void *hpa = (void *) d->hpa; - unsigned int irq; + unsigned long hpa = dev->hpa; char *name; - int device_found; + int device_found = 0; u8 id; id = gsc_readb(hpa+LASI_ID) & 0x0f; @@ -475,7 +536,7 @@ switch (id) { case 0: name = "keyboard"; - lasikbd_hpa = hpa; + lasikbd_hpa = hpa; /* save "hpa" for lasikbd_leds() */ break; case 1: name = "psaux"; @@ -487,21 +548,12 @@ } /* reset the PS/2 port */ - device_found = lasi_ps2_reset(hpa,id); - - /* allocate the irq and memory region for that device */ - if (!(irq = busdevice_alloc_irq(d))) - return -ENODEV; - - if (request_irq(irq, lasikbd_interrupt, 0, name, hpa)) - return -ENODEV; - - if (!request_mem_region((unsigned long)hpa, LASI_STATUS + 4, name)) - return -ENODEV; + lasi_ps2_reset(hpa); switch (id) { case 0: - register_kbd_ops(&gsc_ps2_kbd_ops); + device_found = init_keyb(hpa); + if (device_found) register_kbd_ops(&gsc_ps2_kbd_ops); break; case 1: #ifdef CONFIG_PSMOUSE @@ -526,26 +578,42 @@ #endif } /* of case */ - printk(KERN_INFO "PS/2 %s controller at 0x%08lx (irq %d) found, " + if (device_found) { + /* Here we claim only if we have a device attached */ + /* allocate the irq and memory region for that device */ + if (!dev->irq) + return -ENODEV; + + if (request_irq(dev->irq, lasikbd_interrupt, 0, name, (void *)hpa)) + return -ENODEV; + + if (!request_mem_region(hpa, LASI_STATUS + 4, name)) + return -ENODEV; + } + + printk(KERN_INFO "PS/2 %s port at 0x%08lx (irq %d) found, " "%sdevice attached.\n", - name, (unsigned long)hpa, irq, - device_found ? "":"no "); + name, hpa, dev->irq, device_found ? "":"no "); return 0; } +static struct parisc_device_id lasi_psaux_tbl[] = { + { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00084 }, + { 0, } /* 0 terminated list */ +}; + +MODULE_DEVICE_TABLE(parisc, lasi_psaux_tbl); -static struct pa_iodc_driver lasi_psaux_drivers_for[] __initdata = { - {HPHW_FIO, 0x0, 0,0x00084, 0, 0, - DRIVER_CHECK_HWTYPE + DRIVER_CHECK_SVERSION, - "Lasi psaux", "generic", (void *) lasi_ps2_register}, - { 0, } +static struct parisc_driver lasi_psaux_driver = { + name: "Lasi psaux", + id_table: lasi_psaux_tbl, + probe: lasi_ps2_register, }; static int __init gsc_ps2_init(void) { - return pdc_register_driver(lasi_psaux_drivers_for); + return register_parisc_driver(&lasi_psaux_driver); } module_init(gsc_ps2_init); - diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/keyboard.c linux.19rc3-ac4/drivers/char/keyboard.c --- linux.19rc3/drivers/char/keyboard.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/keyboard.c 2002-07-29 13:58:39.000000000 +0100 @@ -42,6 +42,9 @@ #include #include #include +#include /* for mdelay() */ + +#include #define SIZE(x) (sizeof(x)/sizeof((x)[0])) @@ -100,20 +103,21 @@ typedef void (*k_hand)(unsigned char value, char up_flag); typedef void (k_handfn)(unsigned char value, char up_flag); + static k_handfn do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift, - do_meta, do_ascii, do_lock, do_lowercase, do_slock, do_dead2, - do_ignore; + do_meta, do_ascii, do_lock, do_lowercase, do_slock, + do_spkup, do_dead2, do_ignore; -static k_hand key_handler[16] = { +static k_hand key_handler[17] = { do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift, - do_meta, do_ascii, do_lock, do_lowercase, do_slock, do_dead2, - do_ignore, do_ignore + do_meta, do_ascii, do_lock, do_lowercase, do_slock, + do_spkup, do_dead2, do_ignore, do_ignore }; /* Key types processed even in raw modes */ -#define TYPES_ALLOWED_IN_RAW_MODE ((1 << KT_SPEC) | (1 << KT_SHIFT)) +#define TYPES_ALLOWED_IN_RAW_MODE ((1 << KT_SPEC) | (1 << KT_SHIFT) | (1 << KT_SPKUP)) typedef void (*void_fnp)(void); typedef void (void_fn)(void); @@ -137,7 +141,7 @@ 255, SIZE(func_table) - 1, SIZE(spec_fn_table) - 1, NR_PAD - 1, NR_DEAD - 1, 255, 3, NR_SHIFT - 1, 255, NR_ASCII - 1, NR_LOCK - 1, 255, - NR_LOCK - 1, 255 + NR_LOCK - 1, NR_SPKUP - 1, 255, 255 }; const int NR_TYPES = SIZE(max_vals); @@ -257,6 +261,7 @@ raw_mode = 1; /* Most key classes will be ignored */ } + /* * Small change in philosophy: earlier we defined repetition by * rep = keycode == prev_keycode; @@ -286,24 +291,26 @@ type = KTYP(keysym); if (type >= 0xf0) { - type -= 0xf0; - if (raw_mode && ! (TYPES_ALLOWED_IN_RAW_MODE & (1 << type))) - goto out; - if (type == KT_LETTER) { - type = KT_LATIN; - if (vc_kbd_led(kbd, VC_CAPSLOCK)) { - key_map = key_maps[shift_final ^ (1<slockstate = 0; + if (!up_flag) + speakup_reset(fg_console, type); + (*key_handler[type])(keysym & 0xff, up_flag); + if (type != KT_SLOCK) + kbd->slockstate = 0; } else { - /* maybe only if (kbd->kbdmode == VC_UNICODE) ? */ - if (!up_flag && !raw_mode) - to_utf8(keysym); + /* maybe only if (kbd->kbdmode == VC_UNICODE) ? */ + if (!up_flag && !raw_mode) + to_utf8(keysym); } } else { /* maybe beep? */ @@ -315,7 +322,7 @@ keysym = U(key_maps[0][keycode]); type = KTYP(keysym); if (type == KT_SHIFT) - (*key_handler[type])(keysym & 0xff, up_flag); + (*key_handler[type])(keysym & 0xff, up_flag); #endif } } @@ -528,6 +535,138 @@ compute_shiftstate(); } +#ifdef CONFIG_SPEAKUP /* speech output for linux */ +static void do_spkup(unsigned char value, char up_flag) +{ + speakup_savekey(0); /* clear! brzzzot */ + if (up_flag) + return; /* do nothing on key release */ + + if (value == SPEECH_KILL) { + speakup_kill(fg_console); + return; + } + + if (speakup_console[fg_console]->shut_up & 0x40) return; + + switch(value) { + case (QUICK_QUIET): + /* -x- */ + spkup_write("\x18", 1); + return; + case (LINE_QUIET): + return; + case (FULL_QUIET): + spkup_write("\x18", 1); + speakup_shut_up(fg_console); + return; + case (SAY_CHAR): + say_curr_char(fg_console); + return; + case (SAY_PREV_CHAR): + say_prev_char(fg_console); + return; + case (SAY_NEXT_CHAR): + say_next_char(fg_console); + return; + case (SAY_WORD): + say_curr_word(fg_console); + return; + case (SAY_PREV_WORD): + say_prev_word(fg_console); + return; + case (SAY_NEXT_WORD): + say_next_word(fg_console); + return; + case (SAY_LINE): + say_curr_line(fg_console); + return; + case (SAY_PREV_LINE): + say_prev_line(fg_console); + return; + case (SAY_NEXT_LINE): + say_next_line(fg_console); + return; + case (TOP_EDGE): + top_edge(fg_console); + return; + case (BOTTOM_EDGE): + bottom_edge(fg_console); + return; + case (LEFT_EDGE): + left_edge(fg_console); + return; + case (RIGHT_EDGE): + right_edge(fg_console); + return; + case (SAY_PHONETIC_CHAR): + say_phonetic_char(fg_console); + return; + case (SPELL_WORD): + spell_word(fg_console); + return; + case (SPELL_PHONETIC_WORD): + return; + case (SAY_SCREEN): + say_screen(fg_console); + return; + case (SAY_WINDOW): + return; + case (SET_SPEED): + return; + case (SET_PITCH): + return; + case (SET_PUNCTUATION): + return; + case (SET_VOICE): + return; + case (SET_TONE): + return; + case (SAY_POSITION): + say_position(fg_console); + return; + case (SAY_CHAR_NUM): + say_char_num(fg_console); + return; + case (SPEECH_OFF): + speakup_off(fg_console); + return; + case (SPEAKUP_CURSORING): + speakup_cursoring(fg_console); + return; + case (SPEAKUP_CUT): + speakup_cut(fg_console, tty); + return; + case (SPEAKUP_PASTE): + speakup_paste(tty); + return; + case (SAY_ATTRIBUTES): + say_attributes(fg_console); + return; + case (SPEAKUP_PARKED): + speakup_parked(fg_console); + return; + case (SAY_FROM_TOP): + say_from_top(fg_console); + return; + case (SAY_TO_BOTTOM): + say_to_bottom(fg_console); + return; + case (SAY_FROM_LEFT): + say_from_left(fg_console); + return; + case (SAY_TO_RIGHT): + say_to_right(fg_console); + return; + default: + spkup_write("SpeakUp: Invalid command", 25); + return; +} +} +#else +static void do_spkup(unsigned char value, char up_flag) {}; +#endif + static void do_spec(unsigned char value, char up_flag) { if (up_flag) @@ -538,6 +677,7 @@ !(SPECIALS_ALLOWED_IN_RAW_MODE & (1 << value))) return; spec_fn_table[value](); + speakup_control(fg_console, kbd, value); } static void do_lowercase(unsigned char value, char up_flag) @@ -551,7 +691,8 @@ return; /* no action, if this is a key release */ if (diacr) - value = handle_diacr(value); + if ((value = handle_diacr(value)) == 0xff) /* speakup goto pos trigger*/ + return; if (dead_key_next) { dead_key_next = 0; @@ -559,6 +700,7 @@ return; } + speakup_savekey(value); put_queue(value); } @@ -568,8 +710,10 @@ #define A_TILDE '~' #define A_DIAER '"' #define A_CEDIL ',' +#define SPEAKUP_DIACR '$' + static unsigned char ret_diacr[NR_DEAD] = - {A_GRAVE, A_ACUTE, A_CFLEX, A_TILDE, A_DIAER, A_CEDIL }; + {A_GRAVE, A_ACUTE, A_CFLEX, A_TILDE, A_DIAER, A_CEDIL, SPEAKUP_DIACR}; /* Obsolete - for backwards compatibility only */ static void do_dead(unsigned char value, char up_flag) @@ -588,6 +732,12 @@ if (up_flag) return; + if (value == SPEAKUP_DIACR) { /*beep to alert that speakup's waiting */ + kd_mksound(1250,10); + mdelay(100); + kd_mksound(1500,15); + } + diacr = (diacr ? handle_diacr(value) : value); } @@ -604,6 +754,12 @@ int d = diacr; int i; + if (d == '$') { + if (speakup_diacr(ch,fg_console)) + diacr = 0; + return 0xff; + } + diacr = 0; for (i = 0; i < accent_table_size; i++) { @@ -657,7 +813,7 @@ do_fn(KVAL(K_REMOVE), 0); return; case KVAL(K_P0): - do_fn(KVAL(K_INSERT), 0); + do_fn(KVAL(K_INSERT), 0); return; case KVAL(K_P1): do_fn(KVAL(K_SELECT), 0); @@ -717,6 +873,10 @@ clr_vc_kbd_led(kbd, VC_CAPSLOCK); } + /* shift = 0, altgr = 1, ctrl=2, alt=3 */ + if (!up_flag) + speakup_control(fg_console, kbd, value); + if (up_flag) { /* handle the case that two shift or control keys are depressed simultaneously */ @@ -805,6 +965,7 @@ if (up_flag || rep) return; chg_vc_kbd_lock(kbd, value); + } static void do_slock(unsigned char value, char up_flag) diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/Makefile linux.19rc3-ac4/drivers/char/Makefile --- linux.19rc3/drivers/char/Makefile 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/Makefile 2002-07-29 13:58:39.000000000 +0100 @@ -213,6 +213,7 @@ obj-$(CONFIG_DS1620) += ds1620.o obj-$(CONFIG_INTEL_RNG) += i810_rng.o obj-$(CONFIG_AMD_RNG) += amd768_rng.o +obj-$(CONFIG_AMD_PM768) += amd76x_pm.o obj-$(CONFIG_ITE_GPIO) += ite_gpio.o obj-$(CONFIG_AU1000_GPIO) += au1000_gpio.o @@ -230,6 +231,14 @@ obj-y += ftape/ftape.o endif +ifeq ($(CONFIG_SPEAKUP),y) +subdir-y += speakup +obj-y += speakup/spk.o +ifeq ($(CONFIG_SPEAKUP_KEYMAP),y) +KEYMAP = speakup/speakupmap.o +endif +endif + obj-$(CONFIG_H8) += h8.o obj-$(CONFIG_PPDEV) += ppdev.o obj-$(CONFIG_DZ) += dz.o @@ -262,6 +271,7 @@ obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o +obj-$(CONFIG_AMD7XX_TCO) += amd7xx_tco.o subdir-$(CONFIG_MWAVE) += mwave ifeq ($(CONFIG_MWAVE),y) diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/mwave/mwavedd.c linux.19rc3-ac4/drivers/char/mwave/mwavedd.c --- linux.19rc3/drivers/char/mwave/mwavedd.c 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/mwave/mwavedd.c 2002-07-29 13:58:39.000000000 +0100 @@ -279,7 +279,6 @@ pDrvData->IPCs[ipcnum].bIsHere = FALSE; pDrvData->IPCs[ipcnum].bIsEnabled = TRUE; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - current->nice = -20; /* boost to provide priority timing */ #else current->priority = 0x28; /* boost to provide priority timing */ #endif diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/mxser.c linux.19rc3-ac4/drivers/char/mxser.c --- linux.19rc3/drivers/char/mxser.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/mxser.c 2002-07-29 17:49:49.000000000 +0100 @@ -653,7 +653,7 @@ n = (sizeof(mxser_pcibrds) / sizeof(mxser_pcibrds[0])) - 1; index = 0; for (b = 0; b < n; b++) { - while (pdev = pci_find_device(mxser_pcibrds[b].vendor, mxser_pcibrds[b].device, pdev)) + while ((pdev = pci_find_device(mxser_pcibrds[b].vendor, mxser_pcibrds[b].device, pdev)) != NULL) { if (pci_enable_device(pdev)) continue; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/n_r3964.c linux.19rc3-ac4/drivers/char/n_r3964.c --- linux.19rc3/drivers/char/n_r3964.c 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/n_r3964.c 2002-07-29 13:58:39.000000000 +0100 @@ -1364,7 +1364,7 @@ pHeader->owner = pClient; } - copy_from_user (pHeader->data, data, count); /* We already verified this */ + __copy_from_user(pHeader->data, data, count); /* We already verified this */ if(pInfo->flags & R3964_DEBUG) { diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/nwflash.c linux.19rc3-ac4/drivers/char/nwflash.c --- linux.19rc3/drivers/char/nwflash.c 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/nwflash.c 2002-07-29 13:58:39.000000000 +0100 @@ -154,12 +154,11 @@ if (down_interruptible(&nwflash_sem)) return -ERESTARTSYS; - ret = copy_to_user(buf, (void *)(FLASH_BASE + p), count); - if (ret == 0) { - ret = count; - *ppos += count; - } + ret = count - copy_to_user(buf, (void *)(FLASH_BASE + p), count); + *ppos += ret; up(&nwflash_sem); + if (ret == 0) + ret = -EFAULT; } return ret; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/pc_keyb.c linux.19rc3-ac4/drivers/char/pc_keyb.c --- linux.19rc3/drivers/char/pc_keyb.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/pc_keyb.c 2002-07-29 15:21:52.000000000 +0100 @@ -64,7 +64,6 @@ static void kbd_write_command_w(int data); static void kbd_write_output_w(int data); #ifdef CONFIG_PSMOUSE -static void aux_write_ack(int val); static void __aux_write_ack(int val); static int aux_reconnect = 0; #endif @@ -1001,6 +1000,7 @@ kb_wait(); } +#ifdef INITIALIZE_MOUSE static void aux_write_ack(int val) { unsigned long flags; @@ -1009,6 +1009,7 @@ __aux_write_ack(val); spin_unlock_irqrestore(&kbd_controller_lock, flags); } +#endif static unsigned char get_from_queue(void) { @@ -1066,6 +1067,9 @@ static int open_aux(struct inode * inode, struct file * file) { + unsigned long flags; + int cnt, status; + if (aux_count++) { return 0; } @@ -1077,7 +1081,30 @@ kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE); /* Enable the auxiliary port on controller. */ - aux_write_ack(AUX_ENABLE_DEV); /* Enable aux device */ + + spin_lock_irqsave(&kbd_controller_lock, flags); + __aux_write_ack(AUX_ENABLE_DEV); /* Enable aux device */ + for(cnt = 50; cnt > 0; --cnt) { + status = handle_kbd_event(); + if (mouse_reply_expected == 0 || + (status & (KBD_STAT_GTO | KBD_STAT_PERR))) + break; + set_current_state(TASK_UNINTERRUPTIBLE); + spin_unlock_irqrestore(&kbd_controller_lock, flags); + schedule_timeout(2); + spin_lock_irqsave(&kbd_controller_lock, flags); + set_current_state(TASK_RUNNING); + } + if (cnt == 0 || (status & (KBD_STAT_GTO | KBD_STAT_PERR))) { + --aux_count; + spin_unlock_irqrestore(&kbd_controller_lock, flags); + kbd_write_cmd(AUX_INTS_OFF); + kbd_write_command_w(KBD_CCMD_MOUSE_DISABLE); + aux_free_irq(AUX_DEV); + return -ENXIO; + } + spin_unlock_irqrestore(&kbd_controller_lock, flags); + kbd_write_cmd(AUX_INTS_ON); /* Enable controller ints */ mdelay(2); /* Ensure we follow the kbc access delay rules.. */ @@ -1217,41 +1244,13 @@ #endif /* CONFIG_PSMOUSE */ -static int blink_frequency = HZ/2; +void pckbd_blink (char led) { + led = led ? (0x01 | 0x04) : 0x00; -/* Tell the user who may be running in X and not see the console that we have - panic'ed. This is to distingush panics from "real" lockups. - Could in theory send the panic message as morse, but that is left as an - exercise for the reader. */ -void panic_blink(void) -{ - static unsigned long last_jiffie; - static char led; - /* Roughly 1/2s frequency. KDB uses about 1s. Make sure it is - different. */ - if (!blink_frequency) - return; - if (jiffies - last_jiffie > blink_frequency) { - led ^= 0x01 | 0x04; while (kbd_read_status() & KBD_STAT_IBF) mdelay(1); kbd_write_output(KBD_CMD_SET_LEDS); mdelay(1); while (kbd_read_status() & KBD_STAT_IBF) mdelay(1); mdelay(1); kbd_write_output(led); - last_jiffie = jiffies; - } -} - -static int __init panicblink_setup(char *str) -{ - int par; - if (get_option(&str,&par)) - blink_frequency = par*(1000/HZ); - return 1; } - -/* panicblink=0 disables the blinking as it caused problems with some console - switches. otherwise argument is ms of a blink period. */ -__setup("panicblink=", panicblink_setup); - diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/pcmcia/Config.in linux.19rc3-ac4/drivers/char/pcmcia/Config.in --- linux.19rc3/drivers/char/pcmcia/Config.in 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/pcmcia/Config.in 2002-07-29 13:58:39.000000000 +0100 @@ -10,5 +10,7 @@ define_bool CONFIG_PCMCIA_CHRDEV y fi +tristate 'SyncLink PC Card support' CONFIG_SYNCLINK_CS + endmenu diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/pcmcia/Makefile linux.19rc3-ac4/drivers/char/pcmcia/Makefile --- linux.19rc3/drivers/char/pcmcia/Makefile 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/pcmcia/Makefile 2002-07-29 13:58:39.000000000 +0100 @@ -16,5 +16,6 @@ obj- := obj-$(CONFIG_PCMCIA_SERIAL_CS) += serial_cs.o +obj-$(CONFIG_SYNCLINK_CS) += synclink_cs.o include $(TOPDIR)/Rules.make diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/pcmcia/synclink_cs.c linux.19rc3-ac4/drivers/char/pcmcia/synclink_cs.c --- linux.19rc3/drivers/char/pcmcia/synclink_cs.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/pcmcia/synclink_cs.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,4568 @@ +/* + * linux/drivers/char/synclink_cs.c + * + * $Id: synclink_cs.c,v 3.4 2002/04/22 14:36:41 paulkf Exp $ + * + * Device driver for Microgate SyncLink PC Card + * multiprotocol serial adapter. + * + * written by Paul Fulghum for Microgate Corporation + * paulkf@microgate.com + * + * Microgate and SyncLink are trademarks of Microgate Corporation + * + * This code is released under the GNU General Public License (GPL) + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define VERSION(ver,rel,seq) (((ver)<<16) | ((rel)<<8) | (seq)) +#if defined(__i386__) +# define BREAKPOINT() asm(" int $3"); +#else +# define BREAKPOINT() { } +#endif + +#define MAX_DEVICE_COUNT 4 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_SYNCLINK_SYNCPPP_MODULE +#define CONFIG_SYNCLINK_SYNCPPP 1 +#endif + +#ifdef CONFIG_SYNCLINK_SYNCPPP +#if LINUX_VERSION_CODE < VERSION(2,4,3) +#include "../net/wan/syncppp.h" +#else +#include +#endif +#endif + +#include +#define GET_USER(error,value,addr) error = get_user(value,addr) +#define COPY_FROM_USER(error,dest,src,size) error = copy_from_user(dest,src,size) ? -EFAULT : 0 +#define PUT_USER(error,value,addr) error = put_user(value,addr) +#define COPY_TO_USER(error,dest,src,size) error = copy_to_user(dest,src,size) ? -EFAULT : 0 + +#include + +#include "linux/synclink.h" + +static MGSL_PARAMS default_params = { + MGSL_MODE_HDLC, /* unsigned long mode */ + 0, /* unsigned char loopback; */ + HDLC_FLAG_UNDERRUN_ABORT15, /* unsigned short flags; */ + HDLC_ENCODING_NRZI_SPACE, /* unsigned char encoding; */ + 0, /* unsigned long clock_speed; */ + 0xff, /* unsigned char addr_filter; */ + HDLC_CRC_16_CCITT, /* unsigned short crc_type; */ + HDLC_PREAMBLE_LENGTH_8BITS, /* unsigned char preamble_length; */ + HDLC_PREAMBLE_PATTERN_NONE, /* unsigned char preamble; */ + 9600, /* unsigned long data_rate; */ + 8, /* unsigned char data_bits; */ + 1, /* unsigned char stop_bits; */ + ASYNC_PARITY_NONE /* unsigned char parity; */ +}; + +typedef struct +{ + int count; + unsigned char status; + char data[1]; +} RXBUF; + +/* The queue of BH actions to be performed */ + +#define BH_RECEIVE 1 +#define BH_TRANSMIT 2 +#define BH_STATUS 4 + +#define IO_PIN_SHUTDOWN_LIMIT 100 + +#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) + +struct _input_signal_events { + int ri_up; + int ri_down; + int dsr_up; + int dsr_down; + int dcd_up; + int dcd_down; + int cts_up; + int cts_down; +}; + + +/* + * Device instance data structure + */ + +typedef struct _mgslpc_info { + void *if_ptr; /* General purpose pointer (used by SPPP) */ + int magic; + int flags; + int count; /* count of opens */ + int line; + unsigned short close_delay; + unsigned short closing_wait; /* time to wait before closing */ + + struct mgsl_icount icount; + + struct termios normal_termios; + struct termios callout_termios; + + struct tty_struct *tty; + int timeout; + int x_char; /* xon/xoff character */ + int blocked_open; /* # of blocked opens */ + long session; /* Session of opening process */ + long pgrp; /* pgrp of opening process */ + unsigned char read_status_mask; + unsigned char ignore_status_mask; + + unsigned char *tx_buf; + int tx_put; + int tx_get; + int tx_count; + + /* circular list of fixed length rx buffers */ + + unsigned char *rx_buf; /* memory allocated for all rx buffers */ + int rx_buf_total_size; /* size of memory allocated for rx buffers */ + int rx_put; /* index of next empty rx buffer */ + int rx_get; /* index of next full rx buffer */ + int rx_buf_size; /* size in bytes of single rx buffer */ + int rx_buf_count; /* total number of rx buffers */ + int rx_frame_count; /* number of full rx buffers */ + + wait_queue_head_t open_wait; + wait_queue_head_t close_wait; + + wait_queue_head_t status_event_wait_q; + wait_queue_head_t event_wait_q; + struct timer_list tx_timer; /* HDLC transmit timeout timer */ + struct _mgslpc_info *next_device; /* device list link */ + + unsigned short imra_value; + unsigned short imrb_value; + unsigned char pim_value; + + spinlock_t lock; + struct tq_struct task; /* task structure for scheduling bh */ + + u32 max_frame_size; + + u32 pending_bh; + + int bh_running; + int bh_requested; + + int dcd_chkcount; /* check counts to prevent */ + int cts_chkcount; /* too many IRQs if a signal */ + int dsr_chkcount; /* is floating */ + int ri_chkcount; + + int rx_enabled; + int rx_overflow; + + int tx_enabled; + int tx_active; + int tx_aborting; + u32 idle_mode; + + int if_mode; /* serial interface selection (RS-232, v.35 etc) */ + + char device_name[25]; /* device instance name */ + + unsigned int io_base; /* base I/O address of adapter */ + unsigned int irq_level; + + MGSL_PARAMS params; /* communications parameters */ + + unsigned char serial_signals; /* current serial signal states */ + + char irq_occurred; /* for diagnostics use */ + char testing_irq; + unsigned int init_error; /* startup error (DIAGS) */ + + char flag_buf[MAX_ASYNC_BUFFER_SIZE]; + BOOLEAN drop_rts_on_tx_done; + + struct _input_signal_events input_signal_events; + + /* PCMCIA support */ + dev_link_t link; + dev_node_t node; + int stop; + struct bus_operations *bus; + + /* SPPP/Cisco HDLC device parts */ + int netcount; + int dosyncppp; + spinlock_t netlock; +#ifdef CONFIG_SYNCLINK_SYNCPPP + struct ppp_device pppdev; + char netname[10]; + struct net_device *netdev; + struct net_device_stats netstats; + struct net_device netdevice; +#endif +} MGSLPC_INFO; + +#define MGSLPC_MAGIC 0x5402 + +/* + * The size of the serial xmit buffer is 1 page, or 4096 bytes + */ +#define TXBUFSIZE 4096 + + +#define CHA 0x00 /* channel A offset */ +#define CHB 0x40 /* channel B offset */ + +#define RXFIFO 0 +#define TXFIFO 0 +#define STAR 0x20 +#define CMDR 0x20 +#define RSTA 0x21 +#define PRE 0x21 +#define MODE 0x22 +#define TIMR 0x23 +#define XAD1 0x24 +#define XAD2 0x25 +#define RAH1 0x26 +#define RAH2 0x27 +#define DAFO 0x27 +#define RAL1 0x28 +#define RFC 0x28 +#define RHCR 0x29 +#define RAL2 0x29 +#define RBCL 0x2a +#define XBCL 0x2a +#define RBCH 0x2b +#define XBCH 0x2b +#define CCR0 0x2c +#define CCR1 0x2d +#define CCR2 0x2e +#define CCR3 0x2f +#define VSTR 0x34 +#define BGR 0x34 +#define RLCR 0x35 +#define AML 0x36 +#define AMH 0x37 +#define GIS 0x38 +#define IVA 0x38 +#define IPC 0x39 +#define ISR 0x3a +#define IMR 0x3a +#define PVR 0x3c +#define PIS 0x3d +#define PIM 0x3d +#define PCR 0x3e +#define CCR4 0x3f + +// IMR/ISR + +#define IRQ_BREAK_ON BIT15 // rx break detected +#define IRQ_DATAOVERRUN BIT14 // receive data overflow +#define IRQ_ALLSENT BIT13 // all sent +#define IRQ_UNDERRUN BIT12 // transmit data underrun +#define IRQ_TIMER BIT11 // timer interrupt +#define IRQ_CTS BIT10 // CTS status change +#define IRQ_TXREPEAT BIT9 // tx message repeat +#define IRQ_TXFIFO BIT8 // transmit pool ready +#define IRQ_RXEOM BIT7 // receive message end +#define IRQ_EXITHUNT BIT6 // receive frame start +#define IRQ_RXTIME BIT6 // rx char timeout +#define IRQ_DCD BIT2 // carrier detect status change +#define IRQ_OVERRUN BIT1 // receive frame overflow +#define IRQ_RXFIFO BIT0 // receive pool full + +// STAR + +#define XFW BIT6 // transmit FIFO write enable +#define CEC BIT2 // command executing +#define CTS BIT1 // CTS state + +#define PVR_DTR BIT0 +#define PVR_DSR BIT1 +#define PVR_RI BIT2 +#define PVR_AUTOCTS BIT3 +#define PVR_RS232 0x20 /* 0010b */ +#define PVR_V35 0xe0 /* 1110b */ +#define PVR_RS422 0x40 /* 0100b */ + +/* Register access functions */ + +#define write_reg(info, reg, val) outb((val),(info)->io_base + (reg)) +#define read_reg(info, reg) inb((info)->io_base + (reg)) + +#define read_reg16(info, reg) inw((info)->io_base + (reg)) +#define write_reg16(info, reg, val) outw((val), (info)->io_base + (reg)) + +#define set_reg_bits(info, reg, mask) \ + write_reg(info, (reg), \ + (unsigned char) (read_reg(info, (reg)) | (mask))) +#define clear_reg_bits(info, reg, mask) \ + write_reg(info, (reg), \ + (unsigned char) (read_reg(info, (reg)) & ~(mask))) +/* + * interrupt enable/disable routines + */ +static void irq_disable(MGSLPC_INFO *info, unsigned char channel, unsigned short mask) +{ + if (channel == CHA) { + info->imra_value |= mask; + write_reg16(info, CHA + IMR, info->imra_value); + } else { + info->imrb_value |= mask; + write_reg16(info, CHB + IMR, info->imrb_value); + } +} +static void irq_enable(MGSLPC_INFO *info, unsigned char channel, unsigned short mask) +{ + if (channel == CHA) { + info->imra_value &= ~mask; + write_reg16(info, CHA + IMR, info->imra_value); + } else { + info->imrb_value &= ~mask; + write_reg16(info, CHB + IMR, info->imrb_value); + } +} + +#define port_irq_disable(info, mask) \ + { info->pim_value |= (mask); write_reg(info, PIM, info->pim_value); } + +#define port_irq_enable(info, mask) \ + { info->pim_value &= ~(mask); write_reg(info, PIM, info->pim_value); } + +static void rx_start(MGSLPC_INFO *info); +static void rx_stop(MGSLPC_INFO *info); + +static void tx_start(MGSLPC_INFO *info); +static void tx_stop(MGSLPC_INFO *info); +static void tx_set_idle(MGSLPC_INFO *info); + +static void get_signals(MGSLPC_INFO *info); +static void set_signals(MGSLPC_INFO *info); + +static void reset_device(MGSLPC_INFO *info); + +static void hdlc_mode(MGSLPC_INFO *info); +static void async_mode(MGSLPC_INFO *info); + +static void tx_timeout(unsigned long context); + +static int ioctl_common(MGSLPC_INFO *info, unsigned int cmd, unsigned long arg); + +#ifdef CONFIG_SYNCLINK_SYNCPPP +/* SPPP/HDLC stuff */ +static void mgslpc_sppp_init(MGSLPC_INFO *info); +static void mgslpc_sppp_delete(MGSLPC_INFO *info); +static int mgslpc_sppp_open(struct net_device *d); +static int mgslpc_sppp_close(struct net_device *d); +static void mgslpc_sppp_tx_timeout(struct net_device *d); +static int mgslpc_sppp_tx(struct sk_buff *skb, struct net_device *d); +static void mgslpc_sppp_rx_done(MGSLPC_INFO *info, char *buf, int size); +static void mgslpc_sppp_tx_done(MGSLPC_INFO *info); +static int mgslpc_sppp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); +struct net_device_stats *mgslpc_net_stats(struct net_device *dev); +#endif + +static void trace_block(MGSLPC_INFO *info,const char* data, int count, int xmit); + +static BOOLEAN register_test(MGSLPC_INFO *info); +static BOOLEAN irq_test(MGSLPC_INFO *info); +static int adapter_test(MGSLPC_INFO *info); + +static int claim_resources(MGSLPC_INFO *info); +static void release_resources(MGSLPC_INFO *info); +static void mgslpc_add_device(MGSLPC_INFO *info); +static void mgslpc_remove_device(MGSLPC_INFO *info); + +static int rx_get_frame(MGSLPC_INFO *info); +static void rx_reset_buffers(MGSLPC_INFO *info); +static int rx_alloc_buffers(MGSLPC_INFO *info); +static void rx_free_buffers(MGSLPC_INFO *info); + +static void mgslpc_isr(int irq, void *dev_id, struct pt_regs * regs); + +/* + * Bottom half interrupt handlers + */ +static void bh_handler(void* Context); +static void bh_transmit(MGSLPC_INFO *info); +static void bh_status(MGSLPC_INFO *info); + +/* + * ioctl handlers + */ +static int set_modem_info(MGSLPC_INFO *info, unsigned int cmd, + unsigned int *value); +static int get_modem_info(MGSLPC_INFO *info, unsigned int *value); +static int get_stats(MGSLPC_INFO *info, struct mgsl_icount *user_icount); +static int get_params(MGSLPC_INFO *info, MGSL_PARAMS *user_params); +static int set_params(MGSLPC_INFO *info, MGSL_PARAMS *new_params); +static int get_txidle(MGSLPC_INFO *info, int*idle_mode); +static int set_txidle(MGSLPC_INFO *info, int idle_mode); +static int set_txenable(MGSLPC_INFO *info, int enable); +static int tx_abort(MGSLPC_INFO *info); +static int set_rxenable(MGSLPC_INFO *info, int enable); +static int wait_events(MGSLPC_INFO *info, int *mask); + +#define jiffies_from_ms(a) ((((a) * HZ)/1000)+1) + +static MGSLPC_INFO *mgslpc_device_list = NULL; +static int mgslpc_device_count = 0; + +/* + * Set this param to non-zero to load eax with the + * .text section address and breakpoint on module load. + * This is useful for use with gdb and add-symbol-file command. + */ +static int break_on_load=0; + +/* + * Driver major number, defaults to zero to get auto + * assigned major number. May be forced as module parameter. + */ +static int ttymajor=0; +static int cuamajor=0; + +static int debug_level = 0; +static int maxframe[MAX_DEVICE_COUNT] = {0,}; + +/* The old way: bit map of interrupts to choose from */ +/* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, and 3 */ +static u_int irq_mask = 0xdeb8; + +/* Newer, simpler way of listing specific interrupts */ +static int irq_list[4] = { -1 }; + +MODULE_PARM(irq_mask, "i"); +MODULE_PARM(irq_list, "1-4i"); + +MODULE_PARM(break_on_load,"i"); +MODULE_PARM(ttymajor,"i"); +MODULE_PARM(cuamajor,"i"); +MODULE_PARM(debug_level,"i"); +MODULE_PARM(maxframe,"1-" __MODULE_STRING(MAX_DEVICE_COUNT) "i"); + +static char *driver_name = "SyncLink PC Card driver"; +static char *driver_version = "$Revision: 3.4 $"; + +static struct tty_driver serial_driver, callout_driver; +static int serial_refcount; + +/* number of characters left in xmit buffer before we ask for more */ +#define WAKEUP_CHARS 256 + +static void mgslpc_change_params(MGSLPC_INFO *info); +static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout); + +static struct tty_struct *serial_table[MAX_DEVICE_COUNT]; +static struct termios *serial_termios[MAX_DEVICE_COUNT]; +static struct termios *serial_termios_locked[MAX_DEVICE_COUNT]; + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +/* PCMCIA prototypes */ + +static void mgslpc_config(dev_link_t *link); +static void mgslpc_release(u_long arg); +static int mgslpc_event(event_t event, int priority, + event_callback_args_t *args); +static dev_link_t *mgslpc_attach(void); +static void mgslpc_detach(dev_link_t *); + +static dev_info_t dev_info = "synclink_cs"; +static dev_link_t *dev_list = NULL; + +static void cs_error(client_handle_t handle, int func, int ret) +{ + error_info_t err = { func, ret }; + CardServices(ReportError, handle, &err); +} + +/* + * 1st function defined in .text section. Calling this function in + * init_module() followed by a breakpoint allows a remote debugger + * (gdb) to get the .text address for the add-symbol-file command. + * This allows remote debugging of dynamically loadable modules. + */ +static void* mgslpc_get_text_ptr(void); +static void* mgslpc_get_text_ptr() {return mgslpc_get_text_ptr;} + +static dev_link_t *mgslpc_attach(void) +{ + MGSLPC_INFO *info; + dev_link_t *link; + client_reg_t client_reg; + int ret, i; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("mgslpc_attach\n"); + + info = (MGSLPC_INFO *)kmalloc(sizeof(MGSLPC_INFO), GFP_KERNEL); + if (!info) { + printk("Error can't allocate device instance data\n"); + return NULL; + } + + memset(info, 0, sizeof(MGSLPC_INFO)); + info->magic = MGSLPC_MAGIC; + info->task.sync = 0; + info->task.routine = bh_handler; + info->task.data = info; + info->max_frame_size = 4096; + info->close_delay = 5*HZ/10; + info->closing_wait = 30*HZ; + init_waitqueue_head(&info->open_wait); + init_waitqueue_head(&info->close_wait); + init_waitqueue_head(&info->status_event_wait_q); + init_waitqueue_head(&info->event_wait_q); + spin_lock_init(&info->lock); + spin_lock_init(&info->netlock); + memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS)); + info->idle_mode = HDLC_TXIDLE_FLAGS; + info->imra_value = 0xffff; + info->imrb_value = 0xffff; + info->pim_value = 0xff; + + link = &info->link; + link->priv = info; + + /* Initialize the dev_link_t structure */ + link->release.function = &mgslpc_release; + link->release.data = (u_long)link; + + /* Interrupt setup */ + link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID; + if (irq_list[0] == -1) + link->irq.IRQInfo2 = irq_mask; + else + for (i = 0; i < 4; i++) + link->irq.IRQInfo2 |= 1 << irq_list[i]; + link->irq.Handler = NULL; + + link->conf.Attributes = 0; + link->conf.Vcc = 50; + link->conf.IntType = INT_MEMORY_AND_IO; + + /* Register with Card Services */ + link->next = dev_list; + dev_list = link; + + client_reg.dev_info = &dev_info; + client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; + client_reg.EventMask = + CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | + CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | + CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; + client_reg.event_handler = &mgslpc_event; + client_reg.Version = 0x0210; + client_reg.event_callback_args.client_data = link; + + ret = CardServices(RegisterClient, &link->handle, &client_reg); + if (ret != CS_SUCCESS) { + cs_error(link->handle, RegisterClient, ret); + mgslpc_detach(link); + return NULL; + } + + mgslpc_add_device(info); + + memset(serial_table,0,sizeof(struct tty_struct*)*MAX_DEVICE_COUNT); + memset(serial_termios,0,sizeof(struct termios*)*MAX_DEVICE_COUNT); + memset(serial_termios_locked,0,sizeof(struct termios*)*MAX_DEVICE_COUNT); + + info->callout_termios = callout_driver.init_termios; + info->normal_termios = serial_driver.init_termios; + + return link; +} + +/* Card has been inserted. + */ + +#define CS_CHECK(fn, args...) \ +while ((last_ret=CardServices(last_fn=(fn),args))!=0) goto cs_failed + +static void mgslpc_config(dev_link_t *link) +{ + client_handle_t handle = link->handle; + MGSLPC_INFO *info = link->priv; + tuple_t tuple; + cisparse_t parse; + int last_fn, last_ret; + u_char buf[64]; + config_info_t conf; + cistpl_cftable_entry_t dflt = { 0 }; + cistpl_cftable_entry_t *cfg; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("mgslpc_config(0x%p)\n", link); + + /* read CONFIG tuple to find its configuration registers */ + tuple.DesiredTuple = CISTPL_CONFIG; + tuple.Attributes = 0; + tuple.TupleData = buf; + tuple.TupleDataMax = sizeof(buf); + tuple.TupleOffset = 0; + CS_CHECK(GetFirstTuple, handle, &tuple); + CS_CHECK(GetTupleData, handle, &tuple); + CS_CHECK(ParseTuple, handle, &tuple, &parse); + link->conf.ConfigBase = parse.config.base; + link->conf.Present = parse.config.rmask[0]; + + /* Configure card */ + link->state |= DEV_CONFIG; + + /* Look up the current Vcc */ + CS_CHECK(GetConfigurationInfo, handle, &conf); + link->conf.Vcc = conf.Vcc; + + /* get CIS configuration entry */ + + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + CS_CHECK(GetFirstTuple, handle, &tuple); + + cfg = &(parse.cftable_entry); + CS_CHECK(GetTupleData, handle, &tuple); + CS_CHECK(ParseTuple, handle, &tuple, &parse); + + if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; + if (cfg->index == 0) + goto cs_failed; + + link->conf.ConfigIndex = cfg->index; + link->conf.Attributes |= CONF_ENABLE_IRQ; + + /* IO window settings */ + link->io.NumPorts1 = 0; + if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { + cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; + link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; + if (!(io->flags & CISTPL_IO_8BIT)) + link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; + if (!(io->flags & CISTPL_IO_16BIT)) + link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; + link->io.BasePort1 = io->win[0].base; + link->io.NumPorts1 = io->win[0].len; + CS_CHECK(RequestIO, link->handle, &link->io); + } + + link->conf.Attributes = CONF_ENABLE_IRQ; + link->conf.Vcc = 50; + link->conf.IntType = INT_MEMORY_AND_IO; + link->conf.ConfigIndex = 8; + link->conf.Present = PRESENT_OPTION; + + link->irq.Attributes |= IRQ_HANDLE_PRESENT; + link->irq.Handler = mgslpc_isr; + link->irq.Instance = info; + CS_CHECK(RequestIRQ, link->handle, &link->irq); + + CS_CHECK(RequestConfiguration, link->handle, &link->conf); + + info->io_base = link->io.BasePort1; + info->irq_level = link->irq.AssignedIRQ; + + /* add to linked list of devices */ + sprintf(info->node.dev_name, "mgslpc0"); + info->node.major = info->node.minor = 0; + link->dev = &info->node; + + printk(KERN_INFO "%s: index 0x%02x:", + info->node.dev_name, link->conf.ConfigIndex); + if (link->conf.Attributes & CONF_ENABLE_IRQ) + printk(", irq %d", link->irq.AssignedIRQ); + if (link->io.NumPorts1) + printk(", io 0x%04x-0x%04x", link->io.BasePort1, + link->io.BasePort1+link->io.NumPorts1-1); + printk("\n"); + + link->state &= ~DEV_CONFIG_PENDING; + return; + +cs_failed: + cs_error(link->handle, last_fn, last_ret); + mgslpc_release((u_long)link); +} + +/* Card has been removed. + * Unregister device and release PCMCIA configuration. + * If device is open, postpone until it is closed. + */ +static void mgslpc_release(u_long arg) +{ + dev_link_t *link = (dev_link_t *)arg; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("mgslpc_release(0x%p)\n", link); + + if (link->open) { + if (debug_level >= DEBUG_LEVEL_INFO) + printk("synclink_cs: release postponed, '%s' still open\n", + link->dev->dev_name); + link->state |= DEV_STALE_CONFIG; + return; + } + + /* Unlink the device chain */ + link->dev = NULL; + link->state &= ~DEV_CONFIG; + + CardServices(ReleaseConfiguration, link->handle); + if (link->io.NumPorts1) + CardServices(ReleaseIO, link->handle, &link->io); + if (link->irq.AssignedIRQ) + CardServices(ReleaseIRQ, link->handle, &link->irq); + if (link->state & DEV_STALE_LINK) + mgslpc_detach(link); +} + +static void mgslpc_detach(dev_link_t *link) +{ + dev_link_t **linkp; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("mgslpc_detach(0x%p)\n", link); + + /* find device */ + for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) + if (*linkp == link) break; + if (*linkp == NULL) + return; + + if (link->state & DEV_CONFIG) { + /* device is configured/active, mark it so when + * release() is called a proper detach() occurs. + */ + if (debug_level >= DEBUG_LEVEL_INFO) + printk(KERN_DEBUG "synclinkpc: detach postponed, '%s' " + "still locked\n", link->dev->dev_name); + link->state |= DEV_STALE_LINK; + return; + } + + /* Break the link with Card Services */ + if (link->handle) + CardServices(DeregisterClient, link->handle); + + /* Unlink device structure, and free it */ + *linkp = link->next; + mgslpc_remove_device((MGSLPC_INFO *)link->priv); +} + +static int mgslpc_event(event_t event, int priority, + event_callback_args_t *args) +{ + dev_link_t *link = args->client_data; + MGSLPC_INFO *info = link->priv; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("mgslpc_event(0x%06x)\n", event); + + switch (event) { + case CS_EVENT_CARD_REMOVAL: + link->state &= ~DEV_PRESENT; + if (link->state & DEV_CONFIG) { + ((MGSLPC_INFO *)link->priv)->stop = 1; + mod_timer(&link->release, jiffies + HZ/20); + } + break; + case CS_EVENT_CARD_INSERTION: + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + info->bus = args->bus; + mgslpc_config(link); + break; + case CS_EVENT_PM_SUSPEND: + link->state |= DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_RESET_PHYSICAL: + /* Mark the device as stopped, to block IO until later */ + info->stop = 1; + if (link->state & DEV_CONFIG) + CardServices(ReleaseConfiguration, link->handle); + break; + case CS_EVENT_PM_RESUME: + link->state &= ~DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_CARD_RESET: + if (link->state & DEV_CONFIG) + CardServices(RequestConfiguration, link->handle, &link->conf); + info->stop = 0; + break; + } + return 0; +} + +static inline int mgslpc_paranoia_check(MGSLPC_INFO *info, + kdev_t device, const char *routine) +{ +#ifdef MGSLPC_PARANOIA_CHECK + static const char *badmagic = + "Warning: bad magic number for mgsl struct (%s) in %s\n"; + static const char *badinfo = + "Warning: null mgslpc_info for (%s) in %s\n"; + + if (!info) { + printk(badinfo, kdevname(device), routine); + return 1; + } + if (info->magic != MGSLPC_MAGIC) { + printk(badmagic, kdevname(device), routine); + return 1; + } +#endif + return 0; +} + + +#define CMD_RXFIFO BIT7 // release current rx FIFO +#define CMD_RXRESET BIT6 // receiver reset +#define CMD_RXFIFO_READ BIT5 +#define CMD_START_TIMER BIT4 +#define CMD_TXFIFO BIT3 // release current tx FIFO +#define CMD_TXEOM BIT1 // transmit end message +#define CMD_TXRESET BIT0 // transmit reset + +static BOOLEAN wait_command_complete(MGSLPC_INFO *info, unsigned char channel) +{ + int i = 0; + unsigned char status; + /* wait for command completion */ + while ((status = read_reg(info, (unsigned char)(channel+STAR)) & BIT2)) { + udelay(1); + if (i++ == 1000) + return FALSE; + } + return TRUE; +} + +static void issue_command(MGSLPC_INFO *info, unsigned char channel, unsigned char cmd) +{ + wait_command_complete(info, channel); + write_reg(info, (unsigned char) (channel + CMDR), cmd); +} + +static void tx_pause(struct tty_struct *tty) +{ + MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data; + unsigned long flags; + + if (mgslpc_paranoia_check(info, tty->device, "tx_pause")) + return; + if (debug_level >= DEBUG_LEVEL_INFO) + printk("tx_pause(%s)\n",info->device_name); + + spin_lock_irqsave(&info->lock,flags); + if (info->tx_enabled) + tx_stop(info); + spin_unlock_irqrestore(&info->lock,flags); +} + +static void tx_release(struct tty_struct *tty) +{ + MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data; + unsigned long flags; + + if (mgslpc_paranoia_check(info, tty->device, "tx_release")) + return; + if (debug_level >= DEBUG_LEVEL_INFO) + printk("tx_release(%s)\n",info->device_name); + + spin_lock_irqsave(&info->lock,flags); + if (!info->tx_enabled) + tx_start(info); + spin_unlock_irqrestore(&info->lock,flags); +} + +/* Return next bottom half action to perform. + * or 0 if nothing to do. + */ +int bh_action(MGSLPC_INFO *info) +{ + unsigned long flags; + int rc = 0; + + spin_lock_irqsave(&info->lock,flags); + + if (info->pending_bh & BH_RECEIVE) { + info->pending_bh &= ~BH_RECEIVE; + rc = BH_RECEIVE; + } else if (info->pending_bh & BH_TRANSMIT) { + info->pending_bh &= ~BH_TRANSMIT; + rc = BH_TRANSMIT; + } else if (info->pending_bh & BH_STATUS) { + info->pending_bh &= ~BH_STATUS; + rc = BH_STATUS; + } + + if (!rc) { + /* Mark BH routine as complete */ + info->bh_running = 0; + info->bh_requested = 0; + } + + spin_unlock_irqrestore(&info->lock,flags); + + return rc; +} + +void bh_handler(void* Context) +{ + MGSLPC_INFO *info = (MGSLPC_INFO*)Context; + int action; + + if (!info) + return; + + if (debug_level >= DEBUG_LEVEL_BH) + printk( "%s(%d):bh_handler(%s) entry\n", + __FILE__,__LINE__,info->device_name); + + info->bh_running = 1; + + while((action = bh_action(info)) != 0) { + + /* Process work item */ + if ( debug_level >= DEBUG_LEVEL_BH ) + printk( "%s(%d):bh_handler() work item action=%d\n", + __FILE__,__LINE__,action); + + switch (action) { + + case BH_RECEIVE: + while(rx_get_frame(info)); + break; + case BH_TRANSMIT: + bh_transmit(info); + break; + case BH_STATUS: + bh_status(info); + break; + default: + /* unknown work item ID */ + printk("Unknown work item ID=%08X!\n", action); + break; + } + } + + if (debug_level >= DEBUG_LEVEL_BH) + printk( "%s(%d):bh_handler(%s) exit\n", + __FILE__,__LINE__,info->device_name); +} + +void bh_transmit(MGSLPC_INFO *info) +{ + struct tty_struct *tty = info->tty; + if (debug_level >= DEBUG_LEVEL_BH) + printk("bh_transmit() entry on %s\n", info->device_name); + + if (tty) { + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) { + if ( debug_level >= DEBUG_LEVEL_BH ) + printk( "%s(%d):calling ldisc.write_wakeup on %s\n", + __FILE__,__LINE__,info->device_name); + (tty->ldisc.write_wakeup)(tty); + } + wake_up_interruptible(&tty->write_wait); + } +} + +void bh_status(MGSLPC_INFO *info) +{ + info->ri_chkcount = 0; + info->dsr_chkcount = 0; + info->dcd_chkcount = 0; + info->cts_chkcount = 0; +} + +/* eom: non-zero = end of frame */ +void rx_ready_hdlc(MGSLPC_INFO *info, int eom) +{ + unsigned char data[2]; + unsigned char fifo_count, read_count, i; + RXBUF *buf = (RXBUF*)(info->rx_buf + (info->rx_put * info->rx_buf_size)); + + if (debug_level >= DEBUG_LEVEL_ISR) + printk("%s(%d):rx_ready_hdlc(eom=%d)\n",__FILE__,__LINE__,eom); + + if (!info->rx_enabled) + return; + + if (info->rx_frame_count >= info->rx_buf_count) { + /* no more free buffers */ + issue_command(info, CHA, CMD_RXRESET); + info->pending_bh |= BH_RECEIVE; + info->rx_overflow = 1; + info->icount.buf_overrun++; + return; + } + + if (eom) { + /* end of frame, get FIFO count from RBCL register */ + if (!(fifo_count = (unsigned char)(read_reg(info, CHA+RBCL) & 0x1f))) + fifo_count = 32; + } else + fifo_count = 32; + + do { + if (fifo_count == 1) { + read_count = 1; + data[0] = read_reg(info, CHA + RXFIFO); + } else { + read_count = 2; + *((unsigned short *) data) = read_reg16(info, CHA + RXFIFO); + } + fifo_count -= read_count; + if (!fifo_count && eom) + buf->status = data[--read_count]; + + for (i = 0; i < read_count; i++) { + if (buf->count >= info->max_frame_size) { + /* frame too large, reset receiver and reset current buffer */ + issue_command(info, CHA, CMD_RXRESET); + buf->count = 0; + return; + } + *(buf->data + buf->count) = data[i]; + buf->count++; + } + } while (fifo_count); + + if (eom) { + info->pending_bh |= BH_RECEIVE; + info->rx_frame_count++; + info->rx_put++; + if (info->rx_put >= info->rx_buf_count) + info->rx_put = 0; + } + issue_command(info, CHA, CMD_RXFIFO); +} + +void rx_ready_async(MGSLPC_INFO *info, int tcd) +{ + unsigned char data, status; + int fifo_count; + struct tty_struct *tty = info->tty; + struct mgsl_icount *icount = &info->icount; + + if (tcd) { + /* early termination, get FIFO count from RBCL register */ + fifo_count = (unsigned char)(read_reg(info, CHA+RBCL) & 0x1f); + + /* Zero fifo count could mean 0 or 32 bytes available. + * If BIT5 of STAR is set then at least 1 byte is available. + */ + if (!fifo_count && (read_reg(info,CHA+STAR) & BIT5)) + fifo_count = 32; + } else + fifo_count = 32; + + /* Flush received async data to receive data buffer. */ + while (fifo_count) { + data = read_reg(info, CHA + RXFIFO); + status = read_reg(info, CHA + RXFIFO); + fifo_count -= 2; + + if (tty->flip.count >= TTY_FLIPBUF_SIZE) + break; + + *tty->flip.char_buf_ptr = data; + icount->rx++; + + *tty->flip.flag_buf_ptr = 0; + + // if no frameing/crc error then save data + // BIT7:parity error + // BIT6:framing error + + if (status & (BIT7 + BIT6)) { + if (status & BIT7) + icount->parity++; + else + icount->frame++; + + /* discard char if tty control flags say so */ + if (status & info->ignore_status_mask) + continue; + + status &= info->read_status_mask; + + if (status & BIT7) + *tty->flip.flag_buf_ptr = TTY_PARITY; + else if (status & BIT6) + *tty->flip.flag_buf_ptr = TTY_FRAME; + } + + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + tty->flip.count++; + } + issue_command(info, CHA, CMD_RXFIFO); + + if (debug_level >= DEBUG_LEVEL_ISR) { + printk("%s(%d):rx_ready_async count=%d\n", + __FILE__,__LINE__,tty->flip.count); + printk("%s(%d):rx=%d brk=%d parity=%d frame=%d overrun=%d\n", + __FILE__,__LINE__,icount->rx,icount->brk, + icount->parity,icount->frame,icount->overrun); + } + + if (tty->flip.count) + tty_flip_buffer_push(tty); +} + + +void tx_done(MGSLPC_INFO *info) +{ + if (!info->tx_active) + return; + + info->tx_active = 0; + info->tx_aborting = 0; + + if (info->params.mode == MGSL_MODE_ASYNC) + return; + + info->tx_count = info->tx_put = info->tx_get = 0; + del_timer(&info->tx_timer); + + if (info->drop_rts_on_tx_done) { + get_signals(info); + if (info->serial_signals & SerialSignal_RTS) { + info->serial_signals &= ~SerialSignal_RTS; + set_signals(info); + } + info->drop_rts_on_tx_done = 0; + } + +#ifdef CONFIG_SYNCLINK_SYNCPPP + if (info->netcount) + mgslpc_sppp_tx_done(info); + else +#endif + { + if (info->tty->stopped || info->tty->hw_stopped) { + tx_stop(info); + return; + } + info->pending_bh |= BH_TRANSMIT; + } +} + +void tx_ready(MGSLPC_INFO *info) +{ + unsigned char fifo_count = 32; + int c; + + if (debug_level >= DEBUG_LEVEL_ISR) + printk("%s(%d):tx_ready(%s)\n", __FILE__,__LINE__,info->device_name); + + if (info->params.mode == MGSL_MODE_HDLC) { + if (!info->tx_active) + return; + } else { + if (info->tty->stopped || info->tty->hw_stopped) { + tx_stop(info); + return; + } + if (!info->tx_count) + info->tx_active = 0; + } + + if (!info->tx_count) + return; + + while (info->tx_count && fifo_count) { + c = MIN(2, MIN(fifo_count, MIN(info->tx_count, TXBUFSIZE - info->tx_get))); + + if (c == 1) { + write_reg(info, CHA + TXFIFO, *(info->tx_buf + info->tx_get)); + } else { + write_reg16(info, CHA + TXFIFO, + *((unsigned short*)(info->tx_buf + info->tx_get))); + } + info->tx_count -= c; + info->tx_get = (info->tx_get + c) & (TXBUFSIZE - 1); + fifo_count -= c; + } + + if (info->params.mode == MGSL_MODE_ASYNC) { + if (info->tx_count < WAKEUP_CHARS) + info->pending_bh |= BH_TRANSMIT; + issue_command(info, CHA, CMD_TXFIFO); + } else { + if (info->tx_count) + issue_command(info, CHA, CMD_TXFIFO); + else + issue_command(info, CHA, CMD_TXFIFO + CMD_TXEOM); + } +} + +void cts_change(MGSLPC_INFO *info) +{ + get_signals(info); + if ((info->cts_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) + irq_disable(info, CHB, IRQ_CTS); + info->icount.cts++; + if (info->serial_signals & SerialSignal_CTS) + info->input_signal_events.cts_up++; + else + info->input_signal_events.cts_down++; + wake_up_interruptible(&info->status_event_wait_q); + wake_up_interruptible(&info->event_wait_q); + + if (info->flags & ASYNC_CTS_FLOW) { + if (info->tty->hw_stopped) { + if (info->serial_signals & SerialSignal_CTS) { + if (debug_level >= DEBUG_LEVEL_ISR) + printk("CTS tx start..."); + if (info->tty) + info->tty->hw_stopped = 0; + tx_start(info); + info->pending_bh |= BH_TRANSMIT; + return; + } + } else { + if (!(info->serial_signals & SerialSignal_CTS)) { + if (debug_level >= DEBUG_LEVEL_ISR) + printk("CTS tx stop..."); + if (info->tty) + info->tty->hw_stopped = 1; + tx_stop(info); + } + } + } + info->pending_bh |= BH_STATUS; +} + +void dcd_change(MGSLPC_INFO *info) +{ + get_signals(info); + if ((info->dcd_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) + irq_disable(info, CHB, IRQ_DCD); + info->icount.dcd++; + if (info->serial_signals & SerialSignal_DCD) { + info->input_signal_events.dcd_up++; +#ifdef CONFIG_SYNCLINK_SYNCPPP + if (info->netcount) + sppp_reopen(info->netdev); +#endif + } + else + info->input_signal_events.dcd_down++; + wake_up_interruptible(&info->status_event_wait_q); + wake_up_interruptible(&info->event_wait_q); + + if (info->flags & ASYNC_CHECK_CD) { + if (debug_level >= DEBUG_LEVEL_ISR) + printk("%s CD now %s...", info->device_name, + (info->serial_signals & SerialSignal_DCD) ? "on" : "off"); + if (info->serial_signals & SerialSignal_DCD) + wake_up_interruptible(&info->open_wait); + else if (!(info->flags & (ASYNC_CALLOUT_ACTIVE | ASYNC_CALLOUT_NOHUP))) { + if (debug_level >= DEBUG_LEVEL_ISR) + printk("doing serial hangup..."); + if (info->tty) + tty_hangup(info->tty); + } + } + info->pending_bh |= BH_STATUS; +} + +void dsr_change(MGSLPC_INFO *info) +{ + get_signals(info); + if ((info->dsr_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) + port_irq_disable(info, PVR_DSR); + info->icount.dsr++; + if (info->serial_signals & SerialSignal_DSR) + info->input_signal_events.dsr_up++; + else + info->input_signal_events.dsr_down++; + wake_up_interruptible(&info->status_event_wait_q); + wake_up_interruptible(&info->event_wait_q); + info->pending_bh |= BH_STATUS; +} + +void ri_change(MGSLPC_INFO *info) +{ + get_signals(info); + if ((info->ri_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) + port_irq_disable(info, PVR_RI); + info->icount.rng++; + if (info->serial_signals & SerialSignal_RI) + info->input_signal_events.ri_up++; + else + info->input_signal_events.ri_down++; + wake_up_interruptible(&info->status_event_wait_q); + wake_up_interruptible(&info->event_wait_q); + info->pending_bh |= BH_STATUS; +} + +/* Interrupt service routine entry point. + * + * Arguments: + * + * irq interrupt number that caused interrupt + * dev_id device ID supplied during interrupt registration + * regs interrupted processor context + */ +static void mgslpc_isr(int irq, void *dev_id, struct pt_regs * regs) +{ + MGSLPC_INFO * info = (MGSLPC_INFO *)dev_id; + unsigned short isr; + unsigned char gis, pis; + int count=0; + + if (debug_level >= DEBUG_LEVEL_ISR) + printk("mgslpc_isr(%d) entry.\n", irq); + if (!info) + return; + + if (!(info->link.state & DEV_CONFIG)) + return; + + spin_lock(&info->lock); + + while ((gis = read_reg(info, CHA + GIS))) { + if (debug_level >= DEBUG_LEVEL_ISR) + printk("mgslpc_isr %s gis=%04X\n", info->device_name,gis); + + if ((gis & 0x70) || count > 1000) { + printk("synclink_cs:hardware failed or ejected\n"); + break; + } + count++; + + if (gis & (BIT1 + BIT0)) { + isr = read_reg16(info, CHB + ISR); + if (isr & IRQ_DCD) + dcd_change(info); + if (isr & IRQ_CTS) + cts_change(info); + } + if (gis & (BIT3 + BIT2)) + { + isr = read_reg16(info, CHA + ISR); + if (isr & IRQ_TIMER) { + info->irq_occurred = 1; + irq_disable(info, CHA, IRQ_TIMER); + } + + /* receive IRQs */ + if (isr & IRQ_EXITHUNT) { + info->icount.exithunt++; + wake_up_interruptible(&info->event_wait_q); + } + if (isr & IRQ_BREAK_ON) { + info->icount.brk++; + if (info->flags & ASYNC_SAK) + do_SAK(info->tty); + } + if (isr & IRQ_RXTIME) { + issue_command(info, CHA, CMD_RXFIFO_READ); + } + if (isr & (IRQ_RXEOM + IRQ_RXFIFO)) { + if (info->params.mode == MGSL_MODE_HDLC) + rx_ready_hdlc(info, isr & IRQ_RXEOM); + else + rx_ready_async(info, isr & IRQ_RXEOM); + } + + /* transmit IRQs */ + if (isr & IRQ_UNDERRUN) { + if (info->tx_aborting) + info->icount.txabort++; + else + info->icount.txunder++; + tx_done(info); + } + else if (isr & IRQ_ALLSENT) { + info->icount.txok++; + tx_done(info); + } + else if (isr & IRQ_TXFIFO) + tx_ready(info); + } + if (gis & BIT7) { + pis = read_reg(info, CHA + PIS); + if (pis & BIT1) + dsr_change(info); + if (pis & BIT2) + ri_change(info); + } + } + + /* Request bottom half processing if there's something + * for it to do and the bh is not already running + */ + + if (info->pending_bh && !info->bh_running && !info->bh_requested) { + if ( debug_level >= DEBUG_LEVEL_ISR ) + printk("%s(%d):%s queueing bh task.\n", + __FILE__,__LINE__,info->device_name); + queue_task(&info->task, &tq_immediate); + mark_bh(IMMEDIATE_BH); + info->bh_requested = 1; + } + + spin_unlock(&info->lock); + + if (debug_level >= DEBUG_LEVEL_ISR) + printk("%s(%d):mgslpc_isr(%d)exit.\n", + __FILE__,__LINE__,irq); +} + +/* Initialize and start device. + */ +static int startup(MGSLPC_INFO * info) +{ + int retval = 0; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):startup(%s)\n",__FILE__,__LINE__,info->device_name); + + if (info->flags & ASYNC_INITIALIZED) + return 0; + + if (!info->tx_buf) { + /* allocate a page of memory for a transmit buffer */ + info->tx_buf = (unsigned char *)get_free_page(GFP_KERNEL); + if (!info->tx_buf) { + printk(KERN_ERR"%s(%d):%s can't allocate transmit buffer\n", + __FILE__,__LINE__,info->device_name); + return -ENOMEM; + } + } + + info->pending_bh = 0; + + init_timer(&info->tx_timer); + info->tx_timer.data = (unsigned long)info; + info->tx_timer.function = tx_timeout; + + /* Allocate and claim adapter resources */ + retval = claim_resources(info); + + /* perform existance check and diagnostics */ + if ( !retval ) + retval = adapter_test(info); + + if ( retval ) { + if (capable(CAP_SYS_ADMIN) && info->tty) + set_bit(TTY_IO_ERROR, &info->tty->flags); + release_resources(info); + return retval; + } + + /* program hardware for current parameters */ + mgslpc_change_params(info); + + if (info->tty) + clear_bit(TTY_IO_ERROR, &info->tty->flags); + + info->flags |= ASYNC_INITIALIZED; + + return 0; +} + +/* Called by mgslpc_close() and mgslpc_hangup() to shutdown hardware + */ +static void shutdown(MGSLPC_INFO * info) +{ + unsigned long flags; + + if (!(info->flags & ASYNC_INITIALIZED)) + return; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgslpc_shutdown(%s)\n", + __FILE__,__LINE__, info->device_name ); + + /* clear status wait queue because status changes */ + /* can't happen after shutting down the hardware */ + wake_up_interruptible(&info->status_event_wait_q); + wake_up_interruptible(&info->event_wait_q); + + del_timer(&info->tx_timer); + + if (info->tx_buf) { + free_page((unsigned long) info->tx_buf); + info->tx_buf = 0; + } + + spin_lock_irqsave(&info->lock,flags); + + rx_stop(info); + tx_stop(info); + + /* TODO:disable interrupts instead of reset to preserve signal states */ + reset_device(info); + + if (!info->tty || info->tty->termios->c_cflag & HUPCL) { + info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS); + set_signals(info); + } + + spin_unlock_irqrestore(&info->lock,flags); + + release_resources(info); + + if (info->tty) + set_bit(TTY_IO_ERROR, &info->tty->flags); + + info->flags &= ~ASYNC_INITIALIZED; +} + +static void mgslpc_program_hw(MGSLPC_INFO *info) +{ + unsigned long flags; + + spin_lock_irqsave(&info->lock,flags); + + rx_stop(info); + tx_stop(info); + info->tx_count = info->tx_put = info->tx_get = 0; + + if (info->params.mode == MGSL_MODE_HDLC || info->netcount) + hdlc_mode(info); + else + async_mode(info); + + set_signals(info); + + info->dcd_chkcount = 0; + info->cts_chkcount = 0; + info->ri_chkcount = 0; + info->dsr_chkcount = 0; + + irq_enable(info, CHB, IRQ_DCD | IRQ_CTS); + port_irq_enable(info, (unsigned char) PVR_DSR | PVR_RI); + get_signals(info); + + if (info->netcount || info->tty->termios->c_cflag & CREAD) + rx_start(info); + + spin_unlock_irqrestore(&info->lock,flags); +} + +/* Reconfigure adapter based on new parameters + */ +static void mgslpc_change_params(MGSLPC_INFO *info) +{ + unsigned cflag; + int bits_per_char; + + if (!info->tty || !info->tty->termios) + return; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgslpc_change_params(%s)\n", + __FILE__,__LINE__, info->device_name ); + + cflag = info->tty->termios->c_cflag; + + /* if B0 rate (hangup) specified then negate DTR and RTS */ + /* otherwise assert DTR and RTS */ + if (cflag & CBAUD) + info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; + else + info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR); + + /* byte size and parity */ + + switch (cflag & CSIZE) { + case CS5: info->params.data_bits = 5; break; + case CS6: info->params.data_bits = 6; break; + case CS7: info->params.data_bits = 7; break; + case CS8: info->params.data_bits = 8; break; + default: info->params.data_bits = 7; break; + } + + if (cflag & CSTOPB) + info->params.stop_bits = 2; + else + info->params.stop_bits = 1; + + info->params.parity = ASYNC_PARITY_NONE; + if (cflag & PARENB) { + if (cflag & PARODD) + info->params.parity = ASYNC_PARITY_ODD; + else + info->params.parity = ASYNC_PARITY_EVEN; +#ifdef CMSPAR + if (cflag & CMSPAR) + info->params.parity = ASYNC_PARITY_SPACE; +#endif + } + + /* calculate number of jiffies to transmit a full + * FIFO (32 bytes) at specified data rate + */ + bits_per_char = info->params.data_bits + + info->params.stop_bits + 1; + + /* if port data rate is set to 460800 or less then + * allow tty settings to override, otherwise keep the + * current data rate. + */ + if (info->params.data_rate <= 460800) { + info->params.data_rate = tty_get_baud_rate(info->tty); + } + + if ( info->params.data_rate ) { + info->timeout = (32*HZ*bits_per_char) / + info->params.data_rate; + } + info->timeout += HZ/50; /* Add .02 seconds of slop */ + + if (cflag & CRTSCTS) + info->flags |= ASYNC_CTS_FLOW; + else + info->flags &= ~ASYNC_CTS_FLOW; + + if (cflag & CLOCAL) + info->flags &= ~ASYNC_CHECK_CD; + else + info->flags |= ASYNC_CHECK_CD; + + /* process tty input control flags */ + + info->read_status_mask = 0; + if (I_INPCK(info->tty)) + info->read_status_mask |= BIT7 | BIT6; + if (I_IGNPAR(info->tty)) + info->ignore_status_mask |= BIT7 | BIT6; + + mgslpc_program_hw(info); +} + +/* Add a character to the transmit buffer + */ +static void mgslpc_put_char(struct tty_struct *tty, unsigned char ch) +{ + MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data; + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) { + printk( "%s(%d):mgslpc_put_char(%d) on %s\n", + __FILE__,__LINE__,ch,info->device_name); + } + + if (mgslpc_paranoia_check(info, tty->device, "mgslpc_put_char")) + return; + + if (!tty || !info->tx_buf) + return; + + spin_lock_irqsave(&info->lock,flags); + + if (info->params.mode == MGSL_MODE_ASYNC || !info->tx_active) { + if (info->tx_count < TXBUFSIZE - 1) { + info->tx_buf[info->tx_put++] = ch; + info->tx_put &= TXBUFSIZE-1; + info->tx_count++; + } + } + + spin_unlock_irqrestore(&info->lock,flags); +} + +/* Enable transmitter so remaining characters in the + * transmit buffer are sent. + */ +static void mgslpc_flush_chars(struct tty_struct *tty) +{ + MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data; + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk( "%s(%d):mgslpc_flush_chars() entry on %s tx_count=%d\n", + __FILE__,__LINE__,info->device_name,info->tx_count); + + if (mgslpc_paranoia_check(info, tty->device, "mgslpc_flush_chars")) + return; + + if (info->tx_count <= 0 || tty->stopped || + tty->hw_stopped || !info->tx_buf) + return; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk( "%s(%d):mgslpc_flush_chars() entry on %s starting transmitter\n", + __FILE__,__LINE__,info->device_name); + + spin_lock_irqsave(&info->lock,flags); + if (!info->tx_active) + tx_start(info); + spin_unlock_irqrestore(&info->lock,flags); +} + +/* Send a block of data + * + * Arguments: + * + * tty pointer to tty information structure + * from_user flag: 1 = from user process + * buf pointer to buffer containing send data + * count size of send data in bytes + * + * Returns: number of characters written + */ +static int mgslpc_write(struct tty_struct * tty, int from_user, + const unsigned char *buf, int count) +{ + int c, ret = 0, err; + MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data; + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk( "%s(%d):mgslpc_write(%s) count=%d\n", + __FILE__,__LINE__,info->device_name,count); + + if (mgslpc_paranoia_check(info, tty->device, "mgslpc_write") || + !tty || !info->tx_buf) + goto cleanup; + + if (info->params.mode == MGSL_MODE_HDLC) { + if (count > TXBUFSIZE) { + ret = -EIO; + goto cleanup; + } + if (info->tx_active) + goto cleanup; + else if (info->tx_count) + goto start; + } + + for (;;) { + c = MIN(count, + MIN(TXBUFSIZE - info->tx_count - 1, + TXBUFSIZE - info->tx_put)); + if (c <= 0) + break; + + if (from_user) { + COPY_FROM_USER(err, info->tx_buf + info->tx_put, buf, c); + if (err) { + if (!ret) + ret = -EFAULT; + break; + } + } else + memcpy(info->tx_buf + info->tx_put, buf, c); + + spin_lock_irqsave(&info->lock,flags); + info->tx_put = (info->tx_put + c) & (TXBUFSIZE-1); + info->tx_count += c; + spin_unlock_irqrestore(&info->lock,flags); + + buf += c; + count -= c; + ret += c; + } +start: + if (info->tx_count && !tty->stopped && !tty->hw_stopped) { + spin_lock_irqsave(&info->lock,flags); + if (!info->tx_active) + tx_start(info); + spin_unlock_irqrestore(&info->lock,flags); + } +cleanup: + if (debug_level >= DEBUG_LEVEL_INFO) + printk( "%s(%d):mgslpc_write(%s) returning=%d\n", + __FILE__,__LINE__,info->device_name,ret); + return ret; +} + +/* Return the count of free bytes in transmit buffer + */ +static int mgslpc_write_room(struct tty_struct *tty) +{ + MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data; + int ret; + + if (mgslpc_paranoia_check(info, tty->device, "mgslpc_write_room")) + return 0; + + if (info->params.mode == MGSL_MODE_HDLC) { + /* HDLC (frame oriented) mode */ + if (info->tx_active) + return 0; + else + return HDLC_MAX_FRAME_SIZE; + } else { + ret = TXBUFSIZE - info->tx_count - 1; + if (ret < 0) + ret = 0; + } + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgslpc_write_room(%s)=%d\n", + __FILE__,__LINE__, info->device_name, ret); + return ret; +} + +/* Return the count of bytes in transmit buffer + */ +static int mgslpc_chars_in_buffer(struct tty_struct *tty) +{ + MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data; + int rc; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgslpc_chars_in_buffer(%s)\n", + __FILE__,__LINE__, info->device_name ); + + if (mgslpc_paranoia_check(info, tty->device, "mgslpc_chars_in_buffer")) + return 0; + + if (info->params.mode == MGSL_MODE_HDLC) + rc = info->tx_active ? info->max_frame_size : 0; + else + rc = info->tx_count; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgslpc_chars_in_buffer(%s)=%d\n", + __FILE__,__LINE__, info->device_name, rc); + + return rc; +} + +/* Discard all data in the send buffer + */ +static void mgslpc_flush_buffer(struct tty_struct *tty) +{ + MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data; + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgslpc_flush_buffer(%s) entry\n", + __FILE__,__LINE__, info->device_name ); + + if (mgslpc_paranoia_check(info, tty->device, "mgslpc_flush_buffer")) + return; + + spin_lock_irqsave(&info->lock,flags); + info->tx_count = info->tx_put = info->tx_get = 0; + del_timer(&info->tx_timer); + spin_unlock_irqrestore(&info->lock,flags); + + wake_up_interruptible(&tty->write_wait); + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); +} + +/* Send a high-priority XON/XOFF character + */ +static void mgslpc_send_xchar(struct tty_struct *tty, char ch) +{ + MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data; + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgslpc_send_xchar(%s,%d)\n", + __FILE__,__LINE__, info->device_name, ch ); + + if (mgslpc_paranoia_check(info, tty->device, "mgslpc_send_xchar")) + return; + + info->x_char = ch; + if (ch) { + spin_lock_irqsave(&info->lock,flags); + if (!info->tx_enabled) + tx_start(info); + spin_unlock_irqrestore(&info->lock,flags); + } +} + +/* Signal remote device to throttle send data (our receive data) + */ +static void mgslpc_throttle(struct tty_struct * tty) +{ + MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data; + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgslpc_throttle(%s) entry\n", + __FILE__,__LINE__, info->device_name ); + + if (mgslpc_paranoia_check(info, tty->device, "mgslpc_throttle")) + return; + + if (I_IXOFF(tty)) + mgslpc_send_xchar(tty, STOP_CHAR(tty)); + + if (tty->termios->c_cflag & CRTSCTS) { + spin_lock_irqsave(&info->lock,flags); + info->serial_signals &= ~SerialSignal_RTS; + set_signals(info); + spin_unlock_irqrestore(&info->lock,flags); + } +} + +/* Signal remote device to stop throttling send data (our receive data) + */ +static void mgslpc_unthrottle(struct tty_struct * tty) +{ + MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data; + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgslpc_unthrottle(%s) entry\n", + __FILE__,__LINE__, info->device_name ); + + if (mgslpc_paranoia_check(info, tty->device, "mgslpc_unthrottle")) + return; + + if (I_IXOFF(tty)) { + if (info->x_char) + info->x_char = 0; + else + mgslpc_send_xchar(tty, START_CHAR(tty)); + } + + if (tty->termios->c_cflag & CRTSCTS) { + spin_lock_irqsave(&info->lock,flags); + info->serial_signals |= SerialSignal_RTS; + set_signals(info); + spin_unlock_irqrestore(&info->lock,flags); + } +} + +/* get the current serial statistics + */ +static int get_stats(MGSLPC_INFO * info, struct mgsl_icount *user_icount) +{ + int err; + if (debug_level >= DEBUG_LEVEL_INFO) + printk("get_params(%s)\n", info->device_name); + COPY_TO_USER(err,user_icount, &info->icount, sizeof(struct mgsl_icount)); + if (err) + return -EFAULT; + return 0; +} + +/* get the current serial parameters + */ +static int get_params(MGSLPC_INFO * info, MGSL_PARAMS *user_params) +{ + int err; + if (debug_level >= DEBUG_LEVEL_INFO) + printk("get_params(%s)\n", info->device_name); + COPY_TO_USER(err,user_params, &info->params, sizeof(MGSL_PARAMS)); + if (err) + return -EFAULT; + return 0; +} + +/* set the serial parameters + * + * Arguments: + * + * info pointer to device instance data + * new_params user buffer containing new serial params + * + * Returns: 0 if success, otherwise error code + */ +static int set_params(MGSLPC_INFO * info, MGSL_PARAMS *new_params) +{ + unsigned long flags; + MGSL_PARAMS tmp_params; + int err; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):set_params %s\n", __FILE__,__LINE__, + info->device_name ); + COPY_FROM_USER(err,&tmp_params, new_params, sizeof(MGSL_PARAMS)); + if (err) { + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk( "%s(%d):set_params(%s) user buffer copy failed\n", + __FILE__,__LINE__,info->device_name); + return -EFAULT; + } + + spin_lock_irqsave(&info->lock,flags); + memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS)); + spin_unlock_irqrestore(&info->lock,flags); + + mgslpc_change_params(info); + + return 0; +} + +static int get_txidle(MGSLPC_INFO * info, int*idle_mode) +{ + int err; + if (debug_level >= DEBUG_LEVEL_INFO) + printk("get_txidle(%s)=%d\n", info->device_name, info->idle_mode); + COPY_TO_USER(err,idle_mode, &info->idle_mode, sizeof(int)); + if (err) + return -EFAULT; + return 0; +} + +static int set_txidle(MGSLPC_INFO * info, int idle_mode) +{ + unsigned long flags; + if (debug_level >= DEBUG_LEVEL_INFO) + printk("set_txidle(%s,%d)\n", info->device_name, idle_mode); + spin_lock_irqsave(&info->lock,flags); + info->idle_mode = idle_mode; + tx_set_idle(info); + spin_unlock_irqrestore(&info->lock,flags); + return 0; +} + +static int get_interface(MGSLPC_INFO * info, int*if_mode) +{ + int err; + if (debug_level >= DEBUG_LEVEL_INFO) + printk("get_interface(%s)=%d\n", info->device_name, info->if_mode); + COPY_TO_USER(err,if_mode, &info->if_mode, sizeof(int)); + if (err) + return -EFAULT; + return 0; +} + +static int set_interface(MGSLPC_INFO * info, int if_mode) +{ + unsigned long flags; + unsigned char val; + if (debug_level >= DEBUG_LEVEL_INFO) + printk("set_interface(%s,%d)\n", info->device_name, if_mode); + spin_lock_irqsave(&info->lock,flags); + info->if_mode = if_mode; + + val = read_reg(info, PVR) & 0x0f; + switch (info->if_mode) + { + case MGSL_INTERFACE_RS232: val |= PVR_RS232; break; + case MGSL_INTERFACE_V35: val |= PVR_V35; break; + case MGSL_INTERFACE_RS422: val |= PVR_RS422; break; + } + write_reg(info, PVR, val); + + spin_unlock_irqrestore(&info->lock,flags); + return 0; +} + +static int set_txenable(MGSLPC_INFO * info, int enable) +{ + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("set_txenable(%s,%d)\n", info->device_name, enable); + + spin_lock_irqsave(&info->lock,flags); + if (enable) { + if (!info->tx_enabled) + tx_start(info); + } else { + if (info->tx_enabled) + tx_stop(info); + } + spin_unlock_irqrestore(&info->lock,flags); + return 0; +} + +static int tx_abort(MGSLPC_INFO * info) +{ + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("tx_abort(%s)\n", info->device_name); + + spin_lock_irqsave(&info->lock,flags); + if (info->tx_active && info->tx_count && + info->params.mode == MGSL_MODE_HDLC) { + /* clear data count so FIFO is not filled on next IRQ. + * This results in underrun and abort transmission. + */ + info->tx_count = info->tx_put = info->tx_get = 0; + info->tx_aborting = TRUE; + } + spin_unlock_irqrestore(&info->lock,flags); + return 0; +} + +static int set_rxenable(MGSLPC_INFO * info, int enable) +{ + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("set_rxenable(%s,%d)\n", info->device_name, enable); + + spin_lock_irqsave(&info->lock,flags); + if (enable) { + if (!info->rx_enabled) + rx_start(info); + } else { + if (info->rx_enabled) + rx_stop(info); + } + spin_unlock_irqrestore(&info->lock,flags); + return 0; +} + +/* wait for specified event to occur + * + * Arguments: info pointer to device instance data + * mask pointer to bitmask of events to wait for + * Return Value: 0 if successful and bit mask updated with + * of events triggerred, + * otherwise error code + */ +static int wait_events(MGSLPC_INFO * info, int * mask_ptr) +{ + unsigned long flags; + int s; + int rc=0; + struct mgsl_icount cprev, cnow; + int events; + int mask; + struct _input_signal_events oldsigs, newsigs; + DECLARE_WAITQUEUE(wait, current); + + COPY_FROM_USER(rc,&mask, mask_ptr, sizeof(int)); + if (rc) + return -EFAULT; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("wait_events(%s,%d)\n", info->device_name, mask); + + spin_lock_irqsave(&info->lock,flags); + + /* return immediately if state matches requested events */ + get_signals(info); + s = info->serial_signals; + events = mask & + ( ((s & SerialSignal_DSR) ? MgslEvent_DsrActive:MgslEvent_DsrInactive) + + ((s & SerialSignal_DCD) ? MgslEvent_DcdActive:MgslEvent_DcdInactive) + + ((s & SerialSignal_CTS) ? MgslEvent_CtsActive:MgslEvent_CtsInactive) + + ((s & SerialSignal_RI) ? MgslEvent_RiActive :MgslEvent_RiInactive) ); + if (events) { + spin_unlock_irqrestore(&info->lock,flags); + goto exit; + } + + /* save current irq counts */ + cprev = info->icount; + oldsigs = info->input_signal_events; + + if ((info->params.mode == MGSL_MODE_HDLC) && + (mask & MgslEvent_ExitHuntMode)) + irq_enable(info, CHA, IRQ_EXITHUNT); + + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&info->event_wait_q, &wait); + + spin_unlock_irqrestore(&info->lock,flags); + + + for(;;) { + schedule(); + if (signal_pending(current)) { + rc = -ERESTARTSYS; + break; + } + + /* get current irq counts */ + spin_lock_irqsave(&info->lock,flags); + cnow = info->icount; + newsigs = info->input_signal_events; + set_current_state(TASK_INTERRUPTIBLE); + spin_unlock_irqrestore(&info->lock,flags); + + /* if no change, wait aborted for some reason */ + if (newsigs.dsr_up == oldsigs.dsr_up && + newsigs.dsr_down == oldsigs.dsr_down && + newsigs.dcd_up == oldsigs.dcd_up && + newsigs.dcd_down == oldsigs.dcd_down && + newsigs.cts_up == oldsigs.cts_up && + newsigs.cts_down == oldsigs.cts_down && + newsigs.ri_up == oldsigs.ri_up && + newsigs.ri_down == oldsigs.ri_down && + cnow.exithunt == cprev.exithunt && + cnow.rxidle == cprev.rxidle) { + rc = -EIO; + break; + } + + events = mask & + ( (newsigs.dsr_up != oldsigs.dsr_up ? MgslEvent_DsrActive:0) + + (newsigs.dsr_down != oldsigs.dsr_down ? MgslEvent_DsrInactive:0) + + (newsigs.dcd_up != oldsigs.dcd_up ? MgslEvent_DcdActive:0) + + (newsigs.dcd_down != oldsigs.dcd_down ? MgslEvent_DcdInactive:0) + + (newsigs.cts_up != oldsigs.cts_up ? MgslEvent_CtsActive:0) + + (newsigs.cts_down != oldsigs.cts_down ? MgslEvent_CtsInactive:0) + + (newsigs.ri_up != oldsigs.ri_up ? MgslEvent_RiActive:0) + + (newsigs.ri_down != oldsigs.ri_down ? MgslEvent_RiInactive:0) + + (cnow.exithunt != cprev.exithunt ? MgslEvent_ExitHuntMode:0) + + (cnow.rxidle != cprev.rxidle ? MgslEvent_IdleReceived:0) ); + if (events) + break; + + cprev = cnow; + oldsigs = newsigs; + } + + remove_wait_queue(&info->event_wait_q, &wait); + set_current_state(TASK_RUNNING); + + if (mask & MgslEvent_ExitHuntMode) { + spin_lock_irqsave(&info->lock,flags); + if (!waitqueue_active(&info->event_wait_q)) + irq_disable(info, CHA, IRQ_EXITHUNT); + spin_unlock_irqrestore(&info->lock,flags); + } +exit: + if (rc == 0) + PUT_USER(rc, events, mask_ptr); + return rc; +} + +static int modem_input_wait(MGSLPC_INFO *info,int arg) +{ + unsigned long flags; + int rc; + struct mgsl_icount cprev, cnow; + DECLARE_WAITQUEUE(wait, current); + + /* save current irq counts */ + spin_lock_irqsave(&info->lock,flags); + cprev = info->icount; + add_wait_queue(&info->status_event_wait_q, &wait); + set_current_state(TASK_INTERRUPTIBLE); + spin_unlock_irqrestore(&info->lock,flags); + + for(;;) { + schedule(); + if (signal_pending(current)) { + rc = -ERESTARTSYS; + break; + } + + /* get new irq counts */ + spin_lock_irqsave(&info->lock,flags); + cnow = info->icount; + set_current_state(TASK_INTERRUPTIBLE); + spin_unlock_irqrestore(&info->lock,flags); + + /* if no change, wait aborted for some reason */ + if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && + cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) { + rc = -EIO; + break; + } + + /* check for change in caller specified modem input */ + if ((arg & TIOCM_RNG && cnow.rng != cprev.rng) || + (arg & TIOCM_DSR && cnow.dsr != cprev.dsr) || + (arg & TIOCM_CD && cnow.dcd != cprev.dcd) || + (arg & TIOCM_CTS && cnow.cts != cprev.cts)) { + rc = 0; + break; + } + + cprev = cnow; + } + remove_wait_queue(&info->status_event_wait_q, &wait); + set_current_state(TASK_RUNNING); + return rc; +} + +/* Return state of the serial control/status signals + * + * Arguments: info pointer to device instance data + * value pointer to int to hold returned info + * + * Return Value: 0 if success, otherwise error code + */ +static int get_modem_info(MGSLPC_INFO * info, unsigned int *value) +{ + unsigned int result; + unsigned long flags; + int err; + + spin_lock_irqsave(&info->lock,flags); + get_signals(info); + spin_unlock_irqrestore(&info->lock,flags); + + result = ((info->serial_signals & SerialSignal_RTS) ? TIOCM_RTS:0) | + ((info->serial_signals & SerialSignal_DTR) ? TIOCM_DTR:0) | + ((info->serial_signals & SerialSignal_DCD) ? TIOCM_CAR:0) | + ((info->serial_signals & SerialSignal_RI) ? TIOCM_RNG:0) | + ((info->serial_signals & SerialSignal_DSR) ? TIOCM_DSR:0) | + ((info->serial_signals & SerialSignal_CTS) ? TIOCM_CTS:0); + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("mgslpc_get_modem_info %s value=%08X\n", info->device_name, result); + + PUT_USER(err,result,value); + return err ? -EFAULT : 0; +} + +/* Set the state of the modem control signals (DTR/RTS) + * + * Arguments: + * + * info pointer to device instance data + * cmd signal command: TIOCMBIS = set bit TIOCMBIC = clear bit + * TIOCMSET = set/clear signal values + * value bit mask for command + * + * Return Value: 0 if success, otherwise error code + */ +static int set_modem_info(MGSLPC_INFO * info, unsigned int cmd, + unsigned int *value) +{ + int error; + unsigned int arg; + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("mgslpc_set_modem_info %s\n", info->device_name); + + GET_USER(error,arg,value); + if (error) + return error; + + switch (cmd) { + case TIOCMBIS: + if (arg & TIOCM_RTS) + info->serial_signals |= SerialSignal_RTS; + if (arg & TIOCM_DTR) + info->serial_signals |= SerialSignal_DTR; + break; + case TIOCMBIC: + if (arg & TIOCM_RTS) + info->serial_signals &= ~SerialSignal_RTS; + if (arg & TIOCM_DTR) + info->serial_signals &= ~SerialSignal_DTR; + break; + case TIOCMSET: + if (arg & TIOCM_RTS) + info->serial_signals |= SerialSignal_RTS; + else + info->serial_signals &= ~SerialSignal_RTS; + + if (arg & TIOCM_DTR) + info->serial_signals |= SerialSignal_DTR; + else + info->serial_signals &= ~SerialSignal_DTR; + break; + default: + return -EINVAL; + } + + spin_lock_irqsave(&info->lock,flags); + set_signals(info); + spin_unlock_irqrestore(&info->lock,flags); + + return 0; +} + +/* Set or clear transmit break condition + * + * Arguments: tty pointer to tty instance data + * break_state -1=set break condition, 0=clear + */ +static void mgslpc_break(struct tty_struct *tty, int break_state) +{ + MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data; + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgslpc_break(%s,%d)\n", + __FILE__,__LINE__, info->device_name, break_state); + + if (mgslpc_paranoia_check(info, tty->device, "mgslpc_break")) + return; + + spin_lock_irqsave(&info->lock,flags); + if (break_state == -1) + set_reg_bits(info, CHA+DAFO, BIT6); + else + clear_reg_bits(info, CHA+DAFO, BIT6); + spin_unlock_irqrestore(&info->lock,flags); +} + +/* Service an IOCTL request + * + * Arguments: + * + * tty pointer to tty instance data + * file pointer to associated file object for device + * cmd IOCTL command code + * arg command argument/context + * + * Return Value: 0 if success, otherwise error code + */ +static int mgslpc_ioctl(struct tty_struct *tty, struct file * file, + unsigned int cmd, unsigned long arg) +{ + MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgslpc_ioctl %s cmd=%08X\n", __FILE__,__LINE__, + info->device_name, cmd ); + + if (mgslpc_paranoia_check(info, tty->device, "mgslpc_ioctl")) + return -ENODEV; + + if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && + (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + } + + return ioctl_common(info, cmd, arg); +} + +int ioctl_common(MGSLPC_INFO *info, unsigned int cmd, unsigned long arg) +{ + int error; + struct mgsl_icount cnow; /* kernel counter temps */ + struct serial_icounter_struct *p_cuser; /* user space */ + unsigned long flags; + + switch (cmd) { + case TIOCMGET: + return get_modem_info(info, (unsigned int *) arg); + case TIOCMBIS: + case TIOCMBIC: + case TIOCMSET: + return set_modem_info(info, cmd, (unsigned int *) arg); + case MGSL_IOCGPARAMS: + return get_params(info,(MGSL_PARAMS *)arg); + case MGSL_IOCSPARAMS: + return set_params(info,(MGSL_PARAMS *)arg); + case MGSL_IOCGTXIDLE: + return get_txidle(info,(int*)arg); + case MGSL_IOCSTXIDLE: + return set_txidle(info,(int)arg); + case MGSL_IOCGIF: + return get_interface(info,(int*)arg); + case MGSL_IOCSIF: + return set_interface(info,(int)arg); + case MGSL_IOCTXENABLE: + return set_txenable(info,(int)arg); + case MGSL_IOCRXENABLE: + return set_rxenable(info,(int)arg); + case MGSL_IOCTXABORT: + return tx_abort(info); + case MGSL_IOCGSTATS: + return get_stats(info,(struct mgsl_icount*)arg); + case MGSL_IOCWAITEVENT: + return wait_events(info,(int*)arg); + case MGSL_IOCCLRMODCOUNT: + while(MOD_IN_USE) + MOD_DEC_USE_COUNT; + return 0; + case TIOCMIWAIT: + return modem_input_wait(info,(int)arg); + case TIOCGICOUNT: + spin_lock_irqsave(&info->lock,flags); + cnow = info->icount; + spin_unlock_irqrestore(&info->lock,flags); + p_cuser = (struct serial_icounter_struct *) arg; + PUT_USER(error,cnow.cts, &p_cuser->cts); + if (error) return error; + PUT_USER(error,cnow.dsr, &p_cuser->dsr); + if (error) return error; + PUT_USER(error,cnow.rng, &p_cuser->rng); + if (error) return error; + PUT_USER(error,cnow.dcd, &p_cuser->dcd); + if (error) return error; + PUT_USER(error,cnow.rx, &p_cuser->rx); + if (error) return error; + PUT_USER(error,cnow.tx, &p_cuser->tx); + if (error) return error; + PUT_USER(error,cnow.frame, &p_cuser->frame); + if (error) return error; + PUT_USER(error,cnow.overrun, &p_cuser->overrun); + if (error) return error; + PUT_USER(error,cnow.parity, &p_cuser->parity); + if (error) return error; + PUT_USER(error,cnow.brk, &p_cuser->brk); + if (error) return error; + PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun); + if (error) return error; + return 0; + default: + return -ENOIOCTLCMD; + } + return 0; +} + +/* Set new termios settings + * + * Arguments: + * + * tty pointer to tty structure + * termios pointer to buffer to hold returned old termios + */ +static void mgslpc_set_termios(struct tty_struct *tty, struct termios *old_termios) +{ + MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data; + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgslpc_set_termios %s\n", __FILE__,__LINE__, + tty->driver.name ); + + /* just return if nothing has changed */ + if ((tty->termios->c_cflag == old_termios->c_cflag) + && (RELEVANT_IFLAG(tty->termios->c_iflag) + == RELEVANT_IFLAG(old_termios->c_iflag))) + return; + + mgslpc_change_params(info); + + /* Handle transition to B0 status */ + if (old_termios->c_cflag & CBAUD && + !(tty->termios->c_cflag & CBAUD)) { + info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR); + spin_lock_irqsave(&info->lock,flags); + set_signals(info); + spin_unlock_irqrestore(&info->lock,flags); + } + + /* Handle transition away from B0 status */ + if (!(old_termios->c_cflag & CBAUD) && + tty->termios->c_cflag & CBAUD) { + info->serial_signals |= SerialSignal_DTR; + if (!(tty->termios->c_cflag & CRTSCTS) || + !test_bit(TTY_THROTTLED, &tty->flags)) { + info->serial_signals |= SerialSignal_RTS; + } + spin_lock_irqsave(&info->lock,flags); + set_signals(info); + spin_unlock_irqrestore(&info->lock,flags); + } + + /* Handle turning off CRTSCTS */ + if (old_termios->c_cflag & CRTSCTS && + !(tty->termios->c_cflag & CRTSCTS)) { + tty->hw_stopped = 0; + tx_release(tty); + } +} + +static void mgslpc_close(struct tty_struct *tty, struct file * filp) +{ + MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data; + + if (!info || mgslpc_paranoia_check(info, tty->device, "mgslpc_close")) + return; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgslpc_close(%s) entry, count=%d\n", + __FILE__,__LINE__, info->device_name, info->count); + + if (!info->count || tty_hung_up_p(filp)) + goto cleanup; + + if ((tty->count == 1) && (info->count != 1)) { + /* + * tty->count is 1 and the tty structure will be freed. + * info->count should be one in this case. + * if it's not, correct it so that the port is shutdown. + */ + printk("mgslpc_close: bad refcount; tty->count is 1, " + "info->count is %d\n", info->count); + info->count = 1; + } + + info->count--; + + /* if at least one open remaining, leave hardware active */ + if (info->count) + goto cleanup; + + info->flags |= ASYNC_CLOSING; + + /* Save the termios structure, since this port may have + * separate termios for callout and dialin. + */ + if (info->flags & ASYNC_NORMAL_ACTIVE) + info->normal_termios = *tty->termios; + if (info->flags & ASYNC_CALLOUT_ACTIVE) + info->callout_termios = *tty->termios; + + /* set tty->closing to notify line discipline to + * only process XON/XOFF characters. Only the N_TTY + * discipline appears to use this (ppp does not). + */ + tty->closing = 1; + + /* wait for transmit data to clear all layers */ + + if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) { + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgslpc_close(%s) calling tty_wait_until_sent\n", + __FILE__,__LINE__, info->device_name ); + tty_wait_until_sent(tty, info->closing_wait); + } + + if (info->flags & ASYNC_INITIALIZED) + mgslpc_wait_until_sent(tty, info->timeout); + + if (tty->driver.flush_buffer) + tty->driver.flush_buffer(tty); + + if (tty->ldisc.flush_buffer) + tty->ldisc.flush_buffer(tty); + + shutdown(info); + + tty->closing = 0; + info->tty = 0; + + if (info->blocked_open) { + if (info->close_delay) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(info->close_delay); + } + wake_up_interruptible(&info->open_wait); + } + + info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE| + ASYNC_CLOSING); + + wake_up_interruptible(&info->close_wait); + +cleanup: + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgslpc_close(%s) exit, count=%d\n", __FILE__,__LINE__, + tty->driver.name, info->count); + if(MOD_IN_USE) + MOD_DEC_USE_COUNT; +} + +/* Wait until the transmitter is empty. + */ +static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout) +{ + MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data; + unsigned long orig_jiffies, char_time; + + if (!info ) + return; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgslpc_wait_until_sent(%s) entry\n", + __FILE__,__LINE__, info->device_name ); + + if (mgslpc_paranoia_check(info, tty->device, "mgslpc_wait_until_sent")) + return; + + if (!(info->flags & ASYNC_INITIALIZED)) + goto exit; + + orig_jiffies = jiffies; + + /* Set check interval to 1/5 of estimated time to + * send a character, and make it at least 1. The check + * interval should also be less than the timeout. + * Note: use tight timings here to satisfy the NIST-PCTS. + */ + + if ( info->params.data_rate ) { + char_time = info->timeout/(32 * 5); + if (!char_time) + char_time++; + } else + char_time = 1; + + if (timeout) + char_time = MIN(char_time, timeout); + + if (info->params.mode == MGSL_MODE_HDLC) { + while (info->tx_active) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(char_time); + if (signal_pending(current)) + break; + if (timeout && ((orig_jiffies + timeout) < jiffies)) + break; + } + } else { + while ((info->tx_count || info->tx_active) && + info->tx_enabled) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(char_time); + if (signal_pending(current)) + break; + if (timeout && ((orig_jiffies + timeout) < jiffies)) + break; + } + } + +exit: + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgslpc_wait_until_sent(%s) exit\n", + __FILE__,__LINE__, info->device_name ); +} + +/* Called by tty_hangup() when a hangup is signaled. + * This is the same as closing all open files for the port. + */ +static void mgslpc_hangup(struct tty_struct *tty) +{ + MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgslpc_hangup(%s)\n", + __FILE__,__LINE__, info->device_name ); + + if (mgslpc_paranoia_check(info, tty->device, "mgslpc_hangup")) + return; + + mgslpc_flush_buffer(tty); + shutdown(info); + + info->count = 0; + info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE); + info->tty = 0; + + wake_up_interruptible(&info->open_wait); +} + +/* Block the current process until the specified port + * is ready to be opened. + */ +static int block_til_ready(struct tty_struct *tty, struct file *filp, + MGSLPC_INFO *info) +{ + DECLARE_WAITQUEUE(wait, current); + int retval; + int do_clocal = 0, extra_count = 0; + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):block_til_ready on %s\n", + __FILE__,__LINE__, tty->driver.name ); + + if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) { + /* this is a callout device */ + /* just verify that normal device is not in use */ + if (info->flags & ASYNC_NORMAL_ACTIVE) + return -EBUSY; + if ((info->flags & ASYNC_CALLOUT_ACTIVE) && + (info->flags & ASYNC_SESSION_LOCKOUT) && + (info->session != current->session)) + return -EBUSY; + if ((info->flags & ASYNC_CALLOUT_ACTIVE) && + (info->flags & ASYNC_PGRP_LOCKOUT) && + (info->pgrp != current->pgrp)) + return -EBUSY; + info->flags |= ASYNC_CALLOUT_ACTIVE; + return 0; + } + + if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ + /* nonblock mode is set or port is not enabled */ + /* just verify that callout device is not active */ + if (info->flags & ASYNC_CALLOUT_ACTIVE) + return -EBUSY; + info->flags |= ASYNC_NORMAL_ACTIVE; + return 0; + } + + if (info->flags & ASYNC_CALLOUT_ACTIVE) { + if (info->normal_termios.c_cflag & CLOCAL) + do_clocal = 1; + } else { + if (tty->termios->c_cflag & CLOCAL) + do_clocal = 1; + } + + /* Wait for carrier detect and the line to become + * free (i.e., not in use by the callout). While we are in + * this loop, info->count is dropped by one, so that + * mgslpc_close() knows when to free things. We restore it upon + * exit, either normal or abnormal. + */ + + retval = 0; + add_wait_queue(&info->open_wait, &wait); + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):block_til_ready before block on %s count=%d\n", + __FILE__,__LINE__, tty->driver.name, info->count ); + + save_flags(flags); cli(); + if (!tty_hung_up_p(filp)) { + extra_count = 1; + info->count--; + } + restore_flags(flags); + info->blocked_open++; + + while (1) { + if (!(info->flags & ASYNC_CALLOUT_ACTIVE) && + (tty->termios->c_cflag & CBAUD)) { + spin_lock_irqsave(&info->lock,flags); + info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; + set_signals(info); + spin_unlock_irqrestore(&info->lock,flags); + } + + set_current_state(TASK_INTERRUPTIBLE); + + if (tty_hung_up_p(filp) || !(info->flags & ASYNC_INITIALIZED)){ + retval = (info->flags & ASYNC_HUP_NOTIFY) ? + -EAGAIN : -ERESTARTSYS; + break; + } + + spin_lock_irqsave(&info->lock,flags); + get_signals(info); + spin_unlock_irqrestore(&info->lock,flags); + + if (!(info->flags & ASYNC_CALLOUT_ACTIVE) && + !(info->flags & ASYNC_CLOSING) && + (do_clocal || (info->serial_signals & SerialSignal_DCD)) ) { + break; + } + + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):block_til_ready blocking on %s count=%d\n", + __FILE__,__LINE__, tty->driver.name, info->count ); + + schedule(); + } + + set_current_state(TASK_RUNNING); + remove_wait_queue(&info->open_wait, &wait); + + if (extra_count) + info->count++; + info->blocked_open--; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):block_til_ready after blocking on %s count=%d\n", + __FILE__,__LINE__, tty->driver.name, info->count ); + + if (!retval) + info->flags |= ASYNC_NORMAL_ACTIVE; + + return retval; +} + +static int mgslpc_open(struct tty_struct *tty, struct file * filp) +{ + MGSLPC_INFO *info; + int retval, line; + unsigned long flags; + + /* verify range of specified line number */ + line = MINOR(tty->device) - tty->driver.minor_start; + if ((line < 0) || (line >= mgslpc_device_count)) { + printk("%s(%d):mgslpc_open with illegal line #%d.\n", + __FILE__,__LINE__,line); + return -ENODEV; + } + + /* find the info structure for the specified line */ + info = mgslpc_device_list; + while(info && info->line != line) + info = info->next_device; + if ( !info ){ + printk("%s(%d):Can't find specified device on open (line=%d)\n", + __FILE__,__LINE__,line); + return -ENODEV; + } + + tty->driver_data = info; + info->tty = tty; + if (mgslpc_paranoia_check(info, tty->device, "mgslpc_open")) + return -ENODEV; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgslpc_open(%s), old ref count = %d\n", + __FILE__,__LINE__,tty->driver.name, info->count); + + MOD_INC_USE_COUNT; + + /* If port is closing, signal caller to try again */ + if (tty_hung_up_p(filp) || info->flags & ASYNC_CLOSING){ + if (info->flags & ASYNC_CLOSING) + interruptible_sleep_on(&info->close_wait); + retval = ((info->flags & ASYNC_HUP_NOTIFY) ? + -EAGAIN : -ERESTARTSYS); + goto cleanup; + } + + info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + + spin_lock_irqsave(&info->netlock, flags); + if (info->netcount) { + retval = -EBUSY; + spin_unlock_irqrestore(&info->netlock, flags); + goto cleanup; + } + info->count++; + spin_unlock_irqrestore(&info->netlock, flags); + + if (info->count == 1) { + /* 1st open on this device, init hardware */ + retval = startup(info); + if (retval < 0) + goto cleanup; + } + + retval = block_til_ready(tty, filp, info); + if (retval) { + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):block_til_ready(%s) returned %d\n", + __FILE__,__LINE__, info->device_name, retval); + goto cleanup; + } + + if ((info->count == 1) && + info->flags & ASYNC_SPLIT_TERMIOS) { + if (tty->driver.subtype == SERIAL_TYPE_NORMAL) + *tty->termios = info->normal_termios; + else + *tty->termios = info->callout_termios; + mgslpc_change_params(info); + } + + info->session = current->session; + info->pgrp = current->pgrp; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgslpc_open(%s) success\n", + __FILE__,__LINE__, info->device_name); + retval = 0; + +cleanup: + if (retval) { + if(MOD_IN_USE) + MOD_DEC_USE_COUNT; + if(info->count) + info->count--; + } + + return retval; +} + +/* + * /proc fs routines.... + */ + +static inline int line_info(char *buf, MGSLPC_INFO *info) +{ + char stat_buf[30]; + int ret; + unsigned long flags; + + ret = sprintf(buf, "%s:io:%04X irq:%d", + info->device_name, info->io_base, info->irq_level); + + /* output current serial signal states */ + spin_lock_irqsave(&info->lock,flags); + get_signals(info); + spin_unlock_irqrestore(&info->lock,flags); + + stat_buf[0] = 0; + stat_buf[1] = 0; + if (info->serial_signals & SerialSignal_RTS) + strcat(stat_buf, "|RTS"); + if (info->serial_signals & SerialSignal_CTS) + strcat(stat_buf, "|CTS"); + if (info->serial_signals & SerialSignal_DTR) + strcat(stat_buf, "|DTR"); + if (info->serial_signals & SerialSignal_DSR) + strcat(stat_buf, "|DSR"); + if (info->serial_signals & SerialSignal_DCD) + strcat(stat_buf, "|CD"); + if (info->serial_signals & SerialSignal_RI) + strcat(stat_buf, "|RI"); + + if (info->params.mode == MGSL_MODE_HDLC) { + ret += sprintf(buf+ret, " HDLC txok:%d rxok:%d", + info->icount.txok, info->icount.rxok); + if (info->icount.txunder) + ret += sprintf(buf+ret, " txunder:%d", info->icount.txunder); + if (info->icount.txabort) + ret += sprintf(buf+ret, " txabort:%d", info->icount.txabort); + if (info->icount.rxshort) + ret += sprintf(buf+ret, " rxshort:%d", info->icount.rxshort); + if (info->icount.rxlong) + ret += sprintf(buf+ret, " rxlong:%d", info->icount.rxlong); + if (info->icount.rxover) + ret += sprintf(buf+ret, " rxover:%d", info->icount.rxover); + if (info->icount.rxcrc) + ret += sprintf(buf+ret, " rxlong:%d", info->icount.rxcrc); + } else { + ret += sprintf(buf+ret, " ASYNC tx:%d rx:%d", + info->icount.tx, info->icount.rx); + if (info->icount.frame) + ret += sprintf(buf+ret, " fe:%d", info->icount.frame); + if (info->icount.parity) + ret += sprintf(buf+ret, " pe:%d", info->icount.parity); + if (info->icount.brk) + ret += sprintf(buf+ret, " brk:%d", info->icount.brk); + if (info->icount.overrun) + ret += sprintf(buf+ret, " oe:%d", info->icount.overrun); + } + + /* Append serial signal status to end */ + ret += sprintf(buf+ret, " %s\n", stat_buf+1); + + ret += sprintf(buf+ret, "txactive=%d bh_req=%d bh_run=%d pending_bh=%x\n", + info->tx_active,info->bh_requested,info->bh_running, + info->pending_bh); + + return ret; +} + +/* Called to print information about devices + */ +int mgslpc_read_proc(char *page, char **start, off_t off, int count, + int *eof, void *data) +{ + int len = 0, l; + off_t begin = 0; + MGSLPC_INFO *info; + + len += sprintf(page, "synclink driver:%s\n", driver_version); + + info = mgslpc_device_list; + while( info ) { + l = line_info(page + len, info); + len += l; + if (len+begin > off+count) + goto done; + if (len+begin < off) { + begin += len; + len = 0; + } + info = info->next_device; + } + + *eof = 1; +done: + if (off >= len+begin) + return 0; + *start = page + (off-begin); + return ((count < begin+len-off) ? count : begin+len-off); +} + +int rx_alloc_buffers(MGSLPC_INFO *info) +{ + /* each buffer has header and data */ + info->rx_buf_size = sizeof(RXBUF) + info->max_frame_size; + + /* calculate total allocation size for 8 buffers */ + info->rx_buf_total_size = info->rx_buf_size * 8; + + /* limit total allocated memory */ + if (info->rx_buf_total_size > 0x10000) + info->rx_buf_total_size = 0x10000; + + /* calculate number of buffers */ + info->rx_buf_count = info->rx_buf_total_size / info->rx_buf_size; + + info->rx_buf = kmalloc(info->rx_buf_total_size, GFP_KERNEL); + if (info->rx_buf == NULL) + return -ENOMEM; + + rx_reset_buffers(info); + return 0; +} + +void rx_free_buffers(MGSLPC_INFO *info) +{ + if (info->rx_buf) + kfree(info->rx_buf); + info->rx_buf = NULL; +} + +int claim_resources(MGSLPC_INFO *info) +{ + if (rx_alloc_buffers(info) < 0 ) { + printk( "Cant allocate rx buffer %s\n", info->device_name); + release_resources(info); + return -ENODEV; + } + return 0; +} + +void release_resources(MGSLPC_INFO *info) +{ + if (debug_level >= DEBUG_LEVEL_INFO) + printk("release_resources(%s)\n", info->device_name); + rx_free_buffers(info); +} + +/* Add the specified device instance data structure to the + * global linked list of devices and increment the device count. + * + * Arguments: info pointer to device instance data + */ +void mgslpc_add_device(MGSLPC_INFO *info) +{ + info->next_device = NULL; + info->line = mgslpc_device_count; + sprintf(info->device_name,"ttySLP%d",info->line); + + if (info->line < MAX_DEVICE_COUNT) { + if (maxframe[info->line]) + info->max_frame_size = maxframe[info->line]; +// info->dosyncppp = dosyncppp[info->line]; + info->dosyncppp = 1; + } + + mgslpc_device_count++; + + if (!mgslpc_device_list) + mgslpc_device_list = info; + else { + MGSLPC_INFO *current_dev = mgslpc_device_list; + while( current_dev->next_device ) + current_dev = current_dev->next_device; + current_dev->next_device = info; + } + + if (info->max_frame_size < 4096) + info->max_frame_size = 4096; + else if (info->max_frame_size > 65535) + info->max_frame_size = 65535; + + printk( "SyncLink PC Card %s:IO=%04X IRQ=%d\n", + info->device_name, info->io_base, info->irq_level); + + +#ifdef CONFIG_SYNCLINK_SYNCPPP +#ifdef MODULE + if (info->dosyncppp) +#endif + mgslpc_sppp_init(info); +#endif +} + +void mgslpc_remove_device(MGSLPC_INFO *remove_info) +{ + MGSLPC_INFO *info = mgslpc_device_list; + MGSLPC_INFO *last = NULL; + + while(info) { + if (info == remove_info) { + if (last) + last->next_device = info->next_device; + else + mgslpc_device_list = info->next_device; +#ifdef CONFIG_SYNCLINK_SYNCPPP + if (info->dosyncppp) + mgslpc_sppp_delete(info); +#endif + release_resources(info); + kfree(info); + mgslpc_device_count--; + return; + } + last = info; + info = info->next_device; + } +} + +static int __init synclink_cs_init(void) +{ + servinfo_t serv; + + EXPORT_NO_SYMBOLS; + + if (break_on_load) { + mgslpc_get_text_ptr(); + BREAKPOINT(); + } + + printk("%s %s\n", driver_name, driver_version); + + CardServices(GetCardServicesInfo, &serv); + if (serv.Revision != CS_RELEASE_CODE) { + printk(KERN_NOTICE "synclink_cs: Card Services release " + "does not match!\n"); + return -1; + } + register_pccard_driver(&dev_info, &mgslpc_attach, &mgslpc_detach); + + /* Initialize the tty_driver structure */ + + memset(&serial_driver, 0, sizeof(struct tty_driver)); + serial_driver.magic = TTY_DRIVER_MAGIC; + serial_driver.driver_name = "synclink_cs"; + serial_driver.name = "ttySLP"; + serial_driver.major = ttymajor; + serial_driver.minor_start = 64; + serial_driver.num = MAX_DEVICE_COUNT; + serial_driver.type = TTY_DRIVER_TYPE_SERIAL; + serial_driver.subtype = SERIAL_TYPE_NORMAL; + serial_driver.init_termios = tty_std_termios; + serial_driver.init_termios.c_cflag = + B9600 | CS8 | CREAD | HUPCL | CLOCAL; + serial_driver.flags = TTY_DRIVER_REAL_RAW; + serial_driver.refcount = &serial_refcount; + serial_driver.table = serial_table; + serial_driver.termios = serial_termios; + serial_driver.termios_locked = serial_termios_locked; + + serial_driver.open = mgslpc_open; + serial_driver.close = mgslpc_close; + serial_driver.write = mgslpc_write; + serial_driver.put_char = mgslpc_put_char; + serial_driver.flush_chars = mgslpc_flush_chars; + serial_driver.write_room = mgslpc_write_room; + serial_driver.chars_in_buffer = mgslpc_chars_in_buffer; + serial_driver.flush_buffer = mgslpc_flush_buffer; + serial_driver.ioctl = mgslpc_ioctl; + serial_driver.throttle = mgslpc_throttle; + serial_driver.unthrottle = mgslpc_unthrottle; + serial_driver.send_xchar = mgslpc_send_xchar; + serial_driver.break_ctl = mgslpc_break; + serial_driver.wait_until_sent = mgslpc_wait_until_sent; + serial_driver.read_proc = mgslpc_read_proc; + serial_driver.set_termios = mgslpc_set_termios; + serial_driver.stop = tx_pause; + serial_driver.start = tx_release; + serial_driver.hangup = mgslpc_hangup; + + /* + * The callout device is just like normal device except for + * major number and the subtype code. + */ + callout_driver = serial_driver; + callout_driver.name = "cuaSLP"; + callout_driver.major = cuamajor; + callout_driver.subtype = SERIAL_TYPE_CALLOUT; + callout_driver.read_proc = 0; + callout_driver.proc_entry = 0; + + if (tty_register_driver(&serial_driver) < 0) + printk("%s(%d):Couldn't register serial driver\n", + __FILE__,__LINE__); + + if (tty_register_driver(&callout_driver) < 0) + printk("%s(%d):Couldn't register callout driver\n", + __FILE__,__LINE__); + + printk("%s %s, tty major#%d callout major#%d\n", + driver_name, driver_version, + serial_driver.major, callout_driver.major); + + return 0; +} + +static void __exit synclink_cs_exit(void) +{ + unsigned long flags; + int rc; + + printk("Unloading %s: version %s\n", driver_name, driver_version); + + while(mgslpc_device_list) + mgslpc_remove_device(mgslpc_device_list); + + save_flags(flags); + cli(); + if ((rc = tty_unregister_driver(&serial_driver))) + printk("%s(%d) failed to unregister tty driver err=%d\n", + __FILE__,__LINE__,rc); + if ((rc = tty_unregister_driver(&callout_driver))) + printk("%s(%d) failed to unregister callout driver err=%d\n", + __FILE__,__LINE__,rc); + restore_flags(flags); + + unregister_pccard_driver(&dev_info); + while (dev_list != NULL) { + del_timer(&dev_list->release); + if (dev_list->state & DEV_CONFIG) + mgslpc_release((u_long)dev_list); + mgslpc_detach(dev_list); + } +} + +module_init(synclink_cs_init); +module_exit(synclink_cs_exit); + +void mgslpc_set_rate(MGSLPC_INFO *info, unsigned char channel, unsigned int rate) +{ + unsigned int M, N; + unsigned char val; + + /* note:standard BRG mode is broken in V3.2 chip + * so enhanced mode is always used + */ + + if (rate) { + N = 3686400 / rate; + if (!N) + N = 1; + N >>= 1; + for (M = 1; N > 64 && M < 16; M++) + N >>= 1; + N--; + + /* BGR[5..0] = N + * BGR[9..6] = M + * BGR[7..0] contained in BGR register + * BGR[9..8] contained in CCR2[7..6] + * divisor = (N+1)*2^M + * + * Note: M *must* not be zero (causes asymetric duty cycle) + */ + write_reg(info, (unsigned char) (channel + BGR), + (unsigned char) ((M << 6) + N)); + val = read_reg(info, (unsigned char) (channel + CCR2)) & 0x3f; + val |= ((M << 4) & 0xc0); + write_reg(info, (unsigned char) (channel + CCR2), val); + } +} + +/* Enabled the AUX clock output at the specified frequency. + */ +void enable_auxclk(MGSLPC_INFO *info) +{ + unsigned char val; + + /* MODE + * + * 07..06 MDS[1..0] 10 = transparent HDLC mode + * 05 ADM Address Mode, 0 = no addr recognition + * 04 TMD Timer Mode, 0 = external + * 03 RAC Receiver Active, 0 = inactive + * 02 RTS 0=RTS active during xmit, 1=RTS always active + * 01 TRS Timer Resolution, 1=512 + * 00 TLP Test Loop, 0 = no loop + * + * 1000 0010 + */ + val = 0x82; + + /* channel B RTS is used to enable AUXCLK driver on SP505 */ + if (info->params.mode == MGSL_MODE_HDLC && info->params.clock_speed) + val |= BIT2; + write_reg(info, CHB + MODE, val); + + /* CCR0 + * + * 07 PU Power Up, 1=active, 0=power down + * 06 MCE Master Clock Enable, 1=enabled + * 05 Reserved, 0 + * 04..02 SC[2..0] Encoding + * 01..00 SM[1..0] Serial Mode, 00=HDLC + * + * 11000000 + */ + write_reg(info, CHB + CCR0, 0xc0); + + /* CCR1 + * + * 07 SFLG Shared Flag, 0 = disable shared flags + * 06 GALP Go Active On Loop, 0 = not used + * 05 GLP Go On Loop, 0 = not used + * 04 ODS Output Driver Select, 1=TxD is push-pull output + * 03 ITF Interframe Time Fill, 0=mark, 1=flag + * 02..00 CM[2..0] Clock Mode + * + * 0001 0111 + */ + write_reg(info, CHB + CCR1, 0x17); + + /* CCR2 (Channel B) + * + * 07..06 BGR[9..8] Baud rate bits 9..8 + * 05 BDF Baud rate divisor factor, 0=1, 1=BGR value + * 04 SSEL Clock source select, 1=submode b + * 03 TOE 0=TxCLK is input, 1=TxCLK is output + * 02 RWX Read/Write Exchange 0=disabled + * 01 C32, CRC select, 0=CRC-16, 1=CRC-32 + * 00 DIV, data inversion 0=disabled, 1=enabled + * + * 0011 1000 + */ + if (info->params.mode == MGSL_MODE_HDLC && info->params.clock_speed) + write_reg(info, CHB + CCR2, 0x38); + else + write_reg(info, CHB + CCR2, 0x30); + + /* CCR4 + * + * 07 MCK4 Master Clock Divide by 4, 1=enabled + * 06 EBRG Enhanced Baud Rate Generator Mode, 1=enabled + * 05 TST1 Test Pin, 0=normal operation + * 04 ICD Ivert Carrier Detect, 1=enabled (active low) + * 03..02 Reserved, must be 0 + * 01..00 RFT[1..0] RxFIFO Threshold 00=32 bytes + * + * 0101 0000 + */ + write_reg(info, CHB + CCR4, 0x50); + + /* if auxclk not enabled, set internal BRG so + * CTS transitions can be detected (requires TxC) + */ + if (info->params.mode == MGSL_MODE_HDLC && info->params.clock_speed) + mgslpc_set_rate(info, CHB, info->params.clock_speed); + else + mgslpc_set_rate(info, CHB, 921600); +} + +static void loopback_enable(MGSLPC_INFO *info) +{ + unsigned char val; + + /* CCR1:02..00 CM[2..0] Clock Mode = 111 (clock mode 7) */ + val = read_reg(info, CHA + CCR1) | (BIT2 + BIT1 + BIT0); + write_reg(info, CHA + CCR1, val); + + /* CCR2:04 SSEL Clock source select, 1=submode b */ + val = read_reg(info, CHA + CCR2) | (BIT4 + BIT5); + write_reg(info, CHA + CCR2, val); + + /* set LinkSpeed if available, otherwise default to 2Mbps */ + if (info->params.clock_speed) + mgslpc_set_rate(info, CHA, info->params.clock_speed); + else + mgslpc_set_rate(info, CHA, 1843200); + + /* MODE:00 TLP Test Loop, 1=loopback enabled */ + val = read_reg(info, CHA + MODE) | BIT0; + write_reg(info, CHA + MODE, val); +} + +void hdlc_mode(MGSLPC_INFO *info) +{ + unsigned char val; + unsigned char clkmode, clksubmode; + + /* disable all interrupts */ + irq_disable(info, CHA, 0xffff); + irq_disable(info, CHB, 0xffff); + port_irq_disable(info, 0xff); + + /* assume clock mode 0a, rcv=RxC xmt=TxC */ + clkmode = clksubmode = 0; + if (info->params.flags & HDLC_FLAG_RXC_DPLL + && info->params.flags & HDLC_FLAG_TXC_DPLL) { + /* clock mode 7a, rcv = DPLL, xmt = DPLL */ + clkmode = 7; + } else if (info->params.flags & HDLC_FLAG_RXC_BRG + && info->params.flags & HDLC_FLAG_TXC_BRG) { + /* clock mode 7b, rcv = BRG, xmt = BRG */ + clkmode = 7; + clksubmode = 1; + } else if (info->params.flags & HDLC_FLAG_RXC_DPLL) { + if (info->params.flags & HDLC_FLAG_TXC_BRG) { + /* clock mode 6b, rcv = DPLL, xmt = BRG/16 */ + clkmode = 6; + clksubmode = 1; + } else { + /* clock mode 6a, rcv = DPLL, xmt = TxC */ + clkmode = 6; + } + } else if (info->params.flags & HDLC_FLAG_TXC_BRG) { + /* clock mode 0b, rcv = RxC, xmt = BRG */ + clksubmode = 1; + } + + /* MODE + * + * 07..06 MDS[1..0] 10 = transparent HDLC mode + * 05 ADM Address Mode, 0 = no addr recognition + * 04 TMD Timer Mode, 0 = external + * 03 RAC Receiver Active, 0 = inactive + * 02 RTS 0=RTS active during xmit, 1=RTS always active + * 01 TRS Timer Resolution, 1=512 + * 00 TLP Test Loop, 0 = no loop + * + * 1000 0010 + */ + val = 0x82; + if (info->params.loopback) + val |= BIT0; + + /* preserve RTS state */ + if (info->serial_signals & SerialSignal_RTS) + val |= BIT2; + write_reg(info, CHA + MODE, val); + + /* CCR0 + * + * 07 PU Power Up, 1=active, 0=power down + * 06 MCE Master Clock Enable, 1=enabled + * 05 Reserved, 0 + * 04..02 SC[2..0] Encoding + * 01..00 SM[1..0] Serial Mode, 00=HDLC + * + * 11000000 + */ + val = 0xc0; + switch (info->params.encoding) + { + case HDLC_ENCODING_NRZI: + val |= BIT3; + break; + case HDLC_ENCODING_BIPHASE_SPACE: + val |= BIT4; + break; // FM0 + case HDLC_ENCODING_BIPHASE_MARK: + val |= BIT4 + BIT2; + break; // FM1 + case HDLC_ENCODING_BIPHASE_LEVEL: + val |= BIT4 + BIT3; + break; // Manchester + } + write_reg(info, CHA + CCR0, val); + + /* CCR1 + * + * 07 SFLG Shared Flag, 0 = disable shared flags + * 06 GALP Go Active On Loop, 0 = not used + * 05 GLP Go On Loop, 0 = not used + * 04 ODS Output Driver Select, 1=TxD is push-pull output + * 03 ITF Interframe Time Fill, 0=mark, 1=flag + * 02..00 CM[2..0] Clock Mode + * + * 0001 0000 + */ + val = 0x10 + clkmode; + write_reg(info, CHA + CCR1, val); + + /* CCR2 + * + * 07..06 BGR[9..8] Baud rate bits 9..8 + * 05 BDF Baud rate divisor factor, 0=1, 1=BGR value + * 04 SSEL Clock source select, 1=submode b + * 03 TOE 0=TxCLK is input, 0=TxCLK is input + * 02 RWX Read/Write Exchange 0=disabled + * 01 C32, CRC select, 0=CRC-16, 1=CRC-32 + * 00 DIV, data inversion 0=disabled, 1=enabled + * + * 0000 0000 + */ + val = 0x00; + if (clkmode == 2 || clkmode == 3 || clkmode == 6 + || clkmode == 7 || (clkmode == 0 && clksubmode == 1)) + val |= BIT5; + if (clksubmode) + val |= BIT4; + if (info->params.crc_type == HDLC_CRC_32_CCITT) + val |= BIT1; + if (info->params.encoding == HDLC_ENCODING_NRZB) + val |= BIT0; + write_reg(info, CHA + CCR2, val); + + /* CCR3 + * + * 07..06 PRE[1..0] Preamble count 00=1, 01=2, 10=4, 11=8 + * 05 EPT Enable preamble transmission, 1=enabled + * 04 RADD Receive address pushed to FIFO, 0=disabled + * 03 CRL CRC Reset Level, 0=FFFF + * 02 RCRC Rx CRC 0=On 1=Off + * 01 TCRC Tx CRC 0=On 1=Off + * 00 PSD DPLL Phase Shift Disable + * + * 0000 0000 + */ + val = 0x00; + if (info->params.crc_type == HDLC_CRC_NONE) + val |= BIT2 + BIT1; + if (info->params.preamble != HDLC_PREAMBLE_PATTERN_NONE) + val |= BIT5; + switch (info->params.preamble_length) + { + case HDLC_PREAMBLE_LENGTH_16BITS: + val |= BIT6; + break; + case HDLC_PREAMBLE_LENGTH_32BITS: + val |= BIT6; + break; + case HDLC_PREAMBLE_LENGTH_64BITS: + val |= BIT7 + BIT6; + break; + } + write_reg(info, CHA + CCR3, val); + + /* PRE - Preamble pattern */ + val = 0; + switch (info->params.preamble) + { + case HDLC_PREAMBLE_PATTERN_FLAGS: val = 0x7e; break; + case HDLC_PREAMBLE_PATTERN_10: val = 0xaa; break; + case HDLC_PREAMBLE_PATTERN_01: val = 0x55; break; + case HDLC_PREAMBLE_PATTERN_ONES: val = 0xff; break; + } + write_reg(info, CHA + PRE, val); + + /* CCR4 + * + * 07 MCK4 Master Clock Divide by 4, 1=enabled + * 06 EBRG Enhanced Baud Rate Generator Mode, 1=enabled + * 05 TST1 Test Pin, 0=normal operation + * 04 ICD Ivert Carrier Detect, 1=enabled (active low) + * 03..02 Reserved, must be 0 + * 01..00 RFT[1..0] RxFIFO Threshold 00=32 bytes + * + * 0101 0000 + */ + val = 0x50; + write_reg(info, CHA + CCR4, val); + if (info->params.flags & HDLC_FLAG_RXC_DPLL) + mgslpc_set_rate(info, CHA, info->params.clock_speed * 16); + else + mgslpc_set_rate(info, CHA, info->params.clock_speed); + + /* RLCR Receive length check register + * + * 7 1=enable receive length check + * 6..0 Max frame length = (RL + 1) * 32 + */ + write_reg(info, CHA + RLCR, 0); + + /* XBCH Transmit Byte Count High + * + * 07 DMA mode, 0 = interrupt driven + * 06 NRM, 0=ABM (ignored) + * 05 CAS Carrier Auto Start + * 04 XC Transmit Continuously (ignored) + * 03..00 XBC[10..8] Transmit byte count bits 10..8 + * + * 0000 0000 + */ + val = 0x00; + if (info->params.flags & HDLC_FLAG_AUTO_DCD) + val |= BIT5; + write_reg(info, CHA + XBCH, val); + enable_auxclk(info); + if (info->params.loopback || info->testing_irq) + loopback_enable(info); + if (info->params.flags & HDLC_FLAG_AUTO_CTS) + { + irq_enable(info, CHB, IRQ_CTS); + /* PVR[3] 1=AUTO CTS active */ + set_reg_bits(info, CHA + PVR, BIT3); + } else + clear_reg_bits(info, CHA + PVR, BIT3); + + irq_enable(info, CHA, + IRQ_RXEOM + IRQ_RXFIFO + IRQ_ALLSENT + + IRQ_UNDERRUN + IRQ_TXFIFO); + issue_command(info, CHA, CMD_TXRESET + CMD_RXRESET); + wait_command_complete(info, CHA); + read_reg16(info, CHA + ISR); /* clear pending IRQs */ + + /* Master clock mode enabled above to allow reset commands + * to complete even if no data clocks are present. + * + * Disable master clock mode for normal communications because + * V3.2 of the ESCC2 has a bug that prevents the transmit all sent + * IRQ when in master clock mode. + * + * Leave master clock mode enabled for IRQ test because the + * timer IRQ used by the test can only happen in master clock mode. + */ + if (!info->testing_irq) + clear_reg_bits(info, CHA + CCR0, BIT6); + + tx_set_idle(info); + + tx_stop(info); + rx_stop(info); +} + +void rx_stop(MGSLPC_INFO *info) +{ + if (debug_level >= DEBUG_LEVEL_ISR) + printk("%s(%d):rx_stop(%s)\n", + __FILE__,__LINE__, info->device_name ); + + /* MODE:03 RAC Receiver Active, 0=inactive */ + clear_reg_bits(info, CHA + MODE, BIT3); + + info->rx_enabled = 0; + info->rx_overflow = 0; +} + +void rx_start(MGSLPC_INFO *info) +{ + if (debug_level >= DEBUG_LEVEL_ISR) + printk("%s(%d):rx_start(%s)\n", + __FILE__,__LINE__, info->device_name ); + + rx_reset_buffers(info); + info->rx_enabled = 0; + info->rx_overflow = 0; + + /* MODE:03 RAC Receiver Active, 1=active */ + set_reg_bits(info, CHA + MODE, BIT3); + + info->rx_enabled = 1; +} + +void tx_start(MGSLPC_INFO *info) +{ + if (debug_level >= DEBUG_LEVEL_ISR) + printk("%s(%d):tx_start(%s)\n", + __FILE__,__LINE__, info->device_name ); + + if (info->tx_count) { + /* If auto RTS enabled and RTS is inactive, then assert */ + /* RTS and set a flag indicating that the driver should */ + /* negate RTS when the transmission completes. */ + info->drop_rts_on_tx_done = 0; + + if (info->params.flags & HDLC_FLAG_AUTO_RTS) { + get_signals(info); + if (!(info->serial_signals & SerialSignal_RTS)) { + info->serial_signals |= SerialSignal_RTS; + set_signals(info); + info->drop_rts_on_tx_done = 1; + } + } + + if (info->params.mode == MGSL_MODE_ASYNC) { + if (!info->tx_active) { + info->tx_active = 1; + tx_ready(info); + } + } else { + info->tx_active = 1; + tx_ready(info); + info->tx_timer.expires = jiffies + jiffies_from_ms(5000); + add_timer(&info->tx_timer); + } + } + + if (!info->tx_enabled) + info->tx_enabled = 1; +} + +void tx_stop(MGSLPC_INFO *info) +{ + if (debug_level >= DEBUG_LEVEL_ISR) + printk("%s(%d):tx_stop(%s)\n", + __FILE__,__LINE__, info->device_name ); + + del_timer(&info->tx_timer); + + info->tx_enabled = 0; + info->tx_active = 0; +} + +/* Reset the adapter to a known state and prepare it for further use. + */ +void reset_device(MGSLPC_INFO *info) +{ + /* power up both channels (set BIT7) */ + write_reg(info, CHA + CCR0, 0x80); + write_reg(info, CHB + CCR0, 0x80); + write_reg(info, CHA + MODE, 0); + write_reg(info, CHB + MODE, 0); + + /* disable all interrupts */ + irq_disable(info, CHA, 0xffff); + irq_disable(info, CHB, 0xffff); + port_irq_disable(info, 0xff); + + /* PCR Port Configuration Register + * + * 07..04 DEC[3..0] Serial I/F select outputs + * 03 output, 1=AUTO CTS control enabled + * 02 RI Ring Indicator input 0=active + * 01 DSR input 0=active + * 00 DTR output 0=active + * + * 0000 0110 + */ + write_reg(info, PCR, 0x06); + + /* PVR Port Value Register + * + * 07..04 DEC[3..0] Serial I/F select (0000=disabled) + * 03 AUTO CTS output 1=enabled + * 02 RI Ring Indicator input + * 01 DSR input + * 00 DTR output (1=inactive) + * + * 0000 0001 + */ +// write_reg(info, PVR, PVR_DTR); + + /* IPC Interrupt Port Configuration + * + * 07 VIS 1=Masked interrupts visible + * 06..05 Reserved, 0 + * 04..03 SLA Slave address, 00 ignored + * 02 CASM Cascading Mode, 1=daisy chain + * 01..00 IC[1..0] Interrupt Config, 01=push-pull output, active low + * + * 0000 0101 + */ + write_reg(info, IPC, 0x05); +} + +void async_mode(MGSLPC_INFO *info) +{ + unsigned char val; + + /* disable all interrupts */ + irq_disable(info, CHA, 0xffff); + irq_disable(info, CHB, 0xffff); + port_irq_disable(info, 0xff); + + /* MODE + * + * 07 Reserved, 0 + * 06 FRTS RTS State, 0=active + * 05 FCTS Flow Control on CTS + * 04 FLON Flow Control Enable + * 03 RAC Receiver Active, 0 = inactive + * 02 RTS 0=Auto RTS, 1=manual RTS + * 01 TRS Timer Resolution, 1=512 + * 00 TLP Test Loop, 0 = no loop + * + * 0000 0110 + */ + val = 0x06; + if (info->params.loopback) + val |= BIT0; + + /* preserve RTS state */ + if (!(info->serial_signals & SerialSignal_RTS)) + val |= BIT6; + write_reg(info, CHA + MODE, val); + + /* CCR0 + * + * 07 PU Power Up, 1=active, 0=power down + * 06 MCE Master Clock Enable, 1=enabled + * 05 Reserved, 0 + * 04..02 SC[2..0] Encoding, 000=NRZ + * 01..00 SM[1..0] Serial Mode, 11=Async + * + * 1000 0011 + */ + write_reg(info, CHA + CCR0, 0x83); + + /* CCR1 + * + * 07..05 Reserved, 0 + * 04 ODS Output Driver Select, 1=TxD is push-pull output + * 03 BCR Bit Clock Rate, 1=16x + * 02..00 CM[2..0] Clock Mode, 111=BRG + * + * 0001 1111 + */ + write_reg(info, CHA + CCR1, 0x1f); + + /* CCR2 (channel A) + * + * 07..06 BGR[9..8] Baud rate bits 9..8 + * 05 BDF Baud rate divisor factor, 0=1, 1=BGR value + * 04 SSEL Clock source select, 1=submode b + * 03 TOE 0=TxCLK is input, 0=TxCLK is input + * 02 RWX Read/Write Exchange 0=disabled + * 01 Reserved, 0 + * 00 DIV, data inversion 0=disabled, 1=enabled + * + * 0001 0000 + */ + write_reg(info, CHA + CCR2, 0x10); + + /* CCR3 + * + * 07..01 Reserved, 0 + * 00 PSD DPLL Phase Shift Disable + * + * 0000 0000 + */ + write_reg(info, CHA + CCR3, 0); + + /* CCR4 + * + * 07 MCK4 Master Clock Divide by 4, 1=enabled + * 06 EBRG Enhanced Baud Rate Generator Mode, 1=enabled + * 05 TST1 Test Pin, 0=normal operation + * 04 ICD Ivert Carrier Detect, 1=enabled (active low) + * 03..00 Reserved, must be 0 + * + * 0101 0000 + */ + write_reg(info, CHA + CCR4, 0x50); + mgslpc_set_rate(info, CHA, info->params.data_rate * 16); + + /* DAFO Data Format + * + * 07 Reserved, 0 + * 06 XBRK transmit break, 0=normal operation + * 05 Stop bits (0=1, 1=2) + * 04..03 PAR[1..0] Parity (01=odd, 10=even) + * 02 PAREN Parity Enable + * 01..00 CHL[1..0] Character Length (00=8, 01=7) + * + */ + val = 0x00; + if (info->params.data_bits != 8) + val |= BIT0; /* 7 bits */ + if (info->params.stop_bits != 1) + val |= BIT5; + if (info->params.parity != ASYNC_PARITY_NONE) + { + val |= BIT2; /* Parity enable */ + if (info->params.parity == ASYNC_PARITY_ODD) + val |= BIT3; + else + val |= BIT4; + } + write_reg(info, CHA + DAFO, val); + + /* RFC Rx FIFO Control + * + * 07 Reserved, 0 + * 06 DPS, 1=parity bit not stored in data byte + * 05 DXS, 0=all data stored in FIFO (including XON/XOFF) + * 04 RFDF Rx FIFO Data Format, 1=status byte stored in FIFO + * 03..02 RFTH[1..0], rx threshold, 11=16 status + 16 data byte + * 01 Reserved, 0 + * 00 TCDE Terminate Char Detect Enable, 0=disabled + * + * 0101 1100 + */ + write_reg(info, CHA + RFC, 0x5c); + + /* RLCR Receive length check register + * + * Max frame length = (RL + 1) * 32 + */ + write_reg(info, CHA + RLCR, 0); + + /* XBCH Transmit Byte Count High + * + * 07 DMA mode, 0 = interrupt driven + * 06 NRM, 0=ABM (ignored) + * 05 CAS Carrier Auto Start + * 04 XC Transmit Continuously (ignored) + * 03..00 XBC[10..8] Transmit byte count bits 10..8 + * + * 0000 0000 + */ + val = 0x00; + if (info->params.flags & HDLC_FLAG_AUTO_DCD) + val |= BIT5; + write_reg(info, CHA + XBCH, val); + if (info->params.flags & HDLC_FLAG_AUTO_CTS) + irq_enable(info, CHA, IRQ_CTS); + + /* MODE:03 RAC Receiver Active, 1=active */ + set_reg_bits(info, CHA + MODE, BIT3); + enable_auxclk(info); + if (info->params.flags & HDLC_FLAG_AUTO_CTS) { + irq_enable(info, CHB, IRQ_CTS); + /* PVR[3] 1=AUTO CTS active */ + set_reg_bits(info, CHA + PVR, BIT3); + } else + clear_reg_bits(info, CHA + PVR, BIT3); + irq_enable(info, CHA, + IRQ_RXEOM + IRQ_RXFIFO + IRQ_BREAK_ON + IRQ_RXTIME + + IRQ_ALLSENT + IRQ_TXFIFO); + issue_command(info, CHA, CMD_TXRESET + CMD_RXRESET); + wait_command_complete(info, CHA); + read_reg16(info, CHA + ISR); /* clear pending IRQs */ +} + +/* Set the HDLC idle mode for the transmitter. + */ +void tx_set_idle(MGSLPC_INFO *info) +{ + /* Note: ESCC2 only supports flags and one idle modes */ + if (info->idle_mode == HDLC_TXIDLE_FLAGS) + set_reg_bits(info, CHA + CCR1, BIT3); + else + clear_reg_bits(info, CHA + CCR1, BIT3); +} + +/* get state of the V24 status (input) signals. + */ +void get_signals(MGSLPC_INFO *info) +{ + unsigned char status = 0; + + /* preserve DTR and RTS */ + info->serial_signals &= SerialSignal_DTR + SerialSignal_RTS; + + if (read_reg(info, CHB + VSTR) & BIT7) + info->serial_signals |= SerialSignal_DCD; + if (read_reg(info, CHB + STAR) & BIT1) + info->serial_signals |= SerialSignal_CTS; + + status = read_reg(info, CHA + PVR); + if (!(status & PVR_RI)) + info->serial_signals |= SerialSignal_RI; + if (!(status & PVR_DSR)) + info->serial_signals |= SerialSignal_DSR; +} + +/* Set the state of DTR and RTS based on contents of + * serial_signals member of device extension. + */ +void set_signals(MGSLPC_INFO *info) +{ + unsigned char val; + + val = read_reg(info, CHA + MODE); + if (info->params.mode == MGSL_MODE_ASYNC) { + if (info->serial_signals & SerialSignal_RTS) + val &= ~BIT6; + else + val |= BIT6; + } else { + if (info->serial_signals & SerialSignal_RTS) + val |= BIT2; + else + val &= ~BIT2; + } + write_reg(info, CHA + MODE, val); + + if (info->serial_signals & SerialSignal_DTR) + clear_reg_bits(info, CHA + PVR, PVR_DTR); + else + set_reg_bits(info, CHA + PVR, PVR_DTR); +} + +void rx_reset_buffers(MGSLPC_INFO *info) +{ + RXBUF *buf; + int i; + + info->rx_put = 0; + info->rx_get = 0; + info->rx_frame_count = 0; + for (i=0 ; i < info->rx_buf_count ; i++) { + buf = (RXBUF*)(info->rx_buf + (i * info->rx_buf_size)); + buf->status = buf->count = 0; + } +} + +/* Attempt to return a received HDLC frame + * Only frames received without errors are returned. + * + * Returns 1 if frame returned, otherwise 0 + */ +int rx_get_frame(MGSLPC_INFO *info) +{ + unsigned short status; + RXBUF *buf; + unsigned int framesize = 0; + unsigned long flags; + struct tty_struct *tty = info->tty; + int return_frame = 0; + + if (info->rx_frame_count == 0) + return 0; + + buf = (RXBUF*)(info->rx_buf + (info->rx_get * info->rx_buf_size)); + + status = buf->status; + + /* 07 VFR 1=valid frame + * 06 RDO 1=data overrun + * 05 CRC 1=OK, 0=error + * 04 RAB 1=frame aborted + */ + if ((status & 0xf0) != 0xA0) { + if (!(status & BIT7) || (status & BIT4)) + info->icount.rxabort++; + else if (status & BIT6) + info->icount.rxover++; + else if (!(status & BIT5)) { + info->icount.rxcrc++; + if (info->params.crc_type & HDLC_CRC_RETURN_EX) + return_frame = 1; + } + framesize = 0; +#ifdef CONFIG_SYNCLINK_SYNCPPP + info->netstats.rx_errors++; + info->netstats.rx_frame_errors++; +#endif + } else + return_frame = 1; + + if (return_frame) + framesize = buf->count; + + if (debug_level >= DEBUG_LEVEL_BH) + printk("%s(%d):rx_get_frame(%s) status=%04X size=%d\n", + __FILE__,__LINE__,info->device_name,status,framesize); + + if (debug_level >= DEBUG_LEVEL_DATA) + trace_block(info, buf->data, framesize, 0); + + if (framesize) { + if ((info->params.crc_type & HDLC_CRC_RETURN_EX && + framesize+1 > info->max_frame_size) || + framesize > info->max_frame_size) + info->icount.rxlong++; + else { + if (status & BIT5) + info->icount.rxok++; + + if (info->params.crc_type & HDLC_CRC_RETURN_EX) { + *(buf->data + framesize) = status & BIT5 ? RX_OK:RX_CRC_ERROR; + ++framesize; + } + +#ifdef CONFIG_SYNCLINK_SYNCPPP + if (info->netcount) { + /* pass frame to syncppp device */ + mgslpc_sppp_rx_done(info, buf->data, framesize); + } + else +#endif + { + /* Call the line discipline receive callback directly. */ + if (tty && tty->ldisc.receive_buf) + tty->ldisc.receive_buf(tty, buf->data, info->flag_buf, framesize); + } + } + } + + spin_lock_irqsave(&info->lock,flags); + buf->status = buf->count = 0; + info->rx_frame_count--; + info->rx_get++; + if (info->rx_get >= info->rx_buf_count) + info->rx_get = 0; + spin_unlock_irqrestore(&info->lock,flags); + + return 1; +} + +BOOLEAN register_test(MGSLPC_INFO *info) +{ + static unsigned char patterns[] = + { 0x00, 0xff, 0xaa, 0x55, 0x69, 0x96, 0x0f }; + static unsigned int count = sizeof(patterns) / sizeof(patterns[0]); + unsigned int i; + BOOLEAN rc = TRUE; + unsigned long flags; + + spin_lock_irqsave(&info->lock,flags); + reset_device(info); + + for (i = 0; i < count; i++) { + write_reg(info, XAD1, patterns[i]); + write_reg(info, XAD2, patterns[(i + 1) % count]); + if ((read_reg(info, XAD1) != patterns[i]) || + (read_reg(info, XAD2) != patterns[(i + 1) % count])) { + rc = FALSE; + break; + } + } + + spin_unlock_irqrestore(&info->lock,flags); + return rc; +} + +BOOLEAN irq_test(MGSLPC_INFO *info) +{ + unsigned long end_time; + unsigned long flags; + + spin_lock_irqsave(&info->lock,flags); + reset_device(info); + + info->testing_irq = TRUE; + hdlc_mode(info); + + info->irq_occurred = FALSE; + + /* init hdlc mode */ + + irq_enable(info, CHA, IRQ_TIMER); + write_reg(info, CHA + TIMR, 0); /* 512 cycles */ + issue_command(info, CHA, CMD_START_TIMER); + + spin_unlock_irqrestore(&info->lock,flags); + + end_time=100; + while(end_time-- && !info->irq_occurred) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(jiffies_from_ms(10)); + } + + info->testing_irq = FALSE; + + spin_lock_irqsave(&info->lock,flags); + reset_device(info); + spin_unlock_irqrestore(&info->lock,flags); + + return info->irq_occurred ? TRUE : FALSE; +} + +int adapter_test(MGSLPC_INFO *info) +{ + if (!register_test(info)) { + info->init_error = DiagStatus_AddressFailure; + printk( "%s(%d):Register test failure for device %s Addr=%04X\n", + __FILE__,__LINE__,info->device_name, (unsigned short)(info->io_base) ); + return -ENODEV; + } + + if (!irq_test(info)) { + info->init_error = DiagStatus_IrqFailure; + printk( "%s(%d):Interrupt test failure for device %s IRQ=%d\n", + __FILE__,__LINE__,info->device_name, (unsigned short)(info->irq_level) ); + return -ENODEV; + } + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):device %s passed diagnostics\n", + __FILE__,__LINE__,info->device_name); + return 0; +} + +void trace_block(MGSLPC_INFO *info,const char* data, int count, int xmit) +{ + int i; + int linecount; + if (xmit) + printk("%s tx data:\n",info->device_name); + else + printk("%s rx data:\n",info->device_name); + + while(count) { + if (count > 16) + linecount = 16; + else + linecount = count; + + for(i=0;i=040 && data[i]<=0176) + printk("%c",data[i]); + else + printk("."); + } + printk("\n"); + + data += linecount; + count -= linecount; + } +} + +/* HDLC frame time out + * update stats and do tx completion processing + */ +void tx_timeout(unsigned long context) +{ + MGSLPC_INFO *info = (MGSLPC_INFO*)context; + unsigned long flags; + + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk( "%s(%d):tx_timeout(%s)\n", + __FILE__,__LINE__,info->device_name); + if(info->tx_active && + info->params.mode == MGSL_MODE_HDLC) { + info->icount.txtimeout++; + } + spin_lock_irqsave(&info->lock,flags); + info->tx_active = 0; + info->tx_count = info->tx_put = info->tx_get = 0; + + spin_unlock_irqrestore(&info->lock,flags); + +#ifdef CONFIG_SYNCLINK_SYNCPPP + if (info->netcount) + mgslpc_sppp_tx_done(info); + else +#endif + bh_transmit(info); +} + +#ifdef CONFIG_SYNCLINK_SYNCPPP +/* syncppp net device routines + */ + +void mgslpc_sppp_init(MGSLPC_INFO *info) +{ + struct net_device *d; + + sprintf(info->netname,"mgslp%d",info->line); + + info->if_ptr = &info->pppdev; + info->netdev = info->pppdev.dev = &info->netdevice; + + sppp_attach(&info->pppdev); + + d = info->netdev; + strcpy(d->name,info->netname); + d->base_addr = info->io_base; + d->irq = info->irq_level; + d->priv = info; + d->init = NULL; + d->open = mgslpc_sppp_open; + d->stop = mgslpc_sppp_close; + d->hard_start_xmit = mgslpc_sppp_tx; + d->do_ioctl = mgslpc_sppp_ioctl; + d->get_stats = mgslpc_net_stats; + d->tx_timeout = mgslpc_sppp_tx_timeout; + d->watchdog_timeo = 10*HZ; + +#if LINUX_VERSION_CODE < VERSION(2,4,4) + dev_init_buffers(d); +#endif + + if (register_netdev(d) == -1) { + printk(KERN_WARNING "%s: register_netdev failed.\n", d->name); + sppp_detach(info->netdev); + return; + } + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("mgslpc_sppp_init()\n"); +} + +void mgslpc_sppp_delete(MGSLPC_INFO *info) +{ + if (debug_level >= DEBUG_LEVEL_INFO) + printk("mgslpc_sppp_delete(%s)\n",info->netname); + sppp_detach(info->netdev); + unregister_netdev(info->netdev); +} + +int mgslpc_sppp_open(struct net_device *d) +{ + MGSLPC_INFO *info = d->priv; + int err, flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("mgslpc_sppp_open(%s)\n",info->netname); + + spin_lock_irqsave(&info->netlock, flags); + if (info->count != 0 || info->netcount != 0) { + printk(KERN_WARNING "%s: sppp_open returning busy\n", info->netname); + spin_unlock_irqrestore(&info->netlock, flags); + return -EBUSY; + } + info->netcount=1; + MOD_INC_USE_COUNT; + spin_unlock_irqrestore(&info->netlock, flags); + + /* claim resources and init adapter */ + if ((err = startup(info)) != 0) + goto open_fail; + + /* allow syncppp module to do open processing */ + if ((err = sppp_open(d)) != 0) { + shutdown(info); + goto open_fail; + } + + info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; + mgslpc_program_hw(info); + + d->trans_start = jiffies; + netif_start_queue(d); + return 0; + +open_fail: + spin_lock_irqsave(&info->netlock, flags); + info->netcount=0; + MOD_DEC_USE_COUNT; + spin_unlock_irqrestore(&info->netlock, flags); + return err; +} + +void mgslpc_sppp_tx_timeout(struct net_device *dev) +{ + MGSLPC_INFO *info = dev->priv; + int flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("mgslpc_sppp_tx_timeout(%s)\n",info->netname); + + info->netstats.tx_errors++; + info->netstats.tx_aborted_errors++; + + spin_lock_irqsave(&info->lock,flags); + tx_stop(info); + spin_unlock_irqrestore(&info->lock,flags); + + netif_wake_queue(dev); +} + +int mgslpc_sppp_tx(struct sk_buff *skb, struct net_device *dev) +{ + MGSLPC_INFO *info = dev->priv; + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("mgslpc_sppp_tx(%s)\n",info->netname); + + netif_stop_queue(dev); + + info->tx_count = skb->len; + + memcpy(info->tx_buf, skb->data, skb->len); + info->tx_get = 0; + info->tx_put = info->tx_count = skb->len; + + info->netstats.tx_packets++; + info->netstats.tx_bytes += skb->len; + dev_kfree_skb(skb); + + dev->trans_start = jiffies; + + spin_lock_irqsave(&info->lock,flags); + if (!info->tx_active) + tx_start(info); + spin_unlock_irqrestore(&info->lock,flags); + + return 0; +} + +int mgslpc_sppp_close(struct net_device *d) +{ + MGSLPC_INFO *info = d->priv; + unsigned long flags; + + if (debug_level >= DEBUG_LEVEL_INFO) + printk("mgslpc_sppp_close(%s)\n",info->netname); + + /* shutdown adapter and release resources */ + shutdown(info); + + /* allow syncppp to do close processing */ + sppp_close(d); + netif_stop_queue(d); + + spin_lock_irqsave(&info->netlock, flags); + info->netcount=0; + MOD_DEC_USE_COUNT; + spin_unlock_irqrestore(&info->netlock, flags); + return 0; +} + +void mgslpc_sppp_rx_done(MGSLPC_INFO *info, char *buf, int size) +{ + struct sk_buff *skb = dev_alloc_skb(size); + if (debug_level >= DEBUG_LEVEL_INFO) + printk("mgslpc_sppp_rx_done(%s)\n",info->netname); + if (skb == NULL) { + printk(KERN_NOTICE "%s: cant alloc skb, dropping packet\n", + info->netname); + info->netstats.rx_dropped++; + return; + } + + memcpy(skb_put(skb, size),buf,size); + + skb->protocol = htons(ETH_P_WAN_PPP); + skb->dev = info->netdev; + skb->mac.raw = skb->data; + info->netstats.rx_packets++; + info->netstats.rx_bytes += size; + netif_rx(skb); + info->netdev->trans_start = jiffies; +} + +void mgslpc_sppp_tx_done(MGSLPC_INFO *info) +{ + if (netif_queue_stopped(info->netdev)) + netif_wake_queue(info->netdev); +} + +struct net_device_stats *mgslpc_net_stats(struct net_device *dev) +{ + MGSLPC_INFO *info = dev->priv; + if (debug_level >= DEBUG_LEVEL_INFO) + printk("mgslpc_net_stats(%s)\n",info->netname); + return &info->netstats; +} + +int mgslpc_sppp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + MGSLPC_INFO *info = (MGSLPC_INFO *)dev->priv; + if (debug_level >= DEBUG_LEVEL_INFO) + printk("%s(%d):mgslpc_ioctl %s cmd=%08X\n", __FILE__,__LINE__, + info->netname, cmd ); + return sppp_do_ioctl(dev, ifr, cmd); +} + +#endif /* ifdef CONFIG_SYNCLINK_SYNCPPP */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/pcxx.c linux.19rc3-ac4/drivers/char/pcxx.c --- linux.19rc3/drivers/char/pcxx.c 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/pcxx.c 2002-07-29 13:58:39.000000000 +0100 @@ -153,7 +153,6 @@ DECLARE_TASK_QUEUE(tq_pcxx); static void pcxxpoll(unsigned long dummy); -static void pcxxdelay(int); static void fepcmd(struct channel *, int, int, int, int, int); static void pcxe_put_char(struct tty_struct *, unsigned char); static void pcxe_flush_chars(struct tty_struct *); @@ -1271,7 +1270,7 @@ for(crd=0; crd < numcards; crd++) { bd = &boards[crd]; outb(FEPRST, bd->port); - pcxxdelay(1); + mdelay(1); for(i=0; (inb(bd->port) & FEPMASK) != FEPRST; i++) { if(i > 100) { @@ -1283,7 +1282,7 @@ #ifdef MODULE schedule(); #endif - pcxxdelay(10); + mdelay(10); } if(bd->status == DISABLED) continue; @@ -1362,7 +1361,7 @@ #ifdef MODULE schedule(); #endif - pcxxdelay(1); + mdelay(1); } if(bd->status == DISABLED) continue; @@ -1413,7 +1412,7 @@ #ifdef MODULE schedule(); #endif - pcxxdelay(50); + mdelay(50); } printk("\nPC/Xx: BIOS download failed for board at 0x%x(addr=%lx-%lx)!\n", @@ -1443,7 +1442,7 @@ #ifdef MODULE schedule(); #endif - pcxxdelay(10); + mdelay(10); } printk("\nPC/Xx: BIOS download failed on the %s at 0x%x!\n", @@ -1487,7 +1486,7 @@ #ifdef MODULE schedule(); #endif - pcxxdelay(1); + mdelay(1); } if(bd->status == DISABLED) @@ -1520,7 +1519,7 @@ #ifdef MODULE schedule(); #endif - pcxxdelay(1); + mdelay(1); } if(bd->status == DISABLED) continue; @@ -1825,15 +1824,6 @@ } -/* - * pcxxdelay - delays a specified number of milliseconds - */ -static void pcxxdelay(int msec) -{ - mdelay(msec); -} - - static void fepcmd(struct channel *ch, int cmd, int word_or_byte, int byte2, int ncmds, int bytecmd) diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/pdc_console.c linux.19rc3-ac4/drivers/char/pdc_console.c --- linux.19rc3/drivers/char/pdc_console.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/pdc_console.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,681 @@ +/* + * linux/drivers/char/pdc_console.c + * + * 2001, Christoph Plattner + * + * Driver template was linux's serial.c + * + */ + +static char *pdc_drv_version = "0.3"; +static char *pdc_drv_revdate = "2001-11-17"; +#define AUTHOR "christoph.plattner@gmx.at" +#include +#include + +#undef PDC_DRV_DEBUG + +#undef SERIAL_PARANOIA_CHECK +#define CONFIG_SERIAL_NOPAUSE_IO +#define SERIAL_DO_RESTART + +#define PDC_POLL_DELAY (30 * HZ / 1000) + +/* + * End of serial driver configuration section. + */ + +#include + +#include +#include +#include +#include +#include +#define LOCAL_VERSTRING "" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef CONFIG_GSC +#include +#endif + +extern int pdc_console_poll_key(void *); +extern void pdc_outc(unsigned char); + +static char *pdc_drv_name = "PDC Software Console"; + +static struct tty_driver pdc_drv_driver; +static int pdc_drv_refcount = 0; +static struct async_struct *pdc_drv_info; + +static struct timer_list pdc_drv_timer; + +/* serial subtype definitions */ +#ifndef SERIAL_TYPE_NORMAL +#define SERIAL_TYPE_NORMAL 1 +#define SERIAL_TYPE_CALLOUT 2 +#endif + +#define NR_PORTS 1 +#define PDC_DUMMY_BUF 2048 + +static struct tty_struct *pdc_drv_table[NR_PORTS]; +static struct termios *pdc_drv_termios[NR_PORTS]; +static struct termios *pdc_drv_termios_locked[NR_PORTS]; + +/* + * tmp_buf is used as a temporary buffer by serial_write. We need to + * lock it in case the copy_from_user blocks while swapping in a page, + * and some other program tries to do a serial write at the same time. + * Since the lock will only come under contention when the system is + * swapping and available memory is low, it makes sense to share one + * buffer across all the serial ports, since it significantly saves + * memory if large numbers of serial ports are open. + */ +static unsigned char *tmp_buf; +#ifdef DECLARE_MUTEX +static DECLARE_MUTEX(tmp_buf_sem); +#else +static struct semaphore tmp_buf_sem = MUTEX; +#endif + +/* + * ------------------------------------------------------------ + * pdc_stop() and pdc_start() + * + * This routines are called before setting or resetting tty->stopped. + * They enable or disable transmitter interrupts, as necessary. + * ------------------------------------------------------------ + */ +static void +pdc_stop(struct tty_struct *tty) +{ +} + +static void +pdc_start(struct tty_struct *tty) +{ +} + +/* + * ---------------------------------------------------------------------- + * + * Here starts the interrupt handling routines. All of the following + * subroutines are declared as inline and are folded into + * rs_interrupt(). They were separated out for readability's sake. + * + * Note: rs_interrupt() is a "fast" interrupt, which means that it + * runs with interrupts turned off. People who may want to modify + * rs_interrupt() should try to keep the interrupt handler as fast as + * possible. After you are done making modifications, it is not a bad + * idea to do: + * + * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c + * + * and look at the resulting assemble code in serial.s. + * + * - Ted Ts'o (tytso@mit.edu), 7-Mar-93 + * ----------------------------------------------------------------------- + */ + +static void +receive_chars(struct async_struct *info, int *status, struct pt_regs *regs) +{ + struct tty_struct *tty = info->tty; + unsigned char ch; + int __ch; + + while (1) { + __ch = pdc_console_poll_key(NULL); + + if (__ch == -1) /* no character available */ + break; + + ch = (unsigned char) ((unsigned) __ch & 0x000000ffu); + + if (tty->flip.count >= TTY_FLIPBUF_SIZE) + continue; + + *tty->flip.char_buf_ptr = ch; + *tty->flip.flag_buf_ptr = 0; + + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + tty->flip.count++; + } + + tty_flip_buffer_push(tty); +} + +static void +pdc_drv_poll(unsigned long dummy) +{ + struct async_struct *info; + int status = 0; + + info = pdc_drv_info; + + if (!info || !info->tty || (pdc_drv_refcount == 0)) { + /* do nothing */ + } else { + receive_chars(info, &status, NULL); + info->last_active = jiffies; + } + + mod_timer(&pdc_drv_timer, jiffies + PDC_POLL_DELAY); +} + +static void +pdc_put_char(struct tty_struct *tty, unsigned char ch) +{ +#ifdef PDC_DRV_DEBUG + printk(KERN_NOTICE "[%s] %c return\n", __FUNCTION__, ch); +#endif + pdc_outc(ch); +} + +static void +pdc_flush_chars(struct tty_struct *tty) +{ + /* PCD console always flushed all characters */ + +#ifdef PDC_DRV_DEBUG + printk(KERN_NOTICE "[%s] return\n", __FUNCTION__); +#endif + + /* nothing to do */ +} + +static int +pdc_write(struct tty_struct *tty, int from_user, + const unsigned char *buf, int count) +{ + char pdc_tmp_buf[PDC_DUMMY_BUF]; + char *pdc_tmp_buf_ptr; + int len; + int ret = 0; + +#ifdef PDC_DRV_DEBUG + printk(KERN_NOTICE "[%s] entry\n", __FUNCTION__); +#endif + while (count) { + if (count < PDC_DUMMY_BUF) + len = count; + else + len = PDC_DUMMY_BUF; + + if (from_user) { + copy_from_user(pdc_tmp_buf, buf, len); + pdc_tmp_buf_ptr = pdc_tmp_buf; + } else + pdc_tmp_buf_ptr = (char *) buf; + + while (len) { + pdc_outc(*pdc_tmp_buf_ptr); + buf++; + pdc_tmp_buf_ptr++; + ret++; + count--; + len--; + } + } +#ifdef PDC_DRV_DEBUG + printk(KERN_NOTICE "[%s] return\n", __FUNCTION__); +#endif + return ret; +} + +static int +pdc_write_room(struct tty_struct *tty) +{ +#ifdef PDC_DRV_DEBUG + printk(KERN_NOTICE "[%s] entry\n", __FUNCTION__); +#endif + return PDC_DUMMY_BUF; +} + +static int +pdc_chars_in_buffer(struct tty_struct *tty) +{ +#ifdef PDC_DRV_DEBUG + printk(KERN_NOTICE "[%s] entry\n", __FUNCTION__); +#endif + return 0; /* no characters in buffer, always flushed ! */ +} + +static void +pdc_flush_buffer(struct tty_struct *tty) +{ +#ifdef PDC_DRV_DEBUG + printk(KERN_NOTICE "[%s] return\n", __FUNCTION__); +#endif +} + +/* + * This function is used to send a high-priority XON/XOFF character to + * the device + */ +static void +pdc_send_xchar(struct tty_struct *tty, char ch) +{ +} + +/* + * ------------------------------------------------------------ + * pdc_throttle() + * + * This routine is called by the upper-layer tty layer to signal that + * incoming characters should be throttled. + * ------------------------------------------------------------ + */ +static void +pdc_throttle(struct tty_struct *tty) +{ +} + +static void +pdc_unthrottle(struct tty_struct *tty) +{ +} + +/* + * ------------------------------------------------------------ + * pdc_ioctl() and friends + * ------------------------------------------------------------ + */ + +static void +pdc_break(struct tty_struct *tty, int break_state) +{ +} + +static int +get_serial_info(struct async_struct * info, + struct serial_struct * retinfo) +{ + struct serial_struct tmp; + + if (!retinfo) + return -EFAULT; + memset(&tmp, 0, sizeof(tmp)); + tmp.line = info->line; + tmp.port = info->line; + tmp.flags = info->flags; + tmp.close_delay = info->close_delay; + return copy_to_user(retinfo,&tmp,sizeof(*retinfo)) ? -EFAULT : 0; +} + +static int get_modem_info(struct async_struct * info, unsigned int *value) +{ + unsigned int result = TIOCM_DTR|TIOCM_CAR|TIOCM_CTS|TIOCM_RTS; + + return copy_to_user(value, &result, sizeof(int)) ? -EFAULT : 0; +} + +static int get_lsr_info(struct async_struct * info, unsigned int *value) +{ + unsigned int result = TIOCSER_TEMT; + + return copy_to_user(value, &result, sizeof(int)) ? -EFAULT : 0; +} + +static int +pdc_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct async_struct *info = (struct async_struct *) tty->driver_data; + + if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && + (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) && + (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + } + + switch (cmd) { + case TIOCMGET: + return get_modem_info(info, (unsigned int *) arg); + case TIOCMBIS: + case TIOCMBIC: + case TIOCMSET: + return 0; + case TIOCGSERIAL: + return get_serial_info(info, (struct serial_struct *) arg); + case TIOCSSERIAL: + return 0; + case TIOCSERCONFIG: + return 0; + + case TIOCSERGETLSR: /* Get line status register */ + return get_lsr_info(info, (unsigned int *) arg); + + case TIOCSERGSTRUCT: + if (copy_to_user((struct async_struct *) arg, + info, sizeof (struct async_struct))) + return -EFAULT; + return 0; + + case TIOCMIWAIT: + return 0; + + case TIOCGICOUNT: + return 0; + case TIOCSERGWILD: + case TIOCSERSWILD: + /* "setserial -W" is called in Debian boot */ + printk("TIOCSER?WILD ioctl obsolete, ignored.\n"); + return 0; + + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static void +pdc_set_termios(struct tty_struct *tty, struct termios *old_termios) +{ + +#if 0 /* XXX CP, has to be checked, if there is stuff to do */ + struct async_struct *info = (struct async_struct *) tty->driver_data; + unsigned long flags; + unsigned int cflag = tty->termios->c_cflag; + + if ((cflag == old_termios->c_cflag) + && (RELEVANT_IFLAG(tty->termios->c_iflag) + == RELEVANT_IFLAG(old_termios->c_iflag))) + return; +#if 0 + change_speed(info, old_termios); +#endif + /* Handle turning off CRTSCTS */ + if ((old_termios->c_cflag & CRTSCTS) && + !(tty->termios->c_cflag & CRTSCTS)) { + tty->hw_stopped = 0; + pdc_start(tty); + } +#endif +} + +/* + * ------------------------------------------------------------ + * pdc_close() + * + * This routine is called when the serial port gets closed. First, we + * wait for the last remaining data to be sent. Then, we unlink its + * async structure from the interrupt chain if necessary, and we free + * that IRQ if nothing is left in the chain. + * ------------------------------------------------------------ + */ +static void +pdc_close(struct tty_struct *tty, struct file *filp) +{ + struct async_struct *info = (struct async_struct *) tty->driver_data; + +#ifdef PDC_DEBUG_OPEN + printk("pdc_close ttyB%d, count = %d\n", info->line, state->count); +#endif + pdc_drv_refcount--; + if (pdc_drv_refcount > 0) + return; + + info->flags |= ASYNC_CLOSING; + + /* + * Save the termios structure, since this port may have + * separate termios for callout and dialin. + */ + if (info->flags & ASYNC_NORMAL_ACTIVE) + info->state->normal_termios = *tty->termios; + if (info->flags & ASYNC_CALLOUT_ACTIVE) + info->state->callout_termios = *tty->termios; + + /* + * At this point we stop accepting input. To do this, we + * disable the receive line status interrupts, and tell the + * interrupt driver to stop checking the data ready bit in the + * line status register. + */ + + /* XXX CP: make mask for receive !!! */ + + if (tty->driver.flush_buffer) + tty->driver.flush_buffer(tty); + if (tty->ldisc.flush_buffer) + tty->ldisc.flush_buffer(tty); + tty->closing = 0; + info->event = 0; + info->tty = 0; + pdc_drv_info = NULL; + if (info->blocked_open) { + if (info->close_delay) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(info->close_delay); + } + wake_up_interruptible(&info->open_wait); + } + info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE | + ASYNC_CLOSING); + wake_up_interruptible(&info->close_wait); + MOD_DEC_USE_COUNT; +} + +/* + * pdc_wait_until_sent() --- wait until the transmitter is empty + */ +static void +pdc_wait_until_sent(struct tty_struct *tty, int timeout) +{ + /* we always send immideate */ +} + +/* + * pdc_hangup() --- called by tty_hangup() when a hangup is signaled. + */ +static void +pdc_hangup(struct tty_struct *tty) +{ +} + +/* + * ------------------------------------------------------------ + * pdc_open() and friends + * ------------------------------------------------------------ + */ + +static int +get_async_struct(int line, struct async_struct **ret_info) +{ + struct async_struct *info; + + info = kmalloc(sizeof (struct async_struct), GFP_KERNEL); + if (!info) { + return -ENOMEM; + } + memset(info, 0, sizeof (struct async_struct)); + init_waitqueue_head(&info->open_wait); + init_waitqueue_head(&info->close_wait); + init_waitqueue_head(&info->delta_msr_wait); + info->magic = SERIAL_MAGIC; + info->port = 0; + info->flags = 0; + info->io_type = 0; + info->iomem_base = 0; + info->iomem_reg_shift = 0; + info->xmit_fifo_size = PDC_DUMMY_BUF; + info->line = line; + info->tqueue.routine = NULL; + info->tqueue.data = info; + info->state = NULL; + *ret_info = info; + return 0; +} + +/* + * This routine is called whenever a serial port is opened. It + * enables interrupts for a serial port, linking in its async structure into + * the IRQ chain. It also performs the serial-specific + * initialization for the tty structure. + */ +static int +pdc_open(struct tty_struct *tty, struct file *filp) +{ + struct async_struct *info; + int retval, line; + unsigned long page; + + MOD_INC_USE_COUNT; + line = MINOR(tty->device) - tty->driver.minor_start; + if ((line < 0) || (line >= NR_PORTS)) { + MOD_DEC_USE_COUNT; + return -ENODEV; + } + retval = get_async_struct(line, &info); + if (retval) { + MOD_DEC_USE_COUNT; + return retval; + } + tty->driver_data = info; + info->tty = tty; + pdc_drv_info = info; + +#ifdef PDC_DEBUG_OPEN + printk("pdc_open %s%d, count = %d\n", tty->driver.name, info->line, + info->state->count); +#endif + info->tty->low_latency = 0; + if (!tmp_buf) { + page = get_zeroed_page(GFP_KERNEL); + if (!page) { + MOD_DEC_USE_COUNT; + return -ENOMEM; + } + if (tmp_buf) + free_page(page); + else + tmp_buf = (unsigned char *) page; + } + + info->session = current->session; + info->pgrp = current->pgrp; + +#ifdef PDC_DEBUG_OPEN + printk("pdc_open ttyB%d successful...", info->line); +#endif + pdc_drv_refcount++; + return 0; +} + +/* + * --------------------------------------------------------------------- + * pdc_init() and friends + * + * pdc_init() is called at boot-time to initialize the pdc driver. + * --------------------------------------------------------------------- + */ + +static void +show_pdc_drv_version(void) +{ + printk(KERN_INFO "%s version %s%s (%s), %s\n", pdc_drv_name, + pdc_drv_version, LOCAL_VERSTRING, pdc_drv_revdate, AUTHOR); +} + +/* + * The serial driver boot-time initialization code! + */ +static int __init +pdc_drv_init(void) +{ + init_timer(&pdc_drv_timer); + pdc_drv_timer.function = pdc_drv_poll; + mod_timer(&pdc_drv_timer, jiffies + PDC_POLL_DELAY); + + show_pdc_drv_version(); + + /* Initialize the tty_driver structure */ + + memset(&pdc_drv_driver, 0, sizeof (struct tty_driver)); + pdc_drv_driver.magic = TTY_DRIVER_MAGIC; + pdc_drv_driver.driver_name = "pdc_console"; +#ifdef CONFIG_DEVFS_FS + pdc_drv_driver.name = "ttb/%d"; +#else + pdc_drv_driver.name = "ttyB"; +#endif + pdc_drv_driver.major = PDCCONS_MAJOR; + pdc_drv_driver.minor_start = 0; + pdc_drv_driver.num = NR_PORTS; + pdc_drv_driver.type = TTY_DRIVER_TYPE_SERIAL; + pdc_drv_driver.subtype = SERIAL_TYPE_NORMAL; + pdc_drv_driver.init_termios = tty_std_termios; + pdc_drv_driver.init_termios.c_cflag = + B9600 | CS8 | CREAD | HUPCL | CLOCAL; + pdc_drv_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS; + pdc_drv_driver.refcount = &pdc_drv_refcount; + pdc_drv_driver.table = pdc_drv_table; + pdc_drv_driver.termios = pdc_drv_termios; + pdc_drv_driver.termios_locked = pdc_drv_termios_locked; + + pdc_drv_driver.open = pdc_open; + pdc_drv_driver.close = pdc_close; + pdc_drv_driver.write = pdc_write; + pdc_drv_driver.put_char = pdc_put_char; + pdc_drv_driver.flush_chars = pdc_flush_chars; + pdc_drv_driver.write_room = pdc_write_room; + pdc_drv_driver.chars_in_buffer = pdc_chars_in_buffer; + pdc_drv_driver.flush_buffer = pdc_flush_buffer; + pdc_drv_driver.ioctl = pdc_ioctl; + pdc_drv_driver.throttle = pdc_throttle; + pdc_drv_driver.unthrottle = pdc_unthrottle; + pdc_drv_driver.set_termios = pdc_set_termios; + pdc_drv_driver.stop = pdc_stop; + pdc_drv_driver.start = pdc_start; + pdc_drv_driver.hangup = pdc_hangup; + pdc_drv_driver.break_ctl = pdc_break; + pdc_drv_driver.send_xchar = pdc_send_xchar; + pdc_drv_driver.wait_until_sent = pdc_wait_until_sent; + pdc_drv_driver.read_proc = NULL; + + if (tty_register_driver(&pdc_drv_driver)) + panic("Couldn't register pdc_console driver\n"); + + return 0; +} + +static void __exit +pdc_fini(void) +{ + int e1; + + if ((e1 = tty_unregister_driver(&pdc_drv_driver))) + printk("pdc_console: failed to unregister pdc_drv driver (%d)\n", + e1); +} + +module_init(pdc_drv_init); +module_exit(pdc_fini); +MODULE_DESCRIPTION("PDC Software Console"); +MODULE_AUTHOR(AUTHOR); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/random.c linux.19rc3-ac4/drivers/char/random.c --- linux.19rc3/drivers/char/random.c 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/random.c 2002-07-29 13:58:39.000000000 +0100 @@ -412,13 +412,13 @@ * deal with a variable rotate of x bits. So we use a bit of asm magic. */ #if (!defined (__i386__)) -extern inline __u32 rotate_left(int i, __u32 word) +static inline __u32 rotate_left(int i, __u32 word) { return (word << i) | (word >> (32 - i)); } #else -extern inline __u32 rotate_left(int i, __u32 word) +static inline __u32 rotate_left(int i, __u32 word) { __asm__("roll %%cl,%0" :"=r" (word) @@ -1643,7 +1643,7 @@ return -EINVAL; if (size > random_state->poolinfo.poolwords) size = random_state->poolinfo.poolwords; - if (copy_to_user(p, random_state->pool, size * 4)) + if (copy_to_user(p, random_state->pool, size * sizeof(__u32))) return -EFAULT; return 0; case RNDADDENTROPY: diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/raw.c linux.19rc3-ac4/drivers/char/raw.c --- linux.19rc3/drivers/char/raw.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/raw.c 2002-07-29 13:58:39.000000000 +0100 @@ -23,6 +23,7 @@ struct block_device *binding; int inuse, sector_size, sector_bits; struct semaphore mutex; + int can_do_vary; } raw_device_data_t; static raw_device_data_t raw_devices[256]; @@ -119,6 +120,8 @@ if (raw_devices[minor].inuse++) goto out; + raw_devices[minor].can_do_vary = + get_blkdev_varyio(MAJOR(rdev), MINOR(rdev)); /* * Don't interfere with mounted devices: we cannot safely set * the blocksize on a device which is already mounted. @@ -128,6 +131,7 @@ if (is_mounted(rdev)) { if (blksize_size[MAJOR(rdev)]) sector_size = blksize_size[MAJOR(rdev)][MINOR(rdev)]; + raw_devices[minor].can_do_vary = 0; } else { if (hardsect_size[MAJOR(rdev)]) sector_size = hardsect_size[MAJOR(rdev)][MINOR(rdev)]; @@ -135,6 +139,7 @@ set_blocksize(rdev, sector_size); raw_devices[minor].sector_size = sector_size; + filp->f_iobuf->dovary = raw_devices[minor].can_do_vary; for (sector_bits = 0; !(sector_size & 1); ) sector_size>>=1, sector_bits++; @@ -201,9 +206,10 @@ /* First, find out which raw minor we want */ - err = copy_from_user(&rq, (void *) arg, sizeof(rq)); - if (err) + if (copy_from_user(&rq, (void *) arg, sizeof(rq))) { + err = -EFAULT; break; + } minor = rq.raw_minor; if (minor <= 0 || minor > MINORMASK) { @@ -260,6 +266,8 @@ rq.block_major = rq.block_minor = 0; } err = copy_to_user((void *) arg, &rq, sizeof(rq)); + if (err) + err = -EFAULT; } break; @@ -322,6 +330,7 @@ if (err) goto out; new_iobuf = 1; + iobuf->dovary = raw_devices[minor].can_do_vary; } dev = to_kdev_t(raw_devices[minor].binding->bd_dev); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/serial.c linux.19rc3-ac4/drivers/char/serial.c --- linux.19rc3/drivers/char/serial.c 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/serial.c 2002-07-29 13:58:39.000000000 +0100 @@ -62,6 +62,10 @@ * Robert Schwebel , * Juergen Beisert , * Theodore Ts'o + * 4/02: added TTY_DO_WRITE_WAKEUP to enable n_tty to send POLL_OUTS + * to waiting processes + * Sapan Bhatia + * */ static char *serial_version = "5.05c"; @@ -203,6 +207,7 @@ #include #include #include +#include #if (LINUX_VERSION_CODE >= 131343) #include #endif @@ -1213,7 +1218,7 @@ if (!page) return -ENOMEM; - save_flags(flags); cli(); + spin_lock_irqsave( &info->irq_spinlock, flags); if (info->flags & ASYNC_INITIALIZED) { free_page(page); @@ -1451,11 +1456,11 @@ change_speed(info, 0); info->flags |= ASYNC_INITIALIZED; - restore_flags(flags); + spin_unlock_irqrestore( &info->irq_spinlock, flags); return 0; errout: - restore_flags(flags); + spin_unlock_irqrestore( &info->irq_spinlock, flags); return retval; } @@ -1479,7 +1484,7 @@ state->irq); #endif - save_flags(flags); cli(); /* Disable interrupts */ + spin_lock_irqsave( &info->irq_spinlock, flags); /* * clear delta_msr_wait queue to avoid mem leaks: we may free the irq @@ -1487,41 +1492,6 @@ */ wake_up_interruptible(&info->delta_msr_wait); - /* - * First unlink the serial port from the IRQ chain... - */ - if (info->next_port) - info->next_port->prev_port = info->prev_port; - if (info->prev_port) - info->prev_port->next_port = info->next_port; - else - IRQ_ports[state->irq] = info->next_port; - figure_IRQ_timeout(state->irq); - - /* - * Free the IRQ, if necessary - */ - if (state->irq && (!IRQ_ports[state->irq] || - !IRQ_ports[state->irq]->next_port)) { - if (IRQ_ports[state->irq]) { - free_irq(state->irq, &IRQ_ports[state->irq]); - retval = request_irq(state->irq, rs_interrupt_single, - SA_SHIRQ, "serial", - &IRQ_ports[state->irq]); - - if (retval) - printk("serial shutdown: request_irq: error %d" - " Couldn't reacquire IRQ.\n", retval); - } else - free_irq(state->irq, &IRQ_ports[state->irq]); - } - - if (info->xmit.buf) { - unsigned long pg = (unsigned long) info->xmit.buf; - info->xmit.buf = 0; - free_page(pg); - } - info->IER = 0; serial_outp(info, UART_IER, 0x00); /* disable all intrs */ #ifdef CONFIG_SERIAL_MANY_PORTS @@ -1578,7 +1548,43 @@ serial_outp(info, UART_IER, UART_IERX_SLEEP); } info->flags &= ~ASYNC_INITIALIZED; - restore_flags(flags); + + /* + * First unlink the serial port from the IRQ chain... + */ + if (info->next_port) + info->next_port->prev_port = info->prev_port; + if (info->prev_port) + info->prev_port->next_port = info->next_port; + else + IRQ_ports[state->irq] = info->next_port; + figure_IRQ_timeout(state->irq); + + /* + * Free the IRQ, if necessary + */ + if (state->irq && (!IRQ_ports[state->irq] || + !IRQ_ports[state->irq]->next_port)) { + if (IRQ_ports[state->irq]) { + free_irq(state->irq, &IRQ_ports[state->irq]); + retval = request_irq(state->irq, rs_interrupt_single, + SA_SHIRQ, "serial", + &IRQ_ports[state->irq]); + + if (retval) + printk("serial shutdown: request_irq: error %d" + " Couldn't reacquire IRQ.\n", retval); + } else + free_irq(state->irq, &IRQ_ports[state->irq]); + } + + if (info->xmit.buf) { + unsigned long pg = (unsigned long) info->xmit.buf; + info->xmit.buf = 0; + free_page(pg); + } + + spin_unlock_irqrestore( &info->irq_spinlock, flags); } #if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */ @@ -3123,6 +3129,7 @@ info->tqueue.routine = do_softint; info->tqueue.data = info; info->state = sstate; + spin_lock_init(&info->irq_spinlock); if (sstate->info) { kfree(info); *ret_info = sstate->info; @@ -3237,6 +3244,7 @@ #ifdef SERIAL_DEBUG_OPEN printk("rs_open ttys%d successful...", info->line); #endif + set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); return 0; } @@ -3650,6 +3658,7 @@ info->io_type = state->io_type; info->iomem_base = state->iomem_base; info->iomem_reg_shift = state->iomem_reg_shift; + info->irq_spinlock= (spinlock_t) SPIN_LOCK_UNLOCKED; save_flags(flags); cli(); @@ -3902,7 +3911,14 @@ case 6: /* BAR 4*/ case 7: base_idx=idx-2; /* BAR 5*/ } - + + /* AFAVLAB uses a different mixture of BARs and offsets */ + /* Not that ugly ;) -- HW */ + if (dev->vendor == PCI_VENDOR_ID_AFAVLAB && idx >= 4) { + base_idx = 4; + offset = (idx - 4) * 8; + } + /* Some Titan cards are also a little weird */ if (dev->vendor == PCI_VENDOR_ID_TITAN && (dev->device == PCI_DEVICE_ID_TITAN_400L || @@ -4306,9 +4322,11 @@ pbn_b0_bt_1_115200, pbn_b0_bt_2_115200, + pbn_b0_bt_8_115200, pbn_b0_bt_1_460800, pbn_b0_bt_2_460800, pbn_b0_bt_2_921600, + pbn_b0_bt_4_460800, pbn_b1_1_115200, pbn_b1_2_115200, @@ -4387,9 +4405,11 @@ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 }, /* pbn_b0_bt_1_115200 */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 }, /* pbn_b0_bt_2_115200 */ + { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 8, 115200 }, /* pbn_b0_bt_8_115200 */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 460800 }, /* pbn_b0_bt_1_460800 */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 460800 }, /* pbn_b0_bt_2_460800 */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 921600 }, /* pbn_b0_bt_2_921600 */ + { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 4, 460800 }, /* pbn_b0_bt_4_460800 */ { SPCI_FL_BASE1, 1, 115200 }, /* pbn_b1_1_115200 */ { SPCI_FL_BASE1, 2, 115200 }, /* pbn_b1_2_115200 */ @@ -4854,6 +4874,12 @@ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUAD_B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_bt_2_460800 }, + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_OCTO_A, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_4_460800 }, + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_OCTO_B, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_4_460800 }, { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_SSERIAL, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_bt_1_115200 }, @@ -4866,6 +4892,11 @@ PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b2_bt_2_115200 }, + /* AFAVLAB serial card, from Harald Welte */ + { PCI_VENDOR_ID_AFAVLAB, PCI_DEVICE_ID_AFAVLAB_P028, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_8_115200 }, + /* EKF addition for i960 Boards form EKF with serial port */ { PCI_VENDOR_ID_INTEL, 0x1960, 0xE4BF, PCI_ANY_ID, 0, 0, @@ -5652,6 +5683,7 @@ info->io_type = req->io_type; info->iomem_base = req->iomem_base; info->iomem_reg_shift = req->iomem_reg_shift; + info->irq_spinlock= (spinlock_t) SPIN_LOCK_UNLOCKED; } autoconfig(state); if (state->type == PORT_UNKNOWN) { @@ -5959,6 +5991,7 @@ info->io_type = state->io_type; info->iomem_base = state->iomem_base; info->iomem_reg_shift = state->iomem_reg_shift; + info->irq_spinlock= (spinlock_t) SPIN_LOCK_UNLOCKED; quot = state->baud_base / baud; cval = cflag & (CSIZE | CSTOPB); #if defined(__powerpc__) || defined(__alpha__) diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/serial_tx3912.h linux.19rc3-ac4/drivers/char/serial_tx3912.h --- linux.19rc3/drivers/char/serial_tx3912.h 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/serial_tx3912.h 2002-07-29 15:45:39.000000000 +0100 @@ -12,6 +12,27 @@ #include #include +/* UART Interrupt (Interrupt 2) bits (UARTA,UARTB) */ +#define UART_RX_INT 9 /* receiver holding register full (31, 21) */ +#define UART_RXOVERRUN_INT 8 /* receiver overrun error (30, 20) */ +#define UART_FRAMEERR_INT 7 /* receiver frame error (29, 19) */ +#define UART_BREAK_INT 6 /* received break signal (28, 18) */ +#define UART_PARITYERR_INT 5 /* receiver parity error (27, 17) */ +#define UART_TX_INT 4 /* transmit holding register empty (26, 16) */ +#define UART_TXOVERRUN_INT 3 /* transmit overrun error (25, 15) */ +#define UART_EMPTY_INT 2 /* both trans/recv regs empty (24, 14) */ +#define UART_DMAFULL_INT 1 /* DMA at end of buffer (23, 13) */ +#define UART_DMAHALF_INT 0 /* DMA halfway through buffer (22, 12) */ + +#define UARTA_SHIFT 22 +#define UARTB_SHIFT 12 + +#define INTTYPE(interrupttype) (1 << interrupttype) + +/* + * This driver can spew a whole lot of debugging output at you. If you + * need maximum performance, you should disable the DEBUG define. + */ #undef TX3912_UART_DEBUG #ifdef TX3912_UART_DEBUG diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/sonypi.h linux.19rc3-ac4/drivers/char/sonypi.h --- linux.19rc3/drivers/char/sonypi.h 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/sonypi.h 2002-07-29 18:09:34.000000000 +0100 @@ -214,6 +214,7 @@ /* The set of possible back button events */ static struct sonypi_event sonypi_backev[] = { { 0x20, SONYPI_EVENT_BACK_PRESSED }, + { 0x3b, SONYPI_EVENT_HELP_PRESSED }, { 0x00, 0x00 } }; @@ -258,7 +259,7 @@ while (--n && (command)) \ udelay(1); \ if (!n && (verbose || !quiet)) \ - printk(KERN_WARNING "sonypi command failed at " __FILE__ " : " __FUNCTION__ "(line %d)\n", __LINE__); \ + printk(KERN_WARNING "sonypi command failed at " __FILE__ " : %s (line %d)\n", __FUNCTION__, __LINE__); \ } #endif /* __KERNEL__ */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/speakup/BUGS linux.19rc3-ac4/drivers/char/speakup/BUGS --- linux.19rc3/drivers/char/speakup/BUGS 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/speakup/BUGS 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,10 @@ +Well, there are probably just thousands to squash, but these are the +ones I think of as bugs. + +There is a problem with speakup interrogating LiteTalks with rom +versions of at least 3.22 and earlier. (kirk) + +I define bugs as things which aren't working correctly although +they've been implemented. NOT features which haven't been added yet. + + Kirk diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/speakup/ChangeLog linux.19rc3-ac4/drivers/char/speakup/ChangeLog --- linux.19rc3/drivers/char/speakup/ChangeLog 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/speakup/ChangeLog 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,1214 @@ +2001-10-18 Thursday 08:53 jim + + Removed the cut and paste bug description from the BUGS file. (Jim) + +2001-10-14 Sunday 15:28 jim + + Part two of the selection.c patch for 2.2. This process sure was fun! (Jim) + +2001-10-14 Sunday 15:21 jim + + Just adding the new patch file for selection.c in the diff-v22 patch + directory. (Jim) + +2001-10-14 Sunday 14:45 kirk + + Just adding the new patch file for selection.c in the diff-v24 patch + directory. (kirk) + +2001-10-14 Sunday 14:42 kirk + + Changed selection.c to test if call is coming from userspace or kernel + space and using GFP_ATOMIC if it is being called from kernel-space. + This works around kmalloc not returning and hanging the system in + set_selection for the block and paste function of speakup. (Jim) + +2001-10-12 Friday 12:10 jim + + speakup.c: + Removed statements which were appending 0x00 to buffers to be spoken + from functions say_curr_line and say_line_from_to. + + Inspected and modified all spkup_write() calls to be consistent, + that is, end in \n and count is correct. + (Jim Danley) + +2001-10-09 Tuesday 08:34 kirk + + Updated the BUGS and Todo list to reflect current speakup + states. (kirk) + +2001-10-07 Sunday 21:19 jim + + speakup.c: + Moved following variable declarations to top of function speakup_cut(). + int ret; + unsigned char args[6*sizeof(short)]; + unsigned short *arg; + static char *buf = "speakup_cut: set_selection failed: "; + (Jim Danley) + +2001-10-07 Sunday 17:11 jim + + Put speakup_dectlk.c back to its original state. Sorry about that! + + Also added a clear_selection() call to speakup.c when hitting the "mark" + key to remove (if any) hi-lighting of a previous mark/cut from the screen. + (Jim Danley) + +2001-10-05 Friday 09:14 kirk + + Checking in a slight change to speakupmap.map to uncomment alt-keypad + five to allow ascii five for extended character sets. (kirk) + +2001-10-02 Tuesday 12:34 kirk + + Modified installation and readme files for the version 1.0 release in + linux/Documentation/speakup. (kirk) + +2001-10-02 Tuesday 11:00 kirk + + Start of the check-ins for the official speakup v-1.00 release. + Modified checkin to change cvsversion format. Modified install to + remove reference to touching speakupmap.map. Modified speakup.c to + reflect version now moved to v-1.00. (kirk) + +2001-10-02 Tuesday 01:18 jim + + Modified the way that cut/paste variables are stored. No longer in spk_t + structure but stand-alone (one per speakup rather than one per console). + + speakup.c: + eliminated unsigned short mode = 0; /* char-by-char selection */ + by assigning it directly. + + Added globals + char mark_cut_flag; + unsigned short mark_x, mark_y; + + /usr/include/linux/include/linux/speakup.h: + removed mark_x and mark_y from the spk_t structure and the associated + defines. + (Jim Danley) + +2001-09-17 Monday 19:58 jim + + speakup.c: + Added: + #define Mark_Cut_Bit 0x04 + #define Mark_Cut_Bit_Mask 0xFB + + Changed from using bit 2 of spk_shut_up to bit 2 of spk_sound to + indicate mark/cut state. + + Removed statement that was assigning 2 to second byte of first short + in args array. + (Jim Danley) + +2001-09-14 Friday 15:43 kirk + + Removed the blank line at the bottom of drivers/char/Makefile which I + must have dreamed I removed in the last log. (kirk) + +2001-09-14 Friday 15:28 kirk + + Added a couple of missing key definitions in DefaultKeyAssignments. + Removed the blank line at the bottom of drivers/char/Makefile. + Rewrote spell_word() to use say_curr_char() and super stream line + it. (kirk) + +2001-09-14 Friday 14:11 jim + + speakup_dectlk.c: + Changed the valid pitch range from 0-99 to 50-350. + (Jim Danley) + +2001-09-14 Friday 01:28 jim + + Made similar changes to add cut and paste feature to 2.2 kernels. (Jim Danley + +2001-09-13 Thursday 23:13 jim + + diff-v2[24]/^usr^src^linux^Documentation^speakup^DefaultKeyAssignments.copy: + Added: + KeyPad-/ Mark and Cut screen region. + InsKeyPad-/ Paste screen region into any console. + (Jim Danley) + +2001-09-13 Thursday 21:41 jim + + Wrote mark/cut/paste feature. + + Usage: + 1. Move reading cursor to one end of the block of text you wish to cut + 2. Press the mark/cut key. You should hear "mark". + 3. Move reading cursor to other end of block of text to be cut. + 4. Press the mark/cut key. You should hear "cut". + 5. The cut buffer is now saved. + 6. Move to a program in any console where you wish to copy the cut buffer. + 7. Press the paste key. You should hear "paste" and text from + the cut buffer will be output just as if you had entered it + at the keyboard. + + Note: Trailing whitespace is stripped and newlines added where appropriate. + + speakup.c: + Added two new functions; speakup_cut() and speakup_paste() + + speakupmap.map: + Modified default keymap so that keypad divide toggles mark/cut and + insert-keypad divide is paste. + + /usr/src/linux/include/linux/speakup.h: + Added two new variables to the spk_t structure; unsigned long mark_x, mark_y + to store the coordinates of the beginning of the mark area to be cut. + Added: + #define spk_mx speakup_console[currcons]->mark_x + #define spk_my speakup_console[currcons]->mark_y + #define SPEAKUP_CUT 0x27 + #define SPEAKUP_PASTE 0x28 + Added two new prototypes: + extern void speakup_cut(unsigned int, struct tty_struct *); + extern void speakup_paste(struct tty_struct *); + + /usr/src/linux/drivers/char/keyboard.c: + In function do_spkup(): + Added case blocks for SPEAKUP_CUT and SPEAKUP_PASTE. + + /usr/src/linux/include/linux/keyboard.h: + Added: + #define K_SPEAKUP_CUT K(KT_SPKUP,SPEAKUP_CUT) + #define K_SPEAKUP_PASTE K(KT_SPKUP,SPEAKUP_PASTE) + and modified: (was 27) + #define NR_SPKUP 0x29 + + Also modified patch/copy files below in both diff-v22 and diff-v24 directories. + ^usr^src^linux^include^linux^keyboard.h.patch + ^usr^src^linux^drivers^char^keyboard.c.patch + ^usr^src^linux^include^linux^speakup.h.copy + +2001-09-08 Saturday 22:22 kirk + + Re-implementing the alpha patch for kernels 2.4.x which somehow keeps + getting lost. I also removed the bottom three lines of the checkout + script which are not needed anymore because we include a + speakupmap.c. (Kirk) + +2001-08-30 Thursday 17:25 kirk + + Modified drivers/char/Makefile to work with the new speakupmap.c + changes to 2.4.x. These changes include a portion of Shane's patch as + well as other rewrites by me. (kirk) + +2001-08-30 Thursday 16:17 kirk + + Modified drivers/char/Makefile and speakup/Makefile to accomodate the + new 2.4.9ac3 Makefile changes. This will also include a new + speakupmap.c moving towards Shane's Makefile patches for the 2.2.x + kernels, not included yet. (kirk) + +2001-08-29 Wednesday 21:26 kirk + + Just adding new patch against linux/init/main.c to cvs. (kirk) + +2001-08-29 Wednesday 21:23 kirk + + Rewrote speakup_init() to call a function speakup_register_devsynth() + which gets called from do_basic_setup in init/main.c. We need to do + this so that miscdevice will get called after the mm has been set up. + This should allow devfs to work with speakup. (kirk) + +2001-08-26 Sunday 13:54 kirk + + Removed an old comment line from console.c which prevent clean + patching against 2.4.8ac11. (kirk) + +2001-08-25 Saturday 18:46 kirk + + Modified keyboard.c, keyboard.h, speakup.c and speakup.h to conform with the standard kernel source tree under 2.4.x kernels. (Kirk) + +2001-08-25 Saturday 18:30 kirk + + Removing lxdialog patch files and removing their entries from + patchlist-22. These are now part of the standard 2.2.19+ kernel + tree. (Kirk) + ---------------------------------------------------------------------- + patchlist-v22 speakupmap.map symbols.h CVS: + diff-v22/^usr^src^linux^Documentation^speakup^DefaultKeyAssignments.copy + diff-v22/^usr^src^linux^Documentation^speakup^keymap-tutorial.copy + Removed Files: CVS: + diff-v22/^usr^src^linux^scripts^lxdialog^menubox.c.patch CVS: + ---------------------------------------------------------------------- + +2001-08-25 Saturday 18:15 kirk + + Changed keyboard.c, keyboard.h, speakup.c and speakup.h to conform to + the standard linux kernel tree code style for the 2.2.x + kernels. (Kirk) + +2001-08-18 Saturday 03:31 jim + + diff-v22/^usr^src^linux^drivers^char^keyboard.c.patch: Modified patch + to allow raw keyboard for version 2.2 kernels. (Jim Danley) + +2001-08-02 Thursday 13:47 kirk + + Adding \x20 to the flush string for the Audapter synths. (Kirk) + +2001-07-31 Tuesday 19:07 jim + + speakup_ltlk.c: appended \x20 to flush string of \x18 for litetalk driver. + This seems to fix the bug that was causing first chars to be dropped by + the double lt and litetalk synths for some users. (Jim Danley) + +2001-07-26 Thursday 20:12 kirk + + A few small clean ups trying to get 2.4.7 to work. (Kirk) + +2001-07-16 Monday 11:30 kirk + + Added KT_SPKUP to allowed_in_raw_mode macro so speakup's review + functions are available in raw mode for v-2.4.x kernels. (Kirk) + +2001-03-17 Saturday 15:40 jim + + speakup.c: + Added silent feature. + The print screen key kills and revives speakup. Sending specific values to + /proc/speakup/silent now allows the same control without having to press a key. + Valid settings are 0 through 3. + 0 and 2 turn on speakup if not already alive. + 1 and 3 turn off speakup if not already killed. + 0 and 1 announce the changes as the print screen key does, + 2 and 3 act silently. + (Jim Danley) + +2001-03-17 Saturday 08:45 jim + + speakup.c and symbols.h: + Added bell position feature. + When a letter is typed in column bell_pos, console beeps. + Valid settings are 0 through video_num_columns. Zero disables. + Get/set via /proc/speakup/bell_pos. + (Brian Borowski) + +2001-03-13 Tuesday 14:50 jim + + speakup.c: + Added code in say_screen() to insert a space at the end of full lines. + (Gene Collins) + +2001-03-13 Tuesday 14:40 jim + + speakup.c: + Found and fixed a couple of places where synth_write() was writing len of + string plus 1 which caused a NULL to be sent to the synth which causes + problems for the Doubletalk LT. + + speakup.c and keyboard.c for 2.2 and 2.4 + Corrected the length parameter on several spkup_write() statements which + were also sending unnecessary NULLs. + + Corrected spelling of /proc/speakup/transport directory. (Jim Danley) + +2001-02-28 Wednesday 10:55 kirk + + Removing the make menuconfig patches for checklist.c and menubox.c + because they have been included in linux 2.4.2. (Kirk) + +2001-02-11 Sunday 14:05 kirk + + Checking support for alpha support in 2.4.x kernels. (Kirk) + +2001-01-30 Tuesday 20:55 kirk + + Fixed arch/ppc/config.in to source drivers/char/Config.in which had + gotten broken in the post 2.4.0 ac patches. (Kirk) + +2001-01-28 Sunday 23:53 jim + + Reduced duplicate code in proc_speakup_synth_init() by creating two arrays + of strings, read_only[] and root_writable[] and using these arrays in + for loops. + Bumped version numbers on remaining serial synth drivers. (Jim Danley) + +2001-01-28 Sunday 20:26 kirk + + Made modifications to speakup.h for v2.2 and the remainder of the + serial synth drivers to use the initialize_uart() function in + speakup_drvcommon.c. (Kirk) + +2001-01-28 Sunday 19:15 kirk + + Made changes to 2.4.0 to move uart initialization code into + speakup_drvcommon.c and modified speakup_dectlk.c to use that + change. (Kirk) + +2001-01-28 Sunday 00:26 jim + + Modified the serprobe() function in the Accent SA driver. + This should allow the Accent SA to start talking from a cold boot with + no help from the lilo serial= or speakup_ser= options. + Ran speakup_acntsa.c through Lindent. + Bumped speakup_acntsa.c version number. (Jim Danley) + +2001-01-27 Saturday 23:26 jim + + Modified the serprobe() function in the Dectalk Express driver. + My Dectalk Express now starts talking just fine from a cold boot with + no help from the lilo serial= or speakup_ser= options. + Ran speakup_dectlk.c through Lindent and cleaned up some comments. + Bumped Dectalk Express driver version number. (Jim Danley) + +2001-01-25 Thursday 17:58 jim + + Worked on the write handler for /proc/speakup/synth. + It error-checks new_synth_name, prints out msg if synth selected is + already in use, looks for new_synth_name in list of synths compiled into + kernel, and prepares to switch to new synth. + Ran speakup.c through Lindent and cleaned up some comments. (Jim Danley) + +2001-01-24 Wednesday 22:59 jim + + + Modified speakup_drvcommon.c so that those synth-specific /proc file + entries which are writable will now accept "" to trigger resetting of + the default value. + Ran speakup_drvcommon.c through Lindent and cleaned up some comments. + (Jim Danley) + +2001-01-24 Wednesday 12:33 kirk + + Made changes for Maintaners to v-24. (Kirk) + +2001-01-24 Wednesday 12:31 kirk + + Another typo fix in Configure.help and an update to the URL in Maintaners. (Kirk) + +2001-01-24 Wednesday 11:57 kirk + + Fixed clarification in Configure.help in v-24. (Kirk) + +2001-01-24 Wednesday 11:56 kirk + + Fixed spelling error in Config.in and modified Configure.help yet again. (Kirk) + +2001-01-24 Wednesday 11:47 kirk + + Fixed formatting in v-24 configure.help. (Kirk) + +2001-01-24 Wednesday 11:46 kirk + + Fixed indentation and spelling errors in configure.help. (Kirk) + +2001-01-24 Wednesday 10:49 kirk + + Fixing the v-2.4 version of the Configure.help file. (Kirk) + +2001-01-24 Wednesday 10:47 kirk + + Updated the Configure.help documentation and re-arranged the speakup + Config.in file. (Kirk) + +2001-01-23 Tuesday 15:45 jim + + + Modified speakup.c to handle input in either upper or lower case written + to the /proc file entries for those settings that accept a range of + values that includes alpha chars. + The value is forced to lower case before any comparisons. + Modified the synth driver range parameters to accept only lower case as follows: + rate in both speakup_acntpc.c and speakup_acntsa.c, + pitch and volume in speakup_apolo.c, + tone in speakup_txprt.c. + Bumped synth driver version numbers. + (Jim Danley) + +2001-01-23 Tuesday 11:58 jim + + + Fixed typo in speakup_dectlk.c. + (Jim Danley) + +2001-01-23 Tuesday 11:39 jim + + + Moved full_time into the spk_synth structure for all synths and created + /proc/speakup/synth-specific/full_time entry. + Modified /usr/include/linux/speakup.h and associated files in diff-v22 and diff-v24. + (Jim Danley) + +2001-01-23 Tuesday 01:14 jim + + + Added to the TODO list. + (Jim Danley) + +2001-01-23 Tuesday 00:42 jim + + + Moved delay_time, trigger_time, and jiffy_delta into the spk_synth + structure for all synths. + Modified /usr/include/linux/speakup.h and associated files in diff-v22 and diff-v24. + Assigned following default values for Accent SA and Audapter drivers: + delay_time = 400, trigger_time = 5, jiffy_delta = 3. + Bumped synth driver version numbers. + (Jim Danley) + +2001-01-22 Monday 21:32 jim + + + Moved INIT_STRING and REINIT_STRING into the spk_synth structure for all synths. + Modified /usr/include/linux/speakup.h and associated files in diff-v22 and diff-v24. + Commented out some unused driver code that caused compile warnings. + (Jim Danley) + +2001-01-22 Monday 17:44 jim + + + Test number 2. + (Jim Danley) + +2001-01-22 Monday 16:28 kirk + + + Testing my new CVS login. + (Jim Danley) + +2001-01-21 Sunday 19:48 kirk + + Wrote char *strlwr(char *) and now use it to be certain that the + synth_name (provided by the user in config or at boot time) is forced + to lower case. + (Jim Danley) + +2001-01-21 Sunday 13:53 kirk + + Added /proc/speakup/synth entry -- read-only so far. + Removed old ioctl functions from speakup.c + Wrote xlate function to translate escape chars in user provided strings. + Added synth_name to "unknown synthesizer" message at boot up. + Check for length of synth_name. + Made certain that synth_name is NULL terminated. + (Jim Danley) + +2001-01-21 Sunday 09:03 kirk + + Changed synth_write("\n", 2); + to synth_write("\n", 1); + when sending user provided synth settings via /proc to the synth. + This *might* fix the problem reported by litetalk users. + Cleaned up some comments and indenting. + (Jim Danley) + +2001-01-14 Sunday 21:05 matt + + Checking in 2.2.x patches for the last modification. (Matt) + +2001-01-14 Sunday 20:49 kirk + + Checking in Matt Campbells driver rewrite to include all the synths in + the kernel at the same time. (Kirk) + +2001-01-10 Wednesday 12:16 kirk + + Fixed bug when writing to /proc/speakup files caps_start, caps_stop, + punc_some, and punc_most. + Defined PUNC_CHARS and PUNC_CHARS_SIZE in symbols.h. + Added MULTI_CHAR to list of possible spk_variable.flags, necessary to + define a list of chars that must belong to another list of chars -- + used for punc_some and punc_most. + Set arbitrary limit of 33 chars on caps_*. + Set PUNC_CHARS_SIZE char limit on user supplied value to punc_some and punc_most. + Fixed erroneous error strings. + #define'd error conditions to make code more clear. + Added STRING_TOO_LONG and CHAR_NOT_ONE_OF. + Added missing volume setting to DEFAULT_STATIC for Dectalk Express. + (Jim Danley) + +2001-01-08 Monday 19:08 kirk + + Made more changes to the cursoring. I got backspace working in and + out of cursoring. (Kirk) + +2001-01-08 Monday 16:25 kirk + + I have rewritten the cursoring routine speakup_check() to hopefully + improve it. We are not there yet! (Kirk) + +2001-01-07 Sunday 16:05 kirk + + Just fixing some indentation settings. (Kirk) + +2001-01-07 Sunday 13:37 kirk + + added a single line to the top of speakup.c for testing. + (Jim Danley) + +2001-01-07 Sunday 12:58 kirk + + Fixed char/Makefile to build depends which it wasn't doing for some + reason under 2.2.18. (Kirk) + +2001-01-07 Sunday 12:16 kirk + + Fixed char/Makefile to create the speakup/.depend correctly. I don't + know why it wasn't working before. Everything else did. (Kirk) + +2001-01-07 Sunday 12:05 kirk + + modified range checking code in speakup.c to handle negative numbers in + user provided parameter to /proc/speakup/* and also in spk_variable.valid. + (Jim Danley) + +2001-01-07 Sunday 09:02 kirk + + cleaned up and commented symbols.h. + re-wrote some of the range logic in symbols.h and speakup.c. + changed char valid[33] to char *valid in spk_variable struct. + dropped 0xff as char string terminator for spk_variable.valid member. + removed NUMERIC from rate flags for accents. + made /proc/speakup/tone read-only for dectalk express. + (Jim Danley) + +2001-01-06 Saturday 15:52 kirk + + Reorganized the Todo list and placed bugs in the bugs file. (Kirk) + +2001-01-05 Friday 21:19 kirk + + Made modifications to fix the make menuconfig bug in 2.4.0. (Kirk) + +2001-01-05 Friday 20:42 kirk + + Modified menubox.c in lxdialog to fix bug with initial menus not being + shown completely. (Kirk) + +2001-01-05 Friday 15:54 kirk + + merged symbols_*.h into symbols.h and removed symbols_*.h from CVS. + cleaned up the format a bit along the way. + (Jim Danley) + +2001-01-04 Thursday 18:33 kirk + + Modified the console.c, speakup.h and speakup.c for the 2.4.0 kernels. + I have also removed vt.c in preparation for just using the + /proc/speakup configuration system. (Kirk) + +2001-01-04 Thursday 12:11 kirk + + Starting major changes for merging into the kernel source tree. Files + updated are console.c speakup.c speakup.h and vt.c. I have built a + new set of functions to interact with the kernel which will be speakup + functions if speakup is configured in and null stubs if speakup is not + configured in. So far they include: speakup_allocate(), speakup_bs(), + speakup_con_update(), speakup_con_write() and speakup_init(). These + changes only affect the 2.2.18 tree currently. (Kirk) + +2001-01-03 Wednesday 10:04 kirk + + Fixed transport driver by giving the uart time to settle before + testing for the port. (Kirk) + +2001-01-02 Tuesday 20:18 kirk + + First attempt to change checkout to work with an installed tarball and + update it to cvs. (Kirk) + +2001-01-02 Tuesday 14:09 kirk + + Made tchanges to make v24 compatible with 2.4.0-prerelease. (Kirk) + +2001-01-02 Tuesday 09:50 kirk + + Added code to correctly parse range string for /proc file speech + parameters which use a range of chars. + Added a priority of KERN_ALERT to printk statements that need to be + displayed on user's console regardless. + Enhanced warning output if user attempts to assign a value out of range + to a /proc variable. + (Jim Danley) + +2000-12-31 Sunday 13:20 kirk + + Rewrote checkclean and changed semee to semi in the character + array. (Kirk) + +2000-12-31 Sunday 12:12 kirk + + Fixed syntax errors in speakup_txprt.c and modified the install + script. (Kirk) + +2000-12-31 Sunday 11:43 kirk + + Fixing typo's in the documentation files. (Kirk) + +2000-12-30 Saturday 23:33 kirk + + Rewrote install and INSTALLATION for a different installing + design. (Kirk) + +2000-12-30 Saturday 17:03 kirk + + We are officially version v-0.10. (Kirk) + +2000-12-30 Saturday 16:58 kirk + + Modified the installation file and created an install script. (Kirk) + +2000-12-30 Saturday 15:13 kirk + + Fixed a syntax problem with speakup_audptr.c. (Kirk) + +2000-12-30 Saturday 14:58 kirk + + Placed a length limit on reading of version number in + speakup_audptr.c. (Kirk) + +2000-12-30 Saturday 13:12 kirk + + Adding file changes for v22. (Kirk) + +2000-12-30 Saturday 13:10 kirk + + Removing files related to version changes. (Kirk) + +2000-12-30 Saturday 13:00 kirk + + Changed structure of Documentation/speakup and related files to remove + references to speakup version for ease in updating documentation. + (Kirk) + +2000-12-29 Friday 14:00 kirk + + echo "" > /proc/speakup/characters now resets to defaults for consistency. + wrote script to reset all speakup defaults + added key_echo toggle to speakup vars controllable by user + via /proc/speakup/key_echo + key_echo is not 100% -- keypad slash talks even if key_echo == 0 + (Jim Danley) + +2000-12-24 Sunday 16:46 kirk + + finished ability to write to /proc files, changed some default char descs, added "direct" to /proc + +2000-12-22 Friday 15:04 kirk + + These are the cursoring fixes for the 2.4.0-testxx kernels. They also + include the requested changes I was experimenting with by Alan Cox in + preparation for kernel source tree inclusion. (Kirk) + +2000-12-22 Friday 13:54 kirk + + Fixed up some of the cursoring issues and have started making the + changes requested by Alan Cox in preparation for kernel source tree + inclusion. (Kirk) + +2000-12-21 Thursday 08:56 kirk + + rewrite of speakup_characters_write_proc() to handle fragmented buffers when called by dd, cp, or cat in kernel 2.4 (Jim Danley) + +2000-12-20 Wednesday 12:17 kirk + + Cleaned up some warnings. (Kirk) + +2000-12-20 Wednesday 11:32 kirk + + Fixed toggle for synth timeout to set it off when waking up the + synth. (Kirk) + +2000-12-19 Tuesday 19:31 kirk + + This is atest fix to see if I have helped eliminate the synth bleed + through problem with all of the synths. (Kirk) + +2000-12-19 Tuesday 16:29 kirk + + quick change to speakup_audptr.c to fix synth_ver typo for kernel 2.2.18 (Jim Danley) + +2000-12-19 Tuesday 15:35 kirk + + Checking in the 2.2.18 fixes for the synth hanging problems. (Kirk) + +2000-12-19 Tuesday 15:10 kirk + + Finally fixed the synth hanging problem on synth turn off. (Kirk) + +2000-12-18 Monday 14:44 kirk + + Just updating BUGS to put the backspace problem to bed. (Kirk) + +2000-12-18 Monday 14:40 kirk + + Checking in the backspace fix for 2.4.0-test11. Yeah! Finally + fixed. (Kirk) + +2000-12-18 Monday 14:14 kirk + + Fixed the backspace bug at last! In 2.2.18 so far. (Kirk) + +2000-12-18 Monday 10:03 kirk + + Checking in Jim Danleys changes again. When will I learn to checkout + before checking in?? (Kirk) + +2000-12-15 Friday 13:50 kirk + + Checking first draft of menubox.c and checklist.c for + v-2.4.0-testxx. (Kirk) + +2000-12-15 Friday 13:48 kirk + + Taking first diff of menubox.c and checklist.c for v2.4.0-test11 for + make menuconfig cursoring. (Kirk) + +2000-12-15 Friday 13:17 kirk + + Checking in the new diffs of menubox.c and checklist.c for the first + time. (Kirk) + +2000-12-15 Friday 13:14 kirk + + Taking first diff of the make menuconfig patches from checklist.c and + menubox.c. (Kirk) + +2000-12-12 Tuesday 18:56 kirk + + Fixed a spelling error added to Todo list and fix speakup.c to not + need the is_alive() function. (Kirk) + +2000-12-12 Tuesday 15:21 kirk + + Fixed speakup to patch correctly with 2.2.18. Unfortunately it won't + work with kernels less than 2.2.18 anymore. It was totally agreed + upon by the folks on the reflector. It's not my fault mom! (Kirk) + +2000-12-12 Tuesday 10:41 kirk + + Fix a problem with a conflict in cvsversion.h. (Kirk) + +2000-12-11 Monday 20:40 kirk + + Attempt to fix the Audapter driver by limiting how long it can stay in + kernel space. (Kirk) + +2000-12-11 Monday 17:37 kirk + + Made a slight fix to spk_reset() and moved it's call up a bit in + handle_scancodes(); (Kirk) + +2000-12-11 Monday 16:28 kirk + + Just checking in the cvs adds for the new diff-v24 patch files. (Kirk) + +2000-12-11 Monday 16:25 kirk + + Checking in the 2.4.0 kernel patches for Jim Danley's /proc file + system additions. (Kirk) + +2000-12-11 Monday 14:34 kirk + + Checking in added proc files. (Kirk) + +2000-12-11 Monday 14:31 kirk + + Added two new files to v22 kernel for /proc file system, + linux/include/linux/proc_fs.h and linux/fs/proc/root.c. (Kirk) + +2000-12-11 Monday 12:59 kirk + + Checking in Jim Danleys /proc file system additions to speakup. (Kirk) + +2000-12-09 Saturday 19:14 kirk + + Changed spk_control to test for zero specifically on say_control. (Kirk) + +2000-12-09 Saturday 18:29 kirk + + Changed spk_control to say capslock scroll_lock and num_lock even when + say_control isn't on. (Kirk) + +2000-12-08 Friday 16:21 kirk + + Removing the linux version 2.3.xx stuff again. (Kirk) + +2000-12-08 Friday 15:40 kirk + + patched Configure.help by hand from v2.4 and committing. (Kirk) + +2000-12-08 Friday 14:47 kirk + + Checked in diff-v22/^usr^src^linux^Documentation^Configure.help.patch + which seems to have been missed as well as the init/main.c stuff. + This is really weird (Kirk) + +2000-12-08 Friday 14:40 kirk + + Added the -d flag to updat in checkout to see if we get cleanup + improvement. (Kirk) + +2000-12-08 Friday 13:13 kirk + + Removing patchlist and the linux 2.3.xx support. (Kirk) + +2000-12-08 Friday 13:07 kirk + + Edited check.orig and fix.orig to use the new patchlist filename + convention. (Kirk) + +2000-12-07 Thursday 22:17 kirk + + Just checking in the new files, three to be exact. (kirk) + +2000-12-07 Thursday 22:14 kirk + + rewrote checkin, checkout and moved patchlist to patchlist-v22 and + patchlist-v24 because we were missing the linux/init/main.c patches + and we didn't have a way to handle different files for different + versions. (kirk) + +2000-12-06 Wednesday 19:06 kirk + + Added support for the codepage 437 extended character set. (Jim and Kirk) + +2000-11-29 Wednesday 11:30 kirk + + Fixed the 2.2.xx kernels to have the almost correct backspace code. + Also move the new character output in do_con_write() to lf(). I've + experimentally put a 'space' in to see if that helps the wrapping + during console output. (Kirk) + +2000-11-27 Monday 15:38 kirk + + Fix or partial to the backspace problem at least on 2.4.0-test11. I + probably broke cursoring. + +2000-11-22 Wednesday 20:12 kirk + + Fixed a stupid unused variable by deleting it. + Fixed speakup_file_write to send raw user data to the synth. (Thanx Matt) + +2000-11-21 Tuesday 15:10 kirk + + Adjusted console.c patch for test11 of 2.4.0. + +2000-11-16 Thursday 11:42 kirk + + Modified all drivers to test for no port when clearing the holding + register. + +2000-11-16 Thursday 07:56 kirk + + Fixed console.c patch to compensate for the line movement. in Test10. + +2000-10-24 Tuesday 11:10 kirk + + Fix to the LiteTalk driver to get around the hanging when the synth isn't + on. + +2000-10-23 Monday 12:15 kirk + + Fixed dtlk driver so non-valid ports are released correctly in + dev_probe. Also added externs for synth_request_region and + release. (Kirk) + +2000-08-28 Monday 13:29 kirk + + Fixed Makefile for 2.4.0-test7 in drivers/char. + +2000-08-17 Thursday 16:21 kirk + + Birth of cursoring for version 2.4.xx kernels. + +2000-08-17 Thursday 12:06 kirk + + Okay, I proclaim the birth of cursoring, at least in the 2.2.x kernels. Next we'll try the 2.3/4.x kernels. + +2000-08-17 Thursday 11:01 kirk + + Fixed CFLAGS to EXTRA_CFLAGS in Makefile to get speakup to compile + again. The break took place between 2.4.0-test4 and test5. + +2000-07-20 Thursday 10:43 kirk + + Changed krealloc to just use kfree instead of kfree_s. Kirk + +2000-07-03 Monday 14:19 kirk + + Fixed one line in keyboard.c and changes to cvs + +2000-06-29 Thursday 16:32 andy + + Fixed checkin / cvsversion.h + +2000-06-29 Thursday 16:27 andy + + v2.3 keyboard.c + speakup_kill() fix + +2000-06-29 Thursday 16:26 andy + + v2.2.x keyboard.c + speakup_kill() fix + +2000-06-29 Thursday 16:03 andy + + v2.3 addition of speakup_kill() function (bound to sysreq key) + +2000-06-29 Thursday 16:00 andy + + v2.2 addition of speakup_kill() function (bound to sysreq key) + +2000-06-29 Thursday 15:56 andy + + v2.4 addition of speakup_kill() function (bound to sysrq key) + +2000-06-26 Monday 16:19 andy + + Added (very minimal) read() and ioctl() functions for /dev/synth. + +2000-06-23 Friday 11:16 andy + + Fixed miscdevice.h bad patch + +2000-06-22 Thursday 15:47 andy + + Fixed defkeymap.c not being built properly. + +2000-06-22 Thursday 15:17 andy + + Fixed v2.2.x zero-byte patch bug + +2000-06-22 Thursday 14:48 andy + + Checkout prunes now. + +2000-06-22 Thursday 12:48 andy + + Forgot to kill the old patch files... cleaning up. + +2000-06-22 Thursday 12:45 andy + + Changed checkin/checkout philosophy... + v2.2.x, v2.3.x, v2.4.x trees are all in this release + +2000-06-21 Wednesday 16:27 andy + + More checkin/checkout fixes. + +2000-06-21 Wednesday 16:19 andy + + Changed checkin/checkout philosophy, so 0-byte files aren't such a headache + +2000-06-21 Wednesday 14:13 andy + + New checkout script, fixing non-updating of previously patched files. + +2000-06-20 Tuesday 15:14 andy + + /dev/synth (MAJOR 10, MINOR 25) fix for v2.2.x tree + +2000-06-19 Monday 16:02 andy + + checkin script that fixes busted/nonexstant .orig files + +2000-06-19 Monday 13:08 andy + + cvsversion.h fix + speakup_decext.c fix for v2.2.x (no such member 'list' problem) + +2000-06-14 Wednesday 16:00 andy + + TODO update + +2000-06-14 Wednesday 15:25 andy + + Fixed: + checkin 'older than' bug + disabled -lock speech when spk_shut_up is set + +2000-06-14 Wednesday 13:15 andy + + Added a cvsversion.h and cvs date tracking into speakup. + +2000-06-14 Wednesday 12:44 andy + + Oops. Forgot these. + +2000-06-14 Wednesday 08:06 kirk + + Put SYNTH_MINOR #ifdefs in miscdevices.h for v2.2.x kernels. + Updated Todo file and temporarily incremented version number of speakup. (Kirk) + +2000-06-13 Tuesday 16:30 andy + + v2.4.x spanky checkin + +2000-06-13 Tuesday 15:36 andy + + v2.4.x checkin for /dev/synth stuff. + +2000-06-13 Tuesday 15:28 andy + + typo fix. + +2000-06-13 Tuesday 15:23 andy + + v2.2.x checkin for the new /dev/synth stuff. + +2000-06-13 Tuesday 15:17 andy + + Added a /dev/synth fops to speakup (MAJOR 10, MINOR 25), so that users can + use the synth without speakup (but why?). :) + + Also fixed a couple of issues with the check* scripts, and added a -p option + to checkin to just create patches. + +2000-06-12 Monday 14:36 andy + + Had a 0-byte defkeymap.c file... + +2000-06-12 Monday 14:26 andy + + Fixed the screwed up v2.2.x patch files, and added a fixorig script which + copies .orig files from /usr/src/linux.orig as stated in the + patchlist file + +2000-06-09 Friday 16:03 andy + + TODO change + +2000-06-09 Friday 14:21 andy + + added checkclean script + +2000-06-09 Friday 12:46 andy + + updates to the v2.2.x tree. + +2000-06-08 Thursday 14:59 andy + + Fixed v2.2.x diffs, and made a few changes to checkin/checkout/checkorig.. + + Namely, + checkin: + fixed bailout on CVSROOT set + diffs only for new or files that have changed since last patch + cvs adds directories properly + checks exit values of cvs commands + checkout/checkorig: + zeroes out .orig files that should exist and should be zeroed + patchlist: + now specifies patchfiles in the form: + <0|1>, + where the first number is a flag to copy the file to create + a .orig, or create a zero-byte file (0) for .orig + +2000-06-07 Wednesday 15:52 kirk + + [no log message] + +2000-06-07 Wednesday 14:15 andy + + checkin mod + +2000-06-07 Wednesday 14:14 andy + + date test added to ./checkin + +2000-06-07 Wednesday 14:11 andy + + test + +2000-06-07 Wednesday 14:09 andy + + test patch + +2000-06-07 Wednesday 13:02 kirk + + test of checkin on spanky + +2000-06-07 Wednesday 12:32 andy + + more checkin/checkout updates + +2000-06-07 Wednesday 12:19 andy + + quick print fix for checkin script + +2000-06-07 Wednesday 12:17 andy + + Fixed new tree commit/checkout/update bugs with checkin and checkout + +2000-06-07 Wednesday 12:10 kirk + + v24 tree added to cvs + +2000-06-07 Wednesday 11:30 andy + + logic error in ./checkin + + New diff-vXX directories are added now... just cp -a diff-vYY div-vXX, and + kill the CVS/ dir. + +2000-06-05 Monday 15:54 andy + + Fixed ./checkin to 'cvs add' created patch directories. + +2000-06-05 Monday 15:39 andy + + Added synth_release_region, and seperated out a speakup_drvcommon.c file, + which contains common driver stuff -- current just synth_release_region(), + and synth_request_region(). + +2000-06-02 Friday 15:32 andy + + Final test?? + +2000-06-02 Friday 14:11 andy + + bleah + +2000-06-02 Friday 13:58 andy + + another test.. *sigh* + +2000-06-02 Friday 13:57 andy + + foo + +2000-06-02 Friday 13:56 andy + + adding speakup.h.patch + +2000-06-02 Friday 13:55 andy + + bleah + +2000-06-02 Friday 13:49 andy + + test 342.7 + +2000-06-02 Friday 12:56 andy + + wrong checkout script. + +2000-06-02 Friday 12:51 andy + + Yet another test. + +2000-06-01 Thursday 15:45 andy + + test #2 + +2000-06-01 Thursday 15:40 andy + + ./checkin script test + +2000-06-01 Thursday 15:38 andy + + Initial revision + +2000-06-01 Thursday 15:38 andy + + Initial version of speakup in CVS. + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/speakup/Config.in linux.19rc3-ac4/drivers/char/speakup/Config.in --- linux.19rc3/drivers/char/speakup/Config.in 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/speakup/Config.in 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,18 @@ +bool 'Speakup console speech' CONFIG_SPEAKUP +if [ "$CONFIG_SPEAKUP" != "n" ]; then + comment 'Type "y" for each synthesizer you want built into the kernel.' + bool "Accent SA, acntsa" CONFIG_SPEAKUP_ACNTSA + bool "Accent PC, acntpc" CONFIG_SPEAKUP_ACNTPC + bool "Apollo, apolo" CONFIG_SPEAKUP_APOLO + bool "Audapter, audptr" CONFIG_SPEAKUP_AUDPTR + bool "Braille 'n' Speak, bns" CONFIG_SPEAKUP_BNS + bool "DECtalk Express, dectlk" CONFIG_SPEAKUP_DECTLK + bool "DECtalk External (old), decext" CONFIG_SPEAKUP_DECEXT + bool "DoubleTalk PC, dtlk" CONFIG_SPEAKUP_DTLK + bool "DoubleTalk LT or LiteTalk, ltlk" CONFIG_SPEAKUP_LTLK + bool "Speak Out, spkout" CONFIG_SPEAKUP_SPKOUT + bool "Transport, txprt" CONFIG_SPEAKUP_TXPRT + comment 'Enter the four to six character synth string from above or none.' + string "Default synthesizer for Speakup" CONFIG_SPEAKUP_DEFAULT "none" + bool "Use Speakup keymap by default" CONFIG_SPEAKUP_KEYMAP +fi diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/speakup/Makefile linux.19rc3-ac4/drivers/char/speakup/Makefile --- linux.19rc3/drivers/char/speakup/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/speakup/Makefile 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,24 @@ +# +# Makefile for the speakup speech output system. +# + +O_TARGET := spk.o + +obj-$(CONFIG_SPEAKUP) += speakup.o speakup_drvcommon.o +obj-$(CONFIG_SPEAKUP_DTLK) += speakup_dtlk.o +obj-$(CONFIG_SPEAKUP_LTLK) += speakup_ltlk.o +obj-$(CONFIG_SPEAKUP_ACNTPC) += speakup_acntpc.o +obj-$(CONFIG_SPEAKUP_ACNTSA) += speakup_acntsa.o +obj-$(CONFIG_SPEAKUP_TXPRT) += speakup_txprt.o +obj-$(CONFIG_SPEAKUP_BNS) += speakup_bns.o +obj-$(CONFIG_SPEAKUP_AUDPTR) += speakup_audptr.o +obj-$(CONFIG_SPEAKUP_DECTLK) += speakup_dectlk.o +obj-$(CONFIG_SPEAKUP_DECEXT) += speakup_decext.o +obj-$(CONFIG_SPEAKUP_APOLO) += speakup_apolo.o +obj-$(CONFIG_SPEAKUP_SPKOUT) += speakup_spkout.o +obj-$(CONFIG_SPEAKUP_KEYMAP) += speakupmap.o + +include $(TOPDIR)/Rules.make + +speakupmap.c: speakupmap.map + set -e ; loadkeys --mktable $< | sed -e 's/^static *//' > $@ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/speakup/speakup_acnt.h linux.19rc3-ac4/drivers/char/speakup/speakup_acnt.h --- linux.19rc3/drivers/char/speakup/speakup_acnt.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/speakup/speakup_acnt.h 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,17 @@ +/* speakup_acntpc.h - header file for speakups Accent-PC driver. */ + +#define SYNTH_IO_EXTENT 0x02 + +#define SYNTH_CLEAR 0x18 /* stops speech */ + + /* Port Status Flags */ +#define SYNTH_READABLE 0x01 /* mask for bit which is nonzero if a + byte can be read from the data port */ +#define SYNTH_WRITABLE 0x02 /* mask for RDY bit, which when set to + 1, indicates the data port is ready + to accept a byte of data. */ +#define SYNTH_QUIET 'S' /* synth is not speaking */ +#define SYNTH_FULL 'F' /* synth is full. */ +#define SYNTH_ALMOST_EMPTY 'M' /* synth has les than 2 seconds of text left */ +#define SYNTH_SPEAKING 's' /* synth is speaking and has a fare way to go */ + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/speakup/speakup_acntpc.c linux.19rc3-ac4/drivers/char/speakup/speakup_acntpc.c --- linux.19rc3/drivers/char/speakup/speakup_acntpc.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/speakup/speakup_acntpc.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,240 @@ +/* + * speakup_acntpc.c - Accent PC driver for Linux kernel 2.3.x and speakup + * + * author: Kirk Reiser + + Copyright (C) 1998-99 Kirk Reiser. + + 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 + + Kirk Reiser + 261 Trott dr. London, Ontario, Canada. N6G 1B6 + */ + +/* These routines are written to control the Accent PC speech + synthesizer by Aicom. They are not ment to be thought of as a device driver + in that they do not register themselves as a chr device and there + is no file_operations structure. They are strictly to provide an + interface to the Accent-pc from the speakup screen review package. +*/ + +#define KERNEL +#include +#include +#include +#include /* for -EBUSY */ +#include /* for check_region, request_region */ +#include /* for loops_per_sec */ +#include /* for put_user_byte */ +#include /* for inb_p, outb_p, inb, outb, etc... */ +#include /* for wait_queue */ +#include /* kd_mksound */ +#include /* for __init */ +#include + +#include +#include "speakup_acnt.h" /* local header file for Accent values */ + +#define synth_readable() (inb_p(synth_port_control) & SYNTH_READABLE) +#define synth_writable() (inb_p(synth_port_control) & SYNTH_WRITABLE) +#define synth_full() (inb_p(synth_port_tts) == 'F') +static int synth_port_control; +/* 160 ms delay and ctrl-x as flush */ +static unsigned int synth_portlist[] = { 0x2a8, 0 }; + +static void do_catch_up(unsigned long data) +{ + unsigned long jiff_in = jiffies; + + synth_stop_timer(); + while ((synth_sent_bytes < synth_queued_bytes) && !synth_full()) { + while (synth_writable()); + + outb_p(*(synth_buffer + synth_sent_bytes++), synth_port_tts); + if (jiffies >= jiff_in + synth_jiffy_delta && + *(synth_buffer + synth_sent_bytes - 1) == ' ') { + while (synth_writable()); + + outb_p('\r', synth_port_tts); + synth_delay(synth_delay_time); + return; + } + } + if (synth_full()) { + synth_delay(synth_full_time); + return; + } + while (synth_writable()); + + outb_p('\r', synth_port_tts); + synth_sent_bytes = synth_queued_bytes = synth_timer_active = 0; + + if (waitqueue_active(&synth_sleeping_list)) + wake_up_interruptible(&synth_sleeping_list); +} + +static void synth_write_tts(char ch) +{ + if (ch < 0x00) + return; /* don't want unprintable chars */ + if (ch == 0x0a) /* turn lf into to force talking. */ + ch = 0x0D; + if (ch == SYNTH_CLEAR) { /* clear all and wake sleeping */ + outb_p(ch, synth_port_tts); /* output to data port */ + if (waitqueue_active(&synth_sleeping_list)) + wake_up_interruptible(&synth_sleeping_list); + synth_timer_active = synth_queued_bytes = synth_sent_bytes = 0; + return; + } + + synth_buffer_add(ch); + + if (synth_buffering && !synth_timer_active) + synth_delay(synth_trigger_time); +} + +static int __init synth_dev_probe(void) +{ + unsigned int port_val = 0; + int i = 0; + + printk(KERN_INFO "Probing for Accent PC.\n"); + if (synth_port_tts) { + printk(KERN_INFO "probe forced to %x by kernel command line\n", + synth_port_tts); + + if (synth_request_region(synth_port_tts - 1, SYNTH_IO_EXTENT)) { + printk(KERN_WARNING "sorry, port already reserved\n"); + return -EBUSY; + } + + port_val = inw(synth_port_tts-1); + synth_port_control = synth_port_tts-1; + } else { + for (i = 0; synth_portlist[i]; i++) { + if (synth_request_region(synth_portlist[i], + SYNTH_IO_EXTENT)) { + printk(KERN_WARNING "request_region: failed " + "with 0x%x, %d\n", + synth_portlist[i], SYNTH_IO_EXTENT); + continue; + } + + port_val = inw(synth_portlist[i]); + if ((port_val &= 0xfffc) == 0x53fc) { + /* 'S' and out & input bits */ + synth_port_control = synth_portlist[i]; + synth_port_tts = synth_port_control+1; + break; + } + } + } + + if ((port_val &= 0xfffc) != 0x53fc) { /* 'S' and out&input bits */ + printk(KERN_WARNING "Accent PC: not found\n"); + synth_release_region(synth_portlist[i], SYNTH_IO_EXTENT); + return -ENODEV; + } + + printk(KERN_INFO "Accent-PC: %03x-%03x, driver version %s,\n", + synth_port_control, synth_port_control + SYNTH_IO_EXTENT - 1, + synth->version); + synth_write(synth->init, strlen(synth->init)); + return 0; +} + +static int synth_alive(void) +{ + return 1; +} + +static const char init_string[] = "\x1b=X \x1bOi\x1bT2\x1b=M\x1bN1\x1bR9\n" + "Accent PC Found\n"; +static const char reinit_string[] = ""; + +static struct spk_variable vars[] = { + { + .id = "flush", + .param = "\x18", + .build = "_", + .flags = BUILDER | HARD_DIRECT | USE_RANGE | NO_USER, + .valid = "*", + }, + { + .id = "pitch", + .param = "5", + .build = "\x1bP_", + .flags = NUMERIC | HARD_DIRECT | USE_RANGE, + .valid = "0,9", + }, + { + .id = "caps_start", + .param = "\x1bP8", + .build = "_", + .flags = 0, + .valid = "*", + }, + { + .id = "caps_stop", + .param = "\x1bP5", + .build = "_", + .flags = 0, + .valid = "*", + }, + { + .id = "rate", + .param = "9", + .build = "\x1bR_", + .flags = HARD_DIRECT, + .valid = "0123456789abcdefgh", + }, + { + .id = "tone", + .param = "5", + .build = "\x1bV_", + .flags = NUMERIC | HARD_DIRECT | USE_RANGE, + .valid = "0,9", + }, + { + .id = "volume", + .param = "9", + .build = "\x1b\x41_", + .flags = NUMERIC | HARD_DIRECT | USE_RANGE, + .valid = "0,9", + }, + { NULL, } +}; + +static char *config[] = { "\x18", "\x1bP5", "\x1bP8", "\x1bP5", "\x1bR9", + "\x1bV5", "\x1b\x41\x39"}; + +struct spk_synth synth_acntpc = { + .name = "acntpc", + .version = "Version-0.9", + .proc_name = "accent_pc", + .init = init_string, + .reinit = reinit_string, + .delay_time = 500, + .trigger_time = 50, + .jiffy_delta = 5, + .full_time = 1000, + .vars = vars, + .config = config, + .config_map = 0, + .probe = synth_dev_probe, + .catch_up = do_catch_up, + .write = synth_write_tts, + .is_alive = synth_alive, +}; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/speakup/speakup_acntsa.c linux.19rc3-ac4/drivers/char/speakup/speakup_acntsa.c --- linux.19rc3/drivers/char/speakup/speakup_acntsa.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/speakup/speakup_acntsa.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,352 @@ +/* + * speakup_acntsa.c - Accent SA driver for Linux kernel 2.3.x and speakup + * + * author: Kirk Reiser + + Copyright (C) 1998-99 Kirk Reiser. + + 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 + + Kirk Reiser + 261 Trott dr. London, Ontario, Canada. N6G 1B6 + */ + +/* These routines are written to control the Accent SA speech + synthesizer by Aicom. They are not ment to be thought of as a device driver + in that they do not register themselves as a chr device and there + is no file_operations structure. They are strictly to provide an + interface to the Accent-SA from the speakup screen review package. +*/ + +#define KERNEL +#include +#include +#include +#include /* for verify_area */ +#include /* for -EBUSY */ +#include /* for check_region, request_region */ +#include /* for loops_per_sec */ +/* #include */ +#include /* for put_user_byte */ +/* #include */ +#include /* for inb_p, outb_p, inb, outb, etc... */ +#include /* for wait_queue */ +#include /* kd_mksound */ +#include /* for __init */ +#include +#include /* for rs_table, serial constants & + serial_uart_config */ +#include /* for more serial constants */ +#include /* for struct serial_state */ +#include + +#include +#include "speakup_acnt.h" /* local header file for Accent values */ + +#define synth_full() (inb_p(synth_port_tts) == 'F') +/* countdown values for serial timeouts */ +#define SPK_SERIAL_TIMEOUT 1000000 +/* countdown values transmitter/dsr timeouts */ +#define SPK_XMITR_TIMEOUT 1000000 +#define SPK_LO_TTY 0 /* check ttyS0 ... ttyS3 */ +#define SPK_HI_TTY 3 +#define NUM_DISABLE_TIMEOUTS 3 /* # of timeouts permitted before disable */ + +static int acntsa_alive; + /* 160 ms delay and ctrl-x as flush */ +#ifdef OLDSUCKYWAY +#define INIT_LEN 45 +static char INIT_STRING[] = "\x1bT2\x1b=M\x1bN1\x1bRD\x1bOp\x1bOL\x1bOi\x1b=" + "B\x1bM2\nAccent S A found\n"; +#define REINIT_LEN 49 +static char *REINIT_STRING = "\x1bT2\x1b=M\x1bN1\x1bRB\x1bOp\x1bOL\x1bOi\x1b" + "=B\x1bM3\nAccent S A restarted\n"; +#endif + +#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) + +static struct serial_state rs_table[] __initdata = { + SERIAL_PORT_DFNS +}; + +static int timeouts; /* sequential number of timeouts */ + +static int wait_for_xmitr(void) +{ + int check, tmout = SPK_XMITR_TIMEOUT; + + if (acntsa_alive && timeouts >= NUM_DISABLE_TIMEOUTS) { + acntsa_alive = 0; + return 0; + } + + /* holding register empty? */ + do { + check = inb_p(synth_port_tts + UART_LSR); + if (--tmout == 0) { + printk(KERN_WARNING "Accent-SA: timed out\n"); + timeouts++; + return 0; + } + } while ((check & BOTH_EMPTY) != BOTH_EMPTY); + + tmout = SPK_XMITR_TIMEOUT; + /* CTS */ + do { + check = inb_p(synth_port_tts + UART_MSR); + if (--tmout == 0) { + timeouts++; + return 0; + } + } while ((check & UART_MSR_CTS) != UART_MSR_CTS); + + timeouts = 0; + return 1; +} + +static inline int spk_serial_out(const char ch) +{ + if (acntsa_alive && synth_port_tts) { + if (wait_for_xmitr()) { + outb_p(ch, synth_port_tts); + return 1; + } + } + return 0; +} + +static void do_catch_up(unsigned long data) +{ + unsigned long jiff_in = jiffies; + + synth_stop_timer(); + while ((synth_sent_bytes < synth_queued_bytes) && !synth_full()) { + if (!spk_serial_out(*(synth_buffer + synth_sent_bytes))) { + synth_delay(synth_full_time); + return; + } + synth_sent_bytes++; + if (jiffies >= jiff_in + synth_jiffy_delta + && *(synth_buffer + synth_sent_bytes - 1) == ' ') { + spk_serial_out('\r'); + synth_delay(synth_delay_time); + return; + } + } + + synth_sent_bytes = synth_queued_bytes = 0; + spk_serial_out('\r'); + synth_timer_active = 0; + if (waitqueue_active(&synth_sleeping_list)) + wake_up_interruptible(&synth_sleeping_list); +} + +static void synth_write_tts(char ch) +{ + if (!acntsa_alive) + return; + if (ch < 0x00) + return; /* don't want unprintable chars */ + if (ch == 0x0a) /* turn lf into to force talking. */ + ch = 0x0D; + if (ch == SYNTH_CLEAR) { /* clear all and wake sleeping */ + spk_serial_out(ch); + if (waitqueue_active(&synth_sleeping_list)) + wake_up_interruptible(&synth_sleeping_list); + synth_timer_active = synth_queued_bytes = synth_sent_bytes = 0; + return; + } + + synth_buffer_add(ch); + if (synth_buffering) + return; + if (synth_timer_active == 0) + synth_delay(synth_trigger_time); +} + +static inline void synth_immediate_tts(const char *buf, size_t count) +{ + while (count--) + spk_serial_out(*buf++); + return; +} + +/* + * Setup initial baud/bits/parity. Swiped from serial.c (console section) + * Return non-zero if we didn't find a serial port. + */ +static int __init serprobe(int index) +{ + struct serial_state *ser = NULL; + unsigned char test = 0; + + if (synth_port_tts) { + for (test = 0; test <= SPK_HI_TTY; test++) + if ((rs_table + test)->port == synth_port_tts) { + ser = rs_table + test; + break; + } + } else + ser = rs_table + index; + + /* don't do output yet... */ + if (synth_request_region(ser->port, 8)) + return -1; + + initialize_uart(ser); + /* If we read 0xff from the LSR, there is no UART here. */ + if (inb(ser->port + UART_LSR) == 0xff) { + synth_release_region(ser->port, 8); + return -1; + } + outb(0x0d, ser->port); + mdelay(1); + + acntsa_alive = 1; + /* ignore any error results, if port was forced */ + if (synth_port_tts) + return 0; + + synth_port_tts = ser->port; + /* check for accent s.a now... */ + if (spk_serial_out(0x18)) + return 0; + + synth_release_region(ser->port, 8); + timeouts = acntsa_alive = synth_port_tts = 0; /* not ignoring */ + return -1; +} + +static int __init synth_dev_probe(void) +{ + int i = 0; + + printk(KERN_INFO "Probing for Accent-SA.\n"); + if (synth_port_tts) + printk(KERN_INFO "probe forced to 0x%x by " + "kernel command line\n", synth_port_tts); + + /* check ttyS0-ttyS3 */ + for (i = SPK_LO_TTY; i <= SPK_HI_TTY; i++) { + if (serprobe(i) == 0) + break; /* found it */ + } + + if (acntsa_alive) { + printk(KERN_INFO "Acnt-SA: %03x-%03x, Driver Version %s,\n", + synth_port_tts, synth_port_tts + 7, synth->version); + synth_immediate_tts("\x1b=R\r", 5); + synth_write(synth->init, strlen(synth->init)); + return 0; + } + + printk(KERN_INFO "Accent-SA: not found\n"); + return -ENODEV; +} + +static int synth_alive(void) +{ + if (acntsa_alive) + return 1; /* already on */ + else if (!acntsa_alive && synth_port_tts) { + if (wait_for_xmitr() > 0) { /* restart */ + acntsa_alive = 1; + synth_write(synth->reinit, strlen(synth->reinit)); + return 2; /* reenabled */ + } else + printk(KERN_INFO "Accent-SA: can't restart synth\n"); + } + return 0; +} + +static const char init_string[] = "\x1bT2\x1b=M\x1bOi\x1bN1\x1bRB\n" + "Accent S A Found\n"; +static const char reinit_string[] = "\x1bT2\x1bOi\x1b=M\x1bN1\x1bR9\n" + "Accent S A restarted\n"; + +static struct spk_variable vars[] = { + { + .id = "flush", + .param = "\x18", + .build = "_", + .flags = BUILDER | HARD_DIRECT | USE_RANGE | NO_USER, + .valid = "*", + }, + { + .id = "pitch", + .param = "5", + .build = "\x1bP_", + .flags = NUMERIC | HARD_DIRECT | USE_RANGE, + .valid = "0,9", + }, + { + .id = "caps_start", + .param = "\x1bP8", + .build = "_", + .flags = 0, + .valid = "*", + }, + { + .id = "caps_stop", + .param = "\x1bP5", + .build = "_", + .flags = 0, + .valid = "*", + }, + { + .id = "rate", + .param = "9", + .build = "\x1bR_", + .flags = HARD_DIRECT, + .valid = "0123456789abcdefgh", + }, + { + .id = "tone", + .param = "5", + .build = "\x1bV_", + .flags = NUMERIC | HARD_DIRECT | USE_RANGE, + .valid = "0,9", + }, + { + .id = "volume", + .param = "9", + .build = "\x1b\x41_", + .flags = NUMERIC | HARD_DIRECT | USE_RANGE, + .valid = "0,9", + }, + { NULL, } +}; + +static char *config[] = { "\x18", "\x1bP5", "\x1bP8", "\x1bP5", "\x1bR9", + "\x1bV5", "\x1b\x41\x39" }; + +struct spk_synth synth_acntsa = { + .name = "acntsa", + .version = "Version-0.14", + .proc_name = "accent_sa", + .init = init_string, + .reinit = reinit_string, + .delay_time = 400, + .trigger_time = 5, + .jiffy_delta = 3, + .full_time = 1000, + .vars = vars, + .config = config, + .config_map = 0, + .probe = synth_dev_probe, + .catch_up = do_catch_up, + .write = synth_write_tts, + .is_alive = synth_alive, +}; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/speakup/speakup_apolo.c linux.19rc3-ac4/drivers/char/speakup/speakup_apolo.c --- linux.19rc3/drivers/char/speakup/speakup_apolo.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/speakup/speakup_apolo.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,346 @@ +/* + * speakup_apolo.c for linux kernels 2.2.x and speakup + * + * author: Kirk Reiser + + Copyright (C) 2000 Kirk Reiser. + + 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 + + Kirk Reiser + 261 Trott dr. London, Ontario, Canada. N6G 1B6 + */ + + +/* These routines are written to control the Apolo serial speech + synthesizer. They are not ment to be thought of as a device driver + in that they do not register themselves as a chr device and there + is no file_operations structure. They are strictly to provide an + interface to the apolo from the speakup screen review package. */ + +#define KERNEL +#include +#include +#include +#include /* for verify_area */ +#include /* for -EBUSY */ +#include /* for loops_per_sec */ +#include /* for put_user_byte */ +#include /* for inb_p, outb_p, inb, outb, etc... */ +#include /* for wait_queue */ +#include /* kd_mksound */ +#include /* for __init */ +#include +#include /* for rs_table, serial constants and + serial_uart_config */ +#include /* for more serial constants */ +#include /* for struct serial_state */ +#include +#include + +#define SYNTH_CLEAR 0x18 +#define PROCSPEECH '\r' +#define SPK_TIMEOUT 100 /* buffer timeout in ms */ +#define NUM_DISABLE_TIMEOUTS 3 /* disable synth if n timeouts */ +/* countdown values for serial timeouts */ +#define SPK_SERIAL_TIMEOUT 1000000 +/* countdown values transmitter/dsr timeouts */ +#define SPK_XMITR_TIMEOUT 1000000 +#define SPK_LO_TTY 0 /* check ttyS0 ... ttyS3 */ +#define SPK_HI_TTY 3 + +static int apolo_alive; + +#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) + +static struct serial_state rs_table[] = { + SERIAL_PORT_DFNS /* Defined in serial.h */ +}; + +static int timeouts; /* sequential number of timeouts */ + +static int wait_for_xmitr(void) +{ + int check, tmout = SPK_XMITR_TIMEOUT; + + if (apolo_alive && timeouts >= NUM_DISABLE_TIMEOUTS) { + apolo_alive = 0; + timeouts = 0; + return 0; + } + + /* holding register empty? */ + do { + check = inb(synth_port_tts + UART_LSR); + if (--tmout == 0) { + printk(KERN_WARNING "APOLO: timed out\n"); + timeouts++; + return 0; + } + } while ((check & BOTH_EMPTY) != BOTH_EMPTY); + + tmout = SPK_XMITR_TIMEOUT; + /* CTS */ + do { + check = inb(synth_port_tts + UART_MSR); + if (--tmout == 0) { + timeouts++; + return 0; + } + } while ((check & UART_MSR_CTS) != UART_MSR_CTS); + + timeouts = 0; + return 1; +} + +static inline int spk_serial_out(const char ch) +{ + if (apolo_alive && synth_port_tts) { + if (wait_for_xmitr()) { + outb(ch, synth_port_tts); + return 1; + } + } + return 0; +} + +static void do_catch_up(unsigned long data) +{ + unsigned long jiff_in = jiffies; + + synth_stop_timer(); + while (synth_sent_bytes < synth_queued_bytes) { + if (!spk_serial_out(*(synth_buffer+synth_sent_bytes))) { + outb(UART_MCR_DTR, synth_port_tts + UART_MCR); + outb(UART_MCR_DTR | UART_MCR_RTS, + synth_port_tts + UART_MCR); + synth_delay(synth_full_time); + return; + } + synth_sent_bytes++; + if (jiffies >= jiff_in + synth_jiffy_delta && + synth_sent_bytes > 10) { + spk_serial_out(PROCSPEECH); + synth_delay(synth_delay_time); + return; + } + } + + synth_sent_bytes = synth_queued_bytes = 0; + spk_serial_out(PROCSPEECH); + synth_timer_active = 0; + + if (waitqueue_active(&synth_sleeping_list)) + wake_up_interruptible(&synth_sleeping_list); +} + +static void synth_write_tts(char ch) +{ + if (!apolo_alive) + return; + if (ch < 0x00) + return; /* don't want unprintable chars */ + if (ch == 0x0a) /* turn lf into to force talking. */ + ch = PROCSPEECH; + if (ch == SYNTH_CLEAR) { /* clear all and wake sleeping */ + spk_serial_out(ch); + if (waitqueue_active(&synth_sleeping_list)) + wake_up_interruptible(&synth_sleeping_list); + synth_timer_active = synth_queued_bytes = synth_sent_bytes = 0; + return; + } + + synth_buffer_add(ch); + + if (!synth_buffering && !synth_timer_active) + synth_delay(synth_trigger_time); +} + +static inline void synth_immediate_tts(const char *buf, short count) +{ + while (count--) + spk_serial_out(*buf++); +} + +static int __init serprobe(int index) +{ + struct serial_state *ser = NULL; + + if (synth_port_tts) { + unsigned char test; + + for (test = 0; test <= SPK_HI_TTY; test++) + if ((rs_table + test)->port == synth_port_tts) { + ser = rs_table + test; + break; + } + } else + ser = rs_table + index; + + if (synth_request_region(ser->port, 8)) + return -1; + + initialize_uart(ser); + /* If we read 0xff from the LSR, there is no UART here. */ + if (inb (ser->port + UART_LSR) == 0xff) { + synth_release_region(ser->port,8); + return -1; + } + outb(0x0d, ser->port); /* wake it up if older BIOS */ + mdelay(1); + + apolo_alive = 1; + if (synth_port_tts) + return 0; + synth_port_tts = ser->port; + + /* check for apolo now... */ + if (spk_serial_out(0x18)) + return 0; + else + printk(KERN_WARNING "port %x failed\n", synth_port_tts); + + synth_release_region(ser->port,8); + timeouts = apolo_alive = synth_port_tts = 0; + return -1; +} + +static int __init synth_dev_probe(void) +{ + int i; + + printk(KERN_INFO "Probing for Apolo.\n"); + if (synth_port_tts) + printk(KERN_INFO "Probe forced to 0x%x by " + "kernel command line\n", synth_port_tts); + for (i = SPK_LO_TTY; i <= SPK_HI_TTY; i++) { + if (serprobe(i) == 0) + break; /* found it */ + } + + if (apolo_alive) { + /* found 'em */ + printk(KERN_INFO "Apolo: %03x-%03x, Driver version %s,\n", + synth_port_tts, synth_port_tts + 7, synth->version); + synth_immediate_tts(synth->init, strlen(synth->init)); + return 0; + } + + printk(KERN_INFO "Apolo: not found\n"); + return -ENODEV; +} + +static int synth_alive(void) +{ + if (apolo_alive) + return 1; /* already on */ + + if (!apolo_alive && synth_port_tts) { + if (wait_for_xmitr() > 0) { /* restart */ + apolo_alive = 1; + synth_write(synth->reinit, strlen(synth->reinit)); + return 2; /* reenabled */ + } + + printk(KERN_INFO "Apolo: can't restart synth\n"); + } + + return 0; +} + +static const char init_string[] = "@R0@D0@K1@W5\rApolo found\r"; +static const char reinit_string[] = "@R0@D0@K1@W5\rApolo Restarted\r"; + +static struct spk_variable vars[] = { + { + .id = "flush", + .param = "\x18", + .build = "_", + .flags = BUILDER | HARD_DIRECT | NO_USER, + .valid = "*", + }, + { + .id = "pitch", + .param = "8", + .build = "@F_", + .flags = HARD_DIRECT, + .valid = "0123456789abcdef", + }, + { + .id = "caps_start", + .param = "cap ", + .build = "_", + .flags = 0, + .valid = "*", + }, + { + .id = "caps_stop", + .param = "", + .build = "_", + .flags = 0, + .valid = "*", + }, + { + .id = "rate", + .param = "5", + .build = "@W_", + .flags = NUMERIC | HARD_DIRECT | USE_RANGE, + .valid = "1,9", + }, + { + .id = "voice", + .param = "1", + .build = "@V_", + .flags = NUMERIC | HARD_DIRECT | USE_RANGE, + .valid = "1,6", + }, + { + .id = "volume", + .param = "A", + .build = "@A_", + .flags = HARD_DIRECT, + .valid = "0123456789abcdef", + }, + { + .id = "language", + .param = "1", + .build = "@=_,", + .flags = NUMERIC | HARD_DIRECT | USE_RANGE, + .valid = "1,4", + }, + { NULL, }, +}; + +static char *config[] = { "\x18", "@F8", "cap ", "", "@W5", + "@V1", "@AA", "@=1,"}; + +struct spk_synth synth_apolo = { + .name = "apolo", + .version = "Version-0.10", + .proc_name = "apolo", + .init = init_string, + .reinit = reinit_string, + .delay_time = 500, + .trigger_time = 50, + .jiffy_delta = 5, + .full_time = 5000, + .vars = vars, + .config = config, + .config_map = 0, + .probe = synth_dev_probe, + .catch_up = do_catch_up, + .write = synth_write_tts, + .is_alive = synth_alive, +}; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/speakup/speakup_audptr.c linux.19rc3-ac4/drivers/char/speakup/speakup_audptr.c --- linux.19rc3/drivers/char/speakup/speakup_audptr.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/speakup/speakup_audptr.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,311 @@ +/* + * speakup_audapter.c for linux kernels 2.2.x and speakup + * + * author: Kirk Reiser and William Acker + + Copyright (C) 1998-2000 Kirk Reiser. + + 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 + + Kirk Reiser + 261 Trott dr. London, Ontario, Canada. N6G 1B6 + */ + + +/* These routines are written to control the audapter serial speech + synthesizer. They are not ment to be thought of as a device driver + in that they do not register themselves as a chr device and there + is no file_operations structure. They are strictly to provide an + interface to the audapter from the speakup screen review package. +*/ + +#define KERNEL +#include +#include +#include +#include /* for verify_area */ +#include /* for -EBUSY */ +#include /* for check_region, request_region */ +#include /* for loops_per_sec */ +#include /* for put_user_byte */ +#include /* for inb_p, outb_p, inb, outb, etc... */ +#include /* for wait_queue */ +#include /* kd_mksound */ +#include /* for __init */ +#include +#include /* for rs_table, serial constants and + serial_uart_config */ +#include /* for more serial constants */ +#if (LINUX_VERSION_CODE >= 0x20332) /* v 2.3.50+ */ +#include /* for struct serial_state */ +#endif +#include +#include + +#define SYNTH_CLEAR 0x18 /* flush synth buffer */ +#define PROCSPEECH '\r' /* start synth processing speech char */ +#define SPK_TIMEOUT 100 /* buffer timeout in ms */ +#define NUM_DISABLE_TIMEOUTS 3 /* disable synth if n timeouts */ +#define SPK_SERIAL_TIMEOUT 1000000 /* countdown values for serial timeouts */ +#define SPK_XMITR_TIMEOUT 1000000 /* countdown values transmitter/dsr timeouts */ +#define SPK_LO_TTY 0 /* check ttyS0 ... ttyS3 */ +#define SPK_HI_TTY 3 + +static int audptr_alive = 0; + +#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) + +static struct serial_state rs_table[] __initdata = { + SERIAL_PORT_DFNS +}; + +static int timeouts = 0; /* sequential number of timeouts */ + +static int wait_for_xmitr(void) +{ +int check, tmout = SPK_XMITR_TIMEOUT; + + if ((audptr_alive) && (timeouts >= NUM_DISABLE_TIMEOUTS)) { + audptr_alive = 0; + timeouts = 0; + return 0; + } + + /* holding register empty? */ + do { + check = inb(synth_port_tts + UART_LSR); + if (--tmout == 0) { + printk("Audapter: timed out\n"); + timeouts++; + return 0; + } + } while ((check & BOTH_EMPTY) != BOTH_EMPTY); + + tmout = SPK_XMITR_TIMEOUT; + /* CTS */ + do { + check = inb(synth_port_tts + UART_MSR); + if (--tmout == 0) { + timeouts++; + return 0; + } + } while ((check & UART_MSR_CTS) != UART_MSR_CTS); + + timeouts = 0; + return 1; +} + +static inline int spk_serial_out(const char ch) +{ + if (audptr_alive && synth_port_tts) { + if (wait_for_xmitr()) { + outb(ch, synth_port_tts); + return 1; + } + } + return 0; +} + +static unsigned char __init spk_serial_in(void) +{ +int c, lsr, tmout = SPK_SERIAL_TIMEOUT; + + do { + lsr = inb(synth_port_tts + UART_LSR); + if (--tmout == 0) return 0xff; + } while (!(lsr & UART_LSR_DR)); + c = inb(synth_port_tts + UART_RX); + return (unsigned char) c; +} + +static void do_catch_up(unsigned long data) +{ + unsigned long jiff_in = jiffies; + +synth_stop_timer(); + while (synth_sent_bytes < synth_queued_bytes) + { + if (!spk_serial_out(*(synth_buffer+synth_sent_bytes))) { + synth_delay(synth_full_time); + return; + } + synth_sent_bytes++; + if ((jiffies >= jiff_in+synth_jiffy_delta && *(synth_buffer+synth_sent_bytes-1) == ' ') + || (jiffies > jiff_in+HZ/10)) { + spk_serial_out(PROCSPEECH); + synth_delay(synth_delay_time); + return; + } + } + +synth_sent_bytes = synth_queued_bytes = 0; +synth_timer_active = 0; +spk_serial_out(PROCSPEECH); +if (waitqueue_active(&synth_sleeping_list)) + wake_up_interruptible(&synth_sleeping_list); +} + +static inline void clear_it(char ch) +{ + while ((inb(synth_port_tts + UART_LSR) & BOTH_EMPTY) != BOTH_EMPTY); + outb(ch, synth_port_tts); +} + +static void synth_write_tts(char ch) +{ + if (!audptr_alive) return; + if (ch < 0x00) return; /* don't want unprintable chars */ + if (ch == 0x0a) /* turn lf into to force talking. */ + ch = '\r'; + if (ch == SYNTH_CLEAR) /* clear all and wake sleeping */ + { + clear_it(ch); + spk_serial_out(PROCSPEECH); + if (waitqueue_active(&synth_sleeping_list)) + wake_up_interruptible(&synth_sleeping_list); + synth_timer_active = synth_queued_bytes = synth_sent_bytes = 0; + return; + } + +synth_buffer_add(ch); +if (synth_buffering) return; +if (synth_timer_active == 0) synth_delay( synth_trigger_time ); +} + +static inline void synth_immediate_tts(const char *buf, short count) +{ + while (count--) spk_serial_out(*buf++); +return; +} + +static char synth_id[40] = ""; + +static int __init serprobe(int index) +{ + struct serial_state *ser = NULL; + unsigned char test=0; + + if (synth_port_tts) { + for (test=0; test <= SPK_HI_TTY; test++) + if ( (rs_table+test)->port == synth_port_tts) { + ser = rs_table+test; + break; + } + } else ser = rs_table + index; + + if (synth_request_region(ser->port,8)) + return -1; + + initialize_uart(ser); + /* If we read 0xff from the LSR, there is no UART here. */ + if (inb (ser->port + UART_LSR) == 0xff) { + synth_release_region(ser->port,8); + return -1; + } + mdelay(1); + + audptr_alive = 1; + /* ignore any error results, if port was forced */ + if (synth_port_tts) + return 0; + + synth_port_tts = ser->port; + test = 0; + spk_serial_out(0x05); + spk_serial_out('['); + spk_serial_out('Q'); /* query command */ + spk_serial_out(']'); /* close the query. */ + + if ((synth_id[test] = spk_serial_in()) == 'A') { + do { /* read version string from synth */ + synth_id[++test] = spk_serial_in(); + } while (synth_id[test] != '\n' && test < 32); + synth_id[++test] = 0x00; + if (test != 32) + return 0; + } + + synth_release_region(ser->port,8); + timeouts = audptr_alive = synth_port_tts = 0; /* not ignoring */ + return -1; +} + +static int __init synth_dev_probe(void) +{ +int i=0; + + printk("Probing for Audapter.\n"); + if (synth_port_tts != 0) /* set from commandline */ + printk("Probe forced to 0x%x by kernel command line.\n",synth_port_tts); + + for (i=SPK_LO_TTY; i <= SPK_HI_TTY; i++) { + if (serprobe(i) == 0) break; /* found it */ + } + + if (audptr_alive) { + /* found 'em */ + printk("Audapter: %03x-%03x, Driver %s,\n", + synth_port_tts, synth_port_tts + 7, synth->version); + if (synth_id[0] == 'A') + printk("Audapter version: %s", synth_id); + synth_immediate_tts(synth->init, strlen(synth->init)); + return 0; + } + + printk("Audapter: not found\n"); + return -ENODEV; +} + + /* this is a new function required by speakup: + * if synth is not active, make it active and return 2 + * if synth is already active, return 1 + * otherwise (if it can't be made active), return 0 + */ +static int synth_alive(void) +{ + if (audptr_alive) + return 1; /* already on */ + else if ((!audptr_alive) && (synth_port_tts)) { + if (wait_for_xmitr() > 0) { /* restart */ + audptr_alive = 1; + synth_write(synth->reinit, strlen(synth->reinit)); + return 2; /* reenabled */ + } else printk("Audapter: can't restart synth\n"); + } + return 0; +} + +static const char init_string[] = "\x05[An]\x05[D1]\x05[Ol]Audapter found\r"; +static const char reinit_string[] = "\x05[An]\x05[D1]\x05[Ol]Audapter found\r"; + +static struct spk_variable vars[] = +{{"flush", "\x18\x20", "_", (BUILDER|HARD_DIRECT|NO_USER), "*"}, + {"pitch", "80", "\x05[f_]", (NUMERIC|HARD_DIRECT|USE_RANGE), "39,4500"}, + {"caps_start", "\x05[f99]", "_", 0, "*"}, + {"caps_stop", "\x05[f80]", "_", 0, "*"}, + {"rate", "0", "\x05[r_]", (NUMERIC|HARD_DIRECT|USE_RANGE), "-100,100"}, + {"tone", "9", "\x05[s_]", (NUMERIC|HARD_DIRECT|USE_RANGE), "0,63"}, + {"volume", "21", "\x05[g_]", (NUMERIC|HARD_DIRECT|USE_RANGE), "0,40"}, + {"punct", "n", "\x05[A_]", HARD_DIRECT, "nmsa"}, + END_VARS}; + +static char *config[] = +{"\x18\x20", "\x05[f80]", "\x05[f99]", "\x05[f80]", "\x05[r0]", "\x05[s9]", + "\x05[g21]", "\x05[An]"}; + +struct spk_synth synth_audptr = {"audptr", "Version-0.13", "audapter", + init_string, reinit_string, 400, 5, 3, 5000, + vars, config, 0, synth_dev_probe, do_catch_up, + synth_write_tts, synth_alive}; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/speakup/speakup_bns.c linux.19rc3-ac4/drivers/char/speakup/speakup_bns.c --- linux.19rc3/drivers/char/speakup/speakup_bns.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/speakup/speakup_bns.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,286 @@ +/* + * speakup_bns.c for linux kernels 2.2.x and speakup + * + * author: Kirk Reiser + + Copyright (C) 1998-99 Kirk Reiser. + + 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 + + Kirk Reiser + 261 Trott dr. London, Ontario, Canada. N6G 1B6 + */ + + +/* These routines are written to control the Braille 'n Speak serial + speech synthesizer in speech box mode. They are not ment to be + thought of as a device driver in that they do not register + themselves as a chr device and there is no file_operations + structure. They are strictly to provide an interface to the bns + from the speakup screen review package. */ + +#define KERNEL +#include +#include +#include +#include /* for verify_area */ +#include /* for -EBUSY */ +#include /* for check_region, request_region */ +#include /* for loops_per_sec */ +#include /* for put_user_byte */ +#include /* for inb_p, outb_p, inb, outb, etc... */ +#include /* for wait_queue */ +#include /* kd_mksound */ +#include /* for __init */ +#include +#include /* for rs_table, serial constants and + serial_uart_config */ +#include /* for more serial constants */ +#if (LINUX_VERSION_CODE >= 0x20300) /* v 2.3.50+ */ +#include /* for struct serial_state */ +#endif +#include +#include + +#define SYNTH_CLEAR 0x18 +#define SPK_TIMEOUT 100 /* buffer timeout in ms */ +#define NUM_DISABLE_TIMEOUTS 3 /* disable synth if n timeouts */ +#define SPK_SERIAL_TIMEOUT 1000000 /* countdown values for serial timeouts */ +#define SPK_XMITR_TIMEOUT 1000000 /* countdown values transmitter/dsr timeouts */ +#define SPK_LO_TTY 0 /* check ttyS0 ... ttyS3 */ +#define SPK_HI_TTY 3 +#define PROCSPEECH '\r' /* process speech char */ + +static int bns_alive = 0; + +#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) + +static struct serial_state rs_table[] = { + SERIAL_PORT_DFNS /* Defined in serial.h */ +}; + +static int wait_for_xmitr(void) +{ +static int timeouts = 0; /* sequential number of timeouts */ +int check, tmout = SPK_XMITR_TIMEOUT; + + if ((bns_alive) && (timeouts >= NUM_DISABLE_TIMEOUTS)) { + bns_alive = 0; + timeouts = 0; + return 0; + } + + /* holding register empty? */ + do { + check = inb(synth_port_tts + UART_LSR); + if (--tmout == 0) { + printk("BNS: timed out\n"); + timeouts++; + return 0; + } + } while ((check & BOTH_EMPTY) != BOTH_EMPTY); + + tmout = SPK_XMITR_TIMEOUT; + /* CTS */ + do { + check = inb(synth_port_tts + UART_MSR); + if (--tmout == 0) { + timeouts++; + return 0; + } + } while ((check & UART_MSR_CTS) != UART_MSR_CTS); + + timeouts = 0; + return 1; +} + +static inline int spk_serial_out(const char ch) +{ + if (bns_alive && synth_port_tts) { + if (wait_for_xmitr()) { + outb(ch, synth_port_tts); + return 1; + } + } + return 0; +} + +#if 0 +static unsigned char __init spk_serial_in(void) +{ +int c, lsr, tmout = SPK_SERIAL_TIMEOUT; + + do { + lsr = inb(synth_port_tts + UART_LSR); + if (--tmout == 0) return 0xff; + } while (!(lsr & UART_LSR_DR)); + c = inb(synth_port_tts + UART_RX); + return (unsigned char) c; +} +#endif + +static void do_catch_up(unsigned long data) +{ + unsigned long jiff_in = jiffies; + +synth_stop_timer(); + while (synth_sent_bytes < synth_queued_bytes) + { + if (!spk_serial_out(*(synth_buffer+synth_sent_bytes))) { + synth_delay(synth_full_time); + return; + } + synth_sent_bytes++; + if (jiffies >= jiff_in+synth_jiffy_delta && *(synth_buffer+synth_sent_bytes-1) == ' ') + { + spk_serial_out(PROCSPEECH); + synth_delay(synth_delay_time); + return; + } + } + +synth_sent_bytes = synth_queued_bytes = 0; +spk_serial_out(PROCSPEECH); +synth_timer_active = 0; +if (waitqueue_active(&synth_sleeping_list)) + wake_up_interruptible(&synth_sleeping_list); +} + +static void synth_write_tts(char ch) +{ + if (!bns_alive) return; + if (ch < 0x00) return; /* don't want unprintable chars */ + if (ch == 0x0a) /* turn lf into to force talking. */ + ch = PROCSPEECH; + if (ch == SYNTH_CLEAR) /* clear all and wake sleeping */ + { + spk_serial_out(ch); + if (waitqueue_active(&synth_sleeping_list)) + wake_up_interruptible(&synth_sleeping_list); + synth_timer_active = synth_queued_bytes = synth_sent_bytes = 0; + return; + } + +synth_buffer_add(ch); +if (synth_buffering) return; +if (synth_timer_active == 0) synth_delay( synth_trigger_time ); +return; +} + +static inline void synth_immediate_tts(const char *buf, short count) +{ + while (count--) spk_serial_out(*buf++); +return; +} + +static int __init serprobe(int index) +{ + struct serial_state *ser = NULL; + unsigned char test=0; + + if (synth_port_tts) { + for (test=0; test <= SPK_HI_TTY; test++) + if ( (rs_table+test)->port == synth_port_tts) { + ser = rs_table+test; + break; + } + } else ser = rs_table + index; + + if (synth_request_region(ser->port,8)) + return -1; + + initialize_uart(ser); + /* If we read 0xff from the LSR, there is no UART here. */ + if (inb (ser->port + UART_LSR) == 0xff) { + synth_release_region(ser->port,8); + return -1; + } + mdelay(1); + outb('\r', ser->port); + + bns_alive = 1; + if (synth_port_tts) return 0; + synth_port_tts = ser->port; + + /* check for bns now... */ + if (spk_serial_out(SYNTH_CLEAR)) return 0; + /*spk_serial_out('\r'); * flush buffer for safety * + spk_serial_out(0x06); + mdelay(10); + if (spk_serial_in() == 0x06) return 0;*/ + + synth_release_region(ser->port,8); + bns_alive = synth_port_tts = 0; + return -1; +} + +static int __init synth_dev_probe(void) +{ +int i; + + printk("Probing for Braille 'N Speak.\n"); + if (synth_port_tts) + printk("Probe forced to 0x%x by kernel command line\n", synth_port_tts); + for (i=SPK_LO_TTY; i <= SPK_HI_TTY; i++) { + if (serprobe(i) == 0) break; /* found it */ + } + + if (bns_alive) { + /* found 'em */ + printk("Braille 'N Speak: %03x-%03x, Driver version %s,\n", + synth_port_tts, synth_port_tts + 7, synth->version); + synth_immediate_tts(synth->init, strlen(synth->init)); + return 0; + } + + printk("Braille 'N Speak: not found\n"); + return -ENODEV; +} + +static int synth_alive(void) +{ + if (bns_alive) + return 1; /* already on */ + else if ((!bns_alive) && (synth_port_tts)) { + if (wait_for_xmitr() > 0) { /* restart */ + bns_alive = 1; + synth_write(synth->reinit, strlen(synth->reinit)); + return 2; /* reenabled */ + } else printk("Braille 'N Speak: can't restart synth\n"); + } + return 0; +} + +static const char init_string[] = "\x05Z\x05\x38P\x05\x43 Braille 'n Speak found\r"; +static const char reinit_string[] = "\x05Z\x05\x38P\x05\x43 Braille 'N Speak initialized\r"; + +static struct spk_variable vars[] = +{{"flush", "\x18", "_", (BUILDER|HARD_DIRECT|NO_USER), "*"}, + {"pitch", "8", "\x05_P", (NUMERIC|HARD_DIRECT|USE_RANGE), "0,16"}, + {"caps_start", "\x05\x31\x32P", "_", 0, "*"}, + {"caps_stop", "\x05\x38P", "_", 0, "*"}, + {"rate", "8", "\x05_E", (NUMERIC|HARD_DIRECT|USE_RANGE), "1,16"}, + {"tone", "8", "\x05_T", (NUMERIC|HARD_DIRECT|USE_RANGE), "0,16"}, + {"volume", "8", "\x05_V", (NUMERIC|HARD_DIRECT|USE_RANGE), "0,16"}, + END_VARS}; + +static char *config[] = +{"\x18", "\x05\x38P", "\x05\x31\x32P", "\x05\x38P", "\x05\x38\x45", + "\x05\x38T", "\x05\x38V"}; + +struct spk_synth synth_bns = {"bns", "Version-0.10", "bns", + init_string, reinit_string, 500, 50, 5, 5000, + vars, config, 0, synth_dev_probe, do_catch_up, + synth_write_tts, synth_alive}; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/speakup/speakup.c linux.19rc3-ac4/drivers/char/speakup/speakup.c --- linux.19rc3/drivers/char/speakup/speakup.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/speakup/speakup.c 2002-07-29 17:45:38.000000000 +0100 @@ -0,0 +1,2246 @@ +/* speakup.c + review functions for the speakup screen review package. + written by: Kirk Reiser and Andy Berdan. + + Thanks to Barry Pollock for the more responsive diacritical code. + + Thanx eternal to Jim Danley for help with the extended codepage 437 + character array! Very nice job on the /proc file system entries as + well. + + Thanks also to Matt Campbell for a fine job on the driver code + building in the ability to include a number of drivers in at the + same time. + + Copyright (C) 1998 Kirk Reiser. + + 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 + + Kirk Reiser + 261 Trott dr. London, Ontario, Canada. N6G 1B6 */ + +#define __KERNEL_SYSCALLS__ +#include + +#include +#include +#include +#include +#include +#include /* __get_free_page() and friends */ +#include +#include +#include +#include +#include /* copy_from|to|user() and others */ +#include +#include /* for mdelay() */ +#include /* for __init */ +#include /* for misc_register, and SYNTH_MINOR */ + +#ifdef CONFIG_PROC_FS +#include +#endif + +#include +#include /* for alloc_bootmem */ + +#include "../console_macros.h" /* for x, y, attr and pos macros */ +#include /* for KT_SHIFT */ +#include /* for vc_kbd_* and friends */ +#include +#include +#include +#include + +#include /* for isdigit() and friends */ +#include +#include "symbols.h" + + +#define SPEAKUP_VERSION "Speakup v-1.00" + +/* these are globals from the kernel code */ +extern void *kmalloc (size_t, int); +extern void kfree (const void *); +extern struct tty_struct *tty; +extern int fg_console; + +/* These are ours from synth drivers. */ +extern void proc_speakup_synth_init (void); // init /proc synth-specific subtree +#ifdef CONFIG_SPEAKUP_ACNTPC +extern struct spk_synth synth_acntpc; +#endif +#ifdef CONFIG_SPEAKUP_ACNTSA +extern struct spk_synth synth_acntsa; +#endif +#ifdef CONFIG_SPEAKUP_APOLO +extern struct spk_synth synth_apolo; +#endif +#ifdef CONFIG_SPEAKUP_AUDPTR +extern struct spk_synth synth_audptr; +#endif +#ifdef CONFIG_SPEAKUP_BNS +extern struct spk_synth synth_bns; +#endif +#ifdef CONFIG_SPEAKUP_DECEXT +extern struct spk_synth synth_decext; +#endif +#ifdef CONFIG_SPEAKUP_DECTLK +extern struct spk_synth synth_dectlk; +#endif +#ifdef CONFIG_SPEAKUP_DTLK +extern struct spk_synth synth_dtlk; +#endif +#ifdef CONFIG_SPEAKUP_LTLK +extern struct spk_synth synth_ltlk; +#endif +#ifdef CONFIG_SPEAKUP_SPKOUT +extern struct spk_synth synth_spkout; +#endif +#ifdef CONFIG_SPEAKUP_TXPRT +extern struct spk_synth synth_txprt; +#endif + +#define MIN(a,b) ( ((a) < (b))?(a):(b) ) +#define krealloc(ptr,newsize) ( kfree(ptr), ptr = kmalloc(newsize,GFP_KERNEL) ) +#define toctrl(x) ( ( ((x) >= 'A') && ((x) <='Z')) ? ((x) - 'A') : \ + (((x) >= 'a') && ((x) <= 'z')) ? ((x) - 'a') : 0 ) +#define allowable(c) ( ((c) > 0x2f && (c) < 0x3a) \ + || (((c)&0x5f) > 0x40 && ((c)&0x5f) < 0x5b) \ + || (strchr(" \n,.'-:?!", (c)) != NULL) \ + ) + +static int errno; +char *spk_cfg[] = { DEFAULT_SPKUP_VARS }; +long spk_cfg_map; /* which ones have been re'alloc'ed */ +int synth_file_inuse; +static struct spk_variable spk_vars[] = { SPKUP_VARS }; +static unsigned char pitch_shift; +char saved_punc_level = 0x30; +char mark_cut_flag; +unsigned short mark_x; +unsigned short mark_y; +static char synth_name[10] = CONFIG_SPEAKUP_DEFAULT; +static struct spk_synth *synths[] = { +#ifdef CONFIG_SPEAKUP_ACNTPC + &synth_acntpc, +#endif +#ifdef CONFIG_SPEAKUP_ACNTSA + &synth_acntsa, +#endif +#ifdef CONFIG_SPEAKUP_APOLO + &synth_apolo, +#endif +#ifdef CONFIG_SPEAKUP_AUDPTR + &synth_audptr, +#endif +#ifdef CONFIG_SPEAKUP_BNS + &synth_bns, +#endif +#ifdef CONFIG_SPEAKUP_DECEXT + &synth_decext, +#endif +#ifdef CONFIG_SPEAKUP_DECTLK + &synth_dectlk, +#endif +#ifdef CONFIG_SPEAKUP_DTLK + &synth_dtlk, +#endif +#ifdef CONFIG_SPEAKUP_LTLK + &synth_ltlk, +#endif +#ifdef CONFIG_SPEAKUP_SPKOUT + &synth_spkout, +#endif +#ifdef CONFIG_SPEAKUP_TXPRT + &synth_txprt, +#endif + NULL, /* Leave room for one dynamically registered synth. */ + NULL +}; + +#define LineWrapBleep 0x01 +#define LineWrapMask 0xFE +#define AttributeChangeBleep 0x02 +#define AttributeChangeMask 0xFD + +#define punc_level (*(spk_cfg[PUNCT_LEVEL])) +#define spell_delay (*(spk_cfg[SPELL_DELAY])-0x30) +#define key_echo (*(spk_cfg[KEY_ECHO])-0x30) + +/* how about a couple of arrays to index our colours and attributes */ +char *fg_color[] = { + "black", "blue", "green", "cyan", "red", "magenta", "yellow", "white", + "grey", "bright blue", "bright green", "bright cyan", "bright red", + "bright magenta", "bright yellow", "bright white" +}; + +char *bg_color[] = { + "black", "blue", "green", "cyan", "red", "magenta", "yellow", "white", + "blinking black", "blinking blue", "blinking green", "blinking cyan", + "blinking red", "blinking magenta", "blinking yellow", "blinking white" +}; + +char *phonetic[] = { + "alpha", "beta", "charley", "delta", "echo", "fox", "gamma", "hotel", + "india", "juleiet", "keelo", "leema", "mike", "november", "oscar", + "papa", + "quebec", "romeo", "seeara", "tango", "uniform", "victer", "wiskey", + "x ray", + "yankee", "zooloo" +}; + +// array of 256 char pointers (one for each ASCII character description) +// initialized to default_chars and user selectable via /proc/speakup/characters +char *characters[256]; + +char *default_chars[256] = { + "null", "control-a", "control-b", "control-c", "control-d", "control-e", + "control-f", "control-g", "control-h", "control-i", "control-j", + "control-k", + "control-l", "control-m", "control-n", "control-o", "control-p", + "control-q", + "control-r", "control-s", "control-t", "control-u", "control-v", + "control-w", + "control-x", "control-y", "control-z", NULL, NULL, NULL, NULL, NULL, + "space", "bang!", "quote", "number", "dollars", "percent", "and", + "tick", + "left paren", "right paren", "star", "plus", "comma,", "dash", "dot", + "slash", + "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", + "nine", + "colon", "semi", "less", "equals", "greater", "question?", "at", "eigh", + "b", + "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", + "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", + "y", "zehd", "left bracket", "backslash", "right bracket", "caret", + "line", + "accent", "eigh", "b", "c", "d", "e", "f", "g", "h", "i", "j", + "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", + "v", "w", "x", "y", "zehd", "left brace", "bar", "right brace", + "tihlduh", "cap delta", "cap see cedilla", "u oomlout", "e acute", + "eigh circumflex", "eigh oomlout", "eigh grave", "eigh ring", + "see cedilla", + "e circumflex", "e oomlout", "e grave", "i oomlout", "i circumflex", + "i grave", "cap eigh oomlout", "cap eigh ring", "cap e acute", + "eigh e dipthong", "cap eigh cap e dipthong", "o circumflex", + "o oomlout", + "o grave", "u circumflex", "u grave", "y oomlout", "cap o oomlout", + "cap u oomlout", "cents", "pounds", "yen", "peseta", "florin", + "eigh acute", + "i acute", "o acute", "u acute", "n tilde", "cap n tilde", + "feminine ordinal", + "masculin ordinal", "inverted question", + "reversed not", "not", "half", "quarter", "inverted bang", + "much less than", "much greater than", "dark shading", "medium shading", + "light shading", "verticle line", "left tee", "double left tee", + "left double tee", "double top right", "top double right", + "double left double tee", "double vertical line", + "double top double right", + "double bottom double right", "double bottom right", + "bottom double right", + "top right", "left bottom", "up tee", "tee down", "tee right", + "horizontal line", "cross bars", "tee double right", "double tee right", + "double left double bottom", "double left double top", + "double up double tee", + "double tee double down", "double tee double right", + "double horizontal line", + "double cross bars", "up double tee", "double up tee", + "double tee down", + "tee double down", "double left bottom", "left double bottom", + "double left top", "left double top", "double vertical cross", + "double horizontal cross", "bottom right", "left top", "solid square", + "solid lower half", "solid left half", "solid right half", + "solid upper half", + "alpha", "beta", "cap gamma", "pie", "cap sigma", "sigma", "mu", "tou", + "cap phigh", "cap thayta", "cap ohmega", "delta", "infinity", "phigh", + "epsilaun", "intersection", "identical to", "plus or minus", + "equal grater than", "less than equal", "upper integral", + "lower integral", + "divided by", "almost equal", "degrees", "centre dot", + "bullet", "square root", "power", "squared", "black square", + "white space" +}; + +int spk_keydown; +int bell_pos; +static int spk_lastkey; + +struct spk_t *speakup_console[MAX_NR_CONSOLES]; + +int spk_setup (char *str) +{ + int ints[4]; + str = get_options (str, ARRAY_SIZE (ints), ints); + if (ints[0] > 0 && ints[1] >= 0) + synth_port_tts = ints[1]; + return 1; +} + +int spk_ser_setup (char *str) +{ + int lookup[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; + int ints[4]; + str = get_options (str, ARRAY_SIZE (ints), ints); + if (ints[0] > 0 && ints[1] >= 0) + synth_port_tts = lookup[ints[1]]; + return 1; +} + +int spk_synth_setup (char *str) +{ + size_t len = MIN (strlen (str), 9); + memcpy (synth_name, str, len); + synth_name[len] = '\0'; + return 1; +} + +__setup ("speakup_port=", spk_setup); +__setup ("speakup_ser=", spk_ser_setup); +__setup ("speakup_synth=", spk_synth_setup); + +void speakup_savekey (unsigned char ch) +{ + /* keydown is seperate since they are handled by two + seperate routines */ + if (ch) + spk_keydown++; + else + spk_keydown = 0; + // keypad slash key is not calling this function as it should -- jd + spk_lastkey = ch; +} + +static void spk_control (int currcons, int value) +{ + if (spk_shut_up || (synth == NULL)) + return; + /* interrupt active + not shut up + not shift key (value == 0) */ + if ((*spk_cfg[NO_INTERRUPT] - 0x30) && value) { + synth_write (synth->config[FLUSH], + strlen (synth->config[FLUSH])); + synth_write (synth->config[PITCH], + strlen (synth->config[PITCH])); + } + + if ((*spk_cfg[SAY_CONTROL] - 0x30 == 0) && (value < 4)) + return; + switch (value) { + case 0: + spkup_write ("shift\n", 6); + break; + case 1: + spkup_write ("insert\n", 7); + break; + case 2: + spkup_write ("control\n", 8); + break; + case 3: + spkup_write ("ault\n", 5); + break; + + case 10: + spkup_write ("caps lock on\n", 13); + break; + case 11: + spkup_write ("caps lock off\n", 14); + break; + case 12: + spkup_write ("numm lock on\n", 13); + break; + case 13: + spkup_write ("numm lock off\n", 14); + break; + case 14: + spkup_write ("scroll lock on\n", 15); + break; + case 15: + spkup_write ("scroll lock off\n", 16); + break; + } +} + +static void s2i (char *start, int length, int *dest) +{ + int i; + for (i = 0; i < length; i++) { + *dest *= 10; + *dest += start[i] - 0x30; + } +} + +static inline void bleep (unsigned short val) +{ + int time = 0; + val = (val + 1) * 75 + 75; + time = *(spk_cfg[BLEEP_TIME]) - 0x30; + if (*(spk_cfg[BLEEP_TIME] + 1) != '\0') { + time *= 10; + time += (*(spk_cfg[BLEEP_TIME] + 1) - 0x30); + } + kd_mksound (val, time); +} + +void speakup_reset (int currcons, unsigned char type) +{ + + spk_shut_up &= 0xfe; + if (spk_killed) + return; + spk_parked &= 0xfe; + if (*(spk_cfg[NO_INTERRUPT]) - 0x30) + return; + spk_keydown++; + + if (synth == NULL) + return; + synth_write (synth->config[FLUSH], strlen (synth->config[FLUSH])); + if (pitch_shift) { + synth_write (synth->config[PITCH], + strlen (synth->config[PITCH])); + pitch_shift = 0; + } +} + +void speakup_shut_up (unsigned int currcons) +{ + spk_shut_up |= 0x01; + speakup_date (currcons); + if (synth == NULL) + return; + synth_write (synth->config[FLUSH], strlen (synth->config[FLUSH])); + synth_write (synth->config[PITCH], strlen (synth->config[PITCH])); +} + +int speakup_diacr (unsigned char ch, unsigned int currcons) +{ + static unsigned char *buf = "\0\0\0\0\0"; + static int num; + int tmp = 0; + + buf[num++] = ch; + buf[num] = '\0'; + + if ((ch == '$' || ch == 27 || (ch > 47 && ch < 58) || ch == 'x' + || ch == 'y' || ch == '+' || ch == '-') && num < 5) + switch (ch) { + case '$': + case 0x1b: /* cancel */ + num = 0; + buf[0] = '\0'; + return 1; + case 'x': + case 'y': + if (buf[0] == '+' || buf[0] == '-') { + s2i (buf + 1, num - 2, &tmp); + tmp = (buf[0] == '+') ? tmp : -tmp; + + /* set tmp to new position */ + if (ch == 'x') + tmp = tmp + spk_x; + else + tmp = tmp + spk_y; + } else { + s2i (buf, num - 1, &tmp); + --tmp; + } + + /* range checking */ + if (ch == 'x') { + if (tmp > video_num_columns) + tmp = video_num_columns; + if (tmp < 0) + tmp = 0; + } else { + if (tmp > video_num_lines) + tmp = video_num_lines; + if (tmp < 0) + tmp = 0; + } + + /* move it, baby... */ + if (ch == 'x') { + spk_pos -= spk_x * 2; + /* set x */ + spk_x = tmp; + spk_pos += tmp * 2; + } else { + /* zero y */ + spk_pos -= spk_y * video_size_row; + /* set y */ + spk_y = tmp; + spk_pos += tmp * video_size_row; + } + num = 0; + buf[0] = '\0'; + return 1; /* no more characters req'd */ + } else { + /* no valid terminator characters or wrong key */ + num = 0; + buf[0] = '\0'; + if (!spk_killed) + spkup_write ("Error\n", 6); + return -1; + } + return 0; /* I want more! */ +} + +void speakup_kill (unsigned int currcons) +{ + if (spk_killed) { /* dead */ + spk_shut_up &= ~0x40; + spkup_write ("Eyem a Lighve!\n", 15); + } else { + spkup_write ("You killed speak up!\n", 21); + spk_shut_up |= 0x40; + } +} + +void speakup_off (unsigned int currcons) +{ + char val = 0; + + if (spk_shut_up & 0x40) + return; /* if speech is killed don't bother. */ + if ((synth == NULL) || (val = synth->is_alive ())) { + /* re-enables synth, if disabled */ + if (spk_shut_up & 0x80 || (val == 2)) { + spk_shut_up &= 0x7f; + spkup_write ("hey. That's better!\n", 20); + } else { + spk_shut_up |= 0x80; + spkup_write ("You turned me off!\n", 19); + } + } + speakup_date (currcons); +} + +void function_announce (unsigned int currcons) +{ + if (spk_sound & 0x40) { + spk_sound &= 0xbf; + spkup_write ("Function announce off.\n", 23); + } else { + spk_sound |= 0x40; + spkup_write ("Function announce on.\n", 22); + } +} + +void speakup_parked (unsigned int currcons) +{ + if (spk_parked & 0x80) { + spk_parked = 0; + spkup_write ("unparked!\n", 10); + } else { + spk_parked |= 0x80; + spkup_write ("parked!\n", 8); + } +} + +void speakup_cursoring (unsigned int currcons) +{ + if (spk_shut_up & 0x02) { + spk_shut_up &= 0xfd; + spkup_write ("cursoring off!\n", 15); + } else { + spk_shut_up |= 0x02; + spkup_write ("cursoring on!\n", 14); + } +} + +void speakup_cut (unsigned int currcons, struct tty_struct *tty) +{ + int ret; + unsigned char args[6*sizeof(short)]; + unsigned short *arg; + static char *buf = "speakup_cut: set_selection failed: "; + + if (mark_cut_flag) { + /* cut */ + arg = (unsigned short *)args + 1; + arg[0] = mark_x + 1; + arg[1] = mark_y + 1; + arg[2] = (unsigned short)spk_x + 1; + arg[3] = (unsigned short)spk_y + 1; + arg[4] = 0; /* char-by-char selection */ + mark_cut_flag = 0; + spkup_write ("cut\n", 4); + + if ((ret = set_selection ((const unsigned long)args+sizeof(short)-1, tty, 0))) { + switch (ret) { + case -EFAULT : + printk(KERN_WARNING "%sEFAULT\n", buf); + break; + case -EINVAL : + printk(KERN_WARNING "%sEINVAL\n", buf); + break; + case -ENOMEM : + printk(KERN_WARNING "%sENOMEM\n", buf); + break; + } + } + } else { + /* mark */ + mark_cut_flag = 1; + mark_x = spk_x; + mark_y = spk_y; + spkup_write ("mark\n", 5); + clear_selection(); + } +} + +void speakup_paste (struct tty_struct *tty) +{ + spkup_write ("paste\n", 6); + paste_selection (tty); +} + +void say_attributes (int currcons) +{ + char buf[80], cnt; + + if (synth == NULL) + return; + spk_parked |= 0x01; + cnt = sprintf (buf, "%s on %s\n", *(fg_color + (spk_attr & 0x0f)), + *(bg_color + (spk_attr >> 4))); + synth_write (buf, cnt); +} + +void say_curr_char (unsigned int currcons) +{ + unsigned short ch; + char buf[128]; + + if (synth == NULL) + return; + spk_parked |= 0x01; + spk_old_attr = spk_attr; + ch = scr_readw ((unsigned short *) spk_pos); + spk_attr = ((ch & 0xff00) >> 8); + if (spk_attr != spk_old_attr && spk_sound & AttributeChangeBleep) + bleep (spk_y); + if ((ch & 0x00ff) > 0x40 && (ch & 0x00ff) < 0x5b) { + pitch_shift++; + ch = sprintf (buf, "%s %s %s", synth->config[CAPS_START], + characters[(unsigned char) ch], + synth->config[CAPS_STOP]); + } else + ch = sprintf (buf, " %s ", characters[(unsigned char) ch]); + synth_write (buf, ch); +} + +void say_phonetic_char (unsigned int currcons) +{ + unsigned short ch; + char buf[64]; + + if (synth == NULL) + return; + spk_parked |= 0x01; + spk_old_attr = spk_attr; + ch = scr_readw ((unsigned short *) spk_pos); + spk_attr = ((ch & 0xff00) >> 8); + if ((ch & 0x00ff) > 0x40 && (ch & 0x00ff) < 0x5b) + ch = ((ch - 0x41) & 0x00ff); + else if ((ch & 0x00ff) > 0x60 && (ch & 0x00ff) < 0x7b) + ch = ((ch - 0x61) & 0x00ff); + else { + say_curr_char (currcons); + return; + } + ch = sprintf (buf, "%s\n", *(phonetic + ch)); + synth_write (buf, ch); +} + +void say_prev_char (unsigned int currcons) +{ + spk_parked |= 0x01; + if (spk_x == 0) { + spkup_write ("left edge\n", 10); + return; + } + spk_x--; + spk_pos -= 2; + say_curr_char (currcons); +} + +void say_next_char (unsigned int currcons) +{ + spk_parked |= 0x01; + if (spk_x == video_num_columns - 1) { + spkup_write ("right edge\n", 11); + return; + } + spk_x++; + spk_pos += 2; + say_curr_char (currcons); +} + +void say_curr_word (unsigned int currcons) +{ + unsigned long cnt = 0, tmpx = 0, tmp_pos = spk_pos; + char buf[video_num_columns + 2]; + + spk_parked |= 0x01; + spk_old_attr = spk_attr; + tmpx = spk_x; + if (((char) scr_readw ((unsigned short *) tmp_pos) == 0x20) + && ((char) scr_readw ((unsigned short *) tmp_pos + 1) > 0x20)) { + tmp_pos += 2; + tmpx++; + } else + while ((tmpx > 0) + && ((scr_readw ((unsigned short *) tmp_pos - 1) & 0x00ff) + != 0x20)) { + tmp_pos -= 2; + tmpx--; + } + spk_attr = + (unsigned char) (scr_readw ((unsigned short *) tmp_pos) >> 8); + while (tmpx < video_num_columns) { + if ((*(buf + cnt) = + (char) scr_readw ((unsigned short *) tmp_pos)) == 0x20) + break; + tmpx++; + tmp_pos += 2; + cnt++; + } + *(buf + cnt++) = '\n'; + saved_punc_level = punc_level; + punc_level = ALL; + spkup_write (buf, cnt); + punc_level = saved_punc_level; +} + +void say_prev_word (unsigned int currcons) +{ + spk_parked |= 0x01; + if (((scr_readw ((unsigned short *) spk_pos) & 0x00ff) > 0x20) + && (((scr_readw ((unsigned short *) spk_pos - 1) & 0x00ff) == 0x20) + || spk_x == 0)) { + if (spk_x > 0) { + spk_x--; + spk_pos -= 2; + } else { + if (spk_y > 0) { + spk_y--; + spk_pos -= 2; + spk_x = video_num_columns - 1; + if (spk_sound & LineWrapBleep) + bleep (spk_y); + else + spkup_write ("left edge.\n", 11); + } else { + spkup_write ("top edge.\n", 10); + return; + } + } + } + + while (!(((scr_readw ((unsigned short *) spk_pos) & 0x00ff) > 0x20) + && + (((scr_readw ((unsigned short *) spk_pos - 1) & 0x00ff) == + 0x20) + || spk_x == 0))) { + if (spk_x > 0) { + spk_x--; + spk_pos -= 2; + } else { + if (spk_y > 0) { + spk_y--; + spk_pos -= 2; + spk_x = video_num_columns - 1; + if (spk_sound & LineWrapBleep) + bleep (spk_y); + else + spkup_write ("left edge.\n", 11); + } else { + spkup_write ("top edge.\n", 10); + break; + } + } + } + + say_curr_word (currcons); +} + +void say_next_word (unsigned int currcons) +{ + spk_parked |= 0x01; + if (((scr_readw ((unsigned short *) spk_pos) & 0x00ff) > 0x20) + && (((scr_readw ((unsigned short *) spk_pos - 1) & 0x00ff) == 0x20) + || spk_x == 0)) { + if (spk_x < video_num_columns - 1) { + spk_x++; + spk_pos += 2; + } else { + if (spk_y < video_num_lines - 1) + spk_y++; + else { + spkup_write ("bottom edge.\n", 13); + return; + } + spk_x = 0; + spk_pos += 2; + if (spk_sound & LineWrapBleep) + bleep (spk_y); + else + spkup_write ("right edge.\n", 12); + } + } + + while (!(((scr_readw ((unsigned short *) spk_pos) & 0x00ff) > 0x20) + && + (((scr_readw ((unsigned short *) spk_pos - 1) & 0x00ff) == + 0x20) + || spk_x == 0))) { + if (spk_x < video_num_columns - 1) { + spk_x++; + spk_pos += 2; + } else { + if (spk_y < video_num_lines - 1) + spk_y++; + else { + spkup_write ("bottom edge.\n", 13); + break; + } + spk_x = 0; + spk_pos += 2; + if (spk_sound & LineWrapBleep) + bleep (spk_y); + else + spkup_write ("right edge.\n", 12); + } + } + + say_curr_word (currcons); +} + +void spell_word (unsigned int currcons) +{ + unsigned long tmpx = spk_x, tmp_pos = spk_pos; + char *delay_str[] = { " ", ", ", ". ", ". . ", ". . . " }; + char dnum[] = { 1, 2, 2, 4, 6 }; + + if (synth == NULL) + return; + spk_parked |= 0x01; + if (((char) scr_readw ((unsigned short *) spk_pos) == 0x20) + && ((char) scr_readw ((unsigned short *) spk_pos + 1) > 0x20)) { + spk_pos += 2; + spk_x++; + } else + while ((spk_x > 0) + && ((scr_readw ((unsigned short *) spk_pos - 1) & 0x00ff) + != 0x20)) { + spk_pos -= 2; + spk_x--; + } + + for (; spk_x < video_num_columns; spk_x++, spk_pos += 2) { + if ((char) scr_readw ((unsigned short *) spk_pos) == 0x20) + break; + synth_write (delay_str[spell_delay - 1], dnum[spell_delay - 1]); + say_curr_char (currcons); + } + + spk_pos = tmp_pos; + spk_x = tmpx; +} + +void say_curr_line (unsigned int currcons) +{ + unsigned long tmp; + unsigned char buf[video_num_columns + 2], i = 0, not_blank = 0; + + spk_parked |= 0x01; + spk_old_attr = spk_attr; + spk_attr = + (unsigned char) (scr_readw ((unsigned short *) spk_pos) >> 8); + for (tmp = spk_pos - (spk_x * 2); + tmp < spk_pos + ((video_num_columns - spk_x) * 2); tmp += 2) { + *(buf + i) = (unsigned char) scr_readw ((unsigned short *) tmp); + if (*(buf + i++) != 0x20) + not_blank++; + } + *(buf + i++) = '\n'; + + if (not_blank) + spkup_write (buf, i); + else + spkup_write ("blank\n", 6); +} + +void say_prev_line (unsigned int currcons) +{ + spk_parked |= 0x01; + if (spk_y == 0) { + spkup_write ("top edge.\n", 10); + return; + } + + spk_y--; + spk_pos -= video_size_row; + say_curr_line (currcons); +} + +void say_next_line (unsigned int currcons) +{ + spk_parked |= 0x01; + if (spk_y == video_num_lines - 1) { + spkup_write ("bottom edge.\n", 13); + return; + } + + spk_y++; + spk_pos += video_size_row; + say_curr_line (currcons); +} + +static inline void say_line_from_to (unsigned int currcons, unsigned long from, unsigned long to) +{ + unsigned long tmp; + unsigned char buf[video_num_columns + 2], i = 0, not_blank = 0; + + spk_parked |= 0x01; + spk_old_attr = spk_attr; + spk_attr = + (unsigned char) (scr_readw ((unsigned short *) spk_pos) >> 8); + for (tmp = origin + (spk_y * video_size_row) + (from * 2); + tmp < origin + (spk_y * video_size_row) + (to * 2); tmp += 2) { + *(buf + i) = (unsigned char) scr_readw ((unsigned short *) tmp); + if (*(buf + i++) != 0x20) + not_blank++; + } + *(buf + i++) = '\n'; + + if (not_blank) + spkup_write (buf, i); + else + spkup_write ("blank\n", 6); +} + +void say_screen (unsigned int currcons) +{ + unsigned long tmp_pos = origin; + unsigned char c, blank = 0; + + spk_parked |= 0x01; + while (tmp_pos < origin + (video_num_lines * video_size_row)) { + if ((c = + (unsigned char) scr_readw ((unsigned long *) tmp_pos)) == + 0x20) + blank++; + else + blank = 0; + tmp_pos += 2; + if (blank > 1) + continue; + spkup_write (&c, 1); +/* insert a space at the end of full lines */ + if ((tmp_pos - origin) % video_size_row == 0 && blank == 0) + spkup_write(" ", 1); + } +} + +static inline void say_screen_from_to (unsigned int currcons, unsigned long from, unsigned long to) +{ + unsigned long tmp_pos; + unsigned char c, blank = 0; + + spk_parked |= 0x01; + if (from > 0) + tmp_pos = origin + ((from - 1) * video_size_row); + else + tmp_pos = origin; + if (to > video_num_lines) + to = video_num_lines; + while (tmp_pos < origin + (to * video_size_row)) { + if ((c = + (unsigned char) scr_readw ((unsigned long *) tmp_pos)) == + 0x20) + blank++; + else + blank = 0; + tmp_pos += 2; + if (blank > 1) + continue; + spkup_write (&c, 1); + } +} + +void top_edge (unsigned int currcons) +{ + spk_parked |= 0x01; + spk_pos -= spk_y * video_size_row; + spk_y = 0; + say_curr_line (currcons); +} + +void bottom_edge (unsigned int currcons) +{ + spk_parked |= 0x01; + spk_pos += (video_num_lines - spk_y - 1) * video_size_row; + spk_y = video_num_lines - 1; + say_curr_line (currcons); +} + +void left_edge (unsigned int currcons) +{ + spk_parked |= 0x01; + spk_pos -= spk_x * 2; + spk_x = 0; + say_curr_char (currcons); +} + +void right_edge (unsigned int currcons) +{ + spk_parked |= 0x01; + spk_pos += (video_num_columns - spk_x - 1) * 2; + spk_x = video_num_columns - 1; + say_curr_char (currcons); +} + +void say_position (unsigned int currcons) +{ + char buf[40]; + int count; + + spk_parked |= 0x01; + count = + sprintf (buf, "line %ld, position %ld, t t y. %d\n", spk_y + 1, + spk_x + 1, currcons + 1); + spkup_write (buf, count); +} + +// Added by brianb +void say_char_num (unsigned int currcons) +{ + char buf[32]; + unsigned short ch; + + spk_parked |= 0x01; + ch = scr_readw ((unsigned short *) spk_pos); + ch &= 0x0ff; + ch = sprintf (buf, "hex %02x, decimal %d\n", ch, ch); + spkup_write (buf, ch); +} + +/* these are stub functions to keep keyboard.c happy. */ + +void say_from_top (unsigned int currcons) +{ + say_screen_from_to (currcons, 0, spk_y + 1); +} + +void say_to_bottom (unsigned int currcons) +{ + say_screen_from_to (currcons, spk_y + 1, video_num_lines); +} + +void say_from_left (unsigned int currcons) +{ + say_line_from_to (currcons, 0, spk_x); +} + +void say_to_right (unsigned int currcons) +{ + say_line_from_to (currcons, spk_x, video_num_columns); +} + +/* end of stub functions. */ + +extern int synth_init (void); +extern char synth_buffering; /* flag to indicate we're buffering */ +unsigned short skip_count = 0; + +void spk_skip (unsigned short cnt) +{ + skip_count += cnt; +} + +int spkup_write (const char *buf, int count) +{ + static unsigned short rep_count; + static char old_ch, oldest_ch, count_buf[30], punc_buf[128]; + int in_count = count; + char *punc_search = NULL; + + if (synth == NULL) + return count; + spk_keydown = 0; + while (count--) { + if (rep_count) { + if (*buf == old_ch) { + buf++; + rep_count++; + continue; + } else { + if (rep_count > 3) { + synth_write (count_buf, + sprintf (count_buf, + " repeated %d times. \n", + rep_count)); + } + rep_count = 0; + } + } + if (!key_echo && (*buf == spk_lastkey)) + goto forget_about_it; + // keypad slash is the only key that slips through and speaks when + // key_echo is 0, not sure why -- bug + if (((*buf == spk_lastkey) || + ((punc_search = + strchr (*(spk_cfg + PUNC_OFFSET + (punc_level - 0x30)), + *buf)) != NULL)) + && *buf != 0x00) { + if ((*buf == spk_lastkey) && (*buf & 0x00ff) > 0x40 + && (*buf & 0x00ff) < 0x5b) { + /* keyboard caps character */ + pitch_shift++; + synth_write (punc_buf, + sprintf (punc_buf, "%s %s %s", + synth->config[CAPS_START], + *(characters + *buf), + synth-> + config[CAPS_STOP])); + } else + synth_write (punc_buf, + sprintf (punc_buf, " %s ", + *(characters + *buf))); + } else if (allowable (*buf)) + synth->write (*buf); + + forget_about_it: + if (*buf == old_ch && *buf == oldest_ch && rep_count == 0 + && punc_search != NULL) + rep_count = 3; + oldest_ch = old_ch; + old_ch = *buf++; + } + + spk_lastkey = 0; + if (in_count > 3 && rep_count > 3) { + synth_write (count_buf, + sprintf (count_buf, " repeated %d times. \n", + rep_count)); + rep_count = 0; + } + return 0; +} + +char *strlwr (char *s) +{ + char *p = s; + while (*p) + { + *p = tolower (*p); + p++; + } + return s; +} + +void __init speakup_open (unsigned int currcons) +{ + int i = 0; + + strlwr (synth_name); + while ((synth == NULL) && (synths[i] != NULL)) { + if (strcmp (synths[i]->name, synth_name) == 0) + synth = synths[i]; + else + i++; + } + + if ((synth == NULL) && (strcmp (synth_name, "none") != 0)) + printk (KERN_WARNING "Speakup: unknown synthesizer \"%s\"\n", + synth_name); + + if ((synth != NULL) && synth_init ()) { + spk_shut_up |= 0x80; /* hopefully let the system work without the synth */ + return; + } + synth_buffering = 0; +} + +// provide a file to users, so people can send to /dev/synth + +static ssize_t speakup_file_write (struct file *fp, const char *buf, + size_t nbytes, loff_t * ppos) +{ + size_t count = nbytes; + const char *ptr = buf; + + int bytes; + char tbuf[256]; + + while (count > 0) { + bytes = MIN (count, sizeof (tbuf)); + if (copy_from_user (&tbuf, ptr, bytes)) + return -EFAULT; + + count -= bytes; + ptr += bytes; + + synth_write (tbuf, bytes); + } + return (ssize_t) nbytes; +} + +static int speakup_file_ioctl (struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + return 0; // silently ignore +} + +static ssize_t speakup_file_read (struct file *fp, char *buf, size_t nbytes, loff_t * ppos) +{ + /* *nod* *nod* We'll take care of that, ma'am. *flush* */ + return 0; +} + +static int speakup_file_open (struct inode *ip, struct file *fp) +{ + if (synth_file_inuse) + return -EBUSY; + else if (synth == NULL) + return -ENODEV; + + synth_file_inuse++; + return 0; +} + +static int speakup_file_release (struct inode *ip, struct file *fp) +{ + synth_file_inuse = 0; + return 0; +} + +static struct file_operations synth_fops = { + .owner = THIS_MODULE, + .read = speakup_file_read, + .write = speakup_file_write, + .ioctl = speakup_file_ioctl, + .open = speakup_file_open, + .release = speakup_file_release, +}; + +void speakup_register_devsynth (void) +{ + static struct miscdevice synth_device; + + synth_device.minor = SYNTH_MINOR; + synth_device.name = "synth"; + synth_device.fops = &synth_fops; + + if (misc_register (&synth_device)) + printk ("speakup: Couldn't initialize miscdevice /dev/synth.\n"); + else + printk + ("speakup: initialized device: /dev/synth, node (MAJOR 10, MINOR 25)\n"); +} + +static void reset_default_chars (void) +{ + static int first_pass = 1; + int i; + + for (i = 0; i < 256; ++i) { + // if pointing to allocated memory, free it! + if (first_pass || characters[i] != default_chars[i]) { + if (!first_pass) + kfree (characters[i]); + characters[i] = default_chars[i]; + } + } + first_pass = 0; +} + +#ifdef CONFIG_PROC_FS + +// speakup /proc interface code + +/* +Notes: +currently, user may store an unlimited character definition + +Usage: +cat /proc/speakup/version + +cat /proc/speakup/characters > foo +less /proc/speakup/characters +vi /proc/speakup/characters + +cat foo > /proc/speakup/characters +cat > /proc/speakup/characters +echo 39 apostrophe > /proc/speakup/characters +echo 87 w > /proc/speakup/characters +echo 119 w > /proc/speakup/characters +echo defaults > /proc/speakup/characters +echo reset > /proc/speakup/characters +*/ + +// the /proc/speakup directory inodes +// static struct proc_dir_entry *proc_speakup_device; +// synth-specific directory created in synth driver file + +// this is the handler for /proc/speakup/version +static int speakup_version_read_proc (char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len = sprintf (page, "%s\n", SPEAKUP_VERSION); + *start = 0; + *eof = 1; + return len; +} + +// this is the read handler for /proc/speakup/characters +static int speakup_characters_read_proc (char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int i; + int len = 0; + off_t begin = 0; + + for (i = 0; i < 256; ++i) { + if (characters[i]) + len += + sprintf (page + len, "%d\t%s\n", i, characters[i]); + else + len += sprintf (page + len, "%d\tNULL\n", i); + if (len + begin > off + count) + break; + if (len + begin < off) { + begin += len; + len = 0; + } + } + if (i >= 256) + *eof = 1; + if (off >= len + begin) + return 0; + *start = page + (off - begin); + return ((count < begin + len - off) ? count : begin + len - off); +} + +static volatile int chars_timer_active; // indicates when a timer is set +static DECLARE_WAIT_QUEUE_HEAD (chars_sleeping_list); +static struct timer_list chars_timer; + +static inline void chars_stop_timer (void) +{ + if (chars_timer_active) + del_timer (&chars_timer); +} + +static int strings, rejects, updates; + +static void show_char_results (unsigned long data) +{ + int len; + char buf[80]; + + chars_stop_timer (); + // tell what happened + len = sprintf (buf, " updated %d of %d character descriptions", + updates, strings); + if (rejects) + sprintf (buf + len, " with %d reject%s\n", + rejects, rejects > 1 ? "s" : ""); + else + sprintf (buf + len, "\n"); + printk (buf); + chars_timer_active = 0; +} + +/* this is the write handler for /proc/speakup/silent */ +static int speakup_silent_write_proc (struct file *file, const char *buffer, + unsigned long count, void *data) +{ + unsigned int currcons = fg_console; + char ch = 0; + if (count < 0 || count > 2) + goto msg_out; + if (count) + get_user (ch, buffer); + if (!count || ch == '\n') + ch = '0'; + switch (ch) { + case '0' : + if (spk_killed) + speakup_kill(currcons); + goto out; + case '1' : + if (!spk_killed) + speakup_kill(currcons); + goto out; + case '2' : + if (spk_killed) + spk_shut_up &= ~0x40; + goto out; + case '3' : + if (!spk_killed) + spk_shut_up |= 0x40; + goto out; + } + +msg_out: + printk (KERN_ALERT "setting silent: value not in range (0,3)\n"); + +out: + return count; +} + +// this is the write handler for /proc/speakup/characters +static int speakup_characters_write_proc (struct file *file, const char *buffer, + unsigned long count, void *data) +{ + static const int max_description_len = 72; + static int cnt, num, state; + static char desc[max_description_len + 1]; + static unsigned long jiff_last; + int i; + char ch, *s1, *s2; + + // reset certain vars if enough time has elapsed since last called + if (jiffies - jiff_last > HZ/10) { + state = strings = rejects = updates = 0; + } + jiff_last = jiffies; + // walk through the buffer + for (i = 0; i < count; ++i) { + get_user (ch, buffer + i); + switch (state) { + case 0: // initial state, only happens once per "write" + // if input matches "defaults" or "reset" reset_default_chars() and return + if ((ch == '\n' && count == 1) || strchr ("dDrR", ch)) { + reset_default_chars (); + printk (KERN_ALERT + "character descriptions reset to defaults\n"); + return count; + } + ++state; + // intentionally fall through to next state + case 1: // check for comment and skip whitespace + if (ch == '#') { // comment + num = -1; // don't count as rejected + state = 6; // ignore remainder of line + break; // and don't process + } + if (ch == ' ' || ch == '\t') // skip whitespace + break; + if (!isdigit (ch)) { + state = 6; + break; + } + num = ch - '0'; // convert first digit from ASCII + ++state; // now expecting only digits or whitespace + break; + case 2: // building number + if (isdigit (ch)) { + num *= 10; + num += ch - '0'; // convert from ASCII + break; + } + if (ch != ' ' && ch != '\t') { // not whitespace + state = 6; + break; + } + // pointing to 1st whitespace past digits -- number is complete + if (num < 0 || num > 255) { // not in range + state = 6; + break; + } + if (num >= 27 && num <= 31) { // no descriptions for these + num = -1; // don't count as rejected + state = 6; // but don't process either + break; + } + ++state; // now looking for 1st char of description + break; + case 3: /* skipping whitespace prior to description */ + if (ch == ' ' || ch == '\t') // skip whitespace + break; + if (ch == '\n') { // reached EOL + state = 6; + break; + } + cnt = 0; // starting new description + desc[cnt++] = ch; + ++state; // now looking for EOL + break; + case 4: // looking for newline + if (ch != '\n') { // not yet + // add char to description + desc[cnt++] = ch; + if (cnt < max_description_len) + break; // building description + // maximum description length reached, truncate remainder + state = 5; + } + // prepare to work on next string + state = state == 5 ? state : 1; + // description string is complete + desc[cnt] = '\0'; // NULL terminate + // if new description matches old, we don't need to update + s1 = desc; // point to new description + s2 = characters[num]; // point to old/current + while (*s1 == *s2) { + if (!*s1) // reached end of strings + break; + ++s1; + ++s2; + } + if (*s1 == *s2) { // strings match + ++strings; + break; + } + // handle new description + // is this description the default or has it already been modified? + if (characters[num] == default_chars[num]) // original + characters[num] = + (char *) kmalloc (sizeof (char) * + (strlen (desc) + 1), + GFP_KERNEL); + else // already redefined/allocated + krealloc (characters[num], strlen (desc) + 1); + if (!characters[num]) { // allocation failed + characters[num] = default_chars[num]; // reset to default + return -ENOMEM; + } + // got mem, copy the string + strcpy (characters[num], desc); + ++updates; + ++strings; + break; + case 5: // truncating oversized description + if (ch == '\n') + state = 1; // ready to start anew + // all other chars go to the bit bucket + break; + case 6: // skipping all chars while looking for newline + // we only get here if the data is invalid + if (ch == '\n') { + state = 1; + // -1 indicates chars with no description (ASCII 27-31) + if (num != -1) + ++rejects; + ++strings; + } + break; + } // end switch + } // finished processing entire buffer + + chars_stop_timer (); + init_timer (&chars_timer); + chars_timer.function = show_char_results; + init_waitqueue_head (&chars_sleeping_list); + + chars_timer.expires = jiffies + HZ/20; + if (!chars_timer.list.prev) + add_timer (&chars_timer); + chars_timer_active++; + return count; +} + +static int human_readable (char *s, struct spk_variable *var, char *buf) +{ + char *fmt = var->build; // point to start of it's format + int len = 0; + char *end = s + strlen (s) - 1; // point to end of string holding value + char *end_fmt = fmt + strlen (fmt) - 1; // point to end of it's format + + while (*fmt != '_' && *s == *fmt) { + ++s; + ++fmt; + } + // s now points to beginning of unformatted value, find the end + while (*end_fmt != '_' && *end == *end_fmt) { + --end; + --end_fmt; + } + // end now points to last char of unformatted value + // store value converting to human readable if necessary + for (; s <= end; ++s) { + if (*s < 32) { // don't print these directly + // convert to hex, 0x00 - 0xff + *(buf + len++) = '\\'; + *(buf + len++) = 'x'; + if (*s > 15) + *(buf + len++) = '1'; + else + *(buf + len++) = '0'; + if ((*s % 16) < 10) + *(buf + len++) = (*s % 16) + '0'; + else + *(buf + len++) = (*s % 16) + 'a' - 10; + } else + *(buf + len++) = *s; + if (*s == '\\') + *(buf + len++) = *s; // double up on escape char + } + // append a newline + *(buf + len++) = '\n'; + return len; +} + +static int find_config_var (const char *name, char ***value, + struct spk_variable **var, long **cfg_map) +{ + int i; + + if (synth != NULL) + for (i = 0; synth->vars[i].id != NULL; i++) { + if (strcmp (synth->vars[i].id, name) == 0) { + *value = &(synth->config[i]); + *var = &(synth->vars[i]); + *cfg_map = &(synth->config_map); + return i; + } + } + + for (i = 0; spk_vars[i].id != NULL; i++) { + if (strcmp (spk_vars[i].id, name) == 0) { + *value = &(spk_cfg[i]); + *var = &(spk_vars[i]); + *cfg_map = &spk_cfg_map; + return i; + } + } + + return -1; +} + +// this is the read handler for /proc/speakup/settings +int speakup_settings_read_proc (char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + struct proc_dir_entry *ent = data; + char **value; + struct spk_variable *var; + long *cfg_map; + int index = find_config_var (ent->name, &value, &var, &cfg_map); + + *start = 0; + *eof = 1; + + if (index == -1) + return sprintf (page, "%s slipped through the cracks!\n", + ent->name); + + return human_readable (*value, var, page); +} + +char *xlate (char *s) +{ + char *p = s, c; + size_t len = strlen (s); + int num, num_len; + + while ((p = strchr (p, '\\'))) { + num_len = 1; + switch (*(p + 1)) { + case '\\': + break; + case 'r': + *p = '\r'; + break; + case 'n': + *p = '\n'; + break; + case 't': + *p = '\t'; + break; + case 'v': + *p = '\v'; + break; + case 'a': + *p = '\a'; + break; +#ifdef fix_octal + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + if (sscanf (p + 1, "%3o%n", &num, &num_len)) + *p = (char) num; + break; +#endif + case 'x': + c = *(p + 2); + if (isdigit (c)) + num = c - '0'; + else if (isxdigit (c)) + num = tolower (c) - 'a' + 10; + else + break; + num *= 0x10; + c = *(p + 3); + if (isdigit (c)) + num += c - '0'; + else if (isxdigit (c)) + num += tolower (c) - 'a' + 10; + else + break; + num_len = 3; + *p = (char) num; + break; + default: + *p = *(p + 1); + } + num = p - s + num_len; + ++p; + memmove (p, p + num_len, len - num); + } + return s; +} + +#define NOT_IN_RANGE -1 +#define NOT_ONE_OF -2 +#define STRING_TOO_LONG -3 +#define RESET_DEFAULT -4 + +// this is the write handler for /proc/speakup/settings +static int speakup_settings_write_proc (struct file *file, const char *buffer, + unsigned long count, void *data) +{ + struct proc_dir_entry *ent = data; + int ret = NOT_IN_RANGE, i, limit, val = 0; + long *cfg_map; + char *p = NULL, *parm, *formatted, *src, *dest, **value; + struct spk_variable *sv; + int index = find_config_var (ent->name, &value, &sv, &cfg_map); + int currcons = 0; + + if (count < 0 || count > 1024) + return -EINVAL; + if (!(parm = (char *) __get_free_page (GFP_KERNEL))) + return -ENOMEM; + if (copy_from_user (parm, buffer, count)) { + ret = -EFAULT; + goto out; + } + // NULL terminate + if (*(parm + count - 1) == '\n') + *(parm + count - 1) = '\0'; + else + *(parm + count) = '\0'; + xlate (parm); + formatted = parm + strlen (parm) + 1; + if (index == -1) { + printk (KERN_ALERT "%s slipped through the cracks!\n", + ent->name); + ret = count; + goto out; + } + // wildcard + if (!sv->flags && *sv->valid == '*') { + // arbitrary 33 char limit + if (strlen (parm) > PUNC_CHARS_SIZE) { + ret = STRING_TOO_LONG; + goto msg_out; + } + // all is well + } else if (*parm && (sv->flags & USE_RANGE)) { + // check range + if (sv->flags & NUMERIC) { + int neg = 0; + // atoi on user provided value + p = parm; + if (*p == '-') { + ++neg; + ++p; + } + for (val = 0; *p; ++p) { + if (!isdigit (*p)) + goto msg_out; + val *= 10; + val += *p - '0'; + } + if (neg) { + val = -val; + neg = 0; + } + // atoi on lower limit of range + p = sv->valid; + if (*p == '-') { + ++neg; + ++p; + } + for (limit = 0; *p && *p != ','; ++p) { + // valid range? + if (!isdigit (*p)) + goto msg_out; + limit *= 10; + limit += *p - '0'; + } + if (neg) { + limit = -limit; + neg = 0; + } + if (val < limit) + goto msg_out; + // should be pointing to the comma in range + if (*p == ',') + ++p; + else + goto msg_out; + // atoi on upper limit of range + /* if bell_pos, this value is video_num_columns */ + dest = p; + if (*p == '-') { + ++neg; + ++p; + } + for (limit = 0; *p; ++p) { + // valid range? + if (!isdigit (*p)) + goto msg_out; + limit *= 10; + limit += *p - '0'; + } + if (neg) + limit = -limit; + if (index == BELL_POS) { + limit = video_num_columns; + sprintf (dest, "%-d", limit); + } + if (val > limit) + goto msg_out; + // numeric val is in range + } else { + // range of chars + p = sv->valid; + // parm should be exactly 1 char + if (*(parm + 1)) { + ret = NOT_ONE_OF; + goto msg_out; + } + *parm = tolower (*parm); + // expecting a comma here and char in range + if (*(p + 1) != ',' || *parm < *p || *parm > *(p + 2)) { + ret = NOT_ONE_OF; + goto msg_out; + } + } + } else if (*parm && (sv->flags & MULTI_SET)) { + // each char must be one of valid + if (strlen (parm) > PUNC_CHARS_SIZE) { + ret = STRING_TOO_LONG; + goto msg_out; + } + for (p = parm; *p; ++p) + if (!strchr (sv->valid, *p)) { + ret = NOT_ONE_OF; + goto msg_out; + } + } else if (*parm) { + // find_is_one_of + p = sv->valid; + // parm should be exactly 1 char + if (*(parm + 1)) { + ret = NOT_ONE_OF; + goto msg_out; + } + *parm = tolower (*parm); + for (; *p; ++p) + if (*parm == *p) + break; + if (!*p) { + // no match found + ret = NOT_ONE_OF; + goto msg_out; + } + } + // in range or doesn't matter + if (sv->flags & (HARD_DIRECT | SOFT_DIRECT) || !sv->flags) { + // replace string provided by user with formated string + if (*parm) { + // copy the format string up to the underscore + src = sv->build; + dest = formatted; + while (*src && *src != '_') + *dest++ = *src++; + // append parm + p = parm; + while (*p) + *dest++ = *p++; + // skip over the underscore + if (*src == '_') + ++src; + // append remainder of format + while (*src) + *dest++ = *src++; + // null terminate + *dest = '\0'; + } + } + // reset to default? + if (!*parm) { + // copy the format string up to the underscore + src = sv->build; + dest = formatted; + while (*src && *src != '_') + *dest++ = *src++; + // append default parameter + p = sv->param; + while (*p) + *dest++ = *p++; + // skip over the underscore + if (*src == '_') + ++src; + // append remainder of format + while (*src) + *dest++ = *src++; + // null terminate + *dest = '\0'; + ret = RESET_DEFAULT; + } + // store formatted value + if (*cfg_map & (0x01 << index)) + krealloc (*value, strlen (formatted) + 1); + else { + *cfg_map |= (0x01 << index); + *value = kmalloc (strlen (formatted) + 1, GFP_KERNEL); + } + strcpy (*value, formatted); + if (sv->flags & HARD_DIRECT) { + synth_write (formatted, strlen (formatted)); + synth_write ("\n", 1); + } + + /* set bell position */ + if (index == BELL_POS) + bell_pos = val; + + /* bleep settings need to be replicated through every console */ + if ((index == LINE_WRAP_BLEEP) || (index == ATTRIBUTE_BLEEP)) + for (i = 0; speakup_console[i] != NULL; ++i) { + if (index == LINE_WRAP_BLEEP) { + if (*parm == '1' || !*parm) + speakup_console[i]->sound |= + LineWrapBleep; + else + speakup_console[i]->sound &= + LineWrapMask; + } else { + // ATTRIBUTE_BLEEP + if (*parm == '1' || !*parm) + speakup_console[i]->sound |= + AttributeChangeBleep; + else + speakup_console[i]->sound &= + AttributeChangeMask; + } + } + if (ret == RESET_DEFAULT) + printk (KERN_ALERT "%s reset to default value\n", sv->id); + ret = count; + goto out; + +msg_out: + switch (ret) { + case NOT_IN_RANGE: + p = "value not in range"; + ret = count; + break; + case NOT_ONE_OF: + p = "value not one of"; + ret = count; + break; + case STRING_TOO_LONG: + p = "string longer than 33 chars"; + ret = count; + break; + } + printk (KERN_ALERT "setting %s (%s): %s (%s)\n", ent->name, parm, p, + sv->valid); + + out: + free_page ((unsigned long) parm); + return ret; +} + +// this is the read handler for /proc/speakup/synth +static int speakup_synth_read_proc (char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len = sprintf (page, "%s\n", synth_name); + *start = 0; + *eof = 1; + return len; +} + +// this is the write handler for /proc/speakup/synth +static int speakup_synth_write_proc (struct file *file, const char *buffer, + unsigned long count, void *data) +{ + int ret = count, i = 0; + char new_synth_name[10]; + struct spk_synth *new_synth = NULL; + + if (count < 1 || count > 9) + return -EINVAL; + if (copy_from_user (new_synth_name, buffer, count)) + return -EFAULT; + // NULL terminate + if (new_synth_name[count - 1] == '\n') + new_synth_name[count - 1] = '\0'; + else + new_synth_name[count] = '\0'; + strlwr (new_synth_name); + if (!strcmp (new_synth_name, synth->name)) { + printk (KERN_WARNING "already in use\n"); + return ret; + } + + for (i = 0; !new_synth && synths[i]; ++i) { + if (!strcmp (synths[i]->name, new_synth_name)) + new_synth = synths[i]; + } + + if (!new_synth && strcmp (new_synth_name, "none")) { + printk (KERN_WARNING + "there is no synth named \"%s\" built into this kernel\n", + new_synth_name); + return ret; + } + + /* At this point, we know that new_synth_name is valid, built into the + kernel, and not already in use. + Next, do the magic to select it as the new active synth */ + + // still working here. announce attempt and leave + printk (KERN_ALERT "attempt to change synth to %s\n", new_synth_name); + return ret; +} + +// called by proc_root_init() to initialize the /proc/speakup subtree +void __init proc_speakup_init (void) +{ + int i; + char path[40]; + mode_t mode; + struct proc_dir_entry *ent; +#define PROC_SPK_DIR "speakup" + + ent = create_proc_entry (PROC_SPK_DIR, S_IFDIR, 0); + if (!ent) { + printk (KERN_ALERT "Unable to create /proc/speakup entry.\n"); + return; + } + + ent = create_proc_entry (PROC_SPK_DIR "/version", S_IFREG | S_IRUGO, 0); + ent->read_proc = speakup_version_read_proc; + + ent = create_proc_entry (PROC_SPK_DIR "/silent", S_IFREG | S_IWUGO, 0); + ent->write_proc = speakup_silent_write_proc; + + ent = + create_proc_entry (PROC_SPK_DIR "/characters", + S_IFREG | S_IRUGO | S_IWUGO, 0); + ent->read_proc = speakup_characters_read_proc; + ent->write_proc = speakup_characters_write_proc; + + ent = + create_proc_entry (PROC_SPK_DIR "/synth", + S_IFREG | S_IRUGO | S_IWUGO, 0); + ent->read_proc = speakup_synth_read_proc; + ent->write_proc = speakup_synth_write_proc; + + if (synth != NULL) { + for (i = 0; synth->vars[i].id != NULL; i++) { + mode = S_IFREG | S_IRUGO; + if (~(synth->vars[i].flags) & NO_USER) + mode |= S_IWUGO; + sprintf (path, PROC_SPK_DIR "/%s", synth->vars[i].id); + ent = create_proc_entry (path, mode, 0); + ent->read_proc = speakup_settings_read_proc; + if (mode & S_IWUGO) + ent->write_proc = speakup_settings_write_proc; + ent->data = (void *) ent; + } + } + + for (i = 0; spk_vars[i].id != '\0'; ++i) { + if (!strcmp (spk_vars[i].id, "punc_none")) + continue; // no /proc file for this one -- it's empty + mode = S_IFREG | S_IRUGO; + if (~(spk_vars[i].flags) & NO_USER) + mode |= S_IWUGO; + sprintf (path, PROC_SPK_DIR "/%s", spk_vars[i].id); + ent = create_proc_entry (path, mode, 0); + ent->read_proc = speakup_settings_read_proc; + if (mode & S_IWUGO) + ent->write_proc = speakup_settings_write_proc; + ent->data = (void *) ent; + } + + // initialize the synth-specific subtree + if (synth != NULL) + proc_speakup_synth_init (); +} + +#endif // CONFIG_PROC_FS + +/* version 2.3.x */ +void __init +speakup_init (int currcons) +{ + unsigned char i; + + reset_default_chars (); + + speakup_console[currcons] = + (struct spk_t *) alloc_bootmem (sizeof (struct spk_t) + 1); + + for (i = 0; i < MIN_NR_CONSOLES; i++) { + spk_shut_up = 0; + spk_x = x; + spk_y = y; + spk_attr = spk_old_attr = attr; + spk_pos = pos; + spk_sound = 3; + spk_parked = 0; + spk_o_cp = spk_o_cy = spk_o_cx = 0; + } + for (; i < MAX_NR_CONSOLES; i++) + speakup_console[i] = NULL; + speakup_open (currcons); /* we'll try it here. */ + printk ("%s: initialized\n", SPEAKUP_VERSION); +} + +void speakup_allocate (int currcons) +{ + + speakup_console[currcons] = (struct spk_t *) kmalloc (sizeof (struct spk_t) + 1, GFP_KERNEL); + + spk_shut_up = 0; + spk_x = x; + spk_y = -1; + spk_old_attr = spk_attr = attr; + spk_pos = pos; + spk_sound = 3; + spk_parked = 0; + spk_o_cp = spk_o_cy = spk_o_cx = 0; +} + +void speakup_date (unsigned int currcons) +{ + spk_x = spk_cx = x; + spk_y = spk_cy = y; + spk_pos = spk_cp = pos; + spk_old_attr = spk_attr; + spk_attr = ((scr_readw ((unsigned short *) spk_pos) & 0xff00) >> 8); +} + +void speakup_check (unsigned int currcons) +{ + if (!spk_keydown) + return; + + if ((x == spk_o_cx + 1 || x == spk_o_cx - 1) && y == spk_o_cy) { + if (spk_keydown > 1 && x > spk_o_cx) + say_prev_char (currcons); + else + say_curr_char (currcons); + } else + if ((x == 0 && spk_o_cx == video_num_columns - 1 + && y == spk_o_cy + 1) + || (x == video_num_columns - 1 && spk_o_cx == 0 + && y == spk_o_cy - 1)) { + say_curr_char (currcons); + } else if (y == spk_o_cy && (y == bottom || y == top)) { + say_curr_line (currcons); + } else if ((y > spk_o_cy || y < spk_o_cy)) { + say_curr_line (currcons); + } else if (pos == spk_o_cp) { + say_curr_char (currcons); + } else + say_curr_word (currcons); + + spk_o_cp = pos; + spk_o_cx = x; + spk_o_cy = y; + spk_keydown = 0; + spk_parked &= 0xfe; + speakup_date (currcons); +} + +/* These functions are the interface to speakup from the actual kernel code. */ + +void speakup_bs (int currcons) +{ + if (!spk_parked) + speakup_date (currcons); + if ((!spk_shut_up || spk_shut_up & 0x02) && (currcons == fg_console) + && spk_keydown) { + spk_keydown = 0; + say_curr_char (currcons); + } +} + +void speakup_con_write (int currcons, const char *str, int len) +{ + if (!spk_shut_up && (currcons == fg_console)) { + if (bell_pos && spk_keydown && (x == bell_pos - 1)) + bleep(38); + spkup_write (str, len); + } +} + +void speakup_con_update (int currcons) +{ + if (speakup_console[currcons] == NULL) + return; + if (!spk_parked) + speakup_date (currcons); + if ((currcons == fg_console) && !spk_parked && spk_shut_up & 0x02) + speakup_check (currcons); +} + +void speakup_control(int currcons, struct kbd_struct * kbd, int value) +{ + /* let there be speech! */ + switch (value) { + case KVAL(K_CAPS): + if (vc_kbd_led(kbd , VC_CAPSLOCK)) + spk_control(fg_console, 10); + else + spk_control(fg_console, 11); + break; + case KVAL(K_NUM): + if (vc_kbd_led(kbd , VC_NUMLOCK)) + spk_control(fg_console, 12); + else + spk_control(fg_console, 13); + break; + case KVAL(K_HOLD): + if (vc_kbd_led(kbd , VC_SCROLLOCK)) + spk_control(fg_console, 14); + else + spk_control(fg_console, 15); + break; + default: + spk_control(currcons, value); + } +} + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/speakup/speakup_decext.c linux.19rc3-ac4/drivers/char/speakup/speakup_decext.c --- linux.19rc3/drivers/char/speakup/speakup_decext.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/speakup/speakup_decext.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,307 @@ +/* + * speakup_dectlk.c - Dectalk External driver for Linux kernel 2.3.x and speakup + * + * author: Kirk Reiser + + Copyright (C) 2000 Kirk Reiser. + + 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 + + Kirk Reiser + 261 Trott dr. London, Ontario, Canada. N6G 1B6 + */ + + +/* These routines are written to control the Dectalk External speech + synthesizer by Digital Equipment Corp. They are not ment to be + thought of as a device driver in that they do not register + themselves as a chr device and there is no file_operations + structure. They are strictly to provide an interface to the + Dectalk External from the speakup screen review package. */ + +#define KERNEL +#include +#include +#include +#include /* for verify_area */ +#include /* for -EBUSY */ +#include /* for check_region, request_region */ +#include /* for loops_per_sec */ +#include /* for put_user_byte */ +#include /* for inb_p, outb_p, inb, outb, etc... */ +#include /* for wait_queue */ +#include /* kd_mksound */ +#include /* for __init */ +#include +#include /* for rs_table, serial constants & + serial_uart_config */ +#include /* for more serial constants */ +#if (LINUX_VERSION_CODE >= 0x20300) /* v 2.3.x */ +#include /* for struct serial_state */ +#endif +#include +#include + +#define SYNTH_CLEAR 0x03 /* synth flush char */ +#define PROCSPEECH 0x0b /* start synth processing char */ +static int full_status = 0; +#define synth_full() (full_status = (inb_p(synth_port_tts) == 0x13)) +#define SPK_SERIAL_TIMEOUT 1000000 /* countdown values for serial timeouts */ +#define SPK_XMITR_TIMEOUT 1000000 /* countdown values transmitter/dsr timeouts */ +#define SPK_LO_TTY 0 /* check ttyS0 ... ttyS3 */ +#define SPK_HI_TTY 3 +#define NUM_DISABLE_TIMEOUTS 3 /* # of timeouts permitted before disable */ + +static int dectlk_alive = 0; + /* 160 ms delay and ctrl-x as flush */ + +#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) + +static struct serial_state rs_table[] __initdata = { + SERIAL_PORT_DFNS +}; + +static int timeouts = 0; /* sequential number of timeouts */ + +static int wait_for_xmitr(void) +{ +int check, tmout = SPK_XMITR_TIMEOUT; + + if ((dectlk_alive) && (timeouts >= NUM_DISABLE_TIMEOUTS)) { + dectlk_alive = 0; + timeouts = 0; + return 0; + } + + /* holding register empty? */ + do { + check = inb_p(synth_port_tts + UART_LSR); + if (--tmout == 0) { + printk("Dectalk External: timed out\n"); + timeouts++; + return 0; + } + } while ((check & BOTH_EMPTY) != BOTH_EMPTY); + + tmout = SPK_XMITR_TIMEOUT; + /* CTS */ + do { + check = inb_p(synth_port_tts + UART_MSR); + if (--tmout == 0) { + timeouts++; + return 0; + } + } while ((check & UART_MSR_CTS) != UART_MSR_CTS); + + timeouts = 0; + return 1; +} + +static inline int spk_serial_out(const char ch) +{ + if (dectlk_alive && synth_port_tts) { + if (wait_for_xmitr()) { + outb_p(ch, synth_port_tts); + return 1; + } + } + return 0; +} + +static unsigned char __init spk_serial_in(void) +{ +int lsr, tmout = SPK_SERIAL_TIMEOUT; +int c; + + do { + lsr = inb_p(synth_port_tts + UART_LSR); + if (--tmout == 0) return 0xff; + } while (!(lsr & UART_LSR_DR)); + c = inb_p(synth_port_tts + UART_RX); + return (unsigned char) c; +} + +static void do_catch_up(unsigned long data) +{ +unsigned long jiff_in = jiffies; + +synth_stop_timer(); +while ((synth_sent_bytes < synth_queued_bytes) && !synth_full()) + { + if (!spk_serial_out(*(synth_buffer+synth_sent_bytes))) { + synth_delay(synth_full_time); + return; + } + synth_sent_bytes++; + if (jiffies >= jiff_in+synth_jiffy_delta && *(synth_buffer+synth_sent_bytes-1) == ' ') { + spk_serial_out(PROCSPEECH); + synth_delay(synth_delay_time); + return; + } + } + + if (full_status) { + synth_delay(synth_full_time); + return; + } +synth_sent_bytes = synth_queued_bytes = 0; +spk_serial_out(PROCSPEECH); +synth_timer_active = 0; +if (waitqueue_active(&synth_sleeping_list)) + wake_up_interruptible(&synth_sleeping_list); +} + +static inline void synth_immediate_tts(const char *buf, size_t count) +{ + while (count--) spk_serial_out(*buf++); +return; +} + +static void synth_write_tts(char ch) +{ +static char last='['; + + if (!dectlk_alive) return; + if (ch < 0x00) return; /* don't want unprintable chars */ + if (ch == 0x0a) /* turn lf into to force talking. */ + ch = 0x0D; + if (ch == SYNTH_CLEAR) { /* clear all and wake sleeping */ + synth_immediate_tts("\x1bP;10z\x1b\\", 8); + if (waitqueue_active(&synth_sleeping_list)) + wake_up_interruptible(&synth_sleeping_list); +#if (LINUX_VERSION_CODE >= 0x20300) /* is it a 2.3.x kernel? */ + if (synth_timer.list.prev) synth_stop_timer(); +#else + if (synth_timer.prev) synth_stop_timer(); +#endif + synth_timer_active = synth_queued_bytes = synth_sent_bytes = 0; + return; + } + +synth_buffer_add(ch); +if ((last != '[') && strchr(",.@!?/-:", ch)) synth_buffer_add(PROCSPEECH); +last = ch; +if (synth_buffering) return; +if (synth_timer_active == 0) synth_delay( synth_trigger_time ); +} + +static int __init serprobe(int index) +{ + struct serial_state *ser = NULL; + unsigned char test=0; + + if (synth_port_tts) { + for (test=0; test <= SPK_HI_TTY; test++) + if ( (rs_table+test)->port == synth_port_tts) { + ser = rs_table+test; + break; + } + } else ser = rs_table + index; + + if (synth_request_region(ser->port,8)) + return -1; + + initialize_uart(ser); + /* If we read 0xff from the LSR, there is no UART here. */ + if (inb (ser->port + UART_LSR) == 0xff) { + synth_release_region(ser->port,8); + return -1; + } + mdelay(1); + + dectlk_alive = 1; + /* ignore any error results, if port was forced */ + if (synth_port_tts) + return 0; + + synth_port_tts = ser->port; + /* check for dectalk external now... */ + spk_serial_out(0x1b); + spk_serial_out('['); + spk_serial_out(';'); + spk_serial_out('5'); + spk_serial_out('n'); + spk_serial_out(0x1b); + spk_serial_out('\\'); + if ((test = spk_serial_in()) == 0x1b) + return 0; + /*printk("test = %x\n", test);*/ + + synth_release_region(ser->port,8); + timeouts = dectlk_alive = synth_port_tts = 0; /* not ignoring */ + return -1; +} + +static int __init synth_dev_probe(void) +{ +int i=0; + + printk("Probing for Dectalk External.\n"); + if (synth_port_tts) + printk("probe forced to 0x%x by kernel command line\n", synth_port_tts); + + /* check ttyS0-ttyS3 */ + for (i=SPK_LO_TTY; i <= SPK_HI_TTY; i++) { + if (serprobe(i) == 0) break; /* found it */ + } + + if (dectlk_alive) { + /* found 'em */ + printk("Dectalk External: %03x-%03x, Driver Version %s,\n", + synth_port_tts, synth_port_tts+7, synth->version); + synth_immediate_tts(synth->init, strlen(synth->init)); + return 0; + } + + printk("Dectalk External: not found\n"); + return -ENODEV; +} + +static int synth_alive(void) +{ + if (dectlk_alive) + return 1; /* already on */ + else if ((!dectlk_alive) && (synth_port_tts)) { + if (wait_for_xmitr() > 0) { /* restart */ + dectlk_alive = 1; + synth_write(synth->reinit, strlen(synth->reinit)); + return 2; /* reenabled */ + } else printk("Dectalk External: can't restart synth\n"); + } + return 0; +} + +static const char init_string[] = "[:ra 300][:dv ap 100][:punc n][:pe -380]Dectalk External found\n"; +static const char reinit_string[] = "[:ra 300][:dv ap 100][:punc n][:pe -380]Dectalk restarted\n"; + +static struct spk_variable vars[] = +{{"flush", "\x03", "_", (BUILDER|HARD_DIRECT|USE_RANGE|NO_USER), "*"}, + {"pitch", "100", "[:dv ap _]", (NUMERIC|HARD_DIRECT|USE_RANGE), "0,99"}, + {"caps_start", "[:dv ap 222]", "_", 0, "*"}, + {"caps_stop", "[:dv ap 100]", "_", 0, "*"}, + {"rate", "300", "[:ra _]", (NUMERIC|HARD_DIRECT|USE_RANGE), "75,650"}, + {"volume", "65", "[:dv gv _]", (NUMERIC|HARD_DIRECT|USE_RANGE), "0,80"}, + {"voice", "p", "[:n_]", HARD_DIRECT, "phfdburwkv"}, + {"punct", "n", "[:pu _]", HARD_DIRECT, "nsa"}, + END_VARS}; + +static char *config[] = +{"\x03", "[:dv ap 100]", "[:dv ap 222]", "[:dv ap 100]", "[:ra 300]", "", + "[:np]", "[:pu n]"}; + +struct spk_synth synth_decext = {"decext", "Version-0.10", "dec_external", + init_string, reinit_string, 500, 50, 5, 1000, + vars, config, 0, synth_dev_probe, do_catch_up, + synth_write_tts, synth_alive}; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/speakup/speakup_dectlk.c linux.19rc3-ac4/drivers/char/speakup/speakup_dectlk.c --- linux.19rc3/drivers/char/speakup/speakup_dectlk.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/speakup/speakup_dectlk.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,337 @@ +/* + * speakup_dectlk.c - Dectalk Express driver for Linux kernel 2.3.x and speakup + * + * author: Kirk Reiser + + Copyright (C) 1998-99 Kirk Reiser. + + 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 + + Kirk Reiser + 261 Trott dr. London, Ontario, Canada. N6G 1B6 + */ + +/* These routines are written to control the Dectalk Express speech + synthesizer by Digital Equipment Corp. They are not ment to be + thought of as a device driver in that they do not register + themselves as a chr device and there is no file_operations + structure. They are strictly to provide an interface to the + Dectalk Express from the speakup screen review package. */ + +#define KERNEL +#include +#include +#include +#include +#include /* for verify_area */ +#include /* for -EBUSY */ +#include /* for check_region, request_region */ +#include /* for loops_per_sec */ +#include /* for put_user_byte */ +#include /* for inb_p, outb_p, inb, outb, etc... */ +#include /* for wait_queue */ +#include /* kd_mksound */ +#include /* for __init */ +#include /* for rs_table, serial constants & + serial_uart_config */ +#include /* for more serial constants */ +#if LINUX_VERSION_CODE >= 0x020200 +#include /* for struct serial_state */ +#endif +#include +#include + +#define SYNTH_CLEAR 0x03 /* synth flush char */ +#define PROCSPEECH 0x0b /* start synth processing char */ +static int full_status = 0; +#define synth_full() (full_status = (inb_p(synth_port_tts) == 0x13)) +#define SPK_SERIAL_TIMEOUT 1000000 /* countdown values for serial timeouts */ +#define SPK_XMITR_TIMEOUT 1000000 /* countdown values transmitter/dsr timeouts */ +#define SPK_LO_TTY 0 /* check ttyS0 ... ttyS3 */ +#define SPK_HI_TTY 3 +#define NUM_DISABLE_TIMEOUTS 3 /* # of timeouts permitted before disable */ + +static int dectlk_alive = 0; + /* 160 ms delay and ctrl-x as flush */ +#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) + +static struct serial_state rs_table[] __initdata = { + SERIAL_PORT_DFNS +}; + +static int timeouts = 0; /* sequential number of timeouts */ + +static int +wait_for_xmitr (void) +{ + int check; + unsigned int tmout = SPK_XMITR_TIMEOUT; + + if ((dectlk_alive) && (timeouts >= NUM_DISABLE_TIMEOUTS)) { + dectlk_alive = 0; + timeouts = 0; + return 0; + } + + /* holding register empty? */ + do { + check = inb_p(synth_port_tts + UART_LSR); + if (--tmout == 0) { + printk ("Dectalk Express: timed out\n"); + timeouts++; + return 0; + } + } while ((check & BOTH_EMPTY) != BOTH_EMPTY); + + tmout = SPK_XMITR_TIMEOUT; + /* CTS */ + do { + check = inb_p (synth_port_tts + UART_MSR); + if (--tmout == 0) { + timeouts++; + return 0; + } + } while ((check & UART_MSR_CTS) != UART_MSR_CTS); + + timeouts = 0; + return 1; +} + +static inline int +spk_serial_out (const char ch) +{ + if (dectlk_alive && synth_port_tts) { + if (wait_for_xmitr ()) { + outb_p (ch, synth_port_tts); + return 1; + } + } + return 0; +} + +static unsigned char __init +spk_serial_in (void) +{ + int lsr, tmout = SPK_SERIAL_TIMEOUT; + int c; + + do { + lsr = inb_p (synth_port_tts + UART_LSR); + if (--tmout == 0) + return 0xff; + } while (!(lsr & UART_LSR_DR)); + c = inb_p (synth_port_tts + UART_RX); + return (unsigned char) c; +} + +static void +do_catch_up (unsigned long data) +{ + unsigned long jiff_in = jiffies; + + synth_stop_timer (); + while ((synth_sent_bytes < synth_queued_bytes) && !synth_full ()) { + if (!spk_serial_out (*(synth_buffer + synth_sent_bytes))) { + synth_delay (synth_full_time); + return; + } + synth_sent_bytes++; + if (jiffies >= jiff_in + synth_jiffy_delta + && *(synth_buffer + synth_sent_bytes - 1) == ' ') { + spk_serial_out (PROCSPEECH); + synth_delay (synth_delay_time); + return; + } + } + + if (full_status) { + synth_delay (synth_full_time); + return; + } + synth_sent_bytes = synth_queued_bytes = 0; + synth_trigger_time = 50; + spk_serial_out (PROCSPEECH); + synth_timer_active = 0; + if (waitqueue_active (&synth_sleeping_list)) + wake_up_interruptible (&synth_sleeping_list); +} + +static inline void +synth_immediate_tts (const char *buf, size_t count) +{ + while (count--) + spk_serial_out (*buf++); + return; +} + +static void +synth_write_tts (char ch) +{ +/* int i = SPK_SERIAL_TIMEOUT; */ + static char last = '['; + + if (!dectlk_alive) + return; + if (ch < 0x00) + return; /* don't want unprintable chars */ + if (ch == 0x0a) /* turn lf into to force talking. */ + ch = 0x0D; + if (strchr ("-'", ch)) + ch = ' '; + if (ch == SYNTH_CLEAR) { /* clear all and wake sleeping */ + spk_serial_out (ch); + /*while(spk_serial_in() != 0x01 && i-- > 0); */ + synth_trigger_time = 100; + if (waitqueue_active (&synth_sleeping_list)) + wake_up_interruptible (&synth_sleeping_list); +#if LINUX_VERSION_CODE >= 0x020300 + if (synth_timer.list.prev) + synth_stop_timer (); +#else + if (synth_timer.prev) + synth_stop_timer (); +#endif + synth_timer_active = synth_queued_bytes = synth_sent_bytes = 0; + return; + } + + synth_buffer_add (ch); + if ((last != '[') && strchr (",_.@!?/-:", ch)) + synth_buffer_add (PROCSPEECH); + last = ch; + if (synth_buffering) + return; + if (synth_timer_active == 0) + synth_delay (synth_trigger_time); + return; +} + +static int __init +serprobe (int index) +{ + struct serial_state *ser = NULL; + unsigned char test = 0; + + if (synth_port_tts) { + for (test = 0; test <= SPK_HI_TTY; test++) + if ((rs_table + test)->port == synth_port_tts) { + ser = rs_table + test; + break; + } + } else + ser = rs_table + index; + + /* don't do output yet... */ + if (synth_request_region (ser->port, 8)) + return -1; + + initialize_uart(ser); + /* If we read 0xff from the LSR, there is no UART here. */ + if (inb (ser->port + UART_LSR) == 0xff) { + synth_release_region (ser->port, 8); + return -1; + } + mdelay (1); + outb (0x0d, ser->port); + + dectlk_alive = 1; + /* ignore any error results, if port was forced */ + if (synth_port_tts) + return 0; + + synth_port_tts = ser->port; + /* check for dectalk express now... */ + if (spk_serial_out (0x03)) { + while (spk_serial_in () != 0x01) ; + return 0; + } + + synth_release_region (ser->port, 8); + timeouts = dectlk_alive = synth_port_tts = 0; /* not ignoring */ + return -1; +} + +static int __init +synth_dev_probe (void) +{ + int i = 0; + + printk ("Probing for Dectalk Express.\n"); + if (synth_port_tts) + printk ("probe forced to 0x%x by kernel command line\n", + synth_port_tts); + + /* check ttyS0-ttyS3 */ + for (i = SPK_LO_TTY; i <= SPK_HI_TTY; i++) { + if (serprobe (i) == 0) + break; /* found it */ + } + + if (dectlk_alive) { + /* found 'em */ + printk ("Dectalk Express: %03x-%03x, Driver Version %s,\n", + synth_port_tts, synth_port_tts + 7, synth->version); + synth_immediate_tts (synth->init, strlen (synth->init)); + return 0; + } + + printk ("Dectalk Express: not found\n"); + return -ENODEV; +} + +static int +synth_alive (void) +{ + if (dectlk_alive) + return 1; /* already on */ + else if ((!dectlk_alive) && (synth_port_tts)) { + if (wait_for_xmitr () > 0) { /* restart */ + dectlk_alive = 1; + synth_write (synth->reinit, strlen (synth->reinit)); + return 2; /* reenabled */ + } else + printk ("Dectalk Express: can't restart synth\n"); + } + return 0; +} + +static const char init_string[] = + "[:ra 300][:dv ap 100][:punc n][:pe -380]Dectalk Express found\n"; +static const char reinit_string[] = + "[:ra 300][:dv ap 100][:punc n][:pe -380]Dectalk restarted\n"; + +static struct spk_variable vars[] = + { {"flush", "\x03", "_", (BUILDER | HARD_DIRECT | USE_RANGE | NO_USER), + "*"}, +{"pitch", "100", "[:dv ap _]", (NUMERIC | HARD_DIRECT | USE_RANGE), "50,350"}, +{"caps_start", "[:dv ap 222]", "_", 0, "*"}, +{"caps_stop", "[:dv ap 100]", "_", 0, "*"}, +{"rate", "300", "[:ra _]", (NUMERIC | HARD_DIRECT | USE_RANGE), "75,650"}, +{"volume", "65", "[:dv gv _]", (NUMERIC | HARD_DIRECT | USE_RANGE), "0,80"}, +{"voice", "p", "[:n_]", HARD_DIRECT, "phfdburwkv"}, +{"punct", "n", "[:pu _]", HARD_DIRECT, "nsa"}, +END_VARS +}; + +static char *config[] = + { "\x03", "[:dv ap 100]", "[:dv ap 222]", "[:dv ap 100]", "[:ra 300]", + "[:dv gv 65]", "[:np]", "[:pu n]" +}; + +struct spk_synth synth_dectlk = { "dectlk", "Version-0.12", "dec_express", + init_string, reinit_string, 500, 50, 5, 1000, + vars, config, 0, synth_dev_probe, do_catch_up, + synth_write_tts, synth_alive +}; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/speakup/speakup_drvcommon.c linux.19rc3-ac4/drivers/char/speakup/speakup_drvcommon.c --- linux.19rc3/drivers/char/speakup/speakup_drvcommon.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/speakup/speakup_drvcommon.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,399 @@ +#define KERNEL +#include +#include +#include /* for isdigit() and friends */ +#include +#include /* for verify_area */ +#include /* for -EBUSY */ +#include /* for check_region, request_region */ +#include /* for loops_per_sec */ +#include /* for put_user_byte */ +#include /* for inb_p, outb_p, inb, outb, etc... */ +#include /* for wait_queue */ +#include /* kd_mksound */ +#include /* for __init */ +#include +#include /* for rs_table, serial constants & + serial_uart_config */ +#include /* for more serial constants */ +#include /* for struct serial_state */ +#include +#include + +#define synthBufferSize 8192 /* currently 8K bytes */ +struct spk_synth *synth = NULL; +unsigned char synth_jiffy_delta = HZ/20; +int synth_port_tts = 0; +volatile int synth_timer_active = 0; /* indicates when a timer is set */ +DECLARE_WAIT_QUEUE_HEAD (synth_sleeping_list); +struct timer_list synth_timer; +unsigned short synth_delay_time = 500; /* time to schedule handler */ +unsigned short synth_trigger_time = 50; +unsigned short synth_full_time = 1000; /* time before coming back when synth is full */ +char synth_buffering = 1; /* flag to indicate we're buffering */ +unsigned char synth_buffer[synthBufferSize]; /* guess what this is for! */ +unsigned short synth_end_of_buffer = synthBufferSize; +volatile unsigned short synth_queued_bytes = 0, synth_sent_bytes = 0; +/* synth_queued_bytes points to top of chars queued, + * synth_sent_bytes points at top of bytes sent by synth->catch_up() */ + +void +initialize_uart(struct serial_state *ser) +{ + int baud = 9600; + int quot = 0; + unsigned cval = 0; + int cflag = CREAD | HUPCL | CLOCAL | B9600 | CS8; + + /* + * Divisor, bytesize and parity + */ + quot = ser->baud_base / baud; + cval = cflag & (CSIZE | CSTOPB); +#if defined(__powerpc__) || defined(__alpha__) + cval >>= 8; +#else /* !__powerpc__ && !__alpha__ */ + cval >>= 4; +#endif /* !__powerpc__ && !__alpha__ */ + if (cflag & PARENB) + cval |= UART_LCR_PARITY; + if (!(cflag & PARODD)) + cval |= UART_LCR_EPAR; + + /* + * Disable UART interrupts, set DTR and RTS high + * and set speed. + */ + outb(cval | UART_LCR_DLAB, ser->port + UART_LCR); /* set DLAB */ + outb(quot & 0xff, ser->port + UART_DLL); /* LS of divisor */ + outb(quot >> 8, ser->port + UART_DLM); /* MS of divisor */ + outb(cval, ser->port + UART_LCR); /* reset DLAB */ + outb(0, ser->port + UART_IER); + outb(UART_MCR_DTR | UART_MCR_RTS, ser->port + UART_MCR); +} + +/* sleep for ms milliseconds */ +void +synth_delay (int ms) +{ + synth_timer.expires = jiffies + (ms * HZ + 1000 - HZ) / 1000; +# if (LINUX_VERSION_CODE >= 0x20300) /* is it a 2.3.x kernel? */ + if (!synth_timer.list.prev) + add_timer (&synth_timer); +# else + if (!synth_timer.prev) + add_timer (&synth_timer); +# endif + synth_timer_active++; +} + +void +synth_stop_timer (void) +{ + if (synth_timer_active) + del_timer (&synth_timer); +} + +void +synth_buffer_add (char ch) +{ + /* someone needs to take a nap for a while. */ + if (synth_queued_bytes + 1 == synth_end_of_buffer - 100 + && (!waitqueue_active (&synth_sleeping_list))) { + interruptible_sleep_on (&synth_sleeping_list); + } + *(synth_buffer + synth_queued_bytes++) = ch; +} + +void +synth_write (const char *buf, size_t count) +{ + while (count--) + synth->write (*buf++); +} + +#if LINUX_VERSION_CODE >= 0x20300 +static struct resource synth_res; +#endif + +int __init +synth_request_region (unsigned long start, unsigned long n) +{ +#if (LINUX_VERSION_CODE >= 0x20300) /* is it a 2.3.x kernel? */ + struct resource *parent = &ioport_resource; + + memset (&synth_res, 0, sizeof (synth_res)); + synth_res.name = synth->name; + synth_res.start = start; + synth_res.end = start + n - 1; + synth_res.flags = IORESOURCE_BUSY; + + return request_resource (parent, &synth_res); +#else + if (check_region (start, n)) + return -EBUSY; + request_region (start, n, synth->name); + return 0; +#endif +} + +int __init +synth_release_region (unsigned long start, unsigned long n) +{ +#if (LINUX_VERSION_CODE >= 0x20300) + return release_resource (&synth_res); +#else + release_region (start, n); + return 0; +#endif +} + +#ifdef CONFIG_PROC_FS + +// /proc/synth-specific code + +#include +#include + +static struct proc_dir_entry *proc_speakup_synth; + +// this is the read handler for /proc/speakup/synth-specific vars +static int +speakup_vars_read_proc (char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + struct proc_dir_entry *ent = data; + + *start = 0; + *eof = 1; + + if (!strcmp (ent->name, "jiffy_delta")) + return sprintf (page, "%d\n", synth_jiffy_delta); + if (!strcmp (ent->name, "delay_time")) + return sprintf (page, "%d\n", synth_delay_time); + if (!strcmp (ent->name, "queued_bytes")) + return sprintf (page, "%d\n", synth_queued_bytes); + if (!strcmp (ent->name, "sent_bytes")) + return sprintf (page, "%d\n", synth_sent_bytes); + if (!strcmp (ent->name, "trigger_time")) + return sprintf (page, "%d\n", synth_trigger_time); + if (!strcmp (ent->name, "full_time")) + return sprintf (page, "%d\n", synth_full_time); + if (!strcmp (ent->name, "version")) + return sprintf (page, "%s\n", synth->version); + + return sprintf (page, "%s slipped through the cracks!\n", ent->name); +} + +#define RESET_DEFAULT -4 + +// this is the write handler for /proc/speakup/synth-specific vars +static int +speakup_vars_write_proc (struct file *file, const char *buffer, + unsigned long count, void *data) +{ + struct proc_dir_entry *ent = data; + int i, len = count, val = 0, ret = -ERANGE; + long min = 0, max = 0; + char *page; + + if (!(page = (char *) __get_free_page (GFP_KERNEL))) + return -ENOMEM; + if (copy_from_user (page, buffer, count)) { + ret = -EFAULT; + goto out; + } + // lose the newline + if (page[len - 1] == '\n') + --len; + + // trigger_time is an unsigned short 0 <= val <= 65535 + if (!strcmp (ent->name, "trigger_time")) { + if (!len) { + synth_trigger_time = synth->trigger_time; + ret = RESET_DEFAULT; + goto out; + } + max = 65535; + // 1 to 5 digits + if (len < 1 || len > 5) + goto out; + for (i = 0; i < len; ++i) { + if (!isdigit (page[i])) + goto out; + val *= 10; + val += page[i] - '0'; + } + if (val < min || val > max) + goto out; + synth_trigger_time = val; + ret = count; + } + // full_time is an unsigned short 0 <= val <= 65535 + else if (!strcmp (ent->name, "full_time")) { + if (!len) { + synth_full_time = synth->full_time; + ret = RESET_DEFAULT; + goto out; + } + max = 65535; + // 1 to 5 digits + if (len < 1 || len > 5) + goto out; + for (i = 0; i < len; ++i) { + if (!isdigit (page[i])) + goto out; + val *= 10; + val += page[i] - '0'; + } + if (val < min || val > max) + goto out; + synth_full_time = val; + ret = count; + } + // jiffy_delta is an unsigned char 0 <= val <= 255 + else if (!strcmp (ent->name, "jiffy_delta")) { + if (!len) { + synth_jiffy_delta = synth->jiffy_delta; + ret = RESET_DEFAULT; + goto out; + } + max = 255; + // 1 to 3 digits + if (len < 1 || len > 3) + goto out; + for (i = 0; i < len; ++i) { + if (!isdigit (page[i])) + goto out; + val *= 10; + val += page[i] - '0'; + } + if (val < min || val > max) + goto out; + synth_jiffy_delta = val; + ret = count; + } + // delay_time is an unsigned short 0 <= val <= 65535 + else if (!strcmp (ent->name, "delay_time")) { + if (!len) { + synth_delay_time = synth->delay_time; + ret = RESET_DEFAULT; + goto out; + } + max = 65535; + // 1 to 5 digits + if (len < 1 || len > 5) + goto out; + for (i = 0; i < len; ++i) { + if (!isdigit (page[i])) + goto out; + val *= 10; + val += page[i] - '0'; + } + if (val < min || val > max) + goto out; + synth_delay_time = val; + ret = count; + } + + out: + if (ret == -ERANGE) { + printk (KERN_ALERT + "setting %s (%.*s): value out of range (%ld-%ld)\n", + ent->name, len, page, min, max); + ret = count; + } else if (ret == RESET_DEFAULT) { + printk (KERN_ALERT "%s reset to default value\n", ent->name); + ret = count; + } + free_page ((unsigned long) page); + return ret; +} + +#define MIN(a,b) ( ((a) < (b))?(a):(b) ) + +// this is the write handler for /proc/speakup/synth-specific/direct +static int +speakup_direct_write_proc (struct file *file, const char *buffer, + unsigned long count, void *data) +{ + static const int max_buf_len = 100; + unsigned char buf[max_buf_len + 1]; + int ret = count; + extern char *xlate (char *); + + if (copy_from_user (buf, buffer, count = (MIN (count, max_buf_len)))) + return -EFAULT; + buf[count] = '\0'; + xlate (buf); + synth_write (buf, strlen (buf)); + return ret; +} + +char *read_only[] = { + "queued_bytes", "sent_bytes", "version", NULL +}; + +char *root_writable[] = { + "delay_time", "full_time", "jiffy_delta", "trigger_time", NULL +}; + +// called by proc_speakup_init() to initialize the /proc/speakup/synth-specific subtree +void +proc_speakup_synth_init (void) +{ + struct proc_dir_entry *ent; + char *dir = "speakup/"; + char path[80]; + int i; + + sprintf (path, "%s%s", dir, synth->proc_name); + proc_speakup_synth = create_proc_entry (path, S_IFDIR, 0); + if (!proc_speakup_synth) { + printk (KERN_WARNING "Unable to create /proc/%s entry.\n", + path); + return; + } + + for (i = 0; read_only[i]; ++i) { + sprintf (path, "%s%s/%s", dir, synth->proc_name, read_only[i]); + ent = create_proc_entry (path, S_IFREG | S_IRUGO, 0); + ent->read_proc = speakup_vars_read_proc; + ent->data = (void *) ent; + } + + for (i = 0; root_writable[i]; ++i) { + sprintf (path, "%s%s/%s", dir, synth->proc_name, root_writable[i]); + ent = create_proc_entry (path, S_IFREG | S_IRUGO | S_IWUSR, 0); + ent->read_proc = speakup_vars_read_proc; + ent->write_proc = speakup_vars_write_proc; + ent->data = (void *) ent; + } + + sprintf (path, "%s%s/direct", dir, synth->proc_name); + ent = create_proc_entry (path, S_IFREG | S_IWUGO, 0); + ent->write_proc = speakup_direct_write_proc; +} + +#endif + +int __init +synth_init (void) +{ + if (synth->probe () < 0) { + printk ("%s: device probe failed\n", synth->name); + return -ENODEV; + } + init_timer (&synth_timer); + synth_timer.function = synth->catch_up; +#if (LINUX_VERSION_CODE >= 0x20300) /* it's a 2.3.x kernel */ + init_waitqueue_head (&synth_sleeping_list); +#else /* it's a 2.2.x kernel */ + init_waitqueue (&synth_sleeping_list); +#endif + synth_delay_time = synth->delay_time; + synth_trigger_time = synth->trigger_time; + synth_jiffy_delta = synth->jiffy_delta; + synth_full_time = synth->full_time; + return 0; +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/speakup/speakup_dtlk.c linux.19rc3-ac4/drivers/char/speakup/speakup_dtlk.c --- linux.19rc3/drivers/char/speakup/speakup_dtlk.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/speakup/speakup_dtlk.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,259 @@ +/* + * speakup_dtlk.c - DoubleTalk PC driver for Linux kernel 2.3.x and speakup + * + * author: Kirk Reiser + + Copyright (C) 1998-99 Kirk Reiser. + + 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 + + Kirk Reiser + 261 Trott dr. London, Ontario, Canada. N6G 1B6 + */ + + +/* These routines are written to control the Double Talk PC speech + synthesizer. They are not ment to be thought of as a device driver + in that they do not register themselves as a chr device and there + is no file_operations structure. They are strictly to provide an + interface to the DoubleTalk from the speakup screen review package. +*/ + +#define KERNEL +#include +#include +#include +#include /* for verify_area */ +#include /* for -EBUSY */ +#include /* for check_region, request_region */ +#include /* for loops_per_sec */ +#include /* for put_user_byte */ +#include /* for inb_p, outb_p, inb, outb, etc... */ +#include /* for wait_queue */ +#include /* kd_mksound */ +#include /* for __init */ +#include /* need to know if 2.2.x or 2.3.x */ + +#include +#include "speakup_dtlk.h" /* local header file for DoubleTalk values */ + +#define synth_readable() ((synth_status = inb_p(synth_port_tts)) & TTS_READABLE) +#define synth_full() ((synth_status = inb_p(synth_port_tts)) & TTS_ALMOST_FULL) +static int synth_port_lpc; +static unsigned int synth_portlist[] = + { 0x25e, 0x29e, 0x2de, 0x31e, 0x35e, 0x39e, 0 }; +/* 200ms delay */ +static unsigned char synth_status = 0; /* speed up some checks which are done regularly */ + +static inline void spk_out(const char ch) +{ +int tmout = 100000; + + while (((synth_status = inb_p(synth_port_tts)) & TTS_WRITABLE) == 0); +outb_p(ch, synth_port_tts); + while ((((synth_status = inb_p(synth_port_tts)) & TTS_WRITABLE) != 0) + && (--tmout != 0) ); +} + +static void do_catch_up(unsigned long data) +{ +unsigned long jiff_in = jiffies; + +synth_stop_timer(); +synth_status = inb_p(synth_port_tts); +while ((synth_sent_bytes < synth_queued_bytes) && !(synth_status & TTS_ALMOST_FULL)) + { + spk_out(*(synth_buffer+synth_sent_bytes++)); + if (jiffies >= jiff_in+synth_jiffy_delta && *(synth_buffer+synth_sent_bytes-1) == ' ') { + spk_out(0x00); + synth_delay(synth_delay_time); + return; + } + } +if (synth_status & TTS_ALMOST_FULL) + { + synth_delay(synth_full_time); + return; + } +spk_out(0x00); +synth_sent_bytes = synth_queued_bytes = 0; +synth_timer_active = 0; +if (waitqueue_active(&synth_sleeping_list)) + wake_up_interruptible(&synth_sleeping_list); +} + +static void synth_write_tts(char ch) +{ + + if (ch < 0x00) return; /* don't want unprintable chars */ + if (ch == 0x0a) /* turn lf into NULL to force talking. */ + ch = 0x00; + if (ch == SYNTH_CLEAR) { /* clear all and wake sleeping */ + outb_p(ch, synth_port_tts); /* output to TTS port */ + while (((synth_status = inb_p(synth_port_tts)) & TTS_WRITABLE) != 0); + if (waitqueue_active(&synth_sleeping_list)) + wake_up_interruptible(&synth_sleeping_list); + synth_queued_bytes = synth_sent_bytes = 0; + return; + } + + synth_buffer_add(ch); + if (synth_buffering) return; + if (synth_timer_active == 0) synth_delay( synth_trigger_time ); +} + +static inline void synth_immediate_tts(const char *buf, short count) +{ +char ch; + + while (count--) { + ch = *buf++; + if (ch != SYNTH_CLEAR) + spk_out(ch); /* output to TTS port */ + } +} + +static char __init synth_read_tts(void) +{ +unsigned char ch; + + while (((synth_status = inb_p(synth_port_tts)) & TTS_READABLE) == 0); + ch = synth_status & 0x7f; + outb_p(ch, synth_port_tts); + while ((inb_p(synth_port_tts) & TTS_READABLE) != 0); +return (char) ch; +} + +/* interrogate the DoubleTalk PC and return its settings */ +static struct synth_settings * __init synth_interrogate(void) +{ +unsigned char *t; +static char buf[sizeof(struct synth_settings) + 1]; +int total, i; +static struct synth_settings status; + + synth_immediate_tts("\x18\x01?", 3); + + for (total = 0, i = 0; i < 50; i++) + { + buf[total] = synth_read_tts(); + if (total > 2 && buf[total] == 0x7f) break; + if (total < sizeof(struct synth_settings)) total++; + } + + t = buf; + status.serial_number = t[0] + t[1]*256; /* serial number is little endian */ + t += 2; + + i = 0; + while (*t != '\r') + { + status.rom_version[i] = *t; + if (i < sizeof(status.rom_version)-1) i++; + t++; + } + status.rom_version[i] = 0; + t++; + + status.mode = *t++; + status.punc_level = *t++; + status.formant_freq = *t++; + status.pitch = *t++; + status.speed = *t++; + status.volume = *t++; + status.tone = *t++; + status.expression = *t++; + status.ext_dict_loaded = *t++; + status.ext_dict_status = *t++; + status.free_ram = *t++; + status.articulation = *t++; + status.reverb = *t++; + status.eob = *t++; + return &status; +} + +static int __init synth_dev_probe(void) +{ +unsigned int port_val = 0; +int i = 0; +struct synth_settings *sp; + + printk("Probing for DoubleTalk.\n"); + if (synth_port_tts) { + printk("probe forced to %x by kernel command line\n", synth_port_tts); + if (synth_request_region(synth_port_tts-1, SYNTH_IO_EXTENT)) { + printk("sorry, port already reserved\n"); + return -EBUSY; + } + port_val = inw(synth_port_tts-1); + synth_port_lpc = synth_port_tts-1; + } + else { + for(i=0; synth_portlist[i]; i++) { + if (synth_request_region(synth_portlist[i], SYNTH_IO_EXTENT)) + continue; + port_val = inw(synth_portlist[i]); + if ((port_val &= 0xfbff) == 0x107f) { + synth_port_lpc = synth_portlist[i]; + synth_port_tts = synth_port_lpc+1; + break; + } + synth_release_region(synth_portlist[i], SYNTH_IO_EXTENT); + } + } + + if ((port_val &= 0xfbff) != 0x107f) { + printk("DoubleTalk PC: not found\n"); + return -ENODEV; + } + + while (inw_p(synth_port_lpc) != 0x147f ); /* wait until it's ready */ + sp = synth_interrogate(); + printk("DoubleTalk PC: %03x-%03x, ROM version %s,\n" + "DoubleTalk PC: serial number %u, driver: %s\n", + synth_port_lpc, synth_port_lpc+SYNTH_IO_EXTENT - 1, + sp->rom_version, sp->serial_number, synth->version); + synth_immediate_tts(synth->init, strlen(synth->init)); + return 0; +} + +static int synth_alive(void) { + return 1; /* I'm *INVINCIBLE* */ +} + +static const char init_string[] = "\x01@doubletalk found\n\x01\x31y\n"; +static const char reinit_string[] = "\x01@doubletalk found\n\x01\x31y\n"; + +static struct spk_variable vars[] = +{{"flush", "\x18", "_", (BUILDER|HARD_DIRECT|USE_RANGE|NO_USER), "*"}, + {"pitch", "50", "\x01_p", (NUMERIC|HARD_DIRECT|USE_RANGE), "0,99"}, + {"caps_start", "\x01+35p", "_", 0, "*"}, + {"caps_stop", "\x01-35p", "_", 0, "*"}, + {"rate", "5", "\x01_s", (NUMERIC|HARD_DIRECT|USE_RANGE), "0,9"}, + {"tone", "1", "\x01_x", (NUMERIC|HARD_DIRECT|USE_RANGE), "0,2"}, + {"volume", "5", "\x01_v", (NUMERIC|HARD_DIRECT|USE_RANGE), "0,9"}, + {"voice", "0", "\x01_o", (NUMERIC|HARD_DIRECT|USE_RANGE), "0,7"}, + {"ffreq", "5", "\x01_f", (NUMERIC|HARD_DIRECT|USE_RANGE), "0,9"}, + {"punct", "7", "\x01_b", (NUMERIC|HARD_DIRECT|USE_RANGE), "0,15"}, + END_VARS}; + +static char *config[] = +{"\x18", "\x01\x35\x30p", "\x01\x38\x35p", "\x01\x35\x30p", "\x01\x35s", + "\x01\x31x", "\x01\x35v", "\x01\x30o", "\x01\x35\x66", "\x01\x37\x62"}; + +struct spk_synth synth_dtlk = {"dtlk", "Version-0.13", "doubletalk_pc", + init_string, reinit_string, 500, 50, 5, 1000, + vars, config, 0, synth_dev_probe, do_catch_up, + synth_write_tts, synth_alive}; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/speakup/speakup_dtlk.h linux.19rc3-ac4/drivers/char/speakup/speakup_dtlk.h --- linux.19rc3/drivers/char/speakup/speakup_dtlk.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/speakup/speakup_dtlk.h 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,57 @@ +/* speakup_dtlk.h - header file for speakups DoubleTalk driver. */ + +#define SYNTH_IO_EXTENT 0x02 + +#define SYNTH_CLEAR 0x18 /* stops speech */ + + /* TTS Port Status Flags */ +#define TTS_READABLE 0x80 /* mask for bit which is nonzero if a + byte can be read from the TTS port */ +#define TTS_SPEAKING 0x40 /* mask for SYNC bit, which is nonzero + while DoubleTalk is producing + output with TTS, PCM or CVSD + synthesizers or tone generators + (that is, all but LPC) */ +#define TTS_SPEAKING2 0x20 /* mask for SYNC2 bit, + which falls to zero up to 0.4 sec + before speech stops */ +#define TTS_WRITABLE 0x10 /* mask for RDY bit, which when set to + 1, indicates the TTS port is ready + to accept a byte of data. The RDY + bit goes zero 2-3 usec after + writing, and goes 1 again 180-190 + usec later. */ +#define TTS_ALMOST_FULL 0x08 /* mask for AF bit: When set to 1, + indicates that less than 300 bytes + are available in the TTS input + buffer. AF is always 0 in the PCM, + TGN and CVSD modes. */ +#define TTS_ALMOST_EMPTY 0x04 /* mask for AE bit: When set to 1, + indicates that less than 300 bytes + are remaining in DoubleTalk's input + (TTS or PCM) buffer. AE is always 1 + in the TGN and CVSD modes. */ + + /* data returned by Interrogate command */ +struct synth_settings +{ + unsigned short serial_number; /* 0-7Fh:0-7Fh */ + unsigned char rom_version[24]; /* null terminated string */ + unsigned char mode; /* 0=Character; 1=Phoneme; 2=Text */ + unsigned char punc_level; /* nB; 0-7 */ + unsigned char formant_freq; /* nF; 0-9 */ + unsigned char pitch; /* nP; 0-99 */ + unsigned char speed; /* nS; 0-9 */ + unsigned char volume; /* nV; 0-9 */ + unsigned char tone; /* nX; 0-2 */ + unsigned char expression; /* nE; 0-9 */ + unsigned char ext_dict_loaded; /* 1=exception dictionary loaded */ + unsigned char ext_dict_status; /* 1=exception dictionary enabled */ + unsigned char free_ram; /* # pages (truncated) remaining for + text buffer */ + unsigned char articulation; /* nA; 0-9 */ + unsigned char reverb; /* nR; 0-9 */ + unsigned char eob; /* 7Fh value indicating end of + parameter block */ + unsigned char has_indexing; /* nonzero if indexing is implemented */ +}; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/speakup/speakup_ltlk.c linux.19rc3-ac4/drivers/char/speakup/speakup_ltlk.c --- linux.19rc3/drivers/char/speakup/speakup_ltlk.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/speakup/speakup_ltlk.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,342 @@ +/* + * speakup_ltlk.c - LiteTalk driver for Linux kernel 2.3.x and speakup + * + * author: Kirk Reiser and Andy Berdan + + Copyright (C) 1998-99 Kirk Reiser, and Andy Berdan + + 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 + + Kirk Reiser + 261 Trott dr. London, Ontario, Canada. N6G 1B6 + + Andy Berdan + 3-337 Wharncliffe Rd. N London, Ontario, Canada N6G 1E4 + */ + + +/* These routines are written to control the Lite Talk speech + synthesizer. They are not ment to be thought of as a device driver + in that they do not register themselves as a chr device and there + is no file_operations structure. They are strictly to provide an + interface to the LiteTalk from the speakup screen review package. +*/ + +#define KERNEL +#include +#include +#include +#include /* for verify_area */ +#include /* for -EBUSY */ +#include /* for check_region, request_region */ +#include /* for loops_per_sec */ +#include /* for put_user_byte */ +#include /* for inb_p, outb_p, inb, outb, etc... */ +#include /* for wait_queue */ +#include /* kd_mksound */ +#include /* for __init */ +#include +#include /* for rs_table, serial constants & + serial_uart_config */ +#include /* for more serial constants */ +#if (LINUX_VERSION_CODE >= 0x20300) /* v 2.3.x */ +#include /* for struct serial_state */ +#endif +#include +#include + +#include "speakup_dtlk.h" /* local header file for LiteTalk values */ + +#define synth_full() ( !(inb(synth_port_tts + UART_MSR) & UART_MSR_CTS) ) +#define PROCSPEECH 0x00 /* synth process speech char */ +#define SPK_SERIAL_TIMEOUT 1000000 /* countdown values for serial timeouts */ +#define SPK_XMITR_TIMEOUT 3000000 /* countdown values transmitter/dsr timeouts */ +#define SPK_LO_TTY 0 /* check ttyS0 ... ttyS3 */ +#define SPK_HI_TTY 3 +#define NUM_DISABLE_TIMEOUTS 3 /* # of timeouts permitted before disable */ + +static int ltlk_alive = 0; + +#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) + +static struct serial_state rs_table[] __initdata = { + SERIAL_PORT_DFNS +}; + +static inline int wait_for_xmitr(void) +{ + static int timeouts = 0; /* sequential number of timeouts */ + int check, tmout = SPK_XMITR_TIMEOUT; + + if ((ltlk_alive) && (timeouts >= NUM_DISABLE_TIMEOUTS)) { + ltlk_alive = 0; + timeouts = 0; + return 0; + } + + /* holding register empty? */ + + do { + check = inb(synth_port_tts + UART_LSR); + if (--tmout == 0) { + printk("LiteTalk: register timed out\n"); + timeouts++; + return 0; + } + } while ((check & BOTH_EMPTY) != BOTH_EMPTY); + tmout = SPK_XMITR_TIMEOUT; + + /* CTS */ + do { + check = inb(synth_port_tts + UART_MSR); + if (--tmout == 0) { + timeouts++; + return 0; + } + } while ((check & UART_MSR_CTS) != UART_MSR_CTS); + + timeouts = 0; + return 1; +} + +static inline int spk_serial_out(const char ch) +{ + if (ltlk_alive && synth_port_tts) { + if (wait_for_xmitr()) { + outb(ch, synth_port_tts); + return 1; + } + } + return 0; +} + +static unsigned char __init spk_serial_in(void) +{ + int c, lsr, tmout = SPK_SERIAL_TIMEOUT; + + do { + lsr = inb(synth_port_tts + UART_LSR); + if (--tmout == 0) { + printk("time out while waiting for input.\n"); + return 0xff; + } + } while ((lsr & UART_LSR_DR) != UART_LSR_DR); + c = inb(synth_port_tts + UART_RX); + return (unsigned char) c; +} + +static void do_catch_up(unsigned long data) +{ + unsigned long jiff_in = jiffies; + + synth_stop_timer(); + while (synth_sent_bytes < synth_queued_bytes) + { + if (!spk_serial_out(*(synth_buffer+synth_sent_bytes))) { + synth_delay(synth_full_time); + return; + } + synth_sent_bytes++; + if (jiffies >= jiff_in+synth_jiffy_delta + && *(synth_buffer+synth_sent_bytes-1) == ' ') { + spk_serial_out(PROCSPEECH); + synth_delay(synth_delay_time); + return; + } + } + + synth_sent_bytes = synth_queued_bytes = 0; + spk_serial_out(PROCSPEECH); + synth_timer_active = 0; + if (waitqueue_active(&synth_sleeping_list)) + wake_up_interruptible(&synth_sleeping_list); +} + +static void synth_write_tts(char ch) +{ + if (!ltlk_alive) return; + if (ch < 0x00) return; /* don't want unprintable chars */ + if (ch == 0x0a) /* turn lf into to force talking. */ + ch = PROCSPEECH; + + /* clear all and wake sleeping */ + if (ch == SYNTH_CLEAR) { + spk_serial_out(ch); + if (waitqueue_active(&synth_sleeping_list)) + wake_up_interruptible(&synth_sleeping_list); + synth_timer_active = synth_queued_bytes = synth_sent_bytes = 0; + return; + } + + synth_buffer_add(ch); + if (synth_buffering) return; + if (synth_timer_active == 0) synth_delay( synth_trigger_time ); +} + +static inline void synth_immediate_tts(const char *buf, short count) +{ + while (count--) spk_serial_out(*buf++); + return; +} + +/* interrogate the LiteTalk and print its settings */ +static void __init synth_interrogate(void) +{ + unsigned char *t, i; + unsigned char buf[50], rom_v[20]; + + synth_immediate_tts("\x18\x01?", 3); + + for (i = 0; i < 50; i++) + { + buf[i] = spk_serial_in(); + if (i > 2 && buf[i] == 0x7f) break; + } + + t = buf+2; + i = 0; + while (*t != '\r') + { + rom_v[i] = *t; + t++; i++; + } + rom_v[i] = 0; + + printk("LiteTalk: ROM version: %s\n", rom_v); + return; +} + +static int __init serprobe(int index) +{ + struct serial_state *ser = NULL; + unsigned char test=0; + + if (synth_port_tts) { + for (test=0; test <= SPK_HI_TTY; test++) + if ( (rs_table+test)->port == synth_port_tts) { + ser = rs_table+test; + break; + } + } else ser = rs_table + index; + + /* don't do output yet... */ + if (synth_request_region(ser->port,8)) + return -1; + + initialize_uart(ser); + /* If we read 0xff from the LSR, there is no UART here. */ + if (inb (ser->port + UART_LSR) == 0xff) { + // printk("initial test = %x\n", test); + synth_release_region(ser->port,8); + return -1; + } + outb(0, ser->port); + mdelay(1); + outb('\r', ser->port); + + ltlk_alive = 1; + /* ignore any error results, if port was forced */ + if (synth_port_tts) { + return 0; + } + + synth_port_tts = ser->port; + + /* check for device... */ + if (spk_serial_out(SYNTH_CLEAR)) return 0; + /*spk_serial_out('@'); + mdelay(100); + + spk_serial_out(0); + + if ((spk_serial_in() == ('C'+ 0x80)) + && ((test = spk_serial_in()) > ('A' + 0x80)) + && (test < ('Z' + 0x80)) + && (spk_serial_in() == 0x8d) ) + return 0; */ + + synth_release_region(ser->port,8); + ltlk_alive = synth_port_tts = 0; /* try next port */ + return -1; +} + +static int __init synth_dev_probe(void) +{ + int i; + + printk("Probing for LiteTalk.\n"); + if (synth_port_tts) + printk("Probe forced to 0x%x by kernel command line\n", synth_port_tts); + + for (i=SPK_LO_TTY; i <= SPK_HI_TTY; i++) { + if (serprobe(i) == 0) break; /* found it */ + } + + if (ltlk_alive) { + /* found 'em */ + synth_interrogate(); + printk("LiteTalk: at %03x-%03x, driver %s\n", + synth_port_tts, synth_port_tts + 7, synth->version); + synth_write(synth->init, strlen(synth->init)); + return 0; + } + + printk("LiteTalk: not found\n"); + return -ENODEV; +} + +static int synth_alive(void) { + + if (ltlk_alive) { + return 1; /* already on */ + } else { + if ((!ltlk_alive) && (synth_port_tts)) { + if (wait_for_xmitr() > 0) { /* restart */ + ltlk_alive = 1; + synth_write(synth->reinit, strlen(synth->reinit)); + return 2; /* reenabled */ + } else printk("LiteTalk: can't restart synth\n"); + } + } + return 0; +} + +static const char init_string[] = "\01@light talk found\n\x01\x31y\n\0"; +static const char reinit_string[] = "\01@light talk restarted\n\x01\x31y\n\0"; +/* 200ms delay */ + +static struct spk_variable vars[] = +{ + { "flush", "\x18\x20", "_", (BUILDER|HARD_DIRECT|USE_RANGE|NO_USER), "*" }, + { "pitch", "50", "\x01_p", (NUMERIC|HARD_DIRECT|USE_RANGE), "0,99" }, + { "caps_start", "\x01+35p", "_", 0, "*" }, + { "caps_stop", "\x01-35p", "_", 0, "*" }, + { "rate", "5", "\x01_s", (NUMERIC|HARD_DIRECT|USE_RANGE), "0,9" }, + { "tone", "1", "\x01_x", (NUMERIC|HARD_DIRECT|USE_RANGE), "0,2" }, + { "volume", "5", "\x01_v", (NUMERIC|HARD_DIRECT|USE_RANGE), "0,9" }, + { "voice", "0", "\x01_o", (NUMERIC|HARD_DIRECT|USE_RANGE), "0,7" }, + { "ffreq", "5", "\x01_f", (NUMERIC|HARD_DIRECT|USE_RANGE), "0,9" }, + { "punct", "7", "\x01_b", (NUMERIC|HARD_DIRECT|USE_RANGE), "0,15" }, + END_VARS +}; + +static char *config[] = +{ "\x18\x20", "\x01\x35\x30p", "\x01\x38\x35p", "\x01\x35\x30p", "\x01\x35s", + "\x01\x31x", "\x01\x35v", "\x01\x30o", "\x01\x35\x66", "\x01\x37\x62" }; + +struct spk_synth synth_ltlk = { "ltlk", "Version-0.13", "litetalk", + init_string, reinit_string, 500, 50, 5, 5000, + vars, config, 0, synth_dev_probe, do_catch_up, + synth_write_tts, synth_alive }; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/speakup/speakupmap.c linux.19rc3-ac4/drivers/char/speakup/speakupmap.c --- linux.19rc3/drivers/char/speakup/speakupmap.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/speakup/speakupmap.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,298 @@ + +/* Do not edit this file! It was automatically generated by */ +/* loadkeys --mktable defkeymap.map > defkeymap.c */ + +#include +#include +#include + +u_short plain_map[NR_KEYS] = { + 0xf200, 0xf01b, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, + 0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf07f, 0xf009, + 0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69, + 0xfb6f, 0xfb70, 0xf05b, 0xf05d, 0xf201, 0xf702, 0xfb61, 0xfb73, + 0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b, + 0xf027, 0xf060, 0xf700, 0xf05c, 0xfb7a, 0xfb78, 0xfb63, 0xfb76, + 0xfb62, 0xfb6e, 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf700, 0xfd26, + 0xf703, 0xf020, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104, + 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf208, 0xf209, 0xfd0b, + 0xfd0a, 0xfd0c, 0xfd1e, 0xfd08, 0xfd07, 0xfd09, 0xfd14, 0xfd05, + 0xfd04, 0xfd06, 0xf701, 0xfd1b, 0xf206, 0xf200, 0xf03c, 0xf10a, + 0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xfd03, 0xf702, 0xfd27, 0xfd25, 0xf703, 0xf205, 0xf114, 0xf603, + 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short shift_map[NR_KEYS] = { + 0xf200, 0xf01b, 0xf021, 0xf040, 0xf023, 0xf024, 0xf025, 0xf05e, + 0xf026, 0xf02a, 0xf028, 0xf029, 0xf05f, 0xf02b, 0xf07f, 0xf009, + 0xfb51, 0xfb57, 0xfb45, 0xfb52, 0xfb54, 0xfb59, 0xfb55, 0xfb49, + 0xfb4f, 0xfb50, 0xf07b, 0xf07d, 0xf201, 0xf702, 0xfb41, 0xfb53, + 0xfb44, 0xfb46, 0xfb47, 0xfb48, 0xfb4a, 0xfb4b, 0xfb4c, 0xf03a, + 0xf022, 0xf07e, 0xf700, 0xf07c, 0xfb5a, 0xfb58, 0xfb43, 0xfb56, + 0xfb42, 0xfb4e, 0xfb4d, 0xf03c, 0xf03e, 0xf03f, 0xf700, 0xfd26, + 0xf703, 0xf020, 0xf207, 0xf10a, 0xf10b, 0xf10c, 0xf10d, 0xf10e, + 0xf10f, 0xf110, 0xf111, 0xf112, 0xf113, 0xf208, 0xf203, 0xfd0b, + 0xfd0a, 0xfd0c, 0xfd1e, 0xfd08, 0xfd07, 0xfd09, 0xfd14, 0xfd05, + 0xfd04, 0xfd06, 0xf701, 0xfd1b, 0xf206, 0xf200, 0xf03e, 0xf10a, + 0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xfd03, 0xf702, 0xfd27, 0xfd25, 0xf703, 0xf205, 0xf114, 0xf603, + 0xf20b, 0xf601, 0xf602, 0xf117, 0xf600, 0xf20a, 0xf115, 0xf116, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short altgr_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf040, 0xf200, 0xf024, 0xf200, 0xf200, + 0xf07b, 0xf05b, 0xf05d, 0xf07d, 0xf05c, 0xf200, 0xf200, 0xf200, + 0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69, + 0xfb6f, 0xfb70, 0xf200, 0xf07e, 0xf201, 0xf702, 0xfb61, 0xfb73, + 0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf200, + 0xf200, 0xf200, 0xf700, 0xf200, 0xfb7a, 0xfb78, 0xfb63, 0xfb76, + 0xfb62, 0xfb6e, 0xfb6d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf406, + 0xf703, 0xf200, 0xf207, 0xf50c, 0xf50d, 0xf50e, 0xf50f, 0xf510, + 0xf511, 0xf512, 0xf513, 0xf514, 0xf515, 0xf208, 0xf202, 0xfd0f, + 0xfd20, 0xfd0d, 0xfd24, 0xfd22, 0xfd12, 0xfd23, 0xfd21, 0xfd10, + 0xfd11, 0xfd0e, 0xf701, 0xfd1d, 0xf206, 0xf200, 0xf07c, 0xf516, + 0xf517, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xfd1c, 0xf702, 0xfd28, 0xfd25, 0xf703, 0xf205, 0xf114, 0xf603, + 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short ctrl_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01d, 0xf01e, + 0xf01f, 0xf07f, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf200, 0xf200, + 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009, + 0xf00f, 0xf010, 0xf01b, 0xf01d, 0xf201, 0xf702, 0xf001, 0xf013, + 0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200, + 0xf007, 0xf000, 0xf700, 0xf01c, 0xf01a, 0xf018, 0xf003, 0xf016, + 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf200, 0xf07f, 0xf700, 0xfd26, + 0xf703, 0xf000, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104, + 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf208, 0xf204, 0xfd0b, + 0xfd0a, 0xfd0c, 0xfd1e, 0xfd08, 0xfd07, 0xfd09, 0xfd14, 0xfd05, + 0xfd04, 0xfd06, 0xf701, 0xfd1b, 0xf206, 0xf200, 0xf200, 0xf10a, + 0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xfd03, 0xf702, 0xfd27, 0xf01c, 0xf703, 0xf205, 0xf114, 0xf603, + 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short shift_ctrl_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf000, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf200, 0xf200, + 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009, + 0xf00f, 0xf010, 0xf200, 0xf200, 0xf201, 0xf702, 0xf001, 0xf013, + 0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200, + 0xf200, 0xf200, 0xf700, 0xf200, 0xf01a, 0xf018, 0xf003, 0xf016, + 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf200, 0xf200, 0xf700, 0xfd26, + 0xf703, 0xf200, 0xf207, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf208, 0xf200, 0xfd0b, + 0xfd0a, 0xfd0c, 0xfd1e, 0xfd08, 0xfd07, 0xfd09, 0xfd14, 0xfd05, + 0xfd04, 0xfd06, 0xf701, 0xfd1b, 0xf206, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xfd03, 0xf702, 0xfd27, 0xfd25, 0xf703, 0xf205, 0xf114, 0xf603, + 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short altgr_ctrl_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009, + 0xf00f, 0xf010, 0xf200, 0xf200, 0xf201, 0xf702, 0xf001, 0xf013, + 0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200, + 0xf200, 0xf200, 0xf700, 0xf200, 0xf01a, 0xf018, 0xf003, 0xf016, + 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf200, 0xf200, 0xf700, 0xfd26, + 0xf703, 0xf200, 0xf207, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf208, 0xf200, 0xfd0b, + 0xfd0a, 0xfd0c, 0xfd1e, 0xfd08, 0xfd07, 0xfd09, 0xfd14, 0xfd05, + 0xfd04, 0xfd06, 0xf701, 0xf20c, 0xf206, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xfd03, 0xf702, 0xfd27, 0xfd25, 0xf703, 0xf205, 0xf114, 0xf603, + 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf20c, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short alt_map[NR_KEYS] = { + 0xf200, 0xf81b, 0xf831, 0xf832, 0xf833, 0xf834, 0xf835, 0xf836, + 0xf837, 0xf838, 0xf839, 0xf830, 0xf82d, 0xf83d, 0xf87f, 0xf809, + 0xf871, 0xf877, 0xf865, 0xf872, 0xf874, 0xf879, 0xf875, 0xf869, + 0xf86f, 0xf870, 0xf85b, 0xf85d, 0xf80d, 0xf702, 0xf861, 0xf873, + 0xf864, 0xf866, 0xf867, 0xf868, 0xf86a, 0xf86b, 0xf86c, 0xf83b, + 0xf827, 0xf860, 0xf700, 0xf85c, 0xf87a, 0xf878, 0xf863, 0xf876, + 0xf862, 0xf86e, 0xf86d, 0xf82c, 0xf82e, 0xf82f, 0xf700, 0xfd26, + 0xf703, 0xf820, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504, + 0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf208, 0xf209, 0xf907, + 0xf908, 0xf909, 0xfd1e, 0xf904, 0xf905, 0xf906, 0xfd14, 0xf901, + 0xf902, 0xf903, 0xf900, 0xfd1b, 0xf206, 0xf200, 0xf83c, 0xf50a, + 0xf50b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xfd03, 0xf702, 0xfd27, 0xf01c, 0xf703, 0xf205, 0xf114, 0xf603, + 0xf118, 0xf210, 0xf211, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short shift_alt_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf821, 0xf840, 0xf823, 0xf824, 0xf825, 0xf85e, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf851, 0xf857, 0xf845, 0xf852, 0xf854, 0xf859, 0xf855, 0xf849, + 0xf84f, 0xf850, 0xf87b, 0xf87d, 0xf201, 0xf702, 0xf841, 0xf853, + 0xf844, 0xf846, 0xf847, 0xf848, 0xf84a, 0xf84b, 0xf84c, 0xf200, + 0xf200, 0xf200, 0xf700, 0xf87c, 0xf85a, 0xf858, 0xf843, 0xf856, + 0xf842, 0xf84e, 0xf84d, 0xf83c, 0xf83e, 0xf200, 0xf700, 0xfd26, + 0xf703, 0xf200, 0xf207, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf208, 0xf200, 0xfd0b, + 0xfd0a, 0xfd0c, 0xfd1e, 0xfd08, 0xfd07, 0xfd09, 0xfd14, 0xfd05, + 0xfd04, 0xfd06, 0xf701, 0xfd1b, 0xf206, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xfd03, 0xf702, 0xfd27, 0xfd25, 0xf703, 0xf205, 0xf114, 0xf603, + 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short ctrl_alt_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf811, 0xf817, 0xf805, 0xf812, 0xf814, 0xf819, 0xf815, 0xf809, + 0xf80f, 0xf810, 0xf200, 0xf200, 0xf201, 0xf702, 0xf801, 0xf813, + 0xf804, 0xf806, 0xf807, 0xf808, 0xf80a, 0xf80b, 0xf80c, 0xf200, + 0xf200, 0xf200, 0xf700, 0xf200, 0xf81a, 0xf818, 0xf803, 0xf816, + 0xf802, 0xf80e, 0xf80d, 0xf200, 0xf200, 0xf200, 0xf700, 0xfd26, + 0xf703, 0xf200, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504, + 0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf208, 0xf200, 0xfd0b, + 0xfd0a, 0xfd0c, 0xfd1e, 0xfd08, 0xfd07, 0xfd09, 0xfd14, 0xfd05, + 0xfd04, 0xfd06, 0xf701, 0xf20c, 0xf206, 0xf200, 0xf200, 0xf50a, + 0xf50b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xfd03, 0xf702, 0xfd27, 0xfd25, 0xf703, 0xf205, 0xf114, 0xf603, + 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf20c, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short shift_ctrl_alt_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf811, 0xf817, 0xf805, 0xf812, 0xf814, 0xf819, 0xf815, 0xf809, + 0xf80f, 0xf810, 0xf200, 0xf200, 0xf201, 0xf702, 0xf801, 0xf813, + 0xf804, 0xf806, 0xf807, 0xf808, 0xf80a, 0xf80b, 0xf80c, 0xf200, + 0xf200, 0xf200, 0xf700, 0xf200, 0xf81a, 0xf818, 0xf803, 0xf816, + 0xf802, 0xf80e, 0xf80d, 0xf200, 0xf200, 0xf200, 0xf700, 0xfd26, + 0xf703, 0xf200, 0xf207, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf208, 0xf200, 0xfd0b, + 0xfd0a, 0xfd0c, 0xfd1e, 0xfd08, 0xfd07, 0xfd09, 0xfd14, 0xfd05, + 0xfd04, 0xfd06, 0xf701, 0xfd1b, 0xf206, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xfd03, 0xf702, 0xfd27, 0xfd25, 0xf703, 0xf205, 0xf114, 0xf603, + 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +ushort *key_maps[MAX_NR_KEYMAPS] = { + plain_map, shift_map, altgr_map, 0, + ctrl_map, shift_ctrl_map, altgr_ctrl_map, 0, + alt_map, shift_alt_map, 0, 0, + ctrl_alt_map, shift_ctrl_alt_map, 0 +}; + +unsigned int keymap_count = 10; + + +/* + * Philosophy: most people do not define more strings, but they who do + * often want quite a lot of string space. So, we statically allocate + * the default and allocate dynamically in chunks of 512 bytes. + */ + +char func_buf[] = { + '\033', '[', '[', 'A', 0, + '\033', '[', '[', 'B', 0, + '\033', '[', '[', 'C', 0, + '\033', '[', '[', 'D', 0, + '\033', '[', '[', 'E', 0, + '\033', '[', '1', '7', '~', 0, + '\033', '[', '1', '8', '~', 0, + '\033', '[', '1', '9', '~', 0, + '\033', '[', '2', '0', '~', 0, + '\033', '[', '2', '1', '~', 0, + '\033', '[', '2', '3', '~', 0, + '\033', '[', '2', '4', '~', 0, + '\033', '[', '2', '5', '~', 0, + '\033', '[', '2', '6', '~', 0, + '\033', '[', '2', '8', '~', 0, + '\033', '[', '2', '9', '~', 0, + '\033', '[', '3', '1', '~', 0, + '\033', '[', '3', '2', '~', 0, + '\033', '[', '3', '3', '~', 0, + '\033', '[', '3', '4', '~', 0, + '\033', '[', '1', '~', 0, + '\033', '[', '2', '~', 0, + '\033', '[', '3', '~', 0, + '\033', '[', '4', '~', 0, + '\033', '[', '5', '~', 0, + '\033', '[', '6', '~', 0, + 0, + 0, + 0, + 0, + 0, + 0, +}; + + +char *funcbufptr = func_buf; +int funcbufsize = sizeof(func_buf); +int funcbufleft = 0; /* space left */ + +char *func_table[MAX_NR_FUNC] = { + func_buf + 0, + func_buf + 5, + func_buf + 10, + func_buf + 15, + func_buf + 20, + func_buf + 25, + func_buf + 31, + func_buf + 37, + func_buf + 43, + func_buf + 49, + func_buf + 55, + func_buf + 61, + func_buf + 67, + func_buf + 73, + func_buf + 79, + func_buf + 85, + func_buf + 91, + func_buf + 97, + func_buf + 103, + func_buf + 109, + func_buf + 115, + func_buf + 120, + func_buf + 125, + func_buf + 130, + func_buf + 135, + func_buf + 140, + 0, + 0, + 0, + 0, + func_buf + 145, + func_buf + 146, + func_buf + 147, + func_buf + 148, + func_buf + 149, + func_buf + 150, + 0, +}; + +struct kbdiacr accent_table[MAX_DIACR] = { +}; + +unsigned int accent_table_size = 0; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/speakup/speakupmap.map linux.19rc3-ac4/drivers/char/speakup/speakupmap.map --- linux.19rc3/drivers/char/speakup/speakupmap.map 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/speakup/speakupmap.map 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,308 @@ +# us.map +# with some additions from quinlan@spectrum.cs.bucknell.edu (Daniel Quinlan) +# 14 Mar 1994 +keymaps 0-2,4-6,8,9,12,13 +keycode 1 = Escape Escape + alt keycode 1 = Meta_Escape +keycode 2 = one exclam + alt keycode 2 = Meta_one + alt shift keycode 2 = Meta_exclam +keycode 3 = two at at + control keycode 3 = nul + control shift keycode 3 = nul + alt keycode 3 = Meta_two + alt shift keycode 3 = Meta_at +keycode 4 = three numbersign + control keycode 4 = Escape + alt keycode 4 = Meta_three + alt shift keycode 4 = Meta_numbersign +keycode 5 = four dollar dollar + control keycode 5 = Control_backslash + alt keycode 5 = Meta_four + alt shift keycode 5 = Meta_dollar +keycode 6 = five percent + control keycode 6 = Control_bracketright + alt keycode 6 = Meta_five + alt shift keycode 6 = Meta_percent +keycode 7 = six asciicircum + control keycode 7 = Control_asciicircum + alt keycode 7 = Meta_six + alt shift keycode 7 = Meta_asciicircum +keycode 8 = seven ampersand braceleft + control keycode 8 = Control_underscore + alt keycode 8 = Meta_seven +keycode 9 = eight asterisk bracketleft + control keycode 9 = Delete + alt keycode 9 = Meta_eight +keycode 10 = nine parenleft bracketright + alt keycode 10 = Meta_nine +keycode 11 = zero parenright braceright + alt keycode 11 = Meta_zero +keycode 12 = minus underscore backslash + control keycode 12 = Control_underscore + control shift keycode 12 = Control_underscore + alt keycode 12 = Meta_minus +keycode 13 = equal plus + alt keycode 13 = Meta_equal +keycode 14 = Delete Delete + alt keycode 14 = Meta_Delete +keycode 15 = Tab Tab + alt keycode 15 = Meta_Tab +keycode 16 = q +keycode 17 = w +keycode 18 = e +keycode 19 = r +keycode 20 = t +keycode 21 = y +keycode 22 = u +keycode 23 = i +keycode 24 = o +keycode 25 = p +keycode 26 = bracketleft braceleft + control keycode 26 = Escape + alt keycode 26 = Meta_bracketleft + alt shift keycode 26 = Meta_braceleft +keycode 27 = bracketright braceright asciitilde + control keycode 27 = Control_bracketright + alt keycode 27 = Meta_bracketright + alt shift keycode 27 = Meta_braceright +keycode 28 = Return + alt keycode 28 = 0x080d +keycode 29 = Control +keycode 30 = a +keycode 31 = s +keycode 32 = d +keycode 33 = f +keycode 34 = g +keycode 35 = h +keycode 36 = j +keycode 37 = k +keycode 38 = l +keycode 39 = semicolon colon + alt keycode 39 = Meta_semicolon +keycode 40 = apostrophe quotedbl + control keycode 40 = Control_g + alt keycode 40 = Meta_apostrophe +keycode 41 = grave asciitilde + control keycode 41 = nul + alt keycode 41 = Meta_grave +keycode 42 = Shift +keycode 43 = backslash bar + control keycode 43 = Control_backslash + alt keycode 43 = Meta_backslash + alt shift keycode 43 = Meta_bar +keycode 44 = z +keycode 45 = x +keycode 46 = c +keycode 47 = v +keycode 48 = b +keycode 49 = n +keycode 50 = m +keycode 51 = comma less + alt keycode 51 = Meta_comma + alt shift keycode 51 = Meta_less +keycode 52 = period greater + alt keycode 52 = Meta_period + alt shift keycode 52 = Meta_greater +keycode 53 = slash question + control keycode 53 = Delete + alt keycode 53 = Meta_slash +keycode 54 = Shift +keycode 55 = 0x0d26 +#keycode 55 = KP_Multiply + altgr keycode 55 = 0x0406 +keycode 56 = Alt +keycode 57 = space space + control keycode 57 = nul + alt keycode 57 = Meta_space +keycode 58 = Caps_Lock +keycode 59 = F1 F11 Console_13 + control keycode 59 = F1 + alt keycode 59 = Console_1 + control alt keycode 59 = Console_1 +keycode 60 = F2 F12 Console_14 + control keycode 60 = F2 + alt keycode 60 = Console_2 + control alt keycode 60 = Console_2 +keycode 61 = F3 F13 Console_15 + control keycode 61 = F3 + alt keycode 61 = Console_3 + control alt keycode 61 = Console_3 +keycode 62 = F4 F14 Console_16 + control keycode 62 = F4 + alt keycode 62 = Console_4 + control alt keycode 62 = Console_4 +keycode 63 = F5 F15 Console_17 + control keycode 63 = F5 + alt keycode 63 = Console_5 + control alt keycode 63 = Console_5 +keycode 64 = F6 F16 Console_18 + control keycode 64 = F6 + alt keycode 64 = Console_6 + control alt keycode 64 = Console_6 +keycode 65 = F7 F17 Console_19 + control keycode 65 = F7 + alt keycode 65 = Console_7 + control alt keycode 65 = Console_7 +keycode 66 = F8 F18 Console_20 + control keycode 66 = F8 + alt keycode 66 = Console_8 + control alt keycode 66 = Console_8 +keycode 67 = F9 F19 Console_21 + control keycode 67 = F9 + alt keycode 67 = Console_9 + control alt keycode 67 = Console_9 +keycode 68 = F10 F20 Console_22 + control keycode 68 = F10 + alt keycode 68 = Console_10 + control alt keycode 68 = Console_10 +keycode 69 = Num_Lock +keycode 70 = Scroll_Lock Show_Memory Show_Registers + control keycode 70 = Show_State + alt keycode 70 = Scroll_Lock +keycode 71 = 0x0d0b + altgr keycode 71 = 0x0d0f +#keycode 71 = KP_7 + alt keycode 71 = Ascii_7 +keycode 72 = 0x0d0a + altgr keycode 72 = 0x0d20 +#keycode 72 = KP_8 + alt keycode 72 = Ascii_8 +keycode 73 = 0x0d0c + altgr keycode 73 = 0x0d0d +#keycode 73 = KP_9 + alt keycode 73 = Ascii_9 +keycode 74 = 0x0d1e + altgr keycode 74 = 0x0d24 +keycode 75 = 0x0d08 + altgr keycode 75 = 0x0d22 +#keycode 75 = KP_4 + alt keycode 75 = Ascii_4 +keycode 76 = 0x0d07 +#keycode 76 = KP_5 + altgr keycode 76 = 0x0d12 + alt keycode 76 = Ascii_5 +keycode 77 = 0x0d09 + altgr keycode 77 = 0x0d23 +#keycode 77 = KP_6 + alt keycode 77 = Ascii_6 +#keycode 78 = KP_Add +keycode 78 = 0x0d14 + altgr keycode 78 = 0x0d21 +keycode 79 = 0x0d05 +#keycode 79 = KP_1 + altgr keycode 79 = 0x0d10 + alt keycode 79 = Ascii_1 +keycode 80 = 0x0d04 +#keycode 80 = KP_2 + altgr keycode 80 = 0x0d11 + alt keycode 80 = Ascii_2 +keycode 81 = 0x0d06 + altgr keycode 81 = 0x0d0e +#keycode 81 = KP_3 + alt keycode 81 = Ascii_3 +#keycode 82 = 0x0d14 +keycode 82 = AltGr +#keycode 82 = KP_0 + alt keycode 82 = Ascii_0 +#keycode 83 = KP_Period +keycode 83 = 0x0d1b + altgr keycode 83 = 0x0d1d + altgr control keycode 83 = Boot + control alt keycode 83 = Boot +keycode 84 = Last_Console +keycode 85 = +keycode 86 = less greater bar + alt keycode 86 = Meta_less +keycode 87 = F11 F11 Console_23 + control keycode 87 = F11 + alt keycode 87 = Console_11 + control alt keycode 87 = Console_11 +keycode 88 = F12 F12 Console_24 + control keycode 88 = F12 + alt keycode 88 = Console_12 + control alt keycode 88 = Console_12 +keycode 89 = +keycode 90 = +keycode 91 = +keycode 92 = +keycode 93 = +keycode 94 = +keycode 95 = +keycode 96 = 0x0d03 + altgr keycode 96 = 0x0d1c +#keycode 96 = KP_Enter +keycode 97 = Control +keycode 98 = 0x0d27 +#keycode 98 = KP_Divide + altgr keycode 98 = 0x0d28 +#keycode 99 = Control_backslash +keycode 99 = 0x0d25 + control keycode 99 = Control_backslash + alt keycode 99 = Control_backslash +keycode 100 = Alt +keycode 101 = Break +keycode 102 = Find +keycode 103 = Up +keycode 104 = Prior + shift keycode 104 = Scroll_Backward +keycode 105 = Left + alt keycode 105 = Decr_Console +keycode 106 = Right + alt keycode 106 = Incr_Console +keycode 107 = Select +keycode 108 = Down +keycode 109 = Next + shift keycode 109 = Scroll_Forward +keycode 110 = Insert +keycode 111 = Remove + altgr control keycode 111 = Boot + control alt keycode 111 = Boot +keycode 112 = +keycode 113 = +keycode 114 = +keycode 115 = +keycode 116 = +keycode 117 = +keycode 118 = +keycode 119 = +keycode 120 = +keycode 121 = +keycode 122 = +keycode 123 = +keycode 124 = +keycode 125 = +keycode 126 = +keycode 127 = +string F1 = "\033[[A" +string F2 = "\033[[B" +string F3 = "\033[[C" +string F4 = "\033[[D" +string F5 = "\033[[E" +string F6 = "\033[17~" +string F7 = "\033[18~" +string F8 = "\033[19~" +string F9 = "\033[20~" +string F10 = "\033[21~" +string F11 = "\033[23~" +string F12 = "\033[24~" +string F13 = "\033[25~" +string F14 = "\033[26~" +string F15 = "\033[28~" +string F16 = "\033[29~" +string F17 = "\033[31~" +string F18 = "\033[32~" +string F19 = "\033[33~" +string F20 = "\033[34~" +string Find = "\033[1~" +string Insert = "\033[2~" +string Remove = "\033[3~" +string Select = "\033[4~" +string Prior = "\033[5~" +string Next = "\033[6~" +string F21 = "" +string F22 = "" +string F23 = "" +string F24 = "" +string F25 = "" +string F26 = "" diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/speakup/speakup_spkout.c linux.19rc3-ac4/drivers/char/speakup/speakup_spkout.c --- linux.19rc3/drivers/char/speakup/speakup_spkout.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/speakup/speakup_spkout.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,301 @@ +/* + * speakup_speakout.c for linux kernels 2.2.x and speakup + * + * author: Kirk Reiser and John Covici + 261 Trott dr. London, Ontario, Canada. N6G 1B6 + */ + + +/* These routines are written to control the speakout serial speech + synthesizer. They are not ment to be thought of as a device driver + in that they do not register themselves as a chr device and there + is no file_operations structure. They are strictly to provide an + interface to the speakout from the speakup screen review package. +*/ + +#define KERNEL +#include +#include +#include +#include /* for verify_area */ +#include /* for -EBUSY */ +#include /* for check_region, request_region */ +#include /* for loops_per_sec */ +#include /* for put_user_byte */ +#include /* for inb_p, outb_p, inb, outb, etc... */ +#include /* for wait_queue */ +#include /* kd_mksound */ +#include /* for __init */ +#include +#include /* for rs_table, serial constants and + serial_uart_config */ +#include /* for more serial constants */ +#if (LINUX_VERSION_CODE >= 0x20300) /* v 2.3.x */ +#include /* for struct serial_state */ +#endif +#include +#include + +#define SYNTH_CLEAR 0x18 +#define SPK_TIMEOUT 100 /* buffer timeout in ms */ +#define NUM_DISABLE_TIMEOUTS 3 /* disable synth if n timeouts */ +#define SPK_SERIAL_TIMEOUT 1000000 /* countdown values for serial timeouts */ +#define SPK_XMITR_TIMEOUT 1000000 /* countdown values transmitter/dsr timeouts */ +#define SPK_LO_TTY 0 /* check ttyS0 ... ttyS3 */ +#define SPK_HI_TTY 3 + +static int spkout_alive = 0; +#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) + +static struct serial_state rs_table[] = { + SERIAL_PORT_DFNS /* Defined in serial.h */ +}; + +static int wait_for_xmitr(void) +{ +static int timeouts = 0; /* sequential number of timeouts */ +int check, tmout = SPK_XMITR_TIMEOUT; + + if ((spkout_alive) && (timeouts >= NUM_DISABLE_TIMEOUTS)) { + spkout_alive = 0; + timeouts = 0; + return 0; + } + + /* holding register empty? */ + do { + check = inb(synth_port_tts + UART_LSR); + if (--tmout == 0) { + printk("SpeakOut: timed out\n"); + timeouts++; + return 0; + } + } while ((check & BOTH_EMPTY) != BOTH_EMPTY); + + tmout = SPK_XMITR_TIMEOUT; + /* CTS */ + do { + check = inb(synth_port_tts + UART_MSR); + if (--tmout == 0) { + timeouts++; + return 0; + } + } while ((check & UART_MSR_CTS) != UART_MSR_CTS); + + timeouts = 0; + return 1; +} + +static inline int spk_serial_out(const char ch) +{ + if (spkout_alive && synth_port_tts) { + if (wait_for_xmitr()) { + outb(ch, synth_port_tts); + return 1; + } + } + return 0; +} + +static unsigned char __init spk_serial_in(void) +{ +int c, lsr, tmout = SPK_SERIAL_TIMEOUT; + + do { + lsr = inb(synth_port_tts + UART_LSR); + if (--tmout == 0) return 0xff; + } while (!(lsr & UART_LSR_DR)); + c = inb(synth_port_tts + UART_RX); + return (unsigned char) c; +} + +static void do_catch_up(unsigned long data) +{ + unsigned long jiff_in = jiffies; + +synth_stop_timer(); + while (synth_sent_bytes < synth_queued_bytes) + { + if (!spk_serial_out(*(synth_buffer+synth_sent_bytes))) { + synth_delay(synth_full_time); + return; + } + synth_sent_bytes++; + if (jiffies >= jiff_in+synth_jiffy_delta && *(synth_buffer+synth_sent_bytes-1) == ' ') { + spk_serial_out('\r'); + synth_delay(synth_delay_time); + return; + } + } + +synth_sent_bytes = synth_queued_bytes = 0; +synth_timer_active = 0; +spk_serial_out('\r'); +if (waitqueue_active(&synth_sleeping_list)) + wake_up_interruptible(&synth_sleeping_list); +} + +static inline void clear_it(char ch) +{ + while ((inb(synth_port_tts + UART_LSR) & BOTH_EMPTY) != BOTH_EMPTY); + outb(ch, synth_port_tts); +} + +void synth_write_tts(char ch) +{ + if (!spkout_alive) return; + if (ch < 0x00) return; /* don't want unprintable chars */ + if (ch == 0x0a) /* turn lf into to force talking. */ + ch = '\r'; + if (ch == SYNTH_CLEAR) /* clear all and wake sleeping */ + { + clear_it(ch); + if (waitqueue_active(&synth_sleeping_list)) + wake_up_interruptible(&synth_sleeping_list); + synth_timer_active = synth_queued_bytes = synth_sent_bytes = 0; + return; + } + +synth_buffer_add(ch); +if (synth_buffering) return; +if (synth_timer_active == 0) synth_delay( synth_trigger_time ); +return; +} + +static inline void synth_immediate_tts(const char *buf, short count) +{ + while (count--) synth_write_tts(*buf++); +return; +} + +/* + * Setup initial baud/bits/parity. Swiped from serial.c (console section) + * Return non-zero if we didn't find a serial port. + */ +static int __init serprobe(int index) +{ + struct serial_state *ser = NULL; + unsigned char test=0; + + if (synth_port_tts) { + for (test=0; test <= SPK_HI_TTY; test++) + if ( (rs_table+test)->port == synth_port_tts) { + ser = rs_table+test; + break; + } + } else ser = rs_table + index; + + if (synth_request_region(ser->port,8)) + return -1; + + initialize_uart(ser); + /* If we read 0xff from the LSR, there is no UART here. */ + if (inb (ser->port + UART_LSR) == 0xff) { + synth_release_region(ser->port,8); + return -1; + } + mdelay(1); + + spkout_alive = 1; + /* ignore any error results, if port was forced */ + if (synth_port_tts) + return 0; + + synth_port_tts = ser->port; + + /* check for speak out now... */ + spk_serial_out(0x05); + spk_serial_out('['); /* set index cmd */ + spk_serial_out(0x0a); /* index mark */ + spk_serial_out('\r'); /* flush buffer for safety */ + mdelay(10); + if (spk_serial_in() == 0x0a) return 0; + + synth_release_region(ser->port,8); + spkout_alive = synth_port_tts = 0; /* not ignoring */ + return -1; +} + +static int __init synth_dev_probe(void) +{ +int i=0; + + printk("Probing for Speak Out.\n"); + if (synth_port_tts != 0) /* set from commandline */ + printk("Probe forced to 0x%x by kernel command line.\n",synth_port_tts); + + for (i=SPK_LO_TTY; i <= SPK_HI_TTY; i++) { + if (serprobe(i) == 0) break; /* found it */ + } + + if (spkout_alive) { + /* found 'em */ + printk("Speak Out: %03x-%03x, Driver version %s,\n", + synth_port_tts, synth_port_tts + 7, synth->version); + synth_immediate_tts(synth->init, strlen(synth->init)); + return 0; + } + + printk("Speak Out: not found\n"); + return -ENODEV; +} + + /* this is a new function required by speakup: + * if synth is not active, make it active and return 2 + * if synth is already active, return 1 + * otherwise (if it can't be made active), return 0 + */ +static int synth_alive(void) +{ + if (spkout_alive) + return 1; /* already on */ + else if ((!spkout_alive) && (synth_port_tts)) { + if (wait_for_xmitr() > 0) { /* restart */ + spkout_alive = 1; + synth_write(synth->reinit, strlen(synth->reinit)); + return 2; /* reenabled */ + } else printk("Speak Out: can't restart synth\n"); + } + return 0; +} + +static const char init_string[] = "\x05R7\x05P3\x05Ti\x05W1\x05I2\x05\x43\x33\x05MnSpeakout found\r"; +static const char reinit_string[] = "\x05R7\x05P3\x05Ti\x05W1\x05I2\x05\x43\x33\x05MnSpeakout found\r"; + +static struct spk_variable vars[] = +{{"flush", "\x18", "_", (BUILDER|HARD_DIRECT|NO_USER), "*"}, + {"pitch", "3", "\x05P_", (NUMERIC|HARD_DIRECT|USE_RANGE), "0,9"}, + {"caps_start", "\x05P+", "_", 0, "*"}, + {"caps_stop", "\x05P-", "_", 0, "*"}, + {"rate", "7", "\x05R_", (NUMERIC|HARD_DIRECT|USE_RANGE), "0,9"}, + {"tone", "i", "\x05T_", (HARD_DIRECT|USE_RANGE), "a,z"}, + {"volume", "9", "\x05V_", (NUMERIC|HARD_DIRECT|USE_RANGE), "0,9"}, + {"punct", "n", "\x05M_", HARD_DIRECT, "nmsa"}, + END_VARS}; + +static char *config[] = +{"\x18", "\x05P3", "\x05P+", "\x05P-", "\x05R7", "\x05Ti", "\x05V9", + "\x05Mn"}; + +struct spk_synth synth_spkout = {"spkout", "Version-0.12", "speakout", + init_string, reinit_string, 500, 50, 5, 5000, + vars, config, 0, synth_dev_probe, do_catch_up, + synth_write_tts, synth_alive}; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/speakup/speakup_txprt.c linux.19rc3-ac4/drivers/char/speakup/speakup_txprt.c --- linux.19rc3/drivers/char/speakup/speakup_txprt.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/speakup/speakup_txprt.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,287 @@ +/* + * speakup_txprt.c for linux kernels 2.2.x and speakup + * + * author: Kirk Reiser + + Copyright (C) 1998-99 Kirk Reiser. + + 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 + + Kirk Reiser + 261 Trott dr. London, Ontario, Canada. N6G 1B6 + */ + + +/* These routines are written to control the Transport serial speech + synthesizer. They are not ment to be thought of as a device driver + in that they do not register themselves as a chr device and there + is no file_operations structure. They are strictly to provide an + interface to the txprt from the speakup screen review package. */ + +#define KERNEL +#include +#include +#include +#include /* for verify_area */ +#include /* for -EBUSY */ +#include /* for check_region, request_region */ +#include /* for loops_per_sec */ +#include /* for put_user_byte */ +#include /* for inb_p, outb_p, inb, outb, etc... */ +#include /* for wait_queue */ +#include /* kd_mksound */ +#include /* for __init */ +#include +#include /* for rs_table, serial constants and + serial_uart_config */ +#include /* for more serial constants */ +#if (LINUX_VERSION_CODE >= 0x20300) /* v 2.3.x */ +#include /* for struct serial_state */ +#endif +#include +#include + +#define SYNTH_CLEAR 0x18 +#define SPK_TIMEOUT 100 /* buffer timeout in ms */ +#define NUM_DISABLE_TIMEOUTS 3 /* disable synth if n timeouts */ +#define SPK_SERIAL_TIMEOUT 1000000 /* countdown values for serial timeouts */ +#define SPK_XMITR_TIMEOUT 1000000 /* countdown values transmitter/dsr timeouts */ +#define SPK_LO_TTY 0 /* check ttyS0 ... ttyS3 */ +#define SPK_HI_TTY 3 +#define PROCSPEECH '\r' /* process speech char */ + +static int txprt_alive = 0; +#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) + +static struct serial_state rs_table[] = { + SERIAL_PORT_DFNS /* Defined in serial.h */ +}; + +static int timeouts = 0; /* sequential number of timeouts */ + +static int wait_for_xmitr(void) +{ +int check, tmout = SPK_XMITR_TIMEOUT; + + if ((txprt_alive) && (timeouts >= NUM_DISABLE_TIMEOUTS)) { + txprt_alive = 0; + timeouts = 0; + return 0; + } + + /* holding register empty? */ + do { + check = inb(synth_port_tts + UART_LSR); + if (--tmout == 0) { + printk("TXPRT: timed out\n"); + timeouts++; + return 0; + } + } while ((check & BOTH_EMPTY) != BOTH_EMPTY); + + tmout = SPK_XMITR_TIMEOUT; + /* CTS */ + do { + check = inb(synth_port_tts + UART_MSR); + if (--tmout == 0) { + timeouts++; + return 0; + } + } while ((check & UART_MSR_CTS) != UART_MSR_CTS); + + timeouts = 0; + return 1; +} + +static inline int spk_serial_out(const char ch) +{ + if (txprt_alive && synth_port_tts) { + if (wait_for_xmitr()) { + outb(ch, synth_port_tts); + return 1; + } + } + return 0; +} + +static unsigned char __init spk_serial_in(void) +{ +int c, lsr, tmout = SPK_SERIAL_TIMEOUT; + + do { + lsr = inb(synth_port_tts + UART_LSR); + if (--tmout == 0) return 0xff; + } while (!(lsr & UART_LSR_DR)); + c = inb(synth_port_tts + UART_RX); + return (unsigned char) c; +} + +static void do_catch_up(unsigned long data) +{ + unsigned long jiff_in = jiffies; + +synth_stop_timer(); + while (synth_sent_bytes < synth_queued_bytes) + { + if (!spk_serial_out(*(synth_buffer+synth_sent_bytes))) { + synth_delay(synth_full_time); + return; + } + synth_sent_bytes++; + if (jiffies >= jiff_in+synth_jiffy_delta && *(synth_buffer+synth_sent_bytes-1) == ' ') + { + spk_serial_out(PROCSPEECH); + synth_delay(synth_delay_time); + return; + } + } + +synth_sent_bytes = synth_queued_bytes = 0; +spk_serial_out(PROCSPEECH); +synth_timer_active = 0; +if (waitqueue_active(&synth_sleeping_list)) + wake_up_interruptible(&synth_sleeping_list); +} + + +static void synth_write_tts(char ch) +{ + if (!txprt_alive) return; + if (ch < 0x00) return; /* don't want unprintable chars */ + if (ch == 0x0a) /* turn lf into to force talking. */ + ch = PROCSPEECH; + if (ch == SYNTH_CLEAR) /* clear all and wake sleeping */ + { + spk_serial_out(ch); + if (waitqueue_active(&synth_sleeping_list)) + wake_up_interruptible(&synth_sleeping_list); + synth_timer_active = synth_queued_bytes = synth_sent_bytes = 0; + return; + } + +synth_buffer_add(ch); +if (synth_buffering) return; +if (synth_timer_active == 0) synth_delay( synth_trigger_time ); +return; +} + +static inline void synth_immediate_tts(const char *buf, short count) +{ + while (count--) spk_serial_out(*buf++); +return; +} + +static int __init serprobe(int index) +{ + struct serial_state *ser = NULL; + unsigned char test=0; + + if (synth_port_tts) { + for (test=0; test <= SPK_HI_TTY; test++) + if ( (rs_table+test)->port == synth_port_tts) { + ser = rs_table+test; + break; + } + } else ser = rs_table + index; + + if (synth_request_region(ser->port,8)) + return -1; + + initialize_uart(ser); + /* If we read 0xff from the LSR, there is no UART here. */ + if (inb (ser->port + UART_LSR) == 0xff) { + synth_release_region(ser->port,8); + return -1; + } + + txprt_alive = 1; + if (synth_port_tts) return 0; + synth_port_tts = ser->port; + + /* check for txprt now... */ + spk_serial_out(0x18); + spk_serial_out('\r'); + mdelay(1); + spk_serial_out(0x05); + spk_serial_out('I'); + spk_serial_out('k'); + mdelay(10); + spk_serial_out(0x05); + spk_serial_out('Q'); + if ((test = spk_serial_in()) == 'k') return 0; + else printk("synth returned %x\n", test); + + synth_release_region(ser->port,8); + timeouts = txprt_alive = synth_port_tts = 0; + return -1; +} + +static int __init synth_dev_probe(void) +{ +int i; + + printk("Probing for Transport.\n"); + if (synth_port_tts) + printk("Probe forced to 0x%x by kernel command line\n", synth_port_tts); + for (i=SPK_LO_TTY; i <= SPK_HI_TTY; i++) { + if (serprobe(i) == 0) break; /* found it */ + } + + if (txprt_alive) { + /* found 'em */ + printk("Transport: %03x-%03x, Driver version %s,\n", + synth_port_tts, synth_port_tts + 7, synth->version); + synth_immediate_tts(synth->init, strlen(synth->init)); + return 0; + } + + printk("Transport: not found\n"); + return -ENODEV; +} + +static int synth_alive(void) +{ + if (txprt_alive) + return 1; /* already on */ + else if ((!txprt_alive) && (synth_port_tts)) { + if (wait_for_xmitr() > 0) { /* restart */ + txprt_alive = 1; + synth_write(synth->reinit, strlen(synth->reinit)); + return 2; /* reenabled */ + } else printk("Transport: can't restart synth\n"); + } + return 0; +} + + +static const char init_string[] = "\x05$\x05P5\x05R5\x05N1Transport found\r"; +static const char reinit_string[] = "\x05$\x05P5\x05R5\x05N1Transport initialized\r"; +static struct spk_variable vars[] = +{{"flush", "\x18\r", "_", (BUILDER|HARD_DIRECT|NO_USER), "*"}, + {"pitch", "5", "\x05P_", (NUMERIC|HARD_DIRECT|USE_RANGE), "0,9"}, + {"caps_start", "\x05P8", "_", 0, "*"}, + {"caps_stop", "\x05P5", "_", 0, "*"}, + {"rate", "5", "\x05R_", (NUMERIC|HARD_DIRECT|USE_RANGE), "0,9"}, + {"tone", "I", "\x05T_", (HARD_DIRECT|USE_RANGE), "a,z"}, + {"volume", "5", "\x05V_", (NUMERIC|HARD_DIRECT|USE_RANGE), "0,9"}, + END_VARS}; + +static char *config[] = +{"\x18\r", "\x05P5", "\x05P8", "\x05P5", "\x05R5", "\x05TI", "\x05V5", NULL}; + +struct spk_synth synth_txprt = {"txprt", "Version-0.13", "transport", + init_string, reinit_string, 500, 50, 5, 5000, + vars, config, 0, synth_dev_probe, do_catch_up, + synth_write_tts, synth_alive}; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/speakup/symbols.h linux.19rc3-ac4/drivers/char/speakup/symbols.h --- linux.19rc3/drivers/char/speakup/symbols.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/speakup/symbols.h 2002-07-29 14:19:07.000000000 +0100 @@ -0,0 +1,62 @@ +#ifndef _SPEAKUP_SYMBOLS_H +#define _SPEAKUP_SYMBOLS_H + +#include + +#define PUNC_CHARS_SIZE 33 +#define PUNC_CHARS "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" + +#define DEFAULT_SPKUP_VARS \ +/* line_wrap_bleep */ "1", \ +/* attribute_bleep */ "1", \ +/* bleep_time (ms) */ "3", \ +/* spell_delay */ "1", \ +/* punc_level */ "1", \ +/* say_control */ "0", \ +/* no_interrupt */ "0", \ +/* punc_none */ "", \ +/* punc_some */ "/$%&@", \ +/* punc_most */ "($%&#@=+*^<>|\\)", \ +/* punc_all */ PUNC_CHARS, \ +/* key_echo */ "1", \ +/* bell_pos */ "0" + +// alias the necessary hardware constants off to generalized constants +#define FLUSH 0 +#define PITCH 1 +#define CAPS_START 2 +#define CAPS_STOP 3 + +#define LINE_WRAP_BLEEP 0 +#define ATTRIBUTE_BLEEP 1 +#define BLEEP_TIME 2 +#define SPELL_DELAY 3 +#define PUNCT_LEVEL 4 +#define SAY_CONTROL 5 +#define NO_INTERRUPT 6 +#define PUNC_NONE 7 +#define PUNC_SOME 8 +#define PUNC_MOST 9 +#define PUNC_ALL 10 +#define KEY_ECHO 11 +#define BELL_POS 12 + +// beginning of the 4 punc levels +#define PUNC_OFFSET PUNC_NONE + +#define SPKUP_VARS \ +{"line_wrap_bleep", "1", "_", (NUMERIC|SOFT_DIRECT|USE_RANGE), TOGGLE}, \ +{"attribute_bleep", "1", "_", (NUMERIC|SOFT_DIRECT|USE_RANGE), TOGGLE}, \ +{"bleep_time", "3", "_", (NUMERIC|SOFT_DIRECT|USE_RANGE), "1,9"}, \ +{"spell_delay", "1", "_", (NUMERIC|SOFT_DIRECT|USE_RANGE), "1,5"}, \ +{"punc_level", "1", "_", (NUMERIC|SOFT_DIRECT|USE_RANGE), "0,3"}, \ +{"say_control", "0", "_", (NUMERIC|SOFT_DIRECT|USE_RANGE), TOGGLE}, \ +{"no_interrupt", "0", "_", (NUMERIC|SOFT_DIRECT|USE_RANGE), TOGGLE}, \ +{"punc_none", "", "_", (SOFT_DIRECT|NO_USER), ""}, \ +{"punc_some", "/$%&", "_", (MULTI_SET|SOFT_DIRECT), PUNC_CHARS}, \ +{"punc_most", "($%&#@=+*^<>|\\)", "_", (MULTI_SET|SOFT_DIRECT), PUNC_CHARS}, \ +{"punc_all", PUNC_CHARS, "_", (SOFT_DIRECT|NO_USER), ""}, \ +{"key_echo", "1", "_", (NUMERIC|SOFT_DIRECT|USE_RANGE), TOGGLE}, \ +{"bell_pos", "0", "_", (NUMERIC|SOFT_DIRECT|USE_RANGE), "0,200"}, \ +END_VARS +#endif diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/speakup/TODO linux.19rc3-ac4/drivers/char/speakup/TODO --- linux.19rc3/drivers/char/speakup/TODO 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/speakup/TODO 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,66 @@ +The format of this file is getting organized to help me keep track of +where we are going. I am organizing it into three sections. +Immediate things which need to be done I.E. code re-organization. New +features we are currently working on or at least in the near future. +Long term features which will move to the new features list as the new +features list empties. + +Immediate: + +Screen cursoring needs to become more reliable and consistant. + +New-Features: + +convert the individual synth drivers into modules (involves moving buffering + into speakup proper). + +synth_file fops need to be filled in and expanded such as some type of +ioctl function and a real synth_file_read() function. + + +Long-Term-Features: + +keyboard macros (ala ASAP/qedit) + +finding calling process, so per-program configurations can be loaded + +Check park status and store it before doing a console switch. (non-trivial) + +make numlock turn review pad to number pad. + +user defined scroll-back ala shift-pgup. + +insert as 'capslock-style'/'next-style' key -- have internalized speakup + variable, which tracks state of the insert key; each speakup bare-key + function checks the variable, and possibly calls the alternate + function and returns + +Expand phonetic spelling to toggle on and off and work with previous + and next and spell_word functions. Also shift pitch on phonetic words + for capitalized letters. [partially complete] + +Chuck wants a bleep if the shift key is hit and the capslock is on. +Here is his suggested test sequence: +1. check if the caps lock is set; if it is, +2. check if the char is alphabetic; if it is, +3. check if the shift key is pressed; if it is, +4. send a bell char to the console. + +Frank would like a fast way to go to the end of the word in addition +to moving to the beginning. + +I'd like a function to move the reading cursor to the last char on a +line in addition to the right edge of the screen. + +Gene thinks we should have a /proc function to store and show the rom +version of any synth currently operating. + +The items in each list have no connection with the order of +implementation. I just jotted them down as I thought of them. + +Bill Acker WB2FLW: When the final result is "none", then, no trace of +Speakup. and use default keymap otherwise business as usual plus use +"built-in" speakupmap.map + +Look at lilo routines which init the serial device and compare to speakup drivers. + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/sx.c linux.19rc3-ac4/drivers/char/sx.c --- linux.19rc3/drivers/char/sx.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/sx.c 2002-07-29 18:08:33.000000000 +0100 @@ -407,11 +407,11 @@ -#define func_enter() sx_dprintk (SX_DEBUG_FLOW, "sx: enter " __FUNCTION__ "\n") -#define func_exit() sx_dprintk (SX_DEBUG_FLOW, "sx: exit " __FUNCTION__ "\n") +#define func_enter() sx_dprintk (SX_DEBUG_FLOW, "sx: enter %s\b",__FUNCTION__) +#define func_exit() sx_dprintk (SX_DEBUG_FLOW, "sx: exit %s\n", __FUNCTION__) -#define func_enter2() sx_dprintk (SX_DEBUG_FLOW, "sx: enter " __FUNCTION__ \ - "(port %d)\n", port->line) +#define func_enter2() sx_dprintk (SX_DEBUG_FLOW, "sx: enter %s (port %d)\n", \ + __FUNCTION__, port->line) diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/char/vt.c linux.19rc3-ac4/drivers/char/vt.c --- linux.19rc3/drivers/char/vt.c 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/char/vt.c 2002-07-29 13:58:39.000000000 +0100 @@ -481,7 +481,7 @@ ucval = keyboard_type; goto setchar; -#if !defined(__alpha__) && !defined(__ia64__) && !defined(__mips__) && !defined(__arm__) && !defined(__sh__) +#if defined(__i386__) || defined(__mc68000__) || defined(__ppc__) || defined(__sparc__) /* * These cannot be implemented on any machine that implements * ioperm() in user level (such as Alpha PCs). diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/gsc/asp.c linux.19rc3-ac4/drivers/gsc/asp.c --- linux.19rc3/drivers/gsc/asp.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/gsc/asp.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,131 @@ +/* + * ASP Device Driver + * + * (c) Copyright 2000 The Puffin Group Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * by Helge Deller + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "busdevice.h" + +#define ASP_GSC_IRQ 3 /* hardcoded interrupt for GSC */ + +#define ASP_VER_OFFSET 0x20 /* offset of ASP version */ + +#define ASP_LED_ADDR 0xf0800020 + +#define VIPER_INT_WORD 0xFFFBF088 /* addr of viper interrupt word */ + +static int asp_choose_irq(struct parisc_device *dev) +{ + int irq = -1; + + switch (dev->id.sversion) { + case 0x71: irq = 22; break; /* SCSI */ + case 0x72: irq = 23; break; /* LAN */ + case 0x73: irq = 30; break; /* HIL */ + case 0x74: irq = 24; break; /* Centronics */ + case 0x75: irq = (dev->hw_path == 4) ? 26 : 25; break; /* RS232 */ + case 0x76: irq = 21; break; /* EISA BA */ + case 0x77: irq = 20; break; /* Graphics1 */ + case 0x7a: irq = 18; break; /* Audio (Bushmaster) */ + case 0x7b: irq = 18; break; /* Audio (Scorpio) */ + case 0x7c: irq = 28; break; /* FW SCSI */ + case 0x7d: irq = 27; break; /* FDDI */ + case 0x7f: irq = 18; break; /* Audio (Outfield) */ + } + return irq; +} + +/* There are two register ranges we're interested in. Interrupt / + * Status / LED are at 0xf080xxxx and Asp special registers are at + * 0xf082fxxx. PDC only tells us that Asp is at 0xf082f000, so for + * the purposes of interrupt handling, we have to tell other bits of + * the kernel to look at the other registers. + */ +#define ASP_INTERRUPT_ADDR 0xf0800000 + +int __init +asp_init_chip(struct parisc_device *dev) +{ + struct busdevice *asp; + struct gsc_irq gsc_irq; + int irq, ret; + + asp = kmalloc(sizeof(struct busdevice), GFP_KERNEL); + if(!asp) + return -ENOMEM; + + asp->version = gsc_readb(dev->hpa + ASP_VER_OFFSET) & 0xf; + asp->name = (asp->version == 1) ? "Asp" : "Cutoff"; + asp->hpa = ASP_INTERRUPT_ADDR; + + printk(KERN_INFO "%s version %d at 0x%lx found.\n", + asp->name, asp->version, dev->hpa); + + /* the IRQ ASP should use */ + ret = -EBUSY; + irq = gsc_claim_irq(&gsc_irq, ASP_GSC_IRQ); + if (irq < 0) { + printk(KERN_ERR "%s(): cannot get GSC irq\n", __FUNCTION__); + goto out; + } + + ret = request_irq(gsc_irq.irq, busdev_barked, 0, "asp", asp); + if (ret < 0) + goto out; + + /* Save this for debugging later */ + asp->parent_irq = gsc_irq.irq; + asp->eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data; + + /* Program VIPER to interrupt on the ASP irq */ + gsc_writel((1 << (31 - ASP_GSC_IRQ)),VIPER_INT_WORD); + + /* Done init'ing, register this driver */ + ret = gsc_common_irqsetup(dev, asp); + if (ret) + goto out; + + fixup_child_irqs(dev, asp->busdev_region->data.irqbase, asp_choose_irq); + /* Mongoose is a sibling of Asp, not a child... */ + fixup_child_irqs(dev->parent, asp->busdev_region->data.irqbase, + asp_choose_irq); + + /* initialize the chassis LEDs */ +#ifdef CONFIG_CHASSIS_LCD_LED + register_led_driver(DISPLAY_MODEL_OLD_ASP, LED_CMD_REG_NONE, + (char *)ASP_LED_ADDR); +#endif + + return 0; + +out: + kfree(asp); + return ret; +} + +static struct parisc_device_id asp_tbl[] = { + { HPHW_BA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00070 }, + { 0, } +}; + +struct parisc_driver asp_driver = { + name: "Asp", + id_table: asp_tbl, + probe: asp_init_chip, +}; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/gsc/busdevice.h linux.19rc3-ac4/drivers/gsc/busdevice.h --- linux.19rc3/drivers/gsc/busdevice.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/gsc/busdevice.h 2002-07-29 15:50:46.000000000 +0100 @@ -0,0 +1,34 @@ +#ifndef BUSDEVICE_H +#define BUSDEVICE_H + +#include +#include +#include +#include + +#define OFFSET_IRR 0x0000 /* Interrupt request register */ +#define OFFSET_IMR 0x0004 /* Interrupt mask register */ +#define OFFSET_IPR 0x0008 /* Interrupt pending register */ +#define OFFSET_ICR 0x000C /* Interrupt control register */ +#define OFFSET_IAR 0x0010 /* Interrupt address register */ + + +struct busdevice { + struct parisc_device *gsc; + unsigned long hpa; + char *name; + int version; + int type; + int parent_irq; + int eim; + struct irq_region *busdev_region; +}; + +/* short cut to keep the compiler happy */ +#define BUSDEV_DEV(x) ((struct busdevice *) (x)) + +int gsc_common_irqsetup(struct parisc_device *parent, struct busdevice *busdev); + +void busdev_barked(int busdev_irq, void *dev, struct pt_regs *regs); + +#endif /* BUSDEVICE_H */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/gsc/dino.c linux.19rc3-ac4/drivers/gsc/dino.c --- linux.19rc3/drivers/gsc/dino.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/gsc/dino.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,931 @@ +/* +** DINO manager +** +** (c) Copyright 1999 Red Hat Software +** (c) Copyright 1999 SuSE GmbH +** (c) Copyright 1999,2000 Hewlett-Packard Company +** (c) Copyright 2000 Grant Grundler +** +** 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 module provides access to Dino PCI bus (config/IOport spaces) +** and helps manage Dino IRQ lines. +** +** Dino interrupt handling is a bit complicated. +** Dino always writes to the broadcast EIR via irr0 for now. +** (BIG WARNING: using broadcast EIR is a really bad thing for SMP!) +** Only one processor interrupt is used for the 11 IRQ line +** inputs to dino. +** +** The different between Built-in Dino and Card-Mode +** dino is in chip initialization and pci device initialization. +** +** Linux drivers can only use Card-Mode Dino if pci devices I/O port +** BARs are configured and used by the driver. Programming MMIO address +** requires substantial knowledge of available Host I/O address ranges +** is currently not supported. Port/Config accessor functions are the +** same. "BIOS" differences are handled within the existing routines. +*/ + +/* Changes : +** 2001-06-14 : Clement Moyroud (moyroudc@esiee.fr) +** - added support for the integrated RS232. +*/ + +/* +** TODO: create a virtual address for each Dino HPA. +** GSC code might be able to do this since IODC data tells us +** how many pages are used. PCI subsystem could (must?) do this +** for PCI drivers devices which implement/use MMIO registers. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for struct irqaction */ +#include /* for spinlock_t and prototypes */ + +#include +#include +#include +#include +#include + +#include /* for "gsc" irq functions */ +#include + +#undef DINO_DEBUG + +#ifdef DINO_DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +/* +** Config accessor functions only pass in the 8-bit bus number +** and not the 8-bit "PCI Segment" number. Each Dino will be +** assigned a PCI bus number based on "when" it's discovered. +** +** The "secondary" bus number is set to this before calling +** pci_scan_bus(). If any PPB's are present, the scan will +** discover them and update the "secondary" and "subordinate" +** fields in Dino's pci_bus structure. +** +** Changes in the configuration *will* result in a different +** bus number for each dino. +*/ + +#define is_card_dino(id) ((id)->hw_type == HPHW_A_DMA) + +#define DINO_IAR0 0x004 +#define DINO_IODC_ADDR 0x008 +#define DINO_IODC_DATA_0 0x008 +#define DINO_IODC_DATA_1 0x008 +#define DINO_IRR0 0x00C +#define DINO_IAR1 0x010 +#define DINO_IRR1 0x014 +#define DINO_IMR 0x018 +#define DINO_IPR 0x01C +#define DINO_TOC_ADDR 0x020 +#define DINO_ICR 0x024 +#define DINO_ILR 0x028 +#define DINO_IO_COMMAND 0x030 +#define DINO_IO_STATUS 0x034 +#define DINO_IO_CONTROL 0x038 +#define DINO_IO_GSC_ERR_RESP 0x040 +#define DINO_IO_ERR_INFO 0x044 +#define DINO_IO_PCI_ERR_RESP 0x048 +#define DINO_IO_FBB_EN 0x05c +#define DINO_IO_ADDR_EN 0x060 +#define DINO_PCI_ADDR 0x064 +#define DINO_CONFIG_DATA 0x068 +#define DINO_IO_DATA 0x06c +#define DINO_MEM_DATA 0x070 /* Dino 3.x only */ +#define DINO_GSC2X_CONFIG 0x7b4 +#define DINO_GMASK 0x800 +#define DINO_PAMR 0x804 +#define DINO_PAPR 0x808 +#define DINO_DAMODE 0x80c +#define DINO_PCICMD 0x810 +#define DINO_PCISTS 0x814 +#define DINO_MLTIM 0x81c +#define DINO_BRDG_FEAT 0x820 +#define DINO_PCIROR 0x824 +#define DINO_PCIWOR 0x828 +#define DINO_TLTIM 0x830 + +#define DINO_IRQS 11 /* bits 0-10 are architected */ +#define DINO_IRR_MASK 0x5ff /* only 10 bits are implemented */ + +#define DINO_MASK_IRQ(x) (1<<(x)) + +#define PCIINTA 0x001 +#define PCIINTB 0x002 +#define PCIINTC 0x004 +#define PCIINTD 0x008 +#define PCIINTE 0x010 +#define PCIINTF 0x020 +#define GSCEXTINT 0x040 +/* #define xxx 0x080 - bit 7 is "default" */ +/* #define xxx 0x100 - bit 8 not used */ +/* #define xxx 0x200 - bit 9 not used */ +#define RS232INT 0x400 + +struct dino_device +{ + struct pci_hba_data hba; /* 'C' inheritance - must be first */ + spinlock_t dinosaur_pen; + unsigned long txn_addr; /* EIR addr to generate interrupt */ + u32 txn_data; /* EIR data assign to each dino */ + int irq; /* Virtual IRQ dino uses */ + struct irq_region *dino_region; /* region for this Dino */ + + u32 imr; /* IRQ's which are enabled */ +#ifdef DINO_DEBUG + unsigned int dino_irr0; /* save most recent IRQ line stat */ +#endif +}; + +/* Looks nice and keeps the compiler happy */ +#define DINO_DEV(d) ((struct dino_device *) d) + + + +/*********************************************** +** +** Dino Configuration Space Accessor Functions +** +************************************************/ + +#define le8_to_cpu(x) (x) +#define cpu_to_le8(x) (x) + +#define DINO_CFG_TOK(bus,dfn,pos) ((u32) ((bus)<<16 | (dfn)<<8 | (pos))) + +#define DINO_CFG_RD(type, size, mask) \ +static int dino_cfg_read##size (struct pci_dev *dev, int pos, u##size *data) \ +{ \ + struct dino_device *d = DINO_DEV(dev->sysdata); \ + u32 local_bus = (dev->bus->parent == NULL) ? 0 : dev->bus->secondary; \ + u32 v = DINO_CFG_TOK(local_bus, dev->devfn, (pos&~3)); \ + unsigned long flags; \ + spin_lock_irqsave(&d->dinosaur_pen, flags); \ + /* tell HW which CFG address */ \ + gsc_writel(v, d->hba.base_addr + DINO_PCI_ADDR); \ + /* generate cfg read cycle */ \ + *data = le##size##_to_cpu(gsc_read##type(d->hba.base_addr+DINO_CONFIG_DATA+(pos&mask))); \ + spin_unlock_irqrestore(&d->dinosaur_pen, flags); \ + return 0; \ +} + +DINO_CFG_RD(b, 8, 3) +DINO_CFG_RD(w, 16, 2) +DINO_CFG_RD(l, 32, 0) + + +/* +** Dino address stepping "feature": +** When address stepping, Dino attempts to drive the bus one cycle too soon +** even though the type of cycle (config vs. MMIO) might be different. +** The read of Ven/Prod ID is harmless and avoids Dino's address stepping. +*/ +#define DINO_CFG_WR(type, size, mask) \ +static int dino_cfg_write##size (struct pci_dev *dev, int pos, u##size data) \ +{ \ + struct dino_device *d = DINO_DEV(dev->sysdata); \ + u32 local_bus = (dev->bus->parent == NULL) ? 0 : dev->bus->secondary; \ + u32 v = DINO_CFG_TOK(local_bus, dev->devfn, (pos&~3)); \ + unsigned long flags; \ + spin_lock_irqsave(&d->dinosaur_pen, flags); \ + /* avoid address stepping feature */ \ + gsc_writel(v & 0xffffff00, d->hba.base_addr + DINO_PCI_ADDR); \ + (volatile int) gsc_readl(d->hba.base_addr + DINO_CONFIG_DATA); \ + /* tell HW which CFG address */ \ + gsc_writel(v, d->hba.base_addr + DINO_PCI_ADDR); \ + /* generate cfg read cycle */ \ + gsc_write##type(cpu_to_le##size(data), d->hba.base_addr+DINO_CONFIG_DATA+(pos&mask)); \ + spin_unlock_irqrestore(&d->dinosaur_pen, flags); \ + return 0; \ +} + +DINO_CFG_WR(b, 8, 3) +DINO_CFG_WR(w, 16, 2) +DINO_CFG_WR(l, 32, 0) + +static struct pci_ops dino_cfg_ops = { + read_byte: dino_cfg_read8, + read_word: dino_cfg_read16, + read_dword: dino_cfg_read32, + write_byte: dino_cfg_write8, + write_word: dino_cfg_write16, + write_dword: dino_cfg_write32 +}; + + + +/******************************************************* +** +** Dino "I/O Port" Space Accessor Functions +** +** Many PCI devices don't require use of I/O port space (eg Tulip, +** NCR720) since they export the same registers to both MMIO and +** I/O port space. Performance is going to stink if drivers use +** I/O port instead of MMIO. +** +********************************************************/ + + +#define DINO_PORT_IN(type, size, mask) \ +static u##size dino_in##size (struct pci_hba_data *d, u16 addr) \ +{ \ + u##size v; \ + unsigned long flags; \ + spin_lock_irqsave(&(DINO_DEV(d)->dinosaur_pen), flags); \ + /* tell HW which IO Port address */ \ + gsc_writel((u32) addr & ~3, d->base_addr + DINO_PCI_ADDR); \ + /* generate I/O PORT read cycle */ \ + v = gsc_read##type(d->base_addr+DINO_IO_DATA+(addr&mask)); \ + spin_unlock_irqrestore(&(DINO_DEV(d)->dinosaur_pen), flags); \ + return le##size##_to_cpu(v); \ +} + +DINO_PORT_IN(b, 8, 3) +DINO_PORT_IN(w, 16, 2) +DINO_PORT_IN(l, 32, 0) + +#define DINO_PORT_OUT(type, size, mask) \ +static void dino_out##size (struct pci_hba_data *d, u16 addr, u##size val) \ +{ \ + unsigned long flags; \ + spin_lock_irqsave(&(DINO_DEV(d)->dinosaur_pen), flags); \ + /* tell HW which CFG address */ \ + gsc_writel((u32) addr, d->base_addr + DINO_PCI_ADDR); \ + /* generate cfg write cycle */ \ + gsc_write##type(cpu_to_le##size(val), d->base_addr+DINO_IO_DATA+(addr&mask)); \ + spin_unlock_irqrestore(&(DINO_DEV(d)->dinosaur_pen), flags); \ +} + +DINO_PORT_OUT(b, 8, 3) +DINO_PORT_OUT(w, 16, 2) +DINO_PORT_OUT(l, 32, 0) + +struct pci_port_ops dino_port_ops = { + inb: dino_in8, + inw: dino_in16, + inl: dino_in32, + outb: dino_out8, + outw: dino_out16, + outl: dino_out32 +}; + +static void +dino_mask_irq(void *irq_dev, int irq) +{ + struct dino_device *dino_dev = DINO_DEV(irq_dev); + + DBG(KERN_WARNING "%s(0x%p, %d)\n", __FUNCTION__, irq_dev, irq); + + if (NULL == irq_dev || irq > DINO_IRQS || irq < 0) { + printk(KERN_WARNING "%s(0x%lx, %d) - not a dino irq?\n", + __FUNCTION__, (long) irq_dev, irq); + BUG(); + } else { + /* + ** Clear the matching bit in the IMR register + */ + dino_dev->imr &= ~(DINO_MASK_IRQ(irq)); + gsc_writel(dino_dev->imr, dino_dev->hba.base_addr+DINO_IMR); + } +} + + +static void +dino_unmask_irq(void *irq_dev, int irq) +{ + struct dino_device *dino_dev = DINO_DEV(irq_dev); + u32 tmp; + + DBG(KERN_WARNING "%s(0x%p, %d)\n", __FUNCTION__, irq_dev, irq); + + if (NULL == irq_dev || irq > DINO_IRQS) { + printk(KERN_WARNING "%s(): %d not a dino irq?\n", + __FUNCTION__, irq); + BUG(); + return; + } + + /* set the matching bit in the IMR register */ + dino_dev->imr |= DINO_MASK_IRQ(irq); /* used in dino_isr() */ + gsc_writel( dino_dev->imr, dino_dev->hba.base_addr+DINO_IMR); + + /* Emulate "Level Triggered" Interrupt + ** Basically, a driver is blowing it if the IRQ line is asserted + ** while the IRQ is disabled. But tulip.c seems to do that.... + ** Give 'em a kluge award and a nice round of applause! + ** + ** The gsc_write will generate an interrupt which invokes dino_isr(). + ** dino_isr() will read IPR and find nothing. But then catch this + ** when it also checks ILR. + */ + tmp = gsc_readl(dino_dev->hba.base_addr+DINO_ILR); + if (tmp & DINO_MASK_IRQ(irq)) { + DBG(KERN_WARNING "%s(): IRQ asserted! (ILR 0x%x)\n", + __FUNCTION__, tmp); + gsc_writel(dino_dev->txn_data, dino_dev->txn_addr); + } +} + + + +static void +dino_enable_irq(void *irq_dev, int irq) +{ + struct dino_device *dino_dev = DINO_DEV(irq_dev); + + /* + ** clear pending IRQ bits + ** + ** This does NOT change ILR state! + ** See comments in dino_unmask_irq() for ILR usage. + */ + gsc_readl(dino_dev->hba.base_addr+DINO_IPR); + + dino_unmask_irq(irq_dev, irq); +} + + +static struct irq_region_ops dino_irq_ops = { + disable_irq: dino_mask_irq, /* ??? */ + enable_irq: dino_enable_irq, + mask_irq: dino_mask_irq, + unmask_irq: dino_unmask_irq +}; + + +/* + * Handle a Processor interrupt generated by Dino. + * + * ilr_loop counter is a kluge to prevent a "stuck" IRQ line from + * wedging the CPU. Could be removed or made optional at some point. + */ +static void +dino_isr(int irq, void *intr_dev, struct pt_regs *regs) +{ + struct dino_device *dino_dev = DINO_DEV(intr_dev); + u32 mask; + int ilr_loop = 100; + extern void do_irq(struct irqaction *a, int i, struct pt_regs *p); + + + /* read and acknowledge pending interrupts */ +#ifdef DINO_DEBUG + dino_dev->dino_irr0 = +#endif + mask = gsc_readl(dino_dev->hba.base_addr+DINO_IRR0) & DINO_IRR_MASK; + +ilr_again: + while (mask) + { + int irq; + + /* + * Perform a binary search on set bits. + * `Less than Fatal' and PS2 interupts aren't supported. + */ + if (mask & 0xf) { + if (mask & 0x3) { + irq = (mask & 0x1) ? 0 : 1; /* PCI INT A, B */ + } else { + irq = (mask & 0x4) ? 2 : 3; /* PCI INT C, D */ + } + } else { + if (mask & 0x30) { + irq = (mask & 0x10) ? 4 : 5; /* PCI INT E, F */ + } else { + irq = (mask & 0x40) ? 6 : 10; /* GSC, RS232 */ + } + } + + mask &= ~(1<dino_region->action[irq], + dino_dev->dino_region->data.irqbase + irq, + regs); + + } + + /* Support for level triggered IRQ lines. + ** + ** Dropping this support would make this routine *much* faster. + ** But since PCI requires level triggered IRQ line to share lines... + ** device drivers may assume lines are level triggered (and not + ** edge triggered like EISA/ISA can be). + */ + mask = gsc_readl(dino_dev->hba.base_addr+DINO_ILR) & dino_dev->imr; + if (mask) { + if (--ilr_loop > 0) + goto ilr_again; + printk("Dino %lx: stuck interrupt %d\n", dino_dev->hba.base_addr, mask); + } +} + +static int dino_choose_irq(struct parisc_device *dev) +{ + int irq = -1; + + switch (dev->id.sversion) { + case 0x00084: irq = 8; break; /* PS/2 */ + case 0x0008c: irq = 10; break; /* RS232 */ + case 0x00096: irq = 8; break; /* PS/2 */ + } + + return irq; +} + +static void __init +dino_bios_init(void) +{ + DBG("dino_bios_init\n"); +} + +/* + * dino_card_setup - Set up the memory space for a Dino in card mode. + * @bus: the bus under this dino + * + * Claim an 8MB chunk of unused IO space and call the generic PCI routines + * to set up the addresses of the devices on this bus. + */ +#define _8MB 0x00800000UL +static void __init +dino_card_setup(struct pci_bus *bus, unsigned long base_addr) +{ + int i; + struct dino_device *dino_dev = DINO_DEV(bus->sysdata); + struct resource *res; + + res = &dino_dev->hba.lmmio_space; + res->flags = IORESOURCE_MEM; + + if (ccio_allocate_resource(dino_dev->hba.dev, res, _8MB, + (unsigned long) 0xfffffffff0000000UL | _8MB, + 0xffffffffffffffffUL &~ _8MB, _8MB, + NULL, NULL) < 0) { + printk(KERN_WARNING "Dino: Failed to allocate memory region\n"); + return; + } + bus->resource[1] = res; + bus->resource[0] = &(dino_dev->hba.io_space); + + /* Now tell dino what range it has */ + for (i = 1; i < 31; i++) { + if (res->start == (0xfffffffff0000000UL | i * _8MB)) + break; + } + gsc_writel(1 << i, base_addr + DINO_IO_ADDR_EN); + + pcibios_assign_unassigned_resources(bus); +} + +static void __init +dino_card_fixup(struct pci_dev *dev) +{ + u8 irq_pin; + + /* + ** REVISIT: card-mode PCI-PCI expansion chassis do exist. + ** Not sure they were ever productized. + ** Die here since we'll die later in dino_inb() anyway. + */ + if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { + panic("Card-Mode Dino: PCI-PCI Bridge not supported\n"); + } + + /* + ** Set Latency Timer to 0xff (not a shared bus) + ** Set CACHELINE_SIZE. + */ + dino_cfg_write16(dev, PCI_CACHE_LINE_SIZE, 0xff00 | L1_CACHE_BYTES/4); + + /* + ** Program INT_LINE for card-mode devices. + ** The cards are hardwired according to this algorithm. + ** And it doesn't matter if PPB's are present or not since + ** the IRQ lines bypass the PPB. + ** + ** "-1" converts INTA-D (1-4) to PCIINTA-D (0-3) range. + ** The additional "-1" adjusts for skewing the IRQ<->slot. + */ + dino_cfg_read8(dev, PCI_INTERRUPT_PIN, &irq_pin); + dev->irq = (irq_pin + PCI_SLOT(dev->devfn) - 1) % 4 ; + + /* Shouldn't really need to do this but it's in case someone tries + ** to bypass PCI services and look at the card themselves. + */ + dino_cfg_write8(dev, PCI_INTERRUPT_LINE, dev->irq); +} + + +static void __init +dino_fixup_bus(struct pci_bus *bus) +{ + struct list_head *ln; + struct pci_dev *dev; + struct dino_device *dino_dev = DINO_DEV(bus->sysdata); + int port_base = HBA_PORT_BASE(dino_dev->hba.hba_num); + + DBG(KERN_WARNING "%s(0x%p) bus %d sysdata 0x%p\n", + __FUNCTION__, bus, bus->secondary, bus->sysdata); + + /* Firmware doesn't set up card-mode dino, so we have to */ + if (is_card_dino(&dino_dev->hba.dev->id)) + dino_card_setup(bus, dino_dev->hba.base_addr); + + /* If this is a PCI-PCI Bridge, read the window registers etc */ + if (bus->self) + pci_read_bridge_bases(bus); + + list_for_each(ln, &bus->devices) { + int i; + + dev = pci_dev_b(ln); + if (is_card_dino(&dino_dev->hba.dev->id)) + dino_card_fixup(dev); + + /* + ** P2PB's only have 2 BARs, no IRQs. + ** I'd like to just ignore them for now. + */ + if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) + continue; + + /* Adjust the I/O Port space addresses */ + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + struct resource *res = &dev->resource[i]; + if (res->flags & IORESOURCE_IO) { + res->start |= port_base; + res->end |= port_base; + } +#ifdef __LP64__ + /* Sign Extend MMIO addresses */ + else if (res->flags & IORESOURCE_MEM) { + res->start |= 0xffffffff00000000UL; + res->end |= 0xffffffff00000000UL; + } +#endif + } + + /* Adjust INT_LINE for that busses region */ + dev->irq = dino_dev->dino_region->data.irqbase + dev->irq; + } +} + + +struct pci_bios_ops dino_bios_ops = { + dino_bios_init, + dino_fixup_bus /* void dino_fixup_bus(struct pci_bus *bus) */ +}; + + +/* + * Initialise a DINO controller chip + */ +static void __init +dino_card_init(struct dino_device *dino_dev) +{ + u32 brdg_feat = 0x00784e05; + + gsc_writel(0x00000000, dino_dev->hba.base_addr+DINO_GMASK); + gsc_writel(0x00000001, dino_dev->hba.base_addr+DINO_IO_FBB_EN); + gsc_writel(0x00000000, dino_dev->hba.base_addr+DINO_ICR); + +#if 1 +/* REVISIT - should be a runtime check (eg if (CPU_IS_PCX_L) ...) */ + /* + ** PCX-L processors don't support XQL like Dino wants it. + ** PCX-L2 ignore XQL signal and it doesn't matter. + */ + brdg_feat &= ~0x4; /* UXQL */ +#endif + gsc_writel( brdg_feat, dino_dev->hba.base_addr+DINO_BRDG_FEAT); + + /* + ** Don't enable address decoding until we know which I/O range + ** currently is available from the host. Only affects MMIO + ** and not I/O port space. + */ + gsc_writel(0x00000000, dino_dev->hba.base_addr+DINO_IO_ADDR_EN); + + gsc_writel(0x00000000, dino_dev->hba.base_addr+DINO_DAMODE); + gsc_writel(0x00222222, dino_dev->hba.base_addr+DINO_PCIROR); + gsc_writel(0x00222222, dino_dev->hba.base_addr+DINO_PCIWOR); + + gsc_writel(0x00000040, dino_dev->hba.base_addr+DINO_MLTIM); + gsc_writel(0x00000080, dino_dev->hba.base_addr+DINO_IO_CONTROL); + gsc_writel(0x0000008c, dino_dev->hba.base_addr+DINO_TLTIM); + + /* Disable PAMR before writing PAPR */ + gsc_writel(0x0000007e, dino_dev->hba.base_addr+DINO_PAMR); + gsc_writel(0x0000007f, dino_dev->hba.base_addr+DINO_PAPR); + gsc_writel(0x00000000, dino_dev->hba.base_addr+DINO_PAMR); + + /* + ** Dino ERS encourages enabling FBB (0x6f). + ** We can't until we know *all* devices below us can support it. + ** (Something in device configuration header tells us). + */ + gsc_writel(0x0000004f, dino_dev->hba.base_addr+DINO_PCICMD); + + /* Somewhere, the PCI spec says give devices 1 second + ** to recover from the #RESET being de-asserted. + ** Experience shows most devices only need 10ms. + ** This short-cut speeds up booting significantly. + */ + mdelay(pci_post_reset_delay); +} + +static int __init +dino_bridge_init(struct dino_device *dino_dev, const char *name) +{ + unsigned long io_addr, bpos; + int result; + struct resource *res; + /* + * Decoding IO_ADDR_EN only works for Built-in Dino + * since PDC has already initialized this. + */ + + io_addr = gsc_readl(dino_dev->hba.base_addr + DINO_IO_ADDR_EN); + if (io_addr == 0) { + printk(KERN_WARNING "%s: No PCI devices enabled.\n", name); + return -ENODEV; + } + + for (bpos = 0; (io_addr & (1 << bpos)) == 0; bpos++) + ; + + res = &dino_dev->hba.lmmio_space; + res->flags = IORESOURCE_MEM; + + res->start = (unsigned long)(signed int)(0xf0000000 | (bpos << 23)); + res->end = res->start + 8 * 1024 * 1024 - 1; + + result = ccio_request_resource(dino_dev->hba.dev, res); + if (result < 0) { + printk(KERN_ERR "%s: failed to claim PCI Bus address space!\n", name); + return result; + } + + return 0; +} + +static int __init dino_common_init(struct parisc_device *dev, + struct dino_device *dino_dev, const char *name) +{ + int status; + u32 eim; + struct gsc_irq gsc_irq; + struct resource *res; + + pcibios_register_hba(&dino_dev->hba); + + pci_bios = &dino_bios_ops; /* used by pci_scan_bus() */ + pci_port = &dino_port_ops; + + /* + ** Note: SMP systems can make use of IRR1/IAR1 registers + ** But it won't buy much performance except in very + ** specific applications/configurations. Note Dino + ** still only has 11 IRQ input lines - just map some of them + ** to a different processor. + */ + dino_dev->irq = gsc_alloc_irq(&gsc_irq); + dino_dev->txn_addr = gsc_irq.txn_addr; + dino_dev->txn_data = gsc_irq.txn_data; + eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data; + + /* + ** Dino needs a PA "IRQ" to get a processor's attention. + ** arch/parisc/kernel/irq.c returns an EIRR bit. + */ + if (dino_dev->irq < 0) { + printk(KERN_WARNING "%s: gsc_alloc_irq() failed\n", name); + return 1; + } + + status = request_irq(dino_dev->irq, dino_isr, 0, name, dino_dev); + if (status) { + printk(KERN_WARNING "%s: request_irq() failed with %d\n", + name, status); + return 1; + } + + /* + ** Tell generic interrupt support we have 11 bits which need + ** be checked in the interrupt handler. + */ + dino_dev->dino_region = alloc_irq_region(DINO_IRQS, &dino_irq_ops, + name, dino_dev); + + if (NULL == dino_dev->dino_region) { + printk(KERN_WARNING "%s: alloc_irq_region() failed\n", name); + return 1; + } + + /* Support the serial port which is sometimes attached on built-in + * Dino / Cujo chips. + */ + + fixup_child_irqs(dev, dino_dev->dino_region->data.irqbase, + dino_choose_irq); + + /* + ** This enables DINO to generate interrupts when it sees + ** any of it's inputs *change*. Just asserting an IRQ + ** before it's enabled (ie unmasked) isn't good enough. + */ + gsc_writel(eim, dino_dev->hba.base_addr+DINO_IAR0); + + /* + ** Some platforms don't clear Dino's IRR0 register at boot time. + ** Reading will clear it now. + */ + gsc_readl(dino_dev->hba.base_addr+DINO_IRR0); + + /* allocate I/O Port resource region */ + res = &dino_dev->hba.io_space; + if (dev->id.hversion == 0x680 || is_card_dino(&dev->id)) { + res->name = "Dino I/O Port"; + dino_dev->hba.lmmio_space.name = "Dino LMMIO"; + } else { + res->name = "Cujo I/O Port"; + dino_dev->hba.lmmio_space.name = "Cujo LMMIO"; + } + res->start = HBA_PORT_BASE(dino_dev->hba.hba_num); + res->end = res->start + (HBA_PORT_SPACE_SIZE - 1); + res->flags = IORESOURCE_IO; /* do not mark it busy ! */ + if (request_resource(&ioport_resource, res) < 0) { + printk(KERN_ERR "%s: request I/O Port region failed 0x%lx/%lx (hpa 0x%lx)\n", + name, res->start, res->end, dino_dev->hba.base_addr); + return 1; + } + + return 0; +} + +#define CUJO_RAVEN_ADDR 0xfffffffff1000000UL +#define CUJO_FIREHAWK_ADDR 0xfffffffff1604000UL +#define CUJO_RAVEN_BADPAGE 0x01003000UL +#define CUJO_FIREHAWK_BADPAGE 0x01607000UL + +static const char *dino_vers[] = { + "2.0", + "2.1", + "3.0", + "3.1" +}; + +static const char *cujo_vers[] = { + "1.0", + "2.0" +}; + +void ccio_cujo20_fixup(struct parisc_device *dev, u32 iovp); + +/* +** Determine if dino should claim this chip (return 0) or not (return 1). +** If so, initialize the chip appropriately (card-mode vs bridge mode). +** Much of the initialization is common though. +*/ +static int __init +dino_driver_callback(struct parisc_device *dev) +{ + struct dino_device *dino_dev; // Dino specific control struct + const char *version = "unknown"; + const char *name = "Dino"; + int is_cujo = 0; + + if (is_card_dino(&dev->id)) { + version = "3.x (card mode)"; + } else { + if(dev->id.hversion == 0x680) { + if (dev->id.hversion_rev < 4) { + version = dino_vers[dev->id.hversion_rev]; + } + } else { + name = "Cujo"; + is_cujo = 1; + if (dev->id.hversion_rev < 2) { + version = cujo_vers[dev->id.hversion_rev]; + } + } + } + + printk("%s version %s found at 0x%lx\n", name, version, dev->hpa); + + if (!request_mem_region(dev->hpa, PAGE_SIZE, name)) { + printk(KERN_ERR "DINO: Hey! Someone took my MMIO space (0x%ld)!\n", + dev->hpa); + return 1; + } + + /* Check for bugs */ + if (is_cujo && dev->id.hversion_rev == 1) { +#ifdef CONFIG_IOMMU_CCIO + printk(KERN_WARNING "Enabling Cujo 2.0 bug workaround\n"); + if (dev->hpa == CUJO_RAVEN_ADDR) { + ccio_cujo20_fixup(dev->parent, CUJO_RAVEN_BADPAGE); + } else if (dev->hpa == CUJO_FIREHAWK_ADDR) { + ccio_cujo20_fixup(dev->parent, CUJO_FIREHAWK_BADPAGE); + } else { + printk("Don't recognise Cujo at address 0x%lx, not enabling workaround\n", dev->hpa); + } +#endif + } else if (!is_cujo && !is_card_dino(&dev->id) && + dev->id.hversion_rev < 3) { + printk(KERN_WARNING +"The GSCtoPCI (Dino hrev %d) bus converter found may exhibit\n" +"data corruption. See Service Note Numbers: A4190A-01, A4191A-01.\n" +"Systems shipped after Aug 20, 1997 will not exhibit this problem.\n" +"Models affected: C180, C160, C160L, B160L, and B132L workstations.\n\n", + dev->id.hversion_rev); +/* REVISIT: why are C200/C240 listed in the README table but not +** "Models affected"? Could be an omission in the original literature. +*/ + } + + dino_dev = kmalloc(sizeof(struct dino_device), GFP_KERNEL); + if (!dino_dev) { + printk("dino_init_chip - couldn't alloc dino_device\n"); + return 1; + } + + memset(dino_dev, 0, sizeof(struct dino_device)); + + dino_dev->hba.dev = dev; + dino_dev->hba.base_addr = dev->hpa; /* faster access */ + dino_dev->hba.lmmio_space_offset = 0; /* CPU addrs == bus addrs */ + dino_dev->dinosaur_pen = SPIN_LOCK_UNLOCKED; + dino_dev->hba.iommu = ccio_get_iommu(dev); + + if (is_card_dino(&dev->id)) { + dino_card_init(dino_dev); + } else { + dino_bridge_init(dino_dev, name); + } + + if (dino_common_init(dev, dino_dev, name)) + return 1; + + /* + ** It's not used to avoid chicken/egg problems + ** with configuration accessor functions. + */ + dino_dev->hba.hba_bus = pci_scan_bus(dino_dev->hba.hba_num, + &dino_cfg_ops, dino_dev); + + return 0; +} + +/* + * Normally, we would just test sversion. But the Elroy PCI adapter has + * the same sversion as Dino, so we have to check hversion as well. + * Unfortunately, the J2240 PDC reports the wrong hversion for the first + * Dino, so we have to test for Dino, Cujo and Dino-in-a-J2240. + */ +static struct parisc_device_id dino_tbl[] = { + { HPHW_A_DMA, HVERSION_REV_ANY_ID, 0x004, 0x0009D }, /* Card-mode Dino. */ + { HPHW_A_DMA, HVERSION_REV_ANY_ID, 0x444, 0x08080 }, /* Same card in a 715. Bug? */ + { HPHW_BRIDGE, HVERSION_REV_ANY_ID, 0x680, 0xa }, /* Bridge-mode Dino */ + { HPHW_BRIDGE, HVERSION_REV_ANY_ID, 0x682, 0xa }, /* Bridge-mode Cujo */ + { HPHW_BRIDGE, HVERSION_REV_ANY_ID, 0x05d, 0xa }, /* Dino in a J2240 */ + { 0, } +}; + +static struct parisc_driver dino_driver = { + name: "Dino", + id_table: dino_tbl, + probe: dino_driver_callback, +}; + +/* + * One time initialization to let the world know Dino is here. + * This is the only routine which is NOT static. + * Must be called exactly once before pci_init(). + */ +int __init dino_init(void) +{ + register_parisc_driver(&dino_driver); + return 0; +} + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/gsc/eisa.c linux.19rc3-ac4/drivers/gsc/eisa.c --- linux.19rc3/drivers/gsc/eisa.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/gsc/eisa.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,454 @@ +/* + * eisa.c - provide support for EISA adapters in PA-RISC machines + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Copyright (c) 2001 Matthew Wilcox for Hewlett Packard + * Copyright (c) 2001 Daniel Engstrom <5116@telia.com> + * + * There are two distinct EISA adapters. Mongoose is found in machines + * before the 712; then the Wax ASIC is used. To complicate matters, the + * Wax ASIC also includes a PS/2 and RS-232 controller, but those are + * dealt with elsewhere; this file is concerned only with the EISA portions + * of Wax. + * + * + * HINT: + * ----- + * To allow an ISA card to work properly in the EISA slot you need to + * set an edge trigger level. This may be done on the palo command line + * by adding the kernel parameter "eisa_irq_edge=n,n2,[...]]", with + * n and n2 as the irq levels you want to use. + * + * Example: "eisa_irq_edge=10,11" allows ISA cards to operate at + * irq levels 10 and 11. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#if 0 +#define EISA_DBG(msg, arg... ) printk(KERN_DEBUG "eisa: " msg , ## arg ) +#else +#define EISA_DBG(msg, arg... ) +#endif + +#define SNAKES_EEPROM_BASE_ADDR 0xF0810400 +#define MIRAGE_EEPROM_BASE_ADDR 0xF00C0400 + +static spinlock_t eisa_irq_lock = SPIN_LOCK_UNLOCKED; + +/* We can only have one EISA adapter in the system because neither + * implementation can be flexed. + */ +static struct eisa_ba { + struct pci_hba_data hba; + unsigned long eeprom_addr; +} eisa_dev; + +/* Port ops */ + +static inline unsigned long eisa_permute(unsigned short port) +{ + if (port & 0x300) { + return 0xfc000000 | ((port & 0xfc00) >> 6) + | ((port & 0x3f8) << 9) | (port & 7); + } else { + return 0xfc000000 | port; + } +} + +unsigned char eisa_in8(unsigned short port) +{ + if (EISA_bus) + return gsc_readb(eisa_permute(port)); + return 0xff; +} + +unsigned short eisa_in16(unsigned short port) +{ + if (EISA_bus) + return le16_to_cpu(gsc_readw(eisa_permute(port))); + return 0xffff; +} + +unsigned int eisa_in32(unsigned short port) +{ + if (EISA_bus) + return le32_to_cpu(gsc_readl(eisa_permute(port))); + return 0xffffffff; +} + +void eisa_out8(unsigned char data, unsigned short port) +{ + if (EISA_bus) + gsc_writeb(data, eisa_permute(port)); +} + +void eisa_out16(unsigned short data, unsigned short port) +{ + if (EISA_bus) + gsc_writew(cpu_to_le16(data), eisa_permute(port)); +} + +void eisa_out32(unsigned int data, unsigned short port) +{ + if (EISA_bus) + gsc_writel(cpu_to_le32(data), eisa_permute(port)); +} + +/* Interrupt handling */ + +/* cached interrupt mask registers */ +static int master_mask; +static int slave_mask; + +/* the trig level can be set with the + * eisa_irq_edge=n,n,n commandline parameter + * We should really read this from the EEPROM + * in the furure. + */ +/* irq 13,8,2,1,0 must be edge */ +static unsigned int eisa_irq_level; /* default to edge triggered */ + + +/* called by free irq */ +static void eisa_disable_irq(void *irq_dev, int irq) +{ + unsigned long flags; + + EISA_DBG("disable irq %d\n", irq); + /* just mask for now */ + spin_lock_irqsave(&eisa_irq_lock, flags); + if (irq & 8) { + slave_mask |= (1 << (irq&7)); + eisa_out8(slave_mask, 0xa1); + } else { + master_mask |= (1 << (irq&7)); + eisa_out8(master_mask, 0x21); + } + spin_unlock_irqrestore(&eisa_irq_lock, flags); + EISA_DBG("pic0 mask %02x\n", eisa_in8(0x21)); + EISA_DBG("pic1 mask %02x\n", eisa_in8(0xa1)); +} + +/* called by request irq */ +static void eisa_enable_irq(void *irq_dev, int irq) +{ + unsigned long flags; + EISA_DBG("enable irq %d\n", irq); + + spin_lock_irqsave(&eisa_irq_lock, flags); + if (irq & 8) { + slave_mask &= ~(1 << (irq&7)); + eisa_out8(slave_mask, 0xa1); + } else { + master_mask &= ~(1 << (irq&7)); + eisa_out8(master_mask, 0x21); + } + spin_unlock_irqrestore(&eisa_irq_lock, flags); + EISA_DBG("pic0 mask %02x\n", eisa_in8(0x21)); + EISA_DBG("pic1 mask %02x\n", eisa_in8(0xa1)); +} + +static void eisa_mask_irq(void *irq_dev, int irq) +{ + unsigned long flags; + EISA_DBG("mask irq %d\n", irq); + + /* mask irq */ + spin_lock_irqsave(&eisa_irq_lock, flags); + if (irq & 8) { + slave_mask |= (1 << (irq&7)); + eisa_out8(slave_mask, 0xa1); + } else { + master_mask |= (1 << (irq&7)); + eisa_out8(master_mask, 0x21); + } + spin_unlock_irqrestore(&eisa_irq_lock, flags); +} + +static void eisa_unmask_irq(void *irq_dev, int irq) +{ + unsigned long flags; + EISA_DBG("unmask irq %d\n", irq); + + /* unmask */ + spin_lock_irqsave(&eisa_irq_lock, flags); + if (irq & 8) { + slave_mask &= ~(1 << (irq&7)); + eisa_out8(slave_mask, 0xa1); + } else { + master_mask &= ~(1 << (irq&7)); + eisa_out8(master_mask, 0x21); + } + spin_unlock_irqrestore(&eisa_irq_lock, flags); +} + +static struct irqaction action[IRQ_PER_REGION]; + +/* EISA needs to be fixed at IRQ region #0 (EISA_IRQ_REGION) */ +static struct irq_region eisa_irq_region = { + ops: { eisa_disable_irq, eisa_enable_irq, eisa_mask_irq, eisa_unmask_irq }, + data: { name: "EISA", irqbase: 0 }, + action: action, +}; + +static void eisa_irq(int _, void *intr_dev, struct pt_regs *regs) +{ + extern void do_irq(struct irqaction *a, int i, struct pt_regs *p); + int irq = gsc_readb(0xfc01f000); /* EISA supports 16 irqs */ + unsigned long flags; + + spin_lock_irqsave(&eisa_irq_lock, flags); + /* read IRR command */ + eisa_out8(0x0a, 0x20); + eisa_out8(0x0a, 0xa0); + + EISA_DBG("irq IAR %02x 8259-1 irr %02x 8259-2 irr %02x\n", + irq, eisa_in8(0x20), eisa_in8(0xa0)); + + /* read ISR command */ + eisa_out8(0x0a, 0x20); + eisa_out8(0x0a, 0xa0); + EISA_DBG("irq 8259-1 isr %02x imr %02x 8259-2 isr %02x imr %02x\n", + eisa_in8(0x20), eisa_in8(0x21), eisa_in8(0xa0), eisa_in8(0xa1)); + + irq &= 0xf; + + /* mask irq and write eoi */ + if (irq & 8) { + slave_mask |= (1 << (irq&7)); + eisa_out8(slave_mask, 0xa1); + eisa_out8(0x60 | (irq&7),0xa0);/* 'Specific EOI' to slave */ + eisa_out8(0x62,0x20); /* 'Specific EOI' to master-IRQ2 */ + + } else { + master_mask |= (1 << (irq&7)); + eisa_out8(master_mask, 0x21); + eisa_out8(0x60|irq,0x20); /* 'Specific EOI' to master */ + } + spin_unlock_irqrestore(&eisa_irq_lock, flags); + + + do_irq(&eisa_irq_region.action[irq], EISA_IRQ_REGION + irq, regs); + + spin_lock_irqsave(&eisa_irq_lock, flags); + /* unmask */ + if (irq & 8) { + slave_mask &= ~(1 << (irq&7)); + eisa_out8(slave_mask, 0xa1); + } else { + master_mask &= ~(1 << (irq&7)); + eisa_out8(master_mask, 0x21); + } + spin_unlock_irqrestore(&eisa_irq_lock, flags); +} + +static void dummy_irq2_handler(int _, void *dev, struct pt_regs *regs) +{ + printk(KERN_ALERT "eisa: uhh, irq2?\n"); +} + +static void init_eisa_pic(void) +{ + unsigned long flags; + + spin_lock_irqsave(&eisa_irq_lock, flags); + + eisa_out8(0xff, 0x21); /* mask during init */ + eisa_out8(0xff, 0xa1); /* mask during init */ + + /* master pic */ + eisa_out8(0x11,0x20); /* ICW1 */ + eisa_out8(0x00,0x21); /* ICW2 */ + eisa_out8(0x04,0x21); /* ICW3 */ + eisa_out8(0x01,0x21); /* ICW4 */ + eisa_out8(0x40,0x20); /* OCW2 */ + + /* slave pic */ + eisa_out8(0x11,0xa0); /* ICW1 */ + eisa_out8(0x08,0xa1); /* ICW2 */ + eisa_out8(0x02,0xa1); /* ICW3 */ + eisa_out8(0x01,0xa1); /* ICW4 */ + eisa_out8(0x40,0xa0); /* OCW2 */ + + udelay(100); + + slave_mask = 0xff; + master_mask = 0xfb; + eisa_out8(slave_mask, 0xa1); /* OCW1 */ + eisa_out8(master_mask, 0x21); /* OCW1 */ + + /* setup trig level */ + EISA_DBG("EISA edge/level %04x\n", eisa_irq_level); + + eisa_out8(eisa_irq_level&0xff, 0x4d0); /* Set all irq's to edge */ + eisa_out8((eisa_irq_level >> 8) & 0xff, 0x4d1); + + EISA_DBG("pic0 mask %02x\n", eisa_in8(0x21)); + EISA_DBG("pic1 mask %02x\n", eisa_in8(0xa1)); + EISA_DBG("pic0 edge/level %02x\n", eisa_in8(0x4d0)); + EISA_DBG("pic1 edge/level %02x\n", eisa_in8(0x4d1)); + + spin_unlock_irqrestore(&eisa_irq_lock, flags); +} + +/* Device initialisation */ + +#define is_mongoose(dev) (dev->id.sversion == 0x00076) + +static int __devinit eisa_probe(struct parisc_device *dev) +{ + int result; + + char *name = is_mongoose(dev) ? "Mongoose" : "Wax"; + + printk(KERN_INFO "%s EISA Adapter found at 0x%08lx\n", + name, dev->hpa); + + eisa_dev.hba.dev = dev; + eisa_dev.hba.iommu = ccio_get_iommu(dev); + + eisa_dev.hba.lmmio_space.name = "EISA"; + eisa_dev.hba.lmmio_space.start = (unsigned long) 0xfffffffffc000000; + eisa_dev.hba.lmmio_space.end = (unsigned long) 0xffffffffffbfffff; + eisa_dev.hba.lmmio_space.flags = IORESOURCE_MEM; + result = ccio_request_resource(dev, &eisa_dev.hba.lmmio_space); + if (result < 0) { + printk(KERN_ERR "EISA: failed to claim EISA Bus address space!\n"); + return result; + } + eisa_dev.hba.io_space.name = "EISA"; + eisa_dev.hba.io_space.start = 0; + eisa_dev.hba.io_space.end = 0xffff; + eisa_dev.hba.lmmio_space.flags = IORESOURCE_IO; + result = request_resource(&ioport_resource, &eisa_dev.hba.io_space); + if (result < 0) { + printk(KERN_ERR "EISA: failed to claim EISA Bus port space!\n"); + return result; + } + pcibios_register_hba(&eisa_dev.hba); + + result = request_irq(dev->irq, eisa_irq, SA_SHIRQ, "EISA", NULL); + if (result) { + printk(KERN_ERR "EISA: request_irq failed!\n"); + return result; + } + + /* Reserve IRQ2 */ + action[2].handler = dummy_irq2_handler; + action[2].name = "cascade"; + + eisa_irq_region.data.dev = dev; + irq_region[0] = &eisa_irq_region; + + EISA_bus = 1; + if (dev->num_addrs) { + /* newer firmware hand out the eeprom address */ + eisa_dev.eeprom_addr = dev->addr[0]; + } else { + /* old firmware, need to figure out the box */ + if (is_mongoose(dev)) { + eisa_dev.eeprom_addr = SNAKES_EEPROM_BASE_ADDR; + } else { + eisa_dev.eeprom_addr = MIRAGE_EEPROM_BASE_ADDR; + } + } + eisa_eeprom_init(eisa_dev.eeprom_addr); + eisa_enumerator(eisa_dev.eeprom_addr, &eisa_dev.hba.io_space, &eisa_dev.hba.lmmio_space); + init_eisa_pic(); + + return 0; +} + +static struct parisc_device_id __devinitdata eisa_tbl[] = { + { HPHW_BA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00076 }, /* Mongoose */ + { HPHW_BA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00090 }, /* Wax EISA */ + { 0, } +}; + +MODULE_DEVICE_TABLE(parisc, eisa_tbl); + +static struct parisc_driver eisa_driver = { + name: "EISA Bus Adapter", + id_table: eisa_tbl, + probe: eisa_probe, +}; + +void __init eisa_init(void) +{ + register_parisc_driver(&eisa_driver); +} + + +static unsigned int eisa_irq_configured; +void eisa_make_irq_level(int num) +{ + if (eisa_irq_configured& (1< 15 || val < 0) { + printk(KERN_ERR "eisa: EISA irq value are 0-15\n"); + continue; + } + if (val == 2) { + val = 9; + } + eisa_make_irq_edge(val); /* clear the corresponding bit */ + EISA_DBG("setting IRQ %d to edge-triggered mode\n", val); + + if ((cur = strchr(cur, ','))) { + cur++; + } else { + break; + } + } + return 1; +} + +__setup("eisa_irq_edge=", eisa_irq_setup); + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/gsc/eisa_eeprom.c linux.19rc3-ac4/drivers/gsc/eisa_eeprom.c --- linux.19rc3/drivers/gsc/eisa_eeprom.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/gsc/eisa_eeprom.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,107 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define EISA_EEPROM_MINOR 241 + +static unsigned long eeprom_addr; + +static long long eisa_eeprom_llseek(struct file *file, loff_t offset, int origin ) +{ + switch (origin) { + case 0: + /* nothing to do */ + break; + case 1: + offset += file->f_pos; + break; + case 2: + offset += HPEE_MAX_LENGTH; + break; + } + return (offset >= 0 && offset < HPEE_MAX_LENGTH) ? (file->f_pos = offset) : -EINVAL; +} + +static ssize_t eisa_eeprom_read(struct file * file, + char *buf, size_t count, loff_t *ppos ) +{ + unsigned char *tmp; + ssize_t ret; + int i; + + if (*ppos >= HPEE_MAX_LENGTH) + return 0; + + count = *ppos + count < HPEE_MAX_LENGTH ? count : HPEE_MAX_LENGTH - *ppos; + tmp = kmalloc(count, GFP_KERNEL); + if (tmp) { + for (i = 0; i < count; i++) + tmp[i] = gsc_readb(eeprom_addr+(*ppos)++); + + if (copy_to_user (buf, tmp, count)) + ret = -EFAULT; + else + ret = count; + kfree (tmp); + } else + ret = -ENOMEM; + + return ret; +} + +static int eisa_eeprom_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, + unsigned long arg) +{ + return -ENOTTY; +} + +static int eisa_eeprom_open(struct inode *inode, struct file *file) +{ + if (file->f_mode & 2 || eeprom_addr == 0) + return -EINVAL; + + return 0; +} + +static int eisa_eeprom_release(struct inode *inode, struct file *file) +{ + return 0; +} + +/* + * The various file operations we support. + */ +static struct file_operations eisa_eeprom_fops = { + owner: THIS_MODULE, + llseek: eisa_eeprom_llseek, + read: eisa_eeprom_read, + ioctl: eisa_eeprom_ioctl, + open: eisa_eeprom_open, + release: eisa_eeprom_release, +}; + +static struct miscdevice eisa_eeprom_dev= +{ + EISA_EEPROM_MINOR, + "eisa eeprom", + &eisa_eeprom_fops +}; + +int __init eisa_eeprom_init(unsigned long addr) +{ + if (addr) { + eeprom_addr = addr; + misc_register(&eisa_eeprom_dev); + printk(KERN_INFO "EISA EEPROM at 0x%lx\n", eeprom_addr); + } + return 0; +} + +MODULE_LICENSE("GPL"); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/gsc/eisa_enumerator.c linux.19rc3-ac4/drivers/gsc/eisa_enumerator.c --- linux.19rc3/drivers/gsc/eisa_enumerator.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/gsc/eisa_enumerator.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,518 @@ +/* + * eisa_enumerator.c - provide support for EISA adapters in PA-RISC machines + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Copyright (c) 2002 Daniel Engstrom <5116@telia.com> + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +/* + * Todo: + * + * PORT init with MASK attr and other size than byte + * MEMORY with other decode than 20 bit + * CRC stuff + * FREEFORM stuff + */ + +#define EPI 0xc80 +#define NUM_SLOT 16 +#define SLOT2PORT(x) (x<<12) + + +/* macros to handle unaligned accesses and + * byte swapping. The data in the EEPROM is + * little-endian on the big-endian PAROSC */ +#define get_8(x) (*(u_int8_t*)(x)) + +static inline u_int16_t get_16(const unsigned char *x) +{ + return (x[1] << 8) | x[0]; +} + +static inline u_int32_t get_32(const unsigned char *x) +{ + return (x[3] << 24) | (x[2] << 16) | (x[1] << 8) | x[0]; +} + +static inline u_int32_t get_24(const unsigned char *x) +{ + return (x[2] << 24) | (x[1] << 16) | (x[0] << 8); +} + +static void print_eisa_id(char *s, u_int32_t id) +{ + char vendor[4]; + int rev; + int device; + + rev = id & 0xff; + id >>= 8; + device = id & 0xff; + id >>= 8; + vendor[3] = '\0'; + vendor[2] = '@' + (id & 0x1f); + id >>= 5; + vendor[1] = '@' + (id & 0x1f); + id >>= 5; + vendor[0] = '@' + (id & 0x1f); + id >>= 5; + + sprintf(s, "%s%02X%02X", vendor, device, rev); +} + +static int configure_memory(const unsigned char *buf, + struct resource *mem_parent, + char *name) +{ + int len; + u_int8_t c; + int i; + struct resource *res; + + len=0; + + for (i=0;iname = name; + res->start = mem_parent->start + get_24(buf+len+2); + res->end = res->start + get_16(buf+len+5)*1024; + res->flags = IORESOURCE_MEM; + printk("memory %lx-%lx ", res->start, res->end); + result = request_resource(mem_parent, res); + if (result < 0) { + printk("\n" KERN_ERR "EISA Enumerator: failed to claim EISA Bus address space!\n"); + return result; + } + } + + len+=7; + + if (!(c & HPEE_MEMORY_MORE)) { + break; + } + } + + return len; +} + + +static int configure_irq(const unsigned char *buf) +{ + int len; + u_int8_t c; + int i; + + len=0; + + for (i=0;iname = board; + res->start = get_16(buf+len+1); + res->end = get_16(buf+len+1)+(c&HPEE_PORT_SIZE_MASK)+1; + res->flags = IORESOURCE_IO; + printk("ioports %lx-%lx ", res->start, res->end); + result = request_resource(io_parent, res); + if (result < 0) { + printk("\n" KERN_ERR "EISA Enumerator: failed to claim EISA Bus address space!\n"); + return result; + } + } + + len+=3; + if (!(c & HPEE_PORT_MORE)) { + break; + } + } + + return len; +} + + +/* byte 1 and 2 is the port number to write + * and at byte 3 the value to write starts. + * I assume that there are and- and or- masks + * here when HPEE_PORT_INIT_MASK is set but I have + * not yet encountered this. */ +static int configure_port_init(const unsigned char *buf) +{ + int len=0; + u_int8_t c; + + while (len 80) { + printk("\n" KERN_ERR "eisa_enumerator: type info field too long (%d, max is 80)\n", len); + } + + return 1+len; +} + +static int configure_function(const unsigned char *buf, int *more) +{ + /* the init field seems to be a two-byte field + * which is non-zero if there are an other function following + * I think it is the length of the function def + */ + *more = get_16(buf); + + return 2; +} + +static int parse_slot_config(int slot, + const unsigned char *buf, + struct eeprom_eisa_slot_info *es, + struct resource *io_parent, + struct resource *mem_parent) +{ + int res=0; + int function_len; + unsigned int pos=0; + unsigned int maxlen; + int num_func=0; + u_int8_t flags; + int p0; + + char *board; + int id_string_used=0; + + if (NULL == (board = kmalloc(8, GFP_KERNEL))) { + return -1; + } + print_eisa_id(board, es->eisa_slot_id); + printk(KERN_INFO "EISA slot %d: %s %s ", + slot, board, es->flags&HPEE_FLAG_BOARD_IS_ISA ? "ISA" : "EISA"); + + maxlen = es->config_data_length < HPEE_MAX_LENGTH ? + es->config_data_length : HPEE_MAX_LENGTH; + while ((pos < maxlen) && (num_func <= es->num_functions)) { + pos+=configure_function(buf+pos, &function_len); + + if (!function_len) { + break; + } + num_func++; + p0 = pos; + pos += configure_choise(buf+pos, &flags); + + if (flags & HPEE_FUNCTION_INFO_F_DISABLED) { + /* function disabled, skip silently */ + pos = p0 + function_len; + continue; + } + if (flags & HPEE_FUNCTION_INFO_CFG_FREE_FORM) { + /* I have no idea how to handle this */ + printk("function %d have free-form confgiuration, skipping ", + num_func); + pos = p0 + function_len; + continue; + } + + /* the ordering of the sections need + * more investigation. + * Currently I think that memory comaed before IRQ + * I assume the order is LSB to MSB in the + * info flags + * eg type, memory, irq, dma, port, HPEE_PORT_init + */ + + if (flags & HPEE_FUNCTION_INFO_HAVE_TYPE) { + pos += configure_type_string(buf+pos); + } + + if (flags & HPEE_FUNCTION_INFO_HAVE_MEMORY) { + id_string_used=1; + pos += configure_memory(buf+pos, mem_parent, board); + } + + if (flags & HPEE_FUNCTION_INFO_HAVE_IRQ) { + pos += configure_irq(buf+pos); + } + + if (flags & HPEE_FUNCTION_INFO_HAVE_DMA) { + pos += configure_dma(buf+pos); + } + + if (flags & HPEE_FUNCTION_INFO_HAVE_PORT) { + id_string_used=1; + pos += configure_port(buf+pos, io_parent, board); + } + + if (flags & HPEE_FUNCTION_INFO_HAVE_PORT_INIT) { + pos += configure_port_init(buf+pos); + } + + if (p0 + function_len < pos) { + printk("\n" KERN_ERR "eisa_enumerator: function %d length mis-match " + "got %d, expected %d\n", + num_func, pos-p0, function_len); + res=-1; + break; + } + pos = p0 + function_len; + } + printk("\n"); + if (!id_string_used) { + kfree(board); + } + + if (pos != es->config_data_length) { + printk(KERN_ERR "eisa_enumerator: config data length mis-match got %d, expected %d\n", + pos, es->config_data_length); + res=-1; + } + + if (num_func != es->num_functions) { + printk(KERN_ERR "eisa_enumerator: number of functions mis-match got %d, expected %d\n", + num_func, es->num_functions); + res=-2; + } + + return res; + +} + +static int init_slot(int slot, struct eeprom_eisa_slot_info *es) +{ + unsigned int id; + + char id_string[8]; + + if (!(es->slot_info&HPEE_SLOT_INFO_NO_READID)) { + /* try to read the id of the board in the slot */ + id = le32_to_cpu(inl(SLOT2PORT(slot)+EPI)); + + if (0xffffffff == id) { + /* this board is not here or it does not + * support readid + */ + printk(KERN_ERR "EISA slot %d a configured board was not detected (", + slot); + + print_eisa_id(id_string, es->eisa_slot_id); + printk(" expected %s)\n", id_string); + + return -1; + + } + if (es->eisa_slot_id != id) { + print_eisa_id(id_string, id); + printk(KERN_ERR "EISA slot %d id mis-match: got %s", + slot, id_string); + + print_eisa_id(id_string, es->eisa_slot_id); + printk(" expected %s \n", id_string); + + return -1; + + } + } + + /* now: we need to enable the board if + * it supports enabling and run through + * the port init sction if present + * and finally record any interrupt polarity + */ + if (es->slot_features & HPEE_SLOT_FEATURES_ENABLE) { + /* enable board */ + outb(0x01| inb(SLOT2PORT(slot)+EPI+4), + SLOT2PORT(slot)+EPI+4); + } + + return 0; +} + + +int eisa_enumerator(unsigned long eeprom_addr, + struct resource *io_parent, struct resource *mem_parent) +{ + int i; + struct eeprom_header *eh; + static char eeprom_buf[HPEE_MAX_LENGTH]; + + for (i=0; i < HPEE_MAX_LENGTH; i++) { + eeprom_buf[i] = gsc_readb(eeprom_addr+i); + } + + printk(KERN_INFO "Enumerating EISA bus\n"); + + eh = (struct eeprom_header*)(eeprom_buf); + for (i=0;inum_slots;i++) { + struct eeprom_eisa_slot_info *es; + + es = (struct eeprom_eisa_slot_info*) + (&eeprom_buf[HPEE_SLOT_INFO(i)]); + + if (-1==init_slot(i+1, es)) { + return -1; + + } + + if (es->config_data_offset < HPEE_MAX_LENGTH) { + if (parse_slot_config(i+1, &eeprom_buf[es->config_data_offset], + es, io_parent, mem_parent)) { + return -1; + } + } else { + printk (KERN_WARNING "EISA EEPROM offset 0x%x out of range\n",es->config_data_offset); + return -1; + } + } + return 0; +} + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/gsc/gsc.c linux.19rc3-ac4/drivers/gsc/gsc.c --- linux.19rc3/drivers/gsc/gsc.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/gsc/gsc.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,204 @@ +/* + * Interrupt management for most GSC and related devices. + * + * (c) Copyright 1999 Alex deVries for The Puffin Group + * (c) Copyright 1999 Grant Grundler for Hewlett-Packard + * (c) Copyright 1999 Matthew Wilcox + * (c) Copyright 2000 Helge Deller + * (c) Copyright 2001 Matthew Wilcox for Hewlett-Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "busdevice.h" + +#undef DEBUG + +#ifdef DEBUG +#define DEBPRINTK printk +#else +#define DEBPRINTK(x,...) +#endif + +int gsc_alloc_irq(struct gsc_irq *i) +{ + int irq = txn_alloc_irq(); + if (irq < 0) { + printk("cannot get irq\n"); + return irq; + } + + i->txn_addr = txn_alloc_addr(irq); + i->txn_data = txn_alloc_data(irq, GSC_EIM_WIDTH); + i->irq = irq; + + return irq; +} + + +int gsc_claim_irq(struct gsc_irq *i, int irq) +{ + int c = irq; + + irq += IRQ_FROM_REGION(CPU_IRQ_REGION); /* virtualize the IRQ first */ + + irq = txn_claim_irq(irq); + if (irq < 0) { + printk("cannot claim irq %d\n", c); + return irq; + } + + i->txn_addr = txn_alloc_addr(irq); + i->txn_data = txn_alloc_data(irq, GSC_EIM_WIDTH); + i->irq = irq; + + return irq; +} + + +/* IRQ bits must be numbered from Most Significant Bit */ +#define GSC_FIX_IRQ(x) (31-(x)) +#define GSC_MASK_IRQ(x) (1<<(GSC_FIX_IRQ(x))) + +/* Common interrupt demultiplexer used by Asp, Lasi & Wax. */ +void busdev_barked(int busdev_irq, void *dev, struct pt_regs *regs) +{ + unsigned long irq; + struct busdevice *busdev = (struct busdevice *) dev; + + /* + Don't need to protect OFFSET_IRR with spinlock since this is + the only place it's touched. + Protect busdev_region by disabling this region's interrupts, + modifying the region, and then re-enabling the region. + */ + + irq = gsc_readl(busdev->hpa+OFFSET_IRR); + if (irq == 0) { + printk(KERN_ERR "%s: barking without apparent reason.\n", busdev->name); + } else { + DEBPRINTK ("%s (0x%x) barked, mask=0x%x, irq=%d\n", + busdev->name, busdev->busdev_region->data.irqbase, + irq, GSC_FIX_IRQ(ffs(irq))+1 ); + + do_irq_mask(irq, busdev->busdev_region, regs); + } +} + +static void +busdev_disable_irq(void *irq_dev, int irq) +{ + /* Disable the IRQ line by clearing the bit in the IMR */ + u32 imr = gsc_readl(BUSDEV_DEV(irq_dev)->hpa+OFFSET_IMR); + imr &= ~(GSC_MASK_IRQ(irq)); + + DEBPRINTK( KERN_WARNING "%s(%p, %d) %s: IMR 0x%x\n", + __FUNCTION__, irq_dev, irq, BUSDEV_DEV(irq_dev)->name, imr); + + gsc_writel(imr, BUSDEV_DEV(irq_dev)->hpa+OFFSET_IMR); +} + + +static void +busdev_enable_irq(void *irq_dev, int irq) +{ + /* Enable the IRQ line by setting the bit in the IMR */ + unsigned long addr = BUSDEV_DEV(irq_dev)->hpa + OFFSET_IMR; + u32 imr = gsc_readl(addr); + imr |= GSC_MASK_IRQ(irq); + + DEBPRINTK (KERN_WARNING "%s(%p, %d) %s: IMR 0x%x\n", + __FUNCTION__, irq_dev, irq, BUSDEV_DEV(irq_dev)->name, imr); + + gsc_writel(imr, addr); +// gsc_writel(~0L, addr); + +/* FIXME: read IPR to make sure the IRQ isn't already pending. +** If so, we need to read IRR and manually call do_irq_mask(). +** This code should be shared with busdev_unmask_irq(). +*/ +} + +static void +busdev_mask_irq(void *irq_dev, int irq) +{ +/* FIXME: Clear the IMR bit in busdev for that IRQ */ +} + +static void +busdev_unmask_irq(void *irq_dev, int irq) +{ +/* FIXME: Read IPR. Set the IMR bit in busdev for that IRQ. + call do_irq_mask() if IPR is non-zero +*/ +} + +struct irq_region_ops busdev_irq_ops = { + disable_irq: busdev_disable_irq, + enable_irq: busdev_enable_irq, + mask_irq: busdev_mask_irq, + unmask_irq: busdev_unmask_irq +}; + + +int gsc_common_irqsetup(struct parisc_device *parent, struct busdevice *busdev) +{ + struct resource *res; + + busdev->gsc = parent; + + /* the IRQs we simulate */ + busdev->busdev_region = alloc_irq_region(32, &busdev_irq_ops, + busdev->name, busdev); + if (!busdev->busdev_region) + return -ENOMEM; + + /* allocate resource region */ + res = request_mem_region(busdev->hpa, 0x100000, busdev->name); + if (res) { + res->flags = IORESOURCE_MEM; /* do not mark it busy ! */ + } + +#if 0 + printk(KERN_WARNING "%s IRQ %d EIM 0x%x", busdev->name, + busdev->parent_irq, busdev->eim); + if (gsc_readl(busdev->hpa + OFFSET_IMR)) + printk(" IMR is non-zero! (0x%x)", + gsc_readl(busdev->hpa + OFFSET_IMR)); + printk("\n"); +#endif + + return 0; +} + +extern struct parisc_driver lasi_driver; +extern struct parisc_driver asp_driver; +extern struct parisc_driver wax_driver; + +void __init gsc_init(void) +{ +#ifdef CONFIG_GSC_LASI + register_parisc_driver(&lasi_driver); + register_parisc_driver(&asp_driver); +#endif +#ifdef CONFIG_GSC_WAX + register_parisc_driver(&wax_driver); +#endif +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/gsc/lasi.c linux.19rc3-ac4/drivers/gsc/lasi.c --- linux.19rc3/drivers/gsc/lasi.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/gsc/lasi.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,245 @@ +/* + * LASI Device Driver + * + * (c) Copyright 1999 Red Hat Software + * Portions (c) Copyright 1999 The Puffin Group Inc. + * Portions (c) Copyright 1999 Hewlett-Packard + * + * 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. + * + * by Alan Cox and + * Alex deVries + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "busdevice.h" + + +#define LASI_VER 0xC008 /* LASI Version */ + +#define LASI_IO_CONF 0x7FFFE /* LASI primary configuration register */ +#define LASI_IO_CONF2 0x7FFFF /* LASI secondary configuration register */ + +static int lasi_choose_irq(struct parisc_device *dev) +{ + int irq; + + /* + ** "irq" bits below are numbered relative to most significant bit. + */ + switch (dev->id.sversion) { + case 0x74: irq = 24; break; /* Centronics */ + case 0x7B: irq = 18; break; /* Audio */ + case 0x81: irq = 17; break; /* Lasi itself */ + case 0x82: irq = 22; break; /* SCSI */ + case 0x83: irq = 11; break; /* Floppy */ + case 0x84: irq = 5; break; /* PS/2 Keyboard */ + case 0x87: irq = 13; break; /* ISDN */ + case 0x8A: irq = 23; break; /* LAN */ + case 0x8C: irq = 26; break; /* RS232 */ + case 0x8D: irq = (dev->hw_path == 13) ? 15 : 14; + break; /* Telephone */ + default: irq = -1; break; /* unknown */ + } + + return irq; +} + +static void __init +lasi_init_irq(struct busdevice *this_lasi) +{ + unsigned long lasi_base = this_lasi->hpa; + + /* Stop LASI barking for a bit */ + gsc_writel(0x00000000, lasi_base+OFFSET_IMR); + + /* clear pending interrupts */ + gsc_readl(lasi_base+OFFSET_IRR); + + /* We're not really convinced we want to reset the onboard + * devices. Firmware does it for us... + */ + + /* Resets */ + /* gsc_writel(0xFFFFFFFF, lasi_base+0x2000);*/ /* Parallel */ + gsc_writel(0xFFFFFFFF, lasi_base+0x4004); /* Audio */ + /* gsc_writel(0xFFFFFFFF, lasi_base+0x5000);*/ /* Serial */ + /* gsc_writel(0xFFFFFFFF, lasi_base+0x6000);*/ /* SCSI */ + gsc_writel(0xFFFFFFFF, lasi_base+0x7000); /* LAN */ + gsc_writel(0xFFFFFFFF, lasi_base+0x8000); /* Keyboard */ + gsc_writel(0xFFFFFFFF, lasi_base+0xA000); /* FDC */ + + /* Ok we hit it on the head with a hammer, our Dog is now + ** comatose and muzzled. Devices will now unmask LASI + ** interrupts as they are registered as irq's in the LASI range. + */ + /* XXX: I thought it was `awks that got `it on the `ead with an + * `ammer. -- willy + */ +} + + +/* + ** lasi_led_init() + ** + ** lasi_led_init() initializes the LED controller on the LASI. + ** + ** Since Mirage and Electra machines use a different LED + ** address register, we need to check for these machines + ** explicitly. + */ + +#ifndef CONFIG_CHASSIS_LCD_LED + +#define lasi_led_init(x) /* nothing */ + +#else + +void __init lasi_led_init(unsigned long lasi_hpa) +{ + unsigned long datareg; + + switch (CPU_HVERSION) { + /* Gecko machines have only one single LED, which can be permanently + turned on by writing a zero into the power control register. */ + case 0x600: /* Gecko (712/60) */ + case 0x601: /* Gecko (712/80) */ + case 0x602: /* Gecko (712/100) */ + case 0x603: /* Anole 64 (743/64) */ + case 0x604: /* Anole 100 (743/100) */ + case 0x605: /* Gecko (712/120) */ + datareg = lasi_hpa + 0x0000C000; + gsc_writeb(0, datareg); + return; /* no need to register the LED interrupt-function */ + + /* Mirage and Electra machines need special offsets */ + case 0x60A: /* Mirage Jr (715/64) */ + case 0x60B: /* Mirage 100 */ + case 0x60C: /* Mirage 100+ */ + case 0x60D: /* Electra 100 */ + case 0x60E: /* Electra 120 */ + datareg = lasi_hpa - 0x00020000; + break; + + default: + datareg = lasi_hpa + 0x0000C000; + break; + } /* switch() */ + + register_led_driver(DISPLAY_MODEL_LASI, LED_CMD_REG_NONE, (char *)datareg); +} +#endif + +/* + * lasi_power_off + * + * Function for lasi to turn off the power. This is accomplished by setting a + * 1 to PWR_ON_L in the Power Control Register + * + */ + +static unsigned long lasi_power_off_hpa; + +static void lasi_power_off(void) +{ + unsigned long datareg; + + /* calculate addr of the Power Control Register */ + datareg = lasi_power_off_hpa + 0x0000C000; + + /* Power down the machine */ + gsc_writel(0x02, datareg); +} + +int __init +lasi_init_chip(struct parisc_device *dev) +{ + struct busdevice *lasi; + struct gsc_irq gsc_irq; + int irq, ret; + + lasi = kmalloc(sizeof(struct busdevice), GFP_KERNEL); + if (!lasi) + return -ENOMEM; + + lasi->name = "Lasi"; + lasi->hpa = dev->hpa; + + /* Check the 4-bit (yes, only 4) version register */ + lasi->version = gsc_readl(lasi->hpa + LASI_VER) & 0xf; + printk(KERN_INFO "%s version %d at 0x%lx found.\n", + lasi->name, lasi->version, lasi->hpa); + + /* initialize the chassis LEDs really early */ + lasi_led_init(lasi->hpa); + + /* Stop LASI barking for a bit */ + lasi_init_irq(lasi); + + /* the IRQ lasi should use */ + irq = gsc_alloc_irq(&gsc_irq); + if (irq < 0) { + printk(KERN_ERR "%s(): cannot get GSC irq\n", + __FUNCTION__); + kfree(lasi); + return -EBUSY; + } + + ret = request_irq(gsc_irq.irq, busdev_barked, 0, "lasi", lasi); + if (ret < 0) { + kfree(lasi); + return ret; + } + + /* Save this for debugging later */ + lasi->parent_irq = gsc_irq.irq; + lasi->eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data; + + /* enable IRQ's for devices below LASI */ + gsc_writel(lasi->eim, lasi->hpa + OFFSET_IAR); + + /* Done init'ing, register this driver */ + ret = gsc_common_irqsetup(dev, lasi); + if (ret) { + kfree(lasi); + return ret; + } + + fixup_child_irqs(dev, lasi->busdev_region->data.irqbase, + lasi_choose_irq); + + /* initialize the power off function */ + /* FIXME: Record the LASI HPA for the power off function. This should + * ensure that only the first LASI (the one controlling the power off) + * should set the HPA here */ + lasi_power_off_hpa = lasi->hpa; + pm_power_off = lasi_power_off; + + return ret; +} + +static struct parisc_device_id lasi_tbl[] = { + { HPHW_BA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00081 }, + { 0, } +}; + +struct parisc_driver lasi_driver = { + name: "Lasi", + id_table: lasi_tbl, + probe: lasi_init_chip, +}; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/gsc/Makefile linux.19rc3-ac4/drivers/gsc/Makefile --- linux.19rc3/drivers/gsc/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/gsc/Makefile 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,25 @@ +# +# Makefile for most of the non-PCI devices in PA-RISC machines +# +# 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 definition is now inherited from the +# parent makefile. +# + +O_TARGET := gscbus.o + +obj-y := gsc.o +obj-m := +obj-n := +obj- := + +obj-$(CONFIG_GSC_DINO) += dino.o +obj-$(CONFIG_GSC_LASI) += lasi.o asp.o +obj-$(CONFIG_GSC_WAX) += wax.o +obj-$(CONFIG_SERIAL_GSC) += serial.o +obj-$(CONFIG_EISA) += eisa.o eisa_enumerator.o eisa_eeprom.o + +include $(TOPDIR)/Rules.make diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/gsc/README.dino linux.19rc3-ac4/drivers/gsc/README.dino --- linux.19rc3/drivers/gsc/README.dino 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/gsc/README.dino 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,28 @@ +/* +** HP VISUALIZE Workstation PCI Bus Defect +** +** "HP has discovered a potential system defect that can affect +** the behavior of five models of HP VISUALIZE workstations when +** equipped with third-party or customer-installed PCI I/O expansion +** cards. The defect is limited to the HP C180, C160, C160L, B160L, +** and B132L VISUALIZE workstations, and will only be encountered +** when data is transmitted through PCI I/O expansion cards on the +** PCI bus. HP-supplied graphics cards that utilize the PCI bus are +** not affected." +** +** REVISIT: "go/pci_defect" link below is stale. +** HP Internal can use +** +** Product First Good Serial Number +** C200/C240 (US) US67350000 +**B132L+/B180 (US) US67390000 +** C200 (Europe) 3713G01000 +** B180L (Europe) 3720G01000 +** +** Note that many boards were fixed/replaced under a free replacement +** program. Assume a machine is only "suspect" until proven otherwise. +** +** "The pci_check program will also be available as application +** patch PHSS_12295" +*/ + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/gsc/serial.c linux.19rc3-ac4/drivers/gsc/serial.c --- linux.19rc3/drivers/gsc/serial.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/gsc/serial.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,133 @@ +/* + * Serial Device Initialisation for LASI/ASP/WAX/DINO + * + * (c) Copyright 2000 The Puffin Group Inc. + * (c) Copyright 2000-2001 Helge Deller + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "busdevice.h" + +static void setup_parisc_serial(struct serial_struct *serial, + unsigned long address, int irq, int line) +{ + memset(serial, 0, sizeof(struct serial_struct)); + + /* autoconfig() sets state->type. This sets info->type */ + serial->type = PORT_16550A; + + serial->line = line; + serial->iomem_base = ioremap(address, 0x8); + + serial->irq = irq; + serial->io_type = SERIAL_IO_MEM; /* define access method */ + serial->flags = 0; + serial->xmit_fifo_size = 16; + serial->custom_divisor = 0; + serial->baud_base = LASI_BASE_BAUD; +} + +static int __init +serial_init_chip(struct parisc_device *dev) +{ + static int serial_line_nr; + unsigned long address; + + struct serial_struct *serial; + + if (!dev->irq) { + if (dev->parent->id.hw_type != HPHW_IOA) { + printk(KERN_INFO "Serial: device 0x%lx not configured.\n" + "Enable support for Wax, Lasi, Asp or Dino.\n", dev->hpa); + } + return -ENODEV; + } + + serial = kmalloc(sizeof(*serial), GFP_KERNEL); + if (!serial) + return -ENOMEM; + + address = dev->hpa; + if (dev->id.sversion != 0x8d) { + address += 0x800; + } + + setup_parisc_serial(serial, address, dev->irq, serial_line_nr++); + + if (register_serial(serial) < 0) { + printk(KERN_WARNING "register_serial returned error\n"); + kfree(serial); + return -ENODEV; + } + + return 0; +} + +static struct parisc_device_id serial_tbl[] = { + { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00075 }, + { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008c }, + { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008d }, + { 0 } +}; + +/* Hack. Dino's serial port will get listed first on some machines. + * So we register this driver first which knows about Lasi's serial port. + * This needs to get fixed properly somehow. + */ +static struct parisc_device_id serial1_tbl[] = { + { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03B, 0x0008C }, /* C1xx/C1xxL */ + { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03C, 0x0008C }, /* B132L */ + { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03D, 0x0008C }, /* B160L */ + { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03E, 0x0008C }, /* B132L+ */ + { HPHW_FIO, HVERSION_REV_ANY_ID, 0x03F, 0x0008C }, /* B180L+ */ + { HPHW_FIO, HVERSION_REV_ANY_ID, 0x046, 0x0008C }, /* Rocky2 120 */ + { HPHW_FIO, HVERSION_REV_ANY_ID, 0x047, 0x0008C }, /* Rocky2 150 */ + { HPHW_FIO, HVERSION_REV_ANY_ID, 0x04E, 0x0008C }, /* Kiji L2 132 */ + { HPHW_FIO, HVERSION_REV_ANY_ID, 0x056, 0x0008C }, /* Raven+ */ + { 0 } +}; + + +MODULE_DEVICE_TABLE(parisc, serial_tbl); + +static struct parisc_driver serial1_driver = { + name: "Serial RS232", + id_table: serial1_tbl, + probe: serial_init_chip, +}; + +static struct parisc_driver serial_driver = { + name: "Serial RS232", + id_table: serial_tbl, + probe: serial_init_chip, +}; + +void __init probe_serial_gsc(void) +{ + register_parisc_driver(&serial1_driver); + register_parisc_driver(&serial_driver); +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/gsc/wax.c linux.19rc3-ac4/drivers/gsc/wax.c --- linux.19rc3/drivers/gsc/wax.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/gsc/wax.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,142 @@ +/* + * WAX Device Driver + * + * (c) Copyright 2000 The Puffin Group Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * by Helge Deller + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "busdevice.h" + +#define WAX_GSC_IRQ 7 /* Hardcoded Interrupt for GSC */ +#define WAX_GSC_NMI_IRQ 29 + +static int wax_choose_irq(struct parisc_device *dev) +{ + int irq = -1; + + switch (dev->id.sversion) { + case 0x73: irq = 30; break; /* HIL */ + case 0x8c: irq = 25; break; /* RS232 */ + case 0x90: irq = 21; break; /* WAX EISA BA */ + } + + return irq; +} + +static void __init +wax_init_irq(struct busdevice *wax) +{ + unsigned long base = wax->hpa; + + /* Stop WAX barking for a bit */ + gsc_writel(0x00000000, base+OFFSET_IMR); + + /* clear pending interrupts */ + (volatile u32) gsc_readl(base+OFFSET_IRR); + + /* We're not really convinced we want to reset the onboard + * devices. Firmware does it for us... + */ + + /* Resets */ +// gsc_writel(0xFFFFFFFF, base+0x1000); /* HIL */ +// gsc_writel(0xFFFFFFFF, base+0x2000); /* RS232-B on Wax */ + + /* Ok we hit it on the head with a hammer, our Dog is now + ** comatose and muzzled. Devices will now unmask WAX + ** interrupts as they are registered as irq's in the WAX range. + */ +} + +int __init +wax_init_chip(struct parisc_device *dev) +{ + struct busdevice *wax; + struct gsc_irq gsc_irq; + int irq, ret; + + wax = kmalloc(sizeof(struct busdevice), GFP_KERNEL); + if (!wax) + return -ENOMEM; + + wax->name = "Wax"; + wax->hpa = dev->hpa; + + wax->version = 0; /* gsc_readb(wax->hpa+WAX_VER); */ + printk(KERN_INFO "%s at 0x%lx found.\n", wax->name, wax->hpa); + + /* Stop wax hissing for a bit */ + wax_init_irq(wax); + + /* the IRQ wax should use */ + irq = gsc_claim_irq(&gsc_irq, WAX_GSC_IRQ); + if (irq < 0) { + printk(KERN_ERR "%s(): cannot get GSC irq\n", + __FUNCTION__); + kfree(wax); + return -EBUSY; + } + + ret = request_irq(gsc_irq.irq, busdev_barked, 0, "wax", wax); + if (ret < 0) { + kfree(wax); + return ret; + } + + /* Save this for debugging later */ + wax->parent_irq = gsc_irq.irq; + wax->eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data; + + /* enable IRQ's for devices below WAX */ + gsc_writel(wax->eim, wax->hpa + OFFSET_IAR); + + /* Done init'ing, register this driver */ + ret = gsc_common_irqsetup(dev, wax); + if (ret) { + kfree(wax); + return ret; + } + + fixup_child_irqs(dev, wax->busdev_region->data.irqbase, + wax_choose_irq); + /* On 715-class machines, Wax EISA is a sibling of Wax, not a child. */ + if (dev->parent->id.hw_type != HPHW_IOA) { + fixup_child_irqs(dev->parent, wax->busdev_region->data.irqbase, + wax_choose_irq); + } + + return ret; +} + +static struct parisc_device_id wax_tbl[] = { + { HPHW_BA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008e }, + { 0, } +}; + +MODULE_DEVICE_TABLE(parisc, wax_tbl); + +struct parisc_driver wax_driver = { + name: "Wax", + id_table: wax_tbl, + probe: wax_init_chip, +}; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/hil/Config.in linux.19rc3-ac4/drivers/hil/Config.in --- linux.19rc3/drivers/hil/Config.in 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/hil/Config.in 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,48 @@ +# +# HIL device driver configuration +# + +mainmenu_option next_comment +comment 'HIL support' + + +if [ "$CONFIG_INPUT" = "n" ]; then + comment 'Input support needed for HIL support' +else + bool 'HIL core support' CONFIG_HIL + + if [ "$CONFIG_HIL" != "n" ]; then + dep_tristate ' HIL Keyboard (basic) support' CONFIG_HIL_KBD_BASIC $CONFIG_INPUT_KEYBDEV + + comment ' HIL driver core support' + tristate ' HP System Device Controller i8042 Support' CONFIG_HP_SDC + dep_tristate ' HP SDC Real Time Clock' CONFIG_HP_SDC_RTC $CONFIG_HP_SDC + + dep_tristate ' HIL MLC Support' CONFIG_HIL_MLC $CONFIG_HP_SDC $CONFIG_INPUT_SERIO + if [ "$CONFIG_INPUT_SERIO" = "n" ]; then + comment ' Serial IO support needed for HIL keyboard and mouse support' + else + # This is not accurate but for now it will save confusion. + define_tristate CONFIG_HP_SDC_MLC $CONFIG_HIL_MLC + fi + + comment ' HIL device driver' + + if [ "$CONFIG_HIL_MLC" != "n" ]; then + if [ "$CONFIG_INPUT_KEYBDEV" = "n" ]; then + comment ' Keyboard input needed for HIL keyboard support' + else + dep_tristate ' HIL Keyboard (full) support' CONFIG_HIL_KBD $CONFIG_INPUT_KEYBDEV $CONFIG_HIL_MLC + fi + + if [ "$CONFIG_INPUT_MOUSEDEV" = "n" ]; then + comment ' Mouse input support needed for HIL mouse/pointer support' + else + dep_tristate ' HIL Mouse & Pointer support' CONFIG_HIL_PTR $CONFIG_INPUT_MOUSEDEV $CONFIG_HIL_MLC + fi + fi + + fi +fi + +endmenu diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/hil/hil_kbd.c linux.19rc3-ac4/drivers/hil/hil_kbd.c --- linux.19rc3/drivers/hil/hil_kbd.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/hil/hil_kbd.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,458 @@ +/* + * Generic linux-input device driver for keyboard devices + * + * Copyright (c) 2001 Brian S. Julin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL"). + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * + * References: + * HP-HIL Technical Reference Manual. Hewlett Packard Product No. 45918A + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef DEBUG /* DEBUG */ +#undef input_report_key +#define input_report_key(a,b,c) { printk("input_report_key(%p, %d, %d)\n", a, b, !!(c)); input_event(a, EV_KEY, b, !!(c)); } +#endif + +#define PREFIX "HIL KEYB: " +#define HIL_GENERIC_NAME "generic HIL keyboard device" + +MODULE_AUTHOR("Brian S. Julin "); +MODULE_DESCRIPTION(HIL_GENERIC_NAME " driver"); +MODULE_LICENSE("Dual BSD/GPL"); + +#define HIL_KBD_MAX_LENGTH 16 + +#define HIL_KBD_SET1_UPBIT 0x01 +#define HIL_KBD_SET1_SHIFT 1 + +static uint8_t hil_kbd_set1[128] = { + KEY_5, KEY_RESERVED, KEY_RIGHTALT, KEY_LEFTALT, + KEY_RIGHTSHIFT, KEY_LEFTSHIFT, KEY_LEFTCTRL, KEY_SYSRQ, + KEY_KP4, KEY_KP8, KEY_KP5, KEY_KP9, + KEY_KP6, KEY_KP7, KEY_KPCOMMA, KEY_KPENTER, + KEY_KP1, KEY_KPSLASH, KEY_KP2, KEY_KPPLUS, + KEY_KP3, KEY_KPASTERISK, KEY_KP0, KEY_KPMINUS, + KEY_B, KEY_V, KEY_C, KEY_X, + KEY_Z, KEY_UNKNOWN, KEY_RESERVED, KEY_ESC, + KEY_6, KEY_F10, KEY_3, KEY_F11, + KEY_KPDOT, KEY_F9, KEY_TAB /*KP*/, KEY_F12, + KEY_H, KEY_G, KEY_F, KEY_D, + KEY_S, KEY_A, KEY_RESERVED, KEY_CAPSLOCK, + KEY_U, KEY_Y, KEY_T, KEY_R, + KEY_E, KEY_W, KEY_Q, KEY_TAB, + KEY_7, KEY_6, KEY_5, KEY_4, + KEY_3, KEY_2, KEY_1, KEY_GRAVE, + KEY_INTL1, KEY_INTL2, KEY_INTL3, KEY_INTL4, /*Buttons*/ + KEY_INTL5, KEY_INTL6, KEY_INTL7, KEY_INTL8, + KEY_MENU, KEY_F4, KEY_F3, KEY_F2, + KEY_F1, KEY_VOLUMEUP, KEY_STOP, KEY_SENDFILE/*Enter/Print*/, + KEY_SYSRQ, KEY_F5, KEY_F6, KEY_F7, + KEY_F8, KEY_VOLUMEDOWN, KEY_CUT /*CLEAR_LINE*/, KEY_REFRESH /*CLEAR_DISPLAY*/, + KEY_8, KEY_9, KEY_0, KEY_MINUS, + KEY_EQUAL, KEY_BACKSPACE, KEY_INSERT/*KPINSERT_LINE*/, KEY_DELETE /*KPDELETE_LINE*/, + KEY_I, KEY_O, KEY_P, KEY_LEFTBRACE, + KEY_RIGHTBRACE, KEY_BACKSLASH, KEY_INSERT, KEY_DELETE, + KEY_J, KEY_K, KEY_L, KEY_SEMICOLON, + KEY_APOSTROPHE, KEY_ENTER, KEY_HOME, KEY_SCROLLUP, + KEY_M, KEY_COMMA, KEY_DOT, KEY_SLASH, + KEY_RESERVED, KEY_OPEN/*Select*/,KEY_RESERVED,KEY_SCROLLDOWN/*KPNEXT*/, + KEY_N, KEY_SPACE, KEY_SCROLLDOWN/*Next*/, KEY_UNKNOWN, + KEY_LEFT, KEY_DOWN, KEY_UP, KEY_RIGHT +}; + +#define HIL_KBD_SET2_UPBIT 0x01 +#define HIL_KBD_SET2_SHIFT 1 + +/* Set2 is user defined */ + +#define HIL_KBD_SET3_UPBIT 0x80 +#define HIL_KBD_SET3_SHIFT 0 + +static uint8_t hil_kbd_set3[128] = { + KEY_RESERVED, KEY_ESC, KEY_1, KEY_2, + KEY_3, KEY_4, KEY_5, KEY_6, + KEY_7, KEY_8, KEY_9, KEY_0, + KEY_MINUS, KEY_EQUAL, KEY_BACKSPACE, KEY_TAB, + KEY_Q, KEY_W, KEY_E, KEY_R, + KEY_T, KEY_Y, KEY_U, KEY_I, + KEY_O, KEY_P, KEY_LEFTBRACE, KEY_RIGHTBRACE, + KEY_ENTER, KEY_LEFTCTRL, KEY_A, KEY_S, + KEY_D, KEY_F, KEY_G, KEY_H, + KEY_J, KEY_K, KEY_L, KEY_SEMICOLON, + KEY_APOSTROPHE,KEY_GRAVE, KEY_LEFTSHIFT, KEY_BACKSLASH, + KEY_Z, KEY_X, KEY_C, KEY_V, + KEY_B, KEY_N, KEY_M, KEY_COMMA, + KEY_DOT, KEY_SLASH, KEY_RIGHTSHIFT, KEY_KPASTERISK, + KEY_LEFTALT, KEY_SPACE, KEY_CAPSLOCK, KEY_F1, + KEY_F2, KEY_F3, KEY_F4, KEY_F5, + KEY_F6, KEY_F7, KEY_F8, KEY_F9, + KEY_F10, KEY_NUMLOCK, KEY_SCROLLLOCK, KEY_KP7, + KEY_KP8, KEY_KP9, KEY_KPMINUS, KEY_KP4, + KEY_KP5, KEY_KP6, KEY_KPPLUS, KEY_KP1, + KEY_KP2, KEY_KP3, KEY_KP0, KEY_KPDOT, + KEY_SYSRQ, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, + KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, + KEY_RESERVED, KEY_RESERVED, KEY_UNKNOWN, KEY_UNKNOWN, + KEY_UP, KEY_LEFT, KEY_DOWN, KEY_RIGHT, + KEY_HOME, KEY_PAGEUP, KEY_END, KEY_PAGEDOWN, + KEY_INSERT, KEY_DELETE, KEY_102ND, KEY_RESERVED, + KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, + KEY_F1, KEY_F2, KEY_F3, KEY_F4, + KEY_F5, KEY_F6, KEY_F7, KEY_F8, + KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, + KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED +}; + +static char *hil_language[] = { HIL_LOCALE_MAP }; + +struct hil_kbd { + struct input_dev dev; + struct serio *serio; + + /* Input buffer and index for packets from HIL bus. */ + hil_packet data[HIL_KBD_MAX_LENGTH]; + int idx4; /* four counts per packet */ + + /* Raw device info records from HIL bus, see hil.h for fields. */ + char idd[HIL_KBD_MAX_LENGTH]; /* DID byte and IDD record */ + char rsc[HIL_KBD_MAX_LENGTH]; /* RSC record */ + char exd[HIL_KBD_MAX_LENGTH]; /* EXD record */ + char rnm[HIL_KBD_MAX_LENGTH + 1]; /* RNM record + NULL term. */ + + /* Something to sleep around with. */ + struct semaphore sem; +}; + +/* Process a complete packet after transfer from the HIL */ +static void hil_kbd_process_record(struct hil_kbd *kbd) +{ + struct input_dev *dev = &kbd->dev; + hil_packet *data = kbd->data; + hil_packet p; + int idx, i, cnt; + + idx = kbd->idx4/4; + p = data[idx - 1]; + + if ((p & ~HIL_CMDCT_POL) == + (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) goto report; + if ((p & ~HIL_CMDCT_RPL) == + (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) goto report; + + /* Not a poll response. See if we are loading config records. */ + switch (p & HIL_PKT_DATA_MASK) { + case HIL_CMD_IDD: + for (i = 0; i < idx; i++) + kbd->idd[i] = kbd->data[i] & HIL_PKT_DATA_MASK; + for (; i < HIL_KBD_MAX_LENGTH; i++) + kbd->idd[i] = 0; + break; + case HIL_CMD_RSC: + for (i = 0; i < idx; i++) + kbd->rsc[i] = kbd->data[i] & HIL_PKT_DATA_MASK; + for (; i < HIL_KBD_MAX_LENGTH; i++) + kbd->rsc[i] = 0; + break; + case HIL_CMD_EXD: + for (i = 0; i < idx; i++) + kbd->exd[i] = kbd->data[i] & HIL_PKT_DATA_MASK; + for (; i < HIL_KBD_MAX_LENGTH; i++) + kbd->exd[i] = 0; + break; + case HIL_CMD_RNM: + for (i = 0; i < idx; i++) + kbd->rnm[i] = kbd->data[i] & HIL_PKT_DATA_MASK; + for (; i < HIL_KBD_MAX_LENGTH + 1; i++) + kbd->rnm[i] = '\0'; + break; + default: + /* These occur when device isn't present */ + if (p == (HIL_ERR_INT | HIL_PKT_CMD)) break; + /* Anything else we'd like to know about. */ + printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p); + break; + } + goto out; + + report: + cnt = 1; + switch (kbd->data[0] & HIL_POL_CHARTYPE_MASK) { + case HIL_POL_CHARTYPE_NONE: + break; + case HIL_POL_CHARTYPE_ASCII: + while (cnt < idx - 1) + input_report_key(dev, kbd->data[cnt++] & 0x7f, 1); + break; + case HIL_POL_CHARTYPE_RSVD1: + case HIL_POL_CHARTYPE_RSVD2: + case HIL_POL_CHARTYPE_BINARY: + while (cnt < idx - 1) + input_report_key(dev, kbd->data[cnt++], 1); + break; + case HIL_POL_CHARTYPE_SET1: + while (cnt < idx - 1) { + unsigned int key; + int up; + key = kbd->data[cnt++]; + up = key & HIL_KBD_SET1_UPBIT; + key &= (~HIL_KBD_SET1_UPBIT & 0xff); + key = key >> HIL_KBD_SET1_SHIFT; + if (key != KEY_RESERVED && key != KEY_UNKNOWN) + input_report_key(dev, hil_kbd_set1[key], !up); + } + break; + case HIL_POL_CHARTYPE_SET2: + while (cnt < idx - 1) { + unsigned int key; + int up; + key = kbd->data[cnt++]; + up = key & HIL_KBD_SET2_UPBIT; + key &= (~HIL_KBD_SET1_UPBIT & 0xff); + key = key >> HIL_KBD_SET2_SHIFT; + if (key != KEY_RESERVED && key != KEY_UNKNOWN) + input_report_key(dev, key, !up); + } + break; + case HIL_POL_CHARTYPE_SET3: + while (cnt < idx - 1) { + unsigned int key; + int up; + key = kbd->data[cnt++]; + up = key & HIL_KBD_SET3_UPBIT; + key &= (~HIL_KBD_SET1_UPBIT & 0xff); + key = key >> HIL_KBD_SET3_SHIFT; + if (key != KEY_RESERVED && key != KEY_UNKNOWN) + input_report_key(dev, hil_kbd_set3[key], !up); + } + break; + } + out: + kbd->idx4 = 0; + up(&kbd->sem); +} + +static void hil_kbd_process_err(struct hil_kbd *kbd) { + printk(KERN_WARNING PREFIX "errored HIL packet\n"); + kbd->idx4 = 0; + up(&kbd->sem); + return; +} + +static void hil_kbd_interrupt(struct serio *serio, + unsigned char data, + unsigned int flags) +{ + struct hil_kbd *kbd; + hil_packet packet; + int idx; + + kbd = (struct hil_kbd *)serio->private; + if (kbd == NULL) { + BUG(); + return; + } + + if (kbd->idx4 >= (HIL_KBD_MAX_LENGTH * sizeof(hil_packet))) { + hil_kbd_process_err(kbd); + return; + } + idx = kbd->idx4/4; + if (!(kbd->idx4 % 4)) kbd->data[idx] = 0; + packet = kbd->data[idx]; + packet |= ((hil_packet)data) << ((3 - (kbd->idx4 % 4)) * 8); + kbd->data[idx] = packet; + + /* Records of N 4-byte hil_packets must terminate with a command. */ + if ((++(kbd->idx4)) % 4) return; + if ((packet & 0xffff0000) != HIL_ERR_INT) { + hil_kbd_process_err(kbd); + return; + } + if (packet & HIL_PKT_CMD) hil_kbd_process_record(kbd); +} + +static void hil_kbd_disconnect(struct serio *serio) +{ + struct hil_kbd *kbd; + + kbd = (struct hil_kbd *)serio->private; + if (kbd == NULL) { + BUG(); + return; + } + + input_unregister_device(&kbd->dev); + serio_close(serio); + kfree(kbd); +} + +static void hil_kbd_connect(struct serio *serio, struct serio_dev *dev) +{ + struct hil_kbd *kbd; + uint8_t did, *idd; + int i; + + if (serio->type != (SERIO_HIL_MLC | SERIO_HIL)) return; + + if (!(kbd = kmalloc(sizeof(struct hil_kbd), GFP_KERNEL))) return; + memset(kbd, 0, sizeof(struct hil_kbd)); + + if (serio_open(serio, dev)) goto bail0; + + serio->private = kbd; + kbd->serio = serio; + kbd->dev.private = kbd; + + init_MUTEX_LOCKED(&(kbd->sem)); + + /* Get device info. MLC driver supplies devid/status/etc. */ + serio->write(serio, 0); + serio->write(serio, 0); + serio->write(serio, HIL_PKT_CMD >> 8); + serio->write(serio, HIL_CMD_IDD); + down(&(kbd->sem)); + + serio->write(serio, 0); + serio->write(serio, 0); + serio->write(serio, HIL_PKT_CMD >> 8); + serio->write(serio, HIL_CMD_RSC); + down(&(kbd->sem)); + + serio->write(serio, 0); + serio->write(serio, 0); + serio->write(serio, HIL_PKT_CMD >> 8); + serio->write(serio, HIL_CMD_RNM); + down(&(kbd->sem)); + + serio->write(serio, 0); + serio->write(serio, 0); + serio->write(serio, HIL_PKT_CMD >> 8); + serio->write(serio, HIL_CMD_EXD); + down(&(kbd->sem)); + + up(&(kbd->sem)); + + did = kbd->idd[0]; + idd = kbd->idd + 1; + switch (did & HIL_IDD_DID_TYPE_MASK) { + case HIL_IDD_DID_TYPE_KB_INTEGRAL: + case HIL_IDD_DID_TYPE_KB_ITF: + case HIL_IDD_DID_TYPE_KB_RSVD: + case HIL_IDD_DID_TYPE_CHAR: + printk(KERN_INFO PREFIX "HIL keyboard found (did = 0x%02x, lang = %s)\n", + did, hil_language[did & HIL_IDD_DID_TYPE_KB_LANG_MASK]); + break; + default: + goto bail1; + } + + if(HIL_IDD_NUM_BUTTONS(idd) || HIL_IDD_NUM_AXES_PER_SET(*idd)) { + printk(KERN_INFO PREFIX "keyboards only, no combo devices supported.\n"); + goto bail1; + } + + kbd->dev.name = strlen(kbd->rnm) ? kbd->rnm : HIL_GENERIC_NAME; + + kbd->dev.idbus = BUS_HIL; + kbd->dev.idvendor = SERIO_HIL; + kbd->dev.idproduct = 0x0001; /* TODO: get from kbd->rsc */ + kbd->dev.idversion = 0x0100; /* TODO: get from kbd->rsc */ + + kbd->dev.evbit[0] |= BIT(EV_KEY); + + for (i = 0; i < 128; i++) { + set_bit(hil_kbd_set1[i], kbd->dev.keybit); + set_bit(hil_kbd_set3[i], kbd->dev.keybit); + } + clear_bit(0, kbd->dev.keybit); + +#if 1 + /* XXX: HACK !!! + * remove this call if hp_psaux.c/hp_keyb.c is converted + * to the input layer... */ + register_ps2_keybfuncs(); +#endif + + input_register_device(&kbd->dev); + printk(KERN_INFO "input%d: %s on hil%d\n", + kbd->dev.number, "HIL keyboard", 0); + + /* HIL keyboards don't have a numlock key, + * simulate a up-down sequence of numlock to + * make the keypad work at expected. */ + input_report_key(&kbd->dev, KEY_NUMLOCK, 1); +/* input_report_key(&kbd->dev, KEY_NUMLOCK, 0); */ + + serio->write(serio, 0); + serio->write(serio, 0); + serio->write(serio, HIL_PKT_CMD >> 8); + serio->write(serio, HIL_CMD_EK1); /* Enable Keyswitch Autorepeat 1 */ + down(&(kbd->sem)); + up(&(kbd->sem)); + + return; + bail1: + serio_close(serio); + bail0: + kfree(kbd); + return; +} + + +struct serio_dev hil_kbd_serio_dev = { + connect: hil_kbd_connect, + disconnect: hil_kbd_disconnect, + interrupt: hil_kbd_interrupt +}; + +static int __init hil_kbd_init(void) +{ + serio_register_device(&hil_kbd_serio_dev); + return 0; +} + +static void __exit hil_kbd_exit(void) +{ + serio_unregister_device(&hil_kbd_serio_dev); + +#if 1 + /* XXX: HACK !!! + * remove this call if hp_psaux.c/hp_keyb.c is converted + * to the input layer... */ + unregister_kbd_ops(); +#endif +} + +module_init(hil_kbd_init); +module_exit(hil_kbd_exit); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/hil/hilkbd.c linux.19rc3-ac4/drivers/hil/hilkbd.c --- linux.19rc3/drivers/hil/hilkbd.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/hil/hilkbd.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,389 @@ +/* + * linux/drivers/hil/hilkbd.c + * + * Copyright (C) 1998 Philip Blundell + * Copyright (C) 1999 Matthew Wilcox + * Copyright (C) 1999-2002 Helge Deller + * + * Very basic HP Human Interface Loop (HIL) driver. + * This driver handles the keyboard on HP300 (m68k) and on some + * HP700 (parisc) series machines. + * + * + * This file is subject to the terms and conditions of the GNU General Public + * License version 2. See the file COPYING in the main directory of this + * archive for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +MODULE_AUTHOR("Philip Blundell, Matthew Wilcox, Helge Deller"); +MODULE_DESCRIPTION("HIL driver (basic functionality)"); +MODULE_LICENSE("GPL"); +EXPORT_NO_SYMBOLS; + + +#if defined(CONFIG_PARISC) + + #include + #include + static unsigned long hil_base; /* HPA for the HIL device */ + static unsigned int hil_irq; + #define HILBASE hil_base /* HPPA (parisc) port address */ + #define HIL_DATA 0x800 + #define HIL_CMD 0x801 + #define HIL_IRQ hil_irq + #define hil_readb(p) gsc_readb(p) + #define hil_writeb(v,p) gsc_writeb((v),(p)) + +#elif defined(CONFIG_HP300) + + #define HILBASE 0xf0428000 /* HP300 (m86k) port address */ + #define HIL_DATA 0x1 + #define HIL_CMD 0x3 + #define HIL_IRQ 2 + #define hil_readb(p) readb(p) + #define hil_writeb(v,p) writeb((v),(p)) + +#else +#error "HIL is not supported on this platform" +#endif + + + +/* HIL helper functions */ + +#define hil_busy() (hil_readb(HILBASE + HIL_CMD) & HIL_BUSY) +#define hil_data_available() (hil_readb(HILBASE + HIL_CMD) & HIL_DATA_RDY) +#define hil_status() (hil_readb(HILBASE + HIL_CMD)) +#define hil_command(x) do { hil_writeb((x), HILBASE + HIL_CMD); } while (0) +#define hil_read_data() (hil_readb(HILBASE + HIL_DATA)) +#define hil_write_data(x) do { hil_writeb((x), HILBASE + HIL_DATA); } while (0) + +/* HIL constants */ + +#define HIL_BUSY 0x02 +#define HIL_DATA_RDY 0x01 + +#define HIL_SETARD 0xA0 /* set auto-repeat delay */ +#define HIL_SETARR 0xA2 /* set auto-repeat rate */ +#define HIL_SETTONE 0xA3 /* set tone generator */ +#define HIL_CNMT 0xB2 /* clear nmi */ +#define HIL_INTON 0x5C /* Turn on interrupts. */ +#define HIL_INTOFF 0x5D /* Turn off interrupts. */ +#define HIL_TRIGGER 0xC5 /* trigger command */ +#define HIL_STARTCMD 0xE0 /* start loop command */ +#define HIL_TIMEOUT 0xFE /* timeout */ +#define HIL_READTIME 0x13 /* Read real time register */ + +#define HIL_READBUSY 0x02 /* internal "busy" register */ +#define HIL_READKBDLANG 0x12 /* read keyboard language code */ +#define HIL_READKBDSADR 0xF9 +#define HIL_WRITEKBDSADR 0xE9 +#define HIL_READLPSTAT 0xFA +#define HIL_WRITELPSTAT 0xEA +#define HIL_READLPCTRL 0xFB +#define HIL_WRITELPCTRL 0xEB + + +static unsigned char hil_kbd_set1[128] = { + KEY_5, KEY_RESERVED, KEY_RIGHTALT, KEY_LEFTALT, + KEY_RIGHTSHIFT, KEY_LEFTSHIFT, KEY_LEFTCTRL, KEY_SYSRQ, + KEY_KP4, KEY_KP8, KEY_KP5, KEY_KP9, + KEY_KP6, KEY_KP7, KEY_KPCOMMA, KEY_KPENTER, + KEY_KP1, KEY_KPSLASH, KEY_KP2, KEY_KPPLUS, + KEY_KP3, KEY_KPASTERISK, KEY_KP0, KEY_KPMINUS, + KEY_B, KEY_V, KEY_C, KEY_X, + KEY_Z, KEY_UNKNOWN, KEY_RESERVED, KEY_ESC, + KEY_6, KEY_F10, KEY_3, KEY_F11, + KEY_KPDOT, KEY_F9, KEY_TAB /*KP*/, KEY_F12, + KEY_H, KEY_G, KEY_F, KEY_D, + KEY_S, KEY_A, KEY_RESERVED, KEY_CAPSLOCK, + KEY_U, KEY_Y, KEY_T, KEY_R, + KEY_E, KEY_W, KEY_Q, KEY_TAB, + KEY_7, KEY_6, KEY_5, KEY_4, + KEY_3, KEY_2, KEY_1, KEY_GRAVE, + KEY_INTL1, KEY_INTL2, KEY_INTL3, KEY_INTL4, /*Buttons*/ + KEY_INTL5, KEY_INTL6, KEY_INTL7, KEY_INTL8, + KEY_MENU, KEY_F4, KEY_F3, KEY_F2, + KEY_F1, KEY_VOLUMEUP, KEY_STOP, KEY_SENDFILE/*Enter/Print*/, + KEY_SYSRQ, KEY_F5, KEY_F6, KEY_F7, + KEY_F8, KEY_VOLUMEDOWN, KEY_CUT /*CLEAR_LINE*/, KEY_REFRESH /*CLEAR_DISPLAY*/, + KEY_8, KEY_9, KEY_0, KEY_MINUS, + KEY_EQUAL, KEY_BACKSPACE, KEY_INSERT/*KPINSERT_LINE*/, KEY_DELETE /*KPDELETE_LINE*/, + KEY_I, KEY_O, KEY_P, KEY_LEFTBRACE, + KEY_RIGHTBRACE, KEY_BACKSLASH, KEY_INSERT, KEY_DELETE, + KEY_J, KEY_K, KEY_L, KEY_SEMICOLON, + KEY_APOSTROPHE, KEY_ENTER, KEY_HOME, KEY_SCROLLUP, + KEY_M, KEY_COMMA, KEY_DOT, KEY_SLASH, + KEY_RESERVED, KEY_OPEN/*Select*/,KEY_RESERVED,KEY_SCROLLDOWN/*KPNEXT*/, + KEY_N, KEY_SPACE, KEY_SCROLLDOWN/*Next*/, KEY_UNKNOWN, + KEY_LEFT, KEY_DOWN, KEY_UP, KEY_RIGHT +}; + + +/* HIL structure */ +static struct { + struct input_dev dev; + + unsigned int curdev; + + unsigned char s; + unsigned char c; + int valid; + + unsigned char data[16]; + unsigned int ptr; + + void *dev_id; /* native bus device */ +} hil_dev; + + +static void poll_finished(void) +{ + int down; + int key; + unsigned char scode; + + switch (hil_dev.data[0]) { + case 0x40: + down = (hil_dev.data[1] & 1) == 0; + scode = hil_dev.data[1] >> 1; + key = hil_kbd_set1[scode & 0x7f]; + input_report_key(&hil_dev.dev, key, down); + break; + } + hil_dev.curdev = 0; +} + +static inline void handle_status(unsigned char s, unsigned char c) +{ + if (c & 0x8) { + /* End of block */ + if (c & 0x10) + poll_finished(); + } else { + if (c & 0x10) { + if (hil_dev.curdev) + poll_finished(); /* just in case */ + hil_dev.curdev = c & 7; + hil_dev.ptr = 0; + } + } +} + +static inline void handle_data(unsigned char s, unsigned char c) +{ + if (hil_dev.curdev) { + hil_dev.data[hil_dev.ptr++] = c; + hil_dev.ptr &= 15; + } +} + + +/* + * Handle HIL interrupts. + */ +static void hil_interrupt(int irq, void *handle, struct pt_regs *regs) +{ + unsigned char s, c; + + s = hil_status(); + c = hil_read_data(); + + switch (s >> 4) { + case 0x5: + handle_status(s, c); + break; + case 0x6: + handle_data(s, c); + break; + case 0x4: + hil_dev.s = s; + hil_dev.c = c; + mb(); + hil_dev.valid = 1; + break; + } +} + +/* + * Send a command to the HIL + */ + +static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len) +{ + unsigned long flags; + + save_flags(flags); + cli(); + while (hil_busy()) + /* wait */; + hil_command(cmd); + while (len--) { + while (hil_busy()) + /* wait */; + hil_write_data(*(data++)); + } + restore_flags(flags); +} + + +/* + * Initialise HIL. + */ + +static int __init +hil_keyb_init(void) +{ + unsigned char c; + unsigned int i, kbid, n = 0; + + if (hil_dev.dev.idbus) { + printk("HIL: already initialized\n"); + return -ENODEV; + } + +#if defined(CONFIG_HP300) + if (!hwreg_present((void *)(HILBASE + HIL_DATA))) + return -ENODEV; + + request_region(HILBASE+HIL_DATA, 2, "hil"); +#endif + + request_irq(HIL_IRQ, hil_interrupt, 0, "hil", hil_dev.dev_id); + + /* Turn on interrupts */ + hil_do(HIL_INTON, NULL, 0); + + /* Look for keyboards */ + hil_dev.valid = 0; /* clear any pending data */ + hil_do(HIL_READKBDSADR, NULL, 0); + while (!hil_dev.valid) { + if (n++ > 100000) { + printk(KERN_DEBUG "HIL: timed out, assuming no keyboard present.\n"); + break; + } + mb(); + } + + c = hil_dev.c; + hil_dev.valid = 0; + if (c == 0) { + kbid = -1; + printk(KERN_WARNING "HIL: no keyboard present.\n"); + } else { + kbid = ffz(~c); + printk(KERN_INFO "HIL: keyboard found at id %d\n", kbid); + } + + /* set it to raw mode */ + c = 0; + hil_do(HIL_WRITEKBDSADR, &c, 1); + + + /* register input interface */ + hil_dev.dev.name = "HIL keyboard"; + hil_dev.dev.idbus = BUS_HIL; + hil_dev.dev.idvendor = PCI_VENDOR_ID_HP; + hil_dev.dev.idproduct = 0x0001; + hil_dev.dev.idversion = 0x0100; + + hil_dev.dev.evbit[0] |= BIT(EV_KEY); + for (i = 0; i < 128; i++) + set_bit(hil_kbd_set1[i], hil_dev.dev.keybit); + clear_bit(0, hil_dev.dev.keybit); + +#if 1 + /* XXX: HACK !!! + * remove this call if hp_psaux.c/hp_keyb.c is converted + * to the input layer... */ + register_ps2_keybfuncs(); +#endif + + input_register_device(&hil_dev.dev); + printk(KERN_INFO "input%d: %s on hil%d (id %d)\n", + hil_dev.dev.number, hil_dev.dev.name, 0, kbid); + + /* HIL keyboards don't have a numlock key, + * simulate a up-down sequence of numlock to + * make the keypad work at expected. */ + input_report_key(&hil_dev.dev, KEY_NUMLOCK, 1); + + return 0; +} + +#if defined(CONFIG_PARISC) +static int __init +hil_init_chip(struct parisc_device *dev) +{ + if (!dev->irq) { + printk(KERN_WARNING "HIL: IRQ not found for HIL at 0x%lx\n", dev->hpa); + return -ENODEV; + } + + hil_base = dev->hpa; + hil_irq = dev->irq; + hil_dev.dev_id = dev; + + printk(KERN_INFO "Found HIL at 0x%lx, IRQ %d\n", hil_base, hil_irq); + + return hil_keyb_init(); +} + +static struct parisc_device_id hil_tbl[] = { + { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00073 }, + { 0, } +}; + +MODULE_DEVICE_TABLE(parisc, hil_tbl); + +static struct parisc_driver hil_driver = { + name: "HIL", + id_table: hil_tbl, + probe: hil_init_chip, +}; +#endif /* CONFIG_PARISC */ + + + + + +static int __init hil_init(void) +{ +#if defined(CONFIG_PARISC) + return register_parisc_driver(&hil_driver); +#else + return hil_keyb_init(); +#endif +} + + +static void __exit hil_exit(void) +{ + if (HIL_IRQ) { + disable_irq(HIL_IRQ); + free_irq(HIL_IRQ, hil_dev.dev_id); + } + + input_unregister_device(&hil_dev.dev); + +#if defined(CONFIG_PARISC) + unregister_parisc_driver(&hil_driver); +#else + release_region(HILBASE+HIL_DATA, 2); +#endif +} + +module_init(hil_init); +module_exit(hil_exit); + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/hil/hil_mlc.c linux.19rc3-ac4/drivers/hil/hil_mlc.c --- linux.19rc3/drivers/hil/hil_mlc.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/hil/hil_mlc.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,951 @@ +/* + * HIL MLC state machine and serio interface driver + * + * Copyright (c) 2001 Brian S. Julin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL"). + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * + * References: + * HP-HIL Technical Reference Manual. Hewlett Packard Product No. 45918A + * + * + * Driver theory of operation: + * + * Some access methods and an ISR is defined by the sub-driver + * (e.g. hp_sdc_mlc.c). These methods are expected to provide a + * few bits of logic in addition to raw access to the HIL MLC, + * specifically, the ISR, which is entirely registered by the + * sub-driver and invoked directly, must check for record + * termination or packet match, at which point a semaphore must + * be cleared and then the hil_mlcs_tasklet must be scheduled. + * + * The hil_mlcs_tasklet processes the state machine for all MLCs + * each time it runs, checking each MLC's progress at the current + * node in the state machine, and moving the MLC to subsequent nodes + * in the state machine when appropriate. It will reschedule + * itself if output is pending. (This rescheduling should be replaced + * at some point with a sub-driver-specific mechanism.) + * + * A timer task prods the tasket once per second to prevent + * hangups when attached devices do not return expected data + * and to initiate probes of the loop for new devices. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_AUTHOR("Brian S. Julin "); +MODULE_DESCRIPTION("HIL MLC serio"); +MODULE_LICENSE("Dual BSD/GPL"); + +EXPORT_SYMBOL(hil_mlc_register); +EXPORT_SYMBOL(hil_mlc_unregister); + +#define PREFIX "HIL MLC: " + +static LIST_HEAD(hil_mlcs); +static rwlock_t hil_mlcs_lock = RW_LOCK_UNLOCKED; +static struct timer_list hil_mlcs_kicker; +static int hil_mlcs_probe; + +static void hil_mlcs_process(unsigned long unused); +DECLARE_TASKLET_DISABLED(hil_mlcs_tasklet, hil_mlcs_process, 0); + + +/* #define HIL_MLC_DEBUG */ + +/********************** Device info/instance management **********************/ + +static void hil_mlc_clear_di_map (hil_mlc *mlc, int val) { + int j; + for (j = val; j < 7 ; j++) { + mlc->di_map[j] = -1; + } +} + +static void hil_mlc_clear_di_scratch (hil_mlc *mlc) { + memset(&(mlc->di_scratch), 0, sizeof(mlc->di_scratch)); +} + +static void hil_mlc_copy_di_scratch (hil_mlc *mlc, int idx) { + memcpy(&(mlc->di[idx]), &(mlc->di_scratch), sizeof(mlc->di_scratch)); +} + +static int hil_mlc_match_di_scratch (hil_mlc *mlc) { + int idx; + + for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) { + int j, found; + + /* In-use slots are not eligible. */ + found = 0; + for (j = 0; j < 7 ; j++) { + if (mlc->di_map[j] == idx) found++; + } + if (found) continue; + if (!memcmp(mlc->di + idx, + &(mlc->di_scratch), + sizeof(mlc->di_scratch))) break; + } + return((idx >= HIL_MLC_DEVMEM) ? -1 : idx); +} + +static int hil_mlc_find_free_di(hil_mlc *mlc) { + int idx; + /* TODO: Pick all-zero slots first, failing that, + * randomize the slot picked among those eligible. + */ + for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) { + int j, found; + found = 0; + for (j = 0; j < 7 ; j++) { + if (mlc->di_map[j] == idx) found++; + } + if (!found) break; + } + return(idx); /* Note: It is guaranteed at least one above will match */ +} + +static inline void hil_mlc_clean_serio_map(hil_mlc *mlc) { + int idx; + for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) { + int j, found; + found = 0; + for (j = 0; j < 7 ; j++) { + if (mlc->di_map[j] == idx) found++; + } + if (!found) mlc->serio_map[idx].di_revmap = -1; + } +} + +static void hil_mlc_send_polls(hil_mlc *mlc) { + int did, i, cnt; + struct serio *serio; + struct serio_dev *dev; + + i = cnt = 0; + did = (mlc->ipacket[0] & HIL_PKT_ADDR_MASK) >> 8; + serio = did ? &(mlc->serio[mlc->di_map[did - 1]]) : NULL; + dev = (serio != NULL) ? serio->dev : NULL; + + while (mlc->icount < 15 - i) { + hil_packet p; + p = mlc->ipacket[i]; + if (did != (p & HIL_PKT_ADDR_MASK) >> 8) { + if (dev == NULL || dev->interrupt == NULL) goto skip; + + dev->interrupt(serio, 0, 0); + dev->interrupt(serio, HIL_ERR_INT >> 16, 0); + dev->interrupt(serio, HIL_PKT_CMD >> 8, 0); + dev->interrupt(serio, HIL_CMD_POL + cnt, 0); + skip: + did = (p & HIL_PKT_ADDR_MASK) >> 8; + serio = did ? &(mlc->serio[mlc->di_map[did-1]]) : NULL; + dev = (serio != NULL) ? serio->dev : NULL; + cnt = 0; + } + cnt++; i++; + if (dev == NULL || dev->interrupt == NULL) continue; + dev->interrupt(serio, (p >> 24), 0); + dev->interrupt(serio, (p >> 16) & 0xff, 0); + dev->interrupt(serio, (p >> 8) & ~HIL_PKT_ADDR_MASK, 0); + dev->interrupt(serio, p & 0xff, 0); + } +} + +/*************************** State engine *********************************/ + +#define HILSEN_SCHED 0x000100 /* Schedule the tasklet */ +#define HILSEN_BREAK 0x000200 /* Wait until next pass */ +#define HILSEN_UP 0x000400 /* relative node#, decrement */ +#define HILSEN_DOWN 0x000800 /* relative node#, increment */ +#define HILSEN_FOLLOW 0x001000 /* use retval as next node# */ + +#define HILSEN_MASK 0x0000ff +#define HILSEN_START 0 +#define HILSEN_RESTART 1 +#define HILSEN_DHR 9 +#define HILSEN_DHR2 10 +#define HILSEN_IFC 14 +#define HILSEN_HEAL0 16 +#define HILSEN_HEAL 18 +#define HILSEN_ACF 21 +#define HILSEN_ACF2 22 +#define HILSEN_DISC0 25 +#define HILSEN_DISC 27 +#define HILSEN_MATCH 40 +#define HILSEN_OPERATE 41 +#define HILSEN_PROBE 44 +#define HILSEN_DSR 52 +#define HILSEN_REPOLL 55 +#define HILSEN_IFCACF 58 +#define HILSEN_END 60 + +#define HILSEN_NEXT (HILSEN_DOWN | 1) +#define HILSEN_SAME (HILSEN_DOWN | 0) +#define HILSEN_LAST (HILSEN_UP | 1) + +#define HILSEN_DOZE (HILSEN_SAME | HILSEN_SCHED | HILSEN_BREAK) +#define HILSEN_SLEEP (HILSEN_SAME | HILSEN_BREAK) + +static int hilse_match(hil_mlc *mlc, int unused) { + int rc; + rc = hil_mlc_match_di_scratch(mlc); + if (rc == -1) { + rc = hil_mlc_find_free_di(mlc); + if (rc == -1) goto err; +#ifdef HIL_MLC_DEBUG + printk(KERN_DEBUG PREFIX "new in slot %i\n", rc); +#endif + hil_mlc_copy_di_scratch(mlc, rc); + mlc->di_map[mlc->ddi] = rc; + mlc->serio_map[rc].di_revmap = mlc->ddi; + hil_mlc_clean_serio_map(mlc); + serio_rescan(mlc->serio + rc); + return -1; + } + mlc->di_map[mlc->ddi] = rc; +#ifdef HIL_MLC_DEBUG + printk(KERN_DEBUG PREFIX "same in slot %i\n", rc); +#endif + mlc->serio_map[rc].di_revmap = mlc->ddi; + hil_mlc_clean_serio_map(mlc); + return 0; + err: + printk(KERN_ERR PREFIX "Residual device slots exhausted, close some serios!\n"); + return 1; +} + +/* An LCV used to prevent runaway loops, forces 5 second sleep when reset. */ +static int hilse_init_lcv(hil_mlc *mlc, int unused) { + struct timeval tv; + + do_gettimeofday(&tv); + + if(mlc->lcv == 0) goto restart; /* First init, no need to dally */ + if(tv.tv_sec - mlc->lcv_tv.tv_sec < 5) return -1; + restart: + mlc->lcv_tv = tv; + mlc->lcv = 0; + return 0; +} + +static int hilse_inc_lcv(hil_mlc *mlc, int lim) { + if (mlc->lcv++ >= lim) return -1; + return 0; +} + +#if 0 +static int hilse_set_lcv(hil_mlc *mlc, int val) { + mlc->lcv = val; + return 0; +} +#endif + +/* Management of the discovered device index (zero based, -1 means no devs) */ +static int hilse_set_ddi(hil_mlc *mlc, int val) { + mlc->ddi = val; + hil_mlc_clear_di_map(mlc, val + 1); + return 0; +} + +static int hilse_dec_ddi(hil_mlc *mlc, int unused) { + mlc->ddi--; + if (mlc->ddi <= -1) { + mlc->ddi = -1; + hil_mlc_clear_di_map(mlc, 0); + return -1; + } + hil_mlc_clear_di_map(mlc, mlc->ddi + 1); + return 0; +} + +static int hilse_inc_ddi(hil_mlc *mlc, int unused) { + if (mlc->ddi >= 6) { + BUG(); + return -1; + } + mlc->ddi++; + return 0; +} + +static int hilse_take_idd(hil_mlc *mlc, int unused) { + int i; + + /* Help the state engine: + * Is this a real IDD response or just an echo? + * + * Real IDD response does not start with a command. + */ + if (mlc->ipacket[0] & HIL_PKT_CMD) goto bail; + /* Should have the command echoed further down. */ + for (i = 1; i < 16; i++) { + if (((mlc->ipacket[i] & HIL_PKT_ADDR_MASK) == + (mlc->ipacket[0] & HIL_PKT_ADDR_MASK)) && + (mlc->ipacket[i] & HIL_PKT_CMD) && + ((mlc->ipacket[i] & HIL_PKT_DATA_MASK) == HIL_CMD_IDD)) + break; + } + if (i > 15) goto bail; + /* And the rest of the packets should still be clear. */ + while (++i < 16) { + if (mlc->ipacket[i]) break; + } + if (i < 16) goto bail; + for (i = 0; i < 16; i++) { + mlc->di_scratch.idd[i] = + mlc->ipacket[i] & HIL_PKT_DATA_MASK; + } + /* Next step is to see if RSC supported */ + if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_RSC) + return HILSEN_NEXT; + if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD) + return HILSEN_DOWN | 4; + return 0; + bail: + mlc->ddi--; + return -1; /* This should send us off to ACF */ +} + +static int hilse_take_rsc(hil_mlc *mlc, int unused) { + int i; + + for (i = 0; i < 16; i++) { + mlc->di_scratch.rsc[i] = + mlc->ipacket[i] & HIL_PKT_DATA_MASK; + } + /* Next step is to see if EXD supported (IDD has already been read) */ + if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD) + return HILSEN_NEXT; + return 0; +} + +static int hilse_take_exd(hil_mlc *mlc, int unused) { + int i; + + for (i = 0; i < 16; i++) { + mlc->di_scratch.exd[i] = + mlc->ipacket[i] & HIL_PKT_DATA_MASK; + } + /* Next step is to see if RNM supported. */ + if (mlc->di_scratch.exd[0] & HIL_EXD_HEADER_RNM) + return HILSEN_NEXT; + return 0; +} + +static int hilse_take_rnm(hil_mlc *mlc, int unused) { + int i; + + for (i = 0; i < 16; i++) { + mlc->di_scratch.rnm[i] = + mlc->ipacket[i] & HIL_PKT_DATA_MASK; + } + do { + char nam[17]; + snprintf(nam, 16, "%s", mlc->di_scratch.rnm); + nam[16] = '\0'; + printk(KERN_INFO PREFIX "Device name gotten: %s\n", nam); + } while (0); + return 0; +} + +static int hilse_operate(hil_mlc *mlc, int repoll) { + + if (mlc->opercnt == 0) hil_mlcs_probe = 0; + mlc->opercnt = 1; + + hil_mlc_send_polls(mlc); + + if (!hil_mlcs_probe) return 0; + hil_mlcs_probe = 0; + mlc->opercnt = 0; + return 1; +} + +#define FUNC(funct, funct_arg, zero_rc, neg_rc, pos_rc) \ +{ HILSE_FUNC, { func: &funct }, funct_arg, zero_rc, neg_rc, pos_rc }, +#define OUT(pack) \ +{ HILSE_OUT, { packet: pack }, 0, HILSEN_NEXT, HILSEN_DOZE, 0 }, +#define CTS \ +{ HILSE_CTS, { packet: 0 }, 0, HILSEN_NEXT | HILSEN_SCHED | HILSEN_BREAK, HILSEN_DOZE, 0 }, +#define EXPECT(comp, to, got, got_wrong, timed_out) \ +{ HILSE_EXPECT, { packet: comp }, to, got, got_wrong, timed_out }, +#define EXPECT_LAST(comp, to, got, got_wrong, timed_out) \ +{ HILSE_EXPECT_LAST, { packet: comp }, to, got, got_wrong, timed_out }, +#define EXPECT_DISC(comp, to, got, got_wrong, timed_out) \ +{ HILSE_EXPECT_DISC, { packet: comp }, to, got, got_wrong, timed_out }, +#define IN(to, got, got_error, timed_out) \ +{ HILSE_IN, { packet: 0 }, to, got, got_error, timed_out }, +#define OUT_DISC(pack) \ +{ HILSE_OUT_DISC, { packet: pack }, 0, 0, 0, 0 }, +#define OUT_LAST(pack) \ +{ HILSE_OUT_LAST, { packet: pack }, 0, 0, 0, 0 }, + +struct hilse_node hil_mlc_se[HILSEN_END] = { + + /* 0 HILSEN_START */ + FUNC(hilse_init_lcv, 0, HILSEN_NEXT, HILSEN_SLEEP, 0) + + /* 1 HILSEN_RESTART */ + FUNC(hilse_inc_lcv, 10, HILSEN_NEXT, HILSEN_START, 0) + OUT(HIL_CTRL_ONLY) /* Disable APE */ + CTS + +#define TEST_PACKET(x) \ +(HIL_PKT_CMD | (x << HIL_PKT_ADDR_SHIFT) | x << 4 | x) + + OUT(HIL_DO_ALTER_CTRL | HIL_CTRL_TEST | TEST_PACKET(0x5)) + EXPECT(HIL_ERR_INT | TEST_PACKET(0x5), + 2000, HILSEN_NEXT, HILSEN_RESTART, HILSEN_RESTART) + OUT(HIL_DO_ALTER_CTRL | HIL_CTRL_TEST | TEST_PACKET(0xa)) + EXPECT(HIL_ERR_INT | TEST_PACKET(0xa), + 2000, HILSEN_NEXT, HILSEN_RESTART, HILSEN_RESTART) + OUT(HIL_CTRL_ONLY | 0) /* Disable test mode */ + + /* 9 HILSEN_DHR */ + FUNC(hilse_init_lcv, 0, HILSEN_NEXT, HILSEN_SLEEP, 0) + + /* 10 HILSEN_DHR2 */ + FUNC(hilse_inc_lcv, 10, HILSEN_NEXT, HILSEN_START, 0) + FUNC(hilse_set_ddi, -1, HILSEN_NEXT, 0, 0) + OUT(HIL_PKT_CMD | HIL_CMD_DHR) + IN(300000, HILSEN_DHR2, HILSEN_DHR2, HILSEN_NEXT) + + /* 14 HILSEN_IFC */ + OUT(HIL_PKT_CMD | HIL_CMD_IFC) + EXPECT(HIL_PKT_CMD | HIL_CMD_IFC | HIL_ERR_INT, + 20000, HILSEN_DISC, HILSEN_DHR2, HILSEN_NEXT ) + + /* If devices are there, they weren't in PUP or other loopback mode. + * We're more concerned at this point with restoring operation + * to devices than discovering new ones, so we try to salvage + * the loop configuration by closing off the loop. + */ + + /* 16 HILSEN_HEAL0 */ + FUNC(hilse_dec_ddi, 0, HILSEN_NEXT, HILSEN_ACF, 0) + FUNC(hilse_inc_ddi, 0, HILSEN_NEXT, 0, 0) + + /* 18 HILSEN_HEAL */ + OUT_LAST(HIL_CMD_ELB) + EXPECT_LAST(HIL_CMD_ELB | HIL_ERR_INT, + 20000, HILSEN_REPOLL, HILSEN_DSR, HILSEN_NEXT) + FUNC(hilse_dec_ddi, 0, HILSEN_HEAL, HILSEN_NEXT, 0) + + /* 21 HILSEN_ACF */ + FUNC(hilse_init_lcv, 0, HILSEN_NEXT, HILSEN_DOZE, 0) + + /* 22 HILSEN_ACF2 */ + FUNC(hilse_inc_lcv, 10, HILSEN_NEXT, HILSEN_START, 0) + OUT(HIL_PKT_CMD | HIL_CMD_ACF | 1) + IN(20000, HILSEN_NEXT, HILSEN_DSR, HILSEN_NEXT) + + /* 25 HILSEN_DISC0 */ + OUT_DISC(HIL_PKT_CMD | HIL_CMD_ELB) + EXPECT_DISC(HIL_PKT_CMD | HIL_CMD_ELB | HIL_ERR_INT, + 20000, HILSEN_NEXT, HILSEN_DSR, HILSEN_DSR) + + /* Only enter here if response just received */ + /* 27 HILSEN_DISC */ + OUT_DISC(HIL_PKT_CMD | HIL_CMD_IDD) + EXPECT_DISC(HIL_PKT_CMD | HIL_CMD_IDD | HIL_ERR_INT, + 20000, HILSEN_NEXT, HILSEN_DSR, HILSEN_START) + FUNC(hilse_inc_ddi, 0, HILSEN_NEXT, HILSEN_START, 0) + FUNC(hilse_take_idd, 0, HILSEN_MATCH, HILSEN_IFCACF, HILSEN_FOLLOW) + OUT_LAST(HIL_PKT_CMD | HIL_CMD_RSC) + EXPECT_LAST(HIL_PKT_CMD | HIL_CMD_RSC | HIL_ERR_INT, + 30000, HILSEN_NEXT, HILSEN_DSR, HILSEN_DSR) + FUNC(hilse_take_rsc, 0, HILSEN_MATCH, 0, HILSEN_FOLLOW) + OUT_LAST(HIL_PKT_CMD | HIL_CMD_EXD) + EXPECT_LAST(HIL_PKT_CMD | HIL_CMD_EXD | HIL_ERR_INT, + 30000, HILSEN_NEXT, HILSEN_DSR, HILSEN_DSR) + FUNC(hilse_take_exd, 0, HILSEN_MATCH, 0, HILSEN_FOLLOW) + OUT_LAST(HIL_PKT_CMD | HIL_CMD_RNM) + EXPECT_LAST(HIL_PKT_CMD | HIL_CMD_RNM | HIL_ERR_INT, + 30000, HILSEN_NEXT, HILSEN_DSR, HILSEN_DSR) + FUNC(hilse_take_rnm, 0, HILSEN_MATCH, 0, 0) + + /* 40 HILSEN_MATCH */ + FUNC(hilse_match, 0, HILSEN_NEXT, HILSEN_NEXT, /* TODO */ 0) + + /* 41 HILSEN_OPERATE */ + OUT(HIL_PKT_CMD | HIL_CMD_POL) + EXPECT(HIL_PKT_CMD | HIL_CMD_POL | HIL_ERR_INT, + 20000, HILSEN_NEXT, HILSEN_DSR, HILSEN_NEXT) + FUNC(hilse_operate, 0, HILSEN_OPERATE, HILSEN_IFC, HILSEN_NEXT) + + /* 44 HILSEN_PROBE */ + OUT_LAST(HIL_PKT_CMD | HIL_CMD_EPT) + IN(10000, HILSEN_DISC, HILSEN_DSR, HILSEN_NEXT) + OUT_DISC(HIL_PKT_CMD | HIL_CMD_ELB) + IN(10000, HILSEN_DISC, HILSEN_DSR, HILSEN_NEXT) + OUT(HIL_PKT_CMD | HIL_CMD_ACF | 1) + IN(10000, HILSEN_DISC0, HILSEN_DSR, HILSEN_NEXT) + OUT_LAST(HIL_PKT_CMD | HIL_CMD_ELB) + IN(10000, HILSEN_OPERATE, HILSEN_DSR, HILSEN_DSR) + + /* 52 HILSEN_DSR */ + FUNC(hilse_set_ddi, -1, HILSEN_NEXT, 0, 0) + OUT(HIL_PKT_CMD | HIL_CMD_DSR) + IN(20000, HILSEN_DHR, HILSEN_DHR, HILSEN_IFC) + + /* 55 HILSEN_REPOLL */ + OUT(HIL_PKT_CMD | HIL_CMD_RPL) + EXPECT(HIL_PKT_CMD | HIL_CMD_RPL | HIL_ERR_INT, + 20000, HILSEN_NEXT, HILSEN_DSR, HILSEN_NEXT) + FUNC(hilse_operate, 1, HILSEN_OPERATE, HILSEN_IFC, HILSEN_PROBE) + + /* 58 HILSEN_IFCACF */ + OUT(HIL_PKT_CMD | HIL_CMD_IFC) + EXPECT(HIL_PKT_CMD | HIL_CMD_IFC | HIL_ERR_INT, + 20000, HILSEN_ACF2, HILSEN_DHR2, HILSEN_HEAL) + + /* 60 HILSEN_END */ +}; + +static inline void hilse_setup_input(hil_mlc *mlc, struct hilse_node *node) { + + switch (node->act) { + case HILSE_EXPECT_DISC: + mlc->imatch = node->object.packet; + mlc->imatch |= ((mlc->ddi + 2) << HIL_PKT_ADDR_SHIFT); + break; + case HILSE_EXPECT_LAST: + mlc->imatch = node->object.packet; + mlc->imatch |= ((mlc->ddi + 1) << HIL_PKT_ADDR_SHIFT); + break; + case HILSE_EXPECT: + mlc->imatch = node->object.packet; + break; + case HILSE_IN: + mlc->imatch = 0; + break; + default: + BUG(); + } + mlc->istarted = 1; + mlc->intimeout = node->arg; + do_gettimeofday(&(mlc->instart)); + mlc->icount = 15; + memset(mlc->ipacket, 0, 16 * sizeof(hil_packet)); + if (down_trylock(&(mlc->isem))) BUG(); + + return; +} + +#ifdef HIL_MLC_DEBUG +static int doze = 0; +static int seidx; /* For debug */ +static int kick = 1; +#endif + +static int hilse_donode (hil_mlc *mlc) { + struct hilse_node *node; + int nextidx = 0; + int sched_long = 0; + unsigned long flags; + +#ifdef HIL_MLC_DEBUG + if (mlc->seidx && (mlc->seidx != seidx) && mlc->seidx != 41 && mlc->seidx != 42 && mlc->seidx != 43) { + printk(KERN_DEBUG PREFIX "z%i \n%s {%i}", doze, kick ? "K" : "", mlc->seidx); + doze = 0; + } + kick = 0; + + seidx = mlc->seidx; +#endif + node = hil_mlc_se + mlc->seidx; + + switch (node->act) { + int rc; + hil_packet pack; + + case HILSE_FUNC: + if (node->object.func == NULL) break; + rc = node->object.func(mlc, node->arg); + nextidx = (rc > 0) ? node->ugly : + ((rc < 0) ? node->bad : node->good); + if (nextidx == HILSEN_FOLLOW) nextidx = rc; + break; + case HILSE_EXPECT_LAST: + case HILSE_EXPECT_DISC: + case HILSE_EXPECT: + case HILSE_IN: + /* Already set up from previous HILSE_OUT_* */ + write_lock_irqsave(&(mlc->lock), flags); + rc = mlc->in(mlc, node->arg); + if (rc == 2) { + nextidx = HILSEN_DOZE; + sched_long = 1; + write_unlock_irqrestore(&(mlc->lock), flags); + break; + } + if (rc == 1) nextidx = node->ugly; + else if (rc == 0) nextidx = node->good; + else nextidx = node->bad; + mlc->istarted = 0; + write_unlock_irqrestore(&(mlc->lock), flags); + break; + case HILSE_OUT_LAST: + write_lock_irqsave(&(mlc->lock), flags); + pack = node->object.packet; + pack |= ((mlc->ddi + 1) << HIL_PKT_ADDR_SHIFT); + goto out; + case HILSE_OUT_DISC: + write_lock_irqsave(&(mlc->lock), flags); + pack = node->object.packet; + pack |= ((mlc->ddi + 2) << HIL_PKT_ADDR_SHIFT); + goto out; + case HILSE_OUT: + write_lock_irqsave(&(mlc->lock), flags); + pack = node->object.packet; + out: + if (mlc->istarted) goto out2; + /* Prepare to receive input */ + if ((node + 1)->act & HILSE_IN) + hilse_setup_input(mlc, node + 1); + + out2: + write_unlock_irqrestore(&(mlc->lock), flags); + + if (down_trylock(&mlc->osem)) { + nextidx = HILSEN_DOZE; + break; + } + up(&mlc->osem); + + write_lock_irqsave(&(mlc->lock), flags); + if (!(mlc->ostarted)) { + mlc->ostarted = 1; + mlc->opacket = pack; + mlc->out(mlc); + nextidx = HILSEN_DOZE; + write_unlock_irqrestore(&(mlc->lock), flags); + break; + } + mlc->ostarted = 0; + do_gettimeofday(&(mlc->instart)); + write_unlock_irqrestore(&(mlc->lock), flags); + nextidx = HILSEN_NEXT; + break; + case HILSE_CTS: + nextidx = mlc->cts(mlc) ? node->bad : node->good; + break; + default: + BUG(); + nextidx = 0; + break; + } + +#ifdef HIL_MLC_DEBUG + if (nextidx == HILSEN_DOZE) doze++; +#endif + + while (nextidx & HILSEN_SCHED) { + struct timeval tv; + + if (!sched_long) goto sched; + + do_gettimeofday(&tv); + tv.tv_usec += 1000000 * (tv.tv_sec - mlc->instart.tv_sec); + tv.tv_usec -= mlc->instart.tv_usec; + if (tv.tv_usec >= mlc->intimeout) goto sched; + tv.tv_usec = (mlc->intimeout - tv.tv_usec) * HZ / 1000000; + if (!tv.tv_usec) goto sched; + mod_timer(&hil_mlcs_kicker, jiffies + tv.tv_usec); + break; + sched: + tasklet_schedule(&hil_mlcs_tasklet); + break; + } + if (nextidx & HILSEN_DOWN) mlc->seidx += nextidx & HILSEN_MASK; + else if (nextidx & HILSEN_UP) mlc->seidx -= nextidx & HILSEN_MASK; + else mlc->seidx = nextidx & HILSEN_MASK; + + if (nextidx & HILSEN_BREAK) return 1; + return 0; +} + +/******************** tasklet context functions **************************/ +static void hil_mlcs_process(unsigned long unused) { + struct list_head *tmp; + + read_lock(&hil_mlcs_lock); + list_for_each(tmp, &hil_mlcs) { + struct hil_mlc *mlc = list_entry(tmp, hil_mlc, list); + while (hilse_donode(mlc) == 0) { +#ifdef HIL_MLC_DEBUG + if (mlc->seidx != 41 && + mlc->seidx != 42 && + mlc->seidx != 43) + printk(KERN_DEBUG PREFIX " + "); +#endif + }; + } + read_unlock(&hil_mlcs_lock); +} + +/************************* Keepalive timer task *********************/ + +void hil_mlcs_timer (unsigned long data) { + hil_mlcs_probe = 1; + tasklet_schedule(&hil_mlcs_tasklet); + /* Re-insert the periodic task. */ + if (!timer_pending(&hil_mlcs_kicker)) + mod_timer(&hil_mlcs_kicker, jiffies + HZ); +} + +/******************** user/kernel context functions **********************/ + +static int hil_mlc_serio_write(struct serio *serio, unsigned char c) { + struct hil_mlc_serio_map *map; + struct hil_mlc *mlc; + struct serio_dev *dev; + uint8_t *idx, *last; + + map = serio->driver; + if (map == NULL) { + BUG(); + return -EIO; + } + mlc = map->mlc; + if (mlc == NULL) { + BUG(); + return -EIO; + } + mlc->serio_opacket[map->didx] |= + ((hil_packet)c) << (8 * (3 - mlc->serio_oidx[map->didx])); + + if (mlc->serio_oidx[map->didx] >= 3) { + /* for now only commands */ + if (!(mlc->serio_opacket[map->didx] & HIL_PKT_CMD)) + return -EIO; + switch (mlc->serio_opacket[map->didx] & HIL_PKT_DATA_MASK) { + case HIL_CMD_IDD: + idx = mlc->di[map->didx].idd; + goto emu; + case HIL_CMD_RSC: + idx = mlc->di[map->didx].rsc; + goto emu; + case HIL_CMD_EXD: + idx = mlc->di[map->didx].exd; + goto emu; + case HIL_CMD_RNM: + idx = mlc->di[map->didx].rnm; + goto emu; + default: + break; + } + mlc->serio_oidx[map->didx] = 0; + mlc->serio_opacket[map->didx] = 0; + } + + mlc->serio_oidx[map->didx]++; + return -EIO; + emu: + dev = serio->dev; + if (dev == NULL) { + BUG(); + return -EIO; + } + last = idx + 15; + while ((last != idx) && (*last == 0)) last--; + + while (idx != last) { + dev->interrupt(serio, 0, 0); + dev->interrupt(serio, HIL_ERR_INT >> 16, 0); + dev->interrupt(serio, 0, 0); + dev->interrupt(serio, *idx, 0); + idx++; + } + dev->interrupt(serio, 0, 0); + dev->interrupt(serio, HIL_ERR_INT >> 16, 0); + dev->interrupt(serio, HIL_PKT_CMD >> 8, 0); + dev->interrupt(serio, *idx, 0); + + mlc->serio_oidx[map->didx] = 0; + mlc->serio_opacket[map->didx] = 0; + + return 0; +} + +static int hil_mlc_serio_open(struct serio *serio) { + struct hil_mlc_serio_map *map; + struct hil_mlc *mlc; + + if (serio->private != NULL) return -EBUSY; + + map = serio->driver; + if (map == NULL) { + BUG(); + return -ENODEV; + } + mlc = map->mlc; + if (mlc == NULL) { + BUG(); + return -ENODEV; + } + + mlc->inc_use_count(); + + return 0; +} + +static void hil_mlc_serio_close(struct serio *serio) { + struct hil_mlc_serio_map *map; + struct hil_mlc *mlc; + + map = serio->driver; + if (map == NULL) { + BUG(); + return; + } + mlc = map->mlc; + if (mlc == NULL) { + BUG(); + return; + } + + mlc->dec_use_count(); + + serio->private = NULL; + serio->dev = NULL; + /* TODO wake up interruptable */ +} + +int hil_mlc_register(hil_mlc *mlc) { + int i; + unsigned long flags; + + MOD_INC_USE_COUNT; + if (mlc == NULL) { + MOD_DEC_USE_COUNT; + return -EINVAL; + } + + mlc->istarted = 0; + mlc->ostarted = 0; + + mlc->lock = RW_LOCK_UNLOCKED; + init_MUTEX(&(mlc->osem)); + + init_MUTEX(&(mlc->isem)); + mlc->icount = -1; + mlc->imatch = 0; + + mlc->opercnt = 0; + + init_MUTEX_LOCKED(&(mlc->csem)); + + hil_mlc_clear_di_scratch(mlc); + hil_mlc_clear_di_map(mlc, 0); + for (i = 0; i < HIL_MLC_DEVMEM; i++) { + hil_mlc_copy_di_scratch(mlc, i); + memset(&(mlc->serio[i]), 0, sizeof(mlc->serio[0])); + mlc->serio[i].type = SERIO_HIL | SERIO_HIL_MLC; + mlc->serio[i].write = hil_mlc_serio_write; + mlc->serio[i].open = hil_mlc_serio_open; + mlc->serio[i].close = hil_mlc_serio_close; + mlc->serio[i].driver = &(mlc->serio_map[i]); + mlc->serio_map[i].mlc = mlc; + mlc->serio_map[i].didx = i; + mlc->serio_map[i].di_revmap = -1; + mlc->serio_opacket[i] = 0; + mlc->serio_oidx[i] = 0; + serio_register_port(&(mlc->serio[i])); + } + + mlc->tasklet = &hil_mlcs_tasklet; + + write_lock_irqsave(&hil_mlcs_lock, flags); + list_add_tail(&mlc->list, &hil_mlcs); + mlc->seidx = HILSEN_START; + write_unlock_irqrestore(&hil_mlcs_lock, flags); + + tasklet_schedule(&hil_mlcs_tasklet); + return 0; +} + +int hil_mlc_unregister(hil_mlc *mlc) { + struct list_head *tmp; + unsigned long flags; + int i; + + if (mlc == NULL) + return -EINVAL; + + write_lock_irqsave(&hil_mlcs_lock, flags); + list_for_each(tmp, &hil_mlcs) { + if (list_entry(tmp, hil_mlc, list) == mlc) + goto found; + } + + /* not found in list */ + write_unlock_irqrestore(&hil_mlcs_lock, flags); + tasklet_schedule(&hil_mlcs_tasklet); + return -ENODEV; + + found: + list_del(tmp); + write_unlock_irqrestore(&hil_mlcs_lock, flags); + MOD_DEC_USE_COUNT; + + for (i = 0; i < HIL_MLC_DEVMEM; i++) + serio_unregister_port(&(mlc->serio[i])); + + tasklet_schedule(&hil_mlcs_tasklet); + return 0; +} + +/**************************** Module interface *************************/ + +static int __init hil_mlc_init(void) +{ + init_timer(&hil_mlcs_kicker); + hil_mlcs_kicker.expires = jiffies + HZ; + hil_mlcs_kicker.function = &hil_mlcs_timer; + add_timer(&hil_mlcs_kicker); + + tasklet_enable(&hil_mlcs_tasklet); + + return 0; +} + +static void __exit hil_mlc_exit(void) +{ + del_timer(&hil_mlcs_kicker); + + tasklet_disable(&hil_mlcs_tasklet); + tasklet_kill(&hil_mlcs_tasklet); +} + +module_init(hil_mlc_init); +module_exit(hil_mlc_exit); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/hil/hil_ptr.c linux.19rc3-ac4/drivers/hil/hil_ptr.c --- linux.19rc3/drivers/hil/hil_ptr.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/hil/hil_ptr.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,406 @@ +/* + * Generic linux-input device driver for axis-bearing devices + * + * Copyright (c) 2001 Brian S. Julin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL"). + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * + * References: + * HP-HIL Technical Reference Manual. Hewlett Packard Product No. 45918A + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#define PREFIX "HIL PTR: " +#define HIL_GENERIC_NAME "generic HIL pointer device" + +MODULE_AUTHOR("Brian S. Julin "); +MODULE_DESCRIPTION(HIL_GENERIC_NAME " driver"); +MODULE_LICENSE("Dual BSD/GPL"); + + +#define TABLET_SIMULATES_MOUSE /* allow tablet to be used as mouse */ +#undef TABLET_AUTOADJUST /* auto-adjust valid tablet ranges */ + + +#define HIL_PTR_MAX_LENGTH 16 + +struct hil_ptr { + struct input_dev dev; + struct serio *serio; + + /* Input buffer and index for packets from HIL bus. */ + hil_packet data[HIL_PTR_MAX_LENGTH]; + int idx4; /* four counts per packet */ + + /* Raw device info records from HIL bus, see hil.h for fields. */ + char idd[HIL_PTR_MAX_LENGTH]; /* DID byte and IDD record */ + char rsc[HIL_PTR_MAX_LENGTH]; /* RSC record */ + char exd[HIL_PTR_MAX_LENGTH]; /* EXD record */ + char rnm[HIL_PTR_MAX_LENGTH + 1]; /* RNM record + NULL term. */ + + /* Extra device details not contained in struct input_dev. */ + unsigned int nbtn, naxes; + unsigned int btnmap[7]; + + /* Something to sleep around with. */ + struct semaphore sem; +}; + +/* Process a complete packet after transfer from the HIL */ +static void hil_ptr_process_record(struct hil_ptr *ptr) +{ + struct input_dev *dev = &ptr->dev; + hil_packet *data = ptr->data; + hil_packet p; + int idx, i, cnt, laxis; + int ax16, absdev; + + idx = ptr->idx4/4; + p = data[idx - 1]; + + if ((p & ~HIL_CMDCT_POL) == + (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) goto report; + if ((p & ~HIL_CMDCT_RPL) == + (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) goto report; + + /* Not a poll response. See if we are loading config records. */ + switch (p & HIL_PKT_DATA_MASK) { + case HIL_CMD_IDD: + for (i = 0; i < idx; i++) + ptr->idd[i] = ptr->data[i] & HIL_PKT_DATA_MASK; + for (; i < HIL_PTR_MAX_LENGTH; i++) + ptr->idd[i] = 0; + break; + case HIL_CMD_RSC: + for (i = 0; i < idx; i++) + ptr->rsc[i] = ptr->data[i] & HIL_PKT_DATA_MASK; + for (; i < HIL_PTR_MAX_LENGTH; i++) + ptr->rsc[i] = 0; + break; + case HIL_CMD_EXD: + for (i = 0; i < idx; i++) + ptr->exd[i] = ptr->data[i] & HIL_PKT_DATA_MASK; + for (; i < HIL_PTR_MAX_LENGTH; i++) + ptr->exd[i] = 0; + break; + case HIL_CMD_RNM: + for (i = 0; i < idx; i++) + ptr->rnm[i] = ptr->data[i] & HIL_PKT_DATA_MASK; + for (; i < HIL_PTR_MAX_LENGTH + 1; i++) + ptr->rnm[i] = '\0'; + break; + default: + /* These occur when device isn't present */ + if (p == (HIL_ERR_INT | HIL_PKT_CMD)) break; + /* Anything else we'd like to know about. */ + printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p); + break; + } + goto out; + + report: + if ((p & HIL_CMDCT_POL) != idx - 1) { + printk(KERN_WARNING PREFIX "Malformed poll packet %x (idx = %i)\n", p, idx); + goto out; + } + + i = (ptr->data[0] & HIL_POL_AXIS_ALT) ? 3 : 0; + laxis = ptr->data[0] & HIL_POL_NUM_AXES_MASK; + laxis += i; + + ax16 = ptr->idd[1] & HIL_IDD_HEADER_16BIT; /* 8 or 16bit resolution */ + absdev = ptr->idd[1] & HIL_IDD_HEADER_ABS; + + for (cnt = 1; i < laxis; i++) { + unsigned int lo,hi,val; + lo = ptr->data[cnt++] & HIL_PKT_DATA_MASK; + hi = ax16 ? (ptr->data[cnt++] & HIL_PKT_DATA_MASK) : 0; + if (absdev) { + val = lo + (hi<<8); +#ifdef TABLET_AUTOADJUST + if (val < ptr->dev.absmin[ABS_X + i]) + ptr->dev.absmin[ABS_X + i] = val; + if (val > ptr->dev.absmax[ABS_X + i]) + ptr->dev.absmax[ABS_X + i] = val; +#endif + if (i%3) val = ptr->dev.absmax[ABS_X + i] - val; + input_report_abs(dev, ABS_X + i, val); + } else { + val = (int) (((int8_t)lo) | ((int8_t)hi<<8)); + if (i%3) val *= -1; + input_report_rel(dev, REL_X + i, val); + } + } + + while (cnt < idx - 1) { + unsigned int btn; + int up; + btn = ptr->data[cnt++]; + up = btn & 1; + btn &= 0xfe; + if (btn == 0x8e) { + continue; /* TODO: proximity == touch? */ + } + else if ((btn > 0x8c) || (btn < 0x80)) continue; + btn = (btn - 0x80) >> 1; + btn = ptr->btnmap[btn]; + input_report_key(dev, btn, !up); + } + out: + ptr->idx4 = 0; + up(&ptr->sem); +} + +static void hil_ptr_process_err(struct hil_ptr *ptr) { + printk(KERN_WARNING PREFIX "errored HIL packet\n"); + ptr->idx4 = 0; + up(&ptr->sem); + return; +} + +static void hil_ptr_interrupt(struct serio *serio, + unsigned char data, + unsigned int flags) +{ + struct hil_ptr *ptr; + hil_packet packet; + int idx; + + ptr = (struct hil_ptr *)serio->private; + if (ptr == NULL) { + BUG(); + return; + } + + if (ptr->idx4 >= (HIL_PTR_MAX_LENGTH * sizeof(hil_packet))) { + hil_ptr_process_err(ptr); + return; + } + idx = ptr->idx4/4; + if (!(ptr->idx4 % 4)) ptr->data[idx] = 0; + packet = ptr->data[idx]; + packet |= ((hil_packet)data) << ((3 - (ptr->idx4 % 4)) * 8); + ptr->data[idx] = packet; + + /* Records of N 4-byte hil_packets must terminate with a command. */ + if ((++(ptr->idx4)) % 4) return; + if ((packet & 0xffff0000) != HIL_ERR_INT) { + hil_ptr_process_err(ptr); + return; + } + if (packet & HIL_PKT_CMD) + hil_ptr_process_record(ptr); +} + +static void hil_ptr_disconnect(struct serio *serio) +{ + struct hil_ptr *ptr; + + ptr = (struct hil_ptr *)serio->private; + if (ptr == NULL) { + BUG(); + return; + } + + input_unregister_device(&ptr->dev); + serio_close(serio); + kfree(ptr); +} + +static void hil_ptr_connect(struct serio *serio, struct serio_dev *dev) +{ + struct hil_ptr *ptr; + char *txt; + unsigned int i, naxsets, btntype; + uint8_t did, *idd; + + if (serio->type != (SERIO_HIL_MLC | SERIO_HIL)) return; + + if (!(ptr = kmalloc(sizeof(struct hil_ptr), GFP_KERNEL))) return; + memset(ptr, 0, sizeof(struct hil_ptr)); + + if (serio_open(serio, dev)) goto bail0; + + serio->private = ptr; + ptr->serio = serio; + ptr->dev.private = ptr; + + init_MUTEX_LOCKED(&(ptr->sem)); + + /* Get device info. MLC driver supplies devid/status/etc. */ + serio->write(serio, 0); + serio->write(serio, 0); + serio->write(serio, HIL_PKT_CMD >> 8); + serio->write(serio, HIL_CMD_IDD); + down(&(ptr->sem)); + + serio->write(serio, 0); + serio->write(serio, 0); + serio->write(serio, HIL_PKT_CMD >> 8); + serio->write(serio, HIL_CMD_RSC); + down(&(ptr->sem)); + + serio->write(serio, 0); + serio->write(serio, 0); + serio->write(serio, HIL_PKT_CMD >> 8); + serio->write(serio, HIL_CMD_RNM); + down(&(ptr->sem)); + + serio->write(serio, 0); + serio->write(serio, 0); + serio->write(serio, HIL_PKT_CMD >> 8); + serio->write(serio, HIL_CMD_EXD); + down(&(ptr->sem)); + + up(&(ptr->sem)); + + did = ptr->idd[0]; + idd = ptr->idd + 1; + txt = "unknown"; + if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) { + ptr->dev.evbit[0] = BIT(EV_REL); + txt = "relative"; + } + + if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_ABS) { + ptr->dev.evbit[0] = BIT(EV_ABS); + txt = "absolute"; + } + if (!ptr->dev.evbit[0]) { + goto bail1; + } + + ptr->nbtn = HIL_IDD_NUM_BUTTONS(idd); + if (ptr->nbtn) ptr->dev.evbit[0] |= BIT(EV_KEY); + + naxsets = HIL_IDD_NUM_AXSETS(*idd); + ptr->naxes = HIL_IDD_NUM_AXES_PER_SET(*idd); + + printk(KERN_INFO PREFIX "HIL pointer device found (did: 0x%02x, axis: %s)\n", + did, txt); + printk(KERN_INFO PREFIX "HIL pointer has %i buttons and %i sets of %i axes\n", + ptr->nbtn, naxsets, ptr->naxes); + + btntype = BTN_MISC; + if ((did & HIL_IDD_DID_ABS_TABLET_MASK) == HIL_IDD_DID_ABS_TABLET) +#ifdef TABLET_SIMULATES_MOUSE + btntype = BTN_TOUCH; +#else + btntype = BTN_DIGI; +#endif + if ((did & HIL_IDD_DID_ABS_TSCREEN_MASK) == HIL_IDD_DID_ABS_TSCREEN) + btntype = BTN_TOUCH; + + if ((did & HIL_IDD_DID_REL_MOUSE_MASK) == HIL_IDD_DID_REL_MOUSE) + btntype = BTN_MOUSE; + + for (i = 0; i < ptr->nbtn; i++) { + set_bit(btntype | i, ptr->dev.keybit); + ptr->btnmap[i] = btntype | i; + } + + if (btntype == BTN_MOUSE) { + /* Swap buttons 2 and 3 */ + ptr->btnmap[1] = BTN_MIDDLE; + ptr->btnmap[2] = BTN_RIGHT; + } + + if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) { + for (i = 0; i < ptr->naxes; i++) { + set_bit(REL_X + i, ptr->dev.relbit); + } + for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) { + set_bit(REL_X + i, ptr->dev.relbit); + } + } else { + for (i = 0; i < ptr->naxes; i++) { + set_bit(ABS_X + i, ptr->dev.absbit); + ptr->dev.absmin[ABS_X + i] = 0; + ptr->dev.absmax[ABS_X + i] = + HIL_IDD_AXIS_MAX((ptr->idd + 1), i); + } + for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) { + set_bit(ABS_X + i, ptr->dev.absbit); + ptr->dev.absmin[ABS_X + i] = 0; + ptr->dev.absmax[ABS_X + i] = + HIL_IDD_AXIS_MAX((ptr->idd + 1), (i - 3)); + } +#ifdef TABLET_AUTOADJUST + for (i = 0; i < ABS_MAX; i++) { + int diff = ptr->dev.absmax[ABS_X + i] / 10; + ptr->dev.absmin[ABS_X + i] += diff; + ptr->dev.absmax[ABS_X + i] -= diff; + } +#endif + } + + ptr->dev.name = strlen(ptr->rnm) ? ptr->rnm : HIL_GENERIC_NAME; + + ptr->dev.idbus = BUS_HIL; + ptr->dev.idvendor = SERIO_HIL; + ptr->dev.idproduct = 0x0001; /* TODO: get from ptr->rsc */ + ptr->dev.idversion = 0x0100; /* TODO: get from ptr->rsc */ + + input_register_device(&ptr->dev); + printk(KERN_INFO "input%d: %s on hil%d\n", + ptr->dev.number, + (btntype == BTN_MOUSE) ? "HIL mouse":"HIL tablet or touchpad", + 0); + + return; + bail1: + serio_close(serio); + bail0: + kfree(ptr); + return; +} + + +struct serio_dev hil_ptr_serio_dev = { + connect: hil_ptr_connect, + disconnect: hil_ptr_disconnect, + interrupt: hil_ptr_interrupt +}; + +static int __init hil_ptr_init(void) +{ + serio_register_device(&hil_ptr_serio_dev); + return 0; +} + +static void __exit hil_ptr_exit(void) +{ + serio_unregister_device(&hil_ptr_serio_dev); +} + +module_init(hil_ptr_init); +module_exit(hil_ptr_exit); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/hil/hp_sdc.c linux.19rc3-ac4/drivers/hil/hp_sdc.c --- linux.19rc3/drivers/hil/hp_sdc.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/hil/hp_sdc.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,1012 @@ +/* + * HP i8042-based System Device Controller driver. + * + * Copyright (c) 2001 Brian S. Julin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL"). + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * + * References: + * System Device Controller Microprocessor Firmware Theory of Operation + * for Part Number 1820-4784 Revision B. Dwg No. A-1820-4784-2 + * Helge Deller's original hilkbd.c port for PA-RISC. + * + * + * Driver theory of operation: + * + * hp_sdc_put does all writing to the SDC. ISR can run on a different + * CPU than hp_sdc_put, but only one CPU runs hp_sdc_put at a time + * (it cannot really benefit from SMP anyway.) A tasket fit this perfectly. + * + * All data coming back from the SDC is sent via interrupt and can be read + * fully in the ISR, so there are no latency/throughput problems there. + * The problem is with output, due to the slow clock speed of the SDC + * compared to the CPU. This should not be too horrible most of the time, + * but if used with HIL devices that support the multibyte transfer command, + * keeping outbound throughput flowing at the 6500KBps that the HIL is + * capable of is more than can be done at HZ=100. + * + * Busy polling for IBF clear wastes CPU cycles and bus cycles. hp_sdc.ibf + * is set to 0 when the IBF flag in the status register has cleared. ISR + * may do this, and may also access the parts of queued transactions related + * to reading data back from the SDC, but otherwise will not touch the + * hp_sdc state. Whenever a register is written hp_sdc.ibf is set to 1. + * + * The i8042 write index and the values in the 4-byte input buffer + * starting at 0x70 are kept track of in hp_sdc.wi, and .r7[], respectively, + * to minimize the amount of IO needed to the SDC. However these values + * do not need to be locked since they are only ever accessed by hp_sdc_put. + * + * A timer task schedules the tasklet once per second just to make + * sure it doesn't freeze up and to allow for bad reads to time out. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define PREFIX "HP SDC: " + +MODULE_AUTHOR("Brian S. Julin "); +MODULE_DESCRIPTION("HP i8042-based SDC Driver"); +MODULE_LICENSE("Dual BSD/GPL"); + +EXPORT_SYMBOL(hp_sdc_request_timer_irq); +EXPORT_SYMBOL(hp_sdc_request_hil_irq); +EXPORT_SYMBOL(hp_sdc_request_cooked_irq); + +EXPORT_SYMBOL(hp_sdc_release_timer_irq); +EXPORT_SYMBOL(hp_sdc_release_hil_irq); +EXPORT_SYMBOL(hp_sdc_release_cooked_irq); + +EXPORT_SYMBOL(hp_sdc_enqueue_transaction); +EXPORT_SYMBOL(hp_sdc_dequeue_transaction); + +static hp_i8042_sdc hp_sdc; /* All driver state is kept in here. */ + +/*************** primitives for use in any context *********************/ +static inline uint8_t hp_sdc_status_in8 (void) { + uint8_t status; + unsigned long flags; + + write_lock_irqsave(&hp_sdc.ibf_lock, flags); + status = gsc_readb(hp_sdc.status_io); + if (!(status & HP_SDC_STATUS_IBF)) hp_sdc.ibf = 0; + write_unlock_irqrestore(&hp_sdc.ibf_lock, flags); + + return status; +} + +static inline uint8_t hp_sdc_data_in8 (void) { + return gsc_readb(hp_sdc.data_io); +} + +static inline void hp_sdc_status_out8 (uint8_t val) { + unsigned long flags; + + write_lock_irqsave(&hp_sdc.ibf_lock, flags); + hp_sdc.ibf = 1; + if ((val & 0xf0) == 0xe0) hp_sdc.wi = 0xff; + gsc_writeb(val, hp_sdc.status_io); + write_unlock_irqrestore(&hp_sdc.ibf_lock, flags); +} + +static inline void hp_sdc_data_out8 (uint8_t val) { + unsigned long flags; + + write_lock_irqsave(&hp_sdc.ibf_lock, flags); + hp_sdc.ibf = 1; + gsc_writeb(val, hp_sdc.data_io); + write_unlock_irqrestore(&hp_sdc.ibf_lock, flags); +} + +/* Care must be taken to only invoke hp_sdc_spin_ibf when + * absolutely needed, or in rarely invoked subroutines. + * Not only does it waste CPU cycles, it also wastes bus cycles. + */ +static inline void hp_sdc_spin_ibf(void) { + unsigned long flags; + rwlock_t *lock; + + lock = &hp_sdc.ibf_lock; + + read_lock_irqsave(lock, flags); + if (!hp_sdc.ibf) { + read_unlock_irqrestore(lock, flags); + return; + } + read_unlock(lock); + write_lock(lock); + while (gsc_readb(hp_sdc.status_io) & HP_SDC_STATUS_IBF) {}; + hp_sdc.ibf = 0; + write_unlock_irqrestore(lock, flags); +} + + +/************************ Interrupt context functions ************************/ +static void hp_sdc_take (int irq, void *dev_id, uint8_t status, uint8_t data) { + hp_sdc_transaction *curr; + + read_lock(&hp_sdc.rtq_lock); + if (hp_sdc.rcurr < 0) { + read_unlock(&hp_sdc.rtq_lock); + return; + } + curr = hp_sdc.tq[hp_sdc.rcurr]; + read_unlock(&hp_sdc.rtq_lock); + + curr->seq[curr->idx++] = status; + curr->seq[curr->idx++] = data; + hp_sdc.rqty -= 2; + do_gettimeofday(&hp_sdc.rtv); + + if (hp_sdc.rqty <= 0) { + /* All data has been gathered. */ + if(curr->seq[curr->actidx] & HP_SDC_ACT_SEMAPHORE) { + if (curr->act.semaphore) up(curr->act.semaphore); + } + if(curr->seq[curr->actidx] & HP_SDC_ACT_CALLBACK) { + if (curr->act.irqhook) + curr->act.irqhook(irq, dev_id, status, data); + } + curr->actidx = curr->idx; + curr->idx++; + /* Return control of this transaction */ + write_lock(&hp_sdc.rtq_lock); + hp_sdc.rcurr = -1; + hp_sdc.rqty = 0; + write_unlock(&hp_sdc.rtq_lock); + tasklet_schedule(&hp_sdc.task); + } +} + +static void hp_sdc_isr(int irq, void *dev_id, struct pt_regs * regs) { + uint8_t status, data; + + status = hp_sdc_status_in8(); + /* Read data unconditionally to advance i8042. */ + data = hp_sdc_data_in8(); + + /* For now we are ignoring these until we get the SDC to behave. */ + if (((status & 0xf1) == 0x51) && data == 0x82) { + return; + } + + switch(status & HP_SDC_STATUS_IRQMASK) { + case 0: /* This case is not documented. */ + break; + case HP_SDC_STATUS_USERTIMER: + case HP_SDC_STATUS_PERIODIC: + case HP_SDC_STATUS_TIMER: + read_lock(&hp_sdc.hook_lock); + if (hp_sdc.timer != NULL) + hp_sdc.timer(irq, dev_id, status, data); + read_unlock(&hp_sdc.hook_lock); + break; + case HP_SDC_STATUS_REG: + hp_sdc_take(irq, dev_id, status, data); + break; + case HP_SDC_STATUS_HILCMD: + case HP_SDC_STATUS_HILDATA: + read_lock(&hp_sdc.hook_lock); + if (hp_sdc.hil != NULL) + hp_sdc.hil(irq, dev_id, status, data); + read_unlock(&hp_sdc.hook_lock); + break; + case HP_SDC_STATUS_PUP: + read_lock(&hp_sdc.hook_lock); + if (hp_sdc.pup != NULL) + hp_sdc.pup(irq, dev_id, status, data); + else printk(KERN_INFO PREFIX "HP SDC reports successful PUP.\n"); + read_unlock(&hp_sdc.hook_lock); + break; + default: + read_lock(&hp_sdc.hook_lock); + if (hp_sdc.cooked != NULL) + hp_sdc.cooked(irq, dev_id, status, data); + read_unlock(&hp_sdc.hook_lock); + break; + } +} + + +static void hp_sdc_nmisr(int irq, void *dev_id, struct pt_regs * regs) { + int status; + + status = hp_sdc_status_in8(); + printk(KERN_WARNING PREFIX "NMI !\n"); + +#if 0 + if (status & HP_SDC_NMISTATUS_FHS) { + read_lock(&hp_sdc.hook_lock); + if (hp_sdc.timer != NULL) + hp_sdc.timer(irq, dev_id, status, 0); + read_unlock(&hp_sdc.hook_lock); + } + else { + /* TODO: pass this on to the HIL handler, or do SAK here? */ + printk(KERN_WARNING PREFIX "HIL NMI\n"); + } +#endif +} + + +/***************** Kernel (tasklet) context functions ****************/ + +unsigned long hp_sdc_put(void); + +static void hp_sdc_tasklet(unsigned long foo) { + + write_lock_irq(&hp_sdc.rtq_lock); + if (hp_sdc.rcurr >= 0) { + struct timeval tv; + do_gettimeofday(&tv); + if (tv.tv_sec > hp_sdc.rtv.tv_sec) tv.tv_usec += 1000000; + if (tv.tv_usec - hp_sdc.rtv.tv_usec > HP_SDC_MAX_REG_DELAY) { + hp_sdc_transaction *curr; + uint8_t tmp; + + curr = hp_sdc.tq[hp_sdc.rcurr]; + /* If this turns out to be a normal failure mode + * we'll need to figure out a way to communicate + * it back to the application. and be less verbose. + */ + printk(KERN_WARNING PREFIX "read timeout (%ius)!\n", + tv.tv_usec - hp_sdc.rtv.tv_usec); + curr->idx += hp_sdc.rqty; + hp_sdc.rqty = 0; + tmp = curr->seq[curr->actidx]; + curr->seq[curr->actidx] |= HP_SDC_ACT_DEAD; + if(tmp & HP_SDC_ACT_SEMAPHORE) { + if (curr->act.semaphore) + up(curr->act.semaphore); + } + if(tmp & HP_SDC_ACT_CALLBACK) { + /* Note this means that irqhooks may be called + * in tasklet/bh context. + */ + if (curr->act.irqhook) + curr->act.irqhook(0, 0, 0, 0); + } + curr->actidx = curr->idx; + curr->idx++; + hp_sdc.rcurr = -1; + } + } + write_unlock_irq(&hp_sdc.rtq_lock); + hp_sdc_put(); +} + +unsigned long hp_sdc_put(void) { + hp_sdc_transaction *curr; + uint8_t act; + int idx, curridx; + + int limit = 0; + + write_lock(&hp_sdc.lock); + + /* If i8042 buffers are full, we cannot do anything that + requires output, so we skip to the administrativa. */ + if (hp_sdc.ibf) { + hp_sdc_status_in8(); + if (hp_sdc.ibf) goto finish; + } + + anew: + /* See if we are in the middle of a sequence. */ + if (hp_sdc.wcurr < 0) hp_sdc.wcurr = 0; + read_lock_irq(&hp_sdc.rtq_lock); + if (hp_sdc.rcurr == hp_sdc.wcurr) hp_sdc.wcurr++; + read_unlock_irq(&hp_sdc.rtq_lock); + if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0; + curridx = hp_sdc.wcurr; + + if (hp_sdc.tq[curridx] != NULL) goto start; + + while (++curridx != hp_sdc.wcurr) { + if (curridx >= HP_SDC_QUEUE_LEN) { + curridx = -1; /* Wrap to top */ + continue; + } + read_lock_irq(&hp_sdc.rtq_lock); + if (hp_sdc.rcurr == curridx) { + read_unlock_irq(&hp_sdc.rtq_lock); + continue; + } + read_unlock_irq(&hp_sdc.rtq_lock); + if (hp_sdc.tq[curridx] != NULL) break; /* Found one. */ + } + if (curridx == hp_sdc.wcurr) { /* There's nothing queued to do. */ + curridx = -1; + } + hp_sdc.wcurr = curridx; + + start: + + /* Check to see if the interrupt mask needs to be set. */ + if (hp_sdc.set_im) { + hp_sdc_status_out8(hp_sdc.im | HP_SDC_CMD_SET_IM); + hp_sdc.set_im = 0; + goto finish; + } + + if (hp_sdc.wcurr == -1) goto done; + + curr = hp_sdc.tq[curridx]; + idx = curr->actidx; + + if (curr->actidx >= curr->endidx) { + hp_sdc.tq[curridx] = NULL; + /* Interleave outbound data between the transactions. */ + hp_sdc.wcurr++; + if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0; + goto finish; + } + + act = curr->seq[idx]; + idx++; + + if (curr->idx >= curr->endidx) { + if (act & HP_SDC_ACT_DEALLOC) kfree(curr); + hp_sdc.tq[curridx] = NULL; + /* Interleave outbound data between the transactions. */ + hp_sdc.wcurr++; + if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0; + goto finish; + } + + while (act & HP_SDC_ACT_PRECMD) { + if (curr->idx != idx) { + idx++; + act &= ~HP_SDC_ACT_PRECMD; + break; + } + hp_sdc_status_out8(curr->seq[idx]); + curr->idx++; + /* act finished? */ + if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_PRECMD) + goto actdone; + /* skip quantity field if data-out sequence follows. */ + if (act & HP_SDC_ACT_DATAOUT) curr->idx++; + goto finish; + } + if (act & HP_SDC_ACT_DATAOUT) { + int qty; + + qty = curr->seq[idx]; + idx++; + if (curr->idx - idx < qty) { + hp_sdc_data_out8(curr->seq[curr->idx]); + curr->idx++; + /* act finished? */ + if ((curr->idx - idx >= qty) && + ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAOUT)) + goto actdone; + goto finish; + } + idx += qty; + act &= ~HP_SDC_ACT_DATAOUT; + } + else while (act & HP_SDC_ACT_DATAREG) { + int mask; + uint8_t w7[4]; + + mask = curr->seq[idx]; + if (idx != curr->idx) { + idx++; + idx += !!(mask & 1); + idx += !!(mask & 2); + idx += !!(mask & 4); + idx += !!(mask & 8); + act &= ~HP_SDC_ACT_DATAREG; + break; + } + + w7[0] = (mask & 1) ? curr->seq[++idx] : hp_sdc.r7[0]; + w7[1] = (mask & 2) ? curr->seq[++idx] : hp_sdc.r7[1]; + w7[2] = (mask & 4) ? curr->seq[++idx] : hp_sdc.r7[2]; + w7[3] = (mask & 8) ? curr->seq[++idx] : hp_sdc.r7[3]; + + if (hp_sdc.wi > 0x73 || hp_sdc.wi < 0x70 || + w7[hp_sdc.wi-0x70] == hp_sdc.r7[hp_sdc.wi-0x70]) { + int i = 0; + + /* Need to point the write index register */ + while ((i < 4) && w7[i] == hp_sdc.r7[i]) i++; + if (i < 4) { + hp_sdc_status_out8(HP_SDC_CMD_SET_D0 + i); + hp_sdc.wi = 0x70 + i; + goto finish; + } + idx++; + if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAREG) + goto actdone; + curr->idx = idx; + act &= ~HP_SDC_ACT_DATAREG; + break; + } + + hp_sdc_data_out8(w7[hp_sdc.wi - 0x70]); + hp_sdc.r7[hp_sdc.wi - 0x70] = w7[hp_sdc.wi - 0x70]; + hp_sdc.wi++; /* write index register autoincrements */ + { + int i = 0; + + while ((i < 4) && w7[i] == hp_sdc.r7[i]) i++; + if (i >= 4) { + curr->idx = idx + 1; + if ((act & HP_SDC_ACT_DURING) == + HP_SDC_ACT_DATAREG) + goto actdone; + } + } + goto finish; + } + /* We don't go any further in the command if there is a pending read, + because we don't want interleaved results. */ + read_lock_irq(&hp_sdc.rtq_lock); + if (hp_sdc.rcurr >= 0) { + read_unlock_irq(&hp_sdc.rtq_lock); + goto finish; + } + read_unlock_irq(&hp_sdc.rtq_lock); + + + if (act & HP_SDC_ACT_POSTCMD) { + uint8_t postcmd; + + /* curr->idx should == idx at this point. */ + postcmd = curr->seq[idx]; + curr->idx++; + if (act & HP_SDC_ACT_DATAIN) { + + /* Start a new read */ + hp_sdc.rqty = curr->seq[curr->idx]; + do_gettimeofday(&hp_sdc.rtv); + curr->idx++; + /* Still need to lock here in case of spurious irq. */ + write_lock_irq(&hp_sdc.rtq_lock); + hp_sdc.rcurr = curridx; + write_unlock_irq(&hp_sdc.rtq_lock); + hp_sdc_status_out8(postcmd); + goto finish; + } + hp_sdc_status_out8(postcmd); + goto actdone; + } + +actdone: + if (act & HP_SDC_ACT_SEMAPHORE) { + up(curr->act.semaphore); + } + else if (act & HP_SDC_ACT_CALLBACK) { + curr->act.irqhook(0,0,0,0); + } + if (curr->idx >= curr->endidx) { /* This transaction is over. */ + if (act & HP_SDC_ACT_DEALLOC) kfree(curr); + hp_sdc.tq[curridx] = NULL; + } + else { + curr->actidx = idx + 1; + curr->idx = idx + 2; + } + /* Interleave outbound data between the transactions. */ + hp_sdc.wcurr++; + if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0; + + finish: + /* If by some quirk IBF has cleared and our ISR has run to + see that that has happened, do it all again. */ + if (!hp_sdc.ibf && limit++ < 20) goto anew; + + done: + if (hp_sdc.wcurr >= 0) tasklet_schedule(&hp_sdc.task); + write_unlock(&hp_sdc.lock); + return 0; +} + +/******* Functions called in either user or kernel context ****/ +int hp_sdc_enqueue_transaction(hp_sdc_transaction *this) { + int i; + + if (this == NULL) { + tasklet_schedule(&hp_sdc.task); + return -EINVAL; + }; + + write_lock_bh(&hp_sdc.lock); + + /* Can't have same transaction on queue twice */ + for (i=0; i < HP_SDC_QUEUE_LEN; i++) + if (hp_sdc.tq[i] == this) goto fail; + + this->actidx = 0; + this->idx = 1; + + /* Search for empty slot */ + for (i=0; i < HP_SDC_QUEUE_LEN; i++) { + if (hp_sdc.tq[i] == NULL) { + hp_sdc.tq[i] = this; + tasklet_schedule(&hp_sdc.task); + write_unlock_bh(&hp_sdc.lock); + return 0; + } + } + write_unlock_bh(&hp_sdc.lock); + printk(KERN_WARNING PREFIX "No free slot to add transaction.\n"); + return -EBUSY; + + fail: + write_unlock_bh(&hp_sdc.lock); + printk(KERN_WARNING PREFIX "Transaction add failed: transaction already queued?\n"); + return -EINVAL; +} + +int hp_sdc_dequeue_transaction(hp_sdc_transaction *this) { + int i; + + write_lock_bh(&hp_sdc.lock); + + /* TODO: don't remove it if it's not done. */ + + for (i=0; i < HP_SDC_QUEUE_LEN; i++) + if (hp_sdc.tq[i] == this) hp_sdc.tq[i] = NULL; + + write_unlock_bh(&hp_sdc.lock); + return 0; +} + + + +/********************** User context functions **************************/ +int hp_sdc_request_timer_irq(hp_sdc_irqhook *callback) { + + MOD_INC_USE_COUNT; + if (callback == NULL || hp_sdc.dev == NULL) { + MOD_DEC_USE_COUNT; + return -EINVAL; + } + write_lock_irq(&hp_sdc.hook_lock); + if (hp_sdc.timer != NULL) { + write_unlock_irq(&hp_sdc.hook_lock); + MOD_DEC_USE_COUNT; + return -EBUSY; + } + + hp_sdc.timer = callback; + /* Enable interrupts from the timers */ + hp_sdc.im &= ~HP_SDC_IM_FH; + hp_sdc.im &= ~HP_SDC_IM_PT; + hp_sdc.im &= ~HP_SDC_IM_TIMERS; + hp_sdc.set_im = 1; + write_unlock_irq(&hp_sdc.hook_lock); + + tasklet_schedule(&hp_sdc.task); + + return 0; +} + +int hp_sdc_request_hil_irq(hp_sdc_irqhook *callback) { + + MOD_INC_USE_COUNT; + if (callback == NULL || hp_sdc.dev == NULL) { + MOD_DEC_USE_COUNT; + return -EINVAL; + } + write_lock_irq(&hp_sdc.hook_lock); + if (hp_sdc.hil != NULL) { + write_unlock_irq(&hp_sdc.hook_lock); + MOD_DEC_USE_COUNT; + return -EBUSY; + } + + hp_sdc.hil = callback; + hp_sdc.im &= ~HP_SDC_IM_HIL; + hp_sdc.set_im = 1; + write_unlock_irq(&hp_sdc.hook_lock); + + tasklet_schedule(&hp_sdc.task); + + return 0; +} + +int hp_sdc_request_cooked_irq(hp_sdc_irqhook *callback) { + + MOD_INC_USE_COUNT; + if (callback == NULL || hp_sdc.dev == NULL) { + MOD_DEC_USE_COUNT; + return -EINVAL; + } + write_lock_irq(&hp_sdc.hook_lock); + if (hp_sdc.cooked != NULL) { + write_unlock_irq(&hp_sdc.hook_lock); + MOD_DEC_USE_COUNT; + return -EBUSY; + } + + /* Enable interrupts from the HIL MLC */ + hp_sdc.cooked = callback; + hp_sdc.im &= ~HP_SDC_IM_HIL; + hp_sdc.set_im = 1; + write_unlock_irq(&hp_sdc.hook_lock); + + tasklet_schedule(&hp_sdc.task); + + return 0; +} + +int hp_sdc_release_timer_irq(hp_sdc_irqhook *callback) { + + + write_lock_irq(&hp_sdc.hook_lock); + if ((callback != hp_sdc.timer) || + (hp_sdc.timer == NULL)) { + write_unlock_irq(&hp_sdc.hook_lock); + return -EINVAL; + } + + /* Disable interrupts from the timers */ + hp_sdc.timer = NULL; + hp_sdc.im |= HP_SDC_IM_TIMERS; + hp_sdc.im |= HP_SDC_IM_FH; + hp_sdc.im |= HP_SDC_IM_PT; + hp_sdc.set_im = 1; + write_unlock_irq(&hp_sdc.hook_lock); + tasklet_schedule(&hp_sdc.task); + + MOD_DEC_USE_COUNT; + return 0; +} + +int hp_sdc_release_hil_irq(hp_sdc_irqhook *callback) { + + write_lock_irq(&hp_sdc.hook_lock); + if ((callback != hp_sdc.hil) || + (hp_sdc.hil == NULL)) { + write_unlock_irq(&hp_sdc.hook_lock); + return -EINVAL; + } + + hp_sdc.hil = NULL; + /* Disable interrupts from HIL only if there is no cooked driver. */ + if(hp_sdc.cooked == NULL) { + hp_sdc.im |= HP_SDC_IM_HIL; + hp_sdc.set_im = 1; + } + write_unlock_irq(&hp_sdc.hook_lock); + tasklet_schedule(&hp_sdc.task); + + MOD_DEC_USE_COUNT; + return 0; +} + +int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback) { + + write_lock_irq(&hp_sdc.hook_lock); + if ((callback != hp_sdc.cooked) || + (hp_sdc.cooked == NULL)) { + write_unlock_irq(&hp_sdc.hook_lock); + return -EINVAL; + } + + hp_sdc.cooked = NULL; + /* Disable interrupts from HIL only if there is no raw HIL driver. */ + if(hp_sdc.hil == NULL) { + hp_sdc.im |= HP_SDC_IM_HIL; + hp_sdc.set_im = 1; + } + write_unlock_irq(&hp_sdc.hook_lock); + tasklet_schedule(&hp_sdc.task); + + MOD_DEC_USE_COUNT; + return 0; +} + +/************************* Keepalive timer task *********************/ + +void hp_sdc_kicker (unsigned long data) { + tasklet_schedule(&hp_sdc.task); + /* Re-insert the periodic task. */ + mod_timer(&hp_sdc.kicker, jiffies + HZ); +} + +/************************** Module Initialization ***************************/ + +static struct parisc_device_id hp_sdc_tbl[] = { + { + hw_type: HPHW_FIO, + hversion_rev: HVERSION_REV_ANY_ID, + hversion: HVERSION_ANY_ID, + sversion: 0x73, + }, + { 0, } +}; + +MODULE_DEVICE_TABLE(parisc, hp_sdc_tbl); + +static int __init hp_sdc_init(struct parisc_device *d); + +static struct parisc_driver hp_sdc_driver = { + name: "HP SDC", + id_table: hp_sdc_tbl, + probe: hp_sdc_init, +}; + +static int __init hp_sdc_init(struct parisc_device *d) +{ + int i; + char *errstr = NULL; + hp_sdc_transaction t_sync; + uint8_t ts_sync[6]; + struct semaphore s_sync; + + + errstr = "foo\n"; + + if (!d) return 1; + if (hp_sdc.dev != NULL) return 1; /* We only expect one SDC */ + + hp_sdc.dev = d; + hp_sdc.irq = d->irq; + /* TODO: Is NMI == IRQ - 1 all cases, or is there a way to query? */ + hp_sdc.nmi = d->irq - 1; + hp_sdc.base_io = (unsigned long) d->hpa; + hp_sdc.data_io = (unsigned long) d->hpa + 0x800; + hp_sdc.status_io = (unsigned long) d->hpa + 0x801; + + hp_sdc.lock = RW_LOCK_UNLOCKED; + hp_sdc.ibf_lock = RW_LOCK_UNLOCKED; + hp_sdc.rtq_lock = RW_LOCK_UNLOCKED; + hp_sdc.hook_lock = RW_LOCK_UNLOCKED; + + hp_sdc.timer = NULL; + hp_sdc.hil = NULL; + hp_sdc.pup = NULL; + hp_sdc.cooked = NULL; + hp_sdc.im = HP_SDC_IM_MASK; /* Mask maskable irqs */ + hp_sdc.set_im = 1; + hp_sdc.wi = 0xff; + hp_sdc.r7[0] = 0xff; + hp_sdc.r7[1] = 0xff; + hp_sdc.r7[2] = 0xff; + hp_sdc.r7[3] = 0xff; + hp_sdc.ibf = 1; + + for (i = 0; i < HP_SDC_QUEUE_LEN; i++) hp_sdc.tq[i] = NULL; + hp_sdc.wcurr = -1; + hp_sdc.rcurr = -1; + hp_sdc.rqty = 0; + + hp_sdc.dev_err = -ENODEV; + + errstr = "IO not found for"; + if (!hp_sdc.base_io) goto err0; + + errstr = "IRQ not found for"; + if (!hp_sdc.irq) goto err0; + + hp_sdc.dev_err = -EBUSY; + + errstr = "IO not available for"; + if (request_region(hp_sdc.data_io, 2, hp_sdc_driver.name)) goto err0; + + errstr = "IRQ not available for"; + if(request_irq(hp_sdc.irq, &hp_sdc_isr, 0, hp_sdc_driver.name, + (void *) hp_sdc.base_io)) goto err1; + + errstr = "NMI not available for"; + if (request_irq(hp_sdc.nmi, &hp_sdc_nmisr, 0, "HP SDC NMI", + (void*)d->hpa)) goto err2; + + printk(KERN_INFO PREFIX "HP SDC at 0x%p, IRQ %d (NMI IRQ %d)\n", + (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi); + + hp_sdc_status_in8(); + hp_sdc_data_in8(); + + tasklet_init(&hp_sdc.task, hp_sdc_tasklet, 0); + + /* Sync the output buffer registers, thus scheduling hp_sdc_tasklet. */ + t_sync.actidx = 0; + t_sync.idx = 1; + t_sync.endidx = 6; + t_sync.seq = ts_sync; + ts_sync[0] = HP_SDC_ACT_DATAREG | HP_SDC_ACT_SEMAPHORE; + ts_sync[1] = 0x0f; + ts_sync[2] = ts_sync[3] = ts_sync[4] = ts_sync[5] = 0; + t_sync.act.semaphore = &s_sync; + init_MUTEX_LOCKED(&s_sync); + hp_sdc_enqueue_transaction(&t_sync); + down(&s_sync); /* Wait for t_sync to complete */ + + /* Create the keepalive task */ + init_timer(&hp_sdc.kicker); + hp_sdc.kicker.expires = jiffies + HZ; + hp_sdc.kicker.function = &hp_sdc_kicker; + add_timer(&hp_sdc.kicker); + + hp_sdc.dev_err = 0; + return 0; + err2: + free_irq(hp_sdc.irq, NULL); + err1: + release_region(hp_sdc.data_io, 2); + err0: + printk(KERN_WARNING PREFIX ": %s SDC IO=0x%p IRQ=0x%x NMI=0x%x\n", + errstr, (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi); + hp_sdc.dev = NULL; + return hp_sdc.dev_err; +} + +static void __exit hp_sdc_exit(void) +{ + write_lock_irq(&hp_sdc.lock); + + /* Turn off all maskable "sub-function" irq's. */ + hp_sdc_spin_ibf(); + gsc_writeb(HP_SDC_CMD_SET_IM | HP_SDC_IM_MASK, hp_sdc.status_io); + + /* Wait until we know this has been processed by the i8042 */ + hp_sdc_spin_ibf(); + + free_irq(hp_sdc.nmi, NULL); + free_irq(hp_sdc.irq, NULL); + write_unlock_irq(&hp_sdc.lock); + + del_timer(&hp_sdc.kicker); + + tasklet_kill(&hp_sdc.task); + +/* release_region(hp_sdc.data_io, 2); */ + + if (unregister_parisc_driver(&hp_sdc_driver)) + printk(KERN_WARNING PREFIX "Error unregistering HP SDC"); +} + +static int __init hp_sdc_register(void) +{ + hp_sdc.dev = NULL; + hp_sdc.dev_err = 0; + hp_sdc_transaction tq_init; + uint8_t tq_init_seq[5]; + struct semaphore tq_init_sem; + + if (register_parisc_driver(&hp_sdc_driver)) { + printk(KERN_WARNING PREFIX "Error registering SDC with system bus tree.\n"); + return -ENODEV; + } + if (hp_sdc.dev == NULL) { + printk(KERN_WARNING PREFIX "No SDC found.\n"); + return hp_sdc.dev_err; + } + + init_MUTEX_LOCKED(&tq_init_sem); + + tq_init.actidx = 0; + tq_init.idx = 1; + tq_init.endidx = 5; + tq_init.seq = tq_init_seq; + tq_init.act.semaphore = &tq_init_sem; + + tq_init_seq[0] = + HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE; + tq_init_seq[1] = HP_SDC_CMD_READ_KCC; + tq_init_seq[2] = 1; + tq_init_seq[3] = 0; + tq_init_seq[4] = 0; + + hp_sdc_enqueue_transaction(&tq_init); + + down(&tq_init_sem); + up(&tq_init_sem); + + if ((tq_init_seq[0] & HP_SDC_ACT_DEAD) == HP_SDC_ACT_DEAD) { + printk(KERN_WARNING PREFIX "Error reading config byte.\n"); + hp_sdc_exit(); + return -ENODEV; + } + hp_sdc.r11 = tq_init_seq[4]; + if (hp_sdc.r11 & HP_SDC_CFG_NEW) { + char *str; + printk(KERN_INFO PREFIX "New style SDC\n"); + tq_init_seq[1] = HP_SDC_CMD_READ_XTD; + tq_init.actidx = 0; + tq_init.idx = 1; + down(&tq_init_sem); + hp_sdc_enqueue_transaction(&tq_init); + down(&tq_init_sem); + up(&tq_init_sem); + if ((tq_init_seq[0] & HP_SDC_ACT_DEAD) == HP_SDC_ACT_DEAD) { + printk(KERN_WARNING PREFIX "Error reading extended config byte.\n"); + return -ENODEV; + } + hp_sdc.r7e = tq_init_seq[4]; + HP_SDC_XTD_REV_STRINGS(hp_sdc.r7e & HP_SDC_XTD_REV, str) + printk(KERN_INFO PREFIX "Revision: %s\n", str); + if (hp_sdc.r7e & HP_SDC_XTD_BEEPER) { + printk(KERN_INFO PREFIX "TI SN76494 beeper present\n"); + } + if (hp_sdc.r7e & HP_SDC_XTD_BBRTC) { + printk(KERN_INFO PREFIX "OKI MSM-58321 BBRTC present\n"); + } + printk(KERN_INFO PREFIX "Spunking the self test register to force PUP " + "on next firmware reset.\n"); + tq_init_seq[0] = HP_SDC_ACT_PRECMD | + HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE; + tq_init_seq[1] = HP_SDC_CMD_SET_STR; + tq_init_seq[2] = 1; + tq_init_seq[3] = 0; + tq_init.actidx = 0; + tq_init.idx = 1; + tq_init.endidx = 4; + down(&tq_init_sem); + hp_sdc_enqueue_transaction(&tq_init); + down(&tq_init_sem); + up(&tq_init_sem); + } + else { + printk(KERN_INFO PREFIX "Old style SDC (1820-%s).\n", + (hp_sdc.r11 & HP_SDC_CFG_REV) ? "3300" : "2564/3087"); + } + + return 0; +} + +module_init(hp_sdc_register); +module_exit(hp_sdc_exit); + +/* Timing notes: These measurements taken on my 64MHz 7100-LC (715/64) + * cycles cycles-adj time + * between two consecutive mfctl(16)'s: 4 n/a 63ns + * hp_sdc_spin_ibf when idle: 119 115 1.7us + * gsc_writeb status register: 83 79 1.2us + * IBF to clear after sending SET_IM: 6204 6006 93us + * IBF to clear after sending LOAD_RT: 4467 4352 68us + * IBF to clear after sending two LOAD_RTs: 18974 18859 295us + * READ_T1, read status/data, IRQ, call handler: 35564 n/a 556us + * cmd to ~IBF READ_T1 2nd time right after: 5158403 n/a 81ms + * between IRQ received and ~IBF for above: 2578877 n/a 40ms + * + * Performance stats after a run of this module configuring HIL and + * receiving a few mouse events: + * + * status in8 282508 cycles 7128 calls + * status out8 8404 cycles 341 calls + * data out8 1734 cycles 78 calls + * isr 174324 cycles 617 calls (includes take) + * take 1241 cycles 2 calls + * put 1411504 cycles 6937 calls + * task 1655209 cycles 6937 calls (includes put) + * + */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/hil/hp_sdc_mlc.c linux.19rc3-ac4/drivers/hil/hp_sdc_mlc.c --- linux.19rc3/drivers/hil/hp_sdc_mlc.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/hil/hp_sdc_mlc.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,370 @@ +/* + * Access to HP-HIL MLC through HP System Device Controller. + * + * Copyright (c) 2001 Brian S. Julin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL"). + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * + * References: + * HP-HIL Technical Reference Manual. Hewlett Packard Product No. 45918A + * System Device Controller Microprocessor Firmware Theory of Operation + * for Part Number 1820-4784 Revision B. Dwg No. A-1820-4784-2 + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#define PREFIX "HP SDC MLC: " + +static hil_mlc hp_sdc_mlc; + +MODULE_AUTHOR("Brian S. Julin "); +MODULE_DESCRIPTION("Glue for onboard HIL MLC in HP-PARISC machines"); +MODULE_LICENSE("Dual BSD/GPL"); + +struct hp_sdc_mlc_priv_s { + int emtestmode; + hp_sdc_transaction trans; + u8 tseq[16]; + int got5x; +} hp_sdc_mlc_priv; + +/************************* Interrupt context ******************************/ +static void hp_sdc_mlc_isr (int irq, void *dev_id, + uint8_t status, uint8_t data) { + int idx; + hil_mlc *mlc = &hp_sdc_mlc; + + write_lock(&(mlc->lock)); + if (mlc->icount < 0) { + printk(KERN_WARNING PREFIX "HIL Overflow!\n"); + up(&mlc->isem); + goto out; + } + idx = 15 - mlc->icount; + if ((status & HP_SDC_STATUS_IRQMASK) == HP_SDC_STATUS_HILDATA) { + mlc->ipacket[idx] |= data | HIL_ERR_INT; + mlc->icount--; + if (hp_sdc_mlc_priv.got5x) goto check; + if (!idx) goto check; + if ((mlc->ipacket[idx-1] & HIL_PKT_ADDR_MASK) != + (mlc->ipacket[idx] & HIL_PKT_ADDR_MASK)) { + mlc->ipacket[idx] &= ~HIL_PKT_ADDR_MASK; + mlc->ipacket[idx] |= (mlc->ipacket[idx-1] + & HIL_PKT_ADDR_MASK); + } + goto check; + } + /* We know status is 5X */ + if (data & HP_SDC_HIL_ISERR) goto err; + mlc->ipacket[idx] = + (data & HP_SDC_HIL_R1MASK) << HIL_PKT_ADDR_SHIFT; + hp_sdc_mlc_priv.got5x = 1; + goto out; + + check: + hp_sdc_mlc_priv.got5x = 0; + if (mlc->imatch == 0) goto done; + if ((mlc->imatch == (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) + && (mlc->ipacket[idx] == (mlc->imatch | idx))) goto done; + if (mlc->ipacket[idx] == mlc->imatch) goto done; + goto out; + + err: + printk(KERN_DEBUG PREFIX "err code %x\n", data); + switch (data) { + case HP_SDC_HIL_RC_DONE: + printk(KERN_WARNING PREFIX "Bastard SDC reconfigured loop!\n"); + break; + case HP_SDC_HIL_ERR: + mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_PERR | + HIL_ERR_FERR | HIL_ERR_FOF; + break; + case HP_SDC_HIL_TO: + mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_LERR; + break; + case HP_SDC_HIL_RC: + printk(KERN_WARNING PREFIX "Bastard SDC decided to reconfigure loop!\n"); + break; + default: + printk(KERN_WARNING PREFIX "Unkown HIL Error status (%x)!\n", data); + break; + } + /* No more data will be coming due to an error. */ + done: + tasklet_schedule(mlc->tasklet); + up(&(mlc->isem)); + out: + write_unlock(&(mlc->lock)); +} + + +/******************** Tasklet or userspace context functions ****************/ + +static int hp_sdc_mlc_in (hil_mlc *mlc, suseconds_t timeout) { + unsigned long flags; + struct hp_sdc_mlc_priv_s *priv; + int rc = 2; + + priv = mlc->priv; + + write_lock_irqsave(&(mlc->lock), flags); + + /* Try to down the semaphore */ + if (down_trylock(&(mlc->isem))) { + struct timeval tv; + if (priv->emtestmode) { + mlc->ipacket[0] = + HIL_ERR_INT | (mlc->opacket & + (HIL_PKT_CMD | + HIL_PKT_ADDR_MASK | + HIL_PKT_DATA_MASK)); + mlc->icount = 14; + /* printk(KERN_DEBUG PREFIX ">[%x]\n", mlc->ipacket[0]); */ + goto wasup; + } + do_gettimeofday(&tv); + tv.tv_usec += 1000000 * (tv.tv_sec - mlc->instart.tv_sec); + if (tv.tv_usec - mlc->instart.tv_usec > mlc->intimeout) { + /* printk("!%i %i", + tv.tv_usec - mlc->instart.tv_usec, + mlc->intimeout); + */ + rc = 1; + up(&(mlc->isem)); + } + goto done; + } + wasup: + up(&(mlc->isem)); + rc = 0; + goto done; + done: + write_unlock_irqrestore(&(mlc->lock), flags); + return rc; +} + +static int hp_sdc_mlc_cts (hil_mlc *mlc) { + struct hp_sdc_mlc_priv_s *priv; + unsigned long flags; + + priv = mlc->priv; + + write_lock_irqsave(&(mlc->lock), flags); + + /* Try to down the semaphores -- they should be up. */ + if (down_trylock(&(mlc->isem))) { + BUG(); + goto busy; + } + if (down_trylock(&(mlc->osem))) { + BUG(); + up(&(mlc->isem)); + goto busy; + } + up(&(mlc->isem)); + up(&(mlc->osem)); + + if (down_trylock(&(mlc->csem))) { + if (priv->trans.act.semaphore != &(mlc->csem)) goto poll; + goto busy; + } + if (!(priv->tseq[4] & HP_SDC_USE_LOOP)) goto done; + + poll: + priv->trans.act.semaphore = &(mlc->csem); + priv->trans.actidx = 0; + priv->trans.idx = 1; + priv->trans.endidx = 5; + priv->tseq[0] = + HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE; + priv->tseq[1] = HP_SDC_CMD_READ_USE; + priv->tseq[2] = 1; + priv->tseq[3] = 0; + priv->tseq[4] = 0; + hp_sdc_enqueue_transaction(&(priv->trans)); + busy: + write_unlock_irqrestore(&(mlc->lock), flags); + return 1; + done: + priv->trans.act.semaphore = &(mlc->osem); + up(&(mlc->csem)); + write_unlock_irqrestore(&(mlc->lock), flags); + return 0; +} + +static void hp_sdc_mlc_out (hil_mlc *mlc) { + struct hp_sdc_mlc_priv_s *priv; + unsigned long flags; + + priv = mlc->priv; + + write_lock_irqsave(&(mlc->lock), flags); + + /* Try to down the semaphore -- it should be up. */ + if (down_trylock(&(mlc->osem))) { + BUG(); + goto done; + } + + if (mlc->opacket & HIL_DO_ALTER_CTRL) goto do_control; + + do_data: + if (priv->emtestmode) { + up(&(mlc->osem)); + goto done; + } + /* Shouldn't be sending commands when loop may be busy */ + if (down_trylock(&(mlc->csem))) { + BUG(); + goto done; + } + up(&(mlc->csem)); + + priv->trans.actidx = 0; + priv->trans.idx = 1; + priv->trans.act.semaphore = &(mlc->osem); + priv->trans.endidx = 6; + priv->tseq[0] = + HP_SDC_ACT_DATAREG | HP_SDC_ACT_POSTCMD | HP_SDC_ACT_SEMAPHORE; + priv->tseq[1] = 0x7; + priv->tseq[2] = + (mlc->opacket & + (HIL_PKT_ADDR_MASK | HIL_PKT_CMD)) + >> HIL_PKT_ADDR_SHIFT; + priv->tseq[3] = + (mlc->opacket & HIL_PKT_DATA_MASK) + >> HIL_PKT_DATA_SHIFT; + priv->tseq[4] = 0; /* No timeout */ + if (priv->tseq[3] == HIL_CMD_DHR) priv->tseq[4] = 1; + priv->tseq[5] = HP_SDC_CMD_DO_HIL; + goto enqueue; + + do_control: + priv->emtestmode = mlc->opacket & HIL_CTRL_TEST; + if ((mlc->opacket & (HIL_CTRL_APE | HIL_CTRL_IPF)) == HIL_CTRL_APE) { + BUG(); /* we cannot emulate this, it should not be used. */ + } + if ((mlc->opacket & HIL_CTRL_ONLY) == HIL_CTRL_ONLY) goto control_only; + if (mlc->opacket & HIL_CTRL_APE) { + BUG(); /* Should not send command/data after engaging APE */ + goto done; + } + /* Disengaging APE this way would not be valid either since + * the loop must be allowed to idle. + * + * So, it works out that we really never actually send control + * and data when using SDC, we just send the data. + */ + goto do_data; + + control_only: + priv->trans.actidx = 0; + priv->trans.idx = 1; + priv->trans.act.semaphore = &(mlc->osem); + priv->trans.endidx = 4; + priv->tseq[0] = + HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE; + priv->tseq[1] = HP_SDC_CMD_SET_LPC; + priv->tseq[2] = 1; + // priv->tseq[3] = (mlc->ddc + 1) | HP_SDC_LPS_ACSUCC; + priv->tseq[3] = 0; + if (mlc->opacket & HIL_CTRL_APE) { + priv->tseq[3] |= HP_SDC_LPC_APE_IPF; + down_trylock(&(mlc->csem)); + } + enqueue: + hp_sdc_enqueue_transaction(&(priv->trans)); + done: + write_unlock_irqrestore(&(mlc->lock), flags); +} + + +static void hp_sdc_mlc_inc_use_count (void) { + MOD_INC_USE_COUNT; +} + +static void hp_sdc_mlc_dec_use_count (void) { + MOD_DEC_USE_COUNT; +} + +static int __init hp_sdc_mlc_init(void) +{ + hil_mlc *mlc = &hp_sdc_mlc; + + printk(KERN_INFO PREFIX "Registering the System Domain Controller's HIL MLC.\n"); + + hp_sdc_mlc_priv.emtestmode = 0; + hp_sdc_mlc_priv.trans.seq = hp_sdc_mlc_priv.tseq; + hp_sdc_mlc_priv.trans.act.semaphore = &(mlc->osem); + hp_sdc_mlc_priv.got5x = 0; + + mlc->cts = &hp_sdc_mlc_cts; + mlc->in = &hp_sdc_mlc_in; + mlc->out = &hp_sdc_mlc_out; + + mlc->inc_use_count = &hp_sdc_mlc_inc_use_count; + mlc->dec_use_count = &hp_sdc_mlc_dec_use_count; + + if (hil_mlc_register(mlc)) { + printk(KERN_WARNING PREFIX "Failed to register MLC structure with hil_mlc\n"); + goto err0; + } + mlc->priv = &hp_sdc_mlc_priv; + + if (hp_sdc_request_hil_irq(&hp_sdc_mlc_isr)) { + printk(KERN_WARNING PREFIX "Request for raw HIL ISR hook denied\n"); + goto err1; + } + return 0; + err1: + if (hil_mlc_unregister(mlc)) { + printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n" + "This is bad. Could cause an oops.\n"); + } + err0: + return -EBUSY; +} + +static void __exit hp_sdc_mlc_exit(void) +{ + hil_mlc *mlc = &hp_sdc_mlc; + if (hp_sdc_release_hil_irq(&hp_sdc_mlc_isr)) { + printk(KERN_ERR PREFIX "Failed to release the raw HIL ISR hook.\n" + "This is bad. Could cause an oops.\n"); + } + if (hil_mlc_unregister(mlc)) { + printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n" + "This is bad. Could cause an oops.\n"); + } +} + +module_init(hp_sdc_mlc_init); +module_exit(hp_sdc_mlc_exit); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/hil/hp_sdc_rtc.c linux.19rc3-ac4/drivers/hil/hp_sdc_rtc.c --- linux.19rc3/drivers/hil/hp_sdc_rtc.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/hil/hp_sdc_rtc.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,720 @@ +/* + * HP i8042 SDC + MSM-58321 BBRTC driver. + * + * Copyright (c) 2001 Brian S. Julin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL"). + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * + * References: + * System Device Controller Microprocessor Firmware Theory of Operation + * for Part Number 1820-4784 Revision B. Dwg No. A-1820-4784-2 + * efirtc.c by Stephane Eranian/Hewlett Packard + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_AUTHOR("Brian S. Julin "); +MODULE_DESCRIPTION("HP i8042 SDC + MSM-58321 RTC Driver"); +MODULE_LICENSE("Dual BSD/GPL"); + +#define RTC_VERSION "1.10d" + +static unsigned long epoch = 2000; + +static struct semaphore i8042tregs; + +static hp_sdc_irqhook hp_sdc_rtc_isr; + +static struct fasync_struct *hp_sdc_rtc_async_queue; + +static DECLARE_WAIT_QUEUE_HEAD(hp_sdc_rtc_wait); + +static loff_t hp_sdc_rtc_llseek(struct file *file, loff_t offset, int origin); + +static ssize_t hp_sdc_rtc_read(struct file *file, char *buf, + size_t count, loff_t *ppos); + +static int hp_sdc_rtc_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg); + +static unsigned int hp_sdc_rtc_poll(struct file *file, poll_table *wait); + +static int hp_sdc_rtc_open(struct inode *inode, struct file *file); +static int hp_sdc_rtc_release(struct inode *inode, struct file *file); +static int hp_sdc_rtc_fasync (int fd, struct file *filp, int on); + +static int hp_sdc_rtc_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data); + +static void hp_sdc_rtc_isr (int irq, void *dev_id, + uint8_t status, uint8_t data) +{ + return; +} + +static int hp_sdc_rtc_do_read_bbrtc (struct rtc_time *rtctm) +{ + struct semaphore tsem; + hp_sdc_transaction t; + uint8_t tseq[91]; + int i; + + i = 0; + while (i < 91) { + tseq[i++] = HP_SDC_ACT_DATAREG | + HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN; + tseq[i++] = 0x01; /* write i8042[0x70] */ + tseq[i] = i / 7; /* BBRTC reg address */ + i++; + tseq[i++] = HP_SDC_CMD_DO_RTCR; /* Trigger command */ + tseq[i++] = 2; /* expect 1 stat/dat pair back. */ + i++; i++; /* buffer for stat/dat pair */ + } + tseq[84] |= HP_SDC_ACT_SEMAPHORE; + t.endidx = 91; + t.seq = tseq; + t.act.semaphore = &tsem; + init_MUTEX_LOCKED(&tsem); + + if (hp_sdc_enqueue_transaction(&t)) return -1; + + down_interruptible(&tsem); /* Put ourselves to sleep for results. */ + + /* Check for nonpresence of BBRTC */ + if (!((tseq[83] | tseq[90] | tseq[69] | tseq[76] | + tseq[55] | tseq[62] | tseq[34] | tseq[41] | + tseq[20] | tseq[27] | tseq[6] | tseq[13]) & 0x0f)) + return -1; + + memset(rtctm, 0, sizeof(struct rtc_time)); + rtctm->tm_year = (tseq[83] & 0x0f) + (tseq[90] & 0x0f) * 10; + rtctm->tm_mon = (tseq[69] & 0x0f) + (tseq[76] & 0x0f) * 10; + rtctm->tm_mday = (tseq[55] & 0x0f) + (tseq[62] & 0x0f) * 10; + rtctm->tm_wday = (tseq[48] & 0x0f); + rtctm->tm_hour = (tseq[34] & 0x0f) + (tseq[41] & 0x0f) * 10; + rtctm->tm_min = (tseq[20] & 0x0f) + (tseq[27] & 0x0f) * 10; + rtctm->tm_sec = (tseq[6] & 0x0f) + (tseq[13] & 0x0f) * 10; + + return 0; +} + +static int hp_sdc_rtc_read_bbrtc (struct rtc_time *rtctm) +{ + struct rtc_time tm, tm_last; + int i = 0; + + /* MSM-58321 has no read latch, so must read twice and compare. */ + + if (hp_sdc_rtc_do_read_bbrtc(&tm_last)) return -1; + if (hp_sdc_rtc_do_read_bbrtc(&tm)) return -1; + + while (memcmp(&tm, &tm_last, sizeof(struct rtc_time))) { + if (i++ > 4) return -1; + memcpy(&tm_last, &tm, sizeof(struct rtc_time)); + if (hp_sdc_rtc_do_read_bbrtc(&tm)) return -1; + } + + memcpy(rtctm, &tm, sizeof(struct rtc_time)); + + return 0; +} + + +static int64_t hp_sdc_rtc_read_i8042timer (uint8_t loadcmd, int numreg) +{ + hp_sdc_transaction t; + uint8_t tseq[26] = { + HP_SDC_ACT_PRECMD | HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN, + 0, + HP_SDC_CMD_READ_T1, 2, 0, 0, + HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN, + HP_SDC_CMD_READ_T2, 2, 0, 0, + HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN, + HP_SDC_CMD_READ_T3, 2, 0, 0, + HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN, + HP_SDC_CMD_READ_T4, 2, 0, 0, + HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN, + HP_SDC_CMD_READ_T5, 2, 0, 0 + }; + + t.endidx = numreg * 5; + + tseq[1] = loadcmd; + tseq[t.endidx - 4] |= HP_SDC_ACT_SEMAPHORE; /* numreg assumed > 1 */ + + t.seq = tseq; + t.act.semaphore = &i8042tregs; + + down_interruptible(&i8042tregs); /* Sleep if output regs in use. */ + + if (hp_sdc_enqueue_transaction(&t)) return -1; + + down_interruptible(&i8042tregs); /* Sleep until results come back. */ + up(&i8042tregs); + + return (tseq[5] | + ((uint64_t)(tseq[10]) << 8) | ((uint64_t)(tseq[15]) << 16) | + ((uint64_t)(tseq[20]) << 24) | ((uint64_t)(tseq[25]) << 32)); +} + + +/* Read the i8042 real-time clock */ +static inline int hp_sdc_rtc_read_rt(struct timeval *res) { + int64_t raw; + uint32_t tenms; + unsigned int days; + + raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_RT, 5); + if (raw < 0) return -1; + + tenms = (uint32_t)raw & 0xffffff; + days = (unsigned int)(raw >> 24) & 0xffff; + + res->tv_usec = (suseconds_t)(tenms % 100) * 10000; + res->tv_sec = (time_t)(tenms / 100) + days * 86400; + + return 0; +} + + +/* Read the i8042 fast handshake timer */ +static inline int hp_sdc_rtc_read_fhs(struct timeval *res) { + uint64_t raw; + unsigned int tenms; + + raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_FHS, 2); + if (raw < 0) return -1; + + tenms = (unsigned int)raw & 0xffff; + + res->tv_usec = (suseconds_t)(tenms % 100) * 10000; + res->tv_sec = (time_t)(tenms / 100); + + return 0; +} + + +/* Read the i8042 match timer (a.k.a. alarm) */ +static inline int hp_sdc_rtc_read_mt(struct timeval *res) { + int64_t raw; + uint32_t tenms; + + raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_MT, 3); + if (raw < 0) return -1; + + tenms = (uint32_t)raw & 0xffffff; + + res->tv_usec = (suseconds_t)(tenms % 100) * 10000; + res->tv_sec = (time_t)(tenms / 100); + + return 0; +} + + +/* Read the i8042 delay timer */ +static inline int hp_sdc_rtc_read_dt(struct timeval *res) { + int64_t raw; + uint32_t tenms; + + raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_DT, 3); + if (raw < 0) return -1; + + tenms = (uint32_t)raw & 0xffffff; + + res->tv_usec = (suseconds_t)(tenms % 100) * 10000; + res->tv_sec = (time_t)(tenms / 100); + + return 0; +} + + +/* Read the i8042 cycle timer (a.k.a. periodic) */ +static inline int hp_sdc_rtc_read_ct(struct timeval *res) { + int64_t raw; + uint32_t tenms; + + raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_CT, 3); + if (raw < 0) return -1; + + tenms = (uint32_t)raw & 0xffffff; + + res->tv_usec = (suseconds_t)(tenms % 100) * 10000; + res->tv_sec = (time_t)(tenms / 100); + + return 0; +} + + +/* Set the i8042 real-time clock */ +static int hp_sdc_rtc_set_rt (struct timeval *setto) +{ + uint32_t tenms; + unsigned int days; + hp_sdc_transaction t; + uint8_t tseq[11] = { + HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT, + HP_SDC_CMD_SET_RTMS, 3, 0, 0, 0, + HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT, + HP_SDC_CMD_SET_RTD, 2, 0, 0 + }; + + t.endidx = 10; + + if (0xffff < setto->tv_sec / 86400) return -1; + days = setto->tv_sec / 86400; + if (0xffff < setto->tv_usec / 1000000 / 86400) return -1; + days += ((setto->tv_sec % 86400) + setto->tv_usec / 1000000) / 86400; + if (days > 0xffff) return -1; + + if (0xffffff < setto->tv_sec) return -1; + tenms = setto->tv_sec * 100; + if (0xffffff < setto->tv_usec / 10000) return -1; + tenms += setto->tv_usec / 10000; + if (tenms > 0xffffff) return -1; + + tseq[3] = (uint8_t)(tenms & 0xff); + tseq[4] = (uint8_t)((tenms >> 8) & 0xff); + tseq[5] = (uint8_t)((tenms >> 16) & 0xff); + + tseq[9] = (uint8_t)(days & 0xff); + tseq[10] = (uint8_t)((days >> 8) & 0xff); + + t.seq = tseq; + + if (hp_sdc_enqueue_transaction(&t)) return -1; + return 0; +} + +/* Set the i8042 fast handshake timer */ +static int hp_sdc_rtc_set_fhs (struct timeval *setto) +{ + uint32_t tenms; + hp_sdc_transaction t; + uint8_t tseq[5] = { + HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT, + HP_SDC_CMD_SET_FHS, 2, 0, 0 + }; + + t.endidx = 4; + + if (0xffff < setto->tv_sec) return -1; + tenms = setto->tv_sec * 100; + if (0xffff < setto->tv_usec / 10000) return -1; + tenms += setto->tv_usec / 10000; + if (tenms > 0xffff) return -1; + + tseq[3] = (uint8_t)(tenms & 0xff); + tseq[4] = (uint8_t)((tenms >> 8) & 0xff); + + t.seq = tseq; + + if (hp_sdc_enqueue_transaction(&t)) return -1; + return 0; +} + + +/* Set the i8042 match timer (a.k.a. alarm) */ +#define hp_sdc_rtc_set_mt (setto) \ + hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_MT) + +/* Set the i8042 delay timer */ +#define hp_sdc_rtc_set_dt (setto) \ + hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_DT) + +/* Set the i8042 cycle timer (a.k.a. periodic) */ +#define hp_sdc_rtc_set_ct (setto) \ + hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_CT) + +/* Set one of the i8042 3-byte wide timers */ +static int hp_sdc_rtc_set_i8042timer (struct timeval *setto, uint8_t setcmd) +{ + uint32_t tenms; + hp_sdc_transaction t; + uint8_t tseq[6] = { + HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT, + 0, 3, 0, 0, 0 + }; + + t.endidx = 6; + + if (0xffffff < setto->tv_sec) return -1; + tenms = setto->tv_sec * 100; + if (0xffffff < setto->tv_usec / 10000) return -1; + tenms += setto->tv_usec / 10000; + if (tenms > 0xffffff) return -1; + + tseq[1] = setcmd; + tseq[3] = (uint8_t)(tenms & 0xff); + tseq[4] = (uint8_t)((tenms >> 8) & 0xff); + tseq[5] = (uint8_t)((tenms >> 16) & 0xff); + + t.seq = tseq; + + if (hp_sdc_enqueue_transaction(&t)) { + return -1; + } + return 0; +} + +static loff_t hp_sdc_rtc_llseek(struct file *file, loff_t offset, int origin) +{ + return -ESPIPE; +} + +static ssize_t hp_sdc_rtc_read(struct file *file, char *buf, + size_t count, loff_t *ppos) { + ssize_t retval; + + if (count < sizeof(unsigned long)) + return -EINVAL; + + retval = put_user(68, (unsigned long *)buf); + return retval; +} + +static unsigned int hp_sdc_rtc_poll(struct file *file, poll_table *wait) +{ + unsigned long l; + + l = 0; + if (l != 0) + return POLLIN | POLLRDNORM; + return 0; +} + +static int hp_sdc_rtc_open(struct inode *inode, struct file *file) +{ + MOD_INC_USE_COUNT; + return 0; +} + +static int hp_sdc_rtc_release(struct inode *inode, struct file *file) +{ + /* Turn off interrupts? */ + + if (file->f_flags & FASYNC) { + hp_sdc_rtc_fasync (-1, file, 0); + } + + MOD_DEC_USE_COUNT; + return 0; +} + +static int hp_sdc_rtc_fasync (int fd, struct file *filp, int on) +{ + return fasync_helper (fd, filp, on, &hp_sdc_rtc_async_queue); +} + +static int hp_sdc_rtc_proc_output (char *buf) +{ +#define YN(bit) ("no") +#define NY(bit) ("yes") + char *p; + struct rtc_time tm; + struct timeval tv; + + memset(&tm, 0, sizeof(struct rtc_time)); + + p = buf; + + if (hp_sdc_rtc_read_bbrtc(&tm)) { + p += sprintf(p, "BBRTC\t\t: READ FAILED!\n"); + } else { + p += sprintf(p, + "rtc_time\t: %02d:%02d:%02d\n" + "rtc_date\t: %04d-%02d-%02d\n" + "rtc_epoch\t: %04lu\n", + tm.tm_hour, tm.tm_min, tm.tm_sec, + tm.tm_year + 1900, tm.tm_mon + 1, + tm.tm_mday, epoch); + } + + if (hp_sdc_rtc_read_rt(&tv)) { + p += sprintf(p, "i8042 rtc\t: READ FAILED!\n"); + } else { + p += sprintf(p, "i8042 rtc\t: %d.%02d seconds\n", + tv.tv_sec, tv.tv_usec/1000); + } + + if (hp_sdc_rtc_read_fhs(&tv)) { + p += sprintf(p, "handshake\t: READ FAILED!\n"); + } else { + p += sprintf(p, "handshake\t: %d.%02d seconds\n", + tv.tv_sec, tv.tv_usec/1000); + } + + if (hp_sdc_rtc_read_mt(&tv)) { + p += sprintf(p, "alarm\t\t: READ FAILED!\n"); + } else { + p += sprintf(p, "alarm\t\t: %d.%02d seconds\n", + tv.tv_sec, tv.tv_usec/1000); + } + + if (hp_sdc_rtc_read_dt(&tv)) { + p += sprintf(p, "delay\t\t: READ FAILED!\n"); + } else { + p += sprintf(p, "delay\t\t: %d.%02d seconds\n", + tv.tv_sec, tv.tv_usec/1000); + } + + if (hp_sdc_rtc_read_ct(&tv)) { + p += sprintf(p, "periodic\t: READ FAILED!\n"); + } else { + p += sprintf(p, "periodic\t: %d.%02d seconds\n", + tv.tv_sec, tv.tv_usec/1000); + } + + p += sprintf(p, + "DST_enable\t: %s\n" + "BCD\t\t: %s\n" + "24hr\t\t: %s\n" + "square_wave\t: %s\n" + "alarm_IRQ\t: %s\n" + "update_IRQ\t: %s\n" + "periodic_IRQ\t: %s\n" + "periodic_freq\t: %ld\n" + "batt_status\t: %s\n", + YN(RTC_DST_EN), + NY(RTC_DM_BINARY), + YN(RTC_24H), + YN(RTC_SQWE), + YN(RTC_AIE), + YN(RTC_UIE), + YN(RTC_PIE), + 1UL, + 1 ? "okay" : "dead"); + + return p - buf; +#undef YN +#undef NY +} + +static int hp_sdc_rtc_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len = hp_sdc_rtc_proc_output (page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + return len; +} + +static int hp_sdc_rtc_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ +#if 1 + return -EINVAL; +#else + + struct rtc_time wtime; + struct timeval ttime; + int use_wtime = 0; + + /* This needs major work. */ + + switch (cmd) { + + case RTC_AIE_OFF: /* Mask alarm int. enab. bit */ + case RTC_AIE_ON: /* Allow alarm interrupts. */ + case RTC_PIE_OFF: /* Mask periodic int. enab. bit */ + case RTC_PIE_ON: /* Allow periodic ints */ + case RTC_UIE_ON: /* Allow ints for RTC updates. */ + case RTC_UIE_OFF: /* Allow ints for RTC updates. */ + { + /* We cannot mask individual user timers and we + cannot tell them apart when they occur, so it + would be disingenuous to succeed these IOCTLs */ + return -EINVAL; + } + case RTC_ALM_READ: /* Read the present alarm time */ + { + if (hp_sdc_rtc_read_mt(&ttime)) return -EFAULT; + break; + } + case RTC_IRQP_READ: /* Read the periodic IRQ rate. */ + { + return put_user(hp_sdc_rtc_freq, (unsigned long *)arg); + } + case RTC_IRQP_SET: /* Set periodic IRQ rate. */ + { + /* + * The max we can do is 100Hz. + */ + + if ((arg < 1) || (arg > 100)) return -EINVAL; + ttime.tv_sec = 0; + ttime.tv_usec = 1000000 / arg; + if (hp_sdc_rtc_set_ct(&ttime)) return -EFAULT; + hp_sdc_rtc_freq = arg; + return 0; + } + case RTC_ALM_SET: /* Store a time into the alarm */ + { + /* + * This expects a struct hp_sdc_rtc_time. Writing 0xff means + * "don't care" or "match all" for PC timers. The HP SDC + * does not support that perk, but it could be emulated fairly + * easily. Only the tm_hour, tm_min and tm_sec are used. + * We could do it with 10ms accuracy with the HP SDC, if the + * rtc interface left us a way to do that. + */ + struct hp_sdc_rtc_time alm_tm; + + if (copy_from_user(&alm_tm, (struct hp_sdc_rtc_time*)arg, + sizeof(struct hp_sdc_rtc_time))) + return -EFAULT; + + if (alm_tm.tm_hour > 23) return -EINVAL; + if (alm_tm.tm_min > 59) return -EINVAL; + if (alm_tm.tm_sec > 59) return -EINVAL; + + ttime.sec = alm_tm.tm_hour * 3600 + + alm_tm.tm_min * 60 + alm_tm.tm_sec; + ttime.usec = 0; + if (hp_sdc_rtc_set_mt(&ttime)) return -EFAULT; + return 0; + } + case RTC_RD_TIME: /* Read the time/date from RTC */ + { + if (hp_sdc_rtc_read_bbrtc(&wtime)) return -EFAULT; + break; + } + case RTC_SET_TIME: /* Set the RTC */ + { + struct rtc_time hp_sdc_rtc_tm; + unsigned char mon, day, hrs, min, sec, leap_yr; + unsigned int yrs; + + if (!capable(CAP_SYS_TIME)) + return -EACCES; + if (copy_from_user(&hp_sdc_rtc_tm, (struct rtc_time *)arg, + sizeof(struct rtc_time))) + return -EFAULT; + + yrs = hp_sdc_rtc_tm.tm_year + 1900; + mon = hp_sdc_rtc_tm.tm_mon + 1; /* tm_mon starts at zero */ + day = hp_sdc_rtc_tm.tm_mday; + hrs = hp_sdc_rtc_tm.tm_hour; + min = hp_sdc_rtc_tm.tm_min; + sec = hp_sdc_rtc_tm.tm_sec; + + if (yrs < 1970) + return -EINVAL; + + leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400)); + + if ((mon > 12) || (day == 0)) + return -EINVAL; + if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr))) + return -EINVAL; + if ((hrs >= 24) || (min >= 60) || (sec >= 60)) + return -EINVAL; + + if ((yrs -= eH) > 255) /* They are unsigned */ + return -EINVAL; + + + return 0; + } + case RTC_epoch_READ: /* Read the epoch. */ + { + return put_user (epoch, (unsigned long *)arg); + } + case RTC_EPOCH_SET: /* Set the epoch. */ + { + /* + * There were no RTC clocks before 1900. + */ + if (arg < 1900) + return -EINVAL; + if (!capable(CAP_SYS_TIME)) + return -EACCES; + + epoch = arg; + return 0; + } + default: + return -EINVAL; + } + return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0; +#endif +} + +static struct file_operations hp_sdc_rtc_fops = { + owner: THIS_MODULE, + llseek: hp_sdc_rtc_llseek, + read: hp_sdc_rtc_read, + poll: hp_sdc_rtc_poll, + ioctl: hp_sdc_rtc_ioctl, + open: hp_sdc_rtc_open, + release: hp_sdc_rtc_release, + fasync: hp_sdc_rtc_fasync, +}; + +static struct miscdevice hp_sdc_rtc_dev = { + minor: RTC_MINOR, + name: "rtc", + fops: &hp_sdc_rtc_fops +}; + +static int __init hp_sdc_rtc_init(void) +{ + int ret; + + init_MUTEX(&i8042tregs); + + if ((ret = hp_sdc_request_timer_irq(&hp_sdc_rtc_isr))) + return ret; + misc_register(&hp_sdc_rtc_dev); + create_proc_read_entry ("driver/rtc", 0, 0, + hp_sdc_rtc_read_proc, NULL); + + printk(KERN_INFO "HP i8042 SDC + MSM-58321 RTC support loaded " + "(RTC v " RTC_VERSION ")\n"); + + return 0; +} + +static void __exit hp_sdc_rtc_exit(void) +{ + remove_proc_entry ("driver/rtc", NULL); + misc_deregister(&hp_sdc_rtc_dev); + hp_sdc_release_timer_irq(hp_sdc_rtc_isr); + printk(KERN_INFO "HP i8042 SDC + MSM-58321 RTC support unloaded\n"); +} + +module_init(hp_sdc_rtc_init); +module_exit(hp_sdc_rtc_exit); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/hil/Makefile linux.19rc3-ac4/drivers/hil/Makefile --- linux.19rc3/drivers/hil/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/hil/Makefile 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,39 @@ +# +# Makefile for the kernel HIL device drivers. +# +# 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 inherited from the +# parent makes.. +# + +O_TARGET := hil.o + +obj-y += + +# All of the (potential) objects that export symbols. +# This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'. +export-objs := hp_sdc.o hil_mlc.o + +mod-subdirs := + +list-multi := + + +obj-$(CONFIG_HIL_KBD_BASIC) += hilkbd.o + +obj-$(CONFIG_HP_SDC) += hp_sdc.o +obj-$(CONFIG_HP_SDC_MLC) += hp_sdc_mlc.o +obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o +obj-$(CONFIG_HIL_MLC) += hil_mlc.o + +obj-$(CONFIG_HIL_KBD) += hil_kbd.o +obj-$(CONFIG_HIL_PTR) += hil_ptr.o + + +include $(TOPDIR)/Rules.make + +fastdep: + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/hotplug/acpiphp_core.c linux.19rc3-ac4/drivers/hotplug/acpiphp_core.c --- linux.19rc3/drivers/hotplug/acpiphp_core.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/hotplug/acpiphp_core.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,470 @@ +/* + * ACPI PCI Hot Plug Controller Driver + * + * Copyright (c) 1995,2001 Compaq Computer Corporation + * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (c) 2001 IBM Corp. + * Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com) + * Copyright (c) 2002 Takayoshi Kochi (t-kouchi@cq.jp.nec.com) + * Copyright (c) 2002 NEC Corporation + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This 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, GOOD TITLE or + * NON INFRINGEMENT. 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. + * + * Send feedback to , + * , + * + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "pci_hotplug.h" +#include "acpiphp.h" + +static LIST_HEAD(slot_list); + +#if !defined(CONFIG_HOTPLUG_PCI_ACPI_MODULE) + #define MY_NAME "acpiphp" +#else + #define MY_NAME THIS_MODULE->name +#endif + +/* local variables */ +static int debug = 1; /* XXX set to 0 after debug */ +static int num_slots; + +#define DRIVER_VERSION "0.3" +#define DRIVER_AUTHOR "Greg Kroah-Hartman " +#define DRIVER_DESC "ACPI Hot Plug PCI Controller Driver" + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); +MODULE_PARM(debug, "i"); +MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); + +static int enable_slot (struct hotplug_slot *slot); +static int disable_slot (struct hotplug_slot *slot); +static int set_attention_status (struct hotplug_slot *slot, u8 value); +static int hardware_test (struct hotplug_slot *slot, u32 value); +static int get_power_status (struct hotplug_slot *slot, u8 *value); +static int get_attention_status (struct hotplug_slot *slot, u8 *value); +static int get_latch_status (struct hotplug_slot *slot, u8 *value); +static int get_adapter_status (struct hotplug_slot *slot, u8 *value); + +static struct hotplug_slot_ops acpi_hotplug_slot_ops = { + owner: THIS_MODULE, + enable_slot: enable_slot, + disable_slot: disable_slot, + set_attention_status: set_attention_status, + hardware_test: hardware_test, + get_power_status: get_power_status, + get_attention_status: get_attention_status, + get_latch_status: get_latch_status, + get_adapter_status: get_adapter_status, +}; + + +/* Inline functions to check the sanity of a pointer that is passed to us */ +static inline int slot_paranoia_check (struct slot *slot, const char *function) +{ + if (!slot) { + dbg("%s - slot == NULL", function); + return -1; + } + if (slot->magic != SLOT_MAGIC) { + dbg("%s - bad magic number for slot", function); + return -1; + } + if (!slot->hotplug_slot) { + dbg("%s - slot->hotplug_slot == NULL!", function); + return -1; + } + return 0; +} + + +static inline struct slot *get_slot (struct hotplug_slot *hotplug_slot, const char *function) +{ + struct slot *slot; + + if (!hotplug_slot) { + dbg("%s - hotplug_slot == NULL", function); + return NULL; + } + + slot = (struct slot *)hotplug_slot->private; + if (slot_paranoia_check (slot, function)) + return NULL; + return slot; +} + + +/** + * enable_slot - power on and enable a slot + * @hotplug_slot: slot to enable + * + * Actual tasks are done in acpiphp_enable_slot() + * + */ +static int enable_slot (struct hotplug_slot *hotplug_slot) +{ + struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + int retval = 0; + + if (slot == NULL) + return -ENODEV; + + dbg ("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); + + /* enable the specified slot */ + retval = acpiphp_enable_slot (slot->acpi_slot); + + return retval; +} + + +/** + * disable_slot - disable and power off a slot + * @hotplug_slot: slot to disable + * + * Actual tasks are done in acpiphp_disable_slot() + * + */ +static int disable_slot (struct hotplug_slot *hotplug_slot) +{ + struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + int retval = 0; + + if (slot == NULL) + return -ENODEV; + + dbg ("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); + + /* disable the specified slot */ + retval = acpiphp_disable_slot (slot->acpi_slot); + + return retval; +} + + +/** + * set_attention_status - set attention LED + * + * TBD: + * ACPI doesn't have known method to manipulate + * attention status LED. + * + */ +static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status) +{ + int retval = 0; + + dbg ("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); + + switch (status) { + case 0: + /* FIXME turn light off */ + hotplug_slot->info->attention_status = 0; + break; + + case 1: + default: + /* FIXME turn light on */ + hotplug_slot->info->attention_status = 1; + break; + } + + return retval; +} + + +/** + * hardware_test - hardware test + * + * We have nothing to do for now... + * + */ +static int hardware_test (struct hotplug_slot *hotplug_slot, u32 value) +{ + struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + int retval = 0; + + if (slot == NULL) + return -ENODEV; + + dbg ("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); + + err ("No hardware tests are defined for this driver"); + retval = -ENODEV; + + return retval; +} + + +/** + * get_power_status - get power status of a slot + * @hotplug_slot: slot to get status + * @value: pointer to store status + * + * Some platforms may not implement _STA method properly. + * In that case, the value returned may not be reliable. + * + */ +static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value) +{ + struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + int retval = 0; + + if (slot == NULL) + return -ENODEV; + + dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); + + *value = acpiphp_get_power_status (slot->acpi_slot); + + return retval; +} + + +/** + * get_attention_status - get attention LED status + * + * TBD: + * ACPI doesn't provide any formal means to access attention LED status. + * + */ +static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value) +{ + int retval = 0; + + dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); + + *value = hotplug_slot->info->attention_status; + + return retval; +} + + +/** + * get_latch_status - get latch status of a slot + * @hotplug_slot: slot to get status + * @value: pointer to store status + * + * ACPI doesn't provide any formal means to access latch status. + * Instead, we fake latch status from _STA + * + */ +static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value) +{ + struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + int retval = 0; + + if (slot == NULL) + return -ENODEV; + + dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); + + *value = acpiphp_get_latch_status (slot->acpi_slot); + + return retval; +} + + +/** + * get_adapter_status - get adapter status of a slot + * @hotplug_slot: slot to get status + * @value: pointer to store status + * + * ACPI doesn't provide any formal means to access adapter status. + * Instead, we fake adapter status from _STA + * + */ +static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) +{ + struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + int retval = 0; + + if (slot == NULL) + return -ENODEV; + + dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); + + *value = acpiphp_get_adapter_status (slot->acpi_slot); + + return retval; +} + + +static int init_acpi (void) +{ + int retval; + + /* initialize internal data structure etc. */ + retval = acpiphp_glue_init(); + + /* read initial number of slots */ + if (!retval) { + num_slots = acpiphp_get_num_slots(); + if (num_slots == 0) + retval = -ENODEV; + } + + return retval; +} + + +static void exit_acpi (void) +{ + /* deallocate internal data structures etc. */ + acpiphp_glue_exit(); +} + + +/** + * make_slot_name - make a slot name that appears in pcihpfs + * @slot: slot to name + * + */ +static void make_slot_name (struct slot *slot) +{ + snprintf (slot->hotplug_slot->name, SLOT_NAME_SIZE, "ACPI%x", slot->acpi_slot->sun); +} + +/** + * init_slots - initialize 'struct slot' structures for each slot + * + */ +static int init_slots (void) +{ + struct slot *slot; + int retval = 0; + int i; + + for (i = 0; i < num_slots; ++i) { + slot = kmalloc (sizeof (struct slot), GFP_KERNEL); + if (!slot) + return -ENOMEM; + memset(slot, 0, sizeof(struct slot)); + + slot->hotplug_slot = kmalloc (sizeof (struct hotplug_slot), GFP_KERNEL); + if (!slot->hotplug_slot) { + kfree (slot); + return -ENOMEM; + } + memset(slot->hotplug_slot, 0, sizeof (struct hotplug_slot)); + + slot->hotplug_slot->info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL); + if (!slot->hotplug_slot->info) { + kfree (slot->hotplug_slot); + kfree (slot); + return -ENOMEM; + } + memset(slot->hotplug_slot->info, 0, sizeof (struct hotplug_slot_info)); + + slot->hotplug_slot->name = kmalloc (SLOT_NAME_SIZE, GFP_KERNEL); + if (!slot->hotplug_slot->name) { + kfree (slot->hotplug_slot->info); + kfree (slot->hotplug_slot); + kfree (slot); + return -ENOMEM; + } + + slot->magic = SLOT_MAGIC; + slot->number = i; + + slot->hotplug_slot->private = slot; + slot->hotplug_slot->ops = &acpi_hotplug_slot_ops; + + slot->acpi_slot = get_slot_from_id (i); + slot->hotplug_slot->info->power_status = acpiphp_get_power_status(slot->acpi_slot); + slot->hotplug_slot->info->attention_status = acpiphp_get_attention_status(slot->acpi_slot); + slot->hotplug_slot->info->latch_status = acpiphp_get_latch_status(slot->acpi_slot); + slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot); + + make_slot_name (slot); + + retval = pci_hp_register (slot->hotplug_slot); + if (retval) { + err ("pci_hp_register failed with error %d", retval); + kfree (slot->hotplug_slot->info); + kfree (slot->hotplug_slot->name); + kfree (slot->hotplug_slot); + kfree (slot); + return retval; + } + + /* add slot to our internal list */ + list_add (&slot->slot_list, &slot_list); + } + + return retval; +} + + +static void cleanup_slots (void) +{ + struct list_head *tmp; + struct slot *slot; + + list_for_each (tmp, &slot_list) { + slot = list_entry (tmp, struct slot, slot_list); + list_del (&slot->slot_list); + pci_hp_deregister (slot->hotplug_slot); + kfree (slot->hotplug_slot->info); + kfree (slot->hotplug_slot->name); + kfree (slot->hotplug_slot); + kfree (slot); + } + + return; +} + + +static int __init acpiphp_init(void) +{ + int retval; + + /* read all the ACPI info from the system */ + retval = init_acpi(); + if (retval) + return retval; + + retval = init_slots(); + if (retval) + return retval; + + info (DRIVER_DESC " version: " DRIVER_VERSION); + return 0; +} + + +static void __exit acpiphp_exit(void) +{ + cleanup_slots(); + exit_acpi(); +} + +module_init(acpiphp_init); +module_exit(acpiphp_exit); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/hotplug/acpiphp_glue.c linux.19rc3-ac4/drivers/hotplug/acpiphp_glue.c --- linux.19rc3/drivers/hotplug/acpiphp_glue.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/hotplug/acpiphp_glue.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,1514 @@ +/* + * ACPI PCI HotPlug glue functions to ACPI CA subsystem + * + * Copyright (c) 2002 Takayoshi Kochi (t-kouchi@cq.jp.nec.com) + * Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com) + * Copyright (c) 2002 NEC Corporation + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This 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, GOOD TITLE or + * NON INFRINGEMENT. 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. + * + * Send feedback to + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "pci_hotplug.h" +#include "acpiphp.h" + +static LIST_HEAD(bridge_list); + +static int debug = 1; /* XXX set 0 after debug */ +#define MY_NAME "acpiphp_glue" + +static void handle_hotplug_event_bridge (acpi_handle, u32, void *); +static void handle_hotplug_event_func (acpi_handle, u32, void *); +static struct pci_ops *default_ops; + +/* + * initialization & terminatation routines + */ + +/** + * is_ejectable - determine if a slot is ejectable + * @handle: handle to acpi namespace + * + * Ejectable slot should satisfy at least these conditions: + * + * 1. has _ADR method + * 2. has _EJ0 method + * + * optionally + * + * 1. has _STA method + * 2. has _PS0 method + * 3. has _PS3 method + * 4. .. + * + */ +static int is_ejectable (acpi_handle handle) +{ + acpi_status status; + acpi_handle tmp; + + status = acpi_get_handle(handle, "_ADR", &tmp); + if (ACPI_FAILURE(status)) { + return 0; + } + + status = acpi_get_handle(handle, "_EJ0", &tmp); + if (ACPI_FAILURE(status)) { + return 0; + } + + return 1; +} + + +/* callback routine to check the existence of ejectable slots */ +static acpi_status +is_ejectable_slot (acpi_handle handle, u32 lvl, void *context, void **rv) +{ + acpi_status status; + acpi_handle tmp; + int *count = (int *)context; + + if (is_ejectable(handle)) { + (*count)++; + /* only one ejectable slot is enough */ + return AE_CTRL_TERMINATE; + } else { + return AE_OK; + } +} + + +/* callback routine to register each ACPI PCI slot object */ +static acpi_status +register_slot (acpi_handle handle, u32 lvl, void *context, void **rv) +{ + struct acpiphp_bridge *bridge = (struct acpiphp_bridge *)context; + struct acpiphp_slot *slot; + struct acpiphp_func *newfunc; + acpi_handle tmp; + acpi_status status = AE_OK; + unsigned long adr, sun; + int device, function; + static int num_slots = 0; /* XXX if we support I/O node hotplug... */ + + status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); + + if (ACPI_FAILURE(status)) + return AE_OK; + + status = acpi_get_handle(handle, "_EJ0", &tmp); + + if (ACPI_FAILURE(status)) + return AE_OK; + + device = (adr >> 16) & 0xffff; + function = adr & 0xffff; + + newfunc = kmalloc(sizeof(struct acpiphp_func), GFP_KERNEL); + if (!newfunc) + return AE_NO_MEMORY; + memset(newfunc, 0, sizeof(struct acpiphp_func)); + + INIT_LIST_HEAD(&newfunc->sibling); + newfunc->handle = handle; + newfunc->function = function; + newfunc->flags = FUNC_HAS_EJ0; + + if (ACPI_SUCCESS(acpi_get_handle(handle, "_STA", &tmp))) + newfunc->flags |= FUNC_HAS_STA; + + if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS0", &tmp))) + newfunc->flags |= FUNC_HAS_PS0; + + if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS3", &tmp))) + newfunc->flags |= FUNC_HAS_PS3; + + status = acpi_evaluate_integer(handle, "_SUN", NULL, &sun); + if (ACPI_FAILURE(status)) + sun = -1; + + /* search for objects that share the same slot */ + for (slot = bridge->slots; slot; slot = slot->next) + if (slot->device == device) { + if (slot->sun != sun) + warn("sibling found, but _SUN doesn't match!"); + break; + } + + if (!slot) { + slot = kmalloc(sizeof(struct acpiphp_slot), GFP_KERNEL); + if (!slot) { + kfree(newfunc); + return AE_NO_MEMORY; + } + + memset(slot, 0, sizeof(struct acpiphp_slot)); + slot->bridge = bridge; + slot->id = num_slots++; + slot->device = device; + slot->sun = sun; + INIT_LIST_HEAD(&slot->funcs); + init_MUTEX(&slot->crit_sect); + + slot->next = bridge->slots; + bridge->slots = slot; + + bridge->nr_slots++; + + dbg("found ACPI PCI Hotplug slot at PCI %02x:%02x Slot:%d", + slot->bridge->bus, slot->device, slot->sun); + } + + newfunc->slot = slot; + list_add_tail(&newfunc->sibling, &slot->funcs); + + /* associate corresponding pci_dev */ + newfunc->pci_dev = pci_find_slot(bridge->bus, + PCI_DEVFN(device, function)); + if (newfunc->pci_dev) { + if (acpiphp_init_func_resource(newfunc) < 0) { + kfree(newfunc); + return AE_ERROR; + } + slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON); + } + + /* install notify handler */ + status = acpi_install_notify_handler(handle, + ACPI_SYSTEM_NOTIFY, + handle_hotplug_event_func, + newfunc); + + if (ACPI_FAILURE(status)) { + err("failed to register interrupt notify handler"); + return status; + } + + return AE_OK; +} + + +/* see if it's worth looking at this bridge */ +static int detect_ejectable_slots (acpi_handle *bridge_handle) +{ + acpi_status status; + int count; + + count = 0; + + /* only check slots defined directly below bridge object */ + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge_handle, (u32)1, + is_ejectable_slot, (void *)&count, NULL); + + return count; +} + + +/* decode ACPI _CRS data and convert into our internal resource list + * TBD: _TRA, etc. + */ +static void +decode_acpi_resource (acpi_resource *resource, struct acpiphp_bridge *bridge) +{ + acpi_resource_address16 *address16_data; + acpi_resource_address32 *address32_data; + acpi_resource_address64 *address64_data; + struct pci_resource *res; + + u32 resource_type, producer_consumer, address_length; + u64 min_address_range, max_address_range; + u16 cache_attribute = 0; + + int done = 0, found; + + /* shut up gcc */ + resource_type = producer_consumer = address_length = 0; + min_address_range = max_address_range = 0; + + while (!done) { + found = 0; + + switch (resource->id) { + case ACPI_RSTYPE_ADDRESS16: + address16_data = (acpi_resource_address16 *)&resource->data; + resource_type = address16_data->resource_type; + producer_consumer = address16_data->producer_consumer; + min_address_range = address16_data->min_address_range; + max_address_range = address16_data->max_address_range; + address_length = address16_data->address_length; + if (resource_type == ACPI_MEMORY_RANGE) + cache_attribute = address16_data->attribute.memory.cache_attribute; + found = 1; + break; + + case ACPI_RSTYPE_ADDRESS32: + address32_data = (acpi_resource_address32 *)&resource->data; + resource_type = address32_data->resource_type; + producer_consumer = address32_data->producer_consumer; + min_address_range = address32_data->min_address_range; + max_address_range = address32_data->max_address_range; + address_length = address32_data->address_length; + if (resource_type == ACPI_MEMORY_RANGE) + cache_attribute = address32_data->attribute.memory.cache_attribute; + found = 1; + break; + + case ACPI_RSTYPE_ADDRESS64: + address64_data = (acpi_resource_address64 *)&resource->data; + resource_type = address64_data->resource_type; + producer_consumer = address64_data->producer_consumer; + min_address_range = address64_data->min_address_range; + max_address_range = address64_data->max_address_range; + address_length = address64_data->address_length; + if (resource_type == ACPI_MEMORY_RANGE) + cache_attribute = address64_data->attribute.memory.cache_attribute; + found = 1; + break; + + case ACPI_RSTYPE_END_TAG: + done = 1; + break; + + default: + /* ignore */ + break; + } + + resource = (acpi_resource *)((char*)resource + resource->length); + + if (found && producer_consumer == ACPI_PRODUCER && address_length > 0) { + switch (resource_type) { + case ACPI_MEMORY_RANGE: + if (cache_attribute == ACPI_PREFETCHABLE_MEMORY) { + dbg("resource type: prefetchable memory 0x%x - 0x%x", (u32)min_address_range, (u32)max_address_range); + res = acpiphp_make_resource(min_address_range, + address_length); + if (!res) { + err("out of memory"); + return; + } + res->next = bridge->p_mem_head; + bridge->p_mem_head = res; + } else { + dbg("resource type: memory 0x%x - 0x%x", (u32)min_address_range, (u32)max_address_range); + res = acpiphp_make_resource(min_address_range, + address_length); + if (!res) { + err("out of memory"); + return; + } + res->next = bridge->mem_head; + bridge->mem_head = res; + } + break; + case ACPI_IO_RANGE: + dbg("resource type: io 0x%x - 0x%x", (u32)min_address_range, (u32)max_address_range); + res = acpiphp_make_resource(min_address_range, + address_length); + if (!res) { + err("out of memory"); + return; + } + res->next = bridge->io_head; + bridge->io_head = res; + break; + case ACPI_BUS_NUMBER_RANGE: + dbg("resource type: bus number %d - %d", (u32)min_address_range, (u32)max_address_range); + res = acpiphp_make_resource(min_address_range, + address_length); + if (!res) { + err("out of memory"); + return; + } + res->next = bridge->bus_head; + bridge->bus_head = res; + break; + default: + /* invalid type */ + break; + } + } + } + + acpiphp_resource_sort_and_combine(&bridge->io_head); + acpiphp_resource_sort_and_combine(&bridge->mem_head); + acpiphp_resource_sort_and_combine(&bridge->p_mem_head); + acpiphp_resource_sort_and_combine(&bridge->bus_head); +#if 1 + info("ACPI _CRS resource:"); + acpiphp_dump_resource(bridge); +#endif +} + + +/* find pci_bus structure associated to specific bus number */ +static struct pci_bus *find_pci_bus(const struct list_head *list, int bus) +{ + const struct list_head *l; + + list_for_each(l, list) { + struct pci_bus *b = pci_bus_b(l); + if (b->number == bus) + return b; + + if (!list_empty(&b->children)) { + /* XXX recursive call */ + b = find_pci_bus(&b->children, bus); + + if (b) + return b; + } + } + + return 0; +} + + +/* decode ACPI 2.0 _HPP hot plug parameters */ +static void decode_hpp(struct acpiphp_bridge *bridge) +{ + acpi_status status; +#if ACPI_CA_VERSION < 0x20020201 + acpi_buffer buffer; +#else + acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; +#endif + acpi_object *package; + int i; + + /* default numbers */ + bridge->hpp.cache_line_size = 0x10; + bridge->hpp.latency_timer = 0x40; + bridge->hpp.enable_SERR = 0; + bridge->hpp.enable_PERR = 0; + +#if ACPI_CA_VERSION < 0x20020201 + buffer.length = 0; + buffer.pointer = NULL; + + status = acpi_evaluate_object(bridge->handle, "_HPP", NULL, &buffer); + + if (status == AE_BUFFER_OVERFLOW) { + buffer.pointer = kmalloc(buffer.length, GFP_KERNEL); + if (!buffer.pointer) + return; + status = acpi_evaluate_object(bridge->handle, "_HPP", NULL, &buffer); + } +#else + status = acpi_evaluate_object(bridge->handle, "_HPP", NULL, &buffer); +#endif + + if (ACPI_FAILURE(status)) { + dbg("_HPP evaluation failed"); + return; + } + + package = (acpi_object *) buffer.pointer; + + if (!package || package->type != ACPI_TYPE_PACKAGE || + package->package.count != 4 || !package->package.elements) { + err("invalid _HPP object; ignoring"); + goto err_exit; + } + + for (i = 0; i < 4; i++) { + if (package->package.elements[i].type != ACPI_TYPE_INTEGER) { + err("invalid _HPP parameter type; ignoring"); + goto err_exit; + } + } + + bridge->hpp.cache_line_size = package->package.elements[0].integer.value; + bridge->hpp.latency_timer = package->package.elements[1].integer.value; + bridge->hpp.enable_SERR = package->package.elements[2].integer.value; + bridge->hpp.enable_PERR = package->package.elements[3].integer.value; + + dbg("_HPP parameter = (%02x, %02x, %02x, %02x)", + bridge->hpp.cache_line_size, + bridge->hpp.latency_timer, + bridge->hpp.enable_SERR, + bridge->hpp.enable_PERR); + + bridge->flags |= BRIDGE_HAS_HPP; + + err_exit: + kfree(buffer.pointer); +} + + +/* initialize miscellaneous stuff for both root and PCI-to-PCI bridge */ +static void init_bridge_misc (struct acpiphp_bridge *bridge) +{ + acpi_status status; + + /* decode ACPI 2.0 _HPP (hot plug parameters) */ + decode_hpp(bridge); + + /* subtract all resources already allocated */ + acpiphp_detect_pci_resource(bridge); + + /* register all slot objects under this bridge */ + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1, + register_slot, bridge, NULL); + + /* install notify handler */ + status = acpi_install_notify_handler(bridge->handle, + ACPI_SYSTEM_NOTIFY, + handle_hotplug_event_bridge, + bridge); + + if (ACPI_FAILURE(status)) { + err("failed to register interrupt notify handler"); + } + + list_add(&bridge->list, &bridge_list); + +#if 1 + dbg("Bridge resource:"); + acpiphp_dump_resource(bridge); +#endif +} + + +/* allocate and initialize host bridge data structure */ +static void add_host_bridge (acpi_handle *handle, int seg, int bus) +{ + acpi_status status; +#if ACPI_CA_VERSION < 0x20020201 + acpi_buffer buffer; +#else + acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; +#endif + struct acpiphp_bridge *bridge; + + bridge = kmalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); + if (bridge == NULL) + return; + + memset(bridge, 0, sizeof(struct acpiphp_bridge)); + + bridge->type = BRIDGE_TYPE_HOST; + bridge->handle = handle; + bridge->seg = seg; + bridge->bus = bus; + + bridge->pci_bus = find_pci_bus(&pci_root_buses, bus); + bridge->pci_ops = bridge->pci_bus->ops; + + bridge->res_lock = SPIN_LOCK_UNLOCKED; + + /* to be overridden when we decode _CRS */ + bridge->sub = bridge->bus; + + /* decode resources */ + +#if ACPI_CA_VERSION < 0x20020201 + buffer.length = 0; + buffer.pointer = NULL; + + status = acpi_get_current_resources(handle, &buffer); + + if (status == AE_BUFFER_OVERFLOW) { + buffer.pointer = kmalloc(buffer.length, GFP_KERNEL); + if (!buffer.pointer) + return; + status = acpi_get_current_resources(handle, &buffer); + } +#else + status = acpi_get_current_resources(handle, &buffer); +#endif + + if (ACPI_FAILURE(status)) { + err("failed to decode bridge resources"); + kfree(bridge); + return; + } + + decode_acpi_resource(buffer.pointer, bridge); + kfree(buffer.pointer); + + if (bridge->bus_head) { + bridge->bus = bridge->bus_head->base; + bridge->sub = bridge->bus_head->base + bridge->bus_head->length - 1; + } + + init_bridge_misc(bridge); +} + + +/* allocate and initialize PCI-to-PCI bridge data structure */ +static void add_p2p_bridge (acpi_handle *handle, int seg, int bus, int dev, int fn) +{ + acpi_status status; + struct acpiphp_bridge *bridge; + u8 tmp8; + u16 tmp16; + u32 tmp; + u64 base64, limit64; + u32 base, limit, base32u, limit32u; + + bridge = kmalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); + if (bridge == NULL) { + err("out of memory"); + return; + } + + memset(bridge, 0, sizeof(struct acpiphp_bridge)); + + bridge->type = BRIDGE_TYPE_P2P; + bridge->handle = handle; + bridge->seg = seg; + + bridge->pci_dev = pci_find_slot(bus, PCI_DEVFN(dev, fn)); + if (!bridge->pci_dev) { + err("Can't get pci_dev"); + kfree(bridge); + return; + } + + bridge->pci_bus = bridge->pci_dev->subordinate; + if (!bridge->pci_bus) { + err("This is not a PCI-to-PCI bridge!"); + kfree(bridge); + return; + } + bridge->pci_ops = bridge->pci_bus->ops; + + bridge->res_lock = SPIN_LOCK_UNLOCKED; + + bridge->bus = bridge->pci_bus->number; + bridge->sub = bridge->pci_bus->subordinate; + + /* + * decode resources under this P2P bridge + */ + + /* I/O resources */ + pci_read_config_byte(bridge->pci_dev, PCI_IO_BASE, &tmp8); + base = tmp8; + pci_read_config_byte(bridge->pci_dev, PCI_IO_LIMIT, &tmp8); + limit = tmp8; + + switch (base & PCI_IO_RANGE_TYPE_MASK) { + case PCI_IO_RANGE_TYPE_16: + base = (base << 8) & 0xf000; + limit = ((limit << 8) & 0xf000) + 0xfff; + bridge->io_head = acpiphp_make_resource((u64)base, limit - base + 1); + if (!bridge->io_head) { + err("out of memory"); + return; + } + dbg("16bit I/O range: %04x-%04x", + (u32)bridge->io_head->base, + (u32)(bridge->io_head->base + bridge->io_head->length - 1)); + break; + case PCI_IO_RANGE_TYPE_32: + pci_read_config_word(bridge->pci_dev, PCI_IO_BASE_UPPER16, &tmp16); + base = ((u32)tmp16 << 16) | ((base << 8) & 0xf000); + pci_read_config_word(bridge->pci_dev, PCI_IO_LIMIT_UPPER16, &tmp16); + limit = (((u32)tmp16 << 16) | ((limit << 8) & 0xf000)) + 0xfff; + bridge->io_head = acpiphp_make_resource((u64)base, limit - base + 1); + if (!bridge->io_head) { + err("out of memory"); + return; + } + dbg("32bit I/O range: %08x-%08x", + (u32)bridge->io_head->base, + (u32)(bridge->io_head->base + bridge->io_head->length - 1)); + break; + case 0x0f: + dbg("I/O space unsupported"); + break; + default: + warn("Unknown I/O range type"); + } + + /* Memory resources (mandatory for P2P bridge) */ + pci_read_config_word(bridge->pci_dev, PCI_MEMORY_BASE, &tmp16); + base = (tmp16 & 0xfff0) << 16; + pci_read_config_word(bridge->pci_dev, PCI_MEMORY_LIMIT, &tmp16); + limit = ((tmp16 & 0xfff0) << 16) | 0xfffff; + bridge->mem_head = acpiphp_make_resource((u64)base, limit - base + 1); + if (!bridge->mem_head) { + err("out of memory"); + return; + } + dbg("32bit Memory range: %08x-%08x", + (u32)bridge->mem_head->base, + (u32)(bridge->mem_head->base + bridge->mem_head->length-1)); + + /* Prefetchable Memory resources (optional) */ + pci_read_config_word(bridge->pci_dev, PCI_PREF_MEMORY_BASE, &tmp16); + base = tmp16; + pci_read_config_word(bridge->pci_dev, PCI_PREF_MEMORY_LIMIT, &tmp16); + limit = tmp16; + + switch (base & PCI_MEMORY_RANGE_TYPE_MASK) { + case PCI_PREF_RANGE_TYPE_32: + base = (base & 0xfff0) << 16; + limit = ((limit & 0xfff0) << 16) | 0xfffff; + bridge->p_mem_head = acpiphp_make_resource((u64)base, limit - base + 1); + if (!bridge->p_mem_head) { + err("out of memory"); + return; + } + dbg("32bit Prefetchable memory range: %08x-%08x", + (u32)bridge->p_mem_head->base, + (u32)(bridge->p_mem_head->base + bridge->p_mem_head->length - 1)); + break; + case PCI_PREF_RANGE_TYPE_64: + pci_read_config_dword(bridge->pci_dev, PCI_PREF_BASE_UPPER32, &base32u); + pci_read_config_dword(bridge->pci_dev, PCI_PREF_LIMIT_UPPER32, &limit32u); + base64 = ((u64)base32u << 32) | ((base & 0xfff0) << 16); + limit64 = (((u64)limit32u << 32) | ((limit & 0xfff0) << 16)) + 0xfffff; + + bridge->p_mem_head = acpiphp_make_resource(base64, limit64 - base64 + 1); + if (!bridge->p_mem_head) { + err("out of memory"); + return; + } + dbg("64bit Prefetchable memory range: %08x%08x-%08x%08x", + (u32)(bridge->p_mem_head->base >> 32), + (u32)(bridge->p_mem_head->base & 0xffffffff), + (u32)((bridge->p_mem_head->base + bridge->p_mem_head->length - 1) >> 32), + (u32)((bridge->p_mem_head->base + bridge->p_mem_head->length - 1) & 0xffffffff)); + break; + case 0x0f: + break; + default: + warn("Unknown prefetchale memory type"); + } + + init_bridge_misc(bridge); +} + + +/* callback routine to find P2P bridges */ +static acpi_status +find_p2p_bridge (acpi_handle handle, u32 lvl, void *context, void **rv) +{ + acpi_status status; + acpi_handle dummy_handle; + unsigned long *segbus = context; + unsigned long tmp; + int seg, bus, device, function; + struct pci_dev *dev; + u32 val; + + /* get PCI address */ + seg = (*segbus >> 8) & 0xff; + bus = *segbus & 0xff; + + status = acpi_get_handle(handle, "_ADR", &dummy_handle); + if (ACPI_FAILURE(status)) + return AE_OK; /* continue */ + + status = acpi_evaluate_integer(handle, "_ADR", NULL, &tmp); + if (ACPI_FAILURE(status)) { + dbg("%s: _ADR evaluation failure", __FUNCTION__); + return AE_OK; + } + + device = (tmp >> 16) & 0xffff; + function = tmp & 0xffff; + + dev = pci_find_slot(bus, PCI_DEVFN(device, function)); + + if (!dev) + return AE_OK; + + if (!dev->subordinate) + return AE_OK; + + /* check if this bridge has ejectable slots */ + if (detect_ejectable_slots(handle) > 0) { + dbg("found PCI-to-PCI bridge at PCI %02x:%02x.%d", bus, device, function); + add_p2p_bridge(handle, seg, bus, device, function); + } + + return AE_OK; +} + + +/* find hot-pluggable slots, and then find P2P bridge */ +static int add_bridges (acpi_handle *handle) +{ + acpi_status status; + unsigned long tmp; + int seg, bus; + acpi_handle dummy_handle; + int sta = -1; + + /* if the bridge doesn't have _STA, we assume it is always there */ + status = acpi_get_handle(handle, "_STA", &dummy_handle); + if (ACPI_SUCCESS(status)) { + status = acpi_evaluate_integer(handle, "_STA", NULL, &tmp); + if (ACPI_FAILURE(status)) { + dbg("%s: _STA evaluation failure", __FUNCTION__); + return 0; + } + if ((tmp & ACPI_STA_FUNCTIONING) == 0) + /* don't register this object */ + return 0; + } + + /* get PCI segment number */ + status = acpi_evaluate_integer(handle, "_SEG", NULL, &tmp); + + seg = ACPI_SUCCESS(status) ? tmp : 0; + + /* get PCI bus number */ + status = acpi_evaluate_integer(handle, "_BBN", NULL, &tmp); + + if (ACPI_SUCCESS(status)) { + bus = tmp; + } else { + warn("can't get bus number, assuming 0"); + bus = 0; + } + + /* check if this bridge has ejectable slots */ + if (detect_ejectable_slots(handle) > 0) { + dbg("found PCI host-bus bridge with hot-pluggable slots"); + add_host_bridge(handle, seg, bus); + return 0; + } + + tmp = seg << 8 | bus; + + /* search P2P bridges under this host bridge */ + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, + find_p2p_bridge, &tmp, NULL); + + if (ACPI_FAILURE(status)) + warn("find_p2p_bridge faied (error code = 0x%x)",status); + + return 0; +} + + +/* callback routine to enumerate all the bridges in ACPI namespace */ +static acpi_status +find_host_bridge (acpi_handle handle, u32 lvl, void *context, void **rv) +{ + acpi_status status; + acpi_device_info info; + char objname[5]; + acpi_buffer buffer = { sizeof(objname), objname }; + + status = acpi_get_object_info(handle, &info); + if (ACPI_FAILURE(status)) { + dbg("%s: failed to get bridge information", __FUNCTION__); + return AE_OK; /* continue */ + } + + info.hardware_id[sizeof(info.hardware_id)-1] = '\0'; + + /* TBD check _CID also */ + if (strcmp(info.hardware_id, ACPI_PCI_HOST_HID) == 0) { + + acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer); + dbg("checking PCI-hotplug capable bridges under [%s]", objname); + add_bridges(handle); + } + return AE_OK; +} + + +static int power_on_slot (struct acpiphp_slot *slot) +{ + acpi_status status; + struct acpiphp_func *func; + struct list_head *l; + int retval = 0; + + /* is this already enabled? */ + if (slot->flags & SLOT_POWEREDON) + goto err_exit; + + list_for_each(l, &slot->funcs) { + func = list_entry(l, struct acpiphp_func, sibling); + + if (func->flags & FUNC_HAS_PS0) { + dbg("%s: executing _PS0 on %02x:%02x.%d", __FUNCTION__, + slot->bridge->bus, slot->device, func->function); + status = acpi_evaluate_object(func->handle, "_PS0", NULL, NULL); + if (ACPI_FAILURE(status)) { + warn("%s: _PS0 failed", __FUNCTION__); + retval = -1; + goto err_exit; + } + } + } + + /* TBD: evaluate _STA to check if the slot is enabled */ + + slot->flags |= SLOT_POWEREDON; + + err_exit: + return retval; +} + + +static int power_off_slot (struct acpiphp_slot *slot) +{ + acpi_status status; + struct acpiphp_func *func; + struct list_head *l; + acpi_object_list arg_list; + acpi_object arg; + + int retval = 0; + + /* is this already enabled? */ + if ((slot->flags & SLOT_POWEREDON) == 0) + goto err_exit; + + list_for_each(l, &slot->funcs) { + func = list_entry(l, struct acpiphp_func, sibling); + + if (func->flags & FUNC_HAS_PS3) { + dbg("%s: executing _PS3 on %02x:%02x.%d", __FUNCTION__, + slot->bridge->bus, slot->device, func->function); + status = acpi_evaluate_object(func->handle, "_PS3", NULL, NULL); + if (ACPI_FAILURE(status)) { + warn("%s: _PS3 failed", __FUNCTION__); + retval = -1; + goto err_exit; + } + } + } + + list_for_each(l, &slot->funcs) { + func = list_entry(l, struct acpiphp_func, sibling); + + if (func->flags & FUNC_HAS_EJ0) { + dbg("%s: executing _EJ0 on %02x:%02x.%d", __FUNCTION__, + slot->bridge->bus, slot->device, func->function); + + /* _EJ0 method take one argument */ + arg_list.count = 1; + arg_list.pointer = &arg; + arg.type = ACPI_TYPE_INTEGER; + arg.integer.value = 1; + + status = acpi_evaluate_object(func->handle, "_EJ0", &arg_list, NULL); + if (ACPI_FAILURE(status)) { + warn("%s: _EJ0 failed", __FUNCTION__); + retval = -1; + goto err_exit; + } + } + } + + /* TBD: evaluate _STA to check if the slot is disabled */ + + slot->flags &= (~SLOT_POWEREDON); + + err_exit: + return retval; +} + + +/** + * enable_device - enable, configure a slot + * @slot: slot to be enabled + * + * This function should be called per *physical slot*, + * not per each slot object in ACPI namespace. + * + */ +static int enable_device (struct acpiphp_slot *slot) +{ + acpi_status status; + u8 bus; + struct pci_dev dev0, *dev; + struct pci_bus *child; + struct list_head *l; + struct acpiphp_func *func; + int retval = 0; + + if (slot->flags & SLOT_ENABLED) + goto err_exit; + + /* sanity check: dev should be NULL when hot-plugged in */ + dev = pci_find_slot(slot->bridge->bus, PCI_DEVFN(slot->device, 0)); + if (dev) { + /* This case shouldn't happen */ + err("pci_dev structure already exists."); + retval = -1; + goto err_exit; + } + + /* allocate resources to device */ + retval = acpiphp_configure_slot(slot); + if (retval) + goto err_exit; + + memset(&dev0, 0, sizeof (struct pci_dev)); + + dev0.bus = slot->bridge->pci_bus; + dev0.devfn = PCI_DEVFN(slot->device, 0); + dev0.sysdata = dev0.bus->sysdata; + + /* returned `dev' is the *first function* only! */ + dev = pci_scan_slot (&dev0); + + if (!dev) { + err("No new device found"); + retval = -1; + goto err_exit; + } + + if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { + pci_read_config_byte(dev, PCI_SECONDARY_BUS, &bus); + child = (struct pci_bus*) pci_add_new_bus(dev->bus, dev, bus); + pci_do_scan_bus(child); + } + + /* associate pci_dev to our representation */ + list_for_each(l, &slot->funcs) { + func = list_entry(l, struct acpiphp_func, sibling); + + func->pci_dev = pci_find_slot(slot->bridge->bus, + PCI_DEVFN(slot->device, + func->function)); + if (!func->pci_dev) + continue; + + /* configure device */ + retval = acpiphp_configure_function(func); + if (retval) + goto err_exit; + } + + slot->flags |= SLOT_ENABLED; + +#if 1 + dbg("Available resources:"); + acpiphp_dump_resource(slot->bridge); +#endif + + err_exit: + return retval; +} + + +/** + * disable_device - disable a slot + */ +static int disable_device (struct acpiphp_slot *slot) +{ + int retval = 0; + struct acpiphp_func *func; + struct list_head *l; + acpi_status status; + + /* is this slot already disabled? */ + if (!(slot->flags & SLOT_ENABLED)) + goto err_exit; + + list_for_each(l, &slot->funcs) { + func = list_entry(l, struct acpiphp_func, sibling); + + if (func->pci_dev) { + if (acpiphp_unconfigure_function(func) == 0) { + func->pci_dev = NULL; + } else { + err("failed to unconfigure device"); + retval = -1; + goto err_exit; + } + } + } + + slot->flags &= (~SLOT_ENABLED); + + err_exit: + return retval; +} + + +/** + * get_slot_status - get ACPI slot status + * + * if a slot has _STA for each function and if any one of them + * returned non-zero status, return it + * + * if a slot doesn't have _STA and if any one of its functions' + * configuration space is configured, return 0x0f as a _STA + * + * otherwise return 0 + */ +static unsigned int get_slot_status (struct acpiphp_slot *slot) +{ + acpi_status status; + unsigned long sta = 0; + int fn; + u32 dvid; + struct list_head *l; + struct acpiphp_func *func; + + list_for_each(l, &slot->funcs) { + func = list_entry(l, struct acpiphp_func, sibling); + + if (func->flags & FUNC_HAS_STA) { + status = acpi_evaluate_integer(func->handle, "_STA", NULL, &sta); + if (ACPI_SUCCESS(status) && sta) + break; + } else { + pci_read_config_dword_nodev(default_ops, + slot->bridge->bus, + slot->device, + func->function, + PCI_VENDOR_ID, &dvid); + if (dvid != 0xffffffff) { + sta = ACPI_STA_ALL; + break; + } + } + } + + return (unsigned int)sta; +} + + +/* + * ACPI event handlers + */ + +/** + * handle_hotplug_event_bridge - handle ACPI event on bridges + * + * @handle: Notify()'ed acpi_handle + * @type: Notify code + * @context: pointer to acpiphp_bridge structure + * + * handles ACPI event notification on {host,p2p} bridges + * + */ +static void handle_hotplug_event_bridge (acpi_handle handle, u32 type, void *context) +{ + struct acpiphp_bridge *bridge; + char objname[64]; + acpi_buffer buffer = { sizeof(objname), objname }; + + bridge = (struct acpiphp_bridge *)context; + + acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); + + switch (type) { + case ACPI_NOTIFY_BUS_CHECK: + /* bus re-enumerate */ + dbg("%s: Bus check notify on %s", __FUNCTION__, objname); + acpiphp_check_bridge(bridge); + break; + + case ACPI_NOTIFY_DEVICE_CHECK: + /* device check */ + dbg("%s: Device check notify on %s", __FUNCTION__, objname); + acpiphp_check_bridge(bridge); + break; + + case ACPI_NOTIFY_DEVICE_WAKE: + /* wake event */ + dbg("%s: Device wake notify on %s", __FUNCTION__, objname); + break; + + case ACPI_NOTIFY_EJECT_REQUEST: + /* request device eject */ + dbg("%s: Device eject notify on %s", __FUNCTION__, objname); + break; + + default: + warn("notify_handler: unknown event type 0x%x for %s", type, objname); + break; + } +} + + +/** + * handle_hotplug_event_func - handle ACPI event on functions (i.e. slots) + * + * @handle: Notify()'ed acpi_handle + * @type: Notify code + * @context: pointer to acpiphp_func structure + * + * handles ACPI event notification on slots + * + */ +static void handle_hotplug_event_func (acpi_handle handle, u32 type, void *context) +{ + struct acpiphp_func *func; + char objname[64]; + acpi_buffer buffer = { sizeof(objname), objname }; + + acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); + + func = (struct acpiphp_func *)context; + + switch (type) { + case ACPI_NOTIFY_BUS_CHECK: + /* bus re-enumerate */ + dbg("%s: Bus check notify on %s", __FUNCTION__, objname); + acpiphp_enable_slot(func->slot); + break; + + case ACPI_NOTIFY_DEVICE_CHECK: + /* device check : re-enumerate from parent bus */ + dbg("%s: Device check notify on %s", __FUNCTION__, objname); + acpiphp_check_bridge(func->slot->bridge); + break; + + case ACPI_NOTIFY_DEVICE_WAKE: + /* wake event */ + dbg("%s: Device wake notify on %s", __FUNCTION__, objname); + break; + + case ACPI_NOTIFY_EJECT_REQUEST: + /* request device eject */ + dbg("%s: Device eject notify on %s", __FUNCTION__, objname); + acpiphp_disable_slot(func->slot); + break; + + default: + warn("notify_handler: unknown event type 0x%x for %s", type, objname); + break; + } +} + + +/** + * acpiphp_glue_init - initializes all PCI hotplug - ACPI glue data structures + * + */ +int acpiphp_glue_init (void) +{ + acpi_status status; + + if (list_empty(&pci_root_buses)) + return -1; + + /* set default pci_ops for configuration space operation */ + default_ops = pci_bus_b(pci_root_buses.next)->ops; + if (!default_ops) + return -1; + + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, find_host_bridge, + NULL, NULL); + + if (ACPI_FAILURE(status)) { + err("%s: acpi_walk_namespace() failed", __FUNCTION__); + return -1; + } + + return 0; +} + + +/** + * acpiphp_glue_exit - terminates all PCI hotplug - ACPI glue data structures + * + * This function frees all data allocated in acpiphp_glue_init() + */ +void acpiphp_glue_exit (void) +{ + struct list_head *node, *shead, *l, *n; + struct acpiphp_bridge *bridge; + struct acpiphp_slot *slot, *next; + struct acpiphp_func *func; + acpi_status status; + + list_for_each(node, &bridge_list) { + bridge = (struct acpiphp_bridge *)node; + slot = bridge->slots; + while (slot) { + next = slot->next; + list_for_each_safe(l, n, &slot->funcs) { + func = list_entry(l, struct acpiphp_func, sibling); + acpiphp_free_resource(&func->io_head); + acpiphp_free_resource(&func->mem_head); + acpiphp_free_resource(&func->p_mem_head); + acpiphp_free_resource(&func->bus_head); + status = acpi_remove_notify_handler(func->handle, + ACPI_SYSTEM_NOTIFY, + handle_hotplug_event_func); + if (ACPI_FAILURE(status)) + err("failed to remove notify handler"); + kfree(func); + } + kfree(slot); + slot = next; + } + status = acpi_remove_notify_handler(bridge->handle, ACPI_SYSTEM_NOTIFY, + handle_hotplug_event_bridge); + if (ACPI_FAILURE(status)) + err("failed to remove notify handler"); + + acpiphp_free_resource(&bridge->io_head); + acpiphp_free_resource(&bridge->mem_head); + acpiphp_free_resource(&bridge->p_mem_head); + acpiphp_free_resource(&bridge->bus_head); + + kfree(bridge); + } +} + + +/** + * acpiphp_get_num_slots - count number of slots in a system + */ +int acpiphp_get_num_slots (void) +{ + struct list_head *node; + struct acpiphp_bridge *bridge; + int num_slots; + + num_slots = 0; + + list_for_each(node, &bridge_list) { + bridge = (struct acpiphp_bridge *)node; + dbg("Bus%d %dslot(s)", bridge->bus, bridge->nr_slots); + num_slots += bridge->nr_slots; + } + + dbg("Total %dslots", num_slots); + return num_slots; +} + + +/** + * acpiphp_for_each_slot - call function for each slot + * @fn: callback function + * @data: context to be passed to callback function + * + */ +int acpiphp_for_each_slot(acpiphp_callback fn, void *data) +{ + struct list_head *node; + struct acpiphp_bridge *bridge; + struct acpiphp_slot *slot; + int retval = 0; + + list_for_each(node, &bridge_list) { + bridge = (struct acpiphp_bridge *)node; + for (slot = bridge->slots; slot; slot = slot->next) { + retval = fn(slot, data); + if (!retval) + goto err_exit; + } + } + + err_exit: + return retval; +} + + +/* search matching slot from id */ +struct acpiphp_slot *get_slot_from_id (int id) +{ + struct list_head *node; + struct acpiphp_bridge *bridge; + struct acpiphp_slot *slot; + + list_for_each(node, &bridge_list) { + bridge = (struct acpiphp_bridge *)node; + for (slot = bridge->slots; slot; slot = slot->next) + if (slot->id == id) + return slot; + } + + /* should never happen! */ + err("%s: no object for id %d",__FUNCTION__, id); + return 0; +} + + +/** + * acpiphp_enable_slot - power on slot + */ +int acpiphp_enable_slot (struct acpiphp_slot *slot) +{ + int retval; + int online = 0; + + down(&slot->crit_sect); + + /* wake up all functions */ + retval = power_on_slot(slot); + if (retval) + goto err_exit; + + if (get_slot_status(slot) == ACPI_STA_ALL) + /* configure all functions */ + retval = enable_device(slot); + + err_exit: + up(&slot->crit_sect); + return retval; +} + + +/** + * acpiphp_disable_slot - power off slot + */ +int acpiphp_disable_slot (struct acpiphp_slot *slot) +{ + struct list_head *l; + struct acpiphp_func *func; + int retval = 0; + + down(&slot->crit_sect); + + /* unconfigure all functions */ + retval = disable_device(slot); + if (retval) + goto err_exit; + + /* power off all functions */ + retval = power_off_slot(slot); + if (retval) + goto err_exit; + +#if 1 + acpiphp_resource_sort_and_combine(&slot->bridge->io_head); + acpiphp_resource_sort_and_combine(&slot->bridge->mem_head); + acpiphp_resource_sort_and_combine(&slot->bridge->p_mem_head); + acpiphp_resource_sort_and_combine(&slot->bridge->bus_head); + dbg("Available resources:"); + acpiphp_dump_resource(slot->bridge); +#endif + + err_exit: + up(&slot->crit_sect); + return retval; +} + + +/** + * acpiphp_check_bridge - re-enumerate devices + */ +int acpiphp_check_bridge (struct acpiphp_bridge *bridge) +{ + struct acpiphp_slot *slot; + unsigned int sta; + int retval = 0; + int enabled, disabled; + + enabled = disabled = 0; + + for (slot = bridge->slots; slot; slot = slot->next) { + sta = get_slot_status(slot); + if (slot->flags & SLOT_ENABLED) { + /* if enabled but not present, disable */ + if (sta != ACPI_STA_ALL) { + retval = acpiphp_disable_slot(slot); + if (retval) { + err("Error occured in enabling"); + up(&slot->crit_sect); + goto err_exit; + } + enabled++; + } + } else { + /* if disabled but present, enable */ + if (sta == ACPI_STA_ALL) { + retval = acpiphp_enable_slot(slot); + if (retval) { + err("Error occured in enabling"); + up(&slot->crit_sect); + goto err_exit; + } + disabled++; + } + } + } + + dbg("%s: %d enabled, %d disabled", __FUNCTION__, enabled, disabled); + + err_exit: + return retval; +} + + +/* + * slot enabled: 1 + * slot disabled: 0 + */ +u8 acpiphp_get_power_status (struct acpiphp_slot *slot) +{ + unsigned int sta; + + sta = get_slot_status(slot); + + return (sta & ACPI_STA_ENABLED) ? 1 : 0; +} + + +/* + * attention LED ON: 1 + * OFF: 0 + * + * TBD + * no direct attention led status information via ACPI + * + */ +u8 acpiphp_get_attention_status (struct acpiphp_slot *slot) +{ + return 0; +} + + +/* + * latch closed: 1 + * latch open: 0 + */ +u8 acpiphp_get_latch_status (struct acpiphp_slot *slot) +{ + unsigned int sta; + + sta = get_slot_status(slot); + + return (sta & ACPI_STA_SHOW_IN_UI) ? 1 : 0; +} + + +/* + * adapter presence : 1 + * absence : 0 + */ +u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot) +{ + unsigned int sta; + + sta = get_slot_status(slot); + + return (sta == 0) ? 0 : 1; +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/hotplug/acpiphp.h linux.19rc3-ac4/drivers/hotplug/acpiphp.h --- linux.19rc3/drivers/hotplug/acpiphp.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/hotplug/acpiphp.h 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,322 @@ +/* + * ACPI PCI Hot Plug Controller Driver + * + * Copyright (c) 1995,2001 Compaq Computer Corporation + * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (c) 2001 IBM Corp. + * Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com) + * Copyright (c) 2002 Takayoshi Kochi (t-kouchi@cq.jp.nec.com) + * Copyright (c) 2002 NEC Corporation + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This 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, GOOD TITLE or + * NON INFRINGEMENT. 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. + * + * Send feedback to , + * , + * + * + */ + +#ifndef _ACPIPHP_H +#define _ACPIPHP_H + +#include "include/acpi.h" +#include "pci_hotplug.h" + +#if ACPI_CA_VERSION < 0x20020201 +/* until we get a new version of the ACPI driver for both ia32 and ia64 ... */ +#define acpi_util_eval_error(h,p,s) + +static acpi_status +acpi_evaluate_integer ( + acpi_handle handle, + acpi_string pathname, + acpi_object_list *arguments, + unsigned long *data) +{ + acpi_status status = AE_OK; + acpi_object element; + acpi_buffer buffer = {sizeof(acpi_object), &element}; + + if (!data) + return AE_BAD_PARAMETER; + + status = acpi_evaluate_object(handle, pathname, arguments, &buffer); + if (ACPI_FAILURE(status)) { + acpi_util_eval_error(handle, pathname, status); + return status; + } + + if (element.type != ACPI_TYPE_INTEGER) { + acpi_util_eval_error(handle, pathname, AE_BAD_DATA); + return AE_BAD_DATA; + } + + *data = element.integer.value; + + return AE_OK; +} +#else /* ACPI_CA_VERSION < 0x20020201 */ +#include "acpi_bus.h" +#endif + +/* compatibility stuff for ACPI CA */ +#ifndef ACPI_MEMORY_RANGE +#define ACPI_MEMORY_RANGE MEMORY_RANGE +#endif + +#ifndef ACPI_IO_RANGE +#define ACPI_IO_RANGE IO_RANGE +#endif + +#ifndef ACPI_BUS_NUMBER_RANGE +#define ACPI_BUS_NUMBER_RANGE BUS_NUMBER_RANGE +#endif + +#ifndef ACPI_PREFETCHABLE_MEMORY +#define ACPI_PREFETCHABLE_MEMORY PREFETCHABLE_MEMORY +#endif + +#ifndef ACPI_PRODUCER +#define ACPI_PRODUCER PRODUCER +#endif + +#define dbg(format, arg...) \ + do { \ + if (debug) \ + printk (KERN_DEBUG "%s: " format "\n", \ + MY_NAME , ## arg); \ + } while (0) +#define err(format, arg...) printk (KERN_ERR "%s: " format "\n", MY_NAME , ## arg) +#define info(format, arg...) printk (KERN_INFO "%s: " format "\n", MY_NAME , ## arg) +#define warn(format, arg...) printk (KERN_WARNING "%s: " format "\n", MY_NAME , ## arg) + +#define SLOT_MAGIC 0x67267322 +/* name size which is used for entries in pcihpfs */ +#define SLOT_NAME_SIZE 16 /* ACPIxxxx */ + +struct acpiphp_bridge; +struct acpiphp_slot; +struct pci_resource; + +/* + * struct slot - slot information for each *physical* slot + */ +struct slot { + u32 magic; + u8 number; + struct hotplug_slot *hotplug_slot; + struct list_head slot_list; + + /* if there are multiple corresponding ACPI slot objects, + this points to one of them */ + struct acpiphp_slot *acpi_slot; +}; + +/* + * struct pci_resource - describes pci resource (mem, pfmem, io, bus) + */ +struct pci_resource { + struct pci_resource * next; + u64 base; + u32 length; +}; + +/** + * struct hpp_param - ACPI 2.0 _HPP Hot Plug Parameters + * @cache_line_size in DWORD + * @latency_timer in PCI clock + * @enable_SERR 0 or 1 + * @enable_PERR 0 or 1 + */ +struct hpp_param { + u8 cache_line_size; + u8 latency_timer; + u8 enable_SERR; + u8 enable_PERR; +}; + + +/** + * struct acpiphp_bridge - PCI bridge information + * + * for each bridge device in ACPI namespace + */ +struct acpiphp_bridge { + struct list_head list; + acpi_handle handle; + struct acpiphp_slot *slots; + int type; + int nr_slots; + + u8 seg; + u8 bus; + u8 sub; + + u32 flags; + + /* This bus (host bridge) or Secondary bus (PCI-to-PCI bridge) */ + struct pci_bus *pci_bus; + + /* PCI-to-PCI bridge device */ + struct pci_dev *pci_dev; + + struct pci_ops *pci_ops; + + /* ACPI 2.0 _HPP parameters */ + struct hpp_param hpp; + + spinlock_t res_lock; + + /* available resources on this bus */ + struct pci_resource *mem_head; + struct pci_resource *p_mem_head; + struct pci_resource *io_head; + struct pci_resource *bus_head; +}; + + +/** + * struct acpiphp_slot - PCI slot information + * + * PCI slot information for each *physical* PCI slot + */ +struct acpiphp_slot { + struct acpiphp_slot *next; + struct acpiphp_bridge *bridge; /* parent */ + struct list_head funcs; /* one slot may have different + objects (i.e. for each function) */ + struct acpiphp_func *func; /* functions */ + struct semaphore crit_sect; + + u32 id; /* slot id (serial #) for hotplug core */ + u8 device; /* pci device# */ + + u32 sun; /* ACPI _SUN (slot unique number) */ + u32 slotno; /* slot number relative to bridge */ + u32 flags; /* see below */ +}; + + +/** + * struct acpiphp_func - PCI slot information + * + * PCI function information for each object in ACPI namespace + * typically 8 objects per slot (i.e. for each PCI function) + */ +struct acpiphp_func { + struct acpiphp_slot *slot; /* parent */ + + struct list_head sibling; + struct pci_dev *pci_dev; + + acpi_handle handle; + + u8 function; /* pci function# */ + u32 flags; /* see below */ + + /* resources used for this function */ + struct pci_resource *mem_head; + struct pci_resource *p_mem_head; + struct pci_resource *io_head; + struct pci_resource *bus_head; +}; + + +/* PCI bus bridge HID */ +#define ACPI_PCI_HOST_HID "PNP0A03" + +/* PCI BRIDGE type */ +#define BRIDGE_TYPE_HOST 0 +#define BRIDGE_TYPE_P2P 1 + +/* ACPI _STA method value (ignore bit 4; battery present) */ +#define ACPI_STA_PRESENT (0x00000001) +#define ACPI_STA_ENABLED (0x00000002) +#define ACPI_STA_SHOW_IN_UI (0x00000004) +#define ACPI_STA_FUNCTIONING (0x00000008) +#define ACPI_STA_ALL (0x0000000f) + +/* bridge flags */ +#define BRIDGE_HAS_STA (0x00000001) +#define BRIDGE_HAS_EJ0 (0x00000002) +#define BRIDGE_HAS_HPP (0x00000004) +#define BRIDGE_HAS_PS0 (0x00000010) +#define BRIDGE_HAS_PS1 (0x00000020) +#define BRIDGE_HAS_PS2 (0x00000040) +#define BRIDGE_HAS_PS3 (0x00000080) + +/* slot flags */ + +#define SLOT_POWEREDON (0x00000001) +#define SLOT_ENABLED (0x00000002) +#define SLOT_MULTIFUNCTION (x000000004) + +/* function flags */ + +#define FUNC_HAS_STA (0x00000001) +#define FUNC_HAS_EJ0 (0x00000002) +#define FUNC_HAS_PS0 (0x00000010) +#define FUNC_HAS_PS1 (0x00000020) +#define FUNC_HAS_PS2 (0x00000040) +#define FUNC_HAS_PS3 (0x00000080) + +/* not yet */ +#define SLOT_SUPPORT_66MHZ (0x00010000) +#define SLOT_SUPPORT_100MHZ (0x00020000) +#define SLOT_SUPPORT_133MHZ (0x00040000) +#define SLOT_SUPPORT_PCIX (0x00080000) + +/* function prototypes */ + +/* acpiphp_glue.c */ +extern int acpiphp_glue_init (void); +extern void acpiphp_glue_exit (void); +extern int acpiphp_get_num_slots (void); +extern struct acpiphp_slot *get_slot_from_id (int id); +typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data); +extern int acpiphp_for_each_slot (acpiphp_callback fn, void *data); + +extern int acpiphp_check_bridge (struct acpiphp_bridge *bridge); +extern int acpiphp_enable_slot (struct acpiphp_slot *slot); +extern int acpiphp_disable_slot (struct acpiphp_slot *slot); +extern u8 acpiphp_get_power_status (struct acpiphp_slot *slot); +extern u8 acpiphp_get_attention_status (struct acpiphp_slot *slot); +extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot); +extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot); + +/* acpiphp_pci.c */ +extern struct pci_dev *acpiphp_allocate_pcidev (struct pci_bus *pbus, int dev, int fn); +extern int acpiphp_configure_slot (struct acpiphp_slot *slot); +extern int acpiphp_configure_function (struct acpiphp_func *func); +extern int acpiphp_unconfigure_function (struct acpiphp_func *func); +extern int acpiphp_detect_pci_resource (struct acpiphp_bridge *bridge); +extern int acpiphp_init_func_resource (struct acpiphp_func *func); + +/* acpiphp_res.c */ +extern struct pci_resource *acpiphp_get_io_resource (struct pci_resource **head, u32 size); +extern struct pci_resource *acpiphp_get_max_resource (struct pci_resource **head, u32 size); +extern struct pci_resource *acpiphp_get_resource (struct pci_resource **head, u32 size); +extern struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head, u64 base, u32 size); +extern int acpiphp_resource_sort_and_combine (struct pci_resource **head); +extern struct pci_resource *acpiphp_make_resource (u64 base, u32 length); +extern void acpiphp_move_resource (struct pci_resource **from, struct pci_resource **to); +extern void acpiphp_free_resource (struct pci_resource **res); +extern void acpiphp_dump_resource (struct acpiphp_bridge *bridge); /* debug */ +extern void acpiphp_dump_func_resource (struct acpiphp_func *func); /* debug */ + +#endif /* _ACPIPHP_H */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/hotplug/acpiphp_pci.c linux.19rc3-ac4/drivers/hotplug/acpiphp_pci.c --- linux.19rc3/drivers/hotplug/acpiphp_pci.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/hotplug/acpiphp_pci.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,763 @@ +/* + * ACPI PCI HotPlug PCI configuration space management + * + * Copyright (c) 1995,2001 Compaq Computer Corporation + * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (c) 2001,2002 IBM Corp. + * Copyright (c) 2002 Takayoshi Kochi (t-kouchi@cq.jp.nec.com) + * Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com) + * Copyright (c) 2002 NEC Corporation + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This 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, GOOD TITLE or + * NON INFRINGEMENT. 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. + * + * Send feedback to + * + */ + +#include +#include +#include +#include +#include +#include "pci_hotplug.h" +#include "acpiphp.h" + +static int debug = 1; /* XXX set 0 after debug */ +#define MY_NAME "acpiphp_pci" + +static void acpiphp_configure_irq (struct pci_dev *dev); + + +/* allocate mem/pmem/io resource to a new function */ +static int alloc_resource (struct acpiphp_func *func) +{ + u64 base; + u32 bar, len; + u32 address[] = { + PCI_BASE_ADDRESS_0, + PCI_BASE_ADDRESS_1, + PCI_BASE_ADDRESS_2, + PCI_BASE_ADDRESS_3, + PCI_BASE_ADDRESS_4, + PCI_BASE_ADDRESS_5, + 0 + }; + int count; + struct acpiphp_bridge *bridge; + struct pci_resource *res; + struct pci_ops *ops; + int bus, device, function; + + bridge = func->slot->bridge; + bus = bridge->bus; + device = func->slot->device; + function = func->function; + ops = bridge->pci_ops; + + for (count = 0; address[count]; count++) { /* for 6 BARs */ + pci_write_config_dword_nodev (ops, bus, device, function, address[count], 0xFFFFFFFF); + pci_read_config_dword_nodev(ops, bus, device, function, address[count], &bar); + + if (!bar) /* This BAR is not implemented */ + continue; + + dbg("Device %02x.%02x BAR %d wants %x", device, function, count, bar); + + if (bar & PCI_BASE_ADDRESS_SPACE_IO) { + /* This is IO */ + + len = bar & 0xFFFFFFFC; + len = ~len + 1; + + dbg ("len in IO %x, BAR %d", len, count); + + spin_lock(&bridge->res_lock); + res = acpiphp_get_io_resource(&bridge->io_head, len); + spin_unlock(&bridge->res_lock); + + if (!res) { + err("cannot allocate requested io for %02x:%02x.%d len %x\n", + bus, device, function, len); + return -1; + } + pci_write_config_dword_nodev(ops, bus, device, function, address[count], (u32)res->base); + res->next = func->io_head; + func->io_head = res; + + } else { + /* This is Memory */ + if (bar & PCI_BASE_ADDRESS_MEM_PREFETCH) { + /* pfmem */ + + len = bar & 0xFFFFFFF0; + len = ~len + 1; + + dbg("len in PFMEM %x, BAR %d", len, count); + + spin_lock(&bridge->res_lock); + res = acpiphp_get_resource(&bridge->p_mem_head, len); + spin_unlock(&bridge->res_lock); + + if (!res) { + err("cannot allocate requested pfmem for %02x:%02x.%d len %x\n", + bus, device, function, len); + return -1; + } + + pci_write_config_dword_nodev(ops, bus, device, function, address[count], (u32)res->base); + + if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */ + dbg ("inside the pfmem 64 case, count %d", count); + count += 1; + pci_write_config_dword_nodev(ops, bus, device, function, address[count], (u32)(res->base >> 32)); + } + + res->next = func->p_mem_head; + func->p_mem_head = res; + + } else { + /* regular memory */ + + len = bar & 0xFFFFFFF0; + len = ~len + 1; + + dbg("len in MEM %x, BAR %d", len, count); + + spin_lock(&bridge->res_lock); + res = acpiphp_get_resource(&bridge->mem_head, len); + spin_unlock(&bridge->res_lock); + + if (!res) { + err("cannot allocate requested pfmem for %02x:%02x.%d len %x\n", + bus, device, function, len); + return -1; + } + + pci_write_config_dword_nodev(ops, bus, device, function, address[count], (u32)res->base); + + if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) { + /* takes up another dword */ + dbg ("inside mem 64 case, reg. mem, count %d", count); + count += 1; + pci_write_config_dword_nodev(ops, bus, device, function, address[count], (u32)(res->base >> 32)); + } + + res->next = func->mem_head; + func->mem_head = res; + + } + } + } + + /* disable expansion rom */ + pci_write_config_dword_nodev(ops, bus, device, function, PCI_ROM_ADDRESS, 0x00000000); + + return 0; +} + + +/* enable pci_dev */ +static int configure_pci_dev (struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_bus) +{ + u16 tmp; + struct acpiphp_func *func; + struct acpiphp_bridge *bridge; + struct pci_dev *dev; + + func = (struct acpiphp_func *)wrapped_dev->data; + bridge = (struct acpiphp_bridge *)wrapped_bus->data; + dev = wrapped_dev->dev; + + /* TBD: support PCI-to-PCI bridge case */ + if (!func || !bridge) + return 0; + + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, bridge->hpp.cache_line_size); + pci_write_config_byte(dev, PCI_LATENCY_TIMER, bridge->hpp.latency_timer); + + pci_read_config_word(dev, PCI_COMMAND, &tmp); + if (bridge->hpp.enable_SERR) + tmp |= PCI_COMMAND_SERR; + if (bridge->hpp.enable_PERR) + tmp |= PCI_COMMAND_PARITY; + //tmp |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY); + pci_write_config_word(dev, PCI_COMMAND, tmp); + + acpiphp_configure_irq(dev); +#ifdef CONFIG_PROC_FS + pci_proc_attach_device(dev); +#endif + pci_announce_device_to_drivers(dev); + + return 0; +} + + +static int is_pci_dev_in_use (struct pci_dev* dev) +{ + /* + * dev->driver will be set if the device is in use by a new-style + * driver -- otherwise, check the device's regions to see if any + * driver has claimed them + */ + + int i, inuse=0; + + if (dev->driver) return 1; //assume driver feels responsible + + for (i = 0; !dev->driver && !inuse && (i < 6); i++) { + if (!pci_resource_start(dev, i)) + continue; + + if (pci_resource_flags(dev, i) & IORESOURCE_IO) + inuse = check_region(pci_resource_start(dev, i), + pci_resource_len(dev, i)); + else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) + inuse = check_mem_region(pci_resource_start(dev, i), + pci_resource_len(dev, i)); + } + + return inuse; +} + + +static int pci_hp_remove_device (struct pci_dev *dev) +{ + if (is_pci_dev_in_use(dev)) { + err("***Cannot safely power down device -- " + "it appears to be in use***\n"); + return -EBUSY; + } + pci_remove_device(dev); + return 0; +} + + +/* remove device driver */ +static int unconfigure_pci_dev_driver (struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_bus) +{ + struct pci_dev *dev = wrapped_dev->dev; + + dbg("attempting removal of driver for device %s", dev->slot_name); + + /* Now, remove the Linux Driver Representation */ + if (dev->driver) { + if (dev->driver->remove) { + dev->driver->remove(dev); + dbg("driver was properly removed"); + } + dev->driver = NULL; + } + + return is_pci_dev_in_use(dev); +} + + +/* remove pci_dev itself from system */ +static int unconfigure_pci_dev (struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_bus) +{ + struct pci_dev *dev = wrapped_dev->dev; + + /* Now, remove the Linux Representation */ + if (dev) { + if (pci_hp_remove_device(dev) == 0) { + kfree(dev); /* Now, remove */ + } else { + return -1; /* problems while freeing, abort visitation */ + } + } + + return 0; +} + + +/* remove pci_bus itself from system */ +static int unconfigure_pci_bus (struct pci_bus_wrapped *wrapped_bus, struct pci_dev_wrapped *wrapped_dev) +{ + struct pci_bus *bus = wrapped_bus->bus; + +#ifdef CONFIG_PROC_FS + /* Now, remove the Linux Representation */ + if (bus->procdir) { + pci_proc_detach_bus(bus); + } +#endif + /* the cleanup code should live in the kernel ... */ + bus->self->subordinate = NULL; + /* unlink from parent bus */ + list_del(&bus->node); + + /* Now, remove */ + if (bus) + kfree(bus); + + return 0; +} + + +/* detect_used_resource - subtract resource under dev from bridge */ +static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev *dev) +{ + u32 bar, len, pin; + u64 base; + u32 address[] = { + PCI_BASE_ADDRESS_0, + PCI_BASE_ADDRESS_1, + PCI_BASE_ADDRESS_2, + PCI_BASE_ADDRESS_3, + PCI_BASE_ADDRESS_4, + PCI_BASE_ADDRESS_5, + 0 + }; + int count; + struct pci_resource *res; + + dbg("Device %s", dev->slot_name); + + for (count = 0; address[count]; count++) { /* for 6 BARs */ + pci_read_config_dword(dev, address[count], &bar); + + if (!bar) /* This BAR is not implemented */ + continue; + + pci_write_config_dword(dev, address[count], 0xFFFFFFFF); + pci_read_config_dword(dev, address[count], &len); + + if (len & PCI_BASE_ADDRESS_SPACE_IO) { + /* This is IO */ + base = bar & 0xFFFFFFFC; + len &= 0xFFFFFFFC; + len = ~len + 1; + + dbg("BAR[%d] %08x - %08x (IO)", count, (u32)base, (u32)base + len - 1); + + spin_lock(&bridge->res_lock); + res = acpiphp_get_resource_with_base(&bridge->io_head, base, len); + spin_unlock(&bridge->res_lock); + if (res) + kfree(res); + } else { + /* This is Memory */ + base = bar & 0xFFFFFFF0; + if (len & PCI_BASE_ADDRESS_MEM_PREFETCH) { + /* pfmem */ + + len &= 0xFFFFFFF0; + len = ~len + 1; + + if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */ + dbg ("prefetch mem 64"); + count += 1; + } + dbg("BAR[%d] %08x - %08x (PMEM)", count, (u32)base, (u32)base + len - 1); + spin_lock(&bridge->res_lock); + res = acpiphp_get_resource_with_base(&bridge->p_mem_head, base, len); + spin_unlock(&bridge->res_lock); + if (res) + kfree(res); + } else { + /* regular memory */ + + len &= 0xFFFFFFF0; + len = ~len + 1; + + if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) { + /* takes up another dword */ + dbg ("mem 64"); + count += 1; + } + dbg("BAR[%d] %08x - %08x (MEM)", count, (u32)base, (u32)base + len - 1); + spin_lock(&bridge->res_lock); + res = acpiphp_get_resource_with_base(&bridge->mem_head, base, len); + spin_unlock(&bridge->res_lock); + if (res) + kfree(res); + } + } + + pci_write_config_dword(dev, address[count], bar); + } + + return 0; +} + + +/* detect_pci_resource_bus - subtract resource under pci_bus */ +static void detect_used_resource_bus(struct acpiphp_bridge *bridge, struct pci_bus *bus) +{ + struct list_head *l; + struct pci_dev *dev; + + list_for_each(l, &bus->devices) { + dev = pci_dev_b(l); + detect_used_resource(bridge, dev); + /* XXX recursive call */ + if (dev->subordinate) + detect_used_resource_bus(bridge, dev->subordinate); + } +} + + +/** + * acpiphp_detect_pci_resource - detect resources under bridge + * @bridge: detect all resources already used under this bridge + * + * collect all resources already allocated for all devices under a bridge. + */ +int acpiphp_detect_pci_resource (struct acpiphp_bridge *bridge) +{ + struct list_head *l; + struct pci_dev *dev; + + detect_used_resource_bus(bridge, bridge->pci_bus); + + return 0; +} + + +/** + * acpiphp_init_slot_resource - gather resource usage information of a slot + * @slot: ACPI slot object to be checked, should have valid pci_dev member + * + * TBD: PCI-to-PCI bridge case + * use pci_dev->resource[] + */ +int acpiphp_init_func_resource (struct acpiphp_func *func) +{ + u64 base; + u32 bar, len; + u32 address[] = { + PCI_BASE_ADDRESS_0, + PCI_BASE_ADDRESS_1, + PCI_BASE_ADDRESS_2, + PCI_BASE_ADDRESS_3, + PCI_BASE_ADDRESS_4, + PCI_BASE_ADDRESS_5, + 0 + }; + int count; + struct pci_resource *res; + struct pci_ops *ops; + struct pci_dev *dev; + + dev = func->pci_dev; + dbg("Hot-pluggable device %s", dev->slot_name); + + for (count = 0; address[count]; count++) { /* for 6 BARs */ + pci_read_config_dword (dev, address[count], &bar); + + if (!bar) /* This BAR is not implemented */ + continue; + + pci_write_config_dword (dev, address[count], 0xFFFFFFFF); + pci_read_config_dword (dev, address[count], &len); + + if (len & PCI_BASE_ADDRESS_SPACE_IO) { + /* This is IO */ + base = bar & 0xFFFFFFFC; + len &= 0xFFFFFFFC; + len = ~len + 1; + + dbg("BAR[%d] %08x - %08x (IO)", count, (u32)base, (u32)base + len - 1); + + res = acpiphp_make_resource(base, len); + if (!res) + goto no_memory; + + res->next = func->io_head; + func->io_head = res; + + } else { + /* This is Memory */ + base = bar & 0xFFFFFFF0; + if (len & PCI_BASE_ADDRESS_MEM_PREFETCH) { + /* pfmem */ + + len &= 0xFFFFFFF0; + len = ~len + 1; + + if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */ + dbg ("prefetch mem 64"); + count += 1; + } + dbg("BAR[%d] %08x - %08x (PMEM)", count, (u32)base, (u32)base + len - 1); + res = acpiphp_make_resource(base, len); + if (!res) + goto no_memory; + + res->next = func->p_mem_head; + func->p_mem_head = res; + + } else { + /* regular memory */ + + len &= 0xFFFFFFF0; + len = ~len + 1; + + if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) { + /* takes up another dword */ + dbg ("mem 64"); + count += 1; + } + dbg("BAR[%d] %08x - %08x (MEM)", count, (u32)base, (u32)base + len - 1); + res = acpiphp_make_resource(base, len); + if (!res) + goto no_memory; + + res->next = func->mem_head; + func->mem_head = res; + + } + } + + pci_write_config_dword (dev, address[count], bar); + } +#if 1 + acpiphp_dump_func_resource(func); +#endif + + return 0; + + no_memory: + err("out of memory"); + acpiphp_free_resource(&func->io_head); + acpiphp_free_resource(&func->mem_head); + acpiphp_free_resource(&func->p_mem_head); + + return -1; +} + + +/** + * acpiphp_configure_slot - allocate PCI resources + * @slot: slot to be configured + * + * initializes a PCI functions on a device inserted + * into the slot + * + */ +int acpiphp_configure_slot (struct acpiphp_slot *slot) +{ + struct acpiphp_func *func; + struct list_head *l; + u8 hdr; + u32 dvid; + int retval = 0; + int is_multi = 0; + + pci_read_config_byte_nodev(slot->bridge->pci_ops, + slot->bridge->bus, slot->device, 0, + PCI_HEADER_TYPE, &hdr); + + if (hdr & 0x80) + is_multi = 1; + + list_for_each(l, &slot->funcs) { + func = list_entry(l, struct acpiphp_func, sibling); + if (is_multi || func->function == 0) { + pci_read_config_dword_nodev(slot->bridge->pci_ops, + slot->bridge->bus, + slot->device, + func->function, + PCI_VENDOR_ID, &dvid); + if (dvid != 0xffffffff) { + retval = alloc_resource(func); + if (retval) + break; + } + } + } + + return retval; +} + + +/* for pci_visit_dev() */ +static struct pci_visit configure_functions = { + post_visit_pci_dev: configure_pci_dev +}; + +static struct pci_visit unconfigure_functions_phase1 = { + post_visit_pci_dev: unconfigure_pci_dev_driver +}; + +static struct pci_visit unconfigure_functions_phase2 = { + post_visit_pci_bus: unconfigure_pci_bus, + post_visit_pci_dev: unconfigure_pci_dev +}; + + +/** + * acpiphp_configure_function - configure PCI function + * @func: function to be configured + * + * initializes a PCI functions on a device inserted + * into the slot + * + */ +int acpiphp_configure_function (struct acpiphp_func *func) +{ + int retval = 0; + struct pci_dev_wrapped wrapped_dev; + struct pci_bus_wrapped wrapped_bus; + struct acpiphp_bridge *bridge; + + /* if pci_dev is NULL, ignore it */ + if (!func->pci_dev) + goto err_exit; + + bridge = func->slot->bridge; + + memset(&wrapped_dev, 0, sizeof(struct pci_dev_wrapped)); + memset(&wrapped_bus, 0, sizeof(struct pci_bus_wrapped)); + wrapped_dev.dev = func->pci_dev; + wrapped_dev.data = func; + wrapped_bus.bus = bridge->pci_bus; + wrapped_bus.data = bridge; + + retval = pci_visit_dev(&configure_functions, &wrapped_dev, &wrapped_bus); + if (retval) + goto err_exit; + + err_exit: + return retval; +} + + +/** + * acpiphp_unconfigure_function - unconfigure PCI function + * @func: function to be unconfigured + * + */ +int acpiphp_unconfigure_function (struct acpiphp_func *func) +{ + struct acpiphp_bridge *bridge; + struct pci_resource *tmp; + struct pci_dev_wrapped wrapped_dev; + struct pci_bus_wrapped wrapped_bus; + int retval = 0; + + /* if pci_dev is NULL, ignore it */ + if (!func->pci_dev) + goto err_exit; + + memset(&wrapped_dev, 0, sizeof(struct pci_dev_wrapped)); + memset(&wrapped_bus, 0, sizeof(struct pci_bus_wrapped)); + wrapped_dev.dev = func->pci_dev; + //wrapped_dev.data = func; + wrapped_bus.bus = func->slot->bridge->pci_bus; + //wrapped_bus.data = func->slot->bridge; + + retval = pci_visit_dev(&unconfigure_functions_phase1, &wrapped_dev, &wrapped_bus); + if (retval) + goto err_exit; + + retval = pci_visit_dev(&unconfigure_functions_phase2, &wrapped_dev, &wrapped_bus); + if (retval) + goto err_exit; + + /* free all resources */ + bridge = func->slot->bridge; + + spin_lock(&bridge->res_lock); + acpiphp_move_resource(&func->io_head, &bridge->io_head); + acpiphp_move_resource(&func->mem_head, &bridge->mem_head); + acpiphp_move_resource(&func->p_mem_head, &bridge->p_mem_head); + acpiphp_move_resource(&func->bus_head, &bridge->bus_head); + spin_unlock(&bridge->res_lock); + + err_exit: + return retval; +} + + +/* XXX IA64 specific */ +#ifdef CONFIG_IA64 +static int ia64_get_irq(struct pci_dev *dev, int pin) +{ + extern int pci_pin_to_vector(int bus, int slot, int pci_pin); + int irq; + + irq = pci_pin_to_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin); + + if (irq < 0 && dev->bus->parent) { + /* go back to the bridge */ + struct pci_dev *bridge = dev->bus->self; + + if (bridge) { + /* allow for multiple bridges on an adapter */ + do { + /* do the bridge swizzle... */ + pin = (pin + PCI_SLOT(dev->devfn)) % 4; + irq = pci_pin_to_vector(bridge->bus->number, + PCI_SLOT(bridge->devfn), + pin); + } while (irq < 0 && (bridge = bridge->bus->self)); + } + if (irq >= 0) + printk(KERN_WARNING + "PCI: using PPB(B%d,I%d,P%d) to get vector %02x\n", + dev->bus->number, PCI_SLOT(dev->devfn), + pin, irq); + else + printk(KERN_WARNING + "PCI: Couldn't map irq for (B%d,I%d,P%d)\n", + dev->bus->number, PCI_SLOT(dev->devfn), pin); + } + + return irq; +} +#endif + + +/* + * acpiphp_configure_irq - configure PCI_INTERRUPT_PIN + * + * for x86 platforms, pcibios_enable_device calls pcibios_enable_irq, + * which allocates irq for pci_dev + * + * for IA64 platforms, we have to program dev->irq from pci IRQ routing + * information derived from ACPI table + * + * TBD: + * separate architecture dependent part + * (preferably, pci_enable_device() cares for allocating irq...) + */ +static void acpiphp_configure_irq (struct pci_dev *dev) +{ +#if CONFIG_IA64 /* XXX IA64 specific, need i386 version */ + int bus, device, function, irq; + u8 tmp; + + bus = dev->bus->number; + device = PCI_SLOT(dev->devfn); + function = PCI_FUNC(dev->devfn); + + pci_read_config_byte (dev, PCI_INTERRUPT_PIN, &tmp); + + if ((tmp > 0x00) && (tmp < 0x05)) { + irq = ia64_get_irq(dev, tmp - 1); + if (irq > 0) { + dev->irq = irq; + pci_write_config_byte (dev, PCI_INTERRUPT_LINE, irq); + } else { + err("Couldn't get IRQ for INT%c", 'A' + tmp - 1); + } + } +#endif +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/hotplug/acpiphp_res.c linux.19rc3-ac4/drivers/hotplug/acpiphp_res.c --- linux.19rc3/drivers/hotplug/acpiphp_res.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/hotplug/acpiphp_res.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,708 @@ +/* + * ACPI PCI HotPlug Utility functions + * + * Copyright (c) 1995,2001 Compaq Computer Corporation + * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (c) 2001 IBM Corp. + * Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com) + * Copyright (c) 2002 Takayoshi Kochi (t-kouchi@cq.jp.nec.com) + * Copyright (c) 2002 NEC Corporation + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This 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, GOOD TITLE or + * NON INFRINGEMENT. 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. + * + * Send feedback to , + * + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "pci_hotplug.h" +#include "acpiphp.h" + +#define MY_NAME "acpiphp_res" + +/* local variables */ +static int debug = 0; + +/* + * sort_by_size - sort nodes by their length, smallest first + */ +static int sort_by_size(struct pci_resource **head) +{ + struct pci_resource *current_res; + struct pci_resource *next_res; + int out_of_order = 1; + + if (!(*head)) + return 1; + + if (!((*head)->next)) + return 0; + + while (out_of_order) { + out_of_order = 0; + + /* Special case for swapping list head */ + if (((*head)->next) && + ((*head)->length > (*head)->next->length)) { + out_of_order++; + current_res = *head; + *head = (*head)->next; + current_res->next = (*head)->next; + (*head)->next = current_res; + } + + current_res = *head; + + while (current_res->next && current_res->next->next) { + if (current_res->next->length > current_res->next->next->length) { + out_of_order++; + next_res = current_res->next; + current_res->next = current_res->next->next; + current_res = current_res->next; + next_res->next = current_res->next; + current_res->next = next_res; + } else + current_res = current_res->next; + } + } /* End of out_of_order loop */ + + return 0; +} + + +/* + * sort_by_max_size - sort nodes by their length, largest first + */ +static int sort_by_max_size(struct pci_resource **head) +{ + struct pci_resource *current_res; + struct pci_resource *next_res; + int out_of_order = 1; + + if (!(*head)) + return 1; + + if (!((*head)->next)) + return 0; + + while (out_of_order) { + out_of_order = 0; + + /* Special case for swapping list head */ + if (((*head)->next) && + ((*head)->length < (*head)->next->length)) { + out_of_order++; + current_res = *head; + *head = (*head)->next; + current_res->next = (*head)->next; + (*head)->next = current_res; + } + + current_res = *head; + + while (current_res->next && current_res->next->next) { + if (current_res->next->length < current_res->next->next->length) { + out_of_order++; + next_res = current_res->next; + current_res->next = current_res->next->next; + current_res = current_res->next; + next_res->next = current_res->next; + current_res->next = next_res; + } else + current_res = current_res->next; + } + } /* End of out_of_order loop */ + + return 0; +} + +/** + * get_io_resource - get resource for I/O ports + * + * this function sorts the resource list by size and then + * returns the first node of "size" length that is not in the + * ISA aliasing window. If it finds a node larger than "size" + * it will split it up. + * + * size must be a power of two. + * + * difference from get_resource is handling of ISA aliasing space. + * + */ +struct pci_resource *acpiphp_get_io_resource (struct pci_resource **head, u32 size) +{ + struct pci_resource *prevnode; + struct pci_resource *node; + struct pci_resource *split_node; + u64 temp_qword; + + if (!(*head)) + return NULL; + + if (acpiphp_resource_sort_and_combine(head)) + return NULL; + + if (sort_by_size(head)) + return NULL; + + for (node = *head; node; node = node->next) { + if (node->length < size) + continue; + + if (node->base & (size - 1)) { + /* this one isn't base aligned properly + so we'll make a new entry and split it up */ + temp_qword = (node->base | (size-1)) + 1; + + /* Short circuit if adjusted size is too small */ + if ((node->length - (temp_qword - node->base)) < size) + continue; + + split_node = acpiphp_make_resource(node->base, temp_qword - node->base); + + if (!split_node) + return NULL; + + node->base = temp_qword; + node->length -= split_node->length; + + /* Put it in the list */ + split_node->next = node->next; + node->next = split_node; + } /* End of non-aligned base */ + + /* Don't need to check if too small since we already did */ + if (node->length > size) { + /* this one is longer than we need + so we'll make a new entry and split it up */ + split_node = acpiphp_make_resource(node->base + size, node->length - size); + + if (!split_node) + return NULL; + + node->length = size; + + /* Put it in the list */ + split_node->next = node->next; + node->next = split_node; + } /* End of too big on top end */ + + /* For IO make sure it's not in the ISA aliasing space */ + if (node->base & 0x300L) + continue; + + /* If we got here, then it is the right size + Now take it out of the list */ + if (*head == node) { + *head = node->next; + } else { + prevnode = *head; + while (prevnode->next != node) + prevnode = prevnode->next; + + prevnode->next = node->next; + } + node->next = NULL; + /* Stop looping */ + break; + } + + return node; +} + + +/** + * get_max_resource - get the largest resource + * + * Gets the largest node that is at least "size" big from the + * list pointed to by head. It aligns the node on top and bottom + * to "size" alignment before returning it. + */ +struct pci_resource *acpiphp_get_max_resource (struct pci_resource **head, u32 size) +{ + struct pci_resource *max; + struct pci_resource *temp; + struct pci_resource *split_node; + u64 temp_qword; + + if (!(*head)) + return NULL; + + if (acpiphp_resource_sort_and_combine(head)) + return NULL; + + if (sort_by_max_size(head)) + return NULL; + + for (max = *head;max; max = max->next) { + + /* If not big enough we could probably just bail, + instead we'll continue to the next. */ + if (max->length < size) + continue; + + if (max->base & (size - 1)) { + /* this one isn't base aligned properly + so we'll make a new entry and split it up */ + temp_qword = (max->base | (size-1)) + 1; + + /* Short circuit if adjusted size is too small */ + if ((max->length - (temp_qword - max->base)) < size) + continue; + + split_node = acpiphp_make_resource(max->base, temp_qword - max->base); + + if (!split_node) + return NULL; + + max->base = temp_qword; + max->length -= split_node->length; + + /* Put it next in the list */ + split_node->next = max->next; + max->next = split_node; + } + + if ((max->base + max->length) & (size - 1)) { + /* this one isn't end aligned properly at the top + so we'll make a new entry and split it up */ + temp_qword = ((max->base + max->length) & ~(size - 1)); + + split_node = acpiphp_make_resource(temp_qword, + max->length + max->base - temp_qword); + + if (!split_node) + return NULL; + + max->length -= split_node->length; + + /* Put it in the list */ + split_node->next = max->next; + max->next = split_node; + } + + /* Make sure it didn't shrink too much when we aligned it */ + if (max->length < size) + continue; + + /* Now take it out of the list */ + temp = (struct pci_resource*) *head; + if (temp == max) { + *head = max->next; + } else { + while (temp && temp->next != max) { + temp = temp->next; + } + + temp->next = max->next; + } + + max->next = NULL; + return max; + } + + /* If we get here, we couldn't find one */ + return NULL; +} + + +/** + * get_resource - get resource (mem, pfmem) + * + * this function sorts the resource list by size and then + * returns the first node of "size" length. If it finds a node + * larger than "size" it will split it up. + * + * size must be a power of two. + * + */ +struct pci_resource *acpiphp_get_resource (struct pci_resource **head, u32 size) +{ + struct pci_resource *prevnode; + struct pci_resource *node; + struct pci_resource *split_node; + u64 temp_qword; + + if (!(*head)) + return NULL; + + if (acpiphp_resource_sort_and_combine(head)) + return NULL; + + if (sort_by_size(head)) + return NULL; + + for (node = *head; node; node = node->next) { + dbg("%s: req_size =%x node=%p, base=%x, length=%x", + __FUNCTION__, size, node, (u32)node->base, node->length); + if (node->length < size) + continue; + + if (node->base & (size - 1)) { + dbg("%s: not aligned", __FUNCTION__); + /* this one isn't base aligned properly + so we'll make a new entry and split it up */ + temp_qword = (node->base | (size-1)) + 1; + + /* Short circuit if adjusted size is too small */ + if ((node->length - (temp_qword - node->base)) < size) + continue; + + split_node = acpiphp_make_resource(node->base, temp_qword - node->base); + + if (!split_node) + return NULL; + + node->base = temp_qword; + node->length -= split_node->length; + + /* Put it in the list */ + split_node->next = node->next; + node->next = split_node; + } /* End of non-aligned base */ + + /* Don't need to check if too small since we already did */ + if (node->length > size) { + dbg("%s: too big", __FUNCTION__); + /* this one is longer than we need + so we'll make a new entry and split it up */ + split_node = acpiphp_make_resource(node->base + size, node->length - size); + + if (!split_node) + return NULL; + + node->length = size; + + /* Put it in the list */ + split_node->next = node->next; + node->next = split_node; + } /* End of too big on top end */ + + dbg("%s: got one!!!", __FUNCTION__); + /* If we got here, then it is the right size + Now take it out of the list */ + if (*head == node) { + *head = node->next; + } else { + prevnode = *head; + while (prevnode->next != node) + prevnode = prevnode->next; + + prevnode->next = node->next; + } + node->next = NULL; + /* Stop looping */ + break; + } + return node; +} + +/** + * get_resource_with_base - get resource with specific base address + * + * this function + * returns the first node of "size" length located at specified base address. + * If it finds a node larger than "size" it will split it up. + * + * size must be a power of two. + * + */ +struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head, u64 base, u32 size) +{ + struct pci_resource *prevnode; + struct pci_resource *node; + struct pci_resource *split_node; + u64 temp_qword; + + if (!(*head)) + return NULL; + + if (acpiphp_resource_sort_and_combine(head)) + return NULL; + + for (node = *head; node; node = node->next) { + dbg(": 1st req_base=%x req_size =%x node=%p, base=%x, length=%x", + (u32)base, size, node, (u32)node->base, node->length); + if (node->base > base) + continue; + + if ((node->base + node->length) < (base + size)) + continue; + + if (node->base < base) { + dbg(": split 1"); + /* this one isn't base aligned properly + so we'll make a new entry and split it up */ + temp_qword = base; + + /* Short circuit if adjusted size is too small */ + if ((node->length - (temp_qword - node->base)) < size) + continue; + + split_node = acpiphp_make_resource(node->base, temp_qword - node->base); + + if (!split_node) + return NULL; + + node->base = temp_qword; + node->length -= split_node->length; + + /* Put it in the list */ + split_node->next = node->next; + node->next = split_node; + } + + dbg(": 2nd req_base=%x req_size =%x node=%p, base=%x, length=%x", + (u32)base, size, node, (u32)node->base, node->length); + + /* Don't need to check if too small since we already did */ + if (node->length > size) { + dbg(": split 2"); + /* this one is longer than we need + so we'll make a new entry and split it up */ + split_node = acpiphp_make_resource(node->base + size, node->length - size); + + if (!split_node) + return NULL; + + node->length = size; + + /* Put it in the list */ + split_node->next = node->next; + node->next = split_node; + } /* End of too big on top end */ + + dbg(": got one!!!"); + /* If we got here, then it is the right size + Now take it out of the list */ + if (*head == node) { + *head = node->next; + } else { + prevnode = *head; + while (prevnode->next != node) + prevnode = prevnode->next; + + prevnode->next = node->next; + } + node->next = NULL; + /* Stop looping */ + break; + } + return node; +} + + +/** + * acpiphp_resource_sort_and_combine + * + * Sorts all of the nodes in the list in ascending order by + * their base addresses. Also does garbage collection by + * combining adjacent nodes. + * + * returns 0 if success + */ +int acpiphp_resource_sort_and_combine (struct pci_resource **head) +{ + struct pci_resource *node1; + struct pci_resource *node2; + int out_of_order = 1; + + if (!(*head)) + return 1; + + dbg("*head->next = %p",(*head)->next); + + if (!(*head)->next) + return 0; /* only one item on the list, already sorted! */ + + dbg("*head->base = 0x%x",(u32)(*head)->base); + dbg("*head->next->base = 0x%x", (u32)(*head)->next->base); + while (out_of_order) { + out_of_order = 0; + + /* Special case for swapping list head */ + if (((*head)->next) && + ((*head)->base > (*head)->next->base)) { + node1 = *head; + (*head) = (*head)->next; + node1->next = (*head)->next; + (*head)->next = node1; + out_of_order++; + } + + node1 = (*head); + + while (node1->next && node1->next->next) { + if (node1->next->base > node1->next->next->base) { + out_of_order++; + node2 = node1->next; + node1->next = node1->next->next; + node1 = node1->next; + node2->next = node1->next; + node1->next = node2; + } else + node1 = node1->next; + } + } /* End of out_of_order loop */ + + node1 = *head; + + while (node1 && node1->next) { + if ((node1->base + node1->length) == node1->next->base) { + /* Combine */ + dbg("8.."); + node1->length += node1->next->length; + node2 = node1->next; + node1->next = node1->next->next; + kfree(node2); + } else + node1 = node1->next; + } + + return 0; +} + + +/** + * acpiphp_make_resource - make resource structure + * @base: base address of a resource + * @length: length of a resource + */ +struct pci_resource *acpiphp_make_resource (u64 base, u32 length) +{ + struct pci_resource *res; + + res = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (res) { + memset(res, 0, sizeof(struct pci_resource)); + res->base = base; + res->length = length; + } + + return res; +} + + +/** + * acpiphp_move_resource - move linked resources from one to another + * @from: head of linked resource list + * @to: head of linked resource list + */ +void acpiphp_move_resource (struct pci_resource **from, struct pci_resource **to) +{ + struct pci_resource *tmp; + + while (*from) { + tmp = (*from)->next; + (*from)->next = *to; + *to = *from; + *from = tmp; + } + + /* *from = NULL is guaranteed */ +} + + +/** + * acpiphp_free_resource - free all linked resources + * @res: head of linked resource list + */ +void acpiphp_free_resource (struct pci_resource **res) +{ + struct pci_resource *tmp; + + while (*res) { + tmp = (*res)->next; + kfree(*res); + *res = tmp; + } + + /* *res = NULL is guaranteed */ +} + + +/* debug support functions; will go away sometime :) */ +static void dump_resource(struct pci_resource *head) +{ + struct pci_resource *p; + int cnt; + + p = head; + cnt = 0; + + while (p) { + info("[%02d] %08x - %08x", + cnt++, (u32)p->base, (u32)p->base + p->length - 1); + p = p->next; + } +} + +void acpiphp_dump_resource(struct acpiphp_bridge *bridge) +{ + info("I/O resource:"); + dump_resource(bridge->io_head); + info("MEM resource:"); + dump_resource(bridge->mem_head); + info("PMEM resource:"); + dump_resource(bridge->p_mem_head); + info("BUS resource:"); + dump_resource(bridge->bus_head); +} + +void acpiphp_dump_func_resource(struct acpiphp_func *func) +{ + info("I/O resource:"); + dump_resource(func->io_head); + info("MEM resource:"); + dump_resource(func->mem_head); + info("PMEM resource:"); + dump_resource(func->p_mem_head); + info("BUS resource:"); + dump_resource(func->bus_head); +} + +/* +EXPORT_SYMBOL(acpiphp_get_io_resource); +EXPORT_SYMBOL(acpiphp_get_max_resource); +EXPORT_SYMBOL(acpiphp_get_resource); +EXPORT_SYMBOL(acpiphp_resource_sort_and_combine); +*/ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/hotplug/cpqphp_nvram.c linux.19rc3-ac4/drivers/hotplug/cpqphp_nvram.c --- linux.19rc3/drivers/hotplug/cpqphp_nvram.c 2002-07-29 12:50:04.000000000 +0100 +++ linux.19rc3-ac4/drivers/hotplug/cpqphp_nvram.c 2002-07-29 13:58:39.000000000 +0100 @@ -176,12 +176,12 @@ spin_lock_irqsave(&int15_lock, flags); __asm__ ( - "xorl %%ebx,%%ebx - xorl %%edx,%%edx - pushf - push %%cs - cli - call *%6" + "xorl %%ebx,%%ebx \n" + "xorl %%edx,%%edx \n" + "pushf \n" + "push %%cs \n" + "cli \n" + "call *%6 \n" : "=c" (*buf_size), "=a" (ret_val) : "a" (op), "c" (*buf_size), "S" (ev_name), "D" (buffer), "m" (compaq_int15_entry_point) diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/hotplug/ibmphp_core.c linux.19rc3-ac4/drivers/hotplug/ibmphp_core.c --- linux.19rc3/drivers/hotplug/ibmphp_core.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/hotplug/ibmphp_core.c 2002-07-29 13:58:39.000000000 +0100 @@ -44,7 +44,7 @@ #define get_ctrl_revision(sl, rev) ibmphp_hpc_readslot (sl, READ_REVLEVEL, rev) #define get_hpc_options(sl, opt) ibmphp_hpc_readslot (sl, READ_HPCOPTIONS, opt) -#define DRIVER_VERSION "0.1" +#define DRIVER_VERSION "0.3" #define DRIVER_DESC "IBM Hot Plug PCI Controller Driver" int ibmphp_debug; @@ -393,8 +393,8 @@ pslot = (struct slot *) hotplug_slot->private; if (pslot) { rc = 0; - mode = pslot->bus_on->supported_bus_mode; - *value = pslot->bus_on->supported_speed; + mode = pslot->supported_bus_mode; + *value = pslot->supported_speed; *value &= 0x0f; if (mode == BUS_MODE_PCIX) @@ -1009,6 +1009,7 @@ } return rc; } + /******************************************************* * Returns whether the bus is empty or not *******************************************************/ @@ -1036,7 +1037,9 @@ /*********************************************************** * If the HPC permits and the bus currently empty, tries to set the - * bus speed and mode at the maximum card capability + * bus speed and mode at the maximum card and bus capability + * Parameters: slot + * Returns: bus is set (0) or error code ***********************************************************/ static int set_bus (struct slot * slot_cur) { @@ -1056,30 +1059,102 @@ cmd = HPC_BUS_33CONVMODE; break; case HPC_SLOT_SPEED_66: - if (SLOT_PCIX (slot_cur->ext_status)) - cmd = HPC_BUS_66PCIXMODE; - else - cmd = HPC_BUS_66CONVMODE; + if (SLOT_PCIX (slot_cur->ext_status)) { + if ((slot_cur->supported_speed >= BUS_SPEED_66) && (slot_cur->supported_bus_mode == BUS_MODE_PCIX)) + cmd = HPC_BUS_66PCIXMODE; + else if (!SLOT_BUS_MODE (slot_cur->ext_status)) + /* if max slot/bus capability is 66 pci + and there's no bus mode mismatch, then + the adapter supports 66 pci */ + cmd = HPC_BUS_66CONVMODE; + else + cmd = HPC_BUS_33CONVMODE; + } else { + if (slot_cur->supported_speed >= BUS_SPEED_66) + cmd = HPC_BUS_66CONVMODE; + else + cmd = HPC_BUS_33CONVMODE; + } break; case HPC_SLOT_SPEED_133: - if (slot_cur->bus_on->slot_count > 1) + switch (slot_cur->supported_speed) { + case BUS_SPEED_33: + cmd = HPC_BUS_33CONVMODE; + break; + case BUS_SPEED_66: + if (slot_cur->supported_bus_mode == BUS_MODE_PCIX) + cmd = HPC_BUS_66PCIXMODE; + else + cmd = HPC_BUS_66CONVMODE; + break; + case BUS_SPEED_100: cmd = HPC_BUS_100PCIXMODE; - else + break; + case BUS_SPEED_133: cmd = HPC_BUS_133PCIXMODE; + break; + default: + err ("Wrong bus speed \n"); + return -ENODEV; + } break; default: err ("wrong slot speed \n"); return -ENODEV; } debug ("setting bus speed for slot %d, cmd %x\n", slot_cur->number, cmd); - rc = ibmphp_hpc_writeslot (slot_cur, cmd); - if (rc) - return rc; + ibmphp_hpc_writeslot (slot_cur, cmd); } + /* This is for x400, once Brandon fixes the firmware, + will not need this delay */ + long_delay (1 * HZ); debug ("%s -Exit \n", __FUNCTION__); return 0; } +/* This routine checks the bus limitations that the slot is on from the BIOS. + * This is used in deciding whether or not to power up the slot. + * (electrical/spec limitations. For example, >1 133 MHz or >2 66 PCI cards on + * same bus) + * Parameters: slot + * Returns: 0 = no limitations, -EINVAL = exceeded limitations on the bus + */ +static int check_limitations (struct slot *slot_cur) +{ + u8 i; + struct slot * tmp_slot; + u8 count = 0; + u8 limitation = 0; + + for (i = slot_cur->bus_on->slot_min; i <= slot_cur->bus_on->slot_max; i++) { + tmp_slot = ibmphp_get_slot_from_physical_num (i); + if ((SLOT_POWER (tmp_slot->status)) && !(SLOT_CONNECT (tmp_slot->status))) + count++; + } + get_cur_bus_info (&slot_cur); + switch (slot_cur->bus_on->current_speed) { + case BUS_SPEED_33: + limitation = slot_cur->bus_on->slots_at_33_conv; + break; + case BUS_SPEED_66: + if (slot_cur->bus_on->current_bus_mode == BUS_MODE_PCIX) + limitation = slot_cur->bus_on->slots_at_66_pcix; + else + limitation = slot_cur->bus_on->slots_at_66_conv; + break; + case BUS_SPEED_100: + limitation = slot_cur->bus_on->slots_at_100_pcix; + break; + case BUS_SPEED_133: + limitation = slot_cur->bus_on->slots_at_133_pcix; + break; + } + + if ((count + 1) > limitation) + return -EINVAL; + return 0; +} + static inline void print_card_capability (struct slot *slot_cur) { info ("capability of the card is "); @@ -1136,7 +1211,28 @@ ibmphp_unlock_operations (); return -ENODEV; } - + + /*-----------------debugging------------------------------*/ + get_cur_bus_info (&slot_cur); + debug ("the current bus speed right after set_bus = %x \n", slot_cur->bus_on->current_speed); + /*----------------------------------------------------------*/ + + rc = check_limitations (slot_cur); + if (rc) { + err ("Adding this card exceeds the limitations of this bus. \n"); + err ("(i.e., >1 133MHz cards running on same bus, or >2 66 PCI cards running on same bus \n. Try hot-adding into another bus \n"); + attn_off (slot_cur); + attn_on (slot_cur); + + if (slot_update (&slot_cur)) { + ibmphp_unlock_operations (); + return -ENODEV; + } + ibmphp_update_slot_info (slot_cur); + ibmphp_unlock_operations (); + return -EINVAL; + } + rc = power_on (slot_cur); if (rc) { @@ -1151,19 +1247,24 @@ return -ENODEV; } /* Check to see the error of why it failed */ - if (!(SLOT_PWRGD (slot_cur->status))) + if ((SLOT_POWER (slot_cur->status)) && !(SLOT_PWRGD (slot_cur->status))) err ("power fault occured trying to power up \n"); else if (SLOT_BUS_SPEED (slot_cur->status)) { err ("bus speed mismatch occured. please check current bus speed and card capability \n"); print_card_capability (slot_cur); - } else if (SLOT_BUS_MODE (slot_cur->ext_status)) + } else if (SLOT_BUS_MODE (slot_cur->ext_status)) { err ("bus mode mismatch occured. please check current bus mode and card capability \n"); - + print_card_capability (slot_cur); + } ibmphp_update_slot_info (slot_cur); - ibmphp_unlock_operations (); + ibmphp_unlock_operations (); return rc; } debug ("after power_on\n"); + /*-----------------------debugging---------------------------*/ + get_cur_bus_info (&slot_cur); + debug ("the current bus speed right after power_on = %x \n", slot_cur->bus_on->current_speed); + /*----------------------------------------------------------*/ rc = slot_update (&slot_cur); if (rc) { @@ -1180,7 +1281,7 @@ if (SLOT_POWER (slot_cur->status) && !(SLOT_PWRGD (slot_cur->status))) { faulted = 1; - err ("power fault occured trying to power up...\n"); + err ("power fault occured trying to power up... \n"); } else if (SLOT_POWER (slot_cur->status) && (SLOT_BUS_SPEED (slot_cur->status))) { faulted = 1; err ("bus speed mismatch occured. please check current bus speed and card capability \n"); @@ -1200,8 +1301,8 @@ return rcpr; } - if (slot_update (&slot_cur)) { - ibmphp_unlock_operations (); + if (slot_update (&slot_cur)) { + ibmphp_unlock_operations (); return -ENODEV; } ibmphp_update_slot_info (slot_cur); @@ -1278,20 +1379,24 @@ { int rc; struct slot *slot_cur = (struct slot *) hotplug_slot->private; - u8 flag = slot_cur->flag; + u8 flag; + int parm = 0; - slot_cur->flag = TRUE; debug ("DISABLING SLOT... \n"); - ibmphp_lock_operations (); - if (slot_cur == NULL) { - ibmphp_unlock_operations (); + if (slot_cur == NULL) return -ENODEV; - } - if (slot_cur->ctrl == NULL) { - ibmphp_unlock_operations (); + + if (slot_cur->ctrl == NULL) return -ENODEV; - } + + flag = slot_cur->flag; /* to see if got here from polling */ + + if (flag) + ibmphp_lock_operations (); + + slot_cur->flag = TRUE; + if (flag == TRUE) { rc = validate (slot_cur, DISABLE); /* checking if powered off already & valid slot # */ if (rc) { @@ -1333,10 +1438,21 @@ ibmphp_unlock_operations (); return rc; } + + /* If we got here from latch suddenly opening on operating card or + a power fault, there's no power to the card, so cannot + read from it to determine what resources it occupied. This operation + is forbidden anyhow. The best we can do is remove it from kernel + lists at least */ + + if (!flag) { + attn_off (slot_cur); + return 0; + } - rc = ibmphp_unconfigure_card (&slot_cur, 0); + rc = ibmphp_unconfigure_card (&slot_cur, parm); slot_cur->func = NULL; - debug ("in disable_slot. after unconfigure_card \n"); + debug ("in disable_slot. after unconfigure_card\n"); if (rc) { err ("could not unconfigure card.\n"); attn_off (slot_cur); /* need to turn off if was blinking b4 */ @@ -1347,9 +1463,7 @@ return -EFAULT; } - if (flag) - ibmphp_update_slot_info (slot_cur); - + ibmphp_update_slot_info (slot_cur); ibmphp_unlock_operations (); return -EFAULT; } @@ -1363,9 +1477,7 @@ return -EFAULT; } - if (flag) - ibmphp_update_slot_info (slot_cur); - + ibmphp_update_slot_info (slot_cur); ibmphp_unlock_operations (); return rc; } @@ -1375,11 +1487,7 @@ ibmphp_unlock_operations (); return -EFAULT; } - if (flag) - rc = ibmphp_update_slot_info (slot_cur); - else - rc = 0; - + rc = ibmphp_update_slot_info (slot_cur); ibmphp_print_test (); ibmphp_unlock_operations(); return rc; @@ -1422,9 +1530,12 @@ int rc = 0; init_flag = 1; + + info (DRIVER_DESC " version: " DRIVER_VERSION "\n"); + ibmphp_pci_root_ops = get_root_pci_ops (); if (ibmphp_pci_root_ops == NULL) { - err ("cannot read bus operations... will not be able to read the cards. Please check your system \n"); + err ("cannot read bus operations... will not be able to read the cards. Please check your system\n"); return -ENODEV; } @@ -1439,13 +1550,13 @@ ibmphp_unload (); return rc; } - debug ("after ibmphp_access_ebda () \n"); + debug ("after ibmphp_access_ebda ()\n"); if ((rc = ibmphp_rsrc_init ())) { ibmphp_unload (); return rc; } - debug ("AFTER Resource & EBDA INITIALIZATIONS \n"); + debug ("AFTER Resource & EBDA INITIALIZATIONS\n"); max_slots = get_max_slots (); @@ -1463,7 +1574,6 @@ * so that no one can unload us. */ MOD_DEC_USE_COUNT; - info (DRIVER_DESC " version: " DRIVER_VERSION "\n"); return 0; } @@ -1471,9 +1581,9 @@ static void __exit ibmphp_exit (void) { ibmphp_hpc_stop_poll_thread (); - debug ("after polling \n"); + debug ("after polling\n"); ibmphp_unload (); - debug ("done \n"); + debug ("done\n"); } module_init (ibmphp_init); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/hotplug/ibmphp_ebda.c linux.19rc3-ac4/drivers/hotplug/ibmphp_ebda.c --- linux.19rc3/drivers/hotplug/ibmphp_ebda.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/hotplug/ibmphp_ebda.c 2002-07-29 13:58:39.000000000 +0100 @@ -161,9 +161,14 @@ debug ("%s - slot_count = %x\n", __FUNCTION__, ptr->slot_count); debug ("%s - bus# = %x\n", __FUNCTION__, ptr->busno); debug ("%s - current_speed = %x\n", __FUNCTION__, ptr->current_speed); - debug ("%s - supported_speed = %x\n", __FUNCTION__, ptr->supported_speed); debug ("%s - controller_id = %x\n", __FUNCTION__, ptr->controller_id); - debug ("%s - bus_mode = %x\n", __FUNCTION__, ptr->supported_bus_mode); + + debug ("%s - slots_at_33_conv = %x\n", __FUNCTION__, ptr->slots_at_33_conv); + debug ("%s - slots_at_66_conv = %x\n", __FUNCTION__, ptr->slots_at_66_conv); + debug ("%s - slots_at_66_pcix = %x\n", __FUNCTION__, ptr->slots_at_66_pcix); + debug ("%s - slots_at_100_pcix = %x\n", __FUNCTION__, ptr->slots_at_100_pcix); + debug ("%s - slots_at_133_pcix = %x\n", __FUNCTION__, ptr->slots_at_133_pcix); + } } @@ -455,19 +460,9 @@ bus_info_ptr1->index = bus_index++; bus_info_ptr1->current_speed = 0xff; bus_info_ptr1->current_bus_mode = 0xff; - if ( ((slot_ptr->slot_cap) & EBDA_SLOT_133_MAX) == EBDA_SLOT_133_MAX ) - bus_info_ptr1->supported_speed = 3; - else if ( ((slot_ptr->slot_cap) & EBDA_SLOT_100_MAX) == EBDA_SLOT_100_MAX ) - bus_info_ptr1->supported_speed = 2; - else if ( ((slot_ptr->slot_cap) & EBDA_SLOT_66_MAX) == EBDA_SLOT_66_MAX ) - bus_info_ptr1->supported_speed = 1; + bus_info_ptr1->controller_id = hpc_ptr->ctlr_id; - if ( ((slot_ptr->slot_cap) & EBDA_SLOT_PCIX_CAP) == EBDA_SLOT_PCIX_CAP ) - bus_info_ptr1->supported_bus_mode = 1; - else - bus_info_ptr1->supported_bus_mode =0; - - + list_add_tail (&bus_info_ptr1->bus_info_list, &bus_info_head); } else { @@ -486,9 +481,25 @@ /* init bus structure */ bus_ptr = hpc_ptr->buses; for (bus = 0; bus < bus_num; bus++) { - bus_ptr->bus_num = readb (io_mem + addr_bus); + bus_ptr->bus_num = readb (io_mem + addr_bus + bus); + bus_ptr->slots_at_33_conv = readb (io_mem + addr_bus + bus_num + 8 * bus); + bus_ptr->slots_at_66_conv = readb (io_mem + addr_bus + bus_num + 8 * bus + 1); + + bus_ptr->slots_at_66_pcix = readb (io_mem + addr_bus + bus_num + 8 * bus + 2); + + bus_ptr->slots_at_100_pcix = readb (io_mem + addr_bus + bus_num + 8 * bus + 3); + + bus_ptr->slots_at_133_pcix = readb (io_mem + addr_bus + bus_num + 8 * bus + 4); + + bus_info_ptr2 = ibmphp_find_same_bus_num (bus_ptr->bus_num); + if (bus_info_ptr2) { + bus_info_ptr2->slots_at_33_conv = bus_ptr->slots_at_33_conv; + bus_info_ptr2->slots_at_66_conv = bus_ptr->slots_at_66_conv; + bus_info_ptr2->slots_at_66_pcix = bus_ptr->slots_at_66_pcix; + bus_info_ptr2->slots_at_100_pcix = bus_ptr->slots_at_100_pcix; + bus_info_ptr2->slots_at_133_pcix = bus_ptr->slots_at_133_pcix; + } bus_ptr++; - addr_bus += 1; } hpc_ptr->ctlr_type = temp; @@ -511,10 +522,6 @@ case 2: hpc_ptr->u.wpeg_ctlr.wpegbbar = readl (io_mem + addr); hpc_ptr->u.wpeg_ctlr.i2c_addr = readb (io_mem + addr + 4); - /* following 2 lines for testing purpose */ - if (hpc_ptr->u.wpeg_ctlr.i2c_addr == 0) - hpc_ptr->ctlr_type = 4; - hpc_ptr->irq = readb (io_mem + addr + 5); addr += 6; @@ -537,6 +544,8 @@ hpc_ptr->revision = 0xff; hpc_ptr->options = 0xff; + hpc_ptr->starting_slot_num = hpc_ptr->slots[0].slot_num; + hpc_ptr->ending_slot_num = hpc_ptr->slots[slot_num-1].slot_num; // register slots with hpc core as well as create linked list of ibm slot for (index = 0; index < hpc_ptr->slot_count; index++) { @@ -573,10 +582,24 @@ return -ENOMEM; } + ((struct slot *)hp_slot_ptr->private)->flag = TRUE; snprintf (hp_slot_ptr->name, 10, "%d", hpc_ptr->slots[index].slot_num); ((struct slot *) hp_slot_ptr->private)->capabilities = hpc_ptr->slots[index].slot_cap; + if ((hpc_ptr->slots[index].slot_cap & EBDA_SLOT_133_MAX) == EBDA_SLOT_133_MAX) + ((struct slot *) hp_slot_ptr->private)->supported_speed = 3; + else if ((hpc_ptr->slots[index].slot_cap & EBDA_SLOT_100_MAX) == EBDA_SLOT_100_MAX) + ((struct slot *) hp_slot_ptr->private)->supported_speed = 2; + else if ((hpc_ptr->slots[index].slot_cap & EBDA_SLOT_66_MAX) == EBDA_SLOT_66_MAX) + ((struct slot *) hp_slot_ptr->private)->supported_speed = 1; + + if ((hpc_ptr->slots[index].slot_cap & EBDA_SLOT_PCIX_CAP) == EBDA_SLOT_PCIX_CAP) + ((struct slot *) hp_slot_ptr->private)->supported_bus_mode = 1; + else + ((struct slot *) hp_slot_ptr->private)->supported_bus_mode = 0; + + ((struct slot *) hp_slot_ptr->private)->bus = hpc_ptr->slots[index].slot_bus_num; bus_info_ptr1 = ibmphp_find_same_bus_num (hpc_ptr->slots[index].slot_bus_num); @@ -591,7 +614,7 @@ ((struct slot *) hp_slot_ptr->private)->ctlr_index = hpc_ptr->slots[index].ctl_index; ((struct slot *) hp_slot_ptr->private)->number = hpc_ptr->slots[index].slot_num; - + ((struct slot *) hp_slot_ptr->private)->hotplug_slot = hp_slot_ptr; rc = ibmphp_hpc_fillhpslotinfo (hp_slot_ptr); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/hotplug/ibmphp.h linux.19rc3-ac4/drivers/hotplug/ibmphp.h --- linux.19rc3/drivers/hotplug/ibmphp.h 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/hotplug/ibmphp.h 2002-07-29 13:58:39.000000000 +0100 @@ -168,13 +168,11 @@ struct ebda_hpc_bus { u32 bus_num; -/* u8 slots_at_33_conv; u8 slots_at_66_conv; u8 slots_at_66_pcix; u8 slots_at_100_pcix; u8 slots_at_133_pcix; -*/ }; @@ -232,12 +230,15 @@ u8 slot_max; u8 slot_count; u8 busno; - u8 current_speed; - u8 supported_speed; u8 controller_id; - u8 supported_bus_mode; + u8 current_speed; u8 current_bus_mode; u8 index; + u8 slots_at_33_conv; + u8 slots_at_66_conv; + u8 slots_at_66_pcix; + u8 slots_at_100_pcix; + u8 slots_at_133_pcix; struct list_head bus_info_list; }; @@ -690,8 +691,11 @@ u8 bus; u8 device; u8 number; + u8 real_physical_slot_num; char name[100]; u32 capabilities; + u8 supported_speed; + u8 supported_bus_mode; struct hotplug_slot *hotplug_slot; struct controller *ctrl; struct pci_func *func; @@ -709,10 +713,12 @@ struct controller { struct ebda_hpc_slot *slots; struct ebda_hpc_bus *buses; + u8 starting_slot_num; /* starting and ending slot #'s this ctrl controls*/ + u8 ending_slot_num; u8 revision; u8 options; /* which options HPC supports */ u8 status; - u8 ctlr_id; /* TONI */ + u8 ctlr_id; u8 slot_count; u8 bus_count; u8 ctlr_relative_id; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/hotplug/ibmphp_hpc.c linux.19rc3-ac4/drivers/hotplug/ibmphp_hpc.c --- linux.19rc3/drivers/hotplug/ibmphp_hpc.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/hotplug/ibmphp_hpc.c 2002-07-29 13:58:39.000000000 +0100 @@ -3,7 +3,7 @@ * * Written By: Jyoti Shah, IBM Corporation * - * Copyright (c) 2001,2001 IBM Corp. + * Copyright (c) 2001-2002 IBM Corp. * * All rights reserved. * @@ -27,7 +27,6 @@ * */ -//#include #include #include #include @@ -35,9 +34,6 @@ #include #include "ibmphp.h" -#define POLL_NO 0x01 -#define POLL_YES 0x00 - static int to_debug = FALSE; #define debug_polling(fmt, arg...) do { if (to_debug) debug (fmt, arg); } while (0) @@ -83,10 +79,6 @@ // //---------------------------------------------------------------------------- #define WPG_I2C_IOREMAP_SIZE 0x2044 // size of linear address interval -#define WPG_CTLR_MAX 0x01 // max controllers -#define WPG_SLOT_MAX 0x06 // max slots -#define WPG_CTLR_SLOT_MAX 0x06 // max slots per controller -#define WPG_FIRST_CTLR 0x00 // index of the controller //---------------------------------------------------------------------------- // command index @@ -102,19 +94,15 @@ // if bits 20,22,25,26,27,29,30 are OFF return TRUE #define HPC_I2CSTATUS_CHECK(s) ((u8)((s & 0x00000A76) ? FALSE : TRUE)) -// return code 0:poll slots, 1-POLL_LATCH_CNT:poll latch register -#define INCREMENT_POLLCNT(i) ((i < POLL_LATCH_CNT) ? i++ : (i=0)) //---------------------------------------------------------------------------- // global variables //---------------------------------------------------------------------------- static int ibmphp_shutdown; static int tid_poll; -static int stop_polling; // 2 values: poll, don't poll static struct semaphore sem_hpcaccess; // lock access to HPC static struct semaphore semOperations; // lock all operations and // access to data structures static struct semaphore sem_exit; // make sure polling thread goes away -static struct semaphore sem_poll; // make sure poll is idle //---------------------------------------------------------------------------- // local function prototypes //---------------------------------------------------------------------------- @@ -127,7 +115,7 @@ static void poll_hpc (void); static int update_slot (struct slot *, u8); static int process_changeinstatus (struct slot *, struct slot *); -static int process_changeinlatch (u8, u8); +static int process_changeinlatch (u8, u8, struct controller *); static int hpc_poll_thread (void *); static int hpc_wait_ctlr_notworking (int, struct controller *, void *, u8 *); //---------------------------------------------------------------------------- @@ -145,8 +133,6 @@ init_MUTEX (&sem_hpcaccess); init_MUTEX (&semOperations); init_MUTEX_LOCKED (&sem_exit); - init_MUTEX_LOCKED (&sem_poll); - stop_polling = POLL_YES; to_debug = FALSE; ibmphp_shutdown = FALSE; tid_poll = 0; @@ -277,8 +263,7 @@ int i; - debug_polling ("%s - Entry WPGBbar[%lx] index[%x] cmd[%x]\n", - __FUNCTION__, (ulong) WPGBbar, index, cmd); + debug_polling ("%s - Entry WPGBbar[%lx] index[%x] cmd[%x]\n", __FUNCTION__, (ulong) WPGBbar, index, cmd); rc = 0; //-------------------------------------------------------------------- @@ -470,8 +455,7 @@ int rc = 0; int busindex; - debug_polling ("%s - Entry pslot[%lx] cmd[%x] pstatus[%lx]\n", - __FUNCTION__, (ulong) pslot, cmd, (ulong) pstatus); + debug_polling ("%s - Entry pslot[%lx] cmd[%x] pstatus[%lx]\n", __FUNCTION__, (ulong) pslot, cmd, (ulong) pstatus); if ((pslot == NULL) || ((pstatus == NULL) && (cmd != READ_ALLSTAT) && (cmd != READ_BUSSTATUS))) { @@ -716,11 +700,6 @@ void ibmphp_lock_operations (void) { down (&semOperations); - stop_polling = POLL_NO; - to_debug = TRUE; - - /* waiting for polling to actually stop */ - down (&sem_poll); } /*---------------------------------------------------------------------- @@ -729,8 +708,6 @@ void ibmphp_unlock_operations (void) { debug ("%s - Entry\n", __FUNCTION__); - stop_polling = POLL_YES; - to_debug = FALSE; up (&semOperations); debug ("%s - Exit\n", __FUNCTION__); } @@ -738,34 +715,30 @@ /*---------------------------------------------------------------------- * Name: poll_hpc() *---------------------------------------------------------------------*/ +#define POLL_LATCH_REGISTER 0 +#define POLL_SLOTS 1 +#define POLL_SLEEP 2 static void poll_hpc (void) { - struct slot myslot, *pslot = NULL; + struct slot myslot; + struct slot *pslot = NULL; struct list_head *pslotlist; int rc; + int poll_state = POLL_LATCH_REGISTER; u8 oldlatchlow = 0x00; u8 curlatchlow = 0x00; - int pollcnt = 0; + int poll_count = 0; u8 ctrl_count = 0x00; - debug ("poll_hpc - Entry\n"); + debug ("%s - Entry\n", __FUNCTION__); while (!ibmphp_shutdown) { - if (stop_polling) { - debug ("poll_hpc - stop_polling\n"); - up (&sem_poll); - /* to prevent deadlock */ - if (ibmphp_shutdown) - break; - /* to make the thread sleep */ - down (&semOperations); - up (&semOperations); - debug ("poll_hpc - after stop_polling sleep\n"); - } else { - if (pollcnt) { - // only poll the latch register - oldlatchlow = curlatchlow; + /* try to get the lock to do some kind of harware access */ + down (&semOperations); + switch (poll_state) { + case POLL_LATCH_REGISTER: + oldlatchlow = curlatchlow; ctrl_count = 0x00; list_for_each (pslotlist, &ibmphp_slot_head) { if (ctrl_count >= ibmphp_get_total_controllers()) @@ -779,14 +752,16 @@ &curlatchlow); if (oldlatchlow != curlatchlow) process_changeinlatch (oldlatchlow, - curlatchlow); + curlatchlow, + pslot->ctrl); } } } - } else { + poll_state = POLL_SLOTS; + break; + + case POLL_SLOTS: list_for_each (pslotlist, &ibmphp_slot_head) { - if (stop_polling) - break; pslot = list_entry (pslotlist, struct slot, ibm_slot_list); // make a copy of the old status memcpy ((void *) &myslot, (void *) pslot, @@ -797,31 +772,45 @@ process_changeinstatus (pslot, &myslot); } - if (!stop_polling) { - ctrl_count = 0x00; - list_for_each (pslotlist, &ibmphp_slot_head) { - if (ctrl_count >= ibmphp_get_total_controllers()) - break; - pslot = - list_entry (pslotlist, struct slot, - ibm_slot_list); - if (pslot->ctrl->ctlr_relative_id == ctrl_count) { - ctrl_count++; - if (READ_SLOT_LATCH (pslot->ctrl)) - rc = ibmphp_hpc_readslot (pslot, - READ_SLOTLATCHLOWREG, - &curlatchlow); - } + ctrl_count = 0x00; + list_for_each (pslotlist, &ibmphp_slot_head) { + if (ctrl_count >= ibmphp_get_total_controllers()) + break; + pslot = list_entry (pslotlist, struct slot, ibm_slot_list); + if (pslot->ctrl->ctlr_relative_id == ctrl_count) { + ctrl_count++; + if (READ_SLOT_LATCH (pslot->ctrl)) + rc = ibmphp_hpc_readslot (pslot, + READ_SLOTLATCHLOWREG, + &curlatchlow); } } - } - INCREMENT_POLLCNT (pollcnt); - long_delay (POLL_INTERVAL_SEC * HZ); // snooze + ++poll_count; + if (poll_count >= POLL_LATCH_CNT) { + poll_count = 0; + poll_state = POLL_SLEEP; + } + break; + + case POLL_SLEEP: + /* don't sleep with a lock on the hardware */ + up (&semOperations); + long_delay (POLL_INTERVAL_SEC * HZ); + down (&semOperations); + poll_state = POLL_LATCH_REGISTER; + break; } + + /* give up the harware semaphore */ + up (&semOperations); + + /* sleep for a short time just for good measure */ + set_current_state (TASK_INTERRUPTIBLE); + schedule_timeout (HZ/10); } - up (&sem_poll); + up (&sem_exit); - debug ("poll_hpc - Exit\n"); + debug ("%s - Exit\n", __FUNCTION__); } @@ -917,7 +906,6 @@ // bit 0 - HPC_SLOT_POWER if ((pslot->status & 0x01) != (poldslot->status & 0x01)) - /* ????????? DO WE NEED TO UPDATE BUS SPEED INFO HERE ??? */ update = TRUE; // bit 1 - HPC_SLOT_CONNECT @@ -936,7 +924,7 @@ // bit 5 - HPC_SLOT_PWRGD if ((pslot->status & 0x20) != (poldslot->status & 0x20)) // OFF -> ON: ignore, ON -> OFF: disable slot - if (poldslot->status & 0x20) + if ((poldslot->status & 0x20) && (SLOT_CONNECT (poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT (poldslot->status))) disable = TRUE; // bit 6 - HPC_SLOT_BUS_SPEED @@ -947,20 +935,20 @@ update = TRUE; // OPEN -> CLOSE if (pslot->status & 0x80) { - if (SLOT_POWER (pslot->status)) { + if (SLOT_PWRGD (pslot->status)) { // power goes on and off after closing latch // check again to make sure power is still ON long_delay (1 * HZ); rc = ibmphp_hpc_readslot (pslot, READ_SLOTSTATUS, &status); - if (SLOT_POWER (status)) + if (SLOT_PWRGD (status)) update = TRUE; else // overwrite power in pslot to OFF pslot->status &= ~HPC_SLOT_POWER; } } // CLOSE -> OPEN - else if ((SLOT_POWER (poldslot->status) == HPC_SLOT_POWER_ON) - || (SLOT_CONNECT (poldslot->status) == HPC_SLOT_CONNECTED)) { + else if ((SLOT_PWRGD (poldslot->status) == HPC_SLOT_PWRGD_GOOD) + && (SLOT_CONNECT (poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT (poldslot->status))) { disable = TRUE; } // else - ignore @@ -994,7 +982,7 @@ * Return 0 or error codes * Value: *---------------------------------------------------------------------*/ -static int process_changeinlatch (u8 old, u8 new) +static int process_changeinlatch (u8 old, u8 new, struct controller *ctrl) { struct slot myslot, *pslot; u8 i; @@ -1004,7 +992,7 @@ debug ("%s - Entry old[%x], new[%x]\n", __FUNCTION__, old, new); // bit 0 reserved, 0 is LSB, check bit 1-6 for 6 slots - for (i = 1; i <= 6; i++) { + for (i = ctrl->starting_slot_num; i <= ctrl->ending_slot_num; i++) { mask = 0x01 << i; if ((mask & old) != (mask & new)) { pslot = ibmphp_get_slot_from_physical_num (i); @@ -1090,7 +1078,6 @@ // cleanup free_hpc_access (); ibmphp_unlock_operations (); - up (&sem_poll); up (&sem_exit); debug ("ibmphp_hpc_stop_poll_thread - Exit\n"); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/hotplug/Makefile linux.19rc3-ac4/drivers/hotplug/Makefile --- linux.19rc3/drivers/hotplug/Makefile 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/hotplug/Makefile 2002-07-29 13:58:39.000000000 +0100 @@ -4,14 +4,14 @@ O_TARGET := vmlinux-obj.o -list-multi := cpqphp.o pci_hotplug.o ibmphp.o pcihpacpi.o +list-multi := cpqphp.o pci_hotplug.o ibmphp.o acpiphp.o export-objs := pci_hotplug_core.o pci_hotplug_util.o obj-$(CONFIG_HOTPLUG_PCI) += pci_hotplug.o obj-$(CONFIG_HOTPLUG_PCI_COMPAQ) += cpqphp.o obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.o -obj-$(CONFIG_HOTPLUG_PCI_ACPI) += pcihpacpi.o +obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o pci_hotplug-objs := pci_hotplug_core.o \ pci_hotplug_util.o @@ -34,8 +34,10 @@ endif endif -pcihp_acpi_objs := pcihp_acpi.o \ - pcihp_acpi_glue.o +acpiphp_objs := acpiphp_core.o \ + acpiphp_glue.o \ + acpiphp_pci.o \ + acpiphp_res.o ifeq ($(CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM),y) cpqphp-objs += cpqphp_nvram.o @@ -53,5 +55,5 @@ ibmphp.o: $(ibmphp-objs) $(LD) -r -o $@ $(ibmphp-objs) -pcihpacpi.o: $(pcihp_acpi_objs) - $(LD) -r -o $@ $(pcihp_acpi_objs) +acpiphp.o: $(acpiphp_objs) + $(LD) -r -o $@ $(acpiphp_objs) diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/hotplug/pcihp_acpi.c linux.19rc3-ac4/drivers/hotplug/pcihp_acpi.c --- linux.19rc3/drivers/hotplug/pcihp_acpi.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/hotplug/pcihp_acpi.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,397 +0,0 @@ -/* - * ACPI PCI Hot Plug Controller Driver - * - * Copyright (c) 2001-2002 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (c) 2001-2002 IBM Corp. - * Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com) - * Copyright (c) 2002 Takayoshi Kochi (t-kouchi@cq.jp.nec.com) - * Copyright (c) 2002 NEC Corporation - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This 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, GOOD TITLE or - * NON INFRINGEMENT. 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. - * - * Send feedback to , - * , - * - * - */ - -#include -#include -#include -#include -#include -#include -#include "pci_hotplug.h" -#include "pcihp_acpi.h" - -static LIST_HEAD(slot_list); - -#if !defined(CONFIG_HOTPLUG_PCI_ACPI_MODULE) - #define MY_NAME "pcihp_acpi" -#else - #define MY_NAME THIS_MODULE->name -#endif - -/* local variables */ -static int debug = 1; /* XXX */ -static int num_slots; - -#define DRIVER_VERSION "0.2" -#define DRIVER_AUTHOR "Greg Kroah-Hartman " -#define DRIVER_DESC "ACPI Hot Plug PCI Controller Driver" - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); -MODULE_PARM(debug, "i"); -MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); - -static int enable_slot (struct hotplug_slot *slot); -static int disable_slot (struct hotplug_slot *slot); -static int set_attention_status (struct hotplug_slot *slot, u8 value); -static int hardware_test (struct hotplug_slot *slot, u32 value); -static int get_power_status (struct hotplug_slot *slot, u8 *value); -static int get_attention_status (struct hotplug_slot *slot, u8 *value); -static int get_latch_status (struct hotplug_slot *slot, u8 *value); -static int get_adapter_status (struct hotplug_slot *slot, u8 *value); - -static struct hotplug_slot_ops acpi_hotplug_slot_ops = { - owner: THIS_MODULE, - enable_slot: enable_slot, - disable_slot: disable_slot, - set_attention_status: set_attention_status, - hardware_test: hardware_test, - get_power_status: get_power_status, - get_attention_status: get_attention_status, - get_latch_status: get_latch_status, - get_adapter_status: get_adapter_status, -}; - - -/* Inline functions to check the sanity of a pointer that is passed to us */ -static inline int slot_paranoia_check (struct slot *slot, const char *function) -{ - if (!slot) { - dbg("%s - slot == NULL", function); - return -1; - } - if (slot->magic != SLOT_MAGIC) { - dbg("%s - bad magic number for slot", function); - return -1; - } - if (!slot->hotplug_slot) { - dbg("%s - slot->hotplug_slot == NULL!", function); - return -1; - } - return 0; -} - -static inline struct slot *get_slot (struct hotplug_slot *hotplug_slot, const char *function) -{ - struct slot *slot; - - if (!hotplug_slot) { - dbg("%s - hotplug_slot == NULL", function); - return NULL; - } - - slot = (struct slot *)hotplug_slot->private; - if (slot_paranoia_check (slot, function)) - return NULL; - return slot; -} - - -static int enable_slot (struct hotplug_slot *hotplug_slot) -{ - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); - int retval = 0; - - if (slot == NULL) - return -ENODEV; - - dbg ("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); - - /* enable the specified slot */ - retval = pcihp_acpi_enable_slot (slot->acpi_slot); - - return retval; -} - -static int disable_slot (struct hotplug_slot *hotplug_slot) -{ - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); - int retval = 0; - - if (slot == NULL) - return -ENODEV; - - dbg ("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); - - /* disable the specified slot */ - retval = pcihp_acpi_disable_slot (slot->acpi_slot); - - return retval; -} - -static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status) -{ - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); - int retval = 0; - - if (slot == NULL) - return -ENODEV; - - dbg ("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); - - /* TBD - * ACPI doesn't have known method to manipulate - * attention status LED - */ - switch (status) { - case 0: - /* FIXME turn light off */ - slot->attention_status = 0; - break; - - case 1: - default: - /* FIXME turn light on */ - slot->attention_status = 1; - break; - } - - return retval; -} - -static int hardware_test (struct hotplug_slot *hotplug_slot, u32 value) -{ - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); - int retval = 0; - - if (slot == NULL) - return -ENODEV; - - dbg ("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); - - err ("No hardware tests are defined for this driver"); - retval = -ENODEV; - - return retval; -} - -static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value) -{ - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); - int retval = 0; - - if (slot == NULL) - return -ENODEV; - - dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); - - *value = pcihp_acpi_get_power_status (slot->acpi_slot); - - return retval; -} - -static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value) -{ - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); - int retval = 0; - - if (slot == NULL) - return -ENODEV; - - dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); - - *value = slot->attention_status; - - return retval; -} - -static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value) -{ - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); - int retval = 0; - - if (slot == NULL) - return -ENODEV; - - dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); - - *value = pcihp_acpi_get_latch_status (slot->acpi_slot); - - return retval; -} - -static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) -{ - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); - int retval = 0; - - if (slot == NULL) - return -ENODEV; - - dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); - - *value = pcihp_acpi_get_adapter_status (slot->acpi_slot); - - return retval; -} - -static int init_acpi (void) -{ - int retval; - - dbg("init_acpi"); /* XXX */ - /* initialize internal data structure etc. */ - retval = pcihp_acpi_glue_init(); - - /* read initial number of slots */ - if (!retval) { - num_slots = pcihp_acpi_get_num_slots(); - if (num_slots == 0) - retval = -ENODEV; - } - - return retval; -} - -static void exit_acpi (void) -{ - /* deallocate internal data structures etc. */ - pcihp_acpi_glue_exit(); -} - -#define SLOT_NAME_SIZE 10 -static void make_slot_name (struct slot *slot) -{ - /* FIXME - get this from the ACPI representation of the slot */ - snprintf (slot->hotplug_slot->name, SLOT_NAME_SIZE, "ACPI%d", slot->number); -} - -static int init_slots (void) -{ - struct slot *slot; - int retval = 0; - int i; - - for (i = 0; i < num_slots; ++i) { - slot = kmalloc (sizeof (struct slot), GFP_KERNEL); - if (!slot) - return -ENOMEM; - memset(slot, 0, sizeof(struct slot)); - - slot->hotplug_slot = kmalloc (sizeof (struct hotplug_slot), GFP_KERNEL); - if (!slot->hotplug_slot) { - kfree (slot); - return -ENOMEM; - } - memset(slot->hotplug_slot, 0, sizeof (struct hotplug_slot)); - - slot->hotplug_slot->info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL); - if (!slot->hotplug_slot->info) { - kfree (slot->hotplug_slot); - kfree (slot); - return -ENOMEM; - } - memset(slot->hotplug_slot->info, 0, sizeof (struct hotplug_slot_info)); - - slot->hotplug_slot->name = kmalloc (SLOT_NAME_SIZE, GFP_KERNEL); - if (!slot->hotplug_slot->name) { - kfree (slot->hotplug_slot->info); - kfree (slot->hotplug_slot); - kfree (slot); - return -ENOMEM; - } - - slot->magic = SLOT_MAGIC; - slot->number = i; - - slot->hotplug_slot->private = slot; - make_slot_name (slot); - slot->hotplug_slot->ops = &acpi_hotplug_slot_ops; - - slot->acpi_slot = get_slot_from_id (i); - slot->hotplug_slot->info->power_status = pcihp_acpi_get_power_status(slot->acpi_slot); - slot->hotplug_slot->info->attention_status = pcihp_acpi_get_attention_status(slot->acpi_slot); - slot->hotplug_slot->info->latch_status = pcihp_acpi_get_latch_status(slot->acpi_slot); - slot->hotplug_slot->info->adapter_status = pcihp_acpi_get_adapter_status(slot->acpi_slot); - - dbg ("registering slot %d", i); - retval = pci_hp_register (slot->hotplug_slot); - if (retval) { - err ("pci_hp_register failed with error %d", retval); - kfree (slot->hotplug_slot->info); - kfree (slot->hotplug_slot->name); - kfree (slot->hotplug_slot); - kfree (slot); - return retval; - } - - /* add slot to our internal list */ - list_add (&slot->slot_list, &slot_list); - } - - return retval; -} - -static void cleanup_slots (void) -{ - struct list_head *tmp; - struct slot *slot; - - list_for_each (tmp, &slot_list) { - slot = list_entry (tmp, struct slot, slot_list); - list_del (&slot->slot_list); - pci_hp_deregister (slot->hotplug_slot); - kfree (slot->hotplug_slot->info); - kfree (slot->hotplug_slot->name); - kfree (slot->hotplug_slot); - kfree (slot); - } - - return; -} - -static int __init pcihp_acpi_init(void) -{ - int retval; - - /* read all the ACPI info from the system */ - retval = init_acpi(); - if (retval) - return retval; - - retval = init_slots(); - if (retval) - return retval; - - info (DRIVER_DESC " version: " DRIVER_VERSION); - return 0; -} - -static void __exit pcihp_acpi_exit(void) -{ - cleanup_slots(); - exit_acpi(); -} - -module_init(pcihp_acpi_init); -module_exit(pcihp_acpi_exit); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/hotplug/pcihp_acpi_ctrl.c linux.19rc3-ac4/drivers/hotplug/pcihp_acpi_ctrl.c --- linux.19rc3/drivers/hotplug/pcihp_acpi_ctrl.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/hotplug/pcihp_acpi_ctrl.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,642 +0,0 @@ -/* - * ACPI PCI HotPlug Utility functions - * - * Copyright (c) 1995,2001 Compaq Computer Corporation - * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (c) 2001 IBM Corp. - * Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com) - * Copyright (c) 2002 Takayoshi Kochi (t-kouchi@cq.jp.nec.com) - * Copyright (c) 2002 NEC Corporation - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This 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, GOOD TITLE or - * NON INFRINGEMENT. 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. - * - * Send feedback to , - * - */ - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include - -#define _LINUX /* for acpi subcomponent */ - -#include "include/acpi.h" - -#include "pci_hotplug.h" -#include "pchihp_acpi.h" - -#if !defined(CONFIG_HOTPLUG_PCI_MODULE) - #define MY_NAME "pci_hotplug" -#else - #define MY_NAME THIS_MODULE->name -#endif - -#define dbg(fmt, arg...) do { if (debug) printk(KERN_WARNING "%s: "__FUNCTION__": " fmt , MY_NAME , ## arg); } while (0) -#define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg) -#define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg) -#define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg) - - -/* local variables */ -static int debug = 0; - -/* - * sort_by_size - * - * Sorts nodes on the list by their length. - * Smallest first. - * - */ -static int sort_by_size(struct pci_resource **head) -{ - struct pci_resource *current_res; - struct pci_resource *next_res; - int out_of_order = 1; - - if (!(*head)) - return(1); - - if (!((*head)->next)) - return(0); - - while (out_of_order) { - out_of_order = 0; - - // Special case for swapping list head - if (((*head)->next) && - ((*head)->length > (*head)->next->length)) { - out_of_order++; - current_res = *head; - *head = (*head)->next; - current_res->next = (*head)->next; - (*head)->next = current_res; - } - - current_res = *head; - - while (current_res->next && current_res->next->next) { - if (current_res->next->length > current_res->next->next->length) { - out_of_order++; - next_res = current_res->next; - current_res->next = current_res->next->next; - current_res = current_res->next; - next_res->next = current_res->next; - current_res->next = next_res; - } else - current_res = current_res->next; - } - } // End of out_of_order loop - - return(0); -} - - -/* - * sort_by_max_size - * - * Sorts nodes on the list by their length. - * Largest first. - * - */ -static int sort_by_max_size(struct pci_resource **head) -{ - struct pci_resource *current_res; - struct pci_resource *next_res; - int out_of_order = 1; - - if (!(*head)) - return(1); - - if (!((*head)->next)) - return(0); - - while (out_of_order) { - out_of_order = 0; - - // Special case for swapping list head - if (((*head)->next) && - ((*head)->length < (*head)->next->length)) { - out_of_order++; - current_res = *head; - *head = (*head)->next; - current_res->next = (*head)->next; - (*head)->next = current_res; - } - - current_res = *head; - - while (current_res->next && current_res->next->next) { - if (current_res->next->length < current_res->next->next->length) { - out_of_order++; - next_res = current_res->next; - current_res->next = current_res->next->next; - current_res = current_res->next; - next_res->next = current_res->next; - current_res->next = next_res; - } else - current_res = current_res->next; - } - } // End of out_of_order loop - - return(0); -} - -/* - * get_io_resource - * - * this function sorts the resource list by size and then - * returns the first node of "size" length that is not in the - * ISA aliasing window. If it finds a node larger than "size" - * it will split it up. - * - * size must be a power of two. - */ -struct pci_resource *hotplug_get_io_resource (struct pci_resource **head, u32 size) -{ - struct pci_resource *prevnode; - struct pci_resource *node; - struct pci_resource *split_node; - u32 temp_dword; - - if (!(*head)) - return(NULL); - - if ( hotplug_resource_sort_and_combine(head) ) - return(NULL); - - if ( sort_by_size(head) ) - return(NULL); - - for (node = *head; node; node = node->next) { - if (node->length < size) - continue; - - if (node->base & (size - 1)) { - // this one isn't base aligned properly - // so we'll make a new entry and split it up - temp_dword = (node->base | (size-1)) + 1; - - // Short circuit if adjusted size is too small - if ((node->length - (temp_dword - node->base)) < size) - continue; - - split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); - - if (!split_node) - return(NULL); - - split_node->base = node->base; - split_node->length = temp_dword - node->base; - node->base = temp_dword; - node->length -= split_node->length; - - // Put it in the list - split_node->next = node->next; - node->next = split_node; - } // End of non-aligned base - - // Don't need to check if too small since we already did - if (node->length > size) { - // this one is longer than we need - // so we'll make a new entry and split it up - split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); - - if (!split_node) - return(NULL); - - split_node->base = node->base + size; - split_node->length = node->length - size; - node->length = size; - - // Put it in the list - split_node->next = node->next; - node->next = split_node; - } // End of too big on top end - - // For IO make sure it's not in the ISA aliasing space - if (node->base & 0x300L) - continue; - - // If we got here, then it is the right size - // Now take it out of the list - if (*head == node) { - *head = node->next; - } else { - prevnode = *head; - while (prevnode->next != node) - prevnode = prevnode->next; - - prevnode->next = node->next; - } - node->next = NULL; - // Stop looping - break; - } - - return(node); -} - - -/* - * get_max_resource - * - * Gets the largest node that is at least "size" big from the - * list pointed to by head. It aligns the node on top and bottom - * to "size" alignment before returning it. - */ -struct pci_resource *hotplug_get_max_resource (struct pci_resource **head, u32 size) -{ - struct pci_resource *max; - struct pci_resource *temp; - struct pci_resource *split_node; - u32 temp_dword; - - if (!(*head)) - return(NULL); - - if (hotplug_resource_sort_and_combine(head)) - return(NULL); - - if (sort_by_max_size(head)) - return(NULL); - - for (max = *head;max; max = max->next) { - - // If not big enough we could probably just bail, - // instead we'll continue to the next. - if (max->length < size) - continue; - - if (max->base & (size - 1)) { - // this one isn't base aligned properly - // so we'll make a new entry and split it up - temp_dword = (max->base | (size-1)) + 1; - - // Short circuit if adjusted size is too small - if ((max->length - (temp_dword - max->base)) < size) - continue; - - split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); - - if (!split_node) - return(NULL); - - split_node->base = max->base; - split_node->length = temp_dword - max->base; - max->base = temp_dword; - max->length -= split_node->length; - - // Put it next in the list - split_node->next = max->next; - max->next = split_node; - } - - if ((max->base + max->length) & (size - 1)) { - // this one isn't end aligned properly at the top - // so we'll make a new entry and split it up - split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); - - if (!split_node) - return(NULL); - temp_dword = ((max->base + max->length) & ~(size - 1)); - split_node->base = temp_dword; - split_node->length = max->length + max->base - - split_node->base; - max->length -= split_node->length; - - // Put it in the list - split_node->next = max->next; - max->next = split_node; - } - - // Make sure it didn't shrink too much when we aligned it - if (max->length < size) - continue; - - // Now take it out of the list - temp = (struct pci_resource*) *head; - if (temp == max) { - *head = max->next; - } else { - while (temp && temp->next != max) { - temp = temp->next; - } - - temp->next = max->next; - } - - max->next = NULL; - return(max); - } - - // If we get here, we couldn't find one - return(NULL); -} - - -/* - * get_resource - * - * this function sorts the resource list by size and then - * returns the first node of "size" length. If it finds a node - * larger than "size" it will split it up. - * - * size must be a power of two. - */ -struct pci_resource *hotplug_get_resource (struct pci_resource **head, u32 size) -{ - struct pci_resource *prevnode; - struct pci_resource *node; - struct pci_resource *split_node; - u32 temp_dword; - - if (!(*head)) - return(NULL); - - if ( hotplug_resource_sort_and_combine(head) ) - return(NULL); - - if ( sort_by_size(head) ) - return(NULL); - - for (node = *head; node; node = node->next) { - dbg(__FUNCTION__": req_size =%x node=%p, base=%x, length=%x\n", - size, node, node->base, node->length); - if (node->length < size) - continue; - - if (node->base & (size - 1)) { - dbg(__FUNCTION__": not aligned\n"); - // this one isn't base aligned properly - // so we'll make a new entry and split it up - temp_dword = (node->base | (size-1)) + 1; - - // Short circuit if adjusted size is too small - if ((node->length - (temp_dword - node->base)) < size) - continue; - - split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); - - if (!split_node) - return(NULL); - - split_node->base = node->base; - split_node->length = temp_dword - node->base; - node->base = temp_dword; - node->length -= split_node->length; - - // Put it in the list - split_node->next = node->next; - node->next = split_node; - } // End of non-aligned base - - // Don't need to check if too small since we already did - if (node->length > size) { - dbg(__FUNCTION__": too big\n"); - // this one is longer than we need - // so we'll make a new entry and split it up - split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); - - if (!split_node) - return(NULL); - - split_node->base = node->base + size; - split_node->length = node->length - size; - node->length = size; - - // Put it in the list - split_node->next = node->next; - node->next = split_node; - } // End of too big on top end - - dbg(__FUNCTION__": got one!!!\n"); - // If we got here, then it is the right size - // Now take it out of the list - if (*head == node) { - *head = node->next; - } else { - prevnode = *head; - while (prevnode->next != node) - prevnode = prevnode->next; - - prevnode->next = node->next; - } - node->next = NULL; - // Stop looping - break; - } - return(node); -} - -/* - * get_resource_with_base - * - * this function - * returns the first node of "size" length located at specified base address. - * If it finds a node larger than "size" it will split it up. - * - * size must be a power of two. - */ -struct pci_resource *hotplug_get_resource_with_base (struct pci_resource **head, u32 base, u32 size) -{ - struct pci_resource *prevnode; - struct pci_resource *node; - struct pci_resource *split_node; - u32 temp_dword; - - if (!(*head)) - return(NULL); - - if ( hotplug_resource_sort_and_combine(head) ) - return(NULL); - - for (node = *head; node; node = node->next) { - dbg(": 1st req_base=%x req_size =%x node=%p, base=%x, length=%x\n", - base, size, node, node->base, node->length); - if (node->base > base) - continue; - - if ((node->base + node->length) < (base + size)) - continue; - - if (node->base < base) { - dbg(": split 1\n"); - // this one isn't base aligned properly - // so we'll make a new entry and split it up - temp_dword = base; - - // Short circuit if adjusted size is too small - if ((node->length - (temp_dword - node->base)) < size) - continue; - - split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); - - if (!split_node) - return(NULL); - - split_node->base = node->base; - split_node->length = temp_dword - node->base; - node->base = temp_dword; - node->length -= split_node->length; - - // Put it in the list - split_node->next = node->next; - node->next = split_node; - } - - dbg(": 2st req_base=%x req_size =%x node=%p, base=%x, length=%x\n", - base, size, node, node->base, node->length); - - // Don't need to check if too small since we already did - if (node->length >= size) { - dbg(": split 2\n"); - // this one is longer than we need - // so we'll make a new entry and split it up - split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); - - if (!split_node) - return(NULL); - - split_node->base = node->base + size; - split_node->length = node->length - size; - node->length = size; - - // Put it in the list - split_node->next = node->next; - node->next = split_node; - } // End of too big on top end - - dbg(": got one!!!\n"); - // If we got here, then it is the right size - // Now take it out of the list - if (*head == node) { - *head = node->next; - } else { - prevnode = *head; - while (prevnode->next != node) - prevnode = prevnode->next; - - prevnode->next = node->next; - } - node->next = NULL; - // Stop looping - break; - } - return(node); -} - -/* - * hotplug_resource_sort_and_combine - * - * Sorts all of the nodes in the list in ascending order by - * their base addresses. Also does garbage collection by - * combining adjacent nodes. - * - * returns 0 if success - */ -int hotplug_resource_sort_and_combine(struct pci_resource **head) -{ - struct pci_resource *node1; - struct pci_resource *node2; - int out_of_order = 1; - - dbg(__FUNCTION__": head = %p, *head = %p\n", head, *head); - - if (!(*head)) - return(1); - - dbg("*head->next = %p\n",(*head)->next); - - if (!(*head)->next) - return(0); /* only one item on the list, already sorted! */ - - dbg("*head->base = 0x%x\n",(*head)->base); - dbg("*head->next->base = 0x%x\n",(*head)->next->base); - while (out_of_order) { - out_of_order = 0; - - // Special case for swapping list head - if (((*head)->next) && - ((*head)->base > (*head)->next->base)) { - node1 = *head; - (*head) = (*head)->next; - node1->next = (*head)->next; - (*head)->next = node1; - out_of_order++; - } - - node1 = (*head); - - while (node1->next && node1->next->next) { - if (node1->next->base > node1->next->next->base) { - out_of_order++; - node2 = node1->next; - node1->next = node1->next->next; - node1 = node1->next; - node2->next = node1->next; - node1->next = node2; - } else - node1 = node1->next; - } - } // End of out_of_order loop - - node1 = *head; - - while (node1 && node1->next) { - if ((node1->base + node1->length) == node1->next->base) { - // Combine - dbg("8..\n"); - node1->length += node1->next->length; - node2 = node1->next; - node1->next = node1->next->next; - kfree(node2); - } else - node1 = node1->next; - } - - return(0); -} - -/* -EXPORT_SYMBOL(hotplug_get_io_resource); -EXPORT_SYMBOL(hotplug_get_max_resource); -EXPORT_SYMBOL(hotplug_get_resource); -EXPORT_SYMBOL(hotplug_resource_sort_and_combine); -*/ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/hotplug/pcihp_acpi_glue.c linux.19rc3-ac4/drivers/hotplug/pcihp_acpi_glue.c --- linux.19rc3/drivers/hotplug/pcihp_acpi_glue.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/hotplug/pcihp_acpi_glue.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,757 +0,0 @@ -/* - * ACPI PCI HotPlug glue functions to ACPI CA subsystem - * - * Copyright (c) 2002 Takayoshi Kochi (t-kouchi@cq.jp.nec.com) - * Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com) - * Copyright (c) 2002 NEC Corporation - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This 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, GOOD TITLE or - * NON INFRINGEMENT. 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. - * - * Send feedback to - * - */ - -#include -#include -#include -#include -#include -#include "pcihp_acpi.h" - -/* - * TODO: - * resource management - * irq related interface? (_PRT) - * consider locking - */ - -static LIST_HEAD(bridge_list); - -static int debug = 1; /* XXX set 0 after debug */ -#define MY_NAME "pcihp_acpi_glue" - -static void handle_hotplug_event (acpi_handle, u32, void *); - -/* - * initialization & terminatation routines - */ - -/* - * Ejectable slot satisfies at least these conditions: - * 1. has _ADR method - * 2. has _STA method - * 3. has _EJ0 method - * - * optionally - * 1. has _PS0 method - * 2. has _PS3 method - * 3. TBD... - */ - -/* callback routine to check the existence of ejectable slots */ -static acpi_status -is_ejectable_slot (acpi_handle handle, u32 lvl, void *context, void **rv) -{ - acpi_status status; - acpi_handle tmp; - int *count = (int *)context; - - status = acpi_get_handle(handle, "_ADR", &tmp); - - if (ACPI_FAILURE(status)) { - return AE_OK; - } - - status = acpi_get_handle(handle, "_STA", &tmp); - - if (ACPI_FAILURE(status)) { - return AE_OK; - } - - status = acpi_get_handle(handle, "_EJ0", &tmp); - - if (ACPI_FAILURE(status)) { - return AE_OK; - } - - (*count)++; - - /* only one ejectable slot is enough */ - return AE_CTRL_TERMINATE; -} - - -/* callback routine to register each ACPI PCI slot object */ -static acpi_status -register_slot (acpi_handle handle, u32 lvl, void *context, void **rv) -{ - struct pcihp_acpi_bridge *bridge = (struct pcihp_acpi_bridge *)context; - struct pcihp_acpi_slot *slot, *newslot; - acpi_handle tmp; - acpi_status status = AE_OK; - static int num_slots = 0; /* XXX */ - unsigned long adr, sun, sta; - - status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); - - if (ACPI_FAILURE(status)) { - return AE_OK; - } - - status = acpi_get_handle(handle, "_EJ0", &tmp); - - if (ACPI_FAILURE(status)) { - dbg("This slot doesn't have _EJ0"); - //return AE_OK; - } - - status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); - - if (ACPI_FAILURE(status)) { - dbg("This slot doesn't have _STA"); - //return AE_OK; - } - - newslot = kmalloc(sizeof(struct pcihp_acpi_slot), GFP_KERNEL); - if (!newslot) { - return AE_NO_MEMORY; - } - - memset(newslot, 0, sizeof(struct pcihp_acpi_slot)); - - INIT_LIST_HEAD(&newslot->sibling); - newslot->bridge = bridge; - newslot->handle = handle; - newslot->device = (adr >> 16) & 0xffff; - newslot->function = adr & 0xffff; - newslot->status = sta; - newslot->sun = -1; - newslot->flags = SLOT_HAS_EJ0; - newslot->id = num_slots++; - bridge->nr_slots++; - - dbg("new slot id=%d device=0x%d function=0x%x", newslot->id, newslot->device, newslot->function); - - status = acpi_evaluate_integer(handle, "_SUN", NULL, &sun); - if (ACPI_SUCCESS(status)) { - newslot->sun = sun; - } - - if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS0", &tmp))) { - newslot->flags |= SLOT_HAS_PS0; - } - - if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS3", &tmp))) { - newslot->flags |= SLOT_HAS_PS3; - } - - /* search for objects that share the same slot */ - for (slot = bridge->slots; slot; slot = slot->next) - if (slot->device == newslot->device) { - dbg("found a sibling slot!"); - list_add(&slot->sibling, &newslot->sibling); - newslot->id = slot->id; - num_slots --; - bridge->nr_slots --; - break; - } - - /* link myself to bridge's slot list */ - newslot->next = bridge->slots; - bridge->slots = newslot; - - return AE_OK; -} - -/* see if it's worth managing this brige */ -static int -detect_ejectable_slots (acpi_handle *root) -{ - acpi_status status; - int count; - - count = 0; - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root, ACPI_UINT32_MAX, - is_ejectable_slot, (void *)&count, NULL); - - dbg("%s: count=%d", __FUNCTION__, count); - return count; -} - - -/* - * push one resource to resource list - * - * TBD: use hotplug_resource_sort_and_combine - * TBD: 64bit resource handling (is it really used?) - */ -static void -push_resource (u32 base, u32 length, struct pci_resource **resource) -{ - struct pci_resource *resp, *newres; - int coalesced = 0; - - if (length == 0) { - dbg("zero sized resource. ignored."); - return; - } - - for (resp = *resource; resp; resp = resp->next) { - - /* coalesce contiguous region */ - - if (resp->base + resp->length == base) { - resp->length += length; - coalesced = 1; - break; - } - } - - if (!coalesced) { - newres = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); - if (!newres) { - /* TBD panic? */ - return; - } - newres->base = base; - newres->length = length; - newres->next = (*resource); - *resource = newres; - } -} - - -/* decode ACPI _CRS data and convert into our internal resource list */ -static void -decode_acpi_resource (acpi_resource *resource, struct pcihp_acpi_bridge *bridge) -{ - acpi_resource_address16 *address16_data; - acpi_resource_address32 *address32_data; - //acpi_resource_address64 *address64_data; - - u32 resource_type, producer_consumer, min_address_range, max_address_range, address_length; - u16 cache_attribute = 0; - - int done = 0, found; - - /* shut up gcc */ - resource_type = producer_consumer = min_address_range = max_address_range = address_length = 0; - - while (!done) { - found = 0; - - switch (resource->id) { - case ACPI_RSTYPE_ADDRESS16: - address16_data = (acpi_resource_address16 *)&resource->data; - resource_type = address16_data->resource_type; - producer_consumer = address16_data->producer_consumer; - min_address_range = address16_data->min_address_range; - max_address_range = address16_data->max_address_range; - address_length = address16_data->address_length; - if (resource_type == ACPI_MEMORY_RANGE) - cache_attribute = address16_data->attribute.memory.cache_attribute; - found = 1; - break; - - case ACPI_RSTYPE_ADDRESS32: - address32_data = (acpi_resource_address32 *)&resource->data; - resource_type = address32_data->resource_type; - producer_consumer = address32_data->producer_consumer; - min_address_range = address32_data->min_address_range; - max_address_range = address32_data->max_address_range; - address_length = address32_data->address_length; - if (resource_type == ACPI_MEMORY_RANGE) - cache_attribute = address32_data->attribute.memory.cache_attribute; - found = 1; - break; -/* - case ACPI_RSTYPE_ADDRESS64: - address64_data = (acpi_resource_address64 *)&resource->data; - resource_type = address64_data->resource_type; - break; -*/ - case ACPI_RSTYPE_END_TAG: - done = 1; - break; - - default: - /* ignore */ - break; - } - - resource = (acpi_resource *)((char*)resource + resource->length); - if (found && producer_consumer == ACPI_PRODUCER) { - switch (resource_type) { - case ACPI_MEMORY_RANGE: - if (cache_attribute == ACPI_PREFETCHABLE_MEMORY) { - dbg("resource type: prefetchable memory 0x%x - 0x%x", min_address_range, max_address_range); - push_resource(min_address_range, - address_length, - &bridge->free_prefetch); - } else { - dbg("resource type: memory 0x%x - 0x%x", min_address_range, max_address_range); - push_resource(min_address_range, - address_length, - &bridge->free_mem); - } - break; - case ACPI_IO_RANGE: - dbg("resource type: io 0x%x - 0x%x", min_address_range, max_address_range); - push_resource(min_address_range, - address_length, - &bridge->free_io); - break; - case ACPI_BUS_NUMBER_RANGE: - dbg("resource type: bus number %d - %d", min_address_range, max_address_range); - push_resource(min_address_range, - address_length, - &bridge->free_bus); - break; - default: - /* invalid type */ - break; - } - } - } -} - - -/* allocate and initialize bridge data structure */ -static int add_bridge (acpi_handle *handle) -{ - struct pcihp_acpi_bridge *bridge; - acpi_status status; - acpi_buffer buffer; - unsigned long tmp; - acpi_handle dummy_handle; - int sta = -1; - - status = acpi_get_handle(handle, "_STA", &dummy_handle); - if (ACPI_SUCCESS(status)) { - status = acpi_evaluate_integer(handle, "_STA", NULL, &tmp); - if (ACPI_FAILURE(status)) { - dbg("%s: _STA evaluation failure", __FUNCTION__); - return 0; - } - sta = tmp; - } - - if (sta >= 0 && !(sta & ACPI_STA_PRESENT)) - /* don't register this object */ - return 0; - - dbg("%s: _STA: 0x%x", __FUNCTION__, (unsigned int)sta); - - /* check if this bridge has ejectable slots */ - - detect_ejectable_slots(handle); - //if (detect_ejectable_slots(handle) == 0) - //return 0; - - /* allocate per-bridge data structure and fill in */ - - bridge = kmalloc(sizeof(struct pcihp_acpi_bridge), GFP_KERNEL); - if (bridge == NULL) - return -ENOMEM; - - memset(bridge, 0, sizeof(struct pcihp_acpi_bridge)); - - if (sta >= 0) - bridge->flags |= BRIDGE_HAS_STA; - - /* get PCI segment number */ - status = acpi_evaluate_integer(handle, "_SEG", NULL, &tmp); - - if (ACPI_SUCCESS(status)) { - bridge->seg = tmp; - } else { - bridge->seg = 0; - } - - /* get PCI bus number */ - status = acpi_evaluate_integer(handle, "_BBN", NULL, &tmp); - - if (ACPI_SUCCESS(status)) { - bridge->bus = tmp; - } else { - bridge->bus = 0; - } - - /* to be overridden when we decode _CRS */ - bridge->sub = bridge->bus; - - /* register all slot objects under this bridge */ - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, ACPI_UINT32_MAX, - register_slot, bridge, NULL); - - /* decode resources */ - buffer.length = 0; - buffer.pointer = NULL; - - - /* TBD use new ACPI_ALLOCATE_BUFFER */ - status = acpi_get_current_resources(handle, &buffer); - if (status != AE_BUFFER_OVERFLOW) { - return -1; - } - - buffer.pointer = kmalloc(buffer.length, GFP_KERNEL); - if (!buffer.pointer) { - return -1; - } - - status = acpi_get_current_resources(handle, &buffer); - if (ACPI_FAILURE(status)) { - return -1; - } - - decode_acpi_resource(buffer.pointer, bridge); - - /* TBD decode _HPP (hot plug parameters) */ - // decode_hpp(bridge); - - kfree(buffer.pointer); - - /* check already allocated resources */ - /* TBD */ - - /* install notify handler */ - dbg("installing notify handler"); - status = acpi_install_notify_handler(handle, - ACPI_SYSTEM_NOTIFY, - handle_hotplug_event, NULL); - - if (ACPI_FAILURE(status)) { - err("failed to register interrupt notify handler"); - } - - list_add(&bridge->list, &bridge_list); - - return 0; -} - - -/* callback routine to enumerate all the bridges in ACPI namespace */ -static acpi_status -check_pci_bridge (acpi_handle handle, u32 lvl, void *context, void **rv) -{ - acpi_status status; - acpi_device_info info; - char objname[5]; - acpi_buffer buffer = { sizeof(objname), objname }; - - status = acpi_get_object_info(handle, &info); - if (ACPI_FAILURE(status)) { - dbg("%s: failed to get bridge information", __FUNCTION__); - return AE_OK; /* continue */ - } - - info.hardware_id[sizeof(info.hardware_id)-1] = '\0'; - - if (strcmp(info.hardware_id, ACPI_PCI_ROOT_HID) == 0) { - - acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer); - dbg("%s: found PCI root bridge[%s]", __FUNCTION__, objname); - - add_bridge(handle); - } - return AE_OK; -} - - -/* interrupt handler */ -static void handle_hotplug_event (acpi_handle handle, u32 type, void *data) -{ - char objname[5]; - acpi_buffer buffer = { sizeof(objname), objname }; - - acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer); - - switch (type) { - case ACPI_NOTIFY_BUS_CHECK: - /* hot insertion/surprise removal */ - /* TBD */ - dbg("%s: Bus check notify on %s", __FUNCTION__, objname); - break; - - case ACPI_NOTIFY_DEVICE_CHECK: - /* TBD */ - dbg("%s: Device check notify on %s", __FUNCTION__, objname); - break; - - case ACPI_NOTIFY_EJECT_REQUEST: - /* eject button pushed */ - /* TBD */ - dbg("%s: Device eject notify on %s", __FUNCTION__, objname); - break; - - default: - warn("notify_handler: unknown event type 0x%x", type); - break; - } -} - - -/* - * external interfaces - */ - -int pcihp_acpi_glue_init (void) -{ - acpi_status status; - - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, check_pci_bridge, - NULL, NULL); - - if (ACPI_FAILURE(status)) { - dbg("%s: acpi_walk_namespace() failed", __FUNCTION__); - } - - return 0; -} - -static void free_all_resources (struct pcihp_acpi_bridge *bridge) -{ - struct pci_resource *res, *next;; - - for (res = bridge->free_io; res; ) { - next = res->next; - kfree(res); - res = next; - } - - for (res = bridge->free_mem; res; ) { - next = res->next; - kfree(res); - res = next; - } - - for (res = bridge->free_prefetch; res; ) { - next = res->next; - kfree(res); - res = next; - } - - for (res = bridge->free_bus; res; ) { - next = res->next; - kfree(res); - res = next; - } -} - - -void pcihp_acpi_glue_exit (void) -{ - struct list_head *node; - struct pcihp_acpi_bridge *bridge; - struct pcihp_acpi_slot *slot, *next; - - list_for_each(node, &bridge_list) { - bridge = (struct pcihp_acpi_bridge *)node; - slot = bridge->slots; - while (slot) { - next = slot->next; - kfree(slot); - slot = next; - } - free_all_resources(bridge); - kfree(bridge); - } -} - - -int pcihp_acpi_get_num_slots (void) -{ - struct list_head *node; - struct pcihp_acpi_bridge *bridge; - int num_slots; - - num_slots = 0; - - list_for_each(node, &bridge_list) { - bridge = (struct pcihp_acpi_bridge *)node; - dbg("Bus:%d num_slots:%d", bridge->bus, bridge->nr_slots); - num_slots += bridge->nr_slots; - } - - dbg("num_slots = %d", num_slots); - return num_slots; -} - - -/* TBD: improve performance */ -struct pcihp_acpi_slot *get_slot_from_id (int id) -{ - struct list_head *node; - struct pcihp_acpi_bridge *bridge; - struct pcihp_acpi_slot *slot; - - list_for_each(node, &bridge_list) { - bridge = (struct pcihp_acpi_bridge *)node; - for (slot = bridge->slots; slot; slot = slot->next) - if (slot->id == id) - return slot; - } - - /* should never happen! */ - dbg("%s: no object for id %d",__FUNCTION__, id); - return 0; -} - - -/* power on slot */ -int pcihp_acpi_enable_slot (struct pcihp_acpi_slot *slot) -{ - acpi_status status; - - if (slot->flags & SLOT_HAS_PS0) { - dbg("%s: powering on bus%d/dev%d.", __FUNCTION__, - slot->bridge->bus, slot->device); - status = acpi_evaluate_object(slot->handle, "_PS0", NULL, NULL); - if (ACPI_FAILURE(status)) { - warn("%s: powering on bus%d/dev%d failed", - __FUNCTION__, slot->bridge->bus, slot->device); - return -1; - } - } - - return 0; -} - - -/* power off slot */ -int pcihp_acpi_disable_slot (struct pcihp_acpi_slot *slot) -{ - acpi_status status; - - if (slot->flags & SLOT_HAS_PS3) { - dbg("%s: powering off bus%d/dev%d.", __FUNCTION__, - slot->bridge->bus, slot->device); - status = acpi_evaluate_object(slot->handle, "_PS3", NULL, NULL); - if (ACPI_FAILURE(status)) { - warn("%s: _PS3 on bus%d/dev%d failed", - __FUNCTION__, slot->bridge->bus, slot->device); - return -1; - } - } - - if (slot->flags & SLOT_HAS_EJ0) { - dbg("%s: eject bus%d/dev%d.", __FUNCTION__, - slot->bridge->bus, slot->device); - status = acpi_evaluate_object(slot->handle, "_EJ0", NULL, NULL); - if (ACPI_FAILURE(status)) { - warn("%s: _EJ0 bus%d/dev%d failed", - __FUNCTION__, slot->bridge->bus, slot->device); - return -1; - } - } - - /* TBD - * evaluate _STA to check if state is successfully changed - * and update status - */ - - return 0; -} - - -static unsigned int get_slot_status(struct pcihp_acpi_slot *slot) -{ - acpi_status status; - unsigned long sta; - - status = acpi_evaluate_integer(slot->handle, "_STA", NULL, &sta); - - if (ACPI_FAILURE(status)) { - err("%s: _STA evaluation failed", __FUNCTION__); - return 0; - } - - return (int)sta; -} - - -/* - * slot enabled: 1 - * slot disabled: 0 - */ -u8 pcihp_acpi_get_power_status (struct pcihp_acpi_slot *slot) -{ - unsigned int sta; - - /* TBD - * . guarantee check _STA on function# 0 - * . check configuration space before _STA? - */ - - sta = get_slot_status(slot); - - return (sta & ACPI_STA_ENABLED) ? 1 : 0; -} - - -/* XXX this function is not used */ -/* - * attention LED ON: 1 - * OFF: 0 - */ -u8 pcihp_acpi_get_attention_status (struct pcihp_acpi_slot *slot) -{ - /* TBD - * no direct attention led status information via ACPI - */ - - return 0; -} - - -/* - * latch closed: 1 - * latch open: 0 - */ -u8 pcihp_acpi_get_latch_status (struct pcihp_acpi_slot *slot) -{ - unsigned int sta; - - /* TBD - * no direct latch information via ACPI - */ - - sta = get_slot_status(slot); - - return (sta & ACPI_STA_SHOW_IN_UI) ? 1 : 0; -} - - -/* - * adapter presence : 2 - * absence : 0 - */ -u8 pcihp_acpi_get_adapter_status (struct pcihp_acpi_slot *slot) -{ - unsigned int sta; - - /* TBD - * is this information correct? - */ - - sta = get_slot_status(slot); - - return (sta == 0) ? 0 : 2; -} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/hotplug/pcihp_acpi.h linux.19rc3-ac4/drivers/hotplug/pcihp_acpi.h --- linux.19rc3/drivers/hotplug/pcihp_acpi.h 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/hotplug/pcihp_acpi.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,231 +0,0 @@ -/* - * ACPI PCI Hot Plug Controller Driver - * - * Copyright (c) 1995,2001 Compaq Computer Corporation - * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (c) 2001 IBM Corp. - * Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com) - * Copyright (c) 2002 Takayoshi Kochi (t-kouchi@cq.jp.nec.com) - * Copyright (c) 2002 NEC Corporation - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This 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, GOOD TITLE or - * NON INFRINGEMENT. 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. - * - * Send feedback to , - * , - * - * - */ - -#ifndef _PCIHP_ACPI_H -#define _PCIHP_ACPI_H - -#include "include/acpi.h" - -#if ACPI_CA_VERSION < 0x20020201 -/* until we get a new version of the ACPI driver for both ia32 and ia64 ... */ -#define acpi_util_eval_error(h,p,s) - -static acpi_status -acpi_evaluate_integer ( - acpi_handle handle, - acpi_string pathname, - acpi_object_list *arguments, - unsigned long *data) -{ - acpi_status status = AE_OK; - acpi_object element; - acpi_buffer buffer = {sizeof(acpi_object), &element}; - - if (!data) - return AE_BAD_PARAMETER; - - status = acpi_evaluate_object(handle, pathname, arguments, &buffer); - if (ACPI_FAILURE(status)) { - acpi_util_eval_error(handle, pathname, status); - return status; - } - - if (element.type != ACPI_TYPE_INTEGER) { - acpi_util_eval_error(handle, pathname, AE_BAD_DATA); - return AE_BAD_DATA; - } - - *data = element.integer.value; - - return AE_OK; -} -#else /* ACPI_CA_VERSION < 0x20020201 */ -#include "acpi_bus.h" -#endif /* ACPI_CA_VERSION < 0x20020201 */ - -/* compatibility stuff */ -#ifndef ACPI_MEMORY_RANGE -#define ACPI_MEMORY_RANGE MEMORY_RANGE -#endif - -#ifndef ACPI_IO_RANGE -#define ACPI_IO_RANGE IO_RANGE -#endif - -#ifndef ACPI_BUS_NUMBER_RANGE -#define ACPI_BUS_NUMBER_RANGE BUS_NUMBER_RANGE -#endif - -#ifndef ACPI_PREFETCHABLE_MEMORY -#define ACPI_PREFETCHABLE_MEMORY PREFETCHABLE_MEMORY -#endif - -#ifndef ACPI_PRODUCER -#define ACPI_PRODUCER PRODUCER -#endif - - -#define dbg(format, arg...) \ - do { \ - if (debug) \ - printk (KERN_DEBUG "%s: " format "\n", \ - MY_NAME , ## arg); \ - } while (0) -#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg) -#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg) -#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg) - -/* - * types and constants - */ - -#define SLOT_MAGIC 0x67267322 - -struct pcihp_acpi_bridge; -struct pcihp_acpi_slot; - -/* slot information for each *physical* slot */ - -struct slot { - u32 magic; - u8 number; - struct hotplug_slot *hotplug_slot; - struct list_head slot_list; - - int attention_status; - - struct pci_resource *mem_head; - struct pci_resource *p_mem_head; - struct pci_resource *io_head; - struct pci_resource *bus_head; - - /* if there are multiple corresponding slot objects, - this point to one of them */ - struct pcihp_acpi_slot *acpi_slot; - - struct pci_dev *pci_dev; -}; - -#define RESOURCE_TYPE_IO (1) -#define RESOURCE_TYPE_MEM (2) -#define RESOURCE_TYPE_PREFETCH (3) -#define RESOURCE_TYPE_BUS (4) - -/* TBD 64bit resource support */ -struct pci_resource { - struct pci_resource * next; - u32 base; - u32 length; -}; - -/* bridge information for each bridge device in ACPI namespace */ - -struct pcihp_acpi_bridge { - struct list_head list; - acpi_handle handle; - struct pcihp_acpi_slot *slots; - int nr_slots; - u8 seg; - u8 bus; - u8 sub; - u32 status; - u32 flags; - - /* resources on this bus (free resources) */ - struct pci_resource *free_io; - struct pci_resource *free_mem; - struct pci_resource *free_prefetch; - struct pci_resource *free_bus; - - /* used resources (embedded or owned resources) */ - struct pci_resource *used_io; - struct pci_resource *used_mem; - struct pci_resource *used_prefetch; - struct pci_resource *used_bus; -}; - -/* - * slot information for each slot object in ACPI namespace - * usually 8 objects per slot (for each PCI function) - */ - -struct pcihp_acpi_slot { - struct pcihp_acpi_slot *next; - struct pcihp_acpi_bridge *bridge; /* this slot located on */ - struct list_head sibling; /* one slot may have different - objects (i.e. for each function) */ - acpi_handle handle; - u32 id; /* slot id (this driver specific) */ - u8 device; /* pci device# */ - u8 function; /* pci function# */ - u8 pin; /* pci interrupt pin */ - u32 sun; /* _SUN */ - u32 flags; /* see below */ - u32 status; /* _STA */ -}; - -/* PCI bus bridge HID */ -#define ACPI_PCI_ROOT_HID "PNP0A03" - -/* ACPI _STA method value (ignore bit 4; battery present) */ -#define ACPI_STA_PRESENT (0x00000001) -#define ACPI_STA_ENABLED (0x00000002) -#define ACPI_STA_SHOW_IN_UI (0x00000004) -#define ACPI_STA_FUNCTIONAL (0x00000008) -#define ACPI_STA_ALL (0x0000000f) - -/* bridge flags */ -#define BRIDGE_HAS_STA (0x00000001) - -/* slot flags */ - -#define SLOT_HAS_EJ0 (0x00000001) -#define SLOT_HAS_PS0 (0x00000002) -#define SLOT_HAS_PS3 (0x00000004) - -/* function prototypes */ - -/* pcihp_acpi_glue.c */ -extern int pcihp_acpi_glue_init (void); -extern void pcihp_acpi_glue_exit (void); -extern int pcihp_acpi_get_num_slots (void); -extern struct pcihp_acpi_slot *get_slot_from_id (int id); - -extern int pcihp_acpi_enable_slot (struct pcihp_acpi_slot *slot); -extern int pcihp_acpi_disable_slot (struct pcihp_acpi_slot *slot); -extern u8 pcihp_acpi_get_power_status (struct pcihp_acpi_slot *slot); -extern u8 pcihp_acpi_get_attention_status (struct pcihp_acpi_slot *slot); -extern u8 pcihp_acpi_get_latch_status (struct pcihp_acpi_slot *slot); -extern u8 pcihp_acpi_get_adapter_status (struct pcihp_acpi_slot *slot); - -#endif /* _PCIHP_ACPI_H */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/adma100.c linux.19rc3-ac4/drivers/ide/adma100.c --- linux.19rc3/drivers/ide/adma100.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/adma100.c 2002-07-29 13:58:39.000000000 +0100 @@ -0,0 +1,30 @@ +/* + * linux/drivers/ide/adma100.c -- basic support for Pacific Digital ADMA-100 boards + * + * Created 09 Apr 2002 by Mark Lord + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +void __init ide_init_adma100 (ide_hwif_t *hwif) +{ + u32 phy_admctl = pci_resource_start(hwif->pci_dev, 4) + 0x80 + (hwif->channel * 0x20); + void *v_admctl; + + hwif->autodma = 0; // not compatible with normal IDE DMA transfers + hwif->dma_base = 0; // disable DMA completely + hwif->io_ports[IDE_CONTROL_OFFSET] += 4; // chip needs offset of 6 instead of 2 + v_admctl = ioremap_nocache(phy_admctl, 1024); // map config regs, so we can turn on drive IRQs + *((unsigned short *)v_admctl) &= 3; // enable aIEN; preserve PIO mode + iounmap(v_admctl); // all done; unmap config regs +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/aec62xx.c linux.19rc3-ac4/drivers/ide/aec62xx.c --- linux.19rc3/drivers/ide/aec62xx.c 2002-07-29 12:49:58.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/aec62xx.c 2002-07-29 13:58:39.000000000 +0100 @@ -1,8 +1,7 @@ /* - * linux/drivers/ide/aec62xx.c Version 0.09 June. 9, 2000 + * linux/drivers/ide/aec62xx.c Version 0.11 March 27, 2002 * - * Copyright (C) 1999-2000 Andre Hedrick (andre@linux-ide.org) - * May be copied or modified under the terms of the GNU General Public License + * Copyright (C) 1999-2002 Andre Hedrick * */ @@ -48,154 +47,209 @@ static int aec62xx_get_info(char *, char **, off_t, int); extern int (*aec62xx_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); -static struct pci_dev *bmide_dev; -static int aec62xx_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - - u32 bibma = pci_resource_start(bmide_dev, 4); - u8 c0 = 0, c1 = 0; - u8 art = 0, uart = 0; +#define AEC_MAX_DEVS 5 - switch(bmide_dev->device) { - case PCI_DEVICE_ID_ARTOP_ATP850UF: - p += sprintf(p, "\n AEC6210 Chipset.\n"); - break; - case PCI_DEVICE_ID_ARTOP_ATP860: - p += sprintf(p, "\n AEC6260 No Bios Chipset.\n"); - break; - case PCI_DEVICE_ID_ARTOP_ATP860R: - p += sprintf(p, "\n AEC6260 Chipset.\n"); - break; - default: - p += sprintf(p, "\n AEC62?? Chipset.\n"); - break; - } +static struct pci_dev *aec_devs[AEC_MAX_DEVS]; +static int n_aec_devs; - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - c0 = inb_p((unsigned short)bibma + 0x02); - c1 = inb_p((unsigned short)bibma + 0x0a); - - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); - (void) pci_read_config_byte(bmide_dev, 0x4a, &art); - p += sprintf(p, " %sabled %sabled\n", - (art&0x02)?" en":"dis",(art&0x04)?" en":"dis"); - p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s %s %s\n", - (c0&0x20)?"yes":"no ",(c0&0x40)?"yes":"no ",(c1&0x20)?"yes":"no ",(c1&0x40)?"yes":"no "); +#undef DEBUG_AEC_REGS - switch(bmide_dev->device) { - case PCI_DEVICE_ID_ARTOP_ATP850UF: - (void) pci_read_config_byte(bmide_dev, 0x54, &art); - p += sprintf(p, "DMA Mode: %s(%s) %s(%s) %s(%s) %s(%s)\n", +static int aec62xx_get_info (char *buffer, char **addr, off_t offset, int count) +{ + char *p = buffer; + char *chipset_nums[] = {"error", "error", "error", "error", + "error", "error", "850UF", "860", + "860R", "865", "865R", "error" }; +// char *modes_33[] = {}; +// char *modes_34[] = {}; + int i; + + for (i = 0; i < n_aec_devs; i++) { + struct pci_dev *dev = aec_devs[i]; + // u32 iobase = dev->resource[4].start; + u32 iobase = pci_resource_start(dev, 4); + u8 c0 = inb_p(iobase + 0x02); + u8 c1 = inb_p(iobase + 0x0a); + u8 art = 0; +#ifdef DEBUG_AEC_REGS + u8 uart = 0; +#endif /* DEBUG_AEC_REGS */ + + p += sprintf(p, "\nController: %d\n", i); + p += sprintf(p, "Chipset: AEC%s\n", chipset_nums[dev->device]); + + p += sprintf(p, "--------------- Primary Channel " + "---------------- Secondary Channel " + "-------------\n"); + (void) pci_read_config_byte(dev, 0x4a, &art); + p += sprintf(p, " %sabled ", + (art&0x02)?" en":"dis"); + p += sprintf(p, " %sabled\n", + (art&0x04)?" en":"dis"); + p += sprintf(p, "--------------- drive0 --------- drive1 " + "-------- drive0 ---------- drive1 ------\n"); + p += sprintf(p, "DMA enabled: %s %s ", + (c0&0x20)?"yes":"no ",(c0&0x40)?"yes":"no "); + p += sprintf(p, " %s %s\n", + (c1&0x20)?"yes":"no ",(c1&0x40)?"yes":"no "); + + if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) { + (void) pci_read_config_byte(dev, 0x54, &art); + p += sprintf(p, "DMA Mode: %s(%s)", (c0&0x20)?((art&0x03)?"UDMA":" DMA"):" PIO", - (art&0x02)?"2":(art&0x01)?"1":"0", + (art&0x02)?"2":(art&0x01)?"1":"0"); + p += sprintf(p, " %s(%s)", (c0&0x40)?((art&0x0c)?"UDMA":" DMA"):" PIO", - (art&0x08)?"2":(art&0x04)?"1":"0", + (art&0x08)?"2":(art&0x04)?"1":"0"); + p += sprintf(p, " %s(%s)", (c1&0x20)?((art&0x30)?"UDMA":" DMA"):" PIO", - (art&0x20)?"2":(art&0x10)?"1":"0", + (art&0x20)?"2":(art&0x10)?"1":"0"); + p += sprintf(p, " %s(%s)\n", (c1&0x40)?((art&0xc0)?"UDMA":" DMA"):" PIO", (art&0x80)?"2":(art&0x40)?"1":"0"); - (void) pci_read_config_byte(bmide_dev, 0x40, &art); +#ifdef DEBUG_AEC_REGS + (void) pci_read_config_byte(dev, 0x40, &art); p += sprintf(p, "Active: 0x%02x", art); - (void) pci_read_config_byte(bmide_dev, 0x42, &art); + (void) pci_read_config_byte(dev, 0x42, &art); p += sprintf(p, " 0x%02x", art); - (void) pci_read_config_byte(bmide_dev, 0x44, &art); + (void) pci_read_config_byte(dev, 0x44, &art); p += sprintf(p, " 0x%02x", art); - (void) pci_read_config_byte(bmide_dev, 0x46, &art); + (void) pci_read_config_byte(dev, 0x46, &art); p += sprintf(p, " 0x%02x\n", art); - (void) pci_read_config_byte(bmide_dev, 0x41, &art); + (void) pci_read_config_byte(dev, 0x41, &art); p += sprintf(p, "Recovery: 0x%02x", art); - (void) pci_read_config_byte(bmide_dev, 0x43, &art); + (void) pci_read_config_byte(dev, 0x43, &art); p += sprintf(p, " 0x%02x", art); - (void) pci_read_config_byte(bmide_dev, 0x45, &art); + (void) pci_read_config_byte(dev, 0x45, &art); p += sprintf(p, " 0x%02x", art); - (void) pci_read_config_byte(bmide_dev, 0x47, &art); + (void) pci_read_config_byte(dev, 0x47, &art); p += sprintf(p, " 0x%02x\n", art); - break; - case PCI_DEVICE_ID_ARTOP_ATP860: - case PCI_DEVICE_ID_ARTOP_ATP860R: - (void) pci_read_config_byte(bmide_dev, 0x44, &art); - p += sprintf(p, "DMA Mode: %s(%s) %s(%s)", +#endif /* DEBUG_AEC_REGS */ + } else { + /* + * case PCI_DEVICE_ID_ARTOP_ATP860: + * case PCI_DEVICE_ID_ARTOP_ATP860R: + * case PCI_DEVICE_ID_ARTOP_ATP865: + * case PCI_DEVICE_ID_ARTOP_ATP865R: + */ + (void) pci_read_config_byte(dev, 0x44, &art); + p += sprintf(p, "DMA Mode: %s(%s)", (c0&0x20)?((art&0x07)?"UDMA":" DMA"):" PIO", - ((art&0x06)==0x06)?"4":((art&0x05)==0x05)?"4":((art&0x04)==0x04)?"3":((art&0x03)==0x03)?"2":((art&0x02)==0x02)?"1":((art&0x01)==0x01)?"0":"?", + ((art&0x07)==0x07)?"6": + ((art&0x06)==0x06)?"5": + ((art&0x05)==0x05)?"4": + ((art&0x04)==0x04)?"3": + ((art&0x03)==0x03)?"2": + ((art&0x02)==0x02)?"1": + ((art&0x01)==0x01)?"0":"?"); + p += sprintf(p, " %s(%s)", (c0&0x40)?((art&0x70)?"UDMA":" DMA"):" PIO", - ((art&0x60)==0x60)?"4":((art&0x50)==0x50)?"4":((art&0x40)==0x40)?"3":((art&0x30)==0x30)?"2":((art&0x20)==0x20)?"1":((art&0x10)==0x10)?"0":"?"); - (void) pci_read_config_byte(bmide_dev, 0x45, &art); - p += sprintf(p, " %s(%s) %s(%s)\n", + ((art&0x70)==0x70)?"6": + ((art&0x60)==0x60)?"5": + ((art&0x50)==0x50)?"4": + ((art&0x40)==0x40)?"3": + ((art&0x30)==0x30)?"2": + ((art&0x20)==0x20)?"1": + ((art&0x10)==0x10)?"0":"?"); + (void) pci_read_config_byte(dev, 0x45, &art); + p += sprintf(p, " %s(%s)", (c1&0x20)?((art&0x07)?"UDMA":" DMA"):" PIO", - ((art&0x06)==0x06)?"4":((art&0x05)==0x05)?"4":((art&0x04)==0x04)?"3":((art&0x03)==0x03)?"2":((art&0x02)==0x02)?"1":((art&0x01)==0x01)?"0":"?", + ((art&0x07)==0x07)?"6": + ((art&0x06)==0x06)?"5": + ((art&0x05)==0x05)?"4": + ((art&0x04)==0x04)?"3": + ((art&0x03)==0x03)?"2": + ((art&0x02)==0x02)?"1": + ((art&0x01)==0x01)?"0":"?"); + p += sprintf(p, " %s(%s)\n", (c1&0x40)?((art&0x70)?"UDMA":" DMA"):" PIO", - ((art&0x60)==0x60)?"4":((art&0x50)==0x50)?"4":((art&0x40)==0x40)?"3":((art&0x30)==0x30)?"2":((art&0x20)==0x20)?"1":((art&0x10)==0x10)?"0":"?"); - (void) pci_read_config_byte(bmide_dev, 0x40, &art); + ((art&0x70)==0x70)?"6": + ((art&0x60)==0x60)?"5": + ((art&0x50)==0x50)?"4": + ((art&0x40)==0x40)?"3": + ((art&0x30)==0x30)?"2": + ((art&0x20)==0x20)?"1": + ((art&0x10)==0x10)?"0":"?"); +#ifdef DEBUG_AEC_REGS + (void) pci_read_config_byte(dev, 0x40, &art); p += sprintf(p, "Active: 0x%02x", HIGH_4(art)); - (void) pci_read_config_byte(bmide_dev, 0x41, &art); + (void) pci_read_config_byte(dev, 0x41, &art); p += sprintf(p, " 0x%02x", HIGH_4(art)); - (void) pci_read_config_byte(bmide_dev, 0x42, &art); + (void) pci_read_config_byte(dev, 0x42, &art); p += sprintf(p, " 0x%02x", HIGH_4(art)); - (void) pci_read_config_byte(bmide_dev, 0x43, &art); + (void) pci_read_config_byte(dev, 0x43, &art); p += sprintf(p, " 0x%02x\n", HIGH_4(art)); - (void) pci_read_config_byte(bmide_dev, 0x40, &art); + (void) pci_read_config_byte(dev, 0x40, &art); p += sprintf(p, "Recovery: 0x%02x", LOW_4(art)); - (void) pci_read_config_byte(bmide_dev, 0x41, &art); + (void) pci_read_config_byte(dev, 0x41, &art); p += sprintf(p, " 0x%02x", LOW_4(art)); - (void) pci_read_config_byte(bmide_dev, 0x42, &art); + (void) pci_read_config_byte(dev, 0x42, &art); p += sprintf(p, " 0x%02x", LOW_4(art)); - (void) pci_read_config_byte(bmide_dev, 0x43, &art); + (void) pci_read_config_byte(dev, 0x43, &art); p += sprintf(p, " 0x%02x\n", LOW_4(art)); - (void) pci_read_config_byte(bmide_dev, 0x49, &uart); + (void) pci_read_config_byte(dev, 0x49, &uart); p += sprintf(p, "reg49h = 0x%02x ", uart); - (void) pci_read_config_byte(bmide_dev, 0x4a, &uart); + (void) pci_read_config_byte(dev, 0x4a, &uart); p += sprintf(p, "reg4ah = 0x%02x\n", uart); - break; - default: - break; +#endif /* DEBUG_AEC_REGS */ + } } - return p-buffer;/* => must be less than 4k! */ } #endif /* defined(DISPLAY_AEC62xx_TIMINGS) && defined(CONFIG_PROC_FS) */ byte aec62xx_proc = 0; -#ifdef CONFIG_AEC62XX_TUNING - struct chipset_bus_clock_list_entry { byte xfer_speed; - - byte chipset_settings_34; - byte ultra_settings_34; - - byte chipset_settings_33; - byte ultra_settings_33; + byte chipset_settings; + byte ultra_settings; }; -struct chipset_bus_clock_list_entry aec62xx_base [] = { +struct chipset_bus_clock_list_entry aec6xxx_33_base [] = { #ifdef CONFIG_BLK_DEV_IDEDMA - { XFER_UDMA_4, 0x41, 0x04, 0x31, 0x05 }, - { XFER_UDMA_3, 0x41, 0x03, 0x31, 0x04 }, - { XFER_UDMA_2, 0x41, 0x02, 0x31, 0x03 }, - { XFER_UDMA_1, 0x41, 0x01, 0x31, 0x02 }, - { XFER_UDMA_0, 0x41, 0x01, 0x31, 0x01 }, - - { XFER_MW_DMA_2, 0x41, 0x00, 0x31, 0x00 }, - { XFER_MW_DMA_1, 0x42, 0x00, 0x31, 0x00 }, - { XFER_MW_DMA_0, 0x7a, 0x00, 0x0a, 0x00 }, + { XFER_UDMA_6, 0x31, 0x07 }, + { XFER_UDMA_5, 0x31, 0x06 }, + { XFER_UDMA_4, 0x31, 0x05 }, + { XFER_UDMA_3, 0x31, 0x04 }, + { XFER_UDMA_2, 0x31, 0x03 }, + { XFER_UDMA_1, 0x31, 0x02 }, + { XFER_UDMA_0, 0x31, 0x01 }, + + { XFER_MW_DMA_2, 0x31, 0x00 }, + { XFER_MW_DMA_1, 0x31, 0x00 }, + { XFER_MW_DMA_0, 0x0a, 0x00 }, #endif /* CONFIG_BLK_DEV_IDEDMA */ - { XFER_PIO_4, 0x41, 0x00, 0x31, 0x00 }, - { XFER_PIO_3, 0x43, 0x00, 0x33, 0x00 }, - { XFER_PIO_2, 0x78, 0x00, 0x08, 0x00 }, - { XFER_PIO_1, 0x7a, 0x00, 0x0a, 0x00 }, - { XFER_PIO_0, 0x70, 0x00, 0x00, 0x00 }, - { 0, 0x00, 0x00, 0x00, 0x00 } + { XFER_PIO_4, 0x31, 0x00 }, + { XFER_PIO_3, 0x33, 0x00 }, + { XFER_PIO_2, 0x08, 0x00 }, + { XFER_PIO_1, 0x0a, 0x00 }, + { XFER_PIO_0, 0x00, 0x00 }, + { 0, 0x00, 0x00 } }; -extern char *ide_xfer_verbose (byte xfer_rate); +struct chipset_bus_clock_list_entry aec6xxx_34_base [] = { +#ifdef CONFIG_BLK_DEV_IDEDMA + { XFER_UDMA_6, 0x41, 0x06 }, + { XFER_UDMA_5, 0x41, 0x05 }, + { XFER_UDMA_4, 0x41, 0x04 }, + { XFER_UDMA_3, 0x41, 0x03 }, + { XFER_UDMA_2, 0x41, 0x02 }, + { XFER_UDMA_1, 0x41, 0x01 }, + { XFER_UDMA_0, 0x41, 0x01 }, + + { XFER_MW_DMA_2, 0x41, 0x00 }, + { XFER_MW_DMA_1, 0x42, 0x00 }, + { XFER_MW_DMA_0, 0x7a, 0x00 }, +#endif /* CONFIG_BLK_DEV_IDEDMA */ + { XFER_PIO_4, 0x41, 0x00 }, + { XFER_PIO_3, 0x43, 0x00 }, + { XFER_PIO_2, 0x78, 0x00 }, + { XFER_PIO_1, 0x7a, 0x00 }, + { XFER_PIO_0, 0x70, 0x00 }, + { 0, 0x00, 0x00 } +}; /* * TO DO: active tuning and correction of cards without a bios. @@ -203,31 +257,73 @@ static byte pci_bus_clock_list (byte speed, struct chipset_bus_clock_list_entry * chipset_table) { - int bus_speed = system_bus_clock(); - for ( ; chipset_table->xfer_speed ; chipset_table++) if (chipset_table->xfer_speed == speed) { - return ((byte) ((bus_speed <= 33) ? chipset_table->chipset_settings_33 : chipset_table->chipset_settings_34)); + return chipset_table->chipset_settings; } - return 0x00; + return chipset_table->chipset_settings; } static byte pci_bus_clock_list_ultra (byte speed, struct chipset_bus_clock_list_entry * chipset_table) { - int bus_speed = system_bus_clock(); - for ( ; chipset_table->xfer_speed ; chipset_table++) if (chipset_table->xfer_speed == speed) { - return ((byte) ((bus_speed <= 33) ? chipset_table->ultra_settings_33 : chipset_table->ultra_settings_34)); + return chipset_table->ultra_settings; } - return 0x00; + return chipset_table->ultra_settings; +} + +static byte aec62xx_ratemask (ide_drive_t *drive) +{ + struct pci_dev *dev = HWIF(drive)->pci_dev; + byte mode = 0x00; + + if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) { + mode |= 0x01; + } else if ((dev->device == PCI_DEVICE_ID_ARTOP_ATP860) || + (dev->device == PCI_DEVICE_ID_ARTOP_ATP860R)) { + mode |= 0x02; + } else if ((dev->device == PCI_DEVICE_ID_ARTOP_ATP865) || + (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R)) { + u32 bmide = pci_resource_start(dev, 4); + if (IN_BYTE(bmide+2) & 0x10) + mode |= 0x04; + else + mode |= 0x03; + } + if (!eighty_ninty_three(drive)) { + mode &= ~0xFE; + mode |= 0x01; + } + return (mode &= ~0xF8); +} + +static byte aec62xx_ratefilter (ide_drive_t *drive, byte speed) +{ +#ifdef CONFIG_BLK_DEV_IDEDMA + byte mode = aec62xx_ratemask(drive); + + switch(mode) { + case 0x04: while (speed > XFER_UDMA_6) speed--; break; + case 0x03: while (speed > XFER_UDMA_5) speed--; break; + case 0x02: while (speed > XFER_UDMA_4) speed--; break; + case 0x01: while (speed > XFER_UDMA_2) speed--; break; + case 0x00: + default: while (speed > XFER_MW_DMA_2) speed--; break; + break; + } +#else + while (speed > XFER_PIO_4) speed--; +#endif /* CONFIG_BLK_DEV_IDEDMA */ +// printk("%s: mode == %02x speed == %02x\n", drive->name, mode, speed); + return speed; } -static int aec6210_tune_chipset (ide_drive_t *drive, byte speed) +static int aec6210_tune_chipset (ide_drive_t *drive, byte xferspeed) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - int err = 0; + byte speed = aec62xx_ratefilter(drive, xferspeed); unsigned short d_conf = 0x0000; byte ultra = 0x00; byte ultra_conf = 0x00; @@ -236,11 +332,10 @@ byte tmp2 = 0x00; unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ - + local_irq_save(flags); pci_read_config_word(dev, 0x40|(2*drive->dn), &d_conf); - tmp0 = pci_bus_clock_list(speed, aec62xx_base); + tmp0 = pci_bus_clock_list(speed, + (struct chipset_bus_clock_list_entry *) dev->driver_data); SPLIT_BYTE(tmp0,tmp1,tmp2); MAKE_WORD(d_conf,tmp1,tmp2); pci_write_config_word(dev, 0x40|(2*drive->dn), d_conf); @@ -249,23 +344,21 @@ tmp2 = 0x00; pci_read_config_byte(dev, 0x54, &ultra); tmp1 = ((0x00 << (2*drive->dn)) | (ultra & ~(3 << (2*drive->dn)))); - ultra_conf = pci_bus_clock_list_ultra(speed, aec62xx_base); + ultra_conf = pci_bus_clock_list_ultra(speed, + (struct chipset_bus_clock_list_entry *) dev->driver_data); tmp2 = ((ultra_conf << (2*drive->dn)) | (tmp1 & ~(3 << (2*drive->dn)))); pci_write_config_byte(dev, 0x54, tmp2); - - __restore_flags(flags); /* local CPU only */ - - err = ide_config_drive_speed(drive, speed); - return(err); + local_irq_restore(flags); + return(ide_config_drive_speed(drive, speed)); } -static int aec6260_tune_chipset (ide_drive_t *drive, byte speed) +static int aec6260_tune_chipset (ide_drive_t *drive, byte xferspeed) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; byte unit = (drive->select.b.unit & 0x01); byte ultra_pci = hwif->channel ? 0x45 : 0x44; - int err = 0; + byte speed = aec62xx_ratefilter(drive, xferspeed); byte drive_conf = 0x00; byte ultra_conf = 0x00; byte ultra = 0x00; @@ -273,143 +366,91 @@ byte tmp2 = 0x00; unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ - + local_irq_save(flags); pci_read_config_byte(dev, 0x40|drive->dn, &drive_conf); - drive_conf = pci_bus_clock_list(speed, aec62xx_base); + drive_conf = pci_bus_clock_list(speed, + (struct chipset_bus_clock_list_entry *) dev->driver_data); pci_write_config_byte(dev, 0x40|drive->dn, drive_conf); pci_read_config_byte(dev, ultra_pci, &ultra); tmp1 = ((0x00 << (4*unit)) | (ultra & ~(7 << (4*unit)))); - ultra_conf = pci_bus_clock_list_ultra(speed, aec62xx_base); + ultra_conf = pci_bus_clock_list_ultra(speed, + (struct chipset_bus_clock_list_entry *) dev->driver_data); tmp2 = ((ultra_conf << (4*unit)) | (tmp1 & ~(7 << (4*unit)))); pci_write_config_byte(dev, ultra_pci, tmp2); - __restore_flags(flags); /* local CPU only */ - - if (!drive->init_speed) - drive->init_speed = speed; - - err = ide_config_drive_speed(drive, speed); - drive->current_speed = speed; - return(err); + local_irq_restore(flags); + return(ide_config_drive_speed(drive, speed)); } - static int aec62xx_tune_chipset (ide_drive_t *drive, byte speed) { - if (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) { - return ((int) aec6210_tune_chipset(drive, speed)); - } else { - return ((int) aec6260_tune_chipset(drive, speed)); + switch (HWIF(drive)->pci_dev->device) { + case PCI_DEVICE_ID_ARTOP_ATP865: + case PCI_DEVICE_ID_ARTOP_ATP865R: + case PCI_DEVICE_ID_ARTOP_ATP860: + case PCI_DEVICE_ID_ARTOP_ATP860R: + return ((int) aec6260_tune_chipset(drive, speed)); + case PCI_DEVICE_ID_ARTOP_ATP850UF: + return ((int) aec6210_tune_chipset(drive, speed)); + default: + return -1; } } #ifdef CONFIG_BLK_DEV_IDEDMA -static int config_aec6210_chipset_for_dma (ide_drive_t *drive, byte ultra) +static int config_chipset_for_dma (ide_drive_t *drive) { struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); - byte unit = (drive->select.b.unit & 0x01); - unsigned long dma_base = hwif->dma_base; - byte speed = -1; - - if (drive->media != ide_disk) - return ((int) ide_dma_off_quietly); - - if (((id->dma_ultra & 0x0010) || - (id->dma_ultra & 0x0008) || - (id->dma_ultra & 0x0004)) && (ultra)) { - speed = XFER_UDMA_2; - } else if ((id->dma_ultra & 0x0002) && (ultra)) { - speed = XFER_UDMA_1; - } else if ((id->dma_ultra & 0x0001) && (ultra)) { - speed = XFER_UDMA_0; - } else if (id->dma_mword & 0x0004) { - speed = XFER_MW_DMA_2; - } else if (id->dma_mword & 0x0002) { - speed = XFER_MW_DMA_1; - } else if (id->dma_mword & 0x0001) { - speed = XFER_MW_DMA_0; - } else if (id->dma_1word & 0x0004) { - speed = XFER_SW_DMA_2; - } else if (id->dma_1word & 0x0002) { - speed = XFER_SW_DMA_1; - } else if (id->dma_1word & 0x0001) { - speed = XFER_SW_DMA_0; - } else { - return ((int) ide_dma_off_quietly); - } - - outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2); - (void) aec6210_tune_chipset(drive, speed); - - return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_off : - ((id->dma_ultra >> 8) & 7) ? ide_dma_on : - ((id->dma_mword >> 8) & 7) ? ide_dma_on : - ((id->dma_1word >> 8) & 7) ? ide_dma_on : - ide_dma_off_quietly); -} - -static int config_aec6260_chipset_for_dma (ide_drive_t *drive, byte ultra) -{ - struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); - byte unit = (drive->select.b.unit & 0x01); - unsigned long dma_base = hwif->dma_base; - byte speed = -1; - byte ultra66 = eighty_ninty_three(drive); + byte mode = aec62xx_ratemask(drive); + byte speed; if (drive->media != ide_disk) return ((int) ide_dma_off_quietly); - - if ((id->dma_ultra & 0x0010) && (ultra) && (ultra66)) { - speed = XFER_UDMA_4; - } else if ((id->dma_ultra & 0x0008) && (ultra) && (ultra66)) { - speed = XFER_UDMA_3; - } else if ((id->dma_ultra & 0x0004) && (ultra)) { - speed = XFER_UDMA_2; - } else if ((id->dma_ultra & 0x0002) && (ultra)) { - speed = XFER_UDMA_1; - } else if ((id->dma_ultra & 0x0001) && (ultra)) { - speed = XFER_UDMA_0; - } else if (id->dma_mword & 0x0004) { - speed = XFER_MW_DMA_2; - } else if (id->dma_mword & 0x0002) { - speed = XFER_MW_DMA_1; - } else if (id->dma_mword & 0x0001) { - speed = XFER_MW_DMA_0; - } else if (id->dma_1word & 0x0004) { - speed = XFER_SW_DMA_2; - } else if (id->dma_1word & 0x0002) { - speed = XFER_SW_DMA_1; - } else if (id->dma_1word & 0x0001) { - speed = XFER_SW_DMA_0; - } else { - return ((int) ide_dma_off_quietly); + + switch(mode) { + case 0x04: + if (id->dma_ultra & 0x0040) + { speed = XFER_UDMA_6; break; } + case 0x03: + if (id->dma_ultra & 0x0020) + { speed = XFER_UDMA_5; break; } + case 0x02: + if (id->dma_ultra & 0x0010) + { speed = XFER_UDMA_4; break; } + if (id->dma_ultra & 0x0008) + { speed = XFER_UDMA_3; break; } + case 0x01: + if (id->dma_ultra & 0x0004) + { speed = XFER_UDMA_2; break; } + if (id->dma_ultra & 0x0002) + { speed = XFER_UDMA_1; break; } + if (id->dma_ultra & 0x0001) + { speed = XFER_UDMA_0; break; } + case 0x00: + if (id->dma_mword & 0x0004) + { speed = XFER_MW_DMA_2; break; } + if (id->dma_mword & 0x0002) + { speed = XFER_MW_DMA_1; break; } + if (id->dma_mword & 0x0001) + { speed = XFER_MW_DMA_0; break; } + if (id->dma_1word & 0x0004) + { speed = XFER_SW_DMA_2; break; } + if (id->dma_1word & 0x0002) + { speed = XFER_SW_DMA_1; break; } + if (id->dma_1word & 0x0001) + { speed = XFER_SW_DMA_0; break; } + default: + return ((int) ide_dma_off_quietly); } - outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2); - (void) aec6260_tune_chipset(drive, speed); + (void) aec62xx_tune_chipset(drive, speed); - return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_on : + return ((int) ((id->dma_ultra >> 11) & 15) ? ide_dma_on : ((id->dma_ultra >> 8) & 7) ? ide_dma_on : ((id->dma_mword >> 8) & 7) ? ide_dma_on : ((id->dma_1word >> 8) & 7) ? ide_dma_on : ide_dma_off_quietly); -} - -static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) -{ - switch(HWIF(drive)->pci_dev->device) { - case PCI_DEVICE_ID_ARTOP_ATP850UF: - return config_aec6210_chipset_for_dma(drive, ultra); - case PCI_DEVICE_ID_ARTOP_ATP860: - case PCI_DEVICE_ID_ARTOP_ATP860R: - return config_aec6260_chipset_for_dma(drive, ultra); - default: - return ((int) ide_dma_off_quietly); - } +// return ((int) ide_dma_on); } #endif /* CONFIG_BLK_DEV_IDEDMA */ @@ -427,16 +468,7 @@ case 1: speed = XFER_PIO_1; break; default: speed = XFER_PIO_0; break; } - - switch(HWIF(drive)->pci_dev->device) { - case PCI_DEVICE_ID_ARTOP_ATP850UF: - (void) aec6210_tune_chipset(drive, speed); - case PCI_DEVICE_ID_ARTOP_ATP860: - case PCI_DEVICE_ID_ARTOP_ATP860R: - (void) aec6260_tune_chipset(drive, speed); - default: - break; - } + (void) aec62xx_tune_chipset(drive, speed); } #ifdef CONFIG_BLK_DEV_IDEDMA @@ -453,9 +485,9 @@ } dma_func = ide_dma_off_quietly; if (id->field_valid & 4) { - if (id->dma_ultra & 0x001F) { + if (id->dma_ultra & 0x007F) { /* Force if Capable UltraDMA */ - dma_func = config_chipset_for_dma(drive, 1); + dma_func = config_chipset_for_dma(drive); if ((id->field_valid & 2) && (dma_func != ide_dma_on)) goto try_dma_modes; @@ -465,7 +497,7 @@ if ((id->dma_mword & 0x0007) || (id->dma_1word & 0x0007)) { /* Force if Capable regular DMA modes */ - dma_func = config_chipset_for_dma(drive, 0); + dma_func = config_chipset_for_dma(drive); if (dma_func != ide_dma_on) goto no_dma_set; } @@ -474,7 +506,7 @@ goto no_dma_set; } /* Consult the list of known "good" drives */ - dma_func = config_chipset_for_dma(drive, 0); + dma_func = config_chipset_for_dma(drive); if (dma_func != ide_dma_on) goto no_dma_set; } else { @@ -494,49 +526,81 @@ */ int aec62xx_dmaproc (ide_dma_action_t func, ide_drive_t *drive) { + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + switch (func) { case ide_dma_check: return config_drive_xfer_rate(drive); case ide_dma_lostirq: case ide_dma_timeout: - switch(HWIF(drive)->pci_dev->device) { + switch(dev->device) { case PCI_DEVICE_ID_ARTOP_ATP860: case PCI_DEVICE_ID_ARTOP_ATP860R: -// { -// int i = 0; -// byte reg49h = 0; -// pci_read_config_byte(HWIF(drive)->pci_dev, 0x49, ®49h); -// for (i=0;i<256;i++) -// pci_write_config_byte(HWIF(drive)->pci_dev, 0x49, reg49h|0x10); -// pci_write_config_byte(HWIF(drive)->pci_dev, 0x49, reg49h & ~0x10); -// } -// return 0; + case PCI_DEVICE_ID_ARTOP_ATP865: + case PCI_DEVICE_ID_ARTOP_ATP865R: + printk(" AEC62XX time out "); +#if 0 + { + int i = 0; + byte reg49h = 0; + pci_read_config_byte(HWIF(drive)->pci_dev, 0x49, ®49h); + for (i=0;i<256;i++) + pci_write_config_byte(HWIF(drive)->pci_dev, 0x49, reg49h|0x10); + pci_write_config_byte(HWIF(drive)->pci_dev, 0x49, reg49h & ~0x10); + } + return 0; +#endif default: break; } default: break; } +#if 0 + { + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + unsigned long dma_base = hwif->dma_base; + byte tmp1 = 0x00; + byte tmp2 = 0x00; + + pci_read_config_byte(dev, 0x44, &tmp1); + pci_read_config_byte(dev, 0x45, &tmp2); + printk(" AEC6280 r44=%x r45=%x ",tmp1,tmp2); + if (hwif->channel) + dma_base -= 0x08; + tmp1=IN_BYTE(dma_base+2) & 0x10; + printk(" AEC6280 133=%x ",tmp1); + } +#endif return ide_dmaproc(func, drive); /* use standard DMA stuff */ } #endif /* CONFIG_BLK_DEV_IDEDMA */ -#endif /* CONFIG_AEC62XX_TUNING */ unsigned int __init pci_init_aec62xx (struct pci_dev *dev, const char *name) { + int bus_speed = system_bus_clock(); + if (dev->resource[PCI_ROM_RESOURCE].start) { pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); printk("%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start); } + aec_devs[n_aec_devs++] = dev; + #if defined(DISPLAY_AEC62XX_TIMINGS) && defined(CONFIG_PROC_FS) if (!aec62xx_proc) { aec62xx_proc = 1; - bmide_dev = dev; aec62xx_display_info = &aec62xx_get_info; } #endif /* DISPLAY_AEC62XX_TIMINGS && CONFIG_PROC_FS */ + if (bus_speed <= 33) + dev->driver_data = (void *) aec6xxx_33_base; + else + dev->driver_data = (void *) aec6xxx_34_base; + return dev->irq; } @@ -551,32 +615,56 @@ void __init ide_init_aec62xx (ide_hwif_t *hwif) { -#ifdef CONFIG_AEC62XX_TUNING + hwif->autodma = 0; hwif->tuneproc = &aec62xx_tune_drive; hwif->speedproc = &aec62xx_tune_chipset; -#ifdef CONFIG_BLK_DEV_IDEDMA - if (hwif->dma_base) - hwif->dmaproc = &aec62xx_dmaproc; -#else /* !CONFIG_BLK_DEV_IDEDMA */ hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; + + if (!hwif->dma_base) + return; + +#ifdef CONFIG_BLK_DEV_IDEDMA + hwif->dmaproc = &aec62xx_dmaproc; +#ifdef CONFIG_IDEDMA_AUTO + if (!noautodma) + hwif->autodma = 1; +#endif /* CONFIG_IDEDMA_AUTO */ #endif /* CONFIG_BLK_DEV_IDEDMA */ -#endif /* CONFIG_AEC62XX_TUNING */ + + } void __init ide_dmacapable_aec62xx (ide_hwif_t *hwif, unsigned long dmabase) { -#ifdef CONFIG_AEC62XX_TUNING + struct pci_dev *dev = hwif->pci_dev; + byte reg54h = 0; unsigned long flags; - byte reg54h = 0; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ + spin_lock_irqsave(&io_request_lock, flags); + pci_read_config_byte(dev, 0x54, ®54h); + pci_write_config_byte(dev, 0x54, reg54h & ~(hwif->channel ? 0xF0 : 0x0F)); + spin_unlock_irqrestore(&io_request_lock, flags); + ide_setup_dma(hwif, dmabase, 8); +} - pci_read_config_byte(hwif->pci_dev, 0x54, ®54h); - pci_write_config_byte(hwif->pci_dev, 0x54, reg54h & ~(hwif->channel ? 0xF0 : 0x0F)); +extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); - __restore_flags(flags); /* local CPU only */ -#endif /* CONFIG_AEC62XX_TUNING */ - ide_setup_dma(hwif, dmabase, 8); +void __init fixup_device_aec6x80 (struct pci_dev *dev, ide_pci_device_t *d) +{ + u32 bar4reg = pci_resource_start(dev, 4); + + if (IN_BYTE(bar4reg+2) & 0x10) { + strcpy(d->name, "AEC6880"); + if (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R) + strcpy(d->name, "AEC6880R"); + } else { + strcpy(d->name, "AEC6280"); + if (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R) + strcpy(d->name, "AEC6280R"); + } + + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d->name, dev->bus->number, dev->devfn); + ide_setup_pci_device(dev, d); } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/ali14xx.c linux.19rc3-ac4/drivers/ide/ali14xx.c --- linux.19rc3/drivers/ide/ali14xx.c 2002-07-29 12:49:58.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/ali14xx.c 2002-07-29 13:58:39.000000000 +0100 @@ -95,7 +95,7 @@ static inline byte inReg (byte reg) { outb_p(reg, regPort); - return inb(dataPort); + return IN_BYTE(dataPort); } /* @@ -137,15 +137,14 @@ /* stuff timing parameters into controller registers */ driveNum = (HWIF(drive)->index << 1) + drive->select.b.unit; - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ + spin_lock_irqsave(&io_request_lock, flags); outb_p(regOn, basePort); outReg(param1, regTab[driveNum].reg1); outReg(param2, regTab[driveNum].reg2); outReg(param3, regTab[driveNum].reg3); outReg(param4, regTab[driveNum].reg4); outb_p(regOff, basePort); - restore_flags(flags); /* all CPUs */ + spin_unlock_irqrestore(&io_request_lock, flags); } /* @@ -157,19 +156,18 @@ byte t; unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ + local_irq_save(flags); for (i = 0; i < ALI_NUM_PORTS; ++i) { basePort = ports[i]; - regOff = inb(basePort); + regOff = IN_BYTE(basePort); for (regOn = 0x30; regOn <= 0x33; ++regOn) { outb_p(regOn, basePort); - if (inb(basePort) == regOn) { + if (IN_BYTE(basePort) == regOn) { regPort = basePort + 4; dataPort = basePort + 8; t = inReg(0) & 0xf0; outb_p(regOff, basePort); - __restore_flags(flags); /* local CPU only */ + local_irq_restore(flags); if (t != 0x50) return 0; return 1; /* success */ @@ -177,7 +175,7 @@ } outb_p(regOff, basePort); } - __restore_flags(flags); /* local CPU only */ + local_irq_restore(flags); return 0; } @@ -189,15 +187,14 @@ byte t; unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ + local_irq_save(flags); outb_p(regOn, basePort); for (p = initData; p->reg != 0; ++p) outReg(p->data, p->reg); outb_p(0x01, regPort); - t = inb(regPort) & 0x01; + t = IN_BYTE(regPort) & 0x01; outb_p(regOff, basePort); - __restore_flags(flags); /* local CPU only */ + local_irq_restore(flags); return t; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/alim15x3.c linux.19rc3-ac4/drivers/ide/alim15x3.c --- linux.19rc3/drivers/ide/alim15x3.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/alim15x3.c 2002-07-29 13:58:39.000000000 +0100 @@ -89,8 +89,8 @@ * at that point bibma+0x2 et bibma+0xa are byte * registers to investigate: */ - c0 = inb((unsigned short)bibma + 0x02); - c1 = inb((unsigned short)bibma + 0x0a); + c0 = IN_BYTE((unsigned short)bibma + 0x02); + c1 = IN_BYTE((unsigned short)bibma + 0x0a); p += sprintf(p, "\n Ali M15x3 Chipset.\n"); @@ -112,16 +112,20 @@ (reg53h & 0x80) ? " OVERRD." : "." ); p += sprintf(p, - "-------------------primary channel-------------------secondary channel---------\n\n"); + "-------------------primary channel" + "-------------------secondary channel" + "---------\n\n"); pci_read_config_byte(bmide_dev, 0x09, ®53h); p += sprintf(p, - "channel status: %s %s\n", + "channel status: %s" + " %s\n", (reg53h & 0x20) ? "On " : "Off", (reg53h & 0x10) ? "On " : "Off" ); p += sprintf(p, - "both channels togth: %s %s\n", + "both channels togth: %s" + " %s\n", (c0&0x80) ? "No " : "Yes", (c1&0x80) ? "No " : "Yes" ); @@ -134,24 +138,29 @@ pci_read_config_byte(bmide_dev, 0x58, ®5xh); pci_read_config_byte(bmide_dev, 0x5c, ®5yh); p += sprintf(p, - "Add. Setup Timing: %dT %dT\n", + "Add. Setup Timing: %dT" + " %dT\n", (reg5xh & 0x07) ? (reg5xh & 0x07) : 8, (reg5yh & 0x07) ? (reg5yh & 0x07) : 8 ); pci_read_config_byte(bmide_dev, 0x59, ®5xh); pci_read_config_byte(bmide_dev, 0x5d, ®5yh); p += sprintf(p, - "Command Act. Count: %dT %dT\n" - "Command Rec. Count: %dT %dT\n\n", + "Command Act. Count: %dT" + " %dT\n" + "Command Rec. Count: %dT" + " %dT\n\n", (reg5xh & 0x70) ? ((reg5xh & 0x70) >> 4) : 8, (reg5yh & 0x70) ? ((reg5yh & 0x70) >> 4) : 8, (reg5xh & 0x0f) ? (reg5xh & 0x0f) : 16, (reg5yh & 0x0f) ? (reg5yh & 0x0f) : 16 ); p += sprintf(p, - "----------------drive0-----------drive1------------drive0-----------drive1------\n\n"); + "----------------drive0-----------drive1" + "------------drive0-----------drive1------\n\n"); p += sprintf(p, - "DMA enabled: %s %s %s %s\n", + "DMA enabled: %s %s" + " %s %s\n", (c0&0x20) ? "Yes" : "No ", (c0&0x40) ? "Yes" : "No ", (c1&0x20) ? "Yes" : "No ", @@ -159,7 +168,8 @@ pci_read_config_byte(bmide_dev, 0x54, ®5xh); pci_read_config_byte(bmide_dev, 0x55, ®5yh); - q = "FIFO threshold: %2d Words %2d Words %2d Words %2d Words\n"; + q = "FIFO threshold: %2d Words %2d Words" + " %2d Words %2d Words\n"; if (rev < 0xc1) { if ((rev == 0x20) && (pci_read_config_byte(bmide_dev, 0x4f, &tmp), (tmp &= 0x20))) { p += sprintf(p, q, 8, 8, 8, 8); @@ -180,7 +190,8 @@ #if 0 p += sprintf(p, - "FIFO threshold: %2d Words %2d Words %2d Words %2d Words\n", + "FIFO threshold: %2d Words %2d Words" + " %2d Words %2d Words\n", (reg5xh & 0x03) + 12, ((reg5xh & 0x30)>>4) + 12, (reg5yh & 0x03) + 12, @@ -200,9 +211,12 @@ pci_read_config_byte(bmide_dev, 0x5f, ®5yh1); p += sprintf(p,/* - "------------------drive0-----------drive1------------drive0-----------drive1------\n")*/ - "Dt RW act. Cnt %2dT %2dT %2dT %2dT\n" - "Dt RW rec. Cnt %2dT %2dT %2dT %2dT\n\n", + "------------------drive0-----------drive1" + "------------drive0-----------drive1------\n")*/ + "Dt RW act. Cnt %2dT %2dT" + " %2dT %2dT\n" + "Dt RW rec. Cnt %2dT %2dT" + " %2dT %2dT\n\n", (reg5xh & 0x70) ? ((reg5xh & 0x70) >> 4) : 8, (reg5xh1 & 0x70) ? ((reg5xh1 & 0x70) >> 4) : 8, (reg5yh & 0x70) ? ((reg5yh & 0x70) >> 4) : 8, @@ -213,13 +227,16 @@ (reg5yh1 & 0x0f) ? (reg5yh1 & 0x0f) : 16 ); p += sprintf(p, - "-----------------------------------UDMA Timings--------------------------------\n\n"); + "-----------------------------------UDMA Timings" + "--------------------------------\n\n"); pci_read_config_byte(bmide_dev, 0x56, ®5xh); pci_read_config_byte(bmide_dev, 0x57, ®5yh); p += sprintf(p, - "UDMA: %s %s %s %s\n" - "UDMA timings: %s %s %s %s\n\n", + "UDMA: %s %s" + " %s %s\n" + "UDMA timings: %s %s" + " %s %s\n\n", (reg5xh & 0x08) ? "OK" : "No", (reg5xh & 0x80) ? "OK" : "No", (reg5yh & 0x08) ? "OK" : "No", @@ -248,7 +265,7 @@ byte s_clc, a_clc, r_clc; unsigned long flags; int bus_speed = system_bus_clock(); - int port = hwif->index ? 0x5c : 0x58; + int port = hwif->channel ? 0x5c : 0x58; int portFIFO = hwif->channel ? 0x55 : 0x54; byte cd_dma_fifo = 0; @@ -272,21 +289,20 @@ if (r_clc >= 16) r_clc = 0; } - __save_flags(flags); - __cli(); + local_irq_save(flags); /* * PIO mode => ATA FIFO on, ATAPI FIFO off */ pci_read_config_byte(dev, portFIFO, &cd_dma_fifo); if (drive->media==ide_disk) { - if (hwif->index) { + if (hwif->channel) { pci_write_config_byte(dev, portFIFO, (cd_dma_fifo & 0x0F) | 0x50); } else { pci_write_config_byte(dev, portFIFO, (cd_dma_fifo & 0xF0) | 0x05); } } else { - if (hwif->index) { + if (hwif->channel) { pci_write_config_byte(dev, portFIFO, cd_dma_fifo & 0x0F); } else { pci_write_config_byte(dev, portFIFO, cd_dma_fifo & 0xF0); @@ -295,7 +311,7 @@ pci_write_config_byte(dev, port, s_clc); pci_write_config_byte(dev, port+drive->select.b.unit+2, (a_clc << 4) | r_clc); - __restore_flags(flags); + local_irq_restore(flags); /* * setup active rec @@ -309,14 +325,79 @@ } -static int ali15x3_tune_chipset (ide_drive_t *drive, byte speed) +static byte ali15x3_can_ultra (ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); +#ifndef CONFIG_WDC_ALI15X3 + struct hd_driveid *id = drive->id; +#endif /* CONFIG_WDC_ALI15X3 */ + + if (m5229_revision <= 0x20) { + return 0; + } else if ((m5229_revision < 0xC2) && +#ifndef CONFIG_WDC_ALI15X3 + ((chip_is_1543c_e && strstr(id->model, "WDC ")) || + (drive->media!=ide_disk))) { +#else /* CONFIG_WDC_ALI15X3 */ + (drive->media!=ide_disk)) { +#endif /* CONFIG_WDC_ALI15X3 */ + return 0; + } else { + return 1; + } +} + +static byte ali15x3_ratemask (ide_drive_t *drive) +{ +// struct pci_dev *dev = HWIF(drive)->pci_dev; + byte mode = 0x00; + byte can_ultra = ali15x3_can_ultra(drive); + + if ((m5229_revision >= 0xC4) && (can_ultra)) { + mode |= 0x03; + } else if ((m5229_revision >= 0xC2) && (can_ultra)) { + mode |= 0x02; + } else if (can_ultra) { + mode |= 0x01; + } else { + return (mode &= ~0xFF); + } + + if (!eighty_ninty_three(drive)) { + mode &= ~0xFE; + mode |= 0x01; + } + return (mode &= ~0xF8); +} + +static byte ali15x3_ratefilter (ide_drive_t *drive, byte speed) +{ +#ifdef CONFIG_BLK_DEV_IDEDMA + byte mode = ali15x3_ratemask(drive); + + switch(mode) { + case 0x04: while (speed > XFER_UDMA_6) speed--; break; + case 0x03: while (speed > XFER_UDMA_5) speed--; break; + case 0x02: while (speed > XFER_UDMA_4) speed--; break; + case 0x01: while (speed > XFER_UDMA_2) speed--; break; + case 0x00: + default: while (speed > XFER_MW_DMA_2) speed--; break; + break; + } +#else + while (speed > XFER_PIO_4) speed--; +#endif /* CONFIG_BLK_DEV_IDEDMA */ +// printk("%s: mode == %02x speed == %02x\n", drive->name, mode, speed); + return speed; +} + +static int ali15x3_tune_chipset (ide_drive_t *drive, byte xferspeed) +{ + ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; + byte speed = ali15x3_ratefilter(drive, xferspeed); byte unit = (drive->select.b.unit & 0x01); byte tmpbyte = 0x00; - int m5229_udma = hwif->channel? 0x57 : 0x56; - int err = 0; + int m5229_udma = (hwif->channel) ? 0x57 : 0x56; if (speed < XFER_UDMA_0) { byte ultra_enable = (unit) ? 0x7f : 0xf7; @@ -326,18 +407,11 @@ pci_read_config_byte(dev, m5229_udma, &tmpbyte); tmpbyte &= ultra_enable; pci_write_config_byte(dev, m5229_udma, tmpbyte); - } - - err = ide_config_drive_speed(drive, speed); + if (speed < XFER_SW_DMA_0) + ali15x3_tune_drive(drive, speed); #ifdef CONFIG_BLK_DEV_IDEDMA - if (speed >= XFER_SW_DMA_0) { - unsigned long dma_base = hwif->dma_base; - - outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2); - } - - if (speed >= XFER_UDMA_0) { + } else { pci_read_config_byte(dev, m5229_udma, &tmpbyte); tmpbyte &= (0x0f << ((1-unit) << 2)); /* @@ -350,89 +424,58 @@ tmpbyte |= 1; pci_write_config_byte(dev, 0x4b, tmpbyte); } - } #endif /* CONFIG_BLK_DEV_IDEDMA */ - - drive->current_speed = speed; - - return (err); -} - -static void config_chipset_for_pio (ide_drive_t *drive) -{ - ali15x3_tune_drive(drive, 5); + } + return (ide_config_drive_speed(drive, speed)); } #ifdef CONFIG_BLK_DEV_IDEDMA -static int config_chipset_for_dma (ide_drive_t *drive, byte ultra33) +static int config_chipset_for_dma (ide_drive_t *drive) { struct hd_driveid *id = drive->id; - byte speed = 0x00; - byte ultra66 = eighty_ninty_three(drive); - byte ultra100 = (m5229_revision>=0xc4) ? 1 : 0; - int rval; - - if ((id->dma_ultra & 0x0020) && (ultra100) && (ultra66) && (ultra33)) { - speed = XFER_UDMA_5; - } else if ((id->dma_ultra & 0x0010) && (ultra66) && (ultra33)) { - speed = XFER_UDMA_4; - } else if ((id->dma_ultra & 0x0008) && (ultra66) && (ultra33)) { - speed = XFER_UDMA_3; - } else if ((id->dma_ultra & 0x0004) && (ultra33)) { - speed = XFER_UDMA_2; - } else if ((id->dma_ultra & 0x0002) && (ultra33)) { - speed = XFER_UDMA_1; - } else if ((id->dma_ultra & 0x0001) && (ultra33)) { - speed = XFER_UDMA_0; - } else if (id->dma_mword & 0x0004) { - speed = XFER_MW_DMA_2; - } else if (id->dma_mword & 0x0002) { - speed = XFER_MW_DMA_1; - } else if (id->dma_mword & 0x0001) { - speed = XFER_MW_DMA_0; - } else if (id->dma_1word & 0x0004) { - speed = XFER_SW_DMA_2; - } else if (id->dma_1word & 0x0002) { - speed = XFER_SW_DMA_1; - } else if (id->dma_1word & 0x0001) { - speed = XFER_SW_DMA_0; - } else { - return ((int) ide_dma_off_quietly); + byte mode = ali15x3_ratemask(drive); + byte speed = 0; + + switch(mode) { + case 0x03: + if (id->dma_ultra & 0x0020) + { speed = XFER_UDMA_5; break; } + case 0x02: + if (id->dma_ultra & 0x0010) + { speed = XFER_UDMA_4; break; } + if (id->dma_ultra & 0x0008) + { speed = XFER_UDMA_3; break; } + case 0x01: + if (id->dma_ultra & 0x0004) + { speed = XFER_UDMA_2; break; } + if (id->dma_ultra & 0x0002) + { speed = XFER_UDMA_1; break; } + if (id->dma_ultra & 0x0001) + { speed = XFER_UDMA_0; break; } + case 0x00: + if (id->dma_mword & 0x0004) + { speed = XFER_MW_DMA_2; break; } + if (id->dma_mword & 0x0002) + { speed = XFER_MW_DMA_1; break; } + if (id->dma_mword & 0x0001) + { speed = XFER_MW_DMA_0; break; } + if (id->dma_1word & 0x0004) + { speed = XFER_SW_DMA_2; break; } + if (id->dma_1word & 0x0002) + { speed = XFER_SW_DMA_1; break; } + if (id->dma_1word & 0x0001) + { speed = XFER_SW_DMA_0; break; } + default: + return ((int) ide_dma_off_quietly); } (void) ali15x3_tune_chipset(drive, speed); - - if (!drive->init_speed) - drive->init_speed = speed; - - rval = (int)( ((id->dma_ultra >> 11) & 3) ? ide_dma_on : +// return ((int) (dma) ? ide_dma_on : ide_dma_off_quietly); + return ((int) ((id->dma_ultra >> 11) & 7) ? ide_dma_on : ((id->dma_ultra >> 8) & 7) ? ide_dma_on : ((id->dma_mword >> 8) & 7) ? ide_dma_on : ((id->dma_1word >> 8) & 7) ? ide_dma_on : ide_dma_off_quietly); - - return rval; -} - -static byte ali15x3_can_ultra (ide_drive_t *drive) -{ -#ifndef CONFIG_WDC_ALI15X3 - struct hd_driveid *id = drive->id; -#endif /* CONFIG_WDC_ALI15X3 */ - - if (m5229_revision <= 0x20) { - return 0; - } else if ((m5229_revision < 0xC2) && -#ifndef CONFIG_WDC_ALI15X3 - ((chip_is_1543c_e && strstr(id->model, "WDC ")) || - (drive->media!=ide_disk))) { -#else /* CONFIG_WDC_ALI15X3 */ - (drive->media!=ide_disk)) { -#endif /* CONFIG_WDC_ALI15X3 */ - return 0; - } else { - return 1; - } } static int ali15x3_config_drive_for_dma(ide_drive_t *drive) @@ -440,11 +483,12 @@ struct hd_driveid *id = drive->id; ide_hwif_t *hwif = HWIF(drive); ide_dma_action_t dma_func = ide_dma_on; - byte can_ultra_dma = ali15x3_can_ultra(drive); if ((m5229_revision<=0x20) && (drive->media!=ide_disk)) return hwif->dmaproc(ide_dma_off_quietly, drive); + drive->init_speed = 0; + if ((id != NULL) && ((id->capability & 1) != 0) && hwif->autodma) { /* Consult the list of known "bad" drives */ if (ide_dmaproc(ide_dma_bad_drive, drive)) { @@ -455,7 +499,7 @@ if ((id->field_valid & 4) && (m5229_revision >= 0xC2)) { if (id->dma_ultra & 0x003F) { /* Force if Capable UltraDMA */ - dma_func = config_chipset_for_dma(drive, can_ultra_dma); + dma_func = config_chipset_for_dma(drive); if ((id->field_valid & 2) && (dma_func != ide_dma_on)) goto try_dma_modes; @@ -465,7 +509,7 @@ if ((id->dma_mword & 0x0007) || (id->dma_1word & 0x0007)) { /* Force if Capable regular DMA modes */ - dma_func = config_chipset_for_dma(drive, can_ultra_dma); + dma_func = config_chipset_for_dma(drive); if (dma_func != ide_dma_on) goto no_dma_set; } @@ -474,7 +518,7 @@ goto no_dma_set; } /* Consult the list of known "good" drives */ - dma_func = config_chipset_for_dma(drive, can_ultra_dma); + dma_func = config_chipset_for_dma(drive); if (dma_func != ide_dma_on) goto no_dma_set; } else { @@ -484,7 +528,7 @@ fast_ata_pio: dma_func = ide_dma_off_quietly; no_dma_set: - config_chipset_for_pio(drive); + hwif->tuneproc(drive, 5); } return hwif->dmaproc(dma_func, drive); } @@ -495,7 +539,8 @@ case ide_dma_check: return ali15x3_config_drive_for_dma(drive); case ide_dma_write: - if ((m5229_revision < 0xC2) && (drive->media != ide_disk)) + if ((m5229_revision < 0xC2) && + (drive->media != ide_disk)) return 1; /* try PIO instead of DMA */ break; default: @@ -505,10 +550,17 @@ } #endif /* CONFIG_BLK_DEV_IDEDMA */ +#define ALI_INIT_CODE_TEST + unsigned int __init pci_init_ali15x3 (struct pci_dev *dev, const char *name) { unsigned long fixdma_base = pci_resource_start(dev, 4); +#ifdef ALI_INIT_CODE_TEST + unsigned long flags; + byte tmpbyte; +#endif /* ALI_INIT_CODE_TEST */ + pci_read_config_byte(dev, PCI_REVISION_ID, &m5229_revision); isa_dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); @@ -521,9 +573,9 @@ /* * enable DMA capable bit, and "not" simplex only */ - outb(inb(fixdma_base+2) & 0x60, fixdma_base+2); + OUT_BYTE(IN_BYTE(fixdma_base+2) & 0x60, fixdma_base+2); - if (inb(fixdma_base+2) & 0x80) + if (IN_BYTE(fixdma_base+2) & 0x80) printk("%s: simplex device: DMA will fail!!\n", name); } @@ -535,6 +587,55 @@ } #endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */ +#ifdef ALI_INIT_CODE_TEST + local_irq_save(flags); + + if (m5229_revision >= 0xC2) { + /* + * 1543C-B?, 1535, 1535D, 1553 + * Note 1: not all "motherboard" support this detection + * Note 2: if no udma 66 device, the detection may "error". + * but in this case, we will not set the device to + * ultra 66, the detection result is not important + */ + + /* + * enable "Cable Detection", m5229, 0x4b, bit3 + */ + pci_read_config_byte(dev, 0x4b, &tmpbyte); + pci_write_config_byte(dev, 0x4b, tmpbyte | 0x08); + + /* + * set south-bridge's enable bit, m1533, 0x79 + */ + pci_read_config_byte(isa_dev, 0x79, &tmpbyte); + if (m5229_revision == 0xC2) { + /* + * 1543C-B0 (m1533, 0x79, bit 2) + */ + pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x04); + } else if (m5229_revision >= 0xC3) { + /* + * 1553/1535 (m1533, 0x79, bit 1) + */ + pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x02); + } + } else { + /* + * revision 0x20 (1543-E, 1543-F) + * revision 0xC0, 0xC1 (1543C-C, 1543C-D, 1543C-E) + * clear CD-ROM DMA write bit, m5229, 0x4b, bit 7 + */ + pci_read_config_byte(dev, 0x4b, &tmpbyte); + /* + * clear bit 7 + */ + pci_write_config_byte(dev, 0x4b, tmpbyte & 0x7F); + } + + local_irq_save(flags); +#endif /* ALI_INIT_CODE_TEST */ + return 0; } @@ -552,10 +653,10 @@ unsigned long flags; byte tmpbyte; - __save_flags(flags); - __cli(); + local_irq_save(flags); if (m5229_revision >= 0xC2) { +#ifndef ALI_INIT_CODE_TEST /* * 1543C-B?, 1535, 1535D, 1553 * Note 1: not all "motherboard" support this detection @@ -585,6 +686,7 @@ */ pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x02); } +#endif /* ALI_INIT_CODE_TEST */ /* * Ultra66 cable detection (from Host View) * m5229, 0x4a, bit0: primary, bit1: secondary 80 pin @@ -605,6 +707,7 @@ */ ata66 = (hwif->channel)?cable_80_pin[1]:cable_80_pin[0]; } else { +#ifndef ALI_INIT_CODE_TEST /* * revision 0x20 (1543-E, 1543-F) * revision 0xC0, 0xC1 (1543C-C, 1543C-D, 1543C-E) @@ -615,6 +718,7 @@ * clear bit 7 */ pci_write_config_byte(dev, 0x4b, tmpbyte & 0x7F); +#endif /* ALI_INIT_CODE_TEST */ /* * check m1533, 0x5e, bit 1~4 == 1001 => & 00011110 = 00010010 */ @@ -633,7 +737,7 @@ pci_write_config_byte(dev, 0x53, tmpbyte); - __restore_flags(flags); + local_irq_restore(flags); return(ata66); } @@ -657,7 +761,8 @@ ideic = ideic & 0x03; /* get IRQ for IDE Controller */ - if ((hwif->channel && ideic == 0x03) || (!hwif->channel && !ideic)) { + if ((hwif->channel && ideic == 0x03) || + (!hwif->channel && !ideic)) { /* * get SIRQ1 routing table */ @@ -675,24 +780,26 @@ } #endif /* CONFIG_SPARC64 */ + hwif->autodma = 0; hwif->tuneproc = &ali15x3_tune_drive; hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; hwif->speedproc = &ali15x3_tune_chipset; + if (!hwif->dma_base) + return; + #ifdef CONFIG_BLK_DEV_IDEDMA - if ((hwif->dma_base) && (m5229_revision >= 0x20)) { + if (m5229_revision >= 0x20) { /* * M1543C or newer for DMAing */ hwif->dmaproc = &ali15x3_dmaproc; - hwif->autodma = 1; +#ifdef CONFIG_IDEDMA_AUTO + if (!noautodma) + hwif->autodma = 1; +#endif /* CONFIG_IDEDMA_AUTO */ } - - if (noautodma) - hwif->autodma = 0; -#else - hwif->autodma = 0; #endif /* CONFIG_BLK_DEV_IDEDMA */ } @@ -703,3 +810,16 @@ } ide_setup_dma(hwif, dmabase, 8); } + +extern void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d); + +void __init fixup_device_ali15x3 (struct pci_dev *dev, ide_pci_device_t *d) +{ + if (dev->resource[0].start != 0x01F1) + ide_register_xp_fix(dev); + + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d->name, dev->bus->number, dev->devfn); + ide_setup_pci_device(dev, d); +} + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/amd74xx.c linux.19rc3-ac4/drivers/ide/amd74xx.c --- linux.19rc3/drivers/ide/amd74xx.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/amd74xx.c 2002-07-29 13:58:39.000000000 +0100 @@ -34,7 +34,6 @@ static int amd74xx_get_info(char *, char **, off_t, int); extern int (*amd74xx_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); static struct pci_dev *bmide_dev; static int amd74xx_get_info (char *buffer, char **addr, off_t offset, int count) @@ -47,16 +46,22 @@ * at that point bibma+0x2 et bibma+0xa are byte registers * to investigate: */ - c0 = inb_p((unsigned short)bibma + 0x02); - c1 = inb_p((unsigned short)bibma + 0x0a); + c0 = IN_BYTE((unsigned short)bibma + 0x02); + c1 = IN_BYTE((unsigned short)bibma + 0x0a); - p += sprintf(p, "\n AMD %04X VIPER Chipset.\n", bmide_dev->device); - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); - p += sprintf(p, " %sabled %sabled\n", + p += sprintf(p, "\n " + "AMD %04X VIPER Chipset.\n", bmide_dev->device); + p += sprintf(p, "--------------- Primary Channel " + "---------------- Secondary Channel " + "-------------\n"); + p += sprintf(p, " %sabled " + " %sabled\n", (c0&0x80) ? "dis" : " en", (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s %s %s\n", + p += sprintf(p, "--------------- drive0 --------- drive1 " + "-------- drive0 ---------- drive1 ------\n"); + p += sprintf(p, "DMA enabled: %s %s " + " %s %s\n", (c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ", (c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " ); p += sprintf(p, "UDMA\n"); @@ -69,40 +74,85 @@ byte amd74xx_proc = 0; -extern char *ide_xfer_verbose (byte xfer_rate); +static int amd74xx_mode5_check (struct pci_dev *dev) +{ + switch(dev->device) { + case PCI_DEVICE_ID_AMD_VIPER_7411: + case PCI_DEVICE_ID_AMD_VIPER_7441: + return 1; + default: + return 0; + } +} static unsigned int amd74xx_swdma_check (struct pci_dev *dev) { unsigned int class_rev; - if ((dev->device == PCI_DEVICE_ID_AMD_VIPER_7411) || - (dev->device == PCI_DEVICE_ID_AMD_VIPER_7441)) - return 0; + if (amd74xx_mode5_check(dev)) + return 1; pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); class_rev &= 0xff; return ((int) (class_rev >= 7) ? 1 : 0); } -static int amd74xx_swdma_error(ide_drive_t *drive) +static int amd74xx_swdma_error (ide_drive_t *drive) { printk("%s: single-word DMA not support (revision < C4)\n", drive->name); return 0; } +static byte amd74xx_ratemask (ide_drive_t *drive) +{ + struct pci_dev *dev = HWIF(drive)->pci_dev; + byte mode = 0x00; + + switch(dev->device) { + case PCI_DEVICE_ID_AMD_VIPER_7441: + case PCI_DEVICE_ID_AMD_VIPER_7411: { mode |= 0x03; break; } + case PCI_DEVICE_ID_AMD_VIPER_7409: { mode |= 0x02; break; } + case PCI_DEVICE_ID_AMD_COBRA_7401: { mode |= 0x01; break; } + default: + return (mode &= ~0xFF); + } + + if (!eighty_ninty_three(drive)) { + mode &= ~0xFE; + mode |= 0x01; + } + return (mode &= ~0xF8); +} + +static byte amd74xx_ratefilter (ide_drive_t *drive, byte speed) +{ +#ifdef CONFIG_BLK_DEV_IDEDMA + byte mode = amd74xx_ratemask(drive); + + switch(mode) { + case 0x04: // while (speed > XFER_UDMA_6) speed--; break; + case 0x03: while (speed > XFER_UDMA_5) speed--; break; + case 0x02: while (speed > XFER_UDMA_4) speed--; break; + case 0x01: while (speed > XFER_UDMA_2) speed--; break; + case 0x00: + default: while (speed > XFER_MW_DMA_2) speed--; break; + break; + } +#else + while (speed > XFER_PIO_4) speed--; +#endif /* CONFIG_BLK_DEV_IDEDMA */ +// printk("%s: mode == %02x speed == %02x\n", drive->name, mode, speed); + return speed; +} + /* * Here is where all the hard work goes to program the chipset. - * */ -static int amd74xx_tune_chipset (ide_drive_t *drive, byte speed) +static int amd74xx_tune_chipset (ide_drive_t *drive, byte xferspeed) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - int err = 0; - byte unit = (drive->select.b.unit & 0x01); -#ifdef CONFIG_BLK_DEV_IDEDMA - unsigned long dma_base = hwif->dma_base; -#endif /* CONFIG_BLK_DEV_IDEDMA */ + byte speed = amd74xx_ratefilter(drive, xferspeed); byte drive_pci = 0x00; byte drive_pci2 = 0x00; byte ultra_timing = 0x00; @@ -122,20 +172,10 @@ pci_read_config_byte(dev, drive_pci2, &dma_pio_timing); pci_read_config_byte(dev, 0x4c, &pio_timing); -#ifdef DEBUG - printk("%s:%d: Speed 0x%02x UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x\n", - drive->name, drive->dn, speed, ultra_timing, dma_pio_timing, pio_timing); -#endif - ultra_timing &= ~0xC7; dma_pio_timing &= ~0xFF; pio_timing &= ~(0x03 << drive->dn); -#ifdef DEBUG - printk("%s: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x\n", - drive->name, ultra_timing, dma_pio_timing, pio_timing); -#endif - switch(speed) { #ifdef CONFIG_BLK_DEV_IDEDMA case XFER_UDMA_7: @@ -162,7 +202,7 @@ dma_pio_timing |= 0x20; break; case XFER_UDMA_0: - ultra_timing |= 0x42; + ultra_timing |= 0x42; dma_pio_timing |= 0x20; break; case XFER_MW_DMA_2: @@ -210,75 +250,19 @@ pio_timing |= (0x03 << drive->dn); - if (!drive->init_speed) - drive->init_speed = speed; - #ifdef CONFIG_BLK_DEV_IDEDMA pci_write_config_byte(dev, drive_pci, ultra_timing); #endif /* CONFIG_BLK_DEV_IDEDMA */ pci_write_config_byte(dev, drive_pci2, dma_pio_timing); pci_write_config_byte(dev, 0x4c, pio_timing); -#ifdef DEBUG - printk("%s: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x\n", - drive->name, ultra_timing, dma_pio_timing, pio_timing); -#endif - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (speed > XFER_PIO_4) { - outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2); - } else { - outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2); - } -#endif /* CONFIG_BLK_DEV_IDEDMA */ - - err = ide_config_drive_speed(drive, speed); - drive->current_speed = speed; - return (err); -} - -static void config_chipset_for_pio (ide_drive_t *drive) -{ - unsigned short eide_pio_timing[6] = {960, 480, 240, 180, 120, 90}; - unsigned short xfer_pio = drive->id->eide_pio_modes; - byte timing, speed, pio; - - pio = ide_get_best_pio_mode(drive, 255, 5, NULL); - - if (xfer_pio> 4) - xfer_pio = 0; - - if (drive->id->eide_pio_iordy > 0) { - for (xfer_pio = 5; - xfer_pio>0 && - drive->id->eide_pio_iordy>eide_pio_timing[xfer_pio]; - xfer_pio--); - } else { - xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 : - (drive->id->eide_pio_modes & 2) ? 0x04 : - (drive->id->eide_pio_modes & 1) ? 0x03 : - (drive->id->tPIO & 2) ? 0x02 : - (drive->id->tPIO & 1) ? 0x01 : xfer_pio; - } - - timing = (xfer_pio >= pio) ? xfer_pio : pio; - - switch(timing) { - case 4: speed = XFER_PIO_4;break; - case 3: speed = XFER_PIO_3;break; - case 2: speed = XFER_PIO_2;break; - case 1: speed = XFER_PIO_1;break; - default: - speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW; - break; - } - (void) amd74xx_tune_chipset(drive, speed); - drive->current_speed = speed; + return (ide_config_drive_speed(drive, speed)); } static void amd74xx_tune_drive (ide_drive_t *drive, byte pio) { byte speed; + pio = ide_get_best_pio_mode(drive, pio, 5, NULL); switch(pio) { case 4: speed = XFER_PIO_4;break; case 3: speed = XFER_PIO_3;break; @@ -297,56 +281,69 @@ */ static int config_chipset_for_dma (ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - struct hd_driveid *id = drive->id; - byte udma_66 = eighty_ninty_three(drive); - byte udma_100 = ((dev->device==PCI_DEVICE_ID_AMD_VIPER_7411)|| - (dev->device==PCI_DEVICE_ID_AMD_VIPER_7441)) ? 1 : 0; - byte speed = 0x00; + struct hd_driveid *id = drive->id; + byte mode = amd74xx_ratemask(drive); + byte swdma = amd74xx_swdma_check(HWIF(drive)->pci_dev); + byte speed = 0; int rval; - if (udma_100) - udma_66 = eighty_ninty_three(drive); - - if ((id->dma_ultra & 0x0020) && (udma_66) && (udma_100)) { - speed = XFER_UDMA_5; - } else if ((id->dma_ultra & 0x0010) && (udma_66)) { - speed = XFER_UDMA_4; - } else if ((id->dma_ultra & 0x0008) && (udma_66)) { - speed = XFER_UDMA_3; - } else if (id->dma_ultra & 0x0004) { - speed = XFER_UDMA_2; - } else if (id->dma_ultra & 0x0002) { - speed = XFER_UDMA_1; - } else if (id->dma_ultra & 0x0001) { - speed = XFER_UDMA_0; - } else if (id->dma_mword & 0x0004) { - speed = XFER_MW_DMA_2; - } else if (id->dma_mword & 0x0002) { - speed = XFER_MW_DMA_1; - } else if (id->dma_mword & 0x0001) { - speed = XFER_MW_DMA_0; - } else { - return ((int) ide_dma_off_quietly); + amd74xx_tune_drive(drive, 5); + + switch(mode) { + case 0x04: + if (id->dma_ultra & 0x0040) + { speed = XFER_UDMA_6; break; } + case 0x03: + if (id->dma_ultra & 0x0020) + { speed = XFER_UDMA_5; break; } + case 0x02: + if (id->dma_ultra & 0x0010) + { speed = XFER_UDMA_4; break; } + if (id->dma_ultra & 0x0008) + { speed = XFER_UDMA_3; break; } + case 0x01: + if (id->dma_ultra & 0x0004) + { speed = XFER_UDMA_2; break; } + if (id->dma_ultra & 0x0002) + { speed = XFER_UDMA_1; break; } + if (id->dma_ultra & 0x0001) + { speed = XFER_UDMA_0; break; } + case 0x00: + if (id->dma_mword & 0x0004) + { speed = XFER_MW_DMA_2; break; } + if (id->dma_mword & 0x0002) + { speed = XFER_MW_DMA_1; break; } + if (id->dma_mword & 0x0001) + { speed = XFER_MW_DMA_0; break; } + if ((id->dma_1word & 0x0004) && (swdma)) + { speed = XFER_SW_DMA_2; break; } + if ((id->dma_1word & 0x0002) && (swdma)) + { speed = XFER_SW_DMA_1; break; } + if ((id->dma_1word & 0x0001) && (swdma)) + { speed = XFER_SW_DMA_0; break; } + default: + return ((int) ide_dma_off_quietly); } (void) amd74xx_tune_chipset(drive, speed); - - rval = (int)( ((id->dma_ultra >> 11) & 7) ? ide_dma_on : - ((id->dma_ultra >> 8) & 7) ? ide_dma_on : - ((id->dma_mword >> 8) & 7) ? ide_dma_on : +// return ((int) (dma) ? ide_dma_on : ide_dma_off_quietly); + rval = (int)( ((id->dma_ultra >> 11) & 7) ? ide_dma_on : + ((id->dma_ultra >> 8) & 7) ? ide_dma_on : + ((id->dma_mword >> 8) & 7) ? ide_dma_on : + (((id->dma_1word >> 8) & 7) && (swdma)) ? ide_dma_on : ide_dma_off_quietly); - return rval; } static int config_drive_xfer_rate (ide_drive_t *drive) { - struct hd_driveid *id = drive->id; + struct hd_driveid *id = drive->id; + ide_hwif_t *hwif = HWIF(drive); ide_dma_action_t dma_func = ide_dma_on; - if (id && (id->capability & 1) && HWIF(drive)->autodma) { + drive->init_speed = 0; + + if (id && (id->capability & 1) && hwif->autodma) { /* Consult the list of known "bad" drives */ if (ide_dmaproc(ide_dma_bad_drive, drive)) { dma_func = ide_dma_off; @@ -387,8 +384,7 @@ fast_ata_pio: dma_func = ide_dma_off_quietly; no_dma_set: - - config_chipset_for_pio(drive); + amd74xx_tune_drive(drive, 5); } return HWIF(drive)->dmaproc(dma_func, drive); } @@ -426,9 +422,9 @@ /* * enable DMA capable bit, and "not" simplex only */ - outb(inb(fixdma_base+2) & 0x60, fixdma_base+2); + OUT_BYTE(IN_BYTE(fixdma_base+2) & 0x60, fixdma_base+2); - if (inb(fixdma_base+2) & 0x80) + if (IN_BYTE(fixdma_base+2) & 0x80) printk("%s: simplex device: DMA will fail!!\n", name); } #if defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS) @@ -488,22 +484,19 @@ hwif->tuneproc = &amd74xx_tune_drive; hwif->speedproc = &amd74xx_tune_chipset; -#ifndef CONFIG_BLK_DEV_IDEDMA - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - hwif->autodma = 0; - return; -#else - - if (hwif->dma_base) { - hwif->dmaproc = &amd74xx_dmaproc; - if (!noautodma) - hwif->autodma = 1; - } else { - hwif->autodma = 0; + if (!hwif->dma_base) { hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; + hwif->autodma = 0; + return; } + +#ifndef CONFIG_BLK_DEV_IDEDMA + hwif->dmaproc = &amd74xx_dmaproc; +#ifdef CONFIG_IDEDMA_AUTO + if (!noautodma) + hwif->autodma = 1; +#endif /* CONFIG_IDEDMA_AUTO */ #endif /* CONFIG_BLK_DEV_IDEDMA */ } @@ -511,3 +504,16 @@ { ide_setup_dma(hwif, dmabase, 8); } + +extern void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d); + +void __init fixup_device_amd74xx (struct pci_dev *dev, ide_pci_device_t *d) +{ + if (dev->resource[0].start != 0x01F1) + ide_register_xp_fix(dev); + + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d->name, dev->bus->number, dev->devfn); + ide_setup_pci_device(dev, d); +} + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/ataraid.c linux.19rc3-ac4/drivers/ide/ataraid.c --- linux.19rc3/drivers/ide/ataraid.c 2002-07-29 12:49:59.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/ataraid.c 2002-07-29 13:58:39.000000000 +0100 @@ -123,8 +123,7 @@ ptr=kmalloc(sizeof(struct buffer_head),GFP_NOIO); if (!ptr) { __set_current_state(TASK_RUNNING); - current->policy |= SCHED_YIELD; - schedule(); + yield(); } } return ptr; @@ -139,8 +138,7 @@ ptr=kmalloc(sizeof(struct ataraid_bh_private),GFP_NOIO); if (!ptr) { __set_current_state(TASK_RUNNING); - current->policy |= SCHED_YIELD; - schedule(); + yield(); } } return ptr; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/cmd640.c linux.19rc3-ac4/drivers/ide/cmd640.c --- linux.19rc3/drivers/ide/cmd640.c 2002-07-29 12:49:58.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/cmd640.c 2002-07-29 13:58:39.000000000 +0100 @@ -217,11 +217,10 @@ { unsigned long flags; - save_flags(flags); - cli(); - outl_p((reg & 0xfc) | cmd640_key, 0xcf8); + spin_lock_irqsave(&io_request_lock, flags); + outb_p((reg & 0xfc) | cmd640_key, 0xcf8); outb_p(val, (reg & 3) | 0xcfc); - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); } static byte get_cmd640_reg_pci1 (unsigned short reg) @@ -229,11 +228,10 @@ byte b; unsigned long flags; - save_flags(flags); - cli(); - outl_p((reg & 0xfc) | cmd640_key, 0xcf8); + spin_lock_irqsave(&io_request_lock, flags); + outb_p((reg & 0xfc) | cmd640_key, 0xcf8); b = inb_p((reg & 3) | 0xcfc); - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); return b; } @@ -243,12 +241,11 @@ { unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&io_request_lock, flags); outb_p(0x10, 0xcf8); outb_p(val, cmd640_key + reg); outb_p(0, 0xcf8); - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); } static byte get_cmd640_reg_pci2 (unsigned short reg) @@ -256,12 +253,11 @@ byte b; unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&io_request_lock, flags); outb_p(0x10, 0xcf8); b = inb_p(cmd640_key + reg); outb_p(0, 0xcf8); - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); return b; } @@ -271,11 +267,10 @@ { unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&io_request_lock, flags); outb_p(reg, cmd640_key); outb_p(val, cmd640_key + 4); - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); } static byte get_cmd640_reg_vlb (unsigned short reg) @@ -283,11 +278,10 @@ byte b; unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&io_request_lock, flags); outb_p(reg, cmd640_key); b = inb_p(cmd640_key + 4); - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); return b; } @@ -315,7 +309,9 @@ { get_cmd640_reg = get_cmd640_reg_pci1; put_cmd640_reg = put_cmd640_reg_pci1; - for (cmd640_key = 0x80000000; cmd640_key <= 0x8000f800; cmd640_key += 0x800) { + for (cmd640_key = 0x80000000; + cmd640_key <= 0x8000f800; + cmd640_key += 0x800) { if (match_pci_cmd640_device()) return 1; /* success */ } @@ -364,8 +360,7 @@ { unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&io_request_lock, flags); outb_p(0x0a, 0x170 + IDE_SELECT_OFFSET); /* select drive0 */ udelay(100); @@ -373,11 +368,11 @@ outb_p(0x1a, 0x170 + IDE_SELECT_OFFSET); /* select drive1 */ udelay(100); if ((inb_p(0x170 + IDE_SELECT_OFFSET) & 0x1f) != 0x1a) { - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); return 0; /* nothing responded */ } } - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); return 1; /* success */ } @@ -458,8 +453,7 @@ byte b; unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&io_request_lock, flags); b = get_cmd640_reg(reg); if (mode) { /* want prefetch on? */ #if CMD640_PREFETCH_MASKS @@ -475,7 +469,7 @@ b |= prefetch_masks[index]; /* disable prefetch */ } put_cmd640_reg(reg, b); - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); } /* @@ -576,8 +570,7 @@ /* * Now that everything is ready, program the new timings */ - save_flags (flags); - cli(); + spin_lock_irqsave(&io_request_lock, flags); /* * Program the address_setup clocks into ARTTIM reg, * and then the active/recovery counts into the DRWTIM reg @@ -586,7 +579,7 @@ setup_count |= get_cmd640_reg(arttim_regs[index]) & 0x3f; put_cmd640_reg(arttim_regs[index], setup_count); put_cmd640_reg(drwtim_regs[index], pack_nibbles(active_count, recovery_count)); - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); } /* @@ -692,6 +685,41 @@ #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ +static int pci_conf1(void) +{ + u32 tmp; + unsigned long flags; + + spin_lock_irqsave(&io_request_lock, flags); + OUT_BYTE(0x01, 0xCFB); + tmp = inl(0xCF8); + outl(0x80000000, 0xCF8); + if (inl(0xCF8) == 0x80000000) { + outl(tmp, 0xCF8); + spin_unlock_irqrestore(&io_request_lock, flags); + return 1; + } + outl(tmp, 0xCF8); + spin_unlock_irqrestore(&io_request_lock, flags); + return 0; +} + +static int pci_conf2(void) +{ + unsigned long flags; + + spin_lock_irqsave(&io_request_lock, flags); + OUT_BYTE(0x00, 0xCFB); + OUT_BYTE(0x00, 0xCF8); + OUT_BYTE(0x00, 0xCFA); + if (IN_BYTE(0xCF8) == 0x00 && IN_BYTE(0xCF8) == 0x00) { + spin_unlock_irqrestore(&io_request_lock, flags); + return 1; + } + spin_unlock_irqrestore(&io_request_lock, flags); + return 0; +} + /* * Probe for a cmd640 chipset, and initialize it if found. Called from ide.c */ @@ -709,9 +737,11 @@ bus_type = "VLB"; } else { cmd640_vlb = 0; - if (probe_for_cmd640_pci1()) + /* Find out what kind of PCI probing is supported otherwise + Justin Gibbs will sulk.. */ + if (pci_conf1() && probe_for_cmd640_pci1()) bus_type = "PCI (type1)"; - else if (probe_for_cmd640_pci2()) + else if (pci_conf2() && probe_for_cmd640_pci2()) bus_type = "PCI (type2)"; else return 0; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/cmd64x.c linux.19rc3-ac4/drivers/ide/cmd64x.c --- linux.19rc3/drivers/ide/cmd64x.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/cmd64x.c 2002-07-29 13:58:39.000000000 +0100 @@ -8,9 +8,10 @@ * Due to massive hardware bugs, UltraDMA is only supported * on the 646U2 and not on the 646U. * - * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) - * Copyright (C) 1998 David S. Miller (davem@redhat.com) - * Copyright (C) 1999-2000 Andre Hedrick + * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) + * Copyright (C) 1998 David S. Miller (davem@redhat.com) + * + * Copyright (C) 1999-2002 Andre Hedrick */ #include @@ -32,7 +33,7 @@ #define CMD_DEBUG 0 #if CMD_DEBUG -#define cmdprintk(x...) printk(##x) +#define cmdprintk(x...) printk(x) #else #define cmdprintk(x...) #endif @@ -85,82 +86,97 @@ #include #include +static char * print_cmd64x_get_info(char *, struct pci_dev *, int); +static char * print_sii_get_info(char *, struct pci_dev *, int); static int cmd64x_get_info(char *, char **, off_t, int); -static int cmd680_get_info(char *, char **, off_t, int); extern int (*cmd64x_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); -static struct pci_dev *bmide_dev; -static int cmd64x_get_info (char *buffer, char **addr, off_t offset, int count) +byte cmd64x_proc = 0; + +#define CMD_MAX_DEVS 5 + +static struct pci_dev *cmd_devs[CMD_MAX_DEVS]; +static int n_cmd_devs; + +#undef DEBUG_CMD_REGS + +static char * print_cmd64x_get_info (char *buf, struct pci_dev *dev, int index) { - char *p = buffer; + char *p = buf; + u8 reg53 = 0, reg54 = 0, reg55 = 0, reg56 = 0; /* primary */ u8 reg57 = 0, reg58 = 0, reg5b; /* secondary */ u8 reg72 = 0, reg73 = 0; /* primary */ u8 reg7a = 0, reg7b = 0; /* secondary */ u8 reg50 = 0, reg71 = 0; /* extra */ +#ifdef DEBUG_CMD_REGS u8 hi_byte = 0, lo_byte = 0; +#endif /* DEBUG_CMD_REGS */ - switch(bmide_dev->device) { - case PCI_DEVICE_ID_CMD_649: - p += sprintf(p, "\n CMD649 Chipset.\n"); - break; - case PCI_DEVICE_ID_CMD_648: - p += sprintf(p, "\n CMD648 Chipset.\n"); - break; - case PCI_DEVICE_ID_CMD_646: - p += sprintf(p, "\n CMD646 Chipset.\n"); - break; - case PCI_DEVICE_ID_CMD_643: - p += sprintf(p, "\n CMD643 Chipset.\n"); - break; - default: - p += sprintf(p, "\n CMD64? Chipse.\n"); - break; - } - (void) pci_read_config_byte(bmide_dev, CFR, ®50); - (void) pci_read_config_byte(bmide_dev, ARTTIM0, ®53); - (void) pci_read_config_byte(bmide_dev, DRWTIM0, ®54); - (void) pci_read_config_byte(bmide_dev, ARTTIM1, ®55); - (void) pci_read_config_byte(bmide_dev, DRWTIM1, ®56); - (void) pci_read_config_byte(bmide_dev, ARTTIM2, ®57); - (void) pci_read_config_byte(bmide_dev, DRWTIM2, ®58); - (void) pci_read_config_byte(bmide_dev, DRWTIM3, ®5b); - (void) pci_read_config_byte(bmide_dev, MRDMODE, ®71); - (void) pci_read_config_byte(bmide_dev, BMIDESR0, ®72); - (void) pci_read_config_byte(bmide_dev, UDIDETCR0, ®73); - (void) pci_read_config_byte(bmide_dev, BMIDESR1, ®7a); - (void) pci_read_config_byte(bmide_dev, UDIDETCR1, ®7b); - - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); - p += sprintf(p, " %sabled %sabled\n", - (reg72&0x80)?"dis":" en",(reg7a&0x80)?"dis":" en"); - p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s %s %s\n", - (reg72&0x20)?"yes":"no ",(reg72&0x40)?"yes":"no ",(reg7a&0x20)?"yes":"no ",(reg7a&0x40)?"yes":"no "); - p += sprintf(p, "DMA Mode: %s(%s) %s(%s) %s(%s) %s(%s)\n", + p += sprintf(p, "\nController: %d\n", index); + p += sprintf(p, "CMD%x Chipset.\n", dev->device); + (void) pci_read_config_byte(dev, CFR, ®50); + (void) pci_read_config_byte(dev, ARTTIM0, ®53); + (void) pci_read_config_byte(dev, DRWTIM0, ®54); + (void) pci_read_config_byte(dev, ARTTIM1, ®55); + (void) pci_read_config_byte(dev, DRWTIM1, ®56); + (void) pci_read_config_byte(dev, ARTTIM2, ®57); + (void) pci_read_config_byte(dev, DRWTIM2, ®58); + (void) pci_read_config_byte(dev, DRWTIM3, ®5b); + (void) pci_read_config_byte(dev, MRDMODE, ®71); + (void) pci_read_config_byte(dev, BMIDESR0, ®72); + (void) pci_read_config_byte(dev, UDIDETCR0, ®73); + (void) pci_read_config_byte(dev, BMIDESR1, ®7a); + (void) pci_read_config_byte(dev, UDIDETCR1, ®7b); + + p += sprintf(p, "--------------- Primary Channel " + "---------------- Secondary Channel " + "-------------\n"); + p += sprintf(p, " %sabled " + " %sabled\n", + (reg72&0x80)?"dis":" en", + (reg7a&0x80)?"dis":" en"); + p += sprintf(p, "--------------- drive0 " + "--------- drive1 -------- drive0 " + "---------- drive1 ------\n"); + p += sprintf(p, "DMA enabled: %s %s" + " %s %s\n", + (reg72&0x20)?"yes":"no ", (reg72&0x40)?"yes":"no ", + (reg7a&0x20)?"yes":"no ", (reg7a&0x40)?"yes":"no "); + + p += sprintf(p, "DMA Mode: %s(%s) %s(%s)", (reg72&0x20)?((reg73&0x01)?"UDMA":" DMA"):" PIO", - (reg72&0x20)?( ((reg73&0x30)==0x30)?(((reg73&0x35)==0x35)?"3":"0"): - ((reg73&0x20)==0x20)?(((reg73&0x25)==0x25)?"3":"1"): - ((reg73&0x10)==0x10)?(((reg73&0x15)==0x15)?"4":"2"): - ((reg73&0x00)==0x00)?(((reg73&0x05)==0x05)?"5":"2"):"X"):"?", + (reg72&0x20)?( + ((reg73&0x30)==0x30)?(((reg73&0x35)==0x35)?"3":"0"): + ((reg73&0x20)==0x20)?(((reg73&0x25)==0x25)?"3":"1"): + ((reg73&0x10)==0x10)?(((reg73&0x15)==0x15)?"4":"2"): + ((reg73&0x00)==0x00)?(((reg73&0x05)==0x05)?"5":"2"): + "X"):"?", (reg72&0x40)?((reg73&0x02)?"UDMA":" DMA"):" PIO", - (reg72&0x40)?( ((reg73&0xC0)==0xC0)?(((reg73&0xC5)==0xC5)?"3":"0"): - ((reg73&0x80)==0x80)?(((reg73&0x85)==0x85)?"3":"1"): - ((reg73&0x40)==0x40)?(((reg73&0x4A)==0x4A)?"4":"2"): - ((reg73&0x00)==0x00)?(((reg73&0x0A)==0x0A)?"5":"2"):"X"):"?", + (reg72&0x40)?( + ((reg73&0xC0)==0xC0)?(((reg73&0xC5)==0xC5)?"3":"0"): + ((reg73&0x80)==0x80)?(((reg73&0x85)==0x85)?"3":"1"): + ((reg73&0x40)==0x40)?(((reg73&0x4A)==0x4A)?"4":"2"): + ((reg73&0x00)==0x00)?(((reg73&0x0A)==0x0A)?"5":"2"): + "X"):"?"); + p += sprintf(p, " %s(%s) %s(%s)\n", (reg7a&0x20)?((reg7b&0x01)?"UDMA":" DMA"):" PIO", - (reg7a&0x20)?( ((reg7b&0x30)==0x30)?(((reg7b&0x35)==0x35)?"3":"0"): - ((reg7b&0x20)==0x20)?(((reg7b&0x25)==0x25)?"3":"1"): - ((reg7b&0x10)==0x10)?(((reg7b&0x15)==0x15)?"4":"2"): - ((reg7b&0x00)==0x00)?(((reg7b&0x05)==0x05)?"5":"2"):"X"):"?", + (reg7a&0x20)?( + ((reg7b&0x30)==0x30)?(((reg7b&0x35)==0x35)?"3":"0"): + ((reg7b&0x20)==0x20)?(((reg7b&0x25)==0x25)?"3":"1"): + ((reg7b&0x10)==0x10)?(((reg7b&0x15)==0x15)?"4":"2"): + ((reg7b&0x00)==0x00)?(((reg7b&0x05)==0x05)?"5":"2"): + "X"):"?", (reg7a&0x40)?((reg7b&0x02)?"UDMA":" DMA"):" PIO", - (reg7a&0x40)?( ((reg7b&0xC0)==0xC0)?(((reg7b&0xC5)==0xC5)?"3":"0"): - ((reg7b&0x80)==0x80)?(((reg7b&0x85)==0x85)?"3":"1"): - ((reg7b&0x40)==0x40)?(((reg7b&0x4A)==0x4A)?"4":"2"): - ((reg7b&0x00)==0x00)?(((reg7b&0x0A)==0x0A)?"5":"2"):"X"):"?" ); - p += sprintf(p, "PIO Mode: %s %s %s %s\n", - "?", "?", "?", "?"); + (reg7a&0x40)?( + ((reg7b&0xC0)==0xC0)?(((reg7b&0xC5)==0xC5)?"3":"0"): + ((reg7b&0x80)==0x80)?(((reg7b&0x85)==0x85)?"3":"1"): + ((reg7b&0x40)==0x40)?(((reg7b&0x4A)==0x4A)?"4":"2"): + ((reg7b&0x00)==0x00)?(((reg7b&0x0A)==0x0A)?"5":"2"): + "X"):"?" ); + p += sprintf(p, "PIO Mode: %s %s" + " %s %s\n", + "?", "?", "?", "?"); p += sprintf(p, " %s %s\n", (reg50 & CFR_INTR_CH0) ? "interrupting" : "polling ", (reg57 & ARTTIM23_INTR_CH1) ? "interrupting" : "polling"); @@ -171,32 +187,58 @@ (reg71 & MRDMODE_BLK_CH0) ? "blocked" : "enabled", (reg71 & MRDMODE_BLK_CH1) ? "blocked" : "enabled"); +#ifdef DEBUG_CMD_REGS SPLIT_BYTE(reg50, hi_byte, lo_byte); - p += sprintf(p, "CFR = 0x%02x, HI = 0x%02x, LOW = 0x%02x\n", reg50, hi_byte, lo_byte); + p += sprintf(p, "CFR = 0x%02x, HI = 0x%02x, " + "LOW = 0x%02x\n", reg50, hi_byte, lo_byte); SPLIT_BYTE(reg57, hi_byte, lo_byte); - p += sprintf(p, "ARTTIM23 = 0x%02x, HI = 0x%02x, LOW = 0x%02x\n", reg57, hi_byte, lo_byte); + p += sprintf(p, "ARTTIM23 = 0x%02x, HI = 0x%02x, " + "LOW = 0x%02x\n", reg57, hi_byte, lo_byte); SPLIT_BYTE(reg71, hi_byte, lo_byte); - p += sprintf(p, "MRDMODE = 0x%02x, HI = 0x%02x, LOW = 0x%02x\n", reg71, hi_byte, lo_byte); + p += sprintf(p, "MRDMODE = 0x%02x, HI = 0x%02x, " + "LOW = 0x%02x\n", reg71, hi_byte, lo_byte); +#endif /* DEBUG_CMD_REGS */ - return p-buffer; /* => must be less than 4k! */ + return (char *)p; } -static int cmd680_get_info (char *buffer, char **addr, off_t offset, int count) +static char * print_sii_get_info (char *buf, struct pci_dev *dev, int index) +{ + char *p = buf; + + p += sprintf(p, "\nController: %d\n", index); + p += sprintf(p, "SII%x Chipset.\n", dev->device); + + p += sprintf(p, "--------------- Primary Channel " + "---------------- Secondary Channel " + "-------------\n"); + p += sprintf(p, "--------------- drive0 --------- drive1 " + "-------- drive0 ---------- drive1 ------\n"); + p += sprintf(p, "PIO Mode: %s %s" + " %s %s\n", + "?", "?", "?", "?"); + return (char *)p; +} + +static int cmd64x_get_info (char *buffer, char **addr, off_t offset, int count) { char *p = buffer; - p += sprintf(p, "\n CMD680 Chipset.\n"); - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); - p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "PIO Mode: %s %s %s %s\n", - "?", "?", "?", "?"); + int i; + + p += sprintf(p, "\n"); + for (i = 0; i < n_cmd_devs; i++) { + struct pci_dev *dev = cmd_devs[i]; + + if (dev->device <= PCI_DEVICE_ID_CMD_649) + p = print_cmd64x_get_info(p, dev, i); + else + p = print_sii_get_info(p, dev, i); + } return p-buffer; /* => must be less than 4k! */ } #endif /* defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) */ -byte cmd64x_proc = 0; -byte cmd680_proc = 0; - /* * Registers and masks for easy access by drive index: */ @@ -212,6 +254,7 @@ static void program_drive_counts (ide_drive_t *drive, int setup_count, int active_count, int recovery_count) { unsigned long flags; + struct pci_dev *dev = HWIF(drive)->pci_dev; ide_drive_t *drives = HWIF(drive)->drives; byte temp_b; static const byte setup_counts[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0}; @@ -250,25 +293,29 @@ active_count &= 0xf; /* Remember, max value is 16 */ recovery_count = (int) recovery_counts[recovery_count]; - cmdprintk("Final values = %d,%d,%d\n", setup_count, active_count, recovery_count); + cmdprintk("Final values = %d,%d,%d\n", + setup_count, active_count, recovery_count); /* * Now that everything is ready, program the new timings */ - __save_flags (flags); - __cli(); + local_irq_save(flags); /* * Program the address_setup clocks into ARTTIM reg, * and then the active/recovery counts into the DRWTIM reg */ - (void) pci_read_config_byte(HWIF(drive)->pci_dev, arttim_regs[channel][slave], &temp_b); - (void) pci_write_config_byte(HWIF(drive)->pci_dev, arttim_regs[channel][slave], + (void) pci_read_config_byte(dev, arttim_regs[channel][slave], &temp_b); + (void) pci_write_config_byte(dev, arttim_regs[channel][slave], ((byte) setup_count) | (temp_b & 0x3f)); - (void) pci_write_config_byte(HWIF(drive)->pci_dev, drwtim_regs[channel][slave], + (void) pci_write_config_byte(dev, drwtim_regs[channel][slave], (byte) ((active_count << 4) | recovery_count)); - cmdprintk ("Write %x to %x\n", ((byte) setup_count) | (temp_b & 0x3f), arttim_regs[channel][slave]); - cmdprintk ("Write %x to %x\n", (byte) ((active_count << 4) | recovery_count), drwtim_regs[channel][slave]); - __restore_flags(flags); + cmdprintk ("Write %x to %x\n", + ((byte) setup_count) | (temp_b & 0x3f), + arttim_regs[channel][slave]); + cmdprintk ("Write %x to %x\n", + (byte) ((active_count << 4) | recovery_count), + drwtim_regs[channel][slave]); + local_irq_restore(flags); } /* @@ -292,7 +339,8 @@ case 9: /* set prefetch on */ mode_wanted &= 1; /*set_prefetch_mode(index, mode_wanted);*/ - cmdprintk("%s: %sabled cmd640 prefetch\n", drive->name, mode_wanted ? "en" : "dis"); + cmdprintk("%s: %sabled cmd640 prefetch\n", + drive->name, mode_wanted ? "en" : "dis"); return; } @@ -301,8 +349,8 @@ cycle_time = d.cycle_time; /* - * I copied all this complicated stuff from cmd640.c and made a few minor changes. - * For now I am just going to pray that it is correct. + * I copied all this complicated stuff from cmd640.c and made a few + * minor changes. For now I am just going to pray that it is correct. */ if (pio_mode > 5) pio_mode = 5; @@ -332,17 +380,85 @@ * (using WIN_SETFEATURE) before continuing. * * But we do not, because: - * 1) this is the wrong place to do it (proper is do_special() in ide.c) + * 1) this is the wrong place to do it + * (proper is do_special() in ide.c) * 2) in practice this is rarely, if ever, necessary */ program_drive_counts (drive, setup_count, active_count, recovery_count); - cmdprintk("%s: selected cmd646 PIO mode%d : %d (%dns)%s, clocks=%d/%d/%d\n", + cmdprintk("%s: selected cmd646 PIO mode%d : %d (%dns)%s, " + "clocks=%d/%d/%d\n", drive->name, pio_mode, mode_wanted, cycle_time, d.overridden ? " (overriding vendor mode)" : "", setup_count, active_count, recovery_count); } +static byte cmd64x_ratemask (ide_drive_t *drive) +{ + struct pci_dev *dev = HWIF(drive)->pci_dev; + byte mode = 0x00; + + switch(dev->device) { + case PCI_DEVICE_ID_CMD_680: { mode |= 0x04; break; } + case PCI_DEVICE_ID_CMD_649: { mode |= 0x03; break; } + case PCI_DEVICE_ID_CMD_648: { mode |= 0x02; break; } + case PCI_DEVICE_ID_CMD_643: { mode |= 0x01; break; } + + case PCI_DEVICE_ID_CMD_646: + { + unsigned int class_rev = 0; + pci_read_config_dword(dev, + PCI_CLASS_REVISION, &class_rev); + class_rev &= 0xff; + /* + * UltraDMA only supported on PCI646U and PCI646U2, which + * correspond to revisions 0x03, 0x05 and 0x07 respectively. + * Actually, although the CMD tech support people won't + * tell me the details, the 0x03 revision cannot support + * UDMA correctly without hardware modifications, and even + * then it only works with Quantum disks due to some + * hold time assumptions in the 646U part which are fixed + * in the 646U2. + * + * So we only do UltraDMA on revision 0x05 and 0x07 chipsets. + */ + switch(class_rev) { + case 0x07: + case 0x05: { mode |= 0x01; break; } + case 0x03: + case 0x01: + default: { mode |= 0x00; break; } + } + } + } + if (!eighty_ninty_three(drive)) { + mode &= ~0xFE; + mode |= 0x01; + } + return (mode &= ~0xF8); +} + +static byte cmd64x_ratefilter (ide_drive_t *drive, byte speed) +{ +#ifdef CONFIG_BLK_DEV_IDEDMA + byte mode = cmd64x_ratemask(drive); + + switch(mode) { + case 0x04: while (speed > XFER_UDMA_6) speed--; break; + case 0x03: while (speed > XFER_UDMA_5) speed--; break; + case 0x02: while (speed > XFER_UDMA_4) speed--; break; + case 0x01: while (speed > XFER_UDMA_2) speed--; break; + case 0x00: + default: while (speed > XFER_MW_DMA_2) speed--; break; + break; + } +#else + while (speed > XFER_PIO_4) speed--; +#endif /* CONFIG_BLK_DEV_IDEDMA */ +// printk("%s: mode == %02x speed == %02x\n", drive->name, mode, speed); + return speed; +} + static byte cmd680_taskfile_timing (ide_hwif_t *hwif) { struct pci_dev *dev = hwif->pci_dev; @@ -422,35 +538,40 @@ cmd680_tuneproc(drive, set_pio); speed = XFER_PIO_0 + set_pio; - if (set_speed) { + if (set_speed) (void) ide_config_drive_speed(drive, speed); - drive->current_speed = speed; - } } static void config_chipset_for_pio (ide_drive_t *drive, byte set_speed) { - if (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_CMD_680) { - config_cmd680_chipset_for_pio(drive, set_speed); - } else { - config_cmd64x_chipset_for_pio(drive, set_speed); + switch(HWIF(drive)->pci_dev->device) { + case PCI_DEVICE_ID_CMD_680: + config_cmd680_chipset_for_pio(drive, set_speed); + return; + default: + break; } + config_cmd64x_chipset_for_pio(drive, set_speed); } -static int cmd64x_tune_chipset (ide_drive_t *drive, byte speed) +static int cmd64x_tune_chipset (ide_drive_t *drive, byte xferspeed) { #ifdef CONFIG_BLK_DEV_IDEDMA ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - int err = 0; u8 unit = (drive->select.b.unit & 0x01); u8 pciU = (hwif->channel) ? UDIDETCR1 : UDIDETCR0; u8 pciD = (hwif->channel) ? BMIDESR1 : BMIDESR0; u8 regU = 0; u8 regD = 0; +#endif /* CONFIG_BLK_DEV_IDEDMA */ - if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0)) return 1; + u8 speed = cmd64x_ratefilter(drive, xferspeed); + +#ifdef CONFIG_BLK_DEV_IDEDMA + if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0)) + return 1; (void) pci_read_config_byte(dev, pciD, ®D); (void) pci_read_config_byte(dev, pciU, ®U); @@ -458,10 +579,12 @@ regU &= ~(unit ? 0xCA : 0x35); (void) pci_write_config_byte(dev, pciD, regD); (void) pci_write_config_byte(dev, pciU, regU); - (void) pci_read_config_byte(dev, pciD, ®D); (void) pci_read_config_byte(dev, pciU, ®U); +#endif /* CONFIG_BLK_DEV_IDEDMA */ + switch(speed) { +#ifdef CONFIG_BLK_DEV_IDEDMA case XFER_UDMA_5: regU |= (unit ? 0x0A : 0x05); break; case XFER_UDMA_4: regU |= (unit ? 0x4A : 0x15); break; case XFER_UDMA_3: regU |= (unit ? 0x8A : 0x25); break; @@ -474,10 +597,6 @@ case XFER_SW_DMA_2: regD |= (unit ? 0x40 : 0x10); break; case XFER_SW_DMA_1: regD |= (unit ? 0x80 : 0x20); break; case XFER_SW_DMA_0: regD |= (unit ? 0xC0 : 0x30); break; -#else - int err = 0; - - switch(speed) { #endif /* CONFIG_BLK_DEV_IDEDMA */ case XFER_PIO_4: cmd64x_tuneproc(drive, 4); break; case XFER_PIO_3: cmd64x_tuneproc(drive, 3); break; @@ -491,33 +610,26 @@ #ifdef CONFIG_BLK_DEV_IDEDMA (void) pci_write_config_byte(dev, pciU, regU); -#endif /* CONFIG_BLK_DEV_IDEDMA */ - - err = ide_config_drive_speed(drive, speed); - - drive->current_speed = speed; - -#ifdef CONFIG_BLK_DEV_IDEDMA regD |= (unit ? 0x40 : 0x20); (void) pci_write_config_byte(dev, pciD, regD); #endif /* CONFIG_BLK_DEV_IDEDMA */ - return err; + return (ide_config_drive_speed(drive, speed)); } -static int cmd680_tune_chipset (ide_drive_t *drive, byte speed) +static int cmd680_tune_chipset (ide_drive_t *drive, byte xferspeed) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; u8 addr_mask = (hwif->channel) ? 0x84 : 0x80; u8 unit = (drive->select.b.unit & 0x01); + u8 speed = cmd64x_ratefilter(drive, xferspeed); u8 dma_pci = 0; u8 udma_pci = 0; u8 mode_pci = 0; u8 scsc = 0; u16 ultra = 0; u16 multi = 0; - int err = 0; pci_read_config_byte(dev, addr_mask, &mode_pci); pci_read_config_byte(dev, 0x8A, &scsc); @@ -538,6 +650,11 @@ if ((speed == XFER_UDMA_6) && (scsc & 0x30) == 0x00) { pci_write_config_byte(dev, 0x8A, scsc|0x01); pci_read_config_byte(dev, 0x8A, &scsc); +#if 0 + /* if 133 clock fails, switch to 2xbus clock */ + if (!(scsc & 0x01)) + pci_write_config_byte(dev, 0x8A, scsc|0x10); +#endif } switch(speed) { @@ -599,7 +716,6 @@ default: return 1; } - if (speed >= XFER_MW_DMA_0) config_cmd680_chipset_for_pio(drive, 0); @@ -615,117 +731,59 @@ pci_write_config_word(dev, dma_pci, multi); pci_write_config_word(dev, udma_pci, ultra); - err = ide_config_drive_speed(drive, speed); - drive->current_speed = speed; - return err; + return (ide_config_drive_speed(drive, speed)); } #ifdef CONFIG_BLK_DEV_IDEDMA -static int config_cmd64x_chipset_for_dma (ide_drive_t *drive, unsigned int rev, byte ultra_66) +static int config_chipset_for_dma (ide_drive_t *drive) { struct hd_driveid *id = drive->id; ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - + byte mode = cmd64x_ratemask(drive); byte speed = 0x00; byte set_pio = 0x00; - byte udma_33 = ((rev >= 0x05) || (ultra_66)) ? 1 : 0; - byte udma_66 = eighty_ninty_three(drive); - byte udma_100 = 0; int rval; - switch(dev->device) { - case PCI_DEVICE_ID_CMD_649: udma_100 = 1; break; - case PCI_DEVICE_ID_CMD_648: - case PCI_DEVICE_ID_CMD_646: - case PCI_DEVICE_ID_CMD_643: - default: - break; - } - if (drive->media != ide_disk) { - cmdprintk("CMD64X: drive->media != ide_disk at double check, inital check failed!!\n"); + cmdprintk("CMD64X: drive->media != ide_disk at double check," + " inital check failed!!\n"); return ((int) ide_dma_off); } - /* UltraDMA only supported on PCI646U and PCI646U2, - * which correspond to revisions 0x03, 0x05 and 0x07 respectively. - * Actually, although the CMD tech support people won't - * tell me the details, the 0x03 revision cannot support - * UDMA correctly without hardware modifications, and even - * then it only works with Quantum disks due to some - * hold time assumptions in the 646U part which are fixed - * in the 646U2. - * So we only do UltraDMA on revision 0x05 and 0x07 chipsets. - */ - if ((id->dma_ultra & 0x0020) && (udma_100) && (udma_66) && (udma_33)) { - speed = XFER_UDMA_5; - } else if ((id->dma_ultra & 0x0010) && (udma_66) && (udma_33)) { - speed = XFER_UDMA_4; - } else if ((id->dma_ultra & 0x0008) && (udma_66) && (udma_33)) { - speed = XFER_UDMA_3; - } else if ((id->dma_ultra & 0x0004) && (udma_33)) { - speed = XFER_UDMA_2; - } else if ((id->dma_ultra & 0x0002) && (udma_33)) { - speed = XFER_UDMA_1; - } else if ((id->dma_ultra & 0x0001) && (udma_33)) { - speed = XFER_UDMA_0; - } else if (id->dma_mword & 0x0004) { - speed = XFER_MW_DMA_2; - } else if (id->dma_mword & 0x0002) { - speed = XFER_MW_DMA_1; - } else if (id->dma_mword & 0x0001) { - speed = XFER_MW_DMA_0; - } else if (id->dma_1word & 0x0004) { - speed = XFER_SW_DMA_2; - } else if (id->dma_1word & 0x0002) { - speed = XFER_SW_DMA_1; - } else if (id->dma_1word & 0x0001) { - speed = XFER_SW_DMA_0; - } else { - set_pio = 1; - } - - if (!drive->init_speed) - drive->init_speed = speed; - - config_chipset_for_pio(drive, set_pio); - - if (set_pio) - return ((int) ide_dma_off_quietly); - - if (cmd64x_tune_chipset(drive, speed)) - return ((int) ide_dma_off); - - rval = (int)( ((id->dma_ultra >> 11) & 7) ? ide_dma_on : - ((id->dma_ultra >> 8) & 7) ? ide_dma_on : - ((id->dma_mword >> 8) & 7) ? ide_dma_on : - ((id->dma_1word >> 8) & 7) ? ide_dma_on : - ide_dma_off_quietly); - - return rval; -} - -static int config_cmd680_chipset_for_dma (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - byte udma_66 = eighty_ninty_three(drive); - byte speed = 0x00; - byte set_pio = 0x00; - int rval; - - if ((id->dma_ultra & 0x0040) && (udma_66)) speed = XFER_UDMA_6; - else if ((id->dma_ultra & 0x0020) && (udma_66)) speed = XFER_UDMA_5; - else if ((id->dma_ultra & 0x0010) && (udma_66)) speed = XFER_UDMA_4; - else if ((id->dma_ultra & 0x0008) && (udma_66)) speed = XFER_UDMA_3; - else if (id->dma_ultra & 0x0004) speed = XFER_UDMA_2; - else if (id->dma_ultra & 0x0002) speed = XFER_UDMA_1; - else if (id->dma_ultra & 0x0001) speed = XFER_UDMA_0; - else if (id->dma_mword & 0x0004) speed = XFER_MW_DMA_2; - else if (id->dma_mword & 0x0002) speed = XFER_MW_DMA_1; - else if (id->dma_mword & 0x0001) speed = XFER_MW_DMA_0; - else { - set_pio = 1; + switch(mode) { + case 0x04: + if (id->dma_ultra & 0x0040) + { speed = XFER_UDMA_6; break; } + case 0x03: + if (id->dma_ultra & 0x0020) + { speed = XFER_UDMA_5; break; } + case 0x02: + if (id->dma_ultra & 0x0010) + { speed = XFER_UDMA_4; break; } + if (id->dma_ultra & 0x0008) + { speed = XFER_UDMA_3; break; } + case 0x01: + if (id->dma_ultra & 0x0004) + { speed = XFER_UDMA_2; break; } + if (id->dma_ultra & 0x0002) + { speed = XFER_UDMA_1; break; } + if (id->dma_ultra & 0x0001) + { speed = XFER_UDMA_0; break; } + case 0x00: + if (id->dma_mword & 0x0004) + { speed = XFER_MW_DMA_2; break; } + if (id->dma_mword & 0x0002) + { speed = XFER_MW_DMA_1; break; } + if (id->dma_mword & 0x0001) + { speed = XFER_MW_DMA_0; break; } + if (id->dma_1word & 0x0004) + { speed = XFER_SW_DMA_2; break; } + if (id->dma_1word & 0x0002) + { speed = XFER_SW_DMA_1; break; } + if (id->dma_1word & 0x0001) + { speed = XFER_SW_DMA_0; break; } + default: + { set_pio = 1; break; } } if (!drive->init_speed) @@ -736,7 +794,7 @@ if (set_pio) return ((int) ide_dma_off_quietly); - if (cmd680_tune_chipset(drive, speed)) + if (hwif->speedproc(drive, speed)) return ((int) ide_dma_off); rval = (int)( ((id->dma_ultra >> 14) & 3) ? ide_dma_on : @@ -745,50 +803,16 @@ ((id->dma_mword >> 8) & 7) ? ide_dma_on : ((id->dma_1word >> 8) & 7) ? ide_dma_on : ide_dma_off_quietly); - return rval; -} -static int config_chipset_for_dma (ide_drive_t *drive, unsigned int rev, byte ultra_66) -{ - if (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_CMD_680) - return (config_cmd680_chipset_for_dma(drive)); - return (config_cmd64x_chipset_for_dma(drive, rev, ultra_66)); + return rval; } static int cmd64x_config_drive_for_dma (ide_drive_t *drive) { struct hd_driveid *id = drive->id; ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - unsigned int class_rev = 0; - byte can_ultra_33 = 0; - byte can_ultra_66 = 0; - byte can_ultra_100 = 0; - byte can_ultra_133 = 0; ide_dma_action_t dma_func = ide_dma_on; - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xff; - - switch(dev->device) { - case PCI_DEVICE_ID_CMD_680: - can_ultra_133 = 1; - case PCI_DEVICE_ID_CMD_649: - can_ultra_100 = 1; - case PCI_DEVICE_ID_CMD_648: - can_ultra_66 = 1; - case PCI_DEVICE_ID_CMD_643: - can_ultra_33 = 1; - break; - case PCI_DEVICE_ID_CMD_646: - can_ultra_33 = (class_rev >= 0x05) ? 1 : 0; - can_ultra_66 = 0; - can_ultra_100 = 0; - break; - default: - return hwif->dmaproc(ide_dma_off, drive); - } - if ((id != NULL) && ((id->capability & 1) != 0) && hwif->autodma && (drive->media == ide_disk)) { /* Consult the list of known "bad" drives */ @@ -797,10 +821,10 @@ goto fast_ata_pio; } dma_func = ide_dma_off_quietly; - if ((id->field_valid & 4) && (can_ultra_33)) { + if ((id->field_valid & 4) && cmd64x_ratemask(drive)) { if (id->dma_ultra & 0x007F) { /* Force if Capable UltraDMA */ - dma_func = config_chipset_for_dma(drive, class_rev, can_ultra_66); + dma_func = config_chipset_for_dma(drive); if ((id->field_valid & 2) && (dma_func != ide_dma_on)) goto try_dma_modes; @@ -810,7 +834,7 @@ if ((id->dma_mword & 0x0007) || (id->dma_1word & 0x0007)) { /* Force if Capable regular DMA modes */ - dma_func = config_chipset_for_dma(drive, class_rev, 0); + dma_func = config_chipset_for_dma(drive); if (dma_func != ide_dma_on) goto no_dma_set; } @@ -819,7 +843,7 @@ goto no_dma_set; } /* Consult the list of known "good" drives */ - dma_func = config_chipset_for_dma(drive, class_rev, 0); + dma_func = config_chipset_for_dma(drive); if (dma_func != ide_dma_on) goto no_dma_set; } else { @@ -846,47 +870,64 @@ return ide_dmaproc(func, drive); } +static int cmd64x_alt_dma_status (struct pci_dev *dev) +{ + switch(dev->device) { + case PCI_DEVICE_ID_CMD_648: + case PCI_DEVICE_ID_CMD_649: + return 1; + default: + break; + } + return 0; +} + static int cmd64x_dmaproc (ide_dma_action_t func, ide_drive_t *drive) { byte dma_stat = 0; byte dma_alt_stat = 0; - byte mask = (HWIF(drive)->channel) ? MRDMODE_INTR_CH1 : MRDMODE_INTR_CH0; - unsigned long dma_base = HWIF(drive)->dma_base; - struct pci_dev *dev = HWIF(drive)->pci_dev; - byte jack_slap = ((dev->device == PCI_DEVICE_ID_CMD_648) || (dev->device == PCI_DEVICE_ID_CMD_649)) ? 1 : 0; + ide_hwif_t *hwif = HWIF(drive); + byte mask = (hwif->channel) ? MRDMODE_INTR_CH1 : MRDMODE_INTR_CH0; + unsigned long dma_base = hwif->dma_base; + struct pci_dev *dev = hwif->pci_dev; + byte alt_dma_stat = cmd64x_alt_dma_status(dev); switch (func) { case ide_dma_check: return cmd64x_config_drive_for_dma(drive); case ide_dma_end: /* returns 1 on error, 0 otherwise */ drive->waiting_for_dma = 0; - outb(inb(dma_base)&~1, dma_base); /* stop DMA */ - dma_stat = inb(dma_base+2); /* get DMA status */ - outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */ - if (jack_slap) { + /* stop DMA */ + OUT_BYTE(IN_BYTE(dma_base)&~1, dma_base); + /* get DMA status */ + dma_stat = IN_BYTE(dma_base+2); + /* clear the INTR & ERROR bits */ + OUT_BYTE(dma_stat|6, dma_base+2); + if (alt_dma_stat) { byte dma_intr = 0; - byte dma_mask = (HWIF(drive)->channel) ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0; - byte dma_reg = (HWIF(drive)->channel) ? ARTTIM2 : CFR; + byte dma_mask = (hwif->channel) ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0; + byte dma_reg = (hwif->channel) ? ARTTIM2 : CFR; (void) pci_read_config_byte(dev, dma_reg, &dma_intr); - /* - * DAMN BMIDE is not connected to PCI space! - * Have to manually jack-slap that bitch! - * To allow the PCI side to read incoming interrupts. - */ - (void) pci_write_config_byte(dev, dma_reg, dma_intr|dma_mask); /* clear the INTR bit */ + /* clear the INTR bit */ + (void) pci_write_config_byte(dev, dma_reg, dma_intr|dma_mask); } - ide_destroy_dmatable(drive); /* purge DMA mappings */ - return (dma_stat & 7) != 4; /* verify good DMA status */ + /* purge DMA mappings */ + ide_destroy_dmatable(drive); + /* verify good DMA status */ + return (dma_stat & 7) != 4; case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */ - dma_stat = inb(dma_base+2); + dma_stat = IN_BYTE(dma_base+2); (void) pci_read_config_byte(dev, MRDMODE, &dma_alt_stat); #ifdef DEBUG - printk("%s: dma_stat: 0x%02x dma_alt_stat: 0x%02x mask: 0x%02x\n", drive->name, dma_stat, dma_alt_stat, mask); + printk("%s: dma_stat: 0x%02x dma_alt_stat: " + "0x%02x mask: 0x%02x\n", drive->name, + dma_stat, dma_alt_stat, mask); #endif if (!(dma_alt_stat & mask)) { return 0; } - return (dma_stat & 4) == 4; /* return 1 if INTR asserted */ + /* return 1 if INTR asserted */ + return (dma_stat & 4) == 4; default: break; } @@ -909,11 +950,16 @@ return cmd64x_config_drive_for_dma(drive); case ide_dma_end: drive->waiting_for_dma = 0; - dma_stat = inb(dma_base+2); /* get DMA status */ - outb(inb(dma_base)&~1, dma_base); /* stop DMA */ - outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */ - ide_destroy_dmatable(drive); /* and free any DMA resources */ - return (dma_stat & 7) != 4; /* verify good DMA status */ + /* get DMA status */ + dma_stat = IN_BYTE(dma_base+2); + /* stop DMA */ + OUT_BYTE(IN_BYTE(dma_base)&~1, dma_base); + /* clear the INTR & ERROR bits */ + OUT_BYTE(dma_stat|6, dma_base+2); + /* and free any DMA resources */ + ide_destroy_dmatable(drive); + /* verify good DMA status */ + return (dma_stat & 7) != 4; default: break; } @@ -975,6 +1021,13 @@ pci_write_config_byte(dev, 0x84, 0x00); pci_read_config_byte(dev, 0x8A, &tmpbyte); pci_write_config_byte(dev, 0x8A, tmpbyte|0x01); +#if 0 + /* if 133 clock fails, switch to 2xbus clock */ + if (!(tmpbyte & 0x01)) { + pci_read_config_byte(dev, 0x8A, &tmpbyte); + pci_write_config_byte(dev, 0x8A, tmpbyte|0x10); + } +#endif pci_write_config_word(dev, 0xA2, 0x328A); pci_write_config_dword(dev, 0xA4, 0x328A); pci_write_config_dword(dev, 0xA8, 0x4392); @@ -984,13 +1037,15 @@ pci_write_config_dword(dev, 0xB8, 0x4392); pci_write_config_dword(dev, 0xBC, 0x4009); + cmd_devs[n_cmd_devs++] = dev; + #if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) if (!cmd64x_proc) { cmd64x_proc = 1; - bmide_dev = dev; - cmd64x_display_info = &cmd680_get_info; + cmd64x_display_info = &cmd64x_get_info; } #endif /* DISPLAY_CMD64X_TIMINGS && CONFIG_PROC_FS */ + return 0; } @@ -1072,10 +1127,11 @@ (void) pci_write_config_byte(dev, UDIDETCR0, 0xf0); #endif /* CONFIG_PPC */ + cmd_devs[n_cmd_devs++] = dev; + #if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) if (!cmd64x_proc) { cmd64x_proc = 1; - bmide_dev = dev; cmd64x_display_info = &cmd64x_get_info; } #endif /* DISPLAY_CMD64X_TIMINGS && CONFIG_PROC_FS */ @@ -1085,8 +1141,12 @@ unsigned int __init pci_init_cmd64x (struct pci_dev *dev, const char *name) { - if (dev->device == PCI_DEVICE_ID_CMD_680) - return cmd680_pci_init (dev, name); + switch(dev->device) { + case PCI_DEVICE_ID_CMD_680: + return cmd680_pci_init (dev, name); + default: + break; + } return cmd64x_pci_init (dev, name); } @@ -1110,9 +1170,12 @@ unsigned int __init ata66_cmd64x (ide_hwif_t *hwif) { - struct pci_dev *dev = hwif->pci_dev; - if (dev->device == PCI_DEVICE_ID_CMD_680) - return cmd680_ata66(hwif); + switch(hwif->pci_dev->device) { + case PCI_DEVICE_ID_CMD_680: + return cmd680_ata66(hwif); + default: + break; + } return cmd64x_ata66(hwif); } @@ -1127,14 +1190,13 @@ hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; - if (!hwif->dma_base) - return; - -#ifdef CONFIG_BLK_DEV_IDEDMA switch(dev->device) { case PCI_DEVICE_ID_CMD_680: hwif->busproc = &cmd680_busproc; - hwif->dmaproc = &cmd680_dmaproc; +#ifdef CONFIG_BLK_DEV_IDEDMA + if (hwif->dma_base) + hwif->dmaproc = &cmd680_dmaproc; +#endif /* CONFIG_BLK_DEV_IDEDMA */ hwif->resetproc = &cmd680_reset; hwif->speedproc = &cmd680_tune_chipset; hwif->tuneproc = &cmd680_tuneproc; @@ -1142,22 +1204,33 @@ case PCI_DEVICE_ID_CMD_649: case PCI_DEVICE_ID_CMD_648: case PCI_DEVICE_ID_CMD_643: - hwif->dmaproc = &cmd64x_dmaproc; +#ifdef CONFIG_BLK_DEV_IDEDMA + if (hwif->dma_base) + hwif->dmaproc = &cmd64x_dmaproc; +#endif /* CONFIG_BLK_DEV_IDEDMA */ hwif->tuneproc = &cmd64x_tuneproc; hwif->speedproc = &cmd64x_tune_chipset; break; case PCI_DEVICE_ID_CMD_646: hwif->chipset = ide_cmd646; - if (class_rev == 0x01) { - hwif->dmaproc = &cmd646_1_dmaproc; - } else { - hwif->dmaproc = &cmd64x_dmaproc; +#ifdef CONFIG_BLK_DEV_IDEDMA + if (hwif->dma_base) { + if (class_rev == 0x01) + hwif->dmaproc = &cmd646_1_dmaproc; + else + hwif->dmaproc = &cmd64x_dmaproc; } +#endif /* CONFIG_BLK_DEV_IDEDMA */ hwif->tuneproc = &cmd64x_tuneproc; hwif->speedproc = &cmd64x_tune_chipset; break; default: break; } -#endif /* CONFIG_BLK_DEV_IDEDMA */ + +#if defined(CONFIG_BLK_DEV_IDEDMA) && defined(CONFIG_IDEDMA_AUTO) + if (hwif->dma_base) + if (!noautodma) + hwif->autodma = 1; +#endif /* CONFIG_BLK_DEV_IDEDMA && CONFIG_IDEDMA_AUTO*/ } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/Config.in linux.19rc3-ac4/drivers/ide/Config.in --- linux.19rc3/drivers/ide/Config.in 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/Config.in 2002-07-29 13:58:39.000000000 +0100 @@ -34,7 +34,7 @@ dep_tristate ' SCSI emulation support' CONFIG_BLK_DEV_IDESCSI $CONFIG_BLK_DEV_IDE $CONFIG_SCSI bool ' IDE Taskfile Access' CONFIG_IDE_TASK_IOCTL -# bool ' IDE Taskfile IO' CONFIG_IDE_TASKFILE_IO + bool ' IDE Taskfile IO' CONFIG_IDE_TASKFILE_IO comment 'IDE chipset support/bugfixes' if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then @@ -55,17 +55,13 @@ dep_bool ' ATA Work(s) In Progress (EXPERIMENTAL)' CONFIG_IDEDMA_PCI_WIP $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_EXPERIMENTAL dep_bool ' Attempt to HACK around Chipsets that TIMEOUT (WIP)' CONFIG_BLK_DEV_IDEDMA_TIMEOUT $CONFIG_IDEDMA_PCI_WIP dep_bool ' Good-Bad DMA Model-Firmware (WIP)' CONFIG_IDEDMA_NEW_DRIVE_LISTINGS $CONFIG_IDEDMA_PCI_WIP -# dep_bool ' Asynchronous DMA support (WIP) (EXPERIMENTAL)' CONFIG_BLK_DEV_ADMA $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_IDEDMA_PCI_WIP $CONFIG_EXPERIMENTAL - define_bool CONFIG_BLK_DEV_ADMA $CONFIG_BLK_DEV_IDEDMA_PCI -# dep_bool ' Tag Command Queue DMA support (WIP) (EXPERIMENTAL)' CONFIG_BLK_DEV_IDEDMA_TCQ $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_IDEDMA_PCI_WIP $CONFIG_EXPERIMENTAL - dep_bool ' AEC62XX chipset support' CONFIG_BLK_DEV_AEC62XX $CONFIG_BLK_DEV_IDEDMA_PCI dep_mbool ' AEC62XX Tuning support' CONFIG_AEC62XX_TUNING $CONFIG_BLK_DEV_AEC62XX dep_bool ' ALI M15x3 chipset support' CONFIG_BLK_DEV_ALI15X3 $CONFIG_BLK_DEV_IDEDMA_PCI dep_mbool ' ALI M15x3 WDC support (DANGEROUS)' CONFIG_WDC_ALI15X3 $CONFIG_BLK_DEV_ALI15X3 dep_bool ' AMD Viper support' CONFIG_BLK_DEV_AMD74XX $CONFIG_BLK_DEV_IDEDMA_PCI dep_mbool ' AMD Viper ATA-66 Override (WIP)' CONFIG_AMD74XX_OVERRIDE $CONFIG_BLK_DEV_AMD74XX $CONFIG_IDEDMA_PCI_WIP - dep_bool ' CMD64X chipset support' CONFIG_BLK_DEV_CMD64X $CONFIG_BLK_DEV_IDEDMA_PCI + dep_bool ' CMD64X, CMD680 chipset support' CONFIG_BLK_DEV_CMD64X $CONFIG_BLK_DEV_IDEDMA_PCI dep_bool ' CMD680 chipset tuning support' CONFIG_BLK_DEV_CMD680 $CONFIG_BLK_DEV_CMD64X dep_bool ' CY82C693 chipset support' CONFIG_BLK_DEV_CY82C693 $CONFIG_BLK_DEV_IDEDMA_PCI dep_bool ' Cyrix CS5530 MediaGX chipset support' CONFIG_BLK_DEV_CS5530 $CONFIG_BLK_DEV_IDEDMA_PCI @@ -82,14 +78,15 @@ fi dep_bool ' NS87415 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_NS87415 $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_EXPERIMENTAL dep_bool ' OPTi 82C621 chipset enhanced support (EXPERIMENTAL)' CONFIG_BLK_DEV_OPTI621 $CONFIG_EXPERIMENTAL -# dep_mbool ' Pacific Digital A-DMA support (EXPERIMENTAL)' CONFIG_BLK_DEV_PDC_ADMA $CONFIG_BLK_DEV_ADMA $CONFIG_IDEDMA_PCI_WIP $CONFIG_EXPERIMENTAL + dep_bool ' Pacific Digital ADMA100 basic support' CONFIG_BLK_DEV_ADMA100 $CONFIG_BLK_DEV_IDEDMA_PCI dep_bool ' PROMISE PDC202{46|62|65|67|68|69|70} support' CONFIG_BLK_DEV_PDC202XX $CONFIG_BLK_DEV_IDEDMA_PCI dep_bool ' Special UDMA Feature' CONFIG_PDC202XX_BURST $CONFIG_BLK_DEV_PDC202XX dep_bool ' Special FastTrak Feature' CONFIG_PDC202XX_FORCE $CONFIG_BLK_DEV_PDC202XX - dep_bool ' ServerWorks OSB4/CSB5 chipsets support' CONFIG_BLK_DEV_SVWKS $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86 + dep_bool ' RZ1000 chipset bugfix/support' CONFIG_BLK_DEV_RZ1000 $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86 + dep_bool ' ServerWorks OSB4/CSB5/CSB6 chipsets support' CONFIG_BLK_DEV_SVWKS $CONFIG_BLK_DEV_IDEDMA_PCI dep_bool ' SiS5513 chipset support' CONFIG_BLK_DEV_SIS5513 $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86 dep_bool ' SLC90E66 chipset support' CONFIG_BLK_DEV_SLC90E66 $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86 - dep_bool ' Tekram TRM290 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_TRM290 $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_EXPERIMENTAL + dep_bool ' Tekram TRM290 chipset support' CONFIG_BLK_DEV_TRM290 $CONFIG_BLK_DEV_IDEDMA_PCI dep_bool ' VIA82CXXX chipset support' CONFIG_BLK_DEV_VIA82CXXX $CONFIG_BLK_DEV_IDEDMA_PCI if [ "$CONFIG_PPC" = "y" -o "$CONFIG_ARM" = "y" ]; then bool ' Winbond SL82c105 support' CONFIG_BLK_DEV_SL82C105 diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/cs5530.c linux.19rc3-ac4/drivers/ide/cs5530.c --- linux.19rc3/drivers/ide/cs5530.c 2002-07-29 12:49:58.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/cs5530.c 2002-07-29 13:58:39.000000000 +0100 @@ -37,7 +37,6 @@ static int cs5530_get_info(char *, char **, off_t, int); extern int (*cs5530_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); static struct pci_dev *bmide_dev; static int cs5530_get_info (char *buffer, char **addr, off_t offset, int count) @@ -54,13 +53,19 @@ c0 = inb_p((unsigned short)bibma + 0x02); c1 = inb_p((unsigned short)bibma + 0x0a); - p += sprintf(p, "\n Cyrix 5530 Chipset.\n"); - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); - p += sprintf(p, " %sabled %sabled\n", + p += sprintf(p, "\n " + "Cyrix 5530 Chipset.\n"); + p += sprintf(p, "--------------- Primary Channel " + "---------------- Secondary Channel " + "-------------\n"); + p += sprintf(p, " %sabled " + " %sabled\n", (c0&0x80) ? "dis" : " en", (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s %s %s\n", + p += sprintf(p, "--------------- drive0 --------- drive1 " + "-------- drive0 ---------- drive1 ------\n"); + p += sprintf(p, "DMA enabled: %s %s " + " %s %s\n", (c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ", (c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " ); @@ -74,19 +79,14 @@ byte cs5530_proc = 0; -extern char *ide_xfer_verbose (byte xfer_rate); - /* * Set a new transfer mode at the drive */ int cs5530_set_xfer_mode (ide_drive_t *drive, byte mode) { - int error = 0; - - printk("%s: cs5530_set_xfer_mode(%s)\n", drive->name, ide_xfer_verbose(mode)); - error = ide_config_drive_speed(drive, mode); - - return error; + printk("%s: cs5530_set_xfer_mode(%s)\n", + drive->name, ide_xfer_verbose(mode)); + return (ide_config_drive_speed(drive, mode)); } /* @@ -115,12 +115,13 @@ { ide_hwif_t *hwif = HWIF(drive); unsigned int format, basereg = CS5530_BASEREG(hwif); - static byte modes[5] = {XFER_PIO_0, XFER_PIO_1, XFER_PIO_2, XFER_PIO_3, XFER_PIO_4}; + static byte modes[5] = { XFER_PIO_0, XFER_PIO_1, XFER_PIO_2, XFER_PIO_3, XFER_PIO_4}; pio = ide_get_best_pio_mode(drive, pio, 4, NULL); if (!cs5530_set_xfer_mode(drive, modes[pio])) { format = (inl(basereg+4) >> 31) & 1; - outl(cs5530_pio_timings[format][pio], basereg+(drive->select.b.unit<<3)); + outl(cs5530_pio_timings[format][pio], + basereg+(drive->select.b.unit<<3)); } } @@ -138,12 +139,13 @@ struct hd_driveid *id = drive->id; unsigned int basereg, reg, timings; - /* * Default to DMA-off in case we run into trouble here. */ - (void)hwif->dmaproc(ide_dma_off_quietly, drive); /* turn off DMA while we fiddle */ - outb(inb(hwif->dma_base+2)&~(unit?0x40:0x20), hwif->dma_base+2); /* clear DMA_capable bit */ + (void)hwif->dmaproc(ide_dma_off_quietly, drive); + /* turn off DMA while we fiddle */ + (void)hwif->dmaproc(ide_dma_host_off, drive); + /* clear DMA_capable bit */ /* * The CS5530 specifies that two drives sharing a cable cannot @@ -156,10 +158,13 @@ */ if (mate->present) { struct hd_driveid *mateid = mate->id; - if (mateid && (mateid->capability & 1) && !hwif->dmaproc(ide_dma_bad_drive, mate)) { - if ((mateid->field_valid & 4) && (mateid->dma_ultra & 7)) + if (mateid && (mateid->capability & 1) && + !hwif->dmaproc(ide_dma_bad_drive, mate)) { + if ((mateid->field_valid & 4) && + (mateid->dma_ultra & 7)) udma_ok = 1; - else if ((mateid->field_valid & 2) && (mateid->dma_mword & 7)) + else if ((mateid->field_valid & 2) && + (mateid->dma_mword & 7)) udma_ok = 0; else udma_ok = 1; @@ -170,7 +175,8 @@ * Now see what the current drive is capable of, * selecting UDMA only if the mate said it was ok. */ - if (id && (id->capability & 1) && hwif->autodma && !hwif->dmaproc(ide_dma_bad_drive, drive)) { + if (id && (id->capability & 1) && hwif->autodma && + !hwif->dmaproc(ide_dma_bad_drive, drive)) { if (udma_ok && (id->field_valid & 4) && (id->dma_ultra & 7)) { if (id->dma_ultra & 4) mode = XFER_UDMA_2; @@ -206,11 +212,12 @@ case XFER_MW_DMA_1: timings = 0x00012121; break; case XFER_MW_DMA_2: timings = 0x00002020; break; default: - printk("%s: cs5530_config_dma: huh? mode=%02x\n", drive->name, mode); + printk("%s: cs5530_config_dma: huh? mode=%02x\n", + drive->name, mode); return 1; /* failure */ } basereg = CS5530_BASEREG(hwif); - reg = inl(basereg+4); /* get drive0 config register */ + reg = inl(basereg+4); /* get drive0 config register */ timings |= reg & 0x80000000; /* preserve PIO format bit */ if (unit == 0) { /* are we configuring drive0? */ outl(timings, basereg+4); /* write drive0 config register */ @@ -222,7 +229,8 @@ outl(reg, basereg+4); /* write drive0 config register */ outl(timings, basereg+12); /* write drive1 config register */ } - outb(inb(hwif->dma_base+2)|(unit?0x40:0x20), hwif->dma_base+2); /* set DMA_capable bit */ + (void)hwif->dmaproc(ide_dma_host_on, drive); + /* set DMA_capable bit */ /* * Finally, turn DMA on in software, and exit. @@ -286,8 +294,8 @@ return 0; } - save_flags(flags); - cli(); /* all CPUs (there should only be one CPU with this chipset) */ + spin_lock_irqsave(&io_request_lock, flags); + /* all CPUs (there should only be one CPU with this chipset) */ /* * Enable BusMaster and MemoryWriteAndInvalidate for the cs5530: @@ -333,7 +341,7 @@ pci_write_config_byte(master_0, 0x42, 0x00); pci_write_config_byte(master_0, 0x43, 0xc1); - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); return 0; } @@ -344,31 +352,35 @@ */ void __init ide_init_cs5530 (ide_hwif_t *hwif) { + unsigned int basereg, d0_timings; + hwif->autodma = 0; + if (hwif->mate) hwif->serialized = hwif->mate->serialized = 1; - if (!hwif->dma_base) { - hwif->autodma = 0; - } else { - unsigned int basereg, d0_timings; + + hwif->tuneproc = &cs5530_tuneproc; + basereg = CS5530_BASEREG(hwif); + d0_timings = inl(basereg+0); + if (CS5530_BAD_PIO(d0_timings)) { + /* PIO timings not initialized? */ + outl(cs5530_pio_timings[(d0_timings>>31)&1][0], basereg+0); + if (!hwif->drives[0].autotune) + hwif->drives[0].autotune = 1; + /* needs autotuning later */ + } + if (CS5530_BAD_PIO(inl(basereg+8))) { + /* PIO timings not initialized? */ + outl(cs5530_pio_timings[(d0_timings>>31)&1][0], basereg+8); + if (!hwif->drives[1].autotune) + hwif->drives[1].autotune = 1; + /* needs autotuning later */ + } #ifdef CONFIG_BLK_DEV_IDEDMA - hwif->dmaproc = &cs5530_dmaproc; -#else - hwif->autodma = 0; + hwif->dmaproc = &cs5530_dmaproc; +#ifdef CONFIG_IDEDMA_AUTO + if (!noautodma) + hwif->autodma = 1; +#endif /* CONFIG_IDEDMA_AUTO */ #endif /* CONFIG_BLK_DEV_IDEDMA */ - - hwif->tuneproc = &cs5530_tuneproc; - basereg = CS5530_BASEREG(hwif); - d0_timings = inl(basereg+0); - if (CS5530_BAD_PIO(d0_timings)) { /* PIO timings not initialized? */ - outl(cs5530_pio_timings[(d0_timings>>31)&1][0], basereg+0); - if (!hwif->drives[0].autotune) - hwif->drives[0].autotune = 1; /* needs autotuning later */ - } - if (CS5530_BAD_PIO(inl(basereg+8))) { /* PIO timings not initialized? */ - outl(cs5530_pio_timings[(d0_timings>>31)&1][0], basereg+8); - if (!hwif->drives[1].autotune) - hwif->drives[1].autotune = 1; /* needs autotuning later */ - } - } } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/cy82c693.c linux.19rc3-ac4/drivers/ide/cy82c693.c --- linux.19rc3/drivers/ide/cy82c693.c 2002-07-29 12:49:58.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/cy82c693.c 2002-07-29 13:58:39.000000000 +0100 @@ -105,10 +105,10 @@ /* the struct for the PIO mode timings */ typedef struct pio_clocks_s { - byte address_time; /* Address setup (clocks) */ - byte time_16r; /* clocks for 16bit IOR (0xF0=Active/data, 0x0F=Recovery) */ - byte time_16w; /* clocks for 16bit IOW (0xF0=Active/data, 0x0F=Recovery) */ - byte time_8; /* clocks for 8bit (0xF0=Active/data, 0x0F=Recovery) */ + byte address_time; /* Address setup (clocks) */ + byte time_16r; /* clocks for 16bit IOR (0xF0=Active/data, 0x0F=Recovery) */ + byte time_16w; /* clocks for 16bit IOW (0xF0=Active/data, 0x0F=Recovery) */ + byte time_8; /* clocks for 8bit (0xF0=Active/data, 0x0F=Recovery) */ } pio_clocks_t; /* @@ -183,24 +183,26 @@ */ static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single) { - byte index; + byte index; byte data; - if (mode>2) /* make sure we set a valid mode */ + if (mode>2) /* make sure we set a valid mode */ mode = 2; if (mode > drive->id->tDMA) /* to be absolutly sure we have a valid mode */ mode = drive->id->tDMA; - index = (HWIF(drive)->channel==0) ? CY82_INDEX_CHANNEL0 : CY82_INDEX_CHANNEL1; + index = (HWIF(drive)->channel==0) ? CY82_INDEX_CHANNEL0 : CY82_INDEX_CHANNEL1; #if CY82C693_DEBUG_LOGS - /* for debug let's show the previous values */ + /* for debug let's show the previous values */ OUT_BYTE(index, CY82_INDEX_PORT); data = IN_BYTE(CY82_DATA_PORT); - printk (KERN_INFO "%s (ch=%d, dev=%d): DMA mode is %d (single=%d)\n", drive->name, HWIF(drive)->channel, drive->select.b.unit, (data&0x3), ((data>>2)&1)); + printk (KERN_INFO "%s (ch=%d, dev=%d): DMA mode is %d (single=%d)\n", + drive->name, HWIF(drive)->channel, drive->select.b.unit, + (data&0x3), ((data>>2)&1)); #endif /* CY82C693_DEBUG_LOGS */ data = (byte)mode|(byte)(single<<2); @@ -209,7 +211,9 @@ OUT_BYTE(data, CY82_DATA_PORT); #if CY82C693_DEBUG_INFO - printk (KERN_INFO "%s (ch=%d, dev=%d): set DMA mode to %d (single=%d)\n", drive->name, HWIF(drive)->channel, drive->select.b.unit, mode, single); + printk(KERN_INFO "%s (ch=%d, dev=%d): set DMA mode to %d (single=%d)\n", + drive->name, HWIF(drive)->channel, drive->select.b.unit, + mode, single); #endif /* CY82C693_DEBUG_INFO */ /* @@ -227,7 +231,8 @@ OUT_BYTE(data, CY82_DATA_PORT); #if CY82C693_DEBUG_INFO - printk (KERN_INFO "%s: Set IDE Bus Master TimeOut Register to 0x%X\n", drive->name, data); + printk (KERN_INFO "%s: Set IDE Bus Master TimeOut Register to 0x%X\n", + drive->name, data); #endif /* CY82C693_DEBUG_INFO */ } @@ -318,7 +323,10 @@ pci_read_config_byte(dev, CY82_IDE_SLAVE_8BIT, &pclk.time_8); } - printk (KERN_INFO "%s (ch=%d, dev=%d): PIO timing is (addr=0x%X, ior=0x%X, iow=0x%X, 8bit=0x%X)\n", drive->name, hwif->channel, drive->select.b.unit, addrCtrl, pclk.time_16r, pclk.time_16w, pclk.time_8); + printk(KERN_INFO "%s (ch=%d, dev=%d): PIO timing is " + "(addr=0x%X, ior=0x%X, iow=0x%X, 8bit=0x%X)\n", + drive->name, hwif->channel, drive->select.b.unit, + addrCtrl, pclk.time_16r, pclk.time_16w, pclk.time_8); #endif /* CY82C693_DEBUG_LOGS */ /* first let's calc the pio modes */ @@ -371,7 +379,10 @@ } #if CY82C693_DEBUG_INFO - printk (KERN_INFO "%s (ch=%d, dev=%d): set PIO timing to (addr=0x%X, ior=0x%X, iow=0x%X, 8bit=0x%X)\n", drive->name, hwif->channel, drive->select.b.unit, addrCtrl, pclk.time_16r, pclk.time_16w, pclk.time_8); + printk(KERN_INFO "%s (ch=%d, dev=%d): set PIO timing to " + "(addr=0x%X, ior=0x%X, iow=0x%X, 8bit=0x%X)\n", + drive->name, hwif->channel, drive->select.b.unit, + addrCtrl, pclk.time_16r, pclk.time_16w, pclk.time_8); #endif /* CY82C693_DEBUG_INFO */ } @@ -391,7 +402,7 @@ #endif /* CY82C693_SETDMA_CLOCK */ /* write info about this verion of the driver */ - printk (KERN_INFO CY82_VERSION "\n"); + printk(KERN_INFO CY82_VERSION "\n"); #ifdef CY82C693_SETDMA_CLOCK /* okay let's set the DMA clock speed */ @@ -400,7 +411,8 @@ data = IN_BYTE(CY82_DATA_PORT); #if CY82C693_DEBUG_INFO - printk (KERN_INFO "%s: Peripheral Configuration Register: 0x%X\n", name, data); + printk(KERN_INFO "%s: Peripheral Configuration Register: 0x%X\n", + name, data); #endif /* CY82C693_DEBUG_INFO */ /* @@ -421,7 +433,8 @@ OUT_BYTE(data, CY82_DATA_PORT); #if CY82C693_DEBUG_INFO - printk (KERN_INFO "%s: New Peripheral Configuration Register: 0x%X\n", name, data); + printk (KERN_INFO "%s: New Peripheral Configuration Register: 0x%X\n", + name, data); #endif /* CY82C693_DEBUG_INFO */ #endif /* CY82C693_SETDMA_CLOCK */ @@ -439,11 +452,27 @@ hwif->drives[1].autotune = 1; hwif->autodma = 0; + if (!hwif->dma_base) + return; #ifdef CONFIG_BLK_DEV_IDEDMA - if (hwif->dma_base) { - hwif->dmaproc = &cy82c693_dmaproc; - if (!noautodma) - hwif->autodma = 1; - } + hwif->dmaproc = &cy82c693_dmaproc; +#ifdef CONFIG_IDEDMA_AUTO + if (!noautodma) + hwif->autodma = 1; +#endif /* CONFIG_IDEDMA_AUTO */ #endif /* CONFIG_BLK_DEV_IDEDMA */ } + +extern void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d); + +void __init fixup_device_cy82c693 (struct pci_dev *dev, ide_pci_device_t *d) +{ + if ((!(PCI_FUNC(dev->devfn) & 1) || + (!((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)))) + return; /* CY82C693 is more than only a IDE controller */ + + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d->name, dev->bus->number, dev->devfn); + ide_setup_pci_device(dev, d); +} + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/dtc2278.c linux.19rc3-ac4/drivers/ide/dtc2278.c --- linux.19rc3/drivers/ide/dtc2278.c 2002-07-29 12:49:58.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/dtc2278.c 2002-07-29 13:58:39.000000000 +0100 @@ -57,14 +57,14 @@ int i; for(i = 0; i < 3; ++i) { - inb(0x3f6); + IN_BYTE(0x3f6); outb_p(b,0xb0); - inb(0x3f6); + IN_BYTE(0x3f6); outb_p(c,0xb4); - inb(0x3f6); - if(inb(0xb4) == c) { + IN_BYTE(0x3f6); + if(IN_BYTE(0xb4) == c) { outb_p(7,0xb0); - inb(0x3f6); + IN_BYTE(0x3f6); return; /* success */ } } @@ -77,14 +77,13 @@ pio = ide_get_best_pio_mode(drive, pio, 4, NULL); if (pio >= 3) { - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ + spin_lock_irqsave(&io_request_lock, flags); /* * This enables PIO mode4 (3?) on the first interface */ sub22(1,0xc3); sub22(0,0xa0); - restore_flags(flags); /* all CPUs */ + spin_unlock_irqrestore(&io_request_lock, flags); } else { /* we don't know how to set it back again.. */ } @@ -100,15 +99,14 @@ { unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ + local_irq_save(flags); /* * This enables the second interface */ outb_p(4,0xb0); - inb(0x3f6); + IN_BYTE(0x3f6); outb_p(0x20,0xb4); - inb(0x3f6); + IN_BYTE(0x3f6); #ifdef ALWAYS_SET_DTC2278_PIO_MODE /* * This enables PIO mode4 (3?) on the first interface @@ -117,7 +115,7 @@ sub22(1,0xc3); sub22(0,0xa0); #endif - __restore_flags(flags); /* local CPU only */ + local_irq_restore(flags); ide_hwifs[0].serialized = 1; ide_hwifs[1].serialized = 1; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/hd.c linux.19rc3-ac4/drivers/ide/hd.c --- linux.19rc3/drivers/ide/hd.c 2002-07-29 12:49:58.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/hd.c 2002-07-29 13:58:39.000000000 +0100 @@ -135,13 +135,12 @@ unsigned long t, flags; int i; - save_flags(flags); - cli(); + spin_lock_irqsave(&io_request_lock, flags); t = jiffies * 11932; outb_p(0, 0x43); i = inb_p(0x40); - i |= inb(0x40) << 8; - restore_flags(flags); + i |= IN_BYTE(0x40) << 8; + spin_unlock_irqrestore(&io_request_lock, flags); return(t - i); } #endif @@ -185,7 +184,7 @@ if ((stat & ERR_STAT) == 0) { hd_error = 0; } else { - hd_error = inb(HD_ERROR); + hd_error = IN_BYTE(HD_ERROR); printk("hd%c: %s: error=0x%02x { ", devc, msg, hd_error & 0xff); if (hd_error & BBD_ERR) printk("BadSector "); if (hd_error & ECC_ERR) printk("UncorrectableError "); @@ -195,8 +194,9 @@ if (hd_error & MARK_ERR) printk("AddrMarkNotFound "); printk("}"); if (hd_error & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) { - printk(", CHS=%d/%d/%d", (inb(HD_HCYL)<<8) + inb(HD_LCYL), - inb(HD_CURRENT) & 0xf, inb(HD_SECTOR)); + printk(", CHS=%d/%d/%d", + (IN_BYTE(HD_HCYL)<<8) + IN_BYTE(HD_LCYL), + IN_BYTE(HD_CURRENT) & 0xf, IN_BYTE(HD_SECTOR)); if (!QUEUE_EMPTY) printk(", sector=%ld", CURRENT->sector); } @@ -207,7 +207,7 @@ if ((stat & ERR_STAT) == 0) { hd_error = 0; } else { - hd_error = inb(HD_ERROR); + hd_error = IN_BYTE(HD_ERROR); printk("hd%c: %s: error=0x%02x.\n", devc, msg, hd_error & 0xff); } #endif /* verbose errors */ @@ -318,7 +318,7 @@ for(i = 0; i < 1000; i++) barrier(); if (drive_busy()) printk("hd: controller still busy\n"); - else if ((hd_error = inb(HD_ERROR)) != 1) + else if ((hd_error = IN_BYTE(HD_ERROR)) != 1) printk("hd: controller reset failed: %02x\n",hd_error); } @@ -346,6 +346,13 @@ hd_request(); } +void do_reset_hd(void) +{ + DEVICE_INTR = NULL; + reset = 1; + reset_hd(); +} + /* * Ok, don't know what to do with the unexpected interrupts: on some machines * doing a reset and a retry seems to result in an eternal loop. Right now I @@ -876,14 +883,13 @@ target = DEVICE_NR(dev); gdev = &GENDISK_STRUCT; - save_flags(flags); - cli(); + spin_lock_irqsave(&io_request_lock, flags); if (DEVICE_BUSY || USAGE > maxusage) { - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); return -EBUSY; } DEVICE_BUSY = 1; - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); max_p = gdev->max_p; start = target << gdev->minor_shift; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/hpt34x.c linux.19rc3-ac4/drivers/ide/hpt34x.c --- linux.19rc3/drivers/ide/hpt34x.c 2002-07-29 12:49:58.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/hpt34x.c 2002-07-29 13:58:39.000000000 +0100 @@ -50,41 +50,57 @@ #undef DISPLAY_HPT34X_TIMINGS +#define HPT34X_MAX_DEVS 8 +static struct pci_dev *hpt34x_devs[HPT34X_MAX_DEVS]; +static int n_hpt34x_devs; + #if defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS) #include #include static int hpt34x_get_info(char *, char **, off_t, int); extern int (*hpt34x_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); -static struct pci_dev *bmide_dev; static int hpt34x_get_info (char *buffer, char **addr, off_t offset, int count) { char *p = buffer; - u32 bibma = pci_resource_start(bmide_dev, 4); - u8 c0 = 0, c1 = 0; + int i; - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - c0 = inb_p((unsigned short)bibma + 0x02); - c1 = inb_p((unsigned short)bibma + 0x0a); - - p += sprintf(p, "\n HPT34X Chipset.\n"); - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); - p += sprintf(p, " %sabled %sabled\n", - (c0&0x80) ? "dis" : " en", - (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s %s %s\n", - (c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ", - (c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " ); - - p += sprintf(p, "UDMA\n"); - p += sprintf(p, "DMA\n"); - p += sprintf(p, "PIO\n"); + p += sprintf(p, "\n " + "HPT34X Chipset.\n"); + for (i = 0; i < n_hpt34x_devs; i++) { + struct pci_dev *dev = hpt34x_devs[i]; + u32 bibma = pci_resource_start(dev, 4); + u8 c0 = 0, c1 = 0; + + /* + * at that point bibma+0x2 et bibma+0xa are byte registers + * to investigate: + */ + c0 = inb_p((unsigned short)bibma + 0x02); + c1 = inb_p((unsigned short)bibma + 0x0a); + p += sprintf(p, "\nController: %d\n", i); + p += sprintf(p, "--------------- Primary Channel " + "---------------- Secondary Channel " + "-------------\n"); + p += sprintf(p, " %sabled " + " %sabled\n", + (c0&0x80) ? "dis" : " en", + (c1&0x80) ? "dis" : " en"); + p += sprintf(p, "--------------- drive0 --------- drive1 " + "-------- drive0 ---------- drive1 ------\n"); + p += sprintf(p, "DMA enabled: %s %s" + " %s %s\n", + (c0&0x20) ? "yes" : "no ", + (c0&0x40) ? "yes" : "no ", + (c1&0x20) ? "yes" : "no ", + (c1&0x40) ? "yes" : "no " ); + + p += sprintf(p, "UDMA\n"); + p += sprintf(p, "DMA\n"); + p += sprintf(p, "PIO\n"); + } + p += sprintf(p, "\n"); return p-buffer; /* => must be less than 4k! */ } @@ -92,27 +108,65 @@ byte hpt34x_proc = 0; -extern char *ide_xfer_verbose (byte xfer_rate); +static byte hpt34x_ratemask (ide_drive_t *drive) +{ + byte mode = 0x00; + + mode |= 0x01; + + if (!eighty_ninty_three(drive)) { + mode &= ~0xFE; + mode |= 0x01; + } + return (mode &= ~0xF8); +} + +static byte hpt34x_ratefilter (ide_drive_t *drive, byte speed) +{ +#ifdef CONFIG_BLK_DEV_IDEDMA +# ifdef CONFIG_HPT34X_AUTODMA +byte mode = hpt34x_ratemask(drive); + + switch(mode) { + case 0x04: // while (speed > XFER_UDMA_6) speed--; break; + case 0x03: // while (speed > XFER_UDMA_5) speed--; break; + case 0x02: // while (speed > XFER_UDMA_4) speed--; break; + case 0x01: while (speed > XFER_UDMA_2) speed--; break; + case 0x00: + default: while (speed > XFER_MW_DMA_2) speed--; break; + break; + } +# else /* !CONFIG_HPT34X_AUTODMA */ + while (speed > XFER_PIO_4) speed--; +# endif /* CONFIG_HPT34X_AUTODMA */ +#else + while (speed > XFER_PIO_4) speed--; +#endif /* CONFIG_BLK_DEV_IDEDMA */ +// printk("%s: mode == %02x speed == %02x\n", drive->name, mode, speed); + return speed; +} static void hpt34x_clear_chipset (ide_drive_t *drive) { + struct pci_dev *dev = HWIF(drive)->pci_dev; unsigned int reg1 = 0, tmp1 = 0; unsigned int reg2 = 0, tmp2 = 0; - pci_read_config_dword(HWIF(drive)->pci_dev, 0x44, ®1); - pci_read_config_dword(HWIF(drive)->pci_dev, 0x48, ®2); + pci_read_config_dword(dev, 0x44, ®1); + pci_read_config_dword(dev, 0x48, ®2); tmp1 = ((0x00 << (3*drive->dn)) | (reg1 & ~(7 << (3*drive->dn)))); tmp2 = (reg2 & ~(0x11 << drive->dn)); - pci_write_config_dword(HWIF(drive)->pci_dev, 0x44, tmp1); - pci_write_config_dword(HWIF(drive)->pci_dev, 0x48, tmp2); + pci_write_config_dword(dev, 0x44, tmp1); + pci_write_config_dword(dev, 0x48, tmp2); } -static int hpt34x_tune_chipset (ide_drive_t *drive, byte speed) +static int hpt34x_tune_chipset (ide_drive_t *drive, byte xferspeed) { - int err; - byte hi_speed, lo_speed; + struct pci_dev *dev = HWIF(drive)->pci_dev; + byte speed = hpt34x_ratefilter(drive, xferspeed); unsigned int reg1 = 0, tmp1 = 0; unsigned int reg2 = 0, tmp2 = 0; + byte hi_speed, lo_speed; SPLIT_BYTE(speed, hi_speed, lo_speed); @@ -123,76 +177,35 @@ lo_speed >>= 5; } - pci_read_config_dword(HWIF(drive)->pci_dev, 0x44, ®1); - pci_read_config_dword(HWIF(drive)->pci_dev, 0x48, ®2); + pci_read_config_dword(dev, 0x44, ®1); + pci_read_config_dword(dev, 0x48, ®2); tmp1 = ((lo_speed << (3*drive->dn)) | (reg1 & ~(7 << (3*drive->dn)))); tmp2 = ((hi_speed << drive->dn) | reg2); - err = ide_config_drive_speed(drive, speed); - pci_write_config_dword(HWIF(drive)->pci_dev, 0x44, tmp1); - pci_write_config_dword(HWIF(drive)->pci_dev, 0x48, tmp2); - - if (!drive->init_speed) - drive->init_speed = speed; + pci_write_config_dword(dev, 0x44, tmp1); + pci_write_config_dword(dev, 0x48, tmp2); #if HPT343_DEBUG_DRIVE_INFO printk("%s: %s drive%d (0x%04x 0x%04x) (0x%04x 0x%04x)" \ - " (0x%02x 0x%02x) 0x%04x\n", + " (0x%02x 0x%02x)\n", drive->name, ide_xfer_verbose(speed), drive->dn, reg1, tmp1, reg2, tmp2, - hi_speed, lo_speed, err); + hi_speed, lo_speed); #endif /* HPT343_DEBUG_DRIVE_INFO */ - drive->current_speed = speed; - return(err); -} - -static void config_chipset_for_pio (ide_drive_t *drive) -{ - unsigned short eide_pio_timing[6] = {960, 480, 240, 180, 120, 90}; - unsigned short xfer_pio = drive->id->eide_pio_modes; - - byte timing, speed, pio; - - pio = ide_get_best_pio_mode(drive, 255, 5, NULL); - - if (xfer_pio> 4) - xfer_pio = 0; - - if (drive->id->eide_pio_iordy > 0) { - for (xfer_pio = 5; - xfer_pio>0 && - drive->id->eide_pio_iordy>eide_pio_timing[xfer_pio]; - xfer_pio--); - } else { - xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 : - (drive->id->eide_pio_modes & 2) ? 0x04 : - (drive->id->eide_pio_modes & 1) ? 0x03 : xfer_pio; - } - - timing = (xfer_pio >= pio) ? xfer_pio : pio; - - switch(timing) { - case 4: speed = XFER_PIO_4;break; - case 3: speed = XFER_PIO_3;break; - case 2: speed = XFER_PIO_2;break; - case 1: speed = XFER_PIO_1;break; - default: - speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW; - break; - } - (void) hpt34x_tune_chipset(drive, speed); + return(ide_config_drive_speed(drive, speed)); } static void hpt34x_tune_drive (ide_drive_t *drive, byte pio) { byte speed; + pio = ide_get_best_pio_mode(drive, pio, 5, NULL); switch(pio) { - case 4: speed = XFER_PIO_4;break; - case 3: speed = XFER_PIO_3;break; - case 2: speed = XFER_PIO_2;break; - case 1: speed = XFER_PIO_1;break; - default: speed = XFER_PIO_0;break; + case 4: speed = XFER_PIO_4; break; + case 3: speed = XFER_PIO_3; break; + case 2: speed = XFER_PIO_2; break; + case 1: speed = XFER_PIO_1; break; + default: speed = XFER_PIO_0; break; } hpt34x_clear_chipset(drive); (void) hpt34x_tune_chipset(drive, speed); @@ -205,42 +218,41 @@ * after the drive is reported by the OS. Initally for designed for * HPT343 UDMA chipset by HighPoint|Triones Technologies, Inc. */ -static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) +static int config_chipset_for_dma (ide_drive_t *drive) { struct hd_driveid *id = drive->id; + byte mode = hpt34x_ratemask(drive); byte speed = 0x00; if (drive->media != ide_disk) return ((int) ide_dma_off_quietly); - hpt34x_clear_chipset(drive); - - if ((id->dma_ultra & 0x0010) && ultra) { - speed = XFER_UDMA_2; - } else if ((id->dma_ultra & 0x0008) && ultra) { - speed = XFER_UDMA_2; - } else if ((id->dma_ultra & 0x0004) && ultra) { - speed = XFER_UDMA_2; - } else if ((id->dma_ultra & 0x0002) && ultra) { - speed = XFER_UDMA_1; - } else if ((id->dma_ultra & 0x0001) && ultra) { - speed = XFER_UDMA_0; - } else if (id->dma_mword & 0x0004) { - speed = XFER_MW_DMA_2; - } else if (id->dma_mword & 0x0002) { - speed = XFER_MW_DMA_1; - } else if (id->dma_mword & 0x0001) { - speed = XFER_MW_DMA_0; - } else if (id->dma_1word & 0x0004) { - speed = XFER_SW_DMA_2; - } else if (id->dma_1word & 0x0002) { - speed = XFER_SW_DMA_1; - } else if (id->dma_1word & 0x0001) { - speed = XFER_SW_DMA_0; - } else { - return ((int) ide_dma_off_quietly); + switch(mode) { + case 0x01: + if (id->dma_ultra & 0x0004) + { speed = XFER_UDMA_2; break; } + if (id->dma_ultra & 0x0002) + { speed = XFER_UDMA_1; break; } + if (id->dma_ultra & 0x0001) + { speed = XFER_UDMA_0; break; } + case 0x00: + if (id->dma_mword & 0x0004) + { speed = XFER_MW_DMA_2; break; } + if (id->dma_mword & 0x0002) + { speed = XFER_MW_DMA_1; break; } + if (id->dma_mword & 0x0001) + { speed = XFER_MW_DMA_0; break; } + if (id->dma_1word & 0x0004) + { speed = XFER_SW_DMA_2; break; } + if (id->dma_1word & 0x0002) + { speed = XFER_SW_DMA_1; break; } + if (id->dma_1word & 0x0001) + { speed = XFER_SW_DMA_0; break; } + default: + return ((int) ide_dma_off_quietly); } + hpt34x_clear_chipset(drive); (void) hpt34x_tune_chipset(drive, speed); return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_off : @@ -255,6 +267,8 @@ struct hd_driveid *id = drive->id; ide_dma_action_t dma_func = ide_dma_on; + drive->init_speed = 0; + if (id && (id->capability & 1) && HWIF(drive)->autodma) { /* Consult the list of known "bad" drives */ if (ide_dmaproc(ide_dma_bad_drive, drive)) { @@ -265,7 +279,7 @@ if (id->field_valid & 4) { if (id->dma_ultra & 0x0007) { /* Force if Capable UltraDMA */ - dma_func = config_chipset_for_dma(drive, 1); + dma_func = config_chipset_for_dma(drive); if ((id->field_valid & 2) && (dma_func != ide_dma_on)) goto try_dma_modes; @@ -275,7 +289,7 @@ if ((id->dma_mword & 0x0007) || (id->dma_1word & 0x0007)) { /* Force if Capable regular DMA modes */ - dma_func = config_chipset_for_dma(drive, 0); + dma_func = config_chipset_for_dma(drive); if (dma_func != ide_dma_on) goto no_dma_set; } @@ -284,7 +298,7 @@ goto no_dma_set; } /* Consult the list of known "good" drives */ - dma_func = config_chipset_for_dma(drive, 0); + dma_func = config_chipset_for_dma(drive); if (dma_func != ide_dma_on) goto no_dma_set; } else { @@ -294,7 +308,7 @@ fast_ata_pio: dma_func = ide_dma_off_quietly; no_dma_set: - config_chipset_for_pio(drive); + hpt34x_tune_drive(drive, 255); } #ifndef CONFIG_HPT34X_AUTODMA @@ -316,6 +330,7 @@ int hpt34x_dmaproc (ide_dma_action_t func, ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); +// ide_task_t *args = HWGROUP(drive)->rq->special; unsigned long dma_base = hwif->dma_base; unsigned int count, reading = 0; byte dma_stat; @@ -327,24 +342,52 @@ reading = 1 << 3; case ide_dma_write: if (!(count = ide_build_dmatable(drive, func))) - return 1; /* try PIO instead of DMA */ - outl(hwif->dmatable_dma, dma_base + 4); /* PRD table */ + return 1; + /* try PIO instead of DMA */ + outl(hwif->dmatable_dma, dma_base + 4); + /* PRD table */ reading |= 0x01; - outb(reading, dma_base); /* specify r/w */ - outb(inb(dma_base+2)|6, dma_base+2); /* clear INTR & ERROR flags */ + OUT_BYTE(reading, dma_base); + /* specify r/w */ + OUT_BYTE(IN_BYTE(dma_base+2)|6, dma_base+2); + /* clear INTR & ERROR flags */ drive->waiting_for_dma = 1; if (drive->media != ide_disk) return 0; - ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); /* issue cmd to drive */ - OUT_BYTE((reading == 9) ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); - return 0; + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); + ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); + /* issue cmd to drive */ + /* + * FIX ME to use only ACB ide_task_t args Struct + */ +#if 0 + { + ide_task_t *args = HWGROUP(drive)->rq->special; + OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); + { +#else + if (HWGROUP(drive)->rq->cmd == IDE_DRIVE_TASKFILE) { + ide_task_t *args = HWGROUP(drive)->rq->special; + OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); + } else if (drive->addressing == 1) + OUT_BYTE((reading == 9) ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG); + else + OUT_BYTE((reading == 9) ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); +#endif + return HWIF(drive)->dmaproc(ide_dma_begin, drive); case ide_dma_end: /* returns 1 on error, 0 otherwise */ drive->waiting_for_dma = 0; - outb(inb(dma_base)&~1, dma_base); /* stop DMA */ - dma_stat = inb(dma_base+2); /* get DMA status */ - outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */ - ide_destroy_dmatable(drive); /* purge DMA mappings */ - return (dma_stat & 7) != 4; /* verify good DMA status */ + /* stop DMA */ + OUT_BYTE(IN_BYTE(dma_base)&~1, dma_base); + /* get DMA status */ + dma_stat = IN_BYTE(dma_base+2); + /* clear the INTR & ERROR bits */ + OUT_BYTE(dma_stat|6, dma_base+2); + /* purge DMA mappings */ + ide_destroy_dmatable(drive); + /* verify good DMA status */ + return (dma_stat & 7) != 4; default: break; } @@ -361,11 +404,11 @@ { int i = 0; unsigned long hpt34xIoBase = pci_resource_start(dev, 4); + unsigned long hpt_addr[4] = { 0x20, 0x34, 0x28, 0x3c }; unsigned short cmd; unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ + local_irq_save(flags); pci_write_config_byte(dev, HPT34X_PCI_INIT_REG, 0x00); pci_read_config_word(dev, PCI_COMMAND, &cmd); @@ -373,35 +416,34 @@ if (cmd & PCI_COMMAND_MEMORY) { if (pci_resource_start(dev, PCI_ROM_RESOURCE)) { pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); - printk(KERN_INFO "HPT345: ROM enabled at 0x%08lx\n", dev->resource[PCI_ROM_RESOURCE].start); + printk(KERN_INFO "HPT345: ROM enabled at 0x%08lx\n", + dev->resource[PCI_ROM_RESOURCE].start); } pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xF0); } else { pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20); } - pci_write_config_word(dev, PCI_COMMAND, cmd & ~PCI_COMMAND_IO); - dev->resource[0].start = (hpt34xIoBase + 0x20); - dev->resource[1].start = (hpt34xIoBase + 0x34); - dev->resource[2].start = (hpt34xIoBase + 0x28); - dev->resource[3].start = (hpt34xIoBase + 0x3c); - for(i=0; i<4; i++) - dev->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO; /* * Since 20-23 can be assigned and are R/W, we correct them. */ - pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, dev->resource[0].start); - pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, dev->resource[1].start); - pci_write_config_dword(dev, PCI_BASE_ADDRESS_2, dev->resource[2].start); - pci_write_config_dword(dev, PCI_BASE_ADDRESS_3, dev->resource[3].start); + pci_write_config_word(dev, PCI_COMMAND, cmd & ~PCI_COMMAND_IO); + for(i=0; i<4; i++) { + dev->resource[i].start = (hpt34xIoBase + hpt_addr[i]); + dev->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO; + pci_write_config_dword(dev, + (PCI_BASE_ADDRESS_0 + (i * 4)), + dev->resource[i].start); + } pci_write_config_word(dev, PCI_COMMAND, cmd); - __restore_flags(flags); /* local CPU only */ + local_irq_restore(flags); + + hpt34x_devs[n_hpt34x_devs++] = dev; #if defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS) if (!hpt34x_proc) { hpt34x_proc = 1; - bmide_dev = dev; hpt34x_display_info = &hpt34x_get_info; } #endif /* DISPLAY_HPT34X_TIMINGS && CONFIG_PROC_FS */ @@ -411,27 +453,39 @@ void __init ide_init_hpt34x (ide_hwif_t *hwif) { + unsigned short pcicmd = 0; hwif->tuneproc = &hpt34x_tune_drive; hwif->speedproc = &hpt34x_tune_chipset; - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (hwif->dma_base) { - unsigned short pcicmd = 0; - - pci_read_config_word(hwif->pci_dev, PCI_COMMAND, &pcicmd); - if (!noautodma) - hwif->autodma = (pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0; - else - hwif->autodma = 0; - - hwif->dmaproc = &hpt34x_dmaproc; - } else { - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - } -#else /* !CONFIG_BLK_DEV_IDEDMA */ hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; hwif->autodma = 0; + + pci_read_config_word(hwif->pci_dev, PCI_COMMAND, &pcicmd); + + if (!hwif->dma_base) + return; + +#ifdef CONFIG_BLK_DEV_IDEDMA + hwif->dmaproc = &hpt34x_dmaproc; +#ifdef CONFIG_IDEDMA_AUTO + if (!noautodma) + hwif->autodma = (pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0; +#endif /* CONFIG_IDEDMA_AUTO */ #endif /* CONFIG_BLK_DEV_IDEDMA */ } + +extern void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d); + +void __init fixup_device_hpt343 (struct pci_dev *dev, ide_pci_device_t *d) +{ + char *chipset_names[] = {"HPT343", "HPT345"}; + unsigned short pcicmd = 0; + + pci_read_config_word(dev, PCI_COMMAND, &pcicmd); + + strcpy(d->name, chipset_names[(pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0]); + d->bootable = (pcicmd & PCI_COMMAND_MEMORY) ? OFF_BOARD : NEVER_BOARD; + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d->name, dev->bus->number, dev->devfn); + ide_setup_pci_device(dev, d); +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/hpt366.c linux.19rc3-ac4/drivers/ide/hpt366.c --- linux.19rc3/drivers/ide/hpt366.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/hpt366.c 2002-07-29 13:58:39.000000000 +0100 @@ -1,9 +1,8 @@ /* - * linux/drivers/ide/hpt366.c Version 0.22 20 Sep 2001 + * linux/drivers/ide/hpt366.c Version 0.33 April 17, 2002 * - * Copyright (C) 1999-2000 Andre Hedrick + * Copyright (C) 1999-2002 Andre Hedrick * Portions Copyright (C) 2001 Sun Microsystems, Inc. - * May be copied or modified under the terms of the GNU General Public License * * Thanks to HighPoint Technologies for their assistance, and hardware. * Special Thanks to Jon Burchmore in SanDiego for the deep pockets, his @@ -42,6 +41,7 @@ * Mike Waychison */ + #include #include #include @@ -67,16 +67,14 @@ /* various tuning parameters */ #define HPT_RESET_STATE_ENGINE -/*#define HPT_DELAY_INTERRUPT*/ -/*#define HPT_SERIALIZE_IO*/ +#undef HPT_DELAY_INTERRUPT +#undef HPT_SERIALIZE_IO #if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) #include #include #endif /* defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) */ -extern char *ide_dmafunc_verbose(ide_dma_action_t dmafunc); - const char *quirk_drives[] = { "QUANTUM FIREBALLlct08 08", "QUANTUM FIREBALLP KA6.4", @@ -166,9 +164,8 @@ * PIO. * 31 FIFO enable. */ -struct chipset_bus_clock_list_entry forty_base [] = { - - { XFER_UDMA_4, 0x900fd943 }, +struct chipset_bus_clock_list_entry forty_base_hpt366[] = { + { XFER_UDMA_4, 0x900fd943 }, { XFER_UDMA_3, 0x900ad943 }, { XFER_UDMA_2, 0x900bd943 }, { XFER_UDMA_1, 0x9008d943 }, @@ -186,8 +183,7 @@ { 0, 0x0120d9d9 } }; -struct chipset_bus_clock_list_entry thirty_three_base [] = { - +struct chipset_bus_clock_list_entry thirty_three_base_hpt366[] = { { XFER_UDMA_4, 0x90c9a731 }, { XFER_UDMA_3, 0x90cfa731 }, { XFER_UDMA_2, 0x90caa731 }, @@ -206,7 +202,7 @@ { 0, 0x0120a7a7 } }; -struct chipset_bus_clock_list_entry twenty_five_base [] = { +struct chipset_bus_clock_list_entry twenty_five_base_hpt366[] = { { XFER_UDMA_4, 0x90c98521 }, { XFER_UDMA_3, 0x90cf8521 }, @@ -226,51 +222,9 @@ { 0, 0x01208585 } }; -#if 1 -/* these are the current (4 sep 2001) timings from highpoint */ -struct chipset_bus_clock_list_entry thirty_three_base_hpt370[] = { - { XFER_UDMA_5, 0x12446231 }, - { XFER_UDMA_4, 0x12446231 }, - { XFER_UDMA_3, 0x126c6231 }, - { XFER_UDMA_2, 0x12486231 }, - { XFER_UDMA_1, 0x124c6233 }, - { XFER_UDMA_0, 0x12506297 }, - - { XFER_MW_DMA_2, 0x22406c31 }, - { XFER_MW_DMA_1, 0x22406c33 }, - { XFER_MW_DMA_0, 0x22406c97 }, - - { XFER_PIO_4, 0x06414e31 }, - { XFER_PIO_3, 0x06414e42 }, - { XFER_PIO_2, 0x06414e53 }, - { XFER_PIO_1, 0x06814e93 }, - { XFER_PIO_0, 0x06814ea7 }, - { 0, 0x06814ea7 } -}; - -/* 2x 33MHz timings */ -struct chipset_bus_clock_list_entry sixty_six_base_hpt370[] = { - { XFER_UDMA_5, 0x1488e673 }, - { XFER_UDMA_4, 0x1488e673 }, - { XFER_UDMA_3, 0x1498e673 }, - { XFER_UDMA_2, 0x1490e673 }, - { XFER_UDMA_1, 0x1498e677 }, - { XFER_UDMA_0, 0x14a0e73f }, - - { XFER_MW_DMA_2, 0x2480fa73 }, - { XFER_MW_DMA_1, 0x2480fa77 }, - { XFER_MW_DMA_0, 0x2480fb3f }, - - { XFER_PIO_4, 0x0c82be73 }, - { XFER_PIO_3, 0x0c82be95 }, - { XFER_PIO_2, 0x0c82beb7 }, - { XFER_PIO_1, 0x0d02bf37 }, - { XFER_PIO_0, 0x0d02bf5f }, - { 0, 0x0d02bf5f } -}; -#else /* from highpoint documentation. these are old values */ struct chipset_bus_clock_list_entry thirty_three_base_hpt370[] = { +/* { XFER_UDMA_5, 0x1A85F442, 0x16454e31 }, */ { XFER_UDMA_5, 0x16454e31 }, { XFER_UDMA_4, 0x16454e31 }, { XFER_UDMA_3, 0x166d4e31 }, @@ -309,9 +263,50 @@ { XFER_PIO_0, 0x06914e57 }, { 0, 0x06514e57 } }; -#endif -struct chipset_bus_clock_list_entry fifty_base_hpt370[] = { +/* these are the current (4 sep 2001) timings from highpoint */ +struct chipset_bus_clock_list_entry thirty_three_base_hpt370a[] = { + { XFER_UDMA_5, 0x12446231 }, + { XFER_UDMA_4, 0x12446231 }, + { XFER_UDMA_3, 0x126c6231 }, + { XFER_UDMA_2, 0x12486231 }, + { XFER_UDMA_1, 0x124c6233 }, + { XFER_UDMA_0, 0x12506297 }, + + { XFER_MW_DMA_2, 0x22406c31 }, + { XFER_MW_DMA_1, 0x22406c33 }, + { XFER_MW_DMA_0, 0x22406c97 }, + + { XFER_PIO_4, 0x06414e31 }, + { XFER_PIO_3, 0x06414e42 }, + { XFER_PIO_2, 0x06414e53 }, + { XFER_PIO_1, 0x06814e93 }, + { XFER_PIO_0, 0x06814ea7 }, + { 0, 0x06814ea7 } +}; + +/* 2x 33MHz timings */ +struct chipset_bus_clock_list_entry sixty_six_base_hpt370a[] = { + { XFER_UDMA_5, 0x1488e673 }, + { XFER_UDMA_4, 0x1488e673 }, + { XFER_UDMA_3, 0x1498e673 }, + { XFER_UDMA_2, 0x1490e673 }, + { XFER_UDMA_1, 0x1498e677 }, + { XFER_UDMA_0, 0x14a0e73f }, + + { XFER_MW_DMA_2, 0x2480fa73 }, + { XFER_MW_DMA_1, 0x2480fa77 }, + { XFER_MW_DMA_0, 0x2480fb3f }, + + { XFER_PIO_4, 0x0c82be73 }, + { XFER_PIO_3, 0x0c82be95 }, + { XFER_PIO_2, 0x0c82beb7 }, + { XFER_PIO_1, 0x0d02bf37 }, + { XFER_PIO_0, 0x0d02bf5f }, + { 0, 0x0d02bf5f } +}; + +struct chipset_bus_clock_list_entry fifty_base_hpt370a[] = { { XFER_UDMA_5, 0x12848242 }, { XFER_UDMA_4, 0x12ac8242 }, { XFER_UDMA_3, 0x128c8242 }, @@ -331,7 +326,149 @@ { 0, 0x0ac1f48a } }; +struct chipset_bus_clock_list_entry thirty_three_base_hpt372[] = { + { XFER_UDMA_6, 0x1c81dc62 }, + { XFER_UDMA_5, 0x1c6ddc62 }, + { XFER_UDMA_4, 0x1c8ddc62 }, + { XFER_UDMA_3, 0x1c8edc62 }, /* checkme */ + { XFER_UDMA_2, 0x1c91dc62 }, + { XFER_UDMA_1, 0x1c9adc62 }, /* checkme */ + { XFER_UDMA_0, 0x1c82dc62 }, /* checkme */ + + { XFER_MW_DMA_2, 0x2c829262 }, + { XFER_MW_DMA_1, 0x2c829266 }, /* checkme */ + { XFER_MW_DMA_0, 0x2c82922e }, /* checkme */ + + { XFER_PIO_4, 0x0c829c62 }, + { XFER_PIO_3, 0x0c829c84 }, + { XFER_PIO_2, 0x0c829ca6 }, + { XFER_PIO_1, 0x0d029d26 }, + { XFER_PIO_0, 0x0d029d5e }, + { 0, 0x0d029d5e } +}; + +struct chipset_bus_clock_list_entry fifty_base_hpt372[] = { + { XFER_UDMA_5, 0x12848242 }, + { XFER_UDMA_4, 0x12ac8242 }, + { XFER_UDMA_3, 0x128c8242 }, + { XFER_UDMA_2, 0x120c8242 }, + { XFER_UDMA_1, 0x12148254 }, + { XFER_UDMA_0, 0x121882ea }, + + { XFER_MW_DMA_2, 0x22808242 }, + { XFER_MW_DMA_1, 0x22808254 }, + { XFER_MW_DMA_0, 0x228082ea }, + + { XFER_PIO_4, 0x0a81f442 }, + { XFER_PIO_3, 0x0a81f443 }, + { XFER_PIO_2, 0x0a81f454 }, + { XFER_PIO_1, 0x0ac1f465 }, + { XFER_PIO_0, 0x0ac1f48a }, + { 0, 0x0a81f443 } +}; + +struct chipset_bus_clock_list_entry sixty_six_base_hpt372[] = { + { XFER_UDMA_6, 0x1c869c62 }, + { XFER_UDMA_5, 0x1cae9c62 }, + { XFER_UDMA_4, 0x1c8a9c62 }, + { XFER_UDMA_3, 0x1c8e9c62 }, + { XFER_UDMA_2, 0x1c929c62 }, + { XFER_UDMA_1, 0x1c9a9c62 }, + { XFER_UDMA_0, 0x1c829c62 }, + + { XFER_MW_DMA_2, 0x2c829c62 }, + { XFER_MW_DMA_1, 0x2c829c66 }, + { XFER_MW_DMA_0, 0x2c829d2e }, + + { XFER_PIO_4, 0x0c829c62 }, + { XFER_PIO_3, 0x0c829c84 }, + { XFER_PIO_2, 0x0c829ca6 }, + { XFER_PIO_1, 0x0d029d26 }, + { XFER_PIO_0, 0x0d029d5e }, + { 0, 0x0d029d26 } +}; + +struct chipset_bus_clock_list_entry thirty_three_base_hpt374[] = { + { XFER_UDMA_6, 0x12808242 }, + { XFER_UDMA_5, 0x12848242 }, + { XFER_UDMA_4, 0x12ac8242 }, + { XFER_UDMA_3, 0x128c8242 }, + { XFER_UDMA_2, 0x120c8242 }, + { XFER_UDMA_1, 0x12148254 }, + { XFER_UDMA_0, 0x121882ea }, + + { XFER_MW_DMA_2, 0x22808242 }, + { XFER_MW_DMA_1, 0x22808254 }, + { XFER_MW_DMA_0, 0x228082ea }, + + { XFER_PIO_4, 0x0a81f442 }, + { XFER_PIO_3, 0x0a81f443 }, + { XFER_PIO_2, 0x0a81f454 }, + { XFER_PIO_1, 0x0ac1f465 }, + { XFER_PIO_0, 0x0ac1f48a }, + { 0, 0x06814e93 } +}; + +#if 0 +struct chipset_bus_clock_list_entry fifty_base_hpt374[] = { + { XFER_UDMA_6, }, + { XFER_UDMA_5, }, + { XFER_UDMA_4, }, + { XFER_UDMA_3, }, + { XFER_UDMA_2, }, + { XFER_UDMA_1, }, + { XFER_UDMA_0, }, + { XFER_MW_DMA_2, }, + { XFER_MW_DMA_1, }, + { XFER_MW_DMA_0, }, + { XFER_PIO_4, }, + { XFER_PIO_3, }, + { XFER_PIO_2, }, + { XFER_PIO_1, }, + { XFER_PIO_0, }, + { 0, } +}; +#endif +#if 0 +struct chipset_bus_clock_list_entry sixty_six_base_hpt374[] = { + { XFER_UDMA_6, 0x12406231 }, /* checkme */ + { XFER_UDMA_5, 0x12446231 }, + 0x14846231 + { XFER_UDMA_4, 0x16814ea7 }, + 0x14886231 + { XFER_UDMA_3, 0x16814ea7 }, + 0x148c6231 + { XFER_UDMA_2, 0x16814ea7 }, + 0x148c6231 + { XFER_UDMA_1, 0x16814ea7 }, + 0x14906231 + { XFER_UDMA_0, 0x16814ea7 }, + 0x14986231 + { XFER_MW_DMA_2, 0x16814ea7 }, + 0x26514e21 + { XFER_MW_DMA_1, 0x16814ea7 }, + 0x26514e97 + { XFER_MW_DMA_0, 0x16814ea7 }, + 0x26514e97 + { XFER_PIO_4, 0x06814ea7 }, + 0x06514e21 + { XFER_PIO_3, 0x06814ea7 }, + 0x06514e22 + { XFER_PIO_2, 0x06814ea7 }, + 0x06514e33 + { XFER_PIO_1, 0x06814ea7 }, + 0x06914e43 + { XFER_PIO_0, 0x06814ea7 }, + 0x06914e57 + { 0, 0x06814ea7 } +}; +#endif + #define HPT366_DEBUG_DRIVE_INFO 0 +#define HPT374_ALLOW_ATA133_6 0 +#define HPT371_ALLOW_ATA133_6 0 +#define HPT302_ALLOW_ATA133_6 0 +#define HPT372_ALLOW_ATA133_6 1 #define HPT370_ALLOW_ATA100_5 1 #define HPT366_ALLOW_ATA66_4 1 #define HPT366_ALLOW_ATA66_3 1 @@ -345,35 +482,33 @@ static struct pci_dev *hpt_devs[HPT366_MAX_DEVS]; static int n_hpt_devs; -static unsigned int pci_rev_check_hpt3xx(struct pci_dev *dev); -static unsigned int pci_rev2_check_hpt3xx(struct pci_dev *dev); +static unsigned int hpt_revision(struct pci_dev *dev); +static unsigned int hpt_minimum_revision(struct pci_dev *dev, int revision); + byte hpt366_proc = 0; byte hpt363_shared_irq; byte hpt363_shared_pin; -extern char *ide_xfer_verbose (byte xfer_rate); #if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) static int hpt366_get_info(char *, char **, off_t, int); extern int (*hpt366_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); static int hpt366_get_info (char *buffer, char **addr, off_t offset, int count) { char *p = buffer; - char *chipset_nums[] = {"366", "366", "368", "370", "370A"}; + char *chipset_nums[] = {"366", "366", "368", + "370", "370A", "372", + "302", "371", "374" }; int i; p += sprintf(p, "\n " - "HighPoint HPT366/368/370\n"); + "HighPoint HPT366/368/370/372/374\n"); for (i = 0; i < n_hpt_devs; i++) { struct pci_dev *dev = hpt_devs[i]; unsigned long iobase = dev->resource[4].start; - u32 class_rev; + u32 class_rev = hpt_revision(dev); u8 c0, c1; - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xff; - p += sprintf(p, "\nController: %d\n", i); p += sprintf(p, "Chipset: HPT%s\n", chipset_nums[class_rev]); p += sprintf(p, "--------------- Primary Channel " @@ -388,7 +523,7 @@ (c0 & 0x80) ? "no" : "yes", (c1 & 0x80) ? "no" : "yes"); - if (pci_rev_check_hpt3xx(dev)) { + if (hpt_minimum_revision(dev, 3)) { u8 cbl; cbl = inb_p(iobase + 0x7b); outb_p(cbl | 1, iobase + 0x7b); @@ -437,20 +572,121 @@ } #endif /* defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) */ -static unsigned int pci_rev_check_hpt3xx (struct pci_dev *dev) +static unsigned int hpt_revision (struct pci_dev *dev) { unsigned int class_rev; pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); class_rev &= 0xff; - return ((int) (class_rev > 0x02) ? 1 : 0); + + switch(dev->device) { + case PCI_DEVICE_ID_TTI_HPT374: + class_rev = PCI_DEVICE_ID_TTI_HPT374; break; + case PCI_DEVICE_ID_TTI_HPT371: + class_rev = PCI_DEVICE_ID_TTI_HPT371; break; + case PCI_DEVICE_ID_TTI_HPT302: + class_rev = PCI_DEVICE_ID_TTI_HPT302; break; + case PCI_DEVICE_ID_TTI_HPT372: + class_rev = PCI_DEVICE_ID_TTI_HPT372; break; + default: + break; + } + return class_rev; } -static unsigned int pci_rev2_check_hpt3xx (struct pci_dev *dev) +static unsigned int hpt_minimum_revision (struct pci_dev *dev, int revision) { - unsigned int class_rev; - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xff; - return ((int) (class_rev > 0x01) ? 1 : 0); + unsigned int class_rev = hpt_revision(dev); + revision--; + return ((int) (class_rev > revision) ? 1 : 0); +} + +static int check_in_drive_lists(ide_drive_t *drive, const char **list); + +static byte hpt3xx_ratemask (ide_drive_t *drive) +{ + struct pci_dev *dev = HWIF(drive)->pci_dev; + byte mode = 0x00; + + if (hpt_minimum_revision(dev, 8)) { /* HPT374 */ + mode |= (HPT374_ALLOW_ATA133_6) ? 0x04 : 0x03; + } else if (hpt_minimum_revision(dev, 7)) { /* HPT371 */ + mode |= (HPT371_ALLOW_ATA133_6) ? 0x04 : 0x03; + } else if (hpt_minimum_revision(dev, 6)) { /* HPT302 */ + mode |= (HPT302_ALLOW_ATA133_6) ? 0x04 : 0x03; + } else if (hpt_minimum_revision(dev, 5)) { /* HPT372 */ + mode |= (HPT372_ALLOW_ATA133_6) ? 0x04 : 0x03; + } else if (hpt_minimum_revision(dev, 4)) { /* HPT370A */ + mode |= (HPT370_ALLOW_ATA100_5) ? 0x03 : 0x02; + } else if (hpt_minimum_revision(dev, 3)) { /* HPT370 */ + mode |= (HPT370_ALLOW_ATA100_5) ? 0x03 : 0x02; + if (check_in_drive_lists(drive, bad_ata33)) + return (mode &= ~0xFF); + } else { /* HPT366 and HPT368 */ + mode |= 0x02; + if (check_in_drive_lists(drive, bad_ata33)) + return (mode &= ~0xFF); + } + + if (!eighty_ninty_three(drive)) { + mode &= ~0xFE; + mode |= 0x01; + } + return (mode &= ~0xF8); +} + +static byte hpt3xx_ratefilter (ide_drive_t *drive, byte speed) +{ +#ifdef CONFIG_BLK_DEV_IDEDMA + struct pci_dev *dev = HWIF(drive)->pci_dev; + byte mode = hpt3xx_ratemask(drive); + + if (drive->media != ide_disk) + while (speed > XFER_PIO_4) speed--; + + switch(mode) { + case 0x04: + while (speed > XFER_UDMA_6) speed--; + break; + case 0x03: + while (speed > XFER_UDMA_5) speed--; + if (hpt_minimum_revision(dev, 5)) + break; + if (check_in_drive_lists(drive, bad_ata100_5)) + while (speed > XFER_UDMA_4) speed--; + break; + case 0x02: + while (speed > XFER_UDMA_4) speed--; + /* + * CHECK ME, Does this need to be set to 5 ?? + */ + if (hpt_minimum_revision(dev, 3)) + break; + if ((check_in_drive_lists(drive, bad_ata66_4)) || + (!(HPT366_ALLOW_ATA66_4))) + while (speed > XFER_UDMA_3) speed--; + if ((check_in_drive_lists(drive, bad_ata66_3)) || + (!(HPT366_ALLOW_ATA66_3))) + while (speed > XFER_UDMA_2) speed--; + break; + case 0x01: + while (speed > XFER_UDMA_2) speed--; + /* + * CHECK ME, Does this need to be set to 5 ?? + */ + if (hpt_minimum_revision(dev, 3)) + break; + if (check_in_drive_lists(drive, bad_ata33)) + while (speed > XFER_MW_DMA_2) speed--; + break; + case 0x00: + default: while (speed > XFER_MW_DMA_2) speed--; break; + break; + } +#else + while (speed > XFER_PIO_4) speed--; +#endif /* CONFIG_BLK_DEV_IDEDMA */ +// printk("%s: mode == %02x speed == %02x\n", drive->name, mode, speed); + return speed; } static int check_in_drive_lists (ide_drive_t *drive, const char **list) @@ -482,48 +718,35 @@ return chipset_table->chipset_settings; } -static void hpt366_tune_chipset (ide_drive_t *drive, byte speed) +static void hpt366_tune_chipset (ide_drive_t *drive, byte xferspeed) { + struct pci_dev *dev = HWIF(drive)->pci_dev; + byte speed = hpt3xx_ratefilter(drive, xferspeed); byte regtime = (drive->select.b.unit & 0x01) ? 0x44 : 0x40; byte regfast = (HWIF(drive)->channel) ? 0x55 : 0x51; - /* - * since the channel is always 0 it does not matter. - */ - + byte drive_fast = 0; unsigned int reg1 = 0; unsigned int reg2 = 0; - byte drive_fast = 0; /* - * Disable the "fast interrupt" prediction. + * Disable the "fast interrupt" prediction. */ - pci_read_config_byte(HWIF(drive)->pci_dev, regfast, &drive_fast); - if (drive_fast & 0x02) - pci_write_config_byte(HWIF(drive)->pci_dev, regfast, drive_fast & ~0x20); - - pci_read_config_dword(HWIF(drive)->pci_dev, regtime, ®1); - /* detect bus speed by looking at control reg timing: */ - switch((reg1 >> 8) & 7) { - case 5: - reg2 = pci_bus_clock_list(speed, forty_base); - break; - case 9: - reg2 = pci_bus_clock_list(speed, twenty_five_base); - break; - default: - case 7: - reg2 = pci_bus_clock_list(speed, thirty_three_base); - break; - } + pci_read_config_byte(dev, regfast, &drive_fast); #if 0 - /* this is a nice idea ... */ - list_conf = pci_bus_clock_list(speed, - (struct chipset_bus_clock_list_entry *) - dev->sysdata); + if (drive_fast & 0x02) + pci_write_config_byte(dev, regfast, drive_fast & ~0x20); +#else + if (drive_fast & 0x80) + pci_write_config_byte(dev, regfast, drive_fast & ~0x80); #endif + + reg2 = pci_bus_clock_list(speed, + (struct chipset_bus_clock_list_entry *) dev->driver_data); /* - * Disable on-chip PIO FIFO/buffer (to avoid problems handling I/O errors later) + * Disable on-chip PIO FIFO/buffer + * (to avoid problems handling I/O errors later) */ + pci_read_config_dword(dev, regtime, ®1); if (speed >= XFER_MW_DMA_0) { reg2 = (reg2 & ~0xc0000000) | (reg1 & 0xc0000000); } else { @@ -531,11 +754,17 @@ } reg2 &= ~0x80000000; - pci_write_config_dword(HWIF(drive)->pci_dev, regtime, reg2); + pci_write_config_dword(dev, regtime, reg2); } -static void hpt370_tune_chipset (ide_drive_t *drive, byte speed) +static void hpt368_tune_chipset (ide_drive_t *drive, byte speed) { + hpt366_tune_chipset(drive, speed); +} + +static void hpt370_tune_chipset (ide_drive_t *drive, byte xferspeed) +{ + byte speed = hpt3xx_ratefilter(drive, xferspeed); byte regfast = (HWIF(drive)->channel) ? 0x55 : 0x51; unsigned int list_conf = 0; unsigned int drive_conf = 0; @@ -561,11 +790,11 @@ new_fast |= 0x01; #endif if (new_fast != drive_fast) - pci_write_config_byte(HWIF(drive)->pci_dev, regfast, new_fast); + pci_write_config_byte(dev, regfast, new_fast); list_conf = pci_bus_clock_list(speed, (struct chipset_bus_clock_list_entry *) - dev->sysdata); + dev->driver_data); pci_read_config_dword(dev, drive_pci, &drive_conf); list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask); @@ -577,70 +806,75 @@ pci_write_config_dword(dev, drive_pci, list_conf); } -static int hpt3xx_tune_chipset (ide_drive_t *drive, byte speed) +static void hpt372_tune_chipset (ide_drive_t *drive, byte xferspeed) { - if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0)) - return -1; + byte speed = hpt3xx_ratefilter(drive, xferspeed); + byte regfast = (HWIF(drive)->channel) ? 0x55 : 0x51; + unsigned int list_conf = 0; + unsigned int drive_conf = 0; + unsigned int conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000; + byte drive_pci = 0x40 + (drive->dn * 4); + byte drive_fast = 0; + struct pci_dev *dev = HWIF(drive)->pci_dev; - if (!drive->init_speed) - drive->init_speed = speed; + /* + * Disable the "fast interrupt" prediction. + * don't holdoff on interrupts. (== 0x01 despite what the docs say) + */ + pci_read_config_byte(dev, regfast, &drive_fast); + drive_fast &= ~0x07; + pci_write_config_byte(dev, regfast, drive_fast); + + list_conf = pci_bus_clock_list(speed, + (struct chipset_bus_clock_list_entry *) + dev->driver_data); + pci_read_config_dword(dev, drive_pci, &drive_conf); + list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask); + if (speed < XFER_MW_DMA_0) + list_conf &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */ + pci_write_config_dword(dev, drive_pci, list_conf); +} - if (pci_rev_check_hpt3xx(HWIF(drive)->pci_dev)) { - hpt370_tune_chipset(drive, speed); - } else { - hpt366_tune_chipset(drive, speed); - } - drive->current_speed = speed; - return ((int) ide_config_drive_speed(drive, speed)); +static void hpt374_tune_chipset (ide_drive_t *drive, byte speed) +{ + hpt372_tune_chipset(drive, speed); } -static void config_chipset_for_pio (ide_drive_t *drive) +static int hpt3xx_tune_chipset (ide_drive_t *drive, byte speed) { - unsigned short eide_pio_timing[6] = {960, 480, 240, 180, 120, 90}; - unsigned short xfer_pio = drive->id->eide_pio_modes; - byte timing, speed, pio; - - pio = ide_get_best_pio_mode(drive, 255, 5, NULL); - - if (xfer_pio> 4) - xfer_pio = 0; - - if (drive->id->eide_pio_iordy > 0) { - for (xfer_pio = 5; - xfer_pio>0 && - drive->id->eide_pio_iordy>eide_pio_timing[xfer_pio]; - xfer_pio--); - } else { - xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 : - (drive->id->eide_pio_modes & 2) ? 0x04 : - (drive->id->eide_pio_modes & 1) ? 0x03 : - (drive->id->tPIO & 2) ? 0x02 : - (drive->id->tPIO & 1) ? 0x01 : xfer_pio; - } + struct pci_dev *dev = HWIF(drive)->pci_dev; - timing = (xfer_pio >= pio) ? xfer_pio : pio; - - switch(timing) { - case 4: speed = XFER_PIO_4;break; - case 3: speed = XFER_PIO_3;break; - case 2: speed = XFER_PIO_2;break; - case 1: speed = XFER_PIO_1;break; - default: - speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW; - break; - } - (void) hpt3xx_tune_chipset(drive, speed); + if (hpt_minimum_revision(dev, 8)) + hpt374_tune_chipset(drive, speed); +#if 0 + else if (hpt_minimum_revision(dev, 7)) + hpt371_tune_chipset(drive, speed); + else if (hpt_minimum_revision(dev, 6)) + hpt302_tune_chipset(drive, speed); +#endif + else if (hpt_minimum_revision(dev, 5)) + hpt372_tune_chipset(drive, speed); + else if (hpt_minimum_revision(dev, 3)) + hpt370_tune_chipset(drive, speed); + else if (hpt_minimum_revision(dev, 2)) + hpt368_tune_chipset(drive, speed); + else + hpt366_tune_chipset(drive, speed); + + return ((int) ide_config_drive_speed(drive, speed)); } static void hpt3xx_tune_drive (ide_drive_t *drive, byte pio) { byte speed; + + pio = ide_get_best_pio_mode(drive, pio, 5, NULL); switch(pio) { - case 4: speed = XFER_PIO_4;break; - case 3: speed = XFER_PIO_3;break; - case 2: speed = XFER_PIO_2;break; - case 1: speed = XFER_PIO_1;break; - default: speed = XFER_PIO_0;break; + case 4: speed = XFER_PIO_4; break; + case 3: speed = XFER_PIO_3; break; + case 2: speed = XFER_PIO_2; break; + case 1: speed = XFER_PIO_1; break; + default: speed = XFER_PIO_0; break; } (void) hpt3xx_tune_chipset(drive, speed); } @@ -660,54 +894,49 @@ static int config_chipset_for_dma (ide_drive_t *drive) { struct hd_driveid *id = drive->id; + byte mode = hpt3xx_ratemask(drive); byte speed = 0x00; - byte ultra66 = eighty_ninty_three(drive); - int rval; - if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0)) - return ((int) ide_dma_off_quietly); + if (drive->media != ide_disk) + mode |= 0x08; - if ((id->dma_ultra & 0x0020) && - (!check_in_drive_lists(drive, bad_ata100_5)) && - (HPT370_ALLOW_ATA100_5) && - (pci_rev_check_hpt3xx(HWIF(drive)->pci_dev)) && - (ultra66)) { - speed = XFER_UDMA_5; - } else if ((id->dma_ultra & 0x0010) && - (!check_in_drive_lists(drive, bad_ata66_4)) && - (HPT366_ALLOW_ATA66_4) && - (ultra66)) { - speed = XFER_UDMA_4; - } else if ((id->dma_ultra & 0x0008) && - (!check_in_drive_lists(drive, bad_ata66_3)) && - (HPT366_ALLOW_ATA66_3) && - (ultra66)) { - speed = XFER_UDMA_3; - } else if (id->dma_ultra && (!check_in_drive_lists(drive, bad_ata33))) { - if (id->dma_ultra & 0x0004) { - speed = XFER_UDMA_2; - } else if (id->dma_ultra & 0x0002) { - speed = XFER_UDMA_1; - } else if (id->dma_ultra & 0x0001) { - speed = XFER_UDMA_0; - } - } else if (id->dma_mword & 0x0004) { - speed = XFER_MW_DMA_2; - } else if (id->dma_mword & 0x0002) { - speed = XFER_MW_DMA_1; - } else if (id->dma_mword & 0x0001) { - speed = XFER_MW_DMA_0; - } else { - return ((int) ide_dma_off_quietly); + switch(mode) { + case 0x04: + if (id->dma_ultra & 0x0040) + { speed = XFER_UDMA_6; break; } + case 0x03: + if (id->dma_ultra & 0x0020) + { speed = XFER_UDMA_5; break; } + case 0x02: + if (id->dma_ultra & 0x0010) + { speed = XFER_UDMA_4; break; } + if (id->dma_ultra & 0x0008) + { speed = XFER_UDMA_3; break; } + case 0x01: + if (id->dma_ultra & 0x0004) + { speed = XFER_UDMA_2; break; } + if (id->dma_ultra & 0x0002) + { speed = XFER_UDMA_1; break; } + if (id->dma_ultra & 0x0001) + { speed = XFER_UDMA_0; break; } + case 0x00: + if (id->dma_mword & 0x0004) + { speed = XFER_MW_DMA_2; break; } + if (id->dma_mword & 0x0002) + { speed = XFER_MW_DMA_1; break; } + if (id->dma_mword & 0x0001) + { speed = XFER_MW_DMA_0; break; } + default: + return ((int) ide_dma_off_quietly); } (void) hpt3xx_tune_chipset(drive, speed); - rval = (int)( ((id->dma_ultra >> 11) & 7) ? ide_dma_on : + return ((int) ((id->dma_ultra >> 14) & 3) ? ide_dma_on : + ((id->dma_ultra >> 11) & 7) ? ide_dma_on : ((id->dma_ultra >> 8) & 7) ? ide_dma_on : ((id->dma_mword >> 8) & 7) ? ide_dma_on : ide_dma_off_quietly); - return rval; } int hpt3xx_quirkproc (ide_drive_t *drive) @@ -717,21 +946,22 @@ void hpt3xx_intrproc (ide_drive_t *drive) { - if (drive->quirk_list) { - /* drives in the quirk_list may not like intr setups/cleanups */ - } else { - OUT_BYTE((drive)->ctl|2, HWIF(drive)->io_ports[IDE_CONTROL_OFFSET]); - } + if (drive->quirk_list) + return; + /* drives in the quirk_list may not like intr setups/cleanups */ + OUT_BYTE((drive)->ctl|2, HWIF(drive)->io_ports[IDE_CONTROL_OFFSET]); } void hpt3xx_maskproc (ide_drive_t *drive, int mask) { + struct pci_dev *dev = HWIF(drive)->pci_dev; + if (drive->quirk_list) { - if (pci_rev_check_hpt3xx(HWIF(drive)->pci_dev)) { + if (hpt_minimum_revision(dev,3)) { byte reg5a = 0; - pci_read_config_byte(HWIF(drive)->pci_dev, 0x5a, ®5a); + pci_read_config_byte(dev, 0x5a, ®5a); if (((reg5a & 0x10) >> 4) != mask) - pci_write_config_byte(HWIF(drive)->pci_dev, 0x5a, mask ? (reg5a | 0x10) : (reg5a & ~0x10)); + pci_write_config_byte(dev, 0x5a, mask ? (reg5a | 0x10) : (reg5a & ~0x10)); } else { if (mask) { disable_irq(HWIF(drive)->irq); @@ -750,6 +980,8 @@ struct hd_driveid *id = drive->id; ide_dma_action_t dma_func = ide_dma_on; + drive->init_speed = 0; + if (id && (id->capability & 1) && HWIF(drive)->autodma) { /* Consult the list of known "bad" drives */ if (ide_dmaproc(ide_dma_bad_drive, drive)) { @@ -758,7 +990,7 @@ } dma_func = ide_dma_off_quietly; if (id->field_valid & 4) { - if (id->dma_ultra & 0x002F) { + if (id->dma_ultra & 0x007F) { /* Force if Capable UltraDMA */ dma_func = config_chipset_for_dma(drive); if ((id->field_valid & 2) && @@ -789,7 +1021,7 @@ dma_func = ide_dma_off_quietly; no_dma_set: - config_chipset_for_pio(drive); + hpt3xx_tune_drive(drive, 5); } return HWIF(drive)->dmaproc(dma_func, drive); } @@ -802,60 +1034,71 @@ */ int hpt366_dmaproc (ide_dma_action_t func, ide_drive_t *drive) { + struct pci_dev *dev = HWIF(drive)->pci_dev; + unsigned long dma_base = HWIF(drive)->dma_base; byte reg50h = 0, reg52h = 0, reg5ah = 0, dma_stat = 0; - unsigned long dma_base = HWIF(drive)->dma_base; switch (func) { case ide_dma_check: return config_drive_xfer_rate(drive); - case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */ - dma_stat = inb(dma_base+2); - return (dma_stat & 4) == 4; /* return 1 if INTR asserted */ + case ide_dma_test_irq: + /* returns 1 if dma irq issued, 0 otherwise */ + dma_stat = IN_BYTE(dma_base+2); + /* return 1 if INTR asserted */ + return (dma_stat & 4) == 4; case ide_dma_lostirq: - pci_read_config_byte(HWIF(drive)->pci_dev, 0x50, ®50h); - pci_read_config_byte(HWIF(drive)->pci_dev, 0x52, ®52h); - pci_read_config_byte(HWIF(drive)->pci_dev, 0x5a, ®5ah); - printk("%s: (%s) reg50h=0x%02x, reg52h=0x%02x, reg5ah=0x%02x\n", + pci_read_config_byte(dev, 0x50, ®50h); + pci_read_config_byte(dev, 0x52, ®52h); + pci_read_config_byte(dev, 0x5a, ®5ah); + printk("%s: (%s) reg50h=0x%02x, reg52h=0x%02x," + " reg5ah=0x%02x\n", drive->name, ide_dmafunc_verbose(func), reg50h, reg52h, reg5ah); if (reg5ah & 0x10) - pci_write_config_byte(HWIF(drive)->pci_dev, 0x5a, reg5ah & ~0x10); - /* fall through to a reset */ + pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10); #if 0 + /* how about we flush and reset, mmmkay? */ + pci_write_config_byte(dev, 0x51, 0x1F); + /* fall through to a reset */ case ide_dma_begin: case ide_dma_end: /* reset the chips state over and over.. */ - pci_write_config_byte(HWIF(drive)->pci_dev, 0x51, 0x13); + pci_write_config_byte(dev, 0x51, 0x13); #endif break; case ide_dma_timeout: default: break; } - return ide_dmaproc(func, drive); /* use standard DMA stuff */ + /* use standard DMA stuff */ + return ide_dmaproc(func, drive); } int hpt370_dmaproc (ide_dma_action_t func, ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); - unsigned long dma_base = hwif->dma_base; - byte regstate = hwif->channel ? 0x54 : 0x50; - byte reginfo = hwif->channel ? 0x56 : 0x52; + struct pci_dev *dev = HWIF(drive)->pci_dev; + ide_hwif_t *hwif = HWIF(drive); + unsigned long dma_base = hwif->dma_base; + byte regstate = hwif->channel ? 0x54 : 0x50; + byte reginfo = hwif->channel ? 0x56 : 0x52; byte dma_stat; switch (func) { case ide_dma_check: return config_drive_xfer_rate(drive); - case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */ - dma_stat = inb(dma_base+2); - return (dma_stat & 4) == 4; /* return 1 if INTR asserted */ + case ide_dma_test_irq: + /* returns 1 if dma irq issued, 0 otherwise */ + dma_stat = IN_BYTE(dma_base+2); + /* return 1 if INTR asserted */ + return (dma_stat & 4) == 4; case ide_dma_end: - dma_stat = inb(dma_base + 2); + dma_stat = IN_BYTE(dma_base + 2); if (dma_stat & 0x01) { - udelay(20); /* wait a little */ - dma_stat = inb(dma_base + 2); + /* wait a little */ + udelay(20); + dma_stat = IN_BYTE(dma_base + 2); } if ((dma_stat & 0x01) == 0) break; @@ -865,29 +1108,70 @@ case ide_dma_timeout: case ide_dma_lostirq: - pci_read_config_byte(hwif->pci_dev, reginfo, - &dma_stat); + pci_read_config_byte(dev, reginfo, &dma_stat); printk("%s: %d bytes in FIFO\n", drive->name, dma_stat); - pci_write_config_byte(hwif->pci_dev, regstate, 0x37); + pci_write_config_byte(dev, regstate, 0x37); udelay(10); - dma_stat = inb(dma_base); - outb(dma_stat & ~0x1, dma_base); /* stop dma */ - dma_stat = inb(dma_base + 2); - outb(dma_stat | 0x6, dma_base+2); /* clear errors */ + dma_stat = IN_BYTE(dma_base); + /* stop dma */ + OUT_BYTE(dma_stat & ~0x1, dma_base); + dma_stat = IN_BYTE(dma_base + 2); + /* clear errors */ + OUT_BYTE(dma_stat | 0x6, dma_base+2); /* fallthrough */ #ifdef HPT_RESET_STATE_ENGINE case ide_dma_begin: #endif - pci_write_config_byte(hwif->pci_dev, regstate, 0x37); + pci_write_config_byte(dev, regstate, 0x37); udelay(10); break; default: break; } - return ide_dmaproc(func, drive); /* use standard DMA stuff */ + /* use standard DMA stuff */ + return ide_dmaproc(func, drive); +} + +int hpt374_dmaproc (ide_dma_action_t func, ide_drive_t *drive) +{ + struct pci_dev *dev = HWIF(drive)->pci_dev; + ide_hwif_t *hwif = HWIF(drive); + unsigned long dma_base = hwif->dma_base; + byte mscreg = hwif->channel ? 0x54 : 0x50; +// byte reginfo = hwif->channel ? 0x56 : 0x52; + byte dma_stat; + + switch (func) { + case ide_dma_check: + return config_drive_xfer_rate(drive); + case ide_dma_test_irq: + /* returns 1 if dma irq issued, 0 otherwise */ + dma_stat = IN_BYTE(dma_base+2); +#if 0 /* do not set unless you know what you are doing */ + if (dma_stat & 4) { + byte stat = GET_STAT(); + OUT_BYTE(dma_base+2, dma_stat & 0xE4); + } +#endif + /* return 1 if INTR asserted */ + return (dma_stat & 4) == 4; + case ide_dma_end: + { + byte bwsr_mask = hwif->channel ? 0x02 : 0x01; + byte bwsr_stat, msc_stat; + pci_read_config_byte(dev, 0x6a, &bwsr_stat); + pci_read_config_byte(dev, mscreg, &msc_stat); + if ((bwsr_stat & bwsr_mask) == bwsr_mask) + pci_write_config_byte(dev, mscreg, msc_stat|0x30); + } + default: + break; + } + /* use standard DMA stuff */ + return ide_dmaproc(func, drive); } #endif /* CONFIG_BLK_DEV_IDEDMA */ @@ -949,7 +1233,8 @@ #define TRISTATE_BIT 0x8000 static int hpt370_busproc(ide_drive_t * drive, int state) { - ide_hwif_t *hwif = HWIF(drive); + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; byte tristate, resetmask, bus_reg; u16 tri_reg; @@ -969,8 +1254,8 @@ } /* grab status */ - pci_read_config_word(hwif->pci_dev, tristate, &tri_reg); - pci_read_config_byte(hwif->pci_dev, 0x59, &bus_reg); + pci_read_config_word(dev, tristate, &tri_reg); + pci_read_config_byte(dev, 0x59, &bus_reg); /* set the state. we don't set it if we don't need to do so. * make sure that the drive knows that it has failed if it's off */ @@ -1000,19 +1285,26 @@ bus_reg |= resetmask; break; } - pci_write_config_byte(hwif->pci_dev, 0x59, bus_reg); - pci_write_config_word(hwif->pci_dev, tristate, tri_reg); + pci_write_config_byte(dev, 0x59, bus_reg); + pci_write_config_word(dev, tristate, tri_reg); return 0; } -static void __init init_hpt370(struct pci_dev *dev) +static void __init init_hpt37x(struct pci_dev *dev) { int adjust, i; u16 freq; u32 pll; byte reg5bh; +#if 1 + byte reg5ah = 0; + pci_read_config_byte(dev, 0x5a, ®5ah); + /* interrupt force enable */ + pci_write_config_byte(dev, 0x5a, (reg5ah & ~0x10)); +#endif + /* * default to pci clock. make sure MA15/16 are set to output * to prevent drives having problems with 40-pin cables. @@ -1027,18 +1319,39 @@ freq &= 0x1FF; if (freq < 0x9c) { pll = F_LOW_PCI_33; - dev->sysdata = (void *) thirty_three_base_hpt370; - printk("HPT370: using 33MHz PCI clock\n"); + if (hpt_minimum_revision(dev,8)) + dev->driver_data = (void *) thirty_three_base_hpt374; + else if (hpt_minimum_revision(dev,5)) + dev->driver_data = (void *) thirty_three_base_hpt372; + else if (hpt_minimum_revision(dev,4)) + dev->driver_data = (void *) thirty_three_base_hpt370a; + else + dev->driver_data = (void *) thirty_three_base_hpt370; + printk("HPT37X: using 33MHz PCI clock\n"); } else if (freq < 0xb0) { pll = F_LOW_PCI_40; } else if (freq < 0xc8) { pll = F_LOW_PCI_50; - dev->sysdata = (void *) fifty_base_hpt370; - printk("HPT370: using 50MHz PCI clock\n"); + if (hpt_minimum_revision(dev,8)) + BUG(); + else if (hpt_minimum_revision(dev,5)) + dev->driver_data = (void *) fifty_base_hpt372; + else if (hpt_minimum_revision(dev,4)) + dev->driver_data = (void *) fifty_base_hpt370a; + else + dev->driver_data = (void *) fifty_base_hpt370a; + printk("HPT37X: using 50MHz PCI clock\n"); } else { pll = F_LOW_PCI_66; - dev->sysdata = (void *) sixty_six_base_hpt370; - printk("HPT370: using 66MHz PCI clock\n"); + if (hpt_minimum_revision(dev,8)) + BUG(); + else if (hpt_minimum_revision(dev,5)) + dev->driver_data = (void *) sixty_six_base_hpt372; + else if (hpt_minimum_revision(dev,4)) + dev->driver_data = (void *) sixty_six_base_hpt370a; + else + dev->driver_data = (void *) sixty_six_base_hpt370; + printk("HPT37X: using 66MHz PCI clock\n"); } /* @@ -1048,8 +1361,8 @@ * don't like to use the PLL because it will cause glitches * on PRST/SRST when the HPT state engine gets reset. */ - if (dev->sysdata) - goto init_hpt370_done; + if (dev->driver_data) + goto init_hpt37X_done; /* * adjust PLL based upon PCI clock, enable it, and wait for @@ -1076,9 +1389,16 @@ pci_write_config_dword(dev, 0x5c, pll & ~0x100); pci_write_config_byte(dev, 0x5b, 0x21); - dev->sysdata = (void *) fifty_base_hpt370; - printk("HPT370: using 50MHz internal PLL\n"); - goto init_hpt370_done; + if (hpt_minimum_revision(dev,8)) + BUG(); + else if (hpt_minimum_revision(dev,5)) + dev->driver_data = (void *) fifty_base_hpt372; + else if (hpt_minimum_revision(dev,4)) + dev->driver_data = (void *) fifty_base_hpt370a; + else + dev->driver_data = (void *) fifty_base_hpt370a; + printk("HPT37X: using 50MHz internal PLL\n"); + goto init_hpt37X_done; } } pll_recal: @@ -1088,13 +1408,44 @@ pll += (adjust >> 1); } -init_hpt370_done: +init_hpt37X_done: /* reset state engine */ pci_write_config_byte(dev, 0x50, 0x37); pci_write_config_byte(dev, 0x54, 0x37); udelay(100); } +static void __init init_hpt366 (struct pci_dev *dev) +{ + unsigned int reg1 = 0; + byte drive_fast = 0; + + /* + * Disable the "fast interrupt" prediction. + */ + pci_read_config_byte(dev, 0x51, &drive_fast); + if (drive_fast & 0x80) + pci_write_config_byte(dev, 0x51, drive_fast & ~0x80); + pci_read_config_dword(dev, 0x40, ®1); + + /* detect bus speed by looking at control reg timing: */ + switch((reg1 >> 8) & 7) { + case 5: + dev->driver_data = (void *) forty_base_hpt366; + break; + case 9: + dev->driver_data = (void *) twenty_five_base_hpt366; + break; + case 7: + default: + dev->driver_data = (void *) thirty_three_base_hpt366; + break; + } + + if (!dev->driver_data) + BUG(); +} + unsigned int __init pci_init_hpt366 (struct pci_dev *dev, const char *name) { byte test = 0; @@ -1118,10 +1469,11 @@ if (test != 0x08) pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); - if (pci_rev_check_hpt3xx(dev)) { - init_hpt370(dev); + if (hpt_minimum_revision(dev, 3)) { + init_hpt37x(dev); hpt_devs[n_hpt_devs++] = dev; } else { + init_hpt366(dev); hpt_devs[n_hpt_devs++] = dev; } @@ -1137,7 +1489,7 @@ unsigned int __init ata66_hpt366 (ide_hwif_t *hwif) { - byte ata66 = 0; + byte ata66 = 0; byte regmask = (hwif->channel) ? 0x01 : 0x02; pci_read_config_byte(hwif->pci_dev, 0x5a, &ata66); @@ -1151,13 +1503,12 @@ void __init ide_init_hpt366 (ide_hwif_t *hwif) { - int hpt_rev; - - hwif->tuneproc = &hpt3xx_tune_drive; - hwif->speedproc = &hpt3xx_tune_chipset; - hwif->quirkproc = &hpt3xx_quirkproc; - hwif->intrproc = &hpt3xx_intrproc; - hwif->maskproc = &hpt3xx_maskproc; + struct pci_dev *dev = hwif->pci_dev; + hwif->tuneproc = &hpt3xx_tune_drive; + hwif->speedproc = &hpt3xx_tune_chipset; + hwif->quirkproc = &hpt3xx_quirkproc; + hwif->intrproc = &hpt3xx_intrproc; + hwif->maskproc = &hpt3xx_maskproc; #ifdef HPT_SERIALIZE_IO /* serialize access to this device */ @@ -1165,59 +1516,58 @@ hwif->serialized = hwif->mate->serialized = 1; #endif - hpt_rev = pci_rev_check_hpt3xx(hwif->pci_dev); - if (hpt_rev) { - /* set up ioctl for power status. note: power affects both - * drives on each channel */ - hwif->busproc = &hpt370_busproc; - } - - if (pci_rev2_check_hpt3xx(hwif->pci_dev)) { - /* do nothing now but will split device types */ + if (hpt_minimum_revision(dev,3)) { + byte reg5ah = 0; + pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10); + /* + * set up ioctl for power status. + * note: power affects both + * drives on each channel + */ + hwif->resetproc = &hpt3xx_reset; + hwif->busproc = &hpt370_busproc; + hwif->drives[0].autotune = 1; + hwif->drives[1].autotune = 1; + } else if (hpt_minimum_revision(dev,2)) { + hwif->resetproc = &hpt3xx_reset; + hwif->busproc = &hpt3xx_tristate; + } else { hwif->resetproc = &hpt3xx_reset; -/* - * don't do until we can parse out the cobalt box argh ... - * hwif->busproc = &hpt3xx_tristate; - */ + hwif->busproc = &hpt3xx_tristate; } + if (!hwif->dma_base) + return; + #ifdef CONFIG_BLK_DEV_IDEDMA - if (hwif->dma_base) { - if (hpt_rev) { - byte reg5ah = 0; - pci_read_config_byte(hwif->pci_dev, 0x5a, ®5ah); - if (reg5ah & 0x10) /* interrupt force enable */ - pci_write_config_byte(hwif->pci_dev, 0x5a, reg5ah & ~0x10); - hwif->dmaproc = &hpt370_dmaproc; - } else { - hwif->dmaproc = &hpt366_dmaproc; - } - if (!noautodma) - hwif->autodma = 1; - else - hwif->autodma = 0; - } else { - hwif->autodma = 0; - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - } -#else /* !CONFIG_BLK_DEV_IDEDMA */ - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - hwif->autodma = 0; + if (hpt_minimum_revision(dev,8)) + hwif->dmaproc = &hpt374_dmaproc; + else if (hpt_minimum_revision(dev,5)) + hwif->dmaproc = &hpt374_dmaproc; + else if (hpt_minimum_revision(dev,3)) + hwif->dmaproc = &hpt370_dmaproc; + else if (hpt_minimum_revision(dev,2)) + hwif->dmaproc = &hpt366_dmaproc; + else + hwif->dmaproc = &hpt366_dmaproc; + + +#ifdef CONFIG_IDEDMA_AUTO + if (!noautodma) + hwif->autodma = 1; +#endif /* CONFIG_IDEDMA_AUTO */ #endif /* CONFIG_BLK_DEV_IDEDMA */ } void __init ide_dmacapable_hpt366 (ide_hwif_t *hwif, unsigned long dmabase) { byte masterdma = 0, slavedma = 0; - byte dma_new = 0, dma_old = inb(dmabase+2); + byte dma_new = 0, dma_old = IN_BYTE(dmabase+2); byte primary = hwif->channel ? 0x4b : 0x43; byte secondary = hwif->channel ? 0x4f : 0x47; unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ + local_irq_save(flags); dma_new = dma_old; pci_read_config_byte(hwif->pci_dev, primary, &masterdma); @@ -1225,9 +1575,121 @@ if (masterdma & 0x30) dma_new |= 0x20; if (slavedma & 0x30) dma_new |= 0x40; - if (dma_new != dma_old) outb(dma_new, dmabase+2); + if (dma_new != dma_old) OUT_BYTE(dma_new, dmabase+2); - __restore_flags(flags); /* local CPU only */ + local_irq_restore(flags); ide_setup_dma(hwif, dmabase, 8); } + +extern void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d); + +void __init fixup_device_hpt374 (struct pci_dev *dev, ide_pci_device_t *d) +{ + struct pci_dev *dev2 = NULL, *findev; + ide_pci_device_t *d2; + + if (PCI_FUNC(dev->devfn) & 1) + return; + + pci_for_each_dev(findev) { + if ((findev->vendor == dev->vendor) && + (findev->device == dev->device) && + ((findev->devfn - dev->devfn) == 1) && + (PCI_FUNC(findev->devfn) & 1)) { + dev2 = findev; + break; + } + } + + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d->name, dev->bus->number, dev->devfn); + ide_setup_pci_device(dev, d); + if (!dev2) { + return; + } else { + byte irq = 0, irq2 = 0; + pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); + pci_read_config_byte(dev2, PCI_INTERRUPT_LINE, &irq2); + if (irq != irq2) { + pci_write_config_byte(dev2, PCI_INTERRUPT_LINE, irq); + dev2->irq = dev->irq; + printk("%s: pci-config space interrupt fixed.\n", + d->name); + } + } + d2 = d; + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d2->name, dev2->bus->number, dev2->devfn); + ide_setup_pci_device(dev2, d2); + +} + +void __init fixup_device_hpt366 (struct pci_dev *dev, ide_pci_device_t *d) +{ + struct pci_dev *dev2 = NULL, *findev; + ide_pci_device_t *d2; + unsigned char pin1 = 0, pin2 = 0; + unsigned int class_rev; + char *chipset_names[] = {"HPT366", "HPT366", "HPT368", + "HPT370", "HPT370A", "HPT372"}; + + if (PCI_FUNC(dev->devfn) & 1) + return; + + pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); + class_rev &= 0xff; + + strcpy(d->name, chipset_names[class_rev]); + + switch(class_rev) { + case 5: + case 4: + case 3: printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d->name, dev->bus->number, dev->devfn); + ide_setup_pci_device(dev, d); + return; + default: break; + } + + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1); + pci_for_each_dev(findev) { + if ((findev->vendor == dev->vendor) && + (findev->device == dev->device) && + ((findev->devfn - dev->devfn) == 1) && + (PCI_FUNC(findev->devfn) & 1)) { + dev2 = findev; + pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2); + hpt363_shared_pin = (pin1 != pin2) ? 1 : 0; + hpt363_shared_irq = (dev->irq == dev2->irq) ? 1 : 0; + if (hpt363_shared_pin && hpt363_shared_irq) { + d->bootable = ON_BOARD; + printk("%s: onboard version of chipset, " + "pin1=%d pin2=%d\n", d->name, + pin1, pin2); +#if 0 + /* + * This is the third undocumented detection + * method and is generally required for the + * ABIT-BP6 boards. + */ + pci_write_config_byte(dev2, PCI_INTERRUPT_PIN, dev->irq); + printk("PCI: %s: Fixing interrupt %d pin %d " + "to ZERO \n", d->name, dev2->irq, pin2); + pci_write_config_byte(dev2, PCI_INTERRUPT_LINE, 0); +#endif + } + break; + } + } + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d->name, dev->bus->number, dev->devfn); + ide_setup_pci_device(dev, d); + if (!dev2) + return; + d2 = d; + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d2->name, dev2->bus->number, dev2->devfn); + ide_setup_pci_device(dev2, d2); +} + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/ht6560b.c linux.19rc3-ac4/drivers/ide/ht6560b.c --- linux.19rc3/drivers/ide/ht6560b.c 2002-07-29 12:49:58.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/ht6560b.c 2002-07-29 13:58:39.000000000 +0100 @@ -134,8 +134,7 @@ static byte current_timing = 0; byte select, timing; - __save_flags (flags); /* local CPU only */ - __cli(); /* local CPU only */ + local_irq_save(flags); select = HT_CONFIG(drive); timing = HT_TIMING(drive); @@ -145,21 +144,22 @@ current_timing = timing; if (drive->media != ide_disk || !drive->present) select |= HT_PREFETCH_MODE; - (void) inb(HT_CONFIG_PORT); - (void) inb(HT_CONFIG_PORT); - (void) inb(HT_CONFIG_PORT); - (void) inb(HT_CONFIG_PORT); - outb(select, HT_CONFIG_PORT); + (void) IN_BYTE(HT_CONFIG_PORT); + (void) IN_BYTE(HT_CONFIG_PORT); + (void) IN_BYTE(HT_CONFIG_PORT); + (void) IN_BYTE(HT_CONFIG_PORT); + OUT_BYTE(select, HT_CONFIG_PORT); /* * Set timing for this drive: */ - outb(timing, IDE_SELECT_REG); - (void) inb(IDE_STATUS_REG); + OUT_BYTE(timing, IDE_SELECT_REG); + (void) IN_BYTE(IDE_STATUS_REG); #ifdef DEBUG - printk("ht6560b: %s: select=%#x timing=%#x\n", drive->name, select, timing); + printk("ht6560b: %s: select=%#x timing=%#x\n", + drive->name, select, timing); #endif } - __restore_flags (flags); /* local CPU only */ + local_irq_restore(flags); } /* @@ -171,27 +171,27 @@ int i; /* Autodetect ht6560b */ - if ((orig_value=inb(HT_CONFIG_PORT)) == 0xff) + if ((orig_value = IN_BYTE(HT_CONFIG_PORT)) == 0xff) return 0; for (i=3;i>0;i--) { - outb(0x00, HT_CONFIG_PORT); - if (!( (~inb(HT_CONFIG_PORT)) & 0x3f )) { - outb(orig_value, HT_CONFIG_PORT); + OUT_BYTE(0x00, HT_CONFIG_PORT); + if (!( (~IN_BYTE(HT_CONFIG_PORT)) & 0x3f )) { + OUT_BYTE(orig_value, HT_CONFIG_PORT); return 0; } } - outb(0x00, HT_CONFIG_PORT); - if ((~inb(HT_CONFIG_PORT))& 0x3f) { - outb(orig_value, HT_CONFIG_PORT); + OUT_BYTE(0x00, HT_CONFIG_PORT); + if ((~IN_BYTE(HT_CONFIG_PORT))& 0x3f) { + OUT_BYTE(orig_value, HT_CONFIG_PORT); return 0; } /* * Ht6560b autodetected */ - outb(HT_CONFIG_DEFAULT, HT_CONFIG_PORT); - outb(HT_TIMING_DEFAULT, 0x1f6); /* IDE_SELECT_REG */ - (void) inb(0x1f7); /* IDE_STATUS_REG */ + OUT_BYTE(HT_CONFIG_DEFAULT, HT_CONFIG_PORT); + OUT_BYTE(HT_TIMING_DEFAULT, 0x1f6); /* IDE_SELECT_REG */ + (void) IN_BYTE(0x1f7); /* IDE_STATUS_REG */ printk("\nht6560b " HT6560B_VERSION ": chipset detected and initialized" @@ -257,8 +257,7 @@ unsigned long flags; int t = HT_PREFETCH_MODE << 8; - save_flags (flags); /* all CPUs */ - cli(); /* all CPUs */ + spin_lock_irqsave(&io_request_lock, flags); /* * Prefetch mode and unmask irq seems to conflict @@ -272,7 +271,7 @@ drive->no_unmask = 0; } - restore_flags (flags); /* all CPUs */ + spin_unlock_irqrestore(&io_request_lock, flags); #ifdef DEBUG printk("ht6560b: drive %s prefetch mode %sabled\n", drive->name, (state ? "en" : "dis")); @@ -293,13 +292,12 @@ timing = ht_pio2timings(drive, pio); - save_flags (flags); /* all CPUs */ - cli(); /* all CPUs */ + spin_lock_irqsave(&io_request_lock, flags); drive->drive_data &= 0xff00; drive->drive_data |= timing; - restore_flags (flags); /* all CPUs */ + spin_unlock_irqrestore(&io_request_lock, flags); #ifdef DEBUG printk("ht6560b: drive %s tuned to pio mode %#x timing=%#x\n", drive->name, pio, timing); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/icside.c linux.19rc3-ac4/drivers/ide/icside.c --- linux.19rc3/drivers/ide/icside.c 2002-07-29 12:49:58.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/icside.c 2002-07-29 13:58:39.000000000 +0100 @@ -26,8 +26,6 @@ #include #include -extern char *ide_xfer_verbose (byte xfer_rate); - /* * Maximum number of interfaces per card */ @@ -94,7 +92,7 @@ static void icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr) { unsigned int memc_port = (unsigned int)ec->irq_data; - outb (0, memc_port + ICS_ARCIN_V5_INTROFFSET); + OUT_BYTE(0, memc_port + ICS_ARCIN_V5_INTROFFSET); } /* Prototype: icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr) @@ -103,7 +101,7 @@ static void icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr) { unsigned int memc_port = (unsigned int)ec->irq_data; - inb (memc_port + ICS_ARCIN_V5_INTROFFSET); + IN_BYTE(memc_port + ICS_ARCIN_V5_INTROFFSET); } static const expansioncard_ops_t icside_ops_arcin_v5 = { @@ -124,8 +122,8 @@ { unsigned int ide_base_port = (unsigned int)ec->irq_data; - outb (0, ide_base_port + ICS_ARCIN_V6_INTROFFSET_1); - outb (0, ide_base_port + ICS_ARCIN_V6_INTROFFSET_2); + OUT_BYTE(0, ide_base_port + ICS_ARCIN_V6_INTROFFSET_1); + OUT_BYTE(0, ide_base_port + ICS_ARCIN_V6_INTROFFSET_2); } /* Prototype: icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr) @@ -135,8 +133,8 @@ { unsigned int ide_base_port = (unsigned int)ec->irq_data; - inb (ide_base_port + ICS_ARCIN_V6_INTROFFSET_1); - inb (ide_base_port + ICS_ARCIN_V6_INTROFFSET_2); + IN_BYTE(ide_base_port + ICS_ARCIN_V6_INTROFFSET_1); + IN_BYTE(ide_base_port + ICS_ARCIN_V6_INTROFFSET_2); } /* Prototype: icside_irqprobe(struct expansion_card *ec) @@ -146,8 +144,8 @@ { unsigned int ide_base_port = (unsigned int)ec->irq_data; - return inb(ide_base_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 || - inb(ide_base_port + ICS_ARCIN_V6_INTRSTAT_2) & 1; + return IN_BYTE(ide_base_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 || + IN_BYTE(ide_base_port + ICS_ARCIN_V6_INTRSTAT_2) & 1; } static const expansioncard_ops_t icside_ops_arcin_v6 = { @@ -173,10 +171,10 @@ addr = ecard_address (ec, ECARD_IOC, ECARD_FAST) + ICS_IDENT_OFFSET; - id = inb (addr) & 1; - id |= (inb (addr + 1) & 1) << 1; - id |= (inb (addr + 2) & 1) << 2; - id |= (inb (addr + 3) & 1) << 3; + id = IN_BYTE(addr) & 1; + id |= (IN_BYTE(addr + 1) & 1) << 1; + id |= (IN_BYTE(addr + 2) & 1) << 2; + id |= (IN_BYTE(addr + 3) & 1) << 3; switch (id) { case 0: /* A3IN */ @@ -334,14 +332,14 @@ rq = HWGROUP(drive)->rq; for (i = rq->nr_sectors; i > 0;) { i -= rq->current_nr_sectors; - ide_end_request(1, HWGROUP(drive)); + DRIVER(drive)->end_request(drive, 1); } return ide_stopped; } printk("%s: dma_intr: bad DMA status (dma_stat=%x)\n", drive->name, dma_stat); } - return ide_error(drive, "dma_intr", stat); + return DRIVER(drive)->error(drive, "dma_intr", stat); } /* @@ -493,6 +491,7 @@ icside_dmaproc(ide_dma_action_t func, ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); +// ide_task_t *args = HWGROUP(drive)->rq->special; int count, reading = 0; switch (func) { @@ -519,7 +518,7 @@ /* Route the DMA signals to * to the correct interface. */ - outb(hwif->select_data, hwif->config_data); + OUT_BYTE(hwif->select_data, hwif->config_data); /* Select the correct timing * for this drive @@ -534,10 +533,27 @@ if (drive->media != ide_disk) return 0; + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler(drive, &icside_dmaintr, WAIT_CMD, NULL); - OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, - IDE_COMMAND_REG); - + /* + * FIX ME to use only ACB ide_task_t args Struct + */ +#if 0 + { + ide_task_t *args = HWGROUP(drive)->rq->special; + OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); + } +#else + if (HWGROUP(drive)->rq->cmd == IDE_DRIVE_TASKFILE) { + ide_task_t *args = HWGROUP(drive)->rq->special; + OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); + } else if (drive->addressing == 1) + OUT_BYTE(reading ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG); + else + OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); +#endif + return HWIF(drive)->dmaproc(ide_dma_begin, drive); case ide_dma_begin: enable_dma(hwif->hw.dma); return 0; @@ -549,7 +565,7 @@ return get_dma_residue(hwif->hw.dma) != 0; case ide_dma_test_irq: - return inb((unsigned long)hwif->hw.priv) & 1; + return IN_BYTE((unsigned long)hwif->hw.priv) & 1; case ide_dma_bad_drive: case ide_dma_good_drive: @@ -660,7 +676,7 @@ /* * Be on the safe side - disable interrupts */ - inb(slot_port + ICS_ARCIN_V5_INTROFFSET); + IN_BYTE(slot_port + ICS_ARCIN_V5_INTROFFSET); hwif = icside_setup(slot_port, &icside_cardinfo_v5, ec->irq); @@ -681,7 +697,7 @@ else sel = 1 << 5; - outb(sel, slot_port); + OUT_BYTE(sel, slot_port); ec->irq_data = (void *)port; ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v6; @@ -689,8 +705,8 @@ /* * Be on the safe side - disable interrupts */ - inb(port + ICS_ARCIN_V6_INTROFFSET_1); - inb(port + ICS_ARCIN_V6_INTROFFSET_2); + IN_BYTE(port + ICS_ARCIN_V6_INTROFFSET_1); + IN_BYTE(port + ICS_ARCIN_V6_INTROFFSET_2); hwif = icside_setup(port, &icside_cardinfo_v6_1, ec->irq); mate = icside_setup(port, &icside_cardinfo_v6_2, ec->irq); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/ide.c linux.19rc3-ac4/drivers/ide/ide.c --- linux.19rc3/drivers/ide/ide.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/ide.c 2002-07-29 13:58:40.000000000 +0100 @@ -163,16 +163,6 @@ #include #endif /* CONFIG_KMOD */ -#ifdef CONFIG_IDE_TASKFILE_IO -# define __TASKFILE__IO -#else /* CONFIG_IDE_TASKFILE_IO */ -# undef __TASKFILE__IO -#endif /* CONFIG_IDE_TASKFILE_IO */ - -#ifdef __TASKFILE__IO -#else /* !__TASKFILE__IO */ -#endif /* __TASKFILE__IO */ - /* default maximum number of failures */ #define IDE_DEFAULT_MAX_FAILURES 1 @@ -217,13 +207,12 @@ unsigned long t, flags; int i; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ + local_irq_save(flags); t = jiffies * 11932; outb_p(0, 0x43); i = inb_p(0x40); - i |= inb(0x40) << 8; - __restore_flags(flags); /* local CPU only */ + i |= IN_BYTE(0x40) << 8; + local_irq_restore(flags); return (t - i); } #endif /* DISK_RECOVERY_TIME */ @@ -373,198 +362,17 @@ return system_bus_speed; } -#if SUPPORT_VLB_SYNC -/* - * Some localbus EIDE interfaces require a special access sequence - * when using 32-bit I/O instructions to transfer data. We call this - * the "vlb_sync" sequence, which consists of three successive reads - * of the sector count register location, with interrupts disabled - * to ensure that the reads all happen together. - */ -static inline void do_vlb_sync (ide_ioreg_t port) { - (void) inb (port); - (void) inb (port); - (void) inb (port); -} -#endif /* SUPPORT_VLB_SYNC */ - -/* - * This is used for most PIO data transfers *from* the IDE interface - */ -void ide_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount) -{ - byte io_32bit; - - /* first check if this controller has defined a special function - * for handling polled ide transfers - */ - - if(HWIF(drive)->ideproc) { - HWIF(drive)->ideproc(ideproc_ide_input_data, - drive, buffer, wcount); - return; - } - - io_32bit = drive->io_32bit; - - if (io_32bit) { -#if SUPPORT_VLB_SYNC - if (io_32bit & 2) { - unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ - do_vlb_sync(IDE_NSECTOR_REG); - insl(IDE_DATA_REG, buffer, wcount); - __restore_flags(flags); /* local CPU only */ - } else -#endif /* SUPPORT_VLB_SYNC */ - insl(IDE_DATA_REG, buffer, wcount); - } else { -#if SUPPORT_SLOW_DATA_PORTS - if (drive->slow) { - unsigned short *ptr = (unsigned short *) buffer; - while (wcount--) { - *ptr++ = inw_p(IDE_DATA_REG); - *ptr++ = inw_p(IDE_DATA_REG); - } - } else -#endif /* SUPPORT_SLOW_DATA_PORTS */ - insw(IDE_DATA_REG, buffer, wcount<<1); - } -} - -/* - * This is used for most PIO data transfers *to* the IDE interface - */ -void ide_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount) -{ - byte io_32bit; - - if(HWIF(drive)->ideproc) { - HWIF(drive)->ideproc(ideproc_ide_output_data, - drive, buffer, wcount); - return; - } - - io_32bit = drive->io_32bit; - - if (io_32bit) { -#if SUPPORT_VLB_SYNC - if (io_32bit & 2) { - unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ - do_vlb_sync(IDE_NSECTOR_REG); - outsl(IDE_DATA_REG, buffer, wcount); - __restore_flags(flags); /* local CPU only */ - } else -#endif /* SUPPORT_VLB_SYNC */ - outsl(IDE_DATA_REG, buffer, wcount); - } else { -#if SUPPORT_SLOW_DATA_PORTS - if (drive->slow) { - unsigned short *ptr = (unsigned short *) buffer; - while (wcount--) { - outw_p(*ptr++, IDE_DATA_REG); - outw_p(*ptr++, IDE_DATA_REG); - } - } else -#endif /* SUPPORT_SLOW_DATA_PORTS */ - outsw(IDE_DATA_REG, buffer, wcount<<1); - } -} - -/* - * The following routines are mainly used by the ATAPI drivers. - * - * These routines will round up any request for an odd number of bytes, - * so if an odd bytecount is specified, be sure that there's at least one - * extra byte allocated for the buffer. - */ -void atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount) -{ - if(HWIF(drive)->ideproc) { - HWIF(drive)->ideproc(ideproc_atapi_input_bytes, - drive, buffer, bytecount); - return; - } - - ++bytecount; -#if defined(CONFIG_ATARI) || defined(CONFIG_Q40) - if (MACH_IS_ATARI || MACH_IS_Q40) { - /* Atari has a byte-swapped IDE interface */ - insw_swapw(IDE_DATA_REG, buffer, bytecount / 2); - return; - } -#endif /* CONFIG_ATARI */ - ide_input_data (drive, buffer, bytecount / 4); - if ((bytecount & 0x03) >= 2) - insw (IDE_DATA_REG, ((byte *)buffer) + (bytecount & ~0x03), 1); -} - -void atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount) -{ - if(HWIF(drive)->ideproc) { - HWIF(drive)->ideproc(ideproc_atapi_output_bytes, - drive, buffer, bytecount); - return; - } - - ++bytecount; -#if defined(CONFIG_ATARI) || defined(CONFIG_Q40) - if (MACH_IS_ATARI || MACH_IS_Q40) { - /* Atari has a byte-swapped IDE interface */ - outsw_swapw(IDE_DATA_REG, buffer, bytecount / 2); - return; - } -#endif /* CONFIG_ATARI */ - ide_output_data (drive, buffer, bytecount / 4); - if ((bytecount & 0x03) >= 2) - outsw (IDE_DATA_REG, ((byte *)buffer) + (bytecount & ~0x03), 1); -} - -/* - * Needed for PCI irq sharing - */ -//static inline -int drive_is_ready (ide_drive_t *drive) -{ - byte stat = 0; - if (drive->waiting_for_dma) - return HWIF(drive)->dmaproc(ide_dma_test_irq, drive); -#if 0 - udelay(1); /* need to guarantee 400ns since last command was issued */ -#endif - -#ifdef CONFIG_IDEPCI_SHARE_IRQ - /* - * We do a passive status test under shared PCI interrupts on - * cards that truly share the ATA side interrupt, but may also share - * an interrupt with another pci card/device. We make no assumptions - * about possible isa-pnp and pci-pnp issues yet. - */ - if (IDE_CONTROL_REG) - stat = GET_ALTSTAT(); - else -#endif /* CONFIG_IDEPCI_SHARE_IRQ */ - stat = GET_STAT(); /* Note: this may clear a pending IRQ!! */ - - if (stat & BUSY_STAT) - return 0; /* drive busy: definitely not interrupting */ - return 1; /* drive ready: *might* be interrupting */ -} - /* * This is our end_request replacement function. */ -void ide_end_request (byte uptodate, ide_hwgroup_t *hwgroup) +int ide_end_request (ide_drive_t *drive, int uptodate) { struct request *rq; unsigned long flags; - ide_drive_t *drive = hwgroup->drive; + int ret = 1; spin_lock_irqsave(&io_request_lock, flags); - rq = hwgroup->rq; + rq = HWGROUP(drive)->rq; /* * decide whether to reenable DMA -- 3 is a random magic for now, @@ -572,16 +380,18 @@ */ if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) { drive->state = 0; - hwgroup->hwif->dmaproc(ide_dma_on, drive); + HWGROUP(drive)->hwif->dmaproc(ide_dma_on, drive); } - if (!end_that_request_first(rq, uptodate, hwgroup->drive->name)) { + if (!end_that_request_first(rq, uptodate, drive->name)) { add_blkdev_randomness(MAJOR(rq->rq_dev)); blkdev_dequeue_request(rq); - hwgroup->rq = NULL; + HWGROUP(drive)->rq = NULL; end_that_request_last(rq); + ret = 0; } spin_unlock_irqrestore(&io_request_lock, flags); + return ret; } /* @@ -666,7 +476,9 @@ if (OK_STAT(stat=GET_STAT(), 0, BUSY_STAT)) { printk("%s: ATAPI reset complete\n", drive->name); } else { - if (0 < (signed long)(hwgroup->poll_timeout - jiffies)) { + if (time_before(jiffies, hwgroup->poll_timeout)) { + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20, NULL); return ide_started; /* continue polling */ } @@ -691,7 +503,9 @@ byte tmp; if (!OK_STAT(tmp=GET_STAT(), 0, BUSY_STAT)) { - if (0 < (signed long)(hwgroup->poll_timeout - jiffies)) { + if (time_before(jiffies, hwgroup->poll_timeout)) { + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler (drive, &reset_pollfunc, HZ/20, NULL); return ide_started; /* continue polling */ } @@ -784,8 +598,7 @@ ide_hwif_t *hwif = HWIF(drive); ide_hwgroup_t *hwgroup = HWGROUP(drive); - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ + local_irq_save(flags); /* For an ATAPI device, first try an ATAPI SRST. */ if (drive->media != ide_disk && !do_not_try_atapi) { @@ -794,8 +607,10 @@ udelay (20); OUT_BYTE (WIN_SRST, IDE_COMMAND_REG); hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20, NULL); - __restore_flags (flags); /* local CPU only */ + local_irq_restore(flags); return ide_started; } @@ -808,7 +623,7 @@ #if OK_TO_RESET_CONTROLLER if (!IDE_CONTROL_REG) { - __restore_flags(flags); + local_irq_restore(flags); return ide_stopped; } /* @@ -828,6 +643,8 @@ } udelay(10); /* more than enough time */ hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler (drive, &reset_pollfunc, HZ/20, NULL); /* @@ -840,7 +657,7 @@ #endif /* OK_TO_RESET_CONTROLLER */ - __restore_flags (flags); /* local CPU only */ + local_irq_restore(flags); return ide_started; } @@ -875,7 +692,9 @@ case IDE_DRIVE_CMD: { byte *args = (byte *) rq->buffer; - rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); + if (rq->errors == 0) + rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); + if (args) { args[0] = stat; args[1] = err; @@ -886,7 +705,9 @@ case IDE_DRIVE_TASK: { byte *args = (byte *) rq->buffer; - rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); + if (rq->errors == 0) + rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); + if (args) { args[0] = stat; args[1] = err; @@ -901,7 +722,9 @@ case IDE_DRIVE_TASKFILE: { ide_task_t *args = (ide_task_t *) rq->special; - rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); + if (rq->errors == 0) + rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); + if (args) { if (args->tf_in_flags.b.data) { unsigned short data = IN_WORD(IDE_DATA_REG); @@ -947,8 +770,7 @@ unsigned long flags; byte err = 0; - __save_flags (flags); /* local CPU only */ - ide__sti(); /* local CPU only */ + local_irq_set(flags); printk("%s: %s: status=0x%02x", drive->name, msg, stat); #if FANCY_STATUS_DUMPS printk(" { "); @@ -1016,7 +838,7 @@ #endif /* FANCY_STATUS_DUMPS */ printk("\n"); } - __restore_flags (flags); /* local CPU only */ + local_irq_restore(flags); return err; } @@ -1037,11 +859,15 @@ u32 buffer[16]; unsigned int wcount = (i > 16) ? 16 : i; i -= wcount; - ide_input_data (drive, buffer, wcount); + ata_input_data (drive, buffer, wcount); } } /* + * FIXME Add an ATAPI error + */ + +/* * ide_error() takes action based on the error returned by the drive. */ ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, byte stat) @@ -1068,6 +894,8 @@ if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { /* other bits are useless when BUSY */ rq->errors |= ERROR_RESET; } else { + +/* ide_disk */ if (drive->media == ide_disk && (stat & ERR_STAT)) { /* err has different meaning on cdrom and tape */ if (err == ABRT_ERR) { @@ -1080,17 +908,19 @@ else if (err & TRK0_ERR) /* help it find track zero */ rq->errors |= ERROR_RECAL; } +/* !ide_disk */ if ((stat & DRQ_STAT) && rq->cmd != WRITE) try_to_flush_leftover_data(drive); +/* !ide_disk */ } if (GET_STAT() & (BUSY_STAT|DRQ_STAT)) OUT_BYTE(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG); /* force an abort */ if (rq->errors >= ERROR_MAX) { if (drive->driver != NULL) - DRIVER(drive)->end_request(0, HWGROUP(drive)); + DRIVER(drive)->end_request(drive, 0); else - ide_end_request(0, HWGROUP(drive)); + ide_end_request(drive, 0); } else { if ((rq->errors & ERROR_RESET) == ERROR_RESET) { ++rq->errors; @@ -1109,6 +939,8 @@ */ void ide_cmd (ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler) { + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler (drive, handler, WAIT_CMD, NULL); if (IDE_CONTROL_REG) OUT_BYTE(drive->ctl,IDE_CONTROL_REG); /* clear nIEN */ @@ -1127,18 +959,18 @@ byte stat = GET_STAT(); int retries = 10; - ide__sti(); /* local CPU only */ + local_irq_enable(); if ((stat & DRQ_STAT) && args && args[3]) { byte io_32bit = drive->io_32bit; drive->io_32bit = 0; - ide_input_data(drive, &args[4], args[3] * SECTOR_WORDS); + ata_input_data(drive, &args[4], args[3] * SECTOR_WORDS); drive->io_32bit = io_32bit; while (((stat = GET_STAT()) & BUSY_STAT) && retries--) udelay(100); } if (!OK_STAT(stat, READY_STAT, BAD_STAT)) - return ide_error(drive, "drive_cmd", stat); /* calls ide_end_drive_cmd */ + return DRIVER(drive)->error(drive, "drive_cmd", stat); /* calls ide_end_drive_cmd */ ide_end_drive_cmd (drive, stat, GET_ERR()); return ide_stopped; } @@ -1155,10 +987,9 @@ printk("%s: do_special: 0x%02x\n", drive->name, s->all); #endif if (s->b.set_tune) { - ide_tuneproc_t *tuneproc = HWIF(drive)->tuneproc; s->b.set_tune = 0; - if (tuneproc != NULL) - tuneproc(drive, drive->tune_req); + if (HWIF(drive)->tuneproc != NULL) + HWIF(drive)->tuneproc(drive, drive->tune_req); } else if (drive->driver != NULL) { return DRIVER(drive)->special(drive); } else if (s->all) { @@ -1169,58 +1000,6 @@ } /* - * This routine busy-waits for the drive status to be not "busy". - * It then checks the status for all of the "good" bits and none - * of the "bad" bits, and if all is okay it returns 0. All other - * cases return 1 after invoking ide_error() -- caller should just return. - * - * This routine should get fixed to not hog the cpu during extra long waits.. - * That could be done by busy-waiting for the first jiffy or two, and then - * setting a timer to wake up at half second intervals thereafter, - * until timeout is achieved, before timing out. - */ -int ide_wait_stat (ide_startstop_t *startstop, ide_drive_t *drive, byte good, byte bad, unsigned long timeout) { - byte stat; - int i; - unsigned long flags; - - /* bail early if we've exceeded max_failures */ - if (drive->max_failures && (drive->failures > drive->max_failures)) { - *startstop = ide_stopped; - return 1; - } - - udelay(1); /* spec allows drive 400ns to assert "BUSY" */ - if ((stat = GET_STAT()) & BUSY_STAT) { - __save_flags(flags); /* local CPU only */ - ide__sti(); /* local CPU only */ - timeout += jiffies; - while ((stat = GET_STAT()) & BUSY_STAT) { - if (0 < (signed long)(jiffies - timeout)) { - __restore_flags(flags); /* local CPU only */ - *startstop = ide_error(drive, "status timeout", stat); - return 1; - } - } - __restore_flags(flags); /* local CPU only */ - } - /* - * Allow status to settle, then read it again. - * A few rare drives vastly violate the 400ns spec here, - * so we'll wait up to 10usec for a "good" status - * rather than expensively fail things immediately. - * This fix courtesy of Matthew Faupel & Niccolo Rigacci. - */ - for (i = 0; i < 10; i++) { - udelay(1); - if (OK_STAT((stat = GET_STAT()), good, bad)) - return 0; - } - *startstop = ide_error(drive, "status error", stat); - return 1; -} - -/* * execute_drive_cmd() issues a special drive command, * usually initiated by ioctl() from the external hdparm program. */ @@ -1233,43 +1012,9 @@ if (!(args)) break; -#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG - { - printk(KERN_INFO "%s: ", drive->name); -// printk("TF.0=x%02x ", args->tfRegister[IDE_DATA_OFFSET]); - printk("TF.1=x%02x ", args->tfRegister[IDE_FEATURE_OFFSET]); - printk("TF.2=x%02x ", args->tfRegister[IDE_NSECTOR_OFFSET]); - printk("TF.3=x%02x ", args->tfRegister[IDE_SECTOR_OFFSET]); - printk("TF.4=x%02x ", args->tfRegister[IDE_LCYL_OFFSET]); - printk("TF.5=x%02x ", args->tfRegister[IDE_HCYL_OFFSET]); - printk("TF.6=x%02x ", args->tfRegister[IDE_SELECT_OFFSET]); - printk("TF.7=x%02x\n", args->tfRegister[IDE_COMMAND_OFFSET]); - printk(KERN_INFO "%s: ", drive->name); -// printk("HTF.0=x%02x ", args->hobRegister[IDE_DATA_OFFSET_HOB]); - printk("HTF.1=x%02x ", args->hobRegister[IDE_FEATURE_OFFSET_HOB]); - printk("HTF.2=x%02x ", args->hobRegister[IDE_NSECTOR_OFFSET_HOB]); - printk("HTF.3=x%02x ", args->hobRegister[IDE_SECTOR_OFFSET_HOB]); - printk("HTF.4=x%02x ", args->hobRegister[IDE_LCYL_OFFSET_HOB]); - printk("HTF.5=x%02x ", args->hobRegister[IDE_HCYL_OFFSET_HOB]); - printk("HTF.6=x%02x ", args->hobRegister[IDE_SELECT_OFFSET_HOB]); - printk("HTF.7=x%02x\n", args->hobRegister[IDE_CONTROL_OFFSET_HOB]); - } -#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */ - -// if (args->tf_out_flags.all == 0) { - do_taskfile(drive, - (struct hd_drive_task_hdr *)&args->tfRegister, - (struct hd_drive_hob_hdr *)&args->hobRegister, - args->handler); -// } else { -// return flagged_taskfile(drive, args); -// } - - if (((args->command_type == IDE_DRIVE_TASK_RAW_WRITE) || - (args->command_type == IDE_DRIVE_TASK_OUT)) && - args->prehandler && args->handler) - return args->prehandler(drive, rq); - return ide_started; + if (args->tf_out_flags.all != 0) + return flagged_taskfile(drive, args); + return do_rw_taskfile(drive, args); } case IDE_DRIVE_TASK: { @@ -1349,15 +1094,26 @@ ide_hwif_t *hwif = HWIF(drive); #ifdef DEBUG - printk("%s: start_request: current=0x%08lx\n", hwif->name, (unsigned long) rq); + printk("%s: start_request: current=0x%08lx\n", + hwif->name, (unsigned long) rq); #endif + /* bail early if we've exceeded max_failures */ if (drive->max_failures && (drive->failures > drive->max_failures)) { goto kill_rq; } + /* + * bail early if we've sent a device to sleep, however how to wake + * this needs to be a masked flag. FIXME for proper operations. + */ + if (drive->suspend_reset) { + goto kill_rq; + } + if (unit >= MAX_DRIVES) { - printk("%s: bad device number: %s\n", hwif->name, kdevname(rq->rq_dev)); + printk("%s: bad device number: %s\n", + hwif->name, kdevname(rq->rq_dev)); goto kill_rq; } #ifdef DEBUG @@ -1396,6 +1152,7 @@ switch(rq->cmd) { case IDE_DRIVE_CMD: case IDE_DRIVE_TASK: + return execute_drive_cmd(drive, rq); case IDE_DRIVE_TASKFILE: return execute_drive_cmd(drive, rq); default: @@ -1410,25 +1167,16 @@ return do_special(drive); kill_rq: if (drive->driver != NULL) - DRIVER(drive)->end_request(0, HWGROUP(drive)); + DRIVER(drive)->end_request(drive, 0); else - ide_end_request(0, HWGROUP(drive)); + ide_end_request(drive, 0); return ide_stopped; } -ide_startstop_t restart_request (ide_drive_t *drive) +int restart_request (ide_drive_t *drive, struct request *rq) { - ide_hwgroup_t *hwgroup = HWGROUP(drive); - unsigned long flags; - struct request *rq; - - spin_lock_irqsave(&io_request_lock, flags); - hwgroup->handler = NULL; - del_timer(&hwgroup->timer); - rq = hwgroup->rq; - spin_unlock_irqrestore(&io_request_lock, flags); - - return start_request(drive, rq); + (void) start_request(drive, rq); + return 0; } /* @@ -1455,7 +1203,7 @@ best = NULL; drive = hwgroup->drive; do { - if (!list_empty(&drive->queue.queue_head) && (!drive->sleep || 0 <= (signed long)(jiffies - drive->sleep))) { + if (!list_empty(&drive->queue.queue_head) && (!drive->sleep || time_after_eq(jiffies, drive->sleep))) { if (!best || (drive->sleep && (!best->sleep || 0 < (signed long)(best->sleep - drive->sleep))) || (!best->sleep && 0 < (signed long)(WAKEUP(best) - WAKEUP(drive)))) @@ -1468,10 +1216,10 @@ if (best && best->nice1 && !best->sleep && best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) { long t = (signed long)(WAKEUP(best) - jiffies); if (t >= WAIT_MIN_SLEEP) { - /* - * We *may* have some time to spare, but first let's see if - * someone can potentially benefit from our nice mood today.. - */ + /* + * We *may* have some time to spare, but first let's see if + * someone can potentially benefit from our nice mood today.. + */ drive = best->next; do { if (!drive->sleep @@ -1534,7 +1282,8 @@ ide_get_lock(&ide_lock, ide_intr, hwgroup); /* for atari only: POSSIBLY BROKEN HERE(?) */ - __cli(); /* necessary paranoia: ensure IRQs are masked on local CPU */ + local_irq_disable(); + /* necessary paranoia: ensure IRQs are masked on local CPU */ while (!hwgroup->busy) { hwgroup->busy = 1; @@ -1548,13 +1297,13 @@ sleep = drive->sleep; } while ((drive = drive->next) != hwgroup->drive); if (sleep) { - /* - * Take a short snooze, and then wake up this hwgroup again. - * This gives other hwgroups on the same a chance to - * play fairly with us, just in case there are big differences - * in relative throughputs.. don't want to hog the cpu too much. - */ - if (0 < (signed long)(jiffies + WAIT_MIN_SLEEP - sleep)) + /* + * Take a short snooze, and then wake up this hwgroup again. + * This gives other hwgroups on the same a chance to + * play fairly with us, just in case there are big differences + * in relative throughputs.. don't want to hog the cpu too much. + */ + if (time_before(sleep, jiffies + WAIT_MIN_SLEEP)) sleep = jiffies + WAIT_MIN_SLEEP; #if 1 if (timer_pending(&hwgroup->timer)) @@ -1595,7 +1344,8 @@ if (masked_irq && hwif->irq != masked_irq) disable_irq_nosync(hwif->irq); spin_unlock(&io_request_lock); - ide__sti(); /* allow other IRQs while we start this request */ + local_irq_enable(); + /* allow other IRQs while we start this request */ startstop = start_request(drive, rq); spin_lock_irq(&io_request_lock); if (masked_irq && hwif->irq != masked_irq) @@ -1623,6 +1373,7 @@ ide_do_request(q->queuedata, 0); } +#ifndef __IDEDMA_TIMEOUT /* * un-busy the hwgroup etc, and clear any pending DMA status. we want to * retry the current request in pio mode instead of risking tossing it @@ -1663,8 +1414,17 @@ rq->errors = 0; rq->sector = rq->bh->b_rsector; rq->current_nr_sectors = rq->bh->b_size >> 9; + rq->hard_cur_sectors = rq->current_nr_sectors; rq->buffer = rq->bh->b_data; + + /* + * FIXME or DELETE ME + * + * so what do we do if the device is left in an invalid state + * and will not accept commands. SOFT RESET is the only chance. + */ } +#endif /* * ide_timer_expiry() is our timeout function for all drive operations. @@ -1700,7 +1460,7 @@ hwgroup->handler = NULL; } else { ide_hwif_t *hwif; - ide_startstop_t startstop; + ide_startstop_t startstop = ide_stopped; if (!hwgroup->busy) { hwgroup->busy = 1; /* paranoia */ printk("%s: ide_timer_expiry: hwgroup->busy was 0 ??\n", drive->name); @@ -1728,7 +1488,8 @@ #else disable_irq(hwif->irq); /* disable_irq_nosync ?? */ #endif /* DISABLE_IRQ_NOSYNC */ - __cli(); /* local CPU only, as if we were handling an interrupt */ + local_irq_disable(); + /* local CPU only, as if we were handling an interrupt */ if (hwgroup->poll_timeout != 0) { startstop = handler(drive); } else if (drive_is_ready(drive)) { @@ -1739,10 +1500,16 @@ startstop = handler(drive); } else { if (drive->waiting_for_dma) { +#ifndef __IDEDMA_TIMEOUT startstop = ide_stopped; ide_dma_timeout_retry(drive); +#else /* __IDEDMA_TIMEOUT */ + (void) hwgroup->hwif->dmaproc(ide_dma_end, drive); + printk("%s: timeout waiting for DMA\n", drive->name); + (void) hwgroup->hwif->dmaproc(ide_dma_timeout, drive); +#endif /* __IDEDMA_TIMEOUT */ } else - startstop = ide_error(drive, "irq timeout", GET_STAT()); + startstop = DRIVER(drive)->error(drive, "irq timeout", GET_STAT()); } set_recovery_timer(hwif); drive->service_time = jiffies - drive->service_start; @@ -1794,7 +1561,7 @@ /* Try to not flood the console with msgs */ static unsigned long last_msgtime, count; ++count; - if (0 < (signed long)(jiffies - (last_msgtime + HZ))) { + if (time_after(jiffies, last_msgtime + HZ)) { last_msgtime = jiffies; printk("%s%s: unexpected interrupt, status=0x%02x, count=%ld\n", hwif->name, (hwif->next == hwgroup->hwif) ? "" : "(?)", stat, count); @@ -1849,7 +1616,8 @@ #ifdef CONFIG_BLK_DEV_IDEPCI } else { /* - * Whack the status register, just in case we have a leftover pending IRQ. + * Whack the status register, just in case + * we have a leftover pending IRQ. */ (void) IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]); #endif /* CONFIG_BLK_DEV_IDEPCI */ @@ -1860,16 +1628,18 @@ drive = hwgroup->drive; if (!drive) { /* - * This should NEVER happen, and there isn't much we could do about it here. + * This should NEVER happen, and there isn't much + * we could do about it here. */ spin_unlock_irqrestore(&io_request_lock, flags); return; } if (!drive_is_ready(drive)) { /* - * This happens regularly when we share a PCI IRQ with another device. - * Unfortunately, it can also happen with some buggy drives that trigger - * the IRQ before their status register is up to date. Hopefully we have + * This happens regularly when we share a PCI IRQ with + * another device. Unfortunately, it can also happen + * with some buggy drives that trigger the IRQ before + * their status register is up to date. Hopefully we have * enough advance overhead that the latter isn't a problem. */ spin_unlock_irqrestore(&io_request_lock, flags); @@ -1884,7 +1654,7 @@ spin_unlock(&io_request_lock); if (drive->unmask) - ide__sti(); /* local CPU only */ + local_irq_enable(); startstop = handler(drive); /* service this interrupt, may set handler for next interrupt */ spin_lock_irq(&io_request_lock); @@ -2228,8 +1998,7 @@ if (index >= MAX_HWIFS) return; - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ + spin_lock_irqsave(&io_request_lock, flags); hwif = &ide_hwifs[index]; if (!hwif->present) goto abort; @@ -2247,7 +2016,7 @@ /* * All clear? Then blow away the buffer cache */ - sti(); + spin_unlock_irqrestore(&io_request_lock, flags); for (unit = 0; unit < MAX_DRIVES; ++unit) { drive = &hwif->drives[unit]; if (!drive->present) @@ -2263,7 +2032,7 @@ destroy_proc_ide_drives(hwif); #endif } - cli(); + spin_lock_irqsave(&io_request_lock, flags); hwgroup = hwif->hwgroup; /* @@ -2276,7 +2045,7 @@ g = g->next; } while (g != hwgroup->hwif); if (irq_count == 1) - free_irq(hwif->irq, hwgroup); + ide_free_irq(hwif->irq, hwgroup); /* * Note that we only release the standard ports, @@ -2383,7 +2152,7 @@ hwif->straight8 = old_hwif.straight8; hwif->hwif_data = old_hwif.hwif_data; abort: - restore_flags(flags); /* all CPUs */ + spin_unlock_irqrestore(&io_request_lock, flags); } /* @@ -2595,14 +2364,13 @@ while (hwgroup->busy) { unsigned long lflags; spin_unlock_irq(&io_request_lock); - __save_flags(lflags); /* local CPU only */ - __sti(); /* local CPU only; needed for jiffies */ - if (0 < (signed long)(jiffies - timeout)) { - __restore_flags(lflags); /* local CPU only */ + local_irq_set(lflags); + if (time_after(jiffies, timeout)) { + local_irq_restore(lflags); printk("%s: channel busy\n", drive->name); return -EBUSY; } - __restore_flags(lflags); /* local CPU only */ + local_irq_restore(lflags); spin_lock_irq(&io_request_lock); } return 0; @@ -2697,8 +2465,8 @@ ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL); ide_add_setting(drive, "using_dma", SETTING_RW, HDIO_GET_DMA, HDIO_SET_DMA, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma); ide_add_setting(drive, "ide_scsi", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->scsi, NULL); - ide_add_setting(drive, "init_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 69, 1, 1, &drive->init_speed, NULL); - ide_add_setting(drive, "current_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 69, 1, 1, &drive->current_speed, NULL); + ide_add_setting(drive, "init_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL); + ide_add_setting(drive, "current_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, NULL); ide_add_setting(drive, "number", SETTING_RW, -1, -1, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL); } @@ -2918,68 +2686,15 @@ #endif /* CONFIG_IDE_TASK_IOCTL */ case HDIO_DRIVE_CMD: - { - byte args[4], *argbuf = args; - byte xfer_rate = 0; - int argsize = 4; - ide_task_t tfargs; - if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) return -EACCES; - if (NULL == (void *) arg) - return ide_do_drive_cmd(drive, &rq, ide_wait); - if (copy_from_user(args, (void *)arg, 4)) - return -EFAULT; + return ide_cmd_ioctl(drive, inode, file, cmd, arg); - tfargs.tfRegister[IDE_FEATURE_OFFSET] = args[2]; - tfargs.tfRegister[IDE_NSECTOR_OFFSET] = args[3]; - tfargs.tfRegister[IDE_SECTOR_OFFSET] = args[1]; - tfargs.tfRegister[IDE_LCYL_OFFSET] = 0x00; - tfargs.tfRegister[IDE_HCYL_OFFSET] = 0x00; - tfargs.tfRegister[IDE_SELECT_OFFSET] = 0x00; - tfargs.tfRegister[IDE_COMMAND_OFFSET] = args[0]; - - if (args[3]) { - argsize = 4 + (SECTOR_WORDS * 4 * args[3]); - argbuf = kmalloc(argsize, GFP_KERNEL); - if (argbuf == NULL) - return -ENOMEM; - memcpy(argbuf, args, 4); - } - - if (set_transfer(drive, &tfargs)) { - xfer_rate = args[1]; - if (ide_ata66_check(drive, &tfargs)) - goto abort; - } - - err = ide_wait_cmd(drive, args[0], args[1], args[2], args[3], argbuf); - - if (!err && xfer_rate) { - /* active-retuning-calls future */ - if ((HWIF(drive)->speedproc) != NULL) - HWIF(drive)->speedproc(drive, xfer_rate); - ide_driveid_update(drive); - } - abort: - if (copy_to_user((void *)arg, argbuf, argsize)) - err = -EFAULT; - if (argsize > 4) - kfree(argbuf); - return err; - } case HDIO_DRIVE_TASK: - { - byte args[7], *argbuf = args; - int argsize = 7; - if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) return -EACCES; - if (copy_from_user(args, (void *)arg, 7)) - return -EFAULT; - err = ide_wait_cmd_task(drive, argbuf); - if (copy_to_user((void *)arg, argbuf, argsize)) - err = -EFAULT; - return err; - } + if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) + return -EACCES; + return ide_task_ioctl(drive, inode, file, cmd, arg); + case HDIO_SCAN_HWIF: { int args[3]; @@ -3011,18 +2726,15 @@ case HDIO_DRIVE_RESET: { unsigned long flags; - ide_hwgroup_t *hwgroup = HWGROUP(drive); - if (!capable(CAP_SYS_ADMIN)) return -EACCES; #if 1 spin_lock_irqsave(&io_request_lock, flags); - if (hwgroup->handler != NULL) { - printk("%s: ide_set_handler: handler not null; %p\n", drive->name, hwgroup->handler); - (void) hwgroup->handler(drive); -// hwgroup->handler = NULL; -// hwgroup->expiry = NULL; - hwgroup->timer.expires = jiffies + 0;; - del_timer(&hwgroup->timer); + if ( HWGROUP(drive)->handler != NULL) { + printk("%s: ide_set_handler: handler not null; %p\n", drive->name, HWGROUP(drive)->handler); + (void) HWGROUP(drive)->handler(drive); +// HWGROUP(drive)->handler = NULL; + HWGROUP(drive)->expiry = NULL; + del_timer(&HWGROUP(drive)->timer); } spin_unlock_irqrestore(&io_request_lock, flags); @@ -3581,13 +3293,6 @@ { #ifdef CONFIG_BLK_DEV_IDEPCI ide_scan_pcibus(ide_scan_direction); -#else -#ifdef CONFIG_BLK_DEV_RZ1000 - { - extern void ide_probe_for_rz100x(void); - ide_probe_for_rz100x(); - } -#endif /* CONFIG_BLK_DEV_RZ1000 */ #endif /* CONFIG_BLK_DEV_IDEPCI */ } #endif /* CONFIG_PCI */ @@ -3736,22 +3441,42 @@ return 0; } +static int default_suspend (ide_drive_t *drive) +{ + return 0; +} + +static int default_resume (ide_drive_t *drive) +{ + return 0; +} + static int default_flushcache (ide_drive_t *drive) { return 0; } -static ide_startstop_t default_do_request(ide_drive_t *drive, struct request *rq, unsigned long block) +static ide_startstop_t default_do_request (ide_drive_t *drive, struct request *rq, unsigned long block) { - ide_end_request(0, HWGROUP(drive)); + ide_end_request(drive, 0); return ide_stopped; } - -static void default_end_request (byte uptodate, ide_hwgroup_t *hwgroup) + +static int default_end_request (ide_drive_t *drive, int uptodate) { - ide_end_request(uptodate, hwgroup); + return ide_end_request(drive, uptodate); } - + +static byte default_sense (ide_drive_t *drive, const char *msg, byte stat) +{ + return ide_dump_status(drive, msg, stat); +} + +static ide_startstop_t default_error (ide_drive_t *drive, const char *msg, byte stat) +{ + return ide_error(drive, msg, stat); +} + static int default_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { @@ -3791,6 +3516,11 @@ return ide_stopped; } +static int default_init (void) +{ + return 0; +} + static int default_reinit (ide_drive_t *drive) { printk(KERN_ERR "%s: does not support hotswap of device class !\n", drive->name); @@ -3804,9 +3534,13 @@ if (d->cleanup == NULL) d->cleanup = default_cleanup; if (d->standby == NULL) d->standby = default_standby; + if (d->suspend == NULL) d->suspend = default_suspend; + if (d->resume == NULL) d->resume = default_resume; if (d->flushcache == NULL) d->flushcache = default_flushcache; if (d->do_request == NULL) d->do_request = default_do_request; if (d->end_request == NULL) d->end_request = default_end_request; + if (d->sense == NULL) d->sense = default_sense; + if (d->error == NULL) d->error = default_error; if (d->ioctl == NULL) d->ioctl = default_ioctl; if (d->open == NULL) d->open = default_open; if (d->release == NULL) d->release = default_release; @@ -3814,6 +3548,7 @@ if (d->pre_reset == NULL) d->pre_reset = default_pre_reset; if (d->capacity == NULL) d->capacity = default_capacity; if (d->special == NULL) d->special = default_special; + if (d->init == NULL) d->init = default_init; if (d->reinit == NULL) d->reinit = default_reinit; } @@ -3841,15 +3576,15 @@ { unsigned long flags; - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ - if (version != IDE_SUBDRIVER_VERSION || !drive->present || drive->driver != NULL || drive->busy || drive->usage) { - restore_flags(flags); /* all CPUs */ + spin_lock_irqsave(&io_request_lock, flags); + if (version != IDE_SUBDRIVER_VERSION || !drive->present || + drive->driver != NULL || drive->busy || drive->usage) { + spin_unlock_irqrestore(&io_request_lock, flags); return 1; } drive->driver = driver; setup_driver_defaults(drive); - restore_flags(flags); /* all CPUs */ + spin_unlock_irqrestore(&io_request_lock, flags); if (drive->autotune != 2) { if (driver->supports_dma && HWIF(drive)->dmaproc != NULL) { /* @@ -3877,10 +3612,10 @@ { unsigned long flags; - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ - if (drive->usage || drive->busy || drive->driver == NULL || DRIVER(drive)->busy) { - restore_flags(flags); /* all CPUs */ + spin_lock_irqsave(&io_request_lock, flags); + if (drive->usage || drive->busy || + drive->driver == NULL || DRIVER(drive)->busy) { + spin_unlock_irqrestore(&io_request_lock, flags); return 1; } #if defined(CONFIG_BLK_DEV_ISAPNP) && defined(CONFIG_ISAPNP) && defined(MODULE) @@ -3892,7 +3627,7 @@ #endif auto_remove_settings(drive); drive->driver = NULL; - restore_flags(flags); /* all CPUs */ + spin_unlock_irqrestore(&io_request_lock, flags); return 0; } @@ -3955,16 +3690,10 @@ EXPORT_SYMBOL(ide_register_subdriver); EXPORT_SYMBOL(ide_unregister_subdriver); EXPORT_SYMBOL(ide_replace_subdriver); -EXPORT_SYMBOL(ide_input_data); -EXPORT_SYMBOL(ide_output_data); -EXPORT_SYMBOL(atapi_input_bytes); -EXPORT_SYMBOL(atapi_output_bytes); -EXPORT_SYMBOL(drive_is_ready); EXPORT_SYMBOL(ide_set_handler); EXPORT_SYMBOL(ide_dump_status); EXPORT_SYMBOL(ide_error); EXPORT_SYMBOL(ide_fixstring); -EXPORT_SYMBOL(ide_wait_stat); EXPORT_SYMBOL(ide_do_reset); EXPORT_SYMBOL(restart_request); EXPORT_SYMBOL(ide_init_drive_cmd); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/ide-cd.c linux.19rc3-ac4/drivers/ide/ide-cd.c --- linux.19rc3/drivers/ide/ide-cd.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/ide-cd.c 2002-07-29 13:58:39.000000000 +0100 @@ -540,7 +540,113 @@ } -static void cdrom_end_request (int uptodate, ide_drive_t *drive) +/* + * This is our end_request replacement function. + */ +static int ide_cdrom_end_request (ide_drive_t *drive, int uptodate) +{ + struct request *rq; + unsigned long flags; + int ret = 1; + + spin_lock_irqsave(&io_request_lock, flags); + rq = HWGROUP(drive)->rq; + + /* + * decide whether to reenable DMA -- 3 is a random magic for now, + * if we DMA timeout more than 3 times, just stay in PIO + */ + if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) { + drive->state = 0; + HWGROUP(drive)->hwif->dmaproc(ide_dma_on, drive); + } + + if (!end_that_request_first(rq, uptodate, drive->name)) { + add_blkdev_randomness(MAJOR(rq->rq_dev)); + blkdev_dequeue_request(rq); + HWGROUP(drive)->rq = NULL; + end_that_request_last(rq); + ret = 0; + } + spin_unlock_irqrestore(&io_request_lock, flags); + return ret; +} + +/* + * Error reporting, in human readable form (luxurious, but a memory hog). + */ +byte ide_cdrom_dump_status (ide_drive_t *drive, const char *msg, byte stat) +{ + unsigned long flags; + byte err = 0; + + local_irq_set(flags); + printk("%s: %s: status=0x%02x", drive->name, msg, stat); +#if FANCY_STATUS_DUMPS + printk(" { "); + if (stat & BUSY_STAT) + printk("Busy "); + else { + if (stat & READY_STAT) printk("DriveReady "); + if (stat & WRERR_STAT) printk("DeviceFault "); + if (stat & SEEK_STAT) printk("SeekComplete "); + if (stat & DRQ_STAT) printk("DataRequest "); + if (stat & ECC_STAT) printk("CorrectedError "); + if (stat & INDEX_STAT) printk("Index "); + if (stat & ERR_STAT) printk("Error "); + } + printk("}"); +#endif /* FANCY_STATUS_DUMPS */ + printk("\n"); + if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) { + err = GET_ERR(); + printk("%s: %s: error=0x%02x", drive->name, msg, err); +#if FANCY_STATUS_DUMPS +#endif /* FANCY_STATUS_DUMPS */ + printk("\n"); + } + local_irq_restore(flags); + return err; +} + +/* + * ide_error() takes action based on the error returned by the drive. + */ +ide_startstop_t ide_cdrom_error (ide_drive_t *drive, const char *msg, byte stat) +{ + struct request *rq; + byte err; + + err = ide_cdrom_dump_status(drive, msg, stat); + if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL) + return ide_stopped; + /* retry only "normal" I/O: */ + if (rq->cmd == IDE_DRIVE_CMD || rq->cmd == IDE_DRIVE_TASK) { + rq->errors = 1; + ide_end_drive_cmd(drive, stat, err); + return ide_stopped; + } + + if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { + /* other bits are useless when BUSY */ + rq->errors |= ERROR_RESET; + } + if (GET_STAT() & (BUSY_STAT|DRQ_STAT)) + /* force an abort */ + OUT_BYTE(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG); + if (rq->errors >= ERROR_MAX) { + DRIVER(drive)->end_request(drive, 0); + } else { + if ((rq->errors & ERROR_RESET) == ERROR_RESET) { + ++rq->errors; + return ide_do_reset(drive); + } + ++rq->errors; + } + return ide_stopped; +} + +static void cdrom_end_request (ide_drive_t *drive, int uptodate) { struct request *rq = HWGROUP(drive)->rq; @@ -554,7 +660,7 @@ if (!rq->current_nr_sectors) uptodate = 1; - ide_end_request (uptodate, HWGROUP(drive)); + ide_cdrom_end_request(drive, uptodate); } @@ -591,8 +697,8 @@ pc = (struct packet_command *) rq->buffer; pc->stat = 1; - cdrom_end_request (1, drive); - *startstop = ide_error (drive, "request sense failure", stat); + cdrom_end_request(drive, 1); + *startstop = DRIVER(drive)->error(drive, "request sense failure", stat); return 1; } else if (rq->cmd == PACKET_COMMAND) { @@ -628,7 +734,7 @@ } pc->stat = 1; - cdrom_end_request (1, drive); + cdrom_end_request(drive, 1); if ((stat & ERR_STAT) != 0) cdrom_queue_request_sense(drive, wait, pc->sense, pc); @@ -641,7 +747,7 @@ /* Fail the request. */ printk ("%s: tray open\n", drive->name); - cdrom_end_request (0, drive); + cdrom_end_request(drive, 0); } else if (sense_key == UNIT_ATTENTION) { /* Media change. */ cdrom_saw_media_change (drive); @@ -650,21 +756,21 @@ But be sure to give up if we've retried too many times. */ if (++rq->errors > ERROR_MAX) - cdrom_end_request (0, drive); + cdrom_end_request(drive, 0); } else if (sense_key == ILLEGAL_REQUEST || sense_key == DATA_PROTECT) { /* No point in retrying after an illegal request or data protect error.*/ ide_dump_status (drive, "command error", stat); - cdrom_end_request (0, drive); + cdrom_end_request(drive, 0); } else if ((err & ~ABRT_ERR) != 0) { /* Go to the default handler for other errors. */ - *startstop = ide_error (drive, "cdrom_decode_status", stat); + *startstop = DRIVER(drive)->error(drive, "cdrom_decode_status", stat); return 1; } else if ((++rq->errors > ERROR_MAX)) { /* We've racked up too many retries. Abort. */ - cdrom_end_request (0, drive); + cdrom_end_request(drive, 0); } /* If we got a CHECK_CONDITION status, @@ -732,24 +838,26 @@ } /* Set up the controller registers. */ - OUT_BYTE (info->dma, IDE_FEATURE_REG); - OUT_BYTE (0, IDE_NSECTOR_REG); - OUT_BYTE (0, IDE_SECTOR_REG); + OUT_BYTE(info->dma, IDE_FEATURE_REG); + OUT_BYTE(0, IDE_NSECTOR_REG); + OUT_BYTE(0, IDE_SECTOR_REG); - OUT_BYTE (xferlen & 0xff, IDE_LCYL_REG); - OUT_BYTE (xferlen >> 8 , IDE_HCYL_REG); + OUT_BYTE(xferlen & 0xff, IDE_LCYL_REG); + OUT_BYTE(xferlen >> 8 , IDE_HCYL_REG); if (IDE_CONTROL_REG) - OUT_BYTE (drive->ctl, IDE_CONTROL_REG); + OUT_BYTE(drive->ctl, IDE_CONTROL_REG); if (info->dma) (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive)); if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) { + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler (drive, handler, WAIT_CMD, cdrom_timer_expiry); - OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */ + OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */ return ide_started; } else { - OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */ + OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */ return (*handler) (drive); } } @@ -786,6 +894,9 @@ return startstop; } + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); + /* Arm the interrupt handler. */ ide_set_handler (drive, handler, timeout, cdrom_timer_expiry); @@ -879,7 +990,7 @@ drive->name, ireason); } - cdrom_end_request (0, drive); + cdrom_end_request(drive, 0); return -1; } @@ -910,16 +1021,16 @@ if (!dma_error) { for (i = rq->nr_sectors; i > 0;) { i -= rq->current_nr_sectors; - ide_end_request(1, HWGROUP(drive)); + ide_cdrom_end_request(drive, 1); } return ide_stopped; } else - return ide_error (drive, "dma error", stat); + return DRIVER(drive)->error(drive, "dma error", stat); } /* Read the interrupt reason and the transfer length. */ - ireason = IN_BYTE (IDE_NSECTOR_REG); - len = IN_BYTE (IDE_LCYL_REG) + 256 * IN_BYTE (IDE_HCYL_REG); + ireason = IN_BYTE(IDE_NSECTOR_REG); + len = IN_BYTE(IDE_LCYL_REG) + 256 * IN_BYTE(IDE_HCYL_REG); /* If DRQ is clear, the command has completed. */ if ((stat & DRQ_STAT) == 0) { @@ -928,9 +1039,9 @@ if (rq->current_nr_sectors > 0) { printk ("%s: cdrom_read_intr: data underrun (%ld blocks)\n", drive->name, rq->current_nr_sectors); - cdrom_end_request (0, drive); + cdrom_end_request(drive, 0); } else - cdrom_end_request (1, drive); + cdrom_end_request(drive, 1); return ide_stopped; } @@ -950,7 +1061,7 @@ printk (" Trying to limit transfer sizes\n"); CDROM_CONFIG_FLAGS (drive)->limit_nframes = 1; } - cdrom_end_request (0, drive); + cdrom_end_request(drive, 0); return ide_stopped; } @@ -979,7 +1090,7 @@ /* If we've filled the present buffer but there's another chained buffer after it, move on. */ if (rq->current_nr_sectors == 0 && rq->nr_sectors) - cdrom_end_request (1, drive); + cdrom_end_request(drive, 1); /* If the buffers are full, cache the rest of the data in our internal buffer. */ @@ -1007,8 +1118,10 @@ } } - /* Done moving data! - Wait for another interrupt. */ + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); + + /* Done moving data! Wait for another interrupt. */ ide_set_handler(drive, &cdrom_read_intr, WAIT_CMD, NULL); return ide_started; } @@ -1031,7 +1144,7 @@ rq->sector >= info->sector_buffered && rq->sector < info->sector_buffered + info->nsectors_buffered) { if (rq->current_nr_sectors == 0) - cdrom_end_request (1, drive); + cdrom_end_request(drive, 1); memcpy (rq->buffer, info->buffer + @@ -1046,13 +1159,13 @@ /* If we've satisfied the current request, terminate it successfully. */ if (rq->nr_sectors == 0) { - cdrom_end_request (1, drive); + cdrom_end_request(drive, 1); return -1; } /* Move on to the next buffer if needed. */ if (rq->current_nr_sectors == 0) - cdrom_end_request (1, drive); + cdrom_end_request(drive, 1); /* If this condition does not hold, then the kluge i use to represent the number of sectors to skip at the start of a transfer @@ -1062,7 +1175,7 @@ (rq->sector % SECTORS_PER_FRAME) != 0) { printk ("%s: cdrom_read_from_buffer: buffer botch (%ld)\n", drive->name, rq->sector); - cdrom_end_request (0, drive); + cdrom_end_request(drive, 0); return -1; } @@ -1101,7 +1214,7 @@ (rq->sector % CD_FRAMESIZE != 0)) { printk ("%s: cdrom_start_read_continuation: buffer botch (%lu)\n", drive->name, rq->current_nr_sectors); - cdrom_end_request (0, drive); + cdrom_end_request(drive, 0); return ide_stopped; } sector -= nskip; @@ -1147,7 +1260,7 @@ return startstop; CDROM_CONFIG_FLAGS(drive)->seeking = 1; - if (retry && jiffies - info->start_seek > IDECD_SEEK_TIMER) { + if (retry && time_after(jiffies, info->start_seek + IDECD_SEEK_TIMER)) { if (--retry == 0) { /* * this condition is far too common, to bother @@ -1337,7 +1450,7 @@ } if (pc->buflen == 0) - cdrom_end_request (1, drive); + cdrom_end_request(drive, 1); else { /* Comment this out, because this always happens right after a reset occurs, and it is annoying to @@ -1347,7 +1460,7 @@ drive->name, pc->buflen); */ pc->stat = 1; - cdrom_end_request (1, drive); + cdrom_end_request(drive, 1); } return ide_stopped; } @@ -1398,6 +1511,9 @@ pc->stat = 1; } + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); + /* Now we wait for another interrupt. */ ide_set_handler (drive, &cdrom_pc_intr, WAIT_CMD, cdrom_timer_expiry); return ide_started; @@ -1522,7 +1638,7 @@ drive->name, ireason); } - cdrom_end_request(0, drive); + cdrom_end_request(drive, 0); return 1; } @@ -1554,12 +1670,12 @@ */ if (dma) { if (dma_error) - return ide_error(drive, "dma error", stat); + return DRIVER(drive)->error(drive, "dma error", stat); rq = HWGROUP(drive)->rq; for (i = rq->nr_sectors; i > 0;) { i -= rq->current_nr_sectors; - ide_end_request(1, HWGROUP(drive)); + ide_cdrom_end_request(drive, 1); } return ide_stopped; } @@ -1579,7 +1695,7 @@ drive->name, rq->current_nr_sectors); uptodate = 0; } - cdrom_end_request(uptodate, drive); + cdrom_end_request(drive, uptodate); return ide_stopped; } @@ -1620,9 +1736,12 @@ * current buffer complete, move on */ if (rq->current_nr_sectors == 0 && rq->nr_sectors) - cdrom_end_request (1, drive); + cdrom_end_request(drive, 1); } + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); + /* re-arm handler */ ide_set_handler(drive, &cdrom_write_intr, 5 * WAIT_CMD, NULL); return ide_started; @@ -1662,7 +1781,7 @@ * writes *must* be 2kB frame aligned */ if ((rq->nr_sectors & 3) || (rq->sector & 3)) { - cdrom_end_request(0, drive); + cdrom_end_request(drive, 0); return ide_stopped; } @@ -1698,11 +1817,10 @@ case WRITE: case READ: { if (CDROM_CONFIG_FLAGS(drive)->seeking) { - unsigned long elpased = jiffies - info->start_seek; int stat = GET_STAT(); if ((stat & SEEK_STAT) != SEEK_STAT) { - if (elpased < IDECD_SEEK_TIMEOUT) { + if (time_before(jiffies, info->start_seek + IDECD_SEEK_TIMEOUT)) { ide_stall_queue(drive, IDECD_SEEK_TIMER); return ide_stopped; } @@ -1728,13 +1846,13 @@ } case RESET_DRIVE_COMMAND: { - cdrom_end_request(1, drive); + cdrom_end_request(drive, 1); return ide_do_reset(drive); } default: { printk("ide-cd: bad cmd %d\n", rq->cmd); - cdrom_end_request(0, drive); + cdrom_end_request(drive, 0); return ide_stopped; } } @@ -2963,6 +3081,7 @@ return 0; } +int ide_cdrom_init(void); int ide_cdrom_reinit (ide_drive_t *drive); static ide_driver_t ide_cdrom_driver = { @@ -2970,13 +3089,21 @@ version: IDECD_VERSION, media: ide_cdrom, busy: 0, +#ifdef CONFIG_IDEDMA_ONLYDISK + supports_dma: 0, +#else supports_dma: 1, +#endif supports_dsc_overlap: 1, cleanup: ide_cdrom_cleanup, standby: NULL, + suspend: NULL, + resume: NULL, flushcache: NULL, do_request: ide_do_rw_cdrom, - end_request: NULL, + end_request: ide_cdrom_end_request, + sense: ide_cdrom_dump_status, + error: ide_cdrom_error, ioctl: ide_cdrom_ioctl, open: ide_cdrom_open, release: ide_cdrom_release, @@ -2986,12 +3113,12 @@ capacity: ide_cdrom_capacity, special: NULL, proc: NULL, + init: ide_cdrom_init, reinit: ide_cdrom_reinit, ata_prebuilder: NULL, atapi_prebuilder: NULL, }; -int ide_cdrom_init(void); static ide_module_t ide_cdrom_module = { IDE_DRIVER_MODULE, ide_cdrom_init, diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/ide-cs.c linux.19rc3-ac4/drivers/ide/ide-cs.c --- linux.19rc3/drivers/ide/ide-cs.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/ide-cs.c 2002-07-29 13:58:39.000000000 +0100 @@ -340,12 +340,12 @@ /* retry registration in case device is still spinning up */ for (i = 0; i < 10; i++) { if (ctl_base) - outb(0x02, ctl_base); /* Set nIEN = disable device interrupts */ + OUT_BYTE(0x02, ctl_base); /* Set nIEN = disable device interrupts */ hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ); if (hd >= 0) break; if (link->io.NumPorts1 == 0x20) { if (ctl_base) - outb(0x02, ctl_base+0x10); + OUT_BYTE(0x02, ctl_base+0x10); hd = idecs_register(io_base+0x10, ctl_base+0x10, link->irq.AssignedIRQ); if (hd >= 0) { diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/ide-disk.c linux.19rc3-ac4/drivers/ide/ide-disk.c --- linux.19rc3/drivers/ide/ide-disk.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/ide-disk.c 2002-07-29 13:58:39.000000000 +0100 @@ -1,5 +1,9 @@ /* - * linux/drivers/ide/ide-disk.c Version 1.10 June 9, 2000 + * linux/drivers/ide/ide-disk.c Version 1.16 April 7, 2002 + * + * Copyright (C) 1998-2002 Linux ATA Developemt + * Andre Hedrick + * * * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) */ @@ -29,9 +33,14 @@ * Version 1.10 request queue changes, Ultra DMA 100 * Version 1.11 added 48-bit lba * Version 1.12 adding taskfile io access method + * Version 1.13 added standby and flush-cache for notifier + * Version 1.14 added acoustic-wcache + * Version 1.15 convert all calls to ide_raw_taskfile + * since args will return register content. + * Version 1.16 added suspend-resume-checkpower */ -#define IDEDISK_VERSION "1.12" +#define IDEDISK_VERSION "1.16" #undef REALLY_SLOW_IO /* most systems can safely undef this */ @@ -61,42 +70,16 @@ #define IS_PDC4030_DRIVE (0) /* auto-NULLs out pdc4030 code */ #endif -#ifdef CONFIG_IDE_TASKFILE_IO -# undef __TASKFILE__IO /* define __TASKFILE__IO */ -#else /* CONFIG_IDE_TASKFILE_IO */ -# undef __TASKFILE__IO -#endif /* CONFIG_IDE_TASKFILE_IO */ - -#ifndef __TASKFILE__IO - -static void idedisk_bswap_data (void *buffer, int wcount) -{ - u16 *p = buffer; - - while (wcount--) { - *p = *p << 8 | *p >> 8; p++; - *p = *p << 8 | *p >> 8; p++; - } -} - -static inline void idedisk_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount) -{ - ide_input_data(drive, buffer, wcount); - if (drive->bswap) - idedisk_bswap_data(buffer, wcount); -} +static int driver_blocked; -static inline void idedisk_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount) +static inline u32 idedisk_read_24 (ide_drive_t *drive) { - if (drive->bswap) { - idedisk_bswap_data(buffer, wcount); - ide_output_data(drive, buffer, wcount); - idedisk_bswap_data(buffer, wcount); - } else - ide_output_data(drive, buffer, wcount); + return (IN_BYTE(IDE_HCYL_REG)<<16) | + (IN_BYTE(IDE_LCYL_REG)<<8) | + IN_BYTE(IDE_SECTOR_REG); } -#endif /* __TASKFILE__IO */ +static int idedisk_end_request(ide_drive_t *drive, int uptodate); /* * lba_capacity_is_ok() performs a sanity check on the claimed "lba_capacity" @@ -148,7 +131,7 @@ return 0; /* lba_capacity value may be bad */ } -#ifndef __TASKFILE__IO +#ifndef CONFIG_IDE_TASKFILE_IO /* * read_intr() is the handler for disk read/multread interrupts @@ -163,9 +146,11 @@ /* new way for dealing with premature shared PCI interrupts */ if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) { if (stat & (ERR_STAT|DRQ_STAT)) { - return ide_error(drive, "read_intr", stat); + return DRIVER(drive)->error(drive, "read_intr", stat); } /* no data yet, so wait for another interrupt */ + if (HWGROUP(drive)->handler != NULL) + BUG(); ide_set_handler(drive, &read_intr, WAIT_CMD, NULL); return ide_started; } @@ -179,7 +164,7 @@ msect -= nsect; } else nsect = 1; - idedisk_input_data(drive, rq->buffer, nsect * SECTOR_WORDS); + taskfile_input_data(drive, rq->buffer, nsect * SECTOR_WORDS); #ifdef DEBUG printk("%s: read: sectors(%ld-%ld), buffer=0x%08lx, remaining=%ld\n", drive->name, rq->sector, rq->sector+nsect-1, @@ -190,11 +175,18 @@ rq->errors = 0; i = (rq->nr_sectors -= nsect); if (((long)(rq->current_nr_sectors -= nsect)) <= 0) - ide_end_request(1, HWGROUP(drive)); + idedisk_end_request(drive, 1); + /* + * Another BH Page walker and DATA INTERGRITY Questioned on ERROR. + * If passed back up on multimode read, BAD DATA could be ACKED + * to FILE SYSTEMS above ... + */ if (i > 0) { if (msect) goto read_next; - ide_set_handler (drive, &read_intr, WAIT_CMD, NULL); + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); + ide_set_handler(drive, &read_intr, WAIT_CMD, NULL); return ide_started; } return ide_stopped; @@ -225,17 +217,19 @@ i = --rq->nr_sectors; --rq->current_nr_sectors; if (((long)rq->current_nr_sectors) <= 0) - ide_end_request(1, hwgroup); + idedisk_end_request(drive, 1); if (i > 0) { - idedisk_output_data (drive, rq->buffer, SECTOR_WORDS); - ide_set_handler (drive, &write_intr, WAIT_CMD, NULL); + taskfile_output_data(drive, rq->buffer, SECTOR_WORDS); + if (HWGROUP(drive)->handler != NULL) + BUG(); + ide_set_handler(drive, &write_intr, WAIT_CMD, NULL); return ide_started; } return ide_stopped; } return ide_stopped; /* the original code did this here (?) */ } - return ide_error(drive, "write_intr", stat); + return DRIVER(drive)->error(drive, "write_intr", stat); } /* @@ -248,6 +242,11 @@ * and IRQ context. The IRQ can happen any time after we've output the * full "mcount" number of sectors, so we must make sure we update the * state _before_ we output the final part of the data! + * + * The update and return to BH is a BLOCK Layer Fakey to get more data + * to satisfy the hardware atomic segment. If the hardware atomic segment + * is shorter or smaller than the BH segment then we should be OKAY. + * This is only valid if we can rewind the rq->current_nr_sectors counter. */ int ide_multwrite (ide_drive_t *drive, unsigned int mcount) { @@ -286,7 +285,7 @@ * Ok, we're all setup for the interrupt * re-entering us on the last transfer. */ - idedisk_output_data(drive, buffer, nsect<<7); + taskfile_output_data(drive, buffer, nsect<<7); } while (mcount); return 0; @@ -311,7 +310,9 @@ if (rq->nr_sectors) { if (ide_multwrite(drive, drive->mult_count)) return ide_stopped; - ide_set_handler (drive, &multwrite_intr, WAIT_CMD, NULL); + if (HWGROUP(drive)->handler != NULL) + BUG(); + ide_set_handler(drive, &multwrite_intr, WAIT_CMD, NULL); return ide_started; } } else { @@ -323,18 +324,18 @@ rq = hwgroup->rq; for (i = rq->nr_sectors; i > 0;){ i -= rq->current_nr_sectors; - ide_end_request(1, hwgroup); + idedisk_end_request(drive, 1); } return ide_stopped; } } return ide_stopped; /* the original code did this here (?) */ } - return ide_error(drive, "multwrite_intr", stat); + return DRIVER(drive)->error(drive, "multwrite_intr", stat); } -#endif /* __TASKFILE__IO */ +#endif /* CONFIG_IDE_TASKFILE_IO */ -#ifdef __TASKFILE__IO +#ifdef CONFIG_IDE_TASKFILE_IO static ide_startstop_t chs_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block); static ide_startstop_t lba_28_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block); @@ -353,7 +354,7 @@ goto good_command; printk(KERN_ERR "%s: bad command: %d\n", drive->name, rq->cmd); - ide_end_request(0, HWGROUP(drive)); + idedisk_end_request(drive, 0); return ide_stopped; good_command: @@ -365,7 +366,8 @@ } #endif /* CONFIG_BLK_DEV_PDC4030 */ - if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing)) /* 48-bit LBA */ + if ((drive->id->cfs_enable_2 & 0x0400) && + (drive->addressing == 1)) /* 48-bit LBA */ return lba_48_rw_disk(drive, rq, (unsigned long long) block); if (drive->select.b.lba) /* 28-bit LBA */ return lba_28_rw_disk(drive, rq, (unsigned long) block); @@ -379,7 +381,7 @@ int lba48bit = (drive->id->cfs_enable_2 & 0x0400) ? 1 : 0; #if 1 - lba48bit = drive->addressing; + lba48bit = (drive->addressing == 1) ? 1 : 0; #endif if ((cmd == READ) && (drive->using_dma)) @@ -400,88 +402,63 @@ static ide_startstop_t chs_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - ide_task_t args; - + ide_task_t args; + int sectors; task_ioreg_t command = get_command(drive, rq->cmd); unsigned int track = (block / drive->sect); unsigned int sect = (block % drive->sect) + 1; unsigned int head = (track % drive->head); unsigned int cyl = (track / drive->head); - memset(&taskfile, 0, sizeof(task_struct_t)); - memset(&hobfile, 0, sizeof(hob_struct_t)); - - taskfile.sector_count = (rq->nr_sectors==256)?0x00:rq->nr_sectors; - taskfile.sector_number = sect; - taskfile.low_cylinder = cyl; - taskfile.high_cylinder = (cyl>>8); - taskfile.device_head = head; - taskfile.device_head |= drive->select.all; - taskfile.command = command; - #ifdef DEBUG printk("%s: %sing: ", drive->name, (rq->cmd==READ) ? "read" : "writ"); - if (lba) printk("LBAsect=%lld, ", block); - else printk("CHS=%d/%d/%d, ", cyl, head, sect); + printk("CHS=%d/%d/%d, ", cyl, head, sect); printk("sectors=%ld, ", rq->nr_sectors); printk("buffer=0x%08lx\n", (unsigned long) rq->buffer); #endif - memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr)); - memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr)); - args.command_type = ide_cmd_type_parser(&args); - args.prehandler = ide_pre_handler_parser(&taskfile, &hobfile); - args.handler = ide_handler_parser(&taskfile, &hobfile); - args.posthandler = NULL; - args.rq = (struct request *) rq; - args.block = block; - rq->special = NULL; - rq->special = (ide_task_t *)&args; + memset(&args, 0, sizeof(ide_task_t)); + sectors = (rq->nr_sectors == 256) ? 0x00 : rq->nr_sectors; + args.tfRegister[IDE_NSECTOR_OFFSET] = sectors; + args.tfRegister[IDE_SECTOR_OFFSET] = sect; + args.tfRegister[IDE_LCYL_OFFSET] = cyl; + args.tfRegister[IDE_HCYL_OFFSET] = (cyl>>8); + args.tfRegister[IDE_SELECT_OFFSET] = head; + args.tfRegister[IDE_SELECT_OFFSET] |= drive->select.all; + args.tfRegister[IDE_COMMAND_OFFSET] = command; + args.command_type = ide_cmd_type_parser(&args); + args.rq = (struct request *) rq; + rq->special = (ide_task_t *)&args; return do_rw_taskfile(drive, &args); } static ide_startstop_t lba_28_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - ide_task_t args; - + ide_task_t args; + int sectors; task_ioreg_t command = get_command(drive, rq->cmd); - memset(&taskfile, 0, sizeof(task_struct_t)); - memset(&hobfile, 0, sizeof(hob_struct_t)); - - taskfile.sector_count = (rq->nr_sectors==256)?0x00:rq->nr_sectors; - taskfile.sector_number = block; - taskfile.low_cylinder = (block>>=8); - taskfile.high_cylinder = (block>>=8); - taskfile.device_head = ((block>>8)&0x0f); - taskfile.device_head |= drive->select.all; - taskfile.command = command; - - #ifdef DEBUG printk("%s: %sing: ", drive->name, (rq->cmd==READ) ? "read" : "writ"); - if (lba) printk("LBAsect=%lld, ", block); - else printk("CHS=%d/%d/%d, ", cyl, head, sect); + printk("LBAsect=%lld, ", block); printk("sectors=%ld, ", rq->nr_sectors); printk("buffer=0x%08lx\n", (unsigned long) rq->buffer); #endif - memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr)); - memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr)); - args.command_type = ide_cmd_type_parser(&args); - args.prehandler = ide_pre_handler_parser(&taskfile, &hobfile); - args.handler = ide_handler_parser(&taskfile, &hobfile); - args.posthandler = NULL; - args.rq = (struct request *) rq; - args.block = block; - rq->special = NULL; - rq->special = (ide_task_t *)&args; + memset(&args, 0, sizeof(ide_task_t)); + sectors = (rq->nr_sectors == 256) ? 0x00 : rq->nr_sectors; + args.tfRegister[IDE_NSECTOR_OFFSET] = sectors; + args.tfRegister[IDE_SECTOR_OFFSET] = block; + args.tfRegister[IDE_LCYL_OFFSET] = (block>>=8); + args.tfRegister[IDE_HCYL_OFFSET] = (block>>=8); + args.tfRegister[IDE_SELECT_OFFSET] = ((block>>8)&0x0f); + args.tfRegister[IDE_SELECT_OFFSET] |= drive->select.all; + args.tfRegister[IDE_COMMAND_OFFSET] = command; + args.command_type = ide_cmd_type_parser(&args); + args.rq = (struct request *) rq; + rq->special = (ide_task_t *)&args; return do_rw_taskfile(drive, &args); } @@ -493,57 +470,40 @@ static ide_startstop_t lba_48_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long long block) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - ide_task_t args; - + ide_task_t args; + int sectors; task_ioreg_t command = get_command(drive, rq->cmd); - memset(&taskfile, 0, sizeof(task_struct_t)); - memset(&hobfile, 0, sizeof(hob_struct_t)); - - taskfile.sector_count = rq->nr_sectors; - hobfile.sector_count = (rq->nr_sectors>>8); - - if (rq->nr_sectors == 65536) { - taskfile.sector_count = 0x00; - hobfile.sector_count = 0x00; - } - - taskfile.sector_number = block; /* low lba */ - taskfile.low_cylinder = (block>>=8); /* mid lba */ - taskfile.high_cylinder = (block>>=8); /* hi lba */ - hobfile.sector_number = (block>>=8); /* low lba */ - hobfile.low_cylinder = (block>>=8); /* mid lba */ - hobfile.high_cylinder = (block>>=8); /* hi lba */ - taskfile.device_head = drive->select.all; - hobfile.device_head = taskfile.device_head; - hobfile.control = (drive->ctl|0x80); - taskfile.command = command; - #ifdef DEBUG printk("%s: %sing: ", drive->name, (rq->cmd==READ) ? "read" : "writ"); - if (lba) printk("LBAsect=%lld, ", block); - else printk("CHS=%d/%d/%d, ", cyl, head, sect); + printk("LBAsect=%lld, ", block); printk("sectors=%ld, ", rq->nr_sectors); printk("buffer=0x%08lx\n", (unsigned long) rq->buffer); #endif - memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr)); - memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr)); - args.command_type = ide_cmd_type_parser(&args); - args.prehandler = ide_pre_handler_parser(&taskfile, &hobfile); - args.handler = ide_handler_parser(&taskfile, &hobfile); - args.posthandler = NULL; - args.rq = (struct request *) rq; - args.block = block; - rq->special = NULL; - rq->special = (ide_task_t *)&args; + memset(&args, 0, sizeof(ide_task_t)); + sectors = (rq->nr_sectors == 65536) ? 0 : rq->nr_sectors; + args.tfRegister[IDE_NSECTOR_OFFSET] = sectors; + args.tfRegister[IDE_SECTOR_OFFSET] = block; /* low lba */ + args.tfRegister[IDE_LCYL_OFFSET] = (block>>=8); /* mid lba */ + args.tfRegister[IDE_HCYL_OFFSET] = (block>>=8); /* hi lba */ + args.tfRegister[IDE_SELECT_OFFSET] = drive->select.all; + args.tfRegister[IDE_COMMAND_OFFSET] = command; + args.hobRegister[IDE_NSECTOR_OFFSET_HOB]= sectors >> 8; + args.hobRegister[IDE_SECTOR_OFFSET_HOB] = (block>>=8); /* low lba */ + args.hobRegister[IDE_LCYL_OFFSET_HOB] = (block>>=8); /* mid lba */ + args.hobRegister[IDE_HCYL_OFFSET_HOB] = (block>>=8); /* hi lba */ + args.hobRegister[IDE_SELECT_OFFSET_HOB] = drive->select.all; + args.hobRegister[IDE_CONTROL_OFFSET_HOB]= (drive->ctl|0x80); + args.command_type = ide_cmd_type_parser(&args); + args.rq = (struct request *) rq; + rq->special = (ide_task_t *)&args; return do_rw_taskfile(drive, &args); } -#else /* !__TASKFILE__IO */ +#else /* !CONFIG_IDE_TASKFILE_IO */ + /* * do_rw_disk() issues READ and WRITE commands to a disk, * using LBA if supported, or CHS otherwise, to address sectors. @@ -551,6 +511,8 @@ */ static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block) { + if (driver_blocked) + panic("Request while ide driver is blocked?"); if (IDE_CONTROL_REG) OUT_BYTE(drive->ctl,IDE_CONTROL_REG); @@ -560,7 +522,8 @@ if (drive->select.b.lba) { #endif /* CONFIG_BLK_DEV_PDC4030 */ - if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing)) { + if ((drive->id->cfs_enable_2 & 0x0400) && + (drive->addressing == 1)) { task_ioreg_t tasklets[10]; tasklets[0] = 0; @@ -647,8 +610,11 @@ if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_read, drive))) return ide_started; #endif /* CONFIG_BLK_DEV_IDEDMA */ + if (HWGROUP(drive)->handler != NULL) + BUG(); ide_set_handler(drive, &read_intr, WAIT_CMD, NULL); - if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing)) { + if ((drive->id->cfs_enable_2 & 0x0400) && + (drive->addressing == 1)) { OUT_BYTE(drive->mult_count ? WIN_MULTREAD_EXT : WIN_READ_EXT, IDE_COMMAND_REG); } else { OUT_BYTE(drive->mult_count ? WIN_MULTREAD : WIN_READ, IDE_COMMAND_REG); @@ -661,7 +627,8 @@ if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_write, drive))) return ide_started; #endif /* CONFIG_BLK_DEV_IDEDMA */ - if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing)) { + if ((drive->id->cfs_enable_2 & 0x0400) && + (drive->addressing == 1)) { OUT_BYTE(drive->mult_count ? WIN_MULTWRITE_EXT : WIN_WRITE_EXT, IDE_COMMAND_REG); } else { OUT_BYTE(drive->mult_count ? WIN_MULTWRITE : WIN_WRITE, IDE_COMMAND_REG); @@ -672,7 +639,7 @@ return startstop; } if (!drive->unmask) - __cli(); /* local CPU only */ + local_irq_disable(); if (drive->mult_count) { ide_hwgroup_t *hwgroup = HWGROUP(drive); /* @@ -683,8 +650,12 @@ * before returning. Fortunately, this NEVER happens (right?). * * Except when you get an error it seems... + * + * MAJOR DATA INTEGRITY BUG !!! only if we error */ hwgroup->wrq = *rq; /* scratchpad */ + if (HWGROUP(drive)->handler != NULL) + BUG(); ide_set_handler(drive, &multwrite_intr, WAIT_CMD, NULL); if (ide_multwrite(drive, drive->mult_count)) { unsigned long flags; @@ -695,34 +666,35 @@ return ide_stopped; } } else { - ide_set_handler (drive, &write_intr, WAIT_CMD, NULL); - idedisk_output_data(drive, rq->buffer, SECTOR_WORDS); + if (HWGROUP(drive)->handler != NULL) + BUG(); + ide_set_handler(drive, &write_intr, WAIT_CMD, NULL); + taskfile_output_data(drive, rq->buffer, SECTOR_WORDS); } return ide_started; } printk(KERN_ERR "%s: bad command: %d\n", drive->name, rq->cmd); - ide_end_request(0, HWGROUP(drive)); + idedisk_end_request(drive, 0); return ide_stopped; } -#endif /* __TASKFILE__IO */ +#endif /* CONFIG_IDE_TASKFILE_IO */ static int idedisk_open (struct inode *inode, struct file *filp, ide_drive_t *drive) { MOD_INC_USE_COUNT; if (drive->removable && drive->usage == 1) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - taskfile.command = WIN_DOORLOCK; + ide_task_t args; + memset(&args, 0, sizeof(ide_task_t)); + args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORLOCK; + args.command_type = ide_cmd_type_parser(&args); check_disk_change(inode->i_rdev); /* * Ignore the return code from door_lock, * since the open() has already succeeded, * and the door_lock is irrelevant at this point. */ - if (drive->doorlocking && ide_wait_taskfile(drive, &taskfile, &hobfile, NULL)) + if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL)) drive->doorlocking = 0; } return 0; @@ -733,13 +705,12 @@ static void idedisk_release (struct inode *inode, struct file *filp, ide_drive_t *drive) { if (drive->removable && !drive->usage) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - taskfile.command = WIN_DOORUNLOCK; + ide_task_t args; + memset(&args, 0, sizeof(ide_task_t)); + args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORUNLOCK; + args.command_type = ide_cmd_type_parser(&args); invalidate_bdev(inode->i_bdev, 0); - if (drive->doorlocking && ide_wait_taskfile(drive, &taskfile, &hobfile, NULL)) + if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL)) drive->doorlocking = 0; } if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache) @@ -761,6 +732,190 @@ current_capacity(drive)); } +static int idedisk_end_request (ide_drive_t *drive, int uptodate) +{ + struct request *rq; + unsigned long flags; + int ret = 1; + + spin_lock_irqsave(&io_request_lock, flags); + rq = HWGROUP(drive)->rq; + + /* + * decide whether to reenable DMA -- 3 is a random magic for now, + * if we DMA timeout more than 3 times, just stay in PIO + */ + if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) { + drive->state = 0; + HWGROUP(drive)->hwif->dmaproc(ide_dma_on, drive); + } + + if (!end_that_request_first(rq, uptodate, drive->name)) { + add_blkdev_randomness(MAJOR(rq->rq_dev)); + blkdev_dequeue_request(rq); + HWGROUP(drive)->rq = NULL; + end_that_request_last(rq); + ret = 0; + } + spin_unlock_irqrestore(&io_request_lock, flags); + return ret; +} + +static byte idedisk_dump_status (ide_drive_t *drive, const char *msg, byte stat) +{ + unsigned long flags; + byte err = 0; + + local_irq_set(flags); + printk("%s: %s: status=0x%02x", drive->name, msg, stat); +#if FANCY_STATUS_DUMPS + printk(" { "); + if (stat & BUSY_STAT) + printk("Busy "); + else { + if (stat & READY_STAT) printk("DriveReady "); + if (stat & WRERR_STAT) printk("DeviceFault "); + if (stat & SEEK_STAT) printk("SeekComplete "); + if (stat & DRQ_STAT) printk("DataRequest "); + if (stat & ECC_STAT) printk("CorrectedError "); + if (stat & INDEX_STAT) printk("Index "); + if (stat & ERR_STAT) printk("Error "); + } + printk("}"); +#endif /* FANCY_STATUS_DUMPS */ + printk("\n"); + if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) { + err = GET_ERR(); + printk("%s: %s: error=0x%02x", drive->name, msg, err); +#if FANCY_STATUS_DUMPS + printk(" { "); + if (err & ABRT_ERR) printk("DriveStatusError "); + if (err & ICRC_ERR) printk("%s", (err & ABRT_ERR) ? "BadCRC " : "BadSector "); + if (err & ECC_ERR) printk("UncorrectableError "); + if (err & ID_ERR) printk("SectorIdNotFound "); + if (err & TRK0_ERR) printk("TrackZeroNotFound "); + if (err & MARK_ERR) printk("AddrMarkNotFound "); + printk("}"); + if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR || (err & (ECC_ERR|ID_ERR|MARK_ERR))) { + if ((drive->id->command_set_2 & 0x0400) && + (drive->id->cfs_enable_2 & 0x0400) && + (drive->addressing == 1)) { + __u64 sectors = 0; + u32 low = 0, high = 0; + low = idedisk_read_24(drive); + OUT_BYTE(drive->ctl|0x80, IDE_CONTROL_REG); + high = idedisk_read_24(drive); + sectors = ((__u64)high << 24) | low; + printk(", LBAsect=%llu, high=%d, low=%d", + (unsigned long long) sectors, + high, low); + } else { + byte cur = IN_BYTE(IDE_SELECT_REG); + if (cur & 0x40) { /* using LBA? */ + printk(", LBAsect=%ld", (unsigned long) + ((cur&0xf)<<24) + |(IN_BYTE(IDE_HCYL_REG)<<16) + |(IN_BYTE(IDE_LCYL_REG)<<8) + | IN_BYTE(IDE_SECTOR_REG)); + } else { + printk(", CHS=%d/%d/%d", + (IN_BYTE(IDE_HCYL_REG)<<8) + + IN_BYTE(IDE_LCYL_REG), + cur & 0xf, + IN_BYTE(IDE_SECTOR_REG)); + } + } + if (HWGROUP(drive) && HWGROUP(drive)->rq) + printk(", sector=%ld", HWGROUP(drive)->rq->sector); + } + } +#endif /* FANCY_STATUS_DUMPS */ + printk("\n"); + local_irq_restore(flags); + return err; +} + +ide_startstop_t idedisk_error (ide_drive_t *drive, const char *msg, byte stat) +{ + struct request *rq; + byte err; + int i = (drive->mult_count ? drive->mult_count : 1) * SECTOR_WORDS; + + err = idedisk_dump_status(drive, msg, stat); + + if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL) + return ide_stopped; + /* retry only "normal" I/O: */ + switch (rq->cmd) { + case IDE_DRIVE_CMD: + case IDE_DRIVE_TASK: + case IDE_DRIVE_TASKFILE: + rq->errors = 1; + ide_end_drive_cmd(drive, stat, err); + return ide_stopped; +#if 0 + case IDE_DRIVE_TASKFILE: + rq->errors = 1; + ide_end_taskfile(drive, stat, err); + return ide_stopped; +#endif + default: + break; + } + + if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { + /* other bits are useless when BUSY */ + rq->errors |= ERROR_RESET; + } else if (stat & ERR_STAT) { + /* err has different meaning on cdrom and tape */ + if (err == ABRT_ERR) { + if (drive->select.b.lba && + /* some newer drives don't support WIN_SPECIFY */ + IN_BYTE(IDE_COMMAND_REG) == WIN_SPECIFY) + return ide_stopped; + } else if ((err & (ABRT_ERR | ICRC_ERR)) == (ABRT_ERR | ICRC_ERR)) { + /* UDMA crc error, just retry the operation */ + drive->crc_count++; + } else if (err & (BBD_ERR | ECC_ERR)) + /* retries won't help these */ + rq->errors = ERROR_MAX; + else if (err & TRK0_ERR) + /* help it find track zero */ + rq->errors |= ERROR_RECAL; + } + if ((stat & DRQ_STAT) && rq->cmd != WRITE) { + /* + * try_to_flush_leftover_data() is invoked in response to + * a drive unexpectedly having its DRQ_STAT bit set. As + * an alternative to resetting the drive, this routine + * tries to clear the condition by read a sector's worth + * of data from the drive. Of course, this may not help + * if the drive is *waiting* for data from *us*. + */ + while (i > 0) { + u32 buffer[16]; + unsigned int wcount = (i > 16) ? 16 : i; + i -= wcount; + ata_input_data(drive, buffer, wcount); + } + } + if (GET_STAT() & (BUSY_STAT|DRQ_STAT)) + /* force an abort */ + OUT_BYTE(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG); + if (rq->errors >= ERROR_MAX) + DRIVER(drive)->end_request(drive, 0); + else { + if ((rq->errors & ERROR_RESET) == ERROR_RESET) { + ++rq->errors; + return ide_do_reset(drive); + } + if ((rq->errors & ERROR_RECAL) == ERROR_RECAL) + drive->special.b.recalibrate = 1; + ++rq->errors; + } + return ide_stopped; +} + /* * Queries for true maximum capacity of the drive. * Returns maximum LBA address (> 0) of the drive, 0 if failed. @@ -770,16 +925,17 @@ ide_task_t args; unsigned long addr = 0; +#if 0 if (!(drive->id->command_set_1 & 0x0400) && !(drive->id->cfs_enable_2 & 0x0100)) return addr; +#endif /* Create IDE/ATA command request structure */ memset(&args, 0, sizeof(ide_task_t)); args.tfRegister[IDE_SELECT_OFFSET] = 0x40; args.tfRegister[IDE_COMMAND_OFFSET] = WIN_READ_NATIVE_MAX; - args.handler = task_no_data_intr; - + args.command_type = ide_cmd_type_parser(&args); /* submit command request */ ide_raw_taskfile(drive, &args, NULL); @@ -804,8 +960,7 @@ args.tfRegister[IDE_SELECT_OFFSET] = 0x40; args.tfRegister[IDE_COMMAND_OFFSET] = WIN_READ_NATIVE_MAX_EXT; - args.handler = task_no_data_intr; - + args.command_type = ide_cmd_type_parser(&args); /* submit command request */ ide_raw_taskfile(drive, &args, NULL); @@ -841,7 +996,7 @@ args.tfRegister[IDE_HCYL_OFFSET] = ((addr_req >> 16) & 0xff); args.tfRegister[IDE_SELECT_OFFSET] = ((addr_req >> 24) & 0x0f) | 0x40; args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SET_MAX; - args.handler = task_no_data_intr; + args.command_type = ide_cmd_type_parser(&args); /* submit command request */ ide_raw_taskfile(drive, &args, NULL); /* if OK, read new maximum address value */ @@ -873,7 +1028,7 @@ args.hobRegister[IDE_HCYL_OFFSET_HOB] = ((addr_req >>= 8) & 0xff); args.hobRegister[IDE_SELECT_OFFSET_HOB] = 0x40; args.hobRegister[IDE_CONTROL_OFFSET_HOB]= (drive->ctl|0x80); - args.handler = task_no_data_intr; + args.command_type = ide_cmd_type_parser(&args); /* submit command request */ ide_raw_taskfile(drive, &args, NULL); /* if OK, compute maximum address value */ @@ -889,6 +1044,8 @@ return addr_set; } +#endif /* CONFIG_IDEDISK_STROKE */ + /* * Tests if the drive supports Host Protected Area feature. * Returns true if supported, false otherwise. @@ -896,12 +1053,11 @@ static inline int idedisk_supports_host_protected_area(ide_drive_t *drive) { int flag = (drive->id->cfs_enable_1 & 0x0400) ? 1 : 0; - printk("%s: host protected area => %d\n", drive->name, flag); + if (flag) + printk("%s: host protected area => %d\n", drive->name, flag); return flag; } -#endif /* CONFIG_IDEDISK_STROKE */ - /* * Compute drive->capacity, the full capacity of the drive * Called with drive->id != NULL. @@ -927,6 +1083,8 @@ drive->capacity48 = 0; drive->select.b.lba = 0; + (void) idedisk_supports_host_protected_area(drive); + if (id->cfs_enable_2 & 0x0400) { capacity_2 = id->lba_capacity_2; drive->head = drive->bios_head = 255; @@ -949,6 +1107,7 @@ drive->name, set_max_ext, capacity_2); #endif /* CONFIG_IDEDISK_STROKE */ } + drive->cyl = (unsigned int) capacity_2 / (drive->head * drive->sect); drive->bios_cyl = drive->cyl; drive->capacity48 = capacity_2; drive->capacity = (unsigned long) capacity_2; @@ -979,7 +1138,7 @@ drive->capacity = capacity; if ((id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400)) { - drive->capacity48 = id->lba_capacity_2; + drive->capacity48 = id->lba_capacity_2; drive->head = 255; drive->sect = 63; drive->cyl = (unsigned long)(drive->capacity48) / (drive->head * drive->sect); @@ -998,47 +1157,40 @@ special_t *s = &drive->special; if (s->b.set_geometry) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - ide_handler_t *handler = NULL; - - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - s->b.set_geometry = 0; - taskfile.sector_number = drive->sect; - taskfile.low_cylinder = drive->cyl; - taskfile.high_cylinder = drive->cyl>>8; - taskfile.device_head = ((drive->head-1)|drive->select.all)&0xBF; if (!IS_PDC4030_DRIVE) { - taskfile.sector_count = drive->sect; - taskfile.command = WIN_SPECIFY; - handler = ide_handler_parser(&taskfile, &hobfile); + ide_task_t args; + memset(&args, 0, sizeof(ide_task_t)); + args.tfRegister[IDE_NSECTOR_OFFSET] = drive->sect; + args.tfRegister[IDE_SECTOR_OFFSET] = drive->sect; + args.tfRegister[IDE_LCYL_OFFSET] = drive->cyl; + args.tfRegister[IDE_HCYL_OFFSET] = drive->cyl>>8; + args.tfRegister[IDE_SELECT_OFFSET] = ((drive->head-1)|drive->select.all)&0xBF; + args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SPECIFY; + args.command_type = ide_cmd_type_parser(&args); + do_rw_taskfile(drive, &args); } - do_taskfile(drive, &taskfile, &hobfile, handler); } else if (s->b.recalibrate) { s->b.recalibrate = 0; if (!IS_PDC4030_DRIVE) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - taskfile.sector_count = drive->sect; - taskfile.command = WIN_RESTORE; - do_taskfile(drive, &taskfile, &hobfile, ide_handler_parser(&taskfile, &hobfile)); + ide_task_t args; + memset(&args, 0, sizeof(ide_task_t)); + args.tfRegister[IDE_NSECTOR_OFFSET] = drive->sect; + args.tfRegister[IDE_COMMAND_OFFSET] = WIN_RESTORE; + args.command_type = ide_cmd_type_parser(&args); + do_rw_taskfile(drive, &args); } } else if (s->b.set_multmode) { s->b.set_multmode = 0; if (drive->id && drive->mult_req > drive->id->max_multsect) drive->mult_req = drive->id->max_multsect; if (!IS_PDC4030_DRIVE) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - taskfile.sector_count = drive->mult_req; - taskfile.command = WIN_SETMULT; - do_taskfile(drive, &taskfile, &hobfile, ide_handler_parser(&taskfile, &hobfile)); + ide_task_t args; + memset(&args, 0, sizeof(ide_task_t)); + args.tfRegister[IDE_NSECTOR_OFFSET] = drive->mult_req; + args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETMULT; + args.command_type = ide_cmd_type_parser(&args); + do_rw_taskfile(drive, &args); } } else if (s->all) { int special = s->all; @@ -1068,45 +1220,44 @@ static int smart_enable(ide_drive_t *drive) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - taskfile.feature = SMART_ENABLE; - taskfile.low_cylinder = SMART_LCYL_PASS; - taskfile.high_cylinder = SMART_HCYL_PASS; - taskfile.command = WIN_SMART; - return ide_wait_taskfile(drive, &taskfile, &hobfile, NULL); + ide_task_t args; + + memset(&args, 0, sizeof(ide_task_t)); + args.tfRegister[IDE_FEATURE_OFFSET] = SMART_ENABLE; + args.tfRegister[IDE_LCYL_OFFSET] = SMART_LCYL_PASS; + args.tfRegister[IDE_HCYL_OFFSET] = SMART_HCYL_PASS; + args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SMART; + args.command_type = ide_cmd_type_parser(&args); + return ide_raw_taskfile(drive, &args, NULL); } static int get_smart_values(ide_drive_t *drive, byte *buf) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - taskfile.feature = SMART_READ_VALUES; - taskfile.sector_count = 0x01; - taskfile.low_cylinder = SMART_LCYL_PASS; - taskfile.high_cylinder = SMART_HCYL_PASS; - taskfile.command = WIN_SMART; + ide_task_t args; + + memset(&args, 0, sizeof(ide_task_t)); + args.tfRegister[IDE_FEATURE_OFFSET] = SMART_READ_VALUES; + args.tfRegister[IDE_NSECTOR_OFFSET] = 0x01; + args.tfRegister[IDE_LCYL_OFFSET] = SMART_LCYL_PASS; + args.tfRegister[IDE_HCYL_OFFSET] = SMART_HCYL_PASS; + args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SMART; + args.command_type = ide_cmd_type_parser(&args); (void) smart_enable(drive); - return ide_wait_taskfile(drive, &taskfile, &hobfile, buf); + return ide_raw_taskfile(drive, &args, buf); } static int get_smart_thresholds(ide_drive_t *drive, byte *buf) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - taskfile.feature = SMART_READ_THRESHOLDS; - taskfile.sector_count = 0x01; - taskfile.low_cylinder = SMART_LCYL_PASS; - taskfile.high_cylinder = SMART_HCYL_PASS; - taskfile.command = WIN_SMART; + ide_task_t args; + memset(&args, 0, sizeof(ide_task_t)); + args.tfRegister[IDE_FEATURE_OFFSET] = SMART_READ_THRESHOLDS; + args.tfRegister[IDE_NSECTOR_OFFSET] = 0x01; + args.tfRegister[IDE_LCYL_OFFSET] = SMART_LCYL_PASS; + args.tfRegister[IDE_HCYL_OFFSET] = SMART_HCYL_PASS; + args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SMART; + args.command_type = ide_cmd_type_parser(&args); (void) smart_enable(drive); - return ide_wait_taskfile(drive, &taskfile, &hobfile, buf); + return ide_raw_taskfile(drive, &args, buf); } static int proc_idedisk_read_cache @@ -1175,23 +1326,12 @@ #endif /* CONFIG_PROC_FS */ +/* + * This is tightly woven into the driver->do_special can not touch. + * DON'T do it again until a total personality rewrite is committed. + */ static int set_multcount(ide_drive_t *drive, int arg) { -#ifdef __TASKFILE__IO - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - - if (drive->special.b.set_multmode) - return -EBUSY; - - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - taskfile.sector_count = drive->mult_req; - taskfile.command = WIN_SETMULT; - drive->mult_req = arg; - drive->special.b.set_multmode = 1; - ide_wait_taskfile(drive, &taskfile, &hobfile, NULL); -#else /* !__TASKFILE__IO */ struct request rq; if (drive->special.b.set_multmode) @@ -1201,7 +1341,6 @@ drive->mult_req = arg; drive->special.b.set_multmode = 1; (void) ide_do_drive_cmd (drive, &rq, ide_wait); -#endif /* __TASKFILE__IO */ return (drive->mult_count == arg) ? 0 : -EIO; } @@ -1217,57 +1356,112 @@ static int write_cache (ide_drive_t *drive, int arg) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - taskfile.feature = (arg) ? SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE; - taskfile.command = WIN_SETFEATURES; + ide_task_t args; if (!(drive->id->cfs_enable_2 & 0x3000)) return 1; - (void) ide_wait_taskfile(drive, &taskfile, &hobfile, NULL); + memset(&args, 0, sizeof(ide_task_t)); + args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ? + SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE; + args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETFEATURES; + args.command_type = ide_cmd_type_parser(&args); + (void) ide_raw_taskfile(drive, &args, NULL); + drive->wcache = arg; return 0; } +static int call_idedisk_standby (ide_drive_t *drive, int arg) +{ + ide_task_t args; + byte standby = (arg) ? WIN_STANDBYNOW2 : WIN_STANDBYNOW1; + memset(&args, 0, sizeof(ide_task_t)); + args.tfRegister[IDE_COMMAND_OFFSET] = standby; + args.command_type = ide_cmd_type_parser(&args); + return ide_raw_taskfile(drive, &args, NULL); +} + static int do_idedisk_standby (ide_drive_t *drive) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - taskfile.command = WIN_STANDBYNOW1; - return ide_wait_taskfile(drive, &taskfile, &hobfile, NULL); + return call_idedisk_standby(drive, 0); +} + +static int call_idedisk_suspend (ide_drive_t *drive, int arg) +{ + ide_task_t args; + byte suspend = (arg) ? WIN_SLEEPNOW2 : WIN_SLEEPNOW1; + memset(&args, 0, sizeof(ide_task_t)); + args.tfRegister[IDE_COMMAND_OFFSET] = suspend; + args.command_type = ide_cmd_type_parser(&args); + return ide_raw_taskfile(drive, &args, NULL); +} + +static int do_idedisk_suspend (ide_drive_t *drive) +{ + if (drive->suspend_reset) + return 1; + + return call_idedisk_suspend(drive, 0); +} + +#if 0 +static int call_idedisk_checkpower (ide_drive_t *drive, int arg) +{ + ide_task_t args; + byte ckpw = (arg) ? WIN_CHECKPOWERMODE2 : WIN_CHECKPOWERMODE1; + memset(&args, 0, sizeof(ide_task_t)); + args.tfRegister[IDE_COMMAND_OFFSET] = ckpw; + args.command_type = ide_cmd_type_parser(&args); + ide_raw_taskfile(drive, &args, NULL); +#if 0 +if (errno != EIO || args[0] != 0 || args[1] != 0) + state = "unknown"; +else + state = "sleeping"; +} else { + state = (args[2] == 255) ? "active/idle" : "standby"; +#endif + return 0; +} + +static int do_idedisk_checkpower (ide_drive_t *drive) +{ + return call_idedisk_checkpower(drive, 0); +} +#endif + +static int do_idedisk_resume (ide_drive_t *drive) +{ + if (!drive->suspend_reset) + return 1; + return 0; } static int do_idedisk_flushcache (ide_drive_t *drive) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - if (drive->id->cfs_enable_2 & 0x2400) { - taskfile.command = WIN_FLUSH_CACHE_EXT; - } else { - taskfile.command = WIN_FLUSH_CACHE; - } - return ide_wait_taskfile(drive, &taskfile, &hobfile, NULL); + ide_task_t args; + + memset(&args, 0, sizeof(ide_task_t)); + if (drive->id->cfs_enable_2 & 0x2400) + args.tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE_EXT; + else + args.tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE; + args.command_type = ide_cmd_type_parser(&args); + return ide_raw_taskfile(drive, &args, NULL); } static int set_acoustic (ide_drive_t *drive, int arg) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - - taskfile.feature = (arg)?SETFEATURES_EN_AAM:SETFEATURES_DIS_AAM; - taskfile.sector_count = arg; + ide_task_t args; - taskfile.command = WIN_SETFEATURES; - (void) ide_wait_taskfile(drive, &taskfile, &hobfile, NULL); + memset(&args, 0, sizeof(ide_task_t)); + args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ? SETFEATURES_EN_AAM : + SETFEATURES_DIS_AAM; + args.tfRegister[IDE_NSECTOR_OFFSET] = arg; + args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETFEATURES; + args.command_type = ide_cmd_type_parser(&args); + ide_raw_taskfile(drive, &args, NULL); drive->acoustic = arg; return 0; } @@ -1276,9 +1470,11 @@ { drive->addressing = 0; + if (HWIF(drive)->addressing) + return 0; + if (!(drive->id->cfs_enable_2 & 0x0400)) return -EIO; - drive->addressing = arg; return 0; } @@ -1345,6 +1541,14 @@ break; } +#if 1 + (void) probe_lba_addressing(drive, 1); +#else + /* if using 48-bit addressing bump the request size up */ + if (probe_lba_addressing(drive, 1)) + blk_queue_max_sectors(&drive->queue, 2048); +#endif + /* Extract geometry if we did not already have one for the drive */ if (!drive->cyl || !drive->head || !drive->sect) { drive->cyl = drive->bios_cyl = id->cyls; @@ -1414,7 +1618,6 @@ drive->no_io_32bit = id->dword_io ? 1 : 0; if (drive->id->cfs_enable_2 & 0x3000) write_cache(drive, (id->cfs_enable_2 & 0x3000)); - (void) probe_lba_addressing(drive, 1); } static int idedisk_cleanup (ide_drive_t *drive) @@ -1426,6 +1629,7 @@ return ide_unregister_subdriver(drive); } +int idedisk_init (void); int idedisk_reinit(ide_drive_t *drive); /* @@ -1440,9 +1644,13 @@ supports_dsc_overlap: 0, cleanup: idedisk_cleanup, standby: do_idedisk_standby, + suspend: do_idedisk_suspend, + resume: do_idedisk_resume, flushcache: do_idedisk_flushcache, do_request: do_rw_disk, - end_request: NULL, + end_request: idedisk_end_request, + sense: idedisk_dump_status, + error: idedisk_error, ioctl: NULL, open: idedisk_open, release: idedisk_release, @@ -1452,12 +1660,12 @@ capacity: idedisk_capacity, special: idedisk_special, proc: idedisk_proc, + init: idedisk_init, reinit: idedisk_reinit, ata_prebuilder: NULL, atapi_prebuilder: NULL, }; -int idedisk_init (void); static ide_module_t idedisk_module = { IDE_DRIVER_MODULE, idedisk_init, @@ -1480,7 +1688,8 @@ DRIVER(drive)->busy++; idedisk_setup(drive); if ((!drive->head || drive->head > 16) && !drive->select.b.lba) { - printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n", drive->name, drive->head); + printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n", + drive->name, drive->head); (void) idedisk_cleanup(drive); DRIVER(drive)->busy--; return 1; @@ -1540,6 +1749,78 @@ return 0; } +ide_startstop_t panic_box(ide_drive_t *drive) +{ +#if 0 + panic("%s: Attempted to corrupt something: ide operation " +#else + printk(KERN_ERR "%s: Attempted to corrupt something: ide operation " +#endif + "was pending accross suspend/resume.\n", drive->name); + return ide_stopped; +} + +int ide_disks_busy(void) +{ + int i; + for (i=0; ihandler) && (hwgroup->handler != panic_box)) + return 1; + } + return 0; +} + +void ide_disk_suspend(void) +{ + int i; + while (ide_disks_busy()) { + printk("*"); + schedule(); + } + for (i=0; ihandler_save = hwgroup->handler; + hwgroup->handler = panic_box; + } + driver_blocked = 1; + if (ide_disks_busy()) + panic("How did you get that request through?!"); +} + +/* unsuspend and resume should be equal in the ideal world */ + +void ide_disk_unsuspend(void) +{ + int i; + for (i=0; ihandler = NULL; /* hwgroup->handler_save; */ + hwgroup->handler_save = NULL; + } + driver_blocked = 0; +} + +void ide_disk_resume(void) +{ + int i; + for (i=0; ihandler != panic_box) + panic("Handler was not set to panic?"); + hwgroup->handler_save = NULL; + hwgroup->handler = NULL; + } + driver_blocked = 0; +} + module_init(idedisk_init); module_exit(idedisk_exit); MODULE_LICENSE("GPL"); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/ide-dma.c linux.19rc3-ac4/drivers/ide/ide-dma.c --- linux.19rc3/drivers/ide/ide-dma.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/ide-dma.c 2002-07-29 13:58:40.000000000 +0100 @@ -101,8 +101,6 @@ #define DEFAULT_BMCRBA 0xcc00 /* VIA's default value */ #define DEFAULT_BMALIBA 0xd400 /* ALI's default value */ -extern char *ide_dmafunc_verbose(ide_dma_action_t dmafunc); - #ifdef CONFIG_IDEDMA_NEW_DRIVE_LISTINGS struct drive_list_entry { @@ -123,7 +121,6 @@ { "WDC AC11000H" , "ALL" }, { "WDC AC22100H" , "ALL" }, - { "WDC AC31000H" , "ALL" }, { "WDC AC32500H" , "ALL" }, { "WDC AC33100H" , "ALL" }, { "WDC AC31600H" , "ALL" }, @@ -238,14 +235,14 @@ rq = HWGROUP(drive)->rq; for (i = rq->nr_sectors; i > 0;) { i -= rq->current_nr_sectors; - ide_end_request(1, HWGROUP(drive)); + DRIVER(drive)->end_request(drive, 1); } return ide_stopped; } printk("%s: dma_intr: bad DMA status (dma_stat=%x)\n", drive->name, dma_stat); } - return ide_error(drive, "dma_intr", stat); + return DRIVER(drive)->error(drive, "dma_intr", stat); } static int ide_build_sglist (ide_hwif_t *hwif, struct request *rq) @@ -291,13 +288,11 @@ unsigned char *virt_addr = rq->buffer; int sector_count = rq->nr_sectors; -// if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_WRITEDMA) || -// (args->tfRegister[IDE_COMMAND_OFFSET] == WIN_WRITEDMA_EXT)) if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE) hwif->sg_dma_direction = PCI_DMA_TODEVICE; else hwif->sg_dma_direction = PCI_DMA_FROMDEVICE; - +#if 1 if (sector_count > 128) { memset(&sg[nents], 0, sizeof(*sg)); sg[nents].address = virt_addr; @@ -310,7 +305,20 @@ sg[nents].address = virt_addr; sg[nents].length = sector_count * SECTOR_SIZE; nents++; - +#else + while (sector_count > 128) { + memset(&sg[nents], 0, sizeof(*sg)); + sg[nents].address = virt_addr; + sg[nents].length = 128 * SECTOR_SIZE; + nents++; + virt_addr = virt_addr + (128 * SECTOR_SIZE); + sector_count -= 128; + }; + memset(&sg[nents], 0, sizeof(*sg)); + sg[nents].address = virt_addr; + sg[nents].length = sector_count * SECTOR_SIZE; + nents++; +#endif return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction); } @@ -498,16 +506,10 @@ static int config_drive_for_dma (ide_drive_t *drive) { - int config_allows_dma = 1; struct hd_driveid *id = drive->id; ide_hwif_t *hwif = HWIF(drive); -#ifdef CONFIG_IDEDMA_ONLYDISK - if (drive->media != ide_disk) - config_allows_dma = 0; -#endif - - if (id && (id->capability & 1) && hwif->autodma && config_allows_dma) { + if (id && (id->capability & 1) && hwif->autodma) { /* Consult the list of known "bad" drives */ if (ide_dmaproc(ide_dma_bad_drive, drive)) return hwif->dmaproc(ide_dma_off, drive); @@ -535,13 +537,13 @@ return hwif->dmaproc(ide_dma_off_quietly, drive); } -#ifndef CONFIG_BLK_DEV_IDEDMA_TIMEOUT +#ifndef __IDEDMA_TIMEOUT /* * 1 dmaing, 2 error, 4 intr */ static int dma_timer_expiry (ide_drive_t *drive) { - byte dma_stat = inb(HWIF(drive)->dma_base+2); + byte dma_stat = IN_BYTE(HWIF(drive)->dma_base+2); #ifdef DEBUG printk("%s: dma_timer_expiry: dma status == 0x%02x\n", drive->name, dma_stat); @@ -553,36 +555,52 @@ if (dma_stat & 2) { /* ERROR */ byte stat = GET_STAT(); - return ide_error(drive, "dma_timer_expiry", stat); + return DRIVER(drive)->error(drive, "dma_timer_expiry", stat); } if (dma_stat & 1) /* DMAing */ return WAIT_CMD; return 0; } -#else /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */ -static ide_startstop_t ide_dma_timeout_revovery (ide_drive_t *drive) +#else /* __IDEDMA_TIMEOUT */ +static int ide_dma_timeout_recovery (ide_drive_t *drive) { - ide_hwgroup_t *hwgroup = HWGROUP(drive); - ide_hwif_t *hwif = HWIF(drive); + struct request *rq = HWGROUP(drive)->rq; int enable_dma = drive->using_dma; + int speed = drive->current_speed; unsigned long flags; - ide_startstop_t startstop; spin_lock_irqsave(&io_request_lock, flags); - hwgroup->handler = NULL; - del_timer(&hwgroup->timer); + HWGROUP(drive)->handler = NULL; + del_timer(&HWGROUP(drive)->timer); + HWGROUP(drive)->expiry = NULL; + HWGROUP(drive)->rq = NULL; spin_unlock_irqrestore(&io_request_lock, flags); + (void) HWIF(drive)->dmaproc(ide_dma_off, drive); drive->waiting_for_dma = 0; - startstop = ide_do_reset(drive); + (void) ide_do_reset(drive); + + if (!(drive_is_ready(drive))) { + /* FIXME: Replace hard-coded 100, error handling? */ + int i; + for (i=0; i<100; i++) { + if (drive_is_ready(drive)) + break; + } + } + + if ((HWIF(drive)->speedproc) != NULL) { + HWIF(drive)->speedproc(drive, speed); + drive->current_speed = speed; + } if ((enable_dma) && !(drive->using_dma)) - (void) hwif->dmaproc(ide_dma_on, drive); + (void) HWIF(drive)->dmaproc(ide_dma_on, drive); - return startstop; + return restart_request(drive, rq); } -#endif /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */ +#endif /* __IDEDMA_TIMEOUT */ /* * ide_dmaproc() initiates/aborts DMA read/write operations on a drive. @@ -602,8 +620,8 @@ */ int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive) { -// ide_hwgroup_t *hwgroup = HWGROUP(drive); ide_hwif_t *hwif = HWIF(drive); +// ide_task_t *args = HWGROUP(drive)->rq->special; unsigned long dma_base = hwif->dma_base; byte unit = (drive->select.b.unit & 0x01); unsigned int count, reading = 0; @@ -613,11 +631,17 @@ case ide_dma_off: printk("%s: DMA disabled\n", drive->name); case ide_dma_off_quietly: - outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2); + case ide_dma_host_off: + OUT_BYTE(IN_BYTE(dma_base+2) & ~(1<<(5+unit)), dma_base+2); + if (func == ide_dma_host_off) + return 0; case ide_dma_on: drive->using_dma = (func == ide_dma_on); + if (!drive->using_dma) + return 0; + case ide_dma_host_on: if (drive->using_dma) - outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2); + OUT_BYTE(IN_BYTE(dma_base+2)|(1<<(5+unit)), dma_base+2); return 0; case ide_dma_check: return config_drive_for_dma (drive); @@ -626,27 +650,43 @@ case ide_dma_write: SELECT_READ_WRITE(hwif,drive,func); if (!(count = ide_build_dmatable(drive, func))) - return 1; /* try PIO instead of DMA */ - outl(hwif->dmatable_dma, dma_base + 4); /* PRD table */ - outb(reading, dma_base); /* specify r/w */ - outb(inb(dma_base+2)|6, dma_base+2); /* clear INTR & ERROR flags */ + /* try PIO instead of DMA */ + return 1; + /* PRD table */ + outl(hwif->dmatable_dma, dma_base + 4); + /* specify r/w */ + OUT_BYTE(reading, dma_base); + /* clear INTR & ERROR flags */ + OUT_BYTE(IN_BYTE(dma_base+2)|6, dma_base+2); drive->waiting_for_dma = 1; if (drive->media != ide_disk) return 0; -#ifdef CONFIG_BLK_DEV_IDEDMA_TIMEOUT - ide_set_handler(drive, &ide_dma_intr, 2*WAIT_CMD, NULL); /* issue cmd to drive */ -#else /* !CONFIG_BLK_DEV_IDEDMA_TIMEOUT */ - ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, dma_timer_expiry); /* issue cmd to drive */ -#endif /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */ - if ((HWGROUP(drive)->rq->cmd == IDE_DRIVE_TASKFILE) && - (drive->addressing == 1)) { + /* paranoia check */ + if (HWGROUP(drive)->handler != NULL) + BUG(); +#ifndef __IDEDMA_TIMEOUT + ide_set_handler(drive, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry); +#else /* __IDEDMA_TIMEOUT */ + ide_set_handler(drive, &ide_dma_intr, 2*WAIT_CMD, NULL); +#endif /* __IDEDMA_TIMEOUT */ + /* issue cmd to drive */ + /* + * FIX ME to use only ACB ide_task_t args Struct + */ +#if 0 + { + ide_task_t *args = HWGROUP(drive)->rq->special; + OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); + } +#else + if (HWGROUP(drive)->rq->cmd == IDE_DRIVE_TASKFILE) { ide_task_t *args = HWGROUP(drive)->rq->special; OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); - } else if (drive->addressing) { + } else if (drive->addressing == 1) OUT_BYTE(reading ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG); - } else { + else OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); - } +#endif return HWIF(drive)->dmaproc(ide_dma_begin, drive); case ide_dma_begin: /* Note that this is done *after* the cmd has @@ -654,71 +694,83 @@ * The Promise Ultra33 doesn't work correctly when * we do this part before issuing the drive cmd. */ - outb(inb(dma_base)|1, dma_base); /* start DMA */ + /* start DMA */ + OUT_BYTE(IN_BYTE(dma_base)|1, dma_base); return 0; case ide_dma_end: /* returns 1 on error, 0 otherwise */ drive->waiting_for_dma = 0; - outb(inb(dma_base)&~1, dma_base); /* stop DMA */ - dma_stat = inb(dma_base+2); /* get DMA status */ - outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */ - ide_destroy_dmatable(drive); /* purge DMA mappings */ - return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; /* verify good DMA status */ + /* stop DMA */ + OUT_BYTE(IN_BYTE(dma_base)&~1, dma_base); + /* get DMA status */ + dma_stat = IN_BYTE(dma_base+2); + /* clear the INTR & ERROR bits */ + OUT_BYTE(dma_stat|6, dma_base+2); + /* purge DMA mappings */ + ide_destroy_dmatable(drive); + /* verify good DMA status */ + return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */ - dma_stat = inb(dma_base+2); + dma_stat = IN_BYTE(dma_base+2); #if 0 /* do not set unless you know what you are doing */ if (dma_stat & 4) { byte stat = GET_STAT(); - outb(dma_base+2, dma_stat & 0xE4); + OUT_BYTE(dma_base+2, dma_stat & 0xE4); } #endif - return (dma_stat & 4) == 4; /* return 1 if INTR asserted */ + /* return 1 if INTR asserted */ + return (dma_stat & 4) == 4; case ide_dma_bad_drive: case ide_dma_good_drive: return check_drive_lists(drive, (func == ide_dma_good_drive)); case ide_dma_verbose: return report_drive_dmaing(drive); case ide_dma_timeout: - // FIXME: Many IDE chipsets do not permit command file register access - // FIXME: while the bus-master function is still active. - // FIXME: To prevent deadlock with those chipsets, we must be extremely - // FIXME: careful here (and in ide_intr() as well) to NOT access any - // FIXME: registers from the 0x1Fx/0x17x sets before terminating the - // FIXME: bus-master operation via the bus-master control reg. - // FIXME: Otherwise, chipset deadlock will occur, and some systems will - // FIXME: lock up completely!! -#ifdef CONFIG_BLK_DEV_IDEDMA_TIMEOUT + // FIXME: Many IDE chipsets do not permit command file register access + // FIXME: while the bus-master function is still active. + // FIXME: To prevent deadlock with those chipsets, we must be extremely + // FIXME: careful here (and in ide_intr() as well) to NOT access any + // FIXME: registers from the 0x1Fx/0x17x sets before terminating the + // FIXME: bus-master operation via the bus-master control reg. + // FIXME: Otherwise, chipset deadlock will occur, and some systems will + // FIXME: lock up completely!! +#ifdef __IDEDMA_TIMEOUT /* * Have to issue an abort and requeue the request * DMA engine got turned off by a goofy ASIC, and * we have to clean up the mess, and here is as good * as any. Do it globally for all chipsets. */ - outb(0x00, dma_base); /* stop DMA */ - dma_stat = inb(dma_base+2); /* get DMA status */ - outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */ +#if 0 + dma_stat = HWIF(drive)->dmaproc(ide_dma_end, drive); +#else + drive->waiting_for_dma = 0; + /* stop DMA */ + OUT_BYTE(IN_BYTE(dma_base)&~1, dma_base); +// OUT_BYTE(0x00, dma_base); + /* get DMA status */ + dma_stat = IN_BYTE(dma_base+2); + /* clear the INTR & ERROR bits */ + OUT_BYTE(dma_stat|6, dma_base+2); + /* purge DMA mappings */ + ide_destroy_dmatable(drive); +#endif printk("%s: %s: Lets do it again!" \ "stat = 0x%02x, dma_stat = 0x%02x\n", drive->name, ide_dmafunc_verbose(func), GET_STAT(), dma_stat); if (dma_stat & 0xF0) - return ide_dma_timeout_revovery(drive); - - printk("%s: %s: (restart_request) Lets do it again!" \ - "stat = 0x%02x, dma_stat = 0x%02x\n", - drive->name, ide_dmafunc_verbose(func), - GET_STAT(), dma_stat); - - return restart_request(drive); // BUG: return types do not match!! -//#else -// return HWGROUP(drive)->handler(drive); -#endif /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */ + return ide_dma_timeout_recovery(drive); +#endif /* __IDEDMA_TIMEOUT */ case ide_dma_retune: case ide_dma_lostirq: - printk("ide_dmaproc: chipset supported %s func only: %d\n", ide_dmafunc_verbose(func), func); + printk("ide_dmaproc: chipset supported %s " + "func only: %d\n", + ide_dmafunc_verbose(func), func); return 1; default: - printk("ide_dmaproc: unsupported %s func: %d\n", ide_dmafunc_verbose(func), func); + printk("ide_dmaproc: unsupported %s func: %d\n", + ide_dmafunc_verbose(func), func); return 1; } } @@ -746,7 +798,7 @@ } /* - * This can be called for a dynamically installed interface. Don't __init it + * This can be called for a dynamically installed interface. Don't __init it */ void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_ports) @@ -775,7 +827,7 @@ hwif->dmaproc = &ide_dmaproc; if (hwif->chipset != ide_trm290) { - byte dma_stat = inb(dma_base+2); + byte dma_stat = IN_BYTE(dma_base+2); printk(", BIOS settings: %s:%s, %s:%s", hwif->drives[0].name, (dma_stat & 0x20) ? "DMA" : "pio", hwif->drives[1].name, (dma_stat & 0x40) ? "DMA" : "pio"); @@ -840,8 +892,9 @@ case PCI_DEVICE_ID_AL_M5219: case PCI_DEVICE_ID_AMD_VIPER_7409: case PCI_DEVICE_ID_CMD_643: - outb(inb(dma_base+2) & 0x60, dma_base+2); - if (inb(dma_base+2) & 0x80) { + case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE: + OUT_BYTE(IN_BYTE(dma_base+2) & 0x60, dma_base+2); + if (IN_BYTE(dma_base+2) & 0x80) { printk("%s: simplex device: DMA forced\n", name); } break; @@ -853,7 +906,7 @@ * So we should enable DMA only on one of the * two interfaces. */ - if ((inb(dma_base+2) & 0x80)) { /* simplex device? */ + if ((IN_BYTE(dma_base+2) & 0x80)) { /* simplex device? */ if ((!hwif->drives[0].present && !hwif->drives[1].present) || (hwif->mate && hwif->mate->dma_base)) { printk("%s: simplex device: DMA disabled\n", name); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/ide-features.c linux.19rc3-ac4/drivers/ide/ide-features.c --- linux.19rc3/drivers/ide/ide-features.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/ide-features.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,385 +0,0 @@ -/* - * linux/drivers/block/ide-features.c Version 0.04 June 9, 2000 - * - * Copyright (C) 1999-2000 Linus Torvalds & authors (see below) - * - * Copyright (C) 1999-2000 Andre Hedrick - * - * Extracts if ide.c to address the evolving transfer rate code for - * the SETFEATURES_XFER callouts. Various parts of any given function - * are credited to previous ATA-IDE maintainers. - * - * Auto-CRC downgrade for Ultra DMA(ing) - * - * May be copied or modified under the terms of the GNU General Public License - */ - -#include -#define __NO_VERSION__ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* - * A Verbose noise maker for debugging on the attempted transfer rates. - */ -char *ide_xfer_verbose (byte xfer_rate) -{ - switch(xfer_rate) { - case XFER_UDMA_7: return("UDMA 7"); - case XFER_UDMA_6: return("UDMA 6"); - case XFER_UDMA_5: return("UDMA 5"); - case XFER_UDMA_4: return("UDMA 4"); - case XFER_UDMA_3: return("UDMA 3"); - case XFER_UDMA_2: return("UDMA 2"); - case XFER_UDMA_1: return("UDMA 1"); - case XFER_UDMA_0: return("UDMA 0"); - case XFER_MW_DMA_2: return("MW DMA 2"); - case XFER_MW_DMA_1: return("MW DMA 1"); - case XFER_MW_DMA_0: return("MW DMA 0"); - case XFER_SW_DMA_2: return("SW DMA 2"); - case XFER_SW_DMA_1: return("SW DMA 1"); - case XFER_SW_DMA_0: return("SW DMA 0"); - case XFER_PIO_4: return("PIO 4"); - case XFER_PIO_3: return("PIO 3"); - case XFER_PIO_2: return("PIO 2"); - case XFER_PIO_1: return("PIO 1"); - case XFER_PIO_0: return("PIO 0"); - case XFER_PIO_SLOW: return("PIO SLOW"); - default: return("XFER ERROR"); - } -} - -/* - * - */ -char *ide_media_verbose (ide_drive_t *drive) -{ - switch (drive->media) { - case ide_scsi: return("scsi "); - case ide_disk: return("disk "); - case ide_optical: return("optical"); - case ide_cdrom: return("cdrom "); - case ide_tape: return("tape "); - case ide_floppy: return("floppy "); - default: return("???????"); - } -} - -/* - * A Verbose noise maker for debugging on the attempted dmaing calls. - */ -char *ide_dmafunc_verbose (ide_dma_action_t dmafunc) -{ - switch (dmafunc) { - case ide_dma_read: return("ide_dma_read"); - case ide_dma_write: return("ide_dma_write"); - case ide_dma_begin: return("ide_dma_begin"); - case ide_dma_end: return("ide_dma_end:"); - case ide_dma_check: return("ide_dma_check"); - case ide_dma_on: return("ide_dma_on"); - case ide_dma_off: return("ide_dma_off"); - case ide_dma_off_quietly: return("ide_dma_off_quietly"); - case ide_dma_test_irq: return("ide_dma_test_irq"); - case ide_dma_bad_drive: return("ide_dma_bad_drive"); - case ide_dma_good_drive: return("ide_dma_good_drive"); - case ide_dma_verbose: return("ide_dma_verbose"); - case ide_dma_retune: return("ide_dma_retune"); - case ide_dma_lostirq: return("ide_dma_lostirq"); - case ide_dma_timeout: return("ide_dma_timeout"); - default: return("unknown"); - } -} - -/* - * - */ -byte ide_auto_reduce_xfer (ide_drive_t *drive) -{ - if (!drive->crc_count) - return drive->current_speed; - drive->crc_count = 0; - - switch(drive->current_speed) { - case XFER_UDMA_7: return XFER_UDMA_6; - case XFER_UDMA_6: return XFER_UDMA_5; - case XFER_UDMA_5: return XFER_UDMA_4; - case XFER_UDMA_4: return XFER_UDMA_3; - case XFER_UDMA_3: return XFER_UDMA_2; - case XFER_UDMA_2: return XFER_UDMA_1; - case XFER_UDMA_1: return XFER_UDMA_0; - /* - * OOPS we do not goto non Ultra DMA modes - * without iCRC's available we force - * the system to PIO and make the user - * invoke the ATA-1 ATA-2 DMA modes. - */ - case XFER_UDMA_0: - default: return XFER_PIO_4; - } -} - -/* - * Update the - */ -int ide_driveid_update (ide_drive_t *drive) -{ - /* - * Re-read drive->id for possible DMA mode - * change (copied from ide-probe.c) - */ - struct hd_driveid *id; - unsigned long timeout, flags; - - SELECT_MASK(HWIF(drive), drive, 1); - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl,IDE_CONTROL_REG); - ide_delay_50ms(); - OUT_BYTE(WIN_IDENTIFY, IDE_COMMAND_REG); - timeout = jiffies + WAIT_WORSTCASE; - do { - if (0 < (signed long)(jiffies - timeout)) { - SELECT_MASK(HWIF(drive), drive, 0); - return 0; /* drive timed-out */ - } - ide_delay_50ms(); /* give drive a breather */ - } while (IN_BYTE(IDE_ALTSTATUS_REG) & BUSY_STAT); - ide_delay_50ms(); /* wait for IRQ and DRQ_STAT */ - if (!OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)) { - SELECT_MASK(HWIF(drive), drive, 0); - printk("%s: CHECK for good STATUS\n", drive->name); - return 0; - } - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only; some systems need this */ - SELECT_MASK(HWIF(drive), drive, 0); - id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC); - if (!id) { - __restore_flags(flags); /* local CPU only */ - return 0; - } - ide_input_data(drive, id, SECTOR_WORDS); - (void) GET_STAT(); /* clear drive IRQ */ - ide__sti(); /* local CPU only */ - __restore_flags(flags); /* local CPU only */ - ide_fix_driveid(id); - if (id) { - drive->id->dma_ultra = id->dma_ultra; - drive->id->dma_mword = id->dma_mword; - drive->id->dma_1word = id->dma_1word; - /* anything more ? */ - kfree(id); - } - - return 1; -} - -/* - * Verify that we are doing an approved SETFEATURES_XFER with respect - * to the hardware being able to support request. Since some hardware - * can improperly report capabilties, we check to see if the host adapter - * in combination with the device (usually a disk) properly detect - * and acknowledge each end of the ribbon. - */ -int ide_ata66_check (ide_drive_t *drive, ide_task_t *args) -{ - if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) && - (args->tfRegister[IDE_SECTOR_OFFSET] > XFER_UDMA_2) && - (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER)) { - if (!HWIF(drive)->udma_four) { - printk("%s: Speed warnings UDMA 3/4/5 is not functional.\n", HWIF(drive)->name); - return 1; - } -#ifndef CONFIG_IDEDMA_IVB - if ((drive->id->hw_config & 0x6000) == 0) { -#else /* !CONFIG_IDEDMA_IVB */ - if (((drive->id->hw_config & 0x2000) == 0) || - ((drive->id->hw_config & 0x4000) == 0)) { -#endif /* CONFIG_IDEDMA_IVB */ - printk("%s: Speed warnings UDMA 3/4/5 is not functional.\n", drive->name); - return 1; - } - } - return 0; -} - -/* - * Backside of HDIO_DRIVE_CMD call of SETFEATURES_XFER. - * 1 : Safe to update drive->id DMA registers. - * 0 : OOPs not allowed. - */ -int set_transfer (ide_drive_t *drive, ide_task_t *args) -{ - if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) && - (args->tfRegister[IDE_SECTOR_OFFSET] >= XFER_SW_DMA_0) && - (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER) && - (drive->id->dma_ultra || - drive->id->dma_mword || - drive->id->dma_1word)) - return 1; - - return 0; -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -/* - * All hosts that use the 80c ribbon mus use! - */ -byte eighty_ninty_three (ide_drive_t *drive) -{ -#ifdef CONFIG_BLK_DEV_IDEPCI - if (HWIF(drive)->pci_devid.vid==0x105a) - return(HWIF(drive)->udma_four); -#endif - /* PDC202XX: that's because some HDD will return wrong info */ - return ((byte) ((HWIF(drive)->udma_four) && -#ifndef CONFIG_IDEDMA_IVB - (drive->id->hw_config & 0x4000) && -#endif /* CONFIG_IDEDMA_IVB */ - (drive->id->hw_config & 0x6000)) ? 1 : 0); -} -#endif // CONFIG_BLK_DEV_IDEDMA - -/* - * Similar to ide_wait_stat(), except it never calls ide_error internally. - * This is a kludge to handle the new ide_config_drive_speed() function, - * and should not otherwise be used anywhere. Eventually, the tuneproc's - * should be updated to return ide_startstop_t, in which case we can get - * rid of this abomination again. :) -ml - * - * It is gone.......... - * - * const char *msg == consider adding for verbose errors. - */ -int ide_config_drive_speed (ide_drive_t *drive, byte speed) -{ - ide_hwif_t *hwif = HWIF(drive); - int i, error = 1; - byte stat; - -#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI) - byte unit = (drive->select.b.unit & 0x01); - outb(inb(hwif->dma_base+2) & ~(1<<(5+unit)), hwif->dma_base+2); -#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */ - - /* - * Don't use ide_wait_cmd here - it will - * attempt to set_geometry and recalibrate, - * but for some reason these don't work at - * this point (lost interrupt). - */ - /* - * Select the drive, and issue the SETFEATURES command - */ - disable_irq(hwif->irq); /* disable_irq_nosync ?? */ - udelay(1); - SELECT_DRIVE(HWIF(drive), drive); - SELECT_MASK(HWIF(drive), drive, 0); - udelay(1); - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG); - OUT_BYTE(speed, IDE_NSECTOR_REG); - OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG); - OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG); - if ((IDE_CONTROL_REG) && (drive->quirk_list == 2)) - OUT_BYTE(drive->ctl, IDE_CONTROL_REG); - udelay(1); - /* - * Wait for drive to become non-BUSY - */ - if ((stat = GET_STAT()) & BUSY_STAT) { - unsigned long flags, timeout; - __save_flags(flags); /* local CPU only */ - ide__sti(); /* local CPU only -- for jiffies */ - timeout = jiffies + WAIT_CMD; - while ((stat = GET_STAT()) & BUSY_STAT) { - if (0 < (signed long)(jiffies - timeout)) - break; - } - __restore_flags(flags); /* local CPU only */ - } - - /* - * Allow status to settle, then read it again. - * A few rare drives vastly violate the 400ns spec here, - * so we'll wait up to 10usec for a "good" status - * rather than expensively fail things immediately. - * This fix courtesy of Matthew Faupel & Niccolo Rigacci. - */ - for (i = 0; i < 10; i++) { - udelay(1); - if (OK_STAT((stat = GET_STAT()), DRIVE_READY, BUSY_STAT|DRQ_STAT|ERR_STAT)) { - error = 0; - break; - } - } - - SELECT_MASK(HWIF(drive), drive, 0); - - enable_irq(hwif->irq); - - if (error) { - (void) ide_dump_status(drive, "set_drive_speed_status", stat); - return error; - } - - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - -#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI) - if (speed > XFER_PIO_4) { - outb(inb(hwif->dma_base+2)|(1<<(5+unit)), hwif->dma_base+2); - } else { - outb(inb(hwif->dma_base+2) & ~(1<<(5+unit)), hwif->dma_base+2); - } -#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */ - - switch(speed) { - case XFER_UDMA_7: drive->id->dma_ultra |= 0x8080; break; - case XFER_UDMA_6: drive->id->dma_ultra |= 0x4040; break; - case XFER_UDMA_5: drive->id->dma_ultra |= 0x2020; break; - case XFER_UDMA_4: drive->id->dma_ultra |= 0x1010; break; - case XFER_UDMA_3: drive->id->dma_ultra |= 0x0808; break; - case XFER_UDMA_2: drive->id->dma_ultra |= 0x0404; break; - case XFER_UDMA_1: drive->id->dma_ultra |= 0x0202; break; - case XFER_UDMA_0: drive->id->dma_ultra |= 0x0101; break; - case XFER_MW_DMA_2: drive->id->dma_mword |= 0x0404; break; - case XFER_MW_DMA_1: drive->id->dma_mword |= 0x0202; break; - case XFER_MW_DMA_0: drive->id->dma_mword |= 0x0101; break; - case XFER_SW_DMA_2: drive->id->dma_1word |= 0x0404; break; - case XFER_SW_DMA_1: drive->id->dma_1word |= 0x0202; break; - case XFER_SW_DMA_0: drive->id->dma_1word |= 0x0101; break; - default: break; - } - return error; -} - -EXPORT_SYMBOL(ide_auto_reduce_xfer); -EXPORT_SYMBOL(ide_driveid_update); -EXPORT_SYMBOL(ide_ata66_check); -EXPORT_SYMBOL(set_transfer); -#ifdef CONFIG_BLK_DEV_IDEDMA -EXPORT_SYMBOL(eighty_ninty_three); -#endif // CONFIG_BLK_DEV_IDEDMA -EXPORT_SYMBOL(ide_config_drive_speed); - diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/ide-floppy.c linux.19rc3-ac4/drivers/ide/ide-floppy.c --- linux.19rc3/drivers/ide/ide-floppy.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/ide-floppy.c 2002-07-29 13:58:40.000000000 +0100 @@ -668,28 +668,57 @@ static void idefloppy_discard_data (ide_drive_t *drive, unsigned int bcount) { while (bcount--) - IN_BYTE (IDE_DATA_REG); + IN_BYTE(IDE_DATA_REG); } #if IDEFLOPPY_DEBUG_BUGS static void idefloppy_write_zeros (ide_drive_t *drive, unsigned int bcount) { while (bcount--) - OUT_BYTE (0, IDE_DATA_REG); + OUT_BYTE(0, IDE_DATA_REG); } #endif /* IDEFLOPPY_DEBUG_BUGS */ + +static int idefloppy_end_request (ide_drive_t *drive, int uptodate) +{ + struct request *rq; + unsigned long flags; + int ret = 1; + + spin_lock_irqsave(&io_request_lock, flags); + rq = HWGROUP(drive)->rq; + + /* + * decide whether to reenable DMA -- 3 is a random magic for now, + * if we DMA timeout more than 3 times, just stay in PIO + */ + if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) { + drive->state = 0; + HWGROUP(drive)->hwif->dmaproc(ide_dma_on, drive); + } + + if (!end_that_request_first(rq, uptodate, drive->name)) { + add_blkdev_randomness(MAJOR(rq->rq_dev)); + blkdev_dequeue_request(rq); + HWGROUP(drive)->rq = NULL; + end_that_request_last(rq); + ret = 0; + } + spin_unlock_irqrestore(&io_request_lock, flags); + return ret; +} + /* - * idefloppy_end_request is used to finish servicing a request. + * idefloppy_do_end_request is used to finish servicing a request. * * For read/write requests, we will call ide_end_request to pass to the * next buffer. */ -static void idefloppy_end_request (byte uptodate, ide_hwgroup_t *hwgroup) +static int idefloppy_do_end_request (ide_drive_t *drive, int uptodate) { - ide_drive_t *drive = hwgroup->drive; idefloppy_floppy_t *floppy = drive->driver_data; - struct request *rq = hwgroup->rq; + struct request *rq = HWGROUP(drive)->rq; int error; #if IDEFLOPPY_DEBUG_LOG @@ -705,13 +734,16 @@ floppy->failed_pc = NULL; /* Why does this happen? */ if (!rq) - return; + return 0; if (!IDEFLOPPY_RQ_CMD (rq->cmd)) { - ide_end_request (uptodate, hwgroup); - return; + /* our real local end request function */ + idefloppy_end_request(drive, uptodate); + return 0; } rq->errors = error; + /* fixme: need to move this local also */ ide_end_drive_cmd (drive, 0, 0); + return 0; } static void idefloppy_input_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, unsigned int bcount) @@ -724,7 +756,7 @@ if (pc->b_count == bh->b_size) { rq->sector += rq->current_nr_sectors; rq->nr_sectors -= rq->current_nr_sectors; - idefloppy_end_request (1, HWGROUP(drive)); + idefloppy_do_end_request(drive, 1); if ((bh = rq->bh) != NULL) pc->b_count = 0; } @@ -749,7 +781,7 @@ if (!pc->b_count) { rq->sector += rq->current_nr_sectors; rq->nr_sectors -= rq->current_nr_sectors; - idefloppy_end_request (1, HWGROUP(drive)); + idefloppy_do_end_request(drive, 1); if ((bh = rq->bh) != NULL) { pc->b_data = bh->b_data; pc->b_count = bh->b_size; @@ -773,7 +805,7 @@ struct buffer_head *bh = rq->bh; while ((bh = rq->bh) != NULL) - idefloppy_end_request (1, HWGROUP(drive)); + idefloppy_do_end_request(drive, 1); } #endif /* CONFIG_BLK_DEV_IDEDMA */ @@ -836,10 +868,10 @@ #endif /* IDEFLOPPY_DEBUG_LOG */ if (!floppy->pc->error) { idefloppy_analyze_error (drive,(idefloppy_request_sense_result_t *) floppy->pc->buffer); - idefloppy_end_request (1,HWGROUP (drive)); + idefloppy_do_end_request(drive, 1); } else { printk (KERN_ERR "Error in REQUEST SENSE itself - Aborting request!\n"); - idefloppy_end_request (0,HWGROUP (drive)); + idefloppy_do_end_request(drive, 0); } } @@ -854,7 +886,7 @@ printk (KERN_INFO "ide-floppy: Reached idefloppy_pc_callback\n"); #endif /* IDEFLOPPY_DEBUG_LOG */ - idefloppy_end_request (floppy->pc->error ? 0:1, HWGROUP(drive)); + idefloppy_do_end_request(drive, floppy->pc->error ? 0 : 1); } /* @@ -939,7 +971,7 @@ #endif /* IDEFLOPPY_DEBUG_LOG */ clear_bit (PC_DMA_IN_PROGRESS, &pc->flags); - ide__sti(); /* local CPU only */ + local_irq_enable(); if (status.b.check || test_bit (PC_DMA_ERROR, &pc->flags)) { /* Error detected */ #if IDEFLOPPY_DEBUG_LOG @@ -985,7 +1017,9 @@ if (temp > pc->buffer_size) { printk (KERN_ERR "ide-floppy: The floppy wants to send us more data than expected - discarding data\n"); idefloppy_discard_data (drive,bcount.all); - ide_set_handler (drive,&idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD, NULL); + if (HWGROUP(drive)->handler != NULL) + BUG(); + ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); return ide_started; } #if IDEFLOPPY_DEBUG_LOG @@ -1007,7 +1041,9 @@ pc->actually_transferred+=bcount.all; /* Update the current position */ pc->current_position+=bcount.all; - ide_set_handler (drive,&idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD, NULL); /* And set the interrupt handler again */ + if (HWGROUP(drive)->handler != NULL) + BUG(); + ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); /* And set the interrupt handler again */ return ide_started; } @@ -1023,15 +1059,19 @@ idefloppy_ireason_reg_t ireason; if (ide_wait_stat (&startstop,drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) { - printk (KERN_ERR "ide-floppy: Strange, packet command initiated yet DRQ isn't asserted\n"); + printk(KERN_ERR "ide-floppy: Strange, packet command " + "initiated yet DRQ isn't asserted\n"); return startstop; } - ireason.all=IN_BYTE (IDE_IREASON_REG); + ireason.all = IN_BYTE(IDE_IREASON_REG); if (!ireason.b.cod || ireason.b.io) { - printk (KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while issuing a packet command\n"); + printk(KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while " + "issuing a packet command\n"); return ide_do_reset (drive); } - ide_set_handler (drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); /* Set the interrupt routine */ + if (HWGROUP(drive)->handler != NULL) + BUG(); + ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); /* Set the interrupt routine */ atapi_output_bytes (drive, floppy->pc->c, 12); /* Send the actual packet */ return ide_started; } @@ -1053,8 +1093,8 @@ { idefloppy_floppy_t *floppy = drive->driver_data; - atapi_output_bytes (drive, floppy->pc->c, 12); /* Send the actual packet */ - return IDEFLOPPY_WAIT_CMD; /* Timeout for the packet command */ + atapi_output_bytes(drive, floppy->pc->c, 12); /* Send the actual packet */ + return IDEFLOPPY_WAIT_CMD; /* Timeout for the packet command */ } static ide_startstop_t idefloppy_transfer_pc1 (ide_drive_t *drive) @@ -1064,12 +1104,14 @@ idefloppy_ireason_reg_t ireason; if (ide_wait_stat (&startstop,drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) { - printk (KERN_ERR "ide-floppy: Strange, packet command initiated yet DRQ isn't asserted\n"); + printk(KERN_ERR "ide-floppy: Strange, packet command " + "initiated yet DRQ isn't asserted\n"); return startstop; } - ireason.all=IN_BYTE (IDE_IREASON_REG); + ireason.all = IN_BYTE(IDE_IREASON_REG); if (!ireason.b.cod || ireason.b.io) { - printk (KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while issuing a packet command\n"); + printk(KERN_ERR "ide-floppy: (IO,CoD) != (0,1) " + "while issuing a packet command\n"); return ide_do_reset (drive); } /* @@ -1079,9 +1121,11 @@ * 25msec is too short, 40 and 50msec work well. idefloppy_pc_intr will * not be actually used until after the packet is moved in about 50 msec. */ - ide_set_handler (drive, + if (HWGROUP(drive)->handler != NULL) + BUG(); + ide_set_handler(drive, &idefloppy_pc_intr, /* service routine for packet command */ - floppy->ticks, /* wait this long before "failing" */ + floppy->ticks, /* wait this long before "failing" */ &idefloppy_transfer_pc2); /* fail == transfer_pc2 */ return ide_started; } @@ -1114,10 +1158,15 @@ if (!test_bit (PC_ABORT, &pc->flags)) { if (!test_bit (PC_SUPPRESS_ERROR, &pc->flags)) { ; - printk( KERN_ERR "ide-floppy: %s: I/O error, pc = %2x, key = %2x, asc = %2x, ascq = %2x\n", - drive->name, pc->c[0], floppy->sense_key, floppy->asc, floppy->ascq); + printk(KERN_ERR "ide-floppy: %s: I/O error, " + "pc = %2x, key = %2x, " + "asc = %2x, ascq = %2x\n", + drive->name, pc->c[0], + floppy->sense_key, + floppy->asc, floppy->ascq); } - pc->error = IDEFLOPPY_ERROR_GENERAL; /* Giving up */ + /* Giving up */ + pc->error = IDEFLOPPY_ERROR_GENERAL; } floppy->failed_pc=NULL; pc->callback(drive); @@ -1128,7 +1177,7 @@ #endif /* IDEFLOPPY_DEBUG_LOG */ pc->retries++; - pc->actually_transferred=0; /* We haven't transferred any data yet */ + pc->actually_transferred=0; /* We haven't transferred any data yet */ pc->current_position=pc->buffer; bcount.all = IDE_MIN(pc->request_transfer, 63 * 1024); @@ -1141,14 +1190,14 @@ #endif /* CONFIG_BLK_DEV_IDEDMA */ if (IDE_CONTROL_REG) - OUT_BYTE (drive->ctl,IDE_CONTROL_REG); - OUT_BYTE (dma_ok ? 1:0,IDE_FEATURE_REG); /* Use PIO/DMA */ - OUT_BYTE (bcount.b.high,IDE_BCOUNTH_REG); - OUT_BYTE (bcount.b.low,IDE_BCOUNTL_REG); - OUT_BYTE (drive->select.all,IDE_SELECT_REG); + OUT_BYTE(drive->ctl,IDE_CONTROL_REG); + OUT_BYTE(dma_ok ? 1:0,IDE_FEATURE_REG); /* Use PIO/DMA */ + OUT_BYTE(bcount.b.high,IDE_BCOUNTH_REG); + OUT_BYTE(bcount.b.low,IDE_BCOUNTL_REG); + OUT_BYTE(drive->select.all,IDE_SELECT_REG); #ifdef CONFIG_BLK_DEV_IDEDMA - if (dma_ok) { /* Begin DMA, if necessary */ + if (dma_ok) { /* Begin DMA, if necessary */ set_bit (PC_DMA_IN_PROGRESS, &pc->flags); (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive)); } @@ -1162,11 +1211,13 @@ } if (test_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags)) { - ide_set_handler (drive, pkt_xfer_routine, IDEFLOPPY_WAIT_CMD, NULL); - OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* Issue the packet command */ + if (HWGROUP(drive)->handler != NULL) + BUG(); + ide_set_handler(drive, pkt_xfer_routine, IDEFLOPPY_WAIT_CMD, NULL); + OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); /* Issue the packet command */ return ide_started; } else { - OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); + OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); return (*pkt_xfer_routine) (drive); } } @@ -1177,7 +1228,7 @@ printk (KERN_INFO "ide-floppy: Reached idefloppy_rw_callback\n"); #endif /* IDEFLOPPY_DEBUG_LOG */ - idefloppy_end_request(1, HWGROUP(drive)); + idefloppy_do_end_request(drive, 1); return; } @@ -1300,25 +1351,33 @@ idefloppy_pc_t *pc; #if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "rq_status: %d, rq_dev: %u, cmd: %d, errors: %d\n",rq->rq_status,(unsigned int) rq->rq_dev,rq->cmd,rq->errors); - printk (KERN_INFO "sector: %ld, nr_sectors: %ld, current_nr_sectors: %ld\n",rq->sector,rq->nr_sectors,rq->current_nr_sectors); + printk(KERN_INFO "rq_status: %d, rq_dev: %u, cmd: %d, errors: %d\n", + rq->rq_status, (unsigned int) rq->rq_dev, rq->cmd, rq->errors); + printk(KERN_INFO "sector: %ld, nr_sectors: %ld, " + "current_nr_sectors: %ld\n", rq->sector, + rq->nr_sectors, rq->current_nr_sectors); #endif /* IDEFLOPPY_DEBUG_LOG */ if (rq->errors >= ERROR_MAX) { if (floppy->failed_pc != NULL) - printk (KERN_ERR "ide-floppy: %s: I/O error, pc = %2x, key = %2x, asc = %2x, ascq = %2x\n", - drive->name, floppy->failed_pc->c[0], floppy->sense_key, floppy->asc, floppy->ascq); + printk(KERN_ERR "ide-floppy: %s: I/O error, pc = %2x," + " key = %2x, asc = %2x, ascq = %2x\n", + drive->name, floppy->failed_pc->c[0], + floppy->sense_key, floppy->asc, floppy->ascq); else - printk (KERN_ERR "ide-floppy: %s: I/O error\n", drive->name); - idefloppy_end_request (0, HWGROUP(drive)); + printk(KERN_ERR "ide-floppy: %s: I/O error\n", + drive->name); + idefloppy_do_end_request(drive, 0); return ide_stopped; } switch (rq->cmd) { case READ: case WRITE: - if (rq->sector % floppy->bs_factor || rq->nr_sectors % floppy->bs_factor) { - printk ("%s: unsupported r/w request size\n", drive->name); - idefloppy_end_request (0, HWGROUP(drive)); + if (rq->sector % floppy->bs_factor || + rq->nr_sectors % floppy->bs_factor) { + printk("%s: unsupported r/w request size\n", + drive->name); + idefloppy_do_end_request(drive, 0); return ide_stopped; } pc = idefloppy_next_pc_storage (drive); @@ -1328,8 +1387,9 @@ pc = (idefloppy_pc_t *) rq->buffer; break; default: - printk (KERN_ERR "ide-floppy: unsupported command %x in request queue\n", rq->cmd); - idefloppy_end_request (0,HWGROUP (drive)); + printk(KERN_ERR "ide-floppy: unsupported command %x" + " in request queue\n", rq->cmd); + idefloppy_do_end_request(drive, 0); return ide_stopped; } pc->rq = rq; @@ -1377,8 +1437,10 @@ page->rpm = ntohs (page->rpm); capacity = page->cyls * page->heads * page->sectors * page->sector_size; if (memcmp (page, &floppy->flexible_disk_page, sizeof (idefloppy_flexible_disk_page_t))) - printk (KERN_INFO "%s: %dkB, %d/%d/%d CHS, %d kBps, %d sector size, %d rpm\n", - drive->name, capacity / 1024, page->cyls, page->heads, page->sectors, + printk(KERN_INFO "%s: %dkB, %d/%d/%d CHS, %d kBps, " + "%d sector size, %d rpm\n", + drive->name, capacity / 1024, page->cyls, + page->heads, page->sectors, page->transfer_rate / 8, page->sector_size, page->rpm); floppy->flexible_disk_page = *page; @@ -1387,8 +1449,8 @@ drive->bios_sect = page->sectors; lba_capacity = floppy->blocks * floppy->block_size; if (capacity < lba_capacity) { - printk (KERN_NOTICE "%s: The disk reports a capacity of %d bytes, " - "but the drive only handles %d\n", + printk(KERN_NOTICE "%s: The disk reports a capacity of %d " + "bytes, but the drive only handles %d\n", drive->name, lba_capacity, capacity); floppy->blocks = floppy->block_size ? capacity / floppy->block_size : 0; } @@ -1483,8 +1545,7 @@ } /* Clik! disk does not support get_flexible_disk_page */ - if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) - { + if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) { (void) idefloppy_get_flexible_disk_page (drive); } @@ -1659,10 +1720,9 @@ idefloppy_status_reg_t status; unsigned long flags; - __save_flags(flags); - __cli(); + local_irq_save(flags); status.all=GET_STAT(); - __restore_flags(flags); + local_irq_restore(flags); progress_indication= !status.b.dsc ? 0:0x10000; } @@ -2089,6 +2149,7 @@ #endif /* CONFIG_PROC_FS */ +int idefloppy_init (void); int idefloppy_reinit(ide_drive_t *drive); /* @@ -2099,13 +2160,21 @@ version: IDEFLOPPY_VERSION, media: ide_floppy, busy: 0, +#ifdef CONFIG_IDEDMA_ONLYDISK + supports_dma: 0, +#else supports_dma: 1, +#endif supports_dsc_overlap: 0, cleanup: idefloppy_cleanup, standby: NULL, + suspend: NULL, + resume: NULL, flushcache: NULL, do_request: idefloppy_do_request, - end_request: idefloppy_end_request, + end_request: idefloppy_do_end_request, + sense: NULL, + error: NULL, ioctl: idefloppy_ioctl, open: idefloppy_open, release: idefloppy_release, @@ -2115,12 +2184,12 @@ capacity: idefloppy_capacity, special: NULL, proc: idefloppy_proc, + init: idefloppy_init, reinit: idefloppy_reinit, ata_prebuilder: NULL, atapi_prebuilder: NULL, }; -int idefloppy_init (void); static ide_module_t idefloppy_module = { IDE_DRIVER_MODULE, idefloppy_init, diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/ide-pci.c linux.19rc3-ac4/drivers/ide/ide-pci.c --- linux.19rc3/drivers/ide/ide-pci.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/ide-pci.c 2002-07-29 13:58:40.000000000 +0100 @@ -12,6 +12,13 @@ * configuration of all PCI IDE interfaces present in a system. */ +/* + * Chipsets that are on the IDE_IGNORE list because of problems of not being + * set at compile time. + * + * CONFIG_BLK_DEV_PDC202XX + */ + #include #include #include @@ -30,29 +37,32 @@ #define DEVID_MPIIX ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371MX}) #define DEVID_PIIX3 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1}) #define DEVID_PIIX4 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB}) -#define DEVID_ICH0 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_1}) +#define DEVID_PIIX4E ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_1}) #define DEVID_PIIX4E2 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_1}) -#define DEVID_ICH ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_1}) +#define DEVID_PIIX4U ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_1}) #define DEVID_PIIX4U2 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82372FB_1}) #define DEVID_PIIX4NX ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX}) -#define DEVID_ICH2 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_9}) -#define DEVID_ICH2M ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_8}) -#define DEVID_ICH3M ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10}) -#define DEVID_ICH3 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_11}) -#define DEVID_ICH4 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_11}) -#define DEVID_CICH ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_11}) +#define DEVID_PIIX4U3 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_9}) +#define DEVID_PIIX4U4 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_8}) +#define DEVID_PIIX4U5 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10}) +#define DEVID_PIIX4U6 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_11}) +#define DEVID_PIIX4U7 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_11}) +#define DEVID_PIIX4U8 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_11}) #define DEVID_VIA_IDE ((ide_pci_devid_t){PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561}) #define DEVID_MR_IDE ((ide_pci_devid_t){PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576_1}) #define DEVID_VP_IDE ((ide_pci_devid_t){PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1}) #define DEVID_PDC20246 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20246}) #define DEVID_PDC20262 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20262}) +#define DEVID_PDC20263 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20263}) #define DEVID_PDC20265 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20265}) #define DEVID_PDC20267 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20267}) #define DEVID_PDC20268 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268}) -#define DEVID_PDC20270 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20270}) +#define DEVID_PDC20270 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20270}) #define DEVID_PDC20269 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20269}) +#define DEVID_PDC20271 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20271}) #define DEVID_PDC20275 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20275}) #define DEVID_PDC20276 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20276}) +#define DEVID_PDC20277 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20277}) #define DEVID_RZ1000 ((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000}) #define DEVID_RZ1001 ((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001}) #define DEVID_SAMURAI ((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_SAMURAI_IDE}) @@ -73,12 +83,18 @@ #define DEVID_AEC6210 ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF}) #define DEVID_AEC6260 ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860}) #define DEVID_AEC6260R ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860R}) +#define DEVID_AEC6280 ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP865}) +#define DEVID_AEC6880 ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP865R}) #define DEVID_W82C105 ((ide_pci_devid_t){PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105}) #define DEVID_UM8673F ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8673F}) #define DEVID_UM8886A ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886A}) #define DEVID_UM8886BF ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF}) #define DEVID_HPT34X ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT343}) #define DEVID_HPT366 ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT366}) +#define DEVID_HPT372 ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT372}) +#define DEVID_HPT302 ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT302}) +#define DEVID_HPT371 ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT371}) +#define DEVID_HPT374 ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT374}) #define DEVID_ALI15X3 ((ide_pci_devid_t){PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229}) #define DEVID_CY82C693 ((ide_pci_devid_t){PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693}) #define DEVID_HINT ((ide_pci_devid_t){0x3388, 0x8013}) @@ -91,21 +107,25 @@ #define DEVID_SLC90E66 ((ide_pci_devid_t){PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1}) #define DEVID_OSB4 ((ide_pci_devid_t){PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE}) #define DEVID_CSB5 ((ide_pci_devid_t){PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE}) +#define DEVID_CSB6 ((ide_pci_devid_t){PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE}) #define DEVID_ITE8172G ((ide_pci_devid_t){PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_IT8172G}) #define IDE_IGNORE ((void *)-1) #define IDE_NO_DRIVER ((void *)-2) #ifdef CONFIG_BLK_DEV_AEC62XX +extern void fixup_device_aec6x80(struct pci_dev *, ide_pci_device_t *); extern unsigned int pci_init_aec62xx(struct pci_dev *, const char *); extern unsigned int ata66_aec62xx(ide_hwif_t *); extern void ide_init_aec62xx(ide_hwif_t *); extern void ide_dmacapable_aec62xx(ide_hwif_t *, unsigned long); +#define FIXUP_AEC62XX &fixup_device_aec6x80 #define PCI_AEC62XX &pci_init_aec62xx #define ATA66_AEC62XX &ata66_aec62xx #define INIT_AEC62XX &ide_init_aec62xx #define DMA_AEC62XX &ide_dmacapable_aec62xx #else +#define FIXUP_AEC62XX NULL #define PCI_AEC62XX NULL #define ATA66_AEC62XX NULL #define INIT_AEC62XX IDE_NO_DRIVER @@ -113,15 +133,18 @@ #endif #ifdef CONFIG_BLK_DEV_ALI15X3 +extern void fixup_device_ali15x3(struct pci_dev *, ide_pci_device_t *); extern unsigned int pci_init_ali15x3(struct pci_dev *, const char *); extern unsigned int ata66_ali15x3(ide_hwif_t *); extern void ide_init_ali15x3(ide_hwif_t *); extern void ide_dmacapable_ali15x3(ide_hwif_t *, unsigned long); +#define FIXUP_ALI15X3 &fixup_device_ali15x3 #define PCI_ALI15X3 &pci_init_ali15x3 #define ATA66_ALI15X3 &ata66_ali15x3 #define INIT_ALI15X3 &ide_init_ali15x3 #define DMA_ALI15X3 &ide_dmacapable_ali15x3 #else +#define FIXUP_ALI15X3 NULL #define PCI_ALI15X3 NULL #define ATA66_ALI15X3 NULL #define INIT_ALI15X3 IDE_NO_DRIVER @@ -129,15 +152,18 @@ #endif #ifdef CONFIG_BLK_DEV_AMD74XX +extern void fixup_device_amd74xx(struct pci_dev *, ide_pci_device_t *); extern unsigned int pci_init_amd74xx(struct pci_dev *, const char *); extern unsigned int ata66_amd74xx(ide_hwif_t *); extern void ide_init_amd74xx(ide_hwif_t *); extern void ide_dmacapable_amd74xx(ide_hwif_t *, unsigned long); +#define FIXUP_AMD74XX &fixup_device_amd74xx #define PCI_AMD74XX &pci_init_amd74xx #define ATA66_AMD74XX &ata66_amd74xx #define INIT_AMD74XX &ide_init_amd74xx #define DMA_AMD74XX &ide_dmacapable_amd74xx #else +#define FIXUP_AMD74XX NULL #define PCI_AMD74XX NULL #define ATA66_AMD74XX NULL #define INIT_AMD74XX IDE_NO_DRIVER @@ -163,11 +189,14 @@ #endif #ifdef CONFIG_BLK_DEV_CY82C693 +extern void fixup_device_cy82c693(struct pci_dev *, ide_pci_device_t *); extern unsigned int pci_init_cy82c693(struct pci_dev *, const char *); extern void ide_init_cy82c693(ide_hwif_t *); +#define FIXUP_CY82C693 &fixup_device_cy82c693 #define PCI_CY82C693 &pci_init_cy82c693 #define INIT_CY82C693 &ide_init_cy82c693 #else +#define FIXUP_CY82C693 NULL #define PCI_CY82C693 NULL #define INIT_CY82C693 IDE_NO_DRIVER #endif @@ -183,29 +212,34 @@ #endif #ifdef CONFIG_BLK_DEV_HPT34X +extern void fixup_device_hpt343(struct pci_dev *, ide_pci_device_t *); extern unsigned int pci_init_hpt34x(struct pci_dev *, const char *); extern void ide_init_hpt34x(ide_hwif_t *); +#define FIXUP_HPT34X &fixup_device_hpt343 #define PCI_HPT34X &pci_init_hpt34x #define INIT_HPT34X &ide_init_hpt34x #else +#define FIXUP_HPT34X NULL #define PCI_HPT34X NULL #define INIT_HPT34X IDE_IGNORE #endif #ifdef CONFIG_BLK_DEV_HPT366 -extern byte hpt363_shared_irq; -extern byte hpt363_shared_pin; +extern void fixup_device_hpt366(struct pci_dev *, ide_pci_device_t *); +extern void fixup_device_hpt374(struct pci_dev *, ide_pci_device_t *); extern unsigned int pci_init_hpt366(struct pci_dev *, const char *); extern unsigned int ata66_hpt366(ide_hwif_t *); extern void ide_init_hpt366(ide_hwif_t *); extern void ide_dmacapable_hpt366(ide_hwif_t *, unsigned long); +#define FIXUP_HPT366 &fixup_device_hpt366 +#define FIXUP_HPT374 &fixup_device_hpt374 #define PCI_HPT366 &pci_init_hpt366 #define ATA66_HPT366 &ata66_hpt366 #define INIT_HPT366 &ide_init_hpt366 #define DMA_HPT366 &ide_dmacapable_hpt366 #else -static byte hpt363_shared_irq; -static byte hpt363_shared_pin; +#define FIXUP_HPT366 NULL +#define FIXUP_HPT374 NULL #define PCI_HPT366 NULL #define ATA66_HPT366 NULL #define INIT_HPT366 IDE_NO_DRIVER @@ -220,9 +254,12 @@ #endif #ifdef CONFIG_BLK_DEV_OPTI621 +extern void fixup_device_opti621(struct pci_dev *, ide_pci_device_t *); extern void ide_init_opti621(ide_hwif_t *); +#define FIXUP_OPTI621 &fixup_device_opti621 #define INIT_OPTI621 &ide_init_opti621 #else +#define FIXUP_OPTI621 NULL #define INIT_OPTI621 IDE_NO_DRIVER #endif @@ -243,41 +280,54 @@ #endif #ifdef CONFIG_BLK_DEV_PDC202XX +extern void fixup_device_pdc20265(struct pci_dev *, ide_pci_device_t *); +extern void fixup_device_pdc20270(struct pci_dev *, ide_pci_device_t *); extern unsigned int pci_init_pdc202xx(struct pci_dev *, const char *); extern unsigned int ata66_pdc202xx(ide_hwif_t *); extern void ide_init_pdc202xx(ide_hwif_t *); +#define FIXUP_PDC20265 &fixup_device_pdc20265 +#define FIXUP_PDC20270 &fixup_device_pdc20270 #define PCI_PDC202XX &pci_init_pdc202xx #define ATA66_PDC202XX &ata66_pdc202xx #define INIT_PDC202XX &ide_init_pdc202xx #else -#define PCI_PDC202XX NULL -#define ATA66_PDC202XX NULL -#define INIT_PDC202XX NULL +#define FIXUP_PDC20265 IDE_IGNORE +#define FIXUP_PDC20270 IDE_IGNORE +#define PCI_PDC202XX IDE_IGNORE +#define ATA66_PDC202XX IDE_IGNORE +#define INIT_PDC202XX IDE_IGNORE #endif #ifdef CONFIG_BLK_DEV_PIIX +extern void fixup_device_piix(struct pci_dev *, ide_pci_device_t *); extern unsigned int pci_init_piix(struct pci_dev *, const char *); extern unsigned int ata66_piix(ide_hwif_t *); extern void ide_init_piix(ide_hwif_t *); +#define FIXUP_PIIX &fixup_device_piix #define PCI_PIIX &pci_init_piix #define ATA66_PIIX &ata66_piix #define INIT_PIIX &ide_init_piix #else +#define FIXUP_PIIX NULL #define PCI_PIIX NULL #define ATA66_PIIX NULL #define INIT_PIIX IDE_NO_DRIVER #endif #ifdef CONFIG_BLK_DEV_IT8172 +extern void fixup_device_it8172(struct pci_dev *, ide_pci_device_t *); extern unsigned int pci_init_it8172(struct pci_dev *, const char *); extern unsigned int ata66_it8172(ide_hwif_t *); extern void ide_init_it8172(ide_hwif_t *); +#define FIXUP_IT8172 &fixup_device_it8172 #define PCI_IT8172 &pci_init_it8172 +#define ATA66_IT8172 &ata66_it8172 #define INIT_IT8172 &ide_init_it8172 #else +#define FIXUP_IT8172 NULL #define PCI_IT8172 NULL #define ATA66_IT8172 NULL -#define INIT_IT8172 NULL +#define INIT_IT8172 IDE_NO_DRIVER #endif #ifdef CONFIG_BLK_DEV_RZ1000 @@ -290,26 +340,35 @@ #define INIT_SAMURAI NULL #ifdef CONFIG_BLK_DEV_SVWKS +extern void fixup_device_csb6(struct pci_dev *, ide_pci_device_t *); extern unsigned int pci_init_svwks(struct pci_dev *, const char *); extern unsigned int ata66_svwks(ide_hwif_t *); extern void ide_init_svwks(ide_hwif_t *); +extern void ide_dmacapable_svwks(ide_hwif_t *, unsigned long); +#define FIXUP_CSB6 &fixup_device_csb6 #define PCI_SVWKS &pci_init_svwks #define ATA66_SVWKS &ata66_svwks #define INIT_SVWKS &ide_init_svwks +#define DMA_SVWKS &ide_dmacapable_svwks #else +#define FIXUP_CSB6 NULL #define PCI_SVWKS NULL #define ATA66_SVWKS NULL #define INIT_SVWKS IDE_NO_DRIVER +#define DMA_SVWKS NULL #endif #ifdef CONFIG_BLK_DEV_SIS5513 +extern void fixup_device_sis5513(struct pci_dev *, ide_pci_device_t *); extern unsigned int pci_init_sis5513(struct pci_dev *, const char *); extern unsigned int ata66_sis5513(ide_hwif_t *); extern void ide_init_sis5513(ide_hwif_t *); +#define FIXUP_SIS5513 &fixup_device_sis5513 #define PCI_SIS5513 &pci_init_sis5513 #define ATA66_SIS5513 &ata66_sis5513 #define INIT_SIS5513 &ide_init_sis5513 #else +#define FIXUP_SIS5513 NULL #define PCI_SIS5513 NULL #define ATA66_SIS5513 NULL #define INIT_SIS5513 IDE_NO_DRIVER @@ -364,106 +423,98 @@ #define DMA_VIA82CXXX NULL #endif -typedef struct ide_pci_enablebit_s { - byte reg; /* byte pci reg holding the enable-bit */ - byte mask; /* mask to isolate the enable-bit */ - byte val; /* value of masked reg when "enabled" */ -} ide_pci_enablebit_t; - -typedef struct ide_pci_device_s { - ide_pci_devid_t devid; - char *name; - unsigned int (*init_chipset)(struct pci_dev *dev, const char *name); - unsigned int (*ata66_check)(ide_hwif_t *hwif); - void (*init_hwif)(ide_hwif_t *hwif); - void (*dma_init)(ide_hwif_t *hwif, unsigned long dmabase); - ide_pci_enablebit_t enablebits[2]; - byte bootable; - unsigned int extra; -} ide_pci_device_t; - static ide_pci_device_t ide_pci_chipsets[] __initdata = { - {DEVID_PIIXa, "PIIX", NULL, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIXb, "PIIX", NULL, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_MPIIX, "MPIIX", NULL, NULL, INIT_PIIX, NULL, {{0x6D,0x80,0x80}, {0x6F,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX3, "PIIX3", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX4, "PIIX4", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_ICH0, "ICH0", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX4E2, "PIIX4", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_ICH, "ICH", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX4U2, "PIIX4", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX4NX, "PIIX4", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_ICH2, "ICH2", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_ICH2M, "ICH2M", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_ICH3M, "ICH3M", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_ICH3, "ICH3", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_ICH4, "ICH4", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_CICH, "C-ICH", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_VIA_IDE, "VIA_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_MR_IDE, "VP_IDE", PCI_VIA82CXXX, ATA66_VIA82CXXX,INIT_VIA82CXXX, DMA_VIA82CXXX, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 }, - {DEVID_VP_IDE, "VP_IDE", PCI_VIA82CXXX, ATA66_VIA82CXXX,INIT_VIA82CXXX, DMA_VIA82CXXX, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 }, + {DEVID_PIIXa, "PIIX", FIXUP_PIIX, PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIXb, "PIIX", FIXUP_PIIX, PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_MPIIX, "MPIIX", FIXUP_PIIX, NULL, NULL, INIT_PIIX, NULL, {{0x6D,0x80,0x80}, {0x6F,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX3, "PIIX3", FIXUP_PIIX, PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX4, "PIIX4", FIXUP_PIIX, PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX4E, "PIIX4", FIXUP_PIIX, PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX4E2, "PIIX4", FIXUP_PIIX, PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX4U, "PIIX4", FIXUP_PIIX, PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX4U2, "PIIX4", FIXUP_PIIX, PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX4NX, "PIIX4", FIXUP_PIIX, PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX4U3, "PIIX4", FIXUP_PIIX, PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX4U4, "PIIX4", FIXUP_PIIX, PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX4U5, "PIIX4", FIXUP_PIIX, PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX4U6, "PIIX4", FIXUP_PIIX, PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX4U7, "PIIX4", FIXUP_PIIX, PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX4U8, "PIIX4", FIXUP_PIIX, PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_VIA_IDE, "VIA_IDE", NULL, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_MR_IDE, "VP_IDE", NULL, PCI_VIA82CXXX, ATA66_VIA82CXXX,INIT_VIA82CXXX, DMA_VIA82CXXX, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 }, + {DEVID_VP_IDE, "VP_IDE", NULL, PCI_VIA82CXXX, ATA66_VIA82CXXX,INIT_VIA82CXXX, DMA_VIA82CXXX, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 }, #ifdef CONFIG_PDC202XX_FORCE - {DEVID_PDC20246,"PDC20246", PCI_PDC202XX, NULL, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 16 }, - {DEVID_PDC20262,"PDC20262", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 48 }, - {DEVID_PDC20265,"PDC20265", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 48 }, - {DEVID_PDC20267,"PDC20267", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 48 }, + {DEVID_PDC20246,"PDC20246", NULL, PCI_PDC202XX, NULL, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 16 }, + {DEVID_PDC20262,"PDC20262", NULL, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 48 }, + {DEVID_PDC20263,"PDC20263", NULL, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 48 }, + {DEVID_PDC20265,"PDC20265", FIXUP_PDC20265, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 48 }, + {DEVID_PDC20267,"PDC20267", NULL, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 48 }, #else /* !CONFIG_PDC202XX_FORCE */ - {DEVID_PDC20246,"PDC20246", PCI_PDC202XX, NULL, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 16 }, - {DEVID_PDC20262,"PDC20262", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, - {DEVID_PDC20265,"PDC20265", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, - {DEVID_PDC20267,"PDC20267", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, -#endif - {DEVID_PDC20268,"PDC20268", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - /* Promise used a different PCI ident for the raid card apparently to try and - prevent Linux detecting it and using our own raid code. We want to detect - it for the ataraid drivers, so we have to list both here.. */ - {DEVID_PDC20270,"PDC20270", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {DEVID_PDC20269,"PDC20269", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {DEVID_PDC20275,"PDC20275", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {DEVID_PDC20276,"PDC20276", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {DEVID_RZ1000, "RZ1000", NULL, NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_RZ1001, "RZ1001", NULL, NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_SAMURAI, "SAMURAI", NULL, NULL, INIT_SAMURAI, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CMD640, "CMD640", NULL, NULL, IDE_IGNORE, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_NS87410, "NS87410", NULL, NULL, NULL, NULL, {{0x43,0x08,0x08}, {0x47,0x08,0x08}}, ON_BOARD, 0 }, - {DEVID_SIS5513, "SIS5513", PCI_SIS5513, ATA66_SIS5513, INIT_SIS5513, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, ON_BOARD, 0 }, - {DEVID_CMD643, "CMD643", PCI_CMD64X, NULL, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CMD646, "CMD646", PCI_CMD64X, NULL, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x51,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_CMD648, "CMD648", PCI_CMD64X, ATA66_CMD64X, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CMD649, "CMD649", PCI_CMD64X, ATA66_CMD64X, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, -#ifndef CONFIG_BLK_DEV_CMD680 - {DEVID_CMD680, "CMD680", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, -#else /* CONFIG_BLK_DEV_CMD680 */ - {DEVID_CMD680, "CMD680", PCI_CMD64X, ATA66_CMD64X, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, -#endif /* !CONFIG_BLK_DEV_CMD680 */ - {DEVID_HT6565, "HT6565", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_OPTI621, "OPTI621", NULL, NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 }, - {DEVID_OPTI621X,"OPTI621X", NULL, NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 }, - {DEVID_TRM290, "TRM290", NULL, NULL, INIT_TRM290, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_NS87415, "NS87415", NULL, NULL, INIT_NS87415, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_AEC6210, "AEC6210", PCI_AEC62XX, NULL, INIT_AEC62XX, DMA_AEC62XX, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, OFF_BOARD, 0 }, - {DEVID_AEC6260, "AEC6260", PCI_AEC62XX, ATA66_AEC62XX, INIT_AEC62XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 0 }, - {DEVID_AEC6260R,"AEC6260R", PCI_AEC62XX, ATA66_AEC62XX, INIT_AEC62XX, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, OFF_BOARD, 0 }, - {DEVID_W82C105, "W82C105", PCI_W82C105, NULL, INIT_W82C105, DMA_W82C105, {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, ON_BOARD, 0 }, - {DEVID_UM8673F, "UM8673F", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_UM8886A, "UM8886A", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_UM8886BF,"UM8886BF", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_HPT34X, "HPT34X", PCI_HPT34X, NULL, INIT_HPT34X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 16 }, - {DEVID_HPT366, "HPT366", PCI_HPT366, ATA66_HPT366, INIT_HPT366, DMA_HPT366, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 240 }, - {DEVID_ALI15X3, "ALI15X3", PCI_ALI15X3, ATA66_ALI15X3, INIT_ALI15X3, DMA_ALI15X3, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CY82C693,"CY82C693", PCI_CY82C693, NULL, INIT_CY82C693, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_HINT, "HINT_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CS5530, "CS5530", PCI_CS5530, NULL, INIT_CS5530, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_AMD7401, "AMD7401", NULL, NULL, NULL, DMA_AMD74XX, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, - {DEVID_AMD7409, "AMD7409", PCI_AMD74XX, ATA66_AMD74XX, INIT_AMD74XX, DMA_AMD74XX, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, - {DEVID_AMD7411, "AMD7411", PCI_AMD74XX, ATA66_AMD74XX, INIT_AMD74XX, DMA_AMD74XX, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, - {DEVID_AMD7441, "AMD7441", PCI_AMD74XX, ATA66_AMD74XX, INIT_AMD74XX, DMA_AMD74XX, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, - {DEVID_PDCADMA, "PDCADMA", PCI_PDCADMA, ATA66_PDCADMA, INIT_PDCADMA, DMA_PDCADMA, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {DEVID_SLC90E66,"SLC90E66", PCI_SLC90E66, ATA66_SLC90E66, INIT_SLC90E66, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_OSB4, "ServerWorks OSB4", PCI_SVWKS, ATA66_SVWKS, INIT_SVWKS, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CSB5, "ServerWorks CSB5", PCI_SVWKS, ATA66_SVWKS, INIT_SVWKS, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_ITE8172G,"IT8172G", PCI_IT8172, NULL, INIT_IT8172, NULL, {{0x00,0x00,0x00}, {0x40,0x00,0x01}}, ON_BOARD, 0 }, - {IDE_PCI_DEVID_NULL, "PCI_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }}; + {DEVID_PDC20246,"PDC20246", NULL, PCI_PDC202XX, NULL, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 16 }, + {DEVID_PDC20262,"PDC20262", NULL, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, + {DEVID_PDC20263,"PDC20263", NULL, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, + {DEVID_PDC20265,"PDC20265", FIXUP_PDC20265, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, + {DEVID_PDC20267,"PDC20267", NULL, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, +#endif + {DEVID_PDC20268,"PDC20268", NULL, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, + /* + * Promise used a different PCI ident for the raid card apparently + * to try and prevent Linux detecting it and using our own raid code. + * We want to detect it for the ataraid drivers, so we have to list + * both here.. + */ + {DEVID_PDC20270,"PDC20270", FIXUP_PDC20270, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, + {DEVID_PDC20269,"PDC20269", NULL, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, + {DEVID_PDC20271,"PDC20271", NULL, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, + {DEVID_PDC20275,"PDC20275", NULL, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, + {DEVID_PDC20276,"PDC20276", NULL, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, + {DEVID_PDC20277,"PDC20277", NULL, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, + {DEVID_RZ1000, "RZ1000", NULL, NULL, NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_RZ1001, "RZ1001", NULL, NULL, NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_SAMURAI, "SAMURAI", NULL, NULL, NULL, INIT_SAMURAI, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_CMD640, "CMD640", NULL, NULL, NULL, IDE_IGNORE, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_NS87410, "NS87410", NULL, NULL, NULL, NULL, NULL, {{0x43,0x08,0x08}, {0x47,0x08,0x08}}, ON_BOARD, 0 }, + {DEVID_SIS5513, "SIS5513", FIXUP_SIS5513, PCI_SIS5513, ATA66_SIS5513, INIT_SIS5513, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, ON_BOARD, 0 }, + {DEVID_CMD643, "CMD643", NULL, PCI_CMD64X, NULL, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_CMD646, "CMD646", NULL, PCI_CMD64X, NULL, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x51,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_CMD648, "CMD648", NULL, PCI_CMD64X, ATA66_CMD64X, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_CMD649, "CMD649", NULL, PCI_CMD64X, ATA66_CMD64X, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_CMD680, "CMD680", NULL, PCI_CMD64X, ATA66_CMD64X, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_HT6565, "HT6565", NULL, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_OPTI621, "OPTI621", FIXUP_OPTI621, NULL, NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 }, + {DEVID_OPTI621X,"OPTI621X", FIXUP_OPTI621, NULL, NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 }, + {DEVID_TRM290, "TRM290", NULL, NULL, NULL, INIT_TRM290, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_NS87415, "NS87415", NULL, NULL, NULL, INIT_NS87415, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_AEC6210, "AEC6210", NULL, PCI_AEC62XX, NULL, INIT_AEC62XX, DMA_AEC62XX, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, OFF_BOARD, 0 }, + {DEVID_AEC6260, "AEC6260", NULL, PCI_AEC62XX, ATA66_AEC62XX, INIT_AEC62XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 0 }, + {DEVID_AEC6260R,"AEC6260R", NULL, PCI_AEC62XX, ATA66_AEC62XX, INIT_AEC62XX, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, OFF_BOARD, 0 }, + {DEVID_AEC6280, "AEC6X80", FIXUP_AEC62XX, PCI_AEC62XX, ATA66_AEC62XX, INIT_AEC62XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 0 }, + {DEVID_AEC6880, "AEC6X80R", FIXUP_AEC62XX, PCI_AEC62XX, ATA66_AEC62XX, INIT_AEC62XX, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, OFF_BOARD, 0 }, + {DEVID_W82C105, "W82C105", NULL, PCI_W82C105, NULL, INIT_W82C105, DMA_W82C105, {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, ON_BOARD, 0 }, + {DEVID_UM8673F, "UM8673F", NULL, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_UM8886A, "UM8886A", NULL, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_UM8886BF,"UM8886BF", NULL, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_HPT34X, "HPT34X", FIXUP_HPT34X, PCI_HPT34X, NULL, INIT_HPT34X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 16 }, + {DEVID_HPT366, "HPT366", FIXUP_HPT366, PCI_HPT366, ATA66_HPT366, INIT_HPT366, DMA_HPT366, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 240 }, + {DEVID_HPT372, "HPT372A", NULL, PCI_HPT366, ATA66_HPT366, INIT_HPT366, DMA_HPT366, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, + {DEVID_HPT302, "HPT302", NULL, PCI_HPT366, ATA66_HPT366, INIT_HPT366, DMA_HPT366, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, + {DEVID_HPT371, "HPT371", NULL, PCI_HPT366, ATA66_HPT366, INIT_HPT366, DMA_HPT366, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, + {DEVID_HPT374, "HPT374", FIXUP_HPT374, PCI_HPT366, ATA66_HPT366, INIT_HPT366, DMA_HPT366, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, + {DEVID_ALI15X3, "ALI15X3", FIXUP_ALI15X3, PCI_ALI15X3, ATA66_ALI15X3, INIT_ALI15X3, DMA_ALI15X3, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_CY82C693,"CY82C693", FIXUP_CY82C693, PCI_CY82C693, NULL, INIT_CY82C693, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_HINT, "HINT_IDE", NULL, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_CS5530, "CS5530", NULL, PCI_CS5530, NULL, INIT_CS5530, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_AMD7401, "AMD7401", FIXUP_AMD74XX, NULL, NULL, NULL, DMA_AMD74XX, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, + {DEVID_AMD7409, "AMD7409", FIXUP_AMD74XX, PCI_AMD74XX, ATA66_AMD74XX, INIT_AMD74XX, DMA_AMD74XX, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, + {DEVID_AMD7411, "AMD7411", FIXUP_AMD74XX, PCI_AMD74XX, ATA66_AMD74XX, INIT_AMD74XX, DMA_AMD74XX, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, + {DEVID_AMD7441, "AMD7441", FIXUP_AMD74XX, PCI_AMD74XX, ATA66_AMD74XX, INIT_AMD74XX, DMA_AMD74XX, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, + {DEVID_PDCADMA, "PDCADMA", NULL, PCI_PDCADMA, ATA66_PDCADMA, INIT_PDCADMA, DMA_PDCADMA, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, + {DEVID_SLC90E66,"SLC90E66", NULL, PCI_SLC90E66, ATA66_SLC90E66, INIT_SLC90E66, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_OSB4, "SvrWks OSB4", NULL, PCI_SVWKS, ATA66_SVWKS, INIT_SVWKS, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_CSB5, "SvrWks CSB5", NULL, PCI_SVWKS, ATA66_SVWKS, INIT_SVWKS, DMA_SVWKS, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_CSB6, "SvrWks CSB6", FIXUP_CSB6, PCI_SVWKS, ATA66_SVWKS, INIT_SVWKS, DMA_SVWKS, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_ITE8172G,"IT8172G", FIXUP_IT8172, PCI_IT8172, NULL, INIT_IT8172, NULL, {{0x00,0x00,0x00}, {0x40,0x00,0x01}}, ON_BOARD, 0 }, + {IDE_PCI_DEVID_NULL, "PCI_IDE", NULL, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }}; /* * This allows offboard ide-pci cards the enable a BIOS, verify interrupt @@ -474,18 +525,33 @@ { switch(dev->device) { case PCI_DEVICE_ID_TTI_HPT366: + case PCI_DEVICE_ID_TTI_HPT372: + case PCI_DEVICE_ID_TTI_HPT302: + case PCI_DEVICE_ID_TTI_HPT371: + case PCI_DEVICE_ID_TTI_HPT374: case PCI_DEVICE_ID_PROMISE_20246: case PCI_DEVICE_ID_PROMISE_20262: + case PCI_DEVICE_ID_PROMISE_20263: case PCI_DEVICE_ID_PROMISE_20265: case PCI_DEVICE_ID_PROMISE_20267: case PCI_DEVICE_ID_PROMISE_20268: case PCI_DEVICE_ID_PROMISE_20270: case PCI_DEVICE_ID_PROMISE_20269: + case PCI_DEVICE_ID_PROMISE_20271: case PCI_DEVICE_ID_PROMISE_20275: case PCI_DEVICE_ID_PROMISE_20276: - case PCI_DEVICE_ID_ARTOP_ATP850UF: - case PCI_DEVICE_ID_ARTOP_ATP860: - case PCI_DEVICE_ID_ARTOP_ATP860R: + case PCI_DEVICE_ID_PROMISE_20277: + /* + * case PCI_DEVICE_ID_ARTOP_ATP850UF: + * same device ID value as PCI_DEVICE_ID_TTI_HPT372 + * case PCI_DEVICE_ID_ARTOP_ATP860: + * same device ID value as PCI_DEVICE_ID_TTI_HPT302 + * case PCI_DEVICE_ID_ARTOP_ATP860R: + * same device ID value as PCI_DEVICE_ID_TTI_HPT371 + * case PCI_DEVICE_ID_ARTOP_ATP865: + * same device ID value as PCI_DEVICE_ID_TTI_HPT374 + */ + case PCI_DEVICE_ID_ARTOP_ATP865R: return dev->irq; default: break; @@ -523,7 +589,8 @@ if (hwif->io_ports[IDE_DATA_OFFSET] == io_base) { if (hwif->chipset == ide_unknown) return hwif; /* match */ - printk("%s: port 0x%04lx already claimed by %s\n", name, io_base, hwif->name); + printk("%s: port 0x%04lx already claimed by %s\n", + name, io_base, hwif->name); return NULL; /* already claimed */ } } @@ -566,9 +633,11 @@ /* * Place both IDE interfaces into PCI "native" mode: */ - if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || (progif & 5) != 5) { + if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || + (progif & 5) != 5) { if ((progif & 0xa) != 0xa) { - printk("%s: device not capable of full native PCI mode\n", name); + printk("%s: device not capable of full " + "native PCI mode\n", name); return 1; } printk("%s: placing both ports into native PCI mode\n", name); @@ -603,7 +672,7 @@ * we "know" about, this information is in the ide_pci_device_t struct; * for all other chipsets, we just assume both interfaces are enabled. */ -static void __init ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d) +void __init ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d) { unsigned int port, at_least_one_hwif_enabled = 0, autodma = 0, pciirq = 0; unsigned short pcicmd = 0, tried_config = 0; @@ -618,12 +687,14 @@ #endif if (d->init_hwif == IDE_NO_DRIVER) { - printk(KERN_WARNING "%s: detected chipset, but driver not compiled in!\n", d->name); + printk(KERN_WARNING "%s: detected chipset, " + "but driver not compiled in!\n", d->name); d->init_hwif = NULL; } if (pci_enable_device(dev)) { - printk(KERN_WARNING "%s: (ide_setup_pci_device:) Could not enable device.\n", d->name); + printk(KERN_WARNING "%s: (ide_setup_pci_device:) " + "Could not enable device.\n", d->name); return; } @@ -654,14 +725,6 @@ pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); class_rev &= 0xff; - - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X)) { - /* see comments in hpt34x.c on why..... */ - char *chipset_names[] = {"HPT343", "HPT345"}; - strcpy(d->name, chipset_names[(pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0]); - d->bootable = (pcicmd & PCI_COMMAND_MEMORY) ? OFF_BOARD : NEVER_BOARD; - } - printk("%s: chipset revision %d\n", d->name, class_rev); /* @@ -669,20 +732,27 @@ */ pciirq = dev->irq; -#ifndef CONFIG_PDC202XX_FORCE - if (dev->class >> 8 == PCI_CLASS_STORAGE_RAID) { - /* - * By rights we want to ignore Promise FastTrak and SuperTrak - * series here, those use own driver. - */ - if (dev->vendor == PCI_VENDOR_ID_PROMISE) { - printk(KERN_INFO "ide: Skipping Promise RAID controller.\n"); - return; + if (dev->class >> 8 == PCI_CLASS_STORAGE_RAID) + { + /* By rights we want to ignore these, but the Promise Fastrak + people have some strange ideas about proprietary so we have + to act otherwise on those. The supertrak however we need + to skip */ + if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20265) || IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20276)) + { + if(dev->bus->self && dev->bus->self->vendor == PCI_VENDOR_ID_INTEL && + (dev->bus->self->device == PCI_DEVICE_ID_INTEL_I960 || dev->bus->self->device == PCI_DEVICE_ID_INTEL_I960RM)) + { + printk(KERN_INFO "ide: Skipping Promise IDE controller attached to I2O RAID controller.\n"); + return; + } } + /* Its attached to something else, just a random bridge. + Suspect a fastrak and fall through */ } -#endif /* CONFIG_PDC202XX_FORCE */ if ((dev->class & ~(0xfa)) != ((PCI_CLASS_STORAGE_IDE << 8) | 5)) { - printk("%s: not 100%% native mode: will probe irqs later\n", d->name); + printk("%s: not 100%% native mode: " + "will probe irqs later\n", d->name); /* * This allows offboard ide-pci cards the enable a BIOS, * verify interrupt settings of split-mirror pci-config @@ -715,34 +785,52 @@ ide_pci_enablebit_t *e = &(d->enablebits[port]); /* - * If this is a Promise FakeRaid controller, the 2nd controller will be marked as - * disabled while it is actually there and enabled by the bios for raid purposes. + * If this is a Promise FakeRaid controller, + * the 2nd controller will be marked as + * disabled while it is actually there and enabled + * by the bios for raid purposes. * Skip the normal "is it enabled" test for those. */ - if ((IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20265)) && (secondpdc++==1) && (port==1) ) + if ((IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20265)) && + (secondpdc++==1) && (port==1)) goto controller_ok; - if ((IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20262)) && (secondpdc++==1) && (port==1) ) + if ((IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20262)) && + (secondpdc++==1) && (port==1)) goto controller_ok; - if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) || (tmp & e->mask) != e->val)) + if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) || + (tmp & e->mask) != e->val)) continue; /* port not enabled */ controller_ok: - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) && (port) && (class_rev < 0x03)) + if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) && + (port) && (class_rev < 0x03)) return; - if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE || (dev->class & (port ? 4 : 1)) != 0) { + if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT302) && (port)) + return; + if (IDE_PCI_DEVID_EQ(d->devid, DEVID_CSB6) && + (port) && (!(PCI_FUNC(dev->devfn) & 1))) + return; + if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE || + (dev->class & (port ? 4 : 1)) != 0) { ctl = dev->resource[(2*port)+1].start; base = dev->resource[2*port].start; if (!(ctl & PCI_BASE_ADDRESS_IO_MASK) || !(base & PCI_BASE_ADDRESS_IO_MASK)) { - printk("%s: IO baseregs (BIOS) are reported as MEM, report to .\n", d->name); + printk("%s: IO baseregs (BIOS) are reported " + "as MEM, report to " + ".\n", d->name); #if 0 - /* FIXME! This really should check that it really gets the IO/MEM part right! */ + /* + * FIXME! This really should check that + * it really gets the IO/MEM part right! + */ continue; #endif } } if ((ctl && !base) || (base && !ctl)) { - printk("%s: inconsistent baseregs (BIOS) for port %d, skipping\n", d->name, port); + printk("%s: inconsistent baseregs (BIOS) " + "for port %d, skipping\n", d->name, port); continue; } if (!ctl) @@ -781,7 +869,8 @@ if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDCADMA)) goto bypass_legacy_dma; if (hwif->udma_four) { - printk("%s: ATA-66/100 forced bit set (WARNING)!!\n", d->name); + printk("%s: ATA-66/100 forced bit set (WARNING)!!\n", + d->name); } else { hwif->udma_four = (d->ata66_check) ? d->ata66_check(hwif) : 0; } @@ -799,18 +888,27 @@ if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246) || IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20262) || + IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20263) || IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20265) || IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20267) || IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20268) || IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20270) || IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20269) || + IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20271) || IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20275) || IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20276) || + IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20277) || IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6210) || IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260) || IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260R) || + IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6280) || + IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6880) || IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X) || IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) || + IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT372) || + IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT302) || + IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT371) || + IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT374) || IDE_PCI_DEVID_EQ(d->devid, DEVID_CS5530) || IDE_PCI_DEVID_EQ(d->devid, DEVID_CY82C693) || IDE_PCI_DEVID_EQ(d->devid, DEVID_CMD646) || @@ -855,102 +953,6 @@ printk("%s: neither IDE port enabled (BIOS)\n", d->name); } -static void __init pdc20270_device_order_fixup (struct pci_dev *dev, ide_pci_device_t *d) -{ - struct pci_dev *dev2 = NULL, *findev; - ide_pci_device_t *d2; - - if ((dev->bus->self && - dev->bus->self->vendor == PCI_VENDOR_ID_DEC) && - (dev->bus->self->device == PCI_DEVICE_ID_DEC_21150)) { - if (PCI_SLOT(dev->devfn) & 2) { - return; - } - d->extra = 0; - pci_for_each_dev(findev) { - if ((findev->vendor == dev->vendor) && - (findev->device == dev->device) && - (PCI_SLOT(findev->devfn) & 2)) { - byte irq = 0, irq2 = 0; - dev2 = findev; - pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); - pci_read_config_byte(dev2, PCI_INTERRUPT_LINE, &irq2); - if (irq != irq2) { - dev2->irq = dev->irq; - pci_write_config_byte(dev2, PCI_INTERRUPT_LINE, irq); - } - - } - } - } - - printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn); - ide_setup_pci_device(dev, d); - if (!dev2) - return; - d2 = d; - printk("%s: IDE controller on PCI bus %02x dev %02x\n", d2->name, dev2->bus->number, dev2->devfn); - ide_setup_pci_device(dev2, d2); -} - -static void __init hpt366_device_order_fixup (struct pci_dev *dev, ide_pci_device_t *d) -{ - struct pci_dev *dev2 = NULL, *findev; - ide_pci_device_t *d2; - unsigned char pin1 = 0, pin2 = 0; - unsigned int class_rev; - char *chipset_names[] = {"HPT366", "HPT366", "HPT368", "HPT370", "HPT370A", "HPT372"}; - - if (PCI_FUNC(dev->devfn) & 1) - return; - - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xff; - if (class_rev > 5) - class_rev = 5; - - strcpy(d->name, chipset_names[class_rev]); - - switch(class_rev) { - case 4: - case 3: printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn); - ide_setup_pci_device(dev, d); - return; - default: break; - } - - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1); - pci_for_each_dev(findev) { - if ((findev->vendor == dev->vendor) && - (findev->device == dev->device) && - ((findev->devfn - dev->devfn) == 1) && - (PCI_FUNC(findev->devfn) & 1)) { - dev2 = findev; - pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2); - hpt363_shared_pin = (pin1 != pin2) ? 1 : 0; - hpt363_shared_irq = (dev->irq == dev2->irq) ? 1 : 0; - if (hpt363_shared_pin && hpt363_shared_irq) { - d->bootable = ON_BOARD; - printk("%s: onboard version of chipset, pin1=%d pin2=%d\n", d->name, pin1, pin2); -#if 0 - /* I forgot why I did this once, but it fixed something. */ - pci_write_config_byte(dev2, PCI_INTERRUPT_PIN, dev->irq); - printk("PCI: %s: Fixing interrupt %d pin %d to ZERO \n", d->name, dev2->irq, pin2); - pci_write_config_byte(dev2, PCI_INTERRUPT_LINE, 0); -#endif - } - break; - } - } - printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn); - ide_setup_pci_device(dev, d); - if (!dev2) - return; - d2 = d; - printk("%s: IDE controller on PCI bus %02x dev %02x\n", d2->name, dev2->bus->number, dev2->devfn); - ide_setup_pci_device(dev2, d2); -} - /* * ide_scan_pcibus() gets invoked at boot time from ide.c. * It finds all PCI IDE controllers and calls ide_setup_pci_device for them. @@ -962,27 +964,32 @@ devid.vid = dev->vendor; devid.did = dev->device; - for (d = ide_pci_chipsets; d->devid.vid && !IDE_PCI_DEVID_EQ(d->devid, devid); ++d); + for (d = ide_pci_chipsets; + d->devid.vid && !IDE_PCI_DEVID_EQ(d->devid, devid); ++d); + if (d->init_hwif == IDE_IGNORE) - printk("%s: ignored by ide_scan_pci_device() (uses own driver)\n", d->name); - else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_OPTI621V) && !(PCI_FUNC(dev->devfn) & 1)) + printk("%s: ignored by ide_scan_pci_device() " + "(uses own driver)\n", d->name); + else if (d->fixup_device) + d->fixup_device(dev, d); +#if 0 + else if (((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) && + (!(PCI_FUNC(dev->devfn) & 1))) return; - else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_CY82C693) && (!(PCI_FUNC(dev->devfn) & 1) || !((dev->class >> 8) == PCI_CLASS_STORAGE_IDE))) - return; /* CY82C693 is more than only a IDE controller */ - else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_ITE8172G) && (!(PCI_FUNC(dev->devfn) & 1) || !((dev->class >> 8) == PCI_CLASS_STORAGE_IDE))) - return; /* IT8172G is also more than only an IDE controller */ - else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886A) && !(PCI_FUNC(dev->devfn) & 1)) +#endif + else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886A) && + (!(PCI_FUNC(dev->devfn) & 1))) return; /* UM8886A/BF pair */ - else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366)) - hpt366_device_order_fixup(dev, d); - else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20270)) - pdc20270_device_order_fixup(dev, d); - else if (!IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL) || (dev->class >> 8) == PCI_CLASS_STORAGE_IDE) { + else if (!IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL) || + (dev->class >> 8) == PCI_CLASS_STORAGE_IDE) { if (IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL)) - printk("%s: unknown IDE controller on PCI bus %02x device %02x, VID=%04x, DID=%04x\n", - d->name, dev->bus->number, dev->devfn, devid.vid, devid.did); + printk("%s: unknown IDE controller on PCI bus " + "%02x device %02x, VID=%04x, DID=%04x\n", + d->name, dev->bus->number, dev->devfn, + devid.vid, devid.did); else - printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn); + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d->name, dev->bus->number, dev->devfn); ide_setup_pci_device(dev, d); } } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/ide-pmac.c linux.19rc3-ac4/drivers/ide/ide-pmac.c --- linux.19rc3/drivers/ide/ide-pmac.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/ide-pmac.c 2002-07-29 13:58:40.000000000 +0100 @@ -44,7 +44,6 @@ #endif #include "ide_modes.h" -extern char *ide_dmafunc_verbose(ide_dma_action_t dmafunc); extern void ide_do_request(ide_hwgroup_t *hwgroup, int masked_irq); #define IDE_PMAC_DEBUG @@ -362,41 +361,6 @@ } -/* Note: We don't use the generic routine here because for some - * yet unexplained reasons, it cause some media-bay CD-ROMs to - * lockup the bus. Strangely, this new version of the code is - * almost identical to the generic one and works, I've not yet - * managed to figure out what bit is causing the lockup in the - * generic code, possibly a timing issue... - * - * --BenH - */ -static int __pmac -wait_for_ready(ide_drive_t *drive) -{ - /* Timeout bumped for some powerbooks */ - int timeout = 2000; - byte stat; - - while(--timeout) { - stat = GET_STAT(); - if(!(stat & BUSY_STAT)) { - if (drive->ready_stat == 0) - break; - else if((stat & drive->ready_stat) || (stat & ERR_STAT)) - break; - } - mdelay(1); - } - if((stat & ERR_STAT) || timeout <= 0) { - if (stat & ERR_STAT) { - printk(KERN_ERR "ide_pmac: wait_for_ready, error status: %x\n", stat); - } - return 1; - } - return 0; -} - static int __pmac pmac_ide_do_setfeature(ide_drive_t *drive, byte command) { @@ -410,7 +374,7 @@ SELECT_MASK(HWIF(drive), drive, 0); udelay(1); (void)GET_STAT(); /* Get rid of pending error state */ - if(wait_for_ready(drive)) { + if(wait_for_ready(drive, 2000)) { /* Timeout bumped for some powerbooks */ printk(KERN_ERR "pmac_ide_do_setfeature disk not ready before SET_FEATURE!\n"); goto out; } @@ -420,10 +384,9 @@ OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG); OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG); udelay(1); - __save_flags(flags); /* local CPU only */ - ide__sti(); /* local CPU only -- for jiffies */ - result = wait_for_ready(drive); - __restore_flags(flags); /* local CPU only */ + local_irq_set(flags); + result = wait_for_ready(drive, 2000); /* Timeout bumped for some powerbooks */ + local_irq_restore(flags); OUT_BYTE(drive->ctl, IDE_CONTROL_REG); if (result) printk(KERN_ERR "pmac_ide_do_setfeature disk not ready after SET_FEATURE !\n"); @@ -1074,8 +1037,6 @@ unsigned char *virt_addr = rq->buffer; int sector_count = rq->nr_sectors; -// if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_WRITEDMA) || -// (args->tfRegister[IDE_COMMAND_OFFSET] == WIN_WRITEDMA_EXT)) if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE) pmif->sg_dma_direction = PCI_DMA_TODEVICE; else @@ -1333,6 +1294,7 @@ static int __pmac pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive) { +// ide_task_t *args = HWGROUP(drive)->rq->special; int ix, dstat; volatile struct dbdma_regs *dma; byte unit = (drive->select.b.unit & 0x01); @@ -1375,16 +1337,23 @@ drive->waiting_for_dma = 1; if (drive->media != ide_disk) return 0; + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); - if ((HWGROUP(drive)->rq->cmd == IDE_DRIVE_TASKFILE) && - (drive->addressing == 1)) { +#if 0 + { + ide_task_t *args = HWGROUP(drive)->rq->special; + OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); + } +#else + if (HWGROUP(drive)->rq->cmd == IDE_DRIVE_TASKFILE) { ide_task_t *args = HWGROUP(drive)->rq->special; OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); - } else if (drive->addressing) { + } else if (drive->addressing == 1) OUT_BYTE(reading ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG); - } else { + else OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); - } +#endif case ide_dma_begin: out_le32(&dma->control, (RUN << 16) | RUN); /* Make sure it gets to the controller right now */ @@ -1469,19 +1438,19 @@ switch (drive->media) { case ide_disk: /* Spin down the drive */ - outb(drive->select.all, base+0x60); - (void)inb(base+0x60); + OUT_BYTE(drive->select.all, base+0x60); + (void) IN_BYTE(base+0x60); udelay(100); - outb(0x0, base+0x30); - outb(0x0, base+0x20); - outb(0x0, base+0x40); - outb(0x0, base+0x50); - outb(0xe0, base+0x70); - outb(0x2, base+0x160); + OUT_BYTE(0x0, base+0x30); + OUT_BYTE(0x0, base+0x20); + OUT_BYTE(0x0, base+0x40); + OUT_BYTE(0x0, base+0x50); + OUT_BYTE(0xe0, base+0x70); + OUT_BYTE(0x2, base+0x160); for (j = 0; j < 10; j++) { int status; mdelay(100); - status = inb(base+0x70); + status = IN_BYTE(base+0x70); if (!(status & BUSY_STAT) && (status & DRQ_STAT)) break; } @@ -1594,10 +1563,10 @@ for (j = 0; j < 200; j++) { int status; mdelay(100); - outb(drive->select.all, base + 0x60); - if (inb(base + 0x60) != drive->select.all) + OUT_BYTE(drive->select.all, base + 0x60); + if (IN_BYTE(base + 0x60) != drive->select.all) continue; - status = inb(base + 0x70); + status = IN_BYTE(base + 0x70); if (!(status & BUSY_STAT)) break; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/ide-probe.c linux.19rc3-ac4/drivers/ide/ide-probe.c --- linux.19rc3/drivers/ide/ide-probe.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/ide-probe.c 2002-07-29 13:58:40.000000000 +0100 @@ -54,6 +54,7 @@ static inline void do_identify (ide_drive_t *drive, byte cmd) { + ide_hwif_t *hwif = HWIF(drive); int bswap = 1; struct hd_driveid *id; @@ -62,13 +63,24 @@ printk(KERN_WARNING "(ide-probe::do_identify) Out of memory.\n"); goto err_kmalloc; } - - ide_input_data(drive, id, SECTOR_WORDS); /* read 512 bytes of id info */ - ide__sti(); /* local CPU only */ + /* read 512 bytes of id info */ +#if 1 + ata_input_data(drive, id, SECTOR_WORDS); +#else + { + unsigned long *ptr = (unsigned long *)id ; + unsigned long lcount = 256/2 ; + // printk("IDE_DATA_REG = %#lx",IDE_DATA_REG); + while( lcount-- ) + *ptr++ = inl(IDE_DATA_REG); + } +#endif + local_irq_enable(); ide_fix_driveid(id); if (id->word156 == 0x4d42) { - printk("%s: drive->id->word156 == 0x%04x \n", drive->name, drive->id->word156); + printk("%s: drive->id->word156 == 0x%04x \n", + drive->name, drive->id->word156); } if (!drive->forced_lun) @@ -113,7 +125,7 @@ byte type = (id->config >> 8) & 0x1f; printk("ATAPI "); #ifdef CONFIG_BLK_DEV_PDC4030 - if (HWIF(drive)->channel == 1 && HWIF(drive)->chipset == ide_pdc4030) { + if (hwif->channel == 1 && hwif->chipset == ide_pdc4030) { printk(" -- not supported on 2nd Promise port\n"); goto err_misc; } @@ -121,7 +133,9 @@ switch (type) { case ide_floppy: if (!strstr(id->model, "CD-ROM")) { - if (!strstr(id->model, "oppy") && !strstr(id->model, "poyp") && !strstr(id->model, "ZIP")) + if (!strstr(id->model, "oppy") && + !strstr(id->model, "poyp") && + !strstr(id->model, "ZIP")) printk("cdrom or floppy?, assuming "); if (drive->media != ide_cdrom) { printk ("FLOPPY"); @@ -133,7 +147,8 @@ drive->removable = 1; #ifdef CONFIG_PPC /* kludge for Apple PowerBook internal zip */ - if (!strstr(id->model, "CD-ROM") && strstr(id->model, "ZIP")) { + if (!strstr(id->model, "CD-ROM") && + strstr(id->model, "ZIP")) { printk ("FLOPPY"); type = ide_floppy; break; @@ -164,10 +179,11 @@ drive->removable = 1; /* * Prevent long system lockup probing later for non-existant - * slave drive if the hwif is actually a flash memory card of some variety: + * slave drive if the hwif is actually a flash memory card of + * some variety: */ if (drive_is_flashcard(drive)) { - ide_drive_t *mate = &HWIF(drive)->drives[1^drive->select.b.unit]; + ide_drive_t *mate = &hwif->drives[1^drive->select.b.unit]; if (!mate->ata_flash) { mate->present = 0; mate->noprobe = 1; @@ -175,7 +191,7 @@ } drive->media = ide_disk; printk("ATA DISK drive\n"); - QUIRK_LIST(HWIF(drive),drive); + QUIRK_LIST(hwif, drive); return; err_misc: @@ -197,6 +213,7 @@ */ static int actual_try_to_identify (ide_drive_t *drive, byte cmd) { +// ide_hwif_t *hwif = HWIF(drive); int rc; ide_ioreg_t hd_status; unsigned long timeout; @@ -235,7 +252,7 @@ timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2; timeout += jiffies; do { - if (0 < (signed long)(jiffies - timeout)) { + if (time_after(jiffies, timeout)) { return 1; /* drive timed-out */ } ide_delay_50ms(); /* give drive a breather */ @@ -244,12 +261,12 @@ ide_delay_50ms(); /* wait for IRQ and DRQ_STAT */ if (OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)) { unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only; some systems need this */ + local_irq_save(flags); + /* local CPU only; some systems need this */ do_identify(drive, cmd); /* drive returned ID */ rc = 0; /* drive responded with ID */ (void) GET_STAT(); /* clear drive IRQ */ - __restore_flags(flags); /* local CPU only */ + local_irq_restore(flags); } else rc = 2; /* drive refused ID */ return rc; @@ -257,11 +274,12 @@ static int try_to_identify (ide_drive_t *drive, byte cmd) { + ide_hwif_t *hwif = HWIF(drive); int retval; int autoprobe = 0; unsigned long cookie = 0; - if (IDE_CONTROL_REG && !HWIF(drive)->irq) { + if (IDE_CONTROL_REG && !hwif->irq) { autoprobe = 1; cookie = probe_irq_on(); OUT_BYTE(drive->ctl,IDE_CONTROL_REG); /* enable device irq */ @@ -275,14 +293,14 @@ (void) GET_STAT(); /* clear drive IRQ */ udelay(5); irq = probe_irq_off(cookie); - if (!HWIF(drive)->irq) { + if (!hwif->irq) { if (irq > 0) { - HWIF(drive)->irq = irq; + hwif->irq = irq; } else { /* Mmmm.. multiple IRQs.. don't know which was ours */ printk("%s: IRQ probe failed (0x%lx)\n", drive->name, cookie); #ifdef CONFIG_BLK_DEV_CMD640 #ifdef CMD640_DUMP_REGS - if (HWIF(drive)->chipset == ide_cmd640) { + if (hwif->chipset == ide_cmd640) { printk("%s: Hmmm.. probably a driver problem.\n", drive->name); CMD640_DUMP_REGS; } @@ -335,9 +353,8 @@ return 3; /* no i/f present: mmm.. this should be a 4 -ml */ } - if (OK_STAT(GET_STAT(),READY_STAT,BUSY_STAT) - || drive->present || cmd == WIN_PIDENTIFY) - { + if (OK_STAT(GET_STAT(),READY_STAT,BUSY_STAT) || + drive->present || cmd == WIN_PIDENTIFY) { if ((rc = try_to_identify(drive,cmd))) /* send cmd and wait */ rc = try_to_identify(drive,cmd); /* failed: try again */ if (rc == 1 && cmd == WIN_PIDENTIFY && drive->autotune != 2) { @@ -371,10 +388,11 @@ */ static void enable_nest (ide_drive_t *drive) { + ide_hwif_t *hwif = HWIF(drive); unsigned long timeout; - printk("%s: enabling %s -- ", HWIF(drive)->name, drive->id->model); - SELECT_DRIVE(HWIF(drive), drive); + printk("%s: enabling %s -- ", hwif->name, drive->id->model); + SELECT_DRIVE(hwif, drive); ide_delay_50ms(); OUT_BYTE(EXABYTE_ENABLE_NEST, IDE_COMMAND_REG); timeout = jiffies + WAIT_WORSTCASE; @@ -390,9 +408,9 @@ printk("failed (status = 0x%02x)\n", GET_STAT()); else printk("success\n"); - if (do_probe(drive, WIN_IDENTIFY) >= 2) { /* if !(success||timed-out) */ + + if (do_probe(drive, WIN_IDENTIFY) >= 2) /* if !(success||timed-out) */ (void) do_probe(drive, WIN_PIDENTIFY); /* look for ATAPI device */ - } } /* @@ -530,8 +548,7 @@ return; } - __save_flags(flags); /* local CPU only */ - __sti(); /* local CPU only; needed for jiffies and irq probing */ + local_irq_set(flags); /* * Second drive should only exist if first drive was found, * but a lot of cdrom drives are configured as single slaves. @@ -541,7 +558,8 @@ (void) probe_for_drive (drive); if (drive->present && !hwif->present) { hwif->present = 1; - if (hwif->chipset != ide_4drives || !hwif->mate->present) { + if (hwif->chipset != ide_4drives || + !hwif->mate->present) { hwif_register(hwif); } } @@ -557,16 +575,16 @@ do { ide_delay_50ms(); stat = IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]); - } while ((stat & BUSY_STAT) && 0 < (signed long)(timeout - jiffies)); + } while ((stat & BUSY_STAT) && time_after(timeout, jiffies)); } - __restore_flags(flags); /* local CPU only */ + local_irq_restore(flags); for (unit = 0; unit < MAX_DRIVES; ++unit) { ide_drive_t *drive = &hwif->drives[unit]; if (drive->present) { - ide_tuneproc_t *tuneproc = HWIF(drive)->tuneproc; - if (tuneproc != NULL && drive->autotune == 1) - tuneproc(drive, 255); /* auto-tune PIO mode */ + if (hwif->tuneproc != NULL && drive->autotune == 1) + /* auto-tune PIO mode */ + hwif->tuneproc(drive, 255); } } } @@ -590,7 +608,8 @@ if (m && m->hwgroup && m->hwgroup != new->hwgroup) { if (!new->hwgroup) return; - printk("%s: potential irq problem with %s and %s\n", hwif->name, new->name, m->name); + printk("%s: potential irq problem with %s and %s\n", + hwif->name, new->name, m->name); } if (!m || m->irq != hwif->irq) /* don't undo a prior perfect match */ *match = new; @@ -614,6 +633,7 @@ } } +#undef __IRQ_HELL_SPIN /* * This routine sets up the irq for an ide interface, and creates a new * hwgroup for the irq/hwif if none was previously assigned. @@ -639,8 +659,11 @@ new_hwgroup = kmalloc(sizeof(ide_hwgroup_t),GFP_KERNEL); - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ +#ifndef __IRQ_HELL_SPIN + save_and_cli(flags); +#else + spin_lock_irqsave(&io_request_lock, flags); +#endif hwif->hwgroup = NULL; #if MAX_HWIFS > 1 @@ -677,7 +700,11 @@ } else { hwgroup = new_hwgroup; if (!hwgroup) { - restore_flags(flags); /* all CPUs */ +#ifndef __IRQ_HELL_SPIN + restore_flags(flags); +#else + spin_unlock_irqrestore(&io_request_lock, flags); +#endif return 1; } memset(hwgroup, 0, sizeof(ide_hwgroup_t)); @@ -707,7 +734,11 @@ if (ide_request_irq(hwif->irq, &ide_intr, sa, hwif->name, hwgroup)) { if (!match) kfree(hwgroup); - restore_flags(flags); /* all CPUs */ +#ifndef __IRQ_HELL_SPIN + restore_flags(flags); +#else + spin_unlock_irqrestore(&io_request_lock, flags); +#endif return 1; } } @@ -735,7 +766,12 @@ printk("%s : Adding missed hwif to hwgroup!!\n", hwif->name); #endif } - restore_flags(flags); /* all CPUs; safe now that hwif->hwgroup is set up */ +#ifndef __IRQ_HELL_SPIN + restore_flags(flags); +#else + spin_unlock_irqrestore(&io_request_lock, flags); +#endif + /* all CPUs; safe now that hwif->hwgroup is set up */ #if !defined(__mc68000__) && !defined(CONFIG_APUS) && !defined(__sparc__) printk("%s at 0x%03x-0x%03x,0x%03x on irq %d", hwif->name, @@ -785,6 +821,8 @@ gd = kmalloc (sizeof(struct gendisk), GFP_KERNEL); if (!gd) goto err_kmalloc_gd; + memset(gd, 0, sizeof(struct gendisk)); + gd->sizes = kmalloc (minors * sizeof(int), GFP_KERNEL); if (!gd->sizes) goto err_kmalloc_gd_sizes; @@ -892,7 +930,8 @@ } #ifdef CONFIG_BLK_DEV_HD if (hwif->irq == HD_IRQ && hwif->io_ports[IDE_DATA_OFFSET] != HD_DATA) { - printk("%s: CANNOT SHARE IRQ WITH OLD HARDDISK DRIVER (hd.c)\n", hwif->name); + printk("%s: CANNOT SHARE IRQ WITH OLD " + "HARDDISK DRIVER (hd.c)\n", hwif->name); return (hwif->present = 0); } #endif /* CONFIG_BLK_DEV_HD */ @@ -900,7 +939,8 @@ hwif->present = 0; /* we set it back to 1 if all is ok below */ if (devfs_register_blkdev (hwif->major, hwif->name, ide_fops)) { - printk("%s: UNABLE TO GET MAJOR NUMBER %d\n", hwif->name, hwif->major); + printk("%s: UNABLE TO GET MAJOR NUMBER %d\n", + hwif->name, hwif->major); return (hwif->present = 0); } @@ -911,7 +951,8 @@ * this port and try that. */ if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) { - printk("%s: Disabled unable to get IRQ %d.\n", hwif->name, i); + printk("%s: Disabled unable to get IRQ %d.\n", + hwif->name, i); (void) unregister_blkdev (hwif->major, hwif->name); return (hwif->present = 0); } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/ide-proc.c linux.19rc3-ac4/drivers/ide/ide-proc.c --- linux.19rc3/drivers/ide/ide-proc.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/ide-proc.c 2002-07-29 13:58:40.000000000 +0100 @@ -160,6 +160,8 @@ static struct proc_dir_entry * proc_ide_root = NULL; +#undef __PROC_HELL + static int proc_ide_write_config (struct file *file, const char *buffer, unsigned long count, void *data) { @@ -181,7 +183,11 @@ * Do one full pass to verify all parameters, * then do another to actually write the regs. */ +#ifndef __PROC_HELL save_flags(flags); /* all CPUs */ +#else + spin_lock_irqsave(&io_request_lock, flags); +#endif do { const char *p; if (for_real) { @@ -190,15 +196,32 @@ ide_hwgroup_t *mategroup = NULL; if (hwif->mate && hwif->mate->hwgroup) mategroup = (ide_hwgroup_t *)(hwif->mate->hwgroup); +#ifndef __PROC_HELL cli(); /* all CPUs; ensure all writes are done together */ - while (mygroup->busy || (mategroup && mategroup->busy)) { +#else + spin_lock_irqsave(&io_request_lock, flags); +#endif + while (mygroup->busy || + (mategroup && mategroup->busy)) { +#ifndef __PROC_HELL sti(); /* all CPUs */ - if (0 < (signed long)(jiffies - timeout)) { +#else + spin_unlock_irqrestore(&io_request_lock, flags); +#endif + if (time_after(jiffies, timeout)) { printk("/proc/ide/%s/config: channel(s) busy, cannot write\n", hwif->name); +#ifndef __PROC_HELL restore_flags(flags); /* all CPUs */ +#else + spin_unlock_irqrestore(&io_request_lock, flags); +#endif return -EBUSY; } +#ifndef __PROC_HELL cli(); /* all CPUs */ +#else + spin_lock_irqsave(&io_request_lock, flags); +#endif } } p = buffer; @@ -281,7 +304,11 @@ break; } if (rc) { +#ifndef __PROC_HELL restore_flags(flags); /* all CPUs */ +#else + spin_unlock_irqrestore(&io_request_lock, flags); +#endif printk("proc_ide_write_config: error writing %s at bus %02x dev %02x reg 0x%x value 0x%x\n", msg, dev->bus->number, dev->devfn, reg, val); printk("proc_ide_write_config: error %d\n", rc); @@ -311,9 +338,9 @@ * */ switch (digits) { - case 2: outb(val, reg); + case 2: OUT_BYTE(val, reg); break; - case 4: outw(val, reg); + case 4: OUT_WORD(val, reg); break; case 8: outl(val, reg); break; @@ -323,10 +350,18 @@ } } } while (!for_real++); +#ifndef __PROC_HELL restore_flags(flags); /* all CPUs */ +#else + spin_unlock_irqrestore(&io_request_lock, flags); +#endif return count; parse_error: +#ifndef __PROC_HELL restore_flags(flags); /* all CPUs */ +#else + spin_unlock_irqrestore(&io_request_lock, flags); +#endif printk("parse error\n"); return xx_xx_parse_error(start, startn, msg); } @@ -446,26 +481,13 @@ PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } -static int proc_ide_get_identify(ide_drive_t *drive, byte *buf) -{ - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - - taskfile.sector_count = 0x01; - taskfile.command = (drive->media == ide_disk) ? WIN_IDENTIFY : WIN_PIDENTIFY ; - - return ide_wait_taskfile(drive, &taskfile, &hobfile, buf); -} - static int proc_ide_read_identify (char *page, char **start, off_t off, int count, int *eof, void *data) { ide_drive_t *drive = (ide_drive_t *)data; int len = 0, i = 0; - if (drive && !proc_ide_get_identify(drive, page)) { + if (drive && !taskfile_lib_get_identify(drive, page)) { unsigned short *val = (unsigned short *) page; char *out = ((char *)val) + (SECTOR_WORDS * 4); page = out; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/ide-tape.c linux.19rc3-ac4/drivers/ide/ide-tape.c --- linux.19rc3/drivers/ide/ide-tape.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/ide-tape.c 2002-07-29 13:58:40.000000000 +0100 @@ -1835,10 +1835,9 @@ * idetape_end_request is used to finish servicing a request, and to * insert a pending pipeline request into the main device queue. */ -static void idetape_end_request (byte uptodate, ide_hwgroup_t *hwgroup) +static int idetape_end_request (ide_drive_t *drive, int uptodate) { - ide_drive_t *drive = hwgroup->drive; - struct request *rq = hwgroup->rq; + struct request *rq = HWGROUP(drive)->rq; idetape_tape_t *tape = drive->driver_data; unsigned long flags; int error; @@ -1932,6 +1931,7 @@ if (tape->active_data_request == NULL) clear_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags); spin_unlock_irqrestore(&tape->spinlock, flags); + return 0; } static ide_startstop_t idetape_request_sense_callback (ide_drive_t *drive) @@ -1944,10 +1944,10 @@ #endif /* IDETAPE_DEBUG_LOG */ if (!tape->pc->error) { idetape_analyze_error (drive, (idetape_request_sense_result_t *) tape->pc->buffer); - idetape_end_request (1, HWGROUP (drive)); + idetape_end_request(drive, 1); } else { printk (KERN_ERR "ide-tape: Error in REQUEST SENSE itself - Aborting request!\n"); - idetape_end_request (0, HWGROUP (drive)); + idetape_end_request(drive, 0); } return ide_stopped; } @@ -2050,10 +2050,11 @@ #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_pc_intr interrupt handler\n"); + printk(KERN_INFO "ide-tape: Reached idetape_pc_intr " + "interrupt handler\n"); #endif /* IDETAPE_DEBUG_LOG */ - status.all = GET_STAT(); /* Clear the interrupt */ + status.all = GET_STAT(); /* Clear the interrupt */ #ifdef CONFIG_BLK_DEV_IDEDMA if (test_bit (PC_DMA_IN_PROGRESS, &pc->flags)) { @@ -2090,11 +2091,14 @@ #endif /* IDETAPE_DEBUG_LOG */ clear_bit (PC_DMA_IN_PROGRESS, &pc->flags); - ide__sti(); /* local CPU only */ + local_irq_enable(); #if SIMULATE_ERRORS - if ((pc->c[0] == IDETAPE_WRITE_CMD || pc->c[0] == IDETAPE_READ_CMD) && (++error_sim_count % 100) == 0) { - printk(KERN_INFO "ide-tape: %s: simulating error\n", tape->name); + if ((pc->c[0] == IDETAPE_WRITE_CMD || + pc->c[0] == IDETAPE_READ_CMD) && + (++error_sim_count % 100) == 0) { + printk(KERN_INFO "ide-tape: %s: simulating error\n", + tape->name); status.b.check = 1; } #endif @@ -2103,10 +2107,10 @@ if (status.b.check || test_bit (PC_DMA_ERROR, &pc->flags)) { /* Error detected */ #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 1) - printk (KERN_INFO "ide-tape: %s: I/O error, ",tape->name); + printk(KERN_INFO "ide-tape: %s: I/O error, ",tape->name); #endif /* IDETAPE_DEBUG_LOG */ if (pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) { - printk (KERN_ERR "ide-tape: I/O error in request sense command\n"); + printk(KERN_ERR "ide-tape: I/O error in request sense command\n"); return ide_do_reset (drive); } #if IDETAPE_DEBUG_LOG @@ -2116,31 +2120,34 @@ return idetape_retry_pc (drive); /* Retry operation */ } pc->error = 0; - if (!tape->onstream && test_bit (PC_WAIT_FOR_DSC, &pc->flags) && !status.b.dsc) { /* Media access command */ + if (!tape->onstream && + test_bit (PC_WAIT_FOR_DSC, &pc->flags) && !status.b.dsc) { + /* Media access command */ tape->dsc_polling_start = jiffies; tape->dsc_polling_frequency = IDETAPE_DSC_MA_FAST; tape->dsc_timeout = jiffies + IDETAPE_DSC_MA_TIMEOUT; - idetape_postpone_request (drive); /* Allow ide.c to handle other requests */ + idetape_postpone_request(drive); /* Allow ide.c to handle other requests */ return ide_stopped; } if (tape->failed_pc == pc) tape->failed_pc = NULL; - return pc->callback(drive); /* Command finished - Call the callback function */ + return pc->callback(drive); /* Command finished - Call the callback function */ } #ifdef CONFIG_BLK_DEV_IDEDMA if (test_and_clear_bit (PC_DMA_IN_PROGRESS, &pc->flags)) { - printk (KERN_ERR "ide-tape: The tape wants to issue more interrupts in DMA mode\n"); - printk (KERN_ERR "ide-tape: DMA disabled, reverting to PIO\n"); + printk(KERN_ERR "ide-tape: The tape wants to issue more " + "interrupts in DMA mode\n"); + printk(KERN_ERR "ide-tape: DMA disabled, reverting to PIO\n"); (void) HWIF(drive)->dmaproc(ide_dma_off, drive); return ide_do_reset (drive); } #endif /* CONFIG_BLK_DEV_IDEDMA */ - bcount.b.high = IN_BYTE (IDE_BCOUNTH_REG); /* Get the number of bytes to transfer */ - bcount.b.low = IN_BYTE (IDE_BCOUNTL_REG); /* on this interrupt */ - ireason.all = IN_BYTE (IDE_IREASON_REG); + bcount.b.high = IN_BYTE(IDE_BCOUNTH_REG); /* Get the number of bytes to transfer */ + bcount.b.low = IN_BYTE(IDE_BCOUNTL_REG); /* on this interrupt */ + ireason.all = IN_BYTE(IDE_IREASON_REG); if (ireason.b.cod) { - printk (KERN_ERR "ide-tape: CoD != 0 in idetape_pc_intr\n"); + printk(KERN_ERR "ide-tape: CoD != 0 in idetape_pc_intr\n"); return ide_do_reset (drive); } if (ireason.b.io == test_bit (PC_WRITING, &pc->flags)) { /* Hopefully, we will never get here */ @@ -2154,6 +2161,8 @@ if (temp > pc->buffer_size) { printk (KERN_ERR "ide-tape: The tape wants to send us more data than expected - discarding data\n"); idetape_discard_data (drive, bcount.all); + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler (drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); return ide_started; } @@ -2180,6 +2189,8 @@ if (tape->debug_level >= 2) printk(KERN_INFO "ide-tape: [cmd %x] transferred %d bytes on that interrupt\n", pc->c[0], bcount.all); #endif + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler (drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); /* And set the interrupt handler again */ return ide_started; } @@ -2234,28 +2245,33 @@ int retries = 100; ide_startstop_t startstop; - if (ide_wait_stat (&startstop,drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) { - printk (KERN_ERR "ide-tape: Strange, packet command initiated yet DRQ isn't asserted\n"); + if (ide_wait_stat(&startstop,drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) { + printk(KERN_ERR "ide-tape: Strange, packet command initiated yet DRQ isn't asserted\n"); return startstop; } - ireason.all = IN_BYTE (IDE_IREASON_REG); + ireason.all = IN_BYTE(IDE_IREASON_REG); while (retries-- && (!ireason.b.cod || ireason.b.io)) { - printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while issuing a packet command, retrying\n"); + printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while issuing " + "a packet command, retrying\n"); udelay(100); ireason.all = IN_BYTE(IDE_IREASON_REG); if (retries == 0) { - printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while issuing a packet command, ignoring\n"); + printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while " + "issuing a packet command, ignoring\n"); ireason.b.cod = 1; ireason.b.io = 0; } } if (!ireason.b.cod || ireason.b.io) { - printk (KERN_ERR "ide-tape: (IO,CoD) != (0,1) while issuing a packet command\n"); + printk(KERN_ERR "ide-tape: (IO,CoD) != (0,1) while issuing " + "a packet command\n"); return ide_do_reset (drive); } tape->cmd_start_time = jiffies; + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); /* Set the interrupt routine */ - atapi_output_bytes (drive,pc->c,12); /* Send the actual packet */ + atapi_output_bytes(drive,pc->c,12); /* Send the actual packet */ return ide_started; } @@ -2266,16 +2282,19 @@ int dma_ok = 0; #if IDETAPE_DEBUG_BUGS - if (tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD && pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) { - printk (KERN_ERR "ide-tape: possible ide-tape.c bug - Two request sense in serial were issued\n"); + if (tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD && + pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) { + printk(KERN_ERR "ide-tape: possible ide-tape.c bug - " + "Two request sense in serial were issued\n"); } #endif /* IDETAPE_DEBUG_BUGS */ if (tape->failed_pc == NULL && pc->c[0] != IDETAPE_REQUEST_SENSE_CMD) tape->failed_pc = pc; - tape->pc = pc; /* Set the current packet command */ + tape->pc = pc; /* Set the current packet command */ - if (pc->retries > IDETAPE_MAX_PC_RETRIES || test_bit (PC_ABORT, &pc->flags)) { + if (pc->retries > IDETAPE_MAX_PC_RETRIES || + test_bit(PC_ABORT, &pc->flags)) { /* * We will "abort" retrying a packet command in case * a legitimate error code was received (crossing a @@ -2283,14 +2302,19 @@ * example). */ if (!test_bit (PC_ABORT, &pc->flags)) { - if (!(pc->c[0] == IDETAPE_TEST_UNIT_READY_CMD && tape->sense_key == 2 && - tape->asc == 4 && (tape->ascq == 1 || tape->ascq == 8))) { - printk (KERN_ERR "ide-tape: %s: I/O error, pc = %2x, key = %2x, asc = %2x, ascq = %2x\n", - tape->name, pc->c[0], tape->sense_key, tape->asc, tape->ascq); + if (!(pc->c[0] == IDETAPE_TEST_UNIT_READY_CMD && + tape->sense_key == 2 && tape->asc == 4 && + (tape->ascq == 1 || tape->ascq == 8))) { + printk(KERN_ERR "ide-tape: %s: I/O error, " + "pc = %2x, key = %2x, " + "asc = %2x, ascq = %2x\n", + tape->name, pc->c[0], + tape->sense_key, tape->asc, + tape->ascq); if (tape->onstream && pc->c[0] == IDETAPE_READ_CMD && tape->sense_key == 3 && tape->asc == 0x11) /* AJN-1: 11 should be 0x11 */ printk(KERN_ERR "ide-tape: %s: enabling read error recovery\n", tape->name); } - pc->error = IDETAPE_ERROR_GENERAL; /* Giving up */ + pc->error = IDETAPE_ERROR_GENERAL; /* Giving up */ } tape->failed_pc = NULL; return pc->callback(drive); @@ -2301,13 +2325,14 @@ #endif /* IDETAPE_DEBUG_LOG */ pc->retries++; - pc->actually_transferred = 0; /* We haven't transferred any data yet */ + pc->actually_transferred = 0; /* We haven't transferred any data yet */ pc->current_position=pc->buffer; - bcount.all=pc->request_transfer; /* Request to transfer the entire buffer at once */ + bcount.all=pc->request_transfer; /* Request to transfer the entire buffer at once */ #ifdef CONFIG_BLK_DEV_IDEDMA - if (test_and_clear_bit (PC_DMA_ERROR, &pc->flags)) { - printk (KERN_WARNING "ide-tape: DMA disabled, reverting to PIO\n"); + if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags)) { + printk(KERN_WARNING "ide-tape: DMA disabled, " + "reverting to PIO\n"); (void) HWIF(drive)->dmaproc(ide_dma_off, drive); } if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) @@ -2315,18 +2340,20 @@ #endif /* CONFIG_BLK_DEV_IDEDMA */ if (IDE_CONTROL_REG) - OUT_BYTE (drive->ctl, IDE_CONTROL_REG); - OUT_BYTE (dma_ok ? 1 : 0, IDE_FEATURE_REG); /* Use PIO/DMA */ - OUT_BYTE (bcount.b.high, IDE_BCOUNTH_REG); - OUT_BYTE (bcount.b.low, IDE_BCOUNTL_REG); - OUT_BYTE (drive->select.all, IDE_SELECT_REG); + OUT_BYTE(drive->ctl, IDE_CONTROL_REG); + OUT_BYTE(dma_ok ? 1 : 0, IDE_FEATURE_REG); /* Use PIO/DMA */ + OUT_BYTE(bcount.b.high, IDE_BCOUNTH_REG); + OUT_BYTE(bcount.b.low, IDE_BCOUNTL_REG); + OUT_BYTE(drive->select.all, IDE_SELECT_REG); #ifdef CONFIG_BLK_DEV_IDEDMA - if (dma_ok) { /* Begin DMA, if necessary */ + if (dma_ok) { /* Begin DMA, if necessary */ set_bit (PC_DMA_IN_PROGRESS, &pc->flags); (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive)); } #endif /* CONFIG_BLK_DEV_IDEDMA */ if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) { + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler(drive, &idetape_transfer_pc, IDETAPE_WAIT_CMD, NULL); OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); return ide_started; @@ -2348,7 +2375,7 @@ printk (KERN_INFO "ide-tape: Reached idetape_pc_callback\n"); #endif /* IDETAPE_DEBUG_LOG */ - idetape_end_request (tape->pc->error ? 0 : 1, HWGROUP(drive)); + idetape_end_request(drive, tape->pc->error ? 0 : 1); return ide_stopped; } @@ -2360,10 +2387,10 @@ idetape_init_pc (pc); pc->c[0] = IDETAPE_MODE_SENSE_CMD; if (page_code != IDETAPE_BLOCK_DESCRIPTOR) - pc->c[1] = 8; /* DBD = 1 - Don't return block descriptors */ + pc->c[1] = 8; /* DBD = 1 - Don't return block descriptors */ pc->c[2] = page_code; - pc->c[3] = 255; /* Don't limit the returned information */ - pc->c[4] = 255; /* (We will just discard data in that case) */ + pc->c[3] = 255; /* Don't limit the returned information */ + pc->c[4] = 255; /* (We will just discard data in that case) */ if (page_code == IDETAPE_BLOCK_DESCRIPTOR) pc->request_transfer = 12; else if (page_code == IDETAPE_CAPABILITIES_PAGE) @@ -2391,13 +2418,15 @@ } tape->tape_still_time = (jiffies - tape->tape_still_time_begin) * 1000 / HZ; #if USE_IOTRACE - IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor); + IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, + tape->tape_head, tape->minor); #endif #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 1) - printk(KERN_INFO "ide-tape: buffer fill callback, %d/%d\n", tape->cur_frames, tape->max_frames); + printk(KERN_INFO "ide-tape: buffer fill callback, %d/%d\n", + tape->cur_frames, tape->max_frames); #endif - idetape_end_request (tape->pc->error ? 0 : 1, HWGROUP(drive)); + idetape_end_request(drive, tape->pc->error ? 0 : 1); return ide_stopped; } @@ -2471,9 +2500,9 @@ printk(KERN_INFO "ide-tape: bug: onstream, media_access_finished\n"); status.all = GET_STAT(); if (status.b.dsc) { - if (status.b.check) { /* Error detected */ + if (status.b.check) { /* Error detected */ printk (KERN_ERR "ide-tape: %s: I/O error, ",tape->name); - return idetape_retry_pc (drive); /* Retry operation */ + return idetape_retry_pc (drive); /* Retry operation */ } pc->error = 0; if (tape->failed_pc == pc) @@ -2517,9 +2546,9 @@ rq->current_nr_sectors -= blocks; if (!tape->pc->error) - idetape_end_request (1, HWGROUP (drive)); + idetape_end_request(drive, 1); else - idetape_end_request (tape->pc->error, HWGROUP (drive)); + idetape_end_request(drive, tape->pc->error); return ide_stopped; } @@ -2607,6 +2636,38 @@ } /* + * This is our end_request replacement function. + */ +static int idetape_do_end_request (ide_drive_t *drive, int uptodate) +{ + struct request *rq; + unsigned long flags; + int ret = 1; + + spin_lock_irqsave(&io_request_lock, flags); + rq = HWGROUP(drive)->rq; + + /* + * decide whether to reenable DMA -- 3 is a random magic for now, + * if we DMA timeout more than 3 times, just stay in PIO + */ + if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) { + drive->state = 0; + HWGROUP(drive)->hwif->dmaproc(ide_dma_on, drive); + } + + if (!end_that_request_first(rq, uptodate, drive->name)) { + add_blkdev_randomness(MAJOR(rq->rq_dev)); + blkdev_dequeue_request(rq); + HWGROUP(drive)->rq = NULL; + end_that_request_last(rq); + ret = 0; + } + spin_unlock_irqrestore(&io_request_lock, flags); + return ret; +} + +/* * idetape_do_request is our request handling function. */ static ide_startstop_t idetape_do_request (ide_drive_t *drive, struct request *rq, unsigned long block) @@ -2618,31 +2679,38 @@ #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 5) - printk (KERN_INFO "ide-tape: rq_status: %d, rq_dev: %u, cmd: %d, errors: %d\n",rq->rq_status,(unsigned int) rq->rq_dev,rq->cmd,rq->errors); + printk (KERN_INFO "ide-tape: rq_status: %d, " + "rq_dev: %u, cmd: %d, errors: %d\n", rq->rq_status, + (unsigned int) rq->rq_dev, rq->cmd, rq->errors); if (tape->debug_level >= 2) - printk (KERN_INFO "ide-tape: sector: %ld, nr_sectors: %ld, current_nr_sectors: %ld\n",rq->sector,rq->nr_sectors,rq->current_nr_sectors); + printk (KERN_INFO "ide-tape: sector: %ld, " + "nr_sectors: %ld, current_nr_sectors: %ld\n", + rq->sector, rq->nr_sectors, rq->current_nr_sectors); #endif /* IDETAPE_DEBUG_LOG */ if (!IDETAPE_RQ_CMD (rq->cmd)) { /* * We do not support buffer cache originated requests. */ - printk (KERN_NOTICE "ide-tape: %s: Unsupported command in request queue (%d)\n", drive->name, rq->cmd); - ide_end_request (0, HWGROUP (drive)); /* Let the common code handle it */ + printk (KERN_NOTICE "ide-tape: %s: Unsupported command in " + "request queue (%d)\n", drive->name, rq->cmd); + idetape_do_end_request(drive, 0); return ide_stopped; } /* * Retry a failed packet command */ - if (tape->failed_pc != NULL && tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) { + if (tape->failed_pc != NULL && + tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) { return idetape_issue_packet_command (drive, tape->failed_pc); } #if IDETAPE_DEBUG_BUGS if (postponed_rq != NULL) if (rq != postponed_rq) { - printk (KERN_ERR "ide-tape: ide-tape.c bug - Two DSC requests were queued\n"); - idetape_end_request (0, HWGROUP (drive)); + printk (KERN_ERR "ide-tape: ide-tape.c bug - " + "Two DSC requests were queued\n"); + idetape_end_request(drive, 0); return ide_stopped; } #endif /* IDETAPE_DEBUG_BUGS */ @@ -2674,7 +2742,8 @@ */ if (tape->tape_still_time > 100 && tape->tape_still_time < 200) tape->measure_insert_time = 1; - if (tape->req_buffer_fill && (rq->cmd == IDETAPE_WRITE_RQ || rq->cmd == IDETAPE_READ_RQ)) { + if (tape->req_buffer_fill && + (rq->cmd == IDETAPE_WRITE_RQ || rq->cmd == IDETAPE_READ_RQ)) { tape->req_buffer_fill = 0; tape->writes_since_buffer_fill = 0; tape->reads_since_buffer_fill = 0; @@ -2699,7 +2768,8 @@ tape->insert_speed > tape->max_insert_speed ) ) && rq->nr_sectors) ) ) { #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 4) - printk(KERN_INFO "ide-tape: postponing request, cmd %d, cur %d, max %d\n", + printk(KERN_INFO "ide-tape: postponing request, " + "cmd %d, cur %d, max %d\n", rq->cmd, tape->cur_frames, tape->max_frames); #endif if (tape->postpone_cnt++ < 500) { @@ -2708,7 +2778,8 @@ } #if ONSTREAM_DEBUG else if (tape->debug_level >= 4) - printk(KERN_INFO "ide-tape: %s: postpone_cnt %d\n", tape->name, tape->postpone_cnt); + printk(KERN_INFO "ide-tape: %s: postpone_cnt %d\n", + tape->name, tape->postpone_cnt); #endif } if (!test_and_clear_bit (IDETAPE_IGNORE_DSC, &tape->flags) && !status.b.dsc) { @@ -2770,7 +2841,7 @@ break; case IDETAPE_ABORTED_WRITE_RQ: rq->cmd = IDETAPE_WRITE_RQ; - idetape_end_request (IDETAPE_ERROR_EOD, HWGROUP(drive)); + idetape_end_request(drive, IDETAPE_ERROR_EOD); return ide_stopped; case IDETAPE_ABORTED_READ_RQ: #if IDETAPE_DEBUG_LOG @@ -2778,7 +2849,7 @@ printk(KERN_INFO "ide-tape: %s: detected aborted read rq\n", tape->name); #endif rq->cmd = IDETAPE_READ_RQ; - idetape_end_request (IDETAPE_ERROR_EOD, HWGROUP(drive)); + idetape_end_request(drive, IDETAPE_ERROR_EOD); return ide_stopped; case IDETAPE_PC_RQ1: pc = (idetape_pc_t *) rq->buffer; @@ -2789,7 +2860,7 @@ return ide_stopped; default: printk (KERN_ERR "ide-tape: bug in IDETAPE_RQ_CMD macro\n"); - idetape_end_request (0, HWGROUP (drive)); + idetape_end_request(drive, 0); return ide_stopped; } return idetape_issue_packet_command (drive, pc); @@ -3112,7 +3183,7 @@ if (result->bpu) { printk (KERN_INFO "ide-tape: Block location is unknown to the tape\n"); clear_bit (IDETAPE_ADDRESS_VALID, &tape->flags); - idetape_end_request (0, HWGROUP (drive)); + idetape_end_request(drive, 0); } else { #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 2) @@ -3123,10 +3194,10 @@ tape->last_frame_position = ntohl (result->last_block); tape->blocks_in_buffer = result->blocks_in_buffer[2]; set_bit (IDETAPE_ADDRESS_VALID, &tape->flags); - idetape_end_request (1, HWGROUP (drive)); + idetape_end_request(drive, 1); } } else { - idetape_end_request (0, HWGROUP (drive)); + idetape_end_request(drive, 0); } return ide_stopped; } @@ -6085,14 +6156,14 @@ int minor = tape->minor; unsigned long flags; - save_flags (flags); /* all CPUs (overkill?) */ - cli(); /* all CPUs (overkill?) */ - if (test_bit (IDETAPE_BUSY, &tape->flags) || tape->first_stage != NULL || tape->merge_stage_size || drive->usage) { - restore_flags(flags); /* all CPUs (overkill?) */ + spin_lock_irqsave(&io_request_lock, flags); + if (test_bit (IDETAPE_BUSY, &tape->flags) || drive->usage || + tape->first_stage != NULL || tape->merge_stage_size) { + spin_unlock_irqrestore(&io_request_lock, flags); return 1; } idetape_chrdevs[minor].drive = NULL; - restore_flags (flags); /* all CPUs (overkill?) */ + spin_unlock_irqrestore(&io_request_lock, flags); DRIVER(drive)->busy = 0; (void) ide_unregister_subdriver (drive); drive->driver_data = NULL; @@ -6132,6 +6203,7 @@ #endif +int idetape_init (void); int idetape_reinit(ide_drive_t *drive); /* @@ -6142,13 +6214,21 @@ version: IDETAPE_VERSION, media: ide_tape, busy: 1, +#ifdef CONFIG_IDEDMA_ONLYDISK + supports_dma: 0, +#else supports_dma: 1, +#endif supports_dsc_overlap: 1, cleanup: idetape_cleanup, standby: NULL, + suspend: NULL, + resume: NULL, flushcache: NULL, do_request: idetape_do_request, end_request: idetape_end_request, + sense: NULL, + error: NULL, ioctl: idetape_blkdev_ioctl, open: idetape_blkdev_open, release: idetape_blkdev_release, @@ -6156,13 +6236,14 @@ revalidate: NULL, pre_reset: idetape_pre_reset, capacity: NULL, + special: NULL, proc: idetape_proc, + init: idetape_init, reinit: idetape_reinit, ata_prebuilder: NULL, atapi_prebuilder: NULL, }; -int idetape_init (void); static ide_module_t idetape_module = { IDE_DRIVER_MODULE, idetape_init, diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/ide-taskfile.c linux.19rc3-ac4/drivers/ide/ide-taskfile.c --- linux.19rc3/drivers/ide/ide-taskfile.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/ide-taskfile.c 2002-07-29 13:58:40.000000000 +0100 @@ -1,12 +1,29 @@ /* - * linux/drivers/ide/ide-taskfile.c Version 0.20 Oct 11, 2000 + * linux/drivers/ide/ide-taskfile.c Version 0.33 April 11, 2002 * - * Copyright (C) 2000 Michael Cornwell - * Copyright (C) 2000 Andre Hedrick + * Copyright (C) 2000-2002 Michael Cornwell + * Copyright (C) 2000-2002 Andre Hedrick + * Copyright (C) 2001-2002 Klaus Smolin + * IBM Storage Technology Division * - * May be copied or modified under the terms of the GNU General Public License + * The big the bad and the ugly. * - * IDE_DEBUG(__LINE__); + * Problems to be fixed because of BH interface or the lack therefore. + * + * Fill me in stupid !!! + * + * HOST: + * General refers to the Controller and Driver "pair". + * DATA HANDLER: + * Under the context of Linux it generally refers to an interrupt handler. + * However, it correctly describes the 'HOST' + * DATA BLOCK: + * The amount of data needed to be transfered as predefined in the + * setup of the device. + * STORAGE ATOMIC: + * The 'DATA BLOCK' associated to the 'DATA HANDLER', and can be as + * small as a single sector or as large as the entire command block + * request. */ #include @@ -34,20 +51,41 @@ #include #include -#ifdef CONFIG_IDE_TASKFILE_IO -# define __TASKFILE__IO -#else /* CONFIG_IDE_TASKFILE_IO */ -# undef __TASKFILE__IO -#endif /* CONFIG_IDE_TASKFILE_IO */ - #define DEBUG_TASKFILE 0 /* unset when fixed */ #if DEBUG_TASKFILE -#define DTF(x...) printk(##x) +#define DTF(x...) printk(x) #else #define DTF(x...) #endif +/* + * + */ +#define task_rq_offset(rq) \ + (((rq)->nr_sectors - (rq)->current_nr_sectors) * SECTOR_SIZE) + +/* + * for now, taskfile requests are special :/ + * + * However, upon the creation of the atapi version of packet_command + * data-phase ISR plus it own diagnostics and extensions for direct access + * (ioctl,read,write,rip,stream -- atapi), the kmap/kunmap for PIO will + * come localized. + */ +inline char *task_map_rq (struct request *rq, unsigned long *flags) +{ + if (rq->bh) + return ide_map_buffer(rq, flags); + return rq->buffer + task_rq_offset(rq); +} + +inline void task_unmap_rq (struct request *rq, char *buf, unsigned long *flags) +{ + if (rq->bh) + ide_unmap_buffer(buf, flags); +} + inline u32 task_read_24 (ide_drive_t *drive) { return (IN_BYTE(IDE_HCYL_REG)<<16) | @@ -73,10 +111,11 @@ * of the sector count register location, with interrupts disabled * to ensure that the reads all happen together. */ -static inline void task_vlb_sync (ide_ioreg_t port) { - (void) inb (port); - (void) inb (port); - (void) inb (port); +static inline void task_vlb_sync (ide_ioreg_t port) +{ + (void) IN_BYTE (port); + (void) IN_BYTE (port); + (void) IN_BYTE (port); } #endif /* SUPPORT_VLB_SYNC */ @@ -85,17 +124,28 @@ */ void ata_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount) { - byte io_32bit = drive->io_32bit; + byte io_32bit; + + /* + * first check if this controller has defined a special function + * for handling polled ide transfers + */ + + if (HWIF(drive)->ideproc) { + HWIF(drive)->ideproc(ideproc_ide_input_data, drive, buffer, wcount); + return; + } + + io_32bit = drive->io_32bit; if (io_32bit) { #if SUPPORT_VLB_SYNC if (io_32bit & 2) { unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ + local_irq_save(flags); task_vlb_sync(IDE_NSECTOR_REG); insl(IDE_DATA_REG, buffer, wcount); - __restore_flags(flags); /* local CPU only */ + local_irq_restore(flags); } else #endif /* SUPPORT_VLB_SYNC */ insl(IDE_DATA_REG, buffer, wcount); @@ -118,17 +168,23 @@ */ void ata_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount) { - byte io_32bit = drive->io_32bit; + byte io_32bit; + + if (HWIF(drive)->ideproc) { + HWIF(drive)->ideproc(ideproc_ide_output_data, drive, buffer, wcount); + return; + } + + io_32bit = drive->io_32bit; if (io_32bit) { #if SUPPORT_VLB_SYNC if (io_32bit & 2) { unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ + local_irq_save(flags); task_vlb_sync(IDE_NSECTOR_REG); outsl(IDE_DATA_REG, buffer, wcount); - __restore_flags(flags); /* local CPU only */ + local_irq_restore(flags); } else #endif /* SUPPORT_VLB_SYNC */ outsl(IDE_DATA_REG, buffer, wcount); @@ -146,15 +202,61 @@ } } +/* + * The following routines are mainly used by the ATAPI drivers. + * + * These routines will round up any request for an odd number of bytes, + * so if an odd bytecount is specified, be sure that there's at least one + * extra byte allocated for the buffer. + */ +void atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount) +{ + if (HWIF(drive)->ideproc) { + HWIF(drive)->ideproc(ideproc_atapi_input_bytes, drive, buffer, bytecount); + return; + } + + ++bytecount; +#if defined(CONFIG_ATARI) || defined(CONFIG_Q40) + if (MACH_IS_ATARI || MACH_IS_Q40) { + /* Atari has a byte-swapped IDE interface */ + insw_swapw(IDE_DATA_REG, buffer, bytecount / 2); + return; + } +#endif /* CONFIG_ATARI */ + ata_input_data (drive, buffer, bytecount / 4); + if ((bytecount & 0x03) >= 2) + insw (IDE_DATA_REG, ((byte *)buffer) + (bytecount & ~0x03), 1); +} + +void atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount) +{ + if (HWIF(drive)->ideproc) { + HWIF(drive)->ideproc(ideproc_atapi_output_bytes, drive, buffer, bytecount); + return; + } + + ++bytecount; +#if defined(CONFIG_ATARI) || defined(CONFIG_Q40) + if (MACH_IS_ATARI || MACH_IS_Q40) { + /* Atari has a byte-swapped IDE interface */ + outsw_swapw(IDE_DATA_REG, buffer, bytecount / 2); + return; + } +#endif /* CONFIG_ATARI */ + ata_output_data (drive, buffer, bytecount / 4); + if ((bytecount & 0x03) >= 2) + outsw (IDE_DATA_REG, ((byte *)buffer) + (bytecount & ~0x03), 1); +} -static inline void taskfile_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount) +void taskfile_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount) { ata_input_data(drive, buffer, wcount); if (drive->bswap) ata_bswap_data(buffer, wcount); } -static inline void taskfile_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount) +void taskfile_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount) { if (drive->bswap) { ata_bswap_data(buffer, wcount); @@ -165,102 +267,154 @@ } } -ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) +/* + * Needed for PCI irq sharing + */ +int drive_is_ready (ide_drive_t *drive) { - task_struct_t *taskfile = (task_struct_t *) task->tfRegister; - hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister; - struct hd_driveid *id = drive->id; - byte HIHI = (drive->addressing) ? 0xE0 : 0xEF; + byte stat = 0; + if (drive->waiting_for_dma) + return HWIF(drive)->dmaproc(ide_dma_test_irq, drive); +#if 0 + /* need to guarantee 400ns since last command was issued */ + udelay(1); +#endif - /* (ks/hs): Moved to start, do not use for multiple out commands */ - if (task->handler != task_mulout_intr) { - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */ - SELECT_MASK(HWIF(drive), drive, 0); - } +#ifdef CONFIG_IDEPCI_SHARE_IRQ + /* + * We do a passive status test under shared PCI interrupts on + * cards that truly share the ATA side interrupt, but may also share + * an interrupt with another pci card/device. We make no assumptions + * about possible isa-pnp and pci-pnp issues yet. + */ + if (IDE_CONTROL_REG) + stat = GET_ALTSTAT(); + else +#endif /* CONFIG_IDEPCI_SHARE_IRQ */ + stat = GET_STAT(); /* Note: this may clear a pending IRQ!! */ - if ((id->command_set_2 & 0x0400) && - (id->cfs_enable_2 & 0x0400) && - (drive->addressing == 1)) { - OUT_BYTE(hobfile->feature, IDE_FEATURE_REG); - OUT_BYTE(hobfile->sector_count, IDE_NSECTOR_REG); - OUT_BYTE(hobfile->sector_number, IDE_SECTOR_REG); - OUT_BYTE(hobfile->low_cylinder, IDE_LCYL_REG); - OUT_BYTE(hobfile->high_cylinder, IDE_HCYL_REG); - } + if (stat & BUSY_STAT) + return 0; /* drive busy: definitely not interrupting */ + return 1; /* drive ready: *might* be interrupting */ +} - OUT_BYTE(taskfile->feature, IDE_FEATURE_REG); - OUT_BYTE(taskfile->sector_count, IDE_NSECTOR_REG); - /* refers to number of sectors to transfer */ - OUT_BYTE(taskfile->sector_number, IDE_SECTOR_REG); - /* refers to sector offset or start sector */ - OUT_BYTE(taskfile->low_cylinder, IDE_LCYL_REG); - OUT_BYTE(taskfile->high_cylinder, IDE_HCYL_REG); +/* + * Global for All, and taken from ide-pmac.c + */ +int wait_for_ready (ide_drive_t *drive, int timeout) +{ + byte stat = 0; - OUT_BYTE((taskfile->device_head & HIHI) | drive->select.all, IDE_SELECT_REG); - if (task->handler != NULL) { -#if 0 - ide_set_handler (drive, task->handler, WAIT_CMD, NULL); - OUT_BYTE(taskfile->command, IDE_COMMAND_REG); - /* - * warning check for race between handler and prehandler for - * writing first block of data. however since we are well - * inside the boundaries of the seek, we should be okay. - */ - if (task->prehandler != NULL) { - return task->prehandler(drive, task->rq); + while(--timeout) { + stat = GET_STAT(); + if(!(stat & BUSY_STAT)) { + if (drive->ready_stat == 0) + break; + else if((stat & drive->ready_stat) || (stat & ERR_STAT)) + break; } -#else - ide_startstop_t startstop; - - ide_set_handler (drive, task->handler, WAIT_CMD, NULL); - OUT_BYTE(taskfile->command, IDE_COMMAND_REG); + mdelay(1); + } + if((stat & ERR_STAT) || timeout <= 0) { + if (stat & ERR_STAT) { + printk(KERN_ERR "%s: wait_for_ready, error status: %x\n", drive->name, stat); + } + return 1; + } + return 0; +} - if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) { - printk(KERN_ERR "%s: no DRQ after issuing %s\n", - drive->name, - drive->mult_count ? "MULTWRITE" : "WRITE"); - return startstop; - } - /* (ks/hs): Fixed Multi Write */ - if ((taskfile->command != WIN_MULTWRITE) && - (taskfile->command != WIN_MULTWRITE_EXT)) { - struct request *rq = HWGROUP(drive)->rq; - /* For Write_sectors we need to stuff the first sector */ - taskfile_output_data(drive, rq->buffer, SECTOR_WORDS); - rq->current_nr_sectors--; - } else { - /* Stuff first sector(s) by implicitly calling the handler */ - if (!(drive_is_ready(drive))) { - /* FIXME: Replace hard-coded 100, error handling? */ - int i; - for (i=0; i<100; i++) { - if (drive_is_ready(drive)) - break; - } +/* + * This routine busy-waits for the drive status to be not "busy". + * It then checks the status for all of the "good" bits and none + * of the "bad" bits, and if all is okay it returns 0. All other + * cases return 1 after invoking ide_error() -- caller should just return. + * + * This routine should get fixed to not hog the cpu during extra long waits.. + * That could be done by busy-waiting for the first jiffy or two, and then + * setting a timer to wake up at half second intervals thereafter, + * until timeout is achieved, before timing out. + */ +int ide_wait_stat (ide_startstop_t *startstop, ide_drive_t *drive, byte good, byte bad, unsigned long timeout) +{ + byte stat; + int i; + unsigned long flags; + + /* bail early if we've exceeded max_failures */ + if (drive->max_failures && (drive->failures > drive->max_failures)) { + *startstop = ide_stopped; + return 1; + } + + udelay(1); /* spec allows drive 400ns to assert "BUSY" */ + if ((stat = GET_STAT()) & BUSY_STAT) { + local_irq_set(flags); + timeout += jiffies; + while ((stat = GET_STAT()) & BUSY_STAT) { + if (time_after(jiffies, timeout)) { + local_irq_restore(flags); + *startstop = DRIVER(drive)->error(drive, "status timeout", stat); + return 1; } - return task->handler(drive); } -#endif - } else { - /* for dma commands we down set the handler */ - if (drive->using_dma && !(HWIF(drive)->dmaproc(((taskfile->command == WIN_WRITEDMA) || (taskfile->command == WIN_WRITEDMA_EXT)) ? ide_dma_write : ide_dma_read, drive))); + local_irq_restore(flags); + } + /* + * Allow status to settle, then read it again. + * A few rare drives vastly violate the 400ns spec here, + * so we'll wait up to 10usec for a "good" status + * rather than expensively fail things immediately. + * This fix courtesy of Matthew Faupel & Niccolo Rigacci. + */ + for (i = 0; i < 10; i++) { + udelay(1); + if (OK_STAT((stat = GET_STAT()), good, bad)) + return 0; } + *startstop = DRIVER(drive)->error(drive, "status error", stat); + return 1; +} - return ide_started; +void debug_taskfile (ide_drive_t *drive, ide_task_t *args) +{ +#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG + printk(KERN_INFO "%s: ", drive->name); +// printk("TF.0=x%02x ", args->tfRegister[IDE_DATA_OFFSET]); + printk("TF.1=x%02x ", args->tfRegister[IDE_FEATURE_OFFSET]); + printk("TF.2=x%02x ", args->tfRegister[IDE_NSECTOR_OFFSET]); + printk("TF.3=x%02x ", args->tfRegister[IDE_SECTOR_OFFSET]); + printk("TF.4=x%02x ", args->tfRegister[IDE_LCYL_OFFSET]); + printk("TF.5=x%02x ", args->tfRegister[IDE_HCYL_OFFSET]); + printk("TF.6=x%02x ", args->tfRegister[IDE_SELECT_OFFSET]); + printk("TF.7=x%02x\n", args->tfRegister[IDE_COMMAND_OFFSET]); + printk(KERN_INFO "%s: ", drive->name); +// printk("HTF.0=x%02x ", args->hobRegister[IDE_DATA_OFFSET_HOB]); + printk("HTF.1=x%02x ", args->hobRegister[IDE_FEATURE_OFFSET_HOB]); + printk("HTF.2=x%02x ", args->hobRegister[IDE_NSECTOR_OFFSET_HOB]); + printk("HTF.3=x%02x ", args->hobRegister[IDE_SECTOR_OFFSET_HOB]); + printk("HTF.4=x%02x ", args->hobRegister[IDE_LCYL_OFFSET_HOB]); + printk("HTF.5=x%02x ", args->hobRegister[IDE_HCYL_OFFSET_HOB]); + printk("HTF.6=x%02x ", args->hobRegister[IDE_SELECT_OFFSET_HOB]); + printk("HTF.7=x%02x\n", args->hobRegister[IDE_CONTROL_OFFSET_HOB]); +#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */ } -void do_taskfile (ide_drive_t *drive, struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile, ide_handler_t *handler) +ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) { + task_struct_t *taskfile = (task_struct_t *) task->tfRegister; + hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister; struct hd_driveid *id = drive->id; - byte HIHI = (drive->addressing) ? 0xE0 : 0xEF; + byte HIHI = (drive->addressing == 1) ? 0xE0 : 0xEF; - /* (ks/hs): Moved to start, do not use for multiple out commands */ - if (*handler != task_mulout_intr) { - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */ - SELECT_MASK(HWIF(drive), drive, 0); - } +#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG + void debug_taskfile(drive, task); +#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */ + + /* ALL Command Block Executions SHALL clear nIEN, unless otherwise */ + if (IDE_CONTROL_REG) + OUT_BYTE(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */ + SELECT_MASK(HWIF(drive), drive, 0); if ((id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400) && @@ -281,147 +435,41 @@ OUT_BYTE(taskfile->high_cylinder, IDE_HCYL_REG); OUT_BYTE((taskfile->device_head & HIHI) | drive->select.all, IDE_SELECT_REG); - if (handler != NULL) { - ide_set_handler (drive, handler, WAIT_CMD, NULL); - OUT_BYTE(taskfile->command, IDE_COMMAND_REG); - } else { - /* for dma commands we down set the handler */ - if (drive->using_dma && !(HWIF(drive)->dmaproc(((taskfile->command == WIN_WRITEDMA) || (taskfile->command == WIN_WRITEDMA_EXT)) ? ide_dma_write : ide_dma_read, drive))); - } -} - -#if 0 -ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task) -{ - task_struct_t *taskfile = (task_struct_t *) task->tfRegister; - hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister; - struct hd_driveid *id = drive->id; - - /* - * (KS) Check taskfile in/out flags. - * If set, then execute as it is defined. - * If not set, then define default settings. - * The default values are: - * write and read all taskfile registers (except data) - * write and read the hob registers (sector,nsector,lcyl,hcyl) - */ - if (task->tf_out_flags.all == 0) { - task->tf_out_flags.all = IDE_TASKFILE_STD_OUT_FLAGS; - if ((id->command_set_2 & 0x0400) && - (id->cfs_enable_2 & 0x0400) && - (drive->addressing == 1)) { - task->tf_out_flags.all != (IDE_HOB_STD_OUT_FLAGS << 8); - } - } - - if (task->tf_in_flags.all == 0) { - task->tf_in_flags.all = IDE_TASKFILE_STD_IN_FLAGS; - if ((id->command_set_2 & 0x0400) && - (id->cfs_enable_2 & 0x0400) && - (drive->addressing == 1)) { - task->tf_in_flags.all != (IDE_HOB_STD_IN_FLAGS << 8); - } - } - - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */ - SELECT_MASK(HWIF(drive), drive, 0); - - if (task->tf_out_flags.b.data) { - unsigned short data = taskfile->data + (hobfile->data << 8); - OUT_WORD (data, IDE_DATA_REG); - } - - /* (KS) send hob registers first */ - if (task->tf_out_flags.b.nsector_hob) - OUT_BYTE(hobfile->sector_count, IDE_NSECTOR_REG); - if (task->tf_out_flags.b.sector_hob) - OUT_BYTE(hobfile->sector_number, IDE_SECTOR_REG); - if (task->tf_out_flags.b.lcyl_hob) - OUT_BYTE(hobfile->low_cylinder, IDE_LCYL_REG); - if (task->tf_out_flags.b.hcyl_hob) - OUT_BYTE(hobfile->high_cylinder, IDE_HCYL_REG); - - - /* (KS) Send now the standard registers */ - if (task->tf_out_flags.b.error_feature) - OUT_BYTE(taskfile->feature, IDE_FEATURE_REG); - /* refers to number of sectors to transfer */ - if (task->tf_out_flags.b.nsector) - OUT_BYTE(taskfile->sector_count, IDE_NSECTOR_REG); - /* refers to sector offset or start sector */ - if (task->tf_out_flags.b.sector) - OUT_BYTE(taskfile->sector_number, IDE_SECTOR_REG); - if (task->tf_out_flags.b.lcyl) - OUT_BYTE(taskfile->low_cylinder, IDE_LCYL_REG); - if (task->tf_out_flags.b.hcyl) - OUT_BYTE(taskfile->high_cylinder, IDE_HCYL_REG); - - /* - * (KS) Do not modify the specified taskfile. We want to have a - * universal pass through, so we must execute ALL specified values. - * - * (KS) The drive head register is mandatory. - * Don't care about the out flags ! - */ - OUT_BYTE(taskfile->device_head | drive->select.all, IDE_SELECT_REG); if (task->handler != NULL) { -#if 0 ide_set_handler (drive, task->handler, WAIT_CMD, NULL); OUT_BYTE(taskfile->command, IDE_COMMAND_REG); - /* - * warning check for race between handler and prehandler for - * writing first block of data. however since we are well - * inside the boundaries of the seek, we should be okay. - */ - if (task->prehandler != NULL) { + if (task->prehandler != NULL) return task->prehandler(drive, task->rq); - } + return ide_started; + } +#if 0 + switch(task->data_phase) { +#ifdef CONFIG_BLK_DEV_IDEDMA + case TASKFILE_OUT_DMAQ: + case TASKFILE_OUT_DMA: + HWIF(drive)->dmaproc(ide_dma_write, drive); + break; + case TASKFILE_IN_DMAQ: + case TASKFILE_IN_DMA: + HWIF(drive)->dmaproc(ide_dma_read, drive); + break; +#endif /* CONFIG_BLK_DEV_IDEDMA */ + default: + if (task->handler == NULL) + return ide_stopped; + ide_set_handler (drive, task->handler, WAIT_WORSTCASE, NULL); + /* Issue the command */ + OUT_BYTE(taskfile->command, IDE_COMMAND_REG); + if (task->prehandler != NULL) + return task->prehandler(drive, HWGROUP(drive)->rq); + } #else - ide_startstop_t startstop; - - ide_set_handler (drive, task->handler, WAIT_CMD, NULL); - - /* - * (KS) The drive command register is also mandatory. - * Don't care about the out flags ! - */ - OUT_BYTE(taskfile->command, IDE_COMMAND_REG); - - if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) { - printk(KERN_ERR "%s: no DRQ after issuing %s\n", - drive->name, - drive->mult_count ? "MULTWRITE" : "WRITE"); - return startstop; - } - /* (ks/hs): Fixed Multi Write */ - if ((taskfile->command != WIN_MULTWRITE) && - (taskfile->command != WIN_MULTWRITE_EXT)) { - struct request *rq = HWGROUP(drive)->rq; - /* For Write_sectors we need to stuff the first sector */ - taskfile_output_data(drive, rq->buffer, SECTOR_WORDS); - rq->current_nr_sectors--; - } else { - /* Stuff first sector(s) by implicitly calling the handler */ - if (!(drive_is_ready(drive))) { - /* FIXME: Replace hard-coded 100, error handling? */ - int i; - for (i=0; i<100; i++) { - if (drive_is_ready(drive)) - break; - } - } - return task->handler(drive); - } + // if ((rq->cmd == WRITE) && (drive->using_dma)) + /* for dma commands we down set the handler */ + if (drive->using_dma && !(HWIF(drive)->dmaproc(((taskfile->command == WIN_WRITEDMA) || (taskfile->command == WIN_WRITEDMA_EXT)) ? ide_dma_write : ide_dma_read, drive))); #endif - } else { - /* for dma commands we down set the handler */ - if (drive->using_dma && !(HWIF(drive)->dmaproc(((taskfile->command == WIN_WRITEDMA) || (taskfile->command == WIN_WRITEDMA_EXT)) ? ide_dma_write : ide_dma_read, drive))); - } - return ide_started; } -#endif #if 0 /* @@ -432,8 +480,7 @@ unsigned long flags; byte err = 0; - __save_flags (flags); /* local CPU only */ - ide__sti(); /* local CPU only */ + local_irq_set(flags); printk("%s: %s: status=0x%02x", drive->name, msg, stat); #if FANCY_STATUS_DUMPS printk(" { "); @@ -492,15 +539,16 @@ } } if (HWGROUP(drive)->rq) - printk(", sector=%llu", (__u64) HWGROUP(drive)->rq->sector); + printk(", sector=%lu", (__u64) HWGROUP(drive)->rq->sector); } } #endif /* FANCY_STATUS_DUMPS */ printk("\n"); } - __restore_flags (flags); /* local CPU only */ + local_irq_restore(flags); return err; } +#endif /* * Clean up after success/failure of an explicit taskfile operation. @@ -519,8 +567,14 @@ command = args->tfRegister[IDE_COMMAND_OFFSET]; - rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); + if (rq->errors == 0) + rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); + if (args->tf_in_flags.b.data) { + unsigned short data = IN_WORD(IDE_DATA_REG); + args->tfRegister[IDE_DATA_OFFSET] = (data) & 0xFF; + args->hobRegister[IDE_DATA_OFFSET_HOB] = (data >> 8) & 0xFF; + } args->tfRegister[IDE_ERROR_OFFSET] = err; args->tfRegister[IDE_NSECTOR_OFFSET] = IN_BYTE(IDE_NSECTOR_REG); args->tfRegister[IDE_SECTOR_OFFSET] = IN_BYTE(IDE_SECTOR_REG); @@ -539,8 +593,13 @@ args->hobRegister[IDE_HCYL_OFFSET_HOB] = IN_BYTE(IDE_HCYL_REG); } +#if 0 /* taskfile_settings_update(drive, args, command); */ + if (args->posthandler != NULL) + args->posthandler(drive, args); +#endif + spin_lock_irqsave(&io_request_lock, flags); blkdev_dequeue_request(rq); HWGROUP(drive)->rq = NULL; @@ -548,6 +607,7 @@ spin_unlock_irqrestore(&io_request_lock, flags); } +#if 0 /* * try_to_flush_leftover_data() is invoked in response to a drive * unexpectedly having its DRQ_STAT bit set. As an alternative to @@ -608,10 +668,7 @@ OUT_BYTE(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG); /* force an abort */ if (rq->errors >= ERROR_MAX) { - if (drive->driver != NULL) - DRIVER(drive)->end_request(0, HWGROUP(drive)); - else - ide_end_request(0, HWGROUP(drive)); + DRIVER(drive)->end_request(drive, 0); } else { if ((rq->errors & ERROR_RESET) == ERROR_RESET) { ++rq->errors; @@ -657,8 +714,10 @@ return ide_stopped; if (stat & (ERR_STAT|DRQ_STAT)) - return ide_error(drive, "set_geometry_intr", stat); + return DRIVER(drive)->error(drive, "set_geometry_intr", stat); + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler(drive, &set_geometry_intr, WAIT_CMD, NULL); return ide_started; } @@ -671,7 +730,7 @@ byte stat = GET_STAT(); if (!OK_STAT(stat,READY_STAT,BAD_STAT)) - return ide_error(drive, "recal_intr", stat); + return DRIVER(drive)->error(drive, "recal_intr", stat); return ide_stopped; } @@ -683,11 +742,13 @@ ide_task_t *args = HWGROUP(drive)->rq->special; byte stat = GET_STAT(); - ide__sti(); /* local CPU only */ - - if (!OK_STAT(stat, READY_STAT, BAD_STAT)) - return ide_error(drive, "task_no_data_intr", stat); /* calls ide_end_drive_cmd */ - + local_irq_enable(); + if (!OK_STAT(stat, READY_STAT, BAD_STAT)) { + DTF("%s: command opcode 0x%02x\n", drive->name, + args->tfRegister[IDE_COMMAND_OFFSET]); + return DRIVER(drive)->error(drive, "task_no_data_intr", stat); + /* calls ide_end_drive_cmd */ + } if (args) ide_end_drive_cmd (drive, stat, GET_ERR()); @@ -695,42 +756,85 @@ } /* - * Handler for command with PIO data-in phase + * Handler for command with PIO data-in phase, READ + */ +/* + * FIXME before 2.4 enable ... + * DATA integrity issue upon error. */ ide_startstop_t task_in_intr (ide_drive_t *drive) { byte stat = GET_STAT(); - byte io_32bit = drive->io_32bit; struct request *rq = HWGROUP(drive)->rq; char *pBuf = NULL; + unsigned long flags; if (!OK_STAT(stat,DATA_READY,BAD_R_STAT)) { if (stat & (ERR_STAT|DRQ_STAT)) { - return ide_error(drive, "task_in_intr", stat); +#if 0 + DTF("%s: attempting to recover last " \ + "sector counter status=0x%02x\n", + drive->name, stat); + /* + * Expect a BUG BOMB if we attempt to rewind the + * offset in the BH aka PAGE in the current BLOCK + * segment. This is different than the HOST segment. + */ +#endif + if (!rq->bh) + rq->current_nr_sectors++; + return DRIVER(drive)->error(drive, "task_in_intr", stat); } if (!(stat & BUSY_STAT)) { DTF("task_in_intr to Soon wait for next interrupt\n"); - ide_set_handler(drive, &task_in_intr, WAIT_CMD, NULL); + if (HWGROUP(drive)->handler == NULL) + ide_set_handler(drive, &task_in_intr, WAIT_CMD, NULL); return ide_started; } } - DTF("stat: %02x\n", stat); - pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); - DTF("Read: %p, rq->current_nr_sectors: %d\n", pBuf, (int) rq->current_nr_sectors); +#if 0 - drive->io_32bit = 0; - taskfile_input_data(drive, pBuf, SECTOR_WORDS); - drive->io_32bit = io_32bit; + /* + * Holding point for a brain dump of a thought :-/ + */ - if (--rq->current_nr_sectors <= 0) { - /* (hs): swapped next 2 lines */ - DTF("Request Ended stat: %02x\n", GET_STAT()); - ide_end_request(1, HWGROUP(drive)); - } else { + if (!OK_STAT(stat,DRIVE_READY,drive->bad_wstat)) { + DTF("%s: READ attempting to recover last " \ + "sector counter status=0x%02x\n", + drive->name, stat); + rq->current_nr_sectors++; + return DRIVER(drive)->error(drive, "task_in_intr", stat); + } + if (!rq->current_nr_sectors) + if (!DRIVER(drive)->end_request(drive, 1)) + return ide_stopped; + + if (--rq->current_nr_sectors <= 0) + if (!DRIVER(drive)->end_request(drive, 1)) + return ide_stopped; +#endif + + pBuf = task_map_rq(rq, &flags); + DTF("Read: %p, rq->current_nr_sectors: %d, stat: %02x\n", + pBuf, (int) rq->current_nr_sectors, stat); + taskfile_input_data(drive, pBuf, SECTOR_WORDS); + task_unmap_rq(rq, pBuf, &flags); + /* + * FIXME :: We really can not legally get a new page/bh + * regardless, if this is the end of our segment. + * BH walking or segment can only be updated after we have a good + * GET_STAT(); return. + */ + if (--rq->current_nr_sectors <= 0) + if (!DRIVER(drive)->end_request(drive, 1)) + return ide_stopped; + /* + * ERM, it is techincally legal to leave/exit here but it makes + * a mess of the code ... + */ + if (HWGROUP(drive)->handler == NULL) ide_set_handler(drive, &task_in_intr, WAIT_CMD, NULL); - return ide_started; - } - return ide_stopped; + return ide_started; } #undef ALTSTAT_SCREW_UP @@ -765,6 +869,7 @@ */ byte altstat_multi_poll (ide_drive_t *drive, byte stat, const char *msg) { + /* (ks/hs): FIXME: Error handling, time-out? */ while (stat & BUSY_STAT) stat = GET_ALTSTAT(); @@ -778,30 +883,37 @@ */ ide_startstop_t task_mulin_intr (ide_drive_t *drive) { - unsigned int msect, nsect; - #ifdef ALTSTAT_SCREW_UP byte stat = altstat_multi_busy(drive, GET_ALTSTAT(), "read"); #else byte stat = GET_STAT(); #endif /* ALTSTAT_SCREW_UP */ - - byte io_32bit = drive->io_32bit; struct request *rq = HWGROUP(drive)->rq; char *pBuf = NULL; + unsigned int msect = drive->mult_count; + unsigned int nsect; + unsigned long flags; if (!OK_STAT(stat,DATA_READY,BAD_R_STAT)) { if (stat & (ERR_STAT|DRQ_STAT)) { - return ide_error(drive, "task_mulin_intr", stat); + if (!rq->bh) { + rq->current_nr_sectors += drive->mult_count; + /* + * NOTE: could rewind beyond beginning :-/ + */ + } else { + printk("%s: MULTI-READ assume all data " \ + "transfered is bad status=0x%02x\n", + drive->name, stat); + } + return DRIVER(drive)->error(drive, "task_mulin_intr", stat); } /* no data yet, so wait for another interrupt */ - ide_set_handler(drive, &task_mulin_intr, WAIT_CMD, NULL); + if (HWGROUP(drive)->handler == NULL) + ide_set_handler(drive, &task_mulin_intr, WAIT_CMD, NULL); return ide_started; } - /* (ks/hs): Fixed Multi-Sector transfer */ - msect = drive->mult_count; - #ifdef ALTSTAT_SCREW_UP /* * Screw the request we do not support bad data-phase setups! @@ -814,157 +926,237 @@ */ nsect = 1; while (rq->current_nr_sectors) { - pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); - DTF("Multiread: %p, nsect: %d, rq->current_nr_sectors: %ld\n", pBuf, nsect, rq->current_nr_sectors); - drive->io_32bit = 0; + pBuf = task_map_rq(rq, &flags); + DTF("Multiread: %p, nsect: %d, " \ + "rq->current_nr_sectors: %ld\n", + pBuf, nsect, rq->current_nr_sectors); +// rq->current_nr_sectors -= nsect; taskfile_input_data(drive, pBuf, nsect * SECTOR_WORDS); - drive->io_32bit = io_32bit; + task_unmap_rq(rq, pBuf, &flags); rq->errors = 0; rq->current_nr_sectors -= nsect; stat = altstat_multi_poll(drive, GET_ALTSTAT(), "read"); } - ide_end_request(1, HWGROUP(drive)); + DRIVER(drive)->end_request(drive, 1); return ide_stopped; } #endif /* ALTSTAT_SCREW_UP */ - nsect = (rq->current_nr_sectors > msect) ? msect : rq->current_nr_sectors; - pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); - - DTF("Multiread: %p, nsect: %d , rq->current_nr_sectors: %ld\n", - pBuf, nsect, rq->current_nr_sectors); - drive->io_32bit = 0; - taskfile_input_data(drive, pBuf, nsect * SECTOR_WORDS); - drive->io_32bit = io_32bit; - rq->errors = 0; - rq->current_nr_sectors -= nsect; - if (rq->current_nr_sectors != 0) { + do { + nsect = rq->current_nr_sectors; + if (nsect > msect) + nsect = msect; + pBuf = task_map_rq(rq, &flags); + DTF("Multiread: %p, nsect: %d, msect: %d, " \ + " rq->current_nr_sectors: %d\n", + pBuf, nsect, msect, rq->current_nr_sectors); +// rq->current_nr_sectors -= nsect; +// msect -= nsect; + taskfile_input_data(drive, pBuf, nsect * SECTOR_WORDS); + task_unmap_rq(rq, pBuf, &flags); + rq->errors = 0; + rq->current_nr_sectors -= nsect; + msect -= nsect; + /* + * FIXME :: We really can not legally get a new page/bh + * regardless, if this is the end of our segment. + * BH walking or segment can only be updated after we have a + * good GET_STAT(); return. + */ + if (!rq->current_nr_sectors) { + if (!DRIVER(drive)->end_request(drive, 1)) + return ide_stopped; + } + } while (msect); + if (HWGROUP(drive)->handler == NULL) ide_set_handler(drive, &task_mulin_intr, WAIT_CMD, NULL); - return ide_started; - } - ide_end_request(1, HWGROUP(drive)); - return ide_stopped; + return ide_started; } +/* + * VERIFY ME before 2.4 ... unexpected race is possible based on details + * RMK with 74LS245/373/374 TTL buffer logic because of passthrough. + */ ide_startstop_t pre_task_out_intr (ide_drive_t *drive, struct request *rq) { - ide_task_t *args = rq->special; + char *pBuf = NULL; + unsigned long flags; ide_startstop_t startstop; - if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) { - printk(KERN_ERR "%s: no DRQ after issuing %s\n", drive->name, drive->mult_count ? "MULTWRITE" : "WRITE"); + if (ide_wait_stat(&startstop, drive, DATA_READY, + drive->bad_wstat, WAIT_DRQ)) { + printk(KERN_ERR "%s: no DRQ after issuing %s\n", + drive->name, + drive->addressing ? "WRITE_EXT" : "WRITE"); return startstop; } - - /* (ks/hs): Fixed Multi Write */ - if ((args->tfRegister[IDE_COMMAND_OFFSET] != WIN_MULTWRITE) && - (args->tfRegister[IDE_COMMAND_OFFSET] != WIN_MULTWRITE_EXT)) { - /* For Write_sectors we need to stuff the first sector */ - taskfile_output_data(drive, rq->buffer, SECTOR_WORDS); - rq->current_nr_sectors--; - return ide_started; - } else { - /* - * (ks/hs): Stuff the first sector(s) - * by implicitly calling the handler - */ - if (!(drive_is_ready(drive))) { - int i; - /* - * (ks/hs): FIXME: Replace hard-coded - * 100, error handling? - */ - for (i=0; i<100; i++) { - if (drive_is_ready(drive)) - break; - } - } - return args->handler(drive); - } + /* For Write_sectors we need to stuff the first sector */ + pBuf = task_map_rq(rq, &flags); +// rq->current_nr_sectors--; + taskfile_output_data(drive, pBuf, SECTOR_WORDS); + rq->current_nr_sectors--; + /* + * WARNING :: Interrupt could happen instantly :-/ + */ + task_unmap_rq(rq, pBuf, &flags); return ide_started; } /* - * Handler for command with PIO data-out phase + * Handler for command with PIO data-out phase WRITE + * + * WOOHOO this is a CORRECT STATE DIAGRAM NOW, */ ide_startstop_t task_out_intr (ide_drive_t *drive) { byte stat = GET_STAT(); - byte io_32bit = drive->io_32bit; struct request *rq = HWGROUP(drive)->rq; char *pBuf = NULL; - - if (!rq->current_nr_sectors) { - ide_end_request(1, HWGROUP(drive)); - return ide_stopped; - } + unsigned long flags; if (!OK_STAT(stat,DRIVE_READY,drive->bad_wstat)) { - return ide_error(drive, "task_out_intr", stat); + DTF("%s: WRITE attempting to recover last " \ + "sector counter status=0x%02x\n", + drive->name, stat); + rq->current_nr_sectors++; + return DRIVER(drive)->error(drive, "task_out_intr", stat); } + /* + * Safe to update request for partial completions. + * We have a good STATUS CHECK!!! + */ + if (!rq->current_nr_sectors) + if (!DRIVER(drive)->end_request(drive, 1)) + return ide_stopped; if ((rq->current_nr_sectors==1) ^ (stat & DRQ_STAT)) { rq = HWGROUP(drive)->rq; - pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); - DTF("write: %p, rq->current_nr_sectors: %d\n", pBuf, (int) rq->current_nr_sectors); - drive->io_32bit = 0; + pBuf = task_map_rq(rq, &flags); + DTF("write: %p, rq->current_nr_sectors: %d\n", + pBuf, (int) rq->current_nr_sectors); +// rq->current_nr_sectors--; taskfile_output_data(drive, pBuf, SECTOR_WORDS); - drive->io_32bit = io_32bit; + task_unmap_rq(rq, pBuf, &flags); rq->errors = 0; rq->current_nr_sectors--; } - - if (rq->current_nr_sectors <= 0) { - ide_end_request(1, HWGROUP(drive)); - } else { + if (HWGROUP(drive)->handler == NULL) ide_set_handler(drive, &task_out_intr, WAIT_CMD, NULL); - return ide_started; + return ide_started; +} + +ide_startstop_t pre_task_mulout_intr (ide_drive_t *drive, struct request *rq) +{ + ide_task_t *args = rq->special; + ide_startstop_t startstop; + +#if 0 + /* + * assign private copy for multi-write + */ + memcpy(&HWGROUP(drive)->wrq, rq, sizeof(struct request)); +#endif + + if (ide_wait_stat(&startstop, drive, DATA_READY, + drive->bad_wstat, WAIT_DRQ)) { + printk(KERN_ERR "%s: no DRQ after issuing %s\n", + drive->name, + drive->addressing ? "MULTWRITE_EXT" : "MULTWRITE"); + return startstop; } - return ide_stopped; +#if 0 + if (wait_for_ready(drive, 100)) + IDE_DEBUG(__LINE__); //BUG(); +#else + if (!(drive_is_ready(drive))) { + int i; + for (i=0; i<100; i++) { + if (drive_is_ready(drive)) + break; + } + } +#endif + /* + * WARNING :: if the drive as not acked good status we may not + * move the DATA-TRANSFER T-Bar as BSY != 0. + */ + return args->handler(drive); } /* + * FIXME before enabling in 2.4 ... DATA integrity issue upon error. + */ +/* * Handler for command write multiple * Called directly from execute_drive_cmd for the first bunch of sectors, * afterwards only by the ISR */ ide_startstop_t task_mulout_intr (ide_drive_t *drive) { - unsigned int msect, nsect; - #ifdef ALTSTAT_SCREW_UP byte stat = altstat_multi_busy(drive, GET_ALTSTAT(), "write"); #else byte stat = GET_STAT(); #endif /* ALTSTAT_SCREW_UP */ - byte io_32bit = drive->io_32bit; - struct request *rq = HWGROUP(drive)->rq; - ide_hwgroup_t *hwgroup = HWGROUP(drive); - char *pBuf = NULL; + struct request *rq = HWGROUP(drive)->rq; + char *pBuf = NULL; + ide_startstop_t startstop = ide_stopped; + unsigned int msect = drive->mult_count; + unsigned int nsect; + unsigned long flags; /* * (ks/hs): Handle last IRQ on multi-sector transfer, - * occurs after all data was sent + * occurs after all data was sent in this chunk */ if (rq->current_nr_sectors == 0) { - if (stat & (ERR_STAT|DRQ_STAT)) - return ide_error(drive, "task_mulout_intr", stat); - ide_end_request(1, HWGROUP(drive)); - return ide_stopped; + if (stat & (ERR_STAT|DRQ_STAT)) { + if (!rq->bh) { + rq->current_nr_sectors += drive->mult_count; + /* + * NOTE: could rewind beyond beginning :-/ + */ + } else { + printk("%s: MULTI-WRITE assume all data " \ + "transfered is bad status=0x%02x\n", + drive->name, stat); + } + return DRIVER(drive)->error(drive, "task_mulout_intr", stat); + } + if (!rq->bh) + DRIVER(drive)->end_request(drive, 1); + return startstop; } - + /* + * DON'T be lazy code the above and below togather !!! + */ if (!OK_STAT(stat,DATA_READY,BAD_R_STAT)) { if (stat & (ERR_STAT|DRQ_STAT)) { - return ide_error(drive, "task_mulout_intr", stat); + if (!rq->bh) { + rq->current_nr_sectors += drive->mult_count; + /* + * NOTE: could rewind beyond beginning :-/ + */ + } else { + printk("%s: MULTI-WRITE assume all data " \ + "transfered is bad status=0x%02x\n", + drive->name, stat); + } + return DRIVER(drive)->error(drive, "task_mulout_intr", stat); } /* no data yet, so wait for another interrupt */ - if (hwgroup->handler == NULL) + if (HWGROUP(drive)->handler == NULL) ide_set_handler(drive, &task_mulout_intr, WAIT_CMD, NULL); return ide_started; } - /* (ks/hs): See task_mulin_intr */ - msect = drive->mult_count; + if (HWGROUP(drive)->handler != NULL) { + unsigned long lflags; + spin_lock_irqsave(&io_request_lock, lflags); + HWGROUP(drive)->handler = NULL; + del_timer(&HWGROUP(drive)->timer); + spin_unlock_irqrestore(&io_request_lock, lflags); + } #ifdef ALTSTAT_SCREW_UP /* @@ -974,30 +1166,49 @@ if (!msect) { nsect = 1; while (rq->current_nr_sectors) { - pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); - DTF("Multiwrite: %p, nsect: %d, rq->current_nr_sectors: %ld\n", pBuf, nsect, rq->current_nr_sectors); - drive->io_32bit = 0; + pBuf = task_map_rq(rq, &flags); + DTF("Multiwrite: %p, nsect: %d, " \ + "rq->current_nr_sectors: %d\n", + pBuf, nsect, rq->current_nr_sectors); +// rq->current_nr_sectors -= nsect; taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS); - drive->io_32bit = io_32bit; + task_unmap_rq(pBuf, &flags); rq->errors = 0; rq->current_nr_sectors -= nsect; stat = altstat_multi_poll(drive, GET_ALTSTAT(), "write"); } - ide_end_request(1, HWGROUP(drive)); + DRIVER(drive)->end_request(drive, 1); return ide_stopped; } #endif /* ALTSTAT_SCREW_UP */ - nsect = (rq->current_nr_sectors > msect) ? msect : rq->current_nr_sectors; - pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); - DTF("Multiwrite: %p, nsect: %d , rq->current_nr_sectors: %ld\n", - pBuf, nsect, rq->current_nr_sectors); - drive->io_32bit = 0; - taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS); - drive->io_32bit = io_32bit; + do { + nsect = rq->current_nr_sectors; + if (nsect > msect) + nsect = msect; + pBuf = task_map_rq(rq, &flags); + DTF("Multiwrite: %p, nsect: %d, msect: %d, " \ + "rq->current_nr_sectors: %ld\n", + pBuf, nsect, msect, rq->current_nr_sectors); + msect -= nsect; +// rq->current_nr_sectors -= nsect; + taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS); + task_unmap_rq(rq, pBuf, &flags); + rq->current_nr_sectors -= nsect; + /* + * FIXME :: We really can not legally get a new page/bh + * regardless, if this is the end of our segment. + * BH walking or segment can only be updated after we + * have a good GET_STAT(); return. + */ + if (!rq->current_nr_sectors) { + if (!DRIVER(drive)->end_request(drive, 1)) + if (!rq->bh) + return ide_stopped; + } + } while (msect); rq->errors = 0; - rq->current_nr_sectors -= nsect; - if (hwgroup->handler == NULL) + if (HWGROUP(drive)->handler == NULL) ide_set_handler(drive, &task_mulout_intr, WAIT_CMD, NULL); return ide_started; } @@ -1008,14 +1219,16 @@ switch(taskfile->command) { /* IDE_DRIVE_TASK_RAW_WRITE */ case CFA_WRITE_MULTI_WO_ERASE: + // case WIN_WRITE_LONG: + // case WIN_WRITE_LONG_ONCE: case WIN_MULTWRITE: case WIN_MULTWRITE_EXT: -// case WIN_WRITEDMA: -// case WIN_WRITEDMA_QUEUED: -// case WIN_WRITEDMA_EXT: -// case WIN_WRITEDMA_QUEUED_EXT: + return &pre_task_mulout_intr; + /* IDE_DRIVE_TASK_OUT */ case WIN_WRITE: + // case WIN_WRITE_ONCE: + case WIN_WRITE_EXT: case WIN_WRITE_VERIFY: case WIN_WRITE_BUFFER: case CFA_WRITE_SECT_WO_ERASE: @@ -1025,6 +1238,12 @@ case WIN_SMART: if (taskfile->feature == SMART_WRITE_LOG_SECTOR) return &pre_task_out_intr; + case WIN_WRITEDMA: + // case WIN_WRITEDMA_ONCE: + case WIN_WRITEDMA_QUEUED: + case WIN_WRITEDMA_EXT: + case WIN_WRITEDMA_QUEUED_EXT: + /* IDE_DRIVE_TASK_OUT */ default: break; } @@ -1040,6 +1259,7 @@ case CFA_TRANSLATE_SECTOR: case WIN_READ_BUFFER: case WIN_READ: + // case WIN_READ_ONCE: case WIN_READ_EXT: return &task_in_intr; case WIN_SECURITY_DISABLE: @@ -1051,11 +1271,16 @@ case WIN_WRITE_BUFFER: case WIN_WRITE_VERIFY: case WIN_WRITE: + // case WIN_WRITE_ONCE: case WIN_WRITE_EXT: return &task_out_intr; + // case WIN_READ_LONG: + // case WIN_READ_LONG_ONCE: case WIN_MULTREAD: case WIN_MULTREAD_EXT: return &task_mulin_intr; + // case WIN_WRITE_LONG: + // case WIN_WRITE_LONG_ONCE: case CFA_WRITE_MULTI_WO_ERASE: case WIN_MULTWRITE: case WIN_MULTWRITE_EXT: @@ -1074,13 +1299,16 @@ case CFA_REQ_EXT_ERROR_CODE: case CFA_ERASE_SECTORS: case WIN_VERIFY: + // case WIN_VERIFY_ONCE: case WIN_VERIFY_EXT: case WIN_SEEK: return &task_no_data_intr; case WIN_SPECIFY: return &set_geometry_intr; - case WIN_RESTORE: + case WIN_RECAL: + // case WIN_RESTORE: return &recal_intr; + case WIN_NOP: case WIN_DIAGNOSE: case WIN_FLUSH_CACHE: case WIN_FLUSH_CACHE_EXT: @@ -1111,11 +1339,13 @@ return &task_no_data_intr; #ifdef CONFIG_BLK_DEV_IDEDMA case WIN_READDMA: + // case WIN_READDMA_ONCE: case WIN_IDENTIFY_DMA: case WIN_READDMA_QUEUED: case WIN_READDMA_EXT: case WIN_READDMA_QUEUED_EXT: case WIN_WRITEDMA: + // case WIN_WRITEDMA_ONCE: case WIN_WRITEDMA_QUEUED: case WIN_WRITEDMA_EXT: case WIN_WRITEDMA_QUEUED_EXT: @@ -1130,14 +1360,26 @@ } } +ide_post_handler_t * ide_post_handler_parser (struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile) +{ + switch(taskfile->command) { + case WIN_SPECIFY: /* set_geometry_intr */ + case WIN_RESTORE: /* recal_intr */ + case WIN_SETMULT: /* set_multmode_intr */ + default: + return(NULL); + } +} + /* Called by ioctl to feature out type of command being called */ int ide_cmd_type_parser (ide_task_t *args) { struct hd_drive_task_hdr *taskfile = (struct hd_drive_task_hdr *) args->tfRegister; struct hd_drive_hob_hdr *hobfile = (struct hd_drive_hob_hdr *) args->hobRegister; - args->prehandler = ide_pre_handler_parser(taskfile, hobfile); - args->handler = ide_handler_parser(taskfile, hobfile); + args->prehandler = ide_pre_handler_parser(taskfile, hobfile); + args->handler = ide_handler_parser(taskfile, hobfile); + args->posthandler = ide_post_handler_parser(taskfile, hobfile); switch(args->tfRegister[IDE_COMMAND_OFFSET]) { case WIN_IDENTIFY: @@ -1145,18 +1387,28 @@ return IDE_DRIVE_TASK_IN; case CFA_TRANSLATE_SECTOR: case WIN_READ: + // case WIN_READ_ONCE: + case WIN_READ_EXT: case WIN_READ_BUFFER: return IDE_DRIVE_TASK_IN; case WIN_WRITE: + // case WIN_WRITE_ONCE: + case WIN_WRITE_EXT: case WIN_WRITE_VERIFY: case WIN_WRITE_BUFFER: case CFA_WRITE_SECT_WO_ERASE: case WIN_DOWNLOAD_MICROCODE: return IDE_DRIVE_TASK_RAW_WRITE; + // case WIN_READ_LONG: + // case WIN_READ_LONG_ONCE: case WIN_MULTREAD: + case WIN_MULTREAD_EXT: return IDE_DRIVE_TASK_IN; + // case WIN_WRITE_LONG: + // case WIN_WRITE_LONG_ONCE: case CFA_WRITE_MULTI_WO_ERASE: case WIN_MULTWRITE: + case WIN_MULTWRITE_EXT: return IDE_DRIVE_TASK_RAW_WRITE; case WIN_SECURITY_DISABLE: case WIN_SECURITY_ERASE_UNIT: @@ -1178,12 +1430,14 @@ } #ifdef CONFIG_BLK_DEV_IDEDMA case WIN_READDMA: + // case WIN_READDMA_ONCE: case WIN_IDENTIFY_DMA: case WIN_READDMA_QUEUED: case WIN_READDMA_EXT: case WIN_READDMA_QUEUED_EXT: return IDE_DRIVE_TASK_IN; case WIN_WRITEDMA: + // case WIN_WRITEDMA_ONCE: case WIN_WRITEDMA_QUEUED: case WIN_WRITEDMA_EXT: case WIN_WRITEDMA_QUEUED_EXT: @@ -1191,20 +1445,32 @@ #endif case WIN_SETFEATURES: switch(args->tfRegister[IDE_FEATURE_OFFSET]) { + case SETFEATURES_EN_8BIT: + case SETFEATURES_EN_WCACHE: + return IDE_DRIVE_TASK_NO_DATA; case SETFEATURES_XFER: return IDE_DRIVE_TASK_SET_XFER; case SETFEATURES_DIS_DEFECT: case SETFEATURES_EN_APM: case SETFEATURES_DIS_MSN: + case SETFEATURES_DIS_RETRY: + case SETFEATURES_EN_AAM: + case SETFEATURES_RW_LONG: + case SETFEATURES_SET_CACHE: + case SETFEATURES_DIS_RLA: case SETFEATURES_EN_RI: case SETFEATURES_EN_SI: case SETFEATURES_DIS_RPOD: case SETFEATURES_DIS_WCACHE: case SETFEATURES_EN_DEFECT: case SETFEATURES_DIS_APM: + case SETFEATURES_EN_ECC: case SETFEATURES_EN_MSN: + case SETFEATURES_EN_RETRY: case SETFEATURES_EN_RLA: case SETFEATURES_PREFETCH: + case SETFEATURES_4B_RW_LONG: + case SETFEATURES_DIS_AAM: case SETFEATURES_EN_RPOD: case SETFEATURES_DIS_RI: case SETFEATURES_DIS_SI: @@ -1215,6 +1481,7 @@ case CFA_REQ_EXT_ERROR_CODE: case CFA_ERASE_SECTORS: case WIN_VERIFY: + // case WIN_VERIFY_ONCE: case WIN_VERIFY_EXT: case WIN_SEEK: case WIN_SPECIFY: @@ -1254,119 +1521,462 @@ } /* - * This function is intended to be used prior to invoking ide_do_drive_cmd(). + * NOTICE: This is additions from IBM to provide a discrete interface, + * for selective taskregister access operations. Nice JOB Klaus!!! + * Glad to be able to work and co-develop this with you and IBM. */ -void ide_init_drive_taskfile (struct request *rq) +ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task) { - memset(rq, 0, sizeof(*rq)); - rq->cmd = IDE_DRIVE_TASK_NO_DATA; -} + task_struct_t *taskfile = (task_struct_t *) task->tfRegister; + hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister; + struct hd_driveid *id = drive->id; +#if DEBUG_TASKFILE + byte status; +#endif -/* - * This is kept for internal use only !!! - * This is an internal call and nobody in user-space has a damn - * reason to call this taskfile. - * - * ide_raw_taskfile is the one that user-space executes. - */ -int ide_wait_taskfile (ide_drive_t *drive, struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile, byte *buf) -{ - struct request rq; - ide_task_t args; - memset(&args, 0, sizeof(ide_task_t)); +#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG + void debug_taskfile(drive, task); +#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */ - args.tfRegister[IDE_DATA_OFFSET] = taskfile->data; - args.tfRegister[IDE_FEATURE_OFFSET] = taskfile->feature; - args.tfRegister[IDE_NSECTOR_OFFSET] = taskfile->sector_count; - args.tfRegister[IDE_SECTOR_OFFSET] = taskfile->sector_number; - args.tfRegister[IDE_LCYL_OFFSET] = taskfile->low_cylinder; - args.tfRegister[IDE_HCYL_OFFSET] = taskfile->high_cylinder; - args.tfRegister[IDE_SELECT_OFFSET] = taskfile->device_head; - args.tfRegister[IDE_COMMAND_OFFSET] = taskfile->command; - - args.hobRegister[IDE_DATA_OFFSET_HOB] = hobfile->data; - args.hobRegister[IDE_FEATURE_OFFSET_HOB] = hobfile->feature; - args.hobRegister[IDE_NSECTOR_OFFSET_HOB] = hobfile->sector_count; - args.hobRegister[IDE_SECTOR_OFFSET_HOB] = hobfile->sector_number; - args.hobRegister[IDE_LCYL_OFFSET_HOB] = hobfile->low_cylinder; - args.hobRegister[IDE_HCYL_OFFSET_HOB] = hobfile->high_cylinder; - args.hobRegister[IDE_SELECT_OFFSET_HOB] = hobfile->device_head; - args.hobRegister[IDE_CONTROL_OFFSET_HOB] = hobfile->control; + /* + * (ks) Check taskfile in/out flags. + * If set, then execute as it is defined. + * If not set, then define default settings. + * The default values are: + * write and read all taskfile registers (except data) + * write and read the hob registers (sector,nsector,lcyl,hcyl) + */ + if (task->tf_out_flags.all == 0) { + task->tf_out_flags.all = IDE_TASKFILE_STD_OUT_FLAGS; + if ((id->command_set_2 & 0x0400) && + (id->cfs_enable_2 & 0x0400) && + (drive->addressing == 1)) { + task->tf_out_flags.all |= (IDE_HOB_STD_OUT_FLAGS << 8); + } + } - ide_init_drive_taskfile(&rq); - /* This is kept for internal use only !!! */ - args.command_type = ide_cmd_type_parser (&args); - if (args.command_type != IDE_DRIVE_TASK_NO_DATA) - rq.current_nr_sectors = rq.nr_sectors = (hobfile->sector_count << 8) | taskfile->sector_count; + if (task->tf_in_flags.all == 0) { + task->tf_in_flags.all = IDE_TASKFILE_STD_IN_FLAGS; + if ((id->command_set_2 & 0x0400) && + (id->cfs_enable_2 & 0x0400) && + (drive->addressing == 1)) { + task->tf_in_flags.all |= (IDE_HOB_STD_IN_FLAGS << 8); + } + } - rq.cmd = IDE_DRIVE_TASKFILE; - rq.buffer = buf; - rq.special = &args; - return ide_do_drive_cmd(drive, &rq, ide_wait); -} + /* ALL Command Block Executions SHALL clear nIEN, unless otherwise */ + if (IDE_CONTROL_REG) + OUT_BYTE(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */ + SELECT_MASK(HWIF(drive), drive, 0); -int ide_raw_taskfile (ide_drive_t *drive, ide_task_t *args, byte *buf) -{ - struct request rq; - ide_init_drive_taskfile(&rq); - rq.cmd = IDE_DRIVE_TASKFILE; - rq.buffer = buf; +#if DEBUG_TASKFILE + status = GET_STAT(); + if (status & 0x80) { + printk("flagged_taskfile -> Bad status. Status = %02x. wait 100 usec ...\n", status); + udelay(100); + status = GET_STAT(); + printk("flagged_taskfile -> Status = %02x\n", status); + } +#endif - if (args->command_type != IDE_DRIVE_TASK_NO_DATA) - rq.current_nr_sectors = rq.nr_sectors = (args->hobRegister[IDE_NSECTOR_OFFSET_HOB] << 8) | args->tfRegister[IDE_NSECTOR_OFFSET]; + if (task->tf_out_flags.b.data) { + unsigned short data = taskfile->data + (hobfile->data << 8); + OUT_WORD(data, IDE_DATA_REG); + } - rq.special = args; - return ide_do_drive_cmd(drive, &rq, ide_wait); -} + /* (ks) send hob registers first */ + if (task->tf_out_flags.b.nsector_hob) + OUT_BYTE(hobfile->sector_count, IDE_NSECTOR_REG); + if (task->tf_out_flags.b.sector_hob) + OUT_BYTE(hobfile->sector_number, IDE_SECTOR_REG); + if (task->tf_out_flags.b.lcyl_hob) + OUT_BYTE(hobfile->low_cylinder, IDE_LCYL_REG); + if (task->tf_out_flags.b.hcyl_hob) + OUT_BYTE(hobfile->high_cylinder, IDE_HCYL_REG); + + /* (ks) Send now the standard registers */ + if (task->tf_out_flags.b.error_feature) + OUT_BYTE(taskfile->feature, IDE_FEATURE_REG); + /* refers to number of sectors to transfer */ + if (task->tf_out_flags.b.nsector) + OUT_BYTE(taskfile->sector_count, IDE_NSECTOR_REG); + /* refers to sector offset or start sector */ + if (task->tf_out_flags.b.sector) + OUT_BYTE(taskfile->sector_number, IDE_SECTOR_REG); + if (task->tf_out_flags.b.lcyl) + OUT_BYTE(taskfile->low_cylinder, IDE_LCYL_REG); + if (task->tf_out_flags.b.hcyl) + OUT_BYTE(taskfile->high_cylinder, IDE_HCYL_REG); + + /* + * (ks) In the flagged taskfile approch, we will used all specified + * registers and the register value will not be changed. Except the + * select bit (master/slave) in the drive_head register. We must make + * sure that the desired drive is selected. + */ + OUT_BYTE(taskfile->device_head | drive->select.all, IDE_SELECT_REG); + switch(task->data_phase) { + case TASKFILE_OUT_DMAQ: + case TASKFILE_OUT_DMA: + HWIF(drive)->dmaproc(ide_dma_write, drive); + break; -#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG -char * ide_ioctl_verbose (unsigned int cmd) -{ - return("unknown"); + case TASKFILE_IN_DMAQ: + case TASKFILE_IN_DMA: + HWIF(drive)->dmaproc(ide_dma_read, drive); + break; + + default: + if (task->handler == NULL) + return ide_stopped; + + ide_set_handler (drive, task->handler, WAIT_WORSTCASE, NULL); + /* Issue the command */ + OUT_BYTE(taskfile->command, IDE_COMMAND_REG); + if (task->prehandler != NULL) + return task->prehandler(drive, HWGROUP(drive)->rq); + } + + return ide_started; } -char * ide_task_cmd_verbose (byte task) +ide_startstop_t flagged_task_no_data_intr (ide_drive_t *drive) { - return("unknown"); -} -#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */ + byte stat = GET_STAT(); -/* - * The taskfile glue table - * - * reqtask.data_phase reqtask.req_cmd - * args.command_type args.handler - * - * TASKFILE_P_OUT_DMAQ ?? ?? - * TASKFILE_P_IN_DMAQ ?? ?? - * TASKFILE_P_OUT_DMA ?? ?? - * TASKFILE_P_IN_DMA ?? ?? - * TASKFILE_P_OUT ?? ?? - * TASKFILE_P_IN ?? ?? - * - * TASKFILE_OUT_DMAQ IDE_DRIVE_TASK_RAW_WRITE NULL - * TASKFILE_IN_DMAQ IDE_DRIVE_TASK_IN NULL - * - * TASKFILE_OUT_DMA IDE_DRIVE_TASK_RAW_WRITE NULL - * TASKFILE_IN_DMA IDE_DRIVE_TASK_IN NULL - * - * TASKFILE_IN_OUT ?? ?? - * - * TASKFILE_MULTI_OUT IDE_DRIVE_TASK_RAW_WRITE task_mulout_intr - * TASKFILE_MULTI_IN IDE_DRIVE_TASK_IN task_mulin_intr - * - * TASKFILE_OUT IDE_DRIVE_TASK_RAW_WRITE task_out_intr - * TASKFILE_OUT IDE_DRIVE_TASK_OUT task_out_intr - * - * TASKFILE_IN IDE_DRIVE_TASK_IN task_in_intr - * TASKFILE_NO_DATA IDE_DRIVE_TASK_NO_DATA task_no_data_intr - * - * IDE_DRIVE_TASK_SET_XFER task_no_data_intr - * IDE_DRIVE_TASK_INVALID - * + local_irq_enable(); + + if (!OK_STAT(stat, READY_STAT, BAD_STAT)) { + if (stat & ERR_STAT) { + return DRIVER(drive)->error(drive, "flagged_task_no_data_intr", stat); + } + /* + * (ks) Unexpected ATA data phase detected. + * This should not happen. But, it can ! + * I am not sure, which function is best to clean up + * this situation. I choose: ide_error(...) + */ + return DRIVER(drive)->error(drive, "flagged_task_no_data_intr (unexpected phase)", stat); + } + + ide_end_drive_cmd (drive, stat, GET_ERR()); + + return ide_stopped; +} + +/* + * Handler for command with PIO data-in phase */ +ide_startstop_t flagged_task_in_intr (ide_drive_t *drive) +{ + byte stat = GET_STAT(); + struct request *rq = HWGROUP(drive)->rq; + char *pBuf = NULL; + int retries = 5; + + if (rq->current_nr_sectors == 0) + return DRIVER(drive)->error(drive, "flagged_task_in_intr (no data requested)", stat); + + if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) { + if (stat & ERR_STAT) { + return DRIVER(drive)->error(drive, "flagged_task_in_intr", stat); + } + /* + * (ks) Unexpected ATA data phase detected. + * This should not happen. But, it can ! + * I am not sure, which function is best to clean up + * this situation. I choose: ide_error(...) + */ + return DRIVER(drive)->error(drive, "flagged_task_in_intr (unexpected data phase)", stat); + } + + pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); + DTF("Read - rq->current_nr_sectors: %d, status: %02x\n", (int) rq->current_nr_sectors, stat); + + taskfile_input_data(drive, pBuf, SECTOR_WORDS); + + if (--rq->current_nr_sectors != 0) { + /* + * (ks) We don't know which command was executed. + * So, we wait the 'WORSTCASE' value. + */ + ide_set_handler(drive, &flagged_task_in_intr, WAIT_WORSTCASE, NULL); + return ide_started; + } + /* + * (ks) Last sector was transfered, wait until drive is ready. + * This can take up to 10 usec. We willl wait max 50 us. + */ + while (((stat = GET_STAT()) & BUSY_STAT) && retries--) + udelay(10); + ide_end_drive_cmd (drive, stat, GET_ERR()); + + return ide_stopped; +} + +ide_startstop_t flagged_task_mulin_intr (ide_drive_t *drive) +{ + byte stat = GET_STAT(); + struct request *rq = HWGROUP(drive)->rq; + char *pBuf = NULL; + int retries = 5; + unsigned int msect, nsect; + + if (rq->current_nr_sectors == 0) + return DRIVER(drive)->error(drive, "flagged_task_mulin_intr (no data requested)", stat); + + msect = drive->mult_count; + if (msect == 0) + return DRIVER(drive)->error(drive, "flagged_task_mulin_intr (multimode not set)", stat); + + if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) { + if (stat & ERR_STAT) { + return DRIVER(drive)->error(drive, "flagged_task_mulin_intr", stat); + } + /* + * (ks) Unexpected ATA data phase detected. + * This should not happen. But, it can ! + * I am not sure, which function is best to clean up + * this situation. I choose: ide_error(...) + */ + return DRIVER(drive)->error(drive, "flagged_task_mulin_intr (unexpected data phase)", stat); + } + + nsect = (rq->current_nr_sectors > msect) ? msect : rq->current_nr_sectors; + pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); + + DTF("Multiread: %p, nsect: %d , rq->current_nr_sectors: %ld\n", + pBuf, nsect, rq->current_nr_sectors); + + taskfile_input_data(drive, pBuf, nsect * SECTOR_WORDS); + + rq->current_nr_sectors -= nsect; + if (rq->current_nr_sectors != 0) { + /* + * (ks) We don't know which command was executed. + * So, we wait the 'WORSTCASE' value. + */ + ide_set_handler(drive, &flagged_task_mulin_intr, WAIT_WORSTCASE, NULL); + return ide_started; + } + + /* + * (ks) Last sector was transfered, wait until drive is ready. + * This can take up to 10 usec. We willl wait max 50 us. + */ + while (((stat = GET_STAT()) & BUSY_STAT) && retries--) + udelay(10); + ide_end_drive_cmd (drive, stat, GET_ERR()); + + return ide_stopped; +} + +/* + * Pre handler for command with PIO data-out phase + */ +ide_startstop_t flagged_pre_task_out_intr (ide_drive_t *drive, struct request *rq) +{ + byte stat = GET_STAT(); + ide_startstop_t startstop; + + if (!rq->current_nr_sectors) { + return DRIVER(drive)->error(drive, "flagged_pre_task_out_intr (write data not specified)", stat); + } + + if (ide_wait_stat(&startstop, drive, DATA_READY, + BAD_W_STAT, WAIT_DRQ)) { + printk(KERN_ERR "%s: No DRQ bit after issuing write command.\n", drive->name); + return startstop; + } + + taskfile_output_data(drive, rq->buffer, SECTOR_WORDS); + --rq->current_nr_sectors; + + return ide_started; +} + +ide_startstop_t flagged_task_out_intr (ide_drive_t *drive) +{ + byte stat = GET_STAT(); + struct request *rq = HWGROUP(drive)->rq; + char *pBuf = NULL; + + if (!OK_STAT(stat, DRIVE_READY, BAD_W_STAT)) + return DRIVER(drive)->error(drive, "flagged_task_out_intr", stat); + + if (!rq->current_nr_sectors) { + ide_end_drive_cmd (drive, stat, GET_ERR()); + return ide_stopped; + } + + if (!OK_STAT(stat, DATA_READY, BAD_W_STAT)) { + /* + * (ks) Unexpected ATA data phase detected. + * This should not happen. But, it can ! + * I am not sure, which function is best to clean up + * this situation. I choose: ide_error(...) + */ + return DRIVER(drive)->error(drive, "flagged_task_out_intr (unexpected data phase)", stat); + } + + pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); + DTF("Write - rq->current_nr_sectors: %d, status: %02x\n", + (int) rq->current_nr_sectors, stat); + + taskfile_output_data(drive, pBuf, SECTOR_WORDS); + --rq->current_nr_sectors; + + /* + * (ks) We don't know which command was executed. + * So, we wait the 'WORSTCASE' value. + */ + ide_set_handler(drive, &flagged_task_out_intr, WAIT_WORSTCASE, NULL); + + return ide_started; +} + +ide_startstop_t flagged_pre_task_mulout_intr (ide_drive_t *drive, struct request *rq) +{ + byte stat = GET_STAT(); + char *pBuf = NULL; + ide_startstop_t startstop; + unsigned int msect, nsect; + + if (!rq->current_nr_sectors) + return DRIVER(drive)->error(drive, "flagged_pre_task_mulout_intr (write data not specified)", stat); + + msect = drive->mult_count; + if (msect == 0) + return DRIVER(drive)->error(drive, "flagged_pre_task_mulout_intr (multimode not set)", stat); + + if (ide_wait_stat(&startstop, drive, DATA_READY, + BAD_W_STAT, WAIT_DRQ)) { + printk(KERN_ERR "%s: No DRQ bit after issuing write command.\n", drive->name); + return startstop; + } + + nsect = (rq->current_nr_sectors > msect) ? msect : rq->current_nr_sectors; + pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); + DTF("Multiwrite: %p, nsect: %d , rq->current_nr_sectors: %ld\n", + pBuf, nsect, rq->current_nr_sectors); + + taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS); + + rq->current_nr_sectors -= nsect; + + return ide_started; +} + +ide_startstop_t flagged_task_mulout_intr (ide_drive_t *drive) +{ + byte stat = GET_STAT(); + struct request *rq = HWGROUP(drive)->rq; + char *pBuf = NULL; + unsigned int msect, nsect; + + msect = drive->mult_count; + if (msect == 0) + return DRIVER(drive)->error(drive, "flagged_task_mulout_intr (multimode not set)", stat); + + if (!OK_STAT(stat, DRIVE_READY, BAD_W_STAT)) + return DRIVER(drive)->error(drive, "flagged_task_mulout_intr", stat); + + if (!rq->current_nr_sectors) { + ide_end_drive_cmd (drive, stat, GET_ERR()); + return ide_stopped; + } + + if (!OK_STAT(stat, DATA_READY, BAD_W_STAT)) { + /* + * (ks) Unexpected ATA data phase detected. + * This should not happen. But, it can ! + * I am not sure, which function is best to clean up + * this situation. I choose: ide_error(...) + */ + return DRIVER(drive)->error(drive, "flagged_task_mulout_intr (unexpected data phase)", stat); + } + + nsect = (rq->current_nr_sectors > msect) ? msect : rq->current_nr_sectors; + pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); + DTF("Multiwrite: %p, nsect: %d , rq->current_nr_sectors: %ld\n", + pBuf, nsect, rq->current_nr_sectors); + + taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS); + rq->current_nr_sectors -= nsect; + + /* + * (ks) We don't know which command was executed. + * So, we wait the 'WORSTCASE' value. + */ + ide_set_handler(drive, &flagged_task_mulout_intr, WAIT_WORSTCASE, NULL); + + return ide_started; +} + +/* + * This function is intended to be used prior to invoking ide_do_drive_cmd(). + */ +void ide_init_drive_taskfile (struct request *rq) +{ + memset(rq, 0, sizeof(*rq)); + rq->cmd = IDE_DRIVE_TASK_NO_DATA; +} + +int ide_diag_taskfile (ide_drive_t *drive, ide_task_t *args, unsigned long data_size, byte *buf) +{ + struct request rq; + + ide_init_drive_taskfile(&rq); + rq.cmd = IDE_DRIVE_TASKFILE; + rq.buffer = buf; + + /* + * (ks) We transfer currently only whole sectors. + * This is suffient for now. But, it would be great, + * if we would find a solution to transfer any size. + * To support special commands like READ LONG. + */ + if (args->command_type != IDE_DRIVE_TASK_NO_DATA) { + if (data_size == 0) + rq.current_nr_sectors = rq.nr_sectors = (args->hobRegister[IDE_NSECTOR_OFFSET_HOB] << 8) | args->tfRegister[IDE_NSECTOR_OFFSET]; + /* rq.hard_cur_sectors */ + else + rq.current_nr_sectors = rq.nr_sectors = data_size / SECTOR_SIZE; + /* rq.hard_cur_sectors */ + } + + if (args->tf_out_flags.all == 0) { + /* + * clean up kernel settings for driver sanity, regardless. + * except for discrete diag services. + */ + args->posthandler = ide_post_handler_parser( + (struct hd_drive_task_hdr *) args->tfRegister, + (struct hd_drive_hob_hdr *) args->hobRegister); + + } + rq.special = args; + return ide_do_drive_cmd(drive, &rq, ide_wait); +} + +int ide_raw_taskfile (ide_drive_t *drive, ide_task_t *args, byte *buf) +{ + return ide_diag_taskfile(drive, args, 0, buf); +} + +#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG +char * ide_ioctl_verbose (unsigned int cmd) +{ + return("unknown"); +} + +char * ide_task_cmd_verbose (byte task) +{ + return("unknown"); +} +#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */ #define MAX_DMA (256*SECTOR_WORDS) @@ -1374,7 +1984,6 @@ { ide_task_request_t *req_task; ide_task_t args; - byte *outbuf = NULL; byte *inbuf = NULL; task_ioreg_t *argsptr = args.tfRegister; @@ -1383,6 +1992,9 @@ int tasksize = sizeof(struct ide_task_request_s); int taskin = 0; int taskout = 0; + byte io_32bit = drive->io_32bit; + +// printk("IDE Taskfile ...\n"); req_task = kmalloc(tasksize, GFP_KERNEL); if (req_task == NULL) return -ENOMEM; @@ -1423,8 +2035,7 @@ } } - memset(argsptr, 0, HDIO_DRIVE_TASK_HDR_SIZE); - memset(hobsptr, 0, HDIO_DRIVE_HOB_HDR_SIZE); + memset (&args, 0, sizeof (ide_task_t) ); memcpy(argsptr, req_task->io_ports, HDIO_DRIVE_TASK_HDR_SIZE); memcpy(hobsptr, req_task->hob_ports, HDIO_DRIVE_HOB_HDR_SIZE); @@ -1440,64 +2051,61 @@ ide_task_cmd_verbose(args.tfRegister[IDE_COMMAND_OFFSET])); #endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */ + drive->io_32bit = 0; switch(req_task->data_phase) { case TASKFILE_OUT_DMAQ: case TASKFILE_OUT_DMA: - args.prehandler = NULL; - args.handler = NULL; - args.posthandler = NULL; - err = ide_raw_taskfile(drive, &args, outbuf); + err = ide_diag_taskfile(drive, &args, taskout, outbuf); break; case TASKFILE_IN_DMAQ: case TASKFILE_IN_DMA: - args.prehandler = NULL; - args.handler = NULL; - args.posthandler = NULL; - err = ide_raw_taskfile(drive, &args, inbuf); + err = ide_diag_taskfile(drive, &args, taskin, inbuf); break; case TASKFILE_IN_OUT: #if 0 args.prehandler = &pre_task_out_intr; args.handler = &task_out_intr; args.posthandler = NULL; - err = ide_raw_taskfile(drive, &args, outbuf); + err = ide_diag_taskfile(drive, &args, taskout, outbuf); args.prehandler = NULL; args.handler = &task_in_intr; args.posthandler = NULL; - err = ide_raw_taskfile(drive, &args, inbuf); + err = ide_diag_taskfile(drive, &args, taskin, inbuf); break; #else err = -EFAULT; goto abort; #endif case TASKFILE_MULTI_OUT: - if (drive->mult_count) { - args.prehandler = &pre_task_out_intr; - args.handler = &task_mulout_intr; - args.posthandler = NULL; - err = ide_raw_taskfile(drive, &args, outbuf); - } else { + if (!drive->mult_count) { /* (hs): give up if multcount is not set */ printk("%s: %s Multimode Write " \ "multcount is not set\n", - drive->name, __FUNCTION__); + drive->name, __FUNCTION__); err = -EPERM; goto abort; } + if (args.tf_out_flags.all != 0) { + args.prehandler = &flagged_pre_task_mulout_intr; + args.handler = &flagged_task_mulout_intr; + } else { + args.prehandler = &pre_task_mulout_intr; + args.handler = &task_mulout_intr; + } + err = ide_diag_taskfile(drive, &args, taskout, outbuf); break; case TASKFILE_OUT: - args.prehandler = &pre_task_out_intr; - args.handler = &task_out_intr; - args.posthandler = NULL; - err = ide_raw_taskfile(drive, &args, outbuf); + if (args.tf_out_flags.all != 0) { + args.prehandler = &flagged_pre_task_out_intr; + args.handler = &flagged_task_out_intr; + } else { + args.prehandler = &pre_task_out_intr; + args.handler = &task_out_intr; + } + err = ide_diag_taskfile(drive, &args, taskout, outbuf); break; case TASKFILE_MULTI_IN: - if (drive->mult_count) { - args.prehandler = NULL; - args.handler = &task_mulin_intr; - args.posthandler = NULL; - err = ide_raw_taskfile(drive, &args, inbuf); - } else { + if (!drive->mult_count) { /* (hs): give up if multcount is not set */ printk("%s: %s Multimode Read failure " \ "multcount is not set\n", @@ -1505,23 +2113,30 @@ err = -EPERM; goto abort; } + if (args.tf_out_flags.all != 0) { + args.handler = &flagged_task_mulin_intr; + } else { + args.handler = &task_mulin_intr; + } + err = ide_diag_taskfile(drive, &args, taskin, inbuf); break; case TASKFILE_IN: - args.prehandler = NULL; - args.handler = &task_in_intr; - args.posthandler = NULL; - err = ide_raw_taskfile(drive, &args, inbuf); + if (args.tf_out_flags.all != 0) { + args.handler = &flagged_task_in_intr; + } else { + args.handler = &task_in_intr; + } + err = ide_diag_taskfile(drive, &args, taskin, inbuf); break; case TASKFILE_NO_DATA: - args.prehandler = NULL; - args.handler = &task_no_data_intr; - args.posthandler = NULL; - err = ide_raw_taskfile(drive, &args, NULL); + if (args.tf_out_flags.all != 0) { + args.handler = &flagged_task_no_data_intr; + } else { + args.handler = &task_no_data_intr; + } + err = ide_diag_taskfile(drive, &args, 0, NULL); break; default: - args.prehandler = NULL; - args.handler = NULL; - args.posthandler = NULL; err = -EFAULT; goto abort; } @@ -1555,15 +2170,175 @@ kfree(outbuf); if (inbuf != NULL) kfree(inbuf); + +// printk("IDE Taskfile ioctl ended. rc = %i\n", err); + + drive->io_32bit = io_32bit; + + return err; +} + +int ide_ata66_check (ide_drive_t *drive, ide_task_t *args); +int set_transfer(ide_drive_t *drive, ide_task_t *args); + +/* + * FIXME : this needs to map into at taskfile. + */ +int ide_cmd_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ +#if 1 + int err = 0; + byte args[4], *argbuf = args; + byte xfer_rate = 0; + int argsize = 4; + ide_task_t tfargs; + + if (NULL == (void *) arg) { + struct request rq; + ide_init_drive_cmd(&rq); + return ide_do_drive_cmd(drive, &rq, ide_wait); + } + + if (copy_from_user(args, (void *)arg, 4)) + return -EFAULT; + + memset(&tfargs, 0, sizeof(ide_task_t)); + tfargs.tfRegister[IDE_FEATURE_OFFSET] = args[2]; + tfargs.tfRegister[IDE_NSECTOR_OFFSET] = args[3]; + tfargs.tfRegister[IDE_SECTOR_OFFSET] = args[1]; + tfargs.tfRegister[IDE_LCYL_OFFSET] = 0x00; + tfargs.tfRegister[IDE_HCYL_OFFSET] = 0x00; + tfargs.tfRegister[IDE_SELECT_OFFSET] = 0x00; + tfargs.tfRegister[IDE_COMMAND_OFFSET] = args[0]; + + if (args[3]) { + argsize = 4 + (SECTOR_WORDS * 4 * args[3]); + argbuf = kmalloc(argsize, GFP_KERNEL); + if (argbuf == NULL) + return -ENOMEM; + memcpy(argbuf, args, 4); + } + if (set_transfer(drive, &tfargs)) { + xfer_rate = args[1]; + if (ide_ata66_check(drive, &tfargs)) + goto abort; + } + + err = ide_wait_cmd(drive, args[0], args[1], args[2], args[3], argbuf); + + if (!err && xfer_rate) { + /* active-retuning-calls future */ + if ((HWIF(drive)->speedproc) != NULL) + HWIF(drive)->speedproc(drive, xfer_rate); + ide_driveid_update(drive); + } +abort: + if (copy_to_user((void *)arg, argbuf, argsize)) + err = -EFAULT; + if (argsize > 4) + kfree(argbuf); + return err; + +#else + + int err = 0; + byte args[4], *argbuf = args; + byte xfer_rate = 0; + int argsize = 0; + ide_task_t tfargs; + + if (NULL == (void *) arg) { + struct request rq; + ide_init_drive_cmd(&rq); + return ide_do_drive_cmd(drive, &rq, ide_wait); + } + + if (copy_from_user(args, (void *)arg, 4)) + return -EFAULT; + + memset(&tfargs, 0, sizeof(ide_task_t)); + tfargs.tfRegister[IDE_FEATURE_OFFSET] = args[2]; + tfargs.tfRegister[IDE_NSECTOR_OFFSET] = args[3]; + tfargs.tfRegister[IDE_SECTOR_OFFSET] = args[1]; + tfargs.tfRegister[IDE_LCYL_OFFSET] = 0x00; + tfargs.tfRegister[IDE_HCYL_OFFSET] = 0x00; + tfargs.tfRegister[IDE_SELECT_OFFSET] = 0x00; + tfargs.tfRegister[IDE_COMMAND_OFFSET] = args[0]; + + if (args[3]) { + argsize = (SECTOR_WORDS * 4 * args[3]); + argbuf = kmalloc(argsize, GFP_KERNEL); + if (argbuf == NULL) + return -ENOMEM; + } + + if (set_transfer(drive, &tfargs)) { + xfer_rate = args[1]; + if (ide_ata66_check(drive, &tfargs)) + goto abort; + } + + tfargs.command_type = ide_cmd_type_parser(&tfargs); + err = ide_raw_taskfile(drive, &tfargs, argbuf); + + if (!err && xfer_rate) { + /* active-retuning-calls future */ + if ((HWIF(drive)->speedproc) != NULL) + HWIF(drive)->speedproc(drive, xfer_rate); + ide_driveid_update(drive); + } +abort: + + args[0] = tfargs.tfRegister[IDE_COMMAND_OFFSET]; + args[1] = tfargs.tfRegister[IDE_FEATURE_OFFSET]; + args[2] = tfargs.tfRegister[IDE_NSECTOR_OFFSET]; + args[3] = 0; + + if (copy_to_user((void *)arg, argbuf, 4)) + err = -EFAULT; + if (argbuf != NULL) { + if (copy_to_user((void *)arg, argbuf + 4, argsize)) + err = -EFAULT; + kfree(argbuf); + } + return err; + +#endif + +} + +/* + * FIXME : this needs to map into at taskfile. + */ +int ide_task_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + int err = 0; + byte args[7], *argbuf = args; + int argsize = 7; + + if (copy_from_user(args, (void *)arg, 7)) + return -EFAULT; + err = ide_wait_cmd_task(drive, argbuf); + if (copy_to_user((void *)arg, argbuf, argsize)) + err = -EFAULT; return err; } +EXPORT_SYMBOL(drive_is_ready); +EXPORT_SYMBOL(wait_for_ready); + EXPORT_SYMBOL(task_read_24); -EXPORT_SYMBOL(do_rw_taskfile); -EXPORT_SYMBOL(do_taskfile); -// EXPORT_SYMBOL(flagged_taskfile); +EXPORT_SYMBOL(ata_input_data); +EXPORT_SYMBOL(ata_output_data); +EXPORT_SYMBOL(atapi_input_bytes); +EXPORT_SYMBOL(atapi_output_bytes); +EXPORT_SYMBOL(taskfile_input_data); +EXPORT_SYMBOL(taskfile_output_data); -//EXPORT_SYMBOL(ide_end_taskfile); +EXPORT_SYMBOL(ide_wait_stat); +EXPORT_SYMBOL(do_rw_taskfile); +EXPORT_SYMBOL(flagged_taskfile); +EXPORT_SYMBOL(ide_end_taskfile); EXPORT_SYMBOL(set_multmode_intr); EXPORT_SYMBOL(set_geometry_intr); @@ -1574,15 +2349,343 @@ EXPORT_SYMBOL(task_mulin_intr); EXPORT_SYMBOL(pre_task_out_intr); EXPORT_SYMBOL(task_out_intr); +EXPORT_SYMBOL(pre_task_mulout_intr); EXPORT_SYMBOL(task_mulout_intr); EXPORT_SYMBOL(ide_init_drive_taskfile); -EXPORT_SYMBOL(ide_wait_taskfile); EXPORT_SYMBOL(ide_raw_taskfile); EXPORT_SYMBOL(ide_pre_handler_parser); EXPORT_SYMBOL(ide_handler_parser); +EXPORT_SYMBOL(ide_post_handler_parser); EXPORT_SYMBOL(ide_cmd_type_parser); EXPORT_SYMBOL(ide_taskfile_ioctl); +EXPORT_SYMBOL(ide_cmd_ioctl); +EXPORT_SYMBOL(ide_task_ioctl); + +/* + * Beginning of Taskfile OPCODE Library and feature sets. + */ + +/* + * All hosts that use the 80c ribbon must use! + * The name is derived from upper byte of word 93 and the 80c ribbon. + */ +byte eighty_ninty_three (ide_drive_t *drive) +{ +#if 0 + if (!HWIF(drive)->udma_four) + return 0; + + if (drive->id->major_rev_num) { + int hssbd = 0; + int i; + /* + * Determime highest Supported SPEC + */ + for (i=1; i<=15; i++) + if (drive->id->major_rev_num & (1<id->hw_config & 0x4000) && +#endif /* CONFIG_IDEDMA_IVB */ + (drive->id->hw_config & 0x6000)) ? 1 : 0); + +#else + + return ((byte) ((HWIF(drive)->udma_four) && +#ifndef CONFIG_IDEDMA_IVB + (drive->id->hw_config & 0x4000) && +#endif /* CONFIG_IDEDMA_IVB */ + (drive->id->hw_config & 0x6000)) ? 1 : 0); +#endif +} + +int ide_ata66_check (ide_drive_t *drive, ide_task_t *args) +{ + if (!HWIF(drive)->udma_four) { + printk("%s: Speed warnings UDMA 3/4/5 is not functional.\n", + HWIF(drive)->name); + return 1; + } + if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) && + (args->tfRegister[IDE_SECTOR_OFFSET] > XFER_UDMA_2) && + (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER)) { +#ifndef CONFIG_IDEDMA_IVB + if ((drive->id->hw_config & 0x6000) == 0) { +#else /* !CONFIG_IDEDMA_IVB */ + if (((drive->id->hw_config & 0x2000) == 0) || + ((drive->id->hw_config & 0x4000) == 0)) { +#endif /* CONFIG_IDEDMA_IVB */ + printk("%s: Speed warnings UDMA 3/4/5 is not functional.\n", drive->name); + return 1; + } + } + return 0; +} + +/* + * Backside of HDIO_DRIVE_CMD call of SETFEATURES_XFER. + * 1 : Safe to update drive->id DMA registers. + * 0 : OOPs not allowed. + */ +int set_transfer (ide_drive_t *drive, ide_task_t *args) +{ + if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) && + (args->tfRegister[IDE_SECTOR_OFFSET] >= XFER_SW_DMA_0) && + (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER) && + (drive->id->dma_ultra || + drive->id->dma_mword || + drive->id->dma_1word)) + return 1; + + return 0; +} + +byte ide_auto_reduce_xfer (ide_drive_t *drive) +{ + if (!drive->crc_count) + return drive->current_speed; + drive->crc_count = 0; + + switch(drive->current_speed) { + case XFER_UDMA_7: return XFER_UDMA_6; + case XFER_UDMA_6: return XFER_UDMA_5; + case XFER_UDMA_5: return XFER_UDMA_4; + case XFER_UDMA_4: return XFER_UDMA_3; + case XFER_UDMA_3: return XFER_UDMA_2; + case XFER_UDMA_2: return XFER_UDMA_1; + case XFER_UDMA_1: return XFER_UDMA_0; + /* + * OOPS we do not goto non Ultra DMA modes + * without iCRC's available we force + * the system to PIO and make the user + * invoke the ATA-1 ATA-2 DMA modes. + */ + case XFER_UDMA_0: + default: return XFER_PIO_4; + } +} + +int taskfile_lib_get_identify (ide_drive_t *drive, byte *buf) +{ + ide_task_t args; + memset(&args, 0, sizeof(ide_task_t)); + args.tfRegister[IDE_NSECTOR_OFFSET] = 0x01; + if (drive->media == ide_disk) + args.tfRegister[IDE_COMMAND_OFFSET] = WIN_IDENTIFY; + else + args.tfRegister[IDE_COMMAND_OFFSET] = WIN_PIDENTIFY; + args.command_type = ide_cmd_type_parser(&args); + return ide_raw_taskfile(drive, &args, buf); +} + +/* + * Update the + */ +int ide_driveid_update (ide_drive_t *drive) +{ +#if 0 + struct hd_driveid *id; + + id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC); + if (!id) + return 0; + + taskfile_lib_get_identify(drive, (char *)&id); + + ide_fix_driveid(id); + if (id) { + drive->id->dma_ultra = id->dma_ultra; + drive->id->dma_mword = id->dma_mword; + drive->id->dma_1word = id->dma_1word; + /* anything more ? */ + kfree(id); + } + return 1; +#else + /* + * Re-read drive->id for possible DMA mode + * change (copied from ide-probe.c) + */ + struct hd_driveid *id; + unsigned long timeout, flags; + + SELECT_MASK(HWIF(drive), drive, 1); + if (IDE_CONTROL_REG) + OUT_BYTE(drive->ctl,IDE_CONTROL_REG); + ide_delay_50ms(); + OUT_BYTE(WIN_IDENTIFY, IDE_COMMAND_REG); + timeout = jiffies + WAIT_WORSTCASE; + do { + if (time_after(jiffies, timeout)) { + SELECT_MASK(HWIF(drive), drive, 0); + return 0; /* drive timed-out */ + } + ide_delay_50ms(); /* give drive a breather */ + } while (IN_BYTE(IDE_ALTSTATUS_REG) & BUSY_STAT); + ide_delay_50ms(); /* wait for IRQ and DRQ_STAT */ + if (!OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)) { + SELECT_MASK(HWIF(drive), drive, 0); + printk("%s: CHECK for good STATUS\n", drive->name); + return 0; + } + local_irq_save(flags); + SELECT_MASK(HWIF(drive), drive, 0); + id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC); + if (!id) { + local_irq_restore(flags); + return 0; + } + ata_input_data(drive, id, SECTOR_WORDS); + (void) GET_STAT(); /* clear drive IRQ */ + local_irq_enable(); + local_irq_restore(flags); + ide_fix_driveid(id); + if (id) { + drive->id->dma_ultra = id->dma_ultra; + drive->id->dma_mword = id->dma_mword; + drive->id->dma_1word = id->dma_1word; + /* anything more ? */ + kfree(id); + } + + return 1; +#endif +} + + +/* + * Similar to ide_wait_stat(), except it never calls ide_error internally. + * This is a kludge to handle the new ide_config_drive_speed() function, + * and should not otherwise be used anywhere. Eventually, the tuneproc's + * should be updated to return ide_startstop_t, in which case we can get + * rid of this abomination again. :) -ml + * + * It is gone.......... + * + * const char *msg == consider adding for verbose errors. + */ +int ide_config_drive_speed (ide_drive_t *drive, byte speed) +{ + ide_hwif_t *hwif = HWIF(drive); + int i, error = 1; + byte stat; + +#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI) + hwif->dmaproc(ide_dma_host_off, drive); +#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */ + + /* + * Don't use ide_wait_cmd here - it will + * attempt to set_geometry and recalibrate, + * but for some reason these don't work at + * this point (lost interrupt). + */ + /* + * Select the drive, and issue the SETFEATURES command + */ + disable_irq(hwif->irq); /* disable_irq_nosync ?? */ + udelay(1); + SELECT_DRIVE(HWIF(drive), drive); + SELECT_MASK(HWIF(drive), drive, 0); + udelay(1); + if (IDE_CONTROL_REG) + OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG); + OUT_BYTE(speed, IDE_NSECTOR_REG); + OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG); + OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG); + if ((IDE_CONTROL_REG) && (drive->quirk_list == 2)) + OUT_BYTE(drive->ctl, IDE_CONTROL_REG); + udelay(1); + /* + * Wait for drive to become non-BUSY + */ + if ((stat = GET_STAT()) & BUSY_STAT) { + unsigned long flags, timeout; + local_irq_set(flags); + timeout = jiffies + WAIT_CMD; + while ((stat = GET_STAT()) & BUSY_STAT) { + if (time_after(jiffies, timeout)) + break; + } + local_irq_restore(flags); + } + + /* + * Allow status to settle, then read it again. + * A few rare drives vastly violate the 400ns spec here, + * so we'll wait up to 10usec for a "good" status + * rather than expensively fail things immediately. + * This fix courtesy of Matthew Faupel & Niccolo Rigacci. + */ + for (i = 0; i < 10; i++) { + udelay(1); + if (OK_STAT((stat = GET_STAT()), DRIVE_READY, BUSY_STAT|DRQ_STAT|ERR_STAT)) { + error = 0; + break; + } + } + + SELECT_MASK(HWIF(drive), drive, 0); + + enable_irq(hwif->irq); + + if (error) { + (void) ide_dump_status(drive, "set_drive_speed_status", stat); + return error; + } + + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_1word &= ~0x0F00; + +#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI) + if (speed >= XFER_SW_DMA_0) + hwif->dmaproc(ide_dma_host_on, drive); +#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */ + + switch(speed) { + case XFER_UDMA_7: drive->id->dma_ultra |= 0x8080; break; + case XFER_UDMA_6: drive->id->dma_ultra |= 0x4040; break; + case XFER_UDMA_5: drive->id->dma_ultra |= 0x2020; break; + case XFER_UDMA_4: drive->id->dma_ultra |= 0x1010; break; + case XFER_UDMA_3: drive->id->dma_ultra |= 0x0808; break; + case XFER_UDMA_2: drive->id->dma_ultra |= 0x0404; break; + case XFER_UDMA_1: drive->id->dma_ultra |= 0x0202; break; + case XFER_UDMA_0: drive->id->dma_ultra |= 0x0101; break; + case XFER_MW_DMA_2: drive->id->dma_mword |= 0x0404; break; + case XFER_MW_DMA_1: drive->id->dma_mword |= 0x0202; break; + case XFER_MW_DMA_0: drive->id->dma_mword |= 0x0101; break; + case XFER_SW_DMA_2: drive->id->dma_1word |= 0x0404; break; + case XFER_SW_DMA_1: drive->id->dma_1word |= 0x0202; break; + case XFER_SW_DMA_0: drive->id->dma_1word |= 0x0101; break; + default: break; + } + if (!drive->init_speed) + drive->init_speed = speed; + drive->current_speed = speed; + return error; +} + +EXPORT_SYMBOL(eighty_ninty_three); +EXPORT_SYMBOL(ide_auto_reduce_xfer); +EXPORT_SYMBOL(set_transfer); +EXPORT_SYMBOL(taskfile_lib_get_identify); +EXPORT_SYMBOL(ide_driveid_update); +EXPORT_SYMBOL(ide_config_drive_speed); #ifdef CONFIG_PKT_TASK_IOCTL diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/it8172.c linux.19rc3-ac4/drivers/ide/it8172.c --- linux.19rc3/drivers/ide/it8172.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/it8172.c 2002-07-29 13:58:40.000000000 +0100 @@ -46,106 +46,134 @@ /* * Prototypes */ +static byte it8172_ratemask (ide_drive_t *drive); +static byte it8172_ratefilter (ide_drive_t *drive, byte speed); static void it8172_tune_drive (ide_drive_t *drive, byte pio); -#if defined(CONFIG_BLK_DEV_IDEDMA) && defined(CONFIG_IT8172_TUNING) static byte it8172_dma_2_pio (byte xfer_rate); -static int it8172_tune_chipset (ide_drive_t *drive, byte speed); +static int it8172_tune_chipset (ide_drive_t *drive, byte xferspeed); +#ifdef CONFIG_BLK_DEV_IDEDMA static int it8172_config_chipset_for_dma (ide_drive_t *drive); static int it8172_dmaproc(ide_dma_action_t func, ide_drive_t *drive); #endif unsigned int __init pci_init_it8172 (struct pci_dev *dev, const char *name); void __init ide_init_it8172 (ide_hwif_t *hwif); +static byte it8172_ratemask (ide_drive_t *drive) +{ + byte mode = 0x00; +#if 1 + mode |= 0x01; +#endif + return (mode &= ~0xF8); +} -static void it8172_tune_drive (ide_drive_t *drive, byte pio) +static byte it8172_ratefilter (ide_drive_t *drive, byte speed) { - unsigned long flags; - u16 drive_enables; - u32 drive_timing; - int is_slave = (&HWIF(drive)->drives[1] == drive); - - pio = ide_get_best_pio_mode(drive, pio, 4, NULL); - pci_read_config_word(HWIF(drive)->pci_dev, 0x40, &drive_enables); - pci_read_config_dword(HWIF(drive)->pci_dev, 0x44, &drive_timing); +#ifdef CONFIG_BLK_DEV_IDEDMA + byte mode = it8172_ratemask(drive); - /* - * FIX! The DIOR/DIOW pulse width and recovery times in port 0x44 - * are being left at the default values of 8 PCI clocks (242 nsec - * for a 33 MHz clock). These can be safely shortened at higher - * PIO modes. The DIOR/DIOW pulse width and recovery times only - * apply to PIO modes, not to the DMA modes. - */ - - /* - * Enable port 0x44. The IT8172G spec is confused; it calls - * this register the "Slave IDE Timing Register", but in fact, - * it controls timing for both master and slave drives. - */ - drive_enables |= 0x4000; + switch(mode) { + case 0x04: // while (speed > XFER_UDMA_6) speed--; break; + case 0x03: // while (speed > XFER_UDMA_5) speed--; break; + case 0x02: while (speed > XFER_UDMA_4) speed--; break; + case 0x01: while (speed > XFER_UDMA_2) speed--; break; + case 0x00: + default: while (speed > XFER_MW_DMA_2) speed--; break; + break; + } +#else + while (speed > XFER_PIO_4) speed--; +#endif /* CONFIG_BLK_DEV_IDEDMA */ +// printk("%s: mode == %02x speed == %02x\n", drive->name, mode, speed); + return speed; +} + +static void it8172_tune_drive (ide_drive_t *drive, byte pio) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + int is_slave = (hwif->drives[1] == drive); + unsigned long flags; + u16 drive_enables; + u32 drive_timing; + + pio = ide_get_best_pio_mode(drive, pio, 4, NULL); + spin_lock_irqsave(&io_request_lock, flags); + pci_read_config_word(dev, 0x40, &drive_enables); + pci_read_config_dword(dev, 0x44, &drive_timing); + + /* + * FIX! The DIOR/DIOW pulse width and recovery times in port 0x44 + * are being left at the default values of 8 PCI clocks (242 nsec + * for a 33 MHz clock). These can be safely shortened at higher + * PIO modes. The DIOR/DIOW pulse width and recovery times only + * apply to PIO modes, not to the DMA modes. + */ + + /* + * Enable port 0x44. The IT8172G spec is confused; it calls + * this register the "Slave IDE Timing Register", but in fact, + * it controls timing for both master and slave drives. + */ + drive_enables |= 0x4000; + + if (is_slave) { + drive_enables &= 0xc006; + if (pio > 1) + /* enable prefetch and IORDY sample-point */ + drive_enables |= 0x0060; + } else { + drive_enables &= 0xc060; + if (pio > 1) + /* enable prefetch and IORDY sample-point */ + drive_enables |= 0x0006; + } - if (is_slave) { - drive_enables &= 0xc006; - if (pio > 1) - /* enable prefetch and IORDY sample-point */ - drive_enables |= 0x0060; - } else { - drive_enables &= 0xc060; - if (pio > 1) - /* enable prefetch and IORDY sample-point */ - drive_enables |= 0x0006; - } - - save_flags(flags); - cli(); - pci_write_config_word(HWIF(drive)->pci_dev, 0x40, drive_enables); - restore_flags(flags); + pci_write_config_word(dev, 0x40, drive_enables); + spin_unlock_irqrestore(&io_request_lock, flags) } -#if defined(CONFIG_BLK_DEV_IDEDMA) && defined(CONFIG_IT8172_TUNING) -/* - * - */ static byte it8172_dma_2_pio (byte xfer_rate) { - switch(xfer_rate) { - case XFER_UDMA_5: - case XFER_UDMA_4: - case XFER_UDMA_3: - case XFER_UDMA_2: - case XFER_UDMA_1: - case XFER_UDMA_0: - case XFER_MW_DMA_2: - case XFER_PIO_4: - return 4; - case XFER_MW_DMA_1: - case XFER_PIO_3: - return 3; - case XFER_SW_DMA_2: - case XFER_PIO_2: - return 2; - case XFER_MW_DMA_0: - case XFER_SW_DMA_1: - case XFER_SW_DMA_0: - case XFER_PIO_1: - case XFER_PIO_0: - case XFER_PIO_SLOW: - default: - return 0; - } -} - -static int it8172_tune_chipset (ide_drive_t *drive, byte speed) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - int a_speed = 3 << (drive->dn * 4); - int u_flag = 1 << drive->dn; - int u_speed = 0; - int err = 0; - byte reg48, reg4a; + switch(xfer_rate) { + case XFER_UDMA_5: + case XFER_UDMA_4: + case XFER_UDMA_3: + case XFER_UDMA_2: + case XFER_UDMA_1: + case XFER_UDMA_0: + case XFER_MW_DMA_2: + case XFER_PIO_4: + return 4; + case XFER_MW_DMA_1: + case XFER_PIO_3: + return 3; + case XFER_SW_DMA_2: + case XFER_PIO_2: + return 2; + case XFER_MW_DMA_0: + case XFER_SW_DMA_1: + case XFER_SW_DMA_0: + case XFER_PIO_1: + case XFER_PIO_0: + case XFER_PIO_SLOW: + default: + return 0; + } +} + +static int it8172_tune_chipset (ide_drive_t *drive, byte xferspeed) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + byte speed = it8172_ratefilter(drive, xferspeed); + int a_speed = 3 << (drive->dn * 4); + int u_flag = 1 << drive->dn; + int u_speed = 0; + byte reg48, reg4a; - pci_read_config_byte(dev, 0x48, ®48); - pci_read_config_byte(dev, 0x4a, ®4a); + pci_read_config_byte(dev, 0x48, ®48); + pci_read_config_byte(dev, 0x4a, ®4a); /* * Setting the DMA cycle time to 2 or 3 PCI clocks (60 and 91 nsec @@ -157,130 +185,205 @@ * performance. */ - switch(speed) { - case XFER_UDMA_4: - case XFER_UDMA_2: //u_speed = 2 << (drive->dn * 4); break; - case XFER_UDMA_5: - case XFER_UDMA_3: - case XFER_UDMA_1: //u_speed = 1 << (drive->dn * 4); break; - case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break; - case XFER_MW_DMA_2: - case XFER_MW_DMA_1: - case XFER_MW_DMA_0: - case XFER_SW_DMA_2: break; - default: return -1; - } - - if (speed >= XFER_UDMA_0) { - pci_write_config_byte(dev, 0x48, reg48 | u_flag); - reg4a &= ~a_speed; - pci_write_config_byte(dev, 0x4a, reg4a | u_speed); - } else { - pci_write_config_byte(dev, 0x48, reg48 & ~u_flag); - pci_write_config_byte(dev, 0x4a, reg4a & ~a_speed); - } - - it8172_tune_drive(drive, it8172_dma_2_pio(speed)); - - if (!drive->init_speed) - drive->init_speed = speed; - err = ide_config_drive_speed(drive, speed); - drive->current_speed = speed; - return err; + switch(speed) { +#ifdef CONFIG_BLK_DEV_IDEDMA + case XFER_UDMA_4: + case XFER_UDMA_2: //u_speed = 2 << (drive->dn * 4); break; + case XFER_UDMA_5: + case XFER_UDMA_3: + case XFER_UDMA_1: //u_speed = 1 << (drive->dn * 4); break; + case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break; + case XFER_MW_DMA_2: + case XFER_MW_DMA_1: + case XFER_MW_DMA_0: + case XFER_SW_DMA_2: break; +#endif /* CONFIG_BLK_DEV_IDEDMA */ + case XFER_PIO_4: + case XFER_PIO_3: + case XFER_PIO_2: + case XFER_PIO_0: break; + default: return -1; + } + + if (speed >= XFER_UDMA_0) { + pci_write_config_byte(dev, 0x48, reg48 | u_flag); + reg4a &= ~a_speed; + pci_write_config_byte(dev, 0x4a, reg4a | u_speed); + } else { + pci_write_config_byte(dev, 0x48, reg48 & ~u_flag); + pci_write_config_byte(dev, 0x4a, reg4a & ~a_speed); + } + + it8172_tune_drive(drive, it8172_dma_2_pio(speed)); + return (ide_config_drive_speed(drive, speed)); } +#ifdef CONFIG_BLK_DEV_IDEDMA static int it8172_config_chipset_for_dma (ide_drive_t *drive) { - struct hd_driveid *id = drive->id; - byte speed; + struct hd_driveid *id = drive->id; + byte mode = it8172_ratemask(drive); + byte speed, tspeed, dma = 1; + + switch(mode) { + case 0x01: + if (id->dma_ultra & 0x0040) + { speed = XFER_UDMA_2; break; } + if (id->dma_ultra & 0x0020) + { speed = XFER_UDMA_2; break; } + if (id->dma_ultra & 0x0010) + { speed = XFER_UDMA_2; break; } + if (id->dma_ultra & 0x0008) + { speed = XFER_UDMA_2; break; } + if (id->dma_ultra & 0x0004) + { speed = XFER_UDMA_2; break; } + if (id->dma_ultra & 0x0002) + { speed = XFER_UDMA_1; break; } + if (id->dma_ultra & 0x0001) + { speed = XFER_UDMA_0; break; } + case 0x00: + if (id->dma_mword & 0x0004) + { speed = XFER_MW_DMA_2; break; } + if (id->dma_mword & 0x0002) + { speed = XFER_MW_DMA_1; break; } + if (id->dma_1word & 0x0004) + { speed = XFER_SW_DMA_2; break; } + default: + tspeed = ide_get_best_pio_mode(drive, 255, 4, NULL); + speed = it8172_dma_2_pio(XFER_PIO_0 + tspeed); + dma = 0; + break; + } + + (void) it8172_tune_chipset(drive, speed); + +// return ((int)(dma) ? ide_dma_on : ide_dma_off_quietly); + return ((int)((id->dma_ultra >> 11) & 7) ? ide_dma_on : + ((id->dma_ultra >> 8) & 7) ? ide_dma_on : + ((id->dma_mword >> 8) & 7) ? ide_dma_on : + ((id->dma_1word >> 8) & 7) ? ide_dma_on : + ide_dma_off_quietly); +} - if (id->dma_ultra & 0x0010) { - speed = XFER_UDMA_2; - } else if (id->dma_ultra & 0x0008) { - speed = XFER_UDMA_1; - } else if (id->dma_ultra & 0x0004) { - speed = XFER_UDMA_2; - } else if (id->dma_ultra & 0x0002) { - speed = XFER_UDMA_1; - } else if (id->dma_ultra & 0x0001) { - speed = XFER_UDMA_0; - } else if (id->dma_mword & 0x0004) { - speed = XFER_MW_DMA_2; - } else if (id->dma_mword & 0x0002) { - speed = XFER_MW_DMA_1; - } else if (id->dma_mword & 0x0001) { - speed = XFER_MW_DMA_0; - } else if (id->dma_1word & 0x0004) { - speed = XFER_SW_DMA_2; - } else { - speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 4, NULL); - } - - (void) it8172_tune_chipset(drive, speed); - - return ((int)((id->dma_ultra >> 11) & 7) ? ide_dma_on : - ((id->dma_ultra >> 8) & 7) ? ide_dma_on : - ((id->dma_mword >> 8) & 7) ? ide_dma_on : - ((id->dma_1word >> 8) & 7) ? ide_dma_on : - ide_dma_off_quietly); +static int config_drive_xfer_rate (ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + ide_dma_action_t dma_func = ide_dma_on; + + drive->init_speed = 0; + + if (id && (id->capability & 1) && HWIF(drive)->autodma) { + /* Consult the list of known "bad" drives */ + if (ide_dmaproc(ide_dma_bad_drive, drive)) { + dma_func = ide_dma_off; + goto fast_ata_pio; + } + dma_func = ide_dma_off_quietly; + if (id->field_valid & 4) { + if (id->dma_ultra & 0x007F) { + /* Force if Capable UltraDMA */ + dma_func = it8172_config_chipset_for_dma(drive); + if ((id->field_valid & 2) && + (dma_func != ide_dma_on)) + goto try_dma_modes; + } + } else if (id->field_valid & 2) { +try_dma_modes: + if ((id->dma_mword & 0x0007) || + (id->dma_1word & 0x007)) { + /* Force if Capable regular DMA modes */ + dma_func = it8172_config_chipset_for_dma(drive); + if (dma_func != ide_dma_on) + goto no_dma_set; + } + } else if (ide_dmaproc(ide_dma_good_drive, drive)) { + if (id->eide_dma_time > 150) { + goto no_dma_set; + } + /* Consult the list of known "good" drives */ + dma_func = it8172_config_chipset_for_dma(drive); + if (dma_func != ide_dma_on) + goto no_dma_set; + } else { + goto fast_ata_pio; + } + } else if ((id->capability & 8) || (id->field_valid & 2)) { +fast_ata_pio: + dma_func = ide_dma_off_quietly; +no_dma_set: + it8172_tune_drive(drive, 5); + } + return HWIF(drive)->dmaproc(dma_func, drive); } static int it8172_dmaproc(ide_dma_action_t func, ide_drive_t *drive) { - switch (func) { - case ide_dma_check: - return ide_dmaproc((ide_dma_action_t)it8172_config_chipset_for_dma(drive), - drive); - default : - break; - } - /* Other cases are done by generic IDE-DMA code. */ - return ide_dmaproc(func, drive); + switch (func) { + case ide_dma_check: + return config_drive_xfer_rate(drive); + default : + break; + } + /* Other cases are done by generic IDE-DMA code. */ + return ide_dmaproc(func, drive); } - -#endif /* defined(CONFIG_BLK_DEV_IDEDMA) && (CONFIG_IT8172_TUNING) */ +#endif /* CONFIG_BLK_DEV_IDEDMA */ unsigned int __init pci_init_it8172 (struct pci_dev *dev, const char *name) { - unsigned char progif; + unsigned char progif; - /* - * Place both IDE interfaces into PCI "native" mode - */ - (void)pci_read_config_byte(dev, PCI_CLASS_PROG, &progif); - (void)pci_write_config_byte(dev, PCI_CLASS_PROG, progif | 0x05); + /* + * Place both IDE interfaces into PCI "native" mode + */ + pci_read_config_byte(dev, PCI_CLASS_PROG, &progif); + pci_write_config_byte(dev, PCI_CLASS_PROG, progif | 0x05); - return IT8172_IDE_IRQ; + return IT8172_IDE_IRQ; } void __init ide_init_it8172 (ide_hwif_t *hwif) { - struct pci_dev* dev = hwif->pci_dev; - unsigned long cmdBase, ctrlBase; + struct pci_dev* dev = hwif->pci_dev; + unsigned long cmdBase, ctrlBase; - hwif->tuneproc = &it8172_tune_drive; - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - - if (!hwif->dma_base) - return; - -#ifndef CONFIG_BLK_DEV_IDEDMA - hwif->autodma = 0; -#else /* CONFIG_BLK_DEV_IDEDMA */ -#ifdef CONFIG_IT8172_TUNING - hwif->autodma = 1; - hwif->dmaproc = &it8172_dmaproc; - hwif->speedproc = &it8172_tune_chipset; -#endif /* CONFIG_IT8172_TUNING */ -#endif /* !CONFIG_BLK_DEV_IDEDMA */ + hwif->autodma = 0; + hwif->tuneproc = &it8172_tune_drive; + hwif->speedproc = &it8172_tune_chipset; + hwif->drives[0].autotune = 1; + hwif->drives[1].autotune = 1; - cmdBase = dev->resource[0].start; - ctrlBase = dev->resource[1].start; + cmdBase = dev->resource[0].start; + ctrlBase = dev->resource[1].start; - ide_init_hwif_ports(&hwif->hw, cmdBase, ctrlBase | 2, NULL); - memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); - hwif->noprobe = 0; + ide_init_hwif_ports(&hwif->hw, cmdBase, ctrlBase | 2, NULL); + memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); + hwif->noprobe = 0; + + if (!hwif->dma_base) + return; + +#ifdef CONFIG_BLK_DEV_IDEDMA + hwif->dmaproc = &it8172_dmaproc; +# ifdef CONFIG_IDEDMA_AUTO + if (!noautodma) + hwif->autodma = 1; +# endif /* CONFIG_IDEDMA_AUTO */ +#endif /* !CONFIG_BLK_DEV_IDEDMA */ +} + +extern void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d); + +void __init fixup_device_it8172 (struct pci_dev *dev, ide_pci_device_t *d) +{ + if ((!(PCI_FUNC(dev->devfn) & 1) || + (!((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)))) + return; /* IT8172 is more than only a IDE controller */ + + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d->name, dev->bus->number, dev->devfn); + ide_setup_pci_device(dev, d); } + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/Makefile linux.19rc3-ac4/drivers/ide/Makefile --- linux.19rc3/drivers/ide/Makefile 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/Makefile 2002-07-29 13:58:39.000000000 +0100 @@ -10,7 +10,7 @@ O_TARGET := idedriver.o -export-objs := ide.o ide-features.o ide-probe.o ide-taskfile.o ataraid.o +export-objs := ide-taskfile.o ide.o ide-probe.o ataraid.o list-multi := ide-mod.o ide-probe-mod.o obj-y := @@ -27,6 +27,7 @@ obj-$(CONFIG_BLK_DEV_IT8172) += it8172.o +ide-obj-$(CONFIG_BLK_DEV_ADMA100) += adma100.o ide-obj-$(CONFIG_BLK_DEV_AEC62XX) += aec62xx.o ide-obj-$(CONFIG_BLK_DEV_ALI14XX) += ali14xx.o ide-obj-$(CONFIG_BLK_DEV_ALI15X3) += alim15x3.o @@ -44,8 +45,8 @@ ide-obj-$(CONFIG_BLK_DEV_HPT366) += hpt366.o ide-obj-$(CONFIG_BLK_DEV_HT6560B) += ht6560b.o ide-obj-$(CONFIG_BLK_DEV_IDE_ICSIDE) += icside.o -ide-obj-$(CONFIG_BLK_DEV_ADMA) += ide-adma.o ide-obj-$(CONFIG_BLK_DEV_IDEDMA_PCI) += ide-dma.o +ide-obj-$(CONFIG_BLK_DEV_MPC8xx_IDE) += ide-m8xx.o ide-obj-$(CONFIG_BLK_DEV_IDEPCI) += ide-pci.o ide-obj-$(CONFIG_BLK_DEV_ISAPNP) += ide-pnp.o ide-obj-$(CONFIG_BLK_DEV_IDE_PMAC) += ide-pmac.o @@ -56,7 +57,6 @@ ide-obj-$(CONFIG_BLK_DEV_SVWKS) += serverworks.o ide-obj-$(CONFIG_BLK_DEV_PDC202XX) += pdc202xx.o ide-obj-$(CONFIG_BLK_DEV_PDC4030) += pdc4030.o -ide-obj-$(CONFIG_BLK_DEV_PDC_ADMA) += pdcadma.o ide-obj-$(CONFIG_BLK_DEV_PIIX) += piix.o ide-obj-$(CONFIG_BLK_DEV_QD65XX) += qd65xx.o ide-obj-$(CONFIG_BLK_DEV_IDE_RAPIDE) += rapide.o @@ -67,7 +67,6 @@ ide-obj-$(CONFIG_BLK_DEV_TRM290) += trm290.o ide-obj-$(CONFIG_BLK_DEV_UMC8672) += umc8672.o ide-obj-$(CONFIG_BLK_DEV_VIA82CXXX) += via82cxxx.o -ide-obj-$(CONFIG_BLK_DEV_MPC8xx_IDE) += ide-m8xx.o # The virtualised raid layers MUST come after the ide itself or bad stuff # will happen. @@ -77,7 +76,7 @@ ide-obj-$(CONFIG_PROC_FS) += ide-proc.o -ide-mod-objs := ide.o ide-features.o ide-taskfile.o $(ide-obj-y) +ide-mod-objs := ide-taskfile.o ide.o $(ide-obj-y) ide-probe-mod-objs := ide-probe.o ide-geometry.o include $(TOPDIR)/Rules.make diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/ns87415.c linux.19rc3-ac4/drivers/ide/ns87415.c --- linux.19rc3/drivers/ide/ns87415.c 2002-07-29 12:49:58.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/ns87415.c 2002-07-29 13:58:40.000000000 +0100 @@ -24,6 +24,10 @@ #include +#if defined(__hppa__) && defined(CONFIG_SUPERIO) +#include +#endif + static unsigned int ns87415_count = 0, ns87415_control[MAX_HWIFS] = { 0 }; /* @@ -38,8 +42,7 @@ struct pci_dev *dev = hwif->pci_dev; unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ + local_irq_save(flags); new = *old; /* Adjust IRQ enable bit */ @@ -73,7 +76,7 @@ udelay(10); } - __restore_flags(flags); /* local CPU only */ + local_irq_restore(flags); } static void ns87415_selectproc (ide_drive_t *drive) @@ -90,17 +93,24 @@ switch (func) { case ide_dma_end: /* returns 1 on error, 0 otherwise */ drive->waiting_for_dma = 0; - dma_stat = inb(hwif->dma_base+2); - outb(inb(hwif->dma_base)&~1, hwif->dma_base); /* stop DMA */ - outb(inb(hwif->dma_base)|6, hwif->dma_base); /* from ERRATA: clear the INTR & ERROR bits */ - ide_destroy_dmatable(drive); /* and free any DMA resources */ - return (dma_stat & 7) != 4; /* verify good DMA status */ + dma_stat = IN_BYTE(hwif->dma_base+2); + /* stop DMA */ + OUT_BYTE(IN_BYTE(hwif->dma_base)&~1, hwif->dma_base); + /* from ERRATA: clear the INTR & ERROR bits */ + OUT_BYTE(IN_BYTE(hwif->dma_base)|6, hwif->dma_base); + /* and free any DMA resources */ + ide_destroy_dmatable(drive); + /* verify good DMA status */ + return (dma_stat & 7) != 4; case ide_dma_write: case ide_dma_read: - ns87415_prepare_drive(drive, 1); /* select DMA xfer */ - if (!ide_dmaproc(func, drive)) /* use standard DMA stuff */ + /* select DMA xfer */ + ns87415_prepare_drive(drive, 1); + /* use standard DMA stuff */ + if (!ide_dmaproc(func, drive)) return 0; - ns87415_prepare_drive(drive, 0); /* DMA failed: select PIO xfer */ + /* DMA failed: select PIO xfer */ + ns87415_prepare_drive(drive, 0); return 1; case ide_dma_check: if (drive->media != ide_disk) @@ -122,6 +132,9 @@ byte stat; #endif + hwif->autodma = 0; + hwif->selectproc = &ns87415_selectproc; + /* Set a good latency timer and cache line size value. */ (void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); #ifdef __sparc_v9__ @@ -164,30 +177,36 @@ * to SELECT_DRIVE() properly during first probe_hwif(). */ timeout = 10000; - outb(12, hwif->io_ports[IDE_CONTROL_OFFSET]); + OUT_BYTE(12, hwif->io_ports[IDE_CONTROL_OFFSET]); udelay(10); - outb(8, hwif->io_ports[IDE_CONTROL_OFFSET]); + OUT_BYTE(8, hwif->io_ports[IDE_CONTROL_OFFSET]); do { udelay(50); - stat = inb(hwif->io_ports[IDE_STATUS_OFFSET]); + stat = IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]); if (stat == 0xff) break; } while ((stat & BUSY_STAT) && --timeout); #endif } - if (hwif->dma_base) - outb(0x60, hwif->dma_base + 2); - if (!using_inta) +#if defined(__hppa__) && defined(CONFIG_SUPERIO) + hwif->irq = superio_get_ide_irq(); /* legacy mode */ +#else hwif->irq = hwif->channel ? 15 : 14; /* legacy mode */ +#endif else if (!hwif->irq && hwif->mate && hwif->mate->irq) hwif->irq = hwif->mate->irq; /* share IRQ with mate */ + if (!hwif->dma_base) + return; + #ifdef CONFIG_BLK_DEV_IDEDMA - if (hwif->dma_base) - hwif->dmaproc = &ns87415_dmaproc; + OUT_BYTE(0x60, hwif->dma_base + 2); + hwif->dmaproc = &ns87415_dmaproc; +#ifdef CONFIG_IDEDMA_AUTO + if (!noautodma) + hwif->autodma = 1; +#endif /* CONFIG_IDEDMA_AUTO */ #endif /* CONFIG_BLK_DEV_IDEDMA */ - - hwif->selectproc = &ns87415_selectproc; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/opti621.c linux.19rc3-ac4/drivers/ide/opti621.c --- linux.19rc3/drivers/ide/opti621.c 2002-07-29 12:49:58.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/opti621.c 2002-07-29 13:58:40.000000000 +0100 @@ -97,6 +97,7 @@ #include #include #include +#include #include #include @@ -183,11 +184,11 @@ * This is from setupvic.exe program. */ { - inw(reg_base+1); - inw(reg_base+1); - outb(3, reg_base+2); - outb(value, reg_base+reg); - outb(0x83, reg_base+2); + IN_WORD(reg_base+1); + IN_WORD(reg_base+1); + OUT_BYTE(3, reg_base+2); + OUT_BYTE(value, reg_base+reg); + OUT_BYTE(0x83, reg_base+2); } static byte read_reg(int reg) @@ -198,11 +199,11 @@ */ { byte ret; - inw(reg_base+1); - inw(reg_base+1); - outb(3, reg_base+2); - ret=inb(reg_base+reg); - outb(0x83, reg_base+2); + IN_WORD(reg_base+1); + IN_WORD(reg_base+1); + OUT_BYTE(3, reg_base+2); + ret=IN_BYTE(reg_base+reg); + OUT_BYTE(0x83, reg_base+2); return ret; } @@ -276,13 +277,12 @@ hwif->name, ax, second.data_time, second.recovery_time, drdy); #endif - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ + spin_lock_irqsave(&io_request_lock, flags); reg_base = hwif->io_ports[IDE_DATA_OFFSET]; - outb(0xc0, reg_base+CNTRL_REG); /* allow Register-B */ - outb(0xff, reg_base+5); /* hmm, setupvic.exe does this ;-) */ - inb(reg_base+CNTRL_REG); /* if reads 0xff, adapter not exist? */ + OUT_BYTE(0xc0, reg_base+CNTRL_REG); /* allow Register-B */ + OUT_BYTE(0xff, reg_base+5); /* hmm, setupvic.exe does this ;-) */ + IN_BYTE(reg_base+CNTRL_REG); /* if reads 0xff, adapter not exist? */ read_reg(CNTRL_REG); /* if reads 0xc0, no interface exist? */ read_reg(STRAP_REG); /* read version, probably 0 */ @@ -302,7 +302,7 @@ write_reg(misc, MISC_REG); /* set address setup, DRDY timings, */ /* and read prefetch for both drives */ - restore_flags(flags); /* all CPUs */ + spin_unlock_irqrestore(&io_request_lock, flags); } /* @@ -310,7 +310,30 @@ */ void __init ide_init_opti621 (ide_hwif_t *hwif) { + hwif->autodma = 0; hwif->drives[0].drive_data = PIO_DONT_KNOW; hwif->drives[1].drive_data = PIO_DONT_KNOW; hwif->tuneproc = &opti621_tune_drive; + + /* safety call for Anton A */ + hwif->dma_base = 0; +} + +extern void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d); + +void __init fixup_device_opti621 (struct pci_dev *dev, ide_pci_device_t *d) +{ +#if 0 + if (IDE_PCI_DEVID_EQ(d->devid, DEVID_OPTI621V) && + !(PCI_FUNC(dev->devfn) & 1)) +#else + if ((dev->device == PCI_DEVICE_ID_OPTI_82C558) && + (!(PCI_FUNC(dev->devfn) & 1))) +#endif + return; /* OPTI621 is more than only a IDE controller */ + + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d->name, dev->bus->number, dev->devfn); + ide_setup_pci_device(dev, d); } + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/pdc202xx.c linux.19rc3-ac4/drivers/ide/pdc202xx.c --- linux.19rc3/drivers/ide/pdc202xx.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/pdc202xx.c 2002-07-29 16:18:11.000000000 +0100 @@ -1,59 +1,33 @@ /* - * linux/drivers/ide/pdc202xx.c Version 0.32 Feb. 27, 2002 + * linux/drivers/ide/pdc202xx.c Version 0.35 Mar. 30, 2002 * - * Copyright (C) 1998-2000 Andre Hedrick - * May be copied or modified under the terms of the GNU General Public License + * Copyright (C) 1998-2002 Andre Hedrick * - * Promise Ultra66 cards with BIOS v1.11 this + * Promise Ultra33 cards with BIOS v1.20 through 1.28 will need this * compiled into the kernel if you have more than one card installed. + * Note that BIOS v1.29 is reported to fix the problem. Since this is + * safe chipset tuning, including this support is harmless * - * Promise Ultra100 cards with BIOS v2.01 this + * Promise Ultra66 cards with BIOS v1.11 this * compiled into the kernel if you have more than one card installed. * - * Promise Ultra100TX2 with BIOS v2.10 & Ultra133TX2 with BIOS v2.20 - * support 8 hard drives on UDMA mode. + * Promise Ultra100 cards. * - * Linux kernel will misunderstand FastTrak ATA-RAID series as Ultra - * IDE Controller, UNLESS you enable "CONFIG_PDC202XX_FORCE" - * That's you can use FastTrak ATA-RAID controllers as IDE controllers. + * The latest chipset code will support the following :: + * Three Ultra33 controllers and 12 drives. + * 8 are UDMA supported and 4 are limited to DMA mode 2 multi-word. + * The 8/4 ratio is a BIOS code limit by promise. * - * History : - * 05/22/01 v1.20 b1 - * (1) support PDC20268 - * (2) fix cable judge function - * 08/22/01 v1.20 b2 - * (1) support ATA-133 PDC20269/75 - * (2) support UDMA Mode 6 - * (3) fix proc report information - * (4) set ATA133 timing - * (5) fix ultra dma bit 14 selectable - * (6) support 32bit LBA - * 09/11/01 v1.20 b3 - * (1) fix eighty_ninty_three() - * (2) fix offset address 0x1c~0x1f - * 10/30/01 v1.20 b4 - * (1) fix 48bit LBA HOB bit - * (2) force rescan drive under PIO modes if need - * 11/02/01 v1.20.0.5 - * (1) could be patched with ext3 filesystem code - * 11/06/01 v1.20.0.6 - * (1) fix LBA48 drive running without Promise controllers - * (2) fix LBA48 drive running under PIO modes - * 01/28/02 v1.20.0.6 - * (1) release for linux IDE Group kernel 2.4.18 - * (2) add version and controller info to proc - * 05/23/02 v1.20.0.7 - * (1) disable PDC20262 running with 48bit - * (2) Add quirk drive lists for PDC20265/67 + * UNLESS you enable "CONFIG_PDC202XX_BURST" * - * Copyright (C) 1999-2002 Promise Technology, Inc. - * Author: Frank Tiernan - * PROMISE pdc202xx IDE Controller driver MAINTAINERS + */ + +/* + * Portions Copyright (C) 1999 Promise Technology, Inc. + * Author: Frank Tiernan (frankt@promise.com) * Released under terms of General Public License */ - -#define VERSION "1.20.0.7" -#define VERDATE "2002-05-23" + #include #include #include @@ -88,10 +62,60 @@ static int pdc202xx_get_info(char *, char **, off_t, int); extern int (*pdc202xx_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); -static struct pci_dev *bmide_dev; -static struct hd_driveid *id[4]; -static int speed_rate[4]; + +byte pdc202xx_proc = 0; + +#define PDC202_MAX_DEVS 5 + +static struct pci_dev *pdc202_devs[PDC202_MAX_DEVS]; +static int n_pdc202_devs; + +const char *pdc_quirk_drives[] = { + "QUANTUM FIREBALLlct08 08", + "QUANTUM FIREBALLP KA6.4", + "QUANTUM FIREBALLP KA9.1", + "QUANTUM FIREBALLP LM20.4", + "QUANTUM FIREBALLP KX13.6", + "QUANTUM FIREBALLP KX20.5", + "QUANTUM FIREBALLP KX27.3", + "QUANTUM FIREBALLP LM20.5", + NULL +}; + +char *pdc202xx_pio_verbose (u32 drive_pci) +{ + if ((drive_pci & 0x000ff000) == 0x000ff000) return("NOTSET"); + if ((drive_pci & 0x00000401) == 0x00000401) return("PIO 4"); + if ((drive_pci & 0x00000602) == 0x00000602) return("PIO 3"); + if ((drive_pci & 0x00000803) == 0x00000803) return("PIO 2"); + if ((drive_pci & 0x00000C05) == 0x00000C05) return("PIO 1"); + if ((drive_pci & 0x00001309) == 0x00001309) return("PIO 0"); + return("PIO ?"); +} + +char *pdc202xx_dma_verbose (u32 drive_pci) +{ + if ((drive_pci & 0x00036000) == 0x00036000) return("MWDMA 2"); + if ((drive_pci & 0x00046000) == 0x00046000) return("MWDMA 1"); + if ((drive_pci & 0x00056000) == 0x00056000) return("MWDMA 0"); + if ((drive_pci & 0x00056000) == 0x00056000) return("SWDMA 2"); + if ((drive_pci & 0x00068000) == 0x00068000) return("SWDMA 1"); + if ((drive_pci & 0x000BC000) == 0x000BC000) return("SWDMA 0"); + return("PIO---"); +} + +char *pdc202xx_ultra_verbose (u32 drive_pci, u16 slow_cable) +{ + if ((drive_pci & 0x000ff000) == 0x000ff000) + return("NOTSET"); + if ((drive_pci & 0x00012000) == 0x00012000) + return((slow_cable) ? "UDMA 2" : "UDMA 4"); + if ((drive_pci & 0x00024000) == 0x00024000) + return((slow_cable) ? "UDMA 1" : "UDMA 3"); + if ((drive_pci & 0x00036000) == 0x00036000) + return("UDMA 0"); + return(pdc202xx_dma_verbose(drive_pci)); +} static char * pdc202xx_info (char *buf, struct pci_dev *dev) { @@ -99,10 +123,8 @@ u32 bibma = pci_resource_start(dev, 4); u32 reg60h = 0, reg64h = 0, reg68h = 0, reg6ch = 0; - u16 reg50h = 0; - u16 word88 = 0; - int udmasel[4] = {0,0,0,0}, piosel[4] = {0,0,0,0}; - int i = 0, hd = 0; + u16 reg50h = 0, pmask = (1<<10), smask = (1<<11); + u8 hi = 0, lo = 0; /* * at that point bibma+0x2 et bibma+0xa are byte registers @@ -114,10 +136,10 @@ u8 sc11 = inb_p((unsigned short)bibma + 0x11); u8 sc1a = inb_p((unsigned short)bibma + 0x1a); u8 sc1b = inb_p((unsigned short)bibma + 0x1b); - /* u8 sc1c = inb_p((unsigned short)bibma + 0x1c); + u8 sc1c = inb_p((unsigned short)bibma + 0x1c); u8 sc1d = inb_p((unsigned short)bibma + 0x1d); u8 sc1e = inb_p((unsigned short)bibma + 0x1e); - u8 sc1f = inb_p((unsigned short)bibma + 0x1f); */ + u8 sc1f = inb_p((unsigned short)bibma + 0x1f); pci_read_config_word(dev, 0x50, ®50h); pci_read_config_dword(dev, 0x60, ®60h); @@ -125,95 +147,150 @@ pci_read_config_dword(dev, 0x68, ®68h); pci_read_config_dword(dev, 0x6c, ®6ch); - p+=sprintf(p, "\nPROMISE Ultra series driver Ver %s %s Adapter: ", VERSION, VERDATE); + p += sprintf(p, "\n "); switch(dev->device) { - case PCI_DEVICE_ID_PROMISE_20275: - p += sprintf(p, "MBUltra133\n"); - break; - case PCI_DEVICE_ID_PROMISE_20269: - p += sprintf(p, "Ultra133 TX2\n"); - break; - case PCI_DEVICE_ID_PROMISE_20268: - p += sprintf(p, "Ultra100 TX2\n"); - break; case PCI_DEVICE_ID_PROMISE_20267: - p += sprintf(p, "Ultra100\n"); - break; + p += sprintf(p, "Ultra100"); break; case PCI_DEVICE_ID_PROMISE_20265: - p += sprintf(p, "Ultra100 on M/B\n"); - break; + p += sprintf(p, "Ultra100 on M/B"); break; + case PCI_DEVICE_ID_PROMISE_20263: + p += sprintf(p, "FastTrak 66"); break; case PCI_DEVICE_ID_PROMISE_20262: - p += sprintf(p, "Ultra66\n"); - break; + p += sprintf(p, "Ultra66"); break; case PCI_DEVICE_ID_PROMISE_20246: - p += sprintf(p, "Ultra33\n"); + p += sprintf(p, "Ultra33"); reg50h |= 0x0c00; break; default: - p += sprintf(p, "Ultra Series\n"); - break; + p += sprintf(p, "Ultra Series"); break; } + p += sprintf(p, " Chipset.\n"); - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); + p += sprintf(p, "------------------------------- General Status " + "---------------------------------\n"); + p += sprintf(p, "Burst Mode : %sabled\n", + (sc1f & 0x01) ? "en" : "dis"); + p += sprintf(p, "Host Mode : %s\n", + (sc1f & 0x08) ? "Tri-Stated" : "Normal"); + p += sprintf(p, "Bus Clocking : %s\n", + ((sc1f & 0xC0) == 0xC0) ? "100 External" : + ((sc1f & 0x80) == 0x80) ? "66 External" : + ((sc1f & 0x40) == 0x40) ? "33 External" : "33 PCI Internal"); + p += sprintf(p, "IO pad select : %s mA\n", + ((sc1c & 0x03) == 0x03) ? "10" : + ((sc1c & 0x02) == 0x02) ? "8" : + ((sc1c & 0x01) == 0x01) ? "6" : + ((sc1c & 0x00) == 0x00) ? "4" : "??"); + SPLIT_BYTE(sc1e, hi, lo); + p += sprintf(p, "Status Polling Period : %d\n", hi); + p += sprintf(p, "Interrupt Check Status Polling Delay : %d\n", lo); + p += sprintf(p, "--------------- Primary Channel " + "---------------- Secondary Channel " + "-------------\n"); p += sprintf(p, " %s %s\n", (c0&0x80)?"disabled":"enabled ", (c1&0x80)?"disabled":"enabled "); p += sprintf(p, "66 Clocking %s %s\n", (sc11&0x02)?"enabled ":"disabled", (sc11&0x08)?"enabled ":"disabled"); - p += sprintf(p, "Mode %s %s\n", + p += sprintf(p, " Mode %s Mode %s\n", (sc1a & 0x01) ? "MASTER" : "PCI ", (sc1b & 0x01) ? "MASTER" : "PCI "); - p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s %s %s\n", - (id[0]!=NULL && (c0&0x20))?"yes":"no ",(id[1]!=NULL && (c0&0x40))?"yes":"no ", - (id[2]!=NULL && (c1&0x20))?"yes":"no ",(id[3]!=NULL && (c1&0x40))?"yes":"no "); - for( hd = 0; hd < 4 ; hd++) { - if (id[hd] == NULL) - continue; - word88 = id[hd]->dma_ultra; - for ( i = 7 ; i >= 0 ; i--) - if (word88 >> (i+8)) { - udmasel[hd] = i; /* get select UDMA mode */ - break; - } - piosel[hd] = (id[hd]->eide_pio_modes >= 0x02) ? 4 : 3; - } - p += sprintf(p, "UDMA Mode: %d %d %d %d\n", - udmasel[0], udmasel[1], udmasel[2], udmasel[3]); - p += sprintf(p, "PIO Mode: %d %d %d %d\n", - piosel[0], piosel[1], piosel[2], piosel[3]); + p += sprintf(p, " %s %s\n", + (sc1d & 0x08) ? "Error " : + ((sc1d & 0x05) == 0x05) ? "Not My INTR " : + (sc1d & 0x04) ? "Interrupting" : + (sc1d & 0x02) ? "FIFO Full " : + (sc1d & 0x01) ? "FIFO Empty " : "????????????", + (sc1d & 0x80) ? "Error " : + ((sc1d & 0x50) == 0x50) ? "Not My INTR " : + (sc1d & 0x40) ? "Interrupting" : + (sc1d & 0x20) ? "FIFO Full " : + (sc1d & 0x10) ? "FIFO Empty " : "????????????"); + p += sprintf(p, "--------------- drive0 --------- drive1 " + "-------- drive0 ---------- drive1 ------\n"); + p += sprintf(p, "DMA enabled: %s %s " + " %s %s\n", + (c0&0x20)?"yes":"no ", (c0&0x40)?"yes":"no ", + (c1&0x20)?"yes":"no ", (c1&0x40)?"yes":"no "); + p += sprintf(p, "DMA Mode: %s %s " + " %s %s\n", + pdc202xx_ultra_verbose(reg60h, (reg50h & pmask)), + pdc202xx_ultra_verbose(reg64h, (reg50h & pmask)), + pdc202xx_ultra_verbose(reg68h, (reg50h & smask)), + pdc202xx_ultra_verbose(reg6ch, (reg50h & smask))); + p += sprintf(p, "PIO Mode: %s %s " + " %s %s\n", + pdc202xx_pio_verbose(reg60h), + pdc202xx_pio_verbose(reg64h), + pdc202xx_pio_verbose(reg68h), + pdc202xx_pio_verbose(reg6ch)); #if 0 p += sprintf(p, "--------------- Can ATAPI DMA ---------------\n"); #endif return (char *)p; } +static char * pdc202xx_info_new (char *buf, struct pci_dev *dev) +{ + char *p = buf; +// u32 bibma = pci_resource_start(dev, 4); + +// u32 reg60h = 0, reg64h = 0, reg68h = 0, reg6ch = 0; +// u16 reg50h = 0, word88 = 0; +// int udmasel[4]={0,0,0,0}, piosel[4]={0,0,0,0}, i=0, hd=0; + + p += sprintf(p, "\n "); + switch(dev->device) { + case PCI_DEVICE_ID_PROMISE_20277: + p += sprintf(p, "SBFastTrak 133 Lite"); break; + case PCI_DEVICE_ID_PROMISE_20276: + p += sprintf(p, "MBFastTrak 133 Lite"); break; + case PCI_DEVICE_ID_PROMISE_20275: + p += sprintf(p, "MBUltra133"); break; + case PCI_DEVICE_ID_PROMISE_20271: + p += sprintf(p, "FastTrak TX2000"); break; + case PCI_DEVICE_ID_PROMISE_20270: + p += sprintf(p, "FastTrak LP/TX2/TX4"); break; + case PCI_DEVICE_ID_PROMISE_20269: + p += sprintf(p, "Ultra133 TX2"); break; + case PCI_DEVICE_ID_PROMISE_20268: + p += sprintf(p, "Ultra100 TX2"); break; + default: + p += sprintf(p, "Ultra series"); break; + break; + } + p += sprintf(p, " Chipset.\n"); + return (char *)p; +} + static int pdc202xx_get_info (char *buffer, char **addr, off_t offset, int count) { char *p = buffer; - - p = pdc202xx_info(buffer, bmide_dev); + int i; + + for (i = 0; i < n_pdc202_devs; i++) { + struct pci_dev *dev = pdc202_devs[i]; + + switch(dev->device) { + case PCI_DEVICE_ID_PROMISE_20277: + case PCI_DEVICE_ID_PROMISE_20276: + case PCI_DEVICE_ID_PROMISE_20275: + case PCI_DEVICE_ID_PROMISE_20271: + case PCI_DEVICE_ID_PROMISE_20269: + case PCI_DEVICE_ID_PROMISE_20268: + case PCI_DEVICE_ID_PROMISE_20270: + p = pdc202xx_info_new(buffer, dev); + break; + default: + p = pdc202xx_info(buffer, dev); + break; + } + } return p-buffer; /* => must be less than 4k! */ } #endif /* defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) */ -byte pdc202xx_proc = 0; - -const char *pdc_quirk_drives[] = { - "QUANTUM FIREBALLlct08 08", - "QUANTUM FIREBALLP KA6.4", - "QUANTUM FIREBALLP KA9.1", - "QUANTUM FIREBALLP LM20.4", - "QUANTUM FIREBALLP KX13.6", - "QUANTUM FIREBALLP KX20.5", - "QUANTUM FIREBALLP KX27.3", - "QUANTUM FIREBALLP LM20.5", - NULL -}; - -extern char *ide_xfer_verbose (byte xfer_rate); - /* A Register */ #define SYNC_ERRDY_EN 0xC0 @@ -324,6 +401,69 @@ #endif /* PDC202XX_DECODE_REGISTER_INFO */ +#if 0 +static byte pdc202xx_ratemask (ide_drive_t *drive) +{ + struct pci_dev *dev = HWIF(drive)->pci_dev; + byte mode = 0x00; + + switch(dev->device) { + case PCI_DEVICE_ID_PROMISE_20277: + case PCI_DEVICE_ID_PROMISE_20276: + case PCI_DEVICE_ID_PROMISE_20275: + case PCI_DEVICE_ID_PROMISE_20271: + case PCI_DEVICE_ID_PROMISE_20269: + { mode |= 0x04; break; } + case PCI_DEVICE_ID_PROMISE_20270: + case PCI_DEVICE_ID_PROMISE_20268: + { mode |= 0x03; break; } + case PCI_DEVICE_ID_PROMISE_20267: + case PCI_DEVICE_ID_PROMISE_20265: + { mode |= 0x03; break; } + case PCI_DEVICE_ID_PROMISE_20263: + case PCI_DEVICE_ID_PROMISE_20262: + { mode |= 0x02; break; } + case PCI_DEVICE_ID_PROMISE_20246: + { mode |= 0x01; break; } + default: + return (mode &= ~0xF8); + } + + if (!eighty_ninty_three(drive)) { + mode &= ~0xFE; + mode |= 0x01; + } + return (mode &= ~0xF8); +} + +static byte pdc202xx_ratefilter (ide_drive_t *drive, byte speed) +{ +#ifdef CONFIG_BLK_DEV_IDEDMA + byte mode = pdc202xx_ratemask(drive); + + switch(mode) { + case 0x04: while (speed > XFER_UDMA_6) speed--; break; + case 0x03: while (speed > XFER_UDMA_5) speed--; break; + case 0x02: while (speed > XFER_UDMA_4) speed--; break; + case 0x01: while (speed > XFER_UDMA_2) speed--; break; + case 0x00: + default: while (speed > XFER_MW_DMA_2) speed--; break; + break; + } +#else + while (speed > XFER_PIO_4) speed--; +#endif /* CONFIG_BLK_DEV_IDEDMA */ +// printk("%s: mode == %02x speed == %02x\n", drive->name, mode, speed); + return speed; +} + +#else +static byte pdc202xx_ratefilter (ide_drive_t *drive, byte speed) +{ + return speed; +} +#endif + static int check_in_drive_lists (ide_drive_t *drive, const char **list) { struct hd_driveid *id = drive->id; @@ -344,13 +484,13 @@ return 0; } -static int pdc202xx_tune_chipset (ide_drive_t *drive, byte speed) +static int pdc202xx_tune_chipset (ide_drive_t *drive, byte xferspeed) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; + byte speed = pdc202xx_ratefilter(drive, xferspeed); unsigned int drive_conf; - int err = 0, i = 0, j = hwif->channel ? 2 : 0 ; byte drive_pci, AP, BP, CP, DP; byte TA = 0, TB = 0, TC = 0; @@ -362,7 +502,8 @@ default: return -1; } - if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0)) return -1; + if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0)) + return -1; pci_read_config_dword(dev, drive_pci, &drive_conf); pci_read_config_byte(dev, (drive_pci), &AP); @@ -370,59 +511,53 @@ pci_read_config_byte(dev, (drive_pci)|0x02, &CP); pci_read_config_byte(dev, (drive_pci)|0x03, &DP); -#ifdef CONFIG_BLK_DEV_IDEDMA - if (speed >= XFER_SW_DMA_0) { - if ((BP & 0xF0) && (CP & 0x0F)) { - /* clear DMA modes of upper 842 bits of B Register */ - /* clear PIO forced mode upper 1 bit of B Register */ - pci_write_config_byte(dev, (drive_pci)|0x01, BP & ~0xF0); - pci_read_config_byte(dev, (drive_pci)|0x01, &BP); - - /* clear DMA modes of lower 8421 bits of C Register */ - pci_write_config_byte(dev, (drive_pci)|0x02, CP & ~0x0F); - pci_read_config_byte(dev, (drive_pci)|0x02, &CP); - } - } else { -#else - { -#endif /* CONFIG_BLK_DEV_IDEDMA */ + if (speed < XFER_SW_DMA_0) { if ((AP & 0x0F) || (BP & 0x07)) { /* clear PIO modes of lower 8421 bits of A Register */ - pci_write_config_byte(dev, (drive_pci), AP & ~0x0F); + pci_write_config_byte(dev, (drive_pci), AP &~0x0F); pci_read_config_byte(dev, (drive_pci), &AP); /* clear PIO modes of lower 421 bits of B Register */ - pci_write_config_byte(dev, (drive_pci)|0x01, BP & ~0x07); + pci_write_config_byte(dev, (drive_pci)|0x01, BP &~0x07); pci_read_config_byte(dev, (drive_pci)|0x01, &BP); pci_read_config_byte(dev, (drive_pci), &AP); pci_read_config_byte(dev, (drive_pci)|0x01, &BP); } +#ifdef CONFIG_BLK_DEV_IDEDMA + } else { + if ((BP & 0xF0) && (CP & 0x0F)) { + /* clear DMA modes of upper 842 bits of B Register */ + /* clear PIO forced mode upper 1 bit of B Register */ + pci_write_config_byte(dev, (drive_pci)|0x01, BP &~0xF0); + pci_read_config_byte(dev, (drive_pci)|0x01, &BP); + + /* clear DMA modes of lower 8421 bits of C Register */ + pci_write_config_byte(dev, (drive_pci)|0x02, CP &~0x0F); + pci_read_config_byte(dev, (drive_pci)|0x02, &CP); + } +#endif /* CONFIG_BLK_DEV_IDEDMA */ } pci_read_config_byte(dev, (drive_pci), &AP); pci_read_config_byte(dev, (drive_pci)|0x01, &BP); pci_read_config_byte(dev, (drive_pci)|0x02, &CP); - for ( i = 0; i < 2; i++) - if (hwif->drives[i].present) - id[i+j] = hwif->drives[i].id; /* get identify structs */ - switch(speed) { #ifdef CONFIG_BLK_DEV_IDEDMA /* case XFER_UDMA_6: */ case XFER_UDMA_5: - case XFER_UDMA_4: TB = 0x20; TC = 0x01; break; /* speed 8 == UDMA mode 4 */ - case XFER_UDMA_3: TB = 0x40; TC = 0x02; break; /* speed 7 == UDMA mode 3 */ - case XFER_UDMA_2: TB = 0x20; TC = 0x01; break; /* speed 6 == UDMA mode 2 */ - case XFER_UDMA_1: TB = 0x40; TC = 0x02; break; /* speed 5 == UDMA mode 1 */ - case XFER_UDMA_0: TB = 0x60; TC = 0x03; break; /* speed 4 == UDMA mode 0 */ - case XFER_MW_DMA_2: TB = 0x60; TC = 0x03; break; /* speed 4 == MDMA mode 2 */ - case XFER_MW_DMA_1: TB = 0x60; TC = 0x04; break; /* speed 3 == MDMA mode 1 */ - case XFER_MW_DMA_0: TB = 0x60; TC = 0x05; break; /* speed 2 == MDMA mode 0 */ - case XFER_SW_DMA_2: TB = 0x60; TC = 0x05; break; /* speed 0 == SDMA mode 2 */ - case XFER_SW_DMA_1: TB = 0x80; TC = 0x06; break; /* speed 1 == SDMA mode 1 */ - case XFER_SW_DMA_0: TB = 0xC0; TC = 0x0B; break; /* speed 0 == SDMA mode 0 */ + case XFER_UDMA_4: TB = 0x20; TC = 0x01; break; + case XFER_UDMA_3: TB = 0x40; TC = 0x02; break; + case XFER_UDMA_2: TB = 0x20; TC = 0x01; break; + case XFER_UDMA_1: TB = 0x40; TC = 0x02; break; + case XFER_UDMA_0: TB = 0x60; TC = 0x03; break; + case XFER_MW_DMA_2: TB = 0x60; TC = 0x03; break; + case XFER_MW_DMA_1: TB = 0x60; TC = 0x04; break; + case XFER_MW_DMA_0: TB = 0x60; TC = 0x05; break; + case XFER_SW_DMA_2: TB = 0x60; TC = 0x05; break; + case XFER_SW_DMA_1: TB = 0x80; TC = 0x06; break; + case XFER_SW_DMA_0: TB = 0xC0; TC = 0x0B; break; #endif /* CONFIG_BLK_DEV_IDEDMA */ case XFER_PIO_4: TA = 0x01; TB = 0x04; break; case XFER_PIO_3: TA = 0x02; TB = 0x06; break; @@ -432,16 +567,14 @@ default: TA = 0x09; TB = 0x13; break; } + if (speed < XFER_SW_DMA_0) { + pci_write_config_byte(dev, (drive_pci), AP|TA); + pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); #ifdef CONFIG_BLK_DEV_IDEDMA - if (speed >= XFER_SW_DMA_0) { + } else { pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); pci_write_config_byte(dev, (drive_pci)|0x02, CP|TC); - } else { -#else - { #endif /* CONFIG_BLK_DEV_IDEDMA */ - pci_write_config_byte(dev, (drive_pci), AP|TA); - pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); } #if PDC202XX_DECODE_REGISTER_INFO @@ -455,12 +588,6 @@ decode_registers(REG_C, CP); decode_registers(REG_D, DP); #endif /* PDC202XX_DECODE_REGISTER_INFO */ - - if (!drive->init_speed) - drive->init_speed = speed; - err = ide_config_drive_speed(drive, speed); - drive->current_speed = speed; - #if PDC202XX_DEBUG_DRIVE_INFO printk("%s: %s drive%d 0x%08x ", drive->name, ide_xfer_verbose(speed), @@ -468,10 +595,11 @@ pci_read_config_dword(dev, drive_pci, &drive_conf); printk("0x%08x\n", drive_conf); #endif /* PDC202XX_DEBUG_DRIVE_INFO */ - return err; + + return (ide_config_drive_speed(drive, speed)); } -static int pdc202xx_new_tune_chipset (ide_drive_t *drive, byte speed) +static int pdc202xx_new_tune_chipset (ide_drive_t *drive, byte xferspeed) { ide_hwif_t *hwif = HWIF(drive); #ifdef CONFIG_BLK_DEV_IDEDMA @@ -485,158 +613,139 @@ #endif /* CONFIG_BLK_DEV_IDEDMA */ byte thold = 0x10; byte adj = (drive->dn%2) ? 0x08 : 0x00; - int set_speed = 0, i=0, j=hwif->channel ? 2:0; - int err; + byte speed = pdc202xx_ratefilter(drive, xferspeed); - /* Setting tHOLD bit to 0 if using UDMA mode 2 */ +#ifdef CONFIG_BLK_DEV_IDEDMA if (speed == XFER_UDMA_2) { OUT_BYTE((thold + adj), indexreg); OUT_BYTE((IN_BYTE(datareg) & 0x7f), datareg); } - - /* We need to set ATA133 timing if ATA133 drives exist */ - if (speed>=XFER_UDMA_6) - set_speed=1; +#endif /* CONFIG_BLK_DEV_IDEDMA */ - if (!drive->init_speed) - drive->init_speed = speed; -#if PDC202XX_DEBUG_DRIVE_INFO - printk("%s: Before set_feature = %s, word88 = %#x\n", - drive->name, ide_xfer_verbose(speed), drive->id->dma_ultra ); -#endif /* PDC202XX_DEBUG_DRIVE_INFO */ - err = ide_config_drive_speed(drive, speed); - drive->current_speed = speed; - for ( i = 0 ; i < 2 ; i++) - if (hwif->drives[i].present) { - id[i+j] = hwif->drives[i].id; /* get identify structs */ - speed_rate[i+j] = speed; /* get current speed */ - } - if (set_speed) { - for (i=0; i<4; i++) { - if (id[i]==NULL) - continue; - switch(speed_rate[i]) { + switch (speed) { #ifdef CONFIG_BLK_DEV_IDEDMA - case XFER_UDMA_6: - OUT_BYTE((0x10 + adj), indexreg); - OUT_BYTE(0x1a, datareg); - OUT_BYTE((0x11 + adj), indexreg); - OUT_BYTE(0x01, datareg); - OUT_BYTE((0x12 + adj), indexreg); - OUT_BYTE(0xcb, datareg); - break; - case XFER_UDMA_5: - OUT_BYTE((0x10 + adj), indexreg); - OUT_BYTE(0x1a, datareg); - OUT_BYTE((0x11 + adj), indexreg); - OUT_BYTE(0x02, datareg); - OUT_BYTE((0x12 + adj), indexreg); - OUT_BYTE(0xcb, datareg); - break; - case XFER_UDMA_4: - OUT_BYTE((0x10 + adj), indexreg); - OUT_BYTE(0x1a, datareg); - OUT_BYTE((0x11 + adj), indexreg); - OUT_BYTE(0x03, datareg); - OUT_BYTE((0x12 + adj), indexreg); - OUT_BYTE(0xcd, datareg); - break; - case XFER_UDMA_3: - OUT_BYTE((0x10 + adj), indexreg); - OUT_BYTE(0x1a, datareg); - OUT_BYTE((0x11 + adj), indexreg); - OUT_BYTE(0x05, datareg); - OUT_BYTE((0x12 + adj), indexreg); - OUT_BYTE(0xcd, datareg); - break; - case XFER_UDMA_2: - OUT_BYTE((0x10 + adj), indexreg); - OUT_BYTE(0x2a, datareg); - OUT_BYTE((0x11 + adj), indexreg); - OUT_BYTE(0x07, datareg); - OUT_BYTE((0x12 + adj), indexreg); - OUT_BYTE(0xcd, datareg); - break; - case XFER_UDMA_1: - OUT_BYTE((0x10 + adj), indexreg); - OUT_BYTE(0x3a, datareg); - OUT_BYTE((0x11 + adj), indexreg); - OUT_BYTE(0x0a, datareg); - OUT_BYTE((0x12 + adj), indexreg); - OUT_BYTE(0xd0, datareg); - break; - case XFER_UDMA_0: - OUT_BYTE((0x10 + adj), indexreg); - OUT_BYTE(0x4a, datareg); - OUT_BYTE((0x11 + adj), indexreg); - OUT_BYTE(0x0f, datareg); - OUT_BYTE((0x12 + adj), indexreg); - OUT_BYTE(0xd5, datareg); - break; - case XFER_MW_DMA_2: - OUT_BYTE((0x0e + adj), indexreg); - OUT_BYTE(0x69, datareg); - OUT_BYTE((0x0f + adj), indexreg); - OUT_BYTE(0x25, datareg); - break; - case XFER_MW_DMA_1: - OUT_BYTE((0x0e + adj), indexreg); - OUT_BYTE(0x6b, datareg); - OUT_BYTE((0x0f+ adj), indexreg); - OUT_BYTE(0x27, datareg); - break; - case XFER_MW_DMA_0: - OUT_BYTE((0x0e + adj), indexreg); - OUT_BYTE(0xdf, datareg); - OUT_BYTE((0x0f + adj), indexreg); - OUT_BYTE(0x5f, datareg); - break; + case XFER_UDMA_7: + speed = XFER_UDMA_6; + case XFER_UDMA_6: + OUT_BYTE((0x10 + adj), indexreg); + OUT_BYTE(0x1a, datareg); + OUT_BYTE((0x11 + adj), indexreg); + OUT_BYTE(0x01, datareg); + OUT_BYTE((0x12 + adj), indexreg); + OUT_BYTE(0xcb, datareg); + break; + case XFER_UDMA_5: + OUT_BYTE((0x10 + adj), indexreg); + OUT_BYTE(0x1a, datareg); + OUT_BYTE((0x11 + adj), indexreg); + OUT_BYTE(0x02, datareg); + OUT_BYTE((0x12 + adj), indexreg); + OUT_BYTE(0xcb, datareg); + break; + case XFER_UDMA_4: + OUT_BYTE((0x10 + adj), indexreg); + OUT_BYTE(0x1a, datareg); + OUT_BYTE((0x11 + adj), indexreg); + OUT_BYTE(0x03, datareg); + OUT_BYTE((0x12 + adj), indexreg); + OUT_BYTE(0xcd, datareg); + break; + case XFER_UDMA_3: + OUT_BYTE((0x10 + adj), indexreg); + OUT_BYTE(0x1a, datareg); + OUT_BYTE((0x11 + adj), indexreg); + OUT_BYTE(0x05, datareg); + OUT_BYTE((0x12 + adj), indexreg); + OUT_BYTE(0xcd, datareg); + break; + case XFER_UDMA_2: + OUT_BYTE((0x10 + adj), indexreg); + OUT_BYTE(0x2a, datareg); + OUT_BYTE((0x11 + adj), indexreg); + OUT_BYTE(0x07, datareg); + OUT_BYTE((0x12 + adj), indexreg); + OUT_BYTE(0xcd, datareg); + break; + case XFER_UDMA_1: + OUT_BYTE((0x10 + adj), indexreg); + OUT_BYTE(0x3a, datareg); + OUT_BYTE((0x11 + adj), indexreg); + OUT_BYTE(0x0a, datareg); + OUT_BYTE((0x12 + adj), indexreg); + OUT_BYTE(0xd0, datareg); + break; + case XFER_UDMA_0: + OUT_BYTE((0x10 + adj), indexreg); + OUT_BYTE(0x4a, datareg); + OUT_BYTE((0x11 + adj), indexreg); + OUT_BYTE(0x0f, datareg); + OUT_BYTE((0x12 + adj), indexreg); + OUT_BYTE(0xd5, datareg); + break; + case XFER_MW_DMA_2: + OUT_BYTE((0x0e + adj), indexreg); + OUT_BYTE(0x69, datareg); + OUT_BYTE((0x0f + adj), indexreg); + OUT_BYTE(0x25, datareg); + break; + case XFER_MW_DMA_1: + OUT_BYTE((0x0e + adj), indexreg); + OUT_BYTE(0x6b, datareg); + OUT_BYTE((0x0f+ adj), indexreg); + OUT_BYTE(0x27, datareg); + break; + case XFER_MW_DMA_0: + OUT_BYTE((0x0e + adj), indexreg); + OUT_BYTE(0xdf, datareg); + OUT_BYTE((0x0f + adj), indexreg); + OUT_BYTE(0x5f, datareg); + break; #endif /* CONFIG_BLK_DEV_IDEDMA */ - case XFER_PIO_4: - OUT_BYTE((0x0c + adj), indexreg); - OUT_BYTE(0x23, datareg); - OUT_BYTE((0x0d + adj), indexreg); - OUT_BYTE(0x09, datareg); - OUT_BYTE((0x13 + adj), indexreg); - OUT_BYTE(0x25, datareg); - break; - case XFER_PIO_3: - OUT_BYTE((0x0c + adj), indexreg); - OUT_BYTE(0x27, datareg); - OUT_BYTE((0x0d + adj), indexreg); - OUT_BYTE(0x0d, datareg); - OUT_BYTE((0x13 + adj), indexreg); - OUT_BYTE(0x35, datareg); - break; - case XFER_PIO_2: - OUT_BYTE((0x0c + adj), indexreg); - OUT_BYTE(0x23, datareg); - OUT_BYTE((0x0d + adj), indexreg); - OUT_BYTE(0x26, datareg); - OUT_BYTE((0x13 + adj), indexreg); - OUT_BYTE(0x64, datareg); - break; - case XFER_PIO_1: - OUT_BYTE((0x0c + adj), indexreg); - OUT_BYTE(0x46, datareg); - OUT_BYTE((0x0d + adj), indexreg); - OUT_BYTE(0x29, datareg); - OUT_BYTE((0x13 + adj), indexreg); - OUT_BYTE(0xa4, datareg); - break; - case XFER_PIO_0: - OUT_BYTE((0x0c + adj), indexreg); - OUT_BYTE(0xfb, datareg); - OUT_BYTE((0x0d + adj), indexreg); - OUT_BYTE(0x2b, datareg); - OUT_BYTE((0x13 + adj), indexreg); - OUT_BYTE(0xac, datareg); - break; - default: - } - } + case XFER_PIO_4: + OUT_BYTE((0x0c + adj), indexreg); + OUT_BYTE(0x23, datareg); + OUT_BYTE((0x0d + adj), indexreg); + OUT_BYTE(0x09, datareg); + OUT_BYTE((0x13 + adj), indexreg); + OUT_BYTE(0x25, datareg); + break; + case XFER_PIO_3: + OUT_BYTE((0x0c + adj), indexreg); + OUT_BYTE(0x27, datareg); + OUT_BYTE((0x0d + adj), indexreg); + OUT_BYTE(0x0d, datareg); + OUT_BYTE((0x13 + adj), indexreg); + OUT_BYTE(0x35, datareg); + break; + case XFER_PIO_2: + OUT_BYTE((0x0c + adj), indexreg); + OUT_BYTE(0x23, datareg); + OUT_BYTE((0x0d + adj), indexreg); + OUT_BYTE(0x26, datareg); + OUT_BYTE((0x13 + adj), indexreg); + OUT_BYTE(0x64, datareg); + break; + case XFER_PIO_1: + OUT_BYTE((0x0c + adj), indexreg); + OUT_BYTE(0x46, datareg); + OUT_BYTE((0x0d + adj), indexreg); + OUT_BYTE(0x29, datareg); + OUT_BYTE((0x13 + adj), indexreg); + OUT_BYTE(0xa4, datareg); + break; + case XFER_PIO_0: + OUT_BYTE((0x0c + adj), indexreg); + OUT_BYTE(0xfb, datareg); + OUT_BYTE((0x0d + adj), indexreg); + OUT_BYTE(0x2b, datareg); + OUT_BYTE((0x13 + adj), indexreg); + OUT_BYTE(0xac, datareg); + break; + default: + ; } - return err; + + return (ide_config_drive_speed(drive, speed)); } /* 0 1 2 3 4 5 6 7 8 @@ -662,9 +771,10 @@ } #ifdef CONFIG_BLK_DEV_IDEDMA -static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) +static int config_chipset_for_dma (ide_drive_t *drive) { struct hd_driveid *id = drive->id; +// byte mode = pdc202xx_ratemask(drive); ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; unsigned long high_16 = pci_resource_start(dev, 4); @@ -674,65 +784,68 @@ byte iordy = 0x13; byte adj = (drive->dn%2) ? 0x08 : 0x00; byte cable = 0; - byte new_chip = 0; - byte unit = (drive->select.b.unit & 0x01); + byte jumpbit = 0; unsigned int drive_conf; byte drive_pci = 0; byte test1, test2, speed = -1; byte AP; unsigned short EP; byte CLKSPD = 0; - byte clockreg = high_16 + 0x11; - byte udma_33 = ultra; - byte udma_66 = ((eighty_ninty_three(drive)) && udma_33) ? 1 : 0; + byte udma_33 = 1; + byte udma_66 = (eighty_ninty_three(drive)) ? 1 : 0; byte udma_100 = 0; byte udma_133 = 0; - byte mask = hwif->channel ? 0x08 : 0x02; + byte mask = hwif->channel ? 0x08 : 0x02; unsigned short c_mask = hwif->channel ? (1<<11) : (1<<10); byte ultra_66 = ((id->dma_ultra & 0x0010) || (id->dma_ultra & 0x0008)) ? 1 : 0; - byte ultra_100 = ((id->dma_ultra & 0x0020) || - (ultra_66)) ? 1 : 0; - byte ultra_133 = ((id->dma_ultra & 0x0040) || - (ultra_100)) ? 1 : 0; switch(dev->device) { + case PCI_DEVICE_ID_PROMISE_20277: case PCI_DEVICE_ID_PROMISE_20276: case PCI_DEVICE_ID_PROMISE_20275: + case PCI_DEVICE_ID_PROMISE_20271: case PCI_DEVICE_ID_PROMISE_20269: udma_133 = (udma_66) ? 1 : 0; udma_100 = (udma_66) ? 1 : 0; OUT_BYTE(0x0b, (hwif->dma_base + 1)); cable = ((IN_BYTE((hwif->dma_base + 3)) & 0x04)); - new_chip = 1; + jumpbit = 1; break; - case PCI_DEVICE_ID_PROMISE_20268: case PCI_DEVICE_ID_PROMISE_20270: + udma_100 = 1; + udma_66 = 1; + OUT_BYTE(0x0b, (hwif->dma_base + 1)); + cable = ((IN_BYTE((hwif->dma_base + 3)) & 0x04)); + jumpbit = 1; + break; + case PCI_DEVICE_ID_PROMISE_20268: udma_100 = (udma_66) ? 1 : 0; OUT_BYTE(0x0b, (hwif->dma_base + 1)); cable = ((IN_BYTE((hwif->dma_base + 3)) & 0x04)); - new_chip = 1; + jumpbit = 1; break; case PCI_DEVICE_ID_PROMISE_20267: case PCI_DEVICE_ID_PROMISE_20265: udma_100 = (udma_66) ? 1 : 0; pci_read_config_word(dev, 0x50, &EP); cable = (EP & c_mask); - new_chip = 0; - CLKSPD = IN_BYTE(clockreg); + jumpbit = 0; break; + case PCI_DEVICE_ID_PROMISE_20263: case PCI_DEVICE_ID_PROMISE_20262: pci_read_config_word(dev, 0x50, &EP); cable = (EP & c_mask); - new_chip = 0; - CLKSPD = IN_BYTE(clockreg); + jumpbit = 0; break; default: - udma_100 = 0; udma_133 = 0; cable = 0; new_chip = 1; + udma_100 = 0; udma_133 = 0; cable = 1; jumpbit = 0; break; } + if (!jumpbit) + CLKSPD = IN_BYTE(high_16 + 0x11); /* * Set the control register to use the 66Mhz system * clock for UDMA 3/4 mode operation. If one drive on @@ -746,41 +859,50 @@ * parameters. */ - if (((ultra_66) || (ultra_100) || (ultra_133)) && (cable)) { -#ifdef DEBUG - printk("ULTRA66: %s channel of Ultra 66 requires an 80-pin cable for Ultra66 operation.\n", hwif->channel ? "Secondary" : "Primary"); + if ((ultra_66) && (cable)) { +//#ifdef DEBUG +#if 1 + printk("ULTRA 66/100/133: %s channel of Ultra 66/100/133 " + "requires an 80-pin cable for Ultra66 operation.\n", + hwif->channel ? "Secondary" : "Primary"); printk(" Switching to Ultra33 mode.\n"); #endif /* DEBUG */ /* Primary : zero out second bit */ /* Secondary : zero out fourth bit */ - //if (!new_chip) - OUT_BYTE(CLKSPD & ~mask, clockreg); + if (!jumpbit) + OUT_BYTE(CLKSPD & ~mask, (high_16 + 0x11)); printk("Warning: %s channel requires an 80-pin cable for operation.\n", hwif->channel ? "Secondary":"Primary"); printk("%s reduced to Ultra33 mode.\n", drive->name); - udma_66 = 0; udma_100 = 0; udma_133 = 0; + udma_66 = 0; } else { - if ((ultra_66) || (ultra_100) || (ultra_133)) { + if (ultra_66) { /* * check to make sure drive on same channel * is u66 capable */ if (hwif->drives[!(drive->dn%2)].id) { - if ((hwif->drives[!(drive->dn%2)].id->dma_ultra & 0x0040) || - (hwif->drives[!(drive->dn%2)].id->dma_ultra -& 0x0020) || - (hwif->drives[!(drive->dn%2)].id->dma_ultra & 0x0010) || - (hwif->drives[!(drive->dn%2)].id->dma_ultra & 0x0008)) { - OUT_BYTE(CLKSPD | mask, clockreg); + if (hwif->drives[!(drive->dn%2)].id->dma_ultra & 0x0078) { + if (!jumpbit) + OUT_BYTE(CLKSPD | mask, (high_16 + 0x11)); } else { - OUT_BYTE(CLKSPD & ~mask, clockreg); + if (!jumpbit) + OUT_BYTE(CLKSPD & ~mask, (high_16 + 0x11)); } } else { /* udma4 drive by itself */ - OUT_BYTE(CLKSPD | mask, clockreg); + if (!jumpbit) + OUT_BYTE(CLKSPD | mask, (high_16 + 0x11)); } } } - if (new_chip) goto chipset_is_set; + if (jumpbit) { + if (drive->media != ide_disk) return ide_dma_off_quietly; + if (id->capability & 4) { /* IORDY_EN & PREFETCH_EN */ + OUT_BYTE((iordy + adj), indexreg); + OUT_BYTE((IN_BYTE(datareg)|0x03), datareg); + } + goto jumpbit_is_set; + } switch(drive->dn) { case 0: drive_pci = 0x60; @@ -823,24 +945,20 @@ chipset_is_set: - if (drive->media != ide_disk) + if (drive->media != ide_disk) { + hwif->tuneproc(drive, 5); return ide_dma_off_quietly; - - if (new_chip) { - if (id->capability & 4) { /* IORDY_EN & PREFETCH_EN */ - OUT_BYTE((iordy + adj), indexreg); - OUT_BYTE((IN_BYTE(datareg)|0x03), datareg); - } - } - else { - pci_read_config_byte(dev, (drive_pci), &AP); - if (id->capability & 4) /* IORDY_EN */ - pci_write_config_byte(dev, (drive_pci), AP|IORDY_EN); - pci_read_config_byte(dev, (drive_pci), &AP); - if (drive->media == ide_disk) /* PREFETCH_EN */ - pci_write_config_byte(dev, (drive_pci), AP|PREFETCH_EN); } + pci_read_config_byte(dev, (drive_pci), &AP); + if (id->capability & 4) /* IORDY_EN */ + pci_write_config_byte(dev, (drive_pci), AP|IORDY_EN); + pci_read_config_byte(dev, (drive_pci), &AP); + if (drive->media == ide_disk) /* PREFETCH_EN */ + pci_write_config_byte(dev, (drive_pci), AP|PREFETCH_EN); + +jumpbit_is_set: + if ((id->dma_ultra & 0x0040)&&(udma_133)) speed = XFER_UDMA_6; else if ((id->dma_ultra & 0x0020)&&(udma_100)) speed = XFER_UDMA_5; else if ((id->dma_ultra & 0x0010)&&(udma_66)) speed = XFER_UDMA_4; @@ -851,17 +969,17 @@ else if (id->dma_mword & 0x0004) speed = XFER_MW_DMA_2; else if (id->dma_mword & 0x0002) speed = XFER_MW_DMA_1; else if (id->dma_mword & 0x0001) speed = XFER_MW_DMA_0; - else if ((id->dma_1word & 0x0004)&&(!new_chip)) speed = XFER_SW_DMA_2; - else if ((id->dma_1word & 0x0002)&&(!new_chip)) speed = XFER_SW_DMA_1; - else if ((id->dma_1word & 0x0001)&&(!new_chip)) speed = XFER_SW_DMA_0; + else if ((id->dma_1word & 0x0004)&&(!jumpbit)) speed = XFER_SW_DMA_2; + else if ((id->dma_1word & 0x0002)&&(!jumpbit)) speed = XFER_SW_DMA_1; + else if ((id->dma_1word & 0x0001)&&(!jumpbit)) speed = XFER_SW_DMA_0; else { /* restore original pci-config space */ - if (!new_chip) + if (!jumpbit) pci_write_config_dword(dev, drive_pci, drive_conf); + hwif->tuneproc(drive, 5); return ide_dma_off_quietly; } - outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2); (void) hwif->speedproc(drive, speed); return ((int) ((id->dma_ultra >> 14) & 3) ? ide_dma_on : @@ -874,9 +992,11 @@ static int config_drive_xfer_rate (ide_drive_t *drive) { - struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); - ide_dma_action_t dma_func = ide_dma_off_quietly; + struct hd_driveid *id = drive->id; + ide_hwif_t *hwif = HWIF(drive); + ide_dma_action_t dma_func = ide_dma_off_quietly; + + drive->init_speed = 0; if (id && (id->capability & 1) && hwif->autodma) { /* Consult the list of known "bad" drives */ @@ -888,7 +1008,7 @@ if (id->field_valid & 4) { if (id->dma_ultra & 0x007F) { /* Force if Capable UltraDMA */ - dma_func = config_chipset_for_dma(drive, 1); + dma_func = config_chipset_for_dma(drive); if ((id->field_valid & 2) && (dma_func != ide_dma_on)) goto try_dma_modes; @@ -898,7 +1018,7 @@ if ((id->dma_mword & 0x0007) || (id->dma_1word & 0x0007)) { /* Force if Capable regular DMA modes */ - dma_func = config_chipset_for_dma(drive, 0); + dma_func = config_chipset_for_dma(drive); if (dma_func != ide_dma_on) goto no_dma_set; } @@ -907,7 +1027,7 @@ goto no_dma_set; } /* Consult the list of known "good" drives */ - dma_func = config_chipset_for_dma(drive, 0); + dma_func = config_chipset_for_dma(drive); if (dma_func != ide_dma_on) goto no_dma_set; } else { @@ -917,10 +1037,10 @@ fast_ata_pio: dma_func = ide_dma_off_quietly; no_dma_set: - (void) config_chipset_for_pio(drive, 5); + hwif->tuneproc(drive, 5); } - return HWIF(drive)->dmaproc(dma_func, drive); + return hwif->dmaproc(dma_func, drive); } int pdc202xx_quirkproc (ide_drive_t *drive) @@ -941,15 +1061,17 @@ ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; unsigned long high_16 = pci_resource_start(dev, 4); + unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20); unsigned long dma_base = hwif->dma_base; - unsigned long atapi_port= hwif->channel ? high_16+0x24 : high_16+0x20; switch (dev->device) { + case PCI_DEVICE_ID_PROMISE_20277: case PCI_DEVICE_ID_PROMISE_20276: case PCI_DEVICE_ID_PROMISE_20275: + case PCI_DEVICE_ID_PROMISE_20271: + case PCI_DEVICE_ID_PROMISE_20270: case PCI_DEVICE_ID_PROMISE_20269: case PCI_DEVICE_ID_PROMISE_20268: - case PCI_DEVICE_ID_PROMISE_20270: newchip = 1; break; case PCI_DEVICE_ID_PROMISE_20267: @@ -969,29 +1091,21 @@ * The Promise Ultra33 doesn't work correctly when * we do this part before issuing the drive cmd. */ - /* Enable ATAPI UDMA port for 48bit data on PDC20267 */ - if ((drive->addressing) && (hardware48fix)) { + if ((drive->addressing == 1) && (hardware48fix)) { struct request *rq = HWGROUP(drive)->rq; unsigned long word_count = 0; - unsigned long hankval = 0; - byte clockreg = high_16 + 0x11; - - OUT_BYTE(clock|(hwif->channel ? 0x08:0x02), clockreg); + + OUT_BYTE(clock|(hwif->channel ? 0x08 : 0x02), high_16 + 0x11); word_count = (rq->nr_sectors << 8); - hankval = (rq->cmd == READ) ? 0x05<<24 : 0x06<<24; - hankval = hankval | word_count ; - outl(hankval, atapi_port); - } + word_count = (rq->cmd == READ) ? word_count | 0x05000000 : word_count | 0x06000000; + outl(word_count, atapi_reg); + } break; case ide_dma_end: - /* Disable ATAPI UDMA port for 48bit data on PDC20267 */ - if ((drive->addressing) && (hardware48fix)) { - unsigned long hankval = 0; - byte clockreg = high_16 + 0x11; - - outl(hankval, atapi_port); /* zero out extra */ - clock = IN_BYTE(clockreg); - OUT_BYTE(clock & ~(hwif->channel ? 0x08:0x02), clockreg); + if ((drive->addressing == 1) && (hardware48fix)) { + outl(0, atapi_reg); /* zero out extra */ + clock = IN_BYTE(high_16 + 0x11); + OUT_BYTE(clock & ~(hwif->channel ? 0x08:0x02), high_16 + 0x11); } break; case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */ @@ -1000,7 +1114,7 @@ return (dma_stat & 4) == 4; sc1d = IN_BYTE(high_16 + 0x001d); - if (HWIF(drive)->channel) { + if (hwif->channel) { if ((sc1d & 0x50) == 0x50) goto somebody_else; else if ((sc1d & 0x40) == 0x40) return (dma_stat & 4) == 4; @@ -1013,8 +1127,8 @@ return (dma_stat & 4) == 4; /* return 1 if INTR asserted */ case ide_dma_lostirq: case ide_dma_timeout: - if (HWIF(drive)->resetproc != NULL) - HWIF(drive)->resetproc(drive); + if (hwif->resetproc != NULL) + hwif->resetproc(drive); default: break; } @@ -1022,16 +1136,38 @@ } #endif /* CONFIG_BLK_DEV_IDEDMA */ -void pdc202xx_reset (ide_drive_t *drive) +void pdc202xx_new_reset (ide_drive_t *drive) { - OUT_BYTE(0x04,IDE_CONTROL_REG); - mdelay(1000); - OUT_BYTE(0x00,IDE_CONTROL_REG); - mdelay(1000); + /* + * Deleted this because it is redundant from the caller. + */ printk("PDC202XX: %s channel reset.\n", HWIF(drive)->channel ? "Secondary" : "Primary"); } +void pdc202xx_reset_pci (struct pci_dev *dev) +{ + unsigned long high_16 = pci_resource_start(dev, 4); + byte udma_speed_flag = IN_BYTE(high_16 + 0x001f); + + OUT_BYTE(udma_speed_flag | 0x10, high_16 + 0x001f); + mdelay(100); + OUT_BYTE(udma_speed_flag & ~0x10, high_16 + 0x001f); + mdelay(2000); /* 2 seconds ?! */ +} + +void pdc202xx_reset_host (ide_hwif_t *hwif) +{ + pdc202xx_reset_pci(hwif->pci_dev); + printk("PDC202XX: %s channel reset.\n", + hwif->channel ? "Secondary" : "Primary"); +} + +void pdc202xx_reset (ide_drive_t *drive) +{ + pdc202xx_reset_host(HWIF(drive)); +} + /* * Since SUN Cobalt is attempting to do this operation, I should disclose * this has been a long time ago Thu Jul 27 16:40:57 2000 was the patch date @@ -1042,7 +1178,7 @@ #if 0 ide_hwif_t *hwif = HWIF(drive); unsigned long high_16 = pci_resource_start(hwif->pci_dev, 4); - byte sc1f = inb(high_16 + 0x001f); + byte sc1f = IN_BYTE(high_16 + 0x001f); if (!hwif) return -EINVAL; @@ -1050,9 +1186,9 @@ // hwif->bus_state = state; if (state) { - outb(sc1f | 0x08, high_16 + 0x001f); + OUT_BYTE(sc1f | 0x08, high_16 + 0x001f); } else { - outb(sc1f & ~0x08, high_16 + 0x001f); + OUT_BYTE(sc1f & ~0x08, high_16 + 0x001f); } #endif return 0; @@ -1064,17 +1200,58 @@ byte udma_speed_flag = IN_BYTE(high_16 + 0x001f); byte primary_mode = IN_BYTE(high_16 + 0x001a); byte secondary_mode = IN_BYTE(high_16 + 0x001b); - - OUT_BYTE(udma_speed_flag | 0x10, high_16 + 0x001f); - mdelay(100); - OUT_BYTE(udma_speed_flag & ~0x10, high_16 + 0x001f); - mdelay(2000); /* 2 seconds ?! */ + byte newchip = 0; if (dev->resource[PCI_ROM_RESOURCE].start) { - pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); - printk("%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start); + pci_write_config_dword(dev, PCI_ROM_ADDRESS, + dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); + printk("%s: ROM enabled at 0x%08lx\n", + name, dev->resource[PCI_ROM_RESOURCE].start); } - + + switch (dev->device) { + case PCI_DEVICE_ID_PROMISE_20277: + case PCI_DEVICE_ID_PROMISE_20276: + case PCI_DEVICE_ID_PROMISE_20275: + case PCI_DEVICE_ID_PROMISE_20271: + case PCI_DEVICE_ID_PROMISE_20269: + case PCI_DEVICE_ID_PROMISE_20270: + case PCI_DEVICE_ID_PROMISE_20268: + newchip = 1; + break; + case PCI_DEVICE_ID_PROMISE_20267: + case PCI_DEVICE_ID_PROMISE_20265: + pdc202xx_reset_pci(dev); + break; + case PCI_DEVICE_ID_PROMISE_20263: + case PCI_DEVICE_ID_PROMISE_20262: + /* + * software reset - this is required because the bios + * will set UDMA timing on if the hdd supports it. The + * user may want to turn udma off. A bug in the pdc20262 + * is that it cannot handle a downgrade in timing from + * UDMA to DMA. Disk accesses after issuing a set + * feature command will result in errors. A software + * reset leaves the timing registers intact, + * but resets the drives. + */ + pdc202xx_reset_pci(dev); + default: + if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) { + byte irq = 0, irq2 = 0; + pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); + pci_read_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, &irq2); /* 0xbc */ + if (irq != irq2) { + pci_write_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, irq); /* 0xbc */ + printk("%s: pci-config space interrupt mirror fixed.\n", name); + } + } + break; + } + + if (newchip) + goto fttk_tx_series; + printk("%s: (U)DMA Burst Bit %sABLED " \ "Primary %s Mode " \ "Secondary %s Mode.\n", @@ -1107,13 +1284,17 @@ } #endif /* CONFIG_PDC202XX_MASTER */ +fttk_tx_series: + + pdc202_devs[n_pdc202_devs++] = dev; + #if defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) if (!pdc202xx_proc) { pdc202xx_proc = 1; - bmide_dev = dev; pdc202xx_display_info = &pdc202xx_get_info; } #endif /* DISPLAY_PDC202XX_TIMINGS && CONFIG_PROC_FS */ + return dev->irq; } @@ -1122,19 +1303,21 @@ unsigned short mask = (hwif->channel) ? (1<<11) : (1<<10); unsigned short CIS; - switch(hwif->pci_dev->device) { + switch(hwif->pci_dev->device) { + case PCI_DEVICE_ID_PROMISE_20277: case PCI_DEVICE_ID_PROMISE_20276: case PCI_DEVICE_ID_PROMISE_20275: + case PCI_DEVICE_ID_PROMISE_20271: case PCI_DEVICE_ID_PROMISE_20269: case PCI_DEVICE_ID_PROMISE_20268: case PCI_DEVICE_ID_PROMISE_20270: OUT_BYTE(0x0b, (hwif->dma_base + 1)); return (!(IN_BYTE((hwif->dma_base + 3)) & 0x04)); - /* check 80pin cable */ + case PCI_DEVICE_ID_PROMISE_20267: + hwif->addressing = (hwif->channel) ? 0 : 1; default: pci_read_config_word(hwif->pci_dev, 0x50, &CIS); return (!(CIS & mask)); - /* check 80pin cable */ } } @@ -1142,47 +1325,98 @@ { hwif->tuneproc = &pdc202xx_tune_drive; hwif->quirkproc = &pdc202xx_quirkproc; - hwif->resetproc = &pdc202xx_reset; + + hwif->drives[0].autotune = 1; + hwif->drives[1].autotune = 1; + hwif->autodma = 0; + +#undef CONFIG_PDC202XX_32_UNMASK +#ifdef CONFIG_PDC202XX_32_UNMASK + hwif->drives[0].io_32bit = 1; + hwif->drives[1].io_32bit = 1; + hwif->drives[0].unmask = 1; + hwif->drives[1].unmask = 1; +#endif /* CONFIG_PDC202XX_32_UNMASK */ switch(hwif->pci_dev->device) { + case PCI_DEVICE_ID_PROMISE_20277: case PCI_DEVICE_ID_PROMISE_20276: case PCI_DEVICE_ID_PROMISE_20275: + case PCI_DEVICE_ID_PROMISE_20271: case PCI_DEVICE_ID_PROMISE_20269: case PCI_DEVICE_ID_PROMISE_20268: case PCI_DEVICE_ID_PROMISE_20270: hwif->speedproc = &pdc202xx_new_tune_chipset; + hwif->resetproc = &pdc202xx_new_reset; break; case PCI_DEVICE_ID_PROMISE_20267: case PCI_DEVICE_ID_PROMISE_20265: + case PCI_DEVICE_ID_PROMISE_20263: case PCI_DEVICE_ID_PROMISE_20262: hwif->busproc = &pdc202xx_tristate; + hwif->resetproc = &pdc202xx_reset; case PCI_DEVICE_ID_PROMISE_20246: hwif->speedproc = &pdc202xx_tune_chipset; default: break; } -#undef CONFIG_PDC202XX_32_UNMASK -#ifdef CONFIG_PDC202XX_32_UNMASK - hwif->drives[0].io_32bit = 1; - hwif->drives[1].io_32bit = 1; - hwif->drives[0].unmask = 1; - hwif->drives[1].unmask = 1; -#endif /* CONFIG_PDC202XX_32_UNMASK */ + if (!hwif->dma_base) + return; #ifdef CONFIG_BLK_DEV_IDEDMA - if (hwif->dma_base) { - hwif->dmaproc = &pdc202xx_dmaproc; - if (!noautodma) - hwif->autodma = 1; - } else { - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - hwif->autodma = 0; - } -#else /* !CONFIG_BLK_DEV_IDEDMA */ - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - hwif->autodma = 0; + hwif->dmaproc = &pdc202xx_dmaproc; +# ifdef CONFIG_IDEDMA_AUTO + if (!noautodma) + hwif->autodma = 1; +# endif /* CONFIG_IDEDMA_AUTO */ #endif /* CONFIG_BLK_DEV_IDEDMA */ } + +extern void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d); + +void __init fixup_device_pdc20265 (struct pci_dev *dev, ide_pci_device_t *d) +{ + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d->name, dev->bus->number, dev->devfn); + ide_setup_pci_device(dev, d); +} + +void __init fixup_device_pdc20270 (struct pci_dev *dev, ide_pci_device_t *d) +{ + struct pci_dev *dev2 = NULL, *findev; + ide_pci_device_t *d2; + + if ((dev->bus->self && + dev->bus->self->vendor == PCI_VENDOR_ID_DEC) && + (dev->bus->self->device == PCI_DEVICE_ID_DEC_21150)) { + if (PCI_SLOT(dev->devfn) & 2) { + return; + } + d->extra = 0; + pci_for_each_dev(findev) { + if ((findev->vendor == dev->vendor) && + (findev->device == dev->device) && + (PCI_SLOT(findev->devfn) & 2)) { + byte irq = 0, irq2 = 0; + dev2 = findev; + pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); + pci_read_config_byte(dev2, PCI_INTERRUPT_LINE, &irq2); + if (irq != irq2) { + dev2->irq = dev->irq; + pci_write_config_byte(dev2, PCI_INTERRUPT_LINE, irq); + } + } + } + } + + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d->name, dev->bus->number, dev->devfn); + ide_setup_pci_device(dev, d); + if (!dev2) + return; + d2 = d; + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d2->name, dev2->bus->number, dev2->devfn); + ide_setup_pci_device(dev2, d2); +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/pdc4030.c linux.19rc3-ac4/drivers/ide/pdc4030.c --- linux.19rc3/drivers/ide/pdc4030.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/pdc4030.c 2002-07-29 13:58:40.000000000 +0100 @@ -89,12 +89,6 @@ #include "pdc4030.h" -#ifdef CONFIG_IDE_TASKFILE_IO -# define __TASKFILE__IO -#else /* CONFIG_IDE_TASKFILE_IO */ -# undef __TASKFILE__IO -#endif /* CONFIG_IDE_TASKFILE_IO */ - /* * promise_selectproc() is invoked by ide.c * in preparation for access to the specified drive. @@ -174,7 +168,8 @@ if (hwif->chipset == ide_pdc4030) /* we've already been found ! */ return 1; - if (IN_BYTE(IDE_NSECTOR_REG) == 0xFF || IN_BYTE(IDE_SECTOR_REG) == 0xFF) { + if (IN_BYTE(IDE_NSECTOR_REG) == 0xFF || + IN_BYTE(IDE_SECTOR_REG) == 0xFF) { return 0; } if (IDE_CONTROL_REG) @@ -187,7 +182,7 @@ "%s: Failed Promise read config!\n",hwif->name); return 0; } - ide_input_data(drive,&ident,SECTOR_WORDS); + ata_input_data(drive, &ident, SECTOR_WORDS); if (ident.id[1] != 'P' || ident.id[0] != 'T') { return 0; } @@ -240,7 +235,7 @@ #ifdef DEBUG printk(KERN_DEBUG "Shifting i/f %d values to i/f %d\n",i-1,i); -#endif +#endif /* DEBUG */ ide_init_hwif_ports(&h->hw, (h-1)->io_ports[IDE_DATA_OFFSET], 0, NULL); memcpy(h->io_ports, h->hw.io_ports, sizeof(h->io_ports)); h->noprobe = (h-1)->noprobe; @@ -313,10 +308,13 @@ int total_remaining; unsigned int sectors_left, sectors_avail, nsect; struct request *rq; +#ifdef CONFIG_IDE_TASKFILE_IO + unsigned long flags; + char *to; +#endif /* CONFIG_IDE_TASKFILE_IO */ - if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) { - return ide_error(drive, "promise_read_intr", stat); - } + if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) + return DRIVER(drive)->error(drive, "promise_read_intr", stat); read_again: do { @@ -334,20 +332,36 @@ if (nsect > sectors_avail) nsect = sectors_avail; sectors_avail -= nsect; - ide_input_data(drive, rq->buffer, nsect * SECTOR_WORDS); +#ifdef CONFIG_IDE_TASKFILE_IO + to = ide_map_buffer(rq, &flags); + ata_input_data(drive, to, nsect * SECTOR_WORDS); +#else /* !CONFIG_IDE_TASKFILE_IO */ + ata_input_data(drive, rq->buffer, nsect * SECTOR_WORDS); +#endif /* CONFIG_IDE_TASKFILE_IO */ + #ifdef DEBUG_READ printk(KERN_DEBUG "%s: promise_read: sectors(%ld-%ld), " "buf=0x%08lx, rem=%ld\n", drive->name, rq->sector, - rq->sector+nsect-1, (unsigned long) rq->buffer, + rq->sector+nsect-1, +#ifdef CONFIG_IDE_TASKFILE_IO + (unsigned long) to, +#else /* !CONFIG_IDE_TASKFILE_IO */ + (unsigned long) rq->buffer, +#endif /* CONFIG_IDE_TASKFILE_IO */ rq->nr_sectors-nsect); -#endif - rq->sector += nsect; +#endif /* DEBUG_READ */ + +#ifdef CONFIG_IDE_TASKFILE_IO + ide_unmap_buffer(to, &flags); +#else /* !CONFIG_IDE_TASKFILE_IO */ rq->buffer += nsect<<9; +#endif /* CONFIG_IDE_TASKFILE_IO */ + rq->sector += nsect; rq->errors = 0; rq->nr_sectors -= nsect; total_remaining = rq->nr_sectors; if ((rq->current_nr_sectors -= nsect) <= 0) { - ide_end_request(1, HWGROUP(drive)); + DRIVER(drive)->end_request(drive, 1); } /* * Now the data has been read in, do the following: @@ -367,16 +381,18 @@ if (stat & DRQ_STAT) goto read_again; if (stat & BUSY_STAT) { + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler (drive, &promise_read_intr, WAIT_CMD, NULL); #ifdef DEBUG_READ printk(KERN_DEBUG "%s: promise_read: waiting for" "interrupt\n", drive->name); -#endif +#endif /* DEBUG_READ */ return ide_started; } printk(KERN_ERR "%s: Eeek! promise_read_intr: sectors left " "!DRQ !BUSY\n", drive->name); - return ide_error(drive, "promise read intr", stat); + return DRIVER(drive)->error(drive, "promise read intr", stat); } return ide_stopped; } @@ -397,27 +413,95 @@ if (GET_STAT() & BUSY_STAT) { if (time_before(jiffies, hwgroup->poll_timeout)) { + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler(drive, &promise_complete_pollfunc, HZ/100, NULL); return ide_started; /* continue polling... */ } hwgroup->poll_timeout = 0; printk(KERN_ERR "%s: completion timeout - still busy!\n", drive->name); - return ide_error(drive, "busy timeout", GET_STAT()); + return DRIVER(drive)->error(drive, "busy timeout", GET_STAT()); } hwgroup->poll_timeout = 0; #ifdef DEBUG_WRITE printk(KERN_DEBUG "%s: Write complete - end_request\n", drive->name); -#endif +#endif /* DEBUG_WRITE */ for (i = rq->nr_sectors; i > 0; ) { i -= rq->current_nr_sectors; - ide_end_request(1, hwgroup); + DRIVER(drive)->end_request(drive, 1); } return ide_stopped; } /* + * promise_multwrite() transfers a block of up to mcount sectors of data + * to a drive as part of a disk multiple-sector write operation. + * + * Returns 0 on success. + * + * Note that we may be called from two contexts - the do_rw_disk context + * and IRQ context. The IRQ can happen any time after we've output the + * full "mcount" number of sectors, so we must make sure we update the + * state _before_ we output the final part of the data! + */ +int promise_multwrite (ide_drive_t *drive, unsigned int mcount) +{ + ide_hwgroup_t *hwgroup = HWGROUP(drive); + struct request *rq = &hwgroup->wrq; + + do { + char *buffer; + int nsect = rq->current_nr_sectors; +#ifdef CONFIG_IDE_TASKFILE_IO + unsigned long flags; +#endif /* CONFIG_IDE_TASKFILE_IO */ + + if (nsect > mcount) + nsect = mcount; + mcount -= nsect; +#ifdef CONFIG_IDE_TASKFILE_IO + buffer = ide_map_buffer(rq, &flags); + rq->sector += nsect; +#else /* !CONFIG_IDE_TASKFILE_IO */ + buffer = rq->buffer; + + rq->sector += nsect; + rq->buffer += nsect << 9; +#endif /* CONFIG_IDE_TASKFILE_IO */ + rq->nr_sectors -= nsect; + rq->current_nr_sectors -= nsect; + + /* Do we move to the next bh after this? */ + if (!rq->current_nr_sectors) { + struct buffer_head *bh = rq->bh->b_reqnext; + + /* end early early we ran out of requests */ + if (!bh) { + mcount = 0; + } else { + rq->bh = bh; + rq->current_nr_sectors = bh->b_size >> 9; + rq->hard_cur_sectors = rq->current_nr_sectors; + rq->buffer = bh->b_data; + } + } + + /* + * Ok, we're all setup for the interrupt + * re-entering us on the last transfer. + */ + taskfile_output_data(drive, buffer, nsect<<7); +#ifdef CONFIG_IDE_TASKFILE_IO + ide_unmap_buffer(buffer, &flags); +#endif /* CONFIG_IDE_TASKFILE_IO */ + } while (mcount); + + return 0; +} + +/* * promise_write_pollfunc() is the handler for disk write completion polling. */ static ide_startstop_t promise_write_pollfunc (ide_drive_t *drive) @@ -426,24 +510,28 @@ if (IN_BYTE(IDE_NSECTOR_REG) != 0) { if (time_before(jiffies, hwgroup->poll_timeout)) { + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler (drive, &promise_write_pollfunc, HZ/100, NULL); return ide_started; /* continue polling... */ } hwgroup->poll_timeout = 0; printk(KERN_ERR "%s: write timed-out!\n",drive->name); - return ide_error (drive, "write timeout", GET_STAT()); + return DRIVER(drive)->error(drive, "write timeout", GET_STAT()); } /* * Now write out last 4 sectors and poll for not BUSY */ - ide_multwrite(drive, 4); + promise_multwrite(drive, 4); hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler(drive, &promise_complete_pollfunc, HZ/100, NULL); #ifdef DEBUG_WRITE printk(KERN_DEBUG "%s: Done last 4 sectors - status = %02x\n", drive->name, GET_STAT()); -#endif +#endif /* DEBUG_WRITE */ return ide_started; } @@ -463,16 +551,18 @@ printk(KERN_DEBUG "%s: promise_write: sectors(%ld-%ld), " "buffer=%p\n", drive->name, rq->sector, rq->sector + rq->nr_sectors - 1, rq->buffer); -#endif +#endif /* DEBUG_WRITE */ /* * If there are more than 4 sectors to transfer, do n-4 then go into * the polling strategy as defined above. */ if (rq->nr_sectors > 4) { - if (ide_multwrite(drive, rq->nr_sectors - 4)) + if (promise_multwrite(drive, rq->nr_sectors - 4)) return ide_stopped; hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler (drive, &promise_write_pollfunc, HZ/100, NULL); return ide_started; } else { @@ -480,14 +570,16 @@ * There are 4 or fewer sectors to transfer, do them all in one go * and wait for NOT BUSY. */ - if (ide_multwrite(drive, rq->nr_sectors)) + if (promise_multwrite(drive, rq->nr_sectors)) return ide_stopped; hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler(drive, &promise_complete_pollfunc, HZ/100, NULL); #ifdef DEBUG_WRITE printk(KERN_DEBUG "%s: promise_write: <= 4 sectors, " "status = %02x\n", drive->name, GET_STAT()); -#endif +#endif /* DEBUG_WRITE */ return ide_started; } } @@ -497,17 +589,40 @@ * already set up. It issues a READ or WRITE command to the Promise * controller, assuming LBA has been used to set up the block number. */ +#ifndef CONFIG_IDE_TASKFILE_IO ide_startstop_t do_pdc4030_io (ide_drive_t *drive, struct request *rq) { +#else /* CONFIG_IDE_TASKFILE_IO */ +ide_startstop_t do_pdc4030_io (ide_drive_t *drive, ide_task_t *task) +{ + struct request *rq = HWGROUP(drive)->rq; + task_struct_t *taskfile = (task_struct_t *) task->tfRegister; +#endif /* CONFIG_IDE_TASKFILE_IO */ ide_startstop_t startstop; unsigned long timeout; byte stat; +#ifdef CONFIG_IDE_TASKFILE_IO + if (IDE_CONTROL_REG) + OUT_BYTE(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */ + SELECT_MASK(HWIF(drive), drive, 0); + + OUT_BYTE(taskfile->feature, IDE_FEATURE_REG); + OUT_BYTE(taskfile->sector_count, IDE_NSECTOR_REG); + /* refers to number of sectors to transfer */ + OUT_BYTE(taskfile->sector_number, IDE_SECTOR_REG); + /* refers to sector offset or start sector */ + OUT_BYTE(taskfile->low_cylinder, IDE_LCYL_REG); + OUT_BYTE(taskfile->high_cylinder, IDE_HCYL_REG); + OUT_BYTE(taskfile->device_head, IDE_SELECT_REG); + OUT_BYTE(taskfile->command, IDE_COMMAND_REG); +#endif /* CONFIG_IDE_TASKFILE_IO */ + switch(rq->cmd) { - case READ: -#ifndef __TASKFILE__IO - OUT_BYTE(PROMISE_READ, IDE_COMMAND_REG); -#endif + case READ: +#ifndef CONFIG_IDE_TASKFILE_IO + OUT_BYTE(PROMISE_READ, IDE_COMMAND_REG); +#endif /* CONFIG_IDE_TASKFILE_IO */ /* * The card's behaviour is odd at this point. If the data is * available, DRQ will be true, and no interrupt will be @@ -518,49 +633,55 @@ * If neither of these is the case, we wait for up to 50ms (badly I'm * afraid!) until one of them is. */ - timeout = jiffies + HZ/20; /* 50ms wait */ - do { - stat=GET_STAT(); - if (stat & DRQ_STAT) { - udelay(1); - return promise_read_intr(drive); - } - if (IN_BYTE(IDE_SELECT_REG) & 0x01) { -#ifdef DEBUG_READ - printk(KERN_DEBUG "%s: read: waiting for interrupt\n", drive->name); -#endif - ide_set_handler(drive, &promise_read_intr, WAIT_CMD, NULL); - return ide_started; - } + timeout = jiffies + HZ/20; /* 50ms wait */ + do { + stat=GET_STAT(); + if (stat & DRQ_STAT) { udelay(1); - } while (time_before(jiffies, timeout)); + return promise_read_intr(drive); + } + if (IN_BYTE(IDE_SELECT_REG) & 0x01) { +#ifdef DEBUG_READ + printk(KERN_DEBUG "%s: read: waiting for " + "interrupt\n", drive->name); +#endif /* DEBUG_READ */ + ide_set_handler(drive, &promise_read_intr, WAIT_CMD, NULL); + return ide_started; + } + udelay(1); + } while (time_before(jiffies, timeout)); - printk(KERN_ERR "%s: reading: No DRQ and not waiting - Odd!\n", drive->name); - return ide_stopped; - case WRITE: -#ifndef __TASKFILE__IO - OUT_BYTE(PROMISE_WRITE, IDE_COMMAND_REG); -#endif - if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) { - printk(KERN_ERR "%s: no DRQ after issuing PROMISE_WRITE\n", drive->name); - return startstop; - } - if (!drive->unmask) - __cli(); /* local CPU only */ - HWGROUP(drive)->wrq = *rq; /* scratchpad */ - return promise_write(drive); - default: - printk("KERN_WARNING %s: bad command: %d\n", drive->name, rq->cmd); - ide_end_request(0, HWGROUP(drive)); - return ide_stopped; + printk(KERN_ERR "%s: reading: No DRQ and not " + "waiting - Odd!\n", drive->name); + return ide_stopped; + case WRITE: +#ifndef CONFIG_IDE_TASKFILE_IO + OUT_BYTE(PROMISE_WRITE, IDE_COMMAND_REG); +#endif /* CONFIG_IDE_TASKFILE_IO */ + if (ide_wait_stat(&startstop, drive, DATA_READY, + drive->bad_wstat, WAIT_DRQ)) { + printk(KERN_ERR "%s: no DRQ after issuing " + "PROMISE_WRITE\n", drive->name); + return startstop; + } + if (!drive->unmask) + local_irq_disable(); + HWGROUP(drive)->wrq = *rq; /* scratchpad */ + return promise_write(drive); + default: + printk("KERN_WARNING %s: bad command: %d\n", + drive->name, rq->cmd); + DRIVER(drive)->end_request(drive, 0); + return ide_stopped; } } -#ifdef __TASKFILE__IO +#ifdef CONFIG_IDE_TASKFILE_IO ide_startstop_t promise_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block) { - struct hd_drive_task_hdr taskfile; + struct hd_drive_task_hdr taskfile; + ide_task_t args; memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); @@ -571,8 +692,17 @@ taskfile.device_head = ((block>>8)&0x0f)|drive->select.all; taskfile.command = (rq->cmd==READ)?PROMISE_READ:PROMISE_WRITE; - do_taskfile(drive, &taskfile, NULL, NULL); - return do_pdc4030_io(drive, rq); + memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr)); + memcpy(args.hobRegister, NULL, sizeof(struct hd_drive_hob_hdr)); + args.command_type = ide_cmd_type_parser(&args); + args.prehandler = NULL; + args.handler = NULL; + args.posthandler = NULL; + args.rq = (struct request *) rq; + rq->special = NULL; + rq->special = (ide_task_t *)&args; + + return do_pdc4030_io(drive, &args); } -#endif +#endif /* CONFIG_IDE_TASKFILE_IO */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/pdcadma.c linux.19rc3-ac4/drivers/ide/pdcadma.c --- linux.19rc3/drivers/ide/pdcadma.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/pdcadma.c 2002-07-29 13:58:40.000000000 +0100 @@ -0,0 +1,106 @@ +/* + * linux/drivers/ide/pdcadma.c Version 0.01 June 21, 2001 + * + * Copyright (C) 1999-2000 Andre Hedrick + * May be copied or modified under the terms of the GNU General Public License + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "ide_modes.h" + +#undef DISPLAY_PDCADMA_TIMINGS + +#if defined(DISPLAY_PDCADMA_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static int pdcadma_get_info(char *, char **, off_t, int); +extern int (*pdcadma_display_info)(char *, char **, off_t, int); /* ide-proc.c */ +static struct pci_dev *bmide_dev; + +static int pdcadma_get_info (char *buffer, char **addr, off_t offset, int count) +{ + char *p = buffer; + u32 bibma = pci_resource_start(bmide_dev, 4); + + p += sprintf(p, "\n PDC ADMA %04X Chipset.\n", bmide_dev->device); + p += sprintf(p, "UDMA\n"); + p += sprintf(p, "PIO\n"); + + return p-buffer; /* => must be less than 4k! */ +} +#endif /* defined(DISPLAY_PDCADMA_TIMINGS) && defined(CONFIG_PROC_FS) */ + +byte pdcadma_proc = 0; + +#ifdef CONFIG_BLK_DEV_IDEDMA +/* + * pdcadma_dmaproc() initiates/aborts (U)DMA read/write operations on a drive. + */ + +int pdcadma_dmaproc (ide_dma_action_t func, ide_drive_t *drive) +{ + switch (func) { + case ide_dma_check: + func = ide_dma_off_quietly; + default: + break; + } + return ide_dmaproc(func, drive); /* use standard DMA stuff */ +} +#endif /* CONFIG_BLK_DEV_IDEDMA */ + +unsigned int __init pci_init_pdcadma (struct pci_dev *dev, const char *name) +{ +#if defined(DISPLAY_PDCADMA_TIMINGS) && defined(CONFIG_PROC_FS) + if (!pdcadma_proc) { + pdcadma_proc = 1; + bmide_dev = dev; + pdcadma_display_info = &pdcadma_get_info; + } +#endif /* DISPLAY_PDCADMA_TIMINGS && CONFIG_PROC_FS */ + return 0; +} + +unsigned int __init ata66_pdcadma (ide_hwif_t *hwif) +{ + return 1; +} + +void __init ide_init_pdcadma (ide_hwif_t *hwif) +{ + hwif->autodma = 0; + hwif->dma_base = 0; + +// hwif->tuneproc = &pdcadma_tune_drive; +// hwif->speedproc = &pdcadma_tune_chipset; + +// if (hwif->dma_base) { +// hwif->dmaproc = &pdcadma_dmaproc; +// hwif->autodma = 1; +// } +} + +void __init ide_dmacapable_pdcadma (ide_hwif_t *hwif, unsigned long dmabase) +{ +// ide_setup_dma(hwif, dmabase, 8); +} + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/piix.c linux.19rc3-ac4/drivers/ide/piix.c --- linux.19rc3/drivers/ide/piix.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/piix.c 2002-07-29 13:58:40.000000000 +0100 @@ -77,7 +77,6 @@ static int piix_get_info(char *, char **, off_t, int); extern int (*piix_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); static struct pci_dev *bmide_dev; static int piix_get_info (char *buffer, char **addr, off_t offset, int count) @@ -88,35 +87,36 @@ u8 c0 = 0, c1 = 0; u8 reg44 = 0, reg48 = 0, reg4a = 0, reg4b = 0, reg54 = 0, reg55 = 0; + p += sprintf(p, "\n "); switch(bmide_dev->device) { case PCI_DEVICE_ID_INTEL_82801BA_8: case PCI_DEVICE_ID_INTEL_82801BA_9: - case PCI_DEVICE_ID_INTEL_82801CA_10: - case PCI_DEVICE_ID_INTEL_82801CA_11: - case PCI_DEVICE_ID_INTEL_82801DB_11: - case PCI_DEVICE_ID_INTEL_82801E_11: - p += sprintf(p, "\n Intel PIIX4 Ultra 100 Chipset.\n"); + case PCI_DEVICE_ID_INTEL_82801CA_10: + case PCI_DEVICE_ID_INTEL_82801CA_11: + case PCI_DEVICE_ID_INTEL_82801DB_11: + case PCI_DEVICE_ID_INTEL_82801E_11: + p += sprintf(p, "Intel PIIX4 Ultra 100 Chipset.\n"); break; case PCI_DEVICE_ID_INTEL_82372FB_1: case PCI_DEVICE_ID_INTEL_82801AA_1: - p += sprintf(p, "\n Intel PIIX4 Ultra 66 Chipset.\n"); + p += sprintf(p, "Intel PIIX4 Ultra 66 Chipset.\n"); break; case PCI_DEVICE_ID_INTEL_82451NX: case PCI_DEVICE_ID_INTEL_82801AB_1: case PCI_DEVICE_ID_INTEL_82443MX_1: case PCI_DEVICE_ID_INTEL_82371AB: - p += sprintf(p, "\n Intel PIIX4 Ultra 33 Chipset.\n"); + p += sprintf(p, "Intel PIIX4 Ultra 33 Chipset.\n"); break; case PCI_DEVICE_ID_INTEL_82371SB_1: - p += sprintf(p, "\n Intel PIIX3 Chipset.\n"); + p += sprintf(p, "Intel PIIX3 Chipset.\n"); break; case PCI_DEVICE_ID_INTEL_82371MX: - p += sprintf(p, "\n Intel MPIIX Chipset.\n"); + p += sprintf(p, "Intel MPIIX Chipset.\n"); return p-buffer; /* => must be less than 4k! */ case PCI_DEVICE_ID_INTEL_82371FB_1: case PCI_DEVICE_ID_INTEL_82371FB_0: default: - p += sprintf(p, "\n Intel PIIX Chipset.\n"); + p += sprintf(p, "Intel PIIX Chipset.\n"); break; } @@ -139,22 +139,29 @@ c0 = inb_p((unsigned short)bibma + 0x02); c1 = inb_p((unsigned short)bibma + 0x0a); - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); - p += sprintf(p, " %sabled %sabled\n", + p += sprintf(p, "--------------- Primary Channel " + "---------------- Secondary Channel " + "-------------\n"); + p += sprintf(p, " %sabled " + " %sabled\n", (c0&0x80) ? "dis" : " en", (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s %s %s\n", + p += sprintf(p, "--------------- drive0 --------- drive1 " + "-------- drive0 ---------- drive1 ------\n"); + p += sprintf(p, "DMA enabled: %s %s " + " %s %s\n", (c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ", (c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " ); - p += sprintf(p, "UDMA enabled: %s %s %s %s\n", + p += sprintf(p, "UDMA enabled: %s %s " + " %s %s\n", (reg48&0x01) ? "yes" : "no ", (reg48&0x02) ? "yes" : "no ", (reg48&0x04) ? "yes" : "no ", (reg48&0x08) ? "yes" : "no " ); - p += sprintf(p, "UDMA enabled: %s %s %s %s\n", + p += sprintf(p, "UDMA enabled: %s %s " + " %s %s\n", ((reg54&0x11) && (reg55&0x10) && (reg4a&0x01)) ? "5" : ((reg54&0x11) && (reg4a&0x02)) ? "4" : ((reg54&0x11) && (reg4a&0x01)) ? "3" : @@ -198,12 +205,65 @@ byte piix_proc = 0; -extern char *ide_xfer_verbose (byte xfer_rate); -#if defined(CONFIG_BLK_DEV_IDEDMA) && defined(CONFIG_PIIX_TUNING) -/* - * - */ +static byte piix_ratemask (ide_drive_t *drive) +{ + struct pci_dev *dev = HWIF(drive)->pci_dev; + byte mode = 0x00; + + switch(dev->device) { + case PCI_DEVICE_ID_INTEL_82801BA_8: + case PCI_DEVICE_ID_INTEL_82801BA_9: + case PCI_DEVICE_ID_INTEL_82801CA_10: + case PCI_DEVICE_ID_INTEL_82801CA_11: + case PCI_DEVICE_ID_INTEL_82801E_11: + case PCI_DEVICE_ID_INTEL_82801DB_11: + mode |= 0x03; + break; + case PCI_DEVICE_ID_INTEL_82801AA_1: + case PCI_DEVICE_ID_INTEL_82372FB_1: + mode |= 0x02; + break; + case PCI_DEVICE_ID_INTEL_82371AB: + case PCI_DEVICE_ID_INTEL_82443MX_1: + case PCI_DEVICE_ID_INTEL_82451NX: + case PCI_DEVICE_ID_INTEL_82801AB_1: + mode |= 0x01; + case PCI_DEVICE_ID_INTEL_82371SB_1: + case PCI_DEVICE_ID_INTEL_82371FB_1: + case PCI_DEVICE_ID_INTEL_82371FB_0: + case PCI_DEVICE_ID_INTEL_82371MX: + default: + return (mode &= ~0xF8); + } + if (!eighty_ninty_three(drive)) { + mode &= ~0xFE; + mode |= 0x01; + } + return (mode &= ~0xF8); +} + +static byte piix_ratefilter (ide_drive_t *drive, byte speed) +{ +#ifdef CONFIG_BLK_DEV_IDEDMA + byte mode = piix_ratemask(drive); + + switch(mode) { + case 0x04: while (speed > XFER_UDMA_6) speed--; break; + case 0x03: while (speed > XFER_UDMA_5) speed--; break; + case 0x02: while (speed > XFER_UDMA_4) speed--; break; + case 0x01: while (speed > XFER_UDMA_2) speed--; break; + case 0x00: + default: while (speed > XFER_MW_DMA_2) speed--; break; + break; + } +#else + while (speed > XFER_PIO_4) speed--; +#endif /* CONFIG_BLK_DEV_IDEDMA */ +// printk("%s: mode == %02x speed == %02x\n", drive->name, mode, speed); + return speed; +} + static byte piix_dma_2_pio (byte xfer_rate) { switch(xfer_rate) { case XFER_UDMA_5: @@ -231,7 +291,6 @@ return 0; } } -#endif /* defined(CONFIG_BLK_DEV_IDEDMA) && (CONFIG_PIIX_TUNING) */ /* * Based on settings done by AMI BIOS @@ -239,12 +298,14 @@ */ static void piix_tune_drive (ide_drive_t *drive, byte pio) { + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + int is_slave = (&hwif->drives[1] == drive); + int master_port = hwif->channel ? 0x42 : 0x40; + int slave_port = 0x44; unsigned long flags; u16 master_data; byte slave_data; - int is_slave = (&HWIF(drive)->drives[1] == drive); - int master_port = HWIF(drive)->index ? 0x42 : 0x40; - int slave_port = 0x44; /* ISP RTC */ byte timings[][2] = { { 0, 0 }, { 0, 0 }, @@ -253,44 +314,40 @@ { 2, 3 }, }; pio = ide_get_best_pio_mode(drive, pio, 5, NULL); - pci_read_config_word(HWIF(drive)->pci_dev, master_port, &master_data); + spin_lock_irqsave(&io_request_lock, flags); + pci_read_config_word(dev, master_port, &master_data); if (is_slave) { master_data = master_data | 0x4000; if (pio > 1) /* enable PPE, IE and TIME */ master_data = master_data | 0x0070; - pci_read_config_byte(HWIF(drive)->pci_dev, slave_port, &slave_data); - slave_data = slave_data & (HWIF(drive)->index ? 0x0f : 0xf0); - slave_data = slave_data | (((timings[pio][0] << 2) | timings[pio][1]) - << (HWIF(drive)->index ? 4 : 0)); + pci_read_config_byte(dev, slave_port, &slave_data); + slave_data = slave_data & (hwif->channel ? 0x0f : 0xf0); + slave_data = slave_data | (((timings[pio][0] << 2) | timings[pio][1]) << (hwif->channel ? 4 : 0)); } else { master_data = master_data & 0xccf8; if (pio > 1) /* enable PPE, IE and TIME */ master_data = master_data | 0x0007; - master_data = master_data | (timings[pio][0] << 12) | - (timings[pio][1] << 8); + master_data = master_data | (timings[pio][0] << 12) | (timings[pio][1] << 8); } - save_flags(flags); - cli(); - pci_write_config_word(HWIF(drive)->pci_dev, master_port, master_data); + pci_write_config_word(dev, master_port, master_data); if (is_slave) - pci_write_config_byte(HWIF(drive)->pci_dev, slave_port, slave_data); - restore_flags(flags); + pci_write_config_byte(dev, slave_port, slave_data); + spin_unlock_irqrestore(&io_request_lock, flags); } -#if defined(CONFIG_BLK_DEV_IDEDMA) && defined(CONFIG_PIIX_TUNING) -static int piix_tune_chipset (ide_drive_t *drive, byte speed) +static int piix_tune_chipset (ide_drive_t *drive, byte xferspeed) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; byte maslave = hwif->channel ? 0x42 : 0x40; + byte speed = piix_ratefilter(drive, xferspeed); int a_speed = 3 << (drive->dn * 4); int u_flag = 1 << drive->dn; int v_flag = 0x01 << drive->dn; int w_flag = 0x10 << drive->dn; int u_speed = 0; - int err = 0; int sitre; short reg4042, reg44, reg48, reg4a, reg54; byte reg55; @@ -304,6 +361,7 @@ pci_read_config_byte(dev, 0x55, ®55); switch(speed) { +#ifdef CONFIG_BLK_DEV_IDEDMA case XFER_UDMA_4: case XFER_UDMA_2: u_speed = 2 << (drive->dn * 4); break; case XFER_UDMA_5: @@ -313,6 +371,11 @@ case XFER_MW_DMA_2: case XFER_MW_DMA_1: case XFER_SW_DMA_2: break; +#endif /* CONFIG_BLK_DEV_IDEDMA */ + case XFER_PIO_4: + case XFER_PIO_3: + case XFER_PIO_2: + case XFER_PIO_0: break; default: return -1; } @@ -335,8 +398,7 @@ } else { pci_write_config_word(dev, 0x54, reg54 & ~v_flag); } - } - if (speed < XFER_UDMA_0) { + } else { if (reg48 & u_flag) pci_write_config_word(dev, 0x48, reg48 & ~u_flag); if (reg4a & a_speed) @@ -348,64 +410,51 @@ } piix_tune_drive(drive, piix_dma_2_pio(speed)); - -#if PIIX_DEBUG_DRIVE_INFO - printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive->dn); -#endif /* PIIX_DEBUG_DRIVE_INFO */ - if (!drive->init_speed) - drive->init_speed = speed; - err = ide_config_drive_speed(drive, speed); - drive->current_speed = speed; - return err; + return (ide_config_drive_speed(drive, speed)); } +#ifdef CONFIG_BLK_DEV_IDEDMA static int piix_config_drive_for_dma (ide_drive_t *drive) { struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - byte speed; + byte mode = piix_ratemask(drive); + byte speed, tspeed, dma = 1; - byte udma_66 = eighty_ninty_three(drive); - int ultra100 = ((dev->device == PCI_DEVICE_ID_INTEL_82801BA_8) || - (dev->device == PCI_DEVICE_ID_INTEL_82801BA_9) || - (dev->device == PCI_DEVICE_ID_INTEL_82801CA_10) || - (dev->device == PCI_DEVICE_ID_INTEL_82801CA_11) || - (dev->device == PCI_DEVICE_ID_INTEL_82801DB_11) || - (dev->device == PCI_DEVICE_ID_INTEL_82801E_11)) ? 1 : 0; - int ultra66 = ((ultra100) || - (dev->device == PCI_DEVICE_ID_INTEL_82801AA_1) || - (dev->device == PCI_DEVICE_ID_INTEL_82372FB_1)) ? 1 : 0; - int ultra = ((ultra66) || - (dev->device == PCI_DEVICE_ID_INTEL_82371AB) || - (dev->device == PCI_DEVICE_ID_INTEL_82443MX_1) || - (dev->device == PCI_DEVICE_ID_INTEL_82451NX) || - (dev->device == PCI_DEVICE_ID_INTEL_82801AB_1)) ? 1 : 0; - - if ((id->dma_ultra & 0x0020) && (udma_66) && (ultra100)) { - speed = XFER_UDMA_5; - } else if ((id->dma_ultra & 0x0010) && (ultra)) { - speed = ((udma_66) && (ultra66)) ? XFER_UDMA_4 : XFER_UDMA_2; - } else if ((id->dma_ultra & 0x0008) && (ultra)) { - speed = ((udma_66) && (ultra66)) ? XFER_UDMA_3 : XFER_UDMA_1; - } else if ((id->dma_ultra & 0x0004) && (ultra)) { - speed = XFER_UDMA_2; - } else if ((id->dma_ultra & 0x0002) && (ultra)) { - speed = XFER_UDMA_1; - } else if ((id->dma_ultra & 0x0001) && (ultra)) { - speed = XFER_UDMA_0; - } else if (id->dma_mword & 0x0004) { - speed = XFER_MW_DMA_2; - } else if (id->dma_mword & 0x0002) { - speed = XFER_MW_DMA_1; - } else if (id->dma_1word & 0x0004) { - speed = XFER_SW_DMA_2; - } else { - speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL); + switch(mode) { + case 0x03: + if (id->dma_ultra & 0x0040) + { speed = XFER_UDMA_5; break; } + if (id->dma_ultra & 0x0020) + { speed = XFER_UDMA_5; break; } + case 0x02: + if (id->dma_ultra & 0x0010) + { speed = XFER_UDMA_4; break; } + if (id->dma_ultra & 0x0008) + { speed = XFER_UDMA_3; break; } + case 0x01: + if (id->dma_ultra & 0x0004) + { speed = XFER_UDMA_2; break; } + if (id->dma_ultra & 0x0002) + { speed = XFER_UDMA_1; break; } + if (id->dma_ultra & 0x0001) + { speed = XFER_UDMA_0; break; } + case 0x00: + if (id->dma_mword & 0x0004) + { speed = XFER_MW_DMA_2; break; } + if (id->dma_mword & 0x0002) + { speed = XFER_MW_DMA_1; break; } + if (id->dma_1word & 0x0004) + { speed = XFER_SW_DMA_2; break; } + default: + tspeed = ide_get_best_pio_mode(drive, 255, 5, NULL); + speed = piix_dma_2_pio(XFER_PIO_0 + tspeed); + dma = 0; + break; } (void) piix_tune_chipset(drive, speed); +// return ((int) (dma) ? ide_dma_on : ide_dma_off_quietly); return ((int) ((id->dma_ultra >> 11) & 7) ? ide_dma_on : ((id->dma_ultra >> 8) & 7) ? ide_dma_on : ((id->dma_mword >> 8) & 7) ? ide_dma_on : @@ -413,16 +462,13 @@ ide_dma_off_quietly); } -static void config_chipset_for_pio (ide_drive_t *drive) -{ - piix_tune_drive(drive, ide_get_best_pio_mode(drive, 255, 5, NULL)); -} - static int config_drive_xfer_rate (ide_drive_t *drive) { struct hd_driveid *id = drive->id; ide_dma_action_t dma_func = ide_dma_on; + drive->init_speed = 0; + if (id && (id->capability & 1) && HWIF(drive)->autodma) { /* Consult the list of known "bad" drives */ if (ide_dmaproc(ide_dma_bad_drive, drive)) { @@ -431,7 +477,7 @@ } dma_func = ide_dma_off_quietly; if (id->field_valid & 4) { - if (id->dma_ultra & 0x003F) { + if (id->dma_ultra & 0x007F) { /* Force if Capable UltraDMA */ dma_func = piix_config_drive_for_dma(drive); if ((id->field_valid & 2) && @@ -462,7 +508,7 @@ fast_ata_pio: dma_func = ide_dma_off_quietly; no_dma_set: - config_chipset_for_pio(drive); + piix_tune_drive(drive, 255); } return HWIF(drive)->dmaproc(dma_func, drive); } @@ -478,10 +524,28 @@ /* Other cases are done by generic IDE-DMA code. */ return ide_dmaproc(func, drive); } -#endif /* defined(CONFIG_BLK_DEV_IDEDMA) && (CONFIG_PIIX_TUNING) */ +#endif /* CONFIG_BLK_DEV_IDEDMA */ unsigned int __init pci_init_piix (struct pci_dev *dev, const char *name) { + switch(dev->device) { + case PCI_DEVICE_ID_INTEL_82801AA_1: + case PCI_DEVICE_ID_INTEL_82801AB_1: + case PCI_DEVICE_ID_INTEL_82801BA_8: + case PCI_DEVICE_ID_INTEL_82801BA_9: + case PCI_DEVICE_ID_INTEL_82801CA_10: + case PCI_DEVICE_ID_INTEL_82801CA_11: + case PCI_DEVICE_ID_INTEL_82801E_11: + case PCI_DEVICE_ID_INTEL_82801DB_11: + { + unsigned int extra = 0; + pci_read_config_dword(dev, 0x54, &extra); + pci_write_config_dword(dev, 0x54, extra|0x400); + } + default: + break; + } + #if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) if (!piix_proc) { piix_proc = 1; @@ -522,21 +586,32 @@ return; } + hwif->autodma = 0; hwif->tuneproc = &piix_tune_drive; + hwif->speedproc = &piix_tune_chipset; hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; if (!hwif->dma_base) return; -#ifndef CONFIG_BLK_DEV_IDEDMA - hwif->autodma = 0; -#else /* CONFIG_BLK_DEV_IDEDMA */ -#ifdef CONFIG_PIIX_TUNING +#ifdef CONFIG_BLK_DEV_IDEDMA + hwif->dmaproc = &piix_dmaproc; +#ifdef CONFIG_IDEDMA_AUTO if (!noautodma) hwif->autodma = 1; - hwif->dmaproc = &piix_dmaproc; - hwif->speedproc = &piix_tune_chipset; -#endif /* CONFIG_PIIX_TUNING */ +#endif /* CONFIG_IDEDMA_AUTO */ #endif /* !CONFIG_BLK_DEV_IDEDMA */ } + +extern void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d); + +void __init fixup_device_piix (struct pci_dev *dev, ide_pci_device_t *d) +{ + if (dev->resource[0].start != 0x01F1) + ide_register_xp_fix(dev); + + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d->name, dev->bus->number, dev->devfn); + ide_setup_pci_device(dev, d); +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/qd65xx.c linux.19rc3-ac4/drivers/ide/qd65xx.c --- linux.19rc3/drivers/ide/qd65xx.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/qd65xx.c 2002-07-29 13:58:40.000000000 +0100 @@ -94,10 +94,9 @@ { unsigned long flags; - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ - outb(content,reg); - restore_flags(flags); /* all CPUs */ + spin_lock_irqsave(&io_request_lock, flags); + OUT_BYTE(content,reg); + spin_unlock_irqrestore(&io_request_lock, flags); } byte __init qd_read_reg (byte reg) @@ -105,10 +104,9 @@ unsigned long flags; byte read; - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ - read = inb(reg); - restore_flags(flags); /* all CPUs */ + spin_lock_irqsave(&io_request_lock, flags); + read = IN_BYTE(reg); + spin_unlock_irqrestore(&io_request_lock, flags); return read; } @@ -313,13 +311,12 @@ byte readreg; unsigned long flags; - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ + spin_lock_irqsave(&io_request_lock, flags); savereg = inb_p(port); outb_p(QD_TESTVAL,port); /* safe value */ readreg = inb_p(port); - outb(savereg,port); - restore_flags(flags); /* all CPUs */ + OUT_BYTE(savereg,port); + spin_unlock_irqrestore(&io_request_lock, flags); if (savereg == QD_TESTVAL) { printk(KERN_ERR "Outch ! the probe for qd65xx isn't reliable !\n"); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/rz1000.c linux.19rc3-ac4/drivers/ide/rz1000.c --- linux.19rc3/drivers/ide/rz1000.c 2002-07-29 12:49:58.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/rz1000.c 2002-07-29 13:58:40.000000000 +0100 @@ -40,15 +40,16 @@ struct pci_dev *dev = hwif->pci_dev; hwif->chipset = ide_rz1000; - if (!pci_read_config_word (dev, 0x40, ®) - && !pci_write_config_word(dev, 0x40, reg & 0xdfff)) - { - printk("%s: disabled chipset read-ahead (buggy RZ1000/RZ1001)\n", hwif->name); + if (!pci_read_config_word (dev, 0x40, ®) && + !pci_write_config_word(dev, 0x40, reg & 0xdfff)) { + printk("%s: disabled chipset read-ahead " + "(buggy RZ1000/RZ1001)\n", hwif->name); } else { hwif->serialized = 1; hwif->drives[0].no_unmask = 1; hwif->drives[1].no_unmask = 1; - printk("%s: serialized, disabled unmasking (buggy RZ1000/RZ1001)\n", hwif->name); + printk("%s: serialized, disabled unmasking " + "(buggy RZ1000/RZ1001)\n", hwif->name); } } @@ -58,27 +59,29 @@ { unsigned short reg, h; - if (!pci_read_config_word (dev, PCI_COMMAND, ®) && !(reg & PCI_COMMAND_IO)) { + if (!pci_read_config_word (dev, PCI_COMMAND, ®) && + !(reg & PCI_COMMAND_IO)) { printk("%s: buggy IDE controller disabled (BIOS)\n", name); return; } - if (!pci_read_config_word (dev, 0x40, ®) - && !pci_write_config_word(dev, 0x40, reg & 0xdfff)) - { + if (!pci_read_config_word (dev, 0x40, ®) && + !pci_write_config_word(dev, 0x40, reg & 0xdfff)) { printk("IDE: disabled chipset read-ahead (buggy %s)\n", name); } else { for (h = 0; h < MAX_HWIFS; ++h) { ide_hwif_t *hwif = &ide_hwifs[h]; - if ((hwif->io_ports[IDE_DATA_OFFSET] == 0x1f0 || hwif->io_ports[IDE_DATA_OFFSET] == 0x170) - && (hwif->chipset == ide_unknown || hwif->chipset == ide_generic)) - { + if ((hwif->io_ports[IDE_DATA_OFFSET] == 0x1f0 || + hwif->io_ports[IDE_DATA_OFFSET] == 0x170) && + (hwif->chipset == ide_unknown || + hwif->chipset == ide_generic)) { hwif->chipset = ide_rz1000; hwif->serialized = 1; hwif->drives[0].no_unmask = 1; hwif->drives[1].no_unmask = 1; if (hwif->io_ports[IDE_DATA_OFFSET] == 0x170) hwif->channel = 1; - printk("%s: serialized, disabled unmasking (buggy %s)\n", hwif->name, name); + printk("%s: serialized, disabled unmasking " + "(buggy %s)\n", hwif->name, name); } } } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/serverworks.c linux.19rc3-ac4/drivers/ide/serverworks.c --- linux.19rc3/drivers/ide/serverworks.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/serverworks.c 2002-07-29 13:58:40.000000000 +0100 @@ -1,7 +1,5 @@ /* - * linux/drivers/ide/serverworks.c Version 0.3 26 Oct 2001 - * - * May be copied or modified under the terms of the GNU General Public License + * linux/drivers/ide/serverworks.c Version 0.6 05 April 2002 * * Copyright (C) 1998-2000 Michel Aubry * Copyright (C) 1998-2000 Andrzej Krzysztofowicz @@ -21,61 +19,7 @@ * *** The CSB5 does not provide ANY register *** * *** to detect 80-conductor cable presence. *** * - * - * here's the default lspci: - * - * 00:0f.1 IDE interface: ServerWorks: Unknown device 0211 (prog-if 8a [Master SecP PriP]) - * Control: I/O+ Mem- BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR+ FastB2B- - * Status: Cap- 66Mhz- UDF- FastB2B- ParErr- DEVSEL=medium >TAbort- SERR- TAbort- SERR- #include -static struct pci_dev *bmide_dev; +#define SVWKS_MAX_DEVS 2 +static struct pci_dev *svwks_devs[SVWKS_MAX_DEVS]; +static int n_svwks_devs; + static byte svwks_revision = 0; static int svwks_get_info(char *, char **, off_t, int); extern int (*svwks_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); static int svwks_get_info (char *buffer, char **addr, off_t offset, int count) { char *p = buffer; - u32 bibma = pci_resource_start(bmide_dev, 4); - u32 reg40, reg44; - u16 reg48, reg56; - u8 reg54, c0=0, c1=0; - - pci_read_config_dword(bmide_dev, 0x40, ®40); - pci_read_config_dword(bmide_dev, 0x44, ®44); - pci_read_config_word(bmide_dev, 0x48, ®48); - pci_read_config_byte(bmide_dev, 0x54, ®54); - pci_read_config_word(bmide_dev, 0x56, ®56); - - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - c0 = inb_p((unsigned short)bibma + 0x02); - c1 = inb_p((unsigned short)bibma + 0x0a); + int i; - switch(bmide_dev->device) { - case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE: - p += sprintf(p, "\n " - "ServerWorks CSB5 Chipset (rev %02x)\n", - svwks_revision); - break; - case PCI_DEVICE_ID_SERVERWORKS_OSB4IDE: - p += sprintf(p, "\n " - "ServerWorks OSB4 Chipset (rev %02x)\n", - svwks_revision); - break; - default: - p += sprintf(p, "\n " - "ServerWorks %04x Chipset (rev %02x)\n", - bmide_dev->device, svwks_revision); - break; - } + p += sprintf(p, "\n " + "ServerWorks OSB4/CSB5/CSB6\n"); - p += sprintf(p, "------------------------------- General Status ---------------------------------\n"); - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); - p += sprintf(p, " %sabled %sabled\n", - (c0&0x80) ? "dis" : " en", - (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s %s %s\n", + for (i = 0; i < n_svwks_devs; i++) { + struct pci_dev *dev = svwks_devs[i]; + u32 bibma = pci_resource_start(dev, 4); + u32 reg40, reg44; + u16 reg48, reg56; + u8 reg54, c0=0, c1=0; + + pci_read_config_dword(dev, 0x40, ®40); + pci_read_config_dword(dev, 0x44, ®44); + pci_read_config_word(dev, 0x48, ®48); + pci_read_config_byte(dev, 0x54, ®54); + pci_read_config_word(dev, 0x56, ®56); + + /* + * at that point bibma+0x2 et bibma+0xa are byte registers + * to investigate: + */ + c0 = inb_p((unsigned short)bibma + 0x02); + c1 = inb_p((unsigned short)bibma + 0x0a); + + switch(dev->device) { + case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE: + p += sprintf(p, "\n " + "ServerWorks CSB6 Chipset (rev %02x)\n", + svwks_revision); + break; + case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE: + p += sprintf(p, "\n " + "ServerWorks CSB5 Chipset (rev %02x)\n", + svwks_revision); + break; + case PCI_DEVICE_ID_SERVERWORKS_OSB4IDE: + p += sprintf(p, "\n " + "ServerWorks OSB4 Chipset (rev %02x)\n", + svwks_revision); + break; + default: + p += sprintf(p, "\n " + "ServerWorks %04x Chipset (rev %02x)\n", + dev->device, svwks_revision); + break; + } + + p += sprintf(p, "------------------------------- " + "General Status " + "---------------------------------\n"); + p += sprintf(p, "--------------- Primary Channel " + "---------------- Secondary Channel " + "-------------\n"); + p += sprintf(p, " %sabled %sabled\n", + (c0&0x80) ? "dis" : " en", + (c1&0x80) ? "dis" : " en"); + p += sprintf(p, "--------------- drive0 --------- drive1 " + "-------- drive0 ---------- drive1 ------\n"); + p += sprintf(p, "DMA enabled: %s %s" + " %s %s\n", (c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ", (c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " ); - p += sprintf(p, "UDMA enabled: %s %s %s %s\n", + p += sprintf(p, "UDMA enabled: %s %s" + " %s %s\n", (reg54 & 0x01) ? "yes" : "no ", (reg54 & 0x02) ? "yes" : "no ", (reg54 & 0x04) ? "yes" : "no ", (reg54 & 0x08) ? "yes" : "no " ); - p += sprintf(p, "UDMA enabled: %s %s %s %s\n", + p += sprintf(p, "UDMA enabled: %s %s" + " %s %s\n", ((reg56&0x0005)==0x0005)?"5": ((reg56&0x0004)==0x0004)?"4": ((reg56&0x0003)==0x0003)?"3": @@ -187,7 +153,8 @@ ((reg56&0x2000)==0x2000)?"2": ((reg56&0x1000)==0x1000)?"1": ((reg56&0xF000))?"?":"0"); - p += sprintf(p, "DMA enabled: %s %s %s %s\n", + p += sprintf(p, "DMA enabled: %s %s" + " %s %s\n", ((reg44&0x00002000)==0x00002000)?"2": ((reg44&0x00002100)==0x00002100)?"1": ((reg44&0x00007700)==0x00007700)?"0": @@ -205,7 +172,8 @@ ((reg44&0x00770000)==0x00770000)?"0": ((reg44&0x00FF0000)==0x00FF0000)?"X":"?"); - p += sprintf(p, "PIO enabled: %s %s %s %s\n", + p += sprintf(p, "PIO enabled: %s %s" + " %s %s\n", ((reg40&0x00002000)==0x00002000)?"4": ((reg40&0x00002200)==0x00002200)?"3": ((reg40&0x00003400)==0x00003400)?"2": @@ -226,19 +194,83 @@ ((reg40&0x00340000)==0x00340000)?"2": ((reg40&0x00470000)==0x00470000)?"1": ((reg40&0x005D0000)==0x005D0000)?"0":"?"); + + } + p += sprintf(p, "\n"); + return p-buffer; /* => must be less than 4k! */ } #endif /* defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) */ #define SVWKS_CSB5_REVISION_NEW 0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */ -byte svwks_proc = 0; +#define SVWKS_CSB6_REVISION 0xa0 /* min PCI_REVISION_ID for UDMA4 (A1.0) */ -extern char *ide_xfer_verbose (byte xfer_rate); +byte svwks_proc = 0; static struct pci_dev *isa_dev; -static int svwks_tune_chipset (ide_drive_t *drive, byte speed) +static byte svwks_ratemask (ide_drive_t *drive) +{ + struct pci_dev *dev = HWIF(drive)->pci_dev; + byte mode = 0; + + if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) { + u32 reg = 0; + mode &= ~0x01; + if (isa_dev) + pci_read_config_dword(isa_dev, 0x64, ®); + if ((reg & 0x00004000) == 0x00004000) + mode |= 0x01; + } else if (svwks_revision < SVWKS_CSB5_REVISION_NEW) { + mode |= 0x01; + } else if (svwks_revision >= SVWKS_CSB5_REVISION_NEW) { + u8 btr =0; + pci_read_config_byte(dev, 0x5A, &btr); + mode |= btr; + if (!eighty_ninty_three(drive)) + mode &= ~0x02; + } + if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) && + (!(PCI_FUNC(dev->devfn) & 1))) + mode = 0x02; + mode &= ~0xFC; + return (mode); +} + +static byte svwks_ratefilter (ide_drive_t *drive, byte speed) +{ +#ifdef CONFIG_BLK_DEV_IDEDMA + byte mode = svwks_ratemask(drive); + + switch(mode) { + case 0x04: while (speed > XFER_UDMA_6) speed--; break; + case 0x03: while (speed > XFER_UDMA_5) speed--; break; + case 0x02: while (speed > XFER_UDMA_4) speed--; break; + case 0x01: while (speed > XFER_UDMA_2) speed--; break; + case 0x00: + default: while (speed > XFER_MW_DMA_2) speed--; break; + break; + } +#else + while (speed > XFER_PIO_4) speed--; +#endif /* CONFIG_BLK_DEV_IDEDMA */ +// printk("%s: mode == %02x speed == %02x\n", drive->name, mode, speed); + return speed; +} + +static byte svwks_csb_check (struct pci_dev *dev) +{ + switch (dev->device) { + case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE: + case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE: + return 1; + default: + break; + } + return 0; +} +static int svwks_tune_chipset (ide_drive_t *drive, byte xferspeed) { byte udma_modes[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 }; byte dma_modes[] = { 0x77, 0x21, 0x20 }; @@ -247,12 +279,7 @@ ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; byte unit = (drive->select.b.unit & 0x01); - byte csb5 = (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) ? 1 : 0; - -#ifdef CONFIG_BLK_DEV_IDEDMA - unsigned long dma_base = hwif->dma_base; -#endif /* CONFIG_BLK_DEV_IDEDMA */ - int err; + byte csb5 = svwks_csb_check(dev); byte drive_pci = 0x00; byte drive_pci2 = 0x00; @@ -265,6 +292,7 @@ unsigned short csb5_pio = 0x00; byte pio = ide_get_best_pio_mode(drive, 255, 5, NULL); + byte speed = svwks_ratefilter(drive, xferspeed); switch (drive->dn) { case 0: drive_pci = 0x41; drive_pci2 = 0x45; break; @@ -281,11 +309,6 @@ pci_read_config_word(dev, 0x4A, &csb5_pio); pci_read_config_byte(dev, 0x54, &ultra_enable); -#ifdef DEBUG - printk("%s: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x ", - drive->name, ultra_timing, dma_timing, pio_timing); -#endif - pio_timing &= ~0xFF; dma_timing &= ~0xFF; ultra_timing &= ~(0x0F << (4*unit)); @@ -327,18 +350,6 @@ break; } -#ifdef DEBUG - printk("%s: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x ", - drive->name, ultra_timing, dma_timing, pio_timing); -#endif - -#if SVWKS_DEBUG_DRIVE_INFO - printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive->dn); -#endif /* SVWKS_DEBUG_DRIVE_INFO */ - - if (!drive->init_speed) - drive->init_speed = speed; - pci_write_config_byte(dev, drive_pci, pio_timing); if (csb5) pci_write_config_word(dev, 0x4A, csb5_pio); @@ -347,16 +358,9 @@ pci_write_config_byte(dev, drive_pci2, dma_timing); pci_write_config_byte(dev, drive_pci3, ultra_timing); pci_write_config_byte(dev, 0x54, ultra_enable); - - if (speed > XFER_PIO_4) - outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2); - else - outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2); #endif /* CONFIG_BLK_DEV_IDEDMA */ - err = ide_config_drive_speed(drive, speed); - drive->current_speed = speed; - return err; + return (ide_config_drive_speed(drive, speed)); } static void config_chipset_for_pio (ide_drive_t *drive) @@ -414,36 +418,54 @@ static int config_chipset_for_dma (ide_drive_t *drive) { struct hd_driveid *id = drive->id; - struct pci_dev *dev = HWIF(drive)->pci_dev; - byte udma_66 = eighty_ninty_three(drive); - int ultra66 = (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) ? 1 : 0; - int ultra100 = (ultra66 && svwks_revision >= SVWKS_CSB5_REVISION_NEW) ? 1 : 0; - byte speed; + byte mode = svwks_ratemask(drive); + byte speed, dma = 1; + + if (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) + mode = 0; - if ((id->dma_ultra & 0x0020) && (udma_66) && (ultra100)) { - speed = XFER_UDMA_5; - } else if (id->dma_ultra & 0x0010) { - speed = ((udma_66) && (ultra66)) ? XFER_UDMA_4 : XFER_UDMA_2; - } else if (id->dma_ultra & 0x0008) { - speed = ((udma_66) && (ultra66)) ? XFER_UDMA_3 : XFER_UDMA_1; - } else if (id->dma_ultra & 0x0004) { - speed = XFER_UDMA_2; - } else if (id->dma_ultra & 0x0002) { - speed = XFER_UDMA_1; - } else if (id->dma_ultra & 0x0001) { - speed = XFER_UDMA_0; - } else if (id->dma_mword & 0x0004) { - speed = XFER_MW_DMA_2; - } else if (id->dma_mword & 0x0002) { - speed = XFER_MW_DMA_1; - } else if (id->dma_1word & 0x0004) { - speed = XFER_SW_DMA_2; - } else { - speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL); + switch(mode) { + case 0x04: + if (id->dma_ultra & 0x0040) + { speed = XFER_UDMA_6; break; } + case 0x03: + if (id->dma_ultra & 0x0020) + { speed = XFER_UDMA_5; break; } + case 0x02: + if (id->dma_ultra & 0x0010) + { speed = XFER_UDMA_4; break; } + if (id->dma_ultra & 0x0008) + { speed = XFER_UDMA_3; break; } + case 0x01: + if (id->dma_ultra & 0x0004) + { speed = XFER_UDMA_2; break; } + if (id->dma_ultra & 0x0002) + { speed = XFER_UDMA_1; break; } + if (id->dma_ultra & 0x0001) + { speed = XFER_UDMA_0; break; } + if (id->dma_mword & 0x0004) + { speed = XFER_MW_DMA_2; break; } + if (id->dma_mword & 0x0002) + { speed = XFER_MW_DMA_1; break; } + if (id->dma_mword & 0x0001) + { speed = XFER_MW_DMA_0; break; } +#if 0 + if (id->dma_1word & 0x0004) + { speed = XFER_SW_DMA_2; break; } + if (id->dma_1word & 0x0002) + { speed = XFER_SW_DMA_1; break; } + if (id->dma_1word & 0x0001) + { speed = XFER_SW_DMA_0; break; } +#endif + default: + speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL); + dma = 0; + break; } (void) svwks_tune_chipset(drive, speed); +// return ((int) (dma) ? ide_dma_on : ide_dma_off_quietly); return ((int) ((id->dma_ultra >> 11) & 7) ? ide_dma_on : ((id->dma_ultra >> 8) & 7) ? ide_dma_on : ((id->dma_mword >> 8) & 7) ? ide_dma_on : @@ -456,6 +478,8 @@ struct hd_driveid *id = drive->id; ide_dma_action_t dma_func = ide_dma_on; + drive->init_speed = 0; + if (id && (id->capability & 1) && HWIF(drive)->autodma) { /* Consult the list of known "bad" drives */ if (ide_dmaproc(ide_dma_bad_drive, drive)) { @@ -496,6 +520,7 @@ dma_func = ide_dma_off_quietly; no_dma_set: config_chipset_for_pio(drive); + // HWIF(drive)->tuneproc(drive, 5); } return HWIF(drive)->dmaproc(dma_func, drive); } @@ -510,14 +535,14 @@ ide_hwif_t *hwif = HWIF(drive); unsigned long dma_base = hwif->dma_base; - if(inb(dma_base+0x02)&1) + if(IN_BYTE(dma_base+0x02)&1) { #if 0 int i; printk(KERN_ERR "Curious - OSB4 thinks the DMA is still running.\n"); for(i=0;i<10;i++) { - if(!(inb(dma_base+0x02)&1)) + if(!(IN_BYTE(dma_base+0x02)&1)) { printk(KERN_ERR "OSB4 now finished.\n"); break; @@ -570,35 +595,83 @@ } } - /* setup CSB5 : South Bridge and IDE */ - else if (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) { + /* setup CSB5/CSB6 : South Bridge and IDE option RAID */ + else if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) || + (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE)) { + /* Third Channel Test */ + if (!(PCI_FUNC(dev->devfn) & 1)) { +#if 1 + struct pci_dev * findev = NULL; + unsigned int reg4c = 0; + findev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, + PCI_DEVICE_ID_SERVERWORKS_CSB5, NULL); + if (findev) { + pci_read_config_dword(findev, 0x4C, ®4c); + reg4c &= ~0x000007FF; + reg4c |= 0x00000040; + reg4c |= 0x00000020; + pci_write_config_dword(findev, 0x4C, reg4c); + } +#endif + outb_p(0x06, 0x0c00); + dev->irq = inb_p(0x0c01); +#if 1 + /* WE need to figure out how to get the correct one */ + printk("%s: interrupt %d\n", name, dev->irq); + if (dev->irq != 0x0B) + dev->irq = 0x0B; +#endif + } else { + /* + * This is a device pin issue on CSB6. + * Since there will be a future raid mode, + * early versions of the chipset require the + * interrupt pin to be set, and it is a compatablity + * mode issue. + */ + dev->irq = 0; + } + pci_write_config_dword(dev, 0x40, 0x99999999); + pci_write_config_dword(dev, 0x44, 0xFFFFFFFF); /* setup the UDMA Control register * * 1. clear bit 6 to enable DMA * 2. enable DMA modes with bits 0-1 - * 00 : legacy - * 01 : udma2 - * 10 : udma2/udma4 - * 11 : udma2/udma4/udma5 + * 00 : legacy + * 01 : udma2 + * 10 : udma2/udma4 + * 11 : udma2/udma4/udma5 */ pci_read_config_byte(dev, 0x5A, &btr); btr &= ~0x40; - btr |= (svwks_revision >= SVWKS_CSB5_REVISION_NEW) ? 0x3 : 0x2; + if (!(PCI_FUNC(dev->devfn) & 1)) + btr |= 0x2; + else + btr |= (svwks_revision >= SVWKS_CSB5_REVISION_NEW) ? 0x3 : 0x2; pci_write_config_byte(dev, 0x5A, btr); } + svwks_devs[n_svwks_devs++] = dev; + #if defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) if (!svwks_proc) { svwks_proc = 1; - bmide_dev = dev; svwks_display_info = &svwks_get_info; } #endif /* DISPLAY_SVWKS_TIMINGS && CONFIG_PROC_FS */ - return 0; + + return (dev->irq) ? dev->irq : 0; +} + +static unsigned int __init ata66_svwks_svwks (ide_hwif_t *hwif) +{ +// struct pci_dev *dev = hwif->pci_dev; +// return 0; + return 1; } -/* On Dell PowerEdge servers with a CSB5, the top two bits of the subsystem - * device ID indicate presence of an 80-pin cable. +/* On Dell PowerEdge servers with a CSB5/CSB6, the top two bits + * of the subsystem device ID indicate presence of an 80-pin cable. * Bit 15 clear = secondary IDE channel does not have 80-pin cable. * Bit 15 set = secondary IDE channel has 80-pin cable. * Bit 14 clear = primary IDE channel does not have 80-pin cable. @@ -609,7 +682,8 @@ struct pci_dev *dev = hwif->pci_dev; if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL && dev->vendor == PCI_VENDOR_ID_SERVERWORKS && - dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) + (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE || + dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE)) return ((1 << (hwif->channel + 14)) & dev->subsystem_device) ? 1 : 0; return 0; @@ -636,6 +710,10 @@ { struct pci_dev *dev = hwif->pci_dev; + /* Server Works */ + if (dev->subsystem_vendor == PCI_VENDOR_ID_SERVERWORKS) + return ata66_svwks_svwks (hwif); + /* Dell PowerEdge */ if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL) return ata66_svwks_dell (hwif); @@ -654,22 +732,58 @@ hwif->tuneproc = &svwks_tune_drive; hwif->speedproc = &svwks_tune_chipset; - -#ifndef CONFIG_BLK_DEV_IDEDMA hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; hwif->autodma = 0; -#else /* CONFIG_BLK_DEV_IDEDMA */ - if (hwif->dma_base) { -#ifdef CONFIG_IDEDMA_AUTO - if (!noautodma) - hwif->autodma = 1; -#endif - hwif->dmaproc = &svwks_dmaproc; - } else { - hwif->autodma = 0; - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - } + + if (!hwif->dma_base) + return; + +#ifdef CONFIG_BLK_DEV_IDEDMA + hwif->dmaproc = &svwks_dmaproc; +# ifdef CONFIG_IDEDMA_AUTO + if (!noautodma) + hwif->autodma = 1; +# endif /* CONFIG_IDEDMA_AUTO */ #endif /* !CONFIG_BLK_DEV_IDEDMA */ } + +/* + * We allow the BM-DMA driver to only work on enabled interfaces. + */ +void __init ide_dmacapable_svwks (ide_hwif_t *hwif, unsigned long dmabase) +{ + struct pci_dev *dev = hwif->pci_dev; + if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) && + (!(PCI_FUNC(dev->devfn) & 1)) && (hwif->channel)) + return; +#if 0 + if (svwks_revision == (SVWKS_CSB5_REVISION_NEW + 1)) { + if (hwif->mate && hwif->mate->dma_base) { + dmabase = hwif->mate->dma_base - (hwif->channel ? 0 : 8); + } else { + dmabase = pci_resource_start(dev, 4); + if (!dmabase) { + printk("%s: dma_base is invalid (0x%04lx)\n", + hwif->name, dmabase); + dmabase = 0; + } + } + } +#endif + ide_setup_dma(hwif, dmabase, 8); +} + +extern void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d); + +void __init fixup_device_csb6 (struct pci_dev *dev, ide_pci_device_t *d) +{ + if (!(PCI_FUNC(dev->devfn) & 1)) { + d->bootable = NEVER_BOARD; + } + + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d->name, dev->bus->number, dev->devfn); + ide_setup_pci_device(dev, d); +} + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/sis5513.c linux.19rc3-ac4/drivers/ide/sis5513.c --- linux.19rc3/drivers/ide/sis5513.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/sis5513.c 2002-07-29 15:04:12.000000000 +0100 @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/sis5513.c Version 0.13 March 6, 2002 + * linux/drivers/ide/sis5513.c Version 0.14 July 24, 2002 * * Copyright (C) 1999-2000 Andre Hedrick * Copyright (C) 2002 Lionel Bouton , Maintainer @@ -16,13 +16,13 @@ * * Original tests and design on the SiS620/5513 chipset. * ATA100 tests and design on the SiS735/5513 chipset. - * ATA16/33 design from specs + * ATA16/33 support from specs + * ATA133 support for SiS961/962 by L.C. Chang */ /* * TODO: * - Get ridden of SisHostChipInfo[] completness dependancy. - * - Get ATA-133 datasheets, implement ATA-133 init code. * - Study drivers/ide/ide-timing.h. * - Are there pre-ATA_16 SiS5513 chips ? -> tune init code for them * or remove ATA_00 define @@ -53,7 +53,7 @@ #include "ide_modes.h" /* When DEBUG is defined it outputs initial PCI config register - values and changes made to them by the driver */ + values and changes made to them by the driver */ // #define DEBUG /* When BROKEN_LEVEL is defined it limits the DMA mode at boot time to its value */ @@ -71,44 +71,33 @@ #define ATA_66 0x03 #define ATA_100a 0x04 // SiS730 is ATA100 with ATA66 layout #define ATA_100 0x05 -#define ATA_133 0x06 +#define ATA_133a 0x06 // SiS961b with 133 support +#define ATA_133 0x07 // SiS962 /* 2/ variable holding the controller chipset family value */ -static unsigned char chipset_family; +static u8 chipset_family; /* * Debug code: following IDE config registers' changes */ #ifdef DEBUG -/* Copy of IDE Config registers 0x00 -> 0x57 - Fewer might be used depending on the actual chipset */ -static unsigned char ide_regs_copy[0x58]; - -static byte sis5513_max_config_register(void) { - switch(chipset_family) { - case ATA_00: - case ATA_16: return 0x4f; - case ATA_33: return 0x52; - case ATA_66: - case ATA_100a: - case ATA_100: - case ATA_133: - default: return 0x57; - } -} +/* Copy of IDE Config registers fewer will be used + * Some odd chipsets hang if unused registers are accessed + * -> We only access them in #DEBUG code (then we'll see if SiS did + * it right from day one) */ +static u8 ide_regs_copy[0xff]; /* Read config registers, print differences from previous read */ static void sis5513_load_verify_registers(struct pci_dev* dev, char* info) { int i; - byte reg_val; - byte changed=0; - byte max = sis5513_max_config_register(); + u8 reg_val; + u8 changed=0; printk("SIS5513: %s, changed registers:\n", info); - for(i=0; i<=max; i++) { + for(i=0; i<=0xff; i++) { pci_read_config_byte(dev, i, ®_val); if (reg_val != ide_regs_copy[i]) { - printk("%0#x: %0#x -> %0#x\n", + printk("%02x: %02x -> %02x\n", i, ide_regs_copy[i], reg_val); ide_regs_copy[i]=reg_val; changed=1; @@ -123,39 +112,26 @@ /* Load config registers, no printing */ static void sis5513_load_registers(struct pci_dev* dev) { int i; - byte max = sis5513_max_config_register(); - for(i=0; i<=max; i++) { + for(i=0; i<=0xff; i++) { pci_read_config_byte(dev, i, &(ide_regs_copy[i])); } } -/* Print a register */ -static void sis5513_print_register(int reg) { - printk(" %0#x:%0#x", reg, ide_regs_copy[reg]); -} - -/* Print valuable registers */ +/* Print config space registers a la "lspci -vxxx" */ static void sis5513_print_registers(struct pci_dev* dev, char* marker) { - int i; - byte max = sis5513_max_config_register(); + int i,j; sis5513_load_registers(dev); printk("SIS5513 %s\n", marker); - printk("SIS5513 dump:"); - for(i=0x00; i<0x40; i++) { - if ((i % 0x10)==0) printk("\n "); - sis5513_print_register(i); - } - for(; i<49; i++) { - sis5513_print_register(i); - } - printk("\n "); - for(; i<=max; i++) { - sis5513_print_register(i); + for(i=0; i<=0xf; i++) { + printk("SIS5513 dump: %d" "0:", i); + for(j=0; j<=0xf; j++) { + printk(" %02x", ide_regs_copy[(i<<16)+j]); + } + printk("\n"); } - printk("\n"); } #endif @@ -165,21 +141,30 @@ */ static const struct { const char *name; - unsigned short host_id; - unsigned char chipset_family; - unsigned char flags; + u16 host_id; + u8 chipset_family; + u8 flags; } SiSHostChipInfo[] = { - { "SiS750", PCI_DEVICE_ID_SI_750, ATA_100, SIS5513_LATENCY }, - { "SiS745", PCI_DEVICE_ID_SI_745, ATA_100, SIS5513_LATENCY }, - { "SiS740", PCI_DEVICE_ID_SI_740, ATA_100, SIS5513_LATENCY }, + { "SiS752", PCI_DEVICE_ID_SI_752, ATA_133, 0 }, + { "SiS751", PCI_DEVICE_ID_SI_751, ATA_133, 0 }, + { "SiS750", PCI_DEVICE_ID_SI_750, ATA_133, 0 }, + { "SiS748", PCI_DEVICE_ID_SI_748, ATA_133, 0 }, + { "SiS746", PCI_DEVICE_ID_SI_746, ATA_133, 0 }, + { "SiS745", PCI_DEVICE_ID_SI_745, ATA_133, 0 }, + { "SiS740", PCI_DEVICE_ID_SI_740, ATA_100, 0 }, { "SiS735", PCI_DEVICE_ID_SI_735, ATA_100, SIS5513_LATENCY }, { "SiS730", PCI_DEVICE_ID_SI_730, ATA_100a, SIS5513_LATENCY }, - { "SiS650", PCI_DEVICE_ID_SI_650, ATA_100, SIS5513_LATENCY }, - { "SiS645", PCI_DEVICE_ID_SI_645, ATA_100, SIS5513_LATENCY }, + { "SiS652", PCI_DEVICE_ID_SI_652, ATA_133, 0 }, + { "SiS651", PCI_DEVICE_ID_SI_651, ATA_133, 0 }, + { "SiS650", PCI_DEVICE_ID_SI_650, ATA_133, 0 }, + { "SiS648", PCI_DEVICE_ID_SI_648, ATA_133, 0 }, + { "SiS646", PCI_DEVICE_ID_SI_646, ATA_133, 0 }, + { "SiS645", PCI_DEVICE_ID_SI_645, ATA_133, 0 }, { "SiS635", PCI_DEVICE_ID_SI_635, ATA_100, SIS5513_LATENCY }, { "SiS640", PCI_DEVICE_ID_SI_640, ATA_66, SIS5513_LATENCY }, { "SiS630", PCI_DEVICE_ID_SI_630, ATA_66, SIS5513_LATENCY }, { "SiS620", PCI_DEVICE_ID_SI_620, ATA_66, SIS5513_LATENCY }, + { "SiS550", PCI_DEVICE_ID_SI_550, ATA_100a, 0}, { "SiS540", PCI_DEVICE_ID_SI_540, ATA_66, 0}, { "SiS530", PCI_DEVICE_ID_SI_530, ATA_66, 0}, { "SiS5600", PCI_DEVICE_ID_SI_5600, ATA_33, 0}, @@ -193,16 +178,64 @@ /* Cycle time bits and values vary accross chip dma capabilities These three arrays hold the register layout and the values to set. Indexed by chipset_family and (dma_mode - XFER_UDMA_0) */ -static byte cycle_time_offset[] = {0,0,5,4,4,0,0}; -static byte cycle_time_range[] = {0,0,2,3,3,4,4}; -static byte cycle_time_value[][XFER_UDMA_5 - XFER_UDMA_0 + 1] = { - {0,0,0,0,0,0}, /* no udma */ - {0,0,0,0,0,0}, /* no udma */ - {3,2,1,0,0,0}, - {7,5,3,2,1,0}, - {7,5,3,2,1,0}, - {11,7,5,4,2,1}, - {0,0,0,0,0,0} /* not yet known, ask SiS */ + +/* {ATA_00, ATA_16, ATA_33, ATA_66, ATA_100a, ATA_100, ATA_133} */ +static u8 cycle_time_offset[] = {0,0,5,4,4,0,0}; +static u8 cycle_time_range[] = {0,0,2,3,3,4,4}; +static u8 cycle_time_value[][XFER_UDMA_6 - XFER_UDMA_0 + 1] = { + {0,0,0,0,0,0,0}, /* no udma */ + {0,0,0,0,0,0,0}, /* no udma */ + {3,2,1,0,0,0,0}, /* ATA_33 */ + {7,5,3,2,1,0,0}, /* ATA_66 */ + {7,5,3,2,1,0,0}, /* ATA_100a (730 specific), differences are on cycle_time range and offset */ + {11,7,5,4,2,1,0}, /* ATA_100 */ + {15,10,7,5,3,2,1}, /* ATA_133a (earliest 691 southbridges) */ + {15,10,7,5,3,2,1}, /* ATA_133 */ +}; +/* CRC Valid Setup Time vary accross IDE clock setting 33/66/100/133 + See SiS962 data sheet for more detail */ +static u8 cvs_time_value[][XFER_UDMA_6 - XFER_UDMA_0 + 1] = { + {0,0,0,0,0,0,0}, /* no udma */ + {0,0,0,0,0,0,0}, /* no udma */ + {2,1,1,0,0,0,0}, + {4,3,2,1,0,0,0}, + {4,3,2,1,0,0,0}, + {6,4,3,1,1,1,0}, + {9,6,4,2,2,2,2}, + {9,6,4,2,2,2,2}, +}; +/* Initialize time, Active time, Recovery time vary accross + IDE clock settings. These 3 arrays hold the register value + for PIO0/1/2/3/4 and DMA0/1/2 mode in order */ +static u8 ini_time_value[][8] = { + {0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0}, + {2,1,0,0,0,1,0,0}, + {4,3,1,1,1,3,1,1}, + {4,3,1,1,1,3,1,1}, + {6,4,2,2,2,4,2,2}, + {9,6,3,3,3,6,3,3}, + {9,6,3,3,3,6,3,3}, +}; +static u8 act_time_value[][8] = { + {0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0}, + {9,9,9,2,2,7,2,2}, + {19,19,19,5,4,14,5,4}, + {19,19,19,5,4,14,5,4}, + {28,28,28,7,6,21,7,6}, + {38,38,38,10,9,28,10,9}, + {38,38,38,10,9,28,10,9}, +}; +static u8 rco_time_value[][8] = { + {0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0}, + {9,2,0,2,0,7,1,1}, + {19,5,1,5,2,16,3,2}, + {19,5,1,5,2,16,3,2}, + {30,9,3,9,4,25,6,4}, + {40,12,4,12,5,34,12,5}, + {40,12,4,12,5,34,12,5}, }; static struct pci_dev *host_dev = NULL; @@ -249,29 +282,38 @@ "7 CLK", "8 CLK", "9 CLK", "10 CLK", "11 CLK", "12 CLK", - "Reserved", "Reserved", - "Reserved", "Reserved" + "13 CLK", "14 CLK", + "15 CLK", "16 CLK" +}; + +static char* chipset_capability[] = { + "ATA", "ATA 16", + "ATA 33", "ATA 66", + "ATA 100", "ATA 100", + "ATA 133", "ATA 133" }; /* Generic add master or slave info function */ -static char* get_drives_info (char *buffer, byte pos) +static char* get_drives_info (char *buffer, u8 pos) { - byte reg00, reg01, reg10, reg11; /* timing registers */ + u8 reg00, reg01, reg10, reg11; /* timing registers */ char* p = buffer; /* Postwrite/Prefetch */ - pci_read_config_byte(bmide_dev, 0x4b, ®00); - p += sprintf(p, "Drive %d: Postwrite %s \t \t Postwrite %s\n", - pos, (reg00 & (0x10 << pos)) ? "Enabled" : "Disabled", - (reg00 & (0x40 << pos)) ? "Enabled" : "Disabled"); - p += sprintf(p, " Prefetch %s \t \t Prefetch %s\n", - (reg00 & (0x01 << pos)) ? "Enabled" : "Disabled", - (reg00 & (0x04 << pos)) ? "Enabled" : "Disabled"); - - pci_read_config_byte(bmide_dev, 0x40+2*pos, ®00); - pci_read_config_byte(bmide_dev, 0x41+2*pos, ®01); - pci_read_config_byte(bmide_dev, 0x44+2*pos, ®10); - pci_read_config_byte(bmide_dev, 0x45+2*pos, ®11); + if (chipset_family < ATA_133) { + pci_read_config_byte(bmide_dev, 0x4b, ®00); + p += sprintf(p, "Drive %d: Postwrite %s \t \t Postwrite %s\n", + pos, (reg00 & (0x10 << pos)) ? "Enabled" : "Disabled", + (reg00 & (0x40 << pos)) ? "Enabled" : "Disabled"); + p += sprintf(p, " Prefetch %s \t \t Prefetch %s\n", + (reg00 & (0x01 << pos)) ? "Enabled" : "Disabled", + (reg00 & (0x04 << pos)) ? "Enabled" : "Disabled"); + pci_read_config_byte(bmide_dev, 0x40+2*pos, ®00); + pci_read_config_byte(bmide_dev, 0x41+2*pos, ®01); + pci_read_config_byte(bmide_dev, 0x44+2*pos, ®10); + pci_read_config_byte(bmide_dev, 0x45+2*pos, ®11); + } + /* UDMA */ if (chipset_family >= ATA_33) { @@ -284,7 +326,8 @@ case ATA_33: p += sprintf(p, cycle_time[(reg01 & 0x60) >> 5]); break; case ATA_66: case ATA_100a: p += sprintf(p, cycle_time[(reg01 & 0x70) >> 4]); break; - case ATA_100: p += sprintf(p, cycle_time[reg01 & 0x0F]); break; + case ATA_100: + case ATA_133a: p += sprintf(p, cycle_time[reg01 & 0x0F]); break; case ATA_133: default: p += sprintf(p, "133+ ?"); break; } @@ -293,7 +336,8 @@ case ATA_33: p += sprintf(p, cycle_time[(reg11 & 0x60) >> 5]); break; case ATA_66: case ATA_100a: p += sprintf(p, cycle_time[(reg11 & 0x70) >> 4]); break; - case ATA_100: p += sprintf(p, cycle_time[reg11 & 0x0F]); break; + case ATA_100: + case ATA_133a: p += sprintf(p, cycle_time[reg11 & 0x0F]); break; case ATA_133: default: p += sprintf(p, "133+ ?"); break; } @@ -308,7 +352,8 @@ case ATA_33: case ATA_66: case ATA_100a: p += sprintf(p, active_time[reg01 & 0x07]); break; - case ATA_100: p += sprintf(p, active_time[(reg00 & 0x70) >> 4]); break; + case ATA_100: + case ATA_133a: p += sprintf(p, active_time[(reg00 & 0x70) >> 4]); break; case ATA_133: default: p += sprintf(p, "133+ ?"); break; } @@ -319,7 +364,8 @@ case ATA_33: case ATA_66: case ATA_100a: p += sprintf(p, active_time[reg11 & 0x07]); break; - case ATA_100: p += sprintf(p, active_time[(reg10 & 0x70) >> 4]); break; + case ATA_100: + case ATA_133a: p += sprintf(p, active_time[(reg10 & 0x70) >> 4]); break; case ATA_133: default: p += sprintf(p, "133+ ?"); break; } @@ -327,8 +373,10 @@ /* Data Recovery */ /* warning: may need (reg&0x07) for pre ATA66 chips */ - p += sprintf(p, " Data Recovery Time %s \t Data Recovery Time %s\n", - recovery_time[reg00 & 0x0f], recovery_time[reg10 & 0x0f]); + if (chipset_family < ATA_133) { + p += sprintf(p, " Data Recovery Time %s \t Data Recovery Time %s\n", + recovery_time[reg00 & 0x0f], recovery_time[reg10 & 0x0f]); + } return p; } @@ -347,7 +395,7 @@ static int sis_get_info (char *buffer, char **addr, off_t offset, int count) { char *p = buffer; - byte reg; + u8 reg; u16 reg2, reg3; p += sprintf(p, "\nSiS 5513 "); @@ -358,23 +406,34 @@ case ATA_66: p += sprintf(p, "Ultra 66"); break; case ATA_100a: case ATA_100: p += sprintf(p, "Ultra 100"); break; - case ATA_133: - default: p+= sprintf(p, "Ultra 133+"); break; + case ATA_133a: + case ATA_133: p += sprintf(p, "Ultra 133"); break; + default: p+= sprintf(p, "Unknown???"); break; } p += sprintf(p, " chipset\n"); - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); + p += sprintf(p, "--------------- Primary Channel " + "---------------- Secondary Channel " + "-------------\n"); /* Status */ pci_read_config_byte(bmide_dev, 0x4a, ®); + if (chipset_family == ATA_133) { + pci_read_config_word(bmide_dev, 0x50, ®2); + pci_read_config_word(bmide_dev, 0x52, ®3); + } p += sprintf(p, "Channel Status: "); if (chipset_family < ATA_66) { p += sprintf(p, "%s \t \t \t \t %s\n", (reg & 0x04) ? "On" : "Off", (reg & 0x02) ? "On" : "Off"); - } else { + } else if (chipset_family < ATA_133) { p += sprintf(p, "%s \t \t \t \t %s \n", (reg & 0x02) ? "On" : "Off", (reg & 0x04) ? "On" : "Off"); + } else { /* ATA_133 */ + p += sprintf(p, "%s \t \t \t \t %s \n", + (reg2 & 0x02) ? "On" : "Off", + (reg3 & 0x02) ? "On" : "Off"); } /* Operation Mode */ @@ -384,7 +443,11 @@ (reg & 0x04) ? "Native" : "Compatible"); /* 80-pin cable ? */ - if (chipset_family > ATA_33) { + if (chipset_family >= ATA_133) { + p += sprintf(p, "Cable Type: %s \t \t \t %s\n", + (reg2 & 0x01) ? cable_type[1] : cable_type[0], + (reg3 & 0x01) ? cable_type[1] : cable_type[0]); + } else if (chipset_family > ATA_33) { pci_read_config_byte(bmide_dev, 0x48, ®); p += sprintf(p, "Cable Type: %s \t \t \t %s\n", (reg & 0x10) ? cable_type[1] : cable_type[0], @@ -392,10 +455,12 @@ } /* Prefetch Count */ - pci_read_config_word(bmide_dev, 0x4c, ®2); - pci_read_config_word(bmide_dev, 0x4e, ®3); - p += sprintf(p, "Prefetch Count: %d \t \t \t \t %d\n", - reg2, reg3); + if (chipset_family < ATA_133) { + pci_read_config_word(bmide_dev, 0x4c, ®2); + pci_read_config_word(bmide_dev, 0x4e, ®3); + p += sprintf(p, "Prefetch Count: %d \t \t \t \t %d\n", + reg2, reg3); + } p = get_masters_info(p); p = get_slaves_info(p); @@ -405,8 +470,51 @@ #endif /* defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) */ -byte sis_proc = 0; -extern char *ide_xfer_verbose (byte xfer_rate); +u8 sis_proc = 0; + +static u8 sis5513_ratemask (ide_drive_t *drive) +{ + u8 mode = 0x00; + + switch(chipset_family) { + case ATA_133: + case ATA_133a: { mode |= 0x04; break; } + case ATA_100: + case ATA_100a: { mode |= 0x03; break; } + case ATA_66: { mode |= 0x02; break; } + case ATA_33: { mode |= 0x01; break; } + case ATA_16: + case ATA_00: + default: + return (mode &= ~0xF8); + } + if (!eighty_ninty_three(drive)) { + mode &= ~0xFE; + mode |= 0x01; + } + return (mode &= ~0xF8); +} + +static u8 sis5513_ratefilter (ide_drive_t *drive, u8 speed) +{ +#ifdef CONFIG_BLK_DEV_IDEDMA + u8 mode = sis5513_ratemask(drive); + + switch(mode) { + case 0x04: while (speed > XFER_UDMA_6) speed--; break; + case 0x03: while (speed > XFER_UDMA_5) speed--; break; + case 0x02: while (speed > XFER_UDMA_4) speed--; break; + case 0x01: while (speed > XFER_UDMA_2) speed--; break; + case 0x00: + default: while (speed > XFER_MW_DMA_2) speed--; break; + break; + } +#else + while (speed > XFER_PIO_4) speed--; +#endif /* CONFIG_BLK_DEV_IDEDMA */ +// printk("%s: mode == %02x speed == %02x\n", drive->name, mode, speed); + return speed; +} /* @@ -418,8 +526,8 @@ ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - byte reg4bh = 0; - byte rw_prefetch = (0x11 << drive->dn); + u8 reg4bh = 0; + u8 rw_prefetch = (0x11 << drive->dn); #ifdef DEBUG printk("SIS5513: config_drive_art_rwp, drive %d\n", drive->dn); @@ -439,15 +547,15 @@ /* Set per-drive active and recovery time */ -static void config_art_rwp_pio (ide_drive_t *drive, byte pio) +static void config_art_rwp_pio (ide_drive_t *drive, u8 pio) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - byte timing, drive_pci, test1, test2; + u8 timing, drive_pci, test1, test2; - unsigned short eide_pio_timing[6] = {600, 390, 240, 180, 120, 90}; - unsigned short xfer_pio = drive->id->eide_pio_modes; + u16 eide_pio_timing[6] = {600, 390, 240, 180, 120, 90}; + u16 xfer_pio = drive->id->eide_pio_modes; #ifdef DEBUG sis5513_load_verify_registers(dev, "config_drive_art_rwp_pio start"); @@ -477,12 +585,28 @@ drive->dn, pio, timing); #endif - switch(drive->dn) { - case 0: drive_pci = 0x40; break; - case 1: drive_pci = 0x42; break; - case 2: drive_pci = 0x44; break; - case 3: drive_pci = 0x46; break; - default: return; + /* In pre ATA_133 case, drives sit at 0x40 + 4*drive->dn */ + drive_pci = 0x40; + /* In SiS962 case drives sit at (0x40 or 0x70) + 8*drive->dn) */ + if (chipset_family >= ATA_133) { + u32 reg54h; + pci_read_config_dword(dev, 0x54, ®54h); + if (reg54h & 0x40000000) drive_pci = 0x70; + switch(drive->dn) { + case 0: drive_pci += 0x0; break; + case 1: drive_pci += 0x4; break; + case 2: drive_pci += 0x8; break; + case 3: drive_pci += 0xc; break; + default: return; + } + } else { + switch(drive->dn) { + case 0: drive_pci += 0x0; break; + case 1: drive_pci += 0x2; break; + case 2: drive_pci += 0x4; break; + case 3: drive_pci += 0x6; break; + default: return; + } } /* register layout changed with newer ATA100 chips */ @@ -503,9 +627,9 @@ } pci_write_config_byte(dev, drive_pci, test1); pci_write_config_byte(dev, drive_pci+1, test2); - } else { - switch(timing) { /* active recovery - v v */ + } else if (chipset_family < ATA_133) { + switch(timing) { /* active recovery + v v */ case 4: test1 = 0x30|0x01; break; case 3: test1 = 0x30|0x03; break; case 2: test1 = 0x40|0x04; break; @@ -513,6 +637,20 @@ default: break; } pci_write_config_byte(dev, drive_pci, test1); + } else { /* ATA_133 */ + u32 test3; + pci_read_config_dword(dev, drive_pci, &test3); + test3 &= 0xc0c00fff; + if (test3 & 0x08) { + test3 |= (unsigned long)ini_time_value[ATA_133-ATA_00][timing] << 12; + test3 |= (unsigned long)act_time_value[ATA_133-ATA_00][timing] << 16; + test3 |= (unsigned long)rco_time_value[ATA_133-ATA_00][timing] << 24; + } else { + test3 |= (unsigned long)ini_time_value[ATA_100-ATA_00][timing] << 12; + test3 |= (unsigned long)act_time_value[ATA_100-ATA_00][timing] << 16; + test3 |= (unsigned long)rco_time_value[ATA_100-ATA_00][timing] << 24; + } + pci_write_config_dword(dev, drive_pci, test3); } #ifdef DEBUG @@ -520,9 +658,9 @@ #endif } -static int config_chipset_for_pio (ide_drive_t *drive, byte pio) +static int config_chipset_for_pio (ide_drive_t *drive, u8 pio) { - byte speed; + u8 speed; switch(pio) { case 4: speed = XFER_PIO_4; break; @@ -533,62 +671,104 @@ } config_art_rwp_pio(drive, pio); - drive->current_speed = speed; return ide_config_drive_speed(drive, speed); } -static int sis5513_tune_chipset (ide_drive_t *drive, byte speed) +static int sis5513_tune_chipset (ide_drive_t *drive, u8 xferspeed) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - byte drive_pci, reg; + u8 drive_pci, reg; + u32 regdw; #ifdef DEBUG sis5513_load_verify_registers(dev, "sis5513_tune_chipset start"); printk("SIS5513: sis5513_tune_chipset, drive %d, speed %d\n", drive->dn, speed); #endif - switch(drive->dn) { - case 0: drive_pci = 0x40; break; - case 1: drive_pci = 0x42; break; - case 2: drive_pci = 0x44; break; - case 3: drive_pci = 0x46; break; - default: return ide_dma_off; - } #ifdef BROKEN_LEVEL #ifdef DEBUG - printk("SIS5513: BROKEN_LEVEL activated, speed=%d -> speed=%d\n", speed, BROKEN_LEVEL); + printk("SIS5513: BROKEN_LEVEL activated, speed=%d -> speed=%d\n", xferspeed, BROKEN_LEVEL); #endif - if (speed > BROKEN_LEVEL) speed = BROKEN_LEVEL; + if (xferspeed > BROKEN_LEVEL) xferspeed = BROKEN_LEVEL; #endif - pci_read_config_byte(dev, drive_pci+1, ®); - /* Disable UDMA bit for non UDMA modes on UDMA chips */ - if ((speed < XFER_UDMA_0) && (chipset_family > ATA_16)) { - reg &= 0x7F; - pci_write_config_byte(dev, drive_pci+1, reg); + u8 speed = sis5513_ratefilter(drive, xferspeed); + + /* See config_art_rwp_pio for drive pci config registers */ + drive_pci = 0x40; + if (chipset_family >= ATA_133) { + u32 reg54h; + pci_read_config_dword(dev, 0x54, ®54h); + if (reg54h & 0x40000000) drive_pci = 0x70; + switch(drive->dn) { + case 0: drive_pci += 0x0; break; + case 1: drive_pci += 0x4; break; + case 2: drive_pci += 0x8; break; + case 3: drive_pci += 0xc; break; + default: return ide_dma_off; + } + pci_read_config_dword(dev, (unsigned long)drive_pci, ®dw); + /* Disable UDMA bit for non UDMA modes on UDMA chips */ + if (speed < XFER_UDMA_0) { + regdw &= 0xfffffffb; + pci_write_config_dword(dev, (unsigned long)drive_pci, regdw); + } + + } else { + switch(drive->dn) { + case 0: drive_pci += 0x0; break; + case 1: drive_pci += 0x2; break; + case 2: drive_pci += 0x4; break; + case 3: drive_pci += 0x6; break; + default: return ide_dma_off; + } + pci_read_config_byte(dev, drive_pci+1, ®); + /* Disable UDMA bit for non UDMA modes on UDMA chips */ + if ((speed < XFER_UDMA_0) && (chipset_family > ATA_16)) { + reg &= 0x7F; + pci_write_config_byte(dev, drive_pci+1, reg); + } } /* Config chip for mode */ switch(speed) { #ifdef CONFIG_BLK_DEV_IDEDMA + case XFER_UDMA_6: case XFER_UDMA_5: case XFER_UDMA_4: case XFER_UDMA_3: case XFER_UDMA_2: case XFER_UDMA_1: case XFER_UDMA_0: - /* Force the UDMA bit on if we want to use UDMA */ - reg |= 0x80; - /* clean reg cycle time bits */ - reg &= ~((0xFF >> (8 - cycle_time_range[chipset_family])) - << cycle_time_offset[chipset_family]); - /* set reg cycle time bits */ - reg |= cycle_time_value[chipset_family-ATA_00][speed-XFER_UDMA_0] - << cycle_time_offset[chipset_family]; - pci_write_config_byte(dev, drive_pci+1, reg); + if (chipset_family >= ATA_133) { + regdw |= 0x04; + regdw &= 0xfffff00f; + /* check if ATA133 enable */ + if (regdw & 0x08) { + regdw |= (unsigned long)cycle_time_value[ATA_133-ATA_00][speed-XFER_UDMA_0] << 4; + regdw |= (unsigned long)cvs_time_value[ATA_133-ATA_00][speed-XFER_UDMA_0] << 8; + } else { + /* if ATA133 disable, we should not set speed above UDMA5 */ + if (speed > XFER_UDMA_5) + speed = XFER_UDMA_5; + regdw |= (unsigned long)cycle_time_value[ATA_100-ATA_00][speed-XFER_UDMA_0] << 4; + regdw |= (unsigned long)cvs_time_value[ATA_100-ATA_00][speed-XFER_UDMA_0] << 8; + } + pci_write_config_dword(dev, (unsigned long)drive_pci, regdw); + } else { + /* Force the UDMA bit on if we want to use UDMA */ + reg |= 0x80; + /* clean reg cycle time bits */ + reg &= ~((0xFF >> (8 - cycle_time_range[chipset_family])) + << cycle_time_offset[chipset_family]); + /* set reg cycle time bits */ + reg |= cycle_time_value[chipset_family-ATA_00][speed-XFER_UDMA_0] + << cycle_time_offset[chipset_family]; + pci_write_config_byte(dev, drive_pci+1, reg); + } break; case XFER_MW_DMA_2: case XFER_MW_DMA_1: @@ -605,14 +785,13 @@ case XFER_PIO_0: default: return((int) config_chipset_for_pio(drive, 0)); } - drive->current_speed = speed; #ifdef DEBUG sis5513_load_verify_registers(dev, "sis5513_tune_chipset end"); #endif return ((int) ide_config_drive_speed(drive, speed)); } -static void sis5513_tune_drive (ide_drive_t *drive, byte pio) +static void sis5513_tune_drive (ide_drive_t *drive, u8 pio) { (void) config_chipset_for_pio(drive, pio); } @@ -621,53 +800,56 @@ /* * ((id->hw_config & 0x4000|0x2000) && (HWIF(drive)->udma_four)) */ -static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) +static int config_chipset_for_dma (ide_drive_t *drive) { struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); - - byte speed = 0; - - byte unit = (drive->select.b.unit & 0x01); - byte udma_66 = eighty_ninty_three(drive); + u8 mode = sis5513_ratemask(drive); + u8 speed = 0; #ifdef DEBUG - printk("SIS5513: config_chipset_for_dma, drive %d, ultra %d\n", - drive->dn, ultra); + printk("SIS5513: config_chipset_for_dma, drive %d, ultra %x, udma_66 %x\n", + drive->dn, id->dma_ultra); #endif - if ((id->dma_ultra & 0x0020) && ultra && udma_66 && (chipset_family >= ATA_100a)) - speed = XFER_UDMA_5; - else if ((id->dma_ultra & 0x0010) && ultra && udma_66 && (chipset_family >= ATA_66)) - speed = XFER_UDMA_4; - else if ((id->dma_ultra & 0x0008) && ultra && udma_66 && (chipset_family >= ATA_66)) - speed = XFER_UDMA_3; - else if ((id->dma_ultra & 0x0004) && ultra && (chipset_family >= ATA_33)) - speed = XFER_UDMA_2; - else if ((id->dma_ultra & 0x0002) && ultra && (chipset_family >= ATA_33)) - speed = XFER_UDMA_1; - else if ((id->dma_ultra & 0x0001) && ultra && (chipset_family >= ATA_33)) - speed = XFER_UDMA_0; - else if (id->dma_mword & 0x0004) - speed = XFER_MW_DMA_2; - else if (id->dma_mword & 0x0002) - speed = XFER_MW_DMA_1; - else if (id->dma_mword & 0x0001) - speed = XFER_MW_DMA_0; - else if (id->dma_1word & 0x0004) - speed = XFER_SW_DMA_2; - else if (id->dma_1word & 0x0002) - speed = XFER_SW_DMA_1; - else if (id->dma_1word & 0x0001) - speed = XFER_SW_DMA_0; - else - return ((int) ide_dma_off_quietly); - - outb(inb(hwif->dma_base+2)|(1<<(5+unit)), hwif->dma_base+2); - + switch(mode) { + case 0x04: + if (id->dma_ultra & 0x0040) + { speed = XFER_UDMA_6; break; } + case 0x03: + if (id->dma_ultra & 0x0020) + { speed = XFER_UDMA_5; break; } + case 0x02: + if (id->dma_ultra & 0x0010) + { speed = XFER_UDMA_4; break; } + if (id->dma_ultra & 0x0008) + { speed = XFER_UDMA_3; break; } + case 0x01: + if (id->dma_ultra & 0x0004) + { speed = XFER_UDMA_2; break; } + if (id->dma_ultra & 0x0002) + { speed = XFER_UDMA_1; break; } + if (id->dma_ultra & 0x0001) + { speed = XFER_UDMA_0; break; } + case 0x00: + if (id->dma_mword & 0x0004) + { speed = XFER_MW_DMA_2; break; } + if (id->dma_mword & 0x0002) + { speed = XFER_MW_DMA_1; break; } + if (id->dma_mword & 0x0001) + { speed = XFER_MW_DMA_0; break; } + if (id->dma_1word & 0x0004) + { speed = XFER_SW_DMA_2; break; } + if (id->dma_1word & 0x0002) + { speed = XFER_SW_DMA_1; break; } + if (id->dma_1word & 0x0001) + { speed = XFER_SW_DMA_0; break; } + default: + return ((int) ide_dma_off_quietly); + } sis5513_tune_chipset(drive, speed); - return ((int) ((id->dma_ultra >> 11) & 7) ? ide_dma_on : + return ((int) ((id->dma_ultra >> 14) & 3) ? ide_dma_on : + ((id->dma_ultra >> 11) & 7) ? ide_dma_on : ((id->dma_ultra >> 8) & 7) ? ide_dma_on : ((id->dma_mword >> 8) & 7) ? ide_dma_on : ((id->dma_1word >> 8) & 7) ? ide_dma_on : @@ -679,7 +861,7 @@ struct hd_driveid *id = drive->id; ide_dma_action_t dma_func = ide_dma_off_quietly; - (void) config_chipset_for_pio(drive, 5); +// drive->init_speed = 0; if (id && (id->capability & 1) && HWIF(drive)->autodma) { /* Consult the list of known "bad" drives */ @@ -691,7 +873,7 @@ if (id->field_valid & 4) { if (id->dma_ultra & 0x003F) { /* Force if Capable UltraDMA */ - dma_func = config_chipset_for_dma(drive, 1); + dma_func = config_chipset_for_dma(drive); if ((id->field_valid & 2) && (dma_func != ide_dma_on)) goto try_dma_modes; @@ -701,14 +883,14 @@ if ((id->dma_mword & 0x0007) || (id->dma_1word & 0x0007)) { /* Force if Capable regular DMA modes */ - dma_func = config_chipset_for_dma(drive, 0); + dma_func = config_chipset_for_dma(drive); if (dma_func != ide_dma_on) goto no_dma_set; } } else if ((ide_dmaproc(ide_dma_good_drive, drive)) && (id->eide_dma_time > 150)) { /* Consult the list of known "good" drives */ - dma_func = config_chipset_for_dma(drive, 0); + dma_func = config_chipset_for_dma(drive); if (dma_func != ide_dma_on) goto no_dma_set; } else { @@ -718,7 +900,7 @@ fast_ata_pio: dma_func = ide_dma_off_quietly; no_dma_set: - (void) config_chipset_for_pio(drive, 5); + sis5513_tune_drive(drive, 5); } return HWIF(drive)->dmaproc(dma_func, drive); @@ -755,7 +937,32 @@ host_dev = host; chipset_family = SiSHostChipInfo[i].chipset_family; + + /* check 100/133 chipset family */ + if (chipset_family == ATA_133) { + u32 reg54h; + u16 reg02h; + pci_read_config_dword(dev, 0x54, ®54h); + pci_write_config_dword(dev, 0x54, (reg54h & 0x7fffffff)); + pci_read_config_word(dev, 0x02, ®02h); + pci_write_config_dword(dev, 0x54, reg54h); + /* devid 5518 here means SiS962 or later + which supports ATA133 */ + if (reg02h != 0x5518) { + byte reg49h; + unsigned long sbrev; + /* SiS961 family */ + outl(0x80001008, 0x0cf8); + sbrev = inl(0x0cfc); + pci_read_config_byte(dev, 0x49, ®49h); + if (((sbrev & 0xff) == 0x10) && (reg49h & 0x80)) + chipset_family = ATA_133a; + else + chipset_family = ATA_100; + } + } printk(SiSHostChipInfo[i].name); + printk(" %s controller", chipset_capability[chipset_family]); printk("\n"); #ifdef DEBUG @@ -772,9 +979,19 @@ 1/ tell IDE channels to operate in Compabitility mode only 2/ tell old chips to allow per drive IDE timings */ if (host_dev) { - byte reg; + u8 reg; + u16 regw; switch(chipset_family) { case ATA_133: + /* SiS962 operation mode */ + pci_read_config_word(dev, 0x50, ®w); + if (regw & 0x08) + pci_write_config_word(dev, 0x50, regw&0xfff7); + pci_read_config_word(dev, 0x52, ®w); + if (regw & 0x08) + pci_write_config_word(dev, 0x52, regw&0xfff7); + break; + case ATA_133a: case ATA_100: /* Set compatibility bit */ pci_read_config_byte(dev, 0x49, ®); @@ -824,11 +1041,17 @@ unsigned int __init ata66_sis5513 (ide_hwif_t *hwif) { - byte reg48h = 0, ata66 = 0; - byte mask = hwif->channel ? 0x20 : 0x10; - pci_read_config_byte(hwif->pci_dev, 0x48, ®48h); + byte ata66 = 0; - if (chipset_family >= ATA_66) { + if (chipset_family >= ATA_133) { + u16 regw = 0; + u16 reg_addr = hwif->channel ? 0x52: 0x50; + pci_read_config_word(hwif->pci_dev, reg_addr, ®w); + ata66 = (regw & 0x8000) ? 0 : 1; + } else if (chipset_family >= ATA_66) { + byte reg48h = 0; + byte mask = hwif->channel ? 0x20 : 0x10; + pci_read_config_byte(hwif->pci_dev, 0x48, ®48h); ata66 = (reg48h & mask) ? 0 : 1; } return ata66; @@ -841,21 +1064,36 @@ hwif->tuneproc = &sis5513_tune_drive; hwif->speedproc = &sis5513_tune_chipset; +// hwif->drives[0].autotune = 1; +// hwif->drives[1].autotune = 1; + hwif->autodma = 0; if (!(hwif->dma_base)) return; - if (host_dev) { #ifdef CONFIG_BLK_DEV_IDEDMA - if (chipset_family > ATA_16) { - hwif->autodma = noautodma ? 0 : 1; + if (host_dev) { + if (chipset_family > ATA_16) hwif->dmaproc = &sis5513_dmaproc; - } else { -#endif + else hwif->autodma = 0; -#ifdef CONFIG_BLK_DEV_IDEDMA - } -#endif } +# ifdef CONFIG_IDEDMA_AUTO + if (!noautodma) + hwif->autodma = 1; +# endif +#endif return; } + +extern void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d); + +void __init fixup_device_sis5513 (struct pci_dev *dev, ide_pci_device_t *d) +{ + if (dev->resource[0].start != 0x01F1) + ide_register_xp_fix(dev); + + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d->name, dev->bus->number, dev->devfn); + ide_setup_pci_device(dev, d); +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/sl82c105.c linux.19rc3-ac4/drivers/ide/sl82c105.c --- linux.19rc3/drivers/ide/sl82c105.c 2002-07-29 12:49:58.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/sl82c105.c 2002-07-29 13:58:40.000000000 +0100 @@ -26,8 +26,6 @@ #include "ide_modes.h" -extern char *ide_xfer_verbose (byte xfer_rate); - /* * Convert a PIO mode and cycle time to the required on/off * times for the interface. This has protection against run-away @@ -243,7 +241,7 @@ unsigned int rev; byte dma_state; - dma_state = inb(dma_base + 2); + dma_state = IN_BYTE(dma_base + 2); rev = sl82c105_bridge_revision(hwif->pci_dev); if (rev <= 5) { hwif->autodma = 0; @@ -256,7 +254,7 @@ dma_state |= 0x60; hwif->autodma = 1; } - outb(dma_state, dma_base + 2); + OUT_BYTE(dma_state, dma_base + 2); hwif->dmaproc = NULL; ide_setup_dma(hwif, dma_base, 8); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/slc90e66.c linux.19rc3-ac4/drivers/ide/slc90e66.c --- linux.19rc3/drivers/ide/slc90e66.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/slc90e66.c 2002-07-29 13:58:40.000000000 +0100 @@ -60,7 +60,6 @@ static int slc90e66_get_info(char *, char **, off_t, int); extern int (*slc90e66_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); static struct pci_dev *bmide_dev; static int slc90e66_get_info (char *buffer, char **addr, off_t offset, int count) @@ -95,22 +94,29 @@ #endif p += sprintf(p, " SLC90E66 Chipset.\n"); - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); - p += sprintf(p, " %sabled %sabled\n", + p += sprintf(p, "--------------- Primary Channel " + "---------------- Secondary Channel " + "-------------\n"); + p += sprintf(p, " %sabled " + " %sabled\n", (c0&0x80) ? "dis" : " en", (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s %s %s\n", + p += sprintf(p, "--------------- drive0 --------- drive1 " + "-------- drive0 ---------- drive1 ------\n"); + p += sprintf(p, "DMA enabled: %s %s " + " %s %s\n", (c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ", (c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " ); - p += sprintf(p, "UDMA enabled: %s %s %s %s\n", + p += sprintf(p, "UDMA enabled: %s %s " + " %s %s\n", (reg48&0x01) ? "yes" : "no ", (reg48&0x02) ? "yes" : "no ", (reg48&0x04) ? "yes" : "no ", (reg48&0x08) ? "yes" : "no " ); - p += sprintf(p, "UDMA enabled: %s %s %s %s\n", + p += sprintf(p, "UDMA enabled: %s %s " + " %s %s\n", ((reg4a&0x04)==0x04) ? "4" : ((reg4a&0x03)==0x03) ? "3" : (reg4a&0x02) ? "2" : @@ -150,12 +156,40 @@ byte slc90e66_proc = 0; -extern char *ide_xfer_verbose (byte xfer_rate); +static byte slc90e66_ratemask (ide_drive_t *drive) +{ + byte mode = 0x00; + + mode |= 0x02; + if (!eighty_ninty_three(drive)) { + mode &= ~0xFE; + mode |= 0x01; + } + return (mode &= ~0xF8); +} + +static byte slc90e66_ratefilter (ide_drive_t *drive, byte speed) +{ #ifdef CONFIG_BLK_DEV_IDEDMA -/* - * - */ + byte mode = slc90e66_ratemask(drive); + + switch(mode) { + case 0x04: // while (speed > XFER_UDMA_6) speed--; break; + case 0x03: // while (speed > XFER_UDMA_5) speed--; break; + case 0x02: while (speed > XFER_UDMA_4) speed--; break; + case 0x01: while (speed > XFER_UDMA_2) speed--; break; + case 0x00: + default: while (speed > XFER_MW_DMA_2) speed--; break; + break; + } +#else + while (speed > XFER_PIO_4) speed--; +#endif /* CONFIG_BLK_DEV_IDEDMA */ +// printk("%s: mode == %02x speed == %02x\n", drive->name, mode, speed); + return speed; +} + static byte slc90e66_dma_2_pio (byte xfer_rate) { switch(xfer_rate) { case XFER_UDMA_4: @@ -182,7 +216,6 @@ return 0; } } -#endif /* CONFIG_BLK_DEV_IDEDMA */ /* * Based on settings done by AMI BIOS @@ -190,12 +223,14 @@ */ static void slc90e66_tune_drive (ide_drive_t *drive, byte pio) { + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + int is_slave = (&hwif->drives[1] == drive); + int master_port = hwif->channel ? 0x42 : 0x40; + int slave_port = 0x44; unsigned long flags; u16 master_data; byte slave_data; - int is_slave = (&HWIF(drive)->drives[1] == drive); - int master_port = HWIF(drive)->index ? 0x42 : 0x40; - int slave_port = 0x44; /* ISP RTC */ byte timings[][2] = { { 0, 0 }, { 0, 0 }, @@ -204,42 +239,38 @@ { 2, 3 }, }; pio = ide_get_best_pio_mode(drive, pio, 5, NULL); - pci_read_config_word(HWIF(drive)->pci_dev, master_port, &master_data); + spin_lock_irqsave(&io_request_lock, flags); + pci_read_config_word(dev, master_port, &master_data); if (is_slave) { master_data = master_data | 0x4000; if (pio > 1) /* enable PPE, IE and TIME */ master_data = master_data | 0x0070; - pci_read_config_byte(HWIF(drive)->pci_dev, slave_port, &slave_data); - slave_data = slave_data & (HWIF(drive)->index ? 0x0f : 0xf0); - slave_data = slave_data | ((timings[pio][0] << 2) | (timings[pio][1] - << (HWIF(drive)->index ? 4 : 0))); + pci_read_config_byte(dev, slave_port, &slave_data); + slave_data = slave_data & (hwif->channel ? 0x0f : 0xf0); + slave_data = slave_data | (((timings[pio][0] << 2) | timings[pio][1]) << (hwif->channel ? 4 : 0)); } else { master_data = master_data & 0xccf8; if (pio > 1) /* enable PPE, IE and TIME */ master_data = master_data | 0x0007; - master_data = master_data | (timings[pio][0] << 12) | - (timings[pio][1] << 8); + master_data = master_data | (timings[pio][0] << 12) | (timings[pio][1] << 8); } - save_flags(flags); - cli(); - pci_write_config_word(HWIF(drive)->pci_dev, master_port, master_data); + pci_write_config_word(dev, master_port, master_data); if (is_slave) - pci_write_config_byte(HWIF(drive)->pci_dev, slave_port, slave_data); - restore_flags(flags); + pci_write_config_byte(dev, slave_port, slave_data); + spin_unlock_irqrestore(&io_request_lock, flags); } -#ifdef CONFIG_BLK_DEV_IDEDMA -static int slc90e66_tune_chipset (ide_drive_t *drive, byte speed) +static int slc90e66_tune_chipset (ide_drive_t *drive, byte xferspeed) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; byte maslave = hwif->channel ? 0x42 : 0x40; + byte speed = slc90e66_ratefilter(drive, xferspeed); int a_speed = 7 << (drive->dn * 4); int u_flag = 1 << drive->dn; int u_speed = 0; - int err = 0; int sitre; short reg4042, reg44, reg48, reg4a; @@ -250,6 +281,7 @@ pci_read_config_word(dev, 0x4a, ®4a); switch(speed) { +#ifdef CONFIG_BLK_DEV_IDEDMA case XFER_UDMA_4: u_speed = 4 << (drive->dn * 4); break; case XFER_UDMA_3: u_speed = 3 << (drive->dn * 4); break; case XFER_UDMA_2: u_speed = 2 << (drive->dn * 4); break; @@ -258,9 +290,12 @@ case XFER_MW_DMA_2: case XFER_MW_DMA_1: case XFER_SW_DMA_2: break; -#if 0 /* allow PIO modes */ +#endif /* CONFIG_BLK_DEV_IDEDMA */ + case XFER_PIO_4: + case XFER_PIO_3: + case XFER_PIO_2: + case XFER_PIO_0: break; default: return -1; -#endif } if (speed >= XFER_UDMA_0) { @@ -271,8 +306,7 @@ pci_read_config_word(dev, 0x4a, ®4a); pci_write_config_word(dev, 0x4a, reg4a|u_speed); } - } - if (speed < XFER_UDMA_0) { + } else { if (reg48 & u_flag) pci_write_config_word(dev, 0x48, reg48 & ~u_flag); if (reg4a & a_speed) @@ -280,53 +314,45 @@ } slc90e66_tune_drive(drive, slc90e66_dma_2_pio(speed)); - -#if SLC90E66_DEBUG_DRIVE_INFO - printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive->dn); -#endif /* SLC90E66_DEBUG_DRIVE_INFO */ - if (!drive->init_speed) - drive->init_speed = speed; - err = ide_config_drive_speed(drive, speed); - drive->current_speed = speed; - return err; + return (ide_config_drive_speed(drive, speed)); } +#ifdef CONFIG_BLK_DEV_IDEDMA static int slc90e66_config_drive_for_dma (ide_drive_t *drive) { struct hd_driveid *id = drive->id; - int ultra = 1; - byte speed = 0; - byte udma_66 = eighty_ninty_three(drive); - -#if 1 /* allow PIO modes */ - if (!HWIF(drive)->autodma) { - speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL); - (void) slc90e66_tune_chipset(drive, speed); - return ((int) ide_dma_off_quietly); - } -#endif - if ((id->dma_ultra & 0x0010) && (ultra)) { - speed = (udma_66) ? XFER_UDMA_4 : XFER_UDMA_2; - } else if ((id->dma_ultra & 0x0008) && (ultra)) { - speed = (udma_66) ? XFER_UDMA_3 : XFER_UDMA_1; - } else if ((id->dma_ultra & 0x0004) && (ultra)) { - speed = XFER_UDMA_2; - } else if ((id->dma_ultra & 0x0002) && (ultra)) { - speed = XFER_UDMA_1; - } else if ((id->dma_ultra & 0x0001) && (ultra)) { - speed = XFER_UDMA_0; - } else if (id->dma_mword & 0x0004) { - speed = XFER_MW_DMA_2; - } else if (id->dma_mword & 0x0002) { - speed = XFER_MW_DMA_1; - } else if (id->dma_1word & 0x0004) { - speed = XFER_SW_DMA_2; - } else { - speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL); + byte mode = slc90e66_ratemask(drive); + byte speed, tspeed, dma = 1; + + switch(mode) { + case 0x02: + if (id->dma_ultra & 0x0010) + { speed = XFER_UDMA_4; break; } + if (id->dma_ultra & 0x0008) + { speed = XFER_UDMA_3; break; } + case 0x01: + if (id->dma_ultra & 0x0004) + { speed = XFER_UDMA_2; break; } + if (id->dma_ultra & 0x0002) + { speed = XFER_UDMA_1; break; } + if (id->dma_ultra & 0x0001) + { speed = XFER_UDMA_0; break; } + case 0x00: + if (id->dma_mword & 0x0004) + { speed = XFER_MW_DMA_2; break; } + if (id->dma_mword & 0x0002) + { speed = XFER_MW_DMA_1; break; } + if (id->dma_1word & 0x0004) + { speed = XFER_SW_DMA_2; break; } + default: + tspeed = ide_get_best_pio_mode(drive, 255, 5, NULL); + speed = slc90e66_dma_2_pio(XFER_PIO_0 + tspeed); + dma = 0; + break; } (void) slc90e66_tune_chipset(drive, speed); - +// return ((int) (dma) ? ide_dma_on : ide_dma_off_quietly); return ((int) ((id->dma_ultra >> 11) & 7) ? ide_dma_on : ((id->dma_ultra >> 8) & 7) ? ide_dma_on : ((id->dma_mword >> 8) & 7) ? ide_dma_on : @@ -334,11 +360,62 @@ ide_dma_off_quietly); } +static int config_drive_xfer_rate (ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + ide_dma_action_t dma_func = ide_dma_on; + + drive->init_speed = 0; + + if (id && (id->capability & 1) && HWIF(drive)->autodma) { + /* Consult the list of known "bad" drives */ + if (ide_dmaproc(ide_dma_bad_drive, drive)) { + dma_func = ide_dma_off; + goto fast_ata_pio; + } + dma_func = ide_dma_off_quietly; + if (id->field_valid & 4) { + if (id->dma_ultra & 0x007F) { + /* Force if Capable UltraDMA */ + dma_func = slc90e66_config_drive_for_dma(drive); + if ((id->field_valid & 2) && + (dma_func != ide_dma_on)) + goto try_dma_modes; + } + } else if (id->field_valid & 2) { +try_dma_modes: + if ((id->dma_mword & 0x0007) || + (id->dma_1word & 0x007)) { + /* Force if Capable regular DMA modes */ + dma_func = slc90e66_config_drive_for_dma(drive); + if (dma_func != ide_dma_on) + goto no_dma_set; + } + } else if (ide_dmaproc(ide_dma_good_drive, drive)) { + if (id->eide_dma_time > 150) { + goto no_dma_set; + } + /* Consult the list of known "good" drives */ + dma_func = slc90e66_config_drive_for_dma(drive); + if (dma_func != ide_dma_on) + goto no_dma_set; + } else { + goto fast_ata_pio; + } + } else if ((id->capability & 8) || (id->field_valid & 2)) { +fast_ata_pio: + dma_func = ide_dma_off_quietly; +no_dma_set: + slc90e66_tune_drive(drive, 5); + } + return HWIF(drive)->dmaproc(dma_func, drive); +} + static int slc90e66_dmaproc(ide_dma_action_t func, ide_drive_t *drive) { switch (func) { case ide_dma_check: - return ide_dmaproc((ide_dma_action_t) slc90e66_config_drive_for_dma(drive), drive); + return config_drive_xfer_rate(drive); default : break; } @@ -361,16 +438,11 @@ unsigned int __init ata66_slc90e66 (ide_hwif_t *hwif) { -#if 1 byte reg47 = 0, ata66 = 0; byte mask = hwif->channel ? 0x01 : 0x02; /* bit0:Primary */ pci_read_config_byte(hwif->pci_dev, 0x47, ®47); - ata66 = (reg47 & mask) ? 0 : 1; /* bit[0(1)]: 0:80, 1:40 */ -#else - byte ata66 = 0; -#endif return ata66; } @@ -379,6 +451,8 @@ if (!hwif->irq) hwif->irq = hwif->channel ? 15 : 14; + hwif->autodma = 0; + hwif->speedproc = &slc90e66_tune_chipset; hwif->tuneproc = &slc90e66_tune_drive; hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; @@ -386,11 +460,11 @@ if (!hwif->dma_base) return; - hwif->autodma = 0; #ifdef CONFIG_BLK_DEV_IDEDMA + hwif->dmaproc = &slc90e66_dmaproc; +#ifdef CONFIG_IDEDMA_AUTO if (!noautodma) hwif->autodma = 1; - hwif->dmaproc = &slc90e66_dmaproc; - hwif->speedproc = &slc90e66_tune_chipset; +#endif /* CONFIG_IDEDMA_AUTO */ #endif /* !CONFIG_BLK_DEV_IDEDMA */ } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/trm290.c linux.19rc3-ac4/drivers/ide/trm290.c --- linux.19rc3/drivers/ide/trm290.c 2002-07-29 12:49:58.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/trm290.c 2002-07-29 13:58:40.000000000 +0100 @@ -148,23 +148,23 @@ /* select PIO or DMA */ reg = use_dma ? (0x21 | 0x82) : (0x21 & ~0x82); - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ + local_irq_save(flags); if (reg != hwif->select_data) { hwif->select_data = reg; - outb(0x51|(hwif->channel<<3), hwif->config_data+1); /* set PIO/DMA */ - outw(reg & 0xff, hwif->config_data); + /* set PIO/DMA */ + OUT_BYTE(0x51|(hwif->channel<<3), hwif->config_data+1); + OUT_WORD(reg & 0xff, hwif->config_data); } /* enable IRQ if not probing */ if (drive->present) { - reg = inw(hwif->config_data+3) & 0x13; + reg = IN_WORD(hwif->config_data+3) & 0x13; reg &= ~(1 << hwif->channel); - outw(reg, hwif->config_data+3); + OUT_WORD(reg, hwif->config_data+3); } - __restore_flags(flags); /* local CPU only */ + local_irq_restore(flags); } static void trm290_selectproc (ide_drive_t *drive) @@ -176,6 +176,7 @@ static int trm290_dmaproc (ide_dma_action_t func, ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); +// ide_task_t *args = HWGROUP(drive)->rq->special; unsigned int count, reading = 2, writing = 0; switch (func) { @@ -187,24 +188,46 @@ #endif case ide_dma_read: if (!(count = ide_build_dmatable(drive, func))) - break; /* try PIO instead of DMA */ - trm290_prepare_drive(drive, 1); /* select DMA xfer */ + /* try PIO instead of DMA */ + break; + /* select DMA xfer */ + trm290_prepare_drive(drive, 1); outl(hwif->dmatable_dma|reading|writing, hwif->dma_base); drive->waiting_for_dma = 1; - outw((count * 2) - 1, hwif->dma_base+2); /* start DMA */ + /* start DMA */ + OUT_WORD((count * 2) - 1, hwif->dma_base+2); if (drive->media != ide_disk) return 0; + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); - OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); - return 0; +/* + * FIX ME to use only ACB ide_task_t args Struct + */ +#if 0 + { + ide_task_t *args = HWGROUP(drive)->rq->special; + OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); + } +#else + if (HWGROUP(drive)->rq->cmd == IDE_DRIVE_TASKFILE) { + ide_task_t *args = HWGROUP(drive)->rq->special; + OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); + } else if (drive->addressing == 1) + OUT_BYTE(reading ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG); + else + OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); +#endif + return HWIF(drive)->dmaproc(ide_dma_begin, drive); case ide_dma_begin: return 0; case ide_dma_end: drive->waiting_for_dma = 0; - ide_destroy_dmatable(drive); /* purge DMA mappings */ - return (inw(hwif->dma_base+2) != 0x00ff); + /* purge DMA mappings */ + ide_destroy_dmatable(drive); + return (IN_WORD(hwif->dma_base+2) != 0x00ff); case ide_dma_test_irq: - return (inw(hwif->dma_base+2) == 0x00ff); + return (IN_WORD(hwif->dma_base+2) == 0x00ff); default: return ide_dmaproc(func, drive); } @@ -225,25 +248,28 @@ hwif->chipset = ide_trm290; cfgbase = pci_resource_start(dev, 4); - if ((dev->class & 5) && cfgbase) - { + if ((dev->class & 5) && cfgbase) { hwif->config_data = cfgbase; - printk("TRM290: chip config base at 0x%04lx\n", hwif->config_data); + printk("TRM290: chip config base at 0x%04lx\n", + hwif->config_data); } else { hwif->config_data = 0x3df0; - printk("TRM290: using default config base at 0x%04lx\n", hwif->config_data); + printk("TRM290: using default config base at 0x%04lx\n", + hwif->config_data); } - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ + local_irq_save(flags); /* put config reg into first byte of hwif->select_data */ - outb(0x51|(hwif->channel<<3), hwif->config_data+1); - hwif->select_data = 0x21; /* select PIO as default */ - outb(hwif->select_data, hwif->config_data); - reg = inb(hwif->config_data+3); /* get IRQ info */ - reg = (reg & 0x10) | 0x03; /* mask IRQs for both ports */ - outb(reg, hwif->config_data+3); - __restore_flags(flags); /* local CPU only */ + OUT_BYTE(0x51|(hwif->channel<<3), hwif->config_data+1); + /* select PIO as default */ + hwif->select_data = 0x21; + OUT_BYTE(hwif->select_data, hwif->config_data); + /* get IRQ info */ + reg = IN_BYTE(hwif->config_data+3); + /* mask IRQs for both ports */ + reg = (reg & 0x10) | 0x03; + OUT_BYTE(reg, hwif->config_data+3); + local_irq_restore(flags); if ((reg & 0x10)) hwif->irq = hwif->channel ? 15 : 14; /* legacy mode */ @@ -256,20 +282,20 @@ #endif /* CONFIG_BLK_DEV_IDEDMA */ hwif->selectproc = &trm290_selectproc; - hwif->autodma = 0; /* play it safe for now */ + hwif->autodma = 0; /* play it safe for now */ #if 1 { - /* - * My trm290-based card doesn't seem to work with all possible values - * for the control basereg, so this kludge ensures that we use only - * values that are known to work. Ugh. -ml - */ + /* + * My trm290-based card doesn't seem to work with all possible values + * for the control basereg, so this kludge ensures that we use only + * values that are known to work. Ugh. -ml + */ unsigned short old, compat = hwif->channel ? 0x374 : 0x3f4; static unsigned short next_offset = 0; - outb(0x54|(hwif->channel<<3), hwif->config_data+1); - old = inw(hwif->config_data) & ~1; - if (old != compat && inb(old+2) == 0xff) { + OUT_BYTE(0x54|(hwif->channel<<3), hwif->config_data+1); + old = IN_WORD(hwif->config_data) & ~1; + if (old != compat && IN_BYTE(old+2) == 0xff) { compat += (next_offset += 0x400); /* leave lower 10 bits untouched */ #if 1 if (ide_check_region(compat + 2, 1)) @@ -281,8 +307,8 @@ */ #endif hwif->io_ports[IDE_CONTROL_OFFSET] = compat + 2; - outw(compat|1, hwif->config_data); - printk("%s: control basereg workaround: old=0x%04x, new=0x%04x\n", hwif->name, old, inw(hwif->config_data) & ~1); + OUT_WORD(compat|1, hwif->config_data); + printk("%s: control basereg workaround: old=0x%04x, new=0x%04x\n", hwif->name, old, IN_WORD(hwif->config_data) & ~1); } } #endif diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/umc8672.c linux.19rc3-ac4/drivers/ide/umc8672.c --- linux.19rc3/drivers/ide/umc8672.c 2002-07-29 12:49:58.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/umc8672.c 2002-07-29 13:58:40.000000000 +0100 @@ -73,36 +73,34 @@ static void out_umc (char port,char wert) { - outb_p (port,0x108); - outb_p (wert,0x109); + outb_p(port,0x108); + outb_p(wert,0x109); } static inline byte in_umc (char port) { - outb_p (port,0x108); - return inb_p (0x109); + outb_p(port,0x108); + return inb_p(0x109); } static void umc_set_speeds (byte speeds[]) { int i, tmp; - outb_p (0x5A,0x108); /* enable umc */ + outb_p(0x5A,0x108); /* enable umc */ out_umc (0xd7,(speedtab[0][speeds[2]] | (speedtab[0][speeds[3]]<<4))); out_umc (0xd6,(speedtab[0][speeds[0]] | (speedtab[0][speeds[1]]<<4))); tmp = 0; - for (i = 3; i >= 0; i--) - { + for (i = 3; i >= 0; i--) { tmp = (tmp << 2) | speedtab[1][speeds[i]]; } out_umc (0xdc,tmp); - for (i = 0;i < 4; i++) - { + for (i = 0;i < 4; i++) { out_umc (0xd0+i,speedtab[2][speeds[i]]); out_umc (0xd8+i,speedtab[2][speeds[i]]); } - outb_p (0xa5,0x108); /* disable umc */ + outb_p(0xa5,0x108); /* disable umc */ printk ("umc8672: drive speeds [0 to 11]: %d %d %d %d\n", speeds[0], speeds[1], speeds[2], speeds[3]); @@ -114,40 +112,38 @@ ide_hwgroup_t *hwgroup = ide_hwifs[HWIF(drive)->index^1].hwgroup; pio = ide_get_best_pio_mode(drive, pio, 4, NULL); - printk("%s: setting umc8672 to PIO mode%d (speed %d)\n", drive->name, pio, pio_to_umc[pio]); - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ + printk("%s: setting umc8672 to PIO mode%d (speed %d)\n", + drive->name, pio, pio_to_umc[pio]); + spin_lock_irqsave(&io_request_lock, flags); if (hwgroup && hwgroup->handler != NULL) { printk("umc8672: other interface is busy: exiting tune_umc()\n"); } else { current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio]; umc_set_speeds (current_speeds); } - restore_flags(flags); /* all CPUs */ + spin_unlock_irqrestore(&io_request_lock, flags); } void __init init_umc8672 (void) /* called from ide.c */ { unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ + local_irq_save(flags); if (check_region(0x108, 2)) { - __restore_flags(flags); + local_irq_restore(flags); printk("\numc8672: PORTS 0x108-0x109 ALREADY IN USE\n"); return; } - outb_p (0x5A,0x108); /* enable umc */ - if (in_umc (0xd5) != 0xa0) - { - __restore_flags(flags); /* local CPU only */ + outb_p(0x5A,0x108); /* enable umc */ + if (in_umc (0xd5) != 0xa0) { + local_irq_restore(flags); printk ("umc8672: not found\n"); return; } - outb_p (0xa5,0x108); /* disable umc */ + outb_p(0xa5,0x108); /* disable umc */ umc_set_speeds (current_speeds); - __restore_flags(flags); /* local CPU only */ + local_irq_restore(flags); request_region(0x108, 2, "umc8672"); ide_hwifs[0].chipset = ide_umc8672; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/ide/via82cxxx.c linux.19rc3-ac4/drivers/ide/via82cxxx.c --- linux.19rc3/drivers/ide/via82cxxx.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/ide/via82cxxx.c 2002-07-29 13:58:40.000000000 +0100 @@ -193,7 +193,7 @@ pci_read_config_byte(dev, VIA_IDE_ENABLE, &t); via_print("Enabled: %10s%20s", (t & 0x02) ? "yes" : "no", (t & 0x01) ? "yes" : "no"); - c = inb(via_base + 0x02) | (inb(via_base + 0x0a) << 8); + c = IN_BYTE(via_base + 0x02) | (IN_BYTE(via_base + 0x0a) << 8); via_print("Simplex only: %10s%20s", (c & 0x80) ? "yes" : "no", (c & 0x8000) ? "yes" : "no"); via_print("Cable Type: %10s%20s", (via_80w & 1) ? "80w" : "40w", (via_80w & 2) ? "80w" : "40w"); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/isdn/pcbit/drv.c linux.19rc3-ac4/drivers/isdn/pcbit/drv.c --- linux.19rc3/drivers/isdn/pcbit/drv.c 2002-07-29 12:49:58.000000000 +0100 +++ linux.19rc3-ac4/drivers/isdn/pcbit/drv.c 2002-07-29 13:58:40.000000000 +0100 @@ -430,7 +430,7 @@ switch(dev->l2_state) { case L2_LWMODE: /* check (size <= rdp_size); write buf into board */ - if (len > BANK4 + 1) + if (len < 0 || len > BANK4 + 1) { printk("pcbit_writecmd: invalid length %d\n", len); return -EINVAL; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/Makefile linux.19rc3-ac4/drivers/Makefile --- linux.19rc3/drivers/Makefile 2002-07-29 12:54:47.000000000 +0100 +++ linux.19rc3-ac4/drivers/Makefile 2002-07-29 13:58:38.000000000 +0100 @@ -6,7 +6,7 @@ # -mod-subdirs := dio mtd sbus video macintosh usb input telephony sgi ide \ +mod-subdirs := dio hil mtd sbus video macintosh usb input telephony sgi ide \ message/i2o message/fusion scsi md ieee1394 pnp isdn atm \ fc4 net/hamradio i2c acpi bluetooth @@ -16,6 +16,8 @@ subdir-$(CONFIG_DIO) += dio subdir-$(CONFIG_PCI) += pci +subdir-$(CONFIG_GSC) += gsc +subdir-$(CONFIG_HIL) += hil subdir-$(CONFIG_PCMCIA) += pcmcia subdir-$(CONFIG_MTD) += mtd subdir-$(CONFIG_SBUS) += sbus diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/md/md.c linux.19rc3-ac4/drivers/md/md.c --- linux.19rc3/drivers/md/md.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/md/md.c 2002-07-29 13:58:40.000000000 +0100 @@ -2936,8 +2936,6 @@ * bdflush, otherwise bdflush will deadlock if there are too * many dirty RAID5 blocks. */ - current->policy = SCHED_OTHER; - current->nice = -20; md_unlock_kernel(); complete(thread->event); @@ -3391,11 +3389,6 @@ "(but not more than %d KB/sec) for reconstruction.\n", sysctl_speed_limit_max); - /* - * Resync has low priority. - */ - current->nice = 19; - is_mddev_idle(mddev); /* this also initializes IO event counters */ for (m = 0; m < SYNC_MARKS; m++) { mark[m] = jiffies; @@ -3473,16 +3466,13 @@ currspeed = (j-mddev->resync_mark_cnt)/2/((jiffies-mddev->resync_mark)/HZ +1) +1; if (currspeed > sysctl_speed_limit_min) { - current->nice = 19; - if ((currspeed > sysctl_speed_limit_max) || !is_mddev_idle(mddev)) { current->state = TASK_INTERRUPTIBLE; md_schedule_timeout(HZ/4); goto repeat; } - } else - current->nice = -20; + } } printk(KERN_INFO "md: md%d: sync done.\n",mdidx(mddev)); err = 0; @@ -3712,7 +3702,7 @@ * Searches all registered partitions for autorun RAID arrays * at boot time. */ -static int detected_devices[128]; +static kdev_t detected_devices[128]; static int dev_cnt; void md_autodetect_dev(kdev_t dev) diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/bttv-driver.c linux.19rc3-ac4/drivers/media/video/bttv-driver.c --- linux.19rc3/drivers/media/video/bttv-driver.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/bttv-driver.c 2002-07-29 13:58:40.000000000 +0100 @@ -137,97 +137,52 @@ /* Memory management functions */ /*******************************/ -#define MDEBUG(x) do { } while(0) /* Debug memory management */ - /* [DaveM] I've recoded most of this so that: * 1) It's easier to tell what is happening * 2) It's more portable, especially for translating things * out of vmalloc mapped areas in the kernel. * 3) Less unnecessary translations happen. - * - * The code used to assume that the kernel vmalloc mappings - * existed in the page tables of every process, this is simply - * not guarenteed. We now use pgd_offset_k which is the - * defined way to get at the kernel page tables. - */ - -/* 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 = (unsigned long) page_address(pte_page(pte)); - ret |= (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; + unsigned long kva, ret; - va = VMALLOC_VMADDR(adr); - kva = uvirt_to_kva(pgd_offset_k(va), va); + kva = (unsigned long) page_address(vmalloc_to_page((void *)adr)); + kva |= adr & (PAGE_SIZE-1); /* restore the offset */ 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. + * This is used when initializing the contents of the area. */ static inline unsigned long kvirt_to_pa(unsigned long adr) { - unsigned long va, kva, ret; + unsigned long kva, ret; - va = VMALLOC_VMADDR(adr); - kva = uvirt_to_kva(pgd_offset_k(va), va); + kva = (unsigned long) page_address(vmalloc_to_page((void *)adr)); + kva |= adr & (PAGE_SIZE-1); /* restore the offset */ ret = __pa(kva); - MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret)); return ret; } -static void * rvmalloc(signed long size) +static void * rvmalloc(unsigned long size) { void * mem; - unsigned long adr, page; + unsigned long adr; + size=PAGE_ALIGN(size); mem=vmalloc_32(size); if (NULL == mem) - printk(KERN_INFO "bttv: vmalloc_32(%ld) failed\n",size); + printk(KERN_INFO "bttv: vmalloc_32(%lu) failed\n",size); else { /* Clear the ram out, no junk to the user */ memset(mem, 0, size); adr=(unsigned long) mem; while (size > 0) { - page = kvirt_to_pa(adr); - mem_map_reserve(virt_to_page(__va(page))); + mem_map_reserve(vmalloc_to_page((void *)adr)); adr+=PAGE_SIZE; size-=PAGE_SIZE; } @@ -235,17 +190,16 @@ return mem; } -static void rvfree(void * mem, signed long size) +static void rvfree(void * mem, unsigned long size) { - unsigned long adr, page; + unsigned long adr; if (mem) { adr=(unsigned long) mem; - while (size > 0) + while ((long) size > 0) { - page = kvirt_to_pa(adr); - mem_map_unreserve(virt_to_page(__va(page))); + mem_map_unreserve(vmalloc_to_page((void *)adr)); adr+=PAGE_SIZE; size-=PAGE_SIZE; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/Config.in linux.19rc3-ac4/drivers/media/video/Config.in --- linux.19rc3/drivers/media/video/Config.in 2002-07-29 12:50:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/Config.in 2002-07-29 13:58:40.000000000 +0100 @@ -11,6 +11,8 @@ if [ "$CONFIG_I2C_ALGOBIT" = "y" -o "$CONFIG_I2C_ALGOBIT" = "m" ]; then dep_tristate ' BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_I2C_ALGOBIT fi +dep_tristate ' Luxsonor LS220 (EXPERIMENTAL)' CONFIG_VIDEO_LS220 $CONFIG_VIDEO_DEV +dep_tristate ' Margi DVD-to-Go (EXPERIMENTAL)' CONFIG_VIDEO_MARGI $CONFIG_PCMCIA $CONFIG_VIDEO_DEV dep_tristate ' Mediavision Pro Movie Studio Video For Linux' CONFIG_VIDEO_PMS $CONFIG_VIDEO_DEV if [ "$CONFIG_ALL_PPC" = "y" ]; then dep_tristate ' PlanB Video-In on PowerMac' CONFIG_VIDEO_PLANB $CONFIG_VIDEO_DEV diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/cpia.c linux.19rc3-ac4/drivers/media/video/cpia.c --- linux.19rc3/drivers/media/video/cpia.c 2002-07-29 12:50:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/cpia.c 2002-07-29 13:58:40.000000000 +0100 @@ -56,7 +56,7 @@ #ifdef MODULE MODULE_PARM(video_nr,"i"); -MODULE_AUTHOR("Scott J. Bertin & Peter Pregler & Johannes Erdfelt "); +MODULE_AUTHOR("Scott J. Bertin & Peter Pregler & Johannes Erdfelt "); MODULE_DESCRIPTION("V4L-driver for Vision CPiA based cameras"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("video"); @@ -163,6 +163,7 @@ #define COMMAND_SETAPCOR 0x1000 #define COMMAND_SETFLICKERCTRL 0x2000 #define COMMAND_SETVLOFFSET 0x4000 +#define COMMAND_SETLIGHTS 0x8000 /* Developer's Guide Table 5 p 3-34 * indexed by [mains][sensorFps.baserate][sensorFps.divisor]*/ @@ -178,50 +179,17 @@ * * 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 = (unsigned long) page_address(pte_page(pte)); - ret |= (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. + * This is used when initializing the contents of the area. */ static inline unsigned long kvirt_to_pa(unsigned long adr) { - unsigned long va, kva, ret; + unsigned long kva, ret; - va = VMALLOC_VMADDR(adr); - kva = uvirt_to_kva(pgd_offset_k(va), va); + kva = (unsigned long) page_address(vmalloc_to_page((void *)adr)); + kva |= adr & (PAGE_SIZE-1); /* restore the offset */ ret = __pa(kva); return ret; } @@ -229,12 +197,9 @@ 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); + unsigned long adr; + size = PAGE_ALIGN(size); mem = vmalloc_32(size); if (!mem) return NULL; @@ -242,13 +207,9 @@ memset(mem, 0, size); /* Clear the ram out, no junk to the user */ adr = (unsigned long) mem; while (size > 0) { - page = kvirt_to_pa(adr); - mem_map_reserve(virt_to_page(__va(page))); + mem_map_reserve(vmalloc_to_page((void *)adr)); adr += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; + size -= PAGE_SIZE; } return mem; @@ -256,23 +217,16 @@ static void rvfree(void *mem, unsigned long size) { - unsigned long adr, page; + unsigned long adr; 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(virt_to_page(__va(page))); + while ((long) size > 0) { + mem_map_unreserve(vmalloc_to_page((void *)adr)); adr += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; + size -= PAGE_SIZE; } vfree(mem); } @@ -291,7 +245,7 @@ char *out = page; int len, tmp; struct cam_data *cam = data; - char tmpstr[20]; + char tmpstr[29]; /* IMPORTANT: This output MUST be kept under PAGE_SIZE * or we need to get more sophisticated. */ @@ -328,6 +282,13 @@ cam->params.status.vpStatus); out += sprintf(out, "error_code: %#04x\n", cam->params.status.errorCode); + /* QX3 specific entries */ + if (cam->params.qx3.qx3_detected) { + out += sprintf(out, "button: %4d\n", + cam->params.qx3.button); + out += sprintf(out, "cradled: %4d\n", + cam->params.qx3.cradled); + } out += sprintf(out, "video_size: %s\n", cam->params.format.videoSize == VIDEOSIZE_CIF ? "CIF " : "QCIF"); @@ -392,16 +353,17 @@ if (cam->params.version.firmwareVersion == 1 && cam->params.version.firmwareRevision == 2) /* 1-02 firmware limits gain to 2 */ - sprintf(tmpstr, "%8d %8d", 1, 2); + sprintf(tmpstr, "%8d %8d %8d", 1, 2, 2); else - sprintf(tmpstr, "1,2,4,8"); + sprintf(tmpstr, "%8d %8d %8d", 1, 8, 2); if (cam->params.exposure.gainMode == 0) - out += sprintf(out, "max_gain: unknown %18s" - " %8d\n", tmpstr, 2); + out += sprintf(out, "max_gain: unknown %28s" + " powers of 2\n", tmpstr); else - out += sprintf(out, "max_gain: %8d %18s %8d\n", - 1<<(cam->params.exposure.gainMode-1), tmpstr, 2); + out += sprintf(out, "max_gain: %8d %28s" + " 1,2,4 or 8 \n", + 1<<(cam->params.exposure.gainMode-1), tmpstr); switch(cam->params.exposure.expMode) { case 1: @@ -528,6 +490,15 @@ out += sprintf(out, "decimation_thresh_mod: %8d %8d %8d %8d\n", cam->params.compressionParams.decimationThreshMod, 0, 255, 2); + /* QX3 specific entries */ + if (cam->params.qx3.qx3_detected) { + out += sprintf(out, "toplight: %8s %8s %8s %8s\n", + cam->params.qx3.toplight ? "on" : "off", + "off", "on", "off"); + out += sprintf(out, "bottomlight: %8s %8s %8s %8s\n", + cam->params.qx3.bottomlight ? "on" : "off", + "off", "on", "off"); + } len = out - page; len -= off; @@ -541,18 +512,45 @@ return len; } -static int cpia_write_proc(struct file *file, const char *buffer, +static int cpia_write_proc(struct file *file, const char *buf, unsigned long count, void *data) { - return -EINVAL; -#if 0 struct cam_data *cam = data; struct cam_params new_params; + char *page, *buffer; int retval, find_colon; int size = count; - unsigned long val; + unsigned long val = 0; u32 command_flags = 0; u8 new_mains; + + /* + * This code to copy from buf to page is shamelessly copied + * from the comx driver + */ + if (count > PAGE_SIZE) { + printk(KERN_ERR "count is %lu > %d!!!\n", count, (int)PAGE_SIZE); + return -ENOSPC; + } + + if (!(page = (char *)__get_free_page(GFP_KERNEL))) return -ENOMEM; + + if(copy_from_user(page, buf, count)) + { + retval = -EFAULT; + goto out; + } + + if (page[count-1] == '\n') + page[count-1] = '\0'; + else if (count < PAGE_SIZE) + page[count] = '\0'; + else if (page[count]) { + retval = -EINVAL; + goto out; + } + + buffer = page; if (down_interruptible(&cam->param_lock)) return -ERESTARTSYS; @@ -1210,6 +1208,22 @@ retval = -EINVAL; } command_flags |= COMMAND_SETCOMPRESSIONPARAMS; + } else if (MATCH("toplight")) { + if (!retval && MATCH("on")) + new_params.qx3.toplight = 1; + else if (!retval && MATCH("off")) + new_params.qx3.toplight = 0; + else + retval = -EINVAL; + command_flags |= COMMAND_SETLIGHTS; + } else if (MATCH("bottomlight")) { + if (!retval && MATCH("on")) + new_params.qx3.bottomlight = 1; + else if (!retval && MATCH("off")) + new_params.qx3.bottomlight = 0; + else + retval = -EINVAL; + command_flags |= COMMAND_SETLIGHTS; } else { DBG("No match found\n"); retval = -EINVAL; @@ -1221,7 +1235,10 @@ ++buffer; } if (count) { - if (*buffer != '\n' && *buffer != ';') + if (*buffer == '\0' && count != 1) + retval = -EINVAL; + else if (*buffer != '\n' && *buffer != ';' && + *buffer != '\0') retval = -EINVAL; else { --count; @@ -1255,8 +1272,9 @@ up(&cam->param_lock); +out: + free_page((unsigned long)page); return retval; -#endif } static void create_proc_cpia_cam(struct cam_data *cam) @@ -1276,7 +1294,12 @@ ent->data = cam; ent->read_proc = cpia_read_proc; ent->write_proc = cpia_write_proc; - ent->size = 3626; + /* + size of the proc entry is 3672 bytes for the standard webcam; + the extra features of the QX3 microscope add 188 bytes. + (we have not yet probed the camera to see which type it is). + */ + ent->size = 3672 + 188; cam->proc_entry = ent; } @@ -1570,6 +1593,10 @@ down(&cam->param_lock); datasize=8; break; + case CPIA_COMMAND_ReadMCPorts: + case CPIA_COMMAND_ReadVCRegs: + datasize = 4; + break; default: datasize=0; break; @@ -1667,6 +1694,22 @@ } up(&cam->param_lock); break; + + case CPIA_COMMAND_ReadMCPorts: + if (!cam->params.qx3.qx3_detected) + break; + /* test button press */ + cam->params.qx3.button = ((data[1] & 0x02) == 0); + if (cam->params.qx3.button) { + /* button pressed - unlock the latch */ + do_command(cam,CPIA_COMMAND_WriteMCPort,3,0xDF,0xDF,0); + do_command(cam,CPIA_COMMAND_WriteMCPort,3,0xFF,0xFF,0); + } + + /* test whether microscope is cradled */ + cam->params.qx3.cradled = ((data[2] & 0x40) == 0); + break; + default: break; } @@ -1826,6 +1869,7 @@ { switch(fmt) { case VIDEO_PALETTE_GREY: + return count; case VIDEO_PALETTE_RGB555: case VIDEO_PALETTE_RGB565: case VIDEO_PALETTE_YUV422: @@ -2106,6 +2150,13 @@ if (cam->cmd_queue & COMMAND_RESUME) init_stream_cap(cam); + if (cam->cmd_queue & COMMAND_SETLIGHTS && cam->params.qx3.qx3_detected) { + int p1 = (cam->params.qx3.bottomlight == 0) << 1; + int p2 = (cam->params.qx3.toplight == 0) << 3; + do_command(cam, CPIA_COMMAND_WriteVCReg, 0x90, 0x8F, 0x50, 0); + do_command(cam, CPIA_COMMAND_WriteMCPort, 2, 0, (p1|p2|0xE0), 0); + } + up(&cam->param_lock); cam->cmd_queue = COMMAND_NONE; return; @@ -2182,9 +2233,10 @@ /* camera idle now so dispatch queued commands */ dispatch_commands(cam); - /* Update our knowledge of the camera state - FIXME: necessary? */ + /* Update our knowledge of the camera state */ do_command(cam, CPIA_COMMAND_GetColourBalance, 0, 0, 0, 0); do_command(cam, CPIA_COMMAND_GetExposure, 0, 0, 0, 0); + do_command(cam, CPIA_COMMAND_ReadMCPorts, 0, 0, 0, 0); /* decompress and convert image to by copying it from * raw_image to decompressed_frame @@ -2396,7 +2448,11 @@ get_version_information(cam); if (cam->params.version.firmwareVersion != 1) return -ENODEV; - + + /* set QX3 detected flag */ + cam->params.qx3.qx3_detected = (cam->params.pnpID.vendor == 0x0813 && + cam->params.pnpID.product == 0x0001); + /* The fatal error checking should be done after * the camera powers up (developer's guide p 3-38) */ @@ -2526,7 +2582,7 @@ /* GotoLoPower */ goto_low_power(cam); - /* Update the camera ststus */ + /* Update the camera status */ do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0); /* cleanup internal state stuff */ @@ -2566,7 +2622,7 @@ { struct cam_data *cam = dev->priv; - /* make this _really_ smp and multithredi-safe */ + /* make this _really_ smp and multithread-safe */ if (down_interruptible(&cam->busy_lock)) return -EINTR; @@ -2793,7 +2849,6 @@ cam->cmd_queue |= COMMAND_SETFORMAT; } - // FIXME needed??? memcpy(&cam->vw, &vw, sizeof(vw)); up(&cam->param_lock); /* setformat ignored by camera during streaming, @@ -2835,10 +2890,8 @@ 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; @@ -2848,6 +2901,8 @@ cam->vp.palette = vm.format; switch(vm.format) { case VIDEO_PALETTE_GREY: + cam->vp.depth=8; + break; case VIDEO_PALETTE_RGB555: case VIDEO_PALETTE_RGB565: case VIDEO_PALETTE_YUV422: @@ -2880,10 +2935,6 @@ 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); @@ -3035,7 +3086,7 @@ owner: THIS_MODULE, name: "CPiA Camera", type: VID_TYPE_CAPTURE, - hardware: VID_HARDWARE_CPIA, /* FIXME */ + hardware: VID_HARDWARE_CPIA, open: cpia_open, close: cpia_close, read: cpia_read, @@ -3100,8 +3151,8 @@ cam->params.sensorFps.divisor = 1; cam->params.sensorFps.baserate = 1; - cam->params.yuvThreshold.yThreshold = 15; /* FIXME? */ - cam->params.yuvThreshold.uvThreshold = 15; /* FIXME? */ + cam->params.yuvThreshold.yThreshold = 6; /* From windows driver */ + cam->params.yuvThreshold.uvThreshold = 6; /* From windows driver */ cam->params.format.subSample = SUBSAMPLE_422; cam->params.format.yuvOrder = YUVORDER_YUYV; @@ -3109,8 +3160,14 @@ 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->params.compressionTarget.targetFR = 15; /* From windows driver */ + cam->params.compressionTarget.targetQ = 5; /* From windows driver */ + + cam->params.qx3.qx3_detected = 0; + cam->params.qx3.toplight = 0; + cam->params.qx3.bottomlight = 0; + cam->params.qx3.button = 0; + cam->params.qx3.cradled = 0; cam->video_size = VIDEOSIZE_CIF; @@ -3119,8 +3176,8 @@ 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->vp.depth = 24; /* to be set by user */ + cam->vp.palette = VIDEO_PALETTE_RGB24; /* to be set by user */ cam->vw.x = 0; cam->vw.y = 0; @@ -3209,12 +3266,6 @@ /* 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, diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/cpia.h linux.19rc3-ac4/drivers/media/video/cpia.h --- linux.19rc3/drivers/media/video/cpia.h 2002-07-29 12:50:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/cpia.h 2002-07-29 17:29:11.000000000 +0100 @@ -27,12 +27,12 @@ */ #define CPIA_MAJ_VER 0 -#define CPIA_MIN_VER 7 -#define CPIA_PATCH_VER 4 +#define CPIA_MIN_VER 8 +#define CPIA_PATCH_VER 1 #define CPIA_PP_MAJ_VER 0 -#define CPIA_PP_MIN_VER 7 -#define CPIA_PP_PATCH_VER 4 +#define CPIA_PP_MIN_VER 8 +#define CPIA_PP_PATCH_VER 1 #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 */ @@ -204,6 +204,13 @@ u8 subSample; u8 yuvOrder; } format; + struct { /* Intel QX3 specific data */ + u8 qx3_detected; /* a QX3 is present */ + u8 toplight; /* top light lit , R/W */ + u8 bottomlight; /* bottom light lit, R/W */ + u8 button; /* snapshot button pressed (R/O) */ + u8 cradled; /* microscope is in cradle (R/O) */ + } qx3; struct { u8 colStart; /* skip first 8*colStart pixels */ u8 colEnd; /* finish at 8*colEnd pixels */ @@ -393,29 +400,6 @@ (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) - - static inline void cpia_add_to_list(struct cam_data* l, struct cam_data* drv) { drv->next = l; @@ -423,7 +407,6 @@ l = drv; } - static inline void cpia_remove_from_list(struct cam_data* drv) { if (drv->previous != NULL) { @@ -435,7 +418,6 @@ } } - #endif /* __KERNEL__ */ #endif /* cpia_h */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/cpia_pp.c linux.19rc3-ac4/drivers/media/video/cpia_pp.c --- linux.19rc3/drivers/media/video/cpia_pp.c 2002-07-29 12:50:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/cpia_pp.c 2002-07-29 13:58:40.000000000 +0100 @@ -4,7 +4,7 @@ * Supports CPiA based parallel port Video Camera's. * * (C) Copyright 1999 Bas Huisman - * (C) Copyright 1999-2000 Scott J. Bertin , + * (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 @@ -340,17 +340,6 @@ return 0; } -static int cpia_pp_read(struct parport *port, u8 *buffer, int len) -{ - int bytes_read, new_bytes; - for(bytes_read=0; bytes_readport, buffer, CPIA_MAX_IMAGE_SIZE ); + + EndTransferMode(cam); + DBG("read %d bytes\n", read_bytes); + if( read_bytes<0) 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; - } + endseen = 0; + for( i=0; i3 ) { + cam->image_complete=1; + DBG("endseen at %d bytes\n", i); } - EndTransferMode(cam); return cam->image_complete ? read_bytes : -EIO; } @@ -716,15 +696,6 @@ 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) { diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/cpia_usb.c linux.19rc3-ac4/drivers/media/video/cpia_usb.c --- linux.19rc3/drivers/media/video/cpia_usb.c 2002-07-29 12:50:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/cpia_usb.c 2002-07-29 13:58:40.000000000 +0100 @@ -266,14 +266,16 @@ error_urb1: /* free urb 1 */ usb_free_urb(ucpia->sbuf[1].urb); - + ucpia->sbuf[1].urb = NULL; error_urb0: /* free urb 0 */ usb_free_urb(ucpia->sbuf[0].urb); - + ucpia->sbuf[0].urb = NULL; error_1: kfree (ucpia->sbuf[1].data); + ucpia->sbuf[1].data = NULL; error_0: kfree (ucpia->sbuf[0].data); + ucpia->sbuf[0].data = NULL; return retval; } @@ -620,8 +622,10 @@ ucpia->buffers[0] = NULL; } - if (!ucpia->open) + if (!ucpia->open) { kfree(ucpia); + cam->lowlevel_data = NULL; + } } static int __init usb_cpia_init(void) diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/ls220/ac3_240.h linux.19rc3-ac4/drivers/media/video/ls220/ac3_240.h --- linux.19rc3/drivers/media/video/ls220/ac3_240.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/ls220/ac3_240.h 2002-07-29 13:58:40.000000000 +0100 @@ -0,0 +1,2835 @@ +static u32 AC3240Ucode1f1800[] = { + 0xb500000f, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xb500118f, 0x00000000, 0x00000000, 0x00000000, + 0x820f001f, 0x802f001f, 0x80070800, 0x001f6193, + 0x800500d4, 0x8053ffff, 0x9842c7ff, 0x8039ff7c, + 0x1400b802, 0x003f6000, 0x94210007, 0xb0010001, + 0xb4200001, 0x98002800, 0xb0010000, 0xb4200001, + 0x98000800, 0x805300ff, 0x1800b802, 0x800600d4, + 0x8013001f, 0x9020c000, 0x003fb006, 0x803effe0, + 0x803effe8, 0x803effec, 0x9020e000, 0x9021ffe4, + 0x9020fa00, 0x803effd0, 0x803effdc, 0x803effd8, + 0x9020fe00, 0x803effd4, 0x90400000, 0x804600a2, + 0x90421800, 0x804600a3, 0x80134099, 0x98000040, + 0x800600a6, 0x80130000, 0x98003ca1, 0x800600a1, + 0x80050080, 0x98000002, 0x80060080, 0x80070001, + 0x001f2013, 0x001f2324, 0x80070000, 0x001fb0ba, + 0x001f23f9, 0x801eb3f0, 0x80070800, 0x001f600f, + 0x80070000, 0x001f2012, 0x001fb0cb, 0x001fb010, + 0x801efff0, 0x98004000, 0x98008000, 0x001f600e, + 0x83e40123, 0x80070000, 0x801eb3f8, 0x801eff70, + 0x800500a0, 0xb0000001, 0xb4000009, 0x80070001, + 0x800600a0, 0x80050080, 0x98000020, 0x80060080, + 0x9400ffdf, 0x80060080, 0x80070000, 0x800600a0, + 0x81df0004, 0x00000000, 0x00000000, 0x801bfff0, + 0x00000000, 0x940000ff, 0xb0000000, 0xb420004e, + 0x003f400e, 0x94010010, 0xb0000000, 0xb400fff4, + 0x838413a4, 0x003f0013, 0xb0010001, 0xb420003b, + 0x803bffe8, 0x801bffec, 0x00000000, 0x3001b800, + 0xb4600001, 0x90212000, 0x0421b800, 0x005f4193, + 0x5841b802, 0x3001b802, 0xb460000d, 0x80050086, + 0x005f9016, 0xb0020000, 0xb4200002, 0x001fb016, + 0xb500ffdf, 0x0420b802, 0xb0010b50, 0xb4a0ffdc, + 0x80070000, 0x001fb016, 0x83e400ed, 0xb500ffd8, + 0x80070000, 0x001fb016, 0x001f400e, 0x9400000f, + 0xb0000000, 0xb4000014, 0xb0000001, 0xb4000010, + 0x003f400e, 0x9421fff0, 0x003f600e, 0x003f9006, + 0x9421ffff, 0x90210004, 0xb001e000, 0xb4800002, + 0x8421e000, 0x9021c000, 0x8013001f, 0x1021b800, + 0x003fb006, 0x003f90cb, 0x90210004, 0x003fb0cb, + 0x83e400df, 0x83e41383, 0x8007001f, 0x94000003, + 0x5810b800, 0x83e71aa8, 0x1bffb800, 0x003f9008, + 0x1821b800, 0x00ffb801, 0x83e413d6, 0x80270000, + 0x003f2013, 0x8007001f, 0x94000003, 0x5810b800, + 0x83671ad4, 0x1b7bb800, 0x003f9009, 0x1821b800, + 0x00ffb801, 0xb500ffaa, 0x803bffc0, 0x805bffc4, + 0x807bffc8, 0x809bffcc, 0x5828b801, 0x5cb8b802, + 0x1821b805, 0x5848b802, 0x5cb8b803, 0x1842b805, + 0x5868b803, 0x5cb8b804, 0x1863b805, 0x5888b804, + 0x1884b800, 0x803effc0, 0x805effc4, 0x807effc8, + 0x809effcc, 0x003f400e, 0xb0000086, 0xb4400040, + 0xb0000084, 0xb400002a, 0xb0000085, 0xb4000030, + 0xb0000086, 0xb4000032, 0x001f4000, 0x94000080, + 0xb0000080, 0xb400006a, 0x80130000, 0x98003ca1, + 0x005f4000, 0x94420008, 0xb0020008, 0xb4000001, + 0xa0000080, 0x800600a1, 0x8013001f, 0x9040c000, + 0x005fb006, 0x805effe0, 0x805effe8, 0x805effec, + 0x9040e000, 0x805effe4, 0x9040fa00, 0x805effd0, + 0x805effdc, 0x805effd8, 0x9040fe00, 0x805effd4, + 0x80070001, 0x001f2013, 0x80070000, 0x001fb0cb, + 0x001fb010, 0x001f2058, 0x80071f40, 0x001fb008, + 0x80075d70, 0x001fb009, 0x98214000, 0xb5000010, + 0x94011000, 0xb0001000, 0xb4200001, 0x9421efff, + 0x98210010, 0xb500000a, 0x80070000, 0x001fb0cb, + 0x83e4007f, 0x003f400e, 0x9421ffef, 0xb5000004, + 0x83e4007b, 0x003f400e, 0x98211000, 0x9421ffef, + 0x003f600e, 0x80070100, 0x801efff0, 0xb500ff54, + 0xb000008b, 0xb400001c, 0xb000008e, 0xb4000022, + 0xb000008d, 0xb400001c, 0xb000008c, 0xb4000021, + 0xb0000087, 0xb400ffe8, 0xb0000088, 0xb4000014, + 0xb000008a, 0xb4000015, 0xb0000089, 0xb400001d, + 0xb00000a0, 0xb400001f, 0xb00000a1, 0xb4000041, + 0xb00000a2, 0xb400004a, 0xb00000a3, 0xb4000046, + 0xb00000a4, 0xb4000048, 0xb00000a5, 0xb4000048, + 0xb00000a6, 0xb4000048, 0x803efff8, 0xb500ffdd, + 0x9421ffdf, 0xb500ffda, 0xb500ffda, 0x80270100, + 0x803efff8, 0xb500ffd7, 0x80070000, 0x001fb017, + 0xb500ffd4, 0x801bffb0, 0x00000000, 0x001fb003, + 0xb500ffd0, 0x803bff80, 0x00000000, 0x003f6001, + 0xb500ffcc, 0x003f90ba, 0x803efff8, 0xb500ffc9, + 0x80130001, 0x98003da1, 0x800600a1, 0x80070200, + 0x801ebf34, 0x83e4002e, 0x8013001f, 0x9840c000, + 0x805effe0, 0x005fb006, 0x805effe8, 0x805effec, + 0x90422000, 0x805effe4, 0x9040fa00, 0x805effd0, + 0x805effdc, 0x805effd8, 0x9040fe00, 0x805effd4, + 0x80070001, 0x001f2013, 0x80070000, 0x001f2324, + 0x001fb0cb, 0x001fb010, 0x001f2058, 0x80077490, + 0x001fb008, 0x80077710, 0x001fb009, 0x98214000, + 0xb500ffa7, 0x80270000, 0x8047fef0, 0x003eb802, + 0x90420004, 0x003eb802, 0x90420004, 0x003eb802, + 0x90420004, 0x003eb802, 0x83641460, 0xb500ff9d, + 0x8364140e, 0xb500ff9b, 0x836413cd, 0xb500ff99, + 0x83441334, 0xb500ff97, 0x8344131d, 0xb500ff95, + 0x80070000, 0x80470000, 0xb6002003, 0xb6003002, + 0x001eb802, 0x90420004, 0x80171000, 0x8057ffff, + 0xb6002002, 0xb6001801, 0x001fa020, 0x00ffb81f, + 0x001f4000, 0x94000080, 0xb0000080, 0xb4200001, + 0xb500ffef, 0xb500000a, 0x80270000, 0x003f2013, + 0x8007001f, 0x94000003, 0x5810b800, 0x83671e40, + 0x1b7bb800, 0x003f9009, 0x1821b800, 0x00ffb801, + 0x003f0013, 0xb0010001, 0xb420fff3, 0x83a70000, + 0x803bff70, 0x00000000, 0xb0010000, 0xb4000011, + 0x80170300, 0x80070000, 0xb6000601, 0x001fa020, + 0x83640c6e, 0x00ff0325, 0x82870000, 0xb6270002, + 0x83640217, 0x92940001, 0x001f033b, 0xb0000000, + 0xb4000002, 0x80270000, 0xb5000001, 0x80270001, + 0x003f233b, 0x80270000, 0x003f2013, 0x8007001f, + 0x94000003, 0x5810b800, 0x83671ecc, 0x1b7bb800, + 0x003f9009, 0x1821b800, 0x00ffb801, 0x003f0013, + 0xb0010001, 0xb420fff3, 0x93bd0001, 0xb01d0004, + 0xb480ffdb, 0x803bff70, 0x00000000, 0xb0010000, + 0xb4000001, 0x83640c1a, 0x00000000, 0x00000000, + 0x00ffb81f, 0x007f90cb, 0x90630400, 0x007fb0cb, + 0x003f9006, 0x9421ffff, 0x90210400, 0xb001e000, + 0xb4800002, 0x8421e000, 0x9021c000, 0x8013001f, + 0x1021b800, 0x003fb006, 0x803effec, 0x00ffb81f, + 0x015f400e, 0x944a4000, 0xb0024000, 0xb4200084, + 0x954abfff, 0x015f600e, 0x820f001f, 0x802f001f, + 0x81470000, 0x015f23f9, 0x829702ec, 0x82d7ffff, + 0x82f70000, 0xb6000501, 0x029fa02a, 0x82970400, + 0xb6000702, 0xb6000001, 0x029fa02a, 0x8053ff00, + 0x98420000, 0x805ebf14, 0x805ebf18, 0x805ebf1c, + 0x805ebf20, 0x805ebf24, 0x805ebf28, 0x80270000, + 0x003f2328, 0x80275480, 0x005fb801, 0x8033001f, + 0x9821c000, 0x803effe0, 0x90212000, 0x803effe4, + 0x80dbff8c, 0x80fbff90, 0x80debf14, 0x80febf18, + 0x80dbff94, 0x80fbff98, 0x80debf1c, 0x80febf20, + 0x80dbff9c, 0x80fbffa0, 0x80debf24, 0x80febf28, + 0x80dbff84, 0x80e70001, 0x00dfb001, 0x80dbff88, + 0x00ff6191, 0x00dfb002, 0x80dbffb0, 0x80470000, + 0x00dfb003, 0x80d9ff80, 0x005fb0cf, 0x005fb0c6, + 0x00df6001, 0x80470001, 0x005f618f, 0x804700ff, + 0x005f231c, 0x005f231d, 0x80470000, 0x005f204e, + 0x8047e138, 0x5c42b802, 0x814f6300, 0x80cf00a9, + 0x005fb0bc, 0x5842b802, 0x01cfb802, 0x005f90bc, + 0xb520ffff, 0x8067e16c, 0x5c62b803, 0x80270040, + 0xb6000209, 0x814fffc0, 0x00cfb801, 0x007fb0bc, + 0x5862b803, 0x01cfb803, 0x007f90bc, 0xb520ffff, + 0x90210020, 0x90630020, 0x8047e398, 0x5c42b802, + 0x814fce40, 0x80cf0080, 0x005fb0bc, 0x5842b802, + 0x01cfb802, 0x005f90bc, 0xb520ffff, 0x8047e400, + 0x5c42b802, 0x814f7380, 0x80cf009a, 0x005fb0bc, + 0x5842b802, 0x01cfb802, 0x005f90bc, 0xb520ffff, + 0x8047e43c, 0x5c42b802, 0x814f18c0, 0x80cf00b6, + 0x005fb0bc, 0x5842b802, 0x01cfb802, 0x005f90bc, + 0xb520ffff, 0x80e70000, 0x00ffb0ba, 0x808f0000, + 0x806f001f, 0x80af001f, 0x8027b9fc, 0x5c22b801, + 0x80670700, 0xb600080a, 0x00cfb803, 0x003fb0bc, + 0x5822b801, 0x01cfb801, 0x003f90bc, 0x0047b86f, + 0xb0020001, 0xb4c0fffd, 0x90210020, 0x90630020, + 0x834400d3, 0xb0180000, 0xb4200025, 0x83440680, + 0x80c70000, 0x00df2324, 0x83640026, 0x83440228, + 0x00df0324, 0x90c60001, 0x00df2324, 0xb0060006, + 0xb4000003, 0x81472178, 0x015fb008, 0x00ffb81f, + 0x00ff90ba, 0x90e70001, 0x00ffb0ba, 0x019f9006, + 0x958cffff, 0x00df4193, 0x58c1b806, 0x118cb806, + 0xb00ce000, 0xb4800002, 0x858ce000, 0x918cc000, + 0x8153001f, 0x118cb80a, 0x819effec, 0x019fb006, + 0x015f4193, 0x5941b80a, 0x019f90cb, 0x118cb80a, + 0x019fb0cb, 0x81472160, 0x015fb008, 0x00ffb81f, + 0x015f400e, 0x194ab818, 0x015f600e, 0x802500a5, + 0x00ffb81f, 0x803bff8c, 0x805bff90, 0x803ebf14, + 0x805ebf18, 0x803bff94, 0x805bff98, 0x803ebf1c, + 0x805ebf20, 0x803bff9c, 0x805bffa0, 0x803ebf24, + 0x805ebf28, 0x80470003, 0x805ebefc, 0x003f0384, + 0x5822b801, 0x9021eb50, 0x005bb801, 0x00000000, + 0xb0020001, 0xb4200002, 0x80470001, 0x805ebefc, + 0x8073ff80, 0x98630000, 0x8027bf14, 0x8047befc, + 0xb6000609, 0x009bb801, 0x00000000, 0x00a7b804, + 0x6081b804, 0x3004b803, 0xb4000001, 0x00beb802, + 0x90210004, 0x90420004, 0x00ffb81b, 0x00000000, + 0x81150010, 0x00000000, 0x00000000, 0x81350010, + 0x00000000, 0x00000000, 0x81550002, 0x00000000, + 0x015f2380, 0x81550006, 0x00000000, 0x015f2381, + 0x81550005, 0x00000000, 0x015f2382, 0x81550003, + 0x00000000, 0x015f2383, 0x81550003, 0x015f2384, + 0xb00a0001, 0xb4000005, 0x956a0001, 0xb00b0000, + 0xb4000002, 0x81750002, 0x017f2385, 0x956a0004, + 0xb00b0000, 0xb4000002, 0x81750002, 0x017f2386, + 0xb00a0002, 0xb4200003, 0x81750002, 0x00000000, + 0x017f2387, 0x81750001, 0x00000000, 0x017f2388, + 0x81750005, 0x00000000, 0x017f2389, 0x81750001, + 0x017f239f, 0xb00b0001, 0xb4200003, 0x81750008, + 0x5968b80b, 0x017f61c5, 0x81750001, 0x017f238c, + 0xb00b0001, 0xb4200003, 0x81750008, 0x00000000, + 0x017f238d, 0x81750001, 0x017f238e, 0xb00b0001, + 0xb4200005, 0x81750005, 0x00000000, 0x017f238f, + 0x81750002, 0x017f2390, 0xb00a0000, 0xb420001b, + 0x81750005, 0x00000000, 0x017f2391, 0x81750001, + 0x017f23a0, 0xb00b0001, 0xb4200003, 0x81750008, + 0x5968b80b, 0x017f61c9, 0x81750001, 0x017f2394, + 0xb00b0001, 0xb4200003, 0x81750008, 0x00000000, + 0x017f2395, 0x81750001, 0x017f2396, 0xb00b0001, + 0xb4200006, 0x81750005, 0x00000000, 0x017f2397, + 0x81750002, 0x00000000, 0x017f2398, 0x81750001, + 0x00000000, 0x017f2399, 0x81750001, 0x00000000, + 0x017f239a, 0x81750001, 0x017f239b, 0xb00b0001, + 0xb4200003, 0x8175000e, 0x00000000, 0x017f61be, + 0x81750001, 0x017f239c, 0xb00b0001, 0xb4200003, + 0x8175000e, 0x00000000, 0x017f237e, 0x81750001, + 0x017f239d, 0xb00b0001, 0xb4200006, 0x81750006, + 0x017f239e, 0x916b0001, 0x81550008, 0x856b0001, + 0xb4e0fffd, 0x00ffb81c, 0x00000000, 0x00000000, + 0x81470000, 0x015f2385, 0x015f2386, 0x015f2387, + 0x015f238d, 0x015f238f, 0x015f2390, 0x015f2391, + 0x015f2395, 0x015f2396, 0x015f2397, 0x015f2398, + 0x015f61be, 0x015f61bf, 0x82070028, 0x023f9006, + 0x83a4003a, 0x83270000, 0x003fb819, 0x003f9006, + 0x5823b801, 0x83338000, 0x1b39b801, 0x003fb819, + 0x00000000, 0x00000000, 0x81550000, 0x8384ff64, + 0x017f0380, 0xad4b0026, 0x013f0381, 0x114ab809, + 0x5941b80a, 0x914ae00c, 0x0199b80a, 0x00000000, + 0x019f6193, 0xb0080b77, 0xb4200016, 0x015f0380, + 0xb00a0003, 0xb4600017, 0xb0090026, 0xb4600019, + 0x017f90ba, 0xb00b0000, 0xb4200004, 0x017f0384, + 0x017f204d, 0x017f0383, 0x017f2057, 0x015f0383, + 0x017f0057, 0x300ab80b, 0xb4200012, 0x015f0384, + 0x017f004d, 0x300ab80b, 0xb420000e, 0x83070000, + 0x00ffb81a, 0x83070800, 0x031f6193, 0x83070001, + 0x00ffb81a, 0x83070800, 0x031f6193, 0x83070002, + 0x00ffb81a, 0x83070800, 0x031f6193, 0x83070003, + 0x00ffb81a, 0x83070003, 0x00ffb81a, 0x5e02b810, + 0x5a02b810, 0x00bf9011, 0x00df004f, 0xa5260020, + 0x81e70000, 0x82471000, 0x95d1ffff, 0xa5cee000, + 0x300eb810, 0xb4600002, 0x05f0b80e, 0x0207b80e, + 0x8267001f, 0x82c70020, 0x82971000, 0xb0100080, + 0xb480001f, 0x5a8bb813, 0x5aa6b813, 0x1a94b815, + 0x01efb812, 0x014fb814, 0x01cfb811, 0xb520ffff, + 0xb636000f, 0x81470000, 0x039f8014, 0xb6000404, + 0x5948b80a, 0x957c00ff, 0x194ab80b, 0x5f88b81c, + 0xb0060020, 0xb4200001, 0x80a70000, 0x64a6b805, + 0x68e9b80a, 0x18a5b807, 0x029fa025, 0x00a7b80a, + 0x01efb812, 0x014fb814, 0x01afb811, 0xb520ffff, + 0x5ae2b816, 0x1231b817, 0x0610b817, 0xb500ffde, + 0xb0100000, 0xb4000003, 0x5ec2b810, 0x86760001, + 0xb500ffdc, 0xb00f0000, 0xb4000005, 0x0207b80f, + 0x81f3001f, 0x9a2fc000, 0x81e70000, 0xb500ffd0, + 0x015fb011, 0x00ffb81d, 0x00000000, 0x00000000, + 0x8057ffff, 0x80d7ffff, 0x8157ffff, 0x81d7ffff, + 0x8257ffff, 0x82d7ffff, 0x8357ffff, 0x83d7ffff, + 0x80770000, 0x80f70000, 0x81770000, 0x81f70000, + 0x82770000, 0x82f70000, 0x83770000, 0x83f70000, + 0xaeb40080, 0x808f0000, 0x806f001f, 0x80af001f, + 0xb0140000, 0xb4400014, 0x806f001f, 0x80af001f, + 0x8027b9fc, 0x5c22b801, 0x80670700, 0xb6000208, + 0x00cfb803, 0x003fb0bc, 0x5822b801, 0x01cfb801, + 0x003f90bc, 0xb520ffff, 0x90630020, 0x90210020, + 0x80270000, 0x80171000, 0xb6000303, 0xb6000001, + 0x001fa021, 0x00000000, 0x82670000, 0xb6000268, + 0x80170a00, 0x80970afc, 0x81170b00, 0x81970bfc, + 0x80271c00, 0x1021b813, 0x1021b813, 0x0217b801, + 0x80271ffc, 0x0421b813, 0x0421b813, 0x0297b801, + 0x80270c00, 0x1021b813, 0x1021b813, 0x0317b801, + 0x80270ffc, 0x0421b813, 0x0421b813, 0x0397b801, + 0x80478500, 0x1042b813, 0x5c42b802, 0x1022b815, + 0x80670280, 0x00cfb803, 0x003fb0bc, 0x5822b801, + 0x01cfb801, 0x003f90bc, 0xb520ffff, 0x009f033b, + 0x80478480, 0x0442b813, 0x5c42b802, 0x1022b815, + 0x806702a0, 0x00cfb803, 0x003fb0bc, 0x5822b801, + 0x01cfb801, 0x003f90bc, 0xb520ffff, 0xb0040000, + 0xb4000002, 0x80479000, 0xb5000001, 0x80479c00, + 0x1042b813, 0x5c42b802, 0x1022b815, 0x806702c0, + 0x00cfb803, 0x003fb0bc, 0x5822b801, 0x01cfb801, + 0x003f90bc, 0xb520ffff, 0xb0040000, 0xb4000002, + 0x80479180, 0xb5000001, 0x80479d80, 0x0442b813, + 0x5c42b802, 0x1022b815, 0x806702e0, 0x00cfb803, + 0x003fb0bc, 0x5822b801, 0x01cfb801, 0x003f90bc, + 0xb520ffff, 0x81270000, 0x80370000, 0x80b70000, + 0x81370000, 0x81b70000, 0x82370004, 0x82b7fffc, + 0xb6002016, 0x41498008, 0x51498814, 0x51498814, + 0x51418810, 0x51418810, 0x41818814, 0x0308a02a, + 0x49958820, 0x51898810, 0x51918828, 0x414d8814, + 0x0388a7ec, 0x494d8814, 0x49458810, 0x49458810, + 0x418d8810, 0x0308a02a, 0x49918fec, 0x51858814, + 0x51958fe4, 0x00000000, 0x0388a7ec, 0x92730080, + 0x009f033b, 0x5802b814, 0x90400300, 0x001f9802, + 0x00000000, 0xb0000000, 0xb4200016, 0x80170a00, + 0x80070000, 0xb6002001, 0x001fa020, 0xb0040000, + 0xb4200002, 0x80279000, 0xb5000001, 0x80279c00, + 0xac740080, 0x5c22b801, 0x11e1b803, 0x806f001f, + 0x80af001f, 0xb6000407, 0x80cf0280, 0x01ffb0bc, + 0x59e2b80f, 0x01afb80f, 0x01ff90bc, 0xb520ffff, + 0x91ef0020, 0x007f0320, 0x011f90cd, 0xaca30006, + 0x80c7b004, 0x10a5b814, 0x58a1b805, 0x10a5b806, + 0x0099b805, 0x8027b3dc, 0x5841b804, 0x1021b802, + 0x0159b801, 0x8027b3d0, 0x5841b804, 0x1021b802, + 0x0139b801, 0x80170c00, 0x0097b80a, 0xb0090000, + 0xb4200004, 0xb6000002, 0x015f8020, 0x009fe0ca, + 0xb5000004, 0x015fc024, 0xb6000002, 0x015f8020, + 0x009fe0ca, 0x00ffb81b, 0x00000000, 0x00000000, + 0x009f0011, 0x015f0012, 0xb0060000, 0xb4200007, + 0x968a0001, 0xb0140000, 0xb400000d, 0x80870001, + 0x009f2011, 0x954a0002, 0x015f2012, 0xb0060002, + 0xb4200007, 0x968a0002, 0xb0140000, 0xb4000004, + 0x80870001, 0x009f2011, 0x81470000, 0x015f2012, + 0x8364002b, 0x00bf2010, 0xb0060000, 0xb4200003, + 0xb0050000, 0xb4200001, 0x8364008d, 0xb0050000, + 0xb4200001, 0x836400b2, 0x00bf0010, 0xb0050000, + 0xb4200006, 0x83640983, 0x8364029d, 0x00000000, + 0x8364092b, 0x00000000, 0xb5000005, 0x00bf0010, + 0xb0050001, 0xb4000002, 0x00000000, 0x83640924, + 0x00ff0325, 0x82870000, 0xb6270002, 0x8364ff00, + 0x92940001, 0x80070001, 0x801eff70, 0x001f0010, + 0xb0000001, 0xb4000007, 0x001f033b, 0xb0000000, + 0xb4000002, 0x80270000, 0xb5000001, 0x80270001, + 0x003f233b, 0x00ffb81a, 0x00000000, 0x00000000, + 0x027f4001, 0x5e2ab813, 0x96310003, 0x81c70000, + 0x820700ff, 0xb0110000, 0xb4000005, 0x5a21b811, + 0x81c70200, 0x8207000e, 0x69d1b80e, 0x1210b811, + 0x01dfb0cd, 0x5e2cb813, 0x96310003, 0x023f2323, + 0x5e28b813, 0x96310003, 0x023f2322, 0x5e27b813, + 0x96310001, 0x023f2328, 0x5e23b813, 0x96310001, + 0x023f2321, 0x95f30007, 0x01ff2320, 0x920fe004, + 0x0258b810, 0x00000000, 0x1252b811, 0x025f2325, + 0x8167befc, 0x017f6195, 0x021f031c, 0x01df031d, + 0x3010b80f, 0xb4200003, 0x3011b80e, 0xb4200001, + 0xb5000021, 0x80270000, 0x80471000, 0x0017b802, + 0x8057ffff, 0xb6002001, 0x001fa021, 0x80270400, + 0x80679000, 0x5c62b803, 0xb6001809, 0x00cfb801, + 0x007fb0bc, 0x5862b803, 0x01afb803, 0x007f90bc, + 0x0047b86f, 0xb0020001, 0xb4c0fffd, 0x90630020, + 0x80679c00, 0x5c62b803, 0xb6001809, 0x00cfb801, + 0x007fb0bc, 0x5862b803, 0x01afb803, 0x007f90bc, + 0x0047b86f, 0xb0020001, 0xb4c0fffd, 0x90630020, + 0x01ff231c, 0x023f231d, 0x83970300, 0x82070000, + 0xb6320001, 0x039fa030, 0x00bf0010, 0x021f0324, + 0xb0100000, 0xb4200001, 0x80a70000, 0xb0050000, + 0xb4200008, 0xb0040000, 0xb4a00002, 0x80a70001, + 0xb5000004, 0x82070000, 0x021f204e, 0xb4000001, + 0x80a70002, 0xb0050001, 0xb4200007, 0x021f004e, + 0xb0100002, 0xb4a00002, 0x80a70002, 0x00ffb81b, + 0x92100001, 0x021f204e, 0x00000000, 0x00ffb81b, + 0x81530000, 0x003fb80a, 0x00000000, 0x00000000, + 0x003fb819, 0x00000000, 0x00000000, 0x81550000, + 0x8384fd73, 0x81470000, 0x015f61ee, 0x015f61ef, + 0x015f23a4, 0x8297050c, 0x82d7ffff, 0xb6000501, + 0x029fa02a, 0x8167e004, 0x116b0384, 0x0158b80b, + 0x019f0382, 0x015f237b, 0x017f0388, 0x116bb80a, + 0xb00c0008, 0xb4a00003, 0x80a70003, 0x00bf2010, + 0x00ffb81b, 0xb00a0005, 0xb4400003, 0xb00b0006, + 0xb4400001, 0x00ffb81b, 0x80a70004, 0x00bf2010, + 0x00ffb81b, 0x00000000, 0x00000000, 0x00000000, + 0x027f0388, 0x02bf037b, 0x02df0384, 0x02ff03a1, + 0x82970400, 0x8257ffff, 0x82d7ffff, 0xb6350003, + 0x81550001, 0x8357ffff, 0x029fa02a, 0x82970414, + 0xb6350003, 0x81550001, 0x83d7ffff, 0x029fa02a, + 0x81550001, 0xb00a0001, 0xb4200004, 0x814d0008, + 0x6149b80a, 0x954affff, 0x015f61ee, 0xb0160000, + 0xb4200007, 0x81550001, 0xb00a0001, 0xb4200004, + 0x814d0008, 0x6149b80a, 0x954affff, 0x015f61ef, + 0x81550001, 0xb00a0001, 0xb4200036, 0x82f50001, + 0x02ff23a1, 0xb0170001, 0xb420002c, 0x82970428, + 0xb6350003, 0x81550001, 0x00000000, 0x029fa02a, + 0x82970428, 0x81470000, 0x017f8034, 0xb00b0001, + 0xb4000004, 0x914a0001, 0x300ab815, 0xb480fffa, + 0xb5000001, 0x015f23a5, 0x81670000, 0xb0160002, + 0xb4200002, 0x81750001, 0x00000000, 0x017f233a, + 0x81550004, 0xadaa000c, 0x015f23a2, 0x81750004, + 0x916b0003, 0x017f23a3, 0x91ad0025, 0x01bf23a6, + 0xadab000c, 0x81e70000, 0x91ad0025, 0x01bf23a7, + 0x920a0001, 0x05abb810, 0xb00d0000, 0xb400000d, + 0xb62d0004, 0x81b50001, 0x65b0b80d, 0x19efb80d, + 0x92100001, 0x01ffb0be, 0xb5000006, 0x81a70000, + 0x82970428, 0xb6350001, 0x029fa02d, 0x01bf233a, + 0x01bf23a5, 0x82070000, 0x82270000, 0x82170428, + 0xb635003a, 0x01bf8030, 0xb00d0001, 0xb4200036, + 0x81d50001, 0x65b1b80e, 0x1a10b80d, 0xb00e0001, + 0xb4200031, 0x81b50002, 0xadad0003, 0xae510048, + 0x91cd000f, 0x91320868, 0x015f03a2, 0xad4a0004, + 0x92920700, 0x1189b80a, 0x0297b80c, 0x1194b80a, + 0x0317b80c, 0x01ff90be, 0x015f03a2, 0x017f03a3, + 0x064bb80a, 0x0107b80a, 0xb0120000, 0xb400001e, + 0xb632001d, 0x6928b80f, 0x95290001, 0xb0090000, + 0xb420000e, 0x81350004, 0x1129b80d, 0x029fa029, + 0x824d0004, 0x5a48b812, 0x5e48b812, 0x3009b80e, + 0xb4200002, 0x5e41b812, 0xb500000d, 0x5e42b812, + 0x81330040, 0x1a52b809, 0xb5000009, 0x0127b854, + 0x85290004, 0x0397b809, 0x0287b858, 0x86940004, + 0x013f803c, 0x0397b814, 0x029fa029, 0x025f803c, + 0x031fa032, 0x91080001, 0x92310001, 0x015f03a2, + 0x017f03a3, 0x013f033a, 0xb0090001, 0xb420001f, + 0x95300002, 0x95900001, 0x1929b80c, 0xb0090000, + 0xb400001a, 0x064bb80a, 0x0107b80a, 0xb6320017, + 0x6928b80f, 0x95290001, 0xb0090000, 0xb4200002, + 0x81350001, 0x013f23f8, 0x81a70700, 0x91ad0048, + 0x5982b808, 0x11adb80c, 0x0397b80d, 0x013f03f8, + 0xb0090001, 0xb4200005, 0x019f801c, 0x0196b80c, + 0x81b3ff80, 0x418cb80d, 0xb5000002, 0x019f801c, + 0x0196b80c, 0x039fa00c, 0x91080001, 0xb0160002, + 0xb420001a, 0xb0170001, 0xb4200008, 0xb00a0000, + 0xb4200002, 0x81270002, 0xb5000005, 0xb00a0002, + 0xb4400002, 0x81270003, 0xb5000001, 0x81270004, + 0x013f23a9, 0x81950001, 0xb00c0001, 0xb420000d, + 0x81a70000, 0x8397043c, 0xb6290006, 0x81150001, + 0x039fa028, 0xb0080001, 0xb4200001, 0x81a70001, + 0x00000000, 0x01bf23a8, 0xb5000002, 0x81a70000, + 0x01bf23a8, 0xb0170001, 0xb4200001, 0x81b50002, + 0x82970c20, 0xb6350003, 0x81550002, 0x00000000, + 0x029fa02a, 0xb0130001, 0xb4200001, 0x81150001, + 0x81c70000, 0xb6350014, 0x922e0c20, 0x015ff011, + 0xb00a0000, 0xb400000f, 0x922e0428, 0x015ff011, + 0xb00a0001, 0xb4200005, 0x922e044c, 0x0297b811, + 0x015f03a6, 0x029fa00a, 0xb5000006, 0x81550006, + 0xad4a0003, 0x922e044c, 0x0297b811, 0x914a0049, + 0x029fa00a, 0x91ce0004, 0xb0170001, 0xb420001e, + 0xb00d0000, 0xb400001c, 0x852d0001, 0x81470001, + 0x6549b80a, 0xad6a0003, 0x019f03a7, 0x058c03a6, + 0x81270000, 0xb00b0000, 0xb4000005, 0x300cb80b, + 0xb4800003, 0x058cb80b, 0x91290001, 0xb500fffb, + 0x81750004, 0x5961b80b, 0x839704ec, 0x0187b860, + 0x039fa02c, 0x039fa02a, 0x039fa029, 0x039fa02b, + 0xb0090000, 0xb4000004, 0xb6290003, 0x81550007, + 0x00000000, 0x00000000, 0x81c70000, 0xb635002e, + 0x922e0c20, 0x01fff011, 0xb00f0000, 0xb4000029, + 0x852f0001, 0x81470001, 0x6549b80a, 0xad6a0003, + 0x922e044c, 0x025fd811, 0x86520001, 0x0227b812, + 0x81270000, 0xb00b0000, 0xb4000005, 0x3012b80b, + 0xb4800003, 0x0652b80b, 0x91290001, 0xb500fffb, + 0x2e09b80b, 0x00000000, 0x3010b811, 0xb4600001, + 0x91290001, 0xae4e0004, 0x82150004, 0x9232049c, + 0x0297b811, 0x0187b860, 0x029fa02c, 0x029fa02a, + 0x029fa029, 0x029fa030, 0xb0090000, 0xb4000004, + 0xb6290003, 0x81550007, 0x00000000, 0x00000000, + 0x82270460, 0x1231b80e, 0x0217b811, 0x81550002, + 0x021fa00a, 0x91ce0004, 0xb0130001, 0xb420000c, + 0xb0080000, 0xb400000a, 0x81550004, 0x839704fc, + 0x0167b860, 0x039fa02b, 0x81670001, 0x039fa02b, + 0x8175000e, 0x81670002, 0x039fa02b, 0x039fa02a, + 0x81150001, 0xb0080001, 0xb420000a, 0x8135000b, + 0x5d2923aa, 0x95490180, 0x5d4723ab, 0x95490060, + 0x5d4523ac, 0x95490018, 0x5d4323ad, 0x95490007, + 0x015f23ae, 0x81350001, 0xb0090001, 0xb4200017, + 0x81350006, 0x013f23af, 0xb0170001, 0xb4200005, + 0x81550004, 0x00000000, 0x015f23b0, 0x81550003, + 0x015f23b1, 0x82970474, 0x83170488, 0xb6350004, + 0x81550007, 0x5e83a02a, 0x954a0007, 0x031fa02a, + 0xb0130001, 0xb4200005, 0x81750004, 0x00000000, + 0x017f23b2, 0x81750003, 0x017f23b3, 0xb0170001, + 0xb420000b, 0x81b50001, 0xb00d0001, 0xb4200008, + 0x81d50003, 0x59c8b80e, 0x91ce0300, 0x01df61da, + 0x81d50003, 0x59c8b80e, 0x91ce0300, 0x01df61db, + 0x81550001, 0xb00a0001, 0xb420004b, 0xb0170001, + 0xb4200001, 0x81550002, 0x82470000, 0x82270000, + 0xb6350004, 0x81750002, 0x6571b80b, 0x92310002, + 0x1a52b80b, 0xb0170001, 0xb4200017, 0xb00a0001, + 0xb4200011, 0x81150003, 0x91080001, 0x011f23a4, + 0x829709d0, 0x831709f0, 0x83970060, 0xb6280009, + 0x81750005, 0x00000000, 0x029fa02b, 0x81750004, + 0x00000000, 0x031fa02b, 0x81750003, 0x00000000, + 0x039fa02b, 0xb5000004, 0xb00a0002, 0xb4800002, + 0x81070000, 0x011f23a4, 0x82270000, 0x81270000, + 0xb6350025, 0x6a11b812, 0x92310002, 0x96100003, + 0xb0100001, 0xb4200018, 0xada90020, 0x81750003, + 0x920d0520, 0x0217b810, 0x920d05c0, 0x0297b810, + 0x920d0660, 0x0317b810, 0x5942b809, 0x920a050c, + 0x0397b810, 0x916b0001, 0x039fa02b, 0xb62b0009, + 0x81750005, 0x00000000, 0x021fa02b, 0x81750004, + 0x00000000, 0x029fa02b, 0x81750003, 0x00000000, + 0x031fa02b, 0xb5000007, 0xb0100002, 0xb4800005, + 0x59a2b809, 0x91ad050c, 0x0397b80d, 0x82070000, + 0x039fa010, 0x91290001, 0x81550001, 0xb00a0001, + 0xb4200007, 0x81550009, 0xb00a0000, 0xb4000004, + 0xb62a0003, 0x82150008, 0x00000000, 0x00000000, + 0xb00a0100, 0xb4a00007, 0x954aff00, 0xb6008003, + 0x82150010, 0x00000000, 0x00000000, 0x854a0100, + 0xb4e0fffa, 0x00ffb81b, 0x00000000, 0x00000000, + 0x81070000, 0x011f61dc, 0x011f61de, 0x011f61e0, + 0x011f03aa, 0x9108e0f4, 0x0138b808, 0x011f03ab, + 0x013f61ac, 0x9108e0f0, 0x0138b808, 0x011f03ac, + 0x013f61ad, 0x5901b808, 0x9108e0f8, 0x0139b808, + 0x011f03ad, 0x013f61ae, 0x5901b808, 0x9108e100, + 0x0139b808, 0x011f03ae, 0x013f61b0, 0x5901b808, + 0x9108e108, 0x0179b808, 0x013f03af, 0x017f61b1, + 0x02bf037b, 0x82970474, 0xb6350002, 0x015f8034, + 0x1929b80a, 0x011f03a1, 0xb0080001, 0xb4200002, + 0x015f03b0, 0x1929b80a, 0x019f0388, 0xb00c0001, + 0xb4200002, 0x015f03b2, 0x1929b80a, 0x013f61b3, + 0x015f03a8, 0xb00a0001, 0xb420003a, 0x81a70000, + 0x01bf237a, 0x83840056, 0x806f001f, 0x80af001f, + 0x80270300, 0x8067a800, 0x5c62b803, 0xb600080a, + 0x00cfb801, 0x007fb0bc, 0x5862b803, 0x01afb803, + 0x007f90bc, 0x0047b86f, 0xb0020001, 0xb4c0fffd, + 0x90210020, 0x90630020, 0x81a70001, 0x01bf237a, + 0x83840043, 0x838403c6, 0x81a70000, 0x01bf237a, + 0x82470400, 0x01bff012, 0x01bf23fa, 0x83840418, + 0x8384048f, 0x8384053e, 0x83840595, 0x806f001f, + 0x80af001f, 0x80270300, 0x8067ac00, 0x5c62b803, + 0xb600080a, 0x00cfb801, 0x007fb0bc, 0x5862b803, + 0x01cfb803, 0x007f90bc, 0x0047b86f, 0xb0020001, + 0xb4c0fffd, 0x90210020, 0x90630020, 0x81a70001, + 0x01bf237a, 0x82470404, 0x015ff012, 0x015f23fa, + 0x838403ff, 0x83840476, 0x83840525, 0x8384057c, + 0xb5000011, 0x81a70000, 0x01bf237a, 0xb635000e, + 0x8384001b, 0x01bf037a, 0xad4d0004, 0x00000000, + 0x914a0400, 0x01bff00a, 0x01bf23fa, 0x838403f0, + 0x83840467, 0x83840516, 0x8384056d, 0x01df037a, + 0x91ce0001, 0x01df237a, 0x019f0388, 0xb00c0001, + 0xb4200009, 0x02bf037b, 0x02bf237a, 0x838400e8, + 0x82470000, 0x025f23fa, 0x838403e1, 0x83840458, + 0x83840507, 0x8384055e, 0x00ffb81b, 0x00000000, + 0x80770000, 0x80f70000, 0x81770000, 0x81f70000, + 0x82770000, 0x82f70000, 0x83770000, 0x83f70000, + 0x8057ffff, 0x80d7ffff, 0x8157ffff, 0x81d7ffff, + 0x8257ffff, 0x82d7ffff, 0x8357ffff, 0x83d7ffff, + 0x017f037a, 0x5a42b80b, 0x01bf03a8, 0xb00d0001, + 0xb4200004, 0x011f9118, 0x013f9119, 0x7929b808, + 0xb5000002, 0x91b20460, 0x013ff00d, 0x91b20340, + 0x0297b80d, 0x00000000, 0x029fa009, 0x01df0384, + 0xb00e0000, 0xb4200005, 0xb00b0001, 0xb4200003, + 0x009f90c6, 0x00bf0391, 0xb5000002, 0x009f90cf, + 0x00bf0389, 0x83a4013a, 0x81870000, 0x019f61b5, + 0x019f61b4, 0x5a02b80b, 0x9190044c, 0x01dfd80c, + 0x01df61b6, 0x91900488, 0x01dff00c, 0x59c1b80e, + 0x918ee118, 0x01d9b80c, 0x019f03af, 0x01df61af, + 0x858c000f, 0x5986b80c, 0x91d00474, 0x01bff00e, + 0x59c2b80d, 0x11cc61b2, 0x81870000, 0x019f61b8, + 0x91900414, 0x01dfd80c, 0x01df61b7, 0xadab0010, + 0x00000000, 0x908d049c, 0x83a40189, 0xadcb0020, + 0x5982b80b, 0x908e0520, 0x90ae05c0, 0x90ce0660, + 0x928c050c, 0x00ff9814, 0x83a40161, 0x83a401b0, + 0x017f037a, 0x59c2b80b, 0x918e0428, 0x01fff00c, + 0xb00f0001, 0xb4200081, 0x023f03a5, 0x3011b80b, + 0xb420000f, 0x01c7b860, 0x01dfb0fa, 0x01df41dc, + 0x01df61e8, 0x01df41de, 0x01df61ea, 0x01df41e0, + 0x01df61ec, 0x01df41dd, 0x01df61e9, 0x01df41df, + 0x01df61eb, 0x01df41e1, 0x01df61ed, 0xb5000024, + 0x01c7b860, 0x01dfb0f9, 0x01df41dc, 0x01df61e2, + 0x01df41de, 0x01df61e4, 0x01df41e0, 0x01df61e6, + 0x01df41dd, 0x01df61e3, 0x01df41df, 0x01df61e5, + 0x01df41e1, 0x01df61e7, 0x803f0000, 0x00000000, + 0x00000000, 0x01df90fa, 0x003fb80e, 0x00000000, + 0x00000000, 0x81d50000, 0x00000000, 0x00000000, + 0x01df41e8, 0x01df61dc, 0x01df41ea, 0x01df61de, + 0x01df41ec, 0x01df61e0, 0x01df41e9, 0x01df61dd, + 0x01df41eb, 0x01df61df, 0x01df41ed, 0x01df61e1, + 0x029f03a6, 0x029f236a, 0x029f03a7, 0x029f236c, + 0x027f03a2, 0x92b3e128, 0x0298b815, 0x019f03b0, + 0x029f2368, 0x5982b80c, 0x01df03af, 0x85ce000f, + 0x59c6b80e, 0x11cc61b2, 0x82a70001, 0x02bf61b8, + 0x82a70000, 0x02bf61b9, 0x029f41da, 0x029f61ba, + 0x029f41db, 0x029f61bb, 0x019f03b1, 0x5981b80c, + 0x918ce118, 0x0299b80c, 0xad8b0048, 0x029f61af, + 0x59a2b813, 0x118cb80d, 0x928c0868, 0x029fb0fb, + 0x928c0700, 0x029fb0fc, 0x019f41bc, 0x918c0003, + 0x019f61bc, 0x5a02b80b, 0x91900414, 0x029fd80c, + 0x029f236e, 0x808704ec, 0x83a40119, 0x808709d0, + 0x80a709f0, 0x80c70060, 0x00ff03a4, 0x83a400f4, + 0x83a40143, 0x021f037a, 0x019f03a5, 0x300cb810, + 0xb4000016, 0x803f0000, 0x00000000, 0x00000000, + 0x01df90f9, 0x003fb80e, 0x00000000, 0x00000000, + 0x81d50000, 0x00000000, 0x00000000, 0x01df41e2, + 0x01df61dc, 0x01df41e4, 0x01df61de, 0x01df41e6, + 0x01df61e0, 0x01df41e3, 0x01df61dd, 0x01df41e5, + 0x01df61df, 0x01df41e7, 0x01df61e1, 0x029f41b6, + 0xa6d40100, 0xaeb40004, 0x81870000, 0x92b50c00, + 0x0397b815, 0xb6360001, 0x039fa02c, 0x00ffb81c, + 0x009f90cf, 0x00bf0389, 0x019f037a, 0x5982b80c, + 0x918c0340, 0x0397b80c, 0x81870000, 0x039fa00c, + 0x83a4007b, 0x81870000, 0x019f61b5, 0x019f61b4, + 0x81870007, 0x019f61b6, 0x019f03b3, 0x5981b80c, + 0x918ce118, 0x01b9b80c, 0x019f03af, 0x01bf61af, + 0x858c000f, 0x5986b80c, 0x01bf03b2, 0x59a2b80d, + 0x118cb80d, 0x019f61b2, 0x81870000, 0x019f61b7, + 0x019f61b8, 0x808704fc, 0x83a400d1, 0x80870000, + 0x80a70000, 0x80c70000, 0x80e70000, 0x83a400ac, + 0x83a400fb, 0x81470000, 0x81e70c1c, 0x0397b80f, + 0xb600f901, 0x039fa02a, 0x00ffb81c, 0x00000000, + 0x82270000, 0x023f2011, 0x0227b860, 0x023fb0ff, + 0x02bf9006, 0x92350028, 0x8213001f, 0x9210e000, + 0x3011b810, 0xb4800001, 0x86312000, 0x021f4193, + 0x5a01b810, 0x86100028, 0x83a4fa8c, 0x82270000, + 0x003fb811, 0x02bf9006, 0x5aa3b815, 0x82338000, + 0x1a31b815, 0x003fb811, 0x8067e950, 0x5c62b803, + 0x81f50000, 0x80270400, 0xb6000409, 0x814fffc0, + 0x00cfb801, 0x007fb0bc, 0x5862b803, 0x01cfb803, + 0x007f90bc, 0xb520ffff, 0x90210020, 0x90630020, + 0x82870000, 0x81f50010, 0x019f4193, 0x5d61b80c, + 0x5d43b80c, 0x114ab80b, 0x0187b80a, 0x960cff00, + 0x92100100, 0x858c0001, 0xb62c000c, 0x81f50010, + 0x5e28b80f, 0xb6000209, 0x5a48b814, 0x9652ff00, + 0x5e68b814, 0x5981b813, 0x918c1000, 0x01dfd80c, + 0x2252b811, 0x2292b80e, 0x962f00ff, 0x81870000, + 0x86100100, 0xb4e0fff0, 0xb00a0000, 0xb4000009, + 0x81670000, 0xb0140000, 0xb4000001, 0x81670001, + 0x017f2012, 0x258a4193, 0x918c0001, 0x81470000, + 0xb500ffe2, 0x81670000, 0xb0140000, 0xb4000001, + 0x81670002, 0x116b0012, 0x803f0000, 0x00000000, + 0x00000000, 0x003fb811, 0x00000000, 0x00000000, + 0x81f50000, 0x017f2012, 0x00ffb81a, 0x00000000, + 0x61f4b804, 0x91ef0001, 0x8233003f, 0x9a31ffff, + 0x5a02b804, 0x1610b811, 0x92510001, 0x1a10b812, + 0x029f03fb, 0xb0140001, 0xb4200012, 0x5a21b805, + 0x92b1e910, 0x0299b815, 0x5a22b805, 0x5a90b814, + 0x6290b814, 0x92b1e890, 0x11efb814, 0x029bb815, + 0x8233ff80, 0x3011b814, 0xb4000006, 0x4294b811, + 0x00000000, 0x0288b814, 0x4210b814, 0x00000000, + 0x0208b810, 0x029f9003, 0x82f3007f, 0x9af7ffff, + 0x3017b814, 0xb4000003, 0x4210b814, 0x00000000, + 0x0208b810, 0x82270000, 0x02c7b810, 0xb0160000, + 0xb400000a, 0x1676b812, 0x3013b812, 0xb4000003, + 0x5ac1b816, 0x92310001, 0xb500fffa, 0x81d3ff80, + 0x3010b80e, 0xb4200001, 0x1ad6b80e, 0x05efb811, + 0x027f037a, 0x5a62b813, 0x92730340, 0x0397b813, + 0x023fd813, 0x02dfb0fd, 0x5a30b811, 0x6230b811, + 0x0631b80f, 0x3010b812, 0xb4200001, 0x92310001, + 0x82470000, 0xb0110000, 0xb4800004, 0x82470003, + 0xb0110003, 0xb4400001, 0x0247b811, 0x039fa012, + 0x124f61bc, 0x00ffb81d, 0x00000000, 0x00000000, + 0x83970a10, 0x82070000, 0xb6003201, 0x039fa030, + 0xb0070000, 0xb4000019, 0x029f41b4, 0x0297b804, + 0x0317b805, 0x0397b806, 0xb6270014, 0x12948034, + 0x01df8038, 0xb00e0000, 0xb4a0000e, 0x02bf803c, + 0x5a02b814, 0x91b00a10, 0x0217b80d, 0xb62e0008, + 0x96150003, 0x91f00001, 0xadef0080, 0xb0150004, + 0xb4600001, 0x85ef0280, 0x021fa02f, 0x92940001, + 0xb5000001, 0x021f803c, 0x00000000, 0x00ffb81d, + 0x0397b804, 0x021f036a, 0x027f803c, 0x029f803c, + 0x02bf803c, 0x02df803c, 0x5a22b810, 0x92311000, + 0x0397b811, 0xb0100000, 0xb4200001, 0x039fa036, + 0xb0150000, 0xb4000021, 0x0227b860, 0x023fb0ff, + 0xb520ffff, 0x803f0000, 0x82138000, 0x1a10b813, + 0x003fb810, 0x00000000, 0x00000000, 0x82150000, + 0x00000000, 0xb635000d, 0x82550007, 0x5a42b812, + 0x9212e4b8, 0x025bb810, 0x8227000c, 0xb6000307, + 0x68d1b812, 0x94c6000f, 0x84c60002, 0x12d6b806, + 0xb6340001, 0x039fa036, 0x86310004, 0x803f0000, + 0x82138000, 0x023f90ff, 0x1a31b810, 0x003fb811, + 0x00000000, 0x00000000, 0x82150000, 0x00ffb81d, + 0x00ff41b5, 0x011f41b4, 0x019f41af, 0x01bf41ae, + 0x01df41ba, 0x01ff41bb, 0x82070000, 0x023f0380, + 0x82470000, 0xae310032, 0x029f41b3, 0x5862b807, + 0x90431000, 0x81970ad8, 0x0217b802, 0x90430c00, + 0x0297b802, 0x0317b802, 0x912802a4, 0x007ff009, + 0x58478030, 0x792341b6, 0x0529b807, 0x019fa029, + 0xb0080014, 0xb4800011, 0xa5420c00, 0x031fa02a, + 0x84690001, 0xb4a00011, 0xb623000b, 0x58678030, + 0xa4030c00, 0x031fa020, 0x044ab800, 0x0056b802, + 0x5c41b802, 0xf84200ff, 0x90620100, 0x005ff003, + 0x7d40b80a, 0x114ab802, 0xb5000004, 0xa5420c00, + 0x58478010, 0xa5620c00, 0x031fa02a, 0xb0080016, + 0xb4400043, 0xb0080013, 0xb440002c, 0xb0080006, + 0xb4400024, 0xb0080005, 0xb4400014, 0xb0080002, + 0xb4400006, 0x80440030, 0x015f619c, 0x05cab80c, + 0x05eab80d, 0x066eb810, 0xb500003c, 0x8044002a, + 0x300a419c, 0xb4800001, 0x82470001, 0x015f619c, + 0xb0120001, 0xb4200001, 0xb500001a, 0x05cab80c, + 0x05eab80d, 0x066eb810, 0xb5000030, 0x001f41b6, + 0xb0000007, 0xb4000001, 0x8044001b, 0x300a419c, + 0xb4800001, 0x82470001, 0xb0120001, 0xb4200001, + 0xb500000c, 0x05cab80c, 0x05eab80d, 0x066eb810, + 0xb5000022, 0x80440010, 0x840b0100, 0x300ab800, + 0xb4200001, 0x86100040, 0xb5000002, 0x86100080, + 0xfe100000, 0x046e41ad, 0x042ab80c, 0x7dc1b803, + 0x044f41ac, 0x042ab80d, 0x7de1b802, 0x046eb810, + 0x7e6fb803, 0xb5000011, 0x840b0100, 0x3000b80a, + 0xb4200002, 0x82070180, 0x00ffb802, 0x300ab80b, + 0xb4a00002, 0x86100040, 0xfe100000, 0x00ffb802, + 0x046e41ad, 0x042ab80c, 0x7dc1b803, 0x044f41ac, + 0x042ab80d, 0x7de1b802, 0x7e6eb80f, 0x380a41b0, + 0xb4600003, 0x242a41b0, 0x5c22b801, 0x1273b801, + 0xb0140000, 0xb4200002, 0x80071fe0, 0xb5000016, + 0x1011b808, 0x5801b800, 0x9020e26c, 0x0079b801, + 0x5842b808, 0x90420a10, 0x7c03b813, 0x003f9802, + 0x1000b801, 0x003f41b2, 0x5830b801, 0x6030b801, + 0x0400b801, 0x003f41b1, 0x5830b801, 0x6030b801, + 0x0400b801, 0xfc000000, 0xf8001fe0, 0x94001fe0, + 0x100041b1, 0x9400ffff, 0x8067003f, 0xb6290008, + 0x005f8014, 0x0442b800, 0x9442ffff, 0x5850b802, + 0x6050b802, 0xfc420000, 0x5c45b802, 0x7a82a023, + 0x10e7b809, 0x91080001, 0x300741b6, 0xb420ff6a, + 0x019f61af, 0x01bf61ae, 0x01df61ba, 0x01ff61bb, + 0x00ff41b5, 0x011f41b4, 0x019f41b8, 0x01bf41b7, + 0x01df41dd, 0x01ff41df, 0x021f41e1, 0x027f90fd, + 0x029f41bc, 0x02ff41dc, 0x031f41de, 0x033f41e0, + 0x5822b807, 0x91210c00, 0x0117b809, 0x81970ad8, + 0x91211000, 0x0217b809, 0x91210c00, 0x0317b809, + 0x80170ba0, 0x013f802c, 0xb629005f, 0x003f8038, + 0xb001000e, 0xb440001e, 0xb001000c, 0xb4400054, + 0xb001000a, 0xb4400043, 0xb0010007, 0xb440003c, + 0xb0010005, 0xb440002b, 0xb0010000, 0xb440001a, + 0xb00d0001, 0xb4200010, 0x005f418f, 0xac42bb75, + 0x8073005a, 0x9442ffff, 0x005f618f, 0x95628000, + 0x5848b802, 0xb00b8000, 0xb4200002, 0x8173ff00, + 0x1842b80b, 0x9863827a, 0x4043b802, 0x00000000, + 0x0048b802, 0xb500003f, 0x80470000, 0xb500003d, + 0x8401000f, 0x5c22b800, 0x902102d8, 0x001ff001, + 0x004db800, 0xb5000037, 0x86f70001, 0xb4600005, + 0x80750005, 0x5862b803, 0x9043e44c, 0x01d9b802, + 0x82e70002, 0x5c4cb80e, 0x9462000f, 0x5862b803, + 0x90630200, 0x005f9803, 0x59c4b80e, 0x95ceffff, + 0xb5000028, 0x87180001, 0xb4600005, 0x80750007, + 0x5862b803, 0x9043e4b8, 0x01f9b802, 0x83070002, + 0x5c4cb80f, 0x9462000f, 0x5862b803, 0x9063020c, + 0x005f9803, 0x59e4b80f, 0x95efffff, 0xb5000019, + 0x80750003, 0x5862b803, 0x90630220, 0x005f9803, + 0xb5000014, 0x87390001, 0xb4600005, 0x80750007, + 0x5862b803, 0x9043e6ac, 0x0219b802, 0x83270001, + 0x5c4cb810, 0x9462000f, 0x5862b803, 0x9063023c, + 0x005f9803, 0x5a04b810, 0x9610ffff, 0xb5000005, + 0x80750004, 0x5862b803, 0x90630268, 0x005f9803, + 0x00000000, 0x001fa022, 0x80170ba0, 0xb00c0001, + 0xb4200035, 0x023f90fb, 0x007f9811, 0x025f90fc, + 0x06d4b803, 0x007f9812, 0x4083b813, 0x00000000, + 0x0088b804, 0xb629002b, 0x24368030, 0x9421ffff, + 0x5830b801, 0x6030b801, 0x40448020, 0xb0010020, + 0xb4800003, 0x80470000, 0x80670000, 0xb500000e, + 0xb0010000, 0xb4a00004, 0x82b30080, 0x6aa1b815, + 0x4042b815, 0xb5000008, 0x6c41b802, 0x82a70017, + 0x12b5b801, 0x6875b803, 0x1842b803, 0x00000000, + 0x00000000, 0x00000000, 0x0108a022, 0x007f41b9, + 0x90630001, 0x007f61b9, 0xb003000c, 0xb420000c, + 0x92310004, 0x023fb0fb, 0x007f9811, 0x92520004, + 0x06d4b803, 0x025fb0fc, 0x007f9812, 0x80470000, + 0x4083b813, 0x00000000, 0x0088b804, 0x005f61b9, + 0x00000000, 0xb500001a, 0xb6290019, 0x24348030, + 0x9421ffff, 0x5830b801, 0x6030b801, 0x40538020, + 0xb0010020, 0xb4800003, 0x80470000, 0x80670000, + 0xb500000e, 0xb0010000, 0xb4a00004, 0x82b30080, + 0x6aa1b815, 0x4042b815, 0xb5000008, 0x6c41b802, + 0x82a70017, 0x12b5b801, 0x6875b803, 0x1842b803, + 0x00000000, 0x00000000, 0x00000000, 0x0108a022, + 0x10e7b809, 0x91080001, 0x300741b6, 0xb420ff48, + 0x00ff61b5, 0x011f61b4, 0x01df61dd, 0x01ff61df, + 0x021f61e1, 0x02ff61dc, 0x031f61de, 0x033f61e0, + 0x00ffb81d, 0x00000000, 0x00000000, 0x00000000, + 0x8057ffff, 0x80d7ffff, 0x8157ffff, 0x81d7ffff, + 0x8257ffff, 0x808f0000, 0x003f9113, 0x005f9114, + 0x7141b802, 0x80cf0700, 0x8027b064, 0x5c22b801, + 0x003fb0bc, 0x5822b801, 0x01cfb801, 0x003f90bc, + 0xb520ffff, 0x80cf0704, 0x8027b06c, 0x5c22b801, + 0x003fb0bc, 0x5822b801, 0x01cfb801, 0x003f90bc, + 0xb520ffff, 0x81e7043c, 0x82071c00, 0x82271c10, + 0x019f03a9, 0x806f001f, 0x80af001f, 0x80270400, + 0x8067a800, 0x5c62b803, 0xb6000808, 0x00cfb801, + 0x007fb0bc, 0x5862b803, 0x01cfb803, 0x007f90bc, + 0xb520ffff, 0x90210020, 0x90630020, 0x81971000, + 0x82170c00, 0xb6000004, 0x003f800c, 0x005f8010, + 0x021fa021, 0x019fa022, 0x00bfd810, 0x003fd811, + 0x70c1b80a, 0x001f980f, 0x91ef0004, 0x92100002, + 0x92310002, 0x5822b805, 0x90411000, 0x0197b802, + 0x90410c00, 0x0217b802, 0x0466b805, 0xb0000000, + 0xb4000005, 0xb6230004, 0x003f8010, 0x005f800c, + 0x1201a022, 0x0581a022, 0x858c0001, 0xb4e0ffea, + 0x80270400, 0x8067ac00, 0x5c62b803, 0xb6000808, + 0x00cfb801, 0x007fb0bc, 0x5862b803, 0x01afb803, + 0x007f90bc, 0xb520ffff, 0x90210020, 0x90630020, + 0x00ffb81c, 0x00000000, 0x00000000, 0x00000000, + 0x808f0000, 0x806f001f, 0x80af001f, 0x003f037a, + 0xb0010000, 0xb4400030, 0x81a7b7fc, 0x5da2b80d, + 0x80670500, 0xb6000208, 0x00cfb803, 0x01bfb0bc, + 0x59a2b80d, 0x01cfb80d, 0x01bf90bc, 0xb520ffff, + 0x90630020, 0x91ad0020, 0x81c7b8fc, 0x5dc2b80e, + 0x80670540, 0xb6000208, 0x00cfb803, 0x01dfb0bc, + 0x59c2b80e, 0x01cfb80e, 0x01df90bc, 0xb520ffff, + 0x90630020, 0x91ce0020, 0x81a7b3fc, 0x5da2b80d, + 0x80670600, 0xb6000408, 0x00cfb803, 0x01bfb0bc, + 0x59a2b80d, 0x01cfb80d, 0x01bf90bc, 0xb520ffff, + 0x90630020, 0x91ad0020, 0x81c7b5fc, 0x5dc2b80e, + 0x80670680, 0xb6000408, 0x00cfb803, 0x01dfb0bc, + 0x59c2b80e, 0x01cfb80e, 0x01df90bc, 0xb520ffff, + 0x90630020, 0x91ce0020, 0x005f03fa, 0xb0020000, + 0xb4000024, 0x8057ffff, 0x80d7ffff, 0x8157ffff, + 0x81d7ffff, 0x8257ffff, 0x82d7ffff, 0x8357ffff, + 0x83d7ffff, 0x83971300, 0x83171200, 0x82971100, + 0x82171000, 0x81170c00, 0x81970ff8, 0x80171400, + 0x80971500, 0x005f802c, 0x001f8028, 0xb6004010, + 0x41028000, 0x51008004, 0x007f876c, 0x0208a028, + 0x41008000, 0x49028004, 0x003f8068, 0x0388a028, + 0x41038000, 0x51018004, 0x005f802c, 0x0288a028, + 0x41018020, 0x49038024, 0x001f8028, 0x0308a028, + 0x00ffb81c, 0x83d7ffff, 0x8357ffff, 0x82d7ffff, + 0x8257ffff, 0x8157ffff, 0x81d7ffff, 0x8057ffff, + 0x80d7ffff, 0x82971200, 0x82171000, 0x81170c00, + 0x81970ffc, 0x83171800, 0x83971a00, 0x83370000, + 0x83b70000, 0x81370008, 0x81b7fff8, 0x4119880c, + 0xb6008006, 0x511d8808, 0x41498838, 0x0208a028, + 0x494d883c, 0x4119880c, 0x0288a02a, 0x00ffb81c, + 0x82670000, 0x82a70000, 0x003f037a, 0xb0010000, + 0xb4400018, 0x81a7bdfc, 0x5da2b80d, 0x80670580, + 0xb6000208, 0x00cfb803, 0x01bfb0bc, 0x59a2b80d, + 0x01cfb80d, 0x01bf90bc, 0xb520ffff, 0x90630020, + 0x91ad0020, 0x81a7eb70, 0x5da2b80d, 0x806705c0, + 0xb6000208, 0x00cfb803, 0x01bfb0bc, 0x59a2b80d, + 0x01cfb80d, 0x01bf90bc, 0xb520ffff, 0x90630020, + 0x91ad0020, 0x02bf03fa, 0x808f0000, 0xb0150000, + 0xb4000006, 0x81470040, 0x81670003, 0x81870002, + 0x81a71000, 0x81c71300, 0xb5000005, 0x81470080, + 0x81670004, 0x81870001, 0x81a71000, 0x81c71200, + 0x0017b80d, 0x0097b80e, 0x108db80a, 0x0117b804, + 0x108eb80a, 0x0197b804, 0x5841b80a, 0x108db802, + 0x0217b804, 0x108eb802, 0x0297b804, 0x106ab802, + 0x108db803, 0x0317b804, 0x108eb803, 0x0397b804, + 0x5ea2b80a, 0xb6350020, 0x001f8000, 0x003f8008, + 0x005f8004, 0x007f800c, 0x10c08010, 0x10a18018, + 0x10828014, 0x10e3801c, 0x1246b805, 0x0686b805, + 0x10c4b807, 0x0484b807, 0x80e70000, 0x80a70000, + 0x0008a032, 0x0108a034, 0x0088a026, 0x0188a024, + 0x04c08010, 0x04a18018, 0x04828014, 0x04e3801c, + 0x0646b807, 0x1286b807, 0x10c4b805, 0x0484b805, + 0x80e70000, 0x80a70000, 0x0208a032, 0x0308a034, + 0x0288a026, 0x0388a024, 0x5de1b80a, 0x82070004, + 0xb62b002a, 0x0017b80d, 0x0097b80e, 0x102db80f, + 0x0117b801, 0x104eb80f, 0x0197b802, 0x82171600, + 0x82971700, 0x0037b80f, 0x00b7b80f, 0x0137b80f, + 0x01b7b80f, 0xb630001b, 0x003f8030, 0x005f8034, + 0x5ee2b80f, 0x8013007f, 0x9800ffff, 0xb6370011, + 0x41008000, 0x51018008, 0x4902800c, 0x40c08000, + 0x0008a028, 0x48c18008, 0x50c2800c, 0x42808004, + 0x00c8b806, 0x52828008, 0x5281800c, 0x41008004, + 0x0088a034, 0x49028008, 0x4901800c, 0x011fa026, + 0x0188a028, 0x001f8001, 0x001f8005, 0x001f8009, + 0x001f800d, 0x5de1b80f, 0x5a01b810, 0x0017b80d, + 0x0097b80e, 0x902d0004, 0x0117b801, 0x904e0004, + 0x0197b802, 0x82171600, 0x82971700, 0x5ea1b80a, + 0x8013007f, 0x9800ffff, 0xb6350013, 0x003f8030, + 0x005f8034, 0x42408000, 0x52418008, 0x4a42800c, + 0x41008000, 0x0008a052, 0x49018008, 0x5102800c, + 0x42808004, 0x0108b808, 0x52828008, 0x5281800c, + 0x40c08004, 0x0088a054, 0x48c28008, 0x48c1800c, + 0x011fa048, 0x0188a046, 0x81a71100, 0x81c71200, + 0x858c0001, 0xb4e0ff7e, 0x00ffb81c, 0x00000000, + 0x005f03fa, 0x00000000, 0xb0020000, 0xb4000034, + 0x81b70080, 0x81d7ffff, 0x81f70001, 0x82370080, + 0x8257ffff, 0x82770001, 0x82b70080, 0x82d7ffff, + 0x82f70001, 0x83370080, 0x8357ffff, 0x83770001, + 0x81971000, 0x82171100, 0x82971200, 0x83171300, + 0x815703fc, 0x81370200, 0x81170c00, 0x83d703fc, + 0x83b70200, 0x83970f00, 0x8057ffff, 0x80d7ffff, + 0x80171400, 0x80971500, 0x001f800d, 0x003f8019, + 0xb6004012, 0x41008000, 0x51018004, 0x007f8011, + 0x0128a008, 0x41018000, 0x49008004, 0x009f8015, + 0x03a8a008, 0x41038000, 0x51048004, 0x001f800d, + 0x03a8a008, 0x41048020, 0x49038024, 0x003f8019, + 0x0128a008, 0x005f8028, 0x005f803c, 0x81f70000, + 0x82770000, 0x82f70000, 0x83770000, 0x00ffb81c, + 0x82370040, 0x8257ffff, 0x82770001, 0x82b70040, + 0x82d7ffff, 0x82f70001, 0x82171000, 0x82971200, + 0x8157ffff, 0x81170c00, 0x81d7ffff, 0x81970e00, + 0x8057ffff, 0x80d7ffff, 0x80171800, 0x80971a00, + 0xb600800a, 0x001f8011, 0x003f8015, 0x41008000, + 0x51018004, 0x00000000, 0x0108a028, 0x41018020, + 0x49008024, 0x00000000, 0x0188a028, 0x82770000, + 0x82f70000, 0x00ffb81c, 0x00000000, 0x00000000, + 0x8057ffff, 0x80d7ffff, 0x8157ffff, 0x808f0000, + 0x015f0384, 0x017f037a, 0xac4a0006, 0x8027b004, + 0x1042b80b, 0x5841b802, 0x1021b802, 0x0159b801, + 0x013f0325, 0x01bf0320, 0x5822b80b, 0x90210340, + 0x00ff9801, 0x8027b2e8, 0x5842b807, 0x1021b802, + 0x025bb801, 0x80070000, 0xac4d0006, 0x8027b004, + 0x1042b800, 0x5841b802, 0x1021b802, 0x0199b801, + 0x00000000, 0xac4c0006, 0x8027b078, 0x1042b80a, + 0x5842b802, 0x1021b802, 0x011bb801, 0x00000000, + 0x40d2b808, 0x00000000, 0xb0060000, 0xb4000080, + 0x005f033b, 0x80278400, 0xac600080, 0x5c22b801, + 0x10a1b803, 0xb0020000, 0xb4200002, 0x80279000, + 0xb5000001, 0x80279c00, 0x5c22b801, 0x11e1b803, + 0x80470300, 0x5822b800, 0x1042b801, 0x003f9802, + 0x806f001f, 0x80af001f, 0xb0010000, 0xb4200024, + 0x80170c00, 0x80971000, 0x003f8020, 0xb6000003, + 0x4201b806, 0x003f8020, 0x0088a030, 0x80270400, + 0xb6000208, 0x00cfb801, 0x00bfb0bc, 0x58a2b805, + 0x01afb805, 0x00bf90bc, 0xb520ffff, 0x90210020, + 0x90a50020, 0xb6000408, 0x00cfb801, 0x01ffb0bc, + 0x59e2b80f, 0x01afb80f, 0x01ff90bc, 0xb520ffff, + 0x90210020, 0x91ef0020, 0xb6000208, 0x00cfb801, + 0x00bfb0bc, 0x58a2b805, 0x01afb805, 0x00bf90bc, + 0xb520ffff, 0x90210020, 0x90a50020, 0xb5000043, + 0x80270400, 0x0087b805, 0x01c7b80f, 0xb6000208, + 0x00cfb801, 0x009fb0bc, 0x5882b804, 0x01cfb804, + 0x009f90bc, 0xb520ffff, 0x90210020, 0x90840020, + 0xb6000408, 0x00cfb801, 0x01dfb0bc, 0x59c2b80e, + 0x01cfb80e, 0x01df90bc, 0xb520ffff, 0x90210020, + 0x91ce0020, 0xb6000208, 0x00cfb801, 0x009fb0bc, + 0x5882b804, 0x01cfb804, 0x009f90bc, 0xb520ffff, + 0x90210020, 0x90840020, 0x80170c00, 0x80971000, + 0x8053007f, 0x9842ffff, 0xb6000004, 0x42028004, + 0x4a068020, 0x00000000, 0x0088a030, 0x80270400, + 0xb6000208, 0x00cfb801, 0x00bfb0bc, 0x58a2b805, + 0x01afb805, 0x00bf90bc, 0xb520ffff, 0x90210020, + 0x90a50020, 0xb6000408, 0x00cfb801, 0x01ffb0bc, + 0x59e2b80f, 0x01afb80f, 0x01ff90bc, 0xb520ffff, + 0x90210020, 0x91ef0020, 0xb6000208, 0x00cfb801, + 0x00bfb0bc, 0x58a2b805, 0x01afb805, 0x00bf90bc, + 0xb520ffff, 0x90210020, 0x90a50020, 0x5822b800, + 0x90210300, 0x0117b801, 0x80470001, 0x011fa002, + 0x90000001, 0x3000b809, 0xb480ff6b, 0x00ffb81c, + 0x8057ffff, 0x013f0325, 0x015f033b, 0x80171000, + 0x80070000, 0xb6002001, 0x001fa020, 0xb00a0001, + 0xb4c00002, 0x81679000, 0xb5000001, 0x81679c00, + 0x5d62b80b, 0x81878400, 0x5d82b80c, 0x80070000, + 0x5822b800, 0x90410300, 0x003f9802, 0x00000000, + 0xb0010000, 0xb4200019, 0xac400080, 0x00000000, + 0x10ccb802, 0x10abb802, 0x806f001f, 0x80af001f, + 0x80cf0400, 0xb6000408, 0xb520ffff, 0x00dfb0bc, + 0x58c2b806, 0x01afb806, 0x00df90bc, 0xb520ffff, + 0x80cf0400, 0x90c60020, 0x80cf0400, 0xb6000407, + 0x00bfb0bc, 0x58a2b805, 0x01afb805, 0x00bf90bc, + 0xb520ffff, 0x80cf0400, 0x90a50020, 0x90000001, + 0x3000b809, 0xb480ffde, 0x00ffb81b, 0x8057ffff, + 0x013f0325, 0x80171000, 0x80070000, 0xb6002001, + 0x001fa020, 0x81878400, 0x5d82b80c, 0x80070000, + 0x5822b800, 0x90410300, 0x003f9802, 0x00000000, + 0xb0010000, 0xb420000f, 0xac400080, 0x00000000, + 0x10ccb802, 0x806f001f, 0x80af001f, 0x80cf0400, + 0xb6000408, 0xb520ffff, 0x00dfb0bc, 0x58c2b806, + 0x01afb806, 0x00df90bc, 0xb520ffff, 0x80cf0400, + 0x90c60020, 0x90000001, 0x3000b809, 0xb480ffe8, + 0x00ffb81b, 0x8057ffff, 0x80d7ffff, 0x8157ffff, + 0x8139b000, 0x00000000, 0xb0090000, 0xb4000012, + 0x806f001f, 0x80af001f, 0x80cf0400, 0x013fb0bc, + 0x5922b809, 0x01cfb809, 0x013f90bc, 0xb520ffff, + 0x806f0003, 0x80af0003, 0x80cf0420, 0x91290020, + 0x013fb0bc, 0x5922b809, 0x01cfb809, 0x013f90bc, + 0xb520ffff, 0xb5000233, 0x80270000, 0x80171000, + 0xb6002401, 0x001fa021, 0x007f0384, 0x009f0320, + 0x00bf0385, 0x00df0386, 0x80e7b36c, 0x5821b803, + 0x1021b807, 0x0159b801, 0x5821b804, 0x1021b807, + 0x0179b801, 0x80e7b37c, 0x5821b803, 0x1021b807, + 0x0199b801, 0x5821b804, 0x1021b807, 0x01b9b801, + 0x80e7b38c, 0x5821b803, 0x1021b807, 0x01d9b801, + 0x5821b804, 0x1021b807, 0x01f9b801, 0x005f0385, + 0x8027b39c, 0x5842b802, 0x1021b802, 0x021bb801, + 0x005f0386, 0x8027b3ac, 0x5842b802, 0x1021b802, + 0x023bb801, 0x027f0383, 0x003f0328, 0x005f4195, + 0xb0130007, 0xb42000df, 0xb0010000, 0xb42000dd, + 0xb0020000, 0xb40000db, 0xb0030002, 0xb48000d9, + 0x029bb802, 0x82a7b108, 0xb00b0001, 0xb4200001, + 0xb5000005, 0xb00b0002, 0xb4200002, 0x92b500a0, + 0xb5000001, 0x92b50140, 0xb0030004, 0xb4600002, + 0x82870000, 0xb5000006, 0xb0030006, 0xb4600004, + 0xb0140001, 0xb4a00002, 0x82870001, 0xb5000000, + 0xac54000a, 0x806f0009, 0x80af0009, 0x5c22b815, + 0x80cf0440, 0x1021b802, 0x003fb0bc, 0x5822b801, + 0x01cfb801, 0x003f90bc, 0xb520ffff, 0xb0030003, + 0xb400000f, 0xb0030004, 0xb400001d, 0xb0030005, + 0xb400002b, 0xb0030006, 0xb4000042, 0xb0030007, + 0xb4000059, 0x80171000, 0x005f9440, 0x001fa002, + 0x80171038, 0x005f9440, 0x001fa002, 0xb5000073, + 0x80171000, 0x005f9440, 0x001fa002, 0x80171004, + 0x005f9443, 0x001fa002, 0x8017101c, 0x005f9446, + 0x001fa002, 0x80171034, 0x005f9449, 0x001fa002, + 0x80171038, 0x005f9440, 0x001fa002, 0xb5000063, + 0x80171000, 0x005f9440, 0x001fa002, 0x80171008, + 0x005f9441, 0x001fa002, 0x80171020, 0x005f9444, + 0x001fa002, 0x80171034, 0x005f9440, 0x001fa002, + 0x80171038, 0x005f9447, 0x001fa002, 0xb5000053, + 0x80171000, 0x005f9440, 0x001fa002, 0x80171004, + 0x005f9443, 0x001fa002, 0x8017100c, 0x005f9441, + 0x001fa002, 0x8017101c, 0x005f9446, 0x001fa002, + 0x80171024, 0x005f9444, 0x001fa002, 0x80171034, + 0x005f9449, 0x001fa002, 0x80171038, 0x005f9440, + 0x001fa002, 0x8017103c, 0x005f9447, 0x001fa002, + 0xb500003a, 0x80171000, 0x005f9440, 0x001fa002, + 0x80171008, 0x005f9441, 0x001fa002, 0x8017100c, + 0x005f9442, 0x001fa002, 0x80171020, 0x005f9444, + 0x001fa002, 0x80171024, 0x005f9445, 0x001fa002, + 0x80171034, 0x005f9440, 0x001fa002, 0x80171038, + 0x005f9447, 0x001fa002, 0x8017103c, 0x005f9448, + 0x001fa002, 0xb5000021, 0x80171000, 0x005f9440, + 0x001fa002, 0x80171004, 0x005f9443, 0x001fa002, + 0x8017100c, 0x005f9441, 0x001fa002, 0x80171010, + 0x005f9442, 0x001fa002, 0x8017101c, 0x005f9446, + 0x001fa002, 0x80171024, 0x005f9444, 0x001fa002, + 0x80171028, 0x005f9445, 0x001fa002, 0x80171034, + 0x005f9449, 0x001fa002, 0x80171038, 0x005f9440, + 0x001fa002, 0x8017103c, 0x005f9447, 0x001fa002, + 0x80171040, 0x005f9448, 0x001fa002, 0x80270001, + 0x803eff90, 0x80171000, 0x82b30020, 0x9ab50000, + 0x40158020, 0xb6000501, 0x48158020, 0x82b30020, + 0x9ab50000, 0x80470000, 0x3015b800, 0xb4600006, + 0x80171000, 0x83840226, 0xb6000603, 0x40028000, + 0x00000000, 0x0008a020, 0x80171018, 0x82b30020, + 0x9ab50000, 0x40158020, 0xb6000501, 0x48158020, + 0x82b30020, 0x9ab50000, 0x80470000, 0x3015b800, + 0xb4600006, 0x80171018, 0x83840215, 0xb6000603, + 0x40028000, 0x00000000, 0x0008a020, 0x80171030, + 0x82b30020, 0x9ab50000, 0x40158020, 0xb6000501, + 0x48158020, 0x82b30020, 0x9ab50000, 0x80470000, + 0x3015b800, 0xb4600006, 0x80171030, 0x83840204, + 0xb6000603, 0x40028000, 0x00000000, 0x0008a020, + 0xb500011e, 0x80270000, 0x803eff90, 0xb0030000, + 0xb4200067, 0x025f0322, 0xb00b0001, 0xb4200016, + 0xb0120001, 0xb4200005, 0x80171018, 0x8033007f, + 0x9821ffff, 0x001fa001, 0xb5000110, 0xb0120002, + 0xb4200005, 0x80171020, 0x8033007f, 0x9821ffff, + 0x001fa001, 0xb5000109, 0x80171018, 0x80330040, + 0x98210000, 0x001fa001, 0x80171020, 0x00000000, + 0x001fa001, 0xb5000101, 0xb00b0002, 0xb420002c, + 0xb0120000, 0xb4200008, 0x80171000, 0x8033007f, + 0x9821ffff, 0x001fa001, 0x80171038, 0x00000000, + 0x001fa001, 0xb50000f5, 0xb0120001, 0xb4200008, + 0x80171000, 0x8033005a, 0x98218279, 0x001fa001, + 0x80171030, 0x00000000, 0x001fa001, 0xb50000eb, + 0xb0120002, 0xb4200008, 0x80171008, 0x8033005a, + 0x98218279, 0x001fa001, 0x80171038, 0x00000000, + 0x001fa001, 0xb50000e1, 0x80171000, 0x80330040, + 0x98210000, 0x001fa001, 0x80171008, 0x00000000, + 0x001fa001, 0x8017100c, 0x00000000, 0x001fa001, + 0x80171038, 0x00000000, 0x001fa001, 0xb50000d3, + 0xb0120000, 0xb4200008, 0x80171000, 0x8033007f, + 0x9821ffff, 0x001fa001, 0x80171038, 0x00000000, + 0x001fa001, 0xb50000c9, 0xb0120001, 0xb4200005, + 0x80171018, 0x8033007f, 0x9821ffff, 0x001fa001, + 0xb50000c2, 0xb0120002, 0xb4200005, 0x80171020, + 0x8033007f, 0x9821ffff, 0x001fa001, 0xb50000bb, + 0x80171018, 0x80330040, 0x98210000, 0x001fa001, + 0x80171020, 0x00000000, 0x001fa001, 0xb50000b3, + 0x80070000, 0x8033007f, 0x9821ffff, 0xb600050e, + 0x144eb80f, 0xb0028000, 0xb4c00008, 0xac400006, + 0x00000000, 0x1042b800, 0x5842b802, 0x90421000, + 0x0017b802, 0x00000000, 0x001fa001, 0x90000001, + 0x59c1b80e, 0x59e1b80f, 0xb0040000, 0xb4200023, + 0xb00a0002, 0xb4000007, 0x80171004, 0x8033005a, + 0x98218279, 0x001fa001, 0x80171034, 0x00000000, + 0x001fa001, 0xb00c0002, 0xb4000009, 0x8017100c, + 0x8033ffa5, 0x98217d87, 0x001fa001, 0x8017103c, + 0x8033005a, 0x98218279, 0x001fa001, 0xb500008b, + 0x8017100c, 0x8033ffa5, 0x98217d87, 0x001fa001, + 0x80171010, 0x00000000, 0x001fa001, 0x8017103c, + 0x8033005a, 0x98218279, 0x001fa001, 0x80171040, + 0x00000000, 0x001fa001, 0xb500007c, 0xb0040001, + 0xb420002a, 0xb00a0001, 0xb4000007, 0x80171018, + 0x8033005a, 0x98218279, 0x001fa001, 0x80171020, + 0x00000000, 0x001fa001, 0xb00a0003, 0xb420000a, + 0x8053005a, 0x98428279, 0x4030b802, 0x8017101c, + 0x5821b801, 0x00000000, 0x00000000, 0x00000000, + 0x0028b801, 0x001fa001, 0xb00c0001, 0xb4200007, + 0x8053005a, 0x98428279, 0x4031b802, 0x80171024, + 0x0028b801, 0x001fa001, 0xb500005c, 0xb00c0002, + 0xb420005a, 0x8053005a, 0x98428279, 0x4031b802, + 0x80171024, 0x0028b801, 0x001fa001, 0x80171028, + 0x00000000, 0x001fa001, 0xb5000050, 0xb00b0002, + 0xb4200012, 0xb00a0001, 0xb4200008, 0x80171004, + 0x8033005a, 0x98218279, 0x001fa001, 0x80171034, + 0x00000000, 0x001fa001, 0xb5000008, 0xb00a0003, + 0xb4200006, 0x80171004, 0x00000000, 0x001fa010, + 0x80171034, 0x00000000, 0x001fa010, 0xb00c0001, + 0xb4200025, 0x027f0383, 0x003f0328, 0xb0130007, + 0xb420000b, 0xb00b0003, 0xb4200009, 0xb0010000, + 0xb4200007, 0x80171024, 0x00000000, 0x001fa011, + 0x80171054, 0x80270000, 0x001fa001, 0xb500002b, + 0xb00d0000, 0xb420000a, 0x8033005a, 0x98218279, + 0x4041b811, 0x8017100c, 0x0048b802, 0x001fa002, + 0x8017103c, 0x00000000, 0x001fa002, 0xb500001f, + 0xb00d0002, 0xb420001d, 0x80171054, 0x8033005a, + 0x98218279, 0x001fa001, 0x8017106c, 0x00000000, + 0x001fa001, 0xb5000015, 0xb00c0002, 0xb4200013, + 0xb00d0000, 0xb4200007, 0x8017100c, 0x00000000, + 0x001fa011, 0x80171040, 0x00000000, 0x001fa011, + 0xb500000a, 0xb00d0001, 0xb4200008, 0x80171054, + 0x8033005a, 0x98218279, 0x001fa001, 0x80171058, + 0x00000000, 0x001fa001, 0xb5000000, 0x029f0388, + 0x02bf0321, 0xb0140000, 0xb4000006, 0xb0150000, + 0xb4000004, 0x8017108c, 0x8033007f, 0x9821ffff, + 0x001fa001, 0x8027b078, 0x5c22b801, 0x806f001f, + 0x80af001f, 0x80cf0400, 0x003fb0bc, 0x5822b801, + 0x01afb801, 0x003f90bc, 0xb520ffff, 0x90210020, + 0x806f0003, 0x80af0003, 0x80cf0420, 0x003fb0bc, + 0x5822b801, 0x01afb801, 0x003f90bc, 0xb520ffff, + 0x81270000, 0x8033007f, 0x9821ffff, 0x80171000, + 0xb600060a, 0x80470000, 0xb6000603, 0x015f8020, + 0x0156b80a, 0x1042b80a, 0x3002b801, 0xb4a00001, + 0x81270001, 0x00000000, 0x00000000, 0x015f0323, + 0x00000000, 0xb00a0000, 0xb4200002, 0x81670000, + 0xb5000001, 0x81670001, 0x017f23fb, 0x01ff41ee, + 0x59f0b80f, 0x61f0b80f, 0x021f41ef, 0x5a10b810, + 0x6210b810, 0xb00a0003, 0xb420003b, 0x017f039f, + 0x019f41c5, 0x5990b80c, 0x6190b80c, 0xb00b0000, + 0xb400000c, 0xb00c0000, 0xb4000005, 0xac4c0100, + 0x8033001d, 0x98215500, 0x12c1b802, 0xb500000f, + 0xac4f0100, 0x8033001d, 0x98215500, 0x12c1b802, + 0xb500000a, 0xb0090000, 0xb4000005, 0xac4f0100, + 0x8033ffe2, 0x9821ab00, 0x12c1b802, 0xb5000003, + 0xac4f0100, 0x00000000, 0x02c7b802, 0xb0030000, + 0xb420007e, 0x01bf03a0, 0x01df41c9, 0x59d0b80e, + 0x61d0b80e, 0xb00d0000, 0xb400000c, 0xb00e0000, + 0xb4000005, 0xac4e0100, 0x8033001d, 0x98215500, + 0x12e1b802, 0xb5000071, 0xac500100, 0x8033001d, + 0x98215500, 0x12e1b802, 0xb500006c, 0xb0090000, + 0xb4000005, 0xac500100, 0x8033ffe2, 0x9821ab00, + 0x12e1b802, 0xb5000065, 0xac500100, 0x00000000, + 0x02e7b802, 0xb5000061, 0xb00a0002, 0xb420002f, + 0x023f9002, 0x025f9001, 0xb00f0000, 0xb4a00007, + 0xac4f0100, 0x00000000, 0x4022b811, 0x00000000, + 0x0028b801, 0x02c7b801, 0xb500000c, 0xb0090000, + 0xb4000004, 0xac4f0100, 0x00000000, 0x02c7b802, + 0xb5000006, 0xac4f0100, 0x00000000, 0x4022b812, + 0x00000000, 0x0028b801, 0x02c7b801, 0xb0030000, + 0xb4200046, 0xb0100000, 0xb4a00007, 0xac500100, + 0x00000000, 0x4022b811, 0x00000000, 0x0028b801, + 0x02e7b801, 0xb500003d, 0xb0090000, 0xb4000004, + 0xac500100, 0x00000000, 0x02e7b802, 0xb5000037, + 0xac500100, 0x00000000, 0x4022b812, 0x00000000, + 0x0028b801, 0x02e7b801, 0xb5000030, 0x023f9002, + 0x025f9001, 0xb00f0000, 0xb4a00007, 0xac4f0100, + 0x00000000, 0x4022b811, 0x00000000, 0x0028b801, + 0x02c7b801, 0xb5000006, 0xac4f0100, 0x00000000, + 0x4022b812, 0x00000000, 0x0028b801, 0x02c7b801, + 0xb0090000, 0xb4000005, 0x0047b816, 0x8033ffe2, + 0x9821ab00, 0x1042b801, 0x02c7b802, 0xb0030000, + 0xb4200016, 0xb0100000, 0xb4a00007, 0xac500100, + 0x00000000, 0x4022b811, 0x00000000, 0x0028b801, + 0x02e7b801, 0xb5000006, 0xac500100, 0x00000000, + 0x4022b812, 0x00000000, 0x0028b801, 0x02e7b801, + 0xb0090000, 0xb4000005, 0x0047b817, 0x8033ffe2, + 0x9821ab00, 0x1042b801, 0x02e7b802, 0x00000000, + 0x00000000, 0x02c8b816, 0x02dfb0cf, 0xb0030000, + 0xb4200002, 0x02e8b817, 0x02ffb0c6, 0x00ffb81b, + 0xb6001807, 0x5841b802, 0x3015b800, 0xb4800002, + 0x06b5b800, 0x98420001, 0x5aa1b815, 0x00000000, + 0x00ffb81c, 0x00000000, 0x00000000, 0x00000000, + 0x003f03f9, 0x009f0324, 0x84840001, 0xb0010000, + 0xb4000011, 0x815bb3f0, 0x81070000, 0x81270bf4, + 0xb00a0000, 0xb4000002, 0x81070c00, 0x812717f4, + 0x802500a5, 0x806500a5, 0x3001b803, 0xb420fffc, + 0x9421ffff, 0x3001b808, 0xb480000b, 0x3001b809, + 0xb4a00029, 0xb5000008, 0xb0040000, 0xb4200003, + 0x802717ff, 0x81470000, 0xb5000003, 0x80270001, + 0x003f23f9, 0x81470c00, 0xb0040000, 0xb4200001, + 0x8384026c, 0x80af001f, 0x808f0000, 0x806f0000, + 0x80670400, 0x5d22b80a, 0xb600180a, 0x00cfb803, + 0x013fb0bc, 0x5922b809, 0x01afb809, 0x013f90bc, + 0x0047b86f, 0xb0020001, 0xb4c0fffd, 0x90630020, + 0x91290020, 0x801bb3f8, 0x80270001, 0xb0000001, + 0xb4000002, 0x802600a0, 0x803eb3f8, 0x81270c00, + 0xb00a0000, 0xb4000001, 0x81270000, 0x813eb3f0, + 0x80270001, 0x003f2013, 0x00ffb81b, 0x00000000, + 0x029fb00a, 0x02bfb00b, 0x02dfb00c, 0x02ffb00d, + 0x031fb00e, 0x033fb00f, 0x033f400f, 0x0287b86f, + 0x029fb005, 0x8285009d, 0x9a940008, 0x8286009d, + 0x8285009c, 0x96b48000, 0xb0158000, 0xb40001b5, + 0x96b40100, 0xb0150100, 0xb400020c, 0x96b40400, + 0xb0150400, 0xb400020d, 0x96b40001, 0xb0150001, + 0xb400000c, 0x96b40008, 0xb0150008, 0xb40001ad, + 0x96b44000, 0xb0154000, 0xb400020c, 0x96b40002, + 0xb0150002, 0xb4000182, 0x00000000, 0x00000000, + 0xb500021e, 0x02bf9017, 0x92b50001, 0x02bfb017, + 0x82850082, 0x96f40001, 0xb0170000, 0xb4000171, + 0x5efdb814, 0x96f70001, 0xb0170001, 0xb420000b, + 0x83050069, 0x9718003f, 0x82e50064, 0x12f7b818, + 0x86f70109, 0x82feff74, 0x02e7b86f, 0x9af74000, + 0x01ffb817, 0x96f7bfff, 0x01ffb817, 0x83050081, + 0x82a5009a, 0x96b50001, 0xb0150001, 0xb4200014, + 0x82a70000, 0x02bfb017, 0x96b41840, 0xb0150800, + 0xb420000c, 0x96b40008, 0x5aa9b815, 0x96d46000, + 0x5ec3b816, 0x82f3000f, 0x9af7c00f, 0x1718b817, + 0x1ab5b818, 0x1ab5b816, 0x9ab50340, 0x82a60081, + 0xb500014c, 0x9b180180, 0x83060081, 0xb5000149, + 0x82a5009a, 0x96b50002, 0xb0150002, 0xb420001b, + 0x82a70000, 0x02bfb017, 0x96b41800, 0xb0151800, + 0xb4000013, 0x96b40040, 0xb0150040, 0xb4200004, + 0xa3180c00, 0x9b180340, 0x83060081, 0xb5000139, + 0x96b40008, 0x5aa9b815, 0x96d46000, 0x5ec3b816, + 0x82f3000f, 0x9af7c00f, 0x1718b817, 0x1ab5b818, + 0x1ab5b816, 0x9ab50340, 0x82a60081, 0xb500012d, + 0x9b180180, 0x83060081, 0xb500012a, 0x82a500c1, + 0x96b5000f, 0xb015000b, 0xb420000e, 0x96b40020, + 0xb0150020, 0xb400000b, 0x96b40200, 0xb0150200, + 0xb4000008, 0x82c50086, 0x82e50094, 0x3016b817, + 0xb4400004, 0x06f7b816, 0xb017ff00, 0xb4400001, + 0xb5000118, 0x96b46000, 0xb0156000, 0xb4000011, + 0x96b41820, 0xb0150820, 0xb4200004, 0x9b391000, + 0x82a5009a, 0x96b5feff, 0x82a6009a, 0x96b40040, + 0xb0150040, 0xb4200001, 0x9739efff, 0x96b91000, + 0xb0151000, 0xb4200003, 0x82a5009a, 0x9ab50100, + 0x82a6009a, 0x96b40040, 0xb0150040, 0xb4200019, + 0x96b41800, 0xb0151800, 0xb4200006, 0x96b98000, + 0xb0158000, 0xb4200003, 0x9b180180, 0x83060081, + 0xb50000f8, 0x96d80c00, 0x82b300ff, 0x9ab5f3ff, + 0x1718b815, 0xb0160c00, 0xb4000007, 0x82e50098, + 0x96f70400, 0xb0170400, 0xb4200002, 0x82c70c00, + 0xb5000001, 0xa2d60c00, 0x1b18b816, 0x9b180340, + 0xb50000c4, 0x96b40220, 0xb0150000, 0xb4e00021, + 0x82a5009d, 0x82f3ffff, 0x16b5b817, 0x82f33800, + 0x3015b817, 0xb420001b, 0x96f98000, 0xb0178000, + 0xb4000018, 0x82a70000, 0x02bfb017, 0x82c5009d, + 0x96d6ffff, 0x82b3c800, 0x9ab58001, 0x82e500c1, + 0x96f7000f, 0xb017000b, 0xb4000002, 0x82b38800, + 0x9ab58001, 0x1ab5b816, 0x82c5009a, 0x96d60020, + 0xb0160020, 0xb4200002, 0x82b3c800, 0x9ab58001, + 0x82a6009d, 0x02ff9017, 0x00000000, 0xb0170040, + 0xb4800000, 0x5eb5b814, 0x96b500f0, 0x96f46000, + 0x5eedb817, 0x1ab5b817, 0xb0170003, 0xb4000004, + 0x96b500ef, 0x96f70001, 0x5ae4b817, 0x1ab5b817, + 0x96d41800, 0xb0161800, 0xb400000a, 0x96f900ff, + 0x96b500ff, 0x9739ff00, 0x1b39b815, 0x02a7b817, + 0x96b500f3, 0x96d40008, 0x5ec1b816, 0x1ab5b816, + 0xb500000c, 0x96f98000, 0xb0178000, 0xb4200007, + 0x5efeb814, 0x96f70001, 0xb0170001, 0xb4000003, + 0x9b180180, 0x83060081, 0xb50000a2, 0x96b500f3, + 0x9ab50008, 0x9739fff3, 0x96d40020, 0xb0160020, + 0xb4200019, 0x82c7001f, 0x82c600c9, 0x9b398000, + 0x82c70000, 0x02dfb017, 0x96d40010, 0x5ac8b816, + 0x82f300ff, 0x9af7cfff, 0x1718b817, 0x1b18b816, + 0x9b180340, 0x82c5009d, 0x96d6ffff, 0x82f33800, + 0x9af78001, 0x1af7b816, 0x82c5009a, 0x96d60020, + 0xb0160020, 0xb4200002, 0x82f3c800, 0x9af78001, + 0x82e6009d, 0xb500005f, 0x97397fff, 0x96b500ff, + 0x5aaab815, 0x82f300fc, 0x9af703ff, 0x1718b817, + 0x1b18b815, 0x9b180340, 0x82c5009a, 0x96d60010, + 0xb0160010, 0xb4200027, 0x82c70000, 0x02dfb017, + 0x82c50086, 0x92d60bb8, 0x82c60086, 0x82c50094, + 0x5eefb818, 0x96f70003, 0xb0170003, 0xb4200002, + 0x82e70bb8, 0xb5000001, 0x82e70bb8, 0x12d6b817, + 0x82e50081, 0x9af70020, 0x82e60081, 0x82c60094, + 0xa2f70020, 0x82e60081, 0x82f30001, 0x16f7b818, + 0x5ef0b817, 0xb0170001, 0xb4000004, 0x96f84000, + 0x5ee4b817, 0x9718f3ff, 0x1b18b817, 0x82f32800, + 0x9af78000, 0x82e6009d, 0x83060081, 0x83070001, + 0x8306009f, 0x8305009c, 0xb0180001, 0xb4e0fffb, + 0xb50000f6, 0x82c5009d, 0x82f33800, 0x9af78001, + 0x3016b817, 0xb420000f, 0x82b3c800, 0x9ab58001, + 0x82e500c1, 0x96f7000f, 0xb017000b, 0xb4000002, + 0x82b38800, 0x9ab58001, 0x82c5009a, 0x96d60020, + 0xb0160020, 0xb4200002, 0x82b3c800, 0x9ab58001, + 0x82a6009d, 0x82c5009a, 0x96d60080, 0xb0160080, + 0xb4000013, 0x02df9017, 0x00000000, 0xb0160010, + 0xb480000f, 0x82c500c1, 0x96d6000f, 0xb016000b, + 0xb400000b, 0x82c50087, 0x96d60080, 0x5ac7b816, + 0x82c50098, 0x96d60800, 0x5ac3b816, 0x96f84000, + 0x3017b816, 0xb4200002, 0x033f400f, 0x9b394000, + 0x9739bfff, 0x82e50061, 0x96f70008, 0xb0170008, + 0xb4000005, 0x5eefb818, 0x96f70003, 0xb0170003, + 0xb4000001, 0x9718ffff, 0x96b41800, 0xb0151800, + 0xb4000008, 0x5eb9b814, 0x96b5000f, 0x82c50099, + 0x5ed0b816, 0x96f6000f, 0x5ab0b815, 0x82a60099, + 0xb5000002, 0x5ef9b814, 0x96f7000f, 0x5aecb817, + 0x82c5009a, 0x96d60fff, 0x1ad6b817, 0x82c6009a, + 0x96b46000, 0xb0156000, 0xb4200005, 0x5ae2b817, + 0x82d30ffc, 0x9ad63fff, 0x1718b816, 0x1b18b817, + 0x83060081, 0x83070001, 0x8306009f, 0x8305009c, + 0xb0180001, 0xb4e0fffb, 0x00000000, 0xb500009f, + 0x82850083, 0x96b400ff, 0xb015003c, 0xb4200019, + 0x96b92000, 0xb0152000, 0xb4000002, 0x9b392000, + 0xb5000014, 0x9739d3ff, 0x82870000, 0x82860087, + 0x82870008, 0x82860083, 0x829bff78, 0x82a7001f, + 0xb0140400, 0xb4000001, 0x82a70010, 0x82a600c9, + 0x829bff78, 0x00000000, 0x828600cb, 0x8285009d, + 0x82b3ffff, 0x9ab5fffd, 0x1694b815, 0x8286009d, + 0xb5000000, 0x83070002, 0x8306009f, 0x00000000, + 0xb500007e, 0x83078000, 0x8306009f, 0x00000000, + 0xb500007a, 0x82850094, 0x82a50086, 0x06b5b814, + 0x02b6b815, 0xb0151700, 0xb440004c, 0x8285006c, + 0x969400ff, 0xb0140024, 0xb4000019, 0xb0140012, + 0xb4000017, 0x8285009a, 0x5eedb814, 0x96f70003, + 0xb0170003, 0xb4000009, 0x82a50083, 0x5ea8b815, + 0x96b500ff, 0xb0150020, 0xb4400002, 0x82c70bbc, + 0xb5000001, 0x82c70bb8, 0xb5000008, 0x82a50083, + 0x5ea8b815, 0x96b500ff, 0xb0150020, 0xb4400002, + 0x82c71199, 0xb5000001, 0x82c71197, 0xb5000017, + 0xb500002e, 0x8285009a, 0x5eedb814, 0x96f70003, + 0xb0170003, 0xb4000009, 0x82a50083, 0x5ea8b815, + 0x96b500ff, 0xb0150020, 0xb4400002, 0x82c70e12, + 0xb5000001, 0x82c70e0e, 0xb5000008, 0x82a50083, + 0x5ea8b815, 0x96b500ff, 0xb0150020, 0xb4400002, + 0x82c70e12, 0xb5000001, 0x82c70e0e, 0x82e50086, + 0x12f7b816, 0x02bf9017, 0xb0150020, 0xb480000b, + 0x82a5009a, 0x96b56000, 0xb0156000, 0xb4000007, + 0x82a50098, 0x96d50a00, 0xb0160a00, 0xb4000002, + 0xb0160000, 0xb4200001, 0x92f705dc, 0x82850081, + 0x9ab40020, 0x82a60081, 0x82c50094, 0x82e60094, + 0x82860081, 0x86b705dc, 0x82a6009b, 0x83070008, + 0x8306009f, 0x00000000, 0xb5000024, 0x83070100, + 0x8306009f, 0x00000000, 0xb5000020, 0x83070000, + 0x83050081, 0x9b180180, 0x83060081, 0x83070400, + 0x8306009f, 0x00000000, 0xb5000018, 0x82870000, + 0x82850082, 0x5eb7b814, 0x96b500fc, 0x96d40006, + 0x5ec1b816, 0x1ab5b816, 0x5aacb815, 0x83050081, + 0x82d3001c, 0x9ad600ff, 0x1718b816, 0x1b18b815, + 0x9b180e00, 0x83060081, 0x83074000, 0x8306009f, + 0x8305009d, 0x82d3ffff, 0x9ad6bfff, 0x1718b816, + 0x8306009d, 0x00000000, 0xb5000000, 0x029f9005, + 0x01ffb814, 0x033f600f, 0x029f900a, 0x02bf900b, + 0x02df900c, 0x02ff900d, 0x031f900e, 0x033f900f, + 0x00ffb81e, 0x02ff9010, 0x92f70b43, 0x02ffb010, + 0x02ff90cb, 0x82bbffdc, 0x829bffd8, 0x93150004, + 0x3014b815, 0xb400000f, 0x02dbb818, 0x029bb815, + 0x3017b816, 0xb480000b, 0x5a81b814, 0x029fb010, + 0x82860095, 0x8293001f, 0x9294fe00, 0x92b50008, + 0x3015b814, 0xb4800002, 0x82b3001f, 0x92b5fa00, + 0x82beffdc, 0x82850086, 0x83250094, 0x06d4b819, + 0x02d6b816, 0xb016ffff, 0xb4a00009, 0x82c50081, + 0x9ab60020, 0x82a60081, 0x82a50086, 0x92b50bbb, + 0x82a60094, 0x82c60081, 0x86b505df, 0x82a6009b, + 0x00ffb81c, 0x82870001, 0x829ef500, 0x82850086, + 0x83250094, 0x06d4b819, 0x02d6b816, 0xb016ffff, + 0xb4a0000b, 0x82870001, 0x829ef504, 0x82c50081, + 0x9ab60020, 0x82a60081, 0x82a50086, 0x92b50bbb, + 0x82a60094, 0x82c60081, 0x86b505df, 0x82a6009b, + 0x00ffb81c, 0x82070028, 0x023f9006, 0x83a4ef4f, + 0x80070000, 0x001fb011, 0x001f204f, 0x003fb800, + 0x001f9006, 0x5803b800, 0x80338000, 0x1800b801, + 0x003fb800, 0x005f4193, 0x5c41b802, 0x80350000, + 0x00000000, 0x0027b860, 0x80150010, 0x5810b800, + 0x80750010, 0x1863b800, 0x8087ffff, 0x80a7770b, + 0x80c70000, 0x1403b804, 0x3000b805, 0xb4000008, + 0x5888b804, 0x58a8b805, 0x90c60001, 0xb0060003, + 0xb4a0fff8, 0x84420001, 0xb4e0ffee, 0xb5000027, + 0xb0060003, 0xb4200007, 0x80150010, 0x5810b800, + 0x81150010, 0x950800ff, 0xb0080077, 0xb4000001, + 0xb500fff4, 0x001f400e, 0x98000010, 0x98004000, + 0x9400fffe, 0x001f600e, 0x80e71f40, 0x001f4000, + 0x94000080, 0xb0000080, 0xb4200001, 0x80e77490, + 0x00ffb008, 0x80e70020, 0xb0060000, 0xb400000e, + 0x58e3b806, 0x90210020, 0x81070000, 0x5938b803, + 0x1908b809, 0x9523ff00, 0x5928b809, 0x1908b809, + 0x5d28b803, 0x9529ff00, 0x1908b809, 0x5d38b803, + 0x1908b809, 0x011fb011, 0x00ff204f, 0x80137fff, + 0x9800ffe7, 0x1421b800, 0x5c23b801, 0x001f9006, + 0x0441b800, 0x3001b800, 0xb4600002, 0x0440b801, + 0xa4422000, 0x007f90cb, 0x1063b802, 0x007fb0cb, + 0x003fb006, 0x803effec, 0x80470001, 0x005f2013, + 0xb500ebdf, 0x001f400e, 0x9400000f, 0xb0000000, + 0xb4200001, 0x00ffb81f, 0xb0000001, 0xb4000005, + 0xb0000003, 0xb4000003, 0xb0000002, 0xb4000001, + 0x00ffb81f, 0x80070001, 0x001f2013, 0xb500ebd0, + 0x001f9012, 0x001fb100, 0x001f004c, 0x001f2404, + 0x801bfef0, 0x8058fef4, 0x803bff68, 0x8078ff6c, + 0x2000b801, 0x2042b803, 0x001fb104, 0x005f2414, + 0x82e70001, 0x83640048, 0x029fb014, 0x829efef0, + 0x8286000f, 0x02bf2054, 0x82bcfef4, 0x82a6000e, + 0x00ffb81a, 0x80e70001, 0x801336e3, 0x9800eb76, + 0x001fb100, 0x800700ab, 0x001f2404, 0x801bc3e8, + 0x8058c3ec, 0x83640024, 0x82e70000, 0x83640036, + 0x029fb300, 0x029fb100, 0x02bf2c04, 0x02bf2404, + 0x801bc000, 0x8058c004, 0x8364001b, 0x82e70000, + 0x8364002d, 0x001f9300, 0x3000b814, 0xb420000a, + 0x001f0c04, 0x3000b815, 0xb4200007, 0x829efef0, + 0x82bcfef4, 0x029fb012, 0x02bf204c, 0x82870001, + 0x829cfef5, 0x00ffb81a, 0xb0070000, 0xb4000007, + 0x80e70000, 0x801399fa, 0x9800c92e, 0x001fb100, + 0x800700af, 0x001f2404, 0xb500ffdc, 0x82870000, + 0x829cfef5, 0x00ffb81a, 0x80c700ff, 0x803bff68, + 0x8078ff6c, 0x14a0b806, 0x2063b805, 0x007f2414, + 0x2021b802, 0x58c8b806, 0x14a0b806, 0x58b0b805, + 0x2021b805, 0x58c8b806, 0x14a0b806, 0x2021b805, + 0x58c8b806, 0x14a0b806, 0x5cb0b805, 0x2021b805, + 0x003fb104, 0x00ffb81b, 0x82c70000, 0x83070400, + 0x83270005, 0x8197040c, 0x81d7ffff, 0x83840126, + 0x83840001, 0x00ffb81b, 0x808f0000, 0x806f001f, + 0x80af001f, 0x80270140, 0x81e7ef98, 0x5de2b80f, + 0xb6000208, 0x00cfb801, 0x01ffb0bc, 0x59e2b80f, + 0x01cfb80f, 0x01ff90bc, 0xb520ffff, 0x91ef0020, + 0x90210020, 0x80270180, 0x81e7ee90, 0x5de2b80f, + 0xb6000208, 0x00cfb801, 0x01ffb0bc, 0x59e2b80f, + 0x01cfb80f, 0x01ff90bc, 0xb520ffff, 0x91ef0020, + 0x90210020, 0x8057ffff, 0x80170430, 0x80070410, + 0x80270408, 0xb6000509, 0x005ff000, 0x90420500, + 0x007ff001, 0x90630600, 0x009ff002, 0x00bff003, + 0x2004a025, 0x90000001, 0x90210001, 0x80070414, + 0x80d7ffff, 0x8097045c, 0x8017043c, 0xb6000404, + 0x005ff000, 0x007f87e0, 0x84000001, 0x2082a7e3, + 0x80970460, 0x80170440, 0x2082b803, 0x007f8000, + 0x2083a004, 0x80170430, 0x80970450, 0x80270408, + 0xb6000508, 0x005f8024, 0x90420500, 0x007ff001, + 0x90630600, 0x009ff002, 0x00bff003, 0x2004a025, + 0x90210001, 0x80170440, 0x00000000, 0x02bf87e0, + 0x80970460, 0x82870000, 0xb6000404, 0x005f87e4, + 0x5a88b814, 0x204287e0, 0x1a94b802, 0x00ffb81c, + 0x001f0a49, 0x001f2709, 0x001f0a41, 0x001f2708, + 0x001f0a46, 0x001f2707, 0x001f0a48, 0x001f2706, + 0x001f0a42, 0x001f2705, 0x001f0a47, 0x001f2704, + 0x001f0a45, 0x001f2703, 0x001f0a43, 0x001f2702, + 0x001f0a40, 0x001f2701, 0x001f0a44, 0x001f2700, + 0x001f0c25, 0xa020000c, 0x94400001, 0x94600002, + 0x94810004, 0x94a10008, 0x94c00010, 0x5943b802, + 0x5861b803, 0x5882b804, 0x5ca2b805, 0x5cc4b806, + 0x194ab803, 0x194ab804, 0x194ab805, 0x194ab806, + 0x015f2738, 0x801bef90, 0x003f91c1, 0x5c28b801, + 0x005f91c2, 0x5858b802, 0x1821b802, 0x2000b801, + 0x001fb1c4, 0x8018ef94, 0x003f0709, 0x2000b801, + 0x001f2714, 0x82c70001, 0x82e70001, 0x83070710, + 0x8327001e, 0x81970735, 0x8384009f, 0x02df0738, + 0x82170a30, 0x838400f1, 0x819efef0, 0x817cfef4, + 0x819eff68, 0x817cff6c, 0x00ffb81b, 0x820f001f, + 0x8018fef8, 0x8057ffff, 0x001f2709, 0x8018fef6, + 0x80d7ffff, 0x001f2708, 0x8018fefa, 0x8157ffff, + 0x001f2707, 0x8018fefd, 0x81d7ffff, 0x001f2706, + 0x8018fefb, 0x802f001f, 0x001f2705, 0x8018fefe, + 0x00000000, 0x001f2704, 0x8018fef9, 0x00000000, + 0x001f2703, 0x8018feff, 0x00000000, 0x001f2702, + 0x8018fef7, 0x00000000, 0x001f2701, 0x8018fefc, + 0x00000000, 0x001f2700, 0x001f0c25, 0xa0200011, + 0x94410001, 0x94600002, 0x94800004, 0x94a00008, + 0x94c10010, 0x5941b802, 0x5861b803, 0x5c82b804, + 0x58a1b805, 0x5cc1b806, 0x194ab803, 0x194ab804, + 0x194ab805, 0x194ab806, 0x015f2738, 0x801bef90, + 0x003f91c1, 0x5c28b801, 0x005f91c2, 0x5858b802, + 0x1821b802, 0x2000b801, 0x001fb1c4, 0x8018ef94, + 0x003f0709, 0x2000b801, 0x001f2714, 0x82c70001, + 0x82e70001, 0x83070710, 0x8327001e, 0x81970735, + 0x83840055, 0x02df0738, 0x82170a20, 0x838400a7, + 0x819efef0, 0x817cfef4, 0x5ac8b80c, 0x02ff0a44, + 0x1ad6b817, 0x02dfb291, 0x5ed8b80c, 0x5968b80b, + 0x1ad6b80b, 0x02df6524, 0x00ffb81b, 0x820f001f, + 0x8018fefe, 0x8057ffff, 0x001f2709, 0x8018fefa, + 0x80d7ffff, 0x001f2708, 0x8018fefc, 0x8157ffff, + 0x001f2707, 0x8018feff, 0x81d7ffff, 0x001f2706, + 0x8018fef8, 0x802f001f, 0x001f2705, 0x8018fefb, + 0x00000000, 0x001f2704, 0x8018fefd, 0x00000000, + 0x001f2703, 0x8018fef6, 0x00000000, 0x001f2702, + 0x8018fef9, 0x00000000, 0x001f2701, 0x8018fef7, + 0x00000000, 0x001f2700, 0x801bef90, 0x003f91c1, + 0x5c28b801, 0x005f91c2, 0x5858b802, 0x1821b802, + 0x2000b801, 0x001fb1c4, 0x8018ef94, 0x003f0709, + 0x2000b801, 0x001f2714, 0x82c70001, 0x82e70001, + 0x83070710, 0x8327001e, 0x81970735, 0x83840016, + 0x83270000, 0x831bfef0, 0x82f8fef4, 0x02c7b819, + 0x82170a28, 0x83840065, 0x300cb818, 0xb4200002, + 0x300bb817, 0xb4000006, 0x93390001, 0xb0190020, + 0xb480fff6, 0x83270000, 0x833cfef5, 0x00ffb81b, + 0x019fb290, 0x017f2a44, 0x033f2c25, 0x83270001, + 0x833cfef5, 0x00ffb81b, 0x0007b818, 0x90000003, + 0x00000000, 0x015ff000, 0x90000001, 0x5949b80a, + 0x013ff000, 0x194ab809, 0x84000002, 0x994a0100, + 0x017ff000, 0x958b00f8, 0x5981b80c, 0x956b0007, + 0x198cb80b, 0x84000002, 0x998c0008, 0x017ff000, + 0x90000001, 0x5971b80b, 0x198cb80b, 0x017ff000, + 0x5969b80b, 0x198cb80b, 0x81a70000, 0x94d90003, + 0x82a70000, 0xb6260019, 0xb6000818, 0x5df0b80a, + 0x5e02b80a, 0x21efb810, 0x95ef0001, 0x5941b80a, + 0x194ab80f, 0x21efb816, 0x5e18b80c, 0x5e35b80c, + 0x5e54b80c, 0x5e6cb80c, 0x2210b811, 0x2252b813, + 0x2210b812, 0x96100001, 0x5981b80c, 0x198cb810, + 0x2210b817, 0x10afb810, 0x10a5b80d, 0x5da1b805, + 0x94a50001, 0x5aa1b815, 0x1ab5b805, 0x019fa7f5, + 0x5cc2b819, 0xb626001c, 0x82870000, 0xb6000419, + 0xb6000818, 0x5df0b80a, 0x5e02b80a, 0x21efb810, + 0x95ef0001, 0x5941b80a, 0x194ab80f, 0x21efb816, + 0x5e18b80c, 0x5e35b80c, 0x5e54b80c, 0x5e6cb80c, + 0x2210b811, 0x2252b813, 0x2210b812, 0x96100001, + 0x5981b80c, 0x198cb810, 0x2210b817, 0x10afb810, + 0x10a5b80d, 0x5da1b805, 0x94a50001, 0x5a81b814, + 0x1a94b805, 0x019fa7f4, 0x00ffb81c, 0x8257ffff, + 0x808f0000, 0x806f001f, 0x80af001f, 0x80270200, + 0x81e7ec70, 0x5de2b80f, 0xb6000208, 0x00cfb801, + 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, 0x01ff90bc, + 0xb520ffff, 0x91ef0020, 0x90210020, 0x80270240, + 0x81e7ed70, 0x5de2b80f, 0xb6000208, 0x00cfb801, + 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, 0x01ff90bc, + 0xb520ffff, 0x91ef0020, 0x90210020, 0x80270180, + 0x81e7ee90, 0x5de2b80f, 0xb6000208, 0x00cfb801, + 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, 0x01ff90bc, + 0xb520ffff, 0x91ef0020, 0x90210020, 0x806f0007, + 0x80af0007, 0x80270280, 0x81e7ee70, 0x5de2b80f, + 0x00cfb801, 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, + 0x01ff90bc, 0xb520ffff, 0x91ef0020, 0x90210020, + 0x80170760, 0x001f0700, 0x001fa020, 0x001f0701, + 0x001fa020, 0x001f0702, 0x001fa020, 0x001f0703, + 0x001fa020, 0x001f0704, 0x001fa000, 0x80970750, + 0x81170770, 0x82a70735, 0x83a40060, 0x001f87e4, + 0xb6000405, 0x86b50001, 0x83a4005c, 0x001f8004, + 0x003f87e8, 0x2080a7e1, 0x80970770, 0x80170750, + 0x81170750, 0x81970740, 0x82a70730, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a40050, 0x001f87e4, + 0xb6000405, 0x86b50001, 0x83a4004c, 0x001f8004, + 0x003f87e8, 0x2080a7e1, 0x80970750, 0x80170770, + 0x81170770, 0x81970760, 0x82a7072b, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a40040, 0x83a4004e, + 0xb6000407, 0x86b50001, 0x83a4003c, 0x001f8004, + 0x003f87e8, 0x2080a001, 0x83a40047, 0x00000000, + 0x80970770, 0x80170750, 0x81170750, 0x81970740, + 0x82a70726, 0x001f800c, 0x003f8008, 0x2100a001, + 0x83a4002e, 0x83a4003c, 0xb6000407, 0x86b50001, + 0x83a4002a, 0x001f8004, 0x003f87e8, 0x2080a001, + 0x83a40035, 0x00000000, 0x80970750, 0x80170770, + 0x81170770, 0x81970760, 0x82a70721, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a4001c, 0x001f87e4, + 0xb6000405, 0x86b50001, 0x83a40018, 0x001f8004, + 0x003f87e8, 0x2080a7e1, 0x80970770, 0x80170750, + 0x81170750, 0x81970740, 0x82a7071c, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a4000c, 0x017f87e4, + 0x81870000, 0xb6000406, 0x86b50001, 0x83a40007, + 0x001f87e4, 0x200087e8, 0x5988b80c, 0x198cb800, + 0x021fa02c, 0x021fa00b, 0x00ffb81c, 0x005ff015, + 0x90420600, 0x003f87e0, 0x001ff002, 0x2060b801, + 0x90630800, 0x90960a00, 0x001ff003, 0x003ff004, + 0x20a0b801, 0x90a50900, 0x00000000, 0x001ff005, + 0x009fa000, 0x00ffb81d, 0x001f8004, 0x5c21b800, + 0x5847b800, 0x1821b802, 0x942100ff, 0x2080a7e1, + 0x00ffb81d, 0x00000000, 0x00000000, 0x00000000, + 0x015f400e, 0x944a4000, 0xb0024000, 0xb420001a, + 0x954abfff, 0x015f600e, 0x820f001f, 0x802f001f, + 0x81470000, 0x015f23f9, 0x015fb0ba, 0x8057ffff, + 0x80770000, 0x82970400, 0x82d7ffff, 0x82f70000, + 0xb6000702, 0xb6000001, 0x029fa02a, 0x80275480, + 0x005fb801, 0x8033001f, 0x9821c000, 0x803effe0, + 0x90212000, 0x803effe4, 0x80d9ff80, 0x00df6001, + 0x81477508, 0x015fb008, 0x003f0324, 0xb0010000, + 0xb4200076, 0x8344ebe6, 0xb0180000, 0xb4000004, + 0x011f400e, 0x1908b818, 0x011f600e, 0x00ffb81f, + 0x8344f18f, 0xb00b0000, 0xb4000006, 0x023f400e, + 0x9a310002, 0x023f600e, 0x82270000, 0x023f2012, + 0x00ffb81f, 0x8364ed72, 0x82270000, 0x023f2011, + 0x80070000, 0x80170800, 0xb6002002, 0xb6003001, + 0x001fa020, 0x82270000, 0x003fb811, 0x02bf9006, + 0x5aa3b815, 0x82338000, 0x1a31b815, 0x003fb811, + 0x8067e950, 0x5c62b803, 0x81f50000, 0x019f4193, + 0x0267b80c, 0xadcc0010, 0x80170800, 0x80130000, + 0x9800f872, 0x001fa020, 0x80134e1f, 0x98000001, + 0x001fa020, 0x59d0b80e, 0x81150010, 0x1908b80e, + 0x001fa028, 0x858c0001, 0x5e01b80c, 0x5e25b810, + 0xb6310006, 0xb6002005, 0x81150010, 0x5910b808, + 0x00000000, 0x81350010, 0x1808a029, 0x9630001f, + 0xb0110000, 0xb4000006, 0xb6310005, 0x81150010, + 0x5910b808, 0x00000000, 0x81350010, 0x1808a029, + 0x962c0001, 0xb0110000, 0xb4000003, 0x81150010, + 0x5910b808, 0x001fa028, 0x019f9006, 0x958cffff, + 0x00df4193, 0x58c1b806, 0x118cb806, 0xb00ce000, + 0xb4800002, 0x858ce000, 0x918cc000, 0x8153001f, + 0x118cb80a, 0x819effec, 0x019fb006, 0x015f4193, + 0x5941b80a, 0x019f90cb, 0x118cb80a, 0x019fb0cb, + 0x019f90ba, 0x918c0001, 0x019fb0ba, 0xb00c0002, + 0xb4200016, 0x019f400e, 0x940c8000, 0xb0008000, + 0xb4200012, 0x958c7fff, 0x019f600e, 0x80070000, + 0x800600a0, 0x80073da1, 0x800600a1, 0x801bff60, + 0x00000000, 0x801eff60, 0x00000000, 0x801bff60, + 0x00000000, 0x801eff60, 0x80130001, 0x98003da1, + 0x800600a1, 0x80070001, 0x800600a0, 0x003f0324, + 0x90210001, 0xb0010005, 0xb4a00001, 0x80270000, + 0x003f2324, 0x00ffb81f, 0x00000000, 0x00000000, + 0x003f03f9, 0x009f0324, 0x84840001, 0xb0010000, + 0xb4000011, 0x815bb3f0, 0x81070000, 0x81270bf4, + 0xb00a0000, 0xb4000002, 0x81070c00, 0x81271800, + 0x802500a5, 0x806500a5, 0x3001b803, 0xb420fffc, + 0x9421ffff, 0x3001b808, 0xb480000b, 0x3001b809, + 0xb4a0002e, 0xb5000008, 0xb0040000, 0xb4200003, + 0x802717ff, 0x81470000, 0xb5000003, 0x80270001, + 0x003f23f9, 0x81470c00, 0xb0040000, 0xb4200001, + 0x8384fc04, 0x80af001f, 0x808f0002, 0x806f0000, + 0x807bbf34, 0x5d22b80a, 0xb600080a, 0x00cfb803, + 0x013fb0bc, 0x5922b809, 0x01afb809, 0x013f90bc, + 0x0047b86f, 0xb0020001, 0xb4c0fffd, 0x90630020, + 0x91290060, 0x808f0000, 0x813bb3f8, 0x80270001, + 0xb0090001, 0xb4000002, 0x802600a0, 0x803eb3f8, + 0x81270c00, 0xb00a0000, 0xb4000001, 0x81270000, + 0x813eb3f0, 0xb0030800, 0xb4800001, 0x80670200, + 0x807ebf34, 0x80270001, 0x003f2013, 0x00ffb81b, + +}; + +static u32 AC3240Ucode1f8000[] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00020000, 0xffff0005, 0xffffffff, + 0x00050001, 0xffffffff, 0xffffffff, 0x00020000, + 0xffff0005, 0xffffffff, 0x00010000, 0x00050002, + 0xffffffff, 0x00020000, 0x00050003, 0xffffffff, + 0x00010000, 0x00030002, 0xffff0005, 0x00020000, + 0x00040003, 0xffff0005, 0x00010000, 0x00030002, + 0x00050004, 0x0019000d, 0x003d0025, 0x00250019, + 0x00fd003d, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x007fffff, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00000000, 0x007fffff, 0x00000000, + 0x00000000, 0x00000000, 0x007fffff, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x007fffff, + 0x007fffff, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x007fffff, 0x007fffff, 0x00000000, + 0x00000000, 0x00000000, 0x007fffff, 0x00000000, + 0x00000000, 0x00599999, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00599999, + 0x007fffff, 0x00599999, 0x00000000, 0x00599999, + 0x00000000, 0x00000000, 0x00000000, 0x00599999, + 0x00000000, 0x00599999, 0x007fffff, 0x00000000, + 0x00599999, 0x00599999, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00599999, 0x00599999, + 0x007fffff, 0x007fffff, 0x00000000, 0x00599999, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00599999, 0x007fffff, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00000000, 0x007fffff, 0x00000000, + 0x00000000, 0x00000000, 0x007fffff, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x007fffff, + 0x007fffff, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x007fffff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x007fffff, 0x00000000, + 0x007fffff, 0x00000000, 0x007fffff, 0x00400000, + 0x00200000, 0x00100000, 0x00080000, 0x00040000, + 0x00020000, 0x00010000, 0x00008000, 0x00004000, + 0x00002000, 0x00001000, 0x00000800, 0x00000400, + 0x00000200, 0x00000100, 0x00000080, 0x00000040, + 0x00000020, 0x00000010, 0x00000008, 0x00000004, + 0x00000002, 0x00000001, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00010002, + 0x00030002, 0x00030002, 0x00030002, 0x00000000, + 0x00000000, 0x00010001, 0x00020002, 0x4000a000, + 0xe000a000, 0xf000b000, 0xf800b800, 0x005a8279, + 0x004c1bf8, 0x00400000, 0x004c1bf8, 0x005a8279, + 0x00400000, 0x00000000, 0x00400000, 0x03020100, + 0x00000000, 0x00000080, 0x00000020, 0x00000008, + 0x00000000, 0x00000001, 0x00010001, 0x10081000, + 0x10041000, 0x10081004, 0x10081008, 0x10081008, + 0x00000000, 0x00000000, 0x00000000, 0xff80000a, + 0xff80031f, 0xff800b24, 0xff801818, 0xff8029fa, + 0xff8040c9, 0xff805c86, 0xff807d2e, 0xff80a2c1, + 0xff80cd3c, 0xff80fc9f, 0xff8130e8, 0xff816a14, + 0xff81a821, 0xff81eb0e, 0xff8232d6, 0xff827f79, + 0xff82d0f2, 0xff83273e, 0xff83825b, 0xff83e244, + 0xff8446f7, 0xff84b06e, 0xff851ea6, 0xff85919b, + 0xff860949, 0xff8685aa, 0xff8706ba, 0xff878c74, + 0xff8816d3, 0xff88a5d1, 0xff89396a, 0xff89d196, + 0xff8a6e51, 0xff8b0f94, 0xff8bb55a, 0xff8c5f9b, + 0xff8d0e51, 0xff8dc176, 0xff8e7902, 0xff8f34ef, + 0xff8ff535, 0xff90b9cc, 0xff9182ae, 0xff924fd3, + 0xff932132, 0xff93f6c3, 0xff94d07f, 0xff95ae5d, + 0xff969054, 0xff97765b, 0xff98606a, 0xff994e78, + 0xff9a407c, 0xff9b366b, 0xff9c303e, 0xff9d2de9, + 0xff9e2f64, 0xff9f34a4, 0xffa03da0, 0xffa14a4c, + 0xffa25aa0, 0xffa36e8f, 0xffa48610, 0xffa5a118, + 0xffa6bf9c, 0xffa7e191, 0xffa906ec, 0xffaa2fa0, + 0xffab5ba4, 0xffac8aeb, 0xffadbd6a, 0xffaef315, + 0xffb02bdf, 0xffb167be, 0xffb2a6a4, 0xffb3e886, + 0xffb52d56, 0xffb67509, 0xffb7bf92, 0xffb90ce4, + 0xffba5cf2, 0xffbbafb0, 0xffbd050f, 0xffbe5d04, + 0xffbfb780, 0xffc11477, 0xffc273db, 0xffc3d59f, + 0xffc539b4, 0xffc6a00d, 0xffc8089d, 0xffc97355, + 0xffcae027, 0xffcc4f05, 0xffcdbfe2, 0xffcf32af, + 0xffd0a75d, 0xffd21ddf, 0xffd39625, 0xffd51022, + 0xffd68bc7, 0xffd80904, 0xffd987cd, 0xffdb0810, + 0xffdc89c1, 0xffde0cd0, 0xffdf912d, 0xffe116cb, + 0xffe29d9a, 0xffe4258b, 0xffe5ae8f, 0xffe73896, + 0xffe8c392, 0xffea4f74, 0xffebdc2b, 0xffed69aa, + 0xffeef7df, 0xfff086bd, 0xfff21634, 0xfff3a634, + 0xfff536ad, 0xfff6c792, 0xfff858d1, 0xfff9ea5b, + 0xfffb7c22, 0xfffd0e16, 0xfffea026, 0xffffcdbc, + 0xfffe3ba0, 0xfffca995, 0xfffb17ac, 0xfff985f3, + 0xfff7f479, 0xfff6634f, 0xfff4d284, 0xfff34228, + 0xfff1b249, 0xfff022f7, 0xffee9442, 0xffed0638, + 0xffeb78ea, 0xffe9ec67, 0xffe860bd, 0xffe6d5fd, + 0xffe54c35, 0xffe3c374, 0xffe23bcb, 0xffe0b547, + 0xffdf2ff7, 0xffddabec, 0xffdc2933, 0xffdaa7dd, + 0xffd927f6, 0xffd7a98f, 0xffd62cb7, 0xffd4b17b, + 0xffd337ea, 0xffd1c013, 0xffd04a05, 0xffced5ce, + 0xffcd637c, 0xffcbf31d, 0xffca84c1, 0xffc91874, + 0xffc7ae45, 0xffc64641, 0xffc4e078, 0xffc37cf6, + 0xffc21bc9, 0xffc0bcff, 0xffbf60a5, 0xffbe06c9, + 0xffbcaf79, 0xffbb5ac0, 0xffba08ae, 0xffb8b94d, + 0xffb76cac, 0xffb622d8, 0xffb4dbdc, 0xffb397c6, + 0xffb256a2, 0xffb1187d, 0xffafdd62, 0xffaea55f, + 0xffad707e, 0xffac3ecc, 0xffab1054, 0xffa9e523, + 0xffa8bd44, 0xffa798c2, 0xffa677a8, 0xffa55a02, + 0xffa43fdb, 0xffa3293d, 0xffa21634, 0xffa106c9, + 0xff9ffb08, 0xff9ef2fa, 0xff9deeab, 0xff9cee23, + 0xff9bf16c, 0xff9af892, 0xff9a039c, 0xff991295, + 0xff982586, 0xff973c78, 0xff965774, 0xff957683, + 0xff9499ad, 0xff93c0fb, 0xff92ec75, 0xff921c24, + 0xff91500f, 0xff90883f, 0xff8fc4bb, 0xff8f058b, + 0xff8e4ab6, 0xff8d9443, 0xff8ce239, 0xff8c349f, + 0xff8b8b7d, 0xff8ae6d7, 0xff8a46b5, 0xff89ab1e, + 0xff891416, 0xff8881a3, 0xff87f3cc, 0xff876a96, + 0xff86e606, 0xff866621, 0xff85eaed, 0xff85746d, + 0xff8502a6, 0xff84959e, 0xff842d57, 0xff83c9d7, + 0xff836b20, 0xff831138, 0xff82bc20, 0xff826bdc, + 0xff822070, 0xff81d9de, 0xff819829, 0xff815b54, + 0xff812360, 0xff80f051, 0xff80c228, 0xff8098e6, + 0xff80748e, 0xff805521, 0xff803a9f, 0xff80250b, + 0xff801464, 0xff8008ad, 0xff8001e4, 0xff800027, + 0xff800c7e, 0xff802c8f, 0xff806056, 0xff80a7cb, + 0xff8102e4, 0xff817191, 0xff81f3c3, 0xff828964, + 0xff83325f, 0xff83ee98, 0xff84bdf3, 0xff85a04f, + 0xff86958b, 0xff879d7f, 0xff88b804, 0xff89e4ee, + 0xff8b240e, 0xff8c7533, 0xff8dd82a, 0xff8f4cbb, + 0xff90d2ad, 0xff9269c4, 0xff9411c1, 0xff95ca62, + 0xff979365, 0xff996c81, 0xff9b5570, 0xff9d4de4, + 0xff9f5590, 0xffa16c24, 0xffa3914e, 0xffa5c4b8, + 0xffa8060d, 0xffaa54f3, 0xffacb10e, 0xffaf1a03, + 0xffb18f70, 0xffb410f7, 0xffb69e33, 0xffb936c0, + 0xffbbda37, 0xffbe8830, 0xffc14042, 0xffc40201, + 0xffc6cd00, 0xffc9a0d2, 0xffcc7d05, 0xffcf612b, + 0xffd24ccf, 0xffd53f80, 0xffd838c8, 0xffdb3833, + 0xffde3d49, 0xffe14795, 0xffe4569d, 0xffe769e9, + 0xffea80ff, 0xffed9b67, 0xfff0b8a4, 0xfff3d83c, + 0xfff6f9b5, 0xfffa1c91, 0xfffd4056, 0xffff9b78, + 0xfffc7756, 0xfff953c0, 0xfff63130, 0xfff31025, + 0xffeff117, 0xffecd484, 0xffe9bae5, 0xffe6a4b6, + 0xffe39270, 0xffe0848b, 0xffdd7b82, 0xffda77cb, + 0xffd779de, 0xffd48231, 0xffd19138, 0xffcea769, + 0xffcbc535, 0xffc8eb10, 0xffc61969, 0xffc350af, + 0xffc09151, 0xffbddbbb, 0xffbb3059, 0xffb88f92, + 0xffb5f9d0, 0xffb36f78, 0xffb0f0ef, 0xffae7e96, + 0xffac18cf, 0xffa9bff9, 0xffa7746f, 0xffa5368c, + 0xffa306aa, 0xffa0e51e, 0xff9ed23c, 0xff9cce56, + 0xff9ad9bc, 0xff98f4bc, 0xff971f9f, 0xff955aae, + 0xff93a62f, 0xff920266, 0xff906f92, 0xff8eedf3, + 0xff8d7dc4, 0xff8c1f3c, 0xff8ad294, 0xff8997fd, + 0xff886fa8, 0xff8759c3, 0xff865679, 0xff8565f2, + 0xff848852, 0xff83bdbd, 0xff830651, 0xff82622b, + 0xff81d163, 0xff815411, 0xff80ea47, 0xff809416, + 0xff80518b, 0xff8022b1, 0xff80078e, 0x00000475, + 0x000007fe, 0x00000c02, 0x000010a3, 0x000015f5, + 0x00001c08, 0x000022ed, 0x00002ab5, 0x00003371, + 0x00003d32, 0x0000480a, 0x0000540d, 0x0000614b, + 0x00006fda, 0x00007fcd, 0x00009138, 0x0000a431, + 0x0000b8cc, 0x0000cf1f, 0x0000e741, 0x00010148, + 0x00011d4b, 0x00013b61, 0x00015ba2, 0x00017e25, + 0x0001a302, 0x0001ca51, 0x0001f42c, 0x000220a9, + 0x00024fe2, 0x000281f0, 0x0002b6ea, 0x0002eee9, + 0x00032a07, 0x0003685a, 0x0003a9fc, 0x0003ef04, + 0x0004378a, 0x000483a5, 0x0004d36d, 0x000526f7, + 0x00057e5b, 0x0005d9ae, 0x00063904, 0x00069c74, + 0x00070410, 0x00076feb, 0x0007e01a, 0x000854ac, + 0x0008cdb3, 0x00094b40, 0x0009cd61, 0x000a5425, + 0x000adf98, 0x000b6fc8, 0x000c04bf, 0x000c9e87, + 0x000d3d2a, 0x000de0ae, 0x000e891a, 0x000f3674, + 0x000fe8c0, 0x00109fff, 0x00115c34, 0x00121d5d, + 0x0012e37b, 0x0013ae89, 0x00147e84, 0x00155366, + 0x00162d27, 0x00170bbf, 0x0017ef23, 0x0018d748, + 0x0019c421, 0x001ab59f, 0x001babb2, 0x001ca648, + 0x001da54f, 0x001ea8b0, 0x001fb058, 0x0020bc2d, + 0x0021cc18, 0x0022dffd, 0x0023f7c2, 0x00251348, + 0x00263272, 0x00275520, 0x00287b31, 0x0029a482, + 0x002ad0f1, 0x002c0059, 0x002d3294, 0x002e677c, + 0x002f9ee8, 0x0030d8b1, 0x003214ac, 0x003352b0, + 0x00349290, 0x0035d422, 0x00371738, 0x00385ba5, + 0x0039a13b, 0x003ae7cc, 0x003c2f2a, 0x003d7725, + 0x003ebf8d, 0x00400834, 0x004150e9, 0x0042997d, + 0x0043e1c0, 0x00452981, 0x00467092, 0x0047b6c3, + 0x0048fbe3, 0x004a3fc6, 0x004b823b, 0x004cc316, + 0x004e0228, 0x004f3f45, 0x00507a40, 0x0051b2ef, + 0x0052e925, 0x00541cba, 0x00554d85, 0x00567b5e, + 0x0057a61d, 0x0058cd9e, 0x0059f1bb, 0x005b1252, + 0x005c2f3f, 0x005d4863, 0x005e5d9d, 0x005f6ed0, + 0x00607bde, 0x006184ad, 0x00628923, 0x00638927, + 0x006484a3, 0x00657b81, 0x00666daf, 0x00675b19, + 0x006843b1, 0x00692767, 0x006a062d, 0x006adff9, + 0x006bb4c2, 0x006c847d, 0x006d4f27, 0x006e14b8, + 0x006ed52f, 0x006f9089, 0x007046c6, 0x0070f7e9, + 0x0071a3f3, 0x00724aea, 0x0072ecd3, 0x007389b6, + 0x0074219d, 0x0074b490, 0x0075429b, 0x0075cbcc, + 0x00765031, 0x0076cfd8, 0x00774ad3, 0x0077c132, + 0x00783308, 0x0078a068, 0x00790968, 0x00796e1c, + 0x0079ce9a, 0x007a2af9, 0x007a8350, 0x007ad7b8, + 0x007b2849, 0x007b751d, 0x007bbe4c, 0x007c03f1, + 0x007c4625, 0x007c8504, 0x007cc0a8, 0x007cf92c, + 0x007d2eaa, 0x007d613e, 0x007d9101, 0x007dbe10, + 0x007de883, 0x007e1076, 0x007e3603, 0x007e5943, + 0x007e7a4f, 0x007e9942, 0x007eb633, 0x007ed13a, + 0x007eea6f, 0x007f01ea, 0x007f17c0, 0x007f2c08, + 0x007f3ed7, 0x007f5043, 0x007f605e, 0x007f6f3c, + 0x007f7cf1, 0x007f898e, 0x007f9525, 0x007f9fc6, + 0x007fa982, 0x007fb268, 0x007fba86, 0x007fc1eb, + 0x007fc8a4, 0x007fcebe, 0x007fd443, 0x007fd941, + 0x007fddc2, 0x007fe1cf, 0x007fe572, 0x007fe8b4, + 0x007feb9e, 0x007fee36, 0x007ff086, 0x007ff293, + 0x007ff463, 0x007ff5fd, 0x007ff765, 0x007ff8a1, + 0x007ff9b6, 0x007ffaa7, 0x007ffb79, 0x007ffc2f, + 0x007ffccb, 0x007ffd52, 0x007ffdc6, 0x007ffe28, + 0x007ffe7b, 0x007ffec2, 0x007ffefd, 0x007fff2f, + 0x007fff58, 0x007fff7b, 0x007fff97, 0x007fffae, + 0x007fffc0, 0x007fffcf, 0x007fffdb, 0x007fffe4, + 0x007fffec, 0x007ffff1, 0x007ffff6, 0x007ffff9, + 0x007ffffb, 0x007ffffd, 0x007ffffe, 0x007fffff, + 0x007fffff, 0x007fffff, 0x007fffff, 0xff800000, + 0x00000000, 0xffa57d86, 0x005a827a, 0xff89be51, + 0x0030fbc5, 0xffcf043b, 0x007641af, 0xff8275a1, + 0x0018f8b8, 0xffb8e313, 0x006a6d99, 0xff959267, + 0x00471ced, 0xffe70748, 0x007d8a5f, 0xff809dc9, + 0x000c8bd3, 0xffaecc33, 0x0062f202, 0xff8f1d34, + 0x003c56ba, 0xffdad7f4, 0x007a7d05, 0xff8582fb, + 0x0025280c, 0xffc3a946, 0x0070e2cc, 0xff9d0dfe, + 0x005133cd, 0xfff3742d, 0x007f6237, 0xff802778, + 0x000647d9, 0xffaa0a5b, 0x005ed77d, 0xff8c4a14, + 0x0036ba20, 0xffd4e0cb, 0x00788484, 0xff83d604, + 0x001f19f9, 0xffbe31e2, 0x006dca0d, 0xff99307f, + 0x004c3fe0, 0xffed37f0, 0x007e9d56, 0xff8162aa, + 0x0012c810, 0xffb3c020, 0x0066cf81, 0xff9235f3, + 0x0041ce1e, 0xffe0e607, 0x007c29fc, 0xff877b7c, + 0x002b1f35, 0xffc945e0, 0x0073b5ec, 0xffa12883, + 0x0055f5a5, 0xfff9b827, 0x007fd888, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + +}; + +static u32 AC3240Ucode1fe000[] = { + 0x00000000, 0x03020102, 0x05040403, 0x00400040, + 0x00500050, 0x00600060, 0x00700070, 0x00800080, + 0x00a000a0, 0x00c000c0, 0x00e000e0, 0x01000100, + 0x01400140, 0x01800180, 0x01c001c0, 0x02000200, + 0x02800280, 0x03000300, 0x03800380, 0x04000400, + 0x04800480, 0x05000500, 0x00460045, 0x00580057, + 0x00690068, 0x007a0079, 0x008c008b, 0x00af00ae, + 0x00d100d0, 0x00f400f3, 0x01170116, 0x015d015c, + 0x01a201a1, 0x01e801e7, 0x022e022d, 0x02b902b8, + 0x03440343, 0x03d003cf, 0x045b045a, 0x04e604e5, + 0x05720571, 0x00600060, 0x00780078, 0x00900090, + 0x00a800a8, 0x00c000c0, 0x00f000f0, 0x01200120, + 0x01500150, 0x01800180, 0x01e001e0, 0x02400240, + 0x02a002a0, 0x03000300, 0x03c003c0, 0x04800480, + 0x05400540, 0x06000600, 0x06c006c0, 0x07800780, + 0x7b67533f, 0x1513110f, 0x04d80540, 0x04100478, + 0x07000000, 0x0b000900, 0x02b002f0, 0x02300270, + 0x017001f0, 0xf80000f0, 0x01000080, 0x02000180, + 0x03000280, 0x04000380, 0x2725231f, 0x2c2b2a29, + 0x2e2e2d2d, 0x30302f2f, 0x04030201, 0x08070605, + 0x0c0b0a09, 0x100f0e0d, 0x14131211, 0x18171615, + 0x1c1b1a19, 0x2825221f, 0x37312e2b, 0x4f49433d, + 0x796d6155, 0xcdb59d85, 0x0000fde5, 0x3d3e3f40, + 0x393a3b3c, 0x35363738, 0x32333434, 0x2f2f3031, + 0x2c2c2d2e, 0x29292a2b, 0x26262728, 0x23242425, + 0x21212223, 0x1e1f2020, 0x1c1d1d1e, 0x1a1b1b1c, + 0x1819191a, 0x16171718, 0x15151516, 0x13131414, + 0x12121213, 0x10111111, 0x0f0f1010, 0x0e0e0e0f, + 0x0d0d0d0d, 0x0c0c0c0c, 0x0b0b0b0b, 0x0a0a0a0a, + 0x0909090a, 0x08080909, 0x08080808, 0x07070707, + 0x06060707, 0x06060606, 0x05050606, 0x05050505, + 0x04040505, 0x04040404, 0x04040404, 0x03030304, + 0x03030303, 0x03030303, 0x02030303, 0x02020202, + 0x02020202, 0x02020202, 0x02020202, 0x01010202, + 0x01010101, 0x01010101, 0x01010101, 0x01010101, + 0x01010101, 0x01010101, 0x01010101, 0x00000101, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x04d004d0, + 0x04000440, 0x03c003e0, 0x03b003b0, 0x03a003a0, + 0x03a003a0, 0x039003a0, 0x03900390, 0x03800380, + 0x03700370, 0x03600360, 0x03500350, 0x03400340, + 0x03200330, 0x03000310, 0x02f002f0, 0x02f002f0, + 0x03100300, 0x03900340, 0x042003e0, 0x04900460, + 0x046004a0, 0x04400440, 0x08000520, 0x08400840, + 0x04f004f0, 0x04100460, 0x03d003e0, 0x03b003c0, + 0x03a003b0, 0x03a003a0, 0x03a003a0, 0x03900390, + 0x03800390, 0x03800380, 0x03700370, 0x03600360, + 0x03500350, 0x03400340, 0x03100320, 0x02f00300, + 0x02f002f0, 0x030002f0, 0x03500320, 0x03e00390, + 0x04500420, 0x049004a0, 0x04400460, 0x06300480, + 0x08400840, 0x05800580, 0x045004b0, 0x03f00420, + 0x03d003e0, 0x03b003c0, 0x03b003b0, 0x03a003a0, + 0x03a003a0, 0x03a003a0, 0x03a003a0, 0x03900390, + 0x03900390, 0x03800380, 0x03700380, 0x03500360, + 0x03300340, 0x03100320, 0x02f00300, 0x02f002f0, + 0x03100300, 0x03500330, 0x041003c0, 0x04a00470, + 0x04400460, 0x04e00450, 0xffaaaaab, 0x00000000, + 0x00555555, 0xff99999a, 0xffcccccd, 0x00000000, + 0x00333333, 0x00666666, 0xff924925, 0xffb6db6e, + 0xffdb6db7, 0x00000000, 0x00249249, 0x00492492, + 0x006db6db, 0xff8ba2e9, 0xffa2e8ba, 0xffba2e8c, + 0xffd1745d, 0xffe8ba2f, 0x00000000, 0x001745d1, + 0x002e8ba3, 0x0045d174, 0x005d1746, 0x00745d17, + 0xff888889, 0xff99999a, 0xffaaaaab, 0xffbbbbbc, + 0xffcccccd, 0xffddddde, 0xffeeeeef, 0x00000000, + 0x00111111, 0x00222222, 0x00333333, 0x00444444, + 0x00555555, 0x00666666, 0x00777777, 0x08070605, + 0x0c0b0a09, 0x10100e0e, 0x00000010, 0x00000000, + 0x00000010, 0x00000020, 0x00000100, 0x00000110, + 0x00000120, 0x00000200, 0x00000210, 0x00000220, + 0x00001000, 0x00001010, 0x00001020, 0x00001100, + 0x00001110, 0x00001120, 0x00001200, 0x00001210, + 0x00001220, 0x00002000, 0x00002010, 0x00002020, + 0x00002100, 0x00002110, 0x00002120, 0x00002200, + 0x00002210, 0x00002220, 0x00000000, 0x00000010, + 0x00000020, 0x00000030, 0x00000040, 0x00000100, + 0x00000110, 0x00000120, 0x00000130, 0x00000140, + 0x00000200, 0x00000210, 0x00000220, 0x00000230, + 0x00000240, 0x00000300, 0x00000310, 0x00000320, + 0x00000330, 0x00000340, 0x00000400, 0x00000410, + 0x00000420, 0x00000430, 0x00000440, 0x00001000, + 0x00001010, 0x00001020, 0x00001030, 0x00001040, + 0x00001100, 0x00001110, 0x00001120, 0x00001130, + 0x00001140, 0x00001200, 0x00001210, 0x00001220, + 0x00001230, 0x00001240, 0x00001300, 0x00001310, + 0x00001320, 0x00001330, 0x00001340, 0x00001400, + 0x00001410, 0x00001420, 0x00001430, 0x00001440, + 0x00002000, 0x00002010, 0x00002020, 0x00002030, + 0x00002040, 0x00002100, 0x00002110, 0x00002120, + 0x00002130, 0x00002140, 0x00002200, 0x00002210, + 0x00002220, 0x00002230, 0x00002240, 0x00002300, + 0x00002310, 0x00002320, 0x00002330, 0x00002340, + 0x00002400, 0x00002410, 0x00002420, 0x00002430, + 0x00002440, 0x00003000, 0x00003010, 0x00003020, + 0x00003030, 0x00003040, 0x00003100, 0x00003110, + 0x00003120, 0x00003130, 0x00003140, 0x00003200, + 0x00003210, 0x00003220, 0x00003230, 0x00003240, + 0x00003300, 0x00003310, 0x00003320, 0x00003330, + 0x00003340, 0x00003400, 0x00003410, 0x00003420, + 0x00003430, 0x00003440, 0x00004000, 0x00004010, + 0x00004020, 0x00004030, 0x00004040, 0x00004100, + 0x00004110, 0x00004120, 0x00004130, 0x00004140, + 0x00004200, 0x00004210, 0x00004220, 0x00004230, + 0x00004240, 0x00004300, 0x00004310, 0x00004320, + 0x00004330, 0x00004340, 0x00004400, 0x00004410, + 0x00004420, 0x00004430, 0x00004440, 0x00000000, + 0x00000100, 0x00000200, 0x00000300, 0x00000400, + 0x00000500, 0x00000600, 0x00000700, 0x00000800, + 0x00000900, 0x00000a00, 0x00001000, 0x00001100, + 0x00001200, 0x00001300, 0x00001400, 0x00001500, + 0x00001600, 0x00001700, 0x00001800, 0x00001900, + 0x00001a00, 0x00002000, 0x00002100, 0x00002200, + 0x00002300, 0x00002400, 0x00002500, 0x00002600, + 0x00002700, 0x00002800, 0x00002900, 0x00002a00, + 0x00003000, 0x00003100, 0x00003200, 0x00003300, + 0x00003400, 0x00003500, 0x00003600, 0x00003700, + 0x00003800, 0x00003900, 0x00003a00, 0x00004000, + 0x00004100, 0x00004200, 0x00004300, 0x00004400, + 0x00004500, 0x00004600, 0x00004700, 0x00004800, + 0x00004900, 0x00004a00, 0x00005000, 0x00005100, + 0x00005200, 0x00005300, 0x00005400, 0x00005500, + 0x00005600, 0x00005700, 0x00005800, 0x00005900, + 0x00005a00, 0x00006000, 0x00006100, 0x00006200, + 0x00006300, 0x00006400, 0x00006500, 0x00006600, + 0x00006700, 0x00006800, 0x00006900, 0x00006a00, + 0x00007000, 0x00007100, 0x00007200, 0x00007300, + 0x00007400, 0x00007500, 0x00007600, 0x00007700, + 0x00007800, 0x00007900, 0x00007a00, 0x00008000, + 0x00008100, 0x00008200, 0x00008300, 0x00008400, + 0x00008500, 0x00008600, 0x00008700, 0x00008800, + 0x00008900, 0x00008a00, 0x00009000, 0x00009100, + 0x00009200, 0x00009300, 0x00009400, 0x00009500, + 0x00009600, 0x00009700, 0x00009800, 0x00009900, + 0x00009a00, 0x0000a000, 0x0000a100, 0x0000a200, + 0x0000a300, 0x0000a400, 0x0000a500, 0x0000a600, + 0x0000a700, 0x0000a800, 0x0000a900, 0x0000aa00, + 0xff800000, 0xff800000, 0xffb82995, 0xffaf5d75, + 0xffa57d87, 0xff9a6806, 0xff8df708, 0xff800000, + 0xffb82995, 0xffaf5d75, 0xffa57d87, 0xff9a6806, + 0xff8df708, 0xff800000, 0xffb82995, 0xffaf5d75, + 0xffa57d87, 0xff9a6806, 0xff8df708, 0xff800000, + 0xffb82995, 0xffaf5d75, 0xffa57d87, 0xff9a6806, + 0xff8df708, 0xff800000, 0xffb82995, 0xffaf5d75, + 0xffa57d87, 0xff9a6806, 0xff8df708, 0xff800000, + 0xfffb0000, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, + 0xfffdfffd, 0xfffdfffd, 0xfffdfffd, 0xfffefffe, + 0xfffefffe, 0xfffefffe, 0xffffffff, 0xffffffff, + 0xffffffff, 0x00000000, 0x00000000, 0x00000000, + 0x80050000, 0x000a800f, 0x001e801b, 0x80110014, + 0x00368033, 0x8039003c, 0x802d0028, 0x00228027, + 0x00668063, 0x8069006c, 0x807d0078, 0x00728077, + 0x80550050, 0x005a805f, 0x004e804b, 0x80410044, + 0x00c680c3, 0x80c900cc, 0x80dd00d8, 0x00d280d7, + 0x80f500f0, 0x00fa80ff, 0x00ee80eb, 0x80e100e4, + 0x80a500a0, 0x00aa80af, 0x00be80bb, 0x80b100b4, + 0x00968093, 0x8099009c, 0x808d0088, 0x00828087, + 0x01868183, 0x8189018c, 0x819d0198, 0x01928197, + 0x81b501b0, 0x01ba81bf, 0x01ae81ab, 0x81a101a4, + 0x81e501e0, 0x01ea81ef, 0x01fe81fb, 0x81f101f4, + 0x01d681d3, 0x81d901dc, 0x81cd01c8, 0x01c281c7, + 0x81450140, 0x014a814f, 0x015e815b, 0x81510154, + 0x01768173, 0x8179017c, 0x816d0168, 0x01628167, + 0x01268123, 0x8129012c, 0x813d0138, 0x01328137, + 0x81150110, 0x011a811f, 0x010e810b, 0x81010104, + 0x03068303, 0x8309030c, 0x831d0318, 0x03128317, + 0x83350330, 0x033a833f, 0x032e832b, 0x83210324, + 0x83650360, 0x036a836f, 0x037e837b, 0x83710374, + 0x03568353, 0x8359035c, 0x834d0348, 0x03428347, + 0x83c503c0, 0x03ca83cf, 0x03de83db, 0x83d103d4, + 0x03f683f3, 0x83f903fc, 0x83ed03e8, 0x03e283e7, + 0x03a683a3, 0x83a903ac, 0x83bd03b8, 0x03b283b7, + 0x83950390, 0x039a839f, 0x038e838b, 0x83810384, + 0x82850280, 0x028a828f, 0x029e829b, 0x82910294, + 0x02b682b3, 0x82b902bc, 0x82ad02a8, 0x02a282a7, + 0x02e682e3, 0x82e902ec, 0x82fd02f8, 0x02f282f7, + 0x82d502d0, 0x02da82df, 0x02ce82cb, 0x82c102c4, + 0x02468243, 0x8249024c, 0x825d0258, 0x02528257, + 0x82750270, 0x027a827f, 0x026e826b, 0x82610264, + 0x82250220, 0x022a822f, 0x023e823b, 0x82310234, + 0x02168213, 0x8219021c, 0x820d0208, 0x02028207, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0xff800000, 0xffa57d86, 0xffa57d86, + 0xffcf043b, 0xff89be51, 0xff89be51, 0xffcf043b, + 0xffe70748, 0xff8275a1, 0xff959267, 0xffb8e313, + 0xffb8e313, 0xff959267, 0xff8275a1, 0xffe70748, + 0xfff3742d, 0xff809dc9, 0xff9d0dfe, 0xffaecc33, + 0xffc3a946, 0xff8f1d34, 0xff8582fb, 0xffdad7f4, + 0xffdad7f4, 0xff8582fb, 0xff8f1d34, 0xffc3a946, + 0xffaecc33, 0xff9d0dfe, 0xff809dc9, 0xfff3742d, + 0xfff9b827, 0xff802778, 0xffa12883, 0xffaa0a5b, + 0xffc945e0, 0xff8c4a14, 0xff877b7c, 0xffd4e0cb, + 0xffe0e607, 0xff83d604, 0xff9235f3, 0xffbe31e2, + 0xffb3c020, 0xff99307f, 0xff8162aa, 0xffed37f0, + 0xffed37f0, 0xff8162aa, 0xff99307f, 0xffb3c020, + 0xffbe31e2, 0xff9235f3, 0xff83d604, 0xffe0e607, + 0xffd4e0cb, 0xff877b7c, 0xff8c4a14, 0xffc945e0, + 0xffaa0a5b, 0xffa12883, 0xff802778, 0xfff9b827, + 0xcbcecdc4, 0xcfcac9c8, 0xc3c6c5cc, 0xc7c2c1c0, + 0x1b1e1d14, 0x1f1a1918, 0x1316151c, 0x17121110, + 0x2b2e2d24, 0x2f2a2928, 0x2326252c, 0x27222120, + 0x3b3e3d34, 0x3f3a3938, 0x3336353c, 0x37323130, + 0x0b0e0d04, 0x0f0a0908, 0x0306050c, 0x07020100, + 0xdbdeddd4, 0xdfdad9d8, 0xd3d6d5dc, 0xd7d2d1d0, + 0xebeeede4, 0xefeae9e8, 0xe3e6e5ec, 0xe7e2e1e0, + 0xfbfefdf4, 0xfffaf9f8, 0xf3f6f5fc, 0xf7f2f1f0, + 0x4b4e4d44, 0x4f4a4948, 0x4346454c, 0x47424140, + 0x9b9e9d94, 0x9f9a9998, 0x9396959c, 0x97929190, + 0xabaeada4, 0xafaaa9a8, 0xa3a6a5ac, 0xa7a2a1a0, + 0xbbbebdb4, 0xbfbab9b8, 0xb3b6b5bc, 0xb7b2b1b0, + 0x8b8e8d84, 0x8f8a8988, 0x8386858c, 0x87828180, + 0x5b5e5d54, 0x5f5a5958, 0x5356555c, 0x57525150, + 0x6b6e6d64, 0x6f6a6968, 0x6366656c, 0x67626160, + 0x7b7e7d74, 0x7f7a7978, 0x7376757c, 0x77727170, + 0x341424c4, 0x3e1e2ece, 0x3d1d2dcd, 0x3b1b2bcb, + 0xb494a444, 0xbe9eae4e, 0xbd9dad4d, 0xbb9bab4b, + 0xf4d4e404, 0xfedeee0e, 0xfddded0d, 0xfbdbeb0b, + 0x74546484, 0x7e5e6e8e, 0x7d5d6d8d, 0x7b5b6b8b, + 0x3c1c2ccc, 0x361626c6, 0x351525c5, 0x331323c3, + 0xbc9cac4c, 0xb696a646, 0xb595a545, 0xb393a343, + 0xfcdcec0c, 0xf6d6e606, 0xf5d5e505, 0xf3d3e303, + 0x7c5c6c8c, 0x76566686, 0x75556585, 0x73536383, + 0x381828c8, 0x3a1a2aca, 0x391929c9, 0x3f1f2fcf, + 0xb898a848, 0xba9aaa4a, 0xb999a949, 0xbf9faf4f, + 0xf8d8e808, 0xfadaea0a, 0xf9d9e909, 0xffdfef0f, + 0x78586888, 0x7a5a6a8a, 0x79596989, 0x7f5f6f8f, + 0x301020c0, 0x321222c2, 0x311121c1, 0x371727c7, + 0xb090a040, 0xb292a242, 0xb191a141, 0xb797a747, + 0xf0d0e000, 0xf2d2e202, 0xf1d1e101, 0xf7d7e707, + 0x70506080, 0x72526282, 0x71516181, 0x77576787, + 0x05040100, 0x15141110, 0x25242120, 0x35343130, + 0x85848180, 0x95949190, 0xa5a4a1a0, 0xb5b4b1b0, + 0xc0408000, 0xe060a020, 0xd0509010, 0xf070b030, + 0xc8488808, 0xe868a828, 0xd8589818, 0xf878b838, + 0xc4448404, 0xe464a424, 0xd4549414, 0xf474b434, + 0xcc4c8c0c, 0xec6cac2c, 0xdc5c9c1c, 0xfc7cbc3c, + 0xc2428202, 0xe262a222, 0xd2529212, 0xf272b232, + 0xca4a8a0a, 0xea6aaa2a, 0xda5a9a1a, 0xfa7aba3a, + 0xc6468606, 0xe666a626, 0xd6569616, 0xf676b636, + 0xce4e8e0e, 0xee6eae2e, 0xde5e9e1e, 0xfe7ebe3e, + 0xc1418101, 0xe161a121, 0xd1519111, 0xf171b131, + 0xc9498909, 0xe969a929, 0xd9599919, 0xf979b939, + 0xc5458505, 0xe565a525, 0xd5559515, 0xf575b535, + 0xcd4d8d0d, 0xed6dad2d, 0xdd5d9d1d, 0xfd7dbd3d, + 0xc3438303, 0xe363a323, 0xd3539313, 0xf373b333, + 0xcb4b8b0b, 0xeb6bab2b, 0xdb5b9b1b, 0xfb7bbb3b, + 0xc7478707, 0xe767a727, 0xd7579717, 0xf777b737, + 0xcf4f8f0f, 0xef6faf2f, 0xdf5f9f1f, 0xff7fbf3f, + 0x1045a3e2, 0x000000f4, 0x263b7333, 0x766b2363, + 0x2b367e3e, 0x7b662e6e, 0x06db93d3, 0x964b0343, + 0x0bd69ede, 0x9b460e4e, 0x825f1757, 0x12cf87c7, + 0x8f521a5a, 0x1fc28aca, 0x00d199d9, 0x90410949, + 0x01d098d8, 0x91400848, 0x24357d3d, 0x74652d6d, + 0x25347c3c, 0x75642c6c, 0x04d59ddd, 0x94450d4d, + 0x05d49cdc, 0x95440c4c, 0x80511959, 0x10c189c9, + 0x81501858, 0x11c088c8, 0x02df97d7, 0x924f0747, + 0x0fd29ada, 0x9f420a4a, 0x865b1353, 0x16cb83c3, + 0x8b561e5e, 0x1bc68ece, 0xa6bbf3b3, 0xf6eba3e3, + 0xabb6febe, 0xfbe6aeee, 0x223f7737, 0x726f2767, + 0x2f327a3a, 0x7f622a6a, 0xa0b1f9b9, 0xf0e1a9e9, + 0xa1b0f8b8, 0xf1e0a8e8, 0x84551d5d, 0x14c58dcd, + 0x85541c5c, 0x15c48ccc, 0xa4b5fdbd, 0xf4e5aded, + 0xa5b4fcbc, 0xf5e4acec, 0x20317939, 0x70612969, + 0x21307838, 0x71602868, 0xa2bff7b7, 0xf2efa7e7, + 0xafb2faba, 0xffe2aaea, 0x00000000, 0x00000000, + +}; + +static u32 AC3240Ucode1fff80[] = { + 0x0000240f, 0x007fffff, 0x007fffff, 0x00000003, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00000000, 0x00000000, 0x00000000, + +}; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/ls220/ac3.h linux.19rc3-ac4/drivers/media/video/ls220/ac3.h --- linux.19rc3/drivers/media/video/ls220/ac3.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/ls220/ac3.h 2002-07-29 13:58:40.000000000 +0100 @@ -0,0 +1,2850 @@ +static u32 AC3Ucode1f1800[] = { + 0xb500000f, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xb5001223, 0x00000000, 0x00000000, 0x00000000, + 0x820f001f, 0x802f001f, 0x80070800, 0x001f6193, + 0x800500d4, 0x8053ffff, 0x9842c7ff, 0x8039ff7c, + 0x1400b802, 0x003f6000, 0x94210007, 0xb0010001, + 0xb4200001, 0x98002800, 0xb0010000, 0xb4200001, + 0x98000800, 0x805300ff, 0x1800b802, 0x800600d4, + 0x8013001f, 0x9020c000, 0x003fb006, 0x803effe0, + 0x803effe8, 0x803effec, 0x9020e000, 0x9021ffe4, + 0x9020fa00, 0x803effd0, 0x803effdc, 0x803effd8, + 0x9020fe00, 0x803effd4, 0x90400000, 0x804600a2, + 0x90421800, 0x804600a3, 0x80134099, 0x98000040, + 0x800600a6, 0x80130000, 0x98003ca1, 0x800600a1, + 0x80050080, 0x98000002, 0x80060080, 0x80070001, + 0x001f2013, 0x001f2324, 0x80070000, 0x001fb0ba, + 0x001f23f9, 0x801eb3f0, 0x80070800, 0x001f600f, + 0x80070000, 0x001f2012, 0x001fb0cb, 0x001fb010, + 0x801efff0, 0x98004000, 0x98008000, 0x001f600e, + 0x83e40137, 0x80070000, 0x801eb3f8, 0x801eff70, + 0x800500a0, 0xb0000001, 0xb4000009, 0x80070001, + 0x800600a0, 0x80050080, 0x98000020, 0x80060080, + 0x9400ffdf, 0x80060080, 0x80070000, 0x800600a0, + 0x81df0004, 0x00000000, 0x00000000, 0x801bfff0, + 0x00000000, 0x940000ff, 0xb0000000, 0xb420004e, + 0x003f400e, 0x94010010, 0xb0000000, 0xb400fff4, + 0x838413d5, 0x003f0013, 0xb0010001, 0xb420003b, + 0x803bffe8, 0x801bffec, 0x00000000, 0x3001b800, + 0xb4600001, 0x90212000, 0x0421b800, 0x005f4193, + 0x5841b802, 0x3001b802, 0xb460000d, 0x80050086, + 0x005f9016, 0xb0020000, 0xb4200002, 0x001fb016, + 0xb500ffdf, 0x0420b802, 0xb0010b50, 0xb4a0ffdc, + 0x80070000, 0x001fb016, 0x83e40101, 0xb500ffd8, + 0x80070000, 0x001fb016, 0x001f400e, 0x9400000f, + 0xb0000000, 0xb4000014, 0xb0000001, 0xb4000010, + 0x003f400e, 0x9421fff0, 0x003f600e, 0x003f9006, + 0x9421ffff, 0x90210004, 0xb001e000, 0xb4800002, + 0x8421e000, 0x9021c000, 0x8013001f, 0x1021b800, + 0x003fb006, 0x003f90cb, 0x90210004, 0x003fb0cb, + 0x83e400f7, 0x83e413b4, 0x8007001f, 0x94000003, + 0x5810b800, 0x83e71aa8, 0x1bffb800, 0x003f9008, + 0x1821b800, 0x00ffb801, 0x83e41407, 0x80270000, + 0x003f2013, 0x8007001f, 0x94000003, 0x5810b800, + 0x83671ad4, 0x1b7bb800, 0x003f9009, 0x1821b800, + 0x00ffb801, 0xb500ffaa, 0x803bffc0, 0x805bffc4, + 0x807bffc8, 0x809bffcc, 0x5828b801, 0x5cb8b802, + 0x1821b805, 0x5848b802, 0x5cb8b803, 0x1842b805, + 0x5868b803, 0x5cb8b804, 0x1863b805, 0x5888b804, + 0x1884b800, 0x803effc0, 0x805effc4, 0x807effc8, + 0x809effcc, 0x003f400e, 0xb0000086, 0xb4400040, + 0xb0000084, 0xb400002a, 0xb0000085, 0xb4000030, + 0xb0000086, 0xb4000032, 0x001f4000, 0x94000080, + 0xb0000080, 0xb400006a, 0x80130000, 0x98003ca1, + 0x005f4000, 0x94420008, 0xb0020008, 0xb4000001, + 0xa0000080, 0x800600a1, 0x8013001f, 0x9040c000, + 0x005fb006, 0x805effe0, 0x805effe8, 0x805effec, + 0x9040e000, 0x805effe4, 0x9040fa00, 0x805effd0, + 0x805effdc, 0x805effd8, 0x9040fe00, 0x805effd4, + 0x80070001, 0x001f2013, 0x80070000, 0x001fb0cb, + 0x001fb010, 0x001f2058, 0x80071fc0, 0x001fb008, + 0x80075fb0, 0x001fb009, 0x98214000, 0xb5000010, + 0x94011000, 0xb0001000, 0xb4200001, 0x9421efff, + 0x98210010, 0xb500000a, 0x80070000, 0x001fb0cb, + 0x83e40097, 0x003f400e, 0x9421ffef, 0xb5000004, + 0x83e40093, 0x003f400e, 0x98211000, 0x9421ffef, + 0x003f600e, 0x80070100, 0x801efff0, 0xb500ff54, + 0xb000008b, 0xb400001c, 0xb000008e, 0xb4000022, + 0xb000008d, 0xb400001c, 0xb000008c, 0xb4000021, + 0xb0000087, 0xb400ffe8, 0xb0000088, 0xb4000014, + 0xb000008a, 0xb4000015, 0xb0000089, 0xb400001d, + 0xb00000a0, 0xb400001f, 0xb00000a1, 0xb4000041, + 0xb00000a2, 0xb400004e, 0xb00000a3, 0xb4000046, + 0xb00000a4, 0xb4000050, 0xb00000a5, 0xb4000054, + 0xb00000a6, 0xb4000058, 0x803efff8, 0xb500ffdd, + 0x9421ffdf, 0xb500ffda, 0xb500ffda, 0x80270100, + 0x803efff8, 0xb500ffd7, 0x80070000, 0x001fb017, + 0xb500ffd4, 0x801bffb0, 0x00000000, 0x001fb003, + 0xb500ffd0, 0x803bff80, 0x00000000, 0x003f6001, + 0xb500ffcc, 0x003f90ba, 0x803efff8, 0xb500ffc9, + 0x80130001, 0x98003da1, 0x800600a1, 0x80070200, + 0x801ebf34, 0x83e40042, 0x8013001f, 0x9840c000, + 0x805effe0, 0x005fb006, 0x805effe8, 0x805effec, + 0x90422000, 0x805effe4, 0x9040fa00, 0x805effd0, + 0x805effdc, 0x805effd8, 0x9040fe00, 0x805effd4, + 0x80070001, 0x001f2013, 0x80070000, 0x001f2324, + 0x001fb0cb, 0x001fb010, 0x001f2058, 0x80077560, + 0x001fb008, 0x80077810, 0x001fb009, 0x98214000, + 0xb500ffa7, 0x80270000, 0x8047fef0, 0x003eb802, + 0x90420004, 0x003eb802, 0x90420004, 0x003eb802, + 0x90420004, 0x003eb802, 0x81df0000, 0x00000000, + 0x00000000, 0x83641491, 0x81df0004, 0xb500ff99, + 0x81df0000, 0x00000000, 0x00000000, 0x8364143b, + 0x81df0004, 0xb500ff93, 0x81df0000, 0x00000000, + 0x00000000, 0x836413f6, 0x81df0004, 0xb500ff8d, + 0x81df0000, 0x00000000, 0x00000000, 0x83441359, + 0x81df0004, 0xb500ff87, 0x81df0000, 0x00000000, + 0x00000000, 0x8344133e, 0x81df0004, 0xb500ff81, + 0x80070000, 0x80470000, 0x81df0000, 0x00000000, + 0x00000000, 0xb6002003, 0xb6003002, 0x001eb802, + 0x90420004, 0x80171000, 0x8057ffff, 0xb6002002, + 0xb6001801, 0x001fa020, 0x81df0004, 0x00ffb81f, + 0x001f4000, 0x94000080, 0xb0000080, 0xb4200001, + 0xb500ffeb, 0xb500000a, 0x80270000, 0x003f2013, + 0x8007001f, 0x94000003, 0x5810b800, 0x83671ea0, + 0x1b7bb800, 0x003f9009, 0x1821b800, 0x00ffb801, + 0x003f0013, 0xb0010001, 0xb420fff3, 0x83a70000, + 0x803bff70, 0x00000000, 0xb0010000, 0xb4000015, + 0x80170300, 0x80070000, 0x81df0000, 0x00000000, + 0x00000000, 0xb6000601, 0x001fa020, 0x83640ce3, + 0x00ff0325, 0x82870000, 0xb6270002, 0x83640228, + 0x92940001, 0x81df0004, 0x001f033b, 0xb0000000, + 0xb4000002, 0x80270000, 0xb5000001, 0x80270001, + 0x003f233b, 0x80270000, 0x003f2013, 0x8007001f, + 0x94000003, 0x5810b800, 0x83671f3c, 0x1b7bb800, + 0x003f9009, 0x1821b800, 0x00ffb801, 0x003f0013, + 0xb0010001, 0xb420fff3, 0x93bd0001, 0xb01d0004, + 0xb480ffd7, 0x803bff70, 0x00000000, 0xb0010000, + 0xb4000005, 0x81df0000, 0x00000000, 0x00000000, + 0x83640c8b, 0x81df0004, 0x00000000, 0x00000000, + 0x00ffb81f, 0x007f90cb, 0x90630400, 0x007fb0cb, + 0x003f9006, 0x9421ffff, 0x90210400, 0xb001e000, + 0xb4800002, 0x8421e000, 0x9021c000, 0x8013001f, + 0x1021b800, 0x003fb006, 0x803effec, 0x00ffb81f, + 0x015f400e, 0x944a4000, 0xb0024000, 0xb4200090, + 0x954abfff, 0x015f600e, 0x820f001f, 0x802f001f, + 0x81470000, 0x015f23f9, 0x829702ec, 0x82d7ffff, + 0x82f70000, 0x81df0000, 0x00000000, 0x00000000, + 0xb6000501, 0x029fa02a, 0x82970400, 0xb6000702, + 0xb6000001, 0x029fa02a, 0x81df0004, 0x8053ff00, + 0x98420000, 0x805ebf14, 0x805ebf18, 0x805ebf1c, + 0x805ebf20, 0x805ebf24, 0x805ebf28, 0x80270000, + 0x003f2328, 0x80275480, 0x005fb801, 0x8033001f, + 0x9821c000, 0x803effe0, 0x90212000, 0x803effe4, + 0x80dbff8c, 0x80fbff90, 0x80debf14, 0x80febf18, + 0x80dbff94, 0x80fbff98, 0x80debf1c, 0x80febf20, + 0x80dbff9c, 0x80fbffa0, 0x80debf24, 0x80febf28, + 0x80dbff84, 0x80e70001, 0x00dfb001, 0x80dbff88, + 0x00ff6191, 0x00dfb002, 0x80dbffb0, 0x80470000, + 0x00dfb003, 0x80d9ff80, 0x005fb0cf, 0x005fb0c6, + 0x00df6001, 0x80470001, 0x005f618f, 0x804700ff, + 0x005f231c, 0x005f231d, 0x80470000, 0x005f204e, + 0x8047e138, 0x5c42b802, 0x814f6300, 0x80cf00a9, + 0x005fb0bc, 0x5842b802, 0x01cfb802, 0x005f90bc, + 0xb520ffff, 0x8067e16c, 0x5c62b803, 0x80270040, + 0x81df0000, 0x00000000, 0x00000000, 0xb6000209, + 0x814fffc0, 0x00cfb801, 0x007fb0bc, 0x5862b803, + 0x01cfb803, 0x007f90bc, 0xb520ffff, 0x90210020, + 0x90630020, 0x81df0004, 0x8047e398, 0x5c42b802, + 0x814fce40, 0x80cf0080, 0x005fb0bc, 0x5842b802, + 0x01cfb802, 0x005f90bc, 0xb520ffff, 0x8047e400, + 0x5c42b802, 0x814f7380, 0x80cf009a, 0x005fb0bc, + 0x5842b802, 0x01cfb802, 0x005f90bc, 0xb520ffff, + 0x8047e43c, 0x5c42b802, 0x814f18c0, 0x80cf00b6, + 0x005fb0bc, 0x5842b802, 0x01cfb802, 0x005f90bc, + 0xb520ffff, 0x80e70000, 0x00ffb0ba, 0x808f0000, + 0x806f001f, 0x80af001f, 0x8027b9fc, 0x5c22b801, + 0x80670700, 0x81df0000, 0x00000000, 0x00000000, + 0xb600080a, 0x00cfb803, 0x003fb0bc, 0x5822b801, + 0x01cfb801, 0x003f90bc, 0x0047b86f, 0xb0020001, + 0xb4c0fffd, 0x90210020, 0x90630020, 0x81df0004, + 0x834400d7, 0xb0180000, 0xb4200025, 0x834406dc, + 0x80c70000, 0x00df2324, 0x83640026, 0x83440228, + 0x00df0324, 0x90c60001, 0x00df2324, 0xb0060006, + 0xb4000003, 0x81472228, 0x015fb008, 0x00ffb81f, + 0x00ff90ba, 0x90e70001, 0x00ffb0ba, 0x019f9006, + 0x958cffff, 0x00df4193, 0x58c1b806, 0x118cb806, + 0xb00ce000, 0xb4800002, 0x858ce000, 0x918cc000, + 0x8153001f, 0x118cb80a, 0x819effec, 0x019fb006, + 0x015f4193, 0x5941b80a, 0x019f90cb, 0x118cb80a, + 0x019fb0cb, 0x81472210, 0x015fb008, 0x00ffb81f, + 0x015f400e, 0x194ab818, 0x015f600e, 0x802500a5, + 0x00ffb81f, 0x803bff8c, 0x805bff90, 0x803ebf14, + 0x805ebf18, 0x803bff94, 0x805bff98, 0x803ebf1c, + 0x805ebf20, 0x803bff9c, 0x805bffa0, 0x803ebf24, + 0x805ebf28, 0x80470003, 0x805ebefc, 0x003f0384, + 0x5822b801, 0x9021eb50, 0x005bb801, 0x00000000, + 0xb0020001, 0xb4200002, 0x80470001, 0x805ebefc, + 0x8073ff80, 0x98630000, 0x8027bf14, 0x8047befc, + 0x81df0000, 0x00000000, 0x00000000, 0xb6000609, + 0x009bb801, 0x00000000, 0x00a7b804, 0x6081b804, + 0x3004b803, 0xb4000001, 0x00beb802, 0x90210004, + 0x90420004, 0x81df0004, 0x00ffb81b, 0x00000000, + 0x81150010, 0x00000000, 0x00000000, 0x81350010, + 0x00000000, 0x00000000, 0x81550002, 0x00000000, + 0x015f2380, 0x81550006, 0x00000000, 0x015f2381, + 0x81550005, 0x00000000, 0x015f2382, 0x81550003, + 0x00000000, 0x015f2383, 0x81550003, 0x015f2384, + 0xb00a0001, 0xb4000005, 0x956a0001, 0xb00b0000, + 0xb4000002, 0x81750002, 0x017f2385, 0x956a0004, + 0xb00b0000, 0xb4000002, 0x81750002, 0x017f2386, + 0xb00a0002, 0xb4200003, 0x81750002, 0x00000000, + 0x017f2387, 0x81750001, 0x00000000, 0x017f2388, + 0x81750005, 0x00000000, 0x017f2389, 0x81750001, + 0x017f239f, 0xb00b0001, 0xb4200003, 0x81750008, + 0x5968b80b, 0x017f61c5, 0x81750001, 0x017f238c, + 0xb00b0001, 0xb4200003, 0x81750008, 0x00000000, + 0x017f238d, 0x81750001, 0x017f238e, 0xb00b0001, + 0xb4200005, 0x81750005, 0x00000000, 0x017f238f, + 0x81750002, 0x017f2390, 0xb00a0000, 0xb420001b, + 0x81750005, 0x00000000, 0x017f2391, 0x81750001, + 0x017f23a0, 0xb00b0001, 0xb4200003, 0x81750008, + 0x5968b80b, 0x017f61c9, 0x81750001, 0x017f2394, + 0xb00b0001, 0xb4200003, 0x81750008, 0x00000000, + 0x017f2395, 0x81750001, 0x017f2396, 0xb00b0001, + 0xb4200006, 0x81750005, 0x00000000, 0x017f2397, + 0x81750002, 0x00000000, 0x017f2398, 0x81750001, + 0x00000000, 0x017f2399, 0x81750001, 0x00000000, + 0x017f239a, 0x81750001, 0x017f239b, 0xb00b0001, + 0xb4200003, 0x8175000e, 0x00000000, 0x017f61be, + 0x81750001, 0x017f239c, 0xb00b0001, 0xb4200003, + 0x8175000e, 0x00000000, 0x017f237e, 0x81750001, + 0x017f239d, 0xb00b0001, 0xb4200006, 0x81750006, + 0x017f239e, 0x916b0001, 0x81550008, 0x856b0001, + 0xb4e0fffd, 0x00ffb81c, 0x00000000, 0x00000000, + 0x81470000, 0x015f2385, 0x015f2386, 0x015f2387, + 0x015f238d, 0x015f238f, 0x015f2390, 0x015f2391, + 0x015f2395, 0x015f2396, 0x015f2397, 0x015f2398, + 0x015f61be, 0x015f61bf, 0x82070028, 0x023f9006, + 0x83a40034, 0x83270000, 0x003fb819, 0x003f9006, + 0x5823b801, 0x83338000, 0x1b39b801, 0x003fb819, + 0x00000000, 0x00000000, 0x81550000, 0x8384ff64, + 0x017f0380, 0xad4b0026, 0x013f0381, 0x114ab809, + 0x5941b80a, 0x914ae00c, 0x0199b80a, 0x00000000, + 0x019f6193, 0xb0080b77, 0xb4200010, 0x015f0380, + 0xb00a0003, 0xb4600011, 0xb0090026, 0xb4600013, + 0x017f90ba, 0xb00b0000, 0xb4200002, 0x017f0383, + 0x017f2057, 0x015f0383, 0x017f0057, 0x300ab80b, + 0xb420000e, 0x83070000, 0x00ffb81a, 0x83070800, + 0x031f6193, 0x83070001, 0x00ffb81a, 0x83070800, + 0x031f6193, 0x83070002, 0x00ffb81a, 0x83070800, + 0x031f6193, 0x83070003, 0x00ffb81a, 0x83070003, + 0x00ffb81a, 0x5e02b810, 0x5a02b810, 0x00bf9011, + 0x00df004f, 0xa5260020, 0x81e70000, 0x82471000, + 0x95d1ffff, 0xa5cee000, 0x300eb810, 0xb4600002, + 0x05f0b80e, 0x0207b80e, 0x8267001f, 0x82c70020, + 0x82971000, 0xb0100080, 0xb4800023, 0x5a8bb813, + 0x5aa6b813, 0x1a94b815, 0x01efb812, 0x014fb814, + 0x01cfb811, 0xb520ffff, 0x81df0000, 0x00000000, + 0x00000000, 0xb636000f, 0x81470000, 0x039f8014, + 0xb6000404, 0x5948b80a, 0x957c00ff, 0x194ab80b, + 0x5f88b81c, 0xb0060020, 0xb4200001, 0x80a70000, + 0x64a6b805, 0x68e9b80a, 0x18a5b807, 0x029fa025, + 0x00a7b80a, 0x81df0004, 0x01efb812, 0x014fb814, + 0x01afb811, 0xb520ffff, 0x5ae2b816, 0x1231b817, + 0x0610b817, 0xb500ffda, 0xb0100000, 0xb4000003, + 0x5ec2b810, 0x86760001, 0xb500ffd8, 0xb00f0000, + 0xb4000005, 0x0207b80f, 0x81f3001f, 0x9a2fc000, + 0x81e70000, 0xb500ffcc, 0x015fb011, 0x00ffb81d, + 0x8057ffff, 0x80d7ffff, 0x8157ffff, 0x81d7ffff, + 0x8257ffff, 0x82d7ffff, 0x8357ffff, 0x83d7ffff, + 0x80770000, 0x80f70000, 0x81770000, 0x81f70000, + 0x82770000, 0x82f70000, 0x83770000, 0x83f70000, + 0xaeb40080, 0x808f0000, 0x806f001f, 0x80af001f, + 0xb0140000, 0xb4400014, 0x806f001f, 0x80af001f, + 0x8027b9fc, 0x5c22b801, 0x80670700, 0xb6000208, + 0x00cfb803, 0x003fb0bc, 0x5822b801, 0x01cfb801, + 0x003f90bc, 0xb520ffff, 0x90630020, 0x90210020, + 0x80270000, 0x80171000, 0xb6000303, 0xb6000001, + 0x001fa021, 0x00000000, 0x82670000, 0xb6000268, + 0x80170a00, 0x80970afc, 0x81170b00, 0x81970bfc, + 0x80271c00, 0x1021b813, 0x1021b813, 0x0217b801, + 0x80271ffc, 0x0421b813, 0x0421b813, 0x0297b801, + 0x80270c00, 0x1021b813, 0x1021b813, 0x0317b801, + 0x80270ffc, 0x0421b813, 0x0421b813, 0x0397b801, + 0x80478500, 0x1042b813, 0x5c42b802, 0x1022b815, + 0x80670280, 0x00cfb803, 0x003fb0bc, 0x5822b801, + 0x01cfb801, 0x003f90bc, 0xb520ffff, 0x009f033b, + 0x80478480, 0x0442b813, 0x5c42b802, 0x1022b815, + 0x806702a0, 0x00cfb803, 0x003fb0bc, 0x5822b801, + 0x01cfb801, 0x003f90bc, 0xb520ffff, 0xb0040000, + 0xb4000002, 0x80479000, 0xb5000001, 0x80479c00, + 0x1042b813, 0x5c42b802, 0x1022b815, 0x806702c0, + 0x00cfb803, 0x003fb0bc, 0x5822b801, 0x01cfb801, + 0x003f90bc, 0xb520ffff, 0xb0040000, 0xb4000002, + 0x80479180, 0xb5000001, 0x80479d80, 0x0442b813, + 0x5c42b802, 0x1022b815, 0x806702e0, 0x00cfb803, + 0x003fb0bc, 0x5822b801, 0x01cfb801, 0x003f90bc, + 0xb520ffff, 0x81270000, 0x80370000, 0x80b70000, + 0x81370000, 0x81b70000, 0x82370004, 0x82b7fffc, + 0xb6002016, 0x41498008, 0x51498814, 0x51498814, + 0x51418810, 0x51418810, 0x41818814, 0x0308a02a, + 0x49958820, 0x51898810, 0x51918828, 0x414d8814, + 0x0388a7ec, 0x494d8814, 0x49458810, 0x49458810, + 0x418d8810, 0x0308a02a, 0x49918fec, 0x51858814, + 0x51958fe4, 0x00000000, 0x0388a7ec, 0x92730080, + 0x009f033b, 0x5802b814, 0x90400300, 0x001f9802, + 0x00000000, 0xb0000000, 0xb4200016, 0x80170a00, + 0x80070000, 0xb6002001, 0x001fa020, 0xb0040000, + 0xb4200002, 0x80279000, 0xb5000001, 0x80279c00, + 0xac740080, 0x5c22b801, 0x11e1b803, 0x806f001f, + 0x80af001f, 0xb6000407, 0x80cf0280, 0x01ffb0bc, + 0x59e2b80f, 0x01afb80f, 0x01ff90bc, 0xb520ffff, + 0x91ef0020, 0x007f0320, 0x011f90cd, 0xaca30006, + 0x80c7b004, 0x10a5b814, 0x58a1b805, 0x10a5b806, + 0x0099b805, 0x8027b3dc, 0x5841b804, 0x1021b802, + 0x0159b801, 0x8027b3d0, 0x5841b804, 0x1021b802, + 0x0139b801, 0x80170c00, 0x0097b80a, 0xb0090000, + 0xb4200004, 0xb6000002, 0x015f8020, 0x009fe0ca, + 0xb5000004, 0x015fc024, 0xb6000002, 0x015f8020, + 0x009fe0ca, 0x00ffb81b, 0x00000000, 0x00000000, + 0x009f0011, 0x015f0012, 0xb0060000, 0xb4200007, + 0x968a0001, 0xb0140000, 0xb400000d, 0x80870001, + 0x009f2011, 0x954a0002, 0x015f2012, 0xb0060002, + 0xb4200007, 0x968a0002, 0xb0140000, 0xb4000004, + 0x80870001, 0x009f2011, 0x81470000, 0x015f2012, + 0x83640037, 0x00bf2010, 0xb0060000, 0xb4200003, + 0xb0050000, 0xb4200001, 0x836400a1, 0xb0050000, + 0xb4200001, 0x836400ca, 0x00bf0010, 0xb0050000, + 0xb420000a, 0x81df0000, 0x00000000, 0x00000000, + 0x836409e4, 0x836402f6, 0x00000000, 0x8364098c, + 0x81df0004, 0x00000000, 0xb5000009, 0x00bf0010, + 0xb0050001, 0xb4000006, 0x00000000, 0x81df0000, + 0x00000000, 0x00000000, 0x83640981, 0x81df0004, + 0x00ff0325, 0x82870000, 0x81df0000, 0x00000000, + 0x00000000, 0xb6270002, 0x8364fef5, 0x92940001, + 0x81df0004, 0x80070001, 0x801eff70, 0x001f0010, + 0xb0000001, 0xb4000007, 0x001f033b, 0xb0000000, + 0xb4000002, 0x80270000, 0xb5000001, 0x80270001, + 0x003f233b, 0x00ffb81a, 0x00000000, 0x00000000, + 0x027f4001, 0x5e2ab813, 0x96310003, 0x81c70000, + 0x820700ff, 0xb0110000, 0xb4000005, 0x5a21b811, + 0x81c70200, 0x8207000e, 0x69d1b80e, 0x1210b811, + 0x01dfb0cd, 0x5e2cb813, 0x96310003, 0x023f2323, + 0x5e28b813, 0x96310003, 0x023f2322, 0x5e27b813, + 0x96310001, 0x023f2328, 0x5e23b813, 0x96310001, + 0x023f2321, 0x95f30007, 0x01ff2320, 0x920fe004, + 0x0258b810, 0x00000000, 0x1252b811, 0x025f2325, + 0x8167befc, 0x017f6195, 0x021f031c, 0x01df031d, + 0x3010b80f, 0xb4200003, 0x3011b80e, 0xb4200001, + 0xb5000025, 0x80270000, 0x80471000, 0x0017b802, + 0x8057ffff, 0x81df0000, 0x00000000, 0x00000000, + 0xb6002001, 0x001fa021, 0x80270400, 0x80679000, + 0x5c62b803, 0xb6001809, 0x00cfb801, 0x007fb0bc, + 0x5862b803, 0x01afb803, 0x007f90bc, 0x0047b86f, + 0xb0020001, 0xb4c0fffd, 0x90630020, 0x80679c00, + 0x5c62b803, 0xb6001809, 0x00cfb801, 0x007fb0bc, + 0x5862b803, 0x01afb803, 0x007f90bc, 0x0047b86f, + 0xb0020001, 0xb4c0fffd, 0x90630020, 0x81df0004, + 0x01ff231c, 0x023f231d, 0x83970300, 0x82070000, + 0x81df0000, 0x00000000, 0x00000000, 0xb6320001, + 0x039fa030, 0x81df0004, 0x00bf0010, 0x021f0324, + 0xb0100000, 0xb4200001, 0x80a70000, 0xb0050000, + 0xb4200008, 0xb0040000, 0xb4a00002, 0x80a70001, + 0xb5000004, 0x82070000, 0x021f204e, 0xb4000001, + 0x80a70002, 0xb0050001, 0xb4200007, 0x021f004e, + 0xb0100002, 0xb4a00002, 0x80a70002, 0x00ffb81b, + 0x92100001, 0x021f204e, 0x00000000, 0x00ffb81b, + 0x81530000, 0x003fb80a, 0x00000000, 0x00000000, + 0x003fb819, 0x00000000, 0x00000000, 0x81550000, + 0x8384fd63, 0x81470000, 0x015f61ee, 0x015f61ef, + 0x015f23a4, 0x8297050c, 0x82d7ffff, 0x81df0000, + 0x00000000, 0x00000000, 0xb6000501, 0x029fa02a, + 0x81df0004, 0x8167e004, 0x116b0384, 0x0158b80b, + 0x019f0382, 0x015f237b, 0x017f0388, 0x116bb80a, + 0xb00c0008, 0xb4a00003, 0x80a70003, 0x00bf2010, + 0x00ffb81b, 0xb00a0005, 0xb4400003, 0xb00b0006, + 0xb4400001, 0x00ffb81b, 0x80a70004, 0x00bf2010, + 0x00ffb81b, 0x00000000, 0x00000000, 0x00000000, + 0x027f0388, 0x02bf037b, 0x02df0384, 0x02ff03a1, + 0x82970400, 0x8257ffff, 0x82d7ffff, 0x81df0000, + 0x00000000, 0x00000000, 0xb6350003, 0x81550001, + 0x8357ffff, 0x029fa02a, 0x82970414, 0xb6350003, + 0x81550001, 0x83d7ffff, 0x029fa02a, 0x81df0004, + 0x81550001, 0xb00a0001, 0xb4200004, 0x814d0008, + 0x6149b80a, 0x954affff, 0x015f61ee, 0xb0160000, + 0xb4200007, 0x81550001, 0xb00a0001, 0xb4200004, + 0x814d0008, 0x6149b80a, 0x954affff, 0x015f61ef, + 0x81550001, 0xb00a0001, 0xb4200042, 0x82f50001, + 0x02ff23a1, 0xb0170001, 0xb4200034, 0x82970428, + 0x81df0000, 0x00000000, 0x00000000, 0xb6350003, + 0x81550001, 0x00000000, 0x029fa02a, 0x81df0004, + 0x82970428, 0x81470000, 0x017f8034, 0xb00b0001, + 0xb4000004, 0x914a0001, 0x300ab815, 0xb480fffa, + 0xb5000001, 0x015f23a5, 0x81670000, 0xb0160002, + 0xb4200002, 0x81750001, 0x00000000, 0x017f233a, + 0x81550004, 0xadaa000c, 0x015f23a2, 0x81750004, + 0x916b0003, 0x017f23a3, 0x91ad0025, 0x01bf23a6, + 0xadab000c, 0x81e70000, 0x91ad0025, 0x01bf23a7, + 0x920a0001, 0x05abb810, 0xb00d0000, 0xb4000015, + 0x81df0000, 0x00000000, 0x00000000, 0xb62d0004, + 0x81b50001, 0x65b0b80d, 0x19efb80d, 0x92100001, + 0x81df0004, 0x01ffb0be, 0xb500000a, 0x81a70000, + 0x82970428, 0x81df0000, 0x00000000, 0x00000000, + 0xb6350001, 0x029fa02d, 0x81df0004, 0x01bf233a, + 0x01bf23a5, 0x82070000, 0x82270000, 0x82170428, + 0x81df0000, 0x00000000, 0x00000000, 0xb635003a, + 0x01bf8030, 0xb00d0001, 0xb4200036, 0x81d50001, + 0x65b1b80e, 0x1a10b80d, 0xb00e0001, 0xb4200031, + 0x81b50002, 0xadad0003, 0xae510048, 0x91cd000f, + 0x91320868, 0x015f03a2, 0xad4a0004, 0x92920700, + 0x1189b80a, 0x0297b80c, 0x1194b80a, 0x0317b80c, + 0x01ff90be, 0x015f03a2, 0x017f03a3, 0x064bb80a, + 0x0107b80a, 0xb0120000, 0xb400001e, 0xb632001d, + 0x6928b80f, 0x95290001, 0xb0090000, 0xb420000e, + 0x81350004, 0x1129b80d, 0x029fa029, 0x824d0004, + 0x5a48b812, 0x5e48b812, 0x3009b80e, 0xb4200002, + 0x5e41b812, 0xb500000d, 0x5e42b812, 0x81330040, + 0x1a52b809, 0xb5000009, 0x0127b854, 0x85290004, + 0x0397b809, 0x0287b858, 0x86940004, 0x013f803c, + 0x0397b814, 0x029fa029, 0x025f803c, 0x031fa032, + 0x91080001, 0x92310001, 0x81df0004, 0x015f03a2, + 0x017f03a3, 0x013f033a, 0xb0090001, 0xb4200023, + 0x95300002, 0x95900001, 0x1929b80c, 0xb0090000, + 0xb400001e, 0x064bb80a, 0x0107b80a, 0x81df0000, + 0x00000000, 0x00000000, 0xb6320017, 0x6928b80f, + 0x95290001, 0xb0090000, 0xb4200002, 0x81350001, + 0x013f23f8, 0x81a70700, 0x91ad0048, 0x5982b808, + 0x11adb80c, 0x0397b80d, 0x013f03f8, 0xb0090001, + 0xb4200005, 0x019f801c, 0x0196b80c, 0x81b3ff80, + 0x418cb80d, 0xb5000002, 0x019f801c, 0x0196b80c, + 0x039fa00c, 0x91080001, 0x81df0004, 0xb0160002, + 0xb420001e, 0xb0170001, 0xb4200008, 0xb00a0000, + 0xb4200002, 0x81270002, 0xb5000005, 0xb00a0002, + 0xb4400002, 0x81270003, 0xb5000001, 0x81270004, + 0x013f23a9, 0x81950001, 0xb00c0001, 0xb4200011, + 0x81a70000, 0x8397043c, 0x81df0000, 0x00000000, + 0x00000000, 0xb6290006, 0x81150001, 0x039fa028, + 0xb0080001, 0xb4200001, 0x81a70001, 0x00000000, + 0x81df0004, 0x01bf23a8, 0xb5000002, 0x81a70000, + 0x01bf23a8, 0xb0170001, 0xb4200001, 0x81b50002, + 0x82970c20, 0x81df0000, 0x00000000, 0x00000000, + 0xb6350003, 0x81550002, 0x00000000, 0x029fa02a, + 0x81df0004, 0xb0130001, 0xb4200001, 0x81150001, + 0x81c70000, 0x81df0000, 0x00000000, 0x00000000, + 0xb6350014, 0x922e0c20, 0x015ff011, 0xb00a0000, + 0xb400000f, 0x922e0428, 0x015ff011, 0xb00a0001, + 0xb4200005, 0x922e044c, 0x0297b811, 0x015f03a6, + 0x029fa00a, 0xb5000006, 0x81550006, 0xad4a0003, + 0x922e044c, 0x0297b811, 0x914a0049, 0x029fa00a, + 0x91ce0004, 0x81df0004, 0xb0170001, 0xb4200022, + 0xb00d0000, 0xb4000020, 0x852d0001, 0x81470001, + 0x6549b80a, 0xad6a0003, 0x019f03a7, 0x058c03a6, + 0x81270000, 0xb00b0000, 0xb4000005, 0x300cb80b, + 0xb4800003, 0x058cb80b, 0x91290001, 0xb500fffb, + 0x81750004, 0x5961b80b, 0x839704ec, 0x0187b860, + 0x039fa02c, 0x039fa02a, 0x039fa029, 0x039fa02b, + 0xb0090000, 0xb4000007, 0x81df0000, 0x00000000, + 0x00000000, 0xb6290003, 0x81550007, 0x00000000, + 0x00000000, 0x81df0004, 0x81c70000, 0x81df0000, + 0x00000000, 0x00000000, 0xb635002e, 0x922e0c20, + 0x01fff011, 0xb00f0000, 0xb4000029, 0x852f0001, + 0x81470001, 0x6549b80a, 0xad6a0003, 0x922e044c, + 0x025fd811, 0x86520001, 0x0227b812, 0x81270000, + 0xb00b0000, 0xb4000005, 0x3012b80b, 0xb4800003, + 0x0652b80b, 0x91290001, 0xb500fffb, 0x2e09b80b, + 0x00000000, 0x3010b811, 0xb4600001, 0x91290001, + 0xae4e0004, 0x82150004, 0x9232049c, 0x0297b811, + 0x0187b860, 0x029fa02c, 0x029fa02a, 0x029fa029, + 0x029fa030, 0xb0090000, 0xb4000004, 0xb6290003, + 0x81550007, 0x00000000, 0x00000000, 0x82270460, + 0x1231b80e, 0x0217b811, 0x81550002, 0x021fa00a, + 0x91ce0004, 0x81df0004, 0xb0130001, 0xb420000c, + 0xb0080000, 0xb400000a, 0x81550004, 0x839704fc, + 0x0167b860, 0x039fa02b, 0x81670001, 0x039fa02b, + 0x8175000e, 0x81670002, 0x039fa02b, 0x039fa02a, + 0x81150001, 0xb0080001, 0xb420000a, 0x8135000b, + 0x5d2923aa, 0x95490180, 0x5d4723ab, 0x95490060, + 0x5d4523ac, 0x95490018, 0x5d4323ad, 0x95490007, + 0x015f23ae, 0x81350001, 0xb0090001, 0xb420001b, + 0x81350006, 0x013f23af, 0xb0170001, 0xb4200005, + 0x81550004, 0x00000000, 0x015f23b0, 0x81550003, + 0x015f23b1, 0x82970474, 0x83170488, 0x81df0000, + 0x00000000, 0x00000000, 0xb6350004, 0x81550007, + 0x5e83a02a, 0x954a0007, 0x031fa02a, 0x81df0004, + 0xb0130001, 0xb4200005, 0x81750004, 0x00000000, + 0x017f23b2, 0x81750003, 0x017f23b3, 0xb0170001, + 0xb420000b, 0x81b50001, 0xb00d0001, 0xb4200008, + 0x81d50003, 0x59c8b80e, 0x91ce0300, 0x01df61da, + 0x81d50003, 0x59c8b80e, 0x91ce0300, 0x01df61db, + 0x81550001, 0xb00a0001, 0xb4200057, 0xb0170001, + 0xb4200001, 0x81550002, 0x82470000, 0x82270000, + 0x81df0000, 0x00000000, 0x00000000, 0xb6350004, + 0x81750002, 0x6571b80b, 0x92310002, 0x1a52b80b, + 0x81df0004, 0xb0170001, 0xb420001b, 0xb00a0001, + 0xb4200015, 0x81150003, 0x91080001, 0x011f23a4, + 0x829709d0, 0x831709f0, 0x83970060, 0x81df0000, + 0x00000000, 0x00000000, 0xb6280009, 0x81750005, + 0x00000000, 0x029fa02b, 0x81750004, 0x00000000, + 0x031fa02b, 0x81750003, 0x00000000, 0x039fa02b, + 0x81df0004, 0xb5000004, 0xb00a0002, 0xb4800002, + 0x81070000, 0x011f23a4, 0x82270000, 0x81270000, + 0x81df0000, 0x00000000, 0x00000000, 0xb6350025, + 0x6a11b812, 0x92310002, 0x96100003, 0xb0100001, + 0xb4200018, 0xada90020, 0x81750003, 0x920d0520, + 0x0217b810, 0x920d05c0, 0x0297b810, 0x920d0660, + 0x0317b810, 0x5942b809, 0x920a050c, 0x0397b810, + 0x916b0001, 0x039fa02b, 0xb62b0009, 0x81750005, + 0x00000000, 0x021fa02b, 0x81750004, 0x00000000, + 0x029fa02b, 0x81750003, 0x00000000, 0x031fa02b, + 0xb5000007, 0xb0100002, 0xb4800005, 0x59a2b809, + 0x91ad050c, 0x0397b80d, 0x82070000, 0x039fa010, + 0x91290001, 0x81df0004, 0x81550001, 0xb00a0001, + 0xb420000a, 0x81550009, 0xb00a0000, 0xb4000007, + 0x81df0000, 0x00000000, 0x00000000, 0xb62a0003, + 0x82150008, 0x00000000, 0x00000000, 0x81df0004, + 0xb00a0100, 0xb4a0000b, 0x954aff00, 0x81df0000, + 0x00000000, 0x00000000, 0xb6008003, 0x82150010, + 0x00000000, 0x00000000, 0x81df0004, 0x854a0100, + 0xb4e0fff6, 0x00ffb81b, 0x00000000, 0x00000000, + 0x81070000, 0x011f61dc, 0x011f61de, 0x011f61e0, + 0x011f03aa, 0x9108e0f4, 0x0138b808, 0x011f03ab, + 0x013f61ac, 0x9108e0f0, 0x0138b808, 0x011f03ac, + 0x013f61ad, 0x5901b808, 0x9108e0f8, 0x0139b808, + 0x011f03ad, 0x013f61ae, 0x5901b808, 0x9108e100, + 0x0139b808, 0x011f03ae, 0x013f61b0, 0x5901b808, + 0x9108e108, 0x0179b808, 0x013f03af, 0x017f61b1, + 0x02bf037b, 0x82970474, 0xb6350002, 0x015f8034, + 0x1929b80a, 0x011f03a1, 0xb0080001, 0xb4200002, + 0x015f03b0, 0x1929b80a, 0x019f0388, 0xb00c0001, + 0xb4200002, 0x015f03b2, 0x1929b80a, 0x013f61b3, + 0x015f03a8, 0xb00a0001, 0xb420003a, 0x81a70000, + 0x01bf237a, 0x83840056, 0x806f001f, 0x80af001f, + 0x80270300, 0x8067a800, 0x5c62b803, 0xb600080a, + 0x00cfb801, 0x007fb0bc, 0x5862b803, 0x01afb803, + 0x007f90bc, 0x0047b86f, 0xb0020001, 0xb4c0fffd, + 0x90210020, 0x90630020, 0x81a70001, 0x01bf237a, + 0x83840043, 0x838403ce, 0x81a70000, 0x01bf237a, + 0x82470400, 0x01bff012, 0x01bf23fa, 0x83840420, + 0x83840497, 0x83840546, 0x8384059d, 0x806f001f, + 0x80af001f, 0x80270300, 0x8067ac00, 0x5c62b803, + 0xb600080a, 0x00cfb801, 0x007fb0bc, 0x5862b803, + 0x01cfb803, 0x007f90bc, 0x0047b86f, 0xb0020001, + 0xb4c0fffd, 0x90210020, 0x90630020, 0x81a70001, + 0x01bf237a, 0x82470404, 0x015ff012, 0x015f23fa, + 0x83840407, 0x8384047e, 0x8384052d, 0x83840584, + 0xb5000011, 0x81a70000, 0x01bf237a, 0xb635000e, + 0x8384001b, 0x01bf037a, 0xad4d0004, 0x00000000, + 0x914a0400, 0x01bff00a, 0x01bf23fa, 0x838403f8, + 0x8384046f, 0x8384051e, 0x83840575, 0x01df037a, + 0x91ce0001, 0x01df237a, 0x019f0388, 0xb00c0001, + 0xb4200009, 0x02bf037b, 0x02bf237a, 0x838400e8, + 0x82470000, 0x025f23fa, 0x838403e9, 0x83840460, + 0x8384050f, 0x83840566, 0x00ffb81b, 0x00000000, + 0x80770000, 0x80f70000, 0x81770000, 0x81f70000, + 0x82770000, 0x82f70000, 0x83770000, 0x83f70000, + 0x8057ffff, 0x80d7ffff, 0x8157ffff, 0x81d7ffff, + 0x8257ffff, 0x82d7ffff, 0x8357ffff, 0x83d7ffff, + 0x017f037a, 0x5a42b80b, 0x01bf03a8, 0xb00d0001, + 0xb4200004, 0x011f9118, 0x013f9119, 0x7929b808, + 0xb5000002, 0x91b20460, 0x013ff00d, 0x91b20340, + 0x0297b80d, 0x00000000, 0x029fa009, 0x01df0384, + 0xb00e0000, 0xb4200005, 0xb00b0001, 0xb4200003, + 0x009f90c6, 0x00bf0391, 0xb5000002, 0x009f90cf, + 0x00bf0389, 0x83a40142, 0x81870000, 0x019f61b5, + 0x019f61b4, 0x5a02b80b, 0x9190044c, 0x01dfd80c, + 0x01df61b6, 0x91900488, 0x01dff00c, 0x59c1b80e, + 0x918ee118, 0x01d9b80c, 0x019f03af, 0x01df61af, + 0x858c000f, 0x5986b80c, 0x91d00474, 0x01bff00e, + 0x59c2b80d, 0x11cc61b2, 0x81870000, 0x019f61b8, + 0x91900414, 0x01dfd80c, 0x01df61b7, 0xadab0010, + 0x00000000, 0x908d049c, 0x83a40191, 0xadcb0020, + 0x5982b80b, 0x908e0520, 0x90ae05c0, 0x90ce0660, + 0x928c050c, 0x00ff9814, 0x83a40169, 0x83a401b8, + 0x017f037a, 0x59c2b80b, 0x918e0428, 0x01fff00c, + 0xb00f0001, 0xb4200081, 0x023f03a5, 0x3011b80b, + 0xb420000f, 0x01c7b860, 0x01dfb0fa, 0x01df41dc, + 0x01df61e8, 0x01df41de, 0x01df61ea, 0x01df41e0, + 0x01df61ec, 0x01df41dd, 0x01df61e9, 0x01df41df, + 0x01df61eb, 0x01df41e1, 0x01df61ed, 0xb5000024, + 0x01c7b860, 0x01dfb0f9, 0x01df41dc, 0x01df61e2, + 0x01df41de, 0x01df61e4, 0x01df41e0, 0x01df61e6, + 0x01df41dd, 0x01df61e3, 0x01df41df, 0x01df61e5, + 0x01df41e1, 0x01df61e7, 0x803f0000, 0x00000000, + 0x00000000, 0x01df90fa, 0x003fb80e, 0x00000000, + 0x00000000, 0x81d50000, 0x00000000, 0x00000000, + 0x01df41e8, 0x01df61dc, 0x01df41ea, 0x01df61de, + 0x01df41ec, 0x01df61e0, 0x01df41e9, 0x01df61dd, + 0x01df41eb, 0x01df61df, 0x01df41ed, 0x01df61e1, + 0x029f03a6, 0x029f236a, 0x029f03a7, 0x029f236c, + 0x027f03a2, 0x92b3e128, 0x0298b815, 0x019f03b0, + 0x029f2368, 0x5982b80c, 0x01df03af, 0x85ce000f, + 0x59c6b80e, 0x11cc61b2, 0x82a70001, 0x02bf61b8, + 0x82a70000, 0x02bf61b9, 0x029f41da, 0x029f61ba, + 0x029f41db, 0x029f61bb, 0x019f03b1, 0x5981b80c, + 0x918ce118, 0x0299b80c, 0xad8b0048, 0x029f61af, + 0x59a2b813, 0x118cb80d, 0x928c0868, 0x029fb0fb, + 0x928c0700, 0x029fb0fc, 0x019f41bc, 0x918c0003, + 0x019f61bc, 0x5a02b80b, 0x91900414, 0x029fd80c, + 0x029f236e, 0x808704ec, 0x83a40121, 0x808709d0, + 0x80a709f0, 0x80c70060, 0x00ff03a4, 0x83a400fc, + 0x83a4014b, 0x021f037a, 0x019f03a5, 0x300cb810, + 0xb4000016, 0x803f0000, 0x00000000, 0x00000000, + 0x01df90f9, 0x003fb80e, 0x00000000, 0x00000000, + 0x81d50000, 0x00000000, 0x00000000, 0x01df41e2, + 0x01df61dc, 0x01df41e4, 0x01df61de, 0x01df41e6, + 0x01df61e0, 0x01df41e3, 0x01df61dd, 0x01df41e5, + 0x01df61df, 0x01df41e7, 0x01df61e1, 0x029f41b6, + 0xa6d40100, 0xaeb40004, 0x81870000, 0x92b50c00, + 0x0397b815, 0xb6360001, 0x039fa02c, 0x00ffb81c, + 0x009f90cf, 0x00bf0389, 0x019f037a, 0x5982b80c, + 0x918c0340, 0x0397b80c, 0x81870000, 0x039fa00c, + 0x83a40083, 0x81870000, 0x019f61b5, 0x019f61b4, + 0x81870007, 0x019f61b6, 0x019f03b3, 0x5981b80c, + 0x918ce118, 0x01b9b80c, 0x019f03af, 0x01bf61af, + 0x858c000f, 0x5986b80c, 0x01bf03b2, 0x59a2b80d, + 0x118cb80d, 0x019f61b2, 0x81870000, 0x019f61b7, + 0x019f61b8, 0x808704fc, 0x83a400d9, 0x80870000, + 0x80a70000, 0x80c70000, 0x80e70000, 0x83a400b4, + 0x83a40103, 0x81470000, 0x81e70c1c, 0x0397b80f, + 0xb600f901, 0x039fa02a, 0x00ffb81c, 0x00000000, + 0x82270000, 0x023f2011, 0x0227b860, 0x023fb0ff, + 0x02bf9006, 0x92350028, 0x8213001f, 0x9210e000, + 0x3011b810, 0xb4800001, 0x86312000, 0x021f4193, + 0x5a01b810, 0x86100028, 0x83a4fa2e, 0x82270000, + 0x003fb811, 0x02bf9006, 0x5aa3b815, 0x82338000, + 0x1a31b815, 0x003fb811, 0x8067e950, 0x5c62b803, + 0x81f50000, 0x80270400, 0x81df0000, 0x00000000, + 0x00000000, 0xb6000409, 0x814fffc0, 0x00cfb801, + 0x007fb0bc, 0x5862b803, 0x01cfb803, 0x007f90bc, + 0xb520ffff, 0x90210020, 0x90630020, 0x81df0004, + 0x82870000, 0x81f50010, 0x019f4193, 0x5d61b80c, + 0x5d43b80c, 0x114ab80b, 0x0187b80a, 0x960cff00, + 0x92100100, 0x858c0001, 0x81df0000, 0x00000000, + 0x00000000, 0xb62c000c, 0x81f50010, 0x5e28b80f, + 0xb6000209, 0x5a48b814, 0x9652ff00, 0x5e68b814, + 0x5981b813, 0x918c1000, 0x01dfd80c, 0x2252b811, + 0x2292b80e, 0x962f00ff, 0x81df0004, 0x81870000, + 0x86100100, 0xb4e0ffec, 0xb00a0000, 0xb4000009, + 0x81670000, 0xb0140000, 0xb4000001, 0x81670001, + 0x017f2012, 0x258a4193, 0x918c0001, 0x81470000, + 0xb500ffde, 0x81670000, 0xb0140000, 0xb4000001, + 0x81670002, 0x116b0012, 0x803f0000, 0x00000000, + 0x00000000, 0x003fb811, 0x00000000, 0x00000000, + 0x81f50000, 0x017f2012, 0x00ffb81a, 0x00000000, + 0x61f4b804, 0x91ef0001, 0x8233003f, 0x9a31ffff, + 0x5a02b804, 0x1610b811, 0x92510001, 0x1a10b812, + 0x029f03fb, 0xb0140001, 0xb4200012, 0x5a21b805, + 0x92b1e910, 0x0299b815, 0x5a22b805, 0x5a90b814, + 0x6290b814, 0x92b1e890, 0x11efb814, 0x029bb815, + 0x8233ff80, 0x3011b814, 0xb4000006, 0x4294b811, + 0x00000000, 0x0288b814, 0x4210b814, 0x00000000, + 0x0208b810, 0x029f9003, 0x82f3007f, 0x9af7ffff, + 0x3017b814, 0xb4000003, 0x4210b814, 0x00000000, + 0x0208b810, 0x82270000, 0x02c7b810, 0xb0160000, + 0xb400000a, 0x1676b812, 0x3013b812, 0xb4000003, + 0x5ac1b816, 0x92310001, 0xb500fffa, 0x81d3ff80, + 0x3010b80e, 0xb4200001, 0x1ad6b80e, 0x05efb811, + 0x027f037a, 0x5a62b813, 0x92730340, 0x0397b813, + 0x023fd813, 0x02dfb0fd, 0x5a30b811, 0x6230b811, + 0x0631b80f, 0x3010b812, 0xb4200001, 0x92310001, + 0x82470000, 0xb0110000, 0xb4800004, 0x82470003, + 0xb0110003, 0xb4400001, 0x0247b811, 0x039fa012, + 0x124f61bc, 0x00ffb81d, 0x00000000, 0x00000000, + 0x83970a10, 0x82070000, 0xb6003201, 0x039fa030, + 0xb0070000, 0xb4000019, 0x029f41b4, 0x0297b804, + 0x0317b805, 0x0397b806, 0xb6270014, 0x12948034, + 0x01df8038, 0xb00e0000, 0xb4a0000e, 0x02bf803c, + 0x5a02b814, 0x91b00a10, 0x0217b80d, 0xb62e0008, + 0x96150003, 0x91f00001, 0xadef0080, 0xb0150004, + 0xb4600001, 0x85ef0280, 0x021fa02f, 0x92940001, + 0xb5000001, 0x021f803c, 0x00000000, 0x00ffb81d, + 0x0397b804, 0x021f036a, 0x027f803c, 0x029f803c, + 0x02bf803c, 0x02df803c, 0x5a22b810, 0x92311000, + 0x0397b811, 0xb0100000, 0xb4200001, 0x039fa036, + 0xb0150000, 0xb4000021, 0x0227b860, 0x023fb0ff, + 0xb520ffff, 0x803f0000, 0x82138000, 0x1a10b813, + 0x003fb810, 0x00000000, 0x00000000, 0x82150000, + 0x00000000, 0xb635000d, 0x82550007, 0x5a42b812, + 0x9212e4b8, 0x025bb810, 0x8227000c, 0xb6000307, + 0x68d1b812, 0x94c6000f, 0x84c60002, 0x12d6b806, + 0xb6340001, 0x039fa036, 0x86310004, 0x803f0000, + 0x82138000, 0x023f90ff, 0x1a31b810, 0x003fb811, + 0x00000000, 0x00000000, 0x82150000, 0x00ffb81d, + 0x00ff41b5, 0x011f41b4, 0x019f41af, 0x01bf41ae, + 0x01df41ba, 0x01ff41bb, 0x82070000, 0x023f0380, + 0x82470000, 0xae310032, 0x029f41b3, 0x5862b807, + 0x90431000, 0x81970ad8, 0x0217b802, 0x90430c00, + 0x0297b802, 0x0317b802, 0x912802a4, 0x007ff009, + 0x58478030, 0x792341b6, 0x0529b807, 0x019fa029, + 0xb0080014, 0xb4800011, 0xa5420c00, 0x031fa02a, + 0x84690001, 0xb4a00011, 0xb623000b, 0x58678030, + 0xa4030c00, 0x031fa020, 0x044ab800, 0x0056b802, + 0x5c41b802, 0xf84200ff, 0x90620100, 0x005ff003, + 0x7d40b80a, 0x114ab802, 0xb5000004, 0xa5420c00, + 0x58478010, 0xa5620c00, 0x031fa02a, 0xb0080016, + 0xb4400043, 0xb0080013, 0xb440002c, 0xb0080006, + 0xb4400024, 0xb0080005, 0xb4400014, 0xb0080002, + 0xb4400006, 0x80440030, 0x015f619c, 0x05cab80c, + 0x05eab80d, 0x066eb810, 0xb500003c, 0x8044002a, + 0x300a419c, 0xb4800001, 0x82470001, 0x015f619c, + 0xb0120001, 0xb4200001, 0xb500001a, 0x05cab80c, + 0x05eab80d, 0x066eb810, 0xb5000030, 0x001f41b6, + 0xb0000007, 0xb4000001, 0x8044001b, 0x300a419c, + 0xb4800001, 0x82470001, 0xb0120001, 0xb4200001, + 0xb500000c, 0x05cab80c, 0x05eab80d, 0x066eb810, + 0xb5000022, 0x80440010, 0x840b0100, 0x300ab800, + 0xb4200001, 0x86100040, 0xb5000002, 0x86100080, + 0xfe100000, 0x046e41ad, 0x042ab80c, 0x7dc1b803, + 0x044f41ac, 0x042ab80d, 0x7de1b802, 0x046eb810, + 0x7e6fb803, 0xb5000011, 0x840b0100, 0x3000b80a, + 0xb4200002, 0x82070180, 0x00ffb802, 0x300ab80b, + 0xb4a00002, 0x86100040, 0xfe100000, 0x00ffb802, + 0x046e41ad, 0x042ab80c, 0x7dc1b803, 0x044f41ac, + 0x042ab80d, 0x7de1b802, 0x7e6eb80f, 0x380a41b0, + 0xb4600003, 0x242a41b0, 0x5c22b801, 0x1273b801, + 0xb0140000, 0xb4200002, 0x80071fe0, 0xb5000016, + 0x1011b808, 0x5801b800, 0x9020e26c, 0x0079b801, + 0x5842b808, 0x90420a10, 0x7c03b813, 0x003f9802, + 0x1000b801, 0x003f41b2, 0x5830b801, 0x6030b801, + 0x0400b801, 0x003f41b1, 0x5830b801, 0x6030b801, + 0x0400b801, 0xfc000000, 0xf8001fe0, 0x94001fe0, + 0x100041b1, 0x9400ffff, 0x8067003f, 0xb6290008, + 0x005f8014, 0x0442b800, 0x9442ffff, 0x5850b802, + 0x6050b802, 0xfc420000, 0x5c45b802, 0x7a82a023, + 0x10e7b809, 0x91080001, 0x300741b6, 0xb420ff6a, + 0x019f61af, 0x01bf61ae, 0x01df61ba, 0x01ff61bb, + 0x00ff41b5, 0x011f41b4, 0x019f41b8, 0x01bf41b7, + 0x01df41dd, 0x01ff41df, 0x021f41e1, 0x027f90fd, + 0x029f41bc, 0x02ff41dc, 0x031f41de, 0x033f41e0, + 0x5822b807, 0x91210c00, 0x0117b809, 0x81970ad8, + 0x91211000, 0x0217b809, 0x91210c00, 0x0317b809, + 0x80170ba0, 0x013f802c, 0xb629005f, 0x003f8038, + 0xb001000e, 0xb440001e, 0xb001000c, 0xb4400054, + 0xb001000a, 0xb4400043, 0xb0010007, 0xb440003c, + 0xb0010005, 0xb440002b, 0xb0010000, 0xb440001a, + 0xb00d0001, 0xb4200010, 0x005f418f, 0xac42bb75, + 0x8073005a, 0x9442ffff, 0x005f618f, 0x95628000, + 0x5848b802, 0xb00b8000, 0xb4200002, 0x8173ff00, + 0x1842b80b, 0x9863827a, 0x4043b802, 0x00000000, + 0x0048b802, 0xb500003f, 0x80470000, 0xb500003d, + 0x8401000f, 0x5c22b800, 0x902102d8, 0x001ff001, + 0x004db800, 0xb5000037, 0x86f70001, 0xb4600005, + 0x80750005, 0x5862b803, 0x9043e44c, 0x01d9b802, + 0x82e70002, 0x5c4cb80e, 0x9462000f, 0x5862b803, + 0x90630200, 0x005f9803, 0x59c4b80e, 0x95ceffff, + 0xb5000028, 0x87180001, 0xb4600005, 0x80750007, + 0x5862b803, 0x9043e4b8, 0x01f9b802, 0x83070002, + 0x5c4cb80f, 0x9462000f, 0x5862b803, 0x9063020c, + 0x005f9803, 0x59e4b80f, 0x95efffff, 0xb5000019, + 0x80750003, 0x5862b803, 0x90630220, 0x005f9803, + 0xb5000014, 0x87390001, 0xb4600005, 0x80750007, + 0x5862b803, 0x9043e6ac, 0x0219b802, 0x83270001, + 0x5c4cb810, 0x9462000f, 0x5862b803, 0x9063023c, + 0x005f9803, 0x5a04b810, 0x9610ffff, 0xb5000005, + 0x80750004, 0x5862b803, 0x90630268, 0x005f9803, + 0x00000000, 0x001fa022, 0x80170ba0, 0xb00c0001, + 0xb4200035, 0x023f90fb, 0x007f9811, 0x025f90fc, + 0x06d4b803, 0x007f9812, 0x4083b813, 0x00000000, + 0x0088b804, 0xb629002b, 0x24368030, 0x9421ffff, + 0x5830b801, 0x6030b801, 0x40448020, 0xb0010020, + 0xb4800003, 0x80470000, 0x80670000, 0xb500000e, + 0xb0010000, 0xb4a00004, 0x82b30080, 0x6aa1b815, + 0x4042b815, 0xb5000008, 0x6c41b802, 0x82a70017, + 0x12b5b801, 0x6875b803, 0x1842b803, 0x00000000, + 0x00000000, 0x00000000, 0x0108a022, 0x007f41b9, + 0x90630001, 0x007f61b9, 0xb003000c, 0xb420000c, + 0x92310004, 0x023fb0fb, 0x007f9811, 0x92520004, + 0x06d4b803, 0x025fb0fc, 0x007f9812, 0x80470000, + 0x4083b813, 0x00000000, 0x0088b804, 0x005f61b9, + 0x00000000, 0xb500001a, 0xb6290019, 0x24348030, + 0x9421ffff, 0x5830b801, 0x6030b801, 0x40538020, + 0xb0010020, 0xb4800003, 0x80470000, 0x80670000, + 0xb500000e, 0xb0010000, 0xb4a00004, 0x82b30080, + 0x6aa1b815, 0x4042b815, 0xb5000008, 0x6c41b802, + 0x82a70017, 0x12b5b801, 0x6875b803, 0x1842b803, + 0x00000000, 0x00000000, 0x00000000, 0x0108a022, + 0x10e7b809, 0x91080001, 0x300741b6, 0xb420ff48, + 0x00ff61b5, 0x011f61b4, 0x01df61dd, 0x01ff61df, + 0x021f61e1, 0x02ff61dc, 0x031f61de, 0x033f61e0, + 0x00ffb81d, 0x00000000, 0x00000000, 0x00000000, + 0x8057ffff, 0x80d7ffff, 0x8157ffff, 0x81d7ffff, + 0x8257ffff, 0x808f0000, 0x003f9113, 0x005f9114, + 0x7141b802, 0x80cf0700, 0x8027b064, 0x5c22b801, + 0x003fb0bc, 0x5822b801, 0x01cfb801, 0x003f90bc, + 0xb520ffff, 0x80cf0704, 0x8027b06c, 0x5c22b801, + 0x003fb0bc, 0x5822b801, 0x01cfb801, 0x003f90bc, + 0xb520ffff, 0x81e7043c, 0x82071c00, 0x82271c10, + 0x019f03a9, 0x806f001f, 0x80af001f, 0x80270400, + 0x8067a800, 0x5c62b803, 0xb6000808, 0x00cfb801, + 0x007fb0bc, 0x5862b803, 0x01cfb803, 0x007f90bc, + 0xb520ffff, 0x90210020, 0x90630020, 0x81971000, + 0x82170c00, 0xb6000004, 0x003f800c, 0x005f8010, + 0x021fa021, 0x019fa022, 0x00bfd810, 0x003fd811, + 0x70c1b80a, 0x001f980f, 0x91ef0004, 0x92100002, + 0x92310002, 0x5822b805, 0x90411000, 0x0197b802, + 0x90410c00, 0x0217b802, 0x0466b805, 0xb0000000, + 0xb4000005, 0xb6230004, 0x003f8010, 0x005f800c, + 0x1201a022, 0x0581a022, 0x858c0001, 0xb4e0ffea, + 0x80270400, 0x8067ac00, 0x5c62b803, 0xb6000808, + 0x00cfb801, 0x007fb0bc, 0x5862b803, 0x01afb803, + 0x007f90bc, 0xb520ffff, 0x90210020, 0x90630020, + 0x00ffb81c, 0x00000000, 0x00000000, 0x00000000, + 0x808f0000, 0x806f001f, 0x80af001f, 0x003f037a, + 0xb0010000, 0xb4400030, 0x81a7b7fc, 0x5da2b80d, + 0x80670500, 0xb6000208, 0x00cfb803, 0x01bfb0bc, + 0x59a2b80d, 0x01cfb80d, 0x01bf90bc, 0xb520ffff, + 0x90630020, 0x91ad0020, 0x81c7b8fc, 0x5dc2b80e, + 0x80670540, 0xb6000208, 0x00cfb803, 0x01dfb0bc, + 0x59c2b80e, 0x01cfb80e, 0x01df90bc, 0xb520ffff, + 0x90630020, 0x91ce0020, 0x81a7b3fc, 0x5da2b80d, + 0x80670600, 0xb6000408, 0x00cfb803, 0x01bfb0bc, + 0x59a2b80d, 0x01cfb80d, 0x01bf90bc, 0xb520ffff, + 0x90630020, 0x91ad0020, 0x81c7b5fc, 0x5dc2b80e, + 0x80670680, 0xb6000408, 0x00cfb803, 0x01dfb0bc, + 0x59c2b80e, 0x01cfb80e, 0x01df90bc, 0xb520ffff, + 0x90630020, 0x91ce0020, 0x005f03fa, 0xb0020000, + 0xb4000024, 0x8057ffff, 0x80d7ffff, 0x8157ffff, + 0x81d7ffff, 0x8257ffff, 0x82d7ffff, 0x8357ffff, + 0x83d7ffff, 0x83971300, 0x83171200, 0x82971100, + 0x82171000, 0x81170c00, 0x81970ff8, 0x80171400, + 0x80971500, 0x005f802c, 0x001f8028, 0xb6004010, + 0x41028000, 0x51008004, 0x007f876c, 0x0208a028, + 0x41008000, 0x49028004, 0x003f8068, 0x0388a028, + 0x41038000, 0x51018004, 0x005f802c, 0x0288a028, + 0x41018020, 0x49038024, 0x001f8028, 0x0308a028, + 0x00ffb81c, 0x83d7ffff, 0x8357ffff, 0x82d7ffff, + 0x8257ffff, 0x8157ffff, 0x81d7ffff, 0x8057ffff, + 0x80d7ffff, 0x82971200, 0x82171000, 0x81170c00, + 0x81970ffc, 0x83171800, 0x83971a00, 0x83370000, + 0x83b70000, 0x81370008, 0x81b7fff8, 0x4119880c, + 0xb6008006, 0x511d8808, 0x41498838, 0x0208a028, + 0x494d883c, 0x4119880c, 0x0288a02a, 0x00ffb81c, + 0x82670000, 0x82a70000, 0x003f037a, 0xb0010000, + 0xb4400018, 0x81a7bdfc, 0x5da2b80d, 0x80670580, + 0xb6000208, 0x00cfb803, 0x01bfb0bc, 0x59a2b80d, + 0x01cfb80d, 0x01bf90bc, 0xb520ffff, 0x90630020, + 0x91ad0020, 0x81a7eb70, 0x5da2b80d, 0x806705c0, + 0xb6000208, 0x00cfb803, 0x01bfb0bc, 0x59a2b80d, + 0x01cfb80d, 0x01bf90bc, 0xb520ffff, 0x90630020, + 0x91ad0020, 0x02bf03fa, 0x808f0000, 0xb0150000, + 0xb4000006, 0x81470040, 0x81670003, 0x81870002, + 0x81a71000, 0x81c71300, 0xb5000005, 0x81470080, + 0x81670004, 0x81870001, 0x81a71000, 0x81c71200, + 0x0017b80d, 0x0097b80e, 0x108db80a, 0x0117b804, + 0x108eb80a, 0x0197b804, 0x5841b80a, 0x108db802, + 0x0217b804, 0x108eb802, 0x0297b804, 0x106ab802, + 0x108db803, 0x0317b804, 0x108eb803, 0x0397b804, + 0x5ea2b80a, 0xb6350020, 0x001f8000, 0x003f8008, + 0x005f8004, 0x007f800c, 0x10c08010, 0x10a18018, + 0x10828014, 0x10e3801c, 0x1246b805, 0x0686b805, + 0x10c4b807, 0x0484b807, 0x80e70000, 0x80a70000, + 0x0008a032, 0x0108a034, 0x0088a026, 0x0188a024, + 0x04c08010, 0x04a18018, 0x04828014, 0x04e3801c, + 0x0646b807, 0x1286b807, 0x10c4b805, 0x0484b805, + 0x80e70000, 0x80a70000, 0x0208a032, 0x0308a034, + 0x0288a026, 0x0388a024, 0x5de1b80a, 0x82070004, + 0xb62b002a, 0x0017b80d, 0x0097b80e, 0x102db80f, + 0x0117b801, 0x104eb80f, 0x0197b802, 0x82171600, + 0x82971700, 0x0037b80f, 0x00b7b80f, 0x0137b80f, + 0x01b7b80f, 0xb630001b, 0x003f8030, 0x005f8034, + 0x5ee2b80f, 0x8013007f, 0x9800ffff, 0xb6370011, + 0x41008000, 0x51018008, 0x4902800c, 0x40c08000, + 0x0008a028, 0x48c18008, 0x50c2800c, 0x42808004, + 0x00c8b806, 0x52828008, 0x5281800c, 0x41008004, + 0x0088a034, 0x49028008, 0x4901800c, 0x011fa026, + 0x0188a028, 0x001f8001, 0x001f8005, 0x001f8009, + 0x001f800d, 0x5de1b80f, 0x5a01b810, 0x0017b80d, + 0x0097b80e, 0x902d0004, 0x0117b801, 0x904e0004, + 0x0197b802, 0x82171600, 0x82971700, 0x5ea1b80a, + 0x8013007f, 0x9800ffff, 0xb6350013, 0x003f8030, + 0x005f8034, 0x42408000, 0x52418008, 0x4a42800c, + 0x41008000, 0x0008a052, 0x49018008, 0x5102800c, + 0x42808004, 0x0108b808, 0x52828008, 0x5281800c, + 0x40c08004, 0x0088a054, 0x48c28008, 0x48c1800c, + 0x011fa048, 0x0188a046, 0x81a71100, 0x81c71200, + 0x858c0001, 0xb4e0ff7e, 0x00ffb81c, 0x00000000, + 0x005f03fa, 0x00000000, 0xb0020000, 0xb4000034, + 0x81b70080, 0x81d7ffff, 0x81f70001, 0x82370080, + 0x8257ffff, 0x82770001, 0x82b70080, 0x82d7ffff, + 0x82f70001, 0x83370080, 0x8357ffff, 0x83770001, + 0x81971000, 0x82171100, 0x82971200, 0x83171300, + 0x815703fc, 0x81370200, 0x81170c00, 0x83d703fc, + 0x83b70200, 0x83970f00, 0x8057ffff, 0x80d7ffff, + 0x80171400, 0x80971500, 0x001f800d, 0x003f8019, + 0xb6004012, 0x41008000, 0x51018004, 0x007f8011, + 0x0128a008, 0x41018000, 0x49008004, 0x009f8015, + 0x03a8a008, 0x41038000, 0x51048004, 0x001f800d, + 0x03a8a008, 0x41048020, 0x49038024, 0x003f8019, + 0x0128a008, 0x005f8028, 0x005f803c, 0x81f70000, + 0x82770000, 0x82f70000, 0x83770000, 0x00ffb81c, + 0x82370040, 0x8257ffff, 0x82770001, 0x82b70040, + 0x82d7ffff, 0x82f70001, 0x82171000, 0x82971200, + 0x8157ffff, 0x81170c00, 0x81d7ffff, 0x81970e00, + 0x8057ffff, 0x80d7ffff, 0x80171800, 0x80971a00, + 0xb600800a, 0x001f8011, 0x003f8015, 0x41008000, + 0x51018004, 0x00000000, 0x0108a028, 0x41018020, + 0x49008024, 0x00000000, 0x0188a028, 0x82770000, + 0x82f70000, 0x00ffb81c, 0x00000000, 0x00000000, + 0x8057ffff, 0x80d7ffff, 0x8157ffff, 0x808f0000, + 0x015f0384, 0x017f037a, 0xac4a0006, 0x8027b004, + 0x1042b80b, 0x5841b802, 0x1021b802, 0x0159b801, + 0x013f0325, 0x01bf0320, 0x5822b80b, 0x90210340, + 0x00ff9801, 0x8027b2e8, 0x5842b807, 0x1021b802, + 0x025bb801, 0x80070000, 0xac4d0006, 0x8027b004, + 0x1042b800, 0x5841b802, 0x1021b802, 0x0199b801, + 0x00000000, 0xac4c0006, 0x8027b078, 0x1042b80a, + 0x5842b802, 0x1021b802, 0x011bb801, 0x00000000, + 0x40d2b808, 0x00000000, 0xb0060000, 0xb4000080, + 0x005f033b, 0x80278400, 0xac600080, 0x5c22b801, + 0x10a1b803, 0xb0020000, 0xb4200002, 0x80279000, + 0xb5000001, 0x80279c00, 0x5c22b801, 0x11e1b803, + 0x80470300, 0x5822b800, 0x1042b801, 0x003f9802, + 0x806f001f, 0x80af001f, 0xb0010000, 0xb4200024, + 0x80170c00, 0x80971000, 0x003f8020, 0xb6000003, + 0x4201b806, 0x003f8020, 0x0088a030, 0x80270400, + 0xb6000208, 0x00cfb801, 0x00bfb0bc, 0x58a2b805, + 0x01afb805, 0x00bf90bc, 0xb520ffff, 0x90210020, + 0x90a50020, 0xb6000408, 0x00cfb801, 0x01ffb0bc, + 0x59e2b80f, 0x01afb80f, 0x01ff90bc, 0xb520ffff, + 0x90210020, 0x91ef0020, 0xb6000208, 0x00cfb801, + 0x00bfb0bc, 0x58a2b805, 0x01afb805, 0x00bf90bc, + 0xb520ffff, 0x90210020, 0x90a50020, 0xb5000043, + 0x80270400, 0x0087b805, 0x01c7b80f, 0xb6000208, + 0x00cfb801, 0x009fb0bc, 0x5882b804, 0x01cfb804, + 0x009f90bc, 0xb520ffff, 0x90210020, 0x90840020, + 0xb6000408, 0x00cfb801, 0x01dfb0bc, 0x59c2b80e, + 0x01cfb80e, 0x01df90bc, 0xb520ffff, 0x90210020, + 0x91ce0020, 0xb6000208, 0x00cfb801, 0x009fb0bc, + 0x5882b804, 0x01cfb804, 0x009f90bc, 0xb520ffff, + 0x90210020, 0x90840020, 0x80170c00, 0x80971000, + 0x8053007f, 0x9842ffff, 0xb6000004, 0x42028004, + 0x4a068020, 0x00000000, 0x0088a030, 0x80270400, + 0xb6000208, 0x00cfb801, 0x00bfb0bc, 0x58a2b805, + 0x01afb805, 0x00bf90bc, 0xb520ffff, 0x90210020, + 0x90a50020, 0xb6000408, 0x00cfb801, 0x01ffb0bc, + 0x59e2b80f, 0x01afb80f, 0x01ff90bc, 0xb520ffff, + 0x90210020, 0x91ef0020, 0xb6000208, 0x00cfb801, + 0x00bfb0bc, 0x58a2b805, 0x01afb805, 0x00bf90bc, + 0xb520ffff, 0x90210020, 0x90a50020, 0x5822b800, + 0x90210300, 0x0117b801, 0x80470001, 0x011fa002, + 0x90000001, 0x3000b809, 0xb480ff6b, 0x00ffb81c, + 0x8057ffff, 0x013f0325, 0x015f033b, 0x80171000, + 0x80070000, 0xb6002001, 0x001fa020, 0xb00a0001, + 0xb4c00002, 0x81679000, 0xb5000001, 0x81679c00, + 0x5d62b80b, 0x81878400, 0x5d82b80c, 0x80070000, + 0x5822b800, 0x90410300, 0x003f9802, 0x00000000, + 0xb0010000, 0xb4200019, 0xac400080, 0x00000000, + 0x10ccb802, 0x10abb802, 0x806f001f, 0x80af001f, + 0x80cf0400, 0xb6000408, 0xb520ffff, 0x00dfb0bc, + 0x58c2b806, 0x01afb806, 0x00df90bc, 0xb520ffff, + 0x80cf0400, 0x90c60020, 0x80cf0400, 0xb6000407, + 0x00bfb0bc, 0x58a2b805, 0x01afb805, 0x00bf90bc, + 0xb520ffff, 0x80cf0400, 0x90a50020, 0x90000001, + 0x3000b809, 0xb480ffde, 0x00ffb81b, 0x8057ffff, + 0x013f0325, 0x80171000, 0x80070000, 0xb6002001, + 0x001fa020, 0x81878400, 0x5d82b80c, 0x80070000, + 0x5822b800, 0x90410300, 0x003f9802, 0x00000000, + 0xb0010000, 0xb420000f, 0xac400080, 0x00000000, + 0x10ccb802, 0x806f001f, 0x80af001f, 0x80cf0400, + 0xb6000408, 0xb520ffff, 0x00dfb0bc, 0x58c2b806, + 0x01afb806, 0x00df90bc, 0xb520ffff, 0x80cf0400, + 0x90c60020, 0x90000001, 0x3000b809, 0xb480ffe8, + 0x00ffb81b, 0x8057ffff, 0x80d7ffff, 0x8157ffff, + 0x8139b000, 0x00000000, 0xb0090000, 0xb4000012, + 0x806f001f, 0x80af001f, 0x80cf0400, 0x013fb0bc, + 0x5922b809, 0x01cfb809, 0x013f90bc, 0xb520ffff, + 0x806f0003, 0x80af0003, 0x80cf0420, 0x91290020, + 0x013fb0bc, 0x5922b809, 0x01cfb809, 0x013f90bc, + 0xb520ffff, 0xb5000233, 0x80270000, 0x80171000, + 0xb6002401, 0x001fa021, 0x007f0384, 0x009f0320, + 0x00bf0385, 0x00df0386, 0x80e7b36c, 0x5821b803, + 0x1021b807, 0x0159b801, 0x5821b804, 0x1021b807, + 0x0179b801, 0x80e7b37c, 0x5821b803, 0x1021b807, + 0x0199b801, 0x5821b804, 0x1021b807, 0x01b9b801, + 0x80e7b38c, 0x5821b803, 0x1021b807, 0x01d9b801, + 0x5821b804, 0x1021b807, 0x01f9b801, 0x005f0385, + 0x8027b39c, 0x5842b802, 0x1021b802, 0x021bb801, + 0x005f0386, 0x8027b3ac, 0x5842b802, 0x1021b802, + 0x023bb801, 0x027f0383, 0x003f0328, 0x005f4195, + 0xb0130007, 0xb42000df, 0xb0010000, 0xb42000dd, + 0xb0020000, 0xb40000db, 0xb0030002, 0xb48000d9, + 0x029bb802, 0x82a7b108, 0xb00b0001, 0xb4200001, + 0xb5000005, 0xb00b0002, 0xb4200002, 0x92b500a0, + 0xb5000001, 0x92b50140, 0xb0030004, 0xb4600002, + 0x82870000, 0xb5000006, 0xb0030006, 0xb4600004, + 0xb0140001, 0xb4a00002, 0x82870001, 0xb5000000, + 0xac54000a, 0x806f0009, 0x80af0009, 0x5c22b815, + 0x80cf0440, 0x1021b802, 0x003fb0bc, 0x5822b801, + 0x01cfb801, 0x003f90bc, 0xb520ffff, 0xb0030003, + 0xb400000f, 0xb0030004, 0xb400001d, 0xb0030005, + 0xb400002b, 0xb0030006, 0xb4000042, 0xb0030007, + 0xb4000059, 0x80171000, 0x005f9440, 0x001fa002, + 0x80171038, 0x005f9440, 0x001fa002, 0xb5000073, + 0x80171000, 0x005f9440, 0x001fa002, 0x80171004, + 0x005f9443, 0x001fa002, 0x8017101c, 0x005f9446, + 0x001fa002, 0x80171034, 0x005f9449, 0x001fa002, + 0x80171038, 0x005f9440, 0x001fa002, 0xb5000063, + 0x80171000, 0x005f9440, 0x001fa002, 0x80171008, + 0x005f9441, 0x001fa002, 0x80171020, 0x005f9444, + 0x001fa002, 0x80171034, 0x005f9440, 0x001fa002, + 0x80171038, 0x005f9447, 0x001fa002, 0xb5000053, + 0x80171000, 0x005f9440, 0x001fa002, 0x80171004, + 0x005f9443, 0x001fa002, 0x8017100c, 0x005f9441, + 0x001fa002, 0x8017101c, 0x005f9446, 0x001fa002, + 0x80171024, 0x005f9444, 0x001fa002, 0x80171034, + 0x005f9449, 0x001fa002, 0x80171038, 0x005f9440, + 0x001fa002, 0x8017103c, 0x005f9447, 0x001fa002, + 0xb500003a, 0x80171000, 0x005f9440, 0x001fa002, + 0x80171008, 0x005f9441, 0x001fa002, 0x8017100c, + 0x005f9442, 0x001fa002, 0x80171020, 0x005f9444, + 0x001fa002, 0x80171024, 0x005f9445, 0x001fa002, + 0x80171034, 0x005f9440, 0x001fa002, 0x80171038, + 0x005f9447, 0x001fa002, 0x8017103c, 0x005f9448, + 0x001fa002, 0xb5000021, 0x80171000, 0x005f9440, + 0x001fa002, 0x80171004, 0x005f9443, 0x001fa002, + 0x8017100c, 0x005f9441, 0x001fa002, 0x80171010, + 0x005f9442, 0x001fa002, 0x8017101c, 0x005f9446, + 0x001fa002, 0x80171024, 0x005f9444, 0x001fa002, + 0x80171028, 0x005f9445, 0x001fa002, 0x80171034, + 0x005f9449, 0x001fa002, 0x80171038, 0x005f9440, + 0x001fa002, 0x8017103c, 0x005f9447, 0x001fa002, + 0x80171040, 0x005f9448, 0x001fa002, 0x80270001, + 0x803eff90, 0x80171000, 0x82b30020, 0x9ab50000, + 0x40158020, 0xb6000501, 0x48158020, 0x82b30020, + 0x9ab50000, 0x80470000, 0x3015b800, 0xb4600006, + 0x80171000, 0x83840226, 0xb6000603, 0x40028000, + 0x00000000, 0x0008a020, 0x80171018, 0x82b30020, + 0x9ab50000, 0x40158020, 0xb6000501, 0x48158020, + 0x82b30020, 0x9ab50000, 0x80470000, 0x3015b800, + 0xb4600006, 0x80171018, 0x83840215, 0xb6000603, + 0x40028000, 0x00000000, 0x0008a020, 0x80171030, + 0x82b30020, 0x9ab50000, 0x40158020, 0xb6000501, + 0x48158020, 0x82b30020, 0x9ab50000, 0x80470000, + 0x3015b800, 0xb4600006, 0x80171030, 0x83840204, + 0xb6000603, 0x40028000, 0x00000000, 0x0008a020, + 0xb500011e, 0x80270000, 0x803eff90, 0xb0030000, + 0xb4200067, 0x025f0322, 0xb00b0001, 0xb4200016, + 0xb0120001, 0xb4200005, 0x80171018, 0x8033007f, + 0x9821ffff, 0x001fa001, 0xb5000110, 0xb0120002, + 0xb4200005, 0x80171020, 0x8033007f, 0x9821ffff, + 0x001fa001, 0xb5000109, 0x80171018, 0x80330040, + 0x98210000, 0x001fa001, 0x80171020, 0x00000000, + 0x001fa001, 0xb5000101, 0xb00b0002, 0xb420002c, + 0xb0120000, 0xb4200008, 0x80171000, 0x8033007f, + 0x9821ffff, 0x001fa001, 0x80171038, 0x00000000, + 0x001fa001, 0xb50000f5, 0xb0120001, 0xb4200008, + 0x80171000, 0x8033005a, 0x98218279, 0x001fa001, + 0x80171030, 0x00000000, 0x001fa001, 0xb50000eb, + 0xb0120002, 0xb4200008, 0x80171008, 0x8033005a, + 0x98218279, 0x001fa001, 0x80171038, 0x00000000, + 0x001fa001, 0xb50000e1, 0x80171000, 0x80330040, + 0x98210000, 0x001fa001, 0x80171008, 0x00000000, + 0x001fa001, 0x8017100c, 0x00000000, 0x001fa001, + 0x80171038, 0x00000000, 0x001fa001, 0xb50000d3, + 0xb0120000, 0xb4200008, 0x80171000, 0x8033007f, + 0x9821ffff, 0x001fa001, 0x80171038, 0x00000000, + 0x001fa001, 0xb50000c9, 0xb0120001, 0xb4200005, + 0x80171018, 0x8033007f, 0x9821ffff, 0x001fa001, + 0xb50000c2, 0xb0120002, 0xb4200005, 0x80171020, + 0x8033007f, 0x9821ffff, 0x001fa001, 0xb50000bb, + 0x80171018, 0x80330040, 0x98210000, 0x001fa001, + 0x80171020, 0x00000000, 0x001fa001, 0xb50000b3, + 0x80070000, 0x8033007f, 0x9821ffff, 0xb600050e, + 0x144eb80f, 0xb0028000, 0xb4c00008, 0xac400006, + 0x00000000, 0x1042b800, 0x5842b802, 0x90421000, + 0x0017b802, 0x00000000, 0x001fa001, 0x90000001, + 0x59c1b80e, 0x59e1b80f, 0xb0040000, 0xb4200023, + 0xb00a0002, 0xb4000007, 0x80171004, 0x8033005a, + 0x98218279, 0x001fa001, 0x80171034, 0x00000000, + 0x001fa001, 0xb00c0002, 0xb4000009, 0x8017100c, + 0x8033ffa5, 0x98217d87, 0x001fa001, 0x8017103c, + 0x8033005a, 0x98218279, 0x001fa001, 0xb500008b, + 0x8017100c, 0x8033ffa5, 0x98217d87, 0x001fa001, + 0x80171010, 0x00000000, 0x001fa001, 0x8017103c, + 0x8033005a, 0x98218279, 0x001fa001, 0x80171040, + 0x00000000, 0x001fa001, 0xb500007c, 0xb0040001, + 0xb420002a, 0xb00a0001, 0xb4000007, 0x80171018, + 0x8033005a, 0x98218279, 0x001fa001, 0x80171020, + 0x00000000, 0x001fa001, 0xb00a0003, 0xb420000a, + 0x8053005a, 0x98428279, 0x4030b802, 0x8017101c, + 0x5821b801, 0x00000000, 0x00000000, 0x00000000, + 0x0028b801, 0x001fa001, 0xb00c0001, 0xb4200007, + 0x8053005a, 0x98428279, 0x4031b802, 0x80171024, + 0x0028b801, 0x001fa001, 0xb500005c, 0xb00c0002, + 0xb420005a, 0x8053005a, 0x98428279, 0x4031b802, + 0x80171024, 0x0028b801, 0x001fa001, 0x80171028, + 0x00000000, 0x001fa001, 0xb5000050, 0xb00b0002, + 0xb4200012, 0xb00a0001, 0xb4200008, 0x80171004, + 0x8033005a, 0x98218279, 0x001fa001, 0x80171034, + 0x00000000, 0x001fa001, 0xb5000008, 0xb00a0003, + 0xb4200006, 0x80171004, 0x00000000, 0x001fa010, + 0x80171034, 0x00000000, 0x001fa010, 0xb00c0001, + 0xb4200025, 0x027f0383, 0x003f0328, 0xb0130007, + 0xb420000b, 0xb00b0003, 0xb4200009, 0xb0010000, + 0xb4200007, 0x80171024, 0x00000000, 0x001fa011, + 0x80171054, 0x80270000, 0x001fa001, 0xb500002b, + 0xb00d0000, 0xb420000a, 0x8033005a, 0x98218279, + 0x4041b811, 0x8017100c, 0x0048b802, 0x001fa002, + 0x8017103c, 0x00000000, 0x001fa002, 0xb500001f, + 0xb00d0002, 0xb420001d, 0x80171054, 0x8033005a, + 0x98218279, 0x001fa001, 0x8017106c, 0x00000000, + 0x001fa001, 0xb5000015, 0xb00c0002, 0xb4200013, + 0xb00d0000, 0xb4200007, 0x8017100c, 0x00000000, + 0x001fa011, 0x80171040, 0x00000000, 0x001fa011, + 0xb500000a, 0xb00d0001, 0xb4200008, 0x80171054, + 0x8033005a, 0x98218279, 0x001fa001, 0x80171058, + 0x00000000, 0x001fa001, 0xb5000000, 0x029f0388, + 0x02bf0321, 0xb0140000, 0xb4000006, 0xb0150000, + 0xb4000004, 0x8017108c, 0x8033007f, 0x9821ffff, + 0x001fa001, 0x8027b078, 0x5c22b801, 0x806f001f, + 0x80af001f, 0x80cf0400, 0x003fb0bc, 0x5822b801, + 0x01afb801, 0x003f90bc, 0xb520ffff, 0x90210020, + 0x806f0003, 0x80af0003, 0x80cf0420, 0x003fb0bc, + 0x5822b801, 0x01afb801, 0x003f90bc, 0xb520ffff, + 0x81270000, 0x8033007f, 0x9821ffff, 0x80171000, + 0xb600060a, 0x80470000, 0xb6000603, 0x015f8020, + 0x0156b80a, 0x1042b80a, 0x3002b801, 0xb4a00001, + 0x81270001, 0x00000000, 0x00000000, 0x015f0323, + 0x00000000, 0xb00a0000, 0xb4200002, 0x81670000, + 0xb5000001, 0x81670001, 0x017f23fb, 0x01ff41ee, + 0x59f0b80f, 0x61f0b80f, 0x021f41ef, 0x5a10b810, + 0x6210b810, 0xb00a0003, 0xb420003b, 0x017f039f, + 0x019f41c5, 0x5990b80c, 0x6190b80c, 0xb00b0000, + 0xb400000c, 0xb00c0000, 0xb4000005, 0xac4c0100, + 0x8033001d, 0x98215500, 0x12c1b802, 0xb500000f, + 0xac4f0100, 0x8033001d, 0x98215500, 0x12c1b802, + 0xb500000a, 0xb0090000, 0xb4000005, 0xac4f0100, + 0x8033ffe2, 0x9821ab00, 0x12c1b802, 0xb5000003, + 0xac4f0100, 0x00000000, 0x02c7b802, 0xb0030000, + 0xb420007e, 0x01bf03a0, 0x01df41c9, 0x59d0b80e, + 0x61d0b80e, 0xb00d0000, 0xb400000c, 0xb00e0000, + 0xb4000005, 0xac4e0100, 0x8033001d, 0x98215500, + 0x12e1b802, 0xb5000071, 0xac500100, 0x8033001d, + 0x98215500, 0x12e1b802, 0xb500006c, 0xb0090000, + 0xb4000005, 0xac500100, 0x8033ffe2, 0x9821ab00, + 0x12e1b802, 0xb5000065, 0xac500100, 0x00000000, + 0x02e7b802, 0xb5000061, 0xb00a0002, 0xb420002f, + 0x023f9002, 0x025f9001, 0xb00f0000, 0xb4a00007, + 0xac4f0100, 0x00000000, 0x4022b811, 0x00000000, + 0x0028b801, 0x02c7b801, 0xb500000c, 0xb0090000, + 0xb4000004, 0xac4f0100, 0x00000000, 0x02c7b802, + 0xb5000006, 0xac4f0100, 0x00000000, 0x4022b812, + 0x00000000, 0x0028b801, 0x02c7b801, 0xb0030000, + 0xb4200046, 0xb0100000, 0xb4a00007, 0xac500100, + 0x00000000, 0x4022b811, 0x00000000, 0x0028b801, + 0x02e7b801, 0xb500003d, 0xb0090000, 0xb4000004, + 0xac500100, 0x00000000, 0x02e7b802, 0xb5000037, + 0xac500100, 0x00000000, 0x4022b812, 0x00000000, + 0x0028b801, 0x02e7b801, 0xb5000030, 0x023f9002, + 0x025f9001, 0xb00f0000, 0xb4a00007, 0xac4f0100, + 0x00000000, 0x4022b811, 0x00000000, 0x0028b801, + 0x02c7b801, 0xb5000006, 0xac4f0100, 0x00000000, + 0x4022b812, 0x00000000, 0x0028b801, 0x02c7b801, + 0xb0090000, 0xb4000005, 0x0047b816, 0x8033ffe2, + 0x9821ab00, 0x1042b801, 0x02c7b802, 0xb0030000, + 0xb4200016, 0xb0100000, 0xb4a00007, 0xac500100, + 0x00000000, 0x4022b811, 0x00000000, 0x0028b801, + 0x02e7b801, 0xb5000006, 0xac500100, 0x00000000, + 0x4022b812, 0x00000000, 0x0028b801, 0x02e7b801, + 0xb0090000, 0xb4000005, 0x0047b817, 0x8033ffe2, + 0x9821ab00, 0x1042b801, 0x02e7b802, 0x00000000, + 0x00000000, 0x02c8b816, 0x02dfb0cf, 0xb0030000, + 0xb4200002, 0x02e8b817, 0x02ffb0c6, 0x00ffb81b, + 0xb6001807, 0x5841b802, 0x3015b800, 0xb4800002, + 0x06b5b800, 0x98420001, 0x5aa1b815, 0x00000000, + 0x00ffb81c, 0x00000000, 0x00000000, 0x00000000, + 0x003f03f9, 0x009f0324, 0x84840001, 0xb0010000, + 0xb4000011, 0x815bb3f0, 0x81070000, 0x81270bf4, + 0xb00a0000, 0xb4000002, 0x81070c00, 0x812717f4, + 0x802500a5, 0x806500a5, 0x3001b803, 0xb420fffc, + 0x9421ffff, 0x3001b808, 0xb480000b, 0x3001b809, + 0xb4a0002d, 0xb5000008, 0xb0040000, 0xb4200003, + 0x802717ff, 0x81470000, 0xb5000003, 0x80270001, + 0x003f23f9, 0x81470c00, 0xb0040000, 0xb4200001, + 0x8384020c, 0x80af001f, 0x808f0000, 0x806f0000, + 0x80670400, 0x5d22b80a, 0x81df0000, 0x00000000, + 0x00000000, 0xb600180a, 0x00cfb803, 0x013fb0bc, + 0x5922b809, 0x01afb809, 0x013f90bc, 0x0047b86f, + 0xb0020001, 0xb4c0fffd, 0x90630020, 0x91290020, + 0x81df0004, 0x801bb3f8, 0x80270001, 0xb0000001, + 0xb4000002, 0x802600a0, 0x803eb3f8, 0x81270c00, + 0xb00a0000, 0xb4000001, 0x81270000, 0x813eb3f0, + 0x80270001, 0x003f2013, 0x00ffb81b, 0x00000000, + 0x029fb00a, 0x02bfb00b, 0x02dfb00c, 0x02ffb00d, + 0x031fb00e, 0x033fb00f, 0x033f400f, 0x0287b86f, + 0x029fb005, 0x8285009c, 0x96b48000, 0xb0158000, + 0xb4000195, 0x96b40100, 0xb0150100, 0xb40001ab, + 0x96b40400, 0xb0150400, 0xb40001ac, 0x96b40001, + 0xb0150001, 0xb400000c, 0x96b40008, 0xb0150008, + 0xb400019e, 0x96b44000, 0xb0154000, 0xb40001ab, + 0x96b40002, 0xb0150002, 0xb4000162, 0x00000000, + 0x00000000, 0xb50001bd, 0x02bf9017, 0x92b50001, + 0x02bfb017, 0x82850082, 0x5efdb814, 0x96f70001, + 0xb0170001, 0xb420000b, 0x83050069, 0x9718003f, + 0x82e50064, 0x12f7b818, 0x86f70109, 0x82feff74, + 0x02e7b86f, 0x9af74000, 0x01ffb817, 0x96f7bfff, + 0x01ffb817, 0x83050081, 0x82a5009a, 0x96b50001, + 0xb0150001, 0xb4200014, 0x82a70000, 0x02bfb017, + 0x96b41840, 0xb0150800, 0xb420000c, 0x96b40008, + 0x5aa9b815, 0x96d46000, 0x5ec3b816, 0x82f3000f, + 0x9af7c00f, 0x1718b817, 0x1ab5b818, 0x1ab5b816, + 0x9ab50340, 0x82a60081, 0xb5000132, 0x9b180180, + 0x83060081, 0xb500012f, 0x82a5009a, 0x96b50002, + 0xb0150002, 0xb420001b, 0x82a70000, 0x02bfb017, + 0x96b41800, 0xb0151800, 0xb4000013, 0x96b40040, + 0xb0150040, 0xb4200004, 0xa3180c00, 0x9b180340, + 0x83060081, 0xb500011f, 0x96b40008, 0x5aa9b815, + 0x96d46000, 0x5ec3b816, 0x82f3000f, 0x9af7c00f, + 0x1718b817, 0x1ab5b818, 0x1ab5b816, 0x9ab50340, + 0x82a60081, 0xb5000113, 0x9b180180, 0x83060081, + 0xb5000110, 0x82a500c1, 0x96b5000f, 0xb015000b, + 0xb420000e, 0x96b40020, 0xb0150020, 0xb400000b, + 0x96b40200, 0xb0150200, 0xb4000008, 0x82c50086, + 0x82e50094, 0x3016b817, 0xb4400004, 0x06f7b816, + 0xb017ff00, 0xb4400001, 0xb50000fe, 0x96b46000, + 0xb0156000, 0xb4000011, 0x96b41820, 0xb0150820, + 0xb4200004, 0x9b391000, 0x82a5009a, 0x96b5feff, + 0x82a6009a, 0x96b40040, 0xb0150040, 0xb4200001, + 0x9739efff, 0x96b91000, 0xb0151000, 0xb4200003, + 0x82a5009a, 0x9ab50100, 0x82a6009a, 0x96b40040, + 0xb0150040, 0xb4200019, 0x96b41800, 0xb0151800, + 0xb4200006, 0x96b98000, 0xb0158000, 0xb4200003, + 0x9b180180, 0x83060081, 0xb50000de, 0x96d80c00, + 0x82b300ff, 0x9ab5f3ff, 0x1718b815, 0xb0160c00, + 0xb4000007, 0x82e50098, 0x96f70400, 0xb0170400, + 0xb4200002, 0x82c70c00, 0xb5000001, 0xa2d60c00, + 0x1b18b816, 0x9b180340, 0xb50000c4, 0x96b40220, + 0xb0150000, 0xb4e00028, 0x82a5009d, 0x82f3ffff, + 0x16b5b817, 0x82f3000e, 0x3015b817, 0xb4200022, + 0x96f98000, 0xb0178000, 0xb400001f, 0x82a70000, + 0x02bfb017, 0x82c50081, 0x9ab60020, 0x82a60081, + 0x82a50086, 0x92b50bb8, 0x82a60094, 0x82c60081, + 0x82c5009d, 0x96d6ffff, 0x82b30032, 0x9ab58001, + 0x82e500c1, 0x96f7000f, 0xb017000b, 0xb4000002, + 0x82b30022, 0x9ab58001, 0x1ab5b816, 0x82c5009a, + 0x96d60020, 0xb0160020, 0xb4200002, 0x82b30032, + 0x9ab58001, 0x82a6009d, 0x02ff9017, 0x00000000, + 0xb0170040, 0xb4800000, 0x5eb5b814, 0x96b500f0, + 0x96f46000, 0x5eedb817, 0x1ab5b817, 0xb0170003, + 0xb4000004, 0x96b500ef, 0x96f70001, 0x5ae4b817, + 0x1ab5b817, 0x96d41800, 0xb0161800, 0xb400000a, + 0x96f900ff, 0x96b500ff, 0x9739ff00, 0x1b39b815, + 0x02a7b817, 0x96b500f3, 0x96d40008, 0x5ec1b816, + 0x1ab5b816, 0xb500000c, 0x96f98000, 0xb0178000, + 0xb4200007, 0x5efeb814, 0x96f70001, 0xb0170001, + 0xb4000003, 0x9b180180, 0x83060081, 0xb5000081, + 0x96b500f3, 0x9ab50008, 0x9739fff3, 0x96d40020, + 0xb0160020, 0xb4200017, 0x9b398000, 0x82c70000, + 0x02dfb017, 0x96d40010, 0x5ac8b816, 0x82f300ff, + 0x9af7cfff, 0x1718b817, 0x1b18b816, 0x9b180340, + 0x82c5009d, 0x96d6ffff, 0x82f3000e, 0x9af78001, + 0x1af7b816, 0x82c5009a, 0x96d60020, 0xb0160020, + 0xb4200002, 0x82f30032, 0x9af78001, 0x82e6009d, + 0xb500005a, 0x97397fff, 0x96b500ff, 0x5aaab815, + 0x82f300fc, 0x9af703ff, 0x1718b817, 0x1b18b815, + 0x9b180340, 0x82c5009a, 0x96d60010, 0xb0160010, + 0xb4200024, 0x82c70000, 0x02dfb017, 0x82c50086, + 0x92d60bb8, 0x82c60086, 0x82c50094, 0x5eefb818, + 0x96f70003, 0xb0170003, 0xb4200002, 0x82e70bb8, + 0xb5000001, 0x82e70bb8, 0x12d6b817, 0x82e50081, + 0x9af70020, 0x82e60081, 0x82c60094, 0xa2f70020, + 0x82e60081, 0x82f30001, 0x16f7b818, 0x5ef0b817, + 0xb0170001, 0xb4000004, 0x96f84000, 0x5ee4b817, + 0x9718f3ff, 0x1b18b817, 0x82f3000a, 0x9af78000, + 0x82e6009d, 0x83060081, 0x83070001, 0x8306009f, + 0xb5000096, 0x82c5009d, 0x82f3000e, 0x9af78001, + 0x3016b817, 0xb420000f, 0x82b30032, 0x9ab58001, + 0x82e500c1, 0x96f7000f, 0xb017000b, 0xb4000002, + 0x82b30022, 0x9ab58001, 0x82c5009a, 0x96d60020, + 0xb0160020, 0xb4200002, 0x82b30032, 0x9ab58001, + 0x82a6009d, 0x82c5009a, 0x96d60080, 0xb0160080, + 0xb4000011, 0x02df9017, 0x00000000, 0xb0160010, + 0xb480000d, 0x82c500c1, 0x96d6000f, 0xb016000b, + 0xb4000009, 0x82c50087, 0x96d60080, 0x5ac7b816, + 0x96f84000, 0x3017b816, 0xb4200003, 0x033f400f, + 0x9b394000, 0xb500000b, 0x9739bfff, 0x82e50061, + 0x96f70008, 0xb0170008, 0xb4000005, 0x5eefb818, + 0x96f70003, 0xb0170003, 0xb4000001, 0x9718ffff, + 0x83060081, 0x83070001, 0x8306009f, 0x00000000, + 0xb500005e, 0x82850083, 0x96b400ff, 0xb015003c, + 0xb4200019, 0x96b92000, 0xb0152000, 0xb4000002, + 0x9b392000, 0xb5000014, 0x9739d3ff, 0x82870000, + 0x82860087, 0x82870008, 0x82860083, 0x829bff78, + 0x82a7001f, 0xb0140400, 0xb4000001, 0x82a70010, + 0x82a600c9, 0x829bff78, 0x00000000, 0x828600cb, + 0x8285009d, 0x82b3ffff, 0x9ab5fffd, 0x1694b815, + 0x8286009d, 0xb5000000, 0x83070002, 0x8306009f, + 0x00000000, 0xb500003d, 0x96b90800, 0xb0150800, + 0xb4200009, 0x9739f7ff, 0x82a703fd, 0x82a600cb, + 0x82a7003c, 0x82a60083, 0x8285009d, 0x9a940002, + 0x8286009d, 0xb5000004, 0x82850087, 0x5a82b814, + 0xa2940200, 0x82860087, 0xb5000000, 0x83078000, + 0x8306009f, 0x00000000, 0xb5000028, 0x83070008, + 0x8306009f, 0x00000000, 0xb5000024, 0x83070100, + 0x8306009f, 0x00000000, 0xb5000020, 0x83070000, + 0x83050081, 0x9b180180, 0x83060081, 0x83070400, + 0x8306009f, 0x00000000, 0xb5000018, 0x82870000, + 0x82850082, 0x5eb7b814, 0x96b500fc, 0x96d40006, + 0x5ec1b816, 0x1ab5b816, 0x5aacb815, 0x83050081, + 0x82d3001c, 0x9ad600ff, 0x1718b816, 0x1b18b815, + 0x9b180e00, 0x83060081, 0x83074000, 0x8306009f, + 0x8305009d, 0x82d300ff, 0x9ad6bfff, 0x1718b816, + 0x8306009d, 0x00000000, 0xb5000000, 0x029f9005, + 0x01ffb814, 0x033f600f, 0x029f900a, 0x02bf900b, + 0x02df900c, 0x02ff900d, 0x031f900e, 0x033f900f, + 0x00ffb81e, 0x02ff9010, 0x92f70b43, 0x02ffb010, + 0x02ff90cb, 0x82bbffdc, 0x829bffd8, 0x93150004, + 0x3014b815, 0xb400000f, 0x02dbb818, 0x029bb815, + 0x3017b816, 0xb480000b, 0x5a81b814, 0x029fb010, + 0x82860095, 0x8293001f, 0x9294fe00, 0x92b50008, + 0x3015b814, 0xb4800002, 0x82b3001f, 0x92b5fa00, + 0x82beffdc, 0x029f9010, 0x83250094, 0x06d4b819, + 0x02d6b816, 0xb016ffff, 0xb4a0000a, 0x8293000e, + 0x9a948001, 0x82c5009d, 0x96d6ffff, 0x1a94b816, + 0x82c5009a, 0x96d60010, 0xb0160010, 0xb4000001, + 0x8286009d, 0x00ffb81c, 0x82870001, 0x829ef500, + 0x82850086, 0x83250094, 0x06d4b819, 0x02d6b816, + 0xb016ffff, 0xb4a0000b, 0x82870001, 0x829ef504, + 0x82c50081, 0x9ab60020, 0x82a60081, 0x82a50086, + 0x92b50bbb, 0x82a60094, 0x82c60081, 0x86b505df, + 0x82a6009b, 0x00ffb81c, 0x82070028, 0x023f9006, + 0x83a4ef48, 0x80070000, 0x001fb011, 0x001f204f, + 0x003fb800, 0x001f9006, 0x5803b800, 0x80338000, + 0x1800b801, 0x003fb800, 0x005f4193, 0x5c41b802, + 0x80350000, 0x00000000, 0x0027b860, 0x80150010, + 0x5810b800, 0x80750010, 0x1863b800, 0x8087ffff, + 0x80a7770b, 0x80c70000, 0x1403b804, 0x3000b805, + 0xb4000008, 0x5888b804, 0x58a8b805, 0x90c60001, + 0xb0060003, 0xb4a0fff8, 0x84420001, 0xb4e0ffee, + 0xb5000027, 0xb0060003, 0xb4200007, 0x80150010, + 0x5810b800, 0x81150010, 0x950800ff, 0xb0080077, + 0xb4000001, 0xb500fff4, 0x001f400e, 0x98000010, + 0x98004000, 0x9400fffe, 0x001f600e, 0x80e71fc0, + 0x001f4000, 0x94000080, 0xb0000080, 0xb4200001, + 0x80e77560, 0x00ffb008, 0x80e70020, 0xb0060000, + 0xb400000e, 0x58e3b806, 0x90210020, 0x81070000, + 0x5938b803, 0x1908b809, 0x9523ff00, 0x5928b809, + 0x1908b809, 0x5d28b803, 0x9529ff00, 0x1908b809, + 0x5d38b803, 0x1908b809, 0x011fb011, 0x00ff204f, + 0x80137fff, 0x9800ffe7, 0x1421b800, 0x5c23b801, + 0x001f9006, 0x0441b800, 0x3001b800, 0xb4600002, + 0x0440b801, 0xa4422000, 0x007f90cb, 0x1063b802, + 0x007fb0cb, 0x003fb006, 0x803effec, 0x80470001, + 0x005f2013, 0xb500ebae, 0x001f400e, 0x9400000f, + 0xb0000000, 0xb4200001, 0x00ffb81f, 0xb0000001, + 0xb4000005, 0xb0000003, 0xb4000003, 0xb0000002, + 0xb4000001, 0x00ffb81f, 0x80070001, 0x001f2013, + 0xb500eb9f, 0x00000000, 0x00000000, 0x00000000, + 0x001f9012, 0x001fb100, 0x001f004c, 0x001f2404, + 0x801bfef0, 0x8058fef4, 0x803bff68, 0x8078ff6c, + 0x2000b801, 0x2042b803, 0x001fb104, 0x005f2414, + 0x82e70001, 0x83640048, 0x029fb014, 0x829efef0, + 0x8286000f, 0x02bf2054, 0x82bcfef4, 0x82a6000e, + 0x00ffb81a, 0x80e70001, 0x801336e3, 0x9800eb76, + 0x001fb100, 0x800700ab, 0x001f2404, 0x801bc3e8, + 0x8058c3ec, 0x83640024, 0x82e70000, 0x83640036, + 0x029fb300, 0x029fb100, 0x02bf2c04, 0x02bf2404, + 0x801bc000, 0x8058c004, 0x8364001b, 0x82e70000, + 0x8364002d, 0x001f9300, 0x3000b814, 0xb420000a, + 0x001f0c04, 0x3000b815, 0xb4200007, 0x829efef0, + 0x82bcfef4, 0x029fb012, 0x02bf204c, 0x82870001, + 0x829cfef5, 0x00ffb81a, 0xb0070000, 0xb4000007, + 0x80e70000, 0x801399fa, 0x9800c92e, 0x001fb100, + 0x800700af, 0x001f2404, 0xb500ffdc, 0x82870000, + 0x829cfef5, 0x00ffb81a, 0x80c700ff, 0x803bff68, + 0x8078ff6c, 0x14a0b806, 0x2063b805, 0x007f2414, + 0x2021b802, 0x58c8b806, 0x14a0b806, 0x58b0b805, + 0x2021b805, 0x58c8b806, 0x14a0b806, 0x2021b805, + 0x58c8b806, 0x14a0b806, 0x5cb0b805, 0x2021b805, + 0x003fb104, 0x00ffb81b, 0x82c70000, 0x83070400, + 0x83270005, 0x8197040c, 0x81d7ffff, 0x83840126, + 0x83840001, 0x00ffb81b, 0x808f0000, 0x806f001f, + 0x80af001f, 0x80270140, 0x81e7ef98, 0x5de2b80f, + 0xb6000208, 0x00cfb801, 0x01ffb0bc, 0x59e2b80f, + 0x01cfb80f, 0x01ff90bc, 0xb520ffff, 0x91ef0020, + 0x90210020, 0x80270180, 0x81e7ee90, 0x5de2b80f, + 0xb6000208, 0x00cfb801, 0x01ffb0bc, 0x59e2b80f, + 0x01cfb80f, 0x01ff90bc, 0xb520ffff, 0x91ef0020, + 0x90210020, 0x8057ffff, 0x80170430, 0x80070410, + 0x80270408, 0xb6000509, 0x005ff000, 0x90420500, + 0x007ff001, 0x90630600, 0x009ff002, 0x00bff003, + 0x2004a025, 0x90000001, 0x90210001, 0x80070414, + 0x80d7ffff, 0x8097045c, 0x8017043c, 0xb6000404, + 0x005ff000, 0x007f87e0, 0x84000001, 0x2082a7e3, + 0x80970460, 0x80170440, 0x2082b803, 0x007f8000, + 0x2083a004, 0x80170430, 0x80970450, 0x80270408, + 0xb6000508, 0x005f8024, 0x90420500, 0x007ff001, + 0x90630600, 0x009ff002, 0x00bff003, 0x2004a025, + 0x90210001, 0x80170440, 0x00000000, 0x02bf87e0, + 0x80970460, 0x82870000, 0xb6000404, 0x005f87e4, + 0x5a88b814, 0x204287e0, 0x1a94b802, 0x00ffb81c, + 0x001f0a49, 0x001f2709, 0x001f0a41, 0x001f2708, + 0x001f0a46, 0x001f2707, 0x001f0a48, 0x001f2706, + 0x001f0a42, 0x001f2705, 0x001f0a47, 0x001f2704, + 0x001f0a45, 0x001f2703, 0x001f0a43, 0x001f2702, + 0x001f0a40, 0x001f2701, 0x001f0a44, 0x001f2700, + 0x001f0c25, 0xa020000c, 0x94400001, 0x94600002, + 0x94810004, 0x94a10008, 0x94c00010, 0x5943b802, + 0x5861b803, 0x5882b804, 0x5ca2b805, 0x5cc4b806, + 0x194ab803, 0x194ab804, 0x194ab805, 0x194ab806, + 0x015f2738, 0x801bef90, 0x003f91c1, 0x5c28b801, + 0x005f91c2, 0x5858b802, 0x1821b802, 0x2000b801, + 0x001fb1c4, 0x8018ef94, 0x003f0709, 0x2000b801, + 0x001f2714, 0x82c70001, 0x82e70001, 0x83070710, + 0x8327001e, 0x81970735, 0x8384009f, 0x02df0738, + 0x82170a30, 0x838400f1, 0x819efef0, 0x817cfef4, + 0x819eff68, 0x817cff6c, 0x00ffb81b, 0x820f001f, + 0x8018fef8, 0x8057ffff, 0x001f2709, 0x8018fef6, + 0x80d7ffff, 0x001f2708, 0x8018fefa, 0x8157ffff, + 0x001f2707, 0x8018fefd, 0x81d7ffff, 0x001f2706, + 0x8018fefb, 0x802f001f, 0x001f2705, 0x8018fefe, + 0x00000000, 0x001f2704, 0x8018fef9, 0x00000000, + 0x001f2703, 0x8018feff, 0x00000000, 0x001f2702, + 0x8018fef7, 0x00000000, 0x001f2701, 0x8018fefc, + 0x00000000, 0x001f2700, 0x001f0c25, 0xa0200011, + 0x94410001, 0x94600002, 0x94800004, 0x94a00008, + 0x94c10010, 0x5941b802, 0x5861b803, 0x5c82b804, + 0x58a1b805, 0x5cc1b806, 0x194ab803, 0x194ab804, + 0x194ab805, 0x194ab806, 0x015f2738, 0x801bef90, + 0x003f91c1, 0x5c28b801, 0x005f91c2, 0x5858b802, + 0x1821b802, 0x2000b801, 0x001fb1c4, 0x8018ef94, + 0x003f0709, 0x2000b801, 0x001f2714, 0x82c70001, + 0x82e70001, 0x83070710, 0x8327001e, 0x81970735, + 0x83840055, 0x02df0738, 0x82170a20, 0x838400a7, + 0x819efef0, 0x817cfef4, 0x5ac8b80c, 0x02ff0a44, + 0x1ad6b817, 0x02dfb291, 0x5ed8b80c, 0x5968b80b, + 0x1ad6b80b, 0x02df6524, 0x00ffb81b, 0x820f001f, + 0x8018fefe, 0x8057ffff, 0x001f2709, 0x8018fefa, + 0x80d7ffff, 0x001f2708, 0x8018fefc, 0x8157ffff, + 0x001f2707, 0x8018feff, 0x81d7ffff, 0x001f2706, + 0x8018fef8, 0x802f001f, 0x001f2705, 0x8018fefb, + 0x00000000, 0x001f2704, 0x8018fefd, 0x00000000, + 0x001f2703, 0x8018fef6, 0x00000000, 0x001f2702, + 0x8018fef9, 0x00000000, 0x001f2701, 0x8018fef7, + 0x00000000, 0x001f2700, 0x801bef90, 0x003f91c1, + 0x5c28b801, 0x005f91c2, 0x5858b802, 0x1821b802, + 0x2000b801, 0x001fb1c4, 0x8018ef94, 0x003f0709, + 0x2000b801, 0x001f2714, 0x82c70001, 0x82e70001, + 0x83070710, 0x8327001e, 0x81970735, 0x83840016, + 0x83270000, 0x831bfef0, 0x82f8fef4, 0x02c7b819, + 0x82170a28, 0x83840065, 0x300cb818, 0xb4200002, + 0x300bb817, 0xb4000006, 0x93390001, 0xb0190020, + 0xb480fff6, 0x83270000, 0x833cfef5, 0x00ffb81b, + 0x019fb290, 0x017f2a44, 0x033f2c25, 0x83270001, + 0x833cfef5, 0x00ffb81b, 0x0007b818, 0x90000003, + 0x00000000, 0x015ff000, 0x90000001, 0x5949b80a, + 0x013ff000, 0x194ab809, 0x84000002, 0x994a0100, + 0x017ff000, 0x958b00f8, 0x5981b80c, 0x956b0007, + 0x198cb80b, 0x84000002, 0x998c0008, 0x017ff000, + 0x90000001, 0x5971b80b, 0x198cb80b, 0x017ff000, + 0x5969b80b, 0x198cb80b, 0x81a70000, 0x94d90003, + 0x82a70000, 0xb6260019, 0xb6000818, 0x5df0b80a, + 0x5e02b80a, 0x21efb810, 0x95ef0001, 0x5941b80a, + 0x194ab80f, 0x21efb816, 0x5e18b80c, 0x5e35b80c, + 0x5e54b80c, 0x5e6cb80c, 0x2210b811, 0x2252b813, + 0x2210b812, 0x96100001, 0x5981b80c, 0x198cb810, + 0x2210b817, 0x10afb810, 0x10a5b80d, 0x5da1b805, + 0x94a50001, 0x5aa1b815, 0x1ab5b805, 0x019fa7f5, + 0x5cc2b819, 0xb626001c, 0x82870000, 0xb6000419, + 0xb6000818, 0x5df0b80a, 0x5e02b80a, 0x21efb810, + 0x95ef0001, 0x5941b80a, 0x194ab80f, 0x21efb816, + 0x5e18b80c, 0x5e35b80c, 0x5e54b80c, 0x5e6cb80c, + 0x2210b811, 0x2252b813, 0x2210b812, 0x96100001, + 0x5981b80c, 0x198cb810, 0x2210b817, 0x10afb810, + 0x10a5b80d, 0x5da1b805, 0x94a50001, 0x5a81b814, + 0x1a94b805, 0x019fa7f4, 0x00ffb81c, 0x8257ffff, + 0x808f0000, 0x806f001f, 0x80af001f, 0x80270200, + 0x81e7ec70, 0x5de2b80f, 0xb6000208, 0x00cfb801, + 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, 0x01ff90bc, + 0xb520ffff, 0x91ef0020, 0x90210020, 0x80270240, + 0x81e7ed70, 0x5de2b80f, 0xb6000208, 0x00cfb801, + 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, 0x01ff90bc, + 0xb520ffff, 0x91ef0020, 0x90210020, 0x80270180, + 0x81e7ee90, 0x5de2b80f, 0xb6000208, 0x00cfb801, + 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, 0x01ff90bc, + 0xb520ffff, 0x91ef0020, 0x90210020, 0x806f0007, + 0x80af0007, 0x80270280, 0x81e7ee70, 0x5de2b80f, + 0x00cfb801, 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, + 0x01ff90bc, 0xb520ffff, 0x91ef0020, 0x90210020, + 0x80170760, 0x001f0700, 0x001fa020, 0x001f0701, + 0x001fa020, 0x001f0702, 0x001fa020, 0x001f0703, + 0x001fa020, 0x001f0704, 0x001fa000, 0x80970750, + 0x81170770, 0x82a70735, 0x83a40060, 0x001f87e4, + 0xb6000405, 0x86b50001, 0x83a4005c, 0x001f8004, + 0x003f87e8, 0x2080a7e1, 0x80970770, 0x80170750, + 0x81170750, 0x81970740, 0x82a70730, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a40050, 0x001f87e4, + 0xb6000405, 0x86b50001, 0x83a4004c, 0x001f8004, + 0x003f87e8, 0x2080a7e1, 0x80970750, 0x80170770, + 0x81170770, 0x81970760, 0x82a7072b, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a40040, 0x83a4004e, + 0xb6000407, 0x86b50001, 0x83a4003c, 0x001f8004, + 0x003f87e8, 0x2080a001, 0x83a40047, 0x00000000, + 0x80970770, 0x80170750, 0x81170750, 0x81970740, + 0x82a70726, 0x001f800c, 0x003f8008, 0x2100a001, + 0x83a4002e, 0x83a4003c, 0xb6000407, 0x86b50001, + 0x83a4002a, 0x001f8004, 0x003f87e8, 0x2080a001, + 0x83a40035, 0x00000000, 0x80970750, 0x80170770, + 0x81170770, 0x81970760, 0x82a70721, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a4001c, 0x001f87e4, + 0xb6000405, 0x86b50001, 0x83a40018, 0x001f8004, + 0x003f87e8, 0x2080a7e1, 0x80970770, 0x80170750, + 0x81170750, 0x81970740, 0x82a7071c, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a4000c, 0x017f87e4, + 0x81870000, 0xb6000406, 0x86b50001, 0x83a40007, + 0x001f87e4, 0x200087e8, 0x5988b80c, 0x198cb800, + 0x021fa02c, 0x021fa00b, 0x00ffb81c, 0x005ff015, + 0x90420600, 0x003f87e0, 0x001ff002, 0x2060b801, + 0x90630800, 0x90960a00, 0x001ff003, 0x003ff004, + 0x20a0b801, 0x90a50900, 0x00000000, 0x001ff005, + 0x009fa000, 0x00ffb81d, 0x001f8004, 0x5c21b800, + 0x5847b800, 0x1821b802, 0x942100ff, 0x2080a7e1, + 0x00ffb81d, 0x00000000, 0x00000000, 0x00000000, + 0x015f400e, 0x944a4000, 0xb0024000, 0xb420001e, + 0x954abfff, 0x015f600e, 0x820f001f, 0x802f001f, + 0x81470000, 0x015f23f9, 0x015fb0ba, 0x8057ffff, + 0x80770000, 0x82970400, 0x82d7ffff, 0x82f70000, + 0x81df0000, 0x00000000, 0x00000000, 0xb6000702, + 0xb6000001, 0x029fa02a, 0x81df0004, 0x80275480, + 0x005fb801, 0x8033001f, 0x9821c000, 0x803effe0, + 0x90212000, 0x803effe4, 0x80d9ff80, 0x00df6001, + 0x814775e8, 0x015fb008, 0x003f0324, 0xb0010000, + 0xb420007e, 0x8344ebde, 0xb0180000, 0xb4000004, + 0x011f400e, 0x1908b818, 0x011f600e, 0x00ffb81f, + 0x8344f1df, 0xb00b0000, 0xb4000006, 0x023f400e, + 0x9a310002, 0x023f600e, 0x82270000, 0x023f2012, + 0x00ffb81f, 0x8364ed72, 0x82270000, 0x023f2011, + 0x80070000, 0x80170800, 0x81df0000, 0x00000000, + 0x00000000, 0xb6002002, 0xb6003001, 0x001fa020, + 0x81df0004, 0x82270000, 0x003fb811, 0x02bf9006, + 0x5aa3b815, 0x82338000, 0x1a31b815, 0x003fb811, + 0x8067e950, 0x5c62b803, 0x81f50000, 0x019f4193, + 0x0267b80c, 0xadcc0010, 0x80170800, 0x80130000, + 0x9800f872, 0x001fa020, 0x80134e1f, 0x98000001, + 0x001fa020, 0x59d0b80e, 0x81150010, 0x1908b80e, + 0x001fa028, 0x858c0001, 0x5e01b80c, 0x5e25b810, + 0x81df0000, 0x00000000, 0x00000000, 0xb6310006, + 0xb6002005, 0x81150010, 0x5910b808, 0x00000000, + 0x81350010, 0x1808a029, 0x9630001f, 0xb0110000, + 0xb4000006, 0xb6310005, 0x81150010, 0x5910b808, + 0x00000000, 0x81350010, 0x1808a029, 0x81df0004, + 0x962c0001, 0xb0110000, 0xb4000003, 0x81150010, + 0x5910b808, 0x001fa028, 0x019f9006, 0x958cffff, + 0x00df4193, 0x58c1b806, 0x118cb806, 0xb00ce000, + 0xb4800002, 0x858ce000, 0x918cc000, 0x8153001f, + 0x118cb80a, 0x819effec, 0x019fb006, 0x015f4193, + 0x5941b80a, 0x019f90cb, 0x118cb80a, 0x019fb0cb, + 0x019f90ba, 0x918c0001, 0x019fb0ba, 0xb00c0002, + 0xb4200016, 0x019f400e, 0x940c8000, 0xb0008000, + 0xb4200012, 0x958c7fff, 0x019f600e, 0x80070000, + 0x800600a0, 0x80073da1, 0x800600a1, 0x801bff60, + 0x00000000, 0x801eff60, 0x00000000, 0x801bff60, + 0x00000000, 0x801eff60, 0x80130001, 0x98003da1, + 0x800600a1, 0x80070001, 0x800600a0, 0x003f0324, + 0x90210001, 0xb0010005, 0xb4a00001, 0x80270000, + 0x003f2324, 0x00ffb81f, 0x00000000, 0x00000000, + 0x003f03f9, 0x009f0324, 0x84840001, 0xb0010000, + 0xb4000011, 0x815bb3f0, 0x81070000, 0x81270bf4, + 0xb00a0000, 0xb4000002, 0x81070c00, 0x81271800, + 0x802500a5, 0x806500a5, 0x3001b803, 0xb420fffc, + 0x9421ffff, 0x3001b808, 0xb480000b, 0x3001b809, + 0xb4a00032, 0xb5000008, 0xb0040000, 0xb4200003, + 0x802717ff, 0x81470000, 0xb5000003, 0x80270001, + 0x003f23f9, 0x81470c00, 0xb0040000, 0xb4200001, + 0x8384fbf4, 0x80af001f, 0x808f0002, 0x806f0000, + 0x807bbf34, 0x5d22b80a, 0x81df0000, 0x00000000, + 0x00000000, 0xb600080a, 0x00cfb803, 0x013fb0bc, + 0x5922b809, 0x01afb809, 0x013f90bc, 0x0047b86f, + 0xb0020001, 0xb4c0fffd, 0x90630020, 0x91290060, + 0x81df0004, 0x808f0000, 0x813bb3f8, 0x80270001, + 0xb0090001, 0xb4000002, 0x802600a0, 0x803eb3f8, + 0x81270c00, 0xb00a0000, 0xb4000001, 0x81270000, + 0x813eb3f0, 0xb0030800, 0xb4800001, 0x80670200, + 0x807ebf34, 0x80270001, 0x003f2013, 0x00ffb81b, + +}; + +static u32 AC3Ucode1f8000[] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00020000, 0xffff0005, 0xffffffff, + 0x00050001, 0xffffffff, 0xffffffff, 0x00020000, + 0xffff0005, 0xffffffff, 0x00010000, 0x00050002, + 0xffffffff, 0x00020000, 0x00050003, 0xffffffff, + 0x00010000, 0x00030002, 0xffff0005, 0x00020000, + 0x00040003, 0xffff0005, 0x00010000, 0x00030002, + 0x00050004, 0x0019000d, 0x003d0025, 0x00250019, + 0x00fd003d, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x007fffff, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00000000, 0x007fffff, 0x00000000, + 0x00000000, 0x00000000, 0x007fffff, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x007fffff, + 0x007fffff, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x007fffff, 0x007fffff, 0x00000000, + 0x00000000, 0x00000000, 0x007fffff, 0x00000000, + 0x00000000, 0x00599999, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00599999, + 0x007fffff, 0x00599999, 0x00000000, 0x00599999, + 0x00000000, 0x00000000, 0x00000000, 0x00599999, + 0x00000000, 0x00599999, 0x007fffff, 0x00000000, + 0x00599999, 0x00599999, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00599999, 0x00599999, + 0x007fffff, 0x007fffff, 0x00000000, 0x00599999, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00599999, 0x007fffff, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00000000, 0x007fffff, 0x00000000, + 0x00000000, 0x00000000, 0x007fffff, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x007fffff, + 0x007fffff, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x007fffff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x007fffff, 0x00000000, + 0x007fffff, 0x00000000, 0x007fffff, 0x00400000, + 0x00200000, 0x00100000, 0x00080000, 0x00040000, + 0x00020000, 0x00010000, 0x00008000, 0x00004000, + 0x00002000, 0x00001000, 0x00000800, 0x00000400, + 0x00000200, 0x00000100, 0x00000080, 0x00000040, + 0x00000020, 0x00000010, 0x00000008, 0x00000004, + 0x00000002, 0x00000001, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00010002, + 0x00030002, 0x00030002, 0x00030002, 0x00000000, + 0x00000000, 0x00010001, 0x00020002, 0x4000a000, + 0xe000a000, 0xf000b000, 0xf800b800, 0x005a8279, + 0x004c1bf8, 0x00400000, 0x004c1bf8, 0x005a8279, + 0x00400000, 0x00000000, 0x00400000, 0x03020100, + 0x00000000, 0x00000080, 0x00000020, 0x00000008, + 0x00000000, 0x00000001, 0x00010001, 0x10081000, + 0x10041000, 0x10081004, 0x10081008, 0x10081008, + 0x00000000, 0x00000000, 0x00000000, 0xff80000a, + 0xff80031f, 0xff800b24, 0xff801818, 0xff8029fa, + 0xff8040c9, 0xff805c86, 0xff807d2e, 0xff80a2c1, + 0xff80cd3c, 0xff80fc9f, 0xff8130e8, 0xff816a14, + 0xff81a821, 0xff81eb0e, 0xff8232d6, 0xff827f79, + 0xff82d0f2, 0xff83273e, 0xff83825b, 0xff83e244, + 0xff8446f7, 0xff84b06e, 0xff851ea6, 0xff85919b, + 0xff860949, 0xff8685aa, 0xff8706ba, 0xff878c74, + 0xff8816d3, 0xff88a5d1, 0xff89396a, 0xff89d196, + 0xff8a6e51, 0xff8b0f94, 0xff8bb55a, 0xff8c5f9b, + 0xff8d0e51, 0xff8dc176, 0xff8e7902, 0xff8f34ef, + 0xff8ff535, 0xff90b9cc, 0xff9182ae, 0xff924fd3, + 0xff932132, 0xff93f6c3, 0xff94d07f, 0xff95ae5d, + 0xff969054, 0xff97765b, 0xff98606a, 0xff994e78, + 0xff9a407c, 0xff9b366b, 0xff9c303e, 0xff9d2de9, + 0xff9e2f64, 0xff9f34a4, 0xffa03da0, 0xffa14a4c, + 0xffa25aa0, 0xffa36e8f, 0xffa48610, 0xffa5a118, + 0xffa6bf9c, 0xffa7e191, 0xffa906ec, 0xffaa2fa0, + 0xffab5ba4, 0xffac8aeb, 0xffadbd6a, 0xffaef315, + 0xffb02bdf, 0xffb167be, 0xffb2a6a4, 0xffb3e886, + 0xffb52d56, 0xffb67509, 0xffb7bf92, 0xffb90ce4, + 0xffba5cf2, 0xffbbafb0, 0xffbd050f, 0xffbe5d04, + 0xffbfb780, 0xffc11477, 0xffc273db, 0xffc3d59f, + 0xffc539b4, 0xffc6a00d, 0xffc8089d, 0xffc97355, + 0xffcae027, 0xffcc4f05, 0xffcdbfe2, 0xffcf32af, + 0xffd0a75d, 0xffd21ddf, 0xffd39625, 0xffd51022, + 0xffd68bc7, 0xffd80904, 0xffd987cd, 0xffdb0810, + 0xffdc89c1, 0xffde0cd0, 0xffdf912d, 0xffe116cb, + 0xffe29d9a, 0xffe4258b, 0xffe5ae8f, 0xffe73896, + 0xffe8c392, 0xffea4f74, 0xffebdc2b, 0xffed69aa, + 0xffeef7df, 0xfff086bd, 0xfff21634, 0xfff3a634, + 0xfff536ad, 0xfff6c792, 0xfff858d1, 0xfff9ea5b, + 0xfffb7c22, 0xfffd0e16, 0xfffea026, 0xffffcdbc, + 0xfffe3ba0, 0xfffca995, 0xfffb17ac, 0xfff985f3, + 0xfff7f479, 0xfff6634f, 0xfff4d284, 0xfff34228, + 0xfff1b249, 0xfff022f7, 0xffee9442, 0xffed0638, + 0xffeb78ea, 0xffe9ec67, 0xffe860bd, 0xffe6d5fd, + 0xffe54c35, 0xffe3c374, 0xffe23bcb, 0xffe0b547, + 0xffdf2ff7, 0xffddabec, 0xffdc2933, 0xffdaa7dd, + 0xffd927f6, 0xffd7a98f, 0xffd62cb7, 0xffd4b17b, + 0xffd337ea, 0xffd1c013, 0xffd04a05, 0xffced5ce, + 0xffcd637c, 0xffcbf31d, 0xffca84c1, 0xffc91874, + 0xffc7ae45, 0xffc64641, 0xffc4e078, 0xffc37cf6, + 0xffc21bc9, 0xffc0bcff, 0xffbf60a5, 0xffbe06c9, + 0xffbcaf79, 0xffbb5ac0, 0xffba08ae, 0xffb8b94d, + 0xffb76cac, 0xffb622d8, 0xffb4dbdc, 0xffb397c6, + 0xffb256a2, 0xffb1187d, 0xffafdd62, 0xffaea55f, + 0xffad707e, 0xffac3ecc, 0xffab1054, 0xffa9e523, + 0xffa8bd44, 0xffa798c2, 0xffa677a8, 0xffa55a02, + 0xffa43fdb, 0xffa3293d, 0xffa21634, 0xffa106c9, + 0xff9ffb08, 0xff9ef2fa, 0xff9deeab, 0xff9cee23, + 0xff9bf16c, 0xff9af892, 0xff9a039c, 0xff991295, + 0xff982586, 0xff973c78, 0xff965774, 0xff957683, + 0xff9499ad, 0xff93c0fb, 0xff92ec75, 0xff921c24, + 0xff91500f, 0xff90883f, 0xff8fc4bb, 0xff8f058b, + 0xff8e4ab6, 0xff8d9443, 0xff8ce239, 0xff8c349f, + 0xff8b8b7d, 0xff8ae6d7, 0xff8a46b5, 0xff89ab1e, + 0xff891416, 0xff8881a3, 0xff87f3cc, 0xff876a96, + 0xff86e606, 0xff866621, 0xff85eaed, 0xff85746d, + 0xff8502a6, 0xff84959e, 0xff842d57, 0xff83c9d7, + 0xff836b20, 0xff831138, 0xff82bc20, 0xff826bdc, + 0xff822070, 0xff81d9de, 0xff819829, 0xff815b54, + 0xff812360, 0xff80f051, 0xff80c228, 0xff8098e6, + 0xff80748e, 0xff805521, 0xff803a9f, 0xff80250b, + 0xff801464, 0xff8008ad, 0xff8001e4, 0xff800027, + 0xff800c7e, 0xff802c8f, 0xff806056, 0xff80a7cb, + 0xff8102e4, 0xff817191, 0xff81f3c3, 0xff828964, + 0xff83325f, 0xff83ee98, 0xff84bdf3, 0xff85a04f, + 0xff86958b, 0xff879d7f, 0xff88b804, 0xff89e4ee, + 0xff8b240e, 0xff8c7533, 0xff8dd82a, 0xff8f4cbb, + 0xff90d2ad, 0xff9269c4, 0xff9411c1, 0xff95ca62, + 0xff979365, 0xff996c81, 0xff9b5570, 0xff9d4de4, + 0xff9f5590, 0xffa16c24, 0xffa3914e, 0xffa5c4b8, + 0xffa8060d, 0xffaa54f3, 0xffacb10e, 0xffaf1a03, + 0xffb18f70, 0xffb410f7, 0xffb69e33, 0xffb936c0, + 0xffbbda37, 0xffbe8830, 0xffc14042, 0xffc40201, + 0xffc6cd00, 0xffc9a0d2, 0xffcc7d05, 0xffcf612b, + 0xffd24ccf, 0xffd53f80, 0xffd838c8, 0xffdb3833, + 0xffde3d49, 0xffe14795, 0xffe4569d, 0xffe769e9, + 0xffea80ff, 0xffed9b67, 0xfff0b8a4, 0xfff3d83c, + 0xfff6f9b5, 0xfffa1c91, 0xfffd4056, 0xffff9b78, + 0xfffc7756, 0xfff953c0, 0xfff63130, 0xfff31025, + 0xffeff117, 0xffecd484, 0xffe9bae5, 0xffe6a4b6, + 0xffe39270, 0xffe0848b, 0xffdd7b82, 0xffda77cb, + 0xffd779de, 0xffd48231, 0xffd19138, 0xffcea769, + 0xffcbc535, 0xffc8eb10, 0xffc61969, 0xffc350af, + 0xffc09151, 0xffbddbbb, 0xffbb3059, 0xffb88f92, + 0xffb5f9d0, 0xffb36f78, 0xffb0f0ef, 0xffae7e96, + 0xffac18cf, 0xffa9bff9, 0xffa7746f, 0xffa5368c, + 0xffa306aa, 0xffa0e51e, 0xff9ed23c, 0xff9cce56, + 0xff9ad9bc, 0xff98f4bc, 0xff971f9f, 0xff955aae, + 0xff93a62f, 0xff920266, 0xff906f92, 0xff8eedf3, + 0xff8d7dc4, 0xff8c1f3c, 0xff8ad294, 0xff8997fd, + 0xff886fa8, 0xff8759c3, 0xff865679, 0xff8565f2, + 0xff848852, 0xff83bdbd, 0xff830651, 0xff82622b, + 0xff81d163, 0xff815411, 0xff80ea47, 0xff809416, + 0xff80518b, 0xff8022b1, 0xff80078e, 0x00000475, + 0x000007fe, 0x00000c02, 0x000010a3, 0x000015f5, + 0x00001c08, 0x000022ed, 0x00002ab5, 0x00003371, + 0x00003d32, 0x0000480a, 0x0000540d, 0x0000614b, + 0x00006fda, 0x00007fcd, 0x00009138, 0x0000a431, + 0x0000b8cc, 0x0000cf1f, 0x0000e741, 0x00010148, + 0x00011d4b, 0x00013b61, 0x00015ba2, 0x00017e25, + 0x0001a302, 0x0001ca51, 0x0001f42c, 0x000220a9, + 0x00024fe2, 0x000281f0, 0x0002b6ea, 0x0002eee9, + 0x00032a07, 0x0003685a, 0x0003a9fc, 0x0003ef04, + 0x0004378a, 0x000483a5, 0x0004d36d, 0x000526f7, + 0x00057e5b, 0x0005d9ae, 0x00063904, 0x00069c74, + 0x00070410, 0x00076feb, 0x0007e01a, 0x000854ac, + 0x0008cdb3, 0x00094b40, 0x0009cd61, 0x000a5425, + 0x000adf98, 0x000b6fc8, 0x000c04bf, 0x000c9e87, + 0x000d3d2a, 0x000de0ae, 0x000e891a, 0x000f3674, + 0x000fe8c0, 0x00109fff, 0x00115c34, 0x00121d5d, + 0x0012e37b, 0x0013ae89, 0x00147e84, 0x00155366, + 0x00162d27, 0x00170bbf, 0x0017ef23, 0x0018d748, + 0x0019c421, 0x001ab59f, 0x001babb2, 0x001ca648, + 0x001da54f, 0x001ea8b0, 0x001fb058, 0x0020bc2d, + 0x0021cc18, 0x0022dffd, 0x0023f7c2, 0x00251348, + 0x00263272, 0x00275520, 0x00287b31, 0x0029a482, + 0x002ad0f1, 0x002c0059, 0x002d3294, 0x002e677c, + 0x002f9ee8, 0x0030d8b1, 0x003214ac, 0x003352b0, + 0x00349290, 0x0035d422, 0x00371738, 0x00385ba5, + 0x0039a13b, 0x003ae7cc, 0x003c2f2a, 0x003d7725, + 0x003ebf8d, 0x00400834, 0x004150e9, 0x0042997d, + 0x0043e1c0, 0x00452981, 0x00467092, 0x0047b6c3, + 0x0048fbe3, 0x004a3fc6, 0x004b823b, 0x004cc316, + 0x004e0228, 0x004f3f45, 0x00507a40, 0x0051b2ef, + 0x0052e925, 0x00541cba, 0x00554d85, 0x00567b5e, + 0x0057a61d, 0x0058cd9e, 0x0059f1bb, 0x005b1252, + 0x005c2f3f, 0x005d4863, 0x005e5d9d, 0x005f6ed0, + 0x00607bde, 0x006184ad, 0x00628923, 0x00638927, + 0x006484a3, 0x00657b81, 0x00666daf, 0x00675b19, + 0x006843b1, 0x00692767, 0x006a062d, 0x006adff9, + 0x006bb4c2, 0x006c847d, 0x006d4f27, 0x006e14b8, + 0x006ed52f, 0x006f9089, 0x007046c6, 0x0070f7e9, + 0x0071a3f3, 0x00724aea, 0x0072ecd3, 0x007389b6, + 0x0074219d, 0x0074b490, 0x0075429b, 0x0075cbcc, + 0x00765031, 0x0076cfd8, 0x00774ad3, 0x0077c132, + 0x00783308, 0x0078a068, 0x00790968, 0x00796e1c, + 0x0079ce9a, 0x007a2af9, 0x007a8350, 0x007ad7b8, + 0x007b2849, 0x007b751d, 0x007bbe4c, 0x007c03f1, + 0x007c4625, 0x007c8504, 0x007cc0a8, 0x007cf92c, + 0x007d2eaa, 0x007d613e, 0x007d9101, 0x007dbe10, + 0x007de883, 0x007e1076, 0x007e3603, 0x007e5943, + 0x007e7a4f, 0x007e9942, 0x007eb633, 0x007ed13a, + 0x007eea6f, 0x007f01ea, 0x007f17c0, 0x007f2c08, + 0x007f3ed7, 0x007f5043, 0x007f605e, 0x007f6f3c, + 0x007f7cf1, 0x007f898e, 0x007f9525, 0x007f9fc6, + 0x007fa982, 0x007fb268, 0x007fba86, 0x007fc1eb, + 0x007fc8a4, 0x007fcebe, 0x007fd443, 0x007fd941, + 0x007fddc2, 0x007fe1cf, 0x007fe572, 0x007fe8b4, + 0x007feb9e, 0x007fee36, 0x007ff086, 0x007ff293, + 0x007ff463, 0x007ff5fd, 0x007ff765, 0x007ff8a1, + 0x007ff9b6, 0x007ffaa7, 0x007ffb79, 0x007ffc2f, + 0x007ffccb, 0x007ffd52, 0x007ffdc6, 0x007ffe28, + 0x007ffe7b, 0x007ffec2, 0x007ffefd, 0x007fff2f, + 0x007fff58, 0x007fff7b, 0x007fff97, 0x007fffae, + 0x007fffc0, 0x007fffcf, 0x007fffdb, 0x007fffe4, + 0x007fffec, 0x007ffff1, 0x007ffff6, 0x007ffff9, + 0x007ffffb, 0x007ffffd, 0x007ffffe, 0x007fffff, + 0x007fffff, 0x007fffff, 0x007fffff, 0xff800000, + 0x00000000, 0xffa57d86, 0x005a827a, 0xff89be51, + 0x0030fbc5, 0xffcf043b, 0x007641af, 0xff8275a1, + 0x0018f8b8, 0xffb8e313, 0x006a6d99, 0xff959267, + 0x00471ced, 0xffe70748, 0x007d8a5f, 0xff809dc9, + 0x000c8bd3, 0xffaecc33, 0x0062f202, 0xff8f1d34, + 0x003c56ba, 0xffdad7f4, 0x007a7d05, 0xff8582fb, + 0x0025280c, 0xffc3a946, 0x0070e2cc, 0xff9d0dfe, + 0x005133cd, 0xfff3742d, 0x007f6237, 0xff802778, + 0x000647d9, 0xffaa0a5b, 0x005ed77d, 0xff8c4a14, + 0x0036ba20, 0xffd4e0cb, 0x00788484, 0xff83d604, + 0x001f19f9, 0xffbe31e2, 0x006dca0d, 0xff99307f, + 0x004c3fe0, 0xffed37f0, 0x007e9d56, 0xff8162aa, + 0x0012c810, 0xffb3c020, 0x0066cf81, 0xff9235f3, + 0x0041ce1e, 0xffe0e607, 0x007c29fc, 0xff877b7c, + 0x002b1f35, 0xffc945e0, 0x0073b5ec, 0xffa12883, + 0x0055f5a5, 0xfff9b827, 0x007fd888, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + +}; + +static u32 AC3Ucode1fe000[] = { + 0x00000000, 0x03020102, 0x05040403, 0x00400040, + 0x00500050, 0x00600060, 0x00700070, 0x00800080, + 0x00a000a0, 0x00c000c0, 0x00e000e0, 0x01000100, + 0x01400140, 0x01800180, 0x01c001c0, 0x02000200, + 0x02800280, 0x03000300, 0x03800380, 0x04000400, + 0x04800480, 0x05000500, 0x00460045, 0x00580057, + 0x00690068, 0x007a0079, 0x008c008b, 0x00af00ae, + 0x00d100d0, 0x00f400f3, 0x01170116, 0x015d015c, + 0x01a201a1, 0x01e801e7, 0x022e022d, 0x02b902b8, + 0x03440343, 0x03d003cf, 0x045b045a, 0x04e604e5, + 0x05720571, 0x00600060, 0x00780078, 0x00900090, + 0x00a800a8, 0x00c000c0, 0x00f000f0, 0x01200120, + 0x01500150, 0x01800180, 0x01e001e0, 0x02400240, + 0x02a002a0, 0x03000300, 0x03c003c0, 0x04800480, + 0x05400540, 0x06000600, 0x06c006c0, 0x07800780, + 0x7b67533f, 0x1513110f, 0x04d80540, 0x04100478, + 0x07000000, 0x0b000900, 0x02b002f0, 0x02300270, + 0x017001f0, 0xf80000f0, 0x01000080, 0x02000180, + 0x03000280, 0x04000380, 0x2725231f, 0x2c2b2a29, + 0x2e2e2d2d, 0x30302f2f, 0x04030201, 0x08070605, + 0x0c0b0a09, 0x100f0e0d, 0x14131211, 0x18171615, + 0x1c1b1a19, 0x2825221f, 0x37312e2b, 0x4f49433d, + 0x796d6155, 0xcdb59d85, 0x0000fde5, 0x3d3e3f40, + 0x393a3b3c, 0x35363738, 0x32333434, 0x2f2f3031, + 0x2c2c2d2e, 0x29292a2b, 0x26262728, 0x23242425, + 0x21212223, 0x1e1f2020, 0x1c1d1d1e, 0x1a1b1b1c, + 0x1819191a, 0x16171718, 0x15151516, 0x13131414, + 0x12121213, 0x10111111, 0x0f0f1010, 0x0e0e0e0f, + 0x0d0d0d0d, 0x0c0c0c0c, 0x0b0b0b0b, 0x0a0a0a0a, + 0x0909090a, 0x08080909, 0x08080808, 0x07070707, + 0x06060707, 0x06060606, 0x05050606, 0x05050505, + 0x04040505, 0x04040404, 0x04040404, 0x03030304, + 0x03030303, 0x03030303, 0x02030303, 0x02020202, + 0x02020202, 0x02020202, 0x02020202, 0x01010202, + 0x01010101, 0x01010101, 0x01010101, 0x01010101, + 0x01010101, 0x01010101, 0x01010101, 0x00000101, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x04d004d0, + 0x04000440, 0x03c003e0, 0x03b003b0, 0x03a003a0, + 0x03a003a0, 0x039003a0, 0x03900390, 0x03800380, + 0x03700370, 0x03600360, 0x03500350, 0x03400340, + 0x03200330, 0x03000310, 0x02f002f0, 0x02f002f0, + 0x03100300, 0x03900340, 0x042003e0, 0x04900460, + 0x046004a0, 0x04400440, 0x08000520, 0x08400840, + 0x04f004f0, 0x04100460, 0x03d003e0, 0x03b003c0, + 0x03a003b0, 0x03a003a0, 0x03a003a0, 0x03900390, + 0x03800390, 0x03800380, 0x03700370, 0x03600360, + 0x03500350, 0x03400340, 0x03100320, 0x02f00300, + 0x02f002f0, 0x030002f0, 0x03500320, 0x03e00390, + 0x04500420, 0x049004a0, 0x04400460, 0x06300480, + 0x08400840, 0x05800580, 0x045004b0, 0x03f00420, + 0x03d003e0, 0x03b003c0, 0x03b003b0, 0x03a003a0, + 0x03a003a0, 0x03a003a0, 0x03a003a0, 0x03900390, + 0x03900390, 0x03800380, 0x03700380, 0x03500360, + 0x03300340, 0x03100320, 0x02f00300, 0x02f002f0, + 0x03100300, 0x03500330, 0x041003c0, 0x04a00470, + 0x04400460, 0x04e00450, 0xffaaaaab, 0x00000000, + 0x00555555, 0xff99999a, 0xffcccccd, 0x00000000, + 0x00333333, 0x00666666, 0xff924925, 0xffb6db6e, + 0xffdb6db7, 0x00000000, 0x00249249, 0x00492492, + 0x006db6db, 0xff8ba2e9, 0xffa2e8ba, 0xffba2e8c, + 0xffd1745d, 0xffe8ba2f, 0x00000000, 0x001745d1, + 0x002e8ba3, 0x0045d174, 0x005d1746, 0x00745d17, + 0xff888889, 0xff99999a, 0xffaaaaab, 0xffbbbbbc, + 0xffcccccd, 0xffddddde, 0xffeeeeef, 0x00000000, + 0x00111111, 0x00222222, 0x00333333, 0x00444444, + 0x00555555, 0x00666666, 0x00777777, 0x08070605, + 0x0c0b0a09, 0x10100e0e, 0x00000010, 0x00000000, + 0x00000010, 0x00000020, 0x00000100, 0x00000110, + 0x00000120, 0x00000200, 0x00000210, 0x00000220, + 0x00001000, 0x00001010, 0x00001020, 0x00001100, + 0x00001110, 0x00001120, 0x00001200, 0x00001210, + 0x00001220, 0x00002000, 0x00002010, 0x00002020, + 0x00002100, 0x00002110, 0x00002120, 0x00002200, + 0x00002210, 0x00002220, 0x00000000, 0x00000010, + 0x00000020, 0x00000030, 0x00000040, 0x00000100, + 0x00000110, 0x00000120, 0x00000130, 0x00000140, + 0x00000200, 0x00000210, 0x00000220, 0x00000230, + 0x00000240, 0x00000300, 0x00000310, 0x00000320, + 0x00000330, 0x00000340, 0x00000400, 0x00000410, + 0x00000420, 0x00000430, 0x00000440, 0x00001000, + 0x00001010, 0x00001020, 0x00001030, 0x00001040, + 0x00001100, 0x00001110, 0x00001120, 0x00001130, + 0x00001140, 0x00001200, 0x00001210, 0x00001220, + 0x00001230, 0x00001240, 0x00001300, 0x00001310, + 0x00001320, 0x00001330, 0x00001340, 0x00001400, + 0x00001410, 0x00001420, 0x00001430, 0x00001440, + 0x00002000, 0x00002010, 0x00002020, 0x00002030, + 0x00002040, 0x00002100, 0x00002110, 0x00002120, + 0x00002130, 0x00002140, 0x00002200, 0x00002210, + 0x00002220, 0x00002230, 0x00002240, 0x00002300, + 0x00002310, 0x00002320, 0x00002330, 0x00002340, + 0x00002400, 0x00002410, 0x00002420, 0x00002430, + 0x00002440, 0x00003000, 0x00003010, 0x00003020, + 0x00003030, 0x00003040, 0x00003100, 0x00003110, + 0x00003120, 0x00003130, 0x00003140, 0x00003200, + 0x00003210, 0x00003220, 0x00003230, 0x00003240, + 0x00003300, 0x00003310, 0x00003320, 0x00003330, + 0x00003340, 0x00003400, 0x00003410, 0x00003420, + 0x00003430, 0x00003440, 0x00004000, 0x00004010, + 0x00004020, 0x00004030, 0x00004040, 0x00004100, + 0x00004110, 0x00004120, 0x00004130, 0x00004140, + 0x00004200, 0x00004210, 0x00004220, 0x00004230, + 0x00004240, 0x00004300, 0x00004310, 0x00004320, + 0x00004330, 0x00004340, 0x00004400, 0x00004410, + 0x00004420, 0x00004430, 0x00004440, 0x00000000, + 0x00000100, 0x00000200, 0x00000300, 0x00000400, + 0x00000500, 0x00000600, 0x00000700, 0x00000800, + 0x00000900, 0x00000a00, 0x00001000, 0x00001100, + 0x00001200, 0x00001300, 0x00001400, 0x00001500, + 0x00001600, 0x00001700, 0x00001800, 0x00001900, + 0x00001a00, 0x00002000, 0x00002100, 0x00002200, + 0x00002300, 0x00002400, 0x00002500, 0x00002600, + 0x00002700, 0x00002800, 0x00002900, 0x00002a00, + 0x00003000, 0x00003100, 0x00003200, 0x00003300, + 0x00003400, 0x00003500, 0x00003600, 0x00003700, + 0x00003800, 0x00003900, 0x00003a00, 0x00004000, + 0x00004100, 0x00004200, 0x00004300, 0x00004400, + 0x00004500, 0x00004600, 0x00004700, 0x00004800, + 0x00004900, 0x00004a00, 0x00005000, 0x00005100, + 0x00005200, 0x00005300, 0x00005400, 0x00005500, + 0x00005600, 0x00005700, 0x00005800, 0x00005900, + 0x00005a00, 0x00006000, 0x00006100, 0x00006200, + 0x00006300, 0x00006400, 0x00006500, 0x00006600, + 0x00006700, 0x00006800, 0x00006900, 0x00006a00, + 0x00007000, 0x00007100, 0x00007200, 0x00007300, + 0x00007400, 0x00007500, 0x00007600, 0x00007700, + 0x00007800, 0x00007900, 0x00007a00, 0x00008000, + 0x00008100, 0x00008200, 0x00008300, 0x00008400, + 0x00008500, 0x00008600, 0x00008700, 0x00008800, + 0x00008900, 0x00008a00, 0x00009000, 0x00009100, + 0x00009200, 0x00009300, 0x00009400, 0x00009500, + 0x00009600, 0x00009700, 0x00009800, 0x00009900, + 0x00009a00, 0x0000a000, 0x0000a100, 0x0000a200, + 0x0000a300, 0x0000a400, 0x0000a500, 0x0000a600, + 0x0000a700, 0x0000a800, 0x0000a900, 0x0000aa00, + 0xff800000, 0xff800000, 0xffb82995, 0xffaf5d75, + 0xffa57d87, 0xff9a6806, 0xff8df708, 0xff800000, + 0xffb82995, 0xffaf5d75, 0xffa57d87, 0xff9a6806, + 0xff8df708, 0xff800000, 0xffb82995, 0xffaf5d75, + 0xffa57d87, 0xff9a6806, 0xff8df708, 0xff800000, + 0xffb82995, 0xffaf5d75, 0xffa57d87, 0xff9a6806, + 0xff8df708, 0xff800000, 0xffb82995, 0xffaf5d75, + 0xffa57d87, 0xff9a6806, 0xff8df708, 0xff800000, + 0xfffb0000, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, + 0xfffdfffd, 0xfffdfffd, 0xfffdfffd, 0xfffefffe, + 0xfffefffe, 0xfffefffe, 0xffffffff, 0xffffffff, + 0xffffffff, 0x00000000, 0x00000000, 0x00000000, + 0x80050000, 0x000a800f, 0x001e801b, 0x80110014, + 0x00368033, 0x8039003c, 0x802d0028, 0x00228027, + 0x00668063, 0x8069006c, 0x807d0078, 0x00728077, + 0x80550050, 0x005a805f, 0x004e804b, 0x80410044, + 0x00c680c3, 0x80c900cc, 0x80dd00d8, 0x00d280d7, + 0x80f500f0, 0x00fa80ff, 0x00ee80eb, 0x80e100e4, + 0x80a500a0, 0x00aa80af, 0x00be80bb, 0x80b100b4, + 0x00968093, 0x8099009c, 0x808d0088, 0x00828087, + 0x01868183, 0x8189018c, 0x819d0198, 0x01928197, + 0x81b501b0, 0x01ba81bf, 0x01ae81ab, 0x81a101a4, + 0x81e501e0, 0x01ea81ef, 0x01fe81fb, 0x81f101f4, + 0x01d681d3, 0x81d901dc, 0x81cd01c8, 0x01c281c7, + 0x81450140, 0x014a814f, 0x015e815b, 0x81510154, + 0x01768173, 0x8179017c, 0x816d0168, 0x01628167, + 0x01268123, 0x8129012c, 0x813d0138, 0x01328137, + 0x81150110, 0x011a811f, 0x010e810b, 0x81010104, + 0x03068303, 0x8309030c, 0x831d0318, 0x03128317, + 0x83350330, 0x033a833f, 0x032e832b, 0x83210324, + 0x83650360, 0x036a836f, 0x037e837b, 0x83710374, + 0x03568353, 0x8359035c, 0x834d0348, 0x03428347, + 0x83c503c0, 0x03ca83cf, 0x03de83db, 0x83d103d4, + 0x03f683f3, 0x83f903fc, 0x83ed03e8, 0x03e283e7, + 0x03a683a3, 0x83a903ac, 0x83bd03b8, 0x03b283b7, + 0x83950390, 0x039a839f, 0x038e838b, 0x83810384, + 0x82850280, 0x028a828f, 0x029e829b, 0x82910294, + 0x02b682b3, 0x82b902bc, 0x82ad02a8, 0x02a282a7, + 0x02e682e3, 0x82e902ec, 0x82fd02f8, 0x02f282f7, + 0x82d502d0, 0x02da82df, 0x02ce82cb, 0x82c102c4, + 0x02468243, 0x8249024c, 0x825d0258, 0x02528257, + 0x82750270, 0x027a827f, 0x026e826b, 0x82610264, + 0x82250220, 0x022a822f, 0x023e823b, 0x82310234, + 0x02168213, 0x8219021c, 0x820d0208, 0x02028207, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0xff800000, 0xffa57d86, 0xffa57d86, + 0xffcf043b, 0xff89be51, 0xff89be51, 0xffcf043b, + 0xffe70748, 0xff8275a1, 0xff959267, 0xffb8e313, + 0xffb8e313, 0xff959267, 0xff8275a1, 0xffe70748, + 0xfff3742d, 0xff809dc9, 0xff9d0dfe, 0xffaecc33, + 0xffc3a946, 0xff8f1d34, 0xff8582fb, 0xffdad7f4, + 0xffdad7f4, 0xff8582fb, 0xff8f1d34, 0xffc3a946, + 0xffaecc33, 0xff9d0dfe, 0xff809dc9, 0xfff3742d, + 0xfff9b827, 0xff802778, 0xffa12883, 0xffaa0a5b, + 0xffc945e0, 0xff8c4a14, 0xff877b7c, 0xffd4e0cb, + 0xffe0e607, 0xff83d604, 0xff9235f3, 0xffbe31e2, + 0xffb3c020, 0xff99307f, 0xff8162aa, 0xffed37f0, + 0xffed37f0, 0xff8162aa, 0xff99307f, 0xffb3c020, + 0xffbe31e2, 0xff9235f3, 0xff83d604, 0xffe0e607, + 0xffd4e0cb, 0xff877b7c, 0xff8c4a14, 0xffc945e0, + 0xffaa0a5b, 0xffa12883, 0xff802778, 0xfff9b827, + 0xcbcecdc4, 0xcfcac9c8, 0xc3c6c5cc, 0xc7c2c1c0, + 0x1b1e1d14, 0x1f1a1918, 0x1316151c, 0x17121110, + 0x2b2e2d24, 0x2f2a2928, 0x2326252c, 0x27222120, + 0x3b3e3d34, 0x3f3a3938, 0x3336353c, 0x37323130, + 0x0b0e0d04, 0x0f0a0908, 0x0306050c, 0x07020100, + 0xdbdeddd4, 0xdfdad9d8, 0xd3d6d5dc, 0xd7d2d1d0, + 0xebeeede4, 0xefeae9e8, 0xe3e6e5ec, 0xe7e2e1e0, + 0xfbfefdf4, 0xfffaf9f8, 0xf3f6f5fc, 0xf7f2f1f0, + 0x4b4e4d44, 0x4f4a4948, 0x4346454c, 0x47424140, + 0x9b9e9d94, 0x9f9a9998, 0x9396959c, 0x97929190, + 0xabaeada4, 0xafaaa9a8, 0xa3a6a5ac, 0xa7a2a1a0, + 0xbbbebdb4, 0xbfbab9b8, 0xb3b6b5bc, 0xb7b2b1b0, + 0x8b8e8d84, 0x8f8a8988, 0x8386858c, 0x87828180, + 0x5b5e5d54, 0x5f5a5958, 0x5356555c, 0x57525150, + 0x6b6e6d64, 0x6f6a6968, 0x6366656c, 0x67626160, + 0x7b7e7d74, 0x7f7a7978, 0x7376757c, 0x77727170, + 0x341424c4, 0x3e1e2ece, 0x3d1d2dcd, 0x3b1b2bcb, + 0xb494a444, 0xbe9eae4e, 0xbd9dad4d, 0xbb9bab4b, + 0xf4d4e404, 0xfedeee0e, 0xfddded0d, 0xfbdbeb0b, + 0x74546484, 0x7e5e6e8e, 0x7d5d6d8d, 0x7b5b6b8b, + 0x3c1c2ccc, 0x361626c6, 0x351525c5, 0x331323c3, + 0xbc9cac4c, 0xb696a646, 0xb595a545, 0xb393a343, + 0xfcdcec0c, 0xf6d6e606, 0xf5d5e505, 0xf3d3e303, + 0x7c5c6c8c, 0x76566686, 0x75556585, 0x73536383, + 0x381828c8, 0x3a1a2aca, 0x391929c9, 0x3f1f2fcf, + 0xb898a848, 0xba9aaa4a, 0xb999a949, 0xbf9faf4f, + 0xf8d8e808, 0xfadaea0a, 0xf9d9e909, 0xffdfef0f, + 0x78586888, 0x7a5a6a8a, 0x79596989, 0x7f5f6f8f, + 0x301020c0, 0x321222c2, 0x311121c1, 0x371727c7, + 0xb090a040, 0xb292a242, 0xb191a141, 0xb797a747, + 0xf0d0e000, 0xf2d2e202, 0xf1d1e101, 0xf7d7e707, + 0x70506080, 0x72526282, 0x71516181, 0x77576787, + 0x05040100, 0x15141110, 0x25242120, 0x35343130, + 0x85848180, 0x95949190, 0xa5a4a1a0, 0xb5b4b1b0, + 0xc0408000, 0xe060a020, 0xd0509010, 0xf070b030, + 0xc8488808, 0xe868a828, 0xd8589818, 0xf878b838, + 0xc4448404, 0xe464a424, 0xd4549414, 0xf474b434, + 0xcc4c8c0c, 0xec6cac2c, 0xdc5c9c1c, 0xfc7cbc3c, + 0xc2428202, 0xe262a222, 0xd2529212, 0xf272b232, + 0xca4a8a0a, 0xea6aaa2a, 0xda5a9a1a, 0xfa7aba3a, + 0xc6468606, 0xe666a626, 0xd6569616, 0xf676b636, + 0xce4e8e0e, 0xee6eae2e, 0xde5e9e1e, 0xfe7ebe3e, + 0xc1418101, 0xe161a121, 0xd1519111, 0xf171b131, + 0xc9498909, 0xe969a929, 0xd9599919, 0xf979b939, + 0xc5458505, 0xe565a525, 0xd5559515, 0xf575b535, + 0xcd4d8d0d, 0xed6dad2d, 0xdd5d9d1d, 0xfd7dbd3d, + 0xc3438303, 0xe363a323, 0xd3539313, 0xf373b333, + 0xcb4b8b0b, 0xeb6bab2b, 0xdb5b9b1b, 0xfb7bbb3b, + 0xc7478707, 0xe767a727, 0xd7579717, 0xf777b737, + 0xcf4f8f0f, 0xef6faf2f, 0xdf5f9f1f, 0xff7fbf3f, + 0x1045a3e2, 0x000000f4, 0x263b7333, 0x766b2363, + 0x2b367e3e, 0x7b662e6e, 0x06db93d3, 0x964b0343, + 0x0bd69ede, 0x9b460e4e, 0x825f1757, 0x12cf87c7, + 0x8f521a5a, 0x1fc28aca, 0x00d199d9, 0x90410949, + 0x01d098d8, 0x91400848, 0x24357d3d, 0x74652d6d, + 0x25347c3c, 0x75642c6c, 0x04d59ddd, 0x94450d4d, + 0x05d49cdc, 0x95440c4c, 0x80511959, 0x10c189c9, + 0x81501858, 0x11c088c8, 0x02df97d7, 0x924f0747, + 0x0fd29ada, 0x9f420a4a, 0x865b1353, 0x16cb83c3, + 0x8b561e5e, 0x1bc68ece, 0xa6bbf3b3, 0xf6eba3e3, + 0xabb6febe, 0xfbe6aeee, 0x223f7737, 0x726f2767, + 0x2f327a3a, 0x7f622a6a, 0xa0b1f9b9, 0xf0e1a9e9, + 0xa1b0f8b8, 0xf1e0a8e8, 0x84551d5d, 0x14c58dcd, + 0x85541c5c, 0x15c48ccc, 0xa4b5fdbd, 0xf4e5aded, + 0xa5b4fcbc, 0xf5e4acec, 0x20317939, 0x70612969, + 0x21307838, 0x71602868, 0xa2bff7b7, 0xf2efa7e7, + 0xafb2faba, 0xffe2aaea, 0x00000000, 0x00000000, +}; + +static u32 AC3Ucode1fff80[] = { + 0x0000240f, 0x007fffff, 0x007fffff, 0x00000003, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00000000, 0x00000000, 0x00000000, +}; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/ls220/ac3i2s_240.h linux.19rc3-ac4/drivers/media/video/ls220/ac3i2s_240.h --- linux.19rc3/drivers/media/video/ls220/ac3i2s_240.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/ls220/ac3i2s_240.h 2002-07-29 13:58:41.000000000 +0100 @@ -0,0 +1,2833 @@ +static u32 AC3I2S240Ucode1f1800[] = { + 0xb500000f, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xb5001197, 0x00000000, 0x00000000, 0x00000000, + 0x820f001f, 0x802f001f, 0x80070800, 0x001f6193, + 0x800500d4, 0x8053ffff, 0x9842c7ff, 0x8039ff7c, + 0x1400b802, 0x003f6000, 0x94210007, 0xb0010001, + 0xb4200001, 0x98002800, 0xb0010000, 0xb4200001, + 0x98000800, 0x805300ff, 0x1800b802, 0x800600d4, + 0x8013001f, 0x9020c000, 0x003fb006, 0x803effe0, + 0x803effe8, 0x803effec, 0x9020e000, 0x9021ffe4, + 0x9020fa00, 0x803effd0, 0x803effdc, 0x803effd8, + 0x9020fe00, 0x803effd4, 0x90400000, 0x804600a2, + 0x90421800, 0x804600a3, 0x80134099, 0x98000040, + 0x800600a6, 0x80130000, 0x98003ca1, 0x800600a1, + 0x80050080, 0x98000002, 0x80060080, 0x80070001, + 0x001f2013, 0x001f2324, 0x80070000, 0x001fb0ba, + 0x001f23f9, 0x801eb3f0, 0x80070800, 0x001f600f, + 0x80070000, 0x001f2012, 0x001fb0cb, 0x001fb010, + 0x801efff0, 0x98004000, 0x98008000, 0x001f600e, + 0x83e4012b, 0x80070000, 0x801eb3f8, 0x801eff70, + 0x800500a0, 0xb0000001, 0xb4000009, 0x80070001, + 0x800600a0, 0x80050080, 0x98000020, 0x80060080, + 0x9400ffdf, 0x80060080, 0x80070000, 0x800600a0, + 0x81df0004, 0x00000000, 0x00000000, 0x801bfff0, + 0x00000000, 0x940000ff, 0xb0000000, 0xb420004e, + 0x003f400e, 0x94010010, 0xb0000000, 0xb400fff4, + 0x838413ac, 0x003f0013, 0xb0010001, 0xb420003b, + 0x803bffe8, 0x801bffec, 0x00000000, 0x3001b800, + 0xb4600001, 0x90212000, 0x0421b800, 0x005f4193, + 0x5841b802, 0x3001b802, 0xb460000d, 0x80050086, + 0x005f9016, 0xb0020000, 0xb4200002, 0x001fb016, + 0xb500ffdf, 0x0420b802, 0xb0010b50, 0xb4a0ffdc, + 0x80070000, 0x001fb016, 0x83e400f5, 0xb500ffd8, + 0x80070000, 0x001fb016, 0x001f400e, 0x9400000f, + 0xb0000000, 0xb4000014, 0xb0000001, 0xb4000010, + 0x003f400e, 0x9421fff0, 0x003f600e, 0x003f9006, + 0x9421ffff, 0x90210004, 0xb001e000, 0xb4800002, + 0x8421e000, 0x9021c000, 0x8013001f, 0x1021b800, + 0x003fb006, 0x003f90cb, 0x90210004, 0x003fb0cb, + 0x83e400e7, 0x83e4138b, 0x8007001f, 0x94000003, + 0x5810b800, 0x83e71aa8, 0x1bffb800, 0x003f9008, + 0x1821b800, 0x00ffb801, 0x83e413de, 0x80270000, + 0x003f2013, 0x8007001f, 0x94000003, 0x5810b800, + 0x83671ad4, 0x1b7bb800, 0x003f9009, 0x1821b800, + 0x00ffb801, 0xb500ffaa, 0x803bffc0, 0x805bffc4, + 0x807bffc8, 0x809bffcc, 0x5828b801, 0x5cb8b802, + 0x1821b805, 0x5848b802, 0x5cb8b803, 0x1842b805, + 0x5868b803, 0x5cb8b804, 0x1863b805, 0x5888b804, + 0x1884b800, 0x803effc0, 0x805effc4, 0x807effc8, + 0x809effcc, 0x003f400e, 0xb0000086, 0xb4400048, + 0xb0000084, 0xb4000032, 0xb0000085, 0xb4000038, + 0xb0000086, 0xb400003a, 0x001f4000, 0x94000080, + 0xb0000080, 0xb4000072, 0x800500d4, 0x8053ffff, + 0x9842c7ff, 0x1400b802, 0x805300ff, 0x98422800, + 0x1800b802, 0x800600d4, 0x80130000, 0x98000c7f, + 0x005f4000, 0x94420008, 0xb0020008, 0xb4200001, + 0xa0000080, 0x800600a1, 0x8013001f, 0x9040c000, + 0x005fb006, 0x805effe0, 0x805effe8, 0x805effec, + 0x9040e000, 0x805effe4, 0x9040fa00, 0x805effd0, + 0x805effdc, 0x805effd8, 0x9040fe00, 0x805effd4, + 0x80070001, 0x001f2013, 0x80070000, 0x001fb0cb, + 0x001fb010, 0x001f2058, 0x80071f60, 0x001fb008, + 0x80075d70, 0x001fb009, 0x98214000, 0xb5000010, + 0x94011000, 0xb0001000, 0xb4200001, 0x9421efff, + 0x98210010, 0xb500000a, 0x80070000, 0x001fb0cb, + 0x83e4007f, 0x003f400e, 0x9421ffef, 0xb5000004, + 0x83e4007b, 0x003f400e, 0x98211000, 0x9421ffef, + 0x003f600e, 0x80070100, 0x801efff0, 0xb500ff4c, + 0xb000008b, 0xb400001c, 0xb000008e, 0xb4000022, + 0xb000008d, 0xb400001c, 0xb000008c, 0xb4000021, + 0xb0000087, 0xb400ffe8, 0xb0000088, 0xb4000014, + 0xb000008a, 0xb4000015, 0xb0000089, 0xb400001d, + 0xb00000a0, 0xb400001f, 0xb00000a1, 0xb4000041, + 0xb00000a2, 0xb400004a, 0xb00000a3, 0xb4000046, + 0xb00000a4, 0xb4000048, 0xb00000a5, 0xb4000048, + 0xb00000a6, 0xb4000048, 0x803efff8, 0xb500ffdd, + 0x9421ffdf, 0xb500ffda, 0xb500ffda, 0x80270100, + 0x803efff8, 0xb500ffd7, 0x80070000, 0x001fb017, + 0xb500ffd4, 0x801bffb0, 0x00000000, 0x001fb003, + 0xb500ffd0, 0x803bff80, 0x00000000, 0x003f6001, + 0xb500ffcc, 0x003f90ba, 0x803efff8, 0xb500ffc9, + 0x80130001, 0x98003da1, 0x800600a1, 0x80070200, + 0x801ebf34, 0x83e4002e, 0x8013001f, 0x9840c000, + 0x805effe0, 0x005fb006, 0x805effe8, 0x805effec, + 0x90422000, 0x805effe4, 0x9040fa00, 0x805effd0, + 0x805effdc, 0x805effd8, 0x9040fe00, 0x805effd4, + 0x80070001, 0x001f2013, 0x80070000, 0x001f2324, + 0x001fb0cb, 0x001fb010, 0x001f2058, 0x800774b0, + 0x001fb008, 0x80077730, 0x001fb009, 0x98214000, + 0xb500ffa7, 0x80270000, 0x8047fef0, 0x003eb802, + 0x90420004, 0x003eb802, 0x90420004, 0x003eb802, + 0x90420004, 0x003eb802, 0x83641460, 0xb500ff9d, + 0x8364140e, 0xb500ff9b, 0x836413cd, 0xb500ff99, + 0x83441334, 0xb500ff97, 0x8344131d, 0xb500ff95, + 0x80070000, 0x80470000, 0xb6002003, 0xb6003002, + 0x001eb802, 0x90420004, 0x80171000, 0x8057ffff, + 0xb6002002, 0xb6001801, 0x001fa020, 0x00ffb81f, + 0x001f4000, 0x94000080, 0xb0000080, 0xb4200001, + 0xb500ffef, 0xb500000a, 0x80270000, 0x003f2013, + 0x8007001f, 0x94000003, 0x5810b800, 0x83671e60, + 0x1b7bb800, 0x003f9009, 0x1821b800, 0x00ffb801, + 0x003f0013, 0xb0010001, 0xb420fff3, 0x83a70000, + 0x803bff70, 0x00000000, 0xb0010000, 0xb4000011, + 0x80170300, 0x80070000, 0xb6000601, 0x001fa020, + 0x83640c66, 0x00ff0325, 0x82870000, 0xb6270002, + 0x83640217, 0x92940001, 0x001f033b, 0xb0000000, + 0xb4000002, 0x80270000, 0xb5000001, 0x80270001, + 0x003f233b, 0x80270000, 0x003f2013, 0x8007001f, + 0x94000003, 0x5810b800, 0x83671eec, 0x1b7bb800, + 0x003f9009, 0x1821b800, 0x00ffb801, 0x003f0013, + 0xb0010001, 0xb420fff3, 0x93bd0001, 0xb01d0004, + 0xb480ffdb, 0x803bff70, 0x00000000, 0xb0010000, + 0xb4000001, 0x83640c12, 0x00000000, 0x00000000, + 0x00ffb81f, 0x007f90cb, 0x90630400, 0x007fb0cb, + 0x003f9006, 0x9421ffff, 0x90210400, 0xb001e000, + 0xb4800002, 0x8421e000, 0x9021c000, 0x8013001f, + 0x1021b800, 0x003fb006, 0x803effec, 0x00ffb81f, + 0x015f400e, 0x944a4000, 0xb0024000, 0xb4200084, + 0x954abfff, 0x015f600e, 0x820f001f, 0x802f001f, + 0x81470000, 0x015f23f9, 0x829702ec, 0x82d7ffff, + 0x82f70000, 0xb6000501, 0x029fa02a, 0x82970400, + 0xb6000702, 0xb6000001, 0x029fa02a, 0x8053ff00, + 0x98420000, 0x805ebf14, 0x805ebf18, 0x805ebf1c, + 0x805ebf20, 0x805ebf24, 0x805ebf28, 0x80270000, + 0x003f2328, 0x80275480, 0x005fb801, 0x8033001f, + 0x9821c000, 0x803effe0, 0x90212000, 0x803effe4, + 0x80dbff8c, 0x80fbff90, 0x80debf14, 0x80febf18, + 0x80dbff94, 0x80fbff98, 0x80debf1c, 0x80febf20, + 0x80dbff9c, 0x80fbffa0, 0x80debf24, 0x80febf28, + 0x80dbff84, 0x80e70001, 0x00dfb001, 0x80dbff88, + 0x00ff6191, 0x00dfb002, 0x80dbffb0, 0x80470000, + 0x00dfb003, 0x80d9ff80, 0x005fb0cf, 0x005fb0c6, + 0x00df6001, 0x80470001, 0x005f618f, 0x804700ff, + 0x005f231c, 0x005f231d, 0x80470000, 0x005f204e, + 0x8047e138, 0x5c42b802, 0x814f6300, 0x80cf00a9, + 0x005fb0bc, 0x5842b802, 0x01cfb802, 0x005f90bc, + 0xb520ffff, 0x8067e16c, 0x5c62b803, 0x80270040, + 0xb6000209, 0x814fffc0, 0x00cfb801, 0x007fb0bc, + 0x5862b803, 0x01cfb803, 0x007f90bc, 0xb520ffff, + 0x90210020, 0x90630020, 0x8047e398, 0x5c42b802, + 0x814fce40, 0x80cf0080, 0x005fb0bc, 0x5842b802, + 0x01cfb802, 0x005f90bc, 0xb520ffff, 0x8047e400, + 0x5c42b802, 0x814f7380, 0x80cf009a, 0x005fb0bc, + 0x5842b802, 0x01cfb802, 0x005f90bc, 0xb520ffff, + 0x8047e43c, 0x5c42b802, 0x814f18c0, 0x80cf00b6, + 0x005fb0bc, 0x5842b802, 0x01cfb802, 0x005f90bc, + 0xb520ffff, 0x80e70000, 0x00ffb0ba, 0x808f0000, + 0x806f001f, 0x80af001f, 0x8027b9fc, 0x5c22b801, + 0x80670700, 0xb600080a, 0x00cfb803, 0x003fb0bc, + 0x5822b801, 0x01cfb801, 0x003f90bc, 0x0047b86f, + 0xb0020001, 0xb4c0fffd, 0x90210020, 0x90630020, + 0x834400d3, 0xb0180000, 0xb4200025, 0x83440678, + 0x80c70000, 0x00df2324, 0x83640026, 0x83440220, + 0x00df0324, 0x90c60001, 0x00df2324, 0xb0060006, + 0xb4000003, 0x81472198, 0x015fb008, 0x00ffb81f, + 0x00ff90ba, 0x90e70001, 0x00ffb0ba, 0x019f9006, + 0x958cffff, 0x00df4193, 0x58c1b806, 0x118cb806, + 0xb00ce000, 0xb4800002, 0x858ce000, 0x918cc000, + 0x8153001f, 0x118cb80a, 0x819effec, 0x019fb006, + 0x015f4193, 0x5941b80a, 0x019f90cb, 0x118cb80a, + 0x019fb0cb, 0x81472180, 0x015fb008, 0x00ffb81f, + 0x015f400e, 0x194ab818, 0x015f600e, 0x802500a5, + 0x00ffb81f, 0x803bff8c, 0x805bff90, 0x803ebf14, + 0x805ebf18, 0x803bff94, 0x805bff98, 0x803ebf1c, + 0x805ebf20, 0x803bff9c, 0x805bffa0, 0x803ebf24, + 0x805ebf28, 0x80470003, 0x805ebefc, 0x003f0384, + 0x5822b801, 0x9021eb50, 0x005bb801, 0x00000000, + 0xb0020001, 0xb4200002, 0x80470001, 0x805ebefc, + 0x8073ff80, 0x98630000, 0x8027bf14, 0x8047befc, + 0xb6000609, 0x009bb801, 0x00000000, 0x00a7b804, + 0x6081b804, 0x3004b803, 0xb4000001, 0x00beb802, + 0x90210004, 0x90420004, 0x00ffb81b, 0x00000000, + 0x81150010, 0x00000000, 0x00000000, 0x81350010, + 0x00000000, 0x00000000, 0x81550002, 0x00000000, + 0x015f2380, 0x81550006, 0x00000000, 0x015f2381, + 0x81550005, 0x00000000, 0x015f2382, 0x81550003, + 0x00000000, 0x015f2383, 0x81550003, 0x015f2384, + 0xb00a0001, 0xb4000005, 0x956a0001, 0xb00b0000, + 0xb4000002, 0x81750002, 0x017f2385, 0x956a0004, + 0xb00b0000, 0xb4000002, 0x81750002, 0x017f2386, + 0xb00a0002, 0xb4200003, 0x81750002, 0x00000000, + 0x017f2387, 0x81750001, 0x00000000, 0x017f2388, + 0x81750005, 0x00000000, 0x017f2389, 0x81750001, + 0x017f239f, 0xb00b0001, 0xb4200003, 0x81750008, + 0x5968b80b, 0x017f61c5, 0x81750001, 0x017f238c, + 0xb00b0001, 0xb4200003, 0x81750008, 0x00000000, + 0x017f238d, 0x81750001, 0x017f238e, 0xb00b0001, + 0xb4200005, 0x81750005, 0x00000000, 0x017f238f, + 0x81750002, 0x017f2390, 0xb00a0000, 0xb420001b, + 0x81750005, 0x00000000, 0x017f2391, 0x81750001, + 0x017f23a0, 0xb00b0001, 0xb4200003, 0x81750008, + 0x5968b80b, 0x017f61c9, 0x81750001, 0x017f2394, + 0xb00b0001, 0xb4200003, 0x81750008, 0x00000000, + 0x017f2395, 0x81750001, 0x017f2396, 0xb00b0001, + 0xb4200006, 0x81750005, 0x00000000, 0x017f2397, + 0x81750002, 0x00000000, 0x017f2398, 0x81750001, + 0x00000000, 0x017f2399, 0x81750001, 0x00000000, + 0x017f239a, 0x81750001, 0x017f239b, 0xb00b0001, + 0xb4200003, 0x8175000e, 0x00000000, 0x017f61be, + 0x81750001, 0x017f239c, 0xb00b0001, 0xb4200003, + 0x8175000e, 0x00000000, 0x017f237e, 0x81750001, + 0x017f239d, 0xb00b0001, 0xb4200006, 0x81750006, + 0x017f239e, 0x916b0001, 0x81550008, 0x856b0001, + 0xb4e0fffd, 0x00ffb81c, 0x00000000, 0x00000000, + 0x81470000, 0x015f2385, 0x015f2386, 0x015f2387, + 0x015f238d, 0x015f238f, 0x015f2390, 0x015f2391, + 0x015f2395, 0x015f2396, 0x015f2397, 0x015f2398, + 0x015f61be, 0x015f61bf, 0x82070028, 0x023f9006, + 0x83a4003a, 0x83270000, 0x003fb819, 0x003f9006, + 0x5823b801, 0x83338000, 0x1b39b801, 0x003fb819, + 0x00000000, 0x00000000, 0x81550000, 0x8384ff64, + 0x017f0380, 0xad4b0026, 0x013f0381, 0x114ab809, + 0x5941b80a, 0x914ae00c, 0x0199b80a, 0x00000000, + 0x019f6193, 0xb0080b77, 0xb4200016, 0x015f0380, + 0xb00a0003, 0xb4600017, 0xb0090026, 0xb4600019, + 0x017f90ba, 0xb00b0000, 0xb4200004, 0x017f0384, + 0x017f204d, 0x017f0383, 0x017f2057, 0x015f0383, + 0x017f0057, 0x300ab80b, 0xb4200012, 0x015f0384, + 0x017f004d, 0x300ab80b, 0xb420000e, 0x83070000, + 0x00ffb81a, 0x83070800, 0x031f6193, 0x83070001, + 0x00ffb81a, 0x83070800, 0x031f6193, 0x83070002, + 0x00ffb81a, 0x83070800, 0x031f6193, 0x83070003, + 0x00ffb81a, 0x83070003, 0x00ffb81a, 0x5e02b810, + 0x5a02b810, 0x00bf9011, 0x00df004f, 0xa5260020, + 0x81e70000, 0x82471000, 0x95d1ffff, 0xa5cee000, + 0x300eb810, 0xb4600002, 0x05f0b80e, 0x0207b80e, + 0x8267001f, 0x82c70020, 0x82971000, 0xb0100080, + 0xb480001f, 0x5a8bb813, 0x5aa6b813, 0x1a94b815, + 0x01efb812, 0x014fb814, 0x01cfb811, 0xb520ffff, + 0xb636000f, 0x81470000, 0x039f8014, 0xb6000404, + 0x5948b80a, 0x957c00ff, 0x194ab80b, 0x5f88b81c, + 0xb0060020, 0xb4200001, 0x80a70000, 0x64a6b805, + 0x68e9b80a, 0x18a5b807, 0x029fa025, 0x00a7b80a, + 0x01efb812, 0x014fb814, 0x01afb811, 0xb520ffff, + 0x5ae2b816, 0x1231b817, 0x0610b817, 0xb500ffde, + 0xb0100000, 0xb4000003, 0x5ec2b810, 0x86760001, + 0xb500ffdc, 0xb00f0000, 0xb4000005, 0x0207b80f, + 0x81f3001f, 0x9a2fc000, 0x81e70000, 0xb500ffd0, + 0x015fb011, 0x00ffb81d, 0x00000000, 0x00000000, + 0x8057ffff, 0x80d7ffff, 0x8157ffff, 0x81d7ffff, + 0x8257ffff, 0x82d7ffff, 0x8357ffff, 0x83d7ffff, + 0x80770000, 0x80f70000, 0x81770000, 0x81f70000, + 0x82770000, 0x82f70000, 0x83770000, 0x83f70000, + 0xaeb40080, 0x808f0000, 0x806f001f, 0x80af001f, + 0xb0140000, 0xb4400014, 0x806f001f, 0x80af001f, + 0x8027b9fc, 0x5c22b801, 0x80670700, 0xb6000208, + 0x00cfb803, 0x003fb0bc, 0x5822b801, 0x01cfb801, + 0x003f90bc, 0xb520ffff, 0x90630020, 0x90210020, + 0x80270000, 0x80171000, 0xb6000303, 0xb6000001, + 0x001fa021, 0x00000000, 0x82670000, 0xb6000268, + 0x80170a00, 0x80970afc, 0x81170b00, 0x81970bfc, + 0x80271c00, 0x1021b813, 0x1021b813, 0x0217b801, + 0x80271ffc, 0x0421b813, 0x0421b813, 0x0297b801, + 0x80270c00, 0x1021b813, 0x1021b813, 0x0317b801, + 0x80270ffc, 0x0421b813, 0x0421b813, 0x0397b801, + 0x80478500, 0x1042b813, 0x5c42b802, 0x1022b815, + 0x80670280, 0x00cfb803, 0x003fb0bc, 0x5822b801, + 0x01cfb801, 0x003f90bc, 0xb520ffff, 0x009f033b, + 0x80478480, 0x0442b813, 0x5c42b802, 0x1022b815, + 0x806702a0, 0x00cfb803, 0x003fb0bc, 0x5822b801, + 0x01cfb801, 0x003f90bc, 0xb520ffff, 0xb0040000, + 0xb4000002, 0x80479000, 0xb5000001, 0x80479c00, + 0x1042b813, 0x5c42b802, 0x1022b815, 0x806702c0, + 0x00cfb803, 0x003fb0bc, 0x5822b801, 0x01cfb801, + 0x003f90bc, 0xb520ffff, 0xb0040000, 0xb4000002, + 0x80479180, 0xb5000001, 0x80479d80, 0x0442b813, + 0x5c42b802, 0x1022b815, 0x806702e0, 0x00cfb803, + 0x003fb0bc, 0x5822b801, 0x01cfb801, 0x003f90bc, + 0xb520ffff, 0x81270000, 0x80370000, 0x80b70000, + 0x81370000, 0x81b70000, 0x82370004, 0x82b7fffc, + 0xb6002016, 0x41498008, 0x51498814, 0x51498814, + 0x51418810, 0x51418810, 0x41818814, 0x0308a02a, + 0x49958820, 0x51898810, 0x51918828, 0x414d8814, + 0x0388a7ec, 0x494d8814, 0x49458810, 0x49458810, + 0x418d8810, 0x0308a02a, 0x49918fec, 0x51858814, + 0x51958fe4, 0x00000000, 0x0388a7ec, 0x92730080, + 0x009f033b, 0x5802b814, 0x90400300, 0x001f9802, + 0x00000000, 0xb0000000, 0xb4200016, 0x80170a00, + 0x80070000, 0xb6002001, 0x001fa020, 0xb0040000, + 0xb4200002, 0x80279000, 0xb5000001, 0x80279c00, + 0xac740080, 0x5c22b801, 0x11e1b803, 0x806f001f, + 0x80af001f, 0xb6000407, 0x80cf0280, 0x01ffb0bc, + 0x59e2b80f, 0x01afb80f, 0x01ff90bc, 0xb520ffff, + 0x91ef0020, 0x007f0320, 0x011f90cd, 0xaca30006, + 0x80c7b004, 0x10a5b814, 0x58a1b805, 0x10a5b806, + 0x0099b805, 0x8027b3dc, 0x5841b804, 0x1021b802, + 0x0159b801, 0x8027b3d0, 0x5841b804, 0x1021b802, + 0x0139b801, 0x80170c00, 0x0097b80a, 0xb6000002, + 0x59478020, 0x009fa04a, 0x00ffb81b, 0x00000000, + 0x009f0011, 0x015f0012, 0xb0060000, 0xb4200007, + 0x968a0001, 0xb0140000, 0xb400000d, 0x80870001, + 0x009f2011, 0x954a0002, 0x015f2012, 0xb0060002, + 0xb4200007, 0x968a0002, 0xb0140000, 0xb4000004, + 0x80870001, 0x009f2011, 0x81470000, 0x015f2012, + 0x8364002b, 0x00bf2010, 0xb0060000, 0xb4200003, + 0xb0050000, 0xb4200001, 0x8364008d, 0xb0050000, + 0xb4200001, 0x836400b2, 0x00bf0010, 0xb0050000, + 0xb4200006, 0x83640983, 0x8364029d, 0x00000000, + 0x8364092b, 0x00000000, 0xb5000005, 0x00bf0010, + 0xb0050001, 0xb4000002, 0x00000000, 0x83640924, + 0x00ff0325, 0x82870000, 0xb6270002, 0x8364ff08, + 0x92940001, 0x80070001, 0x801eff70, 0x001f0010, + 0xb0000001, 0xb4000007, 0x001f033b, 0xb0000000, + 0xb4000002, 0x80270000, 0xb5000001, 0x80270001, + 0x003f233b, 0x00ffb81a, 0x00000000, 0x00000000, + 0x027f4001, 0x5e2ab813, 0x96310003, 0x81c70000, + 0x820700ff, 0xb0110000, 0xb4000005, 0x5a21b811, + 0x81c70200, 0x8207000e, 0x69d1b80e, 0x1210b811, + 0x01dfb0cd, 0x5e2cb813, 0x96310003, 0x023f2323, + 0x5e28b813, 0x96310003, 0x023f2322, 0x5e27b813, + 0x96310001, 0x023f2328, 0x5e23b813, 0x96310001, + 0x023f2321, 0x95f30007, 0x01ff2320, 0x920fe004, + 0x0258b810, 0x00000000, 0x1252b811, 0x025f2325, + 0x8167befc, 0x017f6195, 0x021f031c, 0x01df031d, + 0x3010b80f, 0xb4200003, 0x3011b80e, 0xb4200001, + 0xb5000021, 0x80270000, 0x80471000, 0x0017b802, + 0x8057ffff, 0xb6002001, 0x001fa021, 0x80270400, + 0x80679000, 0x5c62b803, 0xb6001809, 0x00cfb801, + 0x007fb0bc, 0x5862b803, 0x01afb803, 0x007f90bc, + 0x0047b86f, 0xb0020001, 0xb4c0fffd, 0x90630020, + 0x80679c00, 0x5c62b803, 0xb6001809, 0x00cfb801, + 0x007fb0bc, 0x5862b803, 0x01afb803, 0x007f90bc, + 0x0047b86f, 0xb0020001, 0xb4c0fffd, 0x90630020, + 0x01ff231c, 0x023f231d, 0x83970300, 0x82070000, + 0xb6320001, 0x039fa030, 0x00bf0010, 0x021f0324, + 0xb0100000, 0xb4200001, 0x80a70000, 0xb0050000, + 0xb4200008, 0xb0040000, 0xb4a00002, 0x80a70001, + 0xb5000004, 0x82070000, 0x021f204e, 0xb4000001, + 0x80a70002, 0xb0050001, 0xb4200007, 0x021f004e, + 0xb0100002, 0xb4a00002, 0x80a70002, 0x00ffb81b, + 0x92100001, 0x021f204e, 0x00000000, 0x00ffb81b, + 0x81530000, 0x003fb80a, 0x00000000, 0x00000000, + 0x003fb819, 0x00000000, 0x00000000, 0x81550000, + 0x8384fd7b, 0x81470000, 0x015f61ee, 0x015f61ef, + 0x015f23a4, 0x8297050c, 0x82d7ffff, 0xb6000501, + 0x029fa02a, 0x8167e004, 0x116b0384, 0x0158b80b, + 0x019f0382, 0x015f237b, 0x017f0388, 0x116bb80a, + 0xb00c0008, 0xb4a00003, 0x80a70003, 0x00bf2010, + 0x00ffb81b, 0xb00a0005, 0xb4400003, 0xb00b0006, + 0xb4400001, 0x00ffb81b, 0x80a70004, 0x00bf2010, + 0x00ffb81b, 0x00000000, 0x00000000, 0x00000000, + 0x027f0388, 0x02bf037b, 0x02df0384, 0x02ff03a1, + 0x82970400, 0x8257ffff, 0x82d7ffff, 0xb6350003, + 0x81550001, 0x8357ffff, 0x029fa02a, 0x82970414, + 0xb6350003, 0x81550001, 0x83d7ffff, 0x029fa02a, + 0x81550001, 0xb00a0001, 0xb4200004, 0x814d0008, + 0x6149b80a, 0x954affff, 0x015f61ee, 0xb0160000, + 0xb4200007, 0x81550001, 0xb00a0001, 0xb4200004, + 0x814d0008, 0x6149b80a, 0x954affff, 0x015f61ef, + 0x81550001, 0xb00a0001, 0xb4200036, 0x82f50001, + 0x02ff23a1, 0xb0170001, 0xb420002c, 0x82970428, + 0xb6350003, 0x81550001, 0x00000000, 0x029fa02a, + 0x82970428, 0x81470000, 0x017f8034, 0xb00b0001, + 0xb4000004, 0x914a0001, 0x300ab815, 0xb480fffa, + 0xb5000001, 0x015f23a5, 0x81670000, 0xb0160002, + 0xb4200002, 0x81750001, 0x00000000, 0x017f233a, + 0x81550004, 0xadaa000c, 0x015f23a2, 0x81750004, + 0x916b0003, 0x017f23a3, 0x91ad0025, 0x01bf23a6, + 0xadab000c, 0x81e70000, 0x91ad0025, 0x01bf23a7, + 0x920a0001, 0x05abb810, 0xb00d0000, 0xb400000d, + 0xb62d0004, 0x81b50001, 0x65b0b80d, 0x19efb80d, + 0x92100001, 0x01ffb0be, 0xb5000006, 0x81a70000, + 0x82970428, 0xb6350001, 0x029fa02d, 0x01bf233a, + 0x01bf23a5, 0x82070000, 0x82270000, 0x82170428, + 0xb635003a, 0x01bf8030, 0xb00d0001, 0xb4200036, + 0x81d50001, 0x65b1b80e, 0x1a10b80d, 0xb00e0001, + 0xb4200031, 0x81b50002, 0xadad0003, 0xae510048, + 0x91cd000f, 0x91320868, 0x015f03a2, 0xad4a0004, + 0x92920700, 0x1189b80a, 0x0297b80c, 0x1194b80a, + 0x0317b80c, 0x01ff90be, 0x015f03a2, 0x017f03a3, + 0x064bb80a, 0x0107b80a, 0xb0120000, 0xb400001e, + 0xb632001d, 0x6928b80f, 0x95290001, 0xb0090000, + 0xb420000e, 0x81350004, 0x1129b80d, 0x029fa029, + 0x824d0004, 0x5a48b812, 0x5e48b812, 0x3009b80e, + 0xb4200002, 0x5e41b812, 0xb500000d, 0x5e42b812, + 0x81330040, 0x1a52b809, 0xb5000009, 0x0127b854, + 0x85290004, 0x0397b809, 0x0287b858, 0x86940004, + 0x013f803c, 0x0397b814, 0x029fa029, 0x025f803c, + 0x031fa032, 0x91080001, 0x92310001, 0x015f03a2, + 0x017f03a3, 0x013f033a, 0xb0090001, 0xb420001f, + 0x95300002, 0x95900001, 0x1929b80c, 0xb0090000, + 0xb400001a, 0x064bb80a, 0x0107b80a, 0xb6320017, + 0x6928b80f, 0x95290001, 0xb0090000, 0xb4200002, + 0x81350001, 0x013f23f8, 0x81a70700, 0x91ad0048, + 0x5982b808, 0x11adb80c, 0x0397b80d, 0x013f03f8, + 0xb0090001, 0xb4200005, 0x019f801c, 0x0196b80c, + 0x81b3ff80, 0x418cb80d, 0xb5000002, 0x019f801c, + 0x0196b80c, 0x039fa00c, 0x91080001, 0xb0160002, + 0xb420001a, 0xb0170001, 0xb4200008, 0xb00a0000, + 0xb4200002, 0x81270002, 0xb5000005, 0xb00a0002, + 0xb4400002, 0x81270003, 0xb5000001, 0x81270004, + 0x013f23a9, 0x81950001, 0xb00c0001, 0xb420000d, + 0x81a70000, 0x8397043c, 0xb6290006, 0x81150001, + 0x039fa028, 0xb0080001, 0xb4200001, 0x81a70001, + 0x00000000, 0x01bf23a8, 0xb5000002, 0x81a70000, + 0x01bf23a8, 0xb0170001, 0xb4200001, 0x81b50002, + 0x82970c20, 0xb6350003, 0x81550002, 0x00000000, + 0x029fa02a, 0xb0130001, 0xb4200001, 0x81150001, + 0x81c70000, 0xb6350014, 0x922e0c20, 0x015ff011, + 0xb00a0000, 0xb400000f, 0x922e0428, 0x015ff011, + 0xb00a0001, 0xb4200005, 0x922e044c, 0x0297b811, + 0x015f03a6, 0x029fa00a, 0xb5000006, 0x81550006, + 0xad4a0003, 0x922e044c, 0x0297b811, 0x914a0049, + 0x029fa00a, 0x91ce0004, 0xb0170001, 0xb420001e, + 0xb00d0000, 0xb400001c, 0x852d0001, 0x81470001, + 0x6549b80a, 0xad6a0003, 0x019f03a7, 0x058c03a6, + 0x81270000, 0xb00b0000, 0xb4000005, 0x300cb80b, + 0xb4800003, 0x058cb80b, 0x91290001, 0xb500fffb, + 0x81750004, 0x5961b80b, 0x839704ec, 0x0187b860, + 0x039fa02c, 0x039fa02a, 0x039fa029, 0x039fa02b, + 0xb0090000, 0xb4000004, 0xb6290003, 0x81550007, + 0x00000000, 0x00000000, 0x81c70000, 0xb635002e, + 0x922e0c20, 0x01fff011, 0xb00f0000, 0xb4000029, + 0x852f0001, 0x81470001, 0x6549b80a, 0xad6a0003, + 0x922e044c, 0x025fd811, 0x86520001, 0x0227b812, + 0x81270000, 0xb00b0000, 0xb4000005, 0x3012b80b, + 0xb4800003, 0x0652b80b, 0x91290001, 0xb500fffb, + 0x2e09b80b, 0x00000000, 0x3010b811, 0xb4600001, + 0x91290001, 0xae4e0004, 0x82150004, 0x9232049c, + 0x0297b811, 0x0187b860, 0x029fa02c, 0x029fa02a, + 0x029fa029, 0x029fa030, 0xb0090000, 0xb4000004, + 0xb6290003, 0x81550007, 0x00000000, 0x00000000, + 0x82270460, 0x1231b80e, 0x0217b811, 0x81550002, + 0x021fa00a, 0x91ce0004, 0xb0130001, 0xb420000c, + 0xb0080000, 0xb400000a, 0x81550004, 0x839704fc, + 0x0167b860, 0x039fa02b, 0x81670001, 0x039fa02b, + 0x8175000e, 0x81670002, 0x039fa02b, 0x039fa02a, + 0x81150001, 0xb0080001, 0xb420000a, 0x8135000b, + 0x5d2923aa, 0x95490180, 0x5d4723ab, 0x95490060, + 0x5d4523ac, 0x95490018, 0x5d4323ad, 0x95490007, + 0x015f23ae, 0x81350001, 0xb0090001, 0xb4200017, + 0x81350006, 0x013f23af, 0xb0170001, 0xb4200005, + 0x81550004, 0x00000000, 0x015f23b0, 0x81550003, + 0x015f23b1, 0x82970474, 0x83170488, 0xb6350004, + 0x81550007, 0x5e83a02a, 0x954a0007, 0x031fa02a, + 0xb0130001, 0xb4200005, 0x81750004, 0x00000000, + 0x017f23b2, 0x81750003, 0x017f23b3, 0xb0170001, + 0xb420000b, 0x81b50001, 0xb00d0001, 0xb4200008, + 0x81d50003, 0x59c8b80e, 0x91ce0300, 0x01df61da, + 0x81d50003, 0x59c8b80e, 0x91ce0300, 0x01df61db, + 0x81550001, 0xb00a0001, 0xb420004b, 0xb0170001, + 0xb4200001, 0x81550002, 0x82470000, 0x82270000, + 0xb6350004, 0x81750002, 0x6571b80b, 0x92310002, + 0x1a52b80b, 0xb0170001, 0xb4200017, 0xb00a0001, + 0xb4200011, 0x81150003, 0x91080001, 0x011f23a4, + 0x829709d0, 0x831709f0, 0x83970060, 0xb6280009, + 0x81750005, 0x00000000, 0x029fa02b, 0x81750004, + 0x00000000, 0x031fa02b, 0x81750003, 0x00000000, + 0x039fa02b, 0xb5000004, 0xb00a0002, 0xb4800002, + 0x81070000, 0x011f23a4, 0x82270000, 0x81270000, + 0xb6350025, 0x6a11b812, 0x92310002, 0x96100003, + 0xb0100001, 0xb4200018, 0xada90020, 0x81750003, + 0x920d0520, 0x0217b810, 0x920d05c0, 0x0297b810, + 0x920d0660, 0x0317b810, 0x5942b809, 0x920a050c, + 0x0397b810, 0x916b0001, 0x039fa02b, 0xb62b0009, + 0x81750005, 0x00000000, 0x021fa02b, 0x81750004, + 0x00000000, 0x029fa02b, 0x81750003, 0x00000000, + 0x031fa02b, 0xb5000007, 0xb0100002, 0xb4800005, + 0x59a2b809, 0x91ad050c, 0x0397b80d, 0x82070000, + 0x039fa010, 0x91290001, 0x81550001, 0xb00a0001, + 0xb4200007, 0x81550009, 0xb00a0000, 0xb4000004, + 0xb62a0003, 0x82150008, 0x00000000, 0x00000000, + 0xb00a0100, 0xb4a00007, 0x954aff00, 0xb6008003, + 0x82150010, 0x00000000, 0x00000000, 0x854a0100, + 0xb4e0fffa, 0x00ffb81b, 0x00000000, 0x00000000, + 0x81070000, 0x011f61dc, 0x011f61de, 0x011f61e0, + 0x011f03aa, 0x9108e0f4, 0x0138b808, 0x011f03ab, + 0x013f61ac, 0x9108e0f0, 0x0138b808, 0x011f03ac, + 0x013f61ad, 0x5901b808, 0x9108e0f8, 0x0139b808, + 0x011f03ad, 0x013f61ae, 0x5901b808, 0x9108e100, + 0x0139b808, 0x011f03ae, 0x013f61b0, 0x5901b808, + 0x9108e108, 0x0179b808, 0x013f03af, 0x017f61b1, + 0x02bf037b, 0x82970474, 0xb6350002, 0x015f8034, + 0x1929b80a, 0x011f03a1, 0xb0080001, 0xb4200002, + 0x015f03b0, 0x1929b80a, 0x019f0388, 0xb00c0001, + 0xb4200002, 0x015f03b2, 0x1929b80a, 0x013f61b3, + 0x015f03a8, 0xb00a0001, 0xb420003a, 0x81a70000, + 0x01bf237a, 0x83840056, 0x806f001f, 0x80af001f, + 0x80270300, 0x8067a800, 0x5c62b803, 0xb600080a, + 0x00cfb801, 0x007fb0bc, 0x5862b803, 0x01afb803, + 0x007f90bc, 0x0047b86f, 0xb0020001, 0xb4c0fffd, + 0x90210020, 0x90630020, 0x81a70001, 0x01bf237a, + 0x83840043, 0x838403c6, 0x81a70000, 0x01bf237a, + 0x82470400, 0x01bff012, 0x01bf23fa, 0x83840418, + 0x8384048f, 0x8384053e, 0x83840595, 0x806f001f, + 0x80af001f, 0x80270300, 0x8067ac00, 0x5c62b803, + 0xb600080a, 0x00cfb801, 0x007fb0bc, 0x5862b803, + 0x01cfb803, 0x007f90bc, 0x0047b86f, 0xb0020001, + 0xb4c0fffd, 0x90210020, 0x90630020, 0x81a70001, + 0x01bf237a, 0x82470404, 0x015ff012, 0x015f23fa, + 0x838403ff, 0x83840476, 0x83840525, 0x8384057c, + 0xb5000011, 0x81a70000, 0x01bf237a, 0xb635000e, + 0x8384001b, 0x01bf037a, 0xad4d0004, 0x00000000, + 0x914a0400, 0x01bff00a, 0x01bf23fa, 0x838403f0, + 0x83840467, 0x83840516, 0x8384056d, 0x01df037a, + 0x91ce0001, 0x01df237a, 0x019f0388, 0xb00c0001, + 0xb4200009, 0x02bf037b, 0x02bf237a, 0x838400e8, + 0x82470000, 0x025f23fa, 0x838403e1, 0x83840458, + 0x83840507, 0x8384055e, 0x00ffb81b, 0x00000000, + 0x80770000, 0x80f70000, 0x81770000, 0x81f70000, + 0x82770000, 0x82f70000, 0x83770000, 0x83f70000, + 0x8057ffff, 0x80d7ffff, 0x8157ffff, 0x81d7ffff, + 0x8257ffff, 0x82d7ffff, 0x8357ffff, 0x83d7ffff, + 0x017f037a, 0x5a42b80b, 0x01bf03a8, 0xb00d0001, + 0xb4200004, 0x011f9118, 0x013f9119, 0x7929b808, + 0xb5000002, 0x91b20460, 0x013ff00d, 0x91b20340, + 0x0297b80d, 0x00000000, 0x029fa009, 0x01df0384, + 0xb00e0000, 0xb4200005, 0xb00b0001, 0xb4200003, + 0x009f90c6, 0x00bf0391, 0xb5000002, 0x009f90cf, + 0x00bf0389, 0x83a4013a, 0x81870000, 0x019f61b5, + 0x019f61b4, 0x5a02b80b, 0x9190044c, 0x01dfd80c, + 0x01df61b6, 0x91900488, 0x01dff00c, 0x59c1b80e, + 0x918ee118, 0x01d9b80c, 0x019f03af, 0x01df61af, + 0x858c000f, 0x5986b80c, 0x91d00474, 0x01bff00e, + 0x59c2b80d, 0x11cc61b2, 0x81870000, 0x019f61b8, + 0x91900414, 0x01dfd80c, 0x01df61b7, 0xadab0010, + 0x00000000, 0x908d049c, 0x83a40189, 0xadcb0020, + 0x5982b80b, 0x908e0520, 0x90ae05c0, 0x90ce0660, + 0x928c050c, 0x00ff9814, 0x83a40161, 0x83a401b0, + 0x017f037a, 0x59c2b80b, 0x918e0428, 0x01fff00c, + 0xb00f0001, 0xb4200081, 0x023f03a5, 0x3011b80b, + 0xb420000f, 0x01c7b860, 0x01dfb0fa, 0x01df41dc, + 0x01df61e8, 0x01df41de, 0x01df61ea, 0x01df41e0, + 0x01df61ec, 0x01df41dd, 0x01df61e9, 0x01df41df, + 0x01df61eb, 0x01df41e1, 0x01df61ed, 0xb5000024, + 0x01c7b860, 0x01dfb0f9, 0x01df41dc, 0x01df61e2, + 0x01df41de, 0x01df61e4, 0x01df41e0, 0x01df61e6, + 0x01df41dd, 0x01df61e3, 0x01df41df, 0x01df61e5, + 0x01df41e1, 0x01df61e7, 0x803f0000, 0x00000000, + 0x00000000, 0x01df90fa, 0x003fb80e, 0x00000000, + 0x00000000, 0x81d50000, 0x00000000, 0x00000000, + 0x01df41e8, 0x01df61dc, 0x01df41ea, 0x01df61de, + 0x01df41ec, 0x01df61e0, 0x01df41e9, 0x01df61dd, + 0x01df41eb, 0x01df61df, 0x01df41ed, 0x01df61e1, + 0x029f03a6, 0x029f236a, 0x029f03a7, 0x029f236c, + 0x027f03a2, 0x92b3e128, 0x0298b815, 0x019f03b0, + 0x029f2368, 0x5982b80c, 0x01df03af, 0x85ce000f, + 0x59c6b80e, 0x11cc61b2, 0x82a70001, 0x02bf61b8, + 0x82a70000, 0x02bf61b9, 0x029f41da, 0x029f61ba, + 0x029f41db, 0x029f61bb, 0x019f03b1, 0x5981b80c, + 0x918ce118, 0x0299b80c, 0xad8b0048, 0x029f61af, + 0x59a2b813, 0x118cb80d, 0x928c0868, 0x029fb0fb, + 0x928c0700, 0x029fb0fc, 0x019f41bc, 0x918c0003, + 0x019f61bc, 0x5a02b80b, 0x91900414, 0x029fd80c, + 0x029f236e, 0x808704ec, 0x83a40119, 0x808709d0, + 0x80a709f0, 0x80c70060, 0x00ff03a4, 0x83a400f4, + 0x83a40143, 0x021f037a, 0x019f03a5, 0x300cb810, + 0xb4000016, 0x803f0000, 0x00000000, 0x00000000, + 0x01df90f9, 0x003fb80e, 0x00000000, 0x00000000, + 0x81d50000, 0x00000000, 0x00000000, 0x01df41e2, + 0x01df61dc, 0x01df41e4, 0x01df61de, 0x01df41e6, + 0x01df61e0, 0x01df41e3, 0x01df61dd, 0x01df41e5, + 0x01df61df, 0x01df41e7, 0x01df61e1, 0x029f41b6, + 0xa6d40100, 0xaeb40004, 0x81870000, 0x92b50c00, + 0x0397b815, 0xb6360001, 0x039fa02c, 0x00ffb81c, + 0x009f90cf, 0x00bf0389, 0x019f037a, 0x5982b80c, + 0x918c0340, 0x0397b80c, 0x81870000, 0x039fa00c, + 0x83a4007b, 0x81870000, 0x019f61b5, 0x019f61b4, + 0x81870007, 0x019f61b6, 0x019f03b3, 0x5981b80c, + 0x918ce118, 0x01b9b80c, 0x019f03af, 0x01bf61af, + 0x858c000f, 0x5986b80c, 0x01bf03b2, 0x59a2b80d, + 0x118cb80d, 0x019f61b2, 0x81870000, 0x019f61b7, + 0x019f61b8, 0x808704fc, 0x83a400d1, 0x80870000, + 0x80a70000, 0x80c70000, 0x80e70000, 0x83a400ac, + 0x83a400fb, 0x81470000, 0x81e70c1c, 0x0397b80f, + 0xb600f901, 0x039fa02a, 0x00ffb81c, 0x00000000, + 0x82270000, 0x023f2011, 0x0227b860, 0x023fb0ff, + 0x02bf9006, 0x92350028, 0x8213001f, 0x9210e000, + 0x3011b810, 0xb4800001, 0x86312000, 0x021f4193, + 0x5a01b810, 0x86100028, 0x83a4fa94, 0x82270000, + 0x003fb811, 0x02bf9006, 0x5aa3b815, 0x82338000, + 0x1a31b815, 0x003fb811, 0x8067e950, 0x5c62b803, + 0x81f50000, 0x80270400, 0xb6000409, 0x814fffc0, + 0x00cfb801, 0x007fb0bc, 0x5862b803, 0x01cfb803, + 0x007f90bc, 0xb520ffff, 0x90210020, 0x90630020, + 0x82870000, 0x81f50010, 0x019f4193, 0x5d61b80c, + 0x5d43b80c, 0x114ab80b, 0x0187b80a, 0x960cff00, + 0x92100100, 0x858c0001, 0xb62c000c, 0x81f50010, + 0x5e28b80f, 0xb6000209, 0x5a48b814, 0x9652ff00, + 0x5e68b814, 0x5981b813, 0x918c1000, 0x01dfd80c, + 0x2252b811, 0x2292b80e, 0x962f00ff, 0x81870000, + 0x86100100, 0xb4e0fff0, 0xb00a0000, 0xb4000009, + 0x81670000, 0xb0140000, 0xb4000001, 0x81670001, + 0x017f2012, 0x258a4193, 0x918c0001, 0x81470000, + 0xb500ffe2, 0x81670000, 0xb0140000, 0xb4000001, + 0x81670002, 0x116b0012, 0x803f0000, 0x00000000, + 0x00000000, 0x003fb811, 0x00000000, 0x00000000, + 0x81f50000, 0x017f2012, 0x00ffb81a, 0x00000000, + 0x61f4b804, 0x91ef0001, 0x8233003f, 0x9a31ffff, + 0x5a02b804, 0x1610b811, 0x92510001, 0x1a10b812, + 0x029f03fb, 0xb0140001, 0xb4200012, 0x5a21b805, + 0x92b1e910, 0x0299b815, 0x5a22b805, 0x5a90b814, + 0x6290b814, 0x92b1e890, 0x11efb814, 0x029bb815, + 0x8233ff80, 0x3011b814, 0xb4000006, 0x4294b811, + 0x00000000, 0x0288b814, 0x4210b814, 0x00000000, + 0x0208b810, 0x029f9003, 0x82f3007f, 0x9af7ffff, + 0x3017b814, 0xb4000003, 0x4210b814, 0x00000000, + 0x0208b810, 0x82270000, 0x02c7b810, 0xb0160000, + 0xb400000a, 0x1676b812, 0x3013b812, 0xb4000003, + 0x5ac1b816, 0x92310001, 0xb500fffa, 0x81d3ff80, + 0x3010b80e, 0xb4200001, 0x1ad6b80e, 0x05efb811, + 0x027f037a, 0x5a62b813, 0x92730340, 0x0397b813, + 0x023fd813, 0x02dfb0fd, 0x5a30b811, 0x6230b811, + 0x0631b80f, 0x3010b812, 0xb4200001, 0x92310001, + 0x82470000, 0xb0110000, 0xb4800004, 0x82470003, + 0xb0110003, 0xb4400001, 0x0247b811, 0x039fa012, + 0x124f61bc, 0x00ffb81d, 0x00000000, 0x00000000, + 0x83970a10, 0x82070000, 0xb6003201, 0x039fa030, + 0xb0070000, 0xb4000019, 0x029f41b4, 0x0297b804, + 0x0317b805, 0x0397b806, 0xb6270014, 0x12948034, + 0x01df8038, 0xb00e0000, 0xb4a0000e, 0x02bf803c, + 0x5a02b814, 0x91b00a10, 0x0217b80d, 0xb62e0008, + 0x96150003, 0x91f00001, 0xadef0080, 0xb0150004, + 0xb4600001, 0x85ef0280, 0x021fa02f, 0x92940001, + 0xb5000001, 0x021f803c, 0x00000000, 0x00ffb81d, + 0x0397b804, 0x021f036a, 0x027f803c, 0x029f803c, + 0x02bf803c, 0x02df803c, 0x5a22b810, 0x92311000, + 0x0397b811, 0xb0100000, 0xb4200001, 0x039fa036, + 0xb0150000, 0xb4000021, 0x0227b860, 0x023fb0ff, + 0xb520ffff, 0x803f0000, 0x82138000, 0x1a10b813, + 0x003fb810, 0x00000000, 0x00000000, 0x82150000, + 0x00000000, 0xb635000d, 0x82550007, 0x5a42b812, + 0x9212e4b8, 0x025bb810, 0x8227000c, 0xb6000307, + 0x68d1b812, 0x94c6000f, 0x84c60002, 0x12d6b806, + 0xb6340001, 0x039fa036, 0x86310004, 0x803f0000, + 0x82138000, 0x023f90ff, 0x1a31b810, 0x003fb811, + 0x00000000, 0x00000000, 0x82150000, 0x00ffb81d, + 0x00ff41b5, 0x011f41b4, 0x019f41af, 0x01bf41ae, + 0x01df41ba, 0x01ff41bb, 0x82070000, 0x023f0380, + 0x82470000, 0xae310032, 0x029f41b3, 0x5862b807, + 0x90431000, 0x81970ad8, 0x0217b802, 0x90430c00, + 0x0297b802, 0x0317b802, 0x912802a4, 0x007ff009, + 0x58478030, 0x792341b6, 0x0529b807, 0x019fa029, + 0xb0080014, 0xb4800011, 0xa5420c00, 0x031fa02a, + 0x84690001, 0xb4a00011, 0xb623000b, 0x58678030, + 0xa4030c00, 0x031fa020, 0x044ab800, 0x0056b802, + 0x5c41b802, 0xf84200ff, 0x90620100, 0x005ff003, + 0x7d40b80a, 0x114ab802, 0xb5000004, 0xa5420c00, + 0x58478010, 0xa5620c00, 0x031fa02a, 0xb0080016, + 0xb4400043, 0xb0080013, 0xb440002c, 0xb0080006, + 0xb4400024, 0xb0080005, 0xb4400014, 0xb0080002, + 0xb4400006, 0x80440030, 0x015f619c, 0x05cab80c, + 0x05eab80d, 0x066eb810, 0xb500003c, 0x8044002a, + 0x300a419c, 0xb4800001, 0x82470001, 0x015f619c, + 0xb0120001, 0xb4200001, 0xb500001a, 0x05cab80c, + 0x05eab80d, 0x066eb810, 0xb5000030, 0x001f41b6, + 0xb0000007, 0xb4000001, 0x8044001b, 0x300a419c, + 0xb4800001, 0x82470001, 0xb0120001, 0xb4200001, + 0xb500000c, 0x05cab80c, 0x05eab80d, 0x066eb810, + 0xb5000022, 0x80440010, 0x840b0100, 0x300ab800, + 0xb4200001, 0x86100040, 0xb5000002, 0x86100080, + 0xfe100000, 0x046e41ad, 0x042ab80c, 0x7dc1b803, + 0x044f41ac, 0x042ab80d, 0x7de1b802, 0x046eb810, + 0x7e6fb803, 0xb5000011, 0x840b0100, 0x3000b80a, + 0xb4200002, 0x82070180, 0x00ffb802, 0x300ab80b, + 0xb4a00002, 0x86100040, 0xfe100000, 0x00ffb802, + 0x046e41ad, 0x042ab80c, 0x7dc1b803, 0x044f41ac, + 0x042ab80d, 0x7de1b802, 0x7e6eb80f, 0x380a41b0, + 0xb4600003, 0x242a41b0, 0x5c22b801, 0x1273b801, + 0xb0140000, 0xb4200002, 0x80071fe0, 0xb5000016, + 0x1011b808, 0x5801b800, 0x9020e26c, 0x0079b801, + 0x5842b808, 0x90420a10, 0x7c03b813, 0x003f9802, + 0x1000b801, 0x003f41b2, 0x5830b801, 0x6030b801, + 0x0400b801, 0x003f41b1, 0x5830b801, 0x6030b801, + 0x0400b801, 0xfc000000, 0xf8001fe0, 0x94001fe0, + 0x100041b1, 0x9400ffff, 0x8067003f, 0xb6290008, + 0x005f8014, 0x0442b800, 0x9442ffff, 0x5850b802, + 0x6050b802, 0xfc420000, 0x5c45b802, 0x7a82a023, + 0x10e7b809, 0x91080001, 0x300741b6, 0xb420ff6a, + 0x019f61af, 0x01bf61ae, 0x01df61ba, 0x01ff61bb, + 0x00ff41b5, 0x011f41b4, 0x019f41b8, 0x01bf41b7, + 0x01df41dd, 0x01ff41df, 0x021f41e1, 0x027f90fd, + 0x029f41bc, 0x02ff41dc, 0x031f41de, 0x033f41e0, + 0x5822b807, 0x91210c00, 0x0117b809, 0x81970ad8, + 0x91211000, 0x0217b809, 0x91210c00, 0x0317b809, + 0x80170ba0, 0x013f802c, 0xb629005f, 0x003f8038, + 0xb001000e, 0xb440001e, 0xb001000c, 0xb4400054, + 0xb001000a, 0xb4400043, 0xb0010007, 0xb440003c, + 0xb0010005, 0xb440002b, 0xb0010000, 0xb440001a, + 0xb00d0001, 0xb4200010, 0x005f418f, 0xac42bb75, + 0x8073005a, 0x9442ffff, 0x005f618f, 0x95628000, + 0x5848b802, 0xb00b8000, 0xb4200002, 0x8173ff00, + 0x1842b80b, 0x9863827a, 0x4043b802, 0x00000000, + 0x0048b802, 0xb500003f, 0x80470000, 0xb500003d, + 0x8401000f, 0x5c22b800, 0x902102d8, 0x001ff001, + 0x004db800, 0xb5000037, 0x86f70001, 0xb4600005, + 0x80750005, 0x5862b803, 0x9043e44c, 0x01d9b802, + 0x82e70002, 0x5c4cb80e, 0x9462000f, 0x5862b803, + 0x90630200, 0x005f9803, 0x59c4b80e, 0x95ceffff, + 0xb5000028, 0x87180001, 0xb4600005, 0x80750007, + 0x5862b803, 0x9043e4b8, 0x01f9b802, 0x83070002, + 0x5c4cb80f, 0x9462000f, 0x5862b803, 0x9063020c, + 0x005f9803, 0x59e4b80f, 0x95efffff, 0xb5000019, + 0x80750003, 0x5862b803, 0x90630220, 0x005f9803, + 0xb5000014, 0x87390001, 0xb4600005, 0x80750007, + 0x5862b803, 0x9043e6ac, 0x0219b802, 0x83270001, + 0x5c4cb810, 0x9462000f, 0x5862b803, 0x9063023c, + 0x005f9803, 0x5a04b810, 0x9610ffff, 0xb5000005, + 0x80750004, 0x5862b803, 0x90630268, 0x005f9803, + 0x00000000, 0x001fa022, 0x80170ba0, 0xb00c0001, + 0xb4200035, 0x023f90fb, 0x007f9811, 0x025f90fc, + 0x06d4b803, 0x007f9812, 0x4083b813, 0x00000000, + 0x0088b804, 0xb629002b, 0x24368030, 0x9421ffff, + 0x5830b801, 0x6030b801, 0x40448020, 0xb0010020, + 0xb4800003, 0x80470000, 0x80670000, 0xb500000e, + 0xb0010000, 0xb4a00004, 0x82b30080, 0x6aa1b815, + 0x4042b815, 0xb5000008, 0x6c41b802, 0x82a70017, + 0x12b5b801, 0x6875b803, 0x1842b803, 0x00000000, + 0x00000000, 0x00000000, 0x0108a022, 0x007f41b9, + 0x90630001, 0x007f61b9, 0xb003000c, 0xb420000c, + 0x92310004, 0x023fb0fb, 0x007f9811, 0x92520004, + 0x06d4b803, 0x025fb0fc, 0x007f9812, 0x80470000, + 0x4083b813, 0x00000000, 0x0088b804, 0x005f61b9, + 0x00000000, 0xb500001a, 0xb6290019, 0x24348030, + 0x9421ffff, 0x5830b801, 0x6030b801, 0x40538020, + 0xb0010020, 0xb4800003, 0x80470000, 0x80670000, + 0xb500000e, 0xb0010000, 0xb4a00004, 0x82b30080, + 0x6aa1b815, 0x4042b815, 0xb5000008, 0x6c41b802, + 0x82a70017, 0x12b5b801, 0x6875b803, 0x1842b803, + 0x00000000, 0x00000000, 0x00000000, 0x0108a022, + 0x10e7b809, 0x91080001, 0x300741b6, 0xb420ff48, + 0x00ff61b5, 0x011f61b4, 0x01df61dd, 0x01ff61df, + 0x021f61e1, 0x02ff61dc, 0x031f61de, 0x033f61e0, + 0x00ffb81d, 0x00000000, 0x00000000, 0x00000000, + 0x8057ffff, 0x80d7ffff, 0x8157ffff, 0x81d7ffff, + 0x8257ffff, 0x808f0000, 0x003f9113, 0x005f9114, + 0x7141b802, 0x80cf0700, 0x8027b064, 0x5c22b801, + 0x003fb0bc, 0x5822b801, 0x01cfb801, 0x003f90bc, + 0xb520ffff, 0x80cf0704, 0x8027b06c, 0x5c22b801, + 0x003fb0bc, 0x5822b801, 0x01cfb801, 0x003f90bc, + 0xb520ffff, 0x81e7043c, 0x82071c00, 0x82271c10, + 0x019f03a9, 0x806f001f, 0x80af001f, 0x80270400, + 0x8067a800, 0x5c62b803, 0xb6000808, 0x00cfb801, + 0x007fb0bc, 0x5862b803, 0x01cfb803, 0x007f90bc, + 0xb520ffff, 0x90210020, 0x90630020, 0x81971000, + 0x82170c00, 0xb6000004, 0x003f800c, 0x005f8010, + 0x021fa021, 0x019fa022, 0x00bfd810, 0x003fd811, + 0x70c1b80a, 0x001f980f, 0x91ef0004, 0x92100002, + 0x92310002, 0x5822b805, 0x90411000, 0x0197b802, + 0x90410c00, 0x0217b802, 0x0466b805, 0xb0000000, + 0xb4000005, 0xb6230004, 0x003f8010, 0x005f800c, + 0x1201a022, 0x0581a022, 0x858c0001, 0xb4e0ffea, + 0x80270400, 0x8067ac00, 0x5c62b803, 0xb6000808, + 0x00cfb801, 0x007fb0bc, 0x5862b803, 0x01afb803, + 0x007f90bc, 0xb520ffff, 0x90210020, 0x90630020, + 0x00ffb81c, 0x00000000, 0x00000000, 0x00000000, + 0x808f0000, 0x806f001f, 0x80af001f, 0x003f037a, + 0xb0010000, 0xb4400030, 0x81a7b7fc, 0x5da2b80d, + 0x80670500, 0xb6000208, 0x00cfb803, 0x01bfb0bc, + 0x59a2b80d, 0x01cfb80d, 0x01bf90bc, 0xb520ffff, + 0x90630020, 0x91ad0020, 0x81c7b8fc, 0x5dc2b80e, + 0x80670540, 0xb6000208, 0x00cfb803, 0x01dfb0bc, + 0x59c2b80e, 0x01cfb80e, 0x01df90bc, 0xb520ffff, + 0x90630020, 0x91ce0020, 0x81a7b3fc, 0x5da2b80d, + 0x80670600, 0xb6000408, 0x00cfb803, 0x01bfb0bc, + 0x59a2b80d, 0x01cfb80d, 0x01bf90bc, 0xb520ffff, + 0x90630020, 0x91ad0020, 0x81c7b5fc, 0x5dc2b80e, + 0x80670680, 0xb6000408, 0x00cfb803, 0x01dfb0bc, + 0x59c2b80e, 0x01cfb80e, 0x01df90bc, 0xb520ffff, + 0x90630020, 0x91ce0020, 0x005f03fa, 0xb0020000, + 0xb4000024, 0x8057ffff, 0x80d7ffff, 0x8157ffff, + 0x81d7ffff, 0x8257ffff, 0x82d7ffff, 0x8357ffff, + 0x83d7ffff, 0x83971300, 0x83171200, 0x82971100, + 0x82171000, 0x81170c00, 0x81970ff8, 0x80171400, + 0x80971500, 0x005f802c, 0x001f8028, 0xb6004010, + 0x41028000, 0x51008004, 0x007f876c, 0x0208a028, + 0x41008000, 0x49028004, 0x003f8068, 0x0388a028, + 0x41038000, 0x51018004, 0x005f802c, 0x0288a028, + 0x41018020, 0x49038024, 0x001f8028, 0x0308a028, + 0x00ffb81c, 0x83d7ffff, 0x8357ffff, 0x82d7ffff, + 0x8257ffff, 0x8157ffff, 0x81d7ffff, 0x8057ffff, + 0x80d7ffff, 0x82971200, 0x82171000, 0x81170c00, + 0x81970ffc, 0x83171800, 0x83971a00, 0x83370000, + 0x83b70000, 0x81370008, 0x81b7fff8, 0x4119880c, + 0xb6008006, 0x511d8808, 0x41498838, 0x0208a028, + 0x494d883c, 0x4119880c, 0x0288a02a, 0x00ffb81c, + 0x82670000, 0x82a70000, 0x003f037a, 0xb0010000, + 0xb4400018, 0x81a7bdfc, 0x5da2b80d, 0x80670580, + 0xb6000208, 0x00cfb803, 0x01bfb0bc, 0x59a2b80d, + 0x01cfb80d, 0x01bf90bc, 0xb520ffff, 0x90630020, + 0x91ad0020, 0x81a7eb70, 0x5da2b80d, 0x806705c0, + 0xb6000208, 0x00cfb803, 0x01bfb0bc, 0x59a2b80d, + 0x01cfb80d, 0x01bf90bc, 0xb520ffff, 0x90630020, + 0x91ad0020, 0x02bf03fa, 0x808f0000, 0xb0150000, + 0xb4000006, 0x81470040, 0x81670003, 0x81870002, + 0x81a71000, 0x81c71300, 0xb5000005, 0x81470080, + 0x81670004, 0x81870001, 0x81a71000, 0x81c71200, + 0x0017b80d, 0x0097b80e, 0x108db80a, 0x0117b804, + 0x108eb80a, 0x0197b804, 0x5841b80a, 0x108db802, + 0x0217b804, 0x108eb802, 0x0297b804, 0x106ab802, + 0x108db803, 0x0317b804, 0x108eb803, 0x0397b804, + 0x5ea2b80a, 0xb6350020, 0x001f8000, 0x003f8008, + 0x005f8004, 0x007f800c, 0x10c08010, 0x10a18018, + 0x10828014, 0x10e3801c, 0x1246b805, 0x0686b805, + 0x10c4b807, 0x0484b807, 0x80e70000, 0x80a70000, + 0x0008a032, 0x0108a034, 0x0088a026, 0x0188a024, + 0x04c08010, 0x04a18018, 0x04828014, 0x04e3801c, + 0x0646b807, 0x1286b807, 0x10c4b805, 0x0484b805, + 0x80e70000, 0x80a70000, 0x0208a032, 0x0308a034, + 0x0288a026, 0x0388a024, 0x5de1b80a, 0x82070004, + 0xb62b002a, 0x0017b80d, 0x0097b80e, 0x102db80f, + 0x0117b801, 0x104eb80f, 0x0197b802, 0x82171600, + 0x82971700, 0x0037b80f, 0x00b7b80f, 0x0137b80f, + 0x01b7b80f, 0xb630001b, 0x003f8030, 0x005f8034, + 0x5ee2b80f, 0x8013007f, 0x9800ffff, 0xb6370011, + 0x41008000, 0x51018008, 0x4902800c, 0x40c08000, + 0x0008a028, 0x48c18008, 0x50c2800c, 0x42808004, + 0x00c8b806, 0x52828008, 0x5281800c, 0x41008004, + 0x0088a034, 0x49028008, 0x4901800c, 0x011fa026, + 0x0188a028, 0x001f8001, 0x001f8005, 0x001f8009, + 0x001f800d, 0x5de1b80f, 0x5a01b810, 0x0017b80d, + 0x0097b80e, 0x902d0004, 0x0117b801, 0x904e0004, + 0x0197b802, 0x82171600, 0x82971700, 0x5ea1b80a, + 0x8013007f, 0x9800ffff, 0xb6350013, 0x003f8030, + 0x005f8034, 0x42408000, 0x52418008, 0x4a42800c, + 0x41008000, 0x0008a052, 0x49018008, 0x5102800c, + 0x42808004, 0x0108b808, 0x52828008, 0x5281800c, + 0x40c08004, 0x0088a054, 0x48c28008, 0x48c1800c, + 0x011fa048, 0x0188a046, 0x81a71100, 0x81c71200, + 0x858c0001, 0xb4e0ff7e, 0x00ffb81c, 0x00000000, + 0x005f03fa, 0x00000000, 0xb0020000, 0xb4000034, + 0x81b70080, 0x81d7ffff, 0x81f70001, 0x82370080, + 0x8257ffff, 0x82770001, 0x82b70080, 0x82d7ffff, + 0x82f70001, 0x83370080, 0x8357ffff, 0x83770001, + 0x81971000, 0x82171100, 0x82971200, 0x83171300, + 0x815703fc, 0x81370200, 0x81170c00, 0x83d703fc, + 0x83b70200, 0x83970f00, 0x8057ffff, 0x80d7ffff, + 0x80171400, 0x80971500, 0x001f800d, 0x003f8019, + 0xb6004012, 0x41008000, 0x51018004, 0x007f8011, + 0x0128a008, 0x41018000, 0x49008004, 0x009f8015, + 0x03a8a008, 0x41038000, 0x51048004, 0x001f800d, + 0x03a8a008, 0x41048020, 0x49038024, 0x003f8019, + 0x0128a008, 0x005f8028, 0x005f803c, 0x81f70000, + 0x82770000, 0x82f70000, 0x83770000, 0x00ffb81c, + 0x82370040, 0x8257ffff, 0x82770001, 0x82b70040, + 0x82d7ffff, 0x82f70001, 0x82171000, 0x82971200, + 0x8157ffff, 0x81170c00, 0x81d7ffff, 0x81970e00, + 0x8057ffff, 0x80d7ffff, 0x80171800, 0x80971a00, + 0xb600800a, 0x001f8011, 0x003f8015, 0x41008000, + 0x51018004, 0x00000000, 0x0108a028, 0x41018020, + 0x49008024, 0x00000000, 0x0188a028, 0x82770000, + 0x82f70000, 0x00ffb81c, 0x00000000, 0x00000000, + 0x8057ffff, 0x80d7ffff, 0x8157ffff, 0x808f0000, + 0x015f0384, 0x017f037a, 0xac4a0006, 0x8027b004, + 0x1042b80b, 0x5841b802, 0x1021b802, 0x0159b801, + 0x013f0325, 0x01bf0320, 0x5822b80b, 0x90210340, + 0x00ff9801, 0x8027b2e8, 0x5842b807, 0x1021b802, + 0x025bb801, 0x80070000, 0xac4d0006, 0x8027b004, + 0x1042b800, 0x5841b802, 0x1021b802, 0x0199b801, + 0x00000000, 0xac4c0006, 0x8027b078, 0x1042b80a, + 0x5842b802, 0x1021b802, 0x011bb801, 0x00000000, + 0x40d2b808, 0x00000000, 0xb0060000, 0xb4000080, + 0x005f033b, 0x80278400, 0xac600080, 0x5c22b801, + 0x10a1b803, 0xb0020000, 0xb4200002, 0x80279000, + 0xb5000001, 0x80279c00, 0x5c22b801, 0x11e1b803, + 0x80470300, 0x5822b800, 0x1042b801, 0x003f9802, + 0x806f001f, 0x80af001f, 0xb0010000, 0xb4200024, + 0x80170c00, 0x80971000, 0x003f8020, 0xb6000003, + 0x4201b806, 0x003f8020, 0x0088a030, 0x80270400, + 0xb6000208, 0x00cfb801, 0x00bfb0bc, 0x58a2b805, + 0x01afb805, 0x00bf90bc, 0xb520ffff, 0x90210020, + 0x90a50020, 0xb6000408, 0x00cfb801, 0x01ffb0bc, + 0x59e2b80f, 0x01afb80f, 0x01ff90bc, 0xb520ffff, + 0x90210020, 0x91ef0020, 0xb6000208, 0x00cfb801, + 0x00bfb0bc, 0x58a2b805, 0x01afb805, 0x00bf90bc, + 0xb520ffff, 0x90210020, 0x90a50020, 0xb5000043, + 0x80270400, 0x0087b805, 0x01c7b80f, 0xb6000208, + 0x00cfb801, 0x009fb0bc, 0x5882b804, 0x01cfb804, + 0x009f90bc, 0xb520ffff, 0x90210020, 0x90840020, + 0xb6000408, 0x00cfb801, 0x01dfb0bc, 0x59c2b80e, + 0x01cfb80e, 0x01df90bc, 0xb520ffff, 0x90210020, + 0x91ce0020, 0xb6000208, 0x00cfb801, 0x009fb0bc, + 0x5882b804, 0x01cfb804, 0x009f90bc, 0xb520ffff, + 0x90210020, 0x90840020, 0x80170c00, 0x80971000, + 0x8053007f, 0x9842ffff, 0xb6000004, 0x42028004, + 0x4a068020, 0x00000000, 0x0088a030, 0x80270400, + 0xb6000208, 0x00cfb801, 0x00bfb0bc, 0x58a2b805, + 0x01afb805, 0x00bf90bc, 0xb520ffff, 0x90210020, + 0x90a50020, 0xb6000408, 0x00cfb801, 0x01ffb0bc, + 0x59e2b80f, 0x01afb80f, 0x01ff90bc, 0xb520ffff, + 0x90210020, 0x91ef0020, 0xb6000208, 0x00cfb801, + 0x00bfb0bc, 0x58a2b805, 0x01afb805, 0x00bf90bc, + 0xb520ffff, 0x90210020, 0x90a50020, 0x5822b800, + 0x90210300, 0x0117b801, 0x80470001, 0x011fa002, + 0x90000001, 0x3000b809, 0xb480ff6b, 0x00ffb81c, + 0x8057ffff, 0x013f0325, 0x015f033b, 0x80171000, + 0x80070000, 0xb6002001, 0x001fa020, 0xb00a0001, + 0xb4c00002, 0x81679000, 0xb5000001, 0x81679c00, + 0x5d62b80b, 0x81878400, 0x5d82b80c, 0x80070000, + 0x5822b800, 0x90410300, 0x003f9802, 0x00000000, + 0xb0010000, 0xb4200019, 0xac400080, 0x00000000, + 0x10ccb802, 0x10abb802, 0x806f001f, 0x80af001f, + 0x80cf0400, 0xb6000408, 0xb520ffff, 0x00dfb0bc, + 0x58c2b806, 0x01afb806, 0x00df90bc, 0xb520ffff, + 0x80cf0400, 0x90c60020, 0x80cf0400, 0xb6000407, + 0x00bfb0bc, 0x58a2b805, 0x01afb805, 0x00bf90bc, + 0xb520ffff, 0x80cf0400, 0x90a50020, 0x90000001, + 0x3000b809, 0xb480ffde, 0x00ffb81b, 0x8057ffff, + 0x013f0325, 0x80171000, 0x80070000, 0xb6002001, + 0x001fa020, 0x81878400, 0x5d82b80c, 0x80070000, + 0x5822b800, 0x90410300, 0x003f9802, 0x00000000, + 0xb0010000, 0xb420000f, 0xac400080, 0x00000000, + 0x10ccb802, 0x806f001f, 0x80af001f, 0x80cf0400, + 0xb6000408, 0xb520ffff, 0x00dfb0bc, 0x58c2b806, + 0x01afb806, 0x00df90bc, 0xb520ffff, 0x80cf0400, + 0x90c60020, 0x90000001, 0x3000b809, 0xb480ffe8, + 0x00ffb81b, 0x8057ffff, 0x80d7ffff, 0x8157ffff, + 0x8139b000, 0x00000000, 0xb0090000, 0xb4000012, + 0x806f001f, 0x80af001f, 0x80cf0400, 0x013fb0bc, + 0x5922b809, 0x01cfb809, 0x013f90bc, 0xb520ffff, + 0x806f0003, 0x80af0003, 0x80cf0420, 0x91290020, + 0x013fb0bc, 0x5922b809, 0x01cfb809, 0x013f90bc, + 0xb520ffff, 0xb5000233, 0x80270000, 0x80171000, + 0xb6002401, 0x001fa021, 0x007f0384, 0x009f0320, + 0x00bf0385, 0x00df0386, 0x80e7b36c, 0x5821b803, + 0x1021b807, 0x0159b801, 0x5821b804, 0x1021b807, + 0x0179b801, 0x80e7b37c, 0x5821b803, 0x1021b807, + 0x0199b801, 0x5821b804, 0x1021b807, 0x01b9b801, + 0x80e7b38c, 0x5821b803, 0x1021b807, 0x01d9b801, + 0x5821b804, 0x1021b807, 0x01f9b801, 0x005f0385, + 0x8027b39c, 0x5842b802, 0x1021b802, 0x021bb801, + 0x005f0386, 0x8027b3ac, 0x5842b802, 0x1021b802, + 0x023bb801, 0x027f0383, 0x003f0328, 0x005f4195, + 0xb0130007, 0xb42000df, 0xb0010000, 0xb42000dd, + 0xb0020000, 0xb40000db, 0xb0030002, 0xb48000d9, + 0x029bb802, 0x82a7b108, 0xb00b0001, 0xb4200001, + 0xb5000005, 0xb00b0002, 0xb4200002, 0x92b500a0, + 0xb5000001, 0x92b50140, 0xb0030004, 0xb4600002, + 0x82870000, 0xb5000006, 0xb0030006, 0xb4600004, + 0xb0140001, 0xb4a00002, 0x82870001, 0xb5000000, + 0xac54000a, 0x806f0009, 0x80af0009, 0x5c22b815, + 0x80cf0440, 0x1021b802, 0x003fb0bc, 0x5822b801, + 0x01cfb801, 0x003f90bc, 0xb520ffff, 0xb0030003, + 0xb400000f, 0xb0030004, 0xb400001d, 0xb0030005, + 0xb400002b, 0xb0030006, 0xb4000042, 0xb0030007, + 0xb4000059, 0x80171000, 0x005f9440, 0x001fa002, + 0x80171038, 0x005f9440, 0x001fa002, 0xb5000073, + 0x80171000, 0x005f9440, 0x001fa002, 0x80171004, + 0x005f9443, 0x001fa002, 0x8017101c, 0x005f9446, + 0x001fa002, 0x80171034, 0x005f9449, 0x001fa002, + 0x80171038, 0x005f9440, 0x001fa002, 0xb5000063, + 0x80171000, 0x005f9440, 0x001fa002, 0x80171008, + 0x005f9441, 0x001fa002, 0x80171020, 0x005f9444, + 0x001fa002, 0x80171034, 0x005f9440, 0x001fa002, + 0x80171038, 0x005f9447, 0x001fa002, 0xb5000053, + 0x80171000, 0x005f9440, 0x001fa002, 0x80171004, + 0x005f9443, 0x001fa002, 0x8017100c, 0x005f9441, + 0x001fa002, 0x8017101c, 0x005f9446, 0x001fa002, + 0x80171024, 0x005f9444, 0x001fa002, 0x80171034, + 0x005f9449, 0x001fa002, 0x80171038, 0x005f9440, + 0x001fa002, 0x8017103c, 0x005f9447, 0x001fa002, + 0xb500003a, 0x80171000, 0x005f9440, 0x001fa002, + 0x80171008, 0x005f9441, 0x001fa002, 0x8017100c, + 0x005f9442, 0x001fa002, 0x80171020, 0x005f9444, + 0x001fa002, 0x80171024, 0x005f9445, 0x001fa002, + 0x80171034, 0x005f9440, 0x001fa002, 0x80171038, + 0x005f9447, 0x001fa002, 0x8017103c, 0x005f9448, + 0x001fa002, 0xb5000021, 0x80171000, 0x005f9440, + 0x001fa002, 0x80171004, 0x005f9443, 0x001fa002, + 0x8017100c, 0x005f9441, 0x001fa002, 0x80171010, + 0x005f9442, 0x001fa002, 0x8017101c, 0x005f9446, + 0x001fa002, 0x80171024, 0x005f9444, 0x001fa002, + 0x80171028, 0x005f9445, 0x001fa002, 0x80171034, + 0x005f9449, 0x001fa002, 0x80171038, 0x005f9440, + 0x001fa002, 0x8017103c, 0x005f9447, 0x001fa002, + 0x80171040, 0x005f9448, 0x001fa002, 0x80270001, + 0x803eff90, 0x80171000, 0x82b30020, 0x9ab50000, + 0x40158020, 0xb6000501, 0x48158020, 0x82b30020, + 0x9ab50000, 0x80470000, 0x3015b800, 0xb4600006, + 0x80171000, 0x83840226, 0xb6000603, 0x40028000, + 0x00000000, 0x0008a020, 0x80171018, 0x82b30020, + 0x9ab50000, 0x40158020, 0xb6000501, 0x48158020, + 0x82b30020, 0x9ab50000, 0x80470000, 0x3015b800, + 0xb4600006, 0x80171018, 0x83840215, 0xb6000603, + 0x40028000, 0x00000000, 0x0008a020, 0x80171030, + 0x82b30020, 0x9ab50000, 0x40158020, 0xb6000501, + 0x48158020, 0x82b30020, 0x9ab50000, 0x80470000, + 0x3015b800, 0xb4600006, 0x80171030, 0x83840204, + 0xb6000603, 0x40028000, 0x00000000, 0x0008a020, + 0xb500011e, 0x80270000, 0x803eff90, 0xb0030000, + 0xb4200067, 0x025f0322, 0xb00b0001, 0xb4200016, + 0xb0120001, 0xb4200005, 0x80171018, 0x8033007f, + 0x9821ffff, 0x001fa001, 0xb5000110, 0xb0120002, + 0xb4200005, 0x80171020, 0x8033007f, 0x9821ffff, + 0x001fa001, 0xb5000109, 0x80171018, 0x80330040, + 0x98210000, 0x001fa001, 0x80171020, 0x00000000, + 0x001fa001, 0xb5000101, 0xb00b0002, 0xb420002c, + 0xb0120000, 0xb4200008, 0x80171000, 0x8033007f, + 0x9821ffff, 0x001fa001, 0x80171038, 0x00000000, + 0x001fa001, 0xb50000f5, 0xb0120001, 0xb4200008, + 0x80171000, 0x8033005a, 0x98218279, 0x001fa001, + 0x80171030, 0x00000000, 0x001fa001, 0xb50000eb, + 0xb0120002, 0xb4200008, 0x80171008, 0x8033005a, + 0x98218279, 0x001fa001, 0x80171038, 0x00000000, + 0x001fa001, 0xb50000e1, 0x80171000, 0x80330040, + 0x98210000, 0x001fa001, 0x80171008, 0x00000000, + 0x001fa001, 0x8017100c, 0x00000000, 0x001fa001, + 0x80171038, 0x00000000, 0x001fa001, 0xb50000d3, + 0xb0120000, 0xb4200008, 0x80171000, 0x8033007f, + 0x9821ffff, 0x001fa001, 0x80171038, 0x00000000, + 0x001fa001, 0xb50000c9, 0xb0120001, 0xb4200005, + 0x80171018, 0x8033007f, 0x9821ffff, 0x001fa001, + 0xb50000c2, 0xb0120002, 0xb4200005, 0x80171020, + 0x8033007f, 0x9821ffff, 0x001fa001, 0xb50000bb, + 0x80171018, 0x80330040, 0x98210000, 0x001fa001, + 0x80171020, 0x00000000, 0x001fa001, 0xb50000b3, + 0x80070000, 0x8033007f, 0x9821ffff, 0xb600050e, + 0x144eb80f, 0xb0028000, 0xb4c00008, 0xac400006, + 0x00000000, 0x1042b800, 0x5842b802, 0x90421000, + 0x0017b802, 0x00000000, 0x001fa001, 0x90000001, + 0x59c1b80e, 0x59e1b80f, 0xb0040000, 0xb4200023, + 0xb00a0002, 0xb4000007, 0x80171004, 0x8033005a, + 0x98218279, 0x001fa001, 0x80171034, 0x00000000, + 0x001fa001, 0xb00c0002, 0xb4000009, 0x8017100c, + 0x8033ffa5, 0x98217d87, 0x001fa001, 0x8017103c, + 0x8033005a, 0x98218279, 0x001fa001, 0xb500008b, + 0x8017100c, 0x8033ffa5, 0x98217d87, 0x001fa001, + 0x80171010, 0x00000000, 0x001fa001, 0x8017103c, + 0x8033005a, 0x98218279, 0x001fa001, 0x80171040, + 0x00000000, 0x001fa001, 0xb500007c, 0xb0040001, + 0xb420002a, 0xb00a0001, 0xb4000007, 0x80171018, + 0x8033005a, 0x98218279, 0x001fa001, 0x80171020, + 0x00000000, 0x001fa001, 0xb00a0003, 0xb420000a, + 0x8053005a, 0x98428279, 0x4030b802, 0x8017101c, + 0x5821b801, 0x00000000, 0x00000000, 0x00000000, + 0x0028b801, 0x001fa001, 0xb00c0001, 0xb4200007, + 0x8053005a, 0x98428279, 0x4031b802, 0x80171024, + 0x0028b801, 0x001fa001, 0xb500005c, 0xb00c0002, + 0xb420005a, 0x8053005a, 0x98428279, 0x4031b802, + 0x80171024, 0x0028b801, 0x001fa001, 0x80171028, + 0x00000000, 0x001fa001, 0xb5000050, 0xb00b0002, + 0xb4200012, 0xb00a0001, 0xb4200008, 0x80171004, + 0x8033005a, 0x98218279, 0x001fa001, 0x80171034, + 0x00000000, 0x001fa001, 0xb5000008, 0xb00a0003, + 0xb4200006, 0x80171004, 0x00000000, 0x001fa010, + 0x80171034, 0x00000000, 0x001fa010, 0xb00c0001, + 0xb4200025, 0x027f0383, 0x003f0328, 0xb0130007, + 0xb420000b, 0xb00b0003, 0xb4200009, 0xb0010000, + 0xb4200007, 0x80171024, 0x00000000, 0x001fa011, + 0x80171054, 0x80270000, 0x001fa001, 0xb500002b, + 0xb00d0000, 0xb420000a, 0x8033005a, 0x98218279, + 0x4041b811, 0x8017100c, 0x0048b802, 0x001fa002, + 0x8017103c, 0x00000000, 0x001fa002, 0xb500001f, + 0xb00d0002, 0xb420001d, 0x80171054, 0x8033005a, + 0x98218279, 0x001fa001, 0x8017106c, 0x00000000, + 0x001fa001, 0xb5000015, 0xb00c0002, 0xb4200013, + 0xb00d0000, 0xb4200007, 0x8017100c, 0x00000000, + 0x001fa011, 0x80171040, 0x00000000, 0x001fa011, + 0xb500000a, 0xb00d0001, 0xb4200008, 0x80171054, + 0x8033005a, 0x98218279, 0x001fa001, 0x80171058, + 0x00000000, 0x001fa001, 0xb5000000, 0x029f0388, + 0x02bf0321, 0xb0140000, 0xb4000006, 0xb0150000, + 0xb4000004, 0x8017108c, 0x8033007f, 0x9821ffff, + 0x001fa001, 0x8027b078, 0x5c22b801, 0x806f001f, + 0x80af001f, 0x80cf0400, 0x003fb0bc, 0x5822b801, + 0x01afb801, 0x003f90bc, 0xb520ffff, 0x90210020, + 0x806f0003, 0x80af0003, 0x80cf0420, 0x003fb0bc, + 0x5822b801, 0x01afb801, 0x003f90bc, 0xb520ffff, + 0x81270000, 0x8033007f, 0x9821ffff, 0x80171000, + 0xb600060a, 0x80470000, 0xb6000603, 0x015f8020, + 0x0156b80a, 0x1042b80a, 0x3002b801, 0xb4a00001, + 0x81270001, 0x00000000, 0x00000000, 0x015f0323, + 0x00000000, 0xb00a0000, 0xb4200002, 0x81670000, + 0xb5000001, 0x81670001, 0x017f23fb, 0x01ff41ee, + 0x59f0b80f, 0x61f0b80f, 0x021f41ef, 0x5a10b810, + 0x6210b810, 0xb00a0003, 0xb420003b, 0x017f039f, + 0x019f41c5, 0x5990b80c, 0x6190b80c, 0xb00b0000, + 0xb400000c, 0xb00c0000, 0xb4000005, 0xac4c0100, + 0x8033001d, 0x98215500, 0x12c1b802, 0xb500000f, + 0xac4f0100, 0x8033001d, 0x98215500, 0x12c1b802, + 0xb500000a, 0xb0090000, 0xb4000005, 0xac4f0100, + 0x8033ffe2, 0x9821ab00, 0x12c1b802, 0xb5000003, + 0xac4f0100, 0x00000000, 0x02c7b802, 0xb0030000, + 0xb420007e, 0x01bf03a0, 0x01df41c9, 0x59d0b80e, + 0x61d0b80e, 0xb00d0000, 0xb400000c, 0xb00e0000, + 0xb4000005, 0xac4e0100, 0x8033001d, 0x98215500, + 0x12e1b802, 0xb5000071, 0xac500100, 0x8033001d, + 0x98215500, 0x12e1b802, 0xb500006c, 0xb0090000, + 0xb4000005, 0xac500100, 0x8033ffe2, 0x9821ab00, + 0x12e1b802, 0xb5000065, 0xac500100, 0x00000000, + 0x02e7b802, 0xb5000061, 0xb00a0002, 0xb420002f, + 0x023f9002, 0x025f9001, 0xb00f0000, 0xb4a00007, + 0xac4f0100, 0x00000000, 0x4022b811, 0x00000000, + 0x0028b801, 0x02c7b801, 0xb500000c, 0xb0090000, + 0xb4000004, 0xac4f0100, 0x00000000, 0x02c7b802, + 0xb5000006, 0xac4f0100, 0x00000000, 0x4022b812, + 0x00000000, 0x0028b801, 0x02c7b801, 0xb0030000, + 0xb4200046, 0xb0100000, 0xb4a00007, 0xac500100, + 0x00000000, 0x4022b811, 0x00000000, 0x0028b801, + 0x02e7b801, 0xb500003d, 0xb0090000, 0xb4000004, + 0xac500100, 0x00000000, 0x02e7b802, 0xb5000037, + 0xac500100, 0x00000000, 0x4022b812, 0x00000000, + 0x0028b801, 0x02e7b801, 0xb5000030, 0x023f9002, + 0x025f9001, 0xb00f0000, 0xb4a00007, 0xac4f0100, + 0x00000000, 0x4022b811, 0x00000000, 0x0028b801, + 0x02c7b801, 0xb5000006, 0xac4f0100, 0x00000000, + 0x4022b812, 0x00000000, 0x0028b801, 0x02c7b801, + 0xb0090000, 0xb4000005, 0x0047b816, 0x8033ffe2, + 0x9821ab00, 0x1042b801, 0x02c7b802, 0xb0030000, + 0xb4200016, 0xb0100000, 0xb4a00007, 0xac500100, + 0x00000000, 0x4022b811, 0x00000000, 0x0028b801, + 0x02e7b801, 0xb5000006, 0xac500100, 0x00000000, + 0x4022b812, 0x00000000, 0x0028b801, 0x02e7b801, + 0xb0090000, 0xb4000005, 0x0047b817, 0x8033ffe2, + 0x9821ab00, 0x1042b801, 0x02e7b802, 0x00000000, + 0x00000000, 0x02c8b816, 0x02dfb0cf, 0xb0030000, + 0xb4200002, 0x02e8b817, 0x02ffb0c6, 0x00ffb81b, + 0xb6001807, 0x5841b802, 0x3015b800, 0xb4800002, + 0x06b5b800, 0x98420001, 0x5aa1b815, 0x00000000, + 0x00ffb81c, 0x00000000, 0x00000000, 0x00000000, + 0x003f03f9, 0x009f0324, 0x84840001, 0xb0010000, + 0xb4000015, 0x815bb3f0, 0x81070000, 0x812707f8, + 0xb00a0000, 0xb4000006, 0x81070800, 0x81270ff8, + 0xb00a0001, 0xb4000002, 0x81071000, 0x812717f8, + 0x802500a5, 0x806500a5, 0x3001b803, 0xb420fffc, + 0x9421ffff, 0x3001b808, 0xb480000f, 0x3001b809, + 0xb4a0002d, 0xb500000c, 0xb0040000, 0xb4200003, + 0x802717ff, 0x81070000, 0xb5000007, 0xb0040001, + 0xb4200002, 0x81070800, 0xb5000003, 0x80270001, + 0x003f23f9, 0x81071000, 0xb0040000, 0xb4200001, + 0x8384026c, 0x80af001f, 0x808f0000, 0x806f0000, + 0x80670400, 0x5d22b808, 0xb600100a, 0x00cfb803, + 0x013fb0bc, 0x5922b809, 0x01afb809, 0x013f90bc, + 0x0047b86f, 0xb0020001, 0xb4c0fffd, 0x90630020, + 0x91290020, 0x801bb3f8, 0x80270001, 0xb0000001, + 0xb4000002, 0x802600a0, 0x803eb3f8, 0x914a0001, + 0xb00a0002, 0xb4a00001, 0x81470000, 0x815eb3f0, + 0x80270001, 0x003f2013, 0x00ffb81b, 0x00000000, + 0x029fb00a, 0x02bfb00b, 0x02dfb00c, 0x02ffb00d, + 0x031fb00e, 0x033fb00f, 0x033f400f, 0x0287b86f, + 0x029fb005, 0x8285009d, 0x9a940008, 0x8286009d, + 0x8285009c, 0x96b48000, 0xb0158000, 0xb40001b5, + 0x96b40100, 0xb0150100, 0xb400020c, 0x96b40400, + 0xb0150400, 0xb400020d, 0x96b40001, 0xb0150001, + 0xb400000c, 0x96b40008, 0xb0150008, 0xb40001ad, + 0x96b44000, 0xb0154000, 0xb400020c, 0x96b40002, + 0xb0150002, 0xb4000182, 0x00000000, 0x00000000, + 0xb500021e, 0x02bf9017, 0x92b50001, 0x02bfb017, + 0x82850082, 0x96f40001, 0xb0170000, 0xb4000171, + 0x5efdb814, 0x96f70001, 0xb0170001, 0xb420000b, + 0x83050069, 0x9718003f, 0x82e50064, 0x12f7b818, + 0x86f70109, 0x82feff74, 0x02e7b86f, 0x9af74000, + 0x01ffb817, 0x96f7bfff, 0x01ffb817, 0x83050081, + 0x82a5009a, 0x96b50001, 0xb0150001, 0xb4200014, + 0x82a70000, 0x02bfb017, 0x96b41840, 0xb0150800, + 0xb420000c, 0x96b40008, 0x5aa9b815, 0x96d46000, + 0x5ec3b816, 0x82f3000f, 0x9af7c00f, 0x1718b817, + 0x1ab5b818, 0x1ab5b816, 0x9ab50340, 0x82a60081, + 0xb500014c, 0x9b180180, 0x83060081, 0xb5000149, + 0x82a5009a, 0x96b50002, 0xb0150002, 0xb420001b, + 0x82a70000, 0x02bfb017, 0x96b41800, 0xb0151800, + 0xb4000013, 0x96b40040, 0xb0150040, 0xb4200004, + 0xa3180c00, 0x9b180340, 0x83060081, 0xb5000139, + 0x96b40008, 0x5aa9b815, 0x96d46000, 0x5ec3b816, + 0x82f3000f, 0x9af7c00f, 0x1718b817, 0x1ab5b818, + 0x1ab5b816, 0x9ab50340, 0x82a60081, 0xb500012d, + 0x9b180180, 0x83060081, 0xb500012a, 0x82a500c1, + 0x96b5000f, 0xb015000b, 0xb420000e, 0x96b40020, + 0xb0150020, 0xb400000b, 0x96b40200, 0xb0150200, + 0xb4000008, 0x82c50086, 0x82e50094, 0x3016b817, + 0xb4400004, 0x06f7b816, 0xb017ff00, 0xb4400001, + 0xb5000118, 0x96b46000, 0xb0156000, 0xb4000011, + 0x96b41820, 0xb0150820, 0xb4200004, 0x9b391000, + 0x82a5009a, 0x96b5feff, 0x82a6009a, 0x96b40040, + 0xb0150040, 0xb4200001, 0x9739efff, 0x96b91000, + 0xb0151000, 0xb4200003, 0x82a5009a, 0x9ab50100, + 0x82a6009a, 0x96b40040, 0xb0150040, 0xb4200019, + 0x96b41800, 0xb0151800, 0xb4200006, 0x96b98000, + 0xb0158000, 0xb4200003, 0x9b180180, 0x83060081, + 0xb50000f8, 0x96d80c00, 0x82b300ff, 0x9ab5f3ff, + 0x1718b815, 0xb0160c00, 0xb4000007, 0x82e50098, + 0x96f70400, 0xb0170400, 0xb4200002, 0x82c70c00, + 0xb5000001, 0xa2d60c00, 0x1b18b816, 0x9b180340, + 0xb50000c4, 0x96b40220, 0xb0150000, 0xb4e00021, + 0x82a5009d, 0x82f3ffff, 0x16b5b817, 0x82f33800, + 0x3015b817, 0xb420001b, 0x96f98000, 0xb0178000, + 0xb4000018, 0x82a70000, 0x02bfb017, 0x82c5009d, + 0x96d6ffff, 0x82b3c800, 0x9ab58001, 0x82e500c1, + 0x96f7000f, 0xb017000b, 0xb4000002, 0x82b38800, + 0x9ab58001, 0x1ab5b816, 0x82c5009a, 0x96d60020, + 0xb0160020, 0xb4200002, 0x82b3c800, 0x9ab58001, + 0x82a6009d, 0x02ff9017, 0x00000000, 0xb0170040, + 0xb4800000, 0x5eb5b814, 0x96b500f0, 0x96f46000, + 0x5eedb817, 0x1ab5b817, 0xb0170003, 0xb4000004, + 0x96b500ef, 0x96f70001, 0x5ae4b817, 0x1ab5b817, + 0x96d41800, 0xb0161800, 0xb400000a, 0x96f900ff, + 0x96b500ff, 0x9739ff00, 0x1b39b815, 0x02a7b817, + 0x96b500f3, 0x96d40008, 0x5ec1b816, 0x1ab5b816, + 0xb500000c, 0x96f98000, 0xb0178000, 0xb4200007, + 0x5efeb814, 0x96f70001, 0xb0170001, 0xb4000003, + 0x9b180180, 0x83060081, 0xb50000a2, 0x96b500f3, + 0x9ab50008, 0x9739fff3, 0x96d40020, 0xb0160020, + 0xb4200019, 0x82c7001f, 0x82c600c9, 0x9b398000, + 0x82c70000, 0x02dfb017, 0x96d40010, 0x5ac8b816, + 0x82f300ff, 0x9af7cfff, 0x1718b817, 0x1b18b816, + 0x9b180340, 0x82c5009d, 0x96d6ffff, 0x82f33800, + 0x9af78001, 0x1af7b816, 0x82c5009a, 0x96d60020, + 0xb0160020, 0xb4200002, 0x82f3c800, 0x9af78001, + 0x82e6009d, 0xb500005f, 0x97397fff, 0x96b500ff, + 0x5aaab815, 0x82f300fc, 0x9af703ff, 0x1718b817, + 0x1b18b815, 0x9b180340, 0x82c5009a, 0x96d60010, + 0xb0160010, 0xb4200027, 0x82c70000, 0x02dfb017, + 0x82c50086, 0x92d60bb8, 0x82c60086, 0x82c50094, + 0x5eefb818, 0x96f70003, 0xb0170003, 0xb4200002, + 0x82e70bb8, 0xb5000001, 0x82e70bb8, 0x12d6b817, + 0x82e50081, 0x9af70020, 0x82e60081, 0x82c60094, + 0xa2f70020, 0x82e60081, 0x82f30001, 0x16f7b818, + 0x5ef0b817, 0xb0170001, 0xb4000004, 0x96f84000, + 0x5ee4b817, 0x9718f3ff, 0x1b18b817, 0x82f32800, + 0x9af78000, 0x82e6009d, 0x83060081, 0x83070001, + 0x8306009f, 0x8305009c, 0xb0180001, 0xb4e0fffb, + 0xb50000f6, 0x82c5009d, 0x82f33800, 0x9af78001, + 0x3016b817, 0xb420000f, 0x82b3c800, 0x9ab58001, + 0x82e500c1, 0x96f7000f, 0xb017000b, 0xb4000002, + 0x82b38800, 0x9ab58001, 0x82c5009a, 0x96d60020, + 0xb0160020, 0xb4200002, 0x82b3c800, 0x9ab58001, + 0x82a6009d, 0x82c5009a, 0x96d60080, 0xb0160080, + 0xb4000013, 0x02df9017, 0x00000000, 0xb0160010, + 0xb480000f, 0x82c500c1, 0x96d6000f, 0xb016000b, + 0xb400000b, 0x82c50087, 0x96d60080, 0x5ac7b816, + 0x82c50098, 0x96d60800, 0x5ac3b816, 0x96f84000, + 0x3017b816, 0xb4200002, 0x033f400f, 0x9b394000, + 0x9739bfff, 0x82e50061, 0x96f70008, 0xb0170008, + 0xb4000005, 0x5eefb818, 0x96f70003, 0xb0170003, + 0xb4000001, 0x9718ffff, 0x96b41800, 0xb0151800, + 0xb4000008, 0x5eb9b814, 0x96b5000f, 0x82c50099, + 0x5ed0b816, 0x96f6000f, 0x5ab0b815, 0x82a60099, + 0xb5000002, 0x5ef9b814, 0x96f7000f, 0x5aecb817, + 0x82c5009a, 0x96d60fff, 0x1ad6b817, 0x82c6009a, + 0x96b46000, 0xb0156000, 0xb4200005, 0x5ae2b817, + 0x82d30ffc, 0x9ad63fff, 0x1718b816, 0x1b18b817, + 0x83060081, 0x83070001, 0x8306009f, 0x8305009c, + 0xb0180001, 0xb4e0fffb, 0x00000000, 0xb500009f, + 0x82850083, 0x96b400ff, 0xb015003c, 0xb4200019, + 0x96b92000, 0xb0152000, 0xb4000002, 0x9b392000, + 0xb5000014, 0x9739d3ff, 0x82870000, 0x82860087, + 0x82870008, 0x82860083, 0x829bff78, 0x82a7001f, + 0xb0140400, 0xb4000001, 0x82a70010, 0x82a600c9, + 0x829bff78, 0x00000000, 0x828600cb, 0x8285009d, + 0x82b3ffff, 0x9ab5fffd, 0x1694b815, 0x8286009d, + 0xb5000000, 0x83070002, 0x8306009f, 0x00000000, + 0xb500007e, 0x83078000, 0x8306009f, 0x00000000, + 0xb500007a, 0x82850094, 0x82a50086, 0x06b5b814, + 0x02b6b815, 0xb0151700, 0xb440004c, 0x8285006c, + 0x969400ff, 0xb0140024, 0xb4000019, 0xb0140012, + 0xb4000017, 0x8285009a, 0x5eedb814, 0x96f70003, + 0xb0170003, 0xb4000009, 0x82a50083, 0x5ea8b815, + 0x96b500ff, 0xb0150020, 0xb4400002, 0x82c70bbc, + 0xb5000001, 0x82c70bb8, 0xb5000008, 0x82a50083, + 0x5ea8b815, 0x96b500ff, 0xb0150020, 0xb4400002, + 0x82c71199, 0xb5000001, 0x82c71197, 0xb5000017, + 0xb500002e, 0x8285009a, 0x5eedb814, 0x96f70003, + 0xb0170003, 0xb4000009, 0x82a50083, 0x5ea8b815, + 0x96b500ff, 0xb0150020, 0xb4400002, 0x82c70e12, + 0xb5000001, 0x82c70e0e, 0xb5000008, 0x82a50083, + 0x5ea8b815, 0x96b500ff, 0xb0150020, 0xb4400002, + 0x82c70e12, 0xb5000001, 0x82c70e0e, 0x82e50086, + 0x12f7b816, 0x02bf9017, 0xb0150020, 0xb480000b, + 0x82a5009a, 0x96b56000, 0xb0156000, 0xb4000007, + 0x82a50098, 0x96d50a00, 0xb0160a00, 0xb4000002, + 0xb0160000, 0xb4200001, 0x92f705dc, 0x82850081, + 0x9ab40020, 0x82a60081, 0x82c50094, 0x82e60094, + 0x82860081, 0x86b705dc, 0x82a6009b, 0x83070008, + 0x8306009f, 0x00000000, 0xb5000024, 0x83070100, + 0x8306009f, 0x00000000, 0xb5000020, 0x83070000, + 0x83050081, 0x9b180180, 0x83060081, 0x83070400, + 0x8306009f, 0x00000000, 0xb5000018, 0x82870000, + 0x82850082, 0x5eb7b814, 0x96b500fc, 0x96d40006, + 0x5ec1b816, 0x1ab5b816, 0x5aacb815, 0x83050081, + 0x82d3001c, 0x9ad600ff, 0x1718b816, 0x1b18b815, + 0x9b180e00, 0x83060081, 0x83074000, 0x8306009f, + 0x8305009d, 0x82d3ffff, 0x9ad6bfff, 0x1718b816, + 0x8306009d, 0x00000000, 0xb5000000, 0x029f9005, + 0x01ffb814, 0x033f600f, 0x029f900a, 0x02bf900b, + 0x02df900c, 0x02ff900d, 0x031f900e, 0x033f900f, + 0x00ffb81e, 0x02ff9010, 0x92f70b43, 0x02ffb010, + 0x02ff90cb, 0x82bbffdc, 0x829bffd8, 0x93150004, + 0x3014b815, 0xb400000f, 0x02dbb818, 0x029bb815, + 0x3017b816, 0xb480000b, 0x5a81b814, 0x029fb010, + 0x82860095, 0x8293001f, 0x9294fe00, 0x92b50008, + 0x3015b814, 0xb4800002, 0x82b3001f, 0x92b5fa00, + 0x82beffdc, 0x82850086, 0x83250094, 0x06d4b819, + 0x02d6b816, 0xb016ffff, 0xb4a00009, 0x82c50081, + 0x9ab60020, 0x82a60081, 0x82a50086, 0x92b50bbb, + 0x82a60094, 0x82c60081, 0x86b505df, 0x82a6009b, + 0x00ffb81c, 0x82870001, 0x829ef500, 0x82850086, + 0x83250094, 0x06d4b819, 0x02d6b816, 0xb016ffff, + 0xb4a0000b, 0x82870001, 0x829ef504, 0x82c50081, + 0x9ab60020, 0x82a60081, 0x82a50086, 0x92b50bbb, + 0x82a60094, 0x82c60081, 0x86b505df, 0x82a6009b, + 0x00ffb81c, 0x82070028, 0x023f9006, 0x83a4ef4f, + 0x80070000, 0x001fb011, 0x001f204f, 0x003fb800, + 0x001f9006, 0x5803b800, 0x80338000, 0x1800b801, + 0x003fb800, 0x005f4193, 0x5c41b802, 0x80350000, + 0x00000000, 0x0027b860, 0x80150010, 0x5810b800, + 0x80750010, 0x1863b800, 0x8087ffff, 0x80a7770b, + 0x80c70000, 0x1403b804, 0x3000b805, 0xb4000008, + 0x5888b804, 0x58a8b805, 0x90c60001, 0xb0060003, + 0xb4a0fff8, 0x84420001, 0xb4e0ffee, 0xb5000027, + 0xb0060003, 0xb4200007, 0x80150010, 0x5810b800, + 0x81150010, 0x950800ff, 0xb0080077, 0xb4000001, + 0xb500fff4, 0x001f400e, 0x98000010, 0x98004000, + 0x9400fffe, 0x001f600e, 0x80e71f60, 0x001f4000, + 0x94000080, 0xb0000080, 0xb4200001, 0x80e774b0, + 0x00ffb008, 0x80e70020, 0xb0060000, 0xb400000e, + 0x58e3b806, 0x90210020, 0x81070000, 0x5938b803, + 0x1908b809, 0x9523ff00, 0x5928b809, 0x1908b809, + 0x5d28b803, 0x9529ff00, 0x1908b809, 0x5d38b803, + 0x1908b809, 0x011fb011, 0x00ff204f, 0x80137fff, + 0x9800ffe7, 0x1421b800, 0x5c23b801, 0x001f9006, + 0x0441b800, 0x3001b800, 0xb4600002, 0x0440b801, + 0xa4422000, 0x007f90cb, 0x1063b802, 0x007fb0cb, + 0x003fb006, 0x803effec, 0x80470001, 0x005f2013, + 0xb500ebd7, 0x001f400e, 0x9400000f, 0xb0000000, + 0xb4200001, 0x00ffb81f, 0xb0000001, 0xb4000005, + 0xb0000003, 0xb4000003, 0xb0000002, 0xb4000001, + 0x00ffb81f, 0x80070001, 0x001f2013, 0xb500ebc8, + 0x001f9012, 0x001fb100, 0x001f004c, 0x001f2404, + 0x801bfef0, 0x8058fef4, 0x803bff68, 0x8078ff6c, + 0x2000b801, 0x2042b803, 0x001fb104, 0x005f2414, + 0x82e70001, 0x83640048, 0x029fb014, 0x829efef0, + 0x8286000f, 0x02bf2054, 0x82bcfef4, 0x82a6000e, + 0x00ffb81a, 0x80e70001, 0x801336e3, 0x9800eb76, + 0x001fb100, 0x800700ab, 0x001f2404, 0x801bc3e8, + 0x8058c3ec, 0x83640024, 0x82e70000, 0x83640036, + 0x029fb300, 0x029fb100, 0x02bf2c04, 0x02bf2404, + 0x801bc000, 0x8058c004, 0x8364001b, 0x82e70000, + 0x8364002d, 0x001f9300, 0x3000b814, 0xb420000a, + 0x001f0c04, 0x3000b815, 0xb4200007, 0x829efef0, + 0x82bcfef4, 0x029fb012, 0x02bf204c, 0x82870001, + 0x829cfef5, 0x00ffb81a, 0xb0070000, 0xb4000007, + 0x80e70000, 0x801399fa, 0x9800c92e, 0x001fb100, + 0x800700af, 0x001f2404, 0xb500ffdc, 0x82870000, + 0x829cfef5, 0x00ffb81a, 0x80c700ff, 0x803bff68, + 0x8078ff6c, 0x14a0b806, 0x2063b805, 0x007f2414, + 0x2021b802, 0x58c8b806, 0x14a0b806, 0x58b0b805, + 0x2021b805, 0x58c8b806, 0x14a0b806, 0x2021b805, + 0x58c8b806, 0x14a0b806, 0x5cb0b805, 0x2021b805, + 0x003fb104, 0x00ffb81b, 0x82c70000, 0x83070400, + 0x83270005, 0x8197040c, 0x81d7ffff, 0x83840126, + 0x83840001, 0x00ffb81b, 0x808f0000, 0x806f001f, + 0x80af001f, 0x80270140, 0x81e7ef98, 0x5de2b80f, + 0xb6000208, 0x00cfb801, 0x01ffb0bc, 0x59e2b80f, + 0x01cfb80f, 0x01ff90bc, 0xb520ffff, 0x91ef0020, + 0x90210020, 0x80270180, 0x81e7ee90, 0x5de2b80f, + 0xb6000208, 0x00cfb801, 0x01ffb0bc, 0x59e2b80f, + 0x01cfb80f, 0x01ff90bc, 0xb520ffff, 0x91ef0020, + 0x90210020, 0x8057ffff, 0x80170430, 0x80070410, + 0x80270408, 0xb6000509, 0x005ff000, 0x90420500, + 0x007ff001, 0x90630600, 0x009ff002, 0x00bff003, + 0x2004a025, 0x90000001, 0x90210001, 0x80070414, + 0x80d7ffff, 0x8097045c, 0x8017043c, 0xb6000404, + 0x005ff000, 0x007f87e0, 0x84000001, 0x2082a7e3, + 0x80970460, 0x80170440, 0x2082b803, 0x007f8000, + 0x2083a004, 0x80170430, 0x80970450, 0x80270408, + 0xb6000508, 0x005f8024, 0x90420500, 0x007ff001, + 0x90630600, 0x009ff002, 0x00bff003, 0x2004a025, + 0x90210001, 0x80170440, 0x00000000, 0x02bf87e0, + 0x80970460, 0x82870000, 0xb6000404, 0x005f87e4, + 0x5a88b814, 0x204287e0, 0x1a94b802, 0x00ffb81c, + 0x001f0a49, 0x001f2709, 0x001f0a41, 0x001f2708, + 0x001f0a46, 0x001f2707, 0x001f0a48, 0x001f2706, + 0x001f0a42, 0x001f2705, 0x001f0a47, 0x001f2704, + 0x001f0a45, 0x001f2703, 0x001f0a43, 0x001f2702, + 0x001f0a40, 0x001f2701, 0x001f0a44, 0x001f2700, + 0x001f0c25, 0xa020000c, 0x94400001, 0x94600002, + 0x94810004, 0x94a10008, 0x94c00010, 0x5943b802, + 0x5861b803, 0x5882b804, 0x5ca2b805, 0x5cc4b806, + 0x194ab803, 0x194ab804, 0x194ab805, 0x194ab806, + 0x015f2738, 0x801bef90, 0x003f91c1, 0x5c28b801, + 0x005f91c2, 0x5858b802, 0x1821b802, 0x2000b801, + 0x001fb1c4, 0x8018ef94, 0x003f0709, 0x2000b801, + 0x001f2714, 0x82c70001, 0x82e70001, 0x83070710, + 0x8327001e, 0x81970735, 0x8384009f, 0x02df0738, + 0x82170a30, 0x838400f1, 0x819efef0, 0x817cfef4, + 0x819eff68, 0x817cff6c, 0x00ffb81b, 0x820f001f, + 0x8018fef8, 0x8057ffff, 0x001f2709, 0x8018fef6, + 0x80d7ffff, 0x001f2708, 0x8018fefa, 0x8157ffff, + 0x001f2707, 0x8018fefd, 0x81d7ffff, 0x001f2706, + 0x8018fefb, 0x802f001f, 0x001f2705, 0x8018fefe, + 0x00000000, 0x001f2704, 0x8018fef9, 0x00000000, + 0x001f2703, 0x8018feff, 0x00000000, 0x001f2702, + 0x8018fef7, 0x00000000, 0x001f2701, 0x8018fefc, + 0x00000000, 0x001f2700, 0x001f0c25, 0xa0200011, + 0x94410001, 0x94600002, 0x94800004, 0x94a00008, + 0x94c10010, 0x5941b802, 0x5861b803, 0x5c82b804, + 0x58a1b805, 0x5cc1b806, 0x194ab803, 0x194ab804, + 0x194ab805, 0x194ab806, 0x015f2738, 0x801bef90, + 0x003f91c1, 0x5c28b801, 0x005f91c2, 0x5858b802, + 0x1821b802, 0x2000b801, 0x001fb1c4, 0x8018ef94, + 0x003f0709, 0x2000b801, 0x001f2714, 0x82c70001, + 0x82e70001, 0x83070710, 0x8327001e, 0x81970735, + 0x83840055, 0x02df0738, 0x82170a20, 0x838400a7, + 0x819efef0, 0x817cfef4, 0x5ac8b80c, 0x02ff0a44, + 0x1ad6b817, 0x02dfb291, 0x5ed8b80c, 0x5968b80b, + 0x1ad6b80b, 0x02df6524, 0x00ffb81b, 0x820f001f, + 0x8018fefe, 0x8057ffff, 0x001f2709, 0x8018fefa, + 0x80d7ffff, 0x001f2708, 0x8018fefc, 0x8157ffff, + 0x001f2707, 0x8018feff, 0x81d7ffff, 0x001f2706, + 0x8018fef8, 0x802f001f, 0x001f2705, 0x8018fefb, + 0x00000000, 0x001f2704, 0x8018fefd, 0x00000000, + 0x001f2703, 0x8018fef6, 0x00000000, 0x001f2702, + 0x8018fef9, 0x00000000, 0x001f2701, 0x8018fef7, + 0x00000000, 0x001f2700, 0x801bef90, 0x003f91c1, + 0x5c28b801, 0x005f91c2, 0x5858b802, 0x1821b802, + 0x2000b801, 0x001fb1c4, 0x8018ef94, 0x003f0709, + 0x2000b801, 0x001f2714, 0x82c70001, 0x82e70001, + 0x83070710, 0x8327001e, 0x81970735, 0x83840016, + 0x83270000, 0x831bfef0, 0x82f8fef4, 0x02c7b819, + 0x82170a28, 0x83840065, 0x300cb818, 0xb4200002, + 0x300bb817, 0xb4000006, 0x93390001, 0xb0190020, + 0xb480fff6, 0x83270000, 0x833cfef5, 0x00ffb81b, + 0x019fb290, 0x017f2a44, 0x033f2c25, 0x83270001, + 0x833cfef5, 0x00ffb81b, 0x0007b818, 0x90000003, + 0x00000000, 0x015ff000, 0x90000001, 0x5949b80a, + 0x013ff000, 0x194ab809, 0x84000002, 0x994a0100, + 0x017ff000, 0x958b00f8, 0x5981b80c, 0x956b0007, + 0x198cb80b, 0x84000002, 0x998c0008, 0x017ff000, + 0x90000001, 0x5971b80b, 0x198cb80b, 0x017ff000, + 0x5969b80b, 0x198cb80b, 0x81a70000, 0x94d90003, + 0x82a70000, 0xb6260019, 0xb6000818, 0x5df0b80a, + 0x5e02b80a, 0x21efb810, 0x95ef0001, 0x5941b80a, + 0x194ab80f, 0x21efb816, 0x5e18b80c, 0x5e35b80c, + 0x5e54b80c, 0x5e6cb80c, 0x2210b811, 0x2252b813, + 0x2210b812, 0x96100001, 0x5981b80c, 0x198cb810, + 0x2210b817, 0x10afb810, 0x10a5b80d, 0x5da1b805, + 0x94a50001, 0x5aa1b815, 0x1ab5b805, 0x019fa7f5, + 0x5cc2b819, 0xb626001c, 0x82870000, 0xb6000419, + 0xb6000818, 0x5df0b80a, 0x5e02b80a, 0x21efb810, + 0x95ef0001, 0x5941b80a, 0x194ab80f, 0x21efb816, + 0x5e18b80c, 0x5e35b80c, 0x5e54b80c, 0x5e6cb80c, + 0x2210b811, 0x2252b813, 0x2210b812, 0x96100001, + 0x5981b80c, 0x198cb810, 0x2210b817, 0x10afb810, + 0x10a5b80d, 0x5da1b805, 0x94a50001, 0x5a81b814, + 0x1a94b805, 0x019fa7f4, 0x00ffb81c, 0x8257ffff, + 0x808f0000, 0x806f001f, 0x80af001f, 0x80270200, + 0x81e7ec70, 0x5de2b80f, 0xb6000208, 0x00cfb801, + 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, 0x01ff90bc, + 0xb520ffff, 0x91ef0020, 0x90210020, 0x80270240, + 0x81e7ed70, 0x5de2b80f, 0xb6000208, 0x00cfb801, + 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, 0x01ff90bc, + 0xb520ffff, 0x91ef0020, 0x90210020, 0x80270180, + 0x81e7ee90, 0x5de2b80f, 0xb6000208, 0x00cfb801, + 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, 0x01ff90bc, + 0xb520ffff, 0x91ef0020, 0x90210020, 0x806f0007, + 0x80af0007, 0x80270280, 0x81e7ee70, 0x5de2b80f, + 0x00cfb801, 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, + 0x01ff90bc, 0xb520ffff, 0x91ef0020, 0x90210020, + 0x80170760, 0x001f0700, 0x001fa020, 0x001f0701, + 0x001fa020, 0x001f0702, 0x001fa020, 0x001f0703, + 0x001fa020, 0x001f0704, 0x001fa000, 0x80970750, + 0x81170770, 0x82a70735, 0x83a40060, 0x001f87e4, + 0xb6000405, 0x86b50001, 0x83a4005c, 0x001f8004, + 0x003f87e8, 0x2080a7e1, 0x80970770, 0x80170750, + 0x81170750, 0x81970740, 0x82a70730, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a40050, 0x001f87e4, + 0xb6000405, 0x86b50001, 0x83a4004c, 0x001f8004, + 0x003f87e8, 0x2080a7e1, 0x80970750, 0x80170770, + 0x81170770, 0x81970760, 0x82a7072b, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a40040, 0x83a4004e, + 0xb6000407, 0x86b50001, 0x83a4003c, 0x001f8004, + 0x003f87e8, 0x2080a001, 0x83a40047, 0x00000000, + 0x80970770, 0x80170750, 0x81170750, 0x81970740, + 0x82a70726, 0x001f800c, 0x003f8008, 0x2100a001, + 0x83a4002e, 0x83a4003c, 0xb6000407, 0x86b50001, + 0x83a4002a, 0x001f8004, 0x003f87e8, 0x2080a001, + 0x83a40035, 0x00000000, 0x80970750, 0x80170770, + 0x81170770, 0x81970760, 0x82a70721, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a4001c, 0x001f87e4, + 0xb6000405, 0x86b50001, 0x83a40018, 0x001f8004, + 0x003f87e8, 0x2080a7e1, 0x80970770, 0x80170750, + 0x81170750, 0x81970740, 0x82a7071c, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a4000c, 0x017f87e4, + 0x81870000, 0xb6000406, 0x86b50001, 0x83a40007, + 0x001f87e4, 0x200087e8, 0x5988b80c, 0x198cb800, + 0x021fa02c, 0x021fa00b, 0x00ffb81c, 0x005ff015, + 0x90420600, 0x003f87e0, 0x001ff002, 0x2060b801, + 0x90630800, 0x90960a00, 0x001ff003, 0x003ff004, + 0x20a0b801, 0x90a50900, 0x00000000, 0x001ff005, + 0x009fa000, 0x00ffb81d, 0x001f8004, 0x5c21b800, + 0x5847b800, 0x1821b802, 0x942100ff, 0x2080a7e1, + 0x00ffb81d, 0x00000000, 0x00000000, 0x00000000, + 0x015f400e, 0x944a4000, 0xb0024000, 0xb420001a, + 0x954abfff, 0x015f600e, 0x820f001f, 0x802f001f, + 0x81470000, 0x015f23f9, 0x015fb0ba, 0x8057ffff, + 0x80770000, 0x82970400, 0x82d7ffff, 0x82f70000, + 0xb6000702, 0xb6000001, 0x029fa02a, 0x80275480, + 0x005fb801, 0x8033001f, 0x9821c000, 0x803effe0, + 0x90212000, 0x803effe4, 0x80d9ff80, 0x00df6001, + 0x81477528, 0x015fb008, 0x003f0324, 0xb0010000, + 0xb4200076, 0x8344ebe6, 0xb0180000, 0xb4000004, + 0x011f400e, 0x1908b818, 0x011f600e, 0x00ffb81f, + 0x8344f187, 0xb00b0000, 0xb4000006, 0x023f400e, + 0x9a310002, 0x023f600e, 0x82270000, 0x023f2012, + 0x00ffb81f, 0x8364ed6a, 0x82270000, 0x023f2011, + 0x80070000, 0x80170800, 0xb6002002, 0xb6003001, + 0x001fa020, 0x82270000, 0x003fb811, 0x02bf9006, + 0x5aa3b815, 0x82338000, 0x1a31b815, 0x003fb811, + 0x8067e950, 0x5c62b803, 0x81f50000, 0x019f4193, + 0x0267b80c, 0xadcc0010, 0x80170800, 0x80130000, + 0x9800f872, 0x001fa020, 0x80134e1f, 0x98000001, + 0x001fa020, 0x59d0b80e, 0x81150010, 0x1908b80e, + 0x001fa028, 0x858c0001, 0x5e01b80c, 0x5e25b810, + 0xb6310006, 0xb6002005, 0x81150010, 0x5910b808, + 0x00000000, 0x81350010, 0x1808a029, 0x9630001f, + 0xb0110000, 0xb4000006, 0xb6310005, 0x81150010, + 0x5910b808, 0x00000000, 0x81350010, 0x1808a029, + 0x962c0001, 0xb0110000, 0xb4000003, 0x81150010, + 0x5910b808, 0x001fa028, 0x019f9006, 0x958cffff, + 0x00df4193, 0x58c1b806, 0x118cb806, 0xb00ce000, + 0xb4800002, 0x858ce000, 0x918cc000, 0x8153001f, + 0x118cb80a, 0x819effec, 0x019fb006, 0x015f4193, + 0x5941b80a, 0x019f90cb, 0x118cb80a, 0x019fb0cb, + 0x019f90ba, 0x918c0001, 0x019fb0ba, 0xb00c0002, + 0xb4200016, 0x019f400e, 0x940c8000, 0xb0008000, + 0xb4200012, 0x958c7fff, 0x019f600e, 0x80070000, + 0x800600a0, 0x80073da1, 0x800600a1, 0x801bff60, + 0x00000000, 0x801eff60, 0x00000000, 0x801bff60, + 0x00000000, 0x801eff60, 0x80130001, 0x98003da1, + 0x800600a1, 0x80070001, 0x800600a0, 0x003f0324, + 0x90210001, 0xb0010005, 0xb4a00001, 0x80270000, + 0x003f2324, 0x00ffb81f, 0x00000000, 0x00000000, + 0x003f03f9, 0x009f0324, 0x84840001, 0xb0010000, + 0xb4000011, 0x815bb3f0, 0x81070000, 0x81270bf4, + 0xb00a0000, 0xb4000002, 0x81070c00, 0x81271800, + 0x802500a5, 0x806500a5, 0x3001b803, 0xb420fffc, + 0x9421ffff, 0x3001b808, 0xb480000b, 0x3001b809, + 0xb4a0002e, 0xb5000008, 0xb0040000, 0xb4200003, + 0x802717ff, 0x81470000, 0xb5000003, 0x80270001, + 0x003f23f9, 0x81470c00, 0xb0040000, 0xb4200001, + 0x8384fc04, 0x80af001f, 0x808f0002, 0x806f0000, + 0x807bbf34, 0x5d22b80a, 0xb600080a, 0x00cfb803, + 0x013fb0bc, 0x5922b809, 0x01afb809, 0x013f90bc, + 0x0047b86f, 0xb0020001, 0xb4c0fffd, 0x90630020, + 0x91290060, 0x808f0000, 0x813bb3f8, 0x80270001, + 0xb0090001, 0xb4000002, 0x802600a0, 0x803eb3f8, + 0x81270c00, 0xb00a0000, 0xb4000001, 0x81270000, + 0x813eb3f0, 0xb0030800, 0xb4800001, 0x80670200, + 0x807ebf34, 0x80270001, 0x003f2013, 0x00ffb81b, +}; + +static u32 AC3I2S240Ucode1f8000[] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00020000, 0xffff0005, 0xffffffff, + 0x00050001, 0xffffffff, 0xffffffff, 0x00020000, + 0xffff0005, 0xffffffff, 0x00010000, 0x00050002, + 0xffffffff, 0x00020000, 0x00050003, 0xffffffff, + 0x00010000, 0x00030002, 0xffff0005, 0x00020000, + 0x00040003, 0xffff0005, 0x00010000, 0x00030002, + 0x00050004, 0x0019000d, 0x003d0025, 0x00250019, + 0x00fd003d, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x007fffff, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00000000, 0x007fffff, 0x00000000, + 0x00000000, 0x00000000, 0x007fffff, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x007fffff, + 0x007fffff, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x007fffff, 0x007fffff, 0x00000000, + 0x00000000, 0x00000000, 0x007fffff, 0x00000000, + 0x00000000, 0x00599999, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00599999, + 0x007fffff, 0x00599999, 0x00000000, 0x00599999, + 0x00000000, 0x00000000, 0x00000000, 0x00599999, + 0x00000000, 0x00599999, 0x007fffff, 0x00000000, + 0x00599999, 0x00599999, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00599999, 0x00599999, + 0x007fffff, 0x007fffff, 0x00000000, 0x00599999, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00599999, 0x007fffff, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00000000, 0x007fffff, 0x00000000, + 0x00000000, 0x00000000, 0x007fffff, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x007fffff, + 0x007fffff, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x007fffff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x007fffff, 0x00000000, + 0x007fffff, 0x00000000, 0x007fffff, 0x00400000, + 0x00200000, 0x00100000, 0x00080000, 0x00040000, + 0x00020000, 0x00010000, 0x00008000, 0x00004000, + 0x00002000, 0x00001000, 0x00000800, 0x00000400, + 0x00000200, 0x00000100, 0x00000080, 0x00000040, + 0x00000020, 0x00000010, 0x00000008, 0x00000004, + 0x00000002, 0x00000001, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00010002, + 0x00030002, 0x00030002, 0x00030002, 0x00000000, + 0x00000000, 0x00010001, 0x00020002, 0x4000a000, + 0xe000a000, 0xf000b000, 0xf800b800, 0x005a8279, + 0x004c1bf8, 0x00400000, 0x004c1bf8, 0x005a8279, + 0x00400000, 0x00000000, 0x00400000, 0x03020100, + 0x00000000, 0x00000080, 0x00000020, 0x00000008, + 0x00000000, 0x00000001, 0x00010001, 0x10001000, + 0x10001004, 0x10041004, 0x10041004, 0x10041004, + 0x00000000, 0x00000000, 0x00000000, 0xff80000a, + 0xff80031f, 0xff800b24, 0xff801818, 0xff8029fa, + 0xff8040c9, 0xff805c86, 0xff807d2e, 0xff80a2c1, + 0xff80cd3c, 0xff80fc9f, 0xff8130e8, 0xff816a14, + 0xff81a821, 0xff81eb0e, 0xff8232d6, 0xff827f79, + 0xff82d0f2, 0xff83273e, 0xff83825b, 0xff83e244, + 0xff8446f7, 0xff84b06e, 0xff851ea6, 0xff85919b, + 0xff860949, 0xff8685aa, 0xff8706ba, 0xff878c74, + 0xff8816d3, 0xff88a5d1, 0xff89396a, 0xff89d196, + 0xff8a6e51, 0xff8b0f94, 0xff8bb55a, 0xff8c5f9b, + 0xff8d0e51, 0xff8dc176, 0xff8e7902, 0xff8f34ef, + 0xff8ff535, 0xff90b9cc, 0xff9182ae, 0xff924fd3, + 0xff932132, 0xff93f6c3, 0xff94d07f, 0xff95ae5d, + 0xff969054, 0xff97765b, 0xff98606a, 0xff994e78, + 0xff9a407c, 0xff9b366b, 0xff9c303e, 0xff9d2de9, + 0xff9e2f64, 0xff9f34a4, 0xffa03da0, 0xffa14a4c, + 0xffa25aa0, 0xffa36e8f, 0xffa48610, 0xffa5a118, + 0xffa6bf9c, 0xffa7e191, 0xffa906ec, 0xffaa2fa0, + 0xffab5ba4, 0xffac8aeb, 0xffadbd6a, 0xffaef315, + 0xffb02bdf, 0xffb167be, 0xffb2a6a4, 0xffb3e886, + 0xffb52d56, 0xffb67509, 0xffb7bf92, 0xffb90ce4, + 0xffba5cf2, 0xffbbafb0, 0xffbd050f, 0xffbe5d04, + 0xffbfb780, 0xffc11477, 0xffc273db, 0xffc3d59f, + 0xffc539b4, 0xffc6a00d, 0xffc8089d, 0xffc97355, + 0xffcae027, 0xffcc4f05, 0xffcdbfe2, 0xffcf32af, + 0xffd0a75d, 0xffd21ddf, 0xffd39625, 0xffd51022, + 0xffd68bc7, 0xffd80904, 0xffd987cd, 0xffdb0810, + 0xffdc89c1, 0xffde0cd0, 0xffdf912d, 0xffe116cb, + 0xffe29d9a, 0xffe4258b, 0xffe5ae8f, 0xffe73896, + 0xffe8c392, 0xffea4f74, 0xffebdc2b, 0xffed69aa, + 0xffeef7df, 0xfff086bd, 0xfff21634, 0xfff3a634, + 0xfff536ad, 0xfff6c792, 0xfff858d1, 0xfff9ea5b, + 0xfffb7c22, 0xfffd0e16, 0xfffea026, 0xffffcdbc, + 0xfffe3ba0, 0xfffca995, 0xfffb17ac, 0xfff985f3, + 0xfff7f479, 0xfff6634f, 0xfff4d284, 0xfff34228, + 0xfff1b249, 0xfff022f7, 0xffee9442, 0xffed0638, + 0xffeb78ea, 0xffe9ec67, 0xffe860bd, 0xffe6d5fd, + 0xffe54c35, 0xffe3c374, 0xffe23bcb, 0xffe0b547, + 0xffdf2ff7, 0xffddabec, 0xffdc2933, 0xffdaa7dd, + 0xffd927f6, 0xffd7a98f, 0xffd62cb7, 0xffd4b17b, + 0xffd337ea, 0xffd1c013, 0xffd04a05, 0xffced5ce, + 0xffcd637c, 0xffcbf31d, 0xffca84c1, 0xffc91874, + 0xffc7ae45, 0xffc64641, 0xffc4e078, 0xffc37cf6, + 0xffc21bc9, 0xffc0bcff, 0xffbf60a5, 0xffbe06c9, + 0xffbcaf79, 0xffbb5ac0, 0xffba08ae, 0xffb8b94d, + 0xffb76cac, 0xffb622d8, 0xffb4dbdc, 0xffb397c6, + 0xffb256a2, 0xffb1187d, 0xffafdd62, 0xffaea55f, + 0xffad707e, 0xffac3ecc, 0xffab1054, 0xffa9e523, + 0xffa8bd44, 0xffa798c2, 0xffa677a8, 0xffa55a02, + 0xffa43fdb, 0xffa3293d, 0xffa21634, 0xffa106c9, + 0xff9ffb08, 0xff9ef2fa, 0xff9deeab, 0xff9cee23, + 0xff9bf16c, 0xff9af892, 0xff9a039c, 0xff991295, + 0xff982586, 0xff973c78, 0xff965774, 0xff957683, + 0xff9499ad, 0xff93c0fb, 0xff92ec75, 0xff921c24, + 0xff91500f, 0xff90883f, 0xff8fc4bb, 0xff8f058b, + 0xff8e4ab6, 0xff8d9443, 0xff8ce239, 0xff8c349f, + 0xff8b8b7d, 0xff8ae6d7, 0xff8a46b5, 0xff89ab1e, + 0xff891416, 0xff8881a3, 0xff87f3cc, 0xff876a96, + 0xff86e606, 0xff866621, 0xff85eaed, 0xff85746d, + 0xff8502a6, 0xff84959e, 0xff842d57, 0xff83c9d7, + 0xff836b20, 0xff831138, 0xff82bc20, 0xff826bdc, + 0xff822070, 0xff81d9de, 0xff819829, 0xff815b54, + 0xff812360, 0xff80f051, 0xff80c228, 0xff8098e6, + 0xff80748e, 0xff805521, 0xff803a9f, 0xff80250b, + 0xff801464, 0xff8008ad, 0xff8001e4, 0xff800027, + 0xff800c7e, 0xff802c8f, 0xff806056, 0xff80a7cb, + 0xff8102e4, 0xff817191, 0xff81f3c3, 0xff828964, + 0xff83325f, 0xff83ee98, 0xff84bdf3, 0xff85a04f, + 0xff86958b, 0xff879d7f, 0xff88b804, 0xff89e4ee, + 0xff8b240e, 0xff8c7533, 0xff8dd82a, 0xff8f4cbb, + 0xff90d2ad, 0xff9269c4, 0xff9411c1, 0xff95ca62, + 0xff979365, 0xff996c81, 0xff9b5570, 0xff9d4de4, + 0xff9f5590, 0xffa16c24, 0xffa3914e, 0xffa5c4b8, + 0xffa8060d, 0xffaa54f3, 0xffacb10e, 0xffaf1a03, + 0xffb18f70, 0xffb410f7, 0xffb69e33, 0xffb936c0, + 0xffbbda37, 0xffbe8830, 0xffc14042, 0xffc40201, + 0xffc6cd00, 0xffc9a0d2, 0xffcc7d05, 0xffcf612b, + 0xffd24ccf, 0xffd53f80, 0xffd838c8, 0xffdb3833, + 0xffde3d49, 0xffe14795, 0xffe4569d, 0xffe769e9, + 0xffea80ff, 0xffed9b67, 0xfff0b8a4, 0xfff3d83c, + 0xfff6f9b5, 0xfffa1c91, 0xfffd4056, 0xffff9b78, + 0xfffc7756, 0xfff953c0, 0xfff63130, 0xfff31025, + 0xffeff117, 0xffecd484, 0xffe9bae5, 0xffe6a4b6, + 0xffe39270, 0xffe0848b, 0xffdd7b82, 0xffda77cb, + 0xffd779de, 0xffd48231, 0xffd19138, 0xffcea769, + 0xffcbc535, 0xffc8eb10, 0xffc61969, 0xffc350af, + 0xffc09151, 0xffbddbbb, 0xffbb3059, 0xffb88f92, + 0xffb5f9d0, 0xffb36f78, 0xffb0f0ef, 0xffae7e96, + 0xffac18cf, 0xffa9bff9, 0xffa7746f, 0xffa5368c, + 0xffa306aa, 0xffa0e51e, 0xff9ed23c, 0xff9cce56, + 0xff9ad9bc, 0xff98f4bc, 0xff971f9f, 0xff955aae, + 0xff93a62f, 0xff920266, 0xff906f92, 0xff8eedf3, + 0xff8d7dc4, 0xff8c1f3c, 0xff8ad294, 0xff8997fd, + 0xff886fa8, 0xff8759c3, 0xff865679, 0xff8565f2, + 0xff848852, 0xff83bdbd, 0xff830651, 0xff82622b, + 0xff81d163, 0xff815411, 0xff80ea47, 0xff809416, + 0xff80518b, 0xff8022b1, 0xff80078e, 0x00000475, + 0x000007fe, 0x00000c02, 0x000010a3, 0x000015f5, + 0x00001c08, 0x000022ed, 0x00002ab5, 0x00003371, + 0x00003d32, 0x0000480a, 0x0000540d, 0x0000614b, + 0x00006fda, 0x00007fcd, 0x00009138, 0x0000a431, + 0x0000b8cc, 0x0000cf1f, 0x0000e741, 0x00010148, + 0x00011d4b, 0x00013b61, 0x00015ba2, 0x00017e25, + 0x0001a302, 0x0001ca51, 0x0001f42c, 0x000220a9, + 0x00024fe2, 0x000281f0, 0x0002b6ea, 0x0002eee9, + 0x00032a07, 0x0003685a, 0x0003a9fc, 0x0003ef04, + 0x0004378a, 0x000483a5, 0x0004d36d, 0x000526f7, + 0x00057e5b, 0x0005d9ae, 0x00063904, 0x00069c74, + 0x00070410, 0x00076feb, 0x0007e01a, 0x000854ac, + 0x0008cdb3, 0x00094b40, 0x0009cd61, 0x000a5425, + 0x000adf98, 0x000b6fc8, 0x000c04bf, 0x000c9e87, + 0x000d3d2a, 0x000de0ae, 0x000e891a, 0x000f3674, + 0x000fe8c0, 0x00109fff, 0x00115c34, 0x00121d5d, + 0x0012e37b, 0x0013ae89, 0x00147e84, 0x00155366, + 0x00162d27, 0x00170bbf, 0x0017ef23, 0x0018d748, + 0x0019c421, 0x001ab59f, 0x001babb2, 0x001ca648, + 0x001da54f, 0x001ea8b0, 0x001fb058, 0x0020bc2d, + 0x0021cc18, 0x0022dffd, 0x0023f7c2, 0x00251348, + 0x00263272, 0x00275520, 0x00287b31, 0x0029a482, + 0x002ad0f1, 0x002c0059, 0x002d3294, 0x002e677c, + 0x002f9ee8, 0x0030d8b1, 0x003214ac, 0x003352b0, + 0x00349290, 0x0035d422, 0x00371738, 0x00385ba5, + 0x0039a13b, 0x003ae7cc, 0x003c2f2a, 0x003d7725, + 0x003ebf8d, 0x00400834, 0x004150e9, 0x0042997d, + 0x0043e1c0, 0x00452981, 0x00467092, 0x0047b6c3, + 0x0048fbe3, 0x004a3fc6, 0x004b823b, 0x004cc316, + 0x004e0228, 0x004f3f45, 0x00507a40, 0x0051b2ef, + 0x0052e925, 0x00541cba, 0x00554d85, 0x00567b5e, + 0x0057a61d, 0x0058cd9e, 0x0059f1bb, 0x005b1252, + 0x005c2f3f, 0x005d4863, 0x005e5d9d, 0x005f6ed0, + 0x00607bde, 0x006184ad, 0x00628923, 0x00638927, + 0x006484a3, 0x00657b81, 0x00666daf, 0x00675b19, + 0x006843b1, 0x00692767, 0x006a062d, 0x006adff9, + 0x006bb4c2, 0x006c847d, 0x006d4f27, 0x006e14b8, + 0x006ed52f, 0x006f9089, 0x007046c6, 0x0070f7e9, + 0x0071a3f3, 0x00724aea, 0x0072ecd3, 0x007389b6, + 0x0074219d, 0x0074b490, 0x0075429b, 0x0075cbcc, + 0x00765031, 0x0076cfd8, 0x00774ad3, 0x0077c132, + 0x00783308, 0x0078a068, 0x00790968, 0x00796e1c, + 0x0079ce9a, 0x007a2af9, 0x007a8350, 0x007ad7b8, + 0x007b2849, 0x007b751d, 0x007bbe4c, 0x007c03f1, + 0x007c4625, 0x007c8504, 0x007cc0a8, 0x007cf92c, + 0x007d2eaa, 0x007d613e, 0x007d9101, 0x007dbe10, + 0x007de883, 0x007e1076, 0x007e3603, 0x007e5943, + 0x007e7a4f, 0x007e9942, 0x007eb633, 0x007ed13a, + 0x007eea6f, 0x007f01ea, 0x007f17c0, 0x007f2c08, + 0x007f3ed7, 0x007f5043, 0x007f605e, 0x007f6f3c, + 0x007f7cf1, 0x007f898e, 0x007f9525, 0x007f9fc6, + 0x007fa982, 0x007fb268, 0x007fba86, 0x007fc1eb, + 0x007fc8a4, 0x007fcebe, 0x007fd443, 0x007fd941, + 0x007fddc2, 0x007fe1cf, 0x007fe572, 0x007fe8b4, + 0x007feb9e, 0x007fee36, 0x007ff086, 0x007ff293, + 0x007ff463, 0x007ff5fd, 0x007ff765, 0x007ff8a1, + 0x007ff9b6, 0x007ffaa7, 0x007ffb79, 0x007ffc2f, + 0x007ffccb, 0x007ffd52, 0x007ffdc6, 0x007ffe28, + 0x007ffe7b, 0x007ffec2, 0x007ffefd, 0x007fff2f, + 0x007fff58, 0x007fff7b, 0x007fff97, 0x007fffae, + 0x007fffc0, 0x007fffcf, 0x007fffdb, 0x007fffe4, + 0x007fffec, 0x007ffff1, 0x007ffff6, 0x007ffff9, + 0x007ffffb, 0x007ffffd, 0x007ffffe, 0x007fffff, + 0x007fffff, 0x007fffff, 0x007fffff, 0xff800000, + 0x00000000, 0xffa57d86, 0x005a827a, 0xff89be51, + 0x0030fbc5, 0xffcf043b, 0x007641af, 0xff8275a1, + 0x0018f8b8, 0xffb8e313, 0x006a6d99, 0xff959267, + 0x00471ced, 0xffe70748, 0x007d8a5f, 0xff809dc9, + 0x000c8bd3, 0xffaecc33, 0x0062f202, 0xff8f1d34, + 0x003c56ba, 0xffdad7f4, 0x007a7d05, 0xff8582fb, + 0x0025280c, 0xffc3a946, 0x0070e2cc, 0xff9d0dfe, + 0x005133cd, 0xfff3742d, 0x007f6237, 0xff802778, + 0x000647d9, 0xffaa0a5b, 0x005ed77d, 0xff8c4a14, + 0x0036ba20, 0xffd4e0cb, 0x00788484, 0xff83d604, + 0x001f19f9, 0xffbe31e2, 0x006dca0d, 0xff99307f, + 0x004c3fe0, 0xffed37f0, 0x007e9d56, 0xff8162aa, + 0x0012c810, 0xffb3c020, 0x0066cf81, 0xff9235f3, + 0x0041ce1e, 0xffe0e607, 0x007c29fc, 0xff877b7c, + 0x002b1f35, 0xffc945e0, 0x0073b5ec, 0xffa12883, + 0x0055f5a5, 0xfff9b827, 0x007fd888, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, +}; + +static u32 AC3I2S240Ucode1fe000[] = { + 0x00000000, 0x03020102, 0x05040403, 0x00400040, + 0x00500050, 0x00600060, 0x00700070, 0x00800080, + 0x00a000a0, 0x00c000c0, 0x00e000e0, 0x01000100, + 0x01400140, 0x01800180, 0x01c001c0, 0x02000200, + 0x02800280, 0x03000300, 0x03800380, 0x04000400, + 0x04800480, 0x05000500, 0x00460045, 0x00580057, + 0x00690068, 0x007a0079, 0x008c008b, 0x00af00ae, + 0x00d100d0, 0x00f400f3, 0x01170116, 0x015d015c, + 0x01a201a1, 0x01e801e7, 0x022e022d, 0x02b902b8, + 0x03440343, 0x03d003cf, 0x045b045a, 0x04e604e5, + 0x05720571, 0x00600060, 0x00780078, 0x00900090, + 0x00a800a8, 0x00c000c0, 0x00f000f0, 0x01200120, + 0x01500150, 0x01800180, 0x01e001e0, 0x02400240, + 0x02a002a0, 0x03000300, 0x03c003c0, 0x04800480, + 0x05400540, 0x06000600, 0x06c006c0, 0x07800780, + 0x7b67533f, 0x1513110f, 0x04d80540, 0x04100478, + 0x07000000, 0x0b000900, 0x02b002f0, 0x02300270, + 0x017001f0, 0xf80000f0, 0x01000080, 0x02000180, + 0x03000280, 0x04000380, 0x2725231f, 0x2c2b2a29, + 0x2e2e2d2d, 0x30302f2f, 0x04030201, 0x08070605, + 0x0c0b0a09, 0x100f0e0d, 0x14131211, 0x18171615, + 0x1c1b1a19, 0x2825221f, 0x37312e2b, 0x4f49433d, + 0x796d6155, 0xcdb59d85, 0x0000fde5, 0x3d3e3f40, + 0x393a3b3c, 0x35363738, 0x32333434, 0x2f2f3031, + 0x2c2c2d2e, 0x29292a2b, 0x26262728, 0x23242425, + 0x21212223, 0x1e1f2020, 0x1c1d1d1e, 0x1a1b1b1c, + 0x1819191a, 0x16171718, 0x15151516, 0x13131414, + 0x12121213, 0x10111111, 0x0f0f1010, 0x0e0e0e0f, + 0x0d0d0d0d, 0x0c0c0c0c, 0x0b0b0b0b, 0x0a0a0a0a, + 0x0909090a, 0x08080909, 0x08080808, 0x07070707, + 0x06060707, 0x06060606, 0x05050606, 0x05050505, + 0x04040505, 0x04040404, 0x04040404, 0x03030304, + 0x03030303, 0x03030303, 0x02030303, 0x02020202, + 0x02020202, 0x02020202, 0x02020202, 0x01010202, + 0x01010101, 0x01010101, 0x01010101, 0x01010101, + 0x01010101, 0x01010101, 0x01010101, 0x00000101, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x04d004d0, + 0x04000440, 0x03c003e0, 0x03b003b0, 0x03a003a0, + 0x03a003a0, 0x039003a0, 0x03900390, 0x03800380, + 0x03700370, 0x03600360, 0x03500350, 0x03400340, + 0x03200330, 0x03000310, 0x02f002f0, 0x02f002f0, + 0x03100300, 0x03900340, 0x042003e0, 0x04900460, + 0x046004a0, 0x04400440, 0x08000520, 0x08400840, + 0x04f004f0, 0x04100460, 0x03d003e0, 0x03b003c0, + 0x03a003b0, 0x03a003a0, 0x03a003a0, 0x03900390, + 0x03800390, 0x03800380, 0x03700370, 0x03600360, + 0x03500350, 0x03400340, 0x03100320, 0x02f00300, + 0x02f002f0, 0x030002f0, 0x03500320, 0x03e00390, + 0x04500420, 0x049004a0, 0x04400460, 0x06300480, + 0x08400840, 0x05800580, 0x045004b0, 0x03f00420, + 0x03d003e0, 0x03b003c0, 0x03b003b0, 0x03a003a0, + 0x03a003a0, 0x03a003a0, 0x03a003a0, 0x03900390, + 0x03900390, 0x03800380, 0x03700380, 0x03500360, + 0x03300340, 0x03100320, 0x02f00300, 0x02f002f0, + 0x03100300, 0x03500330, 0x041003c0, 0x04a00470, + 0x04400460, 0x04e00450, 0xffaaaaab, 0x00000000, + 0x00555555, 0xff99999a, 0xffcccccd, 0x00000000, + 0x00333333, 0x00666666, 0xff924925, 0xffb6db6e, + 0xffdb6db7, 0x00000000, 0x00249249, 0x00492492, + 0x006db6db, 0xff8ba2e9, 0xffa2e8ba, 0xffba2e8c, + 0xffd1745d, 0xffe8ba2f, 0x00000000, 0x001745d1, + 0x002e8ba3, 0x0045d174, 0x005d1746, 0x00745d17, + 0xff888889, 0xff99999a, 0xffaaaaab, 0xffbbbbbc, + 0xffcccccd, 0xffddddde, 0xffeeeeef, 0x00000000, + 0x00111111, 0x00222222, 0x00333333, 0x00444444, + 0x00555555, 0x00666666, 0x00777777, 0x08070605, + 0x0c0b0a09, 0x10100e0e, 0x00000010, 0x00000000, + 0x00000010, 0x00000020, 0x00000100, 0x00000110, + 0x00000120, 0x00000200, 0x00000210, 0x00000220, + 0x00001000, 0x00001010, 0x00001020, 0x00001100, + 0x00001110, 0x00001120, 0x00001200, 0x00001210, + 0x00001220, 0x00002000, 0x00002010, 0x00002020, + 0x00002100, 0x00002110, 0x00002120, 0x00002200, + 0x00002210, 0x00002220, 0x00000000, 0x00000010, + 0x00000020, 0x00000030, 0x00000040, 0x00000100, + 0x00000110, 0x00000120, 0x00000130, 0x00000140, + 0x00000200, 0x00000210, 0x00000220, 0x00000230, + 0x00000240, 0x00000300, 0x00000310, 0x00000320, + 0x00000330, 0x00000340, 0x00000400, 0x00000410, + 0x00000420, 0x00000430, 0x00000440, 0x00001000, + 0x00001010, 0x00001020, 0x00001030, 0x00001040, + 0x00001100, 0x00001110, 0x00001120, 0x00001130, + 0x00001140, 0x00001200, 0x00001210, 0x00001220, + 0x00001230, 0x00001240, 0x00001300, 0x00001310, + 0x00001320, 0x00001330, 0x00001340, 0x00001400, + 0x00001410, 0x00001420, 0x00001430, 0x00001440, + 0x00002000, 0x00002010, 0x00002020, 0x00002030, + 0x00002040, 0x00002100, 0x00002110, 0x00002120, + 0x00002130, 0x00002140, 0x00002200, 0x00002210, + 0x00002220, 0x00002230, 0x00002240, 0x00002300, + 0x00002310, 0x00002320, 0x00002330, 0x00002340, + 0x00002400, 0x00002410, 0x00002420, 0x00002430, + 0x00002440, 0x00003000, 0x00003010, 0x00003020, + 0x00003030, 0x00003040, 0x00003100, 0x00003110, + 0x00003120, 0x00003130, 0x00003140, 0x00003200, + 0x00003210, 0x00003220, 0x00003230, 0x00003240, + 0x00003300, 0x00003310, 0x00003320, 0x00003330, + 0x00003340, 0x00003400, 0x00003410, 0x00003420, + 0x00003430, 0x00003440, 0x00004000, 0x00004010, + 0x00004020, 0x00004030, 0x00004040, 0x00004100, + 0x00004110, 0x00004120, 0x00004130, 0x00004140, + 0x00004200, 0x00004210, 0x00004220, 0x00004230, + 0x00004240, 0x00004300, 0x00004310, 0x00004320, + 0x00004330, 0x00004340, 0x00004400, 0x00004410, + 0x00004420, 0x00004430, 0x00004440, 0x00000000, + 0x00000100, 0x00000200, 0x00000300, 0x00000400, + 0x00000500, 0x00000600, 0x00000700, 0x00000800, + 0x00000900, 0x00000a00, 0x00001000, 0x00001100, + 0x00001200, 0x00001300, 0x00001400, 0x00001500, + 0x00001600, 0x00001700, 0x00001800, 0x00001900, + 0x00001a00, 0x00002000, 0x00002100, 0x00002200, + 0x00002300, 0x00002400, 0x00002500, 0x00002600, + 0x00002700, 0x00002800, 0x00002900, 0x00002a00, + 0x00003000, 0x00003100, 0x00003200, 0x00003300, + 0x00003400, 0x00003500, 0x00003600, 0x00003700, + 0x00003800, 0x00003900, 0x00003a00, 0x00004000, + 0x00004100, 0x00004200, 0x00004300, 0x00004400, + 0x00004500, 0x00004600, 0x00004700, 0x00004800, + 0x00004900, 0x00004a00, 0x00005000, 0x00005100, + 0x00005200, 0x00005300, 0x00005400, 0x00005500, + 0x00005600, 0x00005700, 0x00005800, 0x00005900, + 0x00005a00, 0x00006000, 0x00006100, 0x00006200, + 0x00006300, 0x00006400, 0x00006500, 0x00006600, + 0x00006700, 0x00006800, 0x00006900, 0x00006a00, + 0x00007000, 0x00007100, 0x00007200, 0x00007300, + 0x00007400, 0x00007500, 0x00007600, 0x00007700, + 0x00007800, 0x00007900, 0x00007a00, 0x00008000, + 0x00008100, 0x00008200, 0x00008300, 0x00008400, + 0x00008500, 0x00008600, 0x00008700, 0x00008800, + 0x00008900, 0x00008a00, 0x00009000, 0x00009100, + 0x00009200, 0x00009300, 0x00009400, 0x00009500, + 0x00009600, 0x00009700, 0x00009800, 0x00009900, + 0x00009a00, 0x0000a000, 0x0000a100, 0x0000a200, + 0x0000a300, 0x0000a400, 0x0000a500, 0x0000a600, + 0x0000a700, 0x0000a800, 0x0000a900, 0x0000aa00, + 0xff800000, 0xff800000, 0xffb82995, 0xffaf5d75, + 0xffa57d87, 0xff9a6806, 0xff8df708, 0xff800000, + 0xffb82995, 0xffaf5d75, 0xffa57d87, 0xff9a6806, + 0xff8df708, 0xff800000, 0xffb82995, 0xffaf5d75, + 0xffa57d87, 0xff9a6806, 0xff8df708, 0xff800000, + 0xffb82995, 0xffaf5d75, 0xffa57d87, 0xff9a6806, + 0xff8df708, 0xff800000, 0xffb82995, 0xffaf5d75, + 0xffa57d87, 0xff9a6806, 0xff8df708, 0xff800000, + 0xfffb0000, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, + 0xfffdfffd, 0xfffdfffd, 0xfffdfffd, 0xfffefffe, + 0xfffefffe, 0xfffefffe, 0xffffffff, 0xffffffff, + 0xffffffff, 0x00000000, 0x00000000, 0x00000000, + 0x80050000, 0x000a800f, 0x001e801b, 0x80110014, + 0x00368033, 0x8039003c, 0x802d0028, 0x00228027, + 0x00668063, 0x8069006c, 0x807d0078, 0x00728077, + 0x80550050, 0x005a805f, 0x004e804b, 0x80410044, + 0x00c680c3, 0x80c900cc, 0x80dd00d8, 0x00d280d7, + 0x80f500f0, 0x00fa80ff, 0x00ee80eb, 0x80e100e4, + 0x80a500a0, 0x00aa80af, 0x00be80bb, 0x80b100b4, + 0x00968093, 0x8099009c, 0x808d0088, 0x00828087, + 0x01868183, 0x8189018c, 0x819d0198, 0x01928197, + 0x81b501b0, 0x01ba81bf, 0x01ae81ab, 0x81a101a4, + 0x81e501e0, 0x01ea81ef, 0x01fe81fb, 0x81f101f4, + 0x01d681d3, 0x81d901dc, 0x81cd01c8, 0x01c281c7, + 0x81450140, 0x014a814f, 0x015e815b, 0x81510154, + 0x01768173, 0x8179017c, 0x816d0168, 0x01628167, + 0x01268123, 0x8129012c, 0x813d0138, 0x01328137, + 0x81150110, 0x011a811f, 0x010e810b, 0x81010104, + 0x03068303, 0x8309030c, 0x831d0318, 0x03128317, + 0x83350330, 0x033a833f, 0x032e832b, 0x83210324, + 0x83650360, 0x036a836f, 0x037e837b, 0x83710374, + 0x03568353, 0x8359035c, 0x834d0348, 0x03428347, + 0x83c503c0, 0x03ca83cf, 0x03de83db, 0x83d103d4, + 0x03f683f3, 0x83f903fc, 0x83ed03e8, 0x03e283e7, + 0x03a683a3, 0x83a903ac, 0x83bd03b8, 0x03b283b7, + 0x83950390, 0x039a839f, 0x038e838b, 0x83810384, + 0x82850280, 0x028a828f, 0x029e829b, 0x82910294, + 0x02b682b3, 0x82b902bc, 0x82ad02a8, 0x02a282a7, + 0x02e682e3, 0x82e902ec, 0x82fd02f8, 0x02f282f7, + 0x82d502d0, 0x02da82df, 0x02ce82cb, 0x82c102c4, + 0x02468243, 0x8249024c, 0x825d0258, 0x02528257, + 0x82750270, 0x027a827f, 0x026e826b, 0x82610264, + 0x82250220, 0x022a822f, 0x023e823b, 0x82310234, + 0x02168213, 0x8219021c, 0x820d0208, 0x02028207, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0xff800000, 0xffa57d86, 0xffa57d86, + 0xffcf043b, 0xff89be51, 0xff89be51, 0xffcf043b, + 0xffe70748, 0xff8275a1, 0xff959267, 0xffb8e313, + 0xffb8e313, 0xff959267, 0xff8275a1, 0xffe70748, + 0xfff3742d, 0xff809dc9, 0xff9d0dfe, 0xffaecc33, + 0xffc3a946, 0xff8f1d34, 0xff8582fb, 0xffdad7f4, + 0xffdad7f4, 0xff8582fb, 0xff8f1d34, 0xffc3a946, + 0xffaecc33, 0xff9d0dfe, 0xff809dc9, 0xfff3742d, + 0xfff9b827, 0xff802778, 0xffa12883, 0xffaa0a5b, + 0xffc945e0, 0xff8c4a14, 0xff877b7c, 0xffd4e0cb, + 0xffe0e607, 0xff83d604, 0xff9235f3, 0xffbe31e2, + 0xffb3c020, 0xff99307f, 0xff8162aa, 0xffed37f0, + 0xffed37f0, 0xff8162aa, 0xff99307f, 0xffb3c020, + 0xffbe31e2, 0xff9235f3, 0xff83d604, 0xffe0e607, + 0xffd4e0cb, 0xff877b7c, 0xff8c4a14, 0xffc945e0, + 0xffaa0a5b, 0xffa12883, 0xff802778, 0xfff9b827, + 0xcbcecdc4, 0xcfcac9c8, 0xc3c6c5cc, 0xc7c2c1c0, + 0x1b1e1d14, 0x1f1a1918, 0x1316151c, 0x17121110, + 0x2b2e2d24, 0x2f2a2928, 0x2326252c, 0x27222120, + 0x3b3e3d34, 0x3f3a3938, 0x3336353c, 0x37323130, + 0x0b0e0d04, 0x0f0a0908, 0x0306050c, 0x07020100, + 0xdbdeddd4, 0xdfdad9d8, 0xd3d6d5dc, 0xd7d2d1d0, + 0xebeeede4, 0xefeae9e8, 0xe3e6e5ec, 0xe7e2e1e0, + 0xfbfefdf4, 0xfffaf9f8, 0xf3f6f5fc, 0xf7f2f1f0, + 0x4b4e4d44, 0x4f4a4948, 0x4346454c, 0x47424140, + 0x9b9e9d94, 0x9f9a9998, 0x9396959c, 0x97929190, + 0xabaeada4, 0xafaaa9a8, 0xa3a6a5ac, 0xa7a2a1a0, + 0xbbbebdb4, 0xbfbab9b8, 0xb3b6b5bc, 0xb7b2b1b0, + 0x8b8e8d84, 0x8f8a8988, 0x8386858c, 0x87828180, + 0x5b5e5d54, 0x5f5a5958, 0x5356555c, 0x57525150, + 0x6b6e6d64, 0x6f6a6968, 0x6366656c, 0x67626160, + 0x7b7e7d74, 0x7f7a7978, 0x7376757c, 0x77727170, + 0x341424c4, 0x3e1e2ece, 0x3d1d2dcd, 0x3b1b2bcb, + 0xb494a444, 0xbe9eae4e, 0xbd9dad4d, 0xbb9bab4b, + 0xf4d4e404, 0xfedeee0e, 0xfddded0d, 0xfbdbeb0b, + 0x74546484, 0x7e5e6e8e, 0x7d5d6d8d, 0x7b5b6b8b, + 0x3c1c2ccc, 0x361626c6, 0x351525c5, 0x331323c3, + 0xbc9cac4c, 0xb696a646, 0xb595a545, 0xb393a343, + 0xfcdcec0c, 0xf6d6e606, 0xf5d5e505, 0xf3d3e303, + 0x7c5c6c8c, 0x76566686, 0x75556585, 0x73536383, + 0x381828c8, 0x3a1a2aca, 0x391929c9, 0x3f1f2fcf, + 0xb898a848, 0xba9aaa4a, 0xb999a949, 0xbf9faf4f, + 0xf8d8e808, 0xfadaea0a, 0xf9d9e909, 0xffdfef0f, + 0x78586888, 0x7a5a6a8a, 0x79596989, 0x7f5f6f8f, + 0x301020c0, 0x321222c2, 0x311121c1, 0x371727c7, + 0xb090a040, 0xb292a242, 0xb191a141, 0xb797a747, + 0xf0d0e000, 0xf2d2e202, 0xf1d1e101, 0xf7d7e707, + 0x70506080, 0x72526282, 0x71516181, 0x77576787, + 0x05040100, 0x15141110, 0x25242120, 0x35343130, + 0x85848180, 0x95949190, 0xa5a4a1a0, 0xb5b4b1b0, + 0xc0408000, 0xe060a020, 0xd0509010, 0xf070b030, + 0xc8488808, 0xe868a828, 0xd8589818, 0xf878b838, + 0xc4448404, 0xe464a424, 0xd4549414, 0xf474b434, + 0xcc4c8c0c, 0xec6cac2c, 0xdc5c9c1c, 0xfc7cbc3c, + 0xc2428202, 0xe262a222, 0xd2529212, 0xf272b232, + 0xca4a8a0a, 0xea6aaa2a, 0xda5a9a1a, 0xfa7aba3a, + 0xc6468606, 0xe666a626, 0xd6569616, 0xf676b636, + 0xce4e8e0e, 0xee6eae2e, 0xde5e9e1e, 0xfe7ebe3e, + 0xc1418101, 0xe161a121, 0xd1519111, 0xf171b131, + 0xc9498909, 0xe969a929, 0xd9599919, 0xf979b939, + 0xc5458505, 0xe565a525, 0xd5559515, 0xf575b535, + 0xcd4d8d0d, 0xed6dad2d, 0xdd5d9d1d, 0xfd7dbd3d, + 0xc3438303, 0xe363a323, 0xd3539313, 0xf373b333, + 0xcb4b8b0b, 0xeb6bab2b, 0xdb5b9b1b, 0xfb7bbb3b, + 0xc7478707, 0xe767a727, 0xd7579717, 0xf777b737, + 0xcf4f8f0f, 0xef6faf2f, 0xdf5f9f1f, 0xff7fbf3f, + 0x1045a3e2, 0x000000f4, 0x263b7333, 0x766b2363, + 0x2b367e3e, 0x7b662e6e, 0x06db93d3, 0x964b0343, + 0x0bd69ede, 0x9b460e4e, 0x825f1757, 0x12cf87c7, + 0x8f521a5a, 0x1fc28aca, 0x00d199d9, 0x90410949, + 0x01d098d8, 0x91400848, 0x24357d3d, 0x74652d6d, + 0x25347c3c, 0x75642c6c, 0x04d59ddd, 0x94450d4d, + 0x05d49cdc, 0x95440c4c, 0x80511959, 0x10c189c9, + 0x81501858, 0x11c088c8, 0x02df97d7, 0x924f0747, + 0x0fd29ada, 0x9f420a4a, 0x865b1353, 0x16cb83c3, + 0x8b561e5e, 0x1bc68ece, 0xa6bbf3b3, 0xf6eba3e3, + 0xabb6febe, 0xfbe6aeee, 0x223f7737, 0x726f2767, + 0x2f327a3a, 0x7f622a6a, 0xa0b1f9b9, 0xf0e1a9e9, + 0xa1b0f8b8, 0xf1e0a8e8, 0x84551d5d, 0x14c58dcd, + 0x85541c5c, 0x15c48ccc, 0xa4b5fdbd, 0xf4e5aded, + 0xa5b4fcbc, 0xf5e4acec, 0x20317939, 0x70612969, + 0x21307838, 0x71602868, 0xa2bff7b7, 0xf2efa7e7, + 0xafb2faba, 0xffe2aaea, 0x00000000, 0x00000000, +}; + +static u32 AC3I2S240Ucode1fff80[] = { + 0x0000240f, 0x007fffff, 0x007fffff, 0x00000003, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00000000, 0x00000000, 0x00000000, +}; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/ls220/ac3i2s.h linux.19rc3-ac4/drivers/media/video/ls220/ac3i2s.h --- linux.19rc3/drivers/media/video/ls220/ac3i2s.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/ls220/ac3i2s.h 2002-07-29 13:58:41.000000000 +0100 @@ -0,0 +1,2850 @@ +static u32 AC3I2SUcode1f1800[] = { + 0xb500000f, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xb500122b, 0x00000000, 0x00000000, 0x00000000, + 0x820f001f, 0x802f001f, 0x80070800, 0x001f6193, + 0x800500d4, 0x8053ffff, 0x9842c7ff, 0x8039ff7c, + 0x1400b802, 0x003f6000, 0x94210007, 0xb0010001, + 0xb4200001, 0x98002800, 0xb0010000, 0xb4200001, + 0x98000800, 0x805300ff, 0x1800b802, 0x800600d4, + 0x8013001f, 0x9020c000, 0x003fb006, 0x803effe0, + 0x803effe8, 0x803effec, 0x9020e000, 0x9021ffe4, + 0x9020fa00, 0x803effd0, 0x803effdc, 0x803effd8, + 0x9020fe00, 0x803effd4, 0x90400000, 0x804600a2, + 0x90421800, 0x804600a3, 0x80134099, 0x98000040, + 0x800600a6, 0x80130000, 0x98003ca1, 0x800600a1, + 0x80050080, 0x98000002, 0x80060080, 0x80070001, + 0x001f2013, 0x001f2324, 0x80070000, 0x001fb0ba, + 0x001f23f9, 0x801eb3f0, 0x80070800, 0x001f600f, + 0x80070000, 0x001f2012, 0x001fb0cb, 0x001fb010, + 0x801efff0, 0x98004000, 0x98008000, 0x001f600e, + 0x83e4013f, 0x80070000, 0x801eb3f8, 0x801eff70, + 0x800500a0, 0xb0000001, 0xb4000009, 0x80070001, + 0x800600a0, 0x80050080, 0x98000020, 0x80060080, + 0x9400ffdf, 0x80060080, 0x80070000, 0x800600a0, + 0x81df0004, 0x00000000, 0x00000000, 0x801bfff0, + 0x00000000, 0x940000ff, 0xb0000000, 0xb420004e, + 0x003f400e, 0x94010010, 0xb0000000, 0xb400fff4, + 0x838413dd, 0x003f0013, 0xb0010001, 0xb420003b, + 0x803bffe8, 0x801bffec, 0x00000000, 0x3001b800, + 0xb4600001, 0x90212000, 0x0421b800, 0x005f4193, + 0x5841b802, 0x3001b802, 0xb460000d, 0x80050086, + 0x005f9016, 0xb0020000, 0xb4200002, 0x001fb016, + 0xb500ffdf, 0x0420b802, 0xb0010b50, 0xb4a0ffdc, + 0x80070000, 0x001fb016, 0x83e40109, 0xb500ffd8, + 0x80070000, 0x001fb016, 0x001f400e, 0x9400000f, + 0xb0000000, 0xb4000014, 0xb0000001, 0xb4000010, + 0x003f400e, 0x9421fff0, 0x003f600e, 0x003f9006, + 0x9421ffff, 0x90210004, 0xb001e000, 0xb4800002, + 0x8421e000, 0x9021c000, 0x8013001f, 0x1021b800, + 0x003fb006, 0x003f90cb, 0x90210004, 0x003fb0cb, + 0x83e400ff, 0x83e413bc, 0x8007001f, 0x94000003, + 0x5810b800, 0x83e71aa8, 0x1bffb800, 0x003f9008, + 0x1821b800, 0x00ffb801, 0x83e4140f, 0x80270000, + 0x003f2013, 0x8007001f, 0x94000003, 0x5810b800, + 0x83671ad4, 0x1b7bb800, 0x003f9009, 0x1821b800, + 0x00ffb801, 0xb500ffaa, 0x803bffc0, 0x805bffc4, + 0x807bffc8, 0x809bffcc, 0x5828b801, 0x5cb8b802, + 0x1821b805, 0x5848b802, 0x5cb8b803, 0x1842b805, + 0x5868b803, 0x5cb8b804, 0x1863b805, 0x5888b804, + 0x1884b800, 0x803effc0, 0x805effc4, 0x807effc8, + 0x809effcc, 0x003f400e, 0xb0000086, 0xb4400048, + 0xb0000084, 0xb4000032, 0xb0000085, 0xb4000038, + 0xb0000086, 0xb400003a, 0x001f4000, 0x94000080, + 0xb0000080, 0xb4000072, 0x800500d4, 0x8053ffff, + 0x9842c7ff, 0x1400b802, 0x805300ff, 0x98422800, + 0x1800b802, 0x800600d4, 0x80130000, 0x98000c7f, + 0x005f4000, 0x94420008, 0xb0020008, 0xb4200001, + 0xa0000080, 0x800600a1, 0x8013001f, 0x9040c000, + 0x005fb006, 0x805effe0, 0x805effe8, 0x805effec, + 0x9040e000, 0x805effe4, 0x9040fa00, 0x805effd0, + 0x805effdc, 0x805effd8, 0x9040fe00, 0x805effd4, + 0x80070001, 0x001f2013, 0x80070000, 0x001fb0cb, + 0x001fb010, 0x001f2058, 0x80071fe0, 0x001fb008, + 0x80075fb0, 0x001fb009, 0x98214000, 0xb5000010, + 0x94011000, 0xb0001000, 0xb4200001, 0x9421efff, + 0x98210010, 0xb500000a, 0x80070000, 0x001fb0cb, + 0x83e40097, 0x003f400e, 0x9421ffef, 0xb5000004, + 0x83e40093, 0x003f400e, 0x98211000, 0x9421ffef, + 0x003f600e, 0x80070100, 0x801efff0, 0xb500ff4c, + 0xb000008b, 0xb400001c, 0xb000008e, 0xb4000022, + 0xb000008d, 0xb400001c, 0xb000008c, 0xb4000021, + 0xb0000087, 0xb400ffe8, 0xb0000088, 0xb4000014, + 0xb000008a, 0xb4000015, 0xb0000089, 0xb400001d, + 0xb00000a0, 0xb400001f, 0xb00000a1, 0xb4000041, + 0xb00000a2, 0xb400004e, 0xb00000a3, 0xb4000046, + 0xb00000a4, 0xb4000050, 0xb00000a5, 0xb4000054, + 0xb00000a6, 0xb4000058, 0x803efff8, 0xb500ffdd, + 0x9421ffdf, 0xb500ffda, 0xb500ffda, 0x80270100, + 0x803efff8, 0xb500ffd7, 0x80070000, 0x001fb017, + 0xb500ffd4, 0x801bffb0, 0x00000000, 0x001fb003, + 0xb500ffd0, 0x803bff80, 0x00000000, 0x003f6001, + 0xb500ffcc, 0x003f90ba, 0x803efff8, 0xb500ffc9, + 0x80130001, 0x98003da1, 0x800600a1, 0x80070200, + 0x801ebf34, 0x83e40042, 0x8013001f, 0x9840c000, + 0x805effe0, 0x005fb006, 0x805effe8, 0x805effec, + 0x90422000, 0x805effe4, 0x9040fa00, 0x805effd0, + 0x805effdc, 0x805effd8, 0x9040fe00, 0x805effd4, + 0x80070001, 0x001f2013, 0x80070000, 0x001f2324, + 0x001fb0cb, 0x001fb010, 0x001f2058, 0x80077580, + 0x001fb008, 0x80077830, 0x001fb009, 0x98214000, + 0xb500ffa7, 0x80270000, 0x8047fef0, 0x003eb802, + 0x90420004, 0x003eb802, 0x90420004, 0x003eb802, + 0x90420004, 0x003eb802, 0x81df0000, 0x00000000, + 0x00000000, 0x83641491, 0x81df0004, 0xb500ff99, + 0x81df0000, 0x00000000, 0x00000000, 0x8364143b, + 0x81df0004, 0xb500ff93, 0x81df0000, 0x00000000, + 0x00000000, 0x836413f6, 0x81df0004, 0xb500ff8d, + 0x81df0000, 0x00000000, 0x00000000, 0x83441359, + 0x81df0004, 0xb500ff87, 0x81df0000, 0x00000000, + 0x00000000, 0x8344133e, 0x81df0004, 0xb500ff81, + 0x80070000, 0x80470000, 0x81df0000, 0x00000000, + 0x00000000, 0xb6002003, 0xb6003002, 0x001eb802, + 0x90420004, 0x80171000, 0x8057ffff, 0xb6002002, + 0xb6001801, 0x001fa020, 0x81df0004, 0x00ffb81f, + 0x001f4000, 0x94000080, 0xb0000080, 0xb4200001, + 0xb500ffeb, 0xb500000a, 0x80270000, 0x003f2013, + 0x8007001f, 0x94000003, 0x5810b800, 0x83671ec0, + 0x1b7bb800, 0x003f9009, 0x1821b800, 0x00ffb801, + 0x003f0013, 0xb0010001, 0xb420fff3, 0x83a70000, + 0x803bff70, 0x00000000, 0xb0010000, 0xb4000015, + 0x80170300, 0x80070000, 0x81df0000, 0x00000000, + 0x00000000, 0xb6000601, 0x001fa020, 0x83640cdb, + 0x00ff0325, 0x82870000, 0xb6270002, 0x83640228, + 0x92940001, 0x81df0004, 0x001f033b, 0xb0000000, + 0xb4000002, 0x80270000, 0xb5000001, 0x80270001, + 0x003f233b, 0x80270000, 0x003f2013, 0x8007001f, + 0x94000003, 0x5810b800, 0x83671f5c, 0x1b7bb800, + 0x003f9009, 0x1821b800, 0x00ffb801, 0x003f0013, + 0xb0010001, 0xb420fff3, 0x93bd0001, 0xb01d0004, + 0xb480ffd7, 0x803bff70, 0x00000000, 0xb0010000, + 0xb4000005, 0x81df0000, 0x00000000, 0x00000000, + 0x83640c83, 0x81df0004, 0x00000000, 0x00000000, + 0x00ffb81f, 0x007f90cb, 0x90630400, 0x007fb0cb, + 0x003f9006, 0x9421ffff, 0x90210400, 0xb001e000, + 0xb4800002, 0x8421e000, 0x9021c000, 0x8013001f, + 0x1021b800, 0x003fb006, 0x803effec, 0x00ffb81f, + 0x015f400e, 0x944a4000, 0xb0024000, 0xb4200090, + 0x954abfff, 0x015f600e, 0x820f001f, 0x802f001f, + 0x81470000, 0x015f23f9, 0x829702ec, 0x82d7ffff, + 0x82f70000, 0x81df0000, 0x00000000, 0x00000000, + 0xb6000501, 0x029fa02a, 0x82970400, 0xb6000702, + 0xb6000001, 0x029fa02a, 0x81df0004, 0x8053ff00, + 0x98420000, 0x805ebf14, 0x805ebf18, 0x805ebf1c, + 0x805ebf20, 0x805ebf24, 0x805ebf28, 0x80270000, + 0x003f2328, 0x80275480, 0x005fb801, 0x8033001f, + 0x9821c000, 0x803effe0, 0x90212000, 0x803effe4, + 0x80dbff8c, 0x80fbff90, 0x80debf14, 0x80febf18, + 0x80dbff94, 0x80fbff98, 0x80debf1c, 0x80febf20, + 0x80dbff9c, 0x80fbffa0, 0x80debf24, 0x80febf28, + 0x80dbff84, 0x80e70001, 0x00dfb001, 0x80dbff88, + 0x00ff6191, 0x00dfb002, 0x80dbffb0, 0x80470000, + 0x00dfb003, 0x80d9ff80, 0x005fb0cf, 0x005fb0c6, + 0x00df6001, 0x80470001, 0x005f618f, 0x804700ff, + 0x005f231c, 0x005f231d, 0x80470000, 0x005f204e, + 0x8047e138, 0x5c42b802, 0x814f6300, 0x80cf00a9, + 0x005fb0bc, 0x5842b802, 0x01cfb802, 0x005f90bc, + 0xb520ffff, 0x8067e16c, 0x5c62b803, 0x80270040, + 0x81df0000, 0x00000000, 0x00000000, 0xb6000209, + 0x814fffc0, 0x00cfb801, 0x007fb0bc, 0x5862b803, + 0x01cfb803, 0x007f90bc, 0xb520ffff, 0x90210020, + 0x90630020, 0x81df0004, 0x8047e398, 0x5c42b802, + 0x814fce40, 0x80cf0080, 0x005fb0bc, 0x5842b802, + 0x01cfb802, 0x005f90bc, 0xb520ffff, 0x8047e400, + 0x5c42b802, 0x814f7380, 0x80cf009a, 0x005fb0bc, + 0x5842b802, 0x01cfb802, 0x005f90bc, 0xb520ffff, + 0x8047e43c, 0x5c42b802, 0x814f18c0, 0x80cf00b6, + 0x005fb0bc, 0x5842b802, 0x01cfb802, 0x005f90bc, + 0xb520ffff, 0x80e70000, 0x00ffb0ba, 0x808f0000, + 0x806f001f, 0x80af001f, 0x8027b9fc, 0x5c22b801, + 0x80670700, 0x81df0000, 0x00000000, 0x00000000, + 0xb600080a, 0x00cfb803, 0x003fb0bc, 0x5822b801, + 0x01cfb801, 0x003f90bc, 0x0047b86f, 0xb0020001, + 0xb4c0fffd, 0x90210020, 0x90630020, 0x81df0004, + 0x834400d7, 0xb0180000, 0xb4200025, 0x834406d4, + 0x80c70000, 0x00df2324, 0x83640026, 0x83440220, + 0x00df0324, 0x90c60001, 0x00df2324, 0xb0060006, + 0xb4000003, 0x81472248, 0x015fb008, 0x00ffb81f, + 0x00ff90ba, 0x90e70001, 0x00ffb0ba, 0x019f9006, + 0x958cffff, 0x00df4193, 0x58c1b806, 0x118cb806, + 0xb00ce000, 0xb4800002, 0x858ce000, 0x918cc000, + 0x8153001f, 0x118cb80a, 0x819effec, 0x019fb006, + 0x015f4193, 0x5941b80a, 0x019f90cb, 0x118cb80a, + 0x019fb0cb, 0x81472230, 0x015fb008, 0x00ffb81f, + 0x015f400e, 0x194ab818, 0x015f600e, 0x802500a5, + 0x00ffb81f, 0x803bff8c, 0x805bff90, 0x803ebf14, + 0x805ebf18, 0x803bff94, 0x805bff98, 0x803ebf1c, + 0x805ebf20, 0x803bff9c, 0x805bffa0, 0x803ebf24, + 0x805ebf28, 0x80470003, 0x805ebefc, 0x003f0384, + 0x5822b801, 0x9021eb50, 0x005bb801, 0x00000000, + 0xb0020001, 0xb4200002, 0x80470001, 0x805ebefc, + 0x8073ff80, 0x98630000, 0x8027bf14, 0x8047befc, + 0x81df0000, 0x00000000, 0x00000000, 0xb6000609, + 0x009bb801, 0x00000000, 0x00a7b804, 0x6081b804, + 0x3004b803, 0xb4000001, 0x00beb802, 0x90210004, + 0x90420004, 0x81df0004, 0x00ffb81b, 0x00000000, + 0x81150010, 0x00000000, 0x00000000, 0x81350010, + 0x00000000, 0x00000000, 0x81550002, 0x00000000, + 0x015f2380, 0x81550006, 0x00000000, 0x015f2381, + 0x81550005, 0x00000000, 0x015f2382, 0x81550003, + 0x00000000, 0x015f2383, 0x81550003, 0x015f2384, + 0xb00a0001, 0xb4000005, 0x956a0001, 0xb00b0000, + 0xb4000002, 0x81750002, 0x017f2385, 0x956a0004, + 0xb00b0000, 0xb4000002, 0x81750002, 0x017f2386, + 0xb00a0002, 0xb4200003, 0x81750002, 0x00000000, + 0x017f2387, 0x81750001, 0x00000000, 0x017f2388, + 0x81750005, 0x00000000, 0x017f2389, 0x81750001, + 0x017f239f, 0xb00b0001, 0xb4200003, 0x81750008, + 0x5968b80b, 0x017f61c5, 0x81750001, 0x017f238c, + 0xb00b0001, 0xb4200003, 0x81750008, 0x00000000, + 0x017f238d, 0x81750001, 0x017f238e, 0xb00b0001, + 0xb4200005, 0x81750005, 0x00000000, 0x017f238f, + 0x81750002, 0x017f2390, 0xb00a0000, 0xb420001b, + 0x81750005, 0x00000000, 0x017f2391, 0x81750001, + 0x017f23a0, 0xb00b0001, 0xb4200003, 0x81750008, + 0x5968b80b, 0x017f61c9, 0x81750001, 0x017f2394, + 0xb00b0001, 0xb4200003, 0x81750008, 0x00000000, + 0x017f2395, 0x81750001, 0x017f2396, 0xb00b0001, + 0xb4200006, 0x81750005, 0x00000000, 0x017f2397, + 0x81750002, 0x00000000, 0x017f2398, 0x81750001, + 0x00000000, 0x017f2399, 0x81750001, 0x00000000, + 0x017f239a, 0x81750001, 0x017f239b, 0xb00b0001, + 0xb4200003, 0x8175000e, 0x00000000, 0x017f61be, + 0x81750001, 0x017f239c, 0xb00b0001, 0xb4200003, + 0x8175000e, 0x00000000, 0x017f237e, 0x81750001, + 0x017f239d, 0xb00b0001, 0xb4200006, 0x81750006, + 0x017f239e, 0x916b0001, 0x81550008, 0x856b0001, + 0xb4e0fffd, 0x00ffb81c, 0x00000000, 0x00000000, + 0x81470000, 0x015f2385, 0x015f2386, 0x015f2387, + 0x015f238d, 0x015f238f, 0x015f2390, 0x015f2391, + 0x015f2395, 0x015f2396, 0x015f2397, 0x015f2398, + 0x015f61be, 0x015f61bf, 0x82070028, 0x023f9006, + 0x83a40034, 0x83270000, 0x003fb819, 0x003f9006, + 0x5823b801, 0x83338000, 0x1b39b801, 0x003fb819, + 0x00000000, 0x00000000, 0x81550000, 0x8384ff64, + 0x017f0380, 0xad4b0026, 0x013f0381, 0x114ab809, + 0x5941b80a, 0x914ae00c, 0x0199b80a, 0x00000000, + 0x019f6193, 0xb0080b77, 0xb4200010, 0x015f0380, + 0xb00a0003, 0xb4600011, 0xb0090026, 0xb4600013, + 0x017f90ba, 0xb00b0000, 0xb4200002, 0x017f0383, + 0x017f2057, 0x015f0383, 0x017f0057, 0x300ab80b, + 0xb420000e, 0x83070000, 0x00ffb81a, 0x83070800, + 0x031f6193, 0x83070001, 0x00ffb81a, 0x83070800, + 0x031f6193, 0x83070002, 0x00ffb81a, 0x83070800, + 0x031f6193, 0x83070003, 0x00ffb81a, 0x83070003, + 0x00ffb81a, 0x5e02b810, 0x5a02b810, 0x00bf9011, + 0x00df004f, 0xa5260020, 0x81e70000, 0x82471000, + 0x95d1ffff, 0xa5cee000, 0x300eb810, 0xb4600002, + 0x05f0b80e, 0x0207b80e, 0x8267001f, 0x82c70020, + 0x82971000, 0xb0100080, 0xb4800023, 0x5a8bb813, + 0x5aa6b813, 0x1a94b815, 0x01efb812, 0x014fb814, + 0x01cfb811, 0xb520ffff, 0x81df0000, 0x00000000, + 0x00000000, 0xb636000f, 0x81470000, 0x039f8014, + 0xb6000404, 0x5948b80a, 0x957c00ff, 0x194ab80b, + 0x5f88b81c, 0xb0060020, 0xb4200001, 0x80a70000, + 0x64a6b805, 0x68e9b80a, 0x18a5b807, 0x029fa025, + 0x00a7b80a, 0x81df0004, 0x01efb812, 0x014fb814, + 0x01afb811, 0xb520ffff, 0x5ae2b816, 0x1231b817, + 0x0610b817, 0xb500ffda, 0xb0100000, 0xb4000003, + 0x5ec2b810, 0x86760001, 0xb500ffd8, 0xb00f0000, + 0xb4000005, 0x0207b80f, 0x81f3001f, 0x9a2fc000, + 0x81e70000, 0xb500ffcc, 0x015fb011, 0x00ffb81d, + 0x8057ffff, 0x80d7ffff, 0x8157ffff, 0x81d7ffff, + 0x8257ffff, 0x82d7ffff, 0x8357ffff, 0x83d7ffff, + 0x80770000, 0x80f70000, 0x81770000, 0x81f70000, + 0x82770000, 0x82f70000, 0x83770000, 0x83f70000, + 0xaeb40080, 0x808f0000, 0x806f001f, 0x80af001f, + 0xb0140000, 0xb4400014, 0x806f001f, 0x80af001f, + 0x8027b9fc, 0x5c22b801, 0x80670700, 0xb6000208, + 0x00cfb803, 0x003fb0bc, 0x5822b801, 0x01cfb801, + 0x003f90bc, 0xb520ffff, 0x90630020, 0x90210020, + 0x80270000, 0x80171000, 0xb6000303, 0xb6000001, + 0x001fa021, 0x00000000, 0x82670000, 0xb6000268, + 0x80170a00, 0x80970afc, 0x81170b00, 0x81970bfc, + 0x80271c00, 0x1021b813, 0x1021b813, 0x0217b801, + 0x80271ffc, 0x0421b813, 0x0421b813, 0x0297b801, + 0x80270c00, 0x1021b813, 0x1021b813, 0x0317b801, + 0x80270ffc, 0x0421b813, 0x0421b813, 0x0397b801, + 0x80478500, 0x1042b813, 0x5c42b802, 0x1022b815, + 0x80670280, 0x00cfb803, 0x003fb0bc, 0x5822b801, + 0x01cfb801, 0x003f90bc, 0xb520ffff, 0x009f033b, + 0x80478480, 0x0442b813, 0x5c42b802, 0x1022b815, + 0x806702a0, 0x00cfb803, 0x003fb0bc, 0x5822b801, + 0x01cfb801, 0x003f90bc, 0xb520ffff, 0xb0040000, + 0xb4000002, 0x80479000, 0xb5000001, 0x80479c00, + 0x1042b813, 0x5c42b802, 0x1022b815, 0x806702c0, + 0x00cfb803, 0x003fb0bc, 0x5822b801, 0x01cfb801, + 0x003f90bc, 0xb520ffff, 0xb0040000, 0xb4000002, + 0x80479180, 0xb5000001, 0x80479d80, 0x0442b813, + 0x5c42b802, 0x1022b815, 0x806702e0, 0x00cfb803, + 0x003fb0bc, 0x5822b801, 0x01cfb801, 0x003f90bc, + 0xb520ffff, 0x81270000, 0x80370000, 0x80b70000, + 0x81370000, 0x81b70000, 0x82370004, 0x82b7fffc, + 0xb6002016, 0x41498008, 0x51498814, 0x51498814, + 0x51418810, 0x51418810, 0x41818814, 0x0308a02a, + 0x49958820, 0x51898810, 0x51918828, 0x414d8814, + 0x0388a7ec, 0x494d8814, 0x49458810, 0x49458810, + 0x418d8810, 0x0308a02a, 0x49918fec, 0x51858814, + 0x51958fe4, 0x00000000, 0x0388a7ec, 0x92730080, + 0x009f033b, 0x5802b814, 0x90400300, 0x001f9802, + 0x00000000, 0xb0000000, 0xb4200016, 0x80170a00, + 0x80070000, 0xb6002001, 0x001fa020, 0xb0040000, + 0xb4200002, 0x80279000, 0xb5000001, 0x80279c00, + 0xac740080, 0x5c22b801, 0x11e1b803, 0x806f001f, + 0x80af001f, 0xb6000407, 0x80cf0280, 0x01ffb0bc, + 0x59e2b80f, 0x01afb80f, 0x01ff90bc, 0xb520ffff, + 0x91ef0020, 0x007f0320, 0x011f90cd, 0xaca30006, + 0x80c7b004, 0x10a5b814, 0x58a1b805, 0x10a5b806, + 0x0099b805, 0x8027b3dc, 0x5841b804, 0x1021b802, + 0x0159b801, 0x8027b3d0, 0x5841b804, 0x1021b802, + 0x0139b801, 0x80170c00, 0x0097b80a, 0xb6000002, + 0x59478020, 0x009fa04a, 0x00ffb81b, 0x00000000, + 0x009f0011, 0x015f0012, 0xb0060000, 0xb4200007, + 0x968a0001, 0xb0140000, 0xb400000d, 0x80870001, + 0x009f2011, 0x954a0002, 0x015f2012, 0xb0060002, + 0xb4200007, 0x968a0002, 0xb0140000, 0xb4000004, + 0x80870001, 0x009f2011, 0x81470000, 0x015f2012, + 0x83640037, 0x00bf2010, 0xb0060000, 0xb4200003, + 0xb0050000, 0xb4200001, 0x836400a1, 0xb0050000, + 0xb4200001, 0x836400ca, 0x00bf0010, 0xb0050000, + 0xb420000a, 0x81df0000, 0x00000000, 0x00000000, + 0x836409e4, 0x836402f6, 0x00000000, 0x8364098c, + 0x81df0004, 0x00000000, 0xb5000009, 0x00bf0010, + 0xb0050001, 0xb4000006, 0x00000000, 0x81df0000, + 0x00000000, 0x00000000, 0x83640981, 0x81df0004, + 0x00ff0325, 0x82870000, 0x81df0000, 0x00000000, + 0x00000000, 0xb6270002, 0x8364fefd, 0x92940001, + 0x81df0004, 0x80070001, 0x801eff70, 0x001f0010, + 0xb0000001, 0xb4000007, 0x001f033b, 0xb0000000, + 0xb4000002, 0x80270000, 0xb5000001, 0x80270001, + 0x003f233b, 0x00ffb81a, 0x00000000, 0x00000000, + 0x027f4001, 0x5e2ab813, 0x96310003, 0x81c70000, + 0x820700ff, 0xb0110000, 0xb4000005, 0x5a21b811, + 0x81c70200, 0x8207000e, 0x69d1b80e, 0x1210b811, + 0x01dfb0cd, 0x5e2cb813, 0x96310003, 0x023f2323, + 0x5e28b813, 0x96310003, 0x023f2322, 0x5e27b813, + 0x96310001, 0x023f2328, 0x5e23b813, 0x96310001, + 0x023f2321, 0x95f30007, 0x01ff2320, 0x920fe004, + 0x0258b810, 0x00000000, 0x1252b811, 0x025f2325, + 0x8167befc, 0x017f6195, 0x021f031c, 0x01df031d, + 0x3010b80f, 0xb4200003, 0x3011b80e, 0xb4200001, + 0xb5000025, 0x80270000, 0x80471000, 0x0017b802, + 0x8057ffff, 0x81df0000, 0x00000000, 0x00000000, + 0xb6002001, 0x001fa021, 0x80270400, 0x80679000, + 0x5c62b803, 0xb6001809, 0x00cfb801, 0x007fb0bc, + 0x5862b803, 0x01afb803, 0x007f90bc, 0x0047b86f, + 0xb0020001, 0xb4c0fffd, 0x90630020, 0x80679c00, + 0x5c62b803, 0xb6001809, 0x00cfb801, 0x007fb0bc, + 0x5862b803, 0x01afb803, 0x007f90bc, 0x0047b86f, + 0xb0020001, 0xb4c0fffd, 0x90630020, 0x81df0004, + 0x01ff231c, 0x023f231d, 0x83970300, 0x82070000, + 0x81df0000, 0x00000000, 0x00000000, 0xb6320001, + 0x039fa030, 0x81df0004, 0x00bf0010, 0x021f0324, + 0xb0100000, 0xb4200001, 0x80a70000, 0xb0050000, + 0xb4200008, 0xb0040000, 0xb4a00002, 0x80a70001, + 0xb5000004, 0x82070000, 0x021f204e, 0xb4000001, + 0x80a70002, 0xb0050001, 0xb4200007, 0x021f004e, + 0xb0100002, 0xb4a00002, 0x80a70002, 0x00ffb81b, + 0x92100001, 0x021f204e, 0x00000000, 0x00ffb81b, + 0x81530000, 0x003fb80a, 0x00000000, 0x00000000, + 0x003fb819, 0x00000000, 0x00000000, 0x81550000, + 0x8384fd6b, 0x81470000, 0x015f61ee, 0x015f61ef, + 0x015f23a4, 0x8297050c, 0x82d7ffff, 0x81df0000, + 0x00000000, 0x00000000, 0xb6000501, 0x029fa02a, + 0x81df0004, 0x8167e004, 0x116b0384, 0x0158b80b, + 0x019f0382, 0x015f237b, 0x017f0388, 0x116bb80a, + 0xb00c0008, 0xb4a00003, 0x80a70003, 0x00bf2010, + 0x00ffb81b, 0xb00a0005, 0xb4400003, 0xb00b0006, + 0xb4400001, 0x00ffb81b, 0x80a70004, 0x00bf2010, + 0x00ffb81b, 0x00000000, 0x00000000, 0x00000000, + 0x027f0388, 0x02bf037b, 0x02df0384, 0x02ff03a1, + 0x82970400, 0x8257ffff, 0x82d7ffff, 0x81df0000, + 0x00000000, 0x00000000, 0xb6350003, 0x81550001, + 0x8357ffff, 0x029fa02a, 0x82970414, 0xb6350003, + 0x81550001, 0x83d7ffff, 0x029fa02a, 0x81df0004, + 0x81550001, 0xb00a0001, 0xb4200004, 0x814d0008, + 0x6149b80a, 0x954affff, 0x015f61ee, 0xb0160000, + 0xb4200007, 0x81550001, 0xb00a0001, 0xb4200004, + 0x814d0008, 0x6149b80a, 0x954affff, 0x015f61ef, + 0x81550001, 0xb00a0001, 0xb4200042, 0x82f50001, + 0x02ff23a1, 0xb0170001, 0xb4200034, 0x82970428, + 0x81df0000, 0x00000000, 0x00000000, 0xb6350003, + 0x81550001, 0x00000000, 0x029fa02a, 0x81df0004, + 0x82970428, 0x81470000, 0x017f8034, 0xb00b0001, + 0xb4000004, 0x914a0001, 0x300ab815, 0xb480fffa, + 0xb5000001, 0x015f23a5, 0x81670000, 0xb0160002, + 0xb4200002, 0x81750001, 0x00000000, 0x017f233a, + 0x81550004, 0xadaa000c, 0x015f23a2, 0x81750004, + 0x916b0003, 0x017f23a3, 0x91ad0025, 0x01bf23a6, + 0xadab000c, 0x81e70000, 0x91ad0025, 0x01bf23a7, + 0x920a0001, 0x05abb810, 0xb00d0000, 0xb4000015, + 0x81df0000, 0x00000000, 0x00000000, 0xb62d0004, + 0x81b50001, 0x65b0b80d, 0x19efb80d, 0x92100001, + 0x81df0004, 0x01ffb0be, 0xb500000a, 0x81a70000, + 0x82970428, 0x81df0000, 0x00000000, 0x00000000, + 0xb6350001, 0x029fa02d, 0x81df0004, 0x01bf233a, + 0x01bf23a5, 0x82070000, 0x82270000, 0x82170428, + 0x81df0000, 0x00000000, 0x00000000, 0xb635003a, + 0x01bf8030, 0xb00d0001, 0xb4200036, 0x81d50001, + 0x65b1b80e, 0x1a10b80d, 0xb00e0001, 0xb4200031, + 0x81b50002, 0xadad0003, 0xae510048, 0x91cd000f, + 0x91320868, 0x015f03a2, 0xad4a0004, 0x92920700, + 0x1189b80a, 0x0297b80c, 0x1194b80a, 0x0317b80c, + 0x01ff90be, 0x015f03a2, 0x017f03a3, 0x064bb80a, + 0x0107b80a, 0xb0120000, 0xb400001e, 0xb632001d, + 0x6928b80f, 0x95290001, 0xb0090000, 0xb420000e, + 0x81350004, 0x1129b80d, 0x029fa029, 0x824d0004, + 0x5a48b812, 0x5e48b812, 0x3009b80e, 0xb4200002, + 0x5e41b812, 0xb500000d, 0x5e42b812, 0x81330040, + 0x1a52b809, 0xb5000009, 0x0127b854, 0x85290004, + 0x0397b809, 0x0287b858, 0x86940004, 0x013f803c, + 0x0397b814, 0x029fa029, 0x025f803c, 0x031fa032, + 0x91080001, 0x92310001, 0x81df0004, 0x015f03a2, + 0x017f03a3, 0x013f033a, 0xb0090001, 0xb4200023, + 0x95300002, 0x95900001, 0x1929b80c, 0xb0090000, + 0xb400001e, 0x064bb80a, 0x0107b80a, 0x81df0000, + 0x00000000, 0x00000000, 0xb6320017, 0x6928b80f, + 0x95290001, 0xb0090000, 0xb4200002, 0x81350001, + 0x013f23f8, 0x81a70700, 0x91ad0048, 0x5982b808, + 0x11adb80c, 0x0397b80d, 0x013f03f8, 0xb0090001, + 0xb4200005, 0x019f801c, 0x0196b80c, 0x81b3ff80, + 0x418cb80d, 0xb5000002, 0x019f801c, 0x0196b80c, + 0x039fa00c, 0x91080001, 0x81df0004, 0xb0160002, + 0xb420001e, 0xb0170001, 0xb4200008, 0xb00a0000, + 0xb4200002, 0x81270002, 0xb5000005, 0xb00a0002, + 0xb4400002, 0x81270003, 0xb5000001, 0x81270004, + 0x013f23a9, 0x81950001, 0xb00c0001, 0xb4200011, + 0x81a70000, 0x8397043c, 0x81df0000, 0x00000000, + 0x00000000, 0xb6290006, 0x81150001, 0x039fa028, + 0xb0080001, 0xb4200001, 0x81a70001, 0x00000000, + 0x81df0004, 0x01bf23a8, 0xb5000002, 0x81a70000, + 0x01bf23a8, 0xb0170001, 0xb4200001, 0x81b50002, + 0x82970c20, 0x81df0000, 0x00000000, 0x00000000, + 0xb6350003, 0x81550002, 0x00000000, 0x029fa02a, + 0x81df0004, 0xb0130001, 0xb4200001, 0x81150001, + 0x81c70000, 0x81df0000, 0x00000000, 0x00000000, + 0xb6350014, 0x922e0c20, 0x015ff011, 0xb00a0000, + 0xb400000f, 0x922e0428, 0x015ff011, 0xb00a0001, + 0xb4200005, 0x922e044c, 0x0297b811, 0x015f03a6, + 0x029fa00a, 0xb5000006, 0x81550006, 0xad4a0003, + 0x922e044c, 0x0297b811, 0x914a0049, 0x029fa00a, + 0x91ce0004, 0x81df0004, 0xb0170001, 0xb4200022, + 0xb00d0000, 0xb4000020, 0x852d0001, 0x81470001, + 0x6549b80a, 0xad6a0003, 0x019f03a7, 0x058c03a6, + 0x81270000, 0xb00b0000, 0xb4000005, 0x300cb80b, + 0xb4800003, 0x058cb80b, 0x91290001, 0xb500fffb, + 0x81750004, 0x5961b80b, 0x839704ec, 0x0187b860, + 0x039fa02c, 0x039fa02a, 0x039fa029, 0x039fa02b, + 0xb0090000, 0xb4000007, 0x81df0000, 0x00000000, + 0x00000000, 0xb6290003, 0x81550007, 0x00000000, + 0x00000000, 0x81df0004, 0x81c70000, 0x81df0000, + 0x00000000, 0x00000000, 0xb635002e, 0x922e0c20, + 0x01fff011, 0xb00f0000, 0xb4000029, 0x852f0001, + 0x81470001, 0x6549b80a, 0xad6a0003, 0x922e044c, + 0x025fd811, 0x86520001, 0x0227b812, 0x81270000, + 0xb00b0000, 0xb4000005, 0x3012b80b, 0xb4800003, + 0x0652b80b, 0x91290001, 0xb500fffb, 0x2e09b80b, + 0x00000000, 0x3010b811, 0xb4600001, 0x91290001, + 0xae4e0004, 0x82150004, 0x9232049c, 0x0297b811, + 0x0187b860, 0x029fa02c, 0x029fa02a, 0x029fa029, + 0x029fa030, 0xb0090000, 0xb4000004, 0xb6290003, + 0x81550007, 0x00000000, 0x00000000, 0x82270460, + 0x1231b80e, 0x0217b811, 0x81550002, 0x021fa00a, + 0x91ce0004, 0x81df0004, 0xb0130001, 0xb420000c, + 0xb0080000, 0xb400000a, 0x81550004, 0x839704fc, + 0x0167b860, 0x039fa02b, 0x81670001, 0x039fa02b, + 0x8175000e, 0x81670002, 0x039fa02b, 0x039fa02a, + 0x81150001, 0xb0080001, 0xb420000a, 0x8135000b, + 0x5d2923aa, 0x95490180, 0x5d4723ab, 0x95490060, + 0x5d4523ac, 0x95490018, 0x5d4323ad, 0x95490007, + 0x015f23ae, 0x81350001, 0xb0090001, 0xb420001b, + 0x81350006, 0x013f23af, 0xb0170001, 0xb4200005, + 0x81550004, 0x00000000, 0x015f23b0, 0x81550003, + 0x015f23b1, 0x82970474, 0x83170488, 0x81df0000, + 0x00000000, 0x00000000, 0xb6350004, 0x81550007, + 0x5e83a02a, 0x954a0007, 0x031fa02a, 0x81df0004, + 0xb0130001, 0xb4200005, 0x81750004, 0x00000000, + 0x017f23b2, 0x81750003, 0x017f23b3, 0xb0170001, + 0xb420000b, 0x81b50001, 0xb00d0001, 0xb4200008, + 0x81d50003, 0x59c8b80e, 0x91ce0300, 0x01df61da, + 0x81d50003, 0x59c8b80e, 0x91ce0300, 0x01df61db, + 0x81550001, 0xb00a0001, 0xb4200057, 0xb0170001, + 0xb4200001, 0x81550002, 0x82470000, 0x82270000, + 0x81df0000, 0x00000000, 0x00000000, 0xb6350004, + 0x81750002, 0x6571b80b, 0x92310002, 0x1a52b80b, + 0x81df0004, 0xb0170001, 0xb420001b, 0xb00a0001, + 0xb4200015, 0x81150003, 0x91080001, 0x011f23a4, + 0x829709d0, 0x831709f0, 0x83970060, 0x81df0000, + 0x00000000, 0x00000000, 0xb6280009, 0x81750005, + 0x00000000, 0x029fa02b, 0x81750004, 0x00000000, + 0x031fa02b, 0x81750003, 0x00000000, 0x039fa02b, + 0x81df0004, 0xb5000004, 0xb00a0002, 0xb4800002, + 0x81070000, 0x011f23a4, 0x82270000, 0x81270000, + 0x81df0000, 0x00000000, 0x00000000, 0xb6350025, + 0x6a11b812, 0x92310002, 0x96100003, 0xb0100001, + 0xb4200018, 0xada90020, 0x81750003, 0x920d0520, + 0x0217b810, 0x920d05c0, 0x0297b810, 0x920d0660, + 0x0317b810, 0x5942b809, 0x920a050c, 0x0397b810, + 0x916b0001, 0x039fa02b, 0xb62b0009, 0x81750005, + 0x00000000, 0x021fa02b, 0x81750004, 0x00000000, + 0x029fa02b, 0x81750003, 0x00000000, 0x031fa02b, + 0xb5000007, 0xb0100002, 0xb4800005, 0x59a2b809, + 0x91ad050c, 0x0397b80d, 0x82070000, 0x039fa010, + 0x91290001, 0x81df0004, 0x81550001, 0xb00a0001, + 0xb420000a, 0x81550009, 0xb00a0000, 0xb4000007, + 0x81df0000, 0x00000000, 0x00000000, 0xb62a0003, + 0x82150008, 0x00000000, 0x00000000, 0x81df0004, + 0xb00a0100, 0xb4a0000b, 0x954aff00, 0x81df0000, + 0x00000000, 0x00000000, 0xb6008003, 0x82150010, + 0x00000000, 0x00000000, 0x81df0004, 0x854a0100, + 0xb4e0fff6, 0x00ffb81b, 0x00000000, 0x00000000, + 0x81070000, 0x011f61dc, 0x011f61de, 0x011f61e0, + 0x011f03aa, 0x9108e0f4, 0x0138b808, 0x011f03ab, + 0x013f61ac, 0x9108e0f0, 0x0138b808, 0x011f03ac, + 0x013f61ad, 0x5901b808, 0x9108e0f8, 0x0139b808, + 0x011f03ad, 0x013f61ae, 0x5901b808, 0x9108e100, + 0x0139b808, 0x011f03ae, 0x013f61b0, 0x5901b808, + 0x9108e108, 0x0179b808, 0x013f03af, 0x017f61b1, + 0x02bf037b, 0x82970474, 0xb6350002, 0x015f8034, + 0x1929b80a, 0x011f03a1, 0xb0080001, 0xb4200002, + 0x015f03b0, 0x1929b80a, 0x019f0388, 0xb00c0001, + 0xb4200002, 0x015f03b2, 0x1929b80a, 0x013f61b3, + 0x015f03a8, 0xb00a0001, 0xb420003a, 0x81a70000, + 0x01bf237a, 0x83840056, 0x806f001f, 0x80af001f, + 0x80270300, 0x8067a800, 0x5c62b803, 0xb600080a, + 0x00cfb801, 0x007fb0bc, 0x5862b803, 0x01afb803, + 0x007f90bc, 0x0047b86f, 0xb0020001, 0xb4c0fffd, + 0x90210020, 0x90630020, 0x81a70001, 0x01bf237a, + 0x83840043, 0x838403ce, 0x81a70000, 0x01bf237a, + 0x82470400, 0x01bff012, 0x01bf23fa, 0x83840420, + 0x83840497, 0x83840546, 0x8384059d, 0x806f001f, + 0x80af001f, 0x80270300, 0x8067ac00, 0x5c62b803, + 0xb600080a, 0x00cfb801, 0x007fb0bc, 0x5862b803, + 0x01cfb803, 0x007f90bc, 0x0047b86f, 0xb0020001, + 0xb4c0fffd, 0x90210020, 0x90630020, 0x81a70001, + 0x01bf237a, 0x82470404, 0x015ff012, 0x015f23fa, + 0x83840407, 0x8384047e, 0x8384052d, 0x83840584, + 0xb5000011, 0x81a70000, 0x01bf237a, 0xb635000e, + 0x8384001b, 0x01bf037a, 0xad4d0004, 0x00000000, + 0x914a0400, 0x01bff00a, 0x01bf23fa, 0x838403f8, + 0x8384046f, 0x8384051e, 0x83840575, 0x01df037a, + 0x91ce0001, 0x01df237a, 0x019f0388, 0xb00c0001, + 0xb4200009, 0x02bf037b, 0x02bf237a, 0x838400e8, + 0x82470000, 0x025f23fa, 0x838403e9, 0x83840460, + 0x8384050f, 0x83840566, 0x00ffb81b, 0x00000000, + 0x80770000, 0x80f70000, 0x81770000, 0x81f70000, + 0x82770000, 0x82f70000, 0x83770000, 0x83f70000, + 0x8057ffff, 0x80d7ffff, 0x8157ffff, 0x81d7ffff, + 0x8257ffff, 0x82d7ffff, 0x8357ffff, 0x83d7ffff, + 0x017f037a, 0x5a42b80b, 0x01bf03a8, 0xb00d0001, + 0xb4200004, 0x011f9118, 0x013f9119, 0x7929b808, + 0xb5000002, 0x91b20460, 0x013ff00d, 0x91b20340, + 0x0297b80d, 0x00000000, 0x029fa009, 0x01df0384, + 0xb00e0000, 0xb4200005, 0xb00b0001, 0xb4200003, + 0x009f90c6, 0x00bf0391, 0xb5000002, 0x009f90cf, + 0x00bf0389, 0x83a40142, 0x81870000, 0x019f61b5, + 0x019f61b4, 0x5a02b80b, 0x9190044c, 0x01dfd80c, + 0x01df61b6, 0x91900488, 0x01dff00c, 0x59c1b80e, + 0x918ee118, 0x01d9b80c, 0x019f03af, 0x01df61af, + 0x858c000f, 0x5986b80c, 0x91d00474, 0x01bff00e, + 0x59c2b80d, 0x11cc61b2, 0x81870000, 0x019f61b8, + 0x91900414, 0x01dfd80c, 0x01df61b7, 0xadab0010, + 0x00000000, 0x908d049c, 0x83a40191, 0xadcb0020, + 0x5982b80b, 0x908e0520, 0x90ae05c0, 0x90ce0660, + 0x928c050c, 0x00ff9814, 0x83a40169, 0x83a401b8, + 0x017f037a, 0x59c2b80b, 0x918e0428, 0x01fff00c, + 0xb00f0001, 0xb4200081, 0x023f03a5, 0x3011b80b, + 0xb420000f, 0x01c7b860, 0x01dfb0fa, 0x01df41dc, + 0x01df61e8, 0x01df41de, 0x01df61ea, 0x01df41e0, + 0x01df61ec, 0x01df41dd, 0x01df61e9, 0x01df41df, + 0x01df61eb, 0x01df41e1, 0x01df61ed, 0xb5000024, + 0x01c7b860, 0x01dfb0f9, 0x01df41dc, 0x01df61e2, + 0x01df41de, 0x01df61e4, 0x01df41e0, 0x01df61e6, + 0x01df41dd, 0x01df61e3, 0x01df41df, 0x01df61e5, + 0x01df41e1, 0x01df61e7, 0x803f0000, 0x00000000, + 0x00000000, 0x01df90fa, 0x003fb80e, 0x00000000, + 0x00000000, 0x81d50000, 0x00000000, 0x00000000, + 0x01df41e8, 0x01df61dc, 0x01df41ea, 0x01df61de, + 0x01df41ec, 0x01df61e0, 0x01df41e9, 0x01df61dd, + 0x01df41eb, 0x01df61df, 0x01df41ed, 0x01df61e1, + 0x029f03a6, 0x029f236a, 0x029f03a7, 0x029f236c, + 0x027f03a2, 0x92b3e128, 0x0298b815, 0x019f03b0, + 0x029f2368, 0x5982b80c, 0x01df03af, 0x85ce000f, + 0x59c6b80e, 0x11cc61b2, 0x82a70001, 0x02bf61b8, + 0x82a70000, 0x02bf61b9, 0x029f41da, 0x029f61ba, + 0x029f41db, 0x029f61bb, 0x019f03b1, 0x5981b80c, + 0x918ce118, 0x0299b80c, 0xad8b0048, 0x029f61af, + 0x59a2b813, 0x118cb80d, 0x928c0868, 0x029fb0fb, + 0x928c0700, 0x029fb0fc, 0x019f41bc, 0x918c0003, + 0x019f61bc, 0x5a02b80b, 0x91900414, 0x029fd80c, + 0x029f236e, 0x808704ec, 0x83a40121, 0x808709d0, + 0x80a709f0, 0x80c70060, 0x00ff03a4, 0x83a400fc, + 0x83a4014b, 0x021f037a, 0x019f03a5, 0x300cb810, + 0xb4000016, 0x803f0000, 0x00000000, 0x00000000, + 0x01df90f9, 0x003fb80e, 0x00000000, 0x00000000, + 0x81d50000, 0x00000000, 0x00000000, 0x01df41e2, + 0x01df61dc, 0x01df41e4, 0x01df61de, 0x01df41e6, + 0x01df61e0, 0x01df41e3, 0x01df61dd, 0x01df41e5, + 0x01df61df, 0x01df41e7, 0x01df61e1, 0x029f41b6, + 0xa6d40100, 0xaeb40004, 0x81870000, 0x92b50c00, + 0x0397b815, 0xb6360001, 0x039fa02c, 0x00ffb81c, + 0x009f90cf, 0x00bf0389, 0x019f037a, 0x5982b80c, + 0x918c0340, 0x0397b80c, 0x81870000, 0x039fa00c, + 0x83a40083, 0x81870000, 0x019f61b5, 0x019f61b4, + 0x81870007, 0x019f61b6, 0x019f03b3, 0x5981b80c, + 0x918ce118, 0x01b9b80c, 0x019f03af, 0x01bf61af, + 0x858c000f, 0x5986b80c, 0x01bf03b2, 0x59a2b80d, + 0x118cb80d, 0x019f61b2, 0x81870000, 0x019f61b7, + 0x019f61b8, 0x808704fc, 0x83a400d9, 0x80870000, + 0x80a70000, 0x80c70000, 0x80e70000, 0x83a400b4, + 0x83a40103, 0x81470000, 0x81e70c1c, 0x0397b80f, + 0xb600f901, 0x039fa02a, 0x00ffb81c, 0x00000000, + 0x82270000, 0x023f2011, 0x0227b860, 0x023fb0ff, + 0x02bf9006, 0x92350028, 0x8213001f, 0x9210e000, + 0x3011b810, 0xb4800001, 0x86312000, 0x021f4193, + 0x5a01b810, 0x86100028, 0x83a4fa36, 0x82270000, + 0x003fb811, 0x02bf9006, 0x5aa3b815, 0x82338000, + 0x1a31b815, 0x003fb811, 0x8067e950, 0x5c62b803, + 0x81f50000, 0x80270400, 0x81df0000, 0x00000000, + 0x00000000, 0xb6000409, 0x814fffc0, 0x00cfb801, + 0x007fb0bc, 0x5862b803, 0x01cfb803, 0x007f90bc, + 0xb520ffff, 0x90210020, 0x90630020, 0x81df0004, + 0x82870000, 0x81f50010, 0x019f4193, 0x5d61b80c, + 0x5d43b80c, 0x114ab80b, 0x0187b80a, 0x960cff00, + 0x92100100, 0x858c0001, 0x81df0000, 0x00000000, + 0x00000000, 0xb62c000c, 0x81f50010, 0x5e28b80f, + 0xb6000209, 0x5a48b814, 0x9652ff00, 0x5e68b814, + 0x5981b813, 0x918c1000, 0x01dfd80c, 0x2252b811, + 0x2292b80e, 0x962f00ff, 0x81df0004, 0x81870000, + 0x86100100, 0xb4e0ffec, 0xb00a0000, 0xb4000009, + 0x81670000, 0xb0140000, 0xb4000001, 0x81670001, + 0x017f2012, 0x258a4193, 0x918c0001, 0x81470000, + 0xb500ffde, 0x81670000, 0xb0140000, 0xb4000001, + 0x81670002, 0x116b0012, 0x803f0000, 0x00000000, + 0x00000000, 0x003fb811, 0x00000000, 0x00000000, + 0x81f50000, 0x017f2012, 0x00ffb81a, 0x00000000, + 0x61f4b804, 0x91ef0001, 0x8233003f, 0x9a31ffff, + 0x5a02b804, 0x1610b811, 0x92510001, 0x1a10b812, + 0x029f03fb, 0xb0140001, 0xb4200012, 0x5a21b805, + 0x92b1e910, 0x0299b815, 0x5a22b805, 0x5a90b814, + 0x6290b814, 0x92b1e890, 0x11efb814, 0x029bb815, + 0x8233ff80, 0x3011b814, 0xb4000006, 0x4294b811, + 0x00000000, 0x0288b814, 0x4210b814, 0x00000000, + 0x0208b810, 0x029f9003, 0x82f3007f, 0x9af7ffff, + 0x3017b814, 0xb4000003, 0x4210b814, 0x00000000, + 0x0208b810, 0x82270000, 0x02c7b810, 0xb0160000, + 0xb400000a, 0x1676b812, 0x3013b812, 0xb4000003, + 0x5ac1b816, 0x92310001, 0xb500fffa, 0x81d3ff80, + 0x3010b80e, 0xb4200001, 0x1ad6b80e, 0x05efb811, + 0x027f037a, 0x5a62b813, 0x92730340, 0x0397b813, + 0x023fd813, 0x02dfb0fd, 0x5a30b811, 0x6230b811, + 0x0631b80f, 0x3010b812, 0xb4200001, 0x92310001, + 0x82470000, 0xb0110000, 0xb4800004, 0x82470003, + 0xb0110003, 0xb4400001, 0x0247b811, 0x039fa012, + 0x124f61bc, 0x00ffb81d, 0x00000000, 0x00000000, + 0x83970a10, 0x82070000, 0xb6003201, 0x039fa030, + 0xb0070000, 0xb4000019, 0x029f41b4, 0x0297b804, + 0x0317b805, 0x0397b806, 0xb6270014, 0x12948034, + 0x01df8038, 0xb00e0000, 0xb4a0000e, 0x02bf803c, + 0x5a02b814, 0x91b00a10, 0x0217b80d, 0xb62e0008, + 0x96150003, 0x91f00001, 0xadef0080, 0xb0150004, + 0xb4600001, 0x85ef0280, 0x021fa02f, 0x92940001, + 0xb5000001, 0x021f803c, 0x00000000, 0x00ffb81d, + 0x0397b804, 0x021f036a, 0x027f803c, 0x029f803c, + 0x02bf803c, 0x02df803c, 0x5a22b810, 0x92311000, + 0x0397b811, 0xb0100000, 0xb4200001, 0x039fa036, + 0xb0150000, 0xb4000021, 0x0227b860, 0x023fb0ff, + 0xb520ffff, 0x803f0000, 0x82138000, 0x1a10b813, + 0x003fb810, 0x00000000, 0x00000000, 0x82150000, + 0x00000000, 0xb635000d, 0x82550007, 0x5a42b812, + 0x9212e4b8, 0x025bb810, 0x8227000c, 0xb6000307, + 0x68d1b812, 0x94c6000f, 0x84c60002, 0x12d6b806, + 0xb6340001, 0x039fa036, 0x86310004, 0x803f0000, + 0x82138000, 0x023f90ff, 0x1a31b810, 0x003fb811, + 0x00000000, 0x00000000, 0x82150000, 0x00ffb81d, + 0x00ff41b5, 0x011f41b4, 0x019f41af, 0x01bf41ae, + 0x01df41ba, 0x01ff41bb, 0x82070000, 0x023f0380, + 0x82470000, 0xae310032, 0x029f41b3, 0x5862b807, + 0x90431000, 0x81970ad8, 0x0217b802, 0x90430c00, + 0x0297b802, 0x0317b802, 0x912802a4, 0x007ff009, + 0x58478030, 0x792341b6, 0x0529b807, 0x019fa029, + 0xb0080014, 0xb4800011, 0xa5420c00, 0x031fa02a, + 0x84690001, 0xb4a00011, 0xb623000b, 0x58678030, + 0xa4030c00, 0x031fa020, 0x044ab800, 0x0056b802, + 0x5c41b802, 0xf84200ff, 0x90620100, 0x005ff003, + 0x7d40b80a, 0x114ab802, 0xb5000004, 0xa5420c00, + 0x58478010, 0xa5620c00, 0x031fa02a, 0xb0080016, + 0xb4400043, 0xb0080013, 0xb440002c, 0xb0080006, + 0xb4400024, 0xb0080005, 0xb4400014, 0xb0080002, + 0xb4400006, 0x80440030, 0x015f619c, 0x05cab80c, + 0x05eab80d, 0x066eb810, 0xb500003c, 0x8044002a, + 0x300a419c, 0xb4800001, 0x82470001, 0x015f619c, + 0xb0120001, 0xb4200001, 0xb500001a, 0x05cab80c, + 0x05eab80d, 0x066eb810, 0xb5000030, 0x001f41b6, + 0xb0000007, 0xb4000001, 0x8044001b, 0x300a419c, + 0xb4800001, 0x82470001, 0xb0120001, 0xb4200001, + 0xb500000c, 0x05cab80c, 0x05eab80d, 0x066eb810, + 0xb5000022, 0x80440010, 0x840b0100, 0x300ab800, + 0xb4200001, 0x86100040, 0xb5000002, 0x86100080, + 0xfe100000, 0x046e41ad, 0x042ab80c, 0x7dc1b803, + 0x044f41ac, 0x042ab80d, 0x7de1b802, 0x046eb810, + 0x7e6fb803, 0xb5000011, 0x840b0100, 0x3000b80a, + 0xb4200002, 0x82070180, 0x00ffb802, 0x300ab80b, + 0xb4a00002, 0x86100040, 0xfe100000, 0x00ffb802, + 0x046e41ad, 0x042ab80c, 0x7dc1b803, 0x044f41ac, + 0x042ab80d, 0x7de1b802, 0x7e6eb80f, 0x380a41b0, + 0xb4600003, 0x242a41b0, 0x5c22b801, 0x1273b801, + 0xb0140000, 0xb4200002, 0x80071fe0, 0xb5000016, + 0x1011b808, 0x5801b800, 0x9020e26c, 0x0079b801, + 0x5842b808, 0x90420a10, 0x7c03b813, 0x003f9802, + 0x1000b801, 0x003f41b2, 0x5830b801, 0x6030b801, + 0x0400b801, 0x003f41b1, 0x5830b801, 0x6030b801, + 0x0400b801, 0xfc000000, 0xf8001fe0, 0x94001fe0, + 0x100041b1, 0x9400ffff, 0x8067003f, 0xb6290008, + 0x005f8014, 0x0442b800, 0x9442ffff, 0x5850b802, + 0x6050b802, 0xfc420000, 0x5c45b802, 0x7a82a023, + 0x10e7b809, 0x91080001, 0x300741b6, 0xb420ff6a, + 0x019f61af, 0x01bf61ae, 0x01df61ba, 0x01ff61bb, + 0x00ff41b5, 0x011f41b4, 0x019f41b8, 0x01bf41b7, + 0x01df41dd, 0x01ff41df, 0x021f41e1, 0x027f90fd, + 0x029f41bc, 0x02ff41dc, 0x031f41de, 0x033f41e0, + 0x5822b807, 0x91210c00, 0x0117b809, 0x81970ad8, + 0x91211000, 0x0217b809, 0x91210c00, 0x0317b809, + 0x80170ba0, 0x013f802c, 0xb629005f, 0x003f8038, + 0xb001000e, 0xb440001e, 0xb001000c, 0xb4400054, + 0xb001000a, 0xb4400043, 0xb0010007, 0xb440003c, + 0xb0010005, 0xb440002b, 0xb0010000, 0xb440001a, + 0xb00d0001, 0xb4200010, 0x005f418f, 0xac42bb75, + 0x8073005a, 0x9442ffff, 0x005f618f, 0x95628000, + 0x5848b802, 0xb00b8000, 0xb4200002, 0x8173ff00, + 0x1842b80b, 0x9863827a, 0x4043b802, 0x00000000, + 0x0048b802, 0xb500003f, 0x80470000, 0xb500003d, + 0x8401000f, 0x5c22b800, 0x902102d8, 0x001ff001, + 0x004db800, 0xb5000037, 0x86f70001, 0xb4600005, + 0x80750005, 0x5862b803, 0x9043e44c, 0x01d9b802, + 0x82e70002, 0x5c4cb80e, 0x9462000f, 0x5862b803, + 0x90630200, 0x005f9803, 0x59c4b80e, 0x95ceffff, + 0xb5000028, 0x87180001, 0xb4600005, 0x80750007, + 0x5862b803, 0x9043e4b8, 0x01f9b802, 0x83070002, + 0x5c4cb80f, 0x9462000f, 0x5862b803, 0x9063020c, + 0x005f9803, 0x59e4b80f, 0x95efffff, 0xb5000019, + 0x80750003, 0x5862b803, 0x90630220, 0x005f9803, + 0xb5000014, 0x87390001, 0xb4600005, 0x80750007, + 0x5862b803, 0x9043e6ac, 0x0219b802, 0x83270001, + 0x5c4cb810, 0x9462000f, 0x5862b803, 0x9063023c, + 0x005f9803, 0x5a04b810, 0x9610ffff, 0xb5000005, + 0x80750004, 0x5862b803, 0x90630268, 0x005f9803, + 0x00000000, 0x001fa022, 0x80170ba0, 0xb00c0001, + 0xb4200035, 0x023f90fb, 0x007f9811, 0x025f90fc, + 0x06d4b803, 0x007f9812, 0x4083b813, 0x00000000, + 0x0088b804, 0xb629002b, 0x24368030, 0x9421ffff, + 0x5830b801, 0x6030b801, 0x40448020, 0xb0010020, + 0xb4800003, 0x80470000, 0x80670000, 0xb500000e, + 0xb0010000, 0xb4a00004, 0x82b30080, 0x6aa1b815, + 0x4042b815, 0xb5000008, 0x6c41b802, 0x82a70017, + 0x12b5b801, 0x6875b803, 0x1842b803, 0x00000000, + 0x00000000, 0x00000000, 0x0108a022, 0x007f41b9, + 0x90630001, 0x007f61b9, 0xb003000c, 0xb420000c, + 0x92310004, 0x023fb0fb, 0x007f9811, 0x92520004, + 0x06d4b803, 0x025fb0fc, 0x007f9812, 0x80470000, + 0x4083b813, 0x00000000, 0x0088b804, 0x005f61b9, + 0x00000000, 0xb500001a, 0xb6290019, 0x24348030, + 0x9421ffff, 0x5830b801, 0x6030b801, 0x40538020, + 0xb0010020, 0xb4800003, 0x80470000, 0x80670000, + 0xb500000e, 0xb0010000, 0xb4a00004, 0x82b30080, + 0x6aa1b815, 0x4042b815, 0xb5000008, 0x6c41b802, + 0x82a70017, 0x12b5b801, 0x6875b803, 0x1842b803, + 0x00000000, 0x00000000, 0x00000000, 0x0108a022, + 0x10e7b809, 0x91080001, 0x300741b6, 0xb420ff48, + 0x00ff61b5, 0x011f61b4, 0x01df61dd, 0x01ff61df, + 0x021f61e1, 0x02ff61dc, 0x031f61de, 0x033f61e0, + 0x00ffb81d, 0x00000000, 0x00000000, 0x00000000, + 0x8057ffff, 0x80d7ffff, 0x8157ffff, 0x81d7ffff, + 0x8257ffff, 0x808f0000, 0x003f9113, 0x005f9114, + 0x7141b802, 0x80cf0700, 0x8027b064, 0x5c22b801, + 0x003fb0bc, 0x5822b801, 0x01cfb801, 0x003f90bc, + 0xb520ffff, 0x80cf0704, 0x8027b06c, 0x5c22b801, + 0x003fb0bc, 0x5822b801, 0x01cfb801, 0x003f90bc, + 0xb520ffff, 0x81e7043c, 0x82071c00, 0x82271c10, + 0x019f03a9, 0x806f001f, 0x80af001f, 0x80270400, + 0x8067a800, 0x5c62b803, 0xb6000808, 0x00cfb801, + 0x007fb0bc, 0x5862b803, 0x01cfb803, 0x007f90bc, + 0xb520ffff, 0x90210020, 0x90630020, 0x81971000, + 0x82170c00, 0xb6000004, 0x003f800c, 0x005f8010, + 0x021fa021, 0x019fa022, 0x00bfd810, 0x003fd811, + 0x70c1b80a, 0x001f980f, 0x91ef0004, 0x92100002, + 0x92310002, 0x5822b805, 0x90411000, 0x0197b802, + 0x90410c00, 0x0217b802, 0x0466b805, 0xb0000000, + 0xb4000005, 0xb6230004, 0x003f8010, 0x005f800c, + 0x1201a022, 0x0581a022, 0x858c0001, 0xb4e0ffea, + 0x80270400, 0x8067ac00, 0x5c62b803, 0xb6000808, + 0x00cfb801, 0x007fb0bc, 0x5862b803, 0x01afb803, + 0x007f90bc, 0xb520ffff, 0x90210020, 0x90630020, + 0x00ffb81c, 0x00000000, 0x00000000, 0x00000000, + 0x808f0000, 0x806f001f, 0x80af001f, 0x003f037a, + 0xb0010000, 0xb4400030, 0x81a7b7fc, 0x5da2b80d, + 0x80670500, 0xb6000208, 0x00cfb803, 0x01bfb0bc, + 0x59a2b80d, 0x01cfb80d, 0x01bf90bc, 0xb520ffff, + 0x90630020, 0x91ad0020, 0x81c7b8fc, 0x5dc2b80e, + 0x80670540, 0xb6000208, 0x00cfb803, 0x01dfb0bc, + 0x59c2b80e, 0x01cfb80e, 0x01df90bc, 0xb520ffff, + 0x90630020, 0x91ce0020, 0x81a7b3fc, 0x5da2b80d, + 0x80670600, 0xb6000408, 0x00cfb803, 0x01bfb0bc, + 0x59a2b80d, 0x01cfb80d, 0x01bf90bc, 0xb520ffff, + 0x90630020, 0x91ad0020, 0x81c7b5fc, 0x5dc2b80e, + 0x80670680, 0xb6000408, 0x00cfb803, 0x01dfb0bc, + 0x59c2b80e, 0x01cfb80e, 0x01df90bc, 0xb520ffff, + 0x90630020, 0x91ce0020, 0x005f03fa, 0xb0020000, + 0xb4000024, 0x8057ffff, 0x80d7ffff, 0x8157ffff, + 0x81d7ffff, 0x8257ffff, 0x82d7ffff, 0x8357ffff, + 0x83d7ffff, 0x83971300, 0x83171200, 0x82971100, + 0x82171000, 0x81170c00, 0x81970ff8, 0x80171400, + 0x80971500, 0x005f802c, 0x001f8028, 0xb6004010, + 0x41028000, 0x51008004, 0x007f876c, 0x0208a028, + 0x41008000, 0x49028004, 0x003f8068, 0x0388a028, + 0x41038000, 0x51018004, 0x005f802c, 0x0288a028, + 0x41018020, 0x49038024, 0x001f8028, 0x0308a028, + 0x00ffb81c, 0x83d7ffff, 0x8357ffff, 0x82d7ffff, + 0x8257ffff, 0x8157ffff, 0x81d7ffff, 0x8057ffff, + 0x80d7ffff, 0x82971200, 0x82171000, 0x81170c00, + 0x81970ffc, 0x83171800, 0x83971a00, 0x83370000, + 0x83b70000, 0x81370008, 0x81b7fff8, 0x4119880c, + 0xb6008006, 0x511d8808, 0x41498838, 0x0208a028, + 0x494d883c, 0x4119880c, 0x0288a02a, 0x00ffb81c, + 0x82670000, 0x82a70000, 0x003f037a, 0xb0010000, + 0xb4400018, 0x81a7bdfc, 0x5da2b80d, 0x80670580, + 0xb6000208, 0x00cfb803, 0x01bfb0bc, 0x59a2b80d, + 0x01cfb80d, 0x01bf90bc, 0xb520ffff, 0x90630020, + 0x91ad0020, 0x81a7eb70, 0x5da2b80d, 0x806705c0, + 0xb6000208, 0x00cfb803, 0x01bfb0bc, 0x59a2b80d, + 0x01cfb80d, 0x01bf90bc, 0xb520ffff, 0x90630020, + 0x91ad0020, 0x02bf03fa, 0x808f0000, 0xb0150000, + 0xb4000006, 0x81470040, 0x81670003, 0x81870002, + 0x81a71000, 0x81c71300, 0xb5000005, 0x81470080, + 0x81670004, 0x81870001, 0x81a71000, 0x81c71200, + 0x0017b80d, 0x0097b80e, 0x108db80a, 0x0117b804, + 0x108eb80a, 0x0197b804, 0x5841b80a, 0x108db802, + 0x0217b804, 0x108eb802, 0x0297b804, 0x106ab802, + 0x108db803, 0x0317b804, 0x108eb803, 0x0397b804, + 0x5ea2b80a, 0xb6350020, 0x001f8000, 0x003f8008, + 0x005f8004, 0x007f800c, 0x10c08010, 0x10a18018, + 0x10828014, 0x10e3801c, 0x1246b805, 0x0686b805, + 0x10c4b807, 0x0484b807, 0x80e70000, 0x80a70000, + 0x0008a032, 0x0108a034, 0x0088a026, 0x0188a024, + 0x04c08010, 0x04a18018, 0x04828014, 0x04e3801c, + 0x0646b807, 0x1286b807, 0x10c4b805, 0x0484b805, + 0x80e70000, 0x80a70000, 0x0208a032, 0x0308a034, + 0x0288a026, 0x0388a024, 0x5de1b80a, 0x82070004, + 0xb62b002a, 0x0017b80d, 0x0097b80e, 0x102db80f, + 0x0117b801, 0x104eb80f, 0x0197b802, 0x82171600, + 0x82971700, 0x0037b80f, 0x00b7b80f, 0x0137b80f, + 0x01b7b80f, 0xb630001b, 0x003f8030, 0x005f8034, + 0x5ee2b80f, 0x8013007f, 0x9800ffff, 0xb6370011, + 0x41008000, 0x51018008, 0x4902800c, 0x40c08000, + 0x0008a028, 0x48c18008, 0x50c2800c, 0x42808004, + 0x00c8b806, 0x52828008, 0x5281800c, 0x41008004, + 0x0088a034, 0x49028008, 0x4901800c, 0x011fa026, + 0x0188a028, 0x001f8001, 0x001f8005, 0x001f8009, + 0x001f800d, 0x5de1b80f, 0x5a01b810, 0x0017b80d, + 0x0097b80e, 0x902d0004, 0x0117b801, 0x904e0004, + 0x0197b802, 0x82171600, 0x82971700, 0x5ea1b80a, + 0x8013007f, 0x9800ffff, 0xb6350013, 0x003f8030, + 0x005f8034, 0x42408000, 0x52418008, 0x4a42800c, + 0x41008000, 0x0008a052, 0x49018008, 0x5102800c, + 0x42808004, 0x0108b808, 0x52828008, 0x5281800c, + 0x40c08004, 0x0088a054, 0x48c28008, 0x48c1800c, + 0x011fa048, 0x0188a046, 0x81a71100, 0x81c71200, + 0x858c0001, 0xb4e0ff7e, 0x00ffb81c, 0x00000000, + 0x005f03fa, 0x00000000, 0xb0020000, 0xb4000034, + 0x81b70080, 0x81d7ffff, 0x81f70001, 0x82370080, + 0x8257ffff, 0x82770001, 0x82b70080, 0x82d7ffff, + 0x82f70001, 0x83370080, 0x8357ffff, 0x83770001, + 0x81971000, 0x82171100, 0x82971200, 0x83171300, + 0x815703fc, 0x81370200, 0x81170c00, 0x83d703fc, + 0x83b70200, 0x83970f00, 0x8057ffff, 0x80d7ffff, + 0x80171400, 0x80971500, 0x001f800d, 0x003f8019, + 0xb6004012, 0x41008000, 0x51018004, 0x007f8011, + 0x0128a008, 0x41018000, 0x49008004, 0x009f8015, + 0x03a8a008, 0x41038000, 0x51048004, 0x001f800d, + 0x03a8a008, 0x41048020, 0x49038024, 0x003f8019, + 0x0128a008, 0x005f8028, 0x005f803c, 0x81f70000, + 0x82770000, 0x82f70000, 0x83770000, 0x00ffb81c, + 0x82370040, 0x8257ffff, 0x82770001, 0x82b70040, + 0x82d7ffff, 0x82f70001, 0x82171000, 0x82971200, + 0x8157ffff, 0x81170c00, 0x81d7ffff, 0x81970e00, + 0x8057ffff, 0x80d7ffff, 0x80171800, 0x80971a00, + 0xb600800a, 0x001f8011, 0x003f8015, 0x41008000, + 0x51018004, 0x00000000, 0x0108a028, 0x41018020, + 0x49008024, 0x00000000, 0x0188a028, 0x82770000, + 0x82f70000, 0x00ffb81c, 0x00000000, 0x00000000, + 0x8057ffff, 0x80d7ffff, 0x8157ffff, 0x808f0000, + 0x015f0384, 0x017f037a, 0xac4a0006, 0x8027b004, + 0x1042b80b, 0x5841b802, 0x1021b802, 0x0159b801, + 0x013f0325, 0x01bf0320, 0x5822b80b, 0x90210340, + 0x00ff9801, 0x8027b2e8, 0x5842b807, 0x1021b802, + 0x025bb801, 0x80070000, 0xac4d0006, 0x8027b004, + 0x1042b800, 0x5841b802, 0x1021b802, 0x0199b801, + 0x00000000, 0xac4c0006, 0x8027b078, 0x1042b80a, + 0x5842b802, 0x1021b802, 0x011bb801, 0x00000000, + 0x40d2b808, 0x00000000, 0xb0060000, 0xb4000080, + 0x005f033b, 0x80278400, 0xac600080, 0x5c22b801, + 0x10a1b803, 0xb0020000, 0xb4200002, 0x80279000, + 0xb5000001, 0x80279c00, 0x5c22b801, 0x11e1b803, + 0x80470300, 0x5822b800, 0x1042b801, 0x003f9802, + 0x806f001f, 0x80af001f, 0xb0010000, 0xb4200024, + 0x80170c00, 0x80971000, 0x003f8020, 0xb6000003, + 0x4201b806, 0x003f8020, 0x0088a030, 0x80270400, + 0xb6000208, 0x00cfb801, 0x00bfb0bc, 0x58a2b805, + 0x01afb805, 0x00bf90bc, 0xb520ffff, 0x90210020, + 0x90a50020, 0xb6000408, 0x00cfb801, 0x01ffb0bc, + 0x59e2b80f, 0x01afb80f, 0x01ff90bc, 0xb520ffff, + 0x90210020, 0x91ef0020, 0xb6000208, 0x00cfb801, + 0x00bfb0bc, 0x58a2b805, 0x01afb805, 0x00bf90bc, + 0xb520ffff, 0x90210020, 0x90a50020, 0xb5000043, + 0x80270400, 0x0087b805, 0x01c7b80f, 0xb6000208, + 0x00cfb801, 0x009fb0bc, 0x5882b804, 0x01cfb804, + 0x009f90bc, 0xb520ffff, 0x90210020, 0x90840020, + 0xb6000408, 0x00cfb801, 0x01dfb0bc, 0x59c2b80e, + 0x01cfb80e, 0x01df90bc, 0xb520ffff, 0x90210020, + 0x91ce0020, 0xb6000208, 0x00cfb801, 0x009fb0bc, + 0x5882b804, 0x01cfb804, 0x009f90bc, 0xb520ffff, + 0x90210020, 0x90840020, 0x80170c00, 0x80971000, + 0x8053007f, 0x9842ffff, 0xb6000004, 0x42028004, + 0x4a068020, 0x00000000, 0x0088a030, 0x80270400, + 0xb6000208, 0x00cfb801, 0x00bfb0bc, 0x58a2b805, + 0x01afb805, 0x00bf90bc, 0xb520ffff, 0x90210020, + 0x90a50020, 0xb6000408, 0x00cfb801, 0x01ffb0bc, + 0x59e2b80f, 0x01afb80f, 0x01ff90bc, 0xb520ffff, + 0x90210020, 0x91ef0020, 0xb6000208, 0x00cfb801, + 0x00bfb0bc, 0x58a2b805, 0x01afb805, 0x00bf90bc, + 0xb520ffff, 0x90210020, 0x90a50020, 0x5822b800, + 0x90210300, 0x0117b801, 0x80470001, 0x011fa002, + 0x90000001, 0x3000b809, 0xb480ff6b, 0x00ffb81c, + 0x8057ffff, 0x013f0325, 0x015f033b, 0x80171000, + 0x80070000, 0xb6002001, 0x001fa020, 0xb00a0001, + 0xb4c00002, 0x81679000, 0xb5000001, 0x81679c00, + 0x5d62b80b, 0x81878400, 0x5d82b80c, 0x80070000, + 0x5822b800, 0x90410300, 0x003f9802, 0x00000000, + 0xb0010000, 0xb4200019, 0xac400080, 0x00000000, + 0x10ccb802, 0x10abb802, 0x806f001f, 0x80af001f, + 0x80cf0400, 0xb6000408, 0xb520ffff, 0x00dfb0bc, + 0x58c2b806, 0x01afb806, 0x00df90bc, 0xb520ffff, + 0x80cf0400, 0x90c60020, 0x80cf0400, 0xb6000407, + 0x00bfb0bc, 0x58a2b805, 0x01afb805, 0x00bf90bc, + 0xb520ffff, 0x80cf0400, 0x90a50020, 0x90000001, + 0x3000b809, 0xb480ffde, 0x00ffb81b, 0x8057ffff, + 0x013f0325, 0x80171000, 0x80070000, 0xb6002001, + 0x001fa020, 0x81878400, 0x5d82b80c, 0x80070000, + 0x5822b800, 0x90410300, 0x003f9802, 0x00000000, + 0xb0010000, 0xb420000f, 0xac400080, 0x00000000, + 0x10ccb802, 0x806f001f, 0x80af001f, 0x80cf0400, + 0xb6000408, 0xb520ffff, 0x00dfb0bc, 0x58c2b806, + 0x01afb806, 0x00df90bc, 0xb520ffff, 0x80cf0400, + 0x90c60020, 0x90000001, 0x3000b809, 0xb480ffe8, + 0x00ffb81b, 0x8057ffff, 0x80d7ffff, 0x8157ffff, + 0x8139b000, 0x00000000, 0xb0090000, 0xb4000012, + 0x806f001f, 0x80af001f, 0x80cf0400, 0x013fb0bc, + 0x5922b809, 0x01cfb809, 0x013f90bc, 0xb520ffff, + 0x806f0003, 0x80af0003, 0x80cf0420, 0x91290020, + 0x013fb0bc, 0x5922b809, 0x01cfb809, 0x013f90bc, + 0xb520ffff, 0xb5000233, 0x80270000, 0x80171000, + 0xb6002401, 0x001fa021, 0x007f0384, 0x009f0320, + 0x00bf0385, 0x00df0386, 0x80e7b36c, 0x5821b803, + 0x1021b807, 0x0159b801, 0x5821b804, 0x1021b807, + 0x0179b801, 0x80e7b37c, 0x5821b803, 0x1021b807, + 0x0199b801, 0x5821b804, 0x1021b807, 0x01b9b801, + 0x80e7b38c, 0x5821b803, 0x1021b807, 0x01d9b801, + 0x5821b804, 0x1021b807, 0x01f9b801, 0x005f0385, + 0x8027b39c, 0x5842b802, 0x1021b802, 0x021bb801, + 0x005f0386, 0x8027b3ac, 0x5842b802, 0x1021b802, + 0x023bb801, 0x027f0383, 0x003f0328, 0x005f4195, + 0xb0130007, 0xb42000df, 0xb0010000, 0xb42000dd, + 0xb0020000, 0xb40000db, 0xb0030002, 0xb48000d9, + 0x029bb802, 0x82a7b108, 0xb00b0001, 0xb4200001, + 0xb5000005, 0xb00b0002, 0xb4200002, 0x92b500a0, + 0xb5000001, 0x92b50140, 0xb0030004, 0xb4600002, + 0x82870000, 0xb5000006, 0xb0030006, 0xb4600004, + 0xb0140001, 0xb4a00002, 0x82870001, 0xb5000000, + 0xac54000a, 0x806f0009, 0x80af0009, 0x5c22b815, + 0x80cf0440, 0x1021b802, 0x003fb0bc, 0x5822b801, + 0x01cfb801, 0x003f90bc, 0xb520ffff, 0xb0030003, + 0xb400000f, 0xb0030004, 0xb400001d, 0xb0030005, + 0xb400002b, 0xb0030006, 0xb4000042, 0xb0030007, + 0xb4000059, 0x80171000, 0x005f9440, 0x001fa002, + 0x80171038, 0x005f9440, 0x001fa002, 0xb5000073, + 0x80171000, 0x005f9440, 0x001fa002, 0x80171004, + 0x005f9443, 0x001fa002, 0x8017101c, 0x005f9446, + 0x001fa002, 0x80171034, 0x005f9449, 0x001fa002, + 0x80171038, 0x005f9440, 0x001fa002, 0xb5000063, + 0x80171000, 0x005f9440, 0x001fa002, 0x80171008, + 0x005f9441, 0x001fa002, 0x80171020, 0x005f9444, + 0x001fa002, 0x80171034, 0x005f9440, 0x001fa002, + 0x80171038, 0x005f9447, 0x001fa002, 0xb5000053, + 0x80171000, 0x005f9440, 0x001fa002, 0x80171004, + 0x005f9443, 0x001fa002, 0x8017100c, 0x005f9441, + 0x001fa002, 0x8017101c, 0x005f9446, 0x001fa002, + 0x80171024, 0x005f9444, 0x001fa002, 0x80171034, + 0x005f9449, 0x001fa002, 0x80171038, 0x005f9440, + 0x001fa002, 0x8017103c, 0x005f9447, 0x001fa002, + 0xb500003a, 0x80171000, 0x005f9440, 0x001fa002, + 0x80171008, 0x005f9441, 0x001fa002, 0x8017100c, + 0x005f9442, 0x001fa002, 0x80171020, 0x005f9444, + 0x001fa002, 0x80171024, 0x005f9445, 0x001fa002, + 0x80171034, 0x005f9440, 0x001fa002, 0x80171038, + 0x005f9447, 0x001fa002, 0x8017103c, 0x005f9448, + 0x001fa002, 0xb5000021, 0x80171000, 0x005f9440, + 0x001fa002, 0x80171004, 0x005f9443, 0x001fa002, + 0x8017100c, 0x005f9441, 0x001fa002, 0x80171010, + 0x005f9442, 0x001fa002, 0x8017101c, 0x005f9446, + 0x001fa002, 0x80171024, 0x005f9444, 0x001fa002, + 0x80171028, 0x005f9445, 0x001fa002, 0x80171034, + 0x005f9449, 0x001fa002, 0x80171038, 0x005f9440, + 0x001fa002, 0x8017103c, 0x005f9447, 0x001fa002, + 0x80171040, 0x005f9448, 0x001fa002, 0x80270001, + 0x803eff90, 0x80171000, 0x82b30020, 0x9ab50000, + 0x40158020, 0xb6000501, 0x48158020, 0x82b30020, + 0x9ab50000, 0x80470000, 0x3015b800, 0xb4600006, + 0x80171000, 0x83840226, 0xb6000603, 0x40028000, + 0x00000000, 0x0008a020, 0x80171018, 0x82b30020, + 0x9ab50000, 0x40158020, 0xb6000501, 0x48158020, + 0x82b30020, 0x9ab50000, 0x80470000, 0x3015b800, + 0xb4600006, 0x80171018, 0x83840215, 0xb6000603, + 0x40028000, 0x00000000, 0x0008a020, 0x80171030, + 0x82b30020, 0x9ab50000, 0x40158020, 0xb6000501, + 0x48158020, 0x82b30020, 0x9ab50000, 0x80470000, + 0x3015b800, 0xb4600006, 0x80171030, 0x83840204, + 0xb6000603, 0x40028000, 0x00000000, 0x0008a020, + 0xb500011e, 0x80270000, 0x803eff90, 0xb0030000, + 0xb4200067, 0x025f0322, 0xb00b0001, 0xb4200016, + 0xb0120001, 0xb4200005, 0x80171018, 0x8033007f, + 0x9821ffff, 0x001fa001, 0xb5000110, 0xb0120002, + 0xb4200005, 0x80171020, 0x8033007f, 0x9821ffff, + 0x001fa001, 0xb5000109, 0x80171018, 0x80330040, + 0x98210000, 0x001fa001, 0x80171020, 0x00000000, + 0x001fa001, 0xb5000101, 0xb00b0002, 0xb420002c, + 0xb0120000, 0xb4200008, 0x80171000, 0x8033007f, + 0x9821ffff, 0x001fa001, 0x80171038, 0x00000000, + 0x001fa001, 0xb50000f5, 0xb0120001, 0xb4200008, + 0x80171000, 0x8033005a, 0x98218279, 0x001fa001, + 0x80171030, 0x00000000, 0x001fa001, 0xb50000eb, + 0xb0120002, 0xb4200008, 0x80171008, 0x8033005a, + 0x98218279, 0x001fa001, 0x80171038, 0x00000000, + 0x001fa001, 0xb50000e1, 0x80171000, 0x80330040, + 0x98210000, 0x001fa001, 0x80171008, 0x00000000, + 0x001fa001, 0x8017100c, 0x00000000, 0x001fa001, + 0x80171038, 0x00000000, 0x001fa001, 0xb50000d3, + 0xb0120000, 0xb4200008, 0x80171000, 0x8033007f, + 0x9821ffff, 0x001fa001, 0x80171038, 0x00000000, + 0x001fa001, 0xb50000c9, 0xb0120001, 0xb4200005, + 0x80171018, 0x8033007f, 0x9821ffff, 0x001fa001, + 0xb50000c2, 0xb0120002, 0xb4200005, 0x80171020, + 0x8033007f, 0x9821ffff, 0x001fa001, 0xb50000bb, + 0x80171018, 0x80330040, 0x98210000, 0x001fa001, + 0x80171020, 0x00000000, 0x001fa001, 0xb50000b3, + 0x80070000, 0x8033007f, 0x9821ffff, 0xb600050e, + 0x144eb80f, 0xb0028000, 0xb4c00008, 0xac400006, + 0x00000000, 0x1042b800, 0x5842b802, 0x90421000, + 0x0017b802, 0x00000000, 0x001fa001, 0x90000001, + 0x59c1b80e, 0x59e1b80f, 0xb0040000, 0xb4200023, + 0xb00a0002, 0xb4000007, 0x80171004, 0x8033005a, + 0x98218279, 0x001fa001, 0x80171034, 0x00000000, + 0x001fa001, 0xb00c0002, 0xb4000009, 0x8017100c, + 0x8033ffa5, 0x98217d87, 0x001fa001, 0x8017103c, + 0x8033005a, 0x98218279, 0x001fa001, 0xb500008b, + 0x8017100c, 0x8033ffa5, 0x98217d87, 0x001fa001, + 0x80171010, 0x00000000, 0x001fa001, 0x8017103c, + 0x8033005a, 0x98218279, 0x001fa001, 0x80171040, + 0x00000000, 0x001fa001, 0xb500007c, 0xb0040001, + 0xb420002a, 0xb00a0001, 0xb4000007, 0x80171018, + 0x8033005a, 0x98218279, 0x001fa001, 0x80171020, + 0x00000000, 0x001fa001, 0xb00a0003, 0xb420000a, + 0x8053005a, 0x98428279, 0x4030b802, 0x8017101c, + 0x5821b801, 0x00000000, 0x00000000, 0x00000000, + 0x0028b801, 0x001fa001, 0xb00c0001, 0xb4200007, + 0x8053005a, 0x98428279, 0x4031b802, 0x80171024, + 0x0028b801, 0x001fa001, 0xb500005c, 0xb00c0002, + 0xb420005a, 0x8053005a, 0x98428279, 0x4031b802, + 0x80171024, 0x0028b801, 0x001fa001, 0x80171028, + 0x00000000, 0x001fa001, 0xb5000050, 0xb00b0002, + 0xb4200012, 0xb00a0001, 0xb4200008, 0x80171004, + 0x8033005a, 0x98218279, 0x001fa001, 0x80171034, + 0x00000000, 0x001fa001, 0xb5000008, 0xb00a0003, + 0xb4200006, 0x80171004, 0x00000000, 0x001fa010, + 0x80171034, 0x00000000, 0x001fa010, 0xb00c0001, + 0xb4200025, 0x027f0383, 0x003f0328, 0xb0130007, + 0xb420000b, 0xb00b0003, 0xb4200009, 0xb0010000, + 0xb4200007, 0x80171024, 0x00000000, 0x001fa011, + 0x80171054, 0x80270000, 0x001fa001, 0xb500002b, + 0xb00d0000, 0xb420000a, 0x8033005a, 0x98218279, + 0x4041b811, 0x8017100c, 0x0048b802, 0x001fa002, + 0x8017103c, 0x00000000, 0x001fa002, 0xb500001f, + 0xb00d0002, 0xb420001d, 0x80171054, 0x8033005a, + 0x98218279, 0x001fa001, 0x8017106c, 0x00000000, + 0x001fa001, 0xb5000015, 0xb00c0002, 0xb4200013, + 0xb00d0000, 0xb4200007, 0x8017100c, 0x00000000, + 0x001fa011, 0x80171040, 0x00000000, 0x001fa011, + 0xb500000a, 0xb00d0001, 0xb4200008, 0x80171054, + 0x8033005a, 0x98218279, 0x001fa001, 0x80171058, + 0x00000000, 0x001fa001, 0xb5000000, 0x029f0388, + 0x02bf0321, 0xb0140000, 0xb4000006, 0xb0150000, + 0xb4000004, 0x8017108c, 0x8033007f, 0x9821ffff, + 0x001fa001, 0x8027b078, 0x5c22b801, 0x806f001f, + 0x80af001f, 0x80cf0400, 0x003fb0bc, 0x5822b801, + 0x01afb801, 0x003f90bc, 0xb520ffff, 0x90210020, + 0x806f0003, 0x80af0003, 0x80cf0420, 0x003fb0bc, + 0x5822b801, 0x01afb801, 0x003f90bc, 0xb520ffff, + 0x81270000, 0x8033007f, 0x9821ffff, 0x80171000, + 0xb600060a, 0x80470000, 0xb6000603, 0x015f8020, + 0x0156b80a, 0x1042b80a, 0x3002b801, 0xb4a00001, + 0x81270001, 0x00000000, 0x00000000, 0x015f0323, + 0x00000000, 0xb00a0000, 0xb4200002, 0x81670000, + 0xb5000001, 0x81670001, 0x017f23fb, 0x01ff41ee, + 0x59f0b80f, 0x61f0b80f, 0x021f41ef, 0x5a10b810, + 0x6210b810, 0xb00a0003, 0xb420003b, 0x017f039f, + 0x019f41c5, 0x5990b80c, 0x6190b80c, 0xb00b0000, + 0xb400000c, 0xb00c0000, 0xb4000005, 0xac4c0100, + 0x8033001d, 0x98215500, 0x12c1b802, 0xb500000f, + 0xac4f0100, 0x8033001d, 0x98215500, 0x12c1b802, + 0xb500000a, 0xb0090000, 0xb4000005, 0xac4f0100, + 0x8033ffe2, 0x9821ab00, 0x12c1b802, 0xb5000003, + 0xac4f0100, 0x00000000, 0x02c7b802, 0xb0030000, + 0xb420007e, 0x01bf03a0, 0x01df41c9, 0x59d0b80e, + 0x61d0b80e, 0xb00d0000, 0xb400000c, 0xb00e0000, + 0xb4000005, 0xac4e0100, 0x8033001d, 0x98215500, + 0x12e1b802, 0xb5000071, 0xac500100, 0x8033001d, + 0x98215500, 0x12e1b802, 0xb500006c, 0xb0090000, + 0xb4000005, 0xac500100, 0x8033ffe2, 0x9821ab00, + 0x12e1b802, 0xb5000065, 0xac500100, 0x00000000, + 0x02e7b802, 0xb5000061, 0xb00a0002, 0xb420002f, + 0x023f9002, 0x025f9001, 0xb00f0000, 0xb4a00007, + 0xac4f0100, 0x00000000, 0x4022b811, 0x00000000, + 0x0028b801, 0x02c7b801, 0xb500000c, 0xb0090000, + 0xb4000004, 0xac4f0100, 0x00000000, 0x02c7b802, + 0xb5000006, 0xac4f0100, 0x00000000, 0x4022b812, + 0x00000000, 0x0028b801, 0x02c7b801, 0xb0030000, + 0xb4200046, 0xb0100000, 0xb4a00007, 0xac500100, + 0x00000000, 0x4022b811, 0x00000000, 0x0028b801, + 0x02e7b801, 0xb500003d, 0xb0090000, 0xb4000004, + 0xac500100, 0x00000000, 0x02e7b802, 0xb5000037, + 0xac500100, 0x00000000, 0x4022b812, 0x00000000, + 0x0028b801, 0x02e7b801, 0xb5000030, 0x023f9002, + 0x025f9001, 0xb00f0000, 0xb4a00007, 0xac4f0100, + 0x00000000, 0x4022b811, 0x00000000, 0x0028b801, + 0x02c7b801, 0xb5000006, 0xac4f0100, 0x00000000, + 0x4022b812, 0x00000000, 0x0028b801, 0x02c7b801, + 0xb0090000, 0xb4000005, 0x0047b816, 0x8033ffe2, + 0x9821ab00, 0x1042b801, 0x02c7b802, 0xb0030000, + 0xb4200016, 0xb0100000, 0xb4a00007, 0xac500100, + 0x00000000, 0x4022b811, 0x00000000, 0x0028b801, + 0x02e7b801, 0xb5000006, 0xac500100, 0x00000000, + 0x4022b812, 0x00000000, 0x0028b801, 0x02e7b801, + 0xb0090000, 0xb4000005, 0x0047b817, 0x8033ffe2, + 0x9821ab00, 0x1042b801, 0x02e7b802, 0x00000000, + 0x00000000, 0x02c8b816, 0x02dfb0cf, 0xb0030000, + 0xb4200002, 0x02e8b817, 0x02ffb0c6, 0x00ffb81b, + 0xb6001807, 0x5841b802, 0x3015b800, 0xb4800002, + 0x06b5b800, 0x98420001, 0x5aa1b815, 0x00000000, + 0x00ffb81c, 0x00000000, 0x00000000, 0x00000000, + 0x003f03f9, 0x009f0324, 0x84840001, 0xb0010000, + 0xb4000015, 0x815bb3f0, 0x81070000, 0x812707f8, + 0xb00a0000, 0xb4000006, 0x81070800, 0x81270ff8, + 0xb00a0001, 0xb4000002, 0x81071000, 0x812717f8, + 0x802500a5, 0x806500a5, 0x3001b803, 0xb420fffc, + 0x9421ffff, 0x3001b808, 0xb480000f, 0x3001b809, + 0xb4a00031, 0xb500000c, 0xb0040000, 0xb4200003, + 0x802717ff, 0x81070000, 0xb5000007, 0xb0040001, + 0xb4200002, 0x81070800, 0xb5000003, 0x80270001, + 0x003f23f9, 0x81071000, 0xb0040000, 0xb4200001, + 0x8384020c, 0x80af001f, 0x808f0000, 0x806f0000, + 0x80670400, 0x5d22b808, 0x81df0000, 0x00000000, + 0x00000000, 0xb600100a, 0x00cfb803, 0x013fb0bc, + 0x5922b809, 0x01afb809, 0x013f90bc, 0x0047b86f, + 0xb0020001, 0xb4c0fffd, 0x90630020, 0x91290020, + 0x81df0004, 0x801bb3f8, 0x80270001, 0xb0000001, + 0xb4000002, 0x802600a0, 0x803eb3f8, 0x914a0001, + 0xb00a0002, 0xb4a00001, 0x81470000, 0x815eb3f0, + 0x80270001, 0x003f2013, 0x00ffb81b, 0x00000000, + 0x029fb00a, 0x02bfb00b, 0x02dfb00c, 0x02ffb00d, + 0x031fb00e, 0x033fb00f, 0x033f400f, 0x0287b86f, + 0x029fb005, 0x8285009c, 0x96b48000, 0xb0158000, + 0xb4000195, 0x96b40100, 0xb0150100, 0xb40001ab, + 0x96b40400, 0xb0150400, 0xb40001ac, 0x96b40001, + 0xb0150001, 0xb400000c, 0x96b40008, 0xb0150008, + 0xb400019e, 0x96b44000, 0xb0154000, 0xb40001ab, + 0x96b40002, 0xb0150002, 0xb4000162, 0x00000000, + 0x00000000, 0xb50001bd, 0x02bf9017, 0x92b50001, + 0x02bfb017, 0x82850082, 0x5efdb814, 0x96f70001, + 0xb0170001, 0xb420000b, 0x83050069, 0x9718003f, + 0x82e50064, 0x12f7b818, 0x86f70109, 0x82feff74, + 0x02e7b86f, 0x9af74000, 0x01ffb817, 0x96f7bfff, + 0x01ffb817, 0x83050081, 0x82a5009a, 0x96b50001, + 0xb0150001, 0xb4200014, 0x82a70000, 0x02bfb017, + 0x96b41840, 0xb0150800, 0xb420000c, 0x96b40008, + 0x5aa9b815, 0x96d46000, 0x5ec3b816, 0x82f3000f, + 0x9af7c00f, 0x1718b817, 0x1ab5b818, 0x1ab5b816, + 0x9ab50340, 0x82a60081, 0xb5000132, 0x9b180180, + 0x83060081, 0xb500012f, 0x82a5009a, 0x96b50002, + 0xb0150002, 0xb420001b, 0x82a70000, 0x02bfb017, + 0x96b41800, 0xb0151800, 0xb4000013, 0x96b40040, + 0xb0150040, 0xb4200004, 0xa3180c00, 0x9b180340, + 0x83060081, 0xb500011f, 0x96b40008, 0x5aa9b815, + 0x96d46000, 0x5ec3b816, 0x82f3000f, 0x9af7c00f, + 0x1718b817, 0x1ab5b818, 0x1ab5b816, 0x9ab50340, + 0x82a60081, 0xb5000113, 0x9b180180, 0x83060081, + 0xb5000110, 0x82a500c1, 0x96b5000f, 0xb015000b, + 0xb420000e, 0x96b40020, 0xb0150020, 0xb400000b, + 0x96b40200, 0xb0150200, 0xb4000008, 0x82c50086, + 0x82e50094, 0x3016b817, 0xb4400004, 0x06f7b816, + 0xb017ff00, 0xb4400001, 0xb50000fe, 0x96b46000, + 0xb0156000, 0xb4000011, 0x96b41820, 0xb0150820, + 0xb4200004, 0x9b391000, 0x82a5009a, 0x96b5feff, + 0x82a6009a, 0x96b40040, 0xb0150040, 0xb4200001, + 0x9739efff, 0x96b91000, 0xb0151000, 0xb4200003, + 0x82a5009a, 0x9ab50100, 0x82a6009a, 0x96b40040, + 0xb0150040, 0xb4200019, 0x96b41800, 0xb0151800, + 0xb4200006, 0x96b98000, 0xb0158000, 0xb4200003, + 0x9b180180, 0x83060081, 0xb50000de, 0x96d80c00, + 0x82b300ff, 0x9ab5f3ff, 0x1718b815, 0xb0160c00, + 0xb4000007, 0x82e50098, 0x96f70400, 0xb0170400, + 0xb4200002, 0x82c70c00, 0xb5000001, 0xa2d60c00, + 0x1b18b816, 0x9b180340, 0xb50000c4, 0x96b40220, + 0xb0150000, 0xb4e00028, 0x82a5009d, 0x82f3ffff, + 0x16b5b817, 0x82f3000e, 0x3015b817, 0xb4200022, + 0x96f98000, 0xb0178000, 0xb400001f, 0x82a70000, + 0x02bfb017, 0x82c50081, 0x9ab60020, 0x82a60081, + 0x82a50086, 0x92b50bb8, 0x82a60094, 0x82c60081, + 0x82c5009d, 0x96d6ffff, 0x82b30032, 0x9ab58001, + 0x82e500c1, 0x96f7000f, 0xb017000b, 0xb4000002, + 0x82b30022, 0x9ab58001, 0x1ab5b816, 0x82c5009a, + 0x96d60020, 0xb0160020, 0xb4200002, 0x82b30032, + 0x9ab58001, 0x82a6009d, 0x02ff9017, 0x00000000, + 0xb0170040, 0xb4800000, 0x5eb5b814, 0x96b500f0, + 0x96f46000, 0x5eedb817, 0x1ab5b817, 0xb0170003, + 0xb4000004, 0x96b500ef, 0x96f70001, 0x5ae4b817, + 0x1ab5b817, 0x96d41800, 0xb0161800, 0xb400000a, + 0x96f900ff, 0x96b500ff, 0x9739ff00, 0x1b39b815, + 0x02a7b817, 0x96b500f3, 0x96d40008, 0x5ec1b816, + 0x1ab5b816, 0xb500000c, 0x96f98000, 0xb0178000, + 0xb4200007, 0x5efeb814, 0x96f70001, 0xb0170001, + 0xb4000003, 0x9b180180, 0x83060081, 0xb5000081, + 0x96b500f3, 0x9ab50008, 0x9739fff3, 0x96d40020, + 0xb0160020, 0xb4200017, 0x9b398000, 0x82c70000, + 0x02dfb017, 0x96d40010, 0x5ac8b816, 0x82f300ff, + 0x9af7cfff, 0x1718b817, 0x1b18b816, 0x9b180340, + 0x82c5009d, 0x96d6ffff, 0x82f3000e, 0x9af78001, + 0x1af7b816, 0x82c5009a, 0x96d60020, 0xb0160020, + 0xb4200002, 0x82f30032, 0x9af78001, 0x82e6009d, + 0xb500005a, 0x97397fff, 0x96b500ff, 0x5aaab815, + 0x82f300fc, 0x9af703ff, 0x1718b817, 0x1b18b815, + 0x9b180340, 0x82c5009a, 0x96d60010, 0xb0160010, + 0xb4200024, 0x82c70000, 0x02dfb017, 0x82c50086, + 0x92d60bb8, 0x82c60086, 0x82c50094, 0x5eefb818, + 0x96f70003, 0xb0170003, 0xb4200002, 0x82e70bb8, + 0xb5000001, 0x82e70bb8, 0x12d6b817, 0x82e50081, + 0x9af70020, 0x82e60081, 0x82c60094, 0xa2f70020, + 0x82e60081, 0x82f30001, 0x16f7b818, 0x5ef0b817, + 0xb0170001, 0xb4000004, 0x96f84000, 0x5ee4b817, + 0x9718f3ff, 0x1b18b817, 0x82f3000a, 0x9af78000, + 0x82e6009d, 0x83060081, 0x83070001, 0x8306009f, + 0xb5000096, 0x82c5009d, 0x82f3000e, 0x9af78001, + 0x3016b817, 0xb420000f, 0x82b30032, 0x9ab58001, + 0x82e500c1, 0x96f7000f, 0xb017000b, 0xb4000002, + 0x82b30022, 0x9ab58001, 0x82c5009a, 0x96d60020, + 0xb0160020, 0xb4200002, 0x82b30032, 0x9ab58001, + 0x82a6009d, 0x82c5009a, 0x96d60080, 0xb0160080, + 0xb4000011, 0x02df9017, 0x00000000, 0xb0160010, + 0xb480000d, 0x82c500c1, 0x96d6000f, 0xb016000b, + 0xb4000009, 0x82c50087, 0x96d60080, 0x5ac7b816, + 0x96f84000, 0x3017b816, 0xb4200003, 0x033f400f, + 0x9b394000, 0xb500000b, 0x9739bfff, 0x82e50061, + 0x96f70008, 0xb0170008, 0xb4000005, 0x5eefb818, + 0x96f70003, 0xb0170003, 0xb4000001, 0x9718ffff, + 0x83060081, 0x83070001, 0x8306009f, 0x00000000, + 0xb500005e, 0x82850083, 0x96b400ff, 0xb015003c, + 0xb4200019, 0x96b92000, 0xb0152000, 0xb4000002, + 0x9b392000, 0xb5000014, 0x9739d3ff, 0x82870000, + 0x82860087, 0x82870008, 0x82860083, 0x829bff78, + 0x82a7001f, 0xb0140400, 0xb4000001, 0x82a70010, + 0x82a600c9, 0x829bff78, 0x00000000, 0x828600cb, + 0x8285009d, 0x82b3ffff, 0x9ab5fffd, 0x1694b815, + 0x8286009d, 0xb5000000, 0x83070002, 0x8306009f, + 0x00000000, 0xb500003d, 0x96b90800, 0xb0150800, + 0xb4200009, 0x9739f7ff, 0x82a703fd, 0x82a600cb, + 0x82a7003c, 0x82a60083, 0x8285009d, 0x9a940002, + 0x8286009d, 0xb5000004, 0x82850087, 0x5a82b814, + 0xa2940200, 0x82860087, 0xb5000000, 0x83078000, + 0x8306009f, 0x00000000, 0xb5000028, 0x83070008, + 0x8306009f, 0x00000000, 0xb5000024, 0x83070100, + 0x8306009f, 0x00000000, 0xb5000020, 0x83070000, + 0x83050081, 0x9b180180, 0x83060081, 0x83070400, + 0x8306009f, 0x00000000, 0xb5000018, 0x82870000, + 0x82850082, 0x5eb7b814, 0x96b500fc, 0x96d40006, + 0x5ec1b816, 0x1ab5b816, 0x5aacb815, 0x83050081, + 0x82d3001c, 0x9ad600ff, 0x1718b816, 0x1b18b815, + 0x9b180e00, 0x83060081, 0x83074000, 0x8306009f, + 0x8305009d, 0x82d300ff, 0x9ad6bfff, 0x1718b816, + 0x8306009d, 0x00000000, 0xb5000000, 0x029f9005, + 0x01ffb814, 0x033f600f, 0x029f900a, 0x02bf900b, + 0x02df900c, 0x02ff900d, 0x031f900e, 0x033f900f, + 0x00ffb81e, 0x02ff9010, 0x92f70b43, 0x02ffb010, + 0x02ff90cb, 0x82bbffdc, 0x829bffd8, 0x93150004, + 0x3014b815, 0xb400000f, 0x02dbb818, 0x029bb815, + 0x3017b816, 0xb480000b, 0x5a81b814, 0x029fb010, + 0x82860095, 0x8293001f, 0x9294fe00, 0x92b50008, + 0x3015b814, 0xb4800002, 0x82b3001f, 0x92b5fa00, + 0x82beffdc, 0x029f9010, 0x83250094, 0x06d4b819, + 0x02d6b816, 0xb016ffff, 0xb4a0000a, 0x8293000e, + 0x9a948001, 0x82c5009d, 0x96d6ffff, 0x1a94b816, + 0x82c5009a, 0x96d60010, 0xb0160010, 0xb4000001, + 0x8286009d, 0x00ffb81c, 0x82870001, 0x829ef500, + 0x82850086, 0x83250094, 0x06d4b819, 0x02d6b816, + 0xb016ffff, 0xb4a0000b, 0x82870001, 0x829ef504, + 0x82c50081, 0x9ab60020, 0x82a60081, 0x82a50086, + 0x92b50bbb, 0x82a60094, 0x82c60081, 0x86b505df, + 0x82a6009b, 0x00ffb81c, 0x82070028, 0x023f9006, + 0x83a4ef48, 0x80070000, 0x001fb011, 0x001f204f, + 0x003fb800, 0x001f9006, 0x5803b800, 0x80338000, + 0x1800b801, 0x003fb800, 0x005f4193, 0x5c41b802, + 0x80350000, 0x00000000, 0x0027b860, 0x80150010, + 0x5810b800, 0x80750010, 0x1863b800, 0x8087ffff, + 0x80a7770b, 0x80c70000, 0x1403b804, 0x3000b805, + 0xb4000008, 0x5888b804, 0x58a8b805, 0x90c60001, + 0xb0060003, 0xb4a0fff8, 0x84420001, 0xb4e0ffee, + 0xb5000027, 0xb0060003, 0xb4200007, 0x80150010, + 0x5810b800, 0x81150010, 0x950800ff, 0xb0080077, + 0xb4000001, 0xb500fff4, 0x001f400e, 0x98000010, + 0x98004000, 0x9400fffe, 0x001f600e, 0x80e71fe0, + 0x001f4000, 0x94000080, 0xb0000080, 0xb4200001, + 0x80e77580, 0x00ffb008, 0x80e70020, 0xb0060000, + 0xb400000e, 0x58e3b806, 0x90210020, 0x81070000, + 0x5938b803, 0x1908b809, 0x9523ff00, 0x5928b809, + 0x1908b809, 0x5d28b803, 0x9529ff00, 0x1908b809, + 0x5d38b803, 0x1908b809, 0x011fb011, 0x00ff204f, + 0x80137fff, 0x9800ffe7, 0x1421b800, 0x5c23b801, + 0x001f9006, 0x0441b800, 0x3001b800, 0xb4600002, + 0x0440b801, 0xa4422000, 0x007f90cb, 0x1063b802, + 0x007fb0cb, 0x003fb006, 0x803effec, 0x80470001, + 0x005f2013, 0xb500eba6, 0x001f400e, 0x9400000f, + 0xb0000000, 0xb4200001, 0x00ffb81f, 0xb0000001, + 0xb4000005, 0xb0000003, 0xb4000003, 0xb0000002, + 0xb4000001, 0x00ffb81f, 0x80070001, 0x001f2013, + 0xb500eb97, 0x00000000, 0x00000000, 0x00000000, + 0x001f9012, 0x001fb100, 0x001f004c, 0x001f2404, + 0x801bfef0, 0x8058fef4, 0x803bff68, 0x8078ff6c, + 0x2000b801, 0x2042b803, 0x001fb104, 0x005f2414, + 0x82e70001, 0x83640048, 0x029fb014, 0x829efef0, + 0x8286000f, 0x02bf2054, 0x82bcfef4, 0x82a6000e, + 0x00ffb81a, 0x80e70001, 0x801336e3, 0x9800eb76, + 0x001fb100, 0x800700ab, 0x001f2404, 0x801bc3e8, + 0x8058c3ec, 0x83640024, 0x82e70000, 0x83640036, + 0x029fb300, 0x029fb100, 0x02bf2c04, 0x02bf2404, + 0x801bc000, 0x8058c004, 0x8364001b, 0x82e70000, + 0x8364002d, 0x001f9300, 0x3000b814, 0xb420000a, + 0x001f0c04, 0x3000b815, 0xb4200007, 0x829efef0, + 0x82bcfef4, 0x029fb012, 0x02bf204c, 0x82870001, + 0x829cfef5, 0x00ffb81a, 0xb0070000, 0xb4000007, + 0x80e70000, 0x801399fa, 0x9800c92e, 0x001fb100, + 0x800700af, 0x001f2404, 0xb500ffdc, 0x82870000, + 0x829cfef5, 0x00ffb81a, 0x80c700ff, 0x803bff68, + 0x8078ff6c, 0x14a0b806, 0x2063b805, 0x007f2414, + 0x2021b802, 0x58c8b806, 0x14a0b806, 0x58b0b805, + 0x2021b805, 0x58c8b806, 0x14a0b806, 0x2021b805, + 0x58c8b806, 0x14a0b806, 0x5cb0b805, 0x2021b805, + 0x003fb104, 0x00ffb81b, 0x82c70000, 0x83070400, + 0x83270005, 0x8197040c, 0x81d7ffff, 0x83840126, + 0x83840001, 0x00ffb81b, 0x808f0000, 0x806f001f, + 0x80af001f, 0x80270140, 0x81e7ef98, 0x5de2b80f, + 0xb6000208, 0x00cfb801, 0x01ffb0bc, 0x59e2b80f, + 0x01cfb80f, 0x01ff90bc, 0xb520ffff, 0x91ef0020, + 0x90210020, 0x80270180, 0x81e7ee90, 0x5de2b80f, + 0xb6000208, 0x00cfb801, 0x01ffb0bc, 0x59e2b80f, + 0x01cfb80f, 0x01ff90bc, 0xb520ffff, 0x91ef0020, + 0x90210020, 0x8057ffff, 0x80170430, 0x80070410, + 0x80270408, 0xb6000509, 0x005ff000, 0x90420500, + 0x007ff001, 0x90630600, 0x009ff002, 0x00bff003, + 0x2004a025, 0x90000001, 0x90210001, 0x80070414, + 0x80d7ffff, 0x8097045c, 0x8017043c, 0xb6000404, + 0x005ff000, 0x007f87e0, 0x84000001, 0x2082a7e3, + 0x80970460, 0x80170440, 0x2082b803, 0x007f8000, + 0x2083a004, 0x80170430, 0x80970450, 0x80270408, + 0xb6000508, 0x005f8024, 0x90420500, 0x007ff001, + 0x90630600, 0x009ff002, 0x00bff003, 0x2004a025, + 0x90210001, 0x80170440, 0x00000000, 0x02bf87e0, + 0x80970460, 0x82870000, 0xb6000404, 0x005f87e4, + 0x5a88b814, 0x204287e0, 0x1a94b802, 0x00ffb81c, + 0x001f0a49, 0x001f2709, 0x001f0a41, 0x001f2708, + 0x001f0a46, 0x001f2707, 0x001f0a48, 0x001f2706, + 0x001f0a42, 0x001f2705, 0x001f0a47, 0x001f2704, + 0x001f0a45, 0x001f2703, 0x001f0a43, 0x001f2702, + 0x001f0a40, 0x001f2701, 0x001f0a44, 0x001f2700, + 0x001f0c25, 0xa020000c, 0x94400001, 0x94600002, + 0x94810004, 0x94a10008, 0x94c00010, 0x5943b802, + 0x5861b803, 0x5882b804, 0x5ca2b805, 0x5cc4b806, + 0x194ab803, 0x194ab804, 0x194ab805, 0x194ab806, + 0x015f2738, 0x801bef90, 0x003f91c1, 0x5c28b801, + 0x005f91c2, 0x5858b802, 0x1821b802, 0x2000b801, + 0x001fb1c4, 0x8018ef94, 0x003f0709, 0x2000b801, + 0x001f2714, 0x82c70001, 0x82e70001, 0x83070710, + 0x8327001e, 0x81970735, 0x8384009f, 0x02df0738, + 0x82170a30, 0x838400f1, 0x819efef0, 0x817cfef4, + 0x819eff68, 0x817cff6c, 0x00ffb81b, 0x820f001f, + 0x8018fef8, 0x8057ffff, 0x001f2709, 0x8018fef6, + 0x80d7ffff, 0x001f2708, 0x8018fefa, 0x8157ffff, + 0x001f2707, 0x8018fefd, 0x81d7ffff, 0x001f2706, + 0x8018fefb, 0x802f001f, 0x001f2705, 0x8018fefe, + 0x00000000, 0x001f2704, 0x8018fef9, 0x00000000, + 0x001f2703, 0x8018feff, 0x00000000, 0x001f2702, + 0x8018fef7, 0x00000000, 0x001f2701, 0x8018fefc, + 0x00000000, 0x001f2700, 0x001f0c25, 0xa0200011, + 0x94410001, 0x94600002, 0x94800004, 0x94a00008, + 0x94c10010, 0x5941b802, 0x5861b803, 0x5c82b804, + 0x58a1b805, 0x5cc1b806, 0x194ab803, 0x194ab804, + 0x194ab805, 0x194ab806, 0x015f2738, 0x801bef90, + 0x003f91c1, 0x5c28b801, 0x005f91c2, 0x5858b802, + 0x1821b802, 0x2000b801, 0x001fb1c4, 0x8018ef94, + 0x003f0709, 0x2000b801, 0x001f2714, 0x82c70001, + 0x82e70001, 0x83070710, 0x8327001e, 0x81970735, + 0x83840055, 0x02df0738, 0x82170a20, 0x838400a7, + 0x819efef0, 0x817cfef4, 0x5ac8b80c, 0x02ff0a44, + 0x1ad6b817, 0x02dfb291, 0x5ed8b80c, 0x5968b80b, + 0x1ad6b80b, 0x02df6524, 0x00ffb81b, 0x820f001f, + 0x8018fefe, 0x8057ffff, 0x001f2709, 0x8018fefa, + 0x80d7ffff, 0x001f2708, 0x8018fefc, 0x8157ffff, + 0x001f2707, 0x8018feff, 0x81d7ffff, 0x001f2706, + 0x8018fef8, 0x802f001f, 0x001f2705, 0x8018fefb, + 0x00000000, 0x001f2704, 0x8018fefd, 0x00000000, + 0x001f2703, 0x8018fef6, 0x00000000, 0x001f2702, + 0x8018fef9, 0x00000000, 0x001f2701, 0x8018fef7, + 0x00000000, 0x001f2700, 0x801bef90, 0x003f91c1, + 0x5c28b801, 0x005f91c2, 0x5858b802, 0x1821b802, + 0x2000b801, 0x001fb1c4, 0x8018ef94, 0x003f0709, + 0x2000b801, 0x001f2714, 0x82c70001, 0x82e70001, + 0x83070710, 0x8327001e, 0x81970735, 0x83840016, + 0x83270000, 0x831bfef0, 0x82f8fef4, 0x02c7b819, + 0x82170a28, 0x83840065, 0x300cb818, 0xb4200002, + 0x300bb817, 0xb4000006, 0x93390001, 0xb0190020, + 0xb480fff6, 0x83270000, 0x833cfef5, 0x00ffb81b, + 0x019fb290, 0x017f2a44, 0x033f2c25, 0x83270001, + 0x833cfef5, 0x00ffb81b, 0x0007b818, 0x90000003, + 0x00000000, 0x015ff000, 0x90000001, 0x5949b80a, + 0x013ff000, 0x194ab809, 0x84000002, 0x994a0100, + 0x017ff000, 0x958b00f8, 0x5981b80c, 0x956b0007, + 0x198cb80b, 0x84000002, 0x998c0008, 0x017ff000, + 0x90000001, 0x5971b80b, 0x198cb80b, 0x017ff000, + 0x5969b80b, 0x198cb80b, 0x81a70000, 0x94d90003, + 0x82a70000, 0xb6260019, 0xb6000818, 0x5df0b80a, + 0x5e02b80a, 0x21efb810, 0x95ef0001, 0x5941b80a, + 0x194ab80f, 0x21efb816, 0x5e18b80c, 0x5e35b80c, + 0x5e54b80c, 0x5e6cb80c, 0x2210b811, 0x2252b813, + 0x2210b812, 0x96100001, 0x5981b80c, 0x198cb810, + 0x2210b817, 0x10afb810, 0x10a5b80d, 0x5da1b805, + 0x94a50001, 0x5aa1b815, 0x1ab5b805, 0x019fa7f5, + 0x5cc2b819, 0xb626001c, 0x82870000, 0xb6000419, + 0xb6000818, 0x5df0b80a, 0x5e02b80a, 0x21efb810, + 0x95ef0001, 0x5941b80a, 0x194ab80f, 0x21efb816, + 0x5e18b80c, 0x5e35b80c, 0x5e54b80c, 0x5e6cb80c, + 0x2210b811, 0x2252b813, 0x2210b812, 0x96100001, + 0x5981b80c, 0x198cb810, 0x2210b817, 0x10afb810, + 0x10a5b80d, 0x5da1b805, 0x94a50001, 0x5a81b814, + 0x1a94b805, 0x019fa7f4, 0x00ffb81c, 0x8257ffff, + 0x808f0000, 0x806f001f, 0x80af001f, 0x80270200, + 0x81e7ec70, 0x5de2b80f, 0xb6000208, 0x00cfb801, + 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, 0x01ff90bc, + 0xb520ffff, 0x91ef0020, 0x90210020, 0x80270240, + 0x81e7ed70, 0x5de2b80f, 0xb6000208, 0x00cfb801, + 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, 0x01ff90bc, + 0xb520ffff, 0x91ef0020, 0x90210020, 0x80270180, + 0x81e7ee90, 0x5de2b80f, 0xb6000208, 0x00cfb801, + 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, 0x01ff90bc, + 0xb520ffff, 0x91ef0020, 0x90210020, 0x806f0007, + 0x80af0007, 0x80270280, 0x81e7ee70, 0x5de2b80f, + 0x00cfb801, 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, + 0x01ff90bc, 0xb520ffff, 0x91ef0020, 0x90210020, + 0x80170760, 0x001f0700, 0x001fa020, 0x001f0701, + 0x001fa020, 0x001f0702, 0x001fa020, 0x001f0703, + 0x001fa020, 0x001f0704, 0x001fa000, 0x80970750, + 0x81170770, 0x82a70735, 0x83a40060, 0x001f87e4, + 0xb6000405, 0x86b50001, 0x83a4005c, 0x001f8004, + 0x003f87e8, 0x2080a7e1, 0x80970770, 0x80170750, + 0x81170750, 0x81970740, 0x82a70730, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a40050, 0x001f87e4, + 0xb6000405, 0x86b50001, 0x83a4004c, 0x001f8004, + 0x003f87e8, 0x2080a7e1, 0x80970750, 0x80170770, + 0x81170770, 0x81970760, 0x82a7072b, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a40040, 0x83a4004e, + 0xb6000407, 0x86b50001, 0x83a4003c, 0x001f8004, + 0x003f87e8, 0x2080a001, 0x83a40047, 0x00000000, + 0x80970770, 0x80170750, 0x81170750, 0x81970740, + 0x82a70726, 0x001f800c, 0x003f8008, 0x2100a001, + 0x83a4002e, 0x83a4003c, 0xb6000407, 0x86b50001, + 0x83a4002a, 0x001f8004, 0x003f87e8, 0x2080a001, + 0x83a40035, 0x00000000, 0x80970750, 0x80170770, + 0x81170770, 0x81970760, 0x82a70721, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a4001c, 0x001f87e4, + 0xb6000405, 0x86b50001, 0x83a40018, 0x001f8004, + 0x003f87e8, 0x2080a7e1, 0x80970770, 0x80170750, + 0x81170750, 0x81970740, 0x82a7071c, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a4000c, 0x017f87e4, + 0x81870000, 0xb6000406, 0x86b50001, 0x83a40007, + 0x001f87e4, 0x200087e8, 0x5988b80c, 0x198cb800, + 0x021fa02c, 0x021fa00b, 0x00ffb81c, 0x005ff015, + 0x90420600, 0x003f87e0, 0x001ff002, 0x2060b801, + 0x90630800, 0x90960a00, 0x001ff003, 0x003ff004, + 0x20a0b801, 0x90a50900, 0x00000000, 0x001ff005, + 0x009fa000, 0x00ffb81d, 0x001f8004, 0x5c21b800, + 0x5847b800, 0x1821b802, 0x942100ff, 0x2080a7e1, + 0x00ffb81d, 0x00000000, 0x00000000, 0x00000000, + 0x015f400e, 0x944a4000, 0xb0024000, 0xb420001e, + 0x954abfff, 0x015f600e, 0x820f001f, 0x802f001f, + 0x81470000, 0x015f23f9, 0x015fb0ba, 0x8057ffff, + 0x80770000, 0x82970400, 0x82d7ffff, 0x82f70000, + 0x81df0000, 0x00000000, 0x00000000, 0xb6000702, + 0xb6000001, 0x029fa02a, 0x81df0004, 0x80275480, + 0x005fb801, 0x8033001f, 0x9821c000, 0x803effe0, + 0x90212000, 0x803effe4, 0x80d9ff80, 0x00df6001, + 0x81477608, 0x015fb008, 0x003f0324, 0xb0010000, + 0xb420007e, 0x8344ebde, 0xb0180000, 0xb4000004, + 0x011f400e, 0x1908b818, 0x011f600e, 0x00ffb81f, + 0x8344f1d7, 0xb00b0000, 0xb4000006, 0x023f400e, + 0x9a310002, 0x023f600e, 0x82270000, 0x023f2012, + 0x00ffb81f, 0x8364ed6a, 0x82270000, 0x023f2011, + 0x80070000, 0x80170800, 0x81df0000, 0x00000000, + 0x00000000, 0xb6002002, 0xb6003001, 0x001fa020, + 0x81df0004, 0x82270000, 0x003fb811, 0x02bf9006, + 0x5aa3b815, 0x82338000, 0x1a31b815, 0x003fb811, + 0x8067e950, 0x5c62b803, 0x81f50000, 0x019f4193, + 0x0267b80c, 0xadcc0010, 0x80170800, 0x80130000, + 0x9800f872, 0x001fa020, 0x80134e1f, 0x98000001, + 0x001fa020, 0x59d0b80e, 0x81150010, 0x1908b80e, + 0x001fa028, 0x858c0001, 0x5e01b80c, 0x5e25b810, + 0x81df0000, 0x00000000, 0x00000000, 0xb6310006, + 0xb6002005, 0x81150010, 0x5910b808, 0x00000000, + 0x81350010, 0x1808a029, 0x9630001f, 0xb0110000, + 0xb4000006, 0xb6310005, 0x81150010, 0x5910b808, + 0x00000000, 0x81350010, 0x1808a029, 0x81df0004, + 0x962c0001, 0xb0110000, 0xb4000003, 0x81150010, + 0x5910b808, 0x001fa028, 0x019f9006, 0x958cffff, + 0x00df4193, 0x58c1b806, 0x118cb806, 0xb00ce000, + 0xb4800002, 0x858ce000, 0x918cc000, 0x8153001f, + 0x118cb80a, 0x819effec, 0x019fb006, 0x015f4193, + 0x5941b80a, 0x019f90cb, 0x118cb80a, 0x019fb0cb, + 0x019f90ba, 0x918c0001, 0x019fb0ba, 0xb00c0002, + 0xb4200016, 0x019f400e, 0x940c8000, 0xb0008000, + 0xb4200012, 0x958c7fff, 0x019f600e, 0x80070000, + 0x800600a0, 0x80073da1, 0x800600a1, 0x801bff60, + 0x00000000, 0x801eff60, 0x00000000, 0x801bff60, + 0x00000000, 0x801eff60, 0x80130001, 0x98003da1, + 0x800600a1, 0x80070001, 0x800600a0, 0x003f0324, + 0x90210001, 0xb0010005, 0xb4a00001, 0x80270000, + 0x003f2324, 0x00ffb81f, 0x00000000, 0x00000000, + 0x003f03f9, 0x009f0324, 0x84840001, 0xb0010000, + 0xb4000011, 0x815bb3f0, 0x81070000, 0x81270bf4, + 0xb00a0000, 0xb4000002, 0x81070c00, 0x81271800, + 0x802500a5, 0x806500a5, 0x3001b803, 0xb420fffc, + 0x9421ffff, 0x3001b808, 0xb480000b, 0x3001b809, + 0xb4a00032, 0xb5000008, 0xb0040000, 0xb4200003, + 0x802717ff, 0x81470000, 0xb5000003, 0x80270001, + 0x003f23f9, 0x81470c00, 0xb0040000, 0xb4200001, + 0x8384fbf4, 0x80af001f, 0x808f0002, 0x806f0000, + 0x807bbf34, 0x5d22b80a, 0x81df0000, 0x00000000, + 0x00000000, 0xb600080a, 0x00cfb803, 0x013fb0bc, + 0x5922b809, 0x01afb809, 0x013f90bc, 0x0047b86f, + 0xb0020001, 0xb4c0fffd, 0x90630020, 0x91290060, + 0x81df0004, 0x808f0000, 0x813bb3f8, 0x80270001, + 0xb0090001, 0xb4000002, 0x802600a0, 0x803eb3f8, + 0x81270c00, 0xb00a0000, 0xb4000001, 0x81270000, + 0x813eb3f0, 0xb0030800, 0xb4800001, 0x80670200, + 0x807ebf34, 0x80270001, 0x003f2013, 0x00ffb81b, +}; + +static u32 AC3I2SUcode1f8000[] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00020000, 0xffff0005, 0xffffffff, + 0x00050001, 0xffffffff, 0xffffffff, 0x00020000, + 0xffff0005, 0xffffffff, 0x00010000, 0x00050002, + 0xffffffff, 0x00020000, 0x00050003, 0xffffffff, + 0x00010000, 0x00030002, 0xffff0005, 0x00020000, + 0x00040003, 0xffff0005, 0x00010000, 0x00030002, + 0x00050004, 0x0019000d, 0x003d0025, 0x00250019, + 0x00fd003d, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x007fffff, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00000000, 0x007fffff, 0x00000000, + 0x00000000, 0x00000000, 0x007fffff, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x007fffff, + 0x007fffff, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x007fffff, 0x007fffff, 0x00000000, + 0x00000000, 0x00000000, 0x007fffff, 0x00000000, + 0x00000000, 0x00599999, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00599999, + 0x007fffff, 0x00599999, 0x00000000, 0x00599999, + 0x00000000, 0x00000000, 0x00000000, 0x00599999, + 0x00000000, 0x00599999, 0x007fffff, 0x00000000, + 0x00599999, 0x00599999, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00599999, 0x00599999, + 0x007fffff, 0x007fffff, 0x00000000, 0x00599999, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00599999, 0x007fffff, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00000000, 0x007fffff, 0x00000000, + 0x00000000, 0x00000000, 0x007fffff, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x007fffff, + 0x007fffff, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x007fffff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x007fffff, 0x00000000, + 0x007fffff, 0x00000000, 0x007fffff, 0x00400000, + 0x00200000, 0x00100000, 0x00080000, 0x00040000, + 0x00020000, 0x00010000, 0x00008000, 0x00004000, + 0x00002000, 0x00001000, 0x00000800, 0x00000400, + 0x00000200, 0x00000100, 0x00000080, 0x00000040, + 0x00000020, 0x00000010, 0x00000008, 0x00000004, + 0x00000002, 0x00000001, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00010002, + 0x00030002, 0x00030002, 0x00030002, 0x00000000, + 0x00000000, 0x00010001, 0x00020002, 0x4000a000, + 0xe000a000, 0xf000b000, 0xf800b800, 0x005a8279, + 0x004c1bf8, 0x00400000, 0x004c1bf8, 0x005a8279, + 0x00400000, 0x00000000, 0x00400000, 0x03020100, + 0x00000000, 0x00000080, 0x00000020, 0x00000008, + 0x00000000, 0x00000001, 0x00010001, 0x10001000, + 0x10001004, 0x10041004, 0x10041004, 0x10041004, + 0x00000000, 0x00000000, 0x00000000, 0xff80000a, + 0xff80031f, 0xff800b24, 0xff801818, 0xff8029fa, + 0xff8040c9, 0xff805c86, 0xff807d2e, 0xff80a2c1, + 0xff80cd3c, 0xff80fc9f, 0xff8130e8, 0xff816a14, + 0xff81a821, 0xff81eb0e, 0xff8232d6, 0xff827f79, + 0xff82d0f2, 0xff83273e, 0xff83825b, 0xff83e244, + 0xff8446f7, 0xff84b06e, 0xff851ea6, 0xff85919b, + 0xff860949, 0xff8685aa, 0xff8706ba, 0xff878c74, + 0xff8816d3, 0xff88a5d1, 0xff89396a, 0xff89d196, + 0xff8a6e51, 0xff8b0f94, 0xff8bb55a, 0xff8c5f9b, + 0xff8d0e51, 0xff8dc176, 0xff8e7902, 0xff8f34ef, + 0xff8ff535, 0xff90b9cc, 0xff9182ae, 0xff924fd3, + 0xff932132, 0xff93f6c3, 0xff94d07f, 0xff95ae5d, + 0xff969054, 0xff97765b, 0xff98606a, 0xff994e78, + 0xff9a407c, 0xff9b366b, 0xff9c303e, 0xff9d2de9, + 0xff9e2f64, 0xff9f34a4, 0xffa03da0, 0xffa14a4c, + 0xffa25aa0, 0xffa36e8f, 0xffa48610, 0xffa5a118, + 0xffa6bf9c, 0xffa7e191, 0xffa906ec, 0xffaa2fa0, + 0xffab5ba4, 0xffac8aeb, 0xffadbd6a, 0xffaef315, + 0xffb02bdf, 0xffb167be, 0xffb2a6a4, 0xffb3e886, + 0xffb52d56, 0xffb67509, 0xffb7bf92, 0xffb90ce4, + 0xffba5cf2, 0xffbbafb0, 0xffbd050f, 0xffbe5d04, + 0xffbfb780, 0xffc11477, 0xffc273db, 0xffc3d59f, + 0xffc539b4, 0xffc6a00d, 0xffc8089d, 0xffc97355, + 0xffcae027, 0xffcc4f05, 0xffcdbfe2, 0xffcf32af, + 0xffd0a75d, 0xffd21ddf, 0xffd39625, 0xffd51022, + 0xffd68bc7, 0xffd80904, 0xffd987cd, 0xffdb0810, + 0xffdc89c1, 0xffde0cd0, 0xffdf912d, 0xffe116cb, + 0xffe29d9a, 0xffe4258b, 0xffe5ae8f, 0xffe73896, + 0xffe8c392, 0xffea4f74, 0xffebdc2b, 0xffed69aa, + 0xffeef7df, 0xfff086bd, 0xfff21634, 0xfff3a634, + 0xfff536ad, 0xfff6c792, 0xfff858d1, 0xfff9ea5b, + 0xfffb7c22, 0xfffd0e16, 0xfffea026, 0xffffcdbc, + 0xfffe3ba0, 0xfffca995, 0xfffb17ac, 0xfff985f3, + 0xfff7f479, 0xfff6634f, 0xfff4d284, 0xfff34228, + 0xfff1b249, 0xfff022f7, 0xffee9442, 0xffed0638, + 0xffeb78ea, 0xffe9ec67, 0xffe860bd, 0xffe6d5fd, + 0xffe54c35, 0xffe3c374, 0xffe23bcb, 0xffe0b547, + 0xffdf2ff7, 0xffddabec, 0xffdc2933, 0xffdaa7dd, + 0xffd927f6, 0xffd7a98f, 0xffd62cb7, 0xffd4b17b, + 0xffd337ea, 0xffd1c013, 0xffd04a05, 0xffced5ce, + 0xffcd637c, 0xffcbf31d, 0xffca84c1, 0xffc91874, + 0xffc7ae45, 0xffc64641, 0xffc4e078, 0xffc37cf6, + 0xffc21bc9, 0xffc0bcff, 0xffbf60a5, 0xffbe06c9, + 0xffbcaf79, 0xffbb5ac0, 0xffba08ae, 0xffb8b94d, + 0xffb76cac, 0xffb622d8, 0xffb4dbdc, 0xffb397c6, + 0xffb256a2, 0xffb1187d, 0xffafdd62, 0xffaea55f, + 0xffad707e, 0xffac3ecc, 0xffab1054, 0xffa9e523, + 0xffa8bd44, 0xffa798c2, 0xffa677a8, 0xffa55a02, + 0xffa43fdb, 0xffa3293d, 0xffa21634, 0xffa106c9, + 0xff9ffb08, 0xff9ef2fa, 0xff9deeab, 0xff9cee23, + 0xff9bf16c, 0xff9af892, 0xff9a039c, 0xff991295, + 0xff982586, 0xff973c78, 0xff965774, 0xff957683, + 0xff9499ad, 0xff93c0fb, 0xff92ec75, 0xff921c24, + 0xff91500f, 0xff90883f, 0xff8fc4bb, 0xff8f058b, + 0xff8e4ab6, 0xff8d9443, 0xff8ce239, 0xff8c349f, + 0xff8b8b7d, 0xff8ae6d7, 0xff8a46b5, 0xff89ab1e, + 0xff891416, 0xff8881a3, 0xff87f3cc, 0xff876a96, + 0xff86e606, 0xff866621, 0xff85eaed, 0xff85746d, + 0xff8502a6, 0xff84959e, 0xff842d57, 0xff83c9d7, + 0xff836b20, 0xff831138, 0xff82bc20, 0xff826bdc, + 0xff822070, 0xff81d9de, 0xff819829, 0xff815b54, + 0xff812360, 0xff80f051, 0xff80c228, 0xff8098e6, + 0xff80748e, 0xff805521, 0xff803a9f, 0xff80250b, + 0xff801464, 0xff8008ad, 0xff8001e4, 0xff800027, + 0xff800c7e, 0xff802c8f, 0xff806056, 0xff80a7cb, + 0xff8102e4, 0xff817191, 0xff81f3c3, 0xff828964, + 0xff83325f, 0xff83ee98, 0xff84bdf3, 0xff85a04f, + 0xff86958b, 0xff879d7f, 0xff88b804, 0xff89e4ee, + 0xff8b240e, 0xff8c7533, 0xff8dd82a, 0xff8f4cbb, + 0xff90d2ad, 0xff9269c4, 0xff9411c1, 0xff95ca62, + 0xff979365, 0xff996c81, 0xff9b5570, 0xff9d4de4, + 0xff9f5590, 0xffa16c24, 0xffa3914e, 0xffa5c4b8, + 0xffa8060d, 0xffaa54f3, 0xffacb10e, 0xffaf1a03, + 0xffb18f70, 0xffb410f7, 0xffb69e33, 0xffb936c0, + 0xffbbda37, 0xffbe8830, 0xffc14042, 0xffc40201, + 0xffc6cd00, 0xffc9a0d2, 0xffcc7d05, 0xffcf612b, + 0xffd24ccf, 0xffd53f80, 0xffd838c8, 0xffdb3833, + 0xffde3d49, 0xffe14795, 0xffe4569d, 0xffe769e9, + 0xffea80ff, 0xffed9b67, 0xfff0b8a4, 0xfff3d83c, + 0xfff6f9b5, 0xfffa1c91, 0xfffd4056, 0xffff9b78, + 0xfffc7756, 0xfff953c0, 0xfff63130, 0xfff31025, + 0xffeff117, 0xffecd484, 0xffe9bae5, 0xffe6a4b6, + 0xffe39270, 0xffe0848b, 0xffdd7b82, 0xffda77cb, + 0xffd779de, 0xffd48231, 0xffd19138, 0xffcea769, + 0xffcbc535, 0xffc8eb10, 0xffc61969, 0xffc350af, + 0xffc09151, 0xffbddbbb, 0xffbb3059, 0xffb88f92, + 0xffb5f9d0, 0xffb36f78, 0xffb0f0ef, 0xffae7e96, + 0xffac18cf, 0xffa9bff9, 0xffa7746f, 0xffa5368c, + 0xffa306aa, 0xffa0e51e, 0xff9ed23c, 0xff9cce56, + 0xff9ad9bc, 0xff98f4bc, 0xff971f9f, 0xff955aae, + 0xff93a62f, 0xff920266, 0xff906f92, 0xff8eedf3, + 0xff8d7dc4, 0xff8c1f3c, 0xff8ad294, 0xff8997fd, + 0xff886fa8, 0xff8759c3, 0xff865679, 0xff8565f2, + 0xff848852, 0xff83bdbd, 0xff830651, 0xff82622b, + 0xff81d163, 0xff815411, 0xff80ea47, 0xff809416, + 0xff80518b, 0xff8022b1, 0xff80078e, 0x00000475, + 0x000007fe, 0x00000c02, 0x000010a3, 0x000015f5, + 0x00001c08, 0x000022ed, 0x00002ab5, 0x00003371, + 0x00003d32, 0x0000480a, 0x0000540d, 0x0000614b, + 0x00006fda, 0x00007fcd, 0x00009138, 0x0000a431, + 0x0000b8cc, 0x0000cf1f, 0x0000e741, 0x00010148, + 0x00011d4b, 0x00013b61, 0x00015ba2, 0x00017e25, + 0x0001a302, 0x0001ca51, 0x0001f42c, 0x000220a9, + 0x00024fe2, 0x000281f0, 0x0002b6ea, 0x0002eee9, + 0x00032a07, 0x0003685a, 0x0003a9fc, 0x0003ef04, + 0x0004378a, 0x000483a5, 0x0004d36d, 0x000526f7, + 0x00057e5b, 0x0005d9ae, 0x00063904, 0x00069c74, + 0x00070410, 0x00076feb, 0x0007e01a, 0x000854ac, + 0x0008cdb3, 0x00094b40, 0x0009cd61, 0x000a5425, + 0x000adf98, 0x000b6fc8, 0x000c04bf, 0x000c9e87, + 0x000d3d2a, 0x000de0ae, 0x000e891a, 0x000f3674, + 0x000fe8c0, 0x00109fff, 0x00115c34, 0x00121d5d, + 0x0012e37b, 0x0013ae89, 0x00147e84, 0x00155366, + 0x00162d27, 0x00170bbf, 0x0017ef23, 0x0018d748, + 0x0019c421, 0x001ab59f, 0x001babb2, 0x001ca648, + 0x001da54f, 0x001ea8b0, 0x001fb058, 0x0020bc2d, + 0x0021cc18, 0x0022dffd, 0x0023f7c2, 0x00251348, + 0x00263272, 0x00275520, 0x00287b31, 0x0029a482, + 0x002ad0f1, 0x002c0059, 0x002d3294, 0x002e677c, + 0x002f9ee8, 0x0030d8b1, 0x003214ac, 0x003352b0, + 0x00349290, 0x0035d422, 0x00371738, 0x00385ba5, + 0x0039a13b, 0x003ae7cc, 0x003c2f2a, 0x003d7725, + 0x003ebf8d, 0x00400834, 0x004150e9, 0x0042997d, + 0x0043e1c0, 0x00452981, 0x00467092, 0x0047b6c3, + 0x0048fbe3, 0x004a3fc6, 0x004b823b, 0x004cc316, + 0x004e0228, 0x004f3f45, 0x00507a40, 0x0051b2ef, + 0x0052e925, 0x00541cba, 0x00554d85, 0x00567b5e, + 0x0057a61d, 0x0058cd9e, 0x0059f1bb, 0x005b1252, + 0x005c2f3f, 0x005d4863, 0x005e5d9d, 0x005f6ed0, + 0x00607bde, 0x006184ad, 0x00628923, 0x00638927, + 0x006484a3, 0x00657b81, 0x00666daf, 0x00675b19, + 0x006843b1, 0x00692767, 0x006a062d, 0x006adff9, + 0x006bb4c2, 0x006c847d, 0x006d4f27, 0x006e14b8, + 0x006ed52f, 0x006f9089, 0x007046c6, 0x0070f7e9, + 0x0071a3f3, 0x00724aea, 0x0072ecd3, 0x007389b6, + 0x0074219d, 0x0074b490, 0x0075429b, 0x0075cbcc, + 0x00765031, 0x0076cfd8, 0x00774ad3, 0x0077c132, + 0x00783308, 0x0078a068, 0x00790968, 0x00796e1c, + 0x0079ce9a, 0x007a2af9, 0x007a8350, 0x007ad7b8, + 0x007b2849, 0x007b751d, 0x007bbe4c, 0x007c03f1, + 0x007c4625, 0x007c8504, 0x007cc0a8, 0x007cf92c, + 0x007d2eaa, 0x007d613e, 0x007d9101, 0x007dbe10, + 0x007de883, 0x007e1076, 0x007e3603, 0x007e5943, + 0x007e7a4f, 0x007e9942, 0x007eb633, 0x007ed13a, + 0x007eea6f, 0x007f01ea, 0x007f17c0, 0x007f2c08, + 0x007f3ed7, 0x007f5043, 0x007f605e, 0x007f6f3c, + 0x007f7cf1, 0x007f898e, 0x007f9525, 0x007f9fc6, + 0x007fa982, 0x007fb268, 0x007fba86, 0x007fc1eb, + 0x007fc8a4, 0x007fcebe, 0x007fd443, 0x007fd941, + 0x007fddc2, 0x007fe1cf, 0x007fe572, 0x007fe8b4, + 0x007feb9e, 0x007fee36, 0x007ff086, 0x007ff293, + 0x007ff463, 0x007ff5fd, 0x007ff765, 0x007ff8a1, + 0x007ff9b6, 0x007ffaa7, 0x007ffb79, 0x007ffc2f, + 0x007ffccb, 0x007ffd52, 0x007ffdc6, 0x007ffe28, + 0x007ffe7b, 0x007ffec2, 0x007ffefd, 0x007fff2f, + 0x007fff58, 0x007fff7b, 0x007fff97, 0x007fffae, + 0x007fffc0, 0x007fffcf, 0x007fffdb, 0x007fffe4, + 0x007fffec, 0x007ffff1, 0x007ffff6, 0x007ffff9, + 0x007ffffb, 0x007ffffd, 0x007ffffe, 0x007fffff, + 0x007fffff, 0x007fffff, 0x007fffff, 0xff800000, + 0x00000000, 0xffa57d86, 0x005a827a, 0xff89be51, + 0x0030fbc5, 0xffcf043b, 0x007641af, 0xff8275a1, + 0x0018f8b8, 0xffb8e313, 0x006a6d99, 0xff959267, + 0x00471ced, 0xffe70748, 0x007d8a5f, 0xff809dc9, + 0x000c8bd3, 0xffaecc33, 0x0062f202, 0xff8f1d34, + 0x003c56ba, 0xffdad7f4, 0x007a7d05, 0xff8582fb, + 0x0025280c, 0xffc3a946, 0x0070e2cc, 0xff9d0dfe, + 0x005133cd, 0xfff3742d, 0x007f6237, 0xff802778, + 0x000647d9, 0xffaa0a5b, 0x005ed77d, 0xff8c4a14, + 0x0036ba20, 0xffd4e0cb, 0x00788484, 0xff83d604, + 0x001f19f9, 0xffbe31e2, 0x006dca0d, 0xff99307f, + 0x004c3fe0, 0xffed37f0, 0x007e9d56, 0xff8162aa, + 0x0012c810, 0xffb3c020, 0x0066cf81, 0xff9235f3, + 0x0041ce1e, 0xffe0e607, 0x007c29fc, 0xff877b7c, + 0x002b1f35, 0xffc945e0, 0x0073b5ec, 0xffa12883, + 0x0055f5a5, 0xfff9b827, 0x007fd888, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, +}; + +static u32 AC3I2SUcode1fe000[] = { + 0x00000000, 0x03020102, 0x05040403, 0x00400040, + 0x00500050, 0x00600060, 0x00700070, 0x00800080, + 0x00a000a0, 0x00c000c0, 0x00e000e0, 0x01000100, + 0x01400140, 0x01800180, 0x01c001c0, 0x02000200, + 0x02800280, 0x03000300, 0x03800380, 0x04000400, + 0x04800480, 0x05000500, 0x00460045, 0x00580057, + 0x00690068, 0x007a0079, 0x008c008b, 0x00af00ae, + 0x00d100d0, 0x00f400f3, 0x01170116, 0x015d015c, + 0x01a201a1, 0x01e801e7, 0x022e022d, 0x02b902b8, + 0x03440343, 0x03d003cf, 0x045b045a, 0x04e604e5, + 0x05720571, 0x00600060, 0x00780078, 0x00900090, + 0x00a800a8, 0x00c000c0, 0x00f000f0, 0x01200120, + 0x01500150, 0x01800180, 0x01e001e0, 0x02400240, + 0x02a002a0, 0x03000300, 0x03c003c0, 0x04800480, + 0x05400540, 0x06000600, 0x06c006c0, 0x07800780, + 0x7b67533f, 0x1513110f, 0x04d80540, 0x04100478, + 0x07000000, 0x0b000900, 0x02b002f0, 0x02300270, + 0x017001f0, 0xf80000f0, 0x01000080, 0x02000180, + 0x03000280, 0x04000380, 0x2725231f, 0x2c2b2a29, + 0x2e2e2d2d, 0x30302f2f, 0x04030201, 0x08070605, + 0x0c0b0a09, 0x100f0e0d, 0x14131211, 0x18171615, + 0x1c1b1a19, 0x2825221f, 0x37312e2b, 0x4f49433d, + 0x796d6155, 0xcdb59d85, 0x0000fde5, 0x3d3e3f40, + 0x393a3b3c, 0x35363738, 0x32333434, 0x2f2f3031, + 0x2c2c2d2e, 0x29292a2b, 0x26262728, 0x23242425, + 0x21212223, 0x1e1f2020, 0x1c1d1d1e, 0x1a1b1b1c, + 0x1819191a, 0x16171718, 0x15151516, 0x13131414, + 0x12121213, 0x10111111, 0x0f0f1010, 0x0e0e0e0f, + 0x0d0d0d0d, 0x0c0c0c0c, 0x0b0b0b0b, 0x0a0a0a0a, + 0x0909090a, 0x08080909, 0x08080808, 0x07070707, + 0x06060707, 0x06060606, 0x05050606, 0x05050505, + 0x04040505, 0x04040404, 0x04040404, 0x03030304, + 0x03030303, 0x03030303, 0x02030303, 0x02020202, + 0x02020202, 0x02020202, 0x02020202, 0x01010202, + 0x01010101, 0x01010101, 0x01010101, 0x01010101, + 0x01010101, 0x01010101, 0x01010101, 0x00000101, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x04d004d0, + 0x04000440, 0x03c003e0, 0x03b003b0, 0x03a003a0, + 0x03a003a0, 0x039003a0, 0x03900390, 0x03800380, + 0x03700370, 0x03600360, 0x03500350, 0x03400340, + 0x03200330, 0x03000310, 0x02f002f0, 0x02f002f0, + 0x03100300, 0x03900340, 0x042003e0, 0x04900460, + 0x046004a0, 0x04400440, 0x08000520, 0x08400840, + 0x04f004f0, 0x04100460, 0x03d003e0, 0x03b003c0, + 0x03a003b0, 0x03a003a0, 0x03a003a0, 0x03900390, + 0x03800390, 0x03800380, 0x03700370, 0x03600360, + 0x03500350, 0x03400340, 0x03100320, 0x02f00300, + 0x02f002f0, 0x030002f0, 0x03500320, 0x03e00390, + 0x04500420, 0x049004a0, 0x04400460, 0x06300480, + 0x08400840, 0x05800580, 0x045004b0, 0x03f00420, + 0x03d003e0, 0x03b003c0, 0x03b003b0, 0x03a003a0, + 0x03a003a0, 0x03a003a0, 0x03a003a0, 0x03900390, + 0x03900390, 0x03800380, 0x03700380, 0x03500360, + 0x03300340, 0x03100320, 0x02f00300, 0x02f002f0, + 0x03100300, 0x03500330, 0x041003c0, 0x04a00470, + 0x04400460, 0x04e00450, 0xffaaaaab, 0x00000000, + 0x00555555, 0xff99999a, 0xffcccccd, 0x00000000, + 0x00333333, 0x00666666, 0xff924925, 0xffb6db6e, + 0xffdb6db7, 0x00000000, 0x00249249, 0x00492492, + 0x006db6db, 0xff8ba2e9, 0xffa2e8ba, 0xffba2e8c, + 0xffd1745d, 0xffe8ba2f, 0x00000000, 0x001745d1, + 0x002e8ba3, 0x0045d174, 0x005d1746, 0x00745d17, + 0xff888889, 0xff99999a, 0xffaaaaab, 0xffbbbbbc, + 0xffcccccd, 0xffddddde, 0xffeeeeef, 0x00000000, + 0x00111111, 0x00222222, 0x00333333, 0x00444444, + 0x00555555, 0x00666666, 0x00777777, 0x08070605, + 0x0c0b0a09, 0x10100e0e, 0x00000010, 0x00000000, + 0x00000010, 0x00000020, 0x00000100, 0x00000110, + 0x00000120, 0x00000200, 0x00000210, 0x00000220, + 0x00001000, 0x00001010, 0x00001020, 0x00001100, + 0x00001110, 0x00001120, 0x00001200, 0x00001210, + 0x00001220, 0x00002000, 0x00002010, 0x00002020, + 0x00002100, 0x00002110, 0x00002120, 0x00002200, + 0x00002210, 0x00002220, 0x00000000, 0x00000010, + 0x00000020, 0x00000030, 0x00000040, 0x00000100, + 0x00000110, 0x00000120, 0x00000130, 0x00000140, + 0x00000200, 0x00000210, 0x00000220, 0x00000230, + 0x00000240, 0x00000300, 0x00000310, 0x00000320, + 0x00000330, 0x00000340, 0x00000400, 0x00000410, + 0x00000420, 0x00000430, 0x00000440, 0x00001000, + 0x00001010, 0x00001020, 0x00001030, 0x00001040, + 0x00001100, 0x00001110, 0x00001120, 0x00001130, + 0x00001140, 0x00001200, 0x00001210, 0x00001220, + 0x00001230, 0x00001240, 0x00001300, 0x00001310, + 0x00001320, 0x00001330, 0x00001340, 0x00001400, + 0x00001410, 0x00001420, 0x00001430, 0x00001440, + 0x00002000, 0x00002010, 0x00002020, 0x00002030, + 0x00002040, 0x00002100, 0x00002110, 0x00002120, + 0x00002130, 0x00002140, 0x00002200, 0x00002210, + 0x00002220, 0x00002230, 0x00002240, 0x00002300, + 0x00002310, 0x00002320, 0x00002330, 0x00002340, + 0x00002400, 0x00002410, 0x00002420, 0x00002430, + 0x00002440, 0x00003000, 0x00003010, 0x00003020, + 0x00003030, 0x00003040, 0x00003100, 0x00003110, + 0x00003120, 0x00003130, 0x00003140, 0x00003200, + 0x00003210, 0x00003220, 0x00003230, 0x00003240, + 0x00003300, 0x00003310, 0x00003320, 0x00003330, + 0x00003340, 0x00003400, 0x00003410, 0x00003420, + 0x00003430, 0x00003440, 0x00004000, 0x00004010, + 0x00004020, 0x00004030, 0x00004040, 0x00004100, + 0x00004110, 0x00004120, 0x00004130, 0x00004140, + 0x00004200, 0x00004210, 0x00004220, 0x00004230, + 0x00004240, 0x00004300, 0x00004310, 0x00004320, + 0x00004330, 0x00004340, 0x00004400, 0x00004410, + 0x00004420, 0x00004430, 0x00004440, 0x00000000, + 0x00000100, 0x00000200, 0x00000300, 0x00000400, + 0x00000500, 0x00000600, 0x00000700, 0x00000800, + 0x00000900, 0x00000a00, 0x00001000, 0x00001100, + 0x00001200, 0x00001300, 0x00001400, 0x00001500, + 0x00001600, 0x00001700, 0x00001800, 0x00001900, + 0x00001a00, 0x00002000, 0x00002100, 0x00002200, + 0x00002300, 0x00002400, 0x00002500, 0x00002600, + 0x00002700, 0x00002800, 0x00002900, 0x00002a00, + 0x00003000, 0x00003100, 0x00003200, 0x00003300, + 0x00003400, 0x00003500, 0x00003600, 0x00003700, + 0x00003800, 0x00003900, 0x00003a00, 0x00004000, + 0x00004100, 0x00004200, 0x00004300, 0x00004400, + 0x00004500, 0x00004600, 0x00004700, 0x00004800, + 0x00004900, 0x00004a00, 0x00005000, 0x00005100, + 0x00005200, 0x00005300, 0x00005400, 0x00005500, + 0x00005600, 0x00005700, 0x00005800, 0x00005900, + 0x00005a00, 0x00006000, 0x00006100, 0x00006200, + 0x00006300, 0x00006400, 0x00006500, 0x00006600, + 0x00006700, 0x00006800, 0x00006900, 0x00006a00, + 0x00007000, 0x00007100, 0x00007200, 0x00007300, + 0x00007400, 0x00007500, 0x00007600, 0x00007700, + 0x00007800, 0x00007900, 0x00007a00, 0x00008000, + 0x00008100, 0x00008200, 0x00008300, 0x00008400, + 0x00008500, 0x00008600, 0x00008700, 0x00008800, + 0x00008900, 0x00008a00, 0x00009000, 0x00009100, + 0x00009200, 0x00009300, 0x00009400, 0x00009500, + 0x00009600, 0x00009700, 0x00009800, 0x00009900, + 0x00009a00, 0x0000a000, 0x0000a100, 0x0000a200, + 0x0000a300, 0x0000a400, 0x0000a500, 0x0000a600, + 0x0000a700, 0x0000a800, 0x0000a900, 0x0000aa00, + 0xff800000, 0xff800000, 0xffb82995, 0xffaf5d75, + 0xffa57d87, 0xff9a6806, 0xff8df708, 0xff800000, + 0xffb82995, 0xffaf5d75, 0xffa57d87, 0xff9a6806, + 0xff8df708, 0xff800000, 0xffb82995, 0xffaf5d75, + 0xffa57d87, 0xff9a6806, 0xff8df708, 0xff800000, + 0xffb82995, 0xffaf5d75, 0xffa57d87, 0xff9a6806, + 0xff8df708, 0xff800000, 0xffb82995, 0xffaf5d75, + 0xffa57d87, 0xff9a6806, 0xff8df708, 0xff800000, + 0xfffb0000, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, + 0xfffdfffd, 0xfffdfffd, 0xfffdfffd, 0xfffefffe, + 0xfffefffe, 0xfffefffe, 0xffffffff, 0xffffffff, + 0xffffffff, 0x00000000, 0x00000000, 0x00000000, + 0x80050000, 0x000a800f, 0x001e801b, 0x80110014, + 0x00368033, 0x8039003c, 0x802d0028, 0x00228027, + 0x00668063, 0x8069006c, 0x807d0078, 0x00728077, + 0x80550050, 0x005a805f, 0x004e804b, 0x80410044, + 0x00c680c3, 0x80c900cc, 0x80dd00d8, 0x00d280d7, + 0x80f500f0, 0x00fa80ff, 0x00ee80eb, 0x80e100e4, + 0x80a500a0, 0x00aa80af, 0x00be80bb, 0x80b100b4, + 0x00968093, 0x8099009c, 0x808d0088, 0x00828087, + 0x01868183, 0x8189018c, 0x819d0198, 0x01928197, + 0x81b501b0, 0x01ba81bf, 0x01ae81ab, 0x81a101a4, + 0x81e501e0, 0x01ea81ef, 0x01fe81fb, 0x81f101f4, + 0x01d681d3, 0x81d901dc, 0x81cd01c8, 0x01c281c7, + 0x81450140, 0x014a814f, 0x015e815b, 0x81510154, + 0x01768173, 0x8179017c, 0x816d0168, 0x01628167, + 0x01268123, 0x8129012c, 0x813d0138, 0x01328137, + 0x81150110, 0x011a811f, 0x010e810b, 0x81010104, + 0x03068303, 0x8309030c, 0x831d0318, 0x03128317, + 0x83350330, 0x033a833f, 0x032e832b, 0x83210324, + 0x83650360, 0x036a836f, 0x037e837b, 0x83710374, + 0x03568353, 0x8359035c, 0x834d0348, 0x03428347, + 0x83c503c0, 0x03ca83cf, 0x03de83db, 0x83d103d4, + 0x03f683f3, 0x83f903fc, 0x83ed03e8, 0x03e283e7, + 0x03a683a3, 0x83a903ac, 0x83bd03b8, 0x03b283b7, + 0x83950390, 0x039a839f, 0x038e838b, 0x83810384, + 0x82850280, 0x028a828f, 0x029e829b, 0x82910294, + 0x02b682b3, 0x82b902bc, 0x82ad02a8, 0x02a282a7, + 0x02e682e3, 0x82e902ec, 0x82fd02f8, 0x02f282f7, + 0x82d502d0, 0x02da82df, 0x02ce82cb, 0x82c102c4, + 0x02468243, 0x8249024c, 0x825d0258, 0x02528257, + 0x82750270, 0x027a827f, 0x026e826b, 0x82610264, + 0x82250220, 0x022a822f, 0x023e823b, 0x82310234, + 0x02168213, 0x8219021c, 0x820d0208, 0x02028207, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0xff800000, 0xffa57d86, 0xffa57d86, + 0xffcf043b, 0xff89be51, 0xff89be51, 0xffcf043b, + 0xffe70748, 0xff8275a1, 0xff959267, 0xffb8e313, + 0xffb8e313, 0xff959267, 0xff8275a1, 0xffe70748, + 0xfff3742d, 0xff809dc9, 0xff9d0dfe, 0xffaecc33, + 0xffc3a946, 0xff8f1d34, 0xff8582fb, 0xffdad7f4, + 0xffdad7f4, 0xff8582fb, 0xff8f1d34, 0xffc3a946, + 0xffaecc33, 0xff9d0dfe, 0xff809dc9, 0xfff3742d, + 0xfff9b827, 0xff802778, 0xffa12883, 0xffaa0a5b, + 0xffc945e0, 0xff8c4a14, 0xff877b7c, 0xffd4e0cb, + 0xffe0e607, 0xff83d604, 0xff9235f3, 0xffbe31e2, + 0xffb3c020, 0xff99307f, 0xff8162aa, 0xffed37f0, + 0xffed37f0, 0xff8162aa, 0xff99307f, 0xffb3c020, + 0xffbe31e2, 0xff9235f3, 0xff83d604, 0xffe0e607, + 0xffd4e0cb, 0xff877b7c, 0xff8c4a14, 0xffc945e0, + 0xffaa0a5b, 0xffa12883, 0xff802778, 0xfff9b827, + 0xcbcecdc4, 0xcfcac9c8, 0xc3c6c5cc, 0xc7c2c1c0, + 0x1b1e1d14, 0x1f1a1918, 0x1316151c, 0x17121110, + 0x2b2e2d24, 0x2f2a2928, 0x2326252c, 0x27222120, + 0x3b3e3d34, 0x3f3a3938, 0x3336353c, 0x37323130, + 0x0b0e0d04, 0x0f0a0908, 0x0306050c, 0x07020100, + 0xdbdeddd4, 0xdfdad9d8, 0xd3d6d5dc, 0xd7d2d1d0, + 0xebeeede4, 0xefeae9e8, 0xe3e6e5ec, 0xe7e2e1e0, + 0xfbfefdf4, 0xfffaf9f8, 0xf3f6f5fc, 0xf7f2f1f0, + 0x4b4e4d44, 0x4f4a4948, 0x4346454c, 0x47424140, + 0x9b9e9d94, 0x9f9a9998, 0x9396959c, 0x97929190, + 0xabaeada4, 0xafaaa9a8, 0xa3a6a5ac, 0xa7a2a1a0, + 0xbbbebdb4, 0xbfbab9b8, 0xb3b6b5bc, 0xb7b2b1b0, + 0x8b8e8d84, 0x8f8a8988, 0x8386858c, 0x87828180, + 0x5b5e5d54, 0x5f5a5958, 0x5356555c, 0x57525150, + 0x6b6e6d64, 0x6f6a6968, 0x6366656c, 0x67626160, + 0x7b7e7d74, 0x7f7a7978, 0x7376757c, 0x77727170, + 0x341424c4, 0x3e1e2ece, 0x3d1d2dcd, 0x3b1b2bcb, + 0xb494a444, 0xbe9eae4e, 0xbd9dad4d, 0xbb9bab4b, + 0xf4d4e404, 0xfedeee0e, 0xfddded0d, 0xfbdbeb0b, + 0x74546484, 0x7e5e6e8e, 0x7d5d6d8d, 0x7b5b6b8b, + 0x3c1c2ccc, 0x361626c6, 0x351525c5, 0x331323c3, + 0xbc9cac4c, 0xb696a646, 0xb595a545, 0xb393a343, + 0xfcdcec0c, 0xf6d6e606, 0xf5d5e505, 0xf3d3e303, + 0x7c5c6c8c, 0x76566686, 0x75556585, 0x73536383, + 0x381828c8, 0x3a1a2aca, 0x391929c9, 0x3f1f2fcf, + 0xb898a848, 0xba9aaa4a, 0xb999a949, 0xbf9faf4f, + 0xf8d8e808, 0xfadaea0a, 0xf9d9e909, 0xffdfef0f, + 0x78586888, 0x7a5a6a8a, 0x79596989, 0x7f5f6f8f, + 0x301020c0, 0x321222c2, 0x311121c1, 0x371727c7, + 0xb090a040, 0xb292a242, 0xb191a141, 0xb797a747, + 0xf0d0e000, 0xf2d2e202, 0xf1d1e101, 0xf7d7e707, + 0x70506080, 0x72526282, 0x71516181, 0x77576787, + 0x05040100, 0x15141110, 0x25242120, 0x35343130, + 0x85848180, 0x95949190, 0xa5a4a1a0, 0xb5b4b1b0, + 0xc0408000, 0xe060a020, 0xd0509010, 0xf070b030, + 0xc8488808, 0xe868a828, 0xd8589818, 0xf878b838, + 0xc4448404, 0xe464a424, 0xd4549414, 0xf474b434, + 0xcc4c8c0c, 0xec6cac2c, 0xdc5c9c1c, 0xfc7cbc3c, + 0xc2428202, 0xe262a222, 0xd2529212, 0xf272b232, + 0xca4a8a0a, 0xea6aaa2a, 0xda5a9a1a, 0xfa7aba3a, + 0xc6468606, 0xe666a626, 0xd6569616, 0xf676b636, + 0xce4e8e0e, 0xee6eae2e, 0xde5e9e1e, 0xfe7ebe3e, + 0xc1418101, 0xe161a121, 0xd1519111, 0xf171b131, + 0xc9498909, 0xe969a929, 0xd9599919, 0xf979b939, + 0xc5458505, 0xe565a525, 0xd5559515, 0xf575b535, + 0xcd4d8d0d, 0xed6dad2d, 0xdd5d9d1d, 0xfd7dbd3d, + 0xc3438303, 0xe363a323, 0xd3539313, 0xf373b333, + 0xcb4b8b0b, 0xeb6bab2b, 0xdb5b9b1b, 0xfb7bbb3b, + 0xc7478707, 0xe767a727, 0xd7579717, 0xf777b737, + 0xcf4f8f0f, 0xef6faf2f, 0xdf5f9f1f, 0xff7fbf3f, + 0x1045a3e2, 0x000000f4, 0x263b7333, 0x766b2363, + 0x2b367e3e, 0x7b662e6e, 0x06db93d3, 0x964b0343, + 0x0bd69ede, 0x9b460e4e, 0x825f1757, 0x12cf87c7, + 0x8f521a5a, 0x1fc28aca, 0x00d199d9, 0x90410949, + 0x01d098d8, 0x91400848, 0x24357d3d, 0x74652d6d, + 0x25347c3c, 0x75642c6c, 0x04d59ddd, 0x94450d4d, + 0x05d49cdc, 0x95440c4c, 0x80511959, 0x10c189c9, + 0x81501858, 0x11c088c8, 0x02df97d7, 0x924f0747, + 0x0fd29ada, 0x9f420a4a, 0x865b1353, 0x16cb83c3, + 0x8b561e5e, 0x1bc68ece, 0xa6bbf3b3, 0xf6eba3e3, + 0xabb6febe, 0xfbe6aeee, 0x223f7737, 0x726f2767, + 0x2f327a3a, 0x7f622a6a, 0xa0b1f9b9, 0xf0e1a9e9, + 0xa1b0f8b8, 0xf1e0a8e8, 0x84551d5d, 0x14c58dcd, + 0x85541c5c, 0x15c48ccc, 0xa4b5fdbd, 0xf4e5aded, + 0xa5b4fcbc, 0xf5e4acec, 0x20317939, 0x70612969, + 0x21307838, 0x71602868, 0xa2bff7b7, 0xf2efa7e7, + 0xafb2faba, 0xffe2aaea, 0x00000000, 0x00000000, +}; + +static u32 AC3I2SUcode1fff80[] = { + 0x0000240f, 0x007fffff, 0x007fffff, 0x00000003, + 0xff000000, 0xff000000, 0xff000000, 0xff000000, + 0xff000000, 0x00000000, 0x00000000, 0x00000000, + 0x007fffff, 0x00000000, 0x00000000, 0x00000000, +}; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/ls220/lpcm.h linux.19rc3-ac4/drivers/media/video/ls220/lpcm.h --- linux.19rc3/drivers/media/video/ls220/lpcm.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/ls220/lpcm.h 2002-07-29 13:58:41.000000000 +0100 @@ -0,0 +1,818 @@ +static u32 PCMUcode1f1800[] = { + 0xb500000f, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xb50001f7, 0x00000000, 0x00000000, 0x00000000, + 0x820f001f, 0x802f001f, 0x029f9014, 0x829efef0, + 0x8286000f, 0x02bf0054, 0x82bcfef4, 0x82a6000e, + 0x80074000, 0x001f6193, 0x8013001f, 0x9020c000, + 0x003fb006, 0x803effe8, 0x803effec, 0x9020fa00, + 0x803effd0, 0x803effdc, 0x803effd8, 0x9020fe00, + 0x803effd4, 0x90400000, 0x804600a2, 0x90421800, + 0x804600a3, 0x80132000, 0x98000040, 0x800600a6, + 0x80050080, 0x98000002, 0x80060080, 0x80070001, + 0x001f2013, 0x80070000, 0x001f23f9, 0x801e4b0c, + 0x001f210c, 0x80070001, 0x001f2324, 0x80070800, + 0x001f600f, 0x001fb0cb, 0x001fb010, 0x801efff0, + 0x98004000, 0x001f600e, 0x83e40121, 0x80070000, + 0x801e4b14, 0x800500a0, 0xb0000001, 0xb4000009, + 0x80070001, 0x800600a0, 0x80050080, 0x98000020, + 0x80060080, 0x9400ffdf, 0x80060080, 0x80070000, + 0x800600a0, 0x80074000, 0x801e4b04, 0x81df0004, + 0x801bfff0, 0x00000000, 0x940000ff, 0xb0000000, + 0xb4200033, 0x003f400e, 0x94010010, 0xb0000000, + 0xb400fff7, 0x003f0013, 0xb0010001, 0xb420001f, + 0x803bffe8, 0x801bffec, 0x805b4b04, 0x00000000, + 0x3001b800, 0xb4600001, 0x9021a000, 0x0421b800, + 0x3001b802, 0xb460000d, 0x80050086, 0x005f9044, + 0x0420b802, 0xb00101e0, 0xb4a0ffe5, 0x001fb010, + 0x001f010c, 0xb0000001, 0xb400ffe1, 0x80070001, + 0x001f210c, 0x83e400ee, 0xb500ffdd, 0x8007001f, + 0x94000003, 0x5810b800, 0x83e719ec, 0x1bffb800, + 0x003f9008, 0x1821b800, 0x00ffb801, 0x80270000, + 0x003f2013, 0x8007001f, 0x94000003, 0x5810b800, + 0x83671a14, 0x1b7bb800, 0x003f9009, 0x1821b800, + 0x00ffb801, 0x80070000, 0x001f210c, 0xb500ffc8, + 0x003f400e, 0xb0000086, 0xb4400056, 0xb0000084, + 0xb4000040, 0xb0000085, 0xb4000046, 0xb0000086, + 0xb4000048, 0xb0000083, 0xb4000000, 0x815bff7c, + 0x00000000, 0x940a0080, 0x5c07b800, 0xb0000001, + 0xb4000074, 0x81674b18, 0x940a0007, 0x5803b800, + 0x116bb800, 0x005bb80b, 0x916b0004, 0x001bb80b, + 0x80530030, 0x98422000, 0x8013ffcf, 0x9800cfff, + 0x806500d4, 0x1463b800, 0x1863b802, 0x806600d4, + 0x80073cfb, 0x801e4b00, 0x800600a1, 0x80074000, + 0x801e4b04, 0x8013001f, 0x98405000, 0x805effe0, + 0x005fb006, 0x805effe8, 0x805effec, 0x9042a000, + 0x805effe4, 0x9040fa00, 0x805effd0, 0x805effdc, + 0x805effd8, 0x9040fe00, 0x805effd4, 0x8013007f, + 0x9800ffff, 0x001fb040, 0x80070001, 0x001f2013, + 0x80070000, 0x001f2324, 0x001f600f, 0x001fb0cb, + 0x001fb010, 0x001fb041, 0x001fb042, 0x80073470, + 0x001fb008, 0x80071e50, 0x001fb009, 0x98214000, + 0xb5000010, 0x94011000, 0xb0001000, 0xb4200001, + 0x9421efff, 0x98210010, 0xb500000a, 0x80070000, + 0x001fb0cb, 0x83e4009a, 0x003f400e, 0x9421ffef, + 0xb5000004, 0x83e40096, 0x003f400e, 0x98211000, + 0x9421ffef, 0x003f600e, 0x80070100, 0x801efff0, + 0xb500ff6f, 0xb000008b, 0xb4000018, 0xb0000087, + 0xb400ffee, 0xb0000088, 0xb4000016, 0xb000008a, + 0xb4000016, 0xb000008c, 0xb4000017, 0xb0000089, + 0xb4000019, 0xb00000a0, 0xb400001b, 0xb00000a1, + 0xb4000048, 0xb00000a2, 0xb4000055, 0xb00000a3, + 0xb400004d, 0xb00000a4, 0xb4000057, 0xb00000a5, + 0xb400005b, 0xb00000a6, 0xb400005f, 0x803efff8, + 0xb500ffe1, 0x9421ffdf, 0xb500ffde, 0x80270100, + 0x803efff8, 0xb500ffdc, 0x803bffb0, 0x00000000, + 0x003fb040, 0xb500ffd8, 0x803bff80, 0x00000000, + 0x003f6001, 0xb500ffd4, 0x003f90ba, 0x803efff8, + 0xb500ffd1, 0x81674b18, 0x940a0007, 0x5803b800, + 0x116bb800, 0x005bb80b, 0x916b0004, 0x001bb80b, + 0x806500d4, 0x1463b800, 0x1863b802, 0x806600d4, + 0x80130001, 0x98003d21, 0x800600a1, 0x801e4b00, + 0x80074000, 0x801e4b04, 0x8013001f, 0x98405000, + 0x805effe0, 0x005fb006, 0x805effe8, 0x805effec, + 0x9042a000, 0x805effe4, 0x9040fa00, 0x805effd0, + 0x805effdc, 0x805effd8, 0x9040fe00, 0x805effd4, + 0x80070001, 0x001f2013, 0x80070000, 0x001f2324, + 0x001f600f, 0x001fb0cb, 0x001fb010, 0x80073cb0, + 0x001fb008, 0x800744a0, 0x001fb009, 0x98214000, + 0xb500ffa4, 0x80270000, 0x8047fef0, 0x003eb802, + 0x90420004, 0x003eb802, 0x90420004, 0x003eb802, + 0x90420004, 0x003eb802, 0x81df0000, 0x00000000, + 0x00000000, 0x83640475, 0x81df0004, 0xb500ff96, + 0x81df0000, 0x00000000, 0x00000000, 0x8364041f, + 0x81df0004, 0xb500ff90, 0x81df0000, 0x00000000, + 0x00000000, 0x836403da, 0x81df0004, 0xb500ff8a, + 0x81df0000, 0x00000000, 0x00000000, 0x83440339, + 0x81df0004, 0xb500ff84, 0x81df0000, 0x00000000, + 0x00000000, 0x8344031e, 0x81df0004, 0xb500ff7e, + 0x80070000, 0x80470000, 0x81df0000, 0x00000000, + 0x00000000, 0xb6002003, 0xb6003002, 0x001eb802, + 0x90420004, 0x80171000, 0x8057ffff, 0xb6002002, + 0xb6001801, 0x001fa020, 0x81df0004, 0x00ffb81f, + 0x83a70000, 0x8057ffff, 0x80770000, 0x8073007a, + 0x9863e7d2, 0x0207b803, 0x81df0000, 0x00000000, + 0x00000000, 0x80171000, 0xb6008007, 0x003fc0c0, + 0x005fc740, 0x40c1b810, 0x4102b810, 0x001fe0c6, + 0x001fe0c8, 0x4210b803, 0x81df0004, 0x80270000, + 0x003f2013, 0x8007001f, 0x94000003, 0x5810b800, + 0x83671e34, 0x1b7bb800, 0x003f9009, 0x1821b800, + 0x00ffb801, 0x003f0013, 0xb0010001, 0xb420fff3, + 0x93bd0001, 0xb01d0004, 0xb480ffe3, 0x00ffb81f, + 0x003f03f9, 0x009f0324, 0x84840001, 0xb0010000, + 0xb4000011, 0x815b4b0c, 0x81070000, 0x81270be8, + 0xb00a0000, 0xb4000002, 0x81070c00, 0x812717e8, + 0x802500a5, 0x806500a5, 0x3001b803, 0xb420fffc, + 0x9421ffff, 0x3001b808, 0xb480000b, 0x3001b809, + 0xb4a00059, 0xb5000008, 0xb0040000, 0xb4200003, + 0x802717ff, 0x81470000, 0xb5000003, 0x80270001, + 0x003f23f9, 0x81470c00, 0xb0040000, 0xb4200006, + 0x039f4193, 0x5b81b81c, 0x003f90cb, 0x1021b81c, + 0x003fb0cb, 0x83840237, 0x829bff80, 0x801300e0, + 0x1434b800, 0x5c35b801, 0x8013001f, 0x1454b800, + 0x5c50b802, 0x8073007f, 0x9863ffff, 0xb002000f, + 0xb4800001, 0x90210001, 0x84210004, 0xb0010000, + 0xb4a00001, 0x6861b803, 0x005f9040, 0x4082b803, + 0x80af001f, 0x808f0000, 0x806f0000, 0x8007ffff, + 0x8033ffff, 0x80171000, 0x81df0000, 0x00000000, + 0x00000000, 0xb600180a, 0xb6002009, 0x58708000, + 0x6068b803, 0x40c4b803, 0x00000000, 0x00c8b806, + 0x00000000, 0x00000000, 0x00000000, 0x5807a026, + 0x81df0004, 0x80670400, 0x5d22b80a, 0x81df0000, + 0x00000000, 0x00000000, 0xb600180a, 0x00cfb803, + 0x013fb0bc, 0x5922b809, 0x01afb809, 0x013f90bc, + 0x0047b86f, 0xb0020001, 0xb4c0fffd, 0x90630020, + 0x91290020, 0x81df0004, 0x808f0000, 0x801b4b14, + 0x80270001, 0xb0000001, 0xb4000002, 0x802600a0, + 0x803e4b14, 0x81270c00, 0xb00a0000, 0xb4000001, + 0x81270000, 0x813e4b0c, 0x80270001, 0x003f2013, + 0x80050086, 0x001fb044, 0x00ffb81b, 0x00000000, + 0x029fb00a, 0x02bfb00b, 0x02dfb00c, 0x02ffb00d, + 0x031fb00e, 0x033fb00f, 0x033f400f, 0x0287b86f, + 0x029fb005, 0x8285009c, 0x96b48000, 0xb0158000, + 0xb400018d, 0x96b40100, 0xb0150100, 0xb40001a9, + 0x96b40400, 0xb0150400, 0xb40001b0, 0x96b40001, + 0xb0150001, 0xb400000c, 0x96b40008, 0xb0150008, + 0xb4000196, 0x96b44000, 0xb0154000, 0xb40001af, + 0x96b40002, 0xb0150002, 0xb400015e, 0x00000000, + 0x00000000, 0xb50001c1, 0x02bf9017, 0x92b50001, + 0x02bfb017, 0x82850082, 0x83050081, 0x82a5009a, + 0x96b50001, 0xb0150001, 0xb4200014, 0x82a70000, + 0x02bfb017, 0x96b41840, 0xb0150800, 0xb420000c, + 0x96b40008, 0x5aa9b815, 0x96d46000, 0x5ec3b816, + 0x82f3000f, 0x9af7c00f, 0x1718b817, 0x1ab5b818, + 0x1ab5b816, 0x9ab50340, 0x82a60081, 0xb500013d, + 0x9b180180, 0x83060081, 0xb500013a, 0x82a5009a, + 0x96b50002, 0xb0150002, 0xb420001b, 0x82a70000, + 0x02bfb017, 0x96b41800, 0xb0151800, 0xb4000013, + 0x96b40040, 0xb0150040, 0xb4200004, 0xa3180c00, + 0x9b180340, 0x83060081, 0xb500012a, 0x96b40008, + 0x5aa9b815, 0x96d46000, 0x5ec3b816, 0x82f3000f, + 0x9af7c00f, 0x1718b817, 0x1ab5b818, 0x1ab5b816, + 0x9ab50340, 0x82a60081, 0xb500011e, 0x9b180180, + 0x83060081, 0xb500011b, 0x82a500c1, 0x96b5000f, + 0xb015000b, 0xb420000e, 0x96b40020, 0xb0150020, + 0xb400000b, 0x96b40200, 0xb0150200, 0xb4000008, + 0x82c50086, 0x82e50094, 0x3016b817, 0xb4400004, + 0x06f7b816, 0xb017ff00, 0xb4400001, 0xb5000109, + 0x96b46000, 0xb0156000, 0xb4000011, 0x96b41820, + 0xb0150820, 0xb4200004, 0x9b391000, 0x82a5009a, + 0x96b5feff, 0x82a6009a, 0x96b40040, 0xb0150040, + 0xb4200001, 0x9739efff, 0x96b91000, 0xb0151000, + 0xb4200003, 0x82a5009a, 0x9ab50100, 0x82a6009a, + 0x96b40040, 0xb0150040, 0xb4200019, 0x96b41800, + 0xb0151800, 0xb4200006, 0x96b98000, 0xb0158000, + 0xb4200003, 0x9b180180, 0x83060081, 0xb50000e9, + 0x96d80c00, 0x82b300ff, 0x9ab5f3ff, 0x1718b815, + 0xb0160c00, 0xb4000007, 0x82e50098, 0x96f70400, + 0xb0170400, 0xb4200002, 0x82c70c00, 0xb5000001, + 0xa2d60c00, 0x1b18b816, 0x9b180340, 0xb50000cf, + 0x96b40220, 0xb0150000, 0xb4e00033, 0x82a5009d, + 0x82f3ffff, 0x16b5b817, 0x82f3000e, 0x3015b817, + 0xb420002d, 0x96f98000, 0xb0178000, 0xb400002a, + 0x82a70000, 0x02bfb017, 0x82c50081, 0x9ab60020, + 0x82a60081, 0x82a50086, 0x92b50bb8, 0x82a60094, + 0x82c60081, 0x82c5009d, 0x96d6ffff, 0x82b30032, + 0x9ab58001, 0x82e500c1, 0x96f7000f, 0xb017000b, + 0xb4000002, 0x82b30022, 0x9ab58001, 0x1ab5b816, + 0x82c5009a, 0x96d60020, 0xb0160020, 0xb4200002, + 0x82b30032, 0x9ab58001, 0x82a6009d, 0x02ff9017, + 0x00000000, 0xb0170040, 0xb480000b, 0x96f41c00, + 0xb0171c00, 0xb4200008, 0x82e50086, 0x82c50094, + 0x92d63000, 0x3016b817, 0xb4400003, 0x9b180180, + 0x83060081, 0xb50000a3, 0x5eb5b814, 0x96b500f0, + 0x96f46000, 0x5eedb817, 0x1ab5b817, 0xb0170003, + 0xb4000004, 0x96b500ef, 0x96f70001, 0x5ae4b817, + 0x1ab5b817, 0x96d41800, 0xb0161800, 0xb400000a, + 0x96f900ff, 0x96b500ff, 0x9739ff00, 0x1b39b815, + 0x02a7b817, 0x96b500f3, 0x96d40008, 0x5ec1b816, + 0x1ab5b816, 0xb500000c, 0x96f98000, 0xb0178000, + 0xb4200007, 0x5efeb814, 0x96f70001, 0xb0170001, + 0xb4000003, 0x9b180180, 0x83060081, 0xb5000081, + 0x96b500f3, 0x9ab50008, 0x9739fff3, 0x96d40020, + 0xb0160020, 0xb4200017, 0x9b398000, 0x82c70000, + 0x02dfb017, 0x96d40010, 0x5ac8b816, 0x82f300ff, + 0x9af7cfff, 0x1718b817, 0x1b18b816, 0x9b180340, + 0x82c5009d, 0x96d6ffff, 0x82f3000e, 0x9af78001, + 0x1af7b816, 0x82c5009a, 0x96d60020, 0xb0160020, + 0xb4200002, 0x82f30032, 0x9af78001, 0x82e6009d, + 0xb500005a, 0x97397fff, 0x96b500ff, 0x5aaab815, + 0x82f300fc, 0x9af703ff, 0x1718b817, 0x1b18b815, + 0x9b180340, 0x82c5009a, 0x96d60010, 0xb0160010, + 0xb4200024, 0x82c70000, 0x02dfb017, 0x82c50086, + 0x92d60bb8, 0x82c60086, 0x82c50094, 0x5eefb818, + 0x96f70003, 0xb0170003, 0xb4200002, 0x82e70bb8, + 0xb5000001, 0x82e70bb8, 0x12d6b817, 0x82e50081, + 0x9af70020, 0x82e60081, 0x82c60094, 0xa2f70020, + 0x82e60081, 0x82f30001, 0x16f7b818, 0x5ef0b817, + 0xb0170001, 0xb4000004, 0x96f84000, 0x5ee4b817, + 0x9718f3ff, 0x1b18b817, 0x82f3000a, 0x9af78000, + 0x82e6009d, 0x83060081, 0x83070001, 0x8306009f, + 0xb500009e, 0x82c5009d, 0x82f3000e, 0x9af78001, + 0x3016b817, 0xb420000f, 0x82b30032, 0x9ab58001, + 0x82e500c1, 0x96f7000f, 0xb017000b, 0xb4000002, + 0x82b30022, 0x9ab58001, 0x82c5009a, 0x96d60020, + 0xb0160020, 0xb4200002, 0x82b30032, 0x9ab58001, + 0x82a6009d, 0x82c5009a, 0x96d60080, 0xb0160080, + 0xb4000011, 0x02df9017, 0x00000000, 0xb0160010, + 0xb480000d, 0x82c500c1, 0x96d6000f, 0xb016000b, + 0xb4000009, 0x82c50087, 0x96d60080, 0x5ac7b816, + 0x96f84000, 0x3017b816, 0xb4200003, 0x033f400f, + 0x9b394000, 0xb500000b, 0x9739bfff, 0x82e50061, + 0x96f70008, 0xb0170008, 0xb4000005, 0x5eefb818, + 0x96f70003, 0xb0170003, 0xb4000001, 0x9718ffff, + 0x83060081, 0x83070001, 0x8306009f, 0x00000000, + 0xb5000066, 0x82850083, 0x96b400ff, 0xb015003c, + 0xb4200015, 0x96b92000, 0xb0152000, 0xb4000002, + 0x9b392000, 0xb5000010, 0x9739d3ff, 0x82870000, + 0x82860087, 0x82870008, 0x82860083, 0x8287001f, + 0x828600c9, 0x829bff78, 0x00000000, 0x828600cb, + 0x8285009d, 0x82b3ffff, 0x9ab5fffd, 0x1694b815, + 0x8286009d, 0xb5000000, 0x83070002, 0x8306009f, + 0x00000000, 0xb5000049, 0x96b90800, 0xb0150800, + 0xb4200009, 0x9739f7ff, 0x82a703fd, 0x82a600cb, + 0x82a7003c, 0x82a60083, 0x8285009d, 0x9a940002, + 0x8286009d, 0xb5000004, 0x82850087, 0x5a82b814, + 0xa2940200, 0x82860087, 0xb5000000, 0x83078000, + 0x8306009f, 0x00000000, 0xb5000034, 0x82850086, + 0x82a50094, 0x3015b814, 0xb4800002, 0x86b50bb8, + 0x82a60086, 0x83070008, 0x8306009f, 0x00000000, + 0xb500002a, 0x83050081, 0x82f3001c, 0x9af703ff, + 0x1718b817, 0x9b180140, 0x83060081, 0x83070100, + 0x8306009f, 0x00000000, 0xb5000020, 0x83070000, + 0x83050081, 0x9b180180, 0x83060081, 0x83070400, + 0x8306009f, 0x00000000, 0xb5000018, 0x82870000, + 0x82850082, 0x5eb7b814, 0x96b500fc, 0x96d40006, + 0x5ec1b816, 0x1ab5b816, 0x5aacb815, 0x83050081, + 0x82d3001c, 0x9ad600ff, 0x1718b816, 0x1b18b815, + 0x9b180e00, 0x83060081, 0x83074000, 0x8306009f, + 0x8305009d, 0x82d300ff, 0x9ad6bfff, 0x1718b816, + 0x8306009d, 0x00000000, 0xb5000000, 0x029f9005, + 0x01ffb814, 0x033f600f, 0x029f900a, 0x02bf900b, + 0x02df900c, 0x02ff900d, 0x031f900e, 0x033f900f, + 0x00ffb81e, 0x02ff9010, 0x92f70b43, 0x02ffb010, + 0x02ff90cb, 0x82bbffdc, 0x829bffd8, 0x93150004, + 0x3014b815, 0xb4000010, 0x02dbb818, 0x029bb815, + 0x3017b816, 0xb480000c, 0x5a81b814, 0x029fb010, + 0x82860095, 0x8293001f, 0x9294fe00, 0x92b50008, + 0x3015b814, 0xb4800002, 0x82b3001f, 0x92b5fa00, + 0x82beffdc, 0xb500ffeb, 0x029f9010, 0x83250094, + 0x06d4b819, 0x02d6b816, 0xb016ffff, 0xb4a0000a, + 0x8293000e, 0x9a948001, 0x82c5009d, 0x96d6ffff, + 0x1a94b816, 0x82c5009a, 0x96d60010, 0xb0160010, + 0xb4000001, 0x8286009d, 0x00ffb81c, 0x80070000, + 0x001fb0bf, 0x001f2329, 0x003fb800, 0x001f9006, + 0x5803b800, 0x80338000, 0x1800b801, 0x003fb800, + 0x005f4193, 0x5c41b802, 0x80350000, 0x00000000, + 0x0027b860, 0x80150010, 0x5810b800, 0x80750010, + 0x1863b800, 0x8087ffff, 0x80a7770b, 0x80c70000, + 0x1403b804, 0x3000b805, 0xb4000008, 0x5888b804, + 0x58a8b805, 0x90c60001, 0xb0060003, 0xb4a0fff8, + 0x84420001, 0xb4e0ffee, 0xb5000020, 0xb0060003, + 0xb4200007, 0x80150010, 0x5810b800, 0x81150010, + 0x950800ff, 0xb0080077, 0xb4000001, 0xb500fff4, + 0x001f400e, 0x98000010, 0x98004000, 0x9400fffe, + 0x001f600e, 0x80e70020, 0xb0060000, 0xb400000e, + 0x58e3b806, 0x90210020, 0x81070000, 0x5938b803, + 0x1908b809, 0x9523ff00, 0x5928b809, 0x1908b809, + 0x5d28b803, 0x9529ff00, 0x1908b809, 0x5d38b803, + 0x1908b809, 0x011fb0bf, 0x00ff2329, 0x80137fff, + 0x9800ffe7, 0x1421b800, 0x5c23b801, 0x001f9006, + 0x0441b800, 0x3001b800, 0xb4600002, 0x0440b801, + 0xa4422000, 0x007f90cb, 0x1063b802, 0x007fb0cb, + 0x003fb006, 0x803effec, 0x80470001, 0x005f2013, + 0xb500fbe3, 0x001f400e, 0x9400000f, 0xb0000000, + 0xb4200001, 0x00ffb81f, 0xb0000001, 0xb4000005, + 0xb0000003, 0xb4000003, 0xb0000002, 0xb4000001, + 0x00ffb81f, 0x80070001, 0x001f2013, 0xb500fbd4, + 0x001f9012, 0x001fb100, 0x001f004c, 0x001f2404, + 0x801bfef0, 0x8058fef4, 0x003f9304, 0x007f0c14, + 0x2000b801, 0x2042b803, 0x001fb104, 0x005f2414, + 0x82e70001, 0x83640048, 0x029fb014, 0x829efef0, + 0x8286000f, 0x02bf2054, 0x82bcfef4, 0x82a6000e, + 0x00ffb81a, 0x80e70001, 0x801336e3, 0x9800eb76, + 0x001fb100, 0x800700ab, 0x001f2404, 0x801bc3e8, + 0x8058c3ec, 0x83640024, 0x82e70000, 0x83640036, + 0x029fb300, 0x029fb100, 0x02bf2c04, 0x02bf2404, + 0x801bc000, 0x8058c004, 0x8364001b, 0x82e70000, + 0x8364002d, 0x001f9300, 0x3000b814, 0xb420000a, + 0x001f0c04, 0x3000b815, 0xb4200007, 0x829efef0, + 0x82bcfef4, 0x029fb012, 0x02bf204c, 0x82870001, + 0x829cfef5, 0x00ffb81a, 0xb0070000, 0xb4000007, + 0x80e70000, 0x801399fa, 0x9800c92e, 0x001fb100, + 0x800700af, 0x001f2404, 0xb500ffdc, 0x82870000, + 0x829cfef5, 0x00ffb81a, 0x80c700ff, 0x003f9304, + 0x007f0c14, 0x14a0b806, 0x2063b805, 0x007f2414, + 0x2021b802, 0x58c8b806, 0x14a0b806, 0x58b0b805, + 0x2021b805, 0x58c8b806, 0x14a0b806, 0x2021b805, + 0x58c8b806, 0x14a0b806, 0x5cb0b805, 0x2021b805, + 0x003fb104, 0x00ffb81b, 0x82c70000, 0x83070400, + 0x83270005, 0x8197040c, 0x81d7ffff, 0x8384012a, + 0x83840001, 0x00ffb81b, 0x808f0000, 0x806f001f, + 0x80af001f, 0x80270140, 0x81e74e58, 0x5de2b80f, + 0xb600020a, 0x00cfb801, 0x01ffb0bc, 0x59e2b80f, + 0x01cfb80f, 0x01ff90bc, 0x0047b86f, 0xb0020001, + 0xb4c0fffd, 0x91ef0020, 0x90210020, 0x80270180, + 0x81e74d50, 0x5de2b80f, 0xb600020a, 0x00cfb801, + 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, 0x01ff90bc, + 0x0047b86f, 0xb0020001, 0xb4c0fffd, 0x91ef0020, + 0x90210020, 0x8057ffff, 0x80170430, 0x80070410, + 0x80270408, 0xb6000509, 0x005ff000, 0x90420500, + 0x007ff001, 0x90630600, 0x009ff002, 0x00bff003, + 0x2004a025, 0x90000001, 0x90210001, 0x80070414, + 0x80d7ffff, 0x8097045c, 0x8017043c, 0xb6000404, + 0x005ff000, 0x007f87e0, 0x84000001, 0x2082a7e3, + 0x80970460, 0x80170440, 0x2082b803, 0x007f8000, + 0x2083a004, 0x80170430, 0x80970450, 0x80270408, + 0xb6000508, 0x005f8024, 0x90420500, 0x007ff001, + 0x90630600, 0x009ff002, 0x00bff003, 0x2004a025, + 0x90210001, 0x80170440, 0x00000000, 0x02bf87e0, + 0x80970460, 0x82870000, 0xb6000404, 0x005f87e4, + 0x5a88b814, 0x204287e0, 0x1a94b802, 0x00ffb81c, + 0x001f0a49, 0x001f2709, 0x001f0a41, 0x001f2708, + 0x001f0a46, 0x001f2707, 0x001f0a48, 0x001f2706, + 0x001f0a42, 0x001f2705, 0x001f0a47, 0x001f2704, + 0x001f0a45, 0x001f2703, 0x001f0a43, 0x001f2702, + 0x001f0a40, 0x001f2701, 0x001f0a44, 0x001f2700, + 0x001f0c25, 0xa020000c, 0x94400001, 0x94600002, + 0x94810004, 0x94a10008, 0x94c00010, 0x5943b802, + 0x5861b803, 0x5882b804, 0x5ca2b805, 0x5cc4b806, + 0x194ab803, 0x194ab804, 0x194ab805, 0x194ab806, + 0x015f2738, 0x801b4e50, 0x003f91c1, 0x5c28b801, + 0x005f91c2, 0x5858b802, 0x1821b802, 0x2000b801, + 0x001fb1c4, 0x80184e54, 0x003f0709, 0x2000b801, + 0x001f2714, 0x82c70001, 0x82e70001, 0x83070710, + 0x8327001e, 0x81970735, 0x8384009f, 0x02df0738, + 0x82170a30, 0x838400f1, 0x819efef0, 0x817cfef4, + 0x019fb304, 0x017f2c14, 0x00ffb81b, 0x820f001f, + 0x8018fef8, 0x8057ffff, 0x001f2709, 0x8018fef6, + 0x80d7ffff, 0x001f2708, 0x8018fefa, 0x8157ffff, + 0x001f2707, 0x8018fefd, 0x81d7ffff, 0x001f2706, + 0x8018fefb, 0x802f001f, 0x001f2705, 0x8018fefe, + 0x00000000, 0x001f2704, 0x8018fef9, 0x00000000, + 0x001f2703, 0x8018feff, 0x00000000, 0x001f2702, + 0x8018fef7, 0x00000000, 0x001f2701, 0x8018fefc, + 0x00000000, 0x001f2700, 0x001f0c25, 0xa0200011, + 0x94410001, 0x94600002, 0x94800004, 0x94a00008, + 0x94c10010, 0x5941b802, 0x5861b803, 0x5c82b804, + 0x58a1b805, 0x5cc1b806, 0x194ab803, 0x194ab804, + 0x194ab805, 0x194ab806, 0x015f2738, 0x801b4e50, + 0x003f91c1, 0x5c28b801, 0x005f91c2, 0x5858b802, + 0x1821b802, 0x2000b801, 0x001fb1c4, 0x80184e54, + 0x003f0709, 0x2000b801, 0x001f2714, 0x82c70001, + 0x82e70001, 0x83070710, 0x8327001e, 0x81970735, + 0x83840055, 0x02df0738, 0x82170a20, 0x838400a7, + 0x819efef0, 0x817cfef4, 0x5ac8b80c, 0x02ff0a44, + 0x1ad6b817, 0x02dfb291, 0x5ed8b80c, 0x5968b80b, + 0x1ad6b80b, 0x02df6524, 0x00ffb81b, 0x820f001f, + 0x8018fefe, 0x8057ffff, 0x001f2709, 0x8018fefa, + 0x80d7ffff, 0x001f2708, 0x8018fefc, 0x8157ffff, + 0x001f2707, 0x8018feff, 0x81d7ffff, 0x001f2706, + 0x8018fef8, 0x802f001f, 0x001f2705, 0x8018fefb, + 0x00000000, 0x001f2704, 0x8018fefd, 0x00000000, + 0x001f2703, 0x8018fef6, 0x00000000, 0x001f2702, + 0x8018fef9, 0x00000000, 0x001f2701, 0x8018fef7, + 0x00000000, 0x001f2700, 0x801b4e50, 0x003f91c1, + 0x5c28b801, 0x005f91c2, 0x5858b802, 0x1821b802, + 0x2000b801, 0x001fb1c4, 0x80184e54, 0x003f0709, + 0x2000b801, 0x001f2714, 0x82c70001, 0x82e70001, + 0x83070710, 0x8327001e, 0x81970735, 0x83840016, + 0x83270000, 0x831bfef0, 0x82f8fef4, 0x02c7b819, + 0x82170a28, 0x83840065, 0x300cb818, 0xb4200002, + 0x300bb817, 0xb4000006, 0x93390001, 0xb0190020, + 0xb480fff6, 0x83270000, 0x833cfef5, 0x00ffb81b, + 0x019fb290, 0x017f2a44, 0x033f2c25, 0x83270001, + 0x833cfef5, 0x00ffb81b, 0x0007b818, 0x90000003, + 0x00000000, 0x015ff000, 0x90000001, 0x5949b80a, + 0x013ff000, 0x194ab809, 0x84000002, 0x994a0100, + 0x017ff000, 0x958b00f8, 0x5981b80c, 0x956b0007, + 0x198cb80b, 0x84000002, 0x998c0008, 0x017ff000, + 0x90000001, 0x5971b80b, 0x198cb80b, 0x017ff000, + 0x5969b80b, 0x198cb80b, 0x81a70000, 0x94d90003, + 0x82a70000, 0xb6260019, 0xb6000818, 0x5df0b80a, + 0x5e02b80a, 0x21efb810, 0x95ef0001, 0x5941b80a, + 0x194ab80f, 0x21efb816, 0x5e18b80c, 0x5e35b80c, + 0x5e54b80c, 0x5e6cb80c, 0x2210b811, 0x2252b813, + 0x2210b812, 0x96100001, 0x5981b80c, 0x198cb810, + 0x2210b817, 0x10afb810, 0x10a5b80d, 0x5da1b805, + 0x94a50001, 0x5aa1b815, 0x1ab5b805, 0x019fa7f5, + 0x5cc2b819, 0xb626001c, 0x82870000, 0xb6000419, + 0xb6000818, 0x5df0b80a, 0x5e02b80a, 0x21efb810, + 0x95ef0001, 0x5941b80a, 0x194ab80f, 0x21efb816, + 0x5e18b80c, 0x5e35b80c, 0x5e54b80c, 0x5e6cb80c, + 0x2210b811, 0x2252b813, 0x2210b812, 0x96100001, + 0x5981b80c, 0x198cb810, 0x2210b817, 0x10afb810, + 0x10a5b80d, 0x5da1b805, 0x94a50001, 0x5a81b814, + 0x1a94b805, 0x019fa7f4, 0x00ffb81c, 0x8257ffff, + 0x808f0000, 0x806f001f, 0x80af001f, 0x80270200, + 0x81e74b30, 0x5de2b80f, 0xb600020a, 0x00cfb801, + 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, 0x01ff90bc, + 0x0047b86f, 0xb0020001, 0xb4c0fffd, 0x91ef0020, + 0x90210020, 0x80270240, 0x81e74c30, 0x5de2b80f, + 0xb600020a, 0x00cfb801, 0x01ffb0bc, 0x59e2b80f, + 0x01cfb80f, 0x01ff90bc, 0x0047b86f, 0xb0020001, + 0xb4c0fffd, 0x91ef0020, 0x90210020, 0x80270180, + 0x81e74d50, 0x5de2b80f, 0xb600020a, 0x00cfb801, + 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, 0x01ff90bc, + 0x0047b86f, 0xb0020001, 0xb4c0fffd, 0x91ef0020, + 0x90210020, 0x806f0007, 0x80af0007, 0x80270280, + 0x81e74d30, 0x5de2b80f, 0x00cfb801, 0x01ffb0bc, + 0x59e2b80f, 0x01cfb80f, 0x01ff90bc, 0x0047b86f, + 0xb0020001, 0xb4c0fffd, 0x91ef0020, 0x90210020, + 0x80170760, 0x001f0700, 0x001fa020, 0x001f0701, + 0x001fa020, 0x001f0702, 0x001fa020, 0x001f0703, + 0x001fa020, 0x001f0704, 0x001fa000, 0x80970750, + 0x81170770, 0x82a70735, 0x83a40060, 0x001f87e4, + 0xb6000405, 0x86b50001, 0x83a4005c, 0x001f8004, + 0x003f87e8, 0x2080a7e1, 0x80970770, 0x80170750, + 0x81170750, 0x81970740, 0x82a70730, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a40050, 0x001f87e4, + 0xb6000405, 0x86b50001, 0x83a4004c, 0x001f8004, + 0x003f87e8, 0x2080a7e1, 0x80970750, 0x80170770, + 0x81170770, 0x81970760, 0x82a7072b, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a40040, 0x83a4004e, + 0xb6000407, 0x86b50001, 0x83a4003c, 0x001f8004, + 0x003f87e8, 0x2080a001, 0x83a40047, 0x00000000, + 0x80970770, 0x80170750, 0x81170750, 0x81970740, + 0x82a70726, 0x001f800c, 0x003f8008, 0x2100a001, + 0x83a4002e, 0x83a4003c, 0xb6000407, 0x86b50001, + 0x83a4002a, 0x001f8004, 0x003f87e8, 0x2080a001, + 0x83a40035, 0x00000000, 0x80970750, 0x80170770, + 0x81170770, 0x81970760, 0x82a70721, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a4001c, 0x001f87e4, + 0xb6000405, 0x86b50001, 0x83a40018, 0x001f8004, + 0x003f87e8, 0x2080a7e1, 0x80970770, 0x80170750, + 0x81170750, 0x81970740, 0x82a7071c, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a4000c, 0x017f87e4, + 0x81870000, 0xb6000406, 0x86b50001, 0x83a40007, + 0x001f87e4, 0x200087e8, 0x5988b80c, 0x198cb800, + 0x021fa02c, 0x021fa00b, 0x00ffb81c, 0x005ff015, + 0x90420600, 0x003f87e0, 0x001ff002, 0x2060b801, + 0x90630800, 0x90960a00, 0x001ff003, 0x003ff004, + 0x20a0b801, 0x90a50900, 0x00000000, 0x001ff005, + 0x009fa000, 0x00ffb81d, 0x001f8004, 0x5c21b800, + 0x5847b800, 0x1821b802, 0x942100ff, 0x2080a7e1, + 0x00ffb81d, 0x00000000, 0x00000000, 0x00000000, + 0x829bff80, 0x80af000f, 0x808f0000, 0x806f0000, + 0x82bbffec, 0x82fbffe4, 0x00000000, 0x82beffb8, + 0x95540700, 0x5d48b80a, 0x914a0001, 0x0227b80a, + 0x94343000, 0x5c2cb801, 0xb0010000, 0xb4000001, + 0x5a21b811, 0x9574c000, 0x5d6eb80b, 0x918b4b08, + 0x01b8b80c, 0x96d5ffff, 0x5ec2b816, 0x96f7ffff, + 0x5ee2b817, 0x8057ffff, 0x80d7ffff, 0x8157ffff, + 0x81d7ffff, 0x81f3ff00, 0x99efff00, 0x821300ff, + 0x9a1000ff, 0x81971000, 0x82670000, 0x82470000, + 0x80270280, 0x81df0000, 0x00000000, 0x00000000, + 0xb62d000d, 0x3016b817, 0xb4800001, 0x86d62800, + 0x00cfb801, 0x02dfb0bc, 0x5ac2b816, 0x01cfb816, + 0x02df90bc, 0x0067b86f, 0xb0030001, 0xb4c0fffd, + 0x92d60010, 0x90210010, 0x81df0004, 0x80170a00, + 0x81df0000, 0x00000000, 0x00000000, 0xb62d0006, + 0xb6001005, 0x146f8000, 0x14908000, 0x5c68b803, + 0x5888b804, 0x1803a024, 0x81df0004, 0x80170a00, + 0x80970d00, 0xb00b0000, 0xb4000004, 0xb00b0001, + 0xb400000a, 0xb00b0002, 0xb4000027, 0x81df0000, + 0x00000000, 0x00000000, 0xb6004002, 0x007f8020, + 0x009fa023, 0x81df0004, 0xb5000029, 0x80d3ffff, + 0x81df0000, 0x00000000, 0x00000000, 0xb6001018, + 0x5c648000, 0x9463ffff, 0x5c888020, 0x58b88000, + 0x1884b805, 0x1484b806, 0x1883a024, 0x5c6c8020, + 0x9463ffff, 0x58908000, 0x1883a024, 0x5c748020, + 0x588c8000, 0x1863b804, 0x9463ffff, 0x58888000, + 0x1484b806, 0x1883a024, 0x5c7c8020, 0x58848000, + 0x1863b804, 0x9463ffff, 0x14868020, 0x1883a024, + 0x81df0004, 0xb500000a, 0x80d3ffff, 0x81df0000, + 0x00000000, 0x00000000, 0xb6002004, 0x007f8020, + 0x009fa023, 0x007f8040, 0x009fa023, 0x81df0004, + 0x00000000, 0x81170d00, 0x80070000, 0x94343000, + 0x5c2cb801, 0xb0010001, 0xb4000099, 0xb00a0001, + 0xb400000e, 0xb00a0002, 0xb4000022, 0xb00a0003, + 0xb400002f, 0xb00a0004, 0xb400005d, 0xb00a0005, + 0xb4000066, 0xb00a0006, 0xb400008a, 0xb00a0007, + 0xb4000088, 0xb00a0008, 0xb4000086, 0x81df0000, + 0x00000000, 0x00000000, 0xb6004010, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x019fa020, 0x019fa020, + 0x019fa020, 0x019fa020, 0x019fa020, 0x5c708028, + 0x9463ffff, 0x019fa023, 0x019fa020, 0x019fa020, + 0x019fa020, 0x019fa020, 0x019fa020, 0x81df0004, + 0xb5000070, 0x81df0000, 0x00000000, 0x00000000, + 0x8027ffff, 0xb6004008, 0x14618008, 0x019fa023, + 0x019fa020, 0x019fa020, 0x5c708028, 0x019fa023, + 0x019fa020, 0x019fa020, 0x81df0004, 0xb5000061, + 0xb0130000, 0xb4000004, 0xb0130001, 0xb4000009, + 0xb0130002, 0xb400001a, 0x83a40102, 0x80170f00, + 0x007f8028, 0x001fa023, 0x007f8028, 0x001fa023, + 0xb5000054, 0x80170f00, 0x00000000, 0x007f8020, + 0x019fa023, 0x007f8000, 0x9463ffff, 0x019fa023, + 0x019fa020, 0x5c708020, 0x58908008, 0x1983a024, + 0x5c708028, 0x019fa023, 0x019fa020, 0x83a400ed, + 0x80170f00, 0x007f8028, 0x001fa023, 0xb5000041, + 0x80170f00, 0x00000000, 0x007f8020, 0x019fa023, + 0x007f8008, 0x9463ffff, 0x019fa023, 0x019fa020, + 0x5c708028, 0x58908008, 0x1983a024, 0x5c708028, + 0x019fa023, 0x019fa020, 0x83a400da, 0xb5000031, + 0x81df0000, 0x00000000, 0x00000000, 0xb6002005, + 0x007f8008, 0x019fa023, 0x007f8008, 0x019fa023, + 0x019fa020, 0x81df0004, 0xb5000026, 0xb0130000, + 0xb4000008, 0xb0130001, 0xb4000012, 0xb0130002, + 0xb400001f, 0xb0130003, 0xb400001d, 0xb0130004, + 0xb400001b, 0x83a400d5, 0x007f8028, 0x019fa023, + 0x007f8028, 0x019fa023, 0x007f8008, 0x9463ffff, + 0x019fa023, 0x80170f00, 0x007f8028, 0x001fa023, + 0xb5000010, 0x80170f00, 0x00000000, 0x5c708020, + 0x58908008, 0x1983a024, 0x5c708028, 0x58908008, + 0x1983a024, 0x5c708028, 0x019fa023, 0x83a400bf, + 0x80170f00, 0x007f8028, 0x001fa023, 0xb5000001, + 0xb5000000, 0x00000000, 0x00000000, 0xb500008e, + 0xb00a0001, 0xb400000e, 0xb00a0002, 0xb400001a, + 0xb00a0003, 0xb4000027, 0xb00a0004, 0xb4000055, + 0xb00a0005, 0xb400005e, 0xb00a0006, 0xb4000082, + 0xb00a0007, 0xb4000080, 0xb00a0008, 0xb400007e, + 0x81df0000, 0x00000000, 0x00000000, 0xb6004008, + 0x007f8028, 0x9463ffff, 0x019fa023, 0x019fa020, + 0x019fa020, 0x019fa020, 0x019fa020, 0x019fa020, + 0x81df0004, 0xb5000070, 0x81df0000, 0x00000000, + 0x00000000, 0x8027ffff, 0xb6002008, 0x14618008, + 0x019fa023, 0x019fa020, 0x019fa020, 0x5c708048, + 0x019fa023, 0x019fa020, 0x019fa020, 0x81df0004, + 0xb5000061, 0xb0130000, 0xb4000004, 0xb0130001, + 0xb4000009, 0xb0130002, 0xb400001a, 0x83a40098, + 0x80170f00, 0x007f8028, 0x001fa023, 0x007f8028, + 0x001fa023, 0xb5000054, 0x80170f00, 0x00000000, + 0x007f8020, 0x019fa023, 0x007f8000, 0x9463ffff, + 0x019fa023, 0x019fa020, 0x5c708020, 0x58908008, + 0x1983a024, 0x5c708028, 0x019fa023, 0x019fa020, + 0x83a40083, 0x80170f00, 0x007f8028, 0x001fa023, + 0xb5000041, 0x80170f00, 0x00000000, 0x007f8020, + 0x019fa023, 0x007f8008, 0x9463ffff, 0x019fa023, + 0x019fa020, 0x5c708028, 0x58908008, 0x1983a024, + 0x5c708028, 0x019fa023, 0x019fa020, 0x83a40070, + 0xb5000031, 0x81df0000, 0x00000000, 0x00000000, + 0xb6002005, 0x007f8008, 0x019fa023, 0x007f8008, + 0x019fa023, 0x019fa020, 0x81df0004, 0xb5000026, + 0xb0130000, 0xb4000008, 0xb0130001, 0xb4000012, + 0xb0130002, 0xb400001f, 0xb0130003, 0xb400001d, + 0xb0130004, 0xb400001b, 0x83a4006b, 0x007f8028, + 0x019fa023, 0x007f8028, 0x019fa023, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x80170f00, 0x007f8028, + 0x001fa023, 0xb5000010, 0x80170f00, 0x00000000, + 0x5c708020, 0x58908008, 0x1983a024, 0x5c708028, + 0x58908008, 0x1983a024, 0x5c708028, 0x019fa023, + 0x83a40055, 0x80170f00, 0x007f8028, 0x001fa023, + 0xb5000001, 0xb5000000, 0x92730001, 0x92520001, + 0x3012b811, 0xb480fe76, 0x003f0324, 0x90210001, + 0xb0010006, 0xb4a00001, 0x80270001, 0x003f2324, + 0x2c8db811, 0x803bffe0, 0x805bffe4, 0x5886b804, + 0x1015b804, 0xad440003, 0x3000b802, 0xb4800001, + 0x8400a000, 0x801effec, 0x015f6193, 0x809e4b04, + 0x00ffb81f, 0x81df0000, 0x00000000, 0x00000000, + 0xb6002a0c, 0x007f8028, 0x019fa023, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x019fa020, 0x5c708028, + 0x58908008, 0x1983a024, 0x5c708028, 0x019fa023, + 0x019fa020, 0x81df0004, 0x00ffb81d, 0x81df0000, + 0x00000000, 0x00000000, 0xb600190f, 0x007f8028, + 0x019fa023, 0x007f8028, 0x019fa023, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x5c708028, 0x58908008, + 0x1983a024, 0x5c708028, 0x58908008, 0x1983a024, + 0x5c708028, 0x019fa023, 0x81df0004, 0x00ffb81d, + 0x81df0000, 0x00000000, 0x00000000, 0xb6002a0c, + 0x007f8028, 0x019fa023, 0x007f8008, 0x9463ffff, + 0x019fa023, 0x019fa020, 0x5c708028, 0x58908008, + 0x1983a024, 0x5c708028, 0x019fa023, 0x019fa020, + 0x81df0004, 0x00ffb81d, 0x81df0000, 0x00000000, + 0x00000000, 0xb600190f, 0x007f8028, 0x019fa023, + 0x007f8028, 0x019fa023, 0x007f8008, 0x9463ffff, + 0x019fa023, 0x5c708028, 0x58908008, 0x1983a024, + 0x5c708028, 0x58908008, 0x1983a024, 0x5c708028, + 0x019fa023, 0x81df0004, 0x00ffb81d, 0x00000000, + 0x829bff80, 0x80af001f, 0x808f0000, 0x806f0000, + 0x82bbffec, 0x82fbffe4, 0x00000000, 0x82beffb8, + 0x95540700, 0x5d48b80a, 0x914a0001, 0x0227b80a, + 0x94343000, 0x5c2cb801, 0xb0010000, 0xb4000001, + 0x5a21b811, 0x9574c000, 0x5d6eb80b, 0x918b4b08, + 0x01b8b80c, 0x96d5ffff, 0x5ec2b816, 0x96f7ffff, + 0x5ee2b817, 0x8057ffff, 0x80d7ffff, 0x8157ffff, + 0x81d7ffff, 0x81f3ff00, 0x99efff00, 0x821300ff, + 0x9a1000ff, 0x81971000, 0x82670000, 0x82470000, + 0x80270280, 0x81df0000, 0x00000000, 0x00000000, + 0xb62d000d, 0x3016b817, 0xb4800001, 0x86d62800, + 0x00cfb801, 0x02dfb0bc, 0x5ac2b816, 0x01cfb816, + 0x02df90bc, 0x0067b86f, 0xb0030001, 0xb4c0fffd, + 0x92d60020, 0x90210020, 0x81df0004, 0x80170a00, + 0x81df0000, 0x00000000, 0x00000000, 0xb62d0006, + 0xb6002005, 0x146f8000, 0x14908000, 0x5c68b803, + 0x5888b804, 0x1803a024, 0x81df0004, 0x80170a00, + 0x80970d00, 0xb00b0000, 0xb4000004, 0xb00b0001, + 0xb400000a, 0xb00b0002, 0xb4000027, 0x81df0000, + 0x00000000, 0x00000000, 0xb6008002, 0x007f8020, + 0x009fa023, 0x81df0004, 0xb5000029, 0x80d3ffff, + 0x81df0000, 0x00000000, 0x00000000, 0xb6002018, + 0x5c648000, 0x9463ffff, 0x5c888020, 0x58b88000, + 0x1884b805, 0x1484b806, 0x1883a024, 0x5c6c8020, + 0x9463ffff, 0x58908000, 0x1883a024, 0x5c748020, + 0x588c8000, 0x1863b804, 0x9463ffff, 0x58888000, + 0x1484b806, 0x1883a024, 0x5c7c8020, 0x58848000, + 0x1863b804, 0x9463ffff, 0x14868020, 0x1883a024, + 0x81df0004, 0xb500000a, 0x80d3ffff, 0x81df0000, + 0x00000000, 0x00000000, 0xb6004004, 0x007f8020, + 0x009fa023, 0x007f8040, 0x009fa023, 0x81df0004, + 0x00000000, 0x81170d00, 0x80070000, 0x94343000, + 0x5c2cb801, 0xb0010001, 0xb400008e, 0xb00a0001, + 0xb400000e, 0xb00a0002, 0xb400001c, 0xb00a0003, + 0xb4000024, 0xb00a0004, 0xb4000052, 0xb00a0005, + 0xb400005b, 0xb00a0006, 0xb400007f, 0xb00a0007, + 0xb400007d, 0xb00a0008, 0xb400007b, 0x81df0000, + 0x00000000, 0x00000000, 0xb600800a, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x019fa020, 0x019fa020, + 0x5c708028, 0x9463ffff, 0x019fa023, 0x019fa020, + 0x019fa020, 0x81df0004, 0xb500006b, 0x81df0000, + 0x00000000, 0x00000000, 0xb6008004, 0x007f8028, + 0x019fa023, 0x019fa020, 0x019fa020, 0x81df0004, + 0xb5000061, 0xb0130000, 0xb4000004, 0xb0130001, + 0xb4000009, 0xb0130002, 0xb400001a, 0x83a400fa, + 0x80170f00, 0x007f8028, 0x001fa023, 0x007f8028, + 0x001fa023, 0xb5000054, 0x80170f00, 0x00000000, + 0x007f8020, 0x019fa023, 0x007f8000, 0x9463ffff, + 0x019fa023, 0x019fa020, 0x5c708020, 0x58908008, + 0x1983a024, 0x5c708028, 0x019fa023, 0x019fa020, + 0x83a400e5, 0x80170f00, 0x007f8028, 0x001fa023, + 0xb5000041, 0x80170f00, 0x00000000, 0x007f8020, + 0x019fa023, 0x007f8008, 0x9463ffff, 0x019fa023, + 0x019fa020, 0x5c708028, 0x58908008, 0x1983a024, + 0x5c708028, 0x019fa023, 0x019fa020, 0x83a400d2, + 0xb5000031, 0x81df0000, 0x00000000, 0x00000000, + 0xb6004005, 0x007f8008, 0x019fa023, 0x007f8008, + 0x019fa023, 0x019fa020, 0x81df0004, 0xb5000026, + 0xb0130000, 0xb4000008, 0xb0130001, 0xb4000012, + 0xb0130002, 0xb400001f, 0xb0130003, 0xb400001d, + 0xb0130004, 0xb400001b, 0x83a400cd, 0x007f8028, + 0x019fa023, 0x007f8028, 0x019fa023, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x80170f00, 0x007f8028, + 0x001fa023, 0xb5000010, 0x80170f00, 0x00000000, + 0x5c708020, 0x58908008, 0x1983a024, 0x5c708028, + 0x58908008, 0x1983a024, 0x5c708028, 0x019fa023, + 0x83a400b7, 0x80170f00, 0x007f8028, 0x001fa023, + 0xb5000001, 0xb5000000, 0x00000000, 0x00000000, + 0xb5000086, 0xb00a0001, 0xb400000e, 0xb00a0002, + 0xb4000017, 0xb00a0003, 0xb400001f, 0xb00a0004, + 0xb400004d, 0xb00a0005, 0xb4000056, 0xb00a0006, + 0xb400007a, 0xb00a0007, 0xb4000078, 0xb00a0008, + 0xb4000076, 0x81df0000, 0x00000000, 0x00000000, + 0xb6008005, 0x007f8028, 0x9463ffff, 0x019fa023, + 0x019fa020, 0x019fa020, 0x81df0004, 0xb500006b, + 0x81df0000, 0x00000000, 0x00000000, 0xb6004004, + 0x007f8048, 0x019fa023, 0x019fa020, 0x019fa020, + 0x81df0004, 0xb5000061, 0xb0130000, 0xb4000004, + 0xb0130001, 0xb4000009, 0xb0130002, 0xb400001a, + 0x83a40098, 0x80170f00, 0x007f8028, 0x001fa023, + 0x007f8028, 0x001fa023, 0xb5000054, 0x80170f00, + 0x00000000, 0x007f8020, 0x019fa023, 0x007f8000, + 0x9463ffff, 0x019fa023, 0x019fa020, 0x5c708020, + 0x58908008, 0x1983a024, 0x5c708028, 0x019fa023, + 0x019fa020, 0x83a40083, 0x80170f00, 0x007f8028, + 0x001fa023, 0xb5000041, 0x80170f00, 0x00000000, + 0x007f8020, 0x019fa023, 0x007f8008, 0x9463ffff, + 0x019fa023, 0x019fa020, 0x5c708028, 0x58908008, + 0x1983a024, 0x5c708028, 0x019fa023, 0x019fa020, + 0x83a40070, 0xb5000031, 0x81df0000, 0x00000000, + 0x00000000, 0xb6004005, 0x007f8008, 0x019fa023, + 0x007f8008, 0x019fa023, 0x019fa020, 0x81df0004, + 0xb5000026, 0xb0130000, 0xb4000008, 0xb0130001, + 0xb4000012, 0xb0130002, 0xb400001f, 0xb0130003, + 0xb400001d, 0xb0130004, 0xb400001b, 0x83a4006b, + 0x007f8028, 0x019fa023, 0x007f8028, 0x019fa023, + 0x007f8008, 0x9463ffff, 0x019fa023, 0x80170f00, + 0x007f8028, 0x001fa023, 0xb5000010, 0x80170f00, + 0x00000000, 0x5c708020, 0x58908008, 0x1983a024, + 0x5c708028, 0x58908008, 0x1983a024, 0x5c708028, + 0x019fa023, 0x83a40055, 0x80170f00, 0x007f8028, + 0x001fa023, 0xb5000001, 0xb5000000, 0x92730001, + 0x92520001, 0x3012b811, 0xb480fe89, 0x003f0324, + 0x90210001, 0xb0010006, 0xb4a00001, 0x80270001, + 0x003f2324, 0x2c8db811, 0x803bffe0, 0x805bffe4, + 0x5887b804, 0x1015b804, 0xad440003, 0x3000b802, + 0xb4800001, 0x8400a000, 0x801effec, 0x015f6193, + 0x809e4b04, 0x00ffb81f, 0x81df0000, 0x00000000, + 0x00000000, 0xb6002a0c, 0x007f8028, 0x019fa023, + 0x007f8008, 0x9463ffff, 0x019fa023, 0x019fa020, + 0x5c708028, 0x58908008, 0x1983a024, 0x5c708028, + 0x019fa023, 0x019fa020, 0x81df0004, 0x00ffb81d, + 0x81df0000, 0x00000000, 0x00000000, 0xb600190f, + 0x007f8028, 0x019fa023, 0x007f8028, 0x019fa023, + 0x007f8008, 0x9463ffff, 0x019fa023, 0x5c708028, + 0x58908008, 0x1983a024, 0x5c708028, 0x58908008, + 0x1983a024, 0x5c708028, 0x019fa023, 0x81df0004, + 0x00ffb81d, 0x81df0000, 0x00000000, 0x00000000, + 0xb6002a0c, 0x007f8028, 0x019fa023, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x019fa020, 0x5c708028, + 0x58908008, 0x1983a024, 0x5c708028, 0x019fa023, + 0x019fa020, 0x81df0004, 0x00ffb81d, 0x81df0000, + 0x00000000, 0x00000000, 0xb600190f, 0x007f8028, + 0x019fa023, 0x007f8028, 0x019fa023, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x5c708028, 0x58908008, + 0x1983a024, 0x5c708028, 0x58908008, 0x1983a024, + 0x5c708028, 0x019fa023, 0x81df0004, 0x00ffb81d, + 0x003f03f9, 0x009f0324, 0x84840001, 0xb0010000, + 0xb4000011, 0x815b4b0c, 0x81070000, 0x81270be8, + 0xb00a0000, 0xb4000002, 0x81070c00, 0x812717e8, + 0x802500a5, 0x806500a5, 0x3001b803, 0xb420fffc, + 0x9421ffff, 0x3001b808, 0xb480000b, 0x3001b809, + 0xb4a0005d, 0xb5000008, 0xb0040000, 0xb4200003, + 0x802717ff, 0x81470000, 0xb5000003, 0x80270001, + 0x003f23f9, 0x81470c00, 0xb0040000, 0xb4200006, + 0x039f4193, 0x5b81b81c, 0x003f90cb, 0x1021b81c, + 0x003fb0cb, 0x8384f8a3, 0x829bff80, 0x801300e0, + 0x1434b800, 0x5c35b801, 0x8013001f, 0x1454b800, + 0x5c50b802, 0x8073007f, 0x9863ffff, 0xb002000f, + 0xb4800001, 0x90210001, 0x84210004, 0xb0010000, + 0xb4a00001, 0x6861b803, 0x005f9040, 0x4082b803, + 0x80af001f, 0x808f0000, 0x806f0000, 0x8007ffff, + 0x8033ffff, 0x80171000, 0x81df0000, 0x00000000, + 0x00000000, 0xb6001811, 0xb6002010, 0x14618000, + 0x6068b803, 0x40c4b803, 0x14608000, 0x00c8b806, + 0x5870b803, 0x6068b803, 0x4104b803, 0x58c8b806, + 0x0108b808, 0x14c6b801, 0x00000000, 0x00000000, + 0x5d08b808, 0x1508b800, 0x1806a028, 0x81df0004, + 0x80670400, 0x5d22b80a, 0x81df0000, 0x00000000, + 0x00000000, 0xb600180a, 0x00cfb803, 0x013fb0bc, + 0x5922b809, 0x01afb809, 0x013f90bc, 0x0047b86f, + 0xb0020001, 0xb4c0fffd, 0x90630020, 0x91290020, + 0x81df0004, 0x808f0000, 0x803b4b00, 0x00000000, + 0x802600a1, 0x80270001, 0x802600a0, 0x81270c00, + 0xb00a0000, 0xb4000001, 0x81270000, 0x813e4b0c, + 0x80270001, 0x003f2013, 0x00ffb81b, 0x00000000, +}; + +static u32 PCMUcode1f4b00[] = { + 0x00000000, 0x00000000, 0x00060504, 0x00000000, + 0x00000000, 0x00000000, 0x00300000, 0xffcfcfff, + 0x00302000, 0xffcfcfff, 0x00380000, 0xffc7c7ff, + 0xcbcecdc4, 0xcfcac9c8, 0xc3c6c5cc, 0xc7c2c1c0, + 0x1b1e1d14, 0x1f1a1918, 0x1316151c, 0x17121110, + 0x2b2e2d24, 0x2f2a2928, 0x2326252c, 0x27222120, + 0x3b3e3d34, 0x3f3a3938, 0x3336353c, 0x37323130, + 0x0b0e0d04, 0x0f0a0908, 0x0306050c, 0x07020100, + 0xdbdeddd4, 0xdfdad9d8, 0xd3d6d5dc, 0xd7d2d1d0, + 0xebeeede4, 0xefeae9e8, 0xe3e6e5ec, 0xe7e2e1e0, + 0xfbfefdf4, 0xfffaf9f8, 0xf3f6f5fc, 0xf7f2f1f0, + 0x4b4e4d44, 0x4f4a4948, 0x4346454c, 0x47424140, + 0x9b9e9d94, 0x9f9a9998, 0x9396959c, 0x97929190, + 0xabaeada4, 0xafaaa9a8, 0xa3a6a5ac, 0xa7a2a1a0, + 0xbbbebdb4, 0xbfbab9b8, 0xb3b6b5bc, 0xb7b2b1b0, + 0x8b8e8d84, 0x8f8a8988, 0x8386858c, 0x87828180, + 0x5b5e5d54, 0x5f5a5958, 0x5356555c, 0x57525150, + 0x6b6e6d64, 0x6f6a6968, 0x6366656c, 0x67626160, + 0x7b7e7d74, 0x7f7a7978, 0x7376757c, 0x77727170, + 0x341424c4, 0x3e1e2ece, 0x3d1d2dcd, 0x3b1b2bcb, + 0xb494a444, 0xbe9eae4e, 0xbd9dad4d, 0xbb9bab4b, + 0xf4d4e404, 0xfedeee0e, 0xfddded0d, 0xfbdbeb0b, + 0x74546484, 0x7e5e6e8e, 0x7d5d6d8d, 0x7b5b6b8b, + 0x3c1c2ccc, 0x361626c6, 0x351525c5, 0x331323c3, + 0xbc9cac4c, 0xb696a646, 0xb595a545, 0xb393a343, + 0xfcdcec0c, 0xf6d6e606, 0xf5d5e505, 0xf3d3e303, + 0x7c5c6c8c, 0x76566686, 0x75556585, 0x73536383, + 0x381828c8, 0x3a1a2aca, 0x391929c9, 0x3f1f2fcf, + 0xb898a848, 0xba9aaa4a, 0xb999a949, 0xbf9faf4f, + 0xf8d8e808, 0xfadaea0a, 0xf9d9e909, 0xffdfef0f, + 0x78586888, 0x7a5a6a8a, 0x79596989, 0x7f5f6f8f, + 0x301020c0, 0x321222c2, 0x311121c1, 0x371727c7, + 0xb090a040, 0xb292a242, 0xb191a141, 0xb797a747, + 0xf0d0e000, 0xf2d2e202, 0xf1d1e101, 0xf7d7e707, + 0x70506080, 0x72526282, 0x71516181, 0x77576787, + 0x05040100, 0x15141110, 0x25242120, 0x35343130, + 0x85848180, 0x95949190, 0xa5a4a1a0, 0xb5b4b1b0, + 0xc0408000, 0xe060a020, 0xd0509010, 0xf070b030, + 0xc8488808, 0xe868a828, 0xd8589818, 0xf878b838, + 0xc4448404, 0xe464a424, 0xd4549414, 0xf474b434, + 0xcc4c8c0c, 0xec6cac2c, 0xdc5c9c1c, 0xfc7cbc3c, + 0xc2428202, 0xe262a222, 0xd2529212, 0xf272b232, + 0xca4a8a0a, 0xea6aaa2a, 0xda5a9a1a, 0xfa7aba3a, + 0xc6468606, 0xe666a626, 0xd6569616, 0xf676b636, + 0xce4e8e0e, 0xee6eae2e, 0xde5e9e1e, 0xfe7ebe3e, + 0xc1418101, 0xe161a121, 0xd1519111, 0xf171b131, + 0xc9498909, 0xe969a929, 0xd9599919, 0xf979b939, + 0xc5458505, 0xe565a525, 0xd5559515, 0xf575b535, + 0xcd4d8d0d, 0xed6dad2d, 0xdd5d9d1d, 0xfd7dbd3d, + 0xc3438303, 0xe363a323, 0xd3539313, 0xf373b333, + 0xcb4b8b0b, 0xeb6bab2b, 0xdb5b9b1b, 0xfb7bbb3b, + 0xc7478707, 0xe767a727, 0xd7579717, 0xf777b737, + 0xcf4f8f0f, 0xef6faf2f, 0xdf5f9f1f, 0xff7fbf3f, + 0x1045a3e2, 0x000000f4, 0x263b7333, 0x766b2363, + 0x2b367e3e, 0x7b662e6e, 0x06db93d3, 0x964b0343, + 0x0bd69ede, 0x9b460e4e, 0x825f1757, 0x12cf87c7, + 0x8f521a5a, 0x1fc28aca, 0x00d199d9, 0x90410949, + 0x01d098d8, 0x91400848, 0x24357d3d, 0x74652d6d, + 0x25347c3c, 0x75642c6c, 0x04d59ddd, 0x94450d4d, + 0x05d49cdc, 0x95440c4c, 0x80511959, 0x10c189c9, + 0x81501858, 0x11c088c8, 0x02df97d7, 0x924f0747, + 0x0fd29ada, 0x9f420a4a, 0x865b1353, 0x16cb83c3, + 0x8b561e5e, 0x1bc68ece, 0xa6bbf3b3, 0xf6eba3e3, + 0xabb6febe, 0xfbe6aeee, 0x223f7737, 0x726f2767, + 0x2f327a3a, 0x7f622a6a, 0xa0b1f9b9, 0xf0e1a9e9, + 0xa1b0f8b8, 0xf1e0a8e8, 0x84551d5d, 0x14c58dcd, + 0x85541c5c, 0x15c48ccc, 0xa4b5fdbd, 0xf4e5aded, + 0xa5b4fcbc, 0xf5e4acec, 0x20317939, 0x70612969, + 0x21307838, 0x71602868, 0xa2bff7b7, 0xf2efa7e7, + 0xafb2faba, 0xffe2aaea, 0x00000000, 0x00000000, +}; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/ls220/mpg_240.h linux.19rc3-ac4/drivers/media/video/ls220/mpg_240.h --- linux.19rc3/drivers/media/video/ls220/mpg_240.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/ls220/mpg_240.h 2002-07-29 13:58:41.000000000 +0100 @@ -0,0 +1,1594 @@ +static u32 MPG240Ucode1f1800[] = { +0x820f001f,0x802f001f,0xb500000d,0x00000000, +0x00ffb81e,0x00000000,0x00000000,0x00000000, +0x00ffb81e,0x00000000,0x00000000,0x00000000, +0xb5000b5f,0x00000000,0x00000000,0x00000000, +0x80070800,0x001f6047,0x8013001f,0x90208000, +0x003fb174,0x803effe8,0x803effec,0x9020fa00, +0x803effd0,0x803effdc,0x803effd8,0x9020fe00, +0x803effd4,0x805bff7c,0x802500d4,0x94020080, +0xb0000000,0xb4200023,0x8013ffcf,0x9800cfff, +0x80730030,0x98631000,0x94420007,0xb0020002, +0xb4200005,0x8013ffc7,0x9800c7ff,0x80730038, +0x98631000,0xb5000006,0xb0020001,0xb4200004, +0x8013ffcf,0x9800cfff,0x80730030,0x98631000, +0x1421b800,0x1821b803,0x802600d4,0x8033001f, +0x98210000,0x802600a2,0x8033001f,0x98210300, +0x802600a3,0x80270225,0x80530001,0x98420100, +0x1821b802,0x80530200,0x98420000,0x804600a6, +0xb500001d,0x805bff7c,0x8013ffcf,0x9800cfff, +0x80730030,0x98631000,0x94420007,0xb0020002, +0xb4200005,0x8013ffc7,0x9800c7ff,0x80730038, +0x98631000,0xb5000006,0xb0020001,0xb4200004, +0x8013ffcf,0x9800cfff,0x80730030,0x98631000, +0x1421b800,0x1821b803,0x802600d4,0x8033001f, +0x98210000,0x802600a2,0x8033001f,0x98210300, +0x802600a3,0x80270c25,0x802600a1,0x80270002, +0x803eff84,0x80070000,0x801effc0,0x801effc4, +0x801effc8,0x801effcc,0x801eff88,0x80770000, +0x8057ffff,0x80170080,0x80070000,0xb6003f02, +0xb6002001,0x001fa020,0x8007ffff,0x801eff84, +0x80070001,0x001f25dc,0x001f20b1,0x80070000, +0x001f6046,0x001fb17c,0x001fb17d,0x80070000, +0x801e78d0,0x98004000,0x001f62ea,0x80070100, +0x801efff0,0x81df0004,0x00000000,0x00000000, +0x801bfff0,0x00000000,0x940000ff,0xb0000000, +0xb4200057,0x003f42ea,0x94010010,0xb0000000, +0xb400fff7,0x003f05dc,0xb0010001,0xb4200034, +0x803bffe8,0x801bffec,0x00000000,0x3001b800, +0xb4600001,0x90214000,0x0421b800,0xb0010800, +0xb460000d,0x80050086,0x005f902e,0xb0020000, +0xb4200002,0x001fb02e,0xb5000006,0x0420b802, +0xb0010930,0xb4a0ffe2,0x80070000,0x001fb02e, +0x83e40146,0xb500ffde,0x83e40111,0x80070000, +0x001fb02e,0x001f42ea,0x9400000f,0xb0000000, +0xb4000010,0x9400fff0,0x001f62ea,0x003f9174, +0x9421ffff,0x90210004,0xb001c000,0xb4800002, +0x8421c000,0x90218000,0x8013001f,0x1821b800, +0x003fb174,0x003f917c,0x90210004,0x003fb17c, +0x83e4012e,0x8013001f,0x83e71b0c,0x1bffb800, +0x003f9179,0x1821b800,0x00ffb801,0xb5000008, +0x80270000,0x003f25dc,0x8013001f,0x83e71b30, +0x1bffb800,0x003f917a,0x1821b800,0x00ffb801, +0x80070000,0x001f20b1,0x001f42ea,0x9420000f, +0xb0010000,0xb4200003,0x98000800,0x001f62ea, +0xb500ffaf,0x9400fff0,0x001f62ea,0x80270000, +0x8057ffff,0x80770000,0x80171800,0xb6000302, +0xb6002001,0x001fa021,0xb500ffa5,0xb500ffa4, +0x803bffc0,0x805bffc4,0x807bffc8,0x809bffcc, +0x5828b801,0x5cb8b802,0x1821b805,0x5848b802, +0x5cb8b803,0x1842b805,0x5868b803,0x5cb8b804, +0x1863b805,0x5888b804,0x1884b800,0x803effc0, +0x805effc4,0x807effc8,0x809effcc,0x003f42ea, +0xb0000086,0xb4400079,0xb0000084,0xb4000049, +0xb0000085,0xb4000063,0xb0000086,0xb400006c, +0xb0000081,0xb4000005,0xb0000082,0xb4000003, +0xb0000080,0xb4000001,0xb5000069,0x8013007f, +0x9800ffff,0x001fb02d,0x80070000,0x001fb17c, +0x8013001f,0x9040fa00,0x805effd0,0x805effdc, +0x805effd8,0x9040fe00,0x805effd4,0x9040c000, +0x805effe4,0x90008000,0x801effe0,0x001fb174, +0x801effe8,0x801effec,0x80078000,0x801e78d4, +0x80070000,0x001fb17c,0x001fb17d,0x001fb02e, +0x83e400ce,0x8013001f,0x98000000,0x800600a2, +0x8013001f,0x98000300,0x800600a3,0x805bff7c, +0x80070c25,0x94420080,0xb0020080,0xb420000d, +0x8013001f,0x98000000,0x800600a2,0x8013001f, +0x98000300,0x800600a3,0x80070225,0x80530001, +0x98420100,0x1800b802,0x80530200,0x98420000, +0x804600a6,0x800600a1,0x80050080,0x98000022, +0x80060080,0x80072000,0x001fb179,0x80074360, +0x001fb17a,0x80070001,0x001f25dc,0x98214000, +0xb5000029,0x8047ffff,0x805eff84,0x805bff88, +0x00000000,0xb0020001,0xb4200002,0x80470000, +0x805eff88,0x805bff7c,0x80070c25,0x94420080, +0xb0020080,0xb4200007,0x80070225,0x80530001, +0x98420100,0x1800b802,0x80530200,0x98420000, +0x804600a6,0x800600a1,0x80070001,0x800600a0, +0x9421efff,0x98210010,0xb500000f,0x80070000, +0x001fb17c,0x80070001,0x001f25dc,0x83e4008b, +0x80050081,0x80330008,0x98210000,0x1800b801, +0x80060081,0x003f42ea,0x9421ffef,0xb5000002, +0x98211000,0x9421ffef,0x83e40080,0x003f62ea, +0x80070100,0x801efff0,0xb500ff15,0xb000008b, +0xb400001c,0xb0000087,0xb400ffe8,0xb0000088, +0xb4000023,0xb000008a,0xb4000024,0xb000008c, +0xb4000019,0xb000008e,0xb4000014,0xb000008d, +0xb400001d,0xb0000089,0xb400001f,0xb00000a0, +0xb4000021,0xb00000a1,0xb4000022,0xb00000a2, +0xb400002b,0xb00000a3,0xb4000027,0xb00000a4, +0xb4000029,0xb00000a5,0xb4000029,0xb00000a6, +0xb4000029,0x803efff8,0xb500ffdd,0x80070000, +0x001fb17e,0xb500ffda,0x803bffb0,0x00000000, +0x003fb02d,0xb500ffd6,0x98210020,0xb500ffd2, +0x9421ffdf,0xb500ffd0,0xb500ffd1,0x80270341, +0x803efff8,0xb500ffce,0x803bff80,0x00000000, +0x003f62ef,0xb500ffca,0x003f917b,0x803efff8, +0xb500ffc7,0x80270000,0x8047fef0,0x003eb802, +0x90420004,0x003eb802,0x90420004,0x003eb802, +0x90420004,0x003eb802,0x83640d7c,0xb500ffbc, +0x83640d2a,0xb500ffba,0x83640ce9,0xb500ffb8, +0x83440c50,0xb500ffb6,0x83440c39,0xb500ffb4, +0x817bffe8,0x815b78d4,0x00000000,0x956bffff, +0x300bb80a,0xb4600001,0x916b4000,0x056bb80a, +0xb00b0080,0xb4a00026,0x80af001f,0x808f0000, +0x806f0000,0x81b300ff,0x8057ffff,0x5d67b80b, +0x5d42b80a,0xb62b001c,0xb00a3000,0xb4800001, +0x854a1000,0x80cf0400,0x015fb178,0x5942b80a, +0x01cfb80a,0x015f9178,0xb520ffff,0x80171000, +0xb600200a,0x01ff8000,0x5a18b80f,0x5a28b80f, +0x1631b80d,0x5e48b80f,0x9652ff00,0x5e78b80f, +0x1a73b810,0x1a73b811,0x1813a032,0x80cf0400, +0x015fb178,0x5942b80a,0x01afb80a,0x015f9178, +0xb520ffff,0x914a0020,0x5942b80a,0x815e78d4, +0x00000000,0x00000000,0x00ffb81f,0x80070000, +0x80470000,0x81171800,0xb6002003,0xb6003002, +0x001eb802,0x90420004,0xb6002003,0x011fa020, +0x011fa020,0x011fa020,0x00ffb81f,0x80070000, +0x80478000,0xb6002003,0xb6008002,0x001eb802, +0x90420004,0x00ffb81f,0x00000000,0x00000000, +0x015f42ea,0x944a4000,0xb0024000,0xb4200071, +0x954abfff,0x015f62ea,0x808f0000,0x80ef007c, +0x80171000,0x80971400,0x80270000,0xb6001003, +0xb6002002,0x001fa021,0x009fa021,0x80a76604, +0x80271400,0xb6001004,0x01efb801,0x01afb805, +0xb520ffff,0x90a50080,0x80a76e04,0x80271400, +0xb6001004,0x01efb801,0x01afb805,0xb520ffff, +0x90a50080,0x806f001f,0x80af001f,0x80276400, +0x5c22b801,0x806701e1,0x00cfb803,0x003fb178, +0x5822b801,0x01cfb801,0x003f9178,0x0047b86f, +0xb0020001,0xb4c0fffd,0x80275c00,0x5c22b801, +0x80670200,0xb600100a,0x00cfb803,0x003fb178, +0x5822b801,0x01cfb801,0x003f9178,0x0047b86f, +0xb0020001,0xb4c0fffd,0x90210020,0x90630020, +0x808f0000,0x806f001f,0x80af001f,0x8027647c, +0x5c22b801,0x8067017e,0xb600020a,0x00cfb803, +0x003fb178,0x5822b801,0x01cfb801,0x003f9178, +0x0047b86f,0xb0020001,0xb4c0fffd,0x90210020, +0x90630020,0x806f0010,0x80af0010,0x8027657c, +0x5c22b801,0x806701be,0x00cfb803,0x003fb178, +0x5822b801,0x01cfb801,0x003f9178,0x0047b86f, +0xb0020001,0xb4c0fffd,0x802765c0,0x5c22b801, +0x806701cf,0x00cfb803,0x003fb178,0x5822b801, +0x01cfb801,0x003f9178,0x0047b86f,0xb0020001, +0xb4c0fffd,0x80276000,0x005fb801,0x8033001f, +0x98218000,0x803effe0,0x90214000,0x803effe4, +0x8193001f,0x998c8000,0x019fb174,0x83270000, +0x003fb819,0x003f9174,0x5823b801,0x83338000, +0x1b39b801,0x003fb819,0x00000000,0x00000000, +0x81550000,0x0187b860,0x858c0040,0x81b380fc, +0x99ad0000,0x300cb80d,0xb4600003,0x81b30002, +0x99ad0000,0x118cb80d,0x003fb80c,0x00000000, +0x00000000,0x81550000,0x8257ffff,0x82d7ffff, +0x8357ffff,0x81672000,0x83440189,0xb00a0001, +0xb4000141,0x0187b860,0x858c0010,0x5988b80c, +0x5d8bb80c,0x958cffff,0xb00cc000,0xb4800002, +0x858cc000,0x918c8000,0x81b3001f,0x198cb80d, +0x801bffec,0x00000000,0x819effec,0x819e78d8, +0x019fb174,0x05acb800,0x300cb800,0xb4600001, +0x91ad4000,0x001f917c,0x1000b80d,0x001fb17c, +0x83440194,0xb00a0000,0xb4200127,0x015f0081, +0xb00a0002,0xb4200124,0x037f0082,0xb01b0000, +0xb400001e,0x0367b860,0x5b68b81b,0x5f68b81b, +0x017f4047,0x916b0010,0x5963b80b,0x83440160, +0x801bff84,0xb00a0001,0xb400000b,0xb00b00c0, +0xb460fffa,0x803f0000,0x80138000,0x1b7bb800, +0x003fb81b,0x00000000,0x00000000,0x80150000, +0x801bff84,0xb5000009,0x803f0000,0x80138000, +0x1b7bb800,0x003fb81b,0x00000000,0x00000000, +0x80150000,0x801bff84,0xb5000103,0x801bff84, +0x003f0084,0x3000b801,0x803eff84,0xb4000073, +0x801bff7c,0x00000000,0x94800080,0xb0040080, +0xb4200036,0x94800007,0x80730200,0xb0010002, +0xb420000e,0x80270265,0xb0040001,0xb4200003, +0x80130030,0x98000000,0xb5000006,0x80130030, +0x98000000,0xb0040000,0xb4000002,0x80130038, +0x98000000,0x98630060,0xb500001f,0xb0010000, +0xb420000e,0x80270225,0xb0040001,0xb4200003, +0x80130030,0x98001000,0xb5000006,0x80130030, +0x98001000,0xb0040000,0xb4000002,0x80130038, +0x98001000,0x98630000,0xb500000f,0xb0010001, +0xb420004a,0x80270225,0xb0040001,0xb4200003, +0x80130030,0x98002000,0xb5000006,0x80130030, +0x98000000,0xb0040000,0xb4000002,0x80130038, +0x98000000,0x98630040,0x806600a6,0x80530001, +0x98420100,0x1821b802,0xb500002d,0x94800007, +0xb0010002,0xb420000d,0x80270c65,0xb0040001, +0xb4200003,0x80130030,0x98000000,0xb5000006, +0x80130030,0x98000000,0xb0040000,0xb4000002, +0x80130038,0x98000000,0xb500001d,0xb0010000, +0xb420000d,0x80270c25,0xb0040001,0xb4200003, +0x80130030,0x98001000,0xb5000006,0x80130030, +0x98001000,0xb0040000,0xb4000002,0x80130038, +0x98001000,0xb500000e,0xb0010001,0xb4200017, +0x80270c25,0xb0040001,0xb4200003,0x80130030, +0x98002000,0xb5000006,0x80130030,0x98000000, +0xb0040000,0xb4000002,0x80130038,0x98000000, +0x806500d4,0x8053ffcf,0x9842cfff,0xb0040002, +0xb4200002,0x8053ffc7,0x9842c7ff,0x802600a1, +0x1463b802,0x1863b800,0x806600d4,0x807bff7c, +0x00000000,0x94630080,0xb0030080,0xb420000b, +0x807bff88,0x00000000,0xb0030001,0xb4000007, +0x802500a1,0x80670001,0x807eff88,0x80530001, +0x98420100,0x1821b802,0x802600a1,0x81070000, +0x011f62e2,0x011f62e3,0x011f0082,0xb0080000, +0xb4200004,0x81150010,0x00000000,0x00000000, +0x011f62de,0x011f0081,0xb0080001,0xb4200026, +0x81070020,0x011f25c1,0x81070180,0x011f62e1, +0x8344022a,0x8344024e,0x011f0082,0xb0080000, +0xb4200004,0x834401b1,0x8344019e,0xb00a0000, +0xb4200061,0x80c70000,0x00df25cb,0x83440261, +0x834405e7,0x02ff05b9,0x82a70000,0x82870000, +0x834403cf,0x92940001,0x3014b817,0xb480fffc, +0x8344067f,0x80270000,0x003f25dc,0x83440760, +0x003f05dc,0xb0010001,0xb4000003,0x802725d4, +0x003fb17a,0x00ffb81f,0x80d3001f,0x834725ac, +0x1b5ab806,0xb500002d,0xb0080002,0x81470004, +0xb4200045,0x81070008,0x011f25c1,0x81070480, +0x011f62e1,0x83440276,0x834402b0,0x011f0082, +0xb0080000,0xb4200004,0x8344019a,0x83440175, +0xb00a0000,0xb4200038,0x80c70000,0x00df25cb, +0x83440334,0x02df05cb,0x5ec2b816,0x834405ff, +0x02ff05b9,0x82a70000,0x82870000,0x834403a4, +0x92940001,0x3014b817,0xb480fffc,0x92b50001, +0xb0150003,0xb480fff8,0x83440651,0x80270000, +0x003f25dc,0x83440732,0x003f05dc,0xb0010001, +0xb4000003,0x8027268c,0x003fb17a,0x00ffb81f, +0x80d3001f,0x83472650,0x1b5ab806,0x80db78d8, +0x80fbffec,0x00000000,0x3006b807,0xb4200007, +0x00df05cb,0x90c60001,0x00df25cb,0xb006000c, +0xb4000002,0x035fb179,0x00ffb81f,0x80c70000, +0x00df25cb,0x80fb78dc,0x00000000,0x90e70001, +0xb00701b9,0xb4a00001,0x80e70001,0x80fe78dc, +0xb500feb0,0x802500a5,0x8153001f,0x3001b80a, +0xb420fffc,0x00ffb81f,0x001f42ea,0x1800b80a, +0x001f62ea,0x017f4047,0x5963b80b,0x0187b860, +0x118cb80b,0x81b380fe,0x99ad0000,0x300cb80d, +0xb4800003,0x81b30002,0x99ad0000,0x058cb80d, +0x003fb80c,0x00000000,0x00000000,0x81550000, +0x0187b860,0x5988b80c,0x5d8bb80c,0x958cffff, +0xb00cc000,0xb4800002,0x858cc000,0x918c8000, +0x81b3001f,0x198cb80d,0x801bffec,0x00000000, +0x819effec,0x019fb174,0x05acb800,0x300cb800, +0xb4600001,0x91ad4000,0x001f917c,0x1000b80d, +0x001fb17c,0x80171000,0x80971400,0x80270000, +0xb6001003,0xb6002002,0x001fa021,0x009fa021, +0x80171800,0xb6000602,0xb6002001,0x001fa021, +0x806f001f,0x80af001f,0x80a76604,0x80271400, +0xb6001004,0x01efb801,0x01afb805,0xb520ffff, +0x90a50080,0x80a76e04,0x80271400,0xb6001004, +0x01efb801,0x01afb805,0xb520ffff,0x90a50080, +0x81472000,0x015fb179,0x00ffb81f,0x00000000, +0x811be024,0x0107b860,0x95080007,0xb0080000, +0xb4000004,0xa5080008,0x00000000,0x0155b808, +0x00000000,0x8115000c,0x856b000c,0xb0080fff, +0xb400000b,0x81550004,0x856b0004,0x5904b808, +0x1908b80a,0x95080fff,0xb0080fff,0xb4000004, +0x81470001,0xb00b0020,0xb440fff6,0xb500000c, +0x81d50004,0x856b0004,0x00000000,0xb00e000f, +0xb400fffb,0x940b0007,0xb0000000,0xb420ffed, +0x001f42ea,0x9400fffe,0x81470000,0x001f62ea, +0x00ffb81a,0x950e0008,0x5d03b808,0x00000000, +0xb0080000,0xb40000c9,0x011f2080,0x950e0006, +0x5d01b808,0x81270004,0x0529b808,0x950e0001, +0x013f2081,0x011f2082,0x81150004,0x00000000, +0xb0080000,0xb40000bd,0xb008000f,0xb40000bb, +0x011f2083,0x81150002,0x00000000,0x81670004, +0xb0080002,0xb46000b5,0x011f2084,0x013f0081, +0xb0090002,0xb4200011,0x013f0083,0xb0080000, +0xb4200002,0x81077844,0xb5000005,0xb0080001, +0xb4200002,0x81077884,0xb5000001,0x81077824, +0x013f0083,0x5921b809,0x1129b808,0x0119b809, +0x00000000,0x00000000,0x011f6047,0x81150001, +0x00000000,0x011f2085,0x81150001,0x00000000, +0x011f2086,0x81350002,0x00000000,0x013f2087, +0x81150002,0x00000000,0x011f2088,0x81150001, +0x00000000,0x011f2089,0x81150001,0x00000000, +0x011f208a,0x81150002,0x00000000,0x011f208b, +0x81070001,0xb0090003,0xb4000001,0x81070002, +0x011f25b9,0x81070020,0x013f0081,0xb0090002, +0xb4200065,0x85290001,0xad29000f,0x00000000, +0x011f0083,0x1108b809,0x5901b808,0x910877c8, +0x0139b808,0x011f05b9,0x85080001,0x6928b809, +0x011f0084,0xb0090038,0xb4800007,0xb0080001, +0xb4000002,0xb0090050,0xb4400003,0x81270000, +0x8107001b,0xb5000010,0xb0080001,0xb4000005, +0xb0090060,0xb4800003,0x81270001,0x8107001e, +0xb5000009,0xb0080002,0xb4000005,0xb0090030, +0xb4400003,0x81270002,0x81070008,0xb5000002, +0x81270003,0x8107000c,0x011f25bb,0x013f25c0, +0xb0090002,0xb460001b,0x80477604,0x5c42b802, +0x814fffc0,0x80cf0037,0x005fb178,0x5842b802, +0x01cfb802,0x005f9178,0xb520ffff,0x90420020, +0x814fb580,0x80cf0057,0x005fb178,0x5842b802, +0x01cfb802,0x005f9178,0xb520ffff,0x804778a4, +0x5c42b802,0x814f39c0,0x80cf002f,0x005fb178, +0x5842b802,0x01cfb802,0x005f9178,0xb520ffff, +0xb5000021,0x804776e0,0x5c42b802,0x814fef40, +0x80cf0037,0x005fb178,0x5842b802,0x01cfb802, +0x005f9178,0xb520ffff,0x8297013c,0x8317018c, +0xb6000602,0x005f8034,0x031fa022,0x82970124, +0x83170160,0xb6000602,0x005f8034,0x031fa022, +0x8297010c,0x83170134,0xb6000602,0x005f8034, +0x031fa022,0x804778c4,0x5c42b802,0x814f1080, +0x80cf002f,0x005fb178,0x5842b802,0x01cfb802, +0x005f9178,0xb520ffff,0x013f0081,0xb0090001, +0xb420000e,0x808f0000,0x806f001b,0x80af001b, +0x80277758,0x5c22b801,0x80670037,0x00cfb803, +0x003fb178,0x5822b801,0x01cfb801,0x003f9178, +0x0047b86f,0xb0020001,0xb4c0fffd,0x011f25bb, +0x011f0087,0xb0080001,0xb4000002,0x011f05bb, +0xb5000003,0x011f0088,0x91080001,0x5902b808, +0x011f25ba,0x81470000,0x00ffb81a,0x81470008, +0x00ffb81a,0x81270000,0x81470000,0x300842de, +0xb400000b,0x013f42e2,0x91290001,0x013f62e2, +0x013f42e3,0x91290001,0x013f62e3,0x83640006, +0x00000000,0x00000000,0x013f42e2,0x81470002, +0x013f62e2,0x00ffb81a,0x00ffb81b,0x83640041, +0x80c70004,0x80270000,0xb600200d,0x00ff05b9, +0x5c42b801,0x300205ba,0xb4800001,0x80e70001, +0x80470000,0xb6270005,0x1062b801,0x914301b8, +0x00fff00a,0x83840050,0x90420080,0x90210004, +0x00ffb81a,0x8364002f,0x017f05bb,0x800700bc, +0x80270000,0xb00b0000,0xb4000015,0xb62b0014, +0x00ff05b9,0x5c42b801,0x300205ba,0xb4800001, +0x80e70001,0x80470000,0xb0070000,0xb400000b, +0xb627000a,0x1062b801,0x914301b8,0x00fff00a, +0x5c62b801,0x1063b800,0x00bff003,0x90650134, +0x00dff003,0x83840034,0x90420080,0x90210004, +0x019f05b9,0x80c70002,0x80270000,0xb00b0000, +0xb400000f,0xb62b000e,0x80470000,0xb00c0000, +0xb400000a,0xb62c0009,0x1062b801,0x914301b8, +0x00fff00a,0xb0070000,0xb4000003,0x906302b8, +0x00fff003,0x83840020,0x90420080,0x90210004, +0x00ffb81a,0x8107ffff,0x80c70004,0x00ff0083, +0x83840019,0x80c70002,0x00ff0084,0x83840016, +0x80c70001,0x00ff0085,0x83840013,0x80c70001, +0x00ff0086,0x83840010,0x80c70002,0x00ff0087, +0x8384000d,0x80c70002,0x00ff0088,0x8384000a, +0x80c70001,0x00ff0089,0x83840007,0x80c70001, +0x00ff008a,0x83840004,0x80c70002,0x00ff008b, +0x83840001,0x00ffb81b,0x80a70001,0x64a6b805, +0x5ca1b805,0xb0050000,0xb400000e,0x95288000, +0xb0090000,0xb4000001,0x81270001,0x5901b808, +0x1547b805,0xb00a0000,0xb4000001,0x81470001, +0x2129b80a,0xb0090000,0xb4000001,0xa1088005, +0xb500ffef,0x9508ffff,0x00ffb81c,0x015f05ba, +0x013f05b9,0x800700bc,0xb0090000,0xb400000f, +0xb00a0000,0xb400000d,0x80270000,0xb62a000b, +0x80470000,0xb6290008,0x80950004,0x5865b802, +0x1063b801,0x5862b803,0x906301b8,0x0217b803, +0x90420001,0x021fa004,0x90210001,0xa54a0020, +0xb4c0000e,0xb0090000,0xb400000c,0xb62a000b, +0x80950004,0x80470000,0xb6290007,0x5865b802, +0x1063b801,0x5862b803,0x906301b8,0x0217b803, +0x90420001,0x021fa004,0x90210001,0x00ffb81a, +0x013f05b9,0xb0090000,0xb4000019,0x80270000, +0xb6002017,0x80470000,0xb6290014,0x5865b802, +0x1063b801,0x5862b803,0x914301b8,0x009ff00a, +0xad420060,0x00000000,0x114ab801,0x5942b80a, +0x914a1c80,0x0217b80a,0xb0040000,0xb4000004, +0x80950006,0x00000000,0x021fa004,0xb5000002, +0x8087003f,0x021fa004,0x90420001,0x90210001, +0x00ffb81a,0x8257ffff,0x82d7ffff,0x011f05ba, +0x013f05b9,0x80270000,0xb0090000,0xb400002b, +0xb6280015,0x80470000,0xb6290012,0x5865b802, +0x1063b801,0x5862b803,0x914301b8,0xaca20060, +0x009ff00a,0x10a5b801,0x58a2b805,0x90a502b8, +0x0217b805,0x80670000,0xb0040000,0xb4000003, +0x90840001,0x0075b804,0x00000000,0x021fa003, +0x90420001,0x90210001,0xa5480020,0xb4000013, +0x5822b801,0xb62a0011,0x914101b8,0x90a102b8, +0x0217b805,0x009ff00a,0xb0040000,0x80670000, +0xb4000002,0x90840001,0x0075b804,0xb6290006, +0x021fa203,0x009f8210,0x009f8210,0x009f8210, +0x009f8210,0x009f8210,0x90210004,0x00ffb81a, +0x015f05ba,0x013f05b9,0x800700bc,0xb0090000, +0xb4000013,0xb00a0000,0xb4000011,0x80270000, +0xb62a000f,0x80470000,0xb629000c,0x1080b801, +0x007ff004,0x90830134,0x007ff004,0x0095b803, +0x5865b802,0x1063b801,0x5862b803,0x906301b8, +0x0217b803,0x90420001,0x021fa004,0x90210001, +0x011f05bb,0x254ab808,0xb4c0000d,0xb62a000c, +0x1080b801,0x007ff004,0x90830134,0x007ff004, +0x0095b803,0x5862b801,0x906301b8,0x0217b803, +0x90210001,0x021fa204,0x007f8210,0x021fa004, +0xa5480020,0xb4c0000e,0xb0090000,0xb400000c, +0x80870000,0xb62a000a,0x80470000,0xb6290007, +0x5865b802,0x1063b801,0x5862b803,0x906301b8, +0x0217b803,0x90420001,0x021fa004,0x90210001, +0x00000000,0x00000000,0x00ffb81a,0x011f05bb, +0x013f05b9,0xb0080000,0xb4000015,0xb0090000, +0xb4000013,0x00000000,0x80270000,0xb6280010, +0x80470000,0xb629000d,0x5865b802,0x1063b801, +0x5862b803,0x914301b8,0x009ff00a,0xb0040000, +0xb4000005,0x80950002,0x906302b8,0x0217b803, +0x00000000,0x021fa004,0x90420001,0x90210001, +0xa5480020,0xb00a0000,0xb4000010,0xb0090000, +0xb400000e,0x00000000,0x80870000,0xb62a000b, +0x80470000,0xb6290008,0x5865b802,0x1063b801, +0x5862b803,0x906302b8,0x0217b803,0x00000000, +0x021fa004,0x90420001,0x90210001,0xb0080000, +0xb400004c,0xb0090000,0xb400004a,0x00000000, +0x80270000,0xb6280047,0x80470000,0xb6290044, +0x5865b802,0x1063b801,0x5862b803,0x914301b8, +0x009ff00a,0xad420060,0x00000000,0x00000000, +0x00000000,0x114ab801,0x5942b80a,0x914a1c80, +0x0217b80a,0xb0040000,0xb400002e,0x906302b8, +0x009ff003,0xb0040000,0xb420000a,0x80950006, +0x00000000,0x021fa204,0x80950006,0x015f8210, +0x021fa204,0x80950006,0x015f8210,0x021fa004, +0xb5000026,0xb0040001,0xb4200009,0x80950006, +0x00000000,0x021fa204,0x015f8210,0x021fa204, +0x80950006,0x015f8210,0x021fa004,0xb500001b, +0xb0040003,0xb4200009,0x80950006,0x00000000, +0x021fa204,0x80950006,0x015f8210,0x021fa204, +0x015f8210,0x021fa004,0xb5000010,0xb0040002, +0xb420000e,0x80950006,0x00000000,0x021fa204, +0x015f8210,0x021fa204,0x015f8210,0x021fa004, +0xb5000006,0x8087003f,0x021fa204,0x015f8210, +0x021fa204,0x015f8210,0x021fa004,0x90420001, +0x90210001,0xa5480020,0xb4c00011,0xb0090000, +0xb400000f,0x8087003f,0x5862b801,0x90631afc, +0xb62a000b,0x90630004,0x0047b803,0xb6290008, +0x90420180,0x0217b802,0x00000000,0x021fa204, +0x003f8210,0x021fa204,0x003f8210,0x021fa004, +0x00ffb81a,0x8257ffff,0x82d7ffff,0x011f05bb, +0x013f05b9,0x80270000,0x00e7b809,0x300105ba, +0xb4800001,0x80e70001,0x800700bc,0x80470000, +0xb0070000,0xb400004c,0xb627004b,0x5865b802, +0x1063b801,0x5862b803,0x914301b8,0xaca20060, +0x009ff00a,0x10a5b801,0x58a2b805,0x90a502b8, +0x0217b805,0xb0040000,0xb400002b,0x1060b801, +0x00bff003,0x10a5b804,0x90650160,0x00dff003, +0xb0060003,0xb4200007,0x90650134,0x00dff003, +0xb6000303,0x0075b806,0x021fa203,0x007f8210, +0xb5000021,0x5861b805,0x906300dc,0x009fd803, +0x90650134,0x00dff003,0xaca20060,0x00000000, +0x00000000,0x00000000,0x0075b806,0x10a5b801, +0x58a2b805,0x90a502b8,0x0217b805,0x588fb804, +0xb600030c,0xb6001007,0x04a3b804,0xb4600002, +0x58a1b803,0xb5000002,0x58a1b805,0x90a50001, +0x0067b805,0x9465ffff,0x5d50b805,0x021fa20a, +0x015f8210,0xb5000004,0x81470000,0xb6000302, +0x021fa20a,0x009f8210,0x009f05b9,0xb0040002, +0xb420000c,0x300105ba,0xb480000a,0x58a2b801, +0x90a502b8,0x0217b805,0x90a50180,0x0297b805, +0xb6000304,0x00bf8210,0x009f8210,0x029fa205, +0x009f8214,0x90420001,0x90210001,0x3001b808, +0xb480ffa9,0xa5480020,0xb00a0000,0xb4000015, +0xb0090000,0xb4000013,0x58a2b801,0x90a502b8, +0xb62a0010,0x80470000,0xb629000d,0xaca20060, +0x00000000,0x00000000,0x00000000,0x80670000, +0x10a5b801,0x58a2b805,0x90a502b8,0x0217b805, +0xb6000302,0x021fa203,0x00bf8210,0x90420001, +0x90210001,0x00ffb81a,0x00000000,0x00000000, +0x80770000,0x8057ffff,0x80f70000,0x80d7ffff, +0x81770000,0x8157ffff,0x81f70000,0x81d7ffff, +0xac140060,0xac350020,0x00000000,0x00000000, +0x12c0b801,0x5ac2b816,0x92d61980,0x83a400a5, +0xad940400,0x009f9173,0x013f05ca,0x914c6604, +0x114ab804,0x001f97e0,0x001eb80a,0xb0090000, +0xb4000003,0x80a76e44,0x80c76644,0xb5000002, +0x80a76644,0x80c76e44,0x808f000f,0x806f0000, +0x80af000e,0x80cf07e1,0x11e5b80c,0x11efb804, +0x5de2b80f,0x01ffb178,0x59e2b80f,0x01afb80f, +0x01ff9178,0x0047b86f,0xb0020001,0xb4c0fffd, +0x80cf07f0,0x1206b80c,0x1210b804,0x5e02b810, +0x021fb178,0x5a02b810,0x01afb810,0x021f9178, +0x0047b86f,0xb0020001,0xb4c0fffd,0x916c6e04, +0x116bb804,0x001f97ff,0x001eb80b,0x808f0000, +0x806f001f,0x80af001f,0x90ac6604,0x5ca2b805, +0x80270400,0xb600080a,0x00cfb801,0x00bfb178, +0x58a2b805,0x01cfb805,0x00bf9178,0x0047b86f, +0xb0020001,0xb4c0fffd,0x90210020,0x90a50020, +0x90ac6e04,0x5ca2b805,0x80270500,0xb600080a, +0x00cfb801,0x00bfb178,0x58a2b805,0x01cfb805, +0x00bf9178,0x0047b86f,0xb0020001,0xb4c0fffd, +0x90210020,0x90a50020,0x81530020,0xac140060, +0xac350020,0x80170800,0x80d7003c,0x12c0b801, +0x5ac2b816,0x92d602b8,0x0117b816,0x90241000, +0x0097b801,0x80470000,0x4002b803,0xb6000804, +0x005f8020,0x480287e4,0x005f8020,0x500287e4, +0x00000000,0x00000000,0x00000000,0x1021b80a, +0x5c36b801,0x5801b800,0x18c0b801,0xb0090000, +0xb4000002,0x90641440,0xb5000001,0x90641040, +0xb6000f0d,0x0097b803,0x80470000,0x4002b803, +0xb6001002,0x005f8020,0x480287e4,0x0108a026, +0x90630040,0x00000000,0x1021b80a,0x5c36b801, +0x5801b800,0x18c0b801,0x90641400,0x0097b803, +0x80470000,0x4002b803,0x005f8020,0x005f87e4, +0xb6000802,0x005f8040,0x480287c4,0x005f87e0, +0x0108a026,0x00000000,0x1021b80a,0x5c36b801, +0x5801b800,0x18c0b801,0xb0090000,0xb4000002, +0x906417c0,0xb5000001,0x906413c0,0xb6000f0f, +0x0097b803,0x80470000,0x4002b803,0xb6000804, +0x005f8020,0x500287e4,0x005f8020,0x480287e4, +0x0108a026,0x84630040,0x00000000,0x1021b80a, +0x5c36b801,0x5801b800,0x18c0b801,0xb0140000, +0xb4200005,0x90840004,0x9484003f,0x009fb173, +0xa1290001,0x013f25ca,0x80d7ffff,0x0108a026, +0x00ffb81a,0x81330004,0x8093007f,0x9884ffff, +0x80b3ff80,0x0017b816,0x90360040,0x0097b801, +0x81530010,0xb6001004,0x400a8000,0x404a8004, +0x0008a020,0x0088a022,0x0017b816,0x9036007c, +0x0097b801,0x81171000,0xb6001004,0x40048020, +0x480487e4,0x00000000,0x0108a020,0x81470000, +0x81670001,0x81870008,0x81a70040,0x81c707c4, +0x81e70040,0xb6000432,0xb00a0001,0xb4e00004, +0x80c71000,0x80e71000,0x81171040,0xb5000003, +0x80c71040,0x80e71040,0x81171000,0x844d0004, +0x10e7b802,0xb62b001f,0x0017b806,0x0097b807, +0xb62c0004,0x40048020,0x480487e4,0x00000000, +0x0108a020,0x0017b806,0x0097b807,0x0197b80e, +0x00000000,0x001f8020,0x042087e4,0xb62c000f, +0x4041800c,0x001f8020,0x0048b802,0x5e38802c, +0x2e11b801,0x042087e4,0x1042b810,0x0462b804, +0xb4a00002,0x0047b804,0xb5000003,0x0462b805, +0xb4600001,0x0047b805,0x011fa022,0x10c6b80f, +0x10e7b80f,0x5961b80b,0x5d81b80c,0x5da1b80d, +0x5de1b80f,0x914a0001,0x954a0001,0x11ceb80f, +0x80171018,0x81171fcc,0x80470000,0x41448020, +0x494487c0,0x00000000,0x0188b80a,0x494487e0, +0x00000000,0x0148b80a,0x0502a10a,0x4145b80c, +0x494580e0,0x00000000,0x0108a5ea,0x41448080, +0x494487c0,0x00000000,0x0108a78a,0x49448020, +0x00000000,0x0108a2ea,0x41448020,0x49448720, +0x00000000,0x0188b80a,0x4145b80c,0x49458080, +0x494587a0,0x00000000,0x0108a68a,0x4145b80c, +0x49458080,0x494587a0,0x00000000,0x0108a08a, +0x4145b80c,0x49458020,0x49458040,0x00000000, +0x0188b80a,0x494587e0,0x00000000,0x0108a08a, +0x4144b80c,0x494587a0,0x00000000,0x0108a52a, +0x41448080,0x49448040,0x494486c0,0x00000000, +0x0108a04a,0x41448040,0x49448720,0x00000000, +0x0108a36a,0x04028020,0x011fa420,0x001f8040, +0x011fa100,0x001f8080,0x011fa080,0x001f8100, +0x011fa040,0x001f8660,0x011fa120,0x41458020, +0x49458000,0x00000000,0x0108a00a,0x0017b816, +0x9036007c,0x0097b801,0x81171000,0x81970784, +0x00000000,0x001f8020,0x042087e4,0xb600100f, +0x4041800c,0x001f8020,0x0048b802,0x5e38802c, +0x2e11b801,0x042087e4,0x1042b810,0x0462b804, +0xb4a00002,0x0047b804,0xb5000003,0x0462b805, +0xb4600001,0x0047b805,0x011fa022,0x81470000, +0x81670001,0x81870008,0x81a70040,0x81c707c4, +0x81e70040,0xb6000432,0xb00a0001,0xb4e00004, +0x80c71000,0x80e71000,0x81171040,0xb5000003, +0x80c71040,0x80e71040,0x81171000,0x844d0004, +0x10e7b802,0xb62b001f,0x0017b806,0x0097b807, +0xb62c0004,0x40048020,0x480487e4,0x00000000, +0x0108a020,0x0017b806,0x0097b807,0x0197b80e, +0x00000000,0x001f8020,0x042087e4,0xb62c000f, +0x4041800c,0x001f8020,0x0048b802,0x5e38802c, +0x2e11b801,0x042087e4,0x1042b810,0x0462b804, +0xb4a00002,0x0047b804,0xb5000003,0x0462b805, +0xb4600001,0x0047b805,0x011fa022,0x10c6b80f, +0x10e7b80f,0x5961b80b,0x5d81b80c,0x5da1b80d, +0x5de1b80f,0x914a0001,0x954a0001,0x11ceb80f, +0x80171034,0x81171f84,0x80470000,0x41448040, +0x49448640,0x00000000,0x0188b80a,0x49448100, +0x49448780,0x00000000,0x0108a08a,0x4144b80c, +0x49448040,0x49448080,0x494487c0,0x00000000, +0x0108a16a,0x4145b80c,0x49458700,0x00000000, +0x0188b80a,0x494581a0,0x494586e0,0x00000000, +0x0108a66a,0x4145b80c,0x49448040,0x494487e0, +0x00000000,0x0188b80a,0x011fa1ec,0x4145b80c, +0x49458100,0x49458780,0x00000000,0x0108a08a, +0x41458720,0x49458100,0x494586e0,0x49458160, +0x49458020,0x49458020,0x49458760,0x00000000, +0x0108a08a,0x414587a0,0x49458080,0x49458760, +0x494580c0,0x49458700,0x49458140,0x49458020, +0x49458760,0x00000000,0x0108a74a,0x414587a0, +0x49458080,0x49458760,0x494580e0,0x49458700, +0x49458120,0x49458020,0x49458760,0x00000000, +0x0108a08a,0x41458720,0x49458100,0x494586e0, +0x49458140,0x49458040,0x49458020,0x49458720, +0x00000000,0x0108a0ca,0x41458080,0x49458040, +0x49458020,0x49458620,0x00000000,0x0188b80a, +0x49458080,0x00000000,0x0108a7ca,0x4144b80c, +0x49458040,0x49458020,0x49458080,0x00000000, +0x0108a5ea,0x41448080,0x49448700,0x00000000, +0x0188b80a,0x49448780,0x00000000,0x0108a7ca, +0x4144b80c,0x49448140,0x00000000,0x0108a7ca, +0x49448040,0x00000000,0x0108a0ca,0x41448700, +0x00000000,0x0188b80a,0x49448000,0x00000000, +0x0108a04a,0x011fa00c,0x80171f80,0xb6002006, +0x40048000,0x48048000,0x48048000,0x48048000, +0x00000000,0x0008a020,0x00ffb81d,0x00000000, +0x80770000,0x8057ffff,0x015f05b9,0x017f05bb, +0x8293ffff,0x9a94ffff,0x81a70000,0xb62a003a, +0xaded0180,0xae0d0180,0xadcd0080,0x902f1980, +0x0017b801,0xb6002033,0x904e01b8,0x00000000, +0x013ff002,0xb0090000,0xb400001f,0x904f02b8, +0x80c70000,0x011fd802,0x6829b808,0x94210001, +0xb0010001,0xb4e00001,0x00c7b814,0x6429b806, +0x80470001,0x6449b802,0x84420001,0x1442b808, +0x84690001,0x5863b803,0x906300dc,0x1042b801, +0x003f9803,0x90420001,0x4082b801,0x90630004, +0x003f9803,0x00000000,0x5897b804,0x1804b805, +0x4082b801,0x00000000,0x00000000,0x00000000, +0x10a4b800,0xb5000001,0x80a70000,0x90501c80, +0x00000000,0x007ff002,0x5842b803,0x904205f8, +0x0097b802,0x00000000,0x40058004,0x48058004, +0x00000000,0x0008a020,0x91ce0004,0x91ef0004, +0x92100004,0x91ad0001,0x00ffb81a,0x80770000, +0x8057ffff,0x80d7ffff,0x015f05b9,0x017f05bb, +0x8293ff80,0x9a940000,0x82a70020,0x81a70000, +0x81e702b8,0x80171980,0xb62a004f,0xb600034d, +0xac0d0080,0xac4d0180,0xac960080,0x822700bc, +0x91c001b8,0x00000000,0x1042b804,0x92021c80, +0xb62b003a,0x013ff00e,0x00fff011,0xb0090000, +0xb4000027,0x10e7b809,0x5821b807,0x902100dc, +0x00000000,0x001fd801,0x82470000,0x80270001, +0x6452b801,0x3002b800,0xb4600002,0x92520001, +0xb500fffb,0x86520001,0x80c70000,0x011fd80f, +0x6832b808,0xb0010001,0xb4e00001,0x00c7b814, +0x84520017,0x0056b802,0x80270001,0x6432b801, +0x84210001,0x1408b801,0x6402b800,0x10c6b800, +0x9027018c,0x00000000,0x001ff001,0x5802b800, +0x9020073c,0x904006f8,0x007f9801,0x0097b802, +0x10c6b803,0x40868004,0x48868004,0xb5000003, +0x80c70000,0x40868004,0x00000000,0x0088b804, +0x003ff010,0x5822b801,0x902105f8,0x0097b801, +0x91ce0004,0x91ef0004,0x40448004,0x48448004, +0x92100004,0x0008a022,0x92310001,0x0435b80b, +0xb4000007,0x80870000,0xb6210005,0x001fa024, +0x91ce0004,0x91ef0004,0x92100004,0x92310001, +0x00000000,0x91ad0001,0x00ffb81a,0x00000000, +0x007f05b9,0x001f0081,0xb0000001,0xb4400029, +0x001f05d8,0xac400080,0x801702b8,0x80970438, +0x90421800,0x0117b802,0x8087ffff,0x80b3ffff, +0x80d3007f,0x98c6ff00,0x80f3ff80,0x81070080, +0xb6002018,0x10088020,0x0056b800,0x0442b806, +0xb4a00004,0xb0000000,0x0007b806,0xb4400001, +0x0007b807,0x0027b800,0x5c08b800,0x1400b804, +0xb0030001,0xb4000008,0x10288024,0x0056b801, +0x0442b806,0xb4a00004,0xb0010000,0x0027b806, +0xb4400001,0x0027b807,0x5828b801,0x1421b805, +0x1900a021,0x001f05d8,0x90000001,0x001f25d8, +0x00ffb81a,0x801702b8,0x80970438,0x81171800, +0x8087ffff,0x80b3ffff,0x80d3007f,0x98c6ff00, +0x80f3ff80,0x81070080,0xb6006018,0x10088020, +0x0056b800,0x0442b806,0xb4a00004,0xb0000000, +0x0007b806,0xb4400001,0x0007b807,0x0027b800, +0x5c08b800,0x1400b804,0xb0030001,0xb4000008, +0x10288024,0x0056b801,0x0442b806,0xb4a00004, +0xb0010000,0x0027b806,0xb4400001,0x0027b807, +0x5828b801,0x1421b805,0x1900a021,0x00ffb81a, +0x001f0081,0xb0000001,0xb4400006,0x001f05d8, +0xb0000003,0xb4000003,0x80270001,0x003f25dc, +0x00ffb81a,0x003f05d9,0x009f05cb,0xb0010000, +0xb400000e,0x015f42ed,0x81070000,0x8127017c, +0xb00a0000,0xb4000002,0x81070180,0x812702fc, +0x802500a5,0x9421ffff,0x3001b808,0xb4800011, +0x3001b809,0xb4a00079,0xb500000e,0x001f0081, +0xb0000001,0xb4400003,0xb0040002,0xb4200006, +0xb5000002,0xb0040000,0xb4200003,0x802702ff, +0x81470000,0xb5000003,0x80270001,0x003f25d9, +0x81470180,0xb0040000,0xb4200001,0x83840348, +0x80070000,0x001f25d8,0x009f902d,0x80af001f, +0x808f0000,0x806f0000,0x8007ffff,0x8033ffff, +0x80171800,0x807bff8c,0x94630003,0xb0030003, +0xb4000016,0xb0030002,0xb4000035,0xb0030001, +0xb4000024,0xb6006010,0x14618000,0x6068b803, +0x40c4b803,0x14608000,0x00c8b806,0x5870b803, +0x6068b803,0x4104b803,0x58c8b806,0x0108b808, +0x14c6b801,0x00000000,0x00000000,0x5d08b808, +0x1508b800,0x1806a028,0xb5000030,0xb6006010, +0x14618000,0x6068b803,0x40c4b803,0x14608000, +0x00c8b806,0x5870b803,0x6068b803,0x4104b803, +0x5cc8b806,0x0108b808,0x14c6b800,0x00000000, +0x00000000,0x5908b808,0x1508b801,0x1806a028, +0xb500001e,0xb600600d,0x14618000,0x6068b803, +0x40c4b803,0x00000000,0x00c8b806,0x00000000, +0x00000000,0x00000000,0x5d08b806,0x1508b800, +0x58c8b806,0x14c6b801,0x1806a028,0xb500000f, +0xb600600e,0x14608000,0x5868b803,0x6068b803, +0x40c4b803,0x00000000,0x00c8b806,0x00000000, +0x00000000,0x00000000,0x5d08b806,0x1508b800, +0x58c8b806,0x14c6b801,0x1806a028,0x80670600, +0x5d22b80a,0xb600030a,0x00cfb803,0x013fb178, +0x5922b809,0x01afb809,0x013f9178,0x0047b86f, +0xb0020001,0xb4c0fffd,0x90630020,0x91290020, +0x81270180,0xb00a0000,0xb4000001,0x81270000, +0x013f62ed,0x80270001,0x003f25dc,0x00ffb81a, +0x001f0081,0xb0000001,0xb4400006,0x001f05d8, +0xb0000003,0xb4000003,0x80270001,0x003f25dc, +0x00ffb81a,0x003f05d9,0x009f05cb,0xb0010000, +0xb400000e,0x015f42ed,0x81070000,0x8127017c, +0xb00a0000,0xb4000002,0x81070180,0x812702fc, +0x802500a5,0x9421ffff,0x3001b808,0xb4800011, +0x3001b809,0xb4a00079,0xb500000e,0x001f0081, +0xb0000001,0xb4400003,0xb0040002,0xb4200006, +0xb5000002,0xb0040000,0xb4200003,0x802702ff, +0x81470000,0xb5000003,0x80270001,0x003f25d9, +0x81470180,0xb0040000,0xb4200001,0x838402b4, +0x80070000,0x001f25d8,0x009f902d,0x80af001f, +0x808f0000,0x806f0000,0x8007ffff,0x8033ffff, +0x80171800,0x807bff8c,0x94630003,0xb0030003, +0xb4000016,0xb0030002,0xb4000035,0xb0030001, +0xb4000024,0xb6006010,0x14618000,0x6068b803, +0x40c4b803,0x14608000,0x00c8b806,0x5870b803, +0x6068b803,0x4104b803,0x58c8b806,0x0108b808, +0x14c6b801,0x00000000,0x00000000,0x5d08b808, +0x1508b800,0x1806a028,0xb5000030,0xb6006010, +0x14618000,0x6068b803,0x40c4b803,0x14608000, +0x00c8b806,0x5870b803,0x6068b803,0x4104b803, +0x5cc8b806,0x0108b808,0x14c6b800,0x00000000, +0x00000000,0x5908b808,0x1508b801,0x1806a028, +0xb500001e,0xb600600d,0x14618000,0x6068b803, +0x40c4b803,0x00000000,0x00c8b806,0x00000000, +0x00000000,0x00000000,0x5908b806,0x1508b801, +0x5cc8b806,0x14c6b800,0x1806a028,0xb500000f, +0xb600600e,0x14608000,0x5870b803,0x6068b803, +0x40c4b803,0x00000000,0x00c8b806,0x00000000, +0x00000000,0x00000000,0x5908b806,0x1508b801, +0x5cc8b806,0x14c6b800,0x1806a028,0x80670600, +0x5d22b80a,0xb600030a,0x00cfb803,0x013fb178, +0x5922b809,0x01afb809,0x013f9178,0x0047b86f, +0xb0020001,0xb4c0fffd,0x90630020,0x91290020, +0x81270180,0xb00a0000,0xb4000001,0x81270000, +0x013f62ed,0x80270001,0x003f25dc,0x00ffb81a, +0x029fb024,0x02bfb025,0x02dfb026,0x02ffb027, +0x031fb028,0x033fb029,0x033f4046,0x0287b86f, +0x029fb02a,0x8285009d,0x9a940008,0x8286009d, +0x8285009c,0x96b48000,0xb0158000,0xb40001b5, +0x96b40100,0xb0150100,0xb400020b,0x96b40400, +0xb0150400,0xb400020c,0x96b40001,0xb0150001, +0xb400000c,0x96b40008,0xb0150008,0xb40001ad, +0x96b44000,0xb0154000,0xb400020b,0x96b40002, +0xb0150002,0xb4000182,0x00000000,0x00000000, +0xb500021d,0x02bf917e,0x92b50001,0x02bfb17e, +0x82850082,0x96f40001,0xb0170000,0xb4000171, +0x5efdb814,0x96f70001,0xb0170001,0xb420000b, +0x83050069,0x9718003f,0x82e50064,0x12f7b818, +0x86f70109,0x82feff74,0x02e7b86f,0x9af74000, +0x01ffb817,0x96f7bfff,0x01ffb817,0x83050081, +0x82a5009a,0x96b50001,0xb0150001,0xb4200014, +0x82a70000,0x02bfb17e,0x96b41840,0xb0150800, +0xb420000c,0x96b40008,0x5aa9b815,0x96d46000, +0x5ec3b816,0x82f3000f,0x9af7c00f,0x1718b817, +0x1ab5b818,0x1ab5b816,0x9ab50340,0x82a60081, +0xb500014c,0x9b180180,0x83060081,0xb5000149, +0x82a5009a,0x96b50002,0xb0150002,0xb420001b, +0x82a70000,0x02bfb17e,0x96b41800,0xb0151800, +0xb4000013,0x96b40040,0xb0150040,0xb4200004, +0xa3180c00,0x9b180340,0x83060081,0xb5000139, +0x96b40008,0x5aa9b815,0x96d46000,0x5ec3b816, +0x82f3000f,0x9af7c00f,0x1718b817,0x1ab5b818, +0x1ab5b816,0x9ab50340,0x82a60081,0xb500012d, +0x9b180180,0x83060081,0xb500012a,0x82a500c1, +0x96b5000f,0xb015000b,0xb420000e,0x96b40020, +0xb0150020,0xb400000b,0x96b40200,0xb0150200, +0xb4000008,0x82c50086,0x82e50094,0x3016b817, +0xb4400004,0x06f7b816,0xb017ff00,0xb4400001, +0xb5000118,0x96b46000,0xb0156000,0xb4000011, +0x96b41820,0xb0150820,0xb4200004,0x9b391000, +0x82a5009a,0x96b5feff,0x82a6009a,0x96b40040, +0xb0150040,0xb4200001,0x9739efff,0x96b91000, +0xb0151000,0xb4200003,0x82a5009a,0x9ab50100, +0x82a6009a,0x96b40040,0xb0150040,0xb4200019, +0x96b41800,0xb0151800,0xb4200006,0x96b98000, +0xb0158000,0xb4200003,0x9b180180,0x83060081, +0xb50000f8,0x96d80c00,0x82b300ff,0x9ab5f3ff, +0x1718b815,0xb0160c00,0xb4000007,0x82e50098, +0x96f70400,0xb0170400,0xb4200002,0x82c70c00, +0xb5000001,0xa2d60c00,0x1b18b816,0x9b180340, +0xb50000c4,0x96b40220,0xb0150000,0xb4e00021, +0x82a5009d,0x82f3ffff,0x16b5b817,0x82f33800, +0x3015b817,0xb420001b,0x96f98000,0xb0178000, +0xb4000018,0x82a70000,0x02bfb17e,0x82c5009d, +0x96d6ffff,0x82b3c800,0x9ab58001,0x82e500c1, +0x96f7000f,0xb017000b,0xb4000002,0x82b38800, +0x9ab58001,0x1ab5b816,0x82c5009a,0x96d60020, +0xb0160020,0xb4200002,0x82b3c800,0x9ab58001, +0x82a6009d,0x02ff917e,0x00000000,0xb0170040, +0xb4800000,0x5eb5b814,0x96b500f0,0x96f46000, +0x5eedb817,0x1ab5b817,0xb0170003,0xb4000004, +0x96b500ef,0x96f70001,0x5ae4b817,0x1ab5b817, +0x96d41800,0xb0161800,0xb400000a,0x96f900ff, +0x96b500ff,0x9739ff00,0x1b39b815,0x02a7b817, +0x96b500f3,0x96d40008,0x5ec1b816,0x1ab5b816, +0xb500000c,0x96f98000,0xb0178000,0xb4200007, +0x5efeb814,0x96f70001,0xb0170001,0xb4000003, +0x9b180180,0x83060081,0xb50000a2,0x96b500f3, +0x9ab50008,0x9739fff3,0x96d40020,0xb0160020, +0xb4200019,0x82c7001f,0x82c600c9,0x9b398000, +0x82c70000,0x02dfb17e,0x96d40010,0x5ac8b816, +0x82f300ff,0x9af7cfff,0x1718b817,0x1b18b816, +0x9b180340,0x82c5009d,0x96d6ffff,0x82f33800, +0x9af78001,0x1af7b816,0x82c5009a,0x96d60020, +0xb0160020,0xb4200002,0x82f3c800,0x9af78001, +0x82e6009d,0xb500005f,0x97397fff,0x96b500ff, +0x5aaab815,0x82f300fc,0x9af703ff,0x1718b817, +0x1b18b815,0x9b180340,0x82c5009a,0x96d60010, +0xb0160010,0xb4200027,0x82c70000,0x02dfb17e, +0x82c50086,0x92d60e10,0x82c60086,0x82c50094, +0x5eefb818,0x96f70003,0xb0170003,0xb4200002, +0x82e70e10,0xb5000001,0x82e70e10,0x12d6b817, +0x82e50081,0x9af70020,0x82e60081,0x82c60094, +0xa2f70020,0x82e60081,0x82f30001,0x16f7b818, +0x5ef0b817,0xb0170001,0xb4000004,0x96f84000, +0x5ee4b817,0x9718f3ff,0x1b18b817,0x82f32800, +0x9af78000,0x82e6009d,0x83060081,0x83070001, +0x8306009f,0x8305009c,0xb0180001,0xb4e0fffb, +0xb50000f5,0x82c5009d,0x82f33800,0x9af78001, +0x3016b817,0xb420000f,0x82b3c800,0x9ab58001, +0x82e500c1,0x96f7000f,0xb017000b,0xb4000002, +0x82b38800,0x9ab58001,0x82c5009a,0x96d60020, +0xb0160020,0xb4200002,0x82b3c800,0x9ab58001, +0x82a6009d,0x82c5009a,0x96d60080,0xb0160080, +0xb4000013,0x02df917e,0x00000000,0xb0160010, +0xb480000f,0x82c500c1,0x96d6000f,0xb016000b, +0xb400000b,0x82c50087,0x96d60080,0x5ac7b816, +0x82c50098,0x96d60800,0x5ac3b816,0x96f84000, +0x3017b816,0xb4200002,0x033f4046,0x9b394000, +0x9739bfff,0x82e50061,0x96f70008,0xb0170008, +0xb4000005,0x5eefb818,0x96f70003,0xb0170003, +0xb4000001,0x9718ffff,0x96b41800,0xb0151800, +0xb4000008,0x5eb9b814,0x96b5000f,0x82c50099, +0x5ed0b816,0x96f6000f,0x5ab0b815,0x82a60099, +0xb5000002,0x5ef9b814,0x96f7000f,0x5aecb817, +0x82c5009a,0x96d60fff,0x1ad6b817,0x82c6009a, +0x96b46000,0xb0156000,0xb4200005,0x5ae2b817, +0x82d30ffc,0x9ad63fff,0x1718b816,0x1b18b817, +0x83060081,0x83070001,0x8306009f,0x8305009c, +0xb0180001,0xb4e0fffb,0x00000000,0xb500009e, +0x82850083,0x96b400ff,0xb015003c,0xb4200019, +0x96b92000,0xb0152000,0xb4000002,0x9b392000, +0xb5000014,0x9739d3ff,0x82870000,0x82860087, +0x82870008,0x82860083,0x829bff78,0x82a7001f, +0xb0140400,0xb4000001,0x82a70010,0x82a600c9, +0x829bff78,0x00000000,0x828600cb,0x8285009d, +0x82b3ffff,0x9ab5fffd,0x1694b815,0x8286009d, +0xb5000000,0x83070002,0x8306009f,0x00000000, +0xb500007d,0x83078000,0x8306009f,0x00000000, +0xb5000079,0x82850094,0x82a50086,0x06b5b814, +0x02b6b815,0xb0151700,0xb440004b,0x8285006c, +0x969400ff,0xb0140024,0xb4000019,0xb0140012, +0xb4000017,0x8285009a,0x5eedb814,0x96f70003, +0xb0170003,0xb4000009,0x82a50083,0x5ea8b815, +0x96b500ff,0xb0150020,0xb4400002,0x82c70bbc, +0xb5000001,0x82c70bb8,0xb5000008,0x82a50083, +0x5ea8b815,0x96b500ff,0xb0150020,0xb4400002, +0x82c71199,0xb5000001,0x82c71197,0xb5000016, +0x8285009a,0x5eedb814,0x96f70003,0xb0170003, +0xb4000009,0x82a50083,0x5ea8b815,0x96b500ff, +0xb0150020,0xb4400002,0x82c70e18,0xb5000001, +0x82c70e04,0xb5000008,0x82a50083,0x5ea8b815, +0x96b500ff,0xb0150020,0xb4400002,0x82c70e18, +0xb5000001,0x82c70e04,0x82e50086,0x12f7b816, +0x02bf917e,0xb0150020,0xb480000b,0x82a5009a, +0x96b56000,0xb0156000,0xb4000007,0x82a50098, +0x96d50a00,0xb0160a00,0xb4000002,0xb0160000, +0xb4200001,0x92f70704,0x82850081,0x9ab40020, +0x82a60081,0x82c50094,0x82e60094,0x82860081, +0x86b70704,0x82a6009b,0x83070008,0x8306009f, +0x00000000,0xb5000024,0x83070100,0x8306009f, +0x00000000,0xb5000020,0x83070000,0x83050081, +0x9b180180,0x83060081,0x83070400,0x8306009f, +0x00000000,0xb5000018,0x82870000,0x82850082, +0x5eb7b814,0x96b500fc,0x96d40006,0x5ec1b816, +0x1ab5b816,0x5aacb815,0x83050081,0x82d3001c, +0x9ad600ff,0x1718b816,0x1b18b815,0x9b180e00, +0x83060081,0x83074000,0x8306009f,0x8305009d, +0x82d3ffff,0x9ad6bfff,0x1718b816,0x8306009d, +0x00000000,0xb5000000,0x029f902a,0x01ffb814, +0x033f6046,0x029f9024,0x02bf9025,0x02df9026, +0x02ff9027,0x031f9028,0x033f9029,0x00ffb81e, +0x02ff917d,0x92f7092f,0x031f0084,0xb0180001, +0xb4200002,0x02ff917d,0x92f70870,0x02ffb17d, +0x02ff917c,0x82bbffdc,0x829bffd8,0x93150004, +0x3014b815,0xb4000017,0x02dbb818,0x029bb815, +0x3017b816,0xb4800013,0x5a81b814,0x029fb17d, +0x82def200,0x82fef204,0x82e50086,0x06f7b814, +0x02f6b817,0x82fef208,0x82860095,0x82870001, +0x829ef220,0x8293001f,0x9294fe00,0x92b50008, +0x3015b814,0xb4800002,0x82b3001f,0x92b5fa00, +0x82beffdc,0x82850086,0x83250094,0x06d4b819, +0x02d6b816,0xb016ffff,0xb4a00009,0x82c50081, +0x9ab60020,0x82a60081,0x82a50086,0x92b50e10, +0x82a60094,0x82c60081,0x86b50704,0x82a6009b, +0x00ffb81c,0x00000000,0x00000000,0x00000000, +0x001f9012,0x001fb200,0x001f004c,0x001f2804, +0x801bfef0,0x8058fef4,0x803bff68,0x8078ff6c, +0x2000b801,0x2042b803,0x001fb204,0x005f2814, +0x82e70001,0x83640048,0x029fb014,0x829efef0, +0x8286000f,0x02bf2054,0x82bcfef4,0x82a6000e, +0x00ffb81a,0x80e70001,0x801336e3,0x9800eb76, +0x001fb200,0x800700ab,0x001f2804,0x801bc3e8, +0x8058c3ec,0x83640024,0x82e70000,0x83640036, +0x029fb3c0,0x029fb200,0x02bf2f04,0x02bf2804, +0x801bc000,0x8058c004,0x8364001b,0x82e70000, +0x8364002d,0x001f93c0,0x3000b814,0xb420000a, +0x001f0f04,0x3000b815,0xb4200007,0x829efef0, +0x82bcfef4,0x029fb012,0x02bf204c,0x82870001, +0x829cfef5,0x00ffb81a,0xb0070000,0xb4000007, +0x80e70000,0x801399fa,0x9800c92e,0x001fb200, +0x800700af,0x001f2804,0xb500ffdc,0x82870000, +0x829cfef5,0x00ffb81a,0x80c700ff,0x803bff68, +0x8078ff6c,0x14a0b806,0x2063b805,0x007f2814, +0x2021b802,0x58c8b806,0x14a0b806,0x58b0b805, +0x2021b805,0x58c8b806,0x14a0b806,0x2021b805, +0x58c8b806,0x14a0b806,0x5cb0b805,0x2021b805, +0x003fb204,0x00ffb81b,0x82c70000,0x83070800, +0x83270005,0x8197080c,0x81d7ffff,0x83840126, +0x83840001,0x00ffb81b,0x808f0000,0x806f001f, +0x80af001f,0x80270240,0x81e77c08,0x5de2b80f, +0xb6000208,0x00cfb801,0x01ffb178,0x59e2b80f, +0x01cfb80f,0x01ff9178,0xb520ffff,0x91ef0020, +0x90210020,0x80270280,0x81e77b00,0x5de2b80f, +0xb6000208,0x00cfb801,0x01ffb178,0x59e2b80f, +0x01cfb80f,0x01ff9178,0xb520ffff,0x91ef0020, +0x90210020,0x8057ffff,0x80170830,0x80070810, +0x80270808,0xb6000509,0x005ff000,0x90420900, +0x007ff001,0x90630a00,0x009ff002,0x00bff003, +0x2004a025,0x90000001,0x90210001,0x80070814, +0x80d7ffff,0x8097085c,0x8017083c,0xb6000404, +0x005ff000,0x007f87e0,0x84000001,0x2082a7e3, +0x80970860,0x80170840,0x2082b803,0x007f8000, +0x2083a004,0x80170830,0x80970850,0x80270808, +0xb6000508,0x005f8024,0x90420900,0x007ff001, +0x90630a00,0x009ff002,0x00bff003,0x2004a025, +0x90210001,0x80170840,0x00000000,0x02bf87e0, +0x80970860,0x82870000,0xb6000404,0x005f87e4, +0x5a88b814,0x204287e0,0x1a94b802,0x00ffb81c, +0x001f0e49,0x001f2b09,0x001f0e41,0x001f2b08, +0x001f0e46,0x001f2b07,0x001f0e48,0x001f2b06, +0x001f0e42,0x001f2b05,0x001f0e47,0x001f2b04, +0x001f0e45,0x001f2b03,0x001f0e43,0x001f2b02, +0x001f0e40,0x001f2b01,0x001f0e44,0x001f2b00, +0x001f0f25,0xa020000c,0x94400001,0x94600002, +0x94810004,0x94a10008,0x94c00010,0x5943b802, +0x5861b803,0x5882b804,0x5ca2b805,0x5cc4b806, +0x194ab803,0x194ab804,0x194ab805,0x194ab806, +0x015f2b38,0x801b7c00,0x003f92c1,0x5c28b801, +0x005f92c2,0x5858b802,0x1821b802,0x2000b801, +0x001fb2c4,0x80187c04,0x003f0b09,0x2000b801, +0x001f2b14,0x82c70001,0x82e70001,0x83070b10, +0x8327001e,0x81970b35,0x8384009f,0x02df0b38, +0x82170e30,0x838400f1,0x819efef0,0x817cfef4, +0x819eff68,0x817cff6c,0x00ffb81b,0x820f001f, +0x8018fef8,0x8057ffff,0x001f2b09,0x8018fef6, +0x80d7ffff,0x001f2b08,0x8018fefa,0x8157ffff, +0x001f2b07,0x8018fefd,0x81d7ffff,0x001f2b06, +0x8018fefb,0x802f001f,0x001f2b05,0x8018fefe, +0x00000000,0x001f2b04,0x8018fef9,0x00000000, +0x001f2b03,0x8018feff,0x00000000,0x001f2b02, +0x8018fef7,0x00000000,0x001f2b01,0x8018fefc, +0x00000000,0x001f2b00,0x001f0f25,0xa0200011, +0x94410001,0x94600002,0x94800004,0x94a00008, +0x94c10010,0x5941b802,0x5861b803,0x5c82b804, +0x58a1b805,0x5cc1b806,0x194ab803,0x194ab804, +0x194ab805,0x194ab806,0x015f2b38,0x801b7c00, +0x003f92c1,0x5c28b801,0x005f92c2,0x5858b802, +0x1821b802,0x2000b801,0x001fb2c4,0x80187c04, +0x003f0b09,0x2000b801,0x001f2b14,0x82c70001, +0x82e70001,0x83070b10,0x8327001e,0x81970b35, +0x83840055,0x02df0b38,0x82170e20,0x838400a7, +0x819efef0,0x817cfef4,0x5ac8b80c,0x02ff0e44, +0x1ad6b817,0x02dfb391,0x5ed8b80c,0x5968b80b, +0x1ad6b80b,0x02df6724,0x00ffb81b,0x820f001f, +0x8018fefe,0x8057ffff,0x001f2b09,0x8018fefa, +0x80d7ffff,0x001f2b08,0x8018fefc,0x8157ffff, +0x001f2b07,0x8018feff,0x81d7ffff,0x001f2b06, +0x8018fef8,0x802f001f,0x001f2b05,0x8018fefb, +0x00000000,0x001f2b04,0x8018fefd,0x00000000, +0x001f2b03,0x8018fef6,0x00000000,0x001f2b02, +0x8018fef9,0x00000000,0x001f2b01,0x8018fef7, +0x00000000,0x001f2b00,0x801b7c00,0x003f92c1, +0x5c28b801,0x005f92c2,0x5858b802,0x1821b802, +0x2000b801,0x001fb2c4,0x80187c04,0x003f0b09, +0x2000b801,0x001f2b14,0x82c70001,0x82e70001, +0x83070b10,0x8327001e,0x81970b35,0x83840016, +0x83270000,0x831bfef0,0x82f8fef4,0x02c7b819, +0x82170e28,0x83840065,0x300cb818,0xb4200002, +0x300bb817,0xb4000006,0x93390001,0xb0190020, +0xb480fff6,0x83270000,0x833cfef5,0x00ffb81b, +0x019fb390,0x017f2e44,0x033f2f25,0x83270001, +0x833cfef5,0x00ffb81b,0x0007b818,0x90000003, +0x00000000,0x015ff000,0x90000001,0x5949b80a, +0x013ff000,0x194ab809,0x84000002,0x994a0100, +0x017ff000,0x958b00f8,0x5981b80c,0x956b0007, +0x198cb80b,0x84000002,0x998c0008,0x017ff000, +0x90000001,0x5971b80b,0x198cb80b,0x017ff000, +0x5969b80b,0x198cb80b,0x81a70000,0x94d90003, +0x82a70000,0xb6260019,0xb6000818,0x5df0b80a, +0x5e02b80a,0x21efb810,0x95ef0001,0x5941b80a, +0x194ab80f,0x21efb816,0x5e18b80c,0x5e35b80c, +0x5e54b80c,0x5e6cb80c,0x2210b811,0x2252b813, +0x2210b812,0x96100001,0x5981b80c,0x198cb810, +0x2210b817,0x10afb810,0x10a5b80d,0x5da1b805, +0x94a50001,0x5aa1b815,0x1ab5b805,0x019fa7f5, +0x5cc2b819,0xb626001c,0x82870000,0xb6000419, +0xb6000818,0x5df0b80a,0x5e02b80a,0x21efb810, +0x95ef0001,0x5941b80a,0x194ab80f,0x21efb816, +0x5e18b80c,0x5e35b80c,0x5e54b80c,0x5e6cb80c, +0x2210b811,0x2252b813,0x2210b812,0x96100001, +0x5981b80c,0x198cb810,0x2210b817,0x10afb810, +0x10a5b80d,0x5da1b805,0x94a50001,0x5a81b814, +0x1a94b805,0x019fa7f4,0x00ffb81c,0x8257ffff, +0x808f0000,0x806f001f,0x80af001f,0x80270300, +0x81e778e0,0x5de2b80f,0xb6000208,0x00cfb801, +0x01ffb178,0x59e2b80f,0x01cfb80f,0x01ff9178, +0xb520ffff,0x91ef0020,0x90210020,0x80270340, +0x81e779e0,0x5de2b80f,0xb6000208,0x00cfb801, +0x01ffb178,0x59e2b80f,0x01cfb80f,0x01ff9178, +0xb520ffff,0x91ef0020,0x90210020,0x80270280, +0x81e77b00,0x5de2b80f,0xb6000208,0x00cfb801, +0x01ffb178,0x59e2b80f,0x01cfb80f,0x01ff9178, +0xb520ffff,0x91ef0020,0x90210020,0x806f0007, +0x80af0007,0x80270380,0x81e77ae0,0x5de2b80f, +0x00cfb801,0x01ffb178,0x59e2b80f,0x01cfb80f, +0x01ff9178,0xb520ffff,0x91ef0020,0x90210020, +0x80170b60,0x001f0b00,0x001fa020,0x001f0b01, +0x001fa020,0x001f0b02,0x001fa020,0x001f0b03, +0x001fa020,0x001f0b04,0x001fa000,0x80970b50, +0x81170b70,0x82a70b35,0x83a40060,0x001f87e4, +0xb6000405,0x86b50001,0x83a4005c,0x001f8004, +0x003f87e8,0x2080a7e1,0x80970b70,0x80170b50, +0x81170b50,0x81970b40,0x82a70b30,0x001f800c, +0x003f8008,0x2100a001,0x83a40050,0x001f87e4, +0xb6000405,0x86b50001,0x83a4004c,0x001f8004, +0x003f87e8,0x2080a7e1,0x80970b50,0x80170b70, +0x81170b70,0x81970b60,0x82a70b2b,0x001f800c, +0x003f8008,0x2100a001,0x83a40040,0x83a4004e, +0xb6000407,0x86b50001,0x83a4003c,0x001f8004, +0x003f87e8,0x2080a001,0x83a40047,0x00000000, +0x80970b70,0x80170b50,0x81170b50,0x81970b40, +0x82a70b26,0x001f800c,0x003f8008,0x2100a001, +0x83a4002e,0x83a4003c,0xb6000407,0x86b50001, +0x83a4002a,0x001f8004,0x003f87e8,0x2080a001, +0x83a40035,0x00000000,0x80970b50,0x80170b70, +0x81170b70,0x81970b60,0x82a70b21,0x001f800c, +0x003f8008,0x2100a001,0x83a4001c,0x001f87e4, +0xb6000405,0x86b50001,0x83a40018,0x001f8004, +0x003f87e8,0x2080a7e1,0x80970b70,0x80170b50, +0x81170b50,0x81970b40,0x82a70b1c,0x001f800c, +0x003f8008,0x2100a001,0x83a4000c,0x017f87e4, +0x81870000,0xb6000406,0x86b50001,0x83a40007, +0x001f87e4,0x200087e8,0x5988b80c,0x198cb800, +0x021fa02c,0x021fa00b,0x00ffb81c,0x005ff015, +0x90420a00,0x003f87e0,0x001ff002,0x2060b801, +0x90630c00,0x90960e00,0x001ff003,0x003ff004, +0x20a0b801,0x90a50d00,0x00000000,0x001ff005, +0x009fa000,0x00ffb81d,0x001f8004,0x5c21b800, +0x5847b800,0x1821b802,0x942100ff,0x2080a7e1, +0x00ffb81d,0x00000000,0x00000000,0x00000000, + +}; + +static u32 MPG240Ucode1f5c00[] = { +0x00000000,0xfffff8c0,0x00003540,0xffff8d40, +0x0001fd40,0xfffaf7c0,0x00066b80,0xffdb63c0, +0x00494780,0x00249c40,0x00066b80,0x00050840, +0x0001fd40,0x000072c0,0x00003540,0x00000740, +0xffffffc0,0xfffff840,0x00003680,0xffff7e40, +0x0001f400,0xfffa9cc0,0x0005d1c0,0xffd99600, +0x00493c00,0x0022ce00,0x0006f780,0x0004ad00, +0x000203c0,0x00006440,0x00003400,0x00000680, +0xffffffc0,0xfffff740,0x00003780,0xffff6ec0, +0x0001e800,0xfffa4240,0x00052a00,0xffd7ca00, +0x00491a00,0x0020ffc0,0x00077600,0x00045240, +0x00020800,0x000056c0,0x00003280,0x00000600, +0xffffffc0,0xfffff680,0x00003840,0xffff5ec0, +0x0001d940,0xfff9e8c0,0x00047440,0xffd60080, +0x0048e180,0x001f32c0,0x0007e700,0x0003f7c0, +0x000209c0,0x00004980,0x00003100,0x00000540, +0xffffffc0,0xfffff5c0,0x000038c0,0xffff4e40, +0x0001c780,0xfff990c0,0x0003b000,0xffd43ac0, +0x00489240,0x001d6800,0x00084b00,0x00039e40, +0x00020940,0x00003d00,0x00002f80,0x000004c0, +0xffffffc0,0xfffff4c0,0x00003900,0xffff3d40, +0x0001b2c0,0xfff93a40,0x0002ddc0,0xffd279c0, +0x00482d00,0x001ba040,0x0008a200,0x000345c0, +0x000206c0,0x00003140,0x00002dc0,0x00000440, +0xffffffc0,0xfffff3c0,0x00003900,0xffff2c00, +0x00019b00,0xfff8e640,0x0001fd40,0xffd0be80, +0x0047b1c0,0x0019dc80,0x0008ecc0,0x0002ef00, +0x00020240,0x00002640,0x00002c00,0x00000400, +0xffffff80,0xfffff2c0,0x000038c0,0xffff1a40, +0x00017fc0,0xfff894c0,0x00010e80,0xffcf09c0, +0x004720c0,0x00181d80,0x00092b40,0x000299c0, +0x0001fc00,0x00001bc0,0x00002a40,0x00000380, +0xffffff80,0xfffff180,0x00003800,0xffff0840, +0x00016180,0xfff84680,0x00001180,0xffcd5cc0, +0x00467a40,0x00166440,0x00095e00,0x00024680, +0x0001f440,0x00001200,0x00002840,0x00000340, +0xffffff80,0xfffff040,0x00003740,0xfffef600, +0x00014000,0xfff7fbc0,0xffff0680,0xffcbb880, +0x0045bf00,0x0014b140,0x00098580,0x0001f580, +0x0001ea80,0x00000900,0x00002680,0x000002c0, +0xffffff80,0xffffef00,0x000035c0,0xfffee3c0, +0x00011ac0,0xfff7b540,0xfffded80,0xffca1d80, +0x0044ef80,0x00130580,0x0009a1c0,0x0001a700, +0x0001dfc0,0x00000080,0x000024c0,0x00000280, +0xffffff40,0xffffedc0,0x00003400,0xfffed180, +0x0000f280,0xfff77340,0xfffcc700,0xffc88d80, +0x00440bc0,0x001161c0,0x0009b3c0,0x00015b00, +0x0001d380,0xfffff8c0,0x000022c0,0x00000240, +0xffffff40,0xffffec40,0x00003200,0xfffebf40, +0x0000c680,0xfff73680,0xfffb92c0,0xffc708c0, +0x00431500,0x000fc6c0,0x0009bb80,0x000111c0, +0x0001c640,0xfffff1c0,0x00002100,0x00000200, +0xffffff00,0xffffeac0,0x00002f40,0xfffead00, +0x00009740,0xfff6ff40,0xfffa5180,0xffc59080, +0x00420b40,0x000e3500,0x0009b9c0,0x0000cb80, +0x0001b7c0,0xffffeb40,0x00001f40,0x000001c0, +0xffffff00,0xffffe940,0x00002c40,0xfffe9b00, +0x00006480,0xfff6ce00,0xfff90380,0xffc425c0, +0x0040ef80,0x000cad00,0x0009af00,0x00008840, +0x0001a880,0xffffe580,0x00001d40,0x000001c0, +0xfffffec0,0xffffe7c0,0x000028c0,0xfffe8980, +0x00002e40,0xfff6a3c0,0xfff7a900,0xffc2c900, +0x003fc280,0x000b2fc0,0x00099b80,0x00004800, +0x00019880,0xffffe040,0x00001bc0,0x00000180, +0xfffffec0,0xffffe600,0x00002480,0xfffe7840, +0xfffff4c0,0xfff68040,0xfff64240,0xffc17b40, +0x003e84c0,0x0009bdc0,0x00097fc0,0x00000b40, +0x000187c0,0xffffdb80,0x00001a00,0x00000140, +0xfffffe80,0xffffe440,0x00001fc0,0xfffe6780, +0xffffb800,0xfff66480,0xfff4d040,0xffc03d80, +0x003d3700,0x00085700,0x00095c40,0xffffd1c0, +0x00017680,0xffffd740,0x00001840,0x00000140, +0xfffffe40,0xffffe2c0,0x00001a80,0xfffe5780, +0xffff77c0,0xfff65100,0xfff35300,0xffbf1080, +0x003bda40,0x0006fc80,0x00093200,0xffff9b80, +0x00016500,0xffffd3c0,0x000016c0,0x00000100, +0xfffffe40,0xffffe0c0,0x000014c0,0xfffe4840, +0xffff3480,0xfff64640,0xfff1cb00,0xffbdf4c0, +0x003a6f80,0x0005ae80,0x000900c0,0xffff68c0, +0x00015300,0xffffd0c0,0x00001540,0x00000100, +0xfffffe00,0xffffdf00,0x00000e40,0xfffe39c0, +0xfffeee40,0xfff64480,0xfff03940,0xffbceb00, +0x0038f740,0x00046d40,0x0008c980,0xffff3980, +0x000140c0,0xffffce00,0x000013c0,0x000000c0, +0xfffffdc0,0xffffdd40,0x00000740,0xfffe2c80, +0xfffea500,0xfff64c40,0xffee9e40,0xffbbf440, +0x00377280,0x00033900,0x00088cc0,0xffff0d80, +0x00012e80,0xffffcc00,0x00001240,0x000000c0, +0xfffffd80,0xffffdb40,0xffffff80,0xfffe2040, +0xfffe5900,0xfff65e40,0xffecfa80,0xffbb1080, +0x0035e280,0x00021280,0x00084ac0,0xfffee540, +0x00011c40,0xffffca40,0x00001100,0x00000080, +0xfffffd40,0xffffd980,0xfffff700,0xfffe1580, +0xfffe0a80,0xfff67a80,0xffeb4ec0,0xffba4100, +0x00344780,0x0000f980,0x00080440,0xfffec000, +0x00010a00,0xffffc8c0,0x00000fc0,0x00000080, +0xfffffcc0,0xffffd7c0,0xffffee00,0xfffe0bc0, +0xfffdb980,0xfff6a200,0xffe99bc0,0xffb985c0, +0x0032a340,0xffffee80,0x0007b980,0xfffe9e80, +0x0000f7c0,0xffffc800,0x00000e80,0x00000080, +0xfffffc80,0xffffd5c0,0xffffe440,0xfffe0400, +0xfffd6640,0xfff6d4c0,0xffe7e280,0xffb8df40, +0x0030f640,0xfffef180,0x00076b40,0xfffe8040, +0x0000e5c0,0xffffc740,0x00000d40,0x00000080, +0xfffffc00,0xffffd400,0xffffd9c0,0xfffdfdc0, +0xfffd1100,0xfff71340,0xffe62380,0xffb84e40, +0x002f4180,0xfffe02c0,0x000719c0,0xfffe6500, +0x0000d400,0xffffc700,0x00000c40,0x00000040, +0xfffffbc0,0xffffd240,0xffffcec0,0xfffdf940, +0xfffcba40,0xfff75e00,0xffe45fc0,0xffb7d300, +0x002d8640,0xfffd2240,0x0006c5c0,0xfffe4d40, +0x0000c2c0,0xffffc700,0x00000b40,0x00000040, +0xfffffb40,0xffffd080,0xffffc300,0xfffdf6c0, +0xfffc61c0,0xfff7b500,0xffe29800,0xffb76dc0, +0x002bc540,0xfffc5000,0x00066f40,0xfffe3880, +0x0000b1c0,0xffffc740,0x00000a40,0x00000040, +0xfffffac0,0xffffcf00,0xffffb680,0xfffdf640, +0xfffc0840,0xfff81900,0xffe0cd40,0xffb71e80, +0x0029ff80,0xfffb8bc0,0x00061740,0xfffe26c0, +0x0000a140,0xffffc7c0,0x00000980,0x00000040, +0xfffffa00,0xffffcd80,0xffffa940,0xfffdf800, +0xfffbadc0,0xfff88a00,0xffdf0040,0xffb6e600, +0x00283600,0xfffad600,0x0005bdc0,0xfffe1800, +0x00009140,0xffffc880,0x000008c0,0x00000040, +0xfffff980,0xffffcc00,0xffff9bc0,0xfffdfc40, +0xfffb5300,0xfff90880,0xffdd3200,0xffb6c400, +0x00266a00,0xfffa2e40,0x00056340,0xfffe0c00, +0x000081c0,0xffffc980,0x000007c0,0x00000040, +0x004013c2,0x0040b346,0x0041fa2d,0x0043f934, +0x0046cc1c,0x004a9d9d,0x004fae37,0x0056601f, +0x005f4cf7,0x006b6fcf,0x007c7d1e,0x0115b035, +0x013df91b,0x0207655e,0x03342c83,0x0a185230, +0x00404f46,0x0042e13c,0x0048919f,0x0052cb0e, +0x0064e240,0x0107c449,0x015c7926,0x050cf270, +0x004140fb,0x004cf8df,0x0073326c,0x02480d9d, +0x004545ea,0x01273d75,0x005a827a,0x007fffff, +0x006597fb,0x0050a28c,0x00400000,0x0032cbfd, +0x00285146,0x00200000,0x001965ff,0x001428a3, +0x00100000,0x000cb2ff,0x000a1451,0x00080000, +0x00065980,0x00050a29,0x00040000,0x00032cc0, +0x00028514,0x00020000,0x00019660,0x0001428a, +0x00010000,0x0000cb30,0x0000a145,0x00008000, +0x00006598,0x000050a3,0x00004000,0x000032cc, +0x00002851,0x00002000,0x00001966,0x00001429, +0x00001000,0x00000cb3,0x00000a14,0x00000800, +0x00000659,0x0000050a,0x00000400,0x0000032d, +0x00000285,0x00000200,0x00000196,0x00000143, +0x00000100,0x000000cb,0x000000a1,0x00000080, +0x00000066,0x00000051,0x00000040,0x00000033, +0x00000028,0x00000020,0x00000019,0x00000014, +0x00000010,0x0000000d,0x0000000a,0x00000008, +0x00000006,0x00000005,0x00000000,0x00555555, +0x00666666,0x00492492,0x0071c71c,0x00444444, +0x00421084,0x00410410,0x00408102,0x00404040, +0x00402010,0x00401004,0x00400801,0x00400400, +0x00400200,0x00400100,0x00400080,0x00400040, +0x00400000,0x00400000,0x00200000,0x00400000, +0x00100000,0x00080000,0x00040000,0x00020000, +0x00010000,0x00008000,0x00004000,0x00002000, +0x00001000,0x00000800,0x00000400,0x00000200, +0x00000100,0x0003588d,0x0002b15e,0x0002056d, +0x00015600,0x0000a329,0xffffeed9,0xffff3960, +0xfffe8423,0xfffdd11c,0xfffd2048,0xfffc7353, +0xfffbcb6f,0xfffb29a6,0xfffa8f15,0x000494ae, +0x0003f991,0x00032dd1,0xfffd2d8f,0x0001eb47, +0xfffe9968,0x00009af6,0x000011de,0xffff4335, +0x00018d69,0xfffdecd4,0x000302f8,0xfffca0d7, +0x0004683d,0xfffb67f8,0x0005b36d,0x00045963, +0xfffbd51e,0x00030062,0xfffd0dee,0x0001d046, +0xfffe8a0a,0x00009258,0x000012b1,0xffff4d9e, +0x00019ec3,0xfffe0a44,0x0003245a,0xfffcd082, +0x000498f0,0xfffba919,0x0005f304,0x00041bf4, +0xfffba72a,0x0002d19e,0xfffcf060,0x0001b407, +0xfffe7c08,0x0000894a,0x0000138d,0xffff58ac, +0x0001afaf,0xfffe28fe,0x000343bf,0xfffd026f, +0x0004c6f6,0xfffbed06,0x00062e61,0x0003dc0e, +0xfffb7bf1,0x0002a17f,0xfffcd522,0x000196a0, +0xfffe6e70,0x00007ff6,0x00001439,0xffff63f6, +0x0001beb3,0xfffe4882,0x0003616d,0xfffd361b, +0x0004f1cf,0xfffc332a,0x0006658f,0x00039943, +0xfffb52c0,0x00026ec7,0xfffcbb94,0x0001789f, +0xfffe6160,0x00007677,0x000014d4,0xffff6f74, +0x0001cc9b,0xfffe694f,0x00037cbf,0xfffd6b41, +0x000519c2,0xfffc7baf,0x00069971,0x00035486, +0xfffb2d0c,0x00023ad8,0xfffca3ee,0x00015989, +0xfffe55af,0x00006ca7,0x00001570,0xffff7b71, +0x0001d9cb,0xfffe8b46,0x0003959e,0xfffda1fe, +0x00053ee6,0xfffcc6b4,0x0006c950,0x00030e08, +0xfffb0a7a,0x0002061e,0xfffc8ec0,0x00013911, +0xfffe4b1d,0x00006278,0x000015e8,0xffff87b6, +0x0001e577,0xfffeadd6,0x0003acc2,0xfffdda34, +0x00056059,0xfffd136d,0x0006f4b5,0x0002c562, +0xfffaea7c,0x0001cfa6,0xfffc7b14,0x0001182b, +0xfffe4159,0x00005817,0x0000165c,0xffff9417, +0x0001f00f,0xfffed14c,0x0003c199,0xfffe13f6, +0x00057e83,0xfffd61cd,0x00071ba1,0x00027ab5, +0xfffacdc3,0x00019833,0xfffc6989,0x0000f6ca, +0xfffe38da,0x00004d9d,0x000016ef,0xffffa103, +0x0001f98f,0xfffef5c0,0x0003d3d1,0xfffe4f00, +0x0005998c,0xfffdb21e,0x00073e77,0x00022e75, +0xfffab482,0x00015fd1,0xfffc5b13,0x0000d45d, +0xfffe318f,0x000042ed,0x0000176b,0xffffae8f, +0x0002018f,0xffff1a91,0x0003e40c,0xfffe8af2, +0x0005b0ca,0xfffe03b8,0x00075d14,0x0001e141, +0xfffa9e9b,0x0001262a,0xfffc4e31,0x0000b1af, +0xfffe2b26,0x00003805,0x000017b1,0xffffbc21, +0x000208b8,0xffff3fb6,0x0003f1d7,0xfffec7af, +0x0005c4c5,0xfffe5654,0x0007768a,0x000192fe, +0xfffa8bb0,0x0000ec3f,0xfffc4365,0x00008ec9, +0xfffe25f0,0x00002d05,0x000017ec,0xffffc984, +0x00020ec6,0xffff658d,0x0003fcba,0xffff0500, +0x0005d576,0xfffeaa37,0x00078bc6,0x00014367, +0xfffa7bec,0x0000b1f4,0xfffc3b82,0x00006b06, +0xfffe2201,0x000021eb,0x00001823,0xffffd704, +0x0002132a,0xffff8be7,0x00040534,0xffff4315, +0x0005e22e,0xfffeff0a,0x00079ce3,0x0000f33f, +0xfffa6fc9,0x000076ca,0xfffc3558,0x00004762, +0xfffe1ef3,0x000016a1,0x0000183f,0xffffe4a6, +0x00021664,0xffffb27d,0x00040b7b,0xffff81e5, +0x0005eb4e,0xffff5475,0x0007a857,0x0000a2cb, +0xfffa671b,0x00003b64,0xfffc31e2,0x00002416, +0xfffe1ce1,0x00000b46,0x00001850,0xfffff24d, +0x00021855,0xffffd93a,0x00040f75,0xffffc0e6, +0x0005f0e3,0xffffaa3e,0x0007af45,0x0000519f, +0xfffa6218,0x0003f991,0x0003588d,0x0002b15e, +0x0002056d,0x00015600,0x0000a329,0xffffeed9, +0xffff3960,0xfffe8423,0xfffdd11c,0xfffd2048, +0xfffc7353,0xfffbcb6f,0xfffb29a6,0xfffa8f15, +0x000494ae,0x0003c6b0,0xfffc7e8b,0x00028ef6, +0xfffde181,0x000144eb,0xffff5500,0xffffefb9, +0x0000d01d,0xfffe9755,0x000249a4,0xfffd453c, +0x0003b80e,0xfffc01aa,0x000511d6,0xfffad527, +0xfffb334e,0x0003916c,0xfffc5778,0x00026a92, +0xfffdc9f5,0x00013314,0xffff4d99,0xfffff0b6, +0x0000d911,0xfffeab80,0x00026369,0xfffd6c0a, +0x0003e17f,0xfffc39d8,0x000549df,0xfffb1eb2, +0xfffafe6c,0x00035929,0xfffc3321,0x000244a6, +0xfffdb402,0x00012035,0xffff46ac,0xfffff192, +0x0000e16a,0xfffebfe0,0x00027b3d,0xfffd9433, +0x0004087b,0xfffc74b7,0x00057e8d,0xfffb6a81, +0xfffacc1c,0x00031fbe,0xfffc10df,0x00021e0c, +0xfffd9f6d,0x00010cb7,0xffff402e,0xfffff279, +0x0000e965,0xfffed574,0x00029159,0xfffdbdc4, +0x00042c4c,0xfffcb1e7,0x0005b02d,0xfffbb942, +0xfffa9d38,0x0002e44a,0xfffbf0fd,0x0001f5b4, +0xfffd8c38,0x0000f8b1,0xffff3a21,0xfffff391, +0x0000f0e6,0xfffeec44,0x0002a642,0xfffde90e, +0x00044e32,0xfffcf0fb,0x0005de46,0xfffc0b18, +0xfffa71d1,0x0002a659,0xfffbd3de,0x0001cb90, +0xfffd7a97,0x0000e403,0xffff3490,0xfffff49c, +0x0000f7a8,0xffff0340,0x0002b95f,0xfffe1573, +0x00046dbe,0xfffd3284,0x00060888,0xfffc5f51, +0xfffa4996,0x00026786,0xfffbb8df,0x0001a0e1, +0xfffd6a4e,0x0000ced2,0xffff2f75,0xfffff593, +0x0000fdbe,0xffff1a53,0x0002ca87,0xfffe42f5, +0x0004898a,0xfffd7563,0x00062f0b,0xfffcb5de, +0xfffa2508,0x00022713,0xfffba0bf,0x0001754a, +0xfffd5b5f,0x0000b92c,0xffff2acd,0xfffff6b0, +0x0001034f,0xffff3241,0x0002da5c,0xfffe71c6, +0x0004a341,0xfffdb946,0x000651e8,0xfffd0e37, +0xfffa0402,0x0001e4d4,0xfffb8b9c,0x00014898, +0xfffd4e7d,0x0000a304,0xffff26b7,0xfffff7e1, +0x00010846,0xffff4b34,0x0002e897,0xfffea13f, +0x0004ba63,0xfffdff2d,0x00067115,0xfffd6839, +0xfff9e680,0x0001a1fa,0xfffb789e,0x00011b2e, +0xfffd43a4,0x00008c6e,0xffff2341,0xfffff8fd, +0x00010c9c,0xffff6469,0x0002f48f,0xfffed1a4, +0x0004cd6a,0xfffe4608,0x00068c1b,0xfffdc409, +0xfff9cd15,0x00015dfe,0xfffb68a0,0x0000ecee, +0xfffd3a2e,0x0000757d,0xffff204b,0xfffffa1e, +0x00011054,0xffff7da1,0x0002fe9c,0xffff033e, +0x0004de57,0xfffe8dc6,0x0006a2d5,0xfffe213e, +0xfff9b77d,0x000118d3,0xfffb5bde,0x0000be25, +0xfffd3224,0x00005e52,0xffff1dc1,0xfffffb4b, +0x00011353,0xffff9740,0x00030748,0xffff351c, +0x0004ec95,0xfffed755,0x0006b5b4,0xfffe7fc6, +0xfff9a599,0x0000d334,0xfffb519f,0x00008f08, +0xfffd2bbf,0x00004704,0xffff1bc1,0xfffffc71, +0x00011598,0xffffb135,0x00030e43,0xffff6720, +0x0004f6f3,0xffff2119,0x0006c46e,0xfffedf38, +0xfff997c7,0x00008d13,0xfffb4a55,0x00005fa5, +0xfffd273b,0x00002f76,0xffff1a63,0xfffffda0, +0x00011744,0xffffcb67,0x000312ff,0xffff99cf, +0x0004ff0c,0xffff6a9c,0x0006cebd,0xffff3f0a, +0xfff98dbe,0x00004691,0xfffb4620,0x00003010, +0xfffd24fc,0x000017b5,0xffff199d,0xfffffed8, +0x0001185a,0xffffe5c6,0x0003157e,0xffffcce3, +0x000503ae,0xffffb515,0x0006d537,0xffff9f5a, +0xfff98767,0xfffb44b0,0xfffc3131,0xfffd2475, +0xfffe1c28,0xffff195d,0x00001859,0x000118bd, +0x000218df,0x0003163a,0x000410e0,0x000504a7, +0x0005f2b3,0x0006d796,0x0007b1fe,0xfff98537, +0xfffa609b,0xfffc7e8b,0x00028ef6,0xfffde181, +0x000144eb,0xffff5500,0xffffefb9,0x0000d01d, +0xfffe9755,0x000249a4,0xfffd453c,0x0003b80e, +0xfffc01aa,0x000511d6,0xfffad527,0xfffb334e, +0x0003c6b0,0xfffc5778,0x00026a92,0xfffdc9f5, +0x00013314,0xffff4d99,0xfffff0b6,0x0000d911, +0xfffeab80,0x00026369,0xfffd6c0a,0x0003e17f, +0xfffc39d8,0x000549df,0xfffb1eb2,0xfffafe6c, +0x0003916c,0xfffc3321,0x000244a6,0xfffdb402, +0x00012035,0xffff46ac,0xfffff192,0x0000e16a, +0xfffebfe0,0x00027b3d,0xfffd9433,0x0004087b, +0xfffc74b7,0x00057e8d,0xfffb6a81,0xfffacc1c, +0x00035929,0xfffc10df,0x00021e0c,0xfffd9f6d, +0x00010cb7,0xffff402e,0xfffff279,0x0000e965, +0xfffed574,0x00029159,0xfffdbdc4,0x00042c4c, +0xfffcb1e7,0x0005b02d,0xfffbb942,0xfffa9d38, +0x00031fbe,0xfffbf0fd,0x0001f5b4,0xfffd8c38, +0x0000f8b1,0xffff3a21,0xfffff391,0x0000f0e6, +0xfffeec44,0x0002a642,0xfffde90e,0x00044e32, +0xfffcf0fb,0x0005de46,0xfffc0b18,0xfffa71d1, +0x0002e44a,0xfffbd3de,0x0001cb90,0xfffd7a97, +0x0000e403,0xffff3490,0xfffff49c,0x0000f7a8, +0xffff0340,0x0002b95f,0xfffe1573,0x00046dbe, +0xfffd3284,0x00060888,0xfffc5f51,0xfffa4996, +0x0002a659,0xfffbb8df,0x0001a0e1,0xfffd6a4e, +0x0000ced2,0xffff2f75,0xfffff593,0x0000fdbe, +0xffff1a53,0x0002ca87,0xfffe42f5,0x0004898a, +0xfffd7563,0x00062f0b,0xfffcb5de,0xfffa2508, +0x00026786,0xfffba0bf,0x0001754a,0xfffd5b5f, +0x0000b92c,0xffff2acd,0xfffff6b0,0x0001034f, +0xffff3241,0x0002da5c,0xfffe71c6,0x0004a341, +0xfffdb946,0x000651e8,0xfffd0e37,0xfffa0402, +0x00022713,0xfffb8b9c,0x00014898,0xfffd4e7d, +0x0000a304,0xffff26b7,0xfffff7e1,0x00010846, +0xffff4b34,0x0002e897,0xfffea13f,0x0004ba63, +0xfffdff2d,0x00067115,0xfffd6839,0xfff9e680, +0x0001e4d4,0xfffb789e,0x00011b2e,0xfffd43a4, +0x00008c6e,0xffff2341,0xfffff8fd,0x00010c9c, +0xffff6469,0x0002f48f,0xfffed1a4,0x0004cd6a, +0xfffe4608,0x00068c1b,0xfffdc409,0xfff9cd15, +0x0001a1fa,0xfffb68a0,0x0000ecee,0xfffd3a2e, +0x0000757d,0xffff204b,0xfffffa1e,0x00011054, +0xffff7da1,0x0002fe9c,0xffff033e,0x0004de57, +0xfffe8dc6,0x0006a2d5,0xfffe213e,0xfff9b77d, +0x00015dfe,0xfffb5bde,0x0000be25,0xfffd3224, +0x00005e52,0xffff1dc1,0xfffffb4b,0x00011353, +0xffff9740,0x00030748,0xffff351c,0x0004ec95, +0xfffed755,0x0006b5b4,0xfffe7fc6,0xfff9a599, +0x000118d3,0xfffb519f,0x00008f08,0xfffd2bbf, +0x00004704,0xffff1bc1,0xfffffc71,0x00011598, +0xffffb135,0x00030e43,0xffff6720,0x0004f6f3, +0xffff2119,0x0006c46e,0xfffedf38,0xfff997c7, +0x0000d334,0xfffb4a55,0x00005fa5,0xfffd273b, +0x00002f76,0xffff1a63,0xfffffda0,0x00011744, +0xffffcb67,0x000312ff,0xffff99cf,0x0004ff0c, +0xffff6a9c,0x0006cebd,0xffff3f0a,0xfff98dbe, +0x00008d13,0xfffb4620,0x00003010,0xfffd24fc, +0x000017b5,0xffff199d,0xfffffed8,0x0001185a, +0xffffe5c6,0x0003157e,0xffffcce3,0x000503ae, +0xffffb515,0x0006d537,0xffff9f5a,0xfff98767, +0x00004691,0xfffa609b,0xfffb44b0,0xfffc3131, +0xfffd2475,0xfffe1c28,0xffff195d,0x00001859, +0x000118bd,0x000218df,0x0003163a,0x000410e0, +0x000504a7,0x0005f2b3,0x0006d796,0x0007b1fe, +0xfff98537,0xfffbd51e,0x00032dd1,0xfffd2d8f, +0x0001eb47,0xfffe9968,0x00009af6,0x000011de, +0xffff4335,0x00018d69,0xfffdecd4,0x000302f8, +0xfffca0d7,0x0004683d,0xfffb67f8,0x0005b36d, +0x00045963,0xfffba72a,0x00030062,0xfffd0dee, +0x0001d046,0xfffe8a0a,0x00009258,0x000012b1, +0xffff4d9e,0x00019ec3,0xfffe0a44,0x0003245a, +0xfffcd082,0x000498f0,0xfffba919,0x0005f304, +0x00041bf4,0xfffb7bf1,0x0002d19e,0xfffcf060, +0x0001b407,0xfffe7c08,0x0000894a,0x0000138d, +0xffff58ac,0x0001afaf,0xfffe28fe,0x000343bf, +0xfffd026f,0x0004c6f6,0xfffbed06,0x00062e61, +0x0003dc0e,0xfffb52c0,0x0002a17f,0xfffcd522, +0x000196a0,0xfffe6e70,0x00007ff6,0x00001439, +0xffff63f6,0x0001beb3,0xfffe4882,0x0003616d, +0xfffd361b,0x0004f1cf,0xfffc332a,0x0006658f, +0x00039943,0xfffb2d0c,0x00026ec7,0xfffcbb94, +0x0001789f,0xfffe6160,0x00007677,0x000014d4, +0xffff6f74,0x0001cc9b,0xfffe694f,0x00037cbf, +0xfffd6b41,0x000519c2,0xfffc7baf,0x00069971, +0x00035486,0xfffb0a7a,0x00023ad8,0xfffca3ee, +0x00015989,0xfffe55af,0x00006ca7,0x00001570, +0xffff7b71,0x0001d9cb,0xfffe8b46,0x0003959e, +0xfffda1fe,0x00053ee6,0xfffcc6b4,0x0006c950, +0x00030e08,0xfffaea7c,0x0002061e,0xfffc8ec0, +0x00013911,0xfffe4b1d,0x00006278,0x000015e8, +0xffff87b6,0x0001e577,0xfffeadd6,0x0003acc2, +0xfffdda34,0x00056059,0xfffd136d,0x0006f4b5, +0x0002c562,0xfffacdc3,0x0001cfa6,0xfffc7b14, +0x0001182b,0xfffe4159,0x00005817,0x0000165c, +0xffff9417,0x0001f00f,0xfffed14c,0x0003c199, +0xfffe13f6,0x00057e83,0xfffd61cd,0x00071ba1, +0x00027ab5,0xfffab482,0x00019833,0xfffc6989, +0x0000f6ca,0xfffe38da,0x00004d9d,0x000016ef, +0xffffa103,0x0001f98f,0xfffef5c0,0x0003d3d1, +0xfffe4f00,0x0005998c,0xfffdb21e,0x00073e77, +0x00022e75,0xfffa9e9b,0x00015fd1,0xfffc5b13, +0x0000d45d,0xfffe318f,0x000042ed,0x0000176b, +0xffffae8f,0x0002018f,0xffff1a91,0x0003e40c, +0xfffe8af2,0x0005b0ca,0xfffe03b8,0x00075d14, +0x0001e141,0xfffa8bb0,0x0001262a,0xfffc4e31, +0x0000b1af,0xfffe2b26,0x00003805,0x000017b1, +0xffffbc21,0x000208b8,0xffff3fb6,0x0003f1d7, +0xfffec7af,0x0005c4c5,0xfffe5654,0x0007768a, +0x000192fe,0xfffa7bec,0x0000ec3f,0xfffc4365, +0x00008ec9,0xfffe25f0,0x00002d05,0x000017ec, +0xffffc984,0x00020ec6,0xffff658d,0x0003fcba, +0xffff0500,0x0005d576,0xfffeaa37,0x00078bc6, +0x00014367,0xfffa6fc9,0x0000b1f4,0xfffc3b82, +0x00006b06,0xfffe2201,0x000021eb,0x00001823, +0xffffd704,0x0002132a,0xffff8be7,0x00040534, +0xffff4315,0x0005e22e,0xfffeff0a,0x00079ce3, +0x0000f33f,0xfffa671b,0x000076ca,0xfffc3558, +0x00004762,0xfffe1ef3,0x000016a1,0x0000183f, +0xffffe4a6,0x00021664,0xffffb27d,0x00040b7b, +0xffff81e5,0x0005eb4e,0xffff5475,0x0007a857, +0x0000a2cb,0xfffa6218,0x00003b64,0xfffc31e2, +0x00002416,0xfffe1ce1,0x00000b46,0x00001850, +0xfffff24d,0x00021855,0xffffd93a,0x00040f75, +0xffffc0e6,0x0005f0e3,0xffffaa3e,0x0007af45, +0x0000519f,0x00030000,0x000f0007,0x003f001f, +0x00ff007f,0x03ff01ff,0x0fff07ff,0x3fff1fff, +0xffff7fff,0x00030000,0x00070005,0x000f0009, +0x003f001f,0x00ff007f,0x03ff01ff,0x0fff07ff, +0xffff1fff,0x00030000,0x00070005,0x000f0009, +0xffff001f,0x00030000,0xffff0005,0x04030504, +0x08070605,0x0c0b0a09,0x100f0e0d,0x03070504, +0x0605040a,0x0a090807,0x100d0c0b,0x03070503, +0x1005040a,0x10070502,0x03030100,0x03030303, +0x03030303,0x03030303,0x03010100,0x03030301, +0x03030303,0x03030303,0x03010100,0x03030301, +0x03010100,0x04020000,0x08070605,0x0c0b0a09, +0x100f0e0d,0x02010000,0x06050403,0x0a090807, +0x100d0c0b,0x02010000,0x10050403,0x10010000, +0x00030000,0x00090005,0x001f000f,0x007f003f, +0x01ff00ff,0x07ff03ff,0x1fff0fff,0x7fff3fff, +0x00030000,0x00090005,0x001f000f,0x007f003f, +0x0a070504,0x07060504,0x0b0a0908,0x0f0e0d0c, +0x0a070503,0x07060504,0x01010100,0x03030303, +0x03030303,0x03030303,0x01010100,0x03030303, +0x03010000,0x07060504,0x0b0a0908,0x0f0e0d0c, +0x03010000,0x07060504,0x00555555,0x002aaaab, +0x00249249,0x00124925,0x00111111,0x00088889, +0x00084210,0x00421084,0x00041041,0x00020821, +0x00020408,0x00081020,0x00010101,0x00008081, +0x00008040,0x00100804,0x00004010,0x00020080, +0x00002004,0x00004008,0x00001001,0x00000801, +0x00000800,0x00200100,0x00000400,0x00080020, +0x00000200,0x00020004,0x00200000,0x00600040, +0x00a00080,0x00e000c0,0x01200100,0x01600140, +0x01a00180,0x000001c0,0x00300020,0x00400038, +0x00600050,0x00800070,0x00c000a0,0x010000e0, +0x01800140,0x00200000,0x00300028,0x00400038, +0x00600050,0x00800070,0x00c000a0,0x010000e0, +0x00000140,0x00900000,0x00fc00d8,0x01680120, +0x01f801b0,0x02d00240,0x03f00360,0x05a00480, +0x000006c0,0x00680000,0x00b6009c,0x010500d0, +0x016d0139,0x020a01a1,0x02db0272,0x04140343, +0x000004e5,0x006c0000,0x00bd00a2,0x010e00d8, +0x017a0144,0x006301b0,0x013b00cf,0x00c601a7, +0x0000019e,0x00600000,0x00a80090,0x00f000c0, +0x01500120,0x01e00180,0x02a00240,0x03c00300, +0x00000480,0x10000000,0x10101010,0x20101010, +0x20202020,0x20202020,0x28202020,0x28282828, +0x00002828,0x10100000,0x10101010,0x10101010, +0x00000000,0x00000000,0x00000000,0x00000000, +0xcbcecdc4,0xcfcac9c8,0xc3c6c5cc,0xc7c2c1c0, +0x1b1e1d14,0x1f1a1918,0x1316151c,0x17121110, +0x2b2e2d24,0x2f2a2928,0x2326252c,0x27222120, +0x3b3e3d34,0x3f3a3938,0x3336353c,0x37323130, +0x0b0e0d04,0x0f0a0908,0x0306050c,0x07020100, +0xdbdeddd4,0xdfdad9d8,0xd3d6d5dc,0xd7d2d1d0, +0xebeeede4,0xefeae9e8,0xe3e6e5ec,0xe7e2e1e0, +0xfbfefdf4,0xfffaf9f8,0xf3f6f5fc,0xf7f2f1f0, +0x4b4e4d44,0x4f4a4948,0x4346454c,0x47424140, +0x9b9e9d94,0x9f9a9998,0x9396959c,0x97929190, +0xabaeada4,0xafaaa9a8,0xa3a6a5ac,0xa7a2a1a0, +0xbbbebdb4,0xbfbab9b8,0xb3b6b5bc,0xb7b2b1b0, +0x8b8e8d84,0x8f8a8988,0x8386858c,0x87828180, +0x5b5e5d54,0x5f5a5958,0x5356555c,0x57525150, +0x6b6e6d64,0x6f6a6968,0x6366656c,0x67626160, +0x7b7e7d74,0x7f7a7978,0x7376757c,0x77727170, +0x341424c4,0x3e1e2ece,0x3d1d2dcd,0x3b1b2bcb, +0xb494a444,0xbe9eae4e,0xbd9dad4d,0xbb9bab4b, +0xf4d4e404,0xfedeee0e,0xfddded0d,0xfbdbeb0b, +0x74546484,0x7e5e6e8e,0x7d5d6d8d,0x7b5b6b8b, +0x3c1c2ccc,0x361626c6,0x351525c5,0x331323c3, +0xbc9cac4c,0xb696a646,0xb595a545,0xb393a343, +0xfcdcec0c,0xf6d6e606,0xf5d5e505,0xf3d3e303, +0x7c5c6c8c,0x76566686,0x75556585,0x73536383, +0x381828c8,0x3a1a2aca,0x391929c9,0x3f1f2fcf, +0xb898a848,0xba9aaa4a,0xb999a949,0xbf9faf4f, +0xf8d8e808,0xfadaea0a,0xf9d9e909,0xffdfef0f, +0x78586888,0x7a5a6a8a,0x79596989,0x7f5f6f8f, +0x301020c0,0x321222c2,0x311121c1,0x371727c7, +0xb090a040,0xb292a242,0xb191a141,0xb797a747, +0xf0d0e000,0xf2d2e202,0xf1d1e101,0xf7d7e707, +0x70506080,0x72526282,0x71516181,0x77576787, +0x05040100,0x15141110,0x25242120,0x35343130, +0x85848180,0x95949190,0xa5a4a1a0,0xb5b4b1b0, +0xc0408000,0xe060a020,0xd0509010,0xf070b030, +0xc8488808,0xe868a828,0xd8589818,0xf878b838, +0xc4448404,0xe464a424,0xd4549414,0xf474b434, +0xcc4c8c0c,0xec6cac2c,0xdc5c9c1c,0xfc7cbc3c, +0xc2428202,0xe262a222,0xd2529212,0xf272b232, +0xca4a8a0a,0xea6aaa2a,0xda5a9a1a,0xfa7aba3a, +0xc6468606,0xe666a626,0xd6569616,0xf676b636, +0xce4e8e0e,0xee6eae2e,0xde5e9e1e,0xfe7ebe3e, +0xc1418101,0xe161a121,0xd1519111,0xf171b131, +0xc9498909,0xe969a929,0xd9599919,0xf979b939, +0xc5458505,0xe565a525,0xd5559515,0xf575b535, +0xcd4d8d0d,0xed6dad2d,0xdd5d9d1d,0xfd7dbd3d, +0xc3438303,0xe363a323,0xd3539313,0xf373b333, +0xcb4b8b0b,0xeb6bab2b,0xdb5b9b1b,0xfb7bbb3b, +0xc7478707,0xe767a727,0xd7579717,0xf777b737, +0xcf4f8f0f,0xef6faf2f,0xdf5f9f1f,0xff7fbf3f, +0x1045a3e2,0x000000f4,0x263b7333,0x766b2363, +0x2b367e3e,0x7b662e6e,0x06db93d3,0x964b0343, +0x0bd69ede,0x9b460e4e,0x825f1757,0x12cf87c7, +0x8f521a5a,0x1fc28aca,0x00d199d9,0x90410949, +0x01d098d8,0x91400848,0x24357d3d,0x74652d6d, +0x25347c3c,0x75642c6c,0x04d59ddd,0x94450d4d, +0x05d49cdc,0x95440c4c,0x80511959,0x10c189c9, +0x81501858,0x11c088c8,0x02df97d7,0x924f0747, +0x0fd29ada,0x9f420a4a,0x865b1353,0x16cb83c3, +0x8b561e5e,0x1bc68ece,0xa6bbf3b3,0xf6eba3e3, +0xabb6febe,0xfbe6aeee,0x223f7737,0x726f2767, +0x2f327a3a,0x7f622a6a,0xa0b1f9b9,0xf0e1a9e9, +0xa1b0f8b8,0xf1e0a8e8,0x84551d5d,0x14c58dcd, +0x85541c5c,0x15c48ccc,0xa4b5fdbd,0xf4e5aded, +0xa5b4fcbc,0xf5e4acec,0x20317939,0x70612969, +0x21307838,0x71602868,0xa2bff7b7,0xf2efa7e7, +0xafb2faba,0xffe2aaea,0x00000000,0x00000000, + +}; + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/ls220/mpg.h linux.19rc3-ac4/drivers/media/video/ls220/mpg.h --- linux.19rc3/drivers/media/video/ls220/mpg.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/ls220/mpg.h 2002-07-29 13:58:41.000000000 +0100 @@ -0,0 +1,1612 @@ +static u32 MPGUcode1f1800[] = { +0x820f001f,0x802f001f,0x81df0000,0xb500000c, +0x00ffb81e,0x00000000,0x00000000,0x00000000, +0x00ffb81e,0x00000000,0x00000000,0x00000000, +0xb5000c13,0x00000000,0x00000000,0x00000000, +0x80070800,0x001f6047,0x8013001f,0x90208000, +0x003fb174,0x803effe8,0x803effec,0x9020fa00, +0x803effd0,0x803effdc,0x803effd8,0x9020fe00, +0x803effd4,0x805bff7c,0x802500d4,0x94020080, +0xb0000000,0xb4200023,0x8013ffcf,0x9800cfff, +0x80730030,0x98631000,0x94420007,0xb0020002, +0xb4200005,0x8013ffc7,0x9800c7ff,0x80730038, +0x98631000,0xb5000006,0xb0020001,0xb4200004, +0x8013ffcf,0x9800cfff,0x80730030,0x98631000, +0x1421b800,0x1821b803,0x802600d4,0x8033001f, +0x98210000,0x802600a2,0x8033001f,0x98210300, +0x802600a3,0x80270225,0x80530001,0x98420100, +0x1821b802,0x80530200,0x98420000,0x804600a6, +0xb500001d,0x805bff7c,0x8013ffcf,0x9800cfff, +0x80730030,0x98631000,0x94420007,0xb0020002, +0xb4200005,0x8013ffc7,0x9800c7ff,0x80730038, +0x98631000,0xb5000006,0xb0020001,0xb4200004, +0x8013ffcf,0x9800cfff,0x80730030,0x98631000, +0x1421b800,0x1821b803,0x802600d4,0x8033001f, +0x98210000,0x802600a2,0x8033001f,0x98210300, +0x802600a3,0x80270c25,0x802600a1,0x80270002, +0x803eff84,0x80070000,0x801effc0,0x801effc4, +0x801effc8,0x801effcc,0x801eff88,0x80770000, +0x8057ffff,0x80170080,0x80070000,0xb6003f02, +0xb6002001,0x001fa020,0x8007ffff,0x801eff84, +0x80070001,0x001f25dc,0x001f20b1,0x80070000, +0x001f6046,0x001fb17c,0x001fb17d,0x80070000, +0x801e78d0,0x98004000,0x001f62ea,0x80070100, +0x801efff0,0x81df0004,0x00000000,0x00000000, +0x801bfff0,0x00000000,0x940000ff,0xb0000000, +0xb420005b,0x003f42ea,0x94010010,0xb0000000, +0xb400fff7,0x003f05dc,0xb0010001,0xb4200034, +0x803bffe8,0x801bffec,0x00000000,0x3001b800, +0xb4600001,0x90214000,0x0421b800,0xb0010800, +0xb460000d,0x80050086,0x005f902e,0xb0020000, +0xb4200002,0x001fb02e,0xb5000006,0x0420b802, +0xb0010930,0xb4a0ffe2,0x80070000,0x001fb02e, +0x83e40162,0xb500ffde,0x83e40129,0x80070000, +0x001fb02e,0x001f42ea,0x9400000f,0xb0000000, +0xb4000010,0x9400fff0,0x001f62ea,0x003f9174, +0x9421ffff,0x90210004,0xb001c000,0xb4800002, +0x8421c000,0x90218000,0x8013001f,0x1821b800, +0x003fb174,0x003f917c,0x90210004,0x003fb17c, +0x83e4014a,0x8013001f,0x83e71b0c,0x1bffb800, +0x003f9179,0x1821b800,0x00ffb801,0xb5000008, +0x80270000,0x003f25dc,0x8013001f,0x83e71b30, +0x1bffb800,0x003f917a,0x1821b800,0x00ffb801, +0x80070000,0x001f20b1,0x001f42ea,0x9420000f, +0xb0010000,0xb4200003,0x98000800,0x001f62ea, +0xb500ffaf,0x9400fff0,0x001f62ea,0x80270000, +0x8057ffff,0x80770000,0x80171800,0x81df0000, +0x00000000,0x00000000,0xb6000302,0xb6002001, +0x001fa021,0x81df0004,0xb500ffa1,0xb500ffa0, +0x803bffc0,0x805bffc4,0x807bffc8,0x809bffcc, +0x5828b801,0x5cb8b802,0x1821b805,0x5848b802, +0x5cb8b803,0x1842b805,0x5868b803,0x5cb8b804, +0x1863b805,0x5888b804,0x1884b800,0x803effc0, +0x805effc4,0x807effc8,0x809effcc,0x003f42ea, +0xb0000086,0xb4400079,0xb0000084,0xb4000049, +0xb0000085,0xb4000063,0xb0000086,0xb400006c, +0xb0000081,0xb4000005,0xb0000082,0xb4000003, +0xb0000080,0xb4000001,0xb5000069,0x8013007f, +0x9800ffff,0x001fb02d,0x80070000,0x001fb17c, +0x8013001f,0x9040fa00,0x805effd0,0x805effdc, +0x805effd8,0x9040fe00,0x805effd4,0x9040c000, +0x805effe4,0x90008000,0x801effe0,0x001fb174, +0x801effe8,0x801effec,0x80078000,0x801e78d4, +0x80070000,0x001fb17c,0x001fb17d,0x001fb02e, +0x83e400e6,0x8013001f,0x98000000,0x800600a2, +0x8013001f,0x98000300,0x800600a3,0x805bff7c, +0x80070c25,0x94420080,0xb0020080,0xb420000d, +0x8013001f,0x98000000,0x800600a2,0x8013001f, +0x98000300,0x800600a3,0x80070225,0x80530001, +0x98420100,0x1800b802,0x80530200,0x98420000, +0x804600a6,0x800600a1,0x80050080,0x98000022, +0x80060080,0x80072080,0x001fb179,0x80074618, +0x001fb17a,0x80070001,0x001f25dc,0x98214000, +0xb5000029,0x8047ffff,0x805eff84,0x805bff88, +0x00000000,0xb0020001,0xb4200002,0x80470000, +0x805eff88,0x805bff7c,0x80070c25,0x94420080, +0xb0020080,0xb4200007,0x80070225,0x80530001, +0x98420100,0x1800b802,0x80530200,0x98420000, +0x804600a6,0x800600a1,0x80070001,0x800600a0, +0x9421efff,0x98210010,0xb500000f,0x80070000, +0x001fb17c,0x80070001,0x001f25dc,0x83e400a3, +0x80050081,0x80330008,0x98210000,0x1800b801, +0x80060081,0x003f42ea,0x9421ffef,0xb5000002, +0x98211000,0x9421ffef,0x83e40098,0x003f62ea, +0x80070100,0x801efff0,0xb500ff11,0xb000008b, +0xb400001c,0xb0000087,0xb400ffe8,0xb0000088, +0xb4000023,0xb000008a,0xb4000024,0xb000008c, +0xb4000019,0xb000008e,0xb4000014,0xb000008d, +0xb400001d,0xb0000089,0xb400001f,0xb00000a0, +0xb4000021,0xb00000a1,0xb4000022,0xb00000a2, +0xb400002f,0xb00000a3,0xb4000027,0xb00000a4, +0xb4000031,0xb00000a5,0xb4000035,0xb00000a6, +0xb4000039,0x803efff8,0xb500ffdd,0x80070000, +0x001fb17e,0xb500ffda,0x803bffb0,0x00000000, +0x003fb02d,0xb500ffd6,0x98210020,0xb500ffd2, +0x9421ffdf,0xb500ffd0,0xb500ffd1,0x80270341, +0x803efff8,0xb500ffce,0x803bff80,0x00000000, +0x003f62ef,0xb500ffca,0x003f917b,0x803efff8, +0xb500ffc7,0x80270000,0x8047fef0,0x003eb802, +0x90420004,0x003eb802,0x90420004,0x003eb802, +0x90420004,0x003eb802,0x81df0000,0x00000000, +0x00000000,0x83640dbd,0x81df0004,0xb500ffb8, +0x81df0000,0x00000000,0x00000000,0x83640d67, +0x81df0004,0xb500ffb2,0x81df0000,0x00000000, +0x00000000,0x83640d22,0x81df0004,0xb500ffac, +0x81df0000,0x00000000,0x00000000,0x83440c85, +0x81df0004,0xb500ffa6,0x81df0000,0x00000000, +0x00000000,0x83440c6a,0x81df0004,0xb500ffa0, +0x817bffe8,0x815b78d4,0x00000000,0x956bffff, +0x300bb80a,0xb4600001,0x916b4000,0x056bb80a, +0xb00b0080,0xb4a0002a,0x80af001f,0x808f0000, +0x806f0000,0x81b300ff,0x8057ffff,0x5d67b80b, +0x5d42b80a,0x81df0000,0x00000000,0x00000000, +0xb62b001c,0xb00a3000,0xb4800001,0x854a1000, +0x80cf0400,0x015fb178,0x5942b80a,0x01cfb80a, +0x015f9178,0xb520ffff,0x80171000,0xb600200a, +0x01ff8000,0x5a18b80f,0x5a28b80f,0x1631b80d, +0x5e48b80f,0x9652ff00,0x5e78b80f,0x1a73b810, +0x1a73b811,0x1813a032,0x80cf0400,0x015fb178, +0x5942b80a,0x01afb80a,0x015f9178,0xb520ffff, +0x914a0020,0x81df0004,0x5942b80a,0x815e78d4, +0x00000000,0x00000000,0x00ffb81f,0x81df0000, +0x80070000,0x80470000,0x81171800,0xb6002003, +0xb6003002,0x001eb802,0x90420004,0xb6002003, +0x011fa020,0x011fa020,0x011fa020,0x81df0004, +0x00ffb81f,0x80070000,0x80478000,0x81df0000, +0x00000000,0x00000000,0xb6002003,0xb6008002, +0x001eb802,0x90420004,0x81df0004,0x00ffb81f, +0x015f42ea,0x944a4000,0xb0024000,0xb4200081, +0x954abfff,0x015f62ea,0x808f0000,0x80ef007c, +0x80171000,0x80971400,0x80270000,0xb6001003, +0xb6002002,0x001fa021,0x009fa021,0x80a76604, +0x80271400,0x81df0000,0x00000000,0x00000000, +0xb6001004,0x01efb801,0x01afb805,0xb520ffff, +0x90a50080,0x81df0004,0x80a76e04,0x80271400, +0x81df0000,0x00000000,0x00000000,0xb6001004, +0x01efb801,0x01afb805,0xb520ffff,0x90a50080, +0x81df0004,0x806f001f,0x80af001f,0x80276400, +0x5c22b801,0x806701e1,0x00cfb803,0x003fb178, +0x5822b801,0x01cfb801,0x003f9178,0x0047b86f, +0xb0020001,0xb4c0fffd,0x80275c00,0x5c22b801, +0x80670200,0x81df0000,0x00000000,0x00000000, +0xb600100a,0x00cfb803,0x003fb178,0x5822b801, +0x01cfb801,0x003f9178,0x0047b86f,0xb0020001, +0xb4c0fffd,0x90210020,0x90630020,0x81df0004, +0x808f0000,0x806f001f,0x80af001f,0x8027647c, +0x5c22b801,0x8067017e,0x81df0000,0x00000000, +0x00000000,0xb600020a,0x00cfb803,0x003fb178, +0x5822b801,0x01cfb801,0x003f9178,0x0047b86f, +0xb0020001,0xb4c0fffd,0x90210020,0x90630020, +0x81df0004,0x806f0010,0x80af0010,0x8027657c, +0x5c22b801,0x806701be,0x00cfb803,0x003fb178, +0x5822b801,0x01cfb801,0x003f9178,0x0047b86f, +0xb0020001,0xb4c0fffd,0x802765c0,0x5c22b801, +0x806701cf,0x00cfb803,0x003fb178,0x5822b801, +0x01cfb801,0x003f9178,0x0047b86f,0xb0020001, +0xb4c0fffd,0x80276000,0x005fb801,0x8033001f, +0x98218000,0x803effe0,0x90214000,0x803effe4, +0x8193001f,0x998c8000,0x019fb174,0x83270000, +0x003fb819,0x003f9174,0x5823b801,0x83338000, +0x1b39b801,0x003fb819,0x00000000,0x00000000, +0x81550000,0x0187b860,0x858c0040,0x81b380fc, +0x99ad0000,0x300cb80d,0xb4600003,0x81b30002, +0x99ad0000,0x118cb80d,0x003fb80c,0x00000000, +0x00000000,0x81550000,0x8257ffff,0x82d7ffff, +0x8357ffff,0x81672000,0x83440191,0xb00a0001, +0xb4000141,0x0187b860,0x858c0010,0x5988b80c, +0x5d8bb80c,0x958cffff,0xb00cc000,0xb4800002, +0x858cc000,0x918c8000,0x81b3001f,0x198cb80d, +0x801bffec,0x00000000,0x819effec,0x819e78d8, +0x019fb174,0x05acb800,0x300cb800,0xb4600001, +0x91ad4000,0x001f917c,0x1000b80d,0x001fb17c, +0x8344019c,0xb00a0000,0xb4200127,0x015f0081, +0xb00a0002,0xb4200124,0x037f0082,0xb01b0000, +0xb400001e,0x0367b860,0x5b68b81b,0x5f68b81b, +0x017f4047,0x916b0010,0x5963b80b,0x83440168, +0x801bff84,0xb00a0001,0xb400000b,0xb00b00c0, +0xb460fffa,0x803f0000,0x80138000,0x1b7bb800, +0x003fb81b,0x00000000,0x00000000,0x80150000, +0x801bff84,0xb5000009,0x803f0000,0x80138000, +0x1b7bb800,0x003fb81b,0x00000000,0x00000000, +0x80150000,0x801bff84,0xb5000103,0x801bff84, +0x003f0084,0x3000b801,0x803eff84,0xb4000073, +0x801bff7c,0x00000000,0x94800080,0xb0040080, +0xb4200036,0x94800007,0x80730200,0xb0010002, +0xb420000e,0x80270265,0xb0040001,0xb4200003, +0x80130030,0x98000000,0xb5000006,0x80130030, +0x98000000,0xb0040000,0xb4000002,0x80130038, +0x98000000,0x98630060,0xb500001f,0xb0010000, +0xb420000e,0x80270225,0xb0040001,0xb4200003, +0x80130030,0x98001000,0xb5000006,0x80130030, +0x98001000,0xb0040000,0xb4000002,0x80130038, +0x98001000,0x98630000,0xb500000f,0xb0010001, +0xb420004a,0x80270225,0xb0040001,0xb4200003, +0x80130030,0x98002000,0xb5000006,0x80130030, +0x98000000,0xb0040000,0xb4000002,0x80130038, +0x98000000,0x98630040,0x806600a6,0x80530001, +0x98420100,0x1821b802,0xb500002d,0x94800007, +0xb0010002,0xb420000d,0x80270c65,0xb0040001, +0xb4200003,0x80130030,0x98000000,0xb5000006, +0x80130030,0x98000000,0xb0040000,0xb4000002, +0x80130038,0x98000000,0xb500001d,0xb0010000, +0xb420000d,0x80270c25,0xb0040001,0xb4200003, +0x80130030,0x98001000,0xb5000006,0x80130030, +0x98001000,0xb0040000,0xb4000002,0x80130038, +0x98001000,0xb500000e,0xb0010001,0xb4200017, +0x80270c25,0xb0040001,0xb4200003,0x80130030, +0x98002000,0xb5000006,0x80130030,0x98000000, +0xb0040000,0xb4000002,0x80130038,0x98000000, +0x806500d4,0x8053ffcf,0x9842cfff,0xb0040002, +0xb4200002,0x8053ffc7,0x9842c7ff,0x802600a1, +0x1463b802,0x1863b800,0x806600d4,0x807bff7c, +0x00000000,0x94630080,0xb0030080,0xb420000b, +0x807bff88,0x00000000,0xb0030001,0xb4000007, +0x802500a1,0x80670001,0x807eff88,0x80530001, +0x98420100,0x1821b802,0x802600a1,0x81070000, +0x011f62e2,0x011f62e3,0x011f0082,0xb0080000, +0xb4200004,0x81150010,0x00000000,0x00000000, +0x011f62de,0x011f0081,0xb0080001,0xb4200026, +0x81070020,0x011f25c1,0x81070180,0x011f62e1, +0x8344023e,0x8344026a,0x011f0082,0xb0080000, +0xb4200004,0x834401bd,0x834401aa,0xb00a0000, +0xb4200061,0x80c70000,0x00df25cb,0x83440281, +0x8344064f,0x02ff05b9,0x82a70000,0x82870000, +0x83440407,0x92940001,0x3014b817,0xb480fffc, +0x834406ef,0x80270000,0x003f25dc,0x834407de, +0x003f05dc,0xb0010001,0xb4000003,0x80272694, +0x003fb17a,0x00ffb81f,0x80d3001f,0x8347266c, +0x1b5ab806,0xb500002d,0xb0080002,0x81470004, +0xb4200045,0x81070008,0x011f25c1,0x81070480, +0x011f62e1,0x8344029e,0x834402dc,0x011f0082, +0xb0080000,0xb4200004,0x834401aa,0x83440181, +0xb00a0000,0xb4200038,0x80c70000,0x00df25cb, +0x83440368,0x02df05cb,0x5ec2b816,0x8344066b, +0x02ff05b9,0x82a70000,0x82870000,0x834403dc, +0x92940001,0x3014b817,0xb480fffc,0x92b50001, +0xb0150003,0xb480fff8,0x834406c1,0x80270000, +0x003f25dc,0x834407b0,0x003f05dc,0xb0010001, +0xb4000003,0x8027274c,0x003fb17a,0x00ffb81f, +0x80d3001f,0x83472710,0x1b5ab806,0x80db78d8, +0x80fbffec,0x00000000,0x3006b807,0xb4200007, +0x00df05cb,0x90c60001,0x00df25cb,0xb006000c, +0xb4000002,0x035fb179,0x00ffb81f,0x80c70000, +0x00df25cb,0x80fb78dc,0x00000000,0x90e70001, +0xb00701b9,0xb4a00001,0x80e70001,0x80fe78dc, +0xb500feb0,0x802500a5,0x8153001f,0x3001b80a, +0xb420fffc,0x00ffb81f,0x001f42ea,0x1800b80a, +0x001f62ea,0x017f4047,0x5963b80b,0x0187b860, +0x118cb80b,0x81b380fe,0x99ad0000,0x300cb80d, +0xb4800003,0x81b30002,0x99ad0000,0x058cb80d, +0x003fb80c,0x00000000,0x00000000,0x81550000, +0x0187b860,0x5988b80c,0x5d8bb80c,0x958cffff, +0xb00cc000,0xb4800002,0x858cc000,0x918c8000, +0x81b3001f,0x198cb80d,0x801bffec,0x00000000, +0x819effec,0x019fb174,0x05acb800,0x300cb800, +0xb4600001,0x91ad4000,0x001f917c,0x1000b80d, +0x001fb17c,0x80171000,0x80971400,0x80270000, +0xb6001003,0xb6002002,0x001fa021,0x009fa021, +0x80171800,0xb6000602,0xb6002001,0x001fa021, +0x806f001f,0x80af001f,0x80a76604,0x80271400, +0x81df0000,0x00000000,0x00000000,0xb6001004, +0x01efb801,0x01afb805,0xb520ffff,0x90a50080, +0x81df0004,0x80a76e04,0x80271400,0x81df0000, +0x00000000,0x00000000,0xb6001004,0x01efb801, +0x01afb805,0xb520ffff,0x90a50080,0x81df0004, +0x81472080,0x015fb179,0x00ffb81f,0x00000000, +0x811be024,0x0107b860,0x95080007,0xb0080000, +0xb4000004,0xa5080008,0x00000000,0x0155b808, +0x00000000,0x8115000c,0x856b000c,0xb0080fff, +0xb400000b,0x81550004,0x856b0004,0x5904b808, +0x1908b80a,0x95080fff,0xb0080fff,0xb4000004, +0x81470001,0xb00b0020,0xb440fff6,0xb500000c, +0x81d50004,0x856b0004,0x00000000,0xb00e000f, +0xb400fffb,0x940b0007,0xb0000000,0xb420ffed, +0x001f42ea,0x9400fffe,0x81470000,0x001f62ea, +0x00ffb81a,0x950e0008,0x5d03b808,0x00000000, +0xb0080000,0xb40000cd,0x011f2080,0x950e0006, +0x5d01b808,0x81270004,0x0529b808,0x950e0001, +0x013f2081,0x011f2082,0x81150004,0x00000000, +0xb0080000,0xb40000c1,0xb008000f,0xb40000bf, +0x011f2083,0x81150002,0x00000000,0x81670004, +0xb0080002,0xb46000b9,0x011f2084,0x013f0081, +0xb0090002,0xb4200011,0x013f0083,0xb0080000, +0xb4200002,0x81077844,0xb5000005,0xb0080001, +0xb4200002,0x81077884,0xb5000001,0x81077824, +0x013f0083,0x5921b809,0x1129b808,0x0119b809, +0x00000000,0x00000000,0x011f6047,0x81150001, +0x00000000,0x011f2085,0x81150001,0x00000000, +0x011f2086,0x81350002,0x00000000,0x013f2087, +0x81150002,0x00000000,0x011f2088,0x81150001, +0x00000000,0x011f2089,0x81150001,0x00000000, +0x011f208a,0x81150002,0x00000000,0x011f208b, +0x81070001,0xb0090003,0xb4000001,0x81070002, +0x011f25b9,0x81070020,0x013f0081,0xb0090002, +0xb4200069,0x85290001,0xad29000f,0x00000000, +0x011f0083,0x1108b809,0x5901b808,0x910877c8, +0x0139b808,0x011f05b9,0x85080001,0x6928b809, +0x011f0084,0xb0090038,0xb4800007,0xb0080001, +0xb4000002,0xb0090050,0xb4400003,0x81270000, +0x8107001b,0xb5000010,0xb0080001,0xb4000005, +0xb0090060,0xb4800003,0x81270001,0x8107001e, +0xb5000009,0xb0080002,0xb4000005,0xb0090030, +0xb4400003,0x81270002,0x81070008,0xb5000002, +0x81270003,0x8107000c,0x011f25bb,0x013f25c0, +0xb0090002,0xb460001b,0x80477604,0x5c42b802, +0x814fffc0,0x80cf0037,0x005fb178,0x5842b802, +0x01cfb802,0x005f9178,0xb520ffff,0x90420020, +0x814fb580,0x80cf0057,0x005fb178,0x5842b802, +0x01cfb802,0x005f9178,0xb520ffff,0x804778a4, +0x5c42b802,0x814f39c0,0x80cf002f,0x005fb178, +0x5842b802,0x01cfb802,0x005f9178,0xb520ffff, +0xb5000025,0x804776e0,0x5c42b802,0x814fef40, +0x80cf0037,0x005fb178,0x5842b802,0x01cfb802, +0x005f9178,0xb520ffff,0x8297013c,0x8317018c, +0x81df0000,0x00000000,0x00000000,0xb6000602, +0x005f8034,0x031fa022,0x82970124,0x83170160, +0xb6000602,0x005f8034,0x031fa022,0x8297010c, +0x83170134,0xb6000602,0x005f8034,0x031fa022, +0x81df0004,0x804778c4,0x5c42b802,0x814f1080, +0x80cf002f,0x005fb178,0x5842b802,0x01cfb802, +0x005f9178,0xb520ffff,0x013f0081,0xb0090001, +0xb420000e,0x808f0000,0x806f001b,0x80af001b, +0x80277758,0x5c22b801,0x80670037,0x00cfb803, +0x003fb178,0x5822b801,0x01cfb801,0x003f9178, +0x0047b86f,0xb0020001,0xb4c0fffd,0x011f25bb, +0x011f0087,0xb0080001,0xb4000002,0x011f05bb, +0xb5000003,0x011f0088,0x91080001,0x5902b808, +0x011f25ba,0x81470000,0x00ffb81a,0x81470008, +0x00ffb81a,0x81270000,0x81470000,0x300842de, +0xb400000b,0x013f42e2,0x91290001,0x013f62e2, +0x013f42e3,0x91290001,0x013f62e3,0x83640006, +0x00000000,0x00000000,0x013f42e2,0x81470002, +0x013f62e2,0x00ffb81a,0x00ffb81b,0x83640049, +0x80c70004,0x80270000,0x81df0000,0x00000000, +0x00000000,0xb600200d,0x00ff05b9,0x5c42b801, +0x300205ba,0xb4800001,0x80e70001,0x80470000, +0xb6270005,0x1062b801,0x914301b8,0x00fff00a, +0x83840055,0x90420080,0x90210004,0x81df0004, +0x00ffb81a,0x83640033,0x017f05bb,0x800700bc, +0x80270000,0x81df0000,0xb00b0000,0xb4000015, +0xb62b0014,0x00ff05b9,0x5c42b801,0x300205ba, +0xb4800001,0x80e70001,0x80470000,0xb0070000, +0xb400000b,0xb627000a,0x1062b801,0x914301b8, +0x00fff00a,0x5c62b801,0x1063b800,0x00bff003, +0x90650134,0x00dff003,0x83840037,0x90420080, +0x90210004,0x81df0004,0x019f05b9,0x80c70002, +0x80270000,0x81df0000,0xb00b0000,0xb400000f, +0xb62b000e,0x80470000,0xb00c0000,0xb400000a, +0xb62c0009,0x1062b801,0x914301b8,0x00fff00a, +0xb0070000,0xb4000003,0x906302b8,0x00fff003, +0x83840021,0x90420080,0x90210004,0x81df0004, +0x00ffb81a,0x8107ffff,0x80c70004,0x00ff0083, +0x83840019,0x80c70002,0x00ff0084,0x83840016, +0x80c70001,0x00ff0085,0x83840013,0x80c70001, +0x00ff0086,0x83840010,0x80c70002,0x00ff0087, +0x8384000d,0x80c70002,0x00ff0088,0x8384000a, +0x80c70001,0x00ff0089,0x83840007,0x80c70001, +0x00ff008a,0x83840004,0x80c70002,0x00ff008b, +0x83840001,0x00ffb81b,0x80a70001,0x64a6b805, +0x5ca1b805,0xb0050000,0xb400000e,0x95288000, +0xb0090000,0xb4000001,0x81270001,0x5901b808, +0x1547b805,0xb00a0000,0xb4000001,0x81470001, +0x2129b80a,0xb0090000,0xb4000001,0xa1088005, +0xb500ffef,0x9508ffff,0x00ffb81c,0x015f05ba, +0x013f05b9,0x800700bc,0xb0090000,0xb4000012, +0xb00a0000,0xb4000010,0x80270000,0x81df0000, +0x00000000,0x00000000,0xb62a000b,0x80470000, +0xb6290008,0x80950004,0x5865b802,0x1063b801, +0x5862b803,0x906301b8,0x0217b803,0x90420001, +0x021fa004,0x90210001,0x81df0004,0xa54a0020, +0xb4c00011,0xb0090000,0xb400000f,0x81df0000, +0x00000000,0x00000000,0xb62a000b,0x80950004, +0x80470000,0xb6290007,0x5865b802,0x1063b801, +0x5862b803,0x906301b8,0x0217b803,0x90420001, +0x021fa004,0x90210001,0x81df0004,0x00ffb81a, +0x013f05b9,0xb0090000,0xb400001c,0x80270000, +0x81df0000,0x00000000,0x00000000,0xb6002017, +0x80470000,0xb6290014,0x5865b802,0x1063b801, +0x5862b803,0x914301b8,0x009ff00a,0xad420060, +0x00000000,0x114ab801,0x5942b80a,0x914a1c80, +0x0217b80a,0xb0040000,0xb4000004,0x80950006, +0x00000000,0x021fa004,0xb5000002,0x8087003f, +0x021fa004,0x90420001,0x90210001,0x81df0004, +0x00ffb81a,0x8257ffff,0x82d7ffff,0x011f05ba, +0x013f05b9,0x80270000,0xb0090000,0xb4000033, +0x81df0000,0x00000000,0x00000000,0xb6280015, +0x80470000,0xb6290012,0x5865b802,0x1063b801, +0x5862b803,0x914301b8,0xaca20060,0x009ff00a, +0x10a5b801,0x58a2b805,0x90a502b8,0x0217b805, +0x80670000,0xb0040000,0xb4000003,0x90840001, +0x0075b804,0x00000000,0x021fa003,0x90420001, +0x90210001,0x81df0004,0xa5480020,0xb4000017, +0x5822b801,0x81df0000,0x00000000,0x00000000, +0xb62a0011,0x914101b8,0x90a102b8,0x0217b805, +0x009ff00a,0xb0040000,0x80670000,0xb4000002, +0x90840001,0x0075b804,0xb6290006,0x021fa203, +0x009f8210,0x009f8210,0x009f8210,0x009f8210, +0x009f8210,0x90210004,0x81df0004,0x00ffb81a, +0x015f05ba,0x013f05b9,0x800700bc,0xb0090000, +0xb4000016,0xb00a0000,0xb4000014,0x80270000, +0x81df0000,0x00000000,0x00000000,0xb62a000f, +0x80470000,0xb629000c,0x1080b801,0x007ff004, +0x90830134,0x007ff004,0x0095b803,0x5865b802, +0x1063b801,0x5862b803,0x906301b8,0x0217b803, +0x90420001,0x021fa004,0x90210001,0x011f05bb, +0x254ab808,0xb4c0000d,0xb62a000c,0x1080b801, +0x007ff004,0x90830134,0x007ff004,0x0095b803, +0x5862b801,0x906301b8,0x0217b803,0x90210001, +0x021fa204,0x007f8210,0x021fa004,0xa5480020, +0xb4c0000e,0xb0090000,0xb400000c,0x80870000, +0xb62a000a,0x80470000,0xb6290007,0x5865b802, +0x1063b801,0x5862b803,0x906301b8,0x0217b803, +0x90420001,0x021fa004,0x90210001,0x81df0004, +0x00000000,0x00000000,0x00ffb81a,0x011f05bb, +0x013f05b9,0xb0080000,0xb4000016,0xb0090000, +0xb4000014,0x81df0000,0x00000000,0x80270000, +0xb6280010,0x80470000,0xb629000d,0x5865b802, +0x1063b801,0x5862b803,0x914301b8,0x009ff00a, +0xb0040000,0xb4000005,0x80950002,0x906302b8, +0x0217b803,0x00000000,0x021fa004,0x90420001, +0x90210001,0x81df0004,0xa5480020,0xb00a0000, +0xb4000011,0xb0090000,0xb400000f,0x81df0000, +0x00000000,0x80870000,0xb62a000b,0x80470000, +0xb6290008,0x5865b802,0x1063b801,0x5862b803, +0x906302b8,0x0217b803,0x00000000,0x021fa004, +0x90420001,0x90210001,0x81df0004,0xb0080000, +0xb400004d,0xb0090000,0xb400004b,0x81df0000, +0x00000000,0x80270000,0xb6280047,0x80470000, +0xb6290044,0x5865b802,0x1063b801,0x5862b803, +0x914301b8,0x009ff00a,0xad420060,0x00000000, +0x00000000,0x00000000,0x114ab801,0x5942b80a, +0x914a1c80,0x0217b80a,0xb0040000,0xb400002e, +0x906302b8,0x009ff003,0xb0040000,0xb420000a, +0x80950006,0x00000000,0x021fa204,0x80950006, +0x015f8210,0x021fa204,0x80950006,0x015f8210, +0x021fa004,0xb5000026,0xb0040001,0xb4200009, +0x80950006,0x00000000,0x021fa204,0x015f8210, +0x021fa204,0x80950006,0x015f8210,0x021fa004, +0xb500001b,0xb0040003,0xb4200009,0x80950006, +0x00000000,0x021fa204,0x80950006,0x015f8210, +0x021fa204,0x015f8210,0x021fa004,0xb5000010, +0xb0040002,0xb420000e,0x80950006,0x00000000, +0x021fa204,0x015f8210,0x021fa204,0x015f8210, +0x021fa004,0xb5000006,0x8087003f,0x021fa204, +0x015f8210,0x021fa204,0x015f8210,0x021fa004, +0x90420001,0x90210001,0x81df0004,0xa5480020, +0xb4c00012,0xb0090000,0xb4000010,0x8087003f, +0x81df0000,0x5862b801,0x90631afc,0xb62a000b, +0x90630004,0x0047b803,0xb6290008,0x90420180, +0x0217b802,0x00000000,0x021fa204,0x003f8210, +0x021fa204,0x003f8210,0x021fa004,0x81df0004, +0x00ffb81a,0x8257ffff,0x82d7ffff,0x011f05bb, +0x013f05b9,0x80270000,0x00e7b809,0x300105ba, +0xb4800001,0x80e70001,0x800700bc,0x80470000, +0x81df0000,0xb0070000,0xb400004c,0xb627004b, +0x5865b802,0x1063b801,0x5862b803,0x914301b8, +0xaca20060,0x009ff00a,0x10a5b801,0x58a2b805, +0x90a502b8,0x0217b805,0xb0040000,0xb400002b, +0x1060b801,0x00bff003,0x10a5b804,0x90650160, +0x00dff003,0xb0060003,0xb4200007,0x90650134, +0x00dff003,0xb6000303,0x0075b806,0x021fa203, +0x007f8210,0xb5000021,0x5861b805,0x906300dc, +0x009fd803,0x90650134,0x00dff003,0xaca20060, +0x00000000,0x00000000,0x00000000,0x0075b806, +0x10a5b801,0x58a2b805,0x90a502b8,0x0217b805, +0x588fb804,0xb600030c,0xb6001007,0x04a3b804, +0xb4600002,0x58a1b803,0xb5000002,0x58a1b805, +0x90a50001,0x0067b805,0x9465ffff,0x5d50b805, +0x021fa20a,0x015f8210,0xb5000004,0x81470000, +0xb6000302,0x021fa20a,0x009f8210,0x009f05b9, +0xb0040002,0xb420000c,0x300105ba,0xb480000a, +0x58a2b801,0x90a502b8,0x0217b805,0x90a50180, +0x0297b805,0xb6000304,0x00bf8210,0x009f8210, +0x029fa205,0x009f8214,0x90420001,0x81df0004, +0x90210001,0x3001b808,0xb480ffa7,0xa5480020, +0xb00a0000,0xb4000019,0xb0090000,0xb4000017, +0x58a2b801,0x90a502b8,0x81df0000,0x00000000, +0x00000000,0xb62a0010,0x80470000,0xb629000d, +0xaca20060,0x00000000,0x00000000,0x00000000, +0x80670000,0x10a5b801,0x58a2b805,0x90a502b8, +0x0217b805,0xb6000302,0x021fa203,0x00bf8210, +0x90420001,0x90210001,0x81df0004,0x00ffb81a, +0x80770000,0x8057ffff,0x80f70000,0x80d7ffff, +0x81770000,0x8157ffff,0x81f70000,0x81d7ffff, +0xac140060,0xac350020,0x00000000,0x00000000, +0x12c0b801,0x5ac2b816,0x92d61980,0x83a400bd, +0xad940400,0x009f9173,0x013f05ca,0x914c6604, +0x114ab804,0x001f97e0,0x001eb80a,0xb0090000, +0xb4000003,0x80a76e44,0x80c76644,0xb5000002, +0x80a76644,0x80c76e44,0x808f000f,0x806f0000, +0x80af000e,0x80cf07e1,0x11e5b80c,0x11efb804, +0x5de2b80f,0x01ffb178,0x59e2b80f,0x01afb80f, +0x01ff9178,0x0047b86f,0xb0020001,0xb4c0fffd, +0x80cf07f0,0x1206b80c,0x1210b804,0x5e02b810, +0x021fb178,0x5a02b810,0x01afb810,0x021f9178, +0x0047b86f,0xb0020001,0xb4c0fffd,0x916c6e04, +0x116bb804,0x001f97ff,0x001eb80b,0x808f0000, +0x806f001f,0x80af001f,0x90ac6604,0x5ca2b805, +0x80270400,0x81df0000,0x00000000,0x00000000, +0xb600080a,0x00cfb801,0x00bfb178,0x58a2b805, +0x01cfb805,0x00bf9178,0x0047b86f,0xb0020001, +0xb4c0fffd,0x90210020,0x90a50020,0x81df0004, +0x90ac6e04,0x5ca2b805,0x80270500,0x81df0000, +0x00000000,0x00000000,0xb600080a,0x00cfb801, +0x00bfb178,0x58a2b805,0x01cfb805,0x00bf9178, +0x0047b86f,0xb0020001,0xb4c0fffd,0x90210020, +0x90a50020,0x81df0004,0x81530020,0xac140060, +0xac350020,0x80170800,0x80d7003c,0x12c0b801, +0x5ac2b816,0x92d602b8,0x0117b816,0x90241000, +0x0097b801,0x80470000,0x4002b803,0x81df0000, +0x00000000,0x00000000,0xb6000804,0x005f8020, +0x480287e4,0x005f8020,0x500287e4,0x81df0004, +0x00000000,0x00000000,0x00000000,0x1021b80a, +0x5c36b801,0x5801b800,0x18c0b801,0xb0090000, +0xb4000002,0x90641440,0xb5000001,0x90641040, +0x81df0000,0x00000000,0x00000000,0xb6000f0d, +0x0097b803,0x80470000,0x4002b803,0xb6001002, +0x005f8020,0x480287e4,0x0108a026,0x90630040, +0x00000000,0x1021b80a,0x5c36b801,0x5801b800, +0x18c0b801,0x81df0004,0x90641400,0x0097b803, +0x80470000,0x4002b803,0x005f8020,0x005f87e4, +0x81df0000,0x00000000,0x00000000,0xb6000802, +0x005f8040,0x480287c4,0x81df0004,0x005f87e0, +0x0108a026,0x00000000,0x1021b80a,0x5c36b801, +0x5801b800,0x18c0b801,0xb0090000,0xb4000002, +0x906417c0,0xb5000001,0x906413c0,0x81df0000, +0x00000000,0x00000000,0xb6000f0f,0x0097b803, +0x80470000,0x4002b803,0xb6000804,0x005f8020, +0x500287e4,0x005f8020,0x480287e4,0x0108a026, +0x84630040,0x00000000,0x1021b80a,0x5c36b801, +0x5801b800,0x18c0b801,0x81df0004,0xb0140000, +0xb4200005,0x90840004,0x9484003f,0x009fb173, +0xa1290001,0x013f25ca,0x80d7ffff,0x0108a026, +0x00ffb81a,0x81330004,0x8093007f,0x9884ffff, +0x80b3ff80,0x0017b816,0x90360040,0x0097b801, +0x81530010,0x81df0000,0x00000000,0x00000000, +0xb6001004,0x400a8000,0x404a8004,0x0008a020, +0x0088a022,0x81df0004,0x0017b816,0x9036007c, +0x0097b801,0x81171000,0x81df0000,0x00000000, +0x00000000,0xb6001004,0x40048020,0x480487e4, +0x00000000,0x0108a020,0x81df0004,0x81470000, +0x81670001,0x81870008,0x81a70040,0x81c707c4, +0x81e70040,0x81df0000,0x00000000,0x00000000, +0xb6000432,0xb00a0001,0xb4e00004,0x80c71000, +0x80e71000,0x81171040,0xb5000003,0x80c71040, +0x80e71040,0x81171000,0x844d0004,0x10e7b802, +0xb62b001f,0x0017b806,0x0097b807,0xb62c0004, +0x40048020,0x480487e4,0x00000000,0x0108a020, +0x0017b806,0x0097b807,0x0197b80e,0x00000000, +0x001f8020,0x042087e4,0xb62c000f,0x4041800c, +0x001f8020,0x0048b802,0x5e38802c,0x2e11b801, +0x042087e4,0x1042b810,0x0462b804,0xb4a00002, +0x0047b804,0xb5000003,0x0462b805,0xb4600001, +0x0047b805,0x011fa022,0x10c6b80f,0x10e7b80f, +0x5961b80b,0x5d81b80c,0x5da1b80d,0x5de1b80f, +0x914a0001,0x954a0001,0x11ceb80f,0x81df0004, +0x80171018,0x81171fcc,0x80470000,0x41448020, +0x494487c0,0x00000000,0x0188b80a,0x494487e0, +0x00000000,0x0148b80a,0x0502a10a,0x4145b80c, +0x494580e0,0x00000000,0x0108a5ea,0x41448080, +0x494487c0,0x00000000,0x0108a78a,0x49448020, +0x00000000,0x0108a2ea,0x41448020,0x49448720, +0x00000000,0x0188b80a,0x4145b80c,0x49458080, +0x494587a0,0x00000000,0x0108a68a,0x4145b80c, +0x49458080,0x494587a0,0x00000000,0x0108a08a, +0x4145b80c,0x49458020,0x49458040,0x00000000, +0x0188b80a,0x494587e0,0x00000000,0x0108a08a, +0x4144b80c,0x494587a0,0x00000000,0x0108a52a, +0x41448080,0x49448040,0x494486c0,0x00000000, +0x0108a04a,0x41448040,0x49448720,0x00000000, +0x0108a36a,0x04028020,0x011fa420,0x001f8040, +0x011fa100,0x001f8080,0x011fa080,0x001f8100, +0x011fa040,0x001f8660,0x011fa120,0x41458020, +0x49458000,0x00000000,0x0108a00a,0x0017b816, +0x9036007c,0x0097b801,0x81171000,0x81970784, +0x00000000,0x001f8020,0x042087e4,0x81df0000, +0x00000000,0x00000000,0xb600100f,0x4041800c, +0x001f8020,0x0048b802,0x5e38802c,0x2e11b801, +0x042087e4,0x1042b810,0x0462b804,0xb4a00002, +0x0047b804,0xb5000003,0x0462b805,0xb4600001, +0x0047b805,0x011fa022,0x81df0004,0x81470000, +0x81670001,0x81870008,0x81a70040,0x81c707c4, +0x81e70040,0x81df0000,0x00000000,0x00000000, +0xb6000432,0xb00a0001,0xb4e00004,0x80c71000, +0x80e71000,0x81171040,0xb5000003,0x80c71040, +0x80e71040,0x81171000,0x844d0004,0x10e7b802, +0xb62b001f,0x0017b806,0x0097b807,0xb62c0004, +0x40048020,0x480487e4,0x00000000,0x0108a020, +0x0017b806,0x0097b807,0x0197b80e,0x00000000, +0x001f8020,0x042087e4,0xb62c000f,0x4041800c, +0x001f8020,0x0048b802,0x5e38802c,0x2e11b801, +0x042087e4,0x1042b810,0x0462b804,0xb4a00002, +0x0047b804,0xb5000003,0x0462b805,0xb4600001, +0x0047b805,0x011fa022,0x10c6b80f,0x10e7b80f, +0x5961b80b,0x5d81b80c,0x5da1b80d,0x5de1b80f, +0x914a0001,0x954a0001,0x11ceb80f,0x81df0004, +0x80171034,0x81171f84,0x80470000,0x41448040, +0x49448640,0x00000000,0x0188b80a,0x49448100, +0x49448780,0x00000000,0x0108a08a,0x4144b80c, +0x49448040,0x49448080,0x494487c0,0x00000000, +0x0108a16a,0x4145b80c,0x49458700,0x00000000, +0x0188b80a,0x494581a0,0x494586e0,0x00000000, +0x0108a66a,0x4145b80c,0x49448040,0x494487e0, +0x00000000,0x0188b80a,0x011fa1ec,0x4145b80c, +0x49458100,0x49458780,0x00000000,0x0108a08a, +0x41458720,0x49458100,0x494586e0,0x49458160, +0x49458020,0x49458020,0x49458760,0x00000000, +0x0108a08a,0x414587a0,0x49458080,0x49458760, +0x494580c0,0x49458700,0x49458140,0x49458020, +0x49458760,0x00000000,0x0108a74a,0x414587a0, +0x49458080,0x49458760,0x494580e0,0x49458700, +0x49458120,0x49458020,0x49458760,0x00000000, +0x0108a08a,0x41458720,0x49458100,0x494586e0, +0x49458140,0x49458040,0x49458020,0x49458720, +0x00000000,0x0108a0ca,0x41458080,0x49458040, +0x49458020,0x49458620,0x00000000,0x0188b80a, +0x49458080,0x00000000,0x0108a7ca,0x4144b80c, +0x49458040,0x49458020,0x49458080,0x00000000, +0x0108a5ea,0x41448080,0x49448700,0x00000000, +0x0188b80a,0x49448780,0x00000000,0x0108a7ca, +0x4144b80c,0x49448140,0x00000000,0x0108a7ca, +0x49448040,0x00000000,0x0108a0ca,0x41448700, +0x00000000,0x0188b80a,0x49448000,0x00000000, +0x0108a04a,0x011fa00c,0x80171f80,0x81df0000, +0x00000000,0x00000000,0xb6002006,0x40048000, +0x48048000,0x48048000,0x48048000,0x00000000, +0x0008a020,0x81df0004,0x00ffb81d,0x00000000, +0x80770000,0x8057ffff,0x015f05b9,0x017f05bb, +0x8293ffff,0x9a94ffff,0x81a70000,0x81df0000, +0x00000000,0x00000000,0xb62a003a,0xaded0180, +0xae0d0180,0xadcd0080,0x902f1980,0x0017b801, +0xb6002033,0x904e01b8,0x00000000,0x013ff002, +0xb0090000,0xb400001f,0x904f02b8,0x80c70000, +0x011fd802,0x6829b808,0x94210001,0xb0010001, +0xb4e00001,0x00c7b814,0x6429b806,0x80470001, +0x6449b802,0x84420001,0x1442b808,0x84690001, +0x5863b803,0x906300dc,0x1042b801,0x003f9803, +0x90420001,0x4082b801,0x90630004,0x003f9803, +0x00000000,0x5897b804,0x1804b805,0x4082b801, +0x00000000,0x00000000,0x00000000,0x10a4b800, +0xb5000001,0x80a70000,0x90501c80,0x00000000, +0x007ff002,0x5842b803,0x904205f8,0x0097b802, +0x00000000,0x40058004,0x48058004,0x00000000, +0x0008a020,0x91ce0004,0x91ef0004,0x92100004, +0x91ad0001,0x81df0004,0x00ffb81a,0x80770000, +0x8057ffff,0x80d7ffff,0x015f05b9,0x017f05bb, +0x8293ff80,0x9a940000,0x82a70020,0x81a70000, +0x81e702b8,0x80171980,0x81df0000,0x00000000, +0x00000000,0xb62a004f,0xb600034d,0xac0d0080, +0xac4d0180,0xac960080,0x822700bc,0x91c001b8, +0x00000000,0x1042b804,0x92021c80,0xb62b003a, +0x013ff00e,0x00fff011,0xb0090000,0xb4000027, +0x10e7b809,0x5821b807,0x902100dc,0x00000000, +0x001fd801,0x82470000,0x80270001,0x6452b801, +0x3002b800,0xb4600002,0x92520001,0xb500fffb, +0x86520001,0x80c70000,0x011fd80f,0x6832b808, +0xb0010001,0xb4e00001,0x00c7b814,0x84520017, +0x0056b802,0x80270001,0x6432b801,0x84210001, +0x1408b801,0x6402b800,0x10c6b800,0x9027018c, +0x00000000,0x001ff001,0x5802b800,0x9020073c, +0x904006f8,0x007f9801,0x0097b802,0x10c6b803, +0x40868004,0x48868004,0xb5000003,0x80c70000, +0x40868004,0x00000000,0x0088b804,0x003ff010, +0x5822b801,0x902105f8,0x0097b801,0x91ce0004, +0x91ef0004,0x40448004,0x48448004,0x92100004, +0x0008a022,0x92310001,0x0435b80b,0xb4000007, +0x80870000,0xb6210005,0x001fa024,0x91ce0004, +0x91ef0004,0x92100004,0x92310001,0x00000000, +0x91ad0001,0x81df0004,0x00ffb81a,0x00000000, +0x007f05b9,0x001f0081,0xb0000001,0xb440002d, +0x001f05d8,0xac400080,0x801702b8,0x80970438, +0x90421800,0x0117b802,0x8087ffff,0x80b3ffff, +0x80d3007f,0x98c6ff00,0x80f3ff80,0x81070080, +0x81df0000,0x00000000,0x00000000,0xb6002018, +0x10088020,0x0056b800,0x0442b806,0xb4a00004, +0xb0000000,0x0007b806,0xb4400001,0x0007b807, +0x0027b800,0x5c08b800,0x1400b804,0xb0030001, +0xb4000008,0x10288024,0x0056b801,0x0442b806, +0xb4a00004,0xb0010000,0x0027b806,0xb4400001, +0x0027b807,0x5828b801,0x1421b805,0x1900a021, +0x81df0004,0x001f05d8,0x90000001,0x001f25d8, +0x00ffb81a,0x801702b8,0x80970438,0x81171800, +0x8087ffff,0x80b3ffff,0x80d3007f,0x98c6ff00, +0x80f3ff80,0x81070080,0x81df0000,0x00000000, +0x00000000,0xb6006018,0x10088020,0x0056b800, +0x0442b806,0xb4a00004,0xb0000000,0x0007b806, +0xb4400001,0x0007b807,0x0027b800,0x5c08b800, +0x1400b804,0xb0030001,0xb4000008,0x10288024, +0x0056b801,0x0442b806,0xb4a00004,0xb0010000, +0x0027b806,0xb4400001,0x0027b807,0x5828b801, +0x1421b805,0x1900a021,0x81df0004,0x00ffb81a, +0x001f0081,0xb0000001,0xb4400006,0x001f05d8, +0xb0000003,0xb4000003,0x80270001,0x003f25dc, +0x00ffb81a,0x003f05d9,0x009f05cb,0xb0010000, +0xb400000e,0x015f42ed,0x81070000,0x8127017c, +0xb00a0000,0xb4000002,0x81070180,0x812702fc, +0x802500a5,0x9421ffff,0x3001b808,0xb4800011, +0x3001b809,0xb4a0007f,0xb500000e,0x001f0081, +0xb0000001,0xb4400003,0xb0040002,0xb4200006, +0xb5000002,0xb0040000,0xb4200003,0x802702ff, +0x81470000,0xb5000003,0x80270001,0x003f25d9, +0x81470180,0xb0040000,0xb4200001,0x838402ea, +0x80070000,0x001f25d8,0x009f902d,0x80af001f, +0x808f0000,0x806f0000,0x8007ffff,0x8033ffff, +0x80171800,0x81df0000,0x807bff8c,0x94630003, +0xb0030003,0xb4000016,0xb0030002,0xb4000035, +0xb0030001,0xb4000024,0xb6006010,0x14618000, +0x6068b803,0x40c4b803,0x14608000,0x00c8b806, +0x5870b803,0x6068b803,0x4104b803,0x58c8b806, +0x0108b808,0x14c6b801,0x00000000,0x00000000, +0x5d08b808,0x1508b800,0x1806a028,0xb5000030, +0xb6006010,0x14618000,0x6068b803,0x40c4b803, +0x14608000,0x00c8b806,0x5870b803,0x6068b803, +0x4104b803,0x5cc8b806,0x0108b808,0x14c6b800, +0x00000000,0x00000000,0x5908b808,0x1508b801, +0x1806a028,0xb500001e,0xb600600d,0x14618000, +0x6068b803,0x40c4b803,0x00000000,0x00c8b806, +0x00000000,0x00000000,0x00000000,0x5d08b806, +0x1508b800,0x58c8b806,0x14c6b801,0x1806a028, +0xb500000f,0xb600600e,0x14608000,0x5868b803, +0x6068b803,0x40c4b803,0x00000000,0x00c8b806, +0x00000000,0x00000000,0x00000000,0x5d08b806, +0x1508b800,0x58c8b806,0x14c6b801,0x1806a028, +0x81df0004,0x80670600,0x5d22b80a,0x81df0000, +0x00000000,0x00000000,0xb600030a,0x00cfb803, +0x013fb178,0x5922b809,0x01afb809,0x013f9178, +0x0047b86f,0xb0020001,0xb4c0fffd,0x90630020, +0x91290020,0x81df0004,0x81270180,0xb00a0000, +0xb4000001,0x81270000,0x013f62ed,0x80270001, +0x003f25dc,0x00ffb81a,0x001f0081,0xb0000001, +0xb4400006,0x001f05d8,0xb0000003,0xb4000003, +0x80270001,0x003f25dc,0x00ffb81a,0x003f05d9, +0x009f05cb,0xb0010000,0xb400000e,0x015f42ed, +0x81070000,0x8127017c,0xb00a0000,0xb4000002, +0x81070180,0x812702fc,0x802500a5,0x9421ffff, +0x3001b808,0xb4800011,0x3001b809,0xb4a0007f, +0xb500000e,0x001f0081,0xb0000001,0xb4400003, +0xb0040002,0xb4200006,0xb5000002,0xb0040000, +0xb4200003,0x802702ff,0x81470000,0xb5000003, +0x80270001,0x003f25d9,0x81470180,0xb0040000, +0xb4200001,0x83840250,0x80070000,0x001f25d8, +0x009f902d,0x80af001f,0x808f0000,0x806f0000, +0x8007ffff,0x8033ffff,0x80171800,0x807bff8c, +0x81df0000,0x94630003,0xb0030003,0xb4000016, +0xb0030002,0xb4000035,0xb0030001,0xb4000024, +0xb6006010,0x14618000,0x6068b803,0x40c4b803, +0x14608000,0x00c8b806,0x5870b803,0x6068b803, +0x4104b803,0x58c8b806,0x0108b808,0x14c6b801, +0x00000000,0x00000000,0x5d08b808,0x1508b800, +0x1806a028,0xb5000030,0xb6006010,0x14618000, +0x6068b803,0x40c4b803,0x14608000,0x00c8b806, +0x5870b803,0x6068b803,0x4104b803,0x5cc8b806, +0x0108b808,0x14c6b800,0x00000000,0x00000000, +0x5908b808,0x1508b801,0x1806a028,0xb500001e, +0xb600600d,0x14618000,0x6068b803,0x40c4b803, +0x00000000,0x00c8b806,0x00000000,0x00000000, +0x00000000,0x5908b806,0x1508b801,0x5cc8b806, +0x14c6b800,0x1806a028,0xb500000f,0xb600600e, +0x14608000,0x5870b803,0x6068b803,0x40c4b803, +0x00000000,0x00c8b806,0x00000000,0x00000000, +0x00000000,0x5908b806,0x1508b801,0x5cc8b806, +0x14c6b800,0x1806a028,0x81df0004,0x80670600, +0x5d22b80a,0x81df0000,0x00000000,0x00000000, +0xb600030a,0x00cfb803,0x013fb178,0x5922b809, +0x01afb809,0x013f9178,0x0047b86f,0xb0020001, +0xb4c0fffd,0x90630020,0x91290020,0x81df0004, +0x81270180,0xb00a0000,0xb4000001,0x81270000, +0x013f62ed,0x80270001,0x003f25dc,0x00ffb81a, +0x029fb024,0x02bfb025,0x02dfb026,0x02ffb027, +0x031fb028,0x033fb029,0x033f4046,0x0287b86f, +0x029fb02a,0x8285009c,0x96b48000,0xb0158000, +0xb400018e,0x96b40100,0xb0150100,0xb40001a4, +0x96b40400,0xb0150400,0xb40001a5,0x96b40001, +0xb0150001,0xb400000c,0x96b40008,0xb0150008, +0xb4000197,0x96b44000,0xb0154000,0xb40001a4, +0x96b40002,0xb0150002,0xb400015b,0x00000000, +0x00000000,0xb50001b6,0x02bf917e,0x92b50001, +0x02bfb17e,0x82850082,0x5efdb814,0x96f70001, +0xb0170001,0xb420000b,0x83050069,0x9718003f, +0x82e50064,0x12f7b818,0x86f70109,0x82feff74, +0x02e7b86f,0x9af74000,0x01ffb817,0x96f7bfff, +0x01ffb817,0x83050081,0x82a5009a,0x96b50001, +0xb0150001,0xb4200014,0x82a70000,0x02bfb17e, +0x96b41840,0xb0150800,0xb420000c,0x96b40008, +0x5aa9b815,0x96d46000,0x5ec3b816,0x82f3000f, +0x9af7c00f,0x1718b817,0x1ab5b818,0x1ab5b816, +0x9ab50340,0x82a60081,0xb500012b,0x9b180180, +0x83060081,0xb5000128,0x82a5009a,0x96b50002, +0xb0150002,0xb420001b,0x82a70000,0x02bfb17e, +0x96b41800,0xb0151800,0xb4000013,0x96b40040, +0xb0150040,0xb4200004,0xa3180c00,0x9b180340, +0x83060081,0xb5000118,0x96b40008,0x5aa9b815, +0x96d46000,0x5ec3b816,0x82f3000f,0x9af7c00f, +0x1718b817,0x1ab5b818,0x1ab5b816,0x9ab50340, +0x82a60081,0xb500010c,0x9b180180,0x83060081, +0xb5000109,0x82a500c1,0x96b5000f,0xb015000b, +0xb420000e,0x96b40020,0xb0150020,0xb400000b, +0x96b40200,0xb0150200,0xb4000008,0x82c50086, +0x82e50094,0x3016b817,0xb4400004,0x06f7b816, +0xb017ff00,0xb4400001,0xb50000f7,0x96b46000, +0xb0156000,0xb4000011,0x96b41820,0xb0150820, +0xb4200004,0x9b391000,0x82a5009a,0x96b5feff, +0x82a6009a,0x96b40040,0xb0150040,0xb4200001, +0x9739efff,0x96b91000,0xb0151000,0xb4200003, +0x82a5009a,0x9ab50100,0x82a6009a,0x96b40040, +0xb0150040,0xb4200019,0x96b41800,0xb0151800, +0xb4200006,0x96b98000,0xb0158000,0xb4200003, +0x9b180180,0x83060081,0xb50000d7,0x96d80c00, +0x82b300ff,0x9ab5f3ff,0x1718b815,0xb0160c00, +0xb4000007,0x82e50098,0x96f70400,0xb0170400, +0xb4200002,0x82c70c00,0xb5000001,0xa2d60c00, +0x1b18b816,0x9b180340,0xb50000bd,0x96b40220, +0xb0150000,0xb4e00021,0x82a5009d,0x82f3ffff, +0x16b5b817,0x82f3000e,0x3015b817,0xb420001b, +0x96f98000,0xb0178000,0xb4000018,0x82a70000, +0x02bfb17e,0x82c5009d,0x96d6ffff,0x82b30032, +0x9ab58001,0x82e500c1,0x96f7000f,0xb017000b, +0xb4000002,0x82b30022,0x9ab58001,0x1ab5b816, +0x82c5009a,0x96d60020,0xb0160020,0xb4200002, +0x82b30032,0x9ab58001,0x82a6009d,0x02ff917e, +0x00000000,0xb0170040,0xb4800000,0x5eb5b814, +0x96b500f0,0x96f46000,0x5eedb817,0x1ab5b817, +0xb0170003,0xb4000004,0x96b500ef,0x96f70001, +0x5ae4b817,0x1ab5b817,0x96d41800,0xb0161800, +0xb400000a,0x96f900ff,0x96b500ff,0x9739ff00, +0x1b39b815,0x02a7b817,0x96b500f3,0x96d40008, +0x5ec1b816,0x1ab5b816,0xb500000c,0x96f98000, +0xb0178000,0xb4200007,0x5efeb814,0x96f70001, +0xb0170001,0xb4000003,0x9b180180,0x83060081, +0xb5000081,0x96b500f3,0x9ab50008,0x9739fff3, +0x96d40020,0xb0160020,0xb4200017,0x9b398000, +0x82c70000,0x02dfb17e,0x96d40010,0x5ac8b816, +0x82f300ff,0x9af7cfff,0x1718b817,0x1b18b816, +0x9b180340,0x82c5009d,0x96d6ffff,0x82f3000e, +0x9af78001,0x1af7b816,0x82c5009a,0x96d60020, +0xb0160020,0xb4200002,0x82f30032,0x9af78001, +0x82e6009d,0xb500005a,0x97397fff,0x96b500ff, +0x5aaab815,0x82f300fc,0x9af703ff,0x1718b817, +0x1b18b815,0x9b180340,0x82c5009a,0x96d60010, +0xb0160010,0xb4200024,0x82c70000,0x02dfb17e, +0x82c50086,0x92d60e10,0x82c60086,0x82c50094, +0x5eefb818,0x96f70003,0xb0170003,0xb4200002, +0x82e70e10,0xb5000001,0x82e70e10,0x12d6b817, +0x82e50081,0x9af70020,0x82e60081,0x82c60094, +0xa2f70020,0x82e60081,0x82f30001,0x16f7b818, +0x5ef0b817,0xb0170001,0xb4000004,0x96f84000, +0x5ee4b817,0x9718f3ff,0x1b18b817,0x82f3000a, +0x9af78000,0x82e6009d,0x83060081,0x83070001, +0x8306009f,0xb5000096,0x82c5009d,0x82f3000e, +0x9af78001,0x3016b817,0xb420000f,0x82b30032, +0x9ab58001,0x82e500c1,0x96f7000f,0xb017000b, +0xb4000002,0x82b30022,0x9ab58001,0x82c5009a, +0x96d60020,0xb0160020,0xb4200002,0x82b30032, +0x9ab58001,0x82a6009d,0x82c5009a,0x96d60080, +0xb0160080,0xb4000011,0x02df917e,0x00000000, +0xb0160010,0xb480000d,0x82c500c1,0x96d6000f, +0xb016000b,0xb4000009,0x82c50087,0x96d60080, +0x5ac7b816,0x96f84000,0x3017b816,0xb4200003, +0x033f4046,0x9b394000,0xb500000b,0x9739bfff, +0x82e50061,0x96f70008,0xb0170008,0xb4000005, +0x5eefb818,0x96f70003,0xb0170003,0xb4000001, +0x9718ffff,0x83060081,0x83070001,0x8306009f, +0x00000000,0xb500005e,0x82850083,0x96b400ff, +0xb015003c,0xb4200019,0x96b92000,0xb0152000, +0xb4000002,0x9b392000,0xb5000014,0x9739d3ff, +0x82870000,0x82860087,0x82870008,0x82860083, +0x829bff78,0x82a7001f,0xb0140400,0xb4000001, +0x82a70010,0x82a600c9,0x829bff78,0x00000000, +0x828600cb,0x8285009d,0x82b3ffff,0x9ab5fffd, +0x1694b815,0x8286009d,0xb5000000,0x83070002, +0x8306009f,0x00000000,0xb500003d,0x96b90800, +0xb0150800,0xb4200009,0x9739f7ff,0x82a703fd, +0x82a600cb,0x82a7003c,0x82a60083,0x8285009d, +0x9a940002,0x8286009d,0xb5000004,0x82850087, +0x5a82b814,0xa2940200,0x82860087,0xb5000000, +0x83078000,0x8306009f,0x00000000,0xb5000028, +0x83070008,0x8306009f,0x00000000,0xb5000024, +0x83070100,0x8306009f,0x00000000,0xb5000020, +0x83070000,0x83050081,0x9b180180,0x83060081, +0x83070400,0x8306009f,0x00000000,0xb5000018, +0x82870000,0x82850082,0x5eb7b814,0x96b500fc, +0x96d40006,0x5ec1b816,0x1ab5b816,0x5aacb815, +0x83050081,0x82d3001c,0x9ad600ff,0x1718b816, +0x1b18b815,0x9b180e00,0x83060081,0x83074000, +0x8306009f,0x8305009d,0x82d300ff,0x9ad6bfff, +0x1718b816,0x8306009d,0x00000000,0xb5000000, +0x029f902a,0x01ffb814,0x033f6046,0x029f9024, +0x02bf9025,0x02df9026,0x02ff9027,0x031f9028, +0x033f9029,0x00ffb81e,0x02ff917d,0x92f7092f, +0x031f0084,0xb0180001,0xb4200002,0x02ff917d, +0x92f70870,0x02ffb17d,0x02ff917c,0x82bbffdc, +0x829bffd8,0x93150004,0x3014b815,0xb4000017, +0x02dbb818,0x029bb815,0x3017b816,0xb4800013, +0x5a81b814,0x029fb17d,0x82def200,0x82fef204, +0x82e50086,0x06f7b814,0x02f6b817,0x82fef208, +0x82860095,0x82870001,0x829ef220,0x8293001f, +0x9294fe00,0x92b50008,0x3015b814,0xb4800002, +0x82b3001f,0x92b5fa00,0x82beffdc,0x82850086, +0x83250094,0x06d4b819,0x02d6b816,0xb016ffff, +0xb4a00009,0x82c50081,0x9ab60020,0x82a60081, +0x82a50086,0x92b50e10,0x82a60094,0x82c60081, +0x86b50704,0x82a6009b,0x00ffb81c,0x00000000, +0x001f9012,0x001fb200,0x001f004c,0x001f2804, +0x801bfef0,0x8058fef4,0x803bff68,0x8078ff6c, +0x2000b801,0x2042b803,0x001fb204,0x005f2814, +0x82e70001,0x83640048,0x029fb014,0x829efef0, +0x8286000f,0x02bf2054,0x82bcfef4,0x82a6000e, +0x00ffb81a,0x80e70001,0x801336e3,0x9800eb76, +0x001fb200,0x800700ab,0x001f2804,0x801bc3e8, +0x8058c3ec,0x83640024,0x82e70000,0x83640036, +0x029fb3c0,0x029fb200,0x02bf2f04,0x02bf2804, +0x801bc000,0x8058c004,0x8364001b,0x82e70000, +0x8364002d,0x001f93c0,0x3000b814,0xb420000a, +0x001f0f04,0x3000b815,0xb4200007,0x829efef0, +0x82bcfef4,0x029fb012,0x02bf204c,0x82870001, +0x829cfef5,0x00ffb81a,0xb0070000,0xb4000007, +0x80e70000,0x801399fa,0x9800c92e,0x001fb200, +0x800700af,0x001f2804,0xb500ffdc,0x82870000, +0x829cfef5,0x00ffb81a,0x80c700ff,0x803bff68, +0x8078ff6c,0x14a0b806,0x2063b805,0x007f2814, +0x2021b802,0x58c8b806,0x14a0b806,0x58b0b805, +0x2021b805,0x58c8b806,0x14a0b806,0x2021b805, +0x58c8b806,0x14a0b806,0x5cb0b805,0x2021b805, +0x003fb204,0x00ffb81b,0x82c70000,0x83070800, +0x83270005,0x8197080c,0x81d7ffff,0x83840126, +0x83840001,0x00ffb81b,0x808f0000,0x806f001f, +0x80af001f,0x80270240,0x81e77c08,0x5de2b80f, +0xb6000208,0x00cfb801,0x01ffb178,0x59e2b80f, +0x01cfb80f,0x01ff9178,0xb520ffff,0x91ef0020, +0x90210020,0x80270280,0x81e77b00,0x5de2b80f, +0xb6000208,0x00cfb801,0x01ffb178,0x59e2b80f, +0x01cfb80f,0x01ff9178,0xb520ffff,0x91ef0020, +0x90210020,0x8057ffff,0x80170830,0x80070810, +0x80270808,0xb6000509,0x005ff000,0x90420900, +0x007ff001,0x90630a00,0x009ff002,0x00bff003, +0x2004a025,0x90000001,0x90210001,0x80070814, +0x80d7ffff,0x8097085c,0x8017083c,0xb6000404, +0x005ff000,0x007f87e0,0x84000001,0x2082a7e3, +0x80970860,0x80170840,0x2082b803,0x007f8000, +0x2083a004,0x80170830,0x80970850,0x80270808, +0xb6000508,0x005f8024,0x90420900,0x007ff001, +0x90630a00,0x009ff002,0x00bff003,0x2004a025, +0x90210001,0x80170840,0x00000000,0x02bf87e0, +0x80970860,0x82870000,0xb6000404,0x005f87e4, +0x5a88b814,0x204287e0,0x1a94b802,0x00ffb81c, +0x001f0e49,0x001f2b09,0x001f0e41,0x001f2b08, +0x001f0e46,0x001f2b07,0x001f0e48,0x001f2b06, +0x001f0e42,0x001f2b05,0x001f0e47,0x001f2b04, +0x001f0e45,0x001f2b03,0x001f0e43,0x001f2b02, +0x001f0e40,0x001f2b01,0x001f0e44,0x001f2b00, +0x001f0f25,0xa020000c,0x94400001,0x94600002, +0x94810004,0x94a10008,0x94c00010,0x5943b802, +0x5861b803,0x5882b804,0x5ca2b805,0x5cc4b806, +0x194ab803,0x194ab804,0x194ab805,0x194ab806, +0x015f2b38,0x801b7c00,0x003f92c1,0x5c28b801, +0x005f92c2,0x5858b802,0x1821b802,0x2000b801, +0x001fb2c4,0x80187c04,0x003f0b09,0x2000b801, +0x001f2b14,0x82c70001,0x82e70001,0x83070b10, +0x8327001e,0x81970b35,0x8384009f,0x02df0b38, +0x82170e30,0x838400f1,0x819efef0,0x817cfef4, +0x819eff68,0x817cff6c,0x00ffb81b,0x820f001f, +0x8018fef8,0x8057ffff,0x001f2b09,0x8018fef6, +0x80d7ffff,0x001f2b08,0x8018fefa,0x8157ffff, +0x001f2b07,0x8018fefd,0x81d7ffff,0x001f2b06, +0x8018fefb,0x802f001f,0x001f2b05,0x8018fefe, +0x00000000,0x001f2b04,0x8018fef9,0x00000000, +0x001f2b03,0x8018feff,0x00000000,0x001f2b02, +0x8018fef7,0x00000000,0x001f2b01,0x8018fefc, +0x00000000,0x001f2b00,0x001f0f25,0xa0200011, +0x94410001,0x94600002,0x94800004,0x94a00008, +0x94c10010,0x5941b802,0x5861b803,0x5c82b804, +0x58a1b805,0x5cc1b806,0x194ab803,0x194ab804, +0x194ab805,0x194ab806,0x015f2b38,0x801b7c00, +0x003f92c1,0x5c28b801,0x005f92c2,0x5858b802, +0x1821b802,0x2000b801,0x001fb2c4,0x80187c04, +0x003f0b09,0x2000b801,0x001f2b14,0x82c70001, +0x82e70001,0x83070b10,0x8327001e,0x81970b35, +0x83840055,0x02df0b38,0x82170e20,0x838400a7, +0x819efef0,0x817cfef4,0x5ac8b80c,0x02ff0e44, +0x1ad6b817,0x02dfb391,0x5ed8b80c,0x5968b80b, +0x1ad6b80b,0x02df6724,0x00ffb81b,0x820f001f, +0x8018fefe,0x8057ffff,0x001f2b09,0x8018fefa, +0x80d7ffff,0x001f2b08,0x8018fefc,0x8157ffff, +0x001f2b07,0x8018feff,0x81d7ffff,0x001f2b06, +0x8018fef8,0x802f001f,0x001f2b05,0x8018fefb, +0x00000000,0x001f2b04,0x8018fefd,0x00000000, +0x001f2b03,0x8018fef6,0x00000000,0x001f2b02, +0x8018fef9,0x00000000,0x001f2b01,0x8018fef7, +0x00000000,0x001f2b00,0x801b7c00,0x003f92c1, +0x5c28b801,0x005f92c2,0x5858b802,0x1821b802, +0x2000b801,0x001fb2c4,0x80187c04,0x003f0b09, +0x2000b801,0x001f2b14,0x82c70001,0x82e70001, +0x83070b10,0x8327001e,0x81970b35,0x83840016, +0x83270000,0x831bfef0,0x82f8fef4,0x02c7b819, +0x82170e28,0x83840065,0x300cb818,0xb4200002, +0x300bb817,0xb4000006,0x93390001,0xb0190020, +0xb480fff6,0x83270000,0x833cfef5,0x00ffb81b, +0x019fb390,0x017f2e44,0x033f2f25,0x83270001, +0x833cfef5,0x00ffb81b,0x0007b818,0x90000003, +0x00000000,0x015ff000,0x90000001,0x5949b80a, +0x013ff000,0x194ab809,0x84000002,0x994a0100, +0x017ff000,0x958b00f8,0x5981b80c,0x956b0007, +0x198cb80b,0x84000002,0x998c0008,0x017ff000, +0x90000001,0x5971b80b,0x198cb80b,0x017ff000, +0x5969b80b,0x198cb80b,0x81a70000,0x94d90003, +0x82a70000,0xb6260019,0xb6000818,0x5df0b80a, +0x5e02b80a,0x21efb810,0x95ef0001,0x5941b80a, +0x194ab80f,0x21efb816,0x5e18b80c,0x5e35b80c, +0x5e54b80c,0x5e6cb80c,0x2210b811,0x2252b813, +0x2210b812,0x96100001,0x5981b80c,0x198cb810, +0x2210b817,0x10afb810,0x10a5b80d,0x5da1b805, +0x94a50001,0x5aa1b815,0x1ab5b805,0x019fa7f5, +0x5cc2b819,0xb626001c,0x82870000,0xb6000419, +0xb6000818,0x5df0b80a,0x5e02b80a,0x21efb810, +0x95ef0001,0x5941b80a,0x194ab80f,0x21efb816, +0x5e18b80c,0x5e35b80c,0x5e54b80c,0x5e6cb80c, +0x2210b811,0x2252b813,0x2210b812,0x96100001, +0x5981b80c,0x198cb810,0x2210b817,0x10afb810, +0x10a5b80d,0x5da1b805,0x94a50001,0x5a81b814, +0x1a94b805,0x019fa7f4,0x00ffb81c,0x8257ffff, +0x808f0000,0x806f001f,0x80af001f,0x80270300, +0x81e778e0,0x5de2b80f,0xb6000208,0x00cfb801, +0x01ffb178,0x59e2b80f,0x01cfb80f,0x01ff9178, +0xb520ffff,0x91ef0020,0x90210020,0x80270340, +0x81e779e0,0x5de2b80f,0xb6000208,0x00cfb801, +0x01ffb178,0x59e2b80f,0x01cfb80f,0x01ff9178, +0xb520ffff,0x91ef0020,0x90210020,0x80270280, +0x81e77b00,0x5de2b80f,0xb6000208,0x00cfb801, +0x01ffb178,0x59e2b80f,0x01cfb80f,0x01ff9178, +0xb520ffff,0x91ef0020,0x90210020,0x806f0007, +0x80af0007,0x80270380,0x81e77ae0,0x5de2b80f, +0x00cfb801,0x01ffb178,0x59e2b80f,0x01cfb80f, +0x01ff9178,0xb520ffff,0x91ef0020,0x90210020, +0x80170b60,0x001f0b00,0x001fa020,0x001f0b01, +0x001fa020,0x001f0b02,0x001fa020,0x001f0b03, +0x001fa020,0x001f0b04,0x001fa000,0x80970b50, +0x81170b70,0x82a70b35,0x83a40060,0x001f87e4, +0xb6000405,0x86b50001,0x83a4005c,0x001f8004, +0x003f87e8,0x2080a7e1,0x80970b70,0x80170b50, +0x81170b50,0x81970b40,0x82a70b30,0x001f800c, +0x003f8008,0x2100a001,0x83a40050,0x001f87e4, +0xb6000405,0x86b50001,0x83a4004c,0x001f8004, +0x003f87e8,0x2080a7e1,0x80970b50,0x80170b70, +0x81170b70,0x81970b60,0x82a70b2b,0x001f800c, +0x003f8008,0x2100a001,0x83a40040,0x83a4004e, +0xb6000407,0x86b50001,0x83a4003c,0x001f8004, +0x003f87e8,0x2080a001,0x83a40047,0x00000000, +0x80970b70,0x80170b50,0x81170b50,0x81970b40, +0x82a70b26,0x001f800c,0x003f8008,0x2100a001, +0x83a4002e,0x83a4003c,0xb6000407,0x86b50001, +0x83a4002a,0x001f8004,0x003f87e8,0x2080a001, +0x83a40035,0x00000000,0x80970b50,0x80170b70, +0x81170b70,0x81970b60,0x82a70b21,0x001f800c, +0x003f8008,0x2100a001,0x83a4001c,0x001f87e4, +0xb6000405,0x86b50001,0x83a40018,0x001f8004, +0x003f87e8,0x2080a7e1,0x80970b70,0x80170b50, +0x81170b50,0x81970b40,0x82a70b1c,0x001f800c, +0x003f8008,0x2100a001,0x83a4000c,0x017f87e4, +0x81870000,0xb6000406,0x86b50001,0x83a40007, +0x001f87e4,0x200087e8,0x5988b80c,0x198cb800, +0x021fa02c,0x021fa00b,0x00ffb81c,0x005ff015, +0x90420a00,0x003f87e0,0x001ff002,0x2060b801, +0x90630c00,0x90960e00,0x001ff003,0x003ff004, +0x20a0b801,0x90a50d00,0x00000000,0x001ff005, +0x009fa000,0x00ffb81d,0x001f8004,0x5c21b800, +0x5847b800,0x1821b802,0x942100ff,0x2080a7e1, +0x00ffb81d,0x00000000,0x00000000,0x00000000, + +}; + +static u32 MPGUcode1f5c00[] = { +0x00000000,0xfffff8c0,0x00003540,0xffff8d40, +0x0001fd40,0xfffaf7c0,0x00066b80,0xffdb63c0, +0x00494780,0x00249c40,0x00066b80,0x00050840, +0x0001fd40,0x000072c0,0x00003540,0x00000740, +0xffffffc0,0xfffff840,0x00003680,0xffff7e40, +0x0001f400,0xfffa9cc0,0x0005d1c0,0xffd99600, +0x00493c00,0x0022ce00,0x0006f780,0x0004ad00, +0x000203c0,0x00006440,0x00003400,0x00000680, +0xffffffc0,0xfffff740,0x00003780,0xffff6ec0, +0x0001e800,0xfffa4240,0x00052a00,0xffd7ca00, +0x00491a00,0x0020ffc0,0x00077600,0x00045240, +0x00020800,0x000056c0,0x00003280,0x00000600, +0xffffffc0,0xfffff680,0x00003840,0xffff5ec0, +0x0001d940,0xfff9e8c0,0x00047440,0xffd60080, +0x0048e180,0x001f32c0,0x0007e700,0x0003f7c0, +0x000209c0,0x00004980,0x00003100,0x00000540, +0xffffffc0,0xfffff5c0,0x000038c0,0xffff4e40, +0x0001c780,0xfff990c0,0x0003b000,0xffd43ac0, +0x00489240,0x001d6800,0x00084b00,0x00039e40, +0x00020940,0x00003d00,0x00002f80,0x000004c0, +0xffffffc0,0xfffff4c0,0x00003900,0xffff3d40, +0x0001b2c0,0xfff93a40,0x0002ddc0,0xffd279c0, +0x00482d00,0x001ba040,0x0008a200,0x000345c0, +0x000206c0,0x00003140,0x00002dc0,0x00000440, +0xffffffc0,0xfffff3c0,0x00003900,0xffff2c00, +0x00019b00,0xfff8e640,0x0001fd40,0xffd0be80, +0x0047b1c0,0x0019dc80,0x0008ecc0,0x0002ef00, +0x00020240,0x00002640,0x00002c00,0x00000400, +0xffffff80,0xfffff2c0,0x000038c0,0xffff1a40, +0x00017fc0,0xfff894c0,0x00010e80,0xffcf09c0, +0x004720c0,0x00181d80,0x00092b40,0x000299c0, +0x0001fc00,0x00001bc0,0x00002a40,0x00000380, +0xffffff80,0xfffff180,0x00003800,0xffff0840, +0x00016180,0xfff84680,0x00001180,0xffcd5cc0, +0x00467a40,0x00166440,0x00095e00,0x00024680, +0x0001f440,0x00001200,0x00002840,0x00000340, +0xffffff80,0xfffff040,0x00003740,0xfffef600, +0x00014000,0xfff7fbc0,0xffff0680,0xffcbb880, +0x0045bf00,0x0014b140,0x00098580,0x0001f580, +0x0001ea80,0x00000900,0x00002680,0x000002c0, +0xffffff80,0xffffef00,0x000035c0,0xfffee3c0, +0x00011ac0,0xfff7b540,0xfffded80,0xffca1d80, +0x0044ef80,0x00130580,0x0009a1c0,0x0001a700, +0x0001dfc0,0x00000080,0x000024c0,0x00000280, +0xffffff40,0xffffedc0,0x00003400,0xfffed180, +0x0000f280,0xfff77340,0xfffcc700,0xffc88d80, +0x00440bc0,0x001161c0,0x0009b3c0,0x00015b00, +0x0001d380,0xfffff8c0,0x000022c0,0x00000240, +0xffffff40,0xffffec40,0x00003200,0xfffebf40, +0x0000c680,0xfff73680,0xfffb92c0,0xffc708c0, +0x00431500,0x000fc6c0,0x0009bb80,0x000111c0, +0x0001c640,0xfffff1c0,0x00002100,0x00000200, +0xffffff00,0xffffeac0,0x00002f40,0xfffead00, +0x00009740,0xfff6ff40,0xfffa5180,0xffc59080, +0x00420b40,0x000e3500,0x0009b9c0,0x0000cb80, +0x0001b7c0,0xffffeb40,0x00001f40,0x000001c0, +0xffffff00,0xffffe940,0x00002c40,0xfffe9b00, +0x00006480,0xfff6ce00,0xfff90380,0xffc425c0, +0x0040ef80,0x000cad00,0x0009af00,0x00008840, +0x0001a880,0xffffe580,0x00001d40,0x000001c0, +0xfffffec0,0xffffe7c0,0x000028c0,0xfffe8980, +0x00002e40,0xfff6a3c0,0xfff7a900,0xffc2c900, +0x003fc280,0x000b2fc0,0x00099b80,0x00004800, +0x00019880,0xffffe040,0x00001bc0,0x00000180, +0xfffffec0,0xffffe600,0x00002480,0xfffe7840, +0xfffff4c0,0xfff68040,0xfff64240,0xffc17b40, +0x003e84c0,0x0009bdc0,0x00097fc0,0x00000b40, +0x000187c0,0xffffdb80,0x00001a00,0x00000140, +0xfffffe80,0xffffe440,0x00001fc0,0xfffe6780, +0xffffb800,0xfff66480,0xfff4d040,0xffc03d80, +0x003d3700,0x00085700,0x00095c40,0xffffd1c0, +0x00017680,0xffffd740,0x00001840,0x00000140, +0xfffffe40,0xffffe2c0,0x00001a80,0xfffe5780, +0xffff77c0,0xfff65100,0xfff35300,0xffbf1080, +0x003bda40,0x0006fc80,0x00093200,0xffff9b80, +0x00016500,0xffffd3c0,0x000016c0,0x00000100, +0xfffffe40,0xffffe0c0,0x000014c0,0xfffe4840, +0xffff3480,0xfff64640,0xfff1cb00,0xffbdf4c0, +0x003a6f80,0x0005ae80,0x000900c0,0xffff68c0, +0x00015300,0xffffd0c0,0x00001540,0x00000100, +0xfffffe00,0xffffdf00,0x00000e40,0xfffe39c0, +0xfffeee40,0xfff64480,0xfff03940,0xffbceb00, +0x0038f740,0x00046d40,0x0008c980,0xffff3980, +0x000140c0,0xffffce00,0x000013c0,0x000000c0, +0xfffffdc0,0xffffdd40,0x00000740,0xfffe2c80, +0xfffea500,0xfff64c40,0xffee9e40,0xffbbf440, +0x00377280,0x00033900,0x00088cc0,0xffff0d80, +0x00012e80,0xffffcc00,0x00001240,0x000000c0, +0xfffffd80,0xffffdb40,0xffffff80,0xfffe2040, +0xfffe5900,0xfff65e40,0xffecfa80,0xffbb1080, +0x0035e280,0x00021280,0x00084ac0,0xfffee540, +0x00011c40,0xffffca40,0x00001100,0x00000080, +0xfffffd40,0xffffd980,0xfffff700,0xfffe1580, +0xfffe0a80,0xfff67a80,0xffeb4ec0,0xffba4100, +0x00344780,0x0000f980,0x00080440,0xfffec000, +0x00010a00,0xffffc8c0,0x00000fc0,0x00000080, +0xfffffcc0,0xffffd7c0,0xffffee00,0xfffe0bc0, +0xfffdb980,0xfff6a200,0xffe99bc0,0xffb985c0, +0x0032a340,0xffffee80,0x0007b980,0xfffe9e80, +0x0000f7c0,0xffffc800,0x00000e80,0x00000080, +0xfffffc80,0xffffd5c0,0xffffe440,0xfffe0400, +0xfffd6640,0xfff6d4c0,0xffe7e280,0xffb8df40, +0x0030f640,0xfffef180,0x00076b40,0xfffe8040, +0x0000e5c0,0xffffc740,0x00000d40,0x00000080, +0xfffffc00,0xffffd400,0xffffd9c0,0xfffdfdc0, +0xfffd1100,0xfff71340,0xffe62380,0xffb84e40, +0x002f4180,0xfffe02c0,0x000719c0,0xfffe6500, +0x0000d400,0xffffc700,0x00000c40,0x00000040, +0xfffffbc0,0xffffd240,0xffffcec0,0xfffdf940, +0xfffcba40,0xfff75e00,0xffe45fc0,0xffb7d300, +0x002d8640,0xfffd2240,0x0006c5c0,0xfffe4d40, +0x0000c2c0,0xffffc700,0x00000b40,0x00000040, +0xfffffb40,0xffffd080,0xffffc300,0xfffdf6c0, +0xfffc61c0,0xfff7b500,0xffe29800,0xffb76dc0, +0x002bc540,0xfffc5000,0x00066f40,0xfffe3880, +0x0000b1c0,0xffffc740,0x00000a40,0x00000040, +0xfffffac0,0xffffcf00,0xffffb680,0xfffdf640, +0xfffc0840,0xfff81900,0xffe0cd40,0xffb71e80, +0x0029ff80,0xfffb8bc0,0x00061740,0xfffe26c0, +0x0000a140,0xffffc7c0,0x00000980,0x00000040, +0xfffffa00,0xffffcd80,0xffffa940,0xfffdf800, +0xfffbadc0,0xfff88a00,0xffdf0040,0xffb6e600, +0x00283600,0xfffad600,0x0005bdc0,0xfffe1800, +0x00009140,0xffffc880,0x000008c0,0x00000040, +0xfffff980,0xffffcc00,0xffff9bc0,0xfffdfc40, +0xfffb5300,0xfff90880,0xffdd3200,0xffb6c400, +0x00266a00,0xfffa2e40,0x00056340,0xfffe0c00, +0x000081c0,0xffffc980,0x000007c0,0x00000040, +0x004013c2,0x0040b346,0x0041fa2d,0x0043f934, +0x0046cc1c,0x004a9d9d,0x004fae37,0x0056601f, +0x005f4cf7,0x006b6fcf,0x007c7d1e,0x0115b035, +0x013df91b,0x0207655e,0x03342c83,0x0a185230, +0x00404f46,0x0042e13c,0x0048919f,0x0052cb0e, +0x0064e240,0x0107c449,0x015c7926,0x050cf270, +0x004140fb,0x004cf8df,0x0073326c,0x02480d9d, +0x004545ea,0x01273d75,0x005a827a,0x007fffff, +0x006597fb,0x0050a28c,0x00400000,0x0032cbfd, +0x00285146,0x00200000,0x001965ff,0x001428a3, +0x00100000,0x000cb2ff,0x000a1451,0x00080000, +0x00065980,0x00050a29,0x00040000,0x00032cc0, +0x00028514,0x00020000,0x00019660,0x0001428a, +0x00010000,0x0000cb30,0x0000a145,0x00008000, +0x00006598,0x000050a3,0x00004000,0x000032cc, +0x00002851,0x00002000,0x00001966,0x00001429, +0x00001000,0x00000cb3,0x00000a14,0x00000800, +0x00000659,0x0000050a,0x00000400,0x0000032d, +0x00000285,0x00000200,0x00000196,0x00000143, +0x00000100,0x000000cb,0x000000a1,0x00000080, +0x00000066,0x00000051,0x00000040,0x00000033, +0x00000028,0x00000020,0x00000019,0x00000014, +0x00000010,0x0000000d,0x0000000a,0x00000008, +0x00000006,0x00000005,0x00000000,0x00555555, +0x00666666,0x00492492,0x0071c71c,0x00444444, +0x00421084,0x00410410,0x00408102,0x00404040, +0x00402010,0x00401004,0x00400801,0x00400400, +0x00400200,0x00400100,0x00400080,0x00400040, +0x00400000,0x00400000,0x00200000,0x00400000, +0x00100000,0x00080000,0x00040000,0x00020000, +0x00010000,0x00008000,0x00004000,0x00002000, +0x00001000,0x00000800,0x00000400,0x00000200, +0x00000100,0x0003588d,0x0002b15e,0x0002056d, +0x00015600,0x0000a329,0xffffeed9,0xffff3960, +0xfffe8423,0xfffdd11c,0xfffd2048,0xfffc7353, +0xfffbcb6f,0xfffb29a6,0xfffa8f15,0x000494ae, +0x0003f991,0x00032dd1,0xfffd2d8f,0x0001eb47, +0xfffe9968,0x00009af6,0x000011de,0xffff4335, +0x00018d69,0xfffdecd4,0x000302f8,0xfffca0d7, +0x0004683d,0xfffb67f8,0x0005b36d,0x00045963, +0xfffbd51e,0x00030062,0xfffd0dee,0x0001d046, +0xfffe8a0a,0x00009258,0x000012b1,0xffff4d9e, +0x00019ec3,0xfffe0a44,0x0003245a,0xfffcd082, +0x000498f0,0xfffba919,0x0005f304,0x00041bf4, +0xfffba72a,0x0002d19e,0xfffcf060,0x0001b407, +0xfffe7c08,0x0000894a,0x0000138d,0xffff58ac, +0x0001afaf,0xfffe28fe,0x000343bf,0xfffd026f, +0x0004c6f6,0xfffbed06,0x00062e61,0x0003dc0e, +0xfffb7bf1,0x0002a17f,0xfffcd522,0x000196a0, +0xfffe6e70,0x00007ff6,0x00001439,0xffff63f6, +0x0001beb3,0xfffe4882,0x0003616d,0xfffd361b, +0x0004f1cf,0xfffc332a,0x0006658f,0x00039943, +0xfffb52c0,0x00026ec7,0xfffcbb94,0x0001789f, +0xfffe6160,0x00007677,0x000014d4,0xffff6f74, +0x0001cc9b,0xfffe694f,0x00037cbf,0xfffd6b41, +0x000519c2,0xfffc7baf,0x00069971,0x00035486, +0xfffb2d0c,0x00023ad8,0xfffca3ee,0x00015989, +0xfffe55af,0x00006ca7,0x00001570,0xffff7b71, +0x0001d9cb,0xfffe8b46,0x0003959e,0xfffda1fe, +0x00053ee6,0xfffcc6b4,0x0006c950,0x00030e08, +0xfffb0a7a,0x0002061e,0xfffc8ec0,0x00013911, +0xfffe4b1d,0x00006278,0x000015e8,0xffff87b6, +0x0001e577,0xfffeadd6,0x0003acc2,0xfffdda34, +0x00056059,0xfffd136d,0x0006f4b5,0x0002c562, +0xfffaea7c,0x0001cfa6,0xfffc7b14,0x0001182b, +0xfffe4159,0x00005817,0x0000165c,0xffff9417, +0x0001f00f,0xfffed14c,0x0003c199,0xfffe13f6, +0x00057e83,0xfffd61cd,0x00071ba1,0x00027ab5, +0xfffacdc3,0x00019833,0xfffc6989,0x0000f6ca, +0xfffe38da,0x00004d9d,0x000016ef,0xffffa103, +0x0001f98f,0xfffef5c0,0x0003d3d1,0xfffe4f00, +0x0005998c,0xfffdb21e,0x00073e77,0x00022e75, +0xfffab482,0x00015fd1,0xfffc5b13,0x0000d45d, +0xfffe318f,0x000042ed,0x0000176b,0xffffae8f, +0x0002018f,0xffff1a91,0x0003e40c,0xfffe8af2, +0x0005b0ca,0xfffe03b8,0x00075d14,0x0001e141, +0xfffa9e9b,0x0001262a,0xfffc4e31,0x0000b1af, +0xfffe2b26,0x00003805,0x000017b1,0xffffbc21, +0x000208b8,0xffff3fb6,0x0003f1d7,0xfffec7af, +0x0005c4c5,0xfffe5654,0x0007768a,0x000192fe, +0xfffa8bb0,0x0000ec3f,0xfffc4365,0x00008ec9, +0xfffe25f0,0x00002d05,0x000017ec,0xffffc984, +0x00020ec6,0xffff658d,0x0003fcba,0xffff0500, +0x0005d576,0xfffeaa37,0x00078bc6,0x00014367, +0xfffa7bec,0x0000b1f4,0xfffc3b82,0x00006b06, +0xfffe2201,0x000021eb,0x00001823,0xffffd704, +0x0002132a,0xffff8be7,0x00040534,0xffff4315, +0x0005e22e,0xfffeff0a,0x00079ce3,0x0000f33f, +0xfffa6fc9,0x000076ca,0xfffc3558,0x00004762, +0xfffe1ef3,0x000016a1,0x0000183f,0xffffe4a6, +0x00021664,0xffffb27d,0x00040b7b,0xffff81e5, +0x0005eb4e,0xffff5475,0x0007a857,0x0000a2cb, +0xfffa671b,0x00003b64,0xfffc31e2,0x00002416, +0xfffe1ce1,0x00000b46,0x00001850,0xfffff24d, +0x00021855,0xffffd93a,0x00040f75,0xffffc0e6, +0x0005f0e3,0xffffaa3e,0x0007af45,0x0000519f, +0xfffa6218,0x0003f991,0x0003588d,0x0002b15e, +0x0002056d,0x00015600,0x0000a329,0xffffeed9, +0xffff3960,0xfffe8423,0xfffdd11c,0xfffd2048, +0xfffc7353,0xfffbcb6f,0xfffb29a6,0xfffa8f15, +0x000494ae,0x0003c6b0,0xfffc7e8b,0x00028ef6, +0xfffde181,0x000144eb,0xffff5500,0xffffefb9, +0x0000d01d,0xfffe9755,0x000249a4,0xfffd453c, +0x0003b80e,0xfffc01aa,0x000511d6,0xfffad527, +0xfffb334e,0x0003916c,0xfffc5778,0x00026a92, +0xfffdc9f5,0x00013314,0xffff4d99,0xfffff0b6, +0x0000d911,0xfffeab80,0x00026369,0xfffd6c0a, +0x0003e17f,0xfffc39d8,0x000549df,0xfffb1eb2, +0xfffafe6c,0x00035929,0xfffc3321,0x000244a6, +0xfffdb402,0x00012035,0xffff46ac,0xfffff192, +0x0000e16a,0xfffebfe0,0x00027b3d,0xfffd9433, +0x0004087b,0xfffc74b7,0x00057e8d,0xfffb6a81, +0xfffacc1c,0x00031fbe,0xfffc10df,0x00021e0c, +0xfffd9f6d,0x00010cb7,0xffff402e,0xfffff279, +0x0000e965,0xfffed574,0x00029159,0xfffdbdc4, +0x00042c4c,0xfffcb1e7,0x0005b02d,0xfffbb942, +0xfffa9d38,0x0002e44a,0xfffbf0fd,0x0001f5b4, +0xfffd8c38,0x0000f8b1,0xffff3a21,0xfffff391, +0x0000f0e6,0xfffeec44,0x0002a642,0xfffde90e, +0x00044e32,0xfffcf0fb,0x0005de46,0xfffc0b18, +0xfffa71d1,0x0002a659,0xfffbd3de,0x0001cb90, +0xfffd7a97,0x0000e403,0xffff3490,0xfffff49c, +0x0000f7a8,0xffff0340,0x0002b95f,0xfffe1573, +0x00046dbe,0xfffd3284,0x00060888,0xfffc5f51, +0xfffa4996,0x00026786,0xfffbb8df,0x0001a0e1, +0xfffd6a4e,0x0000ced2,0xffff2f75,0xfffff593, +0x0000fdbe,0xffff1a53,0x0002ca87,0xfffe42f5, +0x0004898a,0xfffd7563,0x00062f0b,0xfffcb5de, +0xfffa2508,0x00022713,0xfffba0bf,0x0001754a, +0xfffd5b5f,0x0000b92c,0xffff2acd,0xfffff6b0, +0x0001034f,0xffff3241,0x0002da5c,0xfffe71c6, +0x0004a341,0xfffdb946,0x000651e8,0xfffd0e37, +0xfffa0402,0x0001e4d4,0xfffb8b9c,0x00014898, +0xfffd4e7d,0x0000a304,0xffff26b7,0xfffff7e1, +0x00010846,0xffff4b34,0x0002e897,0xfffea13f, +0x0004ba63,0xfffdff2d,0x00067115,0xfffd6839, +0xfff9e680,0x0001a1fa,0xfffb789e,0x00011b2e, +0xfffd43a4,0x00008c6e,0xffff2341,0xfffff8fd, +0x00010c9c,0xffff6469,0x0002f48f,0xfffed1a4, +0x0004cd6a,0xfffe4608,0x00068c1b,0xfffdc409, +0xfff9cd15,0x00015dfe,0xfffb68a0,0x0000ecee, +0xfffd3a2e,0x0000757d,0xffff204b,0xfffffa1e, +0x00011054,0xffff7da1,0x0002fe9c,0xffff033e, +0x0004de57,0xfffe8dc6,0x0006a2d5,0xfffe213e, +0xfff9b77d,0x000118d3,0xfffb5bde,0x0000be25, +0xfffd3224,0x00005e52,0xffff1dc1,0xfffffb4b, +0x00011353,0xffff9740,0x00030748,0xffff351c, +0x0004ec95,0xfffed755,0x0006b5b4,0xfffe7fc6, +0xfff9a599,0x0000d334,0xfffb519f,0x00008f08, +0xfffd2bbf,0x00004704,0xffff1bc1,0xfffffc71, +0x00011598,0xffffb135,0x00030e43,0xffff6720, +0x0004f6f3,0xffff2119,0x0006c46e,0xfffedf38, +0xfff997c7,0x00008d13,0xfffb4a55,0x00005fa5, +0xfffd273b,0x00002f76,0xffff1a63,0xfffffda0, +0x00011744,0xffffcb67,0x000312ff,0xffff99cf, +0x0004ff0c,0xffff6a9c,0x0006cebd,0xffff3f0a, +0xfff98dbe,0x00004691,0xfffb4620,0x00003010, +0xfffd24fc,0x000017b5,0xffff199d,0xfffffed8, +0x0001185a,0xffffe5c6,0x0003157e,0xffffcce3, +0x000503ae,0xffffb515,0x0006d537,0xffff9f5a, +0xfff98767,0xfffb44b0,0xfffc3131,0xfffd2475, +0xfffe1c28,0xffff195d,0x00001859,0x000118bd, +0x000218df,0x0003163a,0x000410e0,0x000504a7, +0x0005f2b3,0x0006d796,0x0007b1fe,0xfff98537, +0xfffa609b,0xfffc7e8b,0x00028ef6,0xfffde181, +0x000144eb,0xffff5500,0xffffefb9,0x0000d01d, +0xfffe9755,0x000249a4,0xfffd453c,0x0003b80e, +0xfffc01aa,0x000511d6,0xfffad527,0xfffb334e, +0x0003c6b0,0xfffc5778,0x00026a92,0xfffdc9f5, +0x00013314,0xffff4d99,0xfffff0b6,0x0000d911, +0xfffeab80,0x00026369,0xfffd6c0a,0x0003e17f, +0xfffc39d8,0x000549df,0xfffb1eb2,0xfffafe6c, +0x0003916c,0xfffc3321,0x000244a6,0xfffdb402, +0x00012035,0xffff46ac,0xfffff192,0x0000e16a, +0xfffebfe0,0x00027b3d,0xfffd9433,0x0004087b, +0xfffc74b7,0x00057e8d,0xfffb6a81,0xfffacc1c, +0x00035929,0xfffc10df,0x00021e0c,0xfffd9f6d, +0x00010cb7,0xffff402e,0xfffff279,0x0000e965, +0xfffed574,0x00029159,0xfffdbdc4,0x00042c4c, +0xfffcb1e7,0x0005b02d,0xfffbb942,0xfffa9d38, +0x00031fbe,0xfffbf0fd,0x0001f5b4,0xfffd8c38, +0x0000f8b1,0xffff3a21,0xfffff391,0x0000f0e6, +0xfffeec44,0x0002a642,0xfffde90e,0x00044e32, +0xfffcf0fb,0x0005de46,0xfffc0b18,0xfffa71d1, +0x0002e44a,0xfffbd3de,0x0001cb90,0xfffd7a97, +0x0000e403,0xffff3490,0xfffff49c,0x0000f7a8, +0xffff0340,0x0002b95f,0xfffe1573,0x00046dbe, +0xfffd3284,0x00060888,0xfffc5f51,0xfffa4996, +0x0002a659,0xfffbb8df,0x0001a0e1,0xfffd6a4e, +0x0000ced2,0xffff2f75,0xfffff593,0x0000fdbe, +0xffff1a53,0x0002ca87,0xfffe42f5,0x0004898a, +0xfffd7563,0x00062f0b,0xfffcb5de,0xfffa2508, +0x00026786,0xfffba0bf,0x0001754a,0xfffd5b5f, +0x0000b92c,0xffff2acd,0xfffff6b0,0x0001034f, +0xffff3241,0x0002da5c,0xfffe71c6,0x0004a341, +0xfffdb946,0x000651e8,0xfffd0e37,0xfffa0402, +0x00022713,0xfffb8b9c,0x00014898,0xfffd4e7d, +0x0000a304,0xffff26b7,0xfffff7e1,0x00010846, +0xffff4b34,0x0002e897,0xfffea13f,0x0004ba63, +0xfffdff2d,0x00067115,0xfffd6839,0xfff9e680, +0x0001e4d4,0xfffb789e,0x00011b2e,0xfffd43a4, +0x00008c6e,0xffff2341,0xfffff8fd,0x00010c9c, +0xffff6469,0x0002f48f,0xfffed1a4,0x0004cd6a, +0xfffe4608,0x00068c1b,0xfffdc409,0xfff9cd15, +0x0001a1fa,0xfffb68a0,0x0000ecee,0xfffd3a2e, +0x0000757d,0xffff204b,0xfffffa1e,0x00011054, +0xffff7da1,0x0002fe9c,0xffff033e,0x0004de57, +0xfffe8dc6,0x0006a2d5,0xfffe213e,0xfff9b77d, +0x00015dfe,0xfffb5bde,0x0000be25,0xfffd3224, +0x00005e52,0xffff1dc1,0xfffffb4b,0x00011353, +0xffff9740,0x00030748,0xffff351c,0x0004ec95, +0xfffed755,0x0006b5b4,0xfffe7fc6,0xfff9a599, +0x000118d3,0xfffb519f,0x00008f08,0xfffd2bbf, +0x00004704,0xffff1bc1,0xfffffc71,0x00011598, +0xffffb135,0x00030e43,0xffff6720,0x0004f6f3, +0xffff2119,0x0006c46e,0xfffedf38,0xfff997c7, +0x0000d334,0xfffb4a55,0x00005fa5,0xfffd273b, +0x00002f76,0xffff1a63,0xfffffda0,0x00011744, +0xffffcb67,0x000312ff,0xffff99cf,0x0004ff0c, +0xffff6a9c,0x0006cebd,0xffff3f0a,0xfff98dbe, +0x00008d13,0xfffb4620,0x00003010,0xfffd24fc, +0x000017b5,0xffff199d,0xfffffed8,0x0001185a, +0xffffe5c6,0x0003157e,0xffffcce3,0x000503ae, +0xffffb515,0x0006d537,0xffff9f5a,0xfff98767, +0x00004691,0xfffa609b,0xfffb44b0,0xfffc3131, +0xfffd2475,0xfffe1c28,0xffff195d,0x00001859, +0x000118bd,0x000218df,0x0003163a,0x000410e0, +0x000504a7,0x0005f2b3,0x0006d796,0x0007b1fe, +0xfff98537,0xfffbd51e,0x00032dd1,0xfffd2d8f, +0x0001eb47,0xfffe9968,0x00009af6,0x000011de, +0xffff4335,0x00018d69,0xfffdecd4,0x000302f8, +0xfffca0d7,0x0004683d,0xfffb67f8,0x0005b36d, +0x00045963,0xfffba72a,0x00030062,0xfffd0dee, +0x0001d046,0xfffe8a0a,0x00009258,0x000012b1, +0xffff4d9e,0x00019ec3,0xfffe0a44,0x0003245a, +0xfffcd082,0x000498f0,0xfffba919,0x0005f304, +0x00041bf4,0xfffb7bf1,0x0002d19e,0xfffcf060, +0x0001b407,0xfffe7c08,0x0000894a,0x0000138d, +0xffff58ac,0x0001afaf,0xfffe28fe,0x000343bf, +0xfffd026f,0x0004c6f6,0xfffbed06,0x00062e61, +0x0003dc0e,0xfffb52c0,0x0002a17f,0xfffcd522, +0x000196a0,0xfffe6e70,0x00007ff6,0x00001439, +0xffff63f6,0x0001beb3,0xfffe4882,0x0003616d, +0xfffd361b,0x0004f1cf,0xfffc332a,0x0006658f, +0x00039943,0xfffb2d0c,0x00026ec7,0xfffcbb94, +0x0001789f,0xfffe6160,0x00007677,0x000014d4, +0xffff6f74,0x0001cc9b,0xfffe694f,0x00037cbf, +0xfffd6b41,0x000519c2,0xfffc7baf,0x00069971, +0x00035486,0xfffb0a7a,0x00023ad8,0xfffca3ee, +0x00015989,0xfffe55af,0x00006ca7,0x00001570, +0xffff7b71,0x0001d9cb,0xfffe8b46,0x0003959e, +0xfffda1fe,0x00053ee6,0xfffcc6b4,0x0006c950, +0x00030e08,0xfffaea7c,0x0002061e,0xfffc8ec0, +0x00013911,0xfffe4b1d,0x00006278,0x000015e8, +0xffff87b6,0x0001e577,0xfffeadd6,0x0003acc2, +0xfffdda34,0x00056059,0xfffd136d,0x0006f4b5, +0x0002c562,0xfffacdc3,0x0001cfa6,0xfffc7b14, +0x0001182b,0xfffe4159,0x00005817,0x0000165c, +0xffff9417,0x0001f00f,0xfffed14c,0x0003c199, +0xfffe13f6,0x00057e83,0xfffd61cd,0x00071ba1, +0x00027ab5,0xfffab482,0x00019833,0xfffc6989, +0x0000f6ca,0xfffe38da,0x00004d9d,0x000016ef, +0xffffa103,0x0001f98f,0xfffef5c0,0x0003d3d1, +0xfffe4f00,0x0005998c,0xfffdb21e,0x00073e77, +0x00022e75,0xfffa9e9b,0x00015fd1,0xfffc5b13, +0x0000d45d,0xfffe318f,0x000042ed,0x0000176b, +0xffffae8f,0x0002018f,0xffff1a91,0x0003e40c, +0xfffe8af2,0x0005b0ca,0xfffe03b8,0x00075d14, +0x0001e141,0xfffa8bb0,0x0001262a,0xfffc4e31, +0x0000b1af,0xfffe2b26,0x00003805,0x000017b1, +0xffffbc21,0x000208b8,0xffff3fb6,0x0003f1d7, +0xfffec7af,0x0005c4c5,0xfffe5654,0x0007768a, +0x000192fe,0xfffa7bec,0x0000ec3f,0xfffc4365, +0x00008ec9,0xfffe25f0,0x00002d05,0x000017ec, +0xffffc984,0x00020ec6,0xffff658d,0x0003fcba, +0xffff0500,0x0005d576,0xfffeaa37,0x00078bc6, +0x00014367,0xfffa6fc9,0x0000b1f4,0xfffc3b82, +0x00006b06,0xfffe2201,0x000021eb,0x00001823, +0xffffd704,0x0002132a,0xffff8be7,0x00040534, +0xffff4315,0x0005e22e,0xfffeff0a,0x00079ce3, +0x0000f33f,0xfffa671b,0x000076ca,0xfffc3558, +0x00004762,0xfffe1ef3,0x000016a1,0x0000183f, +0xffffe4a6,0x00021664,0xffffb27d,0x00040b7b, +0xffff81e5,0x0005eb4e,0xffff5475,0x0007a857, +0x0000a2cb,0xfffa6218,0x00003b64,0xfffc31e2, +0x00002416,0xfffe1ce1,0x00000b46,0x00001850, +0xfffff24d,0x00021855,0xffffd93a,0x00040f75, +0xffffc0e6,0x0005f0e3,0xffffaa3e,0x0007af45, +0x0000519f,0x00030000,0x000f0007,0x003f001f, +0x00ff007f,0x03ff01ff,0x0fff07ff,0x3fff1fff, +0xffff7fff,0x00030000,0x00070005,0x000f0009, +0x003f001f,0x00ff007f,0x03ff01ff,0x0fff07ff, +0xffff1fff,0x00030000,0x00070005,0x000f0009, +0xffff001f,0x00030000,0xffff0005,0x04030504, +0x08070605,0x0c0b0a09,0x100f0e0d,0x03070504, +0x0605040a,0x0a090807,0x100d0c0b,0x03070503, +0x1005040a,0x10070502,0x03030100,0x03030303, +0x03030303,0x03030303,0x03010100,0x03030301, +0x03030303,0x03030303,0x03010100,0x03030301, +0x03010100,0x04020000,0x08070605,0x0c0b0a09, +0x100f0e0d,0x02010000,0x06050403,0x0a090807, +0x100d0c0b,0x02010000,0x10050403,0x10010000, +0x00030000,0x00090005,0x001f000f,0x007f003f, +0x01ff00ff,0x07ff03ff,0x1fff0fff,0x7fff3fff, +0x00030000,0x00090005,0x001f000f,0x007f003f, +0x0a070504,0x07060504,0x0b0a0908,0x0f0e0d0c, +0x0a070503,0x07060504,0x01010100,0x03030303, +0x03030303,0x03030303,0x01010100,0x03030303, +0x03010000,0x07060504,0x0b0a0908,0x0f0e0d0c, +0x03010000,0x07060504,0x00555555,0x002aaaab, +0x00249249,0x00124925,0x00111111,0x00088889, +0x00084210,0x00421084,0x00041041,0x00020821, +0x00020408,0x00081020,0x00010101,0x00008081, +0x00008040,0x00100804,0x00004010,0x00020080, +0x00002004,0x00004008,0x00001001,0x00000801, +0x00000800,0x00200100,0x00000400,0x00080020, +0x00000200,0x00020004,0x00200000,0x00600040, +0x00a00080,0x00e000c0,0x01200100,0x01600140, +0x01a00180,0x000001c0,0x00300020,0x00400038, +0x00600050,0x00800070,0x00c000a0,0x010000e0, +0x01800140,0x00200000,0x00300028,0x00400038, +0x00600050,0x00800070,0x00c000a0,0x010000e0, +0x00000140,0x00900000,0x00fc00d8,0x01680120, +0x01f801b0,0x02d00240,0x03f00360,0x05a00480, +0x000006c0,0x00680000,0x00b6009c,0x010500d0, +0x016d0139,0x020a01a1,0x02db0272,0x04140343, +0x000004e5,0x006c0000,0x00bd00a2,0x010e00d8, +0x017a0144,0x006301b0,0x013b00cf,0x00c601a7, +0x0000019e,0x00600000,0x00a80090,0x00f000c0, +0x01500120,0x01e00180,0x02a00240,0x03c00300, +0x00000480,0x10000000,0x10101010,0x20101010, +0x20202020,0x20202020,0x28202020,0x28282828, +0x00002828,0x10100000,0x10101010,0x10101010, +0x00000000,0x00000000,0x00000000,0x00000000, +0xcbcecdc4,0xcfcac9c8,0xc3c6c5cc,0xc7c2c1c0, +0x1b1e1d14,0x1f1a1918,0x1316151c,0x17121110, +0x2b2e2d24,0x2f2a2928,0x2326252c,0x27222120, +0x3b3e3d34,0x3f3a3938,0x3336353c,0x37323130, +0x0b0e0d04,0x0f0a0908,0x0306050c,0x07020100, +0xdbdeddd4,0xdfdad9d8,0xd3d6d5dc,0xd7d2d1d0, +0xebeeede4,0xefeae9e8,0xe3e6e5ec,0xe7e2e1e0, +0xfbfefdf4,0xfffaf9f8,0xf3f6f5fc,0xf7f2f1f0, +0x4b4e4d44,0x4f4a4948,0x4346454c,0x47424140, +0x9b9e9d94,0x9f9a9998,0x9396959c,0x97929190, +0xabaeada4,0xafaaa9a8,0xa3a6a5ac,0xa7a2a1a0, +0xbbbebdb4,0xbfbab9b8,0xb3b6b5bc,0xb7b2b1b0, +0x8b8e8d84,0x8f8a8988,0x8386858c,0x87828180, +0x5b5e5d54,0x5f5a5958,0x5356555c,0x57525150, +0x6b6e6d64,0x6f6a6968,0x6366656c,0x67626160, +0x7b7e7d74,0x7f7a7978,0x7376757c,0x77727170, +0x341424c4,0x3e1e2ece,0x3d1d2dcd,0x3b1b2bcb, +0xb494a444,0xbe9eae4e,0xbd9dad4d,0xbb9bab4b, +0xf4d4e404,0xfedeee0e,0xfddded0d,0xfbdbeb0b, +0x74546484,0x7e5e6e8e,0x7d5d6d8d,0x7b5b6b8b, +0x3c1c2ccc,0x361626c6,0x351525c5,0x331323c3, +0xbc9cac4c,0xb696a646,0xb595a545,0xb393a343, +0xfcdcec0c,0xf6d6e606,0xf5d5e505,0xf3d3e303, +0x7c5c6c8c,0x76566686,0x75556585,0x73536383, +0x381828c8,0x3a1a2aca,0x391929c9,0x3f1f2fcf, +0xb898a848,0xba9aaa4a,0xb999a949,0xbf9faf4f, +0xf8d8e808,0xfadaea0a,0xf9d9e909,0xffdfef0f, +0x78586888,0x7a5a6a8a,0x79596989,0x7f5f6f8f, +0x301020c0,0x321222c2,0x311121c1,0x371727c7, +0xb090a040,0xb292a242,0xb191a141,0xb797a747, +0xf0d0e000,0xf2d2e202,0xf1d1e101,0xf7d7e707, +0x70506080,0x72526282,0x71516181,0x77576787, +0x05040100,0x15141110,0x25242120,0x35343130, +0x85848180,0x95949190,0xa5a4a1a0,0xb5b4b1b0, +0xc0408000,0xe060a020,0xd0509010,0xf070b030, +0xc8488808,0xe868a828,0xd8589818,0xf878b838, +0xc4448404,0xe464a424,0xd4549414,0xf474b434, +0xcc4c8c0c,0xec6cac2c,0xdc5c9c1c,0xfc7cbc3c, +0xc2428202,0xe262a222,0xd2529212,0xf272b232, +0xca4a8a0a,0xea6aaa2a,0xda5a9a1a,0xfa7aba3a, +0xc6468606,0xe666a626,0xd6569616,0xf676b636, +0xce4e8e0e,0xee6eae2e,0xde5e9e1e,0xfe7ebe3e, +0xc1418101,0xe161a121,0xd1519111,0xf171b131, +0xc9498909,0xe969a929,0xd9599919,0xf979b939, +0xc5458505,0xe565a525,0xd5559515,0xf575b535, +0xcd4d8d0d,0xed6dad2d,0xdd5d9d1d,0xfd7dbd3d, +0xc3438303,0xe363a323,0xd3539313,0xf373b333, +0xcb4b8b0b,0xeb6bab2b,0xdb5b9b1b,0xfb7bbb3b, +0xc7478707,0xe767a727,0xd7579717,0xf777b737, +0xcf4f8f0f,0xef6faf2f,0xdf5f9f1f,0xff7fbf3f, +0x1045a3e2,0x000000f4,0x263b7333,0x766b2363, +0x2b367e3e,0x7b662e6e,0x06db93d3,0x964b0343, +0x0bd69ede,0x9b460e4e,0x825f1757,0x12cf87c7, +0x8f521a5a,0x1fc28aca,0x00d199d9,0x90410949, +0x01d098d8,0x91400848,0x24357d3d,0x74652d6d, +0x25347c3c,0x75642c6c,0x04d59ddd,0x94450d4d, +0x05d49cdc,0x95440c4c,0x80511959,0x10c189c9, +0x81501858,0x11c088c8,0x02df97d7,0x924f0747, +0x0fd29ada,0x9f420a4a,0x865b1353,0x16cb83c3, +0x8b561e5e,0x1bc68ece,0xa6bbf3b3,0xf6eba3e3, +0xabb6febe,0xfbe6aeee,0x223f7737,0x726f2767, +0x2f327a3a,0x7f622a6a,0xa0b1f9b9,0xf0e1a9e9, +0xa1b0f8b8,0xf1e0a8e8,0x84551d5d,0x14c58dcd, +0x85541c5c,0x15c48ccc,0xa4b5fdbd,0xf4e5aded, +0xa5b4fcbc,0xf5e4acec,0x20317939,0x70612969, +0x21307838,0x71602868,0xa2bff7b7,0xf2efa7e7, +0xafb2faba,0xffe2aaea,0x00000000,0x00000000, + +}; + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/ls220/mpgi2s_240.h linux.19rc3-ac4/drivers/media/video/ls220/mpgi2s_240.h --- linux.19rc3/drivers/media/video/ls220/mpgi2s_240.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/ls220/mpgi2s_240.h 2002-07-29 13:58:41.000000000 +0100 @@ -0,0 +1,1593 @@ +static u32 MPGI2S240Ucode1f1800[] = { +0x820f001f,0x802f001f,0xb500000d,0x00000000, +0x00ffb81e,0x00000000,0x00000000,0x00000000, +0x00ffb81e,0x00000000,0x00000000,0x00000000, +0xb5000b5b,0x00000000,0x00000000,0x00000000, +0x80070800,0x001f6047,0x8013001f,0x90208000, +0x003fb174,0x803effe8,0x803effec,0x9020fa00, +0x803effd0,0x803effdc,0x803effd8,0x9020fe00, +0x803effd4,0x805bff7c,0x802500d4,0x94020080, +0xb0000000,0xb4200023,0x8013ffcf,0x9800cfff, +0x80730030,0x98631000,0x94420007,0xb0020002, +0xb4200005,0x8013ffc7,0x9800c7ff,0x80730038, +0x98631000,0xb5000006,0xb0020001,0xb4200004, +0x8013ffcf,0x9800cfff,0x80730030,0x98631000, +0x1421b800,0x1821b803,0x802600d4,0x8033001f, +0x98210000,0x802600a2,0x8033001f,0x98210300, +0x802600a3,0x80270225,0x80530001,0x98420100, +0x1821b802,0x80530200,0x98420000,0x804600a6, +0xb500001d,0x805bff7c,0x8013ffcf,0x9800cfff, +0x80730030,0x98632000,0x94420007,0xb0020002, +0xb4200005,0x8013ffc7,0x9800c7ff,0x80730038, +0x98632800,0xb5000006,0xb0020001,0xb4200004, +0x8013ffcf,0x9800cfff,0x80730030,0x98632000, +0x1421b800,0x1821b803,0x802600d4,0x8033001f, +0x98210000,0x802600a2,0x8033001f,0x98210600, +0x802600a3,0x80270eff,0x802600a1,0x80270002, +0x803eff84,0x80070000,0x801effc0,0x801effc4, +0x801effc8,0x801effcc,0x801eff88,0x80770000, +0x8057ffff,0x80170080,0x80070000,0xb6003f02, +0xb6002001,0x001fa020,0x8007ffff,0x801eff84, +0x80070001,0x001f25dc,0x001f20b1,0x80070000, +0x001f6046,0x001fb17c,0x001fb17d,0x80070000, +0x801e78d0,0x98004000,0x001f62ea,0x80070100, +0x801efff0,0x81df0004,0x00000000,0x00000000, +0x801bfff0,0x00000000,0x940000ff,0xb0000000, +0xb4200057,0x003f42ea,0x94010010,0xb0000000, +0xb400fff7,0x003f05dc,0xb0010001,0xb4200034, +0x803bffe8,0x801bffec,0x00000000,0x3001b800, +0xb4600001,0x90214000,0x0421b800,0xb0010800, +0xb460000d,0x80050086,0x005f902e,0xb0020000, +0xb4200002,0x001fb02e,0xb5000006,0x0420b802, +0xb0010930,0xb4a0ffe2,0x80070000,0x001fb02e, +0x83e40146,0xb500ffde,0x83e40111,0x80070000, +0x001fb02e,0x001f42ea,0x9400000f,0xb0000000, +0xb4000010,0x9400fff0,0x001f62ea,0x003f9174, +0x9421ffff,0x90210004,0xb001c000,0xb4800002, +0x8421c000,0x90218000,0x8013001f,0x1821b800, +0x003fb174,0x003f917c,0x90210004,0x003fb17c, +0x83e4012e,0x8013001f,0x83e71b0c,0x1bffb800, +0x003f9179,0x1821b800,0x00ffb801,0xb5000008, +0x80270000,0x003f25dc,0x8013001f,0x83e71b30, +0x1bffb800,0x003f917a,0x1821b800,0x00ffb801, +0x80070000,0x001f20b1,0x001f42ea,0x9420000f, +0xb0010000,0xb4200003,0x98000800,0x001f62ea, +0xb500ffaf,0x9400fff0,0x001f62ea,0x80270000, +0x8057ffff,0x80770000,0x80171980,0xb6000602, +0xb6002001,0x001fa021,0xb500ffa5,0xb500ffa4, +0x803bffc0,0x805bffc4,0x807bffc8,0x809bffcc, +0x5828b801,0x5cb8b802,0x1821b805,0x5848b802, +0x5cb8b803,0x1842b805,0x5868b803,0x5cb8b804, +0x1863b805,0x5888b804,0x1884b800,0x803effc0, +0x805effc4,0x807effc8,0x809effcc,0x003f42ea, +0xb0000086,0xb4400079,0xb0000084,0xb4000049, +0xb0000085,0xb4000063,0xb0000086,0xb400006c, +0xb0000081,0xb4000005,0xb0000082,0xb4000003, +0xb0000080,0xb4000001,0xb5000069,0x8013007f, +0x9800ffff,0x001fb02d,0x80070000,0x001fb17c, +0x8013001f,0x9040fa00,0x805effd0,0x805effdc, +0x805effd8,0x9040fe00,0x805effd4,0x9040c000, +0x805effe4,0x90008000,0x801effe0,0x001fb174, +0x801effe8,0x801effec,0x80078000,0x801e78d4, +0x80070000,0x001fb17c,0x001fb17d,0x001fb02e, +0x83e400ce,0x8013001f,0x98000000,0x800600a2, +0x8013001f,0x98000600,0x800600a3,0x805bff7c, +0x80070eff,0x94420080,0xb0020080,0xb420000d, +0x8013001f,0x98000000,0x800600a2,0x8013001f, +0x98000300,0x800600a3,0x80070225,0x80530001, +0x98420100,0x1800b802,0x80530200,0x98420000, +0x804600a6,0x800600a1,0x80050080,0x98000022, +0x80060080,0x80072000,0x001fb179,0x80074360, +0x001fb17a,0x80070001,0x001f25dc,0x98214000, +0xb5000029,0x8047ffff,0x805eff84,0x805bff88, +0x00000000,0xb0020001,0xb4200002,0x80470000, +0x805eff88,0x805bff7c,0x80070eff,0x94420080, +0xb0020080,0xb4200007,0x80070225,0x80530001, +0x98420100,0x1800b802,0x80530200,0x98420000, +0x804600a6,0x800600a1,0x80070001,0x800600a0, +0x9421efff,0x98210010,0xb500000f,0x80070000, +0x001fb17c,0x80070001,0x001f25dc,0x83e4008b, +0x80050081,0x80330008,0x98210000,0x1800b801, +0x80060081,0x003f42ea,0x9421ffef,0xb5000002, +0x98211000,0x9421ffef,0x83e40080,0x003f62ea, +0x80070100,0x801efff0,0xb500ff15,0xb000008b, +0xb400001c,0xb0000087,0xb400ffe8,0xb0000088, +0xb4000023,0xb000008a,0xb4000024,0xb000008c, +0xb4000019,0xb000008e,0xb4000014,0xb000008d, +0xb400001d,0xb0000089,0xb400001f,0xb00000a0, +0xb4000021,0xb00000a1,0xb4000022,0xb00000a2, +0xb400002b,0xb00000a3,0xb4000027,0xb00000a4, +0xb4000029,0xb00000a5,0xb4000029,0xb00000a6, +0xb4000029,0x803efff8,0xb500ffdd,0x80070000, +0x001fb17e,0xb500ffda,0x803bffb0,0x00000000, +0x003fb02d,0xb500ffd6,0x98210020,0xb500ffd2, +0x9421ffdf,0xb500ffd0,0xb500ffd1,0x80270351, +0x803efff8,0xb500ffce,0x803bff80,0x00000000, +0x003f62ef,0xb500ffca,0x003f917b,0x803efff8, +0xb500ffc7,0x80270000,0x8047fef0,0x003eb802, +0x90420004,0x003eb802,0x90420004,0x003eb802, +0x90420004,0x003eb802,0x83640d78,0xb500ffbc, +0x83640d26,0xb500ffba,0x83640ce5,0xb500ffb8, +0x83440c4c,0xb500ffb6,0x83440c35,0xb500ffb4, +0x817bffe8,0x815b78d4,0x00000000,0x956bffff, +0x300bb80a,0xb4600001,0x916b4000,0x056bb80a, +0xb00b0080,0xb4a00026,0x80af001f,0x808f0000, +0x806f0000,0x81b300ff,0x8057ffff,0x5d67b80b, +0x5d42b80a,0xb62b001c,0xb00a3000,0xb4800001, +0x854a1000,0x80cf0400,0x015fb178,0x5942b80a, +0x01cfb80a,0x015f9178,0xb520ffff,0x80171000, +0xb600200a,0x01ff8000,0x5a18b80f,0x5a28b80f, +0x1631b80d,0x5e48b80f,0x9652ff00,0x5e78b80f, +0x1a73b810,0x1a73b811,0x1813a032,0x80cf0400, +0x015fb178,0x5942b80a,0x01afb80a,0x015f9178, +0xb520ffff,0x914a0020,0x5942b80a,0x815e78d4, +0x00000000,0x00000000,0x00ffb81f,0x80070000, +0x80470000,0x81171800,0xb6002003,0xb6003002, +0x001eb802,0x90420004,0xb6002003,0x011fa020, +0x011fa020,0x011fa020,0x00ffb81f,0x80070000, +0x80478000,0xb6002003,0xb6008002,0x001eb802, +0x90420004,0x00ffb81f,0x00000000,0x00000000, +0x015f42ea,0x944a4000,0xb0024000,0xb4200071, +0x954abfff,0x015f62ea,0x808f0000,0x80ef007c, +0x80171000,0x80971400,0x80270000,0xb6001003, +0xb6002002,0x001fa021,0x009fa021,0x80a76604, +0x80271400,0xb6001004,0x01efb801,0x01afb805, +0xb520ffff,0x90a50080,0x80a76e04,0x80271400, +0xb6001004,0x01efb801,0x01afb805,0xb520ffff, +0x90a50080,0x806f001f,0x80af001f,0x80276400, +0x5c22b801,0x806701e1,0x00cfb803,0x003fb178, +0x5822b801,0x01cfb801,0x003f9178,0x0047b86f, +0xb0020001,0xb4c0fffd,0x80275c00,0x5c22b801, +0x80670200,0xb600100a,0x00cfb803,0x003fb178, +0x5822b801,0x01cfb801,0x003f9178,0x0047b86f, +0xb0020001,0xb4c0fffd,0x90210020,0x90630020, +0x808f0000,0x806f001f,0x80af001f,0x8027647c, +0x5c22b801,0x8067017e,0xb600020a,0x00cfb803, +0x003fb178,0x5822b801,0x01cfb801,0x003f9178, +0x0047b86f,0xb0020001,0xb4c0fffd,0x90210020, +0x90630020,0x806f0010,0x80af0010,0x8027657c, +0x5c22b801,0x806701be,0x00cfb803,0x003fb178, +0x5822b801,0x01cfb801,0x003f9178,0x0047b86f, +0xb0020001,0xb4c0fffd,0x802765c0,0x5c22b801, +0x806701cf,0x00cfb803,0x003fb178,0x5822b801, +0x01cfb801,0x003f9178,0x0047b86f,0xb0020001, +0xb4c0fffd,0x80276000,0x005fb801,0x8033001f, +0x98218000,0x803effe0,0x90214000,0x803effe4, +0x8193001f,0x998c8000,0x019fb174,0x83270000, +0x003fb819,0x003f9174,0x5823b801,0x83338000, +0x1b39b801,0x003fb819,0x00000000,0x00000000, +0x81550000,0x0187b860,0x858c0040,0x81b380fc, +0x99ad0000,0x300cb80d,0xb4600003,0x81b30002, +0x99ad0000,0x118cb80d,0x003fb80c,0x00000000, +0x00000000,0x81550000,0x8257ffff,0x82d7ffff, +0x8357ffff,0x81672000,0x83440189,0xb00a0001, +0xb4000141,0x0187b860,0x858c0010,0x5988b80c, +0x5d8bb80c,0x958cffff,0xb00cc000,0xb4800002, +0x858cc000,0x918c8000,0x81b3001f,0x198cb80d, +0x801bffec,0x00000000,0x819effec,0x819e78d8, +0x019fb174,0x05acb800,0x300cb800,0xb4600001, +0x91ad4000,0x001f917c,0x1000b80d,0x001fb17c, +0x83440194,0xb00a0000,0xb4200127,0x015f0081, +0xb00a0002,0xb4200124,0x037f0082,0xb01b0000, +0xb400001e,0x0367b860,0x5b68b81b,0x5f68b81b, +0x017f4047,0x916b0010,0x5963b80b,0x83440160, +0x801bff84,0xb00a0001,0xb400000b,0xb00b00c0, +0xb460fffa,0x803f0000,0x80138000,0x1b7bb800, +0x003fb81b,0x00000000,0x00000000,0x80150000, +0x801bff84,0xb5000009,0x803f0000,0x80138000, +0x1b7bb800,0x003fb81b,0x00000000,0x00000000, +0x80150000,0x801bff84,0xb5000103,0x801bff84, +0x003f0084,0x3000b801,0x803eff84,0xb4000073, +0x801bff7c,0x00000000,0x94800080,0xb0040080, +0xb4200036,0x94800007,0x80730200,0xb0010002, +0xb420000e,0x80270265,0xb0040001,0xb4200003, +0x80130030,0x98000000,0xb5000006,0x80130030, +0x98000000,0xb0040000,0xb4000002,0x80130038, +0x98000000,0x98630060,0xb500001f,0xb0010000, +0xb420000e,0x80270225,0xb0040001,0xb4200003, +0x80130030,0x98001000,0xb5000006,0x80130030, +0x98001000,0xb0040000,0xb4000002,0x80130038, +0x98001000,0x98630000,0xb500000f,0xb0010001, +0xb420004a,0x80270225,0xb0040001,0xb4200003, +0x80130030,0x98002000,0xb5000006,0x80130030, +0x98000000,0xb0040000,0xb4000002,0x80130038, +0x98000000,0x98630040,0x806600a6,0x80530001, +0x98420100,0x1821b802,0xb500002d,0x94800007, +0xb0010002,0xb420000d,0x80270eff,0xb0040001, +0xb4200003,0x80130030,0x98002000,0xb5000006, +0x80130030,0x98000000,0xb0040000,0xb4000002, +0x80130038,0x98000000,0xb500001d,0xb0010000, +0xb420000d,0x80270eff,0xb0040001,0xb4200003, +0x80130030,0x98002000,0xb5000006,0x80130030, +0x98002000,0xb0040000,0xb4000002,0x80130038, +0x98002800,0xb500000e,0xb0010001,0xb4200017, +0x80270eff,0xb0040001,0xb4200003,0x80130030, +0x98002000,0xb5000006,0x80130030,0x98002000, +0xb0040000,0xb4000002,0x80130038,0x98002800, +0x806500d4,0x8053ffcf,0x9842cfff,0xb0040002, +0xb4200002,0x8053ffc7,0x9842c7ff,0x802600a1, +0x1463b802,0x1863b800,0x806600d4,0x807bff7c, +0x00000000,0x94630080,0xb0030080,0xb420000b, +0x807bff88,0x00000000,0xb0030001,0xb4000007, +0x802500a1,0x80670001,0x807eff88,0x80530001, +0x98420100,0x1821b802,0x802600a1,0x81070000, +0x011f62e2,0x011f62e3,0x011f0082,0xb0080000, +0xb4200004,0x81150010,0x00000000,0x00000000, +0x011f62de,0x011f0081,0xb0080001,0xb4200026, +0x81070020,0x011f25c1,0x81070180,0x011f62e1, +0x8344022a,0x8344024e,0x011f0082,0xb0080000, +0xb4200004,0x834401b1,0x8344019e,0xb00a0000, +0xb4200061,0x80c70000,0x00df25cb,0x83440261, +0x834405e7,0x02ff05b9,0x82a70000,0x82870000, +0x834403cf,0x92940001,0x3014b817,0xb480fffc, +0x8344067f,0x80270000,0x003f25dc,0x83440760, +0x003f05dc,0xb0010001,0xb4000003,0x802725d4, +0x003fb17a,0x00ffb81f,0x80d3001f,0x834725ac, +0x1b5ab806,0xb500002d,0xb0080002,0x81470004, +0xb4200045,0x81070008,0x011f25c1,0x81070480, +0x011f62e1,0x83440276,0x834402b0,0x011f0082, +0xb0080000,0xb4200004,0x8344019a,0x83440175, +0xb00a0000,0xb4200038,0x80c70000,0x00df25cb, +0x83440334,0x02df05cb,0x5ec2b816,0x834405ff, +0x02ff05b9,0x82a70000,0x82870000,0x834403a4, +0x92940001,0x3014b817,0xb480fffc,0x92b50001, +0xb0150003,0xb480fff8,0x83440651,0x80270000, +0x003f25dc,0x83440732,0x003f05dc,0xb0010001, +0xb4000003,0x8027268c,0x003fb17a,0x00ffb81f, +0x80d3001f,0x83472650,0x1b5ab806,0x80db78d8, +0x80fbffec,0x00000000,0x3006b807,0xb4200007, +0x00df05cb,0x90c60001,0x00df25cb,0xb006000c, +0xb4000002,0x035fb179,0x00ffb81f,0x80c70000, +0x00df25cb,0x80fb78dc,0x00000000,0x90e70001, +0xb00701b9,0xb4a00001,0x80e70001,0x80fe78dc, +0xb500feb0,0x802500a5,0x8153001f,0x3001b80a, +0xb420fffc,0x00ffb81f,0x001f42ea,0x1800b80a, +0x001f62ea,0x017f4047,0x5963b80b,0x0187b860, +0x118cb80b,0x81b380fe,0x99ad0000,0x300cb80d, +0xb4800003,0x81b30002,0x99ad0000,0x058cb80d, +0x003fb80c,0x00000000,0x00000000,0x81550000, +0x0187b860,0x5988b80c,0x5d8bb80c,0x958cffff, +0xb00cc000,0xb4800002,0x858cc000,0x918c8000, +0x81b3001f,0x198cb80d,0x801bffec,0x00000000, +0x819effec,0x019fb174,0x05acb800,0x300cb800, +0xb4600001,0x91ad4000,0x001f917c,0x1000b80d, +0x001fb17c,0x80171000,0x80971400,0x80270000, +0xb6001003,0xb6002002,0x001fa021,0x009fa021, +0x80171800,0xb6000602,0xb6002001,0x001fa021, +0x806f001f,0x80af001f,0x80a76604,0x80271400, +0xb6001004,0x01efb801,0x01afb805,0xb520ffff, +0x90a50080,0x80a76e04,0x80271400,0xb6001004, +0x01efb801,0x01afb805,0xb520ffff,0x90a50080, +0x81472000,0x015fb179,0x00ffb81f,0x00000000, +0x811be024,0x0107b860,0x95080007,0xb0080000, +0xb4000004,0xa5080008,0x00000000,0x0155b808, +0x00000000,0x8115000c,0x856b000c,0xb0080fff, +0xb400000b,0x81550004,0x856b0004,0x5904b808, +0x1908b80a,0x95080fff,0xb0080fff,0xb4000004, +0x81470001,0xb00b0020,0xb440fff6,0xb500000c, +0x81d50004,0x856b0004,0x00000000,0xb00e000f, +0xb400fffb,0x940b0007,0xb0000000,0xb420ffed, +0x001f42ea,0x9400fffe,0x81470000,0x001f62ea, +0x00ffb81a,0x950e0008,0x5d03b808,0x00000000, +0xb0080000,0xb40000c9,0x011f2080,0x950e0006, +0x5d01b808,0x81270004,0x0529b808,0x950e0001, +0x013f2081,0x011f2082,0x81150004,0x00000000, +0xb0080000,0xb40000bd,0xb008000f,0xb40000bb, +0x011f2083,0x81150002,0x00000000,0x81670004, +0xb0080002,0xb46000b5,0x011f2084,0x013f0081, +0xb0090002,0xb4200011,0x013f0083,0xb0080000, +0xb4200002,0x81077844,0xb5000005,0xb0080001, +0xb4200002,0x81077884,0xb5000001,0x81077824, +0x013f0083,0x5921b809,0x1129b808,0x0119b809, +0x00000000,0x00000000,0x011f6047,0x81150001, +0x00000000,0x011f2085,0x81150001,0x00000000, +0x011f2086,0x81350002,0x00000000,0x013f2087, +0x81150002,0x00000000,0x011f2088,0x81150001, +0x00000000,0x011f2089,0x81150001,0x00000000, +0x011f208a,0x81150002,0x00000000,0x011f208b, +0x81070001,0xb0090003,0xb4000001,0x81070002, +0x011f25b9,0x81070020,0x013f0081,0xb0090002, +0xb4200065,0x85290001,0xad29000f,0x00000000, +0x011f0083,0x1108b809,0x5901b808,0x910877c8, +0x0139b808,0x011f05b9,0x85080001,0x6928b809, +0x011f0084,0xb0090038,0xb4800007,0xb0080001, +0xb4000002,0xb0090050,0xb4400003,0x81270000, +0x8107001b,0xb5000010,0xb0080001,0xb4000005, +0xb0090060,0xb4800003,0x81270001,0x8107001e, +0xb5000009,0xb0080002,0xb4000005,0xb0090030, +0xb4400003,0x81270002,0x81070008,0xb5000002, +0x81270003,0x8107000c,0x011f25bb,0x013f25c0, +0xb0090002,0xb460001b,0x80477604,0x5c42b802, +0x814fffc0,0x80cf0037,0x005fb178,0x5842b802, +0x01cfb802,0x005f9178,0xb520ffff,0x90420020, +0x814fb580,0x80cf0057,0x005fb178,0x5842b802, +0x01cfb802,0x005f9178,0xb520ffff,0x804778a4, +0x5c42b802,0x814f39c0,0x80cf002f,0x005fb178, +0x5842b802,0x01cfb802,0x005f9178,0xb520ffff, +0xb5000021,0x804776e0,0x5c42b802,0x814fef40, +0x80cf0037,0x005fb178,0x5842b802,0x01cfb802, +0x005f9178,0xb520ffff,0x8297013c,0x8317018c, +0xb6000602,0x005f8034,0x031fa022,0x82970124, +0x83170160,0xb6000602,0x005f8034,0x031fa022, +0x8297010c,0x83170134,0xb6000602,0x005f8034, +0x031fa022,0x804778c4,0x5c42b802,0x814f1080, +0x80cf002f,0x005fb178,0x5842b802,0x01cfb802, +0x005f9178,0xb520ffff,0x013f0081,0xb0090001, +0xb420000e,0x808f0000,0x806f001b,0x80af001b, +0x80277758,0x5c22b801,0x80670037,0x00cfb803, +0x003fb178,0x5822b801,0x01cfb801,0x003f9178, +0x0047b86f,0xb0020001,0xb4c0fffd,0x011f25bb, +0x011f0087,0xb0080001,0xb4000002,0x011f05bb, +0xb5000003,0x011f0088,0x91080001,0x5902b808, +0x011f25ba,0x81470000,0x00ffb81a,0x81470008, +0x00ffb81a,0x81270000,0x81470000,0x300842de, +0xb400000b,0x013f42e2,0x91290001,0x013f62e2, +0x013f42e3,0x91290001,0x013f62e3,0x83640006, +0x00000000,0x00000000,0x013f42e2,0x81470002, +0x013f62e2,0x00ffb81a,0x00ffb81b,0x83640041, +0x80c70004,0x80270000,0xb600200d,0x00ff05b9, +0x5c42b801,0x300205ba,0xb4800001,0x80e70001, +0x80470000,0xb6270005,0x1062b801,0x914301b8, +0x00fff00a,0x83840050,0x90420080,0x90210004, +0x00ffb81a,0x8364002f,0x017f05bb,0x800700bc, +0x80270000,0xb00b0000,0xb4000015,0xb62b0014, +0x00ff05b9,0x5c42b801,0x300205ba,0xb4800001, +0x80e70001,0x80470000,0xb0070000,0xb400000b, +0xb627000a,0x1062b801,0x914301b8,0x00fff00a, +0x5c62b801,0x1063b800,0x00bff003,0x90650134, +0x00dff003,0x83840034,0x90420080,0x90210004, +0x019f05b9,0x80c70002,0x80270000,0xb00b0000, +0xb400000f,0xb62b000e,0x80470000,0xb00c0000, +0xb400000a,0xb62c0009,0x1062b801,0x914301b8, +0x00fff00a,0xb0070000,0xb4000003,0x906302b8, +0x00fff003,0x83840020,0x90420080,0x90210004, +0x00ffb81a,0x8107ffff,0x80c70004,0x00ff0083, +0x83840019,0x80c70002,0x00ff0084,0x83840016, +0x80c70001,0x00ff0085,0x83840013,0x80c70001, +0x00ff0086,0x83840010,0x80c70002,0x00ff0087, +0x8384000d,0x80c70002,0x00ff0088,0x8384000a, +0x80c70001,0x00ff0089,0x83840007,0x80c70001, +0x00ff008a,0x83840004,0x80c70002,0x00ff008b, +0x83840001,0x00ffb81b,0x80a70001,0x64a6b805, +0x5ca1b805,0xb0050000,0xb400000e,0x95288000, +0xb0090000,0xb4000001,0x81270001,0x5901b808, +0x1547b805,0xb00a0000,0xb4000001,0x81470001, +0x2129b80a,0xb0090000,0xb4000001,0xa1088005, +0xb500ffef,0x9508ffff,0x00ffb81c,0x015f05ba, +0x013f05b9,0x800700bc,0xb0090000,0xb400000f, +0xb00a0000,0xb400000d,0x80270000,0xb62a000b, +0x80470000,0xb6290008,0x80950004,0x5865b802, +0x1063b801,0x5862b803,0x906301b8,0x0217b803, +0x90420001,0x021fa004,0x90210001,0xa54a0020, +0xb4c0000e,0xb0090000,0xb400000c,0xb62a000b, +0x80950004,0x80470000,0xb6290007,0x5865b802, +0x1063b801,0x5862b803,0x906301b8,0x0217b803, +0x90420001,0x021fa004,0x90210001,0x00ffb81a, +0x013f05b9,0xb0090000,0xb4000019,0x80270000, +0xb6002017,0x80470000,0xb6290014,0x5865b802, +0x1063b801,0x5862b803,0x914301b8,0x009ff00a, +0xad420060,0x00000000,0x114ab801,0x5942b80a, +0x914a1c80,0x0217b80a,0xb0040000,0xb4000004, +0x80950006,0x00000000,0x021fa004,0xb5000002, +0x8087003f,0x021fa004,0x90420001,0x90210001, +0x00ffb81a,0x8257ffff,0x82d7ffff,0x011f05ba, +0x013f05b9,0x80270000,0xb0090000,0xb400002b, +0xb6280015,0x80470000,0xb6290012,0x5865b802, +0x1063b801,0x5862b803,0x914301b8,0xaca20060, +0x009ff00a,0x10a5b801,0x58a2b805,0x90a502b8, +0x0217b805,0x80670000,0xb0040000,0xb4000003, +0x90840001,0x0075b804,0x00000000,0x021fa003, +0x90420001,0x90210001,0xa5480020,0xb4000013, +0x5822b801,0xb62a0011,0x914101b8,0x90a102b8, +0x0217b805,0x009ff00a,0xb0040000,0x80670000, +0xb4000002,0x90840001,0x0075b804,0xb6290006, +0x021fa203,0x009f8210,0x009f8210,0x009f8210, +0x009f8210,0x009f8210,0x90210004,0x00ffb81a, +0x015f05ba,0x013f05b9,0x800700bc,0xb0090000, +0xb4000013,0xb00a0000,0xb4000011,0x80270000, +0xb62a000f,0x80470000,0xb629000c,0x1080b801, +0x007ff004,0x90830134,0x007ff004,0x0095b803, +0x5865b802,0x1063b801,0x5862b803,0x906301b8, +0x0217b803,0x90420001,0x021fa004,0x90210001, +0x011f05bb,0x254ab808,0xb4c0000d,0xb62a000c, +0x1080b801,0x007ff004,0x90830134,0x007ff004, +0x0095b803,0x5862b801,0x906301b8,0x0217b803, +0x90210001,0x021fa204,0x007f8210,0x021fa004, +0xa5480020,0xb4c0000e,0xb0090000,0xb400000c, +0x80870000,0xb62a000a,0x80470000,0xb6290007, +0x5865b802,0x1063b801,0x5862b803,0x906301b8, +0x0217b803,0x90420001,0x021fa004,0x90210001, +0x00000000,0x00000000,0x00ffb81a,0x011f05bb, +0x013f05b9,0xb0080000,0xb4000015,0xb0090000, +0xb4000013,0x00000000,0x80270000,0xb6280010, +0x80470000,0xb629000d,0x5865b802,0x1063b801, +0x5862b803,0x914301b8,0x009ff00a,0xb0040000, +0xb4000005,0x80950002,0x906302b8,0x0217b803, +0x00000000,0x021fa004,0x90420001,0x90210001, +0xa5480020,0xb00a0000,0xb4000010,0xb0090000, +0xb400000e,0x00000000,0x80870000,0xb62a000b, +0x80470000,0xb6290008,0x5865b802,0x1063b801, +0x5862b803,0x906302b8,0x0217b803,0x00000000, +0x021fa004,0x90420001,0x90210001,0xb0080000, +0xb400004c,0xb0090000,0xb400004a,0x00000000, +0x80270000,0xb6280047,0x80470000,0xb6290044, +0x5865b802,0x1063b801,0x5862b803,0x914301b8, +0x009ff00a,0xad420060,0x00000000,0x00000000, +0x00000000,0x114ab801,0x5942b80a,0x914a1c80, +0x0217b80a,0xb0040000,0xb400002e,0x906302b8, +0x009ff003,0xb0040000,0xb420000a,0x80950006, +0x00000000,0x021fa204,0x80950006,0x015f8210, +0x021fa204,0x80950006,0x015f8210,0x021fa004, +0xb5000026,0xb0040001,0xb4200009,0x80950006, +0x00000000,0x021fa204,0x015f8210,0x021fa204, +0x80950006,0x015f8210,0x021fa004,0xb500001b, +0xb0040003,0xb4200009,0x80950006,0x00000000, +0x021fa204,0x80950006,0x015f8210,0x021fa204, +0x015f8210,0x021fa004,0xb5000010,0xb0040002, +0xb420000e,0x80950006,0x00000000,0x021fa204, +0x015f8210,0x021fa204,0x015f8210,0x021fa004, +0xb5000006,0x8087003f,0x021fa204,0x015f8210, +0x021fa204,0x015f8210,0x021fa004,0x90420001, +0x90210001,0xa5480020,0xb4c00011,0xb0090000, +0xb400000f,0x8087003f,0x5862b801,0x90631afc, +0xb62a000b,0x90630004,0x0047b803,0xb6290008, +0x90420180,0x0217b802,0x00000000,0x021fa204, +0x003f8210,0x021fa204,0x003f8210,0x021fa004, +0x00ffb81a,0x8257ffff,0x82d7ffff,0x011f05bb, +0x013f05b9,0x80270000,0x00e7b809,0x300105ba, +0xb4800001,0x80e70001,0x800700bc,0x80470000, +0xb0070000,0xb400004c,0xb627004b,0x5865b802, +0x1063b801,0x5862b803,0x914301b8,0xaca20060, +0x009ff00a,0x10a5b801,0x58a2b805,0x90a502b8, +0x0217b805,0xb0040000,0xb400002b,0x1060b801, +0x00bff003,0x10a5b804,0x90650160,0x00dff003, +0xb0060003,0xb4200007,0x90650134,0x00dff003, +0xb6000303,0x0075b806,0x021fa203,0x007f8210, +0xb5000021,0x5861b805,0x906300dc,0x009fd803, +0x90650134,0x00dff003,0xaca20060,0x00000000, +0x00000000,0x00000000,0x0075b806,0x10a5b801, +0x58a2b805,0x90a502b8,0x0217b805,0x588fb804, +0xb600030c,0xb6001007,0x04a3b804,0xb4600002, +0x58a1b803,0xb5000002,0x58a1b805,0x90a50001, +0x0067b805,0x9465ffff,0x5d50b805,0x021fa20a, +0x015f8210,0xb5000004,0x81470000,0xb6000302, +0x021fa20a,0x009f8210,0x009f05b9,0xb0040002, +0xb420000c,0x300105ba,0xb480000a,0x58a2b801, +0x90a502b8,0x0217b805,0x90a50180,0x0297b805, +0xb6000304,0x00bf8210,0x009f8210,0x029fa205, +0x009f8214,0x90420001,0x90210001,0x3001b808, +0xb480ffa9,0xa5480020,0xb00a0000,0xb4000015, +0xb0090000,0xb4000013,0x58a2b801,0x90a502b8, +0xb62a0010,0x80470000,0xb629000d,0xaca20060, +0x00000000,0x00000000,0x00000000,0x80670000, +0x10a5b801,0x58a2b805,0x90a502b8,0x0217b805, +0xb6000302,0x021fa203,0x00bf8210,0x90420001, +0x90210001,0x00ffb81a,0x00000000,0x00000000, +0x80770000,0x8057ffff,0x80f70000,0x80d7ffff, +0x81770000,0x8157ffff,0x81f70000,0x81d7ffff, +0xac140060,0xac350020,0x00000000,0x00000000, +0x12c0b801,0x5ac2b816,0x92d61980,0x83a400a5, +0xad940400,0x009f9173,0x013f05ca,0x914c6604, +0x114ab804,0x001f97e0,0x001eb80a,0xb0090000, +0xb4000003,0x80a76e44,0x80c76644,0xb5000002, +0x80a76644,0x80c76e44,0x808f000f,0x806f0000, +0x80af000e,0x80cf07e1,0x11e5b80c,0x11efb804, +0x5de2b80f,0x01ffb178,0x59e2b80f,0x01afb80f, +0x01ff9178,0x0047b86f,0xb0020001,0xb4c0fffd, +0x80cf07f0,0x1206b80c,0x1210b804,0x5e02b810, +0x021fb178,0x5a02b810,0x01afb810,0x021f9178, +0x0047b86f,0xb0020001,0xb4c0fffd,0x916c6e04, +0x116bb804,0x001f97ff,0x001eb80b,0x808f0000, +0x806f001f,0x80af001f,0x90ac6604,0x5ca2b805, +0x80270400,0xb600080a,0x00cfb801,0x00bfb178, +0x58a2b805,0x01cfb805,0x00bf9178,0x0047b86f, +0xb0020001,0xb4c0fffd,0x90210020,0x90a50020, +0x90ac6e04,0x5ca2b805,0x80270500,0xb600080a, +0x00cfb801,0x00bfb178,0x58a2b805,0x01cfb805, +0x00bf9178,0x0047b86f,0xb0020001,0xb4c0fffd, +0x90210020,0x90a50020,0x81530020,0xac140060, +0xac350020,0x80170800,0x80d7003c,0x12c0b801, +0x5ac2b816,0x92d602b8,0x0117b816,0x90241000, +0x0097b801,0x80470000,0x4002b803,0xb6000804, +0x005f8020,0x480287e4,0x005f8020,0x500287e4, +0x00000000,0x00000000,0x00000000,0x1021b80a, +0x5c36b801,0x5801b800,0x18c0b801,0xb0090000, +0xb4000002,0x90641440,0xb5000001,0x90641040, +0xb6000f0d,0x0097b803,0x80470000,0x4002b803, +0xb6001002,0x005f8020,0x480287e4,0x0108a026, +0x90630040,0x00000000,0x1021b80a,0x5c36b801, +0x5801b800,0x18c0b801,0x90641400,0x0097b803, +0x80470000,0x4002b803,0x005f8020,0x005f87e4, +0xb6000802,0x005f8040,0x480287c4,0x005f87e0, +0x0108a026,0x00000000,0x1021b80a,0x5c36b801, +0x5801b800,0x18c0b801,0xb0090000,0xb4000002, +0x906417c0,0xb5000001,0x906413c0,0xb6000f0f, +0x0097b803,0x80470000,0x4002b803,0xb6000804, +0x005f8020,0x500287e4,0x005f8020,0x480287e4, +0x0108a026,0x84630040,0x00000000,0x1021b80a, +0x5c36b801,0x5801b800,0x18c0b801,0xb0140000, +0xb4200005,0x90840004,0x9484003f,0x009fb173, +0xa1290001,0x013f25ca,0x80d7ffff,0x0108a026, +0x00ffb81a,0x81330004,0x8093007f,0x9884ffff, +0x80b3ff80,0x0017b816,0x90360040,0x0097b801, +0x81530010,0xb6001004,0x400a8000,0x404a8004, +0x0008a020,0x0088a022,0x0017b816,0x9036007c, +0x0097b801,0x81171000,0xb6001004,0x40048020, +0x480487e4,0x00000000,0x0108a020,0x81470000, +0x81670001,0x81870008,0x81a70040,0x81c707c4, +0x81e70040,0xb6000432,0xb00a0001,0xb4e00004, +0x80c71000,0x80e71000,0x81171040,0xb5000003, +0x80c71040,0x80e71040,0x81171000,0x844d0004, +0x10e7b802,0xb62b001f,0x0017b806,0x0097b807, +0xb62c0004,0x40048020,0x480487e4,0x00000000, +0x0108a020,0x0017b806,0x0097b807,0x0197b80e, +0x00000000,0x001f8020,0x042087e4,0xb62c000f, +0x4041800c,0x001f8020,0x0048b802,0x5e38802c, +0x2e11b801,0x042087e4,0x1042b810,0x0462b804, +0xb4a00002,0x0047b804,0xb5000003,0x0462b805, +0xb4600001,0x0047b805,0x011fa022,0x10c6b80f, +0x10e7b80f,0x5961b80b,0x5d81b80c,0x5da1b80d, +0x5de1b80f,0x914a0001,0x954a0001,0x11ceb80f, +0x80171018,0x81171fcc,0x80470000,0x41448020, +0x494487c0,0x00000000,0x0188b80a,0x494487e0, +0x00000000,0x0148b80a,0x0502a10a,0x4145b80c, +0x494580e0,0x00000000,0x0108a5ea,0x41448080, +0x494487c0,0x00000000,0x0108a78a,0x49448020, +0x00000000,0x0108a2ea,0x41448020,0x49448720, +0x00000000,0x0188b80a,0x4145b80c,0x49458080, +0x494587a0,0x00000000,0x0108a68a,0x4145b80c, +0x49458080,0x494587a0,0x00000000,0x0108a08a, +0x4145b80c,0x49458020,0x49458040,0x00000000, +0x0188b80a,0x494587e0,0x00000000,0x0108a08a, +0x4144b80c,0x494587a0,0x00000000,0x0108a52a, +0x41448080,0x49448040,0x494486c0,0x00000000, +0x0108a04a,0x41448040,0x49448720,0x00000000, +0x0108a36a,0x04028020,0x011fa420,0x001f8040, +0x011fa100,0x001f8080,0x011fa080,0x001f8100, +0x011fa040,0x001f8660,0x011fa120,0x41458020, +0x49458000,0x00000000,0x0108a00a,0x0017b816, +0x9036007c,0x0097b801,0x81171000,0x81970784, +0x00000000,0x001f8020,0x042087e4,0xb600100f, +0x4041800c,0x001f8020,0x0048b802,0x5e38802c, +0x2e11b801,0x042087e4,0x1042b810,0x0462b804, +0xb4a00002,0x0047b804,0xb5000003,0x0462b805, +0xb4600001,0x0047b805,0x011fa022,0x81470000, +0x81670001,0x81870008,0x81a70040,0x81c707c4, +0x81e70040,0xb6000432,0xb00a0001,0xb4e00004, +0x80c71000,0x80e71000,0x81171040,0xb5000003, +0x80c71040,0x80e71040,0x81171000,0x844d0004, +0x10e7b802,0xb62b001f,0x0017b806,0x0097b807, +0xb62c0004,0x40048020,0x480487e4,0x00000000, +0x0108a020,0x0017b806,0x0097b807,0x0197b80e, +0x00000000,0x001f8020,0x042087e4,0xb62c000f, +0x4041800c,0x001f8020,0x0048b802,0x5e38802c, +0x2e11b801,0x042087e4,0x1042b810,0x0462b804, +0xb4a00002,0x0047b804,0xb5000003,0x0462b805, +0xb4600001,0x0047b805,0x011fa022,0x10c6b80f, +0x10e7b80f,0x5961b80b,0x5d81b80c,0x5da1b80d, +0x5de1b80f,0x914a0001,0x954a0001,0x11ceb80f, +0x80171034,0x81171f84,0x80470000,0x41448040, +0x49448640,0x00000000,0x0188b80a,0x49448100, +0x49448780,0x00000000,0x0108a08a,0x4144b80c, +0x49448040,0x49448080,0x494487c0,0x00000000, +0x0108a16a,0x4145b80c,0x49458700,0x00000000, +0x0188b80a,0x494581a0,0x494586e0,0x00000000, +0x0108a66a,0x4145b80c,0x49448040,0x494487e0, +0x00000000,0x0188b80a,0x011fa1ec,0x4145b80c, +0x49458100,0x49458780,0x00000000,0x0108a08a, +0x41458720,0x49458100,0x494586e0,0x49458160, +0x49458020,0x49458020,0x49458760,0x00000000, +0x0108a08a,0x414587a0,0x49458080,0x49458760, +0x494580c0,0x49458700,0x49458140,0x49458020, +0x49458760,0x00000000,0x0108a74a,0x414587a0, +0x49458080,0x49458760,0x494580e0,0x49458700, +0x49458120,0x49458020,0x49458760,0x00000000, +0x0108a08a,0x41458720,0x49458100,0x494586e0, +0x49458140,0x49458040,0x49458020,0x49458720, +0x00000000,0x0108a0ca,0x41458080,0x49458040, +0x49458020,0x49458620,0x00000000,0x0188b80a, +0x49458080,0x00000000,0x0108a7ca,0x4144b80c, +0x49458040,0x49458020,0x49458080,0x00000000, +0x0108a5ea,0x41448080,0x49448700,0x00000000, +0x0188b80a,0x49448780,0x00000000,0x0108a7ca, +0x4144b80c,0x49448140,0x00000000,0x0108a7ca, +0x49448040,0x00000000,0x0108a0ca,0x41448700, +0x00000000,0x0188b80a,0x49448000,0x00000000, +0x0108a04a,0x011fa00c,0x80171f80,0xb6002006, +0x40048000,0x48048000,0x48048000,0x48048000, +0x00000000,0x0008a020,0x00ffb81d,0x00000000, +0x80770000,0x8057ffff,0x015f05b9,0x017f05bb, +0x8293ffff,0x9a94ffff,0x81a70000,0xb62a003a, +0xaded0180,0xae0d0180,0xadcd0080,0x902f1980, +0x0017b801,0xb6002033,0x904e01b8,0x00000000, +0x013ff002,0xb0090000,0xb400001f,0x904f02b8, +0x80c70000,0x011fd802,0x6829b808,0x94210001, +0xb0010001,0xb4e00001,0x00c7b814,0x6429b806, +0x80470001,0x6449b802,0x84420001,0x1442b808, +0x84690001,0x5863b803,0x906300dc,0x1042b801, +0x003f9803,0x90420001,0x4082b801,0x90630004, +0x003f9803,0x00000000,0x5897b804,0x1804b805, +0x4082b801,0x00000000,0x00000000,0x00000000, +0x10a4b800,0xb5000001,0x80a70000,0x90501c80, +0x00000000,0x007ff002,0x5842b803,0x904205f8, +0x0097b802,0x00000000,0x40058004,0x48058004, +0x00000000,0x0008a020,0x91ce0004,0x91ef0004, +0x92100004,0x91ad0001,0x00ffb81a,0x80770000, +0x8057ffff,0x80d7ffff,0x015f05b9,0x017f05bb, +0x8293ff80,0x9a940000,0x82a70020,0x81a70000, +0x81e702b8,0x80171980,0xb62a004f,0xb600034d, +0xac0d0080,0xac4d0180,0xac960080,0x822700bc, +0x91c001b8,0x00000000,0x1042b804,0x92021c80, +0xb62b003a,0x013ff00e,0x00fff011,0xb0090000, +0xb4000027,0x10e7b809,0x5821b807,0x902100dc, +0x00000000,0x001fd801,0x82470000,0x80270001, +0x6452b801,0x3002b800,0xb4600002,0x92520001, +0xb500fffb,0x86520001,0x80c70000,0x011fd80f, +0x6832b808,0xb0010001,0xb4e00001,0x00c7b814, +0x84520017,0x0056b802,0x80270001,0x6432b801, +0x84210001,0x1408b801,0x6402b800,0x10c6b800, +0x9027018c,0x00000000,0x001ff001,0x5802b800, +0x9020073c,0x904006f8,0x007f9801,0x0097b802, +0x10c6b803,0x40868004,0x48868004,0xb5000003, +0x80c70000,0x40868004,0x00000000,0x0088b804, +0x003ff010,0x5822b801,0x902105f8,0x0097b801, +0x91ce0004,0x91ef0004,0x40448004,0x48448004, +0x92100004,0x0008a022,0x92310001,0x0435b80b, +0xb4000007,0x80870000,0xb6210005,0x001fa024, +0x91ce0004,0x91ef0004,0x92100004,0x92310001, +0x00000000,0x91ad0001,0x00ffb81a,0x00000000, +0x007f05b9,0x001f0081,0xb0000001,0xb4400029, +0x001f05d8,0xac400080,0x801702b8,0x80970438, +0x90421800,0x0117b802,0x8087ffff,0x80b3ffff, +0x80d3007f,0x98c6ff00,0x80f3ff80,0x81070080, +0xb6002018,0x10088020,0x0056b800,0x0442b806, +0xb4a00004,0xb0000000,0x0007b806,0xb4400001, +0x0007b807,0x0027b800,0x5c08b800,0x1400b804, +0xb0030001,0xb4000008,0x10288024,0x0056b801, +0x0442b806,0xb4a00004,0xb0010000,0x0027b806, +0xb4400001,0x0027b807,0x5828b801,0x1421b805, +0x1900a021,0x001f05d8,0x90000001,0x001f25d8, +0x00ffb81a,0x801702b8,0x80970438,0x81171800, +0x8087ffff,0x80b3ffff,0x80d3007f,0x98c6ff00, +0x80f3ff80,0x81070080,0xb6006018,0x10088020, +0x0056b800,0x0442b806,0xb4a00004,0xb0000000, +0x0007b806,0xb4400001,0x0007b807,0x0027b800, +0x5c08b800,0x1400b804,0xb0030001,0xb4000008, +0x10288024,0x0056b801,0x0442b806,0xb4a00004, +0xb0010000,0x0027b806,0xb4400001,0x0027b807, +0x5828b801,0x1421b805,0x1900a021,0x00ffb81a, +0x001f0081,0xb0000001,0xb4400006,0x001f05d8, +0xb0000003,0xb4000003,0x80270001,0x003f25dc, +0x00ffb81a,0x003f05d9,0x009f05cb,0xb0010000, +0xb400000e,0x015f42ed,0x81070000,0x8127017c, +0xb00a0000,0xb4000002,0x81070180,0x812702fc, +0x802500a5,0x9421ffff,0x3001b808,0xb4800011, +0x3001b809,0xb4a00079,0xb500000e,0x001f0081, +0xb0000001,0xb4400003,0xb0040002,0xb4200006, +0xb5000002,0xb0040000,0xb4200003,0x802702ff, +0x81470000,0xb5000003,0x80270001,0x003f25d9, +0x81470180,0xb0040000,0xb4200001,0x83840344, +0x80070000,0x001f25d8,0x009f902d,0x80af001f, +0x808f0000,0x806f0000,0x8007ffff,0x8033ffff, +0x80171800,0x807bff8c,0x94630003,0xb0030003, +0xb4000016,0xb0030002,0xb4000035,0xb0030001, +0xb4000024,0xb6006010,0x14618000,0x6068b803, +0x40c4b803,0x14608000,0x00c8b806,0x5870b803, +0x6068b803,0x4104b803,0x58c8b806,0x0108b808, +0x14c6b801,0x00000000,0x00000000,0x5d08b808, +0x1508b800,0x1806a028,0xb5000030,0xb6006010, +0x14618000,0x6068b803,0x40c4b803,0x14608000, +0x00c8b806,0x5870b803,0x6068b803,0x4104b803, +0x5cc8b806,0x0108b808,0x14c6b800,0x00000000, +0x00000000,0x5908b808,0x1508b801,0x1806a028, +0xb500001e,0xb600600d,0x14618000,0x6068b803, +0x40c4b803,0x00000000,0x00c8b806,0x00000000, +0x00000000,0x00000000,0x5d08b806,0x1508b800, +0x58c8b806,0x14c6b801,0x1806a028,0xb500000f, +0xb600600e,0x14608000,0x5868b803,0x6068b803, +0x40c4b803,0x00000000,0x00c8b806,0x00000000, +0x00000000,0x00000000,0x5d08b806,0x1508b800, +0x58c8b806,0x14c6b801,0x1806a028,0x80670600, +0x5d22b80a,0xb600030a,0x00cfb803,0x013fb178, +0x5922b809,0x01afb809,0x013f9178,0x0047b86f, +0xb0020001,0xb4c0fffd,0x90630020,0x91290020, +0x81270180,0xb00a0000,0xb4000001,0x81270000, +0x013f62ed,0x80270001,0x003f25dc,0x00ffb81a, +0x801bff7c,0x00000000,0x94000080,0xb0000080, +0xb400ff67,0x001f0081,0xb0000001,0xb4400006, +0x001f05d8,0xb0000003,0xb4000003,0x80270001, +0x003f25dc,0x00ffb81a,0x003f05d9,0x009f05cb, +0xb0010000,0xb400000e,0x015f42ed,0x81070000, +0x812702fc,0xb00a0000,0xb4000002,0x81070300, +0x812705fc,0x802500a5,0x9421ffff,0x3001b808, +0xb4800011,0x3001b809,0xb4a0006d,0xb500000e, +0x001f0081,0xb0000001,0xb4400003,0xb0040002, +0xb4200006,0xb5000002,0xb0040000,0xb4200003, +0x802705ff,0x81470000,0xb5000003,0x80270001, +0x003f25d9,0x81470300,0xb0040000,0xb4200001, +0x838402ab,0x80070000,0x001f25d8,0x009f902d, +0x80af001f,0x808f0000,0x806f0000,0x8007ffff, +0x8033ffff,0x80171800,0x807bff8c,0x80971980, +0x94630003,0xb0030003,0xb4000013,0xb0030002, +0xb400002c,0xb0030001,0xb400001e,0xb600600d, +0x58708000,0x6068b803,0x40c4b803,0x14618020, +0x00c8b806,0x6068b803,0x4104b803,0x00000000, +0x0108b808,0x5887a026,0x00000000,0x00000000, +0x5887a028,0xb5000026,0xb600600d,0x14618000, +0x6068b803,0x40c4b803,0x58708020,0x00c8b806, +0x6068b803,0x4104b803,0x00000000,0x0108b808, +0x5887a026,0x00000000,0x00000000,0x5887a028, +0xb5000017,0xb600600a,0x14618000,0x6068b803, +0x40c4b803,0x00000000,0x00c8b806,0x00000000, +0x00000000,0x00000000,0x5887a026,0x5887a026, +0xb500000b,0xb600600a,0x58708000,0x6068b803, +0x40c4b803,0x00000000,0x00c8b806,0x00000000, +0x00000000,0x00000000,0x5887a026,0x5887a026, +0x80670660,0x5d22b80a,0xb600060a,0x00cfb803, +0x013fb178,0x5922b809,0x01afb809,0x013f9178, +0x0047b86f,0xb0020001,0xb4c0fffd,0x90630020, +0x91290020,0x81270300,0xb00a0000,0xb4000001, +0x81270000,0x013f62ed,0x80270001,0x003f25dc, +0x00ffb81a,0x00000000,0x00000000,0x00000000, +0x029fb024,0x02bfb025,0x02dfb026,0x02ffb027, +0x031fb028,0x033fb029,0x033f4046,0x0287b86f, +0x029fb02a,0x8285009d,0x9a940008,0x8286009d, +0x8285009c,0x96b48000,0xb0158000,0xb40001b5, +0x96b40100,0xb0150100,0xb400020b,0x96b40400, +0xb0150400,0xb400020c,0x96b40001,0xb0150001, +0xb400000c,0x96b40008,0xb0150008,0xb40001ad, +0x96b44000,0xb0154000,0xb400020b,0x96b40002, +0xb0150002,0xb4000182,0x00000000,0x00000000, +0xb500021d,0x02bf917e,0x92b50001,0x02bfb17e, +0x82850082,0x96f40001,0xb0170000,0xb4000171, +0x5efdb814,0x96f70001,0xb0170001,0xb420000b, +0x83050069,0x9718003f,0x82e50064,0x12f7b818, +0x86f70109,0x82feff74,0x02e7b86f,0x9af74000, +0x01ffb817,0x96f7bfff,0x01ffb817,0x83050081, +0x82a5009a,0x96b50001,0xb0150001,0xb4200014, +0x82a70000,0x02bfb17e,0x96b41840,0xb0150800, +0xb420000c,0x96b40008,0x5aa9b815,0x96d46000, +0x5ec3b816,0x82f3000f,0x9af7c00f,0x1718b817, +0x1ab5b818,0x1ab5b816,0x9ab50340,0x82a60081, +0xb500014c,0x9b180180,0x83060081,0xb5000149, +0x82a5009a,0x96b50002,0xb0150002,0xb420001b, +0x82a70000,0x02bfb17e,0x96b41800,0xb0151800, +0xb4000013,0x96b40040,0xb0150040,0xb4200004, +0xa3180c00,0x9b180340,0x83060081,0xb5000139, +0x96b40008,0x5aa9b815,0x96d46000,0x5ec3b816, +0x82f3000f,0x9af7c00f,0x1718b817,0x1ab5b818, +0x1ab5b816,0x9ab50340,0x82a60081,0xb500012d, +0x9b180180,0x83060081,0xb500012a,0x82a500c1, +0x96b5000f,0xb015000b,0xb420000e,0x96b40020, +0xb0150020,0xb400000b,0x96b40200,0xb0150200, +0xb4000008,0x82c50086,0x82e50094,0x3016b817, +0xb4400004,0x06f7b816,0xb017ff00,0xb4400001, +0xb5000118,0x96b46000,0xb0156000,0xb4000011, +0x96b41820,0xb0150820,0xb4200004,0x9b391000, +0x82a5009a,0x96b5feff,0x82a6009a,0x96b40040, +0xb0150040,0xb4200001,0x9739efff,0x96b91000, +0xb0151000,0xb4200003,0x82a5009a,0x9ab50100, +0x82a6009a,0x96b40040,0xb0150040,0xb4200019, +0x96b41800,0xb0151800,0xb4200006,0x96b98000, +0xb0158000,0xb4200003,0x9b180180,0x83060081, +0xb50000f8,0x96d80c00,0x82b300ff,0x9ab5f3ff, +0x1718b815,0xb0160c00,0xb4000007,0x82e50098, +0x96f70400,0xb0170400,0xb4200002,0x82c70c00, +0xb5000001,0xa2d60c00,0x1b18b816,0x9b180340, +0xb50000c4,0x96b40220,0xb0150000,0xb4e00021, +0x82a5009d,0x82f3ffff,0x16b5b817,0x82f33800, +0x3015b817,0xb420001b,0x96f98000,0xb0178000, +0xb4000018,0x82a70000,0x02bfb17e,0x82c5009d, +0x96d6ffff,0x82b3c800,0x9ab58001,0x82e500c1, +0x96f7000f,0xb017000b,0xb4000002,0x82b38800, +0x9ab58001,0x1ab5b816,0x82c5009a,0x96d60020, +0xb0160020,0xb4200002,0x82b3c800,0x9ab58001, +0x82a6009d,0x02ff917e,0x00000000,0xb0170040, +0xb4800000,0x5eb5b814,0x96b500f0,0x96f46000, +0x5eedb817,0x1ab5b817,0xb0170003,0xb4000004, +0x96b500ef,0x96f70001,0x5ae4b817,0x1ab5b817, +0x96d41800,0xb0161800,0xb400000a,0x96f900ff, +0x96b500ff,0x9739ff00,0x1b39b815,0x02a7b817, +0x96b500f3,0x96d40008,0x5ec1b816,0x1ab5b816, +0xb500000c,0x96f98000,0xb0178000,0xb4200007, +0x5efeb814,0x96f70001,0xb0170001,0xb4000003, +0x9b180180,0x83060081,0xb50000a2,0x96b500f3, +0x9ab50008,0x9739fff3,0x96d40020,0xb0160020, +0xb4200019,0x82c7001f,0x82c600c9,0x9b398000, +0x82c70000,0x02dfb17e,0x96d40010,0x5ac8b816, +0x82f300ff,0x9af7cfff,0x1718b817,0x1b18b816, +0x9b180340,0x82c5009d,0x96d6ffff,0x82f33800, +0x9af78001,0x1af7b816,0x82c5009a,0x96d60020, +0xb0160020,0xb4200002,0x82f3c800,0x9af78001, +0x82e6009d,0xb500005f,0x97397fff,0x96b500ff, +0x5aaab815,0x82f300fc,0x9af703ff,0x1718b817, +0x1b18b815,0x9b180340,0x82c5009a,0x96d60010, +0xb0160010,0xb4200027,0x82c70000,0x02dfb17e, +0x82c50086,0x92d60e10,0x82c60086,0x82c50094, +0x5eefb818,0x96f70003,0xb0170003,0xb4200002, +0x82e70e10,0xb5000001,0x82e70e10,0x12d6b817, +0x82e50081,0x9af70020,0x82e60081,0x82c60094, +0xa2f70020,0x82e60081,0x82f30001,0x16f7b818, +0x5ef0b817,0xb0170001,0xb4000004,0x96f84000, +0x5ee4b817,0x9718f3ff,0x1b18b817,0x82f32800, +0x9af78000,0x82e6009d,0x83060081,0x83070001, +0x8306009f,0x8305009c,0xb0180001,0xb4e0fffb, +0xb50000f5,0x82c5009d,0x82f33800,0x9af78001, +0x3016b817,0xb420000f,0x82b3c800,0x9ab58001, +0x82e500c1,0x96f7000f,0xb017000b,0xb4000002, +0x82b38800,0x9ab58001,0x82c5009a,0x96d60020, +0xb0160020,0xb4200002,0x82b3c800,0x9ab58001, +0x82a6009d,0x82c5009a,0x96d60080,0xb0160080, +0xb4000013,0x02df917e,0x00000000,0xb0160010, +0xb480000f,0x82c500c1,0x96d6000f,0xb016000b, +0xb400000b,0x82c50087,0x96d60080,0x5ac7b816, +0x82c50098,0x96d60800,0x5ac3b816,0x96f84000, +0x3017b816,0xb4200002,0x033f4046,0x9b394000, +0x9739bfff,0x82e50061,0x96f70008,0xb0170008, +0xb4000005,0x5eefb818,0x96f70003,0xb0170003, +0xb4000001,0x9718ffff,0x96b41800,0xb0151800, +0xb4000008,0x5eb9b814,0x96b5000f,0x82c50099, +0x5ed0b816,0x96f6000f,0x5ab0b815,0x82a60099, +0xb5000002,0x5ef9b814,0x96f7000f,0x5aecb817, +0x82c5009a,0x96d60fff,0x1ad6b817,0x82c6009a, +0x96b46000,0xb0156000,0xb4200005,0x5ae2b817, +0x82d30ffc,0x9ad63fff,0x1718b816,0x1b18b817, +0x83060081,0x83070001,0x8306009f,0x8305009c, +0xb0180001,0xb4e0fffb,0x00000000,0xb500009e, +0x82850083,0x96b400ff,0xb015003c,0xb4200019, +0x96b92000,0xb0152000,0xb4000002,0x9b392000, +0xb5000014,0x9739d3ff,0x82870000,0x82860087, +0x82870008,0x82860083,0x829bff78,0x82a7001f, +0xb0140400,0xb4000001,0x82a70010,0x82a600c9, +0x829bff78,0x00000000,0x828600cb,0x8285009d, +0x82b3ffff,0x9ab5fffd,0x1694b815,0x8286009d, +0xb5000000,0x83070002,0x8306009f,0x00000000, +0xb500007d,0x83078000,0x8306009f,0x00000000, +0xb5000079,0x82850094,0x82a50086,0x06b5b814, +0x02b6b815,0xb0151700,0xb440004b,0x8285006c, +0x969400ff,0xb0140024,0xb4000019,0xb0140012, +0xb4000017,0x8285009a,0x5eedb814,0x96f70003, +0xb0170003,0xb4000009,0x82a50083,0x5ea8b815, +0x96b500ff,0xb0150020,0xb4400002,0x82c70bbc, +0xb5000001,0x82c70bb8,0xb5000008,0x82a50083, +0x5ea8b815,0x96b500ff,0xb0150020,0xb4400002, +0x82c71199,0xb5000001,0x82c71197,0xb5000016, +0x8285009a,0x5eedb814,0x96f70003,0xb0170003, +0xb4000009,0x82a50083,0x5ea8b815,0x96b500ff, +0xb0150020,0xb4400002,0x82c70e18,0xb5000001, +0x82c70e04,0xb5000008,0x82a50083,0x5ea8b815, +0x96b500ff,0xb0150020,0xb4400002,0x82c70e18, +0xb5000001,0x82c70e04,0x82e50086,0x12f7b816, +0x02bf917e,0xb0150020,0xb480000b,0x82a5009a, +0x96b56000,0xb0156000,0xb4000007,0x82a50098, +0x96d50a00,0xb0160a00,0xb4000002,0xb0160000, +0xb4200001,0x92f70704,0x82850081,0x9ab40020, +0x82a60081,0x82c50094,0x82e60094,0x82860081, +0x86b70704,0x82a6009b,0x83070008,0x8306009f, +0x00000000,0xb5000024,0x83070100,0x8306009f, +0x00000000,0xb5000020,0x83070000,0x83050081, +0x9b180180,0x83060081,0x83070400,0x8306009f, +0x00000000,0xb5000018,0x82870000,0x82850082, +0x5eb7b814,0x96b500fc,0x96d40006,0x5ec1b816, +0x1ab5b816,0x5aacb815,0x83050081,0x82d3001c, +0x9ad600ff,0x1718b816,0x1b18b815,0x9b180e00, +0x83060081,0x83074000,0x8306009f,0x8305009d, +0x82d3ffff,0x9ad6bfff,0x1718b816,0x8306009d, +0x00000000,0xb5000000,0x029f902a,0x01ffb814, +0x033f6046,0x029f9024,0x02bf9025,0x02df9026, +0x02ff9027,0x031f9028,0x033f9029,0x00ffb81e, +0x02ff917d,0x92f7092f,0x031f0084,0xb0180001, +0xb4200002,0x02ff917d,0x92f70870,0x02ffb17d, +0x02ff917c,0x82bbffdc,0x829bffd8,0x93150004, +0x3014b815,0xb4000017,0x02dbb818,0x029bb815, +0x3017b816,0xb4800013,0x5a81b814,0x029fb17d, +0x82def200,0x82fef204,0x82e50086,0x06f7b814, +0x02f6b817,0x82fef208,0x82860095,0x82870001, +0x829ef220,0x8293001f,0x9294fe00,0x92b50008, +0x3015b814,0xb4800002,0x82b3001f,0x92b5fa00, +0x82beffdc,0x82850086,0x83250094,0x06d4b819, +0x02d6b816,0xb016ffff,0xb4a00009,0x82c50081, +0x9ab60020,0x82a60081,0x82a50086,0x92b50e10, +0x82a60094,0x82c60081,0x86b50704,0x82a6009b, +0x00ffb81c,0x00000000,0x00000000,0x00000000, +0x001f9012,0x001fb200,0x001f004c,0x001f2804, +0x801bfef0,0x8058fef4,0x803bff68,0x8078ff6c, +0x2000b801,0x2042b803,0x001fb204,0x005f2814, +0x82e70001,0x83640048,0x029fb014,0x829efef0, +0x8286000f,0x02bf2054,0x82bcfef4,0x82a6000e, +0x00ffb81a,0x80e70001,0x801336e3,0x9800eb76, +0x001fb200,0x800700ab,0x001f2804,0x801bc3e8, +0x8058c3ec,0x83640024,0x82e70000,0x83640036, +0x029fb3c0,0x029fb200,0x02bf2f04,0x02bf2804, +0x801bc000,0x8058c004,0x8364001b,0x82e70000, +0x8364002d,0x001f93c0,0x3000b814,0xb420000a, +0x001f0f04,0x3000b815,0xb4200007,0x829efef0, +0x82bcfef4,0x029fb012,0x02bf204c,0x82870001, +0x829cfef5,0x00ffb81a,0xb0070000,0xb4000007, +0x80e70000,0x801399fa,0x9800c92e,0x001fb200, +0x800700af,0x001f2804,0xb500ffdc,0x82870000, +0x829cfef5,0x00ffb81a,0x80c700ff,0x803bff68, +0x8078ff6c,0x14a0b806,0x2063b805,0x007f2814, +0x2021b802,0x58c8b806,0x14a0b806,0x58b0b805, +0x2021b805,0x58c8b806,0x14a0b806,0x2021b805, +0x58c8b806,0x14a0b806,0x5cb0b805,0x2021b805, +0x003fb204,0x00ffb81b,0x82c70000,0x83070800, +0x83270005,0x8197080c,0x81d7ffff,0x83840126, +0x83840001,0x00ffb81b,0x808f0000,0x806f001f, +0x80af001f,0x80270240,0x81e77c08,0x5de2b80f, +0xb6000208,0x00cfb801,0x01ffb178,0x59e2b80f, +0x01cfb80f,0x01ff9178,0xb520ffff,0x91ef0020, +0x90210020,0x80270280,0x81e77b00,0x5de2b80f, +0xb6000208,0x00cfb801,0x01ffb178,0x59e2b80f, +0x01cfb80f,0x01ff9178,0xb520ffff,0x91ef0020, +0x90210020,0x8057ffff,0x80170830,0x80070810, +0x80270808,0xb6000509,0x005ff000,0x90420900, +0x007ff001,0x90630a00,0x009ff002,0x00bff003, +0x2004a025,0x90000001,0x90210001,0x80070814, +0x80d7ffff,0x8097085c,0x8017083c,0xb6000404, +0x005ff000,0x007f87e0,0x84000001,0x2082a7e3, +0x80970860,0x80170840,0x2082b803,0x007f8000, +0x2083a004,0x80170830,0x80970850,0x80270808, +0xb6000508,0x005f8024,0x90420900,0x007ff001, +0x90630a00,0x009ff002,0x00bff003,0x2004a025, +0x90210001,0x80170840,0x00000000,0x02bf87e0, +0x80970860,0x82870000,0xb6000404,0x005f87e4, +0x5a88b814,0x204287e0,0x1a94b802,0x00ffb81c, +0x001f0e49,0x001f2b09,0x001f0e41,0x001f2b08, +0x001f0e46,0x001f2b07,0x001f0e48,0x001f2b06, +0x001f0e42,0x001f2b05,0x001f0e47,0x001f2b04, +0x001f0e45,0x001f2b03,0x001f0e43,0x001f2b02, +0x001f0e40,0x001f2b01,0x001f0e44,0x001f2b00, +0x001f0f25,0xa020000c,0x94400001,0x94600002, +0x94810004,0x94a10008,0x94c00010,0x5943b802, +0x5861b803,0x5882b804,0x5ca2b805,0x5cc4b806, +0x194ab803,0x194ab804,0x194ab805,0x194ab806, +0x015f2b38,0x801b7c00,0x003f92c1,0x5c28b801, +0x005f92c2,0x5858b802,0x1821b802,0x2000b801, +0x001fb2c4,0x80187c04,0x003f0b09,0x2000b801, +0x001f2b14,0x82c70001,0x82e70001,0x83070b10, +0x8327001e,0x81970b35,0x8384009f,0x02df0b38, +0x82170e30,0x838400f1,0x819efef0,0x817cfef4, +0x819eff68,0x817cff6c,0x00ffb81b,0x820f001f, +0x8018fef8,0x8057ffff,0x001f2b09,0x8018fef6, +0x80d7ffff,0x001f2b08,0x8018fefa,0x8157ffff, +0x001f2b07,0x8018fefd,0x81d7ffff,0x001f2b06, +0x8018fefb,0x802f001f,0x001f2b05,0x8018fefe, +0x00000000,0x001f2b04,0x8018fef9,0x00000000, +0x001f2b03,0x8018feff,0x00000000,0x001f2b02, +0x8018fef7,0x00000000,0x001f2b01,0x8018fefc, +0x00000000,0x001f2b00,0x001f0f25,0xa0200011, +0x94410001,0x94600002,0x94800004,0x94a00008, +0x94c10010,0x5941b802,0x5861b803,0x5c82b804, +0x58a1b805,0x5cc1b806,0x194ab803,0x194ab804, +0x194ab805,0x194ab806,0x015f2b38,0x801b7c00, +0x003f92c1,0x5c28b801,0x005f92c2,0x5858b802, +0x1821b802,0x2000b801,0x001fb2c4,0x80187c04, +0x003f0b09,0x2000b801,0x001f2b14,0x82c70001, +0x82e70001,0x83070b10,0x8327001e,0x81970b35, +0x83840055,0x02df0b38,0x82170e20,0x838400a7, +0x819efef0,0x817cfef4,0x5ac8b80c,0x02ff0e44, +0x1ad6b817,0x02dfb391,0x5ed8b80c,0x5968b80b, +0x1ad6b80b,0x02df6724,0x00ffb81b,0x820f001f, +0x8018fefe,0x8057ffff,0x001f2b09,0x8018fefa, +0x80d7ffff,0x001f2b08,0x8018fefc,0x8157ffff, +0x001f2b07,0x8018feff,0x81d7ffff,0x001f2b06, +0x8018fef8,0x802f001f,0x001f2b05,0x8018fefb, +0x00000000,0x001f2b04,0x8018fefd,0x00000000, +0x001f2b03,0x8018fef6,0x00000000,0x001f2b02, +0x8018fef9,0x00000000,0x001f2b01,0x8018fef7, +0x00000000,0x001f2b00,0x801b7c00,0x003f92c1, +0x5c28b801,0x005f92c2,0x5858b802,0x1821b802, +0x2000b801,0x001fb2c4,0x80187c04,0x003f0b09, +0x2000b801,0x001f2b14,0x82c70001,0x82e70001, +0x83070b10,0x8327001e,0x81970b35,0x83840016, +0x83270000,0x831bfef0,0x82f8fef4,0x02c7b819, +0x82170e28,0x83840065,0x300cb818,0xb4200002, +0x300bb817,0xb4000006,0x93390001,0xb0190020, +0xb480fff6,0x83270000,0x833cfef5,0x00ffb81b, +0x019fb390,0x017f2e44,0x033f2f25,0x83270001, +0x833cfef5,0x00ffb81b,0x0007b818,0x90000003, +0x00000000,0x015ff000,0x90000001,0x5949b80a, +0x013ff000,0x194ab809,0x84000002,0x994a0100, +0x017ff000,0x958b00f8,0x5981b80c,0x956b0007, +0x198cb80b,0x84000002,0x998c0008,0x017ff000, +0x90000001,0x5971b80b,0x198cb80b,0x017ff000, +0x5969b80b,0x198cb80b,0x81a70000,0x94d90003, +0x82a70000,0xb6260019,0xb6000818,0x5df0b80a, +0x5e02b80a,0x21efb810,0x95ef0001,0x5941b80a, +0x194ab80f,0x21efb816,0x5e18b80c,0x5e35b80c, +0x5e54b80c,0x5e6cb80c,0x2210b811,0x2252b813, +0x2210b812,0x96100001,0x5981b80c,0x198cb810, +0x2210b817,0x10afb810,0x10a5b80d,0x5da1b805, +0x94a50001,0x5aa1b815,0x1ab5b805,0x019fa7f5, +0x5cc2b819,0xb626001c,0x82870000,0xb6000419, +0xb6000818,0x5df0b80a,0x5e02b80a,0x21efb810, +0x95ef0001,0x5941b80a,0x194ab80f,0x21efb816, +0x5e18b80c,0x5e35b80c,0x5e54b80c,0x5e6cb80c, +0x2210b811,0x2252b813,0x2210b812,0x96100001, +0x5981b80c,0x198cb810,0x2210b817,0x10afb810, +0x10a5b80d,0x5da1b805,0x94a50001,0x5a81b814, +0x1a94b805,0x019fa7f4,0x00ffb81c,0x8257ffff, +0x808f0000,0x806f001f,0x80af001f,0x80270300, +0x81e778e0,0x5de2b80f,0xb6000208,0x00cfb801, +0x01ffb178,0x59e2b80f,0x01cfb80f,0x01ff9178, +0xb520ffff,0x91ef0020,0x90210020,0x80270340, +0x81e779e0,0x5de2b80f,0xb6000208,0x00cfb801, +0x01ffb178,0x59e2b80f,0x01cfb80f,0x01ff9178, +0xb520ffff,0x91ef0020,0x90210020,0x80270280, +0x81e77b00,0x5de2b80f,0xb6000208,0x00cfb801, +0x01ffb178,0x59e2b80f,0x01cfb80f,0x01ff9178, +0xb520ffff,0x91ef0020,0x90210020,0x806f0007, +0x80af0007,0x80270380,0x81e77ae0,0x5de2b80f, +0x00cfb801,0x01ffb178,0x59e2b80f,0x01cfb80f, +0x01ff9178,0xb520ffff,0x91ef0020,0x90210020, +0x80170b60,0x001f0b00,0x001fa020,0x001f0b01, +0x001fa020,0x001f0b02,0x001fa020,0x001f0b03, +0x001fa020,0x001f0b04,0x001fa000,0x80970b50, +0x81170b70,0x82a70b35,0x83a40060,0x001f87e4, +0xb6000405,0x86b50001,0x83a4005c,0x001f8004, +0x003f87e8,0x2080a7e1,0x80970b70,0x80170b50, +0x81170b50,0x81970b40,0x82a70b30,0x001f800c, +0x003f8008,0x2100a001,0x83a40050,0x001f87e4, +0xb6000405,0x86b50001,0x83a4004c,0x001f8004, +0x003f87e8,0x2080a7e1,0x80970b50,0x80170b70, +0x81170b70,0x81970b60,0x82a70b2b,0x001f800c, +0x003f8008,0x2100a001,0x83a40040,0x83a4004e, +0xb6000407,0x86b50001,0x83a4003c,0x001f8004, +0x003f87e8,0x2080a001,0x83a40047,0x00000000, +0x80970b70,0x80170b50,0x81170b50,0x81970b40, +0x82a70b26,0x001f800c,0x003f8008,0x2100a001, +0x83a4002e,0x83a4003c,0xb6000407,0x86b50001, +0x83a4002a,0x001f8004,0x003f87e8,0x2080a001, +0x83a40035,0x00000000,0x80970b50,0x80170b70, +0x81170b70,0x81970b60,0x82a70b21,0x001f800c, +0x003f8008,0x2100a001,0x83a4001c,0x001f87e4, +0xb6000405,0x86b50001,0x83a40018,0x001f8004, +0x003f87e8,0x2080a7e1,0x80970b70,0x80170b50, +0x81170b50,0x81970b40,0x82a70b1c,0x001f800c, +0x003f8008,0x2100a001,0x83a4000c,0x017f87e4, +0x81870000,0xb6000406,0x86b50001,0x83a40007, +0x001f87e4,0x200087e8,0x5988b80c,0x198cb800, +0x021fa02c,0x021fa00b,0x00ffb81c,0x005ff015, +0x90420a00,0x003f87e0,0x001ff002,0x2060b801, +0x90630c00,0x90960e00,0x001ff003,0x003ff004, +0x20a0b801,0x90a50d00,0x00000000,0x001ff005, +0x009fa000,0x00ffb81d,0x001f8004,0x5c21b800, +0x5847b800,0x1821b802,0x942100ff,0x2080a7e1, +0x00ffb81d,0x00000000,0x00000000,0x00000000, + +}; + +static u32 MPGI2S240Ucode1f5c00[] = { +0x00000000,0xfffff8c0,0x00003540,0xffff8d40, +0x0001fd40,0xfffaf7c0,0x00066b80,0xffdb63c0, +0x00494780,0x00249c40,0x00066b80,0x00050840, +0x0001fd40,0x000072c0,0x00003540,0x00000740, +0xffffffc0,0xfffff840,0x00003680,0xffff7e40, +0x0001f400,0xfffa9cc0,0x0005d1c0,0xffd99600, +0x00493c00,0x0022ce00,0x0006f780,0x0004ad00, +0x000203c0,0x00006440,0x00003400,0x00000680, +0xffffffc0,0xfffff740,0x00003780,0xffff6ec0, +0x0001e800,0xfffa4240,0x00052a00,0xffd7ca00, +0x00491a00,0x0020ffc0,0x00077600,0x00045240, +0x00020800,0x000056c0,0x00003280,0x00000600, +0xffffffc0,0xfffff680,0x00003840,0xffff5ec0, +0x0001d940,0xfff9e8c0,0x00047440,0xffd60080, +0x0048e180,0x001f32c0,0x0007e700,0x0003f7c0, +0x000209c0,0x00004980,0x00003100,0x00000540, +0xffffffc0,0xfffff5c0,0x000038c0,0xffff4e40, +0x0001c780,0xfff990c0,0x0003b000,0xffd43ac0, +0x00489240,0x001d6800,0x00084b00,0x00039e40, +0x00020940,0x00003d00,0x00002f80,0x000004c0, +0xffffffc0,0xfffff4c0,0x00003900,0xffff3d40, +0x0001b2c0,0xfff93a40,0x0002ddc0,0xffd279c0, +0x00482d00,0x001ba040,0x0008a200,0x000345c0, +0x000206c0,0x00003140,0x00002dc0,0x00000440, +0xffffffc0,0xfffff3c0,0x00003900,0xffff2c00, +0x00019b00,0xfff8e640,0x0001fd40,0xffd0be80, +0x0047b1c0,0x0019dc80,0x0008ecc0,0x0002ef00, +0x00020240,0x00002640,0x00002c00,0x00000400, +0xffffff80,0xfffff2c0,0x000038c0,0xffff1a40, +0x00017fc0,0xfff894c0,0x00010e80,0xffcf09c0, +0x004720c0,0x00181d80,0x00092b40,0x000299c0, +0x0001fc00,0x00001bc0,0x00002a40,0x00000380, +0xffffff80,0xfffff180,0x00003800,0xffff0840, +0x00016180,0xfff84680,0x00001180,0xffcd5cc0, +0x00467a40,0x00166440,0x00095e00,0x00024680, +0x0001f440,0x00001200,0x00002840,0x00000340, +0xffffff80,0xfffff040,0x00003740,0xfffef600, +0x00014000,0xfff7fbc0,0xffff0680,0xffcbb880, +0x0045bf00,0x0014b140,0x00098580,0x0001f580, +0x0001ea80,0x00000900,0x00002680,0x000002c0, +0xffffff80,0xffffef00,0x000035c0,0xfffee3c0, +0x00011ac0,0xfff7b540,0xfffded80,0xffca1d80, +0x0044ef80,0x00130580,0x0009a1c0,0x0001a700, +0x0001dfc0,0x00000080,0x000024c0,0x00000280, +0xffffff40,0xffffedc0,0x00003400,0xfffed180, +0x0000f280,0xfff77340,0xfffcc700,0xffc88d80, +0x00440bc0,0x001161c0,0x0009b3c0,0x00015b00, +0x0001d380,0xfffff8c0,0x000022c0,0x00000240, +0xffffff40,0xffffec40,0x00003200,0xfffebf40, +0x0000c680,0xfff73680,0xfffb92c0,0xffc708c0, +0x00431500,0x000fc6c0,0x0009bb80,0x000111c0, +0x0001c640,0xfffff1c0,0x00002100,0x00000200, +0xffffff00,0xffffeac0,0x00002f40,0xfffead00, +0x00009740,0xfff6ff40,0xfffa5180,0xffc59080, +0x00420b40,0x000e3500,0x0009b9c0,0x0000cb80, +0x0001b7c0,0xffffeb40,0x00001f40,0x000001c0, +0xffffff00,0xffffe940,0x00002c40,0xfffe9b00, +0x00006480,0xfff6ce00,0xfff90380,0xffc425c0, +0x0040ef80,0x000cad00,0x0009af00,0x00008840, +0x0001a880,0xffffe580,0x00001d40,0x000001c0, +0xfffffec0,0xffffe7c0,0x000028c0,0xfffe8980, +0x00002e40,0xfff6a3c0,0xfff7a900,0xffc2c900, +0x003fc280,0x000b2fc0,0x00099b80,0x00004800, +0x00019880,0xffffe040,0x00001bc0,0x00000180, +0xfffffec0,0xffffe600,0x00002480,0xfffe7840, +0xfffff4c0,0xfff68040,0xfff64240,0xffc17b40, +0x003e84c0,0x0009bdc0,0x00097fc0,0x00000b40, +0x000187c0,0xffffdb80,0x00001a00,0x00000140, +0xfffffe80,0xffffe440,0x00001fc0,0xfffe6780, +0xffffb800,0xfff66480,0xfff4d040,0xffc03d80, +0x003d3700,0x00085700,0x00095c40,0xffffd1c0, +0x00017680,0xffffd740,0x00001840,0x00000140, +0xfffffe40,0xffffe2c0,0x00001a80,0xfffe5780, +0xffff77c0,0xfff65100,0xfff35300,0xffbf1080, +0x003bda40,0x0006fc80,0x00093200,0xffff9b80, +0x00016500,0xffffd3c0,0x000016c0,0x00000100, +0xfffffe40,0xffffe0c0,0x000014c0,0xfffe4840, +0xffff3480,0xfff64640,0xfff1cb00,0xffbdf4c0, +0x003a6f80,0x0005ae80,0x000900c0,0xffff68c0, +0x00015300,0xffffd0c0,0x00001540,0x00000100, +0xfffffe00,0xffffdf00,0x00000e40,0xfffe39c0, +0xfffeee40,0xfff64480,0xfff03940,0xffbceb00, +0x0038f740,0x00046d40,0x0008c980,0xffff3980, +0x000140c0,0xffffce00,0x000013c0,0x000000c0, +0xfffffdc0,0xffffdd40,0x00000740,0xfffe2c80, +0xfffea500,0xfff64c40,0xffee9e40,0xffbbf440, +0x00377280,0x00033900,0x00088cc0,0xffff0d80, +0x00012e80,0xffffcc00,0x00001240,0x000000c0, +0xfffffd80,0xffffdb40,0xffffff80,0xfffe2040, +0xfffe5900,0xfff65e40,0xffecfa80,0xffbb1080, +0x0035e280,0x00021280,0x00084ac0,0xfffee540, +0x00011c40,0xffffca40,0x00001100,0x00000080, +0xfffffd40,0xffffd980,0xfffff700,0xfffe1580, +0xfffe0a80,0xfff67a80,0xffeb4ec0,0xffba4100, +0x00344780,0x0000f980,0x00080440,0xfffec000, +0x00010a00,0xffffc8c0,0x00000fc0,0x00000080, +0xfffffcc0,0xffffd7c0,0xffffee00,0xfffe0bc0, +0xfffdb980,0xfff6a200,0xffe99bc0,0xffb985c0, +0x0032a340,0xffffee80,0x0007b980,0xfffe9e80, +0x0000f7c0,0xffffc800,0x00000e80,0x00000080, +0xfffffc80,0xffffd5c0,0xffffe440,0xfffe0400, +0xfffd6640,0xfff6d4c0,0xffe7e280,0xffb8df40, +0x0030f640,0xfffef180,0x00076b40,0xfffe8040, +0x0000e5c0,0xffffc740,0x00000d40,0x00000080, +0xfffffc00,0xffffd400,0xffffd9c0,0xfffdfdc0, +0xfffd1100,0xfff71340,0xffe62380,0xffb84e40, +0x002f4180,0xfffe02c0,0x000719c0,0xfffe6500, +0x0000d400,0xffffc700,0x00000c40,0x00000040, +0xfffffbc0,0xffffd240,0xffffcec0,0xfffdf940, +0xfffcba40,0xfff75e00,0xffe45fc0,0xffb7d300, +0x002d8640,0xfffd2240,0x0006c5c0,0xfffe4d40, +0x0000c2c0,0xffffc700,0x00000b40,0x00000040, +0xfffffb40,0xffffd080,0xffffc300,0xfffdf6c0, +0xfffc61c0,0xfff7b500,0xffe29800,0xffb76dc0, +0x002bc540,0xfffc5000,0x00066f40,0xfffe3880, +0x0000b1c0,0xffffc740,0x00000a40,0x00000040, +0xfffffac0,0xffffcf00,0xffffb680,0xfffdf640, +0xfffc0840,0xfff81900,0xffe0cd40,0xffb71e80, +0x0029ff80,0xfffb8bc0,0x00061740,0xfffe26c0, +0x0000a140,0xffffc7c0,0x00000980,0x00000040, +0xfffffa00,0xffffcd80,0xffffa940,0xfffdf800, +0xfffbadc0,0xfff88a00,0xffdf0040,0xffb6e600, +0x00283600,0xfffad600,0x0005bdc0,0xfffe1800, +0x00009140,0xffffc880,0x000008c0,0x00000040, +0xfffff980,0xffffcc00,0xffff9bc0,0xfffdfc40, +0xfffb5300,0xfff90880,0xffdd3200,0xffb6c400, +0x00266a00,0xfffa2e40,0x00056340,0xfffe0c00, +0x000081c0,0xffffc980,0x000007c0,0x00000040, +0x004013c2,0x0040b346,0x0041fa2d,0x0043f934, +0x0046cc1c,0x004a9d9d,0x004fae37,0x0056601f, +0x005f4cf7,0x006b6fcf,0x007c7d1e,0x0115b035, +0x013df91b,0x0207655e,0x03342c83,0x0a185230, +0x00404f46,0x0042e13c,0x0048919f,0x0052cb0e, +0x0064e240,0x0107c449,0x015c7926,0x050cf270, +0x004140fb,0x004cf8df,0x0073326c,0x02480d9d, +0x004545ea,0x01273d75,0x005a827a,0x007fffff, +0x006597fb,0x0050a28c,0x00400000,0x0032cbfd, +0x00285146,0x00200000,0x001965ff,0x001428a3, +0x00100000,0x000cb2ff,0x000a1451,0x00080000, +0x00065980,0x00050a29,0x00040000,0x00032cc0, +0x00028514,0x00020000,0x00019660,0x0001428a, +0x00010000,0x0000cb30,0x0000a145,0x00008000, +0x00006598,0x000050a3,0x00004000,0x000032cc, +0x00002851,0x00002000,0x00001966,0x00001429, +0x00001000,0x00000cb3,0x00000a14,0x00000800, +0x00000659,0x0000050a,0x00000400,0x0000032d, +0x00000285,0x00000200,0x00000196,0x00000143, +0x00000100,0x000000cb,0x000000a1,0x00000080, +0x00000066,0x00000051,0x00000040,0x00000033, +0x00000028,0x00000020,0x00000019,0x00000014, +0x00000010,0x0000000d,0x0000000a,0x00000008, +0x00000006,0x00000005,0x00000000,0x00555555, +0x00666666,0x00492492,0x0071c71c,0x00444444, +0x00421084,0x00410410,0x00408102,0x00404040, +0x00402010,0x00401004,0x00400801,0x00400400, +0x00400200,0x00400100,0x00400080,0x00400040, +0x00400000,0x00400000,0x00200000,0x00400000, +0x00100000,0x00080000,0x00040000,0x00020000, +0x00010000,0x00008000,0x00004000,0x00002000, +0x00001000,0x00000800,0x00000400,0x00000200, +0x00000100,0x0003588d,0x0002b15e,0x0002056d, +0x00015600,0x0000a329,0xffffeed9,0xffff3960, +0xfffe8423,0xfffdd11c,0xfffd2048,0xfffc7353, +0xfffbcb6f,0xfffb29a6,0xfffa8f15,0x000494ae, +0x0003f991,0x00032dd1,0xfffd2d8f,0x0001eb47, +0xfffe9968,0x00009af6,0x000011de,0xffff4335, +0x00018d69,0xfffdecd4,0x000302f8,0xfffca0d7, +0x0004683d,0xfffb67f8,0x0005b36d,0x00045963, +0xfffbd51e,0x00030062,0xfffd0dee,0x0001d046, +0xfffe8a0a,0x00009258,0x000012b1,0xffff4d9e, +0x00019ec3,0xfffe0a44,0x0003245a,0xfffcd082, +0x000498f0,0xfffba919,0x0005f304,0x00041bf4, +0xfffba72a,0x0002d19e,0xfffcf060,0x0001b407, +0xfffe7c08,0x0000894a,0x0000138d,0xffff58ac, +0x0001afaf,0xfffe28fe,0x000343bf,0xfffd026f, +0x0004c6f6,0xfffbed06,0x00062e61,0x0003dc0e, +0xfffb7bf1,0x0002a17f,0xfffcd522,0x000196a0, +0xfffe6e70,0x00007ff6,0x00001439,0xffff63f6, +0x0001beb3,0xfffe4882,0x0003616d,0xfffd361b, +0x0004f1cf,0xfffc332a,0x0006658f,0x00039943, +0xfffb52c0,0x00026ec7,0xfffcbb94,0x0001789f, +0xfffe6160,0x00007677,0x000014d4,0xffff6f74, +0x0001cc9b,0xfffe694f,0x00037cbf,0xfffd6b41, +0x000519c2,0xfffc7baf,0x00069971,0x00035486, +0xfffb2d0c,0x00023ad8,0xfffca3ee,0x00015989, +0xfffe55af,0x00006ca7,0x00001570,0xffff7b71, +0x0001d9cb,0xfffe8b46,0x0003959e,0xfffda1fe, +0x00053ee6,0xfffcc6b4,0x0006c950,0x00030e08, +0xfffb0a7a,0x0002061e,0xfffc8ec0,0x00013911, +0xfffe4b1d,0x00006278,0x000015e8,0xffff87b6, +0x0001e577,0xfffeadd6,0x0003acc2,0xfffdda34, +0x00056059,0xfffd136d,0x0006f4b5,0x0002c562, +0xfffaea7c,0x0001cfa6,0xfffc7b14,0x0001182b, +0xfffe4159,0x00005817,0x0000165c,0xffff9417, +0x0001f00f,0xfffed14c,0x0003c199,0xfffe13f6, +0x00057e83,0xfffd61cd,0x00071ba1,0x00027ab5, +0xfffacdc3,0x00019833,0xfffc6989,0x0000f6ca, +0xfffe38da,0x00004d9d,0x000016ef,0xffffa103, +0x0001f98f,0xfffef5c0,0x0003d3d1,0xfffe4f00, +0x0005998c,0xfffdb21e,0x00073e77,0x00022e75, +0xfffab482,0x00015fd1,0xfffc5b13,0x0000d45d, +0xfffe318f,0x000042ed,0x0000176b,0xffffae8f, +0x0002018f,0xffff1a91,0x0003e40c,0xfffe8af2, +0x0005b0ca,0xfffe03b8,0x00075d14,0x0001e141, +0xfffa9e9b,0x0001262a,0xfffc4e31,0x0000b1af, +0xfffe2b26,0x00003805,0x000017b1,0xffffbc21, +0x000208b8,0xffff3fb6,0x0003f1d7,0xfffec7af, +0x0005c4c5,0xfffe5654,0x0007768a,0x000192fe, +0xfffa8bb0,0x0000ec3f,0xfffc4365,0x00008ec9, +0xfffe25f0,0x00002d05,0x000017ec,0xffffc984, +0x00020ec6,0xffff658d,0x0003fcba,0xffff0500, +0x0005d576,0xfffeaa37,0x00078bc6,0x00014367, +0xfffa7bec,0x0000b1f4,0xfffc3b82,0x00006b06, +0xfffe2201,0x000021eb,0x00001823,0xffffd704, +0x0002132a,0xffff8be7,0x00040534,0xffff4315, +0x0005e22e,0xfffeff0a,0x00079ce3,0x0000f33f, +0xfffa6fc9,0x000076ca,0xfffc3558,0x00004762, +0xfffe1ef3,0x000016a1,0x0000183f,0xffffe4a6, +0x00021664,0xffffb27d,0x00040b7b,0xffff81e5, +0x0005eb4e,0xffff5475,0x0007a857,0x0000a2cb, +0xfffa671b,0x00003b64,0xfffc31e2,0x00002416, +0xfffe1ce1,0x00000b46,0x00001850,0xfffff24d, +0x00021855,0xffffd93a,0x00040f75,0xffffc0e6, +0x0005f0e3,0xffffaa3e,0x0007af45,0x0000519f, +0xfffa6218,0x0003f991,0x0003588d,0x0002b15e, +0x0002056d,0x00015600,0x0000a329,0xffffeed9, +0xffff3960,0xfffe8423,0xfffdd11c,0xfffd2048, +0xfffc7353,0xfffbcb6f,0xfffb29a6,0xfffa8f15, +0x000494ae,0x0003c6b0,0xfffc7e8b,0x00028ef6, +0xfffde181,0x000144eb,0xffff5500,0xffffefb9, +0x0000d01d,0xfffe9755,0x000249a4,0xfffd453c, +0x0003b80e,0xfffc01aa,0x000511d6,0xfffad527, +0xfffb334e,0x0003916c,0xfffc5778,0x00026a92, +0xfffdc9f5,0x00013314,0xffff4d99,0xfffff0b6, +0x0000d911,0xfffeab80,0x00026369,0xfffd6c0a, +0x0003e17f,0xfffc39d8,0x000549df,0xfffb1eb2, +0xfffafe6c,0x00035929,0xfffc3321,0x000244a6, +0xfffdb402,0x00012035,0xffff46ac,0xfffff192, +0x0000e16a,0xfffebfe0,0x00027b3d,0xfffd9433, +0x0004087b,0xfffc74b7,0x00057e8d,0xfffb6a81, +0xfffacc1c,0x00031fbe,0xfffc10df,0x00021e0c, +0xfffd9f6d,0x00010cb7,0xffff402e,0xfffff279, +0x0000e965,0xfffed574,0x00029159,0xfffdbdc4, +0x00042c4c,0xfffcb1e7,0x0005b02d,0xfffbb942, +0xfffa9d38,0x0002e44a,0xfffbf0fd,0x0001f5b4, +0xfffd8c38,0x0000f8b1,0xffff3a21,0xfffff391, +0x0000f0e6,0xfffeec44,0x0002a642,0xfffde90e, +0x00044e32,0xfffcf0fb,0x0005de46,0xfffc0b18, +0xfffa71d1,0x0002a659,0xfffbd3de,0x0001cb90, +0xfffd7a97,0x0000e403,0xffff3490,0xfffff49c, +0x0000f7a8,0xffff0340,0x0002b95f,0xfffe1573, +0x00046dbe,0xfffd3284,0x00060888,0xfffc5f51, +0xfffa4996,0x00026786,0xfffbb8df,0x0001a0e1, +0xfffd6a4e,0x0000ced2,0xffff2f75,0xfffff593, +0x0000fdbe,0xffff1a53,0x0002ca87,0xfffe42f5, +0x0004898a,0xfffd7563,0x00062f0b,0xfffcb5de, +0xfffa2508,0x00022713,0xfffba0bf,0x0001754a, +0xfffd5b5f,0x0000b92c,0xffff2acd,0xfffff6b0, +0x0001034f,0xffff3241,0x0002da5c,0xfffe71c6, +0x0004a341,0xfffdb946,0x000651e8,0xfffd0e37, +0xfffa0402,0x0001e4d4,0xfffb8b9c,0x00014898, +0xfffd4e7d,0x0000a304,0xffff26b7,0xfffff7e1, +0x00010846,0xffff4b34,0x0002e897,0xfffea13f, +0x0004ba63,0xfffdff2d,0x00067115,0xfffd6839, +0xfff9e680,0x0001a1fa,0xfffb789e,0x00011b2e, +0xfffd43a4,0x00008c6e,0xffff2341,0xfffff8fd, +0x00010c9c,0xffff6469,0x0002f48f,0xfffed1a4, +0x0004cd6a,0xfffe4608,0x00068c1b,0xfffdc409, +0xfff9cd15,0x00015dfe,0xfffb68a0,0x0000ecee, +0xfffd3a2e,0x0000757d,0xffff204b,0xfffffa1e, +0x00011054,0xffff7da1,0x0002fe9c,0xffff033e, +0x0004de57,0xfffe8dc6,0x0006a2d5,0xfffe213e, +0xfff9b77d,0x000118d3,0xfffb5bde,0x0000be25, +0xfffd3224,0x00005e52,0xffff1dc1,0xfffffb4b, +0x00011353,0xffff9740,0x00030748,0xffff351c, +0x0004ec95,0xfffed755,0x0006b5b4,0xfffe7fc6, +0xfff9a599,0x0000d334,0xfffb519f,0x00008f08, +0xfffd2bbf,0x00004704,0xffff1bc1,0xfffffc71, +0x00011598,0xffffb135,0x00030e43,0xffff6720, +0x0004f6f3,0xffff2119,0x0006c46e,0xfffedf38, +0xfff997c7,0x00008d13,0xfffb4a55,0x00005fa5, +0xfffd273b,0x00002f76,0xffff1a63,0xfffffda0, +0x00011744,0xffffcb67,0x000312ff,0xffff99cf, +0x0004ff0c,0xffff6a9c,0x0006cebd,0xffff3f0a, +0xfff98dbe,0x00004691,0xfffb4620,0x00003010, +0xfffd24fc,0x000017b5,0xffff199d,0xfffffed8, +0x0001185a,0xffffe5c6,0x0003157e,0xffffcce3, +0x000503ae,0xffffb515,0x0006d537,0xffff9f5a, +0xfff98767,0xfffb44b0,0xfffc3131,0xfffd2475, +0xfffe1c28,0xffff195d,0x00001859,0x000118bd, +0x000218df,0x0003163a,0x000410e0,0x000504a7, +0x0005f2b3,0x0006d796,0x0007b1fe,0xfff98537, +0xfffa609b,0xfffc7e8b,0x00028ef6,0xfffde181, +0x000144eb,0xffff5500,0xffffefb9,0x0000d01d, +0xfffe9755,0x000249a4,0xfffd453c,0x0003b80e, +0xfffc01aa,0x000511d6,0xfffad527,0xfffb334e, +0x0003c6b0,0xfffc5778,0x00026a92,0xfffdc9f5, +0x00013314,0xffff4d99,0xfffff0b6,0x0000d911, +0xfffeab80,0x00026369,0xfffd6c0a,0x0003e17f, +0xfffc39d8,0x000549df,0xfffb1eb2,0xfffafe6c, +0x0003916c,0xfffc3321,0x000244a6,0xfffdb402, +0x00012035,0xffff46ac,0xfffff192,0x0000e16a, +0xfffebfe0,0x00027b3d,0xfffd9433,0x0004087b, +0xfffc74b7,0x00057e8d,0xfffb6a81,0xfffacc1c, +0x00035929,0xfffc10df,0x00021e0c,0xfffd9f6d, +0x00010cb7,0xffff402e,0xfffff279,0x0000e965, +0xfffed574,0x00029159,0xfffdbdc4,0x00042c4c, +0xfffcb1e7,0x0005b02d,0xfffbb942,0xfffa9d38, +0x00031fbe,0xfffbf0fd,0x0001f5b4,0xfffd8c38, +0x0000f8b1,0xffff3a21,0xfffff391,0x0000f0e6, +0xfffeec44,0x0002a642,0xfffde90e,0x00044e32, +0xfffcf0fb,0x0005de46,0xfffc0b18,0xfffa71d1, +0x0002e44a,0xfffbd3de,0x0001cb90,0xfffd7a97, +0x0000e403,0xffff3490,0xfffff49c,0x0000f7a8, +0xffff0340,0x0002b95f,0xfffe1573,0x00046dbe, +0xfffd3284,0x00060888,0xfffc5f51,0xfffa4996, +0x0002a659,0xfffbb8df,0x0001a0e1,0xfffd6a4e, +0x0000ced2,0xffff2f75,0xfffff593,0x0000fdbe, +0xffff1a53,0x0002ca87,0xfffe42f5,0x0004898a, +0xfffd7563,0x00062f0b,0xfffcb5de,0xfffa2508, +0x00026786,0xfffba0bf,0x0001754a,0xfffd5b5f, +0x0000b92c,0xffff2acd,0xfffff6b0,0x0001034f, +0xffff3241,0x0002da5c,0xfffe71c6,0x0004a341, +0xfffdb946,0x000651e8,0xfffd0e37,0xfffa0402, +0x00022713,0xfffb8b9c,0x00014898,0xfffd4e7d, +0x0000a304,0xffff26b7,0xfffff7e1,0x00010846, +0xffff4b34,0x0002e897,0xfffea13f,0x0004ba63, +0xfffdff2d,0x00067115,0xfffd6839,0xfff9e680, +0x0001e4d4,0xfffb789e,0x00011b2e,0xfffd43a4, +0x00008c6e,0xffff2341,0xfffff8fd,0x00010c9c, +0xffff6469,0x0002f48f,0xfffed1a4,0x0004cd6a, +0xfffe4608,0x00068c1b,0xfffdc409,0xfff9cd15, +0x0001a1fa,0xfffb68a0,0x0000ecee,0xfffd3a2e, +0x0000757d,0xffff204b,0xfffffa1e,0x00011054, +0xffff7da1,0x0002fe9c,0xffff033e,0x0004de57, +0xfffe8dc6,0x0006a2d5,0xfffe213e,0xfff9b77d, +0x00015dfe,0xfffb5bde,0x0000be25,0xfffd3224, +0x00005e52,0xffff1dc1,0xfffffb4b,0x00011353, +0xffff9740,0x00030748,0xffff351c,0x0004ec95, +0xfffed755,0x0006b5b4,0xfffe7fc6,0xfff9a599, +0x000118d3,0xfffb519f,0x00008f08,0xfffd2bbf, +0x00004704,0xffff1bc1,0xfffffc71,0x00011598, +0xffffb135,0x00030e43,0xffff6720,0x0004f6f3, +0xffff2119,0x0006c46e,0xfffedf38,0xfff997c7, +0x0000d334,0xfffb4a55,0x00005fa5,0xfffd273b, +0x00002f76,0xffff1a63,0xfffffda0,0x00011744, +0xffffcb67,0x000312ff,0xffff99cf,0x0004ff0c, +0xffff6a9c,0x0006cebd,0xffff3f0a,0xfff98dbe, +0x00008d13,0xfffb4620,0x00003010,0xfffd24fc, +0x000017b5,0xffff199d,0xfffffed8,0x0001185a, +0xffffe5c6,0x0003157e,0xffffcce3,0x000503ae, +0xffffb515,0x0006d537,0xffff9f5a,0xfff98767, +0x00004691,0xfffa609b,0xfffb44b0,0xfffc3131, +0xfffd2475,0xfffe1c28,0xffff195d,0x00001859, +0x000118bd,0x000218df,0x0003163a,0x000410e0, +0x000504a7,0x0005f2b3,0x0006d796,0x0007b1fe, +0xfff98537,0xfffbd51e,0x00032dd1,0xfffd2d8f, +0x0001eb47,0xfffe9968,0x00009af6,0x000011de, +0xffff4335,0x00018d69,0xfffdecd4,0x000302f8, +0xfffca0d7,0x0004683d,0xfffb67f8,0x0005b36d, +0x00045963,0xfffba72a,0x00030062,0xfffd0dee, +0x0001d046,0xfffe8a0a,0x00009258,0x000012b1, +0xffff4d9e,0x00019ec3,0xfffe0a44,0x0003245a, +0xfffcd082,0x000498f0,0xfffba919,0x0005f304, +0x00041bf4,0xfffb7bf1,0x0002d19e,0xfffcf060, +0x0001b407,0xfffe7c08,0x0000894a,0x0000138d, +0xffff58ac,0x0001afaf,0xfffe28fe,0x000343bf, +0xfffd026f,0x0004c6f6,0xfffbed06,0x00062e61, +0x0003dc0e,0xfffb52c0,0x0002a17f,0xfffcd522, +0x000196a0,0xfffe6e70,0x00007ff6,0x00001439, +0xffff63f6,0x0001beb3,0xfffe4882,0x0003616d, +0xfffd361b,0x0004f1cf,0xfffc332a,0x0006658f, +0x00039943,0xfffb2d0c,0x00026ec7,0xfffcbb94, +0x0001789f,0xfffe6160,0x00007677,0x000014d4, +0xffff6f74,0x0001cc9b,0xfffe694f,0x00037cbf, +0xfffd6b41,0x000519c2,0xfffc7baf,0x00069971, +0x00035486,0xfffb0a7a,0x00023ad8,0xfffca3ee, +0x00015989,0xfffe55af,0x00006ca7,0x00001570, +0xffff7b71,0x0001d9cb,0xfffe8b46,0x0003959e, +0xfffda1fe,0x00053ee6,0xfffcc6b4,0x0006c950, +0x00030e08,0xfffaea7c,0x0002061e,0xfffc8ec0, +0x00013911,0xfffe4b1d,0x00006278,0x000015e8, +0xffff87b6,0x0001e577,0xfffeadd6,0x0003acc2, +0xfffdda34,0x00056059,0xfffd136d,0x0006f4b5, +0x0002c562,0xfffacdc3,0x0001cfa6,0xfffc7b14, +0x0001182b,0xfffe4159,0x00005817,0x0000165c, +0xffff9417,0x0001f00f,0xfffed14c,0x0003c199, +0xfffe13f6,0x00057e83,0xfffd61cd,0x00071ba1, +0x00027ab5,0xfffab482,0x00019833,0xfffc6989, +0x0000f6ca,0xfffe38da,0x00004d9d,0x000016ef, +0xffffa103,0x0001f98f,0xfffef5c0,0x0003d3d1, +0xfffe4f00,0x0005998c,0xfffdb21e,0x00073e77, +0x00022e75,0xfffa9e9b,0x00015fd1,0xfffc5b13, +0x0000d45d,0xfffe318f,0x000042ed,0x0000176b, +0xffffae8f,0x0002018f,0xffff1a91,0x0003e40c, +0xfffe8af2,0x0005b0ca,0xfffe03b8,0x00075d14, +0x0001e141,0xfffa8bb0,0x0001262a,0xfffc4e31, +0x0000b1af,0xfffe2b26,0x00003805,0x000017b1, +0xffffbc21,0x000208b8,0xffff3fb6,0x0003f1d7, +0xfffec7af,0x0005c4c5,0xfffe5654,0x0007768a, +0x000192fe,0xfffa7bec,0x0000ec3f,0xfffc4365, +0x00008ec9,0xfffe25f0,0x00002d05,0x000017ec, +0xffffc984,0x00020ec6,0xffff658d,0x0003fcba, +0xffff0500,0x0005d576,0xfffeaa37,0x00078bc6, +0x00014367,0xfffa6fc9,0x0000b1f4,0xfffc3b82, +0x00006b06,0xfffe2201,0x000021eb,0x00001823, +0xffffd704,0x0002132a,0xffff8be7,0x00040534, +0xffff4315,0x0005e22e,0xfffeff0a,0x00079ce3, +0x0000f33f,0xfffa671b,0x000076ca,0xfffc3558, +0x00004762,0xfffe1ef3,0x000016a1,0x0000183f, +0xffffe4a6,0x00021664,0xffffb27d,0x00040b7b, +0xffff81e5,0x0005eb4e,0xffff5475,0x0007a857, +0x0000a2cb,0xfffa6218,0x00003b64,0xfffc31e2, +0x00002416,0xfffe1ce1,0x00000b46,0x00001850, +0xfffff24d,0x00021855,0xffffd93a,0x00040f75, +0xffffc0e6,0x0005f0e3,0xffffaa3e,0x0007af45, +0x0000519f,0x00030000,0x000f0007,0x003f001f, +0x00ff007f,0x03ff01ff,0x0fff07ff,0x3fff1fff, +0xffff7fff,0x00030000,0x00070005,0x000f0009, +0x003f001f,0x00ff007f,0x03ff01ff,0x0fff07ff, +0xffff1fff,0x00030000,0x00070005,0x000f0009, +0xffff001f,0x00030000,0xffff0005,0x04030504, +0x08070605,0x0c0b0a09,0x100f0e0d,0x03070504, +0x0605040a,0x0a090807,0x100d0c0b,0x03070503, +0x1005040a,0x10070502,0x03030100,0x03030303, +0x03030303,0x03030303,0x03010100,0x03030301, +0x03030303,0x03030303,0x03010100,0x03030301, +0x03010100,0x04020000,0x08070605,0x0c0b0a09, +0x100f0e0d,0x02010000,0x06050403,0x0a090807, +0x100d0c0b,0x02010000,0x10050403,0x10010000, +0x00030000,0x00090005,0x001f000f,0x007f003f, +0x01ff00ff,0x07ff03ff,0x1fff0fff,0x7fff3fff, +0x00030000,0x00090005,0x001f000f,0x007f003f, +0x0a070504,0x07060504,0x0b0a0908,0x0f0e0d0c, +0x0a070503,0x07060504,0x01010100,0x03030303, +0x03030303,0x03030303,0x01010100,0x03030303, +0x03010000,0x07060504,0x0b0a0908,0x0f0e0d0c, +0x03010000,0x07060504,0x00555555,0x002aaaab, +0x00249249,0x00124925,0x00111111,0x00088889, +0x00084210,0x00421084,0x00041041,0x00020821, +0x00020408,0x00081020,0x00010101,0x00008081, +0x00008040,0x00100804,0x00004010,0x00020080, +0x00002004,0x00004008,0x00001001,0x00000801, +0x00000800,0x00200100,0x00000400,0x00080020, +0x00000200,0x00020004,0x00200000,0x00600040, +0x00a00080,0x00e000c0,0x01200100,0x01600140, +0x01a00180,0x000001c0,0x00300020,0x00400038, +0x00600050,0x00800070,0x00c000a0,0x010000e0, +0x01800140,0x00200000,0x00300028,0x00400038, +0x00600050,0x00800070,0x00c000a0,0x010000e0, +0x00000140,0x00900000,0x00fc00d8,0x01680120, +0x01f801b0,0x02d00240,0x03f00360,0x05a00480, +0x000006c0,0x00680000,0x00b6009c,0x010500d0, +0x016d0139,0x020a01a1,0x02db0272,0x04140343, +0x000004e5,0x006c0000,0x00bd00a2,0x010e00d8, +0x017a0144,0x006301b0,0x013b00cf,0x00c601a7, +0x0000019e,0x00600000,0x00a80090,0x00f000c0, +0x01500120,0x01e00180,0x02a00240,0x03c00300, +0x00000480,0x10000000,0x10101010,0x20101010, +0x20202020,0x20202020,0x28202020,0x28282828, +0x00002828,0x10100000,0x10101010,0x10101010, +0x00000000,0x00000000,0x00000000,0x00000000, +0xcbcecdc4,0xcfcac9c8,0xc3c6c5cc,0xc7c2c1c0, +0x1b1e1d14,0x1f1a1918,0x1316151c,0x17121110, +0x2b2e2d24,0x2f2a2928,0x2326252c,0x27222120, +0x3b3e3d34,0x3f3a3938,0x3336353c,0x37323130, +0x0b0e0d04,0x0f0a0908,0x0306050c,0x07020100, +0xdbdeddd4,0xdfdad9d8,0xd3d6d5dc,0xd7d2d1d0, +0xebeeede4,0xefeae9e8,0xe3e6e5ec,0xe7e2e1e0, +0xfbfefdf4,0xfffaf9f8,0xf3f6f5fc,0xf7f2f1f0, +0x4b4e4d44,0x4f4a4948,0x4346454c,0x47424140, +0x9b9e9d94,0x9f9a9998,0x9396959c,0x97929190, +0xabaeada4,0xafaaa9a8,0xa3a6a5ac,0xa7a2a1a0, +0xbbbebdb4,0xbfbab9b8,0xb3b6b5bc,0xb7b2b1b0, +0x8b8e8d84,0x8f8a8988,0x8386858c,0x87828180, +0x5b5e5d54,0x5f5a5958,0x5356555c,0x57525150, +0x6b6e6d64,0x6f6a6968,0x6366656c,0x67626160, +0x7b7e7d74,0x7f7a7978,0x7376757c,0x77727170, +0x341424c4,0x3e1e2ece,0x3d1d2dcd,0x3b1b2bcb, +0xb494a444,0xbe9eae4e,0xbd9dad4d,0xbb9bab4b, +0xf4d4e404,0xfedeee0e,0xfddded0d,0xfbdbeb0b, +0x74546484,0x7e5e6e8e,0x7d5d6d8d,0x7b5b6b8b, +0x3c1c2ccc,0x361626c6,0x351525c5,0x331323c3, +0xbc9cac4c,0xb696a646,0xb595a545,0xb393a343, +0xfcdcec0c,0xf6d6e606,0xf5d5e505,0xf3d3e303, +0x7c5c6c8c,0x76566686,0x75556585,0x73536383, +0x381828c8,0x3a1a2aca,0x391929c9,0x3f1f2fcf, +0xb898a848,0xba9aaa4a,0xb999a949,0xbf9faf4f, +0xf8d8e808,0xfadaea0a,0xf9d9e909,0xffdfef0f, +0x78586888,0x7a5a6a8a,0x79596989,0x7f5f6f8f, +0x301020c0,0x321222c2,0x311121c1,0x371727c7, +0xb090a040,0xb292a242,0xb191a141,0xb797a747, +0xf0d0e000,0xf2d2e202,0xf1d1e101,0xf7d7e707, +0x70506080,0x72526282,0x71516181,0x77576787, +0x05040100,0x15141110,0x25242120,0x35343130, +0x85848180,0x95949190,0xa5a4a1a0,0xb5b4b1b0, +0xc0408000,0xe060a020,0xd0509010,0xf070b030, +0xc8488808,0xe868a828,0xd8589818,0xf878b838, +0xc4448404,0xe464a424,0xd4549414,0xf474b434, +0xcc4c8c0c,0xec6cac2c,0xdc5c9c1c,0xfc7cbc3c, +0xc2428202,0xe262a222,0xd2529212,0xf272b232, +0xca4a8a0a,0xea6aaa2a,0xda5a9a1a,0xfa7aba3a, +0xc6468606,0xe666a626,0xd6569616,0xf676b636, +0xce4e8e0e,0xee6eae2e,0xde5e9e1e,0xfe7ebe3e, +0xc1418101,0xe161a121,0xd1519111,0xf171b131, +0xc9498909,0xe969a929,0xd9599919,0xf979b939, +0xc5458505,0xe565a525,0xd5559515,0xf575b535, +0xcd4d8d0d,0xed6dad2d,0xdd5d9d1d,0xfd7dbd3d, +0xc3438303,0xe363a323,0xd3539313,0xf373b333, +0xcb4b8b0b,0xeb6bab2b,0xdb5b9b1b,0xfb7bbb3b, +0xc7478707,0xe767a727,0xd7579717,0xf777b737, +0xcf4f8f0f,0xef6faf2f,0xdf5f9f1f,0xff7fbf3f, +0x1045a3e2,0x000000f4,0x263b7333,0x766b2363, +0x2b367e3e,0x7b662e6e,0x06db93d3,0x964b0343, +0x0bd69ede,0x9b460e4e,0x825f1757,0x12cf87c7, +0x8f521a5a,0x1fc28aca,0x00d199d9,0x90410949, +0x01d098d8,0x91400848,0x24357d3d,0x74652d6d, +0x25347c3c,0x75642c6c,0x04d59ddd,0x94450d4d, +0x05d49cdc,0x95440c4c,0x80511959,0x10c189c9, +0x81501858,0x11c088c8,0x02df97d7,0x924f0747, +0x0fd29ada,0x9f420a4a,0x865b1353,0x16cb83c3, +0x8b561e5e,0x1bc68ece,0xa6bbf3b3,0xf6eba3e3, +0xabb6febe,0xfbe6aeee,0x223f7737,0x726f2767, +0x2f327a3a,0x7f622a6a,0xa0b1f9b9,0xf0e1a9e9, +0xa1b0f8b8,0xf1e0a8e8,0x84551d5d,0x14c58dcd, +0x85541c5c,0x15c48ccc,0xa4b5fdbd,0xf4e5aded, +0xa5b4fcbc,0xf5e4acec,0x20317939,0x70612969, +0x21307838,0x71602868,0xa2bff7b7,0xf2efa7e7, +0xafb2faba,0xffe2aaea,0x00000000,0x00000000, + +}; + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/ls220/mpgi2s.h linux.19rc3-ac4/drivers/media/video/ls220/mpgi2s.h --- linux.19rc3/drivers/media/video/ls220/mpgi2s.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/ls220/mpgi2s.h 2002-07-29 13:58:41.000000000 +0100 @@ -0,0 +1,1611 @@ +static u32 MPGI2SUcode1f1800[] = { +0x820f001f,0x802f001f,0x81df0000,0xb500000c, +0x00ffb81e,0x00000000,0x00000000,0x00000000, +0x00ffb81e,0x00000000,0x00000000,0x00000000, +0xb5000c0f,0x00000000,0x00000000,0x00000000, +0x80070800,0x001f6047,0x8013001f,0x90208000, +0x003fb174,0x803effe8,0x803effec,0x9020fa00, +0x803effd0,0x803effdc,0x803effd8,0x9020fe00, +0x803effd4,0x805bff7c,0x802500d4,0x94020080, +0xb0000000,0xb4200023,0x8013ffcf,0x9800cfff, +0x80730030,0x98631000,0x94420007,0xb0020002, +0xb4200005,0x8013ffc7,0x9800c7ff,0x80730038, +0x98631000,0xb5000006,0xb0020001,0xb4200004, +0x8013ffcf,0x9800cfff,0x80730030,0x98631000, +0x1421b800,0x1821b803,0x802600d4,0x8033001f, +0x98210000,0x802600a2,0x8033001f,0x98210300, +0x802600a3,0x80270225,0x80530001,0x98420100, +0x1821b802,0x80530200,0x98420000,0x804600a6, +0xb500001d,0x805bff7c,0x8013ffcf,0x9800cfff, +0x80730030,0x98632000,0x94420007,0xb0020002, +0xb4200005,0x8013ffc7,0x9800c7ff,0x80730038, +0x98632800,0xb5000006,0xb0020001,0xb4200004, +0x8013ffcf,0x9800cfff,0x80730030,0x98632000, +0x1421b800,0x1821b803,0x802600d4,0x8033001f, +0x98210000,0x802600a2,0x8033001f,0x98210600, +0x802600a3,0x80270eff,0x802600a1,0x80270002, +0x803eff84,0x80070000,0x801effc0,0x801effc4, +0x801effc8,0x801effcc,0x801eff88,0x80770000, +0x8057ffff,0x80170080,0x80070000,0xb6003f02, +0xb6002001,0x001fa020,0x8007ffff,0x801eff84, +0x80070001,0x001f25dc,0x001f20b1,0x80070000, +0x001f6046,0x001fb17c,0x001fb17d,0x80070000, +0x801e78d0,0x98004000,0x001f62ea,0x80070100, +0x801efff0,0x81df0004,0x00000000,0x00000000, +0x801bfff0,0x00000000,0x940000ff,0xb0000000, +0xb420005b,0x003f42ea,0x94010010,0xb0000000, +0xb400fff7,0x003f05dc,0xb0010001,0xb4200034, +0x803bffe8,0x801bffec,0x00000000,0x3001b800, +0xb4600001,0x90214000,0x0421b800,0xb0010800, +0xb460000d,0x80050086,0x005f902e,0xb0020000, +0xb4200002,0x001fb02e,0xb5000006,0x0420b802, +0xb0010930,0xb4a0ffe2,0x80070000,0x001fb02e, +0x83e40162,0xb500ffde,0x83e40129,0x80070000, +0x001fb02e,0x001f42ea,0x9400000f,0xb0000000, +0xb4000010,0x9400fff0,0x001f62ea,0x003f9174, +0x9421ffff,0x90210004,0xb001c000,0xb4800002, +0x8421c000,0x90218000,0x8013001f,0x1821b800, +0x003fb174,0x003f917c,0x90210004,0x003fb17c, +0x83e4014a,0x8013001f,0x83e71b0c,0x1bffb800, +0x003f9179,0x1821b800,0x00ffb801,0xb5000008, +0x80270000,0x003f25dc,0x8013001f,0x83e71b30, +0x1bffb800,0x003f917a,0x1821b800,0x00ffb801, +0x80070000,0x001f20b1,0x001f42ea,0x9420000f, +0xb0010000,0xb4200003,0x98000800,0x001f62ea, +0xb500ffaf,0x9400fff0,0x001f62ea,0x80270000, +0x8057ffff,0x80770000,0x80171980,0x81df0000, +0x00000000,0x00000000,0xb6000602,0xb6002001, +0x001fa021,0x81df0004,0xb500ffa1,0xb500ffa0, +0x803bffc0,0x805bffc4,0x807bffc8,0x809bffcc, +0x5828b801,0x5cb8b802,0x1821b805,0x5848b802, +0x5cb8b803,0x1842b805,0x5868b803,0x5cb8b804, +0x1863b805,0x5888b804,0x1884b800,0x803effc0, +0x805effc4,0x807effc8,0x809effcc,0x003f42ea, +0xb0000086,0xb4400079,0xb0000084,0xb4000049, +0xb0000085,0xb4000063,0xb0000086,0xb400006c, +0xb0000081,0xb4000005,0xb0000082,0xb4000003, +0xb0000080,0xb4000001,0xb5000069,0x8013007f, +0x9800ffff,0x001fb02d,0x80070000,0x001fb17c, +0x8013001f,0x9040fa00,0x805effd0,0x805effdc, +0x805effd8,0x9040fe00,0x805effd4,0x9040c000, +0x805effe4,0x90008000,0x801effe0,0x001fb174, +0x801effe8,0x801effec,0x80078000,0x801e78d4, +0x80070000,0x001fb17c,0x001fb17d,0x001fb02e, +0x83e400e6,0x8013001f,0x98000000,0x800600a2, +0x8013001f,0x98000600,0x800600a3,0x805bff7c, +0x80070eff,0x94420080,0xb0020080,0xb420000d, +0x8013001f,0x98000000,0x800600a2,0x8013001f, +0x98000300,0x800600a3,0x80070225,0x80530001, +0x98420100,0x1800b802,0x80530200,0x98420000, +0x804600a6,0x800600a1,0x80050080,0x98000022, +0x80060080,0x80072080,0x001fb179,0x80074618, +0x001fb17a,0x80070001,0x001f25dc,0x98214000, +0xb5000029,0x8047ffff,0x805eff84,0x805bff88, +0x00000000,0xb0020001,0xb4200002,0x80470000, +0x805eff88,0x805bff7c,0x80070eff,0x94420080, +0xb0020080,0xb4200007,0x80070225,0x80530001, +0x98420100,0x1800b802,0x80530200,0x98420000, +0x804600a6,0x800600a1,0x80070001,0x800600a0, +0x9421efff,0x98210010,0xb500000f,0x80070000, +0x001fb17c,0x80070001,0x001f25dc,0x83e400a3, +0x80050081,0x80330008,0x98210000,0x1800b801, +0x80060081,0x003f42ea,0x9421ffef,0xb5000002, +0x98211000,0x9421ffef,0x83e40098,0x003f62ea, +0x80070100,0x801efff0,0xb500ff11,0xb000008b, +0xb400001c,0xb0000087,0xb400ffe8,0xb0000088, +0xb4000023,0xb000008a,0xb4000024,0xb000008c, +0xb4000019,0xb000008e,0xb4000014,0xb000008d, +0xb400001d,0xb0000089,0xb400001f,0xb00000a0, +0xb4000021,0xb00000a1,0xb4000022,0xb00000a2, +0xb400002f,0xb00000a3,0xb4000027,0xb00000a4, +0xb4000031,0xb00000a5,0xb4000035,0xb00000a6, +0xb4000039,0x803efff8,0xb500ffdd,0x80070000, +0x001fb17e,0xb500ffda,0x803bffb0,0x00000000, +0x003fb02d,0xb500ffd6,0x98210020,0xb500ffd2, +0x9421ffdf,0xb500ffd0,0xb500ffd1,0x80270351, +0x803efff8,0xb500ffce,0x803bff80,0x00000000, +0x003f62ef,0xb500ffca,0x003f917b,0x803efff8, +0xb500ffc7,0x80270000,0x8047fef0,0x003eb802, +0x90420004,0x003eb802,0x90420004,0x003eb802, +0x90420004,0x003eb802,0x81df0000,0x00000000, +0x00000000,0x83640db9,0x81df0004,0xb500ffb8, +0x81df0000,0x00000000,0x00000000,0x83640d63, +0x81df0004,0xb500ffb2,0x81df0000,0x00000000, +0x00000000,0x83640d1e,0x81df0004,0xb500ffac, +0x81df0000,0x00000000,0x00000000,0x83440c81, +0x81df0004,0xb500ffa6,0x81df0000,0x00000000, +0x00000000,0x83440c66,0x81df0004,0xb500ffa0, +0x817bffe8,0x815b78d4,0x00000000,0x956bffff, +0x300bb80a,0xb4600001,0x916b4000,0x056bb80a, +0xb00b0080,0xb4a0002a,0x80af001f,0x808f0000, +0x806f0000,0x81b300ff,0x8057ffff,0x5d67b80b, +0x5d42b80a,0x81df0000,0x00000000,0x00000000, +0xb62b001c,0xb00a3000,0xb4800001,0x854a1000, +0x80cf0400,0x015fb178,0x5942b80a,0x01cfb80a, +0x015f9178,0xb520ffff,0x80171000,0xb600200a, +0x01ff8000,0x5a18b80f,0x5a28b80f,0x1631b80d, +0x5e48b80f,0x9652ff00,0x5e78b80f,0x1a73b810, +0x1a73b811,0x1813a032,0x80cf0400,0x015fb178, +0x5942b80a,0x01afb80a,0x015f9178,0xb520ffff, +0x914a0020,0x81df0004,0x5942b80a,0x815e78d4, +0x00000000,0x00000000,0x00ffb81f,0x81df0000, +0x80070000,0x80470000,0x81171800,0xb6002003, +0xb6003002,0x001eb802,0x90420004,0xb6002003, +0x011fa020,0x011fa020,0x011fa020,0x81df0004, +0x00ffb81f,0x80070000,0x80478000,0x81df0000, +0x00000000,0x00000000,0xb6002003,0xb6008002, +0x001eb802,0x90420004,0x81df0004,0x00ffb81f, +0x015f42ea,0x944a4000,0xb0024000,0xb4200081, +0x954abfff,0x015f62ea,0x808f0000,0x80ef007c, +0x80171000,0x80971400,0x80270000,0xb6001003, +0xb6002002,0x001fa021,0x009fa021,0x80a76604, +0x80271400,0x81df0000,0x00000000,0x00000000, +0xb6001004,0x01efb801,0x01afb805,0xb520ffff, +0x90a50080,0x81df0004,0x80a76e04,0x80271400, +0x81df0000,0x00000000,0x00000000,0xb6001004, +0x01efb801,0x01afb805,0xb520ffff,0x90a50080, +0x81df0004,0x806f001f,0x80af001f,0x80276400, +0x5c22b801,0x806701e1,0x00cfb803,0x003fb178, +0x5822b801,0x01cfb801,0x003f9178,0x0047b86f, +0xb0020001,0xb4c0fffd,0x80275c00,0x5c22b801, +0x80670200,0x81df0000,0x00000000,0x00000000, +0xb600100a,0x00cfb803,0x003fb178,0x5822b801, +0x01cfb801,0x003f9178,0x0047b86f,0xb0020001, +0xb4c0fffd,0x90210020,0x90630020,0x81df0004, +0x808f0000,0x806f001f,0x80af001f,0x8027647c, +0x5c22b801,0x8067017e,0x81df0000,0x00000000, +0x00000000,0xb600020a,0x00cfb803,0x003fb178, +0x5822b801,0x01cfb801,0x003f9178,0x0047b86f, +0xb0020001,0xb4c0fffd,0x90210020,0x90630020, +0x81df0004,0x806f0010,0x80af0010,0x8027657c, +0x5c22b801,0x806701be,0x00cfb803,0x003fb178, +0x5822b801,0x01cfb801,0x003f9178,0x0047b86f, +0xb0020001,0xb4c0fffd,0x802765c0,0x5c22b801, +0x806701cf,0x00cfb803,0x003fb178,0x5822b801, +0x01cfb801,0x003f9178,0x0047b86f,0xb0020001, +0xb4c0fffd,0x80276000,0x005fb801,0x8033001f, +0x98218000,0x803effe0,0x90214000,0x803effe4, +0x8193001f,0x998c8000,0x019fb174,0x83270000, +0x003fb819,0x003f9174,0x5823b801,0x83338000, +0x1b39b801,0x003fb819,0x00000000,0x00000000, +0x81550000,0x0187b860,0x858c0040,0x81b380fc, +0x99ad0000,0x300cb80d,0xb4600003,0x81b30002, +0x99ad0000,0x118cb80d,0x003fb80c,0x00000000, +0x00000000,0x81550000,0x8257ffff,0x82d7ffff, +0x8357ffff,0x81672000,0x83440191,0xb00a0001, +0xb4000141,0x0187b860,0x858c0010,0x5988b80c, +0x5d8bb80c,0x958cffff,0xb00cc000,0xb4800002, +0x858cc000,0x918c8000,0x81b3001f,0x198cb80d, +0x801bffec,0x00000000,0x819effec,0x819e78d8, +0x019fb174,0x05acb800,0x300cb800,0xb4600001, +0x91ad4000,0x001f917c,0x1000b80d,0x001fb17c, +0x8344019c,0xb00a0000,0xb4200127,0x015f0081, +0xb00a0002,0xb4200124,0x037f0082,0xb01b0000, +0xb400001e,0x0367b860,0x5b68b81b,0x5f68b81b, +0x017f4047,0x916b0010,0x5963b80b,0x83440168, +0x801bff84,0xb00a0001,0xb400000b,0xb00b00c0, +0xb460fffa,0x803f0000,0x80138000,0x1b7bb800, +0x003fb81b,0x00000000,0x00000000,0x80150000, +0x801bff84,0xb5000009,0x803f0000,0x80138000, +0x1b7bb800,0x003fb81b,0x00000000,0x00000000, +0x80150000,0x801bff84,0xb5000103,0x801bff84, +0x003f0084,0x3000b801,0x803eff84,0xb4000073, +0x801bff7c,0x00000000,0x94800080,0xb0040080, +0xb4200036,0x94800007,0x80730200,0xb0010002, +0xb420000e,0x80270265,0xb0040001,0xb4200003, +0x80130030,0x98000000,0xb5000006,0x80130030, +0x98000000,0xb0040000,0xb4000002,0x80130038, +0x98000000,0x98630060,0xb500001f,0xb0010000, +0xb420000e,0x80270225,0xb0040001,0xb4200003, +0x80130030,0x98001000,0xb5000006,0x80130030, +0x98001000,0xb0040000,0xb4000002,0x80130038, +0x98001000,0x98630000,0xb500000f,0xb0010001, +0xb420004a,0x80270225,0xb0040001,0xb4200003, +0x80130030,0x98002000,0xb5000006,0x80130030, +0x98000000,0xb0040000,0xb4000002,0x80130038, +0x98000000,0x98630040,0x806600a6,0x80530001, +0x98420100,0x1821b802,0xb500002d,0x94800007, +0xb0010002,0xb420000d,0x80270eff,0xb0040001, +0xb4200003,0x80130030,0x98002000,0xb5000006, +0x80130030,0x98000000,0xb0040000,0xb4000002, +0x80130038,0x98000000,0xb500001d,0xb0010000, +0xb420000d,0x80270eff,0xb0040001,0xb4200003, +0x80130030,0x98002000,0xb5000006,0x80130030, +0x98002000,0xb0040000,0xb4000002,0x80130038, +0x98002800,0xb500000e,0xb0010001,0xb4200017, +0x80270eff,0xb0040001,0xb4200003,0x80130030, +0x98002000,0xb5000006,0x80130030,0x98002000, +0xb0040000,0xb4000002,0x80130038,0x98002800, +0x806500d4,0x8053ffcf,0x9842cfff,0xb0040002, +0xb4200002,0x8053ffc7,0x9842c7ff,0x802600a1, +0x1463b802,0x1863b800,0x806600d4,0x807bff7c, +0x00000000,0x94630080,0xb0030080,0xb420000b, +0x807bff88,0x00000000,0xb0030001,0xb4000007, +0x802500a1,0x80670001,0x807eff88,0x80530001, +0x98420100,0x1821b802,0x802600a1,0x81070000, +0x011f62e2,0x011f62e3,0x011f0082,0xb0080000, +0xb4200004,0x81150010,0x00000000,0x00000000, +0x011f62de,0x011f0081,0xb0080001,0xb4200026, +0x81070020,0x011f25c1,0x81070180,0x011f62e1, +0x8344023e,0x8344026a,0x011f0082,0xb0080000, +0xb4200004,0x834401bd,0x834401aa,0xb00a0000, +0xb4200061,0x80c70000,0x00df25cb,0x83440281, +0x8344064f,0x02ff05b9,0x82a70000,0x82870000, +0x83440407,0x92940001,0x3014b817,0xb480fffc, +0x834406ef,0x80270000,0x003f25dc,0x834407de, +0x003f05dc,0xb0010001,0xb4000003,0x80272694, +0x003fb17a,0x00ffb81f,0x80d3001f,0x8347266c, +0x1b5ab806,0xb500002d,0xb0080002,0x81470004, +0xb4200045,0x81070008,0x011f25c1,0x81070480, +0x011f62e1,0x8344029e,0x834402dc,0x011f0082, +0xb0080000,0xb4200004,0x834401aa,0x83440181, +0xb00a0000,0xb4200038,0x80c70000,0x00df25cb, +0x83440368,0x02df05cb,0x5ec2b816,0x8344066b, +0x02ff05b9,0x82a70000,0x82870000,0x834403dc, +0x92940001,0x3014b817,0xb480fffc,0x92b50001, +0xb0150003,0xb480fff8,0x834406c1,0x80270000, +0x003f25dc,0x834407b0,0x003f05dc,0xb0010001, +0xb4000003,0x8027274c,0x003fb17a,0x00ffb81f, +0x80d3001f,0x83472710,0x1b5ab806,0x80db78d8, +0x80fbffec,0x00000000,0x3006b807,0xb4200007, +0x00df05cb,0x90c60001,0x00df25cb,0xb006000c, +0xb4000002,0x035fb179,0x00ffb81f,0x80c70000, +0x00df25cb,0x80fb78dc,0x00000000,0x90e70001, +0xb00701b9,0xb4a00001,0x80e70001,0x80fe78dc, +0xb500feb0,0x802500a5,0x8153001f,0x3001b80a, +0xb420fffc,0x00ffb81f,0x001f42ea,0x1800b80a, +0x001f62ea,0x017f4047,0x5963b80b,0x0187b860, +0x118cb80b,0x81b380fe,0x99ad0000,0x300cb80d, +0xb4800003,0x81b30002,0x99ad0000,0x058cb80d, +0x003fb80c,0x00000000,0x00000000,0x81550000, +0x0187b860,0x5988b80c,0x5d8bb80c,0x958cffff, +0xb00cc000,0xb4800002,0x858cc000,0x918c8000, +0x81b3001f,0x198cb80d,0x801bffec,0x00000000, +0x819effec,0x019fb174,0x05acb800,0x300cb800, +0xb4600001,0x91ad4000,0x001f917c,0x1000b80d, +0x001fb17c,0x80171000,0x80971400,0x80270000, +0xb6001003,0xb6002002,0x001fa021,0x009fa021, +0x80171800,0xb6000602,0xb6002001,0x001fa021, +0x806f001f,0x80af001f,0x80a76604,0x80271400, +0x81df0000,0x00000000,0x00000000,0xb6001004, +0x01efb801,0x01afb805,0xb520ffff,0x90a50080, +0x81df0004,0x80a76e04,0x80271400,0x81df0000, +0x00000000,0x00000000,0xb6001004,0x01efb801, +0x01afb805,0xb520ffff,0x90a50080,0x81df0004, +0x81472080,0x015fb179,0x00ffb81f,0x00000000, +0x811be024,0x0107b860,0x95080007,0xb0080000, +0xb4000004,0xa5080008,0x00000000,0x0155b808, +0x00000000,0x8115000c,0x856b000c,0xb0080fff, +0xb400000b,0x81550004,0x856b0004,0x5904b808, +0x1908b80a,0x95080fff,0xb0080fff,0xb4000004, +0x81470001,0xb00b0020,0xb440fff6,0xb500000c, +0x81d50004,0x856b0004,0x00000000,0xb00e000f, +0xb400fffb,0x940b0007,0xb0000000,0xb420ffed, +0x001f42ea,0x9400fffe,0x81470000,0x001f62ea, +0x00ffb81a,0x950e0008,0x5d03b808,0x00000000, +0xb0080000,0xb40000cd,0x011f2080,0x950e0006, +0x5d01b808,0x81270004,0x0529b808,0x950e0001, +0x013f2081,0x011f2082,0x81150004,0x00000000, +0xb0080000,0xb40000c1,0xb008000f,0xb40000bf, +0x011f2083,0x81150002,0x00000000,0x81670004, +0xb0080002,0xb46000b9,0x011f2084,0x013f0081, +0xb0090002,0xb4200011,0x013f0083,0xb0080000, +0xb4200002,0x81077844,0xb5000005,0xb0080001, +0xb4200002,0x81077884,0xb5000001,0x81077824, +0x013f0083,0x5921b809,0x1129b808,0x0119b809, +0x00000000,0x00000000,0x011f6047,0x81150001, +0x00000000,0x011f2085,0x81150001,0x00000000, +0x011f2086,0x81350002,0x00000000,0x013f2087, +0x81150002,0x00000000,0x011f2088,0x81150001, +0x00000000,0x011f2089,0x81150001,0x00000000, +0x011f208a,0x81150002,0x00000000,0x011f208b, +0x81070001,0xb0090003,0xb4000001,0x81070002, +0x011f25b9,0x81070020,0x013f0081,0xb0090002, +0xb4200069,0x85290001,0xad29000f,0x00000000, +0x011f0083,0x1108b809,0x5901b808,0x910877c8, +0x0139b808,0x011f05b9,0x85080001,0x6928b809, +0x011f0084,0xb0090038,0xb4800007,0xb0080001, +0xb4000002,0xb0090050,0xb4400003,0x81270000, +0x8107001b,0xb5000010,0xb0080001,0xb4000005, +0xb0090060,0xb4800003,0x81270001,0x8107001e, +0xb5000009,0xb0080002,0xb4000005,0xb0090030, +0xb4400003,0x81270002,0x81070008,0xb5000002, +0x81270003,0x8107000c,0x011f25bb,0x013f25c0, +0xb0090002,0xb460001b,0x80477604,0x5c42b802, +0x814fffc0,0x80cf0037,0x005fb178,0x5842b802, +0x01cfb802,0x005f9178,0xb520ffff,0x90420020, +0x814fb580,0x80cf0057,0x005fb178,0x5842b802, +0x01cfb802,0x005f9178,0xb520ffff,0x804778a4, +0x5c42b802,0x814f39c0,0x80cf002f,0x005fb178, +0x5842b802,0x01cfb802,0x005f9178,0xb520ffff, +0xb5000025,0x804776e0,0x5c42b802,0x814fef40, +0x80cf0037,0x005fb178,0x5842b802,0x01cfb802, +0x005f9178,0xb520ffff,0x8297013c,0x8317018c, +0x81df0000,0x00000000,0x00000000,0xb6000602, +0x005f8034,0x031fa022,0x82970124,0x83170160, +0xb6000602,0x005f8034,0x031fa022,0x8297010c, +0x83170134,0xb6000602,0x005f8034,0x031fa022, +0x81df0004,0x804778c4,0x5c42b802,0x814f1080, +0x80cf002f,0x005fb178,0x5842b802,0x01cfb802, +0x005f9178,0xb520ffff,0x013f0081,0xb0090001, +0xb420000e,0x808f0000,0x806f001b,0x80af001b, +0x80277758,0x5c22b801,0x80670037,0x00cfb803, +0x003fb178,0x5822b801,0x01cfb801,0x003f9178, +0x0047b86f,0xb0020001,0xb4c0fffd,0x011f25bb, +0x011f0087,0xb0080001,0xb4000002,0x011f05bb, +0xb5000003,0x011f0088,0x91080001,0x5902b808, +0x011f25ba,0x81470000,0x00ffb81a,0x81470008, +0x00ffb81a,0x81270000,0x81470000,0x300842de, +0xb400000b,0x013f42e2,0x91290001,0x013f62e2, +0x013f42e3,0x91290001,0x013f62e3,0x83640006, +0x00000000,0x00000000,0x013f42e2,0x81470002, +0x013f62e2,0x00ffb81a,0x00ffb81b,0x83640049, +0x80c70004,0x80270000,0x81df0000,0x00000000, +0x00000000,0xb600200d,0x00ff05b9,0x5c42b801, +0x300205ba,0xb4800001,0x80e70001,0x80470000, +0xb6270005,0x1062b801,0x914301b8,0x00fff00a, +0x83840055,0x90420080,0x90210004,0x81df0004, +0x00ffb81a,0x83640033,0x017f05bb,0x800700bc, +0x80270000,0x81df0000,0xb00b0000,0xb4000015, +0xb62b0014,0x00ff05b9,0x5c42b801,0x300205ba, +0xb4800001,0x80e70001,0x80470000,0xb0070000, +0xb400000b,0xb627000a,0x1062b801,0x914301b8, +0x00fff00a,0x5c62b801,0x1063b800,0x00bff003, +0x90650134,0x00dff003,0x83840037,0x90420080, +0x90210004,0x81df0004,0x019f05b9,0x80c70002, +0x80270000,0x81df0000,0xb00b0000,0xb400000f, +0xb62b000e,0x80470000,0xb00c0000,0xb400000a, +0xb62c0009,0x1062b801,0x914301b8,0x00fff00a, +0xb0070000,0xb4000003,0x906302b8,0x00fff003, +0x83840021,0x90420080,0x90210004,0x81df0004, +0x00ffb81a,0x8107ffff,0x80c70004,0x00ff0083, +0x83840019,0x80c70002,0x00ff0084,0x83840016, +0x80c70001,0x00ff0085,0x83840013,0x80c70001, +0x00ff0086,0x83840010,0x80c70002,0x00ff0087, +0x8384000d,0x80c70002,0x00ff0088,0x8384000a, +0x80c70001,0x00ff0089,0x83840007,0x80c70001, +0x00ff008a,0x83840004,0x80c70002,0x00ff008b, +0x83840001,0x00ffb81b,0x80a70001,0x64a6b805, +0x5ca1b805,0xb0050000,0xb400000e,0x95288000, +0xb0090000,0xb4000001,0x81270001,0x5901b808, +0x1547b805,0xb00a0000,0xb4000001,0x81470001, +0x2129b80a,0xb0090000,0xb4000001,0xa1088005, +0xb500ffef,0x9508ffff,0x00ffb81c,0x015f05ba, +0x013f05b9,0x800700bc,0xb0090000,0xb4000012, +0xb00a0000,0xb4000010,0x80270000,0x81df0000, +0x00000000,0x00000000,0xb62a000b,0x80470000, +0xb6290008,0x80950004,0x5865b802,0x1063b801, +0x5862b803,0x906301b8,0x0217b803,0x90420001, +0x021fa004,0x90210001,0x81df0004,0xa54a0020, +0xb4c00011,0xb0090000,0xb400000f,0x81df0000, +0x00000000,0x00000000,0xb62a000b,0x80950004, +0x80470000,0xb6290007,0x5865b802,0x1063b801, +0x5862b803,0x906301b8,0x0217b803,0x90420001, +0x021fa004,0x90210001,0x81df0004,0x00ffb81a, +0x013f05b9,0xb0090000,0xb400001c,0x80270000, +0x81df0000,0x00000000,0x00000000,0xb6002017, +0x80470000,0xb6290014,0x5865b802,0x1063b801, +0x5862b803,0x914301b8,0x009ff00a,0xad420060, +0x00000000,0x114ab801,0x5942b80a,0x914a1c80, +0x0217b80a,0xb0040000,0xb4000004,0x80950006, +0x00000000,0x021fa004,0xb5000002,0x8087003f, +0x021fa004,0x90420001,0x90210001,0x81df0004, +0x00ffb81a,0x8257ffff,0x82d7ffff,0x011f05ba, +0x013f05b9,0x80270000,0xb0090000,0xb4000033, +0x81df0000,0x00000000,0x00000000,0xb6280015, +0x80470000,0xb6290012,0x5865b802,0x1063b801, +0x5862b803,0x914301b8,0xaca20060,0x009ff00a, +0x10a5b801,0x58a2b805,0x90a502b8,0x0217b805, +0x80670000,0xb0040000,0xb4000003,0x90840001, +0x0075b804,0x00000000,0x021fa003,0x90420001, +0x90210001,0x81df0004,0xa5480020,0xb4000017, +0x5822b801,0x81df0000,0x00000000,0x00000000, +0xb62a0011,0x914101b8,0x90a102b8,0x0217b805, +0x009ff00a,0xb0040000,0x80670000,0xb4000002, +0x90840001,0x0075b804,0xb6290006,0x021fa203, +0x009f8210,0x009f8210,0x009f8210,0x009f8210, +0x009f8210,0x90210004,0x81df0004,0x00ffb81a, +0x015f05ba,0x013f05b9,0x800700bc,0xb0090000, +0xb4000016,0xb00a0000,0xb4000014,0x80270000, +0x81df0000,0x00000000,0x00000000,0xb62a000f, +0x80470000,0xb629000c,0x1080b801,0x007ff004, +0x90830134,0x007ff004,0x0095b803,0x5865b802, +0x1063b801,0x5862b803,0x906301b8,0x0217b803, +0x90420001,0x021fa004,0x90210001,0x011f05bb, +0x254ab808,0xb4c0000d,0xb62a000c,0x1080b801, +0x007ff004,0x90830134,0x007ff004,0x0095b803, +0x5862b801,0x906301b8,0x0217b803,0x90210001, +0x021fa204,0x007f8210,0x021fa004,0xa5480020, +0xb4c0000e,0xb0090000,0xb400000c,0x80870000, +0xb62a000a,0x80470000,0xb6290007,0x5865b802, +0x1063b801,0x5862b803,0x906301b8,0x0217b803, +0x90420001,0x021fa004,0x90210001,0x81df0004, +0x00000000,0x00000000,0x00ffb81a,0x011f05bb, +0x013f05b9,0xb0080000,0xb4000016,0xb0090000, +0xb4000014,0x81df0000,0x00000000,0x80270000, +0xb6280010,0x80470000,0xb629000d,0x5865b802, +0x1063b801,0x5862b803,0x914301b8,0x009ff00a, +0xb0040000,0xb4000005,0x80950002,0x906302b8, +0x0217b803,0x00000000,0x021fa004,0x90420001, +0x90210001,0x81df0004,0xa5480020,0xb00a0000, +0xb4000011,0xb0090000,0xb400000f,0x81df0000, +0x00000000,0x80870000,0xb62a000b,0x80470000, +0xb6290008,0x5865b802,0x1063b801,0x5862b803, +0x906302b8,0x0217b803,0x00000000,0x021fa004, +0x90420001,0x90210001,0x81df0004,0xb0080000, +0xb400004d,0xb0090000,0xb400004b,0x81df0000, +0x00000000,0x80270000,0xb6280047,0x80470000, +0xb6290044,0x5865b802,0x1063b801,0x5862b803, +0x914301b8,0x009ff00a,0xad420060,0x00000000, +0x00000000,0x00000000,0x114ab801,0x5942b80a, +0x914a1c80,0x0217b80a,0xb0040000,0xb400002e, +0x906302b8,0x009ff003,0xb0040000,0xb420000a, +0x80950006,0x00000000,0x021fa204,0x80950006, +0x015f8210,0x021fa204,0x80950006,0x015f8210, +0x021fa004,0xb5000026,0xb0040001,0xb4200009, +0x80950006,0x00000000,0x021fa204,0x015f8210, +0x021fa204,0x80950006,0x015f8210,0x021fa004, +0xb500001b,0xb0040003,0xb4200009,0x80950006, +0x00000000,0x021fa204,0x80950006,0x015f8210, +0x021fa204,0x015f8210,0x021fa004,0xb5000010, +0xb0040002,0xb420000e,0x80950006,0x00000000, +0x021fa204,0x015f8210,0x021fa204,0x015f8210, +0x021fa004,0xb5000006,0x8087003f,0x021fa204, +0x015f8210,0x021fa204,0x015f8210,0x021fa004, +0x90420001,0x90210001,0x81df0004,0xa5480020, +0xb4c00012,0xb0090000,0xb4000010,0x8087003f, +0x81df0000,0x5862b801,0x90631afc,0xb62a000b, +0x90630004,0x0047b803,0xb6290008,0x90420180, +0x0217b802,0x00000000,0x021fa204,0x003f8210, +0x021fa204,0x003f8210,0x021fa004,0x81df0004, +0x00ffb81a,0x8257ffff,0x82d7ffff,0x011f05bb, +0x013f05b9,0x80270000,0x00e7b809,0x300105ba, +0xb4800001,0x80e70001,0x800700bc,0x80470000, +0x81df0000,0xb0070000,0xb400004c,0xb627004b, +0x5865b802,0x1063b801,0x5862b803,0x914301b8, +0xaca20060,0x009ff00a,0x10a5b801,0x58a2b805, +0x90a502b8,0x0217b805,0xb0040000,0xb400002b, +0x1060b801,0x00bff003,0x10a5b804,0x90650160, +0x00dff003,0xb0060003,0xb4200007,0x90650134, +0x00dff003,0xb6000303,0x0075b806,0x021fa203, +0x007f8210,0xb5000021,0x5861b805,0x906300dc, +0x009fd803,0x90650134,0x00dff003,0xaca20060, +0x00000000,0x00000000,0x00000000,0x0075b806, +0x10a5b801,0x58a2b805,0x90a502b8,0x0217b805, +0x588fb804,0xb600030c,0xb6001007,0x04a3b804, +0xb4600002,0x58a1b803,0xb5000002,0x58a1b805, +0x90a50001,0x0067b805,0x9465ffff,0x5d50b805, +0x021fa20a,0x015f8210,0xb5000004,0x81470000, +0xb6000302,0x021fa20a,0x009f8210,0x009f05b9, +0xb0040002,0xb420000c,0x300105ba,0xb480000a, +0x58a2b801,0x90a502b8,0x0217b805,0x90a50180, +0x0297b805,0xb6000304,0x00bf8210,0x009f8210, +0x029fa205,0x009f8214,0x90420001,0x81df0004, +0x90210001,0x3001b808,0xb480ffa7,0xa5480020, +0xb00a0000,0xb4000019,0xb0090000,0xb4000017, +0x58a2b801,0x90a502b8,0x81df0000,0x00000000, +0x00000000,0xb62a0010,0x80470000,0xb629000d, +0xaca20060,0x00000000,0x00000000,0x00000000, +0x80670000,0x10a5b801,0x58a2b805,0x90a502b8, +0x0217b805,0xb6000302,0x021fa203,0x00bf8210, +0x90420001,0x90210001,0x81df0004,0x00ffb81a, +0x80770000,0x8057ffff,0x80f70000,0x80d7ffff, +0x81770000,0x8157ffff,0x81f70000,0x81d7ffff, +0xac140060,0xac350020,0x00000000,0x00000000, +0x12c0b801,0x5ac2b816,0x92d61980,0x83a400bd, +0xad940400,0x009f9173,0x013f05ca,0x914c6604, +0x114ab804,0x001f97e0,0x001eb80a,0xb0090000, +0xb4000003,0x80a76e44,0x80c76644,0xb5000002, +0x80a76644,0x80c76e44,0x808f000f,0x806f0000, +0x80af000e,0x80cf07e1,0x11e5b80c,0x11efb804, +0x5de2b80f,0x01ffb178,0x59e2b80f,0x01afb80f, +0x01ff9178,0x0047b86f,0xb0020001,0xb4c0fffd, +0x80cf07f0,0x1206b80c,0x1210b804,0x5e02b810, +0x021fb178,0x5a02b810,0x01afb810,0x021f9178, +0x0047b86f,0xb0020001,0xb4c0fffd,0x916c6e04, +0x116bb804,0x001f97ff,0x001eb80b,0x808f0000, +0x806f001f,0x80af001f,0x90ac6604,0x5ca2b805, +0x80270400,0x81df0000,0x00000000,0x00000000, +0xb600080a,0x00cfb801,0x00bfb178,0x58a2b805, +0x01cfb805,0x00bf9178,0x0047b86f,0xb0020001, +0xb4c0fffd,0x90210020,0x90a50020,0x81df0004, +0x90ac6e04,0x5ca2b805,0x80270500,0x81df0000, +0x00000000,0x00000000,0xb600080a,0x00cfb801, +0x00bfb178,0x58a2b805,0x01cfb805,0x00bf9178, +0x0047b86f,0xb0020001,0xb4c0fffd,0x90210020, +0x90a50020,0x81df0004,0x81530020,0xac140060, +0xac350020,0x80170800,0x80d7003c,0x12c0b801, +0x5ac2b816,0x92d602b8,0x0117b816,0x90241000, +0x0097b801,0x80470000,0x4002b803,0x81df0000, +0x00000000,0x00000000,0xb6000804,0x005f8020, +0x480287e4,0x005f8020,0x500287e4,0x81df0004, +0x00000000,0x00000000,0x00000000,0x1021b80a, +0x5c36b801,0x5801b800,0x18c0b801,0xb0090000, +0xb4000002,0x90641440,0xb5000001,0x90641040, +0x81df0000,0x00000000,0x00000000,0xb6000f0d, +0x0097b803,0x80470000,0x4002b803,0xb6001002, +0x005f8020,0x480287e4,0x0108a026,0x90630040, +0x00000000,0x1021b80a,0x5c36b801,0x5801b800, +0x18c0b801,0x81df0004,0x90641400,0x0097b803, +0x80470000,0x4002b803,0x005f8020,0x005f87e4, +0x81df0000,0x00000000,0x00000000,0xb6000802, +0x005f8040,0x480287c4,0x81df0004,0x005f87e0, +0x0108a026,0x00000000,0x1021b80a,0x5c36b801, +0x5801b800,0x18c0b801,0xb0090000,0xb4000002, +0x906417c0,0xb5000001,0x906413c0,0x81df0000, +0x00000000,0x00000000,0xb6000f0f,0x0097b803, +0x80470000,0x4002b803,0xb6000804,0x005f8020, +0x500287e4,0x005f8020,0x480287e4,0x0108a026, +0x84630040,0x00000000,0x1021b80a,0x5c36b801, +0x5801b800,0x18c0b801,0x81df0004,0xb0140000, +0xb4200005,0x90840004,0x9484003f,0x009fb173, +0xa1290001,0x013f25ca,0x80d7ffff,0x0108a026, +0x00ffb81a,0x81330004,0x8093007f,0x9884ffff, +0x80b3ff80,0x0017b816,0x90360040,0x0097b801, +0x81530010,0x81df0000,0x00000000,0x00000000, +0xb6001004,0x400a8000,0x404a8004,0x0008a020, +0x0088a022,0x81df0004,0x0017b816,0x9036007c, +0x0097b801,0x81171000,0x81df0000,0x00000000, +0x00000000,0xb6001004,0x40048020,0x480487e4, +0x00000000,0x0108a020,0x81df0004,0x81470000, +0x81670001,0x81870008,0x81a70040,0x81c707c4, +0x81e70040,0x81df0000,0x00000000,0x00000000, +0xb6000432,0xb00a0001,0xb4e00004,0x80c71000, +0x80e71000,0x81171040,0xb5000003,0x80c71040, +0x80e71040,0x81171000,0x844d0004,0x10e7b802, +0xb62b001f,0x0017b806,0x0097b807,0xb62c0004, +0x40048020,0x480487e4,0x00000000,0x0108a020, +0x0017b806,0x0097b807,0x0197b80e,0x00000000, +0x001f8020,0x042087e4,0xb62c000f,0x4041800c, +0x001f8020,0x0048b802,0x5e38802c,0x2e11b801, +0x042087e4,0x1042b810,0x0462b804,0xb4a00002, +0x0047b804,0xb5000003,0x0462b805,0xb4600001, +0x0047b805,0x011fa022,0x10c6b80f,0x10e7b80f, +0x5961b80b,0x5d81b80c,0x5da1b80d,0x5de1b80f, +0x914a0001,0x954a0001,0x11ceb80f,0x81df0004, +0x80171018,0x81171fcc,0x80470000,0x41448020, +0x494487c0,0x00000000,0x0188b80a,0x494487e0, +0x00000000,0x0148b80a,0x0502a10a,0x4145b80c, +0x494580e0,0x00000000,0x0108a5ea,0x41448080, +0x494487c0,0x00000000,0x0108a78a,0x49448020, +0x00000000,0x0108a2ea,0x41448020,0x49448720, +0x00000000,0x0188b80a,0x4145b80c,0x49458080, +0x494587a0,0x00000000,0x0108a68a,0x4145b80c, +0x49458080,0x494587a0,0x00000000,0x0108a08a, +0x4145b80c,0x49458020,0x49458040,0x00000000, +0x0188b80a,0x494587e0,0x00000000,0x0108a08a, +0x4144b80c,0x494587a0,0x00000000,0x0108a52a, +0x41448080,0x49448040,0x494486c0,0x00000000, +0x0108a04a,0x41448040,0x49448720,0x00000000, +0x0108a36a,0x04028020,0x011fa420,0x001f8040, +0x011fa100,0x001f8080,0x011fa080,0x001f8100, +0x011fa040,0x001f8660,0x011fa120,0x41458020, +0x49458000,0x00000000,0x0108a00a,0x0017b816, +0x9036007c,0x0097b801,0x81171000,0x81970784, +0x00000000,0x001f8020,0x042087e4,0x81df0000, +0x00000000,0x00000000,0xb600100f,0x4041800c, +0x001f8020,0x0048b802,0x5e38802c,0x2e11b801, +0x042087e4,0x1042b810,0x0462b804,0xb4a00002, +0x0047b804,0xb5000003,0x0462b805,0xb4600001, +0x0047b805,0x011fa022,0x81df0004,0x81470000, +0x81670001,0x81870008,0x81a70040,0x81c707c4, +0x81e70040,0x81df0000,0x00000000,0x00000000, +0xb6000432,0xb00a0001,0xb4e00004,0x80c71000, +0x80e71000,0x81171040,0xb5000003,0x80c71040, +0x80e71040,0x81171000,0x844d0004,0x10e7b802, +0xb62b001f,0x0017b806,0x0097b807,0xb62c0004, +0x40048020,0x480487e4,0x00000000,0x0108a020, +0x0017b806,0x0097b807,0x0197b80e,0x00000000, +0x001f8020,0x042087e4,0xb62c000f,0x4041800c, +0x001f8020,0x0048b802,0x5e38802c,0x2e11b801, +0x042087e4,0x1042b810,0x0462b804,0xb4a00002, +0x0047b804,0xb5000003,0x0462b805,0xb4600001, +0x0047b805,0x011fa022,0x10c6b80f,0x10e7b80f, +0x5961b80b,0x5d81b80c,0x5da1b80d,0x5de1b80f, +0x914a0001,0x954a0001,0x11ceb80f,0x81df0004, +0x80171034,0x81171f84,0x80470000,0x41448040, +0x49448640,0x00000000,0x0188b80a,0x49448100, +0x49448780,0x00000000,0x0108a08a,0x4144b80c, +0x49448040,0x49448080,0x494487c0,0x00000000, +0x0108a16a,0x4145b80c,0x49458700,0x00000000, +0x0188b80a,0x494581a0,0x494586e0,0x00000000, +0x0108a66a,0x4145b80c,0x49448040,0x494487e0, +0x00000000,0x0188b80a,0x011fa1ec,0x4145b80c, +0x49458100,0x49458780,0x00000000,0x0108a08a, +0x41458720,0x49458100,0x494586e0,0x49458160, +0x49458020,0x49458020,0x49458760,0x00000000, +0x0108a08a,0x414587a0,0x49458080,0x49458760, +0x494580c0,0x49458700,0x49458140,0x49458020, +0x49458760,0x00000000,0x0108a74a,0x414587a0, +0x49458080,0x49458760,0x494580e0,0x49458700, +0x49458120,0x49458020,0x49458760,0x00000000, +0x0108a08a,0x41458720,0x49458100,0x494586e0, +0x49458140,0x49458040,0x49458020,0x49458720, +0x00000000,0x0108a0ca,0x41458080,0x49458040, +0x49458020,0x49458620,0x00000000,0x0188b80a, +0x49458080,0x00000000,0x0108a7ca,0x4144b80c, +0x49458040,0x49458020,0x49458080,0x00000000, +0x0108a5ea,0x41448080,0x49448700,0x00000000, +0x0188b80a,0x49448780,0x00000000,0x0108a7ca, +0x4144b80c,0x49448140,0x00000000,0x0108a7ca, +0x49448040,0x00000000,0x0108a0ca,0x41448700, +0x00000000,0x0188b80a,0x49448000,0x00000000, +0x0108a04a,0x011fa00c,0x80171f80,0x81df0000, +0x00000000,0x00000000,0xb6002006,0x40048000, +0x48048000,0x48048000,0x48048000,0x00000000, +0x0008a020,0x81df0004,0x00ffb81d,0x00000000, +0x80770000,0x8057ffff,0x015f05b9,0x017f05bb, +0x8293ffff,0x9a94ffff,0x81a70000,0x81df0000, +0x00000000,0x00000000,0xb62a003a,0xaded0180, +0xae0d0180,0xadcd0080,0x902f1980,0x0017b801, +0xb6002033,0x904e01b8,0x00000000,0x013ff002, +0xb0090000,0xb400001f,0x904f02b8,0x80c70000, +0x011fd802,0x6829b808,0x94210001,0xb0010001, +0xb4e00001,0x00c7b814,0x6429b806,0x80470001, +0x6449b802,0x84420001,0x1442b808,0x84690001, +0x5863b803,0x906300dc,0x1042b801,0x003f9803, +0x90420001,0x4082b801,0x90630004,0x003f9803, +0x00000000,0x5897b804,0x1804b805,0x4082b801, +0x00000000,0x00000000,0x00000000,0x10a4b800, +0xb5000001,0x80a70000,0x90501c80,0x00000000, +0x007ff002,0x5842b803,0x904205f8,0x0097b802, +0x00000000,0x40058004,0x48058004,0x00000000, +0x0008a020,0x91ce0004,0x91ef0004,0x92100004, +0x91ad0001,0x81df0004,0x00ffb81a,0x80770000, +0x8057ffff,0x80d7ffff,0x015f05b9,0x017f05bb, +0x8293ff80,0x9a940000,0x82a70020,0x81a70000, +0x81e702b8,0x80171980,0x81df0000,0x00000000, +0x00000000,0xb62a004f,0xb600034d,0xac0d0080, +0xac4d0180,0xac960080,0x822700bc,0x91c001b8, +0x00000000,0x1042b804,0x92021c80,0xb62b003a, +0x013ff00e,0x00fff011,0xb0090000,0xb4000027, +0x10e7b809,0x5821b807,0x902100dc,0x00000000, +0x001fd801,0x82470000,0x80270001,0x6452b801, +0x3002b800,0xb4600002,0x92520001,0xb500fffb, +0x86520001,0x80c70000,0x011fd80f,0x6832b808, +0xb0010001,0xb4e00001,0x00c7b814,0x84520017, +0x0056b802,0x80270001,0x6432b801,0x84210001, +0x1408b801,0x6402b800,0x10c6b800,0x9027018c, +0x00000000,0x001ff001,0x5802b800,0x9020073c, +0x904006f8,0x007f9801,0x0097b802,0x10c6b803, +0x40868004,0x48868004,0xb5000003,0x80c70000, +0x40868004,0x00000000,0x0088b804,0x003ff010, +0x5822b801,0x902105f8,0x0097b801,0x91ce0004, +0x91ef0004,0x40448004,0x48448004,0x92100004, +0x0008a022,0x92310001,0x0435b80b,0xb4000007, +0x80870000,0xb6210005,0x001fa024,0x91ce0004, +0x91ef0004,0x92100004,0x92310001,0x00000000, +0x91ad0001,0x81df0004,0x00ffb81a,0x00000000, +0x007f05b9,0x001f0081,0xb0000001,0xb440002d, +0x001f05d8,0xac400080,0x801702b8,0x80970438, +0x90421800,0x0117b802,0x8087ffff,0x80b3ffff, +0x80d3007f,0x98c6ff00,0x80f3ff80,0x81070080, +0x81df0000,0x00000000,0x00000000,0xb6002018, +0x10088020,0x0056b800,0x0442b806,0xb4a00004, +0xb0000000,0x0007b806,0xb4400001,0x0007b807, +0x0027b800,0x5c08b800,0x1400b804,0xb0030001, +0xb4000008,0x10288024,0x0056b801,0x0442b806, +0xb4a00004,0xb0010000,0x0027b806,0xb4400001, +0x0027b807,0x5828b801,0x1421b805,0x1900a021, +0x81df0004,0x001f05d8,0x90000001,0x001f25d8, +0x00ffb81a,0x801702b8,0x80970438,0x81171800, +0x8087ffff,0x80b3ffff,0x80d3007f,0x98c6ff00, +0x80f3ff80,0x81070080,0x81df0000,0x00000000, +0x00000000,0xb6006018,0x10088020,0x0056b800, +0x0442b806,0xb4a00004,0xb0000000,0x0007b806, +0xb4400001,0x0007b807,0x0027b800,0x5c08b800, +0x1400b804,0xb0030001,0xb4000008,0x10288024, +0x0056b801,0x0442b806,0xb4a00004,0xb0010000, +0x0027b806,0xb4400001,0x0027b807,0x5828b801, +0x1421b805,0x1900a021,0x81df0004,0x00ffb81a, +0x001f0081,0xb0000001,0xb4400006,0x001f05d8, +0xb0000003,0xb4000003,0x80270001,0x003f25dc, +0x00ffb81a,0x003f05d9,0x009f05cb,0xb0010000, +0xb400000e,0x015f42ed,0x81070000,0x8127017c, +0xb00a0000,0xb4000002,0x81070180,0x812702fc, +0x802500a5,0x9421ffff,0x3001b808,0xb4800011, +0x3001b809,0xb4a0007f,0xb500000e,0x001f0081, +0xb0000001,0xb4400003,0xb0040002,0xb4200006, +0xb5000002,0xb0040000,0xb4200003,0x802702ff, +0x81470000,0xb5000003,0x80270001,0x003f25d9, +0x81470180,0xb0040000,0xb4200001,0x838402e6, +0x80070000,0x001f25d8,0x009f902d,0x80af001f, +0x808f0000,0x806f0000,0x8007ffff,0x8033ffff, +0x80171800,0x81df0000,0x807bff8c,0x94630003, +0xb0030003,0xb4000016,0xb0030002,0xb4000035, +0xb0030001,0xb4000024,0xb6006010,0x14618000, +0x6068b803,0x40c4b803,0x14608000,0x00c8b806, +0x5870b803,0x6068b803,0x4104b803,0x58c8b806, +0x0108b808,0x14c6b801,0x00000000,0x00000000, +0x5d08b808,0x1508b800,0x1806a028,0xb5000030, +0xb6006010,0x14618000,0x6068b803,0x40c4b803, +0x14608000,0x00c8b806,0x5870b803,0x6068b803, +0x4104b803,0x5cc8b806,0x0108b808,0x14c6b800, +0x00000000,0x00000000,0x5908b808,0x1508b801, +0x1806a028,0xb500001e,0xb600600d,0x14618000, +0x6068b803,0x40c4b803,0x00000000,0x00c8b806, +0x00000000,0x00000000,0x00000000,0x5d08b806, +0x1508b800,0x58c8b806,0x14c6b801,0x1806a028, +0xb500000f,0xb600600e,0x14608000,0x5868b803, +0x6068b803,0x40c4b803,0x00000000,0x00c8b806, +0x00000000,0x00000000,0x00000000,0x5d08b806, +0x1508b800,0x58c8b806,0x14c6b801,0x1806a028, +0x81df0004,0x80670600,0x5d22b80a,0x81df0000, +0x00000000,0x00000000,0xb600030a,0x00cfb803, +0x013fb178,0x5922b809,0x01afb809,0x013f9178, +0x0047b86f,0xb0020001,0xb4c0fffd,0x90630020, +0x91290020,0x81df0004,0x81270180,0xb00a0000, +0xb4000001,0x81270000,0x013f62ed,0x80270001, +0x003f25dc,0x00ffb81a,0x801bff7c,0x00000000, +0x94000080,0xb0000080,0xb400ff61,0x001f0081, +0xb0000001,0xb4400006,0x001f05d8,0xb0000003, +0xb4000003,0x80270001,0x003f25dc,0x00ffb81a, +0x003f05d9,0x009f05cb,0xb0010000,0xb400000e, +0x015f42ed,0x81070000,0x812702fc,0xb00a0000, +0xb4000002,0x81070300,0x812705fc,0x802500a5, +0x9421ffff,0x3001b808,0xb4800011,0x3001b809, +0xb4a00073,0xb500000e,0x001f0081,0xb0000001, +0xb4400003,0xb0040002,0xb4200006,0xb5000002, +0xb0040000,0xb4200003,0x802705ff,0x81470000, +0xb5000003,0x80270001,0x003f25d9,0x81470300, +0xb0040000,0xb4200001,0x83840247,0x80070000, +0x001f25d8,0x009f902d,0x80af001f,0x808f0000, +0x806f0000,0x8007ffff,0x8033ffff,0x80171800, +0x807bff8c,0x80971980,0x81df0000,0x94630003, +0xb0030003,0xb4000013,0xb0030002,0xb400002c, +0xb0030001,0xb400001e,0xb600600d,0x58708000, +0x6068b803,0x40c4b803,0x14618020,0x00c8b806, +0x6068b803,0x4104b803,0x00000000,0x0108b808, +0x5887a026,0x00000000,0x00000000,0x5887a028, +0xb5000026,0xb600600d,0x14618000,0x6068b803, +0x40c4b803,0x58708020,0x00c8b806,0x6068b803, +0x4104b803,0x00000000,0x0108b808,0x5887a026, +0x00000000,0x00000000,0x5887a028,0xb5000017, +0xb600600a,0x14618000,0x6068b803,0x40c4b803, +0x00000000,0x00c8b806,0x00000000,0x00000000, +0x00000000,0x5887a026,0x5887a026,0xb500000b, +0xb600600a,0x58708000,0x6068b803,0x40c4b803, +0x00000000,0x00c8b806,0x00000000,0x00000000, +0x00000000,0x5887a026,0x5887a026,0x81df0004, +0x80670660,0x5d22b80a,0x81df0000,0x00000000, +0x00000000,0xb600060a,0x00cfb803,0x013fb178, +0x5922b809,0x01afb809,0x013f9178,0x0047b86f, +0xb0020001,0xb4c0fffd,0x90630020,0x91290020, +0x81df0004,0x81270300,0xb00a0000,0xb4000001, +0x81270000,0x013f62ed,0x80270001,0x003f25dc, +0x00ffb81a,0x00000000,0x00000000,0x00000000, +0x029fb024,0x02bfb025,0x02dfb026,0x02ffb027, +0x031fb028,0x033fb029,0x033f4046,0x0287b86f, +0x029fb02a,0x8285009c,0x96b48000,0xb0158000, +0xb400018e,0x96b40100,0xb0150100,0xb40001a4, +0x96b40400,0xb0150400,0xb40001a5,0x96b40001, +0xb0150001,0xb400000c,0x96b40008,0xb0150008, +0xb4000197,0x96b44000,0xb0154000,0xb40001a4, +0x96b40002,0xb0150002,0xb400015b,0x00000000, +0x00000000,0xb50001b6,0x02bf917e,0x92b50001, +0x02bfb17e,0x82850082,0x5efdb814,0x96f70001, +0xb0170001,0xb420000b,0x83050069,0x9718003f, +0x82e50064,0x12f7b818,0x86f70109,0x82feff74, +0x02e7b86f,0x9af74000,0x01ffb817,0x96f7bfff, +0x01ffb817,0x83050081,0x82a5009a,0x96b50001, +0xb0150001,0xb4200014,0x82a70000,0x02bfb17e, +0x96b41840,0xb0150800,0xb420000c,0x96b40008, +0x5aa9b815,0x96d46000,0x5ec3b816,0x82f3000f, +0x9af7c00f,0x1718b817,0x1ab5b818,0x1ab5b816, +0x9ab50340,0x82a60081,0xb500012b,0x9b180180, +0x83060081,0xb5000128,0x82a5009a,0x96b50002, +0xb0150002,0xb420001b,0x82a70000,0x02bfb17e, +0x96b41800,0xb0151800,0xb4000013,0x96b40040, +0xb0150040,0xb4200004,0xa3180c00,0x9b180340, +0x83060081,0xb5000118,0x96b40008,0x5aa9b815, +0x96d46000,0x5ec3b816,0x82f3000f,0x9af7c00f, +0x1718b817,0x1ab5b818,0x1ab5b816,0x9ab50340, +0x82a60081,0xb500010c,0x9b180180,0x83060081, +0xb5000109,0x82a500c1,0x96b5000f,0xb015000b, +0xb420000e,0x96b40020,0xb0150020,0xb400000b, +0x96b40200,0xb0150200,0xb4000008,0x82c50086, +0x82e50094,0x3016b817,0xb4400004,0x06f7b816, +0xb017ff00,0xb4400001,0xb50000f7,0x96b46000, +0xb0156000,0xb4000011,0x96b41820,0xb0150820, +0xb4200004,0x9b391000,0x82a5009a,0x96b5feff, +0x82a6009a,0x96b40040,0xb0150040,0xb4200001, +0x9739efff,0x96b91000,0xb0151000,0xb4200003, +0x82a5009a,0x9ab50100,0x82a6009a,0x96b40040, +0xb0150040,0xb4200019,0x96b41800,0xb0151800, +0xb4200006,0x96b98000,0xb0158000,0xb4200003, +0x9b180180,0x83060081,0xb50000d7,0x96d80c00, +0x82b300ff,0x9ab5f3ff,0x1718b815,0xb0160c00, +0xb4000007,0x82e50098,0x96f70400,0xb0170400, +0xb4200002,0x82c70c00,0xb5000001,0xa2d60c00, +0x1b18b816,0x9b180340,0xb50000bd,0x96b40220, +0xb0150000,0xb4e00021,0x82a5009d,0x82f3ffff, +0x16b5b817,0x82f3000e,0x3015b817,0xb420001b, +0x96f98000,0xb0178000,0xb4000018,0x82a70000, +0x02bfb17e,0x82c5009d,0x96d6ffff,0x82b30032, +0x9ab58001,0x82e500c1,0x96f7000f,0xb017000b, +0xb4000002,0x82b30022,0x9ab58001,0x1ab5b816, +0x82c5009a,0x96d60020,0xb0160020,0xb4200002, +0x82b30032,0x9ab58001,0x82a6009d,0x02ff917e, +0x00000000,0xb0170040,0xb4800000,0x5eb5b814, +0x96b500f0,0x96f46000,0x5eedb817,0x1ab5b817, +0xb0170003,0xb4000004,0x96b500ef,0x96f70001, +0x5ae4b817,0x1ab5b817,0x96d41800,0xb0161800, +0xb400000a,0x96f900ff,0x96b500ff,0x9739ff00, +0x1b39b815,0x02a7b817,0x96b500f3,0x96d40008, +0x5ec1b816,0x1ab5b816,0xb500000c,0x96f98000, +0xb0178000,0xb4200007,0x5efeb814,0x96f70001, +0xb0170001,0xb4000003,0x9b180180,0x83060081, +0xb5000081,0x96b500f3,0x9ab50008,0x9739fff3, +0x96d40020,0xb0160020,0xb4200017,0x9b398000, +0x82c70000,0x02dfb17e,0x96d40010,0x5ac8b816, +0x82f300ff,0x9af7cfff,0x1718b817,0x1b18b816, +0x9b180340,0x82c5009d,0x96d6ffff,0x82f3000e, +0x9af78001,0x1af7b816,0x82c5009a,0x96d60020, +0xb0160020,0xb4200002,0x82f30032,0x9af78001, +0x82e6009d,0xb500005a,0x97397fff,0x96b500ff, +0x5aaab815,0x82f300fc,0x9af703ff,0x1718b817, +0x1b18b815,0x9b180340,0x82c5009a,0x96d60010, +0xb0160010,0xb4200024,0x82c70000,0x02dfb17e, +0x82c50086,0x92d60e10,0x82c60086,0x82c50094, +0x5eefb818,0x96f70003,0xb0170003,0xb4200002, +0x82e70e10,0xb5000001,0x82e70e10,0x12d6b817, +0x82e50081,0x9af70020,0x82e60081,0x82c60094, +0xa2f70020,0x82e60081,0x82f30001,0x16f7b818, +0x5ef0b817,0xb0170001,0xb4000004,0x96f84000, +0x5ee4b817,0x9718f3ff,0x1b18b817,0x82f3000a, +0x9af78000,0x82e6009d,0x83060081,0x83070001, +0x8306009f,0xb5000096,0x82c5009d,0x82f3000e, +0x9af78001,0x3016b817,0xb420000f,0x82b30032, +0x9ab58001,0x82e500c1,0x96f7000f,0xb017000b, +0xb4000002,0x82b30022,0x9ab58001,0x82c5009a, +0x96d60020,0xb0160020,0xb4200002,0x82b30032, +0x9ab58001,0x82a6009d,0x82c5009a,0x96d60080, +0xb0160080,0xb4000011,0x02df917e,0x00000000, +0xb0160010,0xb480000d,0x82c500c1,0x96d6000f, +0xb016000b,0xb4000009,0x82c50087,0x96d60080, +0x5ac7b816,0x96f84000,0x3017b816,0xb4200003, +0x033f4046,0x9b394000,0xb500000b,0x9739bfff, +0x82e50061,0x96f70008,0xb0170008,0xb4000005, +0x5eefb818,0x96f70003,0xb0170003,0xb4000001, +0x9718ffff,0x83060081,0x83070001,0x8306009f, +0x00000000,0xb500005e,0x82850083,0x96b400ff, +0xb015003c,0xb4200019,0x96b92000,0xb0152000, +0xb4000002,0x9b392000,0xb5000014,0x9739d3ff, +0x82870000,0x82860087,0x82870008,0x82860083, +0x829bff78,0x82a7001f,0xb0140400,0xb4000001, +0x82a70010,0x82a600c9,0x829bff78,0x00000000, +0x828600cb,0x8285009d,0x82b3ffff,0x9ab5fffd, +0x1694b815,0x8286009d,0xb5000000,0x83070002, +0x8306009f,0x00000000,0xb500003d,0x96b90800, +0xb0150800,0xb4200009,0x9739f7ff,0x82a703fd, +0x82a600cb,0x82a7003c,0x82a60083,0x8285009d, +0x9a940002,0x8286009d,0xb5000004,0x82850087, +0x5a82b814,0xa2940200,0x82860087,0xb5000000, +0x83078000,0x8306009f,0x00000000,0xb5000028, +0x83070008,0x8306009f,0x00000000,0xb5000024, +0x83070100,0x8306009f,0x00000000,0xb5000020, +0x83070000,0x83050081,0x9b180180,0x83060081, +0x83070400,0x8306009f,0x00000000,0xb5000018, +0x82870000,0x82850082,0x5eb7b814,0x96b500fc, +0x96d40006,0x5ec1b816,0x1ab5b816,0x5aacb815, +0x83050081,0x82d3001c,0x9ad600ff,0x1718b816, +0x1b18b815,0x9b180e00,0x83060081,0x83074000, +0x8306009f,0x8305009d,0x82d300ff,0x9ad6bfff, +0x1718b816,0x8306009d,0x00000000,0xb5000000, +0x029f902a,0x01ffb814,0x033f6046,0x029f9024, +0x02bf9025,0x02df9026,0x02ff9027,0x031f9028, +0x033f9029,0x00ffb81e,0x02ff917d,0x92f7092f, +0x031f0084,0xb0180001,0xb4200002,0x02ff917d, +0x92f70870,0x02ffb17d,0x02ff917c,0x82bbffdc, +0x829bffd8,0x93150004,0x3014b815,0xb4000017, +0x02dbb818,0x029bb815,0x3017b816,0xb4800013, +0x5a81b814,0x029fb17d,0x82def200,0x82fef204, +0x82e50086,0x06f7b814,0x02f6b817,0x82fef208, +0x82860095,0x82870001,0x829ef220,0x8293001f, +0x9294fe00,0x92b50008,0x3015b814,0xb4800002, +0x82b3001f,0x92b5fa00,0x82beffdc,0x82850086, +0x83250094,0x06d4b819,0x02d6b816,0xb016ffff, +0xb4a00009,0x82c50081,0x9ab60020,0x82a60081, +0x82a50086,0x92b50e10,0x82a60094,0x82c60081, +0x86b50704,0x82a6009b,0x00ffb81c,0x00000000, +0x001f9012,0x001fb200,0x001f004c,0x001f2804, +0x801bfef0,0x8058fef4,0x803bff68,0x8078ff6c, +0x2000b801,0x2042b803,0x001fb204,0x005f2814, +0x82e70001,0x83640048,0x029fb014,0x829efef0, +0x8286000f,0x02bf2054,0x82bcfef4,0x82a6000e, +0x00ffb81a,0x80e70001,0x801336e3,0x9800eb76, +0x001fb200,0x800700ab,0x001f2804,0x801bc3e8, +0x8058c3ec,0x83640024,0x82e70000,0x83640036, +0x029fb3c0,0x029fb200,0x02bf2f04,0x02bf2804, +0x801bc000,0x8058c004,0x8364001b,0x82e70000, +0x8364002d,0x001f93c0,0x3000b814,0xb420000a, +0x001f0f04,0x3000b815,0xb4200007,0x829efef0, +0x82bcfef4,0x029fb012,0x02bf204c,0x82870001, +0x829cfef5,0x00ffb81a,0xb0070000,0xb4000007, +0x80e70000,0x801399fa,0x9800c92e,0x001fb200, +0x800700af,0x001f2804,0xb500ffdc,0x82870000, +0x829cfef5,0x00ffb81a,0x80c700ff,0x803bff68, +0x8078ff6c,0x14a0b806,0x2063b805,0x007f2814, +0x2021b802,0x58c8b806,0x14a0b806,0x58b0b805, +0x2021b805,0x58c8b806,0x14a0b806,0x2021b805, +0x58c8b806,0x14a0b806,0x5cb0b805,0x2021b805, +0x003fb204,0x00ffb81b,0x82c70000,0x83070800, +0x83270005,0x8197080c,0x81d7ffff,0x83840126, +0x83840001,0x00ffb81b,0x808f0000,0x806f001f, +0x80af001f,0x80270240,0x81e77c08,0x5de2b80f, +0xb6000208,0x00cfb801,0x01ffb178,0x59e2b80f, +0x01cfb80f,0x01ff9178,0xb520ffff,0x91ef0020, +0x90210020,0x80270280,0x81e77b00,0x5de2b80f, +0xb6000208,0x00cfb801,0x01ffb178,0x59e2b80f, +0x01cfb80f,0x01ff9178,0xb520ffff,0x91ef0020, +0x90210020,0x8057ffff,0x80170830,0x80070810, +0x80270808,0xb6000509,0x005ff000,0x90420900, +0x007ff001,0x90630a00,0x009ff002,0x00bff003, +0x2004a025,0x90000001,0x90210001,0x80070814, +0x80d7ffff,0x8097085c,0x8017083c,0xb6000404, +0x005ff000,0x007f87e0,0x84000001,0x2082a7e3, +0x80970860,0x80170840,0x2082b803,0x007f8000, +0x2083a004,0x80170830,0x80970850,0x80270808, +0xb6000508,0x005f8024,0x90420900,0x007ff001, +0x90630a00,0x009ff002,0x00bff003,0x2004a025, +0x90210001,0x80170840,0x00000000,0x02bf87e0, +0x80970860,0x82870000,0xb6000404,0x005f87e4, +0x5a88b814,0x204287e0,0x1a94b802,0x00ffb81c, +0x001f0e49,0x001f2b09,0x001f0e41,0x001f2b08, +0x001f0e46,0x001f2b07,0x001f0e48,0x001f2b06, +0x001f0e42,0x001f2b05,0x001f0e47,0x001f2b04, +0x001f0e45,0x001f2b03,0x001f0e43,0x001f2b02, +0x001f0e40,0x001f2b01,0x001f0e44,0x001f2b00, +0x001f0f25,0xa020000c,0x94400001,0x94600002, +0x94810004,0x94a10008,0x94c00010,0x5943b802, +0x5861b803,0x5882b804,0x5ca2b805,0x5cc4b806, +0x194ab803,0x194ab804,0x194ab805,0x194ab806, +0x015f2b38,0x801b7c00,0x003f92c1,0x5c28b801, +0x005f92c2,0x5858b802,0x1821b802,0x2000b801, +0x001fb2c4,0x80187c04,0x003f0b09,0x2000b801, +0x001f2b14,0x82c70001,0x82e70001,0x83070b10, +0x8327001e,0x81970b35,0x8384009f,0x02df0b38, +0x82170e30,0x838400f1,0x819efef0,0x817cfef4, +0x819eff68,0x817cff6c,0x00ffb81b,0x820f001f, +0x8018fef8,0x8057ffff,0x001f2b09,0x8018fef6, +0x80d7ffff,0x001f2b08,0x8018fefa,0x8157ffff, +0x001f2b07,0x8018fefd,0x81d7ffff,0x001f2b06, +0x8018fefb,0x802f001f,0x001f2b05,0x8018fefe, +0x00000000,0x001f2b04,0x8018fef9,0x00000000, +0x001f2b03,0x8018feff,0x00000000,0x001f2b02, +0x8018fef7,0x00000000,0x001f2b01,0x8018fefc, +0x00000000,0x001f2b00,0x001f0f25,0xa0200011, +0x94410001,0x94600002,0x94800004,0x94a00008, +0x94c10010,0x5941b802,0x5861b803,0x5c82b804, +0x58a1b805,0x5cc1b806,0x194ab803,0x194ab804, +0x194ab805,0x194ab806,0x015f2b38,0x801b7c00, +0x003f92c1,0x5c28b801,0x005f92c2,0x5858b802, +0x1821b802,0x2000b801,0x001fb2c4,0x80187c04, +0x003f0b09,0x2000b801,0x001f2b14,0x82c70001, +0x82e70001,0x83070b10,0x8327001e,0x81970b35, +0x83840055,0x02df0b38,0x82170e20,0x838400a7, +0x819efef0,0x817cfef4,0x5ac8b80c,0x02ff0e44, +0x1ad6b817,0x02dfb391,0x5ed8b80c,0x5968b80b, +0x1ad6b80b,0x02df6724,0x00ffb81b,0x820f001f, +0x8018fefe,0x8057ffff,0x001f2b09,0x8018fefa, +0x80d7ffff,0x001f2b08,0x8018fefc,0x8157ffff, +0x001f2b07,0x8018feff,0x81d7ffff,0x001f2b06, +0x8018fef8,0x802f001f,0x001f2b05,0x8018fefb, +0x00000000,0x001f2b04,0x8018fefd,0x00000000, +0x001f2b03,0x8018fef6,0x00000000,0x001f2b02, +0x8018fef9,0x00000000,0x001f2b01,0x8018fef7, +0x00000000,0x001f2b00,0x801b7c00,0x003f92c1, +0x5c28b801,0x005f92c2,0x5858b802,0x1821b802, +0x2000b801,0x001fb2c4,0x80187c04,0x003f0b09, +0x2000b801,0x001f2b14,0x82c70001,0x82e70001, +0x83070b10,0x8327001e,0x81970b35,0x83840016, +0x83270000,0x831bfef0,0x82f8fef4,0x02c7b819, +0x82170e28,0x83840065,0x300cb818,0xb4200002, +0x300bb817,0xb4000006,0x93390001,0xb0190020, +0xb480fff6,0x83270000,0x833cfef5,0x00ffb81b, +0x019fb390,0x017f2e44,0x033f2f25,0x83270001, +0x833cfef5,0x00ffb81b,0x0007b818,0x90000003, +0x00000000,0x015ff000,0x90000001,0x5949b80a, +0x013ff000,0x194ab809,0x84000002,0x994a0100, +0x017ff000,0x958b00f8,0x5981b80c,0x956b0007, +0x198cb80b,0x84000002,0x998c0008,0x017ff000, +0x90000001,0x5971b80b,0x198cb80b,0x017ff000, +0x5969b80b,0x198cb80b,0x81a70000,0x94d90003, +0x82a70000,0xb6260019,0xb6000818,0x5df0b80a, +0x5e02b80a,0x21efb810,0x95ef0001,0x5941b80a, +0x194ab80f,0x21efb816,0x5e18b80c,0x5e35b80c, +0x5e54b80c,0x5e6cb80c,0x2210b811,0x2252b813, +0x2210b812,0x96100001,0x5981b80c,0x198cb810, +0x2210b817,0x10afb810,0x10a5b80d,0x5da1b805, +0x94a50001,0x5aa1b815,0x1ab5b805,0x019fa7f5, +0x5cc2b819,0xb626001c,0x82870000,0xb6000419, +0xb6000818,0x5df0b80a,0x5e02b80a,0x21efb810, +0x95ef0001,0x5941b80a,0x194ab80f,0x21efb816, +0x5e18b80c,0x5e35b80c,0x5e54b80c,0x5e6cb80c, +0x2210b811,0x2252b813,0x2210b812,0x96100001, +0x5981b80c,0x198cb810,0x2210b817,0x10afb810, +0x10a5b80d,0x5da1b805,0x94a50001,0x5a81b814, +0x1a94b805,0x019fa7f4,0x00ffb81c,0x8257ffff, +0x808f0000,0x806f001f,0x80af001f,0x80270300, +0x81e778e0,0x5de2b80f,0xb6000208,0x00cfb801, +0x01ffb178,0x59e2b80f,0x01cfb80f,0x01ff9178, +0xb520ffff,0x91ef0020,0x90210020,0x80270340, +0x81e779e0,0x5de2b80f,0xb6000208,0x00cfb801, +0x01ffb178,0x59e2b80f,0x01cfb80f,0x01ff9178, +0xb520ffff,0x91ef0020,0x90210020,0x80270280, +0x81e77b00,0x5de2b80f,0xb6000208,0x00cfb801, +0x01ffb178,0x59e2b80f,0x01cfb80f,0x01ff9178, +0xb520ffff,0x91ef0020,0x90210020,0x806f0007, +0x80af0007,0x80270380,0x81e77ae0,0x5de2b80f, +0x00cfb801,0x01ffb178,0x59e2b80f,0x01cfb80f, +0x01ff9178,0xb520ffff,0x91ef0020,0x90210020, +0x80170b60,0x001f0b00,0x001fa020,0x001f0b01, +0x001fa020,0x001f0b02,0x001fa020,0x001f0b03, +0x001fa020,0x001f0b04,0x001fa000,0x80970b50, +0x81170b70,0x82a70b35,0x83a40060,0x001f87e4, +0xb6000405,0x86b50001,0x83a4005c,0x001f8004, +0x003f87e8,0x2080a7e1,0x80970b70,0x80170b50, +0x81170b50,0x81970b40,0x82a70b30,0x001f800c, +0x003f8008,0x2100a001,0x83a40050,0x001f87e4, +0xb6000405,0x86b50001,0x83a4004c,0x001f8004, +0x003f87e8,0x2080a7e1,0x80970b50,0x80170b70, +0x81170b70,0x81970b60,0x82a70b2b,0x001f800c, +0x003f8008,0x2100a001,0x83a40040,0x83a4004e, +0xb6000407,0x86b50001,0x83a4003c,0x001f8004, +0x003f87e8,0x2080a001,0x83a40047,0x00000000, +0x80970b70,0x80170b50,0x81170b50,0x81970b40, +0x82a70b26,0x001f800c,0x003f8008,0x2100a001, +0x83a4002e,0x83a4003c,0xb6000407,0x86b50001, +0x83a4002a,0x001f8004,0x003f87e8,0x2080a001, +0x83a40035,0x00000000,0x80970b50,0x80170b70, +0x81170b70,0x81970b60,0x82a70b21,0x001f800c, +0x003f8008,0x2100a001,0x83a4001c,0x001f87e4, +0xb6000405,0x86b50001,0x83a40018,0x001f8004, +0x003f87e8,0x2080a7e1,0x80970b70,0x80170b50, +0x81170b50,0x81970b40,0x82a70b1c,0x001f800c, +0x003f8008,0x2100a001,0x83a4000c,0x017f87e4, +0x81870000,0xb6000406,0x86b50001,0x83a40007, +0x001f87e4,0x200087e8,0x5988b80c,0x198cb800, +0x021fa02c,0x021fa00b,0x00ffb81c,0x005ff015, +0x90420a00,0x003f87e0,0x001ff002,0x2060b801, +0x90630c00,0x90960e00,0x001ff003,0x003ff004, +0x20a0b801,0x90a50d00,0x00000000,0x001ff005, +0x009fa000,0x00ffb81d,0x001f8004,0x5c21b800, +0x5847b800,0x1821b802,0x942100ff,0x2080a7e1, +0x00ffb81d,0x00000000,0x00000000,0x00000000, + +}; + +static u32 MPGI2SUcode1f5c00[] = { +0x00000000,0xfffff8c0,0x00003540,0xffff8d40, +0x0001fd40,0xfffaf7c0,0x00066b80,0xffdb63c0, +0x00494780,0x00249c40,0x00066b80,0x00050840, +0x0001fd40,0x000072c0,0x00003540,0x00000740, +0xffffffc0,0xfffff840,0x00003680,0xffff7e40, +0x0001f400,0xfffa9cc0,0x0005d1c0,0xffd99600, +0x00493c00,0x0022ce00,0x0006f780,0x0004ad00, +0x000203c0,0x00006440,0x00003400,0x00000680, +0xffffffc0,0xfffff740,0x00003780,0xffff6ec0, +0x0001e800,0xfffa4240,0x00052a00,0xffd7ca00, +0x00491a00,0x0020ffc0,0x00077600,0x00045240, +0x00020800,0x000056c0,0x00003280,0x00000600, +0xffffffc0,0xfffff680,0x00003840,0xffff5ec0, +0x0001d940,0xfff9e8c0,0x00047440,0xffd60080, +0x0048e180,0x001f32c0,0x0007e700,0x0003f7c0, +0x000209c0,0x00004980,0x00003100,0x00000540, +0xffffffc0,0xfffff5c0,0x000038c0,0xffff4e40, +0x0001c780,0xfff990c0,0x0003b000,0xffd43ac0, +0x00489240,0x001d6800,0x00084b00,0x00039e40, +0x00020940,0x00003d00,0x00002f80,0x000004c0, +0xffffffc0,0xfffff4c0,0x00003900,0xffff3d40, +0x0001b2c0,0xfff93a40,0x0002ddc0,0xffd279c0, +0x00482d00,0x001ba040,0x0008a200,0x000345c0, +0x000206c0,0x00003140,0x00002dc0,0x00000440, +0xffffffc0,0xfffff3c0,0x00003900,0xffff2c00, +0x00019b00,0xfff8e640,0x0001fd40,0xffd0be80, +0x0047b1c0,0x0019dc80,0x0008ecc0,0x0002ef00, +0x00020240,0x00002640,0x00002c00,0x00000400, +0xffffff80,0xfffff2c0,0x000038c0,0xffff1a40, +0x00017fc0,0xfff894c0,0x00010e80,0xffcf09c0, +0x004720c0,0x00181d80,0x00092b40,0x000299c0, +0x0001fc00,0x00001bc0,0x00002a40,0x00000380, +0xffffff80,0xfffff180,0x00003800,0xffff0840, +0x00016180,0xfff84680,0x00001180,0xffcd5cc0, +0x00467a40,0x00166440,0x00095e00,0x00024680, +0x0001f440,0x00001200,0x00002840,0x00000340, +0xffffff80,0xfffff040,0x00003740,0xfffef600, +0x00014000,0xfff7fbc0,0xffff0680,0xffcbb880, +0x0045bf00,0x0014b140,0x00098580,0x0001f580, +0x0001ea80,0x00000900,0x00002680,0x000002c0, +0xffffff80,0xffffef00,0x000035c0,0xfffee3c0, +0x00011ac0,0xfff7b540,0xfffded80,0xffca1d80, +0x0044ef80,0x00130580,0x0009a1c0,0x0001a700, +0x0001dfc0,0x00000080,0x000024c0,0x00000280, +0xffffff40,0xffffedc0,0x00003400,0xfffed180, +0x0000f280,0xfff77340,0xfffcc700,0xffc88d80, +0x00440bc0,0x001161c0,0x0009b3c0,0x00015b00, +0x0001d380,0xfffff8c0,0x000022c0,0x00000240, +0xffffff40,0xffffec40,0x00003200,0xfffebf40, +0x0000c680,0xfff73680,0xfffb92c0,0xffc708c0, +0x00431500,0x000fc6c0,0x0009bb80,0x000111c0, +0x0001c640,0xfffff1c0,0x00002100,0x00000200, +0xffffff00,0xffffeac0,0x00002f40,0xfffead00, +0x00009740,0xfff6ff40,0xfffa5180,0xffc59080, +0x00420b40,0x000e3500,0x0009b9c0,0x0000cb80, +0x0001b7c0,0xffffeb40,0x00001f40,0x000001c0, +0xffffff00,0xffffe940,0x00002c40,0xfffe9b00, +0x00006480,0xfff6ce00,0xfff90380,0xffc425c0, +0x0040ef80,0x000cad00,0x0009af00,0x00008840, +0x0001a880,0xffffe580,0x00001d40,0x000001c0, +0xfffffec0,0xffffe7c0,0x000028c0,0xfffe8980, +0x00002e40,0xfff6a3c0,0xfff7a900,0xffc2c900, +0x003fc280,0x000b2fc0,0x00099b80,0x00004800, +0x00019880,0xffffe040,0x00001bc0,0x00000180, +0xfffffec0,0xffffe600,0x00002480,0xfffe7840, +0xfffff4c0,0xfff68040,0xfff64240,0xffc17b40, +0x003e84c0,0x0009bdc0,0x00097fc0,0x00000b40, +0x000187c0,0xffffdb80,0x00001a00,0x00000140, +0xfffffe80,0xffffe440,0x00001fc0,0xfffe6780, +0xffffb800,0xfff66480,0xfff4d040,0xffc03d80, +0x003d3700,0x00085700,0x00095c40,0xffffd1c0, +0x00017680,0xffffd740,0x00001840,0x00000140, +0xfffffe40,0xffffe2c0,0x00001a80,0xfffe5780, +0xffff77c0,0xfff65100,0xfff35300,0xffbf1080, +0x003bda40,0x0006fc80,0x00093200,0xffff9b80, +0x00016500,0xffffd3c0,0x000016c0,0x00000100, +0xfffffe40,0xffffe0c0,0x000014c0,0xfffe4840, +0xffff3480,0xfff64640,0xfff1cb00,0xffbdf4c0, +0x003a6f80,0x0005ae80,0x000900c0,0xffff68c0, +0x00015300,0xffffd0c0,0x00001540,0x00000100, +0xfffffe00,0xffffdf00,0x00000e40,0xfffe39c0, +0xfffeee40,0xfff64480,0xfff03940,0xffbceb00, +0x0038f740,0x00046d40,0x0008c980,0xffff3980, +0x000140c0,0xffffce00,0x000013c0,0x000000c0, +0xfffffdc0,0xffffdd40,0x00000740,0xfffe2c80, +0xfffea500,0xfff64c40,0xffee9e40,0xffbbf440, +0x00377280,0x00033900,0x00088cc0,0xffff0d80, +0x00012e80,0xffffcc00,0x00001240,0x000000c0, +0xfffffd80,0xffffdb40,0xffffff80,0xfffe2040, +0xfffe5900,0xfff65e40,0xffecfa80,0xffbb1080, +0x0035e280,0x00021280,0x00084ac0,0xfffee540, +0x00011c40,0xffffca40,0x00001100,0x00000080, +0xfffffd40,0xffffd980,0xfffff700,0xfffe1580, +0xfffe0a80,0xfff67a80,0xffeb4ec0,0xffba4100, +0x00344780,0x0000f980,0x00080440,0xfffec000, +0x00010a00,0xffffc8c0,0x00000fc0,0x00000080, +0xfffffcc0,0xffffd7c0,0xffffee00,0xfffe0bc0, +0xfffdb980,0xfff6a200,0xffe99bc0,0xffb985c0, +0x0032a340,0xffffee80,0x0007b980,0xfffe9e80, +0x0000f7c0,0xffffc800,0x00000e80,0x00000080, +0xfffffc80,0xffffd5c0,0xffffe440,0xfffe0400, +0xfffd6640,0xfff6d4c0,0xffe7e280,0xffb8df40, +0x0030f640,0xfffef180,0x00076b40,0xfffe8040, +0x0000e5c0,0xffffc740,0x00000d40,0x00000080, +0xfffffc00,0xffffd400,0xffffd9c0,0xfffdfdc0, +0xfffd1100,0xfff71340,0xffe62380,0xffb84e40, +0x002f4180,0xfffe02c0,0x000719c0,0xfffe6500, +0x0000d400,0xffffc700,0x00000c40,0x00000040, +0xfffffbc0,0xffffd240,0xffffcec0,0xfffdf940, +0xfffcba40,0xfff75e00,0xffe45fc0,0xffb7d300, +0x002d8640,0xfffd2240,0x0006c5c0,0xfffe4d40, +0x0000c2c0,0xffffc700,0x00000b40,0x00000040, +0xfffffb40,0xffffd080,0xffffc300,0xfffdf6c0, +0xfffc61c0,0xfff7b500,0xffe29800,0xffb76dc0, +0x002bc540,0xfffc5000,0x00066f40,0xfffe3880, +0x0000b1c0,0xffffc740,0x00000a40,0x00000040, +0xfffffac0,0xffffcf00,0xffffb680,0xfffdf640, +0xfffc0840,0xfff81900,0xffe0cd40,0xffb71e80, +0x0029ff80,0xfffb8bc0,0x00061740,0xfffe26c0, +0x0000a140,0xffffc7c0,0x00000980,0x00000040, +0xfffffa00,0xffffcd80,0xffffa940,0xfffdf800, +0xfffbadc0,0xfff88a00,0xffdf0040,0xffb6e600, +0x00283600,0xfffad600,0x0005bdc0,0xfffe1800, +0x00009140,0xffffc880,0x000008c0,0x00000040, +0xfffff980,0xffffcc00,0xffff9bc0,0xfffdfc40, +0xfffb5300,0xfff90880,0xffdd3200,0xffb6c400, +0x00266a00,0xfffa2e40,0x00056340,0xfffe0c00, +0x000081c0,0xffffc980,0x000007c0,0x00000040, +0x004013c2,0x0040b346,0x0041fa2d,0x0043f934, +0x0046cc1c,0x004a9d9d,0x004fae37,0x0056601f, +0x005f4cf7,0x006b6fcf,0x007c7d1e,0x0115b035, +0x013df91b,0x0207655e,0x03342c83,0x0a185230, +0x00404f46,0x0042e13c,0x0048919f,0x0052cb0e, +0x0064e240,0x0107c449,0x015c7926,0x050cf270, +0x004140fb,0x004cf8df,0x0073326c,0x02480d9d, +0x004545ea,0x01273d75,0x005a827a,0x007fffff, +0x006597fb,0x0050a28c,0x00400000,0x0032cbfd, +0x00285146,0x00200000,0x001965ff,0x001428a3, +0x00100000,0x000cb2ff,0x000a1451,0x00080000, +0x00065980,0x00050a29,0x00040000,0x00032cc0, +0x00028514,0x00020000,0x00019660,0x0001428a, +0x00010000,0x0000cb30,0x0000a145,0x00008000, +0x00006598,0x000050a3,0x00004000,0x000032cc, +0x00002851,0x00002000,0x00001966,0x00001429, +0x00001000,0x00000cb3,0x00000a14,0x00000800, +0x00000659,0x0000050a,0x00000400,0x0000032d, +0x00000285,0x00000200,0x00000196,0x00000143, +0x00000100,0x000000cb,0x000000a1,0x00000080, +0x00000066,0x00000051,0x00000040,0x00000033, +0x00000028,0x00000020,0x00000019,0x00000014, +0x00000010,0x0000000d,0x0000000a,0x00000008, +0x00000006,0x00000005,0x00000000,0x00555555, +0x00666666,0x00492492,0x0071c71c,0x00444444, +0x00421084,0x00410410,0x00408102,0x00404040, +0x00402010,0x00401004,0x00400801,0x00400400, +0x00400200,0x00400100,0x00400080,0x00400040, +0x00400000,0x00400000,0x00200000,0x00400000, +0x00100000,0x00080000,0x00040000,0x00020000, +0x00010000,0x00008000,0x00004000,0x00002000, +0x00001000,0x00000800,0x00000400,0x00000200, +0x00000100,0x0003588d,0x0002b15e,0x0002056d, +0x00015600,0x0000a329,0xffffeed9,0xffff3960, +0xfffe8423,0xfffdd11c,0xfffd2048,0xfffc7353, +0xfffbcb6f,0xfffb29a6,0xfffa8f15,0x000494ae, +0x0003f991,0x00032dd1,0xfffd2d8f,0x0001eb47, +0xfffe9968,0x00009af6,0x000011de,0xffff4335, +0x00018d69,0xfffdecd4,0x000302f8,0xfffca0d7, +0x0004683d,0xfffb67f8,0x0005b36d,0x00045963, +0xfffbd51e,0x00030062,0xfffd0dee,0x0001d046, +0xfffe8a0a,0x00009258,0x000012b1,0xffff4d9e, +0x00019ec3,0xfffe0a44,0x0003245a,0xfffcd082, +0x000498f0,0xfffba919,0x0005f304,0x00041bf4, +0xfffba72a,0x0002d19e,0xfffcf060,0x0001b407, +0xfffe7c08,0x0000894a,0x0000138d,0xffff58ac, +0x0001afaf,0xfffe28fe,0x000343bf,0xfffd026f, +0x0004c6f6,0xfffbed06,0x00062e61,0x0003dc0e, +0xfffb7bf1,0x0002a17f,0xfffcd522,0x000196a0, +0xfffe6e70,0x00007ff6,0x00001439,0xffff63f6, +0x0001beb3,0xfffe4882,0x0003616d,0xfffd361b, +0x0004f1cf,0xfffc332a,0x0006658f,0x00039943, +0xfffb52c0,0x00026ec7,0xfffcbb94,0x0001789f, +0xfffe6160,0x00007677,0x000014d4,0xffff6f74, +0x0001cc9b,0xfffe694f,0x00037cbf,0xfffd6b41, +0x000519c2,0xfffc7baf,0x00069971,0x00035486, +0xfffb2d0c,0x00023ad8,0xfffca3ee,0x00015989, +0xfffe55af,0x00006ca7,0x00001570,0xffff7b71, +0x0001d9cb,0xfffe8b46,0x0003959e,0xfffda1fe, +0x00053ee6,0xfffcc6b4,0x0006c950,0x00030e08, +0xfffb0a7a,0x0002061e,0xfffc8ec0,0x00013911, +0xfffe4b1d,0x00006278,0x000015e8,0xffff87b6, +0x0001e577,0xfffeadd6,0x0003acc2,0xfffdda34, +0x00056059,0xfffd136d,0x0006f4b5,0x0002c562, +0xfffaea7c,0x0001cfa6,0xfffc7b14,0x0001182b, +0xfffe4159,0x00005817,0x0000165c,0xffff9417, +0x0001f00f,0xfffed14c,0x0003c199,0xfffe13f6, +0x00057e83,0xfffd61cd,0x00071ba1,0x00027ab5, +0xfffacdc3,0x00019833,0xfffc6989,0x0000f6ca, +0xfffe38da,0x00004d9d,0x000016ef,0xffffa103, +0x0001f98f,0xfffef5c0,0x0003d3d1,0xfffe4f00, +0x0005998c,0xfffdb21e,0x00073e77,0x00022e75, +0xfffab482,0x00015fd1,0xfffc5b13,0x0000d45d, +0xfffe318f,0x000042ed,0x0000176b,0xffffae8f, +0x0002018f,0xffff1a91,0x0003e40c,0xfffe8af2, +0x0005b0ca,0xfffe03b8,0x00075d14,0x0001e141, +0xfffa9e9b,0x0001262a,0xfffc4e31,0x0000b1af, +0xfffe2b26,0x00003805,0x000017b1,0xffffbc21, +0x000208b8,0xffff3fb6,0x0003f1d7,0xfffec7af, +0x0005c4c5,0xfffe5654,0x0007768a,0x000192fe, +0xfffa8bb0,0x0000ec3f,0xfffc4365,0x00008ec9, +0xfffe25f0,0x00002d05,0x000017ec,0xffffc984, +0x00020ec6,0xffff658d,0x0003fcba,0xffff0500, +0x0005d576,0xfffeaa37,0x00078bc6,0x00014367, +0xfffa7bec,0x0000b1f4,0xfffc3b82,0x00006b06, +0xfffe2201,0x000021eb,0x00001823,0xffffd704, +0x0002132a,0xffff8be7,0x00040534,0xffff4315, +0x0005e22e,0xfffeff0a,0x00079ce3,0x0000f33f, +0xfffa6fc9,0x000076ca,0xfffc3558,0x00004762, +0xfffe1ef3,0x000016a1,0x0000183f,0xffffe4a6, +0x00021664,0xffffb27d,0x00040b7b,0xffff81e5, +0x0005eb4e,0xffff5475,0x0007a857,0x0000a2cb, +0xfffa671b,0x00003b64,0xfffc31e2,0x00002416, +0xfffe1ce1,0x00000b46,0x00001850,0xfffff24d, +0x00021855,0xffffd93a,0x00040f75,0xffffc0e6, +0x0005f0e3,0xffffaa3e,0x0007af45,0x0000519f, +0xfffa6218,0x0003f991,0x0003588d,0x0002b15e, +0x0002056d,0x00015600,0x0000a329,0xffffeed9, +0xffff3960,0xfffe8423,0xfffdd11c,0xfffd2048, +0xfffc7353,0xfffbcb6f,0xfffb29a6,0xfffa8f15, +0x000494ae,0x0003c6b0,0xfffc7e8b,0x00028ef6, +0xfffde181,0x000144eb,0xffff5500,0xffffefb9, +0x0000d01d,0xfffe9755,0x000249a4,0xfffd453c, +0x0003b80e,0xfffc01aa,0x000511d6,0xfffad527, +0xfffb334e,0x0003916c,0xfffc5778,0x00026a92, +0xfffdc9f5,0x00013314,0xffff4d99,0xfffff0b6, +0x0000d911,0xfffeab80,0x00026369,0xfffd6c0a, +0x0003e17f,0xfffc39d8,0x000549df,0xfffb1eb2, +0xfffafe6c,0x00035929,0xfffc3321,0x000244a6, +0xfffdb402,0x00012035,0xffff46ac,0xfffff192, +0x0000e16a,0xfffebfe0,0x00027b3d,0xfffd9433, +0x0004087b,0xfffc74b7,0x00057e8d,0xfffb6a81, +0xfffacc1c,0x00031fbe,0xfffc10df,0x00021e0c, +0xfffd9f6d,0x00010cb7,0xffff402e,0xfffff279, +0x0000e965,0xfffed574,0x00029159,0xfffdbdc4, +0x00042c4c,0xfffcb1e7,0x0005b02d,0xfffbb942, +0xfffa9d38,0x0002e44a,0xfffbf0fd,0x0001f5b4, +0xfffd8c38,0x0000f8b1,0xffff3a21,0xfffff391, +0x0000f0e6,0xfffeec44,0x0002a642,0xfffde90e, +0x00044e32,0xfffcf0fb,0x0005de46,0xfffc0b18, +0xfffa71d1,0x0002a659,0xfffbd3de,0x0001cb90, +0xfffd7a97,0x0000e403,0xffff3490,0xfffff49c, +0x0000f7a8,0xffff0340,0x0002b95f,0xfffe1573, +0x00046dbe,0xfffd3284,0x00060888,0xfffc5f51, +0xfffa4996,0x00026786,0xfffbb8df,0x0001a0e1, +0xfffd6a4e,0x0000ced2,0xffff2f75,0xfffff593, +0x0000fdbe,0xffff1a53,0x0002ca87,0xfffe42f5, +0x0004898a,0xfffd7563,0x00062f0b,0xfffcb5de, +0xfffa2508,0x00022713,0xfffba0bf,0x0001754a, +0xfffd5b5f,0x0000b92c,0xffff2acd,0xfffff6b0, +0x0001034f,0xffff3241,0x0002da5c,0xfffe71c6, +0x0004a341,0xfffdb946,0x000651e8,0xfffd0e37, +0xfffa0402,0x0001e4d4,0xfffb8b9c,0x00014898, +0xfffd4e7d,0x0000a304,0xffff26b7,0xfffff7e1, +0x00010846,0xffff4b34,0x0002e897,0xfffea13f, +0x0004ba63,0xfffdff2d,0x00067115,0xfffd6839, +0xfff9e680,0x0001a1fa,0xfffb789e,0x00011b2e, +0xfffd43a4,0x00008c6e,0xffff2341,0xfffff8fd, +0x00010c9c,0xffff6469,0x0002f48f,0xfffed1a4, +0x0004cd6a,0xfffe4608,0x00068c1b,0xfffdc409, +0xfff9cd15,0x00015dfe,0xfffb68a0,0x0000ecee, +0xfffd3a2e,0x0000757d,0xffff204b,0xfffffa1e, +0x00011054,0xffff7da1,0x0002fe9c,0xffff033e, +0x0004de57,0xfffe8dc6,0x0006a2d5,0xfffe213e, +0xfff9b77d,0x000118d3,0xfffb5bde,0x0000be25, +0xfffd3224,0x00005e52,0xffff1dc1,0xfffffb4b, +0x00011353,0xffff9740,0x00030748,0xffff351c, +0x0004ec95,0xfffed755,0x0006b5b4,0xfffe7fc6, +0xfff9a599,0x0000d334,0xfffb519f,0x00008f08, +0xfffd2bbf,0x00004704,0xffff1bc1,0xfffffc71, +0x00011598,0xffffb135,0x00030e43,0xffff6720, +0x0004f6f3,0xffff2119,0x0006c46e,0xfffedf38, +0xfff997c7,0x00008d13,0xfffb4a55,0x00005fa5, +0xfffd273b,0x00002f76,0xffff1a63,0xfffffda0, +0x00011744,0xffffcb67,0x000312ff,0xffff99cf, +0x0004ff0c,0xffff6a9c,0x0006cebd,0xffff3f0a, +0xfff98dbe,0x00004691,0xfffb4620,0x00003010, +0xfffd24fc,0x000017b5,0xffff199d,0xfffffed8, +0x0001185a,0xffffe5c6,0x0003157e,0xffffcce3, +0x000503ae,0xffffb515,0x0006d537,0xffff9f5a, +0xfff98767,0xfffb44b0,0xfffc3131,0xfffd2475, +0xfffe1c28,0xffff195d,0x00001859,0x000118bd, +0x000218df,0x0003163a,0x000410e0,0x000504a7, +0x0005f2b3,0x0006d796,0x0007b1fe,0xfff98537, +0xfffa609b,0xfffc7e8b,0x00028ef6,0xfffde181, +0x000144eb,0xffff5500,0xffffefb9,0x0000d01d, +0xfffe9755,0x000249a4,0xfffd453c,0x0003b80e, +0xfffc01aa,0x000511d6,0xfffad527,0xfffb334e, +0x0003c6b0,0xfffc5778,0x00026a92,0xfffdc9f5, +0x00013314,0xffff4d99,0xfffff0b6,0x0000d911, +0xfffeab80,0x00026369,0xfffd6c0a,0x0003e17f, +0xfffc39d8,0x000549df,0xfffb1eb2,0xfffafe6c, +0x0003916c,0xfffc3321,0x000244a6,0xfffdb402, +0x00012035,0xffff46ac,0xfffff192,0x0000e16a, +0xfffebfe0,0x00027b3d,0xfffd9433,0x0004087b, +0xfffc74b7,0x00057e8d,0xfffb6a81,0xfffacc1c, +0x00035929,0xfffc10df,0x00021e0c,0xfffd9f6d, +0x00010cb7,0xffff402e,0xfffff279,0x0000e965, +0xfffed574,0x00029159,0xfffdbdc4,0x00042c4c, +0xfffcb1e7,0x0005b02d,0xfffbb942,0xfffa9d38, +0x00031fbe,0xfffbf0fd,0x0001f5b4,0xfffd8c38, +0x0000f8b1,0xffff3a21,0xfffff391,0x0000f0e6, +0xfffeec44,0x0002a642,0xfffde90e,0x00044e32, +0xfffcf0fb,0x0005de46,0xfffc0b18,0xfffa71d1, +0x0002e44a,0xfffbd3de,0x0001cb90,0xfffd7a97, +0x0000e403,0xffff3490,0xfffff49c,0x0000f7a8, +0xffff0340,0x0002b95f,0xfffe1573,0x00046dbe, +0xfffd3284,0x00060888,0xfffc5f51,0xfffa4996, +0x0002a659,0xfffbb8df,0x0001a0e1,0xfffd6a4e, +0x0000ced2,0xffff2f75,0xfffff593,0x0000fdbe, +0xffff1a53,0x0002ca87,0xfffe42f5,0x0004898a, +0xfffd7563,0x00062f0b,0xfffcb5de,0xfffa2508, +0x00026786,0xfffba0bf,0x0001754a,0xfffd5b5f, +0x0000b92c,0xffff2acd,0xfffff6b0,0x0001034f, +0xffff3241,0x0002da5c,0xfffe71c6,0x0004a341, +0xfffdb946,0x000651e8,0xfffd0e37,0xfffa0402, +0x00022713,0xfffb8b9c,0x00014898,0xfffd4e7d, +0x0000a304,0xffff26b7,0xfffff7e1,0x00010846, +0xffff4b34,0x0002e897,0xfffea13f,0x0004ba63, +0xfffdff2d,0x00067115,0xfffd6839,0xfff9e680, +0x0001e4d4,0xfffb789e,0x00011b2e,0xfffd43a4, +0x00008c6e,0xffff2341,0xfffff8fd,0x00010c9c, +0xffff6469,0x0002f48f,0xfffed1a4,0x0004cd6a, +0xfffe4608,0x00068c1b,0xfffdc409,0xfff9cd15, +0x0001a1fa,0xfffb68a0,0x0000ecee,0xfffd3a2e, +0x0000757d,0xffff204b,0xfffffa1e,0x00011054, +0xffff7da1,0x0002fe9c,0xffff033e,0x0004de57, +0xfffe8dc6,0x0006a2d5,0xfffe213e,0xfff9b77d, +0x00015dfe,0xfffb5bde,0x0000be25,0xfffd3224, +0x00005e52,0xffff1dc1,0xfffffb4b,0x00011353, +0xffff9740,0x00030748,0xffff351c,0x0004ec95, +0xfffed755,0x0006b5b4,0xfffe7fc6,0xfff9a599, +0x000118d3,0xfffb519f,0x00008f08,0xfffd2bbf, +0x00004704,0xffff1bc1,0xfffffc71,0x00011598, +0xffffb135,0x00030e43,0xffff6720,0x0004f6f3, +0xffff2119,0x0006c46e,0xfffedf38,0xfff997c7, +0x0000d334,0xfffb4a55,0x00005fa5,0xfffd273b, +0x00002f76,0xffff1a63,0xfffffda0,0x00011744, +0xffffcb67,0x000312ff,0xffff99cf,0x0004ff0c, +0xffff6a9c,0x0006cebd,0xffff3f0a,0xfff98dbe, +0x00008d13,0xfffb4620,0x00003010,0xfffd24fc, +0x000017b5,0xffff199d,0xfffffed8,0x0001185a, +0xffffe5c6,0x0003157e,0xffffcce3,0x000503ae, +0xffffb515,0x0006d537,0xffff9f5a,0xfff98767, +0x00004691,0xfffa609b,0xfffb44b0,0xfffc3131, +0xfffd2475,0xfffe1c28,0xffff195d,0x00001859, +0x000118bd,0x000218df,0x0003163a,0x000410e0, +0x000504a7,0x0005f2b3,0x0006d796,0x0007b1fe, +0xfff98537,0xfffbd51e,0x00032dd1,0xfffd2d8f, +0x0001eb47,0xfffe9968,0x00009af6,0x000011de, +0xffff4335,0x00018d69,0xfffdecd4,0x000302f8, +0xfffca0d7,0x0004683d,0xfffb67f8,0x0005b36d, +0x00045963,0xfffba72a,0x00030062,0xfffd0dee, +0x0001d046,0xfffe8a0a,0x00009258,0x000012b1, +0xffff4d9e,0x00019ec3,0xfffe0a44,0x0003245a, +0xfffcd082,0x000498f0,0xfffba919,0x0005f304, +0x00041bf4,0xfffb7bf1,0x0002d19e,0xfffcf060, +0x0001b407,0xfffe7c08,0x0000894a,0x0000138d, +0xffff58ac,0x0001afaf,0xfffe28fe,0x000343bf, +0xfffd026f,0x0004c6f6,0xfffbed06,0x00062e61, +0x0003dc0e,0xfffb52c0,0x0002a17f,0xfffcd522, +0x000196a0,0xfffe6e70,0x00007ff6,0x00001439, +0xffff63f6,0x0001beb3,0xfffe4882,0x0003616d, +0xfffd361b,0x0004f1cf,0xfffc332a,0x0006658f, +0x00039943,0xfffb2d0c,0x00026ec7,0xfffcbb94, +0x0001789f,0xfffe6160,0x00007677,0x000014d4, +0xffff6f74,0x0001cc9b,0xfffe694f,0x00037cbf, +0xfffd6b41,0x000519c2,0xfffc7baf,0x00069971, +0x00035486,0xfffb0a7a,0x00023ad8,0xfffca3ee, +0x00015989,0xfffe55af,0x00006ca7,0x00001570, +0xffff7b71,0x0001d9cb,0xfffe8b46,0x0003959e, +0xfffda1fe,0x00053ee6,0xfffcc6b4,0x0006c950, +0x00030e08,0xfffaea7c,0x0002061e,0xfffc8ec0, +0x00013911,0xfffe4b1d,0x00006278,0x000015e8, +0xffff87b6,0x0001e577,0xfffeadd6,0x0003acc2, +0xfffdda34,0x00056059,0xfffd136d,0x0006f4b5, +0x0002c562,0xfffacdc3,0x0001cfa6,0xfffc7b14, +0x0001182b,0xfffe4159,0x00005817,0x0000165c, +0xffff9417,0x0001f00f,0xfffed14c,0x0003c199, +0xfffe13f6,0x00057e83,0xfffd61cd,0x00071ba1, +0x00027ab5,0xfffab482,0x00019833,0xfffc6989, +0x0000f6ca,0xfffe38da,0x00004d9d,0x000016ef, +0xffffa103,0x0001f98f,0xfffef5c0,0x0003d3d1, +0xfffe4f00,0x0005998c,0xfffdb21e,0x00073e77, +0x00022e75,0xfffa9e9b,0x00015fd1,0xfffc5b13, +0x0000d45d,0xfffe318f,0x000042ed,0x0000176b, +0xffffae8f,0x0002018f,0xffff1a91,0x0003e40c, +0xfffe8af2,0x0005b0ca,0xfffe03b8,0x00075d14, +0x0001e141,0xfffa8bb0,0x0001262a,0xfffc4e31, +0x0000b1af,0xfffe2b26,0x00003805,0x000017b1, +0xffffbc21,0x000208b8,0xffff3fb6,0x0003f1d7, +0xfffec7af,0x0005c4c5,0xfffe5654,0x0007768a, +0x000192fe,0xfffa7bec,0x0000ec3f,0xfffc4365, +0x00008ec9,0xfffe25f0,0x00002d05,0x000017ec, +0xffffc984,0x00020ec6,0xffff658d,0x0003fcba, +0xffff0500,0x0005d576,0xfffeaa37,0x00078bc6, +0x00014367,0xfffa6fc9,0x0000b1f4,0xfffc3b82, +0x00006b06,0xfffe2201,0x000021eb,0x00001823, +0xffffd704,0x0002132a,0xffff8be7,0x00040534, +0xffff4315,0x0005e22e,0xfffeff0a,0x00079ce3, +0x0000f33f,0xfffa671b,0x000076ca,0xfffc3558, +0x00004762,0xfffe1ef3,0x000016a1,0x0000183f, +0xffffe4a6,0x00021664,0xffffb27d,0x00040b7b, +0xffff81e5,0x0005eb4e,0xffff5475,0x0007a857, +0x0000a2cb,0xfffa6218,0x00003b64,0xfffc31e2, +0x00002416,0xfffe1ce1,0x00000b46,0x00001850, +0xfffff24d,0x00021855,0xffffd93a,0x00040f75, +0xffffc0e6,0x0005f0e3,0xffffaa3e,0x0007af45, +0x0000519f,0x00030000,0x000f0007,0x003f001f, +0x00ff007f,0x03ff01ff,0x0fff07ff,0x3fff1fff, +0xffff7fff,0x00030000,0x00070005,0x000f0009, +0x003f001f,0x00ff007f,0x03ff01ff,0x0fff07ff, +0xffff1fff,0x00030000,0x00070005,0x000f0009, +0xffff001f,0x00030000,0xffff0005,0x04030504, +0x08070605,0x0c0b0a09,0x100f0e0d,0x03070504, +0x0605040a,0x0a090807,0x100d0c0b,0x03070503, +0x1005040a,0x10070502,0x03030100,0x03030303, +0x03030303,0x03030303,0x03010100,0x03030301, +0x03030303,0x03030303,0x03010100,0x03030301, +0x03010100,0x04020000,0x08070605,0x0c0b0a09, +0x100f0e0d,0x02010000,0x06050403,0x0a090807, +0x100d0c0b,0x02010000,0x10050403,0x10010000, +0x00030000,0x00090005,0x001f000f,0x007f003f, +0x01ff00ff,0x07ff03ff,0x1fff0fff,0x7fff3fff, +0x00030000,0x00090005,0x001f000f,0x007f003f, +0x0a070504,0x07060504,0x0b0a0908,0x0f0e0d0c, +0x0a070503,0x07060504,0x01010100,0x03030303, +0x03030303,0x03030303,0x01010100,0x03030303, +0x03010000,0x07060504,0x0b0a0908,0x0f0e0d0c, +0x03010000,0x07060504,0x00555555,0x002aaaab, +0x00249249,0x00124925,0x00111111,0x00088889, +0x00084210,0x00421084,0x00041041,0x00020821, +0x00020408,0x00081020,0x00010101,0x00008081, +0x00008040,0x00100804,0x00004010,0x00020080, +0x00002004,0x00004008,0x00001001,0x00000801, +0x00000800,0x00200100,0x00000400,0x00080020, +0x00000200,0x00020004,0x00200000,0x00600040, +0x00a00080,0x00e000c0,0x01200100,0x01600140, +0x01a00180,0x000001c0,0x00300020,0x00400038, +0x00600050,0x00800070,0x00c000a0,0x010000e0, +0x01800140,0x00200000,0x00300028,0x00400038, +0x00600050,0x00800070,0x00c000a0,0x010000e0, +0x00000140,0x00900000,0x00fc00d8,0x01680120, +0x01f801b0,0x02d00240,0x03f00360,0x05a00480, +0x000006c0,0x00680000,0x00b6009c,0x010500d0, +0x016d0139,0x020a01a1,0x02db0272,0x04140343, +0x000004e5,0x006c0000,0x00bd00a2,0x010e00d8, +0x017a0144,0x006301b0,0x013b00cf,0x00c601a7, +0x0000019e,0x00600000,0x00a80090,0x00f000c0, +0x01500120,0x01e00180,0x02a00240,0x03c00300, +0x00000480,0x10000000,0x10101010,0x20101010, +0x20202020,0x20202020,0x28202020,0x28282828, +0x00002828,0x10100000,0x10101010,0x10101010, +0x00000000,0x00000000,0x00000000,0x00000000, +0xcbcecdc4,0xcfcac9c8,0xc3c6c5cc,0xc7c2c1c0, +0x1b1e1d14,0x1f1a1918,0x1316151c,0x17121110, +0x2b2e2d24,0x2f2a2928,0x2326252c,0x27222120, +0x3b3e3d34,0x3f3a3938,0x3336353c,0x37323130, +0x0b0e0d04,0x0f0a0908,0x0306050c,0x07020100, +0xdbdeddd4,0xdfdad9d8,0xd3d6d5dc,0xd7d2d1d0, +0xebeeede4,0xefeae9e8,0xe3e6e5ec,0xe7e2e1e0, +0xfbfefdf4,0xfffaf9f8,0xf3f6f5fc,0xf7f2f1f0, +0x4b4e4d44,0x4f4a4948,0x4346454c,0x47424140, +0x9b9e9d94,0x9f9a9998,0x9396959c,0x97929190, +0xabaeada4,0xafaaa9a8,0xa3a6a5ac,0xa7a2a1a0, +0xbbbebdb4,0xbfbab9b8,0xb3b6b5bc,0xb7b2b1b0, +0x8b8e8d84,0x8f8a8988,0x8386858c,0x87828180, +0x5b5e5d54,0x5f5a5958,0x5356555c,0x57525150, +0x6b6e6d64,0x6f6a6968,0x6366656c,0x67626160, +0x7b7e7d74,0x7f7a7978,0x7376757c,0x77727170, +0x341424c4,0x3e1e2ece,0x3d1d2dcd,0x3b1b2bcb, +0xb494a444,0xbe9eae4e,0xbd9dad4d,0xbb9bab4b, +0xf4d4e404,0xfedeee0e,0xfddded0d,0xfbdbeb0b, +0x74546484,0x7e5e6e8e,0x7d5d6d8d,0x7b5b6b8b, +0x3c1c2ccc,0x361626c6,0x351525c5,0x331323c3, +0xbc9cac4c,0xb696a646,0xb595a545,0xb393a343, +0xfcdcec0c,0xf6d6e606,0xf5d5e505,0xf3d3e303, +0x7c5c6c8c,0x76566686,0x75556585,0x73536383, +0x381828c8,0x3a1a2aca,0x391929c9,0x3f1f2fcf, +0xb898a848,0xba9aaa4a,0xb999a949,0xbf9faf4f, +0xf8d8e808,0xfadaea0a,0xf9d9e909,0xffdfef0f, +0x78586888,0x7a5a6a8a,0x79596989,0x7f5f6f8f, +0x301020c0,0x321222c2,0x311121c1,0x371727c7, +0xb090a040,0xb292a242,0xb191a141,0xb797a747, +0xf0d0e000,0xf2d2e202,0xf1d1e101,0xf7d7e707, +0x70506080,0x72526282,0x71516181,0x77576787, +0x05040100,0x15141110,0x25242120,0x35343130, +0x85848180,0x95949190,0xa5a4a1a0,0xb5b4b1b0, +0xc0408000,0xe060a020,0xd0509010,0xf070b030, +0xc8488808,0xe868a828,0xd8589818,0xf878b838, +0xc4448404,0xe464a424,0xd4549414,0xf474b434, +0xcc4c8c0c,0xec6cac2c,0xdc5c9c1c,0xfc7cbc3c, +0xc2428202,0xe262a222,0xd2529212,0xf272b232, +0xca4a8a0a,0xea6aaa2a,0xda5a9a1a,0xfa7aba3a, +0xc6468606,0xe666a626,0xd6569616,0xf676b636, +0xce4e8e0e,0xee6eae2e,0xde5e9e1e,0xfe7ebe3e, +0xc1418101,0xe161a121,0xd1519111,0xf171b131, +0xc9498909,0xe969a929,0xd9599919,0xf979b939, +0xc5458505,0xe565a525,0xd5559515,0xf575b535, +0xcd4d8d0d,0xed6dad2d,0xdd5d9d1d,0xfd7dbd3d, +0xc3438303,0xe363a323,0xd3539313,0xf373b333, +0xcb4b8b0b,0xeb6bab2b,0xdb5b9b1b,0xfb7bbb3b, +0xc7478707,0xe767a727,0xd7579717,0xf777b737, +0xcf4f8f0f,0xef6faf2f,0xdf5f9f1f,0xff7fbf3f, +0x1045a3e2,0x000000f4,0x263b7333,0x766b2363, +0x2b367e3e,0x7b662e6e,0x06db93d3,0x964b0343, +0x0bd69ede,0x9b460e4e,0x825f1757,0x12cf87c7, +0x8f521a5a,0x1fc28aca,0x00d199d9,0x90410949, +0x01d098d8,0x91400848,0x24357d3d,0x74652d6d, +0x25347c3c,0x75642c6c,0x04d59ddd,0x94450d4d, +0x05d49cdc,0x95440c4c,0x80511959,0x10c189c9, +0x81501858,0x11c088c8,0x02df97d7,0x924f0747, +0x0fd29ada,0x9f420a4a,0x865b1353,0x16cb83c3, +0x8b561e5e,0x1bc68ece,0xa6bbf3b3,0xf6eba3e3, +0xabb6febe,0xfbe6aeee,0x223f7737,0x726f2767, +0x2f327a3a,0x7f622a6a,0xa0b1f9b9,0xf0e1a9e9, +0xa1b0f8b8,0xf1e0a8e8,0x84551d5d,0x14c58dcd, +0x85541c5c,0x15c48ccc,0xa4b5fdbd,0xf4e5aded, +0xa5b4fcbc,0xf5e4acec,0x20317939,0x70612969, +0x21307838,0x71602868,0xa2bff7b7,0xf2efa7e7, +0xafb2faba,0xffe2aaea,0x00000000,0x00000000, + +}; + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/ls220/pcm_240.h linux.19rc3-ac4/drivers/media/video/ls220/pcm_240.h --- linux.19rc3/drivers/media/video/ls220/pcm_240.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/ls220/pcm_240.h 2002-07-29 13:58:41.000000000 +0100 @@ -0,0 +1,868 @@ +static u32 PCM240Ucode1f1800[] = { + 0xb500000f, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xb50001fb, 0x00000000, 0x00000000, 0x00000000, + 0x820f001f, 0x802f001f, 0x029f9014, 0x829efef0, + 0x8286000f, 0x02bf0054, 0x82bcfef4, 0x82a6000e, + 0x80074000, 0x001f6193, 0x8013001f, 0x9020c000, + 0x003fb006, 0x803effe8, 0x803effec, 0x9020fa00, + 0x803effd0, 0x803effdc, 0x803effd8, 0x9020fe00, + 0x803effd4, 0x90400000, 0x804600a2, 0x90421800, + 0x804600a3, 0x80132000, 0x98000040, 0x800600a6, + 0x80050080, 0x98000002, 0x80060080, 0x80070001, + 0x001f2013, 0x80070000, 0x001f23f9, 0x801e4b0c, + 0x001f210c, 0x80070001, 0x001f2324, 0x80070800, + 0x001f600f, 0x001fb0cb, 0x001fb010, 0x801efff0, + 0x98004000, 0x001f600e, 0x83e4011b, 0x80070000, + 0x801e4b14, 0x800500a0, 0xb0000001, 0xb4000009, + 0x80070001, 0x800600a0, 0x80050080, 0x98000020, + 0x80060080, 0x9400ffdf, 0x80060080, 0x80070000, + 0x800600a0, 0x80074000, 0x801e4b04, 0x81df0004, + 0x801bfff0, 0x00000000, 0x940000ff, 0xb0000000, + 0xb4200033, 0x003f400e, 0x94010010, 0xb0000000, + 0xb400fff7, 0x003f0013, 0xb0010001, 0xb420001f, + 0x803bffe8, 0x801bffec, 0x805b4b04, 0x00000000, + 0x3001b800, 0xb4600001, 0x9021a000, 0x0421b800, + 0x3001b802, 0xb460000d, 0x80050086, 0x005f9044, + 0x0420b802, 0xb00101e0, 0xb4a0ffe5, 0x001fb010, + 0x001f010c, 0xb0000001, 0xb400ffe1, 0x80070001, + 0x001f210c, 0x83e400e8, 0xb500ffdd, 0x8007001f, + 0x94000003, 0x5810b800, 0x83e719ec, 0x1bffb800, + 0x003f9008, 0x1821b800, 0x00ffb801, 0x80270000, + 0x003f2013, 0x8007001f, 0x94000003, 0x5810b800, + 0x83671a14, 0x1b7bb800, 0x003f9009, 0x1821b800, + 0x00ffb801, 0x80070000, 0x001f210c, 0xb500ffc8, + 0x003f400e, 0xb0000086, 0xb4400051, 0xb0000084, + 0xb400003b, 0xb0000085, 0xb4000041, 0xb0000086, + 0xb4000043, 0xb0000083, 0xb4000000, 0x815bff7c, + 0x00000000, 0x940a0080, 0x5c07b800, 0xb0000001, + 0xb400006f, 0x81674b18, 0x940a0007, 0x5803b800, + 0x116bb800, 0x005bb80b, 0x916b0004, 0x001bb80b, + 0x806500d4, 0x1463b800, 0x1863b802, 0x806600d4, + 0x80073c21, 0x801e4b00, 0x800600a1, 0x80074000, + 0x801e4b04, 0x8013001f, 0x98405000, 0x805effe0, + 0x005fb006, 0x805effe8, 0x805effec, 0x9042a000, + 0x805effe4, 0x9040fa00, 0x805effd0, 0x805effdc, + 0x805effd8, 0x9040fe00, 0x805effd4, 0x8013007f, + 0x9800ffff, 0x001fb040, 0x80070001, 0x001f2013, + 0x80070000, 0x001f2324, 0x001fb0cb, 0x001fb010, + 0x001fb041, 0x001fb042, 0x80073370, 0x001fb008, + 0x80071e40, 0x001fb009, 0x98214000, 0xb5000010, + 0x94011000, 0xb0001000, 0xb4200001, 0x9421efff, + 0x98210010, 0xb500000a, 0x80070000, 0x001fb0cb, + 0x83e40099, 0x003f400e, 0x9421ffef, 0xb5000004, + 0x83e40095, 0x003f400e, 0x98211000, 0x9421ffef, + 0x003f600e, 0x80070100, 0x801efff0, 0xb500ff74, + 0xb000008b, 0xb4000018, 0xb0000087, 0xb400ffee, + 0xb0000088, 0xb4000016, 0xb000008a, 0xb4000016, + 0xb000008c, 0xb4000017, 0xb0000089, 0xb4000019, + 0xb00000a0, 0xb400001b, 0xb00000a1, 0xb4000047, + 0xb00000a2, 0xb4000054, 0xb00000a3, 0xb400004c, + 0xb00000a4, 0xb4000056, 0xb00000a5, 0xb400005a, + 0xb00000a6, 0xb400005e, 0x803efff8, 0xb500ffe1, + 0x9421ffdf, 0xb500ffde, 0x80270100, 0x803efff8, + 0xb500ffdc, 0x803bffb0, 0x00000000, 0x003fb040, + 0xb500ffd8, 0x803bff80, 0x00000000, 0x003f6001, + 0xb500ffd4, 0x003f90ba, 0x803efff8, 0xb500ffd1, + 0x81674b18, 0x940a0007, 0x5803b800, 0x116bb800, + 0x005bb80b, 0x916b0004, 0x001bb80b, 0x806500d4, + 0x1463b800, 0x1863b802, 0x806600d4, 0x80130001, + 0x98003d21, 0x800600a1, 0x801e4b00, 0x80074000, + 0x801e4b04, 0x8013001f, 0x98405000, 0x805effe0, + 0x005fb006, 0x805effe8, 0x805effec, 0x9042a000, + 0x805effe4, 0x9040fa00, 0x805effd0, 0x805effdc, + 0x805effd8, 0x9040fe00, 0x805effd4, 0x80070001, + 0x001f2013, 0x80070000, 0x001f2324, 0x001fb0cb, + 0x001fb010, 0x80073b60, 0x001fb008, 0x80074350, + 0x001fb009, 0x98214000, 0xb500ffa5, 0x80270000, + 0x8047fef0, 0x003eb802, 0x90420004, 0x003eb802, + 0x90420004, 0x003eb802, 0x90420004, 0x003eb802, + 0x81df0000, 0x00000000, 0x00000000, 0x83640443, + 0x81df0004, 0xb500ff97, 0x81df0000, 0x00000000, + 0x00000000, 0x836403ed, 0x81df0004, 0xb500ff91, + 0x81df0000, 0x00000000, 0x00000000, 0x836403a8, + 0x81df0004, 0xb500ff8b, 0x81df0000, 0x00000000, + 0x00000000, 0x8344030b, 0x81df0004, 0xb500ff85, + 0x81df0000, 0x00000000, 0x00000000, 0x834402f0, + 0x81df0004, 0xb500ff7f, 0x80070000, 0x80470000, + 0x81df0000, 0x00000000, 0x00000000, 0xb6002003, + 0xb6003002, 0x001eb802, 0x90420004, 0x80171000, + 0x8057ffff, 0xb6002002, 0xb6001801, 0x001fa020, + 0x81df0004, 0x00ffb81f, 0x83a70000, 0x8057ffff, + 0x80770000, 0x8073007d, 0x98636d4a, 0x0207b803, + 0x81df0000, 0x00000000, 0x00000000, 0x80171000, + 0xb6000007, 0x003fc020, 0x005fc7e0, 0x40c1b810, + 0x4102b810, 0x001fe026, 0x001fe0a8, 0x4210b803, + 0x81df0004, 0x80270000, 0x003f2013, 0x8007001f, + 0x94000003, 0x5810b800, 0x83671e1c, 0x1b7bb800, + 0x003f9009, 0x1821b800, 0x00ffb801, 0x003f0013, + 0xb0010001, 0xb420fff3, 0x93bd0001, 0xb01d0004, + 0xb480ffe3, 0x00ffb81f, 0x00000000, 0x00000000, + 0x003f03f9, 0x009f0324, 0x84840001, 0xb0010000, + 0xb4000011, 0x815b4b0c, 0x81070000, 0x81270bf4, + 0xb00a0000, 0xb4000002, 0x81070c00, 0x812717f4, + 0x802500a5, 0x806500a5, 0x3001b803, 0xb420fffc, + 0x9421ffff, 0x3001b808, 0xb480000b, 0x3001b809, + 0xb4a00060, 0xb5000008, 0xb0040000, 0xb4200003, + 0x802717ff, 0x81470000, 0xb5000003, 0x80270001, + 0x003f23f9, 0x81470c00, 0xb0040000, 0xb4200006, + 0x039f4193, 0x5b81b81c, 0x003f90cb, 0x1021b81c, + 0x003fb0cb, 0x83840266, 0x829bff80, 0x801300e0, + 0x1434b800, 0x5c35b801, 0x8013001f, 0x1454b800, + 0x5c50b802, 0x8073007f, 0x9863ffff, 0xb002000f, + 0xb4800001, 0x90210001, 0x84210004, 0xb0010000, + 0xb4a00001, 0x6861b803, 0x005f9040, 0x4082b803, + 0x80af001f, 0x808f0000, 0x806f0000, 0x8007ffff, + 0x8033ffff, 0x80171000, 0x81df0000, 0x00000000, + 0x00000000, 0xb6001811, 0xb6002010, 0x14618000, + 0x6068b803, 0x40c4b803, 0x14608000, 0x00c8b806, + 0x5870b803, 0x6068b803, 0x4104b803, 0x58c8b806, + 0x0108b808, 0x14c6b801, 0x00000000, 0x00000000, + 0x5d08b808, 0x1508b800, 0x1806a028, 0x81df0004, + 0x80670400, 0x5d22b80a, 0x81df0000, 0x00000000, + 0x00000000, 0xb600180a, 0x00cfb803, 0x013fb0bc, + 0x5922b809, 0x01afb809, 0x013f90bc, 0x0047b86f, + 0xb0020001, 0xb4c0fffd, 0x90630020, 0x91290020, + 0x81df0004, 0x808f0000, 0x801b4b14, 0x80270001, + 0xb0000001, 0xb4000002, 0x802600a0, 0x803e4b14, + 0x81270c00, 0xb00a0000, 0xb4000001, 0x81270000, + 0x813e4b0c, 0x80270001, 0x003f2013, 0x80050086, + 0x001fb044, 0x00ffb81b, 0x00000000, 0x00000000, + 0x029fb00a, 0x02bfb00b, 0x02dfb00c, 0x02ffb00d, + 0x031fb00e, 0x033fb00f, 0x033f400f, 0x0287b86f, + 0x029fb005, 0x8285009d, 0x82b30002, 0x9ab50040, + 0x1a94b815, 0x8286009d, 0x8285009c, 0x96b48000, + 0xb0158000, 0xb400019c, 0x96b40100, 0xb0150100, + 0xb40001b8, 0x96b40400, 0xb0150400, 0xb40001ca, + 0x96b40001, 0xb0150001, 0xb4000014, 0x96b40008, + 0xb0150008, 0xb40001a5, 0x96b44000, 0xb0154000, + 0xb40001c9, 0x96b40002, 0xb0150002, 0xb4000169, + 0x96b40040, 0xb0150040, 0xb40001dc, 0x82d30002, + 0x9ad60000, 0x16b6b814, 0x3015b816, 0xb40001da, + 0x00000000, 0x00000000, 0xb50001db, 0x02bf9017, + 0x92b50001, 0x02bfb017, 0x82850082, 0x83050081, + 0x82a5009a, 0x96b50001, 0xb0150001, 0xb4200014, + 0x82a70000, 0x02bfb017, 0x96b41840, 0xb0150800, + 0xb420000c, 0x96b40008, 0x5aa9b815, 0x96d46000, + 0x5ec3b816, 0x82f3000f, 0x9af7c00f, 0x1718b817, + 0x1ab5b818, 0x1ab5b816, 0x9ab50340, 0x82a60081, + 0xb5000140, 0x9b180180, 0x83060081, 0xb500013d, + 0x82a5009a, 0x96b50002, 0xb0150002, 0xb420001b, + 0x82a70000, 0x02bfb017, 0x96b41800, 0xb0151800, + 0xb4000013, 0x96b40040, 0xb0150040, 0xb4200004, + 0xa3180c00, 0x9b180340, 0x83060081, 0xb500012d, + 0x96b40008, 0x5aa9b815, 0x96d46000, 0x5ec3b816, + 0x82f3000f, 0x9af7c00f, 0x1718b817, 0x1ab5b818, + 0x1ab5b816, 0x9ab50340, 0x82a60081, 0xb5000121, + 0x9b180180, 0x83060081, 0xb500011e, 0x82a500c1, + 0x96b5000f, 0xb015000b, 0xb420000e, 0x96b40020, + 0xb0150020, 0xb400000b, 0x96b40200, 0xb0150200, + 0xb4000008, 0x82c50086, 0x82e50094, 0x3016b817, + 0xb4400004, 0x06f7b816, 0xb017ff00, 0xb4400001, + 0xb500010c, 0x96b46000, 0xb0156000, 0xb4000011, + 0x96b41820, 0xb0150820, 0xb4200004, 0x9b391000, + 0x82a5009a, 0x96b5feff, 0x82a6009a, 0x96b40040, + 0xb0150040, 0xb4200001, 0x9739efff, 0x96b91000, + 0xb0151000, 0xb4200003, 0x82a5009a, 0x9ab50100, + 0x82a6009a, 0x96b40040, 0xb0150040, 0xb4200019, + 0x96b41800, 0xb0151800, 0xb4200006, 0x96b98000, + 0xb0158000, 0xb4200003, 0x9b180180, 0x83060081, + 0xb50000ec, 0x96d80c00, 0x82b300ff, 0x9ab5f3ff, + 0x1718b815, 0xb0160c00, 0xb4000007, 0x82e50098, + 0x96f70400, 0xb0170400, 0xb4200002, 0x82c70c00, + 0xb5000001, 0xa2d60c00, 0x1b18b816, 0x9b180340, + 0xb50000d2, 0x96b40220, 0xb0150000, 0xb4e00033, + 0x82a5009d, 0x82f3ffff, 0x16b5b817, 0x82f33802, + 0x3015b817, 0xb420002d, 0x96f98000, 0xb0178000, + 0xb400002a, 0x82a70000, 0x02bfb017, 0x82c50081, + 0x9ab60020, 0x82a60081, 0x82a50086, 0x92b50bb8, + 0x82a60094, 0x82c60081, 0x82c5009d, 0x96d6ffff, + 0x82b3c802, 0x9ab50041, 0x82e500c1, 0x96f7000f, + 0xb017000b, 0xb4000002, 0x82b38802, 0x9ab50041, + 0x1ab5b816, 0x82c5009a, 0x96d60020, 0xb0160020, + 0xb4200002, 0x82b3c802, 0x9ab50041, 0x82a6009d, + 0x02ff9017, 0x00000000, 0xb0170040, 0xb480000b, + 0x96f41c00, 0xb0171c00, 0xb4200008, 0x82e50086, + 0x82c50094, 0x92d63000, 0x3016b817, 0xb4400003, + 0x9b180180, 0x83060081, 0xb50000a6, 0x5eb5b814, + 0x96b500f0, 0x96f46000, 0x5eedb817, 0x1ab5b817, + 0xb0170003, 0xb4000004, 0x96b500ef, 0x96f70001, + 0x5ae4b817, 0x1ab5b817, 0x96d41800, 0xb0161800, + 0xb400000a, 0x96f900ff, 0x96b500ff, 0x9739ff00, + 0x1b39b815, 0x02a7b817, 0x96b500f3, 0x96d40008, + 0x5ec1b816, 0x1ab5b816, 0xb500000c, 0x96f98000, + 0xb0178000, 0xb4200007, 0x5efeb814, 0x96f70001, + 0xb0170001, 0xb4000003, 0x9b180180, 0x83060081, + 0xb5000084, 0x96b500f3, 0x9ab50008, 0x9739fff3, + 0x96d40020, 0xb0160020, 0xb4200017, 0x9b398000, + 0x82c70000, 0x02dfb017, 0x96d40010, 0x5ac8b816, + 0x82f300ff, 0x9af7cfff, 0x1718b817, 0x1b18b816, + 0x9b180340, 0x82c5009d, 0x96d6ffff, 0x82f33802, + 0x9af70041, 0x1af7b816, 0x82c5009a, 0x96d60020, + 0xb0160020, 0xb4200002, 0x82f3c802, 0x9af70041, + 0x82e6009d, 0xb500005d, 0x97397fff, 0x96b500ff, + 0x5aaab815, 0x82f300fc, 0x9af703ff, 0x1718b817, + 0x1b18b815, 0x9b180340, 0x82c5009a, 0x96d60010, + 0xb0160010, 0xb4200024, 0x82c70000, 0x02dfb017, + 0x82c50086, 0x92d60bb8, 0x82c60086, 0x82c50094, + 0x5eefb818, 0x96f70003, 0xb0170003, 0xb4200002, + 0x82e70bb8, 0xb5000001, 0x82e70bb8, 0x12d6b817, + 0x82e50081, 0x9af70020, 0x82e60081, 0x82c60094, + 0xa2f70020, 0x82e60081, 0x82f30001, 0x16f7b818, + 0x5ef0b817, 0xb0170001, 0xb4000004, 0x96f84000, + 0x5ee4b817, 0x9718f3ff, 0x1b18b817, 0x82f32802, + 0x9af70040, 0x82e6009d, 0x83060081, 0x83070001, + 0x8306009f, 0xb50000b8, 0x82c5009d, 0x82f33802, + 0x9af70041, 0x3016b817, 0xb420000f, 0x82b3c802, + 0x9ab50041, 0x82e500c1, 0x96f7000f, 0xb017000b, + 0xb4000002, 0x82b38802, 0x9ab50041, 0x82c5009a, + 0x96d60020, 0xb0160020, 0xb4200002, 0x82b3c802, + 0x9ab50041, 0x82a6009d, 0x82c5009a, 0x96d60080, + 0xb0160080, 0xb4000014, 0x02df9017, 0x00000000, + 0xb0160010, 0xb4800010, 0x82c500c1, 0x96d6000f, + 0xb016000b, 0xb400000c, 0x82c50087, 0x96d60080, + 0x5ac7b816, 0x82c50098, 0x96d60800, 0x5ac3b816, + 0x96f84000, 0x3017b816, 0xb4200003, 0x033f400f, + 0x9b394000, 0xb500000b, 0x9739bfff, 0x82e50061, + 0x96f70008, 0xb0170008, 0xb4000005, 0x5eefb818, + 0x96f70003, 0xb0170003, 0xb4000001, 0x9718ffff, + 0x83060081, 0x83070001, 0x8306009f, 0x00000000, + 0xb500007d, 0x82850083, 0x96b400ff, 0xb015003c, + 0xb4200019, 0x96b92000, 0xb0152000, 0xb4000002, + 0x9b392000, 0xb5000014, 0x9739d3ff, 0x82870000, + 0x82860087, 0x82870008, 0x82860083, 0x829bff78, + 0x82a7001f, 0xb0140400, 0xb4000001, 0x82a70010, + 0x82a600c9, 0x829bff78, 0x00000000, 0x828600cb, + 0x8285009d, 0x82b3ffff, 0x9ab5fffd, 0x1694b815, + 0x8286009d, 0xb5000000, 0x83070002, 0x8306009f, + 0x00000000, 0xb500005c, 0x96b90800, 0xb0150800, + 0xb4200009, 0x9739f7ff, 0x82a703fd, 0x82a600cb, + 0x82a7003c, 0x82a60083, 0x8285009d, 0x9a940002, + 0x8286009d, 0xb5000004, 0x82850087, 0x5a82b814, + 0xa2940200, 0x82860087, 0xb5000000, 0x83078000, + 0x8306009f, 0x00000000, 0xb5000047, 0x82850086, + 0x82a50094, 0x3015b814, 0xb4800002, 0x86b50bb8, + 0x82a60086, 0x83070008, 0x8306009f, 0x00000000, + 0xb500003d, 0x83050069, 0x9718003f, 0x82e50064, + 0x12f7b818, 0x86f70088, 0x82feff74, 0x02e7b86f, + 0x9af74000, 0x01ffb817, 0x96f7bfff, 0x01ffb817, + 0x83050081, 0x82f3001c, 0x9af703ff, 0x1718b817, + 0x9b180140, 0x83060081, 0x83070100, 0x8306009f, + 0x00000000, 0xb5000028, 0x83070000, 0x83050081, + 0x9b180180, 0x83060081, 0x83070400, 0x8306009f, + 0x00000000, 0xb5000020, 0x82870000, 0x82850082, + 0x5eb7b814, 0x96b500fc, 0x96d40006, 0x5ec1b816, + 0x1ab5b816, 0x5aacb815, 0x83050081, 0x82d3001c, + 0x9ad600ff, 0x1718b816, 0x1b18b815, 0x9b180e00, + 0x83060081, 0x83074000, 0x8306009f, 0x8305009d, + 0x82d3ffff, 0x9ad6bfff, 0x1718b816, 0x8306009d, + 0x00000000, 0xb5000008, 0xb5000007, 0x83070040, + 0x8306009f, 0xb5000004, 0x83130002, 0x9b180000, + 0x8306009f, 0xb5000000, 0x029f9005, 0x01ffb814, + 0x033f600f, 0x029f900a, 0x02bf900b, 0x02df900c, + 0x02ff900d, 0x031f900e, 0x033f900f, 0x00ffb81e, + 0x02ff9010, 0x92f70b43, 0x02ffb010, 0x02ff90cb, + 0x82bbffdc, 0x829bffd8, 0x93150004, 0x3014b815, + 0xb4000010, 0x02dbb818, 0x029bb815, 0x3017b816, + 0xb480000c, 0x5a81b814, 0x029fb010, 0x82860095, + 0x8293001f, 0x9294fe00, 0x92b50008, 0x3015b814, + 0xb4800002, 0x82b3001f, 0x92b5fa00, 0x82beffdc, + 0xb500ffeb, 0x029f9010, 0x83250094, 0x06d4b819, + 0x02d6b816, 0xb016ffff, 0xb4a0000a, 0x82933802, + 0x9a940041, 0x82c5009d, 0x96d6ffff, 0x1a94b816, + 0x82c5009a, 0x96d60010, 0xb0160010, 0xb4000001, + 0x8286009d, 0x00ffb81c, 0x00000000, 0x00000000, + 0x001f9012, 0x001fb100, 0x001f004c, 0x001f2404, + 0x801bfef0, 0x8058fef4, 0x803bff68, 0x8078ff6c, + 0x2000b801, 0x2042b803, 0x001fb104, 0x005f2414, + 0x82e70001, 0x83640048, 0x029fb014, 0x829efef0, + 0x8286000f, 0x02bf2054, 0x82bcfef4, 0x82a6000e, + 0x00ffb81a, 0x80e70001, 0x801336e3, 0x9800eb76, + 0x001fb100, 0x800700ab, 0x001f2404, 0x801bc3e8, + 0x8058c3ec, 0x83640024, 0x82e70000, 0x83640036, + 0x029fb300, 0x029fb100, 0x02bf2c04, 0x02bf2404, + 0x801bc000, 0x8058c004, 0x8364001b, 0x82e70000, + 0x8364002d, 0x001f9300, 0x3000b814, 0xb420000a, + 0x001f0c04, 0x3000b815, 0xb4200007, 0x829efef0, + 0x82bcfef4, 0x029fb012, 0x02bf204c, 0x82870001, + 0x829cfef5, 0x00ffb81a, 0xb0070000, 0xb4000007, + 0x80e70000, 0x801399fa, 0x9800c92e, 0x001fb100, + 0x800700af, 0x001f2404, 0xb500ffdc, 0x82870000, + 0x829cfef5, 0x00ffb81a, 0x80c700ff, 0x803bff68, + 0x8078ff6c, 0x14a0b806, 0x2063b805, 0x007f2414, + 0x2021b802, 0x58c8b806, 0x14a0b806, 0x58b0b805, + 0x2021b805, 0x58c8b806, 0x14a0b806, 0x2021b805, + 0x58c8b806, 0x14a0b806, 0x5cb0b805, 0x2021b805, + 0x003fb104, 0x00ffb81b, 0x82c70000, 0x83070400, + 0x83270005, 0x8197040c, 0x81d7ffff, 0x83840126, + 0x83840001, 0x00ffb81b, 0x808f0000, 0x806f001f, + 0x80af001f, 0x80270140, 0x81e70228, 0x5de2b80f, + 0xb6000208, 0x00cfb801, 0x01ffb0bc, 0x59e2b80f, + 0x01cfb80f, 0x01ff90bc, 0xb520ffff, 0x91ef0020, + 0x90210020, 0x80270180, 0x81e70120, 0x5de2b80f, + 0xb6000208, 0x00cfb801, 0x01ffb0bc, 0x59e2b80f, + 0x01cfb80f, 0x01ff90bc, 0xb520ffff, 0x91ef0020, + 0x90210020, 0x8057ffff, 0x80170430, 0x80070410, + 0x80270408, 0xb6000509, 0x005ff000, 0x90420500, + 0x007ff001, 0x90630600, 0x009ff002, 0x00bff003, + 0x2004a025, 0x90000001, 0x90210001, 0x80070414, + 0x80d7ffff, 0x8097045c, 0x8017043c, 0xb6000404, + 0x005ff000, 0x007f87e0, 0x84000001, 0x2082a7e3, + 0x80970460, 0x80170440, 0x2082b803, 0x007f8000, + 0x2083a004, 0x80170430, 0x80970450, 0x80270408, + 0xb6000508, 0x005f8024, 0x90420500, 0x007ff001, + 0x90630600, 0x009ff002, 0x00bff003, 0x2004a025, + 0x90210001, 0x80170440, 0x00000000, 0x02bf87e0, + 0x80970460, 0x82870000, 0xb6000404, 0x005f87e4, + 0x5a88b814, 0x204287e0, 0x1a94b802, 0x00ffb81c, + 0x001f0a49, 0x001f2709, 0x001f0a41, 0x001f2708, + 0x001f0a46, 0x001f2707, 0x001f0a48, 0x001f2706, + 0x001f0a42, 0x001f2705, 0x001f0a47, 0x001f2704, + 0x001f0a45, 0x001f2703, 0x001f0a43, 0x001f2702, + 0x001f0a40, 0x001f2701, 0x001f0a44, 0x001f2700, + 0x001f0c25, 0xa020000c, 0x94400001, 0x94600002, + 0x94810004, 0x94a10008, 0x94c00010, 0x5943b802, + 0x5861b803, 0x5882b804, 0x5ca2b805, 0x5cc4b806, + 0x194ab803, 0x194ab804, 0x194ab805, 0x194ab806, + 0x015f2738, 0x801b0220, 0x003f91c1, 0x5c28b801, + 0x005f91c2, 0x5858b802, 0x1821b802, 0x2000b801, + 0x001fb1c4, 0x80180224, 0x003f0709, 0x2000b801, + 0x001f2714, 0x82c70001, 0x82e70001, 0x83070710, + 0x8327001e, 0x81970735, 0x8384009f, 0x02df0738, + 0x82170a30, 0x838400f1, 0x819efef0, 0x817cfef4, + 0x819eff68, 0x817cff6c, 0x00ffb81b, 0x820f001f, + 0x8018fef8, 0x8057ffff, 0x001f2709, 0x8018fef6, + 0x80d7ffff, 0x001f2708, 0x8018fefa, 0x8157ffff, + 0x001f2707, 0x8018fefd, 0x81d7ffff, 0x001f2706, + 0x8018fefb, 0x802f001f, 0x001f2705, 0x8018fefe, + 0x00000000, 0x001f2704, 0x8018fef9, 0x00000000, + 0x001f2703, 0x8018feff, 0x00000000, 0x001f2702, + 0x8018fef7, 0x00000000, 0x001f2701, 0x8018fefc, + 0x00000000, 0x001f2700, 0x001f0c25, 0xa0200011, + 0x94410001, 0x94600002, 0x94800004, 0x94a00008, + 0x94c10010, 0x5941b802, 0x5861b803, 0x5c82b804, + 0x58a1b805, 0x5cc1b806, 0x194ab803, 0x194ab804, + 0x194ab805, 0x194ab806, 0x015f2738, 0x801b0220, + 0x003f91c1, 0x5c28b801, 0x005f91c2, 0x5858b802, + 0x1821b802, 0x2000b801, 0x001fb1c4, 0x80180224, + 0x003f0709, 0x2000b801, 0x001f2714, 0x82c70001, + 0x82e70001, 0x83070710, 0x8327001e, 0x81970735, + 0x83840055, 0x02df0738, 0x82170a20, 0x838400a7, + 0x819efef0, 0x817cfef4, 0x5ac8b80c, 0x02ff0a44, + 0x1ad6b817, 0x02dfb291, 0x5ed8b80c, 0x5968b80b, + 0x1ad6b80b, 0x02df6524, 0x00ffb81b, 0x820f001f, + 0x8018fefe, 0x8057ffff, 0x001f2709, 0x8018fefa, + 0x80d7ffff, 0x001f2708, 0x8018fefc, 0x8157ffff, + 0x001f2707, 0x8018feff, 0x81d7ffff, 0x001f2706, + 0x8018fef8, 0x802f001f, 0x001f2705, 0x8018fefb, + 0x00000000, 0x001f2704, 0x8018fefd, 0x00000000, + 0x001f2703, 0x8018fef6, 0x00000000, 0x001f2702, + 0x8018fef9, 0x00000000, 0x001f2701, 0x8018fef7, + 0x00000000, 0x001f2700, 0x801b0220, 0x003f91c1, + 0x5c28b801, 0x005f91c2, 0x5858b802, 0x1821b802, + 0x2000b801, 0x001fb1c4, 0x80180224, 0x003f0709, + 0x2000b801, 0x001f2714, 0x82c70001, 0x82e70001, + 0x83070710, 0x8327001e, 0x81970735, 0x83840016, + 0x83270000, 0x831bfef0, 0x82f8fef4, 0x02c7b819, + 0x82170a28, 0x83840065, 0x300cb818, 0xb4200002, + 0x300bb817, 0xb4000006, 0x93390001, 0xb0190020, + 0xb480fff6, 0x83270000, 0x833cfef5, 0x00ffb81b, + 0x019fb290, 0x017f2a44, 0x033f2c25, 0x83270001, + 0x833cfef5, 0x00ffb81b, 0x0007b818, 0x90000003, + 0x00000000, 0x015ff000, 0x90000001, 0x5949b80a, + 0x013ff000, 0x194ab809, 0x84000002, 0x994a0100, + 0x017ff000, 0x958b00f8, 0x5981b80c, 0x956b0007, + 0x198cb80b, 0x84000002, 0x998c0008, 0x017ff000, + 0x90000001, 0x5971b80b, 0x198cb80b, 0x017ff000, + 0x5969b80b, 0x198cb80b, 0x81a70000, 0x94d90003, + 0x82a70000, 0xb6260019, 0xb6000818, 0x5df0b80a, + 0x5e02b80a, 0x21efb810, 0x95ef0001, 0x5941b80a, + 0x194ab80f, 0x21efb816, 0x5e18b80c, 0x5e35b80c, + 0x5e54b80c, 0x5e6cb80c, 0x2210b811, 0x2252b813, + 0x2210b812, 0x96100001, 0x5981b80c, 0x198cb810, + 0x2210b817, 0x10afb810, 0x10a5b80d, 0x5da1b805, + 0x94a50001, 0x5aa1b815, 0x1ab5b805, 0x019fa7f5, + 0x5cc2b819, 0xb626001c, 0x82870000, 0xb6000419, + 0xb6000818, 0x5df0b80a, 0x5e02b80a, 0x21efb810, + 0x95ef0001, 0x5941b80a, 0x194ab80f, 0x21efb816, + 0x5e18b80c, 0x5e35b80c, 0x5e54b80c, 0x5e6cb80c, + 0x2210b811, 0x2252b813, 0x2210b812, 0x96100001, + 0x5981b80c, 0x198cb810, 0x2210b817, 0x10afb810, + 0x10a5b80d, 0x5da1b805, 0x94a50001, 0x5a81b814, + 0x1a94b805, 0x019fa7f4, 0x00ffb81c, 0x8257ffff, + 0x808f0000, 0x806f001f, 0x80af001f, 0x80270200, + 0x81e7ff00, 0x5de2b80f, 0xb6000208, 0x00cfb801, + 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, 0x01ff90bc, + 0xb520ffff, 0x91ef0020, 0x90210020, 0x80270240, + 0x81e70000, 0x5de2b80f, 0xb6000208, 0x00cfb801, + 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, 0x01ff90bc, + 0xb520ffff, 0x91ef0020, 0x90210020, 0x80270180, + 0x81e70120, 0x5de2b80f, 0xb6000208, 0x00cfb801, + 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, 0x01ff90bc, + 0xb520ffff, 0x91ef0020, 0x90210020, 0x806f0007, + 0x80af0007, 0x80270280, 0x81e70100, 0x5de2b80f, + 0x00cfb801, 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, + 0x01ff90bc, 0xb520ffff, 0x91ef0020, 0x90210020, + 0x80170760, 0x001f0700, 0x001fa020, 0x001f0701, + 0x001fa020, 0x001f0702, 0x001fa020, 0x001f0703, + 0x001fa020, 0x001f0704, 0x001fa000, 0x80970750, + 0x81170770, 0x82a70735, 0x83a40060, 0x001f87e4, + 0xb6000405, 0x86b50001, 0x83a4005c, 0x001f8004, + 0x003f87e8, 0x2080a7e1, 0x80970770, 0x80170750, + 0x81170750, 0x81970740, 0x82a70730, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a40050, 0x001f87e4, + 0xb6000405, 0x86b50001, 0x83a4004c, 0x001f8004, + 0x003f87e8, 0x2080a7e1, 0x80970750, 0x80170770, + 0x81170770, 0x81970760, 0x82a7072b, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a40040, 0x83a4004e, + 0xb6000407, 0x86b50001, 0x83a4003c, 0x001f8004, + 0x003f87e8, 0x2080a001, 0x83a40047, 0x00000000, + 0x80970770, 0x80170750, 0x81170750, 0x81970740, + 0x82a70726, 0x001f800c, 0x003f8008, 0x2100a001, + 0x83a4002e, 0x83a4003c, 0xb6000407, 0x86b50001, + 0x83a4002a, 0x001f8004, 0x003f87e8, 0x2080a001, + 0x83a40035, 0x00000000, 0x80970750, 0x80170770, + 0x81170770, 0x81970760, 0x82a70721, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a4001c, 0x001f87e4, + 0xb6000405, 0x86b50001, 0x83a40018, 0x001f8004, + 0x003f87e8, 0x2080a7e1, 0x80970770, 0x80170750, + 0x81170750, 0x81970740, 0x82a7071c, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a4000c, 0x017f87e4, + 0x81870000, 0xb6000406, 0x86b50001, 0x83a40007, + 0x001f87e4, 0x200087e8, 0x5988b80c, 0x198cb800, + 0x021fa02c, 0x021fa00b, 0x00ffb81c, 0x005ff015, + 0x90420600, 0x003f87e0, 0x001ff002, 0x2060b801, + 0x90630800, 0x90960a00, 0x001ff003, 0x003ff004, + 0x20a0b801, 0x90a50900, 0x00000000, 0x001ff005, + 0x009fa000, 0x00ffb81d, 0x001f8004, 0x5c21b800, + 0x5847b800, 0x1821b802, 0x942100ff, 0x2080a7e1, + 0x00ffb81d, 0x00000000, 0x00000000, 0x00000000, + 0x829bff80, 0x80af001f, 0x808f0000, 0x806f0000, + 0x82bbffec, 0x82fbffe4, 0x00000000, 0x82beffb8, + 0x95540700, 0x5d48b80a, 0x914a0001, 0x0227b80a, + 0x94343000, 0x5c2cb801, 0xb0010000, 0xb4000001, + 0x5a21b811, 0x9574c000, 0x5d6eb80b, 0x918b4b08, + 0x01b8b80c, 0x96d5ffff, 0x5ec2b816, 0x96f7ffff, + 0x5ee2b817, 0x8057ffff, 0x80d7ffff, 0x8157ffff, + 0x81d7ffff, 0x81f3ff00, 0x99efff00, 0x821300ff, + 0x9a1000ff, 0x81971000, 0x82670000, 0x82470000, + 0x80270280, 0x81df0000, 0x00000000, 0x00000000, + 0xb62d000d, 0x3016b817, 0xb4800001, 0x86d62800, + 0x00cfb801, 0x02dfb0bc, 0x5ac2b816, 0x01cfb816, + 0x02df90bc, 0x0067b86f, 0xb0030001, 0xb4c0fffd, + 0x92d60020, 0x90210020, 0x81df0004, 0x80170a00, + 0x81df0000, 0x00000000, 0x00000000, 0xb62d0006, + 0xb6002005, 0x146f8000, 0x14908000, 0x5c68b803, + 0x5888b804, 0x1803a024, 0x81df0004, 0x80170a00, + 0x80970d00, 0xb00b0000, 0xb4000004, 0xb00b0001, + 0xb400000a, 0xb00b0002, 0xb4000027, 0x81df0000, + 0x00000000, 0x00000000, 0xb6008002, 0x007f8020, + 0x009fa023, 0x81df0004, 0xb5000029, 0x80d3ffff, + 0x81df0000, 0x00000000, 0x00000000, 0xb6002018, + 0x5c648000, 0x9463ffff, 0x5c888020, 0x58b88000, + 0x1884b805, 0x1484b806, 0x1883a024, 0x5c6c8020, + 0x9463ffff, 0x58908000, 0x1883a024, 0x5c748020, + 0x588c8000, 0x1863b804, 0x9463ffff, 0x58888000, + 0x1484b806, 0x1883a024, 0x5c7c8020, 0x58848000, + 0x1863b804, 0x9463ffff, 0x14868020, 0x1883a024, + 0x81df0004, 0xb500000a, 0x80d3ffff, 0x81df0000, + 0x00000000, 0x00000000, 0xb6004004, 0x007f8020, + 0x009fa023, 0x007f8040, 0x009fa023, 0x81df0004, + 0x00000000, 0x81170d00, 0x80070000, 0x94343000, + 0x5c2cb801, 0xb0010001, 0xb400008e, 0xb00a0001, + 0xb400000e, 0xb00a0002, 0xb400001c, 0xb00a0003, + 0xb4000024, 0xb00a0004, 0xb4000052, 0xb00a0005, + 0xb400005b, 0xb00a0006, 0xb400007f, 0xb00a0007, + 0xb400007d, 0xb00a0008, 0xb400007b, 0x81df0000, + 0x00000000, 0x00000000, 0xb600800a, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x019fa020, 0x019fa020, + 0x5c708028, 0x9463ffff, 0x019fa023, 0x019fa020, + 0x019fa020, 0x81df0004, 0xb500006b, 0x81df0000, + 0x00000000, 0x00000000, 0xb6008004, 0x007f8028, + 0x019fa023, 0x019fa020, 0x019fa020, 0x81df0004, + 0xb5000061, 0xb0130000, 0xb4000004, 0xb0130001, + 0xb4000009, 0xb0130002, 0xb400001a, 0x83a400fa, + 0x80170f00, 0x007f8028, 0x001fa023, 0x007f8028, + 0x001fa023, 0xb5000054, 0x80170f00, 0x00000000, + 0x007f8020, 0x019fa023, 0x007f8000, 0x9463ffff, + 0x019fa023, 0x019fa020, 0x5c708020, 0x58908008, + 0x1983a024, 0x5c708028, 0x019fa023, 0x019fa020, + 0x83a400e5, 0x80170f00, 0x007f8028, 0x001fa023, + 0xb5000041, 0x80170f00, 0x00000000, 0x007f8020, + 0x019fa023, 0x007f8008, 0x9463ffff, 0x019fa023, + 0x019fa020, 0x5c708028, 0x58908008, 0x1983a024, + 0x5c708028, 0x019fa023, 0x019fa020, 0x83a400d2, + 0xb5000031, 0x81df0000, 0x00000000, 0x00000000, + 0xb6004005, 0x007f8008, 0x019fa023, 0x007f8008, + 0x019fa023, 0x019fa020, 0x81df0004, 0xb5000026, + 0xb0130000, 0xb4000008, 0xb0130001, 0xb4000012, + 0xb0130002, 0xb400001f, 0xb0130003, 0xb400001d, + 0xb0130004, 0xb400001b, 0x83a400cd, 0x007f8028, + 0x019fa023, 0x007f8028, 0x019fa023, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x80170f00, 0x007f8028, + 0x001fa023, 0xb5000010, 0x80170f00, 0x00000000, + 0x5c708020, 0x58908008, 0x1983a024, 0x5c708028, + 0x58908008, 0x1983a024, 0x5c708028, 0x019fa023, + 0x83a400b7, 0x80170f00, 0x007f8028, 0x001fa023, + 0xb5000001, 0xb5000000, 0x00000000, 0x00000000, + 0xb5000086, 0xb00a0001, 0xb400000e, 0xb00a0002, + 0xb4000017, 0xb00a0003, 0xb400001f, 0xb00a0004, + 0xb400004d, 0xb00a0005, 0xb4000056, 0xb00a0006, + 0xb400007a, 0xb00a0007, 0xb4000078, 0xb00a0008, + 0xb4000076, 0x81df0000, 0x00000000, 0x00000000, + 0xb6008005, 0x007f8028, 0x9463ffff, 0x019fa023, + 0x019fa020, 0x019fa020, 0x81df0004, 0xb500006b, + 0x81df0000, 0x00000000, 0x00000000, 0xb6004004, + 0x007f8048, 0x019fa023, 0x019fa020, 0x019fa020, + 0x81df0004, 0xb5000061, 0xb0130000, 0xb4000004, + 0xb0130001, 0xb4000009, 0xb0130002, 0xb400001a, + 0x83a40098, 0x80170f00, 0x007f8028, 0x001fa023, + 0x007f8028, 0x001fa023, 0xb5000054, 0x80170f00, + 0x00000000, 0x007f8020, 0x019fa023, 0x007f8000, + 0x9463ffff, 0x019fa023, 0x019fa020, 0x5c708020, + 0x58908008, 0x1983a024, 0x5c708028, 0x019fa023, + 0x019fa020, 0x83a40083, 0x80170f00, 0x007f8028, + 0x001fa023, 0xb5000041, 0x80170f00, 0x00000000, + 0x007f8020, 0x019fa023, 0x007f8008, 0x9463ffff, + 0x019fa023, 0x019fa020, 0x5c708028, 0x58908008, + 0x1983a024, 0x5c708028, 0x019fa023, 0x019fa020, + 0x83a40070, 0xb5000031, 0x81df0000, 0x00000000, + 0x00000000, 0xb6004005, 0x007f8008, 0x019fa023, + 0x007f8008, 0x019fa023, 0x019fa020, 0x81df0004, + 0xb5000026, 0xb0130000, 0xb4000008, 0xb0130001, + 0xb4000012, 0xb0130002, 0xb400001f, 0xb0130003, + 0xb400001d, 0xb0130004, 0xb400001b, 0x83a4006b, + 0x007f8028, 0x019fa023, 0x007f8028, 0x019fa023, + 0x007f8008, 0x9463ffff, 0x019fa023, 0x80170f00, + 0x007f8028, 0x001fa023, 0xb5000010, 0x80170f00, + 0x00000000, 0x5c708020, 0x58908008, 0x1983a024, + 0x5c708028, 0x58908008, 0x1983a024, 0x5c708028, + 0x019fa023, 0x83a40055, 0x80170f00, 0x007f8028, + 0x001fa023, 0xb5000001, 0xb5000000, 0x92730001, + 0x92520001, 0x3012b811, 0xb480fe89, 0x003f0324, + 0x90210001, 0xb0010006, 0xb4a00001, 0x80270001, + 0x003f2324, 0x2c8db811, 0x803bffe0, 0x805bffe4, + 0x5887b804, 0x1015b804, 0xad440003, 0x3000b802, + 0xb4800001, 0x8400a000, 0x801effec, 0x015f6193, + 0x809e4b04, 0x00ffb81f, 0x81df0000, 0x00000000, + 0x00000000, 0xb6002a0c, 0x007f8028, 0x019fa023, + 0x007f8008, 0x9463ffff, 0x019fa023, 0x019fa020, + 0x5c708028, 0x58908008, 0x1983a024, 0x5c708028, + 0x019fa023, 0x019fa020, 0x81df0004, 0x00ffb81d, + 0x81df0000, 0x00000000, 0x00000000, 0xb600190f, + 0x007f8028, 0x019fa023, 0x007f8028, 0x019fa023, + 0x007f8008, 0x9463ffff, 0x019fa023, 0x5c708028, + 0x58908008, 0x1983a024, 0x5c708028, 0x58908008, + 0x1983a024, 0x5c708028, 0x019fa023, 0x81df0004, + 0x00ffb81d, 0x81df0000, 0x00000000, 0x00000000, + 0xb6002a0c, 0x007f8028, 0x019fa023, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x019fa020, 0x5c708028, + 0x58908008, 0x1983a024, 0x5c708028, 0x019fa023, + 0x019fa020, 0x81df0004, 0x00ffb81d, 0x81df0000, + 0x00000000, 0x00000000, 0xb600190f, 0x007f8028, + 0x019fa023, 0x007f8028, 0x019fa023, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x5c708028, 0x58908008, + 0x1983a024, 0x5c708028, 0x58908008, 0x1983a024, + 0x5c708028, 0x019fa023, 0x81df0004, 0x00ffb81d, + 0x829bff80, 0x80af001f, 0x808f0000, 0x806f0000, + 0x82bbffec, 0x82fbffe4, 0x00000000, 0x82beffb8, + 0x95540700, 0x5d48b80a, 0x914a0001, 0x0227b80a, + 0x94343000, 0x5c2cb801, 0xb0010000, 0xb4000001, + 0x5a21b811, 0x9574c000, 0x5d6eb80b, 0x918b4b08, + 0x01b8b80c, 0x96d5ffff, 0x5ec2b816, 0x96f7ffff, + 0x5ee2b817, 0x8057ffff, 0x80d7ffff, 0x8157ffff, + 0x81d7ffff, 0x81f3ff00, 0x99efff00, 0x821300ff, + 0x9a1000ff, 0x81971000, 0x82670000, 0x82470000, + 0x80270280, 0x81df0000, 0x00000000, 0x00000000, + 0xb62d000d, 0x3016b817, 0xb4800001, 0x86d62800, + 0x00cfb801, 0x02dfb0bc, 0x5ac2b816, 0x01cfb816, + 0x02df90bc, 0x0067b86f, 0xb0030001, 0xb4c0fffd, + 0x92d60020, 0x90210020, 0x81df0004, 0x80170a00, + 0x81df0000, 0x00000000, 0x00000000, 0xb62d0006, + 0xb6002005, 0x146f8000, 0x14908000, 0x5c68b803, + 0x5888b804, 0x1803a024, 0x81df0004, 0x80170a00, + 0x80970d00, 0xb00b0000, 0xb4000004, 0xb00b0001, + 0xb400000a, 0xb00b0002, 0xb4000027, 0x81df0000, + 0x00000000, 0x00000000, 0xb6008002, 0x007f8020, + 0x009fa023, 0x81df0004, 0xb5000029, 0x80d3ffff, + 0x81df0000, 0x00000000, 0x00000000, 0xb6002018, + 0x5c648000, 0x9463ffff, 0x5c888020, 0x58b88000, + 0x1884b805, 0x1484b806, 0x1883a024, 0x5c6c8020, + 0x9463ffff, 0x58908000, 0x1883a024, 0x5c748020, + 0x588c8000, 0x1863b804, 0x9463ffff, 0x58888000, + 0x1484b806, 0x1883a024, 0x5c7c8020, 0x58848000, + 0x1863b804, 0x9463ffff, 0x14868020, 0x1883a024, + 0x81df0004, 0xb500000a, 0x80d3ffff, 0x81df0000, + 0x00000000, 0x00000000, 0xb6004004, 0x007f8020, + 0x009fa023, 0x007f8040, 0x009fa023, 0x81df0004, + 0x00000000, 0x81170d00, 0x80070000, 0x94343000, + 0x5c2cb801, 0xb0010001, 0xb400008e, 0xb00a0001, + 0xb400000e, 0xb00a0002, 0xb400001c, 0xb00a0003, + 0xb4000024, 0xb00a0004, 0xb4000052, 0xb00a0005, + 0xb400005b, 0xb00a0006, 0xb400007f, 0xb00a0007, + 0xb400007d, 0xb00a0008, 0xb400007b, 0x81df0000, + 0x00000000, 0x00000000, 0xb600800a, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x019fa020, 0x019fa020, + 0x5c708028, 0x9463ffff, 0x019fa023, 0x019fa020, + 0x019fa020, 0x81df0004, 0xb500006b, 0x81df0000, + 0x00000000, 0x00000000, 0xb6008004, 0x007f8028, + 0x019fa023, 0x019fa020, 0x019fa020, 0x81df0004, + 0xb5000061, 0xb0130000, 0xb4000004, 0xb0130001, + 0xb4000009, 0xb0130002, 0xb400001a, 0x83a400fa, + 0x80170f00, 0x007f8028, 0x001fa023, 0x007f8028, + 0x001fa023, 0xb5000054, 0x80170f00, 0x00000000, + 0x007f8020, 0x019fa023, 0x007f8000, 0x9463ffff, + 0x019fa023, 0x019fa020, 0x5c708020, 0x58908008, + 0x1983a024, 0x5c708028, 0x019fa023, 0x019fa020, + 0x83a400e5, 0x80170f00, 0x007f8028, 0x001fa023, + 0xb5000041, 0x80170f00, 0x00000000, 0x007f8020, + 0x019fa023, 0x007f8008, 0x9463ffff, 0x019fa023, + 0x019fa020, 0x5c708028, 0x58908008, 0x1983a024, + 0x5c708028, 0x019fa023, 0x019fa020, 0x83a400d2, + 0xb5000031, 0x81df0000, 0x00000000, 0x00000000, + 0xb6004005, 0x007f8008, 0x019fa023, 0x007f8008, + 0x019fa023, 0x019fa020, 0x81df0004, 0xb5000026, + 0xb0130000, 0xb4000008, 0xb0130001, 0xb4000012, + 0xb0130002, 0xb400001f, 0xb0130003, 0xb400001d, + 0xb0130004, 0xb400001b, 0x83a400cd, 0x007f8028, + 0x019fa023, 0x007f8028, 0x019fa023, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x80170f00, 0x007f8028, + 0x001fa023, 0xb5000010, 0x80170f00, 0x00000000, + 0x5c708020, 0x58908008, 0x1983a024, 0x5c708028, + 0x58908008, 0x1983a024, 0x5c708028, 0x019fa023, + 0x83a400b7, 0x80170f00, 0x007f8028, 0x001fa023, + 0xb5000001, 0xb5000000, 0x00000000, 0x00000000, + 0xb5000086, 0xb00a0001, 0xb400000e, 0xb00a0002, + 0xb4000017, 0xb00a0003, 0xb400001f, 0xb00a0004, + 0xb400004d, 0xb00a0005, 0xb4000056, 0xb00a0006, + 0xb400007a, 0xb00a0007, 0xb4000078, 0xb00a0008, + 0xb4000076, 0x81df0000, 0x00000000, 0x00000000, + 0xb6008005, 0x007f8028, 0x9463ffff, 0x019fa023, + 0x019fa020, 0x019fa020, 0x81df0004, 0xb500006b, + 0x81df0000, 0x00000000, 0x00000000, 0xb6004004, + 0x007f8048, 0x019fa023, 0x019fa020, 0x019fa020, + 0x81df0004, 0xb5000061, 0xb0130000, 0xb4000004, + 0xb0130001, 0xb4000009, 0xb0130002, 0xb400001a, + 0x83a40098, 0x80170f00, 0x007f8028, 0x001fa023, + 0x007f8028, 0x001fa023, 0xb5000054, 0x80170f00, + 0x00000000, 0x007f8020, 0x019fa023, 0x007f8000, + 0x9463ffff, 0x019fa023, 0x019fa020, 0x5c708020, + 0x58908008, 0x1983a024, 0x5c708028, 0x019fa023, + 0x019fa020, 0x83a40083, 0x80170f00, 0x007f8028, + 0x001fa023, 0xb5000041, 0x80170f00, 0x00000000, + 0x007f8020, 0x019fa023, 0x007f8008, 0x9463ffff, + 0x019fa023, 0x019fa020, 0x5c708028, 0x58908008, + 0x1983a024, 0x5c708028, 0x019fa023, 0x019fa020, + 0x83a40070, 0xb5000031, 0x81df0000, 0x00000000, + 0x00000000, 0xb6004005, 0x007f8008, 0x019fa023, + 0x007f8008, 0x019fa023, 0x019fa020, 0x81df0004, + 0xb5000026, 0xb0130000, 0xb4000008, 0xb0130001, + 0xb4000012, 0xb0130002, 0xb400001f, 0xb0130003, + 0xb400001d, 0xb0130004, 0xb400001b, 0x83a4006b, + 0x007f8028, 0x019fa023, 0x007f8028, 0x019fa023, + 0x007f8008, 0x9463ffff, 0x019fa023, 0x80170f00, + 0x007f8028, 0x001fa023, 0xb5000010, 0x80170f00, + 0x00000000, 0x5c708020, 0x58908008, 0x1983a024, + 0x5c708028, 0x58908008, 0x1983a024, 0x5c708028, + 0x019fa023, 0x83a40055, 0x80170f00, 0x007f8028, + 0x001fa023, 0xb5000001, 0xb5000000, 0x92730001, + 0x92520001, 0x3012b811, 0xb480fe89, 0x003f0324, + 0x90210001, 0xb0010006, 0xb4a00001, 0x80270001, + 0x003f2324, 0x2c8db811, 0x803bffe0, 0x805bffe4, + 0x5887b804, 0x1015b804, 0xad440003, 0x3000b802, + 0xb4800001, 0x8400a000, 0x801effec, 0x015f6193, + 0x809e4b04, 0x00ffb81f, 0x81df0000, 0x00000000, + 0x00000000, 0xb6002a0c, 0x007f8028, 0x019fa023, + 0x007f8008, 0x9463ffff, 0x019fa023, 0x019fa020, + 0x5c708028, 0x58908008, 0x1983a024, 0x5c708028, + 0x019fa023, 0x019fa020, 0x81df0004, 0x00ffb81d, + 0x81df0000, 0x00000000, 0x00000000, 0xb600190f, + 0x007f8028, 0x019fa023, 0x007f8028, 0x019fa023, + 0x007f8008, 0x9463ffff, 0x019fa023, 0x5c708028, + 0x58908008, 0x1983a024, 0x5c708028, 0x58908008, + 0x1983a024, 0x5c708028, 0x019fa023, 0x81df0004, + 0x00ffb81d, 0x81df0000, 0x00000000, 0x00000000, + 0xb6002a0c, 0x007f8028, 0x019fa023, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x019fa020, 0x5c708028, + 0x58908008, 0x1983a024, 0x5c708028, 0x019fa023, + 0x019fa020, 0x81df0004, 0x00ffb81d, 0x81df0000, + 0x00000000, 0x00000000, 0xb600190f, 0x007f8028, + 0x019fa023, 0x007f8028, 0x019fa023, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x5c708028, 0x58908008, + 0x1983a024, 0x5c708028, 0x58908008, 0x1983a024, + 0x5c708028, 0x019fa023, 0x81df0004, 0x00ffb81d, + 0x003f03f9, 0x009f0324, 0x84840001, 0xb0010000, + 0xb4000011, 0x815b4b0c, 0x81070000, 0x81270bf4, + 0xb00a0000, 0xb4000002, 0x81070c00, 0x812717f4, + 0x802500a5, 0x806500a5, 0x3001b803, 0xb420fffc, + 0x9421ffff, 0x3001b808, 0xb480000b, 0x3001b809, + 0xb4a00060, 0xb5000008, 0xb0040000, 0xb4200003, + 0x802717ff, 0x81470000, 0xb5000003, 0x80270001, + 0x003f23f9, 0x81470c00, 0xb0040000, 0xb4200006, + 0x039f4193, 0x5b81b81c, 0x003f90cb, 0x1021b81c, + 0x003fb0cb, 0x8384f922, 0x829bff80, 0x801300e0, + 0x1434b800, 0x5c35b801, 0x8013001f, 0x1454b800, + 0x5c50b802, 0x8073007f, 0x9863ffff, 0xb002000f, + 0xb4800001, 0x90210001, 0x84210004, 0xb0010000, + 0xb4a00001, 0x6861b803, 0x005f9040, 0x4082b803, + 0x80af001f, 0x808f0000, 0x806f0000, 0x8007ffff, + 0x8033ffff, 0x80171000, 0x81df0000, 0x00000000, + 0x00000000, 0xb6001811, 0xb6002010, 0x14618000, + 0x6068b803, 0x40c4b803, 0x14608000, 0x00c8b806, + 0x5870b803, 0x6068b803, 0x4104b803, 0x58c8b806, + 0x0108b808, 0x14c6b801, 0x00000000, 0x00000000, + 0x5d08b808, 0x1508b800, 0x1806a028, 0x81df0004, + 0x80670400, 0x5d22b80a, 0x81df0000, 0x00000000, + 0x00000000, 0xb600180a, 0x00cfb803, 0x013fb0bc, + 0x5922b809, 0x01afb809, 0x013f90bc, 0x0047b86f, + 0xb0020001, 0xb4c0fffd, 0x90630020, 0x91290020, + 0x81df0004, 0x808f0000, 0x801b4b14, 0x80270001, + 0xb0000001, 0xb4000002, 0x802600a0, 0x803e4b14, + 0x81270c00, 0xb00a0000, 0xb4000001, 0x81270000, + 0x813e4b0c, 0x80270001, 0x003f2013, 0x80050086, + 0x001fb044, 0x00ffb81b, 0x00000000, 0x00000000, +}; + +static u32 PCM240Ucode1f4b00[] = { + 0x00000000, 0x00000000, 0x00060504, 0x00000000, + 0x00000000, 0x00000000, 0x00300000, 0xffcfcfff, + 0x00302000, 0xffcfcfff, 0x00380000, 0xffc7c7ff, + 0xcbcecdc4, 0xcfcac9c8, 0xc3c6c5cc, 0xc7c2c1c0, + 0x1b1e1d14, 0x1f1a1918, 0x1316151c, 0x17121110, + 0x2b2e2d24, 0x2f2a2928, 0x2326252c, 0x27222120, + 0x3b3e3d34, 0x3f3a3938, 0x3336353c, 0x37323130, + 0x0b0e0d04, 0x0f0a0908, 0x0306050c, 0x07020100, + 0xdbdeddd4, 0xdfdad9d8, 0xd3d6d5dc, 0xd7d2d1d0, + 0xebeeede4, 0xefeae9e8, 0xe3e6e5ec, 0xe7e2e1e0, + 0xfbfefdf4, 0xfffaf9f8, 0xf3f6f5fc, 0xf7f2f1f0, + 0x4b4e4d44, 0x4f4a4948, 0x4346454c, 0x47424140, + 0x9b9e9d94, 0x9f9a9998, 0x9396959c, 0x97929190, + 0xabaeada4, 0xafaaa9a8, 0xa3a6a5ac, 0xa7a2a1a0, + 0xbbbebdb4, 0xbfbab9b8, 0xb3b6b5bc, 0xb7b2b1b0, + 0x8b8e8d84, 0x8f8a8988, 0x8386858c, 0x87828180, + 0x5b5e5d54, 0x5f5a5958, 0x5356555c, 0x57525150, + 0x6b6e6d64, 0x6f6a6968, 0x6366656c, 0x67626160, + 0x7b7e7d74, 0x7f7a7978, 0x7376757c, 0x77727170, + 0x341424c4, 0x3e1e2ece, 0x3d1d2dcd, 0x3b1b2bcb, + 0xb494a444, 0xbe9eae4e, 0xbd9dad4d, 0xbb9bab4b, + 0xf4d4e404, 0xfedeee0e, 0xfddded0d, 0xfbdbeb0b, + 0x74546484, 0x7e5e6e8e, 0x7d5d6d8d, 0x7b5b6b8b, + 0x3c1c2ccc, 0x361626c6, 0x351525c5, 0x331323c3, + 0xbc9cac4c, 0xb696a646, 0xb595a545, 0xb393a343, + 0xfcdcec0c, 0xf6d6e606, 0xf5d5e505, 0xf3d3e303, + 0x7c5c6c8c, 0x76566686, 0x75556585, 0x73536383, + 0x381828c8, 0x3a1a2aca, 0x391929c9, 0x3f1f2fcf, + 0xb898a848, 0xba9aaa4a, 0xb999a949, 0xbf9faf4f, + 0xf8d8e808, 0xfadaea0a, 0xf9d9e909, 0xffdfef0f, + 0x78586888, 0x7a5a6a8a, 0x79596989, 0x7f5f6f8f, + 0x301020c0, 0x321222c2, 0x311121c1, 0x371727c7, + 0xb090a040, 0xb292a242, 0xb191a141, 0xb797a747, + 0xf0d0e000, 0xf2d2e202, 0xf1d1e101, 0xf7d7e707, + 0x70506080, 0x72526282, 0x71516181, 0x77576787, + 0x05040100, 0x15141110, 0x25242120, 0x35343130, + 0x85848180, 0x95949190, 0xa5a4a1a0, 0xb5b4b1b0, + 0xc0408000, 0xe060a020, 0xd0509010, 0xf070b030, + 0xc8488808, 0xe868a828, 0xd8589818, 0xf878b838, + 0xc4448404, 0xe464a424, 0xd4549414, 0xf474b434, + 0xcc4c8c0c, 0xec6cac2c, 0xdc5c9c1c, 0xfc7cbc3c, + 0xc2428202, 0xe262a222, 0xd2529212, 0xf272b232, + 0xca4a8a0a, 0xea6aaa2a, 0xda5a9a1a, 0xfa7aba3a, + 0xc6468606, 0xe666a626, 0xd6569616, 0xf676b636, + 0xce4e8e0e, 0xee6eae2e, 0xde5e9e1e, 0xfe7ebe3e, + 0xc1418101, 0xe161a121, 0xd1519111, 0xf171b131, + 0xc9498909, 0xe969a929, 0xd9599919, 0xf979b939, + 0xc5458505, 0xe565a525, 0xd5559515, 0xf575b535, + 0xcd4d8d0d, 0xed6dad2d, 0xdd5d9d1d, 0xfd7dbd3d, + 0xc3438303, 0xe363a323, 0xd3539313, 0xf373b333, + 0xcb4b8b0b, 0xeb6bab2b, 0xdb5b9b1b, 0xfb7bbb3b, + 0xc7478707, 0xe767a727, 0xd7579717, 0xf777b737, + 0xcf4f8f0f, 0xef6faf2f, 0xdf5f9f1f, 0xff7fbf3f, + 0x1045a3e2, 0x000000f4, 0x263b7333, 0x766b2363, + 0x2b367e3e, 0x7b662e6e, 0x06db93d3, 0x964b0343, + 0x0bd69ede, 0x9b460e4e, 0x825f1757, 0x12cf87c7, + 0x8f521a5a, 0x1fc28aca, 0x00d199d9, 0x90410949, + 0x01d098d8, 0x91400848, 0x24357d3d, 0x74652d6d, + 0x25347c3c, 0x75642c6c, 0x04d59ddd, 0x94450d4d, + 0x05d49cdc, 0x95440c4c, 0x80511959, 0x10c189c9, + 0x81501858, 0x11c088c8, 0x02df97d7, 0x924f0747, + 0x0fd29ada, 0x9f420a4a, 0x865b1353, 0x16cb83c3, + 0x8b561e5e, 0x1bc68ece, 0xa6bbf3b3, 0xf6eba3e3, + 0xabb6febe, 0xfbe6aeee, 0x223f7737, 0x726f2767, + 0x2f327a3a, 0x7f622a6a, 0xa0b1f9b9, 0xf0e1a9e9, + 0xa1b0f8b8, 0xf1e0a8e8, 0x84551d5d, 0x14c58dcd, + 0x85541c5c, 0x15c48ccc, 0xa4b5fdbd, 0xf4e5aded, + 0xa5b4fcbc, 0xf5e4acec, 0x20317939, 0x70612969, + 0x21307838, 0x71602868, 0xa2bff7b7, 0xf2efa7e7, + 0xafb2faba, 0xffe2aaea, 0x00000000, 0x00000000, +}; + +static u32 PCM240Ucode1fff00[] = { + 0xcbcecdc4, 0xcfcac9c8, 0xc3c6c5cc, 0xc7c2c1c0, + 0x1b1e1d14, 0x1f1a1918, 0x1316151c, 0x17121110, + 0x2b2e2d24, 0x2f2a2928, 0x2326252c, 0x27222120, + 0x3b3e3d34, 0x3f3a3938, 0x3336353c, 0x37323130, + 0x0b0e0d04, 0x0f0a0908, 0x0306050c, 0x07020100, + 0xdbdeddd4, 0xdfdad9d8, 0xd3d6d5dc, 0xd7d2d1d0, + 0xebeeede4, 0xefeae9e8, 0xe3e6e5ec, 0xe7e2e1e0, + 0xfbfefdf4, 0xfffaf9f8, 0xf3f6f5fc, 0xf7f2f1f0, + 0x4b4e4d44, 0x4f4a4948, 0x4346454c, 0x47424140, + 0x9b9e9d94, 0x9f9a9998, 0x9396959c, 0x97929190, + 0xabaeada4, 0xafaaa9a8, 0xa3a6a5ac, 0xa7a2a1a0, + 0xbbbebdb4, 0xbfbab9b8, 0xb3b6b5bc, 0xb7b2b1b0, + 0x8b8e8d84, 0x8f8a8988, 0x8386858c, 0x87828180, + 0x5b5e5d54, 0x5f5a5958, 0x5356555c, 0x57525150, + 0x6b6e6d64, 0x6f6a6968, 0x6366656c, 0x67626160, + 0x7b7e7d74, 0x7f7a7978, 0x7376757c, 0x77727170, + 0x341424c4, 0x3e1e2ece, 0x3d1d2dcd, 0x3b1b2bcb, + 0xb494a444, 0xbe9eae4e, 0xbd9dad4d, 0xbb9bab4b, + 0xf4d4e404, 0xfedeee0e, 0xfddded0d, 0xfbdbeb0b, + 0x74546484, 0x7e5e6e8e, 0x7d5d6d8d, 0x7b5b6b8b, + 0x3c1c2ccc, 0x361626c6, 0x351525c5, 0x331323c3, + 0xbc9cac4c, 0xb696a646, 0xb595a545, 0xb393a343, + 0xfcdcec0c, 0xf6d6e606, 0xf5d5e505, 0xf3d3e303, + 0x7c5c6c8c, 0x76566686, 0x75556585, 0x73536383, + 0x381828c8, 0x3a1a2aca, 0x391929c9, 0x3f1f2fcf, + 0xb898a848, 0xba9aaa4a, 0xb999a949, 0xbf9faf4f, + 0xf8d8e808, 0xfadaea0a, 0xf9d9e909, 0xffdfef0f, + 0x78586888, 0x7a5a6a8a, 0x79596989, 0x7f5f6f8f, + 0x301020c0, 0x321222c2, 0x311121c1, 0x371727c7, + 0xb090a040, 0xb292a242, 0xb191a141, 0xb797a747, + 0xf0d0e000, 0xf2d2e202, 0xf1d1e101, 0xf7d7e707, + 0x70506080, 0x72526282, 0x71516181, 0x77576787, + 0x05040100, 0x15141110, 0x25242120, 0x35343130, + 0x85848180, 0x95949190, 0xa5a4a1a0, 0xb5b4b1b0, + 0xc0408000, 0xe060a020, 0xd0509010, 0xf070b030, + 0xc8488808, 0xe868a828, 0xd8589818, 0xf878b838, + 0xc4448404, 0xe464a424, 0xd4549414, 0xf474b434, + 0xcc4c8c0c, 0xec6cac2c, 0xdc5c9c1c, 0xfc7cbc3c, + 0xc2428202, 0xe262a222, 0xd2529212, 0xf272b232, + 0xca4a8a0a, 0xea6aaa2a, 0xda5a9a1a, 0xfa7aba3a, + 0xc6468606, 0xe666a626, 0xd6569616, 0xf676b636, + 0xce4e8e0e, 0xee6eae2e, 0xde5e9e1e, 0xfe7ebe3e, + 0xc1418101, 0xe161a121, 0xd1519111, 0xf171b131, + 0xc9498909, 0xe969a929, 0xd9599919, 0xf979b939, + 0xc5458505, 0xe565a525, 0xd5559515, 0xf575b535, + 0xcd4d8d0d, 0xed6dad2d, 0xdd5d9d1d, 0xfd7dbd3d, + 0xc3438303, 0xe363a323, 0xd3539313, 0xf373b333, + 0xcb4b8b0b, 0xeb6bab2b, 0xdb5b9b1b, 0xfb7bbb3b, + 0xc7478707, 0xe767a727, 0xd7579717, 0xf777b737, + 0xcf4f8f0f, 0xef6faf2f, 0xdf5f9f1f, 0xff7fbf3f, + 0x1045a3e2, 0x000000f4, 0x263b7333, 0x766b2363, + 0x2b367e3e, 0x7b662e6e, 0x06db93d3, 0x964b0343, + 0x0bd69ede, 0x9b460e4e, 0x825f1757, 0x12cf87c7, + 0x8f521a5a, 0x1fc28aca, 0x00d199d9, 0x90410949, + 0x01d098d8, 0x91400848, 0x24357d3d, 0x74652d6d, + 0x25347c3c, 0x75642c6c, 0x04d59ddd, 0x94450d4d, + 0x05d49cdc, 0x95440c4c, 0x80511959, 0x10c189c9, + 0x81501858, 0x11c088c8, 0x02df97d7, 0x924f0747, + 0x0fd29ada, 0x9f420a4a, 0x865b1353, 0x16cb83c3, + 0x8b561e5e, 0x1bc68ece, 0xa6bbf3b3, 0xf6eba3e3, + 0xabb6febe, 0xfbe6aeee, 0x223f7737, 0x726f2767, + 0x2f327a3a, 0x7f622a6a, 0xa0b1f9b9, 0xf0e1a9e9, + 0xa1b0f8b8, 0xf1e0a8e8, 0x84551d5d, 0x14c58dcd, + 0x85541c5c, 0x15c48ccc, 0xa4b5fdbd, 0xf4e5aded, + 0xa5b4fcbc, 0xf5e4acec, 0x20317939, 0x70612969, + 0x21307838, 0x71602868, 0xa2bff7b7, 0xf2efa7e7, + 0xafb2faba, 0xffe2aaea, 0x00000000, 0x00000000, +}; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/ls220/pcm.h linux.19rc3-ac4/drivers/media/video/ls220/pcm.h --- linux.19rc3/drivers/media/video/ls220/pcm.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/ls220/pcm.h 2002-07-29 13:58:41.000000000 +0100 @@ -0,0 +1,792 @@ +static u32 PCMUcode1f1800[] = { + 0xb500000f, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xb50001fb, 0x00000000, 0x00000000, 0x00000000, + 0x820f001f, 0x802f001f, 0x029f9014, 0x829efef0, + 0x8286000f, 0x02bf0054, 0x82bcfef4, 0x82a6000e, + 0x80074000, 0x001f6193, 0x8013001f, 0x9020c000, + 0x003fb006, 0x803effe8, 0x803effec, 0x9020fa00, + 0x803effd0, 0x803effdc, 0x803effd8, 0x9020fe00, + 0x803effd4, 0x90400000, 0x804600a2, 0x90421800, + 0x804600a3, 0x80132000, 0x98000040, 0x800600a6, + 0x80050080, 0x98000002, 0x80060080, 0x80070001, + 0x001f2013, 0x80070000, 0x001f23f9, 0x801e4b0c, + 0x001f210c, 0x80070001, 0x001f2324, 0x80070800, + 0x001f600f, 0x001fb0cb, 0x001fb010, 0x801efff0, + 0x98004000, 0x001f600e, 0x83e4011b, 0x80070000, + 0x801e4b14, 0x800500a0, 0xb0000001, 0xb4000009, + 0x80070001, 0x800600a0, 0x80050080, 0x98000020, + 0x80060080, 0x9400ffdf, 0x80060080, 0x80070000, + 0x800600a0, 0x80074000, 0x801e4b04, 0x81df0004, + 0x801bfff0, 0x00000000, 0x940000ff, 0xb0000000, + 0xb4200033, 0x003f400e, 0x94010010, 0xb0000000, + 0xb400fff7, 0x003f0013, 0xb0010001, 0xb420001f, + 0x803bffe8, 0x801bffec, 0x805b4b04, 0x00000000, + 0x3001b800, 0xb4600001, 0x9021a000, 0x0421b800, + 0x3001b802, 0xb460000d, 0x80050086, 0x005f9044, + 0x0420b802, 0xb00101e0, 0xb4a0ffe5, 0x001fb010, + 0x001f010c, 0xb0000001, 0xb400ffe1, 0x80070001, + 0x001f210c, 0x83e400e8, 0xb500ffdd, 0x8007001f, + 0x94000003, 0x5810b800, 0x83e719ec, 0x1bffb800, + 0x003f9008, 0x1821b800, 0x00ffb801, 0x80270000, + 0x003f2013, 0x8007001f, 0x94000003, 0x5810b800, + 0x83671a14, 0x1b7bb800, 0x003f9009, 0x1821b800, + 0x00ffb801, 0x80070000, 0x001f210c, 0xb500ffc8, + 0x003f400e, 0xb0000086, 0xb4400051, 0xb0000084, + 0xb400003b, 0xb0000085, 0xb4000041, 0xb0000086, + 0xb4000043, 0xb0000083, 0xb4000000, 0x815bff7c, + 0x00000000, 0x940a0080, 0x5c07b800, 0xb0000001, + 0xb400006f, 0x81674b18, 0x940a0007, 0x5803b800, + 0x116bb800, 0x005bb80b, 0x916b0004, 0x001bb80b, + 0x806500d4, 0x1463b800, 0x1863b802, 0x806600d4, + 0x80073c21, 0x801e4b00, 0x800600a1, 0x80074000, + 0x801e4b04, 0x8013001f, 0x98405000, 0x805effe0, + 0x005fb006, 0x805effe8, 0x805effec, 0x9042a000, + 0x805effe4, 0x9040fa00, 0x805effd0, 0x805effdc, + 0x805effd8, 0x9040fe00, 0x805effd4, 0x8013007f, + 0x9800ffff, 0x001fb040, 0x80070001, 0x001f2013, + 0x80070000, 0x001f2324, 0x001fb0cb, 0x001fb010, + 0x001fb041, 0x001fb042, 0x80073310, 0x001fb008, + 0x80071e40, 0x001fb009, 0x98214000, 0xb5000010, + 0x94011000, 0xb0001000, 0xb4200001, 0x9421efff, + 0x98210010, 0xb500000a, 0x80070000, 0x001fb0cb, + 0x83e40099, 0x003f400e, 0x9421ffef, 0xb5000004, + 0x83e40095, 0x003f400e, 0x98211000, 0x9421ffef, + 0x003f600e, 0x80070100, 0x801efff0, 0xb500ff74, + 0xb000008b, 0xb4000018, 0xb0000087, 0xb400ffee, + 0xb0000088, 0xb4000016, 0xb000008a, 0xb4000016, + 0xb000008c, 0xb4000017, 0xb0000089, 0xb4000019, + 0xb00000a0, 0xb400001b, 0xb00000a1, 0xb4000047, + 0xb00000a2, 0xb4000054, 0xb00000a3, 0xb400004c, + 0xb00000a4, 0xb4000056, 0xb00000a5, 0xb400005a, + 0xb00000a6, 0xb400005e, 0x803efff8, 0xb500ffe1, + 0x9421ffdf, 0xb500ffde, 0x80270100, 0x803efff8, + 0xb500ffdc, 0x803bffb0, 0x00000000, 0x003fb040, + 0xb500ffd8, 0x803bff80, 0x00000000, 0x003f6001, + 0xb500ffd4, 0x003f90ba, 0x803efff8, 0xb500ffd1, + 0x81674b18, 0x940a0007, 0x5803b800, 0x116bb800, + 0x005bb80b, 0x916b0004, 0x001bb80b, 0x806500d4, + 0x1463b800, 0x1863b802, 0x806600d4, 0x80130001, + 0x98003d21, 0x800600a1, 0x801e4b00, 0x80074000, + 0x801e4b04, 0x8013001f, 0x98405000, 0x805effe0, + 0x005fb006, 0x805effe8, 0x805effec, 0x9042a000, + 0x805effe4, 0x9040fa00, 0x805effd0, 0x805effdc, + 0x805effd8, 0x9040fe00, 0x805effd4, 0x80070001, + 0x001f2013, 0x80070000, 0x001f2324, 0x001fb0cb, + 0x001fb010, 0x80073b00, 0x001fb008, 0x800742f0, + 0x001fb009, 0x98214000, 0xb500ffa5, 0x80270000, + 0x8047fef0, 0x003eb802, 0x90420004, 0x003eb802, + 0x90420004, 0x003eb802, 0x90420004, 0x003eb802, + 0x81df0000, 0x00000000, 0x00000000, 0x8364042b, + 0x81df0004, 0xb500ff97, 0x81df0000, 0x00000000, + 0x00000000, 0x836403d5, 0x81df0004, 0xb500ff91, + 0x81df0000, 0x00000000, 0x00000000, 0x83640390, + 0x81df0004, 0xb500ff8b, 0x81df0000, 0x00000000, + 0x00000000, 0x834402f3, 0x81df0004, 0xb500ff85, + 0x81df0000, 0x00000000, 0x00000000, 0x834402d8, + 0x81df0004, 0xb500ff7f, 0x80070000, 0x80470000, + 0x81df0000, 0x00000000, 0x00000000, 0xb6002003, + 0xb6003002, 0x001eb802, 0x90420004, 0x80171000, + 0x8057ffff, 0xb6002002, 0xb6001801, 0x001fa020, + 0x81df0004, 0x00ffb81f, 0x83a70000, 0x8057ffff, + 0x80770000, 0x8073007d, 0x98636d4a, 0x0207b803, + 0x81df0000, 0x00000000, 0x00000000, 0x80171000, + 0xb6000007, 0x003fc020, 0x005fc7e0, 0x40c1b810, + 0x4102b810, 0x001fe026, 0x001fe0a8, 0x4210b803, + 0x81df0004, 0x80270000, 0x003f2013, 0x8007001f, + 0x94000003, 0x5810b800, 0x83671e1c, 0x1b7bb800, + 0x003f9009, 0x1821b800, 0x00ffb801, 0x003f0013, + 0xb0010001, 0xb420fff3, 0x93bd0001, 0xb01d0004, + 0xb480ffe3, 0x00ffb81f, 0x00000000, 0x00000000, + 0x003f03f9, 0x009f0324, 0x84840001, 0xb0010000, + 0xb4000011, 0x815b4b0c, 0x81070000, 0x81270bf4, + 0xb00a0000, 0xb4000002, 0x81070c00, 0x812717f4, + 0x802500a5, 0x806500a5, 0x3001b803, 0xb420fffc, + 0x9421ffff, 0x3001b808, 0xb480000b, 0x3001b809, + 0xb4a00060, 0xb5000008, 0xb0040000, 0xb4200003, + 0x802717ff, 0x81470000, 0xb5000003, 0x80270001, + 0x003f23f9, 0x81470c00, 0xb0040000, 0xb4200006, + 0x039f4193, 0x5b81b81c, 0x003f90cb, 0x1021b81c, + 0x003fb0cb, 0x8384024e, 0x829bff80, 0x801300e0, + 0x1434b800, 0x5c35b801, 0x8013001f, 0x1454b800, + 0x5c50b802, 0x8073007f, 0x9863ffff, 0xb002000f, + 0xb4800001, 0x90210001, 0x84210004, 0xb0010000, + 0xb4a00001, 0x6861b803, 0x005f9040, 0x4082b803, + 0x80af001f, 0x808f0000, 0x806f0000, 0x8007ffff, + 0x8033ffff, 0x80171000, 0x81df0000, 0x00000000, + 0x00000000, 0xb6001811, 0xb6002010, 0x14618000, + 0x6068b803, 0x40c4b803, 0x14608000, 0x00c8b806, + 0x5870b803, 0x6068b803, 0x4104b803, 0x58c8b806, + 0x0108b808, 0x14c6b801, 0x00000000, 0x00000000, + 0x5d08b808, 0x1508b800, 0x1806a028, 0x81df0004, + 0x80670400, 0x5d22b80a, 0x81df0000, 0x00000000, + 0x00000000, 0xb600180a, 0x00cfb803, 0x013fb0bc, + 0x5922b809, 0x01afb809, 0x013f90bc, 0x0047b86f, + 0xb0020001, 0xb4c0fffd, 0x90630020, 0x91290020, + 0x81df0004, 0x808f0000, 0x801b4b14, 0x80270001, + 0xb0000001, 0xb4000002, 0x802600a0, 0x803e4b14, + 0x81270c00, 0xb00a0000, 0xb4000001, 0x81270000, + 0x813e4b0c, 0x80270001, 0x003f2013, 0x80050086, + 0x001fb044, 0x00ffb81b, 0x00000000, 0x00000000, + 0x029fb00a, 0x02bfb00b, 0x02dfb00c, 0x02ffb00d, + 0x031fb00e, 0x033fb00f, 0x033f400f, 0x0287b86f, + 0x029fb005, 0x8285009c, 0x96b48000, 0xb0158000, + 0xb4000191, 0x96b40100, 0xb0150100, 0xb40001ad, + 0x96b40400, 0xb0150400, 0xb40001bf, 0x96b40001, + 0xb0150001, 0xb400000c, 0x96b40008, 0xb0150008, + 0xb400019a, 0x96b44000, 0xb0154000, 0xb40001be, + 0x96b40002, 0xb0150002, 0xb400015e, 0x00000000, + 0x00000000, 0xb50001d0, 0x02bf9017, 0x92b50001, + 0x02bfb017, 0x82850082, 0x83050081, 0x82a5009a, + 0x96b50001, 0xb0150001, 0xb4200014, 0x82a70000, + 0x02bfb017, 0x96b41840, 0xb0150800, 0xb420000c, + 0x96b40008, 0x5aa9b815, 0x96d46000, 0x5ec3b816, + 0x82f3000f, 0x9af7c00f, 0x1718b817, 0x1ab5b818, + 0x1ab5b816, 0x9ab50340, 0x82a60081, 0xb500013d, + 0x9b180180, 0x83060081, 0xb500013a, 0x82a5009a, + 0x96b50002, 0xb0150002, 0xb420001b, 0x82a70000, + 0x02bfb017, 0x96b41800, 0xb0151800, 0xb4000013, + 0x96b40040, 0xb0150040, 0xb4200004, 0xa3180c00, + 0x9b180340, 0x83060081, 0xb500012a, 0x96b40008, + 0x5aa9b815, 0x96d46000, 0x5ec3b816, 0x82f3000f, + 0x9af7c00f, 0x1718b817, 0x1ab5b818, 0x1ab5b816, + 0x9ab50340, 0x82a60081, 0xb500011e, 0x9b180180, + 0x83060081, 0xb500011b, 0x82a500c1, 0x96b5000f, + 0xb015000b, 0xb420000e, 0x96b40020, 0xb0150020, + 0xb400000b, 0x96b40200, 0xb0150200, 0xb4000008, + 0x82c50086, 0x82e50094, 0x3016b817, 0xb4400004, + 0x06f7b816, 0xb017ff00, 0xb4400001, 0xb5000109, + 0x96b46000, 0xb0156000, 0xb4000011, 0x96b41820, + 0xb0150820, 0xb4200004, 0x9b391000, 0x82a5009a, + 0x96b5feff, 0x82a6009a, 0x96b40040, 0xb0150040, + 0xb4200001, 0x9739efff, 0x96b91000, 0xb0151000, + 0xb4200003, 0x82a5009a, 0x9ab50100, 0x82a6009a, + 0x96b40040, 0xb0150040, 0xb4200019, 0x96b41800, + 0xb0151800, 0xb4200006, 0x96b98000, 0xb0158000, + 0xb4200003, 0x9b180180, 0x83060081, 0xb50000e9, + 0x96d80c00, 0x82b300ff, 0x9ab5f3ff, 0x1718b815, + 0xb0160c00, 0xb4000007, 0x82e50098, 0x96f70400, + 0xb0170400, 0xb4200002, 0x82c70c00, 0xb5000001, + 0xa2d60c00, 0x1b18b816, 0x9b180340, 0xb50000cf, + 0x96b40220, 0xb0150000, 0xb4e00033, 0x82a5009d, + 0x82f3ffff, 0x16b5b817, 0x82f3000e, 0x3015b817, + 0xb420002d, 0x96f98000, 0xb0178000, 0xb400002a, + 0x82a70000, 0x02bfb017, 0x82c50081, 0x9ab60020, + 0x82a60081, 0x82a50086, 0x92b50bb8, 0x82a60094, + 0x82c60081, 0x82c5009d, 0x96d6ffff, 0x82b30032, + 0x9ab58001, 0x82e500c1, 0x96f7000f, 0xb017000b, + 0xb4000002, 0x82b30022, 0x9ab58001, 0x1ab5b816, + 0x82c5009a, 0x96d60020, 0xb0160020, 0xb4200002, + 0x82b30032, 0x9ab58001, 0x82a6009d, 0x02ff9017, + 0x00000000, 0xb0170040, 0xb480000b, 0x96f41c00, + 0xb0171c00, 0xb4200008, 0x82e50086, 0x82c50094, + 0x92d63000, 0x3016b817, 0xb4400003, 0x9b180180, + 0x83060081, 0xb50000a3, 0x5eb5b814, 0x96b500f0, + 0x96f46000, 0x5eedb817, 0x1ab5b817, 0xb0170003, + 0xb4000004, 0x96b500ef, 0x96f70001, 0x5ae4b817, + 0x1ab5b817, 0x96d41800, 0xb0161800, 0xb400000a, + 0x96f900ff, 0x96b500ff, 0x9739ff00, 0x1b39b815, + 0x02a7b817, 0x96b500f3, 0x96d40008, 0x5ec1b816, + 0x1ab5b816, 0xb500000c, 0x96f98000, 0xb0178000, + 0xb4200007, 0x5efeb814, 0x96f70001, 0xb0170001, + 0xb4000003, 0x9b180180, 0x83060081, 0xb5000081, + 0x96b500f3, 0x9ab50008, 0x9739fff3, 0x96d40020, + 0xb0160020, 0xb4200017, 0x9b398000, 0x82c70000, + 0x02dfb017, 0x96d40010, 0x5ac8b816, 0x82f300ff, + 0x9af7cfff, 0x1718b817, 0x1b18b816, 0x9b180340, + 0x82c5009d, 0x96d6ffff, 0x82f3000e, 0x9af78001, + 0x1af7b816, 0x82c5009a, 0x96d60020, 0xb0160020, + 0xb4200002, 0x82f30032, 0x9af78001, 0x82e6009d, + 0xb500005a, 0x97397fff, 0x96b500ff, 0x5aaab815, + 0x82f300fc, 0x9af703ff, 0x1718b817, 0x1b18b815, + 0x9b180340, 0x82c5009a, 0x96d60010, 0xb0160010, + 0xb4200024, 0x82c70000, 0x02dfb017, 0x82c50086, + 0x92d60bb8, 0x82c60086, 0x82c50094, 0x5eefb818, + 0x96f70003, 0xb0170003, 0xb4200002, 0x82e70bb8, + 0xb5000001, 0x82e70bb8, 0x12d6b817, 0x82e50081, + 0x9af70020, 0x82e60081, 0x82c60094, 0xa2f70020, + 0x82e60081, 0x82f30001, 0x16f7b818, 0x5ef0b817, + 0xb0170001, 0xb4000004, 0x96f84000, 0x5ee4b817, + 0x9718f3ff, 0x1b18b817, 0x82f3000a, 0x9af78000, + 0x82e6009d, 0x83060081, 0x83070001, 0x8306009f, + 0xb50000ad, 0x82c5009d, 0x82f3000e, 0x9af78001, + 0x3016b817, 0xb420000f, 0x82b30032, 0x9ab58001, + 0x82e500c1, 0x96f7000f, 0xb017000b, 0xb4000002, + 0x82b30022, 0x9ab58001, 0x82c5009a, 0x96d60020, + 0xb0160020, 0xb4200002, 0x82b30032, 0x9ab58001, + 0x82a6009d, 0x82c5009a, 0x96d60080, 0xb0160080, + 0xb4000011, 0x02df9017, 0x00000000, 0xb0160010, + 0xb480000d, 0x82c500c1, 0x96d6000f, 0xb016000b, + 0xb4000009, 0x82c50087, 0x96d60080, 0x5ac7b816, + 0x96f84000, 0x3017b816, 0xb4200003, 0x033f400f, + 0x9b394000, 0xb500000b, 0x9739bfff, 0x82e50061, + 0x96f70008, 0xb0170008, 0xb4000005, 0x5eefb818, + 0x96f70003, 0xb0170003, 0xb4000001, 0x9718ffff, + 0x83060081, 0x83070001, 0x8306009f, 0x00000000, + 0xb5000075, 0x82850083, 0x96b400ff, 0xb015003c, + 0xb4200019, 0x96b92000, 0xb0152000, 0xb4000002, + 0x9b392000, 0xb5000014, 0x9739d3ff, 0x82870000, + 0x82860087, 0x82870008, 0x82860083, 0x829bff78, + 0x82a7001f, 0xb0140400, 0xb4000001, 0x82a70010, + 0x82a600c9, 0x829bff78, 0x00000000, 0x828600cb, + 0x8285009d, 0x82b3ffff, 0x9ab5fffd, 0x1694b815, + 0x8286009d, 0xb5000000, 0x83070002, 0x8306009f, + 0x00000000, 0xb5000054, 0x96b90800, 0xb0150800, + 0xb4200009, 0x9739f7ff, 0x82a703fd, 0x82a600cb, + 0x82a7003c, 0x82a60083, 0x8285009d, 0x9a940002, + 0x8286009d, 0xb5000004, 0x82850087, 0x5a82b814, + 0xa2940200, 0x82860087, 0xb5000000, 0x83078000, + 0x8306009f, 0x00000000, 0xb500003f, 0x82850086, + 0x82a50094, 0x3015b814, 0xb4800002, 0x86b50bb8, + 0x82a60086, 0x83070008, 0x8306009f, 0x00000000, + 0xb5000035, 0x83050069, 0x9718003f, 0x82e50064, + 0x12f7b818, 0x86f70088, 0x82feff74, 0x02e7b86f, + 0x9af74000, 0x01ffb817, 0x96f7bfff, 0x01ffb817, + 0x83050081, 0x82f3001c, 0x9af703ff, 0x1718b817, + 0x9b180140, 0x83060081, 0x83070100, 0x8306009f, + 0x00000000, 0xb5000020, 0x83070000, 0x83050081, + 0x9b180180, 0x83060081, 0x83070400, 0x8306009f, + 0x00000000, 0xb5000018, 0x82870000, 0x82850082, + 0x5eb7b814, 0x96b500fc, 0x96d40006, 0x5ec1b816, + 0x1ab5b816, 0x5aacb815, 0x83050081, 0x82d3001c, + 0x9ad600ff, 0x1718b816, 0x1b18b815, 0x9b180e00, + 0x83060081, 0x83074000, 0x8306009f, 0x8305009d, + 0x82d300ff, 0x9ad6bfff, 0x1718b816, 0x8306009d, + 0x00000000, 0xb5000000, 0x029f9005, 0x01ffb814, + 0x033f600f, 0x029f900a, 0x02bf900b, 0x02df900c, + 0x02ff900d, 0x031f900e, 0x033f900f, 0x00ffb81e, + 0x02ff9010, 0x92f70b43, 0x02ffb010, 0x02ff90cb, + 0x82bbffdc, 0x829bffd8, 0x93150004, 0x3014b815, + 0xb4000010, 0x02dbb818, 0x029bb815, 0x3017b816, + 0xb480000c, 0x5a81b814, 0x029fb010, 0x82860095, + 0x8293001f, 0x9294fe00, 0x92b50008, 0x3015b814, + 0xb4800002, 0x82b3001f, 0x92b5fa00, 0x82beffdc, + 0xb500ffeb, 0x029f9010, 0x83250094, 0x06d4b819, + 0x02d6b816, 0xb016ffff, 0xb4a0000a, 0x8293000e, + 0x9a948001, 0x82c5009d, 0x96d6ffff, 0x1a94b816, + 0x82c5009a, 0x96d60010, 0xb0160010, 0xb4000001, + 0x8286009d, 0x00ffb81c, 0x00000000, 0x00000000, + 0x001f9012, 0x001fb100, 0x001f004c, 0x001f2404, + 0x801bfef0, 0x8058fef4, 0x803bff68, 0x8078ff6c, + 0x2000b801, 0x2042b803, 0x001fb104, 0x005f2414, + 0x82e70001, 0x83640048, 0x029fb014, 0x829efef0, + 0x8286000f, 0x02bf2054, 0x82bcfef4, 0x82a6000e, + 0x00ffb81a, 0x80e70001, 0x801336e3, 0x9800eb76, + 0x001fb100, 0x800700ab, 0x001f2404, 0x801bc3e8, + 0x8058c3ec, 0x83640024, 0x82e70000, 0x83640036, + 0x029fb300, 0x029fb100, 0x02bf2c04, 0x02bf2404, + 0x801bc000, 0x8058c004, 0x8364001b, 0x82e70000, + 0x8364002d, 0x001f9300, 0x3000b814, 0xb420000a, + 0x001f0c04, 0x3000b815, 0xb4200007, 0x829efef0, + 0x82bcfef4, 0x029fb012, 0x02bf204c, 0x82870001, + 0x829cfef5, 0x00ffb81a, 0xb0070000, 0xb4000007, + 0x80e70000, 0x801399fa, 0x9800c92e, 0x001fb100, + 0x800700af, 0x001f2404, 0xb500ffdc, 0x82870000, + 0x829cfef5, 0x00ffb81a, 0x80c700ff, 0x803bff68, + 0x8078ff6c, 0x14a0b806, 0x2063b805, 0x007f2414, + 0x2021b802, 0x58c8b806, 0x14a0b806, 0x58b0b805, + 0x2021b805, 0x58c8b806, 0x14a0b806, 0x2021b805, + 0x58c8b806, 0x14a0b806, 0x5cb0b805, 0x2021b805, + 0x003fb104, 0x00ffb81b, 0x82c70000, 0x83070400, + 0x83270005, 0x8197040c, 0x81d7ffff, 0x83840126, + 0x83840001, 0x00ffb81b, 0x808f0000, 0x806f001f, + 0x80af001f, 0x80270140, 0x81e70228, 0x5de2b80f, + 0xb6000208, 0x00cfb801, 0x01ffb0bc, 0x59e2b80f, + 0x01cfb80f, 0x01ff90bc, 0xb520ffff, 0x91ef0020, + 0x90210020, 0x80270180, 0x81e70120, 0x5de2b80f, + 0xb6000208, 0x00cfb801, 0x01ffb0bc, 0x59e2b80f, + 0x01cfb80f, 0x01ff90bc, 0xb520ffff, 0x91ef0020, + 0x90210020, 0x8057ffff, 0x80170430, 0x80070410, + 0x80270408, 0xb6000509, 0x005ff000, 0x90420500, + 0x007ff001, 0x90630600, 0x009ff002, 0x00bff003, + 0x2004a025, 0x90000001, 0x90210001, 0x80070414, + 0x80d7ffff, 0x8097045c, 0x8017043c, 0xb6000404, + 0x005ff000, 0x007f87e0, 0x84000001, 0x2082a7e3, + 0x80970460, 0x80170440, 0x2082b803, 0x007f8000, + 0x2083a004, 0x80170430, 0x80970450, 0x80270408, + 0xb6000508, 0x005f8024, 0x90420500, 0x007ff001, + 0x90630600, 0x009ff002, 0x00bff003, 0x2004a025, + 0x90210001, 0x80170440, 0x00000000, 0x02bf87e0, + 0x80970460, 0x82870000, 0xb6000404, 0x005f87e4, + 0x5a88b814, 0x204287e0, 0x1a94b802, 0x00ffb81c, + 0x001f0a49, 0x001f2709, 0x001f0a41, 0x001f2708, + 0x001f0a46, 0x001f2707, 0x001f0a48, 0x001f2706, + 0x001f0a42, 0x001f2705, 0x001f0a47, 0x001f2704, + 0x001f0a45, 0x001f2703, 0x001f0a43, 0x001f2702, + 0x001f0a40, 0x001f2701, 0x001f0a44, 0x001f2700, + 0x001f0c25, 0xa020000c, 0x94400001, 0x94600002, + 0x94810004, 0x94a10008, 0x94c00010, 0x5943b802, + 0x5861b803, 0x5882b804, 0x5ca2b805, 0x5cc4b806, + 0x194ab803, 0x194ab804, 0x194ab805, 0x194ab806, + 0x015f2738, 0x801b0220, 0x003f91c1, 0x5c28b801, + 0x005f91c2, 0x5858b802, 0x1821b802, 0x2000b801, + 0x001fb1c4, 0x80180224, 0x003f0709, 0x2000b801, + 0x001f2714, 0x82c70001, 0x82e70001, 0x83070710, + 0x8327001e, 0x81970735, 0x8384009f, 0x02df0738, + 0x82170a30, 0x838400f1, 0x819efef0, 0x817cfef4, + 0x819eff68, 0x817cff6c, 0x00ffb81b, 0x820f001f, + 0x8018fef8, 0x8057ffff, 0x001f2709, 0x8018fef6, + 0x80d7ffff, 0x001f2708, 0x8018fefa, 0x8157ffff, + 0x001f2707, 0x8018fefd, 0x81d7ffff, 0x001f2706, + 0x8018fefb, 0x802f001f, 0x001f2705, 0x8018fefe, + 0x00000000, 0x001f2704, 0x8018fef9, 0x00000000, + 0x001f2703, 0x8018feff, 0x00000000, 0x001f2702, + 0x8018fef7, 0x00000000, 0x001f2701, 0x8018fefc, + 0x00000000, 0x001f2700, 0x001f0c25, 0xa0200011, + 0x94410001, 0x94600002, 0x94800004, 0x94a00008, + 0x94c10010, 0x5941b802, 0x5861b803, 0x5c82b804, + 0x58a1b805, 0x5cc1b806, 0x194ab803, 0x194ab804, + 0x194ab805, 0x194ab806, 0x015f2738, 0x801b0220, + 0x003f91c1, 0x5c28b801, 0x005f91c2, 0x5858b802, + 0x1821b802, 0x2000b801, 0x001fb1c4, 0x80180224, + 0x003f0709, 0x2000b801, 0x001f2714, 0x82c70001, + 0x82e70001, 0x83070710, 0x8327001e, 0x81970735, + 0x83840055, 0x02df0738, 0x82170a20, 0x838400a7, + 0x819efef0, 0x817cfef4, 0x5ac8b80c, 0x02ff0a44, + 0x1ad6b817, 0x02dfb291, 0x5ed8b80c, 0x5968b80b, + 0x1ad6b80b, 0x02df6524, 0x00ffb81b, 0x820f001f, + 0x8018fefe, 0x8057ffff, 0x001f2709, 0x8018fefa, + 0x80d7ffff, 0x001f2708, 0x8018fefc, 0x8157ffff, + 0x001f2707, 0x8018feff, 0x81d7ffff, 0x001f2706, + 0x8018fef8, 0x802f001f, 0x001f2705, 0x8018fefb, + 0x00000000, 0x001f2704, 0x8018fefd, 0x00000000, + 0x001f2703, 0x8018fef6, 0x00000000, 0x001f2702, + 0x8018fef9, 0x00000000, 0x001f2701, 0x8018fef7, + 0x00000000, 0x001f2700, 0x801b0220, 0x003f91c1, + 0x5c28b801, 0x005f91c2, 0x5858b802, 0x1821b802, + 0x2000b801, 0x001fb1c4, 0x80180224, 0x003f0709, + 0x2000b801, 0x001f2714, 0x82c70001, 0x82e70001, + 0x83070710, 0x8327001e, 0x81970735, 0x83840016, + 0x83270000, 0x831bfef0, 0x82f8fef4, 0x02c7b819, + 0x82170a28, 0x83840065, 0x300cb818, 0xb4200002, + 0x300bb817, 0xb4000006, 0x93390001, 0xb0190020, + 0xb480fff6, 0x83270000, 0x833cfef5, 0x00ffb81b, + 0x019fb290, 0x017f2a44, 0x033f2c25, 0x83270001, + 0x833cfef5, 0x00ffb81b, 0x0007b818, 0x90000003, + 0x00000000, 0x015ff000, 0x90000001, 0x5949b80a, + 0x013ff000, 0x194ab809, 0x84000002, 0x994a0100, + 0x017ff000, 0x958b00f8, 0x5981b80c, 0x956b0007, + 0x198cb80b, 0x84000002, 0x998c0008, 0x017ff000, + 0x90000001, 0x5971b80b, 0x198cb80b, 0x017ff000, + 0x5969b80b, 0x198cb80b, 0x81a70000, 0x94d90003, + 0x82a70000, 0xb6260019, 0xb6000818, 0x5df0b80a, + 0x5e02b80a, 0x21efb810, 0x95ef0001, 0x5941b80a, + 0x194ab80f, 0x21efb816, 0x5e18b80c, 0x5e35b80c, + 0x5e54b80c, 0x5e6cb80c, 0x2210b811, 0x2252b813, + 0x2210b812, 0x96100001, 0x5981b80c, 0x198cb810, + 0x2210b817, 0x10afb810, 0x10a5b80d, 0x5da1b805, + 0x94a50001, 0x5aa1b815, 0x1ab5b805, 0x019fa7f5, + 0x5cc2b819, 0xb626001c, 0x82870000, 0xb6000419, + 0xb6000818, 0x5df0b80a, 0x5e02b80a, 0x21efb810, + 0x95ef0001, 0x5941b80a, 0x194ab80f, 0x21efb816, + 0x5e18b80c, 0x5e35b80c, 0x5e54b80c, 0x5e6cb80c, + 0x2210b811, 0x2252b813, 0x2210b812, 0x96100001, + 0x5981b80c, 0x198cb810, 0x2210b817, 0x10afb810, + 0x10a5b80d, 0x5da1b805, 0x94a50001, 0x5a81b814, + 0x1a94b805, 0x019fa7f4, 0x00ffb81c, 0x8257ffff, + 0x808f0000, 0x806f001f, 0x80af001f, 0x80270200, + 0x81e7ff00, 0x5de2b80f, 0xb6000208, 0x00cfb801, + 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, 0x01ff90bc, + 0xb520ffff, 0x91ef0020, 0x90210020, 0x80270240, + 0x81e70000, 0x5de2b80f, 0xb6000208, 0x00cfb801, + 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, 0x01ff90bc, + 0xb520ffff, 0x91ef0020, 0x90210020, 0x80270180, + 0x81e70120, 0x5de2b80f, 0xb6000208, 0x00cfb801, + 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, 0x01ff90bc, + 0xb520ffff, 0x91ef0020, 0x90210020, 0x806f0007, + 0x80af0007, 0x80270280, 0x81e70100, 0x5de2b80f, + 0x00cfb801, 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, + 0x01ff90bc, 0xb520ffff, 0x91ef0020, 0x90210020, + 0x80170760, 0x001f0700, 0x001fa020, 0x001f0701, + 0x001fa020, 0x001f0702, 0x001fa020, 0x001f0703, + 0x001fa020, 0x001f0704, 0x001fa000, 0x80970750, + 0x81170770, 0x82a70735, 0x83a40060, 0x001f87e4, + 0xb6000405, 0x86b50001, 0x83a4005c, 0x001f8004, + 0x003f87e8, 0x2080a7e1, 0x80970770, 0x80170750, + 0x81170750, 0x81970740, 0x82a70730, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a40050, 0x001f87e4, + 0xb6000405, 0x86b50001, 0x83a4004c, 0x001f8004, + 0x003f87e8, 0x2080a7e1, 0x80970750, 0x80170770, + 0x81170770, 0x81970760, 0x82a7072b, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a40040, 0x83a4004e, + 0xb6000407, 0x86b50001, 0x83a4003c, 0x001f8004, + 0x003f87e8, 0x2080a001, 0x83a40047, 0x00000000, + 0x80970770, 0x80170750, 0x81170750, 0x81970740, + 0x82a70726, 0x001f800c, 0x003f8008, 0x2100a001, + 0x83a4002e, 0x83a4003c, 0xb6000407, 0x86b50001, + 0x83a4002a, 0x001f8004, 0x003f87e8, 0x2080a001, + 0x83a40035, 0x00000000, 0x80970750, 0x80170770, + 0x81170770, 0x81970760, 0x82a70721, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a4001c, 0x001f87e4, + 0xb6000405, 0x86b50001, 0x83a40018, 0x001f8004, + 0x003f87e8, 0x2080a7e1, 0x80970770, 0x80170750, + 0x81170750, 0x81970740, 0x82a7071c, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a4000c, 0x017f87e4, + 0x81870000, 0xb6000406, 0x86b50001, 0x83a40007, + 0x001f87e4, 0x200087e8, 0x5988b80c, 0x198cb800, + 0x021fa02c, 0x021fa00b, 0x00ffb81c, 0x005ff015, + 0x90420600, 0x003f87e0, 0x001ff002, 0x2060b801, + 0x90630800, 0x90960a00, 0x001ff003, 0x003ff004, + 0x20a0b801, 0x90a50900, 0x00000000, 0x001ff005, + 0x009fa000, 0x00ffb81d, 0x001f8004, 0x5c21b800, + 0x5847b800, 0x1821b802, 0x942100ff, 0x2080a7e1, + 0x00ffb81d, 0x00000000, 0x00000000, 0x00000000, + 0x829bff80, 0x80af001f, 0x808f0000, 0x806f0000, + 0x82bbffec, 0x82fbffe4, 0x00000000, 0x82beffb8, + 0x95540700, 0x5d48b80a, 0x914a0001, 0x0227b80a, + 0x94343000, 0x5c2cb801, 0xb0010000, 0xb4000001, + 0x5a21b811, 0x9574c000, 0x5d6eb80b, 0x918b4b08, + 0x01b8b80c, 0x96d5ffff, 0x5ec2b816, 0x96f7ffff, + 0x5ee2b817, 0x8057ffff, 0x80d7ffff, 0x8157ffff, + 0x81d7ffff, 0x81f3ff00, 0x99efff00, 0x821300ff, + 0x9a1000ff, 0x81971000, 0x82670000, 0x82470000, + 0x80270280, 0x81df0000, 0x00000000, 0x00000000, + 0xb62d000d, 0x3016b817, 0xb4800001, 0x86d62800, + 0x00cfb801, 0x02dfb0bc, 0x5ac2b816, 0x01cfb816, + 0x02df90bc, 0x0067b86f, 0xb0030001, 0xb4c0fffd, + 0x92d60020, 0x90210020, 0x81df0004, 0x80170a00, + 0x81df0000, 0x00000000, 0x00000000, 0xb62d0006, + 0xb6002005, 0x146f8000, 0x14908000, 0x5c68b803, + 0x5888b804, 0x1803a024, 0x81df0004, 0x80170a00, + 0x80970d00, 0xb00b0000, 0xb4000004, 0xb00b0001, + 0xb400000a, 0xb00b0002, 0xb4000027, 0x81df0000, + 0x00000000, 0x00000000, 0xb6008002, 0x007f8020, + 0x009fa023, 0x81df0004, 0xb5000029, 0x80d3ffff, + 0x81df0000, 0x00000000, 0x00000000, 0xb6002018, + 0x5c648000, 0x9463ffff, 0x5c888020, 0x58b88000, + 0x1884b805, 0x1484b806, 0x1883a024, 0x5c6c8020, + 0x9463ffff, 0x58908000, 0x1883a024, 0x5c748020, + 0x588c8000, 0x1863b804, 0x9463ffff, 0x58888000, + 0x1484b806, 0x1883a024, 0x5c7c8020, 0x58848000, + 0x1863b804, 0x9463ffff, 0x14868020, 0x1883a024, + 0x81df0004, 0xb500000a, 0x80d3ffff, 0x81df0000, + 0x00000000, 0x00000000, 0xb6004004, 0x007f8020, + 0x009fa023, 0x007f8040, 0x009fa023, 0x81df0004, + 0x00000000, 0x81170d00, 0x80070000, 0x94343000, + 0x5c2cb801, 0xb0010001, 0xb400008e, 0xb00a0001, + 0xb400000e, 0xb00a0002, 0xb400001c, 0xb00a0003, + 0xb4000024, 0xb00a0004, 0xb4000052, 0xb00a0005, + 0xb400005b, 0xb00a0006, 0xb400007f, 0xb00a0007, + 0xb400007d, 0xb00a0008, 0xb400007b, 0x81df0000, + 0x00000000, 0x00000000, 0xb600800a, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x019fa020, 0x019fa020, + 0x5c708028, 0x9463ffff, 0x019fa023, 0x019fa020, + 0x019fa020, 0x81df0004, 0xb500006b, 0x81df0000, + 0x00000000, 0x00000000, 0xb6008004, 0x007f8028, + 0x019fa023, 0x019fa020, 0x019fa020, 0x81df0004, + 0xb5000061, 0xb0130000, 0xb4000004, 0xb0130001, + 0xb4000009, 0xb0130002, 0xb400001a, 0x83a400fa, + 0x80170f00, 0x007f8028, 0x001fa023, 0x007f8028, + 0x001fa023, 0xb5000054, 0x80170f00, 0x00000000, + 0x007f8020, 0x019fa023, 0x007f8000, 0x9463ffff, + 0x019fa023, 0x019fa020, 0x5c708020, 0x58908008, + 0x1983a024, 0x5c708028, 0x019fa023, 0x019fa020, + 0x83a400e5, 0x80170f00, 0x007f8028, 0x001fa023, + 0xb5000041, 0x80170f00, 0x00000000, 0x007f8020, + 0x019fa023, 0x007f8008, 0x9463ffff, 0x019fa023, + 0x019fa020, 0x5c708028, 0x58908008, 0x1983a024, + 0x5c708028, 0x019fa023, 0x019fa020, 0x83a400d2, + 0xb5000031, 0x81df0000, 0x00000000, 0x00000000, + 0xb6004005, 0x007f8008, 0x019fa023, 0x007f8008, + 0x019fa023, 0x019fa020, 0x81df0004, 0xb5000026, + 0xb0130000, 0xb4000008, 0xb0130001, 0xb4000012, + 0xb0130002, 0xb400001f, 0xb0130003, 0xb400001d, + 0xb0130004, 0xb400001b, 0x83a400cd, 0x007f8028, + 0x019fa023, 0x007f8028, 0x019fa023, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x80170f00, 0x007f8028, + 0x001fa023, 0xb5000010, 0x80170f00, 0x00000000, + 0x5c708020, 0x58908008, 0x1983a024, 0x5c708028, + 0x58908008, 0x1983a024, 0x5c708028, 0x019fa023, + 0x83a400b7, 0x80170f00, 0x007f8028, 0x001fa023, + 0xb5000001, 0xb5000000, 0x00000000, 0x00000000, + 0xb5000086, 0xb00a0001, 0xb400000e, 0xb00a0002, + 0xb4000017, 0xb00a0003, 0xb400001f, 0xb00a0004, + 0xb400004d, 0xb00a0005, 0xb4000056, 0xb00a0006, + 0xb400007a, 0xb00a0007, 0xb4000078, 0xb00a0008, + 0xb4000076, 0x81df0000, 0x00000000, 0x00000000, + 0xb6008005, 0x007f8028, 0x9463ffff, 0x019fa023, + 0x019fa020, 0x019fa020, 0x81df0004, 0xb500006b, + 0x81df0000, 0x00000000, 0x00000000, 0xb6004004, + 0x007f8048, 0x019fa023, 0x019fa020, 0x019fa020, + 0x81df0004, 0xb5000061, 0xb0130000, 0xb4000004, + 0xb0130001, 0xb4000009, 0xb0130002, 0xb400001a, + 0x83a40098, 0x80170f00, 0x007f8028, 0x001fa023, + 0x007f8028, 0x001fa023, 0xb5000054, 0x80170f00, + 0x00000000, 0x007f8020, 0x019fa023, 0x007f8000, + 0x9463ffff, 0x019fa023, 0x019fa020, 0x5c708020, + 0x58908008, 0x1983a024, 0x5c708028, 0x019fa023, + 0x019fa020, 0x83a40083, 0x80170f00, 0x007f8028, + 0x001fa023, 0xb5000041, 0x80170f00, 0x00000000, + 0x007f8020, 0x019fa023, 0x007f8008, 0x9463ffff, + 0x019fa023, 0x019fa020, 0x5c708028, 0x58908008, + 0x1983a024, 0x5c708028, 0x019fa023, 0x019fa020, + 0x83a40070, 0xb5000031, 0x81df0000, 0x00000000, + 0x00000000, 0xb6004005, 0x007f8008, 0x019fa023, + 0x007f8008, 0x019fa023, 0x019fa020, 0x81df0004, + 0xb5000026, 0xb0130000, 0xb4000008, 0xb0130001, + 0xb4000012, 0xb0130002, 0xb400001f, 0xb0130003, + 0xb400001d, 0xb0130004, 0xb400001b, 0x83a4006b, + 0x007f8028, 0x019fa023, 0x007f8028, 0x019fa023, + 0x007f8008, 0x9463ffff, 0x019fa023, 0x80170f00, + 0x007f8028, 0x001fa023, 0xb5000010, 0x80170f00, + 0x00000000, 0x5c708020, 0x58908008, 0x1983a024, + 0x5c708028, 0x58908008, 0x1983a024, 0x5c708028, + 0x019fa023, 0x83a40055, 0x80170f00, 0x007f8028, + 0x001fa023, 0xb5000001, 0xb5000000, 0x92730001, + 0x92520001, 0x3012b811, 0xb480fe89, 0x003f0324, + 0x90210001, 0xb0010006, 0xb4a00001, 0x80270001, + 0x003f2324, 0x2c8db811, 0x803bffe0, 0x805bffe4, + 0x5887b804, 0x1015b804, 0xad440003, 0x3000b802, + 0xb4800001, 0x8400a000, 0x801effec, 0x015f6193, + 0x809e4b04, 0x00ffb81f, 0x81df0000, 0x00000000, + 0x00000000, 0xb6002a0c, 0x007f8028, 0x019fa023, + 0x007f8008, 0x9463ffff, 0x019fa023, 0x019fa020, + 0x5c708028, 0x58908008, 0x1983a024, 0x5c708028, + 0x019fa023, 0x019fa020, 0x81df0004, 0x00ffb81d, + 0x81df0000, 0x00000000, 0x00000000, 0xb600190f, + 0x007f8028, 0x019fa023, 0x007f8028, 0x019fa023, + 0x007f8008, 0x9463ffff, 0x019fa023, 0x5c708028, + 0x58908008, 0x1983a024, 0x5c708028, 0x58908008, + 0x1983a024, 0x5c708028, 0x019fa023, 0x81df0004, + 0x00ffb81d, 0x81df0000, 0x00000000, 0x00000000, + 0xb6002a0c, 0x007f8028, 0x019fa023, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x019fa020, 0x5c708028, + 0x58908008, 0x1983a024, 0x5c708028, 0x019fa023, + 0x019fa020, 0x81df0004, 0x00ffb81d, 0x81df0000, + 0x00000000, 0x00000000, 0xb600190f, 0x007f8028, + 0x019fa023, 0x007f8028, 0x019fa023, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x5c708028, 0x58908008, + 0x1983a024, 0x5c708028, 0x58908008, 0x1983a024, + 0x5c708028, 0x019fa023, 0x81df0004, 0x00ffb81d, + 0x829bff80, 0x80af001f, 0x808f0000, 0x806f0000, + 0x82bbffec, 0x82fbffe4, 0x00000000, 0x82beffb8, + 0x95540700, 0x5d48b80a, 0x914a0001, 0x0227b80a, + 0x94343000, 0x5c2cb801, 0xb0010000, 0xb4000001, + 0x5a21b811, 0x9574c000, 0x5d6eb80b, 0x918b4b08, + 0x01b8b80c, 0x96d5ffff, 0x5ec2b816, 0x96f7ffff, + 0x5ee2b817, 0x8057ffff, 0x80d7ffff, 0x8157ffff, + 0x81d7ffff, 0x81f3ff00, 0x99efff00, 0x821300ff, + 0x9a1000ff, 0x81971000, 0x82670000, 0x82470000, + 0x80270280, 0x81df0000, 0x00000000, 0x00000000, + 0xb62d000d, 0x3016b817, 0xb4800001, 0x86d62800, + 0x00cfb801, 0x02dfb0bc, 0x5ac2b816, 0x01cfb816, + 0x02df90bc, 0x0067b86f, 0xb0030001, 0xb4c0fffd, + 0x92d60020, 0x90210020, 0x81df0004, 0x80170a00, + 0x81df0000, 0x00000000, 0x00000000, 0xb62d0006, + 0xb6002005, 0x146f8000, 0x14908000, 0x5c68b803, + 0x5888b804, 0x1803a024, 0x81df0004, 0x80170a00, + 0x80970d00, 0xb00b0000, 0xb4000004, 0xb00b0001, + 0xb400000a, 0xb00b0002, 0xb4000027, 0x81df0000, + 0x00000000, 0x00000000, 0xb6008002, 0x007f8020, + 0x009fa023, 0x81df0004, 0xb5000029, 0x80d3ffff, + 0x81df0000, 0x00000000, 0x00000000, 0xb6002018, + 0x5c648000, 0x9463ffff, 0x5c888020, 0x58b88000, + 0x1884b805, 0x1484b806, 0x1883a024, 0x5c6c8020, + 0x9463ffff, 0x58908000, 0x1883a024, 0x5c748020, + 0x588c8000, 0x1863b804, 0x9463ffff, 0x58888000, + 0x1484b806, 0x1883a024, 0x5c7c8020, 0x58848000, + 0x1863b804, 0x9463ffff, 0x14868020, 0x1883a024, + 0x81df0004, 0xb500000a, 0x80d3ffff, 0x81df0000, + 0x00000000, 0x00000000, 0xb6004004, 0x007f8020, + 0x009fa023, 0x007f8040, 0x009fa023, 0x81df0004, + 0x00000000, 0x81170d00, 0x80070000, 0x94343000, + 0x5c2cb801, 0xb0010001, 0xb400008e, 0xb00a0001, + 0xb400000e, 0xb00a0002, 0xb400001c, 0xb00a0003, + 0xb4000024, 0xb00a0004, 0xb4000052, 0xb00a0005, + 0xb400005b, 0xb00a0006, 0xb400007f, 0xb00a0007, + 0xb400007d, 0xb00a0008, 0xb400007b, 0x81df0000, + 0x00000000, 0x00000000, 0xb600800a, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x019fa020, 0x019fa020, + 0x5c708028, 0x9463ffff, 0x019fa023, 0x019fa020, + 0x019fa020, 0x81df0004, 0xb500006b, 0x81df0000, + 0x00000000, 0x00000000, 0xb6008004, 0x007f8028, + 0x019fa023, 0x019fa020, 0x019fa020, 0x81df0004, + 0xb5000061, 0xb0130000, 0xb4000004, 0xb0130001, + 0xb4000009, 0xb0130002, 0xb400001a, 0x83a400fa, + 0x80170f00, 0x007f8028, 0x001fa023, 0x007f8028, + 0x001fa023, 0xb5000054, 0x80170f00, 0x00000000, + 0x007f8020, 0x019fa023, 0x007f8000, 0x9463ffff, + 0x019fa023, 0x019fa020, 0x5c708020, 0x58908008, + 0x1983a024, 0x5c708028, 0x019fa023, 0x019fa020, + 0x83a400e5, 0x80170f00, 0x007f8028, 0x001fa023, + 0xb5000041, 0x80170f00, 0x00000000, 0x007f8020, + 0x019fa023, 0x007f8008, 0x9463ffff, 0x019fa023, + 0x019fa020, 0x5c708028, 0x58908008, 0x1983a024, + 0x5c708028, 0x019fa023, 0x019fa020, 0x83a400d2, + 0xb5000031, 0x81df0000, 0x00000000, 0x00000000, + 0xb6004005, 0x007f8008, 0x019fa023, 0x007f8008, + 0x019fa023, 0x019fa020, 0x81df0004, 0xb5000026, + 0xb0130000, 0xb4000008, 0xb0130001, 0xb4000012, + 0xb0130002, 0xb400001f, 0xb0130003, 0xb400001d, + 0xb0130004, 0xb400001b, 0x83a400cd, 0x007f8028, + 0x019fa023, 0x007f8028, 0x019fa023, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x80170f00, 0x007f8028, + 0x001fa023, 0xb5000010, 0x80170f00, 0x00000000, + 0x5c708020, 0x58908008, 0x1983a024, 0x5c708028, + 0x58908008, 0x1983a024, 0x5c708028, 0x019fa023, + 0x83a400b7, 0x80170f00, 0x007f8028, 0x001fa023, + 0xb5000001, 0xb5000000, 0x00000000, 0x00000000, + 0xb5000086, 0xb00a0001, 0xb400000e, 0xb00a0002, + 0xb4000017, 0xb00a0003, 0xb400001f, 0xb00a0004, + 0xb400004d, 0xb00a0005, 0xb4000056, 0xb00a0006, + 0xb400007a, 0xb00a0007, 0xb4000078, 0xb00a0008, + 0xb4000076, 0x81df0000, 0x00000000, 0x00000000, + 0xb6008005, 0x007f8028, 0x9463ffff, 0x019fa023, + 0x019fa020, 0x019fa020, 0x81df0004, 0xb500006b, + 0x81df0000, 0x00000000, 0x00000000, 0xb6004004, + 0x007f8048, 0x019fa023, 0x019fa020, 0x019fa020, + 0x81df0004, 0xb5000061, 0xb0130000, 0xb4000004, + 0xb0130001, 0xb4000009, 0xb0130002, 0xb400001a, + 0x83a40098, 0x80170f00, 0x007f8028, 0x001fa023, + 0x007f8028, 0x001fa023, 0xb5000054, 0x80170f00, + 0x00000000, 0x007f8020, 0x019fa023, 0x007f8000, + 0x9463ffff, 0x019fa023, 0x019fa020, 0x5c708020, + 0x58908008, 0x1983a024, 0x5c708028, 0x019fa023, + 0x019fa020, 0x83a40083, 0x80170f00, 0x007f8028, + 0x001fa023, 0xb5000041, 0x80170f00, 0x00000000, + 0x007f8020, 0x019fa023, 0x007f8008, 0x9463ffff, + 0x019fa023, 0x019fa020, 0x5c708028, 0x58908008, + 0x1983a024, 0x5c708028, 0x019fa023, 0x019fa020, + 0x83a40070, 0xb5000031, 0x81df0000, 0x00000000, + 0x00000000, 0xb6004005, 0x007f8008, 0x019fa023, + 0x007f8008, 0x019fa023, 0x019fa020, 0x81df0004, + 0xb5000026, 0xb0130000, 0xb4000008, 0xb0130001, + 0xb4000012, 0xb0130002, 0xb400001f, 0xb0130003, + 0xb400001d, 0xb0130004, 0xb400001b, 0x83a4006b, + 0x007f8028, 0x019fa023, 0x007f8028, 0x019fa023, + 0x007f8008, 0x9463ffff, 0x019fa023, 0x80170f00, + 0x007f8028, 0x001fa023, 0xb5000010, 0x80170f00, + 0x00000000, 0x5c708020, 0x58908008, 0x1983a024, + 0x5c708028, 0x58908008, 0x1983a024, 0x5c708028, + 0x019fa023, 0x83a40055, 0x80170f00, 0x007f8028, + 0x001fa023, 0xb5000001, 0xb5000000, 0x92730001, + 0x92520001, 0x3012b811, 0xb480fe89, 0x003f0324, + 0x90210001, 0xb0010006, 0xb4a00001, 0x80270001, + 0x003f2324, 0x2c8db811, 0x803bffe0, 0x805bffe4, + 0x5887b804, 0x1015b804, 0xad440003, 0x3000b802, + 0xb4800001, 0x8400a000, 0x801effec, 0x015f6193, + 0x809e4b04, 0x00ffb81f, 0x81df0000, 0x00000000, + 0x00000000, 0xb6002a0c, 0x007f8028, 0x019fa023, + 0x007f8008, 0x9463ffff, 0x019fa023, 0x019fa020, + 0x5c708028, 0x58908008, 0x1983a024, 0x5c708028, + 0x019fa023, 0x019fa020, 0x81df0004, 0x00ffb81d, + 0x81df0000, 0x00000000, 0x00000000, 0xb600190f, + 0x007f8028, 0x019fa023, 0x007f8028, 0x019fa023, + 0x007f8008, 0x9463ffff, 0x019fa023, 0x5c708028, + 0x58908008, 0x1983a024, 0x5c708028, 0x58908008, + 0x1983a024, 0x5c708028, 0x019fa023, 0x81df0004, + 0x00ffb81d, 0x81df0000, 0x00000000, 0x00000000, + 0xb6002a0c, 0x007f8028, 0x019fa023, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x019fa020, 0x5c708028, + 0x58908008, 0x1983a024, 0x5c708028, 0x019fa023, + 0x019fa020, 0x81df0004, 0x00ffb81d, 0x81df0000, + 0x00000000, 0x00000000, 0xb600190f, 0x007f8028, + 0x019fa023, 0x007f8028, 0x019fa023, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x5c708028, 0x58908008, + 0x1983a024, 0x5c708028, 0x58908008, 0x1983a024, + 0x5c708028, 0x019fa023, 0x81df0004, 0x00ffb81d, + 0x003f03f9, 0x009f0324, 0x84840001, 0xb0010000, + 0xb4000011, 0x815b4b0c, 0x81070000, 0x81270bf4, + 0xb00a0000, 0xb4000002, 0x81070c00, 0x812717f4, + 0x802500a5, 0x806500a5, 0x3001b803, 0xb420fffc, + 0x9421ffff, 0x3001b808, 0xb480000b, 0x3001b809, + 0xb4a00060, 0xb5000008, 0xb0040000, 0xb4200003, + 0x802717ff, 0x81470000, 0xb5000003, 0x80270001, + 0x003f23f9, 0x81470c00, 0xb0040000, 0xb4200006, + 0x039f4193, 0x5b81b81c, 0x003f90cb, 0x1021b81c, + 0x003fb0cb, 0x8384f922, 0x829bff80, 0x801300e0, + 0x1434b800, 0x5c35b801, 0x8013001f, 0x1454b800, + 0x5c50b802, 0x8073007f, 0x9863ffff, 0xb002000f, + 0xb4800001, 0x90210001, 0x84210004, 0xb0010000, + 0xb4a00001, 0x6861b803, 0x005f9040, 0x4082b803, + 0x80af001f, 0x808f0000, 0x806f0000, 0x8007ffff, + 0x8033ffff, 0x80171000, 0x81df0000, 0x00000000, + 0x00000000, 0xb6001811, 0xb6002010, 0x14618000, + 0x6068b803, 0x40c4b803, 0x14608000, 0x00c8b806, + 0x5870b803, 0x6068b803, 0x4104b803, 0x58c8b806, + 0x0108b808, 0x14c6b801, 0x00000000, 0x00000000, + 0x5d08b808, 0x1508b800, 0x1806a028, 0x81df0004, + 0x80670400, 0x5d22b80a, 0x81df0000, 0x00000000, + 0x00000000, 0xb600180a, 0x00cfb803, 0x013fb0bc, + 0x5922b809, 0x01afb809, 0x013f90bc, 0x0047b86f, + 0xb0020001, 0xb4c0fffd, 0x90630020, 0x91290020, + 0x81df0004, 0x808f0000, 0x801b4b14, 0x80270001, + 0xb0000001, 0xb4000002, 0x802600a0, 0x803e4b14, + 0x81270c00, 0xb00a0000, 0xb4000001, 0x81270000, + 0x813e4b0c, 0x80270001, 0x003f2013, 0x80050086, + 0x001fb044, 0x00ffb81b, 0x00000000, 0x00000000, +}; + +static u32 PCMUcode1f4b00[] = { + 0x00000000, 0x00000000, 0x00060504, 0x00000000, + 0x00000000, 0x00000000, 0x00300000, 0xffcfcfff, + 0x00302000, 0xffcfcfff, 0x00380000, 0xffc7c7ff, + 0xcbcecdc4, 0xcfcac9c8, 0xc3c6c5cc, 0xc7c2c1c0, + 0x1b1e1d14, 0x1f1a1918, 0x1316151c, 0x17121110, + 0x2b2e2d24, 0x2f2a2928, 0x2326252c, 0x27222120, + 0x3b3e3d34, 0x3f3a3938, 0x3336353c, 0x37323130, + 0x0b0e0d04, 0x0f0a0908, 0x0306050c, 0x07020100, + 0xdbdeddd4, 0xdfdad9d8, 0xd3d6d5dc, 0xd7d2d1d0, + 0xebeeede4, 0xefeae9e8, 0xe3e6e5ec, 0xe7e2e1e0, + 0xfbfefdf4, 0xfffaf9f8, 0xf3f6f5fc, 0xf7f2f1f0, + 0x4b4e4d44, 0x4f4a4948, 0x4346454c, 0x47424140, + 0x9b9e9d94, 0x9f9a9998, 0x9396959c, 0x97929190, + 0xabaeada4, 0xafaaa9a8, 0xa3a6a5ac, 0xa7a2a1a0, + 0xbbbebdb4, 0xbfbab9b8, 0xb3b6b5bc, 0xb7b2b1b0, + 0x8b8e8d84, 0x8f8a8988, 0x8386858c, 0x87828180, + 0x5b5e5d54, 0x5f5a5958, 0x5356555c, 0x57525150, + 0x6b6e6d64, 0x6f6a6968, 0x6366656c, 0x67626160, + 0x7b7e7d74, 0x7f7a7978, 0x7376757c, 0x77727170, + 0x341424c4, 0x3e1e2ece, 0x3d1d2dcd, 0x3b1b2bcb, + 0xb494a444, 0xbe9eae4e, 0xbd9dad4d, 0xbb9bab4b, + 0xf4d4e404, 0xfedeee0e, 0xfddded0d, 0xfbdbeb0b, + 0x74546484, 0x7e5e6e8e, 0x7d5d6d8d, 0x7b5b6b8b, + 0x3c1c2ccc, 0x361626c6, 0x351525c5, 0x331323c3, + 0xbc9cac4c, 0xb696a646, 0xb595a545, 0xb393a343, + 0xfcdcec0c, 0xf6d6e606, 0xf5d5e505, 0xf3d3e303, + 0x7c5c6c8c, 0x76566686, 0x75556585, 0x73536383, + 0x381828c8, 0x3a1a2aca, 0x391929c9, 0x3f1f2fcf, + 0xb898a848, 0xba9aaa4a, 0xb999a949, 0xbf9faf4f, + 0xf8d8e808, 0xfadaea0a, 0xf9d9e909, 0xffdfef0f, + 0x78586888, 0x7a5a6a8a, 0x79596989, 0x7f5f6f8f, + 0x301020c0, 0x321222c2, 0x311121c1, 0x371727c7, + 0xb090a040, 0xb292a242, 0xb191a141, 0xb797a747, + 0xf0d0e000, 0xf2d2e202, 0xf1d1e101, 0xf7d7e707, + 0x70506080, 0x72526282, 0x71516181, 0x77576787, + 0x05040100, 0x15141110, 0x25242120, 0x35343130, + 0x85848180, 0x95949190, 0xa5a4a1a0, 0xb5b4b1b0, + 0xc0408000, 0xe060a020, 0xd0509010, 0xf070b030, + 0xc8488808, 0xe868a828, 0xd8589818, 0xf878b838, + 0xc4448404, 0xe464a424, 0xd4549414, 0xf474b434, + 0xcc4c8c0c, 0xec6cac2c, 0xdc5c9c1c, 0xfc7cbc3c, + 0xc2428202, 0xe262a222, 0xd2529212, 0xf272b232, + 0xca4a8a0a, 0xea6aaa2a, 0xda5a9a1a, 0xfa7aba3a, + 0xc6468606, 0xe666a626, 0xd6569616, 0xf676b636, + 0xce4e8e0e, 0xee6eae2e, 0xde5e9e1e, 0xfe7ebe3e, + 0xc1418101, 0xe161a121, 0xd1519111, 0xf171b131, + 0xc9498909, 0xe969a929, 0xd9599919, 0xf979b939, + 0xc5458505, 0xe565a525, 0xd5559515, 0xf575b535, + 0xcd4d8d0d, 0xed6dad2d, 0xdd5d9d1d, 0xfd7dbd3d, + 0xc3438303, 0xe363a323, 0xd3539313, 0xf373b333, + 0xcb4b8b0b, 0xeb6bab2b, 0xdb5b9b1b, 0xfb7bbb3b, + 0xc7478707, 0xe767a727, 0xd7579717, 0xf777b737, + 0xcf4f8f0f, 0xef6faf2f, 0xdf5f9f1f, 0xff7fbf3f, + 0x1045a3e2, 0x000000f4, 0x263b7333, 0x766b2363, + 0x2b367e3e, 0x7b662e6e, 0x06db93d3, 0x964b0343, + 0x0bd69ede, 0x9b460e4e, 0x825f1757, 0x12cf87c7, + 0x8f521a5a, 0x1fc28aca, 0x00d199d9, 0x90410949, + 0x01d098d8, 0x91400848, 0x24357d3d, 0x74652d6d, + 0x25347c3c, 0x75642c6c, 0x04d59ddd, 0x94450d4d, + 0x05d49cdc, 0x95440c4c, 0x80511959, 0x10c189c9, + 0x81501858, 0x11c088c8, 0x02df97d7, 0x924f0747, + 0x0fd29ada, 0x9f420a4a, 0x865b1353, 0x16cb83c3, + 0x8b561e5e, 0x1bc68ece, 0xa6bbf3b3, 0xf6eba3e3, + 0xabb6febe, 0xfbe6aeee, 0x223f7737, 0x726f2767, + 0x2f327a3a, 0x7f622a6a, 0xa0b1f9b9, 0xf0e1a9e9, + 0xa1b0f8b8, 0xf1e0a8e8, 0x84551d5d, 0x14c58dcd, + 0x85541c5c, 0x15c48ccc, 0xa4b5fdbd, 0xf4e5aded, + 0xa5b4fcbc, 0xf5e4acec, 0x20317939, 0x70612969, + 0x21307838, 0x71602868, 0xa2bff7b7, 0xf2efa7e7, + 0xafb2faba, 0xffe2aaea, 0x00000000, 0x00000000, +}; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/ls220/pcmi2s_240.h linux.19rc3-ac4/drivers/media/video/ls220/pcmi2s_240.h --- linux.19rc3/drivers/media/video/ls220/pcmi2s_240.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/ls220/pcmi2s_240.h 2002-07-29 13:58:41.000000000 +0100 @@ -0,0 +1,877 @@ +static u32 PCMI2S240Ucode1f1800[] = { + 0xb500000f, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xb500020b, 0x00000000, 0x00000000, 0x00000000, + 0x820f001f, 0x802f001f, 0x029f9014, 0x829efef0, + 0x8286000f, 0x02bf0054, 0x82bcfef4, 0x82a6000e, + 0x80074000, 0x001f6193, 0x8013001f, 0x9020c000, + 0x003fb006, 0x803effe8, 0x803effec, 0x9020fa00, + 0x803effd0, 0x803effdc, 0x803effd8, 0x9020fe00, + 0x803effd4, 0x90400000, 0x804600a2, 0x90421800, + 0x804600a3, 0x80132000, 0x98000040, 0x800600a6, + 0x80050080, 0x98000002, 0x80060080, 0x80070001, + 0x001f2013, 0x80070000, 0x001f23f9, 0x801e4b0c, + 0x001f210c, 0x80070001, 0x001f2324, 0x80070800, + 0x001f600f, 0x001fb0cb, 0x001fb010, 0x801efff0, + 0x98004000, 0x001f600e, 0x83e4011f, 0x80070000, + 0x801e4b14, 0x800500a0, 0xb0000001, 0xb4000009, + 0x80070001, 0x800600a0, 0x80050080, 0x98000020, + 0x80060080, 0x9400ffdf, 0x80060080, 0x80070000, + 0x800600a0, 0x80074000, 0x801e4b04, 0x81df0004, + 0x801bfff0, 0x00000000, 0x940000ff, 0xb0000000, + 0xb4200033, 0x003f400e, 0x94010010, 0xb0000000, + 0xb400fff7, 0x003f0013, 0xb0010001, 0xb420001f, + 0x803bffe8, 0x801bffec, 0x805b4b04, 0x00000000, + 0x3001b800, 0xb4600001, 0x9021a000, 0x0421b800, + 0x3001b802, 0xb460000d, 0x80050086, 0x005f9044, + 0x0420b802, 0xb00101e0, 0xb4a0ffe5, 0x001fb010, + 0x001f010c, 0xb0000001, 0xb400ffe1, 0x80070001, + 0x001f210c, 0x83e400ec, 0xb500ffdd, 0x8007001f, + 0x94000003, 0x5810b800, 0x83e719ec, 0x1bffb800, + 0x003f9008, 0x1821b800, 0x00ffb801, 0x80270000, + 0x003f2013, 0x8007001f, 0x94000003, 0x5810b800, + 0x83671a14, 0x1b7bb800, 0x003f9009, 0x1821b800, + 0x00ffb801, 0x80070000, 0x001f210c, 0xb500ffc8, + 0x003f400e, 0xb0000086, 0xb4400055, 0xb0000084, + 0xb400003f, 0xb0000085, 0xb4000045, 0xb0000086, + 0xb4000047, 0xb0000083, 0xb4000000, 0x815bff7c, + 0x00000000, 0x940a0080, 0x5c07b800, 0xb0000001, + 0xb4000073, 0x81674b18, 0x940a0007, 0x5803b800, + 0x116bb800, 0x005bb80b, 0x916b0004, 0x001bb80b, + 0x80530030, 0x98422000, 0x8013ffcf, 0x9800cfff, + 0x806500d4, 0x1463b800, 0x1863b802, 0x806600d4, + 0x80073cfb, 0x801e4b00, 0x800600a1, 0x80074000, + 0x801e4b04, 0x8013001f, 0x98405000, 0x805effe0, + 0x005fb006, 0x805effe8, 0x805effec, 0x9042a000, + 0x805effe4, 0x9040fa00, 0x805effd0, 0x805effdc, + 0x805effd8, 0x9040fe00, 0x805effd4, 0x8013007f, + 0x9800ffff, 0x001fb040, 0x80070001, 0x001f2013, + 0x80070000, 0x001f2324, 0x001fb0cb, 0x001fb010, + 0x001fb041, 0x001fb042, 0x800733b0, 0x001fb008, + 0x80071ea0, 0x001fb009, 0x98214000, 0xb5000010, + 0x94011000, 0xb0001000, 0xb4200001, 0x9421efff, + 0x98210010, 0xb500000a, 0x80070000, 0x001fb0cb, + 0x83e40099, 0x003f400e, 0x9421ffef, 0xb5000004, + 0x83e40095, 0x003f400e, 0x98211000, 0x9421ffef, + 0x003f600e, 0x80070100, 0x801efff0, 0xb500ff70, + 0xb000008b, 0xb4000018, 0xb0000087, 0xb400ffee, + 0xb0000088, 0xb4000016, 0xb000008a, 0xb4000016, + 0xb000008c, 0xb4000017, 0xb0000089, 0xb4000019, + 0xb00000a0, 0xb400001b, 0xb00000a1, 0xb4000047, + 0xb00000a2, 0xb4000054, 0xb00000a3, 0xb400004c, + 0xb00000a4, 0xb4000056, 0xb00000a5, 0xb400005a, + 0xb00000a6, 0xb400005e, 0x803efff8, 0xb500ffe1, + 0x9421ffdf, 0xb500ffde, 0x80270100, 0x803efff8, + 0xb500ffdc, 0x803bffb0, 0x00000000, 0x003fb040, + 0xb500ffd8, 0x803bff80, 0x00000000, 0x003f6001, + 0xb500ffd4, 0x003f90ba, 0x803efff8, 0xb500ffd1, + 0x81674b18, 0x940a0007, 0x5803b800, 0x116bb800, + 0x005bb80b, 0x916b0004, 0x001bb80b, 0x806500d4, + 0x1463b800, 0x1863b802, 0x806600d4, 0x80130001, + 0x98003d21, 0x800600a1, 0x801e4b00, 0x80074000, + 0x801e4b04, 0x8013001f, 0x98405000, 0x805effe0, + 0x005fb006, 0x805effe8, 0x805effec, 0x9042a000, + 0x805effe4, 0x9040fa00, 0x805effd0, 0x805effdc, + 0x805effd8, 0x9040fe00, 0x805effd4, 0x80070001, + 0x001f2013, 0x80070000, 0x001f2324, 0x001fb0cb, + 0x001fb010, 0x80073bf0, 0x001fb008, 0x800743e0, + 0x001fb009, 0x98214000, 0xb500ffa5, 0x80270000, + 0x8047fef0, 0x003eb802, 0x90420004, 0x003eb802, + 0x90420004, 0x003eb802, 0x90420004, 0x003eb802, + 0x81df0000, 0x00000000, 0x00000000, 0x8364044f, + 0x81df0004, 0xb500ff97, 0x81df0000, 0x00000000, + 0x00000000, 0x836403f9, 0x81df0004, 0xb500ff91, + 0x81df0000, 0x00000000, 0x00000000, 0x836403b4, + 0x81df0004, 0xb500ff8b, 0x81df0000, 0x00000000, + 0x00000000, 0x83440317, 0x81df0004, 0xb500ff85, + 0x81df0000, 0x00000000, 0x00000000, 0x834402fc, + 0x81df0004, 0xb500ff7f, 0x80070000, 0x80470000, + 0x81df0000, 0x00000000, 0x00000000, 0xb6002003, + 0xb6003002, 0x001eb802, 0x90420004, 0x80171000, + 0x8057ffff, 0xb6002002, 0xb6001801, 0x001fa020, + 0x81df0004, 0x00ffb81f, 0x817bff7c, 0x00000000, + 0x956b0080, 0x5d67b80b, 0x83a70000, 0x8057ffff, + 0x80770000, 0x8073007a, 0x9863e7d2, 0xb00b0001, + 0xb4200002, 0x8073007d, 0x98636d4a, 0x0207b803, + 0x81df0000, 0x00000000, 0x00000000, 0xb00b0001, + 0xb400000a, 0x80171000, 0xb6008007, 0x003fc0c0, + 0x005fc740, 0x40c1b810, 0x4102b810, 0x001fe0c6, + 0x001fe0c8, 0x4210b803, 0xb5000009, 0x80171000, + 0xb6000007, 0x003fc020, 0x005fc7e0, 0x40c1b810, + 0x4102b810, 0x001fe026, 0x001fe0a8, 0x4210b803, + 0x81df0004, 0x80270000, 0x003f2013, 0x8007001f, + 0x94000003, 0x5810b800, 0x83671e7c, 0x1b7bb800, + 0x003f9009, 0x1821b800, 0x00ffb801, 0x003f0013, + 0xb0010001, 0xb420fff3, 0x93bd0001, 0xb01d0004, + 0xb480ffd7, 0x00ffb81f, 0x00000000, 0x00000000, + 0x003f03f9, 0x009f0324, 0x84840001, 0xb0010000, + 0xb4000011, 0x815b4b0c, 0x81070000, 0x81270be8, + 0xb00a0000, 0xb4000002, 0x81070c00, 0x812717e8, + 0x802500a5, 0x806500a5, 0x3001b803, 0xb420fffc, + 0x9421ffff, 0x3001b808, 0xb480000b, 0x3001b809, + 0xb4a00059, 0xb5000008, 0xb0040000, 0xb4200003, + 0x802717ff, 0x81470000, 0xb5000003, 0x80270001, + 0x003f23f9, 0x81470c00, 0xb0040000, 0xb4200006, + 0x039f4193, 0x5b81b81c, 0x003f90cb, 0x1021b81c, + 0x003fb0cb, 0x8384025e, 0x829bff80, 0x801300e0, + 0x1434b800, 0x5c35b801, 0x8013001f, 0x1454b800, + 0x5c50b802, 0x8073007f, 0x9863ffff, 0xb002000f, + 0xb4800001, 0x90210001, 0x84210004, 0xb0010000, + 0xb4a00001, 0x6861b803, 0x005f9040, 0x4082b803, + 0x80af001f, 0x808f0000, 0x806f0000, 0x8007ffff, + 0x8033ffff, 0x80171000, 0x81df0000, 0x00000000, + 0x00000000, 0xb600180a, 0xb6002009, 0x58708000, + 0x6068b803, 0x40c4b803, 0x00000000, 0x00c8b806, + 0x00000000, 0x00000000, 0x00000000, 0x5807a026, + 0x81df0004, 0x80670400, 0x5d22b80a, 0x81df0000, + 0x00000000, 0x00000000, 0xb600180a, 0x00cfb803, + 0x013fb0bc, 0x5922b809, 0x01afb809, 0x013f90bc, + 0x0047b86f, 0xb0020001, 0xb4c0fffd, 0x90630020, + 0x91290020, 0x81df0004, 0x808f0000, 0x801b4b14, + 0x80270001, 0xb0000001, 0xb4000002, 0x802600a0, + 0x803e4b14, 0x81270c00, 0xb00a0000, 0xb4000001, + 0x81270000, 0x813e4b0c, 0x80270001, 0x003f2013, + 0x80050086, 0x001fb044, 0x00ffb81b, 0x00000000, + 0x029fb00a, 0x02bfb00b, 0x02dfb00c, 0x02ffb00d, + 0x031fb00e, 0x033fb00f, 0x033f400f, 0x0287b86f, + 0x029fb005, 0x8285009d, 0x82b30002, 0x9ab50040, + 0x1a94b815, 0x8286009d, 0x8285009c, 0x96b48000, + 0xb0158000, 0xb400019c, 0x96b40100, 0xb0150100, + 0xb40001b8, 0x96b40400, 0xb0150400, 0xb40001ca, + 0x96b40001, 0xb0150001, 0xb4000014, 0x96b40008, + 0xb0150008, 0xb40001a5, 0x96b44000, 0xb0154000, + 0xb40001c9, 0x96b40002, 0xb0150002, 0xb4000169, + 0x96b40040, 0xb0150040, 0xb40001dc, 0x82d30002, + 0x9ad60000, 0x16b6b814, 0x3015b816, 0xb40001da, + 0x00000000, 0x00000000, 0xb50001db, 0x02bf9017, + 0x92b50001, 0x02bfb017, 0x82850082, 0x83050081, + 0x82a5009a, 0x96b50001, 0xb0150001, 0xb4200014, + 0x82a70000, 0x02bfb017, 0x96b41840, 0xb0150800, + 0xb420000c, 0x96b40008, 0x5aa9b815, 0x96d46000, + 0x5ec3b816, 0x82f3000f, 0x9af7c00f, 0x1718b817, + 0x1ab5b818, 0x1ab5b816, 0x9ab50340, 0x82a60081, + 0xb5000140, 0x9b180180, 0x83060081, 0xb500013d, + 0x82a5009a, 0x96b50002, 0xb0150002, 0xb420001b, + 0x82a70000, 0x02bfb017, 0x96b41800, 0xb0151800, + 0xb4000013, 0x96b40040, 0xb0150040, 0xb4200004, + 0xa3180c00, 0x9b180340, 0x83060081, 0xb500012d, + 0x96b40008, 0x5aa9b815, 0x96d46000, 0x5ec3b816, + 0x82f3000f, 0x9af7c00f, 0x1718b817, 0x1ab5b818, + 0x1ab5b816, 0x9ab50340, 0x82a60081, 0xb5000121, + 0x9b180180, 0x83060081, 0xb500011e, 0x82a500c1, + 0x96b5000f, 0xb015000b, 0xb420000e, 0x96b40020, + 0xb0150020, 0xb400000b, 0x96b40200, 0xb0150200, + 0xb4000008, 0x82c50086, 0x82e50094, 0x3016b817, + 0xb4400004, 0x06f7b816, 0xb017ff00, 0xb4400001, + 0xb500010c, 0x96b46000, 0xb0156000, 0xb4000011, + 0x96b41820, 0xb0150820, 0xb4200004, 0x9b391000, + 0x82a5009a, 0x96b5feff, 0x82a6009a, 0x96b40040, + 0xb0150040, 0xb4200001, 0x9739efff, 0x96b91000, + 0xb0151000, 0xb4200003, 0x82a5009a, 0x9ab50100, + 0x82a6009a, 0x96b40040, 0xb0150040, 0xb4200019, + 0x96b41800, 0xb0151800, 0xb4200006, 0x96b98000, + 0xb0158000, 0xb4200003, 0x9b180180, 0x83060081, + 0xb50000ec, 0x96d80c00, 0x82b300ff, 0x9ab5f3ff, + 0x1718b815, 0xb0160c00, 0xb4000007, 0x82e50098, + 0x96f70400, 0xb0170400, 0xb4200002, 0x82c70c00, + 0xb5000001, 0xa2d60c00, 0x1b18b816, 0x9b180340, + 0xb50000d2, 0x96b40220, 0xb0150000, 0xb4e00033, + 0x82a5009d, 0x82f3ffff, 0x16b5b817, 0x82f33802, + 0x3015b817, 0xb420002d, 0x96f98000, 0xb0178000, + 0xb400002a, 0x82a70000, 0x02bfb017, 0x82c50081, + 0x9ab60020, 0x82a60081, 0x82a50086, 0x92b50bb8, + 0x82a60094, 0x82c60081, 0x82c5009d, 0x96d6ffff, + 0x82b3c802, 0x9ab50041, 0x82e500c1, 0x96f7000f, + 0xb017000b, 0xb4000002, 0x82b38802, 0x9ab50041, + 0x1ab5b816, 0x82c5009a, 0x96d60020, 0xb0160020, + 0xb4200002, 0x82b3c802, 0x9ab50041, 0x82a6009d, + 0x02ff9017, 0x00000000, 0xb0170040, 0xb480000b, + 0x96f41c00, 0xb0171c00, 0xb4200008, 0x82e50086, + 0x82c50094, 0x92d63000, 0x3016b817, 0xb4400003, + 0x9b180180, 0x83060081, 0xb50000a6, 0x5eb5b814, + 0x96b500f0, 0x96f46000, 0x5eedb817, 0x1ab5b817, + 0xb0170003, 0xb4000004, 0x96b500ef, 0x96f70001, + 0x5ae4b817, 0x1ab5b817, 0x96d41800, 0xb0161800, + 0xb400000a, 0x96f900ff, 0x96b500ff, 0x9739ff00, + 0x1b39b815, 0x02a7b817, 0x96b500f3, 0x96d40008, + 0x5ec1b816, 0x1ab5b816, 0xb500000c, 0x96f98000, + 0xb0178000, 0xb4200007, 0x5efeb814, 0x96f70001, + 0xb0170001, 0xb4000003, 0x9b180180, 0x83060081, + 0xb5000084, 0x96b500f3, 0x9ab50008, 0x9739fff3, + 0x96d40020, 0xb0160020, 0xb4200017, 0x9b398000, + 0x82c70000, 0x02dfb017, 0x96d40010, 0x5ac8b816, + 0x82f300ff, 0x9af7cfff, 0x1718b817, 0x1b18b816, + 0x9b180340, 0x82c5009d, 0x96d6ffff, 0x82f33802, + 0x9af70041, 0x1af7b816, 0x82c5009a, 0x96d60020, + 0xb0160020, 0xb4200002, 0x82f3c802, 0x9af70041, + 0x82e6009d, 0xb500005d, 0x97397fff, 0x96b500ff, + 0x5aaab815, 0x82f300fc, 0x9af703ff, 0x1718b817, + 0x1b18b815, 0x9b180340, 0x82c5009a, 0x96d60010, + 0xb0160010, 0xb4200024, 0x82c70000, 0x02dfb017, + 0x82c50086, 0x92d60bb8, 0x82c60086, 0x82c50094, + 0x5eefb818, 0x96f70003, 0xb0170003, 0xb4200002, + 0x82e70bb8, 0xb5000001, 0x82e70bb8, 0x12d6b817, + 0x82e50081, 0x9af70020, 0x82e60081, 0x82c60094, + 0xa2f70020, 0x82e60081, 0x82f30001, 0x16f7b818, + 0x5ef0b817, 0xb0170001, 0xb4000004, 0x96f84000, + 0x5ee4b817, 0x9718f3ff, 0x1b18b817, 0x82f32802, + 0x9af70040, 0x82e6009d, 0x83060081, 0x83070001, + 0x8306009f, 0xb50000b8, 0x82c5009d, 0x82f33802, + 0x9af70041, 0x3016b817, 0xb420000f, 0x82b3c802, + 0x9ab50041, 0x82e500c1, 0x96f7000f, 0xb017000b, + 0xb4000002, 0x82b38802, 0x9ab50041, 0x82c5009a, + 0x96d60020, 0xb0160020, 0xb4200002, 0x82b3c802, + 0x9ab50041, 0x82a6009d, 0x82c5009a, 0x96d60080, + 0xb0160080, 0xb4000014, 0x02df9017, 0x00000000, + 0xb0160010, 0xb4800010, 0x82c500c1, 0x96d6000f, + 0xb016000b, 0xb400000c, 0x82c50087, 0x96d60080, + 0x5ac7b816, 0x82c50098, 0x96d60800, 0x5ac3b816, + 0x96f84000, 0x3017b816, 0xb4200003, 0x033f400f, + 0x9b394000, 0xb500000b, 0x9739bfff, 0x82e50061, + 0x96f70008, 0xb0170008, 0xb4000005, 0x5eefb818, + 0x96f70003, 0xb0170003, 0xb4000001, 0x9718ffff, + 0x83060081, 0x83070001, 0x8306009f, 0x00000000, + 0xb500007d, 0x82850083, 0x96b400ff, 0xb015003c, + 0xb4200019, 0x96b92000, 0xb0152000, 0xb4000002, + 0x9b392000, 0xb5000014, 0x9739d3ff, 0x82870000, + 0x82860087, 0x82870008, 0x82860083, 0x829bff78, + 0x82a7001f, 0xb0140400, 0xb4000001, 0x82a70010, + 0x82a600c9, 0x829bff78, 0x00000000, 0x828600cb, + 0x8285009d, 0x82b3ffff, 0x9ab5fffd, 0x1694b815, + 0x8286009d, 0xb5000000, 0x83070002, 0x8306009f, + 0x00000000, 0xb500005c, 0x96b90800, 0xb0150800, + 0xb4200009, 0x9739f7ff, 0x82a703fd, 0x82a600cb, + 0x82a7003c, 0x82a60083, 0x8285009d, 0x9a940002, + 0x8286009d, 0xb5000004, 0x82850087, 0x5a82b814, + 0xa2940200, 0x82860087, 0xb5000000, 0x83078000, + 0x8306009f, 0x00000000, 0xb5000047, 0x82850086, + 0x82a50094, 0x3015b814, 0xb4800002, 0x86b50bb8, + 0x82a60086, 0x83070008, 0x8306009f, 0x00000000, + 0xb500003d, 0x83050069, 0x9718003f, 0x82e50064, + 0x12f7b818, 0x86f70088, 0x82feff74, 0x02e7b86f, + 0x9af74000, 0x01ffb817, 0x96f7bfff, 0x01ffb817, + 0x83050081, 0x82f3001c, 0x9af703ff, 0x1718b817, + 0x9b180140, 0x83060081, 0x83070100, 0x8306009f, + 0x00000000, 0xb5000028, 0x83070000, 0x83050081, + 0x9b180180, 0x83060081, 0x83070400, 0x8306009f, + 0x00000000, 0xb5000020, 0x82870000, 0x82850082, + 0x5eb7b814, 0x96b500fc, 0x96d40006, 0x5ec1b816, + 0x1ab5b816, 0x5aacb815, 0x83050081, 0x82d3001c, + 0x9ad600ff, 0x1718b816, 0x1b18b815, 0x9b180e00, + 0x83060081, 0x83074000, 0x8306009f, 0x8305009d, + 0x82d3ffff, 0x9ad6bfff, 0x1718b816, 0x8306009d, + 0x00000000, 0xb5000008, 0xb5000007, 0x83070040, + 0x8306009f, 0xb5000004, 0x83130002, 0x9b180000, + 0x8306009f, 0xb5000000, 0x029f9005, 0x01ffb814, + 0x033f600f, 0x029f900a, 0x02bf900b, 0x02df900c, + 0x02ff900d, 0x031f900e, 0x033f900f, 0x00ffb81e, + 0x02ff9010, 0x92f70b43, 0x02ffb010, 0x02ff90cb, + 0x82bbffdc, 0x829bffd8, 0x93150004, 0x3014b815, + 0xb4000010, 0x02dbb818, 0x029bb815, 0x3017b816, + 0xb480000c, 0x5a81b814, 0x029fb010, 0x82860095, + 0x8293001f, 0x9294fe00, 0x92b50008, 0x3015b814, + 0xb4800002, 0x82b3001f, 0x92b5fa00, 0x82beffdc, + 0xb500ffeb, 0x029f9010, 0x83250094, 0x06d4b819, + 0x02d6b816, 0xb016ffff, 0xb4a0000a, 0x82933802, + 0x9a940041, 0x82c5009d, 0x96d6ffff, 0x1a94b816, + 0x82c5009a, 0x96d60010, 0xb0160010, 0xb4000001, + 0x8286009d, 0x00ffb81c, 0x00000000, 0x00000000, + 0x001f9012, 0x001fb100, 0x001f004c, 0x001f2404, + 0x801bfef0, 0x8058fef4, 0x803bff68, 0x8078ff6c, + 0x2000b801, 0x2042b803, 0x001fb104, 0x005f2414, + 0x82e70001, 0x83640048, 0x029fb014, 0x829efef0, + 0x8286000f, 0x02bf2054, 0x82bcfef4, 0x82a6000e, + 0x00ffb81a, 0x80e70001, 0x801336e3, 0x9800eb76, + 0x001fb100, 0x800700ab, 0x001f2404, 0x801bc3e8, + 0x8058c3ec, 0x83640024, 0x82e70000, 0x83640036, + 0x029fb300, 0x029fb100, 0x02bf2c04, 0x02bf2404, + 0x801bc000, 0x8058c004, 0x8364001b, 0x82e70000, + 0x8364002d, 0x001f9300, 0x3000b814, 0xb420000a, + 0x001f0c04, 0x3000b815, 0xb4200007, 0x829efef0, + 0x82bcfef4, 0x029fb012, 0x02bf204c, 0x82870001, + 0x829cfef5, 0x00ffb81a, 0xb0070000, 0xb4000007, + 0x80e70000, 0x801399fa, 0x9800c92e, 0x001fb100, + 0x800700af, 0x001f2404, 0xb500ffdc, 0x82870000, + 0x829cfef5, 0x00ffb81a, 0x80c700ff, 0x803bff68, + 0x8078ff6c, 0x14a0b806, 0x2063b805, 0x007f2414, + 0x2021b802, 0x58c8b806, 0x14a0b806, 0x58b0b805, + 0x2021b805, 0x58c8b806, 0x14a0b806, 0x2021b805, + 0x58c8b806, 0x14a0b806, 0x5cb0b805, 0x2021b805, + 0x003fb104, 0x00ffb81b, 0x82c70000, 0x83070400, + 0x83270005, 0x8197040c, 0x81d7ffff, 0x83840126, + 0x83840001, 0x00ffb81b, 0x808f0000, 0x806f001f, + 0x80af001f, 0x80270140, 0x81e70228, 0x5de2b80f, + 0xb6000208, 0x00cfb801, 0x01ffb0bc, 0x59e2b80f, + 0x01cfb80f, 0x01ff90bc, 0xb520ffff, 0x91ef0020, + 0x90210020, 0x80270180, 0x81e70120, 0x5de2b80f, + 0xb6000208, 0x00cfb801, 0x01ffb0bc, 0x59e2b80f, + 0x01cfb80f, 0x01ff90bc, 0xb520ffff, 0x91ef0020, + 0x90210020, 0x8057ffff, 0x80170430, 0x80070410, + 0x80270408, 0xb6000509, 0x005ff000, 0x90420500, + 0x007ff001, 0x90630600, 0x009ff002, 0x00bff003, + 0x2004a025, 0x90000001, 0x90210001, 0x80070414, + 0x80d7ffff, 0x8097045c, 0x8017043c, 0xb6000404, + 0x005ff000, 0x007f87e0, 0x84000001, 0x2082a7e3, + 0x80970460, 0x80170440, 0x2082b803, 0x007f8000, + 0x2083a004, 0x80170430, 0x80970450, 0x80270408, + 0xb6000508, 0x005f8024, 0x90420500, 0x007ff001, + 0x90630600, 0x009ff002, 0x00bff003, 0x2004a025, + 0x90210001, 0x80170440, 0x00000000, 0x02bf87e0, + 0x80970460, 0x82870000, 0xb6000404, 0x005f87e4, + 0x5a88b814, 0x204287e0, 0x1a94b802, 0x00ffb81c, + 0x001f0a49, 0x001f2709, 0x001f0a41, 0x001f2708, + 0x001f0a46, 0x001f2707, 0x001f0a48, 0x001f2706, + 0x001f0a42, 0x001f2705, 0x001f0a47, 0x001f2704, + 0x001f0a45, 0x001f2703, 0x001f0a43, 0x001f2702, + 0x001f0a40, 0x001f2701, 0x001f0a44, 0x001f2700, + 0x001f0c25, 0xa020000c, 0x94400001, 0x94600002, + 0x94810004, 0x94a10008, 0x94c00010, 0x5943b802, + 0x5861b803, 0x5882b804, 0x5ca2b805, 0x5cc4b806, + 0x194ab803, 0x194ab804, 0x194ab805, 0x194ab806, + 0x015f2738, 0x801b0220, 0x003f91c1, 0x5c28b801, + 0x005f91c2, 0x5858b802, 0x1821b802, 0x2000b801, + 0x001fb1c4, 0x80180224, 0x003f0709, 0x2000b801, + 0x001f2714, 0x82c70001, 0x82e70001, 0x83070710, + 0x8327001e, 0x81970735, 0x8384009f, 0x02df0738, + 0x82170a30, 0x838400f1, 0x819efef0, 0x817cfef4, + 0x819eff68, 0x817cff6c, 0x00ffb81b, 0x820f001f, + 0x8018fef8, 0x8057ffff, 0x001f2709, 0x8018fef6, + 0x80d7ffff, 0x001f2708, 0x8018fefa, 0x8157ffff, + 0x001f2707, 0x8018fefd, 0x81d7ffff, 0x001f2706, + 0x8018fefb, 0x802f001f, 0x001f2705, 0x8018fefe, + 0x00000000, 0x001f2704, 0x8018fef9, 0x00000000, + 0x001f2703, 0x8018feff, 0x00000000, 0x001f2702, + 0x8018fef7, 0x00000000, 0x001f2701, 0x8018fefc, + 0x00000000, 0x001f2700, 0x001f0c25, 0xa0200011, + 0x94410001, 0x94600002, 0x94800004, 0x94a00008, + 0x94c10010, 0x5941b802, 0x5861b803, 0x5c82b804, + 0x58a1b805, 0x5cc1b806, 0x194ab803, 0x194ab804, + 0x194ab805, 0x194ab806, 0x015f2738, 0x801b0220, + 0x003f91c1, 0x5c28b801, 0x005f91c2, 0x5858b802, + 0x1821b802, 0x2000b801, 0x001fb1c4, 0x80180224, + 0x003f0709, 0x2000b801, 0x001f2714, 0x82c70001, + 0x82e70001, 0x83070710, 0x8327001e, 0x81970735, + 0x83840055, 0x02df0738, 0x82170a20, 0x838400a7, + 0x819efef0, 0x817cfef4, 0x5ac8b80c, 0x02ff0a44, + 0x1ad6b817, 0x02dfb291, 0x5ed8b80c, 0x5968b80b, + 0x1ad6b80b, 0x02df6524, 0x00ffb81b, 0x820f001f, + 0x8018fefe, 0x8057ffff, 0x001f2709, 0x8018fefa, + 0x80d7ffff, 0x001f2708, 0x8018fefc, 0x8157ffff, + 0x001f2707, 0x8018feff, 0x81d7ffff, 0x001f2706, + 0x8018fef8, 0x802f001f, 0x001f2705, 0x8018fefb, + 0x00000000, 0x001f2704, 0x8018fefd, 0x00000000, + 0x001f2703, 0x8018fef6, 0x00000000, 0x001f2702, + 0x8018fef9, 0x00000000, 0x001f2701, 0x8018fef7, + 0x00000000, 0x001f2700, 0x801b0220, 0x003f91c1, + 0x5c28b801, 0x005f91c2, 0x5858b802, 0x1821b802, + 0x2000b801, 0x001fb1c4, 0x80180224, 0x003f0709, + 0x2000b801, 0x001f2714, 0x82c70001, 0x82e70001, + 0x83070710, 0x8327001e, 0x81970735, 0x83840016, + 0x83270000, 0x831bfef0, 0x82f8fef4, 0x02c7b819, + 0x82170a28, 0x83840065, 0x300cb818, 0xb4200002, + 0x300bb817, 0xb4000006, 0x93390001, 0xb0190020, + 0xb480fff6, 0x83270000, 0x833cfef5, 0x00ffb81b, + 0x019fb290, 0x017f2a44, 0x033f2c25, 0x83270001, + 0x833cfef5, 0x00ffb81b, 0x0007b818, 0x90000003, + 0x00000000, 0x015ff000, 0x90000001, 0x5949b80a, + 0x013ff000, 0x194ab809, 0x84000002, 0x994a0100, + 0x017ff000, 0x958b00f8, 0x5981b80c, 0x956b0007, + 0x198cb80b, 0x84000002, 0x998c0008, 0x017ff000, + 0x90000001, 0x5971b80b, 0x198cb80b, 0x017ff000, + 0x5969b80b, 0x198cb80b, 0x81a70000, 0x94d90003, + 0x82a70000, 0xb6260019, 0xb6000818, 0x5df0b80a, + 0x5e02b80a, 0x21efb810, 0x95ef0001, 0x5941b80a, + 0x194ab80f, 0x21efb816, 0x5e18b80c, 0x5e35b80c, + 0x5e54b80c, 0x5e6cb80c, 0x2210b811, 0x2252b813, + 0x2210b812, 0x96100001, 0x5981b80c, 0x198cb810, + 0x2210b817, 0x10afb810, 0x10a5b80d, 0x5da1b805, + 0x94a50001, 0x5aa1b815, 0x1ab5b805, 0x019fa7f5, + 0x5cc2b819, 0xb626001c, 0x82870000, 0xb6000419, + 0xb6000818, 0x5df0b80a, 0x5e02b80a, 0x21efb810, + 0x95ef0001, 0x5941b80a, 0x194ab80f, 0x21efb816, + 0x5e18b80c, 0x5e35b80c, 0x5e54b80c, 0x5e6cb80c, + 0x2210b811, 0x2252b813, 0x2210b812, 0x96100001, + 0x5981b80c, 0x198cb810, 0x2210b817, 0x10afb810, + 0x10a5b80d, 0x5da1b805, 0x94a50001, 0x5a81b814, + 0x1a94b805, 0x019fa7f4, 0x00ffb81c, 0x8257ffff, + 0x808f0000, 0x806f001f, 0x80af001f, 0x80270200, + 0x81e7ff00, 0x5de2b80f, 0xb6000208, 0x00cfb801, + 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, 0x01ff90bc, + 0xb520ffff, 0x91ef0020, 0x90210020, 0x80270240, + 0x81e70000, 0x5de2b80f, 0xb6000208, 0x00cfb801, + 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, 0x01ff90bc, + 0xb520ffff, 0x91ef0020, 0x90210020, 0x80270180, + 0x81e70120, 0x5de2b80f, 0xb6000208, 0x00cfb801, + 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, 0x01ff90bc, + 0xb520ffff, 0x91ef0020, 0x90210020, 0x806f0007, + 0x80af0007, 0x80270280, 0x81e70100, 0x5de2b80f, + 0x00cfb801, 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, + 0x01ff90bc, 0xb520ffff, 0x91ef0020, 0x90210020, + 0x80170760, 0x001f0700, 0x001fa020, 0x001f0701, + 0x001fa020, 0x001f0702, 0x001fa020, 0x001f0703, + 0x001fa020, 0x001f0704, 0x001fa000, 0x80970750, + 0x81170770, 0x82a70735, 0x83a40060, 0x001f87e4, + 0xb6000405, 0x86b50001, 0x83a4005c, 0x001f8004, + 0x003f87e8, 0x2080a7e1, 0x80970770, 0x80170750, + 0x81170750, 0x81970740, 0x82a70730, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a40050, 0x001f87e4, + 0xb6000405, 0x86b50001, 0x83a4004c, 0x001f8004, + 0x003f87e8, 0x2080a7e1, 0x80970750, 0x80170770, + 0x81170770, 0x81970760, 0x82a7072b, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a40040, 0x83a4004e, + 0xb6000407, 0x86b50001, 0x83a4003c, 0x001f8004, + 0x003f87e8, 0x2080a001, 0x83a40047, 0x00000000, + 0x80970770, 0x80170750, 0x81170750, 0x81970740, + 0x82a70726, 0x001f800c, 0x003f8008, 0x2100a001, + 0x83a4002e, 0x83a4003c, 0xb6000407, 0x86b50001, + 0x83a4002a, 0x001f8004, 0x003f87e8, 0x2080a001, + 0x83a40035, 0x00000000, 0x80970750, 0x80170770, + 0x81170770, 0x81970760, 0x82a70721, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a4001c, 0x001f87e4, + 0xb6000405, 0x86b50001, 0x83a40018, 0x001f8004, + 0x003f87e8, 0x2080a7e1, 0x80970770, 0x80170750, + 0x81170750, 0x81970740, 0x82a7071c, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a4000c, 0x017f87e4, + 0x81870000, 0xb6000406, 0x86b50001, 0x83a40007, + 0x001f87e4, 0x200087e8, 0x5988b80c, 0x198cb800, + 0x021fa02c, 0x021fa00b, 0x00ffb81c, 0x005ff015, + 0x90420600, 0x003f87e0, 0x001ff002, 0x2060b801, + 0x90630800, 0x90960a00, 0x001ff003, 0x003ff004, + 0x20a0b801, 0x90a50900, 0x00000000, 0x001ff005, + 0x009fa000, 0x00ffb81d, 0x001f8004, 0x5c21b800, + 0x5847b800, 0x1821b802, 0x942100ff, 0x2080a7e1, + 0x00ffb81d, 0x00000000, 0x00000000, 0x00000000, + 0x829bff80, 0x80af000f, 0x808f0000, 0x806f0000, + 0x82bbffec, 0x82fbffe4, 0x00000000, 0x82beffb8, + 0x95540700, 0x5d48b80a, 0x914a0001, 0x0227b80a, + 0x94343000, 0x5c2cb801, 0xb0010000, 0xb4000001, + 0x5a21b811, 0x9574c000, 0x5d6eb80b, 0x918b4b08, + 0x01b8b80c, 0x96d5ffff, 0x5ec2b816, 0x96f7ffff, + 0x5ee2b817, 0x8057ffff, 0x80d7ffff, 0x8157ffff, + 0x81d7ffff, 0x81f3ff00, 0x99efff00, 0x821300ff, + 0x9a1000ff, 0x81971000, 0x82670000, 0x82470000, + 0x80270280, 0x81df0000, 0x00000000, 0x00000000, + 0xb62d000d, 0x3016b817, 0xb4800001, 0x86d62800, + 0x00cfb801, 0x02dfb0bc, 0x5ac2b816, 0x01cfb816, + 0x02df90bc, 0x0067b86f, 0xb0030001, 0xb4c0fffd, + 0x92d60010, 0x90210010, 0x81df0004, 0x80170a00, + 0x81df0000, 0x00000000, 0x00000000, 0xb62d0006, + 0xb6001005, 0x146f8000, 0x14908000, 0x5c68b803, + 0x5888b804, 0x1803a024, 0x81df0004, 0x80170a00, + 0x80970d00, 0xb00b0000, 0xb4000004, 0xb00b0001, + 0xb400000a, 0xb00b0002, 0xb4000027, 0x81df0000, + 0x00000000, 0x00000000, 0xb6004002, 0x007f8020, + 0x009fa023, 0x81df0004, 0xb5000029, 0x80d3ffff, + 0x81df0000, 0x00000000, 0x00000000, 0xb6001018, + 0x5c648000, 0x9463ffff, 0x5c888020, 0x58b88000, + 0x1884b805, 0x1484b806, 0x1883a024, 0x5c6c8020, + 0x9463ffff, 0x58908000, 0x1883a024, 0x5c748020, + 0x588c8000, 0x1863b804, 0x9463ffff, 0x58888000, + 0x1484b806, 0x1883a024, 0x5c7c8020, 0x58848000, + 0x1863b804, 0x9463ffff, 0x14868020, 0x1883a024, + 0x81df0004, 0xb500000a, 0x80d3ffff, 0x81df0000, + 0x00000000, 0x00000000, 0xb6002004, 0x007f8020, + 0x009fa023, 0x007f8040, 0x009fa023, 0x81df0004, + 0x00000000, 0x81170d00, 0x80070000, 0x94343000, + 0x5c2cb801, 0xb0010001, 0xb4000099, 0xb00a0001, + 0xb400000e, 0xb00a0002, 0xb4000022, 0xb00a0003, + 0xb400002f, 0xb00a0004, 0xb400005d, 0xb00a0005, + 0xb4000066, 0xb00a0006, 0xb400008a, 0xb00a0007, + 0xb4000088, 0xb00a0008, 0xb4000086, 0x81df0000, + 0x00000000, 0x00000000, 0xb6004010, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x019fa020, 0x019fa020, + 0x019fa020, 0x019fa020, 0x019fa020, 0x5c708028, + 0x9463ffff, 0x019fa023, 0x019fa020, 0x019fa020, + 0x019fa020, 0x019fa020, 0x019fa020, 0x81df0004, + 0xb5000070, 0x81df0000, 0x00000000, 0x00000000, + 0x8027ffff, 0xb6004008, 0x14618008, 0x019fa023, + 0x019fa020, 0x019fa020, 0x5c708028, 0x019fa023, + 0x019fa020, 0x019fa020, 0x81df0004, 0xb5000061, + 0xb0130000, 0xb4000004, 0xb0130001, 0xb4000009, + 0xb0130002, 0xb400001a, 0x83a40102, 0x80170f00, + 0x007f8028, 0x001fa023, 0x007f8028, 0x001fa023, + 0xb5000054, 0x80170f00, 0x00000000, 0x007f8020, + 0x019fa023, 0x007f8000, 0x9463ffff, 0x019fa023, + 0x019fa020, 0x5c708020, 0x58908008, 0x1983a024, + 0x5c708028, 0x019fa023, 0x019fa020, 0x83a400ed, + 0x80170f00, 0x007f8028, 0x001fa023, 0xb5000041, + 0x80170f00, 0x00000000, 0x007f8020, 0x019fa023, + 0x007f8008, 0x9463ffff, 0x019fa023, 0x019fa020, + 0x5c708028, 0x58908008, 0x1983a024, 0x5c708028, + 0x019fa023, 0x019fa020, 0x83a400da, 0xb5000031, + 0x81df0000, 0x00000000, 0x00000000, 0xb6002005, + 0x007f8008, 0x019fa023, 0x007f8008, 0x019fa023, + 0x019fa020, 0x81df0004, 0xb5000026, 0xb0130000, + 0xb4000008, 0xb0130001, 0xb4000012, 0xb0130002, + 0xb400001f, 0xb0130003, 0xb400001d, 0xb0130004, + 0xb400001b, 0x83a400d5, 0x007f8028, 0x019fa023, + 0x007f8028, 0x019fa023, 0x007f8008, 0x9463ffff, + 0x019fa023, 0x80170f00, 0x007f8028, 0x001fa023, + 0xb5000010, 0x80170f00, 0x00000000, 0x5c708020, + 0x58908008, 0x1983a024, 0x5c708028, 0x58908008, + 0x1983a024, 0x5c708028, 0x019fa023, 0x83a400bf, + 0x80170f00, 0x007f8028, 0x001fa023, 0xb5000001, + 0xb5000000, 0x00000000, 0x00000000, 0xb500008e, + 0xb00a0001, 0xb400000e, 0xb00a0002, 0xb400001a, + 0xb00a0003, 0xb4000027, 0xb00a0004, 0xb4000055, + 0xb00a0005, 0xb400005e, 0xb00a0006, 0xb4000082, + 0xb00a0007, 0xb4000080, 0xb00a0008, 0xb400007e, + 0x81df0000, 0x00000000, 0x00000000, 0xb6004008, + 0x007f8028, 0x9463ffff, 0x019fa023, 0x019fa020, + 0x019fa020, 0x019fa020, 0x019fa020, 0x019fa020, + 0x81df0004, 0xb5000070, 0x81df0000, 0x00000000, + 0x00000000, 0x8027ffff, 0xb6002008, 0x14618008, + 0x019fa023, 0x019fa020, 0x019fa020, 0x5c708048, + 0x019fa023, 0x019fa020, 0x019fa020, 0x81df0004, + 0xb5000061, 0xb0130000, 0xb4000004, 0xb0130001, + 0xb4000009, 0xb0130002, 0xb400001a, 0x83a40098, + 0x80170f00, 0x007f8028, 0x001fa023, 0x007f8028, + 0x001fa023, 0xb5000054, 0x80170f00, 0x00000000, + 0x007f8020, 0x019fa023, 0x007f8000, 0x9463ffff, + 0x019fa023, 0x019fa020, 0x5c708020, 0x58908008, + 0x1983a024, 0x5c708028, 0x019fa023, 0x019fa020, + 0x83a40083, 0x80170f00, 0x007f8028, 0x001fa023, + 0xb5000041, 0x80170f00, 0x00000000, 0x007f8020, + 0x019fa023, 0x007f8008, 0x9463ffff, 0x019fa023, + 0x019fa020, 0x5c708028, 0x58908008, 0x1983a024, + 0x5c708028, 0x019fa023, 0x019fa020, 0x83a40070, + 0xb5000031, 0x81df0000, 0x00000000, 0x00000000, + 0xb6002005, 0x007f8008, 0x019fa023, 0x007f8008, + 0x019fa023, 0x019fa020, 0x81df0004, 0xb5000026, + 0xb0130000, 0xb4000008, 0xb0130001, 0xb4000012, + 0xb0130002, 0xb400001f, 0xb0130003, 0xb400001d, + 0xb0130004, 0xb400001b, 0x83a4006b, 0x007f8028, + 0x019fa023, 0x007f8028, 0x019fa023, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x80170f00, 0x007f8028, + 0x001fa023, 0xb5000010, 0x80170f00, 0x00000000, + 0x5c708020, 0x58908008, 0x1983a024, 0x5c708028, + 0x58908008, 0x1983a024, 0x5c708028, 0x019fa023, + 0x83a40055, 0x80170f00, 0x007f8028, 0x001fa023, + 0xb5000001, 0xb5000000, 0x92730001, 0x92520001, + 0x3012b811, 0xb480fe76, 0x003f0324, 0x90210001, + 0xb0010006, 0xb4a00001, 0x80270001, 0x003f2324, + 0x2c8db811, 0x803bffe0, 0x805bffe4, 0x5886b804, + 0x1015b804, 0xad440003, 0x3000b802, 0xb4800001, + 0x8400a000, 0x801effec, 0x015f6193, 0x809e4b04, + 0x00ffb81f, 0x81df0000, 0x00000000, 0x00000000, + 0xb6002a0c, 0x007f8028, 0x019fa023, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x019fa020, 0x5c708028, + 0x58908008, 0x1983a024, 0x5c708028, 0x019fa023, + 0x019fa020, 0x81df0004, 0x00ffb81d, 0x81df0000, + 0x00000000, 0x00000000, 0xb600190f, 0x007f8028, + 0x019fa023, 0x007f8028, 0x019fa023, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x5c708028, 0x58908008, + 0x1983a024, 0x5c708028, 0x58908008, 0x1983a024, + 0x5c708028, 0x019fa023, 0x81df0004, 0x00ffb81d, + 0x81df0000, 0x00000000, 0x00000000, 0xb6002a0c, + 0x007f8028, 0x019fa023, 0x007f8008, 0x9463ffff, + 0x019fa023, 0x019fa020, 0x5c708028, 0x58908008, + 0x1983a024, 0x5c708028, 0x019fa023, 0x019fa020, + 0x81df0004, 0x00ffb81d, 0x81df0000, 0x00000000, + 0x00000000, 0xb600190f, 0x007f8028, 0x019fa023, + 0x007f8028, 0x019fa023, 0x007f8008, 0x9463ffff, + 0x019fa023, 0x5c708028, 0x58908008, 0x1983a024, + 0x5c708028, 0x58908008, 0x1983a024, 0x5c708028, + 0x019fa023, 0x81df0004, 0x00ffb81d, 0x00000000, + 0x829bff80, 0x80af001f, 0x808f0000, 0x806f0000, + 0x82bbffec, 0x82fbffe4, 0x00000000, 0x82beffb8, + 0x95540700, 0x5d48b80a, 0x914a0001, 0x0227b80a, + 0x94343000, 0x5c2cb801, 0xb0010000, 0xb4000001, + 0x5a21b811, 0x9574c000, 0x5d6eb80b, 0x918b4b08, + 0x01b8b80c, 0x96d5ffff, 0x5ec2b816, 0x96f7ffff, + 0x5ee2b817, 0x8057ffff, 0x80d7ffff, 0x8157ffff, + 0x81d7ffff, 0x81f3ff00, 0x99efff00, 0x821300ff, + 0x9a1000ff, 0x81971000, 0x82670000, 0x82470000, + 0x80270280, 0x81df0000, 0x00000000, 0x00000000, + 0xb62d000d, 0x3016b817, 0xb4800001, 0x86d62800, + 0x00cfb801, 0x02dfb0bc, 0x5ac2b816, 0x01cfb816, + 0x02df90bc, 0x0067b86f, 0xb0030001, 0xb4c0fffd, + 0x92d60020, 0x90210020, 0x81df0004, 0x80170a00, + 0x81df0000, 0x00000000, 0x00000000, 0xb62d0006, + 0xb6002005, 0x146f8000, 0x14908000, 0x5c68b803, + 0x5888b804, 0x1803a024, 0x81df0004, 0x80170a00, + 0x80970d00, 0xb00b0000, 0xb4000004, 0xb00b0001, + 0xb400000a, 0xb00b0002, 0xb4000027, 0x81df0000, + 0x00000000, 0x00000000, 0xb6008002, 0x007f8020, + 0x009fa023, 0x81df0004, 0xb5000029, 0x80d3ffff, + 0x81df0000, 0x00000000, 0x00000000, 0xb6002018, + 0x5c648000, 0x9463ffff, 0x5c888020, 0x58b88000, + 0x1884b805, 0x1484b806, 0x1883a024, 0x5c6c8020, + 0x9463ffff, 0x58908000, 0x1883a024, 0x5c748020, + 0x588c8000, 0x1863b804, 0x9463ffff, 0x58888000, + 0x1484b806, 0x1883a024, 0x5c7c8020, 0x58848000, + 0x1863b804, 0x9463ffff, 0x14868020, 0x1883a024, + 0x81df0004, 0xb500000a, 0x80d3ffff, 0x81df0000, + 0x00000000, 0x00000000, 0xb6004004, 0x007f8020, + 0x009fa023, 0x007f8040, 0x009fa023, 0x81df0004, + 0x00000000, 0x81170d00, 0x80070000, 0x94343000, + 0x5c2cb801, 0xb0010001, 0xb400008e, 0xb00a0001, + 0xb400000e, 0xb00a0002, 0xb400001c, 0xb00a0003, + 0xb4000024, 0xb00a0004, 0xb4000052, 0xb00a0005, + 0xb400005b, 0xb00a0006, 0xb400007f, 0xb00a0007, + 0xb400007d, 0xb00a0008, 0xb400007b, 0x81df0000, + 0x00000000, 0x00000000, 0xb600800a, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x019fa020, 0x019fa020, + 0x5c708028, 0x9463ffff, 0x019fa023, 0x019fa020, + 0x019fa020, 0x81df0004, 0xb500006b, 0x81df0000, + 0x00000000, 0x00000000, 0xb6008004, 0x007f8028, + 0x019fa023, 0x019fa020, 0x019fa020, 0x81df0004, + 0xb5000061, 0xb0130000, 0xb4000004, 0xb0130001, + 0xb4000009, 0xb0130002, 0xb400001a, 0x83a400fa, + 0x80170f00, 0x007f8028, 0x001fa023, 0x007f8028, + 0x001fa023, 0xb5000054, 0x80170f00, 0x00000000, + 0x007f8020, 0x019fa023, 0x007f8000, 0x9463ffff, + 0x019fa023, 0x019fa020, 0x5c708020, 0x58908008, + 0x1983a024, 0x5c708028, 0x019fa023, 0x019fa020, + 0x83a400e5, 0x80170f00, 0x007f8028, 0x001fa023, + 0xb5000041, 0x80170f00, 0x00000000, 0x007f8020, + 0x019fa023, 0x007f8008, 0x9463ffff, 0x019fa023, + 0x019fa020, 0x5c708028, 0x58908008, 0x1983a024, + 0x5c708028, 0x019fa023, 0x019fa020, 0x83a400d2, + 0xb5000031, 0x81df0000, 0x00000000, 0x00000000, + 0xb6004005, 0x007f8008, 0x019fa023, 0x007f8008, + 0x019fa023, 0x019fa020, 0x81df0004, 0xb5000026, + 0xb0130000, 0xb4000008, 0xb0130001, 0xb4000012, + 0xb0130002, 0xb400001f, 0xb0130003, 0xb400001d, + 0xb0130004, 0xb400001b, 0x83a400cd, 0x007f8028, + 0x019fa023, 0x007f8028, 0x019fa023, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x80170f00, 0x007f8028, + 0x001fa023, 0xb5000010, 0x80170f00, 0x00000000, + 0x5c708020, 0x58908008, 0x1983a024, 0x5c708028, + 0x58908008, 0x1983a024, 0x5c708028, 0x019fa023, + 0x83a400b7, 0x80170f00, 0x007f8028, 0x001fa023, + 0xb5000001, 0xb5000000, 0x00000000, 0x00000000, + 0xb5000086, 0xb00a0001, 0xb400000e, 0xb00a0002, + 0xb4000017, 0xb00a0003, 0xb400001f, 0xb00a0004, + 0xb400004d, 0xb00a0005, 0xb4000056, 0xb00a0006, + 0xb400007a, 0xb00a0007, 0xb4000078, 0xb00a0008, + 0xb4000076, 0x81df0000, 0x00000000, 0x00000000, + 0xb6008005, 0x007f8028, 0x9463ffff, 0x019fa023, + 0x019fa020, 0x019fa020, 0x81df0004, 0xb500006b, + 0x81df0000, 0x00000000, 0x00000000, 0xb6004004, + 0x007f8048, 0x019fa023, 0x019fa020, 0x019fa020, + 0x81df0004, 0xb5000061, 0xb0130000, 0xb4000004, + 0xb0130001, 0xb4000009, 0xb0130002, 0xb400001a, + 0x83a40098, 0x80170f00, 0x007f8028, 0x001fa023, + 0x007f8028, 0x001fa023, 0xb5000054, 0x80170f00, + 0x00000000, 0x007f8020, 0x019fa023, 0x007f8000, + 0x9463ffff, 0x019fa023, 0x019fa020, 0x5c708020, + 0x58908008, 0x1983a024, 0x5c708028, 0x019fa023, + 0x019fa020, 0x83a40083, 0x80170f00, 0x007f8028, + 0x001fa023, 0xb5000041, 0x80170f00, 0x00000000, + 0x007f8020, 0x019fa023, 0x007f8008, 0x9463ffff, + 0x019fa023, 0x019fa020, 0x5c708028, 0x58908008, + 0x1983a024, 0x5c708028, 0x019fa023, 0x019fa020, + 0x83a40070, 0xb5000031, 0x81df0000, 0x00000000, + 0x00000000, 0xb6004005, 0x007f8008, 0x019fa023, + 0x007f8008, 0x019fa023, 0x019fa020, 0x81df0004, + 0xb5000026, 0xb0130000, 0xb4000008, 0xb0130001, + 0xb4000012, 0xb0130002, 0xb400001f, 0xb0130003, + 0xb400001d, 0xb0130004, 0xb400001b, 0x83a4006b, + 0x007f8028, 0x019fa023, 0x007f8028, 0x019fa023, + 0x007f8008, 0x9463ffff, 0x019fa023, 0x80170f00, + 0x007f8028, 0x001fa023, 0xb5000010, 0x80170f00, + 0x00000000, 0x5c708020, 0x58908008, 0x1983a024, + 0x5c708028, 0x58908008, 0x1983a024, 0x5c708028, + 0x019fa023, 0x83a40055, 0x80170f00, 0x007f8028, + 0x001fa023, 0xb5000001, 0xb5000000, 0x92730001, + 0x92520001, 0x3012b811, 0xb480fe89, 0x003f0324, + 0x90210001, 0xb0010006, 0xb4a00001, 0x80270001, + 0x003f2324, 0x2c8db811, 0x803bffe0, 0x805bffe4, + 0x5887b804, 0x1015b804, 0xad440003, 0x3000b802, + 0xb4800001, 0x8400a000, 0x801effec, 0x015f6193, + 0x809e4b04, 0x00ffb81f, 0x81df0000, 0x00000000, + 0x00000000, 0xb6002a0c, 0x007f8028, 0x019fa023, + 0x007f8008, 0x9463ffff, 0x019fa023, 0x019fa020, + 0x5c708028, 0x58908008, 0x1983a024, 0x5c708028, + 0x019fa023, 0x019fa020, 0x81df0004, 0x00ffb81d, + 0x81df0000, 0x00000000, 0x00000000, 0xb600190f, + 0x007f8028, 0x019fa023, 0x007f8028, 0x019fa023, + 0x007f8008, 0x9463ffff, 0x019fa023, 0x5c708028, + 0x58908008, 0x1983a024, 0x5c708028, 0x58908008, + 0x1983a024, 0x5c708028, 0x019fa023, 0x81df0004, + 0x00ffb81d, 0x81df0000, 0x00000000, 0x00000000, + 0xb6002a0c, 0x007f8028, 0x019fa023, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x019fa020, 0x5c708028, + 0x58908008, 0x1983a024, 0x5c708028, 0x019fa023, + 0x019fa020, 0x81df0004, 0x00ffb81d, 0x81df0000, + 0x00000000, 0x00000000, 0xb600190f, 0x007f8028, + 0x019fa023, 0x007f8028, 0x019fa023, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x5c708028, 0x58908008, + 0x1983a024, 0x5c708028, 0x58908008, 0x1983a024, + 0x5c708028, 0x019fa023, 0x81df0004, 0x00ffb81d, + 0x003f03f9, 0x009f0324, 0x84840001, 0xb0010000, + 0xb4000011, 0x815b4b0c, 0x81070000, 0x81270be8, + 0xb00a0000, 0xb4000002, 0x81070c00, 0x812717e8, + 0x802500a5, 0x806500a5, 0x3001b803, 0xb420fffc, + 0x9421ffff, 0x3001b808, 0xb480000b, 0x3001b809, + 0xb4a00060, 0xb5000008, 0xb0040000, 0xb4200003, + 0x802717ff, 0x81470000, 0xb5000003, 0x80270001, + 0x003f23f9, 0x81470c00, 0xb0040000, 0xb4200006, + 0x039f4193, 0x5b81b81c, 0x003f90cb, 0x1021b81c, + 0x003fb0cb, 0x8384f90e, 0x829bff80, 0x801300e0, + 0x1434b800, 0x5c35b801, 0x8013001f, 0x1454b800, + 0x5c50b802, 0x8073007f, 0x9863ffff, 0xb002000f, + 0xb4800001, 0x90210001, 0x84210004, 0xb0010000, + 0xb4a00001, 0x6861b803, 0x005f9040, 0x4082b803, + 0x80af001f, 0x808f0000, 0x806f0000, 0x8007ffff, + 0x8033ffff, 0x80171000, 0x81df0000, 0x00000000, + 0x00000000, 0xb6001811, 0xb6002010, 0x14618000, + 0x6068b803, 0x40c4b803, 0x14608000, 0x00c8b806, + 0x5870b803, 0x6068b803, 0x4104b803, 0x58c8b806, + 0x0108b808, 0x14c6b801, 0x00000000, 0x00000000, + 0x5d08b808, 0x1508b800, 0x1806a028, 0x81df0004, + 0x80670400, 0x5d22b80a, 0x81df0000, 0x00000000, + 0x00000000, 0xb600180a, 0x00cfb803, 0x013fb0bc, + 0x5922b809, 0x01afb809, 0x013f90bc, 0x0047b86f, + 0xb0020001, 0xb4c0fffd, 0x90630020, 0x91290020, + 0x81df0004, 0x808f0000, 0x801b4b14, 0x80270001, + 0xb0000001, 0xb4000002, 0x802600a0, 0x803e4b14, + 0x81270c00, 0xb00a0000, 0xb4000001, 0x81270000, + 0x813e4b0c, 0x80270001, 0x003f2013, 0x80050086, + 0x001fb044, 0x00ffb81b, 0x00000000, 0x00000000, +}; + +static u32 PCMI2S240Ucode1f4b00[] = { + 0x00000000, 0x00000000, 0x00060504, 0x00000000, + 0x00000000, 0x00000000, 0x00300000, 0xffcfcfff, + 0x00302000, 0xffcfcfff, 0x00380000, 0xffc7c7ff, + 0xcbcecdc4, 0xcfcac9c8, 0xc3c6c5cc, 0xc7c2c1c0, + 0x1b1e1d14, 0x1f1a1918, 0x1316151c, 0x17121110, + 0x2b2e2d24, 0x2f2a2928, 0x2326252c, 0x27222120, + 0x3b3e3d34, 0x3f3a3938, 0x3336353c, 0x37323130, + 0x0b0e0d04, 0x0f0a0908, 0x0306050c, 0x07020100, + 0xdbdeddd4, 0xdfdad9d8, 0xd3d6d5dc, 0xd7d2d1d0, + 0xebeeede4, 0xefeae9e8, 0xe3e6e5ec, 0xe7e2e1e0, + 0xfbfefdf4, 0xfffaf9f8, 0xf3f6f5fc, 0xf7f2f1f0, + 0x4b4e4d44, 0x4f4a4948, 0x4346454c, 0x47424140, + 0x9b9e9d94, 0x9f9a9998, 0x9396959c, 0x97929190, + 0xabaeada4, 0xafaaa9a8, 0xa3a6a5ac, 0xa7a2a1a0, + 0xbbbebdb4, 0xbfbab9b8, 0xb3b6b5bc, 0xb7b2b1b0, + 0x8b8e8d84, 0x8f8a8988, 0x8386858c, 0x87828180, + 0x5b5e5d54, 0x5f5a5958, 0x5356555c, 0x57525150, + 0x6b6e6d64, 0x6f6a6968, 0x6366656c, 0x67626160, + 0x7b7e7d74, 0x7f7a7978, 0x7376757c, 0x77727170, + 0x341424c4, 0x3e1e2ece, 0x3d1d2dcd, 0x3b1b2bcb, + 0xb494a444, 0xbe9eae4e, 0xbd9dad4d, 0xbb9bab4b, + 0xf4d4e404, 0xfedeee0e, 0xfddded0d, 0xfbdbeb0b, + 0x74546484, 0x7e5e6e8e, 0x7d5d6d8d, 0x7b5b6b8b, + 0x3c1c2ccc, 0x361626c6, 0x351525c5, 0x331323c3, + 0xbc9cac4c, 0xb696a646, 0xb595a545, 0xb393a343, + 0xfcdcec0c, 0xf6d6e606, 0xf5d5e505, 0xf3d3e303, + 0x7c5c6c8c, 0x76566686, 0x75556585, 0x73536383, + 0x381828c8, 0x3a1a2aca, 0x391929c9, 0x3f1f2fcf, + 0xb898a848, 0xba9aaa4a, 0xb999a949, 0xbf9faf4f, + 0xf8d8e808, 0xfadaea0a, 0xf9d9e909, 0xffdfef0f, + 0x78586888, 0x7a5a6a8a, 0x79596989, 0x7f5f6f8f, + 0x301020c0, 0x321222c2, 0x311121c1, 0x371727c7, + 0xb090a040, 0xb292a242, 0xb191a141, 0xb797a747, + 0xf0d0e000, 0xf2d2e202, 0xf1d1e101, 0xf7d7e707, + 0x70506080, 0x72526282, 0x71516181, 0x77576787, + 0x05040100, 0x15141110, 0x25242120, 0x35343130, + 0x85848180, 0x95949190, 0xa5a4a1a0, 0xb5b4b1b0, + 0xc0408000, 0xe060a020, 0xd0509010, 0xf070b030, + 0xc8488808, 0xe868a828, 0xd8589818, 0xf878b838, + 0xc4448404, 0xe464a424, 0xd4549414, 0xf474b434, + 0xcc4c8c0c, 0xec6cac2c, 0xdc5c9c1c, 0xfc7cbc3c, + 0xc2428202, 0xe262a222, 0xd2529212, 0xf272b232, + 0xca4a8a0a, 0xea6aaa2a, 0xda5a9a1a, 0xfa7aba3a, + 0xc6468606, 0xe666a626, 0xd6569616, 0xf676b636, + 0xce4e8e0e, 0xee6eae2e, 0xde5e9e1e, 0xfe7ebe3e, + 0xc1418101, 0xe161a121, 0xd1519111, 0xf171b131, + 0xc9498909, 0xe969a929, 0xd9599919, 0xf979b939, + 0xc5458505, 0xe565a525, 0xd5559515, 0xf575b535, + 0xcd4d8d0d, 0xed6dad2d, 0xdd5d9d1d, 0xfd7dbd3d, + 0xc3438303, 0xe363a323, 0xd3539313, 0xf373b333, + 0xcb4b8b0b, 0xeb6bab2b, 0xdb5b9b1b, 0xfb7bbb3b, + 0xc7478707, 0xe767a727, 0xd7579717, 0xf777b737, + 0xcf4f8f0f, 0xef6faf2f, 0xdf5f9f1f, 0xff7fbf3f, + 0x1045a3e2, 0x000000f4, 0x263b7333, 0x766b2363, + 0x2b367e3e, 0x7b662e6e, 0x06db93d3, 0x964b0343, + 0x0bd69ede, 0x9b460e4e, 0x825f1757, 0x12cf87c7, + 0x8f521a5a, 0x1fc28aca, 0x00d199d9, 0x90410949, + 0x01d098d8, 0x91400848, 0x24357d3d, 0x74652d6d, + 0x25347c3c, 0x75642c6c, 0x04d59ddd, 0x94450d4d, + 0x05d49cdc, 0x95440c4c, 0x80511959, 0x10c189c9, + 0x81501858, 0x11c088c8, 0x02df97d7, 0x924f0747, + 0x0fd29ada, 0x9f420a4a, 0x865b1353, 0x16cb83c3, + 0x8b561e5e, 0x1bc68ece, 0xa6bbf3b3, 0xf6eba3e3, + 0xabb6febe, 0xfbe6aeee, 0x223f7737, 0x726f2767, + 0x2f327a3a, 0x7f622a6a, 0xa0b1f9b9, 0xf0e1a9e9, + 0xa1b0f8b8, 0xf1e0a8e8, 0x84551d5d, 0x14c58dcd, + 0x85541c5c, 0x15c48ccc, 0xa4b5fdbd, 0xf4e5aded, + 0xa5b4fcbc, 0xf5e4acec, 0x20317939, 0x70612969, + 0x21307838, 0x71602868, 0xa2bff7b7, 0xf2efa7e7, + 0xafb2faba, 0xffe2aaea, 0x00000000, 0x00000000, +}; + +static u32 PCMI2S240Ucode1fff00[] = { + 0xcbcecdc4, 0xcfcac9c8, 0xc3c6c5cc, 0xc7c2c1c0, + 0x1b1e1d14, 0x1f1a1918, 0x1316151c, 0x17121110, + 0x2b2e2d24, 0x2f2a2928, 0x2326252c, 0x27222120, + 0x3b3e3d34, 0x3f3a3938, 0x3336353c, 0x37323130, + 0x0b0e0d04, 0x0f0a0908, 0x0306050c, 0x07020100, + 0xdbdeddd4, 0xdfdad9d8, 0xd3d6d5dc, 0xd7d2d1d0, + 0xebeeede4, 0xefeae9e8, 0xe3e6e5ec, 0xe7e2e1e0, + 0xfbfefdf4, 0xfffaf9f8, 0xf3f6f5fc, 0xf7f2f1f0, + 0x4b4e4d44, 0x4f4a4948, 0x4346454c, 0x47424140, + 0x9b9e9d94, 0x9f9a9998, 0x9396959c, 0x97929190, + 0xabaeada4, 0xafaaa9a8, 0xa3a6a5ac, 0xa7a2a1a0, + 0xbbbebdb4, 0xbfbab9b8, 0xb3b6b5bc, 0xb7b2b1b0, + 0x8b8e8d84, 0x8f8a8988, 0x8386858c, 0x87828180, + 0x5b5e5d54, 0x5f5a5958, 0x5356555c, 0x57525150, + 0x6b6e6d64, 0x6f6a6968, 0x6366656c, 0x67626160, + 0x7b7e7d74, 0x7f7a7978, 0x7376757c, 0x77727170, + 0x341424c4, 0x3e1e2ece, 0x3d1d2dcd, 0x3b1b2bcb, + 0xb494a444, 0xbe9eae4e, 0xbd9dad4d, 0xbb9bab4b, + 0xf4d4e404, 0xfedeee0e, 0xfddded0d, 0xfbdbeb0b, + 0x74546484, 0x7e5e6e8e, 0x7d5d6d8d, 0x7b5b6b8b, + 0x3c1c2ccc, 0x361626c6, 0x351525c5, 0x331323c3, + 0xbc9cac4c, 0xb696a646, 0xb595a545, 0xb393a343, + 0xfcdcec0c, 0xf6d6e606, 0xf5d5e505, 0xf3d3e303, + 0x7c5c6c8c, 0x76566686, 0x75556585, 0x73536383, + 0x381828c8, 0x3a1a2aca, 0x391929c9, 0x3f1f2fcf, + 0xb898a848, 0xba9aaa4a, 0xb999a949, 0xbf9faf4f, + 0xf8d8e808, 0xfadaea0a, 0xf9d9e909, 0xffdfef0f, + 0x78586888, 0x7a5a6a8a, 0x79596989, 0x7f5f6f8f, + 0x301020c0, 0x321222c2, 0x311121c1, 0x371727c7, + 0xb090a040, 0xb292a242, 0xb191a141, 0xb797a747, + 0xf0d0e000, 0xf2d2e202, 0xf1d1e101, 0xf7d7e707, + 0x70506080, 0x72526282, 0x71516181, 0x77576787, + 0x05040100, 0x15141110, 0x25242120, 0x35343130, + 0x85848180, 0x95949190, 0xa5a4a1a0, 0xb5b4b1b0, + 0xc0408000, 0xe060a020, 0xd0509010, 0xf070b030, + 0xc8488808, 0xe868a828, 0xd8589818, 0xf878b838, + 0xc4448404, 0xe464a424, 0xd4549414, 0xf474b434, + 0xcc4c8c0c, 0xec6cac2c, 0xdc5c9c1c, 0xfc7cbc3c, + 0xc2428202, 0xe262a222, 0xd2529212, 0xf272b232, + 0xca4a8a0a, 0xea6aaa2a, 0xda5a9a1a, 0xfa7aba3a, + 0xc6468606, 0xe666a626, 0xd6569616, 0xf676b636, + 0xce4e8e0e, 0xee6eae2e, 0xde5e9e1e, 0xfe7ebe3e, + 0xc1418101, 0xe161a121, 0xd1519111, 0xf171b131, + 0xc9498909, 0xe969a929, 0xd9599919, 0xf979b939, + 0xc5458505, 0xe565a525, 0xd5559515, 0xf575b535, + 0xcd4d8d0d, 0xed6dad2d, 0xdd5d9d1d, 0xfd7dbd3d, + 0xc3438303, 0xe363a323, 0xd3539313, 0xf373b333, + 0xcb4b8b0b, 0xeb6bab2b, 0xdb5b9b1b, 0xfb7bbb3b, + 0xc7478707, 0xe767a727, 0xd7579717, 0xf777b737, + 0xcf4f8f0f, 0xef6faf2f, 0xdf5f9f1f, 0xff7fbf3f, + 0x1045a3e2, 0x000000f4, 0x263b7333, 0x766b2363, + 0x2b367e3e, 0x7b662e6e, 0x06db93d3, 0x964b0343, + 0x0bd69ede, 0x9b460e4e, 0x825f1757, 0x12cf87c7, + 0x8f521a5a, 0x1fc28aca, 0x00d199d9, 0x90410949, + 0x01d098d8, 0x91400848, 0x24357d3d, 0x74652d6d, + 0x25347c3c, 0x75642c6c, 0x04d59ddd, 0x94450d4d, + 0x05d49cdc, 0x95440c4c, 0x80511959, 0x10c189c9, + 0x81501858, 0x11c088c8, 0x02df97d7, 0x924f0747, + 0x0fd29ada, 0x9f420a4a, 0x865b1353, 0x16cb83c3, + 0x8b561e5e, 0x1bc68ece, 0xa6bbf3b3, 0xf6eba3e3, + 0xabb6febe, 0xfbe6aeee, 0x223f7737, 0x726f2767, + 0x2f327a3a, 0x7f622a6a, 0xa0b1f9b9, 0xf0e1a9e9, + 0xa1b0f8b8, 0xf1e0a8e8, 0x84551d5d, 0x14c58dcd, + 0x85541c5c, 0x15c48ccc, 0xa4b5fdbd, 0xf4e5aded, + 0xa5b4fcbc, 0xf5e4acec, 0x20317939, 0x70612969, + 0x21307838, 0x71602868, 0xa2bff7b7, 0xf2efa7e7, + 0xafb2faba, 0xffe2aaea, 0x00000000, 0x00000000, +}; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/ls220/pcmi2s.h linux.19rc3-ac4/drivers/media/video/ls220/pcmi2s.h --- linux.19rc3/drivers/media/video/ls220/pcmi2s.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/ls220/pcmi2s.h 2002-07-29 13:58:41.000000000 +0100 @@ -0,0 +1,801 @@ +static u32 PCMI2SUcode1f1800[] = { + 0xb500000f, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xb500020b, 0x00000000, 0x00000000, 0x00000000, + 0x820f001f, 0x802f001f, 0x029f9014, 0x829efef0, + 0x8286000f, 0x02bf0054, 0x82bcfef4, 0x82a6000e, + 0x80074000, 0x001f6193, 0x8013001f, 0x9020c000, + 0x003fb006, 0x803effe8, 0x803effec, 0x9020fa00, + 0x803effd0, 0x803effdc, 0x803effd8, 0x9020fe00, + 0x803effd4, 0x90400000, 0x804600a2, 0x90421800, + 0x804600a3, 0x80132000, 0x98000040, 0x800600a6, + 0x80050080, 0x98000002, 0x80060080, 0x80070001, + 0x001f2013, 0x80070000, 0x001f23f9, 0x801e4b0c, + 0x001f210c, 0x80070001, 0x001f2324, 0x80070800, + 0x001f600f, 0x001fb0cb, 0x001fb010, 0x801efff0, + 0x98004000, 0x001f600e, 0x83e4011f, 0x80070000, + 0x801e4b14, 0x800500a0, 0xb0000001, 0xb4000009, + 0x80070001, 0x800600a0, 0x80050080, 0x98000020, + 0x80060080, 0x9400ffdf, 0x80060080, 0x80070000, + 0x800600a0, 0x80074000, 0x801e4b04, 0x81df0004, + 0x801bfff0, 0x00000000, 0x940000ff, 0xb0000000, + 0xb4200033, 0x003f400e, 0x94010010, 0xb0000000, + 0xb400fff7, 0x003f0013, 0xb0010001, 0xb420001f, + 0x803bffe8, 0x801bffec, 0x805b4b04, 0x00000000, + 0x3001b800, 0xb4600001, 0x9021a000, 0x0421b800, + 0x3001b802, 0xb460000d, 0x80050086, 0x005f9044, + 0x0420b802, 0xb00101e0, 0xb4a0ffe5, 0x001fb010, + 0x001f010c, 0xb0000001, 0xb400ffe1, 0x80070001, + 0x001f210c, 0x83e400ec, 0xb500ffdd, 0x8007001f, + 0x94000003, 0x5810b800, 0x83e719ec, 0x1bffb800, + 0x003f9008, 0x1821b800, 0x00ffb801, 0x80270000, + 0x003f2013, 0x8007001f, 0x94000003, 0x5810b800, + 0x83671a14, 0x1b7bb800, 0x003f9009, 0x1821b800, + 0x00ffb801, 0x80070000, 0x001f210c, 0xb500ffc8, + 0x003f400e, 0xb0000086, 0xb4400055, 0xb0000084, + 0xb400003f, 0xb0000085, 0xb4000045, 0xb0000086, + 0xb4000047, 0xb0000083, 0xb4000000, 0x815bff7c, + 0x00000000, 0x940a0080, 0x5c07b800, 0xb0000001, + 0xb4000073, 0x81674b18, 0x940a0007, 0x5803b800, + 0x116bb800, 0x005bb80b, 0x916b0004, 0x001bb80b, + 0x80530030, 0x98422000, 0x8013ffcf, 0x9800cfff, + 0x806500d4, 0x1463b800, 0x1863b802, 0x806600d4, + 0x80073cfb, 0x801e4b00, 0x800600a1, 0x80074000, + 0x801e4b04, 0x8013001f, 0x98405000, 0x805effe0, + 0x005fb006, 0x805effe8, 0x805effec, 0x9042a000, + 0x805effe4, 0x9040fa00, 0x805effd0, 0x805effdc, + 0x805effd8, 0x9040fe00, 0x805effd4, 0x8013007f, + 0x9800ffff, 0x001fb040, 0x80070001, 0x001f2013, + 0x80070000, 0x001f2324, 0x001fb0cb, 0x001fb010, + 0x001fb041, 0x001fb042, 0x80073350, 0x001fb008, + 0x80071ea0, 0x001fb009, 0x98214000, 0xb5000010, + 0x94011000, 0xb0001000, 0xb4200001, 0x9421efff, + 0x98210010, 0xb500000a, 0x80070000, 0x001fb0cb, + 0x83e40099, 0x003f400e, 0x9421ffef, 0xb5000004, + 0x83e40095, 0x003f400e, 0x98211000, 0x9421ffef, + 0x003f600e, 0x80070100, 0x801efff0, 0xb500ff70, + 0xb000008b, 0xb4000018, 0xb0000087, 0xb400ffee, + 0xb0000088, 0xb4000016, 0xb000008a, 0xb4000016, + 0xb000008c, 0xb4000017, 0xb0000089, 0xb4000019, + 0xb00000a0, 0xb400001b, 0xb00000a1, 0xb4000047, + 0xb00000a2, 0xb4000054, 0xb00000a3, 0xb400004c, + 0xb00000a4, 0xb4000056, 0xb00000a5, 0xb400005a, + 0xb00000a6, 0xb400005e, 0x803efff8, 0xb500ffe1, + 0x9421ffdf, 0xb500ffde, 0x80270100, 0x803efff8, + 0xb500ffdc, 0x803bffb0, 0x00000000, 0x003fb040, + 0xb500ffd8, 0x803bff80, 0x00000000, 0x003f6001, + 0xb500ffd4, 0x003f90ba, 0x803efff8, 0xb500ffd1, + 0x81674b18, 0x940a0007, 0x5803b800, 0x116bb800, + 0x005bb80b, 0x916b0004, 0x001bb80b, 0x806500d4, + 0x1463b800, 0x1863b802, 0x806600d4, 0x80130001, + 0x98003d21, 0x800600a1, 0x801e4b00, 0x80074000, + 0x801e4b04, 0x8013001f, 0x98405000, 0x805effe0, + 0x005fb006, 0x805effe8, 0x805effec, 0x9042a000, + 0x805effe4, 0x9040fa00, 0x805effd0, 0x805effdc, + 0x805effd8, 0x9040fe00, 0x805effd4, 0x80070001, + 0x001f2013, 0x80070000, 0x001f2324, 0x001fb0cb, + 0x001fb010, 0x80073b90, 0x001fb008, 0x80074380, + 0x001fb009, 0x98214000, 0xb500ffa5, 0x80270000, + 0x8047fef0, 0x003eb802, 0x90420004, 0x003eb802, + 0x90420004, 0x003eb802, 0x90420004, 0x003eb802, + 0x81df0000, 0x00000000, 0x00000000, 0x83640437, + 0x81df0004, 0xb500ff97, 0x81df0000, 0x00000000, + 0x00000000, 0x836403e1, 0x81df0004, 0xb500ff91, + 0x81df0000, 0x00000000, 0x00000000, 0x8364039c, + 0x81df0004, 0xb500ff8b, 0x81df0000, 0x00000000, + 0x00000000, 0x834402ff, 0x81df0004, 0xb500ff85, + 0x81df0000, 0x00000000, 0x00000000, 0x834402e4, + 0x81df0004, 0xb500ff7f, 0x80070000, 0x80470000, + 0x81df0000, 0x00000000, 0x00000000, 0xb6002003, + 0xb6003002, 0x001eb802, 0x90420004, 0x80171000, + 0x8057ffff, 0xb6002002, 0xb6001801, 0x001fa020, + 0x81df0004, 0x00ffb81f, 0x817bff7c, 0x00000000, + 0x956b0080, 0x5d67b80b, 0x83a70000, 0x8057ffff, + 0x80770000, 0x8073007a, 0x9863e7d2, 0xb00b0001, + 0xb4200002, 0x8073007d, 0x98636d4a, 0x0207b803, + 0x81df0000, 0x00000000, 0x00000000, 0xb00b0001, + 0xb400000a, 0x80171000, 0xb6008007, 0x003fc0c0, + 0x005fc740, 0x40c1b810, 0x4102b810, 0x001fe0c6, + 0x001fe0c8, 0x4210b803, 0xb5000009, 0x80171000, + 0xb6000007, 0x003fc020, 0x005fc7e0, 0x40c1b810, + 0x4102b810, 0x001fe026, 0x001fe0a8, 0x4210b803, + 0x81df0004, 0x80270000, 0x003f2013, 0x8007001f, + 0x94000003, 0x5810b800, 0x83671e7c, 0x1b7bb800, + 0x003f9009, 0x1821b800, 0x00ffb801, 0x003f0013, + 0xb0010001, 0xb420fff3, 0x93bd0001, 0xb01d0004, + 0xb480ffd7, 0x00ffb81f, 0x00000000, 0x00000000, + 0x003f03f9, 0x009f0324, 0x84840001, 0xb0010000, + 0xb4000011, 0x815b4b0c, 0x81070000, 0x81270be8, + 0xb00a0000, 0xb4000002, 0x81070c00, 0x812717e8, + 0x802500a5, 0x806500a5, 0x3001b803, 0xb420fffc, + 0x9421ffff, 0x3001b808, 0xb480000b, 0x3001b809, + 0xb4a00059, 0xb5000008, 0xb0040000, 0xb4200003, + 0x802717ff, 0x81470000, 0xb5000003, 0x80270001, + 0x003f23f9, 0x81470c00, 0xb0040000, 0xb4200006, + 0x039f4193, 0x5b81b81c, 0x003f90cb, 0x1021b81c, + 0x003fb0cb, 0x83840246, 0x829bff80, 0x801300e0, + 0x1434b800, 0x5c35b801, 0x8013001f, 0x1454b800, + 0x5c50b802, 0x8073007f, 0x9863ffff, 0xb002000f, + 0xb4800001, 0x90210001, 0x84210004, 0xb0010000, + 0xb4a00001, 0x6861b803, 0x005f9040, 0x4082b803, + 0x80af001f, 0x808f0000, 0x806f0000, 0x8007ffff, + 0x8033ffff, 0x80171000, 0x81df0000, 0x00000000, + 0x00000000, 0xb600180a, 0xb6002009, 0x58708000, + 0x6068b803, 0x40c4b803, 0x00000000, 0x00c8b806, + 0x00000000, 0x00000000, 0x00000000, 0x5807a026, + 0x81df0004, 0x80670400, 0x5d22b80a, 0x81df0000, + 0x00000000, 0x00000000, 0xb600180a, 0x00cfb803, + 0x013fb0bc, 0x5922b809, 0x01afb809, 0x013f90bc, + 0x0047b86f, 0xb0020001, 0xb4c0fffd, 0x90630020, + 0x91290020, 0x81df0004, 0x808f0000, 0x801b4b14, + 0x80270001, 0xb0000001, 0xb4000002, 0x802600a0, + 0x803e4b14, 0x81270c00, 0xb00a0000, 0xb4000001, + 0x81270000, 0x813e4b0c, 0x80270001, 0x003f2013, + 0x80050086, 0x001fb044, 0x00ffb81b, 0x00000000, + 0x029fb00a, 0x02bfb00b, 0x02dfb00c, 0x02ffb00d, + 0x031fb00e, 0x033fb00f, 0x033f400f, 0x0287b86f, + 0x029fb005, 0x8285009c, 0x96b48000, 0xb0158000, + 0xb4000191, 0x96b40100, 0xb0150100, 0xb40001ad, + 0x96b40400, 0xb0150400, 0xb40001bf, 0x96b40001, + 0xb0150001, 0xb400000c, 0x96b40008, 0xb0150008, + 0xb400019a, 0x96b44000, 0xb0154000, 0xb40001be, + 0x96b40002, 0xb0150002, 0xb400015e, 0x00000000, + 0x00000000, 0xb50001d0, 0x02bf9017, 0x92b50001, + 0x02bfb017, 0x82850082, 0x83050081, 0x82a5009a, + 0x96b50001, 0xb0150001, 0xb4200014, 0x82a70000, + 0x02bfb017, 0x96b41840, 0xb0150800, 0xb420000c, + 0x96b40008, 0x5aa9b815, 0x96d46000, 0x5ec3b816, + 0x82f3000f, 0x9af7c00f, 0x1718b817, 0x1ab5b818, + 0x1ab5b816, 0x9ab50340, 0x82a60081, 0xb500013d, + 0x9b180180, 0x83060081, 0xb500013a, 0x82a5009a, + 0x96b50002, 0xb0150002, 0xb420001b, 0x82a70000, + 0x02bfb017, 0x96b41800, 0xb0151800, 0xb4000013, + 0x96b40040, 0xb0150040, 0xb4200004, 0xa3180c00, + 0x9b180340, 0x83060081, 0xb500012a, 0x96b40008, + 0x5aa9b815, 0x96d46000, 0x5ec3b816, 0x82f3000f, + 0x9af7c00f, 0x1718b817, 0x1ab5b818, 0x1ab5b816, + 0x9ab50340, 0x82a60081, 0xb500011e, 0x9b180180, + 0x83060081, 0xb500011b, 0x82a500c1, 0x96b5000f, + 0xb015000b, 0xb420000e, 0x96b40020, 0xb0150020, + 0xb400000b, 0x96b40200, 0xb0150200, 0xb4000008, + 0x82c50086, 0x82e50094, 0x3016b817, 0xb4400004, + 0x06f7b816, 0xb017ff00, 0xb4400001, 0xb5000109, + 0x96b46000, 0xb0156000, 0xb4000011, 0x96b41820, + 0xb0150820, 0xb4200004, 0x9b391000, 0x82a5009a, + 0x96b5feff, 0x82a6009a, 0x96b40040, 0xb0150040, + 0xb4200001, 0x9739efff, 0x96b91000, 0xb0151000, + 0xb4200003, 0x82a5009a, 0x9ab50100, 0x82a6009a, + 0x96b40040, 0xb0150040, 0xb4200019, 0x96b41800, + 0xb0151800, 0xb4200006, 0x96b98000, 0xb0158000, + 0xb4200003, 0x9b180180, 0x83060081, 0xb50000e9, + 0x96d80c00, 0x82b300ff, 0x9ab5f3ff, 0x1718b815, + 0xb0160c00, 0xb4000007, 0x82e50098, 0x96f70400, + 0xb0170400, 0xb4200002, 0x82c70c00, 0xb5000001, + 0xa2d60c00, 0x1b18b816, 0x9b180340, 0xb50000cf, + 0x96b40220, 0xb0150000, 0xb4e00033, 0x82a5009d, + 0x82f3ffff, 0x16b5b817, 0x82f3000e, 0x3015b817, + 0xb420002d, 0x96f98000, 0xb0178000, 0xb400002a, + 0x82a70000, 0x02bfb017, 0x82c50081, 0x9ab60020, + 0x82a60081, 0x82a50086, 0x92b50bb8, 0x82a60094, + 0x82c60081, 0x82c5009d, 0x96d6ffff, 0x82b30032, + 0x9ab58001, 0x82e500c1, 0x96f7000f, 0xb017000b, + 0xb4000002, 0x82b30022, 0x9ab58001, 0x1ab5b816, + 0x82c5009a, 0x96d60020, 0xb0160020, 0xb4200002, + 0x82b30032, 0x9ab58001, 0x82a6009d, 0x02ff9017, + 0x00000000, 0xb0170040, 0xb480000b, 0x96f41c00, + 0xb0171c00, 0xb4200008, 0x82e50086, 0x82c50094, + 0x92d63000, 0x3016b817, 0xb4400003, 0x9b180180, + 0x83060081, 0xb50000a3, 0x5eb5b814, 0x96b500f0, + 0x96f46000, 0x5eedb817, 0x1ab5b817, 0xb0170003, + 0xb4000004, 0x96b500ef, 0x96f70001, 0x5ae4b817, + 0x1ab5b817, 0x96d41800, 0xb0161800, 0xb400000a, + 0x96f900ff, 0x96b500ff, 0x9739ff00, 0x1b39b815, + 0x02a7b817, 0x96b500f3, 0x96d40008, 0x5ec1b816, + 0x1ab5b816, 0xb500000c, 0x96f98000, 0xb0178000, + 0xb4200007, 0x5efeb814, 0x96f70001, 0xb0170001, + 0xb4000003, 0x9b180180, 0x83060081, 0xb5000081, + 0x96b500f3, 0x9ab50008, 0x9739fff3, 0x96d40020, + 0xb0160020, 0xb4200017, 0x9b398000, 0x82c70000, + 0x02dfb017, 0x96d40010, 0x5ac8b816, 0x82f300ff, + 0x9af7cfff, 0x1718b817, 0x1b18b816, 0x9b180340, + 0x82c5009d, 0x96d6ffff, 0x82f3000e, 0x9af78001, + 0x1af7b816, 0x82c5009a, 0x96d60020, 0xb0160020, + 0xb4200002, 0x82f30032, 0x9af78001, 0x82e6009d, + 0xb500005a, 0x97397fff, 0x96b500ff, 0x5aaab815, + 0x82f300fc, 0x9af703ff, 0x1718b817, 0x1b18b815, + 0x9b180340, 0x82c5009a, 0x96d60010, 0xb0160010, + 0xb4200024, 0x82c70000, 0x02dfb017, 0x82c50086, + 0x92d60bb8, 0x82c60086, 0x82c50094, 0x5eefb818, + 0x96f70003, 0xb0170003, 0xb4200002, 0x82e70bb8, + 0xb5000001, 0x82e70bb8, 0x12d6b817, 0x82e50081, + 0x9af70020, 0x82e60081, 0x82c60094, 0xa2f70020, + 0x82e60081, 0x82f30001, 0x16f7b818, 0x5ef0b817, + 0xb0170001, 0xb4000004, 0x96f84000, 0x5ee4b817, + 0x9718f3ff, 0x1b18b817, 0x82f3000a, 0x9af78000, + 0x82e6009d, 0x83060081, 0x83070001, 0x8306009f, + 0xb50000ad, 0x82c5009d, 0x82f3000e, 0x9af78001, + 0x3016b817, 0xb420000f, 0x82b30032, 0x9ab58001, + 0x82e500c1, 0x96f7000f, 0xb017000b, 0xb4000002, + 0x82b30022, 0x9ab58001, 0x82c5009a, 0x96d60020, + 0xb0160020, 0xb4200002, 0x82b30032, 0x9ab58001, + 0x82a6009d, 0x82c5009a, 0x96d60080, 0xb0160080, + 0xb4000011, 0x02df9017, 0x00000000, 0xb0160010, + 0xb480000d, 0x82c500c1, 0x96d6000f, 0xb016000b, + 0xb4000009, 0x82c50087, 0x96d60080, 0x5ac7b816, + 0x96f84000, 0x3017b816, 0xb4200003, 0x033f400f, + 0x9b394000, 0xb500000b, 0x9739bfff, 0x82e50061, + 0x96f70008, 0xb0170008, 0xb4000005, 0x5eefb818, + 0x96f70003, 0xb0170003, 0xb4000001, 0x9718ffff, + 0x83060081, 0x83070001, 0x8306009f, 0x00000000, + 0xb5000075, 0x82850083, 0x96b400ff, 0xb015003c, + 0xb4200019, 0x96b92000, 0xb0152000, 0xb4000002, + 0x9b392000, 0xb5000014, 0x9739d3ff, 0x82870000, + 0x82860087, 0x82870008, 0x82860083, 0x829bff78, + 0x82a7001f, 0xb0140400, 0xb4000001, 0x82a70010, + 0x82a600c9, 0x829bff78, 0x00000000, 0x828600cb, + 0x8285009d, 0x82b3ffff, 0x9ab5fffd, 0x1694b815, + 0x8286009d, 0xb5000000, 0x83070002, 0x8306009f, + 0x00000000, 0xb5000054, 0x96b90800, 0xb0150800, + 0xb4200009, 0x9739f7ff, 0x82a703fd, 0x82a600cb, + 0x82a7003c, 0x82a60083, 0x8285009d, 0x9a940002, + 0x8286009d, 0xb5000004, 0x82850087, 0x5a82b814, + 0xa2940200, 0x82860087, 0xb5000000, 0x83078000, + 0x8306009f, 0x00000000, 0xb500003f, 0x82850086, + 0x82a50094, 0x3015b814, 0xb4800002, 0x86b50bb8, + 0x82a60086, 0x83070008, 0x8306009f, 0x00000000, + 0xb5000035, 0x83050069, 0x9718003f, 0x82e50064, + 0x12f7b818, 0x86f70088, 0x82feff74, 0x02e7b86f, + 0x9af74000, 0x01ffb817, 0x96f7bfff, 0x01ffb817, + 0x83050081, 0x82f3001c, 0x9af703ff, 0x1718b817, + 0x9b180140, 0x83060081, 0x83070100, 0x8306009f, + 0x00000000, 0xb5000020, 0x83070000, 0x83050081, + 0x9b180180, 0x83060081, 0x83070400, 0x8306009f, + 0x00000000, 0xb5000018, 0x82870000, 0x82850082, + 0x5eb7b814, 0x96b500fc, 0x96d40006, 0x5ec1b816, + 0x1ab5b816, 0x5aacb815, 0x83050081, 0x82d3001c, + 0x9ad600ff, 0x1718b816, 0x1b18b815, 0x9b180e00, + 0x83060081, 0x83074000, 0x8306009f, 0x8305009d, + 0x82d300ff, 0x9ad6bfff, 0x1718b816, 0x8306009d, + 0x00000000, 0xb5000000, 0x029f9005, 0x01ffb814, + 0x033f600f, 0x029f900a, 0x02bf900b, 0x02df900c, + 0x02ff900d, 0x031f900e, 0x033f900f, 0x00ffb81e, + 0x02ff9010, 0x92f70b43, 0x02ffb010, 0x02ff90cb, + 0x82bbffdc, 0x829bffd8, 0x93150004, 0x3014b815, + 0xb4000010, 0x02dbb818, 0x029bb815, 0x3017b816, + 0xb480000c, 0x5a81b814, 0x029fb010, 0x82860095, + 0x8293001f, 0x9294fe00, 0x92b50008, 0x3015b814, + 0xb4800002, 0x82b3001f, 0x92b5fa00, 0x82beffdc, + 0xb500ffeb, 0x029f9010, 0x83250094, 0x06d4b819, + 0x02d6b816, 0xb016ffff, 0xb4a0000a, 0x8293000e, + 0x9a948001, 0x82c5009d, 0x96d6ffff, 0x1a94b816, + 0x82c5009a, 0x96d60010, 0xb0160010, 0xb4000001, + 0x8286009d, 0x00ffb81c, 0x00000000, 0x00000000, + 0x001f9012, 0x001fb100, 0x001f004c, 0x001f2404, + 0x801bfef0, 0x8058fef4, 0x803bff68, 0x8078ff6c, + 0x2000b801, 0x2042b803, 0x001fb104, 0x005f2414, + 0x82e70001, 0x83640048, 0x029fb014, 0x829efef0, + 0x8286000f, 0x02bf2054, 0x82bcfef4, 0x82a6000e, + 0x00ffb81a, 0x80e70001, 0x801336e3, 0x9800eb76, + 0x001fb100, 0x800700ab, 0x001f2404, 0x801bc3e8, + 0x8058c3ec, 0x83640024, 0x82e70000, 0x83640036, + 0x029fb300, 0x029fb100, 0x02bf2c04, 0x02bf2404, + 0x801bc000, 0x8058c004, 0x8364001b, 0x82e70000, + 0x8364002d, 0x001f9300, 0x3000b814, 0xb420000a, + 0x001f0c04, 0x3000b815, 0xb4200007, 0x829efef0, + 0x82bcfef4, 0x029fb012, 0x02bf204c, 0x82870001, + 0x829cfef5, 0x00ffb81a, 0xb0070000, 0xb4000007, + 0x80e70000, 0x801399fa, 0x9800c92e, 0x001fb100, + 0x800700af, 0x001f2404, 0xb500ffdc, 0x82870000, + 0x829cfef5, 0x00ffb81a, 0x80c700ff, 0x803bff68, + 0x8078ff6c, 0x14a0b806, 0x2063b805, 0x007f2414, + 0x2021b802, 0x58c8b806, 0x14a0b806, 0x58b0b805, + 0x2021b805, 0x58c8b806, 0x14a0b806, 0x2021b805, + 0x58c8b806, 0x14a0b806, 0x5cb0b805, 0x2021b805, + 0x003fb104, 0x00ffb81b, 0x82c70000, 0x83070400, + 0x83270005, 0x8197040c, 0x81d7ffff, 0x83840126, + 0x83840001, 0x00ffb81b, 0x808f0000, 0x806f001f, + 0x80af001f, 0x80270140, 0x81e70228, 0x5de2b80f, + 0xb6000208, 0x00cfb801, 0x01ffb0bc, 0x59e2b80f, + 0x01cfb80f, 0x01ff90bc, 0xb520ffff, 0x91ef0020, + 0x90210020, 0x80270180, 0x81e70120, 0x5de2b80f, + 0xb6000208, 0x00cfb801, 0x01ffb0bc, 0x59e2b80f, + 0x01cfb80f, 0x01ff90bc, 0xb520ffff, 0x91ef0020, + 0x90210020, 0x8057ffff, 0x80170430, 0x80070410, + 0x80270408, 0xb6000509, 0x005ff000, 0x90420500, + 0x007ff001, 0x90630600, 0x009ff002, 0x00bff003, + 0x2004a025, 0x90000001, 0x90210001, 0x80070414, + 0x80d7ffff, 0x8097045c, 0x8017043c, 0xb6000404, + 0x005ff000, 0x007f87e0, 0x84000001, 0x2082a7e3, + 0x80970460, 0x80170440, 0x2082b803, 0x007f8000, + 0x2083a004, 0x80170430, 0x80970450, 0x80270408, + 0xb6000508, 0x005f8024, 0x90420500, 0x007ff001, + 0x90630600, 0x009ff002, 0x00bff003, 0x2004a025, + 0x90210001, 0x80170440, 0x00000000, 0x02bf87e0, + 0x80970460, 0x82870000, 0xb6000404, 0x005f87e4, + 0x5a88b814, 0x204287e0, 0x1a94b802, 0x00ffb81c, + 0x001f0a49, 0x001f2709, 0x001f0a41, 0x001f2708, + 0x001f0a46, 0x001f2707, 0x001f0a48, 0x001f2706, + 0x001f0a42, 0x001f2705, 0x001f0a47, 0x001f2704, + 0x001f0a45, 0x001f2703, 0x001f0a43, 0x001f2702, + 0x001f0a40, 0x001f2701, 0x001f0a44, 0x001f2700, + 0x001f0c25, 0xa020000c, 0x94400001, 0x94600002, + 0x94810004, 0x94a10008, 0x94c00010, 0x5943b802, + 0x5861b803, 0x5882b804, 0x5ca2b805, 0x5cc4b806, + 0x194ab803, 0x194ab804, 0x194ab805, 0x194ab806, + 0x015f2738, 0x801b0220, 0x003f91c1, 0x5c28b801, + 0x005f91c2, 0x5858b802, 0x1821b802, 0x2000b801, + 0x001fb1c4, 0x80180224, 0x003f0709, 0x2000b801, + 0x001f2714, 0x82c70001, 0x82e70001, 0x83070710, + 0x8327001e, 0x81970735, 0x8384009f, 0x02df0738, + 0x82170a30, 0x838400f1, 0x819efef0, 0x817cfef4, + 0x819eff68, 0x817cff6c, 0x00ffb81b, 0x820f001f, + 0x8018fef8, 0x8057ffff, 0x001f2709, 0x8018fef6, + 0x80d7ffff, 0x001f2708, 0x8018fefa, 0x8157ffff, + 0x001f2707, 0x8018fefd, 0x81d7ffff, 0x001f2706, + 0x8018fefb, 0x802f001f, 0x001f2705, 0x8018fefe, + 0x00000000, 0x001f2704, 0x8018fef9, 0x00000000, + 0x001f2703, 0x8018feff, 0x00000000, 0x001f2702, + 0x8018fef7, 0x00000000, 0x001f2701, 0x8018fefc, + 0x00000000, 0x001f2700, 0x001f0c25, 0xa0200011, + 0x94410001, 0x94600002, 0x94800004, 0x94a00008, + 0x94c10010, 0x5941b802, 0x5861b803, 0x5c82b804, + 0x58a1b805, 0x5cc1b806, 0x194ab803, 0x194ab804, + 0x194ab805, 0x194ab806, 0x015f2738, 0x801b0220, + 0x003f91c1, 0x5c28b801, 0x005f91c2, 0x5858b802, + 0x1821b802, 0x2000b801, 0x001fb1c4, 0x80180224, + 0x003f0709, 0x2000b801, 0x001f2714, 0x82c70001, + 0x82e70001, 0x83070710, 0x8327001e, 0x81970735, + 0x83840055, 0x02df0738, 0x82170a20, 0x838400a7, + 0x819efef0, 0x817cfef4, 0x5ac8b80c, 0x02ff0a44, + 0x1ad6b817, 0x02dfb291, 0x5ed8b80c, 0x5968b80b, + 0x1ad6b80b, 0x02df6524, 0x00ffb81b, 0x820f001f, + 0x8018fefe, 0x8057ffff, 0x001f2709, 0x8018fefa, + 0x80d7ffff, 0x001f2708, 0x8018fefc, 0x8157ffff, + 0x001f2707, 0x8018feff, 0x81d7ffff, 0x001f2706, + 0x8018fef8, 0x802f001f, 0x001f2705, 0x8018fefb, + 0x00000000, 0x001f2704, 0x8018fefd, 0x00000000, + 0x001f2703, 0x8018fef6, 0x00000000, 0x001f2702, + 0x8018fef9, 0x00000000, 0x001f2701, 0x8018fef7, + 0x00000000, 0x001f2700, 0x801b0220, 0x003f91c1, + 0x5c28b801, 0x005f91c2, 0x5858b802, 0x1821b802, + 0x2000b801, 0x001fb1c4, 0x80180224, 0x003f0709, + 0x2000b801, 0x001f2714, 0x82c70001, 0x82e70001, + 0x83070710, 0x8327001e, 0x81970735, 0x83840016, + 0x83270000, 0x831bfef0, 0x82f8fef4, 0x02c7b819, + 0x82170a28, 0x83840065, 0x300cb818, 0xb4200002, + 0x300bb817, 0xb4000006, 0x93390001, 0xb0190020, + 0xb480fff6, 0x83270000, 0x833cfef5, 0x00ffb81b, + 0x019fb290, 0x017f2a44, 0x033f2c25, 0x83270001, + 0x833cfef5, 0x00ffb81b, 0x0007b818, 0x90000003, + 0x00000000, 0x015ff000, 0x90000001, 0x5949b80a, + 0x013ff000, 0x194ab809, 0x84000002, 0x994a0100, + 0x017ff000, 0x958b00f8, 0x5981b80c, 0x956b0007, + 0x198cb80b, 0x84000002, 0x998c0008, 0x017ff000, + 0x90000001, 0x5971b80b, 0x198cb80b, 0x017ff000, + 0x5969b80b, 0x198cb80b, 0x81a70000, 0x94d90003, + 0x82a70000, 0xb6260019, 0xb6000818, 0x5df0b80a, + 0x5e02b80a, 0x21efb810, 0x95ef0001, 0x5941b80a, + 0x194ab80f, 0x21efb816, 0x5e18b80c, 0x5e35b80c, + 0x5e54b80c, 0x5e6cb80c, 0x2210b811, 0x2252b813, + 0x2210b812, 0x96100001, 0x5981b80c, 0x198cb810, + 0x2210b817, 0x10afb810, 0x10a5b80d, 0x5da1b805, + 0x94a50001, 0x5aa1b815, 0x1ab5b805, 0x019fa7f5, + 0x5cc2b819, 0xb626001c, 0x82870000, 0xb6000419, + 0xb6000818, 0x5df0b80a, 0x5e02b80a, 0x21efb810, + 0x95ef0001, 0x5941b80a, 0x194ab80f, 0x21efb816, + 0x5e18b80c, 0x5e35b80c, 0x5e54b80c, 0x5e6cb80c, + 0x2210b811, 0x2252b813, 0x2210b812, 0x96100001, + 0x5981b80c, 0x198cb810, 0x2210b817, 0x10afb810, + 0x10a5b80d, 0x5da1b805, 0x94a50001, 0x5a81b814, + 0x1a94b805, 0x019fa7f4, 0x00ffb81c, 0x8257ffff, + 0x808f0000, 0x806f001f, 0x80af001f, 0x80270200, + 0x81e7ff00, 0x5de2b80f, 0xb6000208, 0x00cfb801, + 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, 0x01ff90bc, + 0xb520ffff, 0x91ef0020, 0x90210020, 0x80270240, + 0x81e70000, 0x5de2b80f, 0xb6000208, 0x00cfb801, + 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, 0x01ff90bc, + 0xb520ffff, 0x91ef0020, 0x90210020, 0x80270180, + 0x81e70120, 0x5de2b80f, 0xb6000208, 0x00cfb801, + 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, 0x01ff90bc, + 0xb520ffff, 0x91ef0020, 0x90210020, 0x806f0007, + 0x80af0007, 0x80270280, 0x81e70100, 0x5de2b80f, + 0x00cfb801, 0x01ffb0bc, 0x59e2b80f, 0x01cfb80f, + 0x01ff90bc, 0xb520ffff, 0x91ef0020, 0x90210020, + 0x80170760, 0x001f0700, 0x001fa020, 0x001f0701, + 0x001fa020, 0x001f0702, 0x001fa020, 0x001f0703, + 0x001fa020, 0x001f0704, 0x001fa000, 0x80970750, + 0x81170770, 0x82a70735, 0x83a40060, 0x001f87e4, + 0xb6000405, 0x86b50001, 0x83a4005c, 0x001f8004, + 0x003f87e8, 0x2080a7e1, 0x80970770, 0x80170750, + 0x81170750, 0x81970740, 0x82a70730, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a40050, 0x001f87e4, + 0xb6000405, 0x86b50001, 0x83a4004c, 0x001f8004, + 0x003f87e8, 0x2080a7e1, 0x80970750, 0x80170770, + 0x81170770, 0x81970760, 0x82a7072b, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a40040, 0x83a4004e, + 0xb6000407, 0x86b50001, 0x83a4003c, 0x001f8004, + 0x003f87e8, 0x2080a001, 0x83a40047, 0x00000000, + 0x80970770, 0x80170750, 0x81170750, 0x81970740, + 0x82a70726, 0x001f800c, 0x003f8008, 0x2100a001, + 0x83a4002e, 0x83a4003c, 0xb6000407, 0x86b50001, + 0x83a4002a, 0x001f8004, 0x003f87e8, 0x2080a001, + 0x83a40035, 0x00000000, 0x80970750, 0x80170770, + 0x81170770, 0x81970760, 0x82a70721, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a4001c, 0x001f87e4, + 0xb6000405, 0x86b50001, 0x83a40018, 0x001f8004, + 0x003f87e8, 0x2080a7e1, 0x80970770, 0x80170750, + 0x81170750, 0x81970740, 0x82a7071c, 0x001f800c, + 0x003f8008, 0x2100a001, 0x83a4000c, 0x017f87e4, + 0x81870000, 0xb6000406, 0x86b50001, 0x83a40007, + 0x001f87e4, 0x200087e8, 0x5988b80c, 0x198cb800, + 0x021fa02c, 0x021fa00b, 0x00ffb81c, 0x005ff015, + 0x90420600, 0x003f87e0, 0x001ff002, 0x2060b801, + 0x90630800, 0x90960a00, 0x001ff003, 0x003ff004, + 0x20a0b801, 0x90a50900, 0x00000000, 0x001ff005, + 0x009fa000, 0x00ffb81d, 0x001f8004, 0x5c21b800, + 0x5847b800, 0x1821b802, 0x942100ff, 0x2080a7e1, + 0x00ffb81d, 0x00000000, 0x00000000, 0x00000000, + 0x829bff80, 0x80af000f, 0x808f0000, 0x806f0000, + 0x82bbffec, 0x82fbffe4, 0x00000000, 0x82beffb8, + 0x95540700, 0x5d48b80a, 0x914a0001, 0x0227b80a, + 0x94343000, 0x5c2cb801, 0xb0010000, 0xb4000001, + 0x5a21b811, 0x9574c000, 0x5d6eb80b, 0x918b4b08, + 0x01b8b80c, 0x96d5ffff, 0x5ec2b816, 0x96f7ffff, + 0x5ee2b817, 0x8057ffff, 0x80d7ffff, 0x8157ffff, + 0x81d7ffff, 0x81f3ff00, 0x99efff00, 0x821300ff, + 0x9a1000ff, 0x81971000, 0x82670000, 0x82470000, + 0x80270280, 0x81df0000, 0x00000000, 0x00000000, + 0xb62d000d, 0x3016b817, 0xb4800001, 0x86d62800, + 0x00cfb801, 0x02dfb0bc, 0x5ac2b816, 0x01cfb816, + 0x02df90bc, 0x0067b86f, 0xb0030001, 0xb4c0fffd, + 0x92d60010, 0x90210010, 0x81df0004, 0x80170a00, + 0x81df0000, 0x00000000, 0x00000000, 0xb62d0006, + 0xb6001005, 0x146f8000, 0x14908000, 0x5c68b803, + 0x5888b804, 0x1803a024, 0x81df0004, 0x80170a00, + 0x80970d00, 0xb00b0000, 0xb4000004, 0xb00b0001, + 0xb400000a, 0xb00b0002, 0xb4000027, 0x81df0000, + 0x00000000, 0x00000000, 0xb6004002, 0x007f8020, + 0x009fa023, 0x81df0004, 0xb5000029, 0x80d3ffff, + 0x81df0000, 0x00000000, 0x00000000, 0xb6001018, + 0x5c648000, 0x9463ffff, 0x5c888020, 0x58b88000, + 0x1884b805, 0x1484b806, 0x1883a024, 0x5c6c8020, + 0x9463ffff, 0x58908000, 0x1883a024, 0x5c748020, + 0x588c8000, 0x1863b804, 0x9463ffff, 0x58888000, + 0x1484b806, 0x1883a024, 0x5c7c8020, 0x58848000, + 0x1863b804, 0x9463ffff, 0x14868020, 0x1883a024, + 0x81df0004, 0xb500000a, 0x80d3ffff, 0x81df0000, + 0x00000000, 0x00000000, 0xb6002004, 0x007f8020, + 0x009fa023, 0x007f8040, 0x009fa023, 0x81df0004, + 0x00000000, 0x81170d00, 0x80070000, 0x94343000, + 0x5c2cb801, 0xb0010001, 0xb4000099, 0xb00a0001, + 0xb400000e, 0xb00a0002, 0xb4000022, 0xb00a0003, + 0xb400002f, 0xb00a0004, 0xb400005d, 0xb00a0005, + 0xb4000066, 0xb00a0006, 0xb400008a, 0xb00a0007, + 0xb4000088, 0xb00a0008, 0xb4000086, 0x81df0000, + 0x00000000, 0x00000000, 0xb6004010, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x019fa020, 0x019fa020, + 0x019fa020, 0x019fa020, 0x019fa020, 0x5c708028, + 0x9463ffff, 0x019fa023, 0x019fa020, 0x019fa020, + 0x019fa020, 0x019fa020, 0x019fa020, 0x81df0004, + 0xb5000070, 0x81df0000, 0x00000000, 0x00000000, + 0x8027ffff, 0xb6004008, 0x14618008, 0x019fa023, + 0x019fa020, 0x019fa020, 0x5c708028, 0x019fa023, + 0x019fa020, 0x019fa020, 0x81df0004, 0xb5000061, + 0xb0130000, 0xb4000004, 0xb0130001, 0xb4000009, + 0xb0130002, 0xb400001a, 0x83a40102, 0x80170f00, + 0x007f8028, 0x001fa023, 0x007f8028, 0x001fa023, + 0xb5000054, 0x80170f00, 0x00000000, 0x007f8020, + 0x019fa023, 0x007f8000, 0x9463ffff, 0x019fa023, + 0x019fa020, 0x5c708020, 0x58908008, 0x1983a024, + 0x5c708028, 0x019fa023, 0x019fa020, 0x83a400ed, + 0x80170f00, 0x007f8028, 0x001fa023, 0xb5000041, + 0x80170f00, 0x00000000, 0x007f8020, 0x019fa023, + 0x007f8008, 0x9463ffff, 0x019fa023, 0x019fa020, + 0x5c708028, 0x58908008, 0x1983a024, 0x5c708028, + 0x019fa023, 0x019fa020, 0x83a400da, 0xb5000031, + 0x81df0000, 0x00000000, 0x00000000, 0xb6002005, + 0x007f8008, 0x019fa023, 0x007f8008, 0x019fa023, + 0x019fa020, 0x81df0004, 0xb5000026, 0xb0130000, + 0xb4000008, 0xb0130001, 0xb4000012, 0xb0130002, + 0xb400001f, 0xb0130003, 0xb400001d, 0xb0130004, + 0xb400001b, 0x83a400d5, 0x007f8028, 0x019fa023, + 0x007f8028, 0x019fa023, 0x007f8008, 0x9463ffff, + 0x019fa023, 0x80170f00, 0x007f8028, 0x001fa023, + 0xb5000010, 0x80170f00, 0x00000000, 0x5c708020, + 0x58908008, 0x1983a024, 0x5c708028, 0x58908008, + 0x1983a024, 0x5c708028, 0x019fa023, 0x83a400bf, + 0x80170f00, 0x007f8028, 0x001fa023, 0xb5000001, + 0xb5000000, 0x00000000, 0x00000000, 0xb500008e, + 0xb00a0001, 0xb400000e, 0xb00a0002, 0xb400001a, + 0xb00a0003, 0xb4000027, 0xb00a0004, 0xb4000055, + 0xb00a0005, 0xb400005e, 0xb00a0006, 0xb4000082, + 0xb00a0007, 0xb4000080, 0xb00a0008, 0xb400007e, + 0x81df0000, 0x00000000, 0x00000000, 0xb6004008, + 0x007f8028, 0x9463ffff, 0x019fa023, 0x019fa020, + 0x019fa020, 0x019fa020, 0x019fa020, 0x019fa020, + 0x81df0004, 0xb5000070, 0x81df0000, 0x00000000, + 0x00000000, 0x8027ffff, 0xb6002008, 0x14618008, + 0x019fa023, 0x019fa020, 0x019fa020, 0x5c708048, + 0x019fa023, 0x019fa020, 0x019fa020, 0x81df0004, + 0xb5000061, 0xb0130000, 0xb4000004, 0xb0130001, + 0xb4000009, 0xb0130002, 0xb400001a, 0x83a40098, + 0x80170f00, 0x007f8028, 0x001fa023, 0x007f8028, + 0x001fa023, 0xb5000054, 0x80170f00, 0x00000000, + 0x007f8020, 0x019fa023, 0x007f8000, 0x9463ffff, + 0x019fa023, 0x019fa020, 0x5c708020, 0x58908008, + 0x1983a024, 0x5c708028, 0x019fa023, 0x019fa020, + 0x83a40083, 0x80170f00, 0x007f8028, 0x001fa023, + 0xb5000041, 0x80170f00, 0x00000000, 0x007f8020, + 0x019fa023, 0x007f8008, 0x9463ffff, 0x019fa023, + 0x019fa020, 0x5c708028, 0x58908008, 0x1983a024, + 0x5c708028, 0x019fa023, 0x019fa020, 0x83a40070, + 0xb5000031, 0x81df0000, 0x00000000, 0x00000000, + 0xb6002005, 0x007f8008, 0x019fa023, 0x007f8008, + 0x019fa023, 0x019fa020, 0x81df0004, 0xb5000026, + 0xb0130000, 0xb4000008, 0xb0130001, 0xb4000012, + 0xb0130002, 0xb400001f, 0xb0130003, 0xb400001d, + 0xb0130004, 0xb400001b, 0x83a4006b, 0x007f8028, + 0x019fa023, 0x007f8028, 0x019fa023, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x80170f00, 0x007f8028, + 0x001fa023, 0xb5000010, 0x80170f00, 0x00000000, + 0x5c708020, 0x58908008, 0x1983a024, 0x5c708028, + 0x58908008, 0x1983a024, 0x5c708028, 0x019fa023, + 0x83a40055, 0x80170f00, 0x007f8028, 0x001fa023, + 0xb5000001, 0xb5000000, 0x92730001, 0x92520001, + 0x3012b811, 0xb480fe76, 0x003f0324, 0x90210001, + 0xb0010006, 0xb4a00001, 0x80270001, 0x003f2324, + 0x2c8db811, 0x803bffe0, 0x805bffe4, 0x5886b804, + 0x1015b804, 0xad440003, 0x3000b802, 0xb4800001, + 0x8400a000, 0x801effec, 0x015f6193, 0x809e4b04, + 0x00ffb81f, 0x81df0000, 0x00000000, 0x00000000, + 0xb6002a0c, 0x007f8028, 0x019fa023, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x019fa020, 0x5c708028, + 0x58908008, 0x1983a024, 0x5c708028, 0x019fa023, + 0x019fa020, 0x81df0004, 0x00ffb81d, 0x81df0000, + 0x00000000, 0x00000000, 0xb600190f, 0x007f8028, + 0x019fa023, 0x007f8028, 0x019fa023, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x5c708028, 0x58908008, + 0x1983a024, 0x5c708028, 0x58908008, 0x1983a024, + 0x5c708028, 0x019fa023, 0x81df0004, 0x00ffb81d, + 0x81df0000, 0x00000000, 0x00000000, 0xb6002a0c, + 0x007f8028, 0x019fa023, 0x007f8008, 0x9463ffff, + 0x019fa023, 0x019fa020, 0x5c708028, 0x58908008, + 0x1983a024, 0x5c708028, 0x019fa023, 0x019fa020, + 0x81df0004, 0x00ffb81d, 0x81df0000, 0x00000000, + 0x00000000, 0xb600190f, 0x007f8028, 0x019fa023, + 0x007f8028, 0x019fa023, 0x007f8008, 0x9463ffff, + 0x019fa023, 0x5c708028, 0x58908008, 0x1983a024, + 0x5c708028, 0x58908008, 0x1983a024, 0x5c708028, + 0x019fa023, 0x81df0004, 0x00ffb81d, 0x00000000, + 0x829bff80, 0x80af001f, 0x808f0000, 0x806f0000, + 0x82bbffec, 0x82fbffe4, 0x00000000, 0x82beffb8, + 0x95540700, 0x5d48b80a, 0x914a0001, 0x0227b80a, + 0x94343000, 0x5c2cb801, 0xb0010000, 0xb4000001, + 0x5a21b811, 0x9574c000, 0x5d6eb80b, 0x918b4b08, + 0x01b8b80c, 0x96d5ffff, 0x5ec2b816, 0x96f7ffff, + 0x5ee2b817, 0x8057ffff, 0x80d7ffff, 0x8157ffff, + 0x81d7ffff, 0x81f3ff00, 0x99efff00, 0x821300ff, + 0x9a1000ff, 0x81971000, 0x82670000, 0x82470000, + 0x80270280, 0x81df0000, 0x00000000, 0x00000000, + 0xb62d000d, 0x3016b817, 0xb4800001, 0x86d62800, + 0x00cfb801, 0x02dfb0bc, 0x5ac2b816, 0x01cfb816, + 0x02df90bc, 0x0067b86f, 0xb0030001, 0xb4c0fffd, + 0x92d60020, 0x90210020, 0x81df0004, 0x80170a00, + 0x81df0000, 0x00000000, 0x00000000, 0xb62d0006, + 0xb6002005, 0x146f8000, 0x14908000, 0x5c68b803, + 0x5888b804, 0x1803a024, 0x81df0004, 0x80170a00, + 0x80970d00, 0xb00b0000, 0xb4000004, 0xb00b0001, + 0xb400000a, 0xb00b0002, 0xb4000027, 0x81df0000, + 0x00000000, 0x00000000, 0xb6008002, 0x007f8020, + 0x009fa023, 0x81df0004, 0xb5000029, 0x80d3ffff, + 0x81df0000, 0x00000000, 0x00000000, 0xb6002018, + 0x5c648000, 0x9463ffff, 0x5c888020, 0x58b88000, + 0x1884b805, 0x1484b806, 0x1883a024, 0x5c6c8020, + 0x9463ffff, 0x58908000, 0x1883a024, 0x5c748020, + 0x588c8000, 0x1863b804, 0x9463ffff, 0x58888000, + 0x1484b806, 0x1883a024, 0x5c7c8020, 0x58848000, + 0x1863b804, 0x9463ffff, 0x14868020, 0x1883a024, + 0x81df0004, 0xb500000a, 0x80d3ffff, 0x81df0000, + 0x00000000, 0x00000000, 0xb6004004, 0x007f8020, + 0x009fa023, 0x007f8040, 0x009fa023, 0x81df0004, + 0x00000000, 0x81170d00, 0x80070000, 0x94343000, + 0x5c2cb801, 0xb0010001, 0xb400008e, 0xb00a0001, + 0xb400000e, 0xb00a0002, 0xb400001c, 0xb00a0003, + 0xb4000024, 0xb00a0004, 0xb4000052, 0xb00a0005, + 0xb400005b, 0xb00a0006, 0xb400007f, 0xb00a0007, + 0xb400007d, 0xb00a0008, 0xb400007b, 0x81df0000, + 0x00000000, 0x00000000, 0xb600800a, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x019fa020, 0x019fa020, + 0x5c708028, 0x9463ffff, 0x019fa023, 0x019fa020, + 0x019fa020, 0x81df0004, 0xb500006b, 0x81df0000, + 0x00000000, 0x00000000, 0xb6008004, 0x007f8028, + 0x019fa023, 0x019fa020, 0x019fa020, 0x81df0004, + 0xb5000061, 0xb0130000, 0xb4000004, 0xb0130001, + 0xb4000009, 0xb0130002, 0xb400001a, 0x83a400fa, + 0x80170f00, 0x007f8028, 0x001fa023, 0x007f8028, + 0x001fa023, 0xb5000054, 0x80170f00, 0x00000000, + 0x007f8020, 0x019fa023, 0x007f8000, 0x9463ffff, + 0x019fa023, 0x019fa020, 0x5c708020, 0x58908008, + 0x1983a024, 0x5c708028, 0x019fa023, 0x019fa020, + 0x83a400e5, 0x80170f00, 0x007f8028, 0x001fa023, + 0xb5000041, 0x80170f00, 0x00000000, 0x007f8020, + 0x019fa023, 0x007f8008, 0x9463ffff, 0x019fa023, + 0x019fa020, 0x5c708028, 0x58908008, 0x1983a024, + 0x5c708028, 0x019fa023, 0x019fa020, 0x83a400d2, + 0xb5000031, 0x81df0000, 0x00000000, 0x00000000, + 0xb6004005, 0x007f8008, 0x019fa023, 0x007f8008, + 0x019fa023, 0x019fa020, 0x81df0004, 0xb5000026, + 0xb0130000, 0xb4000008, 0xb0130001, 0xb4000012, + 0xb0130002, 0xb400001f, 0xb0130003, 0xb400001d, + 0xb0130004, 0xb400001b, 0x83a400cd, 0x007f8028, + 0x019fa023, 0x007f8028, 0x019fa023, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x80170f00, 0x007f8028, + 0x001fa023, 0xb5000010, 0x80170f00, 0x00000000, + 0x5c708020, 0x58908008, 0x1983a024, 0x5c708028, + 0x58908008, 0x1983a024, 0x5c708028, 0x019fa023, + 0x83a400b7, 0x80170f00, 0x007f8028, 0x001fa023, + 0xb5000001, 0xb5000000, 0x00000000, 0x00000000, + 0xb5000086, 0xb00a0001, 0xb400000e, 0xb00a0002, + 0xb4000017, 0xb00a0003, 0xb400001f, 0xb00a0004, + 0xb400004d, 0xb00a0005, 0xb4000056, 0xb00a0006, + 0xb400007a, 0xb00a0007, 0xb4000078, 0xb00a0008, + 0xb4000076, 0x81df0000, 0x00000000, 0x00000000, + 0xb6008005, 0x007f8028, 0x9463ffff, 0x019fa023, + 0x019fa020, 0x019fa020, 0x81df0004, 0xb500006b, + 0x81df0000, 0x00000000, 0x00000000, 0xb6004004, + 0x007f8048, 0x019fa023, 0x019fa020, 0x019fa020, + 0x81df0004, 0xb5000061, 0xb0130000, 0xb4000004, + 0xb0130001, 0xb4000009, 0xb0130002, 0xb400001a, + 0x83a40098, 0x80170f00, 0x007f8028, 0x001fa023, + 0x007f8028, 0x001fa023, 0xb5000054, 0x80170f00, + 0x00000000, 0x007f8020, 0x019fa023, 0x007f8000, + 0x9463ffff, 0x019fa023, 0x019fa020, 0x5c708020, + 0x58908008, 0x1983a024, 0x5c708028, 0x019fa023, + 0x019fa020, 0x83a40083, 0x80170f00, 0x007f8028, + 0x001fa023, 0xb5000041, 0x80170f00, 0x00000000, + 0x007f8020, 0x019fa023, 0x007f8008, 0x9463ffff, + 0x019fa023, 0x019fa020, 0x5c708028, 0x58908008, + 0x1983a024, 0x5c708028, 0x019fa023, 0x019fa020, + 0x83a40070, 0xb5000031, 0x81df0000, 0x00000000, + 0x00000000, 0xb6004005, 0x007f8008, 0x019fa023, + 0x007f8008, 0x019fa023, 0x019fa020, 0x81df0004, + 0xb5000026, 0xb0130000, 0xb4000008, 0xb0130001, + 0xb4000012, 0xb0130002, 0xb400001f, 0xb0130003, + 0xb400001d, 0xb0130004, 0xb400001b, 0x83a4006b, + 0x007f8028, 0x019fa023, 0x007f8028, 0x019fa023, + 0x007f8008, 0x9463ffff, 0x019fa023, 0x80170f00, + 0x007f8028, 0x001fa023, 0xb5000010, 0x80170f00, + 0x00000000, 0x5c708020, 0x58908008, 0x1983a024, + 0x5c708028, 0x58908008, 0x1983a024, 0x5c708028, + 0x019fa023, 0x83a40055, 0x80170f00, 0x007f8028, + 0x001fa023, 0xb5000001, 0xb5000000, 0x92730001, + 0x92520001, 0x3012b811, 0xb480fe89, 0x003f0324, + 0x90210001, 0xb0010006, 0xb4a00001, 0x80270001, + 0x003f2324, 0x2c8db811, 0x803bffe0, 0x805bffe4, + 0x5887b804, 0x1015b804, 0xad440003, 0x3000b802, + 0xb4800001, 0x8400a000, 0x801effec, 0x015f6193, + 0x809e4b04, 0x00ffb81f, 0x81df0000, 0x00000000, + 0x00000000, 0xb6002a0c, 0x007f8028, 0x019fa023, + 0x007f8008, 0x9463ffff, 0x019fa023, 0x019fa020, + 0x5c708028, 0x58908008, 0x1983a024, 0x5c708028, + 0x019fa023, 0x019fa020, 0x81df0004, 0x00ffb81d, + 0x81df0000, 0x00000000, 0x00000000, 0xb600190f, + 0x007f8028, 0x019fa023, 0x007f8028, 0x019fa023, + 0x007f8008, 0x9463ffff, 0x019fa023, 0x5c708028, + 0x58908008, 0x1983a024, 0x5c708028, 0x58908008, + 0x1983a024, 0x5c708028, 0x019fa023, 0x81df0004, + 0x00ffb81d, 0x81df0000, 0x00000000, 0x00000000, + 0xb6002a0c, 0x007f8028, 0x019fa023, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x019fa020, 0x5c708028, + 0x58908008, 0x1983a024, 0x5c708028, 0x019fa023, + 0x019fa020, 0x81df0004, 0x00ffb81d, 0x81df0000, + 0x00000000, 0x00000000, 0xb600190f, 0x007f8028, + 0x019fa023, 0x007f8028, 0x019fa023, 0x007f8008, + 0x9463ffff, 0x019fa023, 0x5c708028, 0x58908008, + 0x1983a024, 0x5c708028, 0x58908008, 0x1983a024, + 0x5c708028, 0x019fa023, 0x81df0004, 0x00ffb81d, + 0x003f03f9, 0x009f0324, 0x84840001, 0xb0010000, + 0xb4000011, 0x815b4b0c, 0x81070000, 0x81270be8, + 0xb00a0000, 0xb4000002, 0x81070c00, 0x812717e8, + 0x802500a5, 0x806500a5, 0x3001b803, 0xb420fffc, + 0x9421ffff, 0x3001b808, 0xb480000b, 0x3001b809, + 0xb4a00060, 0xb5000008, 0xb0040000, 0xb4200003, + 0x802717ff, 0x81470000, 0xb5000003, 0x80270001, + 0x003f23f9, 0x81470c00, 0xb0040000, 0xb4200006, + 0x039f4193, 0x5b81b81c, 0x003f90cb, 0x1021b81c, + 0x003fb0cb, 0x8384f90e, 0x829bff80, 0x801300e0, + 0x1434b800, 0x5c35b801, 0x8013001f, 0x1454b800, + 0x5c50b802, 0x8073007f, 0x9863ffff, 0xb002000f, + 0xb4800001, 0x90210001, 0x84210004, 0xb0010000, + 0xb4a00001, 0x6861b803, 0x005f9040, 0x4082b803, + 0x80af001f, 0x808f0000, 0x806f0000, 0x8007ffff, + 0x8033ffff, 0x80171000, 0x81df0000, 0x00000000, + 0x00000000, 0xb6001811, 0xb6002010, 0x14618000, + 0x6068b803, 0x40c4b803, 0x14608000, 0x00c8b806, + 0x5870b803, 0x6068b803, 0x4104b803, 0x58c8b806, + 0x0108b808, 0x14c6b801, 0x00000000, 0x00000000, + 0x5d08b808, 0x1508b800, 0x1806a028, 0x81df0004, + 0x80670400, 0x5d22b80a, 0x81df0000, 0x00000000, + 0x00000000, 0xb600180a, 0x00cfb803, 0x013fb0bc, + 0x5922b809, 0x01afb809, 0x013f90bc, 0x0047b86f, + 0xb0020001, 0xb4c0fffd, 0x90630020, 0x91290020, + 0x81df0004, 0x808f0000, 0x801b4b14, 0x80270001, + 0xb0000001, 0xb4000002, 0x802600a0, 0x803e4b14, + 0x81270c00, 0xb00a0000, 0xb4000001, 0x81270000, + 0x813e4b0c, 0x80270001, 0x003f2013, 0x80050086, + 0x001fb044, 0x00ffb81b, 0x00000000, 0x00000000, +}; + +static u32 PCMI2SUcode1f4b00[] = { + 0x00000000, 0x00000000, 0x00060504, 0x00000000, + 0x00000000, 0x00000000, 0x00300000, 0xffcfcfff, + 0x00302000, 0xffcfcfff, 0x00380000, 0xffc7c7ff, + 0xcbcecdc4, 0xcfcac9c8, 0xc3c6c5cc, 0xc7c2c1c0, + 0x1b1e1d14, 0x1f1a1918, 0x1316151c, 0x17121110, + 0x2b2e2d24, 0x2f2a2928, 0x2326252c, 0x27222120, + 0x3b3e3d34, 0x3f3a3938, 0x3336353c, 0x37323130, + 0x0b0e0d04, 0x0f0a0908, 0x0306050c, 0x07020100, + 0xdbdeddd4, 0xdfdad9d8, 0xd3d6d5dc, 0xd7d2d1d0, + 0xebeeede4, 0xefeae9e8, 0xe3e6e5ec, 0xe7e2e1e0, + 0xfbfefdf4, 0xfffaf9f8, 0xf3f6f5fc, 0xf7f2f1f0, + 0x4b4e4d44, 0x4f4a4948, 0x4346454c, 0x47424140, + 0x9b9e9d94, 0x9f9a9998, 0x9396959c, 0x97929190, + 0xabaeada4, 0xafaaa9a8, 0xa3a6a5ac, 0xa7a2a1a0, + 0xbbbebdb4, 0xbfbab9b8, 0xb3b6b5bc, 0xb7b2b1b0, + 0x8b8e8d84, 0x8f8a8988, 0x8386858c, 0x87828180, + 0x5b5e5d54, 0x5f5a5958, 0x5356555c, 0x57525150, + 0x6b6e6d64, 0x6f6a6968, 0x6366656c, 0x67626160, + 0x7b7e7d74, 0x7f7a7978, 0x7376757c, 0x77727170, + 0x341424c4, 0x3e1e2ece, 0x3d1d2dcd, 0x3b1b2bcb, + 0xb494a444, 0xbe9eae4e, 0xbd9dad4d, 0xbb9bab4b, + 0xf4d4e404, 0xfedeee0e, 0xfddded0d, 0xfbdbeb0b, + 0x74546484, 0x7e5e6e8e, 0x7d5d6d8d, 0x7b5b6b8b, + 0x3c1c2ccc, 0x361626c6, 0x351525c5, 0x331323c3, + 0xbc9cac4c, 0xb696a646, 0xb595a545, 0xb393a343, + 0xfcdcec0c, 0xf6d6e606, 0xf5d5e505, 0xf3d3e303, + 0x7c5c6c8c, 0x76566686, 0x75556585, 0x73536383, + 0x381828c8, 0x3a1a2aca, 0x391929c9, 0x3f1f2fcf, + 0xb898a848, 0xba9aaa4a, 0xb999a949, 0xbf9faf4f, + 0xf8d8e808, 0xfadaea0a, 0xf9d9e909, 0xffdfef0f, + 0x78586888, 0x7a5a6a8a, 0x79596989, 0x7f5f6f8f, + 0x301020c0, 0x321222c2, 0x311121c1, 0x371727c7, + 0xb090a040, 0xb292a242, 0xb191a141, 0xb797a747, + 0xf0d0e000, 0xf2d2e202, 0xf1d1e101, 0xf7d7e707, + 0x70506080, 0x72526282, 0x71516181, 0x77576787, + 0x05040100, 0x15141110, 0x25242120, 0x35343130, + 0x85848180, 0x95949190, 0xa5a4a1a0, 0xb5b4b1b0, + 0xc0408000, 0xe060a020, 0xd0509010, 0xf070b030, + 0xc8488808, 0xe868a828, 0xd8589818, 0xf878b838, + 0xc4448404, 0xe464a424, 0xd4549414, 0xf474b434, + 0xcc4c8c0c, 0xec6cac2c, 0xdc5c9c1c, 0xfc7cbc3c, + 0xc2428202, 0xe262a222, 0xd2529212, 0xf272b232, + 0xca4a8a0a, 0xea6aaa2a, 0xda5a9a1a, 0xfa7aba3a, + 0xc6468606, 0xe666a626, 0xd6569616, 0xf676b636, + 0xce4e8e0e, 0xee6eae2e, 0xde5e9e1e, 0xfe7ebe3e, + 0xc1418101, 0xe161a121, 0xd1519111, 0xf171b131, + 0xc9498909, 0xe969a929, 0xd9599919, 0xf979b939, + 0xc5458505, 0xe565a525, 0xd5559515, 0xf575b535, + 0xcd4d8d0d, 0xed6dad2d, 0xdd5d9d1d, 0xfd7dbd3d, + 0xc3438303, 0xe363a323, 0xd3539313, 0xf373b333, + 0xcb4b8b0b, 0xeb6bab2b, 0xdb5b9b1b, 0xfb7bbb3b, + 0xc7478707, 0xe767a727, 0xd7579717, 0xf777b737, + 0xcf4f8f0f, 0xef6faf2f, 0xdf5f9f1f, 0xff7fbf3f, + 0x1045a3e2, 0x000000f4, 0x263b7333, 0x766b2363, + 0x2b367e3e, 0x7b662e6e, 0x06db93d3, 0x964b0343, + 0x0bd69ede, 0x9b460e4e, 0x825f1757, 0x12cf87c7, + 0x8f521a5a, 0x1fc28aca, 0x00d199d9, 0x90410949, + 0x01d098d8, 0x91400848, 0x24357d3d, 0x74652d6d, + 0x25347c3c, 0x75642c6c, 0x04d59ddd, 0x94450d4d, + 0x05d49cdc, 0x95440c4c, 0x80511959, 0x10c189c9, + 0x81501858, 0x11c088c8, 0x02df97d7, 0x924f0747, + 0x0fd29ada, 0x9f420a4a, 0x865b1353, 0x16cb83c3, + 0x8b561e5e, 0x1bc68ece, 0xa6bbf3b3, 0xf6eba3e3, + 0xabb6febe, 0xfbe6aeee, 0x223f7737, 0x726f2767, + 0x2f327a3a, 0x7f622a6a, 0xa0b1f9b9, 0xf0e1a9e9, + 0xa1b0f8b8, 0xf1e0a8e8, 0x84551d5d, 0x14c58dcd, + 0x85541c5c, 0x15c48ccc, 0xa4b5fdbd, 0xf4e5aded, + 0xa5b4fcbc, 0xf5e4acec, 0x20317939, 0x70612969, + 0x21307838, 0x71602868, 0xa2bff7b7, 0xf2efa7e7, + 0xafb2faba, 0xffe2aaea, 0x00000000, 0x00000000, +}; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/luxsonor.c linux.19rc3-ac4/drivers/media/video/luxsonor.c --- linux.19rc3/drivers/media/video/luxsonor.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/luxsonor.c 2002-07-29 13:58:41.000000000 +0100 @@ -0,0 +1,2123 @@ +/* + * Luxsonor LS220/LS240 series DVD/Mpeg card drivers + * + * (c) Copyright 2002 Red Hat + * + * 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 + * + * Made possible by Luxsonor's rather nice gesture of publishing their + * windows code to allow people to write new drivers based on it. + * + * The firmware is (c) Copyright Luxsonor and a seperate program run + * on the dsp not part of Linux itself. + * + * Note: the hardware css is not supported as Luxsonor decided not to + * document it even though the chip can do all the work. The citizens + * of free countries will need to use software decryption to play such + * films via the card. US citizens should simply report to the district + * attorney for termination. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* + * Firmware modules + */ + +#include "ls220/ac3.h" +#include "ls220/ac3_240.h" +#include "ls220/ac3i2s.h" +#include "ls220/ac3i2s_240.h" + +#include "ls220/mpg.h" +#include "ls220/mpg_240.h" +#include "ls220/mpgi2s.h" +#include "ls220/mpgi2s_240.h" + +#include "ls220/pcm.h" +#include "ls220/pcm_240.h" +#include "ls220/pcmi2s.h" +#include "ls220/pcmi2s_240.h" + +/* + * Board types + */ + +#define LS220C 0 +#define LS220D 1 +#define LS240 2 + +static char *lux_names[3] = { "LS220C", "LS220D", "LS240" }; + +/* + * TV encoder types + */ + +#define BT865 0 +#define BT864 1 +#define SAA7120 2 +#define SAA7121 3 +#define AD7175 4 +#define AD7176 5 +#define CS4953 6 +#define CS4952 7 +#define HS8171 8 +#define HS8170 9 + +static char *lux_tv_names[10] = { + "BT865", "BT864", "SAA7120", "SAA7121", "AD7175", + "AD7176", "CS4953", "CS4952", "HS8171", "HS8170" +}; + +/* + * EEPROM bytes + */ + +#define EPROM_REGION 0x4 +#define EPROM_REGION_COUNT 0x5 +#define EPROM_PARENTAL 0x6 +#define EPROM_BOARDTYPE 0x7 +#define EPROM_CLOCKTYPE 0x8 +#define EPROM_I2S 0x9 +#define EPROM_SPDIF_CH 0xa +#define EPROM_SPDIF_ONOFF 0xb +#define EPROM_TVOUT 0xc +#define EPROM_LEFT_CH_POL 0xf + +/* + * Registers + */ + +/* -- for field lock use -- */ +#define CHANGE_MPGVID_CONTROL +#define CHANGE_REG274 +#define DO_NOT_TOUCH_REG324 + + +#define LS220_DRAM_BASE 0x200000L +#define LS240_DRAM_BASE 0x400000L + +#define DRAM_BASE(dev) ((dev)->dram_base) + +#define VID_FIFO_OFF 0x1a3000L +#define VID_FIFO_LEN 0x3e000L +#define PTS_FIFO_OFF 0x1a2800L +#define PTS_FIFO_LEN 0x800L +#define SUB_FIFO_OFF 0x1e2000L +#define OSD_FIFO_OFF 0x1e1000L +#define OSD_FIFO_LEN 0x1000L +#define LS220_VID_FIFO(dev) (dev->dram_base+VID_FIFO_OFF) + +#define DSPMEM_BASE(dev) (dev->dram_base+0x1f0000L) +#define DSPPROG_BASE(dev) (DSPMEM_BASE(dev)-dev->dram_base) +#define DSPPROG_OFF 0x1800L +#define DSPPROG_SIZE 0x6000L + + +#define AUD_FIFO_LEN 0x2000L +#define AUD_FIFO_OFF 0x1fc000L +#define AUD_PTS_LEN 0x400L +#define AUD_PTS_OFF 0x1ffa00L + +/* Subpict definition */ +#define FIFO_SIZE 8 /* PTS FIFO entry count */ +#define HIGH_FIFO 32 /* HighLight Fifo size */ +#define SCRM_FIFO 0x800 /* Scramble buffer size */ +#define SPBLOCK ( 0xE000 - HIGH_FIFO - SCRM_FIFO ) /* 56K - 32 bytes - 2k */ +#define SubBLOCK 0xE00 /* PTS + DCI = 3.5K */ +#define DCIBLOCK ( SubBLOCK - 8*FIFO_SIZE ) +#define PxdBLOCK ( SPBLOCK - SubBLOCK ) +#define FStart 0x20 /* PTS FIFO Start Address */ + +#define SUBBASE(dev) ( DRAM_BASE(dev) + SUB_FIFO_OFF ) + +#define LS220_DSP_REG 0x100L +#define LS220_MPG_REG 0x180L +#define LS220_SYNC_REG 0x200L +#define LS220_PCM_REG 0x280L +#define LS220_VID_REG 0x300L + +/* SYNC REGS */ +#define SYNC_AUD_CONTROL (LS220_SYNC_REG+0x00) +#define SYNC_VID_CONTROL (LS220_SYNC_REG+0x04) +#define SYNC_WAIT_LINE (LS220_SYNC_REG+0x0c) +#define SYNC_FRAME_PERIOD (LS220_SYNC_REG+0x10) +#define SYNC_STC (LS220_SYNC_REG+0x18) +#define PTS_FIFO_START (LS220_SYNC_REG+0x20) +#define PTS_FIFO_END (LS220_SYNC_REG+0x24) +#define PTS_FIFO_WRITE (LS220_SYNC_REG+0x28) +#define PTS_FIFO_READ (LS220_SYNC_REG+0x2c) +#define SYNC_VIDEO_PTS (LS220_SYNC_REG+0x50) +#define SYNC_INT_CTRL (LS220_SYNC_REG+0x74) +#define SYNC_INT_FORCE (LS220_SYNC_REG+0x78) + +/* MPEG VIDEO REGS */ +#define MPGVID_CONTROL (LS220_MPG_REG+0x0) +#define MPGVID_SETUP (LS220_MPG_REG+0x4) +#define MPGVID_FIFO_START (LS220_MPG_REG+0x8) +#define MPGVID_FIFO_END (LS220_MPG_REG+0xc) +#define MPGVID_FIFO_POS (LS220_MPG_REG+0x10) +#define MPGVID_FIFO_FORCE (LS220_MPG_REG+0x14) +#define MPGVID_FIFO_ADDBLOCK (LS220_MPG_REG+0x18) +#define MPGVID_FIFO_BYTES (LS220_MPG_REG+0x1c) +#define MPGVID_FIFO_INTLEVEL (LS220_MPG_REG+0x20) +#define MPGVID_TOTAL_BYTES (LS220_MPG_REG+0x24) +#define MPGVID_ERROR (LS220_MPG_REG+0x28) +#define MPGVID_MB_WIDTH (LS220_MPG_REG+0x2c) +#define MPGVID_MB_HEIGHT (LS220_MPG_REG+0x30) +#define MPGVID_DEBUG1 (LS220_MPG_REG+0x38) +#define MPGVID_DEBUG2 (LS220_MPG_REG+0x3c) + +/* VID_REG */ +#define VIDP_GPIO (LS220_VID_REG+0x50) + +/* PCM REG */ +#define PCM_FREQ_CONTROL (LS220_PCM_REG+0x0) +#define PCM_OUTPUT_CONTROL (LS220_PCM_REG+0x4) +#define PCM_FIFO_START (LS220_PCM_REG+0x8) +#define PCM_FIFO_END (LS220_PCM_REG+0xc) + +/* DSP REGS */ +#define DSP_CODE_ADDR (LS220_DSP_REG+0x0) + +/* DSP INTERAL MEMORY */ + +#define DSPMEM_DRV_RET(dev) (DSPMEM_BASE(dev)+0xfef0L) +#define DSPMEM_ACC(dev) (DSPMEM_BASE(dev)+0xfef5L) +#define DSPMEM_ACC4(dev) (DSPMEM_BASE(dev)+0xfef4L) +#define DSPMEM_CHAL_KEY(dev) (DSPMEM_BASE(dev)+0xfef6L) + +#define DSPMEM_LOCK(dev) (DSPMEM_BASE(dev)+0xff78L) + +#define DSPMEM_AUDIO_CONF(dev) (DSPMEM_BASE(dev)+0xff7cL) +#define DSPMEM_AC3_CONF(dev) (DSPMEM_BASE(dev)+0xff80L) + +#define DSPMEM_KARAOKE(dev) (DSPMEM_BASE(dev)+0xff8c) + +#define DSPMEM_INT_MASK(dev) (DSPMEM_BASE(dev)+0xffa4L) +#define DSPMEM_INT_STATUS(dev) (DSPMEM_BASE(dev)+0xffa8L) +#define DSPMEM_INT_THREHOLD(dev) (DSPMEM_BASE(dev)+0xffacL) + +#define DSPMEM_VOLUME_LEVEL(dev) (DSPMEM_BASE(dev)+0xffb0L) + +#define DSPMEM_PTS_START(dev) (DSPMEM_BASE(dev)+0xffd0L) +#define DSPMEM_PTS_END(dev) (DSPMEM_BASE(dev)+0xffd4L) +#define DSPMEM_PTS_WR(dev) (DSPMEM_BASE(dev)+0xffd8L) +#define DSPMEM_PTS_RD(dev) (DSPMEM_BASE(dev)+0xffdcL) + +#define DSPMEM_FIFO_START(dev) (DSPMEM_BASE(dev)+0xffe0L) +#define DSPMEM_FIFO_END(dev) (DSPMEM_BASE(dev)+0xffe4L) +#define DSPMEM_FIFO_WR(dev) (DSPMEM_BASE(dev)+0xffe8L) +#define DSPMEM_FIFO_RD(dev) (DSPMEM_BASE(dev)+0xffecL) + + +#define DSPMEM_CMD(dev) (DSPMEM_BASE(dev)+0xfff0L) +#define DSPMEM_STATUS(dev) (DSPMEM_BASE(dev)+0xfff8L) + + +#define DSP_CMD_NOP 0x00 +#define DSP_CMD_AC3 0x80 +#define DSP_CMD_MPEG1 0x81 +#define DSP_CMD_MPEG2 0x82 +#define DSP_CMD_PCM 0x83 + +#define DSP_CMD_PLAY 0x84 +#define DSP_CMD_STOPF 0x85 +#define DSP_CMD_PAUSE 0x86 +#define DSP_CMD_MUTE 0x87 +#define DSP_CMD_UNMUTE 0x88 +#define DSP_CMD_CONFIG 0x89 +#define DSP_CMD_VER 0x8a +#define DSP_CMD_STATUS 0x8b + +#define DSP_CMD_VOLUME 0x8c +#define DSP_CMD_INITDONE 0x8d + +#define DSP_CMD_FRAME 0xa0 +#define DSP_CMD_CLRAUTH 0xa1 +#define DSP_CMD_DECAUTH 0xa2 +#define DSP_CMD_DRVAUTH 0xa3 +#define DSP_CMD_KEYSHARE 0xa4 +#define DSP_CMD_DISCKEY 0xa5 +#define DSP_CMD_TITLEKEY 0xa6 + + +#define I2C_CLIENTS_MAX 16 + + +struct ls220_dev +{ + struct ls220_dev *next; + struct pci_dev *pdev; + void *membase; + int type; + u8 eprom[16]; + int has_eprom; + int tvencoder; + + u32 dram_base; + + u32 audio_fifo_off; + u32 audio_fifo_len; + + u32 audio_m_vol; + u32 audio_m_adj; + int audio_mute; + int audio_ac3; + + u32 audio_pts; + u32 audio_ptscount; + u32 audio_m_total; + u32 audio_speed; + + int audio_spdif; + + int spdif_first_play; + int stop_read; + + /* Buffer management */ + u8 audio_buffer[2048]; + u8 *audio_p; + u8 *audio_cp; + u16 audio_dlen; + + int video_mode; +#define VIDEO_PAL 0 +#define VIDEO_NTSC 1 + int video_mpeg1; + int video_hw_wrap; + int video_letter; + int video_zoomin; + int video_speed; + int video_pts; + int video_total; + int video_remainder; + int video_wptr; + int vga_mode; + + struct i2c_adapter i2c_adap; + struct i2c_algo_bit_data i2c_algo; + struct i2c_client i2c_client; + int i2c_rc; + struct i2c_client *i2c_clients[I2C_CLIENTS_MAX]; +}; + +/* FIXME - spinlock the list */ +static struct ls220_dev *ls_devs; + +static int old = 1; /* Old v new style board */ + +/* + * Hardware access + */ + +static void ls220_dv_write(struct ls220_dev *dev, u32 offset, u32 data) +{ + writel(data, dev->membase+offset); +} + +static u32 ls220_dv_read(struct ls220_dev *dev, u32 offset) +{ + return readl(dev->membase+offset); +} + +static void ls220_write_dram(struct ls220_dev *dev, u32 offset, u32 data) +{ + writel(data, dev->membase+offset); +} + +static u32 ls220_read_dram(struct ls220_dev *dev, u32 offset) +{ + return readl(dev->membase+offset); +} + +static void ls220_memsetl(struct ls220_dev *dev, u32 offset, u32 fill, int len) +{ + int i; + for(i=0;idstoff, f->length); + if(f->dstoff) + { + for(i=0; ilength; i++) + { + ls220_write_dram(dev, DRAM_BASE(dev) + f->dstoff + 4 * i, f->firmware[i]); + if(ls220_read_dram(dev, DRAM_BASE(dev) + f->dstoff + 4 * i)!=f->firmware[i]) + { + printk("luxsonor: firmware upload error.\n"); + printk("%d: Got 0x%X want 0x%X\n", + i, ls220_read_dram(dev, DRAM_BASE(dev) + f->dstoff + 4 * i), + f->firmware[i]); + return; + } + } + } +} + +static void load_firmware_set(struct ls220_dev *dev, int card, int mode) +{ + int i; + for(i=0;i<3;i++) + load_firmware_block(dev, &firmware[card][mode][i]); +} + +static void ls220_load_firmware(struct ls220_dev *dev, int format) +{ + int card = 0; + if(dev->type==LS240) + card = 1; + + if(dev->eprom[EPROM_I2S]==0x03) + format += 3; /* Second table for i2s */ + + format--; /* Numbered 1 to 3 */ + + load_firmware_set(dev, card, format); +} + +/* + * LS220 I2C bus implementation + */ + +static void ls220_i2c_init(struct ls220_dev *dev) +{ + if(!dev->eprom[EPROM_BOARDTYPE]) + ls220_dv_write(dev, 0x350, 0x4f70100); + else + ls220_dv_write(dev, 0x350, 0x4f70f00); + ls220_dv_write(dev, 0x364, 0xff031f); +} + +static void ls220_bit_setscl(void *data, int state) +{ + struct ls220_dev *dev = data; + u32 reg; + + reg = ls220_dv_read(dev, 0x350); + reg &= 0x7FFFFF; + if(state == 0) + reg |= 0x00800000; + ls220_dv_write(dev, 0x350, reg); +// printk("SCL = %d\n", state); + ls220_dv_read(dev, 0x350); +} + +static void ls220_bit_setsda(void *data, int state) +{ + struct ls220_dev *dev = data; + u32 reg; + + reg = ls220_dv_read(dev, 0x350); + reg &= 0xBFFFFF; + if(state == 0) + reg |= 0x00400000; + ls220_dv_write(dev, 0x350, reg); +// printk("SDA = %d\n", state); + ls220_dv_read(dev, 0x350); +} + +static int ls220_bit_getsda(void *data) +{ + struct ls220_dev *dev = data; + if(ls220_dv_read(dev, 0x350)&0x40) + { +// printk("get SDA=0\n"); + return 0; + } +// printk("get SDA=1\n"); + return 1; +} + +static void ls220_i2c_use(struct i2c_adapter *adap) +{ + MOD_INC_USE_COUNT; +} + +static void ls220_i2c_unuse(struct i2c_adapter *adap) +{ + MOD_DEC_USE_COUNT; +} + +static int ls220_attach_inform(struct i2c_client *client) +{ + struct ls220_dev *dev = client->adapter->data; + return 0; +} + +static int ls220_detach_inform(struct i2c_client *client) +{ + struct ls220_dev *dev = client->adapter->data; + return 0; +} + +static int ls220_call_i2c_clients(struct ls220_dev *dev, unsigned int cmd, void *arg) +{ + return 0; +} + +/* + * Structures to define our hardware with the i2c core code. It + * will do all the i2c bus management and locking for us. + */ + +static struct i2c_algo_bit_data ls220_i2c_algo_template = { + setsda: ls220_bit_setsda, + setscl: ls220_bit_setscl, + getsda: ls220_bit_getsda, + udelay: 30, + mdelay: 10, + timeout: 200, +}; + +static struct i2c_adapter ls220_i2c_adap_template = { + name: "ls220", + id: I2C_HW_B_BT848, /* FIXME */ + inc_use: ls220_i2c_use, + dec_use: ls220_i2c_unuse, + client_register: ls220_attach_inform, + client_unregister: ls220_detach_inform, +}; + +static struct i2c_client ls220_i2c_client_template = { + name: "ls220 internal", + id: -1, +}; + +/* + * Register our i2c bus + */ + +static int ls220_i2c_register(struct ls220_dev *dev) +{ + /* Copy template */ + memcpy(&dev->i2c_adap, &ls220_i2c_adap_template, sizeof(struct i2c_adapter)); + memcpy(&dev->i2c_algo, &ls220_i2c_algo_template, sizeof(struct i2c_algo_bit_data)); + memcpy(&dev->i2c_client, &ls220_i2c_client_template, sizeof(struct i2c_client)); + /* Device backlinks */ + dev->i2c_algo.data = dev; + dev->i2c_adap.data = dev; + /* Fix up links */ + dev->i2c_adap.algo_data = &dev->i2c_algo; + dev->i2c_client.adapter = &dev->i2c_adap; + /* Set up */ + ls220_bit_setscl(dev, 1); + ls220_bit_setsda(dev, 1); + dev->i2c_rc = i2c_bit_add_bus(&dev->i2c_adap); + return dev->i2c_rc; +} + +/* + * I2C read interfaces + */ + +static int ls220_new_i2c_read(struct ls220_dev *dev, u8 addr) +{ + u8 buffer; + + if(dev->i2c_rc == -1) + BUG(); + printk("i2c recv from 0x%02X\n", addr); + + dev->i2c_client.addr = addr>>1; + if(i2c_master_recv(&dev->i2c_client, &buffer, 1)) + { + printk("i2c - read error.\n"); + return -EIO; + } + printk("Received %d\n", buffer); + return buffer; +} + +static int ls220_new_i2c_probe(struct ls220_dev *dev, u8 addr) +{ + u8 buffer; + int err; + + if(dev->i2c_rc == -1) + BUG(); + printk("i2c probe for 0x%02X\n", addr); + + dev->i2c_client.addr = addr>>1; + if((err=i2c_master_send(&dev->i2c_client, &buffer, 0))) + { + printk(" - probe failed (%d).\n", err); + return 0; + } + printk(" - found.\n"); + return 1; +} + +/*=================----------------*/ + +/* + * Old built in i2c code - this is here until I find why the generic + * kernel code won't play + */ + +static void iic_delay(struct ls220_dev *dev) +{ + udelay(30); +} + +static void iic_startcode(struct ls220_dev *dev) +{ + u32 tmp; + + tmp = ls220_dv_read(dev, 0x350) & 0x3fffffL; + ls220_dv_write(dev, 0x350, tmp); // both = 1 + iic_delay(dev); + + ls220_dv_write(dev, 0x350, tmp | 0x400000L); // SDA = 0 + + iic_delay(dev); + + ls220_dv_write(dev, 0x350, tmp | 0xc00000L); // SCL = 0 + iic_delay(dev); +} + +////////////////////////////////////////////////////////////////////////// + +static void iic_dataxfer(struct ls220_dev *dev, u8 val) +{ + u32 tmp; + u8 data; + int i; + + data = ~val; + for (i = 0; i < 8; i++) { + tmp = ls220_dv_read(dev, 0x350) & 0xbfffffL; + tmp |= (u32) ((data >> (7 - i)) & 0x1) << 22; // set SDA + ls220_dv_write(dev, 0x350, tmp); + iic_delay(dev); + tmp = ls220_dv_read(dev, 0x350); + ls220_dv_write(dev, 0x350, tmp & 0x7fffffL); // set SCL = 1 + iic_delay(dev); + ls220_dv_write(dev, 0x350, tmp | 0x800000L); // set SCL = 0 + iic_delay(dev); + } +} + +////////////////////////////////////////////////////////////////////////// + +static int iic_ack(struct ls220_dev *dev) +{ + u32 tmp, ack; + + tmp = ls220_dv_read(dev, 0x350); + ls220_dv_write(dev, 0x350, tmp & 0xbfffffL); // disable SDA = 1 + iic_delay(dev); + ack = ls220_dv_read(dev, 0x350) & 0x40; + ls220_dv_write(dev, 0x350, tmp & 0x3fffffL); // SCL = 1 + iic_delay(dev); + tmp = ls220_dv_read(dev, 0x350); + ls220_dv_write(dev, 0x350, tmp | 0x800000L); // set SCL = 0 + iic_delay(dev); + + if (!ack) + return 1; + else + return 0; +} + +////////////////////////////////////////////////////////////////////////// + +static void iic_endcode(struct ls220_dev *dev) +{ + u32 tmp; + + tmp = ls220_dv_read(dev, 0x350); + ls220_dv_write(dev, 0x350, tmp | 0x400000L); // SDA = 0 + iic_delay(dev); + tmp = ls220_dv_read(dev, 0x350); + ls220_dv_write(dev, 0x350, tmp & 0x7fffffL); // set SCL = 1 + iic_delay(dev); + ls220_dv_write(dev, 0x350, tmp & 0x3fffffL); // SDA = 1 + iic_delay(dev); +} + +////////////////////////////////////////////////////////////////////////// + +static u8 iic_dataget(struct ls220_dev *dev) +{ + u8 val, i; + u32 tmp; + + val = 0; + for (i = 0; i < 8; i++) { + iic_delay(dev); + tmp = ls220_dv_read(dev, 0x350); + val <<= 1; + if (tmp & 0x40) + val = val | 0x1; + + tmp = tmp & 0x3fffffL; + ls220_dv_write(dev, 0x350, tmp); // set SCL = 1 + iic_delay(dev); + ls220_dv_write(dev, 0x350, tmp | 0x800000L); // set SCL = 0 + iic_delay(dev); + } + + return val; +} + +////////////////////////////////////////////////////////////////////////// + +static void send_ack(struct ls220_dev *dev) +{ + u32 tmp; + + tmp = ls220_dv_read(dev, 0x350); + tmp = tmp | 0xc00000L; // SCLK SDA + ls220_dv_write(dev, 0x350, tmp); // set 00 + iic_delay(dev); + tmp = tmp & 0x7fffffL; + ls220_dv_write(dev, 0x350, tmp); // set 10 + iic_delay(dev); + tmp = tmp | 0xc00000L; + ls220_dv_write(dev, 0x350, tmp); // set 00 + iic_delay(dev); + tmp = tmp & 0xb00000L; + ls220_dv_write(dev, 0x350, tmp); // set 01 + iic_delay(dev); +} + +static int i2c_readeprom(struct ls220_dev *dev, u8 addr, u8 subaddr, u8 num, u8 * pb) +{ + u8 val; + int i; + + iic_startcode(dev); + iic_dataxfer(dev, addr); // write command + iic_ack(dev); + iic_dataxfer(dev, subaddr); + iic_ack(dev); + iic_startcode(dev); + iic_dataxfer(dev, (u8) (addr | 0x1)); // read command + iic_ack(dev); + + for (i = 0; i < num; i++) { + pb[i] = iic_dataget(dev); // load array here + if (i < (num - 1)) + send_ack(dev); + else + iic_endcode(dev); + } + return 1; +} + +static int ls220_i2c_probe(struct ls220_dev *dev, u8 addr) +{ + int val; +// return ls220_new_i2c_probe(dev,addr); + iic_startcode(dev); + iic_dataxfer(dev, addr); // write command + val = iic_ack(dev); + iic_endcode(dev); + return val; +} + +////////////////////////////////////////////////////////////////////////// + +static int read_i2c(struct ls220_dev *dev, u8 addr) +{ + u32 tmp, val; + u32 dwcnt = 0; + + val = 0xff; + tmp = ls220_dv_read(dev, 0x350); + ls220_dv_write(dev, 0x350, tmp | 0x4000000); // set bit 26=1 + iic_delay(dev); + ls220_dv_write(dev, 0x354, addr << 24 | 0x1000000L); + iic_delay(dev); + + while (!(ls220_dv_read(dev, 0x368) & 0x1000)) { + iic_delay(dev); + if (dwcnt++ > 0xffff) + break; + } + val = (u8) ls220_dv_read(dev, 0x36c); + ls220_dv_write(dev, 0x350, tmp); + iic_delay(dev); + return val; +} + +static void send_i2c(struct ls220_dev *dev, u8 addr,u8 subaddr,u8 data) +{ + iic_startcode(dev); + iic_dataxfer(dev, addr); + iic_ack(dev); + iic_dataxfer(dev, subaddr); + iic_ack(dev); + iic_dataxfer(dev, data); + iic_ack(dev); + iic_endcode(dev); +} + +/*=================----------------*/ + +static int ls220_i2c_read(struct ls220_dev *dev, u8 addr) +{ +// return ls220_new_i2c_read(dev, addr); + return read_i2c(dev, addr); +} + + +static int ls220_i2c_write(struct ls220_dev *dev, u8 addr, u8 b1, u8 b2, int both) +{ + u8 buffer[2]; + int bytes = both ? 2 : 1; + if(dev->i2c_rc == -1) + BUG(); + +// printk("Write to i2c client 0x%02X - 0x%2X (0x%02X, %d)\n", addr, b1, b2, both); + dev->i2c_client.addr = addr >> 1; + buffer[0] = b1; + buffer[1] = b2; + if(i2c_master_send(&dev->i2c_client, buffer, bytes)!=bytes) + { + printk(KERN_ERR "i2c write failed.\n"); + return -EIO; + } + return 0; +} + +static int ls220_load_eeprom(struct ls220_dev *dev, u8 addr, u8 subaddr, u8 len, u8 *buf) +{ + int i; + + i2c_readeprom(dev, addr, subaddr, len, buf); +#if 0 + if(ls220_i2c_write(dev, addr, subaddr, -1, 0)<0) + return -EIO; + dev->i2c_client.addr = addr >> 1; + + if(i2c_master_recv(&dev->i2c_client, buf, 16)!=16) + return -EIO; +#endif +#if 0 + printk("luxsonor: EEPROM "); + for(i=0;i<16;i++) + printk("%02X ", buf[i]); + printk("\n"); +#endif + return 0; +} + +static int ls220_detect_tvencoder(struct ls220_dev *dev) +{ + int type; + u8 id; + + if(ls220_i2c_write(dev, 0x00, 0x0f, 0x40, 1)) + printk("i2c_write failed.\n"); + if(ls220_i2c_probe(dev, 0x80)) + { + u8 id; + ls220_load_eeprom(dev, 0x80, 0x3d, 1, &id); + if(id & 0xf0) + type = CS4953; + else + type = CS4952; + return type; + } + if(ls220_i2c_probe(dev, 0x8A)) + { + id = ls220_i2c_read(dev, 0x8A); + if(((id>>5)&7) == 5) + type = BT865; + else + type = BT864; + return type; + } + if(ls220_i2c_probe(dev, 0x42)) + { + ls220_load_eeprom(dev, 0x42, 0x00, 1, &id); + if(id & 0x0f) + type = HS8171; + else + type = HS8170; + return type; + } + if(ls220_i2c_probe(dev, 0x8c)) + return SAA7120; + if(ls220_i2c_probe(dev, 0xd4)) + return AD7175; + if(ls220_i2c_probe(dev, 0x54)) + return AD7176; + printk("No TV encoder ??\n"); + return -ENODEV; +} + +/* + * The LS220 also has some other i2c like stuff on the same + * registers, so we have to watch our locking. + * + * FIXME:pci posting.. + */ + +#define G_EN 0x60000 +#define G_SC 0x0200 +#define G_SD 0x0400 + +static void ls220_gpio_startcode(struct ls220_dev *dev) +{ + u32 r350 = ls220_dv_read(dev, 0x350); + r350&=0xFF000000; + r350|=G_EN; + ls220_dv_write(dev, 0x350, r350|G_SC|G_SD); + udelay(100); + ls220_dv_write(dev, 0x350, r350|G_SC); + udelay(100); + ls220_dv_write(dev, 0x350, r350); + udelay(100); +} + +static void ls220_gpio_endcode(struct ls220_dev *dev) +{ + u32 r350 = ls220_dv_read(dev, 0x350); + r350&=0xFF000000; + r350|=G_EN; + ls220_dv_write(dev, 0x350, r350); + udelay(10); + ls220_dv_write(dev, 0x350, r350|G_SC); + udelay(10); + ls220_dv_write(dev, 0x350, r350); + udelay(10); + ls220_dv_write(dev, 0x350, r350|G_SC); + udelay(10); + ls220_dv_write(dev, 0x350, r350|G_SC|G_SD); +} + +static void ls220_gpio_addr(struct ls220_dev *dev, u8 addr) +{ + int i; + int sd; + u32 r350 = ls220_dv_read(dev, 0x350); + r350&=0xFF000000; + r350|=G_EN; + + for(i=2;i>=0;i--) + { + if(addr&(1<=0;i--) + { + if(data&(1<type == LS240) + { + ls220_dv_write(dev, 0x10, 1); + ls220_dv_write(dev, 0x10, 0x30); + ls220_dv_write(dev, 0x300, 0); + ls220_dv_write(dev, 0x84, 0x04400000); + udelay(10); + ls220_dv_write(dev, 0x80, 0x66a428ec); + udelay(10); + ls220_dv_write(dev, 0x84, 0x80400000); + ls220_dv_write(dev, 0x30, 0x12c5); + } + else + { + ls220_dv_write(dev, 0x10, 1); + ls220_dv_write(dev, 0x10, 0); + } + + ls220_i2c_init(dev); +} + +/* + * LS220 Audio drivers + */ + +static void ls240_dsp_poke(struct ls220_dev *dev) +{ + if(dev->type == LS240) + { + u32 reg = ls220_dv_read(dev, 0x10); + reg &= ~8; + reg |= 0x30; + ls220_dv_write(dev, 0x10,reg); + } +} + +static int ls220_dsp_wait(struct ls220_dev *dev) +{ + int count; + + ls240_dsp_poke(dev); + + ls220_dv_read(dev, 0x250); + + for(count = 0; count < 4096; count ++) + { + if(ls220_read_dram(dev, DSPMEM_CMD(dev)) == 0x100) + return 0; + ls240_dsp_poke(dev); + udelay(50); + } + printk(KERN_ERR "ls220: dsp not responding.\n"); + return -ETIMEDOUT; +} + +static u32 vol_table[16] = { + 0x7fffff, 0x6046c5, 0x4c79a0, 0x3cbf0f, + 0x3040a5, 0x26540e, 0x1e71fe, 0x182efd, + 0x1335ad, 0xf4240, 0xc1ed8, 0x9a0ad, + 0x7a5c3, 0x6131b, 0x4d343, 0x0 +}; + +static void ls220_audio_set_volume(struct ls220_dev *dev, int vol) +{ + if(dev->audio_mute) + return; + if(vol == 0xFF) + { + ls220_write_dram(dev, DSPMEM_CMD(dev), DSP_CMD_MUTE); + ls220_dsp_wait(dev); + vol = 0; + } + else + dev->audio_m_vol = vol; + if(vol > 15 || vol < 0) + BUG(); + ls220_write_dram(dev, DSPMEM_VOLUME_LEVEL(dev), vol_table[15-vol]); + ls220_write_dram(dev, DSPMEM_CMD(dev), DSP_CMD_VOLUME); +} + +static void ls220_dsp_init(struct ls220_dev *dev, int type) +{ + ls220_write_dram(dev, DSPMEM_AC3_CONF(dev) ,0x3400); + + if(type == 1) /* AC3 */ + { + ls220_write_dram(dev, DSPMEM_CMD(dev), DSP_CMD_AC3); + dev->audio_m_adj = 0x600; + } + else if(type == 0) /* PCM */ + { + ls220_write_dram(dev, DSPMEM_CMD(dev), DSP_CMD_PCM); + dev->audio_m_adj = 0x600; + } + else if(type == 2) /* MPG1 */ + { + ls220_write_dram(dev, DSPMEM_CMD(dev), DSP_CMD_MPEG1); + dev->audio_m_adj = 0x0; + } + ls220_dsp_wait(dev); + ls220_audio_set_volume(dev, dev->audio_m_vol); + + dev->audio_fifo_off = ls220_read_dram(dev, DSPMEM_FIFO_START(dev)); + dev->audio_fifo_len = ls220_read_dram(dev, DSPMEM_FIFO_END(dev)) - dev->audio_fifo_off; +// printk("FIFO at 0x%X, size %d.\n", dev->audio_fifo_off, dev->audio_fifo_len); +} + +static void ls220_audio_init(struct ls220_dev *dev, int type) +{ + dev->audio_mute = 0; + dev->audio_m_vol = 15; + dev->audio_ac3 = 1; + dev->audio_m_total = 0; + dev->audio_pts = 0; + dev->audio_ptscount = 0; + dev->audio_speed = 1000; + dev->stop_read = 0; + ls220_dv_write(dev, 0x24, 0); + + if(old) + { + ls220_dv_write(dev, 0x104, 0); + ls220_dv_write(dev, 0x100, 0x7C600); + ls220_dv_write(dev, 0x104, 1); + udelay(200); + ls220_write_dram(dev, DSPMEM_FIFO_WR(dev), AUD_FIFO_OFF); + ls220_write_dram(dev, DSPMEM_FIFO_RD(dev), AUD_FIFO_OFF); + ls220_write_dram(dev, DSPMEM_PTS_WR(dev), AUD_PTS_OFF); + ls220_write_dram(dev, DSPMEM_PTS_RD(dev), AUD_PTS_OFF); + } + ls220_dsp_init(dev, type); + dev->audio_m_total = 0; + dev->audio_pts = 0; + dev->audio_ptscount = 0; + + if(type == 2) /* Mpeg audio */ + dev->audio_ptscount = 1; +} + +static void ls240_audiopcm_enable_tristate(struct ls220_dev *dev) +{ + ls220_dv_write(dev, 0x284, ls220_dv_read(dev, 0x284)|0x200000); +} + +static void ls220_audio_set_info(struct ls220_dev *dev) +{ + u16 clock_chip; /* clock chip defition */ + u16 left_ch; /* left channel polarity */ + u16 pcm_size; /* PCM ( output ) size */ + u16 i2s_pin; /* I2S pin */ + + clock_chip = (u16)dev->eprom[EPROM_CLOCKTYPE]; + left_ch = (u16)dev->eprom[EPROM_LEFT_CH_POL]<<3; + pcm_size = 0; + + if(dev->eprom[EPROM_I2S] == 0x3) + i2s_pin = 0x40; + else + i2s_pin = 0; + + ls220_write_dram(dev, DSPMEM_AUDIO_CONF(dev), i2s_pin|pcm_size|left_ch|clock_chip); +} + +static void ls220_audio_set_spdif(struct ls220_dev *dev, int onoff) +{ + u32 data; + + dev->audio_spdif = onoff; + + data = ls220_read_dram(dev, DSPMEM_AUDIO_CONF(dev)); + data &= 0x7F; + if(onoff) + data |= 0x80; + ls220_write_dram(dev, DSPMEM_AUDIO_CONF(dev), data); +} + +static int ls220_audio_write(struct ls220_dev *dev, const char *buf, int len) +{ + return 0; +} + +static void ls220_play_audio(struct ls220_dev *dev, int speed) +{ + dev->audio_speed = speed; + if(speed == 1000) + { + /* + * Normal speed - engage hardware synchronization + */ + if(dev->type == LS240) + { + ls220_dv_write(dev, 0x280, 0x8); + ls220_dv_write(dev, 0x280, 0x9); + ls220_dv_write(dev, 0x29C, 0x30008235); + ls220_dv_write(dev, 0x200, 0x419); + ls220_dv_write(dev, 0x200, 0x3b); + } + else + { + u32 tmp = ls220_dv_read(dev, SYNC_AUD_CONTROL); + ls220_dv_write(dev, SYNC_AUD_CONTROL, tmp|0x20); + } + ls220_dv_write(dev, DSPMEM_CMD(dev), DSP_CMD_PLAY); + ls220_dsp_wait(dev); + /* Locking needed on 0x350 */ + if(dev->eprom[EPROM_BOARDTYPE] == 3 && !dev->audio_spdif) + ls220_dv_write(dev, 0x350, ls220_dv_read(dev, 0x350)|0x010100); + if(!(dev->eprom[EPROM_SPDIF_CH]&0x02) && dev->audio_spdif && dev->spdif_first_play) + { + dev->spdif_first_play = 0; + ls220_dv_write(dev, DSPMEM_CMD(dev), DSP_CMD_INITDONE); + ls220_dsp_wait(dev); + } + } +} + +static void ls220_audio_set_speed(struct ls220_dev *dev, int speed) +{ + dev->audio_speed = speed; +} + +static void ls220_audio_set_config(struct ls220_dev *dev, int sixchannel) +{ + if(dev->audio_ac3) + { + if(sixchannel && !(dev->eprom[EPROM_SPDIF_CH]&0x1)) + ls220_write_dram(dev, DSPMEM_AC3_CONF(dev), 0x340F); + else + { + switch(sixchannel) + { + case 0: /* Want prologic */ + case 1: /* Board doesnt do 6 */ + case 3: /* Default to prologic */ + ls220_write_dram(dev, DSPMEM_AC3_CONF(dev), 0x3400); + break; + case 2: /* No six channels but use 2 channel scheme */ + ls220_write_dram(dev, DSPMEM_AC3_CONF(dev), 0x3402); + break; + } + } + } + else + { + /* PCM mode */ + if(sixchannel > 1) + ls220_write_dram(dev, DSPMEM_AC3_CONF(dev), sixchannel); + } +} + +static void ls220_audio_set_type(struct ls220_dev *dev, int type) +{ + dev->audio_ac3 = type; +} + + +static void ls220_audio_stop(struct ls220_dev *dev) +{ + dev->stop_read = 0; + ls220_write_dram(dev, DSPMEM_CMD(dev), DSP_CMD_MUTE); + ls220_dsp_wait(dev); + ls220_write_dram(dev, DSPMEM_PTS_WR(dev), AUD_PTS_OFF); + ls220_write_dram(dev, DSPMEM_PTS_RD(dev), AUD_PTS_OFF); + + if(dev->audio_ac3 == 1) + ls220_write_dram(dev, DSPMEM_CMD(dev), DSP_CMD_AC3); + else if(dev->audio_ac3 == 0) + ls220_write_dram(dev, DSPMEM_CMD(dev), DSP_CMD_PCM); + else if(dev->audio_ac3 == 2) + ls220_write_dram(dev, DSPMEM_CMD(dev), DSP_CMD_MPEG1); + ls220_dsp_wait(dev); + ls220_audio_set_volume(dev, dev->audio_m_vol); + + dev->audio_m_total = 0; + dev->audio_pts = 0; + dev->audio_ptscount = 0; + if(dev->audio_ac3 == 2) + dev->audio_ptscount = 1; +} + +static void ls220_audio_mute(struct ls220_dev *dev) +{ + ls220_write_dram(dev, DSPMEM_CMD(dev), DSP_CMD_STOPF); + ls220_dsp_wait(dev); +} + +static void ls220_audio_pause(struct ls220_dev *dev) +{ + ls220_write_dram(dev, DSPMEM_CMD(dev), DSP_CMD_PAUSE); + ls220_dsp_wait(dev); +} + +static void ls220_audio_continue(struct ls220_dev *dev) +{ + ls220_write_dram(dev, DSPMEM_CMD(dev), DSP_CMD_PLAY); + ls220_dsp_wait(dev); +} + +static u32 ls220_audio_report_frame(struct ls220_dev *dev) +{ + ls220_write_dram(dev, DSPMEM_CMD(dev), DSP_CMD_FRAME); + ls220_dsp_wait(dev); + return ls220_read_dram(dev, DSPMEM_STATUS(dev)); +} + +static u32 ls220_audio_report_status(struct ls220_dev *dev) +{ + ls220_write_dram(dev, DSPMEM_CMD(dev), DSP_CMD_STATUS); + ls220_dsp_wait(dev); + return ls220_read_dram(dev, DSPMEM_STATUS(dev)); +} + +static void ls220_audio_onoff(struct ls220_dev *dev, int onoff) +{ + dev->audio_mute = onoff; + if(!dev->audio_mute) + ls220_audio_set_volume(dev, dev->audio_m_vol); + else + { + ls220_write_dram(dev, DSPMEM_VOLUME_LEVEL(dev), vol_table[15]); + ls220_write_dram(dev, DSPMEM_CMD(dev), DSP_CMD_VOLUME); + ls220_dsp_wait(dev); + } +} + +static void ls220_audio_after_seek(struct ls220_dev *dev) +{ + if(old) + { + ls220_write_dram(dev, DSPMEM_FIFO_WR(dev), AUD_FIFO_OFF); + ls220_write_dram(dev, DSPMEM_FIFO_RD(dev), AUD_FIFO_OFF); + } + ls220_write_dram(dev, DSPMEM_FIFO_WR(dev), dev->audio_fifo_off); + ls220_write_dram(dev, DSPMEM_FIFO_RD(dev), dev->audio_fifo_off); + ls220_write_dram(dev, DSPMEM_PTS_WR(dev), AUD_PTS_OFF); + ls220_write_dram(dev, DSPMEM_PTS_RD(dev), AUD_PTS_OFF); +} + +int ls220_audio_write_pts(struct ls220_dev *dev, u32 pts, u16 aoff) +{ + u32 rdptr; + u32 wrptr; + u32 space; + u32 val; + + rdptr = ls220_dv_read(dev, DSPMEM_PTS_RD(dev)); + wrptr = ls220_dv_read(dev, DSPMEM_PTS_WR(dev)); + space = (wrptr > rdptr) ? (AUD_PTS_LEN + rdptr - wrptr) : (rdptr - wrptr); + + if(space < 0x8) + return 0; + + if(dev->type != LS240) + { + if(!dev->audio_pts) + { + val = ls220_dv_read(dev, 0x200); + ls220_dv_write(dev, 0x200, val&0xFBF); /* Audio master */ + } + } + ls220_write_dram(dev, DRAM_BASE(dev)+wrptr, pts); + wrptr+=4; + ls220_write_dram(dev, DRAM_BASE(dev)+wrptr, dev->audio_m_total+aoff); + wrptr+=4; + if(wrptr >= AUD_PTS_OFF+AUD_PTS_LEN) + wrptr -= AUD_PTS_LEN; + ls220_dv_write(dev, DSPMEM_PTS_WR(dev), wrptr); + dev->audio_pts = pts; + return 1; +} + +static void ls220_audio_stop_dsp(struct ls220_dev *dev) +{ + ls220_dv_write(dev, 0x104, 0); + ls220_dv_write(dev, SYNC_INT_CTRL, 0x8000); +} + +static void ls220_audio_enable_dsp(struct ls220_dev *dev) +{ + ls220_dv_write(dev, 0x100, 0x7c600); + ls220_dv_write(dev, 0x104, 0x1); + udelay(100); + if(dev->type == LS240) + ls220_dv_write(dev, SYNC_INT_CTRL, 0x38000001); + else + ls220_dv_write(dev, SYNC_INT_CTRL, 0xE8001); +} + +static void ls220_audio_setuclock(struct ls220_dev *dev, int type) +{ + if(!old) + return; +#if 0 + if(type && dev->eprom[EPROM_CLOCKTYPE]==1) + ls220_write_dram(dev, DSPMEM_UCLOCK(dev), 1); + else + ls220_write_dram(dev, DSPMEM_UCLOCK(dev), 0); +#endif +} + +static void ls220_audio_set_karaoke(struct ls220_dev *dev, int mode) +{ + if(mode < 0 || mode > 3) + BUG(); + /* bit 0 = vocal 1 enable bit 1 = vocal 2 enable */ + ls220_write_dram(dev, DSPMEM_KARAOKE(dev), mode); +} + +static u32 ls220_audio_send_data(struct ls220_dev *dev, u8 *p, u32 len, u16 pts, int scramble, u16 aoff) +{ + if(dev->audio_speed != 1000) + return len; + /* TODO */ + return 0; +} + +static u32 ls220_audio_mpeg_packet(struct ls220_dev *dev, u8 *mbuf, u8 *pp, u32 used) +{ + /* mbuf is a 2K packet, pp is a pes len ptr */ + u8 aid; + u16 pes_len; + u32 curpts = 0; + u8 scramble; + int m_ext = 0; + u16 ext_pes_len = 0; + int m_exthead = 0; + + memcpy(dev->audio_buffer, mbuf, 2048); + dev->audio_p = dev->audio_buffer + (pp - mbuf); + + aid = dev->audio_p[-1]&7; + + if(dev->stop_read) + { + dev->audio_p+=2; + scramble = dev->audio_p[0]&0x30; + pes_len = dev->audio_p[2]; + dev->audio_p+=3; + if((dev->audio_p[0] & 0xf0)==0x20 && pes_len > 0) /* Found PTS */ + { + curpts = dev->audio_p[1]<<8 | dev->audio_p[2]; + curpts = (curpts << 14) | ((dev->audio_p[3]<<8 | dev->audio_p[4])>>2); + curpts |= (dev->audio_p[0] & 0xE) << 28; + } + dev->audio_p += pes_len; + goto tryit; + } + if((dev->audio_p[-1]&0xF0) == 0xD0) + { + m_exthead = 1; + m_ext = 1; + } + dev->audio_dlen = dev->audio_p[0]<<8 | dev->audio_p[1]; + dev->audio_p+=2; + dev->audio_cp = dev->audio_p+dev->audio_dlen; /* Find A_PKT end */ + if (dev->audio_cp < dev->audio_buffer + 0x0800) + { + if((((dev->audio_cp[0]<<8) | dev->audio_cp[1])&0xFFFFFFF0) != 0x01c0) + m_ext = 1; + } + scramble = dev->audio_p[0]&0x30; + pes_len = dev->audio_p[2]; + dev->audio_p+=3; + + dev->audio_dlen = dev->audio_dlen -3 - pes_len; + + if(((*dev->audio_p & 0xf0) == 0x20) && (pes_len > 0)) + { + curpts = dev->audio_p[1]<<8|dev->audio_p[2]; + curpts <<= 14; + curpts |= (dev->audio_p[3]<< 8 | dev->audio_p[4])>>2; + curpts |= (dev->audio_p[0]&0x0E)<<28; + } + + dev->audio_p+=pes_len; + + if(m_exthead) + { + dev->audio_cp = dev->audio_p; + dev->audio_dlen = 0; + curpts = 0; + } + + if(m_ext) + { + dev->audio_p = dev->audio_cp; + while(dev->audio_p < dev->audio_buffer + 0x800) + { + while(((dev->audio_p[0]<<8 | dev->audio_p[1]) & 0xFFFF00) != 0x100) + { + if(dev->audio_p++ >= dev->audio_buffer + 0x800) + goto tryit; + } + + if((dev->audio_p[3]&0xF0) != 0xC0) + { + dev->audio_p += 4; + ext_pes_len = dev->audio_p[0]<<8 | dev->audio_p[1]; + dev->audio_p += ext_pes_len; + continue; + } + if((((dev->audio_p[0]<<24)|(dev->audio_p[1]<<1)|(dev->audio_p[2]<<8)|dev->audio_p[3]) & 0xFFFFFFF0) != 0x1c0) + { + dev->audio_p+=4; + ext_pes_len = dev->audio_p[0] << 8 | dev->audio_p[1]; + dev->audio_p+=2; + pes_len = dev->audio_p[2]; + dev->audio_p+=3; + ext_pes_len = ext_pes_len - 3 - pes_len; + + if(m_exthead) + { + if((dev->audio_p[0]&0xF0) == 0x20 && pes_len > 0) + { + curpts = dev->audio_p[1]<<8|dev->audio_p[2]; + curpts <<= 14; + curpts |= dev->audio_p[3]<<8|dev->audio_p[4]; + curpts |= (dev->audio_p[0]&0xE)<<28; + } + m_exthead = 0; + } + + dev->audio_p += pes_len; + + memmove(dev->audio_cp, dev->audio_p, ext_pes_len); + dev->audio_dlen += ext_pes_len; + dev->audio_cp += ext_pes_len; + dev->audio_p += ext_pes_len; + } + } + } +tryit: + if(dev->audio_dlen == 0) + { + dev->stop_read = 0; + return used; + } + if(ls220_audio_send_data(dev, dev->audio_p, dev->audio_dlen, curpts, scramble, 0)) + { + dev->stop_read = 0; + return used; + } + else + { + dev->stop_read = 1; + return 0; + } +} + +/* + * Video side drivers + */ + +static void ls240_zoomvideo_enable_tristate(struct ls220_dev *dev) +{ + ls220_dv_write(dev, 0x37c, ls220_dv_read(dev, 0x37c)&0xe0ffffff); +} + +static void ls220_video_set_vpm(struct ls220_dev *dev, int type) +{ + /* TODO */ +} + +static void ls220_configure_tvout(struct ls220_dev *dev, int tvmode) +{ + static u8 bt865_pal[]={ + 0x00, 0x60, 0x7e, 0xfe, 0x54, 0x01, 0xff, 0x01, + 0xd5, 0x73, 0xa8, 0x22, 0x55, 0xa4, 0x05, 0x55, + 0x27, 0x40 + }; + int i; + + switch(dev->tvencoder) + { + case BT865: + for(i=0;i<18;i++) + send_i2c(dev, 0x8A, 0xD8+2*i, bt865_pal[i]); + break; + default: + printk("Sorry only PAL BT865 is supported right now.\n"); + } +} + +/* + * Video gamma table from Luxsonor + */ + +static u32 gamma[][8] = { + {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}, + {0x0,0x0,0x1000000,0x05040302,0x07070606,0x0b0a0908,0x0b0c0b0b,0xe0e0d}, + {0x0,0x03020200,0x07060505,0x0a090808,0x0b0b0b0a,0x0d0d0c0c,0x0e0e0e0d,0x010f0f0f}, + {0x03000000,0x09080706,0x0c0b0b0b,0x0e0e0d0d,0x0f0f0f0f,0x10100f0f,0x1010100f,0x010f1010}, + {0x08050100,0x0e0d0d0b,0x11101010,0x12121112,0x12121212,0x12121212,0x11111111,0x020f1011}, + {0x0d0a0500,0x13121210,0x15151515,0x16161616,0x15151616,0x14141415,0x12131313,0x020f1112}, + {0x120e0900,0x18171615,0x19191919,0x1919191a,0x17181919,0x16161617,0x13141415,0x020f1212}, + {0x16130d00,0x1c1c1b19,0x1d1d1d1e,0x1d1d1d1e,0x1a1b1c1c,0x1818191a,0x14151616,0x020f1213}, + {0x1b171000,0x21201f1e,0x21212122,0x20202021,0x1c1d1e1f,0x191a1a1c,0x15161718,0x020f1314}, + {0x1f1b1400,0x24242322,0x24252525,0x22232324,0x1e1f2121,0x1b1c1c1e,0x16171819,0x020f1315} +}; + +/* + * U chroma values from Luxsonor + */ + +static u32 chroma_U[][7] = { + {0x2,0x0,0x0,0x0,0x0,0x0,0x0}, + {0x3f3f3f02,0x3f3f3f3f,0x0,0x0,0x0,0x01010100,0x02020201}, + {0x3e3d3d02,0x3e3e3e3e,0x3f3f3f3f,0x0,0x01000000,0x03020201,0x04040403}, + {0x3c3c3b02,0x3d3d3d3c,0x3f3e3e3e,0x3f3f,0x02010000,0x04040302,0x07060605}, + {0x3b3a3a02,0x3c3c3c3b,0x3e3e3d3d,0x3f3f,0x02010000,0x06050403,0x09080807}, + {0x39393a02,0x3b3b3a3a,0x3e3d3d3c,0x3f3f3e,0x03020100,0x07060504,0x0c0b0a08}, + {0x38373a02,0x3a3a3938,0x3d3c3c3b,0x3f3e3e,0x04020100,0x09080605,0x0e0d0c0a}, + {0x36363a02,0x39393837,0x3d3c3b3a,0x3f3e3d,0x04030100,0x0a090706,0x100f0e0c}, + {0x35343a02,0x38383736,0x3c3b3a39,0x3f3e3d,0x05030100,0x0c0a0807,0x1011100e}, + {0x33323a02,0x37363534,0x3b3a3938,0x3f3e3d3c,0x06040200,0x0e0c0a08,0x10141210} +}; + +/* + * V chroma values from Luxsonor (remember mpeg is YUV) + */ +static u32 chroma_V[][7] = { + {0x023a0202,0x02020202,0x02020202,0x02020202,0x02020202,0x02020202,0x02020202}, + {0x380002,0x0,0x01010101,0x02020101,0x03030202,0x04040303,0x05050404}, + {0x3f3e3e07,0x3f3f,0x01000000,0x02020101,0x04040302,0x06060505,0x08080707}, + {0x3d3c3c0a,0x3f3e3e3d,0x3f,0x02020101,0x06050403,0x09080706,0x0c0b0a0a}, + {0x3b3a3a0a,0x3e3d3c3c,0x3f3e,0x02020100,0x07060503,0x0b0a0908,0x0f0e0d0c}, + {0x39383a0a,0x3d3c3b3a,0x3f3e3d,0x02020100,0x08070603,0x0e0c0b0a,0x1012100f}, + {0x373e3a0a,0x3b3a3938,0x3f3e3d3c,0x03020100,0x0a080604,0x100e0d0b,0x10151312}, + {0x363c3a0a,0x3a393837,0x3f3e3d3b,0x03020000,0x0b090704,0x12100f0d,0x10181614}, + {0x343a3a0a,0x39383635,0x3e3d3c3a,0x03020000,0x0c0a0804,0x1513100e,0x10181917}, + {0x323a3a0a,0x38363533,0x3e3c3b39,0x0302003f,0x0e0b0905,0x17151210,0x10181c1a} +}; + +static void ls220_video_clear_screen(struct ls220_dev *dev) +{ + ls220_dv_write(dev, 0x3D0, 0); /* Wipe OSD */ + if(dev->video_mode == VIDEO_NTSC || dev->video_mpeg1) + { + ls220_memsetl(dev, 0x200000, 0x0, 0x54600); + ls220_memsetl(dev, 0x254600, 0x80808080, 0x2a300); + ls220_memsetl(dev, 0x27e900, 0x0, 0x54600); + ls220_memsetl(dev, 0x2d2f00, 0x80808080, 0x2a300); + ls220_memsetl(dev, 0x2fd200, 0x0, 0x54600); + ls220_memsetl(dev, 0x351800, 0x80808080, 0x2a300); + } + else + { + ls220_memsetl(dev, 0x200000, 0x0, 0x65400); + ls220_memsetl(dev, 0x265400, 0x80808080, 0x32a00); + ls220_memsetl(dev, 0x297e00, 0x0, 0x65400); + ls220_memsetl(dev, 0x2fd200, 0x80808080, 0x32a00); + ls220_memsetl(dev, 0x32fc00, 0x0, 0x65400); + ls220_memsetl(dev, 0x395000, 0x80808080, 0x32a00); + } +} + +static void ls220_video_init(struct ls220_dev *dev) +{ + dev->video_hw_wrap = 0xF00000; +// ls220_video_set(dev); + ls220_video_clear_screen(dev); +// ls220_video_set_gamma(dev, 1); +} + +static void ls220_video_reset(struct ls220_dev *dev) +{ +// FILL ME IN +} + +static void ls220_video_set_letter(struct ls220_dev *dev, int onoff) +{ +} + +static void ls220_video_set_speed(struct ls220_dev *dev, int speed) +{ +} + +static void ls220_video_release(struct ls220_dev *dev) +{ + ls220_video_clear_screen(dev); + ls220_video_reset(dev); +} + +static void ls220_video_still(struct ls220_dev *dev) +{ + u32 r180; + + ls220_dv_write(dev, 0x200, 0x7b); + r180 = ls220_dv_read(dev, MPGVID_CONTROL) & 0x1E0; + ls220_dv_write(dev, MPGVID_CONTROL, r180|4); /* Start pointer */ + ls220_video_set_vpm(dev, dev->vga_mode); + ls220_video_set_letter(dev, dev->video_letter); + if(dev->type == LS240) + ls220_dv_write(dev, SYNC_INT_CTRL, 0x88004401); + else + ls220_dv_write(dev, SYNC_INT_CTRL, 0x224401); + ls220_dv_write(dev, 0x278, 0x4000); +} + +static void ls220_video_play(struct ls220_dev *dev, int speed) +{ + u32 reg; + + if(dev->type < LS240) /* might be wrong */ + { + if(/* ?? MENU ?> */ !dev->video_mpeg1) + { + if(ls220_dv_read(dev, 0x145fc) == 0x01) + ls220_dv_write(dev, 0x145fc, 0x02); + } + } + + reg = ls220_dv_read(dev, 0x200); + ls220_dv_write(dev, 0x200, reg |0x01); + + reg = ls220_dv_read(dev, MPGVID_CONTROL); + reg &= 0x1E0; + ls220_dv_write(dev, MPGVID_CONTROL, reg|6); + + ls220_video_set_vpm(dev, dev->vga_mode); + + if(!dev->video_zoomin) + { + ls220_video_set_letter(dev, dev->video_letter); + if(dev->type == LS240) + ls220_dv_write(dev, SYNC_INT_CTRL, 0x38000001); + else + ls220_dv_write(dev, SYNC_INT_CTRL, 0x0e8001); + } + else + { + if(dev->type == LS240) + ls220_dv_write(dev, SYNC_INT_CTRL, 0xc8000001); + else + ls220_dv_write(dev, SYNC_INT_CTRL, 0x328001); + } + ls220_video_set_speed(dev, dev->video_speed); +} + +static void ls220_video_stop(struct ls220_dev *dev) +{ + u32 reg; + + reg = ls220_dv_read(dev, SYNC_INT_CTRL); + + if(dev->type == LS240) + ls220_dv_write(dev, SYNC_INT_CTRL, reg&0xFFFFFFFE); + else + ls220_dv_write(dev, SYNC_INT_CTRL, reg&0xFFFFFE); + + reg = ls220_dv_read(dev, 0x200); + ls220_dv_write(dev, 0x200, reg & 0xFFFE); + + reg = ls220_dv_read(dev, MPGVID_CONTROL); + ls220_dv_write(dev, MPGVID_CONTROL, reg & 0x1E0); + + ls220_dv_write(dev, 0x194, VID_FIFO_OFF); + + dev->video_total = 0; + dev->video_remainder = 0; + dev->video_wptr = VID_FIFO_OFF; + dev->video_pts = 0; + + reg = ls220_dv_read(dev, MPGVID_CONTROL); + ls220_dv_write(dev, MPGVID_CONTROL, (reg&0x1E0) | 1); +} + +static void ls220_video_pause(struct ls220_dev *dev) +{ + u32 reg; + + if(dev->video_speed != 1000) + ls220_dv_write(dev, 0x19C, 0x02); + reg = ls220_dv_read(dev, 0x200); + ls220_dv_write(dev, 0x200, reg&0xFFFE); + ls220_dv_write(dev, SYNC_INT_CTRL, 0x28000); +} + +static unsigned long ls220_video_stc(struct ls220_dev *dev) +{ + return ls220_dv_read(dev, 0x218); +} + +static void ls220_video_fastforward(struct ls220_dev *dev) +{ + u32 reg; + + dev->video_speed = 2000; + if(dev->type == LS240) + { + ls220_dv_write(dev, 0x274, 0x28000001); + ls220_dv_write(dev, 0x268, (ls220_dv_read(dev, 0x268) & 0xA0)|1); + } + else + { + ls220_dv_write(dev, 0x274, 0xa8001); + ls220_dv_write(dev, 0x268, (ls220_dv_read(dev, 0x268) & 0x20)|1); + } +} + +/* + * Called when we reset and reload the DSP + */ +static void ls220_change_dsp(struct ls220_dev *dev, int audio, int vga) +{ + ls220_audio_init(dev, audio); + /* FIXME - reset video vars */ + ls220_video_reset(dev); + ls220_video_set_vpm(dev, vga); + ls220_load_firmware(dev, audio); + ls220_audio_set_info(dev); + + if(dev->eprom[EPROM_SPDIF_CH/*CHECK ME*/] && !(dev->eprom[EPROM_SPDIF_CH]&0x2)) + { + /* SPDIF */ + ls220_audio_set_spdif(dev, 1); + } + else + ls220_audio_set_spdif(dev, 0); + ls220_video_reset(dev); + ls220_video_init(dev); + ls220_audio_init(dev, 1); +} + +/* + * IRQ handling + */ + +static void ls220_intr(int irq, void *dev_id, struct pt_regs *unused) +{ + struct ls220_dev *dev = dev_id; + u32 r20, r14; + + r20 = ls220_dv_read(dev, 0x20); + if(r20 == 0) + return; + + r14 = ls220_dv_read(dev, 0x14); + if(!(r14 & 0x0104)) + return; + + ls220_dv_write(dev, 0x20, r20&0xfffffefb); + + if(r14 & 0x4) + { + ; /* User event */ + } + if(r14 & 0x100) + { + ; /* Video line reached */ + } + + /* Check - should we clear both bits or clear the r14 value ?? */ + ls220_dv_write(dev, 0x18, ls220_dv_read(dev, 0x18)|0x0104); + ls220_dv_write(dev, 0x20, r20 | 0x0104); +} + +/* + * Hardware setup + */ + +static int ls220_hw_init(struct ls220_dev *dev) +{ + /* Set up base registers */ + if(dev->type == LS240) + dev->dram_base = LS240_DRAM_BASE; + else + dev->dram_base = LS220_DRAM_BASE; + if(ls220_i2c_register(dev)) + return -ENODEV; + /* Initialise video side */ + if(ls220_i2c_probe(dev, 0xA0)) + ls220_load_eeprom(dev, 0xA0, 0, 16, dev->eprom); + ls220_video_reset(dev); + if((dev->tvencoder = ls220_detect_tvencoder(dev))<0) + { + i2c_bit_del_bus(&dev->i2c_adap); + return -ENODEV; + } + printk(KERN_INFO "luxsonor: Found attached %s TV encoder.\n", + lux_tv_names[dev->tvencoder]); + /* Initialise audio side */ + ls220_audio_init(dev, 1); + /* Now reset and bring up */ + ls220_reset(dev); + /* Set up the VMI */ + ls220_video_set_vpm(dev, 0/* For now.. */); + if(ls220_i2c_probe(dev, 0xA0)) + { + ls220_load_eeprom(dev, 0xA0, 0, 16, dev->eprom); + dev->has_eprom = 1; + if(dev->eprom[EPROM_BOARDTYPE] == 1) + { + ls220_send_gpio(dev, 6, 5); /* chrontel setup */ + ls220_send_gpio(dev, 3, 0xf); + } + } + else + { + dev->has_eprom = 0; + dev->eprom[EPROM_TVOUT] = 0; /* NTSC default */ + } + + ls220_load_firmware(dev, 1); /* Default Microcode */ + + ls220_audio_set_info(dev); + + if(dev->eprom[EPROM_SPDIF_CH/*CHECK ME*/] && !(dev->eprom[EPROM_SPDIF_CH]&0x2)) + { + /* SPDIF */ + ls220_audio_set_spdif(dev, 1); + } + else + ls220_audio_set_spdif(dev, 0); + /* Reset again */ + ls220_video_reset(dev); + ls220_audio_init(dev, 1); + ls220_configure_tvout(dev, 0); + return 0; +} + +static int ls220_init_one(struct pci_dev *pdev, const struct pci_device_id *ident) +{ + struct ls220_dev *dev = kmalloc(sizeof(struct ls220_dev), GFP_KERNEL); + if(dev == NULL) + return -ENOMEM; + memset(dev, 0, sizeof(*dev)); + dev->pdev = pdev; + dev->type = ident->driver_data; + + dev->i2c_rc = -1; + + if(pci_enable_device(pdev)<0) + { + kfree(pdev); + return -ENODEV; + } + + pci_set_drvdata(pdev, dev); + + if(request_irq(pdev->irq, ls220_intr, SA_SHIRQ, "ls220", dev)<0) + { + printk(KERN_ERR "ls220: unable to obtain interrupt.\n"); + pci_set_drvdata(pdev, NULL); + kfree(dev); + return -EBUSY; + } + dev->membase = ioremap(pdev->resource[0].start, pci_resource_len(pdev, 0)); + if(dev->membase == NULL) + { + printk(KERN_ERR "ls220: unable to map device.\n"); + free_irq(pdev->irq, dev); + pci_set_drvdata(pdev, NULL); + kfree(dev); + return -ENOMEM; + } + + pci_set_master(pdev); + + printk(KERN_INFO "luxsonor %s at 0x%lX for %ld bytes, IRQ %d.\n", + lux_names[dev->type], pdev->resource[0].start, + pci_resource_len(pdev, 0), pdev->irq); + + if(ls220_hw_init(dev) < 0) + { + free_irq(pdev->irq, dev); + if(dev->i2c_rc != -1) + i2c_bit_del_bus(&dev->i2c_adap); + pci_set_drvdata(pdev, NULL); + kfree(dev); + return -ENODEV; + } + if(dev->type == LS240) + { + ls240_zoomvideo_enable_tristate(dev); + ls240_audiopcm_enable_tristate(dev); + } + + + dev->next = ls_devs; + ls_devs = dev; + + return 0; +} + +static void __devexit ls220_remove_one(struct pci_dev *pdev) +{ + struct ls220_dev *dev = pci_get_drvdata(pdev); + free_irq(dev->pdev->irq, dev); + if(dev->i2c_rc != -1) + i2c_bit_del_bus(&dev->i2c_adap); + iounmap(dev->membase); + pci_disable_device(dev->pdev); +} + +/* + * This code and tables ensures we are notified if there is a + * luxsonor card, either at boot or in the event of a PCI hotplug + */ + +static struct pci_device_id luxsonor_table[] __devinitdata = { + { 0x1287, 0x001F, PCI_ANY_ID, PCI_ANY_ID, LS220C }, /* 220C */ + { 0x1287, 0x001E, PCI_ANY_ID, PCI_ANY_ID, LS220D }, /* 220D */ + { 0x1287, 0x0020, PCI_ANY_ID, PCI_ANY_ID, LS240 }, /* 240 */ + { 0, } +}; + +MODULE_DEVICE_TABLE(pci, luxsonor_table); + +static struct pci_driver luxsonor_driver = +{ + name: "ls220", + id_table: luxsonor_table, + probe: ls220_init_one, + remove: __devexit_p(ls220_remove_one), + /* No power management yet */ +}; + +static int __init luxsonor_init_module(void) +{ + return pci_module_init(&luxsonor_driver); +} + +static void __exit luxsonor_cleanup_module(void) +{ + pci_unregister_driver(&luxsonor_driver); +} + +module_init(luxsonor_init_module); +module_exit(luxsonor_cleanup_module); + +MODULE_AUTHOR("Alan Cox "); +MODULE_LICENSE("GPL"); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/Makefile linux.19rc3-ac4/drivers/media/video/Makefile --- linux.19rc3/drivers/media/video/Makefile 2002-07-29 12:50:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/Makefile 2002-07-29 13:58:40.000000000 +0100 @@ -1,5 +1,5 @@ # -# Makefile for the kernel character device drivers. +# Makefile for the video capture/playback device drivers. # # Note! Dependencies are done automagically by 'make dep', which also # removes any old dependencies. DON'T put your own dependencies here @@ -16,10 +16,6 @@ obj-n := obj- := -SUB_DIRS := -MOD_SUB_DIRS := $(SUB_DIRS) -ALL_SUB_DIRS := $(SUB_DIRS) - O_TARGET := video.o # All of the (potential) objects that export symbols. @@ -31,8 +27,16 @@ bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o zoran-objs := zr36120.o zr36120_i2c.o zr36120_mem.o +mod-subdirs := margi + obj-$(CONFIG_VIDEO_DEV) += videodev.o +ifeq ($(CONFIG_VIDEO_MARGI),y) + obj-y += margi/margi_cs.o +endif + +subdir-$(CONFIG_VIDEO_MARGI) += margi + obj-$(CONFIG_BUS_I2C) += i2c-old.o obj-$(CONFIG_VIDEO_BT848) += bttv.o msp3400.o tvaudio.o \ tda7432.o tda9875.o tuner.o @@ -58,6 +62,7 @@ obj-$(CONFIG_VIDEO_CPIA_USB) += cpia_usb.o obj-$(CONFIG_VIDEO_MEYE) += meye.o obj-$(CONFIG_TUNER_3036) += tuner-3036.o +obj-$(CONFIG_VIDEO_LS220) += luxsonor.o # Extract lists of the multi-part drivers. # The 'int-*' lists are the intermediate files used to build the multi's. @@ -78,8 +83,6 @@ include $(TOPDIR)/Rules.make -fastdep: - zoran.o: zr36120.o zr36120_i2c.o zr36120_mem.o $(LD) $(LD_RFLAG) -r -o $@ zr36120.o zr36120_i2c.o zr36120_mem.o diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/audio.c linux.19rc3-ac4/drivers/media/video/margi/audio.c --- linux.19rc3/drivers/media/video/margi/audio.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/audio.c 2002-07-29 13:58:41.000000000 +0100 @@ -0,0 +1,248 @@ +/* + audio.c + + Copyright (C) Christian Wolff for convergence integrated media. + + 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. +*/ + +// +// Audio Decoder +// +#define __NO_VERSION__ + +#include "audio.h" +#include "l64021.h" + +// mode=0 pause +// mode=1 normal speed play +// mode=2 fast play, 16/15 +// mode=3 slow play, 16/17 + +void AudioSetPlayMode(struct cvdv_cards *card, int mode) +{ + DecoderMaskByte(card, 0x163, 0x60, (mode & 0x03) << 5); + // audio decoder play mode + DecoderMaskByte(card, 0x164, 0x60, (((mode) ? 1 : 0) & 0x03) << 5); + // S/PDIF formatter play mode +} + +void AudioStartDecode(struct cvdv_cards *card) +{ + DecoderSetByte(card, 0x163, 0x80); +} + +// Stop Decode flushes the Audio ES channel buffer +void AudioStopDecode(struct cvdv_cards *card) +{ + DecoderDelByte(card, 0x163, 0x80); +} + +void AudioStartFormat(struct cvdv_cards *card) +{ + DecoderSetByte(card, 0x164, 0x80); +} + +void AudioStopFormat(struct cvdv_cards *card) +{ + DecoderDelByte(card, 0x164, 0x80); +} + +// Audio source: S/PDIF out: +// mode 0: MPEG IEC958 +// mode 1: AC3 IEC958 +// mode 2: MPEG MPEG +// mode 3: AC3 AC3 +// mode 4: PCM IEC958 (max. 48kHz) +// mode 5: PCM 96->48kHz IEC958 (48kHz) +// mode 6: CD Bypass S/PDIF Bypass +// mode 7: PCM FIFO PCM FIFO +void AudioSetMode(struct cvdv_cards *card, int mode) +{ + mode &= 0x07; + AudioSetPlayMode(card, MAUDIO_PAUSE); + AudioStopFormat(card); + DecoderMaskByte(card, 0x165, 0xE0, mode << 5); + if ((mode == 2) || (mode == 3)) + AudioStartFormat(card); +} + + +// volume: 0..255 +void AudioSetVolume(struct cvdv_cards *card, int volume) +{ + DecoderWriteByte(card, 0x16A, volume); // Set PCM scale to volume +} + +// mute=1: mute audio +void AudioMute(struct cvdv_cards *card, int mute) +{ + DecoderMaskByte(card, 0x166, 0x40, (mute ? 0x40 : 0x00)); + // mute PCM + DecoderMaskByte(card, 0x16E, 0x10, (mute ? 0x10 : 0x00)); + // mute S/PDIF +} + +// mode=0: stereo +// mode=1: surround +void AudioAC3Mode(struct cvdv_cards *card, int mode) +{ + DecoderMaskByte(card, 0x166, 0x10, (mode ? 0x10 : 0x00)); +} + +// mode=0: custom analog +// mode=1: custom digital +// mode=2: line-out (default) +// mode=3: RF mode +void AudioAC3Compression(struct cvdv_cards *card, int mode) +{ + DecoderMaskByte(card, 0x166, 0x03, mode & 0x03); +} + +// mode=0: AC3 +// mode=1: ES1 +void AudioAC3Formatter(struct cvdv_cards *card, int mode) +{ + DecoderMaskByte(card, 0x166, 0x03, mode & 0x03); +} + +// mode=0: Stereo +// mode=1: Right channel only +// mode=2: Left channel only +// mode=3: Mono Mix +void AudioDualMono(struct cvdv_cards *card, int mode) +{ + DecoderMaskByte(card, 0x166, 0x0C, (mode & 0x03) << 2); +} + +// swap=0: L->L, R->R +// swap=1: L->R, R->L +void AudioSwap(struct cvdv_cards *card, int swap) +{ + DecoderMaskByte(card, 0x16B, 0x04, (swap ? 0x00 : 0x04)); +} + +// select=0: use clock from ACLK_441 pin -> ACLK=44.1kHz*N +// select=1: use clock from ACLK_48 pin -> ACLK=48.0kHz*N +// select=2: use clock from ACLK_32 pin -> ACLK=32.0kHz*N +// Since the programmable sample rate generator of the PCM1723 is connected to +// all 3 of them, it doen't matter wich one you choose. +// divider=0: ACLK=768*Fs / S/PDIF-BCLK=ACLK/6 / DAC-BCLK=ACLK/12 / DAC-A_ACLK=ACLK/3 +// divider=1: ACLK=768*Fs / S/PDIF-BCLK=ACLK/6 / DAC-BCLK=ACLK/12 / DAC-A_ACLK=ACLK/2 +// divider=2: ACLK=512*Fs / S/PDIF-BCLK=ACLK/4 / DAC-BCLK=ACLK/8 / DAC-A_ACLK=ACLK/2 +// divider=3: ACLK=384*Fs / S/PDIF-BCLK=ACLK/3 / DAC-BCLK=ACLK/6 / DAC-A_ACLK=ACLK/1 +// divider=4: ACLK=256*Fs / S/PDIF-BCLK=ACLK/2 / DAC-BCLK=ACLK/4 / DAC-A_ACLK=ACLK/1 +// divider=5: ACLK=768*48kHz / S/PDIF-BCLK=ACLK/6 / DAC-BCLK=ACLK/6 / DAC-A_ACLK=ACLK/1 +// divider=6: ACLK=512*48kHz / S/PDIF-BCLK=ACLK/4 / DAC-BCLK=ACLK/4 / DAC-A_ACLK=ACLK/1 +// divider=C: ACLK=768*48kHz / S/PDIF-BCLK=ACLK/9 / DAC-BCLK=ACLK/18 / DAC-A_ACLK=ACLK/3 +// divider=D: ACLK=512*48kHz / S/PDIF-BCLK=ACLK/6 / DAC-BCLK=ACLK/12 / DAC-A_ACLK=ACLK/3 +// divider=E: ACLK=512*48kHz / S/PDIF-BCLK=ACLK/6 / DAC-BCLK=ACLK/12 / DAC-A_ACLK=ACLK/2 +// divider=F: ACLK=256*48kHz / S/PDIF-BCLK=ACLK/3 / DAC-BCLK=ACLK/6 / DAC-A_ACLK=ACLK/1 +// Fs is the audio sample frequency +// For the normal cases, (32, 44.1, and 48 kHz) select divider 0 through 4 and set +// sample frequency in PCM1723 accordingly +// For 96 kHz, select divider 5 or 6, and set PCM1723 to 48kHz*768 or *512 resp. +// Divider C through F are for 32 kHz sample frequency with a 48kHz*x ACLK +void AudioSetACLK(struct cvdv_cards *card, int select, int divider) +{ + DecoderMaskByte(card, 0x16B, 0x03, select & 0x03); + DecoderMaskByte(card, 0x16C, 0x0F, divider & 0x0F); +} + +int AudioOpen(struct cvdv_cards *card) +{ + // initialize the audio card + MDEBUG(1, ": -- AudioOpen\n"); + write_indexed_register(card, IIO_OSC_AUD, 0x10); + return 0; +} + +int AudioClose(struct cvdv_cards *card) +{ + MDEBUG(1, ": -- AudioClose\n"); + card->AudioInitialized = 0; + return 0; +} + +// audiorate: 16, 32, 64, 22(.05), 44(.1), 88(.2), 24, 48, 96 kHz +// surround=0: Stereo +// surround=1: Surround +int AudioInit(struct cvdv_cards *card, int audiorate, int surround) +{ + //if ((audiorate!=44) && (audiorate!=32)) audiorate=48; + MDEBUG(1, ": -- AudioInit %d\n", audiorate); + + DACSetFrequency(card, audiorate, 256); // put Fs*256 on ACLK inputs + + if (audiorate == 96) + AudioSetACLK(card, 1, 0x06); // 512*48kHz at ACLK + else + AudioSetACLK(card, 1, 0x04); // 256 times Fs at ACLK + + DecoderDelByte(card, 0x166, 80); // no mute on error + DecoderWriteByte(card, 0x168, 0xFF); // dynscalehigh + DecoderWriteByte(card, 0x169, 0xFF); // dynscalelow + DecoderWriteByte(card, 0x16A, 0xFF); // PCM scale + + // IEC958 Setup + DecoderDelByte(card, 0x16D, 0x20); // Overwrite Emphasis off + DecoderSetByte(card, 0x16D, 0x40); // Copyright Override + DecoderDelByte(card, 0x16D, 0x80); // Copyright Bit off + DecoderDelByte(card, 0x16E, 0x01); // Overwrite Category off + DecoderDelByte(card, 0x16E, 0x08); // Overwrite Quatization off + DecoderSetByte(card, 0x170, 0x08); // Musicam Stream Debug + + AudioAC3Mode(card, (surround ? 1 : 0)); + AudioAC3Compression(card, 2); + AudioAC3Formatter(card, 0); + + AudioDualMono(card, 0); + AudioSwap(card, 0); + + AudioMute(card, 0); +// AudioSetPlayMode(card,MAUDIO_PLAY); + + card->AudioInitialized = 1; + return 0; +} + + +// returns size of the Video ES Buffer in bytes or 0=error +u32 DecoderGetAudioESSize(struct cvdv_cards * card) +{ + if (!card->ChannelBuffersAllocated) + return 0; // buffer not initialised + return (u32) ((DecoderReadWord(card, 0x04E) & 0x3FFF) - + (DecoderReadWord(card, 0x04C) & 0x3FFF)) * 256; // bytes +} + +// returns level of fullness in bytes +u32 DecoderGetAudioESLevel(struct cvdv_cards * card) +{ + u32 items; + items = DecoderReadByte(card, 0x089); + items |= ((DecoderReadWord(card, 0x08A) & 0x07FF) << 8); + items *= 8; // 64 bit per item + return items; +} + +int DecoderKaraoke(struct cvdv_cards *card, int vocal1, int vocal2, + int melody) +{ + DecoderMaskByte(card, 0x18C, 0x40, ((vocal1) ? 0x40 : 0x00)); + DecoderMaskByte(card, 0x18C, 0x80, ((vocal2) ? 0x80 : 0x00)); + DecoderMaskByte(card, 0x18C, 0x20, ((melody) ? 0x20 : 0x00)); + return 0; +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/audio.h linux.19rc3-ac4/drivers/media/video/margi/audio.h --- linux.19rc3/drivers/media/video/margi/audio.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/audio.h 2002-07-29 17:29:11.000000000 +0100 @@ -0,0 +1,136 @@ +/* + audio.h + + Copyright (C) Christian Wolff for convergence integrated media. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#ifndef CVDV_AUDIO_H +#define CVDV_AUDIO_H + + // + // Audio Decoder +// +#define __NO_VERSION__ + +#include "cardbase.h" + +#define MAUDIO_PAUSE 0 +#define MAUDIO_PLAY 1 +#define MAUDIO_FAST 2 +#define MAUDIO_SLOW 3 + +// mode=0 pause +// mode=1 normal speed play +// mode=2 fast play, 16/15 +// mode=3 slow play, 16/17 +void AudioSetPlayMode(struct cvdv_cards *card, int mode); + +void AudioStartDecode(struct cvdv_cards *card); + +// Stop Decode flushes the Audio ES channel buffer +void AudioStopDecode(struct cvdv_cards *card); + +void AudioStartFormat(struct cvdv_cards *card); + +void AudioStopFormat(struct cvdv_cards *card); + +// Audio source: S/PDIF out: +// mode 0: MPEG IEC958 +// mode 1: AC3 IEC958 +// mode 2: MPEG MPEG +// mode 3: AC3 AC3 +// mode 4: PCM IEC958 (max. 48kHz) +// mode 5: PCM 96->48kHz IEC958 (48kHz) +// mode 6: CD Bypass S/PDIF Bypass +// mode 7: PCM FIFO PCM FIFO +void AudioSetMode(struct cvdv_cards *card, int mode); + + +// volume: 0..255 +void AudioSetVolume(struct cvdv_cards *card, int volume); + +// mute=1: mute audio +void AudioMute(struct cvdv_cards *card, int mute); + +// mode=0: stereo +// mode=1: surround +void AudioAC3Mode(struct cvdv_cards *card, int mode); + +// mode=0: custom analog +// mode=1: custom digital +// mode=2: line-out (default) +// mode=3: RF mode +void AudioAC3Compression(struct cvdv_cards *card, int mode); + +// mode=0: AC3 +// mode=1: ES1 +void AudioAC3Formatter(struct cvdv_cards *card, int mode); + +// mode=0: Stereo +// mode=1: Right channel only +// mode=2: Left channel only +// mode=3: Mono Mix +void AudioDualMono(struct cvdv_cards *card, int mode); + +// swap=0: L->L, R->R +// swap=1: L->R, R->L +void AudioSwap(struct cvdv_cards *card, int swap); + +// select=0: use clock from ACLK_441 pin -> ACLK=44.1kHz*N +// select=1: use clock from ACLK_48 pin -> ACLK=48.0kHz*N +// select=2: use clock from ACLK_32 pin -> ACLK=32.0kHz*N +// Since the programmable sample rate generator of the PCM1723 is connected to +// all 3 of them, it doen't matter wich one you choose. +// divider=0: ACLK=768*Fs / S/PDIF-BCLK=ACLK/6 / DAC-BCLK=ACLK/12 / DAC-A_ACLK=ACLK/3 +// divider=1: ACLK=768*Fs / S/PDIF-BCLK=ACLK/6 / DAC-BCLK=ACLK/12 / DAC-A_ACLK=ACLK/2 +// divider=2: ACLK=512*Fs / S/PDIF-BCLK=ACLK/4 / DAC-BCLK=ACLK/8 / DAC-A_ACLK=ACLK/2 +// divider=3: ACLK=384*Fs / S/PDIF-BCLK=ACLK/3 / DAC-BCLK=ACLK/6 / DAC-A_ACLK=ACLK/1 +// divider=4: ACLK=256*Fs / S/PDIF-BCLK=ACLK/2 / DAC-BCLK=ACLK/4 / DAC-A_ACLK=ACLK/1 +// divider=5: ACLK=768*48kHz / S/PDIF-BCLK=ACLK/6 / DAC-BCLK=ACLK/6 / DAC-A_ACLK=ACLK/1 +// divider=6: ACLK=512*48kHz / S/PDIF-BCLK=ACLK/4 / DAC-BCLK=ACLK/4 / DAC-A_ACLK=ACLK/1 +// divider=C: ACLK=768*48kHz / S/PDIF-BCLK=ACLK/9 / DAC-BCLK=ACLK/18 / DAC-A_ACLK=ACLK/3 +// divider=D: ACLK=512*48kHz / S/PDIF-BCLK=ACLK/6 / DAC-BCLK=ACLK/12 / DAC-A_ACLK=ACLK/3 +// divider=E: ACLK=512*48kHz / S/PDIF-BCLK=ACLK/6 / DAC-BCLK=ACLK/12 / DAC-A_ACLK=ACLK/2 +// divider=F: ACLK=256*48kHz / S/PDIF-BCLK=ACLK/3 / DAC-BCLK=ACLK/6 / DAC-A_ACLK=ACLK/1 +// Fs is the audio sample frequency +// For the normal cases, (32, 44.1, and 48 kHz) select divider 0 through 4 and set +// sample frequency in PCM1723 accordingly +// For 96 kHz, select divider 5 or 6, and set PCM1723 to 48kHz*768 or *512 resp. +// Divider C through F are for 32 kHz sample frequency with a 48kHz*x ACLK +void AudioSetACLK(struct cvdv_cards *card, int select, int divider); + +int AudioOpen(struct cvdv_cards *card); + +int AudioClose(struct cvdv_cards *card); + +// audiorate: 16, 32, 64, 22(.05), 44(.1), 88(.2), 24, 48, 96 kHz +// surround=0: Stereo +// surround=1: Surround +int AudioInit(struct cvdv_cards *card, int audiorate, int surround); + + +// returns size of the Video ES Buffer in bytes or 0=error +u32 DecoderGetAudioESSize(struct cvdv_cards *card); + +// returns level of fullness in bytes +u32 DecoderGetAudioESLevel(struct cvdv_cards *card); + +int DecoderKaraoke(struct cvdv_cards *card, int vocal1, int vocal2, + int melody); + +#endif /* CVDV_AUDIO_H */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/AUTHORS linux.19rc3-ac4/drivers/media/video/margi/AUTHORS --- linux.19rc3/drivers/media/video/margi/AUTHORS 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/AUTHORS 2002-07-29 13:58:41.000000000 +0100 @@ -0,0 +1,6 @@ +Christian Wolff scarabaeus@convergence.de +Marcus Metzler mocm@convergence.de + +Many thanks to +Shigehiro Nomura s.nomura@mba.nifty.ne.jp +for his ZV-patches for Libretto diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/cardbase.c linux.19rc3-ac4/drivers/media/video/margi/cardbase.c --- linux.19rc3/drivers/media/video/margi/cardbase.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/cardbase.c 2002-07-29 13:58:41.000000000 +0100 @@ -0,0 +1,234 @@ +/* + cardbase.c + + Copyright (C) Christian Wolff for convergence integrated media. + + 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 __NO_VERSION__ + +#include "cardbase.h" + +// List of pci cards in the system +struct cvdv_cards *first_card = NULL; +struct cvdv_cards *minorlist[MAXDEV]; + +u8 FlushPacket[32] = { + 0x00, 0x00, 0x01, 0xE0, // video stream start code + 0x00, 0x1a, // 26 more bytes + 0x81, 0xC1, // flags: copy=1, PTS_DTS=11, PES_extension=1 + 0x0D, // 13 more header bytes + 0x31, 0x00, 0x03, 0x5F, 0xEB, // PTS + 0x11, 0x00, 0x03, 0x48, 0x75, // DTS + 0x1E, // flags: P-STD_buffer=1, + 0x60, 0xE8, // P-STD_buffer_scale=1, P-STD_buffer_size=232(kByte) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +void DecoderStreamReset(struct cvdv_cards *card) +{ + card->stream.valid = 0; + card->stream.sh.valid = 0; + card->stream.se.valid = 0; + card->stream.gop.valid = 0; + card->stream.MPEG2 = 0; + card->stream.audio.valid = 0; + memset(&card->stream.audio.mpeg,0,sizeof(struct AudioMPEG)); + memset(&card->stream.audio.ac3,0,sizeof(struct AudioAC3)); + memset(&card->stream.audio.pcm,0,sizeof(struct AudioPCM)); + card->AuxFifoExt = 0; + card->AuxFifoLayer = -1; +} +void PTSStoreInit(PTSStorage * store, int size) +{ + int i; + if (size > MAX_PTS) + size = MAX_PTS; + store->size = size; + store->begin = 0; + store->end = 0; + store->LastAddr = 0; + for (i = 0; i < store->size; i++) { + store->AddrB[i] = 0; + store->AddrE[i] = 0; + store->PTS[i] = 0; + } +} + +void DecoderCSSReset(struct cvdv_cards *card) +{ + card->css.status = 0; + card->css.ChallengeReady = 0; + card->css.ResponseReady = 0; + card->css.DiskKey = 0; + card->css.TitleKey = 0; + card->css.Error = 0; + card->css.TitleKeyDiff = 0; + card->LastAddr = 0; // last used address in PES buffer + card->VPTS = 0; + card->oldVPTS = 0; + card->VSCR = 0; + card->APTS = 0; + card->oldAPTS = 0; + card->ASCR = 0; + card->SyncTime = 0; + card->paused = 0; // pause status + card->lastvattr = 0; // last set dvd video attribute + card->lastaattr = 0; // last set dvd audio attribute + card->nonblock = 0; +} + +void DecoderSetupReset(struct cvdv_cards *card) +{ + card->DecoderOpen = 0; + card->closing = 0; + card->channelrun = 0; + card->setup.streamtype = stream_none; + card->setup.audioselect = audio_none; + card->setup.videoID = 0; + card->setup.audioID = 0; + card->setup.audioIDext = -1; + card->setup.SPDIFmode = 0; + card->startingV = 0; + card->startingA = 0; + card->startingDVDV = 0; + card->startingDVDA = 0; + card->videodelay = 0; + card->videodelay_last = 0; + card->videoslow_last = 0; + card->videoslow = 0; + card->videoffwd = 0; + card->videoffwd_last = 0; + card->videoskip = 0; + card->videoskip_last = 0; + card->videosync = 0; + card->paused = 0; + PTSStoreInit(&card->VideoPTSStore, MAX_PTS); + PTSStoreInit(&card->AudioPTSStore, MAX_PTS); +#ifdef DVB + card->audiostate.AVSyncState=true; +#endif +} + + + +void card_init(struct cvdv_cards *card, unsigned int minor) +{ + card->DRAMFirstBlock = NULL; + card->DRAMSize = 0; + card->OSD.open = 0; + card->DMAABusy = 0; + card->DMABBusy = 0; + card->IntInstalled = 0; + card->ChannelBuffersAllocated = 0; + card->VideoES = BLANK; + card->AudioES = BLANK; + card->VideoPES = BLANK; + card->DataDump = BLANK; + card->AudioPES = BLANK; + card->NaviBank = BLANK; + card->FrameBuffersAllocated = 0; + card->FrameStoreLuma1 = BLANK; + card->FrameStoreChroma1 = BLANK; + card->FrameStoreLuma2 = BLANK; + card->FrameStoreChroma2 = BLANK; + card->FrameStoreLumaB = BLANK; + card->FrameStoreChromaB = BLANK; + card->DecoderOpen = 0; + card->AuxFifoHead = 0; + card->AuxFifoTail = 0; + card->DataFifoHead = 0; + card->DataFifoTail = 0; + card->FifoALast = -1; + card->FifoBLast = -1; + //reset_stream(card); + DecoderStreamReset(card); + DecoderSetupReset(card); + card->AudioInitialized = 0; + card->AudioOldMode = -1; + card->closing = 0; + card->startingV = 0; + card->startingA = 0; + card->startingDVDV = 0; + card->startingDVDA = 0; + card->channelrun = 0; + card->fields = 0; + DecoderCSSReset(card); + card->NaviPackAddress = 0; + init_waitqueue_head(&card->wqA); + init_waitqueue_head(&card->wqB); + card->navihead = 0; // write pointer for navi ring buffer + card->navitail = 0; // read pointer for navi ring buffer + card->intdecodestatus = 0; // last status of decode interrupt + card->showvideo = 0; // show video instead black as soon as picture slice is there + card->videodelay = 0; // slow counter + card->videodelay_last = 0; // slow counter + card->videoffwd = 0; // fast playback + card->videoffwd_last = 0; // fast playback + card->videoskip = 0; // fast counter + card->videoskip_last = 0; // fast counter + card->videoslow_last = 0; + card->videoslow = 0; + card->videosync = 0; // do audio/video sync basen on PTS? + PTSStoreInit(&card->VideoPTSStore, MAX_PTS); + PTSStoreInit(&card->AudioPTSStore, MAX_PTS); + card->LastAddr = 0; // last used address in PES buffer + card->VPTS = 0; + card->oldVPTS = 0; + card->VSCR = 0; + card->APTS = 0; + card->oldAPTS = 0; + card->ASCR = 0; + card->SyncTime = 0; + card->paused = 0; // pause status + card->lastvattr = 0; // last set dvd video attribute + card->lastaattr = 0; // last set dvd audio attribute + card->reg08F = 0; // mirror of decoder registers + card->reg090 = 0; + card->reg091 = 0; + card->reg092 = 0; + card->reg093 = 0; + card->highlight_valid = 0; // SPU highlight info available for next BAV int + card->do_flush = 0; + + card->open = 0; + + card->VideoESSize = 0; + card->AudioESSize = 0; + card->VideoPESSize = 0; + card->DataDumpSize = 0; + card->AudioPESSize = 0; + card->NaviBankSize = 0; + card->currentType = -1; + card->rbufA.buffy = NULL; + card->rbufB.buffy = NULL; + card->use_ringA = 0; + card->use_ringB = 0; + card->minor = minor; + card->hasZV = 0; +#ifdef NOINT + init_timer(&card->timer); + spin_lock_init(&card->timelock); +#endif +#ifdef DVB + card->dvb_registered = 0; + card->audiostate.AVSyncState=true; + card->nonblock = 0; +#endif + card->svhs = 0; + card->composite = 0; +} + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/cardbase.h linux.19rc3-ac4/drivers/media/video/margi/cardbase.h --- linux.19rc3/drivers/media/video/margi/cardbase.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/cardbase.h 2002-07-29 17:29:11.000000000 +0100 @@ -0,0 +1,454 @@ +/* + cardbase.h + + Copyright (C) Christian Wolff for convergence integrated media. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef CARDBASE_H +#define CARDBASE_H + +#define __DVB_PACK__ +#define USE_OSD +#define NOINT +#define DVB +#define USE_ZV + +#ifdef PCMCIA_DEBUG +static int pc_debug = PCMCIA_DEBUG; +MODULE_PARM(pc_debug, "i"); +#define MARGI_DEBUG (pc_debug) +#else +#define MARGI_DEBUG 2 +#endif + +// all the internal structs + +#include + +#include "ringbuffy.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef DVB +#include "dvbdev.h" +#ifdef __DVB_PACK__ +#include "ost/video.h" +#include "ost/audio.h" +#include "ost/demux.h" +#include "ost/dmx.h" +#include "ost/sec.h" +#include "ost/frontend.h" +#include "ost/ca.h" +#include "ost/osd.h" +#else +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#include "dvb_demux.h" +#include "dmxdev.h" +#include "dvb_filter.h" +#endif +// List of pci cards in the system + +#include "cvdvtypes.h" + +#define DVERSION "0.6.0" +#define SHORTDEVNAME "ConvDVD" +#define MEDDEVNAME "convergence DVD" +#define LONGDEVNAME "convergence DVD Video Decoder" +#define LOGNAME "convdvd " +#define NBBUF 8 + + +#ifdef MARGI_DEBUG +#define MDEBUG(n, args...) if (MARGI_DEBUG>(n)) printk(KERN_ERR LOGNAME args) +#else +#define MDEBUG(n, args...) +#endif + + +#define VID_PAN_SCAN_PREF 0x01 /* Pan and Scan Display preferred */ +#define VID_VERT_COMP_PREF 0x02 /* Vertical compression display preferred */ +#define VID_VC_AND_PS_PREF 0x03 /* PanScan and vertical Compression if allowed */ +#define VID_CENTRE_CUT_PREF 0x05 /* PanScan with zero vector */ + + +// Character device definitions +// char dev name +#define CVDV_PROCNAME "msc" // Media Stream Consumer +// got to get another number +#define CVDV_MAJOR 200 // 0=dynamic assignment + +// Author definitions +#define NAME "Christian Wolff" +#define EMAIL "scarabaeus@convergence.de" +#define COMPANY "convergence integrated media GmbH" +#define AUTHOR NAME " <" EMAIL "> " COMPANY + +#define MAXDEV 1 // maximum number of cards, distance between minor devices + +#define MINORNUM (256/MAXDEV) // number of minor devices + +#define NAVISIZE 1024 // size of one navi block +#define NAVIBUFFERSIZE NAVISIZE*10 // size of ten navi blocks + +#define BLANK 0xFFFFFFFF + +#define FIFO_MASK 1023 + +#define CCIR601Lines(system) (((system==NTSC) || (system==NTSC60) || (system==PALM) || (system==PALM60) || (system==PAL60))?525:625) + +// default video mode +#define VIDEO_MODE PAL +//#define VIDEO_MODE NTSC + +struct DRAMBlock { + u32 start; // start address of the block; (21 bit word address, 64 bit aligned) + u32 length; // length of the block (in 16 bit words) + struct DRAMBlock *next; // chain link +}; + +struct CSS { + u8 status; // interrupt status from Register 0x0B0 + int ChallengeReady; // 1 if challenge data valid + u8 challenge[10]; // challenge data + int ResponseReady; // 1 if response data valid + u8 response[5]; // response data + int DiskKey; // 1 if disk key extraction complete + int TitleKey; // 1 if title key decryption complete + int Error; // 1 if authentication or disc key extraction + int TitleKeyDiff; // 1 if title key different from previous +}; + +struct GOPHeader { + int valid; // 1: struct contains valid data + int timecode; + int closedgop; + int brokenlink; +}; + +struct SequenceHeader { + int valid; // 1: struct contains valid data + int hsize; + int vsize; + int aspectratio; + int frameratecode; + int bitrate; + int vbvbuffersize; + int constrained; +}; + +struct SequenceExtension { + int valid; // 1: struct contains valid data + int profilelevel; + int progressive; + int chroma; + int hsizeext; + int vsizeext; + int bitrateext; + int vbvbuffersizeext; + int lowdelay; + int frextn; + int frextd; +}; + +struct AudioMPEG { + int present; // true: MPEG audio stream present + int MPEG2; // 0:MPEG1 Audio + int layer; // 1..3 (I..III) + int bitrate; // 0=free, 32-448 kbps + int samplefreq; // 32,44,48 (44 eq. 44.1) + int mode; // 0=stereo 1=joint-stereo 2=dualchannel 3=single channel (just right channel) + int modeext; // Layer I&II: intensity stereo subbands Layer III: bit 0=intensity stereo, bit 1=ms-stereo + int copyright; // true=copyrighted material + int original; // 0=copy true=original + int emphasis; // 0=no emph. 1=50/15usec 3=CCITT J.17 +}; + +struct AudioAC3 { + int present; // 1: AC3 audio stream present + int acmod; // parameters from the AC3 documentation + int bsmod; + int dialnorm; + int dialnorm2; + int surmixlev; + int mixlevel; + int cmixlev; + int mixlevel2; + int fscod; + int lfeon; + int bsid; + int dsurmod; + int frmsizecod; + int langcod; + int langcod2; + int timecod; + int roomtyp; + int timecod2; + int roomtyp2; +}; + +struct AudioPCM { + int present; // 1: PCM audio stream present + int audio_frm_num; + int num_of_audio_ch; + int Fs; + int quantization; + int emphasis; + int mute_bit; +}; + +struct AudioParam { + int valid; + struct AudioMPEG mpeg; + struct AudioAC3 ac3; + struct AudioPCM pcm; +}; + +struct OSDPicture { // all u32 pointers are 21 bit word addresses + int open; // are the buffers initialized? + int width; // frame width + int height; // frame height + int bpp; // bit per pixel + int evenfirst; // first line is in even field + int aspectratio; // pixel aspect ratio: 11/aspectratio + int oddheight; // height of the odd field + u32 oddmem; // DRAM address of allocated memory + u32 odddata; // data (=header) pointer + u32 oddpalette; // pointer to palette inside data + u32 oddbitmap; // pointer to bitmap inside data + u32 oddterm; // pointer to termination header + int evenheight; // height of the even field + u32 evenmem; // DRAM address of allocated memory + u32 evendata; // data (=header) pointer + u32 evenpalette; // pointer to palette inside data + u32 evenbitmap; // pointer to bitmap inside data + u32 eventerm; // pointer to termination header +}; + +struct StreamInfo { + int valid; // 1: struct contains valid data + int MPEG2; // 0: MPEG1/ISO11172 1: MPEG2/ISO13818 + int hsize; // overall hsize (hsize&hsizeext) + int vsize; // overall vsize (vsize&vsizeext) + int bitrate; // overall bitrate (bitrate&bitrateext) + int vbvbuffersize; // overall... + struct GOPHeader gop; + struct SequenceHeader sh; + struct SequenceExtension se; + struct AudioParam audio; +}; + +struct StreamSetup { // user selected parameters for the stream playback + stream_type streamtype; // what is the type of our input stream? + audio_type audioselect; // 0=auto/unknown 1=MPEG 2=LPCM 3=AC3 + int videoID; // stream ID of the video ES, -1 for any + int audioID; // stream ID of the audio ES, -1 for any + int audioIDext; // stream ID of the audio extension ES, -1 for none + int SPDIFmode; // 0:MPEG/AC3 data on digital S/PDIF out 1:IEC956 data on digital S/PDIF out +}; + +#define MAX_PTS 256 + +typedef struct PTSRecord { + int begin; + int end; + int size; + u32 LastAddr; + u32 AddrB[MAX_PTS]; + u32 AddrE[MAX_PTS]; + u32 PTS[MAX_PTS]; +} PTSStorage; + +#define DVB_DEVS_MAX 9 + +typedef struct dvb_devs_s { + int num; + int tab[DVB_DEVS_MAX]; + int max_users[DVB_DEVS_MAX]; + int max_writers[DVB_DEVS_MAX]; +} dvb_devs_t; + +struct cvdv_cards { +#ifdef DVB + struct dvb_device dvb_dev; + dvb_demux_t demux; +#endif + struct cvdv_cards *next; + void *margi; + struct bus_operations *bus; + u_char scl; + u_char sda; + int i2c_addr; + u32 VideoESSize; + u32 AudioESSize; + u32 VideoPESSize; + u32 DataDumpSize; + u32 AudioPESSize; + u32 NaviBankSize; + int currentType; + ringbuffy rbufA; + ringbuffy rbufB; + int use_ringA; + int use_ringB; + int nonblock; + u8 *addr; + unsigned int size; + unsigned int minor; + struct DRAMBlock *DRAMFirstBlock; + u32 DRAMSize; + struct OSDPicture OSD; + int DMAABusy; // Is the DMA A currently in use? + int DMABBusy; // Is the DMA B currently in use? + int IntInstalled; // is the card interrupt routine installed? + int ChannelBuffersAllocated; // Are the channel buffers for the decoder allocated? + u32 VideoES; // 21 bit word address of the allocated channel + u32 AudioES; // 21 bit word address of the allocated channel + u32 VideoPES; // 21 bit word address of the allocated channel + u32 DataDump; // 21 bit word address of the allocated channel + u32 AudioPES; // 21 bit word address of the allocated channel + u32 NaviBank; // 21 bit word address of the allocated channel + int FrameBuffersAllocated; // Are the frame buffers for the decoder allocated? + u32 FrameStoreLuma1; // 21 bit word address of the allocated frame + u32 FrameStoreChroma1; // 21 bit word address of the allocated frame + u32 FrameStoreLuma2; // 21 bit word address of the allocated frame + u32 FrameStoreChroma2; // 21 bit word address of the allocated frame + u32 FrameStoreLumaB; // 21 bit word address of the allocated frame + u32 FrameStoreChromaB; // 21 bit word address of the allocated frame + int DecoderOpen; // Is the Decoder initialized? + u16 AuxFifo[FIFO_MASK + 1]; // Auxiliary Fifo Data + int AuxFifoHead; // Auxiliary Fifo Position + int AuxFifoTail; // Auxiliary Fifo Position + u16 DataFifo[FIFO_MASK + 1]; // Data Fifo Data + int DataFifoHead; // Data Fifo Position + int DataFifoTail; // Data Fifo Position + int FifoALast; // last used thread of FIFO A + int FifoBLast; // last used thread of FIFO B + videosystem videomode; // current video output mode, PAL or NTSC + struct StreamInfo stream; // header information of the current stream + struct StreamSetup setup; // should be filled bevor sending data, but default is OK + int AuxFifoExt; // used by Aux FIFO parser + int AuxFifoLayer; // " " " " " + int AudioInitialized; // Is the Audio set up? + int AudioOldMode; // remainder of the previous mode while trickmodes, or -1 + int open; // is the 64017 initialized and the video out active? + int closing; // 1 if char device closed, but DMA still running + int startingV; // 1 if card is waiting for the Video ES buffer to fill up, to start the decoder + int startingA; // 1 if card is waiting for the Audio ES buffer to fill up, to start the decoder + int startingDVDV; // 1 if card is waiting for the Video ES buffer to fill up, to start the decoder + int startingDVDA; // 1 if card is waiting for the Audio ES buffer to fill up, to start the decoder + int channelrun; // 1 if channel has been started by the host + int fields; // counter of video fields, debugging only + struct CSS css; // CSS data + u32 NaviPackAddress; // Read address of the Navi Pack Buffer + wait_queue_head_t wqA; + wait_queue_head_t wqB; + u8 navibuffer[NAVIBUFFERSIZE]; + int navihead; + int navitail; + int intdecodestatus; + int showvideo; + int videodelay; + int videodelay_last; + int videoskip; + int videoskip_last; + int videosync; + int videoslow; + int videoslow_last; + int videoffwd; + int videoffwd_last; + PTSStorage VideoPTSStore; + PTSStorage AudioPTSStore; + u32 LastAddr; + u32 VPTS; + u32 oldVPTS; + long VSCR; + u32 APTS; + u32 oldAPTS; + int scrset; + long ASCR; + long SyncTime; + int paused; + u16 lastvattr; + u16 lastaattr; + u8 reg07B; // mirrors of write-only register + u8 reg08F; + u8 reg090; + u8 reg091; + u8 reg092; + u8 reg093; + u8 highlight[10]; // content of registers 1C0 thru 1C0, to be written after next BAV int. + int highlight_valid; // if 1 + int do_flush; // if 1, send flush packet after last transfer done + int hasZV; +#ifdef NOINT + struct timer_list timer; + spinlock_t timelock; +#endif + +#ifdef DVB + dvb_devs_t *dvb_devs; + int users[DVB_DEVS_MAX]; + int writers[DVB_DEVS_MAX]; + + dmxdev_t dmxdev; + boolean video_blank; + struct videoStatus videostate; + struct audioStatus audiostate; + int dvb_registered; + char demux_id[16]; + dmx_frontend_t mem_frontend; + ipack tsa; + ipack tsv; +#endif + + int svhs; + int composite; +}; + +extern u8 FlushPacket[32]; + +extern struct cvdv_cards *first_card; +extern struct cvdv_cards *minorlist[MAXDEV]; + +void DecoderStreamReset(struct cvdv_cards *card); + +void DecoderSetupReset(struct cvdv_cards *card); + +void DecoderCSSReset(struct cvdv_cards *card); + +void card_init(struct cvdv_cards *card, unsigned int minor); + +#endif /* CARDBASE_H */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/CHANGES linux.19rc3-ac4/drivers/media/video/margi/CHANGES --- linux.19rc3/drivers/media/video/margi/CHANGES 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/CHANGES 2002-07-29 13:58:41.000000000 +0100 @@ -0,0 +1,30 @@ +version 0.6 +- added ZV initialisation +- added diff for ZV support in pcmcia-cs version <= 3.1.25 +- added v4l device +- added dvb api devices +- tested it with powerbook g4 and pcmcia-cs-3.1.24 +- WARNING, on some computers using FFWD and slow motion may cause hangups + +version 0.5 +- should work with 2.4.0-test12 +- added driver to public CVS at linuxtv.org + http://linuxtv.org/cgi-bin/cvsweb.cgi/ +- added 32kHz audio support +- fixed problem with PAL MPEG1 playback +- fixed problem with playback of MPEGs with lots of PTS +- fixed switching audio channels + +version 0.4.3 +- it is now working with 2.4.0-test10 and later kernels. Use pcmcia-cs-3.1.22 + and later.(Don't use kernel pcmcia,it's not tested with that. ) +- added playfile to the testsuite + +version 0.4.2 +- changed major device number to 200 until we get a new one +- changed some buffer settings for DVD playback +- added some programming examples in testsuit directory +- some other minor improvements + +version 0.4.1 +- corrected makefile error diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/COPYING linux.19rc3-ac4/drivers/media/video/margi/COPYING --- linux.19rc3/drivers/media/video/margi/COPYING 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/COPYING 2002-07-29 13:58:41.000000000 +0100 @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + 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. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/crc.c linux.19rc3-ac4/drivers/media/video/margi/crc.c --- linux.19rc3/drivers/media/video/margi/crc.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/crc.c 2002-07-29 13:58:41.000000000 +0100 @@ -0,0 +1,78 @@ +/* + crc.c + + Copyright (C) Christian Wolff for convergence integrated media. + + 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. +*/ + +/*--------------------------------------------------------- + +Cyclic Redundancy Check 16 and 32 Bit + +Christian Wolff, 19990122 + +---------------------------------------------------------*/ + +#define __NO_VERSION__ + +#include "crc.h" + +unsigned short crc_16_table[256]; +unsigned long crc_32_table[256]; + +// generate the tables of CRC-16 and CRC-32 remainders for all possible bytes +void gen_crc_table() +{ + register int i, j; + register unsigned short crc16; + register unsigned long crc32; + for (i = 0; i < 256; i++) { + crc16 = (unsigned short) i << 8; + crc32 = (unsigned long) i << 24; + for (j = 0; j < 8; j++) { + if (crc16 & 0x8000) + crc16 = (crc16 << 1) ^ POLYNOMIAL_16; + else + crc16 = (crc16 << 1); + if (crc32 & 0x80000000L) + crc32 = (crc32 << 1) ^ POLYNOMIAL_32; + else + crc32 = (crc32 << 1); + } + crc_16_table[i] = crc16; + crc_32_table[i] = crc32; + } +} + +// update the CRC on the data block one byte at a time +unsigned short update_crc_16_block(unsigned short crc, + char *data_block_ptr, + int data_block_size) +{ + register int i; + for (i = 0; i < data_block_size; i++) + crc = update_crc_16(crc, *data_block_ptr++); + return crc; +} + +unsigned long update_crc_32_block(unsigned long crc, char *data_block_ptr, + int data_block_size) +{ + register int i; + for (i = 0; i < data_block_size; i++) + crc = update_crc_32(crc, *data_block_ptr++); + return crc; +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/crc.h linux.19rc3-ac4/drivers/media/video/margi/crc.h --- linux.19rc3/drivers/media/video/margi/crc.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/crc.h 2002-07-29 13:58:41.000000000 +0100 @@ -0,0 +1,56 @@ +/* + crc.h + + Copyright (C) Christian Wolff for convergence integrated media. + + 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. +*/ + +/*--------------------------------------------------------- + +Cyclic Redundancy Check 16 and 32 Bit - Header File + +Christian Wolff, 19990122 + +---------------------------------------------------------*/ + +#ifndef _CRC_H_ +#define _CRC_H_ + +// 16 Bit CCITT standard polynomial x^16 + x^12 + x^5 + x^1 + x^0 +#define POLYNOMIAL_16 0x1021 +// 32 Bit standard polynomial x^32 + x^26 + x^23 + x^22 + x^16 + +// x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + x^0 +#define POLYNOMIAL_32 0x04C11DB7L + +#define CRC_INIT_16 0xFFFF +#define CRC_INIT_32 0xFFFFFFFFL + +#define update_crc_16(crc, data) ((crc << 8) ^ crc_16_table[((int)(crc >> 8 ) ^ (data)) & 0xFF]) +#define update_crc_32(crc, data) ((crc << 8) ^ crc_32_table[((int)(crc >> 24) ^ (data)) & 0xFF]) + +extern unsigned short crc_16_table[256]; +extern unsigned long crc_32_table[256]; + +extern void gen_crc_table(void); + +extern unsigned short update_crc_16_block(unsigned short crc, + char *data_block_ptr, + int data_block_size); +extern unsigned long update_crc_32_block(unsigned long crc, + char *data_block_ptr, + int data_block_size); + +#endif diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/cvdv.c linux.19rc3-ac4/drivers/media/video/margi/cvdv.c --- linux.19rc3/drivers/media/video/margi/cvdv.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/cvdv.c 2002-07-29 13:58:41.000000000 +0100 @@ -0,0 +1,1985 @@ +/* + cvdv.c + + Copyright (C) Christian Wolff + Marcus Metzler for convergence integrated media. + + 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. +*/ + + ///////////////////////////////////////////////////////////////////// + // // + // Driver for the Convergence Digital Video decoder card (pci) // + // with L64017, L64021, PCM1723, and Bt864/Bt865 chipset // + // (c) Christian Wolff 19990209 for convergence integrated media // + // // +///////////////////////////////////////////////////////////////////// + +// Convergence CV2300i +#define __NO_VERSION__ + +#include +#include "cvdv.h" +#include "ost/osd.h" +#include "i2c.h" + + ////////////////////// + // global variables // +////////////////////// + +// Our major device number +unsigned int major_device_number; + + +// my little random function for memory test +uint16_t rnd_seed; +uint16_t rnd(uint16_t range) +{ // returns random 0..(range-1) range<=872 + uint32_t b = 75 * (rnd_seed + 1) - 1; + rnd_seed = (uint16_t) (b & 0xFFFF); + return ((b * range) / 0xFFFF) - ((b / 0xFFFF) * range); +} +void rnd_omize(void) +{ + rnd_seed = (uint16_t) jiffies; +} + +static char *cimlogo[] = { +".............................................", +".............................................", +"......................###....................", +".....................#####...................", +".....................######..................", +"..............#......#####...................", +"...........#####....######...................", +".........########...######...................", +"........########....######...................", +".......#########...######....................", +"......########.....######...####.............", +".....#######.......#####...#####.............", +".....######.......######...######............", +"....#######.......######....######...........", +"....######........######....######...........", +"....#####........######......#####...........", +"...######........######......#####...........", +"...#####.........######......######..........", +"...#####.........#####.......######..........", +"...#####........######........#####..........", +"...#####........######.......######..........", +"...#####........#####.........#####..........", +"...#####.......######........######..........", +"...#####.......######........#####...........", +"...######.......####.........#####...........", +"....#####........##.........######...........", +"....######..................######...........", +"....######.................######............", +".....#######..............######.....#####...", +".....########............#######....#######..", +"......#########........########.....#######..", +".......#######################......########.", +"........#####################.......#######..", +"..........#################.........#######..", +"............#############............#####...", +"...............#.#####.................##....", +".............................................", +"............................................." +}; + + ///////////////////////////////////////////// + // // + // Controlling the L64021 MPEG-2 Decoder // + // // +///////////////////////////////////////////// + +int OSDTest(struct cvdv_cards *card) +{ + int i, j, col, x0, y0, x1, y1,aspx; + uint8_t b; + + + if (!card->OSD.open) + return -2; + + OSDQuery(card, &x0, &y0, &x1, &y1, &aspx); + OSDShow(card); + OSDSetColor(card, 0, 0, 0, 0, 0, 0, 0); + OSDSetColor(card, 1, 128, 255, 255, 0, 0, 0); + for ( i = 0; i < cimlogo_width; i++){ + for ( j = 0; j < cimlogo_height; j++){ + b = cimlogo[j][i]; + col = (b == '#') ? 1: 0; + OSDSetPixel(card, x0+i, y0+j, col); + } + } + + return 0; +} + + +void SetVideoSystem(struct cvdv_cards *card) +{ + uint8_t reg; + + // set the hsync and vsync generators in the L64017 according to the video standard + reg = read_indexed_register(card, IIO_VIDEO_CONTROL1); + reg &= ~0x03; + switch (card->videomode) { + case PAL: // 864*625*50Hz = 27MHz, 25fps + I2CWrite(card, card->i2c_addr, CS_CONTROL0, 0x41 | 0x0a); + I2CWrite(card, card->i2c_addr, CS_CONTROL1, 0x04); + I2CWrite(card, card->i2c_addr, CS_SC_AMP, 0x15); + I2CWrite(card, card->i2c_addr, CS_SC_SYNTH0, 0x96); + I2CWrite(card, card->i2c_addr, CS_SC_SYNTH1, 0x15); + I2CWrite(card, card->i2c_addr, CS_SC_SYNTH2, 0x13); + I2CWrite(card, card->i2c_addr, CS_SC_SYNTH3, 0x54); + reg |= VMS_PAL; + break; + case PALN: + I2CWrite(card, card->i2c_addr, CS_CONTROL0, 0xa1 | 0x0a); + I2CWrite(card, card->i2c_addr, CS_CONTROL1, 0x04); + I2CWrite(card, card->i2c_addr, CS_SC_AMP, 0x15); + I2CWrite(card, card->i2c_addr, CS_SC_SYNTH0, 0x96); + I2CWrite(card, card->i2c_addr, CS_SC_SYNTH1, 0x15); + I2CWrite(card, card->i2c_addr, CS_SC_SYNTH2, 0x13); + I2CWrite(card, card->i2c_addr, CS_SC_SYNTH3, 0x54); + reg |= VMS_PAL; + break; + + case PALNc: + I2CWrite(card, card->i2c_addr, CS_CONTROL0, 0x81 | 0x0a); + I2CWrite(card, card->i2c_addr, CS_CONTROL1, 0x04); + I2CWrite(card, card->i2c_addr, CS_SC_AMP, 0x15); + I2CWrite(card, card->i2c_addr, CS_SC_SYNTH0, 0x8c); + I2CWrite(card, card->i2c_addr, CS_SC_SYNTH1, 0x28); + I2CWrite(card, card->i2c_addr, CS_SC_SYNTH2, 0xed); + I2CWrite(card, card->i2c_addr, CS_SC_SYNTH3, 0x43); + reg |= VMS_PAL; + break; + + case NTSC: // 858*525*59.94006Hz = 27MHz, 29.97fps + I2CWrite(card, card->i2c_addr, CS_CONTROL0, 0x01 | 0x0a); + I2CWrite(card, card->i2c_addr, CS_CONTROL1, 0x04); + I2CWrite(card, card->i2c_addr, CS_SC_AMP, 0x1c); + I2CWrite(card, card->i2c_addr, CS_SC_SYNTH0, 0x3e); + I2CWrite(card, card->i2c_addr, CS_SC_SYNTH1, 0xf8); + I2CWrite(card, card->i2c_addr, CS_SC_SYNTH2, 0xe0); + I2CWrite(card, card->i2c_addr, CS_SC_SYNTH3, 0x43); + reg |= VMS_NTSC; + break; + + case PALM: + I2CWrite(card, card->i2c_addr, CS_CONTROL0, 0x01 | 0x0a); + I2CWrite(card, card->i2c_addr, CS_CONTROL1, 0x04); + I2CWrite(card, card->i2c_addr, CS_SC_AMP, 0x15); + I2CWrite(card, card->i2c_addr, CS_SC_SYNTH0, 0x4e); + I2CWrite(card, card->i2c_addr, CS_SC_SYNTH1, 0x4a); + I2CWrite(card, card->i2c_addr, CS_SC_SYNTH2, 0xe1); + I2CWrite(card, card->i2c_addr, CS_SC_SYNTH3, 0x43); + reg |= VMS_PAL; + break; + + case NTSC60: // 857*525*60.010002Hz = 27MHz, 30fps + I2CWrite(card, card->i2c_addr, CS_CONTROL0, 0x21 | 0x0a); + I2CWrite(card, card->i2c_addr, CS_CONTROL1, 0x04); + I2CWrite(card, card->i2c_addr, CS_SC_AMP, 0x1c); + I2CWrite(card, card->i2c_addr, CS_SC_SYNTH0, 0x3e); + I2CWrite(card, card->i2c_addr, CS_SC_SYNTH1, 0xf8); + I2CWrite(card, card->i2c_addr, CS_SC_SYNTH2, 0xe0); + I2CWrite(card, card->i2c_addr, CS_SC_SYNTH3, 0x43); + reg |= VMS_NTSC; + break; + + case PALM60: + I2CWrite(card, card->i2c_addr, CS_CONTROL0, 0x61 | 0x0a); + I2CWrite(card, card->i2c_addr, CS_CONTROL1, 0x04); + I2CWrite(card, card->i2c_addr, CS_SC_AMP, 0x15); + I2CWrite(card, card->i2c_addr, CS_SC_SYNTH0, 0x4e); + I2CWrite(card, card->i2c_addr, CS_SC_SYNTH1, 0x4a); + I2CWrite(card, card->i2c_addr, CS_SC_SYNTH2, 0xe1); + I2CWrite(card, card->i2c_addr, CS_SC_SYNTH3, 0x43); + reg |= VMS_PAL; + break; + + case PAL60: + break; + } + write_indexed_register(card, IIO_VIDEO_CONTROL1, reg); + // set the pixel generators according to the video standard + L64021Setup(card); +} + +int SetVideoAttr(struct cvdv_cards *card, uint16_t vattr) +{ + uint8_t video_compression_mode; + uint8_t tv_system; + uint8_t aspect_ratio; + uint8_t display_mode; + uint8_t line_21_switch_1; + uint8_t line_21_switch_2; + uint8_t source_picture_resolution; + uint8_t source_picture_letterboxed; + uint8_t reserved; + uint8_t film_camera_mode; + uint16_t hsize, vsize; + if (vattr != card->lastvattr) { + video_compression_mode = (vattr >> 14) & 0x03; + tv_system = (vattr >> 12) & 0x03; + aspect_ratio = (vattr >> 10) & 0x03; + display_mode = (vattr >> 8) & 0x03; + line_21_switch_1 = (vattr >> 7) & 0x01; + line_21_switch_2 = (vattr >> 6) & 0x01; + source_picture_resolution = (vattr >> 3) & 0x07; + source_picture_letterboxed = (vattr >> 2) & 0x01; + reserved = (vattr >> 1) & 0x01; + film_camera_mode = (vattr >> 0) & 0x01; + card->videomode = + ((tv_system == 0) ? NTSC : ((tv_system == 1) ? + PAL : PAL)); + SetVideoSystem(card); + hsize = + ((source_picture_resolution == 0) ? 720 + : ((source_picture_resolution == 1) ? 702 : 352)); + vsize = ((source_picture_resolution == 3) + ? ((tv_system == 0) ? 240 : 288) + : ((tv_system == 0) ? 480 : 576)); + if (DecoderOpen + (card, hsize, vsize, ((aspect_ratio) ? 3 : 2), + ((video_compression_mode) ? 0 : 1), + source_picture_letterboxed, tv_system)) { + MDEBUG(0, + ": Video Decoder Open failed: On-card memory insufficient for frame stores\n"); + } + card->lastvattr = vattr; + } else { + MDEBUG(0, + ": Video attribute not set, equal to previous one.\n"); + } + return 0; +} + +int SetAudioAttr(struct cvdv_cards *card, uint16_t aattr) +{ + uint8_t audio_coding_mode; + uint8_t multichannel_extension; + uint8_t audio_type; + uint8_t audio_application_mode; + uint8_t quantization_drc; + uint8_t fs; + uint8_t reserved; + uint8_t num_audio_ch; + if (aattr) { + if (aattr != card->lastaattr) { + audio_coding_mode = (aattr >> 13) & 0x07; + multichannel_extension = (aattr >> 12) & 0x01; + audio_type = (aattr >> 10) & 0x03; + audio_application_mode = (aattr >> 8) & 0x03; + quantization_drc = (aattr >> 6) & 0x03; + fs = (aattr >> 4) & 0x03; + reserved = (aattr >> 3) & 0x01; + num_audio_ch = (aattr >> 0) & 0x07; + switch (audio_coding_mode) { + case 0: // AC-3 + card->setup.audioselect = audio_AC3; + break; + case 2: // MPEG Audio + card->setup.audioselect = audio_MPEG; + break; + case 3: // MPEG Audio with ext. + card->setup.audioselect = audio_MPEG_EXT; + break; + case 4: // Linear Pulse Code Modulation LPCM + card->setup.audioselect = audio_LPCM; + break; + case 6: // DTS + card->setup.audioselect = audio_DTS; + break; + case 7: // SDDS + card->setup.audioselect = audio_SDDS; + break; + } + DecoderPrepareAudio(card); + AudioInit(card, ((fs) ? 96 : 48), + ((audio_application_mode == 2) ? 1 : 0)); + } else { + MDEBUG(0, + ": Audio attribute not set, equal to previous one.\n"); + } + } else { + card->setup.audioselect = audio_none; + DecoderPrepareAudio(card); + } + card->lastaattr = aattr; + return 0; +} + +int Prepare(struct cvdv_cards *card) +{ + int err, h; + struct StreamSetup *setup = &card->setup; + + if (!card->ChannelBuffersAllocated) { + + DecoderStreamReset(card); + if (setup->streamtype == stream_none) { + setup->streamtype = stream_PS; + } + + if (setup->audioselect == audio_none) { + setup->audioselect = audio_MPEG; + } + + DecoderPrepareAudio(card); + AudioMute(card, 1); + DecoderPrepareVideo(card); + VideoSetBackground(card, 1, 0, 0, 0); // black + + switch (setup->streamtype) { + default: + case stream_none: // unknown stream! + MDEBUG(0, + ": Video Decoder Prepare failed: unknown stream type\n"); + return -ENODEV; // not an MPEG stream! + case stream_ES: // Elementary Stream + err = DecoderPrepareES(card); + break; + case stream_PES: // Packetized Elementary Stream + err = DecoderPreparePES(card); + break; + case stream_PS: // MPEG-1 System Stream / MPEG-2 Program Stream + err = DecoderPreparePS(card, -1, 0, 0, 0, 0, 0); + break; + case stream_DVD: // DVD Stream + err = DecoderPreparePS(card, 0, 0, 0, 0, 3, 1); + break; + } + if (err) { // insufficient memory + MDEBUG(0, + ": Video Decoder Prepare failed: no kernel memory, please reboot if possible\n"); + CloseCard(card); + return -ENODEV; + } + } + + // Set up the Video Decoder as we have the stream information + if ((!card->FrameBuffersAllocated) + && (card->ChannelBuffersAllocated) && (card->stream.sh.valid)) { + // Automatic PAL/NTSC-switch according to MPEG-Source + h = card->stream.vsize; + if (h < 480) + h *= 2; // catch quarter sized images + printk(KERN_INFO LOGNAME ": Video mode: %s\n", + ((h == 480) ? "NTSC" : "PAL")); + card->videomode = ((h == 480) ? NTSC : PAL); + SetVideoSystem(card); + // Open the Video Decoder with the parameters retreived from the stream + if ( + (err = + DecoderOpen(card, card->stream.hsize, + card->stream.vsize, + card->stream.sh.aspectratio, + !card->stream.MPEG2, 0, + (card->stream.hsize > 480)))) { // TODO: include vbvbuffersize + MDEBUG(0, + ": Video Decoder Open failed: %s\n", + ((err == 1) ? + "Picture size too big (>1440 pixel wide)" : + "On-card memory insufficient for frame stores")); + CloseCard(card); + return -ENODEV; // picture too big or insufficient memory + } + MDEBUG(1, ": Ready to go\n"); + card->startingV = 1; // tell the card to start playing as soon as ES-buffers are sufficiently full + card->startingA = 1; // tell the card to start playing as soon as ES-buffers are sufficiently full + } + + + return 0; +} + +int SetSCRstart(struct cvdv_cards *card, uint32_t SCR_base) +{ + uint32_t SCR_compare; + uint32_t SCR_compareA; + uint32_t SCR_compareV; + if (card->startingV) { + MDEBUG(0, ": SCR in DVD Pack: 0x%08X\n", + SCR_base); + card->startingV = 0; + card->startingA = 0; + DecoderMaskByte(card, 0x007, 0xD2, 0xD2); // Set 0x010, halt SCR counter + SCR_compare = SCR_base + 000; + if (SCR_base < 900) + SCR_base = 0; + else + SCR_base -= 900; + //DecoderWriteDWord(card,0x009,SCR_base); // Set SCR counter + DecoderWriteByte(card, 0x009, SCR_base & 0xFF); // Set SCR counter + DecoderWriteByte(card, 0x00A, (SCR_base >> 8) & 0xFF); + DecoderWriteByte(card, 0x00B, (SCR_base >> 16) & 0xFF); + DecoderWriteByte(card, 0x00C, (SCR_base >> 24) & 0xFF); + DecoderMaskByte(card, 0x011, 0x03, 0x02); // compare, not capture + MDEBUG(0, ": SCR compare value: 0x%08X\n", + SCR_compare); + //DecoderWriteDWord(card,0x00D,SCR_compare); // Set Compare register + DecoderWriteByte(card, 0x00D, SCR_compare & 0xFF); // Set Compare register + DecoderWriteByte(card, 0x00E, (SCR_compare >> 8) & 0xFF); + DecoderWriteByte(card, 0x00F, (SCR_compare >> 16) & 0xFF); + DecoderWriteByte(card, 0x010, (SCR_compare >> 24) & 0xFF); + //DecoderWriteDWord(card,0x014,SCR_compare); // Set audio compare reg. + DecoderWriteByte(card, 0x014, SCR_compare & 0xFF); // Set audio compare reg. + DecoderWriteByte(card, 0x015, (SCR_compare >> 8) & 0xFF); + DecoderWriteByte(card, 0x016, (SCR_compare >> 16) & 0xFF); + DecoderWriteByte(card, 0x017, (SCR_compare >> 24) & 0xFF); + DecoderSetByte(card, 0x013, 0x03); // Video and Audio start on cmp. + //DecoderSetVideoPanic(card,0,DecoderGetVideoESSize(card)/4); // video panic at 25 percent + VideoSetBackground(card, 1, 0, 0, 0); // black + SCR_base = DecoderReadByte(card, 0x009); + SCR_base = + SCR_base | ((uint32_t) DecoderReadByte(card, 0x00A) << 8); + SCR_base = + SCR_base | ((uint32_t) DecoderReadByte(card, 0x00B) << 16); + SCR_base = + SCR_base | ((uint32_t) DecoderReadByte(card, 0x00C) << 24); + SCR_compareA = DecoderReadByte(card, 0x014); + SCR_compareA = + SCR_compareA | ((uint32_t) DecoderReadByte(card, 0x015) << + 8); + SCR_compareA = + SCR_compareA | ((uint32_t) DecoderReadByte(card, 0x016) << + 16); + SCR_compareA = + SCR_compareA | ((uint32_t) DecoderReadByte(card, 0x017) << + 24); + SCR_compareV = DecoderReadByte(card, 0x00D); + SCR_compareV = + SCR_compareV | ((uint32_t) DecoderReadByte(card, 0x00E) << + 8); + SCR_compareV = + SCR_compareV | ((uint32_t) DecoderReadByte(card, 0x00F) << + 16); + SCR_compareV = + SCR_compareV | ((uint32_t) DecoderReadByte(card, 0x010) << + 24); + if (DecoderReadByte(card, 0x013) & 0x03) + MDEBUG(1,": SCR 0x%08X, videocmp=0x%08X, audiocmp=0x%08X %02X\n", + SCR_base, SCR_compareV, SCR_compareA, + DecoderReadByte(card, 0x013)); + DecoderMaskByte(card, 0x007, 0xD2, 0xC2); // Del 0x010, SCR counter run + } + return 0; +} + +int DecoderWriteBlock(struct cvdv_cards *card, uint8_t * data, int size, + int initial, int setSCR) +{ + //int a,v,as,vs,ap,vp; + int res; + uint32_t SCR_base; + int co = 0; + // uint32_t SCR_compare; + res = 0; + + Prepare(card); + + if (size > 0) { + + if (!card->use_ringA) + MargiSetBuffers(card, NBBUF*CHANNELBUFFERSIZE,0); + + if (card->startingDVDV || card->startingDVDA) + setSCR = 1; + + if (initial) { + DecoderStreamReset(card); + //TODO stop and start channel interface + setSCR = 1; + } + + if (setSCR) { + SCR_base = ParseSCR(data); + SetSCR(card, SCR_base); + } + card->DMAABusy = 0; + while (((res = MargiPushA(card, size, data)) < size) + && co < 1000) { + data+=res; + size-=res; + co++; + MDEBUG(2, + ": DecoderWriteBlock - buffers only filled with %d instead of %d bytes\n",res, size); + if (card->DMAABusy){ + interruptible_sleep_on(&card->wqA); + } + } + + if (card->startingDVDV) { + card->startingDVDV = 0; + card->startingV = 1; + DecoderStartDecode(card); + } + if (card->startingDVDA) { + card->startingDVDA = 0; + card->startingA = 1; + AudioSetPlayMode(card, MAUDIO_PLAY); + } + } + return 0; +} + + + + + + ////////////////////////////// + // // + // Char Device Procedures // + // // +////////////////////////////// +static long margi_write(struct cvdv_cards *card, const char *data, + unsigned long count, int nonblock) +{ + + int res; + long int out=0; + int free; + + free = ring_write_rest(&(card->rbufA)); + + if (card != NULL) { + card->nonblock = nonblock; + if (count > 0) { // Do we have data? + if ((res = Prepare(card))) + return res; + if (!card->use_ringA) + MargiSetBuffers(card, NBBUF*CHANNELBUFFERSIZE, + 0); + if (!nonblock && + !wait_event_interruptible( + card->wqA, + ring_write_rest(&(card->rbufA)) >count )){ + + out = MargiPushA(card, count, + data); + } else { + out = MargiPushA(card, count, data); + } + } + return out; + } else { + MDEBUG(0, + ": Video Decoder Prepare failed: device with this minor number not found\n"); + return -ENODEV; // device with this minor number not found + } +} + + +static long margi_write_audio(struct cvdv_cards *card, const char *data, + unsigned long count, int nonblock) +{ + struct StreamSetup *setup = &card->setup; + + int res; + long int out=0; + int free; + + free = ring_write_rest(&(card->rbufB)); + + if (card != NULL) { + card->nonblock = nonblock; + + if (count > 0) { // Do we have data? + if ((res = Prepare(card))) + return res; + if ((setup->streamtype == stream_ES) + || (setup->streamtype == stream_PES)){ + if (!card->use_ringB) + MargiSetBuffers(card, NBBUF* + CHANNELBUFFERSIZE,1); + if (!nonblock && + !wait_event_interruptible( + card->wqB, + ring_write_rest(&(card->rbufB)) + > count)){ + out = MargiPushB(card, count, + data); + } else { + out = MargiPushB(card, count, data); + } + } + } + return out; + } else { + MDEBUG(0, + ": Video Decoder Prepare failed: device with this minor number not found\n"); + return -ENODEV; // device with this minor number not found + } +} + +void pes_write(uint8_t *buf, int count, void *priv) +{ + struct cvdv_cards *card = (struct cvdv_cards *) priv; + + margi_write(card, buf, count, 0); +} + + +static ssize_t PSwrite(struct file *file, const char *data, size_t count, + loff_t * offset) +{ + struct cvdv_cards *card = + minorlist[MINOR(file->f_dentry->d_inode->i_rdev) % MAXDEV]; // minor number modulo 16 + return margi_write(card, data, count, file->f_flags&O_NONBLOCK); +} + +static unsigned int PSpoll(struct file *file, poll_table * table) +{ + struct cvdv_cards *card = + minorlist[MINOR(file->f_dentry->d_inode->i_rdev) % MAXDEV]; // minor number modulo 16 + if (card != NULL) { + poll_wait(file, &card->wqA , table); + if ( !card->rbufA.buffy || ring_write_rest(&(card->rbufA)) ) + return (POLLOUT | POLLWRNORM); + else { + return 0; + } + } else + return POLLERR; +} + +static unsigned int poll_audio(struct file *file, poll_table * table) +{ + struct cvdv_cards *card = + minorlist[MINOR(file->f_dentry->d_inode->i_rdev) % MAXDEV]; // minor number modulo 16 + if (card != NULL) { + poll_wait(file, &card->wqB, table); + if ( !card->rbufB.buffy || ring_write_rest(&(card->rbufB)) ) + return (POLLOUT | POLLWRNORM); + else { + return 0; + } + } else + return POLLERR; +} + +static int +OSD_DrawCommand(struct cvdv_cards *card,osd_cmd_t *dc) +{ + + switch (dc->cmd) { + case OSD_Close: + MDEBUG(1,": OSD Close\n"); + return OSDClose(card); + case OSD_Open: // Open(x0,y0,x1,y1,BitPerPixel(2/4/8),mix(0..15)) + return OSDOpen(card, dc->x0, + dc->y0, dc->x1, + dc->y1, + dc->color & 0x0F, + (dc->color >> 4) & + 0x0F); + case OSD_Show: + return OSDShow(card); + case OSD_Hide: + return OSDHide(card); + case OSD_Clear: + return OSDClear(card); + case OSD_Fill: // Fill(color) + return OSDFill(card, dc->color); + case OSD_SetColor: // SetColor(color,R(x0),G(y0),B(x1),opacity(y1)) + return (OSDSetColor + (card, dc->color, dc->x0, + dc->y0, dc->x1, 0, + (dc->y1 != 255), + (dc->y1 == 0)) >= 0); + case OSD_SetPalette:// SetPalette(firstcolor{color},lastcolor{x0},data) + return OSDSetPalette(card, + dc->color, + dc->x0, (uint8_t *) + dc->data); + case OSD_SetTrans: // SetTrans(transparency{color}) + return OSDSetTrans(card, + (dc->color >> 4) + & 0x0F); + case OSD_SetPixel: // SetPixel(x0,y0,color) + return OSDSetPixel(card, dc->x0, + dc->y0, + dc->color); + case OSD_GetPixel: // GetPixel(x0,y0); + return OSDGetPixel(card, dc->x0, + dc->y0); + case OSD_SetRow: // SetRow(x0,y0,x1,(uint8_t*)data) + return OSDSetRow(card, dc->x0, + dc->y0, dc->x1, + (uint8_t *) dc->data); + case OSD_SetBlock: // SetBlock(x0,y0,x1,y1,(uint8_t*)data) + return OSDSetBlock(card, dc->x0, + dc->y0, dc->x1, + dc->y1, + dc->color, + (uint8_t *) + dc->data); + case OSD_FillRow: // FillRow(x0,y0,x1,color) + return OSDFillRow(card, dc->x0, + dc->y0, dc->x1, + dc->color); + case OSD_FillBlock: // FillRow(x0,y0,x1,y1,color) + return OSDFillBlock(card, dc->x0, + dc->y0, dc->x1, + dc->y1, + dc->color); + case OSD_Line: // Line(x0,y0,x1,y1,color); + return OSDLine(card, dc->x0, + dc->y0, dc->x1, + dc->y1, dc->color); + case OSD_Query: // Query(x0,y0,x1,y1,aspect(color:11) + return OSDQuery(card, &dc->x0, + &dc->y0, &dc->x1, + &dc->y1, + &dc->color); + case OSD_Test: + return OSDTest(card); + default: + return -EINVAL; + } +} + + +static int PSioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct cvdv_cards *card = minorlist[MINOR(inode->i_rdev) % MAXDEV]; // minor number modulo 16 + osd_cmd_t *dc; + struct decodercmd *command; + uint16_t attr; + + if (card != NULL) { + if (_IOC_TYPE(cmd) == CVDV_IOCTL_MAGIC) + switch (_IOC_NR(cmd)) { + case IOCTL_DRAW: // Drawing commands + dc = (osd_cmd_t *) arg; + return OSD_DrawCommand(card,dc); + break; + case IOCTL_DECODER: + command = (struct decodercmd *) arg; + switch (command->cmd) { + + case Decoder_CSS: + /* + return DecoderCSS(card, + command->param1, + command->data1); + */ + break; + + case Decoder_Set_Videosystem: + MDEBUG(1,": -- Decoder_Set_Videosystem\n"); + card->videomode = + (videosystem) command->param1; + SetVideoSystem(card); + return 0; + break; + + case Decoder_Set_Streamtype: + MDEBUG(1,": -- Decoder_Set_Streamtype\n"); + card->setup.streamtype = + (stream_type) command->param1; + return 0; + break; + + case Decoder_Set_Audiotype: + MDEBUG(1,": -- Decoder_Set_Audiotype\n"); + card->setup.audioselect = + (audio_type) command->param1; + DecoderPrepareAudio(card); + return 0; + break; + + case Decoder_Set_VideoStreamID: + MDEBUG(1,": -- Decoder_Set_VideoStreamID\n"); + card->setup.videoID = + command->param1; + DecoderPrepareVideo(card); + return 0; + break; + + case Decoder_Set_AudioStreamID: + MDEBUG(1,": -- Decoder_Set_AudioStreamID 0x%02X 0x%02X\n", + command->param1,command->param2); + card->setup.audioID = + command->param1; + card->setup.audioIDext = + command->param2; + attr = card->lastaattr; + DecoderSelectAudioID(card); + card->lastaattr = attr; + return 0; + break; + + case Decoder_Still_Put: + return DecoderShowStill(card, + command-> + param1, + command-> + param2, + command-> + data1, + command-> + data2); + break; + + case Decoder_Still_Get: + return DecoderGetStill(card, + &command-> + param1, + &command-> + param2, + command-> + data1, + command-> + data2); + break; + + case Decoder_Pause: // pause{param1} 0=run 1=pause 2=toggle + if (command->param1 == 2) { + if (card->paused) + DecoderUnPause + (card); + else + DecoderPause(card); + } else { + if (!command->param1) + DecoderUnPause + (card); + else + DecoderPause(card); + } + return 0; + + /* Too buggy + case Decoder_FFWD: // pause{param1} =normal 1=ffwd 2=toggle + if (command->param1 == 2) { + if (card->videoffwd) + card->videoffwd = 0; + else + card->videoffwd = 3; + } else { + if (!command->param1) + card->videoffwd = 0; + else + card->videoffwd = 3; + } + return 0; + + case Decoder_Slow: // pause{param1} =normal 1=slow 2=toggle + if (command->param1 == 2) { + if (card->videoslow) + card->videoslow = 0; + else + card->videoslow = 4; + } else { + if (!command->param1) + card->videoslow = 0; + else + card->videoslow = 4; + } + return 0; + */ + case Decoder_Highlight: // active{param1}, color information(SL_COLI or AC_COLI){data1[4]}, button position(BTN_POSI){data2[6]} + return DecoderHighlight(card, + command-> + param1, + command-> + data1, + command-> + data2); + case Decoder_SPU: // stream{param1}, active{param2} + return DecoderSPUStream(card, + command-> + param1, + command-> + param2); + case Decoder_SPU_Palette: // length{param1}, palette{data1} + return DecoderSPUPalette(card, + command-> + param1, + command-> + data1); + case Decoder_GetNavi: // data1 will be filled with PCI or DSI pack, and 1024 will be returned + return DecoderGetNavi(card, + command-> + data1); + case Decoder_SetKaraoke: // Vocal1{param1}, Vocal2{param2}, Melody{param3} + return DecoderKaraoke(card, + command-> + param1, + command-> + param2, + command-> + param3); + case Decoder_Set_Videoattribute: + MDEBUG(1,": -- Decoder_Set_Videoattribute\n"); + if (!card->ChannelBuffersAllocated) { + DecoderStreamReset(card); + MargiFlush(card); + + card->setup.streamtype = + stream_DVD; + card->setup.videoID = 0; + DecoderPrepareVideo(card); + DecoderPreparePS(card, 0, + 0, 2, 2, + 3, 1); + } + + SetVideoAttr(card, + command->param1); + card->startingDVDV = 1; +// tell the card to start playing as soon as ES-buffers are sufficiently full + return 0; + case Decoder_Set_Audioattribute: + MDEBUG(1,": -- Decoder_Set_Audioattribute\n"); + SetAudioAttr(card, + command->param1); + card->startingDVDA = + ((card->setup.audioselect != + audio_none) + && (card->setup.audioselect != audio_disable)); // tell the card to start playing as soon as ES-buffers are sufficiently full + return 0; + case Decoder_WriteBlock: // DVD-Sector{data1}, sectorsize{param1{2048}}, initialsector{param2{bool}}, set_SCR{param3} + return DecoderWriteBlock(card, + command-> + data1, + command-> + param1, + command-> + param2, + command-> + param3); + default: + return -EINVAL; + } + default: + return -EINVAL; + } else + return -EINVAL; + } else { + MDEBUG(0, + ": Video Decoder Prepare failed: device with this minor number not found\n"); + return -ENODEV; // device with this minor number not found + } +} + + +static int PSmmap(struct file *file, struct vm_area_struct *vm) +{ + return -ENODEV; +} + + + +static int margi_open(struct cvdv_cards *card, int flags) +{ + int closed; + + printk("Open card = %p\n", card); + + if (card != NULL) { + MDEBUG(1, ": -- open \n"); + CloseCard(card); + OSDClose(card); + + printk("Card and OSD closed.\n"); +#ifdef NOINT + card->timer.function = Timerfunction; + card->timer.data=(unsigned long) card; + card->timer.expires=jiffies+1; + add_timer(&card->timer); +#endif + printk("Timer added.\n"); + + if (card->open) + MDEBUG(0,": PSopen - already open\n"); + closed = 1; + if (card->open) + closed = 0; + if (closed) { // first open() for this card? + printk("Freeing buffers.\n"); + MargiFreeBuffers(card); + printk("Fade to black.\n"); + VideoSetBackground(card, 1, 0, 0, 0); // black + } + printk("Go\n"); + card->open++; + return 0; + } else { + MDEBUG(0, + ": Video Decoder Prepare failed: device with this minor number not found\n"); + return -ENODEV; // device with this minor number not found + } + +} + + +static int PSopen(struct inode *inode, struct file *file) +{ + struct cvdv_cards *card = minorlist[MINOR(inode->i_rdev) % MAXDEV]; +#ifdef DVB + if(card) + card->audiostate.AVSyncState=true; +#endif + return margi_open(card, file->f_flags); +} + + +static int all_margi_close(struct cvdv_cards *card) +{ + + if (card != NULL) { + MDEBUG(1, ": -- PSrelease\n"); + if (card->open <= 0) + MDEBUG(1,": PSrelease - not open\n"); + card->open--; + + if (!card->open) { + MDEBUG(1,": PSrelease - last close\n"); + CloseCard(card); // close immediately + } + return 0; + } else { + MDEBUG(0,": Video Decoder Prepare failed:\n"); + return -ENODEV; // device with this minor number not found + } + +} + +static int PSrelease(struct inode *inode, struct file *file) +{ + struct cvdv_cards *card = minorlist[MINOR(inode->i_rdev) % MAXDEV]; // minor number modulo 16 + return all_margi_close(card); +} + + ////////////////////////// + // // + // Char Device Hookup // + // // +////////////////////////// + +// Hookups for a write-only device, that accepts MPEG-2 Program Stream +struct file_operations cvdv_fileops = { + owner: THIS_MODULE, + write: PSwrite, + poll: PSpoll, + ioctl: PSioctl, + mmap: PSmmap, + open: PSopen, + release: PSrelease, +}; + + +#ifdef DVB + +static inline int +num2type(struct cvdv_cards *card, int num) +{ + if (!card->dvb_devs) + return -2; + if (num>=card->dvb_devs->num) + return -2; + return card->dvb_devs->tab[num]; +} + +static int +dvbdev_open(struct dvb_device *dvbdev, int num, + struct inode *inode, struct file *file) +{ + struct cvdv_cards *card=(struct cvdv_cards *) dvbdev->priv; + int type=num2type(card, num); + int ret=0; + + if (type<0) + return -EINVAL; + + if (card->users[num] >= card->dvb_devs->max_users[num]) + return -EBUSY; + + if ((file->f_flags&O_ACCMODE)!=O_RDONLY) + if (card->writers[num] >= card->dvb_devs->max_writers[num]) + return -EBUSY; + + switch (type) { + case DVB_DEVICE_VIDEO_0: + card->video_blank=true; + card->audiostate.AVSyncState=true; + card->videostate.streamSource=VIDEO_SOURCE_DEMUX; + margi_open(card, file->f_flags); + break; + + case DVB_DEVICE_AUDIO_0: + card->audiostate.AVSyncState=true; + card->audiostate.streamSource=AUDIO_SOURCE_DEMUX; + break; + + case DVB_DEVICE_DEMUX_0: + if ((file->f_flags&O_ACCMODE)!=O_RDWR) + return -EINVAL; + ret=DmxDevFilterAlloc(&card->dmxdev, file); + break; + + case DVB_DEVICE_DVR_0: + card->audiostate.AVSyncState=true; + card->setup.streamtype = stream_PES; + margi_open(card, file->f_flags); + ret=DmxDevDVROpen(&card->dmxdev, file); + break; + + case DVB_DEVICE_OSD_0: + break; + default: + return -EINVAL; + } + if (ret<0) + return ret; + if ((file->f_flags&O_ACCMODE)!=O_RDONLY) + card->writers[num]++; + card->users[num]++; + return ret; +} + +static int +dvbdev_close(struct dvb_device *dvbdev, int num, + struct inode *inode, struct file *file) +{ + struct cvdv_cards *card=(struct cvdv_cards *) dvbdev->priv; + int type=num2type(card, num); + int ret=0; + + if (type<0) + return -EINVAL; + + switch (type) { + case DVB_DEVICE_VIDEO_0: + case DVB_DEVICE_AUDIO_0: + if (card->open) + all_margi_close(card); + break; + + case DVB_DEVICE_DEMUX_0: + ret=DmxDevFilterFree(&card->dmxdev, file); + break; + + case DVB_DEVICE_DVR_0: + ret=DmxDevDVRClose(&card->dmxdev, file); + if (card->open) + all_margi_close(card); + break; + case DVB_DEVICE_OSD_0: + break; + default: + return -EINVAL; + } + if (ret<0) + return ret; + if ((file->f_flags&O_ACCMODE)!=O_RDONLY) + card->writers[num]--; + card->users[num]--; + return ret; +} + + +static ssize_t +dvbdev_write(struct dvb_device *dvbdev, int num, + struct file *file, + const char *buf, size_t count, loff_t *ppos) +{ + struct cvdv_cards *card=(struct cvdv_cards *) dvbdev->priv; + int type=num2type(card, num); + + switch (type) { + case DVB_DEVICE_VIDEO_0: + if (card->videostate.streamSource!=VIDEO_SOURCE_MEMORY) + return -EPERM; + return margi_write(card, buf, count, + file->f_flags&O_NONBLOCK); + + case DVB_DEVICE_AUDIO_0: + if (card->audiostate.streamSource!=AUDIO_SOURCE_MEMORY) + return -EPERM; + if ( card->setup.streamtype != stream_PES ) + return -EPERM; + + return margi_write_audio(card, buf, count, + file->f_flags&O_NONBLOCK); + + case DVB_DEVICE_DVR_0: + return DmxDevDVRWrite(&card->dmxdev, file, buf, count, ppos); + default: + return -EOPNOTSUPP; + } + return 0; +} + +static ssize_t +dvbdev_read(struct dvb_device *dvbdev, int num, + struct file *file, char *buf, size_t count, loff_t *ppos) +{ + struct cvdv_cards *card=(struct cvdv_cards *) dvbdev->priv; + int type=num2type(card, num); + + switch (type) { + case DVB_DEVICE_VIDEO_0: + break; + case DVB_DEVICE_AUDIO_0: + break; + case DVB_DEVICE_DEMUX_0: + return DmxDevRead(&card->dmxdev, file, buf, count, ppos); + case DVB_DEVICE_DVR_0: + return DmxDevDVRRead(&card->dmxdev, file, buf, count, ppos); + case DVB_DEVICE_CA_0: + break; + default: + return -EOPNOTSUPP; + } + return 0; +} + + + + +static int +dvbdev_ioctl(struct dvb_device *dvbdev, int num, + struct file *file, unsigned int cmd, unsigned long arg) +{ + struct cvdv_cards *card=(struct cvdv_cards *) dvbdev->priv; + void *parg=(void *)arg; + int type=num2type(card, num); + uint16_t attr; + + switch (type) { + case DVB_DEVICE_VIDEO_0: + if (((file->f_flags&O_ACCMODE)==O_RDONLY) && + (cmd!=VIDEO_GET_STATUS)) + return -EPERM; + + switch (cmd) { + + case VIDEO_STOP: + DecoderPause(card); + card->videostate.playState = VIDEO_STOPPED; + if (card->videostate.videoBlank) + VideoSetBackground(card, 1, 0, 0, 0); + + + return 0; + + case VIDEO_PLAY: + + if (card->videostate.streamSource== + VIDEO_SOURCE_MEMORY) { + if (card->videostate.playState==VIDEO_FREEZED){ + DecoderUnPause(card); + } else { + DecoderUnPause(card); + } + } + break; + + case VIDEO_FREEZE: + DecoderPause(card); + break; + + case VIDEO_CONTINUE: + if (card->videostate.playState==VIDEO_FREEZED) { + DecoderUnPause(card); + } + break; + + case VIDEO_SELECT_SOURCE: + card->videostate.streamSource=(videoStreamSource_t) arg; + break; + + case VIDEO_SET_BLANK: + card->videostate.videoBlank=(boolean) arg; + break; + + case VIDEO_GET_STATUS: + if(copy_to_user(parg, &card->videostate, + sizeof(struct videoStatus))) + return -EFAULT; + break; + + case VIDEO_GET_EVENT: + return -EOPNOTSUPP; + + case VIDEO_SET_DISPLAY_FORMAT: + { + videoDisplayFormat_t format=(videoDisplayFormat_t) arg; + uint16_t val=0; + + switch(format) { + case VIDEO_PAN_SCAN: + val=VID_PAN_SCAN_PREF; + break; + + case VIDEO_LETTER_BOX: + val=VID_VC_AND_PS_PREF; + break; + + case VIDEO_CENTER_CUT_OUT: + val=VID_CENTRE_CUT_PREF; + break; + + default: + return -EINVAL; + } + + card->videostate.videoFormat=format; + return 0; + } + + case VIDEO_STILLPICTURE: + { + struct videoDisplayStillPicture pic; + + if(copy_from_user(&pic, parg, + sizeof(struct videoDisplayStillPicture))) + return -EFAULT; + + break; + } + + case VIDEO_FAST_FORWARD: + if (card->videostate.streamSource != + VIDEO_SOURCE_MEMORY) + return -EPERM; + card->videoffwd = 3; + break; + + case VIDEO_SLOWMOTION: + if (card->videostate.streamSource!=VIDEO_SOURCE_MEMORY) + return -EPERM; + card->videoslow = arg; + + break; + + case VIDEO_GET_CAPABILITIES: + { + int cap=VIDEO_CAP_MPEG1| + VIDEO_CAP_MPEG2| + VIDEO_CAP_SYS| + VIDEO_CAP_PROG| + VIDEO_CAP_SPU| + VIDEO_CAP_NAVI| + VIDEO_CAP_CSS; + + + if (copy_to_user(parg, &cap, + sizeof(cap))) + return -EFAULT; + break; + } + + case VIDEO_SET_STREAMTYPE: + { + int f = -1; + switch(arg){ + case VIDEO_CAP_MPEG1: + case VIDEO_CAP_MPEG2: + f = stream_PES; + break; + + case VIDEO_CAP_SYS: + case VIDEO_CAP_PROG: + f = stream_PS; + break; + + case VIDEO_CAP_SPU: + case VIDEO_CAP_NAVI: + case VIDEO_CAP_CSS: + f = stream_DVD; + } + card->setup.streamtype = f; + + } + break; + + case VIDEO_SET_ID: + card->setup.videoID = arg; + DecoderPrepareVideo(card); + break; + + case VIDEO_SET_SYSTEM: + card->videomode = (videosystem) arg; + SetVideoSystem(card); + break; + + case VIDEO_SET_HIGHLIGHT: + { + uint8_t data1[4]; + uint8_t data2[6]; + videoHighlight_t vh; + + if(copy_from_user(&vh, parg, sizeof(videoHighlight_t))) + return -EFAULT; + + data1[0] = vh.contrast1; + data1[1] = vh.contrast2; + data1[2] = vh.color1; + data1[3] = vh.color2; + data2[0] = vh.ypos & 0xFF; + data2[1] = (uint8_t) ((vh.ypos >> 1) & 0xFF); + data2[2] = (uint8_t) ((vh.ypos >> 2) & 0xFF); + data2[3] = vh.xpos & 0xFF; + data2[4] = (uint8_t) ((vh.xpos >> 1) & 0xFF); + data2[5] = (uint8_t) ((vh.xpos >> 2) & 0xFF); + return DecoderHighlight(card, vh.active, data1, data2); + break; + } + + case VIDEO_SET_SPU: + { + videoSPU_t spu; + + if(copy_from_user(&spu, parg, sizeof(videoSPU_t))) + return -EFAULT; + + return DecoderSPUStream(card, spu.streamID, spu.active); + break; + } + + case VIDEO_SET_SPU_PALETTE: + { + videoSPUPalette_t spup; + + if(copy_from_user(&spup, parg, sizeof(videoSPUPalette_t))) + return -EFAULT; + + return DecoderSPUPalette(card, spup.length, spup.palette); + break; + } + + case VIDEO_GET_NAVI: + { + videoNaviPack_t navi; + + navi.length = DecoderGetNavi(card, (u8 *)&(navi.data)); + if(copy_to_user(parg, &navi, sizeof(videoNaviPack_t))) + return -EFAULT; + } + break; + + case VIDEO_SET_ATTRIBUTES: + { + if (!card->ChannelBuffersAllocated) { + DecoderStreamReset(card); + MargiFlush(card); + + card->setup.streamtype = stream_DVD; + card->setup.videoID = 0; + DecoderPrepareVideo(card); + DecoderPreparePS(card, 0, 0, 2, 2, 3, 1); + } + + SetVideoAttr(card, arg); + card->startingDVDV = 1; + } + break; + + default: + return -ENOIOCTLCMD; + } + return 0; + + case DVB_DEVICE_AUDIO_0: + if (((file->f_flags&O_ACCMODE)==O_RDONLY) && + (cmd!=AUDIO_GET_STATUS)) + return -EPERM; + + switch (cmd) { + + case AUDIO_STOP: + if (card->audiostate.streamSource!=AUDIO_SOURCE_MEMORY) + break; + AudioStopDecode(card); + card->audiostate.playState=AUDIO_STOPPED; + break; + + case AUDIO_PLAY: + if (card->audiostate.streamSource!=AUDIO_SOURCE_MEMORY) + break; + AudioSetPlayMode(card, MAUDIO_PLAY); + card->audiostate.playState=AUDIO_PLAYING; + break; + + case AUDIO_PAUSE: + card->audiostate.playState=AUDIO_PAUSED; + AudioSetPlayMode(card, MAUDIO_PAUSE); + break; + + case AUDIO_CONTINUE: + if (card->audiostate.playState==AUDIO_PAUSED) { + card->audiostate.playState=AUDIO_PLAYING; + AudioSetPlayMode(card, MAUDIO_PLAY); + } + break; + + case AUDIO_SELECT_SOURCE: + card->audiostate.streamSource= + (audioStreamSource_t) arg; + break; + + case AUDIO_SET_MUTE: + { + AudioMute(card, arg); + card->audiostate.muteState=(boolean) arg; + break; + } + + case AUDIO_SET_AV_SYNC: + card->videosync=(boolean) arg; + card->audiostate.AVSyncState=(boolean) arg; + break; + + case AUDIO_SET_BYPASS_MODE: + return -EINVAL; + + case AUDIO_CHANNEL_SELECT: + card->audiostate.channelSelect=(audioChannelSelect_t) arg; + + switch(card->audiostate.channelSelect) { + case AUDIO_STEREO: + break; + + case AUDIO_MONO_LEFT: + break; + + case AUDIO_MONO_RIGHT: + break; + + default: + return -EINVAL; + } + return 0; + + case AUDIO_GET_STATUS: + if(copy_to_user(parg, &card->audiostate, + sizeof(struct audioStatus))) + return -EFAULT; + break; + + case AUDIO_GET_CAPABILITIES: + { + int cap=AUDIO_CAP_LPCM| + AUDIO_CAP_MP1| + AUDIO_CAP_MP2| + AUDIO_CAP_AC3; + + if (copy_to_user(parg, &cap, + sizeof(cap))) + return -EFAULT; + } + break; + + + case AUDIO_SET_STREAMTYPE: + { + int f = -1; + + switch(arg){ + case AUDIO_CAP_DTS: + case AUDIO_CAP_MP3: + case AUDIO_CAP_AAC: + case AUDIO_CAP_SDDS: + case AUDIO_CAP_OGG: + f = audio_none; + break; + + case AUDIO_CAP_LPCM: + f = audio_LPCM; + break; + + case AUDIO_CAP_MP1: + case AUDIO_CAP_MP2: + f = audio_MPEG; + break; + + case AUDIO_CAP_AC3: + f = audio_AC3; + break; + } + + card->setup.audioselect = (audio_type) f; + DecoderPrepareAudio(card); + break; + } + + case AUDIO_SET_ID: + if (arg < 0 || arg >32) arg = 0; + card->setup.audioID = arg; + arg = 0; + case AUDIO_SET_EXT_ID: + if (arg < 0 || arg >32) arg = 0; + card->setup.audioIDext = arg; + + attr = card->lastaattr; + DecoderSelectAudioID(card); + card->lastaattr = attr; + break; + + case AUDIO_SET_MIXER: + return -EINVAL; + + case AUDIO_SET_ATTRIBUTES: + SetAudioAttr(card,arg); + card->startingDVDA = ((card->setup.audioselect != audio_none) + && (card->setup.audioselect != + audio_disable)); + break; + + + case AUDIO_SET_KARAOKE: + { + break; + } + + default: + return -ENOIOCTLCMD; + } + break; + + case DVB_DEVICE_DEMUX_0: + return DmxDevIoctl(&card->dmxdev, file, cmd, arg); + break; + + case DVB_DEVICE_OSD_0: + { + switch (cmd) { + case OSD_SEND_CMD: + { + osd_cmd_t doc; + + if(copy_from_user(&doc, parg, + sizeof(osd_cmd_t))) + return -EFAULT; + return OSD_DrawCommand(card, &doc); + } + default: + return -EINVAL; + } + break; + } + default: + return -EOPNOTSUPP; + } + return 0; +} + +static unsigned int +dvbdev_poll(struct dvb_device *dvbdev, int num, + struct file *file, poll_table * wait) +{ + struct cvdv_cards *card=(struct cvdv_cards *) dvbdev->priv; + int type=num2type(card, num); + + switch (type) { + case DVB_DEVICE_DEMUX_0: + return DmxDevPoll(&card->dmxdev, file, wait); + + case DVB_DEVICE_VIDEO_0: + return PSpoll(file, wait); + + case DVB_DEVICE_AUDIO_0: + return poll_audio(file, wait); + + case DVB_DEVICE_CA_0: + break; + + default: + return -EOPNOTSUPP; + } + + return 0; +} + + +static int +dvbdev_device_type(struct dvb_device *dvbdev, unsigned int num) +{ + struct cvdv_cards *card=(struct cvdv_cards *) dvbdev->priv; + + return num2type(card, num); +} +#endif + +/****************************************************************************** + * driver registration + ******************************************************************************/ + + +#ifdef DVB + +#define INFU 32768 + + + +static dvb_devs_t mdvb_devs = { + 9, + { + DVB_DEVICE_VIDEO_0, DVB_DEVICE_AUDIO_0, + -1, -1, + DVB_DEVICE_DEMUX_0, DVB_DEVICE_DVR_0, + -1, -1, + DVB_DEVICE_OSD_0, + }, + { INFU, INFU, INFU, INFU, INFU, 1, 1, INFU, 1 }, + { 1, 1, 1, 1, INFU, 1, 1, 1, 1} +}; + + +static int +dvb_start_feed(dvb_demux_feed_t *dvbdmxfeed) +{ + dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + struct cvdv_cards * card = (struct cvdv_cards *)dvbdmx->priv; + + if (!dvbdmx->dmx.frontend || !card) + return -EINVAL; + + if (dvbdmxfeed->type == DMX_TYPE_TS) { + if ((dvbdmxfeed->ts_type & TS_DECODER) + && (dvbdmxfeed->pes_typedmx.frontend->source) { + case DMX_MEMORY_FE: + if (dvbdmxfeed->ts_type & TS_DECODER) + if (dvbdmxfeed->pes_type<2 && + dvbdmx->pids[0]!=0xffff && + dvbdmx->pids[1]!=0xffff) { + + setup_ts2pes( &card->tsa, + &card->tsv, + dvbdmx->pids, + dvbdmx->pids+1, + pes_write, + (void *)card); + + dvbdmx->playing=1; + } + break; + default: + return -EINVAL; + break; + } + } + } + + if (dvbdmxfeed->type == DMX_TYPE_SEC) { + int i; + + for (i=0; ifilternum; i++) { + if (dvbdmx->filter[i].state!=DMX_STATE_READY) + continue; + if (dvbdmx->filter[i].type!=DMX_TYPE_SEC) + continue; + if (dvbdmx->filter[i].filter.parent!= + &dvbdmxfeed->feed.sec) + continue; + + dvbdmxfeed->feed.sec.is_filtering=1; + dvbdmx->filter[i].state=DMX_STATE_GO; + } + } + + return 0; +} + + +static int +dvb_stop_feed(dvb_demux_feed_t *dvbdmxfeed) +{ + dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + struct cvdv_cards * card = (struct cvdv_cards *)dvbdmx->priv; + if (!card) + return -EINVAL; + + if (dvbdmxfeed->type == DMX_TYPE_TS) { + if ((dvbdmxfeed->ts_type & TS_DECODER) + && (dvbdmxfeed->pes_type<=1)) { + if (dvbdmx->playing) { + free_ipack(&card->tsa); + free_ipack(&card->tsv); + DecoderPause(card); + dvbdmx->playing=0; + } + } + + } + if (dvbdmxfeed->type == DMX_TYPE_SEC) { + int i; + + for (i=0; ifilternum; i++) + if (dvbdmx->filter[i].state==DMX_STATE_GO && + dvbdmx->filter[i].filter.parent== + &dvbdmxfeed->feed.sec) { + dvbdmx->filter[i].state=DMX_STATE_READY; + } + + } + return 0; +} + +static uint16_t get_pid(uint8_t *pid) +{ + uint16_t pp = 0; + + pp = (pid[0] & PID_MASK_HI)<<8; + pp |= pid[1]; + + return pp; +} + + +static int +dvb_write_to_decoder(dvb_demux_feed_t *dvbdmxfeed, uint8_t *buf, size_t count) +{ + dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + struct cvdv_cards * card = (struct cvdv_cards *)dvbdmx->priv; + uint16_t pid = 0; + int off = 0; + + ipack *p; + + if (!card) + return -EINVAL; + + pid = get_pid(buf+1); + + if (pid == *(card->tsa.pid)) p = &(card->tsa); + else if (pid == *(card->tsv.pid)) p = &(card->tsv); + else return 0; + + if (dvbdmxfeed->pes_type>1) + return -1; + if (!(buf[3]&0x10)) // no payload? + return -1; + + if (count != TS_SIZE) return -1; + + if ( buf[3] & ADAPT_FIELD) { // adaptation field? + off = buf[4] + 1; + } + + + if (pid == *(card->tsa.pid)){ + MDEBUG(0,"AUDIO count: %d off: %d\n",count,off); + margi_write_audio(card, buf+off+4, TS_SIZE-4-off, 0); + } else { + MDEBUG(0,"VIDEO count: %d off: %d\n",count,off); + margi_write(card, buf+off+4, TS_SIZE-4-off, 0); + } + +// ts_to_pes( p, buf); // don't need count (=188) + return 0; +} + +int dvb_register(struct cvdv_cards *card) +{ + int i,ret; + struct dvb_device *dvbd=&card->dvb_dev; + + dvb_demux_t *dvbdemux = (dvb_demux_t *)&card->demux; + + if (card->dvb_registered) + return -1; + card->dvb_registered=1; + + card->audiostate.AVSyncState=0; + card->audiostate.muteState=0; + card->audiostate.playState=AUDIO_STOPPED; + card->audiostate.streamSource=AUDIO_SOURCE_MEMORY; + card->audiostate.channelSelect=AUDIO_STEREO; + card->audiostate.bypassMode=0; + + card->videostate.videoBlank=0; + card->videostate.playState=VIDEO_STOPPED; + card->videostate.streamSource=VIDEO_SOURCE_MEMORY; + card->videostate.videoFormat=VIDEO_FORMAT_4_3; + card->videostate.displayFormat=VIDEO_CENTER_CUT_OUT; + + // init and register demuxes + memcpy(card->demux_id, "demux0_0", 9); + card->demux_id[7] = 1+0x30; + dvbdemux->priv = (void *) card; + dvbdemux->filternum = 32; + dvbdemux->feednum = 32; + dvbdemux->start_feed = dvb_start_feed; + dvbdemux->stop_feed = dvb_stop_feed; + dvbdemux->write_to_decoder = dvb_write_to_decoder; + + dvbdemux->dmx.vendor="CIM"; + dvbdemux->dmx.model="sw"; + dvbdemux->dmx.id=card->demux_id; + dvbdemux->dmx.capabilities=(DMX_TS_FILTERING| + DMX_SECTION_FILTERING| + DMX_MEMORY_BASED_FILTERING); + + DvbDmxInit(&card->demux); + + card->dmxdev.filternum=32; + card->dmxdev.demux=&dvbdemux->dmx; + card->dmxdev.capabilities=0; + + DmxDevInit(&card->dmxdev); + + card->mem_frontend.id="mem_frontend"; + card->mem_frontend.vendor="memory"; + card->mem_frontend.model="sw"; + card->mem_frontend.source=DMX_MEMORY_FE; + ret=dvbdemux->dmx.add_frontend(&dvbdemux->dmx, + &card->mem_frontend); + if (ret<0) + return ret; + ret=dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, + &card->mem_frontend); + if (ret<0) + return ret; + + // init and register dvb device structure + dvbd->priv=(void *) card; + dvbd->open=dvbdev_open; + dvbd->close=dvbdev_close; + dvbd->write=dvbdev_write; + dvbd->read=dvbdev_read; + dvbd->ioctl=dvbdev_ioctl; + dvbd->poll=dvbdev_poll; + dvbd->device_type=dvbdev_device_type; + + for (i=0; iusers[i]=card->writers[i]=0; + + card->dvb_devs=0; + card->dvb_devs=&mdvb_devs; + + return dvb_register_device(dvbd); +} + +void dvb_unregister(struct cvdv_cards *card) +{ + dvb_demux_t *dvbdemux=&card->demux; + + dvbdemux->dmx.close(&dvbdemux->dmx); + dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &card->mem_frontend); + DmxDevRelease(&card->dmxdev); + DvbDmxRelease(&card->demux); + dvb_unregister_device(&card->dvb_dev); +} +#endif diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/cvdvext.h linux.19rc3-ac4/drivers/media/video/margi/cvdvext.h --- linux.19rc3/drivers/media/video/margi/cvdvext.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/cvdvext.h 2002-07-29 13:58:41.000000000 +0100 @@ -0,0 +1,30 @@ +/* + cvdvtypes.h + + Copyright (C) Christian Wolff for convergence integrated media. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _CVDVEXT_H_ +#define _CVDVEXT_H_ + +#include +#include "cvdvtypes.h" + +#define OSD_Draw(file,cmd) ioctl(fileno(file),_IO(CVDV_IOCTL_MAGIC,IOCTL_DRAW),&cmd) +#define DecoderCommand(file,cmd) ioctl(fileno(file),_IO(CVDV_IOCTL_MAGIC,IOCTL_DECODER),&cmd) + +#endif // _CVDVEXT_H_ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/cvdv.h linux.19rc3-ac4/drivers/media/video/margi/cvdv.h --- linux.19rc3/drivers/media/video/margi/cvdv.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/cvdv.h 2002-07-29 17:29:12.000000000 +0100 @@ -0,0 +1,58 @@ +/* + cvdv.h + + Copyright (C) Christian Wolff for convergence integrated media. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _CVDV_H_ +#define _CVDV_H_ + + ////////////////////////////////////////////////////////// + // // + // Convergence Digital Video Decoder Card // + // Definitions for the PCI-Card and the Char-Driver // + // // +////////////////////////////////////////////////////////// + + +#include "cardbase.h" +#include "dram.h" +#include "osd.h" +#include "crc.h" +#include "l64021.h" +#include "audio.h" +#include "video.h" +#include "streams.h" +#include "decoder.h" +#include "spu.h" + +void SetVideoSystem(struct cvdv_cards *card); +u16 rnd(u16 range); +// debugging of the card: 0=normal, 1=color bars, 2=sync out +#define USE_DEBUG 0 + +#define cimlogo_width 45 +#define cimlogo_height 38 + +#define CHANNELBUFFERSIZE 32768*8 + +int Prepare(struct cvdv_cards *card); +int OSDTest(struct cvdv_cards *card); +void v4l_init(struct cvdv_cards *card); +int dvb_register(struct cvdv_cards *card); +void dvb_unregister(struct cvdv_cards *card); +#endif // _CVDV_H_ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/cvdvtypes.h linux.19rc3-ac4/drivers/media/video/margi/cvdvtypes.h --- linux.19rc3/drivers/media/video/margi/cvdvtypes.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/cvdvtypes.h 2002-07-29 13:58:41.000000000 +0100 @@ -0,0 +1,281 @@ +/* + cvdvtypes.h + + Copyright (C) Christian Wolff for convergence integrated media. + + 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. +*/ + + ///////////////////////////////////////////////// + // // + // Convergence Digital Video Decoder Card // + // External Definitions for the Char-Driver // + // Copyright (c) 1999 Christian Wolff / // + // convergence integrated media GmbH Berlin // + // // +///////////////////////////////////////////////// + +// As of 1999-11-09 + +#ifndef _CVDVTYPE_H_ +#define _CVDVTYPE_H_ + +// our ioctl number: _IOC_TYPE() is 0xA2 (162) and the range of _IOC_NR() is 0x00 to 0x0F. +// submitted 99/10/15 to mec@shout.net +#define CVDV_IOCTL_MAGIC 0xA2 + +// command numbers _IOC_NR() for ioctl +typedef enum { + IOCTL_DRAW = 0x01, + IOCTL_DECODER = 0x02 +} IOCTL_Command; + + +// supported Videosystems +// everything but PAL and NTSC is untested and probably won't work. +typedef enum { + NTSC = 1, // NTSC 29.97 fps + NTSC60, // NTSC 30 fps + PAL, // PAL-B, D, G, H, I, 25 fps + PALM, // PAL-M 29.97 fps + PALM60, // PAL-M 30 fps + PALN, // PAL-N 25 fps + PALNc, // PAL-Nc 25 fps + PAL60 // PAL 30 fps (doesn't work, yet...) +} videosystem; + +typedef enum { + stream_none = 0, // unknown + stream_ES, + stream_PES, + stream_PS, + stream_DVD +} stream_type; + +typedef enum { + audio_disable = -1, + audio_none = 0, // unknown + audio_MPEG, + audio_MPEG_EXT, + audio_LPCM, + audio_AC3, + audio_DTS, + audio_SDDS +} audio_type; + +#if 0 +typedef enum { + // All functions return -2 on "not open" + OSD_Close = 1, // () + // Disables OSD and releases the buffers + // returns 0 on success + OSD_Open, // (x0,y0,x1,y1,BitPerPixel[2/4/8](color&0x0F),mix[0..15](color&0xF0)) + // Opens OSD with this size and bit depth + // returns 0 on success, -1 on DRAM allocation error, -2 on "already open" + OSD_Show, // () + // enables OSD mode + // returns 0 on success + OSD_Hide, // () + // disables OSD mode + // returns 0 on success + OSD_Clear, // () + // Sets all pixel to color 0 + // returns 0 on success + OSD_Fill, // (color) + // Sets all pixel to color + // returns 0 on success + OSD_SetColor, // (color,R{x0},G{y0},B{x1},opacity{y1}) + // set palette entry to , and apply + // R,G,B: 0..255 + // R=Red, G=Green, B=Blue + // opacity=0: pixel opacity 0% (only video pixel shows) + // opacity=1..254: pixel opacity as specified in header + // opacity=255: pixel opacity 100% (only OSD pixel shows) + // returns 0 on success, -1 on error + OSD_SetPalette, // (firstcolor{color},lastcolor{x0},data) + // Set a number of entries in the palette + // sets the entries "firstcolor" through "lastcolor" from the array "data" + // data has 4 byte for each color: + // R,G,B, and a opacity value: 0->transparent, 1..254->mix, 255->pixel + OSD_SetTrans, // (transparency{color}) + // Sets transparency of mixed pixel (0..15) + // returns 0 on success + OSD_SetPixel, // (x0,y0,color) + // sets pixel , to color number + // returns 0 on success, -1 on error + OSD_GetPixel, // (x0,y0) + // returns color number of pixel ,, or -1 + OSD_SetRow, // (x0,y0,x1,data) + // fills pixels x0,y through x1,y with the content of data[] + // returns 0 on success, -1 on clipping all pixel (no pixel drawn) + OSD_SetBlock, // (x0,y0,x1,y1,increment{color},data) + // fills pixels x0,y0 through x1,y1 with the content of data[] + // inc contains the width of one line in the data block, + // inc<=0 uses blockwidth as linewidth + // returns 0 on success, -1 on clipping all pixel + OSD_FillRow, // (x0,y0,x1,color) + // fills pixels x0,y through x1,y with the color + // returns 0 on success, -1 on clipping all pixel + OSD_FillBlock, // (x0,y0,x1,y1,color) + // fills pixels x0,y0 through x1,y1 with the color + // returns 0 on success, -1 on clipping all pixel + OSD_Line, // (x0,y0,x1,y1,color) + // draw a line from x0,y0 to x1,y1 with the color + // returns 0 on success + OSD_Query, // (x0,y0,x1,y1,xasp{color}}), yasp=11 + // fills parameters with the picture dimensions and the pixel aspect ratio + // returns 0 on success + OSD_Test // () + // draws a test picture. for debugging purposes only + // returns 0 on success +// TODO: remove "test" in final version +} OSD_Command; + +struct drawcmd { + OSD_Command cmd; + int x0; + int y0; + int x1; + int y1; + int color; + void *data; +}; +#endif + +typedef enum { + Decoder_Pause, // pause{param1} 0=run 1=pause 2=toggle + Decoder_Still_Put, // (width{param1}, height{param2}, luma{data1}, chroma{data2}) + // show still picture of specified size + // width; width of the image + // height; height of the image + // luma; Y values, one byte per pixel, width*height bytes + // chroma; 4:2:0 U and V values, interlaced, one byte each U, one byte each V, width*height/2 bytes + Decoder_Still_Get, // (width{param1}, height{param2}, luma{data1}, chroma{data2}) + // grab current showing image + // width and height will be set to current picture size + // if luma and croma are NULL, only width and height will be reported + // otherwise the pixel data is filled in there, same format as Still_put + Decoder_Set_Videosystem, // (videosystem{param1}) + // videosystem: see enum {} videosystem; + Decoder_Set_Streamtype, // (streamtype{param1}) + // streamtype: according to enum {} stream_type; + // This has to be set BEFORE you send data to the device + // For ES and PES streams, Audio has to go into the first device (e.g.minor 0) and video into the second (e.g.minor 16) + Decoder_Set_Audiotype, // (audiotype{param1}) + // audiotype: see enum {} audio_type, +16 for IEC956 on S/PDIF out + Decoder_Set_VideoStreamID, // (video stream ID {param1}) + // video stream ID: MPEG ID 0..15 of video stream to display (E0..EF), -1 for any/auto + Decoder_Set_AudioStreamID, // (audio stream ID {param1}, audio extension stream ID {param2}) + // audio stream ID: MPEG ID 0..31 of audio stream to display (C0..DF), -1 for any/auto + // audio extension stream ID: MPEG ID 0..31 of audio extension stream (C0..DF), -1 for none + Decoder_CSS, // Passes CSS information to and from the decoder + // action{param1}, + // data block{data1} MSB first + // execute 1 to 4 once for each disc, then 5 to 8 for each title + // returns 0 on success, <0 on error + // -1: timeout reading data from card + // -2: data pointer not initialized + // -3: invalid action number + // action=0 -> disable and bypass CSS + // Disk key: + // action=1 -> retreive drive challenge (10 byte) from card + // action=2 -> post drive response (5 byte) to card + // action=3 -> post card challenge (10 byte) and retreive card response (5 byte) + // action=4 -> post disk key (2048 byte) into the card + // Title key: + // action=5 -> retreive title challenge (10 byte) from card + // action=6 -> post title response (5 byte) to card + // action=7 -> post card challenge (10 byte) and retreive card response (5 byte) + // action=8 -> post encrypted title key (5 byte) into the card + Decoder_Highlight, // post SPU Highlight information, + // active{param1} + // 1=show highlight, 0=hide highlight + // color information(SL_COLI or AC_COLI){data1[4]} MSB first + // bits: descr. + // 31-28 Emphasis pixel-2 color + // 27-24 Emphasis pixel-1 color + // 23-20 Pattern pixel color + // 19-16 Background pixel color + // 15-12 Emphasis pixel-2 contrast + // 11- 8 Emphasis pixel-1 contrast + // 7- 4 Pattern pixel contrast + // 3- 0 Background pixel contrast + // button position(BTN_POSI){data2[6]} MSB first + // bits: descr. + // 47-46 button color number + // 45-36 start x + // 33-24 end x + // 23-22 auto action mode + // 21-12 start y + // 9- 0 end y + Decoder_SPU, // Activate SPU decoding and select SPU stream ID + // stream{param1} + // active{param2} + Decoder_SPU_Palette, // post SPU Palette information + // length{param1} + // palette{data1} + Decoder_GetNavi, // Retreives CSS-decrypted navigational information from the stream. + // data1 will be filled with PCI or DSI pack (private stream 2 stream_id), + // and the length of data1 (1024 or 0) will be returned + Decoder_SetKaraoke, // Vocal1{param1}, Vocal2{param2}, Melody{param3} + // if Vocal1 or Vocal2 are non-zero, they get mixed into left and right at 70% each + // if both, Vocal1 and Vocal2 are non-zero, Vocal1 gets mixed into the left channel and + // Vocal2 into the right channel at 100% each. + // if Melody is non-zero, the melody channel gets mixed into left and right + Decoder_Set_Videoattribute, // Set the video parameters + // attribute{param1} (2 byte V_ATR) + // bits: descr. + // 15-14 Video compression mode (0=MPEG-1, 1=MPEG-2) + // 13-12 TV system (0=525/60, 1=625/50) + // 11-10 Aspect ratio (0=4:3, 3=16:9) + // 9- 8 permitted display mode on 4:3 monitor (0=both, 1=only pan-scan, 2=only letterbox) + // 7 line 21-1 data present in GOP (1=yes, 0=no) + // 6 line 21-2 data present in GOP (1=yes, 0=no) + // 5- 3 source resolution (0=720x480/576, 1=704x480/576, 2=352x480/576, 3=352x240/288) + // 2 source letterboxed (1=yes, 0=no) + // 0 film/camera mode (0=camera, 1=film (625/50 only)) + Decoder_Set_Audioattribute, // Set the audio parameters + // attribute{param1} (2 most significan bytes of A_ATR (bit 63 through 48)) + // bits: descr. + // 15-13 audio coding mode (0=ac3, 2=mpeg1, 3=mpeg2ext, 4=LPCM, 6=DTS, 7=SDDS) + // 12 multichannel extension + // 11-10 audio type (0=not spec, 1=language included) + // 9- 8 audio application mode (0=not spec, 1=karaoke, 2=surround) + // 7- 6 Quantization / DRC (mpeg audio: 1=DRC exists)(lpcm: 0=16bit, 1=20bit, 2=24bit) + // 5- 4 Sample frequency fs (0=48kHz, 1=96kHz) + // 2- 0 number of audio channels (n+1 channels) + Decoder_WriteBlock, // Post one block of data, e.g. one DVD sector of 2048 byte, into the decoder queue + // sectordata{data1} + // length{param1} + // is_initial_block{param2} + // set_SCR{param3} + /* + Decoder_FFWD, // ffwd{param1} 0=normal 1=ffwd 2=toggle + Decoder_Slow // slow{param1} 0=normal 1=slow 2=toggle + */ +} Decoder_Command; + +struct decodercmd { + Decoder_Command cmd; + int param1; + int param2; + int param3; + int param4; + int param5; + void *data1; + void *data2; +}; + +#endif // _CVDVTYPE_H_ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/decoder.c linux.19rc3-ac4/drivers/media/video/margi/decoder.c --- linux.19rc3/drivers/media/video/margi/decoder.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/decoder.c 2002-07-29 13:58:41.000000000 +0100 @@ -0,0 +1,1536 @@ +/* + decoder.c + + Copyright (C) Christian Wolff for convergence integrated media. + + 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 __NO_VERSION__ + +#include "decoder.h" +#include "l64021.h" +#include "video.h" +#include "audio.h" +#include "streams.h" +#include "osd.h" +#include "dram.h" +#include "cvdv.h" + +int DecoderGetNavi(struct cvdv_cards *card, u8 *navidata) +{ + if (card->navihead == card->navitail) return 0; + MDEBUG(3, ": Retreiving NaviPack\n"); + memcpy(navidata, &card->navibuffer[card->navitail], NAVISIZE); + card->navitail += NAVISIZE; + if (card->navitail >= NAVIBUFFERSIZE) card->navitail = 0; + return NAVISIZE; +} + +// returns 1 on overrun, 0 on no error +int DecoderQueueNavi(struct cvdv_cards *card, u8 *navidata) +{ + memcpy(&card->navibuffer[card->navihead], navidata, NAVISIZE); + card->navihead += NAVISIZE; + if (card->navihead >= NAVIBUFFERSIZE) card->navihead = 0; + if (card->navihead == card->navitail) { + MDEBUG(3, ": NaviPack buffer overflow\n"); + card->navitail += NAVISIZE; + if (card->navitail >= NAVIBUFFERSIZE) card->navitail = 0; + return 1; + } + return 0; +} + +u32 ParseSCR(const u8 *data) +{ + u32 SCR_base=0; + u8 scrdata[9]; + copy_from_user (scrdata, data, 9); + + if ((!scrdata[0]) && (!scrdata[1]) && (scrdata[2]==1) + && (scrdata[3]==0xBA) && ((scrdata[4]&0xC0)==0x40)) { + SCR_base=((scrdata[4]>>3)&0x07); + SCR_base=(SCR_base<<2) | (scrdata[4]&0x03); + SCR_base=(SCR_base<<8) | scrdata[5]; + SCR_base=(SCR_base<<5) | ((scrdata[6]>>3)&0x1F); + SCR_base=(SCR_base<<2) | (scrdata[6]&0x03); + SCR_base=(SCR_base<<8) | scrdata[7]; + SCR_base=(SCR_base<<5) | ((scrdata[8]>>3)&0x1F); + } + return SCR_base; +} + +u32 SetSCR(struct cvdv_cards *card, u32 SCR_base) +{ + MDEBUG(3, ": SCR in DVD Pack: 0x%08X\n",SCR_base); + if (DecoderReadByte(card, 0x007) & 0x10) { // SCR already stopped + DecoderWriteByte(card,0x009,SCR_base&0xFF); // Set SCR counter + DecoderWriteByte(card,0x00A,(SCR_base>>8)&0xFF); + DecoderWriteByte(card,0x00B,(SCR_base>>16)&0xFF); + DecoderWriteByte(card,0x00C,(SCR_base>>24)&0xFF); + } else { + DecoderMaskByte(card,0x007,0xD2,0xD2); + // Set 0x10, halt SCR counter + DecoderWriteByte(card,0x009,SCR_base&0xFF); // Set SCR counter + DecoderWriteByte(card,0x00A,(SCR_base>>8)&0xFF); + DecoderWriteByte(card,0x00B,(SCR_base>>16)&0xFF); + DecoderWriteByte(card,0x00C,(SCR_base>>24)&0xFF); + DecoderMaskByte(card,0x007,0xD2,0xC2); + // Del 0x10, SCR counter run + } + return SCR_base; +} + +void DecoderPause(struct cvdv_cards *card) +{ + DecoderMaskByte(card, 0x007, 0xD2, 0xD2); + // Set 0x010, halt SCR counter + AudioSetPlayMode(card, MAUDIO_PAUSE); + DecoderStopDecode(card); +#ifdef DVB + card->videostate.playState=VIDEO_FREEZED; +#endif + card->videoffwd = 0; + card->videoslow = 0; +} + +void DecoderUnPause(struct cvdv_cards *card) +{ + DecoderStartDecode(card); + card->videoffwd = 0; + AudioSetPlayMode(card, MAUDIO_PLAY); + DecoderMaskByte(card, 0x007, 0xD2, 0xC2); + // Del 0x010, SCR counter run +#ifdef DVB + card->videostate.playState=VIDEO_PLAYING;; +#endif + card->videoslow = 0; +} + +void CloseCard(struct cvdv_cards *card) +{ +#ifdef NOINT + spin_lock(&card->timelock); + del_timer(&card->timer); + spin_unlock(&card->timelock); +#endif + MargiFlush(card); + MDEBUG(1, ": Closing card\n"); + card->DecoderOpen = 1; + DecoderClose(card); + DecoderUnPrepare(card); + DecoderStreamReset(card); + DecoderSetupReset(card); + VideoSetBackground(card, 1, 0, 0, 0); + + AudioClose(card); + OSDClose(card); + L64021Init(card); + MargiFreeBuffers(card); + + OSDOpen(card, 50, 50, 150, 150, 2, 1); + OSDTest(card); +} + + +void DecoderReadAudioInfo(struct cvdv_cards *card) +{ + u8 data; + static int bitrates[17] = {0, 32, 40, 48, 56, 64, 80, 96, 112, + 128, 160, 192, 224, 256, 320, 384, 0}; + struct AudioParam *audio = &card->stream.audio; + data = DecoderReadByte(card, 0x150); + audio->mpeg.present = data & 0x60; + // MPEG Layer Code 00 reserverd, we can assume valid MPEG params + if (audio->mpeg.present) { + audio->mpeg.MPEG2 = data & 0x80; + audio->mpeg.layer = 4 - ((data >> 5) & 0x03); + if (data & 0x0F) { + if ((data & 0x0F) == 1) audio->mpeg.bitrate = 32; + else switch (audio->mpeg.layer) { + case 1: + audio->mpeg.bitrate = 32 * (data & 0x0F); + break; // Layer I + case 2: + audio->mpeg.bitrate = bitrates[(data & 0x0F) + + 1]; + break; // Layer II + default: + audio->mpeg.bitrate = bitrates[data & 0x0F]; + // Layer III + } + } else audio->mpeg.bitrate = 0; + data = DecoderReadByte(card, 0x151); + switch ((data >> 6) & 0x03) { + case 0: + audio->mpeg.samplefreq = 44; + break; + case 1: + audio->mpeg.samplefreq = 48; + break; + case 2: + audio->mpeg.samplefreq = 32; + break; + default: + audio->mpeg.samplefreq = 0; // invalid + } + audio->mpeg.mode = (data >> 3) & 0x03; + audio->mpeg.modeext = (data >> 1) & 0x03; + audio->mpeg.copyright = data & 0x01; + data=DecoderReadByte(card, 0x152); + audio->mpeg.original = data & 0x80; + audio->mpeg.emphasis = (data >> 5) & 0x03; + } + data = DecoderReadByte(card, 0x153); + audio->ac3.present = (data != 0); + // value 0 for bits 0..5 forbidden, we can assume valid ac3 params + if (audio->ac3.present) { + audio->ac3.acmod = (data >> 5) & 0x07; + audio->ac3.dialnorm = data & 0x1F; + data = DecoderReadByte(card, 0x154); + audio->ac3.bsmod = (data >> 5) & 0x07; + audio->ac3.dialnorm2 = data > 0x1F; + data = DecoderReadByte(card, 0x155); + audio->ac3.surmixlev = (data >> 6) & 0x03; + audio->ac3.mixlevel = (data >> 1) & 0x1F; + data = DecoderReadByte(card, 0x156); + audio->ac3.cmixlev = (data >> 6) & 0x03; + audio->ac3.mixlevel2 = (data >> 1) & 0x1F; + data = DecoderReadByte(card, 0x157); + audio->ac3.fscod = (data >> 6) & 0x03; + audio->ac3.lfeon = (data >> 5) & 0x01; + audio->ac3.bsid = data & 0x1F; + data = DecoderReadByte(card, 0x158); + audio->ac3.dsurmod = (data >> 6) & 0x03; + audio->ac3.frmsizecod = data & 0x3F; + audio->ac3.langcod = DecoderReadByte(card, 0x159); + audio->ac3.langcod2 = DecoderReadByte(card, 0x15A); + audio->ac3.timecod = DecoderReadByte(card, 0x15B); + data = DecoderReadByte(card, 0x15C); + audio->ac3.timecod = (audio->ac3.timecod << 6) | + ((data >> 2) & 0x3F); + audio->ac3.roomtyp = data & 0x03; + audio->ac3.timecod2 = DecoderReadByte(card, 0x15D); + data = DecoderReadByte(card, 0x15E); + audio->ac3.timecod2 = (audio->ac3.timecod2 << 6) | + ((data >> 2) & 0x3F); + audio->ac3.roomtyp2 = data & 0x03; + } + audio->pcm.present =! (DecoderReadByte(card, 0x161) & 0x20); + // PCM FIFO not empty? Then, we can assume valid LPCM params + if (audio->pcm.present) { + data = DecoderReadByte(card, 0x15F); + audio->pcm.audio_frm_num = (data >> 3) & 0x1F; + audio->pcm.num_of_audio_ch = data & 0x07; + data = DecoderReadByte(card, 0x160); + audio->pcm.Fs = (data >> 6) & 0x03; + audio->pcm.quantization = (data >> 4) & 0x03; + audio->pcm.emphasis = (data >> 2) & 0x03; + audio->pcm.mute_bit = (data >> 1) & 0x01; + } + switch (card->setup.audioselect) { + case audio_disable: + audio->valid = 0; + break; + case audio_none: + case audio_DTS: + case audio_SDDS: + if ((audio->valid = (audio->ac3.present || + audio->pcm.present || + audio->mpeg.present))) { + if (audio->mpeg.present) { + card->setup.audioselect = audio_MPEG; + } else if (audio->pcm.present) { + card->setup.audioselect = audio_LPCM; + } else if (audio->ac3.present) { + card->setup.audioselect = audio_AC3; + } + } else { + audio->valid = 0; + card->setup.audioselect = audio_none; + } + break; + case audio_MPEG: // MPEG Audio + case audio_MPEG_EXT: // MPEG Audio with extension stream + audio->valid = audio->mpeg.present; + break; + case audio_LPCM: // Linear Pulse Code Modulation LPCM + audio->valid = audio->pcm.present; + break; + case audio_AC3: // AC-3 + audio->valid = audio->ac3.present; + break; + } + MDEBUG(1, ": -- DecoderReadAudioInfo - type/valid %d/%d:\n", card->setup.audioselect, audio->valid); + if (audio->mpeg.present || audio->ac3.present || audio->pcm.present) + MDEBUG(1, ": Audio - Decoded parameters:\n"); + if (audio->mpeg.present) MDEBUG(1, ": MPEG%s Layer %d, %d kHz, %d kbps, %s, %s%s, %s emphasis\n", + ((audio->mpeg.MPEG2) ? "2" : "1"), + audio->mpeg.layer, + audio->mpeg.samplefreq, + audio->mpeg.bitrate, + ((audio->mpeg.mode == 0) ? "stereo" : ((audio->mpeg.mode == 1) ? "joint stereo" : ((audio->mpeg.mode == 2) ? "dual channel" : "single channel"))), + ((audio->mpeg.copyright) ? "copyrighted " : ""), + ((audio->mpeg.original) ? "original" : "copy"), + ((audio->mpeg.emphasis == 0) ? "no" : ((audio->mpeg.emphasis == 1) ? "50/15 usec." : ((audio->mpeg.emphasis == 2) ? "invalid" : "J.17"))) + ); + if (audio->ac3.present) MDEBUG(1, ": AC3 acmod=%d bsmod=%d dialnorm=%d dialnorm2=%d surmixlev=%d mixlevel=%d cmixlev=%d mixlevel2=%d fscod=%d lfeon=%d bsid=%d dsurmod=%d frmsizecod=%d langcod=%d langcod2=%d timecod=%d roomtyp=%d timecod2=%d roomtyp2=%d\n", + audio->ac3.acmod, + audio->ac3.bsmod, + audio->ac3.dialnorm, + audio->ac3.dialnorm2, + audio->ac3.surmixlev, + audio->ac3.mixlevel, + audio->ac3.cmixlev, + audio->ac3.mixlevel2, + audio->ac3.fscod, + audio->ac3.lfeon, + audio->ac3.bsid, + audio->ac3.dsurmod, + audio->ac3.frmsizecod, + audio->ac3.langcod, + audio->ac3.langcod2, + audio->ac3.timecod, + audio->ac3.roomtyp, + audio->ac3.timecod2, + audio->ac3.roomtyp2); + if (audio->pcm.present) MDEBUG(1, ": LPCM audio_frm_num=%d num_of_audio_ch=%d Fs=%d quantization=%d emphasis=%d mute_bit=%d\n", + audio->pcm.audio_frm_num, + audio->pcm.num_of_audio_ch, + audio->pcm.Fs, + audio->pcm.quantization, + audio->pcm.emphasis, + audio->pcm.mute_bit); +} + +void DecoderReadAuxFifo(struct cvdv_cards *card) +{ + int i = 0; + u8 data; + int layer; + + struct StreamInfo *stream = &card->stream; + MDEBUG(3, ": AUX - %03X ", card->AuxFifo[card->AuxFifoTail]); + while (card->AuxFifoHead != card->AuxFifoTail) { + + layer = (card->AuxFifo[card->AuxFifoTail] >> 8) & 0x07; + data = card->AuxFifo[card->AuxFifoTail] & 0xFF; + card->AuxFifoTail = (card->AuxFifoTail + 1) & FIFO_MASK; + if (layer != card->AuxFifoLayer) { // start of a new layer? + i = 0; + card->AuxFifoLayer = layer; + } else i++; + switch (layer) { // layer code + case 0: // sequence header + if (! stream->sh.valid) switch (i) { + case 0: + stream->sh.hsize = data & 0x0F; + break; + case 1: + stream->sh.hsize = (stream->sh.hsize << 8) + | data; + stream->hsize = stream->sh.hsize; + break; + case 2: + stream->sh.vsize = data & 0x0F; + break; + case 3: + stream->sh.vsize = (stream->sh.vsize << 8) | + data; + stream->vsize = stream->sh.vsize; + break; + case 4: + stream->sh.aspectratio = data & 0x0F; + break; + case 5: + stream->sh.frameratecode = data & 0x0F; + break; + case 6: + stream->sh.bitrate = data & 0x03; + break; + case 7: + stream->sh.bitrate = (stream->sh.bitrate << 8) + | data; + break; + case 8: + stream->sh.bitrate = (stream->sh.bitrate << 8) + | data; + stream->bitrate = stream->sh.bitrate; + break; + case 9: + stream->sh.vbvbuffersize = data & 0x03; + break; + case 10: + stream->sh.vbvbuffersize = + (stream->sh.vbvbuffersize << 8) | + data; + stream->vbvbuffersize = + stream->sh.vbvbuffersize; + break; + case 11: + stream->sh.constrained = data & 0x01; + stream->sh.valid = 1; + MDEBUG(1, ": AUX - MPEG1 - %dx%d %s %s fps, %d bps, %d kByte vbv%s\n", stream->sh.hsize, stream->sh.vsize, + ((stream->sh.aspectratio == 1) ? "1:1" : + ((stream->sh.aspectratio == 2) ? "3:4" : + ((stream->sh.aspectratio == 3) ? "9:16" : + ((stream->sh.aspectratio == 4) ? "1:2.21" : + "?:?")))), + ((stream->sh.frameratecode == 1) ? "23.976" : + ((stream->sh.frameratecode == 2) ? "24" : + ((stream->sh.frameratecode == 3) ? "25" : + ((stream->sh.frameratecode == 4) ? "29.97" : + ((stream->sh.frameratecode == 5) ? "30" : + ((stream->sh.frameratecode == 6) ? "50" : + ((stream->sh.frameratecode == 7) ? "59.94" : + ((stream->sh.frameratecode == 8) ? "60" : + "?")))))))), + stream->sh.bitrate * 400, + stream->sh.vbvbuffersize * 16, + ((stream->sh.constrained) ? ", constrained" : "") + ); + break; + } + break; + case 1: // group of pictures + if (! stream->gop.valid) + switch (i) { + case 0: + stream->gop.timecode = data & 0x01; + break; + case 1: + stream->gop.timecode = + (stream->gop.timecode << 8) | + data; + break; + case 2: + stream->gop.timecode = + (stream->gop.timecode << 8) | + data; + break; + case 3: + stream->gop.timecode = + (stream->gop.timecode << 8) | + data; + break; + case 4: + stream->gop.closedgop = data & 0x01; + break; + case 5: + stream->gop.brokenlink = data & 0x01; + stream->gop.valid = 1; + break; + } + break; + case 2: // picture + if (0) + switch (i) { + case 0: + break; + } + break; + case 7: // extension layer + if (i == 0) card->AuxFifoExt = data; + else + switch (card->AuxFifoExt) { // extension code + case 1: // sequence extension + if ((stream->sh.valid) && + (! stream->se.valid)) + switch (i) { + case 1: + stream->se.profilelevel + = data; + break; + case 2: + stream->se.progressive + = data & 0x01; + break; + case 3: + stream->se.chroma = + (data >> 4) & + 0x03; + stream->se.hsizeext = + (data >> 2) & + 0x03; + stream->se.vsizeext = + data & 0x03; + stream->hsize |= + (stream->se.hsizeext << 12); + stream->vsize |= + (stream->se.vsizeext << 12); + break; + case 4: + stream->se.bitrateext = + data & 0x0F; + break; + case 5: + stream->se.bitrateext = + (stream->se.bitrateext << 8) | data; + stream->bitrate |= + (stream->se.bitrateext << 18); + break; + case 6: + stream->se.vbvbuffersizeext = data; + stream->vbvbuffersize |= (stream->se.vbvbuffersizeext << 10); + break; + case 7: + stream->se.lowdelay = + (data >> 7) & + 0x01; + stream->se.frextn = + (data >> 5) & + 0x03; + stream->se.frextd = + data & 0x1F; + stream->se.valid = 1; + stream->MPEG2 = 1; + MDEBUG(1, ": AUX - MPEG2 - %dx%d %s %s*%d/%d fps, %d bps, %d kByte vbv%s%s\n", stream->hsize, stream->vsize, + ((stream->sh.aspectratio == 1) ? "1:1" : + ((stream->sh.aspectratio == 2) ? "3:4" : + ((stream->sh.aspectratio == 3) ? "9:16" : + ((stream->sh.aspectratio == 4) ? "1:2.21" : + "?:?")))), + ((stream->sh.frameratecode == 1) ? "23.976" : + ((stream->sh.frameratecode == 2) ? "24" : + ((stream->sh.frameratecode == 3) ? "25" : + ((stream->sh.frameratecode == 4) ? "29.97" : + ((stream->sh.frameratecode == 5) ? "30" : + ((stream->sh.frameratecode == 6) ? "50" : + ((stream->sh.frameratecode == 7) ? "59.94" : + ((stream->sh.frameratecode == 8) ? "60" : + "?")))))))), + stream->se.frextn + 1, + stream->se.frextd + 1, + stream->bitrate * 400, + stream->vbvbuffersize * 16, + ((stream->sh.constrained) ? ", constrained" : ""), + ((stream->se.lowdelay) ? ", low delay" : "") + ); + break; + } + break; + case 2: // sequence display extension + if (0) + switch (i) { + case 0: + break; + } + break; + case 3: // quant matrix extension + if (0) + switch (i) { + case 0: + break; + } + break; + case 4: // copyright extension + if (0) + switch (i) { + case 0: + break; + } + break; + case 7: // picture display extension + if (0) switch (i) { + case 0: + break; + } + break; + case 8: // picture coding extension + if (0) + switch (i) { + case 0: + break; + } + break; + default: + break; + } + break; + default:break; + } + + } +} + +void DecoderReadDataFifo(struct cvdv_cards *card) +{ + MDEBUG(3, ": DATA - "); + while (card->DataFifoHead != card->DataFifoTail) { + MDEBUG(3,"%03X ", card->DataFifo[card->DataFifoTail]); + card->DataFifoTail = (card->DataFifoTail + 1) & FIFO_MASK; + } + MDEBUG(3,"\n"); +} + +int DecoderReadNavipack(struct cvdv_cards *card) +{ + u32 startaddr, endaddr, writeaddr; + u8 navipack[1024]; + u16 PacketLength; + u8 SubStreamID; + //struct Navi navi; + int i; + startaddr = (DecoderReadWord(card, 0x05C) & 0x3FFF) << 7; + // 21 bit word address + endaddr = (DecoderReadWord(card, 0x05E) & 0x3FFF) << 7; + // 21 bit word address + writeaddr = DecoderReadByte(card, 0x075) & 0xFF; + writeaddr |= (DecoderReadWord(card, 0x077) & 0x0FFF) << 8; + //writeaddr <<= 3; + MDEBUG(3, ": -- DecoderReadNavipack 0x%08X-0x%08X, ->0x%08X <-0x%08X\n", + startaddr, endaddr, writeaddr, card->NaviPackAddress); + + if (DecoderReadByte(card, 0x07B) & 0xC0) { // navi pack available? + DRAMReadByte(card, card->NaviPackAddress, 1024, navipack, 0); + card->reg07B |= 0x20; // decrement navi counter + DecoderWriteByte(card, 0x07B, card->reg07B); + card->reg07B &= ~0x20; + //DecoderSetByte(card, 0x07B, 0x20); // decrement navi counter + card->NaviPackAddress += 512; // increment in words + if (card->NaviPackAddress >= endaddr) + card->NaviPackAddress = startaddr; + MDEBUG(4, ": Navipack %02X %02X %02X %02X %02X %02X %02X %02X\n", + navipack[0], navipack[1], navipack[2], navipack[3], navipack[4], + navipack[5], navipack[6], navipack[7]); + if ((!navipack[0]) && (!navipack[1]) && (navipack[2] == 1) && + (navipack[3] == 0xBF)) { + PacketLength = (navipack[4] << 8) | navipack[5]; + SubStreamID = navipack[6]; + MDEBUG(4, ": Navipack Len=%d, ID=%d\n", PacketLength, SubStreamID); + i = 7; // start of payload data in navipack[] + switch (SubStreamID) { + case 0: // Presentation Control Information (PCI) + if (PacketLength < 980) return 1; // Packet too small + DecoderQueueNavi(card, navipack); + break; + case 1: // Data Search Information (DSI) + if (PacketLength < 1018) return 1; // Packet too small + DecoderQueueNavi(card, navipack); + break; + default: + break; + } + } else { + MDEBUG(4, "navipack format error:%02X %02X %02X %02X %02X %02X %02X %02X\n", + navipack[0], navipack[1], navipack[2], navipack[3], navipack[4], + navipack[5], navipack[6], navipack[7]); + } + } else { + MDEBUG(4, ": no navi pack avail.\n"); + } + return 0; +} + +int AudioStart(struct cvdv_cards *card) +{ + DecoderReadAudioInfo(card); // detect audio type + if (card->stream.audio.valid) { + MDEBUG(1, ": Audio Init in delayed decoder start\n"); + if (card->AudioInitialized) AudioClose(card); + switch (card->setup.audioselect) { + case audio_MPEG: // MPEG Audio + case audio_MPEG_EXT: // MPEG Audio with ext. + MDEBUG(1, ": Using MPEG Audio\n"); + AudioInit(card, card->stream.audio.mpeg.samplefreq, 0); + if (card->stream.audio.mpeg.mode == 3) AudioDualMono(card, 2); // left channel only + else AudioDualMono(card, 0); + break; + case audio_DTS: + case audio_LPCM: // Linear Pulse Code Modulation LPCM + MDEBUG(1, ": Using LPCM Audio\n"); + AudioInit(card, 48, 0); // or 96 + break; + case audio_AC3: // AC-3 + MDEBUG(1, ": Using AC-3 Audio\n"); + switch (card->stream.audio.ac3.fscod) { + case 0:AudioInit(card, 48, 0); break; + case 1:AudioInit(card, 44, 0); break; + case 2:AudioInit(card, 32, 0); break; + } + break; + case audio_none: + case audio_disable: + case audio_SDDS: + } + } else return 1; + return 0; +} + +u32 DecoderReadSCR(struct cvdv_cards *card, u16 address) +{ + u32 SCR; + SCR = DecoderReadByte(card, address); + SCR |= ((u32)DecoderReadByte(card, address+1) << 8); + SCR |= ((u32)DecoderReadByte(card, address+2) << 16); + SCR |= ((u32)DecoderReadByte(card, address+3) << 24); + return SCR; +} + +u32 DecoderReadRWAddr(struct cvdv_cards *card, u16 address) +{ + u32 addr; + addr = DecoderReadByte(card, address) & 0xFF; + addr |= (((u32)DecoderReadByte(card, address+1) & 0xFF) << 8); + addr |= (((u32)DecoderReadByte(card, address+2) & 0x0F) << 16); + return addr; +} + +int PTSGetFirstPTS(PTSStorage *store, u32 *PTS) +{ + if ( store->end == store->begin ) { + return 0; + } else { + *PTS = store->PTS[store->begin]; + return 1; + } +} + +void PTSStoreAdd(PTSStorage *store, u32 PTS, u32 AddrB, u32 AddrE) +{ + int new; + MDEBUG(3, ": PTSStoreAdd - store in [%d] %08X - %08X\n", store->end, AddrB, AddrE); + + // cheap fix: don't store if address rollover + if ((AddrB & 0x00080000) != (AddrE & 0x00080000)) return; + + new = store->end; + + store->end++; + if (store->end >= store->size) store->end = 0; + if (store->end == store->begin) { + store->begin++; + if (store->begin >= store->size) store->begin = 0; + } + + store->AddrB[new] = AddrB; + store->AddrE[new] = AddrE; + store->PTS[new] = PTS; +} + +int PTSGetPTS (PTSStorage *store, u32 Addr, u32 *PTS ) +{ + u32 AddrB; + u32 AddrE; + int i; + int found; + int search; + + MDEBUG(3, ": PTSGetPTS - search %08X\n", Addr); + + if (store->end == store->begin) { + store->LastAddr = Addr; + return 0; + } + + // Search for the PTS in the array + found = 0; + search = 1; + while (search && !found) { + // Get the first value + i = store->begin; + AddrB = store->AddrB[i]; + AddrE = store->AddrE[i]; + + MDEBUG(3, ": PTSGetPTS - search in [%d] %08X - %08X\n", i, AddrB, AddrE); + + //If in range, keep it + if ((Addr >= AddrB) && (Addr <= AddrE)) { + *PTS = store->PTS[i]; + found = 1; + } else { + if ((Addr & 0x00080000) == (AddrB & 0x00080000)) { + if (Addr < AddrB ) search = 0; + } else { + if ((store->LastAddr & 0x00080000) == (Addr & 0x00080000)) search = 0; + } + } + if (search) { + store->begin++; + if (store->begin >= store->size) store->begin = 0; + if (store->end == store->begin ) search = 0; + } + } + store->LastAddr = Addr; + return found; +} + + +u32 GetPTS(u8 *data, u32* MediaPointer, int mpeg, int hlength,int off) +{ + u32 PTS = 0xFFFFFFFFUL; + int p = 0; + + // Read PTS, if present + if ((mpeg == 2 && data[p + 7] & 0x80) || + (mpeg == 1 && off)) { + if (mpeg == 1) p = off-9; + PTS = (data[p + 9] >> 1) & 0x03UL; + PTS = (PTS << 8) | (data[p + 10] & 0xFFUL); + PTS = (PTS << 7) | ((data[p + 11] >> 1) & 0x7FUL); + PTS = (PTS << 8) | (data[p + 12] & 0xFFULL); + PTS = (PTS << 7) | ((data[p + 13] >> 1) & 0x7FUL); + } + // Now, skip rest of PES header and stuffing + if (mpeg == 2){ + p += (9 + (data[p + 8] & 0xFF)); + p = ((p + 7) / 8) * 8; + } else p = hlength+7; + if (!(data[p++] | data[p++] | data[p++] | data[p++])) { + *MediaPointer = (u32)data[p++] & 0xFF; + *MediaPointer = (*MediaPointer << 8) | ((u32)data[p++] & 0xFF); + *MediaPointer = (*MediaPointer << 8) | ((u32)data[p++] & 0xFF); + *MediaPointer = (*MediaPointer << 8) | ((u32)data[p++] & 0xFF); + } else { + *MediaPointer = 0xFFFFFFFFUL; + } + return PTS; +} + +int ReadPESChunk(struct cvdv_cards *card, u32 *addr, u8 *data, u32 start, u32 end) +{ + int i = 5, err = -1; + while (err && (i--)) err &= DRAMReadByte(card, *addr << 2, 8, &data[0], 0); + if (err) return 1; + (*addr)++; + if (*addr >= end) *addr = start; + return 0; +} + +void ReadPESHeaders(struct cvdv_cards *card) +{ + u8 startcode[] = {0x00, 0x00, 0x01}; + int LoopCount; + u32 LastVAddr; // Current Video Address + u32 LastAAddr; // Current Audio Address + u32 Addr; // Current Header Address + u32 PESAddr; // Pointer from Header Block + u32 PTS; // PTS from Header Block + u8 Data[32]; + u32 AudioPESStart; + u32 AudioPESEnd; + int i, j, p, fail; + u32 FailAddr; + int hlength=0; + int mpeg=0; + int check; + int mp=0; + int off=0; + + AudioPESStart = (DecoderReadWord(card, 0x058) & 0x3FFF) << 5; + AudioPESEnd = ((DecoderReadWord(card, 0x05A) & 0x3FFF) + 1) << 5; + + LastVAddr = DecoderReadRWAddr(card, 0x060); + LastAAddr = DecoderReadRWAddr(card, 0x063); + + if (card->LastAddr == 0) card->LastAddr = AudioPESStart; + + //Read the PES header buffer + Addr = DecoderReadRWAddr(card, 0x072) & 0x0007FFFF; + if (Addr >= AudioPESEnd) { + Addr = card->LastAddr = AudioPESStart; + } + + LoopCount = 0; + while ((card->LastAddr != Addr) && (LoopCount++ < 200)) { + FailAddr = card->LastAddr; + fail = 0; + p = 0; + + if (ReadPESChunk(card, &card->LastAddr, &Data[p], + AudioPESStart, AudioPESEnd)) continue; + p+=8; + j=1; + + if (memcmp(Data, startcode, 3)) continue; + if ((Data[3] == 0xE0) || (Data[3] == 0xBD) + || ((Data[3] & 0xE0) == 0xC0)) { + + fail |= ReadPESChunk(card, &card->LastAddr, + &Data[p], AudioPESStart, + AudioPESEnd); + + + p+=8; + j++; + if ( (Data[6] & 0xC0) == 0x80 ){ + hlength = 9+Data[8]; + mpeg = 2; + } else { + mpeg = 1; + mp = 6; + check = Data[mp]; + mp++; + while (check == 0xFF){ + if (!fail && mp == p) { + fail |= ReadPESChunk( + card, + &card->LastAddr, + &Data[p], + AudioPESStart, + AudioPESEnd); + p+=8; + j++; + } + check = Data[mp]; + mp++; + } + if (!fail && mp == p) { + fail |= ReadPESChunk( + card, + &card->LastAddr, + &Data[p], + AudioPESStart, + AudioPESEnd); + p+=8; + j++; + } + + if ( !fail && (check & 0xC0) == 0x40){ + check = Data[mp]; + mp++; + if (!fail && mp == p) { + fail |= ReadPESChunk( + card, + &card->LastAddr, + &Data[p], + AudioPESStart, + AudioPESEnd); + p+=8; + j++; + } + check = Data[mp]; + mp++; + } + if ( !fail && (check & 0x20)){ + if (check & 0x30) hlength = mp+10; + else hlength = mp+5; + off = mp-1; + } + } + + for (i = 1; (i < ((hlength+7) / 8)) && (!fail); + i++) { + fail |= ReadPESChunk(card, &card->LastAddr, + &Data[p], AudioPESStart, + AudioPESEnd); + p+=8; + j++; + } + + if (!fail) { + PTS = GetPTS(Data, &PESAddr, + mpeg, hlength,off); + if ((PTS != 0xFFFFFFFF) && + (PESAddr != 0xFFFFFFFF)) { + if (Data[3] == 0xE0) { // Video + PTSStoreAdd(&card->VideoPTSStore, PTS, PESAddr, LastVAddr); + } else { // Audio + PTSStoreAdd(&card->AudioPTSStore, PTS, PESAddr, LastAAddr); + } + } + } + } else { + //card->LastAddr = Addr; + } + // In case of error, rewind and try again + if (fail) card->LastAddr = FailAddr; + } +} + +void L64021Intr(struct cvdv_cards *card) +{ + u32 SCR_base, SCR_compareV, SCR_compareA; + u32 VideoAddr, AudioAddr, PTS; + int i, a, v, as, vs, ap, vp; + u8 intr[5]; + u8 layer; + long ISRTime, DeltaSyncTime, Offset; + + int used = 0; + u8 err; + + err = DecoderReadByte(card, 0x095); + if (err & 0x17) { + MDEBUG(0, ": Packet Error: 0x%02X\n", err); + } + + ISRTime = 0; // TODO system time + + for (i = 0; i < 5; i++) + if ((intr[i] = DecoderReadByte(card, i))) used = 1; + if (used) { + if (intr[0] & 0x80) { // new field + card->fields++; + + if (card->videoffwd){ + if (!card->videoffwd_last){ + AudioStopDecode(card); + card->videosync = 0; + card->videoskip = card->videoffwd; + card->videoskip = 0; + card->videoffwd_last = 1; + card->videoskip_last = 0; + } else { + if (card->videoskip_last == -1){ + card->videoskip = + card->videoffwd; + } + + if (!card->videoskip) + card->videoskip_last = -1; + else + card->videoffwd_last = + card->videoffwd; + } + } else if( card->videoffwd_last ){ + card->videoffwd_last = 0; +#ifdef DVB + if (card->audiostate.AVSyncState) +#endif + card->videosync = 1; + AudioStartDecode(card); + } + + + if (card->videoslow){ + if (!card->videoslow_last){ + AudioStopDecode(card); + card->videosync = 0; + card->videodelay = card->videoslow; + card->videoskip = 0; + card->videoslow_last = 1; + card->videodelay_last = 0; + } else { + if (card->videodelay_last == -1){ + card->videodelay = + card->videoslow; + } + + if (!card->videodelay) + card->videodelay_last = -1; + else + card->videodelay_last = + card->videodelay; + } + } else if( card->videoslow_last ){ + card->videoslow_last = 0; +#ifdef DVB + if (card->audiostate.AVSyncState) +#endif + card->videosync = 1; + AudioStartDecode(card); + } + + + if (card->videodelay > 0) { + if( (DecoderReadByte(card, 0x0ED) & 0x03) + == 0x00) { + card->videodelay--; + if(card->videodelay){ + DecoderWriteByte(card, 0x0ED, + 0x01); + } else { + DecoderWriteByte(card, 0x0ED, + 0x00); + } + } else { + card->videodelay--; + if(!card->videodelay){ + DecoderWriteByte(card, 0x0ED, + 0x00); + } + } + } else if (card->videoskip > 0) { + if ((DecoderReadByte(card, 0x0EC) & 0x03) + == 0x00) { + if (DecoderReadWord(card, 0x096) > 5){ + // pictures in video ES channel + card->videoskip--; + if(card->videoskip) { + DecoderWriteByte(card, + 0x0EC + ,0x03); + } else { + DecoderWriteByte(card, + 0x0EC + ,0x00); + } + } else { + card->videoskip = 0; + DecoderWriteByte (card, 0x0EC, + 0x00); + } + } + } + + + i = (DecoderReadByte(card, 0x113) & 0xFC) | + (DecoderReadByte(card, 0x114) & 0x01); + v = DecoderGetVideoESLevel(card); + if (card->startingV) { + vs = card->VideoESSize; + if (vs > 0) vp = (100 * v) / vs; + else vp = 0; + if (vp > 90) { + MDEBUG(0,": Delayed Video Decoder start\n"); + card->startingV = 0; + DecoderStartDecode(card); + //DecoderSetVideoPanic(card, 1, 3); + // video panic at 3 pictures + //DecoderSetVideoPanic(card, 0, DecoderGetVideoESSize(card) / 4); // video panic at 25 percent + } + } + a = DecoderGetAudioESLevel(card); + if (card->startingA) { + as = card->AudioESSize; + if (as > 0) ap = (100 * a) / as; + else ap = 0; + if (ap > 90) { + MDEBUG(0,": Delayed Audio Decoder start\n"); + AudioSetPlayMode(card, MAUDIO_PLAY); + if (!AudioStart(card)) { + card->startingA = 0; + } + } + } + if (card->fields >= 250) { // 5 seconds (PAL) + SCR_base = DecoderReadSCR(card, 0x009); + SCR_compareA = DecoderReadSCR(card, 0x014); + SCR_compareV = DecoderReadSCR(card, 0x00D); + if (DecoderReadByte(card, 0x013) & 0x03) + card->fields = 0; + } + } + + if (intr[0] & 0x04) { // First Slice Start Code + if (card->showvideo) { + // Unmute card video if first picture slice detected + VideoSetBackground(card, 0, 0, 0, 0); // Video on black + card->showvideo = 0; + } + } + + if (intr[0] & 0x02 ) { // Aux/User Data Fifo + used = 0; + while ( (used++ < 1000) && + (layer = DecoderReadByte(card, 0x040)) & 0x03){ + card->AuxFifo[card->AuxFifoHead] = + ((layer << 6) & 0x0700) | + DecoderReadByte(card, 0x043); + card->AuxFifoHead = (card->AuxFifoHead + 1) & + FIFO_MASK; + } + if (used < 1000) DecoderReadAuxFifo(card); + used = 0; + + while ( (used++ < 1000) && + (layer = DecoderReadByte(card, 0x041)) & 0x03){ + card->DataFifo[card->DataFifoHead] = + ((layer << 6) & 0x0300) | + DecoderReadByte(card, 0x043); + card->DataFifoHead = (card->DataFifoHead + 1) + & FIFO_MASK; + } + if (used < 1000 ) DecoderReadDataFifo(card); + } + + if ((intr[0] & 0x01) != card->intdecodestatus) { + // decode status + card->intdecodestatus = intr[0] & 0x01; + MDEBUG(0, ": Int - decode status now %s\n", + ((card->intdecodestatus) ? + "running" : "stopped")); + if (card->intdecodestatus) { // now running + //DecoderSetVideoPanic(card, 1, 3); + // video panic at 3 pictures + card->showvideo = 1; + } else { // now stopped + if (card->closing) { + card->closing = 0; + CloseCard(card); + } + } + + } + + if (intr[1] & 0x10) { // Begin Active Video + if (card->highlight_valid) { + for (i = 0; i < 10; i++) + DecoderWriteByte(card, 0x1C0 + i, + card->highlight[i]); + card->highlight_valid = 0; + } + } + if (intr[1] & 0x08) { // SPU Start Code Detected + MDEBUG(0, ": Int - SPU Start Code Detected\n"); + } + + if (intr[1] & 0x04) { // SCR compare audio + MDEBUG(0, ": Int - SCR compare audio\n"); + DecoderDelByte(card, 0x013, 0x01); + AudioStart(card); + } + + if (intr[2] & 0x20) { // DSI PES data ready + DecoderReadNavipack(card); + } + + if (intr[2] & 0x06) { // Audio / Video PES data ready + ReadPESHeaders(card); + } + + if (intr[3] & 0x40) { // CSS + card->css.status = DecoderReadByte(card, 0x0B0); + if (card->css.status&0x01) + card->css.ChallengeReady = 1; + // challenge ready + if (card->css.status&0x02) + card->css.ResponseReady = 1; + // response ready + if (card->css.status&0x04) + card->css.DiskKey = 1; + // Disk key ready + if (card->css.status&0x08) + card->css.Error = 1; + // Disk key error + if (card->css.status&0x10) + card->css.TitleKey = 1; + // Title key ready + if (card->css.status&0x20) + card->css.TitleKeyDiff = 1; + // Title key error + } + + + if (intr[3] & 0x30) { + // Audio/Video ES channel buffer underflow + MDEBUG(1,": Int - ES channel buffer underflow\n"); + if (card->closing) { + card->closing = 0; + CloseCard(card); + } + } + + if (intr[4] & 0x10 ) { // SPU decode error + MDEBUG(1,": Int - SPU decode error: (1CA)=0x%02X\n", + DecoderReadByte(card, 0x1CA)); + DecoderDelByte(card, 0x1A0, 0x01); // SPU decode stop + DecoderSetByte(card, 0x1A0, 0x01); // SPU decode start + } + + // Audio / Video Syncronisation + + if (card->videosync && !card->videoskip && !card->videodelay) { + SCR_base = DecoderReadSCR(card, 0x009); + SCR_compareV = DecoderReadSCR(card, 0x00D); + if (intr[1] & 0x02) { // picture start code detected + DecoderMaskByte(card, 0x011, 0x03, 0x01); + // Set SCR compare/capture mode to capture + DecoderSetByte(card, 0x11, 0x04); + // Set "capture on picture start" + if (intr[1] & 0x01) { + // audio sync code detected + DecoderSetByte(card, 0x11, 0x08); + // Set "capture on audio sync code" + } + VideoAddr = DecoderReadRWAddr(card,0x080); + if (PTSGetPTS(&card->VideoPTSStore, VideoAddr, + &PTS)) { + card->oldVPTS = card->VPTS; + card->VPTS = PTS; + card->VSCR = ((long)SCR_compareV + - (long)PTS) / 2; +// card->VideoTime = ISRTime; + } + } else if (intr[1] & 0x01) { + // audio sync code detected + DecoderMaskByte(card, 0x011, 0x03, 0x01); + // Set SCR compare/capture mode to capture + DecoderSetByte(card, 0x11, 0x08); + // Set "capture on audio sync code" + AudioAddr = DecoderReadRWAddr(card,0x083); + if (PTSGetPTS(&card->AudioPTSStore, AudioAddr, + &PTS)) { + card->oldAPTS = card->APTS; + card->APTS = PTS; + card->ASCR = ((long)SCR_compareV - + (long)PTS) / 2; + } else { + card->ASCR = 0x7FFFFFFF; + } + + if (card->VSCR != 0x7FFFFFFF) { + if (card->ASCR != 0x7FFFFFFF) { + DeltaSyncTime = ISRTime - + card->SyncTime; + card->SyncTime = ISRTime; + + // Calculate Audio and Video SCR difference + Offset = (card->ASCR - + card->VSCR - + (10 * 736)) / 736; + + // if the APTS and SCR are off update SCR to keep SubPic synced + if ((SCR_compareV > card->APTS) + || ((card->APTS - + SCR_compareV) > + 10000)) { + Offset = 0; + SetSCR(card, + card->APTS); + } + + // if more than 3 frames away + if ((Offset > 3) || + (Offset < -3)) { + if (Offset > 0 ) { + card->videodelay = 0; + if (Offset < 100) { + if (Offset < 10) { + card->videodelay = 1; + } else { + card->videodelay = Offset / 2; + if (card->videodelay > 20) { + card->videodelay = 20; + } + } + MDEBUG(0,": <<< Pausing %d\n", card->videodelay); + } else { + } + } else { + card->videoskip = 0; + if (Offset > -100) { + if (Offset < -10) { + card->videoskip = 10; + } else { + card->videoskip = 3; + } + MDEBUG(0, ": >>> FForward %d\n", card->videoskip); + } + } + } else { + } + card->VSCR = 0x7FFFFFFF; + } + } + } + } + } + DecoderWriteByte(card, 0x006, 0x01); // Clear Interrupt Pin +} + +// Enable the IRQ Masks +void L64021InstallIntr(struct cvdv_cards *card) { + u8 data; + + data=0; + data |= 0x80; // new field + data |= 0x40; // audio sync recovery + data |= 0x20; // SPU SCR compare + // data |= 0x10; // SDRAM Transfer Done + // data |= 0x08; // Sequence End Code Detect + data |= 0x04; // First Slice Start Code + data |= 0x02; // Aux/User Data Fifo + data |= 0x01; // decode status + DecoderWriteByte(card, 0x000, (~data) & 0xFF); + + data = 0; + // data |= 0x80; // SCR compare + // data |= 0x40; // SCR Overflow + // data |= 0x20; // Begin Vertical Blank + data |= 0x10; // Begin Active Video + data |= 0x08; // SPU Start Code Detected + data |= 0x04; // SCR compare audio + data |= 0x02; // picture start code detected + data |= 0x01; // audio sync code detected + DecoderWriteByte(card, 0x001, (~data) & 0xFF); + + data = 0; + // data |= 0x80; // DTS video event + // data |= 0x40; // DTS audio event + data |= 0x20; // DSI PES data ready + // data |= 0x10; // Seq end code in video channel + data |= 0x08; // SPU PES data ready + data |= 0x04; // Video PES data ready + data |= 0x02; // Audio PES data ready + // data |= 0x01; // Pack data ready + DecoderWriteByte(card, 0x002, (~data) & 0xFF); + + data = 0; + // data |= 0x80; // Reserved + data |= 0x40; // CSS + data |= 0x20; // Video ES channel buffer underflow + data |= 0x10; // Audio ES channel buffer underflow + // data |= 0x08; // Data Dump channel PES data ready + data |= 0x04; // SPU channel buffer overflow + //data |= 0x02; // Video ES channel buffer overflow + //data |= 0x01; // Audio ES channel buffer overflow + DecoderWriteByte(card, 0x003, (~data) & 0xFF); + + data = 0; +// data |= 0x80; // S/PDIF channel buffer underflow + // data |= 0x40; // packet error + // data |= 0x20; // reserved + data |= 0x10; // SPU decode error +// data |= 0x08; // Audio Sync error +// data |= 0x04; // Audio CRC or illegal bit error +// data |= 0x02; // context error +// data |= 0x01; // VLC or Run length error + DecoderWriteByte(card, 0x004, (~data) & 0xFF); + card->IntInstalled = 1; +} + +int L64021RemoveIntr(struct cvdv_cards *card) { + // Disable the IRQ Masks + DecoderWriteByte(card, 0x000, 0xFF); // No ints + DecoderWriteByte(card, 0x001, 0xFF); // No ints + DecoderWriteByte(card, 0x002, 0xFF); // No ints + DecoderWriteByte(card, 0x003, 0xFF); // No ints + DecoderWriteByte(card, 0x004, 0xFF); // No ints + card->IntInstalled = 0; + return 0; +} + +int L64021Reset(struct cvdv_cards *card) { + L64021RemoveIntr(card); // Stop interrupts + // Reset + MDEBUG(1, ": L64021 Software reset...\n"); + //DecoderSetByte(card, 0x007, 0x20); // reset on + DecoderMaskByte(card, 0x007, 0xE2, 0xE2); // reset on + while (!(DecoderReadByte(card, 0x007) & 0x02)) ; // wait until reset is done + //DecoderDelByte(card, 0x007, 0x20); // reset off + DecoderMaskByte(card, 0x007, 0xE2, 0xC2); // reset off + MDEBUG(1, ": L64021 Software reset done.\n"); + DecoderStopChannel(card); + DecoderStopDecode(card); + DecoderStreamReset(card); + DecoderSetupReset(card); + printk(KERN_INFO LOGNAME ": L64021 Rev. 0x%02X reset successfully.\n", +DecoderReadByte(card, 0x0F5)); + return 0; +} + +int L64021Setup(struct cvdv_cards *card) { + MDEBUG(1, ": -- L64021Setup\n"); + DecoderWriteByte(card, 0x0C1, 0x88); // + switch (card->videomode) { + case NTSC: // NTSC M, N. America, Taiwan, Japan + DecoderMaskByte(card, 0x122, 0x03, 0x01); // Television Standard: NTSC + /* Default values: + DecoderWriteByte(card, 0x116, 90); // Main Reads per Line + DecoderWriteByte(card, 0x11A, 4); // Vline Count Init + DecoderWriteByte(card, 0x11C, 0x13); // Pixel State Reset Value / BT.656 Mode / Sync Active Low + DecoderWriteByte(card, 0x129, 23); // Start- and End Row + DecoderWriteByte(card, 0x12A, 262 & 0xFF); + DecoderWriteByte(card, 0x12B, (262>>4)&0x70); + DecoderWriteByte(card, 0x12C, 244 & 0xFF); // Start- and End Column + DecoderWriteByte(card, 0x12D, 1683 & 0xFF); + DecoderWriteByte(card, 0x12E, ((1683>>4)&0x70)|((244>>8)&0x07)); + DecoderWriteByte(card, 0x132, 240 & 0xFF); // SAV Column + DecoderWriteByte(card, 0x133, 1684 & 0xFF); // EAV Column + DecoderWriteByte(card, 0x134, ((1684>>4)&0x70)|((240>>8)&0x07)); + DecoderWriteByte(card, 0x12F, (21&0x1F)|((262>>3)&0x20)|(1<<6)|((265>>1)&0x80)); // VCode Zero... + DecoderWriteByte(card, 0x130, 262&0xFF); // ... and VCode Even + DecoderWriteByte(card, 0x131, 265&0xFF); // ... and FCode + */ + break; + case PAL: // PAL-B, D, G, H, I, Europe, Asia + DecoderMaskByte(card, 0x122, 0x03, 0x02); // Television Standard: PAL + /* Default values: + DecoderWriteByte(card, 0x116, 90); // Main Reads per Line + DecoderWriteByte(card, 0x11A, 1); // Vline Count Init + DecoderWriteByte(card, 0x11C, 0x13); // Pixel State Reset Value / BT.656 Mode / Sync Active Low + DecoderWriteByte(card, 0x129, 23); // Start- and End Row + DecoderWriteByte(card, 0x12A, 310 & 0xFF); + DecoderWriteByte(card, 0x12B, (310>>4)&0x70); + DecoderWriteByte(card, 0x12C, 264 & 0xFF); // Start- and End Column + DecoderWriteByte(card, 0x12D, 1703 & 0xFF); + DecoderWriteByte(card, 0x12E, ((1703>>4)&0x70)|((264>>8)&0x07)); + DecoderWriteByte(card, 0x132, 260 & 0xFF); // SAV Column + DecoderWriteByte(card, 0x133, 1704 & 0xFF); // EAV Column + DecoderWriteByte(card, 0x134, ((1704>>4)&0x70)|((260>>8)&0x07)); + DecoderWriteByte(card, 0x12F, (21&0x1F)|((310>>3)&0x20)|(0<<6)|((312>>1)&0x80)); // VCode Zero... + DecoderWriteByte(card, 0x130, 310&0xFF); // ... and VCode Even + DecoderWriteByte(card, 0x131, 312&0xFF); // ... and FCode + */ + break; + case PAL60: // PAL 60Hz + case NTSC60: // NTSC 60Hz, USA HDTV + case PALM: // PAL-M normal, Brazil + case PALM60: // PAL-M HDTV, Brazil + case PALN: // PAL-N, Uruguay, Paraguay + case PALNc: // PAL-Nc, Argentinia + default: // TODO: set mode according to other standards + DecoderMaskByte(card, 0x122, 0x03, 0x00); // Television Standard: User programmed + DecoderWriteByte(card, 0x116, 90); // Main Reads per Line + DecoderWriteByte(card, 0x11A, 1); // Vline Count Init + DecoderWriteByte(card, 0x11C, 0x13); // Pixel State Reset Value / BT.656 Mode / Sync Active Low + DecoderWriteByte(card, 0x129, 23); // Start- and End Row + DecoderWriteByte(card, 0x12A, 310 & 0xFF); + DecoderWriteByte(card, 0x12B, (310>>4)&0x70); + DecoderWriteByte(card, 0x12C, 264 & 0xFF); // Start- and End Column + DecoderWriteByte(card, 0x12D, 1703 & 0xFF); + DecoderWriteByte(card, 0x12E, ((1703>>4)&0x70)|((264>>8)&0x07)); + DecoderWriteByte(card, 0x132, 260 & 0xFF); // SAV Column + DecoderWriteByte(card, 0x133, 1704 & 0xFF); // EAV Column + DecoderWriteByte(card, 0x134, ((1704>>4)&0x70)|((260>>8)&0x07)); + DecoderWriteByte(card, 0x12F, (21&0x1F)|((310>>3)&0x20)|(0<<6)|((312>>1)&0x80)); // VCode Zero... + DecoderWriteByte(card, 0x130, 310&0xFF); // ... and VCode Even + DecoderWriteByte(card, 0x131, 312&0xFF); // ... and FCode + break; + } + DecoderWriteByte(card, 0x045, 0x00); // disable compares and panic mode + DecoderWriteByte(card, 0x094, 0x00); // disable TOS Detect + DecoderMaskByte(card, 0x109, 0x30, 0x00); // Display Override off, don't change OSD, Background + DecoderWriteByte(card, 0x112, 0x00); // Disable Horizontal 2:1 Filter + DecoderWriteByte(card, 0x113, 0x14); // FreezeMode 1 / 3:2 Pulldown / Repeat First Field / Top Field First + DecoderWriteByte(card, 0x114, ( 5 <<3)|( 0 <<1)|( 0 <<2)|( 1 <<7)); // VideoMode/FilterEnable/FilterAB/FieldSyncEnable + DecoderWriteByte(card, 0x115, 0); // Horizontal Filter Scale + DecoderWriteByte(card, 0x117, 0x80); // Automatic Field Inversion Correction +// DecoderWriteByte(card, 0x117, 0x00); // no Automatic Field Inversion Correction + DecoderWriteByte(card, 0x118, 0); // Horizontal Pan and Scan Word Offset (signed) + DecoderWriteByte(card, 0x119, 0); // Vertical Pan and Scan Line Offset + DecoderWriteByte(card, 0x11B, 0x00); // Override Picture Width +// if (0) { // letterbox +// DecoderWriteByte(card, 0x114, (DecoderReadByte(card, 0x114) & ~0x78) | 0x40); // mode 8 +// DecoderWriteByte(card, 0x129, 0x35); +// DecoderWriteByte(card, 0x12A, 0xE7); +// DecoderWriteByte(card, 0x114, DecoderReadByte(card, 0x114) & ~0x77); // ??? +// } else { +// if (0) { // MPEG-1 +// DecoderWriteByte(card, 0x114, (DecoderReadByte(card, 0x114) & ~0x78) | 0x10); // mode 2 +// } else { // MPEG-2 +// DecoderWriteByte(card, 0x114, (DecoderReadByte(card, 0x114) & ~0x78) | 0x28); // mode 5 +// } +// } + L64021InstallIntr(card); // Set the interrupt masks, again + + return 0; +} + +int L64021Init(struct cvdv_cards *card) { +MDEBUG(1, ": -- L64021Init\n"); + L64021Reset(card); + L64021Setup(card); + VideoSetBackground(card, 1, 0, 0, 0); // black + DecoderWriteByte(card, 0x135, 0x01); // Enable Video Out, Disable SPU Mix + DecoderWriteByte(card,0x11C,0x13); // Pixel State Reset Value / BT.656 Mode / Sync Active Low + L64021InstallIntr(card); + return 0; +} + + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/decoder.h linux.19rc3-ac4/drivers/media/video/margi/decoder.h --- linux.19rc3/drivers/media/video/margi/decoder.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/decoder.h 2002-07-29 17:29:11.000000000 +0100 @@ -0,0 +1,70 @@ +/* + decoder.h + + Copyright (C) Christian Wolff for convergence integrated media. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef CVDV_DECODER_H +#define CVDV_DECODER_H + +#include "cardbase.h" + + +int DecoderGetNavi(struct cvdv_cards *card, u8 * navidata); + +// returns 1 on overrun, 0 on no error +int DecoderQueueNavi(struct cvdv_cards *card, u8 * navidata); + +u32 ParseSCR(const u8 * scrdata); + +u32 SetSCR(struct cvdv_cards *card, u32 SCR_base); + +void DecoderPause(struct cvdv_cards *card); + +void DecoderUnPause(struct cvdv_cards *card); + +void CloseCard(struct cvdv_cards *card); + + +void DecoderReadAudioInfo(struct cvdv_cards *card); + +void DecoderReadAuxFifo(struct cvdv_cards *card); + +void DecoderReadDataFifo(struct cvdv_cards *card); + +int DecoderReadNavipack(struct cvdv_cards *card); + +int AudioStart(struct cvdv_cards *card); + +// Puts decoder in pause after so many fields +void StepsToPause(struct cvdv_cards *card, int steps); + +void L64021Intr(struct cvdv_cards *card); +//static void L64021Intr(struct cvdv_cards *card); + +// Enable the IRQ Masks +void L64021InstallIntr(struct cvdv_cards *card); + +int L64021RemoveIntr(struct cvdv_cards *card); + +int L64021Reset(struct cvdv_cards *card); + +int L64021Setup(struct cvdv_cards *card); + +int L64021Init(struct cvdv_cards *card); + +#endif /* CVDV_DECODER_H */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/dmxdev.c linux.19rc3-ac4/drivers/media/video/margi/dmxdev.c --- linux.19rc3/drivers/media/video/margi/dmxdev.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/dmxdev.c 2002-07-29 13:58:42.000000000 +0100 @@ -0,0 +1,1065 @@ +/* + * dmxdev.c - DVB demultiplexer device + * + * Copyright (C) 2000 Ralph Metzler + * & Marcus Metzler + for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * 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 Lesser 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. + * + */ + +#include +#include +#include +#include + +#include "cardbase.h" +#include "dmxdev.h" + +#ifdef MODULE +MODULE_DESCRIPTION(""); +MODULE_AUTHOR("Ralph Metzler, Marcus Metzler"); +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif +MODULE_PARM(debug,"i"); +#endif +static int debug = 0; + +#define dprintk if (debug) printk + +inline dmxdev_filter_t * +DmxDevFile2Filter(dmxdev_t *dmxdev, struct file *file) +{ + return (dmxdev_filter_t *) file->private_data; +} + +inline dmxdev_dvr_t * +DmxDevFile2DVR(dmxdev_t *dmxdev, struct file *file) +{ + return (dmxdev_dvr_t *) file->private_data; +} + +static inline void +DmxDevBufferInit(dmxdev_buffer_t *buffer) +{ + buffer->data=0; + buffer->size=8192; + buffer->pread=0; + buffer->pwrite=0; + buffer->error=0; + init_waitqueue_head(&buffer->queue); +} + +static inline int +DmxDevBufferWrite(dmxdev_buffer_t *buf, uint8_t *src, int len) +{ + int split; + int free; + int todo; + + if (!len) + return 0; + if (!buf->data) + return 0; + + free=buf->pread-buf->pwrite; + split=0; + if (free<=0) { + free+=buf->size; + split=buf->size-buf->pwrite; + } + if (len>=free) { + dprintk("dmxdev: buffer overflow\n"); + return -1; + } + if (split>=len) + split=0; + todo=len; + if (split) { + memcpy(buf->data + buf->pwrite, src, split); + todo-=split; + buf->pwrite=0; + } + memcpy(buf->data + buf->pwrite, src+split, todo); + buf->pwrite=(buf->pwrite+todo)%buf->size; + return len; +} + +static ssize_t +DmxDevBufferRead(dmxdev_buffer_t *src, int non_blocking, + char *buf, size_t count, loff_t *ppos) +{ + unsigned long todo=count; + int split, avail, error; + + if (!src->data) + return 0; + if ((error=src->error)) { + src->error=0; + return error; + } + + if (non_blocking && (src->pwrite==src->pread)) + return -EWOULDBLOCK; + + while (todo>0) { + if (non_blocking && (src->pwrite==src->pread)) + return (count-todo) ? (count-todo) : -EWOULDBLOCK; + + if (wait_event_interruptible(src->queue, + (src->pread!=src->pwrite) || + (src->error))<0) + return count-todo; + + if ((error=src->error)) { + src->error=0; + return error; + } + + split=src->size; + avail=src->pwrite - src->pread; + if (avail<0) { + avail+=src->size; + split=src->size - src->pread; + } + if (avail>todo) + avail=todo; + if (splitdata+src->pread, split)) + return -EFAULT; + buf+=split; + src->pread=0; + todo-=split; + avail-=split; + } + if (avail) { + if (copy_to_user(buf, src->data+src->pread, avail)) + return -EFAULT; + src->pread = (src->pread + avail) % src->size; + todo-=avail; + buf+=avail; + } + } + return count; +} + +static dmx_frontend_t * +get_fe(dmx_demux_t *demux, int type) +{ + struct list_head *head, *pos; + + head=demux->get_frontends(demux); + if (!head) + return 0; + list_for_each(pos, head) + if (DMX_FE_ENTRY(pos)->source==type) + return DMX_FE_ENTRY(pos); + + return 0; +} + +static inline void +DmxDevDVRStateSet(dmxdev_dvr_t *dmxdevdvr, int state) +{ + spin_lock_irq(&dmxdevdvr->dev->lock); + dmxdevdvr->state=state; + spin_unlock_irq(&dmxdevdvr->dev->lock); +} + +int +DmxDevDVROpen(dmxdev_t *dmxdev, struct file *file) +{ + dmx_frontend_t *front; + + down(&dmxdev->mutex); + if ((file->f_flags&O_ACCMODE)==O_RDWR) { + if (!(dmxdev->capabilities&DMXDEV_CAP_DUPLEX)) { + up(&dmxdev->mutex); + return -EOPNOTSUPP; + } + } + + if ((file->f_flags&O_ACCMODE)==O_RDONLY) { + DmxDevBufferInit(&dmxdev->dvr_buffer); + dmxdev->dvr_buffer.size=DVR_BUFFER_SIZE; + dmxdev->dvr_buffer.data=vmalloc(DVR_BUFFER_SIZE); + if (!dmxdev->dvr_buffer.data) { + up(&dmxdev->mutex); + return -ENOMEM; + } + } + + if ((file->f_flags&O_ACCMODE)==O_WRONLY) { + dmxdev->dvr_orig_fe=dmxdev->demux->frontend; + + if (!dmxdev->demux->write) { + up(&dmxdev->mutex); + return -EOPNOTSUPP; + } + + front=get_fe(dmxdev->demux, DMX_MEMORY_FE); + + if (!front) { + up(&dmxdev->mutex); + return -EINVAL; + } + dmxdev->demux->disconnect_frontend(dmxdev->demux); + dmxdev->demux->connect_frontend(dmxdev->demux, front); + } + up(&dmxdev->mutex); + return 0; +} + +int +DmxDevDVRClose(dmxdev_t *dmxdev, struct file *file) +{ + down(&dmxdev->mutex); + if ((file->f_flags&O_ACCMODE)==O_WRONLY) { + dmxdev->demux->disconnect_frontend(dmxdev->demux); + dmxdev->demux->connect_frontend(dmxdev->demux, + dmxdev->dvr_orig_fe); + } + if ((file->f_flags&O_ACCMODE)==O_RDONLY) { + if (dmxdev->dvr_buffer.data) { + void *mem=dmxdev->dvr_buffer.data; + mb(); + spin_lock_irq(&dmxdev->lock); + dmxdev->dvr_buffer.data=0; + spin_unlock_irq(&dmxdev->lock); + vfree(mem); + } + } + up(&dmxdev->mutex); + return 0; +} + +ssize_t +DmxDevDVRWrite(dmxdev_t *dmxdev, struct file *file, + const char *buf, size_t count, loff_t *ppos) +{ + int ret; + + if (!dmxdev->demux->write) + return -EOPNOTSUPP; + if ((file->f_flags&O_ACCMODE)!=O_WRONLY) + return -EINVAL; + down(&dmxdev->mutex); + ret=dmxdev->demux->write(dmxdev->demux, buf, count); + up(&dmxdev->mutex); + return ret; +} + +ssize_t +DmxDevDVRRead(dmxdev_t *dmxdev, struct file *file, + char *buf, size_t count, loff_t *ppos) +{ + int ret; + + down(&dmxdev->mutex); + ret= DmxDevBufferRead(&dmxdev->dvr_buffer, + file->f_flags&O_NONBLOCK, + buf, count, ppos); + up(&dmxdev->mutex); + return ret; +} + +static inline void +DmxDevFilterStateSet(dmxdev_filter_t *dmxdevfilter, int state) +{ + spin_lock_irq(&dmxdevfilter->dev->lock); + dmxdevfilter->state=state; + spin_unlock_irq(&dmxdevfilter->dev->lock); +} + +static int +DmxDevSetBufferSize(dmxdev_filter_t *dmxdevfilter, unsigned long size) +{ + dmxdev_buffer_t *buf=&dmxdevfilter->buffer; + + if (buf->size==size) + return 0; + if (dmxdevfilter->state>=DMXDEV_STATE_GO) + return -EBUSY; + spin_lock_irq(&dmxdevfilter->dev->lock); + if (buf->data) + vfree(buf->data); + buf->data=0; + buf->size=size; + buf->pwrite=buf->pread=0; + spin_unlock_irq(&dmxdevfilter->dev->lock); + + if (buf->size) { + void *mem=vmalloc(dmxdevfilter->buffer.size); + + if (!mem) + return -ENOMEM; + spin_lock_irq(&dmxdevfilter->dev->lock); + buf->data=mem; + spin_unlock_irq(&dmxdevfilter->dev->lock); + } + return 0; +} + +static void +DmxDevFilterTimeout(unsigned long data) +{ + dmxdev_filter_t *dmxdevfilter=(dmxdev_filter_t *)data; + + dmxdevfilter->buffer.error=-ETIMEDOUT; + spin_lock_irq(&dmxdevfilter->dev->lock); + dmxdevfilter->state=DMXDEV_STATE_TIMEDOUT; + spin_unlock_irq(&dmxdevfilter->dev->lock); + wake_up(&dmxdevfilter->buffer.queue); +} + +static void +DmxDevFilterTimer(dmxdev_filter_t *dmxdevfilter) +{ + struct dmxSctFilterParams *para=&dmxdevfilter->params.sec; + + del_timer(&dmxdevfilter->timer); + if (para->timeout) { + dmxdevfilter->timer.function=DmxDevFilterTimeout; + dmxdevfilter->timer.data=(unsigned long) dmxdevfilter; + dmxdevfilter->timer.expires=jiffies+1+(HZ/2+HZ*para->timeout)/1000; + add_timer(&dmxdevfilter->timer); + } +} + +static int +DmxDevSectionCallback(u8 *buffer1, size_t buffer1_len, + u8 *buffer2, size_t buffer2_len, + dmx_section_filter_t *filter, + dmx_success_t success) +{ + dmxdev_filter_t *dmxdevfilter=(dmxdev_filter_t *) filter->priv; + int ret; + + if (dmxdevfilter->buffer.error) + return 0; + spin_lock(&dmxdevfilter->dev->lock); + if (dmxdevfilter->state!=DMXDEV_STATE_GO) { + spin_unlock(&dmxdevfilter->dev->lock); + return 0; + } + del_timer(&dmxdevfilter->timer); + dprintk("dmxdev: section callback %02x %02x %02x %02x %02x %02x\n", + buffer1[0], buffer1[1], + buffer1[2], buffer1[3], + buffer1[4], buffer1[5]); + ret=DmxDevBufferWrite(&dmxdevfilter->buffer, buffer1, buffer1_len); + if (ret==buffer1_len) { + ret=DmxDevBufferWrite(&dmxdevfilter->buffer, buffer2, buffer2_len); + } + if (ret<0) { + dmxdevfilter->buffer.pwrite=dmxdevfilter->buffer.pread; + dmxdevfilter->buffer.error=-EBUFFEROVERFLOW; + } + if (dmxdevfilter->params.sec.flags&DMX_ONESHOT) + dmxdevfilter->state=DMXDEV_STATE_DONE; + spin_unlock(&dmxdevfilter->dev->lock); + wake_up(&dmxdevfilter->buffer.queue); + return 0; +} + +static int +DmxDevTSCallback(u8 *buffer1, size_t buffer1_len, + u8 *buffer2, size_t buffer2_len, + dmx_ts_feed_t *feed, + dmx_success_t success) +{ + dmxdev_filter_t *dmxdevfilter=(dmxdev_filter_t *) feed->priv; + dmxdev_buffer_t *buffer; + int ret; + + if (dmxdevfilter->params.pes.output==DMX_OUT_DECODER) + return 0; + + if (dmxdevfilter->params.pes.output==DMX_OUT_TAP) + buffer=&dmxdevfilter->buffer; + else + buffer=&dmxdevfilter->dev->dvr_buffer; + if (buffer->error) { + wake_up(&buffer->queue); + return 0; + } + ret=DmxDevBufferWrite(buffer, buffer1, buffer1_len); + if (ret==buffer1_len) + ret=DmxDevBufferWrite(buffer, buffer2, buffer2_len); + if (ret<0) { + buffer->pwrite=buffer->pread; + buffer->error=-EBUFFEROVERFLOW; + } + wake_up(&buffer->queue); + return 0; +} + + +/* stop feed but only mark the specified filter as stopped (state set) */ + +static int +DmxDevFeedStop(dmxdev_filter_t *dmxdevfilter) +{ + DmxDevFilterStateSet(dmxdevfilter, DMXDEV_STATE_SET); + + switch (dmxdevfilter->type) { + case DMXDEV_TYPE_SEC: + del_timer(&dmxdevfilter->timer); + dmxdevfilter->feed.sec->stop_filtering(dmxdevfilter->feed.sec); + break; + case DMXDEV_TYPE_PES: + dmxdevfilter->feed.ts->stop_filtering(dmxdevfilter->feed.ts); + break; + default: + return -EINVAL; + } + return 0; +} + + +/* start feed associated with the specified filter */ + +static int +DmxDevFeedStart(dmxdev_filter_t *dmxdevfilter) +{ + DmxDevFilterStateSet(dmxdevfilter, DMXDEV_STATE_GO); + + switch (dmxdevfilter->type) { + case DMXDEV_TYPE_SEC: + dmxdevfilter->feed.sec->start_filtering(dmxdevfilter->feed.sec); + break; + case DMXDEV_TYPE_PES: + dmxdevfilter->feed.ts->start_filtering(dmxdevfilter->feed.ts); + break; + default: + return -EINVAL; + } + return 0; +} + + +/* restart section feed if it has filters left associated with it, + otherwise release the feed */ + +static int +DmxDevFeedRestart(dmxdev_filter_t *dmxdevfilter) +{ + int i; + dmxdev_t *dmxdev=dmxdevfilter->dev; + dvb_pid_t pid=dmxdevfilter->params.sec.pid; + + for (i=0; ifilternum; i++) + if (dmxdev->filter[i].state>=DMXDEV_STATE_GO && + dmxdev->filter[i].type==DMXDEV_TYPE_SEC && + dmxdev->filter[i].pid==pid) { + DmxDevFeedStart(&dmxdev->filter[i]); + return 0; + } + + dmxdevfilter->dev->demux-> + release_section_feed(dmxdev->demux, + dmxdevfilter->feed.sec); + + return 0; +} + +static int +DmxDevFilterStop(dmxdev_filter_t *dmxdevfilter) +{ + if (dmxdevfilter->statetype) { + case DMXDEV_TYPE_SEC: + if (!dmxdevfilter->feed.sec) + break; + DmxDevFeedStop(dmxdevfilter); + if (dmxdevfilter->filter.sec) + dmxdevfilter->feed.sec-> + release_filter(dmxdevfilter->feed.sec, + dmxdevfilter->filter.sec); + DmxDevFeedRestart(dmxdevfilter); + dmxdevfilter->feed.sec=0; + break; + case DMXDEV_TYPE_PES: + if (!dmxdevfilter->feed.ts) + break; + DmxDevFeedStop(dmxdevfilter); + dmxdevfilter->dev->demux-> + release_ts_feed(dmxdevfilter->dev->demux, + dmxdevfilter->feed.ts); + dmxdevfilter->feed.ts=0; + break; + default: + if (dmxdevfilter->state==DMXDEV_STATE_ALLOCATED) + return 0; + return -EINVAL; + } + dmxdevfilter->buffer.pwrite=dmxdevfilter->buffer.pread=0; + return 0; +} + +static inline int +DmxDevFilterReset(dmxdev_filter_t *dmxdevfilter) +{ + if (dmxdevfilter->statetype=DMXDEV_TYPE_NONE; + dmxdevfilter->pid=0xffff; + DmxDevFilterStateSet(dmxdevfilter, DMXDEV_STATE_ALLOCATED); + return 0; +} + +static int +DmxDevFilterStart(dmxdev_filter_t *dmxdevfilter) +{ + dmxdev_t *dmxdev=dmxdevfilter->dev; + void *mem; + int ret, i; + + if (dmxdevfilter->statestate>=DMXDEV_STATE_GO) + DmxDevFilterStop(dmxdevfilter); + + mem=dmxdevfilter->buffer.data; + if (!mem) { + mem=vmalloc(dmxdevfilter->buffer.size); + spin_lock_irq(&dmxdevfilter->dev->lock); + dmxdevfilter->buffer.data=mem; + spin_unlock_irq(&dmxdevfilter->dev->lock); + if (!dmxdevfilter->buffer.data) + return -ENOMEM; + } + + switch (dmxdevfilter->type) { + case DMXDEV_TYPE_SEC: + { + struct dmxSctFilterParams *para=&dmxdevfilter->params.sec; + dmx_section_filter_t **secfilter=&dmxdevfilter->filter.sec; + dmx_section_feed_t **secfeed=&dmxdevfilter->feed.sec; + + *secfilter=0; + *secfeed=0; + + /* find active filter/feed with same PID */ + for (i=0; ifilternum; i++) + if (dmxdev->filter[i].state>=DMXDEV_STATE_GO && + dmxdev->filter[i].pid==para->pid) { + if (dmxdev->filter[i].type!=DMXDEV_TYPE_SEC) + return -EBUSY; + *secfeed=dmxdev->filter[i].feed.sec; + break; + } + + /* if no feed found, try to allocate new one */ + if (!*secfeed) { + ret=dmxdev->demux-> + allocate_section_feed(dmxdev->demux, + secfeed, + DmxDevSectionCallback); + if (ret<0) { + printk ("could not alloc feed\n"); + return ret; + } + + ret=(*secfeed)->set(*secfeed, para->pid, 32768, 0, + (para->flags & DMX_CHECK_CRC) ? 1 : 0); + + if (ret<0) { + printk ("could not set feed\n"); + DmxDevFeedRestart(dmxdevfilter); + return ret; + } + } + else + DmxDevFeedStop(dmxdevfilter); + + ret=(*secfeed)->allocate_filter(*secfeed, secfilter); + if (ret<0) { + DmxDevFeedRestart(dmxdevfilter); + dmxdevfilter->feed.sec-> + start_filtering(*secfeed); + dprintk ("could not get filter\n"); + return ret; + } + + (*secfilter)->priv=(void *) dmxdevfilter; + memcpy(&((*secfilter)->filter_value[3]), + &(para->filter.filter[1]), DMX_FILTER_SIZE-1); + memcpy(&(*secfilter)->filter_mask[3], + ¶->filter.mask[1], DMX_FILTER_SIZE-1); + (*secfilter)->filter_value[0]=para->filter.filter[0]; + (*secfilter)->filter_mask[0]=para->filter.mask[0]; + (*secfilter)->filter_mask[1]=0; + (*secfilter)->filter_mask[2]=0; + + dmxdevfilter->todo=0; + dmxdevfilter->feed.sec-> + start_filtering(dmxdevfilter->feed.sec); + DmxDevFilterTimer(dmxdevfilter); + break; + } + + case DMXDEV_TYPE_PES: + { + struct timespec timeout = {0 }; + struct dmxPesFilterParams *para=&dmxdevfilter->params.pes; + dmxOutput_t otype; + int ret; + int ts_type; + dmx_ts_pes_t ts_pes; + dmx_ts_feed_t **tsfeed=&dmxdevfilter->feed.ts; + + dmxdevfilter->feed.ts=0; + otype=para->output; + + ts_pes=(dmx_ts_pes_t) para->pesType; + + if (ts_pesdemux->allocate_ts_feed(dmxdev->demux, + tsfeed, + DmxDevTSCallback); + if (ret<0) + return ret; + + (*tsfeed)->priv=(void *) dmxdevfilter; + ret=(*tsfeed)->set(*tsfeed, para->pid, 188, 32768, 0, timeout); + if (ret<0) { + dmxdev->demux-> + release_ts_feed(dmxdev->demux, *tsfeed); + return ret; + } + if ((*tsfeed)->set_type) + ret=(*tsfeed)->set_type(*tsfeed, ts_type, ts_pes); + if (ret<0) { + dmxdev->demux-> + release_ts_feed(dmxdev->demux, *tsfeed); + return ret; + } + dmxdevfilter->feed.ts-> + start_filtering(dmxdevfilter->feed.ts); + break; + } + default: + return -EINVAL; + } + DmxDevFilterStateSet(dmxdevfilter, DMXDEV_STATE_GO); + return 0; +} + +int +DmxDevFilterNum(dmxdev_t *dmxdev) +{ + int i, num; + + if (!dmxdev->filter) + return 0; + down(&dmxdev->mutex); + for (i=0, num=0; ifilternum; i++) + if (dmxdev->filter[i].state==DMXDEV_STATE_FREE) + num++; + up(&dmxdev->mutex); + return num; +} + +int +DmxDevFilterAlloc(dmxdev_t *dmxdev, struct file *file) +{ + int i; + dmxdev_filter_t *dmxdevfilter; + + if (!dmxdev->filter) + return -EINVAL; + down(&dmxdev->mutex); + for (i=0; ifilternum; i++) + if (dmxdev->filter[i].state==DMXDEV_STATE_FREE) + break; + if (i==dmxdev->filternum) { + up(&dmxdev->mutex); + return -EMFILE; + } + dmxdevfilter=&dmxdev->filter[i]; + file->private_data=dmxdevfilter; + + DmxDevBufferInit(&dmxdevfilter->buffer); + dmxdevfilter->type=DMXDEV_TYPE_NONE; + DmxDevFilterStateSet(dmxdevfilter, DMXDEV_STATE_ALLOCATED); + dmxdevfilter->feed.ts=0; + init_timer(&dmxdevfilter->timer); + + up(&dmxdev->mutex); + //printk("free filters = %d\n", DmxDevFilterNum(dmxdev)); + return 0; +} + +int +DmxDevFilterFree(dmxdev_t *dmxdev, struct file *file) +{ + dmxdev_filter_t *dmxdevfilter; + + down(&dmxdev->mutex); + + if (!(dmxdevfilter=DmxDevFile2Filter(dmxdev, file))) { + up(&dmxdev->mutex); + return -EINVAL; + } + + DmxDevFilterStop(dmxdevfilter); + DmxDevFilterReset(dmxdevfilter); + + if (dmxdevfilter->buffer.data) { + void *mem=dmxdevfilter->buffer.data; + + spin_lock_irq(&dmxdev->lock); + dmxdevfilter->buffer.data=0; + spin_unlock_irq(&dmxdev->lock); + vfree(mem); + } + DmxDevFilterStateSet(dmxdevfilter, DMXDEV_STATE_FREE); + wake_up(&dmxdevfilter->buffer.queue); + up(&dmxdev->mutex); + //printk("free filters = %d\n", DmxDevFilterNum(dmxdev)); + return 0; +} + + +static int +DmxDevFilterSet(dmxdev_t *dmxdev, + dmxdev_filter_t *dmxdevfilter, + struct dmxSctFilterParams *params) +{ + dprintk ("function : %s\n", __FUNCTION__); + + DmxDevFilterStop(dmxdevfilter); + + dmxdevfilter->type=DMXDEV_TYPE_SEC; + dmxdevfilter->pid=params->pid; + memcpy(&dmxdevfilter->params.sec, + params, sizeof(struct dmxSctFilterParams)); + + DmxDevFilterStateSet(dmxdevfilter, DMXDEV_STATE_SET); + + if (params->flags&DMX_IMMEDIATE_START) + return DmxDevFilterStart(dmxdevfilter); + + return 0; +} + +static int +DmxDevPesFilterSet(dmxdev_t *dmxdev, + dmxdev_filter_t *dmxdevfilter, + struct dmxPesFilterParams *params) +{ + DmxDevFilterStop(dmxdevfilter); + + if (params->pesType>DMX_PES_OTHER || params->pesType<0) + return -EINVAL; + + dmxdevfilter->type=DMXDEV_TYPE_PES; + dmxdevfilter->pid=params->pid; + memcpy(&dmxdevfilter->params, params, sizeof(struct dmxPesFilterParams)); + + DmxDevFilterStateSet(dmxdevfilter, DMXDEV_STATE_SET); + + if (params->flags&DMX_IMMEDIATE_START) + return DmxDevFilterStart(dmxdevfilter); + + return 0; +} + +int +DmxDevInit(dmxdev_t *dmxdev) +{ + int i; + + if (dmxdev->demux->open(dmxdev->demux)<0) + return -EUSERS; + + dmxdev->filter=vmalloc(dmxdev->filternum*sizeof(dmxdev_filter_t)); + if (!dmxdev->filter) + return -ENOMEM; + + dmxdev->dvr=vmalloc(dmxdev->filternum*sizeof(dmxdev_dvr_t)); + if (!dmxdev->dvr) { + vfree(dmxdev->filter); + dmxdev->filter=0; + return -ENOMEM; + } + sema_init(&dmxdev->mutex, 1); + spin_lock_init(&dmxdev->lock); + for (i=0; ifilternum; i++) { + dmxdev->filter[i].dev=dmxdev; + dmxdev->filter[i].buffer.data=0; + DmxDevFilterStateSet(&dmxdev->filter[i], DMXDEV_STATE_FREE); + dmxdev->dvr[i].dev=dmxdev; + dmxdev->dvr[i].buffer.data=0; + DmxDevFilterStateSet(&dmxdev->filter[i], DMXDEV_STATE_FREE); + DmxDevDVRStateSet(&dmxdev->dvr[i], DMXDEV_STATE_FREE); + } + DmxDevBufferInit(&dmxdev->dvr_buffer); + MOD_INC_USE_COUNT; + return 0; +} + +void +DmxDevRelease(dmxdev_t *dmxdev) +{ + if (dmxdev->filter) { + vfree(dmxdev->filter); + dmxdev->filter=0; + } + if (dmxdev->dvr) { + vfree(dmxdev->dvr); + dmxdev->dvr=0; + } + dmxdev->demux->close(dmxdev->demux); + MOD_DEC_USE_COUNT; +} + +static ssize_t +DmxDevReadSec(dmxdev_filter_t *dfil, struct file *file, + char *buf, size_t count, loff_t *ppos) +{ + int result, hcount; + int done=0; + + if (dfil->todo<=0) { + hcount=3+dfil->todo; + if (hcount>count) + hcount=count; + result=DmxDevBufferRead(&dfil->buffer, file->f_flags&O_NONBLOCK, + buf, hcount, ppos); + if (result<0) { + dfil->todo=0; + return result; + } + if (copy_from_user(dfil->secheader-dfil->todo, buf, result)) + return -EFAULT; + buf+=result; + done=result; + count-=result; + dfil->todo-=result; + if (dfil->todo>-3) + return done; + dfil->todo=((dfil->secheader[1]<<8)|dfil->secheader[2])&0xfff; + if (!count) + return done; + } + if (count>dfil->todo) + count=dfil->todo; + result=DmxDevBufferRead(&dfil->buffer, file->f_flags&O_NONBLOCK, + buf, count, ppos); + if (result<0) + return result; + dfil->todo-=result; + return (result+done); +} + + +ssize_t +DmxDevRead(dmxdev_t *dmxdev, struct file *file, + char *buf, size_t count, loff_t *ppos) +{ + dmxdev_filter_t *dmxdevfilter=DmxDevFile2Filter(dmxdev, file); + int ret=0; + + down(&dmxdev->mutex); + if (dmxdevfilter->type==DMXDEV_TYPE_SEC) + ret=DmxDevReadSec(dmxdevfilter, file, buf, count, ppos); + else + ret=DmxDevBufferRead(&dmxdevfilter->buffer, + file->f_flags&O_NONBLOCK, + buf, count, ppos); + up(&dmxdev->mutex); + return ret; +} + + +int DmxDevIoctl(dmxdev_t *dmxdev, struct file *file, + unsigned int cmd, unsigned long arg) +{ + void *parg=(void *)arg; + int ret=0; + + dmxdev_filter_t *dmxdevfilter=DmxDevFile2Filter(dmxdev, file); + + if (!dmxdevfilter) + return -EINVAL; + + down(&dmxdev->mutex); + switch (cmd) { + case DMX_START: + if (dmxdevfilter->statedemux->get_pes_pids) { + ret=-EINVAL; + break; + } + dmxdev->demux->get_pes_pids(dmxdev->demux, pids); + if (copy_to_user(parg, pids, 5*sizeof(dvb_pid_t))) + ret=-EFAULT; + break; + } + + default: + ret=-EINVAL; + } + up(&dmxdev->mutex); + return ret; +} + +unsigned int +DmxDevPoll(dmxdev_t *dmxdev, struct file *file, poll_table * wait) +{ + dmxdev_filter_t *dmxdevfilter=DmxDevFile2Filter(dmxdev, file); + + if (!dmxdevfilter) + return -EINVAL; + + if (dmxdevfilter->state==DMXDEV_STATE_FREE) + return 0; + + if (dmxdevfilter->buffer.pread!=dmxdevfilter->buffer.pwrite || + dmxdevfilter->buffer.error) + return (POLLIN | POLLRDNORM | POLLPRI); + + if (dmxdevfilter->state!=DMXDEV_STATE_GO) + return 0; + + poll_wait(file, &dmxdevfilter->buffer.queue, wait); + + if (dmxdevfilter->state==DMXDEV_STATE_FREE) + return 0; + + if (dmxdevfilter->buffer.pread!=dmxdevfilter->buffer.pwrite || + dmxdevfilter->buffer.error) + return (POLLIN | POLLRDNORM | POLLPRI); + + return 0; +} + +int DmxDevDVRIoctl(dmxdev_t *dmxdev, struct file *file, + unsigned int cmd, unsigned long arg) +{ + //void *parg=(void *)arg; + int ret=0; + + down(&dmxdev->mutex); + switch (cmd) { + case DMX_SET_BUFFER_SIZE: + // FIXME: implement + ret=0; + break; + + default: + ret=-EINVAL; + } + up(&dmxdev->mutex); + return ret; +} + +unsigned int +DmxDevDVRPoll(dmxdev_t *dmxdev, struct file *file, poll_table * wait) +{ + if ((file->f_flags&O_ACCMODE)==O_RDONLY) { + if (dmxdev->dvr_buffer.pread!=dmxdev->dvr_buffer.pwrite) + return (POLLIN | POLLRDNORM | POLLPRI); + + poll_wait(file, &dmxdev->dvr_buffer.queue, wait); + + if (dmxdev->dvr_buffer.pread!=dmxdev->dvr_buffer.pwrite) + return (POLLIN | POLLRDNORM | POLLPRI); + + return 0; + } else + return (POLLOUT | POLLWRNORM | POLLPRI); +} + + +#ifdef MODULE +#ifdef EXPORT_SYMTAB +EXPORT_SYMBOL(DmxDevInit); +EXPORT_SYMBOL(DmxDevRelease); + +EXPORT_SYMBOL(DmxDevDVROpen); +EXPORT_SYMBOL(DmxDevDVRClose); +EXPORT_SYMBOL(DmxDevDVRRead); +EXPORT_SYMBOL(DmxDevDVRWrite); +EXPORT_SYMBOL(DmxDevDVRIoctl); +EXPORT_SYMBOL(DmxDevDVRPoll); + +EXPORT_SYMBOL(DmxDevFilterAlloc); +EXPORT_SYMBOL(DmxDevFilterFree); +EXPORT_SYMBOL(DmxDevRead); +EXPORT_SYMBOL(DmxDevIoctl); +EXPORT_SYMBOL(DmxDevPoll); +#endif +#endif diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/dmxdev.h linux.19rc3-ac4/drivers/media/video/margi/dmxdev.h --- linux.19rc3/drivers/media/video/margi/dmxdev.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/dmxdev.h 2002-07-29 15:45:39.000000000 +0100 @@ -0,0 +1,154 @@ +/* + * dmxdev.h + * + * Copyright (C) 2000 Ralph Metzler + * & Marcus Metzler + for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * 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 Lesser 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. + * + */ + +#ifndef _DMXDEV_H_ +#define _DMXDEV_H_ + +#ifndef __KERNEL__ +#define __KERNEL__ +#endif + +#ifdef __DVB_PACK__ +#include "ost/demux.h" +#include "ost/dmx.h" +#else +#include +#include +#endif +#include +#include +#include +#include + +#if LINUX_VERSION_CODE < 0x020300 +#define WAIT_QUEUE struct wait_queue* +#define init_waitqueue_head(wq) *(wq) = NULL; +#define DECLARE_WAITQUEUE(wait, current) struct wait_queue wait = { current, NULL } +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) +#else +#define WAIT_QUEUE wait_queue_head_t +#endif + +typedef enum { + DMXDEV_TYPE_NONE, + DMXDEV_TYPE_SEC, + DMXDEV_TYPE_PES, +} dmxdev_type_t; + +typedef enum { + DMXDEV_STATE_FREE, + DMXDEV_STATE_ALLOCATED, + DMXDEV_STATE_SET, + DMXDEV_STATE_GO, + DMXDEV_STATE_DONE, + DMXDEV_STATE_TIMEDOUT +} dmxdev_state_t; + +typedef struct dmxdev_buffer_s { + uint8_t *data; + uint32_t size; + int32_t pread; + int32_t pwrite; + WAIT_QUEUE queue; + int error; +} dmxdev_buffer_t; + + +typedef struct dmxdev_filter_s { + union { + dmx_pes_filter_t *pes; + dmx_section_filter_t *sec; + } filter; + + union { + dmx_ts_feed_t *ts; + dmx_section_feed_t *sec; + } feed; + + union { + struct dmxSctFilterParams sec; + struct dmxPesFilterParams pes; + } params; + + int type; + dmxdev_state_t state; + struct dmxdev_s *dev; + dmxdev_buffer_t buffer; + + // only for sections + struct timer_list timer; + int todo; + uint8_t secheader[3]; + + u16 pid; +} dmxdev_filter_t; + + +typedef struct dmxdev_dvr_s { + int state; + struct dmxdev_s *dev; + dmxdev_buffer_t buffer; +} dmxdev_dvr_t; + + +typedef struct dmxdev_s { + dmxdev_filter_t *filter; + dmxdev_dvr_t *dvr; + dmx_demux_t *demux; + + int filternum; + int capabilities; +#define DMXDEV_CAP_DUPLEX 1 + dmx_frontend_t *dvr_orig_fe; + + dmxdev_buffer_t dvr_buffer; +#define DVR_BUFFER_SIZE (512*1024) + + struct semaphore mutex; + spinlock_t lock; +} dmxdev_t; + + +int DmxDevInit(dmxdev_t *dmxdev); +void DmxDevRelease(dmxdev_t *dmxdev); + +int DmxDevFilterAlloc(dmxdev_t *dmxdev, struct file *file); +int DmxDevFilterFree(dmxdev_t *dmxdev, struct file *file); +int DmxDevIoctl(dmxdev_t *dmxdev, struct file *file, + unsigned int cmd, unsigned long arg); +unsigned int DmxDevPoll(dmxdev_t *dmxdev, struct file *file, poll_table * wait); +ssize_t DmxDevRead(dmxdev_t *dmxdev, struct file *file, + char *buf, size_t count, loff_t *ppos); + +int DmxDevDVROpen(dmxdev_t *dmxdev, struct file *file); +int DmxDevDVRClose(dmxdev_t *dmxdev, struct file *file); +ssize_t DmxDevDVRWrite(dmxdev_t *dmxdev, struct file *file, + const char *buf, size_t count, loff_t *ppos); +ssize_t DmxDevDVRRead(dmxdev_t *dmxdev, struct file *file, + char *buf, size_t count, loff_t *ppos); +int DmxDevDVRIoctl(dmxdev_t *dmxdev, struct file *file, + unsigned int cmd, unsigned long arg); +unsigned int DmxDevDVRPoll(dmxdev_t *dmxdev, struct file *file, poll_table * wait); + +#endif /* _DMXDEV_H_ */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/dram.c linux.19rc3-ac4/drivers/media/video/margi/dram.c --- linux.19rc3/drivers/media/video/margi/dram.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/dram.c 2002-07-29 13:58:42.000000000 +0100 @@ -0,0 +1,515 @@ +/* + dram.c + + Copyright (C) Christian Wolff for convergence integrated media. + + 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. +*/ + + ///////////////////////////////// + // // + // L64021 DRAM Memory Access // + // // +///////////////////////////////// + +#define __NO_VERSION__ + +#include "dram.h" +#include "l64021.h" + +#define EMERGENCYCOUNTER 5 + + // where: 21 bit DRAM Word-Address, 4 word aligned + // size: bytes (8 byte aligned, remainder will be filled with fill value) + // data: fill value +// returns 0 on success, -1 on collision with DMA transfer +int DRAMFillByte(struct cvdv_cards *card, u32 where, int size, u8 data) +{ + int i, j, k, n; + u8 volatile flag; + + size = (size >> 3) + ((size & 7) ? 1 : 0); // 8 bytes at a time, padding with garbage + where >>= 2; // 8 byte aligned data + DecoderSetByte(card, 0x0C1, 0x08); +//TODO: 0x80? + + DecoderWriteByte(card, 0x0C6, (u8) ((where >> 16) & 0x00000007L)); + DecoderWriteByte(card, 0x0C5, (u8) ((where >> 8) & 0x000000FFL)); + DecoderWriteByte(card, 0x0C4, (u8) (where & 0x000000FFL)); + i = 0; + for (j = 0; j < size; j++) { + for (k = 0; k < 8; k++) { + n = EMERGENCYCOUNTER; + do { // wait if FIFO full + flag = DecoderReadByte(card, 0x0C0); + } while ((flag & 0x08) && n--); + if (n<0) + return -1; + DecoderWriteByte(card, 0x0C3, data); + } + } + flag = DecoderReadByte(card, 0x0C0); + n = EMERGENCYCOUNTER; + do { // wait for FIFO empty + flag = DecoderReadByte(card, 0x0C0); + } while (!(flag & 0x04) && n--); + return ((n>=0) ? 0 : -1); +} + + // where: 21 bit DRAM Word-Address, 8 byte aligned + // size: bytes (8 byte aligned, remainder will be filled with garbage) + // swap: 0=normal mode, 1=write each 8 bytes on reverse order (7,6,5,4,3,2,1,0,15,14,13,etc.) +// returns 0 on success, -1 on collision with DMA transfer +int DRAMWriteByte(struct cvdv_cards *card, u32 where, int size, u8 * data, + int swapburst) +{ + int i, j, k, n; + u8 volatile flag; + + size = (size >> 3) + ((size & 7) ? 1 : 0); // 8 bytes at a time, padding with garbage + where >>= 2; // 8 byte aligned data + MDEBUG(4, ": Moving %d 64-bit-words to DRAM 0x%08X\n",size,where); + //if (swap) DecoderDelByte(card,0x0C1,0x08); // byte swapping of 8 byte bursts + //else DecoderSetByte(card,0x0C1,0x08); // no byte swapping + DecoderSetByte(card, 0x0C1, 0x08); // no byte swapping + + DecoderWriteByte(card, 0x0C6, (u8) ((where >> 16) & 0x00000007L)); + DecoderWriteByte(card, 0x0C5, (u8) ((where >> 8) & 0x000000FFL)); + DecoderWriteByte(card, 0x0C4, (u8) (where & 0x000000FFL)); + i = 0; + if (swapburst) { + for (j = 0; j < size; j++) { + for (k = 7; k >= 0; k--) { + n = EMERGENCYCOUNTER; + do { // wait if FIFO full + flag = + DecoderReadByte(card, 0x0C0); + } while ((flag & 0x08) && n--); + if (n<0) + return -1; + DecoderWriteByte(card, 0x0C3, data[i + k]); + } + i += 8; + } + } else { + for (j = 0; j < size; j++) { + for (k = 0; k < 8; k++) { + n = EMERGENCYCOUNTER; + do { // wait if FIFO full + flag = + DecoderReadByte(card, 0x0C0); + } while ((flag & 0x08) && n--); + if (n<0) + return -1; + DecoderWriteByte(card, 0x0C3, data[i++]); + } + } + } + flag = DecoderReadByte(card, 0x0C0); + n = EMERGENCYCOUNTER; + do { // wait for FIFO empty + flag = DecoderReadByte(card, 0x0C0); + } while (!(flag & 0x04) && n--); + return ((n>=0) ? 0 : -1); +} + + // where: 21 bit DRAM Word-Address, 4 word aligned + // size: words (4 word aligned, remainder will be filled with garbage) + // swap: 0=normal mode, 1=write each 8 bytes on reverse order (7,6,5,4,3,2,1,0,15,14,13,etc.) +// returns 0 on success, -1 on collision with DMA transfer +int DRAMWriteWord(struct cvdv_cards *card, u32 where, int size, u16 * data, + int swap) +{ + int i, j, k, n; + u8 volatile flag; + + size = (size >> 2) + ((size & 3) ? 1 : 0); // 4 words at a time, padding with garbage + where >>= 2; // 8 byte aligned data + MDEBUG(4, ": Moving %d 64-bit-words to DRAM 0x%08X\n",size,where); +//TODO: swap manually + if (swap) + DecoderDelByte(card, 0x0C1, 0x08); // byte swapping of 8 byte bursts + else + DecoderSetByte(card, 0x0C1, 0x08); // no byte swapping + + DecoderWriteByte(card, 0x0C6, (u8) ((where >> 16) & 0x00000007L)); + DecoderWriteByte(card, 0x0C5, (u8) ((where >> 8) & 0x000000FFL)); + DecoderWriteByte(card, 0x0C4, (u8) (where & 0x000000FFL)); + i = 0; + for (j = 0; j < size; j++) { + for (k = 0; k < 4; k++) { + n = EMERGENCYCOUNTER; + do { // wait if FIFO full + flag = DecoderReadByte(card, 0x0C0); + } while ((flag & 0x08) && n--); + if (n<0) + return -1; + DecoderWriteByte(card, 0x0C3, data[i] >> 8); + n = EMERGENCYCOUNTER; + do { // wait if FIFO full + flag = DecoderReadByte(card, 0x0C0); + } while ((flag & 0x08) && n--); + if (n<0) + return -1; + DecoderWriteByte(card, 0x0C3, data[i++]); + } + } + flag = DecoderReadByte(card, 0x0C0); + n = EMERGENCYCOUNTER; + do { // wait for FIFO empty + flag = DecoderReadByte(card, 0x0C0); + } while (!(flag & 0x04) && n--); + return ((n>=0) ? 0 : -1); +} + + // where: 21 bit DRAM Word-Address, 8 byte aligned + // size: bytes + // swap: 0=normal mode, 1=write each 8 bytes on reverse order (7,6,5,4,3,2,1,0,15,14,13,etc.) +// returns 0 on success, -1 on collision with DMA transfer +int DRAMReadByte(struct cvdv_cards *card, u32 where, int size, u8 * data, + int swap) +{ + int i, j, rsize, n; + u8 volatile flag; + + rsize = size & 7; // padding bytes + size = size >> 3; // 8 bytes at a time + where >>= 2; // 8 byte aligned data + MDEBUG(4, ": Moving %d 64-bit-words to DRAM 0x%08X\n",size,where); +//TODO: swap manually + if (swap) + DecoderDelByte(card, 0x0C1, 0x08); // byte swapping of 8 byte bursts + else + DecoderSetByte(card, 0x0C1, 0x08); // no byte swapping + + DecoderWriteByte(card, 0x0C9, (u8) ((where >> 16) & 0x00000007L)); + DecoderWriteByte(card, 0x0C8, (u8) ((where >> 8) & 0x000000FFL)); + DecoderWriteByte(card, 0x0C7, (u8) (where & 0x000000FFL)); + i = 0; + for (j = 0; j < size; j++) { + n = EMERGENCYCOUNTER; + do { // wait if FIFO empty + flag = DecoderReadByte(card, 0x0C0); + } while ((flag & 0x01) && n--); + if (n<0) // WARNING nicht if(!n) + return -1; + data[i++] = DecoderReadByte(card, 0x0C2); + data[i++] = DecoderReadByte(card, 0x0C2); + data[i++] = DecoderReadByte(card, 0x0C2); + data[i++] = DecoderReadByte(card, 0x0C2); + data[i++] = DecoderReadByte(card, 0x0C2); + data[i++] = DecoderReadByte(card, 0x0C2); + data[i++] = DecoderReadByte(card, 0x0C2); + data[i++] = DecoderReadByte(card, 0x0C2); + } + n = EMERGENCYCOUNTER; + do { // wait if FIFO empty + flag = DecoderReadByte(card, 0x0C0); + } while ((flag & 0x01) && n--); + if (n<0) + return -1; + for (j = 0; j < rsize; j++) + data[i++] = DecoderReadByte(card, 0x0C2); + flag = DecoderReadByte(card, 0x0C0); + n = EMERGENCYCOUNTER; + do { // wait for FIFO full + flag = DecoderReadByte(card, 0x0C0); + } while (!(flag & 0x02) && n--); + return ((n>=0) ? 0 : -1); +} + + + // where: 21 bit DRAM Word-Address, 4 word aligned + // size: words + // swap: 0=normal mode, 1=write each 8 bytes on reverse order (7,6,5,4,3,2,1,0,15,14,13,etc.) +// returns 0 on success, -1 on collision with DMA transfer +int DRAMReadWord(struct cvdv_cards *card, u32 where, int size, u16 * data, + int swap) +{ + int i, j, rsize, n; + u8 volatile flag; + u8 b; + + rsize = size & 3; // padding words + size >>= 2; // 4 words at a time + where >>= 2; // 8 byte aligned data + MDEBUG(4, ": Reading %d 64-bit-words and %d 16-bit-words from DRAM 0x%08X\n", + size,rsize,where); +//TODO: swap manually + if (swap) + DecoderDelByte(card, 0x0C1, 0x08); // byte swapping of 8 byte bursts + else + DecoderSetByte(card, 0x0C1, 0x08); // no byte swapping + + DecoderWriteByte(card, 0x0C9, (u8) ((where >> 16) & 0x00000007L)); + DecoderWriteByte(card, 0x0C8, (u8) ((where >> 8) & 0x000000FFL)); + DecoderWriteByte(card, 0x0C7, (u8) (where & 0x000000FFL)); + i = 0; + for (j = 0; j < size; j++) { + n = EMERGENCYCOUNTER; + do { // wait if FIFO empty + flag = DecoderReadByte(card, 0x0C0); + } while ((flag & 0x01) && n--); + if (n<0) + return -1; + b = DecoderReadByte(card, 0x0C2); + data[i++] = ((b << 8) | DecoderReadByte(card, 0x0C2)); + b = DecoderReadByte(card, 0x0C2); + data[i++] = ((b << 8) | DecoderReadByte(card, 0x0C2)); + b = DecoderReadByte(card, 0x0C2); + data[i++] = ((b << 8) | DecoderReadByte(card, 0x0C2)); + b = DecoderReadByte(card, 0x0C2); + data[i++] = ((b << 8) | DecoderReadByte(card, 0x0C2)); + } + n = EMERGENCYCOUNTER; + do { // wait if FIFO empty + flag = DecoderReadByte(card, 0x0C0); + } while ((flag & 0x01) && n--); + if (n<0) + return -1; + for (j = 0; j < rsize; j++) { + b = DecoderReadByte(card, 0x0C2); + data[i++] = ((b << 8) | DecoderReadByte(card, 0x0C2)); + } + flag = DecoderReadByte(card, 0x0C0); + n = EMERGENCYCOUNTER; + do { // wait for FIFO full + flag = DecoderReadByte(card, 0x0C0); + } while (!(flag & 0x02) && n--); + return ((n>=0) ? 0 : -1); +} + + // where: 21 bit DRAM Word-Address, 4 word aligned + // size: words + // swap: 0=normal mode, 1=write each 8 bytes on reverse order (7,6,5,4,3,2,1,0,15,14,13,etc.) + // returns -1 on success (equal content), + // word position on error (compare failure), +// -2 on collision with DMA transfer +int DRAMVerifyWord(struct cvdv_cards *card, u32 where, int size, + u16 * data, int swap) +{ + int i, j, rsize, n; + u8 volatile flag, b; + + rsize = size & 3; // padding words + size >>= 2; // 4 words at a time + where >>= 2; // 8 byte aligned data, now 19 bit 64-bit-word-address +//TODO: swap manually + if (swap) + DecoderDelByte(card, 0x0C1, 0x08); // byte swapping of 8 byte bursts + else + DecoderSetByte(card, 0x0C1, 0x08); // no byte swapping + + DecoderWriteByte(card, 0x0C9, (u8) ((where >> 16) & 0x00000007L)); + DecoderWriteByte(card, 0x0C8, (u8) ((where >> 8) & 0x000000FFL)); + DecoderWriteByte(card, 0x0C7, (u8) (where & 0x000000FFL)); + i = 0; + for (j = 0; j < size; j++) { + n = EMERGENCYCOUNTER; + do { // wait if FIFO empty + flag = DecoderReadByte(card, 0x0C0); + } while ((flag & 0x01) && n--); + b = DecoderReadByte(card, 0x0C2); + if (data[i++] != ((b << 8) | DecoderReadByte(card, 0x0C2))) + return i; + b = DecoderReadByte(card, 0x0C2); + if (data[i++] != ((b << 8) | DecoderReadByte(card, 0x0C2))) + return i; + b = DecoderReadByte(card, 0x0C2); + if (data[i++] != ((b << 8) | DecoderReadByte(card, 0x0C2))) + return i; + b = DecoderReadByte(card, 0x0C2); + if (data[i++] != ((b << 8) | DecoderReadByte(card, 0x0C2))) + return i; + } + n = EMERGENCYCOUNTER; + do { // wait if FIFO empty + flag = DecoderReadByte(card, 0x0C0); + } while ((flag & 0x01) && n--); + for (j = 0; j < rsize; j++) { + b = DecoderReadByte(card, 0x0C2); + if (data[i++] != ((b << 8) | DecoderReadByte(card, 0x0C2))) + return i; + } + flag = DecoderReadByte(card, 0x0C0); + n = EMERGENCYCOUNTER; + do { // wait for FIFO full + flag = DecoderReadByte(card, 0x0C0); + } while (!(flag & 0x02) && n--); + return -1; +} + + // WARNING: better not use this one. It can collide with normal DRAM access and other DMA transfers + // If you want to use it, implement card->DMAMoveBusy in all other DMA functions, initialisation, and header file + // source, destination: 21 bit DRAM Word-Address, 4 word aligned + // size: byte (8 byte aligned, hang over bytes will NOT be moved) + // returns 0 on success on success, + // -1 on collision with DMA transfer, +// -2 on interrupt handler not installed +int DRAMMove(struct cvdv_cards *card, u32 source, u32 destination, + int size) +{ + if (!card->IntInstalled) + return -2; + if (card->DMAABusy || card->DMABBusy) + return -1; + + size >>= 3; // 64-bit-words + source >>= 2; // 8 byte aligned data, + destination >>= 2; // now 19 bit 64-bit-word-address + + DecoderDelByte(card, 0x0C1, 0x06); // DMA idle + + DecoderWriteByte(card, 0x0DA, (u8) ((source >> 16) & 0x00000007L)); + DecoderWriteByte(card, 0x0D9, (u8) ((source >> 8) & 0x000000FFL)); + DecoderWriteByte(card, 0x0D8, (u8) (source & 0x000000FFL)); + DecoderWriteByte(card, 0x0D7, + (u8) ((destination >> 16) & 0x00000007L)); + DecoderWriteByte(card, 0x0D6, + (u8) ((destination >> 8) & 0x000000FFL)); + DecoderWriteByte(card, 0x0D5, (u8) (destination & 0x000000FFL)); + + //card->DMAMoveBusy=1; // would have to catch that in all the other DMA routines + DecoderSetByte(card, 0x0C1, 0x06); // DMA block move + + return 0; +} + + // size in words + // align: number of words on wich start of block will be aligned +// return value is 21 bit word address, or 0xFFFFFFFF on error +u32 DRAMAlloc(struct cvdv_cards * card, u32 size, int align) +{ + struct DRAMBlock *ptr, *ptr2; + u32 addr = 0; + u32 alignmask = align - 1; + int valid = 0; + + printk("DRAMAlloc %d bytes (from %d).\n", size, card->DRAMSize); + + if (size == 0) + { + printk("DRAMAlloc - 0 size.\n"); + return BLANK; + } + + if (size & 3) + size = (size & ~3) + 4; // increase size if not 64 bit aligned + + printk("DRAMAlloc %d bytes.\n", size); + if (card->DRAMFirstBlock == NULL) { // virgin territory? + valid = ((addr + size) <= card->DRAMSize); // does it fit at all? + } else { + addr = 0; + valid = ((addr + size) <= card->DRAMSize); // does it fit at all? + for (ptr2 = card->DRAMFirstBlock; + (ptr2 != NULL) && (valid); ptr2 = ptr2->next) { // check against all existing blocks + if ((ptr2->start >= addr) + && (ptr2->start < (addr + size))) + valid = 0; // existing block start inside new block? + else if (((ptr2->start + ptr2->length) > addr) + && ((ptr2->start + ptr2->length) <= + (addr + size))) + valid = 0; // existing block end inside new block? + else if ((ptr2->start < addr) + && ((ptr2->start + ptr2->length) > + (addr + size))) valid = 0; // new block inside existing block? + } + for (ptr = card->DRAMFirstBlock; (ptr != NULL) && (!valid); + ptr = ptr->next) { // check all existing blocks + addr = ptr->start + ptr->length; // assume, after this block is free space + if (addr & alignmask) + addr = (addr & ~alignmask) + align; // round up to alignation border + valid = ((addr + size) <= card->DRAMSize); // does it fit at all? + for (ptr2 = card->DRAMFirstBlock; + (ptr2 != NULL) && (valid); ptr2 = ptr2->next) { // check against all existing blocks + if ((ptr2->start >= addr) + && (ptr2->start < (addr + size))) + valid = 0; // existing block start inside new block? + else + if ( + ((ptr2->start + ptr2->length) > + addr) + && ((ptr2->start + ptr2->length) <= + (addr + size))) + valid = 0; // existing block end inside new block? + else if ((ptr2->start < addr) + && ((ptr2->start + ptr2->length) > + (addr + size))) + valid = 0; // new block inside existing block? + } + } + } + if (valid) { // The new block fits + ptr = (struct DRAMBlock *) kmalloc(sizeof(struct DRAMBlock), GFP_KERNEL); + if (ptr == NULL) { + printk(KERN_INFO LOGNAME ": ERROR: out of kernel memory for block info. Please reboot if possible.\n"); + return BLANK; // out of kernel mem + } + if (card->DRAMFirstBlock == NULL) { + card->DRAMFirstBlock = ptr; + } else { + ptr2 = card->DRAMFirstBlock; + while (ptr2->next != NULL) + ptr2 = ptr2->next; + ptr2->next = ptr; + } + ptr->next = NULL; + ptr->start = addr; + ptr->length = size; + MDEBUG(1,": DRAM Allocate 0x%08X-0x%08X\n", addr, + addr + size - 1); + + printk("DRAMAlloc ok\n"); + return addr; + } + printk(KERN_ERR "DRAMAlloc: No card memory.\n"); + return BLANK; +} + + // addr is the return value of that resp. DRAMAlloc call +// returns 0 on success (always) +int DRAMFree(struct cvdv_cards *card, u32 addr) +{ + struct DRAMBlock *ptr, *ptr2; + ptr2 = NULL; + for (ptr = card->DRAMFirstBlock; ptr != NULL; ptr = ptr->next) { // check all existent blocks + if (addr == ptr->start) { // this is our block to be removed + if (ptr2 == NULL) + card->DRAMFirstBlock = ptr->next; + else + ptr2->next = ptr->next; + kfree(ptr); + MDEBUG(1, ": DRAM Free 0x%08X\n", addr); + } else + ptr2 = ptr; + } + return 0; +} + + // free all blocks +// returns 0 on success (always) +int DRAMRelease(struct cvdv_cards *card) +{ + struct DRAMBlock *ptr, *ptr2; + MDEBUG(1, ": -- DRAMRelease\n"); + for (ptr = card->DRAMFirstBlock; ptr != NULL; ptr = ptr2) { // check all existent blocks + ptr2 = ptr->next; + MDEBUG(4, ": kfree(0x%08X)\n",(int)ptr); + kfree(ptr); + } + card->DRAMFirstBlock = NULL; + return 0; +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/dram.h linux.19rc3-ac4/drivers/media/video/margi/dram.h --- linux.19rc3/drivers/media/video/margi/dram.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/dram.h 2002-07-29 17:29:11.000000000 +0100 @@ -0,0 +1,99 @@ +/* + dram.h + + Copyright (C) Christian Wolff for convergence integrated media. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef DRAM_H +#define DRAM_H + + ///////////////////////////////// + // // + // L64021 DRAM Memory Access // + // // +///////////////////////////////// + +#include "cardbase.h" + + // where: 21 bit DRAM Word-Address, 4 word aligned + // size: bytes (8 byte aligned, remainder will be filled with fill value) + // data: fill value +// returns 0 on success, -1 on collision with DMA transfer +int DRAMFillByte(struct cvdv_cards *card, u32 where, int size, u8 data); + + // where: 21 bit DRAM Word-Address, 8 byte aligned + // size: bytes (8 byte aligned, remainder will be filled with garbage) + // swap: 0=normal mode, 1=write each 8 bytes on reverse order (7,6,5,4,3,2,1,0,15,14,13,etc.) +// returns 0 on success, -1 on collision with DMA transfer +int DRAMWriteByte(struct cvdv_cards *card, u32 where, int size, u8 * data, + int swapburst); + + // where: 21 bit DRAM Word-Address, 4 word aligned + // size: words (4 word aligned, remainder will be filled with garbage) + // swap: 0=normal mode, 1=write each 8 bytes on reverse order (7,6,5,4,3,2,1,0,15,14,13,etc.) +// returns 0 on success, -1 on collision with DMA transfer +int DRAMWriteWord(struct cvdv_cards *card, u32 where, int size, u16 * data, + int swap); + + // where: 21 bit DRAM Word-Address, 8 byte aligned + // size: bytes + // swap: 0=normal mode, 1=write each 8 bytes on reverse order (7,6,5,4,3,2,1,0,15,14,13,etc.) +// returns 0 on success, -1 on collision with DMA transfer +int DRAMReadByte(struct cvdv_cards *card, u32 where, int size, u8 * data, + int swap); + + + // where: 21 bit DRAM Word-Address, 4 word aligned + // size: words + // swap: 0=normal mode, 1=write each 8 bytes on reverse order (7,6,5,4,3,2,1,0,15,14,13,etc.) +// returns 0 on success, -1 on collision with DMA transfer +int DRAMReadWord(struct cvdv_cards *card, u32 where, int size, u16 * data, + int swap); + + // where: 21 bit DRAM Word-Address, 4 word aligned + // size: words + // swap: 0=normal mode, 1=write each 8 bytes on reverse order (7,6,5,4,3,2,1,0,15,14,13,etc.) + // returns -1 on success (equal content), + // word position on error (compare failure), +// -2 on collision with DMA transfer +int DRAMVerifyWord(struct cvdv_cards *card, u32 where, int size, + u16 * data, int swap); + + // WARNING: better not use this one. It can collide with normal DRAM access and other DMA transfers + // If you want to use it, implement card->DMAMoveBusy in all other DMA functions, initialisation, and header file + // source, destination: 21 bit DRAM Word-Address, 4 word aligned + // size: byte (8 byte aligned, hang over bytes will NOT be moved) + // returns 0 on success on success, + // -1 on collision with DMA transfer, +// -2 on interrupt handler not installed +int DRAMMove(struct cvdv_cards *card, u32 source, u32 destination, + int size); + + // size in words + // align: number of words on wich start of block will be aligned +// return value is 21 bit word address, or 0xFFFFFFFF on error +u32 DRAMAlloc(struct cvdv_cards *card, u32 size, int align); + + // addr is the return value of that resp. DRAMAlloc call +// returns 0 on success (always) +int DRAMFree(struct cvdv_cards *card, u32 addr); + + // free all blocks +// returns 0 on success (always) +int DRAMRelease(struct cvdv_cards *card); + +#endif /* DRAM_H */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/dvb_demux.c linux.19rc3-ac4/drivers/media/video/margi/dvb_demux.c --- linux.19rc3/drivers/media/video/margi/dvb_demux.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/dvb_demux.c 2002-07-29 13:58:42.000000000 +0100 @@ -0,0 +1,1169 @@ +/* + * dvb_demux.c - DVB kernel demux API + * + * Copyright (C) 2000-2001 Ralph Metzler + * & Marcus Metzler + * for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * 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 Lesser 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. + * + */ + +#include +#include +#include +#include + +#include "dvb_demux.h" + +#ifdef MODULE +MODULE_DESCRIPTION(""); +MODULE_AUTHOR("Ralph Metzler, Marcus Metzler"); +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif +#endif + +#define NOBUFS + +LIST_HEAD(dmx_muxs); + +int dmx_register_demux(dmx_demux_t *demux) +{ + struct list_head *pos, *head=&dmx_muxs; + + if (!(demux->id && demux->vendor && demux->model)) + return -EINVAL; + list_for_each(pos, head) + { + if (!strcmp(DMX_DIR_ENTRY(pos)->id, demux->id)) + return -EEXIST; + } + demux->users=0; + list_add(&(demux->reg_list), head); + MOD_INC_USE_COUNT; + return 0; +} + +int dmx_unregister_demux(dmx_demux_t* demux) +{ + struct list_head *pos, *head=&dmx_muxs; + + list_for_each(pos, head) + { + if (DMX_DIR_ENTRY(pos)==demux) + { + if (demux->users>0) + return -EINVAL; + list_del(pos); + MOD_DEC_USE_COUNT; + return 0; + } + } + return -ENODEV; +} + + +struct list_head *dmx_get_demuxes(void) +{ + if (list_empty(&dmx_muxs)) + return NULL; + + return &dmx_muxs; +} + +/****************************************************************************** + * static inlined helper functions + ******************************************************************************/ + +static inline u16 +section_length(const u8 *buf) +{ + return 3+((buf[1]&0x0f)<<8)+buf[2]; +} + +static inline u16 +ts_pid(const u8 *buf) +{ + return ((buf[1]&0x1f)<<8)+buf[2]; +} + +static inline int +payload(const u8 *tsp) +{ + if (!(tsp[3]&0x10)) // no payload? + return 0; + if (tsp[3]&0x20) { // adaptation field? + if (tsp[4]>183) // corrupted data? + return 0; + else + return 184-1-tsp[4]; + } + return 184; +} + + +static u32 +dvb_crc_table[256] = { + 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, + 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, + 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, + 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, + 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, + 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, + 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, + 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, + 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, + 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, + 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, + 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, + 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, + 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, + 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, + 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, + 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, + 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, + 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, + 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, + 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, + 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, + 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, + 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, + 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, + 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, + 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, + 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, + 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, + 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, + 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, + 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, + 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, + 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, + 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, + 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, + 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, + 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, + 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, + 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, + 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, + 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, + 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4}; + +u32 dvb_crc32(u8 *data, int len) +{ + int i; + u32 crc = 0xffffffff; + + for (i=0; i> 24) ^ *data++) & 0xff]; + return crc; +} + +void dvb_set_crc32(u8 *data, int length) +{ + u32 crc; + + crc=dvb_crc32(data,length); + data[length] = (crc>>24)&0xff; + data[length+1] = (crc>>16)&0xff; + data[length+2] = (crc>>8)&0xff; + data[length+3] = (crc)&0xff; +} + + +/****************************************************************************** + * Software filter functions + ******************************************************************************/ + +static inline int +DvbDmxSWFilterPayload(dvb_demux_feed_t *dvbdmxfeed, const u8 *buf) +{ + int p, count; + //int ccok; + //u8 cc; + + if (!(count=payload(buf))) + return -1; + p=188-count; + /* + cc=buf[3]&0x0f; + ccok=((dvbdmxfeed->cc+1)&0x0f)==cc ? 1 : 0; + dvbdmxfeed->cc=cc; + if (!ccok) + printk("missed packet!\n"); + */ + if (buf[1]&0x40) // PUSI ? + dvbdmxfeed->peslen=0xfffa; + dvbdmxfeed->peslen+=count; + + return dvbdmxfeed->cb.ts((u8 *)&buf[p], count, 0, 0, + &dvbdmxfeed->feed.ts, DMX_OK); +} + + +static int +DvbDmxSWFilterSectionFilter(dvb_demux_feed_t *dvbdmxfeed, + dvb_demux_filter_t *dvbdmxfilter) +{ + dmx_section_filter_t *filter=&dvbdmxfilter->filter; +#if 1 + int i; + + for (i=0; ifilter_mask[i]& + (filter->filter_value[i]^dvbdmxfeed->secbuf[i])) + return 0; +#else + u32 res; + u32 *val=(u32 *)(filter->filter_value); + u32 *mask=(u32 *)(filter->filter_mask); + u32 *data=(u32 *)(dvbdmxfeed->secbuf); + + res=mask[0]&(val[0]^data[0]); + if (res) return 0; + + res=mask[1]&(val[1]^data[1]); + if (res) return 0; + + res=mask[2]&(val[2]^data[2]); + if (res) return 0; + + res=mask[3]&(val[3]^data[3]); + if (res) return 0; + + res=*(u16 *)(4+mask) & (*(u16 *)(4+val) ^ *(u16 *)(4+data)); + if (res) return 0; +#endif + + return dvbdmxfeed->cb.sec(dvbdmxfeed->secbuf, dvbdmxfeed->seclen, + 0, 0, filter, DMX_OK); +} + +static inline int +DvbDmxSWFilterSectionFeed(dvb_demux_feed_t *dvbdmxfeed) +{ + u8 *buf=dvbdmxfeed->secbuf; + dvb_demux_filter_t *f; + + if (dvbdmxfeed->secbufp!=dvbdmxfeed->seclen) + return -1; + if (!dvbdmxfeed->feed.sec.is_filtering) + return 0; + if (!(f=dvbdmxfeed->filter)) + return 0; + do + if (DvbDmxSWFilterSectionFilter(dvbdmxfeed, f)<0) + return -1; + while ((f=f->next) && dvbdmxfeed->feed.sec.is_filtering); + + dvbdmxfeed->secbufp=dvbdmxfeed->seclen=0; + memset(buf, 0, DVB_DEMUX_MASK_MAX); + return 0; +} + +static inline int +DvbDmxSWFilterSectionPacket(dvb_demux_feed_t *dvbdmxfeed, const u8 *buf) +{ + int p, count; + int ccok, rest; + u8 cc; + + if (!(count=payload(buf))) + return -1; + p=188-count; + + cc=buf[3]&0x0f; + ccok=((dvbdmxfeed->cc+1)&0x0f)==cc ? 1 : 0; + dvbdmxfeed->cc=cc; + + if (buf[1]&0x40) { // PUSI set + // offset to start of first section is in buf[p] + if (p+buf[p]>187) // trash if it points beyond packet + return -1; + if (buf[p] && ccok) { // rest of previous section? + // did we have enough data in last packet to calc length? + if (dvbdmxfeed->secbufp && dvbdmxfeed->secbufp<3) { + memcpy(dvbdmxfeed->secbuf+dvbdmxfeed->secbufp, + buf+p+1, + 3-dvbdmxfeed->secbufp); + dvbdmxfeed->seclen=section_length(dvbdmxfeed->secbuf); + if (dvbdmxfeed->seclen>4096) + return -1; + } + rest=dvbdmxfeed->seclen-dvbdmxfeed->secbufp; + if (rest==buf[p] && dvbdmxfeed->seclen) { + memcpy(dvbdmxfeed->secbuf+dvbdmxfeed->secbufp, + buf+p+1, buf[p]); + dvbdmxfeed->secbufp+=buf[p]; + DvbDmxSWFilterSectionFeed(dvbdmxfeed); + } + } + p+=buf[p]+1; // skip rest of last section + count=188-p; + while (count>0) { + if ((count>2) && // enough data to determine sec length? + ((dvbdmxfeed->seclen=section_length(buf+p))<=count)) { + if (dvbdmxfeed->seclen>4096) + return -1; + memcpy(dvbdmxfeed->secbuf, buf+p, + dvbdmxfeed->seclen); + dvbdmxfeed->secbufp=dvbdmxfeed->seclen; + p+=dvbdmxfeed->seclen; + count=188-p; + DvbDmxSWFilterSectionFeed(dvbdmxfeed); + + // filling bytes until packet end? + if (count && buf[p]==0xff) + count=0; + } else { // section continues to following TS packet + memcpy(dvbdmxfeed->secbuf, buf+p, count); + dvbdmxfeed->secbufp+=count; + count=0; + } + } + } else { // section continued below + if (!ccok) + return -1; + if (!dvbdmxfeed->secbufp) // any data in last ts packet? + return -1; + // did we have enough data in last packet to calc section length? + if (dvbdmxfeed->secbufp<3) { + memcpy(dvbdmxfeed->secbuf+dvbdmxfeed->secbufp, buf+p, + 3-dvbdmxfeed->secbufp); + dvbdmxfeed->seclen=section_length(dvbdmxfeed->secbuf); + if (dvbdmxfeed->seclen>4096) + return -1; + } + rest=dvbdmxfeed->seclen-dvbdmxfeed->secbufp; + if (rest<0) + return -1; + if (rest<=count) { // section completed in this TS packet + memcpy(dvbdmxfeed->secbuf+dvbdmxfeed->secbufp, buf+p, rest); + dvbdmxfeed->secbufp+=rest; + DvbDmxSWFilterSectionFeed(dvbdmxfeed); + } else { // section continues in following ts block + memcpy(dvbdmxfeed->secbuf+dvbdmxfeed->secbufp, buf+p, count); + dvbdmxfeed->secbufp+=count; + } + + } + return 0; +} + +static inline void +DvbDmxSWFilterPacketType(dvb_demux_feed_t *dvbdmxfeed, const u8 *buf) +{ + switch(dvbdmxfeed->type) { + case DMX_TYPE_TS: + if (!dvbdmxfeed->feed.ts.is_filtering) + break; + if (dvbdmxfeed->ts_type & TS_PACKET) { + if (dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY) + DvbDmxSWFilterPayload(dvbdmxfeed, buf); + else + dvbdmxfeed->cb.ts((u8 *)buf, 188, 0, 0, + &dvbdmxfeed->feed.ts, DMX_OK); + } + if (dvbdmxfeed->ts_type & TS_DECODER) + if (dvbdmxfeed->demux->write_to_decoder) + dvbdmxfeed->demux-> + write_to_decoder(dvbdmxfeed, (u8 *)buf, 188); + break; + + case DMX_TYPE_SEC: + if (!dvbdmxfeed->feed.sec.is_filtering) + break; + if (DvbDmxSWFilterSectionPacket(dvbdmxfeed, buf)<0) + dvbdmxfeed->seclen=dvbdmxfeed->secbufp=0; + break; + + default: + break; + } +} + +void inline +DvbDmxSWFilterPacket(dvb_demux_t *dvbdmx, const u8 *buf) +{ + dvb_demux_feed_t *dvbdmxfeed; + + if (!(dvbdmxfeed=dvbdmx->pid2feed[ts_pid(buf)])) + return; + DvbDmxSWFilterPacketType(dvbdmxfeed, buf); +} + +void +DvbDmxSWFilterPackets(dvb_demux_t *dvbdmx, const u8 *buf, int count) +{ + dvb_demux_feed_t *dvbdmxfeed; + + if ((dvbdmxfeed=dvbdmx->pid2feed[0x2000])) + dvbdmxfeed->cb.ts((u8 *)buf, count*188, 0, 0, + &dvbdmxfeed->feed.ts, DMX_OK); + while (count) { + DvbDmxSWFilterPacket(dvbdmx, buf); + count--; + buf+=188; + } +} + +static inline void +DvbDmxSWFilter(dvb_demux_t *dvbdmx, const u8 *buf, size_t count) +{ + int p=0,i, j; + + if ((i=dvbdmx->tsbufp)) { + if (count<(j=188-i)) { + memcpy(&dvbdmx->tsbuf[i], buf, count); + dvbdmx->tsbufp+=count; + return; + } + memcpy(&dvbdmx->tsbuf[i], buf, j); + DvbDmxSWFilterPacket(dvbdmx, dvbdmx->tsbuf); + dvbdmx->tsbufp=0; + p+=j; + } + + while (p=188) { + DvbDmxSWFilterPacket(dvbdmx, buf+p); + p+=188; + } else { + i=count-p; + memcpy(dvbdmx->tsbuf, buf+p, i); + dvbdmx->tsbufp=i; + return; + } + } else + p++; + } +} + + +/****************************************************************************** + ****************************************************************************** + * DVB DEMUX API LEVEL FUNCTIONS + ****************************************************************************** + ******************************************************************************/ + +static dvb_demux_filter_t * +DvbDmxFilterAlloc(dvb_demux_t *dvbdmx) +{ + int i; + + for (i=0; ifilternum; i++) + if (dvbdmx->filter[i].state==DMX_STATE_FREE) + break; + if (i==dvbdmx->filternum) + return 0; + dvbdmx->filter[i].state=DMX_STATE_ALLOCATED; + return &dvbdmx->filter[i]; +} + +static dvb_demux_feed_t * +DvbDmxFeedAlloc(dvb_demux_t *dvbdmx) +{ + int i; + + for (i=0; ifeednum; i++) + if (dvbdmx->feed[i].state==DMX_STATE_FREE) + break; + if (i==dvbdmx->feednum) + return 0; + dvbdmx->feed[i].state=DMX_STATE_ALLOCATED; + return &dvbdmx->feed[i]; +} + + +/****************************************************************************** + * dmx_ts_feed API calls + ******************************************************************************/ + +static int +dmx_ts_feed_set_type(dmx_ts_feed_t *feed, int type, dmx_ts_pes_t pes_type) +{ + dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed; + dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + + down(&dvbdmx->mutex); + dvbdmxfeed->ts_type=type; + dvbdmxfeed->pes_type=pes_type; + + if (dvbdmxfeed->ts_type & TS_DECODER) { + if (pes_type >= DMX_TS_PES_OTHER) { + up(&dvbdmx->mutex); + return -EINVAL; + } + if (dvbdmx->pesfilter[pes_type] && + (dvbdmx->pesfilter[pes_type]!=dvbdmxfeed)) { + up(&dvbdmx->mutex); + return -EINVAL; + } + dvbdmx->pesfilter[pes_type]=dvbdmxfeed; + dvbdmx->pids[pes_type]=dvbdmxfeed->pid; + } + up(&dvbdmx->mutex); + return 0; +} + +static int +dmx_pid_set(u16 pid, dvb_demux_feed_t *dvbdmxfeed) +{ + dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + dvb_demux_feed_t **pid2feed=dvbdmx->pid2feed; + + if (pid>DMX_MAX_PID) + return -EINVAL; + if (dvbdmxfeed->pid!=0xffff) { + if (dvbdmxfeed->pid<=DMX_MAX_PID) + pid2feed[dvbdmxfeed->pid]=0; + dvbdmxfeed->pid=0xffff; + } + if (pid2feed[pid]) { + return -EBUSY; + } + pid2feed[pid]=dvbdmxfeed; + dvbdmxfeed->pid=pid; + return 0; +} + + +static int +dmx_ts_feed_set(struct dmx_ts_feed_s* feed, + u16 pid, + size_t callback_length, + size_t circular_buffer_size, + int descramble, + struct timespec timeout + ) +{ + dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed; + dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + int ret; + + down(&dvbdmx->mutex); + ret=dmx_pid_set(pid, dvbdmxfeed); + if (ret<0) { + up(&dvbdmx->mutex); + return ret; + } + dvbdmxfeed->buffer_size=circular_buffer_size; + dvbdmxfeed->descramble=descramble; + dvbdmxfeed->timeout=timeout; + dvbdmxfeed->cb_length=callback_length; + dvbdmxfeed->ts_type=TS_PACKET; + + if (dvbdmxfeed->descramble) { + up(&dvbdmx->mutex); + return -ENOSYS; + } + + if (dvbdmxfeed->buffer_size) { +#ifdef NOBUFS + dvbdmxfeed->buffer=0; +#else + dvbdmxfeed->buffer=vmalloc(dvbdmxfeed->buffer_size); + if (!dvbdmxfeed->buffer) { + up(&dvbdmx->mutex); + return -ENOMEM; + } +#endif + } + dvbdmxfeed->state=DMX_STATE_READY; + up(&dvbdmx->mutex); + return 0; +} + +static int +dmx_ts_feed_start_filtering(struct dmx_ts_feed_s* feed) +{ + dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed; + dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + int ret; + + down(&dvbdmx->mutex); + if (dvbdmxfeed->state!=DMX_STATE_READY || + dvbdmxfeed->type!=DMX_TYPE_TS) { + up(&dvbdmx->mutex); + return -EINVAL; + } + if (!dvbdmx->start_feed) { + up(&dvbdmx->mutex); + return -1; + } + ret=dvbdmx->start_feed(dvbdmxfeed); + if (ret<0) { + up(&dvbdmx->mutex); + return ret; + } + feed->is_filtering=1; + dvbdmxfeed->state=DMX_STATE_GO; + up(&dvbdmx->mutex); + return 0; +} + +static int +dmx_ts_feed_stop_filtering(struct dmx_ts_feed_s* feed) +{ + dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed; + dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + int ret; + + down(&dvbdmx->mutex); + if (dvbdmxfeed->statemutex); + return -EINVAL; + } + if (!dvbdmx->stop_feed) { + up(&dvbdmx->mutex); + return -1; + } + ret=dvbdmx->stop_feed(dvbdmxfeed); + feed->is_filtering=0; + dvbdmxfeed->state=DMX_STATE_ALLOCATED; + + up(&dvbdmx->mutex); + return ret; +} + +static int dvbdmx_allocate_ts_feed(dmx_demux_t *demux, + dmx_ts_feed_t **feed, + dmx_ts_cb callback) +{ + dvb_demux_t *dvbdmx=(dvb_demux_t *) demux; + dvb_demux_feed_t *dvbdmxfeed; + + down(&dvbdmx->mutex); + if (!(dvbdmxfeed=DvbDmxFeedAlloc(dvbdmx))) { + up(&dvbdmx->mutex); + return -EBUSY; + } + dvbdmxfeed->type=DMX_TYPE_TS; + dvbdmxfeed->cb.ts=callback; + dvbdmxfeed->demux=dvbdmx; + dvbdmxfeed->pid=0xffff; + dvbdmxfeed->peslen=0xfffa; + dvbdmxfeed->buffer=0; + + (*feed)=&dvbdmxfeed->feed.ts; + (*feed)->is_filtering=0; + (*feed)->parent=demux; + (*feed)->priv=0; + (*feed)->set=dmx_ts_feed_set; + (*feed)->set_type=dmx_ts_feed_set_type; + (*feed)->start_filtering=dmx_ts_feed_start_filtering; + (*feed)->stop_filtering=dmx_ts_feed_stop_filtering; + + + if (!(dvbdmxfeed->filter=DvbDmxFilterAlloc(dvbdmx))) { + dvbdmxfeed->state=DMX_STATE_FREE; + up(&dvbdmx->mutex); + return -EBUSY; + } + + dvbdmxfeed->filter->type=DMX_TYPE_TS; + dvbdmxfeed->filter->feed=dvbdmxfeed; + dvbdmxfeed->filter->state=DMX_STATE_READY; + + up(&dvbdmx->mutex); + return 0; +} + +static int dvbdmx_release_ts_feed(dmx_demux_t *demux, dmx_ts_feed_t *feed) +{ + dvb_demux_t *dvbdmx=(dvb_demux_t *) demux; + dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed; + + down(&dvbdmx->mutex); + if (dvbdmxfeed->state==DMX_STATE_FREE) { + up(&dvbdmx->mutex); + return -EINVAL; + } +#ifndef NOBUFS + if (dvbdmxfeed->buffer) { + vfree(dvbdmxfeed->buffer); + dvbdmxfeed->buffer=0; + } +#endif + dvbdmxfeed->state=DMX_STATE_FREE; + dvbdmxfeed->filter->state=DMX_STATE_FREE; + if (dvbdmxfeed->pid!=0xffff) { + if (dvbdmxfeed->pid<=DMX_MAX_PID) + dvbdmxfeed->demux->pid2feed[dvbdmxfeed->pid]=0; + dvbdmxfeed->pid=0xffff; + } + + up(&dvbdmx->mutex); + return 0; +} + + +/****************************************************************************** + * dmx_pes_feed API calls + ******************************************************************************/ +/* +static int +dmx_pes_feed_set(struct dmx_pes_feed_s* feed, + u16 pid, + size_t circular_buffer_size, + int descramble, + struct timespec timeout) +{ + return 0; +} + +static int +dmx_pes_feed_start_filtering(struct dmx_pes_feed_s* feed) +{ + return 0; +} + +static int +dmx_pes_feed_stop_filtering(struct dmx_pes_feed_s* feed) +{ + return 0; +} +*/ + +static int dvbdmx_allocate_pes_feed(dmx_demux_t *demux, + dmx_pes_feed_t **feed, + dmx_pes_cb callback) +{ + return 0; +} + +static int dvbdmx_release_pes_feed(dmx_demux_t *demux, + dmx_pes_feed_t *feed) +{ + return 0; +} + + +/****************************************************************************** + * dmx_section_feed API calls + ******************************************************************************/ + +static int +dmx_section_feed_allocate_filter(struct dmx_section_feed_s* feed, + dmx_section_filter_t** filter) +{ + dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed; + dvb_demux_t *dvbdemux=dvbdmxfeed->demux; + dvb_demux_filter_t *dvbdmxfilter; + + down(&dvbdemux->mutex); + dvbdmxfilter=DvbDmxFilterAlloc(dvbdemux); + if (!dvbdmxfilter) { + up(&dvbdemux->mutex); + return -ENOSPC; + } + *filter=&dvbdmxfilter->filter; + (*filter)->parent=feed; + (*filter)->priv=0; + dvbdmxfilter->feed=dvbdmxfeed; + dvbdmxfilter->pid=dvbdmxfeed->pid; + dvbdmxfilter->type=DMX_TYPE_SEC; + dvbdmxfilter->state=DMX_STATE_READY; + + dvbdmxfilter->next=dvbdmxfeed->filter; + dvbdmxfeed->filter=dvbdmxfilter; + up(&dvbdemux->mutex); + return 0; +} + +static int +dmx_section_feed_set(struct dmx_section_feed_s* feed, + u16 pid, size_t circular_buffer_size, + int descramble, int check_crc) +{ + dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed; + dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + + if (pid>0x1fff) + return -EINVAL; + down(&dvbdmx->mutex); + if (dvbdmxfeed->pid!=0xffff) { + dvbdmx->pid2feed[dvbdmxfeed->pid]=0; + dvbdmxfeed->pid=0xffff; + } + if (dvbdmx->pid2feed[pid]) { + up(&dvbdmx->mutex); + return -EBUSY; + } + dvbdmx->pid2feed[pid]=dvbdmxfeed; + dvbdmxfeed->pid=pid; + + dvbdmxfeed->buffer_size=circular_buffer_size; + dvbdmxfeed->descramble=descramble; + if (dvbdmxfeed->descramble) { + up(&dvbdmx->mutex); + return -ENOSYS; + } + + dvbdmxfeed->check_crc=check_crc; +#ifdef NOBUFS + dvbdmxfeed->buffer=0; +#else + dvbdmxfeed->buffer=vmalloc(dvbdmxfeed->buffer_size); + if (!dvbdmxfeed->buffer) { + up(&dvbdmx->mutex); + return -ENOMEM; + } +#endif + dvbdmxfeed->state=DMX_STATE_READY; + up(&dvbdmx->mutex); + return 0; +} + +static int +dmx_section_feed_start_filtering(dmx_section_feed_t *feed) +{ + dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed; + dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + int ret; + + down(&dvbdmx->mutex); + if (feed->is_filtering) { + up(&dvbdmx->mutex); + return -EBUSY; + } + if (!dvbdmxfeed->filter) { + up(&dvbdmx->mutex); + return -EINVAL; + } + dvbdmxfeed->secbufp=0; + dvbdmxfeed->seclen=0; + + if (!dvbdmx->start_feed) { + up(&dvbdmx->mutex); + return -1; + } + ret=dvbdmx->start_feed(dvbdmxfeed); + if (ret<0) { + up(&dvbdmx->mutex); + return ret; + } + feed->is_filtering=1; + dvbdmxfeed->state=DMX_STATE_GO; + up(&dvbdmx->mutex); + return 0; +} + +static int +dmx_section_feed_stop_filtering(struct dmx_section_feed_s* feed) +{ + dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed; + dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + int ret; + + down(&dvbdmx->mutex); + if (!dvbdmx->stop_feed) { + up(&dvbdmx->mutex); + return -1; + } + ret=dvbdmx->stop_feed(dvbdmxfeed); + + dvbdmxfeed->state=DMX_STATE_READY; + feed->is_filtering=0; + up(&dvbdmx->mutex); + return ret; +} + +static int +dmx_section_feed_release_filter(dmx_section_feed_t *feed, + dmx_section_filter_t* filter) +{ + dvb_demux_filter_t *dvbdmxfilter=(dvb_demux_filter_t *) filter, *f; + dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed; + dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + + down(&dvbdmx->mutex); + if (dvbdmxfilter->feed!=dvbdmxfeed) { + up(&dvbdmx->mutex); + return -EINVAL; + } + if (feed->is_filtering) + feed->stop_filtering(feed); + + f=dvbdmxfeed->filter; + if (f==dvbdmxfilter) + dvbdmxfeed->filter=dvbdmxfilter->next; + else { + while(f->next!=dvbdmxfilter) + f=f->next; + f->next=f->next->next; + } + dvbdmxfilter->state=DMX_STATE_FREE; + up(&dvbdmx->mutex); + return 0; +} + +static int dvbdmx_allocate_section_feed(dmx_demux_t *demux, + dmx_section_feed_t **feed, + dmx_section_cb callback) +{ + dvb_demux_t *dvbdmx=(dvb_demux_t *) demux; + dvb_demux_feed_t *dvbdmxfeed; + + down(&dvbdmx->mutex); + if (!(dvbdmxfeed=DvbDmxFeedAlloc(dvbdmx))) { + up(&dvbdmx->mutex); + return -EBUSY; + } + dvbdmxfeed->type=DMX_TYPE_SEC; + dvbdmxfeed->cb.sec=callback; + dvbdmxfeed->demux=dvbdmx; + dvbdmxfeed->pid=0xffff; + dvbdmxfeed->secbufp=0; + dvbdmxfeed->filter=0; + dvbdmxfeed->buffer=0; + + (*feed)=&dvbdmxfeed->feed.sec; + (*feed)->is_filtering=0; + (*feed)->parent=demux; + (*feed)->priv=0; + (*feed)->set=dmx_section_feed_set; + (*feed)->allocate_filter=dmx_section_feed_allocate_filter; + (*feed)->release_filter=dmx_section_feed_release_filter; + (*feed)->start_filtering=dmx_section_feed_start_filtering; + (*feed)->stop_filtering=dmx_section_feed_stop_filtering; + + up(&dvbdmx->mutex); + return 0; +} + +static int dvbdmx_release_section_feed(dmx_demux_t *demux, + dmx_section_feed_t *feed) +{ + dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed; + dvb_demux_t *dvbdmx=(dvb_demux_t *) demux; + + down(&dvbdmx->mutex); + if (dvbdmxfeed->state==DMX_STATE_FREE) { + up(&dvbdmx->mutex); + return -EINVAL; + } +#ifndef NOBUFS + if (dvbdmxfeed->buffer) { + vfree(dvbdmxfeed->buffer); + dvbdmxfeed->buffer=0; + } +#endif + dvbdmxfeed->state=DMX_STATE_FREE; + dvbdmxfeed->demux->pid2feed[dvbdmxfeed->pid]=0; + if (dvbdmxfeed->pid!=0xffff) + dvbdmxfeed->demux->pid2feed[dvbdmxfeed->pid]=0; + up(&dvbdmx->mutex); + return 0; +} + + +/****************************************************************************** + * dvb_demux kernel data API calls + ******************************************************************************/ + +static int dvbdmx_open(dmx_demux_t *demux) +{ + dvb_demux_t *dvbdemux=(dvb_demux_t *) demux; + + if (dvbdemux->users>=MAX_DVB_DEMUX_USERS) + return -EUSERS; + dvbdemux->users++; + return 0; +} + +static int dvbdmx_close(struct dmx_demux_s *demux) +{ + dvb_demux_t *dvbdemux=(dvb_demux_t *) demux; + + if (dvbdemux->users==0) + return -ENODEV; + dvbdemux->users--; + //FIXME: release any unneeded resources if users==0 + return 0; +} + +static int dvbdmx_write(dmx_demux_t *demux, const char *buf, size_t count) +{ + dvb_demux_t *dvbdemux=(dvb_demux_t *) demux; + + if ((!demux->frontend) || + (demux->frontend->source!=DMX_MEMORY_FE)) + return -EINVAL; + + down(&dvbdemux->mutex); + DvbDmxSWFilter(dvbdemux, buf, count); + up(&dvbdemux->mutex); + return count; +} + + +static int dvbdmx_add_frontend(dmx_demux_t *demux, + dmx_frontend_t *frontend) +{ + dvb_demux_t *dvbdemux=(dvb_demux_t *) demux; + struct list_head *pos, *head=&dvbdemux->frontend_list; + + //printk ("function : %s\n", __FUNCTION__); + + if (!(frontend->id && frontend->vendor && frontend->model)) + return -EINVAL; + list_for_each(pos, head) + { + if (!strcmp(DMX_FE_ENTRY(pos)->id, frontend->id)) + return -EEXIST; + } + + list_add(&(frontend->connectivity_list), head); + return 0; +} + +static int +dvbdmx_remove_frontend(dmx_demux_t *demux, + dmx_frontend_t *frontend) +{ + dvb_demux_t *dvbdemux=(dvb_demux_t *) demux; + struct list_head *pos, *head=&dvbdemux->frontend_list; + + list_for_each(pos, head) + { + if (DMX_FE_ENTRY(pos)==frontend) + { + list_del(pos); + return 0; + } + } + return -ENODEV; +} + +static struct list_head * +dvbdmx_get_frontends(dmx_demux_t *demux) +{ + dvb_demux_t *dvbdemux=(dvb_demux_t *) demux; + + if (list_empty(&dvbdemux->frontend_list)) + return NULL; + return &dvbdemux->frontend_list; +} + +static int dvbdmx_connect_frontend(dmx_demux_t *demux, + dmx_frontend_t *frontend) +{ + dvb_demux_t *dvbdemux=(dvb_demux_t *) demux; + + if (demux->frontend) + return -EINVAL; + + down(&dvbdemux->mutex); + demux->frontend=frontend; + up(&dvbdemux->mutex); + return 0; +} + +static int dvbdmx_disconnect_frontend(dmx_demux_t *demux) +{ + dvb_demux_t *dvbdemux=(dvb_demux_t *) demux; + + down(&dvbdemux->mutex); + demux->frontend=NULL; + up(&dvbdemux->mutex); + return 0; +} + +static int dvbdmx_get_pes_pids(dmx_demux_t *demux, u16 *pids) +{ + dvb_demux_t *dvbdemux=(dvb_demux_t *) demux; + + memcpy(pids, dvbdemux->pids, 5*sizeof(u16)); + return 0; +} + +int +DvbDmxInit(dvb_demux_t *dvbdemux) +{ + int i; + dmx_demux_t *dmx=&dvbdemux->dmx; + + dvbdemux->users=0; + dvbdemux->filter=vmalloc(dvbdemux->filternum*sizeof(dvb_demux_filter_t)); + if (!dvbdemux->filter) + return -ENOMEM; + + dvbdemux->feed=vmalloc(dvbdemux->feednum*sizeof(dvb_demux_feed_t)); + if (!dvbdemux->feed) { + vfree(dvbdemux->filter); + return -ENOMEM; + } + for (i=0; ifilternum; i++) { + dvbdemux->filter[i].state=DMX_STATE_FREE; + dvbdemux->filter[i].index=i; + } + for (i=0; ifeednum; i++) + dvbdemux->feed[i].state=DMX_STATE_FREE; + dvbdemux->frontend_list.next= + dvbdemux->frontend_list.prev= + &dvbdemux->frontend_list; + for (i=0; ipesfilter[i]=NULL; + dvbdemux->pids[i]=0xffff; + } + dvbdemux->playing=dvbdemux->recording=0; + memset(dvbdemux->pid2feed, 0, (DMX_MAX_PID+1)*sizeof(dvb_demux_feed_t *)); + dvbdemux->tsbufp=0; + + dmx->frontend=0; + dmx->reg_list.next=dmx->reg_list.prev=&dmx->reg_list; + dmx->priv=(void *) dvbdemux; + //dmx->users=0; // reset in dmx_register_demux() + dmx->open=dvbdmx_open; + dmx->close=dvbdmx_close; + dmx->write=dvbdmx_write; + dmx->allocate_ts_feed=dvbdmx_allocate_ts_feed; + dmx->release_ts_feed=dvbdmx_release_ts_feed; + dmx->allocate_pes_feed=dvbdmx_allocate_pes_feed; + dmx->release_pes_feed=dvbdmx_release_pes_feed; + dmx->allocate_section_feed=dvbdmx_allocate_section_feed; + dmx->release_section_feed=dvbdmx_release_section_feed; + + dmx->descramble_mac_address=NULL; + dmx->descramble_section_payload=NULL; + + dmx->add_frontend=dvbdmx_add_frontend; + dmx->remove_frontend=dvbdmx_remove_frontend; + dmx->get_frontends=dvbdmx_get_frontends; + dmx->connect_frontend=dvbdmx_connect_frontend; + dmx->disconnect_frontend=dvbdmx_disconnect_frontend; + dmx->get_pes_pids=dvbdmx_get_pes_pids; + sema_init(&dvbdemux->mutex, 1); + + if (dmx_register_demux(dmx)<0) + return -1; + + return 0; +} + +int +DvbDmxRelease(dvb_demux_t *dvbdemux) +{ + dmx_demux_t *dmx=&dvbdemux->dmx; + + dmx_unregister_demux(dmx); + if (dvbdemux->filter) + vfree(dvbdemux->filter); + if (dvbdemux->feed) + vfree(dvbdemux->feed); + return 0; +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/dvb_demux.h linux.19rc3-ac4/drivers/media/video/margi/dvb_demux.h --- linux.19rc3/drivers/media/video/margi/dvb_demux.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/dvb_demux.h 2002-07-29 13:58:42.000000000 +0100 @@ -0,0 +1,141 @@ +/* + * dvb_demux.h - DVB kernel demux API + * + * Copyright (C) 2000-2001 Marcus Metzler + * & Ralph Metzler + * for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * 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 Lesser 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. + * + */ + +#ifndef _DVB_DEMUX_H_ +#define _DVB_DEMUX_H_ + +#if LINUX_VERSION_CODE < 0x020300 +#define WAIT_QUEUE struct wait_queue* +#define init_waitqueue_head(wq) *(wq) = NULL; +#define DECLARE_WAITQUEUE(wait, current) struct wait_queue wait = { current, NULL } +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) +#else +#define WAIT_QUEUE wait_queue_head_t +#endif + +#include "ost/demux.h" + +#define DMX_TYPE_TS 0 +#define DMX_TYPE_SEC 1 +#define DMX_TYPE_PES 2 + +#define DMX_STATE_FREE 0 +#define DMX_STATE_ALLOCATED 1 +#define DMX_STATE_SET 2 +#define DMX_STATE_READY 3 +#define DMX_STATE_GO 4 + +#define DVB_DEMUX_MASK_MAX 18 + +typedef struct dvb_demux_filter_s { + dmx_section_filter_t filter; + struct dvb_demux_filter_s *next; + struct dvb_demux_feed_s *feed; + int index; + int state; + int type; + int pesto; + + u32 flags; + u16 handle; + u16 hw_handle; + struct timer_list timer; + int ts_state; + + u16 pid; //to be removed +} dvb_demux_filter_t; + +typedef struct dvb_demux_feed_s { + union { + dmx_ts_feed_t ts; + dmx_section_feed_t sec; + dmx_pes_feed_t pes; + } feed; + + union { + dmx_ts_cb ts; + dmx_section_cb sec; + dmx_pes_cb pes; + } cb; + + struct dvb_demux_s *demux; + int type; + int state; + u16 pid; + u8 *buffer; + int buffer_size; + int descramble; + int check_crc; + + struct timespec timeout; + dvb_demux_filter_t *filter; + int cb_length; + + int ts_type; + dmx_ts_pes_t pes_type; + + u8 secbuf[4096]; + int secbufp; + int seclen; + int cc; + + u16 peslen; +} dvb_demux_feed_t; + +typedef struct dvb_demux_s { + dmx_demux_t dmx; + void *priv; + int filternum; + int feednum; + int (*start_feed)(dvb_demux_feed_t *); + int (*stop_feed)(dvb_demux_feed_t *); + int (*write_to_decoder)(dvb_demux_feed_t *, u8 *, size_t); + + + int users; +#define MAX_DVB_DEMUX_USERS 10 + dvb_demux_filter_t *filter; + dvb_demux_feed_t *feed; + + struct list_head frontend_list; + + dvb_demux_feed_t *pesfilter[DMX_TS_PES_OTHER]; + u16 pids[DMX_TS_PES_OTHER]; + int playing; + int recording; + +#define DMX_MAX_PID 0x2000 + dvb_demux_feed_t *pid2feed[DMX_MAX_PID+1]; + u8 tsbuf[188]; + int tsbufp; + + struct semaphore mutex; +} dvb_demux_t; + + +int DvbDmxInit(dvb_demux_t *dvbdemux); +int DvbDmxRelease(dvb_demux_t *dvbdemux); +void DvbDmxSWFilterPackets(dvb_demux_t *dvbdmx, const u8 *buf, int count); + +#endif /* _DVB_DEMUX_H_ */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/dvbdev.c linux.19rc3-ac4/drivers/media/video/margi/dvbdev.c --- linux.19rc3/drivers/media/video/margi/dvbdev.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/dvbdev.c 2002-07-29 13:58:42.000000000 +0100 @@ -0,0 +1,233 @@ +/* + * dvbdev.c + * + * Copyright (C) 2000 Ralph Metzler + * & Marcus Metzler + for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * 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 Lesser 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dvbdev.h" + +#ifdef MODULE +MODULE_DESCRIPTION("Device registrar for DVB drivers"); +MODULE_AUTHOR("Marcus Metzler, Ralph Metzler"); +#ifdef MODULE_LICENSE +MODULE_LICENSE("LGPL"); +#endif +#endif + +#define DVB_MAJOR 250 + +static struct dvb_device *dvb_device[DVB_NUM_DEVICES]; +static devfs_handle_t dvb_devfs_handle; + +static inline struct dvb_device * +inode2dev (struct inode *inode) +{ + int minor=(MINOR(inode->i_rdev)>>6); + + return dvb_device[minor]; +} + +static inline int +inode2num(struct inode *inode) +{ + return (0x3f&MINOR(inode->i_rdev)); +} + +static ssize_t +dvb_device_read(struct file *file, char *buf, size_t count, loff_t *ppos) +{ + struct inode *inode=file->f_dentry->d_inode; + struct dvb_device *dvbdev=inode2dev(inode); + + if (!dvbdev) + return -ENODEV; + return dvbdev->read(dvbdev, inode2num(inode), file, buf, count, ppos); +} + +static ssize_t +dvb_device_write(struct file *file, const char *buf, + size_t count, loff_t *ppos) +{ + struct inode *inode=file->f_dentry->d_inode; + struct dvb_device *dvbdev=inode2dev(inode); + + if (!dvbdev) + return -ENODEV; + return dvbdev->write(dvbdev, inode2num(inode), file, buf, count, ppos); +} + +static int +dvb_device_open(struct inode *inode, struct file *file) +{ + struct dvb_device *dvbdev=inode2dev(inode); + + if (!dvbdev) + return -ENODEV; + return dvbdev->open(dvbdev, inode2num(inode), inode, file); +} + +static int +dvb_device_release(struct inode *inode, struct file *file) +{ + struct dvb_device *dvbdev=inode2dev(inode); + + if (!dvbdev) + return -ENODEV; + return dvbdev->close(dvbdev, inode2num(inode), inode, file); +} + +static int +dvb_device_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct dvb_device *dvbdev=inode2dev(inode); + + if (!dvbdev) + return -ENODEV; + return dvbdev->ioctl(dvbdev, inode2num(inode), file, cmd, arg); +} + +static unsigned int +dvb_device_poll(struct file *file, poll_table *wait) +{ + struct inode *inode=file->f_dentry->d_inode; + struct dvb_device *dvbdev=inode2dev(inode); + + if (!dvbdev) + return -ENODEV; + return dvbdev->poll(dvbdev, inode2num(inode), file, wait); +} + + +static struct file_operations dvb_device_fops = +{ + owner: THIS_MODULE, + read: dvb_device_read, + write: dvb_device_write, + ioctl: dvb_device_ioctl, + open: dvb_device_open, + release: dvb_device_release, + poll: dvb_device_poll, +}; + + +static char *dnames[] = { + "video", "audio", "sec", "frontend", "demux", "dvr", "ca", + "net", "osd" +}; + + +static void dvb_init_device(dvb_device_t *dev) +{ + int i, type; + char name[64]; + + sprintf(name, "card%d", dev->minor); + dev->devfsh = devfs_mk_dir (dvb_devfs_handle, name, NULL); + + for (i=0; (type=dev->device_type(dev,i))>-2; i++) { + if (type==-1) + continue; + + sprintf(name, "%s%d", dnames[type>>2], type&3); + devfs_register(dev->devfsh, name, DEVFS_FL_DEFAULT, + DVB_MAJOR, (dev->minor<<6)+i, + S_IFCHR | S_IRUSR | S_IWUSR, + &dvb_device_fops, NULL); + } + +} + +int dvb_register_device(dvb_device_t *dev) +{ + int i=0; + + for (i=0; iminor=i; + dvb_init_device(dev); + MOD_INC_USE_COUNT; + return 0; + } + } + return -ENFILE; +} + +void dvb_unregister_device(dvb_device_t *dev) +{ + if (dvb_device[dev->minor]!=dev) { + printk("dvbdev: bad unregister\n"); + return; + } + devfs_unregister(dev->devfsh); + dvb_device[dev->minor]=NULL; + MOD_DEC_USE_COUNT; +} + +int __init dvbdev_init(void) +{ + int i=0; + + for(i=0; i + * & Marcus Metzler + for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Lesser Public License + * as published by the Free Software Foundation; either version 2.1 + * 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 Lesser 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. + * + */ + +#ifndef _DVBDEV_H_ +#define _DVBDEV_H_ + +#include +#include +#include +#include + +#define DVB_NUM_DEVICES 16 + +struct dvb_device +{ + char name[32]; + int type; + int hardware; + + void *priv; + int minor; + devfs_handle_t devfs_handle; + + int (*open)(struct dvb_device *, int, struct inode *, struct file *); + int (*close)(struct dvb_device *, int, struct inode *, struct file *); + ssize_t (*read)(struct dvb_device *, int, struct file *, char *, + size_t, loff_t *); + ssize_t (*write)(struct dvb_device *, int, struct file *, const char *, + size_t, loff_t *); + int (*ioctl)(struct dvb_device *, int, struct file *, + unsigned int , unsigned long); + unsigned int (*poll)(struct dvb_device *, int type, + struct file *file, poll_table * wait); + + int (*device_type)(struct dvb_device *, unsigned int device_num); +#define DVB_DEVICE_VIDEO_0 0 +#define DVB_DEVICE_AUDIO_0 4 +#define DVB_DEVICE_SEC_0 8 +#define DVB_DEVICE_FRONTEND_0 12 +#define DVB_DEVICE_DEMUX_0 16 +#define DVB_DEVICE_DEMUX_1 17 +#define DVB_DEVICE_DEMUX_2 18 +#define DVB_DEVICE_DEMUX_3 19 +#define DVB_DEVICE_DVR_0 20 +#define DVB_DEVICE_CA_0 24 +#define DVB_DEVICE_NET_0 28 +#define DVB_DEVICE_OSD_0 32 + devfs_handle_t devfsh; +}; + +typedef struct dvb_device dvb_device_t; + +int dvb_register_device(struct dvb_device *); +void dvb_unregister_device(struct dvb_device *); + +#endif /* #ifndef __DVBDEV_H */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/dvb_filter.c linux.19rc3-ac4/drivers/media/video/margi/dvb_filter.c --- linux.19rc3/drivers/media/video/margi/dvb_filter.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/dvb_filter.c 2002-07-29 13:58:42.000000000 +0100 @@ -0,0 +1,769 @@ +#include +#include +#include "dvb_filter.h" +#if 0 +#ifdef MODULE +MODULE_DESCRIPTION(""); +MODULE_AUTHOR("Marcus Metzler, Ralph Metzler"); +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif +#endif +#endif + +unsigned int bitrates[3][16] = +{{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0}, + {0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0}, + {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0}}; + +uint32_t freq[4] = {441, 480, 320, 0}; + +unsigned int ac3_bitrates[32] = + {32,40,48,56,64,80,96,112,128,160,192,224,256,320,384,448,512,576,640, + 0,0,0,0,0,0,0,0,0,0,0,0,0}; + +uint32_t ac3_freq[4] = {480, 441, 320, 0}; +uint32_t ac3_frames[3][32] = + {{64,80,96,112,128,160,192,224,256,320,384,448,512,640,768,896,1024, + 1152,1280,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {69,87,104,121,139,174,208,243,278,348,417,487,557,696,835,975,1114, + 1253,1393,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {96,120,144,168,192,240,288,336,384,480,576,672,768,960,1152,1344, + 1536,1728,1920,0,0,0,0,0,0,0,0,0,0,0,0,0}}; + + + +void pes2ts_init(pes2ts_t *p2ts, unsigned short pid, + pes2ts_cb_t *cb, void *priv) +{ + unsigned char *buf=p2ts->buf; + + buf[0]=0x47; + buf[1]=(pid>>8); + buf[2]=pid&0xff; + p2ts->cc=0; + p2ts->cb=cb; + p2ts->priv=priv; +} + +int pes2ts(pes2ts_t *p2ts, unsigned char *pes, int len) +{ + unsigned char *buf=p2ts->buf; + int ret=0, rest; + + //len=6+((pes[4]<<8)|pes[5]); + + buf[1]|=0x40; + while (len>=184) { + buf[3]=0x10|((p2ts->cc++)&0x0f); + memcpy(buf+4, pes, 184); + if ((ret=p2ts->cb(p2ts->priv, buf))) + return ret; + len-=184; pes+=184; + buf[1]&=~0x40; + } + if (!len) + return 0; + buf[3]=0x30|((p2ts->cc++)&0x0f); + rest=183-len; + if (rest) { + buf[5]=0x00; + if (rest-1) + memset(buf+6, 0xff, rest-1); + } + buf[4]=rest; + memcpy(buf+5+rest, pes, len); + return p2ts->cb(p2ts->priv, buf); +} + +void reset_ipack(ipack *p) +{ + p->found = 0; + p->cid = 0; + p->plength = 0; + p->flag1 = 0; + p->flag2 = 0; + p->hlength = 0; + p->mpeg = 0; + p->check = 0; + p->which = 0; + p->done = 0; + p->count = 0; +} + +void init_ipack(ipack *p, int size, + void (*func)(u8 *buf, int size, void *priv)) +{ + if ( !(p->buf = vmalloc(size*sizeof(u8))) ){ + printk ("Couldn't allocate memory for ipack\n"); + } + p->size = size; + p->func = func; + p->repack_subids = 0; + reset_ipack(p); +} + +void free_ipack(ipack * p) +{ + if (p->buf) vfree(p->buf); +} + +void send_ipack(ipack *p) +{ + int off; + AudioInfo ai; + int ac3_off = 0; + int streamid=0; + int nframes= 0; + int f=0; + + switch ( p->mpeg ){ + case 2: + if (p->count < 10) return; + p->buf[3] = p->cid; + + p->buf[4] = (u8)(((p->count-6) & 0xFF00) >> 8); + p->buf[5] = (u8)((p->count-6) & 0x00FF); + if (p->repack_subids && p->cid == PRIVATE_STREAM1){ + + off = 9+p->buf[8]; + streamid = p->buf[off]; + if ((streamid & 0xF8) == 0x80){ + ai.off = 0; + ac3_off = ((p->buf[off+2] << 8)| + p->buf[off+3]); + if (ac3_off < p->count) + f=get_ac3info(p->buf+off+3+ac3_off, + p->count-ac3_off, &ai,0); + if ( !f ){ + nframes = (p->count-off-3-ac3_off)/ + ai.framesize + 1; + p->buf[off+2] = (ac3_off >> 8)& 0xFF; + p->buf[off+3] = (ac3_off)& 0xFF; + p->buf[off+1] = nframes; + + ac3_off += nframes * ai.framesize - + p->count; + } + } + } + p->func(p->buf, p->count, p->data); + + p->buf[6] = 0x80; + p->buf[7] = 0x00; + p->buf[8] = 0x00; + p->count = 9; + if (p->repack_subids && p->cid == PRIVATE_STREAM1 + && (streamid & 0xF8)==0x80 ){ + p->count += 4; + p->buf[9] = streamid; + p->buf[10] = (ac3_off >> 8)& 0xFF; + p->buf[11] = (ac3_off)& 0xFF; + p->buf[12] = 0; + } + + break; + case 1: + if (p->count < 8) return; + p->buf[3] = p->cid; + + p->buf[4] = (u8)(((p->count-6) & 0xFF00) >> 8); + p->buf[5] = (u8)((p->count-6) & 0x00FF); + p->func(p->buf, p->count, p->data); + + p->buf[6] = 0x0F; + p->count = 7; + break; + } +} + +void send_ipack_rest(ipack *p) +{ + if (p->plength != MMAX_PLENGTH-6 || p->found<=6) + return; + p->plength = p->found-6; + p->found = 0; + send_ipack(p); + reset_ipack(p); +} + +static void write_ipack(ipack *p, u8 *data, int count) +{ + u8 headr[3] = { 0x00, 0x00, 0x01} ; + + if (p->count < 6){ + memcpy(p->buf, headr, 3); + p->count = 6; + } + + if (p->count + count < p->size){ + memcpy(p->buf+p->count, data, count); + p->count += count; + } else { + int rest = p->size - p->count; + memcpy(p->buf+p->count, data, rest); + p->count += rest; + send_ipack(p); + if (count - rest > 0) + write_ipack(p, data+rest, count-rest); + } +} + +int instant_repack(u8 *buf, int count, ipack *p) +{ + int l; + int c=0; + + while (c < count && (p->mpeg == 0 || + (p->mpeg == 1 && p->found < 7) || + (p->mpeg == 2 && p->found < 9)) + && (p->found < 5 || !p->done)){ + switch ( p->found ){ + case 0: + case 1: + if (buf[c] == 0x00) p->found++; + else p->found = 0; + c++; + break; + case 2: + if (buf[c] == 0x01) p->found++; + else if (buf[c] == 0) { + p->found = 2; + } else p->found = 0; + c++; + break; + case 3: + p->cid = 0; + switch (buf[c]){ + case PROG_STREAM_MAP: + case PRIVATE_STREAM2: + case PROG_STREAM_DIR: + case ECM_STREAM : + case EMM_STREAM : + case PADDING_STREAM : + case DSM_CC_STREAM : + case ISO13522_STREAM: + p->done = 1; + case PRIVATE_STREAM1: + case VIDEO_STREAM_S ... VIDEO_STREAM_E: + case AUDIO_STREAM_S ... AUDIO_STREAM_E: + p->found++; + p->cid = buf[c]; + c++; + break; + default: + p->found = 0; + break; + } + break; + + case 4: + if (count-c > 1){ + p->plen[0] = buf[c]; + c++; + p->plen[1] = buf[c]; + c++; + p->found+=2; + p->plength=(p->plen[0]<<8)|p->plen[1]; + } else { + p->plen[0] = buf[c]; + p->found++; + return count; + } + break; + case 5: + p->plen[1] = buf[c]; + c++; + p->found++; + p->plength=(p->plen[0]<<8)|p->plen[1]; + break; + case 6: + if (!p->done){ + p->flag1 = buf[c]; + c++; + p->found++; + if ( (p->flag1 & 0xC0) == 0x80 ) p->mpeg = 2; + else { + p->hlength = 0; + p->which = 0; + p->mpeg = 1; + p->flag2 = 0; + } + } + break; + + case 7: + if ( !p->done && p->mpeg == 2) { + p->flag2 = buf[c]; + c++; + p->found++; + } + break; + + case 8: + if ( !p->done && p->mpeg == 2) { + p->hlength = buf[c]; + c++; + p->found++; + } + break; + + default: + + break; + } + } + + if (c == count) return count; + + if (!p->plength) p->plength = MMAX_PLENGTH-6; + + if ( p->done || ((p->mpeg == 2 && p->found >= 9) || + (p->mpeg == 1 && p->found >= 7)) ){ + switch (p->cid){ + + case AUDIO_STREAM_S ... AUDIO_STREAM_E: + case VIDEO_STREAM_S ... VIDEO_STREAM_E: + case PRIVATE_STREAM1: + + if (p->mpeg == 2 && p->found == 9) { + write_ipack(p, &p->flag1, 1); + write_ipack(p, &p->flag2, 1); + write_ipack(p, &p->hlength, 1); + } + + if (p->mpeg == 1 && p->found == 7) + write_ipack(p, &p->flag1, 1); + + if (p->mpeg == 2 && (p->flag2 & PTS_ONLY) && + p->found < 14) { + while (c < count && p->found < 14) { + p->pts[p->found-9] = buf[c]; + write_ipack(p, buf+c, 1); + c++; + p->found++; + } + if (c == count) return count; + } + + if (p->mpeg == 1 && p->which < 2000) { + + if (p->found == 7) { + p->check = p->flag1; + p->hlength = 1; + } + + while (!p->which && c < count && + p->check == 0xFF){ + p->check = buf[c]; + write_ipack(p, buf+c, 1); + c++; + p->found++; + p->hlength++; + } + + if ( c == count) return count; + + if ( (p->check & 0xC0) == 0x40 && !p->which){ + p->check = buf[c]; + write_ipack(p, buf+c, 1); + c++; + p->found++; + p->hlength++; + + p->which = 1; + if ( c == count) return count; + p->check = buf[c]; + write_ipack(p, buf+c, 1); + c++; + p->found++; + p->hlength++; + p->which = 2; + if ( c == count) return count; + } + + if (p->which == 1){ + p->check = buf[c]; + write_ipack(p, buf+c, 1); + c++; + p->found++; + p->hlength++; + p->which = 2; + if ( c == count) return count; + } + + if ( (p->check & 0x30) && p->check != 0xFF){ + p->flag2 = (p->check & 0xF0) << 2; + p->pts[0] = p->check; + p->which = 3; + } + + if ( c == count) return count; + if (p->which > 2){ + if ((p->flag2 & PTS_DTS_FLAGS) + == PTS_ONLY){ + while (c < count && + p->which < 7){ + p->pts[p->which-2] = + buf[c]; + write_ipack(p,buf+c,1); + c++; + p->found++; + p->which++; + p->hlength++; + } + if ( c == count) return count; + } else if ((p->flag2 & PTS_DTS_FLAGS) + == PTS_DTS){ + while (c < count && + p->which< 12){ + if (p->which< 7) + p->pts[p->which + -2] = + buf[c]; + write_ipack(p,buf+c,1); + c++; + p->found++; + p->which++; + p->hlength++; + } + if ( c == count) return count; + } + p->which = 2000; + } + + } + + while (c < count && p->found < p->plength+6){ + l = count -c; + if (l+p->found > p->plength+6) + l = p->plength+6-p->found; + write_ipack(p, buf+c, l); + p->found += l; + c += l; + } + + break; + } + + + if ( p->done ){ + if( p->found + count - c < p->plength+6){ + p->found += count-c; + c = count; + } else { + c += p->plength+6 - p->found; + p->found = p->plength+6; + } + } + + if (p->plength && p->found == p->plength+6) { + send_ipack(p); + reset_ipack(p); + if (c < count) + instant_repack(buf+c, count-c, p); + } + } + return count; +} + + + +void setup_ts2pes(ipack *pa, ipack *pv, u16 *pida, u16 *pidv, + void (*pes_write)(u8 *buf, int count, void *data), + void *priv) +{ + init_ipack(pa, IPACKS, pes_write); + init_ipack(pv, IPACKS, pes_write); + pa->pid = pida; + pv->pid = pidv; + pa->data = priv; + pv->data = priv; +} + +void ts_to_pes(ipack *p, u8 *buf) // don't need count (=188) +{ + u8 off = 0; + + if (!buf || !p ){ + printk("NULL POINTER IDIOT\n"); + return; + } + if (buf[1]&PAY_START) { + if (p->plength == MMAX_PLENGTH-6 && p->found>6){ + p->plength = p->found-6; + p->found = 0; + send_ipack(p); + reset_ipack(p); + } + } + if (buf[3] & ADAPT_FIELD) { // adaptation field? + off = buf[4] + 1; + if (off+4 > 187) return; + } + instant_repack(buf+4+off, TS_SIZE-4-off, p); +} + +int get_vinfo(uint8_t *mbuf, int count, VideoInfo *vi, int pr) +{ + uint8_t *headr; + int found = 0; + int sw; + int form = -1; + int c = 0; + + while (found < 4 && c+4 < count){ + uint8_t *b; + + b = mbuf+c; + if ( b[0] == 0x00 && b[1] == 0x00 && b[2] == 0x01 + && b[3] == 0xb3) found = 4; + else { + c++; + } + } + + if (! found) return -1; + c += 4; + if (c+12 >= count) return -1; + headr = mbuf+c; + + vi->horizontal_size = ((headr[1] &0xF0) >> 4) | (headr[0] << 4); + vi->vertical_size = ((headr[1] &0x0F) << 8) | (headr[2]); + + sw = (int)((headr[3]&0xF0) >> 4) ; + + switch( sw ){ + case 1: + if (pr) + printk("Videostream: ASPECT: 1:1"); + vi->aspect_ratio = 100; + break; + case 2: + if (pr) + printk("Videostream: ASPECT: 4:3"); + vi->aspect_ratio = 133; + break; + case 3: + if (pr) + printk("Videostream: ASPECT: 16:9"); + vi->aspect_ratio = 177; + break; + case 4: + if (pr) + printk("Videostream: ASPECT: 2.21:1"); + vi->aspect_ratio = 221; + break; + + case 5 ... 15: + if (pr) + printk("Videostream: ASPECT: reserved"); + vi->aspect_ratio = 0; + break; + + default: + vi->aspect_ratio = 0; + return -1; + } + + if (pr) + printk(" Size = %dx%d",vi->horizontal_size,vi->vertical_size); + + sw = (int)(headr[3]&0x0F); + + switch ( sw ) { + case 1: + if (pr) + printk(" FRate: 23.976 fps"); + vi->framerate = 24000/1001.; + form = -1; + break; + case 2: + if (pr) + printk(" FRate: 24 fps"); + vi->framerate = 24; + form = -1; + break; + case 3: + if (pr) + printk(" FRate: 25 fps"); + vi->framerate = 25; + form = VIDEO_MODE_PAL; + break; + case 4: + if (pr) + printk(" FRate: 29.97 fps"); + vi->framerate = 30000/1001.; + form = VIDEO_MODE_NTSC; + break; + case 5: + if (pr) + printk(" FRate: 30 fps"); + vi->framerate = 30; + form = VIDEO_MODE_NTSC; + break; + case 6: + if (pr) + printk(" FRate: 50 fps"); + vi->framerate = 50; + form = VIDEO_MODE_PAL; + break; + case 7: + if (pr) + printk(" FRate: 60 fps"); + vi->framerate = 60; + form = VIDEO_MODE_NTSC; + break; + } + + vi->bit_rate = 400*(((headr[4] << 10) & 0x0003FC00UL) + | ((headr[5] << 2) & 0x000003FCUL) | + (((headr[6] & 0xC0) >> 6) & 0x00000003UL)); + + if (pr){ + printk(" BRate: %d Mbit/s",(vi->bit_rate)); + printk("\n"); + } + vi->video_format = form; + + vi->off = c-4; + return 0; +} + +int get_ainfo(uint8_t *mbuf, int count, AudioInfo *ai, int pr) +{ + uint8_t *headr; + int found = 0; + int c = 0; + int fr = 0; + + while (found < 2 && c < count){ + uint8_t b[2]; + memcpy( b, mbuf+c, 2); + + if ( b[0] == 0xff && (b[1] & 0xf8) == 0xf8) + found = 2; + else { + c++; + } + } + + if (!found) return -1; + + if (c+3 >= count) return -1; + headr = mbuf+c; + + ai->layer = (headr[1] & 0x06) >> 1; + + if (pr) + printk("Audiostream: Layer: %d", 4-ai->layer); + + + ai->bit_rate = bitrates[(3-ai->layer)][(headr[2] >> 4 )]*1000; + + if (pr){ + if (ai->bit_rate == 0) + printk(" Bit rate: free"); + else if (ai->bit_rate == 0xf) + printk(" BRate: reserved"); + else + printk(" BRate: %d kb/s", ai->bit_rate/1000); + } + + fr = (headr[2] & 0x0c ) >> 2; + ai->frequency = freq[fr]*100; + if (pr){ + if (ai->frequency == 3) + printk(" Freq: reserved\n"); + else + printk(" Freq: %d kHz\n",ai->frequency); + + } + ai->off = c; + return 0; +} + +int get_ac3info(uint8_t *mbuf, int count, AudioInfo *ai, int pr) +{ + uint8_t *headr; + int found = 0; + int c = 0; + uint8_t frame = 0; + int fr = 0; + + while ( !found && c < count){ + uint8_t *b = mbuf+c; + + if ( b[0] == 0x0b && b[1] == 0x77 ) + found = 1; + else { + c++; + } + } + + if (!found) return -1; + if (pr) + printk("Audiostream: AC3"); + + ai->off = c; + if (c+5 >= count) return -1; + + ai->layer = 0; // 0 for AC3 + headr = mbuf+c+2; + + frame = (headr[2]&0x3f); + ai->bit_rate = ac3_bitrates[frame >> 1]*1000; + + if (pr) + printk(" BRate: %d kb/s", ai->bit_rate/1000); + + ai->frequency = (headr[2] & 0xc0 ) >> 6; + fr = (headr[2] & 0xc0 ) >> 6; + ai->frequency = freq[fr]*100; + if (pr) printk (" Freq: %d Hz\n", ai->frequency); + + + ai->framesize = ac3_frames[fr][frame >> 1]; + if ((frame & 1) && (fr == 1)) ai->framesize++; + ai->framesize = ai->framesize << 1; + if (pr) printk (" Framesize %d\n", ai->framesize); + + + return 0; +} + +uint8_t *skip_pes_header(uint8_t **bufp) +{ + uint8_t *inbuf = *bufp; + uint8_t *buf = inbuf; + uint8_t *pts = NULL; + int skip = 0; + +int mpeg1_skip_table[16] = { + 1, 0xffff, 5, 10, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff +}; + + + if ((inbuf[6] & 0xc0) == 0x80){ /* mpeg2 */ + if (buf[7] & PTS_ONLY) + pts = buf+9; + else pts = NULL; + buf = inbuf + 9 + inbuf[8]; + } else { /* mpeg1 */ + for (buf = inbuf + 6; *buf == 0xff; buf++) + if (buf == inbuf + 6 + 16) { + break; + } + if ((*buf & 0xc0) == 0x40) + buf += 2; + skip = mpeg1_skip_table [*buf >> 4]; + if (skip == 5 || skip == 10) pts = buf; + else pts = NULL; + + buf += mpeg1_skip_table [*buf >> 4]; + } + + *bufp = buf; + return pts; +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/dvb_filter.h linux.19rc3-ac4/drivers/media/video/margi/dvb_filter.h --- linux.19rc3/drivers/media/video/margi/dvb_filter.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/dvb_filter.h 2002-07-29 17:29:11.000000000 +0100 @@ -0,0 +1,146 @@ +#ifndef _DVB_FILTER_H_ +#define _DVB_FILTER_H_ + +#include +#include + +#include "ost/demux.h" + +typedef int (pes2ts_cb_t) (void *, unsigned char *); + +typedef struct pes2ts_s { + unsigned char buf[188]; + unsigned char cc; + pes2ts_cb_t *cb; + void *priv; +} pes2ts_t; + +void pes2ts_init(pes2ts_t *p2ts, unsigned short pid, + pes2ts_cb_t *cb, void *priv); +int pes2ts(pes2ts_t *p2ts, unsigned char *pes, int len); + + +#define PROG_STREAM_MAP 0xBC +#define PRIVATE_STREAM1 0xBD +#define PADDING_STREAM 0xBE +#define PRIVATE_STREAM2 0xBF +#define AUDIO_STREAM_S 0xC0 +#define AUDIO_STREAM_E 0xDF +#define VIDEO_STREAM_S 0xE0 +#define VIDEO_STREAM_E 0xEF +#define ECM_STREAM 0xF0 +#define EMM_STREAM 0xF1 +#define DSM_CC_STREAM 0xF2 +#define ISO13522_STREAM 0xF3 +#define PROG_STREAM_DIR 0xFF + +//flags2 +#define PTS_DTS_FLAGS 0xC0 +#define ESCR_FLAG 0x20 +#define ES_RATE_FLAG 0x10 +#define DSM_TRICK_FLAG 0x08 +#define ADD_CPY_FLAG 0x04 +#define PES_CRC_FLAG 0x02 +#define PES_EXT_FLAG 0x01 + +//pts_dts flags +#define PTS_ONLY 0x80 +#define PTS_DTS 0xC0 + +#define TS_SIZE 188 +#define TRANS_ERROR 0x80 +#define PAY_START 0x40 +#define TRANS_PRIO 0x20 +#define PID_MASK_HI 0x1F +//flags +#define TRANS_SCRMBL1 0x80 +#define TRANS_SCRMBL2 0x40 +#define ADAPT_FIELD 0x20 +#define PAYLOAD 0x10 +#define COUNT_MASK 0x0F + +// adaptation flags +#define DISCON_IND 0x80 +#define RAND_ACC_IND 0x40 +#define ES_PRI_IND 0x20 +#define PCR_FLAG 0x10 +#define OPCR_FLAG 0x08 +#define SPLICE_FLAG 0x04 +#define TRANS_PRIV 0x02 +#define ADAP_EXT_FLAG 0x01 + +// adaptation extension flags +#define LTW_FLAG 0x80 +#define PIECE_RATE 0x40 +#define SEAM_SPLICE 0x20 + + +#define MAX_PLENGTH 0xFFFF +#define MMAX_PLENGTH (256*MAX_PLENGTH) + +#ifndef IPACKS +#define IPACKS 2048 +#endif + +typedef struct ipack_s { + int size; + int found; + u8 *buf; + u8 cid; + uint32_t plength; + u8 plen[2]; + u8 flag1; + u8 flag2; + u8 hlength; + u8 pts[5]; + u16 *pid; + int mpeg; + u8 check; + int which; + int done; + void *data; + void (*func)(u8 *buf, int size, void *priv); + int count; + int repack_subids; +} ipack; + +typedef struct video_i{ + u32 horizontal_size; + u32 vertical_size ; + u32 aspect_ratio ; + double framerate ; + u32 video_format; + u32 bit_rate ; + u32 comp_bit_rate ; + u32 vbv_buffer_size; + u32 CSPF ; + u32 off; +} VideoInfo; + +typedef struct audio_i{ + int layer ; + u32 bit_rate ; + u32 frequency ; + u32 mode ; + u32 mode_extension ; + u32 emphasis ; + u32 framesize; + u32 off; +} AudioInfo; + +void reset_ipack(ipack *p); +int instant_repack(u8 *buf, int count, ipack *p); +void init_ipack(ipack *p, int size, + void (*func)(u8 *buf, int size, void *priv)); +void free_ipack(ipack * p); +void setup_ts2pes(ipack *pa, ipack *pv, u16 *pida, u16 *pidv, + void (*pes_write)(u8 *buf, int count, void *data), + void *priv); +void ts_to_pes(ipack *p, u8 *buf); +void send_ipack(ipack *p); +void send_ipack_rest(ipack *p); +int get_ainfo(uint8_t *mbuf, int count, AudioInfo *ai, int pr); +int get_ac3info(uint8_t *mbuf, int count, AudioInfo *ai, int pr); +int get_vinfo(uint8_t *mbuf, int count, VideoInfo *vi, int pr); +uint8_t *skip_pes_header(uint8_t **bufp); +#endif diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/dvb_formats.h linux.19rc3-ac4/drivers/media/video/margi/dvb_formats.h --- linux.19rc3/drivers/media/video/margi/dvb_formats.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/dvb_formats.h 2002-07-29 17:29:11.000000000 +0100 @@ -0,0 +1,152 @@ +/* + * + * Copyright (C) 2000, 2001 Marcus Metzler + * for convergence integrated media GmbH + * + * 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. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + * + + * The author can be reached at marcus@convergence.de, + + * the project's page is at http://linuxtv.org/dvb/ + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef _DVB_FORMATS_H_ +#define _DVB_FORMATS_H_ + + +#define PROG_STREAM_MAP 0xBC +#ifndef PRIVATE_STREAM1 +#define PRIVATE_STREAM1 0xBD +#endif +#define PADDING_STREAM 0xBE +#ifndef PRIVATE_STREAM2 +#define PRIVATE_STREAM2 0xBF +#endif +#define AUDIO_STREAM_S 0xC0 +#define AUDIO_STREAM_E 0xDF +#define VIDEO_STREAM_S 0xE0 +#define VIDEO_STREAM_E 0xEF +#define ECM_STREAM 0xF0 +#define EMM_STREAM 0xF1 +#define DSM_CC_STREAM 0xF2 +#define ISO13522_STREAM 0xF3 +#define PROG_STREAM_DIR 0xFF + +#define BUFFYSIZE 10*MAX_PLENGTH +//#define MAX_PTS 8192 +#define MAX_FRAME 8192 +#define MAX_PACK_L 4096 +#define PS_HEADER_L1 14 +#define PS_HEADER_L2 (PS_HEADER_L1+18) +#define MAX_H_SIZE (PES_H_MIN + PS_HEADER_L1 + 5) +#define PES_MIN 7 +#define PES_H_MIN 9 + +//flags2 +#define PTS_DTS_FLAGS 0xC0 +#define ESCR_FLAG 0x20 +#define ES_RATE_FLAG 0x10 +#define DSM_TRICK_FLAG 0x08 +#define ADD_CPY_FLAG 0x04 +#define PES_CRC_FLAG 0x02 +#define PES_EXT_FLAG 0x01 + +//pts_dts flags +#define PTS_ONLY 0x80 +#define PTS_DTS 0xC0 + +#define TS_SIZE 188 +#define TRANS_ERROR 0x80 +#define PAY_START 0x40 +#define TRANS_PRIO 0x20 +#define PID_MASK_HI 0x1F +//flags +#define TRANS_SCRMBL1 0x80 +#define TRANS_SCRMBL2 0x40 +#define ADAPT_FIELD 0x20 +#define PAYLOAD 0x10 +#define COUNT_MASK 0x0F + +// adaptation flags +#define DISCON_IND 0x80 +#define RAND_ACC_IND 0x40 +#define ES_PRI_IND 0x20 +#define PCR_FLAG 0x10 +#define OPCR_FLAG 0x08 +#define SPLICE_FLAG 0x04 +#define TRANS_PRIV 0x02 +#define ADAP_EXT_FLAG 0x01 + +// adaptation extension flags +#define LTW_FLAG 0x80 +#define PIECE_RATE 0x40 +#define SEAM_SPLICE 0x20 + + +#define MAX_PLENGTH 0xFFFF +#define MMAX_PLENGTH (4*MAX_PLENGTH) + +#define IPACKS 2048 + +typedef struct ipack_s { + int size; + int found; + uint8_t *buf; + uint8_t cid; + uint32_t plength; + uint8_t plen[2]; + uint8_t flag1; + uint8_t flag2; + uint8_t hlength; + uint8_t pts[5]; + uint16_t *pid; + int mpeg; + uint8_t check; + int which; + int done; + void *data; + void (*func)(uint8_t *buf, int size, void *priv); + int count; +} ipack; + +void instant_repack (uint8_t *buf, int count, ipack *p); +void init_ipack(ipack *p, int size, + void (*func)(uint8_t *buf, int size, void *priv)); +void free_ipack(ipack * p); +void setup_ts2pes( ipack *pa, ipack *pv, uint16_t *pida, uint16_t *pidv, + void (*pes_write)(uint8_t *buf, int count, void *data), + void *priv); +void ts_to_pes( ipack *p, uint8_t *buf); // don't need count (=188) +uint16_t get_pid(uint8_t *pid); + + +#endif /* _DVB_FORMATS_H_*/ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/i2c.c linux.19rc3-ac4/drivers/media/video/margi/i2c.c --- linux.19rc3/drivers/media/video/margi/i2c.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/i2c.c 2002-07-29 13:58:42.000000000 +0100 @@ -0,0 +1,186 @@ +/* + i2c.h + + Copyright (C) Marcus Metzler for convergence integrated media. + + 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 __NO_VERSION__ + +#include "i2c.h" + +void out(struct cvdv_cards *card) +{ + write_indexed_register(card, IIO_GPIO_PINS, + (card->scl ? SCL : 0) | + (card->sda ? SDA : 0) | 1); + udelay(10); +} + +void clkon(struct cvdv_cards *card) +{ + card->scl = 1; +} + +void clkoff(struct cvdv_cards *card) +{ + card->scl = 0; +} + +void dat(struct cvdv_cards *card, u_char data) +{ + card->sda = data; +} + +int rdat(struct cvdv_cards *card) +{ + return ((read_indexed_register(card, IIO_GPIO_PINS) & SDA) ? 1 : + 0); +} + + +void I2CStart(struct cvdv_cards *card) +{ + dat(card, 1); + out(card); + clkon(card); + out(card); + dat(card, 0); + out(card); + clkoff(card); + out(card); +} + +void I2CStop(struct cvdv_cards *card) +{ + dat(card, 0); + out(card); + clkon(card); + out(card); + dat(card, 1); + out(card); + clkoff(card); + out(card); +} + +int I2CAck(struct cvdv_cards *card, int ack) +{ + dat(card, ack); + out(card); + write_indexed_register(card, IIO_GPIO_CONTROL, (~SDA) & 0x07); + clkon(card); + out(card); + ack = rdat(card); + clkoff(card); + out(card); + write_indexed_register(card, IIO_GPIO_CONTROL, 0x07); + out(card); + return ack; +} + +u_char I2CReadByte(struct cvdv_cards * card, int ack) +{ + int i; + u_char data = 0; + + clkoff(card); + dat(card, 1); + out(card); + write_indexed_register(card, IIO_GPIO_CONTROL, (~SDA) & 0x07); + for (i = 7; i >= 0; i--) { + clkon(card); + out(card); + data |= (rdat(card) << i); + clkoff(card); + out(card); + } + write_indexed_register(card, IIO_GPIO_CONTROL, 0x07); + I2CAck(card, ack); + return data; +} + + +int I2CSendByte(struct cvdv_cards *card, u_char data) +{ + int i; + + for (i = 7; i >= 0; i--) { + dat(card, data & (1 << i)); + out(card); + clkon(card); + out(card); + clkoff(card); + out(card); + } + i = I2CAck(card, 1); + return i; +} + +void I2CWrite(struct cvdv_cards *card, int adr, int reg, int val) +{ + I2CStart(card); + I2CSendByte(card, adr); + I2CSendByte(card, reg); + I2CSendByte(card, val); + I2CStop(card); +} + + +u_char I2CRead(struct cvdv_cards *card, int adr, int reg) +{ + u_char c; + + I2CStart(card); + I2CSendByte(card, adr); + I2CSendByte(card, reg); + I2CStart(card); + I2CSendByte(card, adr | 1); + c = I2CReadByte(card, 1); + I2CStop(card); + return c; +} + + +int I2CScan(struct cvdv_cards *card, int adr) +{ + int result; + I2CStart(card); + result = I2CSendByte(card, adr); + I2CStop(card); + return result; +} + +void I2CScanBus(struct cvdv_cards *card) +{ + int i; + + for (i = 0; i < 0xff; i += 2) { + if (!I2CScan(card, i)) + MDEBUG(0,"Found i2c device at %d\n", i); + } +} + +void I2CSend(struct cvdv_cards *card, int adr, u_char * vals) +{ + int reg, val; + while (*vals != 0xff) { + reg = *vals; + vals++; + val = *vals; + vals++; + I2CWrite(card, adr, reg, val); + } +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/i2c.h linux.19rc3-ac4/drivers/media/video/margi/i2c.h --- linux.19rc3/drivers/media/video/margi/i2c.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/i2c.h 2002-07-29 17:29:11.000000000 +0100 @@ -0,0 +1,43 @@ +/* + i2c.h + + Copyright (C) Marcus Metzler for convergence integrated media. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef I2C_H +#define I2C_H +#include "cardbase.h" +#include "l64014.h" +#include "margi.h" + +void out(struct cvdv_cards *card); +void clkon(struct cvdv_cards *card); +void clkoff(struct cvdv_cards *card); +void dat(struct cvdv_cards *card, u_char data); +int rdat(struct cvdv_cards *card); +void I2CStart(struct cvdv_cards *card); +void I2CStop(struct cvdv_cards *card); +int I2CAck(struct cvdv_cards *card, int ack); +u_char I2CReadByte(struct cvdv_cards *card, int ack); +int I2CSendByte(struct cvdv_cards *card, u_char data); +void I2CWrite(struct cvdv_cards *card, int adr, int reg, int val); +u_char I2CRead(struct cvdv_cards *card, int adr, int reg); +int I2CScan(struct cvdv_cards *card, int adr); +void I2CScanBus(struct cvdv_cards *card); +void I2CSend(struct cvdv_cards *card, int adr, u_char * vals); + +#endif /* I2C_H */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/l64014.h linux.19rc3-ac4/drivers/media/video/margi/l64014.h --- linux.19rc3/drivers/media/video/margi/l64014.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/l64014.h 2002-07-29 17:29:11.000000000 +0100 @@ -0,0 +1,188 @@ +/* + l64014.h + + Copyright (C) Marcus Metzler for convergence integrated media. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef L64014_h +#define L64014_h + +#include +#include +#include + + +#define DIO_CONTROL_INDEX 0x00 +#define DIO_CONTROL_DATA 0x02 +#define DIO_LSI_STATUS 0x04 +#define DIO_LSI_CHANNEL_DATA 0x04 +#define DIO_LSI_INDEX_LOW 0x08 +#define DIO_LSI_DATA 0x0A +#define DIO_LSI_INDEX_HIGH 0x0C + +#define LSI_READY 0x08 +#define LSI_WAIT 0x04 +#define LSI_ARQ 0x02 +#define LSI_VRQ 0x01 + +#define IIO_ID 0x00 +#define IIO_MODE 0x01 +#define IIO_IRQ_CONTROL 0x02 +#define IIO_IRQ_STATUS 0x03 +#define IIO_LSI_CONTROL 0x06 +#define IIO_OSC_AUD 0x08 +#define IIO_VIDEO_CONTROL0 0x09 +#define IIO_VIDEO_CONTROL1 0x0A +#define IIO_VIDEO_LOOKUP 0x0B +#define IIO_EEPROM_CONTROL 0x0C +#define IIO_VIDEO_HOR_DELAY 0x0D +#define IIO_VIDEO_HOR_ACTIVE 0x0E +#define IIO_VIDEO_HOR_HIGH 0x0F +#define IIO_GPIO_CONTROL 0x10 +#define IIO_GPIO_PINS 0x11 +#define IIO_CSS_COMMAND 0x12 +#define IIO_CSS_STATUS 0x13 +#define IIO_CSS_KEY 0x14 + +#define SCL 0x02 +#define SDA 0x04 + +#define CS_CONTROL0 0x00 +#define CS_CONTROL1 0x01 +#define CS_CONTROL2 0x02 +#define CS_DAC 0x04 +#define CS_STATUS 0x07 +#define CS_BKG_COL 0x08 +#define CS_GPIO_CTRL 0x09 +#define CS_GPIO_DATA 0x0A +#define CS_C_AMP 0x0D +#define CS_Y_AMP 0x0E +#define CS_I2C_ADR 0x0F +#define CS_SC_AMP 0x10 +#define CS_SC_SYNTH0 0x11 +#define CS_SC_SYNTH1 0x12 +#define CS_SC_SYNTH2 0x13 +#define CS_SC_SYNTH3 0x14 +#define CS_HUE_LSB 0x15 +#define CS_HUE_MSB 0x16 +#define CS_CC_EN 0x18 +#define CS_CC_21_1 0x19 +#define CS_CC_21_2 0x1A +#define CS_CC_284_1 0x1B +#define CS_CC_284_2 0x1C +#define CS_INT_EN 0x3B +#define CS_INT_CLR 0x3C +#define CS_ID_REG 0x3D + + +#define CSS_COMMAND 0x12 +#define CSS_STATUS 0x13 +#define CSS_KEY 0x14 + +#define L14_CSS_NONE 0x00 +#define L14_CSS_PASSTHRU 0x01 +#define L14_CSS_DESCRAM 0x05 +#define L14_CSS_GEN_CH 0x08 +#define L14_CSS_RD_CH 0x09 +#define L14_CSS_WR_CH 0x0a +#define L14_CSS_WR_DRVREF 0x0b +#define L14_CSS_DRVAUTH 0x0c +#define L14_CSS_DECAUTH 0x0d +#define L14_CSS_DISCKEY 0x0e +#define L14_CSS_TITLEKEY 0x0f +#define L14_CSS_CMD_START 0x10 + +#define L14_CSS_BUSY 0x01 +#define L14_CSS_SUCCESS 0x02 + +#define DSVC 0x40 +#define RR 0x20 +#define DR 0x01 +#define AF1 0x20 +#define AF0 0x10 +#define SLEEP 0x08 +#define AFS2 0x04 +#define AFS1 0x02 +#define AFS0 0x01 + +#define ZVCLK13 0x04 +#define ZVCLKINV 0x08 +#define ZV16BIT 0x10 +#define ZVVREF_INVERT 0x08 +#define ZVHREF_INVERT 0x10 +#define HSYNC_INVERT 0x20 +#define ZV_OVERRIDE 0x40 +#define ZV_ENABLE 0x80 + + +#define IRQ_EN 0x04 +#define IRQ_MSK 0x08 +#define IRQ_POL 0x10 +#define DEC_EN 0x20 +#define DEC_INT 0x10 +#define VSYNC_EN 0x80 +#define VSYNC_INT 0x40 + +#define VMS_NOSY 0x00 +#define VMS_NTSC 0x01 +#define VMS_PAL 0x02 +#define VMS_PAL24 0x03 + +#define MAUDIO_PAUSE 0 +#define MAUDIO_PLAY 1 +#define MAUDIO_FAST 2 +#define MAUDIO_SLOW 3 + + +#define RegisterReadByte(card,where) read_indexed_register(&(card->link),(where)) +#define RegisterWriteByte(card,where,what) write_indexed_register(&(card->link),where,what) +#define RegisterMaskByte(card,where,mask,bits) RegisterWriteByte(card,where,(RegisterReadByte(card,where)&~(mask))|(bits)) +#define RegisterSetByte(card,where,bits) RegisterWriteByte(card,where,RegisterReadByte(card,where)|(bits)) +#define RegisterDelByte(card,where,mask) RegisterWriteByte(card,where,RegisterReadByte(card,where)&~(mask)) + +#define RegisterReadWord(card,where) (\ + (u16)RegisterReadByte(card,where)|\ + ((u16)RegisterReadByte(card,(where)+1)<<8)) +#define RegisterWriteWord(card,where,what) {\ + RegisterWriteByte(card,where,(what) & 0xFF);\ + RegisterWriteByte(card,(where)+1,((what)>>8) & 0xFF);} + +// 3-byte-wide (medium word, 24 Bit) access to the card's registers, LSB first +#define RegisterReadMWord(card,where) (\ + (u32)RegisterReadByte(card,where)|\ + ((u32)RegisterReadByte(card,(where)+1)<<8)|\ + ((u32)RegisterReadByte(card,(where)+2)<<16)) +#define RegisterWriteMWord(card,where,what) {\ + RegisterWriteByte(card,where,(what) & 0xFF);\ + RegisterWriteByte(card,(where)+1,((what)>>8) & 0xFF);\ + RegisterWriteByte(card,(where)+2,((what)>>16) & 0xFF);} + +// double-word-wide access to the card's registers, LSB first +//#define RegisterReadDWord(card,where) le32_to_cpu(readl(card->addr+(where))) +//#define RegisterWriteDWord(card,where,what) writel(cpu_to_le32(what),card->addr+(where)) +#define RegisterReadDWord(card,where) (\ + (u32)RegisterReadByte(card,where)|\ + ((u32)RegisterReadByte(card,(where)+1)<<8)|\ + ((u32)RegisterReadByte(card,(where)+2)<<16)|\ + ((u32)RegisterReadByte(card,(where)+3)<<24)) +#define RegisterWriteDWord(card,where,what) {\ + RegisterWriteByte(card,where,(what) & 0xFF);\ + RegisterWriteByte(card,(where)+1,((what)>>8) & 0xFF);\ + RegisterWriteByte(card,(where)+2,((what)>>16) & 0xFF);\ + RegisterWriteByte(card,(where)+3,((what)>>24) & 0xFF);} + +#endif diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/l64021.h linux.19rc3-ac4/drivers/media/video/margi/l64021.h --- linux.19rc3/drivers/media/video/margi/l64021.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/l64021.h 2002-07-29 17:29:12.000000000 +0100 @@ -0,0 +1,108 @@ +/* + l64021.h + + Copyright (C) Christian Wolff for convergence integrated media. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _L64021_H_ +#define _L64021_H_ + +#include "margi.h" +#include "l64014.h" +// L64021 DRAM definitions + +#define DRAMMaxSize 0x00200000 // 2 MWords of DRAM + +// definitions for the L64021 + +#define DECODER_OFFSET 0x400 + +#define L21INTR0 0x000 +#define L21INTR1 0x001 +#define L21INTR2 0x002 +#define L21INTR3 0x003 +#define L21INTR4 0x004 + + +// Host interface registers + +// Video Decoder Registers + +// CSS Regs + +// Memory Interface + +// Microcontroller + +// Video Interface + +// Audio Decoder + +// RAM Test + +// SPU Decoder + + + + + //////////////////////////////////////////////////// + // // + // Access to the L64021 registers (0x400-0x7FF) // + // // +//////////////////////////////////////////////////// + +#define DecoderWriteByte(card,where,what) WriteByte(card,where,what) +#define DecoderReadByte(card,where) ReadByte(card,where) +#define DecoderMaskByte(card,where,mask,bits) MaskByte(card,where,mask,bits) +#define DecoderSetByte(card,addr,bits) DecoderWriteByte(card,addr,DecoderReadByte(card,addr)|(bits)) +#define DecoderDelByte(card,addr,mask) DecoderWriteByte(card,addr,DecoderReadByte(card,addr)&~(mask)) + +#define DecoderReadWord(card,addr) ((u16)DecoderReadByte(card,addr)|\ + ((u16)DecoderReadByte(card,(addr)+1)<<8)) + +#define DecoderWriteWord(card,addr,data) {\ + DecoderWriteByte(card,addr,(data) & 0xFF);\ + DecoderWriteByte(card,(addr)+1,((data)>>8) & 0xFF);} + + +#define DecoderReadMWord(card, addr)(\ + (u32)DecoderReadByte(card,addr)|\ + ((u32)DecoderReadByte(card,(addr)+1)<<8)|\ + ((u32)DecoderReadByte(card,(addr)+2)<<16)) + +#define DecoderWriteMWord(card,addr,data) {\ + DecoderWriteByte(card,addr,(data) & 0xFF);\ + DecoderWriteByte(card,(addr)+1,((data)>>8) & 0xFF);\ + DecoderWriteByte(card,(addr)+2,((data)>>16) & 0xFF);} + +#define DecoderReadDWord(card,addr) (\ + (u32)DecoderReadByte(card,addr)|\ + ((u32)DecoderReadByte(card,(addr)+1)<<8)|\ + ((u32)DecoderReadByte(card,(addr)+2)<<16)|\ + ((u32)DecoderReadByte(card,(addr)+3)<<24)) + +#define DecoderWriteDWord(card,addr,data) {\ + DecoderWriteByte(card,addr,(data) & 0xFF);\ + DecoderWriteByte(card,(addr)+1,((data)>>8) & 0xFF);\ + DecoderWriteByte(card,(addr)+2,((data)>>16) & 0xFF);\ + DecoderWriteByte(card,(addr)+3,((data)>>24) & 0xFF);} + + +void l64020Reset(struct cvdv_cards *card); + + +#endif // _L64021_H_ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/makedev.napi linux.19rc3-ac4/drivers/media/video/margi/makedev.napi --- linux.19rc3/drivers/media/video/margi/makedev.napi 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/makedev.napi 2002-07-29 13:58:42.000000000 +0100 @@ -0,0 +1,28 @@ +mkdir /dev/ost +chmod 755 /dev/ost +mknod -m 0666 /dev/ost/video0 c 250 0 +mknod -m 0666 /dev/ost/audio0 c 250 1 +mknod -m 0666 /dev/ost/sec0 c 250 2 +mknod -m 0666 /dev/ost/qpskfe0 c 250 3 +mknod -m 0666 /dev/ost/qamfe0 c 250 7 +mknod -m 0666 /dev/ost/demux0 c 250 4 +mknod -m 0666 /dev/ost/dvr0 c 250 5 +mknod -m 0666 /dev/ost/ca0 c 250 6 + +mknod -m 0666 /dev/ost/video1 c 250 64 +mknod -m 0666 /dev/ost/audio1 c 250 65 +mknod -m 0666 /dev/ost/sec1 c 250 66 +mknod -m 0666 /dev/ost/qpskfe1 c 250 67 +mknod -m 0666 /dev/ost/qamfe1 c 250 71 +mknod -m 0666 /dev/ost/demux1 c 250 68 +mknod -m 0666 /dev/ost/dvr1 c 250 69 +mknod -m 0666 /dev/ost/ca1 c 250 70 + +cd /dev/ost +ln -sf ca0 ca +ln -sf video0 video +ln -sf sec0 sec +ln -sf audio0 audio +ln -sf qpskfe0 qpskfe +ln -sf demux0 demux +ln -sf dvr0 dvr diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/Makefile linux.19rc3-ac4/drivers/media/video/margi/Makefile --- linux.19rc3/drivers/media/video/margi/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/Makefile 2002-07-29 13:58:41.000000000 +0100 @@ -0,0 +1,33 @@ +# +# Makefile for the Margi DVD-to-Go 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 := margilib.o + +CFLAGS_margi_cs.o = -DUSE_OSD -DNOINT -DDVB -DUSE_ZV + +obj-y := +obj-m := +obj-n := +obj- := + +list-multi := margi_cs.o + +margi_cs-objs := margi.o cardbase.o i2c.o dram.o osd.o audio.o \ + video.o streams.o decoder.o spu.o crc.o ringbuffy.o \ + dvb_filter.o cvdv.o + +export-objs := dvbdev.o + +obj-m += margi_cs.o dvbdev.o dmxdev.o dvb_demux.o + +include $(TOPDIR)/Rules.make + +margi_cs.o: $(margi_cs-objs) + $(LD) $(LD_RFLAG) -r -o $@ $(margi_cs-objs) + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/margi linux.19rc3-ac4/drivers/media/video/margi/margi --- linux.19rc3/drivers/media/video/margi/margi 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/margi 2002-07-29 13:58:42.000000000 +0100 @@ -0,0 +1,5 @@ +#!/bin/sh +# +# + +exit 0 diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/margi.c linux.19rc3-ac4/drivers/media/video/margi/margi.c --- linux.19rc3/drivers/media/video/margi/margi.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/margi.c 2002-07-29 13:58:42.000000000 +0100 @@ -0,0 +1,1493 @@ +/* + margi.c + + Copyright (C) Marcus Metzler for convergence integrated media. + + 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 "margi.h" + +#include +#include +#include +#include +#include +#include +#include + + + +#include "l64014.h" +#include "l64021.h" +#include "i2c.h" +#include "decoder.h" +#include "dram.h" +#include "video.h" +#include "cvdv.h" + + +static char *version = "margi_cs.c 0.6 02/04/2000 (Marcus Metzler)"; + +//#define USE_BH 1 +#ifdef USE_BH +#define MARGI_BH 31 +// shouldn't be a number, but then MARGI_BH must be entered into interrupt.h +#endif + +MODULE_AUTHOR(AUTHOR); +MODULE_DESCRIPTION(MEDDEVNAME " Driver V." DVERSION); +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif + +#define MAX_DEV 4 +#define DEVICE_NR(minor) ((minor)>>4) + +/*====================================================================*/ + +/* Parameters that can be set with 'insmod' */ +static int svhs = 1; +MODULE_PARM(svhs,"i"); +static int composite = 1; +MODULE_PARM(composite,"i"); +static int use_zv = 1; +MODULE_PARM(use_zv,"i"); + +/* Release IO ports after configuration? */ +static int free_ports = 0; + +/* The old way: bit map of interrupts to choose from */ +/* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, and 3 */ +static u_int irq_mask = 0xdeb8; +/* Newer, simpler way of listing specific interrupts */ +static int irq_list[4] = { -1 }; + +MODULE_PARM(free_ports, "i"); +MODULE_PARM(irq_mask, "i"); +MODULE_PARM(irq_list, "1-4i"); + +extern unsigned int major_device_number; +extern struct file_operations cvdv_fileops; + +typedef struct margi_info_t { + dev_link_t link; + dev_node_t node; + struct cvdv_cards card; + int stop; +} margi_info_t; + + + +/* + The event() function is this driver's Card Services event handler. + It will be called by Card Services when an appropriate card status + event is received. The config() and release() entry points are + used to configure or release a socket, in response to card + insertion and ejection events. They are invoked from the margi + event handler. +*/ + +static void margi_config(dev_link_t * link); +static void margi_release(u_long arg); +static int margi_event(event_t event, int priority, + event_callback_args_t * args); +/* + The attach() and detach() entry points are used to create and destroy + "instances" of the driver, where each instance represents everything + needed to manage one actual PCMCIA card. +*/ + +static dev_link_t *margi_attach(void); +static void margi_detach(dev_link_t *); +static u_char read_lsi_status(struct cvdv_cards *card); + +/* + You'll also need to prototype all the functions that will actually + be used to talk to your device. See 'memory_cs' for a good example + of a fully self-sufficient driver; the other drivers rely more or + less on other parts of the kernel. +*/ + +/* + The dev_info variable is the "key" that is used to match up this + device driver with appropriate cards, through the card configuration + database. +*/ + +static dev_link_t *dev_table[MAX_DEV] = { NULL, /* ... */ }; + +static dev_info_t dev_info = "margi_cs"; + +/* + A linked list of "instances" of the margi device. Each actual + PCMCIA card corresponds to one device instance, and is described + by one dev_link_t structure (defined in ds.h). + + You may not want to use a linked list for this -- for example, the + memory card driver uses an array of dev_link_t pointers, where minor + device numbers are used to derive the corresponding array index. +*/ + +static dev_link_t *dev_list = NULL; + +/* + A dev_link_t structure has fields for most things that are needed + to keep track of a socket, but there will usually be some device + specific information that also needs to be kept track of. The + 'priv' pointer in a dev_link_t structure can be used to point to + a device-specific private data structure, like this. + + To simplify the data structure handling, we actually include the + dev_link_t structure in the device's private data structure. + + A driver needs to provide a dev_node_t structure for each device + on a card. In some cases, there is only one device per card (for + example, ethernet cards, modems). In other cases, there may be + many actual or logical devices (SCSI adapters, memory cards with + multiple partitions). The dev_node_t structures need to be kept + in a linked list starting at the 'dev' field of a dev_link_t + structure. We allocate them in the card's private data structure, + because they generally shouldn't be allocated dynamically. + + In this case, we also provide a flag to indicate if a device is + "stopped" due to a power management event, or card ejection. The + device IO routines can use a flag like this to throttle IO to a + card that is not ready to accept it. + + The bus_operations pointer is used on platforms for which we need + to use special socket-specific versions of normal IO primitives + (inb, outb, readb, writeb, etc) for card IO. +*/ + +void DACSetFrequency(struct cvdv_cards *card, int khz, int multiple) { + uint8_t b = read_indexed_register(card, IIO_OSC_AUD); + + b &= 0xf8; + + switch (khz){ + case 32: + b |= 0x04; + break; + case 48: + b |= 0x00; + break; + case 44: + b |= 0x01; + break; + case 96: + b |= 0x02; + break; + default: + b |= 0x00; + break; + } + write_indexed_register(card, IIO_OSC_AUD, b); + +} + +int MargiFreeBuffers(struct cvdv_cards *card) +{ + MDEBUG(1, ": -- MargiFreeBuffers\n"); + + ring_destroy(&(card->rbufB)); + card->use_ringB = 0; + ring_destroy(&(card->rbufA)); + card->use_ringA = 0; + + return 0; +} + + +int MargiSetBuffers(struct cvdv_cards *card, uint32_t size, int isB) +{ + int err = 0; + + MDEBUG(0, ": -- MargiSetBuffers(%d) %d\n", + size, isB); + + if (isB){ + err = ring_init(&(card->rbufB),size); + if (!err) card->use_ringB = 1; + } else { + err = ring_init(&(card->rbufA),size); + if (!err) card->use_ringA = 1; + } + + MDEBUG(0,"set buffers: %d use_ringA: %d use_ringB: %d\n",err, +card->use_ringA,card->use_ringB); + return err; +} + + +int MargiFlush (struct cvdv_cards *card) +{ + int co = 0; + int i; + for (i=0;i<100;i++){ + MargiPushA(card, 32, FlushPacket); + MargiPushB(card, 32, FlushPacket); + } + while ( (ring_write_rest(&(card->rbufA))|| ring_write_rest(&(card->rbufB))) && co<100) + co++; + VideoSetBackground(card, 1, 0, 0, 0); // black + + if (card->use_ringA) ring_flush(&(card->rbufA)); + if (card->use_ringB) ring_flush(&(card->rbufB)); + card->DMAABusy = 0; + card->DMABBusy = 0; + + + DecoderStopChannel(card); + DecoderStreamReset(card); + DecoderSetupReset(card); + card->channelrun = 0; + + MDEBUG(1, ": Margi Flush \n"); + return 0; +} + + +int MargiPushA(struct cvdv_cards *card, int count, const char *data) +{ + int fill; + + fill = ring_read_rest(&(card->rbufA)); + + if (!card->use_ringA) + return 0; + if ((count>fill || fill > 3*card->rbufA.size/4) + && !card->channelrun){ + DecoderStartChannel(card); + card->DMAABusy = 1; + } + + count = ring_write(&(card->rbufA),data,count); + + return count; +} + +int MargiPushB(struct cvdv_cards *card, int count, const char *data) +{ + int fill; + + fill = ring_read_rest(&(card->rbufB)); + + if (!card->use_ringB) + return 0; + if ((count>fill || fill > 3*card->rbufB.size/4) + && !card->channelrun){ + DecoderStartChannel(card); + card->DMABBusy = 1; + } + + count = ring_write(&(card->rbufB),data,count); + + return count; +} + +int DecoderStartChannel(struct cvdv_cards *card) +{ + DecoderMaskByte(card, 0x007, 0xC3, 0xC3); // channel start + +#ifdef BYPASS + DecoderMaskByte(card,0x005,0x0F,0x08); +#else + DecoderMaskByte(card,0x005,0x0F,0x01); +#endif + card->channelrun = 1; + return 0; +} + +int DecoderStopChannel(struct cvdv_cards *card) +{ + DecoderMaskByte(card, 0x007, 0xC3, 0xC2); // channel reset + DecoderSetByte(card, 0x005, 0x04); // channel pause + card->channelrun = 0; + return 0; +} + +uint32_t DecoderGetAudioBufferSpace(struct cvdv_cards *card) +{ + + uint32_t MaxSize, Size; + + MaxSize = card->AudioESSize; + Size = DecoderGetAudioESLevel(card); + + if (Size>MaxSize) + return 0; + return (MaxSize - Size); + +} + +uint32_t DecoderGetVideoBufferSpace(struct cvdv_cards *card) +{ + + uint32_t MaxSize, Size; + + MaxSize = card->VideoESSize; + Size = DecoderGetVideoESLevel(card); + + if (Size>MaxSize) + return 0; + return (MaxSize - Size); + +} + +uint32_t DecoderGetBufferSpace(struct cvdv_cards *card) +{ + uint32_t audio,video; + + audio = DecoderGetAudioBufferSpace(card); + video = DecoderGetVideoBufferSpace(card); + + if (audio > 2048) audio -= 2048; + if (video > 2048) video -= 2048; + + if (audio < video) return audio; + return video; +} + + + +static int ringDMA (struct cvdv_cards *card){ + + uint32_t size = 0; + u_char stat; + dev_link_t *link = &(((margi_info_t *) card->margi)->link); + uint32_t acount=0; + uint32_t vcount=0; + uint8_t data; + ringbuffy *buffy; + int stype; + wait_queue_head_t *wq; + stat = read_lsi_status(card); + + + stype = card->setup.streamtype; + + if (stat & LSI_ARQ) { + stat = read_lsi_status(card); + } + + if (stat & LSI_READY){ + data = read_indexed_register(card, IIO_LSI_CONTROL); + data |= RR; + write_indexed_register(card, IIO_LSI_CONTROL, data); + return 0; + } + + if ((stat & LSI_ARQ) == 0) { + switch(stype){ + case stream_PES: + case stream_ES: + data = read_indexed_register(card, IIO_LSI_CONTROL); + data &= ~DSVC; + write_indexed_register(card, IIO_LSI_CONTROL, data); + buffy = &card->rbufB; + wq = &(card->wqB); + acount = ring_read_rest(buffy); + size = DecoderGetAudioBufferSpace(card); + if (size > 2048) size -= 2048; + break; + default: + buffy = &card->rbufA; + wq = &(card->wqA); + acount = ring_read_rest(buffy); + size = DecoderGetBufferSpace(card); + break; + } + if (acount > size) acount = size & 0xfffffffc; + if (acount>=2048) acount &=0xfffff800; + acount &=0xfffffffc; + + if (acount > size) acount = size & 0xfffffffc; + if (acount) { + ring_read_direct(buffy, + link->io.BasePort1+DIO_LSI_STATUS, + acount); + } else { + wake_up_interruptible(wq); + acount = 0; + } + } else { + acount = 0; + } + + if ((stat & LSI_VRQ) == 0 && + (stype == stream_PES || stype == stream_ES)) { + data = read_indexed_register(card, IIO_LSI_CONTROL); + data |= DSVC; + write_indexed_register(card, IIO_LSI_CONTROL, data); + buffy = &card->rbufA; + wq = &(card->wqA); + vcount = ring_read_rest(buffy); + + size = DecoderGetVideoBufferSpace(card); + if (size > 2048) size -= 2048; + if (vcount > size) vcount = size & 0xfffffffc; + if (vcount>=2048) vcount &=0xfffff800; + vcount &=0xfffffffc; + + if (vcount > size) vcount = size & 0xfffffffc; + if (vcount) { + ring_read_direct(buffy, + link->io.BasePort1+DIO_LSI_STATUS, + vcount); + } else { + wake_up_interruptible(wq); + vcount = 0; + } + } else { + vcount = 0; + } + + return vcount+acount; +} + + +u_char read_indexed_register(struct cvdv_cards * card, int addr) +{ + dev_link_t *link = &(((margi_info_t *) card->margi)->link); + u_char data; +#ifdef NOINT + spin_lock(&card->timelock); +#endif + outb(addr, link->io.BasePort1 + DIO_CONTROL_INDEX); + data = (inb(link->io.BasePort1 + DIO_CONTROL_DATA)); +#ifdef NOINT + spin_unlock(&card->timelock); +#endif + return data; +} + + +void write_indexed_register(struct cvdv_cards *card, int addr, u_char data) +{ + dev_link_t *link = &(((margi_info_t *) card->margi)->link); +#ifdef NOINT + spin_lock(&card->timelock); +#endif + outb(addr, link->io.BasePort1 + DIO_CONTROL_INDEX); + outb(data, link->io.BasePort1 + DIO_CONTROL_DATA); + +#ifdef NOINT + spin_unlock(&card->timelock); +#endif +} + +void WriteByte(struct cvdv_cards *card, int addr, u_char data) +{ + dev_link_t *link = &(((margi_info_t *) card->margi)->link); + +#ifdef NOINT + spin_lock(&card->timelock); +#endif + outb((u_char) (addr & 255), + link->io.BasePort1 + DIO_LSI_INDEX_LOW); + outb(((addr & 256) ? 1 : 0), + link->io.BasePort1 + DIO_LSI_INDEX_HIGH); + outb(data, link->io.BasePort1 + DIO_LSI_DATA); +#ifdef NOINT + spin_unlock(&card->timelock); +#endif +} + +u_char ReadByte(struct cvdv_cards *card, int addr) +{ + dev_link_t *link = &(((margi_info_t *) card->margi)->link); + u_char data; + +#ifdef NOINT + spin_lock(&card->timelock); +#endif + outb((u_char) (addr & 255), + link->io.BasePort1 + DIO_LSI_INDEX_LOW); + outb(((addr & 256) ? 1 : 0), + link->io.BasePort1 + DIO_LSI_INDEX_HIGH); + data = inb(link->io.BasePort1 + DIO_LSI_DATA); +#ifdef NOINT + spin_unlock(&card->timelock); +#endif + return data; +} + +void MaskByte(struct cvdv_cards *card, int addr, u_char mask, u_char bits) +{ + WriteByte(card, addr, (ReadByte(card, addr) & ~(mask)) | (bits)); +} + + + +#define MAXWRITE CHANNELBUFFERSIZE/2 +#define MAX_COUNT 400 + +#ifdef USE_BH +struct cvdv_cards *bh_card; + +static void do_margi_bh(void) +{ + struct cvdv_cards *card = bh_card; +#else + +static void do_margi(struct cvdv_cards *card) +{ + +#endif + int countA; + int try; + int stype = card->setup.streamtype; + + countA = 0; + + card->currentType = 0; + for ( try = 0; try < MAX_COUNT ;try++) + if (countA < MAXWRITE){ + int count = 0; + switch (stype){ + case stream_PES: + case stream_ES: + count = ringDMA(card); + countA += count; + if (!count) + try=MAX_COUNT; + break; + case stream_PS: + case stream_DVD: + count = ringDMA(card); + countA += count; + if (!count) + try=MAX_COUNT; + break; + } + } else break; + +} + + + + +void L64014Intr_function(struct cvdv_cards *card) +{ + uint8_t control,mask,stat; + int try; + + + control= read_indexed_register(card, IIO_IRQ_CONTROL); + if (control & IRQ_EN){ + mask = 0; + if ( control & DEC_EN ) mask |= DEC_INT; + if ( control & VSYNC_EN ) mask |= VSYNC_INT; + stat = read_indexed_register(card, IIO_IRQ_STATUS); + try = 0; + while ( (try++ < 100) && (stat & mask) ){ + + if (stat & VSYNC_INT) { + + write_indexed_register(card,IIO_IRQ_CONTROL, + control & (~VSYNC_EN)); + write_indexed_register(card,IIO_IRQ_CONTROL, + control); + + + if (card->DMAABusy || card->DMABBusy){ + +#ifdef USE_BH + bh_card = card; + mark_bh(MARGI_BH); +#else + do_margi(card); +#endif + if(card->use_ringA || card->use_ringB){ + L64021Intr(card); + } + } + } + + if (stat & DEC_INT) { + write_indexed_register(card,IIO_IRQ_CONTROL, + control & (~DEC_EN)); + write_indexed_register(card,IIO_IRQ_CONTROL, + control); + + if(card->use_ringA || card->use_ringB){ + L64021Intr(card); + } + } + + stat = read_indexed_register(card, IIO_IRQ_STATUS); + } + } + +} + + +#ifdef NOINT +void Timerfunction(unsigned long data) +{ + struct cvdv_cards *card = (struct cvdv_cards *) data; + + L64014Intr_function(card); + + card->timer.function = Timerfunction; + card->timer.data=(unsigned long) card; + card->timer.expires=jiffies+10; + if ( card->open) + add_timer(&card->timer); + +} +#endif + + +void L64014Intr(int irq, void *dev_id, struct pt_regs *regs) +{ + margi_info_t *margi = dev_id; + struct cvdv_cards *card = &(margi->card); + u_char dio_index, lsi_index_low, lsi_index_high; + +#ifdef NOINT + spin_lock(&card->timelock); +#endif + //save registers + dio_index = inb(margi->link.io.BasePort1 + DIO_CONTROL_INDEX); + lsi_index_low = inb(margi->link.io.BasePort1 + DIO_LSI_INDEX_LOW); + lsi_index_high = inb(margi->link.io.BasePort1 + DIO_LSI_INDEX_HIGH); + + + L64014Intr_function(card); + + //load registers + outb(dio_index, margi->link.io.BasePort1 + DIO_CONTROL_INDEX); + outb(lsi_index_low, margi->link.io.BasePort1 + DIO_LSI_INDEX_LOW); + outb(lsi_index_high,margi->link.io.BasePort1 + DIO_LSI_INDEX_HIGH); +#ifdef NOINT + spin_unlock(&card->timelock); +#endif +} + +int L64014RemoveIntr(struct cvdv_cards *card) +{ + MDEBUG(1, ": -- L64014RemoveIntr\n"); + // Disable the IRQ's + write_indexed_register(card, IIO_IRQ_CONTROL, 0x00); + if (!card->IntInstalled) + return 1; + L64021RemoveIntr(card); + return 0; +} + +void l64020Reset(struct cvdv_cards *card){ + uint8_t data; + + + data = read_indexed_register(card, IIO_LSI_CONTROL); + data &= ~(RR | DR); + write_indexed_register(card, IIO_LSI_CONTROL, data); + mdelay(100); + data = read_indexed_register(card, IIO_LSI_CONTROL); + data |= DR; + write_indexed_register(card, IIO_LSI_CONTROL, data); + + data = read_indexed_register(card,IIO_GPIO_PINS); + data &= ~0x01; + write_indexed_register(card,IIO_GPIO_PINS,data); + data |= 0x01; + write_indexed_register(card,IIO_GPIO_PINS,data); + + //write_indexed_register(card, IIO_LSI_CONTROL, DR); + + data = read_indexed_register(card, IIO_LSI_CONTROL); + data &= ~DSVC; + write_indexed_register(card, IIO_LSI_CONTROL, data); + +} + +void ZV_init(struct cvdv_cards *card) +{ + uint32_t delay, activel; + uint8_t reg; + delay = 235; + activel = delay + 1448; + + // init delay and active lines + write_indexed_register(card, IIO_VIDEO_HOR_DELAY, + (uint8_t)(delay & 0x00FF)); + write_indexed_register(card, IIO_VIDEO_HOR_ACTIVE, + (uint8_t)(activel & 0x00FF)); + reg = ((uint8_t)((activel >> 4) & 0x0070))|((uint8_t)((delay >> 8) & 0x0007)); + write_indexed_register(card, IIO_VIDEO_HOR_HIGH, reg); + + //init video + reg = read_indexed_register(card, IIO_VIDEO_CONTROL0); + reg |= (ZVCLK13 | ZV16BIT | ZVCLKINV); + write_indexed_register(card, IIO_VIDEO_CONTROL0, reg); + reg = read_indexed_register(card, IIO_VIDEO_CONTROL1); + reg |= (ZV_OVERRIDE | ZV_ENABLE); + write_indexed_register(card, IIO_VIDEO_CONTROL1, reg); +} + +void set_svhs(struct cvdv_cards *card, int onoff) +{ + uint8_t val; + + val = I2CRead(card, card->i2c_addr, CS_DAC)&0x0f; + MDEBUG(1, ": --svhs val 0x%02x\n",val); + + if (onoff){ + if (!card->svhs){ + I2CWrite(card, card->i2c_addr, CS_DAC, val|0x03); + card->svhs = 1; + } + } else { + if (!card->svhs){ + I2CWrite(card, card->i2c_addr, CS_DAC, val|0x30); + card->svhs = 1; + } + } + +} + +void set_composite(struct cvdv_cards *card, int onoff) +{ + uint8_t val; + + val = I2CRead(card, card->i2c_addr, CS_DAC)&0x0f; + MDEBUG(1, ": --composite val 0x%02x\n",val); + + + if (onoff){ + if (!card->composite){ + I2CWrite(card, card->i2c_addr, CS_DAC, val|0x84); + card->composite = 1; + } + } else { + if (!card->svhs){ + I2CWrite(card, card->i2c_addr, CS_DAC, val|0xE0); + card->composite = 1; + } + } + +} + + +int L64014Init(struct cvdv_cards *card) +{ + uint16_t testram[16]; + int i, err; + + MDEBUG(1, ": -- L64014Init\n"); + card->videomode = VIDEO_MODE; + + /* Reset 64020 */ + write_indexed_register(card, IIO_GPIO_CONTROL, 0x01); + l64020Reset(card); + /* init GPIO */ + write_indexed_register(card, IIO_GPIO_CONTROL, 0x01); + write_indexed_register(card, IIO_GPIO_PINS, 0xff); + + /* Set to PAL */ + write_indexed_register(card, IIO_VIDEO_CONTROL0, 0); + write_indexed_register(card, IIO_VIDEO_CONTROL1, VMS_PAL); + + /* Set Audio freq */ + write_indexed_register(card, IIO_OSC_AUD, 0x12); + + write_indexed_register(card, CSS_COMMAND, 0x01); + + + MDEBUG(0, "CSID: %02x\n", I2CRead(card, 0, 0x3d)); + card->i2c_addr = I2CRead(card, 0, 0x0f); + MDEBUG(0, "I2CADDR: %02x\n", card->i2c_addr); + + I2CWrite(card, card->i2c_addr, CS_CONTROL0, 0x4a); + I2CWrite(card, card->i2c_addr, CS_CONTROL1, 0x04); + I2CWrite(card, card->i2c_addr, CS_SC_AMP, 0x15); + I2CWrite(card, card->i2c_addr, CS_SC_SYNTH0, 0x96); + I2CWrite(card, card->i2c_addr, CS_SC_SYNTH1, 0x15); + I2CWrite(card, card->i2c_addr, CS_SC_SYNTH2, 0x13); + I2CWrite(card, card->i2c_addr, CS_SC_SYNTH3, 0x54); + +// I2CWrite(card, card->i2c_addr, CS_DAC, 0x87); + if (svhs) set_svhs(card, 1); + if (composite) set_composite(card, 1); + I2CWrite(card, card->i2c_addr, CS_BKG_COL, 0x03); + + MDEBUG(0,"Decoder Status: %d\n", read_lsi_status(card)); + MDEBUG(0,"lsi stat %d\n", DecoderReadByte(card, 0x005)); + + if (use_zv) ZV_init(card); + L64021Init(card); + + // Find out how much DRAM we have + card->DRAMSize = 0x00100000; // maximum size + do { + MDEBUG(0, + ": Probing DRAM Size: 0x%08X (%d kByte) ... ", + card->DRAMSize, card->DRAMSize / 512); + for (i = 0; i < 8; i++) + testram[i] = rnd(0x100) | (rnd(0x100) << 8); + if (DRAMWriteWord(card, 0, 4, &testram[0], 0)) + MDEBUG(0, ": DRAM Write error.\n"); + if (DRAMWriteWord + (card, card->DRAMSize - 4, 4, &testram[4], + 0)) MDEBUG(0, + ": DRAM Write error.\n"); + if (DRAMReadWord(card, 0, 4, &testram[8], 0)) + MDEBUG(0, ": DRAM Read error.\n"); + if (DRAMReadWord + (card, card->DRAMSize - 4, 4, &testram[12], + 0)) MDEBUG(0, ": DRAM Read error.\n"); + err = 0; + for (i = 0; (!err) && (i < 8); i++) + if (testram[i] != testram[i + 8]) + err = i + 1; + if (err) { + MDEBUG(0," failed\n"); + } else { + MDEBUG(0," ok\n"); + } + if (err) + MDEBUG(2,": DRAM compare error at cell %d: 0x%04X %04X %04X %04X->0x%04X %04X %04X %04X / 0x%04X %04X %04X %04X->0x%04X %04X %04X %04X\n", + err, testram[0], testram[1], testram[2], + testram[3], testram[8], testram[9], + testram[10], testram[11], testram[4], + testram[5], testram[6], testram[7], + testram[12], testram[13], testram[14], + testram[15]); + if (err) + card->DRAMSize >>= 1; + } while (err && (card->DRAMSize >= 0x00100000)); + printk(KERN_INFO LOGNAME ": DRAM Size: 0x%08X (%d kByte)\n", + card->DRAMSize, card->DRAMSize / 512); + if (card->DRAMSize < 0x00100000) { // minimum size + printk(KERN_INFO LOGNAME + ": DRAM ERROR: Not enough memory on card!\n"); + return 1; + } + return 0; +} + + +void CardDeInit(struct cvdv_cards *card) +{ + CloseCard(card); + MargiFlush(card); + MargiFreeBuffers(card); + + L64014RemoveIntr(card); + card_init(card, 0); +} + + +static u_char read_lsi_status(struct cvdv_cards *card) +{ + margi_info_t *margi = (margi_info_t *) card->margi; + return (inb(margi->link.io.BasePort1 + DIO_LSI_STATUS) & 15); + +} + +/*====================================================================*/ + +static void cs_error(client_handle_t handle, int func, int ret) +{ + error_info_t err = { func, ret }; + CardServices(ReportError, handle, &err); +} + +/*====================================================================== + + margi_attach() creates an "instance" of the driver, allocating + local data structures for one device. The device is registered + with Card Services. + + The dev_link structure is initialized, but we don't actually + configure the card at this point -- we wait until we receive a + card insertion event. + +======================================================================*/ + +static dev_link_t *margi_attach(void) +{ + margi_info_t *local; + dev_link_t *link; + client_reg_t client_reg; + int ret, i; + + MDEBUG(0, "margi_attach()\n"); + + for (i = 0; i < MAX_DEV; i++) + if (dev_table[i] == NULL) + break; + if (i == MAX_DEV) { + printk(KERN_NOTICE "margi_cs: no devices available\n"); + return NULL; + } + + /* Allocate space for private device-specific data */ + local = kmalloc(sizeof(margi_info_t), GFP_KERNEL); + if (!local) + return NULL; + memset(local, 0, sizeof(margi_info_t)); + link = &local->link; + link->priv = local; + local->card.margi = (void *) local; + dev_table[i] = link; + + /* Initialize the dev_link_t structure */ + link->release.function = &margi_release; + link->release.data = (u_long) link; + + /* Interrupt setup */ + link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID; + if (irq_list[0] == -1) + link->irq.IRQInfo2 = irq_mask; + else + for (i = 0; i < 4; i++) + link->irq.IRQInfo2 |= 1 << irq_list[i]; + link->irq.Handler = NULL; + + /* + General socket configuration defaults can go here. In this + client, we assume very little, and rely on the CIS for almost + everything. In most clients, many details (i.e., number, sizes, + and attributes of IO windows) are fixed by the nature of the + device, and can be hard-wired here. + */ + link->conf.Attributes = 0; + link->conf.Vcc = 50; + + if(use_zv==0) + link->conf.IntType = INT_MEMORY_AND_IO; + else + link->conf.IntType = INT_ZOOMED_VIDEO; + + /* 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 = &margi_event; + client_reg.Version = 0x0210; + client_reg.event_callback_args.client_data = link; + ret = CardServices(RegisterClient, &link->handle, &client_reg); + if (ret != CS_SUCCESS) { + cs_error(link->handle, RegisterClient, ret); + margi_detach(link); + return NULL; + } + + return link; +} /* margi_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 margi_detach(dev_link_t * link) +{ + dev_link_t **linkp; + + int nd; + + MDEBUG(0, "margi_detach(0x%p)\n", link); + + for (nd = 0; nd < MAX_DEV; nd++) + if (dev_table[nd] == link) + break; + if (nd == MAX_DEV) + return; + + /* Locate device structure */ + for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) + if (*linkp == link) + break; + if (*linkp == NULL) + return; + + /* + If the device is currently configured and active, we won't + actually delete it yet. Instead, it is marked so that when + the release() function is called, that will trigger a proper + detach(). + */ + if (link->state & DEV_CONFIG) { + MDEBUG(2, "margi_cs: detach postponed, '%s' " + "still locked\n", link->dev->dev_name); + link->state |= DEV_STALE_LINK; + return; + } + + /* Break the link with Card Services */ + if (link->handle) + CardServices(DeregisterClient, link->handle); + + /* Unlink device structure, and free it */ + *linkp = link->next; + /* This points to the parent struct cvdv_cards struct */ + dev_table[nd] = NULL; + + kfree(link->priv); + +} /* margi_detach */ + +/*====================================================================== + + margi_config() is scheduled to run after a CARD_INSERTION event + is received, to configure the PCMCIA socket, and to make the + device available to the system. + +======================================================================*/ + +#define CS_CHECK(fn, args...) \ +while ((last_ret=CardServices(last_fn=(fn),args))!=0) goto cs_failed + +#define CFG_CHECK(fn, args...) \ +if (CardServices(fn, args) != 0) goto next_entry + +static void margi_config(dev_link_t * link) +{ + client_handle_t handle = link->handle; + margi_info_t *dev = link->priv; + struct cvdv_cards *card = &(dev->card); + tuple_t tuple; + cisparse_t parse; + int last_fn, last_ret, i; + u_char buf[64]; + config_info_t conf; + win_req_t req; + memreq_t map; + int minor = 0; + + MDEBUG(0, "margi_config(0x%p)\n", link); + + /* + This reads the card's CONFIG tuple to find its configuration + registers. + */ + tuple.DesiredTuple = CISTPL_CONFIG; + tuple.Attributes = 0; + tuple.TupleData = buf; + tuple.TupleDataMax = sizeof(buf); + tuple.TupleOffset = 0; + CS_CHECK(GetFirstTuple, handle, &tuple); + CS_CHECK(GetTupleData, handle, &tuple); + CS_CHECK(ParseTuple, handle, &tuple, &parse); + link->conf.ConfigBase = parse.config.base; + link->conf.Present = parse.config.rmask[0]; + + /* Configure card */ + link->state |= DEV_CONFIG; + + /* Look up the current Vcc */ + CS_CHECK(GetConfigurationInfo, handle, &conf); + link->conf.Vcc = conf.Vcc; + + /* + In this loop, we scan the CIS for configuration table entries, + each of which describes a valid card configuration, including + voltage, IO window, memory window, and interrupt settings. + + We make no assumptions about the card to be configured: we use + just the information available in the CIS. In an ideal world, + this would work for any PCMCIA card, but it requires a complete + and accurate CIS. In practice, a driver usually "knows" most of + these things without consulting the CIS, and most client drivers + will only use the CIS to fill in implementation-defined details. + */ + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + CS_CHECK(GetFirstTuple, handle, &tuple); + while (1) { + cistpl_cftable_entry_t dflt = { 0 }; + cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); + CFG_CHECK(GetTupleData, handle, &tuple); + CFG_CHECK(ParseTuple, handle, &tuple, &parse); + + if (cfg->flags & CISTPL_CFTABLE_DEFAULT) + dflt = *cfg; + if (cfg->index == 0) + goto next_entry; + link->conf.ConfigIndex = cfg->index; + + /* Does this card need audio output? */ + if (cfg->flags & CISTPL_CFTABLE_AUDIO) { + link->conf.Attributes |= CONF_ENABLE_SPKR; + link->conf.Status = CCSR_AUDIO_ENA; + } + + /* Use power settings for Vcc and Vpp if present */ + /* Note that the CIS values need to be rescaled */ + if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { + if (conf.Vcc != + cfg->vcc.param[CISTPL_POWER_VNOM] / + 10000) goto next_entry; + } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) { + if (conf.Vcc != + dflt.vcc.param[CISTPL_POWER_VNOM] / + 10000) goto next_entry; + } + + if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) + link->conf.Vpp1 = link->conf.Vpp2 = + cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; + else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) + link->conf.Vpp1 = link->conf.Vpp2 = + dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; + + /* + Allocate an interrupt line. Note that this does not assign a + handler to the interrupt, unless the 'Handler' member of the + irq structure is initialized. + */ +#ifndef NOINT + link->irq.Attributes = + IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; + link->irq.Handler = &L64014Intr; + link->irq.Instance = link; + link->conf.Attributes |= CONF_ENABLE_IRQ; +#ifdef USE_BH + init_bh(MARGI_BH, do_margi_bh); +#endif + if (link->conf.Attributes & CONF_ENABLE_IRQ) + CS_CHECK(RequestIRQ, link->handle, &link->irq); +#endif + + /* IO window settings */ + link->io.NumPorts1 = link->io.NumPorts2 = 0; + if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { + cistpl_io_t *io = + (cfg->io.nwin) ? &cfg->io : &dflt.io; + link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; + if (!(io->flags & CISTPL_IO_8BIT)) + link->io.Attributes1 = + IO_DATA_PATH_WIDTH_16; + if (!(io->flags & CISTPL_IO_16BIT)) + link->io.Attributes1 = + IO_DATA_PATH_WIDTH_8; + link->io.IOAddrLines = + io->flags & CISTPL_IO_LINES_MASK; + link->io.BasePort1 = io->win[0].base; + link->io.NumPorts1 = io->win[0].len; + if (io->nwin > 1) { + link->io.Attributes2 = + link->io.Attributes1; + link->io.BasePort2 = io->win[1].base; + link->io.NumPorts2 = io->win[1].len; + } + } + + /* This reserves IO space but doesn't actually enable it */ + CFG_CHECK(RequestIO, link->handle, &link->io); + + /* + Now set up a common memory window, if needed. There is room + in the dev_link_t structure for one memory window handle, + but if the base addresses need to be saved, or if multiple + windows are needed, the info should go in the private data + structure for this device. + + Note that the memory window base is a physical address, and + needs to be mapped to virtual space with ioremap() before it + is used. + */ + if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) { + cistpl_mem_t *mem = + (cfg->mem.nwin) ? &cfg->mem : &dflt.mem; + req.Attributes = + WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM; + req.Attributes |= WIN_ENABLE; + req.Base = mem->win[0].host_addr; + req.Size = mem->win[0].len; + req.AccessSpeed = 0; + link->win = (window_handle_t) link->handle; + CFG_CHECK(RequestWindow, &link->win, &req); + map.Page = 0; + map.CardOffset = mem->win[0].card_addr; + CFG_CHECK(MapMemPage, link->win, &map); + } + /* If we got this far, we're cool! */ + break; + + next_entry: + CS_CHECK(GetNextTuple, handle, &tuple); + } + + /* + This actually configures the PCMCIA socket -- setting up + the I/O windows and the interrupt mapping, and putting the + card and host interface into "Memory and IO" mode. + */ + CS_CHECK(RequestConfiguration, link->handle, &link->conf); + + /* + We can release the IO port allocations here, if some other + driver for the card is going to loaded, and will expect the + ports to be available. + */ + if (free_ports) { + if (link->io.BasePort1) + release_region(link->io.BasePort1, + link->io.NumPorts1); + if (link->io.BasePort2) + release_region(link->io.BasePort2, + link->io.NumPorts2); + } + + /* + At this point, the dev_node_t structure(s) need to be + initialized and arranged in a linked list at link->dev. + */ + + first_card = card; + minor=0; + card->next = NULL; + card_init(card, minor); + if ((i = register_chrdev(CVDV_MAJOR, CVDV_PROCNAME, &cvdv_fileops)) + >= 0) { + major_device_number = ((i) ? i : CVDV_MAJOR); + printk(KERN_INFO LOGNAME + ": Char-device with major number %d installed\n", + major_device_number); + } else { + printk(KERN_ERR LOGNAME + ": ERROR: Failed to install Char-device %d, error %d\n", + CVDV_MAJOR, i); + } + + + sprintf(dev->node.dev_name, "margi"); + dev->node.major = major_device_number; + dev->node.minor = minor; + link->dev = &dev->node; +#ifdef DVB + dvb_register(card); +#endif + /* Finally, report what we've done */ + printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d", + dev->node.dev_name, link->conf.ConfigIndex, + link->conf.Vcc / 10, link->conf.Vcc % 10); + if (link->conf.Vpp1) + printk(", Vpp %d.%d", link->conf.Vpp1 / 10, + link->conf.Vpp1 % 10); + if (link->conf.Attributes & CONF_ENABLE_IRQ) + printk(", irq %d", link->irq.AssignedIRQ); + if (link->io.NumPorts1) + printk(", io 0x%04x-0x%04x", link->io.BasePort1, + link->io.BasePort1 + link->io.NumPorts1 - 1); + if (link->io.NumPorts2) + printk(" & 0x%04x-0x%04x", link->io.BasePort2, + link->io.BasePort2 + link->io.NumPorts2 - 1); + if (link->win) + printk(", mem 0x%06lx-0x%06lx", req.Base, + req.Base + req.Size - 1); + printk("\n"); + + link->state &= ~DEV_CONFIG_PENDING; + if (0xdd == read_indexed_register(card, IIO_ID)) { + printk("L64014 Version %d in mode %d detected\n", + (read_indexed_register(card, IIO_MODE) & 248) >> 3, + read_indexed_register(card, IIO_MODE) & 7); + write_indexed_register(card, IIO_GPIO_CONTROL, 0x07); + + L64014Init(card); + + // default: color bars + VideoSetBackground(card, 1, 0, 0, 0); // black + SetVideoSystem(card); + minorlist[minor] = card; // fast access for the char driver + + + /*enable L64014 IRQ */ + write_indexed_register(card, IIO_IRQ_CONTROL, + IRQ_POL | IRQ_EN | VSYNC_EN); +// write_indexed_register(card, IIO_IRQ_CONTROL, 0x24); + + OSDOpen(card, 50, 50, 150, 150, 2, 1); + OSDTest(card); + } + return; + + cs_failed: + cs_error(link->handle, last_fn, last_ret); + margi_release((u_long) link); + +} /* margi_config */ + +/*====================================================================== + + After a card is removed, margi_release() will unregister the + device, and release the PCMCIA configuration. If the device is + still open, this will be postponed until it is closed. + +======================================================================*/ + +static void margi_release(u_long arg) +{ + dev_link_t *link = (dev_link_t *) arg; + margi_info_t *dev = link->priv; + struct cvdv_cards *card = &(dev->card); + + MDEBUG(0, "margi_release(0x%p)\n", link); + /* + If the device is currently in use, we won't release until it + is actually closed, because until then, we can't be sure that + no one will try to access the device or its data structures. + */ + if (link->open) { + MDEBUG(1, "margi_cs: release postponed, '%s' still open\n", + link->dev->dev_name); + link->state |= DEV_STALE_CONFIG; + return; + } + + /* Unlink the device chain */ + link->dev = NULL; + + /* + In a normal driver, additional code may be needed to release + other kernel data structures associated with this device. + */ + + MDEBUG(1,": Unloading device driver\n"); + if (major_device_number) + unregister_chrdev(major_device_number, CVDV_PROCNAME); + CardDeInit(card); + +#ifndef NOINT +#ifdef USE_BH + remove_bh(MARGI_BH); +#endif + mdelay(100); +#endif + CloseCard(card); +#ifdef DVB + dvb_unregister(card); +#endif + /* Don't bother checking to see if these succeed or not */ + if (link->win) + CardServices(ReleaseWindow, link->win); + CardServices(ReleaseConfiguration, link->handle); + if (link->io.NumPorts1) + CardServices(ReleaseIO, link->handle, &link->io); +#ifndef NOINT + if (link->irq.AssignedIRQ) + CardServices(ReleaseIRQ, link->handle, &link->irq); +#endif + link->state &= ~DEV_CONFIG; + + if (link->state & DEV_STALE_LINK) + margi_detach(link); + +} /* margi_release */ + +/*====================================================================== + + The card status event handler. Mostly, this schedules other + stuff to run after an event is received. + + When a CARD_REMOVAL event is received, we immediately set a + private flag to block future accesses to this device. All the + functions that actually access the device should check this flag + to make sure the card is still present. + +======================================================================*/ + +static int margi_event(event_t event, int priority, + event_callback_args_t * args) +{ + dev_link_t *link = args->client_data; + margi_info_t *dev = link->priv; + + MDEBUG(1, "margi_event(0x%06x)\n", event); + + switch (event) { + case CS_EVENT_CARD_REMOVAL: + link->state &= ~DEV_PRESENT; + if (link->state & DEV_CONFIG) { + ((margi_info_t *) link->priv)->stop = 1; + link->release.expires = jiffies + HZ / 20; + add_timer(&link->release); + } + break; + case CS_EVENT_CARD_INSERTION: + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + dev->card.bus = args->bus; + margi_config(link); + break; + case CS_EVENT_PM_SUSPEND: + link->state |= DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_RESET_PHYSICAL: + /* Mark the device as stopped, to block IO until later */ + dev->stop = 1; + if (link->state & DEV_CONFIG) + CardServices(ReleaseConfiguration, link->handle); + break; + case CS_EVENT_PM_RESUME: + link->state &= ~DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_CARD_RESET: + if (link->state & DEV_CONFIG) + CardServices(RequestConfiguration, link->handle, + &link->conf); + dev->stop = 0; + /* + In a normal driver, additional code may go here to restore + the device state and restart IO. + */ + break; + } + return 0; +} /* margi_event */ + +/*====================================================================*/ + +static int __init init_margi_cs(void) +{ + servinfo_t serv; + MDEBUG(0, "%s\n", version); + CardServices(GetCardServicesInfo, &serv); + if (serv.Revision != CS_RELEASE_CODE) { + printk(KERN_NOTICE "margi_cs: Card Services release " + "does not match!\n"); + return -1; + } + register_pccard_driver(&dev_info, &margi_attach, &margi_detach); + return 0; +} + +static void __exit exit_margi_cs(void) +{ + MDEBUG(0, "margi_cs: unloading\n"); + unregister_pccard_driver(&dev_info); + while (dev_list != NULL) { + if (dev_list->state & DEV_CONFIG) + margi_release((u_long) dev_list); + margi_detach(dev_list); + } +} + +module_init(init_margi_cs); +module_exit(exit_margi_cs); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/margi.conf linux.19rc3-ac4/drivers/media/video/margi/margi.conf --- linux.19rc3/drivers/media/video/margi/margi.conf 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/margi.conf 2002-07-29 13:58:42.000000000 +0100 @@ -0,0 +1,9 @@ +device "margi_cs" + class "margi" module "margi_cs" + +# Margi +card "MARGI-Billionton" +manfid 0x01d8, 0x1000 +bind "margi_cs" + + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/margi_cs.4 linux.19rc3-ac4/drivers/media/video/margi/margi_cs.4 --- linux.19rc3/drivers/media/video/margi/margi_cs.4 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/margi_cs.4 2002-07-29 13:58:42.000000000 +0100 @@ -0,0 +1,34 @@ +.\" Copyright (c) 1997,1998,1999 Koji OKAMURA +.\" +.TH ISCC_CS 4 "1997/09/28" "" +.SH NAME +iscc_cs \- IBM Smart Capture Card device driver +.SH SYNOPSIS +.B insmod iscc_cs.o +.RB [ pc_debug=n ] +.RB [ mem_speed=n ] +.SH DESCRIPTION +.B Iscc_cs +is the low-level Card Services driver for the IBM Smart Capture Card +PCMCIA Video Capture adapter. When this driver is attached to a card, it +allocates the next available Video Capture Card device +.RB ( iscc0 .. iscc# ). +This +device name will be reported in the kernel log file, and passed on to +.BR cardmgr (8). +.SH PARAMETERS +.TP +.B pc_debug=n +Selects the PCMCIA debugging level. This parameter is only available +if the module is compiled with debugging enabled. A non-zero value +enables debugging. +.TP +.B mem_speed=n +Sets the access speed of the shared memory window, in nanoseconds. +The default is 0 (i.e., no extra wait states). Values of up to 1000 +are legal. +.SH AUTHOR +Koji OKAMURA \- Kyushu University + +.SH "SEE ALSO" +cardmgr(8), pcmcia(5). diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/margi_cs.mk linux.19rc3-ac4/drivers/media/video/margi/margi_cs.mk --- linux.19rc3/drivers/media/video/margi/margi_cs.mk 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/margi_cs.mk 2002-07-29 13:58:42.000000000 +0100 @@ -0,0 +1,113 @@ +# +# Makefile for margi_cs +# Marcus Metzler +# + +include ../config.mk + +CC = $(KCC) $(AFLAGS) $(KFLAGS) + +CFLAGS += -g -O2 -Wall -Wstrict-prototypes -pipe -Wall -D__DVB_PACK__ -DUSE_OSD -DNOINT -DDVB -DUSE_ZV + +CPPFLAGS += $(PCDEBUG) -D__KERNEL__ -DMODULE -DMODVERSIONS -I../include \ + -I$(LINUX)/include -I$(LINUX) -Iinclude + +CC_MODULE = $(CC) -c $(CFLAGS) $(CPPFLAGS) + +ETC = $(PREFIX)/etc/pcmcia +MANDIR = $(PREFIX)/usr/man +MX_OBJS = dmxdev.o dvb_demux.o dvbdev.o + +all: margi_cs.o $(MX_OBJS) + +install-modules: $(MODULES) $(MX_OBJS) + mkdir -p $(PREFIX)/$(MODDIR)/pcmcia + cp $(MODULES) $(PREFIX)/$(MODDIR)/pcmcia + su -c "mkdir -p $(MODDIR)/misc; cp -v $(MX_OBJS) $(MX_OBJS) $(MODDIR)/misc" + +install-clients: + for f in $(CLIENTS) ; do \ + [ -r $$f.conf ] && cp $$f.conf $(ETC)/$$f.conf ; \ + cmp -s $$f $(ETC)/$$f && continue ; \ + [ -r $(ETC)/$$f ] && mv $(ETC)/$$f $(ETC)/$$f.O ; \ + cp $$f $(ETC)/$$f ; \ + OPTS=$(ETC)/$$f.opts ; \ + test -r $$OPTS || cp $$f.opts $$OPTS ; \ + done + cp cvdvext.h cvdvtypes.h /usr/include/linux + mkdir -p /usr/include/ost/ + cp include/ost/*.h /usr/include/ost + rm -rf /dev/ost + makedev.napi + depmod -a + +install-man4: $(MAN4) + mkdir -p $(MANDIR)/man4 + cp $(MAN4) $(MANDIR)/man4 + + +MMODULES = margi.o cvdv.o cardbase.o i2c.o dram.o osd.o audio.o video.o streams.o decoder.o spu.o crc.o ringbuffy.o dvb_formats.o + +margi_cs.o: $(MMODULES) + $(LD) -r -o margi_cs.o $(MMODULES) + chmod -x margi_cs.o + + +margi.o: margi.h cardbase.h l64014.h l64021.h i2c.h decoder.h dram.h\ + video.h cvdv.h margi.c + $(CC_MODULE) margi.c + +cvdv.o: cvdv.c cvdv.h cardbase.h cvdvtypes.h l64021.h l64014.h dram.h\ + osd.h audio.h video.h streams.h decoder.h spu.h \ + crc.h + $(CC_MODULE) cvdv.c + +cardbase.o: cardbase.c cardbase.h cvdvtypes.h + $(CC_MODULE) cardbase.c + +i2c.o: i2c.c i2c.h cardbase.h cvdvtypes.h l64014.h + $(CC_MODULE) i2c.c + +dram.o: dram.c dram.h cardbase.h cvdvtypes.h l64021.h l64014.h + $(CC_MODULE) dram.c + +osd.o: osd.c osd.h cardbase.h cvdvtypes.h dram.h l64021.h l64014.h + $(CC_MODULE) osd.c + +audio.o: audio.c audio.h cardbase.h cvdvtypes.h l64021.h l64014.h + $(CC_MODULE) audio.c + +video.o: video.c video.h cardbase.h cvdvtypes.h dram.h l64021.h l64014.h + $(CC_MODULE) video.c + +streams.o: streams.c streams.h cardbase.h cvdvtypes.h dram.h l64021.h l64014.h \ +video.h dram.h audio.h + $(CC_MODULE) streams.c + +decoder.o: decoder.c decoder.h cardbase.h cvdvtypes.h dram.h l64021.h l64014.h \ +video.h dram.h audio.h streams.h i2c.h osd.h dram.h + $(CC_MODULE) decoder.c + +spu.o: spu.c spu.h cardbase.h cvdvtypes.h l64021.h l64014.h + $(CC_MODULE) spu.c + +crc.o: crc.c crc.h + $(CC_MODULE) crc.c + +ringbuffy.o: ringbuffy.h ringbuffy.c + $(CC_MODULE) ringbuffy.c + +dvb_formats.o: dvb_formats.h dvb_formats.c + $(CC_MODULE) dvb_formats.c + +dmxdev.o: dmxdev.h dvb_demux.h + $(CC_MODULE) -include $(LINUX)/include/linux/modversions.h dmxdev.c + +dvb_demux.o: dvb_demux.h dmxdev.h dvbdev.h + $(CC_MODULE) -include $(LINUX)/include/linux/modversions.h dvb_demux.c + +dvbdev.o: dvbdev.h + $(CC_MODULE) -include $(LINUX)/include/linux/modversions.h -DEXPORT_SYMTAB -c dvbdev.c + +clean: + rm -f core core.* *.o .*.o *.s *.a *~ .depend .depfiles/*.d diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/margi_cs.mk.MAIN linux.19rc3-ac4/drivers/media/video/margi/margi_cs.mk.MAIN --- linux.19rc3/drivers/media/video/margi/margi_cs.mk.MAIN 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/margi_cs.mk.MAIN 2002-07-29 13:58:42.000000000 +0100 @@ -0,0 +1,43 @@ +# +# Makefile for margi_cs +# Marcus Metzler +# + +VER = 0.5.0 + +FILES = margi_cs.mk margi2/margi_cs.mk \ + margi2/margi margi2/margi.opts margi2/margi.conf margi2/margi_cs.4\ + margi2/audio.c margi2/audio.h margi2/cardbase.c margi2/cardbase.h\ + margi2/crc.c margi2/crc.h margi2/cvdv.c\ + margi2/cvdv.h margi2/cvdvtypes.h margi2/decoder.c margi2/decoder.h\ + margi2/dram.c margi2/dram.h margi2/i2c.c margi2/i2c.h margi2/l64014.h\ + margi2/l64021.h margi2/margi.c margi2/margi.h margi2/video.c \ + margi2/video.h \ + margi2/osd.c margi2/osd.h margi2/spu.c margi2/spu.h margi2/streams.c\ + margi2/streams.h margi2/ringbuffy.c margi2/ringbuffy.h \ + margi2/README margi2/COPYING margi2/AUTHORS margi2/CHANGES\ + margi2/cvdvext.h\ + margi2/testsuite/Makefile margi2/testsuite/cvdvutil.c \ + margi2/testsuite/cvdvutil.h margi2/testsuite/osdtest.c \ + margi2/testsuite/osdwrap.c margi2/testsuite/osdwrap.h \ + margi2/testsuite/showpic.c margi2/testsuite/showpicmovie.c\ + margi2/testsuite/showstill.c margi2/testsuite/testpattern.c\ + margi2/testsuite/showstill.c margi2/testsuite/playfile.c\ + margi2/include/ost/audio.h margi2/include/ost/video.h \ + margi2/include/ost/ca.h margi2/include/ost/demux.h\ + margi2/include/ost/dmx.h margi2/include/ost/frontend.h\ + margi2/dvb_demux.h margi2/dvb_demux.c margi2/dvbdev.h margi2/dvbdev.c\ + margi2/include/ost/sec.h margi2/dmxdev.h margi2/dmxdev.c \ + margi2/include/ost/osd.h margi2/dvb_formats.h margi2/dvb_formats.c + +all: + $(MAKE) -C margi2 -f margi_cs.mk + +install: + $(MAKE) -C margi2 install-modules MODULES="margi_cs.o" -f margi_cs.mk + $(MAKE) -C margi2 install-clients CLIENTS=margi -f margi_cs.mk + $(MAKE) -C margi2 install-man4 MAN4=margi_cs.4 -f margi_cs.mk + +dist: + tar czvf margi_cs-$(VER).tar.gz $(FILES) + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/margi.h linux.19rc3-ac4/drivers/media/video/margi/margi.h --- linux.19rc3/drivers/media/video/margi/margi.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/margi.h 2002-07-29 17:29:11.000000000 +0100 @@ -0,0 +1,62 @@ +/* + margi.h + + Copyright (C) Marcus Metzler for convergence integrated media. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#ifndef margi_cs_h +#define margi_cs_h + +#include "cardbase.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define PBUFFER 100 + +u_char read_indexed_register(struct cvdv_cards *card, int addr); +void write_indexed_register(struct cvdv_cards *card, int addr, + u_char data); +void WriteByte(struct cvdv_cards *card, int addr, u_char data); +u_char ReadByte(struct cvdv_cards *card, int addr); +void MaskByte(struct cvdv_cards *card, int addr, u_char mask, u_char bits); +int MargiFreeBuffers(struct cvdv_cards *card); +int MargiSetBuffers(struct cvdv_cards *card, uint32_t size, int isB); +int MargiFlush (struct cvdv_cards *card); +int MargiPushA(struct cvdv_cards *card, int count, const char *data); +int MargiPushB(struct cvdv_cards *card, int count, const char *data); +int DecoderStartChannel(struct cvdv_cards *card); +int DecoderStopChannel(struct cvdv_cards *card); +void DACSetFrequency(struct cvdv_cards *card, int khz, int multiple); +stream_type get_stream_type(struct cvdv_cards *card); +audio_type get_audio_type(struct cvdv_cards *card); + +#ifdef NOINT +void Timerfunction(unsigned long data); +#endif + + +#endif diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/margi.opts linux.19rc3-ac4/drivers/media/video/margi/margi.opts --- linux.19rc3/drivers/media/video/margi/margi.opts 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/margi.opts 2002-07-29 13:58:42.000000000 +0100 @@ -0,0 +1,4 @@ +# +# Option for margi +# + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/osd.c linux.19rc3-ac4/drivers/media/video/margi/osd.c --- linux.19rc3/drivers/media/video/margi/osd.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/osd.c 2002-07-29 13:58:42.000000000 +0100 @@ -0,0 +1,947 @@ +/* + osd.c + + Copyright (C) Christian Wolff for convergence integrated media. + + 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. +*/ + + //////////////////////////////////////////////////////////////// + // // + // Functions to Draw on the On Screen Display of the L64021 // + // CLUT-Mode with 2, 4, or 8 bit per pixel, up to 720*576 // + // // +//////////////////////////////////////////////////////////////// +// OSD Pixel Aspect Ratio: +// CCIR601 525 Lines (NTSC,PAL-M): 11/10 (100*100 appears as 100*110) +// CCIR601 625 Lines (PAL): 11/12 (100*100 appears as 100*91.6) +// +// OSD functions for external use: +// int OSDOpen(struct cvdv_cards *card); +// int OSDClose(struct cvdv_cards *card); +// int OSDQuery(struct cvdv_cards *card, int *x0, int *y0, int *x1, int *y1, int *aspx, int *aspy); +// int OSDStartPicture(struct cvdv_cards *card, int left, int top, int width, int height, int bit, int mix); +// void OSDShow(struct cvdv_cards *card); +// void OSDHide(struct cvdv_cards *card); +// void OSDClear(struct cvdv_cards *card); +// void OSDFill(struct cvdv_cards *card, int col); +// int OSDSetColor(struct cvdv_cards *card, int num, int R, int G, int B, int mix, int trans); +// int OSDSetPixel(struct cvdv_cards *card, int x, int y, int col); +// int OSDGetPixel(struct cvdv_cards *card, int x, int y); +// int OSDSetRow(struct cvdv_cards *card, int x0, int y, int x1, u8 *data); +// int OSDFillRow(struct cvdv_cards *card, int x0, int y, int x1, int col); +// void OSDLine(struct cvdv_cards *card, int x0, int y0, int x1, int y1, int col); +// +// Return codes: (unless otherwise specified) +// 0: OK +// -1: Range error +// -2: OSD not open +// + +#define __NO_VERSION__ + +#include "osd.h" +#include "dram.h" +#include "l64021.h" + + // Builds a 4-word picture header in buf +// returns number of words in pixel field on success, -1 on error +int OSDHeader(u16 * buf, // 4 words + int *bit, // bit per pixel: 2, 4, or 8 + int *startrow, // position of our block, + int *stoprow, // row: 0..313 + int *startcol, // col: 0..864 + int *stopcol, // + int *mix, // opacity for mixed pixel, 0..15 (0%..94% resp.) + int nopal) +{ // 1: use previous palette + int count; + if (buf != NULL) { + if (*bit == 8) + *bit = 1; + else if (*bit == 2) + *bit = 0; + else + *bit = 2; + if (*startrow < 0) + *startrow = 0; + if (*startrow > 312) + *startrow = 312; + if (*stoprow <= *startrow) + *stoprow = *startrow + 1; + if (*stoprow > 313) + *stoprow = 313; + if (*startcol < 0) + *startcol = 0; + if (*startcol > 863) + *startcol = 863; + if (*stopcol <= *startcol) + *stopcol = *startcol + 2; + if (*stopcol > 864) + *stopcol = 864; + if ((*stopcol - *startcol + 1) & 1) + (*stopcol)--; + if (*mix < 0) + *mix = 0; + if (*mix > 15) + *mix = 15; + buf[0] = ((*bit << 14) & 0x8000) | (*startrow & 0x01FF); + buf[1] = + ((*mix << 12) & 0xF000) | ((*bit << 11) & 0x0800) | + ((nopal) ? 0x0400 : 0x0000) | (*stoprow & 0x01FF); + buf[2] = *startcol & 0x03FF; + buf[3] = *stopcol & 0x03FF; + count = + (*stoprow - *startrow + 1) * (*stopcol - *startcol + + 1); + if (*bit == 1) { + count = + ((count >> 3) + ((count & 0x07) ? 1 : 0)) << 2; + *bit = 8; + } else if (*bit == 0) { + count = + ((count >> 5) + ((count & 0x1F) ? 1 : 0)) << 2; + *bit = 2; + } else if (*bit == 2) { + count = + ((count >> 4) + ((count & 0x0F) ? 1 : 0)) << 2; + *bit = 4; + } + return count; // word count of pixel data + } else + return -1; +} + +// enables OSD mode +int OSDShow(struct cvdv_cards *card) +{ + if (card->OSD.open) { + DecoderMaskByte(card, 0x109, 0x03, 0x01); + DecoderDelByte(card, 0x112, 0x10); // no filter + return 0; + } else + return -2; +} + +// disables OSD mode +int OSDHide(struct cvdv_cards *card) +{ + if (card->OSD.open) { + DecoderMaskByte(card, 0x109, 0x03, 0x00); + return 0; + } else + return -2; +} + +// creates an empty picture in the memory of the card +// ONLY ONE PICTURE PER CARD! +// maximum sizes: NTSC: 720*525 PAL: 720*576 +// maximum positions: NTSC: 858*525 PAL: 864*625 +// returns 0 on success, -1 on DRAM allocation error +int OSDStartPicture(struct cvdv_cards *card, int left, int top, int width, + int height, int bit, int mix) +{ + u16 TermHeader[] = { 0x01FF, 0x05FF, 0x0000, 0x0000 }; + u16 header[4]; + int size, pixelsize, palsize, frametop, startrow, stoprow, + startcol, stopcol; + + if (card->OSD.open) + return -2; + if (top & 1) { + card->OSD.evenfirst = 0; + card->OSD.evenheight = height / 2; + card->OSD.oddheight = height - card->OSD.evenheight; + } else { + card->OSD.evenfirst = 1; + card->OSD.oddheight = height / 2; + card->OSD.evenheight = height - card->OSD.oddheight; + } + + // Setting the picture for the lines in the even field + frametop = top / 2; + startrow = frametop; + stoprow = frametop + card->OSD.evenheight - 1; + startcol = left; + stopcol = left + width - 1; + pixelsize = + OSDHeader(header, &bit, &startrow, &stoprow, &startcol, + &stopcol, &mix, 0); + card->OSD.evenheight = stoprow - startrow + 1; + card->OSD.bpp = bit; + if (bit == 8) + palsize = 256; + else if (bit == 2) + palsize = 4; + else + palsize = 16; + size = 8 + palsize + pixelsize; + card->OSD.evenmem = DRAMAlloc(card, size, 32); + if (card->OSD.evenmem == BLANK) + return -1; + card->OSD.evendata = card->OSD.evenmem; + card->OSD.evenpalette = card->OSD.evendata + 4; + card->OSD.evenbitmap = card->OSD.evenpalette + palsize; + card->OSD.eventerm = card->OSD.evenbitmap + pixelsize; + DecoderWriteWord(card, 0x110, (u16) (card->OSD.evendata >> 5)); + DRAMWriteWord(card, card->OSD.evendata, 4, header, 0); + DRAMFillByte(card, card->OSD.evenpalette, + (palsize + pixelsize) * 2, 0x00); + DRAMWriteWord(card, card->OSD.eventerm, 4, TermHeader, 0); + + // Setting the picture for the lines in the odd frame + frametop += card->OSD.evenfirst; + startrow = frametop; + stoprow = frametop + card->OSD.oddheight - 1; + pixelsize = + OSDHeader(header, &bit, &startrow, &stoprow, &startcol, + &stopcol, &mix, 0); + card->OSD.oddheight = stoprow - startrow + 1; + size = 8 + palsize + pixelsize; + card->OSD.oddmem = DRAMAlloc(card, size, 32); + if (card->OSD.oddmem == BLANK) + return -1; + card->OSD.odddata = card->OSD.oddmem; + card->OSD.oddpalette = card->OSD.odddata + 4; + card->OSD.oddbitmap = card->OSD.oddpalette + palsize; + card->OSD.oddterm = card->OSD.oddbitmap + pixelsize; + DecoderWriteWord(card, 0x10E, (u16) (card->OSD.odddata >> 5)); + DRAMWriteWord(card, card->OSD.odddata, 4, header, 0); + DRAMFillByte(card, card->OSD.oddpalette, (palsize + pixelsize) * 2, + 0x00); + DRAMWriteWord(card, card->OSD.oddterm, 4, TermHeader, 0); + + // Update of the picture dimensions + card->OSD.width = stopcol - startcol + 1; + card->OSD.height = card->OSD.evenheight + card->OSD.oddheight; + card->OSD.open = 1; + + MDEBUG(1,": OSD Open %dX%d, %d bit, mem 0x%08X/0x%08X\n", + card->OSD.width, card->OSD.height, card->OSD.bpp, + card->OSD.evendata, card->OSD.odddata); + return 0; +} + +// Disables OSD and releases the buffers +// returns 0 on success, 1 on "not open" +int OSDClose(struct cvdv_cards *card) +{ + if (card->OSD.open) { + OSDHide(card); + DRAMFree(card, card->OSD.evenmem); + DRAMFree(card, card->OSD.oddmem); + card->OSD.open = 0; + return 0; + } else + return -2; +} + +// Opens OSD with this size and bit depth +// returns 0 on success, 1 on DRAM allocation error, 2 on "already open" +int OSDOpen(struct cvdv_cards *card, int x0, int y0, int x1, int y1, + int bit, int mix) +{ + int ret; + if (card->OSD.open) + OSDClose(card); + if (bit < 0) + bit = 8; + else if (bit < 2) + bit = 2; + else if (bit < 4) + bit = 4; + else + bit = 8; + if (x0 < 0) + x0 = 0; + if (x1 < 0) + x1 = 720 - 1; + if (x1 < x0) + x1 = x0; + if (y0 < 0) + y0 = 0; + if (y1 < 0) + y1 = 576 - 1; + if (y1 < y0) + y1 = y0; + if ((x1 + 1) > 720) + x1 = 720 - 1; + if (x0 > x1) + x0 = x1; + if (CCIR601Lines(card->videomode) == 625) { // PAL + if ((y1 + 1) > 576) + y1 = 576 - 1; + if (y0 > y1) + y0 = y1; + if (! + (ret = + OSDStartPicture(card, 134 + x0, 48 + y0, x1 - x0 + 1, + y1 - y0 + 1, bit, mix))) + card->OSD.aspectratio = 12; // pixel aspect ratio 12/11 + } else { // NTSC + if ((y1 + 1) > 484) + y1 = 484 - 1; + if (y0 > y1) + y0 = y1; + if (! + (ret = + OSDStartPicture(card, 126 + x0, 44 + y0, x1 - x0 + 1, + y1 - y0 + 1, bit, mix))) + card->OSD.aspectratio = 10; // pixel aspect ratio 10/11 + } + return ret; +} + +// fills parameters with the picture dimensions and the pixel aspect ratio (aspy=11) +int OSDQuery(struct cvdv_cards *card, int *x0, int *y0, int *x1, int *y1, + int *aspx) +{ + if (!card->OSD.open) + return -2; + *x0 = 0; + *x1 = card->OSD.width - 1; + *y0 = 0; + *y1 = card->OSD.height - 1; + *aspx = card->OSD.aspectratio; + return 0; +} + +// Sets all pixel to color 0 +int OSDClear(struct cvdv_cards *card) +{ + if (!card->OSD.open) + return -2; + DRAMFillByte(card, card->OSD.oddbitmap, + (int) (card->OSD.oddterm - card->OSD.oddbitmap) * 2, + 0x00); + DRAMFillByte(card, card->OSD.evenbitmap, + (int) (card->OSD.eventerm - card->OSD.evenbitmap) * 2, + 0x00); + return 0; +} + +// Sets all pixel to color +int OSDFill(struct cvdv_cards *card, int col) +{ + u8 color; + if (!card->OSD.open) + return -2; + if (card->OSD.bpp == 8) { + color = col & 0xFF; + } else if (card->OSD.bpp == 4) { + color = (col & 0xF); + color |= (color << 4); + } else if (card->OSD.bpp == 2) { + color = (col & 0x03); + for (col = 1; col <= 3; col++) + color |= (color << 2); + } else + color = 0x00; + DRAMFillByte(card, card->OSD.oddbitmap, + (int) (card->OSD.oddterm - card->OSD.oddbitmap) * 2, + color); + DRAMFillByte(card, card->OSD.evenbitmap, + (int) (card->OSD.eventerm - card->OSD.evenbitmap) * 2, + color); + return 0; +} + +// converts RGB(8 bit) to YCrCb(OSD format) +// mix: 0=opacity 100% 1=opacity at mix value +// trans: 0=mix bit applies 1=opacity 0% +// returns word in OSD palette format +u16 OSDColor(u8 R, u8 G, u8 B, int mix, int trans) +{ + u16 Y, Cr, Cb; + Y = R * 77 + G * 150 + B * 29; // Luma=0.299R+0.587G+0.114B 0..65535 + Cb = 2048 + B * 8 - (Y >> 5); // Cr 0..4095 + Cr = 2048 + R * 10 - (Y >> 5); // Cb 0..4095 + return ((trans) ? 0 : // transparent pixel + (Y & 0xFC00) | // Luma 0..63 + ((mix) ? 0x0100 : 0x0000) | // Opacity applies + ((Cb >> 4) & 0x00F0) | // Cb 0..15 + ((Cr >> 8) & 0x000F) // Cr 0..15 + ); +} + +// set palette entry to , and apply +// R,G,B: 0..255 +// RGB=1: R=Red, G=Green, B=Blue RGB=0: R=Y G=Cb B=Cr +// mix=0, trans=0: pixel opacity 100% (only OSD pixel shows) +// mix=1, trans=0: pixel opacity as specified in header +// trans=1: pixel opacity 0% (only video pixel shows) +// returns 0 on success, 1 on error +int OSDSetColor(struct cvdv_cards *card, int num, int R, int G, int B, + int YUV, int mix, int trans) +{ + u16 burst[4]; // minimal memory unit + u32 addr; + u16 color; + if (!card->OSD.open) + return -2; + if (R < 0) + R = 0; + if (R > 255) + R = 255; + if (G < 0) + G = 0; + if (G > 255) + G = 255; + if (B < 0) + B = 0; + if (B > 255) + B = 255; + if ((num >= 0) && (num < (1 << card->OSD.bpp))) { + if (num==0) MDEBUG(4,"OSD SetColor num=%d, R=%d, G=%d, B=%d, YUV=%d, mix=%d, trans=%d\n", + num,R,G,B,YUV,mix,trans); + color = ((YUV) + ? ((trans) ? 0 : ((R << 8) & 0xFC00) | + ((mix) ? 0x0100 : 0x0000) | (G & 0x00F0) | + ((B >> 4) & 0x000F)) : OSDColor(R, G, B, mix, + trans)); + + addr = card->OSD.oddpalette + num; + DRAMReadWord(card, addr & ~3, 4, burst, 0); + burst[addr & 3] = color; + DRAMWriteWord(card, addr & ~3, 4, burst, 0); + + addr = card->OSD.evenpalette + num; + DRAMReadWord(card, addr & ~3, 4, burst, 0); + burst[addr & 3] = color; + DRAMWriteWord(card, addr & ~3, 4, burst, 0); + + return 0; + } else + return -1; +} + +// Set a number of entries in the palette +// sets the entries "firstcolor" through "lastcolor" from the array "data" +// data has 4 byte for each color: +// R,G,B, and a transparency value: 0->tranparent, 1..254->mix, 255->no mix +int OSDSetPalette(struct cvdv_cards *card, int firstcolor, int lastcolor, + u8 * data) +{ + u16 burst[4]; // minimal memory unit + u32 addr; + u16 color; + int num, i = 0; + if (!card->OSD.open) + return -2; + for (num = firstcolor; num <= lastcolor; num++) + if ((num >= 0) && (num < (1 << card->OSD.bpp))) { + color = + OSDColor(data[i], data[i + 1], data[i + 2], + ((data[i + 3] < 255) ? 1 : 0), + ((data[i + 3] == 0) ? 1 : 0)); + i += 4; + + addr = card->OSD.oddpalette + num; + DRAMReadWord(card, addr & ~3, 4, burst, 0); + burst[addr & 3] = color; + DRAMWriteWord(card, addr & ~3, 4, burst, 0); + + addr = card->OSD.evenpalette + num; + DRAMReadWord(card, addr & ~3, 4, burst, 0); + burst[addr & 3] = color; + DRAMWriteWord(card, addr & ~3, 4, burst, 0); + } + return 0; +} + +// Sets transparency of mixed pixel (0..15) +int OSDSetTrans(struct cvdv_cards *card, int trans) +{ + u16 burst[4]; // minimal memory unit + if (!card->OSD.open) + return -2; + trans &= 0x000F; + DRAMReadWord(card, card->OSD.evendata, 4, burst, 0); + burst[1] = (burst[1] & 0x0FFF) | (trans << 12); + DRAMWriteWord(card, card->OSD.evendata, 4, burst, 0); + + DRAMReadWord(card, card->OSD.odddata, 4, burst, 0); + burst[1] = (burst[1] & 0x0FFF) | (trans << 12); + DRAMWriteWord(card, card->OSD.odddata, 4, burst, 0); + return 0; +} + +// sets pixel , to color number +// returns 0 on success, 1 on error +int OSDSetPixel(struct cvdv_cards *card, int x, int y, int col) +{ + u16 burst[4]; // minimal memory unit od DRAM + u32 addr; + int offset, ppw, pos, shift, height, posmask; + u16 mask; + + if (!card->OSD.open) + return -2; + if ((y & 1) == card->OSD.evenfirst) { // even or odd frame? + addr = card->OSD.oddbitmap; + height = card->OSD.oddheight; + } else { + addr = card->OSD.evenbitmap; + height = card->OSD.evenheight; + } + y >>= 1; + if ((x >= 0) && (x < card->OSD.width) && (y >= 0) && (y < height)) { // clipping + ppw = + ((card->OSD.bpp == 4) ? 2 : ((card->OSD.bpp == 8) ? 1 : 3)); // OK, 4-(ln(bpp)/ln(2)) would have worked, too... + pos = x + y * card->OSD.width; // pixel number in bitfield + addr += (pos >> ppw); // 21 bit address of word with our pixel + offset = addr & 3; // offset in burst + addr &= ~3; // 21 bit burst address + posmask = (1 << ppw) - 1; // mask for position inside word + shift = ((posmask - (pos & posmask)) << (4 - ppw)); // pixel shift inside word + mask = (1 << (1 << (4 - ppw))) - 1; // pixel mask + DRAMReadWord(card, addr, 4, burst, 0); // get the burst with our pixel... + burst[offset] = + (burst[offset] & ~(mask << shift)) | ((col & mask) << + shift); + DRAMWriteWord(card, addr, 4, burst, 0); // ...and write it back + return 0; + } else + return -1; +} + +// returns color number of pixel ,, or -1 +int OSDGetPixel(struct cvdv_cards *card, int x, int y) +{ + u16 burst[4]; // minimal memory unit + u32 addr; + int offset, ppw, pos, shift, height, posmask; + u16 mask; + + if (!card->OSD.open) + return -2; + if ((y & 1) == card->OSD.evenfirst) { // even or odd frame? + addr = card->OSD.oddbitmap; + height = card->OSD.oddheight; + } else { + addr = card->OSD.evenbitmap; + height = card->OSD.evenheight; + } + y >>= 1; + if ((x >= 0) && (x < card->OSD.width) && (y >= 0) && (y < height)) { // clipping + ppw = + ((card->OSD.bpp == 4) ? 2 : ((card->OSD.bpp == 8) ? 1 : 3)); // OK, 4-(ln(bpp)/ln(2)) would have worked, too... + pos = x + y * card->OSD.width; // pixel number in bitfield + addr += (pos >> ppw); // 21 bit address of word with our pixel + offset = addr & 3; // offset in burst + addr &= ~3; // 21 bit burst address + posmask = (1 << ppw) - 1; // mask for position inside word + shift = ((posmask - (pos & posmask)) << (4 - ppw)); // pixel shift inside word + mask = (1 << (1 << (4 - ppw))) - 1; // pixel mask + DRAMReadWord(card, addr, 4, burst, 0); // get the burst with our pixel... + return (burst[offset] >> shift) & mask; // ...and return it's value + } else + return -1; +} + +// fills pixels x0,y through x1,y with the content of data[] +// returns 0 on success, -1 on clipping all pixel +int OSDSetRow(struct cvdv_cards *card, int x0, int y, int x1, u8 * data) +{ + u16 burst[4]; // minimal memory unit + u32 addr, addr1, bitmap; + int offset, offset1, ppw, pos, pos1, shift, shift0, shift1, + shiftstep, height, bpp, x, i, endburst, endword; + u16 mask, posmask; + + if (!card->OSD.open) + return -2; + if ((y & 1) == card->OSD.evenfirst) { + bitmap = card->OSD.oddbitmap; + height = card->OSD.oddheight; + } else { + bitmap = card->OSD.evenbitmap; + height = card->OSD.evenheight; + } + y >>= 1; + if ((y >= 0) && (y < height)) { + i = 0; + if (x0 > x1) { + x = x1; + x1 = x0; + x0 = x; + } + if ((x0 >= card->OSD.width) || (x1 < 0)) + return -1; + if (x0 < 0) { + i -= x0; + x0 = 0; + } + if (x1 >= card->OSD.width) + x1 = card->OSD.width - 1; + bpp = card->OSD.bpp; // bits per pixel + ppw = ((bpp == 4) ? 2 : ((bpp == 8) ? 1 : 3)); // positional parameter + mask = (1 << bpp) - 1; // mask for one pixel + posmask = (1 << ppw) - 1; // mask for position inside word + + pos = x0 + (y * card->OSD.width); // pixel number of first pixel + pos1 = pos + x1 - x0; // pixel number of last pixel + shift0 = ((posmask - (pos & posmask)) << (4 - ppw)); + shift1 = ((posmask - (pos1 & posmask)) << (4 - ppw)); + shiftstep = 1 << (4 - ppw); + + addr = bitmap + (pos >> ppw); // DRAM address of word with first pixel + addr1 = bitmap + (pos1 >> ppw); // " " " " " last " + offset = (int) (addr & 3); // word position inside burst + offset1 = (int) (addr1 & 3); // number of last word in the last burst + addr &= ~3; // burst address + addr1 &= ~3; // burst address of last pixel + + endburst = (addr1 != addr); // end in other burst + endword = (offset1 != offset); // end in other word + + // read old content of first burst if the row start after the beginning or + // end before the end of the first burst + if (offset || (pos & posmask) || + (!endburst + && ((offset1 != 3) + || ((pos1 & posmask) != posmask)))) { + DRAMReadWord(card, addr, 4, burst, 0); + } + // End beyond or at the end of this word? + if (endburst || endword || ((pos1 & posmask) == posmask)) { + // Fill first word + for (shift = shift0; shift >= 0; shift -= shiftstep) { // bit position inside word + burst[offset] = + (burst[offset] & ~(mask << shift)) | + ((data[i++] & mask) << shift); + } + if (endburst || endword) { // Any more words to fill? + shift0 = posmask << (4 - ppw); // from here on, we start at the beginning of each word + offset++; // fill the rest of the burst + if (endburst) { // end not in this burst? + while (offset <= 3) { // fill remaining words + burst[offset] = 0x0000; // clear first + for (shift = shift0; + shift >= 0; + shift -= shiftstep) { + burst[offset] |= + ((data + [i++] & mask) + << shift); + } + offset++; + } + DRAMWriteWord(card, addr, 4, burst, 0); // write first burst + addr += 4; // go on to the next burst + while (addr < addr1) { // all bursts between start and end burst + for (offset = 0; + offset <= 3; offset++) { // 4 words per burst + burst[offset] = 0x0000; // clear first + for (shift = + shift0; + shift >= 0; + shift -= + shiftstep) { + burst + [offset] + |= + ((data + [i++] + & + mask) + << + shift); + } + } + DRAMWriteWord(card, addr, + 4, burst, 0); // write full burst + addr += 4; // next burst + } + offset = 0; + if ((offset1 < 3) || shift1) { // does the row ends before the end of the burst? + DRAMReadWord(card, addr, 4, + burst, 0); // then we have to read the old content + } + } + while (offset < offset1) { // end not in this word + burst[offset] = 0x0000; // clear first + for (shift = shift0; shift >= 0; + shift -= shiftstep) { + burst[offset] |= + ((data[i++] & mask) << + shift); + } + offset++; + } + for (shift = shift0; shift >= shift1; + shift -= shiftstep) { // last word + burst[offset] = + (burst[offset] & + ~(mask << shift)) | + ((data[i++] & mask) << shift); + } + } + } else { // row starts and ends in one word + for (shift = shift0; shift >= shift1; shift -= shiftstep) { // bit position inside word + burst[offset] = + (burst[offset] & ~(mask << shift)) | + ((data[i++] & mask) << shift); + } + } + DRAMWriteWord(card, addr, 4, burst, 0); // write only/last burst + return 0; + } else + return -1; +} + +// fills pixels x0,y0 through x1,y1 with the content of data[] +// inc contains the width of one line in the data block, +// inc<=0 uses blockwidth as linewidth +// returns 0 on success, -1 on clipping all pixel +int OSDSetBlock(struct cvdv_cards *card, int x0, int y0, int x1, int y1, + int inc, u8 * data) +{ + int i, w = x1 - x0 + 1, ret = 0; + if (inc > 0) + w = inc; + for (i = y0; i <= y1; i++) { + ret |= OSDSetRow(card, x0, i, x1, data); + data += w; + } + return ret; +} + +// fills pixels x0,y through x1,y with the color +// returns 0 on success, -1 on clipping all pixel +int OSDFillRow(struct cvdv_cards *card, int x0, int y, int x1, int col) +{ + u16 burst[4]; // minimal memory unit + u32 addr, addr1, bitmap; + int offset, offset1, ppw, pos, pos1, shift, shift0, shift1, + shiftstep, height, bpp, x, i, endburst, endword; + u16 mask, posmask; + + if (!card->OSD.open) + return -2; + if ((y & 1) == card->OSD.evenfirst) { + bitmap = card->OSD.oddbitmap; + height = card->OSD.oddheight; + } else { + bitmap = card->OSD.evenbitmap; + height = card->OSD.evenheight; + } + y >>= 1; + if ((y >= 0) && (y < height)) { + i = 0; + if (x0 > x1) { + x = x1; + x1 = x0; + x0 = x; + } + if ((x0 >= card->OSD.width) || (x1 < 0)) + return -1; + if (x0 < 0) { + i -= x0; + x0 = 0; + } + if (x1 >= card->OSD.width) + x1 = card->OSD.width - 1; + bpp = card->OSD.bpp; // bits per pixel + ppw = ((bpp == 4) ? 2 : ((bpp == 8) ? 1 : 3)); // positional parameter + mask = (1 << bpp) - 1; // mask for one pixel + posmask = (1 << ppw) - 1; // mask for position inside word + + pos = x0 + (y * card->OSD.width); // pixel number of first pixel + pos1 = pos + x1 - x0; // pixel number of last pixel + shift0 = ((posmask - (pos & posmask)) << (4 - ppw)); + shift1 = ((posmask - (pos1 & posmask)) << (4 - ppw)); + shiftstep = 1 << (4 - ppw); + + addr = bitmap + (pos >> ppw); // DRAM address of word with first pixel + addr1 = bitmap + (pos1 >> ppw); // " " " " " last " + offset = (int) (addr & 3); // word position inside burst + offset1 = (int) (addr1 & 3); // number of last word in the last burst + addr &= ~3; // burst address + addr1 &= ~3; // burst address of last pixel + + endburst = (addr1 != addr); // end in other burst + endword = (offset1 != offset); // end in other word + + // read old content of first burst if the row start after the beginning or + // end before the end of the first burst + if (offset || (pos & posmask) || + (!endburst + && ((offset1 != 3) + || ((pos1 & posmask) != posmask)))) { + DRAMReadWord(card, addr, 4, burst, 0); + } + if (endburst || endword || ((pos1 & posmask) == posmask)) { // end beyond or at the end of this word? + for (shift = shift0; shift >= 0; shift -= shiftstep) { // bit position inside word + burst[offset] = + (burst[offset] & ~(mask << shift)) | + ((col & mask) << shift); + } + if (endburst || endword) { + shift0 = posmask << (4 - ppw); // from here on, we start at the beginning of each word + offset++; // fill the rest of the burst + if (endburst) { // end not in this burst? + while (offset <= 3) { // fill remaining words + burst[offset] = 0x0000; // clear first + for (shift = shift0; + shift >= 0; + shift -= shiftstep) { + burst[offset] |= + ((col & mask) + << shift); + } + offset++; + } + DRAMWriteWord(card, addr, 4, burst, 0); // write first burst + addr += 4; // next burst + while (addr < addr1) { // write all the bursts between start and end burst + for (offset = 0; + offset <= 3; offset++) { + burst[offset] = + 0x0000; + for (shift = + shift0; + shift >= 0; + shift -= + shiftstep) { + burst + [offset] + |= + ((col + & + mask) + << + shift); + } + } + DRAMWriteWord(card, addr, + 4, burst, 0); + addr += 4; + } + offset = 0; + if ((offset1 < 3) || shift1) { // does the row ends before the end of the burst? + DRAMReadWord(card, addr, 4, + burst, 0); // then we have to read the old content + } + } + while (offset < offset1) { // end not in this word + burst[offset] = 0x0000; + for (shift = shift0; shift >= 0; + shift -= shiftstep) { + burst[offset] |= + ((col & mask) << + shift); + } + offset++; + } + for (shift = shift0; shift >= shift1; + shift -= shiftstep) { + burst[offset] = + (burst[offset] & + ~(mask << shift)) | ((col & + mask) << + shift); + } + } + } else { // row starts and ends in one word + for (shift = shift0; shift >= shift1; shift -= shiftstep) { // bit position inside word + burst[offset] = + (burst[offset] & ~(mask << shift)) | + ((col & mask) << shift); + } + } + DRAMWriteWord(card, addr, 4, burst, 0); + return 0; + } else + return -1; +} + +// fills pixels x0,y0 through x1,y1 with the color +// returns 0 on success, -1 on clipping all pixel +int OSDFillBlock(struct cvdv_cards *card, int x0, int y0, int x1, int y1, + int col) +{ + int i, ret = 0; + for (i = y0; i <= y1; i++) + ret |= OSDFillRow(card, x0, i, x1, col); + return ret; +} + +// draw a line from x0,y0 to x1,y1 with the color +int OSDLine(struct cvdv_cards *card, int x0, int y0, int x1, int y1, + int col) +{ + int ct, ix, iy, ax, ay, dx, dy, off; +#define sgn(a) ((a)?(((a)>0)?1:-1):0) + if (!card->OSD.open) + return -2; + dx = x1 - x0; + dy = y1 - y0; + if (dx == 0) { + if (dy < 0) + for (iy = y1; iy <= y0; iy++) + OSDSetPixel(card, x0, iy, col); + else + for (iy = y0; iy <= y1; iy++) + OSDSetPixel(card, x0, iy, col); + } else if (dy == 0) { + OSDFillRow(card, x0, y0, x1, col); + } else { + ay = 0; + ax = 0; + ix = sgn(dx); + dx = abs(dx); + iy = sgn(dy); + dy = abs(dy); + if (dx < dy) { + off = dx; + dx = dy; + dy = off; + ay = ix; + ax = iy; + ix = 0; + iy = 0; + } + off = dx >> 1; + ct = 1; + OSDSetPixel(card, x0, y0, col); + x1 = x0; + y1 = y0; + while (dx >= ct) { + x0 += ix; + y0 += ax; + ct++; + off += dy; + if (off > dx) { + off -= dx; + x0 += ay; + y0 += iy; + } + if (ax) { + OSDSetPixel(card, x0, y0, col); + } else { + if (y0 != y1) { + OSDFillRow(card, x1, y1, x0 - ay, + col); + x1 = x0; + y1 = y0; + } + } + } + if (!ax) + OSDFillRow(card, x1, y0, x0, col); + } + return 0; +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/osd.h linux.19rc3-ac4/drivers/media/video/margi/osd.h --- linux.19rc3/drivers/media/video/margi/osd.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/osd.h 2002-07-29 17:29:11.000000000 +0100 @@ -0,0 +1,148 @@ +/* + osd.h + + Copyright (C) Christian Wolff for convergence integrated media. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef CVDV_OSD_H +#define CVDV_OSD_H + + //////////////////////////////////////////////////////////////// + // // + // Functions to Draw on the On Screen Display of the L64021 // + // CLUT-Mode with 2, 4, or 8 bit per pixel, up to 720*576 // + // // +//////////////////////////////////////////////////////////////// +// OSD Pixel Aspect Ratio: +// CCIR601 525 Lines (NTSC,PAL-M): 11/10 (100*100 appears as 100*110) +// CCIR601 625 Lines (PAL): 11/12 (100*100 appears as 100*91.6) +// +// OSD functions for external use: +// int OSDOpen(struct cvdv_cards *card); +// int OSDClose(struct cvdv_cards *card); +// int OSDQuery(struct cvdv_cards *card, int *x0, int *y0, int *x1, int *y1, int *aspx, int *aspy); +// int OSDStartPicture(struct cvdv_cards *card, int left, int top, int width, int height, int bit, int mix); +// void OSDShow(struct cvdv_cards *card); +// void OSDHide(struct cvdv_cards *card); +// void OSDClear(struct cvdv_cards *card); +// void OSDFill(struct cvdv_cards *card, int col); +// int OSDSetColor(struct cvdv_cards *card, int num, int R, int G, int B, int mix, int trans); +// int OSDSetPixel(struct cvdv_cards *card, int x, int y, int col); +// int OSDGetPixel(struct cvdv_cards *card, int x, int y); +// int OSDSetRow(struct cvdv_cards *card, int x0, int y, int x1, u8 *data); +// int OSDFillRow(struct cvdv_cards *card, int x0, int y, int x1, int col); +// void OSDLine(struct cvdv_cards *card, int x0, int y0, int x1, int y1, int col); +// +// Return codes: (unless otherwise specified) +// 0: OK +// -1: Range error +// -2: OSD not open +// + +#include "cardbase.h" + +// enables OSD mode +int OSDShow(struct cvdv_cards *card); + +// disables OSD mode +int OSDHide(struct cvdv_cards *card); + +// creates an empty picture in the memory of the card +// ONLY ONE PICTURE PER CARD! ( might be changed in the future, if i find time...) +// maximum sizes: NTSC: 720*525 PAL: 720*576 +// maximum positions: NTSC: 858*525 PAL: 864*625 +// returns 0 on success, -1 on DRAM allocation error +int OSDStartPicture(struct cvdv_cards *card, int left, int top, int width, + int height, int bit, int mix); + +// Disables OSD and releases the buffers +// returns 0 on success, 1 on "not open" +int OSDClose(struct cvdv_cards *card); + +// Opens OSD with this size and bit depth +// returns 0 on success, 1 on DRAM allocation error, 2 on "already open" +int OSDOpen(struct cvdv_cards *card, int x0, int y0, int x1, int y1, + int bit, int mix); + +// fills parameters with the picture dimensions and the pixel aspect ratio (aspy=11) +int OSDQuery(struct cvdv_cards *card, int *x0, int *y0, int *x1, int *y1, + int *aspx); + +// Sets all pixel to color 0 +int OSDClear(struct cvdv_cards *card); + +// Sets all pixel to color +int OSDFill(struct cvdv_cards *card, int col); + +// converts RGB(8 bit) to YCrCb(OSD format) +// mix: 0=opacity 100% 1=opacity at mix value +// trans: 0=mix bit applies 1=opacity 0% +// returns word in OSD palette format +u16 OSDColor(u8 R, u8 G, u8 B, int mix, int trans); + +// set palette entry to , and apply +// R,G,B: 0..255 +// RGB=1: R=Red, G=Green, B=Blue RGB=0: R=Y G=Cb B=Cr +// mix=0, trans=0: pixel opacity 100% (only OSD pixel shows) +// mix=1, trans=0: pixel opacity as specified in header +// trans=1: pixel opacity 0% (only video pixel shows) +// returns 0 on success, 1 on error +int OSDSetColor(struct cvdv_cards *card, int num, int R, int G, int B, + int YUV, int mix, int trans); + +// Set a number of entries in the palette +// sets the entries "firstcolor" through "lastcolor" from the array "data" +// data has 4 byte for each color: +// R,G,B, and a transparency value: 0->tranparent, 1..254->mix, 255->no mix +int OSDSetPalette(struct cvdv_cards *card, int firstcolor, int lastcolor, + u8 * data); + +// Sets transparency of mixed pixel (0..15) +int OSDSetTrans(struct cvdv_cards *card, int trans); + +// sets pixel , to color number +// returns 0 on success, 1 on error +int OSDSetPixel(struct cvdv_cards *card, int x, int y, int col); + +// returns color number of pixel ,, or -1 +int OSDGetPixel(struct cvdv_cards *card, int x, int y); + +// fills pixels x0,y through x1,y with the content of data[] +// returns 0 on success, -1 on clipping all pixel +int OSDSetRow(struct cvdv_cards *card, int x0, int y, int x1, u8 * data); + +// fills pixels x0,y0 through x1,y1 with the content of data[] +// inc contains the width of one line in the data block, +// inc<=0 uses blockwidth as linewidth +// returns 0 on success, -1 on clipping all pixel +int OSDSetBlock(struct cvdv_cards *card, int x0, int y0, int x1, int y1, + int inc, u8 * data); + +// fills pixels x0,y through x1,y with the color +// returns 0 on success, -1 on clipping all pixel +int OSDFillRow(struct cvdv_cards *card, int x0, int y, int x1, int col); + +// fills pixels x0,y0 through x1,y1 with the color +// returns 0 on success, -1 on clipping all pixel +int OSDFillBlock(struct cvdv_cards *card, int x0, int y0, int x1, int y1, + int col); + +// draw a line from x0,y0 to x1,y1 with the color +int OSDLine(struct cvdv_cards *card, int x0, int y0, int x1, int y1, + int col); + +#endif /* CVDV_OSD_H */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/ost/audio.h linux.19rc3-ac4/drivers/media/video/margi/ost/audio.h --- linux.19rc3/drivers/media/video/margi/ost/audio.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/ost/audio.h 2002-07-29 13:58:42.000000000 +0100 @@ -0,0 +1,120 @@ +/* + * audio.h + * + * Copyright (C) 2000 Ralph Metzler + * & Marcus Metzler + for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Lesser Public License + * as published by the Free Software Foundation; either version 2.1 + * 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 Lesser 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. + * + */ + +#ifndef _OST_AUDIO_H_ +#define _OST_AUDIO_H_ + +#ifdef __KERNEL__ +#include +#else +#include +#endif + +#define boolean int +#define true 1 +#define false 0 + +typedef enum { + AUDIO_SOURCE_DEMUX, /* Select the demux as the main source */ + AUDIO_SOURCE_MEMORY /* Select internal memory as the main source */ +} audioStreamSource_t; + +typedef enum { + AUDIO_STOPPED, /* Device is stopped */ + AUDIO_PLAYING, /* Device is currently playing */ + AUDIO_PAUSED /* Device is paused */ +} audioPlayState_t; + +typedef enum { + AUDIO_STEREO, + AUDIO_MONO_LEFT, + AUDIO_MONO_RIGHT, +} audioChannelSelect_t; + +typedef struct audioStatus { + boolean AVSyncState; /* sync audio and video? */ + boolean muteState; /* audio is muted */ + audioPlayState_t playState; /* current playback state */ + audioStreamSource_t streamSource; /* current stream source */ + audioChannelSelect_t channelSelect; /* currently selected channel */ + boolean bypassMode; /* pass on audio data to separate + decoder hardware */ +} audioStatus_t; + +typedef struct audioMixer { + unsigned int volume_left; + unsigned int volume_right; + // what else do we need? bass, pass-through, ... +} audioMixer_t; + +typedef +struct audioKaraoke{ /* if Vocal1 or Vocal2 are non-zero, they get mixed */ + int vocal1; /* into left and right t at 70% each */ + int vocal2; /* if both, Vocal1 and Vocal2 are non-zero, Vocal1 gets */ + int melody; /* mixed into the left channel and */ + /* Vocal2 into the right channel at 100% each. */ + /* if Melody is non-zero, the melody channel gets mixed */ /* into left and right */ +} audioKaraoke_t; + +typedef uint16_t audioAttributes_t; +/* bits: descr. */ +/* 15-13 audio coding mode (0=ac3, 2=mpeg1, 3=mpeg2ext, 4=LPCM, 6=DTS, */ +/* 12 multichannel extension */ +/* 11-10 audio type (0=not spec, 1=language included) */ +/* 9- 8 audio application mode (0=not spec, 1=karaoke, 2=surround) */ +/* 7- 6 Quantization / DRC (mpeg audio: 1=DRC exists)(lpcm: 0=16bit, */ +/* 5- 4 Sample frequency fs (0=48kHz, 1=96kHz) */ +/* 2- 0 number of audio channels (n+1 channels) */ + + +/* for GET_CAPABILITIES and SET_FORMAT, the latter should only set one bit */ +#define AUDIO_CAP_DTS 1 +#define AUDIO_CAP_LPCM 2 +#define AUDIO_CAP_MP1 4 +#define AUDIO_CAP_MP2 8 +#define AUDIO_CAP_MP3 16 +#define AUDIO_CAP_AAC 32 +#define AUDIO_CAP_OGG 64 +#define AUDIO_CAP_SDDS 128 +#define AUDIO_CAP_AC3 256 + +#define AUDIO_STOP _IO('o', 1) +#define AUDIO_PLAY _IO('o', 2) +#define AUDIO_PAUSE _IO('o', 3) +#define AUDIO_CONTINUE _IO('o', 4) +#define AUDIO_SELECT_SOURCE _IOW('o', 5, audioStreamSource_t) +#define AUDIO_SET_MUTE _IOW('o', 6, boolean) +#define AUDIO_SET_AV_SYNC _IOW('o', 7, boolean) +#define AUDIO_SET_BYPASS_MODE _IOW('o', 8, boolean) +#define AUDIO_CHANNEL_SELECT _IOW('o', 9, audioChannelSelect_t) +#define AUDIO_GET_STATUS _IOR('o', 10, audioStatus_t *) + +#define AUDIO_GET_CAPABILITIES _IOR('o', 11, unsigned int *) +#define AUDIO_CLEAR_BUFFER _IO('o', 12) +#define AUDIO_SET_ID _IOW('o', 13, int) +#define AUDIO_SET_MIXER _IOW('o', 14, audioMixer_t *) +#define AUDIO_SET_STREAMTYPE _IOW('o', 15, unsigned int) +#define AUDIO_SET_EXT_ID _IOW('o', 16, int) +#define AUDIO_SET_ATTRIBUTES _IOW('o', 17, audioAttributes_t) +#define AUDIO_SET_KARAOKE _IOW('o', 18, audioKaraoke_t *) +#endif /* _OST_AUDIO_H_ */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/ost/ca.h linux.19rc3-ac4/drivers/media/video/margi/ost/ca.h --- linux.19rc3/drivers/media/video/margi/ost/ca.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/ost/ca.h 2002-07-29 13:58:42.000000000 +0100 @@ -0,0 +1,85 @@ +/* + * ca.h + * + * Copyright (C) 2000 Ralph Metzler + * & Marcus Metzler + for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Lesser Public License + * as published by the Free Software Foundation; either version 2.1 + * 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 Lesser 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. + * + */ + +#ifndef _OST_CA_H_ +#define _OST_CA_H_ + +/* slot interface types and info */ + +typedef struct ca_slot_info_s { + int num; /* slot number */ + + int type; /* CA interface this slot supports */ +#define CA_CI 1 /* CI high level interface */ +#define CA_CI_LINK 2 /* CI link layer level interface */ +#define CA_CI_PHYS 4 /* CI physical layer level interface */ +#define CA_SC 128 /* simple smart card interface */ + + unsigned int flags; +#define CA_CI_MODULE_PRESENT 1 /* module (or card) inserted */ +#define CA_CI_MODULE_READY 2 +} ca_slot_info_t; + + +/* descrambler types and info */ + +typedef struct ca_descr_info_s { + unsigned int num; /* number of available descramblers (keys) */ + unsigned int type; /* type of supported scrambling system */ +#define CA_ECD 1 +#define CA_NDS 2 +#define CA_DSS 4 +} ca_descr_info_t; + +typedef struct ca_cap_s { + unsigned int slot_num; /* total number of CA card and module slots */ + unsigned int slot_type; /* OR of all supported types */ + unsigned int descr_num; /* total number of descrambler slots (keys) */ + unsigned int descr_type; /* OR of all supported types */ +} ca_cap_t; + +/* a message to/from a CI-CAM */ +typedef struct ca_msg_s { + unsigned int index; + unsigned int type; + unsigned int length; + unsigned char msg[256]; +} ca_msg_t; + +typedef struct ca_descr_s { + unsigned int index; + unsigned int parity; + unsigned char cw[8]; +} ca_descr_t; + +#define CA_RESET _IOW('o', 128, int) +#define CA_GET_CAP _IOR('o', 129, ca_cap_t *) +#define CA_GET_SLOT_INFO _IOR('o', 130, ca_slot_info_t *) +#define CA_GET_DESCR_INFO _IOR('o', 131, ca_descr_info_t *) +#define CA_GET_MSG _IOR('o', 132, ca_msg_t *) +#define CA_SEND_MSG _IOW('o', 133, ca_msg_t *) +#define CA_SET_DESCR _IOW('o', 134, ca_descr_t *) +#define CA_SELECT_SLOT _IOW('o', 135, int) + +#endif + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/ost/demux.h linux.19rc3-ac4/drivers/media/video/margi/ost/demux.h --- linux.19rc3/drivers/media/video/margi/ost/demux.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/ost/demux.h 2002-07-29 13:58:42.000000000 +0100 @@ -0,0 +1,346 @@ +/* * demux.h * * Copyright (c) 2000 Nokia Research Center + * Tampere, FINLAND + * + * Project: + * Universal Broadcast Access + * + * Contains: + * Type definitions of a Linux kernel-level API for filtering MPEG-2 TS + * packets and MPEG-2 sections. Support for PES packet filtering will be + * added later. + * + * History: + * 12.01.2000/JPL File created - Initial version. + * 18.02.2000/JPL Minor corrections. + * 21.02.2000/JPL DMX_NAME_SIZE and dmx_in_use() removed, typos fixed, + * some names changed. + * 23.02.2000/JPL Added a parameter indicating the callback source in + * the callback functions. + * 10.03.2000/JPL Added the macros DMX_DIR_ENTRY() and DMX_FE_ENTRY(). + * 15.03.2000/JPL Added the capabilities field to dmx_demux_t. + * 22.03.2000/JPL Corrected the callback parameter in the + * allocate_x_feed() functions. + * 03.04.2000/JPL Added support for optional resource conflict resolution + * and scarce resource handling. + * 05.04.2000/JPL Changed the dmx_resolve_conflict() to use resource + * type as a parameter. + * 12.04.2000/JPL Added a second buffer parameter for dmx_x_callback() + * functions to better handle buffer wrapping. + * 26.04.2000/JPL Added functions for section-level descrambling. + * 03.09.2000/JPL Removed support for conflict resolution and scarce + * resource handling. Otherwise only minor changes to + * data structures and function prototypes. + * + * + * Author: + * Juha-Pekka Luoma (JPL) + * Nokia Research Center + * + * Notes: + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * 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 Lesser 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. + * + */ +/* $Id: demux.h,v 1.14 2002/02/03 11:38:56 mocm Exp $ */ + +#ifndef __DEMUX_H +#define __DEMUX_H + +#ifndef __KERNEL__ +#define __KERNEL__ +#endif + +#include /* __u8, __u16, ... */ +#include /* list_entry(), struct list_head */ +#include /* struct timespec */ +#include /* Function return values */ + +/*--------------------------------------------------------------------------*/ +/* Common definitions */ +/*--------------------------------------------------------------------------*/ + +/* + * DMX_MAX_FILTER_SIZE: Maximum length (in bytes) of a section/PES filter. + */ + +#ifndef DMX_MAX_FILTER_SIZE +#define DMX_MAX_FILTER_SIZE 18 +#endif +/* + * dmx_success_t: Success codes for the Demux Callback API. + */ + +typedef enum { + DMX_OK = 0, /* Received Ok */ + DMX_LENGTH_ERROR, /* Incorrect length */ + DMX_OVERRUN_ERROR, /* Receiver ring buffer overrun */ + DMX_CRC_ERROR, /* Incorrect CRC */ + DMX_FRAME_ERROR, /* Frame alignment error */ + DMX_FIFO_ERROR, /* Receiver FIFO overrun */ + DMX_MISSED_ERROR /* Receiver missed packet */ +} dmx_success_t; + +/*--------------------------------------------------------------------------*/ +/* TS packet reception */ +/*--------------------------------------------------------------------------*/ + +/* TS filter type for set_type() */ + +#define TS_PACKET 1 /* send TS packets (188 bytes) to callback (default) */ +#define TS_PAYLOAD_ONLY 2 /* in case TS_PACKET is set, only send the TS + payload (<=184 bytes per packet) to callback */ +#define TS_DECODER 4 /* send stream to built-in decoder (if present) */ + +/* PES type for filters which write to built-in decoder */ +/* these should be kept identical to the types in dmx.h */ + +typedef enum +{ + DMX_TS_PES_AUDIO, /* also send packets to audio decoder (if it exists) */ + DMX_TS_PES_VIDEO, /* ... */ + DMX_TS_PES_TELETEXT, + DMX_TS_PES_SUBTITLE, + DMX_TS_PES_PCR, + DMX_TS_PES_OTHER, +} dmx_ts_pes_t; + + +struct dmx_ts_feed_s { + int is_filtering; /* Set to non-zero when filtering in progress */ + struct dmx_demux_s* parent; /* Back-pointer */ + void* priv; /* Pointer to private data of the API client */ + int (*set) (struct dmx_ts_feed_s* feed, + __u16 pid, + size_t callback_length, + size_t circular_buffer_size, + int descramble, + struct timespec timeout); + int (*start_filtering) (struct dmx_ts_feed_s* feed); + int (*stop_filtering) (struct dmx_ts_feed_s* feed); + int (*set_type) (struct dmx_ts_feed_s* feed, + int type, + dmx_ts_pes_t pes_type); +}; + +typedef struct dmx_ts_feed_s dmx_ts_feed_t; + +/*--------------------------------------------------------------------------*/ +/* PES packet reception (not supported yet) */ +/*--------------------------------------------------------------------------*/ + +typedef struct dmx_pes_filter_s { + struct dmx_pes_s* parent; /* Back-pointer */ + void* priv; /* Pointer to private data of the API client */ +} dmx_pes_filter_t; + +typedef struct dmx_pes_feed_s { + int is_filtering; /* Set to non-zero when filtering in progress */ + struct dmx_demux_s* parent; /* Back-pointer */ + void* priv; /* Pointer to private data of the API client */ + int (*set) (struct dmx_pes_feed_s* feed, + __u16 pid, + size_t circular_buffer_size, + int descramble, + struct timespec timeout); + int (*start_filtering) (struct dmx_pes_feed_s* feed); + int (*stop_filtering) (struct dmx_pes_feed_s* feed); + int (*allocate_filter) (struct dmx_pes_feed_s* feed, + dmx_pes_filter_t** filter); + int (*release_filter) (struct dmx_pes_feed_s* feed, + dmx_pes_filter_t* filter); +} dmx_pes_feed_t; + +/*--------------------------------------------------------------------------*/ +/* Section reception */ +/*--------------------------------------------------------------------------*/ + +typedef struct { + __u8 filter_value [DMX_MAX_FILTER_SIZE]; + __u8 filter_mask [DMX_MAX_FILTER_SIZE]; + struct dmx_section_feed_s* parent; /* Back-pointer */ + void* priv; /* Pointer to private data of the API client */ +} dmx_section_filter_t; + +struct dmx_section_feed_s { + int is_filtering; /* Set to non-zero when filtering in progress */ + struct dmx_demux_s* parent; /* Back-pointer */ + void* priv; /* Pointer to private data of the API client */ + int (*set) (struct dmx_section_feed_s* feed, + __u16 pid, + size_t circular_buffer_size, + int descramble, + int check_crc); + int (*allocate_filter) (struct dmx_section_feed_s* feed, + dmx_section_filter_t** filter); + int (*release_filter) (struct dmx_section_feed_s* feed, + dmx_section_filter_t* filter); + int (*start_filtering) (struct dmx_section_feed_s* feed); + int (*stop_filtering) (struct dmx_section_feed_s* feed); +}; +typedef struct dmx_section_feed_s dmx_section_feed_t; + +/*--------------------------------------------------------------------------*/ +/* Callback functions */ +/*--------------------------------------------------------------------------*/ + +typedef int (*dmx_ts_cb) ( __u8 * buffer1, + size_t buffer1_length, + __u8 * buffer2, + size_t buffer2_length, + dmx_ts_feed_t* source, + dmx_success_t success); + +typedef int (*dmx_section_cb) ( __u8 * buffer1, + size_t buffer1_len, + __u8 * buffer2, + size_t buffer2_len, + dmx_section_filter_t * source, + dmx_success_t success); + +typedef int (*dmx_pes_cb) ( __u8 * buffer1, + size_t buffer1_len, + __u8 * buffer2, + size_t buffer2_len, + dmx_pes_filter_t* source, + dmx_success_t success); + +/*--------------------------------------------------------------------------*/ +/* DVB Front-End */ +/*--------------------------------------------------------------------------*/ + +typedef enum { + DMX_OTHER_FE = 0, + DMX_SATELLITE_FE, + DMX_CABLE_FE, + DMX_TERRESTRIAL_FE, + DMX_LVDS_FE, + DMX_ASI_FE, /* DVB-ASI interface */ + DMX_MEMORY_FE +} dmx_frontend_source_t; + +typedef struct { + /* The following char* fields point to NULL terminated strings */ + char* id; /* Unique front-end identifier */ + char* vendor; /* Name of the front-end vendor */ + char* model; /* Name of the front-end model */ + struct list_head connectivity_list; /* List of front-ends that can + be connected to a particular + demux */ + void* priv; /* Pointer to private data of the API client */ + dmx_frontend_source_t source; +} dmx_frontend_t; + +/*--------------------------------------------------------------------------*/ +/* MPEG-2 TS Demux */ +/*--------------------------------------------------------------------------*/ + +/* + * Flags OR'ed in the capabilites field of struct dmx_demux_s. + */ + +#define DMX_TS_FILTERING 1 +#define DMX_PES_FILTERING 2 +#define DMX_SECTION_FILTERING 4 +#define DMX_MEMORY_BASED_FILTERING 8 /* write() available */ +#define DMX_CRC_CHECKING 16 +#define DMX_TS_DESCRAMBLING 32 +#define DMX_SECTION_PAYLOAD_DESCRAMBLING 64 +#define DMX_MAC_ADDRESS_DESCRAMBLING 128 + +/* + * Demux resource type identifier. +*/ + +/* + * DMX_FE_ENTRY(): Casts elements in the list of registered + * front-ends from the generic type struct list_head + * to the type * dmx_frontend_t + *. +*/ + +#define DMX_FE_ENTRY(list) list_entry(list, dmx_frontend_t, connectivity_list) + +struct dmx_demux_s { + /* The following char* fields point to NULL terminated strings */ + char* id; /* Unique demux identifier */ + char* vendor; /* Name of the demux vendor */ + char* model; /* Name of the demux model */ + __u32 capabilities; /* Bitfield of capability flags */ + dmx_frontend_t* frontend; /* Front-end connected to the demux */ + struct list_head reg_list; /* List of registered demuxes */ + void* priv; /* Pointer to private data of the API client */ + int users; /* Number of users */ + int (*open) (struct dmx_demux_s* demux); + int (*close) (struct dmx_demux_s* demux); + int (*write) (struct dmx_demux_s* demux, const char* buf, size_t count); + int (*allocate_ts_feed) (struct dmx_demux_s* demux, + dmx_ts_feed_t** feed, + dmx_ts_cb callback); + int (*release_ts_feed) (struct dmx_demux_s* demux, + dmx_ts_feed_t* feed); + int (*allocate_pes_feed) (struct dmx_demux_s* demux, + dmx_pes_feed_t** feed, + dmx_pes_cb callback); + int (*release_pes_feed) (struct dmx_demux_s* demux, + dmx_pes_feed_t* feed); + int (*allocate_section_feed) (struct dmx_demux_s* demux, + dmx_section_feed_t** feed, + dmx_section_cb callback); + int (*release_section_feed) (struct dmx_demux_s* demux, + dmx_section_feed_t* feed); + int (*descramble_mac_address) (struct dmx_demux_s* demux, + __u8* buffer1, + size_t buffer1_length, + __u8* buffer2, + size_t buffer2_length, + __u16 pid); + int (*descramble_section_payload) (struct dmx_demux_s* demux, + __u8* buffer1, + size_t buffer1_length, + __u8* buffer2, size_t buffer2_length, + __u16 pid); + int (*add_frontend) (struct dmx_demux_s* demux, + dmx_frontend_t* frontend); + int (*remove_frontend) (struct dmx_demux_s* demux, + dmx_frontend_t* frontend); + struct list_head* (*get_frontends) (struct dmx_demux_s* demux); + int (*connect_frontend) (struct dmx_demux_s* demux, + dmx_frontend_t* frontend); + int (*disconnect_frontend) (struct dmx_demux_s* demux); + + + /* added because js cannot keep track of these himself */ + int (*get_pes_pids) (struct dmx_demux_s* demux, __u16 *pids); +}; +typedef struct dmx_demux_s dmx_demux_t; + +/*--------------------------------------------------------------------------*/ +/* Demux directory */ +/*--------------------------------------------------------------------------*/ + +/* + * DMX_DIR_ENTRY(): Casts elements in the list of registered + * demuxes from the generic type struct list_head* to the type dmx_demux_t + *. + */ + +#define DMX_DIR_ENTRY(list) list_entry(list, dmx_demux_t, reg_list) + +int dmx_register_demux (dmx_demux_t* demux); +int dmx_unregister_demux (dmx_demux_t* demux); +struct list_head* dmx_get_demuxes (void); + +#endif /* #ifndef __DEMUX_H */ + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/ost/dmx.h linux.19rc3-ac4/drivers/media/video/margi/ost/dmx.h --- linux.19rc3/drivers/media/video/margi/ost/dmx.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/ost/dmx.h 2002-07-29 13:58:42.000000000 +0100 @@ -0,0 +1,147 @@ +/* + * dmx.h + * + * Copyright (C) 2000 Marcus Metzler + * & Ralph Metzler + for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * 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 Lesser 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. + * + */ + +#ifndef _OST_DMX_H_ +#define _OST_DMX_H_ + +#ifdef __KERNEL__ +#include +#else +#include +#endif + +#ifndef EBUFFEROVERFLOW +#define EBUFFEROVERFLOW 769 +#endif + +typedef uint16_t dvb_pid_t; + +#define DMX_FILTER_SIZE 16 + +typedef enum +{ + DMX_OUT_DECODER, /* Streaming directly to decoder. */ + DMX_OUT_TAP, /* Output going to a memory buffer */ + /* (to be retrieved via the read command).*/ + DMX_OUT_TS_TAP /* Output multiplexed into a new TS */ + /* (to be retrieved by reading from the */ + /* logical DVR device). */ +} dmxOutput_t; + + +typedef enum +{ + DMX_IN_FRONTEND, /* Input from a front-end device. */ + DMX_IN_DVR /* Input from the logical DVR device. */ +} dmxInput_t; + + +typedef enum +{ + DMX_PES_AUDIO, + DMX_PES_VIDEO, + DMX_PES_TELETEXT, + DMX_PES_SUBTITLE, + DMX_PES_PCR, + DMX_PES_OTHER +} dmxPesType_t; + + +typedef enum +{ + DMX_SCRAMBLING_EV, + DMX_FRONTEND_EV +} dmxEvent_t; + + +typedef enum +{ + DMX_SCRAMBLING_OFF, + DMX_SCRAMBLING_ON +} dmxScramblingStatus_t; + + +typedef struct dmxFilter +{ + uint8_t filter[DMX_FILTER_SIZE]; + uint8_t mask[DMX_FILTER_SIZE]; +} dmxFilter_t; + + +struct dmxFrontEnd +{ + +}; + + +struct dmxSctFilterParams +{ + dvb_pid_t pid; + dmxFilter_t filter; + uint32_t timeout; + uint32_t flags; +#define DMX_CHECK_CRC 1 +#define DMX_ONESHOT 2 +#define DMX_IMMEDIATE_START 4 +#define DMX_KERNEL_CLIENT 0x8000 +}; + + +struct dmxPesFilterParams +{ + dvb_pid_t pid; + dmxInput_t input; + dmxOutput_t output; + dmxPesType_t pesType; + uint32_t flags; +}; + + +struct dmxEvent +{ + dmxEvent_t event; + time_t timeStamp; + union + { + dmxScramblingStatus_t scrambling; + } u; +}; + + +typedef struct dmxCaps_s +{ + uint32_t caps; /* */ + int num_decoders; +} dmxCaps_t; + + +#define DMX_START _IOW('o',41,int) +#define DMX_STOP _IOW('o',42,int) +#define DMX_SET_FILTER _IOW('o',43,struct dmxSctFilterParams *) +#define DMX_SET_PES_FILTER _IOW('o',44,struct dmxPesFilterParams *) +#define DMX_SET_BUFFER_SIZE _IOW('o',45,unsigned long) +#define DMX_GET_EVENT _IOR('o',46,struct dmxEvent *) +#define DMX_GET_PES_PIDS _IOR('o',47,dvb_pid_t *) +#define DMX_GET_CAPS _IOR('o',48,dmxCaps_t *) + +#endif /*_OST_DMX_H_*/ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/ost/frontend.h linux.19rc3-ac4/drivers/media/video/margi/ost/frontend.h --- linux.19rc3/drivers/media/video/margi/ost/frontend.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/ost/frontend.h 2002-07-29 13:58:42.000000000 +0100 @@ -0,0 +1,208 @@ +/* + * frontend.h + * + * Copyright (C) 2000 Marcus Metzler + * & Ralph Metzler + * for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * 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 Lesser 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. + * + */ + +#ifndef _FRONTEND_H_ +#define _FRONTEND_H_ + +#include + + +#define ENOSIGNAL 768 +#ifndef EBUFFEROVERFLOW +#define EBUFFEROVERFLOW 769 +#endif + + +typedef __u32 FrontendStatus; + +/* bit definitions for FrontendStatus */ +#define FE_HAS_POWER 1 +#define FE_HAS_SIGNAL 2 +#define FE_SPECTRUM_INV 4 +#define FE_HAS_LOCK 8 +#define FE_HAS_CARRIER 16 +#define FE_HAS_VITERBI 32 +#define FE_HAS_SYNC 64 +#define FE_TUNER_HAS_LOCK 128 + + +/* possible values for spectral inversion */ +typedef enum { + INVERSION_OFF, + INVERSION_ON, + INVERSION_AUTO +} SpectralInversion; + +/* possible values for FEC_inner/FEC_outer */ +typedef enum { + FEC_AUTO, + FEC_1_2, + FEC_2_3, + FEC_3_4, + FEC_5_6, + FEC_7_8, + FEC_NONE +} CodeRate; + + +typedef enum { + QPSK, + QAM_16, + QAM_32, + QAM_64, + QAM_128, + QAM_256 +} Modulation; + + +typedef enum { + TRANSMISSION_MODE_2K, + TRANSMISSION_MODE_8K +} TransmitMode; + +typedef enum { + BANDWIDTH_8_MHZ, + BANDWIDTH_7_MHZ, + BANDWIDTH_6_MHZ +} BandWidth; + + +typedef enum { + GUARD_INTERVAL_1_32, + GUARD_INTERVAL_1_16, + GUARD_INTERVAL_1_8, + GUARD_INTERVAL_1_4 +} GuardInterval; + + +typedef enum { + HIERARCHY_NONE, + HIERARCHY_1, + HIERARCHY_2, + HIERARCHY_4 +} Hierarchy; + + +typedef struct { + __u32 SymbolRate; /* symbol rate in Symbols per second */ + CodeRate FEC_inner; /* forward error correction (see above) */ +} QPSKParameters; + + +typedef struct { + __u32 SymbolRate; /* symbol rate in Symbols per second */ + CodeRate FEC_inner; /* forward error correction (see above) */ + Modulation QAM; /* modulation type (see above) */ +} QAMParameters; + + +typedef struct { + BandWidth bandWidth; + CodeRate HP_CodeRate; /* high priority stream code rate */ + CodeRate LP_CodeRate; /* low priority stream code rate */ + Modulation Constellation; /* modulation type (see above) */ + TransmitMode TransmissionMode; + GuardInterval guardInterval; + Hierarchy HierarchyInformation; +} OFDMParameters; + + +typedef enum { + FE_QPSK, + FE_QAM, + FE_OFDM +} FrontendType; + + +typedef struct { + __u32 Frequency; /* (absolute) frequency in Hz for QAM/OFDM */ + /* intermediate frequency in kHz for QPSK */ + SpectralInversion Inversion; /* spectral inversion */ + union { + QPSKParameters qpsk; + QAMParameters qam; + OFDMParameters ofdm; + } u; +} FrontendParameters; + + +typedef enum { + FE_UNEXPECTED_EV, /* unexpected event (e.g. loss of lock) */ + FE_COMPLETION_EV, /* completion event, tuning succeeded */ + FE_FAILURE_EV /* failure event, we couldn't tune */ +} EventType; + + +typedef struct { + EventType type; /* type of event, FE_UNEXPECTED_EV, ... */ + + long timestamp; /* time in seconds since 1970-01-01 */ + + union { + struct { + FrontendStatus previousStatus; /* status before event */ + FrontendStatus currentStatus; /* status during event */ + } unexpectedEvent; + FrontendParameters completionEvent; /* parameters for which the + tuning succeeded */ + FrontendStatus failureEvent; /* status at failure (e.g. no lock) */ + } u; +} FrontendEvent; + +typedef struct { + FrontendType type; + __u32 minFrequency; + __u32 maxFrequency; + __u32 maxSymbolRate; + __u32 minSymbolRate; + __u32 hwType; + __u32 hwVersion; +} FrontendInfo; + + +typedef enum { + FE_POWER_ON, + FE_POWER_STANDBY, + FE_POWER_SUSPEND, + FE_POWER_OFF +} FrontendPowerState; + + +#define FE_SELFTEST _IO('o', 61) +#define FE_SET_POWER_STATE _IOW('o', 62, FrontendPowerState) +#define FE_GET_POWER_STATE _IOR('o', 63, FrontendPowerState*) +#define FE_READ_STATUS _IOR('o', 64, FrontendStatus*) +#define FE_READ_BER _IOW('o', 65, __u32*) +#define FE_READ_SIGNAL_STRENGTH _IOR('o', 66, __s32*) +#define FE_READ_SNR _IOR('o', 67, __s32*) +#define FE_READ_UNCORRECTED_BLOCKS _IOW('o', 68, __u32*) +#define FE_GET_NEXT_FREQUENCY _IOW('o', 69, __u32*) +#define FE_GET_NEXT_SYMBOL_RATE _IOW('o', 70, __u32*) + +#define FE_SET_FRONTEND _IOW('o', 71, FrontendParameters*) +#define FE_GET_FRONTEND _IOR('o', 72, FrontendParameters*) +#define FE_GET_INFO _IOR('o', 73, FrontendInfo*) +#define FE_GET_EVENT _IOR('o', 74, FrontendEvent*) + +#endif /*_FRONTEND_H_*/ + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/ost/net.h linux.19rc3-ac4/drivers/media/video/margi/ost/net.h --- linux.19rc3/drivers/media/video/margi/ost/net.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/ost/net.h 2002-07-29 13:58:42.000000000 +0100 @@ -0,0 +1,40 @@ +/* + * net.h + * + * Copyright (C) 2000 Marcus Metzler + * & Ralph Metzler + for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * 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 Lesser 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. + * + */ + +#ifndef _OST_NET_H_ +#define _OST_NET_H_ + +#ifdef __KERNEL__ +#include +#else +#include +#endif + +struct dvb_net_if { + uint16_t pid; + uint16_t if_num; +}; + +#define NET_ADD_IF _IOWR('o', 52, struct dvb_net_if *) +#define NET_REMOVE_IF _IOW('o', 53, uint16_t) +#endif /*_OST_VIDEO_H_*/ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/ost/osd.h linux.19rc3-ac4/drivers/media/video/margi/ost/osd.h --- linux.19rc3/drivers/media/video/margi/ost/osd.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/ost/osd.h 2002-07-29 13:58:42.000000000 +0100 @@ -0,0 +1,111 @@ +/* + * osd.h + * + * Copyright (C) 2001 Ralph Metzler + * & Marcus Metzler + for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Lesser Public License + * as published by the Free Software Foundation; either version 2.1 + * 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 Lesser 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. + * + */ + +#ifndef _OST_OSD_H_ +#define _OST_OSD_H_ + +typedef enum { + // All functions return -2 on "not open" + OSD_Close=1, // () + // Disables OSD and releases the buffers + // returns 0 on success + OSD_Open, // (x0,y0,x1,y1,BitPerPixel[2/4/8](color&0x0F),mix[0..15](color&0xF0)) + // Opens OSD with this size and bit depth + // returns 0 on success, -1 on DRAM allocation error, -2 on "already open" + OSD_Show, // () + // enables OSD mode + // returns 0 on success + OSD_Hide, // () + // disables OSD mode + // returns 0 on success + OSD_Clear, // () + // Sets all pixel to color 0 + // returns 0 on success + OSD_Fill, // (color) + // Sets all pixel to color + // returns 0 on success + OSD_SetColor, // (color,R{x0},G{y0},B{x1},opacity{y1}) + // set palette entry to , and apply + // R,G,B: 0..255 + // R=Red, G=Green, B=Blue + // opacity=0: pixel opacity 0% (only video pixel shows) + // opacity=1..254: pixel opacity as specified in header + // opacity=255: pixel opacity 100% (only OSD pixel shows) + // returns 0 on success, -1 on error + OSD_SetPalette, // (firstcolor{color},lastcolor{x0},data) + // Set a number of entries in the palette + // sets the entries "firstcolor" through "lastcolor" from the array "data" + // data has 4 byte for each color: + // R,G,B, and a opacity value: 0->transparent, 1..254->mix, 255->pixel + OSD_SetTrans, // (transparency{color}) + // Sets transparency of mixed pixel (0..15) + // returns 0 on success + OSD_SetPixel, // (x0,y0,color) + // sets pixel , to color number + // returns 0 on success, -1 on error + OSD_GetPixel, // (x0,y0) + // returns color number of pixel ,, or -1 + OSD_SetRow, // (x0,y0,x1,data) + // fills pixels x0,y through x1,y with the content of data[] + // returns 0 on success, -1 on clipping all pixel (no pixel drawn) + OSD_SetBlock, // (x0,y0,x1,y1,increment{color},data) + // fills pixels x0,y0 through x1,y1 with the content of data[] + // inc contains the width of one line in the data block, + // inc<=0 uses blockwidth as linewidth + // returns 0 on success, -1 on clipping all pixel + OSD_FillRow, // (x0,y0,x1,color) + // fills pixels x0,y through x1,y with the color + // returns 0 on success, -1 on clipping all pixel + OSD_FillBlock, // (x0,y0,x1,y1,color) + // fills pixels x0,y0 through x1,y1 with the color + // returns 0 on success, -1 on clipping all pixel + OSD_Line, // (x0,y0,x1,y1,color) + // draw a line from x0,y0 to x1,y1 with the color + // returns 0 on success + OSD_Query, // (x0,y0,x1,y1,xasp{color}}), yasp=11 + // fills parameters with the picture dimensions and the pixel aspect ratio + // returns 0 on success + OSD_Test, // () + // draws a test picture. for debugging purposes only + // returns 0 on success +// TODO: remove "test" in final version + OSD_Text, // (x0,y0,size,color,text) + OSD_SetWindow, // (x0) set window with number 0 + * & Marcus Metzler + for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * 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 Lesser 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. + * + */ + +#ifndef _OST_SEC_H_ +#define _OST_SEC_H_ + +#define SEC_MAX_DISEQC_PARAMS 3 + +struct secDiseqcCmd { + uint8_t addr; + uint8_t cmd; + uint8_t numParams; + uint8_t params[SEC_MAX_DISEQC_PARAMS]; +}; + +typedef uint32_t secVoltage; + +enum { + SEC_VOLTAGE_OFF, + SEC_VOLTAGE_LT, + SEC_VOLTAGE_13, + SEC_VOLTAGE_13_5, + SEC_VOLTAGE_18, + SEC_VOLTAGE_18_5 +}; + +#define SEC_VOLTAGE_HORIZONTAL SEC_VOLTAGE_18 +#define SEC_VOLTAGE_VERTICAL SEC_VOLTAGE_13 + +typedef uint32_t secToneMode; + +typedef enum { + SEC_TONE_ON, + SEC_TONE_OFF +} secToneMode_t; + + +typedef uint32_t secMiniCmd; + +typedef enum { + SEC_MINI_NONE, + SEC_MINI_A, + SEC_MINI_B +} secMiniCmd_t; + +struct secStatus { + int32_t busMode; + secVoltage selVolt; + secToneMode contTone; +}; + +enum { + SEC_BUS_IDLE, + SEC_BUS_BUSY, + SEC_BUS_OFF, + SEC_BUS_OVERLOAD +}; + +struct secCommand { + int32_t type; + union { + struct secDiseqcCmd diseqc; + uint8_t vsec; + uint32_t pause; + } u; +}; + +struct secCmdSequence { + secVoltage voltage; + secMiniCmd miniCommand; + secToneMode continuousTone; + + uint32_t numCommands; + struct secCommand* commands; +}; + +enum { + SEC_CMDTYPE_DISEQC, + SEC_CMDTYPE_VSEC, + SEC_CMDTYPE_PAUSE +}; + + +#define SEC_GET_STATUS _IOR('o',91,struct secStatus *) +#define SEC_RESET_OVERLOAD _IOW('o',92,void) +#define SEC_SEND_SEQUENCE _IOW('o',93,struct secCmdSequence *) +#define SEC_SET_TONE _IOW('o',94,secToneMode) +#define SEC_SET_VOLTAGE _IOW('o',95,secVoltage) + +typedef enum { + SEC_DISEQC_SENT, + SEC_VSEC_SENT, + SEC_PAUSE_COMPLETE, + SEC_CALLBACK_ERROR +} secCallback_t; + + +#endif /*_OST_SEC_H_*/ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/ost/video.h linux.19rc3-ac4/drivers/media/video/margi/ost/video.h --- linux.19rc3/drivers/media/video/margi/ost/video.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/ost/video.h 2002-07-29 13:58:42.000000000 +0100 @@ -0,0 +1,186 @@ +/* + * video.h + * + * Copyright (C) 2000 Marcus Metzler + * & Ralph Metzler + for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * 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 Lesser 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. + * + */ + +#ifndef _OST_VIDEO_H_ +#define _OST_VIDEO_H_ + +#ifdef __KERNEL__ +#include +#else +#include +#endif + +#define boolean int +#define true 1 +#define false 0 + +typedef enum { + VIDEO_FORMAT_4_3, /* Select 4:3 format */ + VIDEO_FORMAT_16_9 /* Select 16:9 format. */ +} videoFormat_t; + +typedef enum { + VIDEO_SYSTEM_PAL, + VIDEO_SYSTEM_NTSC, + VIDEO_SYSTEM_PALN, + VIDEO_SYSTEM_PALNc, + VIDEO_SYSTEM_PALM, + VIDEO_SYSTEM_NTSC60, + VIDEO_SYSTEM_PAL60, + VIDEO_SYSTEM_PALM60 +} videoSystem_t; + +typedef enum { + VIDEO_PAN_SCAN, /* use pan and scan format */ + VIDEO_LETTER_BOX, /* use letterbox format */ + VIDEO_CENTER_CUT_OUT /* use center cut out format */ +} videoDisplayFormat_t; + +typedef enum { + VIDEO_SOURCE_DEMUX, /* Select the demux as the main source */ + VIDEO_SOURCE_MEMORY /* If this source is selected, the stream + comes from the user through the write + system call */ +} videoStreamSource_t; + +typedef enum { + VIDEO_STOPPED, /* Video is stopped */ + VIDEO_PLAYING, /* Video is currently playing */ + VIDEO_FREEZED /* Video is freezed */ +} videoPlayState_t; + +struct videoEvent { + int32_t type; + time_t timestamp; + union { + videoFormat_t videoFormat; + } u; +}; + +struct videoStatus { + boolean videoBlank; /* blank video on freeze? */ + videoPlayState_t playState; /* current state of playback */ + videoStreamSource_t streamSource; /* current source (demux/memory) */ + videoFormat_t videoFormat; /* current aspect ratio of stream */ + videoDisplayFormat_t displayFormat; /* selected cropping mode */ +}; + +/* pointer to and size of a single iframe in memory */ +struct videoDisplayStillPicture { + char *iFrame; + int32_t size; +}; + + +typedef +struct videoHighlight { + boolean active; /* 1=show highlight, 0=hide highlight */ + uint8_t contrast1; /* 7- 4 Pattern pixel contrast */ + /* 3- 0 Background pixel contrast */ + uint8_t contrast2; /* 7- 4 Emphasis pixel-2 contrast */ + /* 3- 0 Emphasis pixel-1 contrast */ + uint8_t color1; /* 7- 4 Pattern pixel color */ + /* 3- 0 Background pixel color */ + uint8_t color2; /* 7- 4 Emphasis pixel-2 color */ + /* 3- 0 Emphasis pixel-1 color */ + uint32_t ypos; /* 23-22 auto action mode */ + /* 21-12 start y */ + /* 9- 0 end y */ + uint32_t xpos; /* 23-22 button color number */ + /* 21-12 start x */ + /* 9- 0 end x */ +} videoHighlight_t; + + +typedef +struct videoSPU { + boolean active; + int streamID; +} videoSPU_t; + +typedef +struct videoSPUPalette{ /* SPU Palette information */ + int length; + uint8_t *palette; +} videoSPUPalette_t; + +typedef +struct videoNaviPack{ + int length; /* 0 ... 1024 */ + uint8_t data[1024]; +} videoNaviPack_t; + + +typedef uint16_t videoAttributes_t; +/* bits: descr. */ +/* 15-14 Video compression mode (0=MPEG-1, 1=MPEG-2) */ +/* 13-12 TV system (0=525/60, 1=625/50) */ +/* 11-10 Aspect ratio (0=4:3, 3=16:9) */ +/* 9- 8 permitted display mode on 4:3 monitor (0=both, 1=only pan-sca */ +/* 7 line 21-1 data present in GOP (1=yes, 0=no) */ +/* 6 line 21-2 data present in GOP (1=yes, 0=no) */ +/* 5- 3 source resolution (0=720x480/576, 1=704x480/576, 2=352x480/57 */ +/* 2 source letterboxed (1=yes, 0=no) */ +/* 0 film/camera mode (0=camera, 1=film (625/50 only)) */ + + +/* bit definitions for capabilities: */ +/* can the hardware decode MPEG1 and/or MPEG2? */ +#define VIDEO_CAP_MPEG1 1 +#define VIDEO_CAP_MPEG2 2 +/* can you send a system and/or program stream to video device? + (you still have to open the video and the audio device but only + send the stream to the video device) */ +#define VIDEO_CAP_SYS 4 +#define VIDEO_CAP_PROG 8 +/* can the driver also handle SPU, NAVI and CSS encoded data? + (CSS API is not present yet) */ +#define VIDEO_CAP_SPU 16 +#define VIDEO_CAP_NAVI 32 +#define VIDEO_CAP_CSS 64 + + +#define VIDEO_STOP _IOW('o', 21, boolean) +#define VIDEO_PLAY _IO('o', 22) +#define VIDEO_FREEZE _IO('o', 23) +#define VIDEO_CONTINUE _IO('o', 24) +#define VIDEO_SELECT_SOURCE _IOW('o', 25, videoStreamSource_t) +#define VIDEO_SET_BLANK _IOW('o', 26, boolean) +#define VIDEO_GET_STATUS _IOR('o', 27, struct videoStatus *) +#define VIDEO_GET_EVENT _IOR('o', 28, struct videoEvent *) +#define VIDEO_SET_DISPLAY_FORMAT _IOW('o', 29, videoDisplayFormat_t) +#define VIDEO_STILLPICTURE _IOW('o', 30, struct videoDisplayStillPicture *) +#define VIDEO_FAST_FORWARD _IOW('o', 31, int) +#define VIDEO_SLOWMOTION _IOW('o', 32, int) +#define VIDEO_GET_CAPABILITIES _IOR('o', 33, unsigned int *) +#define VIDEO_CLEAR_BUFFER _IO('o', 34) +#define VIDEO_SET_ID _IOW('o', 35, unsigned char) +#define VIDEO_SET_STREAMTYPE _IOW('o', 36, int) +#define VIDEO_SET_FORMAT _IOW('o', 37, videoFormat_t) +#define VIDEO_SET_SYSTEM _IOW('o', 38, videoSystem_t) +#define VIDEO_SET_HIGHLIGHT _IOW('o', 39, videoHighlight_t *) +#define VIDEO_SET_SPU _IOW('o', 50, videoSPU_t *) +#define VIDEO_SET_SPU_PALETTE _IOW('o', 51, videoSPUPalette_t *) +#define VIDEO_GET_NAVI _IOR('o', 52, videoNaviPack_t *) +#define VIDEO_SET_ATTRIBUTES _IOW('o', 53, videoAttributes_t) +#endif /*_OST_VIDEO_H_*/ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/README linux.19rc3-ac4/drivers/media/video/margi/README --- linux.19rc3/drivers/media/video/margi/README 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/README 2002-07-29 13:58:41.000000000 +0100 @@ -0,0 +1,97 @@ +This is the driver for the Margi/Billionton MPEG decoder PC-Card. +It is still in a beta state and may cause problems with your system. + +INSTALLING +---------- +0) From now on you will need a 2.4.x kernel to make everything work + +1) Install David Hinds` PCMCIA Card Services package. The current + version is at http://pcmcia.sourceforge.org/. + This driver is known to work under versions 3.1.25 and later. Earlier + version may work too. + + % tar zxvf pcmcia-cs-3.1.25.tar.gz + +2) Enter the pcmcia directory and unpack the margi driver. + + % cd pcmcia-cs-3.1.25 + % tar zxvf margi_cs-0.5.tar.gz + +3) In the pcmcia main directory: + + % make config + % make all + # make install + + +The files for the margi are in margi2. (The name has historical reasons.) + +ATTENTION You now need video4linux support in the kernel. +You can now use /dev/video for playback. + + +Using the driver +---------------- +The driver registers a character device with major number 162. You can +cat an MPEG2 program stream into that device. +If the device doesn`t exist (usually it`s /dev/raw) just + % mknod -m 0666 /dev/margi char 200 0 +Than you + % cat nicempg2.vob > /dev/margi +or + % cat nicempg.mpg > /dev/margi + +At the moment we do not recognize the audio format of the MPEG1/2, so +MPEG audio is hard-coded as default. You can change that in cvdv.c in the +Prepare() routine, or by using the ioctl Decoder_Set_Audiotype, e.g.: + +#include "cvdvext.h" + +main() +{ + struct decodercmd decmd; + + decmd.param1=audio_AC3; + decmd.cmd=Decoder_Set_Audiotype; + DecoderCommand(device,decmd); +... + +} + +In the directory testsuite are some example programs for using the driver. +I hope they are more or less self explanatory. Just use the --help option. + + +If you want the latest drivers apart from the release versions, use +the public CVS at linuxtv.org : http://linuxtv.org/cgi-bin/cvsweb.cgi/ + + +ZV-support +---------- + +You will faind patches for ZV support in the zv-diffs directory. The +ones with the version number for pcmcia-cs ar for the respective +versions of this package. The rest is for graphics chips or sound +chips, like the patches for the Neomagic graphics chip and YMF sound +chip submitted by Shigehiro Nomura. + +There now three module parameters that are all set to 1 (=on) but can +be set to off in /etc/pcmcia/config.opts +They are : "svhs" for switching the svhs output DAC on or off (0 or 1). + "composite" for switching the composite output DAC on or off. + "use_zv" for enabling zv output if you compiled with the + -DUSE_ZV setting in margi_cs.mk. + +E.g. +module "margi_cs" opts "use_zv=0" +turns off zv output. +or +module "margi_cs" opts "composite=0 svhs=0" +turns off the external outputs. + +WHO DO I BLAME/FLAME? +=== == = ============ + +Send comments, patches, free pizza to . + + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/README.CVS linux.19rc3-ac4/drivers/media/video/margi/README.CVS --- linux.19rc3/drivers/media/video/margi/README.CVS 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/README.CVS 2002-07-29 13:58:41.000000000 +0100 @@ -0,0 +1,13 @@ +1) unpack pcmcia_cs distribution + % tar zxvf pcmcia-cs-3.1.14.tar.gz + +2) cd pcmcia-cs-3.1.14 + % cvs co margi2 + +3) cp margi2/margi_cs.mk.MAIN margi_cs.mk + +4) For ZV support in pcmcia-cs use zv.diff. Remember, this is just the + first step to get to watching the output on your notebook's screen. + If you have pcmcia-cs versio >= 3.1.25 you need to use zv.diff.3.1.25. + The patches currently only work for the Rigoch 5c478 controller. + Anybody with information about ZV regarding graphic chips, please tell me. diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/ringbuffy.c linux.19rc3-ac4/drivers/media/video/margi/ringbuffy.c --- linux.19rc3/drivers/media/video/margi/ringbuffy.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/ringbuffy.c 2002-07-29 13:58:42.000000000 +0100 @@ -0,0 +1,212 @@ +/* + ringbuffy.c + + Copyright (C) Marcus Metzler for convergence integrated media. + + 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 __NO_VERSION__ + +#include "margi.h" +#include "ringbuffy.h" + +#ifndef outsl_ns +#define outsl_ns outsl +#endif + +int ring_init (ringbuffy *rbuf, long size) +{ + rbuf->size = 0; + rbuf->read_pos = 0; + rbuf->write_pos = 0; + + if (size > 0){ + if( !(rbuf->buffy = (char *) vmalloc(sizeof(char)*size)) ){ + MDEBUG(0, + "Not enough memory for ringbuffy\n"); + return -1; + } + } else { + MDEBUG(0, "Wrong size for ringbuffy\n"); + return -1; + } + + rbuf->size = size; + return 0; +} + + +void ring_destroy(ringbuffy *rbuf) +{ + if (rbuf->size){ + vfree(rbuf->buffy); + rbuf->buffy = NULL; + } + rbuf->size = 0; + rbuf->read_pos = 0; + rbuf->write_pos = 0; +} + + +int ring_write(ringbuffy *rbuf, const char *data, int count) +{ + + long diff, free, pos, rest; + + + if (count <=0 || !rbuf->buffy) return 0; + pos = rbuf->write_pos; + rest = rbuf->size - pos; + diff = rbuf->read_pos - pos; + free = (diff > 0) ? diff-4 : rbuf->size+diff-4; + + if ( free <= 0 ) return 0; + if ( free < count ) count = free; + + if (count >= rest){ + if(copy_from_user (rbuf->buffy+pos, data, rest)) + return -EFAULT; + if (count - rest) + if(copy_from_user(rbuf->buffy, data+rest, + count - rest)) + return -EFAULT; + rbuf->write_pos = count - rest; + } else { + copy_from_user (rbuf->buffy+pos, data, count); + rbuf->write_pos += count; + } + + return count; +} + + +int ring_writek(ringbuffy *rbuf, const char *data, int count) +{ + + long diff, free, pos, rest; + + + if (count <=0 || !rbuf->buffy) return 0; + pos = rbuf->write_pos; + rest = rbuf->size - pos; + diff = rbuf->read_pos - pos; + free = (diff > 0) ? diff-4 : rbuf->size+diff-4; + + if ( free <= 0 ) return 0; + if ( free < count ) count = free; + + if (count >= rest){ + if(memcpy(rbuf->buffy+pos, data, rest)) + return -EFAULT; + if (count - rest) + if(memcpy(rbuf->buffy, data+rest, + count - rest)) + return -EFAULT; + rbuf->write_pos = count - rest; + } else { + memcpy(rbuf->buffy+pos, data, count); + rbuf->write_pos += count; + } + + return count; +} + + + + +int ring_read(ringbuffy *rbuf, char *data, int count) +{ + + long diff, free, pos, rest; + + + if (count <=0 || !rbuf->buffy) return 0; + pos = rbuf->read_pos; + rest = rbuf->size - pos; + diff = rbuf->write_pos - pos; + free = (diff >= 0) ? diff : rbuf->size+diff; + + if ( free <= 0 ) return 0; + if ( free < count ) count = free; + + if ( count >= rest ){ + memcpy(data,rbuf->buffy+pos,rest); + if ( count - rest) + memcpy(data+rest,rbuf->buffy,count-rest); + rbuf->read_pos = count - rest; + } else { + memcpy(data,rbuf->buffy+pos,count); + rbuf->read_pos += count; + } + + return count; +} + +int ring_read_direct(ringbuffy *rbuf, int addr, int count) +{ + + long diff, free, pos, rest; + + + if (count <=0 || !rbuf->buffy) return 0; + pos = rbuf->read_pos; + rest = rbuf->size - pos; + diff = rbuf->write_pos - pos; + free = (diff >= 0) ? diff : rbuf->size+diff; + + if ( free <= 0 ) return 0; + if ( free < count ) count = free; + + if ( count >= rest ){ + outsl_ns(addr,rbuf->buffy+pos,rest/4); + if ( count - rest) + outsl_ns(addr,rbuf->buffy,(count-rest)/4); + rbuf->read_pos = count - rest; + } else { + outsl_ns(addr,rbuf->buffy+pos,count/4); + rbuf->read_pos += count; + } + + return count; +} + + +long ring_read_rest(ringbuffy *rbuf){ + long diff, free, pos; + + if (!rbuf->buffy) return 0; + pos = rbuf->read_pos; + diff = rbuf->write_pos - pos; + free = (diff >= 0) ? diff : rbuf->size+diff; + + return free; +} + +long ring_write_rest(ringbuffy *rbuf){ + long diff, free, pos; + + if (!rbuf->buffy) return 0; + pos = rbuf->write_pos; + diff = rbuf->read_pos - pos; + free = (diff > 0) ? diff-4 : rbuf->size+diff-4; + + return free; +} + +void ring_flush(ringbuffy *rbuf){ + rbuf->read_pos = 0; + rbuf->write_pos = 0; +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/ringbuffy.h linux.19rc3-ac4/drivers/media/video/margi/ringbuffy.h --- linux.19rc3/drivers/media/video/margi/ringbuffy.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/ringbuffy.h 2002-07-29 13:58:42.000000000 +0100 @@ -0,0 +1,43 @@ +/* + cvdv.h + + Copyright (C) Marcus Metzler for convergence integrated media. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef RINGBUFFY_H +#define RINGBUFFY_H + + +#define FULL_BUFFER -1000 +typedef struct ringbuffy{ + long read_pos; + long write_pos; + long size; + char *buffy; +} ringbuffy; + +int ring_init (ringbuffy *rbuf, long size); +void ring_destroy(ringbuffy *rbuf); +int ring_write(ringbuffy *rbuf, const char *data, int count); +int ring_writek(ringbuffy *rbuf, const char *data, int count); +int ring_read(ringbuffy *rbuf, char *data, int count); +long ring_read_rest(ringbuffy *rbuf); +long ring_write_rest(ringbuffy *rbuf); +void ring_flush(ringbuffy *rbuf); +int ring_read_direct(ringbuffy *rbuf, int addr, int count); + +#endif /* RINGBUFFY_H */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/spu.c linux.19rc3-ac4/drivers/media/video/margi/spu.c --- linux.19rc3/drivers/media/video/margi/spu.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/spu.c 2002-07-29 13:58:42.000000000 +0100 @@ -0,0 +1,103 @@ +/* + spu.c + + Copyright (C) Christian Wolff for convergence integrated media. + + 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 __NO_VERSION__ + +#include "spu.h" +#include "l64021.h" + +int DecoderHighlight(struct cvdv_cards *card, int active, u8 * coli, + u8 * btn_posi) +{ + int i; + if ((coli == NULL) || (btn_posi == NULL)) + return 1; + MDEBUG(0,": -- DecoderHighlight: col 0x%02X%02X, contr 0x%02X%02X, act %d, %d,%d - %d,%d\n", + coli[0], coli[1], coli[2], coli[3], active, + (((int) btn_posi[0] & 0x3F) << 4) | (btn_posi[1] >> 4), + (((int) btn_posi[3] & 0x3F) << 4) | (btn_posi[4] >> 4), + (((int) btn_posi[1] & 0x03) << 8) | btn_posi[2], + (((int) btn_posi[4] & 0x03) << 8) | btn_posi[5]); + //for (i=0; i<4; i++) DecoderWriteByte(card,0x1C0+i,coli[i]); +// DecoderWriteByte(card,0x1C0,coli[1]); +// DecoderWriteByte(card,0x1C1,coli[0]); +// DecoderWriteByte(card,0x1C2,coli[3]); +// DecoderWriteByte(card,0x1C3,coli[2]); + //for (i=0; i<6; i++) DecoderWriteByte(card,0x1C4+i,btn_posi[i]); +// for (i=0; i<6; i++) DecoderWriteByte(card,0x1C4+i,btn_posi[5-i]); + //if (active) DecoderSetByte(card,0x1BF,0x01); + //else DecoderDelByte(card,0x1BF,0x01); + + //for (i=0; i<4; i++) card->highlight[i]=coli[3-i]; + card->highlight[0] = coli[1]; + card->highlight[1] = coli[0]; + card->highlight[2] = coli[3]; + card->highlight[3] = coli[2]; + for (i = 0; i < 6; i++) + card->highlight[4 + i] = btn_posi[5 - i]; + card->highlight_valid = 1; + if (active) + DecoderWriteByte(card, 0x1BF, 0x01); + else + DecoderWriteByte(card, 0x1BF, 0x00); +//DecoderSetByte(card,0x135,0x02); // Enable SPU Mix +//DecoderWriteByte(card,0x1A0,0x01); // decode start, display on + return 0; +} + +int DecoderSPUPalette(struct cvdv_cards *card, int length, u8 * palette) +{ + int i; + MDEBUG(1,": -- DecoderSPUPalette: setting up %d bytes of SPU palette(Y,Cr,Cb):", length); + for (i = 0; i < (length / 3); i++) + MDEBUG(1," %d=(%d,%d,%d)", i, palette[i * 3],palette[i * 3 + 1], + palette[i * 3 + 2]); + MDEBUG(1,"\n"); + DecoderDelByte(card, 0x1A0, 0x01); // SPU decode stop + DecoderSetByte(card, 0x1A0, 0x10); + for (i = 0; i < length; i++) + DecoderWriteByte(card, 0x1BE, palette[i]); + DecoderSetByte(card, 0x1A0, 0x01); // SPU decode start + return 0; +} + +int DecoderSPUStream(struct cvdv_cards *card, int stream, int active) +{ + MDEBUG(1,": -- DecoderSPUStream: stream %d, active %d\n", stream, + active); + if (stream < 32) { + card->reg092 |= (0x20 | (stream & 0x1F)); // stream ID and select + DecoderWriteByte(card, 0x092, card->reg092); + DecoderMaskByte(card, 0x112, 0x20, 0x20); // chroma filter enable + DecoderMaskByte(card, 0x1A1, 0x0F, 0x00); // SPU timeout + DecoderWriteByte(card, 0x1BF, 0x00); // HighLight off + DecoderSetByte(card, 0x135, 0x02); // Enable SPU Mix + if (active) + DecoderWriteByte(card, 0x1A0, 0x01); // decode start, display on + else + DecoderWriteByte(card, 0x1A0, 0x05); // decode start, display off + } else { + DecoderWriteByte(card, 0x1A0, 0x04); // decode stop, display off + card->reg092 &= (~0x20); // stream select off + DecoderWriteByte(card, 0x092, card->reg092); + DecoderDelByte(card, 0x135, 0x02); // Disable SPU Mix + } + return 0; +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/spu.h linux.19rc3-ac4/drivers/media/video/margi/spu.h --- linux.19rc3/drivers/media/video/margi/spu.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/spu.h 2002-07-29 17:29:11.000000000 +0100 @@ -0,0 +1,33 @@ +/* + spu.h + + Copyright (C) Christian Wolff for convergence integrated media. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef CVDV_SPU_H +#define CVDV_SPU_H + +#include "cardbase.h" + +int DecoderHighlight(struct cvdv_cards *card, int active, u8 * coli, + u8 * btn_posi); + +int DecoderSPUPalette(struct cvdv_cards *card, int length, u8 * palette); + +int DecoderSPUStream(struct cvdv_cards *card, int stream, int active); + +#endif /* CVDV_SPU_H */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/streams.c linux.19rc3-ac4/drivers/media/video/margi/streams.c --- linux.19rc3/drivers/media/video/margi/streams.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/streams.c 2002-07-29 13:58:42.000000000 +0100 @@ -0,0 +1,444 @@ +/* + streams.c + + Copyright (C) Christian Wolff for convergence integrated media. + + 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 __NO_VERSION__ + +#include "streams.h" +#include "dram.h" +#include "l64021.h" +#include "video.h" +#include "audio.h" + +// Frees allocated channel buffers +int DecoderKillChannelBuffers(struct cvdv_cards *card) +{ + MDEBUG(1, ": -- DecoderKillChannelBuffers\n"); + DecoderStopDecode(card); + DRAMFree(card, card->VideoES); + card->VideoES = BLANK; + DRAMFree(card, card->AudioES); + card->AudioES = BLANK; + DRAMFree(card, card->VideoPES); + card->VideoPES = BLANK; + DRAMFree(card, card->DataDump); + card->DataDump = BLANK; + DRAMFree(card, card->AudioPES); + card->AudioPES = BLANK; + DRAMFree(card, card->NaviBank); + card->NaviBank = BLANK; + card->ChannelBuffersAllocated = 0; +// DecoderWriteWord( + return 0; +} + +// Allocates channel buffers +// All sizes in bytes, preferably multiple of 256 (will be rounded up otherwise) +int DecoderSetChannelBuffers(struct cvdv_cards *card, int VideoES, // Video ES Channel Buffer size, e.g. 229376 byte for NTSC + int AudioES, // Audio ES Channel Buffer size, 4096 byte + int VideoPES, // Video PES Header / SPU Channel Buffer size, 512 byte + int DataDump, // Data Dump Channel Buffer size, e.g. 80896 byte + int AudioPES, // Audio PES Header / System Channel Buffer size, 512 byte + int NaviBank) +{ // Navi Bank Channel Buffer size, 2048 byte +#define BUFFERSET(buf, id, adr,align) if (buf>0) {\ + if (buf&((1<buf=addr;\ + addr>>=align;\ + DecoderWriteByte(card,adr,addr&0xFF);\ + DecoderWriteByte(card,adr+1,(addr>>8)&(0x003F));\ + addr+=(buf>>align);\ + DecoderWriteByte(card,adr+2,(addr-1)&0xFF);\ + DecoderWriteByte(card,adr+3,((addr-1)>>8)&0x003F);\ +} + u32 addr; + MDEBUG(1, ": -- DecoderSetChannelBuffers\n"); + //DecoderStopDecode(card); + DecoderStopChannel(card); + VideoES >>= 1; // change to word sizes + AudioES >>= 1; + VideoPES >>= 1; + DataDump >>= 1; + AudioPES >>= 1; + NaviBank >>= 1; + if (card->ChannelBuffersAllocated) + DecoderKillChannelBuffers(card); + BUFFERSET(VideoES, "VideoES", 0x048, 7); + BUFFERSET(AudioES, "AudioES", 0x04C, 7); + BUFFERSET(VideoPES, "VideoPES", 0x050, 7); + BUFFERSET(DataDump, "DataDump", 0x054, 7); + BUFFERSET(AudioPES, "AudioPES", 0x058, 7); + BUFFERSET(NaviBank, "NaviBank", 0x05C, 7); + + card->VideoESSize = VideoES; + card->AudioESSize = AudioES; + card->VideoPESSize = VideoPES; + card->DataDumpSize = DataDump; + card->AudioPESSize = AudioPES; + card->NaviBankSize = NaviBank; + + DecoderWriteByte(card, 0x044, 0x7F); + DecoderWriteByte(card, 0x044, 0x01); + if (NaviBank) { + card->reg07B |= 0x10; // navi pack counter enable + DecoderWriteByte(card, 0x07B, card->reg07B); + //DecoderSetByte(card,0x07B,0x10); // navi pack counter enable + card->NaviPackAddress = + (DecoderReadWord(card, 0x05C) & 0x3FFF) << 7; + MDEBUG(4, ": navi bank init'ed: 0x%08X\n",card->NaviPackAddress); + } else { + card->reg07B &= ~0x10; // navi pack counter disable + DecoderWriteByte(card, 0x07B, card->reg07B); + //DecoderDelByte(card,0x07B,0x10); // navi pack counter disable + card->NaviPackAddress = 0; + } + card->ChannelBuffersAllocated = 1; +#undef BUFFERSET + return 0; +} + +//int DecoderReadFifo + +int DecoderUnPrepare(struct cvdv_cards *card) +{ + MDEBUG(0, ": -- DecoderUnPrepare\n"); + //DecoderStopDecode(card); + DecoderStopChannel(card); + DecoderKillChannelBuffers(card); + return 0; +} + +void DecoderPrepare(struct cvdv_cards *card) +{ + //VideoSetBackground(card,0,0,0,0); // Video on black + VideoSetBackground(card, 1, 0, 0, 0); // black + //VideoSetBackground(card,2,83,90,249); // Red + //VideoSetBackground(card,2,155,53,53); // Green + //VideoSetBackground(card,2,35,212,114); // Blue + //VideoSetBackground(card,2,4,128,128); // Black + //VideoSetBackground(card,3,155,53,53); // Video on Green + + //DecoderWriteByte(card,0x044,0x00); // Reset channel buffers on error +// DecoderWriteByte(card,0x044,0x01); // don't Reset channel buffers on error + + DecoderWriteByte(card, 0x040, 0x01); // Reset Aux FIFO + DecoderWriteByte(card, 0x041, 0x01); // Reset Data FIFO + //DecoderWriteByte(card,0x044,0x7E); // Reset channel buffers, Reset channel buffers on error + DecoderWriteByte(card, 0x044, 0x7F); // Reset channel buffers, don't Reset channel buffers on error +// udelay(100); +// DecoderWriteByte(card,0x040,0x00); // Reset Aux FIFO +// DecoderWriteByte(card,0x041,0x00); // Reset Data FIFO +// DecoderDelByte(card,0x044,0x7E); // Reset channel buffers +} + +// Selects audio type MPEG and sets stream ID's +// AID: -1=all MPEG, Audio Stream ID: 0..31 +// AExt: -1=unused, Audio Stream Extension ID: 0..31, only used if AType=5 +void DecoderSelectAudioID(struct cvdv_cards *card) +{ + int AID = card->setup.audioID; + int AExt = card->setup.audioIDext; + MDEBUG(1, ": -- SelectAudio %d %d\n", AID, AExt); + DecoderWriteByte(card, 0x07C, AExt & 0x1F); // Audio Stream Extension ID + card->reg08F = (card->reg08F & ~0x1F) | (AID & 0x1F); + DecoderWriteByte(card, 0x08F, card->reg08F); + //DecoderMaskByte(card,0x08F,0x1F,AID&0x1F); // Set Stream ID +} + +// AHeader: 0=No Headers, 1=first PTS/DTS header, 2=all headers, 3=All with PTS/DTS +// AType: 0=disable audio, 1=MPEG ID (MPEG 1), 2=Lin.PCM ID, 3=AC3 ID, 4=all MPEG (use only, if just one MPEG audio stream), 5=MPEG multichannel ID (MPEG 2) +// AID: -1=all MPEG, Audio Stream ID: 0..31 +// AExt: -1=unused, Audio Stream Extension ID: 0..31, only used if AType=5 +// IEC956: 0:MPEG/AC3 data on digital out 1:IEC956 data on digital S/PDIF out +void DecoderPrepareAudio(struct cvdv_cards *card) +{ + int AHeader = 2; + int AType = 3; + int AID = card->setup.audioID; + int AExt = card->setup.audioIDext; + int IEC956 = card->setup.SPDIFmode; + MDEBUG(1, ": -- PrepAudio %d %d %d %d %d\n", + AHeader, card->setup.audioselect, AID, AExt, IEC956); + switch (card->setup.audioselect) { + case audio_disable: + case audio_none: + case audio_SDDS: + AType = 0; + break; + case audio_MPEG: // MPEG Audio + AType = 1; + break; + case audio_MPEG_EXT: // MPEG Audio with extension stream + AType = 5; + break; + case audio_LPCM: // Linear Pulse Code Modulation LPCM + AType = 2; + break; + case audio_AC3: // AC-3 + AType = 3; + break; + case audio_DTS: // DTS + AType = 8; + break; + } + if (AType <= 0) { + card->reg08F = 0x00; // disable audio and discard all packets + DecoderWriteByte(card, 0x08F, card->reg08F); + //DecoderWriteByte(card,0x08F,0x00); // disable audio and discard all packets + //DecoderMaskByte(card,0x093,0xC3,0xC0); // write no headers + card->reg093 = (card->reg093 & ~0x03); // write no headers + DecoderWriteByte(card, 0x093, card->reg093); + } else { + AudioOpen(card); + DecoderMaskByte(card, 0x165, 0x1F, 0x00); // reset the register + if (AType == 8) { // DTS + card->reg090 |= 0x01; // DTS in Transport Private 1 Stream stored in AudioES channel buffer + DecoderWriteByte(card, 0x090, card->reg090); + //DecoderSetByte(card,0x090,0x01); // DTS in Transport Private 1 Stream stored in AudioES channel buffer + AudioSetMode(card, 0); + DecoderSetByte(card, 0x165, 0x01); + AudioStartFormat(card); + } else if (AType == 3) { // AC3 + card->reg090 |= 0x01; // AC3 in Transport Private 1 Stream stored in AudioES channel buffer + DecoderWriteByte(card, 0x090, card->reg090); + //DecoderSetByte(card,0x090,0x01); // AC3 in Transport Private 1 Stream stored in AudioES channel buffer + AudioSetMode(card, ((IEC956) ? 1 : 3)); + } else if (AType == 2) { // PCM + card->reg090 |= 0x01; // PCM in Transport Private 1 Stream stored in AudioES channel buffer + DecoderWriteByte(card, 0x090, card->reg090); + //DecoderSetByte(card,0x090,0x01); // PCM in Transport Private 1 Stream stored in AudioES channel buffer + AudioSetMode(card, 4); + } else { // MPEG + card->reg090 &= ~0x01; // MPEG Audio stored in AudioES channel buffer + DecoderWriteByte(card, 0x090, card->reg090); + //DecoderDelByte(card,0x090,0x01); // MPEG Audio stored in AudioES channel buffer + if (AID < 0) + AType = 4; + if (AExt >= 0) + AType = 5; + else + AExt = -1; + AudioSetMode(card, ((IEC956) ? 0 : 2)); + } + card->setup.audioID = AID; + card->setup.audioIDext = AExt; + DecoderSelectAudioID(card); + card->reg08F = (card->reg08F & ~0xE0) | ((AType & 0x07) << 5); // Set Stream Type + DecoderWriteByte(card, 0x08F, card->reg08F); + //DecoderMaskByte(card,0x08F,0xE0,(AType&0x07)<<5); // Set Stream Type + AudioSetVolume(card, 0xFF); // Set PCM scale to full volume + //DecoderMaskByte(card,0x093,0xC3,(AHeader&0x03)|0xC0); // write header select + card->reg093 = (card->reg093 & ~0x03) | (AHeader & 0x03); // write header select + DecoderWriteByte(card, 0x093, card->reg093); + // Mute the card and put it in play mode, then wait for the parameters to be parsed and un-mute if successful + //AudioMute(card,1); + if (AType > 0) { + AudioStartDecode(card); + //AudioSetPlayMode(card,MAUDIO_PLAY); + AudioSetPlayMode(card, MAUDIO_PAUSE); + } + //card->startingA=1; + } + card->lastaattr = 0; +} + +// VHeader: -1=disable Video, 0=No Headers, 1=first PTS/DTS header, 2=all headers, 3=All with PTS/DTS +// VID: -1=all MPEG, 0..15=Video Stream ID +void DecoderPrepareVideo(struct cvdv_cards *card) +{ + int VHeader = 3; + int VID = card->setup.videoID; + if (VHeader < 0) { + card->reg091 = 0x00; + DecoderWriteByte(card, 0x091, card->reg091); + //DecoderWriteByte(card,0x091,0x00); + } else { + if (VID < 0) { + card->reg091 = ((VHeader & 0x03) << 6) | (2 << 4); + DecoderWriteByte(card, 0x091, card->reg091); + //DecoderWriteByte(card,0x091,((VHeader&0x03)<<6)|(2<<4)); + } else { + card->reg091 = + ((VHeader & 0x03) << 6) | (1 << 4) | (VID & + 0x0F); + DecoderWriteByte(card, 0x091, card->reg091); + //DecoderWriteByte(card,0x091,((VHeader&0x03)<<6)|(1<<4)|(VID&0x0F)); + } + } +} + +// Prepare Decoder for Elementary Streams, Disable Preparser +int DecoderPrepareES(struct cvdv_cards *card) +{ + int i; + MDEBUG(1, ": -- PrepareES\n"); + //DecoderStopDecode(card); + +// DecoderWriteByte(card,0x05,0x00); + + DecoderMaskByte(card, 0x007, 0xCE, 0xC2 | (3 << 2)); // Stream Select: A/V Elementary Stream + MDEBUG(3, ": Int - A VideoES w/r addr: %08X %08X\n", + (DecoderReadByte(card,0x060)|(DecoderReadByte(card,0x061)<<8)| + (DecoderReadByte(card,0x062)<<16))<<2, + (DecoderReadByte(card,0x06C)|(DecoderReadByte(card,0x06D)<<8)| + (DecoderReadByte(card,0x06E)<<16))<<2); + // set the decoding buffers + card->reg093 = (card->reg093 & ~0xFC); // write no header + DecoderWriteByte(card, 0x093, card->reg093); + if ((i = DecoderSetChannelBuffers(card, 256000, 4096, 0, 0, 0, 0))) { + MDEBUG(0, ": SetDecoderBuffers failed for buffer at 0x%03X\n", i); + DecoderKillChannelBuffers(card); + return 1; + } + MDEBUG(3, ": Int - B VideoES w/r addr: %08X %08X\n", + (DecoderReadByte(card,0x060)|(DecoderReadByte(card,0x061)<<8)| + (DecoderReadByte(card,0x062)<<16))<<2, + (DecoderReadByte(card,0x06C)|(DecoderReadByte(card,0x06D)<<8)| + (DecoderReadByte(card,0x06E)<<16))<<2); + + MDEBUG(3, ": Int - C VideoES w/r addr: %08X %08X\n", + (DecoderReadByte(card,0x060)|(DecoderReadByte(card,0x061)<<8)| + (DecoderReadByte(card,0x062)<<16))<<2, + (DecoderReadByte(card,0x06C)|(DecoderReadByte(card,0x06D)<<8)| + (DecoderReadByte(card,0x06E)<<16))<<2); + +// DecoderStartChannel(card); +// DecoderStartDecode(card); + + MDEBUG(3, ": Int - D VideoES w/r addr: %08X %08X\n", + (DecoderReadByte(card,0x060)|(DecoderReadByte(card,0x061)<<8)| + (DecoderReadByte(card,0x062)<<16))<<2, + (DecoderReadByte(card,0x06C)|(DecoderReadByte(card,0x06D)<<8)| + (DecoderReadByte(card,0x06E)<<16))<<2); + + DecoderPrepare(card); + + return 0; +} + +// Prepare Decoder for Packetised Elementary Streams, set parameters of Preparser +int DecoderPreparePES(struct cvdv_cards *card) +{ + + // SPUID: -1=No SPU, 0..31=Display SPU of this ID + // DataDump: 0=disable DataDump, 1=process DataDump Substreams + // PackHeader: 0=write no headers, 1=write one header, 2=write all headers + // SysHeader: 0=write no headers, 1=write one header, 2=write all headers + // DSIHeader: 0=write no headers, 3=write PCI and DSI headers and packets + int i; + int SPUID = -1; + int DataDump = 0; + int PackHeader = 0; + int SysHeader = 0; + int DSIHeader = 0; + + MDEBUG(1, ": -- PreparePES\n"); + DecoderMaskByte(card, 0x007, 0xCE, 0xC2 | (0 << 2)); // Stream Select: A/V PES Packets + + if (SPUID < 0) + card->reg092 = 0; // Do we use SPU? + else + card->reg092 = 0x20 | (SPUID & 0x1F); + if (DataDump) + card->reg092 |= 0x40; // Do we use DataDump? + DecoderWriteByte(card, 0x092, card->reg092); + //DecoderMaskByte(card,0x093,0xFC,((DSIHeader&0x03)<<6)|((PackHeader&0x03)<<4)|((SysHeader&0x03)<<2)); + card->reg093 = + (card->reg093 & ~0xFC) | (((DSIHeader & 0x03) << 6) | + ((PackHeader & 0x03) << 4) | + ((SysHeader & 0x03) << 2)); + DecoderWriteByte(card, 0x093, card->reg093); + // set the decoding buffers + if ( + (i = + DecoderSetChannelBuffers(card, 256000, 4096, 512, 0, 512, + 0))) { + MDEBUG(0,": SetDecoderBuffers failed for buffer at 0x%03X\n", i); + DecoderKillChannelBuffers(card); + return 1; + } + + DecoderPrepare(card); + + return 0; +} + + +// Prepare Decoder for MPEG 1 Systems Streams or MPEG 2 Program Streams +// SPUID: -1:ignore, 0...15 SPU Substream ID +// DataDump: 0:disable data dump stream, 1:enable data dump stream +// PackHeader: 0:write no headers, 1:write one header, 2:write all headers, 3:always discard +// SysHeader: 0:always discard, 1:write one header, 2:write all headers, 3:always discard +// DSIHeader: 0:write no DSI or PCI headers, 3:write DSI and PCI headers + packets +// DVD: 0: normal MPEG-2 data, 1: DVD stream with navi pack data +int DecoderPreparePS(struct cvdv_cards *card, + int SPUID, int DataDump, + int PackHeader, int SysHeader, int DSIHeader, int DVD) +{ + int i=0; + MDEBUG(1, ": -- PreparePS %s\n", ((DVD) ? "DVD" : "")); + //DecoderStopDecode(card); + DecoderMaskByte(card, 0x007, 0xCE, 0xC2 | (1 << 2)); // Stream Select: MPEG1 System / MPEG2 Program Stream + + if (SPUID < 0) + card->reg092 = 0; // Do we use SPU? + else + card->reg092 = 0x20 | (SPUID & 0x1F); + if (DataDump) + card->reg092 |= 0x40; // Do we use DataDump? + DecoderWriteByte(card, 0x092, card->reg092); + //DecoderMaskByte(card,0x093,0xFC,((DSIHeader&0x03)<<6)|((PackHeader&0x03)<<4)|((SysHeader&0x03)<<2)); + card->reg093 = + (card->reg093 & ~0xFC) | (((DSIHeader & 0x03) << 6) | + ((PackHeader & 0x03) << 4) | + ((SysHeader & 0x03) << 2)); + DecoderWriteByte(card, 0x093, card->reg093); + // set the decoding buffers + if (DVD) { // do we need SPU-, navi- and datadump-buffers? + + // if(card->videomode == NTSC) + i = DecoderSetChannelBuffers(card, 340000, 32768, 32768, 0, + 512,4096) ; + //else + // i = DecoderSetChannelBuffers(card, 291878, 16384, 512, 0, + // 512,0) ; + + if (i) { + MDEBUG(0,": SetDecoderBuffers failed for buffer at 0x%03X\n", i); + DecoderKillChannelBuffers(card); + return 1; + } + + } else { // normal PS + if ( + (i = + DecoderSetChannelBuffers(card, 340000, 32768, 512, + 0, 512, 0))) { + MDEBUG(0,": SetDecoderBuffers failed for buffer at 0x%03X\n", i); + DecoderKillChannelBuffers(card); + return 1; + } + } + + DecoderPrepare(card); + + return 0; +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/streams.h linux.19rc3-ac4/drivers/media/video/margi/streams.h --- linux.19rc3/drivers/media/video/margi/streams.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/streams.h 2002-07-29 17:29:11.000000000 +0100 @@ -0,0 +1,79 @@ +/* + streams.h + + Copyright (C) Christian Wolff for convergence integrated media. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef CVDV_STREAMS_H +#define CVDV_STREAMS_H + +#include "cardbase.h" + +// Frees allocated channel buffers +int DecoderKillChannelBuffers(struct cvdv_cards *card); + +// Allocates channel buffers +// All sizes in bytes, preferably multiple of 256 (will be rounded up otherwise) +int DecoderSetChannelBuffers(struct cvdv_cards *card, int VideoES, // Video ES Channel Buffer size, e.g. 229376 byte for NTSC + int AudioES, // Audio ES Channel Buffer size, 4096 byte + int VideoPES, // Video PES Header / SPU Channel Buffer size, 512 byte + int DataDump, // Data Dump Channel Buffer size, e.g. 80896 byte + int AudioPES, // Audio PES Header / System Channel Buffer size, 512 byte + int NaviBank); // Navi Bank Channel Buffer size, 2048 byte + +//int DecoderReadFifo + +int DecoderUnPrepare(struct cvdv_cards *card); + +void DecoderPrepare(struct cvdv_cards *card); + +// Selects audio type MPEG and sets stream ID's +// AID: -1=all MPEG, Audio Stream ID: 0..31 +// AExt: -1=unused, Audio Stream Extension ID: 0..31, only used if AType=5 +void DecoderSelectAudioID(struct cvdv_cards *card); + +// AHeader: 0=No Headers, 1=first PTS/DTS header, 2=all headers, 3=All with PTS/DTS +// AType: 0=disable audio, 1=MPEG ID (MPEG 1), 2=Lin.PCM ID, 3=AC3 ID, 4=all MPEG (use only, if just one MPEG audio stream), 5=MPEG multichannel ID (MPEG 2) +// AID: -1=all MPEG, Audio Stream ID: 0..31 +// AExt: -1=unused, Audio Stream Extension ID: 0..31, only used if AType=5 +// IEC956: 0:MPEG/AC3 data on digital out 1:IEC956 data on digital S/PDIF out +void DecoderPrepareAudio(struct cvdv_cards *card); + +// VHeader: -1=disable Video, 0=No Headers, 1=first PTS/DTS header, 2=all headers, 3=All with PTS/DTS +// VID: -1=all MPEG, 0..15=Video Stream ID +void DecoderPrepareVideo(struct cvdv_cards *card); + +// Prepare Decoder for Elementary Streams, Disable Preparser +int DecoderPrepareES(struct cvdv_cards *card); + +// Prepare Decoder for Packetised Elementary Streams, set parameters of Preparser +int DecoderPreparePES(struct cvdv_cards *card); + + +// Prepare Decoder for MPEG 1 Systems Streams or MPEG 2 Program Streams +// SPUID: -1:ignore, 0...15 SPU Substream ID +// DataDump: 0:disable data dump stream, 1:enable data dump stream +// PackHeader: 0:write no headers, 1:write one header, 2:write all headers, 3:always discard +// SysHeaader: 0:always discard, 1:write one header, 2:write all headers, 3:always discard +// DSIHeader: 0:write no DSI or PCI headers, 3:write DSI and PCI headers + packets +// DVD: 0: normal MPEG-2 data, 1: DVD stream with navi pack data +int DecoderPreparePS(struct cvdv_cards *card, + int SPUID, int DataDump, + int PackHeader, int SysHeader, int DSIHeader, + int DVD); + +#endif /* CVDV_STREAMS_H */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/video.c linux.19rc3-ac4/drivers/media/video/margi/video.c --- linux.19rc3/drivers/media/video/margi/video.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/video.c 2002-07-29 13:58:42.000000000 +0100 @@ -0,0 +1,525 @@ +/* + video.c + + Copyright (C) Christian Wolff for convergence integrated media. + + 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. +*/ + +// +// Video Decoder +// +#define __NO_VERSION__ + +#include "video.h" +#include "l64021.h" +#include "dram.h" + +// Set the background of the OSD and SPU and it's color +// mode=0: Video on Black +// mode=1: Black +// mode=2: Selected Color +// mode=3: Video on Selected Color +void VideoSetBackground(struct cvdv_cards *card, int mode, u8 Y, u8 Cb, + u8 Cr) +{ + DecoderWriteByte(card, 0x10A, Y); + DecoderWriteByte(card, 0x10B, Cb); + DecoderWriteByte(card, 0x10C, Cr); + DecoderMaskByte(card, 0x109, 0xC0, mode << 6); +} + + +int DecoderStartDecode(struct cvdv_cards *card) +{ + DecoderSetByte(card, 0x0F6, 0x01); +#ifdef DVB + if (card->audiostate.AVSyncState) +#endif + card->videosync = 1; + return 0; +} + +int DecoderStopDecode(struct cvdv_cards *card) +{ + DecoderDelByte(card, 0x0F6, 0x01); + card->videosync = 0; + return 0; +} + +// Sets Display Override (Still Image Display) to Frame Buffer at specified addresses, +// addresses are 16 bit, in 64 byte resolution +// mode: 0=off, 1=Frame, 2=Field +// width: width of the still picture in 8 pixel units +int DecoderStillImageDisplay(struct cvdv_cards *card, int mode, int width, + u16 LumaAddr, u16 ChromaAddr) +{ + DecoderStopDecode(card); + DecoderWriteWord(card, 0x11D, LumaAddr); + DecoderWriteWord(card, 0x11F, ChromaAddr); + DecoderWriteByte(card, 0x11B, width & 0x7F); + DecoderMaskByte(card, 0x109, 0x30, (mode & 3) << 4); // Display Override Mode + return 0; +} + +// Frees allocated frame buffers +int DecoderKillFrameBuffers(struct cvdv_cards *card) +{ + MDEBUG(1, ": -- DecoderKillFrameBuffers\n"); + DecoderStopDecode(card); + DRAMFree(card, card->FrameStoreLuma1); + card->FrameStoreLuma1 = BLANK; + DRAMFree(card, card->FrameStoreChroma1); + card->FrameStoreChroma1 = BLANK; + DRAMFree(card, card->FrameStoreLuma2); + card->FrameStoreLuma2 = BLANK; + DRAMFree(card, card->FrameStoreChroma2); + card->FrameStoreChroma2 = BLANK; + DRAMFree(card, card->FrameStoreLumaB); + card->FrameStoreLumaB = BLANK; + DRAMFree(card, card->FrameStoreChromaB); + card->FrameStoreChromaB = BLANK; + card->FrameBuffersAllocated = 0; +// DecoderWriteWord( + return 0; +} + +int DecoderSetFrameBuffers(struct cvdv_cards *card, int lines, // number of lines of the decoded MPEG + int TwoFrames, // 1 if no B-Frames are present in the video stream, thus allowing only 2 framestores + int RMM) // 1 if RMM +{ +#define SEGMENTS 44 // 40..54 for PAL, 44 recommended +#define BUFFERSET(buf,adr,align) if (buf>0) {\ + if (buf&((1<buf=addr;\ + addr>>=align;\ + DecoderWriteByte(card,adr,addr&0xFF);\ + DecoderWriteByte(card,adr+1,(addr>>8)&(0x00FF));\ +} + u32 addr; + int pixel, byteperline; // visible pixel per video line, same for PAL and NTSC + int FrameStoreLuma1, FrameStoreChroma1, + FrameStoreLuma2, FrameStoreChroma2, + FrameStoreLumaB, FrameStoreChromaB; + MDEBUG(1, ": -- DecoderSetFrameBuffers\n"); + DecoderStopDecode(card); + //DecoderStopChannel(card); + //lines=((CCIR601Lines(card->videomode)==625)?576:480); + byteperline = (DecoderReadByte(card, 0x116) & 0x7F) * 8; // main 64-bit reads per line + pixel = byteperline * lines; + FrameStoreLuma1 = FrameStoreLuma2 = FrameStoreLumaB = pixel >> 1; // 8 bit luma per pixel in words + FrameStoreChroma1 = FrameStoreChroma2 = FrameStoreChromaB = + pixel >> 2; // 8+8 bit chroma every 2nd pixel every 2nd line + if (card->FrameBuffersAllocated) + DecoderKillFrameBuffers(card); + BUFFERSET(FrameStoreLuma1, 0x0E0, 5); // Anchor Frame Store 1 + BUFFERSET(FrameStoreChroma1, 0x0E2, 5); + BUFFERSET(FrameStoreLuma2, 0x0E4, 5); // Anchor Frame Store 2 + BUFFERSET(FrameStoreChroma2, 0x0E6, 5); + if (TwoFrames) { + DecoderDelByte(card, 0x0F8, 0x01); + } else { +// if (CCIR601Lines(card->videomode)==525) { // Normal Mode, NTSC + if (!RMM) { // Normal Mode, NTSC + BUFFERSET(FrameStoreLumaB, 0x0E8, 5); // B Frame Store + BUFFERSET(FrameStoreChromaB, 0x0EA, 5); + DecoderDelByte(card, 0x0F8, 0x01); + } else { // Reduced Memory Mode, PAL + // 44 segments with 8 lines each (8 bit luma + 4 bit chroma) + // only display modes 4-8, 10, and 11 are allowed + FrameStoreLumaB = + (8 * byteperline * SEGMENTS) >> 1; + FrameStoreChromaB = + (4 * byteperline * SEGMENTS) >> 1; + BUFFERSET(FrameStoreLumaB, 0x0E8, 5); // B Frame Store + BUFFERSET(FrameStoreChromaB, 0x0EA, 5); + DecoderWriteByte(card, 0x121, SEGMENTS << 1); // Number of segments + DecoderSetByte(card, 0x0F8, 0x01); + } + } + card->FrameBuffersAllocated = 1; +#undef SEGMENTS +#undef BUFFERSET + return 0; +} + +// returns size of the Video ES Buffer in bytes or 0=error +u32 DecoderGetVideoESSize(struct cvdv_cards * card) +{ + if (!card->ChannelBuffersAllocated) + return 0; // buffer not initialised + return (u32) ((DecoderReadWord(card, 0x04A) & 0x3FFF) - + (DecoderReadWord(card, 0x048) & 0x3FFF)) * 256; // bytes +} + +// returns level of fullness in bytes +u32 DecoderGetVideoESLevel(struct cvdv_cards * card) +{ + u32 items; + items = DecoderReadByte(card, 0x086); + items |= ((DecoderReadWord(card, 0x087) & 0x07FF) << 8); + items *= 8; // 64 bit per item + return items; +} + +// pics=0 --> items=bytes +// pics=1 --> items=pictures +void DecoderSetVideoPanic(struct cvdv_cards *card, int pics, int items) +{ + if (pics < 0) { + DecoderMaskByte(card, 0x045, 0x18, 0x00 << 3); // disable panic mode + } else { + if (pics) { + DecoderWriteMWord(card, 0x086, items & 0x0003FFFF); + DecoderMaskByte(card, 0x045, 0x18, 0x02 << 3); // set panic mode to "number of pictures" in VideoES + } else { + DecoderWriteMWord(card, 0x086, + (items / 8) & 0x0003FFFF); + DecoderMaskByte(card, 0x045, 0x18, 0x01 << 3); // set panic mode to "number of 8-byte-frames" in VideoES + } + } +} + +int DecoderClose(struct cvdv_cards *card) +{ + if (card->DecoderOpen) { + MDEBUG(1, ": -- DecoderClose\n"); + DecoderStopDecode(card); + DecoderKillFrameBuffers(card); + card->DecoderOpen = 0; + card->lastvattr = 0; + return 0; + } else + return 1; +} + +// returns 0 on success, 1 on "picture size too big", 2 on "out of DRAM memory" +int DecoderOpen(struct cvdv_cards *card, int x, int y, // size of the decoded MPEG picture + int aspect, // pixel or picture aspect ratio of the MPEG picture: 1=square pixel 2=3:4 3=9:16 4=1:2.21 + int Field, // 0:Frame (interlaced, MPEG-2) , 1:Field (non-interlaced, MPEG-1) structure + int Letterbox, // 0:PanScan (4:3), 1:letterbox (16:9, 8:3) picture ratio + int RMM) // 1:use ReducedMemoryMode +{ + int mode, // Display Mode + i, factor, // zoom factor + top, bottom, left, right, width, height, newwidth, newheight, // screen size + vaspx, vaspy, // output video pixel aspect ratio + paspx, paspy, // input picture pixel aspect ratio + SIF; // 0:Full (480/576 lines, MPEG-2), 1:SIF (half, 240/288 lines, MPEG-1) resolution + + MDEBUG(1, ": -- DecoderOpen x:%d y:%d asp:%d field:%d lt:%d rmm:%d\n", + x, y, aspect, Field, Letterbox, RMM); + if ((x <= 0) || (y <= 0)) + return 4; // picture too small +//if (card->DecoderOpen) return 3; + DecoderStopDecode(card); + DecoderClose(card); // closes only, if already open + vaspy = 11; + vaspx = ((CCIR601Lines(card->videomode) == 525) ? 10 : 12); // screen pixel aspect ratio + // note: this aspect ratio applies to 704 pixel width, but the card's default is 720, wich is not 3:4 picture aspect ratio anymore!? + i = ((x == 720) ? 704 : x); // 720 wide is overscan of 704 wide + switch (aspect) { // MPEG data pixel aspect ratio + case 1: + paspx = 1; + paspy = 1; + break; + default: + case 2: + paspx = 4 * y; + paspy = 3 * i; + break; + case 3: + paspx = 16 * y; + paspy = 9 * i; + break; + case 4: + paspx = 221 * y; + paspy = 100 * i; + break; + } + top = + DecoderReadByte(card, + 0x129) | ((DecoderReadByte(card, 0x12B) & 0x07) + << 8); // current Start- and End Column + bottom = + DecoderReadByte(card, + 0x12A) | ((DecoderReadByte(card, 0x12B) & 0x70) + << 4); + height = (bottom - top + 1) * 2; // screen (frame) height + left = + DecoderReadByte(card, + 0x12C) | ((DecoderReadByte(card, 0x12E) & 0x07) + << 8); // current Start- and End Row + right = + DecoderReadByte(card, + 0x12D) | ((DecoderReadByte(card, 0x12E) & 0x70) + << 4); + width = (right - left + 1) / 2; // screen width, 2 clocks = 1 pixel + + if (RMM) + DecoderSetByte(card, 0x0F8, 0x01); + else + DecoderDelByte(card, 0x0F8, 0x01); + + DecoderWriteByte(card, 0x0EF, 0x08); + + //if (x>width) { // Is the picture too wide for the screen? + // DecoderSetByte(card,0x112,0x40); // Horiz. 2:1 Filter enable + // x/=2; + //} else { + DecoderDelByte(card, 0x112, 0x40); // Horiz. 2:1 Filter disable + //} + + + + + if (1 /*Letterbox */ ) { // Fit to width, reduce height + newwidth = (x * vaspy * paspx / (paspy * vaspx)); // width in right aspect ratio + if (newwidth <= 360) { // less then about half the screen size? + SIF = 1; + newwidth *= 2; + } else { + SIF = 0; + } + if ((newwidth == 704) || (newwidth == 720)) + width = newwidth; // standard sizes? + newheight = + (y * vaspx * paspy / (paspx * vaspy)) * width / x; + factor = newheight * 100 / y; + printk(KERN_INFO LOGNAME + ": Decoder Open: Display size %d x %d, Picture size %d x %d, Demanded size: %d x %d, factor %d\n", + width, height, x, y, newwidth, newheight, factor); + // 16:9 Letterbox + if ((aspect == 3) + || ((aspect == 0) + && (((factor >= 65) && (factor <= 80)) + || ((factor >= 140) && (factor <= 160))))) { + if (SIF) { // height * 1.5, SIF Letterbox + if (RMM) + return 1; // not supported! + height = (y * 3) / 2 - 2; + mode = 3; + } else { // height * 0.75, 16:9 Letterbox + height = (y * 3) / 4 - 2; + mode = 8; + } + // 2.21:1 Letterbox + } else if ((aspect == 4) + || ((aspect == 0) + && (((factor >= 45) && (factor <= 60)) + || (SIF && ((factor >= 90) + && (factor <= 110)))))) { + if (SIF) { // height * 1 + height = y; + mode = 5; + } else { // height / 2 + height = y / 2; + mode = 11; + } + // 3:4 aspect ratio + } else { + if (SIF) { + height = y * 2; + mode = ((Field && ~RMM) ? 9 : 10); + } else if (newwidth > 720) { // picture too wide, scale down to 3/4 + height = (y * 3) / 4; + mode = 8; + } else { + height = y; + mode = ((Field) ? 7 : 5); +// mode=((Field)?5:7); + } + } + width = (x * vaspy * paspx / (paspy * vaspx)) * height / y; + if (x < width) { // does the picture needs a horizontal blow-up? + DecoderWriteByte(card, 0x115, + ((x * 256 + width - 1) / width) & 0xFF); // Horiz.Filter scale, x/width*256, rounded up + DecoderSetByte(card, 0x114, 0x02); // Horiz.Filter enable + } else if (x == width) { + DecoderWriteByte(card, 0x115, 0); // 1:1 scale + DecoderDelByte(card, 0x114, 0x02); // Horiz.Filter disable + } else if (x <= 720) { + width = x; + DecoderWriteByte(card, 0x115, 0); // 1:1 scale + DecoderDelByte(card, 0x114, 0x02); // Horiz.Filter disable + } else { // picture is more than twice the screen width. sigh. + return 1; + } + } else { // Pan-Scan, fit height to maximum + DecoderSetByte(card, 0x117, 0x40); // pan-scan from bitstream +//TODO + newwidth = (x * vaspy * paspx / (paspy * vaspx)); // width in right aspect ratio + newheight = y; + if (newheight <= 288) { // less then about half the screen size? + SIF = 1; + newheight *= 2; + } else { + SIF = 0; + } + if ((newwidth == 704) || (newwidth == 720)) + width = newwidth; // standard sizes? + //newheight=(y*vaspx*paspy/(paspx*vaspy))*width/x; + factor = newheight * 100 / y; + printk(KERN_INFO LOGNAME + ": Decoder Open: Display size %d x %d, Picture size %d x %d, Demanded size: %d x %d, factor %d\n", + width, height, x, y, newwidth, newheight, factor); + if (aspect == 3) { // 16:9 Letterbox + if (SIF) { // height * 1.5, SIF Letterbox + if (RMM) + return 1; // not supported! + height = (y * 3) / 2; + mode = 3; + } else { // height * 0.75, 16:9 Letterbox + height = (y * 3) / 4; + mode = 8; + } + } else if (aspect == 4) { // 2.21:1 Letterbox + if (SIF) { // height * 1 + height = y; + mode = 5; + } else { // height / 2 + height = y / 2; + mode = 11; + } + } else if (aspect == 2) { // 3:4 aspect ratio + if (SIF) { + height = y * 2; + mode = ((Field && ~RMM) ? 9 : 10); + } else if (newwidth > 720) { // picture too wide, scale down to 3/4 + height = (y * 3) / 4; + mode = 8; + } else { + height = y; + mode = ((Field) ? 7 : 5); +// mode=((Field)?5:7); + } + } + width = (x * vaspy * paspx / (paspy * vaspx)) * height / y; + if (x < width) { // does the picture needs a horizontal blow-up? + DecoderWriteByte(card, 0x115, + ((x * 256 + width - 1) / width) & 0xFF); // Horiz.Filter scale, x/width*256, rounded up + DecoderSetByte(card, 0x114, 0x02); // Horiz.Filter enable + } else if (x == width) { + DecoderWriteByte(card, 0x115, 0); // 1:1 scale + DecoderDelByte(card, 0x114, 0x02); // Horiz.Filter disable + } else if (x <= 720) { + width = x; + DecoderWriteByte(card, 0x115, 0); // 1:1 scale + DecoderDelByte(card, 0x114, 0x02); // Horiz.Filter disable + } else { // picture is more than twice the screen width. sigh. + return 1; + } + } + printk(KERN_INFO LOGNAME + ": Decoder Open: Display size %d x %d, Picture size %d x %d Mode: %d\n", + width, height, x, y, mode); + + // calculate new picture start- and end rows and columns + height /= 2; // convert back to field height + top += ((bottom - top + 1 - height) / 2); + if (top < 0) + top = 0; + bottom = top + height - 1; + width *= 2; // convert back to clocks + left += ((right - left + 1 - width) / 2); + if (left < 0) + left = 0; + right = left + width - 1; + DecoderWriteByte(card, 0x12C, left & 0xFF); // Start- and End Column + DecoderWriteByte(card, 0x12D, right & 0xFF); + DecoderWriteByte(card, 0x12E, + ((right >> 4) & 0x70) | ((left >> 8) & 0x07)); + DecoderWriteByte(card, 0x129, top & 0xFF); // Start- and End Row + DecoderWriteByte(card, 0x12A, bottom & 0xFF); + DecoderWriteByte(card, 0x12b, + ((bottom >> 4) & 0x70) | ((top >> 8) & 0x07)); + + DecoderWriteByte(card, 0x116, ((x + 7) / 8) & 0x7F); // Main Reads per Line + + // set the new mode + DecoderMaskByte(card, 0x114, 0x78, (mode & 0x0F) << 3); + + MDEBUG(3,": Decoder Open: top/bottom/width / left/right/height / main reads %d/%d/%d / %d/%d/%d / %d\n",top,bottom,width,left,right,height,((x+7)/8)&0x7F); + + // set the frame store buffers + if ((i = DecoderSetFrameBuffers(card, y, 0, RMM))) { + MDEBUG(0,": SetFrameBuffers failed for buffer at 0x%03X\n",i); + DecoderKillFrameBuffers(card); + return 2; + } + + card->lastvattr = 0; + card->DecoderOpen = 1; + return 0; +} + +// displays a still image, whose pixel data is in luma and chroma +int DecoderShowStill(struct cvdv_cards *card, int width, int height, + u8 * luma, u8 * chroma) +{ + u16 addr; + DecoderOpen(card, width, height, + (((width == 320) || (width == 640) || (width == 384) + || (width == 768)) ? 1 : 2), + ((height < 313) ? 1 : 0), 1, 0); + addr = + ((DecoderReadWord(card, 0x11D) == DecoderReadWord(card, 0x0E0)) + ? 0x0E4 : 0x0E0); // choose invisible frame + DRAMWriteByte(card, DecoderReadWord(card, addr) << 5, + width * height, luma, 1); + DRAMWriteByte(card, DecoderReadWord(card, addr + 2) << 5, + width * height / 2, chroma, 1); + DecoderStillImageDisplay(card, ((height < 313) ? 2 : 1), + DecoderReadByte(card, 0x116) & 0x7F, + DecoderReadWord(card, addr), + DecoderReadWord(card, addr + 2)); + VideoSetBackground(card, 0, 0, 0, 0); // video on black + return 0; +} + +// TODO: untested, probably won't work (have to use "main reads per line" instead of width on SIF) +int DecoderGetStill(struct cvdv_cards *card, int *width, int *height, + u8 * luma, u8 * chroma) +{ + int framebuffer; + if (card->DecoderOpen) { + //*width=((DecoderReadByte(card,0x12D)|((DecoderReadByte(card,0x12E)&0x70)<<4))-(DecoderReadByte(card,0x12C)|((DecoderReadByte(card,0x12E)&0x07)<<8))+1)/2; // screen width, 2 clocks = 1 pixel + *width = DecoderReadByte(card, 0x116) * 8; + *height = + ((DecoderReadByte + (card, + 0x12A) | ((DecoderReadByte(card, 0x12B) & 0x70) << + 4)) - + (DecoderReadByte(card, 0x129) | + ((DecoderReadByte(card, 0x12B) & 0x07) << 8)) + 1) * 2; // screen (frame) height + if ((luma != NULL) && (chroma != NULL)) { + framebuffer = + (((DecoderReadByte(card, 0x0EE) & 0x0C) == 1) ? + 0x0E4 : 0x0E0); + DRAMReadByte(card, + DecoderReadWord(card, + framebuffer) << 5, + (*width) * (*height), luma, 1); + DRAMReadByte(card, + DecoderReadWord(card, + framebuffer + 2) << 5, + (*width) * (*height) / 2, chroma, 1); + } + return 0; + } else + return 1; +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/media/video/margi/video.h linux.19rc3-ac4/drivers/media/video/margi/video.h --- linux.19rc3/drivers/media/video/margi/video.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/media/video/margi/video.h 2002-07-29 17:29:11.000000000 +0100 @@ -0,0 +1,85 @@ +/* + video.h + + Copyright (C) Christian Wolff for convergence integrated media. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef CVDV_VIDEO_H +#define CVDV_VIDEO_H + + // + // Video Decoder +// + +#include "cardbase.h" + +// Set the background of the OSD and SPU and it's color +// mode=0: Video on Black +// mode=1: Black +// mode=2: Selected Color +// mode=3: Video on Selected Color +void VideoSetBackground(struct cvdv_cards *card, int mode, u8 Y, u8 Cb, + u8 Cr); + + +int DecoderStartDecode(struct cvdv_cards *card); + +int DecoderStopDecode(struct cvdv_cards *card); + +// Sets Display Override (Still Image Display) to Frame Buffer at specified addresses, +// addresses are 16 bit, in 64 byte resolution +// mode: 0=off, 1=Frame, 2=Field +// width: width of the still picture in 8 pixel units +int DecoderStillImageDisplay(struct cvdv_cards *card, int mode, int width, + u16 LumaAddr, u16 ChromaAddr); + +// Frees allocated frame buffers +int DecoderKillFrameBuffers(struct cvdv_cards *card); + +int DecoderSetFrameBuffers(struct cvdv_cards *card, int lines, // number of lines of the decoded MPEG + int TwoFrames, // 1 if no B-Frames are present in the video stream, thus allowing only 2 framestores + int RMM); // 1 if RMM + +// returns size of the Video ES Buffer in bytes or 0=error +u32 DecoderGetVideoESSize(struct cvdv_cards *card); + +// returns level of fullness in bytes +u32 DecoderGetVideoESLevel(struct cvdv_cards *card); + +// pics=0 --> items=bytes +// pics=1 --> items=pictures +void DecoderSetVideoPanic(struct cvdv_cards *card, int pics, int items); + +int DecoderClose(struct cvdv_cards *card); + +// returns 0 on success, 1 on "picture size too big", 2 on "out of DRAM memory" +int DecoderOpen(struct cvdv_cards *card, int x, int y, // size of the decoded MPEG picture + int aspect, // pixel or picture aspect ratio of the MPEG picture: 1=square pixel 2=3:4 3=9:16 4=1:2.21 + int Field, // 0:Frame (interlaced, MPEG-2) , 1:Field (non-interlaced, MPEG-1) structure + int Letterbox, // 0:PanScan (4:3), 1:letterbox (16:9, 8:3) picture ratio // TODO, ignored for now + int RMM // 1:use ReducedMemoryMode + ); + +// displays a still image, whose pixel data is in luma and chroma +int DecoderShowStill(struct cvdv_cards *card, int width, int height, + u8 * luma, u8 * chroma); + +// TODO: untested, probably won't work (have to use "main reads per line" instead of width on SIF) +int DecoderGetStill(struct cvdv_cards *card, int *width, int *height, + u8 * luma, u8 * chroma); + +#endif /* CVDV_VIDEO_H */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/message/fusion/linux_compat.h linux.19rc3-ac4/drivers/message/fusion/linux_compat.h --- linux.19rc3/drivers/message/fusion/linux_compat.h 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/message/fusion/linux_compat.h 2002-07-29 17:29:11.000000000 +0100 @@ -15,6 +15,26 @@ #define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0) #endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) +#define SET_NICE(current,x) do {(current)->nice = (x);} while (0) +#else +#define SET_NICE(current,x) +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) +#define pci_enable_device(pdev) (0) +#define SCSI_DATA_UNKNOWN 0 +#define SCSI_DATA_WRITE 1 +#define SCSI_DATA_READ 2 +#define SCSI_DATA_NONE 3 +#endif + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4) +#define pci_set_dma_mask(pdev, mask) (0) +#define scsi_set_pci_device(sh, pdev) (0) +#endif + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) # if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18) typedef unsigned int dma_addr_t; @@ -210,6 +230,27 @@ /*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ #endif /* PCI_DMA_BIDIRECTIONAL */ +/* + * With the new command queuing code in the SCSI mid-layer we no longer have + * to hold the io_request_lock spin lock when calling the scsi_done routine. + * For now we only do this with the 2.5.1 kernel or newer. + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,1) + #define MPT_HOST_LOCK(flags) + #define MPT_HOST_UNLOCK(flags) +#else + #define MPT_HOST_LOCK(flags) \ + spin_lock_irqsave(&io_request_lock, flags) + #define MPT_HOST_UNLOCK(flags) \ + spin_unlock_irqrestore(&io_request_lock, flags) +#endif + +/* + * We use our new error handling code if the kernel version is 2.5.1 or newer. + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,1) + #define MPT_SCSI_USE_NEW_EH +#endif /*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ #endif /* _LINUX_COMPAT_H */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/message/fusion/Makefile linux.19rc3-ac4/drivers/message/fusion/Makefile --- linux.19rc3/drivers/message/fusion/Makefile 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/message/fusion/Makefile 2002-07-29 13:58:42.000000000 +0100 @@ -36,9 +36,9 @@ #CFLAGS_mptbase.o += -DMPT_DEBUG_IRQ # # For mptscsih: -#CFLAGS_mptscsih.o += -DMPT_SCSI_USE_NEW_EH #CFLAGS_mptscsih.o += -DMPT_DEBUG_SCANDV #CFLAGS_mptscsih.o += -DMPT_DEBUG_RESET +#CFLAGS_mptscsih.o += -DMPT_DEBUG_NEH # # For mptctl: #CFLAGS_mptctl.o += -DMPT_DEBUG_IOCTL diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/message/fusion/mptbase.c linux.19rc3-ac4/drivers/message/fusion/mptbase.c --- linux.19rc3/drivers/message/fusion/mptbase.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/message/fusion/mptbase.c 2002-07-29 13:58:42.000000000 +0100 @@ -49,7 +49,7 @@ * (mailto:sjralston1@netscape.net) * (mailto:Pam.Delaney@lsil.com) * - * $Id: mptbase.c,v 1.110 2002/02/27 18:44:20 sralston Exp $ + * $Id: mptbase.c,v 1.120 2002/06/27 13:53:27 pdelaney Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -443,7 +443,7 @@ if ((mf) && ((mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth)) || (mf < ioc->req_frames)) ) { printk(MYIOC_s_WARN_FMT - "mpt_interrupt: Invalid mf (%p) req_idx (%d)!\n", ioc->name, mf, req_idx); + "mpt_interrupt: Invalid mf (%p) req_idx (%d)!\n", ioc->name, (void *)mf, req_idx); cb_idx = 0; pa = 0; freeme = 0; @@ -451,7 +451,7 @@ if ((pa) && (mr) && ((mr >= MPT_INDEX_2_RFPTR(ioc, ioc->req_depth)) || (mr < ioc->reply_frames)) ) { printk(MYIOC_s_WARN_FMT - "mpt_interrupt: Invalid rf (%p)!\n", ioc->name, mr); + "mpt_interrupt: Invalid rf (%p)!\n", ioc->name, (void *)mr); cb_idx = 0; pa = 0; freeme = 0; @@ -525,7 +525,7 @@ if ((mf == NULL) || (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) { printk(MYIOC_s_ERR_FMT "NULL or BAD request frame ptr! (=%p)\n", - ioc->name, mf); + ioc->name, (void *)mf); return 1; } @@ -938,6 +938,70 @@ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** + * mpt_add_sge - Place a simple SGE at address pAddr. + * @pAddr: virtual address for SGE + * @flagslength: SGE flags and data transfer length + * @dma_addr: Physical address + * + * This routine places a MPT request frame back on the MPT adapter's + * FreeQ. + */ +void +mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr) +{ + if (sizeof(dma_addr_t) == sizeof(u64)) { + SGESimple64_t *pSge = (SGESimple64_t *) pAddr; + u32 tmp = dma_addr & 0xFFFFFFFF; + + pSge->FlagsLength = cpu_to_le32(flagslength); + pSge->Address.Low = cpu_to_le32(tmp); + tmp = (u32) ((u64)dma_addr >> 32); + pSge->Address.High = cpu_to_le32(tmp); + + } else { + SGESimple32_t *pSge = (SGESimple32_t *) pAddr; + pSge->FlagsLength = cpu_to_le32(flagslength); + pSge->Address = cpu_to_le32(dma_addr); + } +} + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/** + * mpt_add_chain - Place a chain SGE at address pAddr. + * @pAddr: virtual address for SGE + * @next: nextChainOffset value (u32's) + * @length: length of next SGL segment + * @dma_addr: Physical address + * + * This routine places a MPT request frame back on the MPT adapter's + * FreeQ. + */ +void +mpt_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr) +{ + if (sizeof(dma_addr_t) == sizeof(u64)) { + SGEChain64_t *pChain = (SGEChain64_t *) pAddr; + u32 tmp = dma_addr & 0xFFFFFFFF; + + pChain->Length = cpu_to_le16(length); + pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size(); + + pChain->NextChainOffset = next; + + pChain->Address.Low = cpu_to_le32(tmp); + tmp = (u32) ((u64)dma_addr >> 32); + pChain->Address.High = cpu_to_le32(tmp); + } else { + SGEChain32_t *pChain = (SGEChain32_t *) pAddr; + pChain->Length = cpu_to_le16(length); + pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size(); + pChain->NextChainOffset = next; + pChain->Address = cpu_to_le32(dma_addr); + } +} + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/** * mpt_send_handshake_request - Send MPT request via doorbell * handshake method. * @handle: Handle of registered MPT protocol driver @@ -1023,7 +1087,7 @@ } } - if ((r = WaitForDoorbellInt(iocp, 10, sleepFlag)) >= 0) + if (r >= 0 && WaitForDoorbellInt(iocp, 10, sleepFlag) >= 0) r = 0; else r = -4; @@ -1090,7 +1154,7 @@ dprintk((KERN_INFO MYNAM ": Checking for MPT adapters...\n")); /* - * NOTE: The 929 and 1030 will appear as 2 separate PCI devices, + * NOTE: The 929, 929X and 1030 will appear as 2 separate PCI devices, * one for each channel. */ pci_for_each_dev(pdev) { @@ -1101,6 +1165,8 @@ if ((pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC909) && (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC929) && (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC919) && + (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC929X) && + (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC919X) && (pdev->device != MPI_MANUFACTPAGE_DEVID_53C1030) && #if 0 /* FIXME! C103x family */ @@ -1113,7 +1179,7 @@ } /* GRRRRR - * dual function devices (929, 1030) may be presented in Func 1,0 order, + * dual function devices (929, 929X, 1030) may be presented in Func 1,0 order, * but we'd really really rather have them in Func 0,1 order. * Do some kind of look ahead here... */ @@ -1206,7 +1272,6 @@ mpt_adapter_install(struct pci_dev *pdev) { MPT_ADAPTER *ioc; - char *myname; u8 *mem; unsigned long mem_phys; unsigned long port; @@ -1214,9 +1279,20 @@ u32 psize; int ii; int r = -ENODEV; - int len; + u64 mask = 0xffffffffffffffff; + + if (pci_enable_device(pdev)) + return r; + + if (!pci_set_dma_mask(pdev, mask)) { + dprintk((KERN_INFO MYNAM + ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n")); + } else if (pci_set_dma_mask(pdev, (u64) 0xffffffff)) { + printk(KERN_WARNING MYNAM ": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n"); + return r; + } - ioc = kmalloc(sizeof(MPT_ADAPTER), GFP_KERNEL); + ioc = kmalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC); if (ioc == NULL) { printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n"); return -ENOMEM; @@ -1241,10 +1317,7 @@ ioc->mfcnt = 0; #endif - /* Initialize the FW and Data image pointers. - */ - ioc->FWImage = NULL; - ioc->FWImage_dma = 0; + ioc->cached_fw = NULL; /* Initilize SCSI Config Data structure */ @@ -1338,6 +1411,14 @@ ioc->chip_type = FC919; ioc->prod_name = "LSIFC919"; } + else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929X) { + ioc->chip_type = FC929X; + ioc->prod_name = "LSIFC929X"; + } + else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919X) { + ioc->chip_type = FC919X; + ioc->prod_name = "LSIFC919X"; + } else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) { ioc->chip_type = C1030; ioc->prod_name = "LSI53C1030"; @@ -1352,10 +1433,7 @@ } } - myname = "iocN"; - len = strlen(myname); - memcpy(ioc->name, myname, len+1); - ioc->name[len-1] = '0' + ioc->id; + sprintf(ioc->name, "ioc%d", ioc->id); Q_INIT(&ioc->FreeQ, MPT_FRAME_HDR); spin_lock_init(&ioc->FreeQlock); @@ -1400,9 +1478,9 @@ mpt_adapters[ioc->id] = ioc; /* NEW! 20010220 -sralston - * Check for "bound ports" (929, 1030) to reduce redundant resets. + * Check for "bound ports" (929, 929X, 1030) to reduce redundant resets. */ - if ((ioc->chip_type == FC929) || (ioc->chip_type == C1030)) + if ((ioc->chip_type == FC929) || (ioc->chip_type == C1030) || (ioc->chip_type == FC929X)) mpt_detect_bound_ports(ioc, pdev); if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP, CAN_SLEEP)) != 0) { @@ -1523,15 +1601,15 @@ } if (reason == MPT_HOSTEVENT_IOC_BRINGUP){ - if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT) { - dprintk((MYIOC_s_INFO_FMT + if (ioc->upload_fw) { + ddlprintk((MYIOC_s_INFO_FMT "firmware upload required!\n", ioc->name)); r = mpt_do_upload(ioc, sleepFlag); if (r != 0) printk(KERN_WARNING MYNAM ": firmware upload failure!\n"); /* Handle the alt IOC too */ - if (alt_ioc_ready){ + if ((alt_ioc_ready) && (ioc->alt_ioc->upload_fw)){ r = mpt_do_upload(ioc->alt_ioc, sleepFlag); if (r != 0) printk(KERN_WARNING MYNAM ": firmware upload failure!\n"); @@ -1645,8 +1723,8 @@ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * mpt_detect_bound_ports - Search for PCI bus/dev_function - * which matches PCI bus/dev_function (+/-1) for newly discovered 929 - * or 1030. + * which matches PCI bus/dev_function (+/-1) for newly discovered 929, + * 929X or 1030. * @ioc: Pointer to MPT adapter structure * @pdev: Pointer to (struct pci_dev) structure * @@ -1710,6 +1788,16 @@ (void) KickStart(this, 1, NO_SLEEP); } + if (this->cached_fw != NULL) { + ddlprintk((KERN_INFO MYNAM ": Pushing FW onto adapter\n")); + + if ((state = mpt_downloadboot(this, NO_SLEEP)) < 0) { + printk(KERN_WARNING MYNAM + ": firmware downloadboot failure (%d)!\n", state); + } + } + + /* Disable adapter interrupts! */ CHIPREG_WRITE32(&this->chip->IntMask, 0xFFFFFFFF); this->active = 0; @@ -1753,11 +1841,26 @@ this->alloc_total -= sz; } - if (freeup && this->FWImage != NULL) { - sz = this->facts.FWImageSize; - pci_free_consistent(this->pcidev, sz, - this->FWImage, this->FWImage_dma); - this->FWImage = NULL; + if (freeup && this->cached_fw != NULL) { + int ii = 0; + + while ((ii < this->num_fw_frags) && (this->cached_fw[ii]!= NULL)) { + sz = this->cached_fw[ii]->size; + pci_free_consistent(this->pcidev, sz, + this->cached_fw[ii]->fw, this->cached_fw[ii]->fw_dma); + this->cached_fw[ii]->fw = NULL; + this->alloc_total -= sz; + + kfree(this->cached_fw[ii]); + this->cached_fw[ii] = NULL; + this->alloc_total -= sizeof(fw_image_t); + + ii++; + } + + kfree(this->cached_fw); + this->cached_fw = NULL; + sz = this->num_fw_frags * sizeof(void *); this->alloc_total -= sz; } @@ -2151,7 +2254,7 @@ * and request & reply queue depths... */ ioc->req_sz = MIN(MPT_DEFAULT_FRAME_SIZE, facts->RequestFrameSize * 4); - ioc->req_depth = MIN(MPT_DEFAULT_REQ_DEPTH, facts->GlobalCredits); + ioc->req_depth = MIN(MPT_MAX_REQ_DEPTH, facts->GlobalCredits); ioc->reply_sz = ioc->req_sz; ioc->reply_depth = MIN(MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth); @@ -2271,10 +2374,24 @@ ioc_init.Function = MPI_FUNCTION_IOC_INIT; /* ioc_init.Flags = 0; */ + /* If we are in a recovery mode and we uploaded the FW image, + * then this pointer is not NULL. Skip the upload a second time. + * Set this flag if cached_fw set for either IOC. + */ + ioc->upload_fw = 0; + ioc_init.Flags = 0; + if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT) { + if ((ioc->cached_fw) || (ioc->alt_ioc && ioc->alt_ioc->cached_fw)) + ioc_init.Flags = MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE; + else + ioc->upload_fw = 1; + } + ddlprintk((MYIOC_s_INFO_FMT "flags %d, upload_fw %d \n", + ioc->name, ioc_init.Flags, ioc->upload_fw)); + if ((int)ioc->chip_type <= (int)FC929) { ioc_init.MaxDevices = MPT_MAX_FC_DEVICES; - } - else { + } else { ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES; } ioc_init.MaxBuses = MPT_MAX_BUS; @@ -2283,17 +2400,17 @@ /* ioc_init.MsgContext = cpu_to_le32(0x00000000); */ ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */ -#ifdef __ia64__ - /* Save the upper 32-bits of the request - * (reply) and sense buffers. - */ - ioc_init.HostMfaHighAddr = cpu_to_le32((u32)(ioc->req_frames_dma >> 32)); - ioc_init.SenseBufferHighAddr = cpu_to_le32((u32)(ioc->sense_buf_pool_dma >> 32)); -#else - /* Force 32-bit addressing */ - ioc_init.HostMfaHighAddr = cpu_to_le32(0); - ioc_init.SenseBufferHighAddr = cpu_to_le32(0); -#endif + if (sizeof(dma_addr_t) == sizeof(u64)) { + /* Save the upper 32-bits of the request + * (reply) and sense buffers. + */ + ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->req_frames_dma >> 32)); + ioc_init.SenseBufferHighAddr = cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32)); + } else { + /* Force 32-bit addressing */ + ioc_init.HostMfaHighAddr = cpu_to_le32(0); + ioc_init.SenseBufferHighAddr = cpu_to_le32(0); + } dprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n", ioc->name, &ioc_init)); @@ -2398,6 +2515,142 @@ return 0; } +/* + * Inputs: size - total FW bytes + * Outputs: frags - number of fragments needed + * Return NULL if failed. + */ +void * +mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size, int *frags, int *alloc_sz) +{ + fw_image_t **cached_fw = NULL; + u8 *mem = NULL; + dma_addr_t fw_dma; + int alloc_total = 0; + int bytes_left, bytes, num_frags; + int sz, ii; + + /* cached_fw + */ + sz = ioc->num_fw_frags * sizeof(void *); + mem = kmalloc(sz, GFP_ATOMIC); + if (mem == NULL) + return NULL; + + memset(mem, 0, sz); + cached_fw = (fw_image_t **)mem; + alloc_total += sz; + + /* malloc fragment memory + * fw_image_t struct and dma for fw data + */ + bytes_left = size; + ii = 0; + num_frags = 0; + bytes = bytes_left; + while((bytes_left) && (num_frags < ioc->num_fw_frags)) { + if (cached_fw[ii] == NULL) { + mem = kmalloc(sizeof(fw_image_t), GFP_ATOMIC); + if (mem == NULL) + break; + + memset(mem, 0, sizeof(fw_image_t)); + cached_fw[ii] = (fw_image_t *)mem; + alloc_total += sizeof(fw_image_t); + } + + mem = pci_alloc_consistent(ioc->pcidev, bytes, &fw_dma); + if (mem == NULL) { + if (bytes > 0x10000) + bytes = 0x10000; + else if (bytes > 0x8000) + bytes = 0x8000; + else if (bytes > 0x4000) + bytes = 0x4000; + else if (bytes > 0x2000) + bytes = 0x2000; + else if (bytes > 0x1000) + bytes = 0x1000; + else + break; + + continue; + } + + cached_fw[ii]->fw = mem; + cached_fw[ii]->fw_dma = fw_dma; + cached_fw[ii]->size = bytes; + memset(mem, 0, bytes); + alloc_total += bytes; + + bytes_left -= bytes; + + num_frags++; + ii++; + } + + if (bytes_left ) { + /* Major Failure. + */ + mpt_free_fw_memory(ioc, cached_fw); + return NULL; + } + + *frags = num_frags; + *alloc_sz = alloc_total; + + return (void *) cached_fw; +} + +/* + * If alt_img is NULL, delete from ioc structure. + * Else, delete a secondary image in same format. + */ +void +mpt_free_fw_memory(MPT_ADAPTER *ioc, fw_image_t **alt_img) +{ + fw_image_t **cached_fw; + int ii; + int sz; + int alloc_freed = 0; + + if (alt_img != NULL) + cached_fw = alt_img; + else + cached_fw = ioc->cached_fw; + + if (cached_fw == NULL) + return; + + ii = 0; + while ((ii < ioc->num_fw_frags) && (cached_fw[ii]!= NULL)) { + sz = cached_fw[ii]->size; + if (sz > 0) { + pci_free_consistent(ioc->pcidev, sz, + cached_fw[ii]->fw, cached_fw[ii]->fw_dma); + } + cached_fw[ii]->fw = NULL; + alloc_freed += sz; + + kfree(cached_fw[ii]); + cached_fw[ii] = NULL; + alloc_freed += sizeof(fw_image_t); + + ii++; + } + + kfree(cached_fw); + cached_fw = NULL; + sz = ioc->num_fw_frags * sizeof(void *); + alloc_freed += sz; + + if (alt_img == NULL) + ioc->alloc_total -= alloc_freed; + + return; +} + + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * mpt_do_upload - Construct and Send FWUpload request to MPT adapter port. @@ -2415,45 +2668,46 @@ static int mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) { - u8 request[sizeof(FWUpload_t) + 24]; + u8 request[ioc->req_sz]; u8 reply[sizeof(FWUploadReply_t)]; FWUpload_t *prequest; FWUploadReply_t *preply; FWUploadTCSGE_t *ptcsge = NULL; - MptSge_t *psge; - u8 *mem; - dma_addr_t dma_addr; int sgeoffset; - int i, sz, req_sz, reply_sz; + int ii, sz, reply_sz; int cmdStatus, freeMem = 0; + int num_frags, alloc_sz; /* If the image size is 0 or if the pointer is * not NULL (error), we are done. */ - if (((sz = ioc->facts.FWImageSize) == 0) || ioc->FWImage) + if (((sz = ioc->facts.FWImageSize) == 0) || ioc->cached_fw) return 0; - /* Allocate memory - */ - mem = pci_alloc_consistent(ioc->pcidev, sz, &ioc->FWImage_dma); - if (mem == NULL) - return -1; + ioc->num_fw_frags = ioc->req_sz - sizeof(FWUpload_t) + sizeof(dma_addr_t) + sizeof(u32) -1; + ioc->num_fw_frags /= sizeof(dma_addr_t) + sizeof(u32); - memset(mem, 0, sz); - ioc->alloc_total += sz; - ioc->FWImage = mem; - dprintk((KERN_INFO MYNAM ": FW Image @ %p[%p], sz=%d bytes\n", - mem, (void *)(ulong)ioc->FWImage_dma, sz)); + ioc->cached_fw = (fw_image_t **) mpt_alloc_fw_memory(ioc, + ioc->facts.FWImageSize, &num_frags, &alloc_sz); - dma_addr = ioc->FWImage_dma; + if (ioc->cached_fw == NULL) { + /* Major Failure. + */ + mpt_free_fw_memory(ioc, NULL); + ioc->cached_fw = NULL; + + return -ENOMEM; + } + ioc->alloc_total += alloc_sz; + + ddlprintk((KERN_INFO MYNAM ": FW Image @ %p, sz=%d bytes\n", + (void *)(ulong)ioc->cached_fw, ioc->facts.FWImageSize)); prequest = (FWUpload_t *)&request; preply = (FWUploadReply_t *)&reply; /* Destination... */ - req_sz = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) - + sizeof(FWUploadTCSGE_t) + sizeof(MptSge_t); - memset(prequest, 0, req_sz); + memset(prequest, 0, ioc->req_sz); reply_sz = sizeof(reply); memset(preply, 0, reply_sz); @@ -2472,19 +2726,29 @@ ptcsge->ImageSize = cpu_to_le32(sz); sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t); - psge = (MptSge_t *) &request[sgeoffset]; - psge->FlagsLength = cpu_to_le32(MPT_SGE_FLAGS_SSIMPLE_READ | (u32) sz); - cpu_to_leXX(dma_addr, psge->Address); + for (ii = 0; ii < (num_frags-1); ii++) { + mpt_add_sge(&request[sgeoffset], MPT_SGE_FLAGS_SIMPLE_ELEMENT | + MPT_SGE_FLAGS_ADDRESSING | MPT_TRANSFER_IOC_TO_HOST | + (u32) ioc->cached_fw[ii]->size, ioc->cached_fw[ii]->fw_dma); + + sgeoffset += sizeof(u32) + sizeof(dma_addr_t); + } + + mpt_add_sge(&request[sgeoffset], + MPT_SGE_FLAGS_SSIMPLE_READ |(u32) ioc->cached_fw[ii]->size, + ioc->cached_fw[ii]->fw_dma); + + sgeoffset += sizeof(u32) + sizeof(dma_addr_t); - dprintk((MYIOC_s_INFO_FMT "Sending FW Upload (req @ %p)\n", - ioc->name, prequest)); + dprintk((MYIOC_s_INFO_FMT "Sending FW Upload (req @ %p) size %d \n", + ioc->name, prequest, sgeoffset)); - i = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)prequest, + ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest, reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag); cmdStatus = -EFAULT; - if (i == 0) { + if (ii == 0) { /* Handshake transfer was complete and successful. * Check the Reply Frame. */ @@ -2496,14 +2760,15 @@ cmdStatus = 0; } } - dprintk((MYIOC_s_INFO_FMT ": do_upload status %d \n", + ddlprintk((MYIOC_s_INFO_FMT ": do_upload status %d \n", ioc->name, cmdStatus)); /* Check to see if we have a copy of this image in * host memory already. */ if (cmdStatus == 0) { - if (ioc->alt_ioc && ioc->alt_ioc->FWImage) + ioc->upload_fw = 0; + if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) freeMem = 1; } @@ -2512,13 +2777,11 @@ * failed (i != 0) or the command did not complete successfully. */ if (cmdStatus || freeMem) { - dprintk((MYIOC_s_INFO_FMT ": do_upload freeing %s image \n", - ioc->name, cmdStatus ? "incomplete" : "duplicate")); - pci_free_consistent(ioc->pcidev, sz, - ioc->FWImage, ioc->FWImage_dma); - ioc->FWImage = NULL; - ioc->alloc_total -= sz; + ddlprintk((MYIOC_s_INFO_FMT ": do_upload freeing %s image \n", + ioc->name, cmdStatus ? "incomplete" : "duplicate")); + mpt_free_fw_memory(ioc, NULL); + ioc->cached_fw = NULL; } return cmdStatus; @@ -2535,7 +2798,7 @@ * * Returns 0 for success * -1 FW Image size is 0 - * -2 No valid FWImage Pointer + * -2 No valid cached_fw Pointer * <0 for fw upload failure. */ static int @@ -2543,6 +2806,7 @@ { MpiFwHeader_t *FwHdr = NULL; MpiExtImageHeader_t *ExtHdr; + fw_image_t **pCached = NULL; int fw_sz; u32 diag0val; #ifdef MPT_DEBUG @@ -2552,22 +2816,26 @@ u32 *ptru32 = NULL; u32 diagRwData; u32 nextImage; + u32 ext_offset; + u32 load_addr; + int max_idx, fw_idx, ext_idx; + int left_u32s; - dprintk((MYIOC_s_INFO_FMT "DbGb0: downloadboot entered.\n", + ddlprintk((MYIOC_s_INFO_FMT "DbGb0: downloadboot entered.\n", ioc->name)); #ifdef MPT_DEBUG diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); if (ioc->alt_ioc) diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic); - dprintk((MYIOC_s_INFO_FMT "DbGb1: diag0=%08x, diag1=%08x\n", + ddlprintk((MYIOC_s_INFO_FMT "DbGb1: diag0=%08x, diag1=%08x\n", ioc->name, diag0val, diag1val)); #endif - dprintk((MYIOC_s_INFO_FMT "fw size 0x%x, ioc FW Ptr %p\n", - ioc->name, ioc->facts.FWImageSize, ioc->FWImage)); + ddlprintk((MYIOC_s_INFO_FMT "fw size 0x%x, ioc FW Ptr %p\n", + ioc->name, ioc->facts.FWImageSize, ioc->cached_fw)); if (ioc->alt_ioc) - dprintk((MYIOC_s_INFO_FMT "alt ioc FW Ptr %p\n", - ioc->name, ioc->alt_ioc->FWImage)); + ddlprintk((MYIOC_s_INFO_FMT "alt ioc FW Ptr %p\n", + ioc->name, ioc->alt_ioc->cached_fw)); /* Get dma_addr and data transfer size. */ @@ -2575,15 +2843,14 @@ return -1; /* Get the DMA from ioc or ioc->alt_ioc */ - if (ioc->FWImage) - FwHdr = (MpiFwHeader_t *)ioc->FWImage; - else if (ioc->alt_ioc && ioc->alt_ioc->FWImage) - FwHdr = (MpiFwHeader_t *)ioc->alt_ioc->FWImage; - - dprintk((MYIOC_s_INFO_FMT "DbGb2: FW Image @ %p\n", - ioc->name, FwHdr)); - - if (!FwHdr) + if (ioc->cached_fw != NULL) + pCached = (fw_image_t **)ioc->cached_fw; + else if (ioc->alt_ioc && (ioc->alt_ioc->cached_fw != NULL)) + pCached = (fw_image_t **)ioc->alt_ioc->cached_fw; + + ddlprintk((MYIOC_s_INFO_FMT "DbGb2: FW Image @ %p\n", + ioc->name, pCached)); + if (!pCached) return -2; /* Write magic sequence to WriteSequence register @@ -2617,10 +2884,10 @@ #ifdef MPT_DEBUG if (ioc->alt_ioc) diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic); - dprintk((MYIOC_s_INFO_FMT "DbGb3: diag0=%08x, diag1=%08x\n", + ddlprintk((MYIOC_s_INFO_FMT "DbGb3: diag0=%08x, diag1=%08x\n", ioc->name, diag0val, diag1val)); #endif - dprintk((MYIOC_s_INFO_FMT "Wrote magic DiagWriteEn sequence (%x)\n", + ddlprintk((MYIOC_s_INFO_FMT "Wrote magic DiagWriteEn sequence (%x)\n", ioc->name, diag0val)); } @@ -2631,60 +2898,145 @@ #ifdef MPT_DEBUG if (ioc->alt_ioc) diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic); - dprintk((MYIOC_s_INFO_FMT "DbGb3: diag0=%08x, diag1=%08x\n", + + ddlprintk((MYIOC_s_INFO_FMT "DbGb3: diag0=%08x, diag1=%08x\n", ioc->name, diag0val, diag1val)); #endif + /* max_idx = 1 + maximum valid buffer index + */ + max_idx = 0; + while (pCached[max_idx]) + max_idx++; + + fw_idx = 0; + FwHdr = (MpiFwHeader_t *) pCached[fw_idx]->fw; + ptru32 = (u32 *) FwHdr; + count = (FwHdr->ImageSize + 3)/4; + nextImage = FwHdr->NextImageHeaderOffset; + /* Write the LoadStartAddress to the DiagRw Address Register * using Programmed IO */ - CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, FwHdr->LoadStartAddress); - dprintk((MYIOC_s_INFO_FMT "LoadStart addr written 0x%x \n", + ddlprintk((MYIOC_s_INFO_FMT "LoadStart addr written 0x%x \n", ioc->name, FwHdr->LoadStartAddress)); - nextImage = FwHdr->NextImageHeaderOffset; - - /* round up count to a 32bit alignment */ - ptru32 = (u32 *) FwHdr; - count = (FwHdr->ImageSize + 3)/4; - - dprintk((MYIOC_s_INFO_FMT "Write FW Image: 0x%x u32's @ %p\n", + ddlprintk((MYIOC_s_INFO_FMT "Write FW Image: 0x%x u32's @ %p\n", ioc->name, count, ptru32)); - while (count-- ) { + left_u32s = pCached[fw_idx]->size/4; + while (count--) { + if (left_u32s == 0) { + fw_idx++; + if (fw_idx >= max_idx) { + /* FIXME + ERROR CASE + */ + ; + } + ptru32 = (u32 *) pCached[fw_idx]->fw; + left_u32s = pCached[fw_idx]->size / 4; + } + left_u32s--; CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptru32); ptru32++; } - dprintk((MYIOC_s_INFO_FMT "FW Image done! \n", ioc->name)); - + /* left_u32s, fw_idx and ptru32 are all valid + */ while (nextImage) { + ext_idx = 0; + ext_offset = nextImage; + while (ext_offset > pCached[ext_idx]->size) { + ext_idx++; + if (ext_idx >= max_idx) { + /* FIXME + ERROR CASE + */ + ; + } + ext_offset -= pCached[ext_idx]->size; + } + ptru32 = (u32 *) ((char *)pCached[ext_idx]->fw + ext_offset); + left_u32s = pCached[ext_idx]->size - ext_offset; - /* Set the pointer to the extended image - */ - ExtHdr = (MpiExtImageHeader_t *) ((char *) FwHdr + nextImage); + if ((left_u32s * 4) >= sizeof(MpiExtImageHeader_t)) { + ExtHdr = (MpiExtImageHeader_t *) ptru32; + count = (ExtHdr->ImageSize + 3 )/4; + nextImage = ExtHdr->NextImageHeaderOffset; + load_addr = ExtHdr->LoadStartAddress; + } else { + u32 * ptmp = (u32 *)pCached[ext_idx+1]->fw; - CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, ExtHdr->LoadStartAddress); + switch (left_u32s) { + case 5: + count = *(ptru32 + 2); + nextImage = *(ptru32 + 3); + load_addr = *(ptru32 + 4); + break; + case 4: + count = *(ptru32 + 2); + nextImage = *(ptru32 + 3); + load_addr = *ptmp; + break; + case 3: + count = *(ptru32 + 2); + nextImage = *ptmp; + load_addr = *(ptmp + 1); + break; + case 2: + count = *ptmp; + nextImage = *(ptmp + 1); + load_addr = *(ptmp + 2); + break; - count = (ExtHdr->ImageSize + 3 )/4; + case 1: + count = *(ptmp + 1); + nextImage = *(ptmp + 2); + load_addr = *(ptmp + 3); + break; - ptru32 = (u32 *) ExtHdr; - dprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x u32's @ %p\n", - ioc->name, count, ptru32)); - while (count-- ) { + default: + count = 0; + nextImage = 0; + load_addr = 0; + /* FIXME + ERROR CASE + */ + ; + + } + count = (count +3)/4; + } + + ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x u32's @ %p\n", + ioc->name, count, ptru32)); + CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr); + + while (count--) { + if (left_u32s == 0) { + fw_idx++; + if (fw_idx >= max_idx) { + /* FIXME + ERROR CASE + */ + ; + } + ptru32 = (u32 *) pCached[fw_idx]->fw; + left_u32s = pCached[fw_idx]->size / 4; + } + left_u32s--; CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptru32); ptru32++; } - nextImage = ExtHdr->NextImageHeaderOffset; } - /* Write the IopResetVectorRegAddr */ - dprintk((MYIOC_s_INFO_FMT "Write IopResetVector Addr! \n", ioc->name)); + ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Addr! \n", ioc->name)); CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, FwHdr->IopResetRegAddr); /* Write the IopResetVectorValue */ - dprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value! \n", ioc->name)); + ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value! \n", ioc->name)); CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, FwHdr->IopResetVectorValue); /* Clear the internal flash bad bit - autoincrementing register, @@ -3182,15 +3534,14 @@ ioc->req_frames_low_dma = (u32) (ioc->req_frames_dma & 0xFFFFFFFF); -#ifdef __ia64__ - /* Check: upper 32-bits of the request and reply frame - * physical addresses must be the same. - * ia64 check only - */ - if ((ioc->req_frames_dma >> 32) != (ioc->reply_frames_dma >> 32)){ - goto out_fail; + if (sizeof(dma_addr_t) == sizeof(u64)) { + /* Check: upper 32-bits of the request and reply frame + * physical addresses must be the same. + */ + if (((u64)ioc->req_frames_dma >> 32) != ((u64)ioc->reply_frames_dma >> 32)){ + goto out_fail; + } } -#endif #if defined(CONFIG_MTRR) && 0 /* @@ -3866,7 +4217,7 @@ int sz; u8 *mem; sz = MPT_MAX_SCSI_DEVICES * sizeof(int); - mem = kmalloc(sz, GFP_KERNEL); + mem = kmalloc(sz, GFP_ATOMIC); if (mem == NULL) return -EFAULT; @@ -4166,7 +4517,7 @@ cfg.physAddr = ioc3_dma; cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; if (mpt_config(ioc, &cfg) == 0) { - mem = kmalloc(iocpage3sz, GFP_KERNEL); + mem = kmalloc(iocpage3sz, GFP_ATOMIC); if (mem) { memcpy(mem, (u8 *)pIoc3, iocpage3sz); ioc->spi_data.pIocPg3 = (IOCPage3_t *) mem; @@ -4271,7 +4622,6 @@ { Config_t *pReq; MPT_FRAME_HDR *mf; - MptSge_t *psge; unsigned long flags; int ii, rc; int flagsLength; @@ -4316,19 +4666,14 @@ /* Add a SGE to the config request. */ - flagsLength = ((MPI_SGE_FLAGS_LAST_ELEMENT | - MPI_SGE_FLAGS_END_OF_BUFFER | - MPI_SGE_FLAGS_END_OF_LIST | - MPI_SGE_FLAGS_SIMPLE_ELEMENT | - MPT_SGE_ADDRESS_SIZE ) << MPI_SGE_FLAGS_SHIFT) | - pCfg->hdr->PageLength * 4; - if (pCfg->dir) - flagsLength |= (MPI_SGE_FLAGS_DIRECTION << MPI_SGE_FLAGS_SHIFT); + flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE; + else + flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ; + + flagsLength |= pCfg->hdr->PageLength * 4; - psge = (MptSge_t *) &pReq->PageBufferSGE; - psge->FlagsLength = cpu_to_le32(flagsLength); - cpu_to_leXX(pCfg->physAddr, psge->Address); + mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr); dprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n", ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action)); @@ -4431,6 +4776,7 @@ /* Search the configQ for internal commands. * Flush the Q, and wake up all suspended threads. */ +#if 1 spin_lock_irqsave(&ioc->FreeQlock, flags); if (! Q_IS_EMPTY(&ioc->configQ)){ pCfg = (CONFIGPARMS *)ioc->configQ.head; @@ -4447,6 +4793,23 @@ } while (pCfg != (CONFIGPARMS *)&ioc->configQ); } spin_unlock_irqrestore(&ioc->FreeQlock, flags); +#else + while (1) { + spin_lock_irqsave(&ioc->FreeQlock, flags); + if (! Q_IS_EMPTY(&ioc->configQ)){ + spin_unlock_irqrestore(&ioc->FreeQlock, flags); + break; + } + pCfg = (CONFIGPARMS *)ioc->configQ.head; + + Q_DEL_ITEM(&pCfg->linkage); + spin_unlock_irqrestore(&ioc->FreeQlock, flags); + + pCfg->status = MPT_CONFIG_ERROR; + pCfg->wait_done = 1; + wake_up(&mpt_waitq); + } +#endif } return 1; /* currently means nothing really */ @@ -4732,7 +5095,7 @@ len += sprintf(buf+len, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize); len += sprintf(buf+len, " RequestFrames @ 0x%p (Dma @ 0x%p)\n", - ioc->req_alloc, (void *)(ulong)ioc->req_alloc_dma); + (void *)ioc->req_alloc, (void *)(ulong)ioc->req_alloc_dma); /* * Rounding UP to nearest 4-kB boundary here... */ @@ -4745,7 +5108,7 @@ ioc->facts.GlobalCredits); len += sprintf(buf+len, " ReplyFrames @ 0x%p (Dma @ 0x%p)\n", - ioc->reply_alloc, (void *)(ulong)ioc->reply_alloc_dma); + (void *)ioc->reply_alloc, (void *)(ulong)ioc->reply_alloc_dma); sz = (ioc->reply_sz * ioc->reply_depth) + 128; len += sprintf(buf+len, " {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n", ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz); @@ -5301,6 +5664,8 @@ EXPORT_SYMBOL(mpt_get_msg_frame); EXPORT_SYMBOL(mpt_put_msg_frame); EXPORT_SYMBOL(mpt_free_msg_frame); +EXPORT_SYMBOL(mpt_add_sge); +EXPORT_SYMBOL(mpt_add_chain); EXPORT_SYMBOL(mpt_send_handshake_request); EXPORT_SYMBOL(mpt_handshake_req_reply_wait); EXPORT_SYMBOL(mpt_adapter_find_first); @@ -5312,6 +5677,8 @@ EXPORT_SYMBOL(mpt_stm_index); EXPORT_SYMBOL(mpt_HardResetHandler); EXPORT_SYMBOL(mpt_config); +EXPORT_SYMBOL(mpt_alloc_fw_memory); +EXPORT_SYMBOL(mpt_free_fw_memory); EXPORT_SYMBOL(mpt_register_ascqops_strings); EXPORT_SYMBOL(mpt_deregister_ascqops_strings); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/message/fusion/mptbase.h linux.19rc3-ac4/drivers/message/fusion/mptbase.h --- linux.19rc3/drivers/message/fusion/mptbase.h 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/message/fusion/mptbase.h 2002-07-29 17:29:12.000000000 +0100 @@ -13,7 +13,7 @@ * (mailto:sjralston1@netscape.net) * (mailto:Pam.Delaney@lsil.com) * - * $Id: mptbase.h,v 1.103 2002/02/27 20:24:38 pdelaney Exp $ + * $Id: mptbase.h,v 1.127 2002/07/09 13:30:36 pdelaney Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -80,8 +80,8 @@ #define COPYRIGHT "Copyright (c) 1999-2002 " MODULEAUTHOR #endif -#define MPT_LINUX_VERSION_COMMON "2.00.11" -#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-2.00.11" +#define MPT_LINUX_VERSION_COMMON "2.01.07" +#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-2.01.07" #define WHAT_MAGIC_STRING "@" "(" "#" ")" #define show_mptmod_ver(s,ver) \ @@ -295,6 +295,8 @@ */ typedef enum { + FC919X = 0x0819, + FC929X = 0x0829, FC909 = 0x0909, FC919 = 0x0919, FC929 = 0x0929, @@ -375,9 +377,13 @@ u8 minSyncFactor; /* 0xFF is async */ u8 maxOffset; /* 0 if async */ u8 maxWidth; /* 0 if narrow, 1 if wide*/ - u8 negoFlags; /* 0 if WDTR/SDTR allowed */ + u8 negoFlags; /* bit field, 0 if WDTR/SDTR/QAS allowed */ u8 raidVolume; /* set, if RAID Volume */ - u8 rsvd; /* alignment */ +#ifdef ABORT_FIX + u8 numAborts; +#else + u8 rsvd; +#endif u16 rsvd1raid; int npaths; u16 fc_phys_lun; @@ -396,11 +402,13 @@ u32 luns; /* Max LUNs is 32 */ u8 inq_data[SCSI_STD_INQUIRY_BYTES]; /* 36 */ u8 pad0[4]; - u8 uniq_prepad[8]; u8 inq00_data[20]; u8 pad1[4]; /* IEEE Registered Extended Identifier obtained via INQUIRY VPD page 0x83 */ + /* NOTE: Do not separate uniq_prepad and uniq_data + as they are treateed as a single entity in the code */ + u8 uniq_prepad[8]; u8 uniq_data[20]; u8 pad2[4]; u8 inqC3_data[12]; @@ -421,6 +429,7 @@ #define MPT_TARGET_NO_NEGO_WIDE 0x01 #define MPT_TARGET_NO_NEGO_SYNC 0x02 +#define MPT_TARGET_NO_NEGO_QAS 0x04 typedef struct _VirtDevTracker { struct _VirtDevice *head; @@ -459,11 +468,15 @@ * IOCTL structure and associated defines */ -#define MPT_IOCTL_STATUS_DID_TIMEOUT 0x01 /* The current IOCTL timed out */ +#define MPT_IOCTL_STATUS_DID_IOCRESET 0x01 /* IOC Reset occurred on the current*/ #define MPT_IOCTL_STATUS_RF_VALID 0x02 /* The Reply Frame is VALID */ #define MPT_IOCTL_STATUS_TIMER_ACTIVE 0x04 /* The timer is running */ #define MPT_IOCTL_STATUS_SENSE_VALID 0x08 /* Sense data is valid */ #define MPT_IOCTL_STATUS_COMMAND_GOOD 0x10 /* Command Status GOOD */ +#define MPT_IOCTL_STATUS_TMTIMER_ACTIVE 0x20 /* The TM timer is running */ +#define MPT_IOCTL_STATUS_TM_FAILED 0x40 /* User TM request failed */ + +#define MPTCTL_RESET_OK 0x01 /* Issue Bus Reset */ typedef struct _MPT_IOCTL { struct _MPT_ADAPTER *ioc; @@ -471,9 +484,12 @@ u8 ReplyFrame[MPT_DEFAULT_FRAME_SIZE]; /* reply frame data */ u8 sense[MPT_SENSE_BUFFER_ALLOC]; int wait_done; /* wake-up value for this ioc */ - u8 cmd; /* current command */ + u8 rsvd; u8 status; /* current command status */ - u8 pad[2]; + u8 reset; /* 1 if bus reset allowed */ + u8 target; /* target for reset */ + void *tmPtr; + struct timer_list TMtimer; /* timer function for this adapter */ } MPT_IOCTL; /* @@ -495,13 +511,17 @@ /* * Substructure to store SCSI specific configuration page data */ + /* dvStatus defines: */ #define MPT_SCSICFG_NEGOTIATE 0x01 /* Negotiate on next IO */ #define MPT_SCSICFG_NEED_DV 0x02 /* Schedule DV */ #define MPT_SCSICFG_DV_PENDING 0x04 /* DV on this physical id pending */ #define MPT_SCSICFG_DV_DONE 0x08 /* DV on this physical id complete */ +#define MPT_SCSICFG_BLK_NEGO 0x10 /* WriteSDP1 with WDTR and SDTR disabled */ + /* Args passed to writeSDP1: */ #define MPT_SCSICFG_USE_NVRAM 0x01 /* WriteSDP1 using NVRAM */ #define MPT_SCSICFG_ALL_IDS 0x02 /* WriteSDP1 to all IDS */ +/* #define MPT_SCSICFG_BLK_NEGO 0x10 WriteSDP1 with WDTR and SDTR disabled */ typedef struct _ScsiCfgData { int *nvram; /* table of device NVRAM values */ @@ -518,9 +538,17 @@ u8 sdp0length; /* SDP0 length */ u8 dvScheduled; /* 1 if scheduled */ u8 forceDv; /* 1 to force DV scheduling */ + u8 noQas; /* Disable QAS for this adapter */ u8 rsvd[2]; } ScsiCfgData; +typedef struct _fw_image { + char *fw; + dma_addr_t fw_dma; + u32 size; + u32 rsvd; +} fw_image_t; + /* * Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS */ @@ -580,9 +608,9 @@ int eventContext; /* Next event context */ int eventLogSize; /* Max number of cached events */ struct _mpt_ioctl_events *events; /* pointer to event log */ - u8 *FWImage; /* Pointer to FW */ - dma_addr_t FWImage_dma; + fw_image_t **cached_fw; /* Pointer to FW SG List */ Q_TRACKER configQ; /* linked list of config. requests */ + int num_fw_frags; /* Number of SGE in FW SG List */ int hs_reply_idx; #ifndef MFCNT u32 pad0; @@ -597,7 +625,8 @@ LANPage0_t lan_cnfg_page0; LANPage1_t lan_cnfg_page1; u8 FirstWhoInit; - u8 pad1[7]; + u8 upload_fw; /* If set, do a fw upload */ + u8 pad1[6]; } MPT_ADAPTER; @@ -631,46 +660,21 @@ #define MPT_HOSTEVENT_IOC_BRINGUP 0x91 #define MPT_HOSTEVENT_IOC_RECOVER 0x92 -/* 32 vs 64 bit SGL code. - * +/* Define the generic types based on the size + * of the dma_addr_t type. */ -#if defined(__ia64__) -typedef SGESimple64_t MptSge_t; -typedef SGEChain64_t MptChain_t; - -#define cpu_to_leXX(y, p) { \ - u32 low = (u32) (y & 0xFFFFFFFF); \ - u32 high = (u32) (y >> 32); \ - p.Low = cpu_to_le32(low); \ - p.High = cpu_to_le32(high); \ -} - -#define leXX_to_cpu(y, p) { \ - y = (dma_addr_t) le32_to_cpu(p.High); \ - y = (y << 32); \ - y |= le32_to_cpu(p.Low); \ -} - -#define MPT_SGE_ADDRESS_SIZE MPI_SGE_FLAGS_64_BIT_ADDRESSING -#define MPT_SCSIIO_MSG_FLAGS MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_64 - - -#else - -typedef SGESimple32_t MptSge_t; -typedef SGEChain32_t MptChain_t; -#define cpu_to_leXX(y,p) { \ - p = cpu_to_le32(y); \ -} - -#define leXX_to_cpu(y,p) { \ - y = le32_to_cpu(p); \ -} - -#define MPT_SGE_ADDRESS_SIZE MPI_SGE_FLAGS_32_BIT_ADDRESSING -#define MPT_SCSIIO_MSG_FLAGS MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_32 - -#endif +typedef struct _mpt_sge { + u32 FlagsLength; + dma_addr_t Address; +} MptSge_t; + +#define mpt_addr_size() \ + ((sizeof(dma_addr_t) == sizeof(u64)) ? MPI_SGE_FLAGS_64_BIT_ADDRESSING : \ + MPI_SGE_FLAGS_32_BIT_ADDRESSING) + +#define mpt_msg_flags() \ + ((sizeof(dma_addr_t) == sizeof(u64)) ? MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_64 : \ + MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_32) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -707,6 +711,13 @@ #define dsgprintk(x) #endif +#if defined(MPT_DEBUG_DL) || defined(MPT_DEBUG) +#define ddlprintk(x) printk x +#else +#define ddlprintk(x) +#endif + + #ifdef MPT_DEBUG_DV #define ddvprintk(x) printk x #else @@ -731,6 +742,12 @@ #define dtmprintk(x) #endif +#ifdef MPT_DEBUG_NEH +#define nehprintk(x) printk x +#else +#define nehprintk(x) +#endif + #define MPT_INDEX_2_MFPTR(ioc,idx) \ (MPT_FRAME_HDR*)( (u8*)(ioc)->req_frames + (ioc)->req_sz * (idx) ) @@ -831,6 +848,15 @@ #define MPT_NVRAM_WIDE_DISABLE (0x00100000) #define MPT_NVRAM_BOOT_CHOICE (0x00200000) +#ifdef MPT_SCSI_USE_NEW_EH +/* The TM_STATE variable is used to provide strict single threading of TM + * requests as well as communicate TM error conditions. + */ +#define TM_STATE_NONE (0) +#define TM_STATE_IN_PROGRESS (1) +#define TM_STATE_ERROR (2) +#endif + typedef struct _MPT_SCSI_HOST { MPT_ADAPTER *ioc; int port; @@ -868,7 +894,12 @@ u8 is_spi; /* Parallel SCSI i/f */ u8 negoNvram; /* DV disabled, nego NVRAM */ u8 is_multipath; /* Multi-path compatible */ +#ifdef MPT_SCSI_USE_NEW_EH + u8 tmState; + u8 rsvd[1]; +#else u8 rsvd[2]; +#endif MPT_FRAME_HDR *tmPtr; /* Ptr to TM request*/ MPT_FRAME_HDR *cmdPtr; /* Ptr to nonOS request */ struct scsi_cmnd *abortSCpnt; @@ -950,6 +981,9 @@ extern MPT_FRAME_HDR *mpt_get_msg_frame(int handle, int iocid); extern void mpt_free_msg_frame(int handle, int iocid, MPT_FRAME_HDR *mf); extern void mpt_put_msg_frame(int handle, int iocid, MPT_FRAME_HDR *mf); +extern void mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr); +extern void mpt_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr); + extern int mpt_send_handshake_request(int handle, int iocid, int reqBytes, u32 *req, int sleepFlag); extern int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req, int replyBytes, u16 *u16reply, int maxwait, int sleepFlag); extern int mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp); @@ -959,6 +993,8 @@ extern void mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buf, int *size, int len, int showlan); extern int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag); extern int mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *cfg); +extern void *mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size, int *frags, int *alloc_sz); +extern void mpt_free_fw_memory(MPT_ADAPTER *ioc, fw_image_t **alt_img); /* * Public data decl's... @@ -1016,7 +1052,7 @@ #define MPT_SGE_FLAGS_END_OF_BUFFER (0x40000000) #define MPT_SGE_FLAGS_LOCAL_ADDRESS (0x08000000) #define MPT_SGE_FLAGS_DIRECTION (0x04000000) -#define MPT_SGE_FLAGS_ADDRESSING (MPT_SGE_ADDRESS_SIZE << MPI_SGE_FLAGS_SHIFT) +#define MPT_SGE_FLAGS_ADDRESSING (mpt_addr_size() << MPI_SGE_FLAGS_SHIFT) #define MPT_SGE_FLAGS_END_OF_LIST (0x01000000) #define MPT_SGE_FLAGS_TRANSACTION_ELEMENT (0x00000000) @@ -1029,14 +1065,14 @@ MPT_SGE_FLAGS_END_OF_BUFFER | \ MPT_SGE_FLAGS_END_OF_LIST | \ MPT_SGE_FLAGS_SIMPLE_ELEMENT | \ - MPT_SGE_FLAGS_ADDRESSING | \ + MPT_SGE_FLAGS_ADDRESSING | \ MPT_TRANSFER_IOC_TO_HOST) #define MPT_SGE_FLAGS_SSIMPLE_WRITE \ (MPT_SGE_FLAGS_LAST_ELEMENT | \ MPT_SGE_FLAGS_END_OF_BUFFER | \ MPT_SGE_FLAGS_END_OF_LIST | \ MPT_SGE_FLAGS_SIMPLE_ELEMENT | \ - MPT_SGE_FLAGS_ADDRESSING | \ + MPT_SGE_FLAGS_ADDRESSING | \ MPT_TRANSFER_HOST_TO_IOC) /*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/message/fusion/mptctl.c linux.19rc3-ac4/drivers/message/fusion/mptctl.c --- linux.19rc3/drivers/message/fusion/mptctl.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/message/fusion/mptctl.c 2002-07-29 13:58:42.000000000 +0100 @@ -34,7 +34,7 @@ * (mailto:sjralston1@netscape.net) * (mailto:Pam.Delaney@lsil.com) * - * $Id: mptctl.c,v 1.52 2002/02/27 18:44:24 sralston Exp $ + * $Id: mptctl.c,v 1.55 2002/06/20 13:28:16 pdelaney Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -126,7 +126,7 @@ * arg contents specific to function. */ static int mptctl_fw_download(unsigned long arg); -static int mptctl_getiocinfo (unsigned long arg); +static int mptctl_getiocinfo (unsigned long arg, unsigned int cmd); static int mptctl_gettargetinfo (unsigned long arg); static int mptctl_readtest (unsigned long arg); static int mptctl_mpt_command (unsigned long arg); @@ -155,6 +155,9 @@ static void kfree_sgl( MptSge_t *sgl, dma_addr_t sgl_dma, struct buflist *buflist, MPT_ADAPTER *ioc); static void mptctl_timer_expired (unsigned long data); +static int mptctl_bus_reset(MPT_IOCTL *ioctl); +static int mptctl_set_tm_flags(MPT_SCSI_HOST *hd); +static void mptctl_free_tm_flags(MPT_ADAPTER *ioc); /* * Reset Handler cleanup function @@ -188,23 +191,6 @@ static pMPIDefaultReply_t ReplyMsg = NULL; /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* Function to return 0 if the sge Address member is 0 and - * non-zero else. Used in the mpt_do_fw_download routines. - */ -static inline int -mptctl_test_address(MptSge_t *sge) -{ -#ifdef __ia64__ - if ((sge->Address.Low) || (sge->Address.High)) - return 1; - else - return 0; -#else - return sge->Address; -#endif -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mptctl_syscall_down - Down the MPT adapter syscall semaphore. * @ioc: Pointer to MPT adapter @@ -221,6 +207,11 @@ int rc = 0; dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down(%p,%d) called\n", ioc, nonblock)); + if (ioc->ioctl->tmPtr != NULL) { + dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down BUSY\n")); + return -EBUSY; + } + #if defined(__sparc__) && defined(__sparc_v9__) /*{*/ if (!nonblock) { if (down_interruptible(&mptctl_syscall_sem_ioc[ioc->id])) @@ -268,7 +259,29 @@ * queues. * Main callback will free message and reply frames. */ - if (ioc->ioctl->status & MPT_IOCTL_STATUS_TIMER_ACTIVE) { + if (reply && (cmd == MPI_FUNCTION_SCSI_TASK_MGMT) && + (ioc->ioctl->status & MPT_IOCTL_STATUS_TMTIMER_ACTIVE)) { + /* This is internally generated TM + */ + del_timer (&ioc->ioctl->TMtimer); + ioc->ioctl->status &= ~MPT_IOCTL_STATUS_TMTIMER_ACTIVE; + + mptctl_free_tm_flags(ioc); + + /* If TM failed, reset the timer on the existing command, + * will trigger an adapter reset. + */ + iocStatus = reply->u.reply.IOCStatus & MPI_IOCSTATUS_MASK; + if (iocStatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED) { + if (ioc->ioctl->status & MPT_IOCTL_STATUS_TIMER_ACTIVE) { + del_timer (&ioc->ioctl->timer); + ioc->ioctl->timer.expires = jiffies + HZ; + add_timer(&ioc->ioctl->timer); + } + } + ioc->ioctl->tmPtr = NULL; + + } else if (ioc->ioctl->status & MPT_IOCTL_STATUS_TIMER_ACTIVE) { /* Delete this timer */ del_timer (&ioc->ioctl->timer); @@ -294,10 +307,12 @@ if (iocStatus == MPI_IOCSTATUS_SUCCESS) ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD; - if ((iocStatus == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN) || - (iocStatus == MPI_IOCSTATUS_SCSI_RECOVERED_ERROR)) { - if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) || - (cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) { + if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) || + (cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) { + ioc->ioctl->reset &= ~MPTCTL_RESET_OK; + + if ((iocStatus == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN) || + (iocStatus == MPI_IOCSTATUS_SCSI_RECOVERED_ERROR)) { ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD; } } @@ -313,9 +328,15 @@ memcpy(ioc->ioctl->sense, sense_data, sz); ioc->ioctl->status |= MPT_IOCTL_STATUS_SENSE_VALID; } + + if (cmd == MPI_FUNCTION_SCSI_TASK_MGMT) + mptctl_free_tm_flags(ioc); + + } else if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) || (cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) { ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD; + ioc->ioctl->reset &= ~MPTCTL_RESET_OK; } /* We are done, issue wake up @@ -343,17 +364,157 @@ static void mptctl_timer_expired (unsigned long data) { MPT_IOCTL *ioctl = (MPT_IOCTL *) data; + int rc = 1; dctlprintk((KERN_NOTICE MYNAM ": Timer Expired! Host %d\n", ioctl->ioc->id)); + if (ioctl == NULL) + return; + + if (ioctl->reset & MPTCTL_RESET_OK) + rc = mptctl_bus_reset(ioctl); + + if (rc) { + /* Issue a reset for this device. + * The IOC is not responding. + */ + mpt_HardResetHandler(ioctl->ioc, NO_SLEEP); + } + return; + +} + +/* mptctl_bus_reset + * + * Bus reset code. + * + */ +static int mptctl_bus_reset(MPT_IOCTL *ioctl) +{ + MPT_FRAME_HDR *mf; + SCSITaskMgmt_t *pScsiTm; + MPT_SCSI_HOST *hd; + int ii; + int retval; + + + ioctl->reset &= ~MPTCTL_RESET_OK; - /* Issue a reset for this device. - * The IOC is not responding. + if (ioctl->ioc->sh == NULL) + return -EPERM; + + hd = (MPT_SCSI_HOST *) ioctl->ioc->sh->hostdata; + if (hd == NULL) + return -EPERM; + + /* Single threading .... + */ + if (mptctl_set_tm_flags(hd) != 0) + return -EPERM; + + /* Send request */ - mpt_HardResetHandler(ioctl->ioc, NO_SLEEP); + if ((mf = mpt_get_msg_frame(mptctl_id, ioctl->ioc->id)) == NULL) { + dtmprintk((MYIOC_s_WARN_FMT "IssueTaskMgmt, no msg frames!!\n", + ioctl->ioc->name)); + + mptctl_free_tm_flags(ioctl->ioc); + return -ENOMEM; + } + + dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n", + ioctl->ioc->name, mf)); + + pScsiTm = (SCSITaskMgmt_t *) mf; + pScsiTm->TargetID = ioctl->target; + pScsiTm->Bus = hd->port; /* 0 */ + pScsiTm->ChainOffset = 0; + pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT; + pScsiTm->Reserved = 0; + pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS; + pScsiTm->Reserved1 = 0; + pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION; + + for (ii= 0; ii < 8; ii++) + pScsiTm->LUN[ii] = 0; + + for (ii=0; ii < 7; ii++) + pScsiTm->Reserved2[ii] = 0; + + pScsiTm->TaskMsgContext = 0; + dtmprintk((MYIOC_s_INFO_FMT "mptctl_bus_reset: issued.\n", ioctl->ioc->name)); + + ioctl->tmPtr = mf; + ioctl->TMtimer.expires = jiffies + HZ * 20; /* 20 seconds */ + ioctl->status |= MPT_IOCTL_STATUS_TMTIMER_ACTIVE; + add_timer(&ioctl->TMtimer); + + retval = mpt_send_handshake_request(mptctl_id, ioctl->ioc->id, + sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, NO_SLEEP); + + if (retval != 0) { + dtmprintk((MYIOC_s_WARN_FMT "_send_handshake FAILED!" + " (hd %p, ioc %p, mf %p) \n", ioctl->ioc->name, hd, hd->ioc, mf)); + + mptctl_free_tm_flags(ioctl->ioc); + del_timer(&ioctl->TMtimer); + mpt_free_msg_frame(mptctl_id, ioctl->ioc->id, mf); + ioctl->tmPtr = NULL; + } + + return retval; +} + +static int +mptctl_set_tm_flags(MPT_SCSI_HOST *hd) { + unsigned long flags; + + spin_lock_irqsave(&hd->ioc->FreeQlock, flags); +#ifdef MPT_SCSI_USE_NEW_EH + if (hd->tmState == TM_STATE_NONE) { + hd->tmState = TM_STATE_IN_PROGRESS; + hd->tmPending = 1; + spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); + } else { + spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); + return -EBUSY; + } +#else + if (hd->tmPending) { + spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); + return -EBUSY; + } else { + hd->tmPending = 1; + spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); + } +#endif + return 0; +} + +static void +mptctl_free_tm_flags(MPT_ADAPTER *ioc) +{ + MPT_SCSI_HOST * hd; + unsigned long flags; + + hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; + if (hd == NULL) + return; + + spin_lock_irqsave(&ioc->FreeQlock, flags); +#ifdef MPT_SCSI_USE_NEW_EH + hd->tmState = TM_STATE_ERROR; + hd->tmPending = 0; + spin_unlock_irqrestore(&ioc->FreeQlock, flags); +#else + hd->tmPending = 0; + spin_unlock_irqrestore(&ioc->FreeQlock, flags); +#endif + return; } + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* mptctl_ioc_reset * @@ -372,14 +533,17 @@ /* Someone has called the reset handler to * do a hard reset. No more replies from the FW. - * Delete the timer. + * Delete the timer. TM flags cleaned up by SCSI driver. + * Do not need to free msg frame, as re-initialized */ if (ioctl && (ioctl->status & MPT_IOCTL_STATUS_TIMER_ACTIVE)){ - - /* Delete this timer - */ del_timer(&ioctl->timer); } + if (ioctl && (ioctl->status & MPT_IOCTL_STATUS_TMTIMER_ACTIVE)){ + ioctl->status &= ~MPT_IOCTL_STATUS_TMTIMER_ACTIVE; + del_timer(&ioctl->TMtimer); + mpt_free_msg_frame(mptctl_id, ioc->id, ioctl->tmPtr); + } } else { /* Set the status and continue IOCTL @@ -388,7 +552,7 @@ * called. */ if (ioctl && (ioctl->status & MPT_IOCTL_STATUS_TIMER_ACTIVE)){ - ioctl->status = MPT_IOCTL_STATUS_DID_TIMEOUT; + ioctl->status = MPT_IOCTL_STATUS_DID_IOCRESET; /* Wake up the calling process */ @@ -459,6 +623,7 @@ } ret = -ENXIO; /* (-6) No such device or address */ + /* Test for Compaq-specific IOCTL's. */ if ((cmd == CPQFCTS_GETPCIINFO) || (cmd == CPQFCTS_CTLR_STATUS) || @@ -477,13 +642,15 @@ return -ENODEV; } + + /* Handle those commands that are just returning * information stored in the driver. * These commands should never time out and are unaffected * by TM and FW reloads. */ - if (cmd == MPTIOCINFO) { - return mptctl_getiocinfo(arg); + if ((cmd & ~IOCSIZE_MASK) == (MPTIOCINFO & ~IOCSIZE_MASK)) { + return mptctl_getiocinfo(arg, _IOC_SIZE(cmd)); } else if (cmd == MPTTARGETINFO) { return mptctl_gettargetinfo(arg); } else if (cmd == MPTTEST) { @@ -625,8 +792,8 @@ MPT_FRAME_HDR *mf; MPT_ADAPTER *iocp; FWDownloadTCSGE_t *ptsge; - MptSge_t *sgl; - MptSge_t *sgOut, *sgIn; + MptSge_t *sgl, *sgIn; + char *sgOut; struct buflist *buflist; struct buflist *bl; dma_addr_t sgl_dma; @@ -660,7 +827,7 @@ return -EAGAIN; dlmsg = (FWDownload_t*) mf; ptsge = (FWDownloadTCSGE_t *) &dlmsg->SGL; - sgOut = (MptSge_t *) (ptsge + 1); + sgOut = (char *) (ptsge + 1); /* * Construct f/w download request @@ -715,7 +882,8 @@ * 96 8 * 64 4 */ - maxfrags = (iocp->req_sz - sizeof(MPIHeader_t) - sizeof(FWDownloadTCSGE_t)) / sizeof(MptSge_t); + maxfrags = (iocp->req_sz - sizeof(MPIHeader_t) - sizeof(FWDownloadTCSGE_t)) + / (sizeof(dma_addr_t) + sizeof(u32)); if (numfrags > maxfrags) { ret = -EMLINK; goto fwdl_out; @@ -738,11 +906,11 @@ * Note: we should not have anything but Simple as * Chain SGE are illegal. */ - nib = (le32_to_cpu(sgIn->FlagsLength) & 0x30000000) >> 28; + nib = (sgIn->FlagsLength & 0x30000000) >> 28; if (nib == 0 || nib == 3) { ; - } else if (mptctl_test_address(sgIn)) { - *sgOut = *sgIn; + } else if (sgIn->Address) { + mpt_add_sge(sgOut, sgIn->FlagsLength, sgIn->Address); n++; if (copy_from_user(bl->kptr, ufwbuf+fw_bytes_copied, bl->len)) { printk(KERN_ERR "%s@%d::_ioctl_fwdl - " @@ -754,7 +922,7 @@ } sgIn++; bl++; - sgOut++; + sgOut += (sizeof(dma_addr_t) + sizeof(u32)); } #ifdef MPT_DEBUG @@ -840,22 +1008,19 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, int sge_offset, int *frags, struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc) { - MptSge_t *sglbuf = NULL; /* pointer to array of SGE - * and chain buffers */ + MptSge_t *sglbuf = NULL; /* pointer to array of SGE */ + /* and chain buffers */ struct buflist *buflist = NULL; /* kernel routine */ MptSge_t *sgl; - MptChain_t *last_chain = NULL; int numfrags = 0; int fragcnt = 0; int alloc_sz = MIN(bytes,MAX_KMALLOC_SZ); // avoid kernel warning msg! int bytes_allocd = 0; int this_alloc; dma_addr_t pa; // phys addr - int chaincnt = 0; int i, buflist_ent; int sg_spill = MAX_FRAGS_SPILL1; int dir; - /* initialization */ *frags = 0; *blp = NULL; @@ -892,7 +1057,7 @@ * */ sgl = sglbuf; - sg_spill = ((ioc->req_sz - sge_offset)/ sizeof(MptSge_t)) - 1; + sg_spill = ((ioc->req_sz - sge_offset)/(sizeof(dma_addr_t) + sizeof(u32))) - 1; while (bytes_allocd < bytes) { this_alloc = MIN(alloc_sz, bytes-bytes_allocd); buflist[buflist_ent].len = this_alloc; @@ -913,11 +1078,9 @@ dma_addr_t dma_addr; bytes_allocd += this_alloc; - - /* Write one SIMPLE sge */ - sgl->FlagsLength = cpu_to_le32(0x10000000|sgdir|this_alloc); + sgl->FlagsLength = (0x10000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|this_alloc); dma_addr = pci_map_single(ioc->pcidev, buflist[buflist_ent].kptr, this_alloc, dir); - cpu_to_leXX(dma_addr, sgl->Address); + sgl->Address = dma_addr; fragcnt++; numfrags++; @@ -930,52 +1093,13 @@ /* Need to chain? */ if (fragcnt == sg_spill) { - dma_addr_t chain_link; - - /* If there is a chain element, set the offset - * (in 32 bit words) to the next chain element. - * fragcnt = # sge = 8 bytes = 2 words - * - * Set the length of the chain element (bytes) - * This includes the size of the next chain element. - * - * We are now done with last_chain and the previous - * buffer. - */ - if (last_chain != NULL) { - last_chain->NextChainOffset = fragcnt * 2; - last_chain->Length = cpu_to_le16((fragcnt+1) * 8); - } - - /* Finish the current buffer: - * - add the LE bit to last sge - * - add the chain element - */ - sgl[-1].FlagsLength |= cpu_to_le32(0x80000000); - - chain_link = (*sglbuf_dma) + - ((u8 *)(sgl+1) - (u8 *)sglbuf); - - /* Write one CHAIN sge */ -// sgl->FlagsLength = cpu_to_le32(0x30000080); - sgl->FlagsLength = cpu_to_le32(0x30000000); - cpu_to_leXX(chain_link, sgl->Address); - - /* Reset everything for the next SGE series, - * save a ptr to the chain element in last_chain - */ - fragcnt = 0; -// sg_spill = MAX_FRAGS_SPILL2; - sg_spill = (ioc->req_sz / sizeof(MptSge_t)) - 1; - - last_chain = (MptChain_t*)sgl; - chaincnt++; - numfrags++; - sgl++; + printk(KERN_WARNING MYNAM "-SG: No can do - " "Chain required! :-(\n"); + printk(KERN_WARNING MYNAM "(freeing %d frags)\n", numfrags); + goto free_and_fail; } /* overflow check... */ - if (numfrags*8 > MAX_SGL_BYTES) { + if (numfrags*8 > MAX_SGL_BYTES){ /* GRRRRR... */ printk(KERN_WARNING MYNAM "-SG: No can do - " "too many SG frags! :-(\n"); @@ -986,19 +1110,14 @@ } /* Last sge fixup: set LE+eol+eob bits */ - sgl[-1].FlagsLength |= cpu_to_le32(0xC1000000); - - /* Chain fixup needed? */ /* SteveR CHECKME!!! */ -// if (last_chain != NULL && fragcnt < 16) - if (last_chain != NULL) - last_chain->Length = cpu_to_le16(fragcnt * 8); + sgl[-1].FlagsLength |= 0xC1000000; *frags = numfrags; *blp = buflist; dctlprintk((KERN_INFO MYNAM "-SG: kbuf_alloc_2_sgl() - " - "%d SG frags generated! (%d CHAIN%s)\n", - numfrags, chaincnt, chaincnt>1?"s":"")); + "%d SG frags generated!\n", + numfrags)); dctlprintk((KERN_INFO MYNAM "-SG: kbuf_alloc_2_sgl() - " "last (big) alloc_sz=%d\n", @@ -1015,10 +1134,10 @@ u8 *kptr; int len; - if ((le32_to_cpu(sglbuf[i].FlagsLength) >> 24) == 0x30) + if ((sglbuf[i].FlagsLength >> 24) == 0x30) continue; - leXX_to_cpu(dma_addr, sglbuf[i].Address); + dma_addr = sglbuf[i].Address; kptr = buflist[i].kptr; len = buflist[i].len; @@ -1043,22 +1162,22 @@ int dir; int n = 0; - if ((le32_to_cpu(sg->FlagsLength) & 0x04000000)) + if (sg->FlagsLength & 0x04000000) dir = PCI_DMA_TODEVICE; else dir = PCI_DMA_FROMDEVICE; - nib = (le32_to_cpu(sg->FlagsLength) & 0xF0000000) >> 28; + nib = (sg->FlagsLength & 0xF0000000) >> 28; while (! (nib & 0x4)) { /* eob */ /* skip ignore/chain. */ if (nib == 0 || nib == 3) { ; - } else if (mptctl_test_address(sg)) { + } else if (sg->Address) { dma_addr_t dma_addr; void *kptr; int len; - leXX_to_cpu(dma_addr, sg->Address); + dma_addr = sg->Address; kptr = bl->kptr; len = bl->len; pci_unmap_single(ioc->pcidev, dma_addr, len, dir); @@ -1071,12 +1190,12 @@ } /* we're at eob! */ - if (mptctl_test_address(sg)) { + if (sg->Address) { dma_addr_t dma_addr; void *kptr; int len; - leXX_to_cpu(dma_addr, sg->Address); + dma_addr = sg->Address; kptr = bl->kptr; len = bl->len; pci_unmap_single(ioc->pcidev, dma_addr, len, dir); @@ -1100,7 +1219,7 @@ * -ENODEV if no such device/adapter */ static int -mptctl_getiocinfo (unsigned long arg) +mptctl_getiocinfo (unsigned long arg, unsigned int data_size) { struct mpt_ioctl_iocinfo *uarg = (struct mpt_ioctl_iocinfo *) arg; struct mpt_ioctl_iocinfo karg; @@ -1113,10 +1232,18 @@ unsigned int max_id; int ii; int port; + int cim_rev; u8 revision; dctlprintk((": mptctl_getiocinfo called.\n")); - if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_iocinfo))) { + if (data_size == sizeof(struct mpt_ioctl_iocinfo)) + cim_rev = 1; + else if (data_size == (sizeof(struct mpt_ioctl_iocinfo) - sizeof(struct mpt_ioctl_pci_info))) + cim_rev = 0; + else + return -EFAULT; + + if (copy_from_user(&karg, uarg, data_size)) { printk(KERN_ERR "%s@%d::mptctl_getiocinfo - " "Unable to read in mpt_ioctl_iocinfo struct @ %p\n", __FILE__, __LINE__, (void*)uarg); @@ -1133,7 +1260,7 @@ /* Verify the data transfer size is correct. * Ignore the port setting. */ - if (karg.hdr.maxDataSize != sizeof(struct mpt_ioctl_iocinfo)) { + if (karg.hdr.maxDataSize != data_size) { printk(KERN_ERR "%s@%d::mptctl_getiocinfo - " "Structure size mismatch. Command not completed.\n", __FILE__, __LINE__); @@ -1161,10 +1288,17 @@ karg.subSystemVendor = pdev->subsystem_vendor; #endif + if (cim_rev == 1) { + /* Get the PCI bus, device, and function numbers for the IOC + */ + karg.pciInfo.u.bits.busNumber = pdev->bus->number; + karg.pciInfo.u.bits.deviceNumber = PCI_SLOT( pdev->devfn ); + karg.pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn ); + } + /* Get number of devices */ - if ( (sh = ioc->sh) != NULL) { - + if ((sh = ioc->sh) != NULL) { /* sh->max_id = maximum target ID + 1 */ max_id = sh->max_id - 1; @@ -1197,8 +1331,7 @@ /* Copy the data from kernel memory to user memory */ - if (copy_to_user((char *)arg, &karg, - sizeof(struct mpt_ioctl_iocinfo))) { + if (copy_to_user((char *)arg, &karg, data_size)) { printk(KERN_ERR "%s@%d::mptctl_getiocinfo - " "Unable to write out mpt_ioctl_iocinfo struct @ %p\n", __FILE__, __LINE__, (void*)uarg); @@ -1558,10 +1691,12 @@ struct mpt_ioctl_replace_fw *uarg = (struct mpt_ioctl_replace_fw *) arg; struct mpt_ioctl_replace_fw karg; MPT_ADAPTER *ioc; + fw_image_t **fwmem = NULL; int iocnum; - u8 *mem = NULL; - dma_addr_t mem_dma; - int oldFwSize, newFwSize; + int newFwSize; + int num_frags, alloc_sz; + int ii; + u32 offset; dctlprintk(("mptctl_replace_fw called.\n")); if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_replace_fw))) { @@ -1580,45 +1715,42 @@ /* If not caching FW, return 0 */ - if ((ioc->FWImage == NULL) && (ioc->alt_ioc) && (ioc->alt_ioc->FWImage == NULL)) { + if ((ioc->cached_fw == NULL) && (ioc->alt_ioc) && (ioc->alt_ioc->cached_fw == NULL)) return 0; - } - /* Allocate memory for the new FW image */ newFwSize = karg.newImageSize; - mem = pci_alloc_consistent(ioc->pcidev, newFwSize, &mem_dma); - if (mem == NULL) + fwmem = mpt_alloc_fw_memory(ioc, newFwSize, &num_frags, &alloc_sz); + if (fwmem == NULL) return -ENOMEM; - ioc->alloc_total += newFwSize; + offset = 0; + for (ii = 0; ii < num_frags; ii++) { + /* Copy the data from user memory to kernel space + */ + if (copy_from_user(fwmem[ii]->fw, uarg->newImage + offset, fwmem[ii]->size)) { + printk(KERN_ERR "%s@%d::mptctl_replace_fw - " + "Unable to read in mpt_ioctl_replace_fw image @ %p\n", + __FILE__, __LINE__, (void*)uarg); - /* Copy the data from user memory to kernel space - */ - if (copy_from_user(mem, uarg->newImage, newFwSize)) { - printk(KERN_ERR "%s@%d::mptctl_replace_fw - " - "Unable to read in mpt_ioctl_replace_fw image @ %p\n", - __FILE__, __LINE__, (void*)uarg); - pci_free_consistent(ioc->pcidev, newFwSize, mem, mem_dma); - ioc->alloc_total -= newFwSize; - return -EFAULT; + mpt_free_fw_memory(ioc, fwmem); + return -EFAULT; + } + offset += fwmem[ii]->size; } + /* Free the old FW image */ - oldFwSize = ioc->facts.FWImageSize; - if (ioc->FWImage) { - pci_free_consistent(ioc->pcidev, oldFwSize, ioc->FWImage, ioc->FWImage_dma); - ioc->alloc_total -= oldFwSize; - ioc->FWImage = mem; - ioc->FWImage_dma = mem_dma; - - } else if ((ioc->alt_ioc) && (ioc->alt_ioc->FWImage)) { - pci_free_consistent(ioc->pcidev, oldFwSize, ioc->alt_ioc->FWImage, ioc->alt_ioc->FWImage_dma); - ioc->alloc_total -= oldFwSize; - ioc->alt_ioc->FWImage = mem; - ioc->alt_ioc->FWImage_dma = mem_dma; + if (ioc->cached_fw) { + mpt_free_fw_memory(ioc, 0); + ioc->cached_fw = fwmem; + ioc->alloc_total += alloc_sz; + } else if ((ioc->alt_ioc) && (ioc->alt_ioc->cached_fw)) { + mpt_free_fw_memory(ioc->alt_ioc, 0); + ioc->alt_ioc->cached_fw = fwmem; + ioc->alt_ioc->alloc_total += alloc_sz; } /* Update IOCFactsReply @@ -1682,6 +1814,7 @@ * -ENODEV if no such device/adapter * -ETIME if timer expires * -ENOMEM if memory allocation error + * -EPERM if SCSI I/O and target is untagged */ static int mptctl_do_mpt_command (struct mpt_ioctl_command karg, char *mfPtr, int local) @@ -1689,7 +1822,7 @@ MPT_ADAPTER *ioc; MPT_FRAME_HDR *mf = NULL; MPIHeader_t *hdr; - MptSge_t *psge; + char *psge; MptSge_t *this_sge = NULL; MptSge_t *sglbuf = NULL; struct buflist bufIn; /* data In buffer */ @@ -1699,9 +1832,10 @@ int dir; /* PCI data direction */ int sgSize = 0; /* Num SG elements */ int this_alloc; - int iocnum, flagsLength; - int sz, rc = 0; - int msgContext; + int iocnum, flagsLength; + int sz, rc = 0; + int msgContext; + int tm_flags_set = 0; u16 req_idx; dctlprintk(("mptctl_do_mpt_command called.\n")); @@ -1717,7 +1851,7 @@ "No memory available during driver init.\n", __FILE__, __LINE__); return -ENOMEM; - } else if (ioc->ioctl->status & MPT_IOCTL_STATUS_DID_TIMEOUT) { + } else if (ioc->ioctl->status & MPT_IOCTL_STATUS_DID_IOCRESET) { printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "Busy with IOC Reset \n", __FILE__, __LINE__); return -EBUSY; @@ -1727,9 +1861,9 @@ */ sz = karg.dataSgeOffset * 4; if (karg.dataInSize > 0) - sz += sizeof (MptSge_t); + sz += sizeof(dma_addr_t) + sizeof(u32); if (karg.dataOutSize > 0) - sz += sizeof (MptSge_t); + sz += sizeof(dma_addr_t) + sizeof(u32); if ( sz > ioc->req_sz) { printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " @@ -1792,7 +1926,7 @@ int target = (int) pScsiReq->TargetID; int dataSize; - pScsiReq->MsgFlags = MPT_SCSIIO_MSG_FLAGS; + pScsiReq->MsgFlags = mpt_msg_flags(); /* verify that app has not requested * more sense data than driver @@ -1814,6 +1948,10 @@ if (pTarget &&(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)) qtag = MPI_SCSIIO_CONTROL_SIMPLEQ; + else { + rc = -EPERM; + goto done_free_mem; + } /* Have the IOCTL driver set the direction based * on the dataOutSize (ordering issue with Sparc). @@ -1830,6 +1968,9 @@ pScsiReq->Control = cpu_to_le32(scsidir | qtag); pScsiReq->DataLength = cpu_to_le32(dataSize); + ioc->ioctl->reset = MPTCTL_RESET_OK; + ioc->ioctl->target = target; + } else { printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "SCSI driver is not loaded. \n", @@ -1851,7 +1992,7 @@ int scsidir = MPI_SCSIIO_CONTROL_READ; int dataSize; - pScsiReq->MsgFlags = MPT_SCSIIO_MSG_FLAGS; + pScsiReq->MsgFlags = mpt_msg_flags(); /* verify that app has not requested * more sense data than driver @@ -1884,6 +2025,8 @@ pScsiReq->Control = cpu_to_le32(scsidir | qtag); pScsiReq->DataLength = cpu_to_le32(dataSize); + ioc->ioctl->reset = MPTCTL_RESET_OK; + ioc->ioctl->target = pScsiReq->TargetID; } else { printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "SCSI driver is not loaded. \n", @@ -1893,6 +2036,23 @@ } break; + case MPI_FUNCTION_SCSI_TASK_MGMT: + { + MPT_SCSI_HOST *hd = NULL; + if ((ioc->sh == NULL) || ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL)) { + printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + "SCSI driver not loaded or SCSI host not found. \n", + __FILE__, __LINE__); + rc = -EFAULT; + goto done_free_mem; + } else if (mptctl_set_tm_flags(hd) != 0) { + rc = -EPERM; + goto done_free_mem; + } + tm_flags_set = 1; + } + break; + default: /* * MPI_FUNCTION_IOC_INIT @@ -1908,7 +2068,6 @@ * MPI_FUNCTION_EVENT_NOTIFICATION * (driver handles event notification) * MPI_FUNCTION_EVENT_ACK - * MPI_FUNCTION_SCSI_TASK_MGMT */ /* What to do with these??? CHECK ME!!! @@ -1933,7 +2092,7 @@ * preceede the data in (read) SGE. psgList is used to free the * allocated memory. */ - psge = (MptSge_t *) ( ((int *) mf) + karg.dataSgeOffset); + psge = (char *) ( ((int *) mf) + karg.dataSgeOffset); flagsLength = 0; /* bufIn and bufOut are used for user to kernel space transfers @@ -1967,7 +2126,7 @@ if (karg.dataInSize > 0 ) { flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT | MPI_SGE_FLAGS_DIRECTION | - MPT_SGE_ADDRESS_SIZE ) + mpt_addr_size() ) << MPI_SGE_FLAGS_SHIFT; } else { flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE; @@ -2001,13 +2160,11 @@ /* Set up this SGE. * Copy to MF and to sglbuf */ + mpt_add_sge(psge, flagsLength, dma_addr); + psge += (sizeof(u32) + sizeof(dma_addr_t)); - psge->FlagsLength = cpu_to_le32 (flagsLength); - cpu_to_leXX(dma_addr, psge->Address); - psge++; - - this_sge->FlagsLength=cpu_to_le32(flagsLength); - cpu_to_leXX(dma_addr, this_sge->Address); + this_sge->FlagsLength = flagsLength; + this_sge->Address = dma_addr; this_sge++; } } @@ -2028,20 +2185,17 @@ /* Set up this SGE * Copy to MF and to sglbuf */ - psge->FlagsLength = cpu_to_le32 (flagsLength); - cpu_to_leXX(dma_addr, psge->Address); + mpt_add_sge(psge, flagsLength, dma_addr); - this_sge->FlagsLength=cpu_to_le32(flagsLength); - cpu_to_leXX(dma_addr, this_sge->Address); + this_sge->FlagsLength = flagsLength; + this_sge->Address = dma_addr; this_sge++; } } } else { /* Add a NULL SGE */ - flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ; - psge->FlagsLength = cpu_to_le32 (flagsLength); - cpu_to_leXX( (dma_addr_t) -1, psge->Address); + mpt_add_sge(psge, flagsLength, (dma_addr_t) -1); } /* The request is complete. Set the timer parameters @@ -2057,8 +2211,22 @@ ioc->ioctl->status |= MPT_IOCTL_STATUS_TIMER_ACTIVE; add_timer(&ioc->ioctl->timer); - mpt_put_msg_frame(mptctl_id, ioc->id, mf); - wait_event(mptctl_wait, ioc->ioctl->wait_done); + if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT) { + rc = mpt_send_handshake_request(mptctl_id, ioc->id, + sizeof(SCSITaskMgmt_t), (u32*)mf, NO_SLEEP); + if (rc == 0) { + wait_event(mptctl_wait, ioc->ioctl->wait_done); + } else { + mptctl_free_tm_flags(ioc); + tm_flags_set= 0; + del_timer(&ioc->ioctl->timer); + ioc->ioctl->status &= ~MPT_IOCTL_STATUS_TIMER_ACTIVE; + ioc->ioctl->status = MPT_IOCTL_STATUS_TM_FAILED; + } + } else { + mpt_put_msg_frame(mptctl_id, ioc->id, mf); + wait_event(mptctl_wait, ioc->ioctl->wait_done); + } /* The command is complete. * Return data to the user. * @@ -2068,7 +2236,7 @@ * If timeout, a recovery mechanism has been called. * Need to free the mf. */ - if (ioc->ioctl->status & MPT_IOCTL_STATUS_DID_TIMEOUT) { + if (ioc->ioctl->status & MPT_IOCTL_STATUS_DID_IOCRESET) { /* A timeout - there is no data to return to the * the user other than an error. @@ -2076,13 +2244,17 @@ * timer and reset the adapter queues. */ printk(KERN_WARNING "%s@%d::mptctl_do_mpt_command - " - "Timeout Occurred on IOCTL! Resetting IOC.\n", __FILE__, __LINE__); + "Timeout Occurred on IOCTL! Reset IOC.\n", __FILE__, __LINE__); + tm_flags_set= 0; rc = -ETIME; /* Free memory and return to the calling function */ goto done_free_mem; - + } else if (ioc->ioctl->status & MPT_IOCTL_STATUS_TM_FAILED) { + /* User TM request failed! + */ + rc = -ENODATA; } else { /* Callback freed request frame. */ @@ -2149,15 +2321,16 @@ */ ioc->ioctl->status = 0; + if (tm_flags_set) + mptctl_free_tm_flags(ioc); + if (sglbuf) { this_sge = sglbuf; /* Free the allocated memory. */ if (bufOut.kptr != NULL ) { - - leXX_to_cpu (dma_addr, this_sge->Address); - + dma_addr = this_sge->Address; this_sge++; /* go to next structure */ this_alloc = bufOut.len; pci_free_consistent(ioc->pcidev, @@ -2165,7 +2338,7 @@ } if (bufIn.kptr != NULL ) { - leXX_to_cpu (dma_addr, this_sge->Address); + dma_addr = this_sge->Address; this_alloc = bufIn.len; pci_free_consistent(ioc->pcidev, @@ -2288,7 +2461,7 @@ printk(KERN_ERR "%s@%d::mptctl_cpq_pciinfo - " "Unable to read in cpqfc_pci_info_struct @ %p\n", __FILE__, __LINE__, (void*)uarg); - return -EFAULT; + return -EINVAL; } if (((iocnum = mpt_verify_adapter(iocnumX, &ioc)) < 0) || @@ -2980,6 +3153,9 @@ init_timer (&ioc->ioctl->timer); ioc->ioctl->timer.data = (unsigned long) ioc->ioctl; ioc->ioctl->timer.function = mptctl_timer_expired; + init_timer (&ioc->ioctl->TMtimer); + ioc->ioctl->TMtimer.data = (unsigned long) ioc->ioctl; + ioc->ioctl->TMtimer.function = mptctl_timer_expired; } } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/message/fusion/mptctl.h linux.19rc3-ac4/drivers/message/fusion/mptctl.h --- linux.19rc3/drivers/message/fusion/mptctl.h 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/message/fusion/mptctl.h 2002-07-29 14:19:07.000000000 +0100 @@ -20,7 +20,7 @@ * (mailto:sjralston1@netscape.net) * (mailto:Pam.Delaney@lsil.com) * - * $Id: mptctl.h,v 1.9 2002/02/27 18:44:26 sralston Exp $ + * $Id: mptctl.h,v 1.10 2002/05/28 15:57:16 pdelaney Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -122,7 +122,6 @@ }; #endif /*}*/ - /* * IOCTL header structure. * iocnum - must be defined. @@ -150,6 +149,20 @@ /* + * PCI bus/device/function information structure. + */ +struct mpt_ioctl_pci_info { + union { + struct { + unsigned long deviceNumber : 5; + unsigned long functionNumber : 3; + unsigned long busNumber : 24; + } bits; + unsigned long asUlong; + } u; +}; + +/* * Adapter Information Page * Read only. * Data starts at offset 0xC @@ -173,6 +186,7 @@ char busChangeEvent; char hostId; char rsvd[2]; + struct mpt_ioctl_pci_info pciInfo; /* Added Rev 1 */ }; /* diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/message/fusion/mptlan.c linux.19rc3-ac4/drivers/message/fusion/mptlan.c --- linux.19rc3/drivers/message/fusion/mptlan.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/message/fusion/mptlan.c 2002-07-29 13:58:42.000000000 +0100 @@ -26,7 +26,7 @@ * Copyright (c) 2000-2002 LSI Logic Corporation * Originally By: Noah Romer * - * $Id: mptlan.c,v 1.51 2002/02/11 14:40:55 sralston Exp $ + * $Id: mptlan.c,v 1.52 2002/05/06 13:45:07 sshirron Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -669,7 +669,7 @@ /* Add check for Loginfo Flag in IOCStatus */ - switch (le16_to_cpu(pSendRep->IOCStatus)) { + switch (le16_to_cpu(pSendRep->IOCStatus) & MPI_IOCSTATUS_MASK) { case MPI_IOCSTATUS_SUCCESS: priv->stats.tx_packets += count; break; @@ -1045,7 +1045,8 @@ dioprintk((KERN_INFO MYNAM ": receive_post_reply: IOCStatus: %04x\n", le16_to_cpu(pRecvRep->IOCStatus))); - if (le16_to_cpu(pRecvRep->IOCStatus) & MPI_IOCSTATUS_LAN_CANCELED) + if ((le16_to_cpu(pRecvRep->IOCStatus) & MPI_IOCSTATUS_MASK) == + MPI_IOCSTATUS_LAN_CANCELED) return mpt_lan_receive_post_free(dev, pRecvRep); len = le32_to_cpu(pRecvRep->PacketLength); @@ -1436,7 +1437,7 @@ { struct net_device *dev; MPT_ADAPTER *curadapter; - int i = 0, j; + int i, j; show_mptmod_ver(LANAME, LANVER); @@ -1468,7 +1469,6 @@ for (j = 0; j < MPT_MAX_ADAPTERS; j++) { mpt_landev[j] = NULL; } - j = 0; curadapter = mpt_adapter_find_first(); while (curadapter != NULL) { @@ -1492,11 +1492,11 @@ // printk (KERN_INFO MYNAM ": %s/%s: Max_TX_outstanding = %d\n", // IOC_AND_NETDEV_NAMES_s_s(dev), // NETDEV_TO_LANPRIV_PTR(dev)->tx_max_out); + j = curadapter->id; mpt_landev[j] = dev; dlprintk((KERN_INFO MYNAM "/init: dev_addr=%p, mpt_landev[%d]=%p\n", dev, j, mpt_landev[j])); - j++; } else { printk (KERN_ERR MYNAM ": %s: Unable to register port%d as a LAN device\n", curadapter->name, diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/message/fusion/mptscsih.c linux.19rc3-ac4/drivers/message/fusion/mptscsih.c --- linux.19rc3/drivers/message/fusion/mptscsih.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/message/fusion/mptscsih.c 2002-07-29 13:58:42.000000000 +0100 @@ -26,7 +26,7 @@ * (mailto:sjralston1@netscape.net) * (mailto:Pam.Delaney@lsil.com) * - * $Id: mptscsih.c,v 1.80 2002/02/27 18:44:27 sralston Exp $ + * $Id: mptscsih.c,v 1.97 2002/07/03 13:11:01 pdelaney Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -158,9 +158,8 @@ static int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); static int mptscsih_io_direction(Scsi_Cmnd *cmd); -static int mptscsih_Add32BitSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt, +static int mptscsih_AddSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt, SCSIIORequest_t *pReq, int req_idx); -static void mptscsih_AddNullSGE(SCSIIORequest_t *pReq); static int mptscsih_getFreeChainBuffer(MPT_SCSI_HOST *hd, int *retIndex); static void mptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx); static int mptscsih_initChainBuffers (MPT_SCSI_HOST *hd, int init); @@ -168,6 +167,8 @@ static void copy_sense_data(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply); #ifndef MPT_SCSI_USE_NEW_EH static void search_taskQ_for_cmd(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd); +#else +static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd); #endif static u32 SCPNT_TO_LOOKUP_IDX(Scsi_Cmnd *sc); static MPT_FRAME_HDR *mptscsih_search_pendingQ(MPT_SCSI_HOST *hd, int scpnt_idx); @@ -180,10 +181,11 @@ static int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); static VirtDevice *mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen); -void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target); +void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56); static void clear_sense_flag(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq); static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq, char *data); static void mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags); +static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id); static int mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target, int flags); static int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); static void mptscsih_timer_expired(unsigned long data); @@ -194,6 +196,8 @@ #ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION static int mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io); static void mptscsih_domainValidation(void *hd); +static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id); +static void mptscsih_qas_check(MPT_SCSI_HOST *hd); static void mptscsih_doDv(MPT_SCSI_HOST *hd, int portnum, int target); static void mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage); static void mptscsih_fillbuf(char *buffer, int size, int index, int width); @@ -286,7 +290,9 @@ MPT_SCSI_HOST *hd; SCSIIORequest_t *pScsiReq; SCSIIOReply_t *pScsiReply; +#ifndef MPT_SCSI_USE_NEW_EH unsigned long flags; +#endif u16 req_idx; hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; @@ -294,7 +300,7 @@ if ((mf == NULL) || (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) { printk(MYIOC_s_ERR_FMT "%s req frame ptr! (=%p)!\n", - ioc->name, mf?"BAD":"NULL", mf); + ioc->name, mf?"BAD":"NULL", (void *) mf); /* return 1; CHECKME SteveR. Don't free. */ return 0; } @@ -403,6 +409,10 @@ * than an unsolicited DID_ABORT. */ sc->result = DID_RESET << 16; + + /* GEM Workaround. */ + if (hd->is_spi) + mptscsih_no_negotiate(hd, sc->target); break; case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */ @@ -411,6 +421,10 @@ search_taskQ_for_cmd(sc, hd); #endif sc->result = DID_RESET << 16; + + /* GEM Workaround. */ + if (hd->is_spi) + mptscsih_no_negotiate(hd, sc->target); break; case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */ @@ -606,9 +620,9 @@ sc->host_scribble = NULL; /* CHECKME! - Do we need to clear this??? */ - spin_lock_irqsave(&io_request_lock, flags); + MPT_HOST_LOCK(flags); sc->scsi_done(sc); /* Issue the command callback */ - spin_unlock_irqrestore(&io_request_lock, flags); + MPT_HOST_UNLOCK(flags); /* Free Chain buffers */ mptscsih_freeChainBuffers(hd, req_idx); @@ -700,6 +714,7 @@ unsigned long flags; dprintk((KERN_INFO MYNAM ": clean_taskQ called\n")); + spin_lock_irqsave(&ioc->FreeQlock, flags); if (! Q_IS_EMPTY(&hd->taskQ)) { mf = hd->taskQ.head; @@ -812,9 +827,9 @@ /* Do the OS callback. */ - spin_lock_irqsave(&io_request_lock, flags); + MPT_HOST_LOCK(flags); SCpnt->scsi_done(SCpnt); - spin_unlock_irqrestore(&io_request_lock, flags); + MPT_HOST_UNLOCK(flags); } return; @@ -871,7 +886,10 @@ MPT_FRAME_HDR *mf = NULL; int ii; int max = hd->ioc->req_depth; + +#ifndef MPT_SCSI_USE_NEW_EH unsigned long flags; +#endif dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n")); for (ii= 0; ii < max; ii++) { @@ -901,16 +919,26 @@ dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n", mf, SCpnt)); - /* Set status + /* Set status, free OS resources (SG DMA buffers) * Do OS callback - * Free chain buffers - * Free message frame + * Free driver resources (chain, msg buffers) */ + if (SCpnt->use_sg) { + pci_unmap_sg(hd->ioc->pcidev, (struct scatterlist *) SCpnt->request_buffer, + SCpnt->use_sg, scsi_to_pci_dma_dir(SCpnt->sc_data_direction)); + } else if (SCpnt->request_bufflen) { + scPrivate *my_priv; + + my_priv = (scPrivate *) &SCpnt->SCp; + pci_unmap_single(hd->ioc->pcidev, (dma_addr_t)(ulong)my_priv->p1, + SCpnt->request_bufflen, + scsi_to_pci_dma_dir(SCpnt->sc_data_direction)); + } SCpnt->result = DID_RESET << 16; SCpnt->host_scribble = NULL; - spin_lock_irqsave(&io_request_lock, flags); + MPT_HOST_LOCK(flags); SCpnt->scsi_done(SCpnt); /* Issue the command callback */ - spin_unlock_irqrestore(&io_request_lock, flags); + MPT_HOST_UNLOCK(flags); /* Free Chain buffers */ mptscsih_freeChainBuffers(hd, ii); @@ -922,6 +950,73 @@ return; } +#ifdef DROP_TEST +/* mptscsih_flush_drop_test - Free resources and do callback if + * DROP_TEST enabled. + * + * @hd: Pointer to a SCSI HOST structure + * + * Returns: None. + * + * Must be called while new I/Os are being queued. + */ +static void +mptscsih_flush_drop_test (MPT_SCSI_HOST *hd) +{ + Scsi_Cmnd *sc; + unsigned long flags; + u16 req_idx; + + /* Free resources for the drop test MF + * and chain buffers. + */ + if (dropMfPtr) { + req_idx = le16_to_cpu(dropMfPtr->u.frame.hwhdr.msgctxu.fld.req_idx); + sc = hd->ScsiLookup[req_idx]; + if (sc == NULL) { + printk(MYIOC_s_ERR_FMT "Drop Test: NULL ScsiCmd ptr!\n", + ioc->name); + } else { + /* unmap OS resources, set status, do callback + * free driver resources + */ + if (sc->use_sg) { + pci_unmap_sg(ioc->pcidev, (struct scatterlist *) sc->request_buffer, + sc->use_sg, scsi_to_pci_dma_dir(sc->sc_data_direction)); + } else if (sc->request_bufflen) { + scPrivate *my_priv; + + my_priv = (scPrivate *) &sc->SCp; + pci_unmap_single(ioc->pcidev, (dma_addr_t)(ulong)my_priv->p1, + sc->request_bufflen, + scsi_to_pci_dma_dir(sc->sc_data_direction)); + } + + sc->host_scribble = NULL; + sc->result = DID_RESET << 16; + hd->ScsiLookup[req_idx] = NULL; + atomic_dec(&queue_depth); + MPT_HOST_LOCK(flags); + sc->scsi_done(sc); /* Issue callback */ + MPT_HOST_UNLOCK(flags); + } + + mptscsih_freeChainBuffers(hd, req_idx); + mpt_free_msg_frame(ScsiDoneCtx, ioc->id, dropMfPtr); + printk(MYIOC_s_INFO_FMT "Free'd Dropped cmd (%p)\n", + hd->ioc->name, sc); + printk(MYIOC_s_INFO_FMT "mf (%p) reqidx (%4x)\n", + hd->ioc->name, dropMfPtr, req_idx); + printk(MYIOC_s_INFO_FMT "Num Tot (%d) Good (%d) Bad (%d) \n", + hd->ioc->name, dropTestNum, + dropTestOK, dropTestBad); + } + dropMfPtr = NULL; + + return; +} +#endif + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * mptscsih_initChainBuffers - Allocate memory for and initialize @@ -951,7 +1046,7 @@ sz = numChain * sizeof(int); if (hd->ReqToChain == NULL) { - mem = kmalloc(sz, GFP_KERNEL); + mem = kmalloc(sz, GFP_ATOMIC); if (mem == NULL) return -1; @@ -962,7 +1057,7 @@ memset(mem, 0xFF, sz); if (hd->ChainToChain == NULL) { - mem = kmalloc(sz, GFP_KERNEL); + mem = kmalloc(sz, GFP_ATOMIC); if (mem == NULL) return -1; @@ -1038,7 +1133,7 @@ if (time - last_queue_full > 10 * HZ) { char *ioc_str = "ioc?"; - if (sc->host && sc->host->hostdata) + if (sc->host != NULL && sc->host->hostdata != NULL) ioc_str = ((MPT_SCSI_HOST *)sc->host->hostdata)->ioc->name; printk(MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n", ioc_str, 0, sc->target, sc->lun); @@ -1175,21 +1270,21 @@ /* Verify that we won't exceed the maximum * number of chain buffers - * We can optimize: ZZ = req_sz/sizeof(MptSge_t) + * We can optimize: ZZ = req_sz/sizeof(SGE) * For 32bit SGE's: * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ - * + (req_sz - 64)/sizeof(MptSge_t) + * + (req_sz - 64)/sizeof(SGE) * A slightly different algorithm is required for * 64bit SGEs. */ - scale = this->req_sz/sizeof(MptSge_t); - if (sizeof(MptSge_t) == sizeof(SGESimple32_t)) { - numSGE = 1 + (scale - 1) * (this->facts.MaxChainDepth-1) + scale + - (this->req_sz - 64) / (sizeof(MptSge_t)); - } else if (sizeof(MptSge_t) == sizeof(SGESimple64_t)) { + scale = this->req_sz/(sizeof(dma_addr_t) + sizeof(u32)); + if (sizeof(dma_addr_t) == sizeof(u64)) { numSGE = (scale - 1) * (this->facts.MaxChainDepth-1) + scale + - (this->req_sz - 60) / (sizeof(MptSge_t)); - } + (this->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32)); + } else { + numSGE = 1 + (scale - 1) * (this->facts.MaxChainDepth-1) + scale + + (this->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32)); + } if (numSGE < sh->sg_tablesize) { /* Reset this value */ @@ -1199,6 +1294,10 @@ sh->sg_tablesize = numSGE; } + /* Set the pci device pointer in Scsi_Host structure. + */ + scsi_set_pci_device(sh, this->pcidev); + restore_flags(flags); hd = (MPT_SCSI_HOST *) sh->hostdata; @@ -1217,7 +1316,7 @@ * (with size equal to req_depth*PtrSz!) */ sz = hd->ioc->req_depth * sizeof(void *); - mem = kmalloc(sz, GFP_KERNEL); + mem = kmalloc(sz, GFP_ATOMIC); if (mem == NULL) goto done; @@ -1233,7 +1332,7 @@ /* Allocate memory for free and doneQ's */ sz = sh->can_queue * sizeof(MPT_DONE_Q); - mem = kmalloc(sz, GFP_KERNEL); + mem = kmalloc(sz, GFP_ATOMIC); if (mem == NULL) goto done; @@ -1266,7 +1365,7 @@ * max_id = 1 + maximum id (hosts.h) */ sz = sh->max_id * sizeof(void *); - mem = kmalloc(sz, GFP_KERNEL); + mem = kmalloc(sz, GFP_ATOMIC); if (mem == NULL) goto done; @@ -1279,6 +1378,9 @@ /* Clear the TM flags */ hd->tmPending = 0; +#ifdef MPT_SCSI_USE_NEW_EH + hd->tmState = TM_STATE_NONE; +#endif hd->resetPending = 0; hd->abortSCpnt = NULL; hd->tmPtr = NULL; @@ -1387,10 +1489,9 @@ spin_unlock_irqrestore(&dvtaskQ_lock, flags); #endif + count = 10 * HZ; spin_lock_irqsave(&mytaskQ_lock, flags); if (mytaskQ_bh_active) { - count = 10 * HZ; - spin_unlock_irqrestore(&mytaskQ_lock, flags); dprintk((KERN_INFO MYNAM ": Info: Zapping TaskMgmt thread!\n")); clean_taskQ(hd); @@ -1399,23 +1500,27 @@ set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1); } - if (!count) - printk(KERN_ERR MYNAM ": ERROR - TaskMgmt thread still active!\n"); + } else { + spin_unlock_irqrestore(&mytaskQ_lock, flags); } - spin_unlock_irqrestore(&mytaskQ_lock, flags); + if (!count) + printk(KERN_ERR MYNAM ": ERROR - TaskMgmt thread still active!\n"); + #endif #ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION /* Check DV thread active */ count = 10 * HZ; spin_lock_irqsave(&dvtaskQ_lock, flags); - while(dvtaskQ_active && --count) { + if (dvtaskQ_active) { + spin_unlock_irqrestore(&dvtaskQ_lock, flags); + while(dvtaskQ_active && --count) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); + } + } else { spin_unlock_irqrestore(&dvtaskQ_lock, flags); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - spin_lock_irqsave(&dvtaskQ_lock, flags); } - spin_unlock_irqrestore(&dvtaskQ_lock, flags); if (!count) printk(KERN_ERR MYNAM ": ERROR - DV thread still active!\n"); #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY) @@ -1428,6 +1533,8 @@ if (hd != NULL) { int sz1, sz2, sz3, sztarget=0; + int szr2chain = 0; + int szc2chain = 0; int szchain = 0; int szQ = 0; int scale; @@ -1452,20 +1559,20 @@ } if (hd->ReqToChain != NULL) { - szchain += scale * hd->ioc->req_depth * sizeof(int); + szr2chain = scale * hd->ioc->req_depth * sizeof(int); kfree(hd->ReqToChain); hd->ReqToChain = NULL; } if (hd->ChainToChain != NULL) { - szchain += scale * hd->ioc->req_depth * sizeof(int); + szc2chain = scale * hd->ioc->req_depth * sizeof(int); kfree(hd->ChainToChain); hd->ChainToChain = NULL; } if (hd->ChainBuffer != NULL) { sz2 = scale * hd->ioc->req_depth * hd->ioc->req_sz; - szchain += sz2; + szchain = szr2chain + szc2chain + sz2; pci_free_consistent(hd->ioc->pcidev, sz2, hd->ChainBuffer, hd->ChainBufferDMA); @@ -1772,10 +1879,10 @@ * will be no data transfer! GRRRRR... */ datadir = mptscsih_io_direction(SCpnt); - if (datadir < 0) { + if (datadir == SCSI_DATA_READ) { datalen = SCpnt->request_bufflen; scsidir = MPI_SCSIIO_CONTROL_READ; /* DATA IN (host<--ioc<--dev) */ - } else if (datadir > 0) { + } else if (datadir == SCSI_DATA_WRITE) { datalen = SCpnt->request_bufflen; scsidir = MPI_SCSIIO_CONTROL_WRITE; /* DATA OUT (host-->ioc-->dev) */ } else { @@ -1812,7 +1919,7 @@ pScsiReq->CDBLength = SCpnt->cmd_len; pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE; pScsiReq->Reserved = 0; - pScsiReq->MsgFlags = MPT_SCSIIO_MSG_FLAGS; + pScsiReq->MsgFlags = mpt_msg_flags(); pScsiReq->LUN[0] = 0; pScsiReq->LUN[1] = lun; pScsiReq->LUN[2] = 0; @@ -1845,10 +1952,11 @@ rc = SUCCESS; if (datalen == 0) { /* Add a NULL SGE */ - mptscsih_AddNullSGE(pScsiReq); + mpt_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0, + (dma_addr_t) -1); } else { /* Add a 32 or 64 bit SGE */ - rc = mptscsih_Add32BitSGE(hd, SCpnt, pScsiReq, my_idx); + rc = mptscsih_AddSGE(hd, SCpnt, pScsiReq, my_idx); } @@ -1896,11 +2004,15 @@ if (dvStatus || hd->ioc->spi_data.forceDv) { - /* Write SDP1 on 1st I/O to this target */ + /* Write SDP1 on this I/O to this target */ if (dvStatus & MPT_SCSICFG_NEGOTIATE) { mptscsih_writeSDP1(hd, 0, target, hd->negoNvram); dvStatus &= ~MPT_SCSICFG_NEGOTIATE; hd->ioc->spi_data.dvStatus[target] = dvStatus; + } else if (dvStatus & MPT_SCSICFG_BLK_NEGO) { + mptscsih_writeSDP1(hd, 0, target, MPT_SCSICFG_BLK_NEGO); + dvStatus &= ~MPT_SCSICFG_BLK_NEGO; + hd->ioc->spi_data.dvStatus[target] = dvStatus; } #ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION @@ -1910,14 +2022,16 @@ spin_lock_irqsave(&dvtaskQ_lock, lflags); if (!dvtaskQ_active) { dvtaskQ_active = 1; + spin_unlock_irqrestore(&dvtaskQ_lock, lflags); mptscsih_dvTask.sync = 0; mptscsih_dvTask.routine = mptscsih_domainValidation; mptscsih_dvTask.data = (void *) hd; SCHEDULE_TASK(&mptscsih_dvTask); + } else { + spin_unlock_irqrestore(&dvtaskQ_lock, lflags); } hd->ioc->spi_data.forceDv = 0; - spin_unlock_irqrestore(&dvtaskQ_lock, lflags); } /* Trying to do DV to this target, extend timeout. @@ -1995,7 +2109,7 @@ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* - * mptscsih_Add32BitSGE - Add a 32Bit SGE (plus chain buffers) to the + * mptscsih_AddSGE - Add a SGE (plus chain buffers) to the * SCSIIORequest_t Message Frame. * @hd: Pointer to MPT_SCSI_HOST structure * @SCpnt: Pointer to Scsi_Cmnd structure @@ -2004,19 +2118,19 @@ * Returns ... */ static int -mptscsih_Add32BitSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt, +mptscsih_AddSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt, SCSIIORequest_t *pReq, int req_idx) { - MptSge_t *psge; - MptChain_t *chainSge; + char *psge; + char *chainSge; struct scatterlist *sg; int frm_sz; int sges_left, sg_done; int chain_idx = MPT_HOST_NO_CHAIN; int sgeOffset; int numSgeSlots, numSgeThisFrame; - u32 sgflags, sgdir, len, thisxfer = 0; - int offset; + u32 sgflags, sgdir, thisxfer = 0; + int chain_dma_off = 0; int newIndex; int ii; dma_addr_t v2; @@ -2028,7 +2142,7 @@ sgdir = MPT_TRANSFER_IOC_TO_HOST; } - psge = (MptSge_t *) &pReq->SGL; + psge = (char *) &pReq->SGL; frm_sz = hd->ioc->req_sz; /* Map the data portion, if any. @@ -2056,10 +2170,9 @@ dsgprintk((MYIOC_s_INFO_FMT "SG: non-SG for %p, len=%d\n", hd->ioc->name, SCpnt, SCpnt->request_bufflen)); - /* 0xD1000000 = LAST | EOB | SIMPLE | EOL */ - psge->FlagsLength = cpu_to_le32( - 0xD1000000|sgdir|SCpnt->request_bufflen); - cpu_to_leXX(buf_dma_addr, psge->Address); + mpt_add_sge((char *) &pReq->SGL, + 0xD1000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|SCpnt->request_bufflen, + buf_dma_addr); return SUCCESS; } @@ -2078,7 +2191,7 @@ */ nextSGEset: - numSgeSlots = ((frm_sz - sgeOffset) / sizeof(MptSge_t)); + numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) ); numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots; sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir; @@ -2095,14 +2208,12 @@ continue; } - len += thisxfer; - psge->FlagsLength = cpu_to_le32( sgflags | thisxfer ); v2 = sg_dma_address(sg); - cpu_to_leXX(v2, psge->Address); + mpt_add_sge(psge, sgflags | thisxfer, v2); sg++; /* Get next SG element from the OS */ - psge++; /* Point to next SG location in this MF */ - sgeOffset += sizeof(MptSge_t); + psge += (sizeof(u32) + sizeof(dma_addr_t)); + sgeOffset += (sizeof(u32) + sizeof(dma_addr_t)); sg_done++; } @@ -2111,19 +2222,20 @@ */ sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT | MPT_SGE_FLAGS_END_OF_BUFFER | - MPT_SGE_FLAGS_ADDRESSING | MPT_SGE_FLAGS_END_OF_LIST; /* Add last SGE and set termination flags. * Note: Last SGE may have a length of 0 - which should be ok. */ thisxfer = sg_dma_len(sg); - len += thisxfer; - psge->FlagsLength = cpu_to_le32( sgflags | thisxfer ); v2 = sg_dma_address(sg); - cpu_to_leXX(v2, psge->Address); - + mpt_add_sge(psge, sgflags | thisxfer, v2); + /* + sg++; + psge += (sizeof(u32) + sizeof(dma_addr_t)); + */ + sgeOffset += (sizeof(u32) + sizeof(dma_addr_t)); sg_done++; if (chainSge) { @@ -2132,9 +2244,7 @@ * Update the chain element * Offset and Length fields. */ - chainSge->NextChainOffset = 0; - sgeOffset += sizeof(MptSge_t); - chainSge->Length = cpu_to_le16(sgeOffset); + mpt_add_chain((char *)chainSge, 0, sgeOffset, hd->ChainBufferDMA + chain_dma_off); } else { /* The current buffer is the original MF * and there is no Chain buffer. @@ -2163,11 +2273,10 @@ * set properly). */ if (sg_done) { - psge--; - sgflags = le32_to_cpu (psge->FlagsLength); + u32 *ptmp = (u32 *) (psge - (sizeof(u32) + sizeof(dma_addr_t))); + sgflags = le32_to_cpu(*ptmp); sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT; - psge->FlagsLength = cpu_to_le32( sgflags ); - psge++; + *ptmp = cpu_to_le32(sgflags); } if (chainSge) { @@ -2177,9 +2286,9 @@ * include chain element size) fields. * Old chain element is now complete. */ - chainSge->NextChainOffset = (u8) (sgeOffset >> 2); - sgeOffset += sizeof(MptSge_t); - chainSge->Length = cpu_to_le16(sgeOffset); + u8 nextChain = (u8) (sgeOffset >> 2); + sgeOffset += (sizeof(u32) + sizeof(dma_addr_t)); + mpt_add_chain((char *)chainSge, nextChain, sgeOffset, hd->ChainBufferDMA + chain_dma_off); } else { /* The original MF buffer requires a chain buffer - * set the offset. @@ -2206,22 +2315,19 @@ hd->ReqToChain[req_idx] = newIndex; } chain_idx = newIndex; - offset = hd->ioc->req_sz * chain_idx; + chain_dma_off = hd->ioc->req_sz * chain_idx; /* Populate the chainSGE for the current buffer. * - Set chain buffer pointer to psge and fill * out the Address and Flags fields. */ - chainSge = (MptChain_t *) psge; - chainSge->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT; - cpu_to_leXX ((hd->ChainBufferDMA + offset), chainSge->Address); - + chainSge = (char *) psge; dsgprintk((KERN_INFO " Current buff @ %p (index 0x%x)", psge, req_idx)); /* Start the SGE for the next buffer */ - psge = (MptSge_t *) (hd->ChainBuffer + offset); + psge = (char *) (hd->ChainBuffer + chain_dma_off); sgeOffset = 0; sg_done = 0; @@ -2239,25 +2345,6 @@ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* - * mptscsih_AddNullSGE - Add a NULL SGE to the SCSIIORequest_t - * Message Frame. - * @pReq: Pointer to SCSIIORequest_t structure - */ -static void -mptscsih_AddNullSGE(SCSIIORequest_t *pReq) -{ - MptSge_t *psge; - - psge = (MptSge_t *) &pReq->SGL; - psge->FlagsLength = cpu_to_le32(MPT_SGE_FLAGS_SSIMPLE_READ | 0); - - cpu_to_leXX( (dma_addr_t) -1, psge->Address); - - return; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* * mptscsih_getFreeChainBuffes - Function to get a free chain * from the MPT_SCSI_HOST FreeChainQ. * @hd: Pointer to the MPT_SCSI_HOST instance @@ -2333,11 +2420,9 @@ chain = (MPT_FRAME_HDR *) (hd->ChainBuffer + (chain_idx * hd->ioc->req_sz)); - //spin_lock_irqsave(&hd->FreeChainQlock, flags); spin_lock_irqsave(&hd->ioc->FreeQlock, flags); Q_ADD_TAIL(&hd->FreeChainQ.head, &chain->u.frame.linkage, MPT_FRAME_HDR); - //spin_unlock_irqrestore(&hd->FreeChainQlock, flags); spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); dmfprintk((MYIOC_s_INFO_FMT "FreeChainBuffers (index %d)\n", @@ -2386,7 +2471,7 @@ /* If FW is being reloaded currently, return success to * the calling function. */ - if (!hd) + if (hd == NULL) return 0; ioc = hd->ioc; @@ -2431,6 +2516,9 @@ */ rc = mptscsih_IssueTaskMgmt(hd, type, target, lun, ctx2abort, sleepFlag); if (rc) { +#ifdef MPT_SCSI_USE_NEW_EH + hd->tmState = TM_STATE_ERROR; +#endif printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name); } else { printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name); @@ -2484,7 +2572,7 @@ MPT_FRAME_HDR *mf; SCSITaskMgmt_t *pScsiTm; int ii; - int retval = 0; + int retval; /* Return Fail to calling function if no message frames available. */ @@ -2508,7 +2596,8 @@ pScsiTm->Reserved = 0; pScsiTm->TaskType = type; pScsiTm->Reserved1 = 0; - pScsiTm->MsgFlags = 0; + pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) + ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0; for (ii= 0; ii < 8; ii++) { pScsiTm->LUN[ii] = 0; @@ -2540,7 +2629,6 @@ hd->tmPtr = NULL; del_timer(&hd->TMtimer); mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf); - return ii; } return retval; @@ -2564,41 +2652,62 @@ unsigned long flags; u32 ctx2abort; int scpnt_idx; - u8 type; - - printk(KERN_WARNING MYNAM ": Attempting ABORT SCSI IO (=%p)\n", SCpnt); - printk(KERN_WARNING MYNAM ": IOs outstanding = %d\n", atomic_read(&queue_depth)); + /* If we can't locate our host adapter structure, return FAILED status. + */ if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL) { SCpnt->result = DID_RESET << 16; - spin_lock_irqsave(&io_request_lock, flags); SCpnt->scsi_done(SCpnt); - spin_unlock_irqrestore(&io_request_lock, flags); - return SUCCESS; + nehprintk((KERN_WARNING MYNAM ": mptscsih_abort: " + "Can't locate host! (sc=%p)\n", + SCpnt)); + return FAILED; } + printk(KERN_WARNING MYNAM ": %s: >> Attempting task abort! (sc=%p)\n", + hd->ioc->name, SCpnt); + printk(KERN_WARNING MYNAM ": %s: IOs outstanding = %d\n", + hd->ioc->name, atomic_read(&queue_depth)); + /* Find this command */ if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) { - /* Cmd not found in ScsiLookup. If found in + /* Cmd not found in ScsiLookup. If found in * doneQ, delete from Q. Do OS callback. */ search_doneQ_for_cmd(hd, SCpnt); SCpnt->result = DID_RESET << 16; - spin_lock_irqsave(&io_request_lock, flags); SCpnt->scsi_done(SCpnt); - spin_unlock_irqrestore(&io_request_lock, flags); + nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: " + "Command not in the active list! (sc=%p)\n", + hd->ioc->name, SCpnt)); return SUCCESS; } + /* Wait a fixed amount of time for the TM pending flag to be cleared. + * If we time out, then we return a FAILED status to the caller. This + * call to mptscsih_tm_pending_wait() will set the pending flag if we are + * successful. + */ + if (mptscsih_tm_pending_wait(hd) == FAILED){ + nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: " + "Timed out waiting for previous TM to complete! " + "(sc = %p)\n", + hd->ioc->name, SCpnt)); + return FAILED; + } + /* If this command is pended, then timeout/hang occurred - * during DV. Post command and flush pending Q + * during DV. Post command and flush pending Q * and then following up with the reset request. */ if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) { mptscsih_put_msgframe(ScsiDoneCtx, hd->ioc->id, mf); post_pendingQ_commands(hd); + nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: " + "Found command in pending queue! (sc=%p)\n", + hd->ioc->name, SCpnt)); } /* Most important! Set TaskMsgContext to SCpnt's MsgContext! @@ -2611,61 +2720,62 @@ mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx); ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext; - /* This thread will not exit until tmPending is cleared - * FIXME - must ensure single threaded....DV conflict possible - */ - spin_lock_irqsave(&hd->ioc->FreeQlock, flags); - hd->tmPending = 1; - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - - if (hd->is_spi) - type = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS; - else { - type = MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK; - hd->abortSCpnt = SCpnt; - printk(KERN_WARNING MYNAM ": Attempting ABORT SCSI IO! (sc=%p)\n", SCpnt); - } + hd->abortSCpnt = SCpnt; - if (mptscsih_TMHandler(hd, type, - SCpnt->target, SCpnt->lun, ctx2abort, CAN_SLEEP) < 0) { + if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, + SCpnt->target, SCpnt->lun, ctx2abort, CAN_SLEEP) + < 0 + || hd->tmState == TM_STATE_ERROR) { /* The TM request failed and the subsequent FW-reload failed! * Fatal error case. */ - printk(MYIOC_s_WARN_FMT "Error processing TaskMgmt request (sc=%p)\n", - hd->ioc->name, SCpnt); + printk(MYIOC_s_WARN_FMT "Error issuing abort task! (sc=%p)\n", + hd->ioc->name, SCpnt); /* If command not found, do not do callback, - * just return failed. CHECKME + * just return failed. CHECKME */ if (hd->ScsiLookup[scpnt_idx] != NULL) { - //atomic_dec(&queue_depth); SCpnt->result = STS_BUSY; - spin_lock_irqsave(&io_request_lock, flags); SCpnt->scsi_done(SCpnt); - spin_unlock_irqrestore(&io_request_lock, flags); } - spin_lock_irqsave(&hd->ioc->FreeQlock, flags); + /* We must clear our pending flag before clearing our state. + */ hd->tmPending = 0; - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - } + hd->tmState = TM_STATE_NONE; + return FAILED; + } - /* Spin on tmPending until we get the interrupt for this TM request. + /* Our task management request will either complete or time out. So we + * spin until tmPending is != 1. If tmState is set to TM_STATE_ERROR, + * we encountered an error executing the task management request. */ - while (1) { - spin_lock_irqsave(&hd->ioc->FreeQlock, flags); - if (!hd->tmPending) { - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - break; - } - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); + while (hd->tmPending == 1){ set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ/4); } + spin_lock_irqsave(&hd->ioc->FreeQlock, flags); + if (hd->tmState == TM_STATE_ERROR){ + hd->tmState = TM_STATE_NONE; + spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); + nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: " + "TM timeout error! (sc=%p)\n", + hd->ioc->name, + SCpnt)); + return FAILED; + } + hd->tmState = TM_STATE_NONE; + spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - return FAILED; + nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: " + "Abort was successful! (sc=%p)\n", + hd->ioc->name, + SCpnt)); + + return SUCCESS; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -2681,98 +2791,75 @@ mptscsih_dev_reset(Scsi_Cmnd * SCpnt) { MPT_SCSI_HOST *hd; - MPT_FRAME_HDR *mf; unsigned long flags; - int scpnt_idx; - u8 type; - printk(KERN_WARNING MYNAM ": Attempting _TARGET_RESET (%p)\n", SCpnt); - printk(KERN_WARNING MYNAM ": IOs outstanding = %d\n", atomic_read(&queue_depth)); - - if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL) { - SCpnt->result = DID_RESET << 16; - spin_lock_irqsave(&io_request_lock, flags); - SCpnt->scsi_done(SCpnt); - spin_unlock_irqrestore(&io_request_lock, flags); - return SUCCESS; - } - - /* Find this command + /* If we can't locate our host adapter structure, return FAILED status. */ - if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) { - /* Cmd not found in ScsiLookup. If found in - * doneQ, delete from Q. Do OS callback. - */ - search_doneQ_for_cmd(hd, SCpnt); - - SCpnt->result = DID_RESET << 16; - spin_lock_irqsave(&io_request_lock, flags); - SCpnt->scsi_done(SCpnt); - spin_unlock_irqrestore(&io_request_lock, flags); - return SUCCESS; - } - - /* If this command is pended, then timeout/hang occurred - * during DV. Force bus reset by posting command to F/W - * and then following up with the reset request. - */ - if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) { - mptscsih_put_msgframe(ScsiDoneCtx, hd->ioc->id, mf); - post_pendingQ_commands(hd); + if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL){ + nehprintk((KERN_WARNING MYNAM ": mptscsih_dev_reset: " + "Can't locate host! (sc=%p)\n", + SCpnt)); + return FAILED; } - /* This thread will not exit until tmPending is cleared - */ - spin_lock_irqsave(&hd->ioc->FreeQlock, flags); - hd->tmPending = 1; - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - - if (hd->is_spi) - type = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS; - else { - type = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET; - printk(KERN_WARNING MYNAM ": Attempting Target Reset! (sc=%p)\n", SCpnt); + printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p)\n", + hd->ioc->name, SCpnt); + printk(KERN_WARNING MYNAM ": %s: IOs outstanding = %d\n", + hd->ioc->name, atomic_read(&queue_depth)); + + /* Wait a fixed amount of time for the TM pending flag to be cleared. + * If we time out, then we return a FAILED status to the caller. This + * call to mptscsih_tm_pending_wait() will set the pending flag if we are + * successful. + */ + if (mptscsih_tm_pending_wait(hd) == FAILED) { + nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_dev_reset: " + "Timed out waiting for previous TM to complete! " + "(sc = %p)\n", + hd->ioc->name, SCpnt)); + return FAILED; } if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, - SCpnt->target, 0, 0, CAN_SLEEP) < 0) { + SCpnt->target, 0, 0, CAN_SLEEP) + < 0){ /* The TM request failed and the subsequent FW-reload failed! * Fatal error case. */ printk(MYIOC_s_WARN_FMT "Error processing TaskMgmt request (sc=%p)\n", hd->ioc->name, SCpnt); - - /* If command not found, do not do callback, - * just returned failed. CHECKME. - */ - if (hd->ScsiLookup[scpnt_idx] != NULL) { - //atomic_dec(&queue_depth); - SCpnt->result = STS_BUSY; - spin_lock_irqsave(&io_request_lock, flags); - SCpnt->scsi_done(SCpnt); - spin_unlock_irqrestore(&io_request_lock, flags); - } - - spin_lock_irqsave(&hd->ioc->FreeQlock, flags); hd->tmPending = 0; - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); + hd->tmState = TM_STATE_NONE; + return FAILED; } - /* Spin on tmPending until we get the interrupt for this TM request. + /* Our task management request will either complete or time out. So we + * spin until tmPending is != 1. If tmState is set to TM_STATE_ERROR, + * we encountered an error executing the task management request. */ - while (1) { - spin_lock_irqsave(&hd->ioc->FreeQlock, flags); - if (!hd->tmPending) { - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - break; - } - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); + while (hd->tmPending == 1){ set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ/4); } + spin_lock_irqsave(&hd->ioc->FreeQlock, flags); + if (hd->tmState == TM_STATE_ERROR){ + hd->tmState = TM_STATE_NONE; + spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); + nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_dev_reset: " + "TM timeout error! (sc=%p)\n", + hd->ioc->name, + SCpnt)); + return FAILED; + } + hd->tmState = TM_STATE_NONE; + spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); + + nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_dev_reset: " + "Device reset was successful! (sc=%p)\n", + hd->ioc->name, + SCpnt)); - //return SUCCESS; - return FAILED; + return SUCCESS; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -2788,95 +2875,80 @@ mptscsih_bus_reset(Scsi_Cmnd * SCpnt) { MPT_SCSI_HOST *hd; - MPT_FRAME_HDR *mf; unsigned long flags; - int scpnt_idx; - - printk(KERN_WARNING MYNAM ": Attempting _BUS_RESET (%p)\n", SCpnt); - printk(KERN_WARNING MYNAM ": IOs outstanding = %d\n", atomic_read(&queue_depth)); - if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL) { - SCpnt->result = DID_RESET << 16; - spin_lock_irqsave(&io_request_lock, flags); - SCpnt->scsi_done(SCpnt); - spin_unlock_irqrestore(&io_request_lock, flags); - return SUCCESS; - } - - /* Find this command + /* If we can't locate our host adapter structure, return FAILED status. */ - if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) { - /* Cmd not found in ScsiLookup. If found in - * doneQ, delete from Q. Do OS callback. - */ - search_doneQ_for_cmd(hd, SCpnt); - - SCpnt->result = DID_RESET << 16; - spin_lock_irqsave(&io_request_lock, flags); - SCpnt->scsi_done(SCpnt); - spin_unlock_irqrestore(&io_request_lock, flags); - return SUCCESS; + if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL){ + nehprintk((KERN_WARNING MYNAM ": mptscsih_bus_reset: " + "Can't locate host! (sc=%p)\n", + SCpnt ) ); + return FAILED; } - /* If this command is pended, then timeout/hang occurred - * during DV. Force bus reset by posting command to F/W - * and then following up with the reset request. - */ - if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) { - mptscsih_put_msgframe(ScsiDoneCtx, hd->ioc->id, mf); - post_pendingQ_commands(hd); + printk(KERN_WARNING MYNAM ": %s: >> Attempting bus reset! (sc=%p)\n", + hd->ioc->name, SCpnt); + printk(KERN_WARNING MYNAM ": %s: IOs outstanding = %d\n", + hd->ioc->name, atomic_read(&queue_depth)); + + /* Wait a fixed amount of time for the TM pending flag to be cleared. + * If we time out, then we return a FAILED status to the caller. This + * call to mptscsih_tm_pending_wait() will set the pending flag if we are + * successful. + */ + if (mptscsih_tm_pending_wait(hd) == FAILED) { + nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_bus_reset: " + "Timed out waiting for previous TM to complete! " + "(sc = %p)\n", + hd->ioc->name, SCpnt ) ); + return FAILED; } - /* This thread will not exit until tmPending is cleared - */ - spin_lock_irqsave(&hd->ioc->FreeQlock, flags); - hd->tmPending = 1; - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - + /* We are now ready to execute the task management request. */ if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, - 0, 0, 0, CAN_SLEEP) < 0) { + 0, 0, 0, CAN_SLEEP) + < 0){ /* The TM request failed and the subsequent FW-reload failed! * Fatal error case. */ - printk(MYIOC_s_WARN_FMT "Error processing TaskMgmt request (sc=%p)\n", - hd->ioc->name, SCpnt); - - /* If command not found, do not do callback, - * just returned failed. CHECKME. - */ - if (hd->ScsiLookup[scpnt_idx] != NULL) { - //atomic_dec(&queue_depth); - SCpnt->result = STS_BUSY; - spin_lock_irqsave(&io_request_lock, flags); - SCpnt->scsi_done(SCpnt); - spin_unlock_irqrestore(&io_request_lock, flags); - } - - spin_lock_irqsave(&hd->ioc->FreeQlock, flags); + printk(MYIOC_s_WARN_FMT + "Error processing TaskMgmt request (sc=%p)\n", + hd->ioc->name, SCpnt); hd->tmPending = 0; - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - + hd->tmState = TM_STATE_NONE; return FAILED; } - /* Spin on tmPending until we get the interrupt for this TM request. + /* Our task management request will either complete or time out. So we + * spin until tmPending is != 1. If tmState is set to TM_STATE_ERROR, + * we encountered an error executing the task management request. */ - while (1) { - spin_lock_irqsave(&hd->ioc->FreeQlock, flags); - if (!hd->tmPending) { - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - break; - } - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); + while (hd->tmPending == 1){ set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ/4); } + spin_lock_irqsave(&hd->ioc->FreeQlock, flags); + if (hd->tmState == TM_STATE_ERROR){ + hd->tmState = TM_STATE_NONE; + spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); + nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_bus_reset: " + "TM timeout error! (sc=%p)\n", + hd->ioc->name, + SCpnt)); + return FAILED; + } + hd->tmState = TM_STATE_NONE; + spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); + + nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_bus_reset: " + "Bus reset was successful! (sc=%p)\n", + hd->ioc->name, + SCpnt)); return SUCCESS; } -#if 0 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mptscsih_host_reset - Perform a SCSI host adapter RESET! @@ -2890,59 +2962,75 @@ int mptscsih_host_reset(Scsi_Cmnd *SCpnt) { - MPT_SCSI_HOST *hd; - MPT_FRAME_HDR *mf; + MPT_SCSI_HOST * hd; + int status = SUCCESS; - printk(KERN_WARNING MYNAM ": Attempting HOST_RESET (%p)\n", SCpnt); - printk(KERN_WARNING MYNAM ": IOs outstanding = %d\n", atomic_read(&queue_depth)); - - if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL) { - SCpnt->result = DID_RESET << 16; - spin_lock_irqsave(&io_request_lock, flags); - SCpnt->scsi_done(SCpnt); - spin_unlock_irqrestore(&io_request_lock, flags); - return SUCCESS; + /* If we can't locate the host to reset, then we failed. */ + if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL){ + nehprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: " + "Can't locate host! (sc=%p)\n", + SCpnt ) ); + return FAILED; } - /* If this command is pended, then timeout/hang occurred - * during DV. Force bus reset by posting command to F/W - * and then following up with the reset request. + printk(KERN_WARNING MYNAM ": %s: >> Attempting host reset! (sc=%p)\n", + hd->ioc->name, SCpnt); + printk(KERN_WARNING MYNAM ": %s: IOs outstanding = %d\n", + hd->ioc->name, atomic_read(&queue_depth)); + + /* If our attempts to reset the host failed, then return a failed + * status. The host will be taken off line by the SCSI mid-layer. */ - if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) { - mptscsih_put_msgframe(ScsiDoneCtx, hd->ioc->id, mf); - post_pendingQ_commands(hd); + if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0){ + status = FAILED; + } else { + /* Make sure TM pending is cleared and TM state is set to + * NONE. + */ + hd->tmPending = 0; + hd->tmState = TM_STATE_NONE; } - /* This thread will not exit until tmPending is cleared - */ - spin_lock_irqsave(&hd->ioc->FreeQlock, flags); - hd->tmPending = 1; - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0) { - SCpnt->result = STS_BUSY; - spin_lock_irqsave(&io_request_lock, flags); // sjr-added - SCpnt->scsi_done(SCpnt); - spin_unlock_irqrestore(&io_request_lock, flags); // sjr-added - return FAILED; - } + nehprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: " + "Status = %s\n", + (status == SUCCESS) ? "SUCCESS" : "FAILED" ) ); - /* Spin on tmPending until we get the interrupt for this TM request. - */ - while (1) { + return status; +} + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/** + * mptscsih_tm_pending_wait - wait for pending task management request to + * complete. + * @hd: Pointer to MPT host structure. + * + * Returns {SUCCESS,FAILED}. + */ +static int +mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd) +{ + unsigned long flags; + int loop_count = 60 * 4; /* Wait 60 seconds */ + int status = FAILED; + + do { spin_lock_irqsave(&hd->ioc->FreeQlock, flags); - if (!hd->tmPending) { + if (hd->tmState == TM_STATE_NONE) { + hd->tmState = TM_STATE_IN_PROGRESS; + hd->tmPending = 1; spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); + status = SUCCESS; break; } spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ/4); - } - return SUCCESS; + } while (--loop_count); + + return status; } -#endif #else /* MPT_SCSI old EH stuff... */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -2963,7 +3051,7 @@ unsigned long flags; int scpnt_idx; - printk(KERN_WARNING MYNAM ": OldAbort scheduling ABORT SCSI IO (sc=%p)\n", SCpnt); + printk(KERN_WARNING MYNAM ": OldAbort scheduling ABORT SCSI IO (sc=%p)\n", (void *) SCpnt); printk(KERN_WARNING " IOs outstanding = %d\n", atomic_read(&queue_depth)); if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL) { @@ -3061,6 +3149,8 @@ if (! mytaskQ_bh_active) { mytaskQ_bh_active = 1; + spin_unlock_irqrestore(&mytaskQ_lock, flags); + /* * Oh how cute, no alloc/free/mgmt needed if we use * (bottom/unused portion of) MPT request frame. @@ -3071,8 +3161,9 @@ ptaskfoo->data = SCpnt; SCHEDULE_TASK(ptaskfoo); + } else { + spin_unlock_irqrestore(&mytaskQ_lock, flags); } - spin_unlock_irqrestore(&mytaskQ_lock, flags); return SCSI_ABORT_PENDING; } @@ -3096,7 +3187,7 @@ unsigned long flags; int scpnt_idx; - printk(KERN_WARNING MYNAM ": OldReset scheduling BUS_RESET (sc=%p)\n", SCpnt); + printk(KERN_WARNING MYNAM ": OldReset scheduling BUS_RESET (sc=%p)\n", (void *) SCpnt); printk(KERN_WARNING " IOs outstanding = %d\n", atomic_read(&queue_depth)); if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL) { @@ -3174,8 +3265,11 @@ atomic_inc(&mpt_taskQdepth); spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - spin_lock_irqsave(&mytaskQ_lock, flags); + dtmprintk((MYIOC_s_INFO_FMT "OldReset: _bh_handler state (%d) taskQ count (%d)\n", + hd->ioc->name, mytaskQ_bh_active, hd->taskQcnt)); + + spin_lock_irqsave(&mytaskQ_lock, flags); /* Save the original SCpnt mf pointer */ SCpnt->host_scribble = (u8 *) MPT_INDEX_2_MFPTR (hd->ioc, scpnt_idx); @@ -3184,11 +3278,9 @@ mf->u.frame.linkage.argp1 = SCpnt; mf->u.frame.linkage.argp2 = (void *) hd; - dtmprintk((MYIOC_s_INFO_FMT "OldReset: _bh_handler state (%d) taskQ count (%d)\n", - hd->ioc->name, mytaskQ_bh_active, hd->taskQcnt)); - if (! mytaskQ_bh_active) { mytaskQ_bh_active = 1; + spin_unlock_irqrestore(&mytaskQ_lock, flags); /* * Oh how cute, no alloc/free/mgmt needed if we use * (bottom/unused portion of) MPT request frame. @@ -3199,8 +3291,9 @@ ptaskfoo->data = SCpnt; SCHEDULE_TASK(ptaskfoo); + } else { + spin_unlock_irqrestore(&mytaskQ_lock, flags); } - spin_unlock_irqrestore(&mytaskQ_lock, flags); return SCSI_RESET_PENDING; } @@ -3243,7 +3336,7 @@ printk(KERN_ERR MYNAM ": ERROR - TaskMgmt NULL SCSI Host!" "(ioc=%p, sh=%p hd=%p)\n", - ioc, ioc->sh, hd); + (void *) ioc, (void *) ioc->sh, (void *) hd); continue; } @@ -3276,7 +3369,7 @@ SCpnt = (Scsi_Cmnd*)mf->u.frame.linkage.argp1; if (SCpnt == NULL) { printk(KERN_ERR MYNAM ": ERROR - TaskMgmt has NULL SCpnt! (mf=%p:sc=%p)\n", - mf, SCpnt); + (void *) mf, (void *) SCpnt); mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf); spin_lock_irqsave(&ioc->FreeQlock, flags); hd->tmPending = 0; @@ -3330,7 +3423,7 @@ hd->abortSCpnt = SCpnt; printk(KERN_WARNING MYNAM ": Attempting ABORT SCSI IO! (mf=%p:sc=%p)\n", - mf, SCpnt); + (void *) mf, (void *) SCpnt); } /* The TM handler will allocate a new mf, @@ -3345,14 +3438,14 @@ * Fatal error case. */ printk(KERN_WARNING MYNAM - ": WARNING[1] - IOC error processing TaskMgmt request (sc=%p)\n", SCpnt); + ": WARNING[1] - IOC error processing TaskMgmt request (sc=%p)\n", (void *) SCpnt); if (hd->ScsiLookup[scpnt_idx] != NULL) { atomic_dec(&queue_depth); SCpnt->result = DID_SOFT_ERROR << 16; - spin_lock_irqsave(&io_request_lock, flags); + MPT_HOST_LOCK(flags); SCpnt->scsi_done(SCpnt); - spin_unlock_irqrestore(&io_request_lock, flags); + MPT_HOST_UNLOCK(flags); mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf); } spin_lock_irqsave(&ioc->FreeQlock, flags); @@ -3462,6 +3555,9 @@ } } } +#ifdef MPT_SCSI_USE_NEW_EH + hd->tmState = TM_STATE_ERROR; +#endif } else { dtmprintk((KERN_INFO " SCSI TaskMgmt SUCCESS!\n")); @@ -3490,51 +3586,7 @@ } #ifdef DROP_TEST - { - Scsi_Cmnd *sc; - unsigned long flags; - u16 req_idx; - - /* Free resources for the drop test MF and chain buffers. - */ - if (dropMfPtr) { - req_idx = le16_to_cpu(dropMfPtr->u.frame.hwhdr.msgctxu.fld.req_idx); - sc = hd->ScsiLookup[req_idx]; - if (sc == NULL) { - printk(MYIOC_s_ERR_FMT - "Drop Test: NULL ScsiCmd ptr!\n", - ioc->name); - } else { - sc->host_scribble = NULL; - if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) - sc->result = DID_RESET << 16; - else - sc->result = DID_ABORT << 16; - - hd->ScsiLookup[req_idx] = NULL; - atomic_dec(&queue_depth); - spin_lock_irqsave(&io_request_lock, flags); - sc->scsi_done(sc); /* Issue callback */ - spin_unlock_irqrestore(&io_request_lock, flags); - - mptscsih_freeChainBuffers(hd, req_idx); - mpt_free_msg_frame(ScsiDoneCtx, ioc->id, dropMfPtr); - - printk(MYIOC_s_INFO_FMT - "Free'd Dropped cmd (%p)\n", - hd->ioc->name, sc); - printk(MYIOC_s_INFO_FMT - "mf (%p) reqidx (%4x)\n", - hd->ioc->name, dropMfPtr, - req_idx); - printk(MYIOC_s_INFO_FMT - "Num Tot (%d) Good (%d) Bad (%d) \n", - hd->ioc->name, dropTestNum, - dropTestOK, dropTestBad); - } - dropMfPtr = NULL; - } - } + mptscsih_flush_drop_test(hd); #endif #ifndef MPT_SCSI_USE_NEW_EH @@ -3588,16 +3640,16 @@ MPT_SCSI_HOST *hd; int ii, max; - for (device = sdList; device; device = device->next) { + for (device = sdList; device != NULL; device = device->next) { if (device->host != sh) continue; hd = (MPT_SCSI_HOST *) sh->hostdata; - if (!hd) + if (hd == NULL) continue; - if (hd->Targets) { + if (hd->Targets != NULL) { if (hd->is_spi) max = MPT_MAX_SCSI_DEVICES; else @@ -3623,10 +3675,22 @@ * 1 = _DATA_OUT * 0 = _DIR_NONE * -1 = _DATA_IN + * + * Changed: 3-20-2002 pdelaney to use the default data + * direction and the defines set up in the + * 2.4 kernel series + * 1 = _DATA_OUT changed to SCSI_DATA_WRITE (1) + * 0 = _DIR_NONE changed to SCSI_DATA_NONE (3) + * -1 = _DATA_IN changed to SCSI_DATA_READ (2) + * If the direction is unknown, fall through to original code. */ static int mptscsih_io_direction(Scsi_Cmnd *cmd) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + if (cmd->sc_data_direction != SCSI_DATA_UNKNOWN) + return cmd->sc_data_direction; +#endif switch (cmd->cmnd[0]) { /* _DATA_OUT commands */ case WRITE_6: case WRITE_10: case WRITE_12: @@ -3642,7 +3706,7 @@ case PERSISTENT_RESERVE_OUT: case 0xea: case 0xa3: - return 1; + return SCSI_DATA_WRITE; /* No data transfer commands */ case SEEK_6: case SEEK_10: @@ -3650,26 +3714,26 @@ case TEST_UNIT_READY: case START_STOP: case ALLOW_MEDIUM_REMOVAL: - return 0; + return SCSI_DATA_NONE; /* Conditional data transfer commands */ case FORMAT_UNIT: if (cmd->cmnd[1] & 0x10) /* FmtData (data out phase)? */ - return 1; + return SCSI_DATA_WRITE; else - return 0; + return SCSI_DATA_NONE; case VERIFY: if (cmd->cmnd[1] & 0x02) /* VERIFY:BYTCHK (data out phase)? */ - return 1; + return SCSI_DATA_WRITE; else - return 0; + return SCSI_DATA_NONE; case RESERVE_10: if (cmd->cmnd[1] & 0x03) /* RESERVE:{LongID|Extent} (data out phase)? */ - return 1; + return SCSI_DATA_WRITE; else - return 0; + return SCSI_DATA_NONE; #if 0 case REZERO_UNIT: /* (or REWIND) */ @@ -3681,7 +3745,7 @@ /* Must be data _IN! */ default: - return -1; + return SCSI_DATA_READ; } } @@ -3727,6 +3791,20 @@ sz = SCSI_STD_SENSE_BYTES; memcpy(target->sense, sense_data, sz); target->tflags |= MPT_TARGET_FLAGS_VALID_SENSE; + +#ifdef ABORT_FIX + if (sz >= SCSI_STD_SENSE_BYTES) { + if ((sense_data[02] == ABORTED_COMMAND) && + (sense_data[12] == 0x47) && (sense_data[13] == 0x00)){ + target->numAborts++; + if ((target->raidVolume == 0) && (target->numAborts > 5)) { + target->numAborts = 0; + target->minSyncFactor++; + hd->ioc->spi_data.dvStatus[index] |= MPT_SCSICFG_NEGOTIATE; + } + } + } +#endif } /* Log SMART data (asc = 0x5D, non-IM case only) if required. @@ -3874,23 +3952,22 @@ Q_DEL_ITEM(buffer); mf = (MPT_FRAME_HDR *) buffer->argp; + buffer->argp = NULL; + + /* Add to the freeQ + */ + Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q); + spin_unlock_irqrestore(&hd->freedoneQlock, flags); + if (!mf) { /* This should never happen */ - printk(MYIOC_s_WARN_FMT "post_pendingQ_commands: mf %p\n", hd->ioc->name, mf); - spin_unlock_irqrestore(&hd->freedoneQlock, flags); + printk(MYIOC_s_WARN_FMT "post_pendingQ_commands: mf %p\n", hd->ioc->name, (void *) mf); continue; } mptscsih_put_msgframe(ScsiDoneCtx, hd->ioc->id, mf); ddvtprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (mf=%p)\n", hd->ioc->name, mf)); - - buffer->argp = NULL; - - /* Add to the freeQ - */ - Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q); - spin_unlock_irqrestore(&hd->freedoneQlock, flags); } return; @@ -3935,40 +4012,7 @@ /* 2a. Drop Test Command. */ #ifdef DROP_TEST - { - Scsi_Cmnd *sc; - unsigned long flags; - u16 req_idx; - - /* Free resources for the drop test MF - * and chain buffers. - */ - if (dropMfPtr) { - req_idx = le16_to_cpu(dropMfPtr->u.frame.hwhdr.msgctxu.fld.req_idx); - sc = hd->ScsiLookup[req_idx]; - if (sc == NULL) { - printk(MYIOC_s_ERR_FMT - "Drop Test: NULL ScsiCmd ptr!\n", - ioc->name); - } else { - sc->host_scribble = NULL; - sc->result = DID_RESET << 16; - hd->ScsiLookup[req_idx] = NULL; - atomic_dec(&queue_depth); - spin_lock_irqsave(&io_request_lock, flags); - sc->scsi_done(sc); /* Issue callback */ - spin_unlock_irqrestore(&io_request_lock, flags); - } - - mptscsih_freeChainBuffers(hd, req_idx); - mpt_free_msg_frame(ScsiDoneCtx, ioc->id, dropMfPtr); - printk(MYIOC_s_INFO_FMT - "Free'd: mf (%p) reqidx (%4x)\n", - hd->ioc->name, dropMfPtr, - req_idx); - } - dropMfPtr = NULL; - } + mptscsih_flush_drop_test(hd); #endif /* 2b. Reply to OS all known outstanding I/O commands. @@ -4102,14 +4146,18 @@ /* * CHECKME! Falling thru... */ + break; case MPI_EVENT_INTEGRATED_RAID: /* 0B */ #ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION /* negoNvram set to 0 if DV enabled and to USE_NVRAM if - * if DV disabled + * if DV disabled. Need to check for target mode. */ - hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; - if (hd->negoNvram == 0) { + hd = NULL; + if (ioc->sh) + hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; + + if (hd && (hd->is_spi) && (hd->negoNvram == 0)) { ScsiCfgData *pSpi; Ioc3PhysDisk_t *pPDisk; int numPDisk; @@ -4556,7 +4604,7 @@ return 0; } if ( (sk==SK_UNIT_ATTENTION && asc==0x29 && (ascq==0x00 || ascq==0x01)) - || (sk==SK_NOT_READY && asc==0x04 && ascq==0x01) + || (sk==SK_NOT_READY && asc==0x04 && (ascq==0x01 || ascq==0x02)) || (sk==SK_ILLEGAL_REQUEST && asc==0x25 && ascq==0x00) ) { @@ -4675,6 +4723,13 @@ } } + if (vdev) { + if (hd->ioc->spi_data.isRaid & (1 << target_id)) + vdev->raidVolume = 1; + else + vdev->raidVolume = 0; + } + if (vdev && data) { if (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) { @@ -4687,7 +4742,10 @@ /* Update the target capabilities */ - mptscsih_setTargetNegoParms(hd, vdev); + if (dlen > 56) + mptscsih_setTargetNegoParms(hd, vdev, data[56]); + else + mptscsih_setTargetNegoParms(hd, vdev, 0); } /* Is LUN supported? If so, upper 3 bits will be 0 @@ -4697,12 +4755,6 @@ vdev->luns |= (1 << lun); } - if (vdev) { - if (hd->ioc->spi_data.isRaid & (1 << target_id)) - vdev->raidVolume = 1; - else - vdev->raidVolume = 0; - } dprintk((KERN_INFO " target = %p\n", vdev)); return vdev; @@ -4714,8 +4766,9 @@ * the Inquiry data, adapter capabilities, and NVRAM settings. * */ -void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target) +void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56) { + ScsiCfgData *pspi_data = &hd->ioc->spi_data; int id = (int) target->target_id; int nvram; char canQ = 0; @@ -4723,7 +4776,7 @@ u8 factor = MPT_ASYNC; u8 offset = 0; u8 version, nfactor; - ScsiCfgData *pspi_data = &hd->ioc->spi_data; + u8 noQas = 1; /* Set flags based on Inquiry data */ @@ -4739,11 +4792,18 @@ } if (target->inq_data[7] & 0x10) { - if (version == 2) + /* bits 2 & 3 show DT support + */ + if ((byte56 & 0x04) == 0) factor = MPT_ULTRA2; else factor = MPT_ULTRA320; + /* bit 1 QAS support, non-raid only + */ + if ((target->raidVolume == 0) && (byte56 & 0x02) != 0) + noQas = 0; + offset = pspi_data->maxSyncOffset; } else { factor = MPT_ASYNC; @@ -4801,15 +4861,39 @@ target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO; - /* Disable all wide (sync) extended messages - * if device is narrow (async). + /* Disable unused features. */ - target->negoFlags = 0; + target->negoFlags = pspi_data->noQas; if (!width) target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE; if (!offset) target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC; + + if (noQas) + target->negoFlags |= MPT_TARGET_NO_NEGO_QAS; + + /* GEM, processor WORKAROUND + */ + if (((target->inq_data[0] & 0x1F) == 0x03) || ((target->inq_data[0] & 0x1F) > 0x08)){ + target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC); + pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO; + } + + /* Disable QAS if mixed configuration case + */ + if ((noQas) && (!pspi_data->noQas) && ((target->inq_data[0] & 0x1F) == 0x00)){ + VirtDevice *vdev; + int ii; + + pspi_data->noQas = MPT_TARGET_NO_NEGO_QAS; + for (ii = 0; ii < id; ii++) { + vdev = hd->Targets[id]; + if (vdev != NULL) + vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS; + } + } + } return; @@ -4873,6 +4957,20 @@ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* + * If no Target, bus reset on 1st I/O. Set the flag to + * prevent any future negotiations to this device. + */ +static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id) +{ + + if ((hd->Targets) && (hd->Targets[target_id] == NULL)) + hd->ioc->spi_data.dvStatus[target_id] |= MPT_SCSICFG_BLK_NEGO; + + return; +} + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* * SCSI Config Page functionality ... */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -4901,8 +4999,9 @@ if (width && offset && !nowide && !nosync) { if (factor < MPT_ULTRA160) { - *requestedPtr |= (MPI_SCSIDEVPAGE1_RP_IU + MPI_SCSIDEVPAGE1_RP_DT + - MPI_SCSIDEVPAGE1_RP_QAS); + *requestedPtr |= (MPI_SCSIDEVPAGE1_RP_IU + MPI_SCSIDEVPAGE1_RP_DT); + if ((flags & MPT_TARGET_NO_NEGO_QAS) == 0) + *requestedPtr |= MPI_SCSIDEVPAGE1_RP_QAS; } else if (factor < MPT_ULTRA2) { *requestedPtr |= MPI_SCSIDEVPAGE1_RP_DT; } @@ -4922,7 +5021,7 @@ * @hd: Pointer to a SCSI Host Strucutre * @portnum: IOC port number * @target_id: writeSDP1 for single ID - * @flags: MPT_SCSICFG_ALL_IDS, MPT_SCSICFG_USE_NVRAM + * @flags: MPT_SCSICFG_ALL_IDS, MPT_SCSICFG_USE_NVRAM, MPT_SCSICFG_BLK_NEGO * * Return: -EFAULT if read of config page header fails * or 0 if success. @@ -4942,7 +5041,6 @@ SCSIDevicePage1_t *pData = NULL; VirtDevice *pTarget = NULL; MPT_FRAME_HDR *mf; - MptSge_t *psge; dma_addr_t dataDma; u16 req_idx; u32 frameOffset; @@ -4998,7 +5096,7 @@ /* Set the negotiation flags. */ - negoFlags = 0; + negoFlags = ioc->spi_data.noQas; if (!width) negoFlags |= MPT_TARGET_NO_NEGO_WIDE; @@ -5008,7 +5106,8 @@ width = 0; factor = MPT_ASYNC; offset = 0; - negoFlags = MPT_TARGET_NO_NEGO_SYNC; + negoFlags = 0; + //negoFlags = MPT_TARGET_NO_NEGO_SYNC; } /* If id is not a raid volume, get the updated @@ -5021,12 +5120,12 @@ negoFlags = pTarget->negoFlags; pTarget = NULL; } - mptscsih_setDevicePage1Flags(width, factor, offset, - &requested, &configuration, negoFlags); + if (flags & MPT_SCSICFG_BLK_NEGO) + negoFlags = MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC; - if (negoFlags == (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC)) - continue; + mptscsih_setDevicePage1Flags(width, factor, offset, + &requested, &configuration, negoFlags); /* Get a MF for this command. */ @@ -5074,9 +5173,7 @@ */ flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | ioc->spi_data.sdp1length * 4; - psge = (MptSge_t *) &pReq->PageBufferSGE; - psge->FlagsLength = cpu_to_le32(flagsLength); - cpu_to_leXX(dataDma, psge->Address); + mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma); /* Set up the common data portion */ @@ -5109,19 +5206,39 @@ { MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data; - dprintk((MYIOC_s_WARN_FMT "TM request timed out!\n", hd->ioc->name)); + dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_taskmgmt_timeout: " + "TM request timed out!\n", hd->ioc->name)); + /* Delete the timer that triggered this callback. * Remark: del_timer checks to make sure timer is active * before deleting. */ del_timer(&hd->TMtimer); +#ifdef MPT_SCSI_USE_NEW_EH + /* Set the error flag to 1 so that the function that started the + * task management request knows it timed out. + */ + hd->tmState = TM_STATE_ERROR; +#endif + /* Call the reset handler. Already had a TM request * timeout - so issue a diagnostic reset */ if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) { printk((KERN_WARNING " Firmware Reload FAILED!!\n")); } +#ifdef MPT_SCSI_USE_NEW_EH + else { + /* Because we have reset the IOC, no TM requests can be + * pending. So let's make sure the tmPending flag is reset. + */ + nehprintk((KERN_WARNING MYNAM + ": %s: mptscsih_taskmgmt_timeout\n", + hd->ioc->name)); + hd->tmPending = 0; + } +#endif return; } @@ -5163,7 +5280,7 @@ (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) { printk(MYIOC_s_ERR_FMT "ScanDvComplete, %s req frame ptr! (=%p)\n", - ioc->name, mf?"BAD":"NULL", mf); + ioc->name, mf?"BAD":"NULL", (void *) mf); goto wakeup; } @@ -5175,7 +5292,7 @@ if (mf != hd->cmdPtr) { printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p)\n", - hd->ioc->name, mf, hd->cmdPtr); + hd->ioc->name, (void *)mf, (void *) hd->cmdPtr); } hd->cmdPtr = NULL; @@ -5392,8 +5509,6 @@ { MpiRaidActionRequest_t *pReq; MPT_FRAME_HDR *mf; - MptSge_t *psge; - int flagsLength; int in_isr; in_isr = in_interrupt(); @@ -5423,14 +5538,8 @@ pReq->ActionDataWord = 0; /* Reserved for this action */ //pReq->ActionDataSGE = 0; - psge = (MptSge_t *) &pReq->ActionDataSGE; - - /* Add a SGE to the config request. - */ - flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | 0; - - psge->FlagsLength = cpu_to_le32(flagsLength); - cpu_to_leXX( (dma_addr_t) -1, psge->Address); + mpt_add_sge((char *)&pReq->ActionDataSGE, + MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1); ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n", hd->ioc->name, action, io->id)); @@ -5479,7 +5588,6 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) { MPT_FRAME_HDR *mf; - MptSge_t *mpisge; SCSIIORequest_t *pScsiReq; SCSIIORequest_t ReqCopy; int my_idx, ii, dir; @@ -5614,7 +5722,7 @@ pScsiReq->Reserved = 0; - pScsiReq->MsgFlags = MPT_SCSIIO_MSG_FLAGS; + pScsiReq->MsgFlags = mpt_msg_flags(); /* MsgContext set in mpt_get_msg_fram call */ for (ii=0; ii < 8; ii++) @@ -5636,21 +5744,16 @@ ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d)\n", hd->ioc->name, cmd, io->bus, io->id, io->lun)); - /* 32 bit SG only */ - mpisge = (MptSge_t *) &pScsiReq->SGL; - if (dir == MPI_SCSIIO_CONTROL_READ) { - mpisge->FlagsLength = cpu_to_le32( - MPT_SGE_FLAGS_SSIMPLE_READ | io->size); + mpt_add_sge((char *) &pScsiReq->SGL, + MPT_SGE_FLAGS_SSIMPLE_READ | io->size, + io->data_dma); } else { - mpisge->FlagsLength = cpu_to_le32( - MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size); + mpt_add_sge((char *) &pScsiReq->SGL, + MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size, + io->data_dma); } - /* data_dma defaults to -1 - */ - cpu_to_leXX(io->data_dma, mpisge->Address); - /* The ISR will free the request frame, but we need * the information to initialize the target. Duplicate. */ @@ -5786,7 +5889,7 @@ if (pTarget && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) { flags = pTarget->negoFlags; } else { - flags = 0; + flags = hd->ioc->spi_data.noQas; if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) { data = hd->ioc->spi_data.nvram[id]; @@ -5862,6 +5965,7 @@ unsigned long flags; int id, maxid, dvStatus, did; int ii, isPhysDisk; + u8 oldQas; spin_lock_irqsave(&dvtaskQ_lock, flags); dvtaskQ_active = 1; @@ -5907,6 +6011,7 @@ maxid = MIN (ioc->sh->max_id, MPT_MAX_SCSI_DEVICES); for (id = 0; id < maxid; id++) { + oldQas = hd->ioc->spi_data.noQas; spin_lock_irqsave(&dvtaskQ_lock, flags); if (dvtaskQ_release) { dvtaskQ_active = 0; @@ -5928,24 +6033,7 @@ * raid volumes * else, process normally */ - isPhysDisk = 0; - if (ioc->spi_data.pIocPg3) { - /* Search IOC page 3 to determine if - * this is hidden physical disk - */ - Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk; - int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks; - - while (numPDisk) { - if (pPDisk->PhysDiskID == id) { - isPhysDisk = 1; - break; - } - pPDisk++; - numPDisk--; - } - } - + isPhysDisk = mptscsih_is_phys_disk(ioc, id); if (isPhysDisk) { for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { if (hd->ioc->spi_data.isRaid & (1 << ii)) { @@ -5971,6 +6059,9 @@ * DV running. */ post_pendingQ_commands(hd); + + if ((!oldQas) && (hd->ioc->spi_data.noQas)) + mptscsih_qas_check(hd); } } } @@ -5983,6 +6074,57 @@ return; } +/* Search IOC page 3 to determine if this is hidden physical disk + */ +static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id) +{ + if (ioc->spi_data.pIocPg3) { + Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk; + int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks; + + while (numPDisk) { + if (pPDisk->PhysDiskID == id) { + return 1; + } + pPDisk++; + numPDisk--; + } + } + return 0; +} + +/* Write SDP1 if no QAS has been enabled + */ +static void mptscsih_qas_check(MPT_SCSI_HOST *hd) +{ + VirtDevice *pTarget = NULL; + int ii; + int change = 0; + + if (hd->Targets == NULL) + return; + + for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { + change = 0; + pTarget = hd->Targets[ii]; + + if ((pTarget != NULL) && (!pTarget->raidVolume)) { + if ((pTarget->negoFlags & hd->ioc->spi_data.noQas) == 0) { + change = 1; + pTarget->negoFlags |= hd->ioc->spi_data.noQas; + } + } else { + if (mptscsih_is_phys_disk(hd->ioc, ii) == 1) + change = 1; + } + + if ((change) && (hd->ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_DONE)) + mptscsih_writeSDP1(hd, 0, ii, 0); + } + return; +} + + #define MPT_GET_NVRAM_VALS 0x01 #define MPT_UPDATE_MAX 0x02 @@ -6009,19 +6151,22 @@ { MPT_ADAPTER *ioc = hd->ioc; VirtDevice *pTarget = NULL; + SCSIDevicePage1_t *pcfg1Data = NULL; + SCSIDevicePage0_t *pcfg0Data = NULL; u8 *pbuf1 = NULL; u8 *pbuf2 = NULL; + u8 *pDvBuf = NULL; + dma_addr_t dvbuf_dma = -1; dma_addr_t buf1_dma = -1; dma_addr_t buf2_dma = -1; - ConfigPageHeader_t header1; - SCSIDevicePage1_t *pcfg1Data = NULL; dma_addr_t cfg1_dma_addr = -1; - ConfigPageHeader_t header0; - SCSIDevicePage0_t *pcfg0Data = NULL; dma_addr_t cfg0_dma_addr = -1; + ConfigPageHeader_t header1; + ConfigPageHeader_t header0; DVPARAMETERS dv; INTERNAL_CMD iocmd; CONFIGPARMS cfg; + int dv_alloc = 0; int rc, sz = 0; int bufsize = 0; int dataBufSize = 0; @@ -6033,6 +6178,7 @@ char doFallback = 0; char readPage0; char bus, lun; + char inq0 = 0; if (ioc->spi_data.sdp1length == 0) return; @@ -6078,6 +6224,16 @@ if (pTarget && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)) iocmd.flags |= MPT_ICFLAG_TAGGED_CMD; + if (pTarget && (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) { + /* Another GEM workaround. Check peripheral device type, + * if PROCESSOR, quit DV. + */ + if (((pTarget->inq_data[0] & 0x1F) == 0x03) || ((pTarget->inq_data[0] & 0x1F) > 0x08)) { + pTarget->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC); + return; + } + } + /* Prep cfg structure */ cfg.pageAddr = (bus<<8) | id; @@ -6089,10 +6245,6 @@ header0.PageLength = ioc->spi_data.sdp0length; header0.PageNumber = 0; header0.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; - pcfg0Data = (SCSIDevicePage0_t *)pci_alloc_consistent(ioc->pcidev, - header0.PageLength * 4, &cfg0_dma_addr); - if (!pcfg0Data) - return; /* Prep SDP1 header */ @@ -6100,10 +6252,36 @@ header1.PageLength = ioc->spi_data.sdp1length; header1.PageNumber = 1; header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; - pcfg1Data = (SCSIDevicePage1_t *)pci_alloc_consistent(ioc->pcidev, - header1.PageLength * 4, &cfg1_dma_addr); - if (!pcfg1Data) - goto target_done; + + if (header0.PageLength & 1) + dv_alloc = (header0.PageLength * 4) + 4; + + dv_alloc += (2048 + (header1.PageLength * 4)); + + pDvBuf = pci_alloc_consistent(ioc->pcidev, dv_alloc, &dvbuf_dma); + if (pDvBuf == NULL) + return; + + sz = 0; + pbuf1 = (u8 *)pDvBuf; + buf1_dma = dvbuf_dma; + sz +=1024; + + pbuf2 = (u8 *) (pDvBuf + sz); + buf2_dma = dvbuf_dma + sz; + sz +=1024; + + pcfg0Data = (SCSIDevicePage0_t *) (pDvBuf + sz); + cfg0_dma_addr = dvbuf_dma + sz; + sz += header0.PageLength * 4; + + /* 8-byte alignment + */ + if (header0.PageLength & 1) + sz += 4; + + pcfg1Data = (SCSIDevicePage1_t *) (pDvBuf + sz); + cfg1_dma_addr = dvbuf_dma + sz; /* Skip this ID? Set cfg.hdr to force config page write */ @@ -6164,11 +6342,6 @@ hd->pLocal = NULL; readPage0 = 0; sz = SCSI_STD_INQUIRY_BYTES; - pbuf1 = pci_alloc_consistent(ioc->pcidev, sz, &buf1_dma); - pbuf2 = pci_alloc_consistent(ioc->pcidev, sz, &buf2_dma); - if (!pbuf1 || !pbuf2) - goto target_done; - while (1) { ddvprintk((MYIOC_s_NOTE_FMT "DV: Start Basic test.\n", ioc->name)); dv.cmd = MPT_SET_MIN; @@ -6277,12 +6450,13 @@ firstPass = 0; } } - /* Free pbuf2, but use pbuf1 for - * acquiring the (echo) buffer size. - */ - pci_free_consistent(ioc->pcidev, sz, pbuf2, buf2_dma); - pbuf2 = NULL; ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test completed OK.\n", ioc->name)); + inq0 = (*pbuf1) & 0x1F; + + /* Continue only for disks + */ + if (inq0 != 0) + goto target_done; /* Start the Enhanced Test. * 0) issue TUR to clear out check conditions @@ -6418,8 +6592,6 @@ else dataBufSize = bufsize; } - pci_free_consistent(ioc->pcidev, sz, pbuf1, buf1_dma); - pbuf1 = NULL; sz = 0; iocmd.flags &= ~MPT_ICFLAG_BUF_CAP; @@ -6438,13 +6610,9 @@ ddvprintk((MYIOC_s_INFO_FMT "%s Buffer Capacity %d\n", ioc->name, (iocmd.flags & MPT_ICFLAG_ECHO) ? "Echo" : " ", bufsize)); - /* Allocate data buffers for write-read-compare test. + /* Data buffers for write-read-compare test max 1K. */ sz = MIN(bufsize, 1024); - pbuf1 = pci_alloc_consistent(ioc->pcidev, sz, &buf1_dma); - pbuf2 = pci_alloc_consistent(ioc->pcidev, sz, &buf2_dma); - if (!pbuf1 || !pbuf2) - goto target_done; /* --- loop ---- * On first pass, always issue a reserve. @@ -6698,6 +6866,12 @@ /* Set if cfg1_dma_addr contents is valid */ if (cfg.hdr != NULL) { + + /* If disk, not U320, disable QAS + */ + if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320)) + hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS; + dv.cmd = MPT_SAVE; mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); @@ -6720,25 +6894,8 @@ /* Done with the DV scan of the current target */ - if (pcfg0Data) { - pci_free_consistent(ioc->pcidev, header0.PageLength * 4, - pcfg0Data, cfg0_dma_addr); - } - - if (pcfg1Data) { - pci_free_consistent(ioc->pcidev, header1.PageLength * 4, - pcfg1Data, cfg1_dma_addr); - } - - if (pbuf1) { - pci_free_consistent(ioc->pcidev, sz, pbuf1, buf1_dma); - pbuf1 = NULL; - } - - if (pbuf2) { - pci_free_consistent(ioc->pcidev, sz, pbuf2, buf2_dma); - pbuf2 = NULL; - } + if (pDvBuf) + pci_free_consistent(ioc->pcidev, dv_alloc, pDvBuf, dvbuf_dma); ddvtprintk((MYIOC_s_INFO_FMT "DV Done. IOs outstanding = %d\n", ioc->name, atomic_read(&queue_depth))); @@ -6800,7 +6957,7 @@ } /* Set the negotiation flags */ - negoFlags = 0; + negoFlags = hd->ioc->spi_data.noQas; if (!width) negoFlags |= MPT_TARGET_NO_NEGO_WIDE; @@ -6947,6 +7104,7 @@ width = MPT_NARROW; factor = MPT_ASYNC; } + dv->max.flags |= MPT_TARGET_NO_NEGO_QAS; dv->now.width = width; dv->now.offset = offset; @@ -6981,24 +7139,27 @@ pTarget->maxWidth = dv->now.width; pTarget->maxOffset = dv->now.offset; pTarget->minSyncFactor = dv->now.factor; + pTarget->negoFlags = dv->now.flags; } else { /* Preserv all flags, use * read-modify-write algorithm */ - data = hd->ioc->spi_data.nvram[id]; + if (hd->ioc->spi_data.nvram) { + data = hd->ioc->spi_data.nvram[id]; - if (dv->now.width) - data &= ~MPT_NVRAM_WIDE_DISABLE; - else - data |= MPT_NVRAM_WIDE_DISABLE; + if (dv->now.width) + data &= ~MPT_NVRAM_WIDE_DISABLE; + else + data |= MPT_NVRAM_WIDE_DISABLE; - if (!dv->now.offset) - factor = MPT_ASYNC; + if (!dv->now.offset) + factor = MPT_ASYNC; - data &= ~MPT_NVRAM_SYNC_MASK; - data |= (dv->now.factor << MPT_NVRAM_SYNC_SHIFT) & MPT_NVRAM_SYNC_MASK; + data &= ~MPT_NVRAM_SYNC_MASK; + data |= (dv->now.factor << MPT_NVRAM_SYNC_SHIFT) & MPT_NVRAM_SYNC_MASK; - hd->ioc->spi_data.nvram[id] = data; + hd->ioc->spi_data.nvram[id] = data; + } } break; } @@ -7186,8 +7347,6 @@ unsigned long val; int c; - printk("KERN_WARNING: mptscsih_setup arg %s\n", str); - while (cur != NULL && (pc = strchr(cur, ':')) != NULL) { char *pe; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/message/fusion/mptscsih.h linux.19rc3-ac4/drivers/message/fusion/mptscsih.h --- linux.19rc3/drivers/message/fusion/mptscsih.h 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/message/fusion/mptscsih.h 2002-07-29 15:50:46.000000000 +0100 @@ -20,7 +20,7 @@ * (mailto:netscape.net) * (mailto:Pam.Delaney@lsil.com) * - * $Id: mptscsih.h,v 1.16 2002/02/27 18:44:30 sralston Exp $ + * $Id: mptscsih.h,v 1.18 2002/06/06 15:32:52 pdelaney Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -73,7 +73,8 @@ * Try to keep these at 2^N-1 */ #define MPT_FC_CAN_QUEUE 63 -#define MPT_SCSI_CAN_QUEUE 31 +//#define MPT_SCSI_CAN_QUEUE 31 +#define MPT_SCSI_CAN_QUEUE MPT_FC_CAN_QUEUE #define MPT_SCSI_CMD_PER_LUN 7 #define MPT_SCSI_SG_DEPTH 40 @@ -195,7 +196,7 @@ extern int x_scsi_abort(Scsi_Cmnd *); extern int x_scsi_bus_reset(Scsi_Cmnd *); extern int x_scsi_dev_reset(Scsi_Cmnd *); -/*extern int x_scsi_host_reset(Scsi_Cmnd *);*/ +extern int x_scsi_host_reset(Scsi_Cmnd *); #else extern int x_scsi_old_abort(Scsi_Cmnd *); extern int x_scsi_old_reset(Scsi_Cmnd *, unsigned int); @@ -212,6 +213,33 @@ #ifdef MPT_SCSI_USE_NEW_EH +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,1) + +#define MPT_SCSIHOST { \ + next: NULL, \ + PROC_SCSI_DECL \ + name: "MPT SCSI Host", \ + detect: x_scsi_detect, \ + release: x_scsi_release, \ + info: x_scsi_info, \ + command: NULL, \ + queuecommand: x_scsi_queuecommand, \ + eh_strategy_handler: NULL, \ + eh_abort_handler: x_scsi_abort, \ + eh_device_reset_handler: x_scsi_dev_reset, \ + eh_bus_reset_handler: x_scsi_bus_reset, \ + eh_host_reset_handler: x_scsi_host_reset, \ + bios_param: x_scsi_bios_param, \ + can_queue: MPT_SCSI_CAN_QUEUE, \ + this_id: -1, \ + sg_tablesize: MPT_SCSI_SG_DEPTH, \ + cmd_per_lun: MPT_SCSI_CMD_PER_LUN, \ + unchecked_isa_dma: 0, \ + use_clustering: ENABLE_CLUSTERING, \ +} + +#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,1) */ + #define MPT_SCSIHOST { \ next: NULL, \ PROC_SCSI_DECL \ @@ -236,7 +264,9 @@ use_new_eh_code: 1 \ } -#else +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,1) */ + +#else /* MPT_SCSI_USE_NEW_EH */ #define MPT_SCSIHOST { \ next: NULL, \ @@ -257,7 +287,7 @@ unchecked_isa_dma: 0, \ use_clustering: ENABLE_CLUSTERING \ } -#endif +#endif /* MPT_SCSI_USE_NEW_EH */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/message/i2o/i2o_block.c linux.19rc3-ac4/drivers/message/i2o/i2o_block.c --- linux.19rc3/drivers/message/i2o/i2o_block.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/message/i2o/i2o_block.c 2002-07-29 13:58:42.000000000 +0100 @@ -1448,6 +1448,12 @@ * 1. If there was a TID reuse. * 2. There was more than one I2O controller. */ + + if(pci_set_dma_mask(c->pdev, 0xffffffff)) + { + printk(KERN_WARNING "i2o_block : No suitable DMA available for controller %d\n", i); + continue; + } if(!bios) { diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/message/i2o/i2o_config.c linux.19rc3-ac4/drivers/message/i2o/i2o_config.c --- linux.19rc3/drivers/message/i2o/i2o_config.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/message/i2o/i2o_config.c 2002-07-29 13:58:42.000000000 +0100 @@ -277,7 +277,14 @@ if(c) { foo[i] = 1; - i2o_unlock_controller(c); + if(pci_set_dma_mask(c->pdev, 0xffffffff)) + { + printk(KERN_WARNING "i2o_config : No suitable DMA available on controller %d\n", i); + i2o_unlock_controller(c); + continue; + } + + i2o_unlock_controller(c); } else { diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/message/i2o/i2o_core.c linux.19rc3-ac4/drivers/message/i2o/i2o_core.c --- linux.19rc3/drivers/message/i2o/i2o_core.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/message/i2o/i2o_core.c 2002-07-29 13:58:42.000000000 +0100 @@ -3390,8 +3390,9 @@ { if(i2o_quiesce_controller(c)) { - printk(KERN_WARNING "i2o: Could not quiesce %s." " - Verify setup on next system power up.\n", c->name); + printk(KERN_WARNING "i2o: Could not quiesce %s.\n" + "Verify setup on next system power up.\n", + c->name); } } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/message/i2o/i2o_lan.c linux.19rc3-ac4/drivers/message/i2o/i2o_lan.c --- linux.19rc3/drivers/message/i2o/i2o_lan.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/message/i2o/i2o_lan.c 2002-07-29 13:58:42.000000000 +0100 @@ -1474,6 +1474,12 @@ if (iop==NULL) continue; + if(pci_set_dma_mask(iop->pdev, 0xffffffff)) + { + printk(KERN_WARNING "i2o_lan : No suitable DMA available for controller %d\n", i); + continue; + } + for (i2o_dev=iop->devices;i2o_dev != NULL;i2o_dev=i2o_dev->next) { if (i2o_dev->lct_data.class_id != I2O_CLASS_LAN) diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/message/i2o/i2o_pci.c linux.19rc3-ac4/drivers/message/i2o/i2o_pci.c --- linux.19rc3/drivers/message/i2o/i2o_pci.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/message/i2o/i2o_pci.c 2002-07-29 17:47:17.000000000 +0100 @@ -334,6 +334,11 @@ continue; printk(KERN_INFO "i2o: I2O controller on bus %d at %d.\n", dev->bus->number, dev->devfn); + if(pci_set_dma_mask(dev, 0xffffffff)) + { + printk(KERN_WARNING "I2O controller on bus %d at %d : No suitable DMA available\n", dev->bus->number, dev->devfn); + continue; + } pci_set_master(dev); if(i2o_pci_install(dev)==0) count++; @@ -384,4 +389,3 @@ MODULE_PARM_DESC(dpt, "Set this if you want to drive DPT cards normally handled by dpt_i2o"); module_init(i2o_pci_core_attach); module_exit(i2o_pci_core_detach); - \ No newline at end of file diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/net/3c503.c linux.19rc3-ac4/drivers/net/3c503.c --- linux.19rc3/drivers/net/3c503.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/net/3c503.c 2002-07-29 17:11:46.000000000 +0100 @@ -512,6 +512,7 @@ if (dev->mem_start) { /* Use the shared memory. */ isa_memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr)); + hdr->count = le16_to_cpu(hdr->count); return; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/net/3c59x.c linux.19rc3-ac4/drivers/net/3c59x.c --- linux.19rc3/drivers/net/3c59x.c 2002-07-29 12:49:56.000000000 +0100 +++ linux.19rc3-ac4/drivers/net/3c59x.c 2002-07-29 13:58:42.000000000 +0100 @@ -166,6 +166,11 @@ - Rename wait_for_completion() to issue_and_wait() to avoid completion.h clash. + LK1.1.18ac 01Jul02 akpm + - Fix for undocumented transceiver power-up bit on some 3c566B's + (Donald Becker, Rahul Karnik) + + - See http://www.uow.edu.au/~andrewm/linux/#3c59x-2.3 for more details. - Also see Documentation/networking/vortex.txt */ @@ -181,8 +186,8 @@ #define DRV_NAME "3c59x" -#define DRV_VERSION "LK1.1.16" -#define DRV_RELDATE "19 July 2001" +#define DRV_VERSION "LK1.1.18-ac" +#define DRV_RELDATE "1 July 2002" @@ -400,7 +405,7 @@ EEPROM_8BIT=0x10, /* AKPM: Uses 0x230 as the base bitmaps for EEPROM reads */ HAS_PWR_CTRL=0x20, HAS_MII=0x40, HAS_NWAY=0x80, HAS_CB_FNS=0x100, INVERT_MII_PWR=0x200, INVERT_LED_PWR=0x400, MAX_COLLISION_RESET=0x800, - EEPROM_OFFSET=0x1000, HAS_HWCKSM=0x2000 }; + EEPROM_OFFSET=0x1000, HAS_HWCKSM=0x2000, WNO_XCVR_PWR=0x4000 }; enum vortex_chips { CH_3C590 = 0, @@ -508,7 +513,7 @@ HAS_HWCKSM, 128, }, {"3c556B Laptop Hurricane", PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|EEPROM_OFFSET|HAS_CB_FNS|INVERT_MII_PWR| - HAS_HWCKSM, 128, }, + WNO_XCVR_PWR|HAS_HWCKSM, 128, }, {"3c575 [Megahertz] 10/100 LAN CardBus", PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_8BIT, 128, }, @@ -1198,6 +1203,10 @@ if (vp->drv_flags & INVERT_MII_PWR) n |= 0x4000; outw(n, ioaddr + Wn2_ResetOptions); + if (vp->drv_flags & WNO_XCVR_PWR) { + EL3WINDOW(0); + outw(0x0800, ioaddr); + } } /* Extract our information from the EEPROM data. */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/net/acenic.c linux.19rc3-ac4/drivers/net/acenic.c --- linux.19rc3/drivers/net/acenic.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/net/acenic.c 2002-07-29 13:58:42.000000000 +0100 @@ -1164,14 +1164,8 @@ * This will most likely need BYTE_SWAP once we switch * to using __raw_writel() */ -#ifdef __parisc__ - writel((WORD_SWAP | BYTE_SWAP | CLR_INT | - ((WORD_SWAP | BYTE_SWAP | CLR_INT) << 24)), - ®s->HostCtrl); -#else writel((WORD_SWAP | CLR_INT | ((WORD_SWAP | CLR_INT) << 24)), ®s->HostCtrl); -#endif #else writel((CLR_INT | WORD_SWAP | ((CLR_INT | WORD_SWAP) << 24)), ®s->HostCtrl); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/net/Config.in linux.19rc3-ac4/drivers/net/Config.in --- linux.19rc3/drivers/net/Config.in 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/net/Config.in 2002-07-29 13:58:42.000000000 +0100 @@ -223,7 +223,7 @@ tristate ' Baget AMD LANCE support' CONFIG_BAGETLANCE fi if [ "$CONFIG_NEC_OSPREY" = "y" ]; then - bool ' Memory-mapped onboard NE2000-compatible ethernet' CONFIG_NE2000 + tristate ' Memory-mapped onboard NE2000-compatible ethernet' CONFIG_NE2000 fi fi @@ -242,7 +242,7 @@ fi dep_tristate 'D-Link DL2000-based Gigabit Ethernet support' CONFIG_DL2K $CONFIG_PCI dep_tristate 'MyriCOM Gigabit Ethernet support' CONFIG_MYRI_SBUS $CONFIG_SBUS -dep_tristate 'National Semiconduct DP83820 support' CONFIG_NS83820 $CONFIG_PCI +dep_tristate 'National Semiconductor DP83820 support' CONFIG_NS83820 $CONFIG_PCI dep_tristate 'Packet Engines Hamachi GNIC-II support' CONFIG_HAMACHI $CONFIG_PCI dep_tristate 'Packet Engines Yellowfin Gigabit-NIC support (EXPERIMENTAL)' CONFIG_YELLOWFIN $CONFIG_PCI $CONFIG_EXPERIMENTAL dep_tristate 'SysKonnect SK-98xx support' CONFIG_SK98LIN $CONFIG_PCI diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/net/cs89x0.h linux.19rc3-ac4/drivers/net/cs89x0.h --- linux.19rc3/drivers/net/cs89x0.h 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/net/cs89x0.h 2002-07-29 13:58:42.000000000 +0100 @@ -385,11 +385,11 @@ #define A_CNF_10B_T 0x0001 #define A_CNF_AUI 0x0002 #define A_CNF_10B_2 0x0004 -#define A_CNF_MEDIA_TYPE 0x0060 -#define A_CNF_MEDIA_AUTO 0x0000 +#define A_CNF_MEDIA_TYPE 0x0070 +#define A_CNF_MEDIA_AUTO 0x0070 #define A_CNF_MEDIA_10B_T 0x0020 #define A_CNF_MEDIA_AUI 0x0040 -#define A_CNF_MEDIA_10B_2 0x0060 +#define A_CNF_MEDIA_10B_2 0x0010 #define A_CNF_DC_DC_POLARITY 0x0080 #define A_CNF_NO_AUTO_POLARITY 0x2000 #define A_CNF_LOW_RX_SQUELCH 0x4000 diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/net/depca.c linux.19rc3-ac4/drivers/net/depca.c --- linux.19rc3/drivers/net/depca.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/net/depca.c 2002-07-29 13:58:42.000000000 +0100 @@ -268,8 +268,7 @@ #include "depca.h" -static char version[] __initdata = - "depca.c:v0.53 2001/1/12 davies@maniac.ultranet.com\n"; +static char version[] __initdata = "depca.c:v0.53 2001/1/12 davies@maniac.ultranet.com\n"; #ifdef DEPCA_DEBUG static int depca_debug = DEPCA_DEBUG; @@ -277,7 +276,7 @@ static int depca_debug = 1; #endif -#define DEPCA_NDA 0xffe0 /* No Device Address */ +#define DEPCA_NDA 0xffe0 /* No Device Address */ #define TX_TIMEOUT (1*HZ) @@ -294,15 +293,15 @@ ** ** total_memory = NUM_RX_DESC*(8+RX_BUFF_SZ) + NUM_TX_DESC*(8+TX_BUFF_SZ) */ -#define NUM_RX_DESC 8 /* Number of RX descriptors */ -#define NUM_TX_DESC 8 /* Number of TX descriptors */ -#define RX_BUFF_SZ 1536 /* Buffer size for each Rx buffer */ -#define TX_BUFF_SZ 1536 /* Buffer size for each Tx buffer */ +#define NUM_RX_DESC 8 /* Number of RX descriptors */ +#define NUM_TX_DESC 8 /* Number of TX descriptors */ +#define RX_BUFF_SZ 1536 /* Buffer size for each Rx buffer */ +#define TX_BUFF_SZ 1536 /* Buffer size for each Tx buffer */ /* ** EISA bus defines */ -#define DEPCA_EISA_IO_PORTS 0x0c00 /* I/O port base address, slot 0 */ +#define DEPCA_EISA_IO_PORTS 0x0c00 /* I/O port base address, slot 0 */ #define MAX_EISA_SLOTS 16 #define EISA_SLOT_INC 0x1000 @@ -329,7 +328,7 @@ "DE422",\ ""} static enum { - DEPCA, de100, de101, de200, de201, de202, de210, de212, de422, unknown + DEPCA, de100, de101, de200, de201, de202, de210, de212, de422, unknown } adapter; /* @@ -344,78 +343,78 @@ ** DESC_ALIGN. ALIGN aligns the start address of the private memory area ** and hence the RX descriptor ring's first entry. */ -#define ALIGN4 ((u_long)4 - 1) /* 1 longword align */ -#define ALIGN8 ((u_long)8 - 1) /* 2 longword (quadword) align */ -#define ALIGN ALIGN8 /* Keep the LANCE happy... */ +#define ALIGN4 ((u_long)4 - 1) /* 1 longword align */ +#define ALIGN8 ((u_long)8 - 1) /* 2 longword (quadword) align */ +#define ALIGN ALIGN8 /* Keep the LANCE happy... */ /* ** The DEPCA Rx and Tx ring descriptors. */ struct depca_rx_desc { - volatile s32 base; - s16 buf_length; /* This length is negative 2's complement! */ - s16 msg_length; /* This length is "normal". */ + volatile s32 base; + s16 buf_length; /* This length is negative 2's complement! */ + s16 msg_length; /* This length is "normal". */ }; struct depca_tx_desc { - volatile s32 base; - s16 length; /* This length is negative 2's complement! */ - s16 misc; /* Errors and TDR info */ + volatile s32 base; + s16 length; /* This length is negative 2's complement! */ + s16 misc; /* Errors and TDR info */ }; -#define LA_MASK 0x0000ffff /* LANCE address mask for mapping network RAM +#define LA_MASK 0x0000ffff /* LANCE address mask for mapping network RAM to LANCE memory address space */ /* ** The Lance initialization block, described in databook, in common memory. */ struct depca_init { - u16 mode; /* Mode register */ - u8 phys_addr[ETH_ALEN]; /* Physical ethernet address */ - u8 mcast_table[8]; /* Multicast Hash Table. */ - u32 rx_ring; /* Rx ring base pointer & ring length */ - u32 tx_ring; /* Tx ring base pointer & ring length */ + u16 mode; /* Mode register */ + u8 phys_addr[ETH_ALEN]; /* Physical ethernet address */ + u8 mcast_table[8]; /* Multicast Hash Table. */ + u32 rx_ring; /* Rx ring base pointer & ring length */ + u32 tx_ring; /* Tx ring base pointer & ring length */ }; #define DEPCA_PKT_STAT_SZ 16 -#define DEPCA_PKT_BIN_SZ 128 /* Should be >=100 unless you - increase DEPCA_PKT_STAT_SZ */ +#define DEPCA_PKT_BIN_SZ 128 /* Should be >=100 unless you + increase DEPCA_PKT_STAT_SZ */ struct depca_private { - char devname[DEPCA_STRLEN]; /* Device Product String */ - char adapter_name[DEPCA_STRLEN];/* /proc/ioports string */ - char adapter; /* Adapter type */ - char mca_slot; /* MCA slot, if MCA else -1 */ - struct depca_init init_block;/* Shadow Initialization block */ + char devname[DEPCA_STRLEN]; /* Device Product String */ + char adapter_name[DEPCA_STRLEN]; /* /proc/ioports string */ + char adapter; /* Adapter type */ + char mca_slot; /* MCA slot, if MCA else -1 */ + struct depca_init init_block; /* Shadow Initialization block */ /* CPU address space fields */ - struct depca_rx_desc *rx_ring; /* Pointer to start of RX descriptor ring */ - struct depca_tx_desc *tx_ring; /* Pointer to start of TX descriptor ring */ - void *rx_buff[NUM_RX_DESC]; /* CPU virt address of sh'd memory buffs */ - void *tx_buff[NUM_TX_DESC]; /* CPU virt address of sh'd memory buffs */ - void *sh_mem; /* CPU mapped virt address of device RAM */ + struct depca_rx_desc *rx_ring; /* Pointer to start of RX descriptor ring */ + struct depca_tx_desc *tx_ring; /* Pointer to start of TX descriptor ring */ + void *rx_buff[NUM_RX_DESC]; /* CPU virt address of sh'd memory buffs */ + void *tx_buff[NUM_TX_DESC]; /* CPU virt address of sh'd memory buffs */ + void *sh_mem; /* CPU mapped virt address of device RAM */ /* Device address space fields */ - u_long device_ram_start; /* Start of RAM in device addr space */ + u_long device_ram_start; /* Start of RAM in device addr space */ /* Offsets used in both address spaces */ - u_long rx_ring_offset; /* Offset from start of RAM to rx_ring */ - u_long tx_ring_offset; /* Offset from start of RAM to tx_ring */ - u_long buffs_offset; /* LANCE Rx and Tx buffers start address. */ + u_long rx_ring_offset; /* Offset from start of RAM to rx_ring */ + u_long tx_ring_offset; /* Offset from start of RAM to tx_ring */ + u_long buffs_offset; /* LANCE Rx and Tx buffers start address. */ /* Kernel-only (not device) fields */ - int rx_new, tx_new; /* The next free ring entry */ - int rx_old, tx_old; /* The ring entries to be free()ed. */ - struct net_device_stats stats; - spinlock_t lock; - struct { /* Private stats counters */ - u32 bins[DEPCA_PKT_STAT_SZ]; - u32 unicast; - u32 multicast; - u32 broadcast; - u32 excessive_collisions; - u32 tx_underruns; - u32 excessive_underruns; - } pktStats; - int txRingMask; /* TX ring mask */ - int rxRingMask; /* RX ring mask */ - s32 rx_rlen; /* log2(rxRingMask+1) for the descriptors */ - s32 tx_rlen; /* log2(txRingMask+1) for the descriptors */ + int rx_new, tx_new; /* The next free ring entry */ + int rx_old, tx_old; /* The ring entries to be free()ed. */ + struct net_device_stats stats; + spinlock_t lock; + struct { /* Private stats counters */ + u32 bins[DEPCA_PKT_STAT_SZ]; + u32 unicast; + u32 multicast; + u32 broadcast; + u32 excessive_collisions; + u32 tx_underruns; + u32 excessive_underruns; + } pktStats; + int txRingMask; /* TX ring mask */ + int rxRingMask; /* RX ring mask */ + s32 rx_rlen; /* log2(rxRingMask+1) for the descriptors */ + s32 tx_rlen; /* log2(txRingMask+1) for the descriptors */ }; /* @@ -432,61 +431,61 @@ /* ** Public Functions */ -static int depca_open(struct net_device *dev); -static int depca_start_xmit(struct sk_buff *skb, struct net_device *dev); -static void depca_interrupt(int irq, void *dev_id, struct pt_regs *regs); -static int depca_close(struct net_device *dev); -static int depca_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -static void depca_tx_timeout (struct net_device *dev); +static int depca_open(struct net_device *dev); +static int depca_start_xmit(struct sk_buff *skb, struct net_device *dev); +static void depca_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static int depca_close(struct net_device *dev); +static int depca_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); +static void depca_tx_timeout(struct net_device *dev); static struct net_device_stats *depca_get_stats(struct net_device *dev); -static void set_multicast_list(struct net_device *dev); +static void set_multicast_list(struct net_device *dev); /* ** Private functions */ -static int depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot); -static void depca_init_ring(struct net_device *dev); -static int depca_rx(struct net_device *dev); -static int depca_tx(struct net_device *dev); - -static void LoadCSRs(struct net_device *dev); -static int InitRestartDepca(struct net_device *dev); -static void DepcaSignature(char *name, u_long paddr); -static int DevicePresent(u_long ioaddr); -static int get_hw_addr(struct net_device *dev); -static int EISA_signature(char *name, s32 eisa_id); -static void SetMulticastFilter(struct net_device *dev); -static void isa_probe(struct net_device *dev, u_long iobase); -static void eisa_probe(struct net_device *dev, u_long iobase); -#ifdef CONFIG_MCA -static void mca_probe(struct net_device *dev, u_long iobase); +static int depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot); +static void depca_init_ring(struct net_device *dev); +static int depca_rx(struct net_device *dev); +static int depca_tx(struct net_device *dev); + +static void LoadCSRs(struct net_device *dev); +static int InitRestartDepca(struct net_device *dev); +static void DepcaSignature(char *name, u_long paddr); +static int DevicePresent(u_long ioaddr); +static int get_hw_addr(struct net_device *dev); +static int EISA_signature(char *name, s32 eisa_id); +static void SetMulticastFilter(struct net_device *dev); +static void isa_probe(struct net_device *dev, u_long iobase); +static void eisa_probe(struct net_device *dev, u_long iobase); +#ifdef CONFIG_MCA +static void mca_probe(struct net_device *dev, u_long iobase); #endif static struct net_device *alloc_device(struct net_device *dev, u_long iobase); -static int depca_dev_index(char *s); -static struct net_device *insert_device(struct net_device *dev, u_long iobase, int (*init)(struct net_device *)); -static int load_packet(struct net_device *dev, struct sk_buff *skb); -static void depca_dbg_open(struct net_device *dev); +static int depca_dev_index(char *s); +static struct net_device *insert_device(struct net_device *dev, u_long iobase, int (*init) (struct net_device *)); +static int load_packet(struct net_device *dev, struct sk_buff *skb); +static void depca_dbg_open(struct net_device *dev); #ifdef MODULE -int init_module(void); -void cleanup_module(void); -static int autoprobed = 1, loading_module = 1; +int init_module(void); +void cleanup_module(void); +static int autoprobed = 1, loading_module = 1; # else -static u_char de1xx_irq[] __initdata = {2,3,4,5,7,9,0}; -static u_char de2xx_irq[] __initdata = {5,9,10,11,15,0}; -static u_char de422_irq[] __initdata = {5,9,10,11,0}; +static u_char de1xx_irq[] __initdata = { 2, 3, 4, 5, 7, 9, 0 }; +static u_char de2xx_irq[] __initdata = { 5, 9, 10, 11, 15, 0 }; +static u_char de422_irq[] __initdata = { 5, 9, 10, 11, 0 }; static u_char *depca_irq; -static int autoprobed, loading_module; -#endif /* MODULE */ +static int autoprobed, loading_module; +#endif /* MODULE */ -static char name[DEPCA_STRLEN]; -static int num_depcas, num_eth; -static int mem; /* For loadable module assignment - use insmod mem=0x????? .... */ -static char *adapter_name; /* = '\0'; If no PROM when loadable module - use insmod adapter_name=DE??? ... - bss initializes this to zero - */ +static char name[DEPCA_STRLEN]; +static int num_depcas, num_eth; +static int mem; /* For loadable module assignment + use insmod mem=0x????? .... */ +static char *adapter_name; /* = '\0'; If no PROM when loadable module + use insmod adapter_name=DE??? ... + bss initializes this to zero + */ /* ** Miscellaneous defines... */ @@ -494,49 +493,48 @@ outw(CSR0, DEPCA_ADDR);\ outw(STOP, DEPCA_DATA) -int __init -depca_probe(struct net_device *dev) +int __init depca_probe(struct net_device *dev) { - int tmp = num_depcas, status = -ENODEV; - u_long iobase = dev->base_addr; + int tmp = num_depcas, status = -ENODEV; + u_long iobase = dev->base_addr; - SET_MODULE_OWNER(dev); + SET_MODULE_OWNER(dev); - if ((iobase == 0) && loading_module){ - printk("Autoprobing is not supported when loading a module based driver.\n"); - status = -EIO; - } else { -#ifdef CONFIG_MCA - mca_probe(dev, iobase); + if ((iobase == 0) && loading_module) { + printk("Autoprobing is not supported when loading a module based driver.\n"); + status = -EIO; + } else { +#ifdef CONFIG_MCA + mca_probe(dev, iobase); #endif - isa_probe(dev, iobase); - eisa_probe(dev, iobase); + isa_probe(dev, iobase); + eisa_probe(dev, iobase); - if ((tmp == num_depcas) && (iobase != 0) && loading_module) { - printk("%s: depca_probe() cannot find device at 0x%04lx.\n", dev->name, - iobase); - } - - /* - ** Walk the device list to check that at least one device - ** initialised OK - */ - for (; (dev->priv == NULL) && (dev->next != NULL); dev = dev->next); + if ((tmp == num_depcas) && (iobase != 0) && loading_module) { + printk("%s: depca_probe() cannot find device at 0x%04lx.\n", dev->name, iobase); + } - if (dev->priv) status = 0; - if (iobase == 0) autoprobed = 1; - } + /* + ** Walk the device list to check that at least one device + ** initialised OK + */ + for (; (dev->priv == NULL) && (dev->next != NULL); dev = dev->next); + + if (dev->priv) + status = 0; + if (iobase == 0) + autoprobed = 1; + } - return status; + return status; } -static int __init -depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot) +static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot) { struct depca_private *lp; - int i, j, offset, netRAM, mem_len, status=0; + int i, j, offset, netRAM, mem_len, status = 0; s16 nicsr; - u_long mem_start=0, mem_base[] = DEPCA_RAM_BASE_ADDRESSES; + u_long mem_start = 0, mem_base[] = DEPCA_RAM_BASE_ADDRESSES; STOP_DEPCA; @@ -554,19 +552,17 @@ DepcaSignature(name, mem_start); } while (!mem && mem_base[mem_chkd] && (adapter == unknown)); - if ((adapter == unknown) || !mem_start) { /* DEPCA device not found */ + if ((adapter == unknown) || !mem_start) { /* DEPCA device not found */ return -ENXIO; } dev->base_addr = ioaddr; if (mca_slot != -1) { - printk("%s: %s at 0x%04lx (MCA slot %d)", dev->name, name, - ioaddr, mca_slot); - } else if ((ioaddr & 0x0fff) == DEPCA_EISA_IO_PORTS) { /* EISA slot address */ - printk("%s: %s at 0x%04lx (EISA slot %d)", - dev->name, name, ioaddr, (int)((ioaddr>>12)&0x0f)); - } else { /* ISA port address */ + printk("%s: %s at 0x%04lx (MCA slot %d)", dev->name, name, ioaddr, mca_slot); + } else if ((ioaddr & 0x0fff) == DEPCA_EISA_IO_PORTS) { /* EISA slot address */ + printk("%s: %s at 0x%04lx (EISA slot %d)", dev->name, name, ioaddr, (int) ((ioaddr >> 12) & 0x0f)); + } else { /* ISA port address */ printk("%s: %s at 0x%04lx", dev->name, name, ioaddr); } @@ -576,7 +572,7 @@ printk(" which has an Ethernet PROM CRC error.\n"); return -ENXIO; } - for (i=0; idev_addr[i]); } printk("%2.2x", dev->dev_addr[i]); @@ -587,19 +583,16 @@ netRAM = 128; offset = 0x0000; - /* Shared Memory Base Address */ + /* Shared Memory Base Address */ if (nicsr & BUF) { - offset = 0x8000; /* 32kbyte RAM offset*/ - nicsr &= ~BS; /* DEPCA RAM in top 32k */ + offset = 0x8000; /* 32kbyte RAM offset */ + nicsr &= ~BS; /* DEPCA RAM in top 32k */ netRAM -= 32; } - mem_start += offset; /* (E)ISA start address */ - if ((mem_len = (NUM_RX_DESC*(sizeof(struct depca_rx_desc)+RX_BUFF_SZ) + - NUM_TX_DESC*(sizeof(struct depca_tx_desc)+TX_BUFF_SZ) + - sizeof(struct depca_init))) - > (netRAM<<10)) { - printk(",\n requests %dkB RAM: only %dkB is available!\n", - (mem_len >> 10), netRAM); + mem_start += offset; /* (E)ISA start address */ + if ((mem_len = (NUM_RX_DESC * (sizeof(struct depca_rx_desc) + RX_BUFF_SZ) + NUM_TX_DESC * (sizeof(struct depca_tx_desc) + TX_BUFF_SZ) + sizeof(struct depca_init))) + > (netRAM << 10)) { + printk(",\n requests %dkB RAM: only %dkB is available!\n", (mem_len >> 10), netRAM); return -ENXIO; } @@ -610,21 +603,20 @@ nicsr |= SHE; outb(nicsr, DEPCA_NICSR); } - + /* Define the device private memory */ dev->priv = (void *) kmalloc(sizeof(struct depca_private), GFP_KERNEL); if (dev->priv == NULL) return -ENOMEM; - lp = (struct depca_private *)dev->priv; - memset((char *)dev->priv, 0, sizeof(struct depca_private)); + lp = (struct depca_private *) dev->priv; + memset((char *) dev->priv, 0, sizeof(struct depca_private)); lp->adapter = adapter; lp->mca_slot = mca_slot; lp->lock = SPIN_LOCK_UNLOCKED; - sprintf(lp->adapter_name,"%s (%s)", name, dev->name); + sprintf(lp->adapter_name, "%s (%s)", name, dev->name); status = -EBUSY; if (!request_region(ioaddr, DEPCA_TOTAL_SIZE, lp->adapter_name)) { - printk(KERN_ERR "depca: I/O resource 0x%x @ 0x%lx busy\n", - DEPCA_TOTAL_SIZE, ioaddr); + printk(KERN_ERR "depca: I/O resource 0x%x @ 0x%lx busy\n", DEPCA_TOTAL_SIZE, ioaddr); goto out_priv; } @@ -636,17 +628,17 @@ goto out_region; } lp->device_ram_start = mem_start & LA_MASK; - + offset = 0; offset += sizeof(struct depca_init); /* Tx & Rx descriptors (aligned to a quadword boundary) */ offset = (offset + ALIGN) & ~ALIGN; - lp->rx_ring = (struct depca_rx_desc *)(lp->sh_mem + offset); + lp->rx_ring = (struct depca_rx_desc *) (lp->sh_mem + offset); lp->rx_ring_offset = offset; offset += (sizeof(struct depca_rx_desc) * NUM_RX_DESC); - lp->tx_ring = (struct depca_tx_desc *)(lp->sh_mem + offset); + lp->tx_ring = (struct depca_tx_desc *) (lp->sh_mem + offset); lp->tx_ring_offset = offset; offset += (sizeof(struct depca_tx_desc) * NUM_TX_DESC); @@ -658,14 +650,14 @@ lp->txRingMask = NUM_TX_DESC - 1; /* Calculate Tx/Rx RLEN size for the descriptors. */ - for (i=0, j = lp->rxRingMask; j>0; i++) { + for (i = 0, j = lp->rxRingMask; j > 0; i++) { j >>= 1; } - lp->rx_rlen = (s32)(i << 29); - for (i=0, j = lp->txRingMask; j>0; i++) { + lp->rx_rlen = (s32) (i << 29); + for (i = 0, j = lp->txRingMask; j > 0; i++) { j >>= 1; } - lp->tx_rlen = (s32)(i << 29); + lp->tx_rlen = (s32) (i << 29); /* Load the initialisation block */ depca_init_ring(dev); @@ -674,7 +666,7 @@ LoadCSRs(dev); /* Enable DEPCA board interrupts for autoprobing */ - nicsr = ((nicsr & ~IM)|IEN); + nicsr = ((nicsr & ~IM) | IEN); outb(nicsr, DEPCA_NICSR); /* To auto-IRQ we enable the initialization-done and DMA err, @@ -705,26 +697,26 @@ /* Trigger an initialization just for the interrupt. */ outw(INEA | INIT, DEPCA_DATA); - + irqnum = autoirq_report(1); status = -ENXIO; if (!irqnum) { printk(" and failed to detect IRQ line.\n"); goto out_region; } else { - for (dev->irq=0,i=0; (depca_irq[i]) && (!dev->irq); i++) + for (dev->irq = 0, i = 0; (depca_irq[i]) && (!dev->irq); i++) if (irqnum == depca_irq[i]) { dev->irq = irqnum; printk(" and uses IRQ%d.\n", dev->irq); } - + status = -ENXIO; if (!dev->irq) { printk(" but incorrect IRQ line detected.\n"); goto out_region; } } -#endif /* MODULE */ +#endif /* MODULE */ } else { printk(" and assigned IRQ%d.\n", dev->irq); } @@ -748,65 +740,63 @@ /* Fill in the generic field of the device structure. */ ether_setup(dev); return 0; -out_region: + out_region: release_region(ioaddr, DEPCA_TOTAL_SIZE); -out_priv: + out_priv: kfree(dev->priv); dev->priv = NULL; return status; } - -static int -depca_open(struct net_device *dev) + +static int depca_open(struct net_device *dev) { - struct depca_private *lp = (struct depca_private *)dev->priv; - u_long ioaddr = dev->base_addr; - s16 nicsr; - int status = 0; - - STOP_DEPCA; - nicsr = inb(DEPCA_NICSR); - - /* Make sure the shadow RAM is enabled */ - if (lp->adapter != DEPCA) { - nicsr |= SHE; - outb(nicsr, DEPCA_NICSR); - } - - /* Re-initialize the DEPCA... */ - depca_init_ring(dev); - LoadCSRs(dev); - - depca_dbg_open(dev); - - if (request_irq(dev->irq, &depca_interrupt, 0, lp->adapter_name, dev)) { - printk("depca_open(): Requested IRQ%d is busy\n",dev->irq); - status = -EAGAIN; - } else { - - /* Enable DEPCA board interrupts and turn off LED */ - nicsr = ((nicsr & ~IM & ~LED)|IEN); - outb(nicsr, DEPCA_NICSR); - outw(CSR0,DEPCA_ADDR); - - netif_start_queue(dev); - - status = InitRestartDepca(dev); - - if (depca_debug > 1){ - printk("CSR0: 0x%4.4x\n",inw(DEPCA_DATA)); - printk("nicsr: 0x%02x\n",inb(DEPCA_NICSR)); - } - } - return status; + struct depca_private *lp = (struct depca_private *) dev->priv; + u_long ioaddr = dev->base_addr; + s16 nicsr; + int status = 0; + + STOP_DEPCA; + nicsr = inb(DEPCA_NICSR); + + /* Make sure the shadow RAM is enabled */ + if (lp->adapter != DEPCA) { + nicsr |= SHE; + outb(nicsr, DEPCA_NICSR); + } + + /* Re-initialize the DEPCA... */ + depca_init_ring(dev); + LoadCSRs(dev); + + depca_dbg_open(dev); + + if (request_irq(dev->irq, &depca_interrupt, 0, lp->adapter_name, dev)) { + printk("depca_open(): Requested IRQ%d is busy\n", dev->irq); + status = -EAGAIN; + } else { + + /* Enable DEPCA board interrupts and turn off LED */ + nicsr = ((nicsr & ~IM & ~LED) | IEN); + outb(nicsr, DEPCA_NICSR); + outw(CSR0, DEPCA_ADDR); + + netif_start_queue(dev); + + status = InitRestartDepca(dev); + + if (depca_debug > 1) { + printk("CSR0: 0x%4.4x\n", inw(DEPCA_DATA)); + printk("nicsr: 0x%02x\n", inb(DEPCA_NICSR)); + } + } + return status; } /* Initialize the lance Rx and Tx descriptor rings. */ -static void -depca_init_ring(struct net_device *dev) +static void depca_init_ring(struct net_device *dev) { - struct depca_private *lp = (struct depca_private *)dev->priv; + struct depca_private *lp = (struct depca_private *) dev->priv; u_int i; u_long offset; @@ -818,17 +808,15 @@ /* Initialize the base address and length of each buffer in the ring */ for (i = 0; i <= lp->rxRingMask; i++) { - offset = lp->buffs_offset + i*RX_BUFF_SZ; - writel((lp->device_ram_start + offset) | R_OWN, - &lp->rx_ring[i].base); + offset = lp->buffs_offset + i * RX_BUFF_SZ; + writel((lp->device_ram_start + offset) | R_OWN, &lp->rx_ring[i].base); writew(-RX_BUFF_SZ, &lp->rx_ring[i].buf_length); lp->rx_buff[i] = lp->sh_mem + offset; } for (i = 0; i <= lp->txRingMask; i++) { - offset = lp->buffs_offset + (i + lp->rxRingMask+1)*TX_BUFF_SZ; - writel((lp->device_ram_start + offset) & 0x00ffffff, - &lp->tx_ring[i].base); + offset = lp->buffs_offset + (i + lp->rxRingMask + 1) * TX_BUFF_SZ; + writel((lp->device_ram_start + offset) & 0x00ffffff, &lp->tx_ring[i].base); lp->tx_buff[i] = lp->sh_mem + offset; } @@ -842,30 +830,29 @@ lp->init_block.phys_addr[i] = dev->dev_addr[i]; } - lp->init_block.mode = 0x0000; /* Enable the Tx and Rx */ + lp->init_block.mode = 0x0000; /* Enable the Tx and Rx */ } -static void depca_tx_timeout (struct net_device *dev) +static void depca_tx_timeout(struct net_device *dev) { u_long ioaddr = dev->base_addr; - printk ("%s: transmit timed out, status %04x, resetting.\n", - dev->name, inw (DEPCA_DATA)); + printk("%s: transmit timed out, status %04x, resetting.\n", dev->name, inw(DEPCA_DATA)); STOP_DEPCA; - depca_init_ring (dev); - LoadCSRs (dev); + depca_init_ring(dev); + LoadCSRs(dev); dev->trans_start = jiffies; - netif_wake_queue (dev); - InitRestartDepca (dev); + netif_wake_queue(dev); + InitRestartDepca(dev); } /* ** Writes a socket buffer to TX descriptor ring and starts transmission */ -static int depca_start_xmit (struct sk_buff *skb, struct net_device *dev) +static int depca_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct depca_private *lp = (struct depca_private *) dev->priv; u_long ioaddr = dev->base_addr; @@ -875,32 +862,32 @@ if (skb->len < 1) goto out; - netif_stop_queue (dev); + netif_stop_queue(dev); if (TX_BUFFS_AVAIL) { /* Fill in a Tx ring entry */ - status = load_packet (dev, skb); + status = load_packet(dev, skb); if (!status) { /* Trigger an immediate send demand. */ - outw (CSR0, DEPCA_ADDR); - outw (INEA | TDMD, DEPCA_DATA); + outw(CSR0, DEPCA_ADDR); + outw(INEA | TDMD, DEPCA_DATA); dev->trans_start = jiffies; - dev_kfree_skb (skb); + dev_kfree_skb(skb); } if (TX_BUFFS_AVAIL) - netif_start_queue (dev); + netif_start_queue(dev); } else status = -1; -out: + out: return status; } /* ** The DEPCA interrupt handler. */ -static void depca_interrupt (int irq, void *dev_id, struct pt_regs *regs) +static void depca_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = dev_id; struct depca_private *lp; @@ -908,308 +895,301 @@ u_long ioaddr; if (dev == NULL) { - printk ("depca_interrupt(): irq %d for unknown device.\n", irq); + printk("depca_interrupt(): irq %d for unknown device.\n", irq); return; } lp = (struct depca_private *) dev->priv; ioaddr = dev->base_addr; - spin_lock (&lp->lock); + spin_lock(&lp->lock); /* mask the DEPCA board interrupts and turn on the LED */ - nicsr = inb (DEPCA_NICSR); + nicsr = inb(DEPCA_NICSR); nicsr |= (IM | LED); - outb (nicsr, DEPCA_NICSR); + outb(nicsr, DEPCA_NICSR); - outw (CSR0, DEPCA_ADDR); - csr0 = inw (DEPCA_DATA); + outw(CSR0, DEPCA_ADDR); + csr0 = inw(DEPCA_DATA); /* Acknowledge all of the current interrupt sources ASAP. */ - outw (csr0 & INTE, DEPCA_DATA); + outw(csr0 & INTE, DEPCA_DATA); if (csr0 & RINT) /* Rx interrupt (packet arrived) */ - depca_rx (dev); + depca_rx(dev); if (csr0 & TINT) /* Tx interrupt (packet sent) */ - depca_tx (dev); + depca_tx(dev); /* Any resources available? */ if ((TX_BUFFS_AVAIL >= 0) && netif_queue_stopped(dev)) { - netif_wake_queue (dev); + netif_wake_queue(dev); } /* Unmask the DEPCA board interrupts and turn off the LED */ nicsr = (nicsr & ~IM & ~LED); - outb (nicsr, DEPCA_NICSR); + outb(nicsr, DEPCA_NICSR); - spin_unlock (&lp->lock); + spin_unlock(&lp->lock); } -static int -depca_rx(struct net_device *dev) +static int depca_rx(struct net_device *dev) { - struct depca_private *lp = (struct depca_private *)dev->priv; - int i, entry; - s32 status; - - for (entry=lp->rx_new; - !(readl(&lp->rx_ring[entry].base) & R_OWN); - entry=lp->rx_new){ - status = readl(&lp->rx_ring[entry].base) >> 16 ; - if (status & R_STP) { /* Remember start of frame */ - lp->rx_old = entry; - } - if (status & R_ENP) { /* Valid frame status */ - if (status & R_ERR) { /* There was an error. */ - lp->stats.rx_errors++; /* Update the error stats. */ - if (status & R_FRAM) lp->stats.rx_frame_errors++; - if (status & R_OFLO) lp->stats.rx_over_errors++; - if (status & R_CRC) lp->stats.rx_crc_errors++; - if (status & R_BUFF) lp->stats.rx_fifo_errors++; - } else { - short len, pkt_len = readw(&lp->rx_ring[entry].msg_length) - 4; - struct sk_buff *skb; - - skb = dev_alloc_skb(pkt_len+2); - if (skb != NULL) { - unsigned char *buf; - skb_reserve(skb,2); /* 16 byte align the IP header */ - buf = skb_put(skb,pkt_len); - skb->dev = dev; - if (entry < lp->rx_old) { /* Wrapped buffer */ - len = (lp->rxRingMask - lp->rx_old + 1) * RX_BUFF_SZ; - memcpy_fromio(buf, lp->rx_buff[lp->rx_old], len); - memcpy_fromio(buf + len, lp->rx_buff[0], pkt_len-len); - } else { /* Linear buffer */ - memcpy_fromio(buf, lp->rx_buff[lp->rx_old], pkt_len); - } - - /* - ** Notify the upper protocol layers that there is another - ** packet to handle - */ - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); - - /* - ** Update stats - */ - dev->last_rx = jiffies; - lp->stats.rx_packets++; - lp->stats.rx_bytes += pkt_len; - for (i=1; ipktStats.bins[i]++; - i = DEPCA_PKT_STAT_SZ; - } - } - if (buf[0] & 0x01) { /* Multicast/Broadcast */ - if ((*(s16 *)&buf[0] == -1) && - (*(s16 *)&buf[2] == -1) && - (*(s16 *)&buf[4] == -1)) { - lp->pktStats.broadcast++; - } else { - lp->pktStats.multicast++; - } - } else if ((*(s16 *)&buf[0] == *(s16 *)&dev->dev_addr[0]) && - (*(s16 *)&buf[2] == *(s16 *)&dev->dev_addr[2]) && - (*(s16 *)&buf[4] == *(s16 *)&dev->dev_addr[4])) { - lp->pktStats.unicast++; - } - - lp->pktStats.bins[0]++; /* Duplicates stats.rx_packets */ - if (lp->pktStats.bins[0] == 0) { /* Reset counters */ - memset((char *)&lp->pktStats, 0, sizeof(lp->pktStats)); - } - } else { - printk("%s: Memory squeeze, deferring packet.\n", dev->name); - lp->stats.rx_dropped++; /* Really, deferred. */ - break; - } - } - /* Change buffer ownership for this last frame, back to the adapter */ - for (; lp->rx_old!=entry; lp->rx_old=(++lp->rx_old)&lp->rxRingMask) { - writel(readl(&lp->rx_ring[lp->rx_old].base) | R_OWN, - &lp->rx_ring[lp->rx_old].base); - } - writel(readl(&lp->rx_ring[entry].base) | R_OWN, &lp->rx_ring[entry].base); - } - - /* - ** Update entry information - */ - lp->rx_new = (++lp->rx_new) & lp->rxRingMask; - } + struct depca_private *lp = (struct depca_private *) dev->priv; + int i, entry; + s32 status; - return 0; + for (entry = lp->rx_new; !(readl(&lp->rx_ring[entry].base) & R_OWN); entry = lp->rx_new) { + status = readl(&lp->rx_ring[entry].base) >> 16; + if (status & R_STP) { /* Remember start of frame */ + lp->rx_old = entry; + } + if (status & R_ENP) { /* Valid frame status */ + if (status & R_ERR) { /* There was an error. */ + lp->stats.rx_errors++; /* Update the error stats. */ + if (status & R_FRAM) + lp->stats.rx_frame_errors++; + if (status & R_OFLO) + lp->stats.rx_over_errors++; + if (status & R_CRC) + lp->stats.rx_crc_errors++; + if (status & R_BUFF) + lp->stats.rx_fifo_errors++; + } else { + short len, pkt_len = readw(&lp->rx_ring[entry].msg_length) - 4; + struct sk_buff *skb; + + skb = dev_alloc_skb(pkt_len + 2); + if (skb != NULL) { + unsigned char *buf; + skb_reserve(skb, 2); /* 16 byte align the IP header */ + buf = skb_put(skb, pkt_len); + skb->dev = dev; + if (entry < lp->rx_old) { /* Wrapped buffer */ + len = (lp->rxRingMask - lp->rx_old + 1) * RX_BUFF_SZ; + memcpy_fromio(buf, lp->rx_buff[lp->rx_old], len); + memcpy_fromio(buf + len, lp->rx_buff[0], pkt_len - len); + } else { /* Linear buffer */ + memcpy_fromio(buf, lp->rx_buff[lp->rx_old], pkt_len); + } + + /* + ** Notify the upper protocol layers that there is another + ** packet to handle + */ + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + + /* + ** Update stats + */ + dev->last_rx = jiffies; + lp->stats.rx_packets++; + lp->stats.rx_bytes += pkt_len; + for (i = 1; i < DEPCA_PKT_STAT_SZ - 1; i++) { + if (pkt_len < (i * DEPCA_PKT_BIN_SZ)) { + lp->pktStats.bins[i]++; + i = DEPCA_PKT_STAT_SZ; + } + } + if (buf[0] & 0x01) { /* Multicast/Broadcast */ + if ((*(s16 *) & buf[0] == -1) && (*(s16 *) & buf[2] == -1) && (*(s16 *) & buf[4] == -1)) { + lp->pktStats.broadcast++; + } else { + lp->pktStats.multicast++; + } + } else if ((*(s16 *) & buf[0] == *(s16 *) & dev->dev_addr[0]) && (*(s16 *) & buf[2] == *(s16 *) & dev->dev_addr[2]) && (*(s16 *) & buf[4] == *(s16 *) & dev->dev_addr[4])) { + lp->pktStats.unicast++; + } + + lp->pktStats.bins[0]++; /* Duplicates stats.rx_packets */ + if (lp->pktStats.bins[0] == 0) { /* Reset counters */ + memset((char *) &lp->pktStats, 0, sizeof(lp->pktStats)); + } + } else { + printk("%s: Memory squeeze, deferring packet.\n", dev->name); + lp->stats.rx_dropped++; /* Really, deferred. */ + break; + } + } + /* Change buffer ownership for this last frame, back to the adapter */ + for (; lp->rx_old != entry; lp->rx_old = (++lp->rx_old) & lp->rxRingMask) { + writel(readl(&lp->rx_ring[lp->rx_old].base) | R_OWN, &lp->rx_ring[lp->rx_old].base); + } + writel(readl(&lp->rx_ring[entry].base) | R_OWN, &lp->rx_ring[entry].base); + } + + /* + ** Update entry information + */ + lp->rx_new = (++lp->rx_new) & lp->rxRingMask; + } + + return 0; } /* ** Buffer sent - check for buffer errors. */ -static int -depca_tx(struct net_device *dev) +static int depca_tx(struct net_device *dev) +{ + struct depca_private *lp = (struct depca_private *) dev->priv; + int entry; + s32 status; + u_long ioaddr = dev->base_addr; + + for (entry = lp->tx_old; entry != lp->tx_new; entry = lp->tx_old) { + status = readl(&lp->tx_ring[entry].base) >> 16; + + if (status < 0) { /* Packet not yet sent! */ + break; + } else if (status & T_ERR) { /* An error occurred. */ + status = readl(&lp->tx_ring[entry].misc); + lp->stats.tx_errors++; + if (status & TMD3_RTRY) + lp->stats.tx_aborted_errors++; + if (status & TMD3_LCAR) + lp->stats.tx_carrier_errors++; + if (status & TMD3_LCOL) + lp->stats.tx_window_errors++; + if (status & TMD3_UFLO) + lp->stats.tx_fifo_errors++; + if (status & (TMD3_BUFF | TMD3_UFLO)) { + /* Trigger an immediate send demand. */ + outw(CSR0, DEPCA_ADDR); + outw(INEA | TDMD, DEPCA_DATA); + } + } else if (status & (T_MORE | T_ONE)) { + lp->stats.collisions++; + } else { + lp->stats.tx_packets++; + } + + /* Update all the pointers */ + lp->tx_old = (++lp->tx_old) & lp->txRingMask; + } + + return 0; +} + +static int depca_close(struct net_device *dev) { - struct depca_private *lp = (struct depca_private *)dev->priv; - int entry; - s32 status; - u_long ioaddr = dev->base_addr; - - for (entry = lp->tx_old; entry != lp->tx_new; entry = lp->tx_old) { - status = readl(&lp->tx_ring[entry].base) >> 16 ; - - if (status < 0) { /* Packet not yet sent! */ - break; - } else if (status & T_ERR) { /* An error occurred. */ - status = readl(&lp->tx_ring[entry].misc); - lp->stats.tx_errors++; - if (status & TMD3_RTRY) lp->stats.tx_aborted_errors++; - if (status & TMD3_LCAR) lp->stats.tx_carrier_errors++; - if (status & TMD3_LCOL) lp->stats.tx_window_errors++; - if (status & TMD3_UFLO) lp->stats.tx_fifo_errors++; - if (status & (TMD3_BUFF | TMD3_UFLO)) { - /* Trigger an immediate send demand. */ + struct depca_private *lp = (struct depca_private *) dev->priv; + s16 nicsr; + u_long ioaddr = dev->base_addr; + + netif_stop_queue(dev); + outw(CSR0, DEPCA_ADDR); - outw(INEA | TDMD, DEPCA_DATA); - } - } else if (status & (T_MORE | T_ONE)) { - lp->stats.collisions++; - } else { - lp->stats.tx_packets++; - } - - /* Update all the pointers */ - lp->tx_old = (++lp->tx_old) & lp->txRingMask; - } - - return 0; -} - -static int -depca_close(struct net_device *dev) -{ - struct depca_private *lp = (struct depca_private *)dev->priv; - s16 nicsr; - u_long ioaddr = dev->base_addr; - - netif_stop_queue(dev); - - outw(CSR0, DEPCA_ADDR); - - if (depca_debug > 1) { - printk("%s: Shutting down ethercard, status was %2.2x.\n", - dev->name, inw(DEPCA_DATA)); - } - - /* - ** We stop the DEPCA here -- it occasionally polls - ** memory if we don't. - */ - outw(STOP, DEPCA_DATA); - - /* - ** Give back the ROM in case the user wants to go to DOS - */ - if (lp->adapter != DEPCA) { - nicsr = inb(DEPCA_NICSR); - nicsr &= ~SHE; - outb(nicsr, DEPCA_NICSR); - } - - /* - ** Free the associated irq - */ - free_irq(dev->irq, dev); - return 0; + + if (depca_debug > 1) { + printk("%s: Shutting down ethercard, status was %2.2x.\n", dev->name, inw(DEPCA_DATA)); + } + + /* + ** We stop the DEPCA here -- it occasionally polls + ** memory if we don't. + */ + outw(STOP, DEPCA_DATA); + + /* + ** Give back the ROM in case the user wants to go to DOS + */ + if (lp->adapter != DEPCA) { + nicsr = inb(DEPCA_NICSR); + nicsr &= ~SHE; + outb(nicsr, DEPCA_NICSR); + } + + /* + ** Free the associated irq + */ + free_irq(dev->irq, dev); + return 0; } static void LoadCSRs(struct net_device *dev) { - struct depca_private *lp = (struct depca_private *)dev->priv; - u_long ioaddr = dev->base_addr; + struct depca_private *lp = (struct depca_private *) dev->priv; + u_long ioaddr = dev->base_addr; - outw(CSR1, DEPCA_ADDR); /* initialisation block address LSW */ - outw((u16)lp->device_ram_start, DEPCA_DATA); - outw(CSR2, DEPCA_ADDR); /* initialisation block address MSW */ - outw((u16)(lp->device_ram_start >> 16), DEPCA_DATA); - outw(CSR3, DEPCA_ADDR); /* ALE control */ - outw(ACON, DEPCA_DATA); + outw(CSR1, DEPCA_ADDR); /* initialisation block address LSW */ + outw((u16) lp->device_ram_start, DEPCA_DATA); + outw(CSR2, DEPCA_ADDR); /* initialisation block address MSW */ + outw((u16) (lp->device_ram_start >> 16), DEPCA_DATA); + outw(CSR3, DEPCA_ADDR); /* ALE control */ + outw(ACON, DEPCA_DATA); - outw(CSR0, DEPCA_ADDR); /* Point back to CSR0 */ + outw(CSR0, DEPCA_ADDR); /* Point back to CSR0 */ - return; + return; } static int InitRestartDepca(struct net_device *dev) { - struct depca_private *lp = (struct depca_private *)dev->priv; - u_long ioaddr = dev->base_addr; - int i, status=0; - - /* Copy the shadow init_block to shared memory */ - memcpy_toio(lp->sh_mem, &lp->init_block, sizeof(struct depca_init)); + struct depca_private *lp = (struct depca_private *) dev->priv; + u_long ioaddr = dev->base_addr; + int i, status = 0; - outw(CSR0, DEPCA_ADDR); /* point back to CSR0 */ - outw(INIT, DEPCA_DATA); /* initialize DEPCA */ + /* Copy the shadow init_block to shared memory */ + memcpy_toio(lp->sh_mem, &lp->init_block, sizeof(struct depca_init)); - /* wait for lance to complete initialisation */ - for (i=0;(i<100) && !(inw(DEPCA_DATA) & IDON); i++); + outw(CSR0, DEPCA_ADDR); /* point back to CSR0 */ + outw(INIT, DEPCA_DATA); /* initialize DEPCA */ - if (i!=100) { - /* clear IDON by writing a "1", enable interrupts and start lance */ - outw(IDON | INEA | STRT, DEPCA_DATA); - if (depca_debug > 2) { - printk("%s: DEPCA open after %d ticks, init block 0x%08lx csr0 %4.4x.\n", - dev->name, i, virt_to_phys(lp->sh_mem), inw(DEPCA_DATA)); - } - } else { - printk("%s: DEPCA unopen after %d ticks, init block 0x%08lx csr0 %4.4x.\n", - dev->name, i, virt_to_phys(lp->sh_mem), inw(DEPCA_DATA)); - status = -1; - } + /* wait for lance to complete initialisation */ + for (i = 0; (i < 100) && !(inw(DEPCA_DATA) & IDON); i++); + + if (i != 100) { + /* clear IDON by writing a "1", enable interrupts and start lance */ + outw(IDON | INEA | STRT, DEPCA_DATA); + if (depca_debug > 2) { + printk("%s: DEPCA open after %d ticks, init block 0x%08lx csr0 %4.4x.\n", dev->name, i, virt_to_phys(lp->sh_mem), inw(DEPCA_DATA)); + } + } else { + printk("%s: DEPCA unopen after %d ticks, init block 0x%08lx csr0 %4.4x.\n", dev->name, i, virt_to_phys(lp->sh_mem), inw(DEPCA_DATA)); + status = -1; + } - return status; + return status; } -static struct net_device_stats * -depca_get_stats(struct net_device *dev) +static struct net_device_stats *depca_get_stats(struct net_device *dev) { - struct depca_private *lp = (struct depca_private *)dev->priv; + struct depca_private *lp = (struct depca_private *) dev->priv; - /* Null body since there is no framing error counter */ + /* Null body since there is no framing error counter */ - return &lp->stats; + return &lp->stats; } /* ** Set or clear the multicast filter for this adaptor. */ -static void -set_multicast_list(struct net_device *dev) +static void set_multicast_list(struct net_device *dev) { - struct depca_private *lp = (struct depca_private *)dev->priv; - u_long ioaddr = dev->base_addr; - - if (dev) { - netif_stop_queue(dev); - while(lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ - - STOP_DEPCA; /* Temporarily stop the depca. */ - depca_init_ring(dev); /* Initialize the descriptor rings */ - - if (dev->flags & IFF_PROMISC) { /* Set promiscuous mode */ - lp->init_block.mode |= PROM; - } else { - SetMulticastFilter(dev); - lp->init_block.mode &= ~PROM; /* Unset promiscuous mode */ - } - - LoadCSRs(dev); /* Reload CSR3 */ - InitRestartDepca(dev); /* Resume normal operation. */ - netif_start_queue(dev); /* Unlock the TX ring */ - } + struct depca_private *lp = (struct depca_private *) dev->priv; + u_long ioaddr = dev->base_addr; + + if (dev) { + netif_stop_queue(dev); + while (lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ + + STOP_DEPCA; /* Temporarily stop the depca. */ + depca_init_ring(dev); /* Initialize the descriptor rings */ + + if (dev->flags & IFF_PROMISC) { /* Set promiscuous mode */ + lp->init_block.mode |= PROM; + } else { + SetMulticastFilter(dev); + lp->init_block.mode &= ~PROM; /* Unset promiscuous mode */ + } + + LoadCSRs(dev); /* Reload CSR3 */ + InitRestartDepca(dev); /* Resume normal operation. */ + netif_start_queue(dev); /* Unlock the TX ring */ + } } /* @@ -1220,274 +1200,278 @@ */ static void SetMulticastFilter(struct net_device *dev) { - struct depca_private *lp = (struct depca_private *)dev->priv; - struct dev_mc_list *dmi=dev->mc_list; - char *addrs; - int i, j, bit, byte; - u16 hashcode; - u32 crc; - - if (dev->flags & IFF_ALLMULTI) { /* Set all multicast bits */ - for (i=0; i<(HASH_TABLE_LEN>>3); i++) { - lp->init_block.mcast_table[i] = (char)0xff; - } - } else { - for (i=0; i<(HASH_TABLE_LEN>>3); i++){ /* Clear the multicast table */ - lp->init_block.mcast_table[i]=0; - } - /* Add multicast addresses */ - for (i=0;imc_count;i++) { /* for each address in the list */ - addrs=dmi->dmi_addr; - dmi=dmi->next; - if ((*addrs & 0x01) == 1) { /* multicast address? */ - crc = ether_crc(ETH_ALEN, addrs); - hashcode = (crc & 1); /* hashcode is 6 LSb of CRC ... */ - for (j=0;j<5;j++) { /* ... in reverse order. */ - hashcode = (hashcode << 1) | ((crc>>=1) & 1); - } - - - byte = hashcode >> 3; /* bit[3-5] -> byte in filter */ - bit = 1 << (hashcode & 0x07); /* bit[0-2] -> bit in byte */ - lp->init_block.mcast_table[byte] |= bit; - } - } - } + struct depca_private *lp = (struct depca_private *) dev->priv; + struct dev_mc_list *dmi = dev->mc_list; + char *addrs; + int i, j, bit, byte; + u16 hashcode; + u32 crc; + + if (dev->flags & IFF_ALLMULTI) { /* Set all multicast bits */ + for (i = 0; i < (HASH_TABLE_LEN >> 3); i++) { + lp->init_block.mcast_table[i] = (char) 0xff; + } + } else { + for (i = 0; i < (HASH_TABLE_LEN >> 3); i++) { /* Clear the multicast table */ + lp->init_block.mcast_table[i] = 0; + } + /* Add multicast addresses */ + for (i = 0; i < dev->mc_count; i++) { /* for each address in the list */ + addrs = dmi->dmi_addr; + dmi = dmi->next; + if ((*addrs & 0x01) == 1) { /* multicast address? */ + crc = ether_crc(ETH_ALEN, addrs); + hashcode = (crc & 1); /* hashcode is 6 LSb of CRC ... */ + for (j = 0; j < 5; j++) { /* ... in reverse order. */ + hashcode = (hashcode << 1) | ((crc >>= 1) & 1); + } + - return; + byte = hashcode >> 3; /* bit[3-5] -> byte in filter */ + bit = 1 << (hashcode & 0x07); /* bit[0-2] -> bit in byte */ + lp->init_block.mcast_table[byte] |= bit; + } + } + } + + return; } #ifdef CONFIG_MCA /* ** Microchannel bus I/O device probe */ -static void __init -mca_probe(struct net_device *dev, u_long ioaddr) +static void __init mca_probe(struct net_device *dev, u_long ioaddr) { - unsigned char pos[2]; - unsigned char where; - unsigned long iobase; - int irq; - int slot = 0; - - /* - ** See if we've been here before. - */ - if ((!ioaddr && autoprobed) || (ioaddr && !loading_module)) return; + unsigned char pos[2]; + unsigned char where; + unsigned long iobase; + int irq; + int slot = 0; - if (MCA_bus) { /* - ** Search for the adapter. If an address has been given, search - ** specifically for the card at that address. Otherwise find the - ** first card in the system. - */ - while ((dev!=NULL) && - ((slot=mca_find_adapter(DE212_ID, slot)) != MCA_NOTFOUND)) { - pos[0] = mca_read_stored_pos(slot, 2); - pos[1] = mca_read_stored_pos(slot, 3); - - /* - ** IO of card is handled by bits 1 and 2 of pos0. - ** - ** bit2 bit1 IO - ** 0 0 0x2c00 - ** 0 1 0x2c10 - ** 1 0 0x2c20 - ** 1 1 0x2c30 - */ - where = (pos[0] & 6) >> 1; - iobase = 0x2c00 + (0x10 * where); - - if ((ioaddr) && (ioaddr != iobase)) { - /* - ** Card was found, but not at the right IO location. Continue - ** scanning from the next MCA slot up for another card. - */ - slot++; - continue; - } - - /* - ** Found the adapter we were looking for. Now start setting it up. - ** - ** First work on decoding the IRQ. It's stored in the lower 4 bits - ** of pos1. Bits are as follows (from the ADF file): - ** - ** Bits - ** 3 2 1 0 IRQ - ** -------------------- - ** 0 0 1 0 5 - ** 0 0 0 1 9 - ** 0 1 0 0 10 - ** 1 0 0 0 11 - **/ - where = pos[1] & 0x0f; - switch(where) { - case 1: - irq = 9; - break; - case 2: - irq = 5; - break; - case 4: - irq = 10; - break; - case 8: - irq = 11; - break; - default: - printk("%s: mca_probe IRQ error. You should never get here (%d).\n", dev->name, where); + ** See if we've been here before. + */ + if ((!ioaddr && autoprobed) || (ioaddr && !loading_module)) return; - } - - /* - ** Shared memory address of adapter is stored in bits 3-5 of pos0. - ** They are mapped as follows: - ** - ** Bit - ** 5 4 3 Memory Addresses - ** 0 0 0 C0000-CFFFF (64K) - ** 1 0 0 C8000-CFFFF (32K) - ** 0 0 1 D0000-DFFFF (64K) - ** 1 0 1 D8000-DFFFF (32K) - ** 0 1 0 E0000-EFFFF (64K) - ** 1 1 0 E8000-EFFFF (32K) - */ - where = (pos[0] & 0x18) >> 3; - mem = 0xc0000 + (where * 0x10000); - if (pos[0] & 0x20) { - mem += 0x8000; - } - - /* - ** Get everything allocated and initialized... (almost just - ** like the ISA and EISA probes) - */ - if (DevicePresent(iobase) != 0) { + + if (MCA_bus) { /* - ** If the MCA configuration says the card should be here, - ** it really should be here. - */ - printk(KERN_ERR "%s: MCA reports card at 0x%lx but it is not + ** Search for the adapter. If an address has been given, search + ** specifically for the card at that address. Otherwise find the + ** first card in the system. + */ + while ((dev != NULL) && ((slot = mca_find_adapter(DE212_ID, slot)) != MCA_NOTFOUND)) { + pos[0] = mca_read_stored_pos(slot, 2); + pos[1] = mca_read_stored_pos(slot, 3); + + /* + ** IO of card is handled by bits 1 and 2 of pos0. + ** + ** bit2 bit1 IO + ** 0 0 0x2c00 + ** 0 1 0x2c10 + ** 1 0 0x2c20 + ** 1 1 0x2c30 + */ + where = (pos[0] & 6) >> 1; + iobase = 0x2c00 + (0x10 * where); + + if ((ioaddr) && (ioaddr != iobase)) { + /* + ** Card was found, but not at the right IO location. Continue + ** scanning from the next MCA slot up for another card. + */ + slot++; + continue; + } + + /* + ** Found the adapter we were looking for. Now start setting it up. + ** + ** First work on decoding the IRQ. It's stored in the lower 4 bits + ** of pos1. Bits are as follows (from the ADF file): + ** + ** Bits + ** 3 2 1 0 IRQ + ** -------------------- + ** 0 0 1 0 5 + ** 0 0 0 1 9 + ** 0 1 0 0 10 + ** 1 0 0 0 11 + * */ + where = pos[1] & 0x0f; + switch (where) { + case 1: + irq = 9; + break; + case 2: + irq = 5; + break; + case 4: + irq = 10; + break; + case 8: + irq = 11; + break; + default: + printk("%s: mca_probe IRQ error. You should never get here (%d).\n", dev->name, where); + return; + } + + /* + ** Shared memory address of adapter is stored in bits 3-5 of pos0. + ** They are mapped as follows: + ** + ** Bit + ** 5 4 3 Memory Addresses + ** 0 0 0 C0000-CFFFF (64K) + ** 1 0 0 C8000-CFFFF (32K) + ** 0 0 1 D0000-DFFFF (64K) + ** 1 0 1 D8000-DFFFF (32K) + ** 0 1 0 E0000-EFFFF (64K) + ** 1 1 0 E8000-EFFFF (32K) + */ + where = (pos[0] & 0x18) >> 3; + mem = 0xc0000 + (where * 0x10000); + if (pos[0] & 0x20) { + mem += 0x8000; + } + + /* + ** Get everything allocated and initialized... (almost just + ** like the ISA and EISA probes) + */ + if (DevicePresent(iobase) != 0) { + /* + ** If the MCA configuration says the card should be here, + ** it really should be here. + */ + printk(KERN_ERR "%s: MCA reports card at 0x%lx but it is not responding.\n", dev->name, iobase); - } - - if (check_region(iobase, DEPCA_TOTAL_SIZE) == 0) { - if ((dev = alloc_device(dev, iobase)) != NULL) { - dev->irq = irq; - if (depca_hw_init(dev, iobase, slot) == 0) { + } + + if (check_region(iobase, DEPCA_TOTAL_SIZE) == 0) { + if ((dev = alloc_device(dev, iobase)) != NULL) { + dev->irq = irq; + if (depca_hw_init(dev, iobase, slot) == 0) { + /* + ** Adapter initialized correctly: Name it in + ** /proc/mca. + */ + mca_set_adapter_name(slot, "DE210/212 Ethernet Adapter"); + mca_mark_as_used(slot); + num_depcas++; + } + num_eth++; + } + } else if (autoprobed) { + printk(KERN_WARNING "%s: region already allocated at 0x%04lx.\n", dev->name, iobase); + } + + /* + ** If this is a probe by a module, return after setting up the + ** given card. + */ + if (ioaddr) + return; + /* - ** Adapter initialized correctly: Name it in - ** /proc/mca. - */ - mca_set_adapter_name(slot, "DE210/212 Ethernet Adapter"); - mca_mark_as_used(slot); - num_depcas++; - } - num_eth++; - } - } else if (autoprobed) { - printk(KERN_WARNING "%s: region already allocated at 0x%04lx.\n", dev->name, iobase); - } - - /* - ** If this is a probe by a module, return after setting up the - ** given card. - */ - if (ioaddr) return; - - /* - ** Set up to check the next slot and loop. - */ - slot++; + ** Set up to check the next slot and loop. + */ + slot++; + } } - } - return; + return; } #endif /* ** ISA bus I/O device probe */ -static void __init -isa_probe(struct net_device *dev, u_long ioaddr) +static void __init isa_probe(struct net_device *dev, u_long ioaddr) { - int i = num_depcas, maxSlots; - s32 ports[] = DEPCA_IO_PORTS; + int i = num_depcas, maxSlots; + s32 ports[] = DEPCA_IO_PORTS; - if (!ioaddr && autoprobed) return ; /* Been here before ! */ - if (ioaddr > 0x400) return; /* EISA Address */ - if (i >= MAX_NUM_DEPCAS) return; /* Too many ISA adapters */ - - if (ioaddr == 0) { /* Autoprobing */ - maxSlots = MAX_NUM_DEPCAS; - } else { /* Probe a specific location */ - ports[i] = ioaddr; - maxSlots = i + 1; - } - - for (; (iname, ports[i]); - } - } + if (!ioaddr && autoprobed) + return; /* Been here before ! */ + if (ioaddr > 0x400) + return; /* EISA Address */ + if (i >= MAX_NUM_DEPCAS) + return; /* Too many ISA adapters */ + + if (ioaddr == 0) { /* Autoprobing */ + maxSlots = MAX_NUM_DEPCAS; + } else { /* Probe a specific location */ + ports[i] = ioaddr; + maxSlots = i + 1; + } + + for (; (i < maxSlots) && (dev != NULL) && ports[i]; i++) { + if (check_region(ports[i], DEPCA_TOTAL_SIZE) == 0) { + if (DevicePresent(ports[i]) == 0) { + if ((dev = alloc_device(dev, ports[i])) != NULL) { + if (depca_hw_init(dev, ports[i], -1) == 0) { + num_depcas++; + } + num_eth++; + } + } + } else if (autoprobed) { + printk("%s: region already allocated at 0x%04x.\n", dev->name, ports[i]); + } + } - return; + return; } /* ** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually ** the motherboard. Upto 15 EISA devices are supported. */ -static void __init -eisa_probe(struct net_device *dev, u_long ioaddr) +static void __init eisa_probe(struct net_device *dev, u_long ioaddr) { - int i, maxSlots; - u_long iobase; - char name[DEPCA_STRLEN]; - - if (!ioaddr && autoprobed) return ; /* Been here before ! */ - if ((ioaddr < 0x400) && (ioaddr > 0)) return; /* ISA Address */ - - if (ioaddr == 0) { /* Autoprobing */ - iobase = EISA_SLOT_INC; /* Get the first slot address */ - i = 1; - maxSlots = MAX_EISA_SLOTS; - } else { /* Probe a specific location */ - iobase = ioaddr; - i = (ioaddr >> 12); - maxSlots = i + 1; - } - if ((iobase & 0x0fff) == 0) iobase += DEPCA_EISA_IO_PORTS; - - for (; (iname, iobase); - } - } + int i, maxSlots; + u_long iobase; + char name[DEPCA_STRLEN]; + + if (!ioaddr && autoprobed) + return; /* Been here before ! */ + if ((ioaddr < 0x400) && (ioaddr > 0)) + return; /* ISA Address */ + + if (ioaddr == 0) { /* Autoprobing */ + iobase = EISA_SLOT_INC; /* Get the first slot address */ + i = 1; + maxSlots = MAX_EISA_SLOTS; + } else { /* Probe a specific location */ + iobase = ioaddr; + i = (ioaddr >> 12); + maxSlots = i + 1; + } + if ((iobase & 0x0fff) == 0) + iobase += DEPCA_EISA_IO_PORTS; + + for (; (i < maxSlots) && (dev != NULL); i++, iobase += EISA_SLOT_INC) { + if (check_region(iobase, DEPCA_TOTAL_SIZE) == 0) { + if (EISA_signature(name, EISA_ID)) { + if (DevicePresent(iobase) == 0) { + if ((dev = alloc_device(dev, iobase)) != NULL) { + if (depca_hw_init(dev, iobase, -1) == 0) { + num_depcas++; + } + num_eth++; + } + } + } + } else if (autoprobed) { + printk("%s: region already allocated at 0x%04lx.\n", dev->name, iobase); + } + } - return; + return; } /* @@ -1496,89 +1480,87 @@ ** are not available then insert a new device structure at the end of ** the current list. */ -static struct net_device * __init -alloc_device(struct net_device *dev, u_long iobase) +static struct net_device *__init alloc_device(struct net_device *dev, u_long iobase) { - struct net_device *adev = NULL; - int fixed = 0, new_dev = 0; + struct net_device *adev = NULL; + int fixed = 0, new_dev = 0; - num_eth = depca_dev_index(dev->name); - if (loading_module) return dev; - - while (1) { - if (((dev->base_addr == DEPCA_NDA) || (dev->base_addr==0)) && !adev) { - adev=dev; - } else if ((dev->priv == NULL) && (dev->base_addr==iobase)) { - fixed = 1; - } else { - if (dev->next == NULL) { - new_dev = 1; - } else if (strncmp(dev->next->name, "eth", 3) != 0) { - new_dev = 1; - } - } - if ((dev->next == NULL) || new_dev || fixed) break; - dev = dev->next; - num_eth++; - } - if (adev && !fixed) { - dev = adev; num_eth = depca_dev_index(dev->name); - new_dev = 0; - } + if (loading_module) + return dev; - if (((dev->next == NULL) && - ((dev->base_addr != DEPCA_NDA) && (dev->base_addr != 0)) && !fixed) || - new_dev) { - num_eth++; /* New device */ - dev = insert_device(dev, iobase, depca_probe); - } - - return dev; + while (1) { + if (((dev->base_addr == DEPCA_NDA) || (dev->base_addr == 0)) && !adev) { + adev = dev; + } else if ((dev->priv == NULL) && (dev->base_addr == iobase)) { + fixed = 1; + } else { + if (dev->next == NULL) { + new_dev = 1; + } else if (strncmp(dev->next->name, "eth", 3) != 0) { + new_dev = 1; + } + } + if ((dev->next == NULL) || new_dev || fixed) + break; + dev = dev->next; + num_eth++; + } + if (adev && !fixed) { + dev = adev; + num_eth = depca_dev_index(dev->name); + new_dev = 0; + } + + if (((dev->next == NULL) && ((dev->base_addr != DEPCA_NDA) && (dev->base_addr != 0)) && !fixed) || new_dev) { + num_eth++; /* New device */ + dev = insert_device(dev, iobase, depca_probe); + } + + return dev; } /* ** If at end of eth device list and can't use current entry, malloc ** one up. If memory could not be allocated, print an error message. */ -static struct net_device * __init -insert_device(struct net_device *dev, u_long iobase, int (*init)(struct net_device *)) +static struct net_device *__init insert_device(struct net_device *dev, u_long iobase, int (*init) (struct net_device *)) { - struct net_device *new; + struct net_device *new; - new = (struct net_device *)kmalloc(sizeof(struct net_device), GFP_KERNEL); - if (new == NULL) { - printk("eth%d: Device not initialised, insufficient memory\n",num_eth); - return NULL; - } else { - new->next = dev->next; - dev->next = new; - dev = dev->next; /* point to the new device */ - if (num_eth > 9999) { - sprintf(dev->name,"eth????");/* New device name */ + new = (struct net_device *) kmalloc(sizeof(struct net_device), GFP_KERNEL); + if (new == NULL) { + printk("eth%d: Device not initialised, insufficient memory\n", num_eth); + return NULL; } else { - sprintf(dev->name,"eth%d", num_eth);/* New device name */ + new->next = dev->next; + dev->next = new; + dev = dev->next; /* point to the new device */ + if (num_eth > 9999) { + sprintf(dev->name, "eth????"); /* New device name */ + } else { + sprintf(dev->name, "eth%d", num_eth); /* New device name */ + } + dev->base_addr = iobase; /* assign the io address */ + dev->init = init; /* initialisation routine */ } - dev->base_addr = iobase; /* assign the io address */ - dev->init = init; /* initialisation routine */ - } - return dev; + return dev; } -static int __init -depca_dev_index(char *s) +static int __init depca_dev_index(char *s) { - int i=0, j=0; + int i = 0, j = 0; - for (;*s; s++) { - if (isdigit(*s)) { - j=1; - i = (i * 10) + (*s - '0'); - } else if (j) break; - } + for (; *s; s++) { + if (isdigit(*s)) { + j = 1; + i = (i * 10) + (*s - '0'); + } else if (j) + break; + } - return i; + return i; } /* @@ -1586,50 +1568,51 @@ ** and Boot (readb) ROM. This will also give us a clue to the network RAM ** base address. */ -static void __init -DepcaSignature(char *name, u_long paddr) +static void __init DepcaSignature(char *name, u_long paddr) { - u_int i,j,k; - const char *signatures[] = DEPCA_SIGNATURE; - void *ptr; - char tmpstr[16]; - - /* Copy the first 16 bytes of ROM */ - ptr = ioremap(paddr + 0xc000, 16); - if (ptr == NULL) { - printk(KERN_ERR "depca: I/O remap failed at %lx\n", paddr+0xc000); - adapter = unknown; - return; - } - for (i=0;i<16;i++) { - tmpstr[i] = readb(ptr + i); - } - iounmap(ptr); - - /* Check if PROM contains a valid string */ - for (i=0;*signatures[i]!='\0';i++) { - for (j=0,k=0;j<16 && kbase_addr; - int i, k, tmp, status = 0; - u_short j, x, chksum; - - x = (((adapter == de100) || (adapter == de101)) ? 1 : 0); - - for (i=0,k=0,j=0;j<3;j++) { - k <<= 1 ; - if (k > 0xffff) k-=0xffff; - - k += (u_char) (tmp = inb(DEPCA_PROM + x)); - dev->dev_addr[i++] = (u_char) tmp; - k += (u_short) ((tmp = inb(DEPCA_PROM + x)) << 8); - dev->dev_addr[i++] = (u_char) tmp; + u_long ioaddr = dev->base_addr; + int i, k, tmp, status = 0; + u_short j, x, chksum; - if (k > 0xffff) k-=0xffff; - } - if (k == 0xffff) k=0; + x = (((adapter == de100) || (adapter == de101)) ? 1 : 0); - chksum = (u_char) inb(DEPCA_PROM + x); - chksum |= (u_short) (inb(DEPCA_PROM + x) << 8); - if (k != chksum) status = -1; + for (i = 0, k = 0, j = 0; j < 3; j++) { + k <<= 1; + if (k > 0xffff) + k -= 0xffff; + + k += (u_char) (tmp = inb(DEPCA_PROM + x)); + dev->dev_addr[i++] = (u_char) tmp; + k += (u_short) ((tmp = inb(DEPCA_PROM + x)) << 8); + dev->dev_addr[i++] = (u_char) tmp; + + if (k > 0xffff) + k -= 0xffff; + } + if (k == 0xffff) + k = 0; + + chksum = (u_char) inb(DEPCA_PROM + x); + chksum |= (u_short) (inb(DEPCA_PROM + x) << 8); + if (k != chksum) + status = -1; - return status; + return status; } /* @@ -1734,165 +1720,161 @@ */ static int load_packet(struct net_device *dev, struct sk_buff *skb) { - struct depca_private *lp = (struct depca_private *)dev->priv; - int i, entry, end, len, status = 0; + struct depca_private *lp = (struct depca_private *) dev->priv; + int i, entry, end, len, status = 0; + + entry = lp->tx_new; /* Ring around buffer number. */ + end = (entry + (skb->len - 1) / TX_BUFF_SZ) & lp->txRingMask; + if (!(readl(&lp->tx_ring[end].base) & T_OWN)) { /* Enough room? */ + /* + ** Caution: the write order is important here... don't set up the + ** ownership rights until all the other information is in place. + */ + if (end < entry) { /* wrapped buffer */ + len = (lp->txRingMask - entry + 1) * TX_BUFF_SZ; + memcpy_toio(lp->tx_buff[entry], skb->data, len); + memcpy_toio(lp->tx_buff[0], skb->data + len, skb->len - len); + } else { /* linear buffer */ + memcpy_toio(lp->tx_buff[entry], skb->data, skb->len); + } - entry = lp->tx_new; /* Ring around buffer number. */ - end = (entry + (skb->len - 1) / TX_BUFF_SZ) & lp->txRingMask; - if (!(readl(&lp->tx_ring[end].base) & T_OWN)) {/* Enough room? */ - /* - ** Caution: the write order is important here... don't set up the - ** ownership rights until all the other information is in place. - */ - if (end < entry) { /* wrapped buffer */ - len = (lp->txRingMask - entry + 1) * TX_BUFF_SZ; - memcpy_toio(lp->tx_buff[entry], skb->data, len); - memcpy_toio(lp->tx_buff[0], skb->data + len, skb->len - len); - } else { /* linear buffer */ - memcpy_toio(lp->tx_buff[entry], skb->data, skb->len); - } - - /* set up the buffer descriptors */ - len = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len; - for (i = entry; i != end; i = (++i) & lp->txRingMask) { - /* clean out flags */ - writel(readl(&lp->tx_ring[i].base) & ~T_FLAGS, &lp->tx_ring[i].base); - writew(0x0000, &lp->tx_ring[i].misc); /* clears other error flags */ - writew(-TX_BUFF_SZ, &lp->tx_ring[i].length);/* packet length in buffer */ - len -= TX_BUFF_SZ; - } - /* clean out flags */ - writel(readl(&lp->tx_ring[end].base) & ~T_FLAGS, &lp->tx_ring[end].base); - writew(0x0000, &lp->tx_ring[end].misc); /* clears other error flags */ - writew(-len, &lp->tx_ring[end].length); /* packet length in last buff */ - - /* start of packet */ - writel(readl(&lp->tx_ring[entry].base) | T_STP, &lp->tx_ring[entry].base); - /* end of packet */ - writel(readl(&lp->tx_ring[end].base) | T_ENP, &lp->tx_ring[end].base); - - for (i=end; i!=entry; --i) { - /* ownership of packet */ - writel(readl(&lp->tx_ring[i].base) | T_OWN, &lp->tx_ring[i].base); - if (i == 0) i=lp->txRingMask+1; - } - writel(readl(&lp->tx_ring[entry].base) | T_OWN, &lp->tx_ring[entry].base); - - lp->tx_new = (++end) & lp->txRingMask; /* update current pointers */ - } else { - status = -1; - } + /* set up the buffer descriptors */ + len = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len; + for (i = entry; i != end; i = (++i) & lp->txRingMask) { + /* clean out flags */ + writel(readl(&lp->tx_ring[i].base) & ~T_FLAGS, &lp->tx_ring[i].base); + writew(0x0000, &lp->tx_ring[i].misc); /* clears other error flags */ + writew(-TX_BUFF_SZ, &lp->tx_ring[i].length); /* packet length in buffer */ + len -= TX_BUFF_SZ; + } + /* clean out flags */ + writel(readl(&lp->tx_ring[end].base) & ~T_FLAGS, &lp->tx_ring[end].base); + writew(0x0000, &lp->tx_ring[end].misc); /* clears other error flags */ + writew(-len, &lp->tx_ring[end].length); /* packet length in last buff */ + + /* start of packet */ + writel(readl(&lp->tx_ring[entry].base) | T_STP, &lp->tx_ring[entry].base); + /* end of packet */ + writel(readl(&lp->tx_ring[end].base) | T_ENP, &lp->tx_ring[end].base); + + for (i = end; i != entry; --i) { + /* ownership of packet */ + writel(readl(&lp->tx_ring[i].base) | T_OWN, &lp->tx_ring[i].base); + if (i == 0) + i = lp->txRingMask + 1; + } + writel(readl(&lp->tx_ring[entry].base) | T_OWN, &lp->tx_ring[entry].base); - return status; + lp->tx_new = (++end) & lp->txRingMask; /* update current pointers */ + } else { + status = -1; + } + + return status; } /* ** Look for a particular board name in the EISA configuration space */ -static int __init -EISA_signature(char *name, s32 eisa_id) +static int __init EISA_signature(char *name, s32 eisa_id) { - u_int i; - const char *signatures[] = DEPCA_SIGNATURE; - char ManCode[DEPCA_STRLEN]; - union { - s32 ID; - char Id[4]; - } Eisa; - int status = 0; - - *name = '\0'; - Eisa.ID = inl(eisa_id); - - ManCode[0]=(((Eisa.Id[0]>>2)&0x1f)+0x40); - ManCode[1]=(((Eisa.Id[1]&0xe0)>>5)+((Eisa.Id[0]&0x03)<<3)+0x40); - ManCode[2]=(((Eisa.Id[2]>>4)&0x0f)+0x30); - ManCode[3]=(( Eisa.Id[2]&0x0f)+0x30); - ManCode[4]=(((Eisa.Id[3]>>4)&0x0f)+0x30); - ManCode[5]='\0'; - - for (i=0;(*signatures[i] != '\0') && (*name == '\0');i++) { - if (strstr(ManCode, signatures[i]) != NULL) { - strcpy(name,ManCode); - status = 1; - } - } + u_int i; + const char *signatures[] = DEPCA_SIGNATURE; + char ManCode[DEPCA_STRLEN]; + union { + s32 ID; + char Id[4]; + } Eisa; + int status = 0; + + *name = '\0'; + Eisa.ID = inl(eisa_id); + + ManCode[0] = (((Eisa.Id[0] >> 2) & 0x1f) + 0x40); + ManCode[1] = (((Eisa.Id[1] & 0xe0) >> 5) + ((Eisa.Id[0] & 0x03) << 3) + 0x40); + ManCode[2] = (((Eisa.Id[2] >> 4) & 0x0f) + 0x30); + ManCode[3] = ((Eisa.Id[2] & 0x0f) + 0x30); + ManCode[4] = (((Eisa.Id[3] >> 4) & 0x0f) + 0x30); + ManCode[5] = '\0'; + + for (i = 0; (*signatures[i] != '\0') && (*name == '\0'); i++) { + if (strstr(ManCode, signatures[i]) != NULL) { + strcpy(name, ManCode); + status = 1; + } + } - return status; + return status; } static void depca_dbg_open(struct net_device *dev) { - struct depca_private *lp = (struct depca_private *)dev->priv; - u_long ioaddr = dev->base_addr; - struct depca_init *p = &lp->init_block; - int i; - - if (depca_debug > 1){ - /* Do not copy the shadow init block into shared memory */ - /* Debugging should not affect normal operation! */ - /* The shadow init block will get copied across during InitRestartDepca */ - printk("%s: depca open with irq %d\n",dev->name,dev->irq); - printk("Descriptor head addresses (CPU):\n"); - printk(" 0x%lx 0x%lx\n",(u_long)lp->rx_ring, (u_long)lp->tx_ring); - printk("Descriptor addresses (CPU):\nRX: "); - for (i=0;irxRingMask;i++){ - if (i < 3) { - printk("0x%8.8lx ", (long) &lp->rx_ring[i].base); - } - } - printk("...0x%8.8lx\n", (long) &lp->rx_ring[i].base); - printk("TX: "); - for (i=0;itxRingMask;i++){ - if (i < 3) { - printk("0x%8.8lx ", (long) &lp->tx_ring[i].base); - } - } - printk("...0x%8.8lx\n", (long) &lp->tx_ring[i].base); - printk("\nDescriptor buffers (Device):\nRX: "); - for (i=0;irxRingMask;i++){ - if (i < 3) { - printk("0x%8.8x ", readl(&lp->rx_ring[i].base)); - } - } - printk("...0x%8.8x\n", readl(&lp->rx_ring[i].base)); - printk("TX: "); - for (i=0;itxRingMask;i++){ - if (i < 3) { - printk("0x%8.8x ", readl(&lp->tx_ring[i].base)); - } - } - printk("...0x%8.8x\n", readl(&lp->tx_ring[i].base)); - printk("Initialisation block at 0x%8.8lx(Phys)\n",virt_to_phys(lp->sh_mem)); - printk(" mode: 0x%4.4x\n",p->mode); - printk(" physical address: "); - for (i=0;iphys_addr[i]); - } - printk("%2.2x\n", p->phys_addr[i]); - printk(" multicast hash table: "); - for (i=0;i<(HASH_TABLE_LEN >> 3)-1;i++){ - printk("%2.2x:", p->mcast_table[i]); - } - printk("%2.2x\n", p->mcast_table[i]); - printk(" rx_ring at: 0x%8.8x\n", p->rx_ring); - printk(" tx_ring at: 0x%8.8x\n", p->tx_ring); - printk("buffers (Phys): 0x%8.8lx\n",virt_to_phys(lp->sh_mem)+lp->buffs_offset); - printk("Ring size:\nRX: %d Log2(rxRingMask): 0x%8.8x\n", - (int)lp->rxRingMask + 1, - lp->rx_rlen); - printk("TX: %d Log2(txRingMask): 0x%8.8x\n", - (int)lp->txRingMask + 1, - lp->tx_rlen); - outw(CSR2,DEPCA_ADDR); - printk("CSR2&1: 0x%4.4x",inw(DEPCA_DATA)); - outw(CSR1,DEPCA_ADDR); - printk("%4.4x\n",inw(DEPCA_DATA)); - outw(CSR3,DEPCA_ADDR); - printk("CSR3: 0x%4.4x\n",inw(DEPCA_DATA)); - } + struct depca_private *lp = (struct depca_private *) dev->priv; + u_long ioaddr = dev->base_addr; + struct depca_init *p = &lp->init_block; + int i; - return; + if (depca_debug > 1) { + /* Do not copy the shadow init block into shared memory */ + /* Debugging should not affect normal operation! */ + /* The shadow init block will get copied across during InitRestartDepca */ + printk("%s: depca open with irq %d\n", dev->name, dev->irq); + printk("Descriptor head addresses (CPU):\n"); + printk(" 0x%lx 0x%lx\n", (u_long) lp->rx_ring, (u_long) lp->tx_ring); + printk("Descriptor addresses (CPU):\nRX: "); + for (i = 0; i < lp->rxRingMask; i++) { + if (i < 3) { + printk("0x%8.8lx ", (long) &lp->rx_ring[i].base); + } + } + printk("...0x%8.8lx\n", (long) &lp->rx_ring[i].base); + printk("TX: "); + for (i = 0; i < lp->txRingMask; i++) { + if (i < 3) { + printk("0x%8.8lx ", (long) &lp->tx_ring[i].base); + } + } + printk("...0x%8.8lx\n", (long) &lp->tx_ring[i].base); + printk("\nDescriptor buffers (Device):\nRX: "); + for (i = 0; i < lp->rxRingMask; i++) { + if (i < 3) { + printk("0x%8.8x ", readl(&lp->rx_ring[i].base)); + } + } + printk("...0x%8.8x\n", readl(&lp->rx_ring[i].base)); + printk("TX: "); + for (i = 0; i < lp->txRingMask; i++) { + if (i < 3) { + printk("0x%8.8x ", readl(&lp->tx_ring[i].base)); + } + } + printk("...0x%8.8x\n", readl(&lp->tx_ring[i].base)); + printk("Initialisation block at 0x%8.8lx(Phys)\n", virt_to_phys(lp->sh_mem)); + printk(" mode: 0x%4.4x\n", p->mode); + printk(" physical address: "); + for (i = 0; i < ETH_ALEN - 1; i++) { + printk("%2.2x:", p->phys_addr[i]); + } + printk("%2.2x\n", p->phys_addr[i]); + printk(" multicast hash table: "); + for (i = 0; i < (HASH_TABLE_LEN >> 3) - 1; i++) { + printk("%2.2x:", p->mcast_table[i]); + } + printk("%2.2x\n", p->mcast_table[i]); + printk(" rx_ring at: 0x%8.8x\n", p->rx_ring); + printk(" tx_ring at: 0x%8.8x\n", p->tx_ring); + printk("buffers (Phys): 0x%8.8lx\n", virt_to_phys(lp->sh_mem) + lp->buffs_offset); + printk("Ring size:\nRX: %d Log2(rxRingMask): 0x%8.8x\n", (int) lp->rxRingMask + 1, lp->rx_rlen); + printk("TX: %d Log2(txRingMask): 0x%8.8x\n", (int) lp->txRingMask + 1, lp->tx_rlen); + outw(CSR2, DEPCA_ADDR); + printk("CSR2&1: 0x%4.4x", inw(DEPCA_DATA)); + outw(CSR1, DEPCA_ADDR); + printk("%4.4x\n", inw(DEPCA_DATA)); + outw(CSR3, DEPCA_ADDR); + printk("CSR3: 0x%4.4x\n", inw(DEPCA_DATA)); + } + + return; } /* @@ -1902,177 +1884,182 @@ */ static int depca_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { - struct depca_private *lp = (struct depca_private *)dev->priv; - struct depca_ioctl *ioc = (struct depca_ioctl *) &rq->ifr_data; - int i, status = 0; - u_long ioaddr = dev->base_addr; - union { - u8 addr[(HASH_TABLE_LEN * ETH_ALEN)]; - u16 sval[(HASH_TABLE_LEN * ETH_ALEN) >> 1]; - u32 lval[(HASH_TABLE_LEN * ETH_ALEN) >> 2]; - } tmp; - - switch(ioc->cmd) { - case DEPCA_GET_HWADDR: /* Get the hardware address */ - for (i=0; idev_addr[i]; - } - ioc->len = ETH_ALEN; - if (copy_to_user(ioc->data, tmp.addr, ioc->len)) - return -EFAULT; - break; - - case DEPCA_SET_HWADDR: /* Set the hardware address */ - if (!capable(CAP_NET_ADMIN)) return -EPERM; - if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN)) - return -EFAULT; - for (i=0; idev_addr[i] = tmp.addr[i]; - } - netif_stop_queue(dev); - while(lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ - - STOP_DEPCA; /* Temporarily stop the depca. */ - depca_init_ring(dev); /* Initialize the descriptor rings */ - LoadCSRs(dev); /* Reload CSR3 */ - InitRestartDepca(dev); /* Resume normal operation. */ - netif_start_queue(dev); /* Unlock the TX ring */ - break; - - case DEPCA_SET_PROM: /* Set Promiscuous Mode */ - if (!capable(CAP_NET_ADMIN)) return -EPERM; - netif_stop_queue(dev); - while(lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ - - STOP_DEPCA; /* Temporarily stop the depca. */ - depca_init_ring(dev); /* Initialize the descriptor rings */ - lp->init_block.mode |= PROM; /* Set promiscuous mode */ - - LoadCSRs(dev); /* Reload CSR3 */ - InitRestartDepca(dev); /* Resume normal operation. */ - netif_start_queue(dev); /* Unlock the TX ring */ - break; - - case DEPCA_CLR_PROM: /* Clear Promiscuous Mode */ - if (!capable(CAP_NET_ADMIN)) return -EPERM; - netif_stop_queue(dev); - while(lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ - - STOP_DEPCA; /* Temporarily stop the depca. */ - depca_init_ring(dev); /* Initialize the descriptor rings */ - lp->init_block.mode &= ~PROM; /* Clear promiscuous mode */ - - LoadCSRs(dev); /* Reload CSR3 */ - InitRestartDepca(dev); /* Resume normal operation. */ - netif_start_queue(dev); /* Unlock the TX ring */ - break; - - case DEPCA_SAY_BOO: /* Say "Boo!" to the kernel log file */ - printk("%s: Boo!\n", dev->name); - break; - - case DEPCA_GET_MCA: /* Get the multicast address table */ - ioc->len = (HASH_TABLE_LEN >> 3); - if (copy_to_user(ioc->data, lp->init_block.mcast_table, ioc->len)) - return -EFAULT; - break; - - case DEPCA_SET_MCA: /* Set a multicast address */ - if (!capable(CAP_NET_ADMIN)) return -EPERM; - if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len)) - return -EFAULT; - set_multicast_list(dev); - break; - - case DEPCA_CLR_MCA: /* Clear all multicast addresses */ - if (!capable(CAP_NET_ADMIN)) return -EPERM; - set_multicast_list(dev); - break; - - case DEPCA_MCA_EN: /* Enable pass all multicast addressing */ - if (!capable(CAP_NET_ADMIN)) return -EPERM; - set_multicast_list(dev); - break; - - case DEPCA_GET_STATS: /* Get the driver statistics */ - cli(); - ioc->len = sizeof(lp->pktStats); - if (copy_to_user(ioc->data, &lp->pktStats, ioc->len)) - status = -EFAULT; - sti(); - break; - - case DEPCA_CLR_STATS: /* Zero out the driver statistics */ - if (!capable(CAP_NET_ADMIN)) return -EPERM; - cli(); - memset(&lp->pktStats, 0, sizeof(lp->pktStats)); - sti(); - break; - - case DEPCA_GET_REG: /* Get the DEPCA Registers */ - i=0; - tmp.sval[i++] = inw(DEPCA_NICSR); - outw(CSR0, DEPCA_ADDR); /* status register */ - tmp.sval[i++] = inw(DEPCA_DATA); - memcpy(&tmp.sval[i], &lp->init_block, sizeof(struct depca_init)); - ioc->len = i+sizeof(struct depca_init); - if (copy_to_user(ioc->data, tmp.addr, ioc->len)) - return -EFAULT; - break; - - default: - return -EOPNOTSUPP; - } + struct depca_private *lp = (struct depca_private *) dev->priv; + struct depca_ioctl *ioc = (struct depca_ioctl *) &rq->ifr_data; + int i, status = 0; + u_long ioaddr = dev->base_addr; + union { + u8 addr[(HASH_TABLE_LEN * ETH_ALEN)]; + u16 sval[(HASH_TABLE_LEN * ETH_ALEN) >> 1]; + u32 lval[(HASH_TABLE_LEN * ETH_ALEN) >> 2]; + } tmp; + + switch (ioc->cmd) { + case DEPCA_GET_HWADDR: /* Get the hardware address */ + for (i = 0; i < ETH_ALEN; i++) { + tmp.addr[i] = dev->dev_addr[i]; + } + ioc->len = ETH_ALEN; + if (copy_to_user(ioc->data, tmp.addr, ioc->len)) + return -EFAULT; + break; - return status; + case DEPCA_SET_HWADDR: /* Set the hardware address */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN)) + return -EFAULT; + for (i = 0; i < ETH_ALEN; i++) { + dev->dev_addr[i] = tmp.addr[i]; + } + netif_stop_queue(dev); + while (lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ + + STOP_DEPCA; /* Temporarily stop the depca. */ + depca_init_ring(dev); /* Initialize the descriptor rings */ + LoadCSRs(dev); /* Reload CSR3 */ + InitRestartDepca(dev); /* Resume normal operation. */ + netif_start_queue(dev); /* Unlock the TX ring */ + break; + + case DEPCA_SET_PROM: /* Set Promiscuous Mode */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + netif_stop_queue(dev); + while (lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ + + STOP_DEPCA; /* Temporarily stop the depca. */ + depca_init_ring(dev); /* Initialize the descriptor rings */ + lp->init_block.mode |= PROM; /* Set promiscuous mode */ + + LoadCSRs(dev); /* Reload CSR3 */ + InitRestartDepca(dev); /* Resume normal operation. */ + netif_start_queue(dev); /* Unlock the TX ring */ + break; + + case DEPCA_CLR_PROM: /* Clear Promiscuous Mode */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + netif_stop_queue(dev); + while (lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ + + STOP_DEPCA; /* Temporarily stop the depca. */ + depca_init_ring(dev); /* Initialize the descriptor rings */ + lp->init_block.mode &= ~PROM; /* Clear promiscuous mode */ + + LoadCSRs(dev); /* Reload CSR3 */ + InitRestartDepca(dev); /* Resume normal operation. */ + netif_start_queue(dev); /* Unlock the TX ring */ + break; + + case DEPCA_SAY_BOO: /* Say "Boo!" to the kernel log file */ + printk("%s: Boo!\n", dev->name); + break; + + case DEPCA_GET_MCA: /* Get the multicast address table */ + ioc->len = (HASH_TABLE_LEN >> 3); + if (copy_to_user(ioc->data, lp->init_block.mcast_table, ioc->len)) + return -EFAULT; + break; + + case DEPCA_SET_MCA: /* Set a multicast address */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len)) + return -EFAULT; + set_multicast_list(dev); + break; + + case DEPCA_CLR_MCA: /* Clear all multicast addresses */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + set_multicast_list(dev); + break; + + case DEPCA_MCA_EN: /* Enable pass all multicast addressing */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + set_multicast_list(dev); + break; + + case DEPCA_GET_STATS: /* Get the driver statistics */ + cli(); + ioc->len = sizeof(lp->pktStats); + if (copy_to_user(ioc->data, &lp->pktStats, ioc->len)) + status = -EFAULT; + sti(); + break; + + case DEPCA_CLR_STATS: /* Zero out the driver statistics */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + cli(); + memset(&lp->pktStats, 0, sizeof(lp->pktStats)); + sti(); + break; + + case DEPCA_GET_REG: /* Get the DEPCA Registers */ + i = 0; + tmp.sval[i++] = inw(DEPCA_NICSR); + outw(CSR0, DEPCA_ADDR); /* status register */ + tmp.sval[i++] = inw(DEPCA_DATA); + memcpy(&tmp.sval[i], &lp->init_block, sizeof(struct depca_init)); + ioc->len = i + sizeof(struct depca_init); + if (copy_to_user(ioc->data, tmp.addr, ioc->len)) + return -EFAULT; + break; + + default: + return -EOPNOTSUPP; + } + + return status; } #ifdef MODULE static struct net_device thisDepca; -static int irq=7; /* EDIT THESE LINE FOR YOUR CONFIGURATION */ -static int io=0x200; /* Or use the irq= io= options to insmod */ +static int irq = 7; /* EDIT THESE LINE FOR YOUR CONFIGURATION */ +static int io = 0x200; /* Or use the irq= io= options to insmod */ MODULE_PARM(irq, "i"); MODULE_PARM(io, "i"); MODULE_PARM_DESC(irq, "DEPCA IRQ number"); MODULE_PARM_DESC(io, "DEPCA I/O base address"); -/* See depca_probe() for autoprobe messages when a module */ -int -init_module(void) +/* See depca_probe() for autoprobe messages when a module */ +int init_module(void) { - thisDepca.irq=irq; - thisDepca.base_addr=io; - thisDepca.init = depca_probe; + thisDepca.irq = irq; + thisDepca.base_addr = io; + thisDepca.init = depca_probe; - if (register_netdev(&thisDepca) != 0) - return -EIO; + if (register_netdev(&thisDepca) != 0) + return -EIO; - return 0; + return 0; } -void -cleanup_module(void) +void cleanup_module(void) { - struct depca_private *lp = thisDepca.priv; + struct depca_private *lp = thisDepca.priv; - unregister_netdev(&thisDepca); - if (lp) { - iounmap(lp->sh_mem); -#ifdef CONFIG_MCA - if(lp->mca_slot != -1) - mca_mark_as_unused(lp->mca_slot); -#endif - kfree(lp); - thisDepca.priv = NULL; - } - thisDepca.irq=0; + unregister_netdev(&thisDepca); + if (lp) { + iounmap(lp->sh_mem); +#ifdef CONFIG_MCA + if (lp->mca_slot != -1) + mca_mark_as_unused(lp->mca_slot); +#endif + kfree(lp); + thisDepca.priv = NULL; + } + thisDepca.irq = 0; - release_region(thisDepca.base_addr, DEPCA_TOTAL_SIZE); + release_region(thisDepca.base_addr, DEPCA_TOTAL_SIZE); } -#endif /* MODULE */ +#endif /* MODULE */ MODULE_LICENSE("GPL"); - + /* * Local variables: * compile-command: "gcc -D__KERNEL__ -I/linux/include -Wall -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce -malign-loops=2 -malign-jumps=2 -malign-functions=2 -O2 -m486 -c depca.c" diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/net/e2100.c linux.19rc3-ac4/drivers/net/e2100.c --- linux.19rc3/drivers/net/e2100.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/net/e2100.c 2002-07-29 13:58:42.000000000 +0100 @@ -72,7 +72,7 @@ #define E21_SAPROM 0x10 /* Offset to station address data. */ #define E21_IO_EXTENT 0x20 -extern inline void mem_on(short port, volatile char *mem_base, +static inline void mem_on(short port, volatile char *mem_base, unsigned char start_page ) { /* This is a little weird: set the shared memory window by doing a @@ -82,7 +82,7 @@ outb(E21_MEM_ON, port + E21_MEM_ENABLE + E21_MEM_ON); } -extern inline void mem_off(short port) +static inline void mem_off(short port) { inb(port + E21_MEM_ENABLE); outb(0x00, port + E21_MEM_ENABLE); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/net/eepro100.c linux.19rc3-ac4/drivers/net/eepro100.c --- linux.19rc3/drivers/net/eepro100.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/net/eepro100.c 2002-07-29 13:58:42.000000000 +0100 @@ -524,8 +524,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 int eepro100_suspend (struct pci_dev *pdev, u32 state); -static int 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); @@ -1144,7 +1142,7 @@ /* Clear sticky bit. */ mdio_read(ioaddr, phy_num, 1); /* If link beat has returned... */ - if (mdio_read(ioaddr, phy_num, 1) & 0x0004) + if (mdio_read(ioaddr, phy_num, MII_BMSR) & BMSR_LSTATUS) netif_carrier_on(dev); else netif_carrier_off(dev); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/net/ewrk3.c linux.19rc3-ac4/drivers/net/ewrk3.c --- linux.19rc3/drivers/net/ewrk3.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/net/ewrk3.c 2002-07-29 13:58:42.000000000 +0100 @@ -133,6 +133,7 @@ 0.42 22-Apr-96 Fix alloc_device() bug 0.43 16-Aug-96 Update alloc_device() to conform to de4x5.c 0.44 08-Nov-01 use library crc32 functions + 0.45 19-Jul-02 fix unaligned access on alpha ========================================================================= */ @@ -1004,12 +1005,13 @@ } p = skb->data; /* Look at the dest addr */ if (p[0] & 0x01) { /* Multicast/Broadcast */ - if ((*(s32 *) & p[0] == -1) && (*(s16 *) & p[4] == -1)) { + if ((*(s16 *) & p[0] == -1) && (*(s16 *) & p[2] == -1) && (*(s16 *) & p[4] == -1)) { lp->pktStats.broadcast++; } else { lp->pktStats.multicast++; } - } else if ((*(s32 *) & p[0] == *(s32 *) & dev->dev_addr[0]) && + } else if ((*(s16 *) & p[0] == *(s16 *) & dev->dev_addr[0]) && + (*(s16 *) & p[2] == *(s16 *) & dev->dev_addr[2]) && (*(s16 *) & p[4] == *(s16 *) & dev->dev_addr[4])) { lp->pktStats.unicast++; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/net/hamachi.c linux.19rc3-ac4/drivers/net/hamachi.c --- linux.19rc3/drivers/net/hamachi.c 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/net/hamachi.c 2002-07-29 13:58:42.000000000 +0100 @@ -210,8 +210,10 @@ /* Condensed bus+endian portability operations. */ #if ADDRLEN == 64 #define cpu_to_leXX(addr) cpu_to_le64(addr) +#define desc_to_virt(addr) bus_to_virt(le64_to_cpu(addr)) #else #define cpu_to_leXX(addr) cpu_to_le32(addr) +#define desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr)) #endif @@ -1544,7 +1546,8 @@ break; pci_dma_sync_single(hmp->pci_dev, desc->addr, hmp->rx_buf_sz, PCI_DMA_FROMDEVICE); - buf_addr = (u8 *)hmp->rx_ring + entry*sizeof(*desc); + //buf_addr = (u8 *)hmp->rx_ring + entry*sizeof(*desc); + buf_addr = desc_to_virt(desc->addr); frame_status = le32_to_cpu(get_unaligned((s32*)&(buf_addr[data_size - 12]))); if (hamachi_debug > 4) printk(KERN_DEBUG " hamachi_rx() status was %8.8x.\n", diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/net/hp100.c linux.19rc3-ac4/drivers/net/hp100.c --- linux.19rc3/drivers/net/hp100.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/net/hp100.c 2002-07-29 13:58:42.000000000 +0100 @@ -237,6 +237,9 @@ /* 10/100 ISA card with Cascade chip */ {0x5019F022, "HP J2573", HP100_BUS_ISA}, + /* 10/100 EISA card with AT&T chip */ + {0x9019f022, "HP J2577", HP100_BUS_EISA }, + /* 10/100 PCI card - old J2585A */ {0x1030103c, "HP J2585A", HP100_BUS_PCI}, @@ -1880,7 +1883,7 @@ #endif /* Now we allocate the skb and transfer the data into it. */ - skb = dev_alloc_skb(pkt_len); + skb = dev_alloc_skb(pkt_len+2); if (skb == NULL) { /* Not enough memory->drop packet */ #ifdef HP100_DEBUG printk("hp100: %s: rx: couldn't allocate a sk_buff of size %d\n", @@ -1891,10 +1894,12 @@ u_char *ptr; + skb_reserve(skb,2); skb->dev = dev; /* ptr to start of the sk_buff data area */ - ptr = (u_char *) skb_put(skb, pkt_len); + skb_put(skb, pkt_len); + ptr = skb->data; /* Now transfer the data from the card into that area */ if (lp->mode == 2) { diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/net/hp-plus.c linux.19rc3-ac4/drivers/net/hp-plus.c --- linux.19rc3/drivers/net/hp-plus.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/net/hp-plus.c 2002-07-29 17:11:46.000000000 +0100 @@ -351,7 +351,7 @@ outw(option_reg & ~(MemDisable + BootROMEnb), ioaddr + HPP_OPTION); isa_memcpy_fromio(hdr, dev->mem_start, sizeof(struct e8390_pkt_hdr)); outw(option_reg, ioaddr + HPP_OPTION); - hdr->count = (hdr->count + 3) & ~3; /* Round up allocation. */ + hdr->count = (le16_to_cpu(hdr->count) + 3) & ~3; /* Round up allocation. */ } static void diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/net/irda/irtty.c linux.19rc3-ac4/drivers/net/irda/irtty.c --- linux.19rc3/drivers/net/irda/irtty.c 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/net/irda/irtty.c 2002-07-29 13:58:42.000000000 +0100 @@ -760,14 +760,11 @@ struct irtty_cb *self; struct tty_struct *tty; mm_segment_t fs; - int arg = 0; + int arg = TIOCM_MODEM_BITS; self = (struct irtty_cb *) dev->priv; tty = self->tty; -#ifdef TIOCM_OUT2 /* Not defined for ARM */ - arg = TIOCM_OUT2; -#endif if (rts) arg |= TIOCM_RTS; if (dtr) diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/net/lasi_82596.c linux.19rc3-ac4/drivers/net/lasi_82596.c --- linux.19rc3/drivers/net/lasi_82596.c 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/net/lasi_82596.c 2002-07-29 13:58:42.000000000 +0100 @@ -84,6 +84,7 @@ #include #include #include +#include #include #include @@ -95,8 +96,8 @@ #include #include -static char version[] __initdata = - "82596.c $Revision: 1.20 $\n"; +static char version[] __devinitdata = + "82596.c $Revision: 1.29 $\n"; /* DEBUG flags */ @@ -120,7 +121,7 @@ #define DEB_ANY 0xffff -#define DEB(x,y) if (i596_debug & (x)) y +#define DEB(x,y) if (i596_debug & (x)) { y; } #define CHECK_WBACK(addr,len) \ @@ -144,13 +145,13 @@ */ #ifdef __BIG_ENDIAN -#define WSWAPrfd(x) ((struct i596_rfd *) (((u32)(x)<<16) | ((((u32)(x)))>>16))) -#define WSWAPrbd(x) ((struct i596_rbd *) (((u32)(x)<<16) | ((((u32)(x)))>>16))) -#define WSWAPiscp(x) ((struct i596_iscp *)(((u32)(x)<<16) | ((((u32)(x)))>>16))) -#define WSWAPscb(x) ((struct i596_scb *) (((u32)(x)<<16) | ((((u32)(x)))>>16))) -#define WSWAPcmd(x) ((struct i596_cmd *) (((u32)(x)<<16) | ((((u32)(x)))>>16))) -#define WSWAPtbd(x) ((struct i596_tbd *) (((u32)(x)<<16) | ((((u32)(x)))>>16))) -#define WSWAPchar(x) ((char *) (((u32)(x)<<16) | ((((u32)(x)))>>16))) +#define WSWAPrfd(x) (((u32)(x)<<16) | ((((u32)(x)))>>16)) +#define WSWAPrbd(x) (((u32)(x)<<16) | ((((u32)(x)))>>16)) +#define WSWAPiscp(x) (((u32)(x)<<16) | ((((u32)(x)))>>16)) +#define WSWAPscb(x) (((u32)(x)<<16) | ((((u32)(x)))>>16)) +#define WSWAPcmd(x) (((u32)(x)<<16) | ((((u32)(x)))>>16)) +#define WSWAPtbd(x) (((u32)(x)<<16) | ((((u32)(x)))>>16)) +#define WSWAPchar(x) (((u32)(x)<<16) | ((((u32)(x)))>>16)) #define ISCP_BUSY 0x00010000 #define MACH_IS_APRICOT 0 #else @@ -183,18 +184,19 @@ MODULE_LICENSE("GPL"); MODULE_PARM(i596_debug, "i"); MODULE_PARM_DESC(i596_debug, "lasi_82596 debug mask"); +EXPORT_NO_SYMBOLS; /* Copy frames shorter than rx_copybreak, otherwise pass on up in * a full sized sk_buff. Value of 100 stolen from tulip.c (!alpha). */ static int rx_copybreak = 100; +#define MAX_DRIVERS 4 /* max count of drivers */ + #define PKT_BUF_SZ 1536 #define MAX_MC_CNT 64 -#define I596_TOTAL_SIZE 17 - -#define I596_NULL ((void *)0xffffffff) +#define I596_NULL ((u32)0xffffffff) #define CMD_EOL 0x8000 /* The last command of the list, stop. */ #define CMD_SUSP 0x4000 /* Suspend after doing cmd. */ @@ -229,7 +231,7 @@ struct i596_reg { unsigned short porthi; unsigned short portlo; - unsigned long ca; + u32 ca; }; #define EOF 0x8000 @@ -238,9 +240,9 @@ struct i596_tbd { unsigned short size; unsigned short pad; - struct i596_tbd *next; - char *data; - long cache_pad[5]; /* Total 32 bytes... */ + dma_addr_t next; + dma_addr_t data; + u32 cache_pad[5]; /* Total 32 bytes... */ }; /* The command structure has two 'next' pointers; v_next is the address of @@ -257,17 +259,21 @@ struct i596_cmd *v_next; /* Address from CPUs viewpoint */ unsigned short status; unsigned short command; - struct i596_cmd *b_next; /* Address from i596 viewpoint */ + dma_addr_t b_next; /* Address from i596 viewpoint */ }; struct tx_cmd { struct i596_cmd cmd; - struct i596_tbd *tbd; + dma_addr_t tbd; unsigned short size; unsigned short pad; struct sk_buff *skb; /* So we can free it after tx */ dma_addr_t dma_addr; - long cache_pad[1]; /* Total 32 bytes... */ +#ifdef __LP64__ + u32 cache_pad[6]; /* Total 64 bytes... */ +#else + u32 cache_pad[1]; /* Total 32 bytes... */ +#endif }; struct tdr_cmd { @@ -295,27 +301,34 @@ struct i596_rfd { unsigned short stat; unsigned short cmd; - struct i596_rfd *b_next; /* Address from i596 viewpoint */ - struct i596_rbd *rbd; + dma_addr_t b_next; /* Address from i596 viewpoint */ + dma_addr_t rbd; unsigned short count; unsigned short size; struct i596_rfd *v_next; /* Address from CPUs viewpoint */ struct i596_rfd *v_prev; - long cache_pad[2]; /* Total 32 bytes... */ +#ifndef __LP64__ + u32 cache_pad[2]; /* Total 32 bytes... */ +#endif }; struct i596_rbd { + /* hardware data */ unsigned short count; unsigned short zero1; - struct i596_rbd *b_next; - unsigned char *b_data; /* Address from i596 viewpoint */ + dma_addr_t b_next; + dma_addr_t b_data; /* Address from i596 viewpoint */ unsigned short size; unsigned short zero2; + /* driver data */ struct sk_buff *skb; struct i596_rbd *v_next; - struct i596_rbd *b_addr; /* This rbd addr from i596 view */ + dma_addr_t b_addr; /* This rbd addr from i596 view */ unsigned char *v_data; /* Address from CPUs viewpoint */ /* Total 32 bytes... */ +#ifdef __LP64__ + u32 cache_pad[4]; +#endif }; /* These values as chosen so struct i596_private fits in one page... */ @@ -326,27 +339,27 @@ struct i596_scb { unsigned short status; unsigned short command; - struct i596_cmd *cmd; - struct i596_rfd *rfd; - unsigned long crc_err; - unsigned long align_err; - unsigned long resource_err; - unsigned long over_err; - unsigned long rcvdt_err; - unsigned long short_err; + dma_addr_t cmd; + dma_addr_t rfd; + u32 crc_err; + u32 align_err; + u32 resource_err; + u32 over_err; + u32 rcvdt_err; + u32 short_err; unsigned short t_on; unsigned short t_off; }; struct i596_iscp { - unsigned long stat; - struct i596_scb *scb; + u32 stat; + dma_addr_t scb; }; struct i596_scp { - unsigned long sysbus; - unsigned long pad; - struct i596_iscp *iscp; + u32 sysbus; + u32 pad; + dma_addr_t iscp; }; struct i596_private { @@ -361,14 +374,14 @@ struct i596_rbd rbds[RX_RING_SIZE] __attribute__((aligned(32))); struct tx_cmd tx_cmds[TX_RING_SIZE] __attribute__((aligned(32))); struct i596_tbd tbds[TX_RING_SIZE] __attribute__((aligned(32))); - unsigned long stat; + u32 stat; int last_restart; struct i596_rfd *rfd_head; struct i596_rbd *rbd_head; struct i596_cmd *cmd_tail; struct i596_cmd *cmd_head; int cmd_backlog; - unsigned long last_cmd; + u32 last_cmd; struct net_device_stats stats; int next_tx_cmd; int options; @@ -393,6 +406,8 @@ 0x00, 0x7f /* *multi IA */ }; +static struct pci_dev *fake_pci_dev; /* The fake pci_dev needed for + pci_* functions under ccio. */ static int dma_consistent = 1; /* Zero if pci_alloc_consistent() fails */ static int i596_open(struct net_device *dev); @@ -412,22 +427,28 @@ static inline void CA(struct net_device *dev) { - gsc_writel(0, (void*)(dev->base_addr + PA_CHANNEL_ATTENTION)); + gsc_writel(0, dev->base_addr + PA_CHANNEL_ATTENTION); } -static inline void MPU_PORT(struct net_device *dev, int c, volatile void *x) +static inline void MPU_PORT(struct net_device *dev, int c, dma_addr_t x) { struct i596_private *lp = (struct i596_private *) dev->priv; u32 v = (u32) (c) | (u32) (x); + u16 a, b; - if (lp->options & OPT_SWAP_PORT) - v = ((u32) (v) << 16) | ((u32) (v) >> 16); + if (lp->options & OPT_SWAP_PORT) { + a = v >> 16; + b = v & 0xffff; + } else { + a = v & 0xffff; + b = v >> 16; + } - gsc_writel(v & 0xffff, (void*)(dev->base_addr + PA_CPU_PORT_L_ACCESS)); + gsc_writel(a, dev->base_addr + PA_CPU_PORT_L_ACCESS); udelay(1); - gsc_writel(v >> 16, (void*)(dev->base_addr + PA_CPU_PORT_L_ACCESS)); + gsc_writel(b, dev->base_addr + PA_CPU_PORT_L_ACCESS); } @@ -439,7 +460,7 @@ CHECK_INV(&(lp->iscp), sizeof(struct i596_iscp)); } if (!delcnt) { - printk("%s: %s, iscp.stat %04lx, didn't clear\n", + printk("%s: %s, iscp.stat %04x, didn't clear\n", dev->name, str, lp->iscp.stat); return -1; } @@ -472,28 +493,28 @@ struct i596_rfd *rfd; struct i596_rbd *rbd; - printk("lp and scp at %p, .sysbus = %08lx, .iscp = %p\n", + printk("lp and scp at %p, .sysbus = %08x, .iscp = %08x\n", &lp->scp, lp->scp.sysbus, lp->scp.iscp); - printk("iscp at %p, iscp.stat = %08lx, .scb = %p\n", + printk("iscp at %p, iscp.stat = %08x, .scb = %08x\n", &lp->iscp, lp->iscp.stat, lp->iscp.scb); printk("scb at %p, scb.status = %04x, .command = %04x," - " .cmd = %p, .rfd = %p\n", + " .cmd = %08x, .rfd = %08x\n", &lp->scb, lp->scb.status, lp->scb.command, lp->scb.cmd, lp->scb.rfd); - printk(" errors: crc %lx, align %lx, resource %lx," - " over %lx, rcvdt %lx, short %lx\n", + printk(" errors: crc %x, align %x, resource %x," + " over %x, rcvdt %x, short %x\n", lp->scb.crc_err, lp->scb.align_err, lp->scb.resource_err, lp->scb.over_err, lp->scb.rcvdt_err, lp->scb.short_err); cmd = lp->cmd_head; - while (cmd != I596_NULL) { - printk("cmd at %p, .status = %04x, .command = %04x, .b_next = %p\n", + while (cmd != NULL) { + printk("cmd at %p, .status = %04x, .command = %04x, .b_next = %08x\n", cmd, cmd->status, cmd->command, cmd->b_next); cmd = cmd->v_next; } rfd = lp->rfd_head; printk("rfd_head = %p\n", rfd); do { - printk (" %p .stat %04x, .cmd %04x, b_next %p, rbd %p," + printk (" %p .stat %04x, .cmd %04x, b_next %08x, rbd %08x," " count %04x\n", rfd, rfd->stat, rfd->cmd, rfd->b_next, rfd->rbd, rfd->count); @@ -502,7 +523,7 @@ rbd = lp->rbd_head; printk("rbd_head = %p\n", rbd); do { - printk(" %p .count %04x, b_next %p, b_data %p, size %04x\n", + printk(" %p .count %04x, b_next %08x, b_data %08x, size %04x\n", rbd, rbd->count, rbd->b_next, rbd->b_data, rbd->size); rbd = rbd->v_next; } while (rbd != lp->rbd_head); @@ -523,7 +544,7 @@ } #endif -#define virt_to_dma(lp,v) ((char *)(v)-(char *)(lp)+(char *)((lp)->dma_addr)) +#define virt_to_dma(lp,v) ((lp)->dma_addr + (dma_addr_t)((unsigned long)(v)-(unsigned long)(lp))) static inline void init_rx_bufs(struct net_device *dev) { @@ -541,7 +562,7 @@ if (skb == NULL) panic("82596: alloc_skb() failed"); skb_reserve(skb, 2); - dma_addr = pci_map_single(NULL, skb->tail,PKT_BUF_SZ, + dma_addr = pci_map_single(fake_pci_dev, skb->tail,PKT_BUF_SZ, PCI_DMA_FROMDEVICE); skb->dev = dev; rbd->v_next = rbd+1; @@ -569,7 +590,7 @@ lp->rfd_head = lp->rfds; lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds)); rfd = lp->rfds; - rfd->rbd = lp->rbd_head; + rfd->rbd = WSWAPrbd(virt_to_dma(lp,lp->rbd_head)); rfd->v_prev = lp->rfds + rx_ring_size - 1; rfd = lp->rfds + rx_ring_size - 1; rfd->v_next = lp->rfds; @@ -588,7 +609,9 @@ for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) { if (rbd->skb == NULL) break; - pci_unmap_single(NULL,(dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, PCI_DMA_FROMDEVICE); + pci_unmap_single(fake_pci_dev, + (dma_addr_t)WSWAPchar(rbd->b_data), + PKT_BUF_SZ, PCI_DMA_FROMDEVICE); dev_kfree_skb(rbd->skb); } } @@ -640,14 +663,15 @@ lp->iscp.stat = ISCP_BUSY; lp->cmd_backlog = 0; - lp->cmd_head = lp->scb.cmd = I596_NULL; + lp->cmd_head = NULL; + lp->scb.cmd = I596_NULL; DEB(DEB_INIT,printk("%s: starting i82596.\n", dev->name)); CHECK_WBACK(&(lp->scp), sizeof(struct i596_scp)); CHECK_WBACK(&(lp->iscp), sizeof(struct i596_iscp)); - MPU_PORT(dev, PORT_ALTSCP, (void *)virt_to_dma(lp,&lp->scp)); + MPU_PORT(dev, PORT_ALTSCP, virt_to_dma(lp,&lp->scp)); CA(dev); @@ -724,7 +748,7 @@ CHECK_INV(rfd, sizeof(struct i596_rfd)); while ((rfd->stat) & STAT_C) { /* Loop while complete frames */ if (rfd->rbd == I596_NULL) - rbd = I596_NULL; + rbd = NULL; else if (rfd->rbd == lp->rbd_head->b_addr) { rbd = lp->rbd_head; CHECK_INV(rbd, sizeof(struct i596_rbd)); @@ -732,12 +756,12 @@ else { printk("%s: rbd chain broken!\n", dev->name); /* XXX Now what? */ - rbd = I596_NULL; + rbd = NULL; } - DEB(DEB_RXFRAME, printk(" rfd %p, rfd.rbd %p, rfd.stat %04x\n", + DEB(DEB_RXFRAME, printk(" rfd %p, rfd.rbd %08x, rfd.stat %04x\n", rfd, rfd->rbd, rfd->stat)); - if (rbd != I596_NULL && ((rfd->stat) & STAT_OK)) { + if (rbd != NULL && ((rfd->stat) & STAT_OK)) { /* a good frame */ int pkt_len = rbd->count & 0x3fff; struct sk_buff *skb = rbd->skb; @@ -754,7 +778,7 @@ struct sk_buff *newskb; dma_addr_t dma_addr; - pci_unmap_single(NULL,(dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, PCI_DMA_FROMDEVICE); + pci_unmap_single(fake_pci_dev,(dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, PCI_DMA_FROMDEVICE); /* Get fresh skbuff to replace filled one. */ newskb = dev_alloc_skb(PKT_BUF_SZ + 4); if (newskb == NULL) { @@ -768,7 +792,7 @@ rx_in_place = 1; rbd->skb = newskb; newskb->dev = dev; - dma_addr = pci_map_single(NULL, newskb->tail, PKT_BUF_SZ, PCI_DMA_FROMDEVICE); + dma_addr = pci_map_single(fake_pci_dev, newskb->tail, PKT_BUF_SZ, PCI_DMA_FROMDEVICE); rbd->v_data = newskb->tail; rbd->b_data = WSWAPchar(dma_addr); CHECK_WBACK_INV(rbd, sizeof(struct i596_rbd)); @@ -785,7 +809,7 @@ skb->dev = dev; if (!rx_in_place) { /* 16 byte align the data fields */ - pci_dma_sync_single(NULL, (dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, PCI_DMA_FROMDEVICE); + pci_dma_sync_single(fake_pci_dev, (dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, PCI_DMA_FROMDEVICE); skb_reserve(skb, 2); memcpy(skb_put(skb,pkt_len), rbd->v_data, pkt_len); } @@ -819,7 +843,7 @@ /* Clear the buffer descriptor count and EOF + F flags */ - if (rbd != I596_NULL && (rbd->count & 0x4000)) { + if (rbd != NULL && (rbd->count & 0x4000)) { rbd->count = 0; lp->rbd_head = rbd->v_next; CHECK_WBACK_INV(rbd, sizeof(struct i596_rbd)); @@ -856,7 +880,7 @@ { struct i596_cmd *ptr; - while (lp->cmd_head != I596_NULL) { + while (lp->cmd_head != NULL) { ptr = lp->cmd_head; lp->cmd_head = ptr->v_next; lp->cmd_backlog--; @@ -866,19 +890,21 @@ { struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr; struct sk_buff *skb = tx_cmd->skb; - pci_unmap_single(NULL, tx_cmd->dma_addr, skb->len, PCI_DMA_TODEVICE); + pci_unmap_single(fake_pci_dev, tx_cmd->dma_addr, skb->len, PCI_DMA_TODEVICE); dev_kfree_skb(skb); lp->stats.tx_errors++; lp->stats.tx_aborted_errors++; - ptr->v_next = ptr->b_next = I596_NULL; + ptr->v_next = NULL; + ptr->b_next = I596_NULL; tx_cmd->cmd.command = 0; /* Mark as free */ break; } default: - ptr->v_next = ptr->b_next = I596_NULL; + ptr->v_next = NULL; + ptr->b_next = I596_NULL; } CHECK_WBACK_INV(ptr, sizeof(struct i596_cmd)); } @@ -889,7 +915,7 @@ } -static inline void i596_reset(struct net_device *dev, struct i596_private *lp, int ioaddr) +static inline void i596_reset(struct net_device *dev, struct i596_private *lp) { unsigned long flags; @@ -921,19 +947,19 @@ static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd) { struct i596_private *lp = (struct i596_private *) dev->priv; - int ioaddr = dev->base_addr; unsigned long flags; DEB(DEB_ADDCMD,printk("i596_add_cmd cmd_head %p\n", lp->cmd_head)); cmd->status = 0; cmd->command |= (CMD_EOL | CMD_INTR); - cmd->v_next = cmd->b_next = I596_NULL; + cmd->v_next = NULL; + cmd->b_next = I596_NULL; CHECK_WBACK(cmd, sizeof(struct i596_cmd)); spin_lock_irqsave (&lp->lock, flags); - if (lp->cmd_head != I596_NULL) { + if (lp->cmd_head != NULL) { lp->cmd_tail->v_next = cmd; lp->cmd_tail->b_next = WSWAPcmd(virt_to_dma(lp,&cmd->status)); CHECK_WBACK(lp->cmd_tail, sizeof(struct i596_cmd)); @@ -958,7 +984,7 @@ printk("%s: command unit timed out, status resetting.\n", dev->name); #if 1 - i596_reset(dev, lp, ioaddr); + i596_reset(dev, lp); #endif } } @@ -1011,8 +1037,6 @@ goto out_remove_rx_bufs; } - request_mem_region(dev->base_addr, I596_TOTAL_SIZE, "i82596"); - netif_start_queue(dev); return 0; @@ -1029,7 +1053,6 @@ static void i596_tx_timeout (struct net_device *dev) { struct i596_private *lp = (struct i596_private *) dev->priv; - int ioaddr = dev->base_addr; /* Transmitter timeout, serious problems. */ DEB(DEB_ERRORS,printk("%s: transmit timed out, status resetting.\n", @@ -1041,7 +1064,7 @@ if (lp->last_restart == lp->stats.tx_packets) { DEB(DEB_ERRORS,printk ("Resetting board.\n")); /* Shutdown and restart */ - i596_reset (dev, lp, ioaddr); + i596_reset (dev, lp); } else { /* Issue a channel attention signal */ DEB(DEB_ERRORS,printk ("Kicking board.\n")); @@ -1064,8 +1087,8 @@ short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; dev->trans_start = jiffies; - DEB(DEB_STARTTX,printk("%s: i596_start_xmit(%x,%x) called\n", dev->name, - skb->len, (unsigned int)skb->data)); + DEB(DEB_STARTTX,printk("%s: i596_start_xmit(%x,%p) called\n", dev->name, + skb->len, skb->data)); netif_stop_queue(dev); @@ -1092,7 +1115,7 @@ tbd->pad = 0; tbd->size = EOF | length; - tx_cmd->dma_addr = pci_map_single(NULL, skb->data, skb->len, + tx_cmd->dma_addr = pci_map_single(fake_pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE); tbd->data = WSWAPchar(tx_cmd->dma_addr); @@ -1126,7 +1149,7 @@ #define LAN_PROM_ADDR 0xF0810000 -static int __init i82596_probe(struct net_device *dev, int options) +static int __devinit i82596_probe(struct net_device *dev) { int i; struct i596_private *lp; @@ -1139,12 +1162,12 @@ sizeof(struct i596_rfd)); return -ENODEV; } - if (sizeof(struct i596_rbd) != 32) { + if ((sizeof(struct i596_rbd) % 32) != 0) { printk("82596: sizeof(struct i596_rbd) = %d\n", sizeof(struct i596_rbd)); return -ENODEV; } - if (sizeof(struct tx_cmd) != 32) { + if ((sizeof(struct tx_cmd) % 32) != 0) { printk("82596: sizeof(struct tx_cmd) = %d\n", sizeof(struct tx_cmd)); return -ENODEV; @@ -1154,27 +1177,25 @@ sizeof(struct i596_tbd)); return -ENODEV; } +#ifndef __LP64__ if (sizeof(struct i596_private) > 4096) { printk("82596: sizeof(struct i596_private) = %d\n", sizeof(struct i596_private)); return -ENODEV; } - - /* FIXME: - Currently this works only, if set-up from lasi.c. - This should be changed to use probing too ! - */ +#endif if (!dev->base_addr || !dev->irq) - return -ENODEV; + return -ENODEV; - if (pdc_lan_station_id( (char*)ð_addr, (void*)dev->base_addr)) { - for(i=0;i<6;i++) - eth_addr[i] = gsc_readb(LAN_PROM_ADDR+i); - printk("82596.c: MAC of HP700 LAN blindely read from the prom!\n"); + if (pdc_lan_station_id(eth_addr, dev->base_addr)) { + for (i=0; i < 6; i++) { + eth_addr[i] = gsc_readb(LAN_PROM_ADDR + i); + } + printk("82596.c: MAC of HP700 LAN read from EEPROM\n"); } - dev->mem_start = (int)pci_alloc_consistent( NULL, + dev->mem_start = (unsigned long) pci_alloc_consistent(fake_pci_dev, sizeof(struct i596_private), &dma_addr); if (!dev->mem_start) { printk("%s: Couldn't get consistent shared memory\n", dev->name); @@ -1210,11 +1231,10 @@ lp = (struct i596_private *) dev->priv; DEB(DEB_INIT,printk ("%s: lp at 0x%08lx (%d bytes), lp->scb at 0x%08lx\n", - dev->name, (unsigned long)lp, - sizeof(struct i596_private), (unsigned long)&lp->scb)); - memset((void *) lp, 0, sizeof(struct i596_private)); + dev->name, (unsigned long)lp, + sizeof(struct i596_private), (unsigned long)&lp->scb)); + memset(lp, 0, sizeof(struct i596_private)); - lp->options = options; lp->scb.command = 0; lp->scb.cmd = I596_NULL; lp->scb.rfd = I596_NULL; @@ -1227,18 +1247,6 @@ } -int __init lasi_i82596_probe(struct net_device *dev) -{ - return i82596_probe(dev, 0); -} - - -int __init asp_i82596_probe(struct net_device *dev) -{ - return i82596_probe(dev, OPT_SWAP_PORT); -} - - static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = dev_id; @@ -1276,7 +1284,7 @@ if ((status & 0x2000)) DEB(DEB_INTS,printk("%s: i596 interrupt command unit inactive %x.\n", dev->name, status & 0x0700)); - while (lp->cmd_head != I596_NULL) { + while (lp->cmd_head != NULL) { CHECK_INV(lp->cmd_head, sizeof(struct i596_cmd)); if (!(lp->cmd_head->status & STAT_C)) break; @@ -1309,7 +1317,7 @@ if ((ptr->status) & 0x1000) lp->stats.tx_aborted_errors++; } - pci_unmap_single(NULL, tx_cmd->dma_addr, skb->len, PCI_DMA_TODEVICE); + pci_unmap_single(fake_pci_dev, tx_cmd->dma_addr, skb->len, PCI_DMA_TODEVICE); dev_kfree_skb_irq(skb); tx_cmd->cmd.command = 0; /* Mark free */ @@ -1338,7 +1346,8 @@ ptr->command = 0; break; } - ptr->v_next = ptr->b_next = I596_NULL; + ptr->v_next = NULL; + ptr->b_next = I596_NULL; CHECK_WBACK(ptr, sizeof(struct i596_cmd)); lp->last_cmd = jiffies; } @@ -1348,7 +1357,7 @@ * only add to the cmd queue when the CU is stopped. */ ptr = lp->cmd_head; - while ((ptr != I596_NULL) && (ptr != lp->cmd_tail)) { + while ((ptr != NULL) && (ptr != lp->cmd_tail)) { struct i596_cmd *prev = ptr; ptr->command &= 0x1fff; @@ -1356,7 +1365,7 @@ CHECK_WBACK_INV(prev, sizeof(struct i596_cmd)); } - if ((lp->cmd_head != I596_NULL)) + if ((lp->cmd_head != NULL)) ack_cmd |= CUC_START; lp->scb.cmd = WSWAPcmd(virt_to_dma(lp,&lp->cmd_head->status)); CHECK_WBACK_INV(&lp->scb, sizeof(struct i596_scb)); @@ -1422,8 +1431,6 @@ free_irq(dev->irq, dev); remove_rx_bufs(dev); - release_mem_region(dev->base_addr, I596_TOTAL_SIZE); - MOD_DEC_USE_COUNT; return 0; @@ -1503,48 +1510,106 @@ } } -#ifdef HAVE_DEVLIST -static unsigned int i596_portlist[] __initdata = -{0x300, 0}; -struct netdev_entry i596_drv = -{"lasi_i82596", lasi_i82596_probe, I596_TOTAL_SIZE, i596_portlist}; -#endif +MODULE_PARM(debug, "i"); +MODULE_PARM_DESC(debug, "lasi_82596 debug mask"); +static int debug = -1; + +static int num_drivers; +static struct net_device *netdevs[MAX_DRIVERS]; -#ifdef MODULE -static char devicename[9] = -{0,}; -static struct net_device dev_82596 = +static int __devinit +lan_init_chip(struct parisc_device *dev) { - name: devicename, /* device name inserted by drivers/net/net_init.c */ - init: lasi_i82596_probe, + struct net_device *netdevice; + int retval; + + if (num_drivers >= MAX_DRIVERS) { + /* max count of possible i82596 drivers reached */ + return -ENODEV; + } + + fake_pci_dev = ccio_get_fake(dev); + + if (!dev->irq) { + printk(KERN_ERR __FILE__ ": IRQ not found for i82596 at 0x%lx\n", dev->hpa); + return -ENODEV; + } + + printk(KERN_INFO "Found i82596 at 0x%lx, IRQ %d\n", dev->hpa, dev->irq); + + netdevice = alloc_etherdev(0); + if (!netdevice) + return -ENOMEM; + + netdevice->base_addr = dev->hpa; + netdevice->irq = dev->irq; + netdevice->init = i82596_probe; + + retval = register_netdev(netdevice); + if (retval) { + printk(KERN_WARNING __FILE__ ": register_netdevice ret'd %d\n", retval); + kfree(netdevice); + return -ENODEV; + }; + if (dev->id.sversion == 0x72) { + ((struct i596_private *)netdevice->priv)->options = OPT_SWAP_PORT; + } + + netdevs[num_drivers++] = netdevice; + + return retval; +} + + +static struct parisc_device_id lan_tbl[] = { + { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008a }, + { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00072 }, + { 0, } }; +MODULE_DEVICE_TABLE(parisc, lan_tbl); -MODULE_PARM(debug, "i"); -MODULE_PARM_DESC(debug, "lasi_82596 debug mask"); -static int debug = -1; +static struct parisc_driver lan_driver = { + name: "Apricot", + id_table: lan_tbl, + probe: lan_init_chip, +}; -int init_module(void) +static int __devinit lasi_82596_init(void) { if (debug >= 0) i596_debug = debug; - if (register_netdev(&dev_82596) != 0) - return -EIO; - return 0; + return register_parisc_driver(&lan_driver); } -void cleanup_module(void) +module_init(lasi_82596_init); + +static void __exit lasi_82596_exit(void) { - unregister_netdev(&dev_82596); - lp = (struct i596_private *) dev_82596.priv; + int i; - if (dma_consistent) - pci_free_consistent( NULL, sizeof( struct i596_private), - dev_82596.mem_start, lp->dma_addr); - else - free_page ((u32)(dev_82596.mem_start)); + for (i=0; ipriv; + if (dma_consistent) + pci_free_consistent(fake_pci_dev, + sizeof(struct i596_private), + (void *)netdevice->mem_start, lp->dma_addr); + else + free_page(netdevice->mem_start); + + netdevice->priv = NULL; + } - dev_82596.priv = NULL; + unregister_parisc_driver(&lan_driver); } -#endif /* MODULE */ +module_exit(lasi_82596_exit); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/net/pcmcia/wavelan_cs.c linux.19rc3-ac4/drivers/net/pcmcia/wavelan_cs.c --- linux.19rc3/drivers/net/pcmcia/wavelan_cs.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/net/pcmcia/wavelan_cs.c 2002-07-29 13:58:42.000000000 +0100 @@ -37,12 +37,6 @@ * Apr 2 '98 made changes to bring the i82593 control/int handling in line * with offical specs... * - * Changes: - * Arnaldo Carvalho de Melo - 08/08/2000 - * - reorganize kmallocs in wavelan_attach, checking all for failure - * and releasing the previous allocations if one fails - * - * **************************************************************************** * Copyright 1995 * Anthony D. Joseph @@ -72,6 +66,34 @@ /*------------------------------------------------------------------*/ /* + * Wrapper for disabling interrupts. + * (note : inline, so optimised away) + */ +static inline void +wv_splhi(net_local * lp, + unsigned long * pflags) +{ + spin_lock_irqsave(&lp->spinlock, *pflags); + /* Note : above does the cli(); itself */ +} + +/*------------------------------------------------------------------*/ +/* + * Wrapper for re-enabling interrupts. + */ +static inline void +wv_splx(net_local * lp, + unsigned long * pflags) +{ + spin_unlock_irqrestore(&lp->spinlock, *pflags); + + /* Note : enabling interrupts on the hardware is done in wv_ru_start() + * via : outb(OP1_INT_ENABLE, LCCR(base)); + */ +} + +/*------------------------------------------------------------------*/ +/* * Wrapper for reporting error to cardservices */ static void cs_error(client_handle_t handle, int func, int ret) @@ -103,7 +125,7 @@ /******************* MODEM MANAGEMENT SUBROUTINES *******************/ /* - * Usefull subroutines to manage the modem of the wavelan + * Useful subroutines to manage the modem of the wavelan */ /*------------------------------------------------------------------*/ @@ -138,7 +160,7 @@ { hacr_write(base, hacr); /* delay might only be needed sometimes */ - mdelay(1L); + mdelay(1); } /* hacr_write_slow */ /*------------------------------------------------------------------*/ @@ -529,7 +551,7 @@ lp->curr_point=NULL; /* No default WavePoint */ lp->cell_search=0; - lp->cell_timer.data=(int)lp; /* Start cell expiry timer */ + lp->cell_timer.data=(long)lp; /* Start cell expiry timer */ lp->cell_timer.function=wl_cell_expiry; lp->cell_timer.expires=jiffies+CELL_TIMEOUT; add_timer(&lp->cell_timer); @@ -569,18 +591,18 @@ #endif /* Disable interrupts & save flags */ - spin_lock_irqsave (&lp->lock, flags); + wv_splhi(lp, &flags); m.w.mmw_loopt_sel = (mode==NWID_PROMISC) ? MMW_LOOPT_SEL_DIS_NWID : 0x00; mmc_write(lp->dev->base_addr, (char *)&m.w.mmw_loopt_sel - (char *)&m, (unsigned char *)&m.w.mmw_loopt_sel, 1); - /* ReEnable interrupts & restore flags */ - spin_unlock_irqrestore (&lp->lock, flags); - if(mode==NWID_PROMISC) lp->cell_search=1; else - lp->cell_search=0; + lp->cell_search=0; + + /* ReEnable interrupts & restore flags */ + wv_splx(lp, &flags); } /* Find a record in the WavePoint table matching a given NWID */ @@ -737,7 +759,7 @@ ioaddr_t base = lp->dev->base_addr; mm_t m; unsigned long flags; - + if(wavepoint==lp->curr_point) /* Sanity check... */ { wv_nwid_filter(!NWID_PROMISC,lp); @@ -749,16 +771,16 @@ #endif /* Disable interrupts & save flags */ - spin_lock_irqsave(&lp->lock, flags); - + wv_splhi(lp, &flags); + m.w.mmw_netw_id_l = wavepoint->nwid & 0xFF; m.w.mmw_netw_id_h = (wavepoint->nwid & 0xFF00) >> 8; mmc_write(base, (char *)&m.w.mmw_netw_id_l - (char *)&m, (unsigned char *)&m.w.mmw_netw_id_l, 2); /* ReEnable interrupts & restore flags */ - spin_unlock_irqrestore (&lp->lock, flags); - + wv_splx(lp, &flags); + wv_nwid_filter(!NWID_PROMISC,lp); lp->curr_point=wavepoint; } @@ -775,6 +797,11 @@ wavepoint_history *wavepoint=NULL; /* WavePoint table entry */ net_local *lp=(net_local *)dev->priv; /* Device info */ +#ifdef I_NEED_THIS_FEATURE + /* Some people don't need this, some other may need it */ + nwid=nwid^ntohs(beacon->domain_id); +#endif + #if WAVELAN_ROAMING_DEBUG > 1 printk(KERN_DEBUG "WaveLAN: beacon, dev %s:\n",dev->name); printk(KERN_DEBUG "Domain: %.4X NWID: %.4X SigQual=%d\n",ntohs(beacon->domain_id),nwid,sigqual); @@ -832,7 +859,9 @@ /*------------------------------------------------------------------*/ /* * Routine to synchronously send a command to the i82593 chip. - * Should be called with interrupts enabled. + * Should be called with interrupts disabled. + * (called by wv_packet_write(), wv_ru_stop(), wv_ru_start(), + * wv_82593_config() & wv_diag()) */ static int wv_82593_cmd(device * dev, @@ -841,74 +870,98 @@ int result) { ioaddr_t base = dev->base_addr; - net_local * lp = (net_local *)dev->priv; int status; + int wait_completed; long spin; - u_long flags; /* Spin until the chip finishes executing its current command (if any) */ + spin = 1000; do { - spin_lock_irqsave (&lp->lock, flags); + /* Time calibration of the loop */ + udelay(10); + + /* Read the interrupt register */ outb(OP0_NOP | CR0_STATUS_3, LCCR(base)); status = inb(LCSR(base)); - spin_unlock_irqrestore (&lp->lock, flags); } - while((status & SR3_EXEC_STATE_MASK) != SR3_EXEC_IDLE); + while(((status & SR3_EXEC_STATE_MASK) != SR3_EXEC_IDLE) && (spin-- > 0)); - /* We are waiting for command completion */ - wv_wait_completed = TRUE; + /* If the interrupt hasn't be posted */ + if(spin <= 0) + { +#ifdef DEBUG_INTERRUPT_ERROR + printk(KERN_INFO "wv_82593_cmd: %s timeout (previous command), status 0x%02x\n", + str, status); +#endif + return(FALSE); + } /* Issue the command to the controller */ outb(cmd, LCCR(base)); - /* If we don't have to check the result of the command */ + /* If we don't have to check the result of the command + * Note : this mean that the irq handler will deal with that */ if(result == SR0_NO_RESULT) - { - wv_wait_completed = FALSE; - return(TRUE); - } + return(TRUE); - /* Busy wait while the LAN controller executes the command. - * Note : wv_wait_completed should be volatile */ - spin = 0; - while(wv_wait_completed && (spin++ < 1000)) - udelay(10); + /* We are waiting for command completion */ + wait_completed = TRUE; - /* If the interrupt handler hasn't be called */ - if(wv_wait_completed) + /* Busy wait while the LAN controller executes the command. */ + spin = 1000; + do { - outb(OP0_NOP, LCCR(base)); + /* Time calibration of the loop */ + udelay(10); + + /* Read the interrupt register */ + outb(CR0_STATUS_0 | OP0_NOP, LCCR(base)); status = inb(LCSR(base)); - if(status & SR0_INTERRUPT) + + /* Check if there was an interrupt posted */ + if((status & SR0_INTERRUPT)) { - /* There was an interrupt : call the interrupt handler */ -#ifdef DEBUG_INTERRUPT_ERROR - printk(KERN_WARNING "wv_82593_cmd: interrupt handler not installed or interrupt disabled\n"); -#endif + /* Acknowledge the interrupt */ + outb(CR0_INT_ACK | OP0_NOP, LCCR(base)); - wavelan_interrupt(dev->irq, (void *) dev, - (struct pt_regs *) NULL); + /* Check if interrupt is a command completion */ + if(((status & SR0_BOTH_RX_TX) != SR0_BOTH_RX_TX) && + ((status & SR0_BOTH_RX_TX) != 0x0) && + !(status & SR0_RECEPTION)) + { + /* Signal command completion */ + wait_completed = FALSE; + } + else + { + /* Note : Rx interrupts will be handled later, because we can + * handle multiple Rx packets at once */ +#ifdef DEBUG_INTERRUPT_INFO + printk(KERN_INFO "wv_82593_cmd: not our interrupt\n"); +#endif + } } - else - { - wv_wait_completed = 0; /* XXX */ + } + while(wait_completed && (spin-- > 0)); + + /* If the interrupt hasn't be posted */ + if(wait_completed) + { #ifdef DEBUG_INTERRUPT_ERROR - printk(KERN_INFO "wv_82593_cmd: %s timeout, status0 0x%02x\n", - str, status); + printk(KERN_INFO "wv_82593_cmd: %s timeout, status 0x%02x\n", + str, status); #endif - /* We probably should reset the controller here */ - return(FALSE); - } + return(FALSE); } - /* Check the return code provided by the interrupt handler against + /* Check the return code returned by the card (see above) against * the expected return code provided by the caller */ - if((lp->status & SR0_EVENT_MASK) != result) + if((status & SR0_EVENT_MASK) != result) { #ifdef DEBUG_INTERRUPT_ERROR - printk(KERN_INFO "wv_82593_cmd: %s failed, status0 = 0x%x\n", - str, lp->status); + printk(KERN_INFO "wv_82593_cmd: %s failed, status = 0x%x\n", + str, status); #endif return(FALSE); } @@ -924,14 +977,16 @@ static inline int wv_diag(device * dev) { + int ret = FALSE; + if(wv_82593_cmd(dev, "wv_diag(): diagnose", OP0_DIAGNOSE, SR0_DIAGNOSE_PASSED)) - return(TRUE); + ret = TRUE; #ifdef DEBUG_CONFIG_ERROR printk(KERN_INFO "wavelan_cs: i82593 Self Test failed!\n"); #endif - return(FALSE); + return(ret); } /* wv_diag */ /*------------------------------------------------------------------*/ @@ -951,15 +1006,6 @@ int chunk_len; char * buf_ptr = buf; -#ifdef OLDIES - /* After having check skb_put (net/core/skbuff.c) in the kernel, it seem - * quite safe to remove this... */ - - /* If buf is NULL, just increment the ring buffer pointer */ - if(buf == NULL) - return((ring_ptr - RX_BASE + len) % RX_SIZE + RX_BASE); -#endif - /* Get all the buffer */ while(len > 0) { @@ -990,70 +1036,32 @@ * wavelan_interrupt is not an option...), so you may experience * some delay sometime... */ -static inline void wv_82593_reconfig (device * dev) +static inline void +wv_82593_reconfig(device * dev) { - net_local *lp = (net_local *) dev->priv; - dev_link_t *link = ((net_local *) dev->priv)->link; + net_local * lp = (net_local *)dev->priv; + dev_link_t * link = ((net_local *) dev->priv)->link; + unsigned long flags; - /* Check if we can do it now ! */ - if (!(link->open)) { - lp->reconfig_82593 = TRUE; + /* Arm the flag, will be cleard in wv_82593_config() */ + lp->reconfig_82593 = TRUE; + + /* Check if we can do it now ! */ + if((link->open) && (netif_running(dev)) && !(netif_queue_stopped(dev))) + { + wv_splhi(lp, &flags); /* Disable interrupts */ + wv_82593_config(dev); + wv_splx(lp, &flags); /* Re-enable interrupts */ + } + else + { #ifdef DEBUG_IOCTL_INFO - printk (KERN_DEBUG "%s: wv_82593_reconfig(): delayed (link = %d)\n", - dev->name, link->open); + printk(KERN_DEBUG + "%s: wv_82593_reconfig(): delayed (state = %lX, link = %d)\n", + dev->name, dev->state, link->open); #endif - } else { - netif_stop_queue (dev); - - lp->reconfig_82593 = FALSE; - wv_82593_config (dev); - netif_wake_queue (dev); - } -} - -#ifdef OLDIES -/*------------------------------------------------------------------*/ -/* - * Dumps the current i82593 receive buffer to the console. - */ -static void wavelan_dump(device *dev) -{ - ioaddr_t base = dev->base_addr; - int i, c; - - /* disable receiver so we can use channel 1 */ - outb(OP0_RCV_DISABLE, LCCR(base)); - - /* reset receive DMA pointer */ - hacr_write_slow(base, HACR_PWR_STAT | HACR_RX_DMA_RESET); - hacr_write(base, HACR_DEFAULT); - - /* dump into receive buffer */ - wv_82593_cmd(dev, "wavelan_dump(): dump", CR0_CHNL|OP0_DUMP, SR0_DUMP_DONE); - - /* set read pointer to start of receive buffer */ - outb(0, PIORL(base)); - outb(0, PIORH(base)); - - printk(KERN_DEBUG "wavelan_cs: dump:\n"); - printk(KERN_DEBUG " 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"); - for(i = 0; i < 73; i++){ - if((i % 16) == 0) { - printk("\n0x%02x:", i); - if (!i) { - printk(" "); - continue; - } } - c = inb(PIOP(base)); - printk("%02x ", c); - } - printk("\n"); - - /* enable the receiver again */ - wv_ru_start(dev); } -#endif /********************* DEBUG & INFO SUBROUTINES *********************/ /* @@ -1171,6 +1179,8 @@ return; } + wv_splhi(lp, &flags); + /* Read the mmc */ mmc_out(base, mmwoff(0, mmw_freeze), 1); mmc_read(base, 0, (u_char *)&m, sizeof(m)); @@ -1181,6 +1191,8 @@ lp->wstats.discard.nwid += (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l; #endif /* WIRELESS_EXT */ + wv_splx(lp, &flags); + printk(KERN_DEBUG "##### wavelan modem status registers: #####\n"); #ifdef DEBUG_SHOW_UNUSED printk(KERN_DEBUG "mmc_unused0[]: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", @@ -1265,6 +1277,7 @@ wv_dev_show(device * dev) { printk(KERN_DEBUG "dev:"); + printk(" state=%lX,", dev->state); printk(" trans_start=%ld,", dev->trans_start); printk(" flags=0x%x,", dev->flags); printk("\n"); @@ -1892,7 +1905,7 @@ #endif /* Disable interrupts & save flags */ - spin_lock_irqsave (&lp->lock, flags); + wv_splhi(lp, &flags); /* Look what is the request */ switch(cmd) @@ -1968,7 +1981,7 @@ case SIOCGIWFREQ: /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable) - * (does it work for everybody XXX - especially old cards...) */ + * (does it work for everybody ? - especially old cards...) */ if(!(mmc_in(base, mmroff(0, mmr_fee_status)) & (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) { @@ -2239,15 +2252,17 @@ { struct iw_range range; - /* Set the length (very important for backward compatibility) */ - wrq->u.data.length = sizeof(struct iw_range); + /* Set the length (very important for backward compatibility) */ + wrq->u.data.length = sizeof(struct iw_range); - /* Set all the info we don't care or don't know about to zero */ - memset(&range, 0, sizeof(range)); + /* Set all the info we don't care or don't know about to zero */ + memset(&range, 0, sizeof(range)); - /* Set the Wireless Extension versions */ - range.we_version_compiled = WIRELESS_EXT; - range.we_version_source = 9; /* Nothing for us in v10 and v11 */ +#if WIRELESS_EXT > 10 + /* Set the Wireless Extension versions */ + range.we_version_compiled = WIRELESS_EXT; + range.we_version_source = 9; /* Nothing for us in v10 and v11 */ +#endif /* WIRELESS_EXT > 10 */ /* Set information in the range struct */ range.throughput = 1.4 * 1000 * 1000; /* don't argue on this ! */ @@ -2517,7 +2532,7 @@ } /* ReEnable interrupts & restore flags */ - spin_unlock_irqrestore (&lp->lock, flags); + wv_splx(lp, &flags); #ifdef DEBUG_IOCTL_TRACE printk(KERN_DEBUG "%s: <-wavelan_ioctl()\n", dev->name); @@ -2543,11 +2558,8 @@ printk(KERN_DEBUG "%s: ->wavelan_get_wireless_stats()\n", dev->name); #endif - if (lp == NULL) /* XXX will this ever occur? */ - return NULL; - /* Disable interrupts & save flags */ - spin_lock_irqsave (&lp->lock, flags); + wv_splhi(lp, &flags); wstats = &lp->wstats; @@ -2573,7 +2585,7 @@ wstats->discard.misc = 0L; /* ReEnable interrupts & restore flags */ - spin_unlock_irqrestore (&lp->lock, flags); + wv_splx(lp, &flags); #ifdef DEBUG_IOCTL_TRACE printk(KERN_DEBUG "%s: <-wavelan_get_wireless_stats()\n", dev->name); @@ -2692,12 +2704,6 @@ skb->protocol = eth_type_trans(skb, dev); #ifdef DEBUG_RX_INFO - /* Another glitch : Due to the way the GET_PACKET macro is written, - * we are not sure to have the same thing in skb->data. On the other - * hand, skb->mac.raw is not defined everywhere... - * For versions between 1.2.13 and those where skb->mac.raw appear, - * I don't have a clue... - */ wv_packet_info(skb->mac.raw, sksize, dev->name, "wv_packet_read"); #endif /* DEBUG_RX_INFO */ @@ -2731,9 +2737,7 @@ wl_roam_gather(dev, skb->data, stats); #endif /* WAVELAN_ROAMING */ - /* Spying stuff */ #ifdef WIRELESS_SPY - /* Same as above */ wl_spy_gather(dev, skb->mac.raw + WAVELAN_ADDR_SIZE, stats); #endif /* WIRELESS_SPY */ #ifdef HISTOGRAM @@ -2766,6 +2770,7 @@ * called to do the actual transfer of the card's data including the * ethernet header into a packet consisting of an sk_buff chain. * (called by wavelan_interrupt()) + * Note : the spinlock is already grabbed for us and irq are disabled. */ static inline void wv_packet_rcv(device * dev) @@ -2916,7 +2921,7 @@ printk(KERN_DEBUG "%s: ->wv_packet_write(%d)\n", dev->name, length); #endif - spin_lock_irqsave (&lp->lock, flags); + wv_splhi(lp, &flags); /* Check if we need some padding */ if(clen < ETH_ZLEN) @@ -2946,15 +2951,7 @@ /* Keep stats up to date */ lp->stats.tx_bytes += length; - /* If watchdog not already active, activate it... */ - if (!timer_pending(&lp->watchdog)) - { - /* set timer to expire in WATCHDOG_JIFFIES */ - lp->watchdog.expires = jiffies + WATCHDOG_JIFFIES; - add_timer(&lp->watchdog); - } - - spin_unlock_irqrestore (&lp->lock, flags); + wv_splx(lp, &flags); #ifdef DEBUG_TX_INFO wv_packet_info((u_char *) buf, length, dev->name, "wv_packet_write"); @@ -2963,56 +2960,57 @@ #ifdef DEBUG_TX_TRACE printk(KERN_DEBUG "%s: <-wv_packet_write()\n", dev->name); #endif - - netif_start_queue (dev); } /*------------------------------------------------------------------*/ /* * This routine is called when we want to send a packet (NET3 callback) - * In this routine, we check if the hardware is ready to accept + * In this routine, we check if the harware is ready to accept * the packet. We also prevent reentrance. Then, we call the function * to send the packet... */ -static int wavelan_packet_xmit (struct sk_buff *skb, - device * dev) +static int +wavelan_packet_xmit(struct sk_buff * skb, + device * dev) { - net_local *lp = (net_local *) dev->priv; + net_local * lp = (net_local *)dev->priv; + unsigned long flags; #ifdef DEBUG_TX_TRACE - printk (KERN_DEBUG "%s: ->wavelan_packet_xmit(0x%X)\n", dev->name, - (unsigned) skb); + printk(KERN_DEBUG "%s: ->wavelan_packet_xmit(0x%X)\n", dev->name, + (unsigned) skb); #endif - /* - * For ethernet, fill in the header. - */ + /* + * Block a timer-based transmit from overlapping a previous transmit. + * In other words, prevent reentering this routine. + */ + netif_stop_queue(dev); - netif_stop_queue (dev); + /* If somebody has asked to reconfigure the controller, + * we can do it now */ + if(lp->reconfig_82593) + { + wv_splhi(lp, &flags); /* Disable interrupts */ + wv_82593_config(dev); + wv_splx(lp, &flags); /* Re-enable interrupts */ + /* Note : the configure procedure was totally synchronous, + * so the Tx buffer is now free */ + } - /* - * Block a timer-based transmit from overlapping a previous transmit. - * In other words, prevent reentering this routine. - */ - if (1) { - /* If somebody has asked to reconfigure the controller, we can do it now */ - if (lp->reconfig_82593) { - lp->reconfig_82593 = FALSE; - wv_82593_config (dev); - } #ifdef DEBUG_TX_ERROR - if (skb->next) - printk (KERN_INFO "skb has next\n"); + if (skb->next) + printk(KERN_INFO "skb has next\n"); #endif - wv_packet_write (dev, skb->data, skb->len); - } - dev_kfree_skb (skb); + wv_packet_write(dev, skb->data, skb->len); + + dev_kfree_skb(skb); #ifdef DEBUG_TX_TRACE - printk (KERN_DEBUG "%s: <-wavelan_packet_xmit()\n", dev->name); + printk(KERN_DEBUG "%s: <-wavelan_packet_xmit()\n", dev->name); #endif - return (0); + return(0); } /********************** HARDWARE CONFIGURATION **********************/ @@ -3165,7 +3163,7 @@ */ /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable) - * (does it work for everybody XXX - especially old cards...) */ + * (does it work for everybody ? - especially old cards...) */ /* Note : WFREQSEL verify that it is able to read from EEprom * a sensible frequency (address 0x00) + that MMR_FEE_STATUS_ID * is 0xA (Xilinx version) or 0xB (Ariadne version). @@ -3223,7 +3221,7 @@ wv_ru_stop(device * dev) { ioaddr_t base = dev->base_addr; - net_local *lp = (net_local *) dev->priv; + net_local * lp = (net_local *) dev->priv; unsigned long flags; int status; int spin; @@ -3232,35 +3230,35 @@ printk(KERN_DEBUG "%s: ->wv_ru_stop()\n", dev->name); #endif + wv_splhi(lp, &flags); + /* First, send the LAN controller a stop receive command */ wv_82593_cmd(dev, "wv_graceful_shutdown(): stop-rcv", OP0_STOP_RCV, SR0_NO_RESULT); /* Then, spin until the receive unit goes idle */ - spin = 0; + spin = 300; do { udelay(10); - spin_lock_irqsave (&lp->lock, flags); outb(OP0_NOP | CR0_STATUS_3, LCCR(base)); status = inb(LCSR(base)); - spin_unlock_irqrestore (&lp->lock, flags); } - while(((status & SR3_RCV_STATE_MASK) != SR3_RCV_IDLE) && (spin++ < 300)); + while(((status & SR3_RCV_STATE_MASK) != SR3_RCV_IDLE) && (spin-- > 0)); /* Now, spin until the chip finishes executing its current command */ do { udelay(10); - spin_lock_irqsave (&lp->lock, flags); outb(OP0_NOP | CR0_STATUS_3, LCCR(base)); status = inb(LCSR(base)); - spin_unlock_irqrestore (&lp->lock, flags); } - while(((status & SR3_EXEC_STATE_MASK) != SR3_EXEC_IDLE) && (spin++ < 300)); + while(((status & SR3_EXEC_STATE_MASK) != SR3_EXEC_IDLE) && (spin-- > 0)); + + wv_splx(lp, &flags); /* If there was a problem */ - if(spin > 300) + if(spin <= 0) { #ifdef DEBUG_CONFIG_ERROR printk(KERN_INFO "%s: wv_ru_stop(): The chip doesn't want to stop...\n", @@ -3287,6 +3285,7 @@ { ioaddr_t base = dev->base_addr; net_local * lp = (net_local *) dev->priv; + unsigned long flags; #ifdef DEBUG_CONFIG_TRACE printk(KERN_DEBUG "%s: ->wv_ru_start()\n", dev->name); @@ -3300,6 +3299,8 @@ if(!wv_ru_stop(dev)) return FALSE; + wv_splhi(lp, &flags); + /* Now we know that no command is being executed. */ /* Set the receive frame pointer and stop pointer */ @@ -3309,8 +3310,17 @@ /* Reset ring management. This sets the receive frame pointer to 1 */ outb(OP1_RESET_RING_MNGMT, LCCR(base)); +#if 0 + /* XXX the i82593 manual page 6-4 seems to indicate that the stop register + should be set as below */ + /* outb(CR1_STOP_REG_UPDATE|((RX_SIZE - 0x40)>> RX_SIZE_SHIFT),LCCR(base));*/ +#elif 0 + /* but I set it 0 instead */ + lp->stop = 0; +#else /* but I set it to 3 bytes per packet less than 8K */ lp->stop = (0 + RX_SIZE - ((RX_SIZE / 64) * 3)) % RX_SIZE; +#endif outb(CR1_STOP_REG_UPDATE | (lp->stop >> RX_SIZE_SHIFT), LCCR(base)); outb(OP1_INT_ENABLE, LCCR(base)); outb(OP1_SWIT_TO_PORT_0, LCCR(base)); @@ -3326,17 +3336,15 @@ #ifdef DEBUG_I82593_SHOW { int status; - unsigned long flags; - int i = 0; + int opri; + int spin = 10000; /* spin until the chip starts receiving */ do { - spin_lock_irqsave (&lp->lock, flags); outb(OP0_NOP | CR0_STATUS_3, LCCR(base)); status = inb(LCSR(base)); - spin_unlock_irqrestore (&lp->lock, flags); - if(i++ > 10000) + if(spin-- <= 0) break; } while(((status & SR3_RCV_STATE_MASK) != SR3_RCV_ACTIVE) && @@ -3345,6 +3353,9 @@ (status & SR3_RCV_STATE_MASK), i); } #endif + + wv_splx(lp, &flags); + #ifdef DEBUG_CONFIG_TRACE printk(KERN_DEBUG "%s: <-wv_ru_start()\n", dev->name); #endif @@ -3363,6 +3374,7 @@ ioaddr_t base = dev->base_addr; net_local * lp = (net_local *) dev->priv; struct i82593_conf_block cfblk; + int ret = TRUE; #ifdef DEBUG_CONFIG_TRACE printk(KERN_DEBUG "%s: ->wv_82593_config()\n", dev->name); @@ -3457,7 +3469,7 @@ hacr_write(base, HACR_DEFAULT); if(!wv_82593_cmd(dev, "wv_82593_config(): configure", OP0_CONFIGURE, SR0_CONFIGURE_DONE)) - return(FALSE); + ret = FALSE; /* Initialize adapter's ethernet MAC address */ outb(TX_BASE & 0xff, PIORL(base)); @@ -3471,7 +3483,7 @@ hacr_write(base, HACR_DEFAULT); if(!wv_82593_cmd(dev, "wv_82593_config(): ia-setup", OP0_IA_SETUP, SR0_IA_SETUP_DONE)) - return(FALSE); + ret = FALSE; #ifdef WAVELAN_ROAMING /* If roaming is enabled, join the "Beacon Request" multicast group... */ @@ -3508,14 +3520,17 @@ hacr_write(base, HACR_DEFAULT); if(!wv_82593_cmd(dev, "wv_82593_config(): mc-setup", OP0_MC_SETUP, SR0_MC_SETUP_DONE)) - return(FALSE); + ret = FALSE; lp->mc_count = dev->mc_count; /* remember to avoid repeated reset */ } + /* Job done, clear the flag */ + lp->reconfig_82593 = FALSE; + #ifdef DEBUG_CONFIG_TRACE printk(KERN_DEBUG "%s: <-wv_82593_config()\n", dev->name); #endif - return(TRUE); + return(ret); } /*------------------------------------------------------------------*/ @@ -3594,6 +3609,8 @@ { net_local * lp = (net_local *) dev->priv; ioaddr_t base = dev->base_addr; + unsigned long flags; + int ret = FALSE; #ifdef DEBUG_CONFIG_TRACE printk(KERN_DEBUG "%s: ->wv_hw_config()\n", dev->name); @@ -3612,50 +3629,78 @@ if(wv_pcmcia_reset(dev) == FALSE) return FALSE; - /* Power UP the module + reset the modem + reset host adapter - * (in fact, reset DMA channels) */ - hacr_write_slow(base, HACR_RESET); - hacr_write(base, HACR_DEFAULT); + /* Disable interrupts */ + wv_splhi(lp, &flags); - /* Check if the module has been powered up... */ - if(hasr_read(base) & HASR_NO_CLK) + /* Disguised goto ;-) */ + do { + /* Power UP the module + reset the modem + reset host adapter + * (in fact, reset DMA channels) */ + hacr_write_slow(base, HACR_RESET); + hacr_write(base, HACR_DEFAULT); + + /* Check if the module has been powered up... */ + if(hasr_read(base) & HASR_NO_CLK) + { #ifdef DEBUG_CONFIG_ERRORS - printk(KERN_WARNING "%s: wv_hw_config(): modem not connected or not a wavelan card\n", - dev->name); + printk(KERN_WARNING "%s: wv_hw_config(): modem not connected or not a wavelan card\n", + dev->name); #endif - return FALSE; - } + break; + } - /* initialize the modem */ - if(wv_mmc_init(dev) == FALSE) - return FALSE; + /* initialize the modem */ + if(wv_mmc_init(dev) == FALSE) + { +#ifdef DEBUG_CONFIG_ERRORS + printk(KERN_WARNING "%s: wv_hw_config(): Can't configure the modem\n", + dev->name); +#endif + break; + } - /* reset the LAN controller (i82593) */ - outb(OP0_RESET, LCCR(base)); - mdelay(1); /* A bit crude ! */ - - /* Initialize the LAN controller */ - if((wv_82593_config(dev) == FALSE) || - (wv_diag(dev) == FALSE)) - { + /* reset the LAN controller (i82593) */ + outb(OP0_RESET, LCCR(base)); + mdelay(1); /* A bit crude ! */ + + /* Initialize the LAN controller */ + if(wv_82593_config(dev) == FALSE) + { #ifdef DEBUG_CONFIG_ERRORS - printk(KERN_INFO "%s: wv_hw_config(): i82593 init failed\n", dev->name); + printk(KERN_INFO "%s: wv_hw_config(): i82593 init failed\n", + dev->name); #endif - return FALSE; - } + break; + } - /* - * insert code for loopback test here - */ + /* Diagnostic */ + if(wv_diag(dev) == FALSE) + { +#ifdef DEBUG_CONFIG_ERRORS + printk(KERN_INFO "%s: wv_hw_config(): i82593 diagnostic failed\n", + dev->name); +#endif + break; + } + + /* + * insert code for loopback test here + */ + + /* The device is now configured */ + lp->configured = 1; + ret = TRUE; + } + while(0); - /* The device is now configured */ - lp->configured = 1; + /* Re-enable interrupts */ + wv_splx(lp, &flags); #ifdef DEBUG_CONFIG_TRACE printk(KERN_DEBUG "%s: <-wv_hw_config()\n", dev->name); #endif - return TRUE; + return(ret); } /*------------------------------------------------------------------*/ @@ -3675,10 +3720,6 @@ printk(KERN_DEBUG "%s: ->wv_hw_reset()\n", dev->name); #endif - /* If watchdog was activated, kill it ! */ - if (timer_pending(&lp->watchdog)) - del_timer(&lp->watchdog); - lp->nresets++; lp->configured = 0; @@ -3786,13 +3827,13 @@ } /* - * Allocate a 4K memory window. Note that the dev_link_t + * Allocate a small memory window. Note that the dev_link_t * structure provides space for one window handle -- if your * device needs several windows, you'll need to keep track of * the handles in your private data structure, link->priv. */ req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; - req.Base = 0; req.Size = 0x1000; + req.Base = req.Size = 0; req.AccessSpeed = mem_speed; link->win = (window_handle_t)link->handle; i = CardServices(RequestWindow, &link->win, &req); @@ -3803,7 +3844,7 @@ } dev->rmem_start = dev->mem_start = - (u_long)ioremap(req.Base, 0x1000); + (u_long)ioremap(req.Base, req.Size); dev->rmem_end = dev->mem_end = dev->mem_start + req.Size; mem.CardOffset = 0; mem.Page = 0; @@ -3817,7 +3858,7 @@ /* Feed device with this info... */ dev->irq = link->irq.AssignedIRQ; dev->base_addr = link->io.BasePort1; - netif_start_queue (dev); + netif_start_queue(dev); #ifdef DEBUG_CONFIG_INFO printk(KERN_DEBUG "wv_pcmcia_config: MEMSTART 0x%x IRQ %d IOPORT 0x%x\n", @@ -3843,7 +3884,7 @@ return FALSE; } - /* XXX Could you explain me this, Dave ? */ + strcpy(((net_local *) dev->priv)->node.dev_name, dev->name); link->dev = &((net_local *) dev->priv)->node; #ifdef DEBUG_CONFIG_TRACE @@ -3887,7 +3928,7 @@ CardServices(ReleaseIO, link->handle, &link->io); CardServices(ReleaseIRQ, link->handle, &link->irq); - link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING | DEV_STALE_CONFIG); + link->state &= ~(DEV_CONFIG | DEV_STALE_CONFIG); #ifdef DEBUG_CONFIG_TRACE printk(KERN_DEBUG "%s: <- wv_pcmcia_release()\n", dev->name); @@ -3896,7 +3937,7 @@ /*------------------------------------------------------------------*/ /* - * Sometimes, netwave_detach can't be performed following a call from + * Sometimes, wavelan_detach can't be performed following a call from * cardmgr (device still open, pcmcia_release not done) and the device * is put in a STALE_LINK state and remains in memory. * @@ -3970,7 +4011,19 @@ lp = (net_local *) dev->priv; base = dev->base_addr; - spin_lock (&lp->lock); +#ifdef DEBUG_INTERRUPT_INFO + /* Check state of our spinlock (it should be cleared) */ + if(spin_is_locked(&lp->spinlock)) + printk(KERN_DEBUG + "%s: wavelan_interrupt(): spinlock is already locked !!!\n", + dev->name); +#endif + + /* Prevent reentrancy. We need to do that because we may have + * multiple interrupt handler running concurently. + * It is safe because wv_splhi() disable interrupts before aquiring + * the spinlock. */ + spin_lock(&lp->spinlock); /* Treat all pending interrupts */ while(1) @@ -4015,8 +4068,6 @@ break; } - lp->status = status0; /* Save current status (for commands) */ - /* ----------------- RECEIVING PACKET ----------------- */ /* * When the wavelan signal the reception of a new packet, @@ -4054,22 +4105,6 @@ * Most likely : transmission done */ - /* If we are already waiting elsewhere for the command to complete */ - if(wv_wait_completed) - { -#ifdef DEBUG_INTERRUPT_INFO - printk(KERN_DEBUG "%s: wv_interrupt(): command completed\n", - dev->name); -#endif - - /* Signal command completion */ - wv_wait_completed = 0; - - /* Acknowledge the interrupt */ - outb(CR0_INT_ACK | OP0_NOP, LCCR(base)); - continue; - } - /* If a transmission has been done */ if((status0 & SR0_EVENT_MASK) == SR0_TRANSMIT_DONE || (status0 & SR0_EVENT_MASK) == SR0_RETRANSMIT_DONE || @@ -4081,10 +4116,6 @@ dev->name); #endif - /* If watchdog was activated, kill it ! */ - if(timer_pending(&lp->watchdog)) - del_timer(&lp->watchdog); - /* Get transmission status */ tx_status = inb(LCSR(base)); tx_status |= (inb(LCSR(base)) << 8); @@ -4174,7 +4205,7 @@ lp->stats.collisions += (tx_status & TX_NCOL_MASK); lp->stats.tx_packets++; - netif_wake_queue (dev); + netif_wake_queue(dev); outb(CR0_INT_ACK | OP0_NOP, LCCR(base)); /* Acknowledge the interrupt */ } else /* if interrupt = transmit done or retransmit done */ @@ -4185,9 +4216,9 @@ #endif outb(CR0_INT_ACK | OP0_NOP, LCCR(base)); /* Acknowledge the interrupt */ } - } + } /* while(1) */ - spin_unlock_irq (&lp->lock); + spin_unlock(&lp->spinlock); #ifdef DEBUG_INTERRUPT_TRACE printk(KERN_DEBUG "%s: <-wavelan_interrupt()\n", dev->name); @@ -4196,30 +4227,23 @@ /*------------------------------------------------------------------*/ /* - * Watchdog : when we start a transmission, we set a timer in the - * kernel. If the transmission complete, this timer is disabled. If - * it expire, it try to unlock the hardware. + * Watchdog: when we start a transmission, a timer is set for us in the + * kernel. If the transmission completes, this timer is disabled. If + * the timer expires, we are called and we try to unlock the hardware. * - * Note : this watchdog doesn't work on the same principle as the - * watchdog in the ISA driver. I make it this way because the overhead - * of add_timer() and del_timer() is nothing and that it avoid calling - * the watchdog, saving some CPU... If you want to apply the same - * watchdog to the ISA driver, you should be a bit carefull, because - * of the many transmit buffers... - * This watchdog is also move clever, it try to abort the current - * command before reseting everything... + * Note : This watchdog is move clever than the one in the ISA driver, + * because it try to abort the current command before reseting + * everything... + * On the other hand, it's a bit simpler, because we don't have to + * deal with the multiple Tx buffers... */ static void -wavelan_watchdog(u_long a) +wavelan_watchdog(device * dev) { - device * dev; - net_local * lp; - ioaddr_t base; - int spin; - - dev = (device *) a; - base = dev->base_addr; - lp = (net_local *) dev->priv; + net_local * lp = (net_local *) dev->priv; + ioaddr_t base = dev->base_addr; + unsigned long flags; + int aborted = FALSE; #ifdef DEBUG_INTERRUPT_TRACE printk(KERN_DEBUG "%s: ->wavelan_watchdog()\n", dev->name); @@ -4230,21 +4254,21 @@ dev->name); #endif - /* We are waiting for command completion */ - wv_wait_completed = TRUE; + wv_splhi(lp, &flags); /* Ask to abort the current command */ outb(OP0_ABORT, LCCR(base)); - /* Busy wait while the LAN controller executes the command. - * Note : wv_wait_completed should be volatile */ - spin = 0; - while(wv_wait_completed && (spin++ < 250)) - udelay(10); - - /* If the interrupt handler hasn't be called or invalid status */ - if((wv_wait_completed) || - ((lp->status & SR0_EVENT_MASK) != SR0_EXECUTION_ABORTED)) + /* Wait for the end of the command (a bit hackish) */ + if(wv_82593_cmd(dev, "wavelan_watchdog(): abort", + OP0_NOP | CR0_STATUS_3, SR0_EXECUTION_ABORTED)) + aborted = TRUE; + + /* Release spinlock here so that wv_hw_reset() can grab it */ + wv_splx(lp, &flags); + + /* Check if we were successful in aborting it */ + if(!aborted) { /* It seem that it wasn't enough */ #ifdef DEBUG_INTERRUPT_ERROR @@ -4269,7 +4293,7 @@ #endif /* We are no more waiting for something... */ - netif_start_queue (dev); + netif_wake_queue(dev); #ifdef DEBUG_INTERRUPT_TRACE printk(KERN_DEBUG "%s: <-wavelan_watchdog()\n", dev->name); @@ -4322,7 +4346,7 @@ return FALSE; if(!wv_ru_start(dev)) wv_hw_reset(dev); /* If problem : reset */ - netif_start_queue (dev); + netif_start_queue(dev); /* Mark the device as used */ link->open++; @@ -4348,7 +4372,6 @@ wavelan_close(device * dev) { dev_link_t * link = ((net_local *) dev->priv)->link; - net_local * lp = (net_local *)dev->priv; ioaddr_t base = dev->base_addr; #ifdef DEBUG_CALLBACK_TRACE @@ -4356,8 +4379,6 @@ (unsigned int) dev); #endif - netif_stop_queue (dev); - /* If the device isn't open, then nothing to do */ if(!link->open) { @@ -4373,17 +4394,13 @@ wv_roam_cleanup(dev); #endif /* WAVELAN_ROAMING */ - /* If watchdog was activated, kill it ! */ - if(timer_pending(&lp->watchdog)) - del_timer(&lp->watchdog); - link->open--; MOD_DEC_USE_COUNT; /* If the card is still present */ - if (netif_device_present(dev)) + if(netif_running(dev)) { - netif_stop_queue (dev); + netif_stop_queue(dev); /* Stop receiving new messages and wait end of transmission */ wv_ru_stop(dev); @@ -4404,21 +4421,6 @@ /*------------------------------------------------------------------*/ /* - * We never need to do anything when a wavelan device is "initialized" - * by the net software, because we only register already-found cards. - */ -static int -wavelan_init(device * dev) -{ -#ifdef DEBUG_CALLBACK_TRACE - printk(KERN_DEBUG "<>wavelan_init()\n"); -#endif - - return(0); -} - -/*------------------------------------------------------------------*/ -/* * wavelan_attach() creates an "instance" of the driver, allocating * local data structures for one device (one interface). The device * is registered with Card Services. @@ -4445,24 +4447,8 @@ /* Initialize the dev_link_t structure */ link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); - if (!link) - return NULL; - - /* Allocate the generic data structure */ - dev = kmalloc(sizeof(struct net_device), GFP_KERNEL); - if (!dev) - goto fail_alloc_dev; - - /* Allocate the wavelan-specific data structure. */ - lp = (net_local *) kmalloc(sizeof(net_local), GFP_KERNEL); - if (!lp) - goto fail_alloc_dev_priv; - - memset(lp, 0, sizeof(net_local)); + if (!link) return NULL; memset(link, 0, sizeof(struct dev_link_t)); - memset(dev, 0, sizeof(struct net_device)); - - dev->priv = lp; /* Unused for the Wavelan */ link->release.function = &wv_pcmcia_release; @@ -4492,18 +4478,35 @@ link->next = dev_list; dev_list = link; + /* Allocate the generic data structure */ + dev = kmalloc(sizeof(struct net_device), GFP_KERNEL); + if (!dev) { + kfree(link); + return NULL; + } + memset(dev, 0x00, sizeof(struct net_device)); link->priv = link->irq.Instance = dev; + /* Allocate the wavelan-specific data structure. */ + dev->priv = lp = (net_local *) kmalloc(sizeof(net_local), GFP_KERNEL); + if (!lp) { + kfree(link); + kfree(dev); + return NULL; + } + memset(lp, 0x00, sizeof(net_local)); + /* Init specific data */ - wv_wait_completed = 0; - lp->status = FALSE; lp->configured = 0; lp->reconfig_82593 = FALSE; lp->nresets = 0; + /* Multicast stuff */ + lp->promiscuous = 0; + lp->allmulticast = 0; + lp->mc_count = 0; - /* Set the watchdog timer */ - lp->watchdog.function = wavelan_watchdog; - lp->watchdog.data = (unsigned long) dev; + /* Init spinlock */ + spin_lock_init(&lp->spinlock); /* back links */ lp->link = link; @@ -4513,7 +4516,6 @@ ether_setup(dev); /* wavelan NET3 callbacks */ - dev->init = &wavelan_init; dev->open = &wavelan_open; dev->stop = &wavelan_close; dev->hard_start_xmit = &wavelan_packet_xmit; @@ -4523,14 +4525,16 @@ dev->set_mac_address = &wavelan_set_mac_address; #endif /* SET_MAC_ADDRESS */ + /* Set the watchdog timer */ + dev->tx_timeout = &wavelan_watchdog; + dev->watchdog_timeo = WATCHDOG_JIFFIES; + #ifdef WIRELESS_EXT /* If wireless extension exist in the kernel */ dev->do_ioctl = wavelan_ioctl; /* wireless extensions */ dev->get_wireless_stats = wavelan_get_wireless_stats; #endif /* Other specific data */ - strcpy(dev->name, ((net_local *)dev->priv)->node.dev_name); - netif_start_queue (dev); dev->mtu = WAVELAN_MTU; /* Register with Card Services */ @@ -4562,12 +4566,6 @@ #endif return link; - -fail_alloc_dev_priv: - kfree(dev); -fail_alloc_dev: - kfree(link); - return NULL; } /*------------------------------------------------------------------*/ @@ -4698,7 +4696,7 @@ if(link->state & DEV_CONFIG) { /* Accept no more transmissions */ - netif_device_detach(dev); + netif_device_detach(dev); /* Release the card */ wv_pcmcia_release((u_long) link); @@ -4720,7 +4718,7 @@ * obliged to close nicely the wavelan here. David, could you * close the device before suspending them ? And, by the way, * could you, on resume, add a "route add -net ..." after the - * ifconfig up XXX Thanks... */ + * ifconfig up ? Thanks... */ /* Stop receiving new messages and wait end of transmission */ wv_ru_stop(dev); @@ -4735,8 +4733,7 @@ if(link->state & DEV_CONFIG) { if(link->open) - netif_device_detach(dev); - + netif_device_detach(dev); CardServices(ReleaseConfiguration, link->handle); } break; @@ -4748,7 +4745,7 @@ if(link->state & DEV_CONFIG) { CardServices(RequestConfiguration, link->handle, &link->conf); - if(link->open) /* If RESET -> True, If RESUME -> False XXX */ + if(link->open) /* If RESET -> True, If RESUME -> False ? */ { wv_hw_reset(dev); netif_device_attach(dev); @@ -4838,4 +4835,3 @@ module_init(init_wavelan_cs); module_exit(exit_wavelan_cs); -MODULE_LICENSE("Dual BSD/GPL"); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/net/pcmcia/wavelan_cs.h linux.19rc3-ac4/drivers/net/pcmcia/wavelan_cs.h --- linux.19rc3/drivers/net/pcmcia/wavelan_cs.h 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/net/pcmcia/wavelan_cs.h 2002-07-29 17:29:11.000000000 +0100 @@ -34,6 +34,25 @@ * I try to maintain a web page with the Wireless LAN Howto at : * http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Wavelan.html * + * SMP + * --- + * We now are SMP compliant (I eventually fixed the remaining bugs). + * The driver has been tested on a dual P6-150 and survived my usual + * set of torture tests. + * Anyway, I spent enough time chasing interrupt re-entrancy during + * errors or reconfigure, and I designed the locked/unlocked sections + * of the driver with great care, and with the recent addition of + * the spinlock (thanks to the new API), we should be quite close to + * the truth. + * The SMP/IRQ locking is quite coarse and conservative (i.e. not fast), + * but better safe than sorry (especially at 2 Mb/s ;-). + * + * I have also looked into disabling only our interrupt on the card + * (via HACR) instead of all interrupts in the processor (via cli), + * so that other driver are not impacted, and it look like it's + * possible, but it's very tricky to do right (full of races). As + * the gain would be mostly for SMP systems, it can wait... + * * Debugging and options * --------------------- * You will find below a set of '#define" allowing a very fine control @@ -122,7 +141,7 @@ * Yunzhou Li finished is work. * Joe Finney patched the driver to start * correctly 2.00 cards (2.4 GHz with frequency selection). - * David Hinds integrated the whole in his + * David Hinds integrated the whole in his * Pcmcia package (+ bug corrections). * * I (Jean Tourrilhes - jt@hplb.hpl.hp.com) then started to make some @@ -158,8 +177,8 @@ * * This software was originally developed under Linux 1.2.3 * (Slackware 2.0 distribution). - * And then under Linux 2.0.x (Debian 1.1 - pcmcia 2.8.18-23) with - * HP OmniBook 4000 & 5500. + * And then under Linux 2.0.x (Debian 1.1 -> 2.2 - pcmcia 2.8.18+) + * with an HP OmniBook 4000 and then a 5500. * * It is based on other device drivers and information either written * or supplied by: @@ -174,7 +193,7 @@ * Matthew Geier (matthew@cs.su.oz.au), * Remo di Giovanni (remo@cs.su.oz.au), * Mark Hagan (mhagan@wtcpost.daytonoh.NCR.COM), - * David Hinds , + * David Hinds , * Jan Hoogendoorn (c/o marteijn@lucent.com), * Bruce Janson , * Anthony D. Joseph , @@ -349,6 +368,32 @@ * - Fix check for root permission (break instead of exit) * - New nwid & encoding setting (Wireless Extension 9) * + * Changes made for release in 3.1.12 : + * ---------------------------------- + * - reworked wv_82593_cmd to avoid using the IRQ handler and doing + * ugly things with interrupts. + * - Add IRQ protection in 82593_config/ru_start/ru_stop/watchdog + * - Update to new network API (softnet - 2.3.43) : + * o replace dev->tbusy (David + me) + * o replace dev->tstart (David + me) + * o remove dev->interrupt (David) + * o add SMP locking via spinlock in splxx (me) + * o add spinlock in interrupt handler (me) + * o use kernel watchdog instead of ours (me) + * o verify that all the changes make sense and work (me) + * - Re-sync kernel/pcmcia versions (not much actually) + * - A few other cleanups (David & me)... + * + * Changes made for release in 3.1.22 : + * ---------------------------------- + * - Check that SMP works, remove annoying log message + * + * Changes made for release in 3.1.24 : + * ---------------------------------- + * - Fix unfrequent card lockup when watchdog was reseting the hardware : + * o control first busy loop in wv_82593_cmd() + * o Extend spinlock protection in wv_hw_config() + * * Wishes & dreams: * ---------------- * - Cleanup and integrate the roaming code @@ -368,6 +413,7 @@ #include #include #include +#include #include #include #include @@ -384,7 +430,7 @@ #ifdef CONFIG_NET_PCMCIA_RADIO #include /* Wireless extensions */ -#endif /* CONFIG_NET_PCMCIA_RADIO */ +#endif /* Pcmcia headers that we need */ #include @@ -437,7 +483,7 @@ #undef DEBUG_RX_INFO /* Header of the transmitted packet */ #undef DEBUG_RX_FAIL /* Normal failure conditions */ #define DEBUG_RX_ERROR /* Unexpected conditions */ -#undef DEBUG_PACKET_DUMP /* Dump packet on the screen */ +#undef DEBUG_PACKET_DUMP 32 /* Dump packet on the screen */ #undef DEBUG_IOCTL_TRACE /* Misc call by Linux */ #undef DEBUG_IOCTL_INFO /* Various debug info */ #define DEBUG_IOCTL_ERROR /* What's going wrong */ @@ -452,7 +498,7 @@ /************************ CONSTANTS & MACROS ************************/ #ifdef DEBUG_VERSION_SHOW -static const char *version = "wavelan_cs.c : v21 (wireless extensions) 18/10/99\n"; +static const char *version = "wavelan_cs.c : v23 (SMP + wireless extensions) 20/12/00\n"; #endif /* Watchdog temporisation */ @@ -557,9 +603,9 @@ */ struct net_local { - spinlock_t lock; dev_node_t node; /* ???? What is this stuff ???? */ device * dev; /* Reverse link... */ + spinlock_t spinlock; /* Serialize access to the hardware (SMP) */ dev_link_t * link; /* pcmcia structure */ en_stats stats; /* Ethernet interface statistics */ int nresets; /* Number of hw resets */ @@ -568,9 +614,7 @@ u_char promiscuous; /* Promiscuous mode */ u_char allmulticast; /* All Multicast mode */ int mc_count; /* Number of multicast addresses */ - timer_list watchdog; /* To avoid blocking state */ - u_char status; /* Current i82593 status */ int stop; /* Current i82593 Stop Hit Register */ int rfp; /* Last DMA machine receive pointer */ int overrunning; /* Receiver overrun flag */ @@ -617,8 +661,14 @@ #endif /* WAVELAN_ROAMING */ /* ----------------------- MISC SUBROUTINES ------------------------ */ +static inline void + wv_splhi(net_local *, /* Disable interrupts */ + unsigned long *); /* flags */ +static inline void + wv_splx(net_local *, /* ReEnable interrupts */ + unsigned long *); /* flags */ static void - cs_error(client_handle_t, /* Report error to cardmgr */ + cs_error(client_handle_t, /* Report error to cardmgr */ int, int); /* ----------------- MODEM MANAGEMENT SUBROUTINES ----------------- */ @@ -722,16 +772,15 @@ wv_flush_stale_links(void); /* "detach" all possible devices */ /* ---------------------- INTERRUPT HANDLING ---------------------- */ static void -wavelan_interrupt(int, /* Interrupt handler */ - void *, - struct pt_regs *); + wavelan_interrupt(int, /* Interrupt handler */ + void *, + struct pt_regs *); static void - wavelan_watchdog(u_long); /* Transmission watchdog */ + wavelan_watchdog(device *); /* Transmission watchdog */ /* ------------------- CONFIGURATION CALLBACKS ------------------- */ static int wavelan_open(device *), /* Open the device */ - wavelan_close(device *), /* Close the device */ - wavelan_init(device *); /* Do nothing */ + wavelan_close(device *); /* Close the device */ static dev_link_t * wavelan_attach(void); /* Create a new device */ static void @@ -744,11 +793,7 @@ /**************************** VARIABLES ****************************/ static dev_info_t dev_info = "wavelan_cs"; -static dev_link_t *dev_list; /* Linked list of devices */ - -/* WARNING : the following variable MUST be volatile - * It is used by wv_82593_cmd to syncronise with wavelan_interrupt */ -static volatile int wv_wait_completed; +static dev_link_t *dev_list = NULL; /* Linked list of devices */ /* * Parameters that can be set with 'insmod' @@ -761,7 +806,7 @@ static int irq_list[4] = { -1 }; /* Shared memory speed, in ns */ -static int mem_speed; +static int mem_speed = 0; /* New module interface */ MODULE_PARM(irq_mask, "i"); @@ -770,9 +815,11 @@ #ifdef WAVELAN_ROAMING /* Conditional compile, see above in options */ /* Enable roaming mode ? No ! Please keep this to 0 */ -static int do_roaming; +static int do_roaming = 0; MODULE_PARM(do_roaming, "i"); #endif /* WAVELAN_ROAMING */ +MODULE_LICENSE("GPL"); + #endif /* WAVELAN_CS_H */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/net/pcnet32.c linux.19rc3-ac4/drivers/net/pcnet32.c --- linux.19rc3/drivers/net/pcnet32.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/net/pcnet32.c 2002-07-29 13:58:42.000000000 +0100 @@ -543,7 +543,7 @@ /* initialize variables */ fdx = mii = fset = dxsuflo = ltint = 0; chip_version = (chip_version >> 12) & 0xffff; - + switch (chip_version) { case 0x2420: chipname = "PCnet/PCI 79C970"; /* PCI */ @@ -1175,19 +1175,12 @@ if (err_status & 0x04000000) lp->stats.tx_aborted_errors++; if (err_status & 0x08000000) lp->stats.tx_carrier_errors++; if (err_status & 0x10000000) lp->stats.tx_window_errors++; -#ifndef DO_DXSUFLO if (err_status & 0x40000000) { lp->stats.tx_fifo_errors++; - /* Ackk! On FIFO errors the Tx unit is turned off! */ - /* Remove this verbosity later! */ - printk(KERN_ERR "%s: Tx FIFO error! CSR0=%4.4x\n", - dev->name, csr0); - must_restart = 1; - } -#else - if (err_status & 0x40000000) { - lp->stats.tx_fifo_errors++; - if (! lp->dxsuflo) { /* If controller doesn't recover ... */ +#ifdef DO_DXSUFLO + if (! lp->dxsuflo) +#endif + { /* If controller doesn't recover ... */ /* Ackk! On FIFO errors the Tx unit is turned off! */ /* Remove this verbosity later! */ printk(KERN_ERR "%s: Tx FIFO error! CSR0=%4.4x\n", @@ -1195,7 +1188,6 @@ must_restart = 1; } } -#endif } else { if (status & 0x1800) lp->stats.collisions++; @@ -1722,12 +1714,13 @@ } } + module_init(pcnet32_init_module); module_exit(pcnet32_cleanup_module); /* * Local variables: - * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c pcnet32.c" + * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include/linux -Wall -Wstrict-prototypes -O2 -m486 -c pcnet32.c" * c-indent-level: 4 * tab-width: 8 * End: diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/net/ppp_deflate.c linux.19rc3-ac4/drivers/net/ppp_deflate.c --- linux.19rc3/drivers/net/ppp_deflate.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/net/ppp_deflate.c 2002-07-29 13:58:42.000000000 +0100 @@ -39,7 +39,7 @@ #include #include -#include "zlib.c" +#include /* * State for a Deflate (de)compressor. @@ -56,10 +56,6 @@ #define DEFLATE_OVHD 2 /* Deflate overhead/packet */ -static void *zalloc __P((void *, unsigned int items, unsigned int size)); -static void *zalloc_init __P((void *, unsigned int items, - unsigned int size)); -static void zfree __P((void *, void *ptr)); static void *z_comp_alloc __P((unsigned char *options, int opt_len)); static void *z_decomp_alloc __P((unsigned char *options, int opt_len)); static void z_comp_free __P((void *state)); @@ -80,72 +76,6 @@ static void z_decomp_reset __P((void *state)); static void z_comp_stats __P((void *state, struct compstat *stats)); -struct chunk_header { - int valloced; /* allocated with valloc, not kmalloc */ - int guard; /* check for overwritten header */ -}; - -#define GUARD_MAGIC 0x77a8011a -#define MIN_VMALLOC 2048 /* use kmalloc for blocks < this */ - -/* - * Space allocation and freeing routines for use by zlib routines. - */ -void -zfree(arg, ptr) - void *arg; - void *ptr; -{ - struct chunk_header *hdr = ((struct chunk_header *)ptr) - 1; - - if (hdr->guard != GUARD_MAGIC) { - printk(KERN_WARNING "zfree: header corrupted (%x %x) at %p\n", - hdr->valloced, hdr->guard, hdr); - return; - } - if (hdr->valloced) - vfree(hdr); - else - kfree(hdr); -} - -void * -zalloc(arg, items, size) - void *arg; - unsigned int items, size; -{ - struct chunk_header *hdr; - unsigned nbytes; - - nbytes = items * size + sizeof(*hdr); - hdr = kmalloc(nbytes, GFP_ATOMIC); - if (hdr == 0) - return 0; - hdr->valloced = 0; - hdr->guard = GUARD_MAGIC; - return (void *) (hdr + 1); -} - -void * -zalloc_init(arg, items, size) - void *arg; - unsigned int items, size; -{ - struct chunk_header *hdr; - unsigned nbytes; - - nbytes = items * size + sizeof(*hdr); - if (nbytes >= MIN_VMALLOC) - hdr = vmalloc(nbytes); - else - hdr = kmalloc(nbytes, GFP_KERNEL); - if (hdr == 0) - return 0; - hdr->valloced = nbytes >= MIN_VMALLOC; - hdr->guard = GUARD_MAGIC; - return (void *) (hdr + 1); -} - static void z_comp_free(arg) void *arg; @@ -153,7 +83,9 @@ struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg; if (state) { - deflateEnd(&state->strm); + zlib_deflateEnd(&state->strm); + if (state->strm.workspace) + vfree(state->strm.workspace); kfree(state); MOD_DEC_USE_COUNT; } @@ -180,27 +112,27 @@ if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE) return NULL; - state = (struct ppp_deflate_state *) kmalloc(sizeof(*state), GFP_KERNEL); + state = (struct ppp_deflate_state *) kmalloc(sizeof(*state), + GFP_KERNEL); if (state == NULL) return NULL; MOD_INC_USE_COUNT; memset (state, 0, sizeof (struct ppp_deflate_state)); - state->strm.next_in = NULL; - state->strm.zalloc = zalloc_init; - state->strm.zfree = zfree; - state->w_size = w_size; + state->strm.next_in = NULL; + state->w_size = w_size; + state->strm.workspace = vmalloc(zlib_deflate_workspacesize()); + if (state->strm.workspace == NULL) + goto out_free; - if (deflateInit2(&state->strm, Z_DEFAULT_COMPRESSION, + if (zlib_deflateInit2(&state->strm, Z_DEFAULT_COMPRESSION, DEFLATE_METHOD_VAL, -w_size, 8, Z_DEFAULT_STRATEGY) != Z_OK) goto out_free; - state->strm.zalloc = zalloc; return (void *) state; out_free: z_comp_free(state); - MOD_DEC_USE_COUNT; return NULL; } @@ -224,7 +156,7 @@ state->unit = unit; state->debug = debug; - deflateReset(&state->strm); + zlib_deflateReset(&state->strm); return 1; } @@ -236,7 +168,7 @@ struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg; state->seqno = 0; - deflateReset(&state->strm); + zlib_deflateReset(&state->strm); } int @@ -286,7 +218,7 @@ state->strm.avail_in = (isize - off); for (;;) { - r = deflate(&state->strm, Z_PACKET_FLUSH); + r = zlib_deflate(&state->strm, Z_PACKET_FLUSH); if (r != Z_OK) { if (state->debug) printk(KERN_ERR @@ -337,7 +269,9 @@ struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg; if (state) { - inflateEnd(&state->strm); + zlib_inflateEnd(&state->strm); + if (state->strm.workspace) + kfree(state->strm.workspace); kfree(state); MOD_DEC_USE_COUNT; } @@ -370,19 +304,19 @@ MOD_INC_USE_COUNT; memset (state, 0, sizeof (struct ppp_deflate_state)); - state->w_size = w_size; - state->strm.next_out = NULL; - state->strm.zalloc = zalloc_init; - state->strm.zfree = zfree; + state->w_size = w_size; + state->strm.next_out = NULL; + state->strm.workspace = kmalloc(zlib_inflate_workspacesize(), + GFP_KERNEL); + if (state->strm.workspace == NULL) + goto out_free; - if (inflateInit2(&state->strm, -w_size) != Z_OK) + if (zlib_inflateInit2(&state->strm, -w_size) != Z_OK) goto out_free; - state->strm.zalloc = zalloc; return (void *) state; out_free: z_decomp_free(state); - MOD_DEC_USE_COUNT; return NULL; } @@ -407,7 +341,7 @@ state->debug = debug; state->mru = mru; - inflateReset(&state->strm); + zlib_inflateReset(&state->strm); return 1; } @@ -419,7 +353,7 @@ struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg; state->seqno = 0; - inflateReset(&state->strm); + zlib_inflateReset(&state->strm); } /* @@ -492,7 +426,7 @@ * Call inflate, supplying more input or output as needed. */ for (;;) { - r = inflate(&state->strm, Z_PACKET_FLUSH); + r = zlib_inflate(&state->strm, Z_PACKET_FLUSH); if (r != Z_OK) { if (state->debug) printk(KERN_DEBUG "z_decompress%d: inflate returned %d (%s)\n", @@ -575,7 +509,7 @@ ++state->strm.avail_in; } - r = inflateIncomp(&state->strm); + r = zlib_inflateIncomp(&state->strm); if (r != Z_OK) { /* gak! */ if (state->debug) { diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/net/slip.c linux.19rc3-ac4/drivers/net/slip.c --- linux.19rc3/drivers/net/slip.c 2002-07-29 12:49:56.000000000 +0100 +++ linux.19rc3-ac4/drivers/net/slip.c 2002-07-29 13:58:42.000000000 +0100 @@ -1393,10 +1393,8 @@ /* First of all: check for active disciplines and hangup them. */ do { - if (busy) { - current->counter = 0; - schedule(); - } + if (busy) + sys_sched_yield(); busy = 0; local_bh_disable(); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/net/smc-ultra32.c linux.19rc3-ac4/drivers/net/smc-ultra32.c --- linux.19rc3/drivers/net/smc-ultra32.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/net/smc-ultra32.c 2002-07-29 17:11:55.000000000 +0100 @@ -320,9 +320,11 @@ /* Select correct 8KB Window. */ outb(ei_status.reg0 | ((ring_page & 0x60) >> 5), RamReg); -#ifdef notdef +#ifdef __BIG_ENDIAN /* Officially this is what we are doing, but the readl() is faster */ + /* unfortunately it isn't endian aware of the struct */ isa_memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr)); + hdr->count = le16_to_cpu(hdr->count); #else ((unsigned int*)hdr)[0] = isa_readl(hdr_start); #endif diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/net/smc-ultra.c linux.19rc3-ac4/drivers/net/smc-ultra.c --- linux.19rc3/drivers/net/smc-ultra.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/net/smc-ultra.c 2002-07-29 17:11:55.000000000 +0100 @@ -383,9 +383,11 @@ unsigned long hdr_start = dev->mem_start + ((ring_page - START_PG)<<8); outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET); /* shmem on */ -#ifdef notdef +#ifdef __BIG_ENDIAN /* Officially this is what we are doing, but the readl() is faster */ + /* unfortunately it isn't endian aware of the struct */ isa_memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr)); + hdr->count = le16_to_cpu(hdr->count); #else ((unsigned int*)hdr)[0] = isa_readl(hdr_start); #endif diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/net/tulip/eeprom.c linux.19rc3-ac4/drivers/net/tulip/eeprom.c --- linux.19rc3/drivers/net/tulip/eeprom.c 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/net/tulip/eeprom.c 2002-07-29 17:12:05.000000000 +0100 @@ -136,6 +136,48 @@ subsequent_board: if (ee_data[27] == 0) { /* No valid media table. */ +#ifdef __hppa__ + /* + * HSC-PCI cards don't have a standard srom, + * but we need to setup a fake mediatable + * for a correct csr12 setup and mii handling + */ + if (ee_data[0] == 0x3c && ee_data[1] == 0x10 && /* sub vendor id */ + ee_data[2] == 0x63 && ee_data[3] == 0x10) { /* sub device id */ + static unsigned char leafdata[] = + { 0x01, /* phy number */ + 0x02, /* gpr setup sequence length */ + 0x02, 0x00, /* gpr setup sequence */ + 0x02, /* phy reset sequence length */ + 0x01, 0x00, /* phy reset sequence */ + 0x00, 0x78, /* media capabilities */ + 0x00, 0xe0, /* nway advertisment */ + 0x00, 0x05, /* fdx bit map */ + 0x00, 0x06 /* ttm bit map */ + }; + struct mediatable *mtable; + + mtable = (struct mediatable *) + kmalloc(sizeof(struct mediatable) + sizeof(struct medialeaf), + GFP_KERNEL); + if (mtable == NULL) + return; /* Horrible, impossible failure. */ + + tp->mtable = mtable; + mtable->defaultmedia = 0x800; + mtable->leafcount = 1; + mtable->csr12dir = 0x3f; /* inputs on bit7 for hsc-pci, bit6 for pci-fx */ + mtable->has_nonmii = 0; + mtable->has_reset = 0; + mtable->has_mii = 1; + mtable->csr15dir = mtable->csr15val = 0; + mtable->mleaf[0].type = 1; + mtable->mleaf[0].media = 11; + mtable->mleaf[0].leafdata = &leafdata[0]; + tp->flags |= HAS_PHY_IRQ; + tp->csr12_shadow = -1; + } +#endif } else if (tp->chip_id == DC21041) { unsigned char *p = (void *)ee_data + ee_data[27 + controller_index*3]; int media = get_u16(p); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/net/tulip/interrupt.c linux.19rc3-ac4/drivers/net/tulip/interrupt.c --- linux.19rc3/drivers/net/tulip/interrupt.c 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/net/tulip/interrupt.c 2002-07-29 17:14:44.000000000 +0100 @@ -291,6 +291,23 @@ #endif } +static inline void phy_interrupt (struct net_device *dev, struct tulip_private *tp, long ioaddr) +{ + int csr12; + + csr12 = inl(ioaddr + CSR12) & 0xff; + if (csr12 != tp->csr12_shadow) { + /* ack interrupt */ + outl(csr12 | 0x02, ioaddr + CSR12); + tp->csr12_shadow = csr12; + /* do link change stuff */ + spin_lock(&tp->lock); + tulip_check_duplex(dev); + spin_unlock(&tp->lock); + /* clear irq ack bit */ + outl(csr12 & ~0x02, ioaddr + CSR12); + } +} /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ @@ -313,6 +330,10 @@ /* Let's see whether the interrupt really is for us */ csr5 = inl(ioaddr + CSR5); + + if (tp->flags & HAS_PHY_IRQ) + phy_interrupt (dev, tp, ioaddr); + if ((csr5 & (NormalIntr|AbnormalIntr)) == 0) return; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/net/tulip/media.c linux.19rc3-ac4/drivers/net/tulip/media.c --- linux.19rc3/drivers/net/tulip/media.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/net/tulip/media.c 2002-07-29 17:12:05.000000000 +0100 @@ -284,6 +284,10 @@ for (i = 0; i < init_length; i++) outl(init_sequence[i], ioaddr + CSR12); } + + inl(ioaddr + CSR6); /* flush posted writes */ + udelay(500); + tmp_info = get_u16(&misc_info[1]); if (tmp_info) tp->advertising[phy_num] = tmp_info | 1; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/net/tulip/tulip.h linux.19rc3-ac4/drivers/net/tulip/tulip.h --- linux.19rc3/drivers/net/tulip/tulip.h 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/net/tulip/tulip.h 2002-07-29 17:29:11.000000000 +0100 @@ -63,6 +63,7 @@ HAS_8023X = 0x0400, COMET_MAC_ADDR = 0x0800, HAS_PCI_MWI = 0x1000, + HAS_PHY_IRQ = 0x2000, }; @@ -387,7 +388,8 @@ int susp_rx; unsigned long nir; unsigned long base_addr; - int pad0, pad1; /* Used for 8-byte alignment */ + int csr12_shadow; + int pad1; /* Used for 8-byte alignment */ }; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/net/via-rhine.c linux.19rc3-ac4/drivers/net/via-rhine.c --- linux.19rc3/drivers/net/via-rhine.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/net/via-rhine.c 2002-07-29 13:58:42.000000000 +0100 @@ -93,6 +93,10 @@ - transmit frame queue message is off by one - fixed - adds IntrNormalSummary to "Something Wicked" exclusion list so normal interrupts will not trigger the message (src: Donald Becker) + (Roger Luethi) + - show confused chip where to continue after Tx error + - location of collision counter is chip specific + - allow selecting backoff algorithm (module parameter) */ @@ -111,6 +115,9 @@ Setting to > 1518 effectively disables this feature. */ static int rx_copybreak; +/* Select a backoff algorithm (Ethernet capture effect) */ +static int backoff; + /* Used to pass the media type, etc. Both 'options[]' and 'full_duplex[]' should exist for driver interoperability. @@ -213,11 +220,13 @@ MODULE_PARM(max_interrupt_work, "i"); MODULE_PARM(debug, "i"); MODULE_PARM(rx_copybreak, "i"); +MODULE_PARM(backoff, "i"); MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM_DESC(max_interrupt_work, "VIA Rhine maximum events handled per interrupt"); MODULE_PARM_DESC(debug, "VIA Rhine debug level (0-7)"); MODULE_PARM_DESC(rx_copybreak, "VIA Rhine copy breakpoint for copy-only-tiny-frames"); +MODULE_PARM_DESC(backoff, "VIA Rhine: Bits 0-3: backoff algorithm"); MODULE_PARM_DESC(options, "VIA Rhine: Bits 0-3: media type, bit 17: full duplex"); MODULE_PARM_DESC(full_duplex, "VIA Rhine full duplex setting(s) (1)"); @@ -234,7 +243,8 @@ Boards with this chip are functional only in a bus-master PCI slot. Many operational settings are loaded from the EEPROM to the Config word at -offset 0x78. This driver assumes that they are correct. +offset 0x78. For most of these settings, this driver assumes that they are +correct. If this driver is compiled to use PCI memory space operations the EEPROM must be configured to enable memory ops. @@ -386,9 +396,10 @@ StickyHW=0x83, WOLcrClr=0xA4, WOLcgClr=0xA7, PwrcsrClr=0xAC, }; -/* Bits in ConfigD (select backoff algorithm (Ethernet capture effect)) */ +/* Bits in ConfigD */ enum backoff_bits { - BackOpt=0x01, BackAMD=0x02, BackDEC=0x04, BackRandom=0x08 + BackOptional=0x01, BackModify=0x02, + BackCaptureEffect=0x04, BackRandom=0x08 }; #ifdef USE_MEM @@ -402,7 +413,7 @@ /* Bits in the interrupt status/mask registers. */ enum intr_status_bits { IntrRxDone=0x0001, IntrRxErr=0x0004, IntrRxEmpty=0x0020, - IntrTxDone=0x0002, IntrTxAbort=0x0008, IntrTxUnderrun=0x0010, + IntrTxDone=0x0002, IntrTxError=0x0008, IntrTxUnderrun=0x0010, IntrPCIErr=0x0040, IntrStatsMax=0x0080, IntrRxEarly=0x0100, IntrMIIChange=0x0200, IntrRxOverflow=0x0400, IntrRxDropped=0x0800, IntrRxNoBuf=0x1000, @@ -428,24 +439,27 @@ /* The Rx and Tx buffer descriptors. */ struct rx_desc { s32 rx_status; - u32 desc_length; + u32 desc_length; /* Chain flag, Buffer/frame length */ u32 addr; u32 next_desc; }; struct tx_desc { s32 tx_status; - u32 desc_length; + u32 desc_length; /* Chain flag, Tx Config, Frame length */ u32 addr; u32 next_desc; }; +/* Initial value for tx_desc.desc_length, Buffer size goes to bits 0-10 */ +#define TXDESC 0x00e08000 + enum rx_status_bits { RxOK=0x8000, RxWholePkt=0x0300, RxErr=0x008F }; -/* Bits in *_desc.status */ +/* Bits in *_desc.*_status */ enum desc_status_bits { - DescOwn=0x80000000, DescEndPacket=0x4000, DescIntr=0x1000, + DescOwn=0x80000000 }; /* Bits in ChipCmd. */ @@ -517,6 +531,7 @@ static int via_rhine_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static int via_rhine_close(struct net_device *dev); static inline void clear_tally_counters(long ioaddr); +static inline void via_restart_tx(struct net_device *dev); static void wait_for_reset(struct net_device *dev, int chip_id, char *name) { @@ -703,6 +718,11 @@ writeb(readb(ioaddr + ConfigA) & 0xFE, ioaddr + ConfigA); } + /* Select backoff algorithm */ + if (backoff) + writeb(readb(ioaddr + ConfigD) & (0xF0 | backoff), + ioaddr + ConfigD); + dev->irq = pdev->irq; np = dev->priv; @@ -937,7 +957,7 @@ for (i = 0; i < TX_RING_SIZE; i++) { np->tx_skbuff[i] = 0; np->tx_ring[i].tx_status = 0; - np->tx_ring[i].desc_length = cpu_to_le32(0x00e08000); + np->tx_ring[i].desc_length = cpu_to_le32(TXDESC); next += sizeof(struct tx_desc); np->tx_ring[i].next_desc = cpu_to_le32(next); np->tx_buf[i] = &np->tx_bufs[i * PKT_BUF_SZ]; @@ -953,7 +973,7 @@ for (i = 0; i < TX_RING_SIZE; i++) { np->tx_ring[i].tx_status = 0; - np->tx_ring[i].desc_length = cpu_to_le32(0x00e08000); + np->tx_ring[i].desc_length = cpu_to_le32(TXDESC); np->tx_ring[i].addr = cpu_to_le32(0xBADF00D0); /* An invalid address. */ if (np->tx_skbuff[i]) { if (np->tx_skbuff_dma[i]) { @@ -978,7 +998,7 @@ writeb(dev->dev_addr[i], ioaddr + StationAddr + i); /* Initialize other registers. */ - writew(0x0006, ioaddr + PCIBusConfig); /* Store & forward */ + writew(0x0006, ioaddr + PCIBusConfig); /* Tune configuration??? */ /* Configure initial FIFO thresholds. */ writeb(0x20, ioaddr + TxConfig); np->tx_thresh = 0x20; @@ -993,8 +1013,9 @@ via_rhine_set_rx_mode(dev); /* Enable interrupts by setting the interrupt mask. */ - writew(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow| IntrRxDropped| - IntrTxDone | IntrTxAbort | IntrTxUnderrun | + writew(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow | + IntrRxDropped | IntrRxNoBuf | IntrTxAborted | + IntrTxDone | IntrTxError | IntrTxUnderrun | IntrPCIErr | IntrStatsMax | IntrLinkChange | IntrMIIChange, ioaddr + IntrEnable); @@ -1237,7 +1258,7 @@ } np->tx_ring[entry].desc_length = - cpu_to_le32(0x00E08000 | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN)); + cpu_to_le32(TXDESC | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN)); /* lock eth irq */ spin_lock_irq (&np->lock); @@ -1289,13 +1310,14 @@ IntrRxWakeUp | IntrRxEmpty | IntrRxNoBuf)) via_rhine_rx(dev); - if (intr_status & (IntrTxDone | IntrTxAbort | IntrTxUnderrun | + if (intr_status & (IntrTxDone | IntrTxError | IntrTxUnderrun | IntrTxAborted)) via_rhine_tx(dev); /* Abnormal error summary/uncommon events handlers. */ if (intr_status & (IntrPCIErr | IntrLinkChange | IntrMIIChange | - IntrStatsMax | IntrTxAbort | IntrTxUnderrun)) + IntrStatsMax | IntrTxError | IntrTxAborted | + IntrTxUnderrun)) via_rhine_error(dev, intr_status); if (--boguscnt < 0) { @@ -1307,7 +1329,7 @@ } if (debug > 3) - printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n", + printk(KERN_DEBUG "%s: exiting interrupt, status=%4.4x.\n", dev->name, readw(ioaddr + IntrStatus)); } @@ -1323,11 +1345,11 @@ /* find and cleanup dirty tx descriptors */ while (np->dirty_tx != np->cur_tx) { txstatus = le32_to_cpu(np->tx_ring[entry].tx_status); - if (txstatus & DescOwn) - break; if (debug > 6) printk(KERN_DEBUG " Tx scavenge %d status %8.8x.\n", entry, txstatus); + if (txstatus & DescOwn) + break; if (txstatus & 0x8000) { if (debug > 1) printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", @@ -1337,10 +1359,22 @@ if (txstatus & 0x0200) np->stats.tx_window_errors++; if (txstatus & 0x0100) np->stats.tx_aborted_errors++; if (txstatus & 0x0080) np->stats.tx_heartbeat_errors++; - if (txstatus & 0x0002) np->stats.tx_fifo_errors++; + if (((np->chip_id == VT86C100A) && txstatus & 0x0002) || + (txstatus & 0x0800) || (txstatus & 0x1000)) { + np->stats.tx_fifo_errors++; + np->tx_ring[entry].tx_status = cpu_to_le32(DescOwn); + break; /* Keep the skb - we try again */ + } /* Transmitter restarted in 'abnormal' handler. */ } else { - np->stats.collisions += (txstatus >> 3) & 15; + if (np->chip_id == VT86C100A) + np->stats.collisions += (txstatus >> 3) & 0x0F; + else + np->stats.collisions += txstatus & 0x0F; + if (debug > 6) + printk(KERN_DEBUG "collisions: %1.1x:%1.1x\n", + (txstatus >> 3) & 0xF, + txstatus & 0xF); np->stats.tx_bytes += np->tx_skbuff[entry]->len; np->stats.tx_packets++; } @@ -1476,6 +1510,17 @@ writew(CmdRxDemand | np->chip_cmd, dev->base_addr + ChipCmd); } +static inline void via_restart_tx(struct net_device *dev) { + struct netdev_private *np = dev->priv; + int entry = np->dirty_tx % TX_RING_SIZE; + + /* We know better than the chip where it should continue */ + writel(np->tx_ring_dma + entry * sizeof(struct tx_desc), + dev->base_addr + TxRingPtr); + + writew(CmdTxDemand | np->chip_cmd, dev->base_addr + ChipCmd); +} + static void via_rhine_error(struct net_device *dev, int intr_status) { struct netdev_private *np = dev->priv; @@ -1501,19 +1546,23 @@ np->stats.rx_missed_errors += readw(ioaddr + RxMissed); clear_tally_counters(ioaddr); } - if (intr_status & IntrTxAbort) { - /* Stats counted in Tx-done handler, just restart Tx. */ - writew(CmdTxDemand | np->chip_cmd, dev->base_addr + ChipCmd); + if (intr_status & IntrTxError) { + if (debug > 1) + printk(KERN_INFO "%s: Abort %4.4x, frame dropped.\n", + dev->name, intr_status); + via_restart_tx(dev); } if (intr_status & IntrTxUnderrun) { if (np->tx_thresh < 0xE0) writeb(np->tx_thresh += 0x20, ioaddr + TxConfig); if (debug > 1) - printk(KERN_INFO "%s: Transmitter underrun, increasing Tx " - "threshold setting to %2.2x.\n", dev->name, np->tx_thresh); + printk(KERN_INFO "%s: Transmitter underrun, Tx " + "threshold now %2.2x.\n", + dev->name, np->tx_thresh); + via_restart_tx(dev); } if (intr_status & ~( IntrLinkChange | IntrStatsMax | - IntrTxAbort | IntrTxAborted | IntrNormalSummary)) { + IntrTxError | IntrTxAborted | IntrNormalSummary)) { if (debug > 1) printk(KERN_ERR "%s: Something Wicked happened! %4.4x.\n", dev->name, intr_status); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/net/wan/8253x/sab8253xds.txt linux.19rc3-ac4/drivers/net/wan/8253x/sab8253xds.txt --- linux.19rc3/drivers/net/wan/8253x/sab8253xds.txt 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/net/wan/8253x/sab8253xds.txt 2002-07-29 13:58:42.000000000 +0100 @@ -92,7 +92,7 @@ -*ln ^Ös /home/martillo/kernel/linux-2.4.3/include/asm-i386 +*ln –s /home/martillo/kernel/linux-2.4.3/include/asm-i386 /home/martillo/kernel/linux-2.4.3/include/asm* * * @@ -101,12 +101,12 @@ * * -*ln ^Ös /home/martillo/kernel/linux-2.4.6/include/asm-i386 +*ln –s /home/martillo/kernel/linux-2.4.6/include/asm-i386 /home/martillo/kernel/linux-2.4.6/include/asm* * * -*ln ^Ös / /frolix * +*ln –s / /frolix * @@ -173,7 +173,7 @@ From a shell window: -*xemacs ^Öe shell&* +*xemacs –e shell&* @@ -854,7 +854,7 @@ -patch ^Öp1 < /{directory-patch}//8253x.patch +patch –p1 < /{directory-patch}//8253x.patch @@ -1051,7 +1051,7 @@ - The ASLX driver is designed to be a ^Óplug-and-play^Ô driver as far as + The ASLX driver is designed to be a “plug-and-play” driver as far as possible. If it is built as a dynamically loadable module, the user (or relevant system configuration file) invokes /insmod /to load the ASLX.o file. @@ -1169,7 +1169,7 @@ -cu ^Öl /dev/ttyS{n} ^Ös 9600 +cu –l /dev/ttyS{n} –s 9600 @@ -1281,7 +1281,7 @@ -cu ^Öl /dev/sttyS{n} ^Ös 9600 +cu –l /dev/sttyS{n} –s 9600 @@ -1289,7 +1289,7 @@ -8253xcfg /dev/sttyS? ^Ön 64 152 0 4 0 140 15 +8253xcfg /dev/sttyS? –n 64 152 0 4 0 140 15 @@ -1658,7 +1658,7 @@ The 8253xcfg command provides access to images of the channel control, mode and baud rate generator registers of the serial port that is specified by the minor device number (port number = minor device number -^Ö minor_start) of the TTY device (either synchronous, asynchronous or +– minor_start) of the TTY device (either synchronous, asynchronous or callout) specified on the command line by which 8253xcfg is invoked. The next time the port is initialized (usually on the first open after every process that currently has the port open has closed it) these @@ -2691,37 +2691,37 @@ -1. SAB_BOARD structure ^Ö driver specific +1. SAB_BOARD structure – driver specific -2. SAB_CHIP structure ^Ö driver specific +2. SAB_CHIP structure – driver specific -3. SAB_PORT structure ^Ö driver specific +3. SAB_PORT structure – driver specific -4. AURA_CIM structure ^Ö driver specific (actually specific to the +4. AURA_CIM structure – driver specific (actually specific to the multichannel server) -5. RING_DESCRIPTOR ^Ö used by all the driver functionalities in the +5. RING_DESCRIPTOR – used by all the driver functionalities in the transmission of data. -6. DCONTROL2 ^Ö used by all the driver functionalities in managing +6. DCONTROL2 – used by all the driver functionalities in managing the transmission of data. -7. struct sk_buff_head ^Ö two buffer lists are associated with the +7. struct sk_buff_head – two buffer lists are associated with the SAB_PORT structure are used to track all the sk_buffs that are currently in use at each port. -8. struct tty_struct ^Ö one per port, standard structure by which +8. struct tty_struct – one per port, standard structure by which the TTY driver access low level routines for either asynchronous TTY, synchronous TTY and callout functionality. The SAB_PORT serves as the private data structure associated with each 8253x TTY, which on a given open can instantiate itself as a synchronous TTY, an asynchronous TTY or as a call out device. -9. struct net_device ^Ö one per port, standard network device +9. struct net_device – one per port, standard network device structure. The SAB_PORT serves as the private data structure associated with each 8253x network interface. -10. struct file_operations ^Ö one per port, standard character device +10. struct file_operations – one per port, standard character device structure. The SAB_PORT serves as the private data structure associated with each 8253x character interface. diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/net/wan/8253x/sab8253xfs.txt linux.19rc3-ac4/drivers/net/wan/8253x/sab8253xfs.txt --- linux.19rc3/drivers/net/wan/8253x/sab8253xfs.txt 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/net/wan/8253x/sab8253xfs.txt 2002-07-29 13:58:42.000000000 +0100 @@ -44,7 +44,7 @@ to the driver. The ASLX driver will automatically correct incorrectly programmed adapter card or Multichannel server serial EEPROMs. Moreover, in addition to the primary serial communications interface, -the ASLX driver provides a ^Ómaintenance^Ô interface to the serial EEPROMs +the ASLX driver provides a “maintenance” interface to the serial EEPROMs so that user intervention can correct an incorrectly programmed EEPROM. @@ -336,7 +336,7 @@ -Synchronous TTYs act just like asynchronous TTYs (e.g., getty^Òs may be +Synchronous TTYs act just like asynchronous TTYs (e.g., getty’s may be associated with them, and a user may invoke cu on them) in so far as possible (to wit, break processing is not possible on a synchronous TTY). @@ -536,7 +536,7 @@ In a sense, the synchronous character device implements an emulation of -Solaris putmsg/getmsg functionality for Aurora^Òs synchronous serial +Solaris putmsg/getmsg functionality for Aurora’s synchronous serial device. The availability of such emulation should help the portation of applications from Solaris to a Linux platform that uses Aurora hardware and software. @@ -586,7 +586,7 @@ Linux is not capable of registering an interrupt handler for each port -separately (when there are many ports ^Ö the specialty of Aurora +separately (when there are many ports – the specialty of Aurora hardware), and such an approach would have lower performance than having a single interrupt handler that polled the ports. In any case, interrupt status registers associated with the Aurora hardware often diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/net/wd.c linux.19rc3-ac4/drivers/net/wd.c --- linux.19rc3/drivers/net/wd.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/net/wd.c 2002-07-29 17:15:05.000000000 +0100 @@ -365,9 +365,11 @@ if (ei_status.word16) outb(ISA16 | ei_status.reg5, wd_cmdreg+WD_CMDREG5); -#ifdef notdef +#ifdef __BIG_ENDIAN /* Officially this is what we are doing, but the readl() is faster */ + /* unfortunately it isn't endian aware of the struct */ isa_memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr)); + hdr->count = le16_to_cpu(hdr->count); #else ((unsigned int*)hdr)[0] = isa_readl(hdr_start); #endif diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/net/zlib.c linux.19rc3-ac4/drivers/net/zlib.c --- linux.19rc3/drivers/net/zlib.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/net/zlib.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,5376 +0,0 @@ -/* - * This file is derived from various .h and .c files from the zlib-1.0.4 - * distribution by Jean-loup Gailly and Mark Adler, with some additions - * by Paul Mackerras to aid in implementing Deflate compression and - * decompression for PPP packets. See zlib.h for conditions of - * distribution and use. - * - * Changes that have been made include: - * - added Z_PACKET_FLUSH (see zlib.h for details) - * - added inflateIncomp and deflateOutputPending - * - allow strm->next_out to be NULL, meaning discard the output - * - * $Id: zlib.c,v 1.3 1997/12/23 10:47:42 paulus Exp $ - */ - -/* - * ==FILEVERSION 20020318== - * - * This marker is used by the Linux installation script to determine - * whether an up-to-date version of this file is already installed. - */ - -#define NO_DUMMY_DECL -#define NO_ZCFUNCS -#define MY_ZCALLOC - -#if defined(__FreeBSD__) && (defined(KERNEL) || defined(_KERNEL)) -#define inflate inflate_ppp /* FreeBSD already has an inflate :-( */ -#endif - - -/* +++ zutil.h */ -/* zutil.h -- internal interface and configuration of the compression library - * Copyright (C) 1995-1996 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* From: zutil.h,v 1.16 1996/07/24 13:41:13 me Exp $ */ - -#ifndef _Z_UTIL_H -#define _Z_UTIL_H - -#include "zlib.h" - -#if defined(KERNEL) || defined(_KERNEL) -/* Assume this is a *BSD or SVR4 kernel */ -#include -#include -#include -# define HAVE_MEMCPY -# define memcpy(d, s, n) bcopy((s), (d), (n)) -# define memset(d, v, n) bzero((d), (n)) -# define memcmp bcmp - -#else -#if defined(__KERNEL__) -/* Assume this is a Linux kernel */ -#include -#define HAVE_MEMCPY - -#else /* not kernel */ - -#if defined(MSDOS)||defined(VMS)||defined(CRAY)||defined(WIN32)||defined(RISCOS) -# include -# include -#else - extern int errno; -#endif -#ifdef STDC -# include -# include -#endif -#endif /* __KERNEL__ */ -#endif /* _KERNEL || KERNEL */ - -#ifndef local -# define local static -#endif -/* compile with -Dlocal if your debugger can't find static symbols */ - -typedef unsigned char uch; -typedef uch FAR uchf; -typedef unsigned short ush; -typedef ush FAR ushf; -typedef unsigned long ulg; - -extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */ -/* (size given to avoid silly warnings with Visual C++) */ - -#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] - -#define ERR_RETURN(strm,err) \ - return (strm->msg = (char*)ERR_MSG(err), (err)) -/* To be used only when the state is known to be valid */ - - /* common constants */ - -#ifndef DEF_WBITS -# define DEF_WBITS MAX_WBITS -#endif -/* default windowBits for decompression. MAX_WBITS is for compression only */ - -#if MAX_MEM_LEVEL >= 8 -# define DEF_MEM_LEVEL 8 -#else -# define DEF_MEM_LEVEL MAX_MEM_LEVEL -#endif -/* default memLevel */ - -#define STORED_BLOCK 0 -#define STATIC_TREES 1 -#define DYN_TREES 2 -/* The three kinds of block type */ - -#define MIN_MATCH 3 -#define MAX_MATCH 258 -/* The minimum and maximum match lengths */ - -#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ - - /* target dependencies */ - -#ifdef MSDOS -# define OS_CODE 0x00 -# ifdef __TURBOC__ -# include -# else /* MSC or DJGPP */ -# include -# endif -#endif - -#ifdef OS2 -# define OS_CODE 0x06 -#endif - -#ifdef WIN32 /* Window 95 & Windows NT */ -# define OS_CODE 0x0b -#endif - -#if defined(VAXC) || defined(VMS) -# define OS_CODE 0x02 -# define FOPEN(name, mode) \ - fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") -#endif - -#ifdef AMIGA -# define OS_CODE 0x01 -#endif - -#if defined(ATARI) || defined(atarist) -# define OS_CODE 0x05 -#endif - -#ifdef MACOS -# define OS_CODE 0x07 -#endif - -#ifdef __50SERIES /* Prime/PRIMOS */ -# define OS_CODE 0x0F -#endif - -#ifdef TOPS20 -# define OS_CODE 0x0a -#endif - -#if defined(_BEOS_) || defined(RISCOS) -# define fdopen(fd,mode) NULL /* No fdopen() */ -#endif - - /* Common defaults */ - -#ifndef OS_CODE -# define OS_CODE 0x03 /* assume Unix */ -#endif - -#ifndef FOPEN -# define FOPEN(name, mode) fopen((name), (mode)) -#endif - - /* functions */ - -#ifdef HAVE_STRERROR - extern char *strerror OF((int)); -# define zstrerror(errnum) strerror(errnum) -#else -# define zstrerror(errnum) "" -#endif - -#if defined(pyr) -# define NO_MEMCPY -#endif -#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(_MSC_VER) - /* Use our own functions for small and medium model with MSC <= 5.0. - * You may have to use the same strategy for Borland C (untested). - */ -# define NO_MEMCPY -#endif -#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) -# define HAVE_MEMCPY -#endif -#ifdef HAVE_MEMCPY -# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ -# define zmemcpy _fmemcpy -# define zmemcmp _fmemcmp -# define zmemzero(dest, len) _fmemset(dest, 0, len) -# else -# define zmemcpy memcpy -# define zmemcmp memcmp -# define zmemzero(dest, len) memset(dest, 0, len) -# endif -#else - extern void zmemcpy OF((Bytef* dest, Bytef* source, uInt len)); - extern int zmemcmp OF((Bytef* s1, Bytef* s2, uInt len)); - extern void zmemzero OF((Bytef* dest, uInt len)); -#endif - -/* Diagnostic functions */ -#ifdef DEBUG_ZLIB -# include -# ifndef verbose -# define verbose 0 -# endif - extern void z_error OF((char *m)); -# define Assert(cond,msg) {if(!(cond)) z_error(msg);} -# define Trace(x) fprintf x -# define Tracev(x) {if (verbose) fprintf x ;} -# define Tracevv(x) {if (verbose>1) fprintf x ;} -# define Tracec(c,x) {if (verbose && (c)) fprintf x ;} -# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} -#else -# define Assert(cond,msg) -# define Trace(x) -# define Tracev(x) -# define Tracevv(x) -# define Tracec(c,x) -# define Tracecv(c,x) -#endif - - -typedef uLong (*check_func) OF((uLong check, const Bytef *buf, uInt len)); - -voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); -void zcfree OF((voidpf opaque, voidpf ptr)); - -#define ZALLOC(strm, items, size) \ - (*((strm)->zalloc))((strm)->opaque, (items), (size)) -#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) -#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} - -#endif /* _Z_UTIL_H */ -/* --- zutil.h */ - -/* +++ deflate.h */ -/* deflate.h -- internal compression state - * Copyright (C) 1995-1996 Jean-loup Gailly - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* From: deflate.h,v 1.10 1996/07/02 12:41:00 me Exp $ */ - -#ifndef _DEFLATE_H -#define _DEFLATE_H - -/* #include "zutil.h" */ - -/* =========================================================================== - * Internal compression state. - */ - -#define LENGTH_CODES 29 -/* number of length codes, not counting the special END_BLOCK code */ - -#define LITERALS 256 -/* number of literal bytes 0..255 */ - -#define L_CODES (LITERALS+1+LENGTH_CODES) -/* number of Literal or Length codes, including the END_BLOCK code */ - -#define D_CODES 30 -/* number of distance codes */ - -#define BL_CODES 19 -/* number of codes used to transfer the bit lengths */ - -#define HEAP_SIZE (2*L_CODES+1) -/* maximum heap size */ - -#define MAX_BITS 15 -/* All codes must not exceed MAX_BITS bits */ - -#define INIT_STATE 42 -#define BUSY_STATE 113 -#define FINISH_STATE 666 -/* Stream status */ - - -/* Data structure describing a single value and its code string. */ -typedef struct ct_data_s { - union { - ush freq; /* frequency count */ - ush code; /* bit string */ - } fc; - union { - ush dad; /* father node in Huffman tree */ - ush len; /* length of bit string */ - } dl; -} FAR ct_data; - -#define Freq fc.freq -#define Code fc.code -#define Dad dl.dad -#define Len dl.len - -typedef struct static_tree_desc_s static_tree_desc; - -typedef struct tree_desc_s { - ct_data *dyn_tree; /* the dynamic tree */ - int max_code; /* largest code with non zero frequency */ - static_tree_desc *stat_desc; /* the corresponding static tree */ -} FAR tree_desc; - -typedef ush Pos; -typedef Pos FAR Posf; -typedef unsigned IPos; - -/* A Pos is an index in the character window. We use short instead of int to - * save space in the various tables. IPos is used only for parameter passing. - */ - -typedef struct deflate_state { - z_streamp strm; /* pointer back to this zlib stream */ - int status; /* as the name implies */ - Bytef *pending_buf; /* output still pending */ - ulg pending_buf_size; /* size of pending_buf */ - Bytef *pending_out; /* next pending byte to output to the stream */ - int pending; /* nb of bytes in the pending buffer */ - int noheader; /* suppress zlib header and adler32 */ - Byte data_type; /* UNKNOWN, BINARY or ASCII */ - Byte method; /* STORED (for zip only) or DEFLATED */ - int last_flush; /* value of flush param for previous deflate call */ - - /* used by deflate.c: */ - - uInt w_size; /* LZ77 window size (32K by default) */ - uInt w_bits; /* log2(w_size) (8..16) */ - uInt w_mask; /* w_size - 1 */ - - Bytef *window; - /* Sliding window. Input bytes are read into the second half of the window, - * and move to the first half later to keep a dictionary of at least wSize - * bytes. With this organization, matches are limited to a distance of - * wSize-MAX_MATCH bytes, but this ensures that IO is always - * performed with a length multiple of the block size. Also, it limits - * the window size to 64K, which is quite useful on MSDOS. - * To do: use the user input buffer as sliding window. - */ - - ulg window_size; - /* Actual size of window: 2*wSize, except when the user input buffer - * is directly used as sliding window. - */ - - Posf *prev; - /* Link to older string with same hash index. To limit the size of this - * array to 64K, this link is maintained only for the last 32K strings. - * An index in this array is thus a window index modulo 32K. - */ - - Posf *head; /* Heads of the hash chains or NIL. */ - - uInt ins_h; /* hash index of string to be inserted */ - uInt hash_size; /* number of elements in hash table */ - uInt hash_bits; /* log2(hash_size) */ - uInt hash_mask; /* hash_size-1 */ - - uInt hash_shift; - /* Number of bits by which ins_h must be shifted at each input - * step. It must be such that after MIN_MATCH steps, the oldest - * byte no longer takes part in the hash key, that is: - * hash_shift * MIN_MATCH >= hash_bits - */ - - long block_start; - /* Window position at the beginning of the current output block. Gets - * negative when the window is moved backwards. - */ - - uInt match_length; /* length of best match */ - IPos prev_match; /* previous match */ - int match_available; /* set if previous match exists */ - uInt strstart; /* start of string to insert */ - uInt match_start; /* start of matching string */ - uInt lookahead; /* number of valid bytes ahead in window */ - - uInt prev_length; - /* Length of the best match at previous step. Matches not greater than this - * are discarded. This is used in the lazy match evaluation. - */ - - uInt max_chain_length; - /* To speed up deflation, hash chains are never searched beyond this - * length. A higher limit improves compression ratio but degrades the - * speed. - */ - - uInt max_lazy_match; - /* Attempt to find a better match only when the current match is strictly - * smaller than this value. This mechanism is used only for compression - * levels >= 4. - */ -# define max_insert_length max_lazy_match - /* Insert new strings in the hash table only if the match length is not - * greater than this length. This saves time but degrades compression. - * max_insert_length is used only for compression levels <= 3. - */ - - int level; /* compression level (1..9) */ - int strategy; /* favor or force Huffman coding*/ - - uInt good_match; - /* Use a faster search when the previous match is longer than this */ - - int nice_match; /* Stop searching when current match exceeds this */ - - /* used by trees.c: */ - /* Didn't use ct_data typedef below to suppress compiler warning */ - struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ - struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ - struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ - - struct tree_desc_s l_desc; /* desc. for literal tree */ - struct tree_desc_s d_desc; /* desc. for distance tree */ - struct tree_desc_s bl_desc; /* desc. for bit length tree */ - - ush bl_count[MAX_BITS+1]; - /* number of codes at each bit length for an optimal tree */ - - int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ - int heap_len; /* number of elements in the heap */ - int heap_max; /* element of largest frequency */ - /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. - * The same heap array is used to build all trees. - */ - - uch depth[2*L_CODES+1]; - /* Depth of each subtree used as tie breaker for trees of equal frequency - */ - - uchf *l_buf; /* buffer for literals or lengths */ - - uInt lit_bufsize; - /* Size of match buffer for literals/lengths. There are 4 reasons for - * limiting lit_bufsize to 64K: - * - frequencies can be kept in 16 bit counters - * - if compression is not successful for the first block, all input - * data is still in the window so we can still emit a stored block even - * when input comes from standard input. (This can also be done for - * all blocks if lit_bufsize is not greater than 32K.) - * - if compression is not successful for a file smaller than 64K, we can - * even emit a stored file instead of a stored block (saving 5 bytes). - * This is applicable only for zip (not gzip or zlib). - * - creating new Huffman trees less frequently may not provide fast - * adaptation to changes in the input data statistics. (Take for - * example a binary file with poorly compressible code followed by - * a highly compressible string table.) Smaller buffer sizes give - * fast adaptation but have of course the overhead of transmitting - * trees more frequently. - * - I can't count above 4 - */ - - uInt last_lit; /* running index in l_buf */ - - ushf *d_buf; - /* Buffer for distances. To simplify the code, d_buf and l_buf have - * the same number of elements. To use different lengths, an extra flag - * array would be necessary. - */ - - ulg opt_len; /* bit length of current block with optimal trees */ - ulg static_len; /* bit length of current block with static trees */ - ulg compressed_len; /* total bit length of compressed file */ - uInt matches; /* number of string matches in current block */ - int last_eob_len; /* bit length of EOB code for last block */ - -#ifdef DEBUG_ZLIB - ulg bits_sent; /* bit length of the compressed data */ -#endif - - ush bi_buf; - /* Output buffer. bits are inserted starting at the bottom (least - * significant bits). - */ - int bi_valid; - /* Number of valid bits in bi_buf. All bits above the last valid bit - * are always zero. - */ - -} FAR deflate_state; - -/* Output a byte on the stream. - * IN assertion: there is enough room in pending_buf. - */ -#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} - - -#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) -/* Minimum amount of lookahead, except at the end of the input file. - * See deflate.c for comments about the MIN_MATCH+1. - */ - -#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) -/* In order to simplify the code, particularly on 16 bit machines, match - * distances are limited to MAX_DIST instead of WSIZE. - */ - - /* in trees.c */ -void _tr_init OF((deflate_state *s)); -int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); -ulg _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, - int eof)); -void _tr_align OF((deflate_state *s)); -void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, - int eof)); -void _tr_stored_type_only OF((deflate_state *)); - -#endif -/* --- deflate.h */ - -/* +++ deflate.c */ -/* deflate.c -- compress data using the deflation algorithm - * Copyright (C) 1995-1996 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * ALGORITHM - * - * The "deflation" process depends on being able to identify portions - * of the input text which are identical to earlier input (within a - * sliding window trailing behind the input currently being processed). - * - * The most straightforward technique turns out to be the fastest for - * most input files: try all possible matches and select the longest. - * The key feature of this algorithm is that insertions into the string - * dictionary are very simple and thus fast, and deletions are avoided - * completely. Insertions are performed at each input character, whereas - * string matches are performed only when the previous match ends. So it - * is preferable to spend more time in matches to allow very fast string - * insertions and avoid deletions. The matching algorithm for small - * strings is inspired from that of Rabin & Karp. A brute force approach - * is used to find longer strings when a small match has been found. - * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze - * (by Leonid Broukhis). - * A previous version of this file used a more sophisticated algorithm - * (by Fiala and Greene) which is guaranteed to run in linear amortized - * time, but has a larger average cost, uses more memory and is patented. - * However the F&G algorithm may be faster for some highly redundant - * files if the parameter max_chain_length (described below) is too large. - * - * ACKNOWLEDGEMENTS - * - * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and - * I found it in 'freeze' written by Leonid Broukhis. - * Thanks to many people for bug reports and testing. - * - * REFERENCES - * - * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". - * Available in ftp://ds.internic.net/rfc/rfc1951.txt - * - * A description of the Rabin and Karp algorithm is given in the book - * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. - * - * Fiala,E.R., and Greene,D.H. - * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 - * - */ - -/* From: deflate.c,v 1.15 1996/07/24 13:40:58 me Exp $ */ - -/* #include "deflate.h" */ - -char deflate_copyright[] = " deflate 1.0.4 Copyright 1995-1996 Jean-loup Gailly "; -/* - If you use the zlib library in a product, an acknowledgment is welcome - in the documentation of your product. If for some reason you cannot - include such an acknowledgment, I would appreciate that you keep this - copyright string in the executable of your product. - */ - -/* =========================================================================== - * Function prototypes. - */ -typedef enum { - need_more, /* block not completed, need more input or more output */ - block_done, /* block flush performed */ - finish_started, /* finish started, need only more output at next deflate */ - finish_done /* finish done, accept no more input or output */ -} block_state; - -typedef block_state (*compress_func) OF((deflate_state *s, int flush)); -/* Compression function. Returns the block state after the call. */ - -local void fill_window OF((deflate_state *s)); -local block_state deflate_stored OF((deflate_state *s, int flush)); -local block_state deflate_fast OF((deflate_state *s, int flush)); -local block_state deflate_slow OF((deflate_state *s, int flush)); -local void lm_init OF((deflate_state *s)); -local void putShortMSB OF((deflate_state *s, uInt b)); -local void flush_pending OF((z_streamp strm)); -local int read_buf OF((z_streamp strm, charf *buf, unsigned size)); -#ifdef ASMV - void match_init OF((void)); /* asm code initialization */ - uInt longest_match OF((deflate_state *s, IPos cur_match)); -#else -local uInt longest_match OF((deflate_state *s, IPos cur_match)); -#endif - -#ifdef DEBUG_ZLIB -local void check_match OF((deflate_state *s, IPos start, IPos match, - int length)); -#endif - -/* =========================================================================== - * Local data - */ - -#define NIL 0 -/* Tail of hash chains */ - -#ifndef TOO_FAR -# define TOO_FAR 4096 -#endif -/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ - -#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) -/* Minimum amount of lookahead, except at the end of the input file. - * See deflate.c for comments about the MIN_MATCH+1. - */ - -/* Values for max_lazy_match, good_match and max_chain_length, depending on - * the desired pack level (0..9). The values given below have been tuned to - * exclude worst case performance for pathological files. Better values may be - * found for specific files. - */ -typedef struct config_s { - ush good_length; /* reduce lazy search above this match length */ - ush max_lazy; /* do not perform lazy search above this match length */ - ush nice_length; /* quit search above this match length */ - ush max_chain; - compress_func func; -} config; - -local config configuration_table[10] = { -/* good lazy nice chain */ -/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ -/* 1 */ {4, 4, 8, 4, deflate_fast}, /* maximum speed, no lazy matches */ -/* 2 */ {4, 5, 16, 8, deflate_fast}, -/* 3 */ {4, 6, 32, 32, deflate_fast}, - -/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ -/* 5 */ {8, 16, 32, 32, deflate_slow}, -/* 6 */ {8, 16, 128, 128, deflate_slow}, -/* 7 */ {8, 32, 128, 256, deflate_slow}, -/* 8 */ {32, 128, 258, 1024, deflate_slow}, -/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* maximum compression */ - -/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 - * For deflate_fast() (levels <= 3) good is ignored and lazy has a different - * meaning. - */ - -#define EQUAL 0 -/* result of memcmp for equal strings */ - -#ifndef NO_DUMMY_DECL -struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ -#endif - -/* =========================================================================== - * Update a hash value with the given input byte - * IN assertion: all calls to UPDATE_HASH are made with consecutive - * input characters, so that a running hash key can be computed from the - * previous key instead of complete recalculation each time. - */ -#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) - - -/* =========================================================================== - * Insert string str in the dictionary and set match_head to the previous head - * of the hash chain (the most recent string with same hash key). Return - * the previous length of the hash chain. - * IN assertion: all calls to INSERT_STRING are made with consecutive - * input characters and the first MIN_MATCH bytes of str are valid - * (except for the last MIN_MATCH-1 bytes of the input file). - */ -#define INSERT_STRING(s, str, match_head) \ - (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ - s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \ - s->head[s->ins_h] = (Pos)(str)) - -/* =========================================================================== - * Initialize the hash table (avoiding 64K overflow for 16 bit systems). - * prev[] will be initialized on the fly. - */ -#define CLEAR_HASH(s) \ - s->head[s->hash_size-1] = NIL; \ - zmemzero((charf *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); - -/* ========================================================================= */ -int deflateInit_(strm, level, version, stream_size) - z_streamp strm; - int level; - const char *version; - int stream_size; -{ - return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, - Z_DEFAULT_STRATEGY, version, stream_size); - /* To do: ignore strm->next_in if we use it as window */ -} - -/* ========================================================================= */ -int deflateInit2_(strm, level, method, windowBits, memLevel, strategy, - version, stream_size) - z_streamp strm; - int level; - int method; - int windowBits; - int memLevel; - int strategy; - const char *version; - int stream_size; -{ - deflate_state *s; - int noheader = 0; - static char* my_version = ZLIB_VERSION; - - ushf *overlay; - /* We overlay pending_buf and d_buf+l_buf. This works since the average - * output size for (length,distance) codes is <= 24 bits. - */ - - if (version == Z_NULL || version[0] != my_version[0] || - stream_size != sizeof(z_stream)) { - return Z_VERSION_ERROR; - } - if (strm == Z_NULL) return Z_STREAM_ERROR; - - strm->msg = Z_NULL; -#ifndef NO_ZCFUNCS - if (strm->zalloc == Z_NULL) { - strm->zalloc = zcalloc; - strm->opaque = (voidpf)0; - } - if (strm->zfree == Z_NULL) strm->zfree = zcfree; -#endif - - if (level == Z_DEFAULT_COMPRESSION) level = 6; - - if (windowBits < 0) { /* undocumented feature: suppress zlib header */ - noheader = 1; - windowBits = -windowBits; - } - if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || - windowBits < 9 || windowBits > 15 || level < 0 || level > 9 || - strategy < 0 || strategy > Z_HUFFMAN_ONLY) { - return Z_STREAM_ERROR; - } - s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); - if (s == Z_NULL) return Z_MEM_ERROR; - strm->state = (struct internal_state FAR *)s; - s->strm = strm; - - s->noheader = noheader; - s->w_bits = windowBits; - s->w_size = 1 << s->w_bits; - s->w_mask = s->w_size - 1; - - s->hash_bits = memLevel + 7; - s->hash_size = 1 << s->hash_bits; - s->hash_mask = s->hash_size - 1; - s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); - - s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); - s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); - s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); - - s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ - - overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); - s->pending_buf = (uchf *) overlay; - s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); - - if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || - s->pending_buf == Z_NULL) { - strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); - deflateEnd (strm); - return Z_MEM_ERROR; - } - s->d_buf = overlay + s->lit_bufsize/sizeof(ush); - s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; - - s->level = level; - s->strategy = strategy; - s->method = (Byte)method; - - return deflateReset(strm); -} - -/* ========================================================================= */ -int deflateSetDictionary (strm, dictionary, dictLength) - z_streamp strm; - const Bytef *dictionary; - uInt dictLength; -{ - deflate_state *s; - uInt length = dictLength; - uInt n; - IPos hash_head = 0; - - if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL) - return Z_STREAM_ERROR; - - s = (deflate_state *) strm->state; - if (s->status != INIT_STATE) return Z_STREAM_ERROR; - - strm->adler = adler32(strm->adler, dictionary, dictLength); - - if (length < MIN_MATCH) return Z_OK; - if (length > MAX_DIST(s)) { - length = MAX_DIST(s); -#ifndef USE_DICT_HEAD - dictionary += dictLength - length; /* use the tail of the dictionary */ -#endif - } - zmemcpy((charf *)s->window, dictionary, length); - s->strstart = length; - s->block_start = (long)length; - - /* Insert all strings in the hash table (except for the last two bytes). - * s->lookahead stays null, so s->ins_h will be recomputed at the next - * call of fill_window. - */ - s->ins_h = s->window[0]; - UPDATE_HASH(s, s->ins_h, s->window[1]); - for (n = 0; n <= length - MIN_MATCH; n++) { - INSERT_STRING(s, n, hash_head); - } - if (hash_head) hash_head = 0; /* to make compiler happy */ - return Z_OK; -} - -/* ========================================================================= */ -int deflateReset (strm) - z_streamp strm; -{ - deflate_state *s; - - if (strm == Z_NULL || strm->state == Z_NULL || - strm->zalloc == Z_NULL || strm->zfree == Z_NULL) return Z_STREAM_ERROR; - - strm->total_in = strm->total_out = 0; - strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ - strm->data_type = Z_UNKNOWN; - - s = (deflate_state *)strm->state; - s->pending = 0; - s->pending_out = s->pending_buf; - - if (s->noheader < 0) { - s->noheader = 0; /* was set to -1 by deflate(..., Z_FINISH); */ - } - s->status = s->noheader ? BUSY_STATE : INIT_STATE; - strm->adler = 1; - s->last_flush = Z_NO_FLUSH; - - _tr_init(s); - lm_init(s); - - return Z_OK; -} - -/* ========================================================================= */ -int deflateParams(strm, level, strategy) - z_streamp strm; - int level; - int strategy; -{ - deflate_state *s; - compress_func func; - int err = Z_OK; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - s = (deflate_state *) strm->state; - - if (level == Z_DEFAULT_COMPRESSION) { - level = 6; - } - if (level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) { - return Z_STREAM_ERROR; - } - func = configuration_table[s->level].func; - - if (func != configuration_table[level].func && strm->total_in != 0) { - /* Flush the last buffer: */ - err = deflate(strm, Z_PARTIAL_FLUSH); - } - if (s->level != level) { - s->level = level; - s->max_lazy_match = configuration_table[level].max_lazy; - s->good_match = configuration_table[level].good_length; - s->nice_match = configuration_table[level].nice_length; - s->max_chain_length = configuration_table[level].max_chain; - } - s->strategy = strategy; - return err; -} - -/* ========================================================================= - * Put a short in the pending buffer. The 16-bit value is put in MSB order. - * IN assertion: the stream state is correct and there is enough room in - * pending_buf. - */ -local void putShortMSB (s, b) - deflate_state *s; - uInt b; -{ - put_byte(s, (Byte)(b >> 8)); - put_byte(s, (Byte)(b & 0xff)); -} - -/* ========================================================================= - * Flush as much pending output as possible. All deflate() output goes - * through this function so some applications may wish to modify it - * to avoid allocating a large strm->next_out buffer and copying into it. - * (See also read_buf()). - */ -local void flush_pending(strm) - z_streamp strm; -{ - deflate_state *s = (deflate_state *) strm->state; - unsigned len = s->pending; - - if (len > strm->avail_out) len = strm->avail_out; - if (len == 0) return; - - if (strm->next_out != Z_NULL) { - zmemcpy(strm->next_out, s->pending_out, len); - strm->next_out += len; - } - s->pending_out += len; - strm->total_out += len; - strm->avail_out -= len; - s->pending -= len; - if (s->pending == 0) { - s->pending_out = s->pending_buf; - } -} - -/* ========================================================================= */ -int deflate (strm, flush) - z_streamp strm; - int flush; -{ - int old_flush; /* value of flush param for previous deflate call */ - deflate_state *s; - - if (strm == Z_NULL || strm->state == Z_NULL || - flush > Z_FINISH || flush < 0) { - return Z_STREAM_ERROR; - } - s = (deflate_state *) strm->state; - - if ((strm->next_in == Z_NULL && strm->avail_in != 0) || - (s->status == FINISH_STATE && flush != Z_FINISH)) { - ERR_RETURN(strm, Z_STREAM_ERROR); - } - if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); - - s->strm = strm; /* just in case */ - old_flush = s->last_flush; - s->last_flush = flush; - - /* Write the zlib header */ - if (s->status == INIT_STATE) { - - uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; - uInt level_flags = (s->level-1) >> 1; - - if (level_flags > 3) level_flags = 3; - header |= (level_flags << 6); - if (s->strstart != 0) header |= PRESET_DICT; - header += 31 - (header % 31); - - s->status = BUSY_STATE; - putShortMSB(s, header); - - /* Save the adler32 of the preset dictionary: */ - if (s->strstart != 0) { - putShortMSB(s, (uInt)(strm->adler >> 16)); - putShortMSB(s, (uInt)(strm->adler & 0xffff)); - } - strm->adler = 1L; - } - - /* Flush as much pending output as possible */ - if (s->pending != 0) { - flush_pending(strm); - if (strm->avail_out == 0) { - /* Since avail_out is 0, deflate will be called again with - * more output space, but possibly with both pending and - * avail_in equal to zero. There won't be anything to do, - * but this is not an error situation so make sure we - * return OK instead of BUF_ERROR at next call of deflate: - */ - s->last_flush = -1; - return Z_OK; - } - - /* Make sure there is something to do and avoid duplicate consecutive - * flushes. For repeated and useless calls with Z_FINISH, we keep - * returning Z_STREAM_END instead of Z_BUFF_ERROR. - */ - } else if (strm->avail_in == 0 && flush <= old_flush && - flush != Z_FINISH) { - ERR_RETURN(strm, Z_BUF_ERROR); - } - - /* User must not provide more input after the first FINISH: */ - if (s->status == FINISH_STATE && strm->avail_in != 0) { - ERR_RETURN(strm, Z_BUF_ERROR); - } - - /* Start a new block or continue the current one. - */ - if (strm->avail_in != 0 || s->lookahead != 0 || - (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { - block_state bstate; - - bstate = (*(configuration_table[s->level].func))(s, flush); - - if (bstate == finish_started || bstate == finish_done) { - s->status = FINISH_STATE; - } - if (bstate == need_more || bstate == finish_started) { - if (strm->avail_out == 0) { - s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ - } - return Z_OK; - /* If flush != Z_NO_FLUSH && avail_out == 0, the next call - * of deflate should use the same flush parameter to make sure - * that the flush is complete. So we don't have to output an - * empty block here, this will be done at next call. This also - * ensures that for a very small output buffer, we emit at most - * one empty block. - */ - } - if (bstate == block_done) { - if (flush == Z_PARTIAL_FLUSH) { - _tr_align(s); - } else if (flush == Z_PACKET_FLUSH) { - /* Output just the 3-bit `stored' block type value, - but not a zero length. */ - _tr_stored_type_only(s); - } else { /* FULL_FLUSH or SYNC_FLUSH */ - _tr_stored_block(s, (char*)0, 0L, 0); - /* For a full flush, this empty block will be recognized - * as a special marker by inflate_sync(). - */ - if (flush == Z_FULL_FLUSH) { - CLEAR_HASH(s); /* forget history */ - } - } - flush_pending(strm); - if (strm->avail_out == 0) { - s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ - return Z_OK; - } - } - } - Assert(strm->avail_out > 0, "bug2"); - - if (flush != Z_FINISH) return Z_OK; - if (s->noheader) return Z_STREAM_END; - - /* Write the zlib trailer (adler32) */ - putShortMSB(s, (uInt)(strm->adler >> 16)); - putShortMSB(s, (uInt)(strm->adler & 0xffff)); - flush_pending(strm); - /* If avail_out is zero, the application will call deflate again - * to flush the rest. - */ - s->noheader = -1; /* write the trailer only once! */ - return s->pending != 0 ? Z_OK : Z_STREAM_END; -} - -/* ========================================================================= */ -int deflateEnd (strm) - z_streamp strm; -{ - int status; - deflate_state *s; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - s = (deflate_state *) strm->state; - - status = s->status; - if (status != INIT_STATE && status != BUSY_STATE && - status != FINISH_STATE) { - return Z_STREAM_ERROR; - } - - /* Deallocate in reverse order of allocations: */ - TRY_FREE(strm, s->pending_buf); - TRY_FREE(strm, s->head); - TRY_FREE(strm, s->prev); - TRY_FREE(strm, s->window); - - ZFREE(strm, s); - strm->state = Z_NULL; - - return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; -} - -/* ========================================================================= - * Copy the source state to the destination state. - */ -int deflateCopy (dest, source) - z_streamp dest; - z_streamp source; -{ - deflate_state *ds; - deflate_state *ss; - ushf *overlay; - - if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) - return Z_STREAM_ERROR; - ss = (deflate_state *) source->state; - - *dest = *source; - - ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); - if (ds == Z_NULL) return Z_MEM_ERROR; - dest->state = (struct internal_state FAR *) ds; - *ds = *ss; - ds->strm = dest; - - ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); - ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); - ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); - overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); - ds->pending_buf = (uchf *) overlay; - - if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || - ds->pending_buf == Z_NULL) { - deflateEnd (dest); - return Z_MEM_ERROR; - } - /* ??? following zmemcpy doesn't work for 16-bit MSDOS */ - zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); - zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); - zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); - zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); - - ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); - ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); - ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; - - ds->l_desc.dyn_tree = ds->dyn_ltree; - ds->d_desc.dyn_tree = ds->dyn_dtree; - ds->bl_desc.dyn_tree = ds->bl_tree; - - return Z_OK; -} - -/* =========================================================================== - * Return the number of bytes of output which are immediately available - * for output from the decompressor. - */ -int deflateOutputPending (strm) - z_streamp strm; -{ - if (strm == Z_NULL || strm->state == Z_NULL) return 0; - - return ((deflate_state *)(strm->state))->pending; -} - -/* =========================================================================== - * Read a new buffer from the current input stream, update the adler32 - * and total number of bytes read. All deflate() input goes through - * this function so some applications may wish to modify it to avoid - * allocating a large strm->next_in buffer and copying from it. - * (See also flush_pending()). - */ -local int read_buf(strm, buf, size) - z_streamp strm; - charf *buf; - unsigned size; -{ - unsigned len = strm->avail_in; - - if (len > size) len = size; - if (len == 0) return 0; - - strm->avail_in -= len; - - if (!((deflate_state *)(strm->state))->noheader) { - strm->adler = adler32(strm->adler, strm->next_in, len); - } - zmemcpy(buf, strm->next_in, len); - strm->next_in += len; - strm->total_in += len; - - return (int)len; -} - -/* =========================================================================== - * Initialize the "longest match" routines for a new zlib stream - */ -local void lm_init (s) - deflate_state *s; -{ - s->window_size = (ulg)2L*s->w_size; - - CLEAR_HASH(s); - - /* Set the default configuration parameters: - */ - s->max_lazy_match = configuration_table[s->level].max_lazy; - s->good_match = configuration_table[s->level].good_length; - s->nice_match = configuration_table[s->level].nice_length; - s->max_chain_length = configuration_table[s->level].max_chain; - - s->strstart = 0; - s->block_start = 0L; - s->lookahead = 0; - s->match_length = s->prev_length = MIN_MATCH-1; - s->match_available = 0; - s->ins_h = 0; -#ifdef ASMV - match_init(); /* initialize the asm code */ -#endif -} - -/* =========================================================================== - * Set match_start to the longest match starting at the given string and - * return its length. Matches shorter or equal to prev_length are discarded, - * in which case the result is equal to prev_length and match_start is - * garbage. - * IN assertions: cur_match is the head of the hash chain for the current - * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 - * OUT assertion: the match length is not greater than s->lookahead. - */ -#ifndef ASMV -/* For 80x86 and 680x0, an optimized version will be provided in match.asm or - * match.S. The code will be functionally equivalent. - */ -local uInt longest_match(s, cur_match) - deflate_state *s; - IPos cur_match; /* current match */ -{ - unsigned chain_length = s->max_chain_length;/* max hash chain length */ - register Bytef *scan = s->window + s->strstart; /* current string */ - register Bytef *match; /* matched string */ - register int len; /* length of current match */ - int best_len = s->prev_length; /* best match length so far */ - int nice_match = s->nice_match; /* stop if match long enough */ - IPos limit = s->strstart > (IPos)MAX_DIST(s) ? - s->strstart - (IPos)MAX_DIST(s) : NIL; - /* Stop when cur_match becomes <= limit. To simplify the code, - * we prevent matches with the string of window index 0. - */ - Posf *prev = s->prev; - uInt wmask = s->w_mask; - -#ifdef UNALIGNED_OK - /* Compare two bytes at a time. Note: this is not always beneficial. - * Try with and without -DUNALIGNED_OK to check. - */ - register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; - register ush scan_start = *(ushf*)scan; - register ush scan_end = *(ushf*)(scan+best_len-1); -#else - register Bytef *strend = s->window + s->strstart + MAX_MATCH; - register Byte scan_end1 = scan[best_len-1]; - register Byte scan_end = scan[best_len]; -#endif - - /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - * It is easy to get rid of this optimization if necessary. - */ - Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); - - /* Do not waste too much time if we already have a good match: */ - if (s->prev_length >= s->good_match) { - chain_length >>= 2; - } - /* Do not look for matches beyond the end of the input. This is necessary - * to make deflate deterministic. - */ - if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; - - Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); - - do { - Assert(cur_match < s->strstart, "no future"); - match = s->window + cur_match; - - /* Skip to next match if the match length cannot increase - * or if the match length is less than 2: - */ -#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) - /* This code assumes sizeof(unsigned short) == 2. Do not use - * UNALIGNED_OK if your compiler uses a different size. - */ - if (*(ushf*)(match+best_len-1) != scan_end || - *(ushf*)match != scan_start) continue; - - /* It is not necessary to compare scan[2] and match[2] since they are - * always equal when the other bytes match, given that the hash keys - * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at - * strstart+3, +5, ... up to strstart+257. We check for insufficient - * lookahead only every 4th comparison; the 128th check will be made - * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is - * necessary to put more guard bytes at the end of the window, or - * to check more often for insufficient lookahead. - */ - Assert(scan[2] == match[2], "scan[2]?"); - scan++, match++; - do { - } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - scan < strend); - /* The funny "do {}" generates better code on most compilers */ - - /* Here, scan <= window+strstart+257 */ - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - if (*scan == *match) scan++; - - len = (MAX_MATCH - 1) - (int)(strend-scan); - scan = strend - (MAX_MATCH-1); - -#else /* UNALIGNED_OK */ - - if (match[best_len] != scan_end || - match[best_len-1] != scan_end1 || - *match != *scan || - *++match != scan[1]) continue; - - /* The check at best_len-1 can be removed because it will be made - * again later. (This heuristic is not always a win.) - * It is not necessary to compare scan[2] and match[2] since they - * are always equal when the other bytes match, given that - * the hash keys are equal and that HASH_BITS >= 8. - */ - scan += 2, match++; - Assert(*scan == *match, "match[2]?"); - - /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. - */ - do { - } while (*++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - scan < strend); - - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - - len = MAX_MATCH - (int)(strend - scan); - scan = strend - MAX_MATCH; - -#endif /* UNALIGNED_OK */ - - if (len > best_len) { - s->match_start = cur_match; - best_len = len; - if (len >= nice_match) break; -#ifdef UNALIGNED_OK - scan_end = *(ushf*)(scan+best_len-1); -#else - scan_end1 = scan[best_len-1]; - scan_end = scan[best_len]; -#endif - } - } while ((cur_match = prev[cur_match & wmask]) > limit - && --chain_length != 0); - - if ((uInt)best_len <= s->lookahead) return best_len; - return s->lookahead; -} -#endif /* ASMV */ - -#ifdef DEBUG_ZLIB -/* =========================================================================== - * Check that the match at match_start is indeed a match. - */ -local void check_match(s, start, match, length) - deflate_state *s; - IPos start, match; - int length; -{ - /* check that the match is indeed a match */ - if (zmemcmp((charf *)s->window + match, - (charf *)s->window + start, length) != EQUAL) { - fprintf(stderr, " start %u, match %u, length %d\n", - start, match, length); - do { - fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); - } while (--length != 0); - z_error("invalid match"); - } - if (z_verbose > 1) { - fprintf(stderr,"\\[%d,%d]", start-match, length); - do { putc(s->window[start++], stderr); } while (--length != 0); - } -} -#else -# define check_match(s, start, match, length) -#endif - -/* =========================================================================== - * Fill the window when the lookahead becomes insufficient. - * Updates strstart and lookahead. - * - * IN assertion: lookahead < MIN_LOOKAHEAD - * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD - * At least one byte has been read, or avail_in == 0; reads are - * performed for at least two bytes (required for the zip translate_eol - * option -- not supported here). - */ -local void fill_window(s) - deflate_state *s; -{ - register unsigned n, m; - register Posf *p; - unsigned more; /* Amount of free space at the end of the window. */ - uInt wsize = s->w_size; - - do { - more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); - - /* Deal with !@#$% 64K limit: */ - if (more == 0 && s->strstart == 0 && s->lookahead == 0) { - more = wsize; - - } else if (more == (unsigned)(-1)) { - /* Very unlikely, but possible on 16 bit machine if strstart == 0 - * and lookahead == 1 (input done one byte at time) - */ - more--; - - /* If the window is almost full and there is insufficient lookahead, - * move the upper half to the lower one to make room in the upper half. - */ - } else if (s->strstart >= wsize+MAX_DIST(s)) { - - zmemcpy((charf *)s->window, (charf *)s->window+wsize, - (unsigned)wsize); - s->match_start -= wsize; - s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ - s->block_start -= (long) wsize; - - /* Slide the hash table (could be avoided with 32 bit values - at the expense of memory usage). We slide even when level == 0 - to keep the hash table consistent if we switch back to level > 0 - later. (Using level 0 permanently is not an optimal usage of - zlib, so we don't care about this pathological case.) - */ - n = s->hash_size; - p = &s->head[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m-wsize : NIL); - } while (--n); - - n = wsize; - p = &s->prev[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m-wsize : NIL); - /* If n is not on any hash chain, prev[n] is garbage but - * its value will never be used. - */ - } while (--n); - more += wsize; - } - if (s->strm->avail_in == 0) return; - - /* If there was no sliding: - * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && - * more == window_size - lookahead - strstart - * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) - * => more >= window_size - 2*WSIZE + 2 - * In the BIG_MEM or MMAP case (not yet supported), - * window_size == input_size + MIN_LOOKAHEAD && - * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. - * Otherwise, window_size == 2*WSIZE so more >= 2. - * If there was sliding, more >= WSIZE. So in all cases, more >= 2. - */ - Assert(more >= 2, "more < 2"); - - n = read_buf(s->strm, (charf *)s->window + s->strstart + s->lookahead, - more); - s->lookahead += n; - - /* Initialize the hash value now that we have some input: */ - if (s->lookahead >= MIN_MATCH) { - s->ins_h = s->window[s->strstart]; - UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); -#if MIN_MATCH != 3 - Call UPDATE_HASH() MIN_MATCH-3 more times -#endif - } - /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, - * but this is not important since only literal bytes will be emitted. - */ - - } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); -} - -/* =========================================================================== - * Flush the current block, with given end-of-file flag. - * IN assertion: strstart is set to the end of the current match. - */ -#define FLUSH_BLOCK_ONLY(s, eof) { \ - _tr_flush_block(s, (s->block_start >= 0L ? \ - (charf *)&s->window[(unsigned)s->block_start] : \ - (charf *)Z_NULL), \ - (ulg)((long)s->strstart - s->block_start), \ - (eof)); \ - s->block_start = s->strstart; \ - flush_pending(s->strm); \ - Tracev((stderr,"[FLUSH]")); \ -} - -/* Same but force premature exit if necessary. */ -#define FLUSH_BLOCK(s, eof) { \ - FLUSH_BLOCK_ONLY(s, eof); \ - if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ -} - -/* =========================================================================== - * Copy without compression as much as possible from the input stream, return - * the current block state. - * This function does not insert new strings in the dictionary since - * uncompressible data is probably not useful. This function is used - * only for the level=0 compression option. - * NOTE: this function should be optimized to avoid extra copying from - * window to pending_buf. - */ -local block_state deflate_stored(s, flush) - deflate_state *s; - int flush; -{ - /* Stored blocks are limited to 0xffff bytes, pending_buf is limited - * to pending_buf_size, and each stored block has a 5 byte header: - */ - ulg max_block_size = 0xffff; - ulg max_start; - - if (max_block_size > s->pending_buf_size - 5) { - max_block_size = s->pending_buf_size - 5; - } - - /* Copy as much as possible from input to output: */ - for (;;) { - /* Fill the window as much as possible: */ - if (s->lookahead <= 1) { - - Assert(s->strstart < s->w_size+MAX_DIST(s) || - s->block_start >= (long)s->w_size, "slide too late"); - - fill_window(s); - if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; - - if (s->lookahead == 0) break; /* flush the current block */ - } - Assert(s->block_start >= 0L, "block gone"); - - s->strstart += s->lookahead; - s->lookahead = 0; - - /* Emit a stored block if pending_buf will be full: */ - max_start = s->block_start + max_block_size; - if (s->strstart == 0 || (ulg)s->strstart >= max_start) { - /* strstart == 0 is possible when wraparound on 16-bit machine */ - s->lookahead = (uInt)(s->strstart - max_start); - s->strstart = (uInt)max_start; - FLUSH_BLOCK(s, 0); - } - /* Flush if we may have to slide, otherwise block_start may become - * negative and the data will be gone: - */ - if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { - FLUSH_BLOCK(s, 0); - } - } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; -} - -/* =========================================================================== - * Compress as much as possible from the input stream, return the current - * block state. - * This function does not perform lazy evaluation of matches and inserts - * new strings in the dictionary only for unmatched strings or for short - * matches. It is used only for the fast compression options. - */ -local block_state deflate_fast(s, flush) - deflate_state *s; - int flush; -{ - IPos hash_head = NIL; /* head of the hash chain */ - int bflush; /* set if current block must be flushed */ - - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s->lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { - return need_more; - } - if (s->lookahead == 0) break; /* flush the current block */ - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - if (s->lookahead >= MIN_MATCH) { - INSERT_STRING(s, s->strstart, hash_head); - } - - /* Find the longest match, discarding those <= prev_length. - * At this point we have always match_length < MIN_MATCH - */ - if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - if (s->strategy != Z_HUFFMAN_ONLY) { - s->match_length = longest_match (s, hash_head); - } - /* longest_match() sets match_start */ - } - if (s->match_length >= MIN_MATCH) { - check_match(s, s->strstart, s->match_start, s->match_length); - - bflush = _tr_tally(s, s->strstart - s->match_start, - s->match_length - MIN_MATCH); - - s->lookahead -= s->match_length; - - /* Insert new strings in the hash table only if the match length - * is not too large. This saves time but degrades compression. - */ - if (s->match_length <= s->max_insert_length && - s->lookahead >= MIN_MATCH) { - s->match_length--; /* string at strstart already in hash table */ - do { - s->strstart++; - INSERT_STRING(s, s->strstart, hash_head); - /* strstart never exceeds WSIZE-MAX_MATCH, so there are - * always MIN_MATCH bytes ahead. - */ - } while (--s->match_length != 0); - s->strstart++; - } else { - s->strstart += s->match_length; - s->match_length = 0; - s->ins_h = s->window[s->strstart]; - UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); -#if MIN_MATCH != 3 - Call UPDATE_HASH() MIN_MATCH-3 more times -#endif - /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not - * matter since it will be recomputed at next deflate call. - */ - } - } else { - /* No match, output a literal byte */ - Tracevv((stderr,"%c", s->window[s->strstart])); - bflush = _tr_tally (s, 0, s->window[s->strstart]); - s->lookahead--; - s->strstart++; - } - if (bflush) FLUSH_BLOCK(s, 0); - } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; -} - -/* =========================================================================== - * Same as above, but achieves better compression. We use a lazy - * evaluation for matches: a match is finally adopted only if there is - * no better match at the next window position. - */ -local block_state deflate_slow(s, flush) - deflate_state *s; - int flush; -{ - IPos hash_head = NIL; /* head of hash chain */ - int bflush; /* set if current block must be flushed */ - - /* Process the input block. */ - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s->lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { - return need_more; - } - if (s->lookahead == 0) break; /* flush the current block */ - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - if (s->lookahead >= MIN_MATCH) { - INSERT_STRING(s, s->strstart, hash_head); - } - - /* Find the longest match, discarding those <= prev_length. - */ - s->prev_length = s->match_length, s->prev_match = s->match_start; - s->match_length = MIN_MATCH-1; - - if (hash_head != NIL && s->prev_length < s->max_lazy_match && - s->strstart - hash_head <= MAX_DIST(s)) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - if (s->strategy != Z_HUFFMAN_ONLY) { - s->match_length = longest_match (s, hash_head); - } - /* longest_match() sets match_start */ - - if (s->match_length <= 5 && (s->strategy == Z_FILTERED || - (s->match_length == MIN_MATCH && - s->strstart - s->match_start > TOO_FAR))) { - - /* If prev_match is also MIN_MATCH, match_start is garbage - * but we will ignore the current match anyway. - */ - s->match_length = MIN_MATCH-1; - } - } - /* If there was a match at the previous step and the current - * match is not better, output the previous match: - */ - if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { - uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; - /* Do not insert strings in hash table beyond this. */ - - check_match(s, s->strstart-1, s->prev_match, s->prev_length); - - bflush = _tr_tally(s, s->strstart -1 - s->prev_match, - s->prev_length - MIN_MATCH); - - /* Insert in hash table all strings up to the end of the match. - * strstart-1 and strstart are already inserted. If there is not - * enough lookahead, the last two strings are not inserted in - * the hash table. - */ - s->lookahead -= s->prev_length-1; - s->prev_length -= 2; - do { - if (++s->strstart <= max_insert) { - INSERT_STRING(s, s->strstart, hash_head); - } - } while (--s->prev_length != 0); - s->match_available = 0; - s->match_length = MIN_MATCH-1; - s->strstart++; - - if (bflush) FLUSH_BLOCK(s, 0); - - } else if (s->match_available) { - /* If there was no match at the previous position, output a - * single literal. If there was a match but the current match - * is longer, truncate the previous match to a single literal. - */ - Tracevv((stderr,"%c", s->window[s->strstart-1])); - if (_tr_tally (s, 0, s->window[s->strstart-1])) { - FLUSH_BLOCK_ONLY(s, 0); - } - s->strstart++; - s->lookahead--; - if (s->strm->avail_out == 0) return need_more; - } else { - /* There is no previous match to compare with, wait for - * the next step to decide. - */ - s->match_available = 1; - s->strstart++; - s->lookahead--; - } - } - Assert (flush != Z_NO_FLUSH, "no flush?"); - if (s->match_available) { - Tracevv((stderr,"%c", s->window[s->strstart-1])); - _tr_tally (s, 0, s->window[s->strstart-1]); - s->match_available = 0; - } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; -} -/* --- deflate.c */ - -/* +++ trees.c */ -/* trees.c -- output deflated data using Huffman coding - * Copyright (C) 1995-1996 Jean-loup Gailly - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * ALGORITHM - * - * The "deflation" process uses several Huffman trees. The more - * common source values are represented by shorter bit sequences. - * - * Each code tree is stored in a compressed form which is itself - * a Huffman encoding of the lengths of all the code strings (in - * ascending order by source values). The actual code strings are - * reconstructed from the lengths in the inflate process, as described - * in the deflate specification. - * - * REFERENCES - * - * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". - * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc - * - * Storer, James A. - * Data Compression: Methods and Theory, pp. 49-50. - * Computer Science Press, 1988. ISBN 0-7167-8156-5. - * - * Sedgewick, R. - * Algorithms, p290. - * Addison-Wesley, 1983. ISBN 0-201-06672-6. - */ - -/* From: trees.c,v 1.11 1996/07/24 13:41:06 me Exp $ */ - -/* #include "deflate.h" */ - -#ifdef DEBUG_ZLIB -# include -#endif - -/* =========================================================================== - * Constants - */ - -#define MAX_BL_BITS 7 -/* Bit length codes must not exceed MAX_BL_BITS bits */ - -#define END_BLOCK 256 -/* end of block literal code */ - -#define REP_3_6 16 -/* repeat previous bit length 3-6 times (2 bits of repeat count) */ - -#define REPZ_3_10 17 -/* repeat a zero length 3-10 times (3 bits of repeat count) */ - -#define REPZ_11_138 18 -/* repeat a zero length 11-138 times (7 bits of repeat count) */ - -local int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ - = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; - -local int extra_dbits[D_CODES] /* extra bits for each distance code */ - = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; - -local int extra_blbits[BL_CODES]/* extra bits for each bit length code */ - = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; - -local uch bl_order[BL_CODES] - = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; -/* The lengths of the bit length codes are sent in order of decreasing - * probability, to avoid transmitting the lengths for unused bit length codes. - */ - -#define Buf_size (8 * 2*sizeof(char)) -/* Number of bits used within bi_buf. (bi_buf might be implemented on - * more than 16 bits on some systems.) - */ - -/* =========================================================================== - * Local data. These are initialized only once. - */ - -local ct_data static_ltree[L_CODES+2]; -/* The static literal tree. Since the bit lengths are imposed, there is no - * need for the L_CODES extra codes used during heap construction. However - * The codes 286 and 287 are needed to build a canonical tree (see _tr_init - * below). - */ - -local ct_data static_dtree[D_CODES]; -/* The static distance tree. (Actually a trivial tree since all codes use - * 5 bits.) - */ - -local uch dist_code[512]; -/* distance codes. The first 256 values correspond to the distances - * 3 .. 258, the last 256 values correspond to the top 8 bits of - * the 15 bit distances. - */ - -local uch length_code[MAX_MATCH-MIN_MATCH+1]; -/* length code for each normalized match length (0 == MIN_MATCH) */ - -local int base_length[LENGTH_CODES]; -/* First normalized length for each code (0 = MIN_MATCH) */ - -local int base_dist[D_CODES]; -/* First normalized distance for each code (0 = distance of 1) */ - -struct static_tree_desc_s { - ct_data *static_tree; /* static tree or NULL */ - intf *extra_bits; /* extra bits for each code or NULL */ - int extra_base; /* base index for extra_bits */ - int elems; /* max number of elements in the tree */ - int max_length; /* max bit length for the codes */ -}; - -local static_tree_desc static_l_desc = -{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; - -local static_tree_desc static_d_desc = -{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; - -local static_tree_desc static_bl_desc = -{(ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; - -/* =========================================================================== - * Local (static) routines in this file. - */ - -local void tr_static_init OF((void)); -local void init_block OF((deflate_state *s)); -local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); -local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); -local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); -local void build_tree OF((deflate_state *s, tree_desc *desc)); -local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); -local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); -local int build_bl_tree OF((deflate_state *s)); -local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, - int blcodes)); -local void compress_block OF((deflate_state *s, ct_data *ltree, - ct_data *dtree)); -local void set_data_type OF((deflate_state *s)); -local unsigned bi_reverse OF((unsigned value, int length)); -local void bi_windup OF((deflate_state *s)); -local void bi_flush OF((deflate_state *s)); -local void copy_block OF((deflate_state *s, charf *buf, unsigned len, - int header)); - -#ifndef DEBUG_ZLIB -# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) - /* Send a code of the given tree. c and tree must not have side effects */ - -#else /* DEBUG_ZLIB */ -# define send_code(s, c, tree) \ - { if (verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ - send_bits(s, tree[c].Code, tree[c].Len); } -#endif - -#define d_code(dist) \ - ((dist) < 256 ? dist_code[dist] : dist_code[256+((dist)>>7)]) -/* Mapping from a distance to a distance code. dist is the distance - 1 and - * must not have side effects. dist_code[256] and dist_code[257] are never - * used. - */ - -/* =========================================================================== - * Output a short LSB first on the stream. - * IN assertion: there is enough room in pendingBuf. - */ -#define put_short(s, w) { \ - put_byte(s, (uch)((w) & 0xff)); \ - put_byte(s, (uch)((ush)(w) >> 8)); \ -} - -/* =========================================================================== - * Send a value on a given number of bits. - * IN assertion: length <= 16 and value fits in length bits. - */ -#ifdef DEBUG_ZLIB -local void send_bits OF((deflate_state *s, int value, int length)); - -local void send_bits(s, value, length) - deflate_state *s; - int value; /* value to send */ - int length; /* number of bits */ -{ - Tracevv((stderr," l %2d v %4x ", length, value)); - Assert(length > 0 && length <= 15, "invalid length"); - s->bits_sent += (ulg)length; - - /* If not enough room in bi_buf, use (valid) bits from bi_buf and - * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) - * unused bits in value. - */ - if (s->bi_valid > (int)Buf_size - length) { - s->bi_buf |= (value << s->bi_valid); - put_short(s, s->bi_buf); - s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); - s->bi_valid += length - Buf_size; - } else { - s->bi_buf |= value << s->bi_valid; - s->bi_valid += length; - } -} -#else /* !DEBUG_ZLIB */ - -#define send_bits(s, value, length) \ -{ int len = length;\ - if (s->bi_valid > (int)Buf_size - len) {\ - int val = value;\ - s->bi_buf |= (val << s->bi_valid);\ - put_short(s, s->bi_buf);\ - s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ - s->bi_valid += len - Buf_size;\ - } else {\ - s->bi_buf |= (value) << s->bi_valid;\ - s->bi_valid += len;\ - }\ -} -#endif /* DEBUG_ZLIB */ - - -#define MAX(a,b) (a >= b ? a : b) -/* the arguments must not have side effects */ - -/* =========================================================================== - * Initialize the various 'constant' tables. In a multi-threaded environment, - * this function may be called by two threads concurrently, but this is - * harmless since both invocations do exactly the same thing. - */ -local void tr_static_init() -{ - static int static_init_done; - int n; /* iterates over tree elements */ - int bits; /* bit counter */ - int length; /* length value */ - int code; /* code value */ - int dist; /* distance index */ - ush bl_count[MAX_BITS+1]; - /* number of codes at each bit length for an optimal tree */ - - if (static_init_done) return; - - /* Initialize the mapping length (0..255) -> length code (0..28) */ - length = 0; - for (code = 0; code < LENGTH_CODES-1; code++) { - base_length[code] = length; - for (n = 0; n < (1< dist code (0..29) */ - dist = 0; - for (code = 0 ; code < 16; code++) { - base_dist[code] = dist; - for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ - for ( ; code < D_CODES; code++) { - base_dist[code] = dist << 7; - for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { - dist_code[256 + dist++] = (uch)code; - } - } - Assert (dist == 256, "tr_static_init: 256+dist != 512"); - - /* Construct the codes of the static literal tree */ - for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; - n = 0; - while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; - while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; - while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; - while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; - /* Codes 286 and 287 do not exist, but we must include them in the - * tree construction to get a canonical Huffman tree (longest code - * all ones) - */ - gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); - - /* The static distance tree is trivial: */ - for (n = 0; n < D_CODES; n++) { - static_dtree[n].Len = 5; - static_dtree[n].Code = bi_reverse((unsigned)n, 5); - } - static_init_done = 1; -} - -/* =========================================================================== - * Initialize the tree data structures for a new zlib stream. - */ -void _tr_init(s) - deflate_state *s; -{ - tr_static_init(); - - s->compressed_len = 0L; - - s->l_desc.dyn_tree = s->dyn_ltree; - s->l_desc.stat_desc = &static_l_desc; - - s->d_desc.dyn_tree = s->dyn_dtree; - s->d_desc.stat_desc = &static_d_desc; - - s->bl_desc.dyn_tree = s->bl_tree; - s->bl_desc.stat_desc = &static_bl_desc; - - s->bi_buf = 0; - s->bi_valid = 0; - s->last_eob_len = 8; /* enough lookahead for inflate */ -#ifdef DEBUG_ZLIB - s->bits_sent = 0L; -#endif - - /* Initialize the first block of the first file: */ - init_block(s); -} - -/* =========================================================================== - * Initialize a new block. - */ -local void init_block(s) - deflate_state *s; -{ - int n; /* iterates over tree elements */ - - /* Initialize the trees. */ - for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; - for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; - for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; - - s->dyn_ltree[END_BLOCK].Freq = 1; - s->opt_len = s->static_len = 0L; - s->last_lit = s->matches = 0; -} - -#define SMALLEST 1 -/* Index within the heap array of least frequent node in the Huffman tree */ - - -/* =========================================================================== - * Remove the smallest element from the heap and recreate the heap with - * one less element. Updates heap and heap_len. - */ -#define pqremove(s, tree, top) \ -{\ - top = s->heap[SMALLEST]; \ - s->heap[SMALLEST] = s->heap[s->heap_len--]; \ - pqdownheap(s, tree, SMALLEST); \ -} - -/* =========================================================================== - * Compares to subtrees, using the tree depth as tie breaker when - * the subtrees have equal frequency. This minimizes the worst case length. - */ -#define smaller(tree, n, m, depth) \ - (tree[n].Freq < tree[m].Freq || \ - (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) - -/* =========================================================================== - * Restore the heap property by moving down the tree starting at node k, - * exchanging a node with the smallest of its two sons if necessary, stopping - * when the heap property is re-established (each father smaller than its - * two sons). - */ -local void pqdownheap(s, tree, k) - deflate_state *s; - ct_data *tree; /* the tree to restore */ - int k; /* node to move down */ -{ - int v = s->heap[k]; - int j = k << 1; /* left son of k */ - while (j <= s->heap_len) { - /* Set j to the smallest of the two sons: */ - if (j < s->heap_len && - smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { - j++; - } - /* Exit if v is smaller than both sons */ - if (smaller(tree, v, s->heap[j], s->depth)) break; - - /* Exchange v with the smallest son */ - s->heap[k] = s->heap[j]; k = j; - - /* And continue down the tree, setting j to the left son of k */ - j <<= 1; - } - s->heap[k] = v; -} - -/* =========================================================================== - * Compute the optimal bit lengths for a tree and update the total bit length - * for the current block. - * IN assertion: the fields freq and dad are set, heap[heap_max] and - * above are the tree nodes sorted by increasing frequency. - * OUT assertions: the field len is set to the optimal bit length, the - * array bl_count contains the frequencies for each bit length. - * The length opt_len is updated; static_len is also updated if stree is - * not null. - */ -local void gen_bitlen(s, desc) - deflate_state *s; - tree_desc *desc; /* the tree descriptor */ -{ - ct_data *tree = desc->dyn_tree; - int max_code = desc->max_code; - ct_data *stree = desc->stat_desc->static_tree; - intf *extra = desc->stat_desc->extra_bits; - int base = desc->stat_desc->extra_base; - int max_length = desc->stat_desc->max_length; - int h; /* heap index */ - int n, m; /* iterate over the tree elements */ - int bits; /* bit length */ - int xbits; /* extra bits */ - ush f; /* frequency */ - int overflow = 0; /* number of elements with bit length too large */ - - for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; - - /* In a first pass, compute the optimal bit lengths (which may - * overflow in the case of the bit length tree). - */ - tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ - - for (h = s->heap_max+1; h < HEAP_SIZE; h++) { - n = s->heap[h]; - bits = tree[tree[n].Dad].Len + 1; - if (bits > max_length) bits = max_length, overflow++; - tree[n].Len = (ush)bits; - /* We overwrite tree[n].Dad which is no longer needed */ - - if (n > max_code) continue; /* not a leaf node */ - - s->bl_count[bits]++; - xbits = 0; - if (n >= base) xbits = extra[n-base]; - f = tree[n].Freq; - s->opt_len += (ulg)f * (bits + xbits); - if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); - } - if (overflow == 0) return; - - Trace((stderr,"\nbit length overflow\n")); - /* This happens for example on obj2 and pic of the Calgary corpus */ - - /* Find the first bit length which could increase: */ - do { - bits = max_length-1; - while (s->bl_count[bits] == 0) bits--; - s->bl_count[bits]--; /* move one leaf down the tree */ - s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ - s->bl_count[max_length]--; - /* The brother of the overflow item also moves one step up, - * but this does not affect bl_count[max_length] - */ - overflow -= 2; - } while (overflow > 0); - - /* Now recompute all bit lengths, scanning in increasing frequency. - * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all - * lengths instead of fixing only the wrong ones. This idea is taken - * from 'ar' written by Haruhiko Okumura.) - */ - for (bits = max_length; bits != 0; bits--) { - n = s->bl_count[bits]; - while (n != 0) { - m = s->heap[--h]; - if (m > max_code) continue; - if (tree[m].Len != (unsigned) bits) { - Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); - s->opt_len += ((long)bits - (long)tree[m].Len) - *(long)tree[m].Freq; - tree[m].Len = (ush)bits; - } - n--; - } - } -} - -/* =========================================================================== - * Generate the codes for a given tree and bit counts (which need not be - * optimal). - * IN assertion: the array bl_count contains the bit length statistics for - * the given tree and the field len is set for all tree elements. - * OUT assertion: the field code is set for all tree elements of non - * zero code length. - */ -local void gen_codes (tree, max_code, bl_count) - ct_data *tree; /* the tree to decorate */ - int max_code; /* largest code with non zero frequency */ - ushf *bl_count; /* number of codes at each bit length */ -{ - ush next_code[MAX_BITS+1]; /* next code value for each bit length */ - ush code = 0; /* running code value */ - int bits; /* bit index */ - int n; /* code index */ - - /* The distribution counts are first used to generate the code values - * without bit reversal. - */ - for (bits = 1; bits <= MAX_BITS; bits++) { - next_code[bits] = code = (code + bl_count[bits-1]) << 1; - } - /* Check that the bit counts in bl_count are consistent. The last code - * must be all ones. - */ - Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; - ct_data *stree = desc->stat_desc->static_tree; - int elems = desc->stat_desc->elems; - int n, m; /* iterate over heap elements */ - int max_code = -1; /* largest code with non zero frequency */ - int node; /* new node being created */ - - /* Construct the initial heap, with least frequent element in - * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. - * heap[0] is not used. - */ - s->heap_len = 0, s->heap_max = HEAP_SIZE; - - for (n = 0; n < elems; n++) { - if (tree[n].Freq != 0) { - s->heap[++(s->heap_len)] = max_code = n; - s->depth[n] = 0; - } else { - tree[n].Len = 0; - } - } - - /* The pkzip format requires that at least one distance code exists, - * and that at least one bit should be sent even if there is only one - * possible code. So to avoid special checks later on we force at least - * two codes of non zero frequency. - */ - while (s->heap_len < 2) { - node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); - tree[node].Freq = 1; - s->depth[node] = 0; - s->opt_len--; if (stree) s->static_len -= stree[node].Len; - /* node is 0 or 1 so it does not have extra bits */ - } - desc->max_code = max_code; - - /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, - * establish sub-heaps of increasing lengths: - */ - for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); - - /* Construct the Huffman tree by repeatedly combining the least two - * frequent nodes. - */ - node = elems; /* next internal node of the tree */ - do { - pqremove(s, tree, n); /* n = node of least frequency */ - m = s->heap[SMALLEST]; /* m = node of next least frequency */ - - s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ - s->heap[--(s->heap_max)] = m; - - /* Create a new node father of n and m */ - tree[node].Freq = tree[n].Freq + tree[m].Freq; - s->depth[node] = (uch) (MAX(s->depth[n], s->depth[m]) + 1); - tree[n].Dad = tree[m].Dad = (ush)node; -#ifdef DUMP_BL_TREE - if (tree == s->bl_tree) { - fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", - node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); - } -#endif - /* and insert the new node in the heap */ - s->heap[SMALLEST] = node++; - pqdownheap(s, tree, SMALLEST); - - } while (s->heap_len >= 2); - - s->heap[--(s->heap_max)] = s->heap[SMALLEST]; - - /* At this point, the fields freq and dad are set. We can now - * generate the bit lengths. - */ - gen_bitlen(s, (tree_desc *)desc); - - /* The field len is now set, we can generate the bit codes */ - gen_codes ((ct_data *)tree, max_code, s->bl_count); -} - -/* =========================================================================== - * Scan a literal or distance tree to determine the frequencies of the codes - * in the bit length tree. - */ -local void scan_tree (s, tree, max_code) - deflate_state *s; - ct_data *tree; /* the tree to be scanned */ - int max_code; /* and its largest code of non zero frequency */ -{ - int n; /* iterates over all tree elements */ - int prevlen = -1; /* last emitted length */ - int curlen; /* length of current code */ - int nextlen = tree[0].Len; /* length of next code */ - int count = 0; /* repeat count of the current code */ - int max_count = 7; /* max repeat count */ - int min_count = 4; /* min repeat count */ - - if (nextlen == 0) max_count = 138, min_count = 3; - tree[max_code+1].Len = (ush)0xffff; /* guard */ - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n+1].Len; - if (++count < max_count && curlen == nextlen) { - continue; - } else if (count < min_count) { - s->bl_tree[curlen].Freq += count; - } else if (curlen != 0) { - if (curlen != prevlen) s->bl_tree[curlen].Freq++; - s->bl_tree[REP_3_6].Freq++; - } else if (count <= 10) { - s->bl_tree[REPZ_3_10].Freq++; - } else { - s->bl_tree[REPZ_11_138].Freq++; - } - count = 0; prevlen = curlen; - if (nextlen == 0) { - max_count = 138, min_count = 3; - } else if (curlen == nextlen) { - max_count = 6, min_count = 3; - } else { - max_count = 7, min_count = 4; - } - } -} - -/* =========================================================================== - * Send a literal or distance tree in compressed form, using the codes in - * bl_tree. - */ -local void send_tree (s, tree, max_code) - deflate_state *s; - ct_data *tree; /* the tree to be scanned */ - int max_code; /* and its largest code of non zero frequency */ -{ - int n; /* iterates over all tree elements */ - int prevlen = -1; /* last emitted length */ - int curlen; /* length of current code */ - int nextlen = tree[0].Len; /* length of next code */ - int count = 0; /* repeat count of the current code */ - int max_count = 7; /* max repeat count */ - int min_count = 4; /* min repeat count */ - - /* tree[max_code+1].Len = -1; */ /* guard already set */ - if (nextlen == 0) max_count = 138, min_count = 3; - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n+1].Len; - if (++count < max_count && curlen == nextlen) { - continue; - } else if (count < min_count) { - do { send_code(s, curlen, s->bl_tree); } while (--count != 0); - - } else if (curlen != 0) { - if (curlen != prevlen) { - send_code(s, curlen, s->bl_tree); count--; - } - Assert(count >= 3 && count <= 6, " 3_6?"); - send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); - - } else if (count <= 10) { - send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); - - } else { - send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); - } - count = 0; prevlen = curlen; - if (nextlen == 0) { - max_count = 138, min_count = 3; - } else if (curlen == nextlen) { - max_count = 6, min_count = 3; - } else { - max_count = 7, min_count = 4; - } - } -} - -/* =========================================================================== - * Construct the Huffman tree for the bit lengths and return the index in - * bl_order of the last bit length code to send. - */ -local int build_bl_tree(s) - deflate_state *s; -{ - int max_blindex; /* index of last bit length code of non zero freq */ - - /* Determine the bit length frequencies for literal and distance trees */ - scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); - scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); - - /* Build the bit length tree: */ - build_tree(s, (tree_desc *)(&(s->bl_desc))); - /* opt_len now includes the length of the tree representations, except - * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. - */ - - /* Determine the number of bit length codes to send. The pkzip format - * requires that at least 4 bit length codes be sent. (appnote.txt says - * 3 but the actual value used is 4.) - */ - for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { - if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; - } - /* Update opt_len to include the bit length tree and counts */ - s->opt_len += 3*(max_blindex+1) + 5+5+4; - Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", - s->opt_len, s->static_len)); - - return max_blindex; -} - -/* =========================================================================== - * Send the header for a block using dynamic Huffman trees: the counts, the - * lengths of the bit length codes, the literal tree and the distance tree. - * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. - */ -local void send_all_trees(s, lcodes, dcodes, blcodes) - deflate_state *s; - int lcodes, dcodes, blcodes; /* number of codes for each tree */ -{ - int rank; /* index in bl_order */ - - Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); - Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, - "too many codes"); - Tracev((stderr, "\nbl counts: ")); - send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ - send_bits(s, dcodes-1, 5); - send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ - for (rank = 0; rank < blcodes; rank++) { - Tracev((stderr, "\nbl code %2d ", bl_order[rank])); - send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); - } - Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); - - send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ - Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); - - send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ - Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); -} - -/* =========================================================================== - * Send a stored block - */ -void _tr_stored_block(s, buf, stored_len, eof) - deflate_state *s; - charf *buf; /* input block */ - ulg stored_len; /* length of input block */ - int eof; /* true if this is the last block for a file */ -{ - send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ - s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; - s->compressed_len += (stored_len + 4) << 3; - - copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ -} - -/* Send just the `stored block' type code without any length bytes or data. - */ -void _tr_stored_type_only(s) - deflate_state *s; -{ - send_bits(s, (STORED_BLOCK << 1), 3); - bi_windup(s); - s->compressed_len = (s->compressed_len + 3) & ~7L; -} - - -/* =========================================================================== - * Send one empty static block to give enough lookahead for inflate. - * This takes 10 bits, of which 7 may remain in the bit buffer. - * The current inflate code requires 9 bits of lookahead. If the - * last two codes for the previous block (real code plus EOB) were coded - * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode - * the last real code. In this case we send two empty static blocks instead - * of one. (There are no problems if the previous block is stored or fixed.) - * To simplify the code, we assume the worst case of last real code encoded - * on one bit only. - */ -void _tr_align(s) - deflate_state *s; -{ - send_bits(s, STATIC_TREES<<1, 3); - send_code(s, END_BLOCK, static_ltree); - s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ - bi_flush(s); - /* Of the 10 bits for the empty block, we have already sent - * (10 - bi_valid) bits. The lookahead for the last real code (before - * the EOB of the previous block) was thus at least one plus the length - * of the EOB plus what we have just sent of the empty static block. - */ - if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { - send_bits(s, STATIC_TREES<<1, 3); - send_code(s, END_BLOCK, static_ltree); - s->compressed_len += 10L; - bi_flush(s); - } - s->last_eob_len = 7; -} - -/* =========================================================================== - * Determine the best encoding for the current block: dynamic trees, static - * trees or store, and output the encoded block to the zip file. This function - * returns the total compressed length for the file so far. - */ -ulg _tr_flush_block(s, buf, stored_len, eof) - deflate_state *s; - charf *buf; /* input block, or NULL if too old */ - ulg stored_len; /* length of input block */ - int eof; /* true if this is the last block for a file */ -{ - ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ - int max_blindex = 0; /* index of last bit length code of non zero freq */ - - /* Build the Huffman trees unless a stored block is forced */ - if (s->level > 0) { - - /* Check if the file is ascii or binary */ - if (s->data_type == Z_UNKNOWN) set_data_type(s); - - /* Construct the literal and distance trees */ - build_tree(s, (tree_desc *)(&(s->l_desc))); - Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, - s->static_len)); - - build_tree(s, (tree_desc *)(&(s->d_desc))); - Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, - s->static_len)); - /* At this point, opt_len and static_len are the total bit lengths of - * the compressed block data, excluding the tree representations. - */ - - /* Build the bit length tree for the above two trees, and get the index - * in bl_order of the last bit length code to send. - */ - max_blindex = build_bl_tree(s); - - /* Determine the best encoding. Compute first the block length in bytes*/ - opt_lenb = (s->opt_len+3+7)>>3; - static_lenb = (s->static_len+3+7)>>3; - - Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", - opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, - s->last_lit)); - - if (static_lenb <= opt_lenb) opt_lenb = static_lenb; - - } else { - Assert(buf != (char*)0, "lost buf"); - opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ - } - - /* If compression failed and this is the first and last block, - * and if the .zip file can be seeked (to rewrite the local header), - * the whole file is transformed into a stored file: - */ -#ifdef STORED_FILE_OK -# ifdef FORCE_STORED_FILE - if (eof && s->compressed_len == 0L) { /* force stored file */ -# else - if (stored_len <= opt_lenb && eof && s->compressed_len==0L && seekable()) { -# endif - /* Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: */ - if (buf == (charf*)0) error ("block vanished"); - - copy_block(s, buf, (unsigned)stored_len, 0); /* without header */ - s->compressed_len = stored_len << 3; - s->method = STORED; - } else -#endif /* STORED_FILE_OK */ - -#ifdef FORCE_STORED - if (buf != (char*)0) { /* force stored block */ -#else - if (stored_len+4 <= opt_lenb && buf != (char*)0) { - /* 4: two words for the lengths */ -#endif - /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. - * Otherwise we can't have processed more than WSIZE input bytes since - * the last block flush, because compression would have been - * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to - * transform a block into a stored block. - */ - _tr_stored_block(s, buf, stored_len, eof); - -#ifdef FORCE_STATIC - } else if (static_lenb >= 0) { /* force static trees */ -#else - } else if (static_lenb == opt_lenb) { -#endif - send_bits(s, (STATIC_TREES<<1)+eof, 3); - compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); - s->compressed_len += 3 + s->static_len; - } else { - send_bits(s, (DYN_TREES<<1)+eof, 3); - send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, - max_blindex+1); - compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); - s->compressed_len += 3 + s->opt_len; - } - Assert (s->compressed_len == s->bits_sent, "bad compressed size"); - init_block(s); - - if (eof) { - bi_windup(s); - s->compressed_len += 7; /* align on byte boundary */ - } - Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, - s->compressed_len-7*eof)); - - return s->compressed_len >> 3; -} - -/* =========================================================================== - * Save the match info and tally the frequency counts. Return true if - * the current block must be flushed. - */ -int _tr_tally (s, dist, lc) - deflate_state *s; - unsigned dist; /* distance of matched string */ - unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ -{ - s->d_buf[s->last_lit] = (ush)dist; - s->l_buf[s->last_lit++] = (uch)lc; - if (dist == 0) { - /* lc is the unmatched char */ - s->dyn_ltree[lc].Freq++; - } else { - s->matches++; - /* Here, lc is the match length - MIN_MATCH */ - dist--; /* dist = match distance - 1 */ - Assert((ush)dist < (ush)MAX_DIST(s) && - (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && - (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); - - s->dyn_ltree[length_code[lc]+LITERALS+1].Freq++; - s->dyn_dtree[d_code(dist)].Freq++; - } - - /* Try to guess if it is profitable to stop the current block here */ - if (s->level > 2 && (s->last_lit & 0xfff) == 0) { - /* Compute an upper bound for the compressed length */ - ulg out_length = (ulg)s->last_lit*8L; - ulg in_length = (ulg)((long)s->strstart - s->block_start); - int dcode; - for (dcode = 0; dcode < D_CODES; dcode++) { - out_length += (ulg)s->dyn_dtree[dcode].Freq * - (5L+extra_dbits[dcode]); - } - out_length >>= 3; - Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", - s->last_lit, in_length, out_length, - 100L - out_length*100L/in_length)); - if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; - } - return (s->last_lit == s->lit_bufsize-1); - /* We avoid equality with lit_bufsize because of wraparound at 64K - * on 16 bit machines and because stored blocks are restricted to - * 64K-1 bytes. - */ -} - -/* =========================================================================== - * Send the block data compressed using the given Huffman trees - */ -local void compress_block(s, ltree, dtree) - deflate_state *s; - ct_data *ltree; /* literal tree */ - ct_data *dtree; /* distance tree */ -{ - unsigned dist; /* distance of matched string */ - int lc; /* match length or unmatched char (if dist == 0) */ - unsigned lx = 0; /* running index in l_buf */ - unsigned code; /* the code to send */ - int extra; /* number of extra bits to send */ - - if (s->last_lit != 0) do { - dist = s->d_buf[lx]; - lc = s->l_buf[lx++]; - if (dist == 0) { - send_code(s, lc, ltree); /* send a literal byte */ - Tracecv(isgraph(lc), (stderr," '%c' ", lc)); - } else { - /* Here, lc is the match length - MIN_MATCH */ - code = length_code[lc]; - send_code(s, code+LITERALS+1, ltree); /* send the length code */ - extra = extra_lbits[code]; - if (extra != 0) { - lc -= base_length[code]; - send_bits(s, lc, extra); /* send the extra length bits */ - } - dist--; /* dist is now the match distance - 1 */ - code = d_code(dist); - Assert (code < D_CODES, "bad d_code"); - - send_code(s, code, dtree); /* send the distance code */ - extra = extra_dbits[code]; - if (extra != 0) { - dist -= base_dist[code]; - send_bits(s, dist, extra); /* send the extra distance bits */ - } - } /* literal or match pair ? */ - - /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ - Assert(s->pending < s->lit_bufsize + 2*lx, "pendingBuf overflow"); - - } while (lx < s->last_lit); - - send_code(s, END_BLOCK, ltree); - s->last_eob_len = ltree[END_BLOCK].Len; -} - -/* =========================================================================== - * Set the data type to ASCII or BINARY, using a crude approximation: - * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. - * IN assertion: the fields freq of dyn_ltree are set and the total of all - * frequencies does not exceed 64K (to fit in an int on 16 bit machines). - */ -local void set_data_type(s) - deflate_state *s; -{ - int n = 0; - unsigned ascii_freq = 0; - unsigned bin_freq = 0; - while (n < 7) bin_freq += s->dyn_ltree[n++].Freq; - while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq; - while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq; - s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII); -} - -/* =========================================================================== - * Reverse the first len bits of a code, using straightforward code (a faster - * method would use a table) - * IN assertion: 1 <= len <= 15 - */ -local unsigned bi_reverse(code, len) - unsigned code; /* the value to invert */ - int len; /* its bit length */ -{ - register unsigned res = 0; - do { - res |= code & 1; - code >>= 1, res <<= 1; - } while (--len > 0); - return res >> 1; -} - -/* =========================================================================== - * Flush the bit buffer, keeping at most 7 bits in it. - */ -local void bi_flush(s) - deflate_state *s; -{ - if (s->bi_valid == 16) { - put_short(s, s->bi_buf); - s->bi_buf = 0; - s->bi_valid = 0; - } else if (s->bi_valid >= 8) { - put_byte(s, (Byte)s->bi_buf); - s->bi_buf >>= 8; - s->bi_valid -= 8; - } -} - -/* =========================================================================== - * Flush the bit buffer and align the output on a byte boundary - */ -local void bi_windup(s) - deflate_state *s; -{ - if (s->bi_valid > 8) { - put_short(s, s->bi_buf); - } else if (s->bi_valid > 0) { - put_byte(s, (Byte)s->bi_buf); - } - s->bi_buf = 0; - s->bi_valid = 0; -#ifdef DEBUG_ZLIB - s->bits_sent = (s->bits_sent+7) & ~7; -#endif -} - -/* =========================================================================== - * Copy a stored block, storing first the length and its - * one's complement if requested. - */ -local void copy_block(s, buf, len, header) - deflate_state *s; - charf *buf; /* the input data */ - unsigned len; /* its length */ - int header; /* true if block header must be written */ -{ - bi_windup(s); /* align on byte boundary */ - s->last_eob_len = 8; /* enough lookahead for inflate */ - - if (header) { - put_short(s, (ush)len); - put_short(s, (ush)~len); -#ifdef DEBUG_ZLIB - s->bits_sent += 2*16; -#endif - } -#ifdef DEBUG_ZLIB - s->bits_sent += (ulg)len<<3; -#endif - /* bundle up the put_byte(s, *buf++) calls */ - zmemcpy(&s->pending_buf[s->pending], buf, len); - s->pending += len; -} -/* --- trees.c */ - -/* +++ inflate.c */ -/* inflate.c -- zlib interface to inflate modules - * Copyright (C) 1995-1996 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* #include "zutil.h" */ - -/* +++ infblock.h */ -/* infblock.h -- header to use infblock.c - * Copyright (C) 1995-1996 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -struct inflate_blocks_state; -typedef struct inflate_blocks_state FAR inflate_blocks_statef; - -extern inflate_blocks_statef * inflate_blocks_new OF(( - z_streamp z, - check_func c, /* check function */ - uInt w)); /* window size */ - -extern int inflate_blocks OF(( - inflate_blocks_statef *, - z_streamp , - int)); /* initial return code */ - -extern void inflate_blocks_reset OF(( - inflate_blocks_statef *, - z_streamp , - uLongf *)); /* check value on output */ - -extern int inflate_blocks_free OF(( - inflate_blocks_statef *, - z_streamp , - uLongf *)); /* check value on output */ - -extern void inflate_set_dictionary OF(( - inflate_blocks_statef *s, - const Bytef *d, /* dictionary */ - uInt n)); /* dictionary length */ - -extern int inflate_addhistory OF(( - inflate_blocks_statef *, - z_streamp)); - -extern int inflate_packet_flush OF(( - inflate_blocks_statef *)); -/* --- infblock.h */ - -#ifndef NO_DUMMY_DECL -struct inflate_blocks_state {int dummy;}; /* for buggy compilers */ -#endif - -/* inflate private state */ -struct internal_state { - - /* mode */ - enum { - METHOD, /* waiting for method byte */ - FLAG, /* waiting for flag byte */ - DICT4, /* four dictionary check bytes to go */ - DICT3, /* three dictionary check bytes to go */ - DICT2, /* two dictionary check bytes to go */ - DICT1, /* one dictionary check byte to go */ - DICT0, /* waiting for inflateSetDictionary */ - BLOCKS, /* decompressing blocks */ - CHECK4, /* four check bytes to go */ - CHECK3, /* three check bytes to go */ - CHECK2, /* two check bytes to go */ - CHECK1, /* one check byte to go */ - DONE, /* finished check, done */ - BAD} /* got an error--stay here */ - mode; /* current inflate mode */ - - /* mode dependent information */ - union { - uInt method; /* if FLAGS, method byte */ - struct { - uLong was; /* computed check value */ - uLong need; /* stream check value */ - } check; /* if CHECK, check values to compare */ - uInt marker; /* if BAD, inflateSync's marker bytes count */ - } sub; /* submode */ - - /* mode independent information */ - int nowrap; /* flag for no wrapper */ - uInt wbits; /* log2(window size) (8..15, defaults to 15) */ - inflate_blocks_statef - *blocks; /* current inflate_blocks state */ - -}; - - -int inflateReset(z) -z_streamp z; -{ - uLong c; - - if (z == Z_NULL || z->state == Z_NULL) - return Z_STREAM_ERROR; - z->total_in = z->total_out = 0; - z->msg = Z_NULL; - z->state->mode = z->state->nowrap ? BLOCKS : METHOD; - inflate_blocks_reset(z->state->blocks, z, &c); - Trace((stderr, "inflate: reset\n")); - return Z_OK; -} - - -int inflateEnd(z) -z_streamp z; -{ - uLong c; - - if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL) - return Z_STREAM_ERROR; - if (z->state->blocks != Z_NULL) - inflate_blocks_free(z->state->blocks, z, &c); - ZFREE(z, z->state); - z->state = Z_NULL; - Trace((stderr, "inflate: end\n")); - return Z_OK; -} - - -int inflateInit2_(z, w, version, stream_size) -z_streamp z; -int w; -const char *version; -int stream_size; -{ - if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || - stream_size != sizeof(z_stream)) - return Z_VERSION_ERROR; - - /* initialize state */ - if (z == Z_NULL) - return Z_STREAM_ERROR; - z->msg = Z_NULL; -#ifndef NO_ZCFUNCS - if (z->zalloc == Z_NULL) - { - z->zalloc = zcalloc; - z->opaque = (voidpf)0; - } - if (z->zfree == Z_NULL) z->zfree = zcfree; -#endif - if ((z->state = (struct internal_state FAR *) - ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL) - return Z_MEM_ERROR; - z->state->blocks = Z_NULL; - - /* handle undocumented nowrap option (no zlib header or check) */ - z->state->nowrap = 0; - if (w < 0) - { - w = - w; - z->state->nowrap = 1; - } - - /* set window size */ - if (w < 8 || w > 15) - { - inflateEnd(z); - return Z_STREAM_ERROR; - } - z->state->wbits = (uInt)w; - - /* create inflate_blocks state */ - if ((z->state->blocks = - inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w)) - == Z_NULL) - { - inflateEnd(z); - return Z_MEM_ERROR; - } - Trace((stderr, "inflate: allocated\n")); - - /* reset state */ - inflateReset(z); - return Z_OK; -} - - -int inflateInit_(z, version, stream_size) -z_streamp z; -const char *version; -int stream_size; -{ - return inflateInit2_(z, DEF_WBITS, version, stream_size); -} - - -#define NEEDBYTE {if(z->avail_in==0)goto empty;r=Z_OK;} -#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++) - -int inflate(z, f) -z_streamp z; -int f; -{ - int r; - uInt b; - - if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL || f < 0) - return Z_STREAM_ERROR; - r = Z_BUF_ERROR; - while (1) switch (z->state->mode) - { - case METHOD: - NEEDBYTE - if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED) - { - z->state->mode = BAD; - z->msg = (char*)"unknown compression method"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - if ((z->state->sub.method >> 4) + 8 > z->state->wbits) - { - z->state->mode = BAD; - z->msg = (char*)"invalid window size"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - z->state->mode = FLAG; - case FLAG: - NEEDBYTE - b = NEXTBYTE; - if (((z->state->sub.method << 8) + b) % 31) - { - z->state->mode = BAD; - z->msg = (char*)"incorrect header check"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - Trace((stderr, "inflate: zlib header ok\n")); - if (!(b & PRESET_DICT)) - { - z->state->mode = BLOCKS; - break; - } - z->state->mode = DICT4; - case DICT4: - NEEDBYTE - z->state->sub.check.need = (uLong)NEXTBYTE << 24; - z->state->mode = DICT3; - case DICT3: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE << 16; - z->state->mode = DICT2; - case DICT2: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE << 8; - z->state->mode = DICT1; - case DICT1: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE; - z->adler = z->state->sub.check.need; - z->state->mode = DICT0; - return Z_NEED_DICT; - case DICT0: - z->state->mode = BAD; - z->msg = (char*)"need dictionary"; - z->state->sub.marker = 0; /* can try inflateSync */ - return Z_STREAM_ERROR; - case BLOCKS: - r = inflate_blocks(z->state->blocks, z, r); - if (f == Z_PACKET_FLUSH && z->avail_in == 0 && z->avail_out != 0) - r = inflate_packet_flush(z->state->blocks); - if (r == Z_DATA_ERROR) - { - z->state->mode = BAD; - z->state->sub.marker = 0; /* can try inflateSync */ - break; - } - if (r != Z_STREAM_END) - return r; - r = Z_OK; - inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was); - if (z->state->nowrap) - { - z->state->mode = DONE; - break; - } - z->state->mode = CHECK4; - case CHECK4: - NEEDBYTE - z->state->sub.check.need = (uLong)NEXTBYTE << 24; - z->state->mode = CHECK3; - case CHECK3: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE << 16; - z->state->mode = CHECK2; - case CHECK2: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE << 8; - z->state->mode = CHECK1; - case CHECK1: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE; - - if (z->state->sub.check.was != z->state->sub.check.need) - { - z->state->mode = BAD; - z->msg = (char*)"incorrect data check"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - Trace((stderr, "inflate: zlib check ok\n")); - z->state->mode = DONE; - case DONE: - return Z_STREAM_END; - case BAD: - return Z_DATA_ERROR; - default: - return Z_STREAM_ERROR; - } - - empty: - if (f != Z_PACKET_FLUSH) - return r; - z->state->mode = BAD; - z->msg = (char *)"need more for packet flush"; - z->state->sub.marker = 0; /* can try inflateSync */ - return Z_DATA_ERROR; -} - - -int inflateSetDictionary(z, dictionary, dictLength) -z_streamp z; -const Bytef *dictionary; -uInt dictLength; -{ - uInt length = dictLength; - - if (z == Z_NULL || z->state == Z_NULL || z->state->mode != DICT0) - return Z_STREAM_ERROR; - - if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR; - z->adler = 1L; - - if (length >= ((uInt)1<state->wbits)) - { - length = (1<state->wbits)-1; - dictionary += dictLength - length; - } - inflate_set_dictionary(z->state->blocks, dictionary, length); - z->state->mode = BLOCKS; - return Z_OK; -} - -/* - * This subroutine adds the data at next_in/avail_in to the output history - * without performing any output. The output buffer must be "caught up"; - * i.e. no pending output (hence s->read equals s->write), and the state must - * be BLOCKS (i.e. we should be willing to see the start of a series of - * BLOCKS). On exit, the output will also be caught up, and the checksum - * will have been updated if need be. - */ - -int inflateIncomp(z) -z_stream *z; -{ - if (z->state->mode != BLOCKS) - return Z_DATA_ERROR; - return inflate_addhistory(z->state->blocks, z); -} - - -int inflateSync(z) -z_streamp z; -{ - uInt n; /* number of bytes to look at */ - Bytef *p; /* pointer to bytes */ - uInt m; /* number of marker bytes found in a row */ - uLong r, w; /* temporaries to save total_in and total_out */ - - /* set up */ - if (z == Z_NULL || z->state == Z_NULL) - return Z_STREAM_ERROR; - if (z->state->mode != BAD) - { - z->state->mode = BAD; - z->state->sub.marker = 0; - } - if ((n = z->avail_in) == 0) - return Z_BUF_ERROR; - p = z->next_in; - m = z->state->sub.marker; - - /* search */ - while (n && m < 4) - { - if (*p == (Byte)(m < 2 ? 0 : 0xff)) - m++; - else if (*p) - m = 0; - else - m = 4 - m; - p++, n--; - } - - /* restore */ - z->total_in += p - z->next_in; - z->next_in = p; - z->avail_in = n; - z->state->sub.marker = m; - - /* return no joy or set up to restart on a new block */ - if (m != 4) - return Z_DATA_ERROR; - r = z->total_in; w = z->total_out; - inflateReset(z); - z->total_in = r; z->total_out = w; - z->state->mode = BLOCKS; - return Z_OK; -} - -#undef NEEDBYTE -#undef NEXTBYTE -/* --- inflate.c */ - -/* +++ infblock.c */ -/* infblock.c -- interpret and process block types to last block - * Copyright (C) 1995-1996 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* #include "zutil.h" */ -/* #include "infblock.h" */ - -/* +++ inftrees.h */ -/* inftrees.h -- header to use inftrees.c - * Copyright (C) 1995-1996 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* Huffman code lookup table entry--this entry is four bytes for machines - that have 16-bit pointers (e.g. PC's in the small or medium model). */ - -typedef struct inflate_huft_s FAR inflate_huft; - -struct inflate_huft_s { - union { - struct { - Byte Exop; /* number of extra bits or operation */ - Byte Bits; /* number of bits in this code or subcode */ - } what; - Bytef *pad; /* pad structure to a power of 2 (4 bytes for */ - } word; /* 16-bit, 8 bytes for 32-bit machines) */ - union { - uInt Base; /* literal, length base, or distance base */ - inflate_huft *Next; /* pointer to next level of table */ - } more; -}; - -#ifdef DEBUG_ZLIB - extern uInt inflate_hufts; -#endif - -extern int inflate_trees_bits OF(( - uIntf *, /* 19 code lengths */ - uIntf *, /* bits tree desired/actual depth */ - inflate_huft * FAR *, /* bits tree result */ - z_streamp )); /* for zalloc, zfree functions */ - -extern int inflate_trees_dynamic OF(( - uInt, /* number of literal/length codes */ - uInt, /* number of distance codes */ - uIntf *, /* that many (total) code lengths */ - uIntf *, /* literal desired/actual bit depth */ - uIntf *, /* distance desired/actual bit depth */ - inflate_huft * FAR *, /* literal/length tree result */ - inflate_huft * FAR *, /* distance tree result */ - z_streamp )); /* for zalloc, zfree functions */ - -extern int inflate_trees_fixed OF(( - uIntf *, /* literal desired/actual bit depth */ - uIntf *, /* distance desired/actual bit depth */ - inflate_huft * FAR *, /* literal/length tree result */ - inflate_huft * FAR *)); /* distance tree result */ - -extern int inflate_trees_free OF(( - inflate_huft *, /* tables to free */ - z_streamp )); /* for zfree function */ - -/* --- inftrees.h */ - -/* +++ infcodes.h */ -/* infcodes.h -- header to use infcodes.c - * Copyright (C) 1995-1996 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -struct inflate_codes_state; -typedef struct inflate_codes_state FAR inflate_codes_statef; - -extern inflate_codes_statef *inflate_codes_new OF(( - uInt, uInt, - inflate_huft *, inflate_huft *, - z_streamp )); - -extern int inflate_codes OF(( - inflate_blocks_statef *, - z_streamp , - int)); - -extern void inflate_codes_free OF(( - inflate_codes_statef *, - z_streamp )); - -/* --- infcodes.h */ - -/* +++ infutil.h */ -/* infutil.h -- types and macros common to blocks and codes - * Copyright (C) 1995-1996 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -#ifndef _INFUTIL_H -#define _INFUTIL_H - -typedef enum { - TYPE, /* get type bits (3, including end bit) */ - LENS, /* get lengths for stored */ - STORED, /* processing stored block */ - TABLE, /* get table lengths */ - BTREE, /* get bit lengths tree for a dynamic block */ - DTREE, /* get length, distance trees for a dynamic block */ - CODES, /* processing fixed or dynamic block */ - DRY, /* output remaining window bytes */ - DONEB, /* finished last block, done */ - BADB} /* got a data error--stuck here */ -inflate_block_mode; - -/* inflate blocks semi-private state */ -struct inflate_blocks_state { - - /* mode */ - inflate_block_mode mode; /* current inflate_block mode */ - - /* mode dependent information */ - union { - uInt left; /* if STORED, bytes left to copy */ - struct { - uInt table; /* table lengths (14 bits) */ - uInt index; /* index into blens (or border) */ - uIntf *blens; /* bit lengths of codes */ - uInt bb; /* bit length tree depth */ - inflate_huft *tb; /* bit length decoding tree */ - } trees; /* if DTREE, decoding info for trees */ - struct { - inflate_huft *tl; - inflate_huft *td; /* trees to free */ - inflate_codes_statef - *codes; - } decode; /* if CODES, current state */ - } sub; /* submode */ - uInt last; /* true if this block is the last block */ - - /* mode independent information */ - uInt bitk; /* bits in bit buffer */ - uLong bitb; /* bit buffer */ - Bytef *window; /* sliding window */ - Bytef *end; /* one byte after sliding window */ - Bytef *read; /* window read pointer */ - Bytef *write; /* window write pointer */ - check_func checkfn; /* check function */ - uLong check; /* check on output */ - -}; - - -/* defines for inflate input/output */ -/* update pointers and return */ -#define UPDBITS {s->bitb=b;s->bitk=k;} -#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;} -#define UPDOUT {s->write=q;} -#define UPDATE {UPDBITS UPDIN UPDOUT} -#define LEAVE {UPDATE return inflate_flush(s,z,r);} -/* get bytes and bits */ -#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;} -#define NEEDBYTE {if(n)r=Z_OK;else LEAVE} -#define NEXTBYTE (n--,*p++) -#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<>=(j);k-=(j);} -/* output bytes */ -#define WAVAIL (uInt)(qread?s->read-q-1:s->end-q) -#define LOADOUT {q=s->write;m=(uInt)WAVAIL;} -#define WWRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}} -#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT} -#define NEEDOUT {if(m==0){WWRAP if(m==0){FLUSH WWRAP if(m==0) LEAVE}}r=Z_OK;} -#define OUTBYTE(a) {*q++=(Byte)(a);m--;} -/* load local pointers */ -#define LOAD {LOADIN LOADOUT} - -/* masks for lower bits (size given to avoid silly warnings with Visual C++) */ -extern uInt inflate_mask[17]; - -/* copy as much as possible from the sliding window to the output area */ -extern int inflate_flush OF(( - inflate_blocks_statef *, - z_streamp , - int)); - -#ifndef NO_DUMMY_DECL -struct internal_state {int dummy;}; /* for buggy compilers */ -#endif - -#endif -/* --- infutil.h */ - -#ifndef NO_DUMMY_DECL -struct inflate_codes_state {int dummy;}; /* for buggy compilers */ -#endif - -/* Table for deflate from PKZIP's appnote.txt. */ -local const uInt border[] = { /* Order of the bit length code lengths */ - 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - -/* - Notes beyond the 1.93a appnote.txt: - - 1. Distance pointers never point before the beginning of the output - stream. - 2. Distance pointers can point back across blocks, up to 32k away. - 3. There is an implied maximum of 7 bits for the bit length table and - 15 bits for the actual data. - 4. If only one code exists, then it is encoded using one bit. (Zero - would be more efficient, but perhaps a little confusing.) If two - codes exist, they are coded using one bit each (0 and 1). - 5. There is no way of sending zero distance codes--a dummy must be - sent if there are none. (History: a pre 2.0 version of PKZIP would - store blocks with no distance codes, but this was discovered to be - too harsh a criterion.) Valid only for 1.93a. 2.04c does allow - zero distance codes, which is sent as one code of zero bits in - length. - 6. There are up to 286 literal/length codes. Code 256 represents the - end-of-block. Note however that the static length tree defines - 288 codes just to fill out the Huffman codes. Codes 286 and 287 - cannot be used though, since there is no length base or extra bits - defined for them. Similarily, there are up to 30 distance codes. - However, static trees define 32 codes (all 5 bits) to fill out the - Huffman codes, but the last two had better not show up in the data. - 7. Unzip can check dynamic Huffman blocks for complete code sets. - The exception is that a single code would not be complete (see #4). - 8. The five bits following the block type is really the number of - literal codes sent minus 257. - 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits - (1+6+6). Therefore, to output three times the length, you output - three codes (1+1+1), whereas to output four times the same length, - you only need two codes (1+3). Hmm. - 10. In the tree reconstruction algorithm, Code = Code + Increment - only if BitLength(i) is not zero. (Pretty obvious.) - 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) - 12. Note: length code 284 can represent 227-258, but length code 285 - really is 258. The last length deserves its own, short code - since it gets used a lot in very redundant files. The length - 258 is special since 258 - 3 (the min match length) is 255. - 13. The literal/length and distance code bit lengths are read as a - single stream of lengths. It is possible (and advantageous) for - a repeat code (16, 17, or 18) to go across the boundary between - the two sets of lengths. - */ - - -void inflate_blocks_reset(s, z, c) -inflate_blocks_statef *s; -z_streamp z; -uLongf *c; -{ - if (s->checkfn != Z_NULL) - *c = s->check; - if (s->mode == BTREE || s->mode == DTREE) - ZFREE(z, s->sub.trees.blens); - if (s->mode == CODES) - { - inflate_codes_free(s->sub.decode.codes, z); - inflate_trees_free(s->sub.decode.td, z); - inflate_trees_free(s->sub.decode.tl, z); - } - s->mode = TYPE; - s->bitk = 0; - s->bitb = 0; - s->read = s->write = s->window; - if (s->checkfn != Z_NULL) - z->adler = s->check = (*s->checkfn)(0L, Z_NULL, 0); - Trace((stderr, "inflate: blocks reset\n")); -} - - -inflate_blocks_statef *inflate_blocks_new(z, c, w) -z_streamp z; -check_func c; -uInt w; -{ - inflate_blocks_statef *s; - - if ((s = (inflate_blocks_statef *)ZALLOC - (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL) - return s; - if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL) - { - ZFREE(z, s); - return Z_NULL; - } - s->end = s->window + w; - s->checkfn = c; - s->mode = TYPE; - Trace((stderr, "inflate: blocks allocated\n")); - inflate_blocks_reset(s, z, &s->check); - return s; -} - - -#ifdef DEBUG_ZLIB - extern uInt inflate_hufts; -#endif -int inflate_blocks(s, z, r) -inflate_blocks_statef *s; -z_streamp z; -int r; -{ - uInt t; /* temporary storage */ - uLong b; /* bit buffer */ - uInt k; /* bits in bit buffer */ - Bytef *p; /* input data pointer */ - uInt n; /* bytes available there */ - Bytef *q; /* output window write pointer */ - uInt m; /* bytes to end of window or read pointer */ - - /* copy input/output information to locals (UPDATE macro restores) */ - LOAD - - /* process input based on current state */ - while (1) switch (s->mode) - { - case TYPE: - NEEDBITS(3) - t = (uInt)b & 7; - s->last = t & 1; - switch (t >> 1) - { - case 0: /* stored */ - Trace((stderr, "inflate: stored block%s\n", - s->last ? " (last)" : "")); - DUMPBITS(3) - t = k & 7; /* go to byte boundary */ - DUMPBITS(t) - s->mode = LENS; /* get length of stored block */ - break; - case 1: /* fixed */ - Trace((stderr, "inflate: fixed codes block%s\n", - s->last ? " (last)" : "")); - { - uInt bl, bd; - inflate_huft *tl, *td; - - inflate_trees_fixed(&bl, &bd, &tl, &td); - s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z); - if (s->sub.decode.codes == Z_NULL) - { - r = Z_MEM_ERROR; - LEAVE - } - s->sub.decode.tl = Z_NULL; /* don't try to free these */ - s->sub.decode.td = Z_NULL; - } - DUMPBITS(3) - s->mode = CODES; - break; - case 2: /* dynamic */ - Trace((stderr, "inflate: dynamic codes block%s\n", - s->last ? " (last)" : "")); - DUMPBITS(3) - s->mode = TABLE; - break; - case 3: /* illegal */ - DUMPBITS(3) - s->mode = BADB; - z->msg = (char*)"invalid block type"; - r = Z_DATA_ERROR; - LEAVE - } - break; - case LENS: - NEEDBITS(32) - if ((((~b) >> 16) & 0xffff) != (b & 0xffff)) - { - s->mode = BADB; - z->msg = (char*)"invalid stored block lengths"; - r = Z_DATA_ERROR; - LEAVE - } - s->sub.left = (uInt)b & 0xffff; - b = k = 0; /* dump bits */ - Tracev((stderr, "inflate: stored length %u\n", s->sub.left)); - s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE); - break; - case STORED: - if (n == 0) - LEAVE - NEEDOUT - t = s->sub.left; - if (t > n) t = n; - if (t > m) t = m; - zmemcpy(q, p, t); - p += t; n -= t; - q += t; m -= t; - if ((s->sub.left -= t) != 0) - break; - Tracev((stderr, "inflate: stored end, %lu total out\n", - z->total_out + (q >= s->read ? q - s->read : - (s->end - s->read) + (q - s->window)))); - s->mode = s->last ? DRY : TYPE; - break; - case TABLE: - NEEDBITS(14) - s->sub.trees.table = t = (uInt)b & 0x3fff; -#ifndef PKZIP_BUG_WORKAROUND - if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) - { - s->mode = BADB; - z->msg = (char*)"too many length or distance symbols"; - r = Z_DATA_ERROR; - LEAVE - } -#endif - t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); - if (t < 19) - t = 19; - if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL) - { - r = Z_MEM_ERROR; - LEAVE - } - DUMPBITS(14) - s->sub.trees.index = 0; - Tracev((stderr, "inflate: table sizes ok\n")); - s->mode = BTREE; - case BTREE: - while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10)) - { - NEEDBITS(3) - s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7; - DUMPBITS(3) - } - while (s->sub.trees.index < 19) - s->sub.trees.blens[border[s->sub.trees.index++]] = 0; - s->sub.trees.bb = 7; - t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb, - &s->sub.trees.tb, z); - if (t != Z_OK) - { - r = t; - if (r == Z_DATA_ERROR) - { - ZFREE(z, s->sub.trees.blens); - s->mode = BADB; - } - LEAVE - } - s->sub.trees.index = 0; - Tracev((stderr, "inflate: bits tree ok\n")); - s->mode = DTREE; - case DTREE: - while (t = s->sub.trees.table, - s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)) - { - inflate_huft *h; - uInt i, j, c; - - t = s->sub.trees.bb; - NEEDBITS(t) - h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]); - t = h->word.what.Bits; - c = h->more.Base; - if (c < 16) - { - DUMPBITS(t) - s->sub.trees.blens[s->sub.trees.index++] = c; - } - else /* c == 16..18 */ - { - i = c == 18 ? 7 : c - 14; - j = c == 18 ? 11 : 3; - NEEDBITS(t + i) - DUMPBITS(t) - j += (uInt)b & inflate_mask[i]; - DUMPBITS(i) - i = s->sub.trees.index; - t = s->sub.trees.table; - if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || - (c == 16 && i < 1)) - { - inflate_trees_free(s->sub.trees.tb, z); - ZFREE(z, s->sub.trees.blens); - s->mode = BADB; - z->msg = (char*)"invalid bit length repeat"; - r = Z_DATA_ERROR; - LEAVE - } - c = c == 16 ? s->sub.trees.blens[i - 1] : 0; - do { - s->sub.trees.blens[i++] = c; - } while (--j); - s->sub.trees.index = i; - } - } - inflate_trees_free(s->sub.trees.tb, z); - s->sub.trees.tb = Z_NULL; - { - uInt bl, bd; - inflate_huft *tl, *td; - inflate_codes_statef *c; - - bl = 9; /* must be <= 9 for lookahead assumptions */ - bd = 6; /* must be <= 9 for lookahead assumptions */ - t = s->sub.trees.table; -#ifdef DEBUG_ZLIB - inflate_hufts = 0; -#endif - t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), - s->sub.trees.blens, &bl, &bd, &tl, &td, z); - if (t != Z_OK) - { - if (t == (uInt)Z_DATA_ERROR) - { - ZFREE(z, s->sub.trees.blens); - s->mode = BADB; - } - r = t; - LEAVE - } - Tracev((stderr, "inflate: trees ok, %d * %d bytes used\n", - inflate_hufts, sizeof(inflate_huft))); - if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL) - { - inflate_trees_free(td, z); - inflate_trees_free(tl, z); - r = Z_MEM_ERROR; - LEAVE - } - ZFREE(z, s->sub.trees.blens); - s->sub.decode.codes = c; - s->sub.decode.tl = tl; - s->sub.decode.td = td; - } - s->mode = CODES; - case CODES: - UPDATE - if ((r = inflate_codes(s, z, r)) != Z_STREAM_END) - return inflate_flush(s, z, r); - r = Z_OK; - inflate_codes_free(s->sub.decode.codes, z); - inflate_trees_free(s->sub.decode.td, z); - inflate_trees_free(s->sub.decode.tl, z); - LOAD - Tracev((stderr, "inflate: codes end, %lu total out\n", - z->total_out + (q >= s->read ? q - s->read : - (s->end - s->read) + (q - s->window)))); - if (!s->last) - { - s->mode = TYPE; - break; - } - if (k > 7) /* return unused byte, if any */ - { - Assert(k < 16, "inflate_codes grabbed too many bytes") - k -= 8; - n++; - p--; /* can always return one */ - } - s->mode = DRY; - case DRY: - FLUSH - if (s->read != s->write) - LEAVE - s->mode = DONEB; - case DONEB: - r = Z_STREAM_END; - LEAVE - case BADB: - r = Z_DATA_ERROR; - LEAVE - default: - r = Z_STREAM_ERROR; - LEAVE - } -} - - -int inflate_blocks_free(s, z, c) -inflate_blocks_statef *s; -z_streamp z; -uLongf *c; -{ - inflate_blocks_reset(s, z, c); - ZFREE(z, s->window); - ZFREE(z, s); - Trace((stderr, "inflate: blocks freed\n")); - return Z_OK; -} - - -void inflate_set_dictionary(s, d, n) -inflate_blocks_statef *s; -const Bytef *d; -uInt n; -{ - zmemcpy((charf *)s->window, d, n); - s->read = s->write = s->window + n; -} - -/* - * This subroutine adds the data at next_in/avail_in to the output history - * without performing any output. The output buffer must be "caught up"; - * i.e. no pending output (hence s->read equals s->write), and the state must - * be BLOCKS (i.e. we should be willing to see the start of a series of - * BLOCKS). On exit, the output will also be caught up, and the checksum - * will have been updated if need be. - */ -int inflate_addhistory(s, z) -inflate_blocks_statef *s; -z_stream *z; -{ - uLong b; /* bit buffer */ /* NOT USED HERE */ - uInt k; /* bits in bit buffer */ /* NOT USED HERE */ - uInt t; /* temporary storage */ - Bytef *p; /* input data pointer */ - uInt n; /* bytes available there */ - Bytef *q; /* output window write pointer */ - uInt m; /* bytes to end of window or read pointer */ - - if (s->read != s->write) - return Z_STREAM_ERROR; - if (s->mode != TYPE) - return Z_DATA_ERROR; - - /* we're ready to rock */ - LOAD - /* while there is input ready, copy to output buffer, moving - * pointers as needed. - */ - while (n) { - t = n; /* how many to do */ - /* is there room until end of buffer? */ - if (t > m) t = m; - /* update check information */ - if (s->checkfn != Z_NULL) - s->check = (*s->checkfn)(s->check, q, t); - zmemcpy(q, p, t); - q += t; - p += t; - n -= t; - z->total_out += t; - s->read = q; /* drag read pointer forward */ -/* WWRAP */ /* expand WWRAP macro by hand to handle s->read */ - if (q == s->end) { - s->read = q = s->window; - m = WAVAIL; - } - } - UPDATE - return Z_OK; -} - - -/* - * At the end of a Deflate-compressed PPP packet, we expect to have seen - * a `stored' block type value but not the (zero) length bytes. - */ -int inflate_packet_flush(s) - inflate_blocks_statef *s; -{ - if (s->mode != LENS) - return Z_DATA_ERROR; - s->mode = TYPE; - return Z_OK; -} -/* --- infblock.c */ - -/* +++ inftrees.c */ -/* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-1996 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* #include "zutil.h" */ -/* #include "inftrees.h" */ - -char inflate_copyright[] = " inflate 1.0.4 Copyright 1995-1996 Mark Adler "; -/* - If you use the zlib library in a product, an acknowledgment is welcome - in the documentation of your product. If for some reason you cannot - include such an acknowledgment, I would appreciate that you keep this - copyright string in the executable of your product. - */ - -#ifndef NO_DUMMY_DECL -struct internal_state {int dummy;}; /* for buggy compilers */ -#endif - -/* simplify the use of the inflate_huft type with some defines */ -#define base more.Base -#define next more.Next -#define exop word.what.Exop -#define bits word.what.Bits - - -local int huft_build OF(( - uIntf *, /* code lengths in bits */ - uInt, /* number of codes */ - uInt, /* number of "simple" codes */ - const uIntf *, /* list of base values for non-simple codes */ - const uIntf *, /* list of extra bits for non-simple codes */ - inflate_huft * FAR*,/* result: starting table */ - uIntf *, /* maximum lookup bits (returns actual) */ - z_streamp )); /* for zalloc function */ - -local voidpf falloc OF(( - voidpf, /* opaque pointer (not used) */ - uInt, /* number of items */ - uInt)); /* size of item */ - -/* Tables for deflate from PKZIP's appnote.txt. */ -local const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; - /* see note #13 above about 258 */ -local const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */ - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, - 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */ -local const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */ - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577}; -local const uInt cpdext[30] = { /* Extra bits for distance codes */ - 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, - 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, - 12, 12, 13, 13}; - -/* - Huffman code decoding is performed using a multi-level table lookup. - The fastest way to decode is to simply build a lookup table whose - size is determined by the longest code. However, the time it takes - to build this table can also be a factor if the data being decoded - is not very long. The most common codes are necessarily the - shortest codes, so those codes dominate the decoding time, and hence - the speed. The idea is you can have a shorter table that decodes the - shorter, more probable codes, and then point to subsidiary tables for - the longer codes. The time it costs to decode the longer codes is - then traded against the time it takes to make longer tables. - - This results of this trade are in the variables lbits and dbits - below. lbits is the number of bits the first level table for literal/ - length codes can decode in one step, and dbits is the same thing for - the distance codes. Subsequent tables are also less than or equal to - those sizes. These values may be adjusted either when all of the - codes are shorter than that, in which case the longest code length in - bits is used, or when the shortest code is *longer* than the requested - table size, in which case the length of the shortest code in bits is - used. - - There are two different values for the two tables, since they code a - different number of possibilities each. The literal/length table - codes 286 possible values, or in a flat code, a little over eight - bits. The distance table codes 30 possible values, or a little less - than five bits, flat. The optimum values for speed end up being - about one bit more than those, so lbits is 8+1 and dbits is 5+1. - The optimum values may differ though from machine to machine, and - possibly even between compilers. Your mileage may vary. - */ - - -/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */ -#define BMAX 15 /* maximum bit length of any code */ -#define N_MAX 288 /* maximum number of codes in any set */ - -#ifdef DEBUG_ZLIB - uInt inflate_hufts; -#endif - -local int huft_build(b, n, s, d, e, t, m, zs) -uIntf *b; /* code lengths in bits (all assumed <= BMAX) */ -uInt n; /* number of codes (assumed <= N_MAX) */ -uInt s; /* number of simple-valued codes (0..s-1) */ -const uIntf *d; /* list of base values for non-simple codes */ -const uIntf *e; /* list of extra bits for non-simple codes */ -inflate_huft * FAR *t; /* result: starting table */ -uIntf *m; /* maximum lookup bits, returns actual */ -z_streamp zs; /* for zalloc function */ -/* Given a list of code lengths and a maximum table size, make a set of - tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR - if the given code set is incomplete (the tables are still built in this - case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of - lengths), or Z_MEM_ERROR if not enough memory. */ -{ - - uInt a; /* counter for codes of length k */ - uInt c[BMAX+1]; /* bit length count table */ - uInt f; /* i repeats in table every f entries */ - int g; /* maximum code length */ - int h; /* table level */ - register uInt i; /* counter, current code */ - register uInt j; /* counter */ - register int k; /* number of bits in current code */ - int l; /* bits per table (returned in m) */ - register uIntf *p; /* pointer into c[], b[], or v[] */ - inflate_huft *q; /* points to current table */ - struct inflate_huft_s r; /* table entry for structure assignment */ - inflate_huft *u[BMAX]; /* table stack */ - uInt v[N_MAX]; /* values in order of bit length */ - register int w; /* bits before this table == (l * h) */ - uInt x[BMAX+1]; /* bit offsets, then code stack */ - uIntf *xp; /* pointer into x */ - int y; /* number of dummy codes added */ - uInt z; /* number of entries in current table */ - - - /* Generate counts for each bit length */ - p = c; -#define C0 *p++ = 0; -#define C2 C0 C0 C0 C0 -#define C4 C2 C2 C2 C2 - C4 /* clear c[]--assume BMAX+1 is 16 */ - p = b; i = n; - do { - c[*p++]++; /* assume all entries <= BMAX */ - } while (--i); - if (c[0] == n) /* null input--all zero length codes */ - { - *t = (inflate_huft *)Z_NULL; - *m = 0; - return Z_OK; - } - - - /* Find minimum and maximum length, bound *m by those */ - l = *m; - for (j = 1; j <= BMAX; j++) - if (c[j]) - break; - k = j; /* minimum code length */ - if ((uInt)l < j) - l = j; - for (i = BMAX; i; i--) - if (c[i]) - break; - g = i; /* maximum code length */ - if ((uInt)l > i) - l = i; - *m = l; - - - /* Adjust last length count to fill out codes, if needed */ - for (y = 1 << j; j < i; j++, y <<= 1) - if ((y -= c[j]) < 0) - return Z_DATA_ERROR; - if ((y -= c[i]) < 0) - return Z_DATA_ERROR; - c[i] += y; - - - /* Generate starting offsets into the value table for each length */ - x[1] = j = 0; - p = c + 1; xp = x + 2; - while (--i) { /* note that i == g from above */ - *xp++ = (j += *p++); - } - - - /* Make a table of values in order of bit lengths */ - p = b; i = 0; - do { - if ((j = *p++) != 0) - v[x[j]++] = i; - } while (++i < n); - n = x[g]; /* set n to length of v */ - - - /* Generate the Huffman codes and for each, make the table entries */ - x[0] = i = 0; /* first Huffman code is zero */ - p = v; /* grab values in bit order */ - h = -1; /* no tables yet--level -1 */ - w = -l; /* bits decoded == (l * h) */ - u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */ - q = (inflate_huft *)Z_NULL; /* ditto */ - z = 0; /* ditto */ - - /* go through the bit lengths (k already is bits in shortest code) */ - for (; k <= g; k++) - { - a = c[k]; - while (a--) - { - /* here i is the Huffman code of length k bits for value *p */ - /* make tables up to required level */ - while (k > w + l) - { - h++; - w += l; /* previous table always l bits */ - - /* compute minimum size table less than or equal to l bits */ - z = g - w; - z = z > (uInt)l ? l : z; /* table size upper limit */ - if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ - { /* too few codes for k-w bit table */ - f -= a + 1; /* deduct codes from patterns left */ - xp = c + k; - if (j < z) - while (++j < z) /* try smaller tables up to z bits */ - { - if ((f <<= 1) <= *++xp) - break; /* enough codes to use up j bits */ - f -= *xp; /* else deduct codes from patterns */ - } - } - z = 1 << j; /* table entries for j-bit table */ - - /* allocate and link in new table */ - if ((q = (inflate_huft *)ZALLOC - (zs,z + 1,sizeof(inflate_huft))) == Z_NULL) - { - if (h) - inflate_trees_free(u[0], zs); - return Z_MEM_ERROR; /* not enough memory */ - } -#ifdef DEBUG_ZLIB - inflate_hufts += z + 1; -#endif - *t = q + 1; /* link to list for huft_free() */ - *(t = &(q->next)) = Z_NULL; - u[h] = ++q; /* table starts after link */ - - /* connect to last table, if there is one */ - if (h) - { - x[h] = i; /* save pattern for backing up */ - r.bits = (Byte)l; /* bits to dump before this table */ - r.exop = (Byte)j; /* bits in this table */ - r.next = q; /* pointer to this table */ - j = i >> (w - l); /* (get around Turbo C bug) */ - u[h-1][j] = r; /* connect to last table */ - } - } - - /* set up table entry in r */ - r.bits = (Byte)(k - w); - if (p >= v + n) - r.exop = 128 + 64; /* out of values--invalid code */ - else if (*p < s) - { - r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */ - r.base = *p++; /* simple code is just the value */ - } - else - { - r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */ - r.base = d[*p++ - s]; - } - - /* fill code-like entries with r */ - f = 1 << (k - w); - for (j = i >> w; j < z; j += f) - q[j] = r; - - /* backwards increment the k-bit code i */ - for (j = 1 << (k - 1); i & j; j >>= 1) - i ^= j; - i ^= j; - - /* backup over finished tables */ - while ((i & ((1 << w) - 1)) != x[h]) - { - h--; /* don't need to update q */ - w -= l; - } - } - } - - - /* Return Z_BUF_ERROR if we were given an incomplete table */ - return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK; -} - - -int inflate_trees_bits(c, bb, tb, z) -uIntf *c; /* 19 code lengths */ -uIntf *bb; /* bits tree desired/actual depth */ -inflate_huft * FAR *tb; /* bits tree result */ -z_streamp z; /* for zfree function */ -{ - int r; - - r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, tb, bb, z); - if (r == Z_DATA_ERROR) - z->msg = (char*)"oversubscribed dynamic bit lengths tree"; - else if (r == Z_BUF_ERROR || *bb == 0) - { - inflate_trees_free(*tb, z); - z->msg = (char*)"incomplete dynamic bit lengths tree"; - r = Z_DATA_ERROR; - } - return r; -} - - -int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, z) -uInt nl; /* number of literal/length codes */ -uInt nd; /* number of distance codes */ -uIntf *c; /* that many (total) code lengths */ -uIntf *bl; /* literal desired/actual bit depth */ -uIntf *bd; /* distance desired/actual bit depth */ -inflate_huft * FAR *tl; /* literal/length tree result */ -inflate_huft * FAR *td; /* distance tree result */ -z_streamp z; /* for zfree function */ -{ - int r; - - /* build literal/length tree */ - r = huft_build(c, nl, 257, cplens, cplext, tl, bl, z); - if (r != Z_OK || *bl == 0) - { - if (r == Z_DATA_ERROR) - z->msg = (char*)"oversubscribed literal/length tree"; - else if (r != Z_MEM_ERROR) - { - inflate_trees_free(*tl, z); - z->msg = (char*)"incomplete literal/length tree"; - r = Z_DATA_ERROR; - } - return r; - } - - /* build distance tree */ - r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, z); - if (r != Z_OK || (*bd == 0 && nl > 257)) - { - if (r == Z_DATA_ERROR) - z->msg = (char*)"oversubscribed distance tree"; - else if (r == Z_BUF_ERROR) { -#ifdef PKZIP_BUG_WORKAROUND - r = Z_OK; - } -#else - inflate_trees_free(*td, z); - z->msg = (char*)"incomplete distance tree"; - r = Z_DATA_ERROR; - } - else if (r != Z_MEM_ERROR) - { - z->msg = (char*)"empty distance tree with lengths"; - r = Z_DATA_ERROR; - } - inflate_trees_free(*tl, z); - return r; -#endif - } - - /* done */ - return Z_OK; -} - - -/* build fixed tables only once--keep them here */ -local int fixed_built = 0; -#define FIXEDH 530 /* number of hufts used by fixed tables */ -local inflate_huft fixed_mem[FIXEDH]; -local uInt fixed_bl; -local uInt fixed_bd; -local inflate_huft *fixed_tl; -local inflate_huft *fixed_td; - - -local voidpf falloc(q, n, s) -voidpf q; /* opaque pointer */ -uInt n; /* number of items */ -uInt s; /* size of item */ -{ - Assert(s == sizeof(inflate_huft) && n <= *(intf *)q, - "inflate_trees falloc overflow"); - *(intf *)q -= n+s-s; /* s-s to avoid warning */ - return (voidpf)(fixed_mem + *(intf *)q); -} - - -int inflate_trees_fixed(bl, bd, tl, td) -uIntf *bl; /* literal desired/actual bit depth */ -uIntf *bd; /* distance desired/actual bit depth */ -inflate_huft * FAR *tl; /* literal/length tree result */ -inflate_huft * FAR *td; /* distance tree result */ -{ - /* build fixed tables if not already (multiple overlapped executions ok) */ - if (!fixed_built) - { - int k; /* temporary variable */ - unsigned c[288]; /* length list for huft_build */ - z_stream z; /* for falloc function */ - int f = FIXEDH; /* number of hufts left in fixed_mem */ - - /* set up fake z_stream for memory routines */ - z.zalloc = falloc; - z.zfree = Z_NULL; - z.opaque = (voidpf)&f; - - /* literal table */ - for (k = 0; k < 144; k++) - c[k] = 8; - for (; k < 256; k++) - c[k] = 9; - for (; k < 280; k++) - c[k] = 7; - for (; k < 288; k++) - c[k] = 8; - fixed_bl = 7; - huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, &z); - - /* distance table */ - for (k = 0; k < 30; k++) - c[k] = 5; - fixed_bd = 5; - huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, &z); - - /* done */ - Assert(f == 0, "invalid build of fixed tables"); - fixed_built = 1; - } - *bl = fixed_bl; - *bd = fixed_bd; - *tl = fixed_tl; - *td = fixed_td; - return Z_OK; -} - - -int inflate_trees_free(t, z) -inflate_huft *t; /* table to free */ -z_streamp z; /* for zfree function */ -/* Free the malloc'ed tables built by huft_build(), which makes a linked - list of the tables it made, with the links in a dummy first entry of - each table. */ -{ - register inflate_huft *p, *q, *r; - - /* Reverse linked list */ - p = Z_NULL; - q = t; - while (q != Z_NULL) - { - r = (q - 1)->next; - (q - 1)->next = p; - p = q; - q = r; - } - /* Go through linked list, freeing from the malloced (t[-1]) address. */ - while (p != Z_NULL) - { - q = (--p)->next; - ZFREE(z,p); - p = q; - } - return Z_OK; -} -/* --- inftrees.c */ - -/* +++ infcodes.c */ -/* infcodes.c -- process literals and length/distance pairs - * Copyright (C) 1995-1996 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* #include "zutil.h" */ -/* #include "inftrees.h" */ -/* #include "infblock.h" */ -/* #include "infcodes.h" */ -/* #include "infutil.h" */ - -/* +++ inffast.h */ -/* inffast.h -- header to use inffast.c - * Copyright (C) 1995-1996 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -extern int inflate_fast OF(( - uInt, - uInt, - inflate_huft *, - inflate_huft *, - inflate_blocks_statef *, - z_streamp )); -/* --- inffast.h */ - -/* simplify the use of the inflate_huft type with some defines */ -#define base more.Base -#define next more.Next -#define exop word.what.Exop -#define bits word.what.Bits - -/* inflate codes private state */ -struct inflate_codes_state { - - /* mode */ - enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ - START, /* x: set up for LEN */ - LEN, /* i: get length/literal/eob next */ - LENEXT, /* i: getting length extra (have base) */ - DIST, /* i: get distance next */ - DISTEXT, /* i: getting distance extra */ - COPY, /* o: copying bytes in window, waiting for space */ - LIT, /* o: got literal, waiting for output space */ - WASH, /* o: got eob, possibly still output waiting */ - END, /* x: got eob and all data flushed */ - BADCODE} /* x: got error */ - mode; /* current inflate_codes mode */ - - /* mode dependent information */ - uInt len; - union { - struct { - inflate_huft *tree; /* pointer into tree */ - uInt need; /* bits needed */ - } code; /* if LEN or DIST, where in tree */ - uInt lit; /* if LIT, literal */ - struct { - uInt get; /* bits to get for extra */ - uInt dist; /* distance back to copy from */ - } copy; /* if EXT or COPY, where and how much */ - } sub; /* submode */ - - /* mode independent information */ - Byte lbits; /* ltree bits decoded per branch */ - Byte dbits; /* dtree bits decoder per branch */ - inflate_huft *ltree; /* literal/length/eob tree */ - inflate_huft *dtree; /* distance tree */ - -}; - - -inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z) -uInt bl, bd; -inflate_huft *tl; -inflate_huft *td; /* need separate declaration for Borland C++ */ -z_streamp z; -{ - inflate_codes_statef *c; - - if ((c = (inflate_codes_statef *) - ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL) - { - c->mode = START; - c->lbits = (Byte)bl; - c->dbits = (Byte)bd; - c->ltree = tl; - c->dtree = td; - Tracev((stderr, "inflate: codes new\n")); - } - return c; -} - - -int inflate_codes(s, z, r) -inflate_blocks_statef *s; -z_streamp z; -int r; -{ - uInt j; /* temporary storage */ - inflate_huft *t; /* temporary pointer */ - uInt e; /* extra bits or operation */ - uLong b; /* bit buffer */ - uInt k; /* bits in bit buffer */ - Bytef *p; /* input data pointer */ - uInt n; /* bytes available there */ - Bytef *q; /* output window write pointer */ - uInt m; /* bytes to end of window or read pointer */ - Bytef *f; /* pointer to copy strings from */ - inflate_codes_statef *c = s->sub.decode.codes; /* codes state */ - - /* copy input/output information to locals (UPDATE macro restores) */ - LOAD - - /* process input and output based on current state */ - while (1) switch (c->mode) - { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ - case START: /* x: set up for LEN */ -#ifndef SLOW - if (m >= 258 && n >= 10) - { - UPDATE - r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z); - LOAD - if (r != Z_OK) - { - c->mode = r == Z_STREAM_END ? WASH : BADCODE; - break; - } - } -#endif /* !SLOW */ - c->sub.code.need = c->lbits; - c->sub.code.tree = c->ltree; - c->mode = LEN; - case LEN: /* i: get length/literal/eob next */ - j = c->sub.code.need; - NEEDBITS(j) - t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); - DUMPBITS(t->bits) - e = (uInt)(t->exop); - if (e == 0) /* literal */ - { - c->sub.lit = t->base; - Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", t->base)); - c->mode = LIT; - break; - } - if (e & 16) /* length */ - { - c->sub.copy.get = e & 15; - c->len = t->base; - c->mode = LENEXT; - break; - } - if ((e & 64) == 0) /* next table */ - { - c->sub.code.need = e; - c->sub.code.tree = t->next; - break; - } - if (e & 32) /* end of block */ - { - Tracevv((stderr, "inflate: end of block\n")); - c->mode = WASH; - break; - } - c->mode = BADCODE; /* invalid code */ - z->msg = (char*)"invalid literal/length code"; - r = Z_DATA_ERROR; - LEAVE - case LENEXT: /* i: getting length extra (have base) */ - j = c->sub.copy.get; - NEEDBITS(j) - c->len += (uInt)b & inflate_mask[j]; - DUMPBITS(j) - c->sub.code.need = c->dbits; - c->sub.code.tree = c->dtree; - Tracevv((stderr, "inflate: length %u\n", c->len)); - c->mode = DIST; - case DIST: /* i: get distance next */ - j = c->sub.code.need; - NEEDBITS(j) - t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); - DUMPBITS(t->bits) - e = (uInt)(t->exop); - if (e & 16) /* distance */ - { - c->sub.copy.get = e & 15; - c->sub.copy.dist = t->base; - c->mode = DISTEXT; - break; - } - if ((e & 64) == 0) /* next table */ - { - c->sub.code.need = e; - c->sub.code.tree = t->next; - break; - } - c->mode = BADCODE; /* invalid code */ - z->msg = (char*)"invalid distance code"; - r = Z_DATA_ERROR; - LEAVE - case DISTEXT: /* i: getting distance extra */ - j = c->sub.copy.get; - NEEDBITS(j) - c->sub.copy.dist += (uInt)b & inflate_mask[j]; - DUMPBITS(j) - Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist)); - c->mode = COPY; - case COPY: /* o: copying bytes in window, waiting for space */ -#ifndef __TURBOC__ /* Turbo C bug for following expression */ - f = (uInt)(q - s->window) < c->sub.copy.dist ? - s->end - (c->sub.copy.dist - (q - s->window)) : - q - c->sub.copy.dist; -#else - f = q - c->sub.copy.dist; - if ((uInt)(q - s->window) < c->sub.copy.dist) - f = s->end - (c->sub.copy.dist - (uInt)(q - s->window)); -#endif - while (c->len) - { - NEEDOUT - OUTBYTE(*f++) - if (f == s->end) - f = s->window; - c->len--; - } - c->mode = START; - break; - case LIT: /* o: got literal, waiting for output space */ - NEEDOUT - OUTBYTE(c->sub.lit) - c->mode = START; - break; - case WASH: /* o: got eob, possibly more output */ - FLUSH - if (s->read != s->write) - LEAVE - c->mode = END; - case END: - r = Z_STREAM_END; - LEAVE - case BADCODE: /* x: got error */ - r = Z_DATA_ERROR; - LEAVE - default: - r = Z_STREAM_ERROR; - LEAVE - } -} - - -void inflate_codes_free(c, z) -inflate_codes_statef *c; -z_streamp z; -{ - ZFREE(z, c); - Tracev((stderr, "inflate: codes free\n")); -} -/* --- infcodes.c */ - -/* +++ infutil.c */ -/* inflate_util.c -- data and routines common to blocks and codes - * Copyright (C) 1995-1996 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* #include "zutil.h" */ -/* #include "infblock.h" */ -/* #include "inftrees.h" */ -/* #include "infcodes.h" */ -/* #include "infutil.h" */ - -#ifndef NO_DUMMY_DECL -struct inflate_codes_state {int dummy;}; /* for buggy compilers */ -#endif - -/* And'ing with mask[n] masks the lower n bits */ -uInt inflate_mask[17] = { - 0x0000, - 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, - 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff -}; - - -/* copy as much as possible from the sliding window to the output area */ -int inflate_flush(s, z, r) -inflate_blocks_statef *s; -z_streamp z; -int r; -{ - uInt n; - Bytef *p; - Bytef *q; - - /* local copies of source and destination pointers */ - p = z->next_out; - q = s->read; - - /* compute number of bytes to copy as far as end of window */ - n = (uInt)((q <= s->write ? s->write : s->end) - q); - if (n > z->avail_out) n = z->avail_out; - if (n && r == Z_BUF_ERROR) r = Z_OK; - - /* update counters */ - z->avail_out -= n; - z->total_out += n; - - /* update check information */ - if (s->checkfn != Z_NULL) - z->adler = s->check = (*s->checkfn)(s->check, q, n); - - /* copy as far as end of window */ - if (p != Z_NULL) { - zmemcpy(p, q, n); - p += n; - } - q += n; - - /* see if more to copy at beginning of window */ - if (q == s->end) - { - /* wrap pointers */ - q = s->window; - if (s->write == s->end) - s->write = s->window; - - /* compute bytes to copy */ - n = (uInt)(s->write - q); - if (n > z->avail_out) n = z->avail_out; - if (n && r == Z_BUF_ERROR) r = Z_OK; - - /* update counters */ - z->avail_out -= n; - z->total_out += n; - - /* update check information */ - if (s->checkfn != Z_NULL) - z->adler = s->check = (*s->checkfn)(s->check, q, n); - - /* copy */ - if (p != Z_NULL) { - zmemcpy(p, q, n); - p += n; - } - q += n; - } - - /* update pointers */ - z->next_out = p; - s->read = q; - - /* done */ - return r; -} -/* --- infutil.c */ - -/* +++ inffast.c */ -/* inffast.c -- process literals and length/distance pairs fast - * Copyright (C) 1995-1996 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* #include "zutil.h" */ -/* #include "inftrees.h" */ -/* #include "infblock.h" */ -/* #include "infcodes.h" */ -/* #include "infutil.h" */ -/* #include "inffast.h" */ - -#ifndef NO_DUMMY_DECL -struct inflate_codes_state {int dummy;}; /* for buggy compilers */ -#endif - -/* simplify the use of the inflate_huft type with some defines */ -#define base more.Base -#define next more.Next -#define exop word.what.Exop -#define bits word.what.Bits - -/* macros for bit input with no checking and for returning unused bytes */ -#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<>3);p-=c;k&=7;} - -/* Called with number of bytes left to write in window at least 258 - (the maximum string length) and number of input bytes available - at least ten. The ten bytes are six bytes for the longest length/ - distance pair plus four bytes for overloading the bit buffer. */ - -int inflate_fast(bl, bd, tl, td, s, z) -uInt bl, bd; -inflate_huft *tl; -inflate_huft *td; /* need separate declaration for Borland C++ */ -inflate_blocks_statef *s; -z_streamp z; -{ - inflate_huft *t; /* temporary pointer */ - uInt e; /* extra bits or operation */ - uLong b; /* bit buffer */ - uInt k; /* bits in bit buffer */ - Bytef *p; /* input data pointer */ - uInt n; /* bytes available there */ - Bytef *q; /* output window write pointer */ - uInt m; /* bytes to end of window or read pointer */ - uInt ml; /* mask for literal/length tree */ - uInt md; /* mask for distance tree */ - uInt c; /* bytes to copy */ - uInt d; /* distance back to copy from */ - Bytef *r; /* copy source pointer */ - - /* load input, output, bit values */ - LOAD - - /* initialize masks */ - ml = inflate_mask[bl]; - md = inflate_mask[bd]; - - /* do until not enough input or output space for fast loop */ - do { /* assume called with m >= 258 && n >= 10 */ - /* get literal/length code */ - GRABBITS(20) /* max bits for literal/length code */ - if ((e = (t = tl + ((uInt)b & ml))->exop) == 0) - { - DUMPBITS(t->bits) - Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? - "inflate: * literal '%c'\n" : - "inflate: * literal 0x%02x\n", t->base)); - *q++ = (Byte)t->base; - m--; - continue; - } - do { - DUMPBITS(t->bits) - if (e & 16) - { - /* get extra bits for length */ - e &= 15; - c = t->base + ((uInt)b & inflate_mask[e]); - DUMPBITS(e) - Tracevv((stderr, "inflate: * length %u\n", c)); - - /* decode distance base of block to copy */ - GRABBITS(15); /* max bits for distance code */ - e = (t = td + ((uInt)b & md))->exop; - do { - DUMPBITS(t->bits) - if (e & 16) - { - /* get extra bits to add to distance base */ - e &= 15; - GRABBITS(e) /* get extra bits (up to 13) */ - d = t->base + ((uInt)b & inflate_mask[e]); - DUMPBITS(e) - Tracevv((stderr, "inflate: * distance %u\n", d)); - - /* do the copy */ - m -= c; - if ((uInt)(q - s->window) >= d) /* offset before dest */ - { /* just copy */ - r = q - d; - *q++ = *r++; c--; /* minimum count is three, */ - *q++ = *r++; c--; /* so unroll loop a little */ - } - else /* else offset after destination */ - { - e = d - (uInt)(q - s->window); /* bytes from offset to end */ - r = s->end - e; /* pointer to offset */ - if (c > e) /* if source crosses, */ - { - c -= e; /* copy to end of window */ - do { - *q++ = *r++; - } while (--e); - r = s->window; /* copy rest from start of window */ - } - } - do { /* copy all or what's left */ - *q++ = *r++; - } while (--c); - break; - } - else if ((e & 64) == 0) - e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop; - else - { - z->msg = (char*)"invalid distance code"; - UNGRAB - UPDATE - return Z_DATA_ERROR; - } - } while (1); - break; - } - if ((e & 64) == 0) - { - if ((e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop) == 0) - { - DUMPBITS(t->bits) - Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? - "inflate: * literal '%c'\n" : - "inflate: * literal 0x%02x\n", t->base)); - *q++ = (Byte)t->base; - m--; - break; - } - } - else if (e & 32) - { - Tracevv((stderr, "inflate: * end of block\n")); - UNGRAB - UPDATE - return Z_STREAM_END; - } - else - { - z->msg = (char*)"invalid literal/length code"; - UNGRAB - UPDATE - return Z_DATA_ERROR; - } - } while (1); - } while (m >= 258 && n >= 10); - - /* not enough input or output--restore pointers and return */ - UNGRAB - UPDATE - return Z_OK; -} -/* --- inffast.c */ - -/* +++ zutil.c */ -/* zutil.c -- target dependent utility functions for the compression library - * Copyright (C) 1995-1996 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* From: zutil.c,v 1.17 1996/07/24 13:41:12 me Exp $ */ - -/* #include "zutil.h" */ - -#ifndef NO_DUMMY_DECL -struct internal_state {int dummy;}; /* for buggy compilers */ -#endif - -#ifndef STDC -extern void exit OF((int)); -#endif - -const char *z_errmsg[10] = { -"need dictionary", /* Z_NEED_DICT 2 */ -"stream end", /* Z_STREAM_END 1 */ -"", /* Z_OK 0 */ -"file error", /* Z_ERRNO (-1) */ -"stream error", /* Z_STREAM_ERROR (-2) */ -"data error", /* Z_DATA_ERROR (-3) */ -"insufficient memory", /* Z_MEM_ERROR (-4) */ -"buffer error", /* Z_BUF_ERROR (-5) */ -"incompatible version",/* Z_VERSION_ERROR (-6) */ -""}; - - -const char *zlibVersion() -{ - return ZLIB_VERSION; -} - -#ifdef DEBUG_ZLIB -void z_error (m) - char *m; -{ - fprintf(stderr, "%s\n", m); - exit(1); -} -#endif - -#ifndef HAVE_MEMCPY - -void zmemcpy(dest, source, len) - Bytef* dest; - Bytef* source; - uInt len; -{ - if (len == 0) return; - do { - *dest++ = *source++; /* ??? to be unrolled */ - } while (--len != 0); -} - -int zmemcmp(s1, s2, len) - Bytef* s1; - Bytef* s2; - uInt len; -{ - uInt j; - - for (j = 0; j < len; j++) { - if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; - } - return 0; -} - -void zmemzero(dest, len) - Bytef* dest; - uInt len; -{ - if (len == 0) return; - do { - *dest++ = 0; /* ??? to be unrolled */ - } while (--len != 0); -} -#endif - -#ifdef __TURBOC__ -#if (defined( __BORLANDC__) || !defined(SMALL_MEDIUM)) && !defined(__32BIT__) -/* Small and medium model in Turbo C are for now limited to near allocation - * with reduced MAX_WBITS and MAX_MEM_LEVEL - */ -# define MY_ZCALLOC - -/* Turbo C malloc() does not allow dynamic allocation of 64K bytes - * and farmalloc(64K) returns a pointer with an offset of 8, so we - * must fix the pointer. Warning: the pointer must be put back to its - * original form in order to free it, use zcfree(). - */ - -#define MAX_PTR 10 -/* 10*64K = 640K */ - -local int next_ptr = 0; - -typedef struct ptr_table_s { - voidpf org_ptr; - voidpf new_ptr; -} ptr_table; - -local ptr_table table[MAX_PTR]; -/* This table is used to remember the original form of pointers - * to large buffers (64K). Such pointers are normalized with a zero offset. - * Since MSDOS is not a preemptive multitasking OS, this table is not - * protected from concurrent access. This hack doesn't work anyway on - * a protected system like OS/2. Use Microsoft C instead. - */ - -voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) -{ - voidpf buf = opaque; /* just to make some compilers happy */ - ulg bsize = (ulg)items*size; - - /* If we allocate less than 65520 bytes, we assume that farmalloc - * will return a usable pointer which doesn't have to be normalized. - */ - if (bsize < 65520L) { - buf = farmalloc(bsize); - if (*(ush*)&buf != 0) return buf; - } else { - buf = farmalloc(bsize + 16L); - } - if (buf == NULL || next_ptr >= MAX_PTR) return NULL; - table[next_ptr].org_ptr = buf; - - /* Normalize the pointer to seg:0 */ - *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; - *(ush*)&buf = 0; - table[next_ptr++].new_ptr = buf; - return buf; -} - -void zcfree (voidpf opaque, voidpf ptr) -{ - int n; - if (*(ush*)&ptr != 0) { /* object < 64K */ - farfree(ptr); - return; - } - /* Find the original pointer */ - for (n = 0; n < next_ptr; n++) { - if (ptr != table[n].new_ptr) continue; - - farfree(table[n].org_ptr); - while (++n < next_ptr) { - table[n-1] = table[n]; - } - next_ptr--; - return; - } - ptr = opaque; /* just to make some compilers happy */ - Assert(0, "zcfree: ptr not found"); -} -#endif -#endif /* __TURBOC__ */ - - -#if defined(M_I86) && !defined(__32BIT__) -/* Microsoft C in 16-bit mode */ - -# define MY_ZCALLOC - -#if (!defined(_MSC_VER) || (_MSC_VER < 600)) -# define _halloc halloc -# define _hfree hfree -#endif - -voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) -{ - if (opaque) opaque = 0; /* to make compiler happy */ - return _halloc((long)items, size); -} - -void zcfree (voidpf opaque, voidpf ptr) -{ - if (opaque) opaque = 0; /* to make compiler happy */ - _hfree(ptr); -} - -#endif /* MSC */ - - -#ifndef MY_ZCALLOC /* Any system without a special alloc function */ - -#ifndef STDC -extern voidp calloc OF((uInt items, uInt size)); -extern void free OF((voidpf ptr)); -#endif - -voidpf zcalloc (opaque, items, size) - voidpf opaque; - unsigned items; - unsigned size; -{ - if (opaque) items += size - size; /* make compiler happy */ - return (voidpf)calloc(items, size); -} - -void zcfree (opaque, ptr) - voidpf opaque; - voidpf ptr; -{ - free(ptr); - if (opaque) return; /* make compiler happy */ -} - -#endif /* MY_ZCALLOC */ -/* --- zutil.c */ - -/* +++ adler32.c */ -/* adler32.c -- compute the Adler-32 checksum of a data stream - * Copyright (C) 1995-1996 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* From: adler32.c,v 1.10 1996/05/22 11:52:18 me Exp $ */ - -/* #include "zlib.h" */ - -#define BASE 65521L /* largest prime smaller than 65536 */ -#define NMAX 5552 -/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ - -#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} -#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); -#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); -#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); -#define DO16(buf) DO8(buf,0); DO8(buf,8); - -/* ========================================================================= */ -uLong adler32(adler, buf, len) - uLong adler; - const Bytef *buf; - uInt len; -{ - unsigned long s1 = adler & 0xffff; - unsigned long s2 = (adler >> 16) & 0xffff; - int k; - - if (buf == Z_NULL) return 1L; - - while (len > 0) { - k = len < NMAX ? len : NMAX; - len -= k; - while (k >= 16) { - DO16(buf); - buf += 16; - k -= 16; - } - if (k != 0) do { - s1 += *buf++; - s2 += s1; - } while (--k); - s1 %= BASE; - s2 %= BASE; - } - return (s2 << 16) | s1; -} -/* --- adler32.c */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/net/zlib.h linux.19rc3-ac4/drivers/net/zlib.h --- linux.19rc3/drivers/net/zlib.h 2002-07-29 12:49:56.000000000 +0100 +++ linux.19rc3-ac4/drivers/net/zlib.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,1010 +0,0 @@ -/* $Id: zlib.h,v 1.2 1997/12/23 10:47:44 paulus Exp $ */ - -/* - * This file is derived from zlib.h and zconf.h from the zlib-1.0.4 - * distribution by Jean-loup Gailly and Mark Adler, with some additions - * by Paul Mackerras to aid in implementing Deflate compression and - * decompression for PPP packets. - */ - -/* - * ==FILEVERSION 971127== - * - * This marker is used by the Linux installation script to determine - * whether an up-to-date version of this file is already installed. - */ - - -/* +++ zlib.h */ -/* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.0.4, Jul 24th, 1996. - - Copyright (C) 1995-1996 Jean-loup Gailly and Mark Adler - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jean-loup Gailly Mark Adler - gzip@prep.ai.mit.edu madler@alumni.caltech.edu - - - The data format used by the zlib library is described by RFCs (Request for - Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt - (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). -*/ - -#ifndef _ZLIB_H -#define _ZLIB_H - -#ifdef __cplusplus -extern "C" { -#endif - - -/* +++ zconf.h */ -/* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-1996 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* From: zconf.h,v 1.20 1996/07/02 15:09:28 me Exp $ */ - -#ifndef _ZCONF_H -#define _ZCONF_H - -/* - * If you *really* need a unique prefix for all types and library functions, - * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. - */ -#ifdef Z_PREFIX -# define deflateInit_ z_deflateInit_ -# define deflate z_deflate -# define deflateEnd z_deflateEnd -# define inflateInit_ z_inflateInit_ -# define inflate z_inflate -# define inflateEnd z_inflateEnd -# define deflateInit2_ z_deflateInit2_ -# define deflateSetDictionary z_deflateSetDictionary -# define deflateCopy z_deflateCopy -# define deflateReset z_deflateReset -# define deflateParams z_deflateParams -# define inflateInit2_ z_inflateInit2_ -# define inflateSetDictionary z_inflateSetDictionary -# define inflateSync z_inflateSync -# define inflateReset z_inflateReset -# define compress z_compress -# define uncompress z_uncompress -# define adler32 z_adler32 -# define crc32 z_crc32 -# define get_crc_table z_get_crc_table - -# define Byte z_Byte -# define uInt z_uInt -# define uLong z_uLong -# define Bytef z_Bytef -# define charf z_charf -# define intf z_intf -# define uIntf z_uIntf -# define uLongf z_uLongf -# define voidpf z_voidpf -# define voidp z_voidp -#endif - -#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) -# define WIN32 -#endif -#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386) -# ifndef __32BIT__ -# define __32BIT__ -# endif -#endif -#if defined(__MSDOS__) && !defined(MSDOS) -# define MSDOS -#endif - -/* - * Compile with -DMAXSEG_64K if the alloc function cannot allocate more - * than 64k bytes at a time (needed on systems with 16-bit int). - */ -#if defined(MSDOS) && !defined(__32BIT__) -# define MAXSEG_64K -#endif -#ifdef MSDOS -# define UNALIGNED_OK -#endif - -#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC) -# define STDC -#endif -#if (defined(__STDC__) || defined(__cplusplus)) && !defined(STDC) -# define STDC -#endif - -#ifndef STDC -# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ -# define const -# endif -#endif - -/* Some Mac compilers merge all .h files incorrectly: */ -#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__) -# define NO_DUMMY_DECL -#endif - -/* Maximum value for memLevel in deflateInit2 */ -#ifndef MAX_MEM_LEVEL -# ifdef MAXSEG_64K -# define MAX_MEM_LEVEL 8 -# else -# define MAX_MEM_LEVEL 9 -# endif -#endif - -/* Maximum value for windowBits in deflateInit2 and inflateInit2 */ -#ifndef MAX_WBITS -# define MAX_WBITS 15 /* 32K LZ77 window */ -#endif - -/* The memory requirements for deflate are (in bytes): - 1 << (windowBits+2) + 1 << (memLevel+9) - that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) - plus a few kilobytes for small objects. For example, if you want to reduce - the default memory requirements from 256K to 128K, compile with - make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" - Of course this will generally degrade compression (there's no free lunch). - - The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus a few kilobytes - for small objects. -*/ - - /* Type declarations */ - -#ifndef OF /* function prototypes */ -# ifdef STDC -# define OF(args) args -# else -# define OF(args) () -# endif -#endif - -/* The following definitions for FAR are needed only for MSDOS mixed - * model programming (small or medium model with some far allocations). - * This was tested only with MSC; for other MSDOS compilers you may have - * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, - * just define FAR to be empty. - */ -#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__) - /* MSC small or medium model */ -# define SMALL_MEDIUM -# ifdef _MSC_VER -# define FAR __far -# else -# define FAR far -# endif -#endif -#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__)) -# ifndef __32BIT__ -# define SMALL_MEDIUM -# define FAR __far -# endif -#endif -#ifndef FAR -# define FAR -#endif - -typedef unsigned char Byte; /* 8 bits */ -typedef unsigned int uInt; /* 16 bits or more */ -typedef unsigned long uLong; /* 32 bits or more */ - -#if defined(__BORLANDC__) && defined(SMALL_MEDIUM) - /* Borland C/C++ ignores FAR inside typedef */ -# define Bytef Byte FAR -#else - typedef Byte FAR Bytef; -#endif -typedef char FAR charf; -typedef int FAR intf; -typedef uInt FAR uIntf; -typedef uLong FAR uLongf; - -#ifdef STDC - typedef void FAR *voidpf; - typedef void *voidp; -#else - typedef Byte FAR *voidpf; - typedef Byte *voidp; -#endif - - -/* Compile with -DZLIB_DLL for Windows DLL support */ -#if (defined(_WINDOWS) || defined(WINDOWS)) && defined(ZLIB_DLL) -# include -# define EXPORT WINAPI -#else -# define EXPORT -#endif - -#endif /* _ZCONF_H */ -/* --- zconf.h */ - -#define ZLIB_VERSION "1.0.4P" - -/* - The 'zlib' compression library provides in-memory compression and - decompression functions, including integrity checks of the uncompressed - data. This version of the library supports only one compression method - (deflation) but other algorithms may be added later and will have the same - stream interface. - - For compression the application must provide the output buffer and - may optionally provide the input buffer for optimization. For decompression, - the application must provide the input buffer and may optionally provide - the output buffer for optimization. - - Compression can be done in a single step if the buffers are large - enough (for example if an input file is mmap'ed), or can be done by - repeated calls of the compression function. In the latter case, the - application must provide more input and/or consume the output - (providing more output space) before each call. - - The library does not install any signal handler. It is recommended to - add at least a handler for SIGSEGV when decompressing; the library checks - the consistency of the input data whenever possible but may go nuts - for some forms of corrupted input. -*/ - -typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); -typedef void (*free_func) OF((voidpf opaque, voidpf address)); - -struct internal_state; - -typedef struct z_stream_s { - Bytef *next_in; /* next input byte */ - uInt avail_in; /* number of bytes available at next_in */ - uLong total_in; /* total nb of input bytes read so far */ - - Bytef *next_out; /* next output byte should be put there */ - uInt avail_out; /* remaining free space at next_out */ - uLong total_out; /* total nb of bytes output so far */ - - char *msg; /* last error message, NULL if no error */ - struct internal_state FAR *state; /* not visible by applications */ - - alloc_func zalloc; /* used to allocate the internal state */ - free_func zfree; /* used to free the internal state */ - voidpf opaque; /* private data object passed to zalloc and zfree */ - - int data_type; /* best guess about the data type: ascii or binary */ - uLong adler; /* adler32 value of the uncompressed data */ - uLong reserved; /* reserved for future use */ -} z_stream; - -typedef z_stream FAR *z_streamp; - -/* - The application must update next_in and avail_in when avail_in has - dropped to zero. It must update next_out and avail_out when avail_out - has dropped to zero. The application must initialize zalloc, zfree and - opaque before calling the init function. All other fields are set by the - compression library and must not be updated by the application. - - The opaque value provided by the application will be passed as the first - parameter for calls of zalloc and zfree. This can be useful for custom - memory management. The compression library attaches no meaning to the - opaque value. - - zalloc must return Z_NULL if there is not enough memory for the object. - On 16-bit systems, the functions zalloc and zfree must be able to allocate - exactly 65536 bytes, but will not be required to allocate more than this - if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, - pointers returned by zalloc for objects of exactly 65536 bytes *must* - have their offset normalized to zero. The default allocation function - provided by this library ensures this (see zutil.c). To reduce memory - requirements and avoid any allocation of 64K objects, at the expense of - compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). - - The fields total_in and total_out can be used for statistics or - progress reports. After compression, total_in holds the total size of - the uncompressed data and may be saved for use in the decompressor - (particularly if the decompressor wants to decompress everything in - a single step). -*/ - - /* constants */ - -#define Z_NO_FLUSH 0 -#define Z_PARTIAL_FLUSH 1 -#define Z_PACKET_FLUSH 2 -#define Z_SYNC_FLUSH 3 -#define Z_FULL_FLUSH 4 -#define Z_FINISH 5 -/* Allowed flush values; see deflate() below for details */ - -#define Z_OK 0 -#define Z_STREAM_END 1 -#define Z_NEED_DICT 2 -#define Z_ERRNO (-1) -#define Z_STREAM_ERROR (-2) -#define Z_DATA_ERROR (-3) -#define Z_MEM_ERROR (-4) -#define Z_BUF_ERROR (-5) -#define Z_VERSION_ERROR (-6) -/* Return codes for the compression/decompression functions. Negative - * values are errors, positive values are used for special but normal events. - */ - -#define Z_NO_COMPRESSION 0 -#define Z_BEST_SPEED 1 -#define Z_BEST_COMPRESSION 9 -#define Z_DEFAULT_COMPRESSION (-1) -/* compression levels */ - -#define Z_FILTERED 1 -#define Z_HUFFMAN_ONLY 2 -#define Z_DEFAULT_STRATEGY 0 -/* compression strategy; see deflateInit2() below for details */ - -#define Z_BINARY 0 -#define Z_ASCII 1 -#define Z_UNKNOWN 2 -/* Possible values of the data_type field */ - -#define Z_DEFLATED 8 -/* The deflate compression method (the only one supported in this version) */ - -#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ - -#define zlib_version zlibVersion() -/* for compatibility with versions < 1.0.2 */ - - /* basic functions */ - -extern const char * EXPORT zlibVersion OF((void)); -/* The application can compare zlibVersion and ZLIB_VERSION for consistency. - If the first character differs, the library code actually used is - not compatible with the zlib.h header file used by the application. - This check is automatically made by deflateInit and inflateInit. - */ - -/* -extern int EXPORT deflateInit OF((z_streamp strm, int level)); - - Initializes the internal stream state for compression. The fields - zalloc, zfree and opaque must be initialized before by the caller. - If zalloc and zfree are set to Z_NULL, deflateInit updates them to - use default allocation functions. - - The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: - 1 gives best speed, 9 gives best compression, 0 gives no compression at - all (the input data is simply copied a block at a time). - Z_DEFAULT_COMPRESSION requests a default compromise between speed and - compression (currently equivalent to level 6). - - deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if level is not a valid compression level, - Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible - with the version assumed by the caller (ZLIB_VERSION). - msg is set to null if there is no error message. deflateInit does not - perform any compression: this will be done by deflate(). -*/ - - -extern int EXPORT deflate OF((z_streamp strm, int flush)); -/* - Performs one or both of the following actions: - - - Compress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in and avail_in are updated and - processing will resume at this point for the next call of deflate(). - - - Provide more output starting at next_out and update next_out and avail_out - accordingly. This action is forced if the parameter flush is non zero. - Forcing flush frequently degrades the compression ratio, so this parameter - should be set only when necessary (in interactive applications). - Some output may be provided even if flush is not set. - - Before the call of deflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming - more output, and updating avail_in or avail_out accordingly; avail_out - should never be zero before the call. The application can consume the - compressed output when it wants, for example when the output buffer is full - (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK - and with zero avail_out, it must be called again after making room in the - output buffer because there might be more output pending. - - If the parameter flush is set to Z_PARTIAL_FLUSH, the current compression - block is terminated and flushed to the output buffer so that the - decompressor can get all input data available so far. For method 9, a future - variant on method 8, the current block will be flushed but not terminated. - Z_SYNC_FLUSH has the same effect as partial flush except that the compressed - output is byte aligned (the compressor can clear its internal bit buffer) - and the current block is always terminated; this can be useful if the - compressor has to be restarted from scratch after an interruption (in which - case the internal state of the compressor may be lost). - If flush is set to Z_FULL_FLUSH, the compression block is terminated, a - special marker is output and the compression dictionary is discarded; this - is useful to allow the decompressor to synchronize if one compressed block - has been damaged (see inflateSync below). Flushing degrades compression and - so should be used only when necessary. Using Z_FULL_FLUSH too often can - seriously degrade the compression. If deflate returns with avail_out == 0, - this function must be called again with the same value of the flush - parameter and more output space (updated avail_out), until the flush is - complete (deflate returns with non-zero avail_out). - - If the parameter flush is set to Z_PACKET_FLUSH, the compression - block is terminated, and a zero-length stored block is output, - omitting the length bytes (the effect of this is that the 3-bit type - code 000 for a stored block is output, and the output is then - byte-aligned). This is designed for use at the end of a PPP packet. - - If the parameter flush is set to Z_FINISH, pending input is processed, - pending output is flushed and deflate returns with Z_STREAM_END if there - was enough output space; if deflate returns with Z_OK, this function must be - called again with Z_FINISH and more output space (updated avail_out) but no - more input data, until it returns with Z_STREAM_END or an error. After - deflate has returned Z_STREAM_END, the only possible operations on the - stream are deflateReset or deflateEnd. - - Z_FINISH can be used immediately after deflateInit if all the compression - is to be done in a single step. In this case, avail_out must be at least - 0.1% larger than avail_in plus 12 bytes. If deflate does not return - Z_STREAM_END, then it must be called again as described above. - - deflate() may update data_type if it can make a good guess about - the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered - binary. This field is only for information purposes and does not affect - the compression algorithm in any manner. - - deflate() returns Z_OK if some progress has been made (more input - processed or more output produced), Z_STREAM_END if all input has been - consumed and all output has been produced (only when flush is set to - Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example - if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible. -*/ - - -extern int EXPORT deflateEnd OF((z_streamp strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any - pending output. - - deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the - stream state was inconsistent, Z_DATA_ERROR if the stream was freed - prematurely (some input or output was discarded). In the error case, - msg may be set but then points to a static string (which must not be - deallocated). -*/ - - -/* -extern int EXPORT inflateInit OF((z_streamp strm)); - - Initializes the internal stream state for decompression. The fields - zalloc, zfree and opaque must be initialized before by the caller. If - zalloc and zfree are set to Z_NULL, inflateInit updates them to use default - allocation functions. - - inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_VERSION_ERROR if the zlib library version is incompatible - with the version assumed by the caller. msg is set to null if there is no - error message. inflateInit does not perform any decompression: this will be - done by inflate(). -*/ - - -extern int EXPORT inflate OF((z_streamp strm, int flush)); -/* - Performs one or both of the following actions: - - - Decompress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in is updated and processing - will resume at this point for the next call of inflate(). - - - Provide more output starting at next_out and update next_out and avail_out - accordingly. inflate() provides as much output as possible, until there - is no more input data or no more space in the output buffer (see below - about the flush parameter). - - Before the call of inflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming - more output, and updating the next_* and avail_* values accordingly. - The application can consume the uncompressed output when it wants, for - example when the output buffer is full (avail_out == 0), or after each - call of inflate(). If inflate returns Z_OK and with zero avail_out, it - must be called again after making room in the output buffer because there - might be more output pending. - - If the parameter flush is set to Z_PARTIAL_FLUSH or Z_PACKET_FLUSH, - inflate flushes as much output as possible to the output buffer. The - flushing behavior of inflate is not specified for values of the flush - parameter other than Z_PARTIAL_FLUSH, Z_PACKET_FLUSH or Z_FINISH, but the - current implementation actually flushes as much output as possible - anyway. For Z_PACKET_FLUSH, inflate checks that once all the input data - has been consumed, it is expecting to see the length field of a stored - block; if not, it returns Z_DATA_ERROR. - - inflate() should normally be called until it returns Z_STREAM_END or an - error. However if all decompression is to be performed in a single step - (a single call of inflate), the parameter flush should be set to - Z_FINISH. In this case all pending input is processed and all pending - output is flushed; avail_out must be large enough to hold all the - uncompressed data. (The size of the uncompressed data may have been saved - by the compressor for this purpose.) The next operation on this stream must - be inflateEnd to deallocate the decompression state. The use of Z_FINISH - is never required, but can be used to inform inflate that a faster routine - may be used for the single inflate() call. - - inflate() returns Z_OK if some progress has been made (more input - processed or more output produced), Z_STREAM_END if the end of the - compressed data has been reached and all uncompressed output has been - produced, Z_NEED_DICT if a preset dictionary is needed at this point (see - inflateSetDictionary below), Z_DATA_ERROR if the input data was corrupted, - Z_STREAM_ERROR if the stream structure was inconsistent (for example if - next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, - Z_BUF_ERROR if no progress is possible or if there was not enough room in - the output buffer when Z_FINISH is used. In the Z_DATA_ERROR case, the - application may then call inflateSync to look for a good compression block. - In the Z_NEED_DICT case, strm->adler is set to the Adler32 value of the - dictionary chosen by the compressor. -*/ - - -extern int EXPORT inflateEnd OF((z_streamp strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any - pending output. - - inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state - was inconsistent. In the error case, msg may be set but then points to a - static string (which must not be deallocated). -*/ - - /* Advanced functions */ - -/* - The following functions are needed only in some special applications. -*/ - -/* -extern int EXPORT deflateInit2 OF((z_streamp strm, - int level, - int method, - int windowBits, - int memLevel, - int strategy)); - - This is another version of deflateInit with more compression options. The - fields next_in, zalloc, zfree and opaque must be initialized before by - the caller. - - The method parameter is the compression method. It must be Z_DEFLATED in - this version of the library. (Method 9 will allow a 64K history buffer and - partial block flushes.) - - The windowBits parameter is the base two logarithm of the window size - (the size of the history buffer). It should be in the range 8..15 for this - version of the library (the value 16 will be allowed for method 9). Larger - values of this parameter result in better compression at the expense of - memory usage. The default value is 15 if deflateInit is used instead. - - The memLevel parameter specifies how much memory should be allocated - for the internal compression state. memLevel=1 uses minimum memory but - is slow and reduces compression ratio; memLevel=9 uses maximum memory - for optimal speed. The default value is 8. See zconf.h for total memory - usage as a function of windowBits and memLevel. - - The strategy parameter is used to tune the compression algorithm. Use the - value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a - filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no - string match). Filtered data consists mostly of small values with a - somewhat random distribution. In this case, the compression algorithm is - tuned to compress them better. The effect of Z_FILTERED is to force more - Huffman coding and less string matching; it is somewhat intermediate - between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects - the compression ratio but not the correctness of the compressed output even - if it is not set appropriately. - - If next_in is not null, the library will use this buffer to hold also - some history information; the buffer must either hold the entire input - data, or have at least 1<<(windowBits+1) bytes and be writable. If next_in - is null, the library will allocate its own history buffer (and leave next_in - null). next_out need not be provided here but must be provided by the - application for the next call of deflate(). - - If the history buffer is provided by the application, next_in must - must never be changed by the application since the compressor maintains - information inside this buffer from call to call; the application - must provide more input only by increasing avail_in. next_in is always - reset by the library in this case. - - deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was - not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as - an invalid method). msg is set to null if there is no error message. - deflateInit2 does not perform any compression: this will be done by - deflate(). -*/ - -extern int EXPORT deflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); -/* - Initializes the compression dictionary (history buffer) from the given - byte sequence without producing any compressed output. This function must - be called immediately after deflateInit or deflateInit2, before any call - of deflate. The compressor and decompressor must use exactly the same - dictionary (see inflateSetDictionary). - The dictionary should consist of strings (byte sequences) that are likely - to be encountered later in the data to be compressed, with the most commonly - used strings preferably put towards the end of the dictionary. Using a - dictionary is most useful when the data to be compressed is short and - can be predicted with good accuracy; the data can then be compressed better - than with the default empty dictionary. In this version of the library, - only the last 32K bytes of the dictionary are used. - Upon return of this function, strm->adler is set to the Adler32 value - of the dictionary; the decompressor may later use this value to determine - which dictionary has been used by the compressor. (The Adler32 value - applies to the whole dictionary even if only a subset of the dictionary is - actually used by the compressor.) - - deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a - parameter is invalid (such as NULL dictionary) or the stream state - is inconsistent (for example if deflate has already been called for this - stream). deflateSetDictionary does not perform any compression: this will - be done by deflate(). -*/ - -extern int EXPORT deflateCopy OF((z_streamp dest, - z_streamp source)); -/* - Sets the destination stream as a complete copy of the source stream. If - the source stream is using an application-supplied history buffer, a new - buffer is allocated for the destination stream. The compressed output - buffer is always application-supplied. It's the responsibility of the - application to provide the correct values of next_out and avail_out for the - next call of deflate. - - This function can be useful when several compression strategies will be - tried, for example when there are several ways of pre-processing the input - data with a filter. The streams that will be discarded should then be freed - by calling deflateEnd. Note that deflateCopy duplicates the internal - compression state which can be quite large, so this strategy is slow and - can consume lots of memory. - - deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being NULL). msg is left unchanged in both source and - destination. -*/ - -extern int EXPORT deflateReset OF((z_streamp strm)); -/* - This function is equivalent to deflateEnd followed by deflateInit, - but does not free and reallocate all the internal compression state. - The stream will keep the same compression level and any other attributes - that may have been set by deflateInit2. - - deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being NULL). -*/ - -extern int EXPORT deflateParams OF((z_streamp strm, int level, int strategy)); -/* - Dynamically update the compression level and compression strategy. - This can be used to switch between compression and straight copy of - the input data, or to switch to a different kind of input data requiring - a different strategy. If the compression level is changed, the input - available so far is compressed with the old level (and may be flushed); - the new level will take effect only at the next call of deflate(). - - Before the call of deflateParams, the stream state must be set as for - a call of deflate(), since the currently available input may have to - be compressed and flushed. In particular, strm->avail_out must be non-zero. - - deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source - stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR - if strm->avail_out was zero. -*/ - -extern int EXPORT deflateOutputPending OF((z_streamp strm)); -/* - Returns the number of bytes of output which are immediately - available from the compressor (i.e. without any further input - or flush). -*/ - -/* -extern int EXPORT inflateInit2 OF((z_streamp strm, - int windowBits)); - - This is another version of inflateInit with more compression options. The - fields next_out, zalloc, zfree and opaque must be initialized before by - the caller. - - The windowBits parameter is the base two logarithm of the maximum window - size (the size of the history buffer). It should be in the range 8..15 for - this version of the library (the value 16 will be allowed soon). The - default value is 15 if inflateInit is used instead. If a compressed stream - with a larger window size is given as input, inflate() will return with - the error code Z_DATA_ERROR instead of trying to allocate a larger window. - - If next_out is not null, the library will use this buffer for the history - buffer; the buffer must either be large enough to hold the entire output - data, or have at least 1< + * (C) 1999-2001 by Helge Deller * * * based on parport_pc.c by @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -47,6 +48,7 @@ MODULE_AUTHOR("Helge Deller "); MODULE_DESCRIPTION("HP-PARISC PC-style parallel port driver"); MODULE_SUPPORTED_DEVICE("integrated PC-style parallel port"); +MODULE_LICENSE("GPL"); /* @@ -347,13 +349,6 @@ struct parport tmp; struct parport *p = &tmp; -#if 1 -#warning Take this out when region handling works again, -#else - if (check_region(base, 3)) - return NULL; -#endif - priv = kmalloc (sizeof (struct parport_gsc_private), GFP_KERNEL); if (!priv) { printk (KERN_DEBUG "parport (0x%lx): no memory!\n", base); @@ -430,12 +425,6 @@ printk("]\n"); parport_proc_register(p); - request_region (p->base, 3, p->name); - if (p->size > 3) - request_region (p->base + 3, p->size - 3, p->name); - if (p->modes & PARPORT_MODE_ECP) - request_region (p->base_hi, 3, p->name); - if (p->irq != PARPORT_IRQ_NONE) { if (request_irq (p->irq, parport_gsc_interrupt, 0, p->name, p)) { @@ -465,62 +454,56 @@ static int __initdata parport_count; -static int __init parport_init_chip(struct hp_device *d, struct pa_iodc_driver *dri) +static int __devinit parport_init_chip(struct parisc_device *dev) { unsigned long port; - int irq; - - irq = busdevice_alloc_irq(d); - if (!irq) { - printk(KERN_DEBUG "IRQ not found for parallel device at 0x%p\n", d->hpa); - return -ENODEV; + if (!dev->irq) { + printk("IRQ not found for parallel device at 0x%lx\n", dev->hpa); + return -ENODEV; } - port = ((unsigned long) d->hpa) + PARPORT_GSC_OFFSET; + port = dev->hpa + PARPORT_GSC_OFFSET; - /* - some older machines with ASP-chip don't support the enhanced parport modes - */ - if (!pdc_add_valid( (void *)(port+4))) { - /* Initialize bidirectional-mode (0x10) & data-tranfer-mode #1 (0x20) */ - printk(KERN_DEBUG "%s: initialize bidirectional-mode.\n", __FUNCTION__); - parport_writeb ( (0x10 + 0x20), port + 4); + /* some older machines with ASP-chip don't support + * the enhanced parport modes. + */ + if (boot_cpu_data.cpu_type > pcxt && !pdc_add_valid(port+4)) { + + /* Initialize bidirectional-mode (0x10) & data-tranfer-mode #1 (0x20) */ + printk("%s: initialize bidirectional-mode.\n", __FUNCTION__); + parport_writeb ( (0x10 + 0x20), port + 4); + } else { - printk(KERN_DEBUG "%s: enhanced parport-modes not supported.\n", __FUNCTION__); + printk("%s: enhanced parport-modes not supported.\n", __FUNCTION__); } - if (parport_gsc_probe_port(port, 0, - irq, /* PARPORT_IRQ_NONE */ - PARPORT_DMA_NONE, NULL)) - parport_count++; + if (parport_gsc_probe_port(port, 0, dev->irq, + /* PARPORT_IRQ_NONE */ PARPORT_DMA_NONE, NULL)) + parport_count++; return 0; } -static struct pa_iodc_driver parport_drivers_for[] __initdata = { - {HPHW_FIO, 0x0, 0x0, 0x74, 0x0, 0, /* 715/64 */ - DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE, - "parallel device", "HP 7xx - Series", (void *) parport_init_chip}, - { 0 } +static struct parisc_device_id parport_tbl[] = { + { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x74 }, + { 0, } }; -int __init parport_gsc_init(void) -{ - parport_count = 0; - - register_driver(parport_drivers_for); - - return 0; -} +MODULE_DEVICE_TABLE(parisc, parport_tbl); +static struct parisc_driver parport_driver = { + name: "Parallel", + id_table: parport_tbl, + probe: parport_init_chip, +}; -static int __init parport_gsc_init_module(void) -{ - return !parport_gsc_init(); +int __devinit parport_gsc_init(void) +{ + return register_parisc_driver(&parport_driver); } -static void __exit parport_gsc_exit_module(void) +static void __devexit parport_gsc_exit(void) { struct parport *p = parport_enumerate(), *tmp; while (p) { @@ -532,11 +515,6 @@ free_dma(p->dma); if (p->irq != PARPORT_IRQ_NONE) free_irq(p->irq, p); - release_region(p->base, 3); - if (p->size > 3) - release_region(p->base + 3, p->size - 3); - if (p->modes & PARPORT_MODE_ECP) - release_region(p->base_hi, 3); parport_proc_unregister(p); if (priv->dma_buf) pci_free_consistent(priv->dev, PAGE_SIZE, @@ -548,9 +526,10 @@ } p = tmp; } + unregister_parisc_driver(&parport_driver); } EXPORT_NO_SYMBOLS; -module_init(parport_gsc_init_module); -module_exit(parport_gsc_exit_module); +module_init(parport_gsc_init); +module_exit(parport_gsc_exit); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/pci/pci.c linux.19rc3-ac4/drivers/pci/pci.c --- linux.19rc3/drivers/pci/pci.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/pci/pci.c 2002-07-29 13:58:43.000000000 +0100 @@ -1629,7 +1629,7 @@ return error; } -static int pci_pm_suspend(u32 state) +int pci_pm_suspend(u32 state) { struct list_head *list; struct pci_bus *bus; @@ -1642,7 +1642,7 @@ return 0; } -static int pci_pm_resume(void) +int pci_pm_resume(void) { struct list_head *list; struct pci_bus *bus; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/pci/pci.ids linux.19rc3-ac4/drivers/pci/pci.ids --- linux.19rc3/drivers/pci/pci.ids 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/pci/pci.ids 2002-07-29 13:58:43.000000000 +0100 @@ -2945,11 +2945,17 @@ 0009 CNB20LE Host Bridge 0010 CIOB30 0011 CMIC-HE + 0017 GCNB-LE Host Bridge 0200 OSB4 South Bridge 0201 CSB5 South Bridge + 0203 CSB6 South Bridge 0211 OSB4 IDE Controller 0212 CSB5 IDE Controller - 0220 OSB4/CSB5 USB Controller + 0213 CSB6 RAID/IDE Controller + 0220 OSB4/CSB5 OHCI USB Controller + 0221 CSB6 OHCI USB Controller + 0225 GCLE Host Bridge + 0227 GCLE-2 Host Bridge 1167 Mutoh Industries Inc 1168 Thine Electronics Inc 1169 Centre for Development of Advanced Computing diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/pnp/Config.in linux.19rc3-ac4/drivers/pnp/Config.in --- linux.19rc3/drivers/pnp/Config.in 2002-07-29 12:49:59.000000000 +0100 +++ linux.19rc3-ac4/drivers/pnp/Config.in 2002-07-29 13:58:43.000000000 +0100 @@ -8,4 +8,8 @@ dep_tristate ' ISA Plug and Play support' CONFIG_ISAPNP $CONFIG_PNP +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + dep_bool ' PNPBIOS support (EXPERIMENTAL)' CONFIG_PNPBIOS $CONFIG_PNP +fi + endmenu diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/pnp/isapnp.c linux.19rc3-ac4/drivers/pnp/isapnp.c --- linux.19rc3/drivers/pnp/isapnp.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/pnp/isapnp.c 2002-07-29 13:58:43.000000000 +0100 @@ -28,6 +28,8 @@ * 2001-11-07 Added isapnp_{,un}register_driver calls along the lines * of the pci driver interface * Kai Germaschewski + * 2002-06-06 Made the use of dma channel 0 configurable + * Gerald Teschl */ #include @@ -59,6 +61,7 @@ int isapnp_disable; /* Disable ISA PnP */ int isapnp_rdp; /* Read Data Port */ int isapnp_reset = 1; /* reset all PnP cards (deactivate) */ +int isapnp_allow_dma0 = -1; /* allow dma 0 during auto activation: -1=off (:default), 0=off (set by user), 1=on */ int isapnp_skip_pci_scan; /* skip PCI resource scanning */ int isapnp_verbose = 1; /* verbose mode */ int isapnp_reserve_irq[16] = { [0 ... 15] = -1 }; /* reserve (don't use) some IRQ */ @@ -74,6 +77,8 @@ MODULE_PARM_DESC(isapnp_rdp, "ISA Plug & Play read data port"); MODULE_PARM(isapnp_reset, "i"); MODULE_PARM_DESC(isapnp_reset, "ISA Plug & Play reset all cards"); +MODULE_PARM(isapnp_allow_dma0, "i"); +MODULE_PARM_DESC(isapnp_allow_dma0, "Allow dma value 0 during auto activation"); MODULE_PARM(isapnp_skip_pci_scan, "i"); MODULE_PARM_DESC(isapnp_skip_pci_scan, "ISA Plug & Play skip PCI resource scanning"); MODULE_PARM(isapnp_verbose, "i"); @@ -1750,13 +1755,14 @@ static int isapnp_check_dma(struct isapnp_cfgtmp *cfg, int dma, int idx) { - int i; + int i, mindma =1; struct pci_dev *dev; /* Some machines allow DMA 0, but others don't. In fact on some boxes DMA 0 is the memory refresh. Play safe */ - - if (dma < 1 || dma == 4 || dma > 7) + if (isapnp_allow_dma0 == 1) + mindma = 0; + if (dma < mindma || dma == 4 || dma > 7) return 1; for (i = 0; i < 8; i++) { if (isapnp_reserve_dma[i] == dma) diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/pnp/isapnp_proc.c linux.19rc3-ac4/drivers/pnp/isapnp_proc.c --- linux.19rc3/drivers/pnp/isapnp_proc.c 2002-07-29 12:49:59.000000000 +0100 +++ linux.19rc3-ac4/drivers/pnp/isapnp_proc.c 2002-07-29 13:58:43.000000000 +0100 @@ -944,6 +944,22 @@ res->start = res->end = dma; res->flags = IORESOURCE_DMA; } + +extern int isapnp_allow_dma0; +static int isapnp_set_allow_dma0(char *line) +{ + int i; + char value[32]; + + isapnp_get_str(value, line, sizeof(value)); + i = simple_strtoul(value, NULL, 0); + if (i < 0 || i > 1) { + printk("isapnp: wrong value %i for allow_dma0\n", i); + return 1; + } + isapnp_allow_dma0 = i; + return 0; +} static int isapnp_set_dma(char *line) { @@ -1030,6 +1046,8 @@ char cmd[32]; line = isapnp_get_str(cmd, line, sizeof(cmd)); + if (!strcmp(cmd, "allow_dma0")) + return isapnp_set_allow_dma0(line); if (!strcmp(cmd, "card")) return isapnp_set_card(line); if (!strcmp(cmd, "csn")) diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/pnp/Makefile linux.19rc3-ac4/drivers/pnp/Makefile --- linux.19rc3/drivers/pnp/Makefile 2002-07-29 12:49:59.000000000 +0100 +++ linux.19rc3-ac4/drivers/pnp/Makefile 2002-07-29 13:58:43.000000000 +0100 @@ -10,15 +10,22 @@ O_TARGET := pnp.o -export-objs := isapnp.o -list-multi := isa-pnp.o +export-objs := isapnp.o pnpbios_core.o +multi-objs := isa-pnp.o pnpbios.o -proc-$(CONFIG_PROC_FS) = isapnp_proc.o -isa-pnp-objs := isapnp.o quirks.o $(proc-y) +isa-pnp-proc-$(CONFIG_PROC_FS) = isapnp_proc.o +pnpbios-proc-$(CONFIG_PROC_FS) = pnpbios_proc.o + +isa-pnp-objs := isapnp.o quirks.o $(isa-pnp-proc-y) +pnpbios-objs := pnpbios_core.o $(pnpbios-proc-y) obj-$(CONFIG_ISAPNP) += isa-pnp.o +obj-$(CONFIG_PNPBIOS) += pnpbios.o include $(TOPDIR)/Rules.make isa-pnp.o: $(isa-pnp-objs) $(LD) $(LD_RFLAG) -r -o $@ $(isa-pnp-objs) + +pnpbios.o: $(pnpbios-objs) + $(LD) $(LD_RFLAG) -r -o $@ $(pnpbios-objs) diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/pnp/pnpbios_core.c linux.19rc3-ac4/drivers/pnp/pnpbios_core.c --- linux.19rc3/drivers/pnp/pnpbios_core.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/pnp/pnpbios_core.c 2002-07-29 13:58:43.000000000 +0100 @@ -0,0 +1,1352 @@ +/* + * PnP BIOS services + * + * Originally (C) 1998 Christian Schmidt + * Modifications (c) 1998 Tom Lees + * Minor reorganizations by David Hinds + * Modifications (c) 2001,2002 by Thomas Hood + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * References: + * Compaq Computer Corporation, Phoenix Technologies Ltd., Intel Corporation + * Plug and Play BIOS Specification, Version 1.0A, May 5, 1994 + * Plug and Play BIOS Clarification Paper, October 6, 1994 + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* + * + * PnP BIOS INTERFACE + * + */ + +/* PnP BIOS signature: "$PnP" */ +#define PNP_SIGNATURE (('$' << 0) + ('P' << 8) + ('n' << 16) + ('P' << 24)) + +#pragma pack(1) +union pnp_bios_expansion_header { + struct { + u32 signature; /* "$PnP" */ + u8 version; /* in BCD */ + u8 length; /* length in bytes, currently 21h */ + u16 control; /* system capabilities */ + u8 checksum; /* all bytes must add up to 0 */ + + u32 eventflag; /* phys. address of the event flag */ + u16 rmoffset; /* real mode entry point */ + u16 rmcseg; + u16 pm16offset; /* 16 bit protected mode entry */ + u32 pm16cseg; + u32 deviceID; /* EISA encoded system ID or 0 */ + u16 rmdseg; /* real mode data segment */ + u32 pm16dseg; /* 16 bit pm data segment base */ + } fields; + char chars[0x21]; /* To calculate the checksum */ +}; +#pragma pack() + +static struct { + u16 offset; + u16 segment; +} pnp_bios_callpoint; + +static union pnp_bios_expansion_header * pnp_bios_hdr = NULL; + +/* The PnP BIOS entries in the GDT */ +#define PNP_GDT (0x0060) +#define PNP_CS32 (PNP_GDT+0x00) /* segment for calling fn */ +#define PNP_CS16 (PNP_GDT+0x08) /* code segment for BIOS */ +#define PNP_DS (PNP_GDT+0x10) /* data segment for BIOS */ +#define PNP_TS1 (PNP_GDT+0x18) /* transfer data segment */ +#define PNP_TS2 (PNP_GDT+0x20) /* another data segment */ + +/* + * These are some opcodes for a "static asmlinkage" + * As this code is *not* executed inside the linux kernel segment, but in a + * alias at offset 0, we need a far return that can not be compiled by + * default (please, prove me wrong! this is *really* ugly!) + * This is the only way to get the bios to return into the kernel code, + * because the bios code runs in 16 bit protected mode and therefore can only + * return to the caller if the call is within the first 64kB, and the linux + * kernel begins at offset 3GB... + */ + +asmlinkage void pnp_bios_callfunc(void); + +__asm__( + ".text \n" + __ALIGN_STR "\n" + SYMBOL_NAME_STR(pnp_bios_callfunc) ":\n" + " pushl %edx \n" + " pushl %ecx \n" + " pushl %ebx \n" + " pushl %eax \n" + " lcallw " SYMBOL_NAME_STR(pnp_bios_callpoint) "\n" + " addl $16, %esp \n" + " lret \n" + ".previous \n" +); + +#define Q_SET_SEL(selname, address, size) \ +set_base (gdt [(selname) >> 3], __va((u32)(address))); \ +set_limit (gdt [(selname) >> 3], size) + +#define Q2_SET_SEL(selname, address, size) \ +set_base (gdt [(selname) >> 3], (u32)(address)); \ +set_limit (gdt [(selname) >> 3], size) + +/* + * At some point we want to use this stack frame pointer to unwind + * after PnP BIOS oopses. + */ + +u32 pnp_bios_fault_esp; +u32 pnp_bios_fault_eip; +u32 pnp_bios_is_utter_crap = 0; + +static spinlock_t pnp_bios_lock; + +static inline u16 call_pnp_bios(u16 func, u16 arg1, u16 arg2, u16 arg3, + u16 arg4, u16 arg5, u16 arg6, u16 arg7, + void *ts1_base, u32 ts1_size, + void *ts2_base, u32 ts2_size) +{ + unsigned long flags; + u16 status; + + /* + * PnP BIOSes are generally not terribly re-entrant. + * Also, don't rely on them to save everything correctly. + */ + if(pnp_bios_is_utter_crap) + return PNP_FUNCTION_NOT_SUPPORTED; + + /* On some boxes IRQ's during PnP BIOS calls are deadly. */ + spin_lock_irqsave(&pnp_bios_lock, flags); + + if (ts1_size) + Q2_SET_SEL(PNP_TS1, ts1_base, ts1_size); + if (ts2_size) + Q2_SET_SEL(PNP_TS2, ts2_base, ts2_size); + + __asm__ __volatile__( + "pushl %%ebp\n\t" + "pushl %%edi\n\t" + "pushl %%esi\n\t" + "pushl %%ds\n\t" + "pushl %%es\n\t" + "pushl %%fs\n\t" + "pushl %%gs\n\t" + "pushfl\n\t" + "movl %%esp, pnp_bios_fault_esp\n\t" + "movl $1f, pnp_bios_fault_eip\n\t" + "lcall %5,%6\n\t" + "1:popfl\n\t" + "popl %%gs\n\t" + "popl %%fs\n\t" + "popl %%es\n\t" + "popl %%ds\n\t" + "popl %%esi\n\t" + "popl %%edi\n\t" + "popl %%ebp\n\t" + : "=a" (status) + : "0" ((func) | (((u32)arg1) << 16)), + "b" ((arg2) | (((u32)arg3) << 16)), + "c" ((arg4) | (((u32)arg5) << 16)), + "d" ((arg6) | (((u32)arg7) << 16)), + "i" (PNP_CS32), + "i" (0) + : "memory" + ); + spin_unlock_irqrestore(&pnp_bios_lock, flags); + + /* If we get here and this is set then the PnP BIOS faulted on us. */ + if(pnp_bios_is_utter_crap) + { + printk(KERN_ERR "PnPBIOS: Warning! Your PnP BIOS caused a fatal error. Attempting to continue.\n"); + printk(KERN_ERR "PnPBIOS: You may need to reboot with the \"pnpbios=off\" option to operate stably.\n"); + printk(KERN_ERR "PnPBIOS: Check with your vendor for an updated BIOS.\n"); + } + + return status; +} + + +/* + * + * UTILITY FUNCTIONS + * + */ + +static void pnpbios_warn_unexpected_status(const char * module, u16 status) +{ + printk(KERN_ERR "PnPBIOS: %s: Unexpected status 0x%x\n", module, status); +} + +void *pnpbios_kmalloc(size_t size, int f) +{ + void *p = kmalloc( size, f ); + if ( p == NULL ) + printk(KERN_ERR "PnPBIOS: kmalloc() failed\n"); + return p; +} + +/* + * Call this only after init time + */ +static inline int pnp_bios_present(void) +{ + return (pnp_bios_hdr != NULL); +} + +/* Forward declaration */ +static void update_devlist( u8 nodenum, struct pnp_bios_node *data ); + + +/* + * + * PnP BIOS ACCESS FUNCTIONS + * + */ + +#define PNP_GET_NUM_SYS_DEV_NODES 0x00 +#define PNP_GET_SYS_DEV_NODE 0x01 +#define PNP_SET_SYS_DEV_NODE 0x02 +#define PNP_GET_EVENT 0x03 +#define PNP_SEND_MESSAGE 0x04 +#define PNP_GET_DOCKING_STATION_INFORMATION 0x05 +#define PNP_SET_STATIC_ALLOCED_RES_INFO 0x09 +#define PNP_GET_STATIC_ALLOCED_RES_INFO 0x0a +#define PNP_GET_APM_ID_TABLE 0x0b +#define PNP_GET_PNP_ISA_CONFIG_STRUC 0x40 +#define PNP_GET_ESCD_INFO 0x41 +#define PNP_READ_ESCD 0x42 +#define PNP_WRITE_ESCD 0x43 + +/* + * Call PnP BIOS with function 0x00, "get number of system device nodes" + */ +static int __pnp_bios_dev_node_info(struct pnp_dev_node_info *data) +{ + u16 status; + if (!pnp_bios_present()) + return PNP_FUNCTION_NOT_SUPPORTED; + status = call_pnp_bios(PNP_GET_NUM_SYS_DEV_NODES, 0, PNP_TS1, 2, PNP_TS1, PNP_DS, 0, 0, + data, sizeof(struct pnp_dev_node_info), 0, 0); + data->no_nodes &= 0xff; + return status; +} + +int pnp_bios_dev_node_info(struct pnp_dev_node_info *data) +{ + int status = __pnp_bios_dev_node_info( data ); + if ( status ) + pnpbios_warn_unexpected_status( "dev_node_info", status ); + return status; +} + +/* + * Note that some PnP BIOSes (e.g., on Sony Vaio laptops) die a horrible + * death if they are asked to access the "current" configuration. + * Therefore, if it's a matter of indifference, it's better to call + * get_dev_node() and set_dev_node() with boot=1 rather than with boot=0. + */ + +/* + * Call PnP BIOS with function 0x01, "get system device node" + * Input: *nodenum = desired node, + * boot = whether to get nonvolatile boot (!=0) + * or volatile current (0) config + * Output: *nodenum=next node or 0xff if no more nodes + */ +static int __pnp_bios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node *data) +{ + u16 status; + if (!pnp_bios_present()) + return PNP_FUNCTION_NOT_SUPPORTED; + if ( !boot & pnpbios_dont_use_current_config ) + return PNP_FUNCTION_NOT_SUPPORTED; + status = call_pnp_bios(PNP_GET_SYS_DEV_NODE, 0, PNP_TS1, 0, PNP_TS2, boot ? 2 : 1, PNP_DS, 0, + nodenum, sizeof(char), data, 65536); + return status; +} + +int pnp_bios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node *data) +{ + int status; + status = __pnp_bios_get_dev_node( nodenum, boot, data ); + if ( status ) + pnpbios_warn_unexpected_status( "get_dev_node", status ); + return status; +} + + +/* + * Call PnP BIOS with function 0x02, "set system device node" + * Input: *nodenum = desired node, + * boot = whether to set nonvolatile boot (!=0) + * or volatile current (0) config + */ +static int __pnp_bios_set_dev_node(u8 nodenum, char boot, struct pnp_bios_node *data) +{ + u16 status; + if (!pnp_bios_present()) + return PNP_FUNCTION_NOT_SUPPORTED; + if ( !boot & pnpbios_dont_use_current_config ) + return PNP_FUNCTION_NOT_SUPPORTED; + status = call_pnp_bios(PNP_SET_SYS_DEV_NODE, nodenum, 0, PNP_TS1, boot ? 2 : 1, PNP_DS, 0, 0, + data, 65536, 0, 0); + return status; +} + +int pnp_bios_set_dev_node(u8 nodenum, char boot, struct pnp_bios_node *data) +{ + int status; + status = __pnp_bios_set_dev_node( nodenum, boot, data ); + if ( status ) { + pnpbios_warn_unexpected_status( "set_dev_node", status ); + return status; + } + if ( !boot ) { /* Update devlist */ + u8 thisnodenum = nodenum; + status = pnp_bios_get_dev_node( &nodenum, boot, data ); + if ( status ) + return status; + update_devlist( thisnodenum, data ); + } + return status; +} + +#if needed +/* + * Call PnP BIOS with function 0x03, "get event" + */ +static int pnp_bios_get_event(u16 *event) +{ + u16 status; + if (!pnp_bios_present()) + return PNP_FUNCTION_NOT_SUPPORTED; + status = call_pnp_bios(PNP_GET_EVENT, 0, PNP_TS1, PNP_DS, 0, 0 ,0 ,0, + event, sizeof(u16), 0, 0); + return status; +} +#endif + +#if needed +/* + * Call PnP BIOS with function 0x04, "send message" + */ +static int pnp_bios_send_message(u16 message) +{ + u16 status; + if (!pnp_bios_present()) + return PNP_FUNCTION_NOT_SUPPORTED; + status = call_pnp_bios(PNP_SEND_MESSAGE, message, PNP_DS, 0, 0, 0, 0, 0, 0, 0, 0, 0); + return status; +} +#endif + +#ifdef CONFIG_HOTPLUG +/* + * Call PnP BIOS with function 0x05, "get docking station information" + */ +static int pnp_bios_dock_station_info(struct pnp_docking_station_info *data) +{ + u16 status; + if (!pnp_bios_present()) + return PNP_FUNCTION_NOT_SUPPORTED; + status = call_pnp_bios(PNP_GET_DOCKING_STATION_INFORMATION, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0, + data, sizeof(struct pnp_docking_station_info), 0, 0); + return status; +} +#endif + +#if needed +/* + * Call PnP BIOS with function 0x09, "set statically allocated resource + * information" + */ +static int pnp_bios_set_stat_res(char *info) +{ + u16 status; + if (!pnp_bios_present()) + return PNP_FUNCTION_NOT_SUPPORTED; + status = call_pnp_bios(PNP_SET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0, + info, *((u16 *) info), 0, 0); + return status; +} +#endif + +/* + * Call PnP BIOS with function 0x0a, "get statically allocated resource + * information" + */ +static int __pnp_bios_get_stat_res(char *info) +{ + u16 status; + if (!pnp_bios_present()) + return PNP_FUNCTION_NOT_SUPPORTED; + status = call_pnp_bios(PNP_GET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0, + info, 65536, 0, 0); + return status; +} + +int pnp_bios_get_stat_res(char *info) +{ + int status; + status = __pnp_bios_get_stat_res( info ); + if ( status ) + pnpbios_warn_unexpected_status( "get_stat_res", status ); + return status; +} + +#if needed +/* + * Call PnP BIOS with function 0x0b, "get APM id table" + */ +static int pnp_bios_apm_id_table(char *table, u16 *size) +{ + u16 status; + if (!pnp_bios_present()) + return PNP_FUNCTION_NOT_SUPPORTED; + status = call_pnp_bios(PNP_GET_APM_ID_TABLE, 0, PNP_TS2, 0, PNP_TS1, PNP_DS, 0, 0, + table, *size, size, sizeof(u16)); + return status; +} +#endif + +/* + * Call PnP BIOS with function 0x40, "get isa pnp configuration structure" + */ +static int __pnp_bios_isapnp_config(struct pnp_isa_config_struc *data) +{ + u16 status; + if (!pnp_bios_present()) + return PNP_FUNCTION_NOT_SUPPORTED; + status = call_pnp_bios(PNP_GET_PNP_ISA_CONFIG_STRUC, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0, + data, sizeof(struct pnp_isa_config_struc), 0, 0); + return status; +} + +int pnp_bios_isapnp_config(struct pnp_isa_config_struc *data) +{ + int status; + status = __pnp_bios_isapnp_config( data ); + if ( status ) + pnpbios_warn_unexpected_status( "isapnp_config", status ); + return status; +} + +/* + * Call PnP BIOS with function 0x41, "get ESCD info" + */ +static int __pnp_bios_escd_info(struct escd_info_struc *data) +{ + u16 status; + if (!pnp_bios_present()) + return ESCD_FUNCTION_NOT_SUPPORTED; + status = call_pnp_bios(PNP_GET_ESCD_INFO, 0, PNP_TS1, 2, PNP_TS1, 4, PNP_TS1, PNP_DS, + data, sizeof(struct escd_info_struc), 0, 0); + return status; +} + +int pnp_bios_escd_info(struct escd_info_struc *data) +{ + int status; + status = __pnp_bios_escd_info( data ); + if ( status ) + pnpbios_warn_unexpected_status( "escd_info", status ); + return status; +} + +/* + * Call PnP BIOS function 0x42, "read ESCD" + * nvram_base is determined by calling escd_info + */ +static int __pnp_bios_read_escd(char *data, u32 nvram_base) +{ + u16 status; + if (!pnp_bios_present()) + return ESCD_FUNCTION_NOT_SUPPORTED; + status = call_pnp_bios(PNP_READ_ESCD, 0, PNP_TS1, PNP_TS2, PNP_DS, 0, 0, 0, + data, 65536, (void *)nvram_base, 65536); + return status; +} + +int pnp_bios_read_escd(char *data, u32 nvram_base) +{ + int status; + status = __pnp_bios_read_escd( data, nvram_base ); + if ( status ) + pnpbios_warn_unexpected_status( "read_escd", status ); + return status; +} + +#if needed +/* + * Call PnP BIOS function 0x43, "write ESCD" + */ +static int pnp_bios_write_escd(char *data, u32 nvram_base) +{ + u16 status; + if (!pnp_bios_present()) + return ESCD_FUNCTION_NOT_SUPPORTED; + status = call_pnp_bios(PNP_WRITE_ESCD, 0, PNP_TS1, PNP_TS2, PNP_DS, 0, 0, 0, + data, 65536, nvram_base, 65536); + return status; +} +#endif + + +/* + * + * DOCKING FUNCTIONS + * + */ + +#ifdef CONFIG_HOTPLUG + +static int unloading = 0; +static struct completion unload_sem; + +/* + * (Much of this belongs in a shared routine somewhere) + */ + +static int pnp_dock_event(int dock, struct pnp_docking_station_info *info) +{ + char *argv [3], **envp, *buf, *scratch; + int i = 0, value; + + if (!hotplug_path [0]) + return -ENOENT; + if (!current->fs->root) { + return -EAGAIN; + } + if (!(envp = (char **) pnpbios_kmalloc (20 * sizeof (char *), GFP_KERNEL))) { + return -ENOMEM; + } + if (!(buf = pnpbios_kmalloc (256, GFP_KERNEL))) { + kfree (envp); + return -ENOMEM; + } + + /* only one standardized param to hotplug command: type */ + argv [0] = hotplug_path; + argv [1] = "dock"; + argv [2] = 0; + + /* minimal command environment */ + envp [i++] = "HOME=/"; + envp [i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; + +#ifdef DEBUG + /* hint that policy agent should enter no-stdout debug mode */ + envp [i++] = "DEBUG=kernel"; +#endif + /* extensible set of named bus-specific parameters, + * supporting multiple driver selection algorithms. + */ + scratch = buf; + + /* action: add, remove */ + envp [i++] = scratch; + scratch += sprintf (scratch, "ACTION=%s", dock?"add":"remove") + 1; + + /* Report the ident for the dock */ + envp [i++] = scratch; + scratch += sprintf (scratch, "DOCK=%x/%x/%x", + info->location_id, info->serial, info->capabilities); + envp[i] = 0; + + value = call_usermodehelper (argv [0], argv, envp); + kfree (buf); + kfree (envp); + return 0; +} + +/* + * Poll the PnP docking at regular intervals + */ +static int pnp_dock_thread(void * unused) +{ + static struct pnp_docking_station_info now; + int docked = -1, d = 0; + daemonize(); + reparent_to_init(); + strcpy(current->comm, "kpnpbiosd"); + while(!unloading && !signal_pending(current)) + { + int status; + + /* + * Poll every 2 seconds + */ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ*2); + if(signal_pending(current)) + break; + + status = pnp_bios_dock_station_info(&now); + + switch(status) + { + /* + * No dock to manage + */ + case PNP_FUNCTION_NOT_SUPPORTED: + complete_and_exit(&unload_sem, 0); + case PNP_SYSTEM_NOT_DOCKED: + d = 0; + break; + case PNP_SUCCESS: + d = 1; + break; + default: + pnpbios_warn_unexpected_status( "pnp_dock_thread", status ); + continue; + } + if(d != docked) + { + if(pnp_dock_event(d, &now)==0) + { + docked = d; +#if 0 + printk(KERN_INFO "PnPBIOS: Docking station %stached\n", docked?"at":"de"); +#endif + } + } + } + complete_and_exit(&unload_sem, 0); +} + +#endif /* CONFIG_HOTPLUG */ + + +/* + * + * NODE DATA PARSING FUNCTIONS + * + */ + +static void add_irqresource(struct pci_dev *dev, int irq) +{ + int i = 0; + while (!(dev->irq_resource[i].flags & IORESOURCE_UNSET) && i < DEVICE_COUNT_IRQ) i++; + if (i < DEVICE_COUNT_IRQ) { + dev->irq_resource[i].start = (unsigned long) irq; + dev->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag + } +} + +static void add_dmaresource(struct pci_dev *dev, int dma) +{ + int i = 0; + while (!(dev->dma_resource[i].flags & IORESOURCE_UNSET) && i < DEVICE_COUNT_DMA) i++; + if (i < DEVICE_COUNT_DMA) { + dev->dma_resource[i].start = (unsigned long) dma; + dev->dma_resource[i].flags = IORESOURCE_DMA; // Also clears _UNSET flag + } +} + +static void add_ioresource(struct pci_dev *dev, int io, int len) +{ + int i = 0; + while (!(dev->resource[i].flags & IORESOURCE_UNSET) && i < DEVICE_COUNT_RESOURCE) i++; + if (i < DEVICE_COUNT_RESOURCE) { + dev->resource[i].start = (unsigned long) io; + dev->resource[i].end = (unsigned long)(io + len - 1); + dev->resource[i].flags = IORESOURCE_IO; // Also clears _UNSET flag + } +} + +static void add_memresource(struct pci_dev *dev, int mem, int len) +{ + int i = 0; + while (!(dev->resource[i].flags & IORESOURCE_UNSET) && i < DEVICE_COUNT_RESOURCE) i++; + if (i < DEVICE_COUNT_RESOURCE) { + dev->resource[i].start = (unsigned long) mem; + dev->resource[i].end = (unsigned long)(mem + len - 1); + dev->resource[i].flags = IORESOURCE_MEM; // Also clears _UNSET flag + } +} + +static void node_resource_data_to_dev(struct pnp_bios_node *node, struct pci_dev *dev) +{ + unsigned char *p = node->data, *lastp=NULL; + int i; + + /* + * First, set resource info to default values + */ + for (i=0;iresource[i].start = 0; // "disabled" + dev->resource[i].flags = IORESOURCE_UNSET; + } + for (i=0;iirq_resource[i].start = (unsigned long)-1; // "disabled" + dev->irq_resource[i].flags = IORESOURCE_UNSET; + } + for (i=0;idma_resource[i].start = (unsigned long)-1; // "disabled" + dev->dma_resource[i].flags = IORESOURCE_UNSET; + } + + /* + * Fill in dev resource info + */ + while ( (char *)p < ((char *)node->data + node->size )) { + if(p==lastp) break; + + if( p[0] & 0x80 ) {// large item + switch (p[0] & 0x7f) { + case 0x01: // memory + { + int io = *(short *) &p[4]; + int len = *(short *) &p[10]; + add_memresource(dev, io, len); + break; + } + case 0x02: // device name + { + int len = *(short *) &p[1]; + memcpy(dev->name, p + 3, len >= 80 ? 79 : len); + break; + } + case 0x05: // 32-bit memory + { + int io = *(int *) &p[4]; + int len = *(int *) &p[16]; + add_memresource(dev, io, len); + break; + } + case 0x06: // fixed location 32-bit memory + { + int io = *(int *) &p[4]; + int len = *(int *) &p[8]; + add_memresource(dev, io, len); + break; + } + } /* switch */ + lastp = p+3; + p = p + p[1] + p[2]*256 + 3; + continue; + } + if ((p[0]>>3) == 0x0f) // end tag + break; + switch (p[0]>>3) { + case 0x04: // irq + { + int i, mask, irq = -1; + mask= p[1] + p[2]*256; + for (i=0;i<16;i++, mask=mask>>1) + if(mask & 0x01) irq=i; + add_irqresource(dev, irq); + break; + } + case 0x05: // dma + { + int i, mask, dma = -1; + mask = p[1]; + for (i=0;i<8;i++, mask = mask>>1) + if(mask & 0x01) dma=i; + add_dmaresource(dev, dma); + break; + } + case 0x08: // io + { + int io= p[2] + p[3] *256; + int len = p[7]; + add_ioresource(dev, io, len); + break; + } + case 0x09: // fixed location io + { + int io = p[1] + p[2] * 256; + int len = p[3]; + add_ioresource(dev, io, len); + break; + } + } /* switch */ + lastp=p+1; + p = p + (p[0] & 0x07) + 1; + + } /* while */ + + return; +} + + +/* + * + * DEVICE LIST MANAGEMENT FUNCTIONS + * + * + * Some of these are exported to give public access + * + * Question: Why maintain a device list when the PnP BIOS can + * list devices for us? Answer: Some PnP BIOSes can't report + * the current configuration, only the boot configuration. + * The boot configuration can be changed, so we need to keep + * a record of what the configuration was when we booted; + * presumably it continues to describe the current config. + * For those BIOSes that can change the current config, we + * keep the information in the devlist up to date. + * + * Note that it is currently assumed that the list does not + * grow or shrink in size after init time, and slot_name + * never changes. The list is protected by a spinlock. + */ + +static LIST_HEAD(pnpbios_devices); + +static spinlock_t pnpbios_devices_lock; + +static int inline insert_device(struct pci_dev *dev) +{ + + /* + * FIXME: Check for re-add of existing node; + * return -1 if node already present + */ + + /* We don't lock because we only do this at init time */ + list_add_tail(&dev->global_list, &pnpbios_devices); + + return 0; +} + +#define HEX(id,a) hex[((id)>>a) & 15] +#define CHAR(id,a) (0x40 + (((id)>>a) & 31)) +// +static void inline pnpid32_to_pnpid(u32 id, char *str) +{ + const char *hex = "0123456789abcdef"; + + id = be32_to_cpu(id); + str[0] = CHAR(id, 26); + str[1] = CHAR(id, 21); + str[2] = CHAR(id,16); + str[3] = HEX(id, 12); + str[4] = HEX(id, 8); + str[5] = HEX(id, 4); + str[6] = HEX(id, 0); + str[7] = '\0'; + + return; +} +// +#undef CHAR +#undef HEX + +/* + * Build a linked list of pci_devs in order of ascending node number + * Called only at init time. + */ +static void __init build_devlist(void) +{ + u8 nodenum; + unsigned int nodes_got = 0; + unsigned int devs = 0; + struct pnp_bios_node *node; + struct pnp_dev_node_info node_info; + struct pci_dev *dev; + + if (!pnp_bios_present()) + return; + + if (pnp_bios_dev_node_info(&node_info) != 0) + return; + + node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL); + if (!node) + return; + + for(nodenum=0; nodenum<0xff; ) { + u8 thisnodenum = nodenum; + /* We build the list from the "boot" config because + * asking for the "current" config causes some + * BIOSes to crash. + */ + if (pnp_bios_get_dev_node(&nodenum, (char )1 , node)) + break; + nodes_got++; + dev = pnpbios_kmalloc(sizeof (struct pci_dev), GFP_KERNEL); + if (!dev) + break; + memset(dev,0,sizeof(struct pci_dev)); + dev->devfn = thisnodenum; + memcpy(dev->name,"PNPBIOS",8); + pnpid32_to_pnpid(node->eisa_id,dev->slot_name); + node_resource_data_to_dev(node,dev); + if(insert_device(dev)<0) + kfree(dev); + else + devs++; + if (nodenum <= thisnodenum) { + printk(KERN_ERR "PnPBIOS: build_devlist: Node number 0x%x is out of sequence following node 0x%x. Aborting.\n", (unsigned int)nodenum, (unsigned int)thisnodenum); + break; + } + } + kfree(node); + + printk(KERN_INFO "PnPBIOS: %i node%s reported by PnP BIOS; %i recorded by driver\n", + nodes_got, nodes_got != 1 ? "s" : "", devs); +} + +static struct pci_dev *find_device_by_nodenum( u8 nodenum ) +{ + struct pci_dev *dev; + + pnpbios_for_each_dev(dev) { + if(dev->devfn == nodenum) + return dev; + } + + return NULL; +} + +static void update_devlist( u8 nodenum, struct pnp_bios_node *data ) +{ + unsigned long flags; + struct pci_dev *dev; + + spin_lock_irqsave(&pnpbios_devices_lock, flags); + dev = find_device_by_nodenum( nodenum ); + if ( dev ) { + node_resource_data_to_dev(data,dev); + } + spin_unlock_irqrestore(&pnpbios_devices_lock, flags); + + return; +} + + +/* + * + * DRIVER REGISTRATION FUNCTIONS + * + * + * Exported to give public access + * + */ + +static LIST_HEAD(pnpbios_drivers); + +static const struct pnpbios_device_id * +match_device(const struct pnpbios_device_id *ids, const struct pci_dev *dev) +{ + while (*ids->id) + { + if(memcmp(ids->id, dev->slot_name, 7)==0) + return ids; + ids++; + } + return NULL; +} + +static int announce_device(struct pnpbios_driver *drv, struct pci_dev *dev) +{ + const struct pnpbios_device_id *id; + struct pci_dev tmpdev; + int ret; + + if (drv->id_table) { + id = match_device(drv->id_table, dev); + if (!id) + return 0; + } else + id = NULL; + + memcpy( &tmpdev, dev, sizeof(struct pci_dev)); + tmpdev.global_list.prev = NULL; + tmpdev.global_list.next = NULL; + + dev_probe_lock(); + /* Obviously, probe() should not call any pnpbios functions */ + ret = drv->probe(&tmpdev, id); + dev_probe_unlock(); + if (ret < 1) + return 0; + + dev->driver = (void *)drv; + + return 1; +} + +/** + * pnpbios_register_driver - register a new pci driver + * @drv: the driver structure to register + * + * Adds the driver structure to the list of registered drivers + * + * For each device in the pnpbios device list that matches one of + * the ids in drv->id_table, calls the driver's "probe" function with + * arguments (1) a pointer to a *temporary* struct pci_dev containing + * resource info for the device, and (2) a pointer to the id string + * of the device. Expects the probe function to return 1 if the + * driver claims the device (otherwise 0) in which case, marks the + * device as having this driver. + * + * Returns the number of pci devices which were claimed by the driver + * during registration. The driver remains registered even if the + * return value is zero. + */ +int pnpbios_register_driver(struct pnpbios_driver *drv) +{ + struct pci_dev *dev; + unsigned long flags; + int count = 0; + + list_add_tail(&drv->node, &pnpbios_drivers); + spin_lock_irqsave(&pnpbios_devices_lock, flags); + pnpbios_for_each_dev(dev) { + if (!pnpbios_dev_driver(dev)) + count += announce_device(drv, dev); + } + spin_unlock_irqrestore(&pnpbios_devices_lock, flags); + return count; +} + +EXPORT_SYMBOL(pnpbios_register_driver); + +/** + * pnpbios_unregister_driver - unregister a pci driver + * @drv: the driver structure to unregister + * + * Deletes the driver structure from the list of registered PnPBIOS + * drivers, gives it a chance to clean up by calling its "remove" + * function for each device it was responsible for, and marks those + * devices as driverless. + */ +void pnpbios_unregister_driver(struct pnpbios_driver *drv) +{ + unsigned long flags; + struct pci_dev *dev; + + list_del(&drv->node); + spin_lock_irqsave(&pnpbios_devices_lock, flags); + pnpbios_for_each_dev(dev) { + if (dev->driver == (void *)drv) { + if (drv->remove) + drv->remove(dev); + dev->driver = NULL; + } + } + spin_unlock_irqrestore(&pnpbios_devices_lock, flags); +} + +EXPORT_SYMBOL(pnpbios_unregister_driver); + + +/* + * + * RESOURCE RESERVATION FUNCTIONS + * + * + * Used only at init time + * + */ + +static void __init reserve_ioport_range(char *pnpid, int start, int end) +{ + struct resource *res; + char *regionid; + +#if 0 + /* + * TEMPORARY hack to work around the fact that the + * floppy driver inappropriately reserves ioports 0x3f0 and 0x3f1 + * Remove this once the floppy driver is fixed. + */ + if ( + (0x3f0 >= start && 0x3f0 <= end) + || (0x3f1 >= start && 0x3f1 <= end) + ) { + printk(KERN_INFO + "PnPBIOS: %s: ioport range 0x%x-0x%x NOT reserved\n", + pnpid, start, end + ); + return; + } +#endif + + regionid = pnpbios_kmalloc(16, GFP_KERNEL); + if ( regionid == NULL ) + return; + snprintf(regionid, 16, "PnPBIOS %s", pnpid); + res = request_region(start,end-start+1,regionid); + if ( res == NULL ) + kfree( regionid ); + else + res->flags &= ~IORESOURCE_BUSY; + /* + * Failures at this point are usually harmless. pci quirks for + * example do reserve stuff they know about too, so we may well + * have double reservations. + */ + printk(KERN_INFO + "PnPBIOS: %s: ioport range 0x%x-0x%x %s reserved\n", + pnpid, start, end, + NULL != res ? "has been" : "could not be" + ); + + return; +} + +static void __init reserve_resources_of_dev( struct pci_dev *dev ) +{ + int i; + + for (i=0;iresource[i].flags & IORESOURCE_UNSET ) + /* end of resources */ + break; + if (dev->resource[i].flags & IORESOURCE_IO) { + /* ioport */ + if ( dev->resource[i].start == 0 ) + /* disabled */ + /* Do nothing */ + continue; + if ( dev->resource[i].start < 0x100 ) + /* + * Below 0x100 is only standard PC hardware + * (pics, kbd, timer, dma, ...) + * We should not get resource conflicts there, + * and the kernel reserves these anyway + * (see arch/i386/kernel/setup.c). + * So, do nothing + */ + continue; + if ( dev->resource[i].end < dev->resource[i].start ) + /* invalid endpoint */ + /* Do nothing */ + continue; + reserve_ioport_range( + dev->slot_name, + dev->resource[i].start, + dev->resource[i].end + ); + } else if (dev->resource[i].flags & IORESOURCE_MEM) { + /* iomem */ + /* For now do nothing */ + continue; + } else { + /* Neither ioport nor iomem */ + /* Do nothing */ + continue; + } + } + + return; +} + +static void __init reserve_resources( void ) +{ + struct pci_dev *dev; + + pnpbios_for_each_dev(dev) { + if ( + 0 != strcmp(dev->slot_name,"PNP0c01") && /* memory controller */ + 0 != strcmp(dev->slot_name,"PNP0c02") /* system peripheral: other */ + ) { + continue; + } + reserve_resources_of_dev(dev); + } + + return; +} + + +/* + * + * INIT AND EXIT + * + */ + +extern int is_sony_vaio_laptop; + +static int pnpbios_disabled; /* = 0 */ +static int dont_reserve_resources; /* = 0 */ +int pnpbios_dont_use_current_config; /* = 0 */ + +#ifndef MODULE +static int __init pnpbios_setup(char *str) +{ + int invert; + + while ((str != NULL) && (*str != '\0')) { + if (strncmp(str, "off", 3) == 0) + pnpbios_disabled=1; + if (strncmp(str, "on", 2) == 0) + pnpbios_disabled=0; + invert = (strncmp(str, "no-", 3) == 0); + if (invert) + str += 3; + if (strncmp(str, "curr", 4) == 0) + pnpbios_dont_use_current_config = invert; + if (strncmp(str, "res", 3) == 0) + dont_reserve_resources = invert; + str = strchr(str, ','); + if (str != NULL) + str += strspn(str, ", \t"); + } + + return 1; +} + +__setup("pnpbios=", pnpbios_setup); +#endif + +int __init pnpbios_init(void) +{ + union pnp_bios_expansion_header *check; + u8 sum; + int i, length, r; + + spin_lock_init(&pnp_bios_lock); + spin_lock_init(&pnpbios_devices_lock); + + if(pnpbios_disabled) { + printk(KERN_INFO "PnPBIOS: Disabled\n"); + return -ENODEV; + } + + if ( is_sony_vaio_laptop ) + pnpbios_dont_use_current_config = 1; + + /* + * Search the defined area (0xf0000-0xffff0) for a valid PnP BIOS + * structure and, if one is found, sets up the selectors and + * entry points + */ + for (check = (union pnp_bios_expansion_header *) __va(0xf0000); + check < (union pnp_bios_expansion_header *) __va(0xffff0); + ((void *) (check)) += 16) { + if (check->fields.signature != PNP_SIGNATURE) + continue; + length = check->fields.length; + if (!length) + continue; + for (sum = 0, i = 0; i < length; i++) + sum += check->chars[i]; + if (sum) + continue; + if (check->fields.version < 0x10) { + printk(KERN_WARNING "PnPBIOS: PnP BIOS version %d.%d is not supported\n", + check->fields.version >> 4, + check->fields.version & 15); + continue; + } + printk(KERN_INFO "PnPBIOS: Found PnP BIOS installation structure at 0x%p\n", check); + printk(KERN_INFO "PnPBIOS: PnP BIOS version %d.%d, entry 0x%x:0x%x, dseg 0x%x\n", + check->fields.version >> 4, check->fields.version & 15, + check->fields.pm16cseg, check->fields.pm16offset, + check->fields.pm16dseg); + Q2_SET_SEL(PNP_CS32, &pnp_bios_callfunc, 64 * 1024); + Q_SET_SEL(PNP_CS16, check->fields.pm16cseg, 64 * 1024); + Q_SET_SEL(PNP_DS, check->fields.pm16dseg, 64 * 1024); + pnp_bios_callpoint.offset = check->fields.pm16offset; + pnp_bios_callpoint.segment = PNP_CS16; + pnp_bios_hdr = check; + break; + } + if (!pnp_bios_present()) + return -ENODEV; + build_devlist(); + if ( ! dont_reserve_resources ) + reserve_resources(); +#ifdef CONFIG_PROC_FS + r = pnpbios_proc_init(); + if (r) + return r; +#endif + return 0; +} + +static int pnpbios_thread_init(void) +{ +#ifdef CONFIG_HOTPLUG + init_completion(&unload_sem); + if(kernel_thread(pnp_dock_thread, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL)>0) + unloading = 0; +#endif + return 0; +} + +#ifndef MODULE + +/* init/main.c calls pnpbios_init early */ + +/* Start the kernel thread later: */ +module_init(pnpbios_thread_init); + +#else + +/* + * N.B.: Building pnpbios as a module hasn't been fully implemented + */ + +MODULE_LICENSE("GPL"); + +static int pnpbios_init_all(void) +{ + int r; + r = pnpbios_init(); + if (r) + return r; + r = pnpbios_thread_init(); + if (r) + return r; + return 0; +} + +static void __exit pnpbios_exit(void) +{ +#ifdef CONFIG_HOTPLUG + unloading = 1; + wait_for_completion(&unload_sem); +#endif + pnpbios_proc_exit(); + /* We ought to free resources here */ + return; +} + +module_init(pnpbios_init_all); +module_exit(pnpbios_exit); + +#endif diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/pnp/pnpbios_proc.c linux.19rc3-ac4/drivers/pnp/pnpbios_proc.c --- linux.19rc3/drivers/pnp/pnpbios_proc.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/pnp/pnpbios_proc.c 2002-07-29 13:58:43.000000000 +0100 @@ -0,0 +1,270 @@ +/* + * /proc/bus/pnp interface for Plug and Play devices + * + * Written by David Hinds, dahinds@users.sourceforge.net + * Modified by Thomas Hood, jdthood@mail.com + * + * The .../devices and .../ and .../boot/ files are + * utilized by the lspnp and setpnp utilities, supplied with the + * pcmcia-cs package. + * http://pcmcia-cs.sourceforge.net + * + * The .../escd file is utilized by the lsescd utility written by + * Gunther Mayer. + * http://home.t-online.de/home/gunther.mayer/lsescd + * + * The .../legacy_device_resources file is not used yet. + * + * The other files are human-readable. + */ + +//#include +#define __NO_VERSION__ +//#include + +#include +#include +#include +#include +#include +#include + +static struct proc_dir_entry *proc_pnp = NULL; +static struct proc_dir_entry *proc_pnp_boot = NULL; +static struct pnp_dev_node_info node_info; + +static int proc_read_pnpconfig(char *buf, char **start, off_t pos, + int count, int *eof, void *data) +{ + struct pnp_isa_config_struc pnps; + + if (pnp_bios_isapnp_config(&pnps)) + return -EIO; + return snprintf(buf, count, + "structure_revision %d\n" + "number_of_CSNs %d\n" + "ISA_read_data_port 0x%x\n", + pnps.revision, + pnps.no_csns, + pnps.isa_rd_data_port + ); +} + +static int proc_read_escdinfo(char *buf, char **start, off_t pos, + int count, int *eof, void *data) +{ + struct escd_info_struc escd; + + if (pnp_bios_escd_info(&escd)) + return -EIO; + return snprintf(buf, count, + "min_ESCD_write_size %d\n" + "ESCD_size %d\n" + "NVRAM_base 0x%x\n", + escd.min_escd_write_size, + escd.escd_size, + escd.nv_storage_base + ); +} + +static int proc_read_escd(char *buf, char **start, off_t pos, + int count, int *eof, void *data) +{ + struct escd_info_struc escd; + char *tmpbuf; + int escd_size, escd_left_to_read, n; + + if (pnp_bios_escd_info(&escd)) + return -EIO; + + /* sanity check */ + if (escd.escd_size > (32*1024)) { + printk(KERN_ERR "PnPBIOS: proc_read_escd: ESCD size is too great\n"); + return -EFBIG; + } + + tmpbuf = pnpbios_kmalloc(escd.escd_size, GFP_KERNEL); + if (!tmpbuf) return -ENOMEM; + + if (pnp_bios_read_escd(tmpbuf, escd.nv_storage_base)) + return -EIO; + + escd_size = (unsigned char)(buf[0]) + (unsigned char)(buf[1])*256; + escd_left_to_read = escd_size - pos; + if (escd_left_to_read < 0) escd_left_to_read = 0; + if (escd_left_to_read == 0) *eof = 1; + n = min(count,escd_left_to_read); + memcpy(buf, tmpbuf + pos, n); + kfree(tmpbuf); + *start = buf; + return n; +} + +static int proc_read_legacyres(char *buf, char **start, off_t pos, + int count, int *eof, void *data) +{ + /* Assume that the following won't overflow the buffer */ + if (pnp_bios_get_stat_res(buf)) + return -EIO; + + return count; // FIXME: Return actual length +} + +static int proc_read_devices(char *buf, char **start, off_t pos, + int count, int *eof, void *data) +{ + struct pnp_bios_node *node; + u8 nodenum; + char *p = buf; + + if (pos >= 0xff) + return 0; + + node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL); + if (!node) return -ENOMEM; + + for (nodenum=pos; nodenum<0xff; ) { + u8 thisnodenum = nodenum; + /* 26 = the number of characters per line sprintf'ed */ + if ((p - buf + 26) > count) + break; + if (pnp_bios_get_dev_node(&nodenum, 1, node)) + break; + p += sprintf(p, "%02x\t%08x\t%02x:%02x:%02x\t%04x\n", + node->handle, node->eisa_id, + node->type_code[0], node->type_code[1], + node->type_code[2], node->flags); + if (nodenum <= thisnodenum) { + printk(KERN_ERR "%s Node number 0x%x is out of sequence following node 0x%x. Aborting.\n", "PnPBIOS: proc_read_devices:", (unsigned int)nodenum, (unsigned int)thisnodenum); + *eof = 1; + break; + } + } + kfree(node); + if (nodenum == 0xff) + *eof = 1; + *start = (char *)((off_t)nodenum - pos); + return p - buf; +} + +static int proc_read_node(char *buf, char **start, off_t pos, + int count, int *eof, void *data) +{ + struct pnp_bios_node *node; + int boot = (long)data >> 8; + u8 nodenum = (long)data; + int len; + + node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL); + if (!node) return -ENOMEM; + if (pnp_bios_get_dev_node(&nodenum, boot, node)) + return -EIO; + len = node->size - sizeof(struct pnp_bios_node); + memcpy(buf, node->data, len); + kfree(node); + return len; +} + +static int proc_write_node(struct file *file, const char *buf, + unsigned long count, void *data) +{ + struct pnp_bios_node *node; + int boot = (long)data >> 8; + u8 nodenum = (long)data; + + node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL); + if (!node) return -ENOMEM; + if ( pnp_bios_get_dev_node(&nodenum, boot, node) ) + return -EIO; + if (count != node->size - sizeof(struct pnp_bios_node)) + return -EINVAL; + memcpy(node->data, buf, count); + if (pnp_bios_set_dev_node(node->handle, boot, node) != 0) + return -EINVAL; + kfree(node); + return count; +} + +/* + * When this is called, pnpbios functions are assumed to + * work and the pnpbios_dont_use_current_config flag + * should already have been set to the appropriate value + */ +int __init pnpbios_proc_init( void ) +{ + struct pnp_bios_node *node; + struct proc_dir_entry *ent; + char name[3]; + u8 nodenum; + + if (pnp_bios_dev_node_info(&node_info)) + return -EIO; + + proc_pnp = proc_mkdir("pnp", proc_bus); + if (!proc_pnp) + return -EIO; + proc_pnp_boot = proc_mkdir("boot", proc_pnp); + if (!proc_pnp_boot) + return -EIO; + create_proc_read_entry("devices", 0, proc_pnp, proc_read_devices, NULL); + create_proc_read_entry("configuration_info", 0, proc_pnp, proc_read_pnpconfig, NULL); + create_proc_read_entry("escd_info", S_IRUSR, proc_pnp, proc_read_escdinfo, NULL); + create_proc_read_entry("escd", S_IRUSR, proc_pnp, proc_read_escd, NULL); + create_proc_read_entry("legacy_device_resources", 0, proc_pnp, proc_read_legacyres, NULL); + + node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL); + if (!node) + return -ENOMEM; + + for (nodenum=0; nodenum<0xff; ) { + u8 thisnodenum = nodenum; + if (pnp_bios_get_dev_node(&nodenum, 1, node) != 0) + break; + sprintf(name, "%02x", node->handle); + if ( !pnpbios_dont_use_current_config ) { + ent = create_proc_entry(name, 0, proc_pnp); + if (ent) { + ent->read_proc = proc_read_node; + ent->write_proc = proc_write_node; + ent->data = (void *)(long)(node->handle); + } + } + ent = create_proc_entry(name, 0, proc_pnp_boot); + if (ent) { + ent->read_proc = proc_read_node; + ent->write_proc = proc_write_node; + ent->data = (void *)(long)(node->handle+0x100); + } + if (nodenum <= thisnodenum) { + printk(KERN_ERR "%s Node number 0x%x is out of sequence following node 0x%x. Aborting.\n", "PnPBIOS: proc_init:", (unsigned int)nodenum, (unsigned int)thisnodenum); + break; + } + } + kfree(node); + + return 0; +} + +void __exit pnpbios_proc_exit(void) +{ + int i; + char name[3]; + + if (!proc_pnp) return; + + for (i=0; i<0xff; i++) { + sprintf(name, "%02x", i); + if ( !pnpbios_dont_use_current_config ) + remove_proc_entry(name, proc_pnp); + remove_proc_entry(name, proc_pnp_boot); + } + remove_proc_entry("legacy_device_resources", proc_pnp); + remove_proc_entry("escd", proc_pnp); + remove_proc_entry("escd_info", proc_pnp); + remove_proc_entry("configuration_info", proc_pnp); + remove_proc_entry("devices", proc_pnp); + remove_proc_entry("boot", proc_pnp); + remove_proc_entry("pnp", proc_bus); + + return; +} diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/sbus/char/aurora.c linux.19rc3-ac4/drivers/sbus/char/aurora.c --- linux.19rc3/drivers/sbus/char/aurora.c 2002-07-29 12:49:58.000000000 +0100 +++ linux.19rc3-ac4/drivers/sbus/char/aurora.c 2002-07-29 13:58:43.000000000 +0100 @@ -136,25 +136,25 @@ */ /* Get board number from pointer */ -extern inline int board_No (struct Aurora_board const * bp) +static inline int board_No (struct Aurora_board const * bp) { return bp - aurora_board; } /* Get port number from pointer */ -extern inline int port_No (struct Aurora_port const * port) +static inline int port_No (struct Aurora_port const * port) { return AURORA_PORT(port - aurora_port); } /* Get pointer to board from pointer to port */ -extern inline struct Aurora_board * port_Board(struct Aurora_port const * port) +static inline struct Aurora_board * port_Board(struct Aurora_port const * port) { return &aurora_board[AURORA_BOARD(port - aurora_port)]; } /* Wait for Channel Command Register ready */ -extern inline void aurora_wait_CCR(struct aurora_reg128 * r) +static inline void aurora_wait_CCR(struct aurora_reg128 * r) { unsigned long delay; @@ -173,7 +173,7 @@ */ /* Must be called with enabled interrupts */ -extern inline void aurora_long_delay(unsigned long delay) +static inline void aurora_long_delay(unsigned long delay) { unsigned long i; @@ -432,7 +432,7 @@ sbus_iounmap((unsigned long)bp->r3, 4); } -extern inline void aurora_mark_event(struct Aurora_port * port, int event) +static inline void aurora_mark_event(struct Aurora_port * port, int event) { #ifdef AURORA_DEBUG printk("aurora_mark_event: start\n"); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/sbus/dvma.c linux.19rc3-ac4/drivers/sbus/dvma.c --- linux.19rc3/drivers/sbus/dvma.c 2002-07-29 12:49:58.000000000 +0100 +++ linux.19rc3-ac4/drivers/sbus/dvma.c 2002-07-29 13:58:43.000000000 +0100 @@ -18,7 +18,7 @@ struct sbus_dma *dma_chain; /* Print out the current values in the DMA control registers */ -extern __inline__ void dump_dma_regs(unsigned long dregs) +static inline void dump_dma_regs(unsigned long dregs) { printk("DMA CONTROL<%08x> ADDR<%08x> CNT<%08x> TEST<%08x>\n", sbus_readl(dregs + DMA_CSR), sbus_readl(dregs + DMA_ADDR), diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/aacraid/aachba.c linux.19rc3-ac4/drivers/scsi/aacraid/aachba.c --- linux.19rc3/drivers/scsi/aacraid/aachba.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/aacraid/aachba.c 2002-07-29 13:58:43.000000000 +0100 @@ -42,6 +42,8 @@ #include "aacraid.h" /* SCSI Commands */ +/* TODO: dmb - use the ones defined in include/scsi/scsi.h */ + #define SS_TEST 0x00 /* Test unit ready */ #define SS_REZERO 0x01 /* Rezero unit */ #define SS_REQSEN 0x03 /* Request Sense */ @@ -60,19 +62,19 @@ #define SS_SEEK 0x2B /* Seek */ /* values for inqd_pdt: Peripheral device type in plain English */ -#define INQD_PDT_DA 0x00 /* Direct-access (DISK) device */ -#define INQD_PDT_PROC 0x03 /* Processor device */ -#define INQD_PDT_CHNGR 0x08 /* Changer (jukebox, scsi2) */ -#define INQD_PDT_COMM 0x09 /* Communication device (scsi2) */ -#define INQD_PDT_NOLUN2 0x1f /* Unknown Device (scsi2) */ -#define INQD_PDT_NOLUN 0x7f /* Logical Unit Not Present */ - -#define INQD_PDT_DMASK 0x1F /* Peripheral Device Type Mask */ -#define INQD_PDT_QMASK 0xE0 /* Peripheral Device Qualifer Mask */ - -#define TARGET_LUN_TO_CONTAINER(target, lun) (((lun) << 4) | target) -#define CONTAINER_TO_TARGET(cont) ((cont) & 0xf) -#define CONTAINER_TO_LUN(cont) ((cont) >> 4) +#define INQD_PDT_DA 0x00 /* Direct-access (DISK) device */ +#define INQD_PDT_PROC 0x03 /* Processor device */ +#define INQD_PDT_CHNGR 0x08 /* Changer (jukebox, scsi2) */ +#define INQD_PDT_COMM 0x09 /* Communication device (scsi2) */ +#define INQD_PDT_NOLUN2 0x1f /* Unknown Device (scsi2) */ +#define INQD_PDT_NOLUN 0x7f /* Logical Unit Not Present */ + +#define INQD_PDT_DMASK 0x1F /* Peripheral Device Type Mask */ +#define INQD_PDT_QMASK 0xE0 /* Peripheral Device Qualifer Mask */ + +#define TARGET_LUN_TO_CONTAINER(target, lun) (target) +#define CONTAINER_TO_TARGET(cont) ((cont)) +#define CONTAINER_TO_LUN(cont) (0) #define MAX_FIB_DATA (sizeof(struct hw_fib) - sizeof(FIB_HEADER)) @@ -81,22 +83,22 @@ /* * Sense keys */ -#define SENKEY_NO_SENSE 0x00 -#define SENKEY_UNDEFINED 0x01 -#define SENKEY_NOT_READY 0x02 -#define SENKEY_MEDIUM_ERR 0x03 -#define SENKEY_HW_ERR 0x04 -#define SENKEY_ILLEGAL 0x05 -#define SENKEY_ATTENTION 0x06 -#define SENKEY_PROTECTED 0x07 -#define SENKEY_BLANK 0x08 -#define SENKEY_V_UNIQUE 0x09 -#define SENKEY_CPY_ABORT 0x0A -#define SENKEY_ABORT 0x0B -#define SENKEY_EQUAL 0x0C -#define SENKEY_VOL_OVERFLOW 0x0D -#define SENKEY_MISCOMP 0x0E -#define SENKEY_RESERVED 0x0F +#define SENKEY_NO_SENSE 0x00 +#define SENKEY_UNDEFINED 0x01 +#define SENKEY_NOT_READY 0x02 +#define SENKEY_MEDIUM_ERR 0x03 +#define SENKEY_HW_ERR 0x04 +#define SENKEY_ILLEGAL 0x05 +#define SENKEY_ATTENTION 0x06 +#define SENKEY_PROTECTED 0x07 +#define SENKEY_BLANK 0x08 +#define SENKEY_V_UNIQUE 0x09 +#define SENKEY_CPY_ABORT 0x0A +#define SENKEY_ABORT 0x0B +#define SENKEY_EQUAL 0x0C +#define SENKEY_VOL_OVERFLOW 0x0D +#define SENKEY_MISCOMP 0x0E +#define SENKEY_RESERVED 0x0F /* * Sense codes @@ -160,16 +162,16 @@ *----------------------------------------------------------------------------*/ /* SCSI inquiry data */ struct inquiry_data { - u8 inqd_pdt; /* Peripheral qualifier | Peripheral Device Type */ - u8 inqd_dtq; /* RMB | Device Type Qualifier */ - u8 inqd_ver; /* ISO version | ECMA version | ANSI-approved version */ - u8 inqd_rdf; /* AENC | TrmIOP | Response data format */ - u8 inqd_len; /* Additional length (n-4) */ - u8 inqd_pad1[2];/* Reserved - must be zero */ - u8 inqd_pad2; /* RelAdr | WBus32 | WBus16 | Sync | Linked |Reserved| CmdQue | SftRe */ - u8 inqd_vid[8]; /* Vendor ID */ - u8 inqd_pid[16];/* Product ID */ - u8 inqd_prl[4]; /* Product Revision Level */ + u8 inqd_pdt; /* Peripheral qualifier | Peripheral Device Type */ + u8 inqd_dtq; /* RMB | Device Type Qualifier */ + u8 inqd_ver; /* ISO version | ECMA version | ANSI-approved version */ + u8 inqd_rdf; /* AENC | TrmIOP | Response data format */ + u8 inqd_len; /* Additional length (n-4) */ + u8 inqd_pad1[2]; /* Reserved - must be zero */ + u8 inqd_pad2; /* RelAdr | WBus32 | WBus16 | Sync | Linked |Reserved| CmdQue | SftRe */ + u8 inqd_vid[8]; /* Vendor ID */ + u8 inqd_pid[16]; /* Product ID */ + u8 inqd_prl[4]; /* Product Revision Level */ }; struct sense_data { @@ -215,6 +217,12 @@ static struct fsa_scsi_hba *fsa_dev[MAXIMUM_NUM_ADAPTERS]; /* SCSI Device Instance Pointers */ static struct sense_data sense_data[MAXIMUM_NUM_CONTAINERS]; static void get_sd_devname(int disknum, char *buffer); +static unsigned long aac_build_sg(Scsi_Cmnd* scsicmd, struct sgmap* sgmap); +static unsigned long aac_build_sg64(Scsi_Cmnd* scsicmd, struct sgmap64* psg); +static int aac_send_srb_fib(Scsi_Cmnd* scsicmd); +#ifdef AAC_DETAILED_STATUS_INFO +static char *aac_get_status_string(u32 status); +#endif /** * aac_get_containers - list containers @@ -225,7 +233,7 @@ int aac_get_containers(struct aac_dev *dev) { struct fsa_scsi_hba *fsa_dev_ptr; - int index, status = 0; + u32 index, status = 0; struct aac_query_mount *dinfo; struct aac_mount *dresp; struct fib * fibptr; @@ -396,9 +404,8 @@ struct scsi_inq *str; char *findit; struct aac_driver_ident *mp; - extern struct aac_driver_ident aac_drivers[]; /* HACK FIXME */ - mp = &aac_drivers[devtype]; + mp = aac_get_driver_ident(devtype); str = (struct scsi_inq *)(data); /* cast data to scsi inq block */ @@ -413,19 +420,19 @@ if (tindex < (sizeof(container_types)/sizeof(char *))){ inqstrcpy (container_types[tindex], findit); } - inqstrcpy ("0001", str->prl); + inqstrcpy ("V1.0", str->prl); } -void set_sense(char *sense_buf, u8 sense_key, u8 sense_code, +void set_sense(u8 *sense_buf, u8 sense_key, u8 sense_code, u8 a_sense_code, u8 incorrect_length, - u8 bit_pointer, unsigned field_pointer, - unsigned long residue) + u8 bit_pointer, u16 field_pointer, + u32 residue) { sense_buf[0] = 0xF0; /* Sense data valid, err code 70h (current error) */ sense_buf[1] = 0; /* Segment number, always zero */ if (incorrect_length) { - sense_buf[2] = sense_key | 0x20; /* Set the ILI bit | sense key */ + sense_buf[2] = sense_key | 0x20; /* Set ILI bit | sense key */ sense_buf[3] = BYTE3(residue); sense_buf[4] = BYTE2(residue); sense_buf[5] = BYTE1(residue); @@ -469,13 +476,76 @@ scsicmd->scsi_done(scsicmd); } +int aac_get_adapter_info(struct aac_dev* dev) +{ + struct fib* fibptr; + struct aac_adapter_info* info; + int rcode; + u32 tmp; + if (!(fibptr = fib_alloc(dev))) + return -ENOMEM; + + fib_init(fibptr); + info = (struct aac_adapter_info*) fib_data(fibptr); + + memset(info,0,sizeof(struct aac_adapter_info)); + + rcode = fib_send(RequestAdapterInfo, + fibptr, + sizeof(struct aac_adapter_info), + FsaNormal, + 1, 1, + NULL, + NULL); + + memcpy(&dev->adapter_info, info, sizeof(struct aac_adapter_info)); + + tmp = dev->adapter_info.kernelrev; + printk(KERN_INFO "%s%d: kernel %d.%d.%d build %d\n", + dev->name, dev->id, + tmp>>24,(tmp>>16)&0xff,(tmp>>8)&0xff, + dev->adapter_info.kernelbuild); + tmp = dev->adapter_info.monitorrev; + printk(KERN_INFO "%s%d: monitor %d.%d.%d build %d\n", + dev->name, dev->id, + tmp>>24,(tmp>>16)&0xff,(tmp>>8)&0xff, + dev->adapter_info.monitorbuild); + tmp = dev->adapter_info.biosrev; + printk(KERN_INFO "%s%d: bios %d.%d.%d build %d\n", + dev->name, dev->id, + tmp>>24,(tmp>>16)&0xff,(tmp>>8)&0xff, + dev->adapter_info.biosbuild); + printk(KERN_INFO "%s%d: serial %x%x\n", + dev->name, dev->id, + dev->adapter_info.serial[0], + dev->adapter_info.serial[1]); + dev->pae_support = 0; + dev->nondasd_support = 0; + if( BITS_PER_LONG >= 64 && + (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64)){ + printk(KERN_INFO "%s%d: 64 Bit PAE enabled\n", dev->name, dev->id); + dev->pae_support = 1; + } + /* TODO - dmb temporary until fw can set this bit */ + dev->pae_support = (BITS_PER_LONG >= 64); + if(dev->pae_support != 0) { + printk(KERN_INFO "%s%d: 64 Bit PAE enabled\n", dev->name, dev->id); + } + + if(dev->adapter_info.options & AAC_OPT_NONDASD){ + dev->nondasd_support = 1; + } + return rcode; +} + + static void read_callback(void *context, struct fib * fibptr) { struct aac_dev *dev; struct aac_read_reply *readreply; Scsi_Cmnd *scsicmd; - unsigned long lba; - int cid; + u32 lba; + u32 cid; scsicmd = (Scsi_Cmnd *) context; @@ -483,7 +553,7 @@ cid =TARGET_LUN_TO_CONTAINER(scsicmd->target, scsicmd->lun); lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3]; - dprintk((KERN_DEBUG "read_callback[cpu %d]: lba = %ld, t = %ld.\n", smp_processor_id(), lba, jiffies)); + dprintk((KERN_DEBUG "read_callback[cpu %d]: lba = %d, t = %ld.\n", smp_processor_id(), lba, jiffies)); if (fibptr == NULL) BUG(); @@ -494,7 +564,7 @@ scsicmd->use_sg, scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); else if(scsicmd->request_bufflen) - pci_unmap_single(dev->pdev, (dma_addr_t)(long)scsicmd->SCp.ptr, + pci_unmap_single(dev->pdev, (dma_addr_t)(unsigned long)scsicmd->SCp.ptr, scsicmd->request_bufflen, scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); readreply = (struct aac_read_reply *)fib_data(fibptr); @@ -503,7 +573,7 @@ else { printk(KERN_WARNING "read_callback: read failed, status = %d\n", readreply->status); scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION; - set_sense((char *) &sense_data[cid], + set_sense((u8 *) &sense_data[cid], SENKEY_HW_ERR, SENCODE_INTERNAL_TARGET_FAILURE, ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0, @@ -520,15 +590,15 @@ struct aac_dev *dev; struct aac_write_reply *writereply; Scsi_Cmnd *scsicmd; - unsigned long lba; - int cid; + u32 lba; + u32 cid; scsicmd = (Scsi_Cmnd *) context; dev = (struct aac_dev *)scsicmd->host->hostdata; cid = TARGET_LUN_TO_CONTAINER(scsicmd->target, scsicmd->lun); lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3]; - dprintk((KERN_DEBUG "write_callback[cpu %d]: lba = %ld, t = %ld.\n", smp_processor_id(), lba, jiffies)); + dprintk((KERN_DEBUG "write_callback[cpu %d]: lba = %d, t = %ld.\n", smp_processor_id(), lba, jiffies)); if (fibptr == NULL) BUG(); @@ -538,7 +608,7 @@ scsicmd->use_sg, scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); else if(scsicmd->request_bufflen) - pci_unmap_single(dev->pdev, (dma_addr_t)(long)scsicmd->SCp.ptr, + pci_unmap_single(dev->pdev, (dma_addr_t)(unsigned long)scsicmd->SCp.ptr, scsicmd->request_bufflen, scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); @@ -548,7 +618,7 @@ else { printk(KERN_WARNING "write_callback: write failed, status = %d\n", writereply->status); scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION; - set_sense((char *) &sense_data[cid], + set_sense((u8 *) &sense_data[cid], SENKEY_HW_ERR, SENCODE_INTERNAL_TARGET_FAILURE, ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0, @@ -562,12 +632,10 @@ int aac_read(Scsi_Cmnd * scsicmd, int cid) { - unsigned long lba; - unsigned long count; - unsigned long byte_count = 0; + u32 lba; + u32 count; int status; - struct aac_read *readcmd; u16 fibsize; struct aac_dev *dev; struct fib * cmd_fibcontext; @@ -591,7 +659,7 @@ lba = (scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8]; } - dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %lu, t = %ld.\n", smp_processor_id(), lba, jiffies)); + dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies)); /* * Alocate and initialize a Fib */ @@ -603,71 +671,58 @@ fib_init(cmd_fibcontext); - readcmd = (struct aac_read *) fib_data(cmd_fibcontext); - readcmd->command = cpu_to_le32(VM_CtBlockRead); - readcmd->cid = cpu_to_le32(cid); - readcmd->block = cpu_to_le32(lba); - readcmd->count = cpu_to_le32(count * 512); - readcmd->sg.count = cpu_to_le32(1); - - if (count * 512 > (64 * 1024)) - BUG(); - /* - * Build Scatter/Gather list - */ - if (scsicmd->use_sg) /* use scatter/gather list */ - { - struct scatterlist *sg; - int i; - int sg_count; - - sg = (struct scatterlist *) scsicmd->request_buffer; + if(dev->pae_support == 1){ + struct aac_read64 *readcmd; + readcmd = (struct aac_read64 *) fib_data(cmd_fibcontext); + readcmd->command = cpu_to_le32(VM_CtHostRead64); + readcmd->cid = cpu_to_le16(cid); + readcmd->sector_count = cpu_to_le16(count); + readcmd->block = cpu_to_le32(lba); + readcmd->pad = cpu_to_le16(0); + readcmd->flags = cpu_to_le16(0); - sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg, - scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); - - byte_count = 0; - - for (i = 0; i < sg_count; i++) { - readcmd->sg.sg[i].addr = cpu_to_le32(sg_dma_address(sg)); - readcmd->sg.sg[i].count = cpu_to_le32(sg_dma_len(sg)); - byte_count += sg->length; - if (sg->length > (64 * 1024)) - BUG(); - sg++; - } - readcmd->sg.count = cpu_to_le32(sg_count); - - if (sg_count > MAX_DRIVER_SG_SEGMENT_COUNT) + aac_build_sg64(scsicmd, &readcmd->sg); + if(readcmd->sg.count > MAX_DRIVER_SG_SEGMENT_COUNT) BUG(); - } - else if(scsicmd->request_bufflen) - { - dma_addr_t addr; - addr = pci_map_single(dev->pdev, scsicmd->request_buffer, - scsicmd->request_bufflen, scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); - scsicmd->SCp.ptr = (void *)(long)addr; - readcmd->sg.sg[0].addr = cpu_to_le32(addr); - readcmd->sg.sg[0].count = cpu_to_le32(scsicmd->request_bufflen); + fibsize = sizeof(struct aac_read64) + ((readcmd->sg.count - 1) * sizeof (struct sgentry64)); + /* + * Now send the Fib to the adapter + */ + status = fib_send(ContainerCommand64, + cmd_fibcontext, + fibsize, + FsaNormal, + 0, 1, + (fib_callback) read_callback, + (void *) scsicmd); + } else { + struct aac_read *readcmd; + readcmd = (struct aac_read *) fib_data(cmd_fibcontext); + readcmd->command = cpu_to_le32(VM_CtBlockRead); + readcmd->cid = cpu_to_le32(cid); + readcmd->block = cpu_to_le32(lba); + readcmd->count = cpu_to_le32(count * 512); - byte_count = scsicmd->request_bufflen; + if (count * 512 > (64 * 1024)) + BUG(); - if (byte_count > (64 * 1024)) + aac_build_sg(scsicmd, &readcmd->sg); + if(readcmd->sg.count > MAX_DRIVER_SG_SEGMENT_COUNT) BUG(); - } - if (byte_count != readcmd->count) - BUG(); - /* - * Now send the Fib to the adapter - */ - fibsize = sizeof(struct aac_read) + ((readcmd->sg.count - 1) * sizeof (struct sgentry)); - status = fib_send(ContainerCommand, + fibsize = sizeof(struct aac_read) + ((readcmd->sg.count - 1) * sizeof (struct sgentry)); + /* + * Now send the Fib to the adapter + */ + status = fib_send(ContainerCommand, cmd_fibcontext, fibsize, FsaNormal, 0, 1, (fib_callback) read_callback, (void *) scsicmd); + } + + /* * Check that the command queued to the controller */ @@ -687,11 +742,9 @@ static int aac_write(Scsi_Cmnd * scsicmd, int cid) { - unsigned long lba; - unsigned long count; - unsigned long byte_count = 0; + u32 lba; + u32 count; int status; - struct aac_write *writecmd; u16 fibsize; struct aac_dev *dev; struct fib * cmd_fibcontext; @@ -722,75 +775,61 @@ } fib_init(cmd_fibcontext); - writecmd = (struct aac_write *) fib_data(cmd_fibcontext); - writecmd->command = cpu_to_le32(VM_CtBlockWrite); - writecmd->cid = cpu_to_le32(cid); - writecmd->block = cpu_to_le32(lba); - writecmd->count = cpu_to_le32(count * 512); - writecmd->sg.count = cpu_to_le32(1); - /* FIXME: why isnt ->stable setup */ - - if (count * 512 > (64 * 1024)) { - BUG(); - } - /* - * Build Scatter/Gather list - */ - if (scsicmd->use_sg) + if(dev->pae_support == 1) { - struct scatterlist *sg; - int i; - int sg_count; - - sg = (struct scatterlist *) scsicmd->request_buffer; + struct aac_write64 *writecmd; + writecmd = (struct aac_write64 *) fib_data(cmd_fibcontext); + writecmd->command = cpu_to_le32(VM_CtHostWrite64); + writecmd->cid = cpu_to_le16(cid); + writecmd->sector_count = cpu_to_le16(count); + writecmd->block = cpu_to_le32(lba); + writecmd->pad = cpu_to_le16(0); + writecmd->flags = cpu_to_le16(0); - sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg, - scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); - - byte_count = 0; - - for (i = 0; i < scsicmd->use_sg; i++) { - writecmd->sg.sg[i].addr = cpu_to_le32(sg_dma_address(sg)); - writecmd->sg.sg[i].count = cpu_to_le32(sg_dma_len(sg)); - byte_count += sg->length; - - if (sg->length > (64 * 1024)) - BUG(); - sg++; - } - writecmd->sg.count = cpu_to_le32(sg_count); - - if (sg_count > MAX_DRIVER_SG_SEGMENT_COUNT) + aac_build_sg64(scsicmd, &writecmd->sg); + if(writecmd->sg.count > MAX_DRIVER_SG_SEGMENT_COUNT) BUG(); + fibsize = sizeof(struct aac_write64) + ((writecmd->sg.count - 1) * sizeof (struct sgentry64)); + /* + * Now send the Fib to the adapter + */ + status = fib_send(ContainerCommand64, + cmd_fibcontext, + fibsize, + FsaNormal, + 0, 1, + (fib_callback) write_callback, + (void *) scsicmd); } - else if(scsicmd->request_bufflen) + else { - dma_addr_t addr; - addr = pci_map_single(dev->pdev, - scsicmd->request_buffer, - scsicmd->request_bufflen, - scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); - writecmd->sg.sg[0].addr = cpu_to_le32(addr); - writecmd->sg.sg[0].count = cpu_to_le32(scsicmd->request_bufflen); - scsicmd->SCp.ptr = (void *)(long)addr; - byte_count = scsicmd->request_bufflen; + struct aac_write *writecmd; + writecmd = (struct aac_write *) fib_data(cmd_fibcontext); + writecmd->command = cpu_to_le32(VM_CtBlockWrite); + writecmd->cid = cpu_to_le32(cid); + writecmd->block = cpu_to_le32(lba); + writecmd->count = cpu_to_le32(count * 512); + writecmd->sg.count = cpu_to_le32(1); + /* ->stable is not used - it did mean which type of write */ - if (byte_count > (64 * 1024)) + if (count * 512 > (64 * 1024)) + BUG(); + aac_build_sg(scsicmd, &writecmd->sg); + if(writecmd->sg.count > MAX_DRIVER_SG_SEGMENT_COUNT) BUG(); + fibsize = sizeof(struct aac_write) + ((writecmd->sg.count - 1) * sizeof (struct sgentry)); + /* + * Now send the Fib to the adapter + */ + status = fib_send(ContainerCommand, + cmd_fibcontext, + fibsize, + FsaNormal, + 0, 1, + (fib_callback) write_callback, + (void *) scsicmd); } - if (byte_count != writecmd->count) - BUG(); - /* - * Now send the Fib to the adapter - */ - fibsize = sizeof (struct aac_write) + ((writecmd->sg.count - 1) * sizeof (struct sgentry)); - status = fib_send(ContainerCommand, - cmd_fibcontext, - fibsize, FsaNormal, - 0, 1, - (fib_callback) write_callback, - (void *) scsicmd); /* * Check that the command queued to the controller */ @@ -821,7 +860,7 @@ int aac_scsi_cmd(Scsi_Cmnd * scsicmd) { - int cid = 0; + u32 cid = 0; struct fsa_scsi_hba *fsa_dev_ptr; int cardtype; int ret; @@ -837,159 +876,174 @@ * itself. */ if (scsicmd->target != scsicmd->host->this_id) { - if ((scsicmd->channel > 0) ||(scsicmd->target > 15) || (scsicmd->lun > 7)) - { - dprintk((KERN_DEBUG "The bus, target or lun is out of range = %d, %d, %d.\n", - scsicmd->channel, scsicmd->target, scsicmd->lun)); - scsicmd->result = DID_BAD_TARGET << 16; - __aac_io_done(scsicmd); - return -1; - } - cid = TARGET_LUN_TO_CONTAINER(scsicmd->target, scsicmd->lun); - /* - * If the target container doesn't exist, it may have - * been newly created - */ - if (fsa_dev_ptr->valid[cid] == 0) { - switch (scsicmd->cmnd[0]) { - case SS_INQUIR: - case SS_RDCAP: - case SS_TEST: - spin_unlock_irq(&io_request_lock); - probe_container(dev, cid); - spin_lock_irq(&io_request_lock); - default: - break; + if ((scsicmd->channel == 0) ){ + if( (scsicmd->target >= AAC_MAX_TARGET) || (scsicmd->lun != 0)){ + scsicmd->result = DID_NO_CONNECT << 16; + __aac_io_done(scsicmd); + return 0; + } + cid = TARGET_LUN_TO_CONTAINER(scsicmd->target, scsicmd->lun); + + /* + * If the target container doesn't exist, it may have + * been newly created + */ + if (fsa_dev_ptr->valid[cid] == 0) { + switch (scsicmd->cmnd[0]) { + case SS_INQUIR: + case SS_RDCAP: + case SS_TEST: + spin_unlock_irq(&io_request_lock); + probe_container(dev, cid); + spin_lock_irq(&io_request_lock); + if (fsa_dev_ptr->valid[cid] == 0) { + scsicmd->result = DID_NO_CONNECT << 16; + __aac_io_done(scsicmd); + return 0; + } + default: + break; + } + } + /* + * If the target container still doesn't exist, + * return failure + */ + if (fsa_dev_ptr->valid[cid] == 0) { + scsicmd->result = DID_BAD_TARGET << 16; + __aac_io_done(scsicmd); + return -1; + } + } else { /* check for physical non-dasd devices */ + if(dev->nondasd_support == 1){ + return aac_send_srb_fib(scsicmd); + } else { + scsicmd->result = DID_NO_CONNECT << 16; + __aac_io_done(scsicmd); + return 0; } } - /* - * If the target container still doesn't exist, - * return failure - */ - if (fsa_dev_ptr->valid[cid] == 0) { - scsicmd->result = DID_BAD_TARGET << 16; - __aac_io_done(scsicmd); - return -1; - } - } + } + /* + * else Command for the controller itself + */ else if ((scsicmd->cmnd[0] != SS_INQUIR) && /* only INQUIRY & TUR cmnd supported for controller */ - (scsicmd->cmnd[0] != SS_TEST)) + (scsicmd->cmnd[0] != SS_TEST)) { - /* - * Command aimed at the controller - */ dprintk((KERN_WARNING "Only INQUIRY & TUR command supported for controller, rcvd = 0x%x.\n", scsicmd->cmnd[0])); scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION; - set_sense((char *) &sense_data[cid], + set_sense((u8 *) &sense_data[cid], SENKEY_ILLEGAL, SENCODE_INVALID_COMMAND, ASENCODE_INVALID_COMMAND, 0, 0, 0, 0); __aac_io_done(scsicmd); return -1; } + + /* Handle commands here that don't really require going out to the adapter */ - switch (scsicmd->cmnd[0]) + switch (scsicmd->cmnd[0]) { + case SS_INQUIR: { - case SS_INQUIR: - { - struct inquiry_data *inq_data_ptr; - - dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", scsicmd->target)); - inq_data_ptr = (struct inquiry_data *)scsicmd->request_buffer; - memset(inq_data_ptr, 0, sizeof (struct inquiry_data)); - - inq_data_ptr->inqd_ver = 2; /* claim compliance to SCSI-2 */ - inq_data_ptr->inqd_dtq = 0x80; /* set RMB bit to one indicating that the medium is removable */ - inq_data_ptr->inqd_rdf = 2; /* A response data format value of two indicates that the data shall be in the format specified in SCSI-2 */ - inq_data_ptr->inqd_len = 31; + struct inquiry_data *inq_data_ptr; - /* - * Set the Vendor, Product, and Revision Level - * see: .c i.e. aac.c - */ - setinqstr(cardtype, (void *) (inq_data_ptr->inqd_vid), fsa_dev_ptr->type[cid]); - if (scsicmd->target == scsicmd->host->this_id) - inq_data_ptr->inqd_pdt = INQD_PDT_PROC; /* Processor device */ - else - inq_data_ptr->inqd_pdt = INQD_PDT_DA; /* Direct/random access device */ - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; - __aac_io_done(scsicmd); - return 0; - } - case SS_RDCAP: - { - int capacity; - char *cp; - - dprintk((KERN_DEBUG "READ CAPACITY command.\n")); - capacity = fsa_dev_ptr->size[cid] - 1; - cp = scsicmd->request_buffer; - cp[0] = (capacity >> 24) & 0xff; - cp[1] = (capacity >> 16) & 0xff; - cp[2] = (capacity >> 8) & 0xff; - cp[3] = (capacity >> 0) & 0xff; - cp[4] = 0; - cp[5] = 0; - cp[6] = 2; - cp[7] = 0; + dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", scsicmd->target)); + inq_data_ptr = (struct inquiry_data *)scsicmd->request_buffer; + memset(inq_data_ptr, 0, sizeof (struct inquiry_data)); + + inq_data_ptr->inqd_ver = 2; /* claim compliance to SCSI-2 */ + inq_data_ptr->inqd_dtq = 0x80; /* set RMB bit to one indicating that the medium is removable */ + inq_data_ptr->inqd_rdf = 2; /* A response data format value of two indicates that the data shall be in the format specified in SCSI-2 */ + inq_data_ptr->inqd_len = 31; + /*Format for "pad2" is RelAdr | WBus32 | WBus16 | Sync | Linked |Reserved| CmdQue | SftRe */ + inq_data_ptr->inqd_pad2= 0x32 ; /*WBus16|Sync|CmdQue */ + /* + * Set the Vendor, Product, and Revision Level + * see: .c i.e. aac.c + */ + setinqstr(cardtype, (void *) (inq_data_ptr->inqd_vid), fsa_dev_ptr->type[cid]); + if (scsicmd->target == scsicmd->host->this_id) + inq_data_ptr->inqd_pdt = INQD_PDT_PROC; /* Processor device */ + else + inq_data_ptr->inqd_pdt = INQD_PDT_DA; /* Direct/random access device */ + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; + __aac_io_done(scsicmd); + return 0; + } + case SS_RDCAP: + { + int capacity; + char *cp; - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; - __aac_io_done(scsicmd); + dprintk((KERN_DEBUG "READ CAPACITY command.\n")); + capacity = fsa_dev_ptr->size[cid] - 1; + cp = scsicmd->request_buffer; + cp[0] = (capacity >> 24) & 0xff; + cp[1] = (capacity >> 16) & 0xff; + cp[2] = (capacity >> 8) & 0xff; + cp[3] = (capacity >> 0) & 0xff; + cp[4] = 0; + cp[5] = 0; + cp[6] = 2; + cp[7] = 0; - return 0; - } + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; + __aac_io_done(scsicmd); - case SS_MODESEN: - { - char *mode_buf; - - dprintk((KERN_DEBUG "MODE SENSE command.\n")); - mode_buf = scsicmd->request_buffer; - mode_buf[0] = 0; /* Mode data length (MSB) */ - mode_buf[1] = 6; /* Mode data length (LSB) */ - mode_buf[2] = 0; /* Medium type - default */ - mode_buf[3] = 0; /* Device-specific param, bit 8: 0/1 = write enabled/protected */ - mode_buf[4] = 0; /* reserved */ - mode_buf[5] = 0; /* reserved */ - mode_buf[6] = 0; /* Block descriptor length (MSB) */ - mode_buf[7] = 0; /* Block descriptor length (LSB) */ + return 0; + } - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; - __aac_io_done(scsicmd); + case SS_MODESEN: + { + char *mode_buf; - return 0; - } - case SS_REQSEN: - dprintk((KERN_DEBUG "REQUEST SENSE command.\n")); - memcpy(scsicmd->sense_buffer, &sense_data[cid], sizeof (struct sense_data)); - memset(&sense_data[cid], 0, sizeof (struct sense_data)); - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; - __aac_io_done(scsicmd); - return (0); + dprintk((KERN_DEBUG "MODE SENSE command.\n")); + mode_buf = scsicmd->request_buffer; + mode_buf[0] = 0; /* Mode data length (MSB) */ + mode_buf[1] = 6; /* Mode data length (LSB) */ + mode_buf[2] = 0; /* Medium type - default */ + mode_buf[3] = 0; /* Device-specific param, bit 8: 0/1 = write enabled/protected */ + mode_buf[4] = 0; /* reserved */ + mode_buf[5] = 0; /* reserved */ + mode_buf[6] = 0; /* Block descriptor length (MSB) */ + mode_buf[7] = 0; /* Block descriptor length (LSB) */ - case SS_LOCK: - dprintk((KERN_DEBUG "LOCK command.\n")); - if (scsicmd->cmnd[4]) - fsa_dev_ptr->locked[cid] = 1; - else - fsa_dev_ptr->locked[cid] = 0; + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; + __aac_io_done(scsicmd); - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; - __aac_io_done(scsicmd); - return 0; - /* - * These commands are all No-Ops - */ - case SS_TEST: - case SS_RESERV: - case SS_RELES: - case SS_REZERO: - case SS_REASGN: - case SS_SEEK: - case SS_ST_SP: - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; - __aac_io_done(scsicmd); - return (0); + return 0; + } + case SS_REQSEN: + dprintk((KERN_DEBUG "REQUEST SENSE command.\n")); + memcpy(scsicmd->sense_buffer, &sense_data[cid], sizeof (struct sense_data)); + memset(&sense_data[cid], 0, sizeof (struct sense_data)); + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; + __aac_io_done(scsicmd); + return (0); + + case SS_LOCK: + dprintk((KERN_DEBUG "LOCK command.\n")); + if (scsicmd->cmnd[4]) + fsa_dev_ptr->locked[cid] = 1; + else + fsa_dev_ptr->locked[cid] = 0; + + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; + __aac_io_done(scsicmd); + return 0; + /* + * These commands are all No-Ops + */ + case SS_TEST: + case SS_RESERV: + case SS_RELES: + case SS_REZERO: + case SS_REASGN: + case SS_SEEK: + case SS_ST_SP: + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; + __aac_io_done(scsicmd); + return (0); } switch (scsicmd->cmnd[0]) @@ -1020,7 +1074,7 @@ */ printk(KERN_WARNING "Unhandled SCSI Command: 0x%x.\n", scsicmd->cmnd[0]); scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION; - set_sense((char *) &sense_data[cid], + set_sense((u8 *) &sense_data[cid], SENKEY_ILLEGAL, SENCODE_INVALID_COMMAND, ASENCODE_INVALID_COMMAND, 0, 0, 0, 0); __aac_io_done(scsicmd); @@ -1153,3 +1207,452 @@ } } +/** + * + * aac_srb_callback + * @context: the context set in the fib - here it is scsi cmd + * @fibptr: pointer to the fib + * + * Handles the completion of a scsi command to a non dasd device + * + */ + +static void aac_srb_callback(void *context, struct fib * fibptr) +{ + struct aac_dev *dev; + struct aac_srb_reply *srbreply; + Scsi_Cmnd *scsicmd; + + scsicmd = (Scsi_Cmnd *) context; + dev = (struct aac_dev *)scsicmd->host->hostdata; + + if (fibptr == NULL) + BUG(); + + srbreply = (struct aac_srb_reply *) fib_data(fibptr); + + scsicmd->sense_buffer[0] = '\0'; // initialize sense valid flag to false + // calculate resid for sg + scsicmd->resid = scsicmd->request_bufflen - srbreply->data_xfer_length; + + if(scsicmd->use_sg) + pci_unmap_sg(dev->pdev, + (struct scatterlist *)scsicmd->buffer, + scsicmd->use_sg, + scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); + else if(scsicmd->request_bufflen) + pci_unmap_single(dev->pdev, (ulong)scsicmd->SCp.ptr, scsicmd->request_bufflen, + scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); + + /* + * First check the fib status + */ + + if (le32_to_cpu(srbreply->status) != ST_OK){ + int len; + printk(KERN_WARNING "aac_srb_callback: srb failed, status = %d\n", le32_to_cpu(srbreply->status)); + len = (srbreply->sense_data_size > sizeof(scsicmd->sense_buffer))? + sizeof(scsicmd->sense_buffer):srbreply->sense_data_size; + scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION; + memcpy(scsicmd->sense_buffer, srbreply->sense_data, len); + } + + /* + * Next check the srb status + */ + switch(le32_to_cpu(srbreply->srb_status)){ + case SRB_STATUS_ERROR_RECOVERY: + case SRB_STATUS_PENDING: + case SRB_STATUS_SUCCESS: + if(scsicmd->cmnd[0] == INQUIRY ){ + u8 b; + /* We can't expose disk devices because we can't tell whether they + * are the raw container drives or stand alone drives + */ + b = *(u8*)scsicmd->buffer; + if( (b & 0x0f) == TYPE_DISK ){ + scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8; + } + } else { + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; + } + break; + case SRB_STATUS_DATA_OVERRUN: + switch(scsicmd->cmnd[0]){ + case READ_6: + case WRITE_6: + case READ_10: + case WRITE_10: + case READ_12: + case WRITE_12: + if(le32_to_cpu(srbreply->data_xfer_length) < scsicmd->underflow ) { + printk(KERN_WARNING"aacraid: SCSI CMD underflow\n"); + } else { + printk(KERN_WARNING"aacraid: SCSI CMD Data Overrun\n"); + } + scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8; + break; + default: + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; + break; + } + break; + case SRB_STATUS_ABORTED: + scsicmd->result = DID_ABORT << 16 | ABORT << 8; + break; + case SRB_STATUS_ABORT_FAILED: + // Not sure about this one - but assuming the hba was trying to abort for some reason + scsicmd->result = DID_ERROR << 16 | ABORT << 8; + break; + case SRB_STATUS_PARITY_ERROR: + scsicmd->result = DID_PARITY << 16 | MSG_PARITY_ERROR << 8; + break; + case SRB_STATUS_NO_DEVICE: + case SRB_STATUS_INVALID_PATH_ID: + case SRB_STATUS_INVALID_TARGET_ID: + case SRB_STATUS_INVALID_LUN: + case SRB_STATUS_SELECTION_TIMEOUT: + scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8; + break; + + case SRB_STATUS_COMMAND_TIMEOUT: + case SRB_STATUS_TIMEOUT: + scsicmd->result = DID_TIME_OUT << 16 | COMMAND_COMPLETE << 8; + break; + + case SRB_STATUS_BUSY: + scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8; + break; + + case SRB_STATUS_BUS_RESET: + scsicmd->result = DID_RESET << 16 | COMMAND_COMPLETE << 8; + break; + + case SRB_STATUS_MESSAGE_REJECTED: + scsicmd->result = DID_ERROR << 16 | MESSAGE_REJECT << 8; + break; + case SRB_STATUS_REQUEST_FLUSHED: + case SRB_STATUS_ERROR: + case SRB_STATUS_INVALID_REQUEST: + case SRB_STATUS_REQUEST_SENSE_FAILED: + case SRB_STATUS_NO_HBA: + case SRB_STATUS_UNEXPECTED_BUS_FREE: + case SRB_STATUS_PHASE_SEQUENCE_FAILURE: + case SRB_STATUS_BAD_SRB_BLOCK_LENGTH: + case SRB_STATUS_DELAYED_RETRY: + case SRB_STATUS_BAD_FUNCTION: + case SRB_STATUS_NOT_STARTED: + case SRB_STATUS_NOT_IN_USE: + case SRB_STATUS_FORCE_ABORT: + case SRB_STATUS_DOMAIN_VALIDATION_FAIL: + default: +#ifdef AAC_DETAILED_STATUS_INFO + printk("aacraid: SRB ERROR (%s)\n",aac_get_status_string(le32_to_cpu(srbreply->srb_status))); +#endif + scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8; + break; + } + if (le32_to_cpu(srbreply->scsi_status) == 0x02 ){ // Check Condition + int len; + len = (srbreply->sense_data_size > sizeof(scsicmd->sense_buffer))? + sizeof(scsicmd->sense_buffer):srbreply->sense_data_size; + printk(KERN_WARNING "aac_srb_callback: check condition, status = %d len=%d\n", le32_to_cpu(srbreply->status), len); + memcpy(scsicmd->sense_buffer, srbreply->sense_data, len); + } + /* + * OR in the scsi status (already shifted up a bit) + */ + scsicmd->result |= le32_to_cpu(srbreply->scsi_status); + + fib_complete(fibptr); + fib_free(fibptr); + aac_io_done(scsicmd); +} + +/** + * + * aac_send_scb_fib + * @scsicmd: the scsi command block + * + * This routine will form a FIB and fill in the aac_srb from the + * scsicmd passed in. + */ + +static int aac_send_srb_fib(Scsi_Cmnd* scsicmd) +{ + struct fib* cmd_fibcontext; + struct aac_dev* dev; + int status; + struct aac_srb *srbcmd; + u16 fibsize; + u32 flag; + + if( scsicmd->target > 15 || scsicmd->lun > 7) { + scsicmd->result = DID_NO_CONNECT << 16; + __aac_io_done(scsicmd); + return 0; + } + + dev = (struct aac_dev *)scsicmd->host->hostdata; + switch(scsicmd->sc_data_direction){ + case SCSI_DATA_WRITE: + flag = SRB_DataOut; + break; + case SCSI_DATA_UNKNOWN: + flag = SRB_DataIn | SRB_DataOut; + break; + case SCSI_DATA_READ: + flag = SRB_DataIn; + break; + case SCSI_DATA_NONE: + default: + flag = SRB_NoDataXfer; + break; + } + + + /* + * Allocate and initialize a Fib then setup a BlockWrite command + */ + if (!(cmd_fibcontext = fib_alloc(dev))) { + scsicmd->result = DID_ERROR << 16; + __aac_io_done(scsicmd); + return -1; + } + fib_init(cmd_fibcontext); + + srbcmd = (struct aac_srb*) fib_data(cmd_fibcontext); + srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi); + srbcmd->channel = cpu_to_le32(aac_logical_to_phys(scsicmd->channel)); + srbcmd->target = cpu_to_le32(scsicmd->target); + srbcmd->lun = cpu_to_le32(scsicmd->lun); + srbcmd->flags = cpu_to_le32(flag); + srbcmd->timeout = cpu_to_le32(0); // timeout not used + srbcmd->retry_limit =cpu_to_le32(0); // Obsolete parameter + srbcmd->cdb_size = cpu_to_le32(scsicmd->cmd_len); + + if( dev->pae_support ==1 ) { + aac_build_sg64(scsicmd, (struct sgmap64*) &srbcmd->sg); + srbcmd->count = cpu_to_le32(scsicmd->request_bufflen); + + memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb)); + memcpy(srbcmd->cdb, scsicmd->cmnd, scsicmd->cmd_len); + /* + * Build Scatter/Gather list + */ + fibsize = sizeof (struct aac_srb) + (((srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry64)); + + /* + * Now send the Fib to the adapter + */ + status = fib_send(ScsiPortCommand64, cmd_fibcontext, fibsize, FsaNormal, 0, 1, + (fib_callback) aac_srb_callback, (void *) scsicmd); + } else { + aac_build_sg(scsicmd, (struct sgmap*)&srbcmd->sg); + srbcmd->count = cpu_to_le32(scsicmd->request_bufflen); + + memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb)); + memcpy(srbcmd->cdb, scsicmd->cmnd, scsicmd->cmd_len); + /* + * Build Scatter/Gather list + */ + fibsize = sizeof (struct aac_srb) + (((srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry)); + + /* + * Now send the Fib to the adapter + */ + status = fib_send(ScsiPortCommand, cmd_fibcontext, fibsize, FsaNormal, 0, 1, + (fib_callback) aac_srb_callback, (void *) scsicmd); + } + /* + * Check that the command queued to the controller + */ + if (status == -EINPROGRESS){ + return 0; + } + + printk(KERN_WARNING "aac_srb: fib_send failed with status: %d\n", status); + /* + * For some reason, the Fib didn't queue, return QUEUE_FULL + */ + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | QUEUE_FULL; + __aac_io_done(scsicmd); + + fib_complete(cmd_fibcontext); + fib_free(cmd_fibcontext); + + return -1; +} + +static unsigned long aac_build_sg(Scsi_Cmnd* scsicmd, struct sgmap* psg) +{ + struct aac_dev *dev; + unsigned long byte_count = 0; + + dev = (struct aac_dev *)scsicmd->host->hostdata; + // Get rid of old data + psg->count = cpu_to_le32(0); + psg->sg[0].addr = cpu_to_le32(NULL); + psg->sg[0].count = cpu_to_le32(0); + if (scsicmd->use_sg) { + struct scatterlist *sg; + int i; + int sg_count; + sg = (struct scatterlist *) scsicmd->request_buffer; + + sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg, + scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); + psg->count = cpu_to_le32(sg_count); + + byte_count = 0; + + for (i = 0; i < sg_count; i++) { + psg->sg[i].addr = cpu_to_le32(sg_dma_address(sg)); + psg->sg[i].count = cpu_to_le32(sg_dma_len(sg)); + byte_count += sg_dma_len(sg); + sg++; + } + /* hba wants the size to be exact */ + if(byte_count > scsicmd->request_bufflen){ + psg->sg[i-1].count -= (byte_count - scsicmd->request_bufflen); + byte_count = scsicmd->request_bufflen; + } + /* Check for command underflow */ + if(scsicmd->underflow && (byte_count < scsicmd->underflow)){ + printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n", + byte_count, scsicmd->underflow); + } + } + else if(scsicmd->request_bufflen) { + dma_addr_t addr; + addr = pci_map_single(dev->pdev, + scsicmd->request_buffer, + scsicmd->request_bufflen, + scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); + psg->count = cpu_to_le32(1); + psg->sg[0].addr = cpu_to_le32(addr); + psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen); + scsicmd->SCp.ptr = (void *)addr; + byte_count = scsicmd->request_bufflen; + } + return byte_count; +} + + +static unsigned long aac_build_sg64(Scsi_Cmnd* scsicmd, struct sgmap64* psg) +{ + struct aac_dev *dev; + unsigned long byte_count = 0; + u64 le_addr; + + dev = (struct aac_dev *)scsicmd->host->hostdata; + // Get rid of old data + psg->count = cpu_to_le32(0); + psg->sg[0].addr[0] = cpu_to_le32(NULL); + psg->sg[0].addr[1] = cpu_to_le32(NULL); + psg->sg[0].count = cpu_to_le32(0); + if (scsicmd->use_sg) { + struct scatterlist *sg; + int i; + int sg_count; + sg = (struct scatterlist *) scsicmd->request_buffer; + + sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg, + scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); + psg->count = cpu_to_le32(sg_count); + + byte_count = 0; + + for (i = 0; i < sg_count; i++) { + le_addr = cpu_to_le64(sg_dma_address(sg)); + psg->sg[i].addr[1] = (u32)(le_addr>>32); + psg->sg[i].addr[0] = (u32)(le_addr & 0xffffffff); + psg->sg[i].count = cpu_to_le32(sg_dma_len(sg)); + byte_count += sg_dma_len(sg); + sg++; + } + /* hba wants the size to be exact */ + if(byte_count > scsicmd->request_bufflen){ + psg->sg[i-1].count -= (byte_count - scsicmd->request_bufflen); + byte_count = scsicmd->request_bufflen; + } + /* Check for command underflow */ + if(scsicmd->underflow && (byte_count < scsicmd->underflow)){ + printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n", + byte_count, scsicmd->underflow); + } + } + else if(scsicmd->request_bufflen) { + dma_addr_t addr; + addr = pci_map_single(dev->pdev, + scsicmd->request_buffer, + scsicmd->request_bufflen, + scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); + psg->count = cpu_to_le32(1); + le_addr = cpu_to_le64(addr); + psg->sg[0].addr[1] = (u32)(le_addr>>32); + psg->sg[0].addr[0] = (u32)(le_addr & 0xffffffff); + psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen); + scsicmd->SCp.ptr = (void *)addr; + byte_count = scsicmd->request_bufflen; + } + return byte_count; +} + +#ifdef AAC_DETAILED_STATUS_INFO + +struct aac_srb_status_info { + u32 status; + char *str; +}; + + +static struct aac_srb_status_info srb_status_info[] = { + { SRB_STATUS_PENDING, "Pending Status"}, + { SRB_STATUS_SUCCESS, "Success"}, + { SRB_STATUS_ABORTED, "Aborted Command"}, + { SRB_STATUS_ABORT_FAILED, "Abort Failed"}, + { SRB_STATUS_ERROR, "Error Event"}, + { SRB_STATUS_BUSY, "Device Busy"}, + { SRB_STATUS_INVALID_REQUEST, "Invalid Request"}, + { SRB_STATUS_INVALID_PATH_ID, "Invalid Path ID"}, + { SRB_STATUS_NO_DEVICE, "No Device"}, + { SRB_STATUS_TIMEOUT, "Timeout"}, + { SRB_STATUS_SELECTION_TIMEOUT, "Selection Timeout"}, + { SRB_STATUS_COMMAND_TIMEOUT, "Command Timeout"}, + { SRB_STATUS_MESSAGE_REJECTED, "Message Rejected"}, + { SRB_STATUS_BUS_RESET, "Bus Reset"}, + { SRB_STATUS_PARITY_ERROR, "Parity Error"}, + { SRB_STATUS_REQUEST_SENSE_FAILED,"Request Sense Failed"}, + { SRB_STATUS_NO_HBA, "No HBA"}, + { SRB_STATUS_DATA_OVERRUN, "Data Overrun/Data Underrun"}, + { SRB_STATUS_UNEXPECTED_BUS_FREE,"Unexpected Bus Free"}, + { SRB_STATUS_PHASE_SEQUENCE_FAILURE,"Phase Error"}, + { SRB_STATUS_BAD_SRB_BLOCK_LENGTH,"Bad Srb Block Length"}, + { SRB_STATUS_REQUEST_FLUSHED, "Request Flushed"}, + { SRB_STATUS_DELAYED_RETRY, "Delayed Retry"}, + { SRB_STATUS_INVALID_LUN, "Invalid LUN"}, + { SRB_STATUS_INVALID_TARGET_ID, "Invalid TARGET ID"}, + { SRB_STATUS_BAD_FUNCTION, "Bad Function"}, + { SRB_STATUS_ERROR_RECOVERY, "Error Recovery"}, + { SRB_STATUS_NOT_STARTED, "Not Started"}, + { SRB_STATUS_NOT_IN_USE, "Not In Use"}, + { SRB_STATUS_FORCE_ABORT, "Force Abort"}, + { SRB_STATUS_DOMAIN_VALIDATION_FAIL,"Domain Validation Failure"}, + { 0xff, "Unknown Error"} +}; + +char *aac_get_status_string(u32 status) +{ + int i; + + for(i=0; i < (sizeof(srb_status_info)/sizeof(struct aac_srb_status_info)); i++ ){ + if(srb_status_info[i].status == status){ + return srb_status_info[i].str; + } + } + + return "Bad Status Code"; +} + +#endif diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/aacraid/aacraid.h linux.19rc3-ac4/drivers/scsi/aacraid/aacraid.h --- linux.19rc3/drivers/scsi/aacraid/aacraid.h 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/aacraid/aacraid.h 2002-07-29 13:58:43.000000000 +0100 @@ -1,12 +1,29 @@ #define dprintk(x) - -#define AAC_NUM_FIB 128 -#define AAC_NUM_IO_FIB 116 +/*#define dprintk(x) printk x */ /*------------------------------------------------------------------------------ * D E F I N E S *----------------------------------------------------------------------------*/ +#define MAXIMUM_NUM_CONTAINERS 31 +#define MAXIMUM_NUM_ADAPTERS 8 + +#define AAC_NUM_FIB 578 +#define AAC_NUM_IO_FIB 512 + +#define AAC_MAX_TARGET (MAXIMUM_NUM_CONTAINERS+1) +//#define AAC_MAX_TARGET (16) +#define AAC_MAX_LUN (8) + +/* + * These macros convert from physical channels to virtual channels + */ +#define CONTAINER_CHANNEL (0) +#define aac_phys_to_logical(x) (x+1) +#define aac_logical_to_phys(x) (x?x-1:0) + +#define AAC_DETAILED_STATUS_INFO + struct diskparm { int heads; @@ -62,10 +79,16 @@ /* * Host side memory scatter gather list * Used by the adapter for read, write, and readdirplus operations + * We have seperate 32 and 64 bit version because even + * on 64 bit systems not all cards support the 64 bit version */ - struct sgentry { - u32 addr; /* 32-bit Base address. */ + u32 addr; /* 32-bit address. */ + u32 count; /* Length. */ +}; + +struct sgentry64 { + u32 addr[2]; /* 64-bit addr. 2 pieces for data alignment */ u32 count; /* Length. */ }; @@ -74,15 +97,16 @@ * * This is the SGMAP structure for all commands that use * 32-bit addressing. - * - * Note that the upper 16 bits of SgCount are used as flags. - * Only the lower 16 bits of SgCount are actually used as the - * SG element count. */ struct sgmap { u32 count; - struct sgentry sg[1]; + struct sgentry sg[1]; +}; + +struct sgmap64 { + u32 count; + struct sgentry64 sg[1]; }; struct creation_info @@ -100,7 +124,7 @@ * unsigned Minute :6; // 0 - 60 * unsigned Second :6; // 0 - 60 */ - u64 serial; /* e.g., 0x1DEADB0BFAFAF001 */ + u32 serial[2]; /* e.g., 0x1DEADB0BFAFAF001 */ }; @@ -145,8 +169,8 @@ */ struct aac_entry { - u32 size; /* Size in bytes of the Fib which this QE points to */ - u32 addr; /* Receiver addressable address of the FIB (low 32 address bits) */ + u32 size; /* Size in bytes of Fib which this QE points to */ + u32 addr; /* Receiver address of the FIB */ }; /* @@ -225,10 +249,10 @@ #define FsaNormal 1 #define FsaHigh 2 -// -// Define the FIB. The FIB is the where all the requested data and -// command information are put to the application on the FSA adapter. -// +/* + * Define the FIB. The FIB is the where all the requested data and + * command information are put to the application on the FSA adapter. + */ struct aac_fibhdr { u32 XferState; // Current transfer state for this CCB @@ -308,6 +332,7 @@ * Scsi Port commands (scsi passthrough) */ #define ScsiPortCommand 600 +#define ScsiPortCommand64 601 /* * Misc house keeping and generic adapter initiated commands */ @@ -395,6 +420,7 @@ void (*adapter_notify)(struct aac_dev *dev, u32 event); void (*adapter_enable_int)(struct aac_dev *dev, u32 event); void (*adapter_disable_int)(struct aac_dev *dev, u32 event); + int (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 *status); }; /* @@ -411,6 +437,7 @@ char * name; char * vname; char * model; + u16 channels; }; /* @@ -459,29 +486,29 @@ struct sa_drawbridge_CSR { // Offset | Name u32 reserved[10]; // 00h-27h | Reserved - u8 LUT_Offset; // 28h | Looup Table Offset + u8 LUT_Offset; // 28h | Looup Table Offset u8 reserved1[3]; // 29h-2bh | Reserved - u32 LUT_Data; // 2ch | Looup Table Data + u32 LUT_Data; // 2ch | Looup Table Data u32 reserved2[26]; // 30h-97h | Reserved - u16 PRICLEARIRQ; // 98h | Primary Clear Irq - u16 SECCLEARIRQ; // 9ah | Secondary Clear Irq - u16 PRISETIRQ; // 9ch | Primary Set Irq - u16 SECSETIRQ; // 9eh | Secondary Set Irq - u16 PRICLEARIRQMASK; // a0h | Primary Clear Irq Mask - u16 SECCLEARIRQMASK; // a2h | Secondary Clear Irq Mask - u16 PRISETIRQMASK; // a4h | Primary Set Irq Mask - u16 SECSETIRQMASK; // a6h | Secondary Set Irq Mask - u32 MAILBOX0; // a8h | Scratchpad 0 - u32 MAILBOX1; // ach | Scratchpad 1 - u32 MAILBOX2; // b0h | Scratchpad 2 - u32 MAILBOX3; // b4h | Scratchpad 3 - u32 MAILBOX4; // b8h | Scratchpad 4 - u32 MAILBOX5; // bch | Scratchpad 5 - u32 MAILBOX6; // c0h | Scratchpad 6 - u32 MAILBOX7; // c4h | Scratchpad 7 + u16 PRICLEARIRQ; // 98h | Primary Clear Irq + u16 SECCLEARIRQ; // 9ah | Secondary Clear Irq + u16 PRISETIRQ; // 9ch | Primary Set Irq + u16 SECSETIRQ; // 9eh | Secondary Set Irq + u16 PRICLEARIRQMASK; // a0h | Primary Clear Irq Mask + u16 SECCLEARIRQMASK; // a2h | Secondary Clear Irq Mask + u16 PRISETIRQMASK; // a4h | Primary Set Irq Mask + u16 SECSETIRQMASK; // a6h | Secondary Set Irq Mask + u32 MAILBOX0; // a8h | Scratchpad 0 + u32 MAILBOX1; // ach | Scratchpad 1 + u32 MAILBOX2; // b0h | Scratchpad 2 + u32 MAILBOX3; // b4h | Scratchpad 3 + u32 MAILBOX4; // b8h | Scratchpad 4 + u32 MAILBOX5; // bch | Scratchpad 5 + u32 MAILBOX6; // c0h | Scratchpad 6 + u32 MAILBOX7; // c4h | Scratchpad 7 - u32 ROM_Setup_Data; // c8h | Rom Setup and Data - u32 ROM_Control_Addr; // cch | Rom Control and Address + u32 ROM_Setup_Data; // c8h | Rom Setup and Data + u32 ROM_Control_Addr; // cch | Rom Control and Address u32 reserved3[12]; // d0h-ffh | reserved u32 LUT[64]; // 100h-1ffh| Lookup Table Entries @@ -597,7 +624,7 @@ struct aac_fib_context { s16 type; // used for verification of structure s16 size; - u32 jiffies; // used for cleanup + ulong jiffies; // used for cleanup - dmb changed to ulong struct list_head next; // used to link context's into a linked list struct semaphore wait_sem; // this is used to wait for the next fib to arrive. int wait; // Set to true when thread is in WaitForSingleObject @@ -605,17 +632,14 @@ struct list_head fibs; }; -#define MAXIMUM_NUM_CONTAINERS 64 // 4 Luns * 16 Targets -#define MAXIMUM_NUM_ADAPTERS 8 - struct fsa_scsi_hba { - unsigned long size[MAXIMUM_NUM_CONTAINERS]; - unsigned long type[MAXIMUM_NUM_CONTAINERS]; - unsigned char valid[MAXIMUM_NUM_CONTAINERS]; - unsigned char ro[MAXIMUM_NUM_CONTAINERS]; - unsigned char locked[MAXIMUM_NUM_CONTAINERS]; - unsigned char deleted[MAXIMUM_NUM_CONTAINERS]; - long devno[MAXIMUM_NUM_CONTAINERS]; + u32 size[MAXIMUM_NUM_CONTAINERS]; + u32 type[MAXIMUM_NUM_CONTAINERS]; + u8 valid[MAXIMUM_NUM_CONTAINERS]; + u8 ro[MAXIMUM_NUM_CONTAINERS]; + u8 locked[MAXIMUM_NUM_CONTAINERS]; + u8 deleted[MAXIMUM_NUM_CONTAINERS]; + u32 devno[MAXIMUM_NUM_CONTAINERS]; }; struct fib { @@ -634,10 +658,10 @@ struct semaphore event_wait; spinlock_t event_lock; - unsigned long done; /* gets set to 1 when fib is complete */ + u32 done; /* gets set to 1 when fib is complete */ fib_callback callback; void *callback_data; - unsigned long flags; + u32 flags; // u32 dmb was ulong /* * The following is used to put this fib context onto the * Outstanding I/O queue. @@ -648,6 +672,68 @@ struct hw_fib *fib; /* Actual shared object */ }; +/* + * Adapter Information Block + * + * This is returned by the RequestAdapterInfo block + */ + +struct aac_adapter_info +{ + u32 platform; + u32 cpu; + u32 subcpu; + u32 clock; + u32 execmem; + u32 buffermem; + u32 totalmem; + u32 kernelrev; + u32 kernelbuild; + u32 monitorrev; + u32 monitorbuild; + u32 hwrev; + u32 hwbuild; + u32 biosrev; + u32 biosbuild; + u32 cluster; + u32 serial[2]; + u32 battery; + u32 options; + u32 OEM; +}; + +/* + * Battery platforms + */ +#define AAC_BAT_REQ_PRESENT (1) +#define AAC_BAT_REQ_NOTPRESENT (2) +#define AAC_BAT_OPT_PRESENT (3) +#define AAC_BAT_OPT_NOTPRESENT (4) +#define AAC_BAT_NOT_SUPPORTED (5) +/* + * cpu types + */ +#define AAC_CPU_SIMULATOR (1) +#define AAC_CPU_I960 (2) +#define AAC_CPU_STRONGARM (3) + +/* + * Supported Options + */ +#define AAC_OPT_SNAPSHOT cpu_to_le32(1) +#define AAC_OPT_CLUSTERS cpu_to_le32(1<<1) +#define AAC_OPT_WRITE_CACHE cpu_to_le32(1<<2) +#define AAC_OPT_64BIT_DATA cpu_to_le32(1<<3) +#define AAC_OPT_HOST_TIME_FIB cpu_to_le32(1<<4) +#define AAC_OPT_RAID50 cpu_to_le32(1<<5) +#define AAC_OPT_4GB_WINDOW cpu_to_le32(1<<6) +#define AAC_OPT_SCSI_UPGRADEABLE cpu_to_le32(1<<7) +#define AAC_OPT_SOFT_ERR_REPORT cpu_to_le32(1<<8) +#define AAC_OPT_SUPPORTED_RECONDITION cpu_to_le32(1<<9) +#define AAC_OPT_SGMAP_HOST64 cpu_to_le32(1<<10) +#define AAC_OPT_ALARM cpu_to_le32(1<<11) +#define AAC_OPT_NONDASD cpu_to_le32(1<<12) + struct aac_dev { struct aac_dev *next; @@ -660,6 +746,9 @@ */ dma_addr_t hw_fib_pa; struct hw_fib *hw_fib_va; +#if BITS_PER_LONG >= 64 + ulong fib_base_va; +#endif /* * Fib Headers */ @@ -706,9 +795,15 @@ /* * The following is the number of the individual adapter */ - long devnum; - int aif_thread; + u32 devnum; + u32 aif_thread; struct completion aif_completion; + struct aac_adapter_info adapter_info; + /* These are in adapter info but they are in the io flow so + * lets break them out so we don't have to do an AND to check them + */ + u8 nondasd_support; + u8 pae_support; }; #define AllocateAndMapFibSpace(dev, MapFibContext) \ @@ -846,6 +941,17 @@ struct sgmap sg; // Must be last in struct because it is variable }; +struct aac_read64 +{ + u32 command; + u16 cid; + u16 sector_count; + u32 block; + u16 pad; + u16 flags; + struct sgmap64 sg; // Must be last in struct because it is variable +}; + struct aac_read_reply { u32 status; @@ -858,10 +964,20 @@ u32 cid; u32 block; u32 count; - u32 stable; + u32 stable; // Not used struct sgmap sg; // Must be last in struct because it is variable }; +struct aac_write64 +{ + u32 command; + u16 cid; + u16 sector_count; + u32 block; + u16 pad; + u16 flags; + struct sgmap64 sg; // Must be last in struct because it is variable +}; struct aac_write_reply { u32 status; @@ -869,6 +985,100 @@ u32 committed; }; +struct aac_srb +{ + u32 function; + u32 channel; + u32 target; + u32 lun; + u32 timeout; + u32 flags; + u32 count; // Data xfer size + u32 retry_limit; + u32 cdb_size; + u8 cdb[16]; + struct sgmap sg; +}; + + + +#define AAC_SENSE_BUFFERSIZE 30 + +struct aac_srb_reply +{ + u32 status; + u32 srb_status; + u32 scsi_status; + u32 data_xfer_length; + u32 sense_data_size; + u8 sense_data[AAC_SENSE_BUFFERSIZE]; // Can this be SCSI_SENSE_BUFFERSIZE +}; +/* + * SRB Flags + */ +#define SRB_NoDataXfer 0x0000 +#define SRB_DisableDisconnect 0x0004 +#define SRB_DisableSynchTransfer 0x0008 +#define SRB_BypassFrozenQueue 0x0010 +#define SRB_DisableAutosense 0x0020 +#define SRB_DataIn 0x0040 +#define SRB_DataOut 0x0080 + +/* + * SRB Functions - set in aac_srb->function + */ +#define SRBF_ExecuteScsi 0x0000 +#define SRBF_ClaimDevice 0x0001 +#define SRBF_IO_Control 0x0002 +#define SRBF_ReceiveEvent 0x0003 +#define SRBF_ReleaseQueue 0x0004 +#define SRBF_AttachDevice 0x0005 +#define SRBF_ReleaseDevice 0x0006 +#define SRBF_Shutdown 0x0007 +#define SRBF_Flush 0x0008 +#define SRBF_AbortCommand 0x0010 +#define SRBF_ReleaseRecovery 0x0011 +#define SRBF_ResetBus 0x0012 +#define SRBF_ResetDevice 0x0013 +#define SRBF_TerminateIO 0x0014 +#define SRBF_FlushQueue 0x0015 +#define SRBF_RemoveDevice 0x0016 +#define SRBF_DomainValidation 0x0017 + +/* + * SRB SCSI Status - set in aac_srb->scsi_status + */ +#define SRB_STATUS_PENDING 0x00 +#define SRB_STATUS_SUCCESS 0x01 +#define SRB_STATUS_ABORTED 0x02 +#define SRB_STATUS_ABORT_FAILED 0x03 +#define SRB_STATUS_ERROR 0x04 +#define SRB_STATUS_BUSY 0x05 +#define SRB_STATUS_INVALID_REQUEST 0x06 +#define SRB_STATUS_INVALID_PATH_ID 0x07 +#define SRB_STATUS_NO_DEVICE 0x08 +#define SRB_STATUS_TIMEOUT 0x09 +#define SRB_STATUS_SELECTION_TIMEOUT 0x0A +#define SRB_STATUS_COMMAND_TIMEOUT 0x0B +#define SRB_STATUS_MESSAGE_REJECTED 0x0D +#define SRB_STATUS_BUS_RESET 0x0E +#define SRB_STATUS_PARITY_ERROR 0x0F +#define SRB_STATUS_REQUEST_SENSE_FAILED 0x10 +#define SRB_STATUS_NO_HBA 0x11 +#define SRB_STATUS_DATA_OVERRUN 0x12 +#define SRB_STATUS_UNEXPECTED_BUS_FREE 0x13 +#define SRB_STATUS_PHASE_SEQUENCE_FAILURE 0x14 +#define SRB_STATUS_BAD_SRB_BLOCK_LENGTH 0x15 +#define SRB_STATUS_REQUEST_FLUSHED 0x16 +#define SRB_STATUS_DELAYED_RETRY 0x17 +#define SRB_STATUS_INVALID_LUN 0x20 +#define SRB_STATUS_INVALID_TARGET_ID 0x21 +#define SRB_STATUS_BAD_FUNCTION 0x22 +#define SRB_STATUS_ERROR_RECOVERY 0x23 +#define SRB_STATUS_NOT_STARTED 0x24 +#define SRB_STATUS_NOT_IN_USE 0x30 +#define SRB_STATUS_FORCE_ABORT 0x31 +#define SRB_STATUS_DOMAIN_VALIDATION_FAIL 0x32 /* * Object-Server / Volume-Manager Dispatch Classes @@ -893,8 +1103,10 @@ #define VM_CtBlockRead64 16 #define VM_CtBlockWrite64 17 #define VM_CtBlockVerify64 18 +#define VM_CtHostRead64 19 +#define VM_CtHostWrite64 20 -#define MAX_VMCOMMAND_NUM 19 /* used for sizing stats array - leave last */ +#define MAX_VMCOMMAND_NUM 21 /* used for sizing stats array - leave last */ /* * Descriptive information (eg, vital stats) @@ -926,7 +1138,7 @@ struct aac_mntent { u32 oid; - char name[16]; // if applicable + u8 name[16]; // if applicable struct creation_info create_info; // if applicable u32 capacity; u32 vol; // substrate structure @@ -988,9 +1200,9 @@ struct revision { - int compat; - unsigned long version; - unsigned long build; + u32 compat; + u32 version; + u32 build; }; /* @@ -1014,36 +1226,39 @@ */ #define FSACTL_SENDFIB CTL_CODE(2050, METHOD_BUFFERED) +#define FSACTL_SEND_RAW_SRB CTL_CODE(2067, METHOD_BUFFERED) #define FSACTL_DELETE_DISK 0x163 #define FSACTL_QUERY_DISK 0x173 #define FSACTL_OPEN_GET_ADAPTER_FIB CTL_CODE(2100, METHOD_BUFFERED) #define FSACTL_GET_NEXT_ADAPTER_FIB CTL_CODE(2101, METHOD_BUFFERED) #define FSACTL_CLOSE_GET_ADAPTER_FIB CTL_CODE(2102, METHOD_BUFFERED) #define FSACTL_MINIPORT_REV_CHECK CTL_CODE(2107, METHOD_BUFFERED) +#define FSACTL_GET_PCI_INFO CTL_CODE(2119, METHOD_BUFFERED) #define FSACTL_FORCE_DELETE_DISK CTL_CODE(2120, METHOD_NEITHER) + struct aac_common { /* * If this value is set to 1 then interrupt moderation will occur * in the base commuication support. */ - unsigned long irq_mod; - int peak_fibs; - int zero_fibs; - unsigned long fib_timeouts; + u32 irq_mod; + u32 peak_fibs; + u32 zero_fibs; + u32 fib_timeouts; /* * Statistical counters in debug mode */ #ifdef DBG - unsigned long FibsSent; - unsigned long FibRecved; - unsigned long NoResponseSent; - unsigned long NoResponseRecved; - unsigned long AsyncSent; - unsigned long AsyncRecved; - unsigned long NormalSent; - unsigned long NormalRecved; + u32 FibsSent; + u32 FibRecved; + u32 NoResponseSent; + u32 NoResponseRecved; + u32 AsyncSent; + u32 AsyncRecved; + u32 NormalSent; + u32 NormalRecved; #endif }; @@ -1063,11 +1278,17 @@ /* * Adapter direct commands + * Monitor/Kernel API */ -#define BREAKPOINT_REQUEST 0x00000004 -#define INIT_STRUCT_BASE_ADDRESS 0x00000005 -#define SEND_SYNCHRONOUS_FIB 0x0000000c +#define BREAKPOINT_REQUEST cpu_to_le32(0x00000004) +#define INIT_STRUCT_BASE_ADDRESS cpu_to_le32(0x00000005) +#define READ_PERMANENT_PARAMETERS cpu_to_le32(0x0000000a) +#define WRITE_PERMANENT_PARAMETERS cpu_to_le32(0x0000000b) +#define HOST_CRASHING cpu_to_le32(0x0000000d) +#define SEND_SYNCHRONOUS_FIB cpu_to_le32(0x0000000c) +#define GET_ADAPTER_PROPERTIES cpu_to_le32(0x00000019) +#define RE_INIT_ADAPTER cpu_to_le32(0x000000ee) /* * Adapter Status Register @@ -1138,37 +1359,6 @@ u8 data[1]; /* Undefined length (from kernel viewpoint) */ }; -/* - * Adapter Information Block - * - * This is returned by the RequestAdapterInfo block - */ - -struct aac_adapter_info -{ - u32 platform; - u32 cpu; - u32 subcpu; - u32 clock; - u32 execmem; - u32 buffermem; - u32 totalmem; - u32 kernelrev; - u32 kernelbuild; - u32 monitorrev; - u32 monitorbuild; - u32 hwrev; - u32 hwbuild; - u32 biosrev; - u32 biosbuild; - u32 clustering; - u32 clustermask; - u64 serial; - u32 battery; - u32 options; - u32 OEM; -}; - static inline u32 fib2addr(struct hw_fib *hw) { return (u32)hw; @@ -1206,3 +1396,5 @@ int aac_command_thread(struct aac_dev * dev); int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context *fibctx); int fib_adapter_complete(struct fib * fibptr, unsigned short size); +struct aac_driver_ident* aac_get_driver_ident(int devtype); +int aac_get_adapter_info(struct aac_dev* dev); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/aacraid/commctrl.c linux.19rc3-ac4/drivers/scsi/aacraid/commctrl.c --- linux.19rc3/drivers/scsi/aacraid/commctrl.c 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/aacraid/commctrl.c 2002-07-29 13:58:43.000000000 +0100 @@ -364,8 +364,8 @@ struct revision response; response.compat = 1; - response.version = 0x03000400; - response.build = 0x5125; + response.version = dev->adapter_info.kernelrev; + response.build = dev->adapter_info.kernelbuild; if (copy_to_user(arg, &response, sizeof(response))) return -EFAULT; @@ -373,6 +373,25 @@ } +struct aac_pci_info { + u32 bus; + u32 slot; +}; + + +int aac_get_pci_info(struct aac_dev* dev, void* arg) +{ + struct aac_pci_info pci_info; + + pci_info.bus = dev->pdev->bus->number; + pci_info.slot = PCI_SLOT(dev->pdev->devfn); + + if(copy_to_user( arg, (void*)&pci_info, sizeof(struct aac_pci_info))) + return -EFAULT; + return 0; + } + + int aac_do_ioctl(struct aac_dev * dev, int cmd, void *arg) { int status; @@ -401,6 +420,9 @@ case FSACTL_CLOSE_GET_ADAPTER_FIB: status = close_getadapter_fib(dev, arg); break; + case FSACTL_GET_PCI_INFO: + status = aac_get_pci_info(dev,arg); + break; default: status = -ENOTTY; break; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/aacraid/comminit.c linux.19rc3-ac4/drivers/scsi/aacraid/comminit.c --- linux.19rc3/drivers/scsi/aacraid/comminit.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/aacraid/comminit.c 2002-07-29 13:58:43.000000000 +0100 @@ -38,6 +38,7 @@ #include #include #include +#include #include #include "scsi.h" #include "hosts.h" @@ -57,6 +58,7 @@ struct aac_init *init; dma_addr_t phys; + /* FIXME: Adaptec add 128 bytes to this value - WHY ?? */ size = fibsize + sizeof(struct aac_init) + commsize + commalign + printfbufsiz; base = pci_alloc_consistent(dev->pdev, size, &phys); @@ -72,6 +74,14 @@ dev->init = (struct aac_init *)(base + fibsize); dev->init_pa = phys + fibsize; + /* + * Cache the upper bits of the virtual mapping for 64bit boxes + * FIXME: this crap should be rewritten + */ +#if BITS_PER_LONG >= 64 + dev->fib_base_va = ((ulong)base & 0xffffffff00000000); +#endif + init = dev->init; init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION); @@ -82,7 +92,7 @@ * Adapter Fibs are the first thing allocated so that they * start page aligned */ - init->AdapterFibsVirtualAddress = cpu_to_le32((long)base); + init->AdapterFibsVirtualAddress = cpu_to_le32((u32)base); init->AdapterFibsPhysicalAddress = cpu_to_le32(phys); init->AdapterFibsSize = cpu_to_le32(fibsize); init->AdapterFibAlign = cpu_to_le32(sizeof(struct hw_fib)); @@ -238,7 +248,7 @@ queues = (struct aac_entry *)((unsigned char *)headers + hdrsize); - /* Adapter to Host normal priority Command queue */ + /* Adapter to Host normal proirity Command queue */ comm->queue[HostNormCmdQueue].base = queues; aac_queue_init(dev, &comm->queue[HostNormCmdQueue], headers, HOST_NORM_CMD_ENTRIES); queues += HOST_NORM_CMD_ENTRIES; @@ -319,7 +329,6 @@ return NULL; INIT_LIST_HEAD(&dev->fib_list); - spin_lock_init(&dev->fib_lock); init_completion(&dev->aif_completion); /* * Add this adapter in to our dev List. diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/aacraid/commsup.c linux.19rc3-ac4/drivers/scsi/aacraid/commsup.c --- linux.19rc3/drivers/scsi/aacraid/commsup.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/aacraid/commsup.c 2002-07-29 13:58:43.000000000 +0100 @@ -180,7 +180,7 @@ } else { if (fibptr->fib->header.XferState != 0) { printk(KERN_WARNING "fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n", - fibptr, fibptr->fib->header.XferState); + (void *)fibptr, fibptr->fib->header.XferState); } fibptr->next = fibptr->dev->free_fib; fibptr->dev->free_fib = fibptr; @@ -280,8 +280,7 @@ else BUG(); if (*index + 1 == le32_to_cpu(*(q->headers.consumer))) { /* Queue is full */ - printk(KERN_WARNING "Queue %d full, %ld outstanding.\n", - qid, q->numpending); + printk(KERN_WARNING "Queue %d full, %ld outstanding.\n", qid, q->numpending); return 0; } else { *entry = q->base + *index; @@ -336,7 +335,7 @@ * Setup queue entry with command, status and fib mapped */ entry->size = cpu_to_le32(le16_to_cpu(fib->header.Size)); - entry->addr = cpu_to_le32(fib->header.SenderFibAddress); /* Restore adapters pointer to the FIB */ + entry->addr = cpu_to_le32(fib->header.SenderFibAddress); /* Restore adapters pointer to the FIB */ fib->header.ReceiverFibAddress = fib->header.SenderFibAddress; /* Let the adapter now where to find its data */ map = 0; } @@ -682,7 +681,7 @@ } else { - printk(KERN_WARNING "fib_complete: Unknown xferstate detected.\n"); + printk(KERN_WARNING "fib_adapter_complete: Unknown xferstate detected.\n"); BUG(); } return 0; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/aacraid/dpcsup.c linux.19rc3-ac4/drivers/scsi/aacraid/dpcsup.c --- linux.19rc3/drivers/scsi/aacraid/dpcsup.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/aacraid/dpcsup.c 2002-07-29 13:58:43.000000000 +0100 @@ -59,8 +59,8 @@ { struct aac_dev * dev = q->dev; struct aac_entry *entry; - struct hw_fib * fib; - struct fib * fibctx; + struct hw_fib * hwfib; + struct fib * fib; int consumed = 0; unsigned long flags; @@ -77,22 +77,22 @@ int fast; fast = (int) (entry->addr & 0x01); - fib = addr2fib(entry->addr & ~0x01); + hwfib = addr2fib(entry->addr & ~0x01); aac_consumer_free(dev, q, HostNormRespQueue); - fibctx = &dev->fibs[fib->header.SenderData]; + fib = &dev->fibs[hwfib->header.SenderData]; /* - * Remove this fibctx from the Outstanding I/O queue. + * Remove this fib from the Outstanding I/O queue. * But only if it has not already been timed out. * * If the fib has been timed out already, then just * continue. The caller has already been notified that * the fib timed out. */ - if (!(fibctx->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) { - list_del(&fibctx->queue); + if (!(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) { + list_del(&fib->queue); dev->queues->queue[AdapNormCmdQueue].numpending--; } else { - printk(KERN_WARNING "aacraid: FIB timeout.\n"); + printk(KERN_WARNING "aacraid: FIB timeout (%x).\n", fib->flags); continue; } spin_unlock_irqrestore(q->lock, flags); @@ -101,35 +101,35 @@ /* * Doctor the fib */ - *(u32 *)fib->data = cpu_to_le32(ST_OK); - fib->header.XferState |= cpu_to_le32(AdapterProcessed); + *(u32 *)hwfib->data = cpu_to_le32(ST_OK); + hwfib->header.XferState |= cpu_to_le32(AdapterProcessed); } FIB_COUNTER_INCREMENT(aac_config.FibRecved); - if (fib->header.Command == cpu_to_le16(NuFileSystem)) + if (hwfib->header.Command == cpu_to_le16(NuFileSystem)) { - u32 *pstatus = (u32 *)fib->data; + u32 *pstatus = (u32 *)hwfib->data; if (*pstatus & cpu_to_le32(0xffff0000)) *pstatus = cpu_to_le32(ST_OK); } - if (fib->header.XferState & cpu_to_le32(NoResponseExpected | Async)) + if (hwfib->header.XferState & cpu_to_le32(NoResponseExpected | Async)) { - if (fib->header.XferState & cpu_to_le32(NoResponseExpected)) + if (hwfib->header.XferState & cpu_to_le32(NoResponseExpected)) FIB_COUNTER_INCREMENT(aac_config.NoResponseRecved); else FIB_COUNTER_INCREMENT(aac_config.AsyncRecved); /* - * NOTE: we cannot touch the fibctx after this + * NOTE: we cannot touch the fib after this * call, because it may have been deallocated. */ - fibctx->callback(fibctx->callback_data, fibctx); + fib->callback(fib->callback_data, fib); } else { unsigned long flagv; - spin_lock_irqsave(&fibctx->event_lock, flagv); - fibctx->done = 1; - up(&fibctx->event_wait); - spin_unlock_irqrestore(&fibctx->event_lock, flagv); + spin_lock_irqsave(&fib->event_lock, flagv); + fib->done = 1; + up(&fib->event_wait); + spin_unlock_irqrestore(&fib->event_lock, flagv); FIB_COUNTER_INCREMENT(aac_config.NormalRecved); } consumed++; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/aacraid/linit.c linux.19rc3-ac4/drivers/scsi/aacraid/linit.c --- linux.19rc3/drivers/scsi/aacraid/linit.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/aacraid/linit.c 2002-07-29 13:58:43.000000000 +0100 @@ -35,7 +35,7 @@ * */ -#define AAC_DRIVER_VERSION "0.9.9ac4-rel" +#define AAC_DRIVER_VERSION "0.9.9ac6-TEST" #define AAC_DRIVER_BUILD_DATE __DATE__ #include @@ -58,34 +58,47 @@ #define AAC_DRIVERNAME "aacraid" -MODULE_AUTHOR("Red Hat Inc and Adaptec OEM RAID Solutions"); -MODULE_DESCRIPTION("Supports Dell PERC2, 2/Si, 3/Si, 3/Di, and HP NetRAID-4M devices. http://domsch.com/linux/"); +MODULE_AUTHOR("Red Hat Inc and Adaptec"); +MODULE_DESCRIPTION("Supports Dell PERC2, 2/Si, 3/Si, 3/Di, Adaptec 2120S, 2200S, 5400S, and HP NetRAID-4M devices. http://domsch.com/linux/ or http://linux.adaptec.com"); MODULE_LICENSE("GPL"); +MODULE_PARM(nondasd, "i"); +MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices. 0=off, 1=on"); + +static int nondasd=-1; struct aac_dev *aac_devices[MAXIMUM_NUM_ADAPTERS]; static unsigned aac_count = 0; static int aac_cfg_major = -1; -static int single_command_done = 0; /* * Because of the way Linux names scsi devices, the order in this table has * become important. Check for on-board Raid first, add-in cards second. + * + * dmb - For now we add the number of channels to this structure. + * In the future we should add a fib that reports the number of channels + * for the card. At that time we can remove the channels from here */ - -/* FIXME static */struct aac_driver_ident aac_drivers[] = { - { 0x1028, 0x0001, 0x1028, 0x0001, aac_rx_init, "percraid", "DELL ", "PERCRAID " }, /* PERC 2/Si */ - { 0x1028, 0x0002, 0x1028, 0x0002, aac_rx_init, "percraid", "DELL ", "PERCRAID " }, /* PERC 3/Di */ - { 0x1028, 0x0003, 0x1028, 0x0003, aac_rx_init, "percraid", "DELL ", "PERCRAID " }, /* PERC 3/Si */ - { 0x1028, 0x0004, 0x1028, 0x00d0, aac_rx_init, "percraid", "DELL ", "PERCRAID " }, /* PERC 3/Si */ - { 0x1028, 0x0002, 0x1028, 0x00d1, aac_rx_init, "percraid", "DELL ", "PERCRAID " }, /* PERC 3/Di */ - { 0x1028, 0x0002, 0x1028, 0x00d9, aac_rx_init, "percraid", "DELL ", "PERCRAID " }, /* PERC 3/Di */ - { 0x1028, 0x000a, 0x1028, 0x0106, aac_rx_init, "percraid", "DELL ", "PERCRAID " }, /* PERC 3/Di */ - { 0x1028, 0x000a, 0x1028, 0x011b, aac_rx_init, "percraid", "DELL ", "PERCRAID " }, /* PERC 3/Di */ - { 0x1028, 0x000a, 0x1028, 0x0121, aac_rx_init, "percraid", "DELL ", "PERCRAID " }, /* PERC 3/Di */ - { 0x1011, 0x0046, 0x9005, 0x1364, aac_sa_init, "percraid", "DELL ", "PERCRAID " }, /* Dell PERC2 "Quad Channel" */ - { 0x1011, 0x0046, 0x9005, 0x0365, aac_sa_init, "aacraid", "ADAPTEC ", "Adaptec 5400S " }, /* Adaptec 5400S */ - { 0x1011, 0x0046, 0x103c, 0x10c2, aac_sa_init, "hpnraid", "HP ", "NetRAID-4M " } /* HP NetRAID-4M */ + +static struct aac_driver_ident aac_drivers[] = { + { 0x1028, 0x0001, 0x1028, 0x0001, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 2/Si */ + { 0x1028, 0x0002, 0x1028, 0x0002, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di */ + { 0x1028, 0x0003, 0x1028, 0x0003, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Si */ + { 0x1028, 0x0004, 0x1028, 0x00d0, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Si */ + { 0x1028, 0x0002, 0x1028, 0x00d1, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di */ + { 0x1028, 0x0002, 0x1028, 0x00d9, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di */ + { 0x1028, 0x000a, 0x1028, 0x0106, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di */ + { 0x1028, 0x000a, 0x1028, 0x011b, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di */ + { 0x1028, 0x000a, 0x1028, 0x0121, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di */ + { 0x9005, 0x0283, 0x9005, 0x0283, aac_rx_init, "aacraid", "ADAPTEC ", "catapult ", 2 }, /* catapult*/ + { 0x9005, 0x0284, 0x9005, 0x0284, aac_rx_init, "aacraid", "ADAPTEC ", "tomcat ", 2 }, /* tomcat*/ + { 0x9005, 0x0285, 0x9005, 0x0286, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2120S ", 1 }, /* Adaptec 2120S (Crusader)*/ + { 0x9005, 0x0285, 0x9005, 0x0285, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2 }, /* Adaptec 2200S (Vulcan)*/ + { 0x9005, 0x0285, 0x9005, 0x0287, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2 }, /* Adaptec 2200S (Vulcan-2m)*/ + { 0x1011, 0x0046, 0x9005, 0x0365, aac_sa_init, "aacraid", "ADAPTEC ", "Adaptec 5400S ", 4 }, /* Adaptec 5400S (Mustang)*/ + { 0x1011, 0x0046, 0x9005, 0x0364, aac_sa_init, "aacraid", "ADAPTEC ", "AAC-364 ", 4 }, /* Adaptec 5400S (Mustang)*/ + { 0x1011, 0x0046, 0x9005, 0x1364, aac_sa_init, "percraid", "DELL ", "PERCRAID ", 4 }, /* Dell PERC2 "Quad Channel" */ + { 0x1011, 0x0046, 0x103c, 0x10c2, aac_sa_init, "hpnraid", "HP ", "NetRAID-4M ", 4 } /* HP NetRAID-4M */ }; #define NUM_AACTYPES (sizeof(aac_drivers) / sizeof(struct aac_driver_ident)) @@ -105,12 +118,13 @@ static int aac_detect(Scsi_Host_Template *); static int aac_release(struct Scsi_Host *); static int aac_queuecommand(Scsi_Cmnd *, void (*CompletionRoutine)(Scsi_Cmnd *)); -static int aac_command(Scsi_Cmnd *); -static int aac_abortcommand(Scsi_Cmnd *scsi_cmnd_ptr); -static int aac_resetcommand(Scsi_Cmnd *, unsigned int); static int aac_biosparm(Scsi_Disk *, kdev_t, int *); static int aac_procinfo(char *, char **, off_t, int, int, int); static int aac_ioctl(Scsi_Device *, int, void *); +static int aac_eh_abort(Scsi_Cmnd * cmd); +static int aac_eh_device_reset(Scsi_Cmnd* cmd); +static int aac_eh_bus_reset(Scsi_Cmnd* cmd); +static int aac_eh_reset(Scsi_Cmnd* cmd); static void aac_queuedepth(struct Scsi_Host *, Scsi_Device *); @@ -160,8 +174,7 @@ aac_drivers[index].subsystem_device)); dev = NULL; - while((dev = pci_find_device(vendor_id, device_id, dev))) - { + while((dev = pci_find_device(vendor_id, device_id, dev))) { if (pci_enable_device(dev)) continue; pci_set_master(dev); @@ -237,13 +250,50 @@ printk(KERN_WARNING "aacraid: device initialization failed.\n"); scsi_unregister(host_ptr); aac_count--; + continue; } - else + dprintk((KERN_DEBUG "%s:%d device initialization successful.\n", name, host_ptr->unique_id)); + aac_get_adapter_info(aac); + if(nondasd != -1) { - dprintk((KERN_DEBUG "%s:%d device initialization successful.\n", name, host_ptr->unique_id)); - aac_get_containers(aac); - aac_devices[aac_count-1] = aac; + /* someone told us how to set this on the cmdline */ + aac->nondasd_support = (nondasd!=0); } + if(aac->nondasd_support != 0){ + printk(KERN_INFO "%s%d: Non-DASD support enabled\n", aac->name, aac->id); + } + dprintk((KERN_DEBUG "%s:%d options flag %04x.\n",name, host_ptr->unique_id,aac->adapter_info.options)); + if(aac->nondasd_support == 1) + { + /* + * max channel will be the physical channels plus 1 virtual channel + * all containers are on the virtual channel 0 + * physical channels are address by their actual physical number+1 + */ + host_ptr->max_channel = aac_drivers[index].channels+1; + } else { + host_ptr->max_channel = 1; + } + dprintk((KERN_DEBUG "Device has %d logical channels\n", host_ptr->max_channel)); + aac_get_containers(aac); + aac_devices[aac_count-1] = aac; + + /* + * dmb - we may need to move these 3 parms somewhere else once + * we get a fib that can report the actual numbers + */ + host_ptr->max_id = AAC_MAX_TARGET; + host_ptr->max_lun = AAC_MAX_LUN; + + /* + * If we are PAE capable then our future DMA mappings + * (for read/write commands) are 64bit clean and don't + * need bouncing. This assumes we do no other 32bit only + * allocations (eg fib table expands) after this point. + */ + + if(aac->pae_support) + pci_set_dma_mask(dev, 0xFFFFFFFFFFFFFFFFUL); } } @@ -305,11 +355,11 @@ * Queues a command for execution by the associated Host Adapter. */ -static int aac_queuecommand(Scsi_Cmnd *scsi_cmnd_ptr, void (*CompletionRoutine)(Scsi_Cmnd *)) +static int aac_queuecommand(Scsi_Cmnd *scsi_cmnd_ptr, void (*complete)(Scsi_Cmnd *)) { int ret; - scsi_cmnd_ptr->scsi_done = CompletionRoutine; + scsi_cmnd_ptr->scsi_done = complete; /* * aac_scsi_cmd() handles command processing, setting the * result code and calling completion routine. @@ -319,79 +369,6 @@ return ret; } - -/** - * aac_done - Callback function for a non-queued command. - * @scsi_cmnd_ptr: SCSI command block to wait for - * - * Sets single_command done to 1. This lets aac_command complete. - * This function is obsolete. - * - * Bugs: Doesn't actually work properly with multiple controllers - */ - -static void aac_done(Scsi_Cmnd * scsi_cmnd_ptr) -{ - single_command_done = 1; -} - -/** - * aac_command - synchronous SCSI command execution - * @scsi_cmnd_ptr: SCSI command to issue - * - * Accepts a single command for execution by the associated Host Adapter. - * Waits until it completes an then returns an int where: - * Byte 0 = SCSI status code - * Byte 1 = SCSI 1 byte message - * Byte 2 = host error return - * Byte 3 = mid level error return - */ - -static int aac_command(Scsi_Cmnd *scsi_cmnd_ptr ) -{ - scsi_cmnd_ptr->scsi_done = aac_done; - dprintk((KERN_DEBUG "aac_command.\n")); - - /* - * aac_scsi_cmd() handles command processing, setting the - * result code and calling completion routine. - */ - single_command_done = 0; - aac_scsi_cmd(scsi_cmnd_ptr); - while(!single_command_done) - rmb(); - return scsi_cmnd_ptr->result; -} - -/** - * aac_abortcommand - Abort command if possible. - * @scsi_cmnd_ptr: SCSI command block to abort - * - * Called when the midlayer wishes to abort a command. We don't support - * this facility, and our firmware looks after life for us. We just - * report the command as busy. - */ - -static int aac_abortcommand(Scsi_Cmnd *scsi_cmnd_ptr ) -{ - return SCSI_ABORT_BUSY; -} - -/** - * aac_resetcommand - Reset command handling - * @scsi_cmnd_ptr: SCSI command block causing the reset - * @reset_flags: Reset hints from the midlayer code - * - * Issue a reset of a SCSI command. We are ourselves not truely a SCSI - * controller and our firmware will do the work for us anyway. Thus this - * is a no-op. We just return SCSI_RESET_PUNT - */ - -static int aac_resetcommand(struct scsi_cmnd *scsi_cmnd_ptr, unsigned int reset_flags ) -{ - return SCSI_RESET_PUNT; -} - /** * aac_driverinfo - Returns the host adapter name * @host_ptr: Scsi host to report on @@ -406,6 +383,17 @@ } /** + * aac_get_driver_ident + * @devtype: index into lookup table + * + * Returns a pointer to the entry in the driver lookup table. + */ +struct aac_driver_ident* aac_get_driver_ident(int devtype) +{ + return &aac_drivers[devtype]; +} + +/** * aac_biosparm - return BIOS parameters for disk * @disk: SCSI disk object to process * @device: kdev_t of the disk in question @@ -558,13 +546,75 @@ } } -/*------------------------------------------------------------------------------ - aac_ioctl() - Handle SCSI ioctls - *----------------------------------------------------------------------------*/ +/** + * aac_eh_abort - Abort command if possible. + * @cmd: SCSI command block to abort + * + * Called when the midlayer wishes to abort a command. We don't support + * this facility, and our firmware looks after life for us. We just + * report this as failing + */ + +static int aac_eh_abort(Scsi_Cmnd *cmd) +{ + return FAILED; +} + +/** + * aac_eh_device_reset - Reset command handling + * @cmd: SCSI command block causing the reset + * + * Issue a reset of a SCSI device. We are ourselves not truely a SCSI + * controller and our firmware will do the work for us anyway. Thus this + * is a no-op. We just return FAILED. + */ + +static int aac_eh_device_reset(Scsi_Cmnd *cmd) +{ + return FAILED; +} + +/** + * aac_eh_bus_reset - Reset command handling + * @scsi_cmd: SCSI command block causing the reset + * + * Issue a reset of a SCSI bus. We are ourselves not truely a SCSI + * controller and our firmware will do the work for us anyway. Thus this + * is a no-op. We just return FAILED. + */ + +static int aac_eh_bus_reset(Scsi_Cmnd* cmd) +{ + return FAILED; +} + +/** + * aac_eh_hba_reset - Reset command handling + * @scsi_cmd: SCSI command block causing the reset + * + * Issue a reset of a SCSI host. If things get this bad then arguably we should + * go take a look at what the host adapter is doing and see if something really + * broke (as can occur at least on my Dell QC card if a drive keeps failing spinup) + */ + +static int aac_eh_reset(Scsi_Cmnd* cmd) +{ + printk(KERN_ERR "aacraid: Host adapter reset request. SCSI hang ?\n"); + return FAILED; +} + +/** + * aac_ioctl - Handle SCSI ioctls + * @scsi_dev_ptr: scsi device to operate upon + * @cmd: ioctl command to use issue + * @arg: ioctl data pointer + * + * Issue an ioctl on an aacraid device. Returns a standard unix error code or + * zero for success + */ + static int aac_ioctl(Scsi_Device * scsi_dev_ptr, int cmd, void * arg) -/*----------------------------------------------------------------------------*/ { struct aac_dev *dev; dprintk((KERN_DEBUG "aac_ioctl.\n")); @@ -640,17 +690,19 @@ release: aac_release, info: aac_driverinfo, ioctl: aac_ioctl, - command: aac_command, queuecommand: aac_queuecommand, - abort: aac_abortcommand, - reset: aac_resetcommand, bios_param: aac_biosparm, can_queue: AAC_NUM_IO_FIB, this_id: 16, sg_tablesize: 16, max_sectors: 128, - cmd_per_lun: 1, - eh_abort_handler: aac_abortcommand, + cmd_per_lun: AAC_NUM_IO_FIB, + eh_abort_handler: aac_eh_abort, + eh_device_reset_handler:aac_eh_device_reset, + eh_bus_reset_handler: aac_eh_bus_reset, + eh_host_reset_handler: aac_eh_reset, + use_new_eh_code: 1, + use_clustering: ENABLE_CLUSTERING, }; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/aacraid/Makefile linux.19rc3-ac4/drivers/scsi/aacraid/Makefile --- linux.19rc3/drivers/scsi/aacraid/Makefile 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/aacraid/Makefile 2002-07-29 13:58:43.000000000 +0100 @@ -5,6 +5,6 @@ obj-m := $(O_TARGET) obj-y := linit.o aachba.o commctrl.o comminit.o commsup.o \ - dpcsup.o rx.o sap1sup.o + dpcsup.o rx.o sa.o include $(TOPDIR)/Rules.make diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/aacraid/README linux.19rc3-ac4/drivers/scsi/aacraid/README --- linux.19rc3/drivers/scsi/aacraid/README 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/aacraid/README 2002-07-29 13:58:43.000000000 +0100 @@ -3,13 +3,11 @@ Introduction ------------------------- The aacraid driver adds support for Adaptec (http://www.adaptec.com) -OEM based RAID controllers. This is a major rewrite from the original +RAID controllers. This is a major rewrite from the original Adaptec supplied driver. It has signficantly cleaned up both the code and the running binary size (the module is less than half the size of the original). -This driver is experimental. - Supported Cards/Chipsets ------------------------- Dell Computer Corporation PERC 2 Quad Channel @@ -17,16 +15,18 @@ Dell Computer Corporation PERC 3/Si Dell Computer Corporation PERC 3/Di HP NetRAID-4M - -Probably Supported Devices -------------------------- - Any and All Adaptec branded AAC964/5400 series raid controllers. + ADAPTEC 2120S + ADAPTEC 2200S + ADAPTEC 5400S People ------------------------- Alan Cox Christoph Hellwig (small cleanups/fixes) Matt Domsch (revision ioctl, adapter messages) +Deanna Bonds (non-DASD support, PAE fibs and 64 bit, added new adaptec controllers + added new ioctls, changed scsi interface to use new error handler, + increased the number of fibs and outstanding commands to a container) Original Driver ------------------------- @@ -36,6 +36,7 @@ ------------------------- None currently. Also note this is very different to Brian's original driver so don't expect him to support it. +Adaptec does support this driver. Contact either tech support or deanna bonds. Original by Brian Boerner February 2001 Rewritten by Alan Cox, November 2001 diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/aacraid/rx.c linux.19rc3-ac4/drivers/scsi/aacraid/rx.c --- linux.19rc3/drivers/scsi/aacraid/rx.c 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/aacraid/rx.c 2002-07-29 13:58:43.000000000 +0100 @@ -50,7 +50,6 @@ struct aac_dev *dev = dev_id; unsigned long bellbits; u8 intstat, mask; - intstat = rx_readb(dev, MUnit.OISR); /* * Read mask and invert because drawbridge is reversed. @@ -62,28 +61,24 @@ if (intstat & mask) { bellbits = rx_readl(dev, OutboundDoorbellReg); - if (bellbits & DoorBellPrintfReady) - { + if (bellbits & DoorBellPrintfReady) { aac_printf(dev, le32_to_cpu(rx_readl (dev, IndexRegs.Mailbox[5]))); rx_writel(dev, MUnit.ODR,DoorBellPrintfReady); rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone); } - else if (bellbits & DoorBellAdapterNormCmdReady) - { + else if (bellbits & DoorBellAdapterNormCmdReady) { aac_command_normal(&dev->queues->queue[HostNormCmdQueue]); rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady); } - else if (bellbits & DoorBellAdapterNormRespReady) - { + else if (bellbits & DoorBellAdapterNormRespReady) { aac_response_normal(&dev->queues->queue[HostNormRespQueue]); rx_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady); } - else if (bellbits & DoorBellAdapterNormCmdNotFull) - { + else if (bellbits & DoorBellAdapterNormCmdNotFull) { rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); } - else if (bellbits & DoorBellAdapterNormRespNotFull) - { + else if (bellbits & DoorBellAdapterNormRespNotFull) { + rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull); } } @@ -160,7 +155,7 @@ * for its completion. */ -static int rx_sync_cmd(struct aac_dev *dev, unsigned long command, unsigned long p1, unsigned long *status) +static int rx_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status) { unsigned long start; int ok; @@ -251,7 +246,7 @@ static void aac_rx_interrupt_adapter(struct aac_dev *dev) { - unsigned long ret; + u32 ret; rx_sync_cmd(dev, BREAKPOINT_REQUEST, 0, &ret); } @@ -304,7 +299,7 @@ static void aac_rx_start_adapter(struct aac_dev *dev) { - unsigned long status; + u32 status; struct aac_init *init; init = dev->init; @@ -323,7 +318,8 @@ // rx_writeb(dev, MUnit.OIMR, ~(u8)OUTBOUND_DOORBELL_INTERRUPT_MASK); rx_writeb(dev, MUnit.OIMR, 0xfb); - rx_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (unsigned long) dev->init_pa, &status); + // We can only use a 32 bit address here + rx_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, &status); } /** @@ -344,7 +340,6 @@ const char * name; dev->devnum = num; - instance = dev->id; name = dev->name; @@ -372,11 +367,11 @@ } start = jiffies; /* - * Wait for the adapter to be up and running. Wait up to 30 seconds. + * Wait for the adapter to be up and running. Wait up to 3 minutes */ while (!(rx_readl(dev, IndexRegs.Mailbox[7]) & KERNEL_UP_AND_RUNNING)) { - if(time_after(jiffies, start+30*HZ)) + if(time_after(jiffies, start+180*HZ)) { status = rx_readl(dev, IndexRegs.Mailbox[7]) >> 16; printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %ld.\n", dev->name, instance, status); @@ -397,6 +392,7 @@ dev->a_ops.adapter_enable_int = aac_rx_enable_interrupt; dev->a_ops.adapter_disable_int = aac_rx_disable_interrupt; dev->a_ops.adapter_notify = aac_rx_notify_adapter; + dev->a_ops.adapter_sync_cmd = rx_sync_cmd; if (aac_init_adapter(dev) == NULL) return -1; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/aacraid/sa.c linux.19rc3-ac4/drivers/scsi/aacraid/sa.c --- linux.19rc3/drivers/scsi/aacraid/sa.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/aacraid/sa.c 2002-07-29 13:58:43.000000000 +0100 @@ -0,0 +1,396 @@ +/* + * Adaptec AAC series RAID controller driver + * (c) Copyright 2001 Red Hat Inc. + * + * based on the old aacraid driver that is.. + * Adaptec aacraid device driver for Linux. + * + * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.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, 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; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Module Name: + * sa.c + * + * Abstract: Drawbridge specific support functions + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "scsi.h" +#include "hosts.h" + +#include "aacraid.h" + +static void aac_sa_intr(int irq, void *dev_id, struct pt_regs *regs) +{ + struct aac_dev *dev = dev_id; + unsigned short intstat, mask; + + intstat = sa_readw(dev, DoorbellReg_p); + /* + * Read mask and invert because drawbridge is reversed. + * This allows us to only service interrupts that have been enabled. + */ + mask = ~(sa_readw(dev, SaDbCSR.PRISETIRQMASK)); + + /* Check to see if this is our interrupt. If it isn't just return */ + + if (intstat & mask) { + if (intstat & PrintfReady) { + aac_printf(dev, le32_to_cpu(sa_readl(dev, Mailbox5))); + sa_writew(dev, DoorbellClrReg_p, PrintfReady); /* clear PrintfReady */ + sa_writew(dev, DoorbellReg_s, PrintfDone); + } else if (intstat & DOORBELL_1) { // dev -> Host Normal Command Ready + aac_command_normal(&dev->queues->queue[HostNormCmdQueue]); + sa_writew(dev, DoorbellClrReg_p, DOORBELL_1); + } else if (intstat & DOORBELL_2) { // dev -> Host Normal Response Ready + aac_response_normal(&dev->queues->queue[HostNormRespQueue]); + sa_writew(dev, DoorbellClrReg_p, DOORBELL_2); + } else if (intstat & DOORBELL_3) { // dev -> Host Normal Command Not Full + sa_writew(dev, DoorbellClrReg_p, DOORBELL_3); + } else if (intstat & DOORBELL_4) { // dev -> Host Normal Response Not Full + sa_writew(dev, DoorbellClrReg_p, DOORBELL_4); + } + } +} + +/** + * aac_sa_enable_interrupt - enable an interrupt event + * @dev: Which adapter to enable. + * @event: Which adapter event. + * + * This routine will enable the corresponding adapter event to cause an interrupt on + * the host. + */ + +void aac_sa_enable_interrupt(struct aac_dev *dev, u32 event) +{ + switch (event) { + + case HostNormCmdQue: + sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, DOORBELL_1); + break; + + case HostNormRespQue: + sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, DOORBELL_2); + break; + + case AdapNormCmdNotFull: + sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, DOORBELL_3); + break; + + case AdapNormRespNotFull: + sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, DOORBELL_4); + break; + } +} + +/** + * aac_sa_disable_interrupt - disable an interrupt event + * @dev: Which adapter to enable. + * @event: Which adapter event. + * + * This routine will enable the corresponding adapter event to cause an interrupt on + * the host. + */ + +void aac_sa_disable_interrupt (struct aac_dev *dev, u32 event) +{ + switch (event) { + + case HostNormCmdQue: + sa_writew(dev, SaDbCSR.PRISETIRQMASK, DOORBELL_1); + break; + + case HostNormRespQue: + sa_writew(dev, SaDbCSR.PRISETIRQMASK, DOORBELL_2); + break; + + case AdapNormCmdNotFull: + sa_writew(dev, SaDbCSR.PRISETIRQMASK, DOORBELL_3); + break; + + case AdapNormRespNotFull: + sa_writew(dev, SaDbCSR.PRISETIRQMASK, DOORBELL_4); + break; + } +} + +/** + * aac_sa_notify_adapter - handle adapter notification + * @dev: Adapter that notification is for + * @event: Event to notidy + * + * Notify the adapter of an event + */ + +void aac_sa_notify_adapter(struct aac_dev *dev, u32 event) +{ + switch (event) { + + case AdapNormCmdQue: + sa_writew(dev, DoorbellReg_s,DOORBELL_1); + break; + case HostNormRespNotFull: + sa_writew(dev, DoorbellReg_s,DOORBELL_4); + break; + case AdapNormRespQue: + sa_writew(dev, DoorbellReg_s,DOORBELL_2); + break; + case HostNormCmdNotFull: + sa_writew(dev, DoorbellReg_s,DOORBELL_3); + break; + case HostShutdown: + //sa_sync_cmd(dev, HOST_CRASHING, 0, &ret); + break; + case FastIo: + sa_writew(dev, DoorbellReg_s,DOORBELL_6); + break; + case AdapPrintfDone: + sa_writew(dev, DoorbellReg_s,DOORBELL_5); + break; + default: + BUG(); + break; + } +} + + +/** + * sa_sync_cmd - send a command and wait + * @dev: Adapter + * @command: Command to execute + * @p1: first parameter + * @ret: adapter status + * + * This routine will send a synchronous comamnd to the adapter and wait + * for its completion. + */ + +static int sa_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *ret) +{ + unsigned long start; + int ok; + /* + * Write the Command into Mailbox 0 + */ + sa_writel(dev, Mailbox0, cpu_to_le32(command)); + /* + * Write the parameters into Mailboxes 1 - 4 + */ + sa_writel(dev, Mailbox1, cpu_to_le32(p1)); + sa_writel(dev, Mailbox2, 0); + sa_writel(dev, Mailbox3, 0); + sa_writel(dev, Mailbox4, 0); + /* + * Clear the synch command doorbell to start on a clean slate. + */ + sa_writew(dev, DoorbellClrReg_p, DOORBELL_0); + /* + * Signal that there is a new synch command + */ + sa_writew(dev, DoorbellReg_s, DOORBELL_0); + + ok = 0; + start = jiffies; + + while(time_before(jiffies, start+30*HZ)) + { + /* + * Delay 5uS so that the monitor gets access + */ + udelay(5); + /* + * Mon110 will set doorbell0 bit when it has + * completed the command. + */ + if(sa_readw(dev, DoorbellReg_p) & DOORBELL_0) { + ok = 1; + break; + } + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); + } + + if (ok != 1) + return -ETIMEDOUT; + /* + * Clear the synch command doorbell. + */ + sa_writew(dev, DoorbellClrReg_p, DOORBELL_0); + /* + * Pull the synch status from Mailbox 0. + */ + *ret = le32_to_cpu(sa_readl(dev, Mailbox0)); + return 0; +} + +/** + * aac_sa_interrupt_adapter - interrupt an adapter + * @dev: Which adapter to enable. + * + * Breakpoint an adapter. + */ + +static void aac_sa_interrupt_adapter (struct aac_dev *dev) +{ + u32 ret; + sa_sync_cmd(dev, BREAKPOINT_REQUEST, 0, &ret); +} + +/** + * aac_sa_start_adapter - activate adapter + * @dev: Adapter + * + * Start up processing on an ARM based AAC adapter + */ + +static void aac_sa_start_adapter(struct aac_dev *dev) +{ + u32 ret; + struct aac_init *init; + /* + * Fill in the remaining pieces of the init. + */ + init = dev->init; + init->HostElapsedSeconds = cpu_to_le32(jiffies/HZ); + + dprintk(("INIT\n")); + /* + * Tell the adapter we are back and up and running so it will scan its command + * queues and enable our interrupts + */ + dev->irq_mask = (PrintfReady | DOORBELL_1 | DOORBELL_2 | DOORBELL_3 | DOORBELL_4); + /* + * First clear out all interrupts. Then enable the one's that + * we can handle. + */ + dprintk(("MASK\n")); + sa_writew(dev, SaDbCSR.PRISETIRQMASK, cpu_to_le16(0xffff)); + sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, (PrintfReady | DOORBELL_1 | DOORBELL_2 | DOORBELL_3 | DOORBELL_4)); + dprintk(("SYNCCMD\n")); + /* We can only use a 32 bit address here */ + sa_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, &ret); +} + +/** + * aac_sa_init - initialize an ARM based AAC card + * @dev: device to configure + * @devnum: adapter number + * + * Allocate and set up resources for the ARM based AAC variants. The + * device_interface in the commregion will be allocated and linked + * to the comm region. + */ + +int aac_sa_init(struct aac_dev *dev, unsigned long devnum) +{ + unsigned long start; + unsigned long status; + int instance; + const char *name; + + dev->devnum = devnum; + + dprintk(("PREINST\n")); + instance = dev->id; + name = dev->name; + + /* + * Map in the registers from the adapter. + */ + dprintk(("PREMAP\n")); + + if((dev->regs.sa = (struct sa_registers *)ioremap((unsigned long)dev->scsi_host_ptr->base, 8192))==NULL) + { + printk(KERN_WARNING "aacraid: unable to map ARM.\n" ); + return -1; + } + /* + * Check to see if the board failed any self tests. + */ + if (sa_readl(dev, Mailbox7) & SELF_TEST_FAILED) { + printk(KERN_WARNING "%s%d: adapter self-test failed.\n", name, instance); + return -1; + } + /* + * Check to see if the board panic'd while booting. + */ + if (sa_readl(dev, Mailbox7) & KERNEL_PANIC) { + printk(KERN_WARNING "%s%d: adapter kernel panic'd.\n", name, instance); + return -1; + } + start = jiffies; + /* + * Wait for the adapter to be up and running. Wait up to 3 minutes. + */ + while (!(sa_readl(dev, Mailbox7) & KERNEL_UP_AND_RUNNING)) { + if (time_after(start+180*HZ, jiffies)) { + status = sa_readl(dev, Mailbox7) >> 16; + printk(KERN_WARNING "%s%d: adapter kernel failed to start, init status = %d.\n", name, instance, le32_to_cpu(status)); + return -1; + } + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); + } + + dprintk(("ATIRQ\n")); + if (request_irq(dev->scsi_host_ptr->irq, aac_sa_intr, SA_SHIRQ|SA_INTERRUPT, "aacraid", (void *)dev ) < 0) { + printk(KERN_WARNING "%s%d: Interrupt unavailable.\n", name, instance); + return -1; + } + + /* + * Fill in the function dispatch table. + */ + + dev->a_ops.adapter_interrupt = aac_sa_interrupt_adapter; + dev->a_ops.adapter_enable_int = aac_sa_enable_interrupt; + dev->a_ops.adapter_disable_int = aac_sa_disable_interrupt; + dev->a_ops.adapter_notify = aac_sa_notify_adapter; + dev->a_ops.adapter_sync_cmd = sa_sync_cmd; + + dprintk(("FUNCDONE\n")); + + if(aac_init_adapter(dev) == NULL) + return -1; + + dprintk(("NEWADAPTDONE\n")); + /* + * Start any kernel threads needed + */ + dev->thread_pid = kernel_thread((int (*)(void *))aac_command_thread, dev, 0); + /* + * Tell the adapter that all is configure, and it can start + * accepting requests + */ + dprintk(("STARTING\n")); + aac_sa_start_adapter(dev); + dprintk(("STARTED\n")); + return 0; +} + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/aacraid/sap1sup.c linux.19rc3-ac4/drivers/scsi/aacraid/sap1sup.c --- linux.19rc3/drivers/scsi/aacraid/sap1sup.c 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/aacraid/sap1sup.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,394 +0,0 @@ -/* - * Adaptec AAC series RAID controller driver - * (c) Copyright 2001 Red Hat Inc. - * - * based on the old aacraid driver that is.. - * Adaptec aacraid device driver for Linux. - * - * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.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, 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; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Module Name: - * sap1sup.c - * - * Abstract: Drawbridge specific support functions - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "scsi.h" -#include "hosts.h" - -#include "aacraid.h" - -static void aac_sa_intr(int irq, void *dev_id, struct pt_regs *regs) -{ - struct aac_dev *dev = dev_id; - unsigned short intstat, mask; - - intstat = sa_readw(dev, DoorbellReg_p); - /* - * Read mask and invert because drawbridge is reversed. - * This allows us to only service interrupts that have been enabled. - */ - mask = ~(sa_readw(dev, SaDbCSR.PRISETIRQMASK)); - - /* Check to see if this is our interrupt. If it isn't just return */ - - if (intstat & mask) { - if (intstat & PrintfReady) { - aac_printf(dev, le32_to_cpu(sa_readl(dev, Mailbox5))); - sa_writew(dev, DoorbellClrReg_p, PrintfReady); /* clear PrintfReady */ - sa_writew(dev, DoorbellReg_s, PrintfDone); - } else if (intstat & DOORBELL_1) { // dev -> Host Normal Command Ready - aac_command_normal(&dev->queues->queue[HostNormCmdQueue]); - sa_writew(dev, DoorbellClrReg_p, DOORBELL_1); - } else if (intstat & DOORBELL_2) { // dev -> Host Normal Response Ready - aac_response_normal(&dev->queues->queue[HostNormRespQueue]); - sa_writew(dev, DoorbellClrReg_p, DOORBELL_2); - } else if (intstat & DOORBELL_3) { // dev -> Host Normal Command Not Full - sa_writew(dev, DoorbellClrReg_p, DOORBELL_3); - } else if (intstat & DOORBELL_4) { // dev -> Host Normal Response Not Full - sa_writew(dev, DoorbellClrReg_p, DOORBELL_4); - } - } -} - -/** - * aac_sa_enable_interrupt - enable an interrupt event - * @dev: Which adapter to enable. - * @event: Which adapter event. - * - * This routine will enable the corresponding adapter event to cause an interrupt on - * the host. - */ - -void aac_sa_enable_interrupt(struct aac_dev *dev, u32 event) -{ - switch (event) { - - case HostNormCmdQue: - sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, DOORBELL_1); - break; - - case HostNormRespQue: - sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, DOORBELL_2); - break; - - case AdapNormCmdNotFull: - sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, DOORBELL_3); - break; - - case AdapNormRespNotFull: - sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, DOORBELL_4); - break; - } -} - -/** - * aac_sa_disable_interrupt - disable an interrupt event - * @dev: Which adapter to enable. - * @event: Which adapter event. - * - * This routine will enable the corresponding adapter event to cause an interrupt on - * the host. - */ - -void aac_sa_disable_interrupt (struct aac_dev *dev, u32 event) -{ - switch (event) { - - case HostNormCmdQue: - sa_writew(dev, SaDbCSR.PRISETIRQMASK, DOORBELL_1); - break; - - case HostNormRespQue: - sa_writew(dev, SaDbCSR.PRISETIRQMASK, DOORBELL_2); - break; - - case AdapNormCmdNotFull: - sa_writew(dev, SaDbCSR.PRISETIRQMASK, DOORBELL_3); - break; - - case AdapNormRespNotFull: - sa_writew(dev, SaDbCSR.PRISETIRQMASK, DOORBELL_4); - break; - } -} - -/** - * aac_sa_notify_adapter - handle adapter notification - * @dev: Adapter that notification is for - * @event: Event to notidy - * - * Notify the adapter of an event - */ - -void aac_sa_notify_adapter(struct aac_dev *dev, u32 event) -{ - switch (event) { - - case AdapNormCmdQue: - sa_writew(dev, DoorbellReg_s,DOORBELL_1); - break; - case HostNormRespNotFull: - sa_writew(dev, DoorbellReg_s,DOORBELL_4); - break; - case AdapNormRespQue: - sa_writew(dev, DoorbellReg_s,DOORBELL_2); - break; - case HostNormCmdNotFull: - sa_writew(dev, DoorbellReg_s,DOORBELL_3); - break; - case HostShutdown: - //sa_sync_cmd(dev, HOST_CRASHING, 0, &ret); - break; - case FastIo: - sa_writew(dev, DoorbellReg_s,DOORBELL_6); - break; - case AdapPrintfDone: - sa_writew(dev, DoorbellReg_s,DOORBELL_5); - break; - default: - BUG(); - break; - } -} - - -/** - * sa_sync_cmd - send a command and wait - * @dev: Adapter - * @command: Command to execute - * @p1: first parameter - * @ret: adapter status - * - * This routine will send a synchronous comamnd to the adapter and wait - * for its completion. - */ - -static int sa_sync_cmd(struct aac_dev *dev, unsigned long command, unsigned long p1, unsigned long *ret) -{ - unsigned long start; - int ok; - /* - * Write the Command into Mailbox 0 - */ - sa_writel(dev, Mailbox0, cpu_to_le32(command)); - /* - * Write the parameters into Mailboxes 1 - 4 - */ - sa_writel(dev, Mailbox1, cpu_to_le32(p1)); - sa_writel(dev, Mailbox2, 0); - sa_writel(dev, Mailbox3, 0); - sa_writel(dev, Mailbox4, 0); - /* - * Clear the synch command doorbell to start on a clean slate. - */ - sa_writew(dev, DoorbellClrReg_p, DOORBELL_0); - /* - * Signal that there is a new synch command - */ - sa_writew(dev, DoorbellReg_s, DOORBELL_0); - - ok = 0; - start = jiffies; - - while(time_before(jiffies, start+30*HZ)) - { - /* - * Delay 5uS so that the monitor gets access - */ - udelay(5); - /* - * Mon110 will set doorbell0 bit when it has - * completed the command. - */ - if(sa_readw(dev, DoorbellReg_p) & DOORBELL_0) { - ok = 1; - break; - } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); - } - - if (ok != 1) - return -ETIMEDOUT; - /* - * Clear the synch command doorbell. - */ - sa_writew(dev, DoorbellClrReg_p, DOORBELL_0); - /* - * Pull the synch status from Mailbox 0. - */ - *ret = le32_to_cpu(sa_readl(dev, Mailbox0)); - return 0; -} - -/** - * aac_sa_interrupt_adapter - interrupt an adapter - * @dev: Which adapter to enable. - * - * Breakpoint an adapter. - */ - -static void aac_sa_interrupt_adapter (struct aac_dev *dev) -{ - unsigned long ret; - sa_sync_cmd(dev, BREAKPOINT_REQUEST, 0, &ret); -} - -/** - * aac_sa_start_adapter - activate adapter - * @dev: Adapter - * - * Start up processing on an ARM based AAC adapter - */ - -static void aac_sa_start_adapter(struct aac_dev *dev) -{ - unsigned long ret; - struct aac_init *init; - /* - * Fill in the remaining pieces of the init. - */ - init = dev->init; - init->HostElapsedSeconds = cpu_to_le32(jiffies/HZ); - - dprintk(("INIT\n")); - /* - * Tell the adapter we are back and up and running so it will scan its command - * queues and enable our interrupts - */ - dev->irq_mask = (PrintfReady | DOORBELL_1 | DOORBELL_2 | DOORBELL_3 | DOORBELL_4); - /* - * First clear out all interrupts. Then enable the one's that - * we can handle. - */ - dprintk(("MASK\n")); - sa_writew(dev, SaDbCSR.PRISETIRQMASK, cpu_to_le16(0xffff)); - sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, (PrintfReady | DOORBELL_1 | DOORBELL_2 | DOORBELL_3 | DOORBELL_4)); - dprintk(("SYNCCMD\n")); - sa_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (unsigned long) dev->init_pa, &ret); -} - -/** - * aac_sa_init - initialize an ARM based AAC card - * @dev: device to configure - * @devnum: adapter number - * - * Allocate and set up resources for the ARM based AAC variants. The - * device_interface in the commregion will be allocated and linked - * to the comm region. - */ - -int aac_sa_init(struct aac_dev *dev, unsigned long devnum) -{ - unsigned long start; - unsigned long status; - int instance; - const char *name; - - dev->devnum = devnum; - - dprintk(("PREINST\n")); - instance = dev->id; - name = dev->name; - - /* - * Map in the registers from the adapter. - */ - dprintk(("PREMAP\n")); - - if((dev->regs.sa = (struct sa_registers *)ioremap((unsigned long)dev->scsi_host_ptr->base, 8192))==NULL) - { - printk(KERN_WARNING "aacraid: unable to map ARM.\n" ); - return -1; - } - /* - * Check to see if the board failed any self tests. - */ - if (sa_readl(dev, Mailbox7) & SELF_TEST_FAILED) { - printk(KERN_WARNING "%s%d: adapter self-test failed.\n", name, instance); - return -1; - } - /* - * Check to see if the board panic'd while booting. - */ - if (sa_readl(dev, Mailbox7) & KERNEL_PANIC) { - printk(KERN_WARNING "%s%d: adapter kernel panic'd.\n", name, instance); - return -1; - } - start = jiffies; - /* - * Wait for the adapter to be up and running. Wait up to 3 minutes. - */ - while (!(sa_readl(dev, Mailbox7) & KERNEL_UP_AND_RUNNING)) { - if (time_after(start+180*HZ, jiffies)) { - status = sa_readl(dev, Mailbox7) >> 16; - printk(KERN_WARNING "%s%d: adapter kernel failed to start, init status = %d.\n", name, instance, le32_to_cpu(status)); - return -1; - } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); - } - - dprintk(("ATIRQ\n")); - if (request_irq(dev->scsi_host_ptr->irq, aac_sa_intr, SA_SHIRQ|SA_INTERRUPT, "aacraid", (void *)dev ) < 0) { - printk(KERN_WARNING "%s%d: Interrupt unavailable.\n", name, instance); - return -1; - } - - /* - * Fill in the function dispatch table. - */ - - dev->a_ops.adapter_interrupt = aac_sa_interrupt_adapter; - dev->a_ops.adapter_enable_int = aac_sa_enable_interrupt; - dev->a_ops.adapter_disable_int = aac_sa_disable_interrupt; - dev->a_ops.adapter_notify = aac_sa_notify_adapter; - - dprintk(("FUNCDONE\n")); - - if(aac_init_adapter(dev) == NULL) - return -1; - - dprintk(("NEWADAPTDONE\n")); - /* - * Start any kernel threads needed - */ - dev->thread_pid = kernel_thread((int (*)(void *))aac_command_thread, dev, 0); - /* - * Tell the adapter that all is configure, and it can start - * accepting requests - */ - dprintk(("STARTING\n")); - aac_sa_start_adapter(dev); - dprintk(("STARTED\n")); - return 0; -} - diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/aic7xxx/aic7xxx_pci.c linux.19rc3-ac4/drivers/scsi/aic7xxx/aic7xxx_pci.c --- linux.19rc3/drivers/scsi/aic7xxx/aic7xxx_pci.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/aic7xxx/aic7xxx_pci.c 2002-07-29 13:58:43.000000000 +0100 @@ -1768,41 +1768,6 @@ *eeprom_present = (ahc_inb(ahc, SPIOCAP) & EEPROM) ? 1 : 0; } -int -ahc_acquire_seeprom(struct ahc_softc *ahc, struct seeprom_descriptor *sd) -{ - int wait; - - if ((ahc->features & AHC_SPIOCAP) != 0 - && (ahc_inb(ahc, SPIOCAP) & SEEPROM) == 0) - return (0); - - /* - * Request access of the memory port. When access is - * granted, SEERDY will go high. We use a 1 second - * timeout which should be near 1 second more than - * is needed. Reason: after the chip reset, there - * should be no contention. - */ - SEEPROM_OUTB(sd, sd->sd_MS); - wait = 1000; /* 1 second timeout in msec */ - while (--wait && ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0)) { - ahc_delay(1000); /* delay 1 msec */ - } - if ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0) { - SEEPROM_OUTB(sd, 0); - return (0); - } - return(1); -} - -void -ahc_release_seeprom(struct seeprom_descriptor *sd) -{ - /* Release access to the memory port and the serial EEPROM. */ - SEEPROM_OUTB(sd, 0); -} - static void write_brdctl(struct ahc_softc *ahc, uint8_t value) { diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/aic7xxx/aic7xxx_proc.c linux.19rc3-ac4/drivers/scsi/aic7xxx/aic7xxx_proc.c --- linux.19rc3/drivers/scsi/aic7xxx/aic7xxx_proc.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/aic7xxx/aic7xxx_proc.c 2002-07-29 13:58:43.000000000 +0100 @@ -54,6 +54,44 @@ struct ahc_linux_device *dev); static int ahc_proc_write_seeprom(struct ahc_softc *ahc, char *buffer, int length); + + +int +ahc_acquire_seeprom(struct ahc_softc *ahc, struct seeprom_descriptor *sd) +{ + int wait; + + if ((ahc->features & AHC_SPIOCAP) != 0 + && (ahc_inb(ahc, SPIOCAP) & SEEPROM) == 0) + return (0); + + /* + * Request access of the memory port. When access is + * granted, SEERDY will go high. We use a 1 second + * timeout which should be near 1 second more than + * is needed. Reason: after the chip reset, there + * should be no contention. + */ + SEEPROM_OUTB(sd, sd->sd_MS); + wait = 1000; /* 1 second timeout in msec */ + while (--wait && ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0)) { + ahc_delay(1000); /* delay 1 msec */ + } + if ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0) { + SEEPROM_OUTB(sd, 0); + return (0); + } + return(1); +} + + +void +ahc_release_seeprom(struct seeprom_descriptor *sd) +{ + /* Release access to the memory port and the serial EEPROM. */ + SEEPROM_OUTB(sd, 0); +} + static void copy_mem_info(struct info_str *info, char *data, int len) diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/ChangeLog.ips linux.19rc3-ac4/drivers/scsi/ChangeLog.ips --- linux.19rc3/drivers/scsi/ChangeLog.ips 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/ChangeLog.ips 2002-07-29 13:58:43.000000000 +0100 @@ -116,4 +116,3 @@ - Fixed read/write errors when the adapter is using an 8K stripe size. - \ No newline at end of file diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/Config.in linux.19rc3-ac4/drivers/scsi/Config.in --- linux.19rc3/drivers/scsi/Config.in 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/Config.in 2002-07-29 13:58:43.000000000 +0100 @@ -150,7 +150,10 @@ if [ "$CONFIG_PCI" = "y" -a "$CONFIG_SCSI_SYM53C8XX_2" != "y" ]; then dep_tristate 'NCR53C8XX SCSI support' CONFIG_SCSI_NCR53C8XX $CONFIG_SCSI dep_tristate 'SYM53C8XX SCSI support' CONFIG_SCSI_SYM53C8XX $CONFIG_SCSI - if [ "$CONFIG_SCSI_NCR53C8XX" != "n" -o "$CONFIG_SCSI_SYM53C8XX" != "n" ]; then + if [ "$CONFIG_PARISC" = "y" ]; then + dep_tristate 'Zalon SCSI support' CONFIG_SCSI_ZALON $CONFIG_GSC $CONFIG_SCSI + fi + if [ "$CONFIG_SCSI_NCR53C8XX" != "n" -o "$CONFIG_SCSI_ZALON" = "y" -o "$CONFIG_SCSI_ZALON" = "m" -o "$CONFIG_SCSI_SYM53C8XX" != "n" ]; then int ' default tagged command queue depth' CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS 8 int ' maximum number of queued commands' CONFIG_SCSI_NCR53C8XX_MAX_TAGS 32 int ' synchronous transfers frequency in MHz' CONFIG_SCSI_NCR53C8XX_SYNC 20 diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/cpqfcTSinit.c linux.19rc3-ac4/drivers/scsi/cpqfcTSinit.c --- linux.19rc3/drivers/scsi/cpqfcTSinit.c 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/cpqfcTSinit.c 2002-07-29 13:58:43.000000000 +0100 @@ -261,10 +261,22 @@ /* "Entry" point to discover if any supported PCI bus adapter can be found */ -// We're supporting: -// Compaq 64-bit, 66MHz HBA with Tachyon TS -// Agilent XL2 -#define HBA_TYPES 2 +/* We're supporting: + * Compaq 64-bit, 66MHz HBA with Tachyon TS + * Agilent XL2 + * HP Tachyon + */ +#define HBA_TYPES 3 + +#ifndef PCI_DEVICE_ID_COMPAQ_ +#define PCI_DEVICE_ID_COMPAQ_TACHYON 0xa0fc +#endif + +static struct SupportedPCIcards cpqfc_boards[] __initdata = { + {PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_TACHYON}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_TACHLITE}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_TACHYON}, +}; int cpqfcTS_detect(Scsi_Host_Template *ScsiHostTemplate) @@ -274,35 +286,28 @@ struct Scsi_Host *HostAdapter = NULL; CPQFCHBA *cpqfcHBAdata = NULL; struct timer_list *cpqfcTStimer = NULL; - SupportedPCIcards PCIids[HBA_TYPES]; int i; - + ENTER("cpqfcTS_detect"); - + #if LINUX_VERSION_CODE < LinuxVersionCode(2,3,27) ScsiHostTemplate->proc_dir = &proc_scsi_cpqfcTS; #else ScsiHostTemplate->proc_name = "cpqfcTS"; #endif - + if( pci_present() == 0) // no PCI busses? { printk( " no PCI bus?@#!\n"); return NumberOfAdapters; } - // what HBA adapters are we supporting? - PCIids[0].vendor_id = PCI_VENDOR_ID_COMPAQ; - PCIids[0].device_id = CPQ_DEVICE_ID; - PCIids[1].vendor_id = PCI_VENDOR_ID_HP; // i.e. 103Ch (Agilent == HP for now) - PCIids[1].device_id = AGILENT_XL2_ID; // i.e. 1029h - for( i=0; i < HBA_TYPES; i++) { // look for all HBAs of each type - while( (PciDev = - pci_find_device( PCIids[i].vendor_id, PCIids[i].device_id, PciDev) )) + while((PciDev = pci_find_device(cpqfc_boards[i].vendor_id, + cpqfc_boards[i].device_id, PciDev))) { if (pci_set_dma_mask(PciDev, CPQFCTS_DMA_MASK) != 0) { diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/cpqfcTSstructs.h linux.19rc3-ac4/drivers/scsi/cpqfcTSstructs.h --- linux.19rc3/drivers/scsi/cpqfcTSstructs.h 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/cpqfcTSstructs.h 2002-07-29 15:45:39.000000000 +0100 @@ -95,14 +95,11 @@ #define DEV_NAME "cpqfcTS" -#define CPQ_DEVICE_ID 0xA0FC -#define AGILENT_XL2_ID 0x1029 - -typedef struct +struct SupportedPCIcards { __u16 vendor_id; __u16 device_id; -} SupportedPCIcards; +}; // nn:nn denotes bit field // TachyonHeader struct def. diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/eata.c linux.19rc3-ac4/drivers/scsi/eata.c --- linux.19rc3/drivers/scsi/eata.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/eata.c 2002-07-29 13:58:43.000000000 +0100 @@ -1,9 +1,45 @@ /* * eata.c - Low-level driver for EATA/DMA SCSI host adapters. * - * 01 Jan 2002 Rev. 6.50 for linux 2.4.16 + * 25 Jun 2002 Rev. 6.70 for linux 2.4.19 + * + This release is the first one tested on a Big Endian platform: + * fixed endian-ness problem due to bitfields; + * fixed endian-ness problem in read_pio. + * + Added new options for selectively probing ISA, EISA and PCI bus: + * + * Boot option Parameter name Default according to + * + * ip:[y|n] isa_probe=[1|0] CONFIG_ISA defined + * ep:[y|n] eisa_probe=[1|0] CONFIG_EISA defined + * pp:[y|n] pci_probe=[1|0] CONFIG_PCI defined + * + * The default action is to perform probing if the corrisponding + * bus is configured and to skip probing otherwise. + * + * + If pci_probe is in effect and a list of I/O ports is specified + * as parameter or boot option, pci_enable_device() is performed + * on all pci devices matching PCI_CLASS_STORAGE_SCSI. + * + * 21 Feb 2002 Rev. 6.52 for linux 2.4.18 + * + Backport from rev. 7.22 (use io_request_lock). + * + * 20 Feb 2002 Rev. 7.22 for linux 2.5.5 + * + Remove any reference to virt_to_bus(). + * + Fix pio hang while detecting multiple HBAs. + * + Fixed a board detection bug: in a system with + * multiple ISA/EISA boards, all but the first one + * were erroneously detected as PCI. + * + * 01 Jan 2002 Rev. 7.20 for linux 2.5.1 * + Use the dynamic DMA mapping API. * + * 19 Dec 2001 Rev. 7.02 for linux 2.5.1 + * + Use SCpnt->sc_data_direction if set. + * + Use sglist.page instead of sglist.address. + * + * 11 Dec 2001 Rev. 7.00 for linux 2.5.1 + * + Use host->host_lock instead of io_request_lock. + * * 1 May 2001 Rev. 6.05 for linux 2.4.4 * + Clean up all pci related routines. * + Fix data transfer direction for opcode SEND_CUE_SHEET (0x5d) @@ -22,7 +58,7 @@ * boot time. * + Improved boot messages: all tagged capable device are * indicated as "tagged" or "soft-tagged" : - * - "soft-tagged" means that the driver is trying to do its + * - "soft-tagged" means that the driver is trying to do its * own tagging (i.e. the tc:y option is in effect); * - "tagged" means that the device supports tagged commands, * but the driver lets the HBA be responsible for tagging @@ -33,7 +69,7 @@ * + When loaded as a module, accepts the new parameter boot_options * which value is a string with the same format of the kernel boot * command line options. A valid example is: - * modprobe eata boot_options=\"0x7410,0x230,lc:y,tc:n,mq:4\" + * modprobe eata 'boot_options="0x7410,0x230,lc:y,tc:n,mq:4"' * * 9 Sep 1999 Rev. 5.10 for linux 2.2.12 and 2.3.17 * + 64bit cleanup for Linux/Alpha platform support @@ -297,7 +333,7 @@ * include in the list of i/o ports to be probed all the PCI SCSI controllers. * * Due to a DPT BIOS "feature", it might not be possible to force an EISA - * address on more then a single DPT PCI board, so in this case you have to + * address on more than a single DPT PCI board, so in this case you have to * let the PCI BIOS assign the addresses. * * The sequence of detection probes is: @@ -414,6 +450,9 @@ MODULE_PARM(tag_mode, "i"); MODULE_PARM(ext_tran, "i"); MODULE_PARM(rev_scan, "i"); +MODULE_PARM(isa_probe, "i"); +MODULE_PARM(eisa_probe, "i"); +MODULE_PARM(pci_probe, "i"); MODULE_AUTHOR("Dario Ballabio"); #endif @@ -441,11 +480,15 @@ #include #include +#if !defined(__BIG_ENDIAN_BITFIELD) && !defined(__LITTLE_ENDIAN_BITFIELD) +#error "Adjust your defines" +#endif + /* Subversion values */ #define ISA 0 #define ESA 1 -#undef FORCE_CONFIG +#undef FORCE_CONFIG #undef DEBUG_LINKED_COMMANDS #undef DEBUG_DETECT @@ -498,7 +541,7 @@ #define REG_LM 3 #define REG_MID 4 #define REG_MSB 5 -#define REGION_SIZE 9 +#define REGION_SIZE 9UL #define MAX_ISA_ADDR 0x03ff #define MIN_EISA_ADDR 0x1c88 #define MAX_EISA_ADDR 0xfc88 @@ -522,7 +565,7 @@ #define TLDEV(type) ((type) == TYPE_DISK || (type) == TYPE_ROM) /* "EATA", in Big Endian format */ -#define EATA_SIGNATURE 0x41544145 +#define EATA_SIG_BE 0x45415441 /* Number of valid bytes in the board config structure for EATA 2.0x */ #define EATA_2_0A_SIZE 28 @@ -533,6 +576,12 @@ struct eata_info { u_int32_t data_len; /* Number of valid bytes after this field */ u_int32_t sign; /* ASCII "EATA" signature */ + +#if defined(__BIG_ENDIAN_BITFIELD) + unchar version:4, :4; + unchar haaval:1, ata:1, drqvld:1, dmasup:1, morsup:1, trnxfr:1, tarsup:1, + ocsena:1; +#else unchar :4, /* unused low nibble */ version:4; /* EATA version, should be 0x1 */ unchar ocsena:1, /* Overlap Command Support Enabled */ @@ -543,6 +592,8 @@ drqvld:1, /* DRQ Index (DRQX) is valid */ ata:1, /* This is an ATA device */ haaval:1; /* Host Adapter Address Valid */ +#endif + ushort cp_pad_len; /* Number of pad bytes after cp_len */ unchar host_addr[4]; /* Host Adapter SCSI ID for channels 3, 2, 1, 0 */ u_int32_t cp_len; /* Number of valid bytes in cp */ @@ -550,6 +601,15 @@ ushort queue_size; /* Max number of cp that can be queued */ ushort unused; ushort scatt_size; /* Max number of entries in scatter/gather table */ + +#if defined(__BIG_ENDIAN_BITFIELD) + unchar drqx:2, second:1, irq_tr:1, irq:4; + unchar sync; + unchar :4, res1:1, large_sg:1, forcaddr:1, isaena:1; + unchar max_chan:3, max_id:5; + unchar max_lun; + unchar eisa:1, pci:1, idquest:1, m1:1, :4; +#else unchar irq:4, /* Interrupt Request assigned to this controller */ irq_tr:1, /* 0 for edge triggered, 1 for level triggered */ second:1, /* 1 if this is a secondary (not primary) controller */ @@ -572,6 +632,8 @@ idquest:1, /* RAIDNUM returned is questionable */ pci:1, /* This board is PCI */ eisa:1; /* This board is EISA */ +#endif + unchar raidnum; /* Uniquely identifies this HBA in a system */ unchar notused; @@ -581,18 +643,30 @@ /* Board config structure */ struct eata_config { ushort len; /* Number of bytes following this field */ + +#if defined(__BIG_ENDIAN_BITFIELD) + unchar :4, tarena:1, mdpena:1, ocena:1, edis:1; +#else unchar edis:1, /* Disable EATA interface after config command */ ocena:1, /* Overlapped Commands Enabled */ mdpena:1, /* Transfer all Modified Data Pointer Messages */ tarena:1, /* Target Mode Enabled for this controller */ :4; +#endif + unchar cpad[511]; }; /* Returned status packet structure */ struct mssp { + +#if defined(__BIG_ENDIAN_BITFIELD) + unchar eoc:1, adapter_status:7; +#else unchar adapter_status:7, /* State related to current command */ eoc:1; /* End Of Command (1 = command completed) */ +#endif + unchar target_status; /* SCSI status received after data transfer */ unchar unused[2]; u_int32_t inv_res_len; /* Number of bytes not transferred */ @@ -607,6 +681,16 @@ /* MailBox SCSI Command Packet */ struct mscp { + +#if defined(__BIG_ENDIAN_BITFIELD) + unchar din:1, dout:1, interp:1, :1, sg:1, reqsen:1, init:1, sreset:1; + unchar sense_len; + unchar unused[3]; + unchar :7, fwnest:1; + unchar :5, hbaci:1, iat:1, phsunit:1; + unchar channel:3, target:5; + unchar one:1, dispri:1, luntar:1, lun:5; +#else unchar sreset:1, /* SCSI Bus Reset Signal should be asserted */ init:1, /* Re-initialize controller and self test */ reqsen:1, /* Transfer Request Sense Data to addr using DMA */ @@ -629,6 +713,8 @@ luntar:1, /* This cp is for Target (not LUN) */ dispri:1, /* Disconnect Privilege granted */ one:1; /* 1 */ +#endif + unchar mess[3]; /* Massage to/from Target */ unchar cdb[12]; /* Command Descriptor Block */ u_int32_t data_len; /* If sg=0 Data Length, if sg=1 sglist length */ @@ -636,11 +722,18 @@ u_int32_t data_address; /* If sg=0 Data Address, if sg=1 sglist address */ u_int32_t sp_dma_addr; /* Address where sp is DMA'ed when cp completes */ u_int32_t sense_addr; /* Address where Sense Data is DMA'ed on error */ + /* Additional fields begin here. */ Scsi_Cmnd *SCpnt; - struct sg_list *sglist; + + /* All the cp structure is zero filled by queuecommand except the + following CP_TAIL_SIZE bytes, initialized by detect */ + dma_addr_t cp_dma_addr; /* dma handle for this cp structure */ + struct sg_list *sglist; /* pointer to the allocated SG list */ }; +#define CP_TAIL_SIZE (sizeof(struct sglist *) + sizeof(dma_addr_t)) + struct hostdata { struct mscp cp[MAX_MAILBOXES]; /* Mailboxes for this board */ unsigned int cp_stat[MAX_MAILBOXES]; /* FREE, IN_USE, LOCKED, IN_RESET */ @@ -648,7 +741,6 @@ unsigned int iocount; /* Total i/o done for this board */ int board_number; /* Number of this board */ char board_name[16]; /* Name of this board */ - char board_id[256]; /* data from INQUIRY on this board */ int in_reset; /* True if board is doing a reset */ int target_to[MAX_TARGET][MAX_CHANNEL]; /* N. of timeout errors on target */ int target_redo[MAX_TARGET][MAX_CHANNEL]; /* If TRUE redo i/o on target */ @@ -698,10 +790,13 @@ #define BN(board) (HD(board)->board_name) /* Device is Big Endian */ -#define H2DEV(x) cpu_to_be32(x) -#define DEV2H(x) be32_to_cpu(x) +#define H2DEV(x) cpu_to_be32(x) +#define DEV2H(x) be32_to_cpu(x) +#define H2DEV16(x) cpu_to_be16(x) +#define DEV2H16(x) be16_to_cpu(x) -#define V2DEV(addr) ((addr) ? H2DEV(virt_to_bus((void *)addr)) : 0) +/* But transfer orientation from the 16 bit data register is Little Endian */ +#define REG2H(x) le16_to_cpu(x) static void do_interrupt_handler(int, void *, struct pt_regs *); static void flush_dev(Scsi_Device *, unsigned long, unsigned int, unsigned int); @@ -731,6 +826,24 @@ static int max_queue_depth = MAX_CMD_PER_LUN; #endif +#if defined(CONFIG_ISA) +static int isa_probe = TRUE; +#else +static int isa_probe = FALSE; +#endif + +#if defined(CONFIG_EISA) +static int eisa_probe = TRUE; +#else +static int eisa_probe = FALSE; +#endif + +#if defined(CONFIG_PCI) +static int pci_probe = TRUE; +#else +static int pci_probe = FALSE; +#endif + static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) { Scsi_Device *dev; int j, ntag = 0, nuntag = 0, tqd, utqd; @@ -801,14 +914,18 @@ } static inline int do_dma(unsigned long iobase, unsigned long addr, unchar cmd) { + unsigned char *byaddr; + unsigned long devaddr; if (wait_on_busy(iobase, (addr ? MAXLOOP * 100 : MAXLOOP))) return TRUE; - if ((addr = V2DEV(addr))) { - outb((char) (addr >> 24), iobase + REG_LOW); - outb((char) (addr >> 16), iobase + REG_LM); - outb((char) (addr >> 8), iobase + REG_MID); - outb((char) addr, iobase + REG_MSB); + if (addr) { + devaddr = H2DEV(addr); + byaddr = (unsigned char *) &devaddr; + outb(byaddr[3], iobase + REG_LOW); + outb(byaddr[2], iobase + REG_LM); + outb(byaddr[1], iobase + REG_MID); + outb(byaddr[0], iobase + REG_MSB); } outb(cmd, iobase + REG_CMD); @@ -827,7 +944,7 @@ } loop = MAXLOOP; - *p = inw(iobase); + *p = REG2H(inw(iobase)); } return FALSE; @@ -858,6 +975,29 @@ return NULL; } +static void enable_pci_ports(void) { + +#if defined(CONFIG_PCI) + + struct pci_dev *dev = NULL; + + if (!pci_present()) return; + + while((dev = pci_find_class(PCI_CLASS_STORAGE_SCSI << 8, dev))) { + +#if defined(DEBUG_PCI_DETECT) + printk("%s: enable_pci_ports, bus %d, devfn 0x%x.\n", + driver_name, dev->bus->number, dev->devfn); +#endif + + if (pci_enable_device (dev)) + printk("%s: warning, pci_enable_device failed, bus %d devfn 0x%x.\n", + driver_name, dev->bus->number, dev->devfn); + } + +#endif /* end CONFIG_PCI */ +} + static inline int port_detect \ (unsigned long port_base, unsigned int j, Scsi_Host_Template *tpnt) { unsigned char irq, dma_channel, subversion, i, is_pci = FALSE; @@ -881,36 +1021,54 @@ } if (do_dma(port_base, 0, READ_CONFIG_PIO)) { +#if defined(DEBUG_DETECT) + printk("%s: detect, do_dma failed at 0x%03lx.\n", name, port_base); +#endif release_region(port_base, REGION_SIZE); return FALSE; } /* Read the info structure */ if (read_pio(port_base, (ushort *)&info, (ushort *)&info.ipad[0])) { +#if defined(DEBUG_DETECT) + printk("%s: detect, read_pio failed at 0x%03lx.\n", name, port_base); +#endif release_region(port_base, REGION_SIZE); return FALSE; } + info.data_len = DEV2H(info.data_len); + info.sign = DEV2H(info.sign); + info.cp_pad_len = DEV2H16(info.cp_pad_len); + info.cp_len = DEV2H(info.cp_len); + info.sp_len = DEV2H(info.sp_len); + info.scatt_size = DEV2H16(info.scatt_size); + info.queue_size = DEV2H16(info.queue_size); + /* Check the controller "EATA" signature */ - if (info.sign != EATA_SIGNATURE) { + if (info.sign != EATA_SIG_BE) { +#if defined(DEBUG_DETECT) + printk("%s: signature 0x%04x discarded.\n", name, info.sign); +#endif release_region(port_base, REGION_SIZE); return FALSE; } - if (DEV2H(info.data_len) < EATA_2_0A_SIZE) { + if (info.data_len < EATA_2_0A_SIZE) { printk("%s: config structure size (%d bytes) too short, detaching.\n", - name, DEV2H(info.data_len)); + name, info.data_len); release_region(port_base, REGION_SIZE); return FALSE; } - else if (DEV2H(info.data_len) == EATA_2_0A_SIZE) + else if (info.data_len == EATA_2_0A_SIZE) protocol_rev = 'A'; - else if (DEV2H(info.data_len) == EATA_2_0B_SIZE) + else if (info.data_len == EATA_2_0B_SIZE) protocol_rev = 'B'; else protocol_rev = 'C'; - if (!setup_done && j > 0 && j <= MAX_PCI) { + if (protocol_rev != 'A' && info.forcaddr) { + printk("%s: warning, port address has been forced.\n", name); bus_type = "PCI"; is_pci = TRUE; subversion = ESA; @@ -973,7 +1131,7 @@ if (is_pci) { pdev = get_pci_dev(port_base); - if (!pdev) + if (!pdev) printk("%s: warning, failed to get pci_dev structure.\n", name); } else @@ -1003,18 +1161,29 @@ #if defined(FORCE_CONFIG) { - struct eata_config config; + struct eata_config *cf; + dma_addr_t cf_dma_addr; + + cf = pci_alloc_consistent(pdev, sizeof(struct eata_config), &cf_dma_addr); + + if (!cf) { + printk("%s: config, pci_alloc_consistent failed, detaching.\n", name); + release_region(port_base, REGION_SIZE); + return FALSE; + } /* Set board configuration */ - memset((char *)&config, 0, sizeof(struct eata_config)); - config.len = (ushort) cpu_to_be16((ushort)510); - config.ocena = TRUE; + memset((char *)cf, 0, sizeof(struct eata_config)); + cf->len = (ushort) H2DEV16((ushort)510); + cf->ocena = TRUE; - if (do_dma(port_base, (unsigned long)&config, SET_CONFIG_DMA)) { + if (do_dma(port_base, cf_dma_addr, SET_CONFIG_DMA)) { printk("%s: busy timeout sending configuration, detaching.\n", name); + pci_free_consistent(pdev, sizeof(struct eata_config), cf, cf_dma_addr); release_region(port_base, REGION_SIZE); return FALSE; } + } #endif @@ -1036,9 +1205,9 @@ sh[j]->n_io_port = REGION_SIZE; sh[j]->dma_channel = dma_channel; sh[j]->irq = irq; - sh[j]->sg_tablesize = (ushort) be16_to_cpu(info.scatt_size); + sh[j]->sg_tablesize = (ushort) info.scatt_size; sh[j]->this_id = (ushort) info.host_addr[3]; - sh[j]->can_queue = (ushort) be16_to_cpu(info.queue_size); + sh[j]->can_queue = (ushort) info.queue_size; sh[j]->cmd_per_lun = MAX_CMD_PER_LUN; sh[j]->select_queue_depths = select_queue_depths; memset(HD(j), 0, sizeof(struct hostdata)); @@ -1102,6 +1271,10 @@ else sprintf(dma_name, "DMA %u", dma_channel); for (i = 0; i < sh[j]->can_queue; i++) + HD(j)->cp[i].cp_dma_addr = pci_map_single(HD(j)->pdev, + &HD(j)->cp[i], sizeof(struct mscp), PCI_DMA_BIDIRECTIONAL); + + for (i = 0; i < sh[j]->can_queue; i++) if (! ((&HD(j)->cp[i])->sglist = kmalloc( sh[j]->sg_tablesize * sizeof(struct sg_list), (sh[j]->unchecked_isa_dma ? GFP_DMA : 0) | GFP_ATOMIC))) { @@ -1110,7 +1283,7 @@ return FALSE; } - if (! (HD(j)->sp_cpu_addr = pci_alloc_consistent(HD(j)->pdev, + if (! (HD(j)->sp_cpu_addr = pci_alloc_consistent(HD(j)->pdev, sizeof(struct mssp), &HD(j)->sp_dma_addr))) { printk("%s: pci_alloc_consistent failed, detaching.\n", BN(j)); eata2x_release(sh[j]); @@ -1132,9 +1305,11 @@ if (j == 0) { printk("EATA/DMA 2.0x: Copyright (C) 1994-2002 Dario Ballabio.\n"); - printk("%s config options -> tc:%c, lc:%c, mq:%d, rs:%c, et:%c.\n", - driver_name, tag_type, YESNO(linked_comm), max_queue_depth, - YESNO(rev_scan), YESNO(ext_tran)); + printk("%s config options -> tc:%c, lc:%c, mq:%d, rs:%c, et:%c, "\ + "ip:%c, ep:%c, pp:%c.\n", driver_name, tag_type, + YESNO(linked_comm), max_queue_depth, YESNO(rev_scan), + YESNO(ext_tran), YESNO(isa_probe), YESNO(eisa_probe), + YESNO(pci_probe)); } printk("%s: 2.0%c, %s 0x%03lx, IRQ %u, %s, SG %d, MB %d.\n", @@ -1153,8 +1328,8 @@ printk("%s: Vers. 0x%x, ocs %u, tar %u, trnxfr %u, more %u, SYNC 0x%x, "\ "sec. %u, infol %d, cpl %d spl %d.\n", name, info.version, info.ocsena, info.tarsup, info.trnxfr, info.morsup, info.sync, - info.second, DEV2H(info.data_len), DEV2H(info.cp_len), - DEV2H(info.sp_len)); + info.second, info.data_len, info.cp_len, + info.sp_len); if (protocol_rev == 'B' || protocol_rev == 'C') printk("%s: isaena %u, forcaddr %u, max_id %u, max_chan %u, "\ @@ -1204,6 +1379,9 @@ else if (!strncmp(cur, "ls:", 3)) link_statistics = val; else if (!strncmp(cur, "et:", 3)) ext_tran = val; else if (!strncmp(cur, "rs:", 3)) rev_scan = val; + else if (!strncmp(cur, "ip:", 3)) isa_probe = val; + else if (!strncmp(cur, "ep:", 3)) eisa_probe = val; + else if (!strncmp(cur, "pp:", 3)) pci_probe = val; if ((cur = strchr(cur, ','))) ++cur; } @@ -1285,7 +1463,19 @@ for (k = 0; k < MAX_BOARDS + 1; k++) sh[k] = NULL; - if (!setup_done) add_pci_ports(); + for (k = MAX_INT_PARAM; io_port[k]; k++) + if (io_port[k] == SKIP) continue; + else if (io_port[k] <= MAX_ISA_ADDR) { + if (!isa_probe) io_port[k] = SKIP; + } + else if (io_port[k] >= MIN_EISA_ADDR && io_port[k] <= MAX_EISA_ADDR) { + if (!eisa_probe) io_port[k] = SKIP; + } + + if (pci_probe) { + if (!setup_done) add_pci_ports(); + else enable_pci_ports(); + } for (k = 0; io_port[k]; k++) { @@ -1315,10 +1505,10 @@ if (!SCpnt->use_sg) { - if (!SCpnt->request_bufflen) - cpp->data_address = V2DEV(SCpnt->request_buffer); + /* If we get here with PCI_DMA_NONE, pci_map_single triggers a BUG() */ + if (!SCpnt->request_bufflen) pci_dir = PCI_DMA_BIDIRECTIONAL; - else if (SCpnt->request_buffer) + if (SCpnt->request_buffer) cpp->data_address = H2DEV(pci_map_single(HD(j)->pdev, SCpnt->request_buffer, SCpnt->request_bufflen, pci_dir)); @@ -1335,7 +1525,8 @@ } cpp->sg = TRUE; - cpp->data_address = V2DEV(cpp->sglist); + cpp->data_address = H2DEV(pci_map_single(HD(j)->pdev, cpp->sglist, + SCpnt->use_sg * sizeof(struct sg_list), pci_dir)); cpp->data_len = H2DEV((SCpnt->use_sg * sizeof(struct sg_list))); } @@ -1351,13 +1542,14 @@ pci_unmap_single(HD(j)->pdev, DEV2H(cpp->sense_addr), DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE); - if (SCpnt->use_sg) + if (SCpnt->use_sg) pci_unmap_sg(HD(j)->pdev, SCpnt->request_buffer, SCpnt->use_sg, pci_dir); - else if (DEV2H(cpp->data_address) && DEV2H(cpp->data_len)) - pci_unmap_single(HD(j)->pdev, DEV2H(cpp->data_address), - DEV2H(cpp->data_len), pci_dir); + if (!DEV2H(cpp->data_len)) pci_dir = PCI_DMA_BIDIRECTIONAL; + if (DEV2H(cpp->data_address)) + pci_unmap_single(HD(j)->pdev, DEV2H(cpp->data_address), + DEV2H(cpp->data_len), pci_dir); } static void sync_dma(unsigned int i, unsigned int j) { @@ -1372,14 +1564,15 @@ pci_dma_sync_single(HD(j)->pdev, DEV2H(cpp->sense_addr), DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE); - if (SCpnt->use_sg) - pci_dma_sync_sg(HD(j)->pdev, SCpnt->request_buffer, + if (SCpnt->use_sg) + pci_dma_sync_sg(HD(j)->pdev, SCpnt->request_buffer, SCpnt->use_sg, pci_dir); - else if (DEV2H(cpp->data_address) && DEV2H(cpp->data_len)) - pci_dma_sync_single(HD(j)->pdev, DEV2H(cpp->data_address), - DEV2H(cpp->data_len), pci_dir); + if (!DEV2H(cpp->data_len)) pci_dir = PCI_DMA_BIDIRECTIONAL; + if (DEV2H(cpp->data_address)) + pci_dma_sync_single(HD(j)->pdev, DEV2H(cpp->data_address), + DEV2H(cpp->data_len), pci_dir); } static inline void scsi_to_dev_dir(unsigned int i, unsigned int j) { @@ -1400,8 +1593,7 @@ struct mscp *cpp; Scsi_Cmnd *SCpnt; - cpp = &HD(j)->cp[i]; - SCpnt = cpp->SCpnt; + cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt; if (SCpnt->sc_data_direction == SCSI_DATA_READ) { cpp->din = TRUE; @@ -1419,7 +1611,7 @@ return; } - if (SCpnt->sc_data_direction != SCSI_DATA_UNKNOWN) + if (SCpnt->sc_data_direction != SCSI_DATA_UNKNOWN) panic("%s: qcomm, invalid SCpnt->sc_data_direction.\n", BN(j)); for (k = 0; k < ARRAY_SIZE(data_out_cmds); k++) @@ -1470,7 +1662,7 @@ /* Set pointer to control packet structure */ cpp = &HD(j)->cp[i]; - memset(cpp, 0, sizeof(struct mscp) - sizeof(struct sg_list *)); + memset(cpp, 0, sizeof(struct mscp) - CP_TAIL_SIZE); /* Set pointer to status packet structure, Big Endian format */ cpp->sp_dma_addr = H2DEV(HD(j)->sp_dma_addr); @@ -1527,7 +1719,7 @@ } /* Send control packet to the board */ - if (do_dma(sh[j]->io_port, (unsigned long) cpp, SEND_CP_DMA)) { + if (do_dma(sh[j]->io_port, cpp->cp_dma_addr, SEND_CP_DMA)) { unmap_dma(i, j); SCpnt->host_scribble = NULL; printk("%s: qcomm, target %d.%d:%d, pid %ld, adapter busy.\n", @@ -1926,7 +2118,7 @@ for (n = 0; n < n_ready; n++) { k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt; - if (do_dma(sh[j]->io_port, (unsigned long) cpp, SEND_CP_DMA)) { + if (do_dma(sh[j]->io_port, cpp->cp_dma_addr, SEND_CP_DMA)) { printk("%s: %s, target %d.%d:%d, pid %ld, mbox %d, adapter"\ " busy, will abort.\n", BN(j), (ihdlr ? "ihdlr" : "qcomm"), SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid, k); @@ -1975,8 +2167,21 @@ /* Read the status register to clear the interrupt indication */ reg = inb(sh[j]->io_port + REG_STATUS); +#if defined (DEBUG_INTERRUPT) + { + unsigned char *bytesp; + int cnt; + bytesp= (unsigned char *) spp; + if (HD(j)->iocount < 200) { + printk("sp[] ="); + for (cnt=0; cnt < 15; cnt++) printk(" 0x%x", bytesp[cnt]); + printk("\n"); + } + } +#endif + /* Reject any sp with supspect data */ - if (spp->eoc == FALSE) + if (spp->eoc == FALSE && HD(j)->iocount > 1) printk("%s: ihdlr, spp->eoc == FALSE, irq %d, reg 0x%x, count %d.\n", BN(j), irq, reg, HD(j)->iocount); if (spp->cpp_index < 0 || spp->cpp_index >= sh[j]->can_queue) @@ -2182,10 +2387,14 @@ for (i = 0; i < sh[j]->can_queue; i++) if ((&HD(j)->cp[i])->sglist) kfree((&HD(j)->cp[i])->sglist); - if (HD(j)->sp_cpu_addr) + for (i = 0; i < sh[j]->can_queue; i++) + pci_unmap_single(HD(j)->pdev, HD(j)->cp[i].cp_dma_addr, + sizeof(struct mscp), PCI_DMA_BIDIRECTIONAL); + + if (HD(j)->sp_cpu_addr) pci_free_consistent(HD(j)->pdev, sizeof(struct mssp), HD(j)->sp_cpu_addr, HD(j)->sp_dma_addr); - + free_irq(sh[j]->irq, &sha[j]); if (sh[j]->dma_channel != NO_DMA) free_dma(sh[j]->dma_channel); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/eata.h linux.19rc3-ac4/drivers/scsi/eata.h --- linux.19rc3/drivers/scsi/eata.h 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/eata.h 2002-07-29 13:58:43.000000000 +0100 @@ -13,7 +13,7 @@ int eata2x_reset(Scsi_Cmnd *); int eata2x_biosparam(Disk *, kdev_t, int *); -#define EATA_VERSION "6.50.00" +#define EATA_VERSION "6.70.00" #define EATA { \ name: "EATA/DMA 2.0x rev. " EATA_VERSION " ", \ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/esp.c linux.19rc3-ac4/drivers/scsi/esp.c --- linux.19rc3/drivers/scsi/esp.c 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/esp.c 2002-07-29 13:58:43.000000000 +0100 @@ -378,7 +378,7 @@ #endif #ifdef DEBUG_ESP_CMDS -extern inline void esp_cmd(struct esp *esp, u8 cmd) +static inline void esp_cmd(struct esp *esp, u8 cmd) { esp->espcmdlog[esp->espcmdent] = cmd; esp->espcmdent = (esp->espcmdent + 1) & 31; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/hosts.c linux.19rc3-ac4/drivers/scsi/hosts.c --- linux.19rc3/drivers/scsi/hosts.c 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/hosts.c 2002-07-29 15:19:03.000000000 +0100 @@ -81,8 +81,8 @@ struct Scsi_Host * scsi_hostlist; struct Scsi_Device_Template * scsi_devicelist; -int max_scsi_hosts; -int next_scsi_host; +int max_scsi_hosts; /* host_no for next new host */ +int next_scsi_host; /* count of registered scsi hosts */ void scsi_unregister(struct Scsi_Host * sh){ @@ -107,21 +107,8 @@ if (shn) shn->host_registered = 0; /* else {} : This should not happen, we should panic here... */ - /* If we are removing the last host registered, it is safe to reuse - * its host number (this avoids "holes" at boot time) (DB) - * It is also safe to reuse those of numbers directly below which have - * been released earlier (to avoid some holes in numbering). - */ - if(sh->host_no == max_scsi_hosts - 1) { - while(--max_scsi_hosts >= next_scsi_host) { - shpnt = scsi_hostlist; - while(shpnt && shpnt->host_no != max_scsi_hosts - 1) - shpnt = shpnt->next; - if(shpnt) - break; - } - } next_scsi_host--; + kfree((char *) sh); } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/hosts.h linux.19rc3-ac4/drivers/scsi/hosts.h --- linux.19rc3/drivers/scsi/hosts.h 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/hosts.h 2002-07-29 17:29:11.000000000 +0100 @@ -292,6 +292,11 @@ unsigned emulated:1; /* + * True for drivers which can handle variable length IO + */ + unsigned can_do_varyio:1; + + /* * Name of proc directory */ char *proc_name; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/ide-scsi.c linux.19rc3-ac4/drivers/scsi/ide-scsi.c --- linux.19rc3/drivers/scsi/ide-scsi.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/ide-scsi.c 2002-07-29 13:58:43.000000000 +0100 @@ -27,6 +27,7 @@ * detection of devices with CONFIG_SCSI_MULTI_LUN * Ver 0.8 Feb 05 99 Optical media need translation too. Reverse 0.7. * Ver 0.9 Jul 04 99 Fix a bug in SG_SET_TRANSFORM. + * Ver 0.91 Jun 10 02 Fix "off by one" error in transforms */ #define IDESCSI_VERSION "0.9" @@ -53,76 +54,77 @@ #include "ide-scsi.h" #include -#define IDESCSI_DEBUG_LOG 0 +#define IDESCSI_DEBUG_LOG 0 typedef struct idescsi_pc_s { - u8 c[12]; /* Actual packet bytes */ - int request_transfer; /* Bytes to transfer */ - int actually_transferred; /* Bytes actually transferred */ - int buffer_size; /* Size of our data buffer */ - struct request *rq; /* The corresponding request */ - byte *buffer; /* Data buffer */ - byte *current_position; /* Pointer into the above buffer */ - struct scatterlist *sg; /* Scatter gather table */ - int b_count; /* Bytes transferred from current entry */ - Scsi_Cmnd *scsi_cmd; /* SCSI command */ - void (*done)(Scsi_Cmnd *); /* Scsi completion routine */ - unsigned long flags; /* Status/Action flags */ - unsigned long timeout; /* Command timeout */ + u8 c[12]; /* Actual packet bytes */ + int request_transfer; /* Bytes to transfer */ + int actually_transferred; /* Bytes actually transferred */ + int buffer_size; /* Size of our data buffer */ + struct request *rq; /* The corresponding request */ + byte *buffer; /* Data buffer */ + byte *current_position; /* Pointer into the above buffer */ + struct scatterlist *sg; /* Scatter gather table */ + int b_count; /* Bytes transferred from current entry */ + Scsi_Cmnd *scsi_cmd; /* SCSI command */ + void (*done)(Scsi_Cmnd *); /* Scsi completion routine */ + unsigned long flags; /* Status/Action flags */ + unsigned long timeout; /* Command timeout */ } idescsi_pc_t; /* * Packet command status bits. */ -#define PC_DMA_IN_PROGRESS 0 /* 1 while DMA in progress */ -#define PC_WRITING 1 /* Data direction */ -#define PC_TRANSFORM 2 /* transform SCSI commands */ +#define PC_DMA_IN_PROGRESS 0 /* 1 while DMA in progress */ +#define PC_WRITING 1 /* Data direction */ +#define PC_TRANSFORM 2 /* transform SCSI commands */ /* * SCSI command transformation layer */ -#define IDESCSI_TRANSFORM 0 /* Enable/Disable transformation */ -#define IDESCSI_SG_TRANSFORM 1 /* /dev/sg transformation */ +#define IDESCSI_TRANSFORM 0 /* Enable/Disable transformation */ +#define IDESCSI_SG_TRANSFORM 1 /* /dev/sg transformation */ /* * Log flags */ -#define IDESCSI_LOG_CMD 0 /* Log SCSI commands */ +#define IDESCSI_LOG_CMD 0 /* Log SCSI commands */ typedef struct { ide_drive_t *drive; - idescsi_pc_t *pc; /* Current packet command */ - unsigned long flags; /* Status/Action flags */ - unsigned long transform; /* SCSI cmd translation layer */ - unsigned long log; /* log flags */ + idescsi_pc_t *pc; /* Current packet command */ + unsigned long flags; /* Status/Action flags */ + unsigned long transform; /* SCSI cmd translation layer */ + unsigned long log; /* log flags */ + devfs_handle_t de; /* pointer to IDE device */ } idescsi_scsi_t; /* * Per ATAPI device status bits. */ -#define IDESCSI_DRQ_INTERRUPT 0 /* DRQ interrupt device */ +#define IDESCSI_DRQ_INTERRUPT 0 /* DRQ interrupt device */ /* * ide-scsi requests. */ -#define IDESCSI_PC_RQ 90 +#define IDESCSI_PC_RQ 90 /* * Bits of the interrupt reason register. */ -#define IDESCSI_IREASON_COD 0x1 /* Information transferred is command */ -#define IDESCSI_IREASON_IO 0x2 /* The device requests us to read */ +#define IDESCSI_IREASON_COD 0x1 /* Information transferred is command */ +#define IDESCSI_IREASON_IO 0x2 /* The device requests us to read */ static void idescsi_discard_data (ide_drive_t *drive, unsigned int bcount) { while (bcount--) - IN_BYTE (IDE_DATA_REG); + IN_BYTE(IDE_DATA_REG); } static void idescsi_output_zeros (ide_drive_t *drive, unsigned int bcount) { while (bcount--) - OUT_BYTE (0, IDE_DATA_REG); + OUT_BYTE(0, IDE_DATA_REG); } /* @@ -181,26 +183,38 @@ return; if (drive->media == ide_cdrom || drive->media == ide_optical) { if (c[0] == READ_6 || c[0] == WRITE_6) { - c[8] = c[4]; c[5] = c[3]; c[4] = c[2]; - c[3] = c[1] & 0x1f; c[2] = 0; c[1] &= 0xe0; + c[8] = c[4]; + c[5] = c[3]; + c[4] = c[2]; + c[3] = c[1] & 0x1f; + c[2] = 0; + c[1] &= 0xe0; c[0] += (READ_10 - READ_6); } if (c[0] == MODE_SENSE || c[0] == MODE_SELECT) { + unsigned short new_len; if (!scsi_buf) return; if ((atapi_buf = kmalloc(pc->buffer_size + 4, GFP_ATOMIC)) == NULL) return; memset(atapi_buf, 0, pc->buffer_size + 4); memset (c, 0, 12); - c[0] = sc[0] | 0x40; c[1] = sc[1]; c[2] = sc[2]; - c[8] = sc[4] + 4; c[9] = sc[5]; - if (sc[4] + 4 > 255) - c[7] = sc[4] + 4 - 255; + c[0] = sc[0] | 0x40; + c[1] = sc[1]; + c[2] = sc[2]; + new_len = sc[4] + 4; + c[8] = new_len; + c[9] = sc[5]; + c[7] = new_len >> 8; if (c[0] == MODE_SELECT_10) { - atapi_buf[1] = scsi_buf[0]; /* Mode data length */ - atapi_buf[2] = scsi_buf[1]; /* Medium type */ - atapi_buf[3] = scsi_buf[2]; /* Device specific parameter */ - atapi_buf[7] = scsi_buf[3]; /* Block descriptor length */ + /* Mode data length */ + atapi_buf[1] = scsi_buf[0]; + /* Medium type */ + atapi_buf[2] = scsi_buf[1]; + /* Device specific parameter */ + atapi_buf[3] = scsi_buf[2]; + /* Block descriptor length */ + atapi_buf[7] = scsi_buf[3]; memcpy(atapi_buf + 8, scsi_buf + 4, pc->buffer_size - 4); } pc->buffer = atapi_buf; @@ -220,15 +234,21 @@ return; if (drive->media == ide_cdrom || drive->media == ide_optical) { if (pc->c[0] == MODE_SENSE_10 && sc[0] == MODE_SENSE) { - scsi_buf[0] = atapi_buf[1]; /* Mode data length */ - scsi_buf[1] = atapi_buf[2]; /* Medium type */ - scsi_buf[2] = atapi_buf[3]; /* Device specific parameter */ - scsi_buf[3] = atapi_buf[7]; /* Block descriptor length */ + /* Mode data length */ + scsi_buf[0] = atapi_buf[1]; + /* Medium type */ + scsi_buf[1] = atapi_buf[2]; + /* Device specific parameter */ + scsi_buf[2] = atapi_buf[3]; + /* Block descriptor length */ + scsi_buf[3] = atapi_buf[7]; memcpy(scsi_buf + 4, atapi_buf + 8, pc->request_transfer - 8); } if (pc->c[0] == INQUIRY) { - scsi_buf[2] |= 2; /* ansi_revision */ - scsi_buf[3] = (scsi_buf[3] & 0xf0) | 2; /* response data format */ + /* ansi_revision */ + scsi_buf[2] |= 2; + /* response data format */ + scsi_buf[3] = (scsi_buf[3] & 0xf0) | 2; } } if (atapi_buf && atapi_buf != scsi_buf) @@ -256,34 +276,65 @@ printk("]\n"); } -static void idescsi_end_request (byte uptodate, ide_hwgroup_t *hwgroup) +static int idescsi_do_end_request (ide_drive_t *drive, int uptodate) +{ + struct request *rq; + unsigned long flags; + int ret = 1; + + spin_lock_irqsave(&io_request_lock, flags); + rq = HWGROUP(drive)->rq; + + /* + * decide whether to reenable DMA -- 3 is a random magic for now, + * if we DMA timeout more than 3 times, just stay in PIO + */ + if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) { + drive->state = 0; + HWGROUP(drive)->hwif->dmaproc(ide_dma_on, drive); + } + + if (!end_that_request_first(rq, uptodate, drive->name)) { + add_blkdev_randomness(MAJOR(rq->rq_dev)); + blkdev_dequeue_request(rq); + HWGROUP(drive)->rq = NULL; + end_that_request_last(rq); + ret = 0; + } + spin_unlock_irqrestore(&io_request_lock, flags); + return ret; +} + +static int idescsi_end_request (ide_drive_t *drive, int uptodate) { - ide_drive_t *drive = hwgroup->drive; idescsi_scsi_t *scsi = drive->driver_data; - struct request *rq = hwgroup->rq; + struct request *rq = HWGROUP(drive)->rq; idescsi_pc_t *pc = (idescsi_pc_t *) rq->buffer; int log = test_bit(IDESCSI_LOG_CMD, &scsi->log); u8 *scsi_buf; unsigned long flags; if (rq->cmd != IDESCSI_PC_RQ) { - ide_end_request (uptodate, hwgroup); - return; + idescsi_do_end_request(drive, uptodate); + return 0; } ide_end_drive_cmd (drive, 0, 0); if (rq->errors >= ERROR_MAX) { pc->scsi_cmd->result = DID_ERROR << 16; if (log) - printk ("ide-scsi: %s: I/O error for %lu\n", drive->name, pc->scsi_cmd->serial_number); + printk ("ide-scsi: %s: I/O error for %lu\n", + drive->name, pc->scsi_cmd->serial_number); } else if (rq->errors) { pc->scsi_cmd->result = (CHECK_CONDITION << 1) | (DID_OK << 16); if (log) - printk ("ide-scsi: %s: check condition for %lu\n", drive->name, pc->scsi_cmd->serial_number); + printk ("ide-scsi: %s: check condition for %lu\n", + drive->name, pc->scsi_cmd->serial_number); } else { pc->scsi_cmd->result = DID_OK << 16; idescsi_transform_pc2 (drive, pc); if (log) { - printk ("ide-scsi: %s: suc %lu", drive->name, pc->scsi_cmd->serial_number); + printk ("ide-scsi: %s: suc %lu", drive->name, + pc->scsi_cmd->serial_number); if (!test_bit(PC_WRITING, &pc->flags) && pc->actually_transferred && pc->actually_transferred <= 1024 && pc->buffer) { printk(", rst = "); scsi_buf = pc->scsi_cmd->request_buffer; @@ -297,6 +348,7 @@ idescsi_free_bh (rq->bh); kfree(pc); kfree(rq); scsi->pc = NULL; + return 0; } static inline unsigned long get_timeout(idescsi_pc_t *pc) @@ -328,23 +380,23 @@ (void) (HWIF(drive)->dmaproc(ide_dma_end, drive)); } - status = GET_STAT(); /* Clear the interrupt */ + status = GET_STAT(); /* Clear the interrupt */ if ((status & DRQ_STAT) == 0) { /* No more interrupts */ if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) printk (KERN_INFO "Packet command completed, %d bytes transferred\n", pc->actually_transferred); - ide__sti(); + local_irq_enable(); if (status & ERR_STAT) rq->errors++; - idescsi_end_request (1, HWGROUP(drive)); + idescsi_end_request(drive, 1); return ide_stopped; } - bcount = IN_BYTE (IDE_BCOUNTH_REG) << 8 | IN_BYTE (IDE_BCOUNTL_REG); - ireason = IN_BYTE (IDE_IREASON_REG); + bcount = IN_BYTE(IDE_BCOUNTH_REG) << 8 | IN_BYTE(IDE_BCOUNTL_REG); + ireason = IN_BYTE(IDE_IREASON_REG); if (ireason & IDESCSI_IREASON_COD) { printk (KERN_ERR "ide-scsi: CoD != 0 in idescsi_pc_intr\n"); - return ide_do_reset (drive); + return ide_do_reset(drive); } if (ireason & IDESCSI_IREASON_IO) { temp = pc->actually_transferred + bcount; @@ -362,7 +414,9 @@ } pc->actually_transferred += temp; pc->current_position += temp; - idescsi_discard_data (drive,bcount - temp); + idescsi_discard_data(drive,bcount - temp); + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), NULL); return ide_started; } @@ -374,24 +428,26 @@ if (ireason & IDESCSI_IREASON_IO) { clear_bit(PC_WRITING, &pc->flags); if (pc->sg) - idescsi_input_buffers (drive, pc, bcount); + idescsi_input_buffers(drive, pc, bcount); else - atapi_input_bytes (drive,pc->current_position,bcount); + atapi_input_bytes(drive,pc->current_position,bcount); } else { set_bit(PC_WRITING, &pc->flags); if (pc->sg) - idescsi_output_buffers (drive, pc, bcount); + idescsi_output_buffers(drive, pc, bcount); else - atapi_output_bytes (drive,pc->current_position,bcount); + atapi_output_bytes(drive,pc->current_position,bcount); } - pc->actually_transferred+=bcount; /* Update the current position */ + pc->actually_transferred+=bcount; /* Update the current position */ pc->current_position+=bcount; + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), NULL); /* And set the interrupt handler again */ return ide_started; } -static ide_startstop_t idescsi_transfer_pc (ide_drive_t *drive) +static ide_startstop_t idescsi_transfer_pc(ide_drive_t *drive) { idescsi_scsi_t *scsi = drive->driver_data; idescsi_pc_t *pc = scsi->pc; @@ -399,16 +455,19 @@ ide_startstop_t startstop; if (ide_wait_stat (&startstop,drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) { - printk (KERN_ERR "ide-scsi: Strange, packet command initiated yet DRQ isn't asserted\n"); + printk (KERN_ERR "ide-scsi: Strange, packet command " \ + "initiated yet DRQ isn't asserted\n"); return startstop; } - ireason = IN_BYTE (IDE_IREASON_REG); + ireason = IN_BYTE(IDE_IREASON_REG); if ((ireason & (IDESCSI_IREASON_IO | IDESCSI_IREASON_COD)) != IDESCSI_IREASON_COD) { printk (KERN_ERR "ide-scsi: (IO,CoD) != (0,1) while issuing a packet command\n"); - return ide_do_reset (drive); + return ide_do_reset(drive); } + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), NULL); /* Set the interrupt routine */ - atapi_output_bytes (drive, scsi->pc->c, 12); /* Send the actual packet */ + atapi_output_bytes(drive, scsi->pc->c, 12); /* Send the actual packet */ return ide_started; } @@ -422,31 +481,36 @@ struct request *rq = pc->rq; int dma_ok = 0; - scsi->pc=pc; /* Set the current packet command */ - pc->actually_transferred=0; /* We haven't transferred any data yet */ + /* Set the current packet command */ + scsi->pc=pc; + /* We haven't transferred any data yet */ + pc->actually_transferred=0; pc->current_position=pc->buffer; - bcount = IDE_MIN (pc->request_transfer, 63 * 1024); /* Request to transfer the entire buffer at once */ + /* Request to transfer the entire buffer at once */ + bcount = IDE_MIN (pc->request_transfer, 63 * 1024); if (drive->using_dma && rq->bh) dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive); SELECT_DRIVE(HWIF(drive), drive); if (IDE_CONTROL_REG) - OUT_BYTE (drive->ctl,IDE_CONTROL_REG); - OUT_BYTE (dma_ok,IDE_FEATURE_REG); - OUT_BYTE (bcount >> 8,IDE_BCOUNTH_REG); - OUT_BYTE (bcount & 0xff,IDE_BCOUNTL_REG); + OUT_BYTE(drive->ctl,IDE_CONTROL_REG); + OUT_BYTE(dma_ok,IDE_FEATURE_REG); + OUT_BYTE(bcount >> 8,IDE_BCOUNTH_REG); + OUT_BYTE(bcount & 0xff,IDE_BCOUNTL_REG); if (dma_ok) { set_bit (PC_DMA_IN_PROGRESS, &pc->flags); (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive)); } if (test_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags)) { + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler (drive, &idescsi_transfer_pc, get_timeout(pc), NULL); - OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* Issue the packet command */ + OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); /* Issue the packet command */ return ide_started; } else { - OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); + OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); return idescsi_transfer_pc (drive); } } @@ -465,7 +529,7 @@ return idescsi_issue_pc (drive, (idescsi_pc_t *) rq->buffer); } printk (KERN_ERR "ide-scsi: %s: unsupported command in request queue (%x)\n", drive->name, rq->cmd); - idescsi_end_request (0,HWGROUP (drive)); + idescsi_end_request(drive, 0); return ide_stopped; } @@ -502,6 +566,8 @@ */ static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi, int id) { + int minor = (drive->select.b.unit) << PARTN_BITS; + DRIVER(drive)->busy++; idescsi_drives[id] = drive; drive->driver_data = scsi; @@ -516,6 +582,10 @@ set_bit(IDESCSI_LOG_CMD, &scsi->log); #endif /* IDESCSI_DEBUG_LOG */ idescsi_add_settings(drive); + scsi->de = devfs_register(drive->de, "generic", DEVFS_FL_DEFAULT, + HWIF(drive)->major, minor, + S_IFBLK | S_IRUSR | S_IWUSR, + ide_fops, NULL); } static int idescsi_cleanup (ide_drive_t *drive) @@ -524,11 +594,14 @@ if (ide_unregister_subdriver (drive)) return 1; + if (scsi->de) + devfs_unregister(scsi->de); drive->driver_data = NULL; kfree (scsi); return 0; } +int idescsi_init (void); int idescsi_reinit(ide_drive_t *drive); /* @@ -539,13 +612,21 @@ version: IDESCSI_VERSION, media: ide_scsi, busy: 0, +#ifdef CONFIG_IDEDMA_ONLYDISK + supports_dma: 0, +#else supports_dma: 1, +#endif supports_dsc_overlap: 0, cleanup: idescsi_cleanup, standby: NULL, + suspend: NULL, + resume: NULL, flushcache: NULL, do_request: idescsi_do_request, end_request: idescsi_end_request, + sense: NULL, + error: NULL, ioctl: NULL, open: idescsi_open, release: idescsi_ide_release, @@ -555,12 +636,12 @@ capacity: NULL, special: NULL, proc: NULL, + init: idescsi_init, reinit: idescsi_reinit, ata_prebuilder: NULL, atapi_prebuilder: NULL, }; -int idescsi_init (void); static ide_module_t idescsi_module = { IDE_DRIVER_MODULE, idescsi_init, diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/lasi700.c linux.19rc3-ac4/drivers/scsi/lasi700.c --- linux.19rc3/drivers/scsi/lasi700.c 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/lasi700.c 2002-07-29 13:58:43.000000000 +0100 @@ -152,12 +152,6 @@ return 1; } memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters)); - if(request_mem_region(base, 64, driver_name) == NULL) { - printk(KERN_ERR "%s: Failed to claim memory region\n", - driver_name); - kfree(hostdata); - return 1; - } hostdata->base = base; hostdata->differential = 0; if(dev->id.sversion == LASI_700_SVERSION) { @@ -172,7 +166,6 @@ hostdata->pci_dev = ccio_get_fake(dev); if((host = NCR_700_detect(host_tpnt, hostdata)) == NULL) { kfree(hostdata); - release_mem_region(host->base, 64); return 1; } host->irq = dev->irq; @@ -196,7 +189,6 @@ NCR_700_release(host); kfree(hostdata); free_irq(host->irq, host); - release_mem_region(host->base, 64); unregister_parisc_driver(&lasi700_driver); return 1; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/Makefile linux.19rc3-ac4/drivers/scsi/Makefile --- linux.19rc3/drivers/scsi/Makefile 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/Makefile 2002-07-29 13:58:43.000000000 +0100 @@ -118,6 +118,7 @@ obj-$(CONFIG_SCSI_PLUTO) += pluto.o obj-$(CONFIG_SCSI_DECNCR) += NCR53C9x.o dec_esp.o obj-$(CONFIG_BLK_DEV_3W_XXXX_RAID) += 3w-xxxx.o +obj-$(CONFIG_SCSI_ZALON) += zalon7xx_mod.o obj-$(CONFIG_SCSI_PPA) += ppa.o obj-$(CONFIG_SCSI_IMM) += imm.o obj-$(CONFIG_JAZZ_ESP) += NCR53C9x.o jazz_esp.o @@ -136,7 +137,8 @@ obj-$(CONFIG_BLK_DEV_SR) += sr_mod.o obj-$(CONFIG_CHR_DEV_SG) += sg.o -list-multi := scsi_mod.o sd_mod.o sr_mod.o initio.o a100u2w.o cpqfc.o +list-multi := scsi_mod.o sd_mod.o sr_mod.o initio.o a100u2w.o cpqfc.o \ + zalon7xx_mod.o scsi_mod-objs := scsi.o hosts.o scsi_ioctl.o constants.o \ scsicam.o scsi_proc.o scsi_error.o \ scsi_obsolete.o scsi_queue.o scsi_lib.o \ @@ -146,6 +148,7 @@ sr_mod-objs := sr.o sr_ioctl.o sr_vendor.o initio-objs := ini9100u.o i91uscsi.o a100u2w-objs := inia100.o i60uscsi.o +zalon7xx_mod-objs := zalon7xx.o ncr53c8xx.o cpqfc-objs := cpqfcTSinit.o cpqfcTScontrol.o cpqfcTSi2c.o \ cpqfcTSworker.o cpqfcTStrigger.o @@ -167,6 +170,9 @@ a100u2w.o: $(a100u2w-objs) $(LD) -r -o $@ $(a100u2w-objs) +zalon7xx_mod.o: $(zalon7xx_mod-objs) + $(LD) -r -o $@ $(zalon7xx_mod-objs) + cpqfc.o: $(cpqfc-objs) $(LD) -r -o $@ $(cpqfc-objs) @@ -183,7 +189,7 @@ 53c7xx_d.h: 53c7xx.scr script_asm.pl ln -sf 53c7xx.scr fake7.c - $(CPP) $(CPPFLAGS) -traditional -DCHIP=710 fake7.c | grep -v '^#' | $(PERL) -s script_asm.pl -ncr7x0_family + $(CPP) $(CPPFLAGS) -traditional -DCHIP=710 fake7.c | grep -v '^#' | $(PERL) -s script_asm.pl -ncr710 mv script.h 53c7xx_d.h mv scriptu.h 53c7xx_u.h rm fake7.c @@ -194,7 +200,7 @@ sim710_d.h: sim710.scr script_asm.pl ln -sf sim710.scr fake7.c - $(CPP) $(CPPFLAGS) -traditional -DCHIP=710 fake7.c | grep -v '^#' | $(PERL) -s script_asm.pl -ncr7x0_family + $(CPP) $(CPPFLAGS) -traditional -DCHIP=710 fake7.c | grep -v '^#' | $(PERL) -s script_asm.pl -ncr710 mv script.h sim710_d.h mv scriptu.h sim710_u.h rm fake7.c diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/ncr53c8xx.c linux.19rc3-ac4/drivers/scsi/ncr53c8xx.c --- linux.19rc3/drivers/scsi/ncr53c8xx.c 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/ncr53c8xx.c 2002-07-29 13:58:43.000000000 +0100 @@ -7185,7 +7185,7 @@ ** ** Possible cases: hs sir msg_in value send goto ** We try to negotiate: -** -> target doesnt't msgin NEG FAIL noop defa. - dispatch +** -> target doesn't msgin NEG FAIL noop defa. - dispatch ** -> target rejected our msg NEG FAIL reject defa. - dispatch ** -> target answered (ok) NEG SYNC sdtr set - clrack ** -> target answered (!ok) NEG SYNC sdtr defa. REJ--->msg_bad diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/NCR53C9x.c linux.19rc3-ac4/drivers/scsi/NCR53C9x.c --- linux.19rc3/drivers/scsi/NCR53C9x.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/NCR53C9x.c 2002-07-29 13:58:43.000000000 +0100 @@ -289,7 +289,7 @@ #endif #ifdef DEBUG_ESP_CMDS -extern inline void esp_cmd(struct NCR_ESP *esp, struct ESP_regs *eregs, +inline void esp_cmd(struct NCR_ESP *esp, struct ESP_regs *eregs, unchar cmd) { esp->espcmdlog[esp->espcmdent] = cmd; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/qlogicisp.h linux.19rc3-ac4/drivers/scsi/qlogicisp.h --- linux.19rc3/drivers/scsi/qlogicisp.h 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/qlogicisp.h 2002-07-29 13:58:43.000000000 +0100 @@ -84,7 +84,8 @@ cmd_per_lun: 1, \ present: 0, \ unchecked_isa_dma: 0, \ - use_clustering: DISABLE_CLUSTERING \ + use_clustering: DISABLE_CLUSTERING, \ + can_do_varyio: 1 \ } #endif /* _QLOGICISP_H */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/script_asm.pl linux.19rc3-ac4/drivers/scsi/script_asm.pl --- linux.19rc3/drivers/scsi/script_asm.pl 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/script_asm.pl 2002-07-29 13:58:43.000000000 +0100 @@ -12,6 +12,7 @@ # # Support for 53c710 (via -ncr7x0_family switch) added by Richard # Hirst - 15th March 1997 +# Renamed to -ncr7x0_family to -ncr710, and added -ncr700 - 5th May 2000. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -77,7 +78,7 @@ # and = 0x04_00_00_00 # add = 0x06_00_00_00 -if ($ncr7x0_family) { +if ($ncr700 || $ncr710) { %operators = ( '|', 0x02_00_00_00, 'OR', 0x02_00_00_00, '&', 0x04_00_00_00, 'AND', 0x04_00_00_00, @@ -99,7 +100,24 @@ # Table of register addresses -if ($ncr7x0_family) { +if ($ncr700) { + %registers = ( + 'SCNTL0', 0, 'SCNTL1', 1, 'SDID', 2, 'SIEN', 3, + 'SCID', 4, 'SXFER', 5, 'SODL', 6, 'SOCL', 7, + 'SFBR', 8, 'SIDL', 9, 'SBDL', 10, 'SBCL', 11, + 'DSTAT', 12, 'SSTAT0', 13, 'SSTAT1', 14, 'SSTAT2', 15, + 'CTEST0', 20, 'CTEST1', 21, 'CTEST2', 22, 'CTEST3', 23, + 'CTEST4', 24, 'CTEST5', 25, 'CTEST6', 26, 'CTEST7', 27, + 'TEMP0', 28, 'TEMP1', 29, 'TEMP2', 30, 'TEMP3', 31, + 'DFIFO', 32, 'ISTAT', 33, 'CTEST8', 34, + 'DBC0', 36, 'DBC1', 37, 'DBC2', 38, 'DCMD', 39, + 'DNAD0', 40, 'DNAD1', 41, 'DNAD2', 42, 'DNAD3', 43, + 'DSP0', 44, 'DSP1', 45, 'DSP2', 46, 'DSP3', 47, + 'DSPS0', 48, 'DSPS1', 49, 'DSPS2', 50, 'DSPS3', 51, + 'DMODE', 52, 'DIEN', 57, 'DWT', 58, 'DCNTL', 59, + ); +} +elsif ($ncr710) { %registers = ( 'SCNTL0', 0, 'SCNTL1', 1, 'SDID', 2, 'SIEN', 3, 'SCID', 4, 'SXFER', 5, 'SODL', 6, 'SOCL', 7, @@ -171,7 +189,7 @@ # be escaped, I can't use the join() trick I used for the register # regex -if ($ncr7x0_family) { +if ($ncr700 || $ncr710) { $operator = '\||OR|AND|\&|\+'; } else { @@ -468,7 +486,7 @@ # Process MOVE length, address, WITH|WHEN phase instruction } elsif (/^\s*MOVE\s+(.*)/i) { $rest = $1; - if ($rest =~ /^FROM\s+($value)\s*,\s*(WITH|WHEN)\s+($phase)\s*$/i) { + if (!$ncr700 && ($rest =~ /^FROM\s+($value)\s*,\s*(WITH|WHEN)\s+($phase)\s*$/i)) { $transfer_addr = $1; $with_when = $2; $scsi_phase = $3; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/scsi.c linux.19rc3-ac4/drivers/scsi/scsi.c --- linux.19rc3/drivers/scsi/scsi.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/scsi.c 2002-07-29 13:58:43.000000000 +0100 @@ -349,8 +349,9 @@ int interruptable) { struct Scsi_Host *host; - Scsi_Cmnd *SCpnt = NULL; + Scsi_Cmnd *SCpnt; Scsi_Device *SDpnt; + struct list_head *lp; unsigned long flags; if (!device) @@ -361,7 +362,6 @@ spin_lock_irqsave(&device_request_lock, flags); while (1 == 1) { - SCpnt = NULL; if (!device->device_blocked) { if (device->single_lun) { /* @@ -401,26 +401,21 @@ * If asked to wait, we need to wait, otherwise * return NULL. */ - SCpnt = NULL; goto busy; } } /* - * Now we can check for a free command block for this device. + * Is there a free command block for this device? */ - for (SCpnt = device->device_queue; SCpnt; SCpnt = SCpnt->next) { - if (SCpnt->request.rq_status == RQ_INACTIVE) - break; - } + if (!list_empty(&device->sdev_free_q)) + goto found; } + /* - * If we couldn't find a free command block, and we have been + * Couldn't find a free command block, and we have been * asked to wait, then do so. */ - if (SCpnt) { - break; - } - busy: +busy: /* * If we have been asked to wait for a free block, then * wait here. @@ -472,12 +467,20 @@ return NULL; } } + continue; } else { spin_unlock_irqrestore(&device_request_lock, flags); return NULL; } } +found: + lp = device->sdev_free_q.next; + list_del(lp); + SCpnt = list_entry(lp, Scsi_Cmnd, sc_list); + if (SCpnt->request.rq_status != RQ_INACTIVE) + BUG(); + SCpnt->request.rq_status = RQ_SCSI_BUSY; SCpnt->request.waiting = NULL; /* And no one is waiting for this * to complete */ @@ -523,6 +526,9 @@ SDpnt = SCpnt->device; + /* command is now free - add to list */ + list_add(&SCpnt->sc_list, &SDpnt->sdev_free_q); + SCpnt->request.rq_status = RQ_INACTIVE; SCpnt->state = SCSI_STATE_UNUSED; SCpnt->owner = SCSI_OWNER_NOBODY; @@ -1445,6 +1451,7 @@ spin_lock_irqsave(&device_request_lock, flags); for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCnext) { SDpnt->device_queue = SCnext = SCpnt->next; + list_del(&SCpnt->sc_list); kfree((char *) SCpnt); } SDpnt->has_cmdblocks = 0; @@ -1481,6 +1488,7 @@ SDpnt->queue_depth = 1; /* live to fight another day */ } SDpnt->device_queue = NULL; + INIT_LIST_HEAD(&SDpnt->sdev_free_q); for (j = 0; j < SDpnt->queue_depth; j++) { SCpnt = (Scsi_Cmnd *) @@ -1510,6 +1518,7 @@ SDpnt->device_queue = SCpnt; SCpnt->state = SCSI_STATE_UNUSED; SCpnt->owner = SCSI_OWNER_NOBODY; + list_add(&SCpnt->sc_list, &SDpnt->sdev_free_q); } if (j < SDpnt->queue_depth) { /* low on space (D.Gilbert 990424) */ printk(KERN_WARNING "scsi_build_commandblocks: want=%d, space for=%d blocks\n", diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/scsi.h linux.19rc3-ac4/drivers/scsi/scsi.h --- linux.19rc3/drivers/scsi/scsi.h 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/scsi.h 2002-07-29 17:29:11.000000000 +0100 @@ -48,7 +48,7 @@ #if ((SCSI_DATA_UNKNOWN == PCI_DMA_BIDIRECTIONAL) && (SCSI_DATA_WRITE == PCI_DMA_TODEVICE) && (SCSI_DATA_READ == PCI_DMA_FROMDEVICE) && (SCSI_DATA_NONE == PCI_DMA_NONE)) #define scsi_to_pci_dma_dir(scsi_dir) ((int)(scsi_dir)) #else -extern __inline__ int scsi_to_pci_dma_dir(unsigned char scsi_dir) +static inline int scsi_to_pci_dma_dir(unsigned char scsi_dir) { if (scsi_dir == SCSI_DATA_UNKNOWN) return PCI_DMA_BIDIRECTIONAL; @@ -66,7 +66,7 @@ #if ((SCSI_DATA_UNKNOWN == SBUS_DMA_BIDIRECTIONAL) && (SCSI_DATA_WRITE == SBUS_DMA_TODEVICE) && (SCSI_DATA_READ == SBUS_DMA_FROMDEVICE) && (SCSI_DATA_NONE == SBUS_DMA_NONE)) #define scsi_to_sbus_dma_dir(scsi_dir) ((int)(scsi_dir)) #else -extern __inline__ int scsi_to_sbus_dma_dir(unsigned char scsi_dir) +static inline int scsi_to_sbus_dma_dir(unsigned char scsi_dir) { if (scsi_dir == SCSI_DATA_UNKNOWN) return SBUS_DMA_BIDIRECTIONAL; @@ -567,6 +567,7 @@ int (*scsi_init_io_fn) (Scsi_Cmnd *); /* Used to initialize new request */ Scsi_Cmnd *device_queue; /* queue of SCSI Command structures */ + struct list_head sdev_free_q; /* list of free cmds */ /* public: */ unsigned int id, lun, channel; @@ -784,6 +785,8 @@ * received on original command * (auto-sense) */ + struct list_head sc_list; /* Inactive cmd list linkage, guarded + * by device_request_lock. */ unsigned flags; /* diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/scsi_lib.c linux.19rc3-ac4/drivers/scsi/scsi_lib.c --- linux.19rc3/drivers/scsi/scsi_lib.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/scsi_lib.c 2002-07-29 13:58:43.000000000 +0100 @@ -702,7 +702,7 @@ switch (SCpnt->sense_buffer[2]) { case ILLEGAL_REQUEST: - if (SCpnt->device->ten) { + if (SCpnt->device->ten && SCSI_RETRY_10(SCpnt->cmnd[0])) { SCpnt->device->ten = 0; /* * This will cause a retry with a 6-byte diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/sd.c linux.19rc3-ac4/drivers/scsi/sd.c --- linux.19rc3/drivers/scsi/sd.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/sd.c 2002-07-29 13:58:43.000000000 +0100 @@ -95,6 +95,7 @@ static int *sd_blocksizes; static int *sd_hardsizes; /* Hardware sector size */ static int *sd_max_sectors; +static char *sd_varyio; static int check_scsidisk_media_change(kdev_t); static int fop_revalidate_scsidisk(kdev_t); @@ -1140,6 +1141,12 @@ if (!sd_max_sectors) goto cleanup_max_sectors; + sd_varyio = kmalloc((sd_template.dev_max << 4), GFP_ATOMIC); + if (!sd_varyio) + goto cleanup_varyio; + + memset(sd_varyio, 0, (sd_template.dev_max << 4)); + for (i = 0; i < sd_template.dev_max << 4; i++) { sd_blocksizes[i] = 1024; sd_hardsizes[i] = 512; @@ -1204,6 +1211,8 @@ kfree(sd_gendisks); sd_gendisks = NULL; cleanup_sd_gendisks: + kfree(sd_varyio); +cleanup_varyio: kfree(sd_max_sectors); cleanup_max_sectors: kfree(sd_hardsizes); @@ -1268,6 +1277,8 @@ return 1; } +#define SD_DISK_MAJOR(i) SD_MAJOR((i) >> 4) + static int sd_attach(Scsi_Device * SDp) { unsigned int devnum; @@ -1306,6 +1317,14 @@ printk("Attached scsi %sdisk %s at scsi%d, channel %d, id %d, lun %d\n", SDp->removable ? "removable " : "", nbuff, SDp->host->host_no, SDp->channel, SDp->id, SDp->lun); + + if (SDp->host->hostt->can_do_varyio) { + if (blkdev_varyio[SD_DISK_MAJOR(i)] == NULL) { + blkdev_varyio[SD_DISK_MAJOR(i)] = + sd_varyio + ((i / SCSI_DISKS_PER_MAJOR) << 8); + } + memset(blkdev_varyio[SD_DISK_MAJOR(i)] + (devnum << 4), 1, 16); + } return 0; } @@ -1438,6 +1457,7 @@ kfree(sd_sizes); kfree(sd_blocksizes); kfree(sd_hardsizes); + kfree(sd_varyio); for (i = 0; i < N_USED_SD_MAJORS; i++) { #if 0 /* XXX aren't we forgetting to deallocate something? */ kfree(sd_gendisks[i].de_arr); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/sd.h linux.19rc3-ac4/drivers/scsi/sd.h --- linux.19rc3/drivers/scsi/sd.h 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/sd.h 2002-07-29 17:29:12.000000000 +0100 @@ -24,13 +24,13 @@ #endif typedef struct scsi_disk { - unsigned capacity; /* size in blocks */ Scsi_Device *device; - unsigned char ready; /* flag ready for FLOPTICAL */ - unsigned char write_prot; /* flag write_protect for rmvable dev */ - unsigned char sector_bit_size; /* sector_size = 2 to the bit size power */ - unsigned char sector_bit_shift; /* power of 2 sectors per FS block */ + unsigned capacity; /* size in blocks */ + unsigned char sector_bit_size; /* sector_size = 2 to the bit size power */ + unsigned char sector_bit_shift; /* power of 2 sectors per FS block */ unsigned has_part_table:1; /* has partition table */ + unsigned ready:1; /* flag ready for FLOPTICAL */ + unsigned write_prot:1; /* flag write_protect for rmvable dev */ } Scsi_Disk; extern int revalidate_scsidisk(kdev_t dev, int maxusage); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/seagate.c linux.19rc3-ac4/drivers/scsi/seagate.c --- linux.19rc3/drivers/scsi/seagate.c 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/seagate.c 2002-07-29 13:58:43.000000000 +0100 @@ -21,7 +21,7 @@ * linux 2.1.112, simplified some #defines etc. * * Aug 2000 - aeb - deleted seagate_st0x_biosparam(). It would try to - * read the physical disk geometry, a bad mistake. Of course it doesnt + * read the physical disk geometry, a bad mistake. Of course it doesn't * matter much what geometry one invents, but on large disks it * returned 256 (or more) heads, causing all kind of failures. * Of course this means that people might see a different geometry now, diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/sim710_d.h linux.19rc3-ac4/drivers/scsi/sim710_d.h --- linux.19rc3/drivers/scsi/sim710_d.h 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/sim710_d.h 2002-07-29 13:58:43.000000000 +0100 @@ -18,15 +18,12 @@ ABSOLUTE reselected_identify = 0 ABSOLUTE msgin_buf = 0 +ABSOLUTE msg_reject = 0 +ABSOLUTE test1_src = 0 +ABSOLUTE test1_dst = 0 -ABSOLUTE int_bad_extmsg1a = 0xab930000 -ABSOLUTE int_bad_extmsg1b = 0xab930001 -ABSOLUTE int_bad_extmsg2a = 0xab930002 -ABSOLUTE int_bad_extmsg2b = 0xab930003 -ABSOLUTE int_bad_extmsg3a = 0xab930004 -ABSOLUTE int_bad_extmsg3b = 0xab930005 ABSOLUTE int_bad_msg1 = 0xab930006 ABSOLUTE int_bad_msg2 = 0xab930007 ABSOLUTE int_bad_msg3 = 0xab930008 @@ -50,7 +47,7 @@ ABSOLUTE int_disc2 = 0xab93001a ABSOLUTE int_disc3 = 0xab93001b ABSOLUTE int_not_rej = 0xab93001c - +ABSOLUTE int_test1 = 0xab93001d @@ -65,6 +62,9 @@ +ABSOLUTE did_reject = 0x01 + + @@ -74,1641 +74,1709 @@ at 0x00000000 : */ 0x60000200,0x00000000, /* - MOVE SCRATCH0 & 0 TO SCRATCH0 - -at 0x00000002 : */ 0x7c340000,0x00000000, -/* ; Enable selection timer MOVE CTEST7 & 0xef TO CTEST7 -at 0x00000004 : */ 0x7c1bef00,0x00000000, +at 0x00000002 : */ 0x7c1bef00,0x00000000, /* SELECT ATN FROM dsa_select, reselect -at 0x00000006 : */ 0x43000000,0x00000c48, +at 0x00000004 : */ 0x43000000,0x00000cd0, /* JUMP get_status, WHEN STATUS -at 0x00000008 : */ 0x830b0000,0x000000a0, +at 0x00000006 : */ 0x830b0000,0x00000098, /* ; Disable selection timer MOVE CTEST7 | 0x10 TO CTEST7 -at 0x0000000a : */ 0x7a1b1000,0x00000000, +at 0x00000008 : */ 0x7a1b1000,0x00000000, /* MOVE SCRATCH0 | had_select TO SCRATCH0 -at 0x0000000c : */ 0x7a340100,0x00000000, +at 0x0000000a : */ 0x7a340100,0x00000000, /* INT int_sel_no_ident, IF NOT MSG_OUT -at 0x0000000e : */ 0x9e020000,0xab930013, +at 0x0000000c : */ 0x9e020000,0xab930013, /* MOVE SCRATCH0 | had_msgout TO SCRATCH0 -at 0x00000010 : */ 0x7a340200,0x00000000, +at 0x0000000e : */ 0x7a340200,0x00000000, /* MOVE FROM dsa_msgout, when MSG_OUT -at 0x00000012 : */ 0x1e000000,0x00000008, +at 0x00000010 : */ 0x1e000000,0x00000008, /* ENTRY done_ident done_ident: JUMP get_status, IF STATUS -at 0x00000014 : */ 0x830a0000,0x000000a0, +at 0x00000012 : */ 0x830a0000,0x00000098, /* redo_msgin1: JUMP get_msgin1, WHEN MSG_IN -at 0x00000016 : */ 0x870b0000,0x00000920, +at 0x00000014 : */ 0x870b0000,0x00000918, /* INT int_sel_not_cmd, IF NOT CMD -at 0x00000018 : */ 0x9a020000,0xab930014, +at 0x00000016 : */ 0x9a020000,0xab930014, /* ENTRY resume_cmd resume_cmd: MOVE SCRATCH0 | had_cmdout TO SCRATCH0 -at 0x0000001a : */ 0x7a340400,0x00000000, +at 0x00000018 : */ 0x7a340400,0x00000000, /* MOVE FROM dsa_cmnd, WHEN CMD -at 0x0000001c : */ 0x1a000000,0x00000010, +at 0x0000001a : */ 0x1a000000,0x00000010, /* ENTRY resume_pmm resume_pmm: redo_msgin2: JUMP get_msgin2, WHEN MSG_IN -at 0x0000001e : */ 0x870b0000,0x00000a20, +at 0x0000001c : */ 0x870b0000,0x00000a48, /* JUMP get_status, IF STATUS -at 0x00000020 : */ 0x830a0000,0x000000a0, +at 0x0000001e : */ 0x830a0000,0x00000098, /* JUMP input_data, IF DATA_IN -at 0x00000022 : */ 0x810a0000,0x000000e0, +at 0x00000020 : */ 0x810a0000,0x000000d8, /* JUMP output_data, IF DATA_OUT -at 0x00000024 : */ 0x800a0000,0x000004f8, +at 0x00000022 : */ 0x800a0000,0x000004f0, /* INT int_cmd_bad_phase -at 0x00000026 : */ 0x98080000,0xab930009, +at 0x00000024 : */ 0x98080000,0xab930009, /* get_status: ; Disable selection timer MOVE CTEST7 | 0x10 TO CTEST7 -at 0x00000028 : */ 0x7a1b1000,0x00000000, +at 0x00000026 : */ 0x7a1b1000,0x00000000, /* MOVE FROM dsa_status, WHEN STATUS -at 0x0000002a : */ 0x1b000000,0x00000018, +at 0x00000028 : */ 0x1b000000,0x00000018, /* INT int_status_not_msgin, WHEN NOT MSG_IN -at 0x0000002c : */ 0x9f030000,0xab930015, +at 0x0000002a : */ 0x9f030000,0xab930015, /* MOVE FROM dsa_msgin, WHEN MSG_IN -at 0x0000002e : */ 0x1f000000,0x00000020, +at 0x0000002c : */ 0x1f000000,0x00000020, /* INT int_not_cmd_complete, IF NOT 0x00 -at 0x00000030 : */ 0x98040000,0xab930012, +at 0x0000002e : */ 0x98040000,0xab930012, /* CLEAR ACK -at 0x00000032 : */ 0x60000040,0x00000000, +at 0x00000030 : */ 0x60000040,0x00000000, /* ENTRY wait_disc_complete wait_disc_complete: WAIT DISCONNECT -at 0x00000034 : */ 0x48000000,0x00000000, +at 0x00000032 : */ 0x48000000,0x00000000, /* INT int_cmd_complete -at 0x00000036 : */ 0x98080000,0xab93000a, +at 0x00000034 : */ 0x98080000,0xab93000a, /* input_data: MOVE SCRATCH0 | had_datain TO SCRATCH0 -at 0x00000038 : */ 0x7a340800,0x00000000, +at 0x00000036 : */ 0x7a340800,0x00000000, /* ENTRY patch_input_data patch_input_data: JUMP 0 -at 0x0000003a : */ 0x80080000,0x00000000, +at 0x00000038 : */ 0x80080000,0x00000000, /* MOVE FROM dsa_datain+0x0000, WHEN DATA_IN -at 0x0000003c : */ 0x19000000,0x00000028, +at 0x0000003a : */ 0x19000000,0x00000028, /* MOVE FROM dsa_datain+0x0008, WHEN DATA_IN -at 0x0000003e : */ 0x19000000,0x00000030, +at 0x0000003c : */ 0x19000000,0x00000030, /* MOVE FROM dsa_datain+0x0010, WHEN DATA_IN -at 0x00000040 : */ 0x19000000,0x00000038, +at 0x0000003e : */ 0x19000000,0x00000038, /* MOVE FROM dsa_datain+0x0018, WHEN DATA_IN -at 0x00000042 : */ 0x19000000,0x00000040, +at 0x00000040 : */ 0x19000000,0x00000040, /* MOVE FROM dsa_datain+0x0020, WHEN DATA_IN -at 0x00000044 : */ 0x19000000,0x00000048, +at 0x00000042 : */ 0x19000000,0x00000048, /* MOVE FROM dsa_datain+0x0028, WHEN DATA_IN -at 0x00000046 : */ 0x19000000,0x00000050, +at 0x00000044 : */ 0x19000000,0x00000050, /* MOVE FROM dsa_datain+0x0030, WHEN DATA_IN -at 0x00000048 : */ 0x19000000,0x00000058, +at 0x00000046 : */ 0x19000000,0x00000058, /* MOVE FROM dsa_datain+0x0038, WHEN DATA_IN -at 0x0000004a : */ 0x19000000,0x00000060, +at 0x00000048 : */ 0x19000000,0x00000060, /* MOVE FROM dsa_datain+0x0040, WHEN DATA_IN -at 0x0000004c : */ 0x19000000,0x00000068, +at 0x0000004a : */ 0x19000000,0x00000068, /* MOVE FROM dsa_datain+0x0048, WHEN DATA_IN -at 0x0000004e : */ 0x19000000,0x00000070, +at 0x0000004c : */ 0x19000000,0x00000070, /* MOVE FROM dsa_datain+0x0050, WHEN DATA_IN -at 0x00000050 : */ 0x19000000,0x00000078, +at 0x0000004e : */ 0x19000000,0x00000078, /* MOVE FROM dsa_datain+0x0058, WHEN DATA_IN -at 0x00000052 : */ 0x19000000,0x00000080, +at 0x00000050 : */ 0x19000000,0x00000080, /* MOVE FROM dsa_datain+0x0060, WHEN DATA_IN -at 0x00000054 : */ 0x19000000,0x00000088, +at 0x00000052 : */ 0x19000000,0x00000088, /* MOVE FROM dsa_datain+0x0068, WHEN DATA_IN -at 0x00000056 : */ 0x19000000,0x00000090, +at 0x00000054 : */ 0x19000000,0x00000090, /* MOVE FROM dsa_datain+0x0070, WHEN DATA_IN -at 0x00000058 : */ 0x19000000,0x00000098, +at 0x00000056 : */ 0x19000000,0x00000098, /* MOVE FROM dsa_datain+0x0078, WHEN DATA_IN -at 0x0000005a : */ 0x19000000,0x000000a0, +at 0x00000058 : */ 0x19000000,0x000000a0, /* MOVE FROM dsa_datain+0x0080, WHEN DATA_IN -at 0x0000005c : */ 0x19000000,0x000000a8, +at 0x0000005a : */ 0x19000000,0x000000a8, /* MOVE FROM dsa_datain+0x0088, WHEN DATA_IN -at 0x0000005e : */ 0x19000000,0x000000b0, +at 0x0000005c : */ 0x19000000,0x000000b0, /* MOVE FROM dsa_datain+0x0090, WHEN DATA_IN -at 0x00000060 : */ 0x19000000,0x000000b8, +at 0x0000005e : */ 0x19000000,0x000000b8, /* MOVE FROM dsa_datain+0x0098, WHEN DATA_IN -at 0x00000062 : */ 0x19000000,0x000000c0, +at 0x00000060 : */ 0x19000000,0x000000c0, /* MOVE FROM dsa_datain+0x00a0, WHEN DATA_IN -at 0x00000064 : */ 0x19000000,0x000000c8, +at 0x00000062 : */ 0x19000000,0x000000c8, /* MOVE FROM dsa_datain+0x00a8, WHEN DATA_IN -at 0x00000066 : */ 0x19000000,0x000000d0, +at 0x00000064 : */ 0x19000000,0x000000d0, /* MOVE FROM dsa_datain+0x00b0, WHEN DATA_IN -at 0x00000068 : */ 0x19000000,0x000000d8, +at 0x00000066 : */ 0x19000000,0x000000d8, /* MOVE FROM dsa_datain+0x00b8, WHEN DATA_IN -at 0x0000006a : */ 0x19000000,0x000000e0, +at 0x00000068 : */ 0x19000000,0x000000e0, /* MOVE FROM dsa_datain+0x00c0, WHEN DATA_IN -at 0x0000006c : */ 0x19000000,0x000000e8, +at 0x0000006a : */ 0x19000000,0x000000e8, /* MOVE FROM dsa_datain+0x00c8, WHEN DATA_IN -at 0x0000006e : */ 0x19000000,0x000000f0, +at 0x0000006c : */ 0x19000000,0x000000f0, /* MOVE FROM dsa_datain+0x00d0, WHEN DATA_IN -at 0x00000070 : */ 0x19000000,0x000000f8, +at 0x0000006e : */ 0x19000000,0x000000f8, /* MOVE FROM dsa_datain+0x00d8, WHEN DATA_IN -at 0x00000072 : */ 0x19000000,0x00000100, +at 0x00000070 : */ 0x19000000,0x00000100, /* MOVE FROM dsa_datain+0x00e0, WHEN DATA_IN -at 0x00000074 : */ 0x19000000,0x00000108, +at 0x00000072 : */ 0x19000000,0x00000108, /* MOVE FROM dsa_datain+0x00e8, WHEN DATA_IN -at 0x00000076 : */ 0x19000000,0x00000110, +at 0x00000074 : */ 0x19000000,0x00000110, /* MOVE FROM dsa_datain+0x00f0, WHEN DATA_IN -at 0x00000078 : */ 0x19000000,0x00000118, +at 0x00000076 : */ 0x19000000,0x00000118, /* MOVE FROM dsa_datain+0x00f8, WHEN DATA_IN -at 0x0000007a : */ 0x19000000,0x00000120, +at 0x00000078 : */ 0x19000000,0x00000120, /* MOVE FROM dsa_datain+0x0100, WHEN DATA_IN -at 0x0000007c : */ 0x19000000,0x00000128, +at 0x0000007a : */ 0x19000000,0x00000128, /* MOVE FROM dsa_datain+0x0108, WHEN DATA_IN -at 0x0000007e : */ 0x19000000,0x00000130, +at 0x0000007c : */ 0x19000000,0x00000130, /* MOVE FROM dsa_datain+0x0110, WHEN DATA_IN -at 0x00000080 : */ 0x19000000,0x00000138, +at 0x0000007e : */ 0x19000000,0x00000138, /* MOVE FROM dsa_datain+0x0118, WHEN DATA_IN -at 0x00000082 : */ 0x19000000,0x00000140, +at 0x00000080 : */ 0x19000000,0x00000140, /* MOVE FROM dsa_datain+0x0120, WHEN DATA_IN -at 0x00000084 : */ 0x19000000,0x00000148, +at 0x00000082 : */ 0x19000000,0x00000148, /* MOVE FROM dsa_datain+0x0128, WHEN DATA_IN -at 0x00000086 : */ 0x19000000,0x00000150, +at 0x00000084 : */ 0x19000000,0x00000150, /* MOVE FROM dsa_datain+0x0130, WHEN DATA_IN -at 0x00000088 : */ 0x19000000,0x00000158, +at 0x00000086 : */ 0x19000000,0x00000158, /* MOVE FROM dsa_datain+0x0138, WHEN DATA_IN -at 0x0000008a : */ 0x19000000,0x00000160, +at 0x00000088 : */ 0x19000000,0x00000160, /* MOVE FROM dsa_datain+0x0140, WHEN DATA_IN -at 0x0000008c : */ 0x19000000,0x00000168, +at 0x0000008a : */ 0x19000000,0x00000168, /* MOVE FROM dsa_datain+0x0148, WHEN DATA_IN -at 0x0000008e : */ 0x19000000,0x00000170, +at 0x0000008c : */ 0x19000000,0x00000170, /* MOVE FROM dsa_datain+0x0150, WHEN DATA_IN -at 0x00000090 : */ 0x19000000,0x00000178, +at 0x0000008e : */ 0x19000000,0x00000178, /* MOVE FROM dsa_datain+0x0158, WHEN DATA_IN -at 0x00000092 : */ 0x19000000,0x00000180, +at 0x00000090 : */ 0x19000000,0x00000180, /* MOVE FROM dsa_datain+0x0160, WHEN DATA_IN -at 0x00000094 : */ 0x19000000,0x00000188, +at 0x00000092 : */ 0x19000000,0x00000188, /* MOVE FROM dsa_datain+0x0168, WHEN DATA_IN -at 0x00000096 : */ 0x19000000,0x00000190, +at 0x00000094 : */ 0x19000000,0x00000190, /* MOVE FROM dsa_datain+0x0170, WHEN DATA_IN -at 0x00000098 : */ 0x19000000,0x00000198, +at 0x00000096 : */ 0x19000000,0x00000198, /* MOVE FROM dsa_datain+0x0178, WHEN DATA_IN -at 0x0000009a : */ 0x19000000,0x000001a0, +at 0x00000098 : */ 0x19000000,0x000001a0, /* MOVE FROM dsa_datain+0x0180, WHEN DATA_IN -at 0x0000009c : */ 0x19000000,0x000001a8, +at 0x0000009a : */ 0x19000000,0x000001a8, /* MOVE FROM dsa_datain+0x0188, WHEN DATA_IN -at 0x0000009e : */ 0x19000000,0x000001b0, +at 0x0000009c : */ 0x19000000,0x000001b0, /* MOVE FROM dsa_datain+0x0190, WHEN DATA_IN -at 0x000000a0 : */ 0x19000000,0x000001b8, +at 0x0000009e : */ 0x19000000,0x000001b8, /* MOVE FROM dsa_datain+0x0198, WHEN DATA_IN -at 0x000000a2 : */ 0x19000000,0x000001c0, +at 0x000000a0 : */ 0x19000000,0x000001c0, /* MOVE FROM dsa_datain+0x01a0, WHEN DATA_IN -at 0x000000a4 : */ 0x19000000,0x000001c8, +at 0x000000a2 : */ 0x19000000,0x000001c8, /* MOVE FROM dsa_datain+0x01a8, WHEN DATA_IN -at 0x000000a6 : */ 0x19000000,0x000001d0, +at 0x000000a4 : */ 0x19000000,0x000001d0, /* MOVE FROM dsa_datain+0x01b0, WHEN DATA_IN -at 0x000000a8 : */ 0x19000000,0x000001d8, +at 0x000000a6 : */ 0x19000000,0x000001d8, /* MOVE FROM dsa_datain+0x01b8, WHEN DATA_IN -at 0x000000aa : */ 0x19000000,0x000001e0, +at 0x000000a8 : */ 0x19000000,0x000001e0, /* MOVE FROM dsa_datain+0x01c0, WHEN DATA_IN -at 0x000000ac : */ 0x19000000,0x000001e8, +at 0x000000aa : */ 0x19000000,0x000001e8, /* MOVE FROM dsa_datain+0x01c8, WHEN DATA_IN -at 0x000000ae : */ 0x19000000,0x000001f0, +at 0x000000ac : */ 0x19000000,0x000001f0, /* MOVE FROM dsa_datain+0x01d0, WHEN DATA_IN -at 0x000000b0 : */ 0x19000000,0x000001f8, +at 0x000000ae : */ 0x19000000,0x000001f8, /* MOVE FROM dsa_datain+0x01d8, WHEN DATA_IN -at 0x000000b2 : */ 0x19000000,0x00000200, +at 0x000000b0 : */ 0x19000000,0x00000200, /* MOVE FROM dsa_datain+0x01e0, WHEN DATA_IN -at 0x000000b4 : */ 0x19000000,0x00000208, +at 0x000000b2 : */ 0x19000000,0x00000208, /* MOVE FROM dsa_datain+0x01e8, WHEN DATA_IN -at 0x000000b6 : */ 0x19000000,0x00000210, +at 0x000000b4 : */ 0x19000000,0x00000210, /* MOVE FROM dsa_datain+0x01f0, WHEN DATA_IN -at 0x000000b8 : */ 0x19000000,0x00000218, +at 0x000000b6 : */ 0x19000000,0x00000218, /* MOVE FROM dsa_datain+0x01f8, WHEN DATA_IN -at 0x000000ba : */ 0x19000000,0x00000220, +at 0x000000b8 : */ 0x19000000,0x00000220, /* MOVE FROM dsa_datain+0x0200, WHEN DATA_IN -at 0x000000bc : */ 0x19000000,0x00000228, +at 0x000000ba : */ 0x19000000,0x00000228, /* MOVE FROM dsa_datain+0x0208, WHEN DATA_IN -at 0x000000be : */ 0x19000000,0x00000230, +at 0x000000bc : */ 0x19000000,0x00000230, /* MOVE FROM dsa_datain+0x0210, WHEN DATA_IN -at 0x000000c0 : */ 0x19000000,0x00000238, +at 0x000000be : */ 0x19000000,0x00000238, /* MOVE FROM dsa_datain+0x0218, WHEN DATA_IN -at 0x000000c2 : */ 0x19000000,0x00000240, +at 0x000000c0 : */ 0x19000000,0x00000240, /* MOVE FROM dsa_datain+0x0220, WHEN DATA_IN -at 0x000000c4 : */ 0x19000000,0x00000248, +at 0x000000c2 : */ 0x19000000,0x00000248, /* MOVE FROM dsa_datain+0x0228, WHEN DATA_IN -at 0x000000c6 : */ 0x19000000,0x00000250, +at 0x000000c4 : */ 0x19000000,0x00000250, /* MOVE FROM dsa_datain+0x0230, WHEN DATA_IN -at 0x000000c8 : */ 0x19000000,0x00000258, +at 0x000000c6 : */ 0x19000000,0x00000258, /* MOVE FROM dsa_datain+0x0238, WHEN DATA_IN -at 0x000000ca : */ 0x19000000,0x00000260, +at 0x000000c8 : */ 0x19000000,0x00000260, /* MOVE FROM dsa_datain+0x0240, WHEN DATA_IN -at 0x000000cc : */ 0x19000000,0x00000268, +at 0x000000ca : */ 0x19000000,0x00000268, /* MOVE FROM dsa_datain+0x0248, WHEN DATA_IN -at 0x000000ce : */ 0x19000000,0x00000270, +at 0x000000cc : */ 0x19000000,0x00000270, /* MOVE FROM dsa_datain+0x0250, WHEN DATA_IN -at 0x000000d0 : */ 0x19000000,0x00000278, +at 0x000000ce : */ 0x19000000,0x00000278, /* MOVE FROM dsa_datain+0x0258, WHEN DATA_IN -at 0x000000d2 : */ 0x19000000,0x00000280, +at 0x000000d0 : */ 0x19000000,0x00000280, /* MOVE FROM dsa_datain+0x0260, WHEN DATA_IN -at 0x000000d4 : */ 0x19000000,0x00000288, +at 0x000000d2 : */ 0x19000000,0x00000288, /* MOVE FROM dsa_datain+0x0268, WHEN DATA_IN -at 0x000000d6 : */ 0x19000000,0x00000290, +at 0x000000d4 : */ 0x19000000,0x00000290, /* MOVE FROM dsa_datain+0x0270, WHEN DATA_IN -at 0x000000d8 : */ 0x19000000,0x00000298, +at 0x000000d6 : */ 0x19000000,0x00000298, /* MOVE FROM dsa_datain+0x0278, WHEN DATA_IN -at 0x000000da : */ 0x19000000,0x000002a0, +at 0x000000d8 : */ 0x19000000,0x000002a0, /* MOVE FROM dsa_datain+0x0280, WHEN DATA_IN -at 0x000000dc : */ 0x19000000,0x000002a8, +at 0x000000da : */ 0x19000000,0x000002a8, /* MOVE FROM dsa_datain+0x0288, WHEN DATA_IN -at 0x000000de : */ 0x19000000,0x000002b0, +at 0x000000dc : */ 0x19000000,0x000002b0, /* MOVE FROM dsa_datain+0x0290, WHEN DATA_IN -at 0x000000e0 : */ 0x19000000,0x000002b8, +at 0x000000de : */ 0x19000000,0x000002b8, /* MOVE FROM dsa_datain+0x0298, WHEN DATA_IN -at 0x000000e2 : */ 0x19000000,0x000002c0, +at 0x000000e0 : */ 0x19000000,0x000002c0, /* MOVE FROM dsa_datain+0x02a0, WHEN DATA_IN -at 0x000000e4 : */ 0x19000000,0x000002c8, +at 0x000000e2 : */ 0x19000000,0x000002c8, /* MOVE FROM dsa_datain+0x02a8, WHEN DATA_IN -at 0x000000e6 : */ 0x19000000,0x000002d0, +at 0x000000e4 : */ 0x19000000,0x000002d0, /* MOVE FROM dsa_datain+0x02b0, WHEN DATA_IN -at 0x000000e8 : */ 0x19000000,0x000002d8, +at 0x000000e6 : */ 0x19000000,0x000002d8, /* MOVE FROM dsa_datain+0x02b8, WHEN DATA_IN -at 0x000000ea : */ 0x19000000,0x000002e0, +at 0x000000e8 : */ 0x19000000,0x000002e0, /* MOVE FROM dsa_datain+0x02c0, WHEN DATA_IN -at 0x000000ec : */ 0x19000000,0x000002e8, +at 0x000000ea : */ 0x19000000,0x000002e8, /* MOVE FROM dsa_datain+0x02c8, WHEN DATA_IN -at 0x000000ee : */ 0x19000000,0x000002f0, +at 0x000000ec : */ 0x19000000,0x000002f0, /* MOVE FROM dsa_datain+0x02d0, WHEN DATA_IN -at 0x000000f0 : */ 0x19000000,0x000002f8, +at 0x000000ee : */ 0x19000000,0x000002f8, /* MOVE FROM dsa_datain+0x02d8, WHEN DATA_IN -at 0x000000f2 : */ 0x19000000,0x00000300, +at 0x000000f0 : */ 0x19000000,0x00000300, /* MOVE FROM dsa_datain+0x02e0, WHEN DATA_IN -at 0x000000f4 : */ 0x19000000,0x00000308, +at 0x000000f2 : */ 0x19000000,0x00000308, /* MOVE FROM dsa_datain+0x02e8, WHEN DATA_IN -at 0x000000f6 : */ 0x19000000,0x00000310, +at 0x000000f4 : */ 0x19000000,0x00000310, /* MOVE FROM dsa_datain+0x02f0, WHEN DATA_IN -at 0x000000f8 : */ 0x19000000,0x00000318, +at 0x000000f6 : */ 0x19000000,0x00000318, /* MOVE FROM dsa_datain+0x02f8, WHEN DATA_IN -at 0x000000fa : */ 0x19000000,0x00000320, +at 0x000000f8 : */ 0x19000000,0x00000320, /* MOVE FROM dsa_datain+0x0300, WHEN DATA_IN -at 0x000000fc : */ 0x19000000,0x00000328, +at 0x000000fa : */ 0x19000000,0x00000328, /* MOVE FROM dsa_datain+0x0308, WHEN DATA_IN -at 0x000000fe : */ 0x19000000,0x00000330, +at 0x000000fc : */ 0x19000000,0x00000330, /* MOVE FROM dsa_datain+0x0310, WHEN DATA_IN -at 0x00000100 : */ 0x19000000,0x00000338, +at 0x000000fe : */ 0x19000000,0x00000338, /* MOVE FROM dsa_datain+0x0318, WHEN DATA_IN -at 0x00000102 : */ 0x19000000,0x00000340, +at 0x00000100 : */ 0x19000000,0x00000340, /* MOVE FROM dsa_datain+0x0320, WHEN DATA_IN -at 0x00000104 : */ 0x19000000,0x00000348, +at 0x00000102 : */ 0x19000000,0x00000348, /* MOVE FROM dsa_datain+0x0328, WHEN DATA_IN -at 0x00000106 : */ 0x19000000,0x00000350, +at 0x00000104 : */ 0x19000000,0x00000350, /* MOVE FROM dsa_datain+0x0330, WHEN DATA_IN -at 0x00000108 : */ 0x19000000,0x00000358, +at 0x00000106 : */ 0x19000000,0x00000358, /* MOVE FROM dsa_datain+0x0338, WHEN DATA_IN -at 0x0000010a : */ 0x19000000,0x00000360, +at 0x00000108 : */ 0x19000000,0x00000360, /* MOVE FROM dsa_datain+0x0340, WHEN DATA_IN -at 0x0000010c : */ 0x19000000,0x00000368, +at 0x0000010a : */ 0x19000000,0x00000368, /* MOVE FROM dsa_datain+0x0348, WHEN DATA_IN -at 0x0000010e : */ 0x19000000,0x00000370, +at 0x0000010c : */ 0x19000000,0x00000370, /* MOVE FROM dsa_datain+0x0350, WHEN DATA_IN -at 0x00000110 : */ 0x19000000,0x00000378, +at 0x0000010e : */ 0x19000000,0x00000378, /* MOVE FROM dsa_datain+0x0358, WHEN DATA_IN -at 0x00000112 : */ 0x19000000,0x00000380, +at 0x00000110 : */ 0x19000000,0x00000380, /* MOVE FROM dsa_datain+0x0360, WHEN DATA_IN -at 0x00000114 : */ 0x19000000,0x00000388, +at 0x00000112 : */ 0x19000000,0x00000388, /* MOVE FROM dsa_datain+0x0368, WHEN DATA_IN -at 0x00000116 : */ 0x19000000,0x00000390, +at 0x00000114 : */ 0x19000000,0x00000390, /* MOVE FROM dsa_datain+0x0370, WHEN DATA_IN -at 0x00000118 : */ 0x19000000,0x00000398, +at 0x00000116 : */ 0x19000000,0x00000398, /* MOVE FROM dsa_datain+0x0378, WHEN DATA_IN -at 0x0000011a : */ 0x19000000,0x000003a0, +at 0x00000118 : */ 0x19000000,0x000003a0, /* MOVE FROM dsa_datain+0x0380, WHEN DATA_IN -at 0x0000011c : */ 0x19000000,0x000003a8, +at 0x0000011a : */ 0x19000000,0x000003a8, /* MOVE FROM dsa_datain+0x0388, WHEN DATA_IN -at 0x0000011e : */ 0x19000000,0x000003b0, +at 0x0000011c : */ 0x19000000,0x000003b0, /* MOVE FROM dsa_datain+0x0390, WHEN DATA_IN -at 0x00000120 : */ 0x19000000,0x000003b8, +at 0x0000011e : */ 0x19000000,0x000003b8, /* MOVE FROM dsa_datain+0x0398, WHEN DATA_IN -at 0x00000122 : */ 0x19000000,0x000003c0, +at 0x00000120 : */ 0x19000000,0x000003c0, /* MOVE FROM dsa_datain+0x03a0, WHEN DATA_IN -at 0x00000124 : */ 0x19000000,0x000003c8, +at 0x00000122 : */ 0x19000000,0x000003c8, /* MOVE FROM dsa_datain+0x03a8, WHEN DATA_IN -at 0x00000126 : */ 0x19000000,0x000003d0, +at 0x00000124 : */ 0x19000000,0x000003d0, /* MOVE FROM dsa_datain+0x03b0, WHEN DATA_IN -at 0x00000128 : */ 0x19000000,0x000003d8, +at 0x00000126 : */ 0x19000000,0x000003d8, /* MOVE FROM dsa_datain+0x03b8, WHEN DATA_IN -at 0x0000012a : */ 0x19000000,0x000003e0, +at 0x00000128 : */ 0x19000000,0x000003e0, /* MOVE FROM dsa_datain+0x03c0, WHEN DATA_IN -at 0x0000012c : */ 0x19000000,0x000003e8, +at 0x0000012a : */ 0x19000000,0x000003e8, /* MOVE FROM dsa_datain+0x03c8, WHEN DATA_IN -at 0x0000012e : */ 0x19000000,0x000003f0, +at 0x0000012c : */ 0x19000000,0x000003f0, /* MOVE FROM dsa_datain+0x03d0, WHEN DATA_IN -at 0x00000130 : */ 0x19000000,0x000003f8, +at 0x0000012e : */ 0x19000000,0x000003f8, /* MOVE FROM dsa_datain+0x03d8, WHEN DATA_IN -at 0x00000132 : */ 0x19000000,0x00000400, +at 0x00000130 : */ 0x19000000,0x00000400, /* MOVE FROM dsa_datain+0x03e0, WHEN DATA_IN -at 0x00000134 : */ 0x19000000,0x00000408, +at 0x00000132 : */ 0x19000000,0x00000408, /* MOVE FROM dsa_datain+0x03e8, WHEN DATA_IN -at 0x00000136 : */ 0x19000000,0x00000410, +at 0x00000134 : */ 0x19000000,0x00000410, /* MOVE FROM dsa_datain+0x03f0, WHEN DATA_IN -at 0x00000138 : */ 0x19000000,0x00000418, +at 0x00000136 : */ 0x19000000,0x00000418, /* MOVE FROM dsa_datain+0x03f8, WHEN DATA_IN -at 0x0000013a : */ 0x19000000,0x00000420, +at 0x00000138 : */ 0x19000000,0x00000420, /* JUMP end_data_trans -at 0x0000013c : */ 0x80080000,0x00000908, +at 0x0000013a : */ 0x80080000,0x00000900, /* output_data: MOVE SCRATCH0 | had_dataout TO SCRATCH0 -at 0x0000013e : */ 0x7a341000,0x00000000, +at 0x0000013c : */ 0x7a341000,0x00000000, /* ENTRY patch_output_data patch_output_data: JUMP 0 -at 0x00000140 : */ 0x80080000,0x00000000, +at 0x0000013e : */ 0x80080000,0x00000000, /* MOVE FROM dsa_dataout+0x0000, WHEN DATA_OUT -at 0x00000142 : */ 0x18000000,0x00000428, +at 0x00000140 : */ 0x18000000,0x00000428, /* MOVE FROM dsa_dataout+0x0008, WHEN DATA_OUT -at 0x00000144 : */ 0x18000000,0x00000430, +at 0x00000142 : */ 0x18000000,0x00000430, /* MOVE FROM dsa_dataout+0x0010, WHEN DATA_OUT -at 0x00000146 : */ 0x18000000,0x00000438, +at 0x00000144 : */ 0x18000000,0x00000438, /* MOVE FROM dsa_dataout+0x0018, WHEN DATA_OUT -at 0x00000148 : */ 0x18000000,0x00000440, +at 0x00000146 : */ 0x18000000,0x00000440, /* MOVE FROM dsa_dataout+0x0020, WHEN DATA_OUT -at 0x0000014a : */ 0x18000000,0x00000448, +at 0x00000148 : */ 0x18000000,0x00000448, /* MOVE FROM dsa_dataout+0x0028, WHEN DATA_OUT -at 0x0000014c : */ 0x18000000,0x00000450, +at 0x0000014a : */ 0x18000000,0x00000450, /* MOVE FROM dsa_dataout+0x0030, WHEN DATA_OUT -at 0x0000014e : */ 0x18000000,0x00000458, +at 0x0000014c : */ 0x18000000,0x00000458, /* MOVE FROM dsa_dataout+0x0038, WHEN DATA_OUT -at 0x00000150 : */ 0x18000000,0x00000460, +at 0x0000014e : */ 0x18000000,0x00000460, /* MOVE FROM dsa_dataout+0x0040, WHEN DATA_OUT -at 0x00000152 : */ 0x18000000,0x00000468, +at 0x00000150 : */ 0x18000000,0x00000468, /* MOVE FROM dsa_dataout+0x0048, WHEN DATA_OUT -at 0x00000154 : */ 0x18000000,0x00000470, +at 0x00000152 : */ 0x18000000,0x00000470, /* MOVE FROM dsa_dataout+0x0050, WHEN DATA_OUT -at 0x00000156 : */ 0x18000000,0x00000478, +at 0x00000154 : */ 0x18000000,0x00000478, /* MOVE FROM dsa_dataout+0x0058, WHEN DATA_OUT -at 0x00000158 : */ 0x18000000,0x00000480, +at 0x00000156 : */ 0x18000000,0x00000480, /* MOVE FROM dsa_dataout+0x0060, WHEN DATA_OUT -at 0x0000015a : */ 0x18000000,0x00000488, +at 0x00000158 : */ 0x18000000,0x00000488, /* MOVE FROM dsa_dataout+0x0068, WHEN DATA_OUT -at 0x0000015c : */ 0x18000000,0x00000490, +at 0x0000015a : */ 0x18000000,0x00000490, /* MOVE FROM dsa_dataout+0x0070, WHEN DATA_OUT -at 0x0000015e : */ 0x18000000,0x00000498, +at 0x0000015c : */ 0x18000000,0x00000498, /* MOVE FROM dsa_dataout+0x0078, WHEN DATA_OUT -at 0x00000160 : */ 0x18000000,0x000004a0, +at 0x0000015e : */ 0x18000000,0x000004a0, /* MOVE FROM dsa_dataout+0x0080, WHEN DATA_OUT -at 0x00000162 : */ 0x18000000,0x000004a8, +at 0x00000160 : */ 0x18000000,0x000004a8, /* MOVE FROM dsa_dataout+0x0088, WHEN DATA_OUT -at 0x00000164 : */ 0x18000000,0x000004b0, +at 0x00000162 : */ 0x18000000,0x000004b0, /* MOVE FROM dsa_dataout+0x0090, WHEN DATA_OUT -at 0x00000166 : */ 0x18000000,0x000004b8, +at 0x00000164 : */ 0x18000000,0x000004b8, /* MOVE FROM dsa_dataout+0x0098, WHEN DATA_OUT -at 0x00000168 : */ 0x18000000,0x000004c0, +at 0x00000166 : */ 0x18000000,0x000004c0, /* MOVE FROM dsa_dataout+0x00a0, WHEN DATA_OUT -at 0x0000016a : */ 0x18000000,0x000004c8, +at 0x00000168 : */ 0x18000000,0x000004c8, /* MOVE FROM dsa_dataout+0x00a8, WHEN DATA_OUT -at 0x0000016c : */ 0x18000000,0x000004d0, +at 0x0000016a : */ 0x18000000,0x000004d0, /* MOVE FROM dsa_dataout+0x00b0, WHEN DATA_OUT -at 0x0000016e : */ 0x18000000,0x000004d8, +at 0x0000016c : */ 0x18000000,0x000004d8, /* MOVE FROM dsa_dataout+0x00b8, WHEN DATA_OUT -at 0x00000170 : */ 0x18000000,0x000004e0, +at 0x0000016e : */ 0x18000000,0x000004e0, /* MOVE FROM dsa_dataout+0x00c0, WHEN DATA_OUT -at 0x00000172 : */ 0x18000000,0x000004e8, +at 0x00000170 : */ 0x18000000,0x000004e8, /* MOVE FROM dsa_dataout+0x00c8, WHEN DATA_OUT -at 0x00000174 : */ 0x18000000,0x000004f0, +at 0x00000172 : */ 0x18000000,0x000004f0, /* MOVE FROM dsa_dataout+0x00d0, WHEN DATA_OUT -at 0x00000176 : */ 0x18000000,0x000004f8, +at 0x00000174 : */ 0x18000000,0x000004f8, /* MOVE FROM dsa_dataout+0x00d8, WHEN DATA_OUT -at 0x00000178 : */ 0x18000000,0x00000500, +at 0x00000176 : */ 0x18000000,0x00000500, /* MOVE FROM dsa_dataout+0x00e0, WHEN DATA_OUT -at 0x0000017a : */ 0x18000000,0x00000508, +at 0x00000178 : */ 0x18000000,0x00000508, /* MOVE FROM dsa_dataout+0x00e8, WHEN DATA_OUT -at 0x0000017c : */ 0x18000000,0x00000510, +at 0x0000017a : */ 0x18000000,0x00000510, /* MOVE FROM dsa_dataout+0x00f0, WHEN DATA_OUT -at 0x0000017e : */ 0x18000000,0x00000518, +at 0x0000017c : */ 0x18000000,0x00000518, /* MOVE FROM dsa_dataout+0x00f8, WHEN DATA_OUT -at 0x00000180 : */ 0x18000000,0x00000520, +at 0x0000017e : */ 0x18000000,0x00000520, /* MOVE FROM dsa_dataout+0x0100, WHEN DATA_OUT -at 0x00000182 : */ 0x18000000,0x00000528, +at 0x00000180 : */ 0x18000000,0x00000528, /* MOVE FROM dsa_dataout+0x0108, WHEN DATA_OUT -at 0x00000184 : */ 0x18000000,0x00000530, +at 0x00000182 : */ 0x18000000,0x00000530, /* MOVE FROM dsa_dataout+0x0110, WHEN DATA_OUT -at 0x00000186 : */ 0x18000000,0x00000538, +at 0x00000184 : */ 0x18000000,0x00000538, /* MOVE FROM dsa_dataout+0x0118, WHEN DATA_OUT -at 0x00000188 : */ 0x18000000,0x00000540, +at 0x00000186 : */ 0x18000000,0x00000540, /* MOVE FROM dsa_dataout+0x0120, WHEN DATA_OUT -at 0x0000018a : */ 0x18000000,0x00000548, +at 0x00000188 : */ 0x18000000,0x00000548, /* MOVE FROM dsa_dataout+0x0128, WHEN DATA_OUT -at 0x0000018c : */ 0x18000000,0x00000550, +at 0x0000018a : */ 0x18000000,0x00000550, /* MOVE FROM dsa_dataout+0x0130, WHEN DATA_OUT -at 0x0000018e : */ 0x18000000,0x00000558, +at 0x0000018c : */ 0x18000000,0x00000558, /* MOVE FROM dsa_dataout+0x0138, WHEN DATA_OUT -at 0x00000190 : */ 0x18000000,0x00000560, +at 0x0000018e : */ 0x18000000,0x00000560, /* MOVE FROM dsa_dataout+0x0140, WHEN DATA_OUT -at 0x00000192 : */ 0x18000000,0x00000568, +at 0x00000190 : */ 0x18000000,0x00000568, /* MOVE FROM dsa_dataout+0x0148, WHEN DATA_OUT -at 0x00000194 : */ 0x18000000,0x00000570, +at 0x00000192 : */ 0x18000000,0x00000570, /* MOVE FROM dsa_dataout+0x0150, WHEN DATA_OUT -at 0x00000196 : */ 0x18000000,0x00000578, +at 0x00000194 : */ 0x18000000,0x00000578, /* MOVE FROM dsa_dataout+0x0158, WHEN DATA_OUT -at 0x00000198 : */ 0x18000000,0x00000580, +at 0x00000196 : */ 0x18000000,0x00000580, /* MOVE FROM dsa_dataout+0x0160, WHEN DATA_OUT -at 0x0000019a : */ 0x18000000,0x00000588, +at 0x00000198 : */ 0x18000000,0x00000588, /* MOVE FROM dsa_dataout+0x0168, WHEN DATA_OUT -at 0x0000019c : */ 0x18000000,0x00000590, +at 0x0000019a : */ 0x18000000,0x00000590, /* MOVE FROM dsa_dataout+0x0170, WHEN DATA_OUT -at 0x0000019e : */ 0x18000000,0x00000598, +at 0x0000019c : */ 0x18000000,0x00000598, /* MOVE FROM dsa_dataout+0x0178, WHEN DATA_OUT -at 0x000001a0 : */ 0x18000000,0x000005a0, +at 0x0000019e : */ 0x18000000,0x000005a0, /* MOVE FROM dsa_dataout+0x0180, WHEN DATA_OUT -at 0x000001a2 : */ 0x18000000,0x000005a8, +at 0x000001a0 : */ 0x18000000,0x000005a8, /* MOVE FROM dsa_dataout+0x0188, WHEN DATA_OUT -at 0x000001a4 : */ 0x18000000,0x000005b0, +at 0x000001a2 : */ 0x18000000,0x000005b0, /* MOVE FROM dsa_dataout+0x0190, WHEN DATA_OUT -at 0x000001a6 : */ 0x18000000,0x000005b8, +at 0x000001a4 : */ 0x18000000,0x000005b8, /* MOVE FROM dsa_dataout+0x0198, WHEN DATA_OUT -at 0x000001a8 : */ 0x18000000,0x000005c0, +at 0x000001a6 : */ 0x18000000,0x000005c0, /* MOVE FROM dsa_dataout+0x01a0, WHEN DATA_OUT -at 0x000001aa : */ 0x18000000,0x000005c8, +at 0x000001a8 : */ 0x18000000,0x000005c8, /* MOVE FROM dsa_dataout+0x01a8, WHEN DATA_OUT -at 0x000001ac : */ 0x18000000,0x000005d0, +at 0x000001aa : */ 0x18000000,0x000005d0, /* MOVE FROM dsa_dataout+0x01b0, WHEN DATA_OUT -at 0x000001ae : */ 0x18000000,0x000005d8, +at 0x000001ac : */ 0x18000000,0x000005d8, /* MOVE FROM dsa_dataout+0x01b8, WHEN DATA_OUT -at 0x000001b0 : */ 0x18000000,0x000005e0, +at 0x000001ae : */ 0x18000000,0x000005e0, /* MOVE FROM dsa_dataout+0x01c0, WHEN DATA_OUT -at 0x000001b2 : */ 0x18000000,0x000005e8, +at 0x000001b0 : */ 0x18000000,0x000005e8, /* MOVE FROM dsa_dataout+0x01c8, WHEN DATA_OUT -at 0x000001b4 : */ 0x18000000,0x000005f0, +at 0x000001b2 : */ 0x18000000,0x000005f0, /* MOVE FROM dsa_dataout+0x01d0, WHEN DATA_OUT -at 0x000001b6 : */ 0x18000000,0x000005f8, +at 0x000001b4 : */ 0x18000000,0x000005f8, /* MOVE FROM dsa_dataout+0x01d8, WHEN DATA_OUT -at 0x000001b8 : */ 0x18000000,0x00000600, +at 0x000001b6 : */ 0x18000000,0x00000600, /* MOVE FROM dsa_dataout+0x01e0, WHEN DATA_OUT -at 0x000001ba : */ 0x18000000,0x00000608, +at 0x000001b8 : */ 0x18000000,0x00000608, /* MOVE FROM dsa_dataout+0x01e8, WHEN DATA_OUT -at 0x000001bc : */ 0x18000000,0x00000610, +at 0x000001ba : */ 0x18000000,0x00000610, /* MOVE FROM dsa_dataout+0x01f0, WHEN DATA_OUT -at 0x000001be : */ 0x18000000,0x00000618, +at 0x000001bc : */ 0x18000000,0x00000618, /* MOVE FROM dsa_dataout+0x01f8, WHEN DATA_OUT -at 0x000001c0 : */ 0x18000000,0x00000620, +at 0x000001be : */ 0x18000000,0x00000620, /* MOVE FROM dsa_dataout+0x0200, WHEN DATA_OUT -at 0x000001c2 : */ 0x18000000,0x00000628, +at 0x000001c0 : */ 0x18000000,0x00000628, /* MOVE FROM dsa_dataout+0x0208, WHEN DATA_OUT -at 0x000001c4 : */ 0x18000000,0x00000630, +at 0x000001c2 : */ 0x18000000,0x00000630, /* MOVE FROM dsa_dataout+0x0210, WHEN DATA_OUT -at 0x000001c6 : */ 0x18000000,0x00000638, +at 0x000001c4 : */ 0x18000000,0x00000638, /* MOVE FROM dsa_dataout+0x0218, WHEN DATA_OUT -at 0x000001c8 : */ 0x18000000,0x00000640, +at 0x000001c6 : */ 0x18000000,0x00000640, /* MOVE FROM dsa_dataout+0x0220, WHEN DATA_OUT -at 0x000001ca : */ 0x18000000,0x00000648, +at 0x000001c8 : */ 0x18000000,0x00000648, /* MOVE FROM dsa_dataout+0x0228, WHEN DATA_OUT -at 0x000001cc : */ 0x18000000,0x00000650, +at 0x000001ca : */ 0x18000000,0x00000650, /* MOVE FROM dsa_dataout+0x0230, WHEN DATA_OUT -at 0x000001ce : */ 0x18000000,0x00000658, +at 0x000001cc : */ 0x18000000,0x00000658, /* MOVE FROM dsa_dataout+0x0238, WHEN DATA_OUT -at 0x000001d0 : */ 0x18000000,0x00000660, +at 0x000001ce : */ 0x18000000,0x00000660, /* MOVE FROM dsa_dataout+0x0240, WHEN DATA_OUT -at 0x000001d2 : */ 0x18000000,0x00000668, +at 0x000001d0 : */ 0x18000000,0x00000668, /* MOVE FROM dsa_dataout+0x0248, WHEN DATA_OUT -at 0x000001d4 : */ 0x18000000,0x00000670, +at 0x000001d2 : */ 0x18000000,0x00000670, /* MOVE FROM dsa_dataout+0x0250, WHEN DATA_OUT -at 0x000001d6 : */ 0x18000000,0x00000678, +at 0x000001d4 : */ 0x18000000,0x00000678, /* MOVE FROM dsa_dataout+0x0258, WHEN DATA_OUT -at 0x000001d8 : */ 0x18000000,0x00000680, +at 0x000001d6 : */ 0x18000000,0x00000680, /* MOVE FROM dsa_dataout+0x0260, WHEN DATA_OUT -at 0x000001da : */ 0x18000000,0x00000688, +at 0x000001d8 : */ 0x18000000,0x00000688, /* MOVE FROM dsa_dataout+0x0268, WHEN DATA_OUT -at 0x000001dc : */ 0x18000000,0x00000690, +at 0x000001da : */ 0x18000000,0x00000690, /* MOVE FROM dsa_dataout+0x0270, WHEN DATA_OUT -at 0x000001de : */ 0x18000000,0x00000698, +at 0x000001dc : */ 0x18000000,0x00000698, /* MOVE FROM dsa_dataout+0x0278, WHEN DATA_OUT -at 0x000001e0 : */ 0x18000000,0x000006a0, +at 0x000001de : */ 0x18000000,0x000006a0, /* MOVE FROM dsa_dataout+0x0280, WHEN DATA_OUT -at 0x000001e2 : */ 0x18000000,0x000006a8, +at 0x000001e0 : */ 0x18000000,0x000006a8, /* MOVE FROM dsa_dataout+0x0288, WHEN DATA_OUT -at 0x000001e4 : */ 0x18000000,0x000006b0, +at 0x000001e2 : */ 0x18000000,0x000006b0, /* MOVE FROM dsa_dataout+0x0290, WHEN DATA_OUT -at 0x000001e6 : */ 0x18000000,0x000006b8, +at 0x000001e4 : */ 0x18000000,0x000006b8, /* MOVE FROM dsa_dataout+0x0298, WHEN DATA_OUT -at 0x000001e8 : */ 0x18000000,0x000006c0, +at 0x000001e6 : */ 0x18000000,0x000006c0, /* MOVE FROM dsa_dataout+0x02a0, WHEN DATA_OUT -at 0x000001ea : */ 0x18000000,0x000006c8, +at 0x000001e8 : */ 0x18000000,0x000006c8, /* MOVE FROM dsa_dataout+0x02a8, WHEN DATA_OUT -at 0x000001ec : */ 0x18000000,0x000006d0, +at 0x000001ea : */ 0x18000000,0x000006d0, /* MOVE FROM dsa_dataout+0x02b0, WHEN DATA_OUT -at 0x000001ee : */ 0x18000000,0x000006d8, +at 0x000001ec : */ 0x18000000,0x000006d8, /* MOVE FROM dsa_dataout+0x02b8, WHEN DATA_OUT -at 0x000001f0 : */ 0x18000000,0x000006e0, +at 0x000001ee : */ 0x18000000,0x000006e0, /* MOVE FROM dsa_dataout+0x02c0, WHEN DATA_OUT -at 0x000001f2 : */ 0x18000000,0x000006e8, +at 0x000001f0 : */ 0x18000000,0x000006e8, /* MOVE FROM dsa_dataout+0x02c8, WHEN DATA_OUT -at 0x000001f4 : */ 0x18000000,0x000006f0, +at 0x000001f2 : */ 0x18000000,0x000006f0, /* MOVE FROM dsa_dataout+0x02d0, WHEN DATA_OUT -at 0x000001f6 : */ 0x18000000,0x000006f8, +at 0x000001f4 : */ 0x18000000,0x000006f8, /* MOVE FROM dsa_dataout+0x02d8, WHEN DATA_OUT -at 0x000001f8 : */ 0x18000000,0x00000700, +at 0x000001f6 : */ 0x18000000,0x00000700, /* MOVE FROM dsa_dataout+0x02e0, WHEN DATA_OUT -at 0x000001fa : */ 0x18000000,0x00000708, +at 0x000001f8 : */ 0x18000000,0x00000708, /* MOVE FROM dsa_dataout+0x02e8, WHEN DATA_OUT -at 0x000001fc : */ 0x18000000,0x00000710, +at 0x000001fa : */ 0x18000000,0x00000710, /* MOVE FROM dsa_dataout+0x02f0, WHEN DATA_OUT -at 0x000001fe : */ 0x18000000,0x00000718, +at 0x000001fc : */ 0x18000000,0x00000718, /* MOVE FROM dsa_dataout+0x02f8, WHEN DATA_OUT -at 0x00000200 : */ 0x18000000,0x00000720, +at 0x000001fe : */ 0x18000000,0x00000720, /* MOVE FROM dsa_dataout+0x0300, WHEN DATA_OUT -at 0x00000202 : */ 0x18000000,0x00000728, +at 0x00000200 : */ 0x18000000,0x00000728, /* MOVE FROM dsa_dataout+0x0308, WHEN DATA_OUT -at 0x00000204 : */ 0x18000000,0x00000730, +at 0x00000202 : */ 0x18000000,0x00000730, /* MOVE FROM dsa_dataout+0x0310, WHEN DATA_OUT -at 0x00000206 : */ 0x18000000,0x00000738, +at 0x00000204 : */ 0x18000000,0x00000738, /* MOVE FROM dsa_dataout+0x0318, WHEN DATA_OUT -at 0x00000208 : */ 0x18000000,0x00000740, +at 0x00000206 : */ 0x18000000,0x00000740, /* MOVE FROM dsa_dataout+0x0320, WHEN DATA_OUT -at 0x0000020a : */ 0x18000000,0x00000748, +at 0x00000208 : */ 0x18000000,0x00000748, /* MOVE FROM dsa_dataout+0x0328, WHEN DATA_OUT -at 0x0000020c : */ 0x18000000,0x00000750, +at 0x0000020a : */ 0x18000000,0x00000750, /* MOVE FROM dsa_dataout+0x0330, WHEN DATA_OUT -at 0x0000020e : */ 0x18000000,0x00000758, +at 0x0000020c : */ 0x18000000,0x00000758, /* MOVE FROM dsa_dataout+0x0338, WHEN DATA_OUT -at 0x00000210 : */ 0x18000000,0x00000760, +at 0x0000020e : */ 0x18000000,0x00000760, /* MOVE FROM dsa_dataout+0x0340, WHEN DATA_OUT -at 0x00000212 : */ 0x18000000,0x00000768, +at 0x00000210 : */ 0x18000000,0x00000768, /* MOVE FROM dsa_dataout+0x0348, WHEN DATA_OUT -at 0x00000214 : */ 0x18000000,0x00000770, +at 0x00000212 : */ 0x18000000,0x00000770, /* MOVE FROM dsa_dataout+0x0350, WHEN DATA_OUT -at 0x00000216 : */ 0x18000000,0x00000778, +at 0x00000214 : */ 0x18000000,0x00000778, /* MOVE FROM dsa_dataout+0x0358, WHEN DATA_OUT -at 0x00000218 : */ 0x18000000,0x00000780, +at 0x00000216 : */ 0x18000000,0x00000780, /* MOVE FROM dsa_dataout+0x0360, WHEN DATA_OUT -at 0x0000021a : */ 0x18000000,0x00000788, +at 0x00000218 : */ 0x18000000,0x00000788, /* MOVE FROM dsa_dataout+0x0368, WHEN DATA_OUT -at 0x0000021c : */ 0x18000000,0x00000790, +at 0x0000021a : */ 0x18000000,0x00000790, /* MOVE FROM dsa_dataout+0x0370, WHEN DATA_OUT -at 0x0000021e : */ 0x18000000,0x00000798, +at 0x0000021c : */ 0x18000000,0x00000798, /* MOVE FROM dsa_dataout+0x0378, WHEN DATA_OUT -at 0x00000220 : */ 0x18000000,0x000007a0, +at 0x0000021e : */ 0x18000000,0x000007a0, /* MOVE FROM dsa_dataout+0x0380, WHEN DATA_OUT -at 0x00000222 : */ 0x18000000,0x000007a8, +at 0x00000220 : */ 0x18000000,0x000007a8, /* MOVE FROM dsa_dataout+0x0388, WHEN DATA_OUT -at 0x00000224 : */ 0x18000000,0x000007b0, +at 0x00000222 : */ 0x18000000,0x000007b0, /* MOVE FROM dsa_dataout+0x0390, WHEN DATA_OUT -at 0x00000226 : */ 0x18000000,0x000007b8, +at 0x00000224 : */ 0x18000000,0x000007b8, /* MOVE FROM dsa_dataout+0x0398, WHEN DATA_OUT -at 0x00000228 : */ 0x18000000,0x000007c0, +at 0x00000226 : */ 0x18000000,0x000007c0, /* MOVE FROM dsa_dataout+0x03a0, WHEN DATA_OUT -at 0x0000022a : */ 0x18000000,0x000007c8, +at 0x00000228 : */ 0x18000000,0x000007c8, /* MOVE FROM dsa_dataout+0x03a8, WHEN DATA_OUT -at 0x0000022c : */ 0x18000000,0x000007d0, +at 0x0000022a : */ 0x18000000,0x000007d0, /* MOVE FROM dsa_dataout+0x03b0, WHEN DATA_OUT -at 0x0000022e : */ 0x18000000,0x000007d8, +at 0x0000022c : */ 0x18000000,0x000007d8, /* MOVE FROM dsa_dataout+0x03b8, WHEN DATA_OUT -at 0x00000230 : */ 0x18000000,0x000007e0, +at 0x0000022e : */ 0x18000000,0x000007e0, /* MOVE FROM dsa_dataout+0x03c0, WHEN DATA_OUT -at 0x00000232 : */ 0x18000000,0x000007e8, +at 0x00000230 : */ 0x18000000,0x000007e8, /* MOVE FROM dsa_dataout+0x03c8, WHEN DATA_OUT -at 0x00000234 : */ 0x18000000,0x000007f0, +at 0x00000232 : */ 0x18000000,0x000007f0, /* MOVE FROM dsa_dataout+0x03d0, WHEN DATA_OUT -at 0x00000236 : */ 0x18000000,0x000007f8, +at 0x00000234 : */ 0x18000000,0x000007f8, /* MOVE FROM dsa_dataout+0x03d8, WHEN DATA_OUT -at 0x00000238 : */ 0x18000000,0x00000800, +at 0x00000236 : */ 0x18000000,0x00000800, /* MOVE FROM dsa_dataout+0x03e0, WHEN DATA_OUT -at 0x0000023a : */ 0x18000000,0x00000808, +at 0x00000238 : */ 0x18000000,0x00000808, /* MOVE FROM dsa_dataout+0x03e8, WHEN DATA_OUT -at 0x0000023c : */ 0x18000000,0x00000810, +at 0x0000023a : */ 0x18000000,0x00000810, /* MOVE FROM dsa_dataout+0x03f0, WHEN DATA_OUT -at 0x0000023e : */ 0x18000000,0x00000818, +at 0x0000023c : */ 0x18000000,0x00000818, /* MOVE FROM dsa_dataout+0x03f8, WHEN DATA_OUT -at 0x00000240 : */ 0x18000000,0x00000820, +at 0x0000023e : */ 0x18000000,0x00000820, /* ENTRY end_data_trans end_data_trans: redo_msgin3: JUMP get_status, WHEN STATUS -at 0x00000242 : */ 0x830b0000,0x000000a0, +at 0x00000240 : */ 0x830b0000,0x00000098, /* JUMP get_msgin3, WHEN MSG_IN -at 0x00000244 : */ 0x870b0000,0x00000b20, +at 0x00000242 : */ 0x870b0000,0x00000b78, /* INT int_data_bad_phase -at 0x00000246 : */ 0x98080000,0xab93000b, +at 0x00000244 : */ 0x98080000,0xab93000b, /* get_msgin1: MOVE SCRATCH0 | had_msgin TO SCRATCH0 -at 0x00000248 : */ 0x7a344000,0x00000000, +at 0x00000246 : */ 0x7a344000,0x00000000, /* MOVE 1, msgin_buf, WHEN MSG_IN -at 0x0000024a : */ 0x0f000001,0x00000000, +at 0x00000248 : */ 0x0f000001,0x00000000, /* JUMP ext_msg1, IF 0x01 ; Extended Message -at 0x0000024c : */ 0x800c0001,0x00000968, +at 0x0000024a : */ 0x800c0001,0x00000960, /* JUMP ignore_msg1, IF 0x02 ; Save Data Pointers -at 0x0000024e : */ 0x800c0002,0x00000958, +at 0x0000024c : */ 0x800c0002,0x00000950, /* JUMP ignore_msg1, IF 0x03 ; Save Restore Pointers -at 0x00000250 : */ 0x800c0003,0x00000958, +at 0x0000024e : */ 0x800c0003,0x00000950, /* JUMP disc1, IF 0x04 ; Disconnect -at 0x00000252 : */ 0x800c0004,0x000009c8, +at 0x00000250 : */ 0x800c0004,0x000009f0, /* INT int_bad_msg1 -at 0x00000254 : */ 0x98080000,0xab930006, +at 0x00000252 : */ 0x98080000,0xab930006, /* ignore_msg1: CLEAR ACK -at 0x00000256 : */ 0x60000040,0x00000000, +at 0x00000254 : */ 0x60000040,0x00000000, /* JUMP redo_msgin1 -at 0x00000258 : */ 0x80080000,0x00000058, +at 0x00000256 : */ 0x80080000,0x00000050, /* ext_msg1: MOVE SCRATCH0 | had_extmsg TO SCRATCH0 -at 0x0000025a : */ 0x7a348000,0x00000000, +at 0x00000258 : */ 0x7a348000,0x00000000, /* CLEAR ACK -at 0x0000025c : */ 0x60000040,0x00000000, +at 0x0000025a : */ 0x60000040,0x00000000, /* MOVE 1, msgin_buf + 1, WHEN MSG_IN -at 0x0000025e : */ 0x0f000001,0x00000001, +at 0x0000025c : */ 0x0f000001,0x00000001, /* - JUMP ext_msg1a, IF 0x03 + JUMP reject_msg1, IF NOT 0x03 ; Only handle SDTR -at 0x00000260 : */ 0x800c0003,0x00000990, +at 0x0000025e : */ 0x80040003,0x000009b0, /* - INT int_bad_extmsg1a + CLEAR ACK -at 0x00000262 : */ 0x98080000,0xab930000, +at 0x00000260 : */ 0x60000040,0x00000000, +/* + MOVE 1, msgin_buf + 2, WHEN MSG_IN + +at 0x00000262 : */ 0x0f000001,0x00000002, +/* + JUMP reject_msg1, IF NOT 0x01 ; Only handle SDTR + +at 0x00000264 : */ 0x80040001,0x000009b0, /* -ext_msg1a: CLEAR ACK -at 0x00000264 : */ 0x60000040,0x00000000, +at 0x00000266 : */ 0x60000040,0x00000000, /* - MOVE 1, msgin_buf + 2, WHEN MSG_IN + MOVE 2, msgin_buf + 3, WHEN MSG_IN -at 0x00000266 : */ 0x0f000001,0x00000002, +at 0x00000268 : */ 0x0f000002,0x00000003, /* - JUMP ext_msg1b, IF 0x01 ; Must be SDTR + INT int_msg_sdtr1 + +at 0x0000026a : */ 0x98080000,0xab93000c, +/* +reject_msg1: + MOVE SCRATCH1 | did_reject TO SCRATCH1 -at 0x00000268 : */ 0x800c0001,0x000009b0, +at 0x0000026c : */ 0x7a350100,0x00000000, /* - INT int_bad_extmsg1b + SET ATN -at 0x0000026a : */ 0x98080000,0xab930001, +at 0x0000026e : */ 0x58000008,0x00000000, /* -ext_msg1b: CLEAR ACK -at 0x0000026c : */ 0x60000040,0x00000000, +at 0x00000270 : */ 0x60000040,0x00000000, /* - MOVE 2, msgin_buf + 3, WHEN MSG_IN + JUMP reject_msg1a, WHEN NOT MSG_IN -at 0x0000026e : */ 0x0f000002,0x00000003, +at 0x00000272 : */ 0x87030000,0x000009e0, /* - INT int_msg_sdtr1 + MOVE 1, msgin_buf + 7, WHEN MSG_IN -at 0x00000270 : */ 0x98080000,0xab93000c, +at 0x00000274 : */ 0x0f000001,0x00000007, +/* + JUMP reject_msg1 + +at 0x00000276 : */ 0x80080000,0x000009b0, +/* +reject_msg1a: + MOVE 1, msg_reject, WHEN MSG_OUT + +at 0x00000278 : */ 0x0e000001,0x00000000, +/* + JUMP redo_msgin1 + +at 0x0000027a : */ 0x80080000,0x00000050, /* disc1: CLEAR ACK -at 0x00000272 : */ 0x60000040,0x00000000, +at 0x0000027c : */ 0x60000040,0x00000000, /* ENTRY wait_disc1 wait_disc1: WAIT DISCONNECT -at 0x00000274 : */ 0x48000000,0x00000000, +at 0x0000027e : */ 0x48000000,0x00000000, /* INT int_disc1 -at 0x00000276 : */ 0x98080000,0xab930019, +at 0x00000280 : */ 0x98080000,0xab930019, /* ENTRY resume_msgin1a resume_msgin1a: CLEAR ACK -at 0x00000278 : */ 0x60000040,0x00000000, +at 0x00000282 : */ 0x60000040,0x00000000, /* JUMP redo_msgin1 -at 0x0000027a : */ 0x80080000,0x00000058, +at 0x00000284 : */ 0x80080000,0x00000050, /* ENTRY resume_msgin1b resume_msgin1b: SET ATN -at 0x0000027c : */ 0x58000008,0x00000000, +at 0x00000286 : */ 0x58000008,0x00000000, /* CLEAR ACK -at 0x0000027e : */ 0x60000040,0x00000000, +at 0x00000288 : */ 0x60000040,0x00000000, /* INT int_no_msgout1, WHEN NOT MSG_OUT -at 0x00000280 : */ 0x9e030000,0xab93000f, +at 0x0000028a : */ 0x9e030000,0xab93000f, /* MOVE SCRATCH0 | had_msgout TO SCRATCH0 -at 0x00000282 : */ 0x7a340200,0x00000000, +at 0x0000028c : */ 0x7a340200,0x00000000, /* MOVE FROM dsa_msgout, when MSG_OUT -at 0x00000284 : */ 0x1e000000,0x00000008, +at 0x0000028e : */ 0x1e000000,0x00000008, /* JUMP redo_msgin1 -at 0x00000286 : */ 0x80080000,0x00000058, +at 0x00000290 : */ 0x80080000,0x00000050, /* get_msgin2: MOVE SCRATCH0 | had_msgin TO SCRATCH0 -at 0x00000288 : */ 0x7a344000,0x00000000, +at 0x00000292 : */ 0x7a344000,0x00000000, /* MOVE 1, msgin_buf, WHEN MSG_IN -at 0x0000028a : */ 0x0f000001,0x00000000, +at 0x00000294 : */ 0x0f000001,0x00000000, /* JUMP ext_msg2, IF 0x01 ; Extended Message -at 0x0000028c : */ 0x800c0001,0x00000a68, +at 0x00000296 : */ 0x800c0001,0x00000a90, /* JUMP ignore_msg2, IF 0x02 ; Save Data Pointers -at 0x0000028e : */ 0x800c0002,0x00000a58, +at 0x00000298 : */ 0x800c0002,0x00000a80, /* JUMP ignore_msg2, IF 0x03 ; Save Restore Pointers -at 0x00000290 : */ 0x800c0003,0x00000a58, +at 0x0000029a : */ 0x800c0003,0x00000a80, /* JUMP disc2, IF 0x04 ; Disconnect -at 0x00000292 : */ 0x800c0004,0x00000ac8, +at 0x0000029c : */ 0x800c0004,0x00000b20, /* INT int_bad_msg2 -at 0x00000294 : */ 0x98080000,0xab930007, +at 0x0000029e : */ 0x98080000,0xab930007, /* ignore_msg2: CLEAR ACK -at 0x00000296 : */ 0x60000040,0x00000000, +at 0x000002a0 : */ 0x60000040,0x00000000, /* JUMP redo_msgin2 -at 0x00000298 : */ 0x80080000,0x00000078, +at 0x000002a2 : */ 0x80080000,0x00000070, /* ext_msg2: MOVE SCRATCH0 | had_extmsg TO SCRATCH0 -at 0x0000029a : */ 0x7a348000,0x00000000, +at 0x000002a4 : */ 0x7a348000,0x00000000, /* CLEAR ACK -at 0x0000029c : */ 0x60000040,0x00000000, +at 0x000002a6 : */ 0x60000040,0x00000000, /* MOVE 1, msgin_buf + 1, WHEN MSG_IN -at 0x0000029e : */ 0x0f000001,0x00000001, +at 0x000002a8 : */ 0x0f000001,0x00000001, +/* + JUMP reject_msg2, IF NOT 0x03 ; Only handle SDTR + +at 0x000002aa : */ 0x80040003,0x00000ae0, +/* + CLEAR ACK + +at 0x000002ac : */ 0x60000040,0x00000000, /* - JUMP ext_msg2a, IF 0x03 + MOVE 1, msgin_buf + 2, WHEN MSG_IN -at 0x000002a0 : */ 0x800c0003,0x00000a90, +at 0x000002ae : */ 0x0f000001,0x00000002, /* - INT int_bad_extmsg2a + JUMP reject_msg2, IF NOT 0x01 ; Only handle SDTR -at 0x000002a2 : */ 0x98080000,0xab930002, +at 0x000002b0 : */ 0x80040001,0x00000ae0, /* -ext_msg2a: CLEAR ACK -at 0x000002a4 : */ 0x60000040,0x00000000, +at 0x000002b2 : */ 0x60000040,0x00000000, /* - MOVE 1, msgin_buf + 2, WHEN MSG_IN + MOVE 2, msgin_buf + 3, WHEN MSG_IN + +at 0x000002b4 : */ 0x0f000002,0x00000003, +/* + INT int_msg_sdtr2 -at 0x000002a6 : */ 0x0f000001,0x00000002, +at 0x000002b6 : */ 0x98080000,0xab93000d, /* - JUMP ext_msg2b, IF 0x01 ; Must be SDTR +reject_msg2: + MOVE SCRATCH1 | did_reject TO SCRATCH1 -at 0x000002a8 : */ 0x800c0001,0x00000ab0, +at 0x000002b8 : */ 0x7a350100,0x00000000, /* - INT int_bad_extmsg2b + SET ATN -at 0x000002aa : */ 0x98080000,0xab930003, +at 0x000002ba : */ 0x58000008,0x00000000, /* -ext_msg2b: CLEAR ACK -at 0x000002ac : */ 0x60000040,0x00000000, +at 0x000002bc : */ 0x60000040,0x00000000, /* - MOVE 2, msgin_buf + 3, WHEN MSG_IN + JUMP reject_msg2a, WHEN NOT MSG_IN -at 0x000002ae : */ 0x0f000002,0x00000003, +at 0x000002be : */ 0x87030000,0x00000b10, /* - INT int_msg_sdtr2 + MOVE 1, msgin_buf + 7, WHEN MSG_IN + +at 0x000002c0 : */ 0x0f000001,0x00000007, +/* + JUMP reject_msg2 + +at 0x000002c2 : */ 0x80080000,0x00000ae0, +/* +reject_msg2a: + MOVE 1, msg_reject, WHEN MSG_OUT + +at 0x000002c4 : */ 0x0e000001,0x00000000, +/* + JUMP redo_msgin2 -at 0x000002b0 : */ 0x98080000,0xab93000d, +at 0x000002c6 : */ 0x80080000,0x00000070, /* disc2: CLEAR ACK -at 0x000002b2 : */ 0x60000040,0x00000000, +at 0x000002c8 : */ 0x60000040,0x00000000, /* ENTRY wait_disc2 wait_disc2: WAIT DISCONNECT -at 0x000002b4 : */ 0x48000000,0x00000000, +at 0x000002ca : */ 0x48000000,0x00000000, /* INT int_disc2 -at 0x000002b6 : */ 0x98080000,0xab93001a, +at 0x000002cc : */ 0x98080000,0xab93001a, /* ENTRY resume_msgin2a resume_msgin2a: CLEAR ACK -at 0x000002b8 : */ 0x60000040,0x00000000, +at 0x000002ce : */ 0x60000040,0x00000000, /* JUMP redo_msgin2 -at 0x000002ba : */ 0x80080000,0x00000078, +at 0x000002d0 : */ 0x80080000,0x00000070, /* ENTRY resume_msgin2b resume_msgin2b: SET ATN -at 0x000002bc : */ 0x58000008,0x00000000, +at 0x000002d2 : */ 0x58000008,0x00000000, /* CLEAR ACK -at 0x000002be : */ 0x60000040,0x00000000, +at 0x000002d4 : */ 0x60000040,0x00000000, /* INT int_no_msgout2, WHEN NOT MSG_OUT -at 0x000002c0 : */ 0x9e030000,0xab930010, +at 0x000002d6 : */ 0x9e030000,0xab930010, /* MOVE SCRATCH0 | had_msgout TO SCRATCH0 -at 0x000002c2 : */ 0x7a340200,0x00000000, +at 0x000002d8 : */ 0x7a340200,0x00000000, /* MOVE FROM dsa_msgout, when MSG_OUT -at 0x000002c4 : */ 0x1e000000,0x00000008, +at 0x000002da : */ 0x1e000000,0x00000008, /* JUMP redo_msgin2 -at 0x000002c6 : */ 0x80080000,0x00000078, +at 0x000002dc : */ 0x80080000,0x00000070, /* get_msgin3: MOVE SCRATCH0 | had_msgin TO SCRATCH0 -at 0x000002c8 : */ 0x7a344000,0x00000000, +at 0x000002de : */ 0x7a344000,0x00000000, /* MOVE 1, msgin_buf, WHEN MSG_IN -at 0x000002ca : */ 0x0f000001,0x00000000, +at 0x000002e0 : */ 0x0f000001,0x00000000, /* JUMP ext_msg3, IF 0x01 ; Extended Message -at 0x000002cc : */ 0x800c0001,0x00000b68, +at 0x000002e2 : */ 0x800c0001,0x00000bc0, /* JUMP ignore_msg3, IF 0x02 ; Save Data Pointers -at 0x000002ce : */ 0x800c0002,0x00000b58, +at 0x000002e4 : */ 0x800c0002,0x00000bb0, /* JUMP ignore_msg3, IF 0x03 ; Save Restore Pointers -at 0x000002d0 : */ 0x800c0003,0x00000b58, +at 0x000002e6 : */ 0x800c0003,0x00000bb0, /* JUMP disc3, IF 0x04 ; Disconnect -at 0x000002d2 : */ 0x800c0004,0x00000bc8, +at 0x000002e8 : */ 0x800c0004,0x00000c50, /* INT int_bad_msg3 -at 0x000002d4 : */ 0x98080000,0xab930008, +at 0x000002ea : */ 0x98080000,0xab930008, /* ignore_msg3: CLEAR ACK -at 0x000002d6 : */ 0x60000040,0x00000000, +at 0x000002ec : */ 0x60000040,0x00000000, /* JUMP redo_msgin3 -at 0x000002d8 : */ 0x80080000,0x00000908, +at 0x000002ee : */ 0x80080000,0x00000900, /* ext_msg3: MOVE SCRATCH0 | had_extmsg TO SCRATCH0 -at 0x000002da : */ 0x7a348000,0x00000000, +at 0x000002f0 : */ 0x7a348000,0x00000000, /* CLEAR ACK -at 0x000002dc : */ 0x60000040,0x00000000, +at 0x000002f2 : */ 0x60000040,0x00000000, /* MOVE 1, msgin_buf + 1, WHEN MSG_IN -at 0x000002de : */ 0x0f000001,0x00000001, +at 0x000002f4 : */ 0x0f000001,0x00000001, /* - JUMP ext_msg3a, IF 0x03 + JUMP reject_msg3, IF NOT 0x03 ; Only handle SDTR -at 0x000002e0 : */ 0x800c0003,0x00000b90, +at 0x000002f6 : */ 0x80040003,0x00000c10, /* - INT int_bad_extmsg3a + CLEAR ACK -at 0x000002e2 : */ 0x98080000,0xab930004, +at 0x000002f8 : */ 0x60000040,0x00000000, +/* + MOVE 1, msgin_buf + 2, WHEN MSG_IN + +at 0x000002fa : */ 0x0f000001,0x00000002, +/* + JUMP reject_msg3, IF NOT 0x01 ; Only handle SDTR + +at 0x000002fc : */ 0x80040001,0x00000c10, /* -ext_msg3a: CLEAR ACK -at 0x000002e4 : */ 0x60000040,0x00000000, +at 0x000002fe : */ 0x60000040,0x00000000, /* - MOVE 1, msgin_buf + 2, WHEN MSG_IN + MOVE 2, msgin_buf + 3, WHEN MSG_IN + +at 0x00000300 : */ 0x0f000002,0x00000003, +/* + INT int_msg_sdtr3 -at 0x000002e6 : */ 0x0f000001,0x00000002, +at 0x00000302 : */ 0x98080000,0xab93000e, /* - JUMP ext_msg3b, IF 0x01 ; Must be SDTR +reject_msg3: + MOVE SCRATCH1 | did_reject TO SCRATCH1 -at 0x000002e8 : */ 0x800c0001,0x00000bb0, +at 0x00000304 : */ 0x7a350100,0x00000000, /* - INT int_bad_extmsg3b + SET ATN -at 0x000002ea : */ 0x98080000,0xab930005, +at 0x00000306 : */ 0x58000008,0x00000000, /* -ext_msg3b: CLEAR ACK -at 0x000002ec : */ 0x60000040,0x00000000, +at 0x00000308 : */ 0x60000040,0x00000000, /* - MOVE 2, msgin_buf + 3, WHEN MSG_IN + JUMP reject_msg3a, WHEN NOT MSG_IN -at 0x000002ee : */ 0x0f000002,0x00000003, +at 0x0000030a : */ 0x87030000,0x00000c40, /* - INT int_msg_sdtr3 + MOVE 1, msgin_buf + 7, WHEN MSG_IN + +at 0x0000030c : */ 0x0f000001,0x00000007, +/* + JUMP reject_msg3 + +at 0x0000030e : */ 0x80080000,0x00000c10, +/* +reject_msg3a: + MOVE 1, msg_reject, WHEN MSG_OUT -at 0x000002f0 : */ 0x98080000,0xab93000e, +at 0x00000310 : */ 0x0e000001,0x00000000, +/* + JUMP redo_msgin3 + +at 0x00000312 : */ 0x80080000,0x00000900, /* disc3: CLEAR ACK -at 0x000002f2 : */ 0x60000040,0x00000000, +at 0x00000314 : */ 0x60000040,0x00000000, /* ENTRY wait_disc3 wait_disc3: WAIT DISCONNECT -at 0x000002f4 : */ 0x48000000,0x00000000, +at 0x00000316 : */ 0x48000000,0x00000000, /* INT int_disc3 -at 0x000002f6 : */ 0x98080000,0xab93001b, +at 0x00000318 : */ 0x98080000,0xab93001b, /* ENTRY resume_msgin3a resume_msgin3a: CLEAR ACK -at 0x000002f8 : */ 0x60000040,0x00000000, +at 0x0000031a : */ 0x60000040,0x00000000, /* JUMP redo_msgin3 -at 0x000002fa : */ 0x80080000,0x00000908, +at 0x0000031c : */ 0x80080000,0x00000900, /* ENTRY resume_msgin3b resume_msgin3b: SET ATN -at 0x000002fc : */ 0x58000008,0x00000000, +at 0x0000031e : */ 0x58000008,0x00000000, /* CLEAR ACK -at 0x000002fe : */ 0x60000040,0x00000000, +at 0x00000320 : */ 0x60000040,0x00000000, /* INT int_no_msgout3, WHEN NOT MSG_OUT -at 0x00000300 : */ 0x9e030000,0xab930011, +at 0x00000322 : */ 0x9e030000,0xab930011, /* MOVE SCRATCH0 | had_msgout TO SCRATCH0 -at 0x00000302 : */ 0x7a340200,0x00000000, +at 0x00000324 : */ 0x7a340200,0x00000000, /* MOVE FROM dsa_msgout, when MSG_OUT -at 0x00000304 : */ 0x1e000000,0x00000008, +at 0x00000326 : */ 0x1e000000,0x00000008, /* JUMP redo_msgin3 -at 0x00000306 : */ 0x80080000,0x00000908, +at 0x00000328 : */ 0x80080000,0x00000900, /* ENTRY resume_rej_ident resume_rej_ident: CLEAR ATN -at 0x00000308 : */ 0x60000008,0x00000000, +at 0x0000032a : */ 0x60000008,0x00000000, /* MOVE 1, msgin_buf, WHEN MSG_IN -at 0x0000030a : */ 0x0f000001,0x00000000, +at 0x0000032c : */ 0x0f000001,0x00000000, /* INT int_not_rej, IF NOT 0x07 ; Reject -at 0x0000030c : */ 0x98040007,0xab93001c, +at 0x0000032e : */ 0x98040007,0xab93001c, /* CLEAR ACK -at 0x0000030e : */ 0x60000040,0x00000000, +at 0x00000330 : */ 0x60000040,0x00000000, /* JUMP done_ident -at 0x00000310 : */ 0x80080000,0x00000050, +at 0x00000332 : */ 0x80080000,0x00000048, /* ENTRY reselect @@ -1716,73 +1784,92 @@ ; Disable selection timer MOVE CTEST7 | 0x10 TO CTEST7 -at 0x00000312 : */ 0x7a1b1000,0x00000000, +at 0x00000334 : */ 0x7a1b1000,0x00000000, /* WAIT RESELECT resel_err -at 0x00000314 : */ 0x50000000,0x00000c70, +at 0x00000336 : */ 0x50000000,0x00000cf8, /* INT int_resel_not_msgin, WHEN NOT MSG_IN -at 0x00000316 : */ 0x9f030000,0xab930016, +at 0x00000338 : */ 0x9f030000,0xab930016, /* MOVE 1, reselected_identify, WHEN MSG_IN -at 0x00000318 : */ 0x0f000001,0x00000000, +at 0x0000033a : */ 0x0f000001,0x00000000, /* INT int_reselected -at 0x0000031a : */ 0x98080000,0xab930017, +at 0x0000033c : */ 0x98080000,0xab930017, /* resel_err: MOVE CTEST2 & 0x40 TO SFBR -at 0x0000031c : */ 0x74164000,0x00000000, +at 0x0000033e : */ 0x74164000,0x00000000, /* JUMP selected, IF 0x00 -at 0x0000031e : */ 0x800c0000,0x00000cb0, +at 0x00000340 : */ 0x800c0000,0x00000d38, /* MOVE SFBR & 0 TO SFBR -at 0x00000320 : */ 0x7c080000,0x00000000, +at 0x00000342 : */ 0x7c080000,0x00000000, /* ENTRY patch_new_dsa patch_new_dsa: MOVE SFBR | 0x11 TO DSA0 -at 0x00000322 : */ 0x6a101100,0x00000000, +at 0x00000344 : */ 0x6a101100,0x00000000, /* MOVE SFBR | 0x22 TO DSA1 -at 0x00000324 : */ 0x6a112200,0x00000000, +at 0x00000346 : */ 0x6a112200,0x00000000, /* MOVE SFBR | 0x33 TO DSA2 -at 0x00000326 : */ 0x6a123300,0x00000000, +at 0x00000348 : */ 0x6a123300,0x00000000, /* MOVE SFBR | 0x44 TO DSA3 -at 0x00000328 : */ 0x6a134400,0x00000000, +at 0x0000034a : */ 0x6a134400,0x00000000, /* JUMP do_select -at 0x0000032a : */ 0x80080000,0x00000000, +at 0x0000034c : */ 0x80080000,0x00000000, /* selected: INT int_selected -at 0x0000032c : */ 0x98080000,0xab930018, +at 0x0000034e : */ 0x98080000,0xab930018, +/* + +ENTRY test1 +test1: + MOVE MEMORY 4, test1_src, test1_dst + +at 0x00000350 : */ 0xc0000004,0x00000000,0x00000000, +/* + INT int_test1 + +at 0x00000353 : */ 0x98080000,0xab93001d, +}; + +#define A_did_reject 0x00000001 +static u32 A_did_reject_used[] __attribute((unused)) = { + 0x0000026c, + 0x000002b8, + 0x00000304, }; #define A_dsa_cmnd 0x00000010 static u32 A_dsa_cmnd_used[] __attribute((unused)) = { - 0x0000001d, + 0x0000001b, }; #define A_dsa_datain 0x00000028 static u32 A_dsa_datain_used[] __attribute((unused)) = { + 0x0000003b, 0x0000003d, 0x0000003f, 0x00000041, @@ -1910,11 +1997,11 @@ 0x00000135, 0x00000137, 0x00000139, - 0x0000013b, }; #define A_dsa_dataout 0x00000428 static u32 A_dsa_dataout_used[] __attribute((unused)) = { + 0x00000141, 0x00000143, 0x00000145, 0x00000147, @@ -2042,25 +2129,24 @@ 0x0000023b, 0x0000023d, 0x0000023f, - 0x00000241, }; #define A_dsa_msgin 0x00000020 static u32 A_dsa_msgin_used[] __attribute((unused)) = { - 0x0000002f, + 0x0000002d, }; #define A_dsa_msgout 0x00000008 static u32 A_dsa_msgout_used[] __attribute((unused)) = { - 0x00000013, - 0x00000285, - 0x000002c5, - 0x00000305, + 0x00000011, + 0x0000028f, + 0x000002db, + 0x00000327, }; #define A_dsa_select 0x00000000 static u32 A_dsa_select_used[] __attribute((unused)) = { - 0x00000006, + 0x00000004, }; #define A_dsa_size 0x00000828 @@ -2069,285 +2155,290 @@ #define A_dsa_status 0x00000018 static u32 A_dsa_status_used[] __attribute((unused)) = { - 0x0000002b, + 0x00000029, }; #define A_had_cmdout 0x00000004 static u32 A_had_cmdout_used[] __attribute((unused)) = { - 0x0000001a, + 0x00000018, }; #define A_had_datain 0x00000008 static u32 A_had_datain_used[] __attribute((unused)) = { - 0x00000038, + 0x00000036, }; #define A_had_dataout 0x00000010 static u32 A_had_dataout_used[] __attribute((unused)) = { - 0x0000013e, + 0x0000013c, }; #define A_had_extmsg 0x00000080 static u32 A_had_extmsg_used[] __attribute((unused)) = { - 0x0000025a, - 0x0000029a, - 0x000002da, + 0x00000258, + 0x000002a4, + 0x000002f0, }; #define A_had_msgin 0x00000040 static u32 A_had_msgin_used[] __attribute((unused)) = { - 0x00000248, - 0x00000288, - 0x000002c8, + 0x00000246, + 0x00000292, + 0x000002de, }; #define A_had_msgout 0x00000002 static u32 A_had_msgout_used[] __attribute((unused)) = { - 0x00000010, - 0x00000282, - 0x000002c2, - 0x00000302, + 0x0000000e, + 0x0000028c, + 0x000002d8, + 0x00000324, }; #define A_had_select 0x00000001 static u32 A_had_select_used[] __attribute((unused)) = { - 0x0000000c, + 0x0000000a, }; #define A_had_status 0x00000020 static u32 A_had_status_used[] __attribute((unused)) = { }; -#define A_int_bad_extmsg1a 0xab930000 -static u32 A_int_bad_extmsg1a_used[] __attribute((unused)) = { - 0x00000263, -}; - -#define A_int_bad_extmsg1b 0xab930001 -static u32 A_int_bad_extmsg1b_used[] __attribute((unused)) = { - 0x0000026b, -}; - -#define A_int_bad_extmsg2a 0xab930002 -static u32 A_int_bad_extmsg2a_used[] __attribute((unused)) = { - 0x000002a3, -}; - -#define A_int_bad_extmsg2b 0xab930003 -static u32 A_int_bad_extmsg2b_used[] __attribute((unused)) = { - 0x000002ab, -}; - -#define A_int_bad_extmsg3a 0xab930004 -static u32 A_int_bad_extmsg3a_used[] __attribute((unused)) = { - 0x000002e3, -}; - -#define A_int_bad_extmsg3b 0xab930005 -static u32 A_int_bad_extmsg3b_used[] __attribute((unused)) = { - 0x000002eb, -}; - #define A_int_bad_msg1 0xab930006 static u32 A_int_bad_msg1_used[] __attribute((unused)) = { - 0x00000255, + 0x00000253, }; #define A_int_bad_msg2 0xab930007 static u32 A_int_bad_msg2_used[] __attribute((unused)) = { - 0x00000295, + 0x0000029f, }; #define A_int_bad_msg3 0xab930008 static u32 A_int_bad_msg3_used[] __attribute((unused)) = { - 0x000002d5, + 0x000002eb, }; #define A_int_cmd_bad_phase 0xab930009 static u32 A_int_cmd_bad_phase_used[] __attribute((unused)) = { - 0x00000027, + 0x00000025, }; #define A_int_cmd_complete 0xab93000a static u32 A_int_cmd_complete_used[] __attribute((unused)) = { - 0x00000037, + 0x00000035, }; #define A_int_data_bad_phase 0xab93000b static u32 A_int_data_bad_phase_used[] __attribute((unused)) = { - 0x00000247, + 0x00000245, }; #define A_int_disc1 0xab930019 static u32 A_int_disc1_used[] __attribute((unused)) = { - 0x00000277, + 0x00000281, }; #define A_int_disc2 0xab93001a static u32 A_int_disc2_used[] __attribute((unused)) = { - 0x000002b7, + 0x000002cd, }; #define A_int_disc3 0xab93001b static u32 A_int_disc3_used[] __attribute((unused)) = { - 0x000002f7, + 0x00000319, }; #define A_int_msg_sdtr1 0xab93000c static u32 A_int_msg_sdtr1_used[] __attribute((unused)) = { - 0x00000271, + 0x0000026b, }; #define A_int_msg_sdtr2 0xab93000d static u32 A_int_msg_sdtr2_used[] __attribute((unused)) = { - 0x000002b1, + 0x000002b7, }; #define A_int_msg_sdtr3 0xab93000e static u32 A_int_msg_sdtr3_used[] __attribute((unused)) = { - 0x000002f1, + 0x00000303, }; #define A_int_no_msgout1 0xab93000f static u32 A_int_no_msgout1_used[] __attribute((unused)) = { - 0x00000281, + 0x0000028b, }; #define A_int_no_msgout2 0xab930010 static u32 A_int_no_msgout2_used[] __attribute((unused)) = { - 0x000002c1, + 0x000002d7, }; #define A_int_no_msgout3 0xab930011 static u32 A_int_no_msgout3_used[] __attribute((unused)) = { - 0x00000301, + 0x00000323, }; #define A_int_not_cmd_complete 0xab930012 static u32 A_int_not_cmd_complete_used[] __attribute((unused)) = { - 0x00000031, + 0x0000002f, }; #define A_int_not_rej 0xab93001c static u32 A_int_not_rej_used[] __attribute((unused)) = { - 0x0000030d, + 0x0000032f, }; #define A_int_resel_not_msgin 0xab930016 static u32 A_int_resel_not_msgin_used[] __attribute((unused)) = { - 0x00000317, + 0x00000339, }; #define A_int_reselected 0xab930017 static u32 A_int_reselected_used[] __attribute((unused)) = { - 0x0000031b, + 0x0000033d, }; #define A_int_sel_no_ident 0xab930013 static u32 A_int_sel_no_ident_used[] __attribute((unused)) = { - 0x0000000f, + 0x0000000d, }; #define A_int_sel_not_cmd 0xab930014 static u32 A_int_sel_not_cmd_used[] __attribute((unused)) = { - 0x00000019, + 0x00000017, }; #define A_int_selected 0xab930018 static u32 A_int_selected_used[] __attribute((unused)) = { - 0x0000032d, + 0x0000034f, }; #define A_int_status_not_msgin 0xab930015 static u32 A_int_status_not_msgin_used[] __attribute((unused)) = { - 0x0000002d, + 0x0000002b, +}; + +#define A_int_test1 0xab93001d +static u32 A_int_test1_used[] __attribute((unused)) = { + 0x00000354, +}; + +#define A_msg_reject 0x00000000 +static u32 A_msg_reject_used[] __attribute((unused)) = { + 0x00000279, + 0x000002c5, + 0x00000311, }; #define A_msgin_buf 0x00000000 static u32 A_msgin_buf_used[] __attribute((unused)) = { - 0x0000024b, - 0x0000025f, - 0x00000267, - 0x0000026f, - 0x0000028b, - 0x0000029f, - 0x000002a7, + 0x00000249, + 0x0000025d, + 0x00000263, + 0x00000269, + 0x00000275, + 0x00000295, + 0x000002a9, 0x000002af, - 0x000002cb, - 0x000002df, - 0x000002e7, - 0x000002ef, - 0x0000030b, + 0x000002b5, + 0x000002c1, + 0x000002e1, + 0x000002f5, + 0x000002fb, + 0x00000301, + 0x0000030d, + 0x0000032d, }; #define A_reselected_identify 0x00000000 static u32 A_reselected_identify_used[] __attribute((unused)) = { - 0x00000319, + 0x0000033b, +}; + +#define A_test1_dst 0x00000000 +static u32 A_test1_dst_used[] __attribute((unused)) = { + 0x00000352, +}; + +#define A_test1_src 0x00000000 +static u32 A_test1_src_used[] __attribute((unused)) = { + 0x00000351, }; #define Ent_do_select 0x00000000 -#define Ent_done_ident 0x00000050 -#define Ent_end_data_trans 0x00000908 -#define Ent_patch_input_data 0x000000e8 -#define Ent_patch_new_dsa 0x00000c88 -#define Ent_patch_output_data 0x00000500 -#define Ent_reselect 0x00000c48 -#define Ent_resume_cmd 0x00000068 -#define Ent_resume_msgin1a 0x000009e0 -#define Ent_resume_msgin1b 0x000009f0 -#define Ent_resume_msgin2a 0x00000ae0 -#define Ent_resume_msgin2b 0x00000af0 -#define Ent_resume_msgin3a 0x00000be0 -#define Ent_resume_msgin3b 0x00000bf0 -#define Ent_resume_pmm 0x00000078 -#define Ent_resume_rej_ident 0x00000c20 -#define Ent_wait_disc1 0x000009d0 -#define Ent_wait_disc2 0x00000ad0 -#define Ent_wait_disc3 0x00000bd0 -#define Ent_wait_disc_complete 0x000000d0 +#define Ent_done_ident 0x00000048 +#define Ent_end_data_trans 0x00000900 +#define Ent_patch_input_data 0x000000e0 +#define Ent_patch_new_dsa 0x00000d10 +#define Ent_patch_output_data 0x000004f8 +#define Ent_reselect 0x00000cd0 +#define Ent_resume_cmd 0x00000060 +#define Ent_resume_msgin1a 0x00000a08 +#define Ent_resume_msgin1b 0x00000a18 +#define Ent_resume_msgin2a 0x00000b38 +#define Ent_resume_msgin2b 0x00000b48 +#define Ent_resume_msgin3a 0x00000c68 +#define Ent_resume_msgin3b 0x00000c78 +#define Ent_resume_pmm 0x00000070 +#define Ent_resume_rej_ident 0x00000ca8 +#define Ent_test1 0x00000d40 +#define Ent_wait_disc1 0x000009f8 +#define Ent_wait_disc2 0x00000b28 +#define Ent_wait_disc3 0x00000c58 +#define Ent_wait_disc_complete 0x000000c8 static u32 LABELPATCHES[] __attribute((unused)) = { + 0x00000005, 0x00000007, - 0x00000009, + 0x00000013, 0x00000015, - 0x00000017, + 0x0000001d, 0x0000001f, 0x00000021, 0x00000023, - 0x00000025, - 0x0000013d, + 0x0000013b, + 0x00000241, 0x00000243, - 0x00000245, + 0x0000024b, 0x0000024d, 0x0000024f, 0x00000251, - 0x00000253, - 0x00000259, - 0x00000261, - 0x00000269, + 0x00000257, + 0x0000025f, + 0x00000265, + 0x00000273, + 0x00000277, 0x0000027b, - 0x00000287, - 0x0000028d, - 0x0000028f, + 0x00000285, 0x00000291, - 0x00000293, + 0x00000297, 0x00000299, - 0x000002a1, - 0x000002a9, - 0x000002bb, + 0x0000029b, + 0x0000029d, + 0x000002a3, + 0x000002ab, + 0x000002b1, + 0x000002bf, + 0x000002c3, 0x000002c7, - 0x000002cd, - 0x000002cf, 0x000002d1, - 0x000002d3, - 0x000002d9, - 0x000002e1, + 0x000002dd, + 0x000002e3, + 0x000002e5, + 0x000002e7, 0x000002e9, - 0x000002fb, - 0x00000307, - 0x00000311, - 0x00000315, - 0x0000031f, - 0x0000032b, + 0x000002ef, + 0x000002f7, + 0x000002fd, + 0x0000030b, + 0x0000030f, + 0x00000313, + 0x0000031d, + 0x00000329, + 0x00000333, + 0x00000337, + 0x00000341, + 0x0000034d, }; static struct { @@ -2356,6 +2447,6 @@ } EXTERNAL_PATCHES[] __attribute((unused)) = { }; -static u32 INSTRUCTIONS __attribute((unused)) = 407; -static u32 PATCHES __attribute((unused)) = 42; +static u32 INSTRUCTIONS __attribute((unused)) = 426; +static u32 PATCHES __attribute((unused)) = 51; static u32 EXTERNAL_PATCHES_LEN __attribute((unused)) = 0; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/sym53c8xx_2/sym_glue.c linux.19rc3-ac4/drivers/scsi/sym53c8xx_2/sym_glue.c --- linux.19rc3/drivers/scsi/sym53c8xx_2/sym_glue.c 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/sym53c8xx_2/sym_glue.c 2002-07-29 13:58:43.000000000 +0100 @@ -1890,7 +1890,7 @@ sym_name(np)); } else { - if (!pci_set_dma_mask(np->s.device, 0xffffffffUL)) + if (pci_set_dma_mask(np->s.device, 0xffffffffUL)) goto out_err32; } } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/sym53c8xx_2/sym_malloc.c linux.19rc3-ac4/drivers/scsi/sym53c8xx_2/sym_malloc.c --- linux.19rc3/drivers/scsi/sym53c8xx_2/sym_malloc.c 2002-07-29 12:49:57.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/sym53c8xx_2/sym_malloc.c 2002-07-29 15:15:52.000000000 +0100 @@ -143,12 +143,15 @@ a = (m_addr_t) ptr; while (1) { -#ifdef SYM_MEM_FREE_UNUSED if (s == SYM_MEM_CLUSTER_SIZE) { +#ifdef SYM_MEM_FREE_UNUSED M_FREE_MEM_CLUSTER(a); +#else + ((m_link_p) a)->next = h[i].next; + h[i].next = (m_link_p) a; +#endif break; } -#endif b = a ^ s; q = &h[i]; while (q->next && q->next != (m_link_p) b) { diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/u14-34f.c linux.19rc3-ac4/drivers/scsi/u14-34f.c --- linux.19rc3/drivers/scsi/u14-34f.c 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/u14-34f.c 2002-07-29 13:58:43.000000000 +0100 @@ -1,9 +1,26 @@ /* * u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters. * - * 01 Jan 2002 Rev. 6.50 for linux 2.4.16 + * 25 Jun 2002 Rev. 6.70 for linux 2.4.19 + * + Fixed endian-ness problem due to bitfields. + * + * 21 Feb 2002 Rev. 6.52 for linux 2.4.18 + * + Backport from rev. 7.22 (use io_request_lock). + * + * 20 Feb 2002 Rev. 7.22 for linux 2.5.5 + * + Remove any reference to virt_to_bus(). + * + Fix pio hang while detecting multiple HBAs. + * + * 01 Jan 2002 Rev. 7.20 for linux 2.5.1 * + Use the dynamic DMA mapping API. * + * 19 Dec 2001 Rev. 7.02 for linux 2.5.1 + * + Use SCpnt->sc_data_direction if set. + * + Use sglist.page instead of sglist.address. + * + * 11 Dec 2001 Rev. 7.00 for linux 2.5.1 + * + Use host->host_lock instead of io_request_lock. + * * 1 May 2001 Rev. 6.05 for linux 2.4.4 * + Fix data transfer direction for opcode SEND_CUE_SHEET (0x5d) * @@ -23,7 +40,7 @@ * + When loaded as a module, accepts the new parameter boot_options * which value is a string with the same format of the kernel boot * command line options. A valid example is: - * modprobe u14-34f boot_options=\"0x230,0x340,lc:y,mq:4\" + * modprobe u14-34f 'boot_options="0x230,0x340,lc:y,mq:4"' * * 22 Jul 1999 Rev. 5.00 for linux 2.2.10 and 2.3.11 * + Removed pre-2.2 source code compatibility. @@ -382,6 +399,10 @@ #include #include +#if !defined(__BIG_ENDIAN_BITFIELD) && !defined(__LITTLE_ENDIAN_BITFIELD) +#error "Adjust your defines" +#endif + /* Values for the PRODUCT_ID ports for the 14/34F */ #define PRODUCT_ID1 0x56 #define PRODUCT_ID2 0x40 /* NOTE: Only upper nibble is used */ @@ -448,7 +469,7 @@ #define REG_CONFIG2 7 #define REG_OGM 8 #define REG_ICM 12 -#define REGION_SIZE 13 +#define REGION_SIZE 13UL #define BSY_ASSERTED 0x01 #define IRQ_ASSERTED 0x01 #define CMD_RESET 0xc0 @@ -470,14 +491,21 @@ /* MailBox SCSI Command Packet */ struct mscp { - unsigned char opcode: 3; /* type of command */ - unsigned char xdir: 2; /* data transfer direction */ - unsigned char dcn: 1; /* disable disconnect */ - unsigned char ca: 1; /* use cache (if available) */ - unsigned char sg: 1; /* scatter/gather operation */ - unsigned char target: 3; /* SCSI target id */ - unsigned char channel: 2; /* SCSI channel number */ - unsigned char lun: 3; /* SCSI logical unit number */ + +#if defined(__BIG_ENDIAN_BITFIELD) + unsigned char sg:1, ca:1, dcn:1, xdir:2, opcode:3; + unsigned char lun: 3, channel:2, target:3; +#else + unsigned char opcode: 3, /* type of command */ + xdir: 2, /* data transfer direction */ + dcn: 1, /* disable disconnect */ + ca: 1, /* use cache (if available) */ + sg: 1; /* scatter/gather operation */ + unsigned char target: 3, /* SCSI target id */ + channel: 2, /* SCSI channel number */ + lun: 3; /* SCSI logical unit number */ +#endif + unsigned int data_address PACKED; /* transfer data pointer */ unsigned int data_len PACKED; /* length in bytes */ unsigned int link_address PACKED; /* for linking command chains */ @@ -489,11 +517,19 @@ unsigned char adapter_status; /* non-zero indicates HA error */ unsigned char target_status; /* non-zero indicates target error */ unsigned int sense_addr PACKED; + + /* Additional fields begin here. */ Scsi_Cmnd *SCpnt; unsigned int cpp_index; /* cp index */ - struct sg_list *sglist; + + /* All the cp structure is zero filled by queuecommand except the + following CP_TAIL_SIZE bytes, initialized by detect */ + dma_addr_t cp_dma_addr; /* dma handle for this cp structure */ + struct sg_list *sglist; /* pointer to the allocated SG list */ }; +#define CP_TAIL_SIZE (sizeof(struct sglist *) + sizeof(dma_addr_t)) + struct hostdata { struct mscp cp[MAX_MAILBOXES]; /* Mailboxes for this board */ unsigned int cp_stat[MAX_MAILBOXES]; /* FREE, IN_USE, LOCKED, IN_RESET */ @@ -501,7 +537,6 @@ unsigned int iocount; /* Total i/o done for this board */ int board_number; /* Number of this board */ char board_name[16]; /* Name of this board */ - char board_id[256]; /* data from INQUIRY on this board */ int in_reset; /* True if board is doing a reset */ int target_to[MAX_TARGET][MAX_CHANNEL]; /* N. of timeout errors on target */ int target_redo[MAX_TARGET][MAX_CHANNEL]; /* If TRUE redo i/o on target */ @@ -511,9 +546,7 @@ struct pci_dev *pdev; /* Always NULL */ unsigned char heads; unsigned char sectors; - - /* slot != 0 for the U24F, slot == 0 for both the U14F and U34F */ - unsigned char slot; + char board_id[256]; /* data from INQUIRY on this board */ }; static struct Scsi_Host *sh[MAX_BOARDS + 1]; @@ -543,8 +576,6 @@ #define H2DEV(x) cpu_to_le32(x) #define DEV2H(x) le32_to_cpu(x) -#define V2DEV(addr) ((addr) ? H2DEV(virt_to_bus((void *)addr)) : 0) - static void do_interrupt_handler(int, void *, struct pt_regs *); static void flush_dev(Scsi_Device *, unsigned long, unsigned int, unsigned int); static int do_trace = FALSE; @@ -637,13 +668,18 @@ static int board_inquiry(unsigned int j) { struct mscp *cpp; + dma_addr_t id_dma_addr; unsigned int time, limit = 0; + id_dma_addr = pci_map_single(HD(j)->pdev, HD(j)->board_id, + sizeof(HD(j)->board_id), PCI_DMA_BIDIRECTIONAL); cpp = &HD(j)->cp[0]; - memset(cpp, 0, sizeof(struct mscp)); + cpp->cp_dma_addr = pci_map_single(HD(j)->pdev, cpp, sizeof(struct mscp), + PCI_DMA_BIDIRECTIONAL); + memset(cpp, 0, sizeof(struct mscp) - CP_TAIL_SIZE); cpp->opcode = OP_HOST_ADAPTER; cpp->xdir = DTD_IN; - cpp->data_address = V2DEV(HD(j)->board_id); + cpp->data_address = H2DEV(id_dma_addr); cpp->data_len = H2DEV(sizeof(HD(j)->board_id)); cpp->cdb_len = 6; cpp->cdb[0] = HA_CMD_INQUIRY; @@ -659,7 +695,7 @@ outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR); /* Store pointer in OGM address bytes */ - outl(V2DEV(cpp), sh[j]->io_port + REG_OGM); + outl(H2DEV(cpp->cp_dma_addr), sh[j]->io_port + REG_OGM); /* Issue OGM interrupt */ outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR); @@ -675,6 +711,10 @@ return TRUE; } + pci_unmap_single(HD(j)->pdev, cpp->cp_dma_addr, sizeof(struct mscp), + PCI_DMA_BIDIRECTIONAL); + pci_unmap_single(HD(j)->pdev, id_dma_addr, sizeof(HD(j)->board_id), + PCI_DMA_BIDIRECTIONAL); return FALSE; } @@ -706,17 +746,27 @@ }; struct config_1 { - unsigned char bios_segment: 3; - unsigned char removable_disks_as_fixed: 1; - unsigned char interrupt: 2; - unsigned char dma_channel: 2; + +#if defined(__BIG_ENDIAN_BITFIELD) + unsigned char dma_channel: 2, interrupt:2, + removable_disks_as_fixed:1, bios_segment: 3; +#else + unsigned char bios_segment: 3, removable_disks_as_fixed: 1, + interrupt: 2, dma_channel: 2; +#endif + } config_1; struct config_2 { - unsigned char ha_scsi_id: 3; - unsigned char mapping_mode: 2; - unsigned char bios_drive_number: 1; - unsigned char tfr_port: 2; + +#if defined(__BIG_ENDIAN_BITFIELD) + unsigned char tfr_port: 2, bios_drive_number: 1, + mapping_mode: 2, ha_scsi_id: 3; +#else + unsigned char ha_scsi_id: 3, mapping_mode: 2, + bios_drive_number: 1, tfr_port: 2; +#endif + } config_2; char name[16]; @@ -812,6 +862,7 @@ HD(j)->heads = mapping_table[config_2.mapping_mode].heads; HD(j)->sectors = mapping_table[config_2.mapping_mode].sectors; HD(j)->subversion = subversion; + HD(j)->pdev = NULL; HD(j)->board_number = j; if (have_old_firmware) sh[j]->sg_tablesize = MAX_SAFE_SGLIST; @@ -859,6 +910,10 @@ else sprintf(dma_name, "DMA %u", dma_channel); for (i = 0; i < sh[j]->can_queue; i++) + HD(j)->cp[i].cp_dma_addr = pci_map_single(HD(j)->pdev, + &HD(j)->cp[i], sizeof(struct mscp), PCI_DMA_BIDIRECTIONAL); + + for (i = 0; i < sh[j]->can_queue; i++) if (! ((&HD(j)->cp[i])->sglist = kmalloc( sh[j]->sg_tablesize * sizeof(struct sg_list), (sh[j]->unchecked_isa_dma ? GFP_DMA : 0) | GFP_ATOMIC))) { @@ -972,7 +1027,8 @@ } static inline void map_dma(unsigned int i, unsigned int j) { - unsigned int k, count, data_len = 0, pci_dir; + unsigned int data_len = 0; + unsigned int k, count, pci_dir; struct scatterlist *sgpnt; struct mscp *cpp; Scsi_Cmnd *SCpnt; @@ -988,10 +1044,10 @@ if (!SCpnt->use_sg) { - if (!SCpnt->request_bufflen) - cpp->data_address = V2DEV(SCpnt->request_buffer); + /* If we get here with PCI_DMA_NONE, pci_map_single triggers a BUG() */ + if (!SCpnt->request_bufflen) pci_dir = PCI_DMA_BIDIRECTIONAL; - else if (SCpnt->request_buffer) + if (SCpnt->request_buffer) cpp->data_address = H2DEV(pci_map_single(HD(j)->pdev, SCpnt->request_buffer, SCpnt->request_bufflen, pci_dir)); @@ -1010,7 +1066,8 @@ cpp->sg = TRUE; cpp->use_sg = SCpnt->use_sg; - cpp->data_address = V2DEV(cpp->sglist); + cpp->data_address = H2DEV(pci_map_single(HD(j)->pdev, cpp->sglist, + SCpnt->use_sg * sizeof(struct sg_list), pci_dir)); cpp->data_len = H2DEV(data_len); } @@ -1026,13 +1083,14 @@ pci_unmap_single(HD(j)->pdev, DEV2H(cpp->sense_addr), DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE); - if (SCpnt->use_sg) + if (SCpnt->use_sg) pci_unmap_sg(HD(j)->pdev, SCpnt->request_buffer, SCpnt->use_sg, pci_dir); - else if (DEV2H(cpp->data_address) && DEV2H(cpp->data_len)) - pci_unmap_single(HD(j)->pdev, DEV2H(cpp->data_address), - DEV2H(cpp->data_len), pci_dir); + if (!DEV2H(cpp->data_len)) pci_dir = PCI_DMA_BIDIRECTIONAL; + if (DEV2H(cpp->data_address)) + pci_unmap_single(HD(j)->pdev, DEV2H(cpp->data_address), + DEV2H(cpp->data_len), pci_dir); } static void sync_dma(unsigned int i, unsigned int j) { @@ -1047,14 +1105,15 @@ pci_dma_sync_single(HD(j)->pdev, DEV2H(cpp->sense_addr), DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE); - if (SCpnt->use_sg) - pci_dma_sync_sg(HD(j)->pdev, SCpnt->request_buffer, + if (SCpnt->use_sg) + pci_dma_sync_sg(HD(j)->pdev, SCpnt->request_buffer, SCpnt->use_sg, pci_dir); - else if (DEV2H(cpp->data_address) && DEV2H(cpp->data_len)) - pci_dma_sync_single(HD(j)->pdev, DEV2H(cpp->data_address), - DEV2H(cpp->data_len), pci_dir); + if (!DEV2H(cpp->data_len)) pci_dir = PCI_DMA_BIDIRECTIONAL; + if (DEV2H(cpp->data_address)) + pci_dma_sync_single(HD(j)->pdev, DEV2H(cpp->data_address), + DEV2H(cpp->data_len), pci_dir); } static inline void scsi_to_dev_dir(unsigned int i, unsigned int j) { @@ -1090,7 +1149,7 @@ return; } - if (SCpnt->sc_data_direction != SCSI_DATA_UNKNOWN) + if (SCpnt->sc_data_direction != SCSI_DATA_UNKNOWN) panic("%s: qcomm, invalid SCpnt->sc_data_direction.\n", BN(j)); cpp->xdir = DTD_IN; @@ -1143,7 +1202,7 @@ /* Set pointer to control packet structure */ cpp = &HD(j)->cp[i]; - memset(cpp, 0, sizeof(struct mscp) - sizeof(struct sg_list *)); + memset(cpp, 0, sizeof(struct mscp) - CP_TAIL_SIZE); SCpnt->scsi_done = done; cpp->cpp_index = i; SCpnt->host_scribble = (unsigned char *) &cpp->cpp_index; @@ -1182,7 +1241,7 @@ } /* Store pointer in OGM address bytes */ - outl(V2DEV(cpp), sh[j]->io_port + REG_OGM); + outl(H2DEV(cpp->cp_dma_addr), sh[j]->io_port + REG_OGM); /* Issue OGM interrupt */ outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR); @@ -1592,7 +1651,7 @@ continue; } - outl(V2DEV(cpp), sh[j]->io_port + REG_OGM); + outl(H2DEV(cpp->cp_dma_addr), sh[j]->io_port + REG_OGM); outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR); HD(j)->cp_stat[k] = IN_USE; } @@ -1630,11 +1689,11 @@ /* Find the mailbox to be serviced on this board */ for (i = 0; i < sh[j]->can_queue; i++) - if (V2DEV(&(HD(j)->cp[i])) == ret) break; + if (H2DEV(HD(j)->cp[i].cp_dma_addr) == ret) break; if (i >= sh[j]->can_queue) panic("%s: ihdlr, invalid mscp bus address %p, cp0 %p.\n", BN(j), - (void *)ret, (void *)V2DEV(HD(j)->cp)); + (void *)ret, (void *)H2DEV(HD(j)->cp[0].cp_dma_addr)); cpp = &(HD(j)->cp[i]); spp = cpp; @@ -1834,6 +1893,10 @@ for (i = 0; i < sh[j]->can_queue; i++) if ((&HD(j)->cp[i])->sglist) kfree((&HD(j)->cp[i])->sglist); + for (i = 0; i < sh[j]->can_queue; i++) + pci_unmap_single(HD(j)->pdev, HD(j)->cp[i].cp_dma_addr, + sizeof(struct mscp), PCI_DMA_BIDIRECTIONAL); + free_irq(sh[j]->irq, &sha[j]); if (sh[j]->dma_channel != NO_DMA) free_dma(sh[j]->dma_channel); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/u14-34f.h linux.19rc3-ac4/drivers/scsi/u14-34f.h --- linux.19rc3/drivers/scsi/u14-34f.h 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/u14-34f.h 2002-07-29 13:58:43.000000000 +0100 @@ -13,7 +13,7 @@ int u14_34f_reset(Scsi_Cmnd *); int u14_34f_biosparam(Disk *, kdev_t, int *); -#define U14_34F_VERSION "6.50.00" +#define U14_34F_VERSION "6.70.00" #define ULTRASTOR_14_34F { \ name: "UltraStor 14F/34F rev. " U14_34F_VERSION " ", \ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/zalon7xx.c linux.19rc3-ac4/drivers/scsi/zalon7xx.c --- linux.19rc3/drivers/scsi/zalon7xx.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/zalon7xx.c 2002-07-29 13:58:43.000000000 +0100 @@ -0,0 +1,162 @@ +/* + * Zalon 53c7xx device driver. + * By Richard Hirst (rhirst@linuxcare.com) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "scsi.h" +#include "hosts.h" + +/* + * ** Define the BSD style u_int32 and u_int64 type. + * ** Are in fact u_int32_t and u_int64_t :-) + * */ +typedef u32 u_int32; +typedef u64 u_int64; +typedef u_long vm_offset_t; + +#include "zalon7xx.h" + + +/* hosts_* are kluges to pass info between the zalon7xx_detected() +** and the register_parisc_driver() callbacks. +*/ +static Scsi_Host_Template *hosts_tptr; +static int hosts_used=0; +static int zalon_id = 0; + +extern int zalon_attach(Scsi_Host_Template *tpnt, + unsigned long base_addr, + struct parisc_device *dev, + int irq_vector, + int unit + ); + + +#if 0 +/* FIXME: + * Is this function dead code? or is someone planning on using it in the + * future. The clock = (int) pdc_result[16] does not look correct to + * me ... I think it should be iodc_data[16]. Since this cause a compile + * error with the new encapsulated PDC, I'm not compiling in this function. + * - RB + */ +/* poke SCSI clock out of iodc data */ + +static u8 iodc_data[32] __attribute__ ((aligned (64))); +static unsigned long pdc_result[32] __attribute__ ((aligned (16))) ={0,0,0,0}; + +static int +lasi_scsi_clock(void * hpa, int defaultclock) +{ + int clock, status; + + status = pdc_iodc_read(&pdc_result, hpa, 0, &iodc_data, 32 ); + if (status == PDC_RET_OK) { + clock = (int) pdc_result[16]; + } else { + printk(KERN_WARNING "%s: pdc_iodc_read returned %d\n", __FUNCTION__, status); + clock = defaultclock; + } + + printk(KERN_DEBUG "%s: SCSI clock %d\n", __FUNCTION__, clock); + return clock; +} +#endif + +static int __init +zalon_scsi_callback(struct parisc_device *dev) +{ + struct gsc_irq gsc_irq; + u32 zalon_vers; + int irq; + unsigned long zalon = dev->hpa; + + __raw_writel(CMD_RESET, zalon + IO_MODULE_IO_COMMAND); + while (!(__raw_readl(zalon + IO_MODULE_IO_STATUS) & IOSTATUS_RY)) + ; + __raw_writel(IOIIDATA_MINT5EN | IOIIDATA_PACKEN | IOIIDATA_PREFETCHEN, + zalon + IO_MODULE_II_CDATA); + + /* XXX: Save the Zalon version for bug workarounds? */ + zalon_vers = __raw_readl(dev->hpa + IO_MODULE_II_CDATA) & 0x07000000; + zalon_vers >>= 24; + + /* Setup the interrupts first. + ** Later on request_irq() will register the handler. + */ + irq = gsc_alloc_irq(&gsc_irq); + + printk("%s: Zalon vers field is 0x%x, IRQ %d\n", __FUNCTION__, + zalon_vers, irq); + + __raw_writel(gsc_irq.txn_addr | gsc_irq.txn_data, dev->hpa + IO_MODULE_EIM); + + if ( zalon_vers == 0) + printk(KERN_WARNING "%s: Zalon 1.1 or earlier\n", __FUNCTION__); + + /* + ** zalon_attach: returns -1 on failure, 0 on success + */ + hosts_used = zalon_attach(hosts_tptr, dev->hpa + GSC_SCSI_ZALON_OFFSET, + dev, irq, zalon_id); + + if (hosts_used == 0) + zalon_id++; + + hosts_used = (hosts_used == 0); + return (hosts_used == 0); +} + +static struct parisc_device_id zalon_tbl[] = { + { HPHW_A_DMA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00089 }, + { 0, } +}; + +MODULE_DEVICE_TABLE(parisc, zalon_tbl); + +static struct parisc_driver zalon_driver = { + name: "GSC SCSI (Zalon)", + id_table: zalon_tbl, + probe: zalon_scsi_callback, +}; + +int zalon7xx_detect(Scsi_Host_Template *tpnt) +{ + /* "pass" the parameter to the callback functions */ + hosts_tptr = tpnt; + hosts_used = 0; + + /* claim all zalon cards. */ + register_parisc_driver(&zalon_driver); + + /* Check if any callbacks actually found/claimed anything. */ + return (hosts_used != 0); +} + +#ifdef MODULE +extern int ncr53c8xx_release(struct Scsi_Host *host); + +int zalon7xx_release(struct Scsi_Host *host) +{ + ncr53c8xx_release(host); + unregister_parisc_driver(&zalon_driver); + return 1; +} +#endif diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/scsi/zalon7xx.h linux.19rc3-ac4/drivers/scsi/zalon7xx.h --- linux.19rc3/drivers/scsi/zalon7xx.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/scsi/zalon7xx.h 2002-07-29 14:19:07.000000000 +0100 @@ -0,0 +1,60 @@ +#ifndef ZALON7XX_H +#define ZALON7XX_H + +#include + +#include "sym53c8xx_defs.h" + +extern int zalon7xx_detect(Scsi_Host_Template *); + +#include + +extern struct proc_dir_entry proc_scsi_zalon7xx; + +/* borrowed from drivers/scsi/ncr53c8xx.h */ +int ncr53c8xx_abort(Scsi_Cmnd *); +int zalon7xx_detect(Scsi_Host_Template *tpnt); +const char *ncr53c8xx_info(struct Scsi_Host *host); +int ncr53c8xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +int ncr53c8xx_reset(Scsi_Cmnd *, unsigned int); + +#ifdef MODULE +int zalon7xx_release(struct Scsi_Host *); +#else +#define zalon7xx_release NULL +#endif + +#define SCSI_ZALON { proc_name: "zalon720", \ + detect: zalon7xx_detect, \ + release: zalon7xx_release, \ + info: ncr53c8xx_info, \ + queuecommand: ncr53c8xx_queue_command,\ + abort: ncr53c8xx_abort, \ + reset: ncr53c8xx_reset, \ + bios_param: scsicam_bios_param, \ + can_queue: SCSI_NCR_CAN_QUEUE, \ + this_id: 7, \ + sg_tablesize: SCSI_NCR_SG_TABLESIZE, \ + cmd_per_lun: SCSI_NCR_CMD_PER_LUN, \ + use_clustering: DISABLE_CLUSTERING} + + +#define GSC_SCSI_ZALON_OFFSET 0x800 + +#define IO_MODULE_EIM (1*4) +#define IO_MODULE_DC_ADATA (2*4) +#define IO_MODULE_II_CDATA (3*4) +#define IO_MODULE_IO_COMMAND (12*4) +#define IO_MODULE_IO_STATUS (13*4) + +#define IOSTATUS_RY 0x40 +#define IOSTATUS_FE 0x80 +#define IOIIDATA_SMINT5L 0x40000000 +#define IOIIDATA_MINT5EN 0x20000000 +#define IOIIDATA_PACKEN 0x10000000 +#define IOIIDATA_PREFETCHEN 0x08000000 +#define IOIIDATA_IOII 0x00000020 + +#define CMD_RESET 5 + +#endif /* ZALON7XX_H */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/sgi/char/sgiserial.h linux.19rc3-ac4/drivers/sgi/char/sgiserial.h --- linux.19rc3/drivers/sgi/char/sgiserial.h 2002-07-29 12:49:59.000000000 +0100 +++ linux.19rc3-ac4/drivers/sgi/char/sgiserial.h 2002-07-29 13:58:43.000000000 +0100 @@ -406,7 +406,7 @@ /* Read Register 15 (value of WR 15) */ /* Misc inlines */ -extern inline void ZS_CLEARERR(struct sgi_zschannel *channel) +static inline void ZS_CLEARERR(struct sgi_zschannel *channel) { volatile unsigned char junk; @@ -416,7 +416,7 @@ junk = ioc_icontrol->istat0; } -extern inline void ZS_CLEARFIFO(struct sgi_zschannel *channel) +static inline void ZS_CLEARFIFO(struct sgi_zschannel *channel) { volatile unsigned char junk; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/sound/ali5455.c linux.19rc3-ac4/drivers/sound/ali5455.c --- linux.19rc3/drivers/sound/ali5455.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/sound/ali5455.c 2002-07-29 13:58:44.000000000 +0100 @@ -0,0 +1,3731 @@ +/* + * ALI ali5455 and friends ICH driver for Linux + * LEI HU + * + * Built from: + * drivers/sound/i810_audio + * + * The ALi 5455 is similar but not quite identical to the Intel ICH + * series of controllers. Its easier to keep the driver seperated from + * the i810 driver. + * + * 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. + * + * + * ALi 5455 theory of operation + * + * The chipset provides three DMA channels that talk to an AC97 + * CODEC (AC97 is a digital/analog mixer standard). At its simplest + * you get 48Khz audio with basic volume and mixer controls. At the + * best you get rate adaption in the codec. We set the card up so + * that we never take completion interrupts but instead keep the card + * chasing its tail around a ring buffer. This is needed for mmap + * mode audio and happens to work rather well for non-mmap modes too. + * + * The board has one output channel for PCM audio (supported) and + * a stereo line in and mono microphone input. Again these are normally + * locked to 48Khz only. Right now recording is not finished. + * + * There is no midi support, no synth support. Use timidity. To get + * esd working you need to use esd -r 48000 as it won't probe 48KHz + * by default. mpg123 can't handle 48Khz only audio so use xmms. + * + * If you need to force a specific rate set the clocking= option + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef PCI_DEVICE_ID_ALI_5455 +#define PCI_DEVICE_ID_ALI_5455 0x5455 +#endif + +#ifndef PCI_VENDOR_ID_ALI +#define PCI_VENDOR_ID_ALI 0x10b9 +#endif + +static int strict_clocking = 0; +static unsigned int clocking = 0; +static unsigned int codec_pcmout_share_spdif_locked = 0; +static unsigned int codec_independent_spdif_locked = 0; +static unsigned int controller_pcmout_share_spdif_locked = 0; +static unsigned int controller_independent_spdif_locked = 0; +static unsigned int globel = 0; + +#define ADC_RUNNING 1 +#define DAC_RUNNING 2 +#define CODEC_SPDIFOUT_RUNNING 8 +#define CONTROLLER_SPDIFOUT_RUNNING 4 + +#define SPDIF_ENABLE_OUTPUT 4 /* bits 0,1 are PCM */ + +#define ALI5455_FMT_16BIT 1 +#define ALI5455_FMT_STEREO 2 +#define ALI5455_FMT_MASK 3 + +#define SPDIF_ON 0x0004 +#define SURR_ON 0x0010 +#define CENTER_LFE_ON 0x0020 +#define VOL_MUTED 0x8000 + + +#define ALI_SPDIF_OUT_CH_STATUS 0xbf +/* the 810's array of pointers to data buffers */ + +struct sg_item { +#define BUSADDR_MASK 0xFFFFFFFE + u32 busaddr; +#define CON_IOC 0x80000000 /* interrupt on completion */ +#define CON_BUFPAD 0x40000000 /* pad underrun with last sample, else 0 */ +#define CON_BUFLEN_MASK 0x0000ffff /* buffer length in samples */ + u32 control; +}; + +/* an instance of the ali channel */ +#define SG_LEN 32 +struct ali_channel { + /* these sg guys should probably be allocated + seperately as nocache. Must be 8 byte aligned */ + struct sg_item sg[SG_LEN]; /* 32*8 */ + u32 offset; /* 4 */ + u32 port; /* 4 */ + u32 used; + u32 num; +}; + +/* + * we have 3 seperate dma engines. pcm in, pcm out, and mic. + * each dma engine has controlling registers. These goofy + * names are from the datasheet, but make it easy to write + * code while leafing through it. + */ + +#define ENUM_ENGINE(PRE,DIG) \ +enum { \ + PRE##_BDBAR = 0x##DIG##0, /* Buffer Descriptor list Base Address */ \ + PRE##_CIV = 0x##DIG##4, /* Current Index Value */ \ + PRE##_LVI = 0x##DIG##5, /* Last Valid Index */ \ + PRE##_SR = 0x##DIG##6, /* Status Register */ \ + PRE##_PICB = 0x##DIG##8, /* Position In Current Buffer */ \ + PRE##_CR = 0x##DIG##b /* Control Register */ \ +} + +ENUM_ENGINE(OFF, 0); /* Offsets */ +ENUM_ENGINE(PI, 4); /* PCM In */ +ENUM_ENGINE(PO, 5); /* PCM Out */ +ENUM_ENGINE(MC, 6); /* Mic In */ +ENUM_ENGINE(CODECSPDIFOUT, 7); /* CODEC SPDIF OUT */ +ENUM_ENGINE(CONTROLLERSPDIFIN, A); /* CONTROLLER SPDIF In */ +ENUM_ENGINE(CONTROLLERSPDIFOUT, B); /* CONTROLLER SPDIF OUT */ + + +enum { + ALI_SCR = 0x00, /* System Control Register */ + ALI_SSR = 0x04, /* System Status Register */ + ALI_DMACR = 0x08, /* DMA Control Register */ + ALI_FIFOCR1 = 0x0c, /* FIFO Control Register 1 */ + ALI_INTERFACECR = 0x10, /* Interface Control Register */ + ALI_INTERRUPTCR = 0x14, /* Interrupt control Register */ + ALI_INTERRUPTSR = 0x18, /* Interrupt Status Register */ + ALI_FIFOCR2 = 0x1c, /* FIFO Control Register 2 */ + ALI_CPR = 0x20, /* Command Port Register */ + ALI_SPR = 0x24, /* Status Port Register */ + ALI_FIFOCR3 = 0x2c, /* FIFO Control Register 3 */ + ALI_TTSR = 0x30, /* Transmit Tag Slot Register */ + ALI_RTSR = 0x34, /* Receive Tag Slot Register */ + ALI_CSPSR = 0x38, /* Command/Status Port Status Register */ + ALI_CAS = 0x3c, /* Codec Write Semaphore Register */ + ALI_SPDIFCSR = 0xf8, /* spdif channel status register */ + ALI_SPDIFICS = 0xfc /* spdif interface control/status */ +}; + +// x-status register(x:pcm in ,pcm out, mic in,) +/* interrupts for a dma engine */ +#define DMA_INT_FIFO (1<<4) /* fifo under/over flow */ +#define DMA_INT_COMPLETE (1<<3) /* buffer read/write complete and ioc set */ +#define DMA_INT_LVI (1<<2) /* last valid done */ +#define DMA_INT_CELV (1<<1) /* last valid is current */ +#define DMA_INT_DCH (1) /* DMA Controller Halted (happens on LVI interrupts) */ //not eqult intel +#define DMA_INT_MASK (DMA_INT_FIFO|DMA_INT_COMPLETE|DMA_INT_LVI) + +/* interrupts for the whole chip */// by interrupt status register finish + +#define INT_SPDIFOUT (1<<23) /* controller spdif out INTERRUPT */ +#define INT_SPDIFIN (1<<22) +#define INT_CODECSPDIFOUT (1<<19) +#define INT_MICIN (1<<18) +#define INT_PCMOUT (1<<17) +#define INT_PCMIN (1<<16) +#define INT_CPRAIS (1<<7) +#define INT_SPRAIS (1<<5) +#define INT_GPIO (1<<1) +#define INT_MASK (INT_SPDIFOUT|INT_CODECSPDIFOUT|INT_MICIN|INT_PCMOUT|INT_PCMIN) + +#define DRIVER_VERSION "0.02ac" + +/* magic numbers to protect our data structures */ +#define ALI5455_CARD_MAGIC 0x5072696E /* "Prin" */ +#define ALI5455_STATE_MAGIC 0x63657373 /* "cess" */ +#define ALI5455_DMA_MASK 0xffffffff /* DMA buffer mask for pci_alloc_consist */ +#define NR_HW_CH 5 //I think 5 channel + +/* maxinum number of AC97 codecs connected, AC97 2.0 defined 4 */ +#define NR_AC97 2 + +/* Please note that an 8bit mono stream is not valid on this card, you must have a 16bit */ +/* stream at a minimum for this card to be happy */ +static const unsigned sample_size[] = { 1, 2, 2, 4 }; +/* Samples are 16bit values, so we are shifting to a word, not to a byte, hence shift */ +/* values are one less than might be expected */ +static const unsigned sample_shift[] = { -1, 0, 0, 1 }; + +#define ALI5455 +static char *card_names[] = { + "ALI 5455" +}; + +static struct pci_device_id ali_pci_tbl[] __initdata = { + {PCI_VENDOR_ID_ALI, PCI_DEVICE_ID_ALI_5455, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, ALI5455}, + {0,} +}; + +MODULE_DEVICE_TABLE(pci, ali_pci_tbl); + +#ifdef CONFIG_PM +#define PM_SUSPENDED(card) (card->pm_suspended) +#else +#define PM_SUSPENDED(card) (0) +#endif + +/* "software" or virtual channel, an instance of opened /dev/dsp */ +struct ali_state { + unsigned int magic; + struct ali_card *card; /* Card info */ + + /* single open lock mechanism, only used for recording */ + struct semaphore open_sem; + wait_queue_head_t open_wait; + + /* file mode */ + mode_t open_mode; + + /* virtual channel number */ + int virt; + +#ifdef CONFIG_PM + unsigned int pm_saved_dac_rate, pm_saved_adc_rate; +#endif + struct dmabuf { + /* wave sample stuff */ + unsigned int rate; + unsigned char fmt, enable, trigger; + + /* hardware channel */ + struct ali_channel *read_channel; + struct ali_channel *write_channel; + struct ali_channel *codec_spdifout_channel; + struct ali_channel *controller_spdifout_channel; + + /* OSS buffer management stuff */ + void *rawbuf; + dma_addr_t dma_handle; + unsigned buforder; + unsigned numfrag; + unsigned fragshift; + + /* our buffer acts like a circular ring */ + unsigned hwptr; /* where dma last started, updated by update_ptr */ + unsigned swptr; /* where driver last clear/filled, updated by read/write */ + int count; /* bytes to be consumed or been generated by dma machine */ + unsigned total_bytes; /* total bytes dmaed by hardware */ + + unsigned error; /* number of over/underruns */ + wait_queue_head_t wait; /* put process on wait queue when no more space in buffer */ + + /* redundant, but makes calculations easier */ + /* what the hardware uses */ + unsigned dmasize; + unsigned fragsize; + unsigned fragsamples; + + /* what we tell the user to expect */ + unsigned userfrags; + unsigned userfragsize; + + /* OSS stuff */ + unsigned mapped:1; + unsigned ready:1; + unsigned update_flag; + unsigned ossfragsize; + unsigned ossmaxfrags; + unsigned subdivision; + } dmabuf; +}; + + +struct ali_card { + struct ali_channel channel[5]; + unsigned int magic; + + /* We keep ali5455 cards in a linked list */ + struct ali_card *next; + + /* The ali has a certain amount of cross channel interaction + so we use a single per card lock */ + spinlock_t lock; + + /* PCI device stuff */ + struct pci_dev *pci_dev; + u16 pci_id; +#ifdef CONFIG_PM + u16 pm_suspended; + u32 pm_save_state[64 / sizeof(u32)]; + int pm_saved_mixer_settings[SOUND_MIXER_NRDEVICES][NR_AC97]; +#endif + /* soundcore stuff */ + int dev_audio; + + /* structures for abstraction of hardware facilities, codecs, banks and channels */ + struct ac97_codec *ac97_codec[NR_AC97]; + struct ali_state *states[NR_HW_CH]; + + u16 ac97_features; + u16 ac97_status; + u16 channels; + + /* hardware resources */ + unsigned long iobase; + + u32 irq; + + /* Function support */ + struct ali_channel *(*alloc_pcm_channel) (struct ali_card *); + struct ali_channel *(*alloc_rec_pcm_channel) (struct ali_card *); + struct ali_channel *(*alloc_rec_mic_channel) (struct ali_card *); + struct ali_channel *(*alloc_codec_spdifout_channel) (struct ali_card *); + struct ali_channel *(*alloc_controller_spdifout_channel) (struct ali_card *); + void (*free_pcm_channel) (struct ali_card *, int chan); + + /* We have a *very* long init time possibly, so use this to block */ + /* attempts to open our devices before we are ready (stops oops'es) */ + int initializing; +}; + + +static struct ali_card *devs = NULL; + +static int ali_open_mixdev(struct inode *inode, struct file *file); +static int ali_ioctl_mixdev(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg); +static u16 ali_ac97_get(struct ac97_codec *dev, u8 reg); +static void ali_ac97_set(struct ac97_codec *dev, u8 reg, u16 data); + +static struct ali_channel *ali_alloc_pcm_channel(struct ali_card *card) +{ + if (card->channel[1].used == 1) + return NULL; + card->channel[1].used = 1; + return &card->channel[1]; +} + +static struct ali_channel *ali_alloc_rec_pcm_channel(struct ali_card *card) +{ + if (card->channel[0].used == 1) + return NULL; + card->channel[0].used = 1; + return &card->channel[0]; +} + +static struct ali_channel *ali_alloc_rec_mic_channel(struct ali_card *card) +{ + if (card->channel[2].used == 1) + return NULL; + card->channel[2].used = 1; + return &card->channel[2]; +} + +static struct ali_channel *ali_alloc_codec_spdifout_channel(struct ali_card *card) +{ + if (card->channel[3].used == 1) + return NULL; + card->channel[3].used = 1; + return &card->channel[3]; +} + +static struct ali_channel *ali_alloc_controller_spdifout_channel(struct ali_card *card) +{ + if (card->channel[4].used == 1) + return NULL; + card->channel[4].used = 1; + return &card->channel[4]; +} +static void ali_free_pcm_channel(struct ali_card *card, int channel) +{ + card->channel[channel].used = 0; +} + + +//add support codec spdif out +static int ali_valid_spdif_rate(struct ac97_codec *codec, int rate) +{ + unsigned long id = 0L; + + id = (ali_ac97_get(codec, AC97_VENDOR_ID1) << 16); + id |= ali_ac97_get(codec, AC97_VENDOR_ID2) & 0xffff; + switch (id) { + case 0x41445361: /* AD1886 */ + if (rate == 48000) { + return 1; + } + break; + case 0x414c4720: /* ALC650 */ + if (rate == 48000) { + return 1; + } + break; + default: /* all other codecs, until we know otherwiae */ + if (rate == 48000 || rate == 44100 || rate == 32000) { + return 1; + } + break; + } + return (0); +} + +/* ali_set_spdif_output + * + * Configure the S/PDIF output transmitter. When we turn on + * S/PDIF, we turn off the analog output. This may not be + * the right thing to do. + * + * Assumptions: + * The DSP sample rate must already be set to a supported + * S/PDIF rate (32kHz, 44.1kHz, or 48kHz) or we abort. + */ +static void ali_set_spdif_output(struct ali_state *state, int slots, + int rate) +{ + int vol; + int aud_reg; + struct ac97_codec *codec = state->card->ac97_codec[0]; + + if (!(state->card->ac97_features & 4)) { + state->card->ac97_status &= ~SPDIF_ON; + } else { + if (slots == -1) { /* Turn off S/PDIF */ + aud_reg = ali_ac97_get(codec, AC97_EXTENDED_STATUS); + ali_ac97_set(codec, AC97_EXTENDED_STATUS, (aud_reg & ~AC97_EA_SPDIF)); + + /* If the volume wasn't muted before we turned on S/PDIF, unmute it */ + if (!(state->card->ac97_status & VOL_MUTED)) { + aud_reg = ali_ac97_get(codec, AC97_MASTER_VOL_STEREO); + ali_ac97_set(codec, AC97_MASTER_VOL_STEREO, + (aud_reg & ~VOL_MUTED)); + } + state->card->ac97_status &= ~(VOL_MUTED | SPDIF_ON); + return; + } + + vol = ali_ac97_get(codec, AC97_MASTER_VOL_STEREO); + state->card->ac97_status = vol & VOL_MUTED; + + /* Set S/PDIF transmitter sample rate */ + aud_reg = ali_ac97_get(codec, AC97_SPDIF_CONTROL); + switch (rate) { + case 32000: + aud_reg = (aud_reg & AC97_SC_SPSR_MASK) | AC97_SC_SPSR_32K; + break; + case 44100: + aud_reg = (aud_reg & AC97_SC_SPSR_MASK) | AC97_SC_SPSR_44K; + break; + case 48000: + aud_reg = (aud_reg & AC97_SC_SPSR_MASK) | AC97_SC_SPSR_48K; + break; + default: + /* turn off S/PDIF */ + aud_reg = ali_ac97_get(codec, AC97_EXTENDED_STATUS); + ali_ac97_set(codec, AC97_EXTENDED_STATUS, (aud_reg & ~AC97_EA_SPDIF)); + state->card->ac97_status &= ~SPDIF_ON; + return; + } + + ali_ac97_set(codec, AC97_SPDIF_CONTROL, aud_reg); + + aud_reg = ali_ac97_get(codec, AC97_EXTENDED_STATUS); + aud_reg = (aud_reg & AC97_EA_SLOT_MASK) | slots | AC97_EA_SPDIF; + ali_ac97_set(codec, AC97_EXTENDED_STATUS, aud_reg); + + aud_reg = ali_ac97_get(codec, AC97_POWER_CONTROL); + aud_reg |= 0x0002; + ali_ac97_set(codec, AC97_POWER_CONTROL, aud_reg); + udelay(1); + + state->card->ac97_status |= SPDIF_ON; + + /* Check to make sure the configuration is valid */ + aud_reg = ali_ac97_get(codec, AC97_EXTENDED_STATUS); + if (!(aud_reg & 0x0400)) { + /* turn off S/PDIF */ + ali_ac97_set(codec, AC97_EXTENDED_STATUS, (aud_reg & ~AC97_EA_SPDIF)); + state->card->ac97_status &= ~SPDIF_ON; + return; + } + if (codec_independent_spdif_locked > 0) { + aud_reg = ali_ac97_get(codec, 0x6a); + ali_ac97_set(codec, 0x6a, (aud_reg & 0xefff)); + } + /* Mute the analog output */ + /* Should this only mute the PCM volume??? */ + } +} + +/* ali_set_dac_channels + * + * Configure the codec's multi-channel DACs + * + * The logic is backwards. Setting the bit to 1 turns off the DAC. + * + * What about the ICH? We currently configure it using the + * SNDCTL_DSP_CHANNELS ioctl. If we're turnning on the DAC, + * does that imply that we want the ICH set to support + * these channels? + * + * TODO: + * vailidate that the codec really supports these DACs + * before turning them on. + */ +static void ali_set_dac_channels(struct ali_state *state, int channel) +{ + int aud_reg; + struct ac97_codec *codec = state->card->ac97_codec[0]; + + aud_reg = ali_ac97_get(codec, AC97_EXTENDED_STATUS); + aud_reg |= AC97_EA_PRI | AC97_EA_PRJ | AC97_EA_PRK; + state->card->ac97_status &= ~(SURR_ON | CENTER_LFE_ON); + + switch (channel) { + case 2: /* always enabled */ + break; + case 4: + aud_reg &= ~AC97_EA_PRJ; + state->card->ac97_status |= SURR_ON; + break; + case 6: + aud_reg &= ~(AC97_EA_PRJ | AC97_EA_PRI | AC97_EA_PRK); + state->card->ac97_status |= SURR_ON | CENTER_LFE_ON; + break; + default: + break; + } + ali_ac97_set(codec, AC97_EXTENDED_STATUS, aud_reg); + +} + +/* set playback sample rate */ +static unsigned int ali_set_dac_rate(struct ali_state *state, + unsigned int rate) +{ + struct dmabuf *dmabuf = &state->dmabuf; + u32 new_rate; + struct ac97_codec *codec = state->card->ac97_codec[0]; + + if (!(state->card->ac97_features & 0x0001)) { + dmabuf->rate = clocking; + return clocking; + } + + if (rate > 48000) + rate = 48000; + if (rate < 8000) + rate = 8000; + dmabuf->rate = rate; + + /* + * Adjust for misclocked crap + */ + + rate = (rate * clocking) / 48000; + + if (strict_clocking && rate < 8000) { + rate = 8000; + dmabuf->rate = (rate * 48000) / clocking; + } + + new_rate = ac97_set_dac_rate(codec, rate); + if (new_rate != rate) { + dmabuf->rate = (new_rate * 48000) / clocking; + } + rate = new_rate; + return dmabuf->rate; +} + +/* set recording sample rate */ +static unsigned int ali_set_adc_rate(struct ali_state *state, + unsigned int rate) +{ + struct dmabuf *dmabuf = &state->dmabuf; + u32 new_rate; + struct ac97_codec *codec = state->card->ac97_codec[0]; + + if (!(state->card->ac97_features & 0x0001)) { + dmabuf->rate = clocking; + return clocking; + } + + if (rate > 48000) + rate = 48000; + if (rate < 8000) + rate = 8000; + dmabuf->rate = rate; + + /* + * Adjust for misclocked crap + */ + + rate = (rate * clocking) / 48000; + if (strict_clocking && rate < 8000) { + rate = 8000; + dmabuf->rate = (rate * 48000) / clocking; + } + + new_rate = ac97_set_adc_rate(codec, rate); + + if (new_rate != rate) { + dmabuf->rate = (new_rate * 48000) / clocking; + rate = new_rate; + } + return dmabuf->rate; +} + +/* set codec independent spdifout sample rate */ +static unsigned int ali_set_codecspdifout_rate(struct ali_state *state, + unsigned int rate) +{ + struct dmabuf *dmabuf = &state->dmabuf; + + if (!(state->card->ac97_features & 0x0001)) { + dmabuf->rate = clocking; + return clocking; + } + + if (rate > 48000) + rate = 48000; + if (rate < 8000) + rate = 8000; + dmabuf->rate = rate; + + return dmabuf->rate; +} + +/* set controller independent spdif out function sample rate */ +static void ali_set_spdifout_rate(struct ali_state *state, + unsigned int rate) +{ + unsigned char ch_st_sel; + unsigned short status_rate; + + switch (rate) { + case 44100: + status_rate = 0; + break; + case 32000: + status_rate = 0x300; + break; + case 48000: + default: + status_rate = 0x200; + break; + } + + ch_st_sel = inb(state->card->iobase + ALI_SPDIFICS) & ALI_SPDIF_OUT_CH_STATUS; //select spdif_out + + ch_st_sel |= 0x80; //select right + outb(ch_st_sel, (state->card->iobase + ALI_SPDIFICS)); + outb(status_rate | 0x20, (state->card->iobase + ALI_SPDIFCSR + 2)); + + ch_st_sel &= (~0x80); //select left + outb(ch_st_sel, (state->card->iobase + ALI_SPDIFICS)); + outw(status_rate | 0x10, (state->card->iobase + ALI_SPDIFCSR + 2)); +} + +/* get current playback/recording dma buffer pointer (byte offset from LBA), + called with spinlock held! */ + +static inline unsigned ali_get_dma_addr(struct ali_state *state, int rec) +{ + struct dmabuf *dmabuf = &state->dmabuf; + unsigned int civ, offset, port, port_picb; + unsigned int data; + + if (!dmabuf->enable) + return 0; + + if (rec == 1) + port = state->card->iobase + dmabuf->read_channel->port; + else if (rec == 2) + port = state->card->iobase + dmabuf->codec_spdifout_channel->port; + else if (rec == 3) + port = state->card->iobase + dmabuf->controller_spdifout_channel->port; + else + port = state->card->iobase + dmabuf->write_channel->port; + + port_picb = port + OFF_PICB; + + do { + civ = inb(port + OFF_CIV) & 31; + offset = inw(port_picb); + /* Must have a delay here! */ + if (offset == 0) + udelay(1); + + /* Reread both registers and make sure that that total + * offset from the first reading to the second is 0. + * There is an issue with SiS hardware where it will count + * picb down to 0, then update civ to the next value, + * then set the new picb to fragsize bytes. We can catch + * it between the civ update and the picb update, making + * it look as though we are 1 fragsize ahead of where we + * are. The next to we get the address though, it will + * be back in thdelay is more than long enough + * that we won't have to worry about the chip still being + * out of sync with reality ;-) + */ + } while (civ != (inb(port + OFF_CIV) & 31) || offset != inw(port_picb)); + + data = ((civ + 1) * dmabuf->fragsize - (2 * offset)) % dmabuf->dmasize; + if (inw(port_picb) == 0) + data -= 2048; + + return data; +} + +/* Stop recording (lock held) */ +static inline void __stop_adc(struct ali_state *state) +{ + struct dmabuf *dmabuf = &state->dmabuf; + struct ali_card *card = state->card; + + dmabuf->enable &= ~ADC_RUNNING; + + outl((1 << 18) | (1 << 16), card->iobase + ALI_DMACR); + udelay(1); + + outb(0, card->iobase + PI_CR); + while (inb(card->iobase + PI_CR) != 0); + + // now clear any latent interrupt bits (like the halt bit) + outb(inb(card->iobase + PI_SR) | 0x001e, card->iobase + PI_SR); + outl(inl(card->iobase + ALI_INTERRUPTSR) & INT_PCMIN, card->iobase + ALI_INTERRUPTSR); +} + +static void stop_adc(struct ali_state *state) +{ + struct ali_card *card = state->card; + unsigned long flags; + spin_lock_irqsave(&card->lock, flags); + __stop_adc(state); + spin_unlock_irqrestore(&card->lock, flags); +} + +static inline void __start_adc(struct ali_state *state) +{ + struct dmabuf *dmabuf = &state->dmabuf; + + if (dmabuf->count < dmabuf->dmasize && dmabuf->ready + && !dmabuf->enable && (dmabuf->trigger & PCM_ENABLE_INPUT)) { + dmabuf->enable |= ADC_RUNNING; + outb((1 << 4) | (1 << 2), state->card->iobase + PI_CR); + if (state->card->channel[0].used == 1) + outl(1, state->card->iobase + ALI_DMACR); // DMA CONTROL REGISTRER + udelay(100); + if (state->card->channel[2].used == 1) + outl((1 << 2), state->card->iobase + ALI_DMACR); //DMA CONTROL REGISTER + udelay(100); + } +} + +static void start_adc(struct ali_state *state) +{ + struct ali_card *card = state->card; + unsigned long flags; + + spin_lock_irqsave(&card->lock, flags); + __start_adc(state); + spin_unlock_irqrestore(&card->lock, flags); +} + +/* stop playback (lock held) */ +static inline void __stop_dac(struct ali_state *state) +{ + struct dmabuf *dmabuf = &state->dmabuf; + struct ali_card *card = state->card; + + dmabuf->enable &= ~DAC_RUNNING; + outl(0x00020000, card->iobase + 0x08); + outb(0, card->iobase + PO_CR); + while (inb(card->iobase + PO_CR) != 0) + cpu_relax(); + + outb(inb(card->iobase + PO_SR) | 0x001e, card->iobase + PO_SR); + + outl(inl(card->iobase + ALI_INTERRUPTSR) & INT_PCMOUT, card->iobase + ALI_INTERRUPTSR); +} + +static void stop_dac(struct ali_state *state) +{ + struct ali_card *card = state->card; + unsigned long flags; + spin_lock_irqsave(&card->lock, flags); + __stop_dac(state); + spin_unlock_irqrestore(&card->lock, flags); +} + +static inline void __start_dac(struct ali_state *state) +{ + struct dmabuf *dmabuf = &state->dmabuf; + if (dmabuf->count > 0 && dmabuf->ready && !dmabuf->enable && + (dmabuf->trigger & PCM_ENABLE_OUTPUT)) { + dmabuf->enable |= DAC_RUNNING; + outb((1 << 4) | (1 << 2), state->card->iobase + PO_CR); + outl((1 << 1), state->card->iobase + 0x08); //dma control register + } +} + +static void start_dac(struct ali_state *state) +{ + struct ali_card *card = state->card; + unsigned long flags; + spin_lock_irqsave(&card->lock, flags); + __start_dac(state); + spin_unlock_irqrestore(&card->lock, flags); +} + +/* stop codec and controller spdif out (lock held) */ +static inline void __stop_spdifout(struct ali_state *state) +{ + struct dmabuf *dmabuf = &state->dmabuf; + struct ali_card *card = state->card; + + if (codec_independent_spdif_locked > 0) { + dmabuf->enable &= ~CODEC_SPDIFOUT_RUNNING; + outl((1 << 19), card->iobase + 0x08); + outb(0, card->iobase + CODECSPDIFOUT_CR); + + while (inb(card->iobase + CODECSPDIFOUT_CR) != 0) + cpu_relax(); + + outb(inb(card->iobase + CODECSPDIFOUT_SR) | 0x001e, card->iobase + CODECSPDIFOUT_SR); + outl(inl(card->iobase + ALI_INTERRUPTSR) & INT_CODECSPDIFOUT, card->iobase + ALI_INTERRUPTSR); + } else { + if (controller_independent_spdif_locked > 0) { + dmabuf->enable &= ~CONTROLLER_SPDIFOUT_RUNNING; + outl((1 << 23), card->iobase + 0x08); + outb(0, card->iobase + CONTROLLERSPDIFOUT_CR); + while (inb(card->iobase + CONTROLLERSPDIFOUT_CR) != 0) + cpu_relax(); + outb(inb(card->iobase + CONTROLLERSPDIFOUT_SR) | 0x001e, card->iobase + CONTROLLERSPDIFOUT_SR); + outl(inl(card->iobase + ALI_INTERRUPTSR) & INT_SPDIFOUT, card->iobase + ALI_INTERRUPTSR); + } + } +} + +static void stop_spdifout(struct ali_state *state) +{ + struct ali_card *card = state->card; + unsigned long flags; + spin_lock_irqsave(&card->lock, flags); + __stop_spdifout(state); + spin_unlock_irqrestore(&card->lock, flags); +} + +static inline void __start_spdifout(struct ali_state *state) +{ + struct dmabuf *dmabuf = &state->dmabuf; + if (dmabuf->count > 0 && dmabuf->ready && !dmabuf->enable && + (dmabuf->trigger & SPDIF_ENABLE_OUTPUT)) { + if (codec_independent_spdif_locked > 0) { + dmabuf->enable |= CODEC_SPDIFOUT_RUNNING; + outb((1 << 4) | (1 << 2), state->card->iobase + CODECSPDIFOUT_CR); + outl((1 << 3), state->card->iobase + 0x08); //dma control register + } else { + if (controller_independent_spdif_locked > 0) { + dmabuf->enable |= CONTROLLER_SPDIFOUT_RUNNING; + outb((1 << 4) | (1 << 2), state->card->iobase + CONTROLLERSPDIFOUT_CR); + outl((1 << 7), state->card->iobase + 0x08); //dma control register + } + } + } +} + +static void start_spdifout(struct ali_state *state) +{ + struct ali_card *card = state->card; + unsigned long flags; + spin_lock_irqsave(&card->lock, flags); + __start_spdifout(state); + spin_unlock_irqrestore(&card->lock, flags); +} + +#define DMABUF_DEFAULTORDER (16-PAGE_SHIFT) +#define DMABUF_MINORDER 1 + +/* allocate DMA buffer, playback , recording,spdif out buffer should be allocated seperately */ +static int alloc_dmabuf(struct ali_state *state) +{ + struct dmabuf *dmabuf = &state->dmabuf; + void *rawbuf = NULL; + int order, size; + struct page *page, *pend; + + /* If we don't have any oss frag params, then use our default ones */ + if (dmabuf->ossmaxfrags == 0) + dmabuf->ossmaxfrags = 4; + if (dmabuf->ossfragsize == 0) + dmabuf->ossfragsize = (PAGE_SIZE << DMABUF_DEFAULTORDER) / dmabuf->ossmaxfrags; + size = dmabuf->ossfragsize * dmabuf->ossmaxfrags; + + if (dmabuf->rawbuf && (PAGE_SIZE << dmabuf->buforder) == size) + return 0; + /* alloc enough to satisfy the oss params */ + for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) { + if ((PAGE_SIZE << order) > size) + continue; + if ((rawbuf = pci_alloc_consistent(state->card->pci_dev, + PAGE_SIZE << order, + &dmabuf->dma_handle))) + break; + } + if (!rawbuf) + return -ENOMEM; + + dmabuf->ready = dmabuf->mapped = 0; + dmabuf->rawbuf = rawbuf; + dmabuf->buforder = order; + + /* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */ + pend = virt_to_page(rawbuf + (PAGE_SIZE << order) - 1); + for (page = virt_to_page(rawbuf); page <= pend; page++) + mem_map_reserve(page); + return 0; +} + +/* free DMA buffer */ +static void dealloc_dmabuf(struct ali_state *state) +{ + struct dmabuf *dmabuf = &state->dmabuf; + struct page *page, *pend; + + if (dmabuf->rawbuf) { + /* undo marking the pages as reserved */ + pend = virt_to_page(dmabuf->rawbuf + (PAGE_SIZE << dmabuf->buforder) - 1); + for (page = virt_to_page(dmabuf->rawbuf); page <= pend; page++) + mem_map_unreserve(page); + pci_free_consistent(state->card->pci_dev, + PAGE_SIZE << dmabuf->buforder, + dmabuf->rawbuf, dmabuf->dma_handle); + } + dmabuf->rawbuf = NULL; + dmabuf->mapped = dmabuf->ready = 0; +} + +static int prog_dmabuf(struct ali_state *state, unsigned rec) +{ + struct dmabuf *dmabuf = &state->dmabuf; + struct ali_channel *c = NULL; + struct sg_item *sg; + unsigned long flags; + int ret; + unsigned fragint; + int i; + + spin_lock_irqsave(&state->card->lock, flags); + if (dmabuf->enable & DAC_RUNNING) + __stop_dac(state); + if (dmabuf->enable & ADC_RUNNING) + __stop_adc(state); + if (dmabuf->enable & CODEC_SPDIFOUT_RUNNING) + __stop_spdifout(state); + if (dmabuf->enable & CONTROLLER_SPDIFOUT_RUNNING) + __stop_spdifout(state); + + dmabuf->total_bytes = 0; + dmabuf->count = dmabuf->error = 0; + dmabuf->swptr = dmabuf->hwptr = 0; + spin_unlock_irqrestore(&state->card->lock, flags); + + /* allocate DMA buffer, let alloc_dmabuf determine if we are already + * allocated well enough or if we should replace the current buffer + * (assuming one is already allocated, if it isn't, then allocate it). + */ + if ((ret = alloc_dmabuf(state))) + return ret; + + /* FIXME: figure out all this OSS fragment stuff */ + /* I did, it now does what it should according to the OSS API. DL */ + /* We may not have realloced our dmabuf, but the fragment size to + * fragment number ratio may have changed, so go ahead and reprogram + * things + */ + + dmabuf->dmasize = PAGE_SIZE << dmabuf->buforder; + dmabuf->numfrag = SG_LEN; + dmabuf->fragsize = dmabuf->dmasize / dmabuf->numfrag; + dmabuf->fragsamples = dmabuf->fragsize >> 1; + dmabuf->userfragsize = dmabuf->ossfragsize; + dmabuf->userfrags = dmabuf->dmasize / dmabuf->ossfragsize; + + memset(dmabuf->rawbuf, 0, dmabuf->dmasize); + + if (dmabuf->ossmaxfrags == 4) { + fragint = 8; + dmabuf->fragshift = 2; + } else if (dmabuf->ossmaxfrags == 8) { + fragint = 4; + dmabuf->fragshift = 3; + } else if (dmabuf->ossmaxfrags == 16) { + fragint = 2; + dmabuf->fragshift = 4; + } else { + fragint = 1; + dmabuf->fragshift = 5; + } + /* + * Now set up the ring + */ + + if (rec == 1) + c = dmabuf->read_channel; + else if (rec == 2) + c = dmabuf->codec_spdifout_channel; + else if (rec == 3) + c = dmabuf->controller_spdifout_channel; + else if (rec == 0) + c = dmabuf->write_channel; + if (c != NULL) { + sg = &c->sg[0]; + /* + * Load up 32 sg entries and take an interrupt at half + * way (we might want more interrupts later..) + */ + for (i = 0; i < dmabuf->numfrag; i++) { + sg->busaddr = + virt_to_bus(dmabuf->rawbuf + + dmabuf->fragsize * i); + // the card will always be doing 16bit stereo + sg->control = dmabuf->fragsamples; + sg->control |= CON_BUFPAD; //I modify + // set us up to get IOC interrupts as often as needed to + // satisfy numfrag requirements, no more + if (((i + 1) % fragint) == 0) { + sg->control |= CON_IOC; + } + sg++; + } + spin_lock_irqsave(&state->card->lock, flags); + outb(2, state->card->iobase + c->port + OFF_CR); /* reset DMA machine */ + outl(virt_to_bus(&c->sg[0]), state->card->iobase + c->port + OFF_BDBAR); + outb(0, state->card->iobase + c->port + OFF_CIV); + outb(0, state->card->iobase + c->port + OFF_LVI); + spin_unlock_irqrestore(&state->card->lock, flags); + } + /* set the ready flag for the dma buffer */ + dmabuf->ready = 1; + return 0; +} + +static void __ali_update_lvi(struct ali_state *state, int rec) +{ + struct dmabuf *dmabuf = &state->dmabuf; + int x, port; + port = state->card->iobase; + if (rec == 1) + port += dmabuf->read_channel->port; + else if (rec == 2) + port += dmabuf->codec_spdifout_channel->port; + else if (rec == 3) + port += dmabuf->controller_spdifout_channel->port; + else if (rec == 0) + port += dmabuf->write_channel->port; + /* if we are currently stopped, then our CIV is actually set to our + * *last* sg segment and we are ready to wrap to the next. However, + * if we set our LVI to the last sg segment, then it won't wrap to + * the next sg segment, it won't even get a start. So, instead, when + * we are stopped, we set both the LVI value and also we increment + * the CIV value to the next sg segment to be played so that when + * we call start_{dac,adc}, things will operate properly + */ + if (!dmabuf->enable && dmabuf->ready) { + if (rec && dmabuf->count < dmabuf->dmasize && (dmabuf->trigger & PCM_ENABLE_INPUT)) { + outb((inb(port + OFF_CIV) + 1) & 31, port + OFF_LVI); + __start_adc(state); + while (! (inb(port + OFF_CR) & ((1 << 4) | (1 << 2)))) + cpu_relax(); + } else if (!rec && dmabuf->count && (dmabuf->trigger & PCM_ENABLE_OUTPUT)) { + outb((inb(port + OFF_CIV) + 1) & 31, port + OFF_LVI); + __start_dac(state); + while (!(inb(port + OFF_CR) & ((1 << 4) | (1 << 2)))) + cpu_relax(); + } else if (rec && dmabuf->count && (dmabuf->trigger & SPDIF_ENABLE_OUTPUT)) { + if (codec_independent_spdif_locked > 0) { + // outb((inb(port+OFF_CIV))&31, port+OFF_LVI); + outb((inb(port + OFF_CIV) + 1) & 31, port + OFF_LVI); + __start_spdifout(state); + while (!(inb(port + OFF_CR) & ((1 << 4) | (1 << 2)))) + cpu_relax(); + } else { + if (controller_independent_spdif_locked > 0) { + outb((inb(port + OFF_CIV) + 1) & 31, port + OFF_LVI); + __start_spdifout(state); + while (!(inb(port + OFF_CR) & ((1 << 4) | (1 << 2)))) + cpu_relax(); + } + } + } + } + + /* swptr - 1 is the tail of our transfer */ + x = (dmabuf->dmasize + dmabuf->swptr - 1) % dmabuf->dmasize; + x /= dmabuf->fragsize; + outb(x, port + OFF_LVI); +} + +static void ali_update_lvi(struct ali_state *state, int rec) +{ + struct dmabuf *dmabuf = &state->dmabuf; + unsigned long flags; + if (!dmabuf->ready) + return; + spin_lock_irqsave(&state->card->lock, flags); + __ali_update_lvi(state, rec); + spin_unlock_irqrestore(&state->card->lock, flags); +} + +/* update buffer manangement pointers, especially, dmabuf->count and dmabuf->hwptr */ +static void ali_update_ptr(struct ali_state *state) +{ + struct dmabuf *dmabuf = &state->dmabuf; + unsigned hwptr; + int diff; + + /* error handling and process wake up for DAC */ + if (dmabuf->enable == ADC_RUNNING) { + /* update hardware pointer */ + hwptr = ali_get_dma_addr(state, 1); + diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize; + dmabuf->hwptr = hwptr; + dmabuf->total_bytes += diff; + dmabuf->count += diff; + if (dmabuf->count > dmabuf->dmasize) { + /* buffer underrun or buffer overrun */ + /* this is normal for the end of a read */ + /* only give an error if we went past the */ + /* last valid sg entry */ + if ((inb(state->card->iobase + PI_CIV) & 31) != (inb(state->card->iobase + PI_LVI) & 31)) { + printk(KERN_WARNING "ali_audio: DMA overrun on read\n"); + dmabuf->error++; + } + } + if (dmabuf->count > dmabuf->userfragsize) + wake_up(&dmabuf->wait); + } + /* error handling and process wake up for DAC */ + if (dmabuf->enable == DAC_RUNNING) { + /* update hardware pointer */ + hwptr = ali_get_dma_addr(state, 0); + diff = + (dmabuf->dmasize + hwptr - + dmabuf->hwptr) % dmabuf->dmasize; +#if defined(DEBUG_INTERRUPTS) || defined(DEBUG_MMAP) + printk("DAC HWP %d,%d,%d\n", hwptr, dmabuf->hwptr, diff); +#endif + dmabuf->hwptr = hwptr; + dmabuf->total_bytes += diff; + dmabuf->count -= diff; + if (dmabuf->count < 0) { + /* buffer underrun or buffer overrun */ + /* this is normal for the end of a write */ + /* only give an error if we went past the */ + /* last valid sg entry */ + if ((inb(state->card->iobase + PO_CIV) & 31) != (inb(state->card->iobase + PO_LVI) & 31)) { + printk(KERN_WARNING "ali_audio: DMA overrun on write\n"); + printk(KERN_DEBUG "ali_audio: CIV %d, LVI %d, hwptr %x, count %d\n", + inb(state->card->iobase + PO_CIV) & 31, + inb(state->card->iobase + PO_LVI) & 31, + dmabuf->hwptr, + dmabuf->count); + dmabuf->error++; + } + } + if (dmabuf->count < (dmabuf->dmasize - dmabuf->userfragsize)) + wake_up(&dmabuf->wait); + } + + /* error handling and process wake up for CODEC SPDIF OUT */ + if (dmabuf->enable == CODEC_SPDIFOUT_RUNNING) { + /* update hardware pointer */ + hwptr = ali_get_dma_addr(state, 2); + diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize; + dmabuf->hwptr = hwptr; + dmabuf->total_bytes += diff; + dmabuf->count -= diff; + if (dmabuf->count < 0) { + /* buffer underrun or buffer overrun */ + /* this is normal for the end of a write */ + /* only give an error if we went past the */ + /* last valid sg entry */ + if ((inb(state->card->iobase + CODECSPDIFOUT_CIV) & 31) != (inb(state->card->iobase + CODECSPDIFOUT_LVI) & 31)) { + printk(KERN_WARNING "ali_audio: DMA overrun on write\n"); + printk(KERN_DEBUG "ali_audio: CIV %d, LVI %d, hwptr %x, count %d\n", + inb(state->card->iobase + CODECSPDIFOUT_CIV) & 31, + inb(state->card->iobase + CODECSPDIFOUT_LVI) & 31, + dmabuf->hwptr, dmabuf->count); + dmabuf->error++; + } + } + if (dmabuf->count < (dmabuf->dmasize - dmabuf->userfragsize)) + wake_up(&dmabuf->wait); + } + /* error handling and process wake up for CONTROLLER SPDIF OUT */ + if (dmabuf->enable == CONTROLLER_SPDIFOUT_RUNNING) { + /* update hardware pointer */ + hwptr = ali_get_dma_addr(state, 3); + diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize; + dmabuf->hwptr = hwptr; + dmabuf->total_bytes += diff; + dmabuf->count -= diff; + if (dmabuf->count < 0) { + /* buffer underrun or buffer overrun */ + /* this is normal for the end of a write */ + /* only give an error if we went past the */ + /* last valid sg entry */ + if ((inb(state->card->iobase + CONTROLLERSPDIFOUT_CIV) & 31) != (inb(state->card->iobase + CONTROLLERSPDIFOUT_LVI) & 31)) { + printk(KERN_WARNING + "ali_audio: DMA overrun on write\n"); + printk("ali_audio: CIV %d, LVI %d, hwptr %x, " + "count %d\n", + inb(state->card->iobase + CONTROLLERSPDIFOUT_CIV) & 31, + inb(state->card->iobase + CONTROLLERSPDIFOUT_LVI) & 31, + dmabuf->hwptr, dmabuf->count); + dmabuf->error++; + } + } + if (dmabuf->count < (dmabuf->dmasize - dmabuf->userfragsize)) + wake_up(&dmabuf->wait); + } +} + +static inline int ali_get_free_write_space(struct + ali_state + *state) +{ + struct dmabuf *dmabuf = &state->dmabuf; + int free; + ali_update_ptr(state); + // catch underruns during playback + if (dmabuf->count < 0) { + dmabuf->count = 0; + dmabuf->swptr = dmabuf->hwptr; + } + free = dmabuf->dmasize - dmabuf->count; + free -= (dmabuf->hwptr % dmabuf->fragsize); + if (free < 0) + return (0); + return (free); +} + +static inline int ali_get_available_read_data(struct + ali_state + *state) +{ + struct dmabuf *dmabuf = &state->dmabuf; + int avail; + ali_update_ptr(state); + // catch overruns during record + if (dmabuf->count > dmabuf->dmasize) { + dmabuf->count = dmabuf->dmasize; + dmabuf->swptr = dmabuf->hwptr; + } + avail = dmabuf->count; + avail -= (dmabuf->hwptr % dmabuf->fragsize); + if (avail < 0) + return (0); + return (avail); +} + +static int drain_dac(struct ali_state *state, int signals_allowed) +{ + + DECLARE_WAITQUEUE(wait, current); + struct dmabuf *dmabuf = &state->dmabuf; + unsigned long flags; + unsigned long tmo; + int count; + if (!dmabuf->ready) + return 0; + if (dmabuf->mapped) { + stop_dac(state); + return 0; + } + add_wait_queue(&dmabuf->wait, &wait); + for (;;) { + + spin_lock_irqsave(&state->card->lock, flags); + ali_update_ptr(state); + count = dmabuf->count; + spin_unlock_irqrestore(&state->card->lock, flags); + if (count <= 0) + break; + /* + * This will make sure that our LVI is correct, that our + * pointer is updated, and that the DAC is running. We + * have to force the setting of dmabuf->trigger to avoid + * any possible deadlocks. + */ + if (!dmabuf->enable) { + dmabuf->trigger = PCM_ENABLE_OUTPUT; + ali_update_lvi(state, 0); + } + if (signal_pending(current) && signals_allowed) { + break; + } + + /* It seems that we have to set the current state to + * TASK_INTERRUPTIBLE every time to make the process + * really go to sleep. This also has to be *after* the + * update_ptr() call because update_ptr is likely to + * do a wake_up() which will unset this before we ever + * try to sleep, resuling in a tight loop in this code + * instead of actually sleeping and waiting for an + * interrupt to wake us up! + */ + set_current_state(TASK_INTERRUPTIBLE); + /* + * set the timeout to significantly longer than it *should* + * take for the DAC to drain the DMA buffer + */ + tmo = (count * HZ) / (dmabuf->rate); + if (!schedule_timeout(tmo >= 2 ? tmo : 2)) { + printk(KERN_ERR "ali_audio: drain_dac, dma timeout?\n"); + count = 0; + break; + } + } + set_current_state(TASK_RUNNING); + remove_wait_queue(&dmabuf->wait, &wait); + if (count > 0 && signal_pending(current) && signals_allowed) + return -ERESTARTSYS; + stop_dac(state); + return 0; +} + + +static int drain_spdifout(struct ali_state *state, int signals_allowed) +{ + + DECLARE_WAITQUEUE(wait, current); + struct dmabuf *dmabuf = &state->dmabuf; + unsigned long flags; + unsigned long tmo; + int count; + if (!dmabuf->ready) + return 0; + if (dmabuf->mapped) { + stop_spdifout(state); + return 0; + } + add_wait_queue(&dmabuf->wait, &wait); + for (;;) { + + spin_lock_irqsave(&state->card->lock, flags); + ali_update_ptr(state); + count = dmabuf->count; + spin_unlock_irqrestore(&state->card->lock, flags); + if (count <= 0) + break; + /* + * This will make sure that our LVI is correct, that our + * pointer is updated, and that the DAC is running. We + * have to force the setting of dmabuf->trigger to avoid + * any possible deadlocks. + */ + if (!dmabuf->enable) { + if (codec_independent_spdif_locked > 0) { + dmabuf->trigger = SPDIF_ENABLE_OUTPUT; + ali_update_lvi(state, 2); + } else { + if (controller_independent_spdif_locked > 0) { + dmabuf->trigger = SPDIF_ENABLE_OUTPUT; + ali_update_lvi(state, 3); + } + } + } + if (signal_pending(current) && signals_allowed) { + break; + } + + /* It seems that we have to set the current state to + * TASK_INTERRUPTIBLE every time to make the process + * really go to sleep. This also has to be *after* the + * update_ptr() call because update_ptr is likely to + * do a wake_up() which will unset this before we ever + * try to sleep, resuling in a tight loop in this code + * instead of actually sleeping and waiting for an + * interrupt to wake us up! + */ + set_current_state(TASK_INTERRUPTIBLE); + /* + * set the timeout to significantly longer than it *should* + * take for the DAC to drain the DMA buffer + */ + tmo = (count * HZ) / (dmabuf->rate); + if (!schedule_timeout(tmo >= 2 ? tmo : 2)) { + printk(KERN_ERR "ali_audio: drain_spdifout, dma timeout?\n"); + count = 0; + break; + } + } + set_current_state(TASK_RUNNING); + remove_wait_queue(&dmabuf->wait, &wait); + if (count > 0 && signal_pending(current) && signals_allowed) + return -ERESTARTSYS; + stop_spdifout(state); + return 0; +} + +static void ali_channel_interrupt(struct ali_card *card) +{ + int i, count; + + for (i = 0; i < NR_HW_CH; i++) { + struct ali_state *state = card->states[i]; + struct ali_channel *c = NULL; + struct dmabuf *dmabuf; + unsigned long port = card->iobase; + u16 status; + if (!state) + continue; + if (!state->dmabuf.ready) + continue; + dmabuf = &state->dmabuf; + if (codec_independent_spdif_locked > 0) { + if (dmabuf->enable & CODEC_SPDIFOUT_RUNNING) { + c = dmabuf->codec_spdifout_channel; + } + } else { + if (controller_independent_spdif_locked > 0) { + if (dmabuf->enable & CONTROLLER_SPDIFOUT_RUNNING) + c = dmabuf->controller_spdifout_channel; + } else { + if (dmabuf->enable & DAC_RUNNING) { + c = dmabuf->write_channel; + } else if (dmabuf->enable & ADC_RUNNING) { + c = dmabuf->read_channel; + } else + continue; + } + } + port += c->port; + + status = inw(port + OFF_SR); + + if (status & DMA_INT_COMPLETE) { + /* only wake_up() waiters if this interrupt signals + * us being beyond a userfragsize of data open or + * available, and ali_update_ptr() does that for + * us + */ + ali_update_ptr(state); + } + + if (status & DMA_INT_LVI) { + ali_update_ptr(state); + wake_up(&dmabuf->wait); + + if (dmabuf->enable & DAC_RUNNING) + count = dmabuf->count; + else if (dmabuf->enable & ADC_RUNNING) + count = dmabuf->dmasize - dmabuf->count; + else if (dmabuf->enable & CODEC_SPDIFOUT_RUNNING) + count = dmabuf->count; + else if (dmabuf->enable & CONTROLLER_SPDIFOUT_RUNNING) + count = dmabuf->count; + else count = 0; + + if (count > 0) { + if (dmabuf->enable & DAC_RUNNING) + outl((1 << 1), state->card->iobase + ALI_DMACR); + else if (dmabuf->enable & CODEC_SPDIFOUT_RUNNING) + outl((1 << 3), state->card->iobase + ALI_DMACR); + else if (dmabuf->enable & CONTROLLER_SPDIFOUT_RUNNING) + outl((1 << 7), state->card->iobase + ALI_DMACR); + } else { + if (dmabuf->enable & DAC_RUNNING) + __stop_dac(state); + if (dmabuf->enable & ADC_RUNNING) + __stop_adc(state); + if (dmabuf->enable & CODEC_SPDIFOUT_RUNNING) + __stop_spdifout(state); + if (dmabuf->enable & CONTROLLER_SPDIFOUT_RUNNING) + __stop_spdifout(state); + dmabuf->enable = 0; + wake_up(&dmabuf->wait); + } + + } + if (!(status & DMA_INT_DCH)) { + ali_update_ptr(state); + wake_up(&dmabuf->wait); + if (dmabuf->enable & DAC_RUNNING) + count = dmabuf->count; + else if (dmabuf->enable & ADC_RUNNING) + count = dmabuf->dmasize - dmabuf->count; + else if (dmabuf->enable & CODEC_SPDIFOUT_RUNNING) + count = dmabuf->count; + else if (dmabuf->enable & CONTROLLER_SPDIFOUT_RUNNING) + count = dmabuf->count; + else + count = 0; + + if (count > 0) { + if (dmabuf->enable & DAC_RUNNING) + outl((1 << 1), state->card->iobase + ALI_DMACR); + else if (dmabuf->enable & CODEC_SPDIFOUT_RUNNING) + outl((1 << 3), state->card->iobase + ALI_DMACR); + else if (dmabuf->enable & CONTROLLER_SPDIFOUT_RUNNING) + outl((1 << 7), state->card->iobase + ALI_DMACR); + } else { + if (dmabuf->enable & DAC_RUNNING) + __stop_dac(state); + if (dmabuf->enable & ADC_RUNNING) + __stop_adc(state); + if (dmabuf->enable & CODEC_SPDIFOUT_RUNNING) + __stop_spdifout(state); + if (dmabuf->enable & CONTROLLER_SPDIFOUT_RUNNING) + __stop_spdifout(state); + dmabuf->enable = 0; + wake_up(&dmabuf->wait); + } + } + outw(status & DMA_INT_MASK, port + OFF_SR); + } +} + +static void ali_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct ali_card *card = (struct ali_card *) dev_id; + u32 status; + u16 status2; + + spin_lock(&card->lock); + status = inl(card->iobase + ALI_INTERRUPTSR); + if (!(status & INT_MASK)) { + spin_unlock(&card->lock); + return; /* not for us */ + } + + if (codec_independent_spdif_locked > 0) { + if (globel == 0) { + globel += 1; + status2 = inw(card->iobase + 0x76); + outw(status2 | 0x000c, card->iobase + 0x76); + } else { + if (status & (INT_PCMOUT | INT_PCMIN | INT_MICIN | INT_SPDIFOUT | INT_CODECSPDIFOUT)) + ali_channel_interrupt(card); + } + } else { + if (status & (INT_PCMOUT | INT_PCMIN | INT_MICIN | INT_SPDIFOUT | INT_CODECSPDIFOUT)) + ali_channel_interrupt(card); + } + + /* clear 'em */ + outl(status & INT_MASK, card->iobase + ALI_INTERRUPTSR); + spin_unlock(&card->lock); +} + +/* in this loop, dmabuf.count signifies the amount of data that is + waiting to be copied to the user's buffer. It is filled by the dma + machine and drained by this loop. */ + +static ssize_t ali_read(struct file *file, char *buffer, + size_t count, loff_t * ppos) +{ + struct ali_state *state = (struct ali_state *) file->private_data; + struct ali_card *card = state ? state->card : 0; + struct dmabuf *dmabuf = &state->dmabuf; + ssize_t ret; + unsigned long flags; + unsigned int swptr; + int cnt; + DECLARE_WAITQUEUE(waita, current); +#ifdef DEBUG2 + printk("ali_audio: ali_read called, count = %d\n", count); +#endif + if (ppos != &file->f_pos) + return -ESPIPE; + if (dmabuf->mapped) + return -ENXIO; + if (dmabuf->enable & DAC_RUNNING) + return -ENODEV; + if (!dmabuf->read_channel) { + dmabuf->ready = 0; + dmabuf->read_channel = card->alloc_rec_pcm_channel(card); + if (!dmabuf->read_channel) { + return -EBUSY; + } + } + if (!dmabuf->ready && (ret = prog_dmabuf(state, 1))) + return ret; + if (!access_ok(VERIFY_WRITE, buffer, count)) + return -EFAULT; + ret = 0; + add_wait_queue(&dmabuf->wait, &waita); + while (count > 0) { + set_current_state(TASK_INTERRUPTIBLE); + spin_lock_irqsave(&card->lock, flags); + if (PM_SUSPENDED(card)) { + spin_unlock_irqrestore(&card->lock, flags); + schedule(); + if (signal_pending(current)) { + if (!ret) + ret = -EAGAIN; + break; + } + continue; + } + swptr = dmabuf->swptr; + cnt = ali_get_available_read_data(state); + // this is to make the copy_to_user simpler below + if (cnt > (dmabuf->dmasize - swptr)) + cnt = dmabuf->dmasize - swptr; + spin_unlock_irqrestore(&card->lock, flags); + if (cnt > count) + cnt = count; + /* Lop off the last two bits to force the code to always + * write in full samples. This keeps software that sets + * O_NONBLOCK but doesn't check the return value of the + * write call from getting things out of state where they + * think a full 4 byte sample was written when really only + * a portion was, resulting in odd sound and stereo + * hysteresis. + */ + cnt &= ~0x3; + if (cnt <= 0) { + unsigned long tmo; + /* + * Don't let us deadlock. The ADC won't start if + * dmabuf->trigger isn't set. A call to SETTRIGGER + * could have turned it off after we set it to on + * previously. + */ + dmabuf->trigger = PCM_ENABLE_INPUT; + /* + * This does three things. Updates LVI to be correct, + * makes sure the ADC is running, and updates the + * hwptr. + */ + ali_update_lvi(state, 1); + if (file->f_flags & O_NONBLOCK) { + if (!ret) + ret = -EAGAIN; + goto done; + } + /* Set the timeout to how long it would take to fill + * two of our buffers. If we haven't been woke up + * by then, then we know something is wrong. + */ + tmo = (dmabuf->dmasize * HZ * 2) / (dmabuf->rate * 4); + + /* There are two situations when sleep_on_timeout returns, one is when + the interrupt is serviced correctly and the process is waked up by + ISR ON TIME. Another is when timeout is expired, which means that + either interrupt is NOT serviced correctly (pending interrupt) or it + is TOO LATE for the process to be scheduled to run (scheduler latency) + which results in a (potential) buffer overrun. And worse, there is + NOTHING we can do to prevent it. */ + if (!schedule_timeout(tmo >= 2 ? tmo : 2)) { + printk(KERN_ERR + "ali_audio: recording schedule timeout, " + "dmasz %u fragsz %u count %i hwptr %u swptr %u\n", + dmabuf->dmasize, dmabuf->fragsize, + dmabuf->count, dmabuf->hwptr, + dmabuf->swptr); + /* a buffer overrun, we delay the recovery until next time the + while loop begin and we REALLY have space to record */ + } + if (signal_pending(current)) { + ret = ret ? ret : -ERESTARTSYS; + goto done; + } + continue; + } + + if (copy_to_user(buffer, dmabuf->rawbuf + swptr, cnt)) { + if (!ret) + ret = -EFAULT; + goto done; + } + + swptr = (swptr + cnt) % dmabuf->dmasize; + spin_lock_irqsave(&card->lock, flags); + if (PM_SUSPENDED(card)) { + spin_unlock_irqrestore(&card->lock, flags); + continue; + } + dmabuf->swptr = swptr; + dmabuf->count -= cnt; + spin_unlock_irqrestore(&card->lock, flags); + count -= cnt; + buffer += cnt; + ret += cnt; + } +done: + ali_update_lvi(state, 1); + set_current_state(TASK_RUNNING); + remove_wait_queue(&dmabuf->wait, &waita); + return ret; +} + +/* in this loop, dmabuf.count signifies the amount of data that is waiting to be dma to + the soundcard. it is drained by the dma machine and filled by this loop. */ +static ssize_t ali_write(struct file *file, + const char *buffer, size_t count, loff_t * ppos) +{ + struct ali_state *state = (struct ali_state *) file->private_data; + struct ali_card *card = state ? state->card : 0; + struct dmabuf *dmabuf = &state->dmabuf; + ssize_t ret; + unsigned long flags; + unsigned int swptr = 0; + int cnt, x; + DECLARE_WAITQUEUE(waita, current); +#ifdef DEBUG2 + printk("ali_audio: ali_write called, count = %d\n", count); +#endif + if (ppos != &file->f_pos) + return -ESPIPE; + if (dmabuf->mapped) + return -ENXIO; + if (dmabuf->enable & ADC_RUNNING) + return -ENODEV; + if (codec_independent_spdif_locked > 0) { + if (!dmabuf->codec_spdifout_channel) { + dmabuf->ready = 0; + dmabuf->codec_spdifout_channel = card->alloc_codec_spdifout_channel(card); + if (!dmabuf->codec_spdifout_channel) + return -EBUSY; + } + } else { + if (controller_independent_spdif_locked > 0) { + if (!dmabuf->controller_spdifout_channel) { + dmabuf->ready = 0; + dmabuf->controller_spdifout_channel = card->alloc_controller_spdifout_channel(card); + if (!dmabuf->controller_spdifout_channel) + return -EBUSY; + } + } else { + if (!dmabuf->write_channel) { + dmabuf->ready = 0; + dmabuf->write_channel = + card->alloc_pcm_channel(card); + if (!dmabuf->write_channel) + return -EBUSY; + } + } + } + + if (codec_independent_spdif_locked > 0) { + if (!dmabuf->ready && (ret = prog_dmabuf(state, 2))) + return ret; + } else { + if (controller_independent_spdif_locked > 0) { + if (!dmabuf->ready && (ret = prog_dmabuf(state, 3))) + return ret; + } else { + + if (!dmabuf->ready && (ret = prog_dmabuf(state, 0))) + return ret; + } + } + if (!access_ok(VERIFY_READ, buffer, count)) + return -EFAULT; + ret = 0; + add_wait_queue(&dmabuf->wait, &waita); + while (count > 0) { + set_current_state(TASK_INTERRUPTIBLE); + spin_lock_irqsave(&state->card->lock, flags); + if (PM_SUSPENDED(card)) { + spin_unlock_irqrestore(&card->lock, flags); + schedule(); + if (signal_pending(current)) { + if (!ret) + ret = -EAGAIN; + break; + } + continue; + } + + swptr = dmabuf->swptr; + cnt = ali_get_free_write_space(state); + /* Bound the maximum size to how much we can copy to the + * dma buffer before we hit the end. If we have more to + * copy then it will get done in a second pass of this + * loop starting from the beginning of the buffer. + */ + if (cnt > (dmabuf->dmasize - swptr)) + cnt = dmabuf->dmasize - swptr; + spin_unlock_irqrestore(&state->card->lock, flags); +#ifdef DEBUG2 + printk(KERN_INFO + "ali_audio: ali_write: %d bytes available space\n", + cnt); +#endif + if (cnt > count) + cnt = count; + /* Lop off the last two bits to force the code to always + * write in full samples. This keeps software that sets + * O_NONBLOCK but doesn't check the return value of the + * write call from getting things out of state where they + * think a full 4 byte sample was written when really only + * a portion was, resulting in odd sound and stereo + * hysteresis. + */ + cnt &= ~0x3; + if (cnt <= 0) { + unsigned long tmo; + // There is data waiting to be played + /* + * Force the trigger setting since we would + * deadlock with it set any other way + */ + if (codec_independent_spdif_locked > 0) { + dmabuf->trigger = SPDIF_ENABLE_OUTPUT; + ali_update_lvi(state, 2); + } else { + if (controller_independent_spdif_locked > 0) { + dmabuf->trigger = SPDIF_ENABLE_OUTPUT; + ali_update_lvi(state, 3); + } else { + + dmabuf->trigger = PCM_ENABLE_OUTPUT; + ali_update_lvi(state, 0); + } + } + if (file->f_flags & O_NONBLOCK) { + if (!ret) + ret = -EAGAIN; + goto ret; + } + /* Not strictly correct but works */ + tmo = (dmabuf->dmasize * HZ * 2) / (dmabuf->rate * 4); + /* There are two situations when sleep_on_timeout returns, one is when + the interrupt is serviced correctly and the process is waked up by + ISR ON TIME. Another is when timeout is expired, which means that + either interrupt is NOT serviced correctly (pending interrupt) or it + is TOO LATE for the process to be scheduled to run (scheduler latency) + which results in a (potential) buffer underrun. And worse, there is + NOTHING we can do to prevent it. */ + + /* FIXME - do timeout handling here !! */ + + if (signal_pending(current)) { + if (!ret) + ret = -ERESTARTSYS; + goto ret; + } + continue; + } + if (copy_from_user(dmabuf->rawbuf + swptr, buffer, cnt)) { + if (!ret) + ret = -EFAULT; + goto ret; + } + + swptr = (swptr + cnt) % dmabuf->dmasize; + spin_lock_irqsave(&state->card->lock, flags); + if (PM_SUSPENDED(card)) { + spin_unlock_irqrestore(&card->lock, flags); + continue; + } + + dmabuf->swptr = swptr; + dmabuf->count += cnt; + count -= cnt; + buffer += cnt; + ret += cnt; + spin_unlock_irqrestore(&state->card->lock, flags); + } + if (swptr % dmabuf->fragsize) { + x = dmabuf->fragsize - (swptr % dmabuf->fragsize); + memset(dmabuf->rawbuf + swptr, '\0', x); + } +ret: + if (codec_independent_spdif_locked > 0) { + ali_update_lvi(state, 2); + } else { + if (controller_independent_spdif_locked > 0) { + ali_update_lvi(state, 3); + } else { + ali_update_lvi(state, 0); + } + } + set_current_state(TASK_RUNNING); + remove_wait_queue(&dmabuf->wait, &waita); + return ret; +} + +/* No kernel lock - we have our own spinlock */ +static unsigned int ali_poll(struct file *file, struct poll_table_struct + *wait) +{ + struct ali_state *state = (struct ali_state *) file->private_data; + struct dmabuf *dmabuf = &state->dmabuf; + unsigned long flags; + unsigned int mask = 0; + if (!dmabuf->ready) + return 0; + poll_wait(file, &dmabuf->wait, wait); + spin_lock_irqsave(&state->card->lock, flags); + ali_update_ptr(state); + if (file->f_mode & FMODE_READ && dmabuf->enable & ADC_RUNNING) { + if (dmabuf->count >= (signed) dmabuf->fragsize) + mask |= POLLIN | POLLRDNORM; + } + if (file->f_mode & FMODE_WRITE && (dmabuf->enable & (DAC_RUNNING|CODEC_SPDIFOUT_RUNNING|CONTROLLER_SPDIFOUT_RUNNING))) { + if ((signed) dmabuf->dmasize >= dmabuf->count + (signed) dmabuf->fragsize) + mask |= POLLOUT | POLLWRNORM; + } + spin_unlock_irqrestore(&state->card->lock, flags); + return mask; +} + +static int ali_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct ali_state *state = (struct ali_state *) file->private_data; + struct dmabuf *dmabuf = &state->dmabuf; + int ret = -EINVAL; + unsigned long size; + lock_kernel(); + if (vma->vm_flags & VM_WRITE) { + if (!dmabuf->write_channel && (dmabuf->write_channel = state->card->alloc_pcm_channel(state->card)) == NULL) { + ret = -EBUSY; + goto out; + } + } + if (vma->vm_flags & VM_READ) { + if (!dmabuf->read_channel && (dmabuf->read_channel = state->card->alloc_rec_pcm_channel(state->card)) == NULL) { + ret = -EBUSY; + goto out; + } + } + if ((ret = prog_dmabuf(state, 0)) != 0) + goto out; + ret = -EINVAL; + if (vma->vm_pgoff != 0) + goto out; + size = vma->vm_end - vma->vm_start; + if (size > (PAGE_SIZE << dmabuf->buforder)) + goto out; + ret = -EAGAIN; + if (remap_page_range(vma->vm_start, virt_to_phys(dmabuf->rawbuf), size, vma->vm_page_prot)) + goto out; + dmabuf->mapped = 1; + dmabuf->trigger = 0; + ret = 0; +out: + unlock_kernel(); + return ret; +} + +static int ali_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + struct ali_state *state = (struct ali_state *) file->private_data; + struct ali_channel *c = NULL; + struct dmabuf *dmabuf = &state->dmabuf; + unsigned long flags; + audio_buf_info abinfo; + count_info cinfo; + unsigned int i_scr; + int val = 0, ret; + struct ac97_codec *codec = state->card->ac97_codec[0]; +#ifdef DEBUG + printk("ali_audio: ali_ioctl, arg=0x%x, cmd=", + arg ? *(int *) arg : 0); +#endif + switch (cmd) { + case OSS_GETVERSION: +#ifdef DEBUG + printk("OSS_GETVERSION\n"); +#endif + return put_user(SOUND_VERSION, (int *) arg); + case SNDCTL_DSP_RESET: +#ifdef DEBUG + printk("SNDCTL_DSP_RESET\n"); +#endif + spin_lock_irqsave(&state->card->lock, flags); + if (dmabuf->enable == DAC_RUNNING) { + c = dmabuf->write_channel; + __stop_dac(state); + } + if (dmabuf->enable == ADC_RUNNING) { + c = dmabuf->read_channel; + __stop_adc(state); + } + if (dmabuf->enable == CODEC_SPDIFOUT_RUNNING) { + c = dmabuf->codec_spdifout_channel; + __stop_spdifout(state); + } + if (dmabuf->enable == CONTROLLER_SPDIFOUT_RUNNING) { + c = dmabuf->controller_spdifout_channel; + __stop_spdifout(state); + } + if (c != NULL) { + outb(2, state->card->iobase + c->port + OFF_CR); /* reset DMA machine */ + outl(virt_to_bus(&c->sg[0]), + state->card->iobase + c->port + OFF_BDBAR); + outb(0, state->card->iobase + c->port + OFF_CIV); + outb(0, state->card->iobase + c->port + OFF_LVI); + } + + spin_unlock_irqrestore(&state->card->lock, flags); + synchronize_irq(); + dmabuf->ready = 0; + dmabuf->swptr = dmabuf->hwptr = 0; + dmabuf->count = dmabuf->total_bytes = 0; + return 0; + case SNDCTL_DSP_SYNC: +#ifdef DEBUG + printk("SNDCTL_DSP_SYNC\n"); +#endif + if (codec_independent_spdif_locked > 0) { + if (dmabuf->enable != CODEC_SPDIFOUT_RUNNING + || file->f_flags & O_NONBLOCK) + return 0; + if ((val = drain_spdifout(state, 1))) + return val; + } else { + if (controller_independent_spdif_locked > 0) { + if (dmabuf->enable != + CONTROLLER_SPDIFOUT_RUNNING + || file->f_flags & O_NONBLOCK) + return 0; + if ((val = drain_spdifout(state, 1))) + return val; + } else { + if (dmabuf->enable != DAC_RUNNING + || file->f_flags & O_NONBLOCK) + return 0; + if ((val = drain_dac(state, 1))) + return val; + } + } + dmabuf->total_bytes = 0; + return 0; + case SNDCTL_DSP_SPEED: /* set smaple rate */ +#ifdef DEBUG + printk("SNDCTL_DSP_SPEED\n"); +#endif + if (get_user(val, (int *) arg)) + return -EFAULT; + if (val >= 0) { + if (file->f_mode & FMODE_WRITE) { + if ((state->card->ac97_status & SPDIF_ON)) { /* S/PDIF Enabled */ + /* RELTEK ALC650 only support 48000, need to check that */ + if (ali_valid_spdif_rate(codec, val)) { + if (codec_independent_spdif_locked > 0) { + ali_set_spdif_output(state, -1, 0); + stop_spdifout(state); + dmabuf->ready = 0; + /* I add test codec independent spdif out */ + spin_lock_irqsave(&state->card->lock, flags); + ali_set_codecspdifout_rate(state, val); // I modified + spin_unlock_irqrestore(&state->card->lock, flags); + /* Set S/PDIF transmitter rate. */ + i_scr = inl(state->card->iobase + ALI_SCR); + if ((i_scr & 0x00300000) == 0x00100000) { + ali_set_spdif_output(state, AC97_EA_SPSA_7_8, codec_independent_spdif_locked); + } else { + if ((i_scr&0x00300000) == 0x00200000) + { + ali_set_spdif_output(state, AC97_EA_SPSA_6_9, codec_independent_spdif_locked); + } else { + if ((i_scr & 0x00300000) == 0x00300000) { + ali_set_spdif_output(state, AC97_EA_SPSA_10_11, codec_independent_spdif_locked); + } else { + ali_set_spdif_output(state, AC97_EA_SPSA_7_8, codec_independent_spdif_locked); + } + } + } + + if (!(state->card->ac97_status & SPDIF_ON)) { + val = dmabuf->rate; + } + } else { + if (controller_independent_spdif_locked > 0) + { + stop_spdifout(state); + dmabuf->ready = 0; + spin_lock_irqsave(&state->card->lock, flags); + ali_set_spdifout_rate(state, controller_independent_spdif_locked); + spin_unlock_irqrestore(&state->card->lock, flags); + } else { + /* Set DAC rate */ + ali_set_spdif_output(state, -1, 0); + stop_dac(state); + dmabuf->ready = 0; + spin_lock_irqsave(&state->card->lock, flags); + ali_set_dac_rate(state, val); + spin_unlock_irqrestore(&state->card->lock, flags); + /* Set S/PDIF transmitter rate. */ + ali_set_spdif_output(state, AC97_EA_SPSA_3_4, val); + if (!(state->card->ac97_status & SPDIF_ON)) + { + val = dmabuf->rate; + } + } + } + } else { /* Not a valid rate for S/PDIF, ignore it */ + val = dmabuf->rate; + } + } else { + stop_dac(state); + dmabuf->ready = 0; + spin_lock_irqsave(&state->card->lock, flags); + ali_set_dac_rate(state, val); + spin_unlock_irqrestore(&state->card->lock, flags); + } + } + if (file->f_mode & FMODE_READ) { + stop_adc(state); + dmabuf->ready = 0; + spin_lock_irqsave(&state->card->lock, flags); + ali_set_adc_rate(state, val); + spin_unlock_irqrestore(&state->card->lock, flags); + } + } + return put_user(dmabuf->rate, (int *) arg); + case SNDCTL_DSP_STEREO: /* set stereo or mono channel */ +#ifdef DEBUG + printk("SNDCTL_DSP_STEREO\n"); +#endif + if (dmabuf->enable & DAC_RUNNING) { + stop_dac(state); + } + if (dmabuf->enable & ADC_RUNNING) { + stop_adc(state); + } + if (dmabuf->enable & CODEC_SPDIFOUT_RUNNING) { + stop_spdifout(state); + } + if (dmabuf->enable & CONTROLLER_SPDIFOUT_RUNNING) { + stop_spdifout(state); + } + return put_user(1, (int *) arg); + case SNDCTL_DSP_GETBLKSIZE: + if (file->f_mode & FMODE_WRITE) { + if (codec_independent_spdif_locked > 0) { + if (!dmabuf->ready && (val = prog_dmabuf(state, 2))) + return val; + } else { + if (controller_independent_spdif_locked > 0) { + if (!dmabuf->ready && (val = prog_dmabuf(state, 3))) + return val; + } else { + if (!dmabuf->ready && (val = prog_dmabuf(state, 0))) + return val; + } + } + } + + if (file->f_mode & FMODE_READ) { + if (!dmabuf->ready && (val = prog_dmabuf(state, 1))) + return val; + } +#ifdef DEBUG + printk("SNDCTL_DSP_GETBLKSIZE %d\n", dmabuf->userfragsize); +#endif + return put_user(dmabuf->userfragsize, (int *) arg); + case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format */ +#ifdef DEBUG + printk("SNDCTL_DSP_GETFMTS\n"); +#endif + return put_user(AFMT_S16_LE, (int *) arg); + case SNDCTL_DSP_SETFMT: /* Select sample format */ +#ifdef DEBUG + printk("SNDCTL_DSP_SETFMT\n"); +#endif + return put_user(AFMT_S16_LE, (int *) arg); + case SNDCTL_DSP_CHANNELS: // add support 4,6 channel +#ifdef DEBUG + printk("SNDCTL_DSP_CHANNELS\n"); +#endif + if (get_user(val, (int *) arg)) + return -EFAULT; + if (val > 0) { + if (dmabuf->enable & DAC_RUNNING) { + stop_dac(state); + } + if (dmabuf->enable & CODEC_SPDIFOUT_RUNNING) { + stop_spdifout(state); + } + if (dmabuf->enable & CONTROLLER_SPDIFOUT_RUNNING) { + stop_spdifout(state); + } + if (dmabuf->enable & ADC_RUNNING) { + stop_adc(state); + } + } else { + return put_user(state->card->channels, (int *) arg); + } + + i_scr = inl(state->card->iobase + ALI_SCR); + /* Current # of channels enabled */ + if (i_scr & 0x00000100) + ret = 4; + else if (i_scr & 0x00000200) + ret = 6; + else + ret = 2; + switch (val) { + case 2: /* 2 channels is always supported */ + if (codec_independent_spdif_locked > 0) { + outl(((i_scr & 0xfffffcff) | 0x00100000), (state->card->iobase + ALI_SCR)); + } else + outl((i_scr & 0xfffffcff), (state->card->iobase + ALI_SCR)); + /* Do we need to change mixer settings???? */ + break; + case 4: /* Supported on some chipsets, better check first */ + if (codec_independent_spdif_locked > 0) { + outl(((i_scr & 0xfffffcff) | 0x00000100 | 0x00200000), (state->card->iobase + ALI_SCR)); + } else + outl(((i_scr & 0xfffffcff) | 0x00000100), (state->card->iobase + ALI_SCR)); + break; + case 6: /* Supported on some chipsets, better check first */ + if (codec_independent_spdif_locked > 0) { + outl(((i_scr & 0xfffffcff) | 0x00000200 | 0x00008000 | 0x00300000), (state->card->iobase + ALI_SCR)); + } else + outl(((i_scr & 0xfffffcff) | 0x00000200 | 0x00008000), (state->card->iobase + ALI_SCR)); + break; + default: /* nothing else is ever supported by the chipset */ + val = ret; + break; + } + return put_user(val, (int *) arg); + case SNDCTL_DSP_POST: /* the user has sent all data and is notifying us */ + /* we update the swptr to the end of the last sg segment then return */ +#ifdef DEBUG + printk("SNDCTL_DSP_POST\n"); +#endif + if (codec_independent_spdif_locked > 0) { + if (!dmabuf->ready || (dmabuf->enable != CODEC_SPDIFOUT_RUNNING)) + return 0; + } else { + if (controller_independent_spdif_locked > 0) { + if (!dmabuf->ready || (dmabuf->enable != CONTROLLER_SPDIFOUT_RUNNING)) + return 0; + } else { + if (!dmabuf->ready || (dmabuf->enable != DAC_RUNNING)) + return 0; + } + } + if ((dmabuf->swptr % dmabuf->fragsize) != 0) { + val = dmabuf->fragsize - (dmabuf->swptr % dmabuf->fragsize); + dmabuf->swptr += val; + dmabuf->count += val; + } + return 0; + case SNDCTL_DSP_SUBDIVIDE: + if (dmabuf->subdivision) + return -EINVAL; + if (get_user(val, (int *) arg)) + return -EFAULT; + if (val != 1 && val != 2 && val != 4) + return -EINVAL; +#ifdef DEBUG + printk("SNDCTL_DSP_SUBDIVIDE %d\n", val); +#endif + dmabuf->subdivision = val; + dmabuf->ready = 0; + return 0; + case SNDCTL_DSP_SETFRAGMENT: + if (get_user(val, (int *) arg)) + return -EFAULT; + dmabuf->ossfragsize = 1 << (val & 0xffff); + dmabuf->ossmaxfrags = (val >> 16) & 0xffff; + if (!dmabuf->ossfragsize || !dmabuf->ossmaxfrags) + return -EINVAL; + /* + * Bound the frag size into our allowed range of 256 - 4096 + */ + if (dmabuf->ossfragsize < 256) + dmabuf->ossfragsize = 256; + else if (dmabuf->ossfragsize > 4096) + dmabuf->ossfragsize = 4096; + /* + * The numfrags could be something reasonable, or it could + * be 0xffff meaning "Give me as much as possible". So, + * we check the numfrags * fragsize doesn't exceed our + * 64k buffer limit, nor is it less than our 8k minimum. + * If it fails either one of these checks, then adjust the + * number of fragments, not the size of them. It's OK if + * our number of fragments doesn't equal 32 or anything + * like our hardware based number now since we are using + * a different frag count for the hardware. Before we get + * into this though, bound the maxfrags to avoid overflow + * issues. A reasonable bound would be 64k / 256 since our + * maximum buffer size is 64k and our minimum frag size is + * 256. On the other end, our minimum buffer size is 8k and + * our maximum frag size is 4k, so the lower bound should + * be 2. + */ + if (dmabuf->ossmaxfrags > 256) + dmabuf->ossmaxfrags = 256; + else if (dmabuf->ossmaxfrags < 2) + dmabuf->ossmaxfrags = 2; + val = dmabuf->ossfragsize * dmabuf->ossmaxfrags; + while (val < 8192) { + val <<= 1; + dmabuf->ossmaxfrags <<= 1; + } + while (val > 65536) { + val >>= 1; + dmabuf->ossmaxfrags >>= 1; + } + dmabuf->ready = 0; +#ifdef DEBUG + printk("SNDCTL_DSP_SETFRAGMENT 0x%x, %d, %d\n", val, + dmabuf->ossfragsize, dmabuf->ossmaxfrags); +#endif + return 0; + case SNDCTL_DSP_GETOSPACE: + if (!(file->f_mode & FMODE_WRITE)) + return -EINVAL; + if (codec_independent_spdif_locked > 0) { + if (!dmabuf->ready && (val = prog_dmabuf(state, 2)) != 0) + return val; + } else { + if (controller_independent_spdif_locked > 0) { + if (!dmabuf->ready && (val = prog_dmabuf(state, 3)) != 0) + return val; + } else { + if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0) + return val; + } + } + spin_lock_irqsave(&state->card->lock, flags); + ali_update_ptr(state); + abinfo.fragsize = dmabuf->userfragsize; + abinfo.fragstotal = dmabuf->userfrags; + if (dmabuf->mapped) + abinfo.bytes = dmabuf->dmasize; + else + abinfo.bytes = ali_get_free_write_space(state); + abinfo.fragments = abinfo.bytes / dmabuf->userfragsize; + spin_unlock_irqrestore(&state->card->lock, flags); +#if defined(DEBUG) || defined(DEBUG_MMAP) + printk("SNDCTL_DSP_GETOSPACE %d, %d, %d, %d\n", + abinfo.bytes, abinfo.fragsize, abinfo.fragments, + abinfo.fragstotal); +#endif + return copy_to_user((void *) arg, &abinfo, + sizeof(abinfo)) ? -EFAULT : 0; + case SNDCTL_DSP_GETOPTR: + if (!(file->f_mode & FMODE_WRITE)) + return -EINVAL; + if (codec_independent_spdif_locked > 0) { + if (!dmabuf->ready && (val = prog_dmabuf(state, 2)) != 0) + return val; + } else { + if (controller_independent_spdif_locked > 0) { + if (!dmabuf->ready && (val = prog_dmabuf(state, 3)) != 0) + return val; + } else { + if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0) + return val; + } + } + spin_lock_irqsave(&state->card->lock, flags); + val = ali_get_free_write_space(state); + cinfo.bytes = dmabuf->total_bytes; + cinfo.ptr = dmabuf->hwptr; + cinfo.blocks = val / dmabuf->userfragsize; + if (codec_independent_spdif_locked > 0) { + if (dmabuf->mapped && (dmabuf->trigger & SPDIF_ENABLE_OUTPUT)) { + dmabuf->count += val; + dmabuf->swptr = (dmabuf->swptr + val) % dmabuf->dmasize; + __ali_update_lvi(state, 2); + } + } else { + if (controller_independent_spdif_locked > 0) { + if (dmabuf->mapped && (dmabuf->trigger & SPDIF_ENABLE_OUTPUT)) { + dmabuf->count += val; + dmabuf->swptr = (dmabuf->swptr + val) % dmabuf->dmasize; + __ali_update_lvi(state, 3); + } + } else { + if (dmabuf->mapped && (dmabuf->trigger & PCM_ENABLE_OUTPUT)) { + dmabuf->count += val; + dmabuf->swptr = (dmabuf->swptr + val) % dmabuf->dmasize; + __ali_update_lvi(state, 0); + } + } + } + spin_unlock_irqrestore(&state->card->lock, flags); +#if defined(DEBUG) || defined(DEBUG_MMAP) + printk("SNDCTL_DSP_GETOPTR %d, %d, %d, %d\n", cinfo.bytes, + cinfo.blocks, cinfo.ptr, dmabuf->count); +#endif + return copy_to_user((void *) arg, &cinfo, sizeof(cinfo)); + case SNDCTL_DSP_GETISPACE: + if (!(file->f_mode & FMODE_READ)) + return -EINVAL; + if (!dmabuf->ready && (val = prog_dmabuf(state, 1)) != 0) + return val; + spin_lock_irqsave(&state->card->lock, flags); + abinfo.bytes = ali_get_available_read_data(state); + abinfo.fragsize = dmabuf->userfragsize; + abinfo.fragstotal = dmabuf->userfrags; + abinfo.fragments = abinfo.bytes / dmabuf->userfragsize; + spin_unlock_irqrestore(&state->card->lock, flags); +#if defined(DEBUG) || defined(DEBUG_MMAP) + printk("SNDCTL_DSP_GETISPACE %d, %d, %d, %d\n", + abinfo.bytes, abinfo.fragsize, abinfo.fragments, + abinfo.fragstotal); +#endif + return copy_to_user((void *) arg, &abinfo, + sizeof(abinfo)) ? -EFAULT : 0; + case SNDCTL_DSP_GETIPTR: + if (!(file->f_mode & FMODE_READ)) + return -EINVAL; + if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0) + return val; + spin_lock_irqsave(&state->card->lock, flags); + val = ali_get_available_read_data(state); + cinfo.bytes = dmabuf->total_bytes; + cinfo.blocks = val / dmabuf->userfragsize; + cinfo.ptr = dmabuf->hwptr; + if (dmabuf->mapped && (dmabuf->trigger & PCM_ENABLE_INPUT)) { + dmabuf->count -= val; + dmabuf->swptr = (dmabuf->swptr + val) % dmabuf->dmasize; + __ali_update_lvi(state, 1); + } + spin_unlock_irqrestore(&state->card->lock, flags); +#if defined(DEBUG) || defined(DEBUG_MMAP) + printk("SNDCTL_DSP_GETIPTR %d, %d, %d, %d\n", cinfo.bytes, + cinfo.blocks, cinfo.ptr, dmabuf->count); +#endif + return copy_to_user((void *) arg, &cinfo, sizeof(cinfo)); + case SNDCTL_DSP_NONBLOCK: +#ifdef DEBUG + printk("SNDCTL_DSP_NONBLOCK\n"); +#endif + file->f_flags |= O_NONBLOCK; + return 0; + case SNDCTL_DSP_GETCAPS: +#ifdef DEBUG + printk("SNDCTL_DSP_GETCAPS\n"); +#endif + return put_user(DSP_CAP_REALTIME | DSP_CAP_TRIGGER | + DSP_CAP_MMAP | DSP_CAP_BIND, (int *) arg); + case SNDCTL_DSP_GETTRIGGER: + val = 0; +#ifdef DEBUG + printk("SNDCTL_DSP_GETTRIGGER 0x%x\n", dmabuf->trigger); +#endif + return put_user(dmabuf->trigger, (int *) arg); + case SNDCTL_DSP_SETTRIGGER: + if (get_user(val, (int *) arg)) + return -EFAULT; +#if defined(DEBUG) || defined(DEBUG_MMAP) + printk("SNDCTL_DSP_SETTRIGGER 0x%x\n", val); +#endif + if (!(val & PCM_ENABLE_INPUT) && dmabuf->enable == ADC_RUNNING) { + stop_adc(state); + } + if (!(val & PCM_ENABLE_OUTPUT) && dmabuf->enable == DAC_RUNNING) { + stop_dac(state); + } + if (!(val & SPDIF_ENABLE_OUTPUT) && dmabuf->enable == CODEC_SPDIFOUT_RUNNING) { + stop_spdifout(state); + } + if (!(val & SPDIF_ENABLE_OUTPUT) && dmabuf->enable == CONTROLLER_SPDIFOUT_RUNNING) { + stop_spdifout(state); + } + dmabuf->trigger = val; + if (val & PCM_ENABLE_OUTPUT && !(dmabuf->enable & DAC_RUNNING)) { + if (!dmabuf->write_channel) { + dmabuf->ready = 0; + dmabuf->write_channel = state->card->alloc_pcm_channel(state->card); + if (!dmabuf->write_channel) + return -EBUSY; + } + if (!dmabuf->ready && (ret = prog_dmabuf(state, 0))) + return ret; + if (dmabuf->mapped) { + spin_lock_irqsave(&state->card->lock, flags); + ali_update_ptr(state); + dmabuf->count = 0; + dmabuf->swptr = dmabuf->hwptr; + dmabuf->count = ali_get_free_write_space(state); + dmabuf->swptr = (dmabuf->swptr + dmabuf->count) % dmabuf->dmasize; + __ali_update_lvi(state, 0); + spin_unlock_irqrestore(&state->card->lock, + flags); + } else + start_dac(state); + } + if (val & SPDIF_ENABLE_OUTPUT && !(dmabuf->enable & CODEC_SPDIFOUT_RUNNING)) { + if (!dmabuf->codec_spdifout_channel) { + dmabuf->ready = 0; + dmabuf->codec_spdifout_channel = state->card->alloc_codec_spdifout_channel(state->card); + if (!dmabuf->codec_spdifout_channel) + return -EBUSY; + } + if (!dmabuf->ready && (ret = prog_dmabuf(state, 2))) + return ret; + if (dmabuf->mapped) { + spin_lock_irqsave(&state->card->lock, flags); + ali_update_ptr(state); + dmabuf->count = 0; + dmabuf->swptr = dmabuf->hwptr; + dmabuf->count = ali_get_free_write_space(state); + dmabuf->swptr = (dmabuf->swptr + dmabuf->count) % dmabuf->dmasize; + __ali_update_lvi(state, 2); + spin_unlock_irqrestore(&state->card->lock, + flags); + } else + start_spdifout(state); + } + if (val & SPDIF_ENABLE_OUTPUT && !(dmabuf->enable & CONTROLLER_SPDIFOUT_RUNNING)) { + if (!dmabuf->controller_spdifout_channel) { + dmabuf->ready = 0; + dmabuf->controller_spdifout_channel = state->card->alloc_controller_spdifout_channel(state->card); + if (!dmabuf->controller_spdifout_channel) + return -EBUSY; + } + if (!dmabuf->ready && (ret = prog_dmabuf(state, 3))) + return ret; + if (dmabuf->mapped) { + spin_lock_irqsave(&state->card->lock, flags); + ali_update_ptr(state); + dmabuf->count = 0; + dmabuf->swptr = dmabuf->hwptr; + dmabuf->count = ali_get_free_write_space(state); + dmabuf->swptr = (dmabuf->swptr + dmabuf->count) % dmabuf->dmasize; + __ali_update_lvi(state, 3); + spin_unlock_irqrestore(&state->card->lock, flags); + } else + start_spdifout(state); + } + if (val & PCM_ENABLE_INPUT && !(dmabuf->enable & ADC_RUNNING)) { + if (!dmabuf->read_channel) { + dmabuf->ready = 0; + dmabuf->read_channel = state->card->alloc_rec_pcm_channel(state->card); + if (!dmabuf->read_channel) + return -EBUSY; + } + if (!dmabuf->ready && (ret = prog_dmabuf(state, 1))) + return ret; + if (dmabuf->mapped) { + spin_lock_irqsave(&state->card->lock, + flags); + ali_update_ptr(state); + dmabuf->swptr = dmabuf->hwptr; + dmabuf->count = 0; + spin_unlock_irqrestore(&state->card->lock, flags); + } + ali_update_lvi(state, 1); + start_adc(state); + } + return 0; + case SNDCTL_DSP_SETDUPLEX: +#ifdef DEBUG + printk("SNDCTL_DSP_SETDUPLEX\n"); +#endif + return -EINVAL; + case SNDCTL_DSP_GETODELAY: + if (!(file->f_mode & FMODE_WRITE)) + return -EINVAL; + spin_lock_irqsave(&state->card->lock, flags); + ali_update_ptr(state); + val = dmabuf->count; + spin_unlock_irqrestore(&state->card->lock, flags); +#ifdef DEBUG + printk("SNDCTL_DSP_GETODELAY %d\n", dmabuf->count); +#endif + return put_user(val, (int *) arg); + case SOUND_PCM_READ_RATE: +#ifdef DEBUG + printk("SOUND_PCM_READ_RATE %d\n", dmabuf->rate); +#endif + return put_user(dmabuf->rate, (int *) arg); + case SOUND_PCM_READ_CHANNELS: +#ifdef DEBUG + printk("SOUND_PCM_READ_CHANNELS\n"); +#endif + return put_user(2, (int *) arg); + case SOUND_PCM_READ_BITS: +#ifdef DEBUG + printk("SOUND_PCM_READ_BITS\n"); +#endif + return put_user(AFMT_S16_LE, (int *) arg); + case SNDCTL_DSP_SETSPDIF: /* Set S/PDIF Control register */ +#ifdef DEBUG + printk("SNDCTL_DSP_SETSPDIF\n"); +#endif + if (get_user(val, (int *) arg)) + return -EFAULT; + /* Check to make sure the codec supports S/PDIF transmitter */ + if ((state->card->ac97_features & 4)) { + /* mask out the transmitter speed bits so the user can't set them */ + val &= ~0x3000; + /* Add the current transmitter speed bits to the passed value */ + ret = ali_ac97_get(codec, AC97_SPDIF_CONTROL); + val |= (ret & 0x3000); + ali_ac97_set(codec, AC97_SPDIF_CONTROL, val); + if (ali_ac97_get(codec, AC97_SPDIF_CONTROL) != val) { + printk(KERN_ERR "ali_audio: Unable to set S/PDIF configuration to 0x%04x.\n", val); + return -EFAULT; + } + } +#ifdef DEBUG + else + printk(KERN_WARNING "ali_audio: S/PDIF transmitter not avalible.\n"); +#endif + return put_user(val, (int *) arg); + case SNDCTL_DSP_GETSPDIF: /* Get S/PDIF Control register */ +#ifdef DEBUG + printk("SNDCTL_DSP_GETSPDIF\n"); +#endif + if (get_user(val, (int *) arg)) + return -EFAULT; + /* Check to make sure the codec supports S/PDIF transmitter */ + if (!(state->card->ac97_features & 4)) { +#ifdef DEBUG + printk(KERN_WARNING "ali_audio: S/PDIF transmitter not avalible.\n"); +#endif + val = 0; + } else { + val = ali_ac97_get(codec, AC97_SPDIF_CONTROL); + } + + return put_user(val, (int *) arg); +//end add support spdif out +//add support 4,6 channel + case SNDCTL_DSP_GETCHANNELMASK: +#ifdef DEBUG + printk("SNDCTL_DSP_GETCHANNELMASK\n"); +#endif + if (get_user(val, (int *) arg)) + return -EFAULT; + /* Based on AC'97 DAC support, not ICH hardware */ + val = DSP_BIND_FRONT; + if (state->card->ac97_features & 0x0004) + val |= DSP_BIND_SPDIF; + if (state->card->ac97_features & 0x0080) + val |= DSP_BIND_SURR; + if (state->card->ac97_features & 0x0140) + val |= DSP_BIND_CENTER_LFE; + return put_user(val, (int *) arg); + case SNDCTL_DSP_BIND_CHANNEL: +#ifdef DEBUG + printk("SNDCTL_DSP_BIND_CHANNEL\n"); +#endif + if (get_user(val, (int *) arg)) + return -EFAULT; + if (val == DSP_BIND_QUERY) { + val = DSP_BIND_FRONT; /* Always report this as being enabled */ + if (state->card->ac97_status & SPDIF_ON) + val |= DSP_BIND_SPDIF; + else { + if (state->card->ac97_status & SURR_ON) + val |= DSP_BIND_SURR; + if (state->card-> + ac97_status & CENTER_LFE_ON) + val |= DSP_BIND_CENTER_LFE; + } + } else { /* Not a query, set it */ + if (!(file->f_mode & FMODE_WRITE)) + return -EINVAL; + if (dmabuf->enable == DAC_RUNNING) { + stop_dac(state); + } + if (val & DSP_BIND_SPDIF) { /* Turn on SPDIF */ + /* Ok, this should probably define what slots + * to use. For now, we'll only set it to the + * defaults: + * + * non multichannel codec maps to slots 3&4 + * 2 channel codec maps to slots 7&8 + * 4 channel codec maps to slots 6&9 + * 6 channel codec maps to slots 10&11 + * + * there should be some way for the app to + * select the slot assignment. + */ + i_scr = inl(state->card->iobase + ALI_SCR); + if (codec_independent_spdif_locked > 0) { + + if ((i_scr & 0x00300000) == 0x00100000) { + ali_set_spdif_output(state, AC97_EA_SPSA_7_8, codec_independent_spdif_locked); + } else { + if ((i_scr & 0x00300000) == 0x00200000) { + ali_set_spdif_output(state, AC97_EA_SPSA_6_9, codec_independent_spdif_locked); + } else { + if ((i_scr & 0x00300000) == 0x00300000) { + ali_set_spdif_output(state, AC97_EA_SPSA_10_11, codec_independent_spdif_locked); + } + } + } + } else { /* codec spdif out (pcm out share ) */ + ali_set_spdif_output(state, AC97_EA_SPSA_3_4, dmabuf->rate); //I do not modify + } + + if (!(state->card->ac97_status & SPDIF_ON)) + val &= ~DSP_BIND_SPDIF; + } else { + int mask; + int channels; + /* Turn off S/PDIF if it was on */ + if (state->card->ac97_status & SPDIF_ON) + ali_set_spdif_output(state, -1, 0); + mask = + val & (DSP_BIND_FRONT | DSP_BIND_SURR | + DSP_BIND_CENTER_LFE); + switch (mask) { + case DSP_BIND_FRONT: + channels = 2; + break; + case DSP_BIND_FRONT | DSP_BIND_SURR: + channels = 4; + break; + case DSP_BIND_FRONT | DSP_BIND_SURR | DSP_BIND_CENTER_LFE: + channels = 6; + break; + default: + val = DSP_BIND_FRONT; + channels = 2; + break; + } + ali_set_dac_channels(state, channels); + /* check that they really got turned on */ + if (!state->card->ac97_status & SURR_ON) + val &= ~DSP_BIND_SURR; + if (!state->card-> + ac97_status & CENTER_LFE_ON) + val &= ~DSP_BIND_CENTER_LFE; + } + } + return put_user(val, (int *) arg); + case SNDCTL_DSP_MAPINBUF: + case SNDCTL_DSP_MAPOUTBUF: + case SNDCTL_DSP_SETSYNCRO: + case SOUND_PCM_WRITE_FILTER: + case SOUND_PCM_READ_FILTER: + return -EINVAL; + } + return -EINVAL; +} + +static int ali_open(struct inode *inode, struct file *file) +{ + int i = 0; + struct ali_card *card = devs; + struct ali_state *state = NULL; + struct dmabuf *dmabuf = NULL; + unsigned int i_scr; + + /* find an available virtual channel (instance of /dev/dsp) */ + + while (card != NULL) { + + /* + * If we are initializing and then fail, card could go + * away unuexpectedly while we are in the for() loop. + * So, check for card on each iteration before we check + * for card->initializing to avoid a possible oops. + * This usually only matters for times when the driver is + * autoloaded by kmod. + */ + for (i = 0; i < 50 && card && card->initializing; i++) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ / 20); + } + + for (i = 0; i < NR_HW_CH && card && !card->initializing; i++) { + if (card->states[i] == NULL) { + state = card->states[i] = (struct ali_state *) kmalloc(sizeof(struct ali_state), GFP_KERNEL); + if (state == NULL) + return -ENOMEM; + memset(state, 0, sizeof(struct ali_state)); + dmabuf = &state->dmabuf; + goto found_virt; + } + } + card = card->next; + } + + /* no more virtual channel avaiable */ + if (!state) + return -ENODEV; +found_virt: + /* initialize the virtual channel */ + + state->virt = i; + state->card = card; + state->magic = ALI5455_STATE_MAGIC; + init_waitqueue_head(&dmabuf->wait); + init_MUTEX(&state->open_sem); + file->private_data = state; + dmabuf->trigger = 0; + /* allocate hardware channels */ + if (file->f_mode & FMODE_READ) { + if ((dmabuf->read_channel = + card->alloc_rec_pcm_channel(card)) == NULL) { + kfree(card->states[i]); + card->states[i] = NULL; + return -EBUSY; + } + dmabuf->trigger |= PCM_ENABLE_INPUT; + ali_set_adc_rate(state, 8000); + } + if (file->f_mode & FMODE_WRITE) { + if (codec_independent_spdif_locked > 0) { + if ((dmabuf->codec_spdifout_channel = card->alloc_codec_spdifout_channel(card)) == NULL) { + kfree(card->states[i]); + card->states[i] = NULL; + return -EBUSY; + } + dmabuf->trigger |= SPDIF_ENABLE_OUTPUT; + ali_set_codecspdifout_rate(state, codec_independent_spdif_locked); //It must add + i_scr = inl(state->card->iobase + ALI_SCR); + if ((i_scr & 0x00300000) == 0x00100000) { + ali_set_spdif_output(state, AC97_EA_SPSA_7_8, codec_independent_spdif_locked); + } else { + if ((i_scr & 0x00300000) == 0x00200000) { + ali_set_spdif_output(state, AC97_EA_SPSA_6_9, codec_independent_spdif_locked); + } else { + if ((i_scr & 0x00300000) == 0x00300000) { + ali_set_spdif_output(state, AC97_EA_SPSA_10_11, codec_independent_spdif_locked); + } else { + ali_set_spdif_output(state, AC97_EA_SPSA_7_8, codec_independent_spdif_locked); + } + } + + } + } else { + if (controller_independent_spdif_locked > 0) { + if ((dmabuf->controller_spdifout_channel = card->alloc_controller_spdifout_channel(card)) == NULL) { + kfree(card->states[i]); + card->states[i] = NULL; + return -EBUSY; + } + dmabuf->trigger |= SPDIF_ENABLE_OUTPUT; + ali_set_spdifout_rate(state, controller_independent_spdif_locked); + } else { + if ((dmabuf->write_channel = card->alloc_pcm_channel(card)) == NULL) { + kfree(card->states[i]); + card->states[i] = NULL; + return -EBUSY; + } + /* Initialize to 8kHz? What if we don't support 8kHz? */ + /* Let's change this to check for S/PDIF stuff */ + + dmabuf->trigger |= PCM_ENABLE_OUTPUT; + if (codec_pcmout_share_spdif_locked) { + ali_set_dac_rate(state, codec_pcmout_share_spdif_locked); + ali_set_spdif_output(state, AC97_EA_SPSA_3_4, codec_pcmout_share_spdif_locked); + } else { + ali_set_dac_rate(state, 8000); + } + } + + } + } + + /* set default sample format. According to OSS Programmer's Guide /dev/dsp + should be default to unsigned 8-bits, mono, with sample rate 8kHz and + /dev/dspW will accept 16-bits sample, but we don't support those so we + set it immediately to stereo and 16bit, which is all we do support */ + dmabuf->fmt |= ALI5455_FMT_16BIT | ALI5455_FMT_STEREO; + dmabuf->ossfragsize = 0; + dmabuf->ossmaxfrags = 0; + dmabuf->subdivision = 0; + state->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); + outl(0x00000000, card->iobase + ALI_INTERRUPTCR); + outl(0x00000000, card->iobase + ALI_INTERRUPTSR); + return 0; +} + +static int ali_release(struct inode *inode, struct file *file) +{ + struct ali_state *state = (struct ali_state *) file->private_data; + struct ali_card *card = state->card; + struct dmabuf *dmabuf = &state->dmabuf; + unsigned long flags; + lock_kernel(); + + /* stop DMA state machine and free DMA buffers/channels */ + if (dmabuf->trigger & PCM_ENABLE_OUTPUT) + drain_dac(state, 0); + + if (dmabuf->trigger & SPDIF_ENABLE_OUTPUT) + drain_spdifout(state, 0); + + if (dmabuf->trigger & PCM_ENABLE_INPUT) + stop_adc(state); + + spin_lock_irqsave(&card->lock, flags); + dealloc_dmabuf(state); + if (file->f_mode & FMODE_WRITE) { + if (codec_independent_spdif_locked > 0) { + state->card->free_pcm_channel(state->card, dmabuf->codec_spdifout_channel->num); + } else { + if (controller_independent_spdif_locked > 0) + state->card->free_pcm_channel(state->card, + dmabuf->controller_spdifout_channel->num); + else state->card->free_pcm_channel(state->card, + dmabuf->write_channel->num); + } + } + if (file->f_mode & FMODE_READ) + state->card->free_pcm_channel(state->card, dmabuf->read_channel->num); + + state->card->states[state->virt] = NULL; + kfree(state); + spin_unlock_irqrestore(&card->lock, flags); + unlock_kernel(); + return 0; +} + +static /*const */ struct file_operations ali_audio_fops = { + owner:THIS_MODULE, + llseek:no_llseek, + read:ali_read, + write:ali_write, + poll:ali_poll, + ioctl:ali_ioctl, + mmap:ali_mmap, + open:ali_open, + release:ali_release, +}; + +/* Read AC97 codec registers */ +static u16 ali_ac97_get(struct ac97_codec *dev, u8 reg) +{ + struct ali_card *card = dev->private_data; + int count1 = 100; + char val; + unsigned short int data, count, addr1, addr2; + + while (count1-- && (inl(card->iobase + ALI_CAS) & 0x80000000)) + udelay(1); + + addr1 = reg; + reg |= 0x0080; + for (count = 0; count < 0x7f; count++) { + val = inb(card->iobase + ALI_CSPSR); + if (val & 0x08) + break; + } + if (count == 0x7f) + return -1; + outw(reg, (card->iobase + ALI_CPR) + 2); + for (count = 0; count < 0x7f; count++) { + val = inb(card->iobase + ALI_CSPSR); + if (val & 0x02) { + data = inw(card->iobase + ALI_SPR); + addr2 = inw((card->iobase + ALI_SPR) + 2); + break; + } + } + if (count == 0x7f) + return -1; + if (addr2 != addr1) + return -1; + return ((u16) data); +} + +/* write ac97 codec register */ + +static void ali_ac97_set(struct ac97_codec *dev, u8 reg, u16 data) +{ + struct ali_card *card = dev->private_data; + int count1 = 100; + unsigned long flags; + char val; + unsigned short int count; + + while (count1-- && (inl(card->iobase + ALI_CAS) & 0x80000000)) + udelay(1); + + for (count = 0; count < 0x7f; count++) { + val = inb(card->iobase + ALI_CSPSR); + if (val & 0x08) + break; + } + if (count == 0x7f) { + printk(KERN_WARNING "ali_ac96_set: AC97 codec register access timed out. \n"); + return; + } + outw(data, (card->iobase + ALI_CPR)); + outb(reg, (card->iobase + ALI_CPR) + 2); + for (count = 0; count < 0x7f; count++) { + val = inb(card->iobase + ALI_CSPSR); + if (val & 0x01) + break; + } + if (count == 0x7f) { + printk(KERN_WARNING "ali_ac96_set: AC97 codec register access timed out. \n"); + return; + } + return; +} + +/* OSS /dev/mixer file operation methods */ + +static int ali_open_mixdev(struct inode *inode, struct file *file) +{ + int i; + int minor = MINOR(inode->i_rdev); + struct ali_card *card = devs; + for (card = devs; card != NULL; card = card->next) { + /* + * If we are initializing and then fail, card could go + * away unuexpectedly while we are in the for() loop. + * So, check for card on each iteration before we check + * for card->initializing to avoid a possible oops. + * This usually only matters for times when the driver is + * autoloaded by kmod. + */ + for (i = 0; i < 50 && card && card->initializing; i++) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ / 20); + } + for (i = 0; i < NR_AC97 && card && !card->initializing; i++) + if (card->ac97_codec[i] != NULL + && card->ac97_codec[i]->dev_mixer == minor) { + file->private_data = card->ac97_codec[i]; + return 0; + } + } + return -ENODEV; +} + +static int ali_ioctl_mixdev(struct inode *inode, + struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct ac97_codec *codec = (struct ac97_codec *) file->private_data; + return codec->mixer_ioctl(codec, cmd, arg); +} + +static /*const */ struct file_operations ali_mixer_fops = { + owner:THIS_MODULE, + llseek:no_llseek, + ioctl:ali_ioctl_mixdev, + open:ali_open_mixdev, +}; + +/* AC97 codec initialisation. These small functions exist so we don't + duplicate code between module init and apm resume */ + +static inline int ali_ac97_exists(struct ali_card *card, int ac97_number) +{ + unsigned int i = 1; + u32 reg = inl(card->iobase + ALI_RTSR); + if (ac97_number) { + while (i < 100) { + + reg = inl(card->iobase + ALI_RTSR); + if (reg & 0x40) { + break; + } else { + outl(reg | 0x00000040, + card->iobase + 0x34); + udelay(1); + } + i++; + } + + } else { + while (i < 100) { + reg = inl(card->iobase + ALI_RTSR); + if (reg & 0x80) { + break; + } else { + outl(reg | 0x00000080, + card->iobase + 0x34); + udelay(1); + } + i++; + } + } + + if (ac97_number) + return reg & 0x40; + else + return reg & 0x80; +} + +static inline int ali_ac97_enable_variable_rate(struct ac97_codec *codec) +{ + ali_ac97_set(codec, AC97_EXTENDED_STATUS, 9); + ali_ac97_set(codec, AC97_EXTENDED_STATUS, ali_ac97_get(codec, AC97_EXTENDED_STATUS) | 0xE800); + return (ali_ac97_get(codec, AC97_EXTENDED_STATUS) & 1); +} + + +static int ali_ac97_probe_and_powerup(struct ali_card *card, struct ac97_codec *codec) +{ + /* Returns 0 on failure */ + int i; + u16 addr; + if (ac97_probe_codec(codec) == 0) + return 0; + /* ac97_probe_codec is success ,then begin to init codec */ + ali_ac97_set(codec, AC97_RESET, 0xffff); + if (card->channel[0].used == 1) { + ali_ac97_set(codec, AC97_RECORD_SELECT, 0x0000); + ali_ac97_set(codec, AC97_LINEIN_VOL, 0x0808); + ali_ac97_set(codec, AC97_RECORD_GAIN, 0x0F0F); + } + + if (card->channel[2].used == 1) //if MICin then init codec + { + ali_ac97_set(codec, AC97_RECORD_SELECT, 0x0000); + ali_ac97_set(codec, AC97_MIC_VOL, 0x8808); + ali_ac97_set(codec, AC97_RECORD_GAIN, 0x0F0F); + ali_ac97_set(codec, AC97_RECORD_GAIN_MIC, 0x0000); + } + + ali_ac97_set(codec, AC97_MASTER_VOL_STEREO, 0x0000); + ali_ac97_set(codec, AC97_HEADPHONE_VOL, 0x0000); + ali_ac97_set(codec, AC97_PCMOUT_VOL, 0x0000); + ali_ac97_set(codec, AC97_CD_VOL, 0x0808); + ali_ac97_set(codec, AC97_VIDEO_VOL, 0x0808); + ali_ac97_set(codec, AC97_AUX_VOL, 0x0808); + ali_ac97_set(codec, AC97_PHONE_VOL, 0x8048); + ali_ac97_set(codec, AC97_PCBEEP_VOL, 0x0000); + ali_ac97_set(codec, AC97_GENERAL_PURPOSE, AC97_GP_MIX); + ali_ac97_set(codec, AC97_MASTER_VOL_MONO, 0x0000); + ali_ac97_set(codec, 0x38, 0x0000); + addr = ali_ac97_get(codec, 0x2a); + ali_ac97_set(codec, 0x2a, addr | 0x0001); + addr = ali_ac97_get(codec, 0x2a); + addr = ali_ac97_get(codec, 0x28); + ali_ac97_set(codec, 0x2c, 0xbb80); + addr = ali_ac97_get(codec, 0x2c); + /* power it all up */ + ali_ac97_set(codec, AC97_POWER_CONTROL, + ali_ac97_get(codec, AC97_POWER_CONTROL) & ~0x7f00); + /* wait for analog ready */ + for (i = 10; i && ((ali_ac97_get(codec, AC97_POWER_CONTROL) & 0xf) != 0xf); i--) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ / 20); + } + /* FIXME !! */ + i++; + return i; +} + + +/* I clone ali5455(2.4.7 ) not clone i810_audio(2.4.18) */ + +static int ali_reset_5455(struct ali_card *card) +{ + outl(0x80000003, card->iobase + ALI_SCR); + outl(0x83838383, card->iobase + ALI_FIFOCR1); + outl(0x83838383, card->iobase + ALI_FIFOCR2); + if (controller_pcmout_share_spdif_locked > 0) { + outl((inl(card->iobase + ALI_SPDIFICS) | 0x00000001), + card->iobase + ALI_SPDIFICS); + outl(0x0408000a, card->iobase + ALI_INTERFACECR); + } else { + if (codec_independent_spdif_locked > 0) { + outl((inl(card->iobase + ALI_SCR) | 0x00100000), card->iobase + ALI_SCR); // now I select slot 7 & 8 + outl(0x00200000, card->iobase + ALI_INTERFACECR); //enable codec independent spdifout + } else + outl(0x04080002, card->iobase + ALI_INTERFACECR); + } + + outl(0x00000000, card->iobase + ALI_INTERRUPTCR); + outl(0x00000000, card->iobase + ALI_INTERRUPTSR); + if (controller_independent_spdif_locked > 0) + outl((inl(card->iobase + ALI_SPDIFICS) | 0x00000001), + card->iobase + ALI_SPDIFICS); + return 1; +} + + +static int ali_ac97_random_init_stuff(struct ali_card + *card) +{ + u32 reg = inl(card->iobase + ALI_SCR); + int i = 0; + reg = inl(card->iobase + ALI_SCR); + if ((reg & 2) == 0) /* Cold required */ + reg |= 2; + else + reg |= 1; /* Warm */ + reg &= ~0x80000000; /* ACLink on */ + outl(reg, card->iobase + ALI_SCR); + + while (i < 10) { + if ((inl(card->iobase + 0x18) & (1 << 1)) == 0) + break; + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout(HZ / 20); + i++; + } + if (i == 10) { + printk(KERN_ERR "ali_audio: AC'97 reset failed.\n"); + return 0; + } + + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ / 2); + return 1; +} + +/* AC97 codec initialisation. */ + +static int __init ali_ac97_init(struct ali_card *card) +{ + int num_ac97 = 0; + int total_channels = 0; + struct ac97_codec *codec; + u16 eid; + + if (!ali_ac97_random_init_stuff(card)) + return 0; + + /* Number of channels supported */ + /* What about the codec? Just because the ICH supports */ + /* multiple channels doesn't mean the codec does. */ + /* we'll have to modify this in the codec section below */ + /* to reflect what the codec has. */ + /* ICH and ICH0 only support 2 channels so don't bother */ + /* to check.... */ + inl(card->iobase + ALI_CPR); + card->channels = 2; + + for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) { + + /* Assume codec isn't available until we go through the + * gauntlet below */ + card->ac97_codec[num_ac97] = NULL; + /* The ICH programmer's reference says you should */ + /* check the ready status before probing. So we chk */ + /* What do we do if it's not ready? Wait and try */ + /* again, or abort? */ + if (!ali_ac97_exists(card, num_ac97)) { + if (num_ac97 == 0) + printk(KERN_ERR "ali_audio: Primary codec not ready.\n"); + break; + } + + if ((codec = kmalloc(sizeof(struct ac97_codec), GFP_KERNEL)) == NULL) + return -ENOMEM; + memset(codec, 0, sizeof(struct ac97_codec)); + /* initialize some basic codec information, other fields will be filled + in ac97_probe_codec */ + codec->private_data = card; + codec->id = num_ac97; + codec->codec_read = ali_ac97_get; + codec->codec_write = ali_ac97_set; + if (!ali_ac97_probe_and_powerup(card, codec)) { + printk(KERN_ERR "ali_audio: timed out waiting for codec %d analog ready", + num_ac97); + kfree(codec); + break; /* it didn't work */ + } + + /* Store state information about S/PDIF transmitter */ + card->ac97_status = 0; + /* Don't attempt to get eid until powerup is complete */ + eid = ali_ac97_get(codec, AC97_EXTENDED_ID); + if (eid == 0xFFFFFF) { + printk(KERN_ERR "ali_audio: no codec attached ?\n"); + kfree(codec); + break; + } + + card->ac97_features = eid; + /* Now check the codec for useful features to make up for + the dumbness of the ali5455 hardware engine */ + if (!(eid & 0x0001)) + printk(KERN_WARNING + "ali_audio: only 48Khz playback available.\n"); + else { + if (!ali_ac97_enable_variable_rate(codec)) { + printk(KERN_WARNING + "ali_audio: Codec refused to allow VRA, using 48Khz only.\n"); + card->ac97_features &= ~1; + } + } + + /* Determine how many channels the codec(s) support */ + /* - The primary codec always supports 2 */ + /* - If the codec supports AMAP, surround DACs will */ + /* automaticlly get assigned to slots. */ + /* * Check for surround DACs and increment if */ + /* found. */ + /* - Else check if the codec is revision 2.2 */ + /* * If surround DACs exist, assign them to slots */ + /* and increment channel count. */ + + /* All of this only applies to ICH2 and above. ICH */ + /* and ICH0 only support 2 channels. ICH2 will only */ + /* support multiple codecs in a "split audio" config. */ + /* as described above. */ + + /* TODO: Remove all the debugging messages! */ + + if ((eid & 0xc000) == 0) /* primary codec */ + total_channels += 2; + if ((codec->dev_mixer = register_sound_mixer(&ali_mixer_fops, -1)) < 0) { + printk(KERN_ERR "ali_audio: couldn't register mixer!\n"); + kfree(codec); + break; + } + card->ac97_codec[num_ac97] = codec; + } + /* pick the minimum of channels supported by ICHx or codec(s) */ + card->channels = (card->channels > total_channels) ? total_channels : card->channels; + return num_ac97; +} + +static void __init ali_configure_clocking(void) +{ + struct ali_card *card; + struct ali_state *state; + struct dmabuf *dmabuf; + unsigned int i, offset, new_offset; + unsigned long flags; + card = devs; + + /* We could try to set the clocking for multiple cards, but can you even have + * more than one ali in a machine? Besides, clocking is global, so unless + * someone actually thinks more than one ali in a machine is possible and + * decides to rewrite that little bit, setting the rate for more than one card + * is a waste of time. + */ + if (card != NULL) { + state = card->states[0] = (struct ali_state *) + kmalloc(sizeof(struct ali_state), GFP_KERNEL); + if (state == NULL) + return; + memset(state, 0, sizeof(struct ali_state)); + dmabuf = &state->dmabuf; + dmabuf->write_channel = card->alloc_pcm_channel(card); + state->virt = 0; + state->card = card; + state->magic = ALI5455_STATE_MAGIC; + init_waitqueue_head(&dmabuf->wait); + init_MUTEX(&state->open_sem); + dmabuf->fmt = ALI5455_FMT_STEREO | ALI5455_FMT_16BIT; + dmabuf->trigger = PCM_ENABLE_OUTPUT; + ali_set_dac_rate(state, 48000); + if (prog_dmabuf(state, 0) != 0) + goto config_out_nodmabuf; + + if (dmabuf->dmasize < 16384) + goto config_out; + + dmabuf->count = dmabuf->dmasize; + outb(31, card->iobase + dmabuf->write_channel->port + OFF_LVI); + + save_flags(flags); + cli(); + start_dac(state); + offset = ali_get_dma_addr(state, 0); + mdelay(50); + new_offset = ali_get_dma_addr(state, 0); + stop_dac(state); + + outb(2, card->iobase + dmabuf->write_channel->port + OFF_CR); + restore_flags(flags); + + i = new_offset - offset; + + if (i == 0) + goto config_out; + i = i / 4 * 20; + if (i > 48500 || i < 47500) { + clocking = clocking * clocking / i; + } +config_out: + dealloc_dmabuf(state); +config_out_nodmabuf: + state->card->free_pcm_channel(state->card, state->dmabuf. write_channel->num); + kfree(state); + card->states[0] = NULL; + } +} + +/* install the driver, we do not allocate hardware channel nor DMA buffer now, they are defered + until "ACCESS" time (in prog_dmabuf called by open/read/write/ioctl/mmap) */ + +static int __init ali_probe(struct pci_dev *pci_dev, const struct pci_device_id + *pci_id) +{ + struct ali_card *card; + if (pci_enable_device(pci_dev)) + return -EIO; + if (pci_set_dma_mask(pci_dev, ALI5455_DMA_MASK)) { + printk(KERN_ERR "ali5455: architecture does not support" + " 32bit PCI busmaster DMA\n"); + return -ENODEV; + } + + if ((card = kmalloc(sizeof(struct ali_card), GFP_KERNEL)) == NULL) { + printk(KERN_ERR "ali_audio: out of memory\n"); + return -ENOMEM; + } + memset(card, 0, sizeof(*card)); + card->initializing = 1; + card->iobase = pci_resource_start(pci_dev, 0); + card->pci_dev = pci_dev; + card->pci_id = pci_id->device; + card->irq = pci_dev->irq; + card->next = devs; + card->magic = ALI5455_CARD_MAGIC; +#ifdef CONFIG_PM + card->pm_suspended = 0; +#endif + spin_lock_init(&card->lock); + devs = card; + pci_set_master(pci_dev); + printk(KERN_INFO "ali: %s found at IO 0x%04lx, IRQ %d\n", + card_names[pci_id->driver_data], card->iobase, card->irq); + card->alloc_pcm_channel = ali_alloc_pcm_channel; + card->alloc_rec_pcm_channel = ali_alloc_rec_pcm_channel; + card->alloc_rec_mic_channel = ali_alloc_rec_mic_channel; + card->alloc_codec_spdifout_channel = ali_alloc_codec_spdifout_channel; + card->alloc_controller_spdifout_channel = ali_alloc_controller_spdifout_channel; + card->free_pcm_channel = ali_free_pcm_channel; + card->channel[0].offset = 0; + card->channel[0].port = 0x40; + card->channel[0].num = 0; + card->channel[1].offset = 0; + card->channel[1].port = 0x50; + card->channel[1].num = 1; + card->channel[2].offset = 0; + card->channel[2].port = 0x60; + card->channel[2].num = 2; + card->channel[3].offset = 0; + card->channel[3].port = 0x70; + card->channel[3].num = 3; + card->channel[4].offset = 0; + card->channel[4].port = 0xb0; + card->channel[4].num = 4; + /* claim our iospace and irq */ + request_region(card->iobase, 256, card_names[pci_id->driver_data]); + if (request_irq(card->irq, &ali_interrupt, SA_SHIRQ, + card_names[pci_id->driver_data], card)) { + printk(KERN_ERR "ali_audio: unable to allocate irq %d\n", + card->irq); + release_region(card->iobase, 256); + kfree(card); + return -ENODEV; + } + + if (ali_reset_5455(card) <= 0) { + unregister_sound_dsp(card->dev_audio); + release_region(card->iobase, 256); + free_irq(card->irq, card); + kfree(card); + return -ENODEV; + } + + /* initialize AC97 codec and register /dev/mixer */ + if (ali_ac97_init(card) < 0) { + release_region(card->iobase, 256); + free_irq(card->irq, card); + kfree(card); + return -ENODEV; + } + + pci_set_drvdata(pci_dev, card); + + if (clocking == 0) { + clocking = 48000; + ali_configure_clocking(); + } + + /* register /dev/dsp */ + if ((card->dev_audio = register_sound_dsp(&ali_audio_fops, -1)) < 0) { + int i; + printk(KERN_ERR"ali_audio: couldn't register DSP device!\n"); + release_region(card->iobase, 256); + free_irq(card->irq, card); + for (i = 0; i < NR_AC97; i++) + if (card->ac97_codec[i] != NULL) { + unregister_sound_mixer(card->ac97_codec[i]->dev_mixer); + kfree(card->ac97_codec[i]); + } + kfree(card); + return -ENODEV; + } + card->initializing = 0; + return 0; +} + +static void __devexit ali_remove(struct pci_dev *pci_dev) +{ + int i; + struct ali_card *card = pci_get_drvdata(pci_dev); + /* free hardware resources */ + free_irq(card->irq, devs); + release_region(card->iobase, 256); + /* unregister audio devices */ + for (i = 0; i < NR_AC97; i++) + if (card->ac97_codec[i] != NULL) { + unregister_sound_mixer(card->ac97_codec[i]-> + dev_mixer); + kfree(card->ac97_codec[i]); + card->ac97_codec[i] = NULL; + } + unregister_sound_dsp(card->dev_audio); + kfree(card); +} + +#ifdef CONFIG_PM +static int ali_pm_suspend(struct pci_dev *dev, u32 pm_state) +{ + struct ali_card *card = pci_get_drvdata(dev); + struct ali_state *state; + unsigned long flags; + struct dmabuf *dmabuf; + int i, num_ac97; + + if (!card) + return 0; + spin_lock_irqsave(&card->lock, flags); + card->pm_suspended = 1; + for (i = 0; i < NR_HW_CH; i++) { + state = card->states[i]; + if (!state) + continue; + /* this happens only if there are open files */ + dmabuf = &state->dmabuf; + if (dmabuf->enable & DAC_RUNNING || + (dmabuf->count + && (dmabuf->trigger & PCM_ENABLE_OUTPUT))) { + state->pm_saved_dac_rate = dmabuf->rate; + stop_dac(state); + } else { + state->pm_saved_dac_rate = 0; + } + if (dmabuf->enable & ADC_RUNNING) { + state->pm_saved_adc_rate = dmabuf->rate; + stop_adc(state); + } else { + state->pm_saved_adc_rate = 0; + } + dmabuf->ready = 0; + dmabuf->swptr = dmabuf->hwptr = 0; + dmabuf->count = dmabuf->total_bytes = 0; + } + + spin_unlock_irqrestore(&card->lock, flags); + /* save mixer settings */ + for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) { + struct ac97_codec *codec = card->ac97_codec[num_ac97]; + if (!codec) + continue; + for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { + if ((supported_mixer(codec, i)) && (codec->read_mixer)) { + card->pm_saved_mixer_settings[i][num_ac97] = codec->read_mixer(codec, i); + } + } + } + pci_save_state(dev, card->pm_save_state); /* XXX do we need this? */ + pci_disable_device(dev); /* disable busmastering */ + pci_set_power_state(dev, 3); /* Zzz. */ + return 0; +} + + +static int ali_pm_resume(struct pci_dev *dev) +{ + int num_ac97, i = 0; + struct ali_card *card = pci_get_drvdata(dev); + pci_enable_device(dev); + pci_restore_state(dev, card->pm_save_state); + /* observation of a toshiba portege 3440ct suggests that the + hardware has to be more or less completely reinitialized from + scratch after an apm suspend. Works For Me. -dan */ + ali_ac97_random_init_stuff(card); + for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) { + struct ac97_codec *codec = card->ac97_codec[num_ac97]; + /* check they haven't stolen the hardware while we were + away */ + if (!codec || !ali_ac97_exists(card, num_ac97)) { + if (num_ac97) + continue; + else + BUG(); + } + if (!ali_ac97_probe_and_powerup(card, codec)) + BUG(); + if ((card->ac97_features & 0x0001)) { + /* at probe time we found we could do variable + rates, but APM suspend has made it forget + its magical powers */ + if (!ali_ac97_enable_variable_rate(codec)) + BUG(); + } + /* we lost our mixer settings, so restore them */ + for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { + if (supported_mixer(codec, i)) { + int val = card->pm_saved_mixer_settings[i][num_ac97]; + codec->mixer_state[i] = val; + codec->write_mixer(codec, i, + (val & 0xff), + ((val >> 8) & 0xff)); + } + } + } + + /* we need to restore the sample rate from whatever it was */ + for (i = 0; i < NR_HW_CH; i++) { + struct ali_state *state = card->states[i]; + if (state) { + if (state->pm_saved_adc_rate) + ali_set_adc_rate(state, state->pm_saved_adc_rate); + if (state->pm_saved_dac_rate) + ali_set_dac_rate(state, state->pm_saved_dac_rate); + } + } + + card->pm_suspended = 0; + /* any processes that were reading/writing during the suspend + probably ended up here */ + for (i = 0; i < NR_HW_CH; i++) { + struct ali_state *state = card->states[i]; + if (state) + wake_up(&state->dmabuf.wait); + } + return 0; +} +#endif /* CONFIG_PM */ + +MODULE_AUTHOR(""); +MODULE_DESCRIPTION("ALI 5455 audio support"); +MODULE_LICENSE("GPL"); +MODULE_PARM(clocking, "i"); +MODULE_PARM(strict_clocking, "i"); +MODULE_PARM(codec_pcmout_share_spdif_locked, "i"); +MODULE_PARM(codec_independent_spdif_locked, "i"); +MODULE_PARM(controller_pcmout_share_spdif_locked, "i"); +MODULE_PARM(controller_independent_spdif_locked, "i"); +#define ALI5455_MODULE_NAME "ali5455" +static struct pci_driver ali_pci_driver = { + name:ALI5455_MODULE_NAME, id_table:ali_pci_tbl, probe:ali_probe, + remove:__devexit_p(ali_remove), +#ifdef CONFIG_PM + suspend:ali_pm_suspend, resume:ali_pm_resume, +#endif /* CONFIG_PM */ +}; + +static int __init ali_init_module(void) +{ + if (!pci_present()) /* No PCI bus in this machine! */ + return -ENODEV; + printk(KERN_INFO "ALI 5455 + AC97 Audio, version " + DRIVER_VERSION ", " __TIME__ " " __DATE__ "\n"); + + if (codec_independent_spdif_locked > 0) { + if (codec_independent_spdif_locked == 32000 + || codec_independent_spdif_locked == 44100 + || codec_independent_spdif_locked == 48000) { + printk(KERN_INFO "ali_audio: Enabling S/PDIF at sample rate %dHz.\n", codec_independent_spdif_locked); + } else { + printk(KERN_INFO "ali_audio: S/PDIF can only be locked to 32000, 44100, or 48000Hz.\n"); + codec_independent_spdif_locked = 0; + } + } + if (controller_independent_spdif_locked > 0) { + if (controller_independent_spdif_locked == 32000 + || controller_independent_spdif_locked == 44100 + || controller_independent_spdif_locked == 48000) { + printk(KERN_INFO "ali_audio: Enabling S/PDIF at sample rate %dHz.\n", controller_independent_spdif_locked); + } else { + printk(KERN_INFO "ali_audio: S/PDIF can only be locked to 32000, 44100, or 48000Hz.\n"); + controller_independent_spdif_locked = 0; + } + } + + if (codec_pcmout_share_spdif_locked > 0) { + if (codec_pcmout_share_spdif_locked == 32000 + || codec_pcmout_share_spdif_locked == 44100 + || codec_pcmout_share_spdif_locked == 48000) { + printk(KERN_INFO "ali_audio: Enabling S/PDIF at sample rate %dHz.\n", codec_pcmout_share_spdif_locked); + } else { + printk(KERN_INFO "ali_audio: S/PDIF can only be locked to 32000, 44100, or 48000Hz.\n"); + codec_pcmout_share_spdif_locked = 0; + } + } + if (controller_pcmout_share_spdif_locked > 0) { + if (controller_pcmout_share_spdif_locked == 32000 + || controller_pcmout_share_spdif_locked == 44100 + || controller_pcmout_share_spdif_locked == 48000) { + printk(KERN_INFO "ali_audio: Enabling controller S/PDIF at sample rate %dHz.\n", controller_pcmout_share_spdif_locked); + } else { + printk(KERN_INFO "ali_audio: S/PDIF can only be locked to 32000, 44100, or 48000Hz.\n"); + controller_pcmout_share_spdif_locked = 0; + } + } + if (!pci_register_driver(&ali_pci_driver)) { + pci_unregister_driver(&ali_pci_driver); + return -ENODEV; + } + return 0; +} + +static void __exit ali_cleanup_module(void) +{ + pci_unregister_driver(&ali_pci_driver); +} + +module_init(ali_init_module); +module_exit(ali_cleanup_module); +/* +Local Variables: +c-basic-offset: 8 +End: +*/ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/sound/Config.in linux.19rc3-ac4/drivers/sound/Config.in --- linux.19rc3/drivers/sound/Config.in 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/sound/Config.in 2002-07-29 13:58:43.000000000 +0100 @@ -6,6 +6,7 @@ # Prompt user for primary drivers. +dep_tristate ' ALi5455 audio support' CONFIG_SOUND_ALI5455 $CONFIG_SOUND $CONFIG_PCI dep_tristate ' BT878 audio dma' CONFIG_SOUND_BT878 $CONFIG_SOUND $CONFIG_PCI dep_tristate ' C-Media PCI (CMI8338/8738)' CONFIG_SOUND_CMPCI $CONFIG_SOUND $CONFIG_PCI if [ "$CONFIG_SOUND_CMPCI" = "y" -o "$CONFIG_SOUND_CMPCI" = "m" ]; then @@ -43,6 +44,9 @@ dep_tristate ' ESS Maestro, Maestro2, Maestro2E driver' CONFIG_SOUND_MAESTRO $CONFIG_SOUND $CONFIG_PCI dep_tristate ' ESS Maestro3/Allegro driver (EXPERIMENTAL)' CONFIG_SOUND_MAESTRO3 $CONFIG_SOUND $CONFIG_PCI $CONFIG_EXPERIMENTAL dep_tristate ' Intel ICH (i8xx), SiS 7012, NVidia nForce Audio or AMD 768' CONFIG_SOUND_ICH $CONFIG_PCI +if [ "$CONFIG_GSC_LASI" = "y" ]; then + dep_tristate ' PA Harmony audio driver' CONFIG_SOUND_HARMONY $CONFIG_SOUND +fi if [ "$CONFIG_MIPS_ITE8172" = "y" -o "$CONFIG_MIPS_IVR" = "y" ]; then dep_tristate ' IT8172G Sound' CONFIG_SOUND_IT8172 $CONFIG_SOUND fi @@ -207,7 +211,7 @@ bool ' Audio Excel DSP 16 (MPU401 emulation)' CONFIG_AEDSP16_MPU401 fi fi - + if [ "$CONFIG_ARM" = "y" ]; then if [ "$CONFIG_ARCH_ACORN" = "y" -o "$CONFIG_ARCH_CLPS7500" = "y" ]; then dep_tristate ' VIDC 16-bit sound' CONFIG_SOUND_VIDC $CONFIG_SOUND_OSS diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/sound/harmony.c linux.19rc3-ac4/drivers/sound/harmony.c --- linux.19rc3/drivers/sound/harmony.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/sound/harmony.c 2002-07-29 13:58:44.000000000 +0100 @@ -0,0 +1,1295 @@ +/* + drivers/sound/harmony.c + + This is a sound driver for ASP's and Lasi's Harmony sound chip + and is unlikely to be used for anything other than on a HP PA-RISC. + + Harmony is found in HP 712s, 715/new and many other GSC based machines. + On older 715 machines you'll find the technically identical chip + called 'Vivace'. Both Harmony and Vicace are supported by this driver. + + Copyright 2000 (c) Linuxcare Canada, Alex deVries + Copyright 2000-2002 (c) Helge Deller + Copyright 2001 (c) Matthieu Delahaye + Copyright 2001 (c) Jean-Christophe Vaugeois + + +TODO: + - fix SNDCTL_DSP_GETOSPACE and SNDCTL_DSP_GETISPACE ioctls to + return the real values + - add private ioctl for selecting line- or microphone input + (only one of them is available at the same time) + - add module parameters + - implement mmap functionality + - implement gain meter ? + - ... +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "sound_config.h" + + +#define PFX "harmony: " +#define HARMONY_VERSION "V0.9a" + +#undef DEBUG +#ifdef DEBUG +# define DPRINTK printk +#else +# define DPRINTK(x,...) +#endif + + +#define MAX_BUFS 10 /* maximum number of rotating buffers */ +#define HARMONY_BUF_SIZE 4096 /* needs to be a multiple of PAGE_SIZE (4096)! */ + +#define CNTL_C 0x80000000 +#define CNTL_ST 0x00000020 +#define CNTL_44100 0x00000015 /* HARMONY_SR_44KHZ */ +#define CNTL_8000 0x00000008 /* HARMONY_SR_8KHZ */ + +#define GAINCTL_HE 0x08000000 +#define GAINCTL_LE 0x04000000 +#define GAINCTL_SE 0x02000000 + +#define DSTATUS_PN 0x00000200 +#define DSTATUS_RN 0x00000002 + +#define DSTATUS_IE 0x80000000 + +#define HARMONY_DF_16BIT_LINEAR 0 +#define HARMONY_DF_8BIT_ULAW 1 +#define HARMONY_DF_8BIT_ALAW 2 + +#define HARMONY_SS_MONO 0 +#define HARMONY_SS_STEREO 1 + +#define HARMONY_SR_8KHZ 0x08 +#define HARMONY_SR_16KHZ 0x09 +#define HARMONY_SR_27KHZ 0x0A +#define HARMONY_SR_32KHZ 0x0B +#define HARMONY_SR_48KHZ 0x0E +#define HARMONY_SR_9KHZ 0x0F +#define HARMONY_SR_5KHZ 0x10 +#define HARMONY_SR_11KHZ 0x11 +#define HARMONY_SR_18KHZ 0x12 +#define HARMONY_SR_22KHZ 0x13 +#define HARMONY_SR_37KHZ 0x14 +#define HARMONY_SR_44KHZ 0x15 +#define HARMONY_SR_33KHZ 0x16 +#define HARMONY_SR_6KHZ 0x17 + +/* + * Some magics numbers used to auto-detect file formats + */ + +#define HARMONY_MAGIC_8B_ULAW 1 +#define HARMONY_MAGIC_8B_ALAW 27 +#define HARMONY_MAGIC_16B_LINEAR 3 +#define HARMONY_MAGIC_MONO 1 +#define HARMONY_MAGIC_STEREO 2 + +/* + * Channels Positions in mixer register + */ + +#define GAIN_HE_SHIFT 27 +#define GAIN_HE_MASK ( 1 << GAIN_HE_SHIFT) +#define GAIN_LE_SHIFT 26 +#define GAIN_LE_MASK ( 1 << GAIN_LE_SHIFT) +#define GAIN_SE_SHIFT 25 +#define GAIN_SE_MASK ( 1 << GAIN_SE_SHIFT) +#define GAIN_IS_SHIFT 24 +#define GAIN_IS_MASK ( 1 << GAIN_IS_SHIFT) +#define GAIN_MA_SHIFT 20 +#define GAIN_MA_MASK ( 0x0f << GAIN_MA_SHIFT) +#define GAIN_LI_SHIFT 16 +#define GAIN_LI_MASK ( 0x0f << GAIN_LI_SHIFT) +#define GAIN_RI_SHIFT 12 +#define GAIN_RI_MASK ( 0x0f << GAIN_RI_SHIFT) +#define GAIN_LO_SHIFT 6 +#define GAIN_LO_MASK ( 0x3f << GAIN_LO_SHIFT) +#define GAIN_RO_SHIFT 0 +#define GAIN_RO_MASK ( 0x3f << GAIN_RO_SHIFT) + + +#define MAX_OUTPUT_LEVEL (GAIN_RO_MASK >> GAIN_RO_SHIFT) +#define MAX_INPUT_LEVEL (GAIN_RI_MASK >> GAIN_RI_SHIFT) +#define MAX_VOLUME_LEVEL (GAIN_MA_MASK >> GAIN_MA_SHIFT) + +/* + * Channels Mask in mixer register + */ + +#define GAIN_TOTAL_SILENCE 0x00F00FFF +#define GAIN_DEFAULT 0x0FF00000 + + +struct harmony_hpa { + u8 unused000; + u8 id; + u8 teleshare_id; + u8 unused003; + u32 reset; + u32 cntl; + u32 gainctl; + u32 pnxtadd; + u32 pcuradd; + u32 rnxtadd; + u32 rcuradd; + u32 dstatus; + u32 ov; + u32 pio; + u32 unused02c; + u32 unused030[3]; + u32 diag; +}; + +struct harmony_dev { + int irq; + struct harmony_hpa *hpa; + u32 current_gain; + u8 data_format; /* HARMONY_DF_xx_BIT_xxx */ + u8 sample_rate; /* HARMONY_SR_xx_KHZ */ + u8 stereo_select; /* HARMONY_SS_MONO or HARMONY_SS_STEREO */ + int format_initialized; + u32 dac_rate; /* 8000 ... 48000 (Hz) */ + int suspended_playing; + int suspended_recording; + + int blocked_playing; + int blocked_recording; + + wait_queue_head_t wq_play, wq_record; + int first_filled_play; /* first buffer containing data (next to play) */ + int nb_filled_play; + int play_offset; + int first_filled_record; + int nb_filled_record; + + int audio_open, mixer_open; + int dsp_unit, mixer_unit; + + struct pci_dev *fake_pci_dev; /* The fake pci_dev needed for + pci_* functions under ccio. */ +}; + + +static struct harmony_dev harmony; + + +/* + * Dynamic sound buffer allocation and DMA memory + */ + +struct harmony_buffer { + unsigned char *addr; + dma_addr_t dma_handle; + int dma_consistent; /* Zero if pci_alloc_consistent() fails */ + int len; +}; + +/* + * Harmony memory buffers + */ + +static struct harmony_buffer played_buf, recorded_buf, silent, graveyard; + + +#define CHECK_WBACK_INV_OFFSET(b,offset,len) \ + do { if (!b.dma_consistent) \ + dma_cache_wback_inv((unsigned long)b.addr+offset,len); \ + } while (0) + + +static int __init harmony_alloc_buffer(struct harmony_buffer *b, + int buffer_count) +{ + b->len = buffer_count * HARMONY_BUF_SIZE; + b->addr = pci_alloc_consistent(harmony.fake_pci_dev, + b->len, &b->dma_handle); + if (b->addr && b->dma_handle) { + b->dma_consistent = 1; + DPRINTK(KERN_INFO PFX "consistent memory: 0x%lx, played_buf: 0x%lx\n", + (unsigned long)b->dma_handle, (unsigned long)b->addr); + } else { + b->dma_consistent = 0; + /* kmalloc()ed memory will HPMC on ccio machines ! */ + b->addr = kmalloc(b->len, GFP_KERNEL); + if (!b->addr) { + printk(KERN_ERR PFX "couldn't allocate memory\n"); + return -EBUSY; + } + b->dma_handle = __pa(b->addr); + } + return 0; +} + +static void __exit harmony_free_buffer(struct harmony_buffer *b) +{ + if (!b->addr) + return; + + if (b->dma_consistent) + pci_free_consistent(harmony.fake_pci_dev, + b->len, b->addr, b->dma_handle); + else + kfree(b->addr); + + memset(b, 0, sizeof(*b)); +} + + + +/* + * Low-Level sound-chip programming + */ + +static void __inline__ harmony_wait_CNTL(void) +{ + /* Wait until we're out of control mode */ + while (gsc_readl(&harmony.hpa->cntl) & CNTL_C) + /* wait */ ; +} + + +static void harmony_update_control(void) +{ + u32 default_cntl; + + /* Set CNTL */ + default_cntl = (CNTL_C | /* The C bit */ + (harmony.data_format << 6) | /* Set the data format */ + (harmony.stereo_select << 5) | /* Stereo select */ + (harmony.sample_rate)); /* Set sample rate */ + harmony.format_initialized = 1; + + /* initialize CNTL */ + gsc_writel(default_cntl, &harmony.hpa->cntl); +} + +static void harmony_set_control(u8 data_format, u8 sample_rate, u8 stereo_select) +{ + harmony.sample_rate = sample_rate; + harmony.data_format = data_format; + harmony.stereo_select = stereo_select; + harmony_update_control(); +} + +static void harmony_set_rate(u8 data_rate) +{ + harmony.sample_rate = data_rate; + harmony_update_control(); +} + +static int harmony_detect_rate(int *freq) +{ + int newrate; + switch (*freq) { + case 8000: newrate = HARMONY_SR_8KHZ; break; + case 16000: newrate = HARMONY_SR_16KHZ; break; + case 27428: newrate = HARMONY_SR_27KHZ; break; + case 32000: newrate = HARMONY_SR_32KHZ; break; + case 48000: newrate = HARMONY_SR_48KHZ; break; + case 9600: newrate = HARMONY_SR_9KHZ; break; + case 5125: newrate = HARMONY_SR_5KHZ; break; + case 11025: newrate = HARMONY_SR_11KHZ; break; + case 18900: newrate = HARMONY_SR_18KHZ; break; + case 22050: newrate = HARMONY_SR_22KHZ; break; + case 37800: newrate = HARMONY_SR_37KHZ; break; + case 44100: newrate = HARMONY_SR_44KHZ; break; + case 33075: newrate = HARMONY_SR_33KHZ; break; + case 6615: newrate = HARMONY_SR_6KHZ; break; + default: newrate = HARMONY_SR_8KHZ; + *freq = 8000; break; + } + return newrate; +} + +static void harmony_set_format(u8 data_format) +{ + harmony.data_format = data_format; + harmony_update_control(); +} + +static void harmony_set_stereo(u8 stereo_select) +{ + harmony.stereo_select = stereo_select; + harmony_update_control(); +} + +static void harmony_disable_interrupts(void) +{ + harmony_wait_CNTL(); + gsc_writel(0, &harmony.hpa->dstatus); +} + +static void harmony_enable_interrupts(void) +{ + harmony_wait_CNTL(); + gsc_writel(DSTATUS_IE, &harmony.hpa->dstatus); +} + +/* + * harmony_silence() + * + * This subroutine fills in a buffer starting at location start and + * silences for length bytes. This references the current + * configuration of the audio format. + * + */ + +static void harmony_silence(struct harmony_buffer *buffer, int start, int length) +{ + u8 silence_char; + + /* Despite what you hear, silence is different in + different audio formats. */ + switch (harmony.data_format) { + case HARMONY_DF_8BIT_ULAW: silence_char = 0x55; break; + case HARMONY_DF_8BIT_ALAW: silence_char = 0xff; break; + case HARMONY_DF_16BIT_LINEAR: /* fall through */ + default: silence_char = 0; + } + + memset(buffer->addr+start, silence_char, length); +} + + +static int harmony_audio_open(struct inode *inode, struct file *file) +{ + if (harmony.audio_open) + return -EBUSY; + + harmony.audio_open++; + harmony.suspended_playing = harmony.suspended_recording = 1; + harmony.blocked_playing = harmony.blocked_recording = 0; + harmony.first_filled_play = harmony.first_filled_record = 0; + harmony.nb_filled_play = harmony.nb_filled_record = 0; + harmony.play_offset = 0; + init_waitqueue_head(&harmony.wq_play); + init_waitqueue_head(&harmony.wq_record); + + /* Start off in a balanced mode. */ + harmony_set_control(HARMONY_DF_8BIT_ULAW, HARMONY_SR_8KHZ, HARMONY_SS_MONO); + harmony_update_control(); + harmony.format_initialized = 0; + + /* Clear out all the buffers and flush to cache */ + harmony_silence(&played_buf, 0, HARMONY_BUF_SIZE*MAX_BUFS); + CHECK_WBACK_INV_OFFSET(played_buf, 0, HARMONY_BUF_SIZE*MAX_BUFS); + + return 0; +} + +/* + * Release (close) the audio device. + */ + +static int harmony_audio_release(struct inode *inode, struct file *file) +{ + if (!harmony.audio_open) + return -EBUSY; + + harmony.audio_open--; + + return 0; +} + +/* + * Read recorded data off the audio device. + */ + +static ssize_t harmony_audio_read(struct file *file, + char *buffer, + size_t size_count, + loff_t *ppos) +{ + int total_count = (int) size_count; + int count = 0; + int buf_to_read; + + while (count24) { + copy_from_user(file_header, buffer, sizeof(file_header)); + start_string = four_bytes_to_u32(0); + + if ((file_header[4]==0) && (start_string==0x2E736E64)) { + u32 format; + u32 nb_voices; + u32 speed; + + format = four_bytes_to_u32(12); + nb_voices = four_bytes_to_u32(20); + speed = four_bytes_to_u32(16); + + switch (format) { + case HARMONY_MAGIC_8B_ULAW: + harmony.data_format = HARMONY_DF_8BIT_ULAW; + break; + case HARMONY_MAGIC_8B_ALAW: + harmony.data_format = HARMONY_DF_8BIT_ALAW; + break; + case HARMONY_MAGIC_16B_LINEAR: + harmony.data_format = HARMONY_DF_16BIT_LINEAR; + break; + default: + harmony_set_control(HARMONY_DF_16BIT_LINEAR, + HARMONY_SR_44KHZ, HARMONY_SS_STEREO); + return; + } + switch (nb_voices) { + case HARMONY_MAGIC_MONO: + harmony.stereo_select = HARMONY_SS_MONO; + break; + case HARMONY_MAGIC_STEREO: + harmony.stereo_select = HARMONY_SS_STEREO; + break; + default: + harmony.stereo_select = HARMONY_SS_MONO; + break; + } + harmony_set_rate(harmony_detect_rate(&speed)); + harmony.dac_rate = speed; + return; + } + } + harmony_set_control(HARMONY_DF_8BIT_ULAW, HARMONY_SR_8KHZ, HARMONY_SS_MONO); +} +#undef four_bytes_to_u32 + + +static ssize_t harmony_audio_write(struct file *file, + const char *buffer, + size_t size_count, + loff_t *ppos) +{ + int total_count = (int) size_count; + int count = 0; + int frame_size; + int buf_to_fill; + + if (!harmony.format_initialized) + harmony_format_auto_detect(buffer, total_count); + + while (count= MAX_BUFS && !harmony.play_offset) { + harmony.blocked_playing = 1; + interruptible_sleep_on(&harmony.wq_play); + harmony.blocked_playing = 0; + } + if (harmony.nb_filled_play+2 >= MAX_BUFS && !harmony.play_offset) + return -EBUSY; + + + buf_to_fill = (harmony.first_filled_play+harmony.nb_filled_play); + if (harmony.play_offset) + buf_to_fill--; + buf_to_fill %= MAX_BUFS; + + /* Figure out the size of the frame */ + if ((total_count-count) > HARMONY_BUF_SIZE - harmony.play_offset) { + frame_size = HARMONY_BUF_SIZE - harmony.play_offset; + } else { + frame_size = total_count - count; + /* Clear out the buffer, since there we'll only be + overlaying part of the old buffer with the new one */ + harmony_silence(&played_buf, + HARMONY_BUF_SIZE*buf_to_fill+frame_size+harmony.play_offset, + HARMONY_BUF_SIZE-frame_size-harmony.play_offset); + } + + /* Copy the page to an aligned buffer */ + copy_from_user(played_buf.addr + (HARMONY_BUF_SIZE*buf_to_fill) + harmony.play_offset, + buffer+count, frame_size); + CHECK_WBACK_INV_OFFSET(played_buf, (HARMONY_BUF_SIZE*buf_to_fill + harmony.play_offset), + frame_size); + + if (!harmony.play_offset) + harmony.nb_filled_play++; + + count += frame_size; + harmony.play_offset += frame_size; + harmony.play_offset %= HARMONY_BUF_SIZE; + if (harmony.suspended_playing && (harmony.nb_filled_play>=4)) + harmony_enable_interrupts(); + } + + return count; +} + +static unsigned int harmony_audio_poll(struct file *file, + struct poll_table_struct *wait) +{ + unsigned int mask = 0; + + if (file->f_mode & FMODE_READ) { + if (!harmony.suspended_recording) + poll_wait(file, &harmony.wq_record, wait); + if (harmony.nb_filled_record) + mask |= POLLIN | POLLRDNORM; + } + + if (file->f_mode & FMODE_WRITE) { + if (!harmony.suspended_playing) + poll_wait(file, &harmony.wq_play, wait); + if (harmony.nb_filled_play) + mask |= POLLOUT | POLLWRNORM; + } + + return mask; +} + +static int harmony_audio_ioctl(struct inode *inode, + struct file *file, + unsigned int cmd, + unsigned long arg) +{ + int ival, new_format; + int frag_size, frag_buf; + struct audio_buf_info info; + + switch (cmd) { + case OSS_GETVERSION: + return put_user(SOUND_VERSION, (int *) arg); + + case SNDCTL_DSP_GETCAPS: + ival = DSP_CAP_DUPLEX; + return put_user(ival, (int *) arg); + + case SNDCTL_DSP_GETFMTS: + ival = (AFMT_S16_BE | AFMT_MU_LAW | AFMT_A_LAW ); + return put_user(ival, (int *) arg); + + case SNDCTL_DSP_SETFMT: + if (get_user(ival, (int *) arg)) + return -EFAULT; + if (ival != AFMT_QUERY) { + switch (ival) { + case AFMT_MU_LAW: new_format = HARMONY_DF_8BIT_ULAW; break; + case AFMT_A_LAW: new_format = HARMONY_DF_8BIT_ALAW; break; + case AFMT_S16_LE: /* fall through, but not really supported */ + case AFMT_S16_BE: new_format = HARMONY_DF_16BIT_LINEAR; + ival = AFMT_S16_BE; + break; + default: { + DPRINTK(KERN_WARNING PFX + "unsupported sound format 0x%04x requested.\n", + ival); + return -EINVAL; + } + } + harmony_set_format(new_format); + } else { + switch (harmony.data_format) { + case HARMONY_DF_8BIT_ULAW: ival = AFMT_MU_LAW; break; + case HARMONY_DF_8BIT_ALAW: ival = AFMT_A_LAW; break; + case HARMONY_DF_16BIT_LINEAR: ival = AFMT_U16_BE; break; + default: ival = 0; + } + } + return put_user(ival, (int *) arg); + + case SOUND_PCM_READ_RATE: + ival = harmony.dac_rate; + return put_user(ival, (int *) arg); + + case SNDCTL_DSP_SPEED: + if (get_user(ival, (int *) arg)) + return -EFAULT; + harmony_set_rate(harmony_detect_rate(&ival)); + harmony.dac_rate = ival; + return put_user(ival, (int*) arg); + + case SNDCTL_DSP_STEREO: + if (get_user(ival, (int *) arg)) + return -EFAULT; + if (ival != 0 && ival != 1) + return -EINVAL; + harmony_set_stereo(ival); + return put_user(ival, (int *) arg); + + case SNDCTL_DSP_GETBLKSIZE: + ival = HARMONY_BUF_SIZE; + return put_user(ival, (int *) arg); + + case SNDCTL_DSP_NONBLOCK: + file->f_flags |= O_NONBLOCK; + return 0; + + case SNDCTL_DSP_RESET: + if (!harmony.suspended_recording) { + /* TODO: stop_recording() */ + } + return 0; + + case SNDCTL_DSP_SETFRAGMENT: + if (get_user(ival, (int *)arg)) + return -EFAULT; + frag_size = ival & 0xffff; + frag_buf = (ival>>16) & 0xffff; + /* TODO: We use hardcoded fragment sizes and numbers for now */ + frag_size = 12; /* 4096 == 2^12 */ + frag_buf = MAX_BUFS; + ival = (frag_buf << 16) + frag_size; + return put_user(ival, (int *) arg); + + case SNDCTL_DSP_GETOSPACE: + if (!(file->f_mode & FMODE_WRITE)) + return -EINVAL; + info.fragstotal = MAX_BUFS; + info.fragments = MAX_BUFS - harmony.nb_filled_play; + info.fragsize = HARMONY_BUF_SIZE; + info.bytes = info.fragments * info.fragsize; + return copy_to_user((void *)arg, &info, sizeof(info)); + + case SNDCTL_DSP_GETISPACE: + if (!(file->f_mode & FMODE_READ)) + return -EINVAL; + info.fragstotal = MAX_BUFS; + info.fragments = /*MAX_BUFS-*/ harmony.nb_filled_record; + info.fragsize = HARMONY_BUF_SIZE; + info.bytes = info.fragments * info.fragsize; + return copy_to_user((void *)arg, &info, sizeof(info)); + + case SNDCTL_DSP_SYNC: + return 0; + } + + return -EINVAL; +} + + +/* + * harmony_interrupt() + * + * harmony interruption service routine + * + */ + +static void harmony_interrupt(int irq, void *dev, struct pt_regs *regs) +{ + u32 dstatus; + struct harmony_hpa *hpa; + + /* Setup the hpa */ + hpa = ((struct harmony_dev *)dev)->hpa; + harmony_wait_CNTL(); + + /* Read dstatus and pcuradd (the current address) */ + dstatus = gsc_readl(&hpa->dstatus); + + /* Turn off interrupts */ + harmony_disable_interrupts(); + + /* Check if this is a request to get the next play buffer */ + if (dstatus & DSTATUS_PN) { + if (!harmony.nb_filled_play) { + harmony.suspended_playing = 1; + gsc_writel((unsigned long)silent.dma_handle, &hpa->pnxtadd); + + if (!harmony.suspended_recording) + harmony_enable_interrupts(); + } else { + harmony.suspended_playing = 0; + gsc_writel((unsigned long)played_buf.dma_handle + + (HARMONY_BUF_SIZE*harmony.first_filled_play), + &hpa->pnxtadd); + harmony.first_filled_play++; + harmony.first_filled_play %= MAX_BUFS; + harmony.nb_filled_play--; + + harmony_enable_interrupts(); + } + + if (harmony.blocked_playing) + wake_up_interruptible(&harmony.wq_play); + } + + /* Check if we're being asked to fill in a recording buffer */ + if (dstatus & DSTATUS_RN) { + if((harmony.nb_filled_record+2>=MAX_BUFS) || harmony.suspended_recording) + { + harmony.nb_filled_record = 0; + harmony.first_filled_record = 0; + harmony.suspended_recording = 1; + gsc_writel((unsigned long)graveyard.dma_handle, &hpa->rnxtadd); + if (!harmony.suspended_playing) + harmony_enable_interrupts(); + } else { + int buf_to_fill; + buf_to_fill = (harmony.first_filled_record+harmony.nb_filled_record) % MAX_BUFS; + CHECK_WBACK_INV_OFFSET(recorded_buf, HARMONY_BUF_SIZE*buf_to_fill, HARMONY_BUF_SIZE); + gsc_writel((unsigned long)recorded_buf.dma_handle + + HARMONY_BUF_SIZE*buf_to_fill, + &hpa->rnxtadd); + harmony.nb_filled_record++; + harmony_enable_interrupts(); + } + + if (harmony.blocked_recording && harmony.nb_filled_record>3) + wake_up_interruptible(&harmony.wq_record); + } +} + +/* + * Sound playing functions + */ + +static struct file_operations harmony_audio_fops = { + owner: THIS_MODULE, + llseek: no_llseek, + read: harmony_audio_read, + write: harmony_audio_write, + poll: harmony_audio_poll, + ioctl: harmony_audio_ioctl, + open: harmony_audio_open, + release:harmony_audio_release, +}; + +static int harmony_audio_init(void) +{ + /* Request that IRQ */ + if (request_irq(harmony.irq, harmony_interrupt, 0 ,"harmony", &harmony)) { + printk(KERN_ERR PFX "Error requesting irq %d.\n", harmony.irq); + return -EFAULT; + } + + harmony.dsp_unit = register_sound_dsp(&harmony_audio_fops, -1); + if (harmony.dsp_unit < 0) { + printk(KERN_ERR PFX "Error registering dsp\n"); + free_irq(harmony.irq, &harmony); + return -EFAULT; + } + + /* Clear the buffers so you don't end up with crap in the buffers. */ + harmony_silence(&played_buf, 0, HARMONY_BUF_SIZE*MAX_BUFS); + + /* Make sure this makes it to cache */ + CHECK_WBACK_INV_OFFSET(played_buf, 0, HARMONY_BUF_SIZE*MAX_BUFS); + + /* Clear out the silent buffer and flush to cache */ + harmony_silence(&silent, 0, HARMONY_BUF_SIZE); + CHECK_WBACK_INV_OFFSET(silent, 0, HARMONY_BUF_SIZE); + + harmony.audio_open = 0; + + return 0; +} + + +/* + * mixer functions + */ + +static void harmony_mixer_set_gain(void) +{ + harmony_wait_CNTL(); + gsc_writel(harmony.current_gain, &harmony.hpa->gainctl); +} + +/* + * Read gain of selected channel. + * The OSS rate is from 0 (silent) to 100 -> need some conversions + * + * The harmony gain are attenuation for output and monitor gain. + * is amplifaction for input gain + */ +#define to_harmony_level(level,max) ((level)*max/100) +#define to_oss_level(level,max) ((level)*100/max) + +static int harmony_mixer_get_level(int channel) +{ + int left_level; + int right_level; + + switch (channel) { + case SOUND_MIXER_OGAIN: + left_level = (harmony.current_gain & GAIN_LO_MASK) >> GAIN_LO_SHIFT; + right_level = (harmony.current_gain & GAIN_RO_MASK) >> GAIN_RO_SHIFT; + left_level = to_oss_level(MAX_OUTPUT_LEVEL - left_level, MAX_OUTPUT_LEVEL); + right_level = to_oss_level(MAX_OUTPUT_LEVEL - right_level, MAX_OUTPUT_LEVEL); + return (right_level << 8)+left_level; + + case SOUND_MIXER_IGAIN: + left_level = (harmony.current_gain & GAIN_LI_MASK) >> GAIN_LI_SHIFT; + right_level= (harmony.current_gain & GAIN_RI_MASK) >> GAIN_RI_SHIFT; + left_level = to_oss_level(left_level, MAX_INPUT_LEVEL); + right_level= to_oss_level(right_level, MAX_INPUT_LEVEL); + return (right_level << 8)+left_level; + + case SOUND_MIXER_VOLUME: + left_level = (harmony.current_gain & GAIN_MA_MASK) >> GAIN_MA_SHIFT; + left_level = to_oss_level(MAX_VOLUME_LEVEL-left_level, MAX_VOLUME_LEVEL); + return left_level; + } + return -EINVAL; +} + + + +/* + * Some conversions for the same reasons. + * We give back the new real value(s) due to + * the rescale. + */ + +static int harmony_mixer_set_level(int channel, int value) +{ + int left_level; + int right_level; + int new_left_level; + int new_right_level; + + right_level = (value & 0x0000ff00) >> 8; + left_level = value & 0x000000ff; + + switch (channel) { + case SOUND_MIXER_OGAIN: + right_level = to_harmony_level(100-right_level, MAX_OUTPUT_LEVEL); + left_level = to_harmony_level(100-left_level, MAX_OUTPUT_LEVEL); + new_right_level = to_oss_level(MAX_OUTPUT_LEVEL - right_level, MAX_OUTPUT_LEVEL); + new_left_level = to_oss_level(MAX_OUTPUT_LEVEL - left_level, MAX_OUTPUT_LEVEL); + harmony.current_gain = (harmony.current_gain & ~(GAIN_LO_MASK | GAIN_RO_MASK)) + | (left_level << GAIN_LO_SHIFT) | (right_level << GAIN_RO_SHIFT); + harmony_mixer_set_gain(); + return (new_right_level << 8) + new_left_level; + + case SOUND_MIXER_IGAIN: + right_level = to_harmony_level(right_level, MAX_INPUT_LEVEL); + left_level = to_harmony_level(left_level, MAX_INPUT_LEVEL); + new_right_level = to_oss_level(right_level, MAX_INPUT_LEVEL); + new_left_level = to_oss_level(left_level, MAX_INPUT_LEVEL); + harmony.current_gain = (harmony.current_gain & ~(GAIN_LI_MASK | GAIN_RI_MASK)) + | (left_level << GAIN_LI_SHIFT) | (right_level << GAIN_RI_SHIFT); + harmony_mixer_set_gain(); + return (new_right_level << 8) + new_left_level; + + case SOUND_MIXER_VOLUME: + left_level = to_harmony_level(100-left_level, MAX_VOLUME_LEVEL); + new_left_level = to_oss_level(MAX_VOLUME_LEVEL-left_level, MAX_VOLUME_LEVEL); + harmony.current_gain = (harmony.current_gain & ~GAIN_MA_MASK)| (left_level << GAIN_MA_SHIFT); + harmony_mixer_set_gain(); + return new_left_level; + } + + return -EINVAL; +} + +#undef to_harmony_level +#undef to_oss_level + +/* + * Return the selected input device (mic or line) + */ + +static int harmony_mixer_get_recmask(void) +{ + int current_input_line; + + current_input_line = (harmony.current_gain & GAIN_IS_MASK) + >> GAIN_IS_SHIFT; + if (current_input_line) + return SOUND_MASK_MIC; + + return SOUND_MASK_LINE; +} + +/* + * Set the input (only one at time, arbitrary priority to line in) + */ + +static int harmony_mixer_set_recmask(int recmask) +{ + int new_input_line; + int new_input_mask; + + if ((recmask & SOUND_MASK_LINE)) { + new_input_line = 0; + new_input_mask = SOUND_MASK_LINE; + } else { + new_input_line = 1; + new_input_mask = SOUND_MASK_MIC; + } + harmony.current_gain = ((harmony.current_gain & ~GAIN_IS_MASK) | + (new_input_line << GAIN_IS_SHIFT )); + harmony_mixer_set_gain(); + return new_input_mask; +} + + +/* + * give the active outlines + */ + +static int harmony_mixer_get_outmask(void) +{ + int outmask = 0; + + if (harmony.current_gain & GAIN_HE_MASK) outmask |=SOUND_MASK_PHONEOUT; + if (harmony.current_gain & GAIN_LE_MASK) outmask |=SOUND_MASK_LINE; + if (harmony.current_gain & GAIN_SE_MASK) outmask |=SOUND_MASK_SPEAKER; + + return outmask; +} + + +static int harmony_mixer_set_outmask(int outmask) +{ + if (outmask & SOUND_MASK_PHONEOUT) + harmony.current_gain |= GAIN_HE_MASK; + else + harmony.current_gain &= ~GAIN_HE_MASK; + + if (outmask & SOUND_MASK_LINE) + harmony.current_gain |= GAIN_LE_MASK; + else + harmony.current_gain &= ~GAIN_LE_MASK; + + if (outmask & SOUND_MASK_SPEAKER) + harmony.current_gain |= GAIN_SE_MASK; + else + harmony.current_gain &= ~GAIN_SE_MASK; + + harmony_mixer_set_gain(); + + return (outmask & (SOUND_MASK_PHONEOUT | SOUND_MASK_LINE | SOUND_MASK_SPEAKER)); +} + +/* + * This code is inspired from sb_mixer.c + */ + +static int harmony_mixer_ioctl(struct inode * inode, struct file * file, + unsigned int cmd, unsigned long arg) +{ + int val; + int ret; + + if (cmd == SOUND_MIXER_INFO) { + mixer_info info; + memset(&info, 0, sizeof(info)); + strncpy(info.id, "harmony", sizeof(info.id)-1); + strncpy(info.name, "Harmony audio", sizeof(info.name)-1); + info.modify_counter = 1; /* ? */ + if (copy_to_user((void *)arg, &info, sizeof(info))) + return -EFAULT; + return 0; + } + + if (cmd == OSS_GETVERSION) + return put_user(SOUND_VERSION, (int *)arg); + + /* read */ + val = 0; + if (_SIOC_DIR(cmd) & _SIOC_WRITE) + if (get_user(val, (int *)arg)) + return -EFAULT; + + switch (cmd) { + case MIXER_READ(SOUND_MIXER_CAPS): + ret = SOUND_CAP_EXCL_INPUT; + break; + case MIXER_READ(SOUND_MIXER_STEREODEVS): + ret = SOUND_MASK_IGAIN | SOUND_MASK_OGAIN; + break; + + case MIXER_READ(SOUND_MIXER_RECMASK): + ret = SOUND_MASK_MIC | SOUND_MASK_LINE; + break; + case MIXER_READ(SOUND_MIXER_DEVMASK): + ret = SOUND_MASK_OGAIN | SOUND_MASK_IGAIN | + SOUND_MASK_VOLUME; + break; + case MIXER_READ(SOUND_MIXER_OUTMASK): + ret = SOUND_MASK_SPEAKER | SOUND_MASK_LINE | + SOUND_MASK_PHONEOUT; + break; + + case MIXER_WRITE(SOUND_MIXER_RECSRC): + ret = harmony_mixer_set_recmask(val); + break; + case MIXER_READ(SOUND_MIXER_RECSRC): + ret = harmony_mixer_get_recmask(); + break; + + case MIXER_WRITE(SOUND_MIXER_OUTSRC): + ret = harmony_mixer_set_outmask(val); + break; + case MIXER_READ(SOUND_MIXER_OUTSRC): + ret = harmony_mixer_get_outmask(); + break; + + case MIXER_WRITE(SOUND_MIXER_OGAIN): + case MIXER_WRITE(SOUND_MIXER_IGAIN): + case MIXER_WRITE(SOUND_MIXER_VOLUME): + ret = harmony_mixer_set_level(cmd & 0xff, val); + break; + + case MIXER_READ(SOUND_MIXER_OGAIN): + case MIXER_READ(SOUND_MIXER_IGAIN): + case MIXER_READ(SOUND_MIXER_VOLUME): + ret = harmony_mixer_get_level(cmd & 0xff); + break; + + default: + return -EINVAL; + } + + if (put_user(ret, (int *)arg)) + return -EFAULT; + return 0; +} + + +static int harmony_mixer_open(struct inode *inode, struct file *file) +{ + if (harmony.mixer_open) + return -EBUSY; + harmony.mixer_open++; + return 0; +} + +static int harmony_mixer_release(struct inode *inode, struct file *file) +{ + if (!harmony.mixer_open) + return -EBUSY; + harmony.mixer_open--; + return 0; +} + +static struct file_operations harmony_mixer_fops = { + owner: THIS_MODULE, + llseek: no_llseek, + open: harmony_mixer_open, + release: harmony_mixer_release, + ioctl: harmony_mixer_ioctl, +}; + + +/* + * Mute all the output and reset Harmony. + */ + +static void __init harmony_mixer_reset(void) +{ + harmony.current_gain = GAIN_TOTAL_SILENCE; + harmony_mixer_set_gain(); + harmony_wait_CNTL(); + gsc_writel(1, &harmony.hpa->reset); + mdelay(50); /* wait 50 ms */ + gsc_writel(0, &harmony.hpa->reset); + harmony.current_gain = GAIN_DEFAULT; + harmony_mixer_set_gain(); +} + +static int __init harmony_mixer_init(void) +{ + /* Register the device file operations */ + harmony.mixer_unit = register_sound_mixer(&harmony_mixer_fops, -1); + if (harmony.mixer_unit < 0) { + printk(KERN_WARNING PFX "Error Registering Mixer Driver\n"); + return -EFAULT; + } + + harmony_mixer_reset(); + harmony.mixer_open = 0; + + return 0; +} + + + +/* + * This is the callback that's called by the inventory hardware code + * if it finds a match to the registered driver. + */ +static int __init +harmony_driver_callback(struct parisc_device *dev) +{ + u8 id; + u8 rev; + u32 cntl; + int ret; + + if (harmony.hpa) { + /* We only support one Harmony at this time */ + printk(KERN_ERR PFX "driver already registered\n"); + return -EBUSY; + } + + /* Set the HPA of harmony */ + harmony.hpa = (struct harmony_hpa *)dev->hpa; + + harmony.irq = dev->irq; + if (!harmony.irq) { + printk(KERN_ERR PFX "no irq found\n"); + return -ENODEV; + } + + /* Grab the ID and revision from the device */ + id = gsc_readb(&harmony.hpa->id); + if ((id | 1) != 0x15) { + printk(KERN_WARNING PFX "wrong harmony id 0x%02x\n", id); + return -EBUSY; + } + cntl = gsc_readl(&harmony.hpa->cntl); + rev = (cntl>>20) & 0xff; + + printk(KERN_INFO "Lasi Harmony Audio driver " HARMONY_VERSION ", " + "h/w id %i, rev. %i at 0x%lx, IRQ %i\n", + id, rev, dev->hpa, harmony.irq); + + /* Make sure the control bit isn't set, although I don't think it + ever is. */ + if (cntl & CNTL_C) { + printk(KERN_WARNING PFX "CNTL busy\n"); + harmony.hpa = 0; + return -EBUSY; + } + + /* a fake pci_dev is needed for pci_* functions under ccio */ + harmony.fake_pci_dev = ccio_get_fake(dev); + + /* Initialize the memory buffers */ + if (harmony_alloc_buffer(&played_buf, MAX_BUFS) || + harmony_alloc_buffer(&recorded_buf, MAX_BUFS) || + harmony_alloc_buffer(&graveyard, 1) || + harmony_alloc_buffer(&silent, 1)) { + ret = -EBUSY; + goto out_err; + } + + /* Initialize /dev/mixer and /dev/audio */ + if ((ret=harmony_mixer_init())) + goto out_err; + if ((ret=harmony_audio_init())) + goto out_err; + + return 0; + +out_err: + harmony.hpa = 0; + harmony_free_buffer(&played_buf); + harmony_free_buffer(&recorded_buf); + harmony_free_buffer(&graveyard); + harmony_free_buffer(&silent); + return ret; +} + + +static struct parisc_device_id harmony_tbl[] = { + /* { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007A }, Bushmaster/Flounder */ + { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007B }, /* 712/715 Audio */ + { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007E }, /* Pace Audio */ + { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007F }, /* Outfield / Coral II */ + { 0, } +}; + +MODULE_DEVICE_TABLE(parisc, harmony_tbl); + +static struct parisc_driver harmony_driver = { + name: "Lasi Harmony", + id_table: harmony_tbl, + probe: harmony_driver_callback, +}; + +static int __init init_harmony(void) +{ + return register_parisc_driver(&harmony_driver); +} + +static void __exit cleanup_harmony(void) +{ + free_irq(harmony.irq, &harmony); + unregister_sound_mixer(harmony.mixer_unit); + unregister_sound_dsp(harmony.dsp_unit); + harmony_free_buffer(&played_buf); + harmony_free_buffer(&recorded_buf); + harmony_free_buffer(&graveyard); + harmony_free_buffer(&silent); + unregister_parisc_driver(&harmony_driver); +} + +EXPORT_NO_SYMBOLS; + +MODULE_AUTHOR("Alex DeVries "); +MODULE_DESCRIPTION("Harmony sound driver"); +MODULE_LICENSE("GPL"); + +module_init(init_harmony); +module_exit(cleanup_harmony); + diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/sound/Makefile linux.19rc3-ac4/drivers/sound/Makefile --- linux.19rc3/drivers/sound/Makefile 2002-07-29 12:54:48.000000000 +0100 +++ linux.19rc3-ac4/drivers/sound/Makefile 2002-07-29 13:58:43.000000000 +0100 @@ -22,6 +22,7 @@ obj-$(CONFIG_SOUND_HAL2) += hal2.o obj-$(CONFIG_SOUND_AEDSP16) += aedsp16.o +obj-$(CONFIG_SOUND_ALI5455) += ali5455.o ac97_codec.o obj-$(CONFIG_SOUND_PSS) += pss.o ad1848.o mpu401.o obj-$(CONFIG_SOUND_TRIX) += trix.o ad1848.o sb_lib.o uart401.o obj-$(CONFIG_SOUND_OPL3SA1) += opl3sa.o ad1848.o uart401.o @@ -71,6 +72,7 @@ obj-$(CONFIG_SOUND_MAESTRO) += maestro.o obj-$(CONFIG_SOUND_MAESTRO3) += maestro3.o ac97_codec.o obj-$(CONFIG_SOUND_TRIDENT) += trident.o ac97_codec.o +obj-$(CONFIG_SOUND_HARMONY) += harmony.o obj-$(CONFIG_SOUND_EMU10K1) += ac97_codec.o obj-$(CONFIG_SOUND_BCM_CS4297A) += swarm_cs4297a.o obj-$(CONFIG_SOUND_RME96XX) += rme96xx.o diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/sound/trident.c linux.19rc3-ac4/drivers/sound/trident.c --- linux.19rc3/drivers/sound/trident.c 2002-07-29 12:54:49.000000000 +0100 +++ linux.19rc3-ac4/drivers/sound/trident.c 2002-07-29 15:21:20.000000000 +0100 @@ -36,6 +36,35 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * History + * v0.14.10f + * July 24 2002 Muli Ben-Yehuda + * patch from Eric Lemar (via Ian Soboroff): in suspend and resume, + * fix wrong cast from pci_dev* to struct trident_card*. + * v0.14.10e + * July 19 2002 Muli Ben-Yehuda + * rewrite the DMA buffer allocation/deallcoation functions, to make it + * modular and fix a bug where we would call free_pages on memory + * obtained with pci_alloc_consistent. Also remove unnecessary #ifdef + * CONFIG_PROC_FS and various other cleanups. + * v0.14.10d + * July 19 2002 Muli Ben-Yehuda + * made several printk(KERN_NOTICE...) into TRDBG(...), to avoid spamming + * my syslog with hundreds of messages. + * v0.14.10c + * July 16 2002 Muli Ben-Yehuda + * Cleaned up Lei Hu's 0.4.10 driver to conform to Documentation/CodingStyle + * and the coding style used in the rest of the file. + * v0.14.10b + * June 23 2002 Muli Ben-Yehuda + * add a missing unlock_set_fmt, remove a superflous lock/unlock pair + * with nothing in between. + * v0.14.10a + * June 21 2002 Muli Ben-Yehuda + * use a debug macro instead of #ifdef CONFIG_DEBUG, trim to 80 columns + * per line, use 'do {} while (0)' in statement macros. + * v0.14.10 + * June 6 2002 Lei Hu + * rewrite the part to read/write registers of audio codec for Ali5451 * v0.14.9d * October 8 2001 Arnaldo Carvalho de Melo * use set_current_state, properly release resources on failure in @@ -46,7 +75,7 @@ * this chip is often found in settop boxes (combined video+audio) * v0.14.9b * Switch to static inline not extern inline (gcc 3) - * v0.14.9a + * v0.14.9a * Aug 6 2001 Alan Cox * 0.14.9 crashed on rmmod due to a timer/bh left running. Simplified * the existing logic (the BH doesnt help as ac97 is lock_irqsave) @@ -158,19 +187,20 @@ #include #include #include -#include -#include #include #include #include #include #include #include -#include -#include #include #include #include +#include +#include +#include +#include +#include #if defined CONFIG_ALPHA_NAUTILUS || CONFIG_ALPHA_GENERIC #include @@ -178,9 +208,7 @@ #include "trident.h" -#include - -#define DRIVER_VERSION "0.14.9d" +#define DRIVER_VERSION "0.14.10f" /* magic numbers to protect our data structures */ #define TRIDENT_CARD_MAGIC 0x5072696E /* "Prin" */ @@ -198,7 +226,13 @@ /* minor number of /dev/swmodem (temporary, experimental) */ #define SND_DEV_SWMODEM 7 -static const unsigned ali_multi_channels_5_1[] = { /*ALI_SURR_LEFT_CHANNEL, ALI_SURR_RIGHT_CHANNEL,*/ ALI_CENTER_CHANNEL, ALI_LEF_CHANNEL, ALI_SURR_LEFT_CHANNEL, ALI_SURR_RIGHT_CHANNEL}; +static const unsigned ali_multi_channels_5_1[] = { + /*ALI_SURR_LEFT_CHANNEL, ALI_SURR_RIGHT_CHANNEL,*/ + ALI_CENTER_CHANNEL, + ALI_LEF_CHANNEL, + ALI_SURR_LEFT_CHANNEL, + ALI_SURR_RIGHT_CHANNEL +}; static const unsigned sample_size[] = { 1, 2, 2, 4 }; static const unsigned sample_shift[] = { 0, 1, 1, 2 }; @@ -288,7 +322,7 @@ } dmabuf; - /* 5.1channels */ + /* 5.1 channels */ struct trident_state *other_states[4]; int multi_channels_adjust_count; unsigned chans_num; @@ -315,6 +349,7 @@ u32 aint; u32 aint_en; }; + static struct trident_pcm_bank_address bank_a_addrs = { T4D_START_A, @@ -322,6 +357,7 @@ T4D_AINT_A, T4D_AINTEN_A }; + static struct trident_pcm_bank_address bank_b_addrs = { T4D_START_B, @@ -329,6 +365,7 @@ T4D_AINT_B, T4D_AINTEN_B }; + struct trident_pcm_bank { /* register addresses to control bank operations */ struct trident_pcm_bank_address *addresses; @@ -391,6 +428,7 @@ HSET, MIC, MODEM_LINE1, MODEM_LINE2, I2S_LR, SPDIF_LR }; + /* table to map from channel attribute to CHANNELMASK for SiS 7018 */ static int attr2mask [] = { DSP_BIND_MODEM1, DSP_BIND_MODEM2, DSP_BIND_FRONT, DSP_BIND_HANDSET, @@ -399,7 +437,7 @@ /* Added by Matt Wu 01-05-2001 for spdif in */ static int ali_close_multi_channels(void); -static void ali_delay(struct trident_card *card,int interval); +static void ali_delay(struct trident_card *card, int interval); static void ali_detect_spdif_rate(struct trident_card *card); static void ali_ac97_write(struct ac97_codec *codec, u8 reg, u16 val); @@ -431,8 +469,11 @@ static void ali_disable_spdif_in(struct trident_card *card); static void ali_disable_special_channel(struct trident_card *card, int ch); static void ali_setup_spdif_out(struct trident_card *card, int flag); -static int ali_write_5_1(struct trident_state *state, const char *buffer,int cnt_for_multi_channel, unsigned int *copy_count, unsigned int *state_cnt); -static int ali_allocate_other_states_resources(struct trident_state *state, int chan_nums); +static int ali_write_5_1(struct trident_state *state, const char *buffer, + int cnt_for_multi_channel, unsigned int *copy_count, + unsigned int *state_cnt); +static int ali_allocate_other_states_resources(struct trident_state *state, + int chan_nums); static void ali_free_other_states_resources(struct trident_state *state); @@ -443,22 +484,29 @@ unsigned mixer_regs[ALI_MIXER_REGS]; } ali_registers; -#define seek_offset(dma_ptr, buffer, cnt, offset, copy_count) (dma_ptr) += (offset); \ - (buffer) += (offset); \ - (cnt) -= (offset); \ - (copy_count) += (offset); - -#define lock_set_fmt(state) {spin_lock_irqsave(&state->card->lock, flags); \ - if (state->fmt_flag) { \ - spin_unlock_irqrestore(&state->card->lock, flags); \ - return -EFAULT; \ - } \ - state->fmt_flag = 1; \ - spin_unlock_irqrestore(&state->card->lock, flags);} +#define seek_offset(dma_ptr, buffer, cnt, offset, copy_count) do { \ + (dma_ptr) += (offset); \ + (buffer) += (offset); \ + (cnt) -= (offset); \ + (copy_count) += (offset); \ +} while (0) + + +#define lock_set_fmt(state) do { \ + spin_lock_irqsave(&state->card->lock, flags); \ + if (state->fmt_flag) { \ + spin_unlock_irqrestore(&state->card->lock, flags); \ + return -EFAULT; \ + } \ + state->fmt_flag = 1; \ + spin_unlock_irqrestore(&state->card->lock, flags); \ +} while (0) -#define unlock_set_fmt(state) {spin_lock_irqsave(&state->card->lock, flags); \ - state->fmt_flag = 0; \ - spin_unlock_irqrestore(&state->card->lock, flags);} +#define unlock_set_fmt(state) do { \ + spin_lock_irqsave(&state->card->lock, flags); \ + state->fmt_flag = 0; \ + spin_unlock_irqrestore(&state->card->lock, flags); \ +} while (0) static int trident_enable_loop_interrupts(struct trident_card * card) { @@ -483,10 +531,9 @@ outl(global_control, TRID_REG(card, T4D_LFO_GC_CIR)); -#ifdef DEBUG - printk("trident: Enable Loop Interrupts, globctl = 0x%08X\n", - inl(TRID_REG(card, T4D_LFO_GC_CIR))); -#endif + TRDBG("trident: Enable Loop Interrupts, globctl = 0x%08X\n", + inl(TRID_REG(card, T4D_LFO_GC_CIR))); + return (TRUE); } @@ -498,10 +545,9 @@ global_control &= ~(ENDLP_IE | MIDLP_IE); outl(global_control, TRID_REG(card, T4D_LFO_GC_CIR)); -#ifdef DEBUG - printk("trident: Disabled Loop Interrupts, globctl = 0x%08X\n", - global_control); -#endif + TRDBG("trident: Disabled Loop Interrupts, globctl = 0x%08X\n", + global_control); + return (TRUE); } @@ -517,9 +563,9 @@ #ifdef DEBUG reg = inl(TRID_REG(card, addr)); - printk("trident: enabled IRQ on channel %d, %s = 0x%08x(addr:%X)\n", - channel, addr==T4D_AINTEN_B? "AINTEN_B":"AINTEN_A",reg,addr); -#endif + TRDBG("trident: enabled IRQ on channel %d, %s = 0x%08x(addr:%X)\n", + channel, addr==T4D_AINTEN_B? "AINTEN_B":"AINTEN_A",reg,addr); +#endif /* DEBUG */ } static void trident_disable_voice_irq(struct trident_card * card, unsigned int channel) @@ -537,9 +583,9 @@ #ifdef DEBUG reg = inl(TRID_REG(card, addr)); - printk("trident: disabled IRQ on channel %d, %s = 0x%08x(addr:%X)\n", - channel, addr==T4D_AINTEN_B? "AINTEN_B":"AINTEN_A",reg,addr); -#endif + TRDBG("trident: disabled IRQ on channel %d, %s = 0x%08x(addr:%X)\n", + channel, addr==T4D_AINTEN_B? "AINTEN_B":"AINTEN_A",reg,addr); +#endif /* DEBUG */ } static void trident_start_voice(struct trident_card * card, unsigned int channel) @@ -550,15 +596,15 @@ #ifdef DEBUG u32 reg; -#endif +#endif /* DEBUG */ outl(mask, TRID_REG(card, addr)); -#ifdef DEBUG +#ifdef DEBUG reg = inl(TRID_REG(card, addr)); - printk("trident: start voice on channel %d, %s = 0x%08x(addr:%X)\n", - channel, addr==T4D_START_B? "START_B":"START_A",reg,addr); -#endif + TRDBG("trident: start voice on channel %d, %s = 0x%08x(addr:%X)\n", + channel, addr==T4D_START_B? "START_B":"START_A",reg,addr); +#endif /* DEBUG */ } static void trident_stop_voice(struct trident_card * card, unsigned int channel) @@ -569,15 +615,15 @@ #ifdef DEBUG u32 reg; -#endif +#endif /* DEBUG */ outl(mask, TRID_REG(card, addr)); #ifdef DEBUG reg = inl(TRID_REG(card, addr)); - printk("trident: stop voice on channel %d, %s = 0x%08x(addr:%X)\n", - channel, addr==T4D_STOP_B? "STOP_B":"STOP_A",reg,addr); -#endif + TRDBG("trident: stop voice on channel %d, %s = 0x%08x(addr:%X)\n", + channel, addr==T4D_STOP_B? "STOP_B":"STOP_A",reg,addr); +#endif /* DEBUG */ } static u32 trident_get_interrupt_mask (struct trident_card * card, unsigned int channel) @@ -594,9 +640,9 @@ #ifdef DEBUG if (reg & mask) - printk("trident: channel %d has interrupt, %s = 0x%08x\n", - channel,reg==T4D_AINT_B? "AINT_B":"AINT_A", reg); -#endif + TRDBG("trident: channel %d has interrupt, %s = 0x%08x\n", + channel,reg==T4D_AINT_B? "AINT_B":"AINT_A", reg); +#endif /* DEBUG */ return (reg & mask) ? TRUE : FALSE; } @@ -612,9 +658,9 @@ #ifdef DEBUG reg = inl(TRID_REG(card, T4D_AINT_B)); - printk("trident: Ack channel %d interrupt, AINT_B = 0x%08x\n", - channel, reg); -#endif + TRDBG("trident: Ack channel %d interrupt, AINT_B = 0x%08x\n", + channel, reg); +#endif /* DEBUG */ } static struct trident_channel * trident_alloc_pcm_channel(struct trident_card *card) @@ -862,9 +908,7 @@ trident_write_voice_regs(state); -#ifdef DEBUG - printk("trident: called trident_set_dac_rate : rate = %d\n", rate); -#endif + TRDBG("trident: called trident_set_dac_rate : rate = %d\n", rate); return rate; } @@ -884,9 +928,8 @@ trident_write_voice_regs(state); -#ifdef DEBUG - printk("trident: called trident_set_adc_rate : rate = %d\n", rate); -#endif + TRDBG("trident: called trident_set_adc_rate : rate = %d\n", rate); + return rate; } @@ -928,11 +971,11 @@ if (dmabuf->fmt & TRIDENT_FMT_STEREO) /* stereo */ channel->control |= CHANNEL_STEREO; -#ifdef DEBUG - printk("trident: trident_play_setup, LBA = 0x%08x, " - "Delta = 0x%08x, ESO = 0x%08x, Control = 0x%08x\n", - channel->lba, channel->delta, channel->eso, channel->control); -#endif + + TRDBG("trident: trident_play_setup, LBA = 0x%08x, " + "Delta = 0x%08x, ESO = 0x%08x, Control = 0x%08x\n", + channel->lba, channel->delta, channel->eso, channel->control); + trident_write_voice_regs(state); } @@ -1014,11 +1057,11 @@ if (dmabuf->fmt & TRIDENT_FMT_STEREO) /* stereo */ channel->control |= CHANNEL_STEREO; -#ifdef DEBUG - printk("trident: trident_rec_setup, LBA = 0x%08x, " - "Delat = 0x%08x, ESO = 0x%08x, Control = 0x%08x\n", - channel->lba, channel->delta, channel->eso, channel->control); -#endif + + TRDBG("trident: trident_rec_setup, LBA = 0x%08x, " + "Delat = 0x%08x, ESO = 0x%08x, Control = 0x%08x\n", + channel->lba, channel->delta, channel->eso, channel->control); + trident_write_voice_regs(state); } @@ -1051,11 +1094,10 @@ return 0; } -#ifdef DEBUG - printk("trident: trident_get_dma_addr: chip reported channel: %d, " - "cso = 0x%04x\n", - dmabuf->channel->num, cso); -#endif + + TRDBG("trident: trident_get_dma_addr: chip reported channel: %d, " + "cso = 0x%04x\n", dmabuf->channel->num, cso); + /* ESO and CSO are in units of Samples, convert to byte offset */ cso <<= sample_shift[dmabuf->fmt]; @@ -1153,27 +1195,18 @@ #define DMABUF_DEFAULTORDER (15-PAGE_SHIFT) #define DMABUF_MINORDER 1 -/* allocate DMA buffer, playback and recording buffer should be allocated seperately */ -static int alloc_dmabuf(struct trident_state *state) +/* alloc a DMA buffer of with a buffer of this order */ +static int alloc_dmabuf(struct dmabuf* dmabuf, struct pci_dev* pci_dev, int order) { - struct dmabuf *dmabuf = &state->dmabuf; void *rawbuf = NULL; - int order; struct page *page, *pend; - /* alloc as big a chunk as we can, FIXME: is this necessary ?? */ - for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) - if ((rawbuf = pci_alloc_consistent(state->card->pci_dev, - PAGE_SIZE << order, - &dmabuf->dma_handle))) - break; - if (!rawbuf) + if (!(rawbuf = pci_alloc_consistent(pci_dev, PAGE_SIZE << order, + &dmabuf->dma_handle))) return -ENOMEM; -#ifdef DEBUG - printk("trident: allocated %ld (order = %d) bytes at %p\n", - PAGE_SIZE << order, order, rawbuf); -#endif + TRDBG("trident: allocated %ld (order = %d) bytes at %p\n", + PAGE_SIZE << order, order, rawbuf); dmabuf->ready = dmabuf->mapped = 0; dmabuf->rawbuf = rawbuf; @@ -1187,21 +1220,37 @@ return 0; } -/* free DMA buffer */ -static void dealloc_dmabuf(struct trident_state *state) +/* allocate the main DMA buffer, playback and recording buffer should be */ +/* allocated seperately */ +static int alloc_main_dmabuf(struct trident_state *state) { struct dmabuf *dmabuf = &state->dmabuf; - struct page *page, *pend; + int order; + int ret = -ENOMEM; + + /* alloc as big a chunk as we can, FIXME: is this necessary ?? */ + for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) { + if (!(ret = alloc_dmabuf(dmabuf, state->card->pci_dev, order))) + return 0; + /* else try again */ + } + return ret; +} +/* deallocate a DMA buffer */ +static void dealloc_dmabuf(struct dmabuf* dmabuf, struct pci_dev* pci_dev) +{ + struct page *page, *pend; + if (dmabuf->rawbuf) { /* undo marking the pages as reserved */ pend = virt_to_page(dmabuf->rawbuf + (PAGE_SIZE << dmabuf->buforder) - 1); for (page = virt_to_page(dmabuf->rawbuf); page <= pend; page++) mem_map_unreserve(page); - pci_free_consistent(state->card->pci_dev, PAGE_SIZE << dmabuf->buforder, + pci_free_consistent(pci_dev, PAGE_SIZE << dmabuf->buforder, dmabuf->rawbuf, dmabuf->dma_handle); + dmabuf->rawbuf = NULL; } - dmabuf->rawbuf = NULL; dmabuf->mapped = dmabuf->ready = 0; } @@ -1213,16 +1262,16 @@ unsigned bufsize, dma_nums; unsigned long flags; int ret, i, order; - struct page *page, *pend; lock_set_fmt(state); if (state->chans_num == 6) dma_nums = 5; - else dma_nums = 1; + else + dma_nums = 1; for (i = 0; i < dma_nums; i++) { if (i > 0) { - s = state->other_states[i - 1]; + s = state->other_states[i - 1]; dmabuf = &s->dmabuf; dmabuf->fmt = state->dmabuf.fmt; dmabuf->rate = state->dmabuf.rate; @@ -1236,35 +1285,25 @@ /* allocate DMA buffer if not allocated yet */ if (!dmabuf->rawbuf) { if (i == 0) { - if ((ret = alloc_dmabuf(state))) { + if ((ret = alloc_main_dmabuf(state))) { unlock_set_fmt(state); return ret; } - } - else { + } else { + ret = -ENOMEM; if ((order = state->dmabuf.buforder - 1) >= DMABUF_MINORDER) { - dmabuf->rawbuf = pci_alloc_consistent(state->card->pci_dev, - PAGE_SIZE << order, - &dmabuf->dma_handle); + ret = alloc_dmabuf(dmabuf, state->card->pci_dev, order); } - if (!dmabuf->rawbuf) { - free_pages((unsigned long)state->dmabuf.rawbuf, state->dmabuf.buforder); - state->dmabuf.rawbuf = NULL; - i-=2; - for (; i >= 0; i--) { - pci_free_consistent(state->card->pci_dev, - PAGE_SIZE << state->other_states[i]->dmabuf.buforder, - state->other_states[i]->dmabuf.rawbuf, - state->other_states[i]->dmabuf.dma_handle); - } + if (ret) { + /* release the main DMA buffer */ + dealloc_dmabuf(&state->dmabuf, state->card->pci_dev); + /* release the auxiliary DMA buffers */ + for (i-=2; i >= 0; i--) + dealloc_dmabuf(&state->other_states[i]->dmabuf, + state->card->pci_dev); unlock_set_fmt(state); - return -ENOMEM; + return ret; } - dmabuf->ready = dmabuf->mapped = 0; - dmabuf->buforder = order; - pend = virt_to_page(dmabuf->rawbuf + (PAGE_SIZE << order) - 1); - for (page = virt_to_page(dmabuf->rawbuf); page <= pend; page++) - mem_map_reserve(page); } } /* FIXME: figure out all this OSS fragment stuff */ @@ -1294,22 +1333,20 @@ dmabuf->dmasize); spin_lock_irqsave(&s->card->lock, flags); - if (rec) { + if (rec) trident_rec_setup(s); - } else { + else trident_play_setup(s); - } + spin_unlock_irqrestore(&s->card->lock, flags); /* set the ready flag for the dma buffer */ dmabuf->ready = 1; -#ifdef DEBUG - printk("trident: prog_dmabuf(%d), sample rate = %d, format = %d, numfrag = %d, " - "fragsize = %d dmasize = %d\n", - dmabuf->channel->num, dmabuf->rate, dmabuf->fmt, dmabuf->numfrag, - dmabuf->fragsize, dmabuf->dmasize); -#endif + TRDBG("trident: prog_dmabuf(%d), sample rate = %d, format = %d, numfrag = %d, " + "fragsize = %d dmasize = %d\n", + dmabuf->channel->num, dmabuf->rate, dmabuf->fmt, dmabuf->numfrag, + dmabuf->fragsize, dmabuf->dmasize); } unlock_set_fmt(state); return 0; @@ -1533,19 +1570,21 @@ { int i; struct trident_state *state; + unsigned int channel; /* Update the pointers for all channels we are running. */ /* FIXME: should read interrupt status only once */ for (i = 0; i < NR_HW_CH; i++) { - if (trident_check_channel_interrupt(card, 63 - i)) { - trident_ack_channel_interrupt(card, 63 - i); + channel = 63 - i; + if (trident_check_channel_interrupt(card, channel)) { + trident_ack_channel_interrupt(card, channel); if ((state = card->states[i]) != NULL) { trident_update_ptr(state); } else { - printk("trident: spurious channel irq %d.\n", - 63 - i); - trident_stop_voice(card, 63 - i); - trident_disable_voice_irq(card, 63 - i); + printk(KERN_WARNING "trident: spurious channel " + "irq %d.\n", channel); + trident_stop_voice(card, channel); + trident_disable_voice_irq(card, channel); } } } @@ -1653,29 +1692,29 @@ { int i,irq_status; struct trident_state *state; + unsigned int channel; /* Update the pointers for all channels we are running. */ /* FIXED: read interrupt status only once */ irq_status=inl(TRID_REG(card, T4D_AINT_A) ); -#ifdef DEBUG - printk("cyber_address_interrupt: irq_status 0x%X\n",irq_status); -#endif - for (i = 0; i < NR_HW_CH; i++) { - if (irq_status & ( 1 << (31 - i)) ) { + TRDBG("cyber_address_interrupt: irq_status 0x%X\n",irq_status); + + for (i = 0; i < NR_HW_CH; i++) { + channel = 31 - i; + if (irq_status & ( 1 << channel) ) { /* clear bit by writing a 1, zeroes are ignored */ - outl( (1 <<(31-i)), TRID_REG(card, T4D_AINT_A)); + outl( (1 << channel), TRID_REG(card, T4D_AINT_A)); -#ifdef DEBUG - printk("cyber_interrupt: channel %d\n", 31-i); -#endif + TRDBG("cyber_interrupt: channel %d\n", channel); + if ((state = card->states[i]) != NULL) { trident_update_ptr(state); } else { - printk("cyber5050: spurious channel irq %d.\n", - 31 - i); - trident_stop_voice(card, 31 - i); - trident_disable_voice_irq(card, 31 - i); + printk(KERN_WARNING "cyber5050: spurious " + "channel irq %d.\n", channel); + trident_stop_voice(card, channel); + trident_disable_voice_irq(card, channel); } } } @@ -1690,9 +1729,7 @@ spin_lock(&card->lock); event = inl(TRID_REG(card, T4D_MISCINT)); -#ifdef DEBUG - printk("trident: trident_interrupt called, MISCINT = 0x%08x\n", event); -#endif + TRDBG("trident: trident_interrupt called, MISCINT = 0x%08x\n", event); if (event & ADDRESS_IRQ) { card->address_interrupt(card); @@ -1730,9 +1767,7 @@ unsigned swptr; int cnt; -#ifdef DEBUG - printk("trident: trident_read called, count = %d\n", count); -#endif + TRDBG("trident: trident_read called, count = %d\n", count); VALIDATE_STATE(state); if (ppos != &file->f_pos) @@ -1786,12 +1821,11 @@ which results in a (potential) buffer overrun. And worse, there is NOTHING we can do to prevent it. */ if (!interruptible_sleep_on_timeout(&dmabuf->wait, tmo)) { -#ifdef DEBUG - printk(KERN_ERR "trident: recording schedule timeout, " - "dmasz %u fragsz %u count %i hwptr %u swptr %u\n", - dmabuf->dmasize, dmabuf->fragsize, dmabuf->count, - dmabuf->hwptr, dmabuf->swptr); -#endif + TRDBG(KERN_ERR "trident: recording schedule timeout, " + "dmasz %u fragsz %u count %i hwptr %u swptr %u\n", + dmabuf->dmasize, dmabuf->fragsize, dmabuf->count, + dmabuf->hwptr, dmabuf->swptr); + /* a buffer overrun, we delay the recovery until next time the while loop begin and we REALLY have space to record */ } @@ -1845,9 +1879,8 @@ unsigned int state_cnt; unsigned int copy_count; -#ifdef DEBUG - printk("trident: trident_write called, count = %d\n", count); -#endif + TRDBG("trident: trident_write called, count = %d\n", count); + VALIDATE_STATE(state); if (ppos != &file->f_pos) return -ESPIPE; @@ -1915,12 +1948,11 @@ which results in a (potential) buffer underrun. And worse, there is NOTHING we can do to prevent it. */ if (!interruptible_sleep_on_timeout(&dmabuf->wait, tmo)) { -#ifdef DEBUG - printk(KERN_ERR "trident: playback schedule timeout, " - "dmasz %u fragsz %u count %i hwptr %u swptr %u\n", - dmabuf->dmasize, dmabuf->fragsize, dmabuf->count, - dmabuf->hwptr, dmabuf->swptr); -#endif + TRDBG(KERN_ERR "trident: playback schedule timeout, " + "dmasz %u fragsz %u count %i hwptr %u swptr %u\n", + dmabuf->dmasize, dmabuf->fragsize, dmabuf->count, + dmabuf->hwptr, dmabuf->swptr); + /* a buffer underrun, we delay the recovery until next time the while loop begin and we REALLY have data to play */ } @@ -2099,10 +2131,8 @@ VALIDATE_STATE(state); mapped = ((file->f_mode & FMODE_WRITE) && dmabuf->mapped) || ((file->f_mode & FMODE_READ) && dmabuf->mapped); -#ifdef DEBUG - printk("trident: trident_ioctl, command = %2d, arg = 0x%08x\n", - _IOC_NR(cmd), arg ? *(int *)arg : 0); -#endif + TRDBG("trident: trident_ioctl, command = %2d, arg = 0x%08x\n", + _IOC_NR(cmd), arg ? *(int *)arg : 0); switch (cmd) { @@ -2262,6 +2292,7 @@ { printk(KERN_ERR "trident: Record is working on the card!\n"); ret = -EBUSY; + unlock_set_fmt(state); break; } @@ -2665,10 +2696,8 @@ state->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); up(&card->open_sem); -#ifdef DEBUG - printk(KERN_ERR "trident: open virtual channel %d, hard channel %d\n", + TRDBG("trident: open virtual channel %d, hard channel %d\n", state->virt, dmabuf->channel->num); -#endif return 0; } @@ -2678,7 +2707,6 @@ struct trident_state *state = (struct trident_state *)file->private_data; struct trident_card *card; struct dmabuf *dmabuf; - unsigned long flags; lock_kernel(); card = state->card; @@ -2690,20 +2718,15 @@ drain_dac(state, file->f_flags & O_NONBLOCK); } -#ifdef DEBUG - printk(KERN_ERR "trident: closing virtual channel %d, hard channel %d\n", - state->virt, dmabuf->channel->num); -#endif + TRDBG("trident: closing virtual channel %d, hard channel %d\n", + state->virt, dmabuf->channel->num); /* stop DMA state machine and free DMA buffers/channels */ down(&card->open_sem); if (file->f_mode & FMODE_WRITE) { stop_dac(state); - lock_set_fmt(state); - - unlock_set_fmt(state); - dealloc_dmabuf(state); + dealloc_dmabuf(&state->dmabuf, state->card->pci_dev); state->card->free_pcm_channel(state->card, dmabuf->channel->num); /* Added by Matt Wu */ @@ -2719,7 +2742,7 @@ } if (file->f_mode & FMODE_READ) { stop_adc(state); - dealloc_dmabuf(state); + dealloc_dmabuf(&state->dmabuf, state->card->pci_dev); state->card->free_pcm_channel(state->card, dmabuf->channel->num); /* Added by Matt Wu */ @@ -2868,62 +2891,74 @@ return ((u16) (data >> 16)); } -/* Write AC97 codec registers for ALi*/ -static void ali_ac97_set(struct trident_card *card, int secondary, u8 reg, u16 val) +/* rewrite ac97 read and write mixer register by hulei for ALI*/ +static int acquirecodecaccess(struct trident_card *card) { - unsigned int address, mask; - unsigned int wCount1 = 0xffff; - unsigned int wCount2= 0xffff; - unsigned long chk1, chk2; - unsigned long flags; - u32 data; - - data = ((u32) val) << 16; - - if(!card) - BUG(); - - address = ALI_AC97_WRITE; - mask = ALI_AC97_WRITE_ACTION | ALI_AC97_AUDIO_BUSY; - if (secondary) - mask |= ALI_AC97_SECONDARY; - if (card->revision == ALI_5451_V02) - mask |= ALI_AC97_WRITE_MIXER_REGISTER; + u16 wsemamask=0x6000; /* bit 14..13 */ + u16 wsemabits; + u16 wcontrol ; + int block = 0; + int ncount = 25; + while (1) { + wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE)); + wsemabits = wcontrol & wsemamask; - spin_lock_irqsave(&card->lock, flags); - while (wCount1--) { - if ((inw(TRID_REG(card, address)) & ALI_AC97_BUSY_WRITE) == 0) { - data |= (mask | (reg & AC97_REG_ADDR)); - - chk1 = inl(TRID_REG(card, ALI_STIMER)); - chk2 = inl(TRID_REG(card, ALI_STIMER)); - while (wCount2-- && (chk1 == chk2)) - chk2 = inl(TRID_REG(card, ALI_STIMER)); - if (wCount2 == 0) { - spin_unlock_irqrestore(&card->lock, flags); - return; - } - outl(data, TRID_REG(card, address)); //write! - spin_unlock_irqrestore(&card->lock, flags); - return; //success + if (wsemabits==0x4000) + return 1; /* 0x4000 is audio ,then success */ + if (ncount-- < 0) + break; + if (wsemabits == 0) + { + unlock: + outl(((u32)(wcontrol & 0x1eff)|0x00004000), TRID_REG(card, ALI_AC97_WRITE)); + continue; } - inw(TRID_REG(card, address)); //wait for a read cycle + udelay(20); + } + if(!block) + { + TRDBG("accesscodecsemaphore: try unlock\n"); + block = 1; + goto unlock; } + printk(KERN_ERR "accesscodecsemaphore: fail\n"); + return 0; +} - printk(KERN_ERR "ali: AC97 CODEC write timed out.\n"); - spin_unlock_irqrestore(&card->lock, flags); - return; +static void releasecodecaccess(struct trident_card *card) +{ + unsigned long wcontrol; + wcontrol = inl(TRID_REG(card, ALI_AC97_WRITE)); + outl((wcontrol & 0xffff1eff), TRID_REG(card, ALI_AC97_WRITE)); +} + +static int waitforstimertick(struct trident_card *card) +{ + unsigned long chk1, chk2; + unsigned int wcount = 0xffff; + chk1 = inl(TRID_REG(card, ALI_STIMER)); + + while(1) { + chk2 = inl(TRID_REG(card, ALI_STIMER)); + if( (wcount > 0) && chk1 != chk2) + return 1; + if(wcount <= 0) + break; + udelay(50); + } + + printk(KERN_NOTICE "waitforstimertick :BIT_CLK is dead\n"); + return 0; } /* Read AC97 codec registers for ALi*/ static u16 ali_ac97_get(struct trident_card *card, int secondary, u8 reg) { unsigned int address, mask; - unsigned int wCount1 = 0xffff; - unsigned int wCount2= 0xffff; - unsigned long chk1, chk2; - unsigned long flags; + unsigned int ncount; + unsigned long aud_reg; u32 data; + u16 wcontrol; if(!card) BUG(); @@ -2935,37 +2970,102 @@ mask = ALI_AC97_READ_ACTION | ALI_AC97_AUDIO_BUSY; if (secondary) mask |= ALI_AC97_SECONDARY; + + if (!acquirecodecaccess(card)) + printk(KERN_ERR "access codec fail\n"); + + wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE)); + wcontrol &= 0xfe00; + wcontrol |= (0x8000|reg); + outw(wcontrol,TRID_REG(card, ALI_AC97_WRITE)); - spin_lock_irqsave(&card->lock, flags); data = (mask | (reg & AC97_REG_ADDR)); - while (wCount1--) { - if ((inw(TRID_REG(card, address)) & ALI_AC97_BUSY_READ) == 0) { - chk1 = inl(TRID_REG(card, ALI_STIMER)); - chk2 = inl(TRID_REG(card, ALI_STIMER)); - while (wCount2-- && (chk1 == chk2)) - chk2 = inl(TRID_REG(card, ALI_STIMER)); - if (wCount2 == 0) { - printk(KERN_ERR "ali: AC97 CODEC read timed out.\n"); - spin_unlock_irqrestore(&card->lock, flags); - return 0; - } - outl(data, TRID_REG(card, address)); //read! - wCount2 = 0xffff; - while (wCount2--) { - if ((inw(TRID_REG(card, address)) & ALI_AC97_BUSY_READ) == 0) { - data = inl(TRID_REG(card, address)); - spin_unlock_irqrestore(&card->lock, flags); - return ((u16) (data >> 16)); - } - } + + if(!waitforstimertick(card)) { + printk(KERN_ERR "BIT_CLOCK is dead\n"); + goto releasecodec; + } + + udelay(20); + + ncount=10; + + while(1) { + if ((inw(TRID_REG(card,ALI_AC97_WRITE)) & ALI_AC97_BUSY_READ) != 0) + break; + if(ncount <=0) + break; + if(ncount--==1) { + TRDBG("ali_ac97_read :try clear busy flag\n"); + aud_reg = inl(TRID_REG(card, ALI_AC97_WRITE)); + outl((aud_reg & 0xffff7fff), TRID_REG(card, ALI_AC97_WRITE)); } - inw(TRID_REG(card, address)); //wait a read cycle + udelay(10); } - spin_unlock_irqrestore(&card->lock, flags); + + data = inl(TRID_REG(card, address)); + + return ((u16) (data >> 16)); + + releasecodec: + releasecodecaccess(card); printk(KERN_ERR "ali: AC97 CODEC read timed out.\n"); return 0; } + +/* Write AC97 codec registers for hulei*/ +static void ali_ac97_set(struct trident_card *card, int secondary, u8 reg, u16 val) +{ + unsigned int address, mask; + unsigned int ncount; + u32 data; + u16 wcontrol; + + data = ((u32) val) << 16; + + if(!card) + BUG(); + + address = ALI_AC97_WRITE; + mask = ALI_AC97_WRITE_ACTION | ALI_AC97_AUDIO_BUSY; + if (secondary) + mask |= ALI_AC97_SECONDARY; + if (card->revision == ALI_5451_V02) + mask |= ALI_AC97_WRITE_MIXER_REGISTER; + + if (!acquirecodecaccess(card)) + printk(KERN_ERR "access codec fail\n"); + + wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE)); + wcontrol &= 0xff00; + wcontrol |= (0x8100|reg);/* bit 8=1: (ali1535 )reserved /ali1535+ write */ + outl(( data |wcontrol), TRID_REG(card,ALI_AC97_WRITE )); + + if(!waitforstimertick(card)) { + printk(KERN_ERR "BIT_CLOCK is dead\n"); + goto releasecodec; + } + + ncount = 10; + while(1) { + wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE)); + if(!wcontrol & 0x8000) + break; + if(ncount <= 0) + break; + if(ncount-- == 1) { + TRDBG("ali_ac97_set :try clear busy flag!!\n"); + outw(wcontrol & 0x7fff, TRID_REG(card, ALI_AC97_WRITE)); + } + udelay(10); + } + + releasecodec: + releasecodecaccess(card); + return; +} + static void ali_enable_special_channel(struct trident_state *stat) { struct trident_card *card = stat->card; @@ -3463,7 +3563,7 @@ static int trident_suspend(struct pci_dev *dev, u32 unused) { - struct trident_card *card = (struct trident_card *) dev; + struct trident_card *card = pci_get_drvdata(dev); if(card->pci_id == PCI_DEVICE_ID_ALI_5451) { ali_save_regs(card); @@ -3473,7 +3573,7 @@ static int trident_resume(struct pci_dev *dev) { - struct trident_card *card = (struct trident_card *) dev; + struct trident_card *card = pci_get_drvdata(dev); if(card->pci_id == PCI_DEVICE_ID_ALI_5451) { ali_restore_regs(card); @@ -3600,7 +3700,10 @@ depend on a master state's DMA, and changing the counters of the master state DMA is protected by a spinlock. */ -static int ali_write_5_1(struct trident_state *state, const char *buf, int cnt_for_multi_channel, unsigned int *copy_count, unsigned int *state_cnt) +static int ali_write_5_1(struct trident_state *state, + const char *buf, int cnt_for_multi_channel, + unsigned int *copy_count, + unsigned int *state_cnt) { struct dmabuf *dmabuf = &state->dmabuf; @@ -3706,7 +3809,7 @@ other_states_count = state->chans_num - 2; /* except PCM L/R channels*/ for ( i = 0; i < other_states_count; i++) { s = state->other_states[i]; - dealloc_dmabuf(s); + dealloc_dmabuf(&s->dmabuf, card->pci_dev); ali_disable_special_channel(s->card, s->dmabuf.channel->num); state->card->free_pcm_channel(s->card, s->dmabuf.channel->num); card->states[s->virt] = NULL; @@ -3714,7 +3817,6 @@ } } -#ifdef CONFIG_PROC_FS struct proc_dir_entry *res; static int ali_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) { @@ -3752,7 +3854,6 @@ return count; } -#endif /* OSS /dev/mixer file operation methods */ static int trident_open_mixdev(struct inode *inode, struct file *file) @@ -4030,13 +4131,11 @@ /* ALi SPDIF OUT function */ if(card->revision == ALI_5451_V02) { ali_setup_spdif_out(card, ALI_PCM_TO_SPDIF_OUT); -#ifdef CONFIG_PROC_FS res = create_proc_entry("ALi5451", 0, NULL); if (res) { res->write_proc = ali_write_proc; res->data = card; } -#endif } /* Add H/W Volume Control By Matt Wu Jul. 06, 2001 */ @@ -4129,7 +4228,7 @@ ali_ac97_set(card, 0, AC97_POWER_CONTROL, ac97_data | ALI_EAPD_POWER_DOWN); } } -#endif +#endif /* CONFIG_ALPHA_NAUTILUS || CONFIG_ALPHA_GENERIC */ /* edited by HMSEO for GT sound*/ } rc = 0; @@ -4143,12 +4242,10 @@ out_free_irq: free_irq(card->irq, card); out_proc_fs: -#ifdef CONFIG_PROC_FS if (res) { remove_proc_entry("ALi5451", NULL); res = NULL; } -#endif kfree(card); devs = NULL; out_release_region: @@ -4173,9 +4270,7 @@ ali_setup_spdif_out(card, ALI_PCM_TO_SPDIF_OUT); ali_disable_special_channel(card, ALI_SPDIF_OUT_CHANNEL); ali_disable_spdif_in(card); -#ifdef CONFIG_PROC_FS remove_proc_entry("ALi5451", NULL); -#endif } /* Kill interrupts, and SP/DIF */ @@ -4219,8 +4314,9 @@ if (!pci_present()) /* No PCI bus in this machine! */ return -ENODEV; - printk(KERN_INFO "Trident 4DWave/SiS 7018/ALi 5451,Tvia CyberPro 5050 PCI Audio, version " - DRIVER_VERSION ", " __TIME__ " " __DATE__ "\n"); + printk(KERN_INFO "Trident 4DWave/SiS 7018/ALi 5451,Tvia CyberPro " + "5050 PCI Audio, version " DRIVER_VERSION ", " + __TIME__ " " __DATE__ "\n"); if (!pci_register_driver(&trident_pci_driver)) { pci_unregister_driver(&trident_pci_driver); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/sound/trident.h linux.19rc3-ac4/drivers/sound/trident.h --- linux.19rc3/drivers/sound/trident.h 2002-07-29 12:54:49.000000000 +0100 +++ linux.19rc3-ac4/drivers/sound/trident.h 2002-07-29 13:58:44.000000000 +0100 @@ -358,5 +358,16 @@ return r; } -#endif /* __TRID4DWAVE_H */ +#ifdef DEBUG + +#define TRDBG(msg, args...) do { \ + printk(KERN_DEBUG msg , ##args ); \ +} while (0) + +#else /* !defined(DEBUG) */ +#define TRDBG(msg, args...) do { } while (0) + +#endif /* DEBUG */ + +#endif /* __TRID4DWAVE_H */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/usb/catc.c linux.19rc3-ac4/drivers/usb/catc.c --- linux.19rc3/drivers/usb/catc.c 2002-07-29 12:54:49.000000000 +0100 +++ linux.19rc3-ac4/drivers/usb/catc.c 2002-07-29 13:58:44.000000000 +0100 @@ -673,9 +673,16 @@ } catc = kmalloc(sizeof(struct catc), GFP_KERNEL); + if (!catc) + return NULL; + memset(catc, 0, sizeof(struct catc)); netdev = init_etherdev(0, 0); + if (!netdev) { + kfree(catc); + return NULL; + } netdev->open = catc_open; netdev->hard_start_xmit = catc_hard_start_xmit; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/usb/dabusb.c linux.19rc3-ac4/drivers/usb/dabusb.c --- linux.19rc3/drivers/usb/dabusb.c 2002-07-29 12:50:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/usb/dabusb.c 2002-07-29 13:58:44.000000000 +0100 @@ -605,6 +605,7 @@ } if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) { err("set_interface failed"); + up(&s->mutex); return -EINVAL; } s->opened = 1; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/usb/devices.c linux.19rc3-ac4/drivers/usb/devices.c --- linux.19rc3/drivers/usb/devices.c 2002-07-29 12:54:49.000000000 +0100 +++ linux.19rc3-ac4/drivers/usb/devices.c 2002-07-29 13:58:44.000000000 +0100 @@ -573,8 +573,10 @@ bus = list_entry(buslist, struct usb_bus, bus_list); /* recurse through all children of the root hub */ ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, bus->root_hub, bus, 0, 0, 0); - if (ret < 0) + if (ret < 0) { + up(&usb_bus_list_lock); return ret; + } total_written += ret; } up (&usb_bus_list_lock); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/usb/devio.c linux.19rc3-ac4/drivers/usb/devio.c --- linux.19rc3/drivers/usb/devio.c 2002-07-29 12:54:49.000000000 +0100 +++ linux.19rc3-ac4/drivers/usb/devio.c 2002-07-29 13:58:44.000000000 +0100 @@ -138,7 +138,7 @@ return ret; } -extern inline unsigned int ld2(unsigned int x) +static inline unsigned int ld2(unsigned int x) { unsigned int r = 0; @@ -188,7 +188,7 @@ kfree(as); } -extern __inline__ void async_newpending(struct async *as) +static inline void async_newpending(struct async *as) { struct dev_state *ps = as->ps; unsigned long flags; @@ -198,7 +198,7 @@ spin_unlock_irqrestore(&ps->lock, flags); } -extern __inline__ void async_removepending(struct async *as) +static inline void async_removepending(struct async *as) { struct dev_state *ps = as->ps; unsigned long flags; @@ -209,7 +209,7 @@ spin_unlock_irqrestore(&ps->lock, flags); } -extern __inline__ struct async *async_getcompleted(struct dev_state *ps) +static inline struct async *async_getcompleted(struct dev_state *ps) { unsigned long flags; struct async *as = NULL; @@ -224,7 +224,7 @@ return as; } -extern __inline__ struct async *async_getpending(struct dev_state *ps, void *userurb) +static inline struct async *async_getpending(struct dev_state *ps, void *userurb) { unsigned long flags; struct async *as; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/usb/kaweth.c linux.19rc3-ac4/drivers/usb/kaweth.c --- linux.19rc3/drivers/usb/kaweth.c 2002-07-29 12:54:49.000000000 +0100 +++ linux.19rc3-ac4/drivers/usb/kaweth.c 2002-07-29 15:24:04.000000000 +0100 @@ -143,6 +143,7 @@ { USB_DEVICE(0x10bd, 0x1427) }, /* ASANTE USB To Ethernet Adapter */ { USB_DEVICE(0x1342, 0x0204) }, /* Mobility USB-Ethernet Adapter */ { USB_DEVICE(0x13d2, 0x0400) }, /* Shark Pocket Adapter */ + { USB_DEVICE(0x1485, 0x0001) }, /* Silicom USB-Ethernet Adapter */ { USB_DEVICE(0x1645, 0x0005) }, /* Entrega E45 */ { USB_DEVICE(0x1645, 0x0008) }, /* Entrega USB Ethernet Adapter */ { USB_DEVICE(0x1645, 0x8005) }, /* PortGear Ethernet Adapter */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/usb/ov511.c linux.19rc3-ac4/drivers/usb/ov511.c --- linux.19rc3/drivers/usb/ov511.c 2002-07-29 12:54:49.000000000 +0100 +++ linux.19rc3-ac4/drivers/usb/ov511.c 2002-07-29 13:58:44.000000000 +0100 @@ -377,55 +377,18 @@ * * 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 - * - * So I copied it again for the OV511 driver -claudio **********************************************************************/ -/* 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 = (unsigned long) - page_address(pte_page(pte)); - ret |= (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. + * This is used when initializing the contents of the area. */ static inline unsigned long kvirt_to_pa(unsigned long adr) { - unsigned long va, kva, ret; + unsigned long kva, ret; - va = VMALLOC_VMADDR(adr); - kva = uvirt_to_kva(pgd_offset_k(va), va); + kva = (unsigned long) page_address(vmalloc_to_page((void *)adr)); + kva |= adr & (PAGE_SIZE-1); /* restore the offset */ ret = __pa(kva); return ret; } @@ -434,12 +397,9 @@ rvmalloc(unsigned long size) { void *mem; - unsigned long adr, page; - - /* Round it off to PAGE_SIZE */ - size += (PAGE_SIZE - 1); - size &= ~(PAGE_SIZE - 1); + unsigned long adr; + size = PAGE_ALIGN(size); mem = vmalloc_32(size); if (!mem) return NULL; @@ -447,13 +407,9 @@ memset(mem, 0, size); /* Clear the ram out, no junk to the user */ adr = (unsigned long) mem; while (size > 0) { - page = kvirt_to_pa(adr); - mem_map_reserve(virt_to_page(__va(page))); + mem_map_reserve(vmalloc_to_page((void *)adr)); adr += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; + size -= PAGE_SIZE; } return mem; @@ -462,23 +418,16 @@ static void rvfree(void *mem, unsigned long size) { - unsigned long adr, page; + unsigned long adr; 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(virt_to_page(__va(page))); + adr = (unsigned long) mem; + while ((long) size > 0) { + mem_map_unreserve(vmalloc_to_page((void *)adr)); adr += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; + size -= PAGE_SIZE; } vfree(mem); } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/usb/printer.c linux.19rc3-ac4/drivers/usb/printer.c --- linux.19rc3/drivers/usb/printer.c 2002-07-29 12:54:49.000000000 +0100 +++ linux.19rc3-ac4/drivers/usb/printer.c 2002-07-29 13:58:44.000000000 +0100 @@ -616,7 +616,11 @@ (count - writecount) : USBLP_BUF_SIZE; if (copy_from_user(usblp->writeurb.transfer_buffer, buffer + writecount, - usblp->writeurb.transfer_buffer_length)) return -EFAULT; + usblp->writeurb.transfer_buffer_length)) + { + up(&usblp->sem); + return writecount?writecount:-EFAULT; + } usblp->writeurb.dev = usblp->dev; usb_submit_urb(&usblp->writeurb); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/usb/pwc-if.c linux.19rc3-ac4/drivers/usb/pwc-if.c --- linux.19rc3/drivers/usb/pwc-if.c 2002-07-29 12:54:49.000000000 +0100 +++ linux.19rc3-ac4/drivers/usb/pwc-if.c 2002-07-29 13:58:44.000000000 +0100 @@ -179,60 +179,25 @@ /***************************************************************************/ /* Private functions */ -/* Memory management functions, nicked from cpia.c, which nicked them from - bttv.c. So far, I've counted duplication of this code 6 times - (bttv, cpia, ibmcam, ov511, pwc, ieee1394). - */ - -/* 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 = (unsigned long) page_address(pte_page(pte)); - ret |= (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. + * This is used when initializing the contents of the area. */ static inline unsigned long kvirt_to_pa(unsigned long adr) { - unsigned long va, kva, ret; + unsigned long kva, ret; - va = VMALLOC_VMADDR(adr); - kva = uvirt_to_kva(pgd_offset_k(va), va); + kva = (unsigned long) page_address(vmalloc_to_page((void *)adr)); + kva |= adr & (PAGE_SIZE-1); /* restore the offset */ ret = __pa(kva); return ret; } -static void * rvmalloc(signed long size) +static void * rvmalloc(unsigned long size) { void * mem; - unsigned long adr, page; + unsigned long adr; - /* Round it off to PAGE_SIZE */ - size += (PAGE_SIZE - 1); - size &= ~(PAGE_SIZE - 1); - + size=PAGE_ALIGN(size); mem=vmalloc_32(size); if (mem) { @@ -240,8 +205,7 @@ adr=(unsigned long) mem; while (size > 0) { - page = kvirt_to_pa(adr); - mem_map_reserve(virt_to_page(__va(page))); + mem_map_reserve(vmalloc_to_page((void *)adr)); adr+=PAGE_SIZE; size-=PAGE_SIZE; } @@ -249,20 +213,16 @@ return mem; } -static void rvfree(void * mem, signed long size) +static void rvfree(void * mem, unsigned long size) { - unsigned long adr, page; - - /* Round it off to PAGE_SIZE */ - size += (PAGE_SIZE - 1); - size &= ~(PAGE_SIZE - 1); + unsigned long adr; + if (mem) { adr=(unsigned long) mem; - while (size > 0) + while ((long) size > 0) { - page = kvirt_to_pa(adr); - mem_map_unreserve(virt_to_page(__va(page))); + mem_map_unreserve(vmalloc_to_page((void *)adr)); adr+=PAGE_SIZE; size-=PAGE_SIZE; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/usb/rio500.c linux.19rc3-ac4/drivers/usb/rio500.c --- linux.19rc3/drivers/usb/rio500.c 2002-07-29 12:50:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/usb/rio500.c 2002-07-29 13:58:44.000000000 +0100 @@ -141,7 +141,7 @@ retval = -EFAULT; goto err_out; } - if (rio_cmd.length > PAGE_SIZE) { + if (rio_cmd.length < 0 || rio_cmd.length > PAGE_SIZE) { retval = -EINVAL; goto err_out; } @@ -211,7 +211,7 @@ retval = -EFAULT; goto err_out; } - if (rio_cmd.length > PAGE_SIZE) { + if (rio_cmd.length < 0 || rio_cmd.length > PAGE_SIZE) { retval = -EINVAL; goto err_out; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/usb/scanner.c linux.19rc3-ac4/drivers/usb/scanner.c --- linux.19rc3/drivers/usb/scanner.c 2002-07-29 12:50:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/usb/scanner.c 2002-07-29 13:58:44.000000000 +0100 @@ -1,13 +1,13 @@ /* -*- linux-c -*- */ /* - * Driver for USB Scanners (linux-2.4.12) + * Driver for USB Scanners (linux-2.4.18) * - * Copyright (C) 1999, 2000, 2001 David E. Nelson + * Copyright (C) 1999, 2000, 2001, 2002 David E. Nelson * * Portions may be copyright Brad Keryan and Michael Gee. * - * David E. Nelson (dnelson@jump.net) + * Brian Beattie * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -300,11 +300,24 @@ * Frank Zago and * Oliver Neukum <520047054719-0001@t-online.de> for reviewing/testing. * + * 0.4.8 5/30/2002 + * - Added Mustek BearPaw 2400 TA. Thanks to Sergey + * Vlasov . + * - Added Mustek 1200UB Plus and Mustek BearPaw 1200 CU ID's. These use + * the Grandtech GT-6801 chip. Thanks to Henning + * Meier-Geinitz . + * - Increased Epson timeout to 60 secs as requested from + * Karl Heinz Kremer . + * - Changed maintainership from David E. Nelson to Brian + * Beattie . + * * TODO + * - Remove the 2/3 endpoint limitation * - Performance * - Select/poll methods * - More testing * - Proper registry/assignment for LM9830 ioctl's + * - More general usage ioctl's * * * Thanks to: @@ -320,6 +333,8 @@ * - All the folks who chimed in with reports and suggestions. * - All the developers that are working on USB SANE backends or other * applications to use USB scanners. + * - Thanks to Greg KH for setting up Brian Beattie + * to be the new USB Scanner maintainer. * * Performance: * @@ -1017,7 +1032,7 @@ switch (dev->descriptor.idVendor) { /* Scanner specific read timeout parameters */ case 0x04b8: /* Seiko/Epson */ - scn->rd_nak_timeout = HZ * 40; + scn->rd_nak_timeout = HZ * 60; break; case 0x055f: /* Mustek */ case 0x0400: /* Another Mustek */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/usb/scanner.h linux.19rc3-ac4/drivers/usb/scanner.h --- linux.19rc3/drivers/usb/scanner.h 2002-07-29 12:50:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/usb/scanner.h 2002-07-29 17:29:11.000000000 +0100 @@ -1,9 +1,9 @@ /* - * Driver for USB Scanners (linux-2.4.12) + * Driver for USB Scanners (linux-2.4.18) * - * Copyright (C) 1999, 2000, 2001 David E. Nelson + * Copyright (C) 1999, 2000, 2001, 2002 David E. Nelson * - * David E. Nelson (dnelson@jump.net) + * Brian Beattie * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -48,7 +48,7 @@ static __s32 vendor=-1, product=-1, read_timeout=0; -MODULE_AUTHOR("David E. Nelson, dnelson@jump.net, http://www.jump.net/~dnelson"); +MODULE_AUTHOR("Brian Beattie, beattie@beattie-home.net"); MODULE_DESCRIPTION(DRIVER_DESC" "DRIVER_VERSION); MODULE_LICENSE("GPL"); @@ -141,6 +141,8 @@ { USB_DEVICE(0x0400, 0x1001) }, /* BearPaw 2400 */ { USB_DEVICE(0x055f, 0x0008) }, /* 1200 CU Plus */ { USB_DEVICE(0x0ff5, 0x0010) }, /* BearPaw 1200F */ + { USB_DEVICE(0x055f, 0x0218) }, /* BearPaw 2400 TA */ + { USB_DEVICE(0x05d8, 0x4002) }, /* 1200 CU and 1200 UB Plus */ /* Plustek */ { USB_DEVICE(0x07b3, 0x0017) }, /* OpticPro UT12 */ { USB_DEVICE(0x07b3, 0x0011) }, /* OpticPro UT24 */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/usb/se401.c linux.19rc3-ac4/drivers/usb/se401.c --- linux.19rc3/drivers/usb/se401.c 2002-07-29 12:54:49.000000000 +0100 +++ linux.19rc3-ac4/drivers/usb/se401.c 2002-07-29 15:09:15.000000000 +0100 @@ -80,54 +80,17 @@ * * 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 - * - * So I copied it again for the ov511 driver -claudio - * - * Same for the se401 driver -Jeroen **********************************************************************/ -/* 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 = (unsigned long) page_address(pte_page(pte)); - ret |= (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. + * This is used when initializing the contents of the area. */ static inline unsigned long kvirt_to_pa(unsigned long adr) { - unsigned long va, kva, ret; + unsigned long kva, ret; - va = VMALLOC_VMADDR(adr); - kva = uvirt_to_kva(pgd_offset_k(va), va); + kva = (unsigned long) page_address(vmalloc_to_page((void *)adr)); + kva |= adr & (PAGE_SIZE-1); /* restore the offset */ ret = __pa(kva); return ret; } @@ -135,12 +98,9 @@ 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); + unsigned long adr; + size = PAGE_ALIGN(size); mem = vmalloc_32(size); if (!mem) return NULL; @@ -148,13 +108,9 @@ memset(mem, 0, size); /* Clear the ram out, no junk to the user */ adr = (unsigned long) mem; while (size > 0) { - page = kvirt_to_pa(adr); - mem_map_reserve(virt_to_page(__va(page))); + mem_map_reserve(vmalloc_to_page((void *)adr)); adr += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; + size -= PAGE_SIZE; } return mem; @@ -162,23 +118,16 @@ static void rvfree(void *mem, unsigned long size) { - unsigned long adr, page; + unsigned long adr; 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(virt_to_page(__va(page))); + adr = (unsigned long) mem; + while ((long) size > 0) { + mem_map_unreserve(vmalloc_to_page((void *)adr)); adr += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; + size -= PAGE_SIZE; } vfree(mem); } @@ -704,7 +653,7 @@ return 0; /* Check for a valid mode */ - if (!width || !height) + if (width <= 0 || height <= 0) return 1; if ((width & 1) || (height & 1)) return 1; @@ -1425,7 +1374,13 @@ se401->sizes=cp[4]+cp[5]*256; se401->width=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL); + if (!se401->width) + return 1; se401->height=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL); + if (!se401->height) { + kfree(se401->width); + return 1; + } for (i=0; isizes; i++) { se401->width[i]=cp[6+i*4+0]+cp[6+i*4+1]*256; se401->height[i]=cp[6+i*4+2]+cp[6+i*4+3]*256; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/usb/serial/belkin_sa.c linux.19rc3-ac4/drivers/usb/serial/belkin_sa.c --- linux.19rc3/drivers/usb/serial/belkin_sa.c 2002-07-29 12:50:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/usb/serial/belkin_sa.c 2002-07-29 13:58:44.000000000 +0100 @@ -361,8 +361,6 @@ dbg(__FUNCTION__" port %d", port->number); - down (&port->sem); - --port->open_count; if (port->open_count <= 0) { @@ -375,7 +373,6 @@ port->active = 0; } - up (&port->sem); MOD_DEC_USE_COUNT; } /* belkin_sa_close */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/usb/serial/cyberjack.c linux.19rc3-ac4/drivers/usb/serial/cyberjack.c --- linux.19rc3/drivers/usb/serial/cyberjack.c 2002-07-29 12:54:49.000000000 +0100 +++ linux.19rc3-ac4/drivers/usb/serial/cyberjack.c 2002-07-29 13:58:44.000000000 +0100 @@ -193,8 +193,6 @@ { dbg(__FUNCTION__ " - port %d", port->number); - down (&port->sem); - --port->open_count; if (port->open_count <= 0) { @@ -209,7 +207,6 @@ port->open_count = 0; } - up (&port->sem); MOD_DEC_USE_COUNT; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/usb/serial/empeg.c linux.19rc3-ac4/drivers/usb/serial/empeg.c --- linux.19rc3/drivers/usb/serial/empeg.c 2002-07-29 12:50:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/usb/serial/empeg.c 2002-07-29 13:58:44.000000000 +0100 @@ -212,8 +212,6 @@ if (!serial) return; - down (&port->sem); - --port->open_count; if (port->open_count <= 0) { @@ -225,8 +223,6 @@ port->open_count = 0; } - up (&port->sem); - /* Uncomment the following line if you want to see some statistics in your syslog */ /* info ("Bytes In = %d Bytes Out = %d", bytes_in, bytes_out); */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/usb/serial/ftdi_sio.c linux.19rc3-ac4/drivers/usb/serial/ftdi_sio.c --- linux.19rc3/drivers/usb/serial/ftdi_sio.c 2002-07-29 12:54:49.000000000 +0100 +++ linux.19rc3-ac4/drivers/usb/serial/ftdi_sio.c 2002-07-29 13:58:44.000000000 +0100 @@ -382,7 +382,6 @@ dbg( __FUNCTION__); - down (&port->sem); --port->open_count; if (port->open_count <= 0) { @@ -421,7 +420,6 @@ } } - up (&port->sem); MOD_DEC_USE_COUNT; } /* ftdi_sio_close */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/usb/serial/ipaq.c linux.19rc3-ac4/drivers/usb/serial/ipaq.c --- linux.19rc3/drivers/usb/serial/ipaq.c 2002-07-29 12:54:49.000000000 +0100 +++ linux.19rc3-ac4/drivers/usb/serial/ipaq.c 2002-07-29 13:58:44.000000000 +0100 @@ -250,8 +250,6 @@ if (!serial) return; - down (&port->sem); - --port->open_count; if (port->open_count <= 0) { @@ -269,7 +267,6 @@ port->open_count = 0; } - up (&port->sem); /* Uncomment the following line if you want to see some statistics in your syslog */ /* info ("Bytes In = %d Bytes Out = %d", bytes_in, bytes_out); */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/usb/serial/ir-usb.c linux.19rc3-ac4/drivers/usb/serial/ir-usb.c --- linux.19rc3/drivers/usb/serial/ir-usb.c 2002-07-29 12:50:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/usb/serial/ir-usb.c 2002-07-29 13:58:44.000000000 +0100 @@ -317,8 +317,6 @@ if (!serial) return; - down (&port->sem); - --port->open_count; if (port->open_count <= 0) { @@ -330,7 +328,6 @@ port->open_count = 0; } - up (&port->sem); MOD_DEC_USE_COUNT; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/usb/serial/keyspan.c linux.19rc3-ac4/drivers/usb/serial/keyspan.c --- linux.19rc3/drivers/usb/serial/keyspan.c 2002-07-29 12:50:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/usb/serial/keyspan.c 2002-07-29 13:58:44.000000000 +0100 @@ -945,8 +945,6 @@ p_priv->out_flip = 0; p_priv->in_flip = 0; - down (&port->sem); - if (--port->open_count <= 0) { if (port->active) { if (serial->dev) { @@ -963,7 +961,6 @@ port->open_count = 0; port->tty = 0; } - up (&port->sem); MOD_DEC_USE_COUNT; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/usb/serial/keyspan_pda.c linux.19rc3-ac4/drivers/usb/serial/keyspan_pda.c --- linux.19rc3/drivers/usb/serial/keyspan_pda.c 2002-07-29 12:50:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/usb/serial/keyspan_pda.c 2002-07-29 13:58:44.000000000 +0100 @@ -738,8 +738,6 @@ { struct usb_serial *serial = port->serial; - down (&port->sem); - --port->open_count; if (port->open_count <= 0) { @@ -756,7 +754,6 @@ port->open_count = 0; } - up (&port->sem); MOD_DEC_USE_COUNT; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/usb/serial/kl5kusb105.c linux.19rc3-ac4/drivers/usb/serial/kl5kusb105.c --- linux.19rc3/drivers/usb/serial/kl5kusb105.c 2002-07-29 12:50:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/usb/serial/kl5kusb105.c 2002-07-29 13:58:44.000000000 +0100 @@ -499,8 +499,6 @@ if(!serial) return; - down (&port->sem); - --port->open_count; if (port->open_count <= 0) { @@ -527,7 +525,6 @@ info("kl5kusb105 port stats: %ld bytes in, %ld bytes out", priv->bytes_in, priv->bytes_out); } - up (&port->sem); MOD_DEC_USE_COUNT; } /* klsi_105_close */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/usb/serial/mct_u232.c linux.19rc3-ac4/drivers/usb/serial/mct_u232.c --- linux.19rc3/drivers/usb/serial/mct_u232.c 2002-07-29 12:50:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/usb/serial/mct_u232.c 2002-07-29 13:58:44.000000000 +0100 @@ -479,8 +479,6 @@ { dbg(__FUNCTION__" port %d", port->number); - down (&port->sem); - --port->open_count; if (port->open_count <= 0) { @@ -493,7 +491,6 @@ port->active = 0; } - up (&port->sem); MOD_DEC_USE_COUNT; } /* mct_u232_close */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/usb/serial/omninet.c linux.19rc3-ac4/drivers/usb/serial/omninet.c --- linux.19rc3/drivers/usb/serial/omninet.c 2002-07-29 12:50:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/usb/serial/omninet.c 2002-07-29 13:58:44.000000000 +0100 @@ -211,8 +211,6 @@ if (!serial) return; - down (&port->sem); - --port->open_count; if (port->open_count <= 0) { @@ -229,7 +227,6 @@ kfree(od); } - up (&port->sem); MOD_DEC_USE_COUNT; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/usb/serial/pl2303.c linux.19rc3-ac4/drivers/usb/serial/pl2303.c --- linux.19rc3/drivers/usb/serial/pl2303.c 2002-07-29 12:54:49.000000000 +0100 +++ linux.19rc3-ac4/drivers/usb/serial/pl2303.c 2002-07-29 13:58:44.000000000 +0100 @@ -451,8 +451,6 @@ dbg (__FUNCTION__ " - port %d", port->number); - down (&port->sem); - --port->open_count; if (port->open_count <= 0) { if (serial->dev) { @@ -490,7 +488,6 @@ port->open_count = 0; } - up (&port->sem); MOD_DEC_USE_COUNT; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/usb/serial/usbserial.c linux.19rc3-ac4/drivers/usb/serial/usbserial.c --- linux.19rc3/drivers/usb/serial/usbserial.c 2002-07-29 12:50:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/usb/serial/usbserial.c 2002-07-29 13:58:44.000000000 +0100 @@ -553,12 +553,21 @@ return; } + down (&port->sem); + + if (tty->driver_data == NULL) { + /* disconnect beat us to the punch here, so handle it gracefully */ + goto exit; + } + /* 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); } +exit: + up (&port->sem); } @@ -826,8 +835,6 @@ dbg(__FUNCTION__ " - port %d", port->number); - down (&port->sem); - --port->open_count; if (port->open_count <= 0) { @@ -843,8 +850,6 @@ port->open_count = 0; } - up (&port->sem); - /* only decrement our usage count, if this device is _really_ a generic device */ if_generic_do(MOD_DEC_USE_COUNT); } @@ -1350,8 +1355,10 @@ if (serial) { /* fail all future close/read/write/ioctl/etc calls */ for (i = 0; i < serial->num_ports; ++i) { + down (&serial->port[i].sem); if (serial->port[i].tty != NULL) serial->port[i].tty->driver_data = NULL; + up (&serial->port[i].sem); } serial->dev = NULL; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/usb/serial/visor.c linux.19rc3-ac4/drivers/usb/serial/visor.c --- linux.19rc3/drivers/usb/serial/visor.c 2002-07-29 12:54:49.000000000 +0100 +++ linux.19rc3-ac4/drivers/usb/serial/visor.c 2002-07-29 13:58:44.000000000 +0100 @@ -391,8 +391,6 @@ if (!serial) return; - down (&port->sem); - --port->open_count; if (port->open_count <= 0) { @@ -417,7 +415,6 @@ port->active = 0; port->open_count = 0; } - up (&port->sem); /* Uncomment the following line if you want to see some statistics in your syslog */ /* info ("Bytes In = %d Bytes Out = %d", bytes_in, bytes_out); */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/usb/serial/whiteheat.c linux.19rc3-ac4/drivers/usb/serial/whiteheat.c --- linux.19rc3/drivers/usb/serial/whiteheat.c 2002-07-29 12:54:49.000000000 +0100 +++ linux.19rc3-ac4/drivers/usb/serial/whiteheat.c 2002-07-29 13:58:44.000000000 +0100 @@ -382,7 +382,6 @@ dbg(__FUNCTION__ " - port %d", port->number); - down (&port->sem); --port->open_count; if (port->open_count <= 0) { @@ -400,7 +399,6 @@ port->active = 0; } MOD_DEC_USE_COUNT; - up (&port->sem); } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/usb/storage/unusual_devs.h linux.19rc3-ac4/drivers/usb/storage/unusual_devs.h --- linux.19rc3/drivers/usb/storage/unusual_devs.h 2002-07-29 12:54:49.000000000 +0100 +++ linux.19rc3-ac4/drivers/usb/storage/unusual_devs.h 2002-07-29 14:19:07.000000000 +0100 @@ -480,6 +480,12 @@ US_SC_SCSI, US_PR_CB, NULL, US_FL_MODE_XLATE ), +UNUSUAL_DEV( 0x0a16, 0x8888, 0x0100, 0x0100, + "IBM", + "IBM USB Memory Key", + US_SC_SCSI, US_PR_BULK, NULL, + US_FL_FIX_INQUIRY ), + #ifdef CONFIG_USB_STORAGE_ISD200 UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110, "ATI", diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/usb/stv680.c linux.19rc3-ac4/drivers/usb/stv680.c --- linux.19rc3/drivers/usb/stv680.c 2002-07-29 12:54:49.000000000 +0100 +++ linux.19rc3-ac4/drivers/usb/stv680.c 2002-07-29 13:58:44.000000000 +0100 @@ -111,67 +111,27 @@ * * 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 - * - * So I copied it again for the ov511 driver -claudio - * - * Same for the se401 driver -Jeroen - * - * And the STV0680 driver - Kevin ********************************************************************/ -/* 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 = (unsigned long) page_address (pte_page (pte)); - ret |= (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. +/* Here we want the physical address of the memory. + * This is used when initializing the contents of the area. */ static inline unsigned long kvirt_to_pa (unsigned long adr) { - unsigned long va, kva, ret; + unsigned long kva, ret; - va = VMALLOC_VMADDR (adr); - kva = uvirt_to_kva (pgd_offset_k (va), va); - ret = __pa (kva); + kva = (unsigned long) page_address(vmalloc_to_page((void *)adr)); + kva |= adr & (PAGE_SIZE-1); /* restore the offset */ + 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); + unsigned long adr; + size = PAGE_ALIGN(size); mem = vmalloc_32 (size); if (!mem) return NULL; @@ -179,36 +139,25 @@ memset (mem, 0, size); /* Clear the ram out, no junk to the user */ adr = (unsigned long) mem; while (size > 0) { - page = kvirt_to_pa (adr); - mem_map_reserve (virt_to_page (__va (page))); + mem_map_reserve(vmalloc_to_page((void *)adr)); adr += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; + size -= PAGE_SIZE; } return mem; } static void rvfree (void *mem, unsigned long size) { - unsigned long adr, page; + unsigned long adr; 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 (virt_to_page (__va (page))); + while ((long) size > 0) { + mem_map_unreserve(vmalloc_to_page((void *)adr)); adr += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; + size -= PAGE_SIZE; } vfree (mem); } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/usb/usb-ohci.c linux.19rc3-ac4/drivers/usb/usb-ohci.c --- linux.19rc3/drivers/usb/usb-ohci.c 2002-07-29 12:54:49.000000000 +0100 +++ linux.19rc3-ac4/drivers/usb/usb-ohci.c 2002-07-29 13:58:44.000000000 +0100 @@ -2144,6 +2144,8 @@ int timeout = 30; int smm_timeout = 50; /* 0,5 sec */ +#ifndef __hppa__ + /* PA-RISC doesn't have SMM, but PDC might leave IR set */ 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"); @@ -2154,7 +2156,8 @@ return -1; } } - } + } +#endif /* Disable HC interrupts */ writel (OHCI_INTR_MIE, &ohci->regs->intrdisable); diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/usb/usbvideo.c linux.19rc3-ac4/drivers/usb/usbvideo.c --- linux.19rc3/drivers/usb/usbvideo.c 2002-07-29 12:50:00.000000000 +0100 +++ linux.19rc3-ac4/drivers/usb/usbvideo.c 2002-07-29 15:12:04.000000000 +0100 @@ -58,57 +58,26 @@ /* Memory management functions */ /*******************************/ -#define MDEBUG(x) do { } while(0) /* Debug memory management */ - -/* Given PGD from the address space's page table, return the kernel - * virtual mapping of the physical memory mapped at ADR. - */ -unsigned long usbvideo_uvirt_to_kva(pgd_t *pgd, unsigned long adr) -{ - unsigned long ret = 0UL; - pmd_t *pmd; - pte_t *ptep, pte; - - if (!pgd_none(*pgd)) { - pmd = pmd_offset(pgd, adr); - if (!pmd_none(*pmd)) { - ptep = pte_offset(pmd, adr); - pte = *ptep; - if (pte_present(pte)) { - ret = (unsigned long) page_address(pte_page(pte)); - ret |= (adr & (PAGE_SIZE-1)); - } - } - } - MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret)); - return ret; -} - /* * 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. + * This is used when initializing the contents of the area. */ unsigned long usbvideo_kvirt_to_pa(unsigned long adr) { - unsigned long va, kva, ret; + unsigned long kva, ret; - va = VMALLOC_VMADDR(adr); - kva = usbvideo_uvirt_to_kva(pgd_offset_k(va), va); + kva = (unsigned long) page_address(vmalloc_to_page((void *)adr)); + kva |= adr & (PAGE_SIZE-1); /* restore the offset */ ret = __pa(kva); - MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret)); return ret; } void *usbvideo_rvmalloc(unsigned long size) { void *mem; - unsigned long adr, page; - - /* Round it off to PAGE_SIZE */ - size += (PAGE_SIZE - 1); - size &= ~(PAGE_SIZE - 1); + unsigned long adr; + size = PAGE_ALIGN(size); mem = vmalloc_32(size); if (!mem) return NULL; @@ -116,13 +85,9 @@ memset(mem, 0, size); /* Clear the ram out, no junk to the user */ adr = (unsigned long) mem; while (size > 0) { - page = usbvideo_kvirt_to_pa(adr); - mem_map_reserve(virt_to_page(__va(page))); + mem_map_reserve(vmalloc_to_page((void *)adr)); adr += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; + size -= PAGE_SIZE; } return mem; @@ -130,23 +95,16 @@ void usbvideo_rvfree(void *mem, unsigned long size) { - unsigned long adr, page; + unsigned long adr; if (!mem) return; - size += (PAGE_SIZE - 1); - size &= ~(PAGE_SIZE - 1); - - adr=(unsigned long) mem; - while (size > 0) { - page = usbvideo_kvirt_to_pa(adr); - mem_map_unreserve(virt_to_page(__va(page))); + adr = (unsigned long) mem; + while ((long) size > 0) { + mem_map_unreserve(vmalloc_to_page((void *)adr)); adr += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; + size -= PAGE_SIZE; } vfree(mem); } @@ -1737,6 +1695,12 @@ * have - even if the application wants more. That would be * a big security embarassment! */ + + if (count + frame->seqRead_Index < count) + { + count = -EINVAL; + goto read_done; + } if ((count + frame->seqRead_Index) > frame->seqRead_Length) count = frame->seqRead_Length - frame->seqRead_Index; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/usb/vicam.c linux.19rc3-ac4/drivers/usb/vicam.c --- linux.19rc3/drivers/usb/vicam.c 2002-07-29 12:54:49.000000000 +0100 +++ linux.19rc3-ac4/drivers/usb/vicam.c 2002-07-29 13:58:44.000000000 +0100 @@ -91,80 +91,25 @@ * ******************************************************************************/ -/* [DaveM] I've recoded most of this so that: - * 1) It's easier to tell what is happening - * 2) It's more portable, especially for translating things - * out of vmalloc mapped areas in the kernel. - * 3) Less unnecessary translations happen. - * - * The code used to assume that the kernel vmalloc mappings - * existed in the page tables of every process, this is simply - * not guarenteed. We now use pgd_offset_k which is the - * defined way to get at the kernel page tables. - */ - -/* 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 = (unsigned long) page_address(pte_page(pte)); - ret |= (adr & (PAGE_SIZE - 1)); - - } - } - } - return ret; -} - -static inline unsigned long uvirt_to_bus(unsigned long adr) -{ - unsigned long kva, ret; - - kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr); - ret = virt_to_bus((void *)kva); - return ret; -} - -static inline unsigned long kvirt_to_bus(unsigned long adr) -{ - unsigned long va, kva, ret; - - va = VMALLOC_VMADDR(adr); - kva = uvirt_to_kva(pgd_offset_k(va), va); - ret = virt_to_bus((void *)kva); - return ret; -} - /* Here we want the physical address of the memory. - * This is used when initializing the contents of the - * area and marking the pages as reserved. + * This is used when initializing the contents of the area. */ static inline unsigned long kvirt_to_pa(unsigned long adr) { - unsigned long va, kva, ret; + unsigned long kva, ret; - va = VMALLOC_VMADDR(adr); - kva = uvirt_to_kva(pgd_offset_k(va), va); + kva = (unsigned long) page_address(vmalloc_to_page((void *)adr)); + kva |= adr & (PAGE_SIZE-1); /* restore the offset */ ret = __pa(kva); return ret; } -static void * rvmalloc(signed long size) +static void * rvmalloc(unsigned long size) { void * mem; - unsigned long adr, page; + unsigned long adr; + size=PAGE_ALIGN(size); mem=vmalloc_32(size); if (mem) { @@ -172,8 +117,7 @@ adr=(unsigned long) mem; while (size > 0) { - page = kvirt_to_pa(adr); - mem_map_reserve(virt_to_page(__va(page))); + mem_map_reserve(vmalloc_to_page((void *)adr)); adr+=PAGE_SIZE; size-=PAGE_SIZE; } @@ -181,17 +125,16 @@ return mem; } -static void rvfree(void * mem, signed long size) +static void rvfree(void * mem, unsigned long size) { - unsigned long adr, page; + unsigned long adr; if (mem) { adr=(unsigned long) mem; - while (size > 0) + while ((long) size > 0) { - page = kvirt_to_pa(adr); - mem_map_unreserve(virt_to_page(__va(page))); + mem_map_unreserve(vmalloc_to_page((void *)adr)); adr+=PAGE_SIZE; size-=PAGE_SIZE; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/usb/wacom.c linux.19rc3-ac4/drivers/usb/wacom.c --- linux.19rc3/drivers/usb/wacom.c 2002-07-29 12:54:49.000000000 +0100 +++ linux.19rc3-ac4/drivers/usb/wacom.c 2002-07-29 13:58:44.000000000 +0100 @@ -111,7 +111,6 @@ struct wacom_features *features; int tool[2]; int open; - int x, y; __u32 serial[2]; }; @@ -209,16 +208,16 @@ input_report_abs(dev, ABS_DISTANCE, data[7]); input_report_rel(dev, REL_WHEEL, (signed char) data[6]); - input_report_abs(dev, ABS_X, wacom->x = x); - input_report_abs(dev, ABS_Y, wacom->y = y); + input_report_abs(dev, ABS_X, x); + input_report_abs(dev, ABS_Y, y); input_event(dev, EV_MSC, MSC_SERIAL, data[1] & 0x01); return; } if (data[1] & 0x80) { - input_report_abs(dev, ABS_X, wacom->x = x); - input_report_abs(dev, ABS_Y, wacom->y = y); + input_report_abs(dev, ABS_X, x); + input_report_abs(dev, ABS_Y, y); } input_report_abs(dev, ABS_PRESSURE, data[6] | ((__u32)data[7] << 8)); @@ -236,7 +235,6 @@ struct input_dev *dev = &wacom->dev; unsigned int t; int idx; - int x, y; if (urb->status) return; @@ -285,11 +283,8 @@ return; } - x = ((__u32)data[2] << 8) | data[3]; - y = ((__u32)data[4] << 8) | data[5]; - - input_report_abs(dev, ABS_X, wacom->x); - input_report_abs(dev, ABS_Y, wacom->y); + input_report_abs(dev, ABS_X, ((__u32)data[2] << 8) | data[3]); + input_report_abs(dev, ABS_Y, ((__u32)data[4] << 8) | data[5]); input_report_abs(dev, ABS_DISTANCE, data[9] >> 4); if ((data[1] & 0xb8) == 0xa0) { /* general pen packet */ diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/video/aty/atyfb_base.c linux.19rc3-ac4/drivers/video/aty/atyfb_base.c --- linux.19rc3/drivers/video/aty/atyfb_base.c 2002-07-29 12:54:49.000000000 +0100 +++ linux.19rc3-ac4/drivers/video/aty/atyfb_base.c 2002-07-29 13:58:44.000000000 +0100 @@ -360,6 +360,7 @@ /* 3D RAGE Mobility */ { 0x4c4d, 0x4c4d, 0x00, 0x00, m64n_mob_p, 230, 50, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_MOBIL_BUS }, + { 0x4c52, 0x4c52, 0x00, 0x00, m64n_mob_p, 230, 40, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_MOBIL_BUS | M64F_MAGIC_POSTDIV | M64F_SDRAM_MAGIC_PLL | M64F_XL_DLL }, { 0x4c4e, 0x4c4e, 0x00, 0x00, m64n_mob_a, 230, 50, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_MOBIL_BUS }, #endif /* CONFIG_FB_ATY_CT */ }; @@ -438,7 +439,7 @@ #endif /* defined(CONFIG_PPC) */ -#if defined(CONFIG_PMAC_PBOOK) || defined(CONFIG_PMAC_BACKLIGHT) +#if defined(CONFIG_PMAC_PBOOK) || defined(CONFIG_PMAC_BACKLIGHT) || defined(CONFIG_FB_ATY_CT_VAIO_LCD) static void aty_st_lcd(int index, u32 val, const struct fb_info_aty *info) { unsigned long temp; @@ -460,7 +461,7 @@ /* read the register value */ return aty_ld_le32(LCD_DATA, info); } -#endif /* CONFIG_PMAC_PBOOK || CONFIG_PMAC_BACKLIGHT */ +#endif /* CONFIG_PMAC_PBOOK || CONFIG_PMAC_BACKLIGHT || CONFIG_FB_ATY_CT_VAIO_LCD */ /* ------------------------------------------------------------------------- */ @@ -1772,6 +1773,9 @@ #if defined(CONFIG_PPC) int sense; #endif +#if defined(CONFIG_FB_ATY_CT_VAIO_LCD) + u32 pm, hs; +#endif u8 pll_ref_div; info->aty_cmap_regs = (struct aty_cmap_regs *)(info->ati_regbase+0xc0); @@ -2089,6 +2093,35 @@ var = default_var; #endif /* !__sparc__ */ #endif /* !CONFIG_PPC */ +#if defined(CONFIG_FB_ATY_CT_VAIO_LCD) + /* Power Management */ + pm=aty_ld_lcd(POWER_MANAGEMENT, info); + pm=(pm & ~PWR_MGT_MODE_MASK) | PWR_MGT_MODE_PCI; + pm|=PWR_MGT_ON; + aty_st_lcd(POWER_MANAGEMENT, pm, info); + udelay(10); + + /* OVR_WID_LEFT_RIGHT */ + hs=aty_ld_le32(OVR_WID_LEFT_RIGHT,info); + hs= 0x00000000; + aty_st_le32(OVR_WID_LEFT_RIGHT, hs, info); + udelay(10); + + /* CONFIG_PANEL */ + hs=aty_ld_lcd(CONFIG_PANEL,info); + hs|=DONT_SHADOW_HEND ; + aty_st_lcd(CONFIG_PANEL, hs, info); + udelay(10); + +#if defined(DEBUG) + printk("LCD_INDEX CONFIG_PANEL LCD_GEN_CTRL POWER_MANAGEMENT\n" + "%08x %08x %08x %08x\n", + aty_ld_le32(LCD_INDEX, info), + aty_ld_lcd(CONFIG_PANEL, info), + aty_ld_lcd(LCD_GEN_CTRL, info), + aty_ld_lcd(POWER_MANAGEMENT, info), +#endif /* DEBUG */ +#endif /* CONFIG_FB_ATY_CT_VAIO_LCD */ #endif /* !MODULE */ if (noaccel) var.accel_flags &= ~FB_ACCELF_TEXT; @@ -2712,6 +2745,23 @@ /* * Blank the display. */ +#if defined(CONFIG_FB_ATY_CT_VAIO_LCD) +static int set_backlight_enable(int on, struct fb_info_aty *info) +{ + unsigned int reg = aty_ld_lcd(POWER_MANAGEMENT, info); + if(on) { + reg=(reg & ~SUSPEND_NOW) | PWR_BLON; + } else { + reg=(reg & ~PWR_BLON) | SUSPEND_NOW; + } + aty_st_lcd(POWER_MANAGEMENT, reg, info); + udelay(10); +#ifdef DEBUG + printk(KERN_INFO "set_backlight_enable(%i): %08x\n", on, aty_ld_lcd(POWER_MANAGEMENT, info) ); +#endif + return 0; +} +#endif /* CONFIG_FB_ATY_CT_VAIO_LCD */ static void atyfbcon_blank(int blank, struct fb_info *fb) { @@ -2723,6 +2773,9 @@ set_backlight_enable(0); #endif /* CONFIG_PMAC_BACKLIGHT */ +#if defined(CONFIG_FB_ATY_CT_VAIO_LCD) + set_backlight_enable(!blank, info); +#endif /* CONFIG_FB_ATY_CT_VAIO_LCD */ gen_cntl = aty_ld_8(CRTC_GEN_CNTL, info); if (blank > 0) switch (blank-1) { diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/video/aty/mach64_ct.c linux.19rc3-ac4/drivers/video/aty/mach64_ct.c --- linux.19rc3/drivers/video/aty/mach64_ct.c 2002-07-29 12:49:59.000000000 +0100 +++ linux.19rc3-ac4/drivers/video/aty/mach64_ct.c 2002-07-29 13:58:44.000000000 +0100 @@ -178,11 +178,14 @@ } pll->pll_gen_cntl |= mpostdiv<<4; /* mclk */ - if (M64_HAS(MAGIC_POSTDIV)) - pll->pll_ext_cntl = 0; - else +#if defined(CONFIG_FB_ATY_CT_VAIO_LCD) pll->pll_ext_cntl = mpostdiv; /* xclk == mclk */ - +#else + if ( M64_HAS(MAGIC_POSTDIV) ) + pll->pll_ext_cntl = 0; + else + pll->pll_ext_cntl = mpostdiv; /* xclk == mclk */ +#endif switch (pll->vclk_post_div_real) { case 2: vpostdiv = 1; diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/video/aty/mach64.h linux.19rc3-ac4/drivers/video/aty/mach64.h --- linux.19rc3/drivers/video/aty/mach64.h 2002-07-29 12:49:59.000000000 +0100 +++ linux.19rc3-ac4/drivers/video/aty/mach64.h 2002-07-29 13:58:44.000000000 +0100 @@ -1148,6 +1148,8 @@ #define APC_LUT_MN 0x39 #define APC_LUT_OP 0x3A +/* Values in CONFIG_PANEL */ +#define DONT_SHADOW_HEND 0x00004000 /* Values in LCD_MISC_CNTL */ #define BIAS_MOD_LEVEL_MASK 0x0000ff00 diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/video/clgenfb.c linux.19rc3-ac4/drivers/video/clgenfb.c --- linux.19rc3/drivers/video/clgenfb.c 2002-07-29 12:54:49.000000000 +0100 +++ linux.19rc3-ac4/drivers/video/clgenfb.c 2002-07-29 13:58:44.000000000 +0100 @@ -3089,7 +3089,7 @@ *********************************************************************/ /* FIXME: use interrupts instead */ -extern inline void clgen_WaitBLT (caddr_t regbase) +static inline void clgen_WaitBLT (caddr_t regbase) { /* now busy-wait until we're done */ while (vga_rgfx (regbase, CL_GR31) & 0x08) diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/video/Config.in linux.19rc3-ac4/drivers/video/Config.in --- linux.19rc3/drivers/video/Config.in 2002-07-29 12:54:49.000000000 +0100 +++ linux.19rc3-ac4/drivers/video/Config.in 2002-07-29 13:58:44.000000000 +0100 @@ -132,14 +132,21 @@ fi fi dep_tristate ' G450/G550 second head support (mandatory for G550)' CONFIG_FB_MATROX_G450 $CONFIG_FB_MATROX_G100 + dep_tristate ' Matrox /proc interface' CONFIG_FB_MATROX_PROC $CONFIG_FB_MATROX bool ' Multihead support' CONFIG_FB_MATROX_MULTIHEAD fi tristate ' ATI Mach64 display support (EXPERIMENTAL)' CONFIG_FB_ATY if [ "$CONFIG_FB_ATY" != "n" ]; then bool ' Mach64 GX support (EXPERIMENTAL)' CONFIG_FB_ATY_GX bool ' Mach64 CT/VT/GT/LT (incl. 3D RAGE) support' CONFIG_FB_ATY_CT + if [ "$CONFIG_FB_ATY_CT" = "y" ]; then + bool ' Sony Vaio C1VE 1024x480 LCD support' CONFIG_FB_ATY_CT_VAIO_LCD + fi fi tristate ' ATI Radeon display support (EXPERIMENTAL)' CONFIG_FB_RADEON + if [ "$CONFIG_FB_RADEON" = "y" ]; then + bool ' Sony Vaio C1MV 1280x600 LCD support' CONFIG_FB_RADEON_VAIO_LCD + fi tristate ' ATI Rage128 display support (EXPERIMENTAL)' CONFIG_FB_ATY128 tristate ' SIS acceleration (EXPERIMENTAL)' CONFIG_FB_SIS if [ "$CONFIG_FB_SIS" != "n" ]; then diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/video/fbcon.c linux.19rc3-ac4/drivers/video/fbcon.c --- linux.19rc3/drivers/video/fbcon.c 2002-07-29 12:49:59.000000000 +0100 +++ linux.19rc3-ac4/drivers/video/fbcon.c 2002-07-29 15:14:53.000000000 +0100 @@ -2417,7 +2417,7 @@ else dst = fb + y1*line + x/8; for( x1 = 0; x1 < LOGO_LINE; ++x1 ) - fb_writeb(fb_readb(src++) ^ inverse, dst++); + fb_writeb(*src++ ^ inverse, dst++); } done = 1; } diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.19rc3/drivers/video/fbcon-sti.c linux.19rc3-ac4/drivers/video/fbcon-sti.c --- linux.19rc3/drivers/video/fbcon-sti.c 2002-07-29 12:49:59.000000000 +0100 +++ linux.19rc3-ac4/drivers/video/fbcon-sti.c 2002-07-29 13:58:44.000000000 +0100 @@ -17,12 +17,13 @@ #include #include #include +#include /* for gsc_read/write */ #include #include